1*5e3f6f95Sbenno /* $OpenBSD: util.c,v 1.24 2017/01/24 04:22:42 benno Exp $ */ 22ffcd4e0Sclaudio 32ffcd4e0Sclaudio /* 42ffcd4e0Sclaudio * Copyright (c) 2006 Claudio Jeker <claudio@openbsd.org> 52ffcd4e0Sclaudio * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> 62ffcd4e0Sclaudio * 72ffcd4e0Sclaudio * Permission to use, copy, modify, and distribute this software for any 82ffcd4e0Sclaudio * purpose with or without fee is hereby granted, provided that the above 92ffcd4e0Sclaudio * copyright notice and this permission notice appear in all copies. 102ffcd4e0Sclaudio * 112ffcd4e0Sclaudio * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 122ffcd4e0Sclaudio * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 132ffcd4e0Sclaudio * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 142ffcd4e0Sclaudio * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 152ffcd4e0Sclaudio * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 162ffcd4e0Sclaudio * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 172ffcd4e0Sclaudio * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 182ffcd4e0Sclaudio */ 192ffcd4e0Sclaudio #include <sys/types.h> 202ffcd4e0Sclaudio #include <sys/socket.h> 212ffcd4e0Sclaudio #include <netinet/in.h> 222ffcd4e0Sclaudio #include <arpa/inet.h> 232ffcd4e0Sclaudio #include <netdb.h> 242ffcd4e0Sclaudio #include <stdlib.h> 252ffcd4e0Sclaudio #include <stdio.h> 262ffcd4e0Sclaudio #include <string.h> 270561b344Sphessler #include <vis.h> 282ffcd4e0Sclaudio 292ffcd4e0Sclaudio #include "bgpd.h" 302ffcd4e0Sclaudio #include "rde.h" 31*5e3f6f95Sbenno #include "log.h" 322ffcd4e0Sclaudio 331e590dcfSclaudio const char *aspath_delim(u_int8_t, int); 341e590dcfSclaudio 352ffcd4e0Sclaudio const char * 362ffcd4e0Sclaudio log_addr(const struct bgpd_addr *addr) 372ffcd4e0Sclaudio { 382ffcd4e0Sclaudio static char buf[48]; 39256b680eSclaudio char tbuf[16]; 402ffcd4e0Sclaudio 4115d8de66Sclaudio switch (addr->aid) { 4215d8de66Sclaudio case AID_INET: 4315d8de66Sclaudio case AID_INET6: 4415d8de66Sclaudio if (inet_ntop(aid2af(addr->aid), &addr->ba, buf, 4515d8de66Sclaudio sizeof(buf)) == NULL) 462ffcd4e0Sclaudio return ("?"); 472ffcd4e0Sclaudio return (buf); 4815d8de66Sclaudio case AID_VPN_IPv4: 49256b680eSclaudio if (inet_ntop(AF_INET, &addr->vpn4.addr, tbuf, 50256b680eSclaudio sizeof(tbuf)) == NULL) 5115d8de66Sclaudio return ("?"); 52256b680eSclaudio snprintf(buf, sizeof(buf), "%s %s", log_rd(addr->vpn4.rd), 53256b680eSclaudio tbuf); 5415d8de66Sclaudio return (buf); 5515d8de66Sclaudio } 5615d8de66Sclaudio return ("???"); 572ffcd4e0Sclaudio } 582ffcd4e0Sclaudio 592ffcd4e0Sclaudio const char * 602ffcd4e0Sclaudio log_in6addr(const struct in6_addr *addr) 612ffcd4e0Sclaudio { 622ffcd4e0Sclaudio struct sockaddr_in6 sa_in6; 632ffcd4e0Sclaudio u_int16_t tmp16; 642ffcd4e0Sclaudio 652ffcd4e0Sclaudio bzero(&sa_in6, sizeof(sa_in6)); 662ffcd4e0Sclaudio sa_in6.sin6_len = sizeof(sa_in6); 672ffcd4e0Sclaudio sa_in6.sin6_family = AF_INET6; 682ffcd4e0Sclaudio memcpy(&sa_in6.sin6_addr, addr, sizeof(sa_in6.sin6_addr)); 692ffcd4e0Sclaudio 702ffcd4e0Sclaudio /* XXX thanks, KAME, for this ugliness... adopted from route/show.c */ 712ffcd4e0Sclaudio if (IN6_IS_ADDR_LINKLOCAL(&sa_in6.sin6_addr) || 722ffcd4e0Sclaudio IN6_IS_ADDR_MC_LINKLOCAL(&sa_in6.sin6_addr)) { 732ffcd4e0Sclaudio memcpy(&tmp16, &sa_in6.sin6_addr.s6_addr[2], sizeof(tmp16)); 742ffcd4e0Sclaudio sa_in6.sin6_scope_id = ntohs(tmp16); 752ffcd4e0Sclaudio sa_in6.sin6_addr.s6_addr[2] = 0; 762ffcd4e0Sclaudio sa_in6.sin6_addr.s6_addr[3] = 0; 772ffcd4e0Sclaudio } 782ffcd4e0Sclaudio 792ffcd4e0Sclaudio return (log_sockaddr((struct sockaddr *)&sa_in6)); 802ffcd4e0Sclaudio } 812ffcd4e0Sclaudio 822ffcd4e0Sclaudio const char * 832ffcd4e0Sclaudio log_sockaddr(struct sockaddr *sa) 842ffcd4e0Sclaudio { 852ffcd4e0Sclaudio static char buf[NI_MAXHOST]; 862ffcd4e0Sclaudio 872ffcd4e0Sclaudio if (getnameinfo(sa, sa->sa_len, buf, sizeof(buf), NULL, 0, 882ffcd4e0Sclaudio NI_NUMERICHOST)) 892ffcd4e0Sclaudio return ("(unknown)"); 902ffcd4e0Sclaudio else 912ffcd4e0Sclaudio return (buf); 922ffcd4e0Sclaudio } 932ffcd4e0Sclaudio 940c88bf70Sclaudio const char * 950c88bf70Sclaudio log_as(u_int32_t as) 960c88bf70Sclaudio { 9706bcde9cSphessler static char buf[11]; /* "4294967294\0" */ 980c88bf70Sclaudio 990c88bf70Sclaudio if (snprintf(buf, sizeof(buf), "%u", as) == -1) 1000c88bf70Sclaudio return ("?"); 10106bcde9cSphessler 1020c88bf70Sclaudio return (buf); 1030c88bf70Sclaudio } 1040c88bf70Sclaudio 105256b680eSclaudio const char * 106256b680eSclaudio log_rd(u_int64_t rd) 107256b680eSclaudio { 108256b680eSclaudio static char buf[32]; 109256b680eSclaudio struct in_addr addr; 110256b680eSclaudio u_int32_t u32; 111256b680eSclaudio u_int16_t u16; 112256b680eSclaudio 113256b680eSclaudio rd = betoh64(rd); 114256b680eSclaudio switch (rd >> 48) { 115256b680eSclaudio case EXT_COMMUNITY_TWO_AS: 116256b680eSclaudio u32 = rd & 0xffffffff; 117256b680eSclaudio u16 = (rd >> 32) & 0xffff; 11832ecd2d8Sderaadt snprintf(buf, sizeof(buf), "rd %hu:%u", u16, u32); 119256b680eSclaudio break; 120256b680eSclaudio case EXT_COMMUNITY_FOUR_AS: 121256b680eSclaudio u32 = (rd >> 16) & 0xffffffff; 122256b680eSclaudio u16 = rd & 0xffff; 12332ecd2d8Sderaadt snprintf(buf, sizeof(buf), "rd %s:%hu", log_as(u32), u16); 124256b680eSclaudio break; 125256b680eSclaudio case EXT_COMMUNITY_IPV4: 126256b680eSclaudio u32 = (rd >> 16) & 0xffffffff; 127256b680eSclaudio u16 = rd & 0xffff; 128256b680eSclaudio addr.s_addr = htonl(u32); 12932ecd2d8Sderaadt snprintf(buf, sizeof(buf), "rd %s:%hu", inet_ntoa(addr), u16); 130256b680eSclaudio break; 131256b680eSclaudio default: 132256b680eSclaudio return ("rd ?"); 133256b680eSclaudio } 134256b680eSclaudio return (buf); 135256b680eSclaudio } 136256b680eSclaudio 137256b680eSclaudio /* NOTE: this function does not check if the type/subtype combo is 138536f41e5Sclaudio * actually valid. */ 139536f41e5Sclaudio const char * 140536f41e5Sclaudio log_ext_subtype(u_int8_t subtype) 141536f41e5Sclaudio { 142536f41e5Sclaudio static char etype[6]; 143536f41e5Sclaudio 144536f41e5Sclaudio switch (subtype) { 145536f41e5Sclaudio case EXT_COMMUNITY_ROUTE_TGT: 146536f41e5Sclaudio return ("rt"); /* route target */ 147e85ee6aeSsthen case EXT_COMMUNITY_ROUTE_ORIG: 148536f41e5Sclaudio return ("soo"); /* source of origin */ 149536f41e5Sclaudio case EXT_COMMUNITY_OSPF_DOM_ID: 150536f41e5Sclaudio return ("odi"); /* ospf domain id */ 151536f41e5Sclaudio case EXT_COMMUNITY_OSPF_RTR_TYPE: 152536f41e5Sclaudio return ("ort"); /* ospf route type */ 153536f41e5Sclaudio case EXT_COMMUNITY_OSPF_RTR_ID: 154536f41e5Sclaudio return ("ori"); /* ospf router id */ 155536f41e5Sclaudio case EXT_COMMUNITY_BGP_COLLECT: 156536f41e5Sclaudio return ("bdc"); /* bgp data collection */ 157536f41e5Sclaudio default: 158d6340f7aSderaadt snprintf(etype, sizeof(etype), "[%u]", subtype); 159536f41e5Sclaudio return (etype); 160536f41e5Sclaudio } 161536f41e5Sclaudio } 162536f41e5Sclaudio 1631e590dcfSclaudio const char * 1640561b344Sphessler log_shutcomm(const char *communication) { 1650561b344Sphessler static char buf[(SHUT_COMM_LEN - 1) * 4 + 1]; 1660561b344Sphessler 1670561b344Sphessler strnvis(buf, communication, sizeof(buf), VIS_NL | VIS_OCTAL); 1680561b344Sphessler 1690561b344Sphessler return buf; 1700561b344Sphessler } 1710561b344Sphessler 1720561b344Sphessler const char * 1731e590dcfSclaudio aspath_delim(u_int8_t seg_type, int closing) 1741e590dcfSclaudio { 1751e590dcfSclaudio static char db[8]; 1761e590dcfSclaudio 1771e590dcfSclaudio switch (seg_type) { 1781e590dcfSclaudio case AS_SET: 1791e590dcfSclaudio if (!closing) 1801e590dcfSclaudio return ("{ "); 1811e590dcfSclaudio else 1821e590dcfSclaudio return (" }"); 1831e590dcfSclaudio case AS_SEQUENCE: 1841e590dcfSclaudio return (""); 1851e590dcfSclaudio case AS_CONFED_SEQUENCE: 1861e590dcfSclaudio if (!closing) 1871e590dcfSclaudio return ("( "); 1881e590dcfSclaudio else 1891e590dcfSclaudio return (" )"); 1901e590dcfSclaudio case AS_CONFED_SET: 1911e590dcfSclaudio if (!closing) 1921e590dcfSclaudio return ("[ "); 1931e590dcfSclaudio else 1941e590dcfSclaudio return (" ]"); 1951e590dcfSclaudio default: 1961e590dcfSclaudio if (!closing) 1971e590dcfSclaudio snprintf(db, sizeof(db), "!%u ", seg_type); 1981e590dcfSclaudio else 1991e590dcfSclaudio snprintf(db, sizeof(db), " !%u", seg_type); 2001e590dcfSclaudio return (db); 2011e590dcfSclaudio } 2021e590dcfSclaudio } 2031e590dcfSclaudio 2042ffcd4e0Sclaudio int 2052ffcd4e0Sclaudio aspath_snprint(char *buf, size_t size, void *data, u_int16_t len) 2062ffcd4e0Sclaudio { 2072ffcd4e0Sclaudio #define UPDATE() \ 2082ffcd4e0Sclaudio do { \ 2092ffcd4e0Sclaudio if (r == -1) \ 2102ffcd4e0Sclaudio return (-1); \ 2112ffcd4e0Sclaudio total_size += r; \ 2122ffcd4e0Sclaudio if ((unsigned int)r < size) { \ 2132ffcd4e0Sclaudio size -= r; \ 2142ffcd4e0Sclaudio buf += r; \ 2152ffcd4e0Sclaudio } else { \ 2162ffcd4e0Sclaudio buf += size; \ 2172ffcd4e0Sclaudio size = 0; \ 2182ffcd4e0Sclaudio } \ 2192ffcd4e0Sclaudio } while (0) 2202ffcd4e0Sclaudio u_int8_t *seg; 2212ffcd4e0Sclaudio int r, total_size; 2222ffcd4e0Sclaudio u_int16_t seg_size; 2232ffcd4e0Sclaudio u_int8_t i, seg_type, seg_len; 2242ffcd4e0Sclaudio 2252ffcd4e0Sclaudio total_size = 0; 2262ffcd4e0Sclaudio seg = data; 2272ffcd4e0Sclaudio for (; len > 0; len -= seg_size, seg += seg_size) { 2282ffcd4e0Sclaudio seg_type = seg[0]; 2292ffcd4e0Sclaudio seg_len = seg[1]; 2300c88bf70Sclaudio seg_size = 2 + sizeof(u_int32_t) * seg_len; 2312ffcd4e0Sclaudio 2321e590dcfSclaudio r = snprintf(buf, size, "%s%s", 2331e590dcfSclaudio total_size != 0 ? " " : "", 2341e590dcfSclaudio aspath_delim(seg_type, 0)); 2352ffcd4e0Sclaudio UPDATE(); 2362ffcd4e0Sclaudio 2372ffcd4e0Sclaudio for (i = 0; i < seg_len; i++) { 2380c88bf70Sclaudio r = snprintf(buf, size, "%s", 2390c88bf70Sclaudio log_as(aspath_extract(seg, i))); 2402ffcd4e0Sclaudio UPDATE(); 2412ffcd4e0Sclaudio if (i + 1 < seg_len) { 2422ffcd4e0Sclaudio r = snprintf(buf, size, " "); 2432ffcd4e0Sclaudio UPDATE(); 2442ffcd4e0Sclaudio } 2452ffcd4e0Sclaudio } 2461e590dcfSclaudio r = snprintf(buf, size, "%s", aspath_delim(seg_type, 1)); 2472ffcd4e0Sclaudio UPDATE(); 2482ffcd4e0Sclaudio } 24955e49665Sclaudio /* ensure that we have a valid C-string especially for empty as path */ 2502ffcd4e0Sclaudio if (size > 0) 2512ffcd4e0Sclaudio *buf = '\0'; 2522ffcd4e0Sclaudio 2532ffcd4e0Sclaudio return (total_size); 2542ffcd4e0Sclaudio #undef UPDATE 2552ffcd4e0Sclaudio } 2562ffcd4e0Sclaudio 2572ffcd4e0Sclaudio int 2582ffcd4e0Sclaudio aspath_asprint(char **ret, void *data, u_int16_t len) 2592ffcd4e0Sclaudio { 2602ffcd4e0Sclaudio size_t slen; 2612ffcd4e0Sclaudio int plen; 2622ffcd4e0Sclaudio 2632ffcd4e0Sclaudio slen = aspath_strlen(data, len) + 1; 2642ffcd4e0Sclaudio *ret = malloc(slen); 2652ffcd4e0Sclaudio if (*ret == NULL) 2662ffcd4e0Sclaudio return (-1); 2672ffcd4e0Sclaudio 2682ffcd4e0Sclaudio plen = aspath_snprint(*ret, slen, data, len); 2692ffcd4e0Sclaudio if (plen == -1) { 2702ffcd4e0Sclaudio free(*ret); 2712ffcd4e0Sclaudio *ret = NULL; 2722ffcd4e0Sclaudio return (-1); 2732ffcd4e0Sclaudio } 2742ffcd4e0Sclaudio 2752ffcd4e0Sclaudio return (0); 2762ffcd4e0Sclaudio } 2772ffcd4e0Sclaudio 2782ffcd4e0Sclaudio size_t 2792ffcd4e0Sclaudio aspath_strlen(void *data, u_int16_t len) 2802ffcd4e0Sclaudio { 2812ffcd4e0Sclaudio u_int8_t *seg; 2822ffcd4e0Sclaudio int total_size; 2830c88bf70Sclaudio u_int32_t as; 2840c88bf70Sclaudio u_int16_t seg_size; 2852ffcd4e0Sclaudio u_int8_t i, seg_type, seg_len; 2862ffcd4e0Sclaudio 2872ffcd4e0Sclaudio total_size = 0; 2882ffcd4e0Sclaudio seg = data; 2892ffcd4e0Sclaudio for (; len > 0; len -= seg_size, seg += seg_size) { 2902ffcd4e0Sclaudio seg_type = seg[0]; 2912ffcd4e0Sclaudio seg_len = seg[1]; 2920c88bf70Sclaudio seg_size = 2 + sizeof(u_int32_t) * seg_len; 2932ffcd4e0Sclaudio 2942ffcd4e0Sclaudio if (seg_type == AS_SET) 2952ffcd4e0Sclaudio if (total_size != 0) 2962ffcd4e0Sclaudio total_size += 3; 2972ffcd4e0Sclaudio else 2982ffcd4e0Sclaudio total_size += 2; 2992ffcd4e0Sclaudio else if (total_size != 0) 3002ffcd4e0Sclaudio total_size += 1; 3012ffcd4e0Sclaudio 3022ffcd4e0Sclaudio for (i = 0; i < seg_len; i++) { 3032ffcd4e0Sclaudio as = aspath_extract(seg, i); 3040c88bf70Sclaudio 3058db4f5d2Sclaudio do { 3068db4f5d2Sclaudio total_size++; 3078db4f5d2Sclaudio } while ((as = as / 10) != 0); 3082ffcd4e0Sclaudio 3092ffcd4e0Sclaudio if (i + 1 < seg_len) 3102ffcd4e0Sclaudio total_size += 1; 3112ffcd4e0Sclaudio } 3122ffcd4e0Sclaudio 3132ffcd4e0Sclaudio if (seg_type == AS_SET) 3142ffcd4e0Sclaudio total_size += 2; 3152ffcd4e0Sclaudio } 3162ffcd4e0Sclaudio return (total_size); 3172ffcd4e0Sclaudio } 3182ffcd4e0Sclaudio 319fafbb788Sclaudio /* we need to be able to search more than one as */ 320fafbb788Sclaudio int 321368f0e94Sbenno aspath_match(void *data, u_int16_t len, struct filter_as *f, u_int32_t match) 322fafbb788Sclaudio { 323fafbb788Sclaudio u_int8_t *seg; 324fafbb788Sclaudio int final; 325fafbb788Sclaudio u_int16_t seg_size; 326de50ed92Sclaudio u_int8_t i, seg_len; 327368f0e94Sbenno u_int32_t as; 328fafbb788Sclaudio 329368f0e94Sbenno if (f->type == AS_EMPTY) { 330fafbb788Sclaudio if (len == 0) 331fafbb788Sclaudio return (1); 332fafbb788Sclaudio else 333fafbb788Sclaudio return (0); 334fafbb788Sclaudio } 335fafbb788Sclaudio 336fafbb788Sclaudio seg = data; 337fafbb788Sclaudio for (; len > 0; len -= seg_size, seg += seg_size) { 338fafbb788Sclaudio seg_len = seg[1]; 339fafbb788Sclaudio seg_size = 2 + sizeof(u_int32_t) * seg_len; 340fafbb788Sclaudio 341fafbb788Sclaudio final = (len == seg_size); 342fafbb788Sclaudio 343fafbb788Sclaudio /* just check the first (leftmost) AS */ 344368f0e94Sbenno if (f->type == AS_PEER) { 345368f0e94Sbenno as = aspath_extract(seg, 0); 346368f0e94Sbenno if (as_compare(f->op, as, match, f->as_min, f->as_max)) 347fafbb788Sclaudio return (1); 348fafbb788Sclaudio else 349fafbb788Sclaudio return (0); 350fafbb788Sclaudio } 351fafbb788Sclaudio /* just check the final (rightmost) AS */ 352368f0e94Sbenno if (f->type == AS_SOURCE) { 353fafbb788Sclaudio /* not yet in the final segment */ 354fafbb788Sclaudio if (!final) 355fafbb788Sclaudio continue; 356368f0e94Sbenno as = aspath_extract(seg, seg_len - 1); 357368f0e94Sbenno if (as_compare(f->op, as, match, f->as_min, f->as_max)) 358fafbb788Sclaudio return (1); 359fafbb788Sclaudio else 360fafbb788Sclaudio return (0); 361fafbb788Sclaudio } 362fafbb788Sclaudio /* AS_TRANSIT or AS_ALL */ 363fafbb788Sclaudio for (i = 0; i < seg_len; i++) { 364fafbb788Sclaudio /* 365fafbb788Sclaudio * the source (rightmost) AS is excluded from 366fafbb788Sclaudio * AS_TRANSIT matches. 367fafbb788Sclaudio */ 368368f0e94Sbenno if (final && i == seg_len - 1 && f->type == AS_TRANSIT) 369fafbb788Sclaudio return (0); 370368f0e94Sbenno as = aspath_extract(seg, i); 371368f0e94Sbenno if (as_compare(f->op, as, match, f->as_min, f->as_max)) 372fafbb788Sclaudio return (1); 373fafbb788Sclaudio } 374fafbb788Sclaudio } 375368f0e94Sbenno return (0); 376fafbb788Sclaudio } 377368f0e94Sbenno 378368f0e94Sbenno int 379368f0e94Sbenno as_compare(u_int8_t op, u_int32_t as, u_int32_t match, u_int32_t as_min, 380368f0e94Sbenno u_int32_t as_max) 381368f0e94Sbenno { 382368f0e94Sbenno if ((op == OP_NONE || op == OP_EQ) && as == match) 383368f0e94Sbenno return (1); 384368f0e94Sbenno else if (op == OP_NE && as != match) 385368f0e94Sbenno return (1); 386368f0e94Sbenno else if (op == OP_RANGE && as >= as_min && as <= as_max) 387368f0e94Sbenno return (1); 388368f0e94Sbenno else if (op == OP_XRANGE && as > as_min && as < as_max) 389368f0e94Sbenno return (1); 390fafbb788Sclaudio return (0); 391fafbb788Sclaudio } 392fafbb788Sclaudio 3932ffcd4e0Sclaudio /* 3942ffcd4e0Sclaudio * Extract the asnum out of the as segment at the specified position. 3952ffcd4e0Sclaudio * Direct access is not possible because of non-aligned reads. 396c5508ee4Sclaudio * ATTENTION: no bounds checks are done. 3972ffcd4e0Sclaudio */ 3980c88bf70Sclaudio u_int32_t 3992ffcd4e0Sclaudio aspath_extract(const void *seg, int pos) 4002ffcd4e0Sclaudio { 4012ffcd4e0Sclaudio const u_char *ptr = seg; 4020c88bf70Sclaudio u_int32_t as; 4032ffcd4e0Sclaudio 4040c88bf70Sclaudio ptr += 2 + sizeof(u_int32_t) * pos; 4050c88bf70Sclaudio memcpy(&as, ptr, sizeof(u_int32_t)); 4060c88bf70Sclaudio return (ntohl(as)); 4072ffcd4e0Sclaudio } 40821a825c9Sclaudio 409de5c2eedSclaudio /* 410de5c2eedSclaudio * This function will have undefined behaviour if the passed in prefixlen is 411de5c2eedSclaudio * to large for the respective bgpd_addr address family. 412de5c2eedSclaudio */ 413fafbb788Sclaudio int 414fafbb788Sclaudio prefix_compare(const struct bgpd_addr *a, const struct bgpd_addr *b, 415fafbb788Sclaudio int prefixlen) 416fafbb788Sclaudio { 417fafbb788Sclaudio in_addr_t mask, aa, ba; 418fafbb788Sclaudio int i; 419fafbb788Sclaudio u_int8_t m; 420fafbb788Sclaudio 421fafbb788Sclaudio if (a->aid != b->aid) 422fafbb788Sclaudio return (a->aid - b->aid); 423fafbb788Sclaudio 424fafbb788Sclaudio switch (a->aid) { 425fafbb788Sclaudio case AID_INET: 4267da59fecSclaudio if (prefixlen == 0) 4277da59fecSclaudio return (0); 428fafbb788Sclaudio if (prefixlen > 32) 429de5c2eedSclaudio return (-1); 430fafbb788Sclaudio mask = htonl(prefixlen2mask(prefixlen)); 431fafbb788Sclaudio aa = ntohl(a->v4.s_addr & mask); 432fafbb788Sclaudio ba = ntohl(b->v4.s_addr & mask); 433fafbb788Sclaudio if (aa != ba) 434fafbb788Sclaudio return (aa - ba); 435fafbb788Sclaudio return (0); 436fafbb788Sclaudio case AID_INET6: 4377da59fecSclaudio if (prefixlen == 0) 4387da59fecSclaudio return (0); 439fafbb788Sclaudio if (prefixlen > 128) 440de5c2eedSclaudio return (-1); 441fafbb788Sclaudio for (i = 0; i < prefixlen / 8; i++) 442fafbb788Sclaudio if (a->v6.s6_addr[i] != b->v6.s6_addr[i]) 443fafbb788Sclaudio return (a->v6.s6_addr[i] - b->v6.s6_addr[i]); 444fafbb788Sclaudio i = prefixlen % 8; 445fafbb788Sclaudio if (i) { 446fafbb788Sclaudio m = 0xff00 >> i; 447fafbb788Sclaudio if ((a->v6.s6_addr[prefixlen / 8] & m) != 448fafbb788Sclaudio (b->v6.s6_addr[prefixlen / 8] & m)) 449fafbb788Sclaudio return ((a->v6.s6_addr[prefixlen / 8] & m) - 450fafbb788Sclaudio (b->v6.s6_addr[prefixlen / 8] & m)); 451fafbb788Sclaudio } 452fafbb788Sclaudio return (0); 453fafbb788Sclaudio case AID_VPN_IPv4: 454fafbb788Sclaudio if (prefixlen > 32) 455de5c2eedSclaudio return (-1); 456fafbb788Sclaudio if (betoh64(a->vpn4.rd) > betoh64(b->vpn4.rd)) 457fafbb788Sclaudio return (1); 458fafbb788Sclaudio if (betoh64(a->vpn4.rd) < betoh64(b->vpn4.rd)) 459fafbb788Sclaudio return (-1); 460fafbb788Sclaudio mask = htonl(prefixlen2mask(prefixlen)); 461fafbb788Sclaudio aa = ntohl(a->vpn4.addr.s_addr & mask); 462fafbb788Sclaudio ba = ntohl(b->vpn4.addr.s_addr & mask); 463fafbb788Sclaudio if (aa != ba) 464fafbb788Sclaudio return (aa - ba); 465fafbb788Sclaudio if (a->vpn4.labellen > b->vpn4.labellen) 466fafbb788Sclaudio return (1); 467fafbb788Sclaudio if (a->vpn4.labellen < b->vpn4.labellen) 468fafbb788Sclaudio return (-1); 469fafbb788Sclaudio return (memcmp(a->vpn4.labelstack, b->vpn4.labelstack, 470fafbb788Sclaudio a->vpn4.labellen)); 471fafbb788Sclaudio } 472fafbb788Sclaudio return (-1); 473fafbb788Sclaudio } 474fafbb788Sclaudio 47521a825c9Sclaudio in_addr_t 47621a825c9Sclaudio prefixlen2mask(u_int8_t prefixlen) 47721a825c9Sclaudio { 47821a825c9Sclaudio if (prefixlen == 0) 47921a825c9Sclaudio return (0); 48021a825c9Sclaudio 48121a825c9Sclaudio return (0xffffffff << (32 - prefixlen)); 48221a825c9Sclaudio } 48321a825c9Sclaudio 48421a825c9Sclaudio void 48521a825c9Sclaudio inet6applymask(struct in6_addr *dest, const struct in6_addr *src, int prefixlen) 48621a825c9Sclaudio { 48721a825c9Sclaudio struct in6_addr mask; 48821a825c9Sclaudio int i; 48921a825c9Sclaudio 49021a825c9Sclaudio bzero(&mask, sizeof(mask)); 49121a825c9Sclaudio for (i = 0; i < prefixlen / 8; i++) 49221a825c9Sclaudio mask.s6_addr[i] = 0xff; 49321a825c9Sclaudio i = prefixlen % 8; 49421a825c9Sclaudio if (i) 49521a825c9Sclaudio mask.s6_addr[prefixlen / 8] = 0xff00 >> i; 49621a825c9Sclaudio 49721a825c9Sclaudio for (i = 0; i < 16; i++) 49821a825c9Sclaudio dest->s6_addr[i] = src->s6_addr[i] & mask.s6_addr[i]; 49921a825c9Sclaudio } 500d6c2e4e8Sclaudio 501d6c2e4e8Sclaudio /* address family translation functions */ 502d6c2e4e8Sclaudio const struct aid aid_vals[AID_MAX] = AID_VALS; 503d6c2e4e8Sclaudio 50486729c90Sclaudio const char * 50586729c90Sclaudio aid2str(u_int8_t aid) 50686729c90Sclaudio { 50786729c90Sclaudio if (aid < AID_MAX) 50886729c90Sclaudio return (aid_vals[aid].name); 50986729c90Sclaudio return ("unknown AID"); 51086729c90Sclaudio } 51186729c90Sclaudio 512d6c2e4e8Sclaudio int 513d6c2e4e8Sclaudio aid2afi(u_int8_t aid, u_int16_t *afi, u_int8_t *safi) 514d6c2e4e8Sclaudio { 515d6c2e4e8Sclaudio if (aid < AID_MAX) { 516d6c2e4e8Sclaudio *afi = aid_vals[aid].afi; 517d6c2e4e8Sclaudio *safi = aid_vals[aid].safi; 518d6c2e4e8Sclaudio return (0); 519d6c2e4e8Sclaudio } 520d6c2e4e8Sclaudio return (-1); 521d6c2e4e8Sclaudio } 522d6c2e4e8Sclaudio 523d6c2e4e8Sclaudio int 524d6c2e4e8Sclaudio afi2aid(u_int16_t afi, u_int8_t safi, u_int8_t *aid) 525d6c2e4e8Sclaudio { 526d6c2e4e8Sclaudio u_int8_t i; 527d6c2e4e8Sclaudio 528d6c2e4e8Sclaudio for (i = 0; i < AID_MAX; i++) 529d6c2e4e8Sclaudio if (aid_vals[i].afi == afi && aid_vals[i].safi == safi) { 530d6c2e4e8Sclaudio *aid = i; 531d6c2e4e8Sclaudio return (0); 532d6c2e4e8Sclaudio } 533d6c2e4e8Sclaudio 534d6c2e4e8Sclaudio return (-1); 535d6c2e4e8Sclaudio } 536d6c2e4e8Sclaudio 537d6c2e4e8Sclaudio sa_family_t 538d6c2e4e8Sclaudio aid2af(u_int8_t aid) 539d6c2e4e8Sclaudio { 540d6c2e4e8Sclaudio if (aid < AID_MAX) 541d6c2e4e8Sclaudio return (aid_vals[aid].af); 542d6c2e4e8Sclaudio return (AF_UNSPEC); 543d6c2e4e8Sclaudio } 544d6c2e4e8Sclaudio 545d6c2e4e8Sclaudio int 546d6c2e4e8Sclaudio af2aid(sa_family_t af, u_int8_t safi, u_int8_t *aid) 547d6c2e4e8Sclaudio { 548d6c2e4e8Sclaudio u_int8_t i; 549d6c2e4e8Sclaudio 550d6c2e4e8Sclaudio if (safi == 0) /* default to unicast subclass */ 551d6c2e4e8Sclaudio safi = SAFI_UNICAST; 552d6c2e4e8Sclaudio 553d6c2e4e8Sclaudio for (i = 0; i < AID_MAX; i++) 554d6c2e4e8Sclaudio if (aid_vals[i].af == af && aid_vals[i].safi == safi) { 555d6c2e4e8Sclaudio *aid = i; 556d6c2e4e8Sclaudio return (0); 557d6c2e4e8Sclaudio } 558d6c2e4e8Sclaudio 559d6c2e4e8Sclaudio return (-1); 560d6c2e4e8Sclaudio } 561d6c2e4e8Sclaudio 562d6c2e4e8Sclaudio struct sockaddr * 563d6c2e4e8Sclaudio addr2sa(struct bgpd_addr *addr, u_int16_t port) 564d6c2e4e8Sclaudio { 565d6c2e4e8Sclaudio static struct sockaddr_storage ss; 566d6c2e4e8Sclaudio struct sockaddr_in *sa_in = (struct sockaddr_in *)&ss; 567d6c2e4e8Sclaudio struct sockaddr_in6 *sa_in6 = (struct sockaddr_in6 *)&ss; 568d6c2e4e8Sclaudio 569d6c2e4e8Sclaudio if (addr->aid == AID_UNSPEC) 570d6c2e4e8Sclaudio return (NULL); 571d6c2e4e8Sclaudio 572d6c2e4e8Sclaudio bzero(&ss, sizeof(ss)); 573d6c2e4e8Sclaudio switch (addr->aid) { 574d6c2e4e8Sclaudio case AID_INET: 575d6c2e4e8Sclaudio sa_in->sin_family = AF_INET; 576d6c2e4e8Sclaudio sa_in->sin_len = sizeof(struct sockaddr_in); 577d6c2e4e8Sclaudio sa_in->sin_addr.s_addr = addr->v4.s_addr; 578d6c2e4e8Sclaudio sa_in->sin_port = htons(port); 579d6c2e4e8Sclaudio break; 580d6c2e4e8Sclaudio case AID_INET6: 581d6c2e4e8Sclaudio sa_in6->sin6_family = AF_INET6; 582d6c2e4e8Sclaudio sa_in6->sin6_len = sizeof(struct sockaddr_in6); 583d6c2e4e8Sclaudio memcpy(&sa_in6->sin6_addr, &addr->v6, 584d6c2e4e8Sclaudio sizeof(sa_in6->sin6_addr)); 585d6c2e4e8Sclaudio sa_in6->sin6_port = htons(port); 586d6c2e4e8Sclaudio sa_in6->sin6_scope_id = addr->scope_id; 587d6c2e4e8Sclaudio break; 588d6c2e4e8Sclaudio } 589d6c2e4e8Sclaudio 590d6c2e4e8Sclaudio return ((struct sockaddr *)&ss); 591d6c2e4e8Sclaudio } 592d6c2e4e8Sclaudio 593d6c2e4e8Sclaudio void 594d6c2e4e8Sclaudio sa2addr(struct sockaddr *sa, struct bgpd_addr *addr) 595d6c2e4e8Sclaudio { 596d6c2e4e8Sclaudio struct sockaddr_in *sa_in = (struct sockaddr_in *)sa; 597d6c2e4e8Sclaudio struct sockaddr_in6 *sa_in6 = (struct sockaddr_in6 *)sa; 598d6c2e4e8Sclaudio 599d6c2e4e8Sclaudio bzero(addr, sizeof(*addr)); 600d6c2e4e8Sclaudio switch (sa->sa_family) { 601d6c2e4e8Sclaudio case AF_INET: 602d6c2e4e8Sclaudio addr->aid = AID_INET; 603d6c2e4e8Sclaudio memcpy(&addr->v4, &sa_in->sin_addr, sizeof(addr->v4)); 604d6c2e4e8Sclaudio break; 605d6c2e4e8Sclaudio case AF_INET6: 606d6c2e4e8Sclaudio addr->aid = AID_INET6; 607d6c2e4e8Sclaudio memcpy(&addr->v6, &sa_in6->sin6_addr, sizeof(addr->v6)); 608d6c2e4e8Sclaudio addr->scope_id = sa_in6->sin6_scope_id; /* I hate v6 */ 609d6c2e4e8Sclaudio break; 610d6c2e4e8Sclaudio } 611d6c2e4e8Sclaudio } 612