diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2006-01-03 22:20:00 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2006-01-03 22:20:00 +0000 |
commit | 4408d355bf203228e260018e43cfbc145f9ea1d3 (patch) | |
tree | d0ccb664c5001a2930f258c48055384edb874f68 /usr.sbin/bgpd/util.c | |
parent | a3c7f60ab9ba3c37009a70632cf95b8266282878 (diff) |
Move functions shared with bgpctl into new file util.c. Simplifies the
link between bgpctl and bgpd mostly because of rde_attr.c.
Diffstat (limited to 'usr.sbin/bgpd/util.c')
-rw-r--r-- | usr.sbin/bgpd/util.c | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/usr.sbin/bgpd/util.c b/usr.sbin/bgpd/util.c new file mode 100644 index 00000000000..d301dce878d --- /dev/null +++ b/usr.sbin/bgpd/util.c @@ -0,0 +1,221 @@ +/* $OpenBSD: util.c,v 1.1 2006/01/03 22:19:59 claudio Exp $ */ + +/* + * Copyright (c) 2006 Claudio Jeker <claudio@openbsd.org> + * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <netdb.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "bgpd.h" +#include "rde.h" + +const char * +log_addr(const struct bgpd_addr *addr) +{ + static char buf[48]; + + if (inet_ntop(addr->af, &addr->ba, buf, sizeof(buf)) == NULL) + return ("?"); + else + return (buf); +} + +const char * +log_in6addr(const struct in6_addr *addr) +{ + struct sockaddr_in6 sa_in6; + u_int16_t tmp16; + + bzero(&sa_in6, sizeof(sa_in6)); + sa_in6.sin6_len = sizeof(sa_in6); + sa_in6.sin6_family = AF_INET6; + memcpy(&sa_in6.sin6_addr, addr, sizeof(sa_in6.sin6_addr)); + + /* XXX thanks, KAME, for this ugliness... adopted from route/show.c */ + if (IN6_IS_ADDR_LINKLOCAL(&sa_in6.sin6_addr) || + IN6_IS_ADDR_MC_LINKLOCAL(&sa_in6.sin6_addr)) { + memcpy(&tmp16, &sa_in6.sin6_addr.s6_addr[2], sizeof(tmp16)); + sa_in6.sin6_scope_id = ntohs(tmp16); + sa_in6.sin6_addr.s6_addr[2] = 0; + sa_in6.sin6_addr.s6_addr[3] = 0; + } + + return (log_sockaddr((struct sockaddr *)&sa_in6)); +} + +const char * +log_sockaddr(struct sockaddr *sa) +{ + static char buf[NI_MAXHOST]; + + if (getnameinfo(sa, sa->sa_len, buf, sizeof(buf), NULL, 0, + NI_NUMERICHOST)) + return ("(unknown)"); + else + return (buf); +} + +int +aspath_snprint(char *buf, size_t size, void *data, u_int16_t len) +{ +#define UPDATE() \ + do { \ + if (r == -1) \ + return (-1); \ + total_size += r; \ + if ((unsigned int)r < size) { \ + size -= r; \ + buf += r; \ + } else { \ + buf += size; \ + size = 0; \ + } \ + } while (0) + u_int8_t *seg; + int r, total_size; + u_int16_t seg_size; + u_int8_t i, seg_type, seg_len; + + total_size = 0; + seg = data; + for (; len > 0; len -= seg_size, seg += seg_size) { + seg_type = seg[0]; + seg_len = seg[1]; + seg_size = 2 + 2 * seg_len; + + if (seg_type == AS_SET) { + if (total_size != 0) + r = snprintf(buf, size, " { "); + else + r = snprintf(buf, size, "{ "); + UPDATE(); + } else if (total_size != 0) { + r = snprintf(buf, size, " "); + UPDATE(); + } + + for (i = 0; i < seg_len; i++) { + r = snprintf(buf, size, "%hu", aspath_extract(seg, i)); + UPDATE(); + if (i + 1 < seg_len) { + r = snprintf(buf, size, " "); + UPDATE(); + } + } + if (seg_type == AS_SET) { + r = snprintf(buf, size, " }"); + UPDATE(); + } + } + /* ensure that we have a valid C-string especially for emtpy as path */ + if (size > 0) + *buf = '\0'; + + return (total_size); +#undef UPDATE +} + +int +aspath_asprint(char **ret, void *data, u_int16_t len) +{ + size_t slen; + int plen; + + slen = aspath_strlen(data, len) + 1; + *ret = malloc(slen); + if (*ret == NULL) + return (-1); + + plen = aspath_snprint(*ret, slen, data, len); + if (plen == -1) { + free(*ret); + *ret = NULL; + return (-1); + } + + return (0); +} + +size_t +aspath_strlen(void *data, u_int16_t len) +{ + u_int8_t *seg; + int total_size; + u_int16_t as, seg_size; + u_int8_t i, seg_type, seg_len; + + total_size = 0; + seg = data; + for (; len > 0; len -= seg_size, seg += seg_size) { + seg_type = seg[0]; + seg_len = seg[1]; + seg_size = 2 + 2 * seg_len; + + if (seg_type == AS_SET) + if (total_size != 0) + total_size += 3; + else + total_size += 2; + else if (total_size != 0) + total_size += 1; + + for (i = 0; i < seg_len; i++) { + as = aspath_extract(seg, i); + if (as >= 10000) + total_size += 5; + else if (as >= 1000) + total_size += 4; + else if (as >= 100) + total_size += 3; + else if (as >= 10) + total_size += 2; + else + total_size += 1; + + if (i + 1 < seg_len) + total_size += 1; + } + + if (seg_type == AS_SET) + total_size += 2; + } + return (total_size); +} + +/* + * Extract the asnum out of the as segment at the specified position. + * Direct access is not possible because of non-aligned reads. + * ATTENTION: no bounds check are done. + */ +u_int16_t +aspath_extract(const void *seg, int pos) +{ + const u_char *ptr = seg; + u_int16_t as = 0; + + ptr += 2 + 2 * pos; + as = *ptr++; + as <<= 8; + as |= *ptr; + return (as); +} + |