Annotation of embedaddon/bird2/sysdep/bsd/krt-sock.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  *     BIRD -- BSD Routing Table Syncing
                      3:  *
                      4:  *     (c) 2004 Ondrej Filip <feela@network.cz>
                      5:  *
                      6:  *     Can be freely distributed and used under the terms of the GNU GPL.
                      7:  */
                      8: 
                      9: #include <stdio.h>
                     10: #include <stdlib.h>
                     11: #include <ctype.h>
                     12: #include <fcntl.h>
                     13: #include <unistd.h>
                     14: #include <sys/param.h>
                     15: #include <sys/types.h>
                     16: #include <sys/socket.h>
                     17: #include <sys/sysctl.h>
                     18: #include <sys/ioctl.h>
                     19: #include <netinet/in.h>
                     20: #include <net/route.h>
                     21: #include <net/if.h>
                     22: #include <net/if_dl.h>
                     23: 
                     24: #undef LOCAL_DEBUG
                     25: 
                     26: #include "nest/bird.h"
                     27: #include "nest/iface.h"
                     28: #include "nest/route.h"
                     29: #include "nest/protocol.h"
                     30: #include "nest/iface.h"
                     31: #include "sysdep/unix/unix.h"
                     32: #include "sysdep/unix/krt.h"
                     33: #include "lib/string.h"
                     34: #include "lib/socket.h"
                     35: 
                     36: const int rt_default_ecmp = 0;
                     37: 
                     38: /*
                     39:  * There are significant differences in multiple tables support between BSD variants.
                     40:  *
                     41:  * OpenBSD has table_id field for routes in route socket protocol, therefore all
                     42:  * tables could be managed by one kernel socket. FreeBSD lacks such field,
                     43:  * therefore multiple sockets (locked to specific table using SO_SETFIB socket
                     44:  * option) must be used.
                     45:  *
                     46:  * Both FreeBSD and OpenBSD uses separate scans for each table. In OpenBSD,
                     47:  * table_id is specified explicitly as sysctl scan argument, while in FreeBSD it
                     48:  * is handled implicitly by changing default table using setfib() syscall.
                     49:  *
                     50:  * KRT_SHARED_SOCKET   - use shared kernel socked instead of one for each krt_proto
                     51:  * KRT_USE_SETFIB_SCAN - use setfib() for sysctl() route scan
                     52:  * KRT_USE_SETFIB_SOCK - use SO_SETFIB socket option for kernel sockets
                     53:  * KRT_USE_SYSCTL_7    - use 7-th arg of sysctl() as table id for route scans
                     54:  * KRT_USE_SYSCTL_NET_FIBS - use net.fibs sysctl() for dynamic max number of fibs
                     55:  */
                     56: 
                     57: #ifdef __FreeBSD__
                     58: #define KRT_MAX_TABLES 256
                     59: #define KRT_USE_SETFIB_SCAN
                     60: #define KRT_USE_SETFIB_SOCK
                     61: #define KRT_USE_SYSCTL_NET_FIBS
                     62: #endif
                     63: 
                     64: #ifdef __OpenBSD__
                     65: #define KRT_MAX_TABLES (RT_TABLEID_MAX+1)
                     66: #define KRT_SHARED_SOCKET
                     67: #define KRT_USE_SYSCTL_7
                     68: #endif
                     69: 
                     70: #ifndef KRT_MAX_TABLES
                     71: #define KRT_MAX_TABLES 1
                     72: #endif
                     73: 
                     74: 
                     75: /* Dynamic max number of tables */
                     76: 
                     77: uint krt_max_tables;
                     78: 
                     79: #ifdef KRT_USE_SYSCTL_NET_FIBS
                     80: 
                     81: static uint
                     82: krt_get_max_tables(void)
                     83: {
                     84:   int fibs;
                     85:   size_t fibs_len = sizeof(fibs);
                     86: 
                     87:   if (sysctlbyname("net.fibs", &fibs, &fibs_len, NULL, 0) < 0)
                     88:   {
                     89:     log(L_WARN "KRT: unable to get max number of fib tables: %m");
                     90:     return 1;
                     91:   }
                     92: 
                     93:   /* Should not happen */
                     94:   if (fibs < 1)
                     95:     return 1;
                     96: 
                     97:   return (uint) MIN(fibs, KRT_MAX_TABLES);
                     98: }
                     99: 
                    100: #else
                    101: 
                    102: static int
                    103: krt_get_max_tables(void)
                    104: {
                    105:   return KRT_MAX_TABLES;
                    106: }
                    107: 
                    108: #endif /* KRT_USE_SYSCTL_NET_FIBS */
                    109: 
                    110: 
                    111: /* setfib() syscall for FreeBSD scans */
                    112: 
                    113: #ifdef KRT_USE_SETFIB_SCAN
                    114: 
                    115: /*
                    116: static int krt_default_fib;
                    117: 
                    118: static int
                    119: krt_get_active_fib(void)
                    120: {
                    121:   int fib;
                    122:   size_t fib_len = sizeof(fib);
                    123: 
                    124:   if (sysctlbyname("net.my_fibnum", &fib, &fib_len, NULL, 0) < 0)
                    125:   {
                    126:     log(L_WARN "KRT: unable to get active fib number: %m");
                    127:     return 0;
                    128:   }
                    129: 
                    130:   return fib;
                    131: }
                    132: */
                    133: 
                    134: extern int setfib(int fib);
                    135: 
                    136: #endif /* KRT_USE_SETFIB_SCAN */
                    137: 
                    138: 
                    139: /* table_id -> krt_proto map */
                    140: 
                    141: #ifdef KRT_SHARED_SOCKET
                    142: static struct krt_proto *krt_table_map[KRT_MAX_TABLES][2];
                    143: #endif
                    144: 
                    145: 
                    146: /* Route socket message processing */
                    147: 
                    148: int
                    149: krt_capable(rte *e)
                    150: {
                    151:   rta *a = e->attrs;
                    152: 
                    153:   return
                    154:     ((a->dest == RTD_UNICAST && !a->nh.next) /* No multipath support */
                    155: #ifdef RTF_REJECT
                    156:      || a->dest == RTD_UNREACHABLE
                    157: #endif
                    158: #ifdef RTF_BLACKHOLE
                    159:      || a->dest == RTD_BLACKHOLE
                    160: #endif
                    161:      );
                    162: }
                    163: 
                    164: #ifndef RTAX_MAX
                    165: #define RTAX_MAX 8
                    166: #endif
                    167: 
                    168: struct ks_msg
                    169: {
                    170:   struct rt_msghdr rtm;
                    171:   struct sockaddr_storage buf[RTAX_MAX];
                    172: } PACKED;
                    173: 
                    174: #define ROUNDUP(a) \
                    175:         ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
                    176: 
                    177: #define NEXTADDR(w, u) \
                    178:         if (msg.rtm.rtm_addrs & (w)) {\
                    179:           l = ROUNDUP(((struct sockaddr *)&(u))->sa_len);\
                    180:           memmove(body, &(u), l); body += l;}
                    181: 
                    182: #define GETADDR(p, F) \
                    183:   bzero(p, sizeof(*p));\
                    184:   if ((addrs & (F)) && ((struct sockaddr *)body)->sa_len) {\
                    185:     uint l = ROUNDUP(((struct sockaddr *)body)->sa_len);\
                    186:     memcpy(p, body, (l > sizeof(*p) ? sizeof(*p) : l));\
                    187:     body += l;}
                    188: 
                    189: static inline void
                    190: sockaddr_fill_dl(struct sockaddr_dl *sa, struct iface *ifa)
                    191: {
                    192:   uint len = OFFSETOF(struct sockaddr_dl, sdl_data);
                    193:   memset(sa, 0, len);
                    194:   sa->sdl_len = len;
                    195:   sa->sdl_family = AF_LINK;
                    196:   sa->sdl_index = ifa->index;
                    197: }
                    198: 
                    199: static int
                    200: krt_send_route(struct krt_proto *p, int cmd, rte *e)
                    201: {
                    202:   net *net = e->net;
                    203:   rta *a = e->attrs;
                    204:   static int msg_seq;
                    205:   struct iface *j, *i = a->nh.iface;
                    206:   int l;
                    207:   struct ks_msg msg;
                    208:   char *body = (char *)msg.buf;
                    209:   sockaddr gate, mask, dst;
                    210: 
                    211:   DBG("krt-sock: send %I/%d via %I\n", net->n.prefix, net->n.pxlen, a->gw);
                    212: 
                    213:   bzero(&msg,sizeof (struct rt_msghdr));
                    214:   msg.rtm.rtm_version = RTM_VERSION;
                    215:   msg.rtm.rtm_type = cmd;
                    216:   msg.rtm.rtm_seq = msg_seq++;
                    217:   msg.rtm.rtm_addrs = RTA_DST;
                    218:   msg.rtm.rtm_flags = RTF_UP | RTF_PROTO1;
                    219: 
                    220:   /* XXXX */
                    221:   if (net_pxlen(net->n.addr) == net_max_prefix_length[net->n.addr->type])
                    222:     msg.rtm.rtm_flags |= RTF_HOST;
                    223:   else
                    224:     msg.rtm.rtm_addrs |= RTA_NETMASK;
                    225: 
                    226: #ifdef KRT_SHARED_SOCKET
                    227:   msg.rtm.rtm_tableid = KRT_CF->sys.table_id;
                    228: #endif
                    229: 
                    230: #ifdef RTF_REJECT
                    231:   if(a->dest == RTD_UNREACHABLE)
                    232:     msg.rtm.rtm_flags |= RTF_REJECT;
                    233: #endif
                    234: #ifdef RTF_BLACKHOLE
                    235:   if(a->dest == RTD_BLACKHOLE)
                    236:     msg.rtm.rtm_flags |= RTF_BLACKHOLE;
                    237: #endif
                    238: 
                    239:   /*
                    240:    * This is really very nasty, but I'm not able to add reject/blackhole route
                    241:    * without gateway address.
                    242:    */
                    243:   if (!i)
                    244:   {
                    245:     WALK_LIST(j, iface_list)
                    246:     {
                    247:       if (j->flags & IF_LOOPBACK)
                    248:       {
                    249:         i = j;
                    250:         break;
                    251:       }
                    252:     }
                    253: 
                    254:     if (!i)
                    255:     {
                    256:       log(L_ERR "KRT: Cannot find loopback iface");
                    257:       return -1;
                    258:     }
                    259:   }
                    260: 
                    261:   int af = AF_UNSPEC;
                    262: 
                    263:   switch (net->n.addr->type) {
                    264:     case NET_IP4:
                    265:       af = AF_INET;
                    266:       break;
                    267:     case NET_IP6:
                    268:       af = AF_INET6;
                    269:       break;
                    270:     default:
                    271:       log(L_ERR "KRT: Not sending route %N to kernel", net->n.addr);
                    272:       return -1;
                    273:   }
                    274: 
                    275:   sockaddr_fill(&dst,  af, net_prefix(net->n.addr), NULL, 0);
                    276:   sockaddr_fill(&mask, af, net_pxmask(net->n.addr), NULL, 0);
                    277: 
                    278:   switch (a->dest)
                    279:   {
                    280:   case RTD_UNICAST:
                    281:     if (ipa_nonzero(a->nh.gw))
                    282:     {
                    283:       ip_addr gw = a->nh.gw;
                    284: 
                    285:       /* Embed interface ID to link-local address */
                    286:       if (ipa_is_link_local(gw))
                    287:        _I0(gw) = 0xfe800000 | (i->index & 0x0000ffff);
                    288: 
                    289:       sockaddr_fill(&gate, af, gw, NULL, 0);
                    290:       msg.rtm.rtm_flags |= RTF_GATEWAY;
                    291:       msg.rtm.rtm_addrs |= RTA_GATEWAY;
                    292:       break;
                    293:     }
                    294: 
                    295: #ifdef RTF_REJECT
                    296:   case RTD_UNREACHABLE:
                    297: #endif
                    298: #ifdef RTF_BLACKHOLE
                    299:   case RTD_BLACKHOLE:
                    300: #endif
                    301:   {
                    302:     /* Fallback for all other valid cases */
                    303: 
                    304: #if __OpenBSD__
                    305:     /* Keeping temporarily old code for OpenBSD */
                    306:     struct ifa *addr = (net->n.addr->type == NET_IP4) ? i->addr4 : (i->addr6 ?: i->llv6);
                    307: 
                    308:     if (!addr)
                    309:     {
                    310:       log(L_ERR "KRT: interface %s has no IP addess", i->name);
                    311:       return -1;
                    312:     }
                    313: 
                    314:     /* Embed interface ID to link-local address */
                    315:     ip_addr gw = addr->ip;
                    316:     if (ipa_is_link_local(gw))
                    317:       _I0(gw) = 0xfe800000 | (i->index & 0x0000ffff);
                    318: 
                    319:     sockaddr_fill(&gate, af, gw, i, 0);
                    320: #else
                    321:     sockaddr_fill_dl(&gate, i);
                    322: #endif
                    323: 
                    324:     msg.rtm.rtm_addrs |= RTA_GATEWAY;
                    325:     break;
                    326:   }
                    327: 
                    328:   default:
                    329:     bug("krt-sock: unknown flags, but not filtered");
                    330:   }
                    331: 
                    332:   msg.rtm.rtm_index = i->index;
                    333: 
                    334:   NEXTADDR(RTA_DST, dst);
                    335:   NEXTADDR(RTA_GATEWAY, gate);
                    336:   NEXTADDR(RTA_NETMASK, mask);
                    337: 
                    338:   l = body - (char *)&msg;
                    339:   msg.rtm.rtm_msglen = l;
                    340: 
                    341:   if ((l = write(p->sys.sk->fd, (char *)&msg, l)) < 0) {
                    342:     log(L_ERR "KRT: Error sending route %N to kernel: %m", net->n.addr);
                    343:     return -1;
                    344:   }
                    345: 
                    346:   return 0;
                    347: }
                    348: 
                    349: void
                    350: krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old)
                    351: {
                    352:   int err = 0;
                    353: 
                    354:   if (old)
                    355:     krt_send_route(p, RTM_DELETE, old);
                    356: 
                    357:   if (new)
                    358:     err = krt_send_route(p, RTM_ADD, new);
                    359: 
                    360:   if (err < 0)
                    361:     n->n.flags |= KRF_SYNC_ERROR;
                    362:   else
                    363:     n->n.flags &= ~KRF_SYNC_ERROR;
                    364: }
                    365: 
                    366: #define SKIP(ARG...) do { DBG("KRT: Ignoring route - " ARG); return; } while(0)
                    367: 
                    368: static void
                    369: krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan)
                    370: {
                    371:   /* p is NULL iff KRT_SHARED_SOCKET and !scan */
                    372: 
                    373:   int ipv6;
                    374:   rte *e;
                    375:   net *net;
                    376:   sockaddr dst, gate, mask;
                    377:   ip_addr idst, igate, imask;
                    378:   net_addr ndst;
                    379:   void *body = (char *)msg->buf;
                    380:   int new = (msg->rtm.rtm_type != RTM_DELETE);
                    381:   char *errmsg = "KRT: Invalid route received";
                    382:   int flags = msg->rtm.rtm_flags;
                    383:   int addrs = msg->rtm.rtm_addrs;
                    384:   int src;
                    385:   byte src2;
                    386: 
                    387:   if (!(flags & RTF_UP) && scan)
                    388:     SKIP("not up in scan\n");
                    389: 
                    390:   if (!(flags & RTF_DONE) && !scan)
                    391:     SKIP("not done in async\n");
                    392: 
                    393:   if (flags & RTF_LLINFO)
                    394:     SKIP("link-local\n");
                    395: 
                    396:   GETADDR(&dst, RTA_DST);
                    397:   GETADDR(&gate, RTA_GATEWAY);
                    398:   GETADDR(&mask, RTA_NETMASK);
                    399: 
                    400:   switch (dst.sa.sa_family) {
                    401:     case AF_INET:
                    402:       ipv6 = 0;
                    403:       break;
                    404:     case AF_INET6:
                    405:       ipv6 = 1;
                    406:       break;
                    407:     default:
                    408:       SKIP("invalid DST");
                    409:   }
                    410: 
                    411:   /* We do not test family for RTA_NETMASK, because BSD sends us
                    412:      some strange values, but interpreting them as IPv4/IPv6 works */
                    413:   mask.sa.sa_family = dst.sa.sa_family;
                    414: 
                    415:   idst  = ipa_from_sa(&dst);
                    416:   imask = ipa_from_sa(&mask);
                    417:   igate = (gate.sa.sa_family == dst.sa.sa_family) ? ipa_from_sa(&gate) : IPA_NONE;
                    418: 
                    419: #ifdef KRT_SHARED_SOCKET
                    420:   if (!scan)
                    421:   {
                    422:     int table_id = msg->rtm.rtm_tableid;
                    423:     p = (table_id < KRT_MAX_TABLES) ? krt_table_map[table_id][ipv6] : NULL;
                    424: 
                    425:     if (!p)
                    426:       SKIP("unknown table id %d\n", table_id);
                    427:   }
                    428: #endif
                    429:   if ((!ipv6) && (p->p.main_channel->table->addr_type != NET_IP4))
                    430:     SKIP("reading only IPv4 routes");
                    431:   if (  ipv6  && (p->p.main_channel->table->addr_type != NET_IP6))
                    432:     SKIP("reading only IPv6 routes");
                    433: 
                    434:   int c = ipa_classify_net(idst);
                    435:   if ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK))
                    436:     SKIP("strange class/scope\n");
                    437: 
                    438:   int pxlen;
                    439:   if (ipv6)
                    440:     pxlen = (flags & RTF_HOST) ? IP6_MAX_PREFIX_LENGTH : ip6_masklen(&ipa_to_ip6(imask));
                    441:   else
                    442:     pxlen = (flags & RTF_HOST) ? IP4_MAX_PREFIX_LENGTH : ip4_masklen(ipa_to_ip4(imask));
                    443: 
                    444:   if (pxlen < 0)
                    445:     { log(L_ERR "%s (%I) - netmask %I", errmsg, idst, imask); return; }
                    446: 
                    447:   if (ipv6)
                    448:     net_fill_ip6(&ndst, ipa_to_ip6(idst), pxlen);
                    449:   else
                    450:     net_fill_ip4(&ndst, ipa_to_ip4(idst), pxlen);
                    451: 
                    452:   if ((flags & RTF_GATEWAY) && ipa_zero(igate))
                    453:     { log(L_ERR "%s (%N) - missing gateway", errmsg, ndst); return; }
                    454: 
                    455:   u32 self_mask = RTF_PROTO1;
                    456:   u32 alien_mask = RTF_STATIC | RTF_PROTO1 | RTF_GATEWAY;
                    457: 
                    458:   src2 = (flags & RTF_STATIC) ? 1 : 0;
                    459:   src2 |= (flags & RTF_PROTO1) ? 2 : 0;
                    460: 
                    461: #ifdef RTF_PROTO2
                    462:   alien_mask |= RTF_PROTO2;
                    463:   src2 |= (flags & RTF_PROTO2) ? 4 : 0;
                    464: #endif
                    465: 
                    466: #ifdef RTF_PROTO3
                    467:   alien_mask |= RTF_PROTO3;
                    468:   src2 |= (flags & RTF_PROTO3) ? 8 : 0;
                    469: #endif
                    470: 
                    471: #ifdef RTF_REJECT
                    472:   alien_mask |= RTF_REJECT;
                    473: #endif
                    474: 
                    475: #ifdef RTF_BLACKHOLE
                    476:   alien_mask |= RTF_BLACKHOLE;
                    477: #endif
                    478: 
                    479:   if (flags & (RTF_DYNAMIC | RTF_MODIFIED))
                    480:     src = KRT_SRC_REDIRECT;
                    481:   else if (flags & self_mask)
                    482:     {
                    483:       if (!scan)
                    484:        SKIP("echo\n");
                    485:       src = KRT_SRC_BIRD;
                    486:     }
                    487:   else if (flags & alien_mask)
                    488:     src = KRT_SRC_ALIEN;
                    489:   else
                    490:     src = KRT_SRC_KERNEL;
                    491: 
                    492:   net = net_get(p->p.main_channel->table, &ndst);
                    493: 
                    494:   rta a = {
                    495:     .src = p->p.main_source,
                    496:     .source = RTS_INHERIT,
                    497:     .scope = SCOPE_UNIVERSE,
                    498:   };
                    499: 
                    500:   /* reject/blackhole routes have also set RTF_GATEWAY,
                    501:      we wil check them first. */
                    502: 
                    503: #ifdef RTF_REJECT
                    504:   if(flags & RTF_REJECT) {
                    505:     a.dest = RTD_UNREACHABLE;
                    506:     goto done;
                    507:   }
                    508: #endif
                    509: 
                    510: #ifdef RTF_BLACKHOLE
                    511:   if(flags & RTF_BLACKHOLE) {
                    512:     a.dest = RTD_BLACKHOLE;
                    513:     goto done;
                    514:   }
                    515: #endif
                    516: 
                    517:   a.nh.iface = if_find_by_index(msg->rtm.rtm_index);
                    518:   if (!a.nh.iface)
                    519:     {
                    520:       log(L_ERR "KRT: Received route %N with unknown ifindex %u",
                    521:          net->n.addr, msg->rtm.rtm_index);
                    522:       return;
                    523:     }
                    524: 
                    525:   a.dest = RTD_UNICAST;
                    526:   if (flags & RTF_GATEWAY)
                    527:   {
                    528:     neighbor *ng;
                    529:     a.nh.gw = igate;
                    530: 
                    531:     /* Clean up embedded interface ID returned in link-local address */
                    532:     if (ipa_is_link_local(a.nh.gw))
                    533:       _I0(a.nh.gw) = 0xfe800000;
                    534: 
                    535:     ng = neigh_find(&p->p, a.nh.gw, a.nh.iface, 0);
                    536:     if (!ng || (ng->scope == SCOPE_HOST))
                    537:       {
                    538:        /* Ignore routes with next-hop 127.0.0.1, host routes with such
                    539:           next-hop appear on OpenBSD for address aliases. */
                    540:         if (ipa_classify(a.nh.gw) == (IADDR_HOST | SCOPE_HOST))
                    541:           return;
                    542: 
                    543:        log(L_ERR "KRT: Received route %N with strange next-hop %I",
                    544:            net->n.addr, a.nh.gw);
                    545:        return;
                    546:       }
                    547:   }
                    548: 
                    549:  done:
                    550:   e = rte_get_temp(&a);
                    551:   e->net = net;
                    552:   e->u.krt.src = src;
                    553:   e->u.krt.proto = src2;
                    554:   e->u.krt.seen = 0;
                    555:   e->u.krt.best = 0;
                    556:   e->u.krt.metric = 0;
                    557: 
                    558:   if (scan)
                    559:     krt_got_route(p, e);
                    560:   else
                    561:     krt_got_route_async(p, e, new);
                    562: }
                    563: 
                    564: static void
                    565: krt_read_ifannounce(struct ks_msg *msg)
                    566: {
                    567:   struct if_announcemsghdr *ifam = (struct if_announcemsghdr *)&msg->rtm;
                    568: 
                    569:   if (ifam->ifan_what == IFAN_ARRIVAL)
                    570:   {
                    571:     /* Not enough info to create the iface, so we just trigger iface scan */
                    572:     kif_request_scan();
                    573:   }
                    574:   else if (ifam->ifan_what == IFAN_DEPARTURE)
                    575:   {
                    576:     struct iface *iface = if_find_by_index(ifam->ifan_index);
                    577: 
                    578:     /* Interface is destroyed */
                    579:     if (!iface)
                    580:     {
                    581:       DBG("KRT: unknown interface (%s, #%d) going down. Ignoring\n", ifam->ifan_name, ifam->ifan_index);
                    582:       return;
                    583:     }
                    584: 
                    585:     if_delete(iface);
                    586:   }
                    587: 
                    588:   DBG("KRT: IFANNOUNCE what: %d index %d name %s\n", ifam->ifan_what, ifam->ifan_index, ifam->ifan_name);
                    589: }
                    590: 
                    591: static void
                    592: krt_read_ifinfo(struct ks_msg *msg, int scan)
                    593: {
                    594:   struct if_msghdr *ifm = (struct if_msghdr *)&msg->rtm;
                    595:   void *body = (void *)(ifm + 1);
                    596:   struct sockaddr_dl *dl = NULL;
                    597:   uint i;
                    598:   struct iface *iface = NULL, f = {};
                    599:   int fl = ifm->ifm_flags;
                    600:   int nlen = 0;
                    601: 
                    602:   for (i = 1; i<=RTA_IFP; i <<= 1)
                    603:   {
                    604:     if (i & ifm->ifm_addrs)
                    605:     {
                    606:       if (i == RTA_IFP)
                    607:       {
                    608:         dl = (struct sockaddr_dl *)body;
                    609:         break;
                    610:       }
                    611:       body += ROUNDUP(((struct sockaddr *)&(body))->sa_len);
                    612:     }
                    613:   }
                    614: 
                    615:   if (dl && (dl->sdl_family != AF_LINK))
                    616:   {
                    617:     log(L_WARN "Ignoring strange IFINFO");
                    618:     return;
                    619:   }
                    620: 
                    621:   if (dl)
                    622:     nlen = MIN(sizeof(f.name)-1, dl->sdl_nlen);
                    623: 
                    624:   /* Note that asynchronous IFINFO messages do not contain iface
                    625:      name, so we have to found an existing iface by iface index */
                    626: 
                    627:   iface = if_find_by_index(ifm->ifm_index);
                    628:   if (!iface)
                    629:   {
                    630:     /* New interface */
                    631:     if (!dl)
                    632:       return;  /* No interface name, ignoring */
                    633: 
                    634:     memcpy(f.name, dl->sdl_data, nlen);
                    635:     DBG("New interface '%s' found\n", f.name);
                    636:   }
                    637:   else if (dl && memcmp(iface->name, dl->sdl_data, nlen))
                    638:   {
                    639:     /* Interface renamed */
                    640:     if_delete(iface);
                    641:     memcpy(f.name, dl->sdl_data, nlen);
                    642:   }
                    643:   else
                    644:   {
                    645:     /* Old interface */
                    646:     memcpy(f.name, iface->name, sizeof(f.name));
                    647:   }
                    648: 
                    649:   f.index = ifm->ifm_index;
                    650:   f.mtu = ifm->ifm_data.ifi_mtu;
                    651: 
                    652:   if (fl & IFF_UP)
                    653:     f.flags |= IF_ADMIN_UP;
                    654:   if (ifm->ifm_data.ifi_link_state != LINK_STATE_DOWN)
                    655:     f.flags |= IF_LINK_UP;          /* up or unknown */
                    656:   if (fl & IFF_LOOPBACK)            /* Loopback */
                    657:     f.flags |= IF_MULTIACCESS | IF_LOOPBACK | IF_IGNORE;
                    658:   else if (fl & IFF_POINTOPOINT)    /* PtP */
                    659:     f.flags |= IF_MULTICAST;
                    660:   else if (fl & IFF_BROADCAST)      /* Broadcast */
                    661:     f.flags |= IF_MULTIACCESS | IF_BROADCAST | IF_MULTICAST;
                    662:   else
                    663:     f.flags |= IF_MULTIACCESS;      /* NBMA */
                    664: 
                    665:   iface = if_update(&f);
                    666: 
                    667:   if (!scan)
                    668:     if_end_partial_update(iface);
                    669: }
                    670: 
                    671: static void
                    672: krt_read_addr(struct ks_msg *msg, int scan)
                    673: {
                    674:   struct ifa_msghdr *ifam = (struct ifa_msghdr *)&msg->rtm;
                    675:   void *body = (void *)(ifam + 1);
                    676:   sockaddr addr, mask, brd;
                    677:   struct iface *iface = NULL;
                    678:   struct ifa ifa;
                    679:   struct sockaddr null;
                    680:   ip_addr iaddr, imask, ibrd;
                    681:   int addrs = ifam->ifam_addrs;
                    682:   int scope, masklen = -1;
                    683:   int new = (ifam->ifam_type == RTM_NEWADDR);
                    684: 
                    685:   /* Strange messages with zero (invalid) ifindex appear on OpenBSD */
                    686:   if (ifam->ifam_index == 0)
                    687:     return;
                    688: 
                    689:   if(!(iface = if_find_by_index(ifam->ifam_index)))
                    690:   {
                    691:     log(L_ERR "KIF: Received address message for unknown interface %d", ifam->ifam_index);
                    692:     return;
                    693:   }
                    694: 
                    695:   GETADDR (&null, RTA_DST);
                    696:   GETADDR (&null, RTA_GATEWAY);
                    697:   GETADDR (&mask, RTA_NETMASK);
                    698:   GETADDR (&null, RTA_GENMASK);
                    699:   GETADDR (&null, RTA_IFP);
                    700:   GETADDR (&addr, RTA_IFA);
                    701:   GETADDR (&null, RTA_AUTHOR);
                    702:   GETADDR (&brd, RTA_BRD);
                    703: 
                    704:   /* Is addr family IP4 or IP6? */
                    705:   int ipv6;
                    706:   switch (addr.sa.sa_family) {
                    707:     case AF_INET: ipv6 = 0; break;
                    708:     case AF_INET6: ipv6 = 1; break;
                    709:     default: return;
                    710:   }
                    711: 
                    712:   /* We do not test family for RTA_NETMASK, because BSD sends us
                    713:      some strange values, but interpreting them as IPv4/IPv6 works */
                    714:   mask.sa.sa_family = addr.sa.sa_family;
                    715: 
                    716:   iaddr = ipa_from_sa(&addr);
                    717:   imask = ipa_from_sa(&mask);
                    718:   ibrd  = ipa_from_sa(&brd);
                    719: 
                    720:   if ((ipv6 ? (masklen = ip6_masklen(&ipa_to_ip6(imask))) : (masklen = ip4_masklen(ipa_to_ip4(imask)))) < 0)
                    721:   {
                    722:     log(L_ERR "KIF: Invalid mask %I for %s", imask, iface->name);
                    723:     return;
                    724:   }
                    725: 
                    726:   /* Clean up embedded interface ID returned in link-local address */
                    727: 
                    728:   if (ipa_is_link_local(iaddr))
                    729:     _I0(iaddr) = 0xfe800000;
                    730: 
                    731:   if (ipa_is_link_local(ibrd))
                    732:     _I0(ibrd) = 0xfe800000;
                    733: 
                    734: 
                    735:   bzero(&ifa, sizeof(ifa));
                    736:   ifa.iface = iface;
                    737:   ifa.ip = iaddr;
                    738: 
                    739:   scope = ipa_classify(ifa.ip);
                    740:   if (scope < 0)
                    741:   {
                    742:     log(L_ERR "KIF: Invalid interface address %I for %s", ifa.ip, iface->name);
                    743:     return;
                    744:   }
                    745:   ifa.scope = scope & IADDR_SCOPE_MASK;
                    746: 
                    747:   if (masklen < (ipv6 ? IP6_MAX_PREFIX_LENGTH : IP4_MAX_PREFIX_LENGTH))
                    748:   {
                    749:     net_fill_ipa(&ifa.prefix, ifa.ip, masklen);
                    750:     net_normalize(&ifa.prefix);
                    751: 
                    752:     if (masklen == ((ipv6 ? IP6_MAX_PREFIX_LENGTH : IP4_MAX_PREFIX_LENGTH) - 1))
                    753:       ifa.opposite = ipa_opposite_m1(ifa.ip);
                    754: 
                    755:     if ((!ipv6) && (masklen == IP4_MAX_PREFIX_LENGTH - 2))
                    756:       ifa.opposite = ipa_opposite_m2(ifa.ip);
                    757: 
                    758:     if (iface->flags & IF_BROADCAST)
                    759:       ifa.brd = ibrd;
                    760: 
                    761:     if (!(iface->flags & IF_MULTIACCESS))
                    762:       ifa.opposite = ibrd;
                    763:   }
                    764:   else if (!(iface->flags & IF_MULTIACCESS) && ipa_nonzero(ibrd))
                    765:   {
                    766:     net_fill_ipa(&ifa.prefix, ibrd, (ipv6 ? IP6_MAX_PREFIX_LENGTH : IP4_MAX_PREFIX_LENGTH));
                    767:     ifa.opposite = ibrd;
                    768:     ifa.flags |= IA_PEER;
                    769:   }
                    770:   else
                    771:   {
                    772:     net_fill_ipa(&ifa.prefix, ifa.ip, (ipv6 ? IP6_MAX_PREFIX_LENGTH : IP4_MAX_PREFIX_LENGTH));
                    773:     ifa.flags |= IA_HOST;
                    774:   }
                    775: 
                    776:   if (new)
                    777:     ifa_update(&ifa);
                    778:   else
                    779:     ifa_delete(&ifa);
                    780: 
                    781:   if (!scan)
                    782:     if_end_partial_update(iface);
                    783: }
                    784: 
                    785: static void
                    786: krt_read_msg(struct proto *p, struct ks_msg *msg, int scan)
                    787: {
                    788:   /* p is NULL iff KRT_SHARED_SOCKET and !scan */
                    789: 
                    790:   switch (msg->rtm.rtm_type)
                    791:   {
                    792:     case RTM_GET:
                    793:       if(!scan) return;
                    794:     case RTM_ADD:
                    795:     case RTM_DELETE:
                    796:     case RTM_CHANGE:
                    797:       krt_read_route(msg, (struct krt_proto *)p, scan);
                    798:       break;
                    799:     case RTM_IFANNOUNCE:
                    800:       krt_read_ifannounce(msg);
                    801:       break;
                    802:     case RTM_IFINFO:
                    803:       krt_read_ifinfo(msg, scan);
                    804:       break;
                    805:     case RTM_NEWADDR:
                    806:     case RTM_DELADDR:
                    807:       krt_read_addr(msg, scan);
                    808:       break;
                    809:     default:
                    810:       break;
                    811:   }
                    812: }
                    813: 
                    814: 
                    815: /* Sysctl based scans */
                    816: 
                    817: static byte *krt_buffer;
                    818: static size_t krt_buflen, krt_bufmin;
                    819: static struct proto *krt_buffer_owner;
                    820: 
                    821: static byte *
                    822: krt_buffer_update(struct proto *p, size_t *needed)
                    823: {
                    824:   size_t req = *needed;
                    825: 
                    826:   if ((req > krt_buflen) ||
                    827:       ((p == krt_buffer_owner) && (req < krt_bufmin)))
                    828:   {
                    829:     /* min buflen is 32 kB, step is 8 kB, or 128 kB if > 1 MB */
                    830:     size_t step = (req < 0x100000) ? 0x2000 : 0x20000;
                    831:     krt_buflen = (req < 0x6000) ? 0x8000 : (req + step);
                    832:     krt_bufmin = (req < 0x8000) ? 0 : (req - 2*step);
                    833: 
                    834:     if (krt_buffer) 
                    835:       mb_free(krt_buffer);
                    836:     krt_buffer = mb_alloc(krt_pool, krt_buflen);
                    837:     krt_buffer_owner = p;
                    838:   }
                    839: 
                    840:   *needed = krt_buflen;
                    841:   return krt_buffer;
                    842: }
                    843: 
                    844: static void
                    845: krt_buffer_release(struct proto *p)
                    846: {
                    847:   if (p == krt_buffer_owner)
                    848:   {
                    849:     mb_free(krt_buffer);
                    850:     krt_buffer = NULL;
                    851:     krt_buflen = 0;
                    852:     krt_buffer_owner = 0;
                    853:   }
                    854: }
                    855: 
                    856: static void
                    857: krt_sysctl_scan(struct proto *p, int cmd, int table_id)
                    858: {
                    859:   byte *buf, *next;
                    860:   int mib[7], mcnt;
                    861:   size_t needed;
                    862:   struct ks_msg *m;
                    863:   int retries = 3;
                    864:   int rv;
                    865: 
                    866:   mib[0] = CTL_NET;
                    867:   mib[1] = PF_ROUTE;
                    868:   mib[2] = 0;
                    869:   mib[3] = 0; // Set AF to 0 for all available families
                    870:   mib[4] = cmd;
                    871:   mib[5] = 0;
                    872:   mcnt = 6;
                    873: 
                    874: #ifdef KRT_USE_SYSCTL_7
                    875:   if (table_id >= 0)
                    876:   {
                    877:     mib[6] = table_id;
                    878:     mcnt = 7;
                    879:   }
                    880: #endif
                    881: 
                    882: #ifdef KRT_USE_SETFIB_SCAN
                    883:   if (table_id > 0)
                    884:     if (setfib(table_id) < 0)
                    885:     {
                    886:       log(L_ERR "KRT: setfib(%d) failed: %m", table_id);
                    887:       return;
                    888:     }
                    889: #endif
                    890: 
                    891:  try:
                    892:   rv = sysctl(mib, mcnt, NULL, &needed, NULL, 0);
                    893:   if (rv < 0)
                    894:   {
                    895:     /* OpenBSD returns EINVAL for not yet used tables */
                    896:     if ((errno == EINVAL) && (table_id > 0))
                    897:       goto exit;
                    898: 
                    899:     log(L_ERR "KRT: Route scan estimate failed: %m");
                    900:     goto exit;
                    901:   }
                    902: 
                    903:   /* The table is empty */
                    904:   if (needed == 0)
                    905:     goto exit;
                    906: 
                    907:   buf = krt_buffer_update(p, &needed);
                    908: 
                    909:   rv = sysctl(mib, mcnt, buf, &needed, NULL, 0);
                    910:   if (rv < 0)
                    911:   {
                    912:     /* The buffer size changed since last sysctl ('needed' is not changed) */
                    913:     if ((errno == ENOMEM) && retries--)
                    914:       goto try;
                    915: 
                    916:     log(L_ERR "KRT: Route scan failed: %m");
                    917:     goto exit;
                    918:   }
                    919: 
                    920: #ifdef KRT_USE_SETFIB_SCAN
                    921:   if (table_id > 0)
                    922:     if (setfib(0) < 0)
                    923:       die("KRT: setfib(%d) failed: %m", 0);
                    924: #endif
                    925: 
                    926:   /* Process received messages */
                    927:   for (next = buf; next < (buf + needed); next += m->rtm.rtm_msglen)
                    928:   {
                    929:     m = (struct ks_msg *)next;
                    930:     krt_read_msg(p, m, 1);
                    931:   }
                    932: 
                    933:   return;
                    934: 
                    935:  exit:
                    936:   krt_buffer_release(p);
                    937: 
                    938: #ifdef KRT_USE_SETFIB_SCAN
                    939:   if (table_id > 0)
                    940:     if (setfib(0) < 0)
                    941:       die("KRT: setfib(%d) failed: %m", 0);
                    942: #endif
                    943: }
                    944: 
                    945: void
                    946: krt_do_scan(struct krt_proto *p)
                    947: {
                    948:   krt_sysctl_scan(&p->p, NET_RT_DUMP, KRT_CF->sys.table_id);
                    949: }
                    950: 
                    951: void
                    952: kif_do_scan(struct kif_proto *p)
                    953: {
                    954:   if_start_update();
                    955:   krt_sysctl_scan(&p->p, NET_RT_IFLIST, -1);
                    956:   if_end_update();
                    957: }
                    958: 
                    959: 
                    960: /* Kernel sockets */
                    961: 
                    962: static int
                    963: krt_sock_hook(sock *sk, uint size UNUSED)
                    964: {
                    965:   struct ks_msg msg;
                    966:   int l = read(sk->fd, (char *)&msg, sizeof(msg));
                    967: 
                    968:   if (l <= 0)
                    969:     log(L_ERR "krt-sock: read failed");
                    970:   else
                    971:     krt_read_msg((struct proto *) sk->data, &msg, 0);
                    972: 
                    973:   return 0;
                    974: }
                    975: 
                    976: static void
                    977: krt_sock_err_hook(sock *sk, int e UNUSED)
                    978: {
                    979:   krt_sock_hook(sk, 0);
                    980: }
                    981: 
                    982: static sock *
                    983: krt_sock_open(pool *pool, void *data, int table_id UNUSED)
                    984: {
                    985:   sock *sk;
                    986:   int fd;
                    987: 
                    988:   fd = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC);
                    989:   if (fd < 0)
                    990:     die("Cannot open kernel socket for routes");
                    991: 
                    992: #ifdef KRT_USE_SETFIB_SOCK
                    993:   if (table_id > 0)
                    994:   {
                    995:     if (setsockopt(fd, SOL_SOCKET, SO_SETFIB, &table_id, sizeof(table_id)) < 0)
                    996:       die("Cannot set FIB %d for kernel socket: %m", table_id);
                    997:   }
                    998: #endif
                    999: 
                   1000:   sk = sk_new(pool);
                   1001:   sk->type = SK_MAGIC;
                   1002:   sk->rx_hook = krt_sock_hook;
                   1003:   sk->err_hook = krt_sock_err_hook;
                   1004:   sk->fd = fd;
                   1005:   sk->data = data;
                   1006: 
                   1007:   if (sk_open(sk) < 0)
                   1008:     bug("krt-sock: sk_open failed");
                   1009: 
                   1010:   return sk;
                   1011: }
                   1012: 
                   1013: static u32 krt_table_cf[(KRT_MAX_TABLES+31) / 32][2];
                   1014: 
                   1015: #ifdef KRT_SHARED_SOCKET
                   1016: 
                   1017: static sock *krt_sock;
                   1018: static int krt_sock_count;
                   1019: 
                   1020: 
                   1021: static void
                   1022: krt_sock_open_shared(void)
                   1023: {
                   1024:   if (!krt_sock_count)
                   1025:     krt_sock = krt_sock_open(krt_pool, NULL, -1);
                   1026:   
                   1027:   krt_sock_count++;
                   1028: }
                   1029: 
                   1030: static void
                   1031: krt_sock_close_shared(void)
                   1032: {
                   1033:   krt_sock_count--;
                   1034: 
                   1035:   if (!krt_sock_count)
                   1036:   {
                   1037:     rfree(krt_sock);
                   1038:     krt_sock = NULL;
                   1039:   }
                   1040: }
                   1041: 
                   1042: int
                   1043: krt_sys_start(struct krt_proto *p)
                   1044: {
                   1045:   int id = KRT_CF->sys.table_id;
                   1046: 
                   1047:   if (krt_table_cf[id/32][!!(p->af == AF_INET6)] & (1 << (id%32)))
                   1048:     {
                   1049:       log(L_ERR "%s: Multiple kernel syncers defined for table #%d", p->p.name, id);
                   1050:       return 0;
                   1051:     }
                   1052: 
                   1053:   krt_table_cf[id/32][!!(p->af == AF_INET6)] |= (1 << (id%32));
                   1054: 
                   1055:   krt_table_map[KRT_CF->sys.table_id][!!(p->af == AF_INET6)] = p;
                   1056: 
                   1057:   krt_sock_open_shared();
                   1058:   p->sys.sk = krt_sock;
                   1059: 
                   1060:   return 1;
                   1061: }
                   1062: 
                   1063: void
                   1064: krt_sys_shutdown(struct krt_proto *p)
                   1065: {
                   1066:   krt_table_cf[(KRT_CF->sys.table_id)/32][!!(p->af == AF_INET6)] &= ~(1 << ((KRT_CF->sys.table_id)%32));
                   1067: 
                   1068:   krt_sock_close_shared();
                   1069:   p->sys.sk = NULL;
                   1070: 
                   1071:   krt_table_map[KRT_CF->sys.table_id][!!(p->af == AF_INET6)] = NULL;
                   1072: 
                   1073:   krt_buffer_release(&p->p);
                   1074: }
                   1075: 
                   1076: #else
                   1077: 
                   1078: int
                   1079: krt_sys_start(struct krt_proto *p)
                   1080: {
                   1081:   int id = KRT_CF->sys.table_id;
                   1082: 
                   1083:   if (krt_table_cf[id/32][!!(p->af == AF_INET6)] & (1 << (id%32)))
                   1084:     {
                   1085:       log(L_ERR "%s: Multiple kernel syncers defined for table #%d", p->p.name, id);
                   1086:       return 0;
                   1087:     }
                   1088: 
                   1089:   krt_table_cf[id/32][!!(p->af == AF_INET6)] |= (1 << (id%32));
                   1090: 
                   1091:   p->sys.sk = krt_sock_open(p->p.pool, p, KRT_CF->sys.table_id);
                   1092:   return 1;
                   1093: }
                   1094: 
                   1095: void
                   1096: krt_sys_shutdown(struct krt_proto *p)
                   1097: {
                   1098:   krt_table_cf[(KRT_CF->sys.table_id)/32][!!(p->af == AF_INET6)] &= ~(1 << ((KRT_CF->sys.table_id)%32));
                   1099: 
                   1100:   rfree(p->sys.sk);
                   1101:   p->sys.sk = NULL;
                   1102: 
                   1103:   krt_buffer_release(&p->p);
                   1104: }
                   1105: 
                   1106: #endif /* KRT_SHARED_SOCKET */
                   1107: 
                   1108: 
                   1109: /* KRT configuration callbacks */
                   1110: 
                   1111: int
                   1112: krt_sys_reconfigure(struct krt_proto *p UNUSED, struct krt_config *n, struct krt_config *o)
                   1113: {
                   1114:   return n->sys.table_id == o->sys.table_id;
                   1115: }
                   1116: 
                   1117: void
                   1118: krt_sys_preconfig(struct config *c UNUSED)
                   1119: {
                   1120:   krt_max_tables = krt_get_max_tables();
                   1121:   bzero(&krt_table_cf, sizeof(krt_table_cf));
                   1122: }
                   1123: 
                   1124: void krt_sys_init_config(struct krt_config *c)
                   1125: {
                   1126:   c->sys.table_id = 0; /* Default table */
                   1127: }
                   1128: 
                   1129: void krt_sys_copy_config(struct krt_config *d, struct krt_config *s)
                   1130: {
                   1131:   d->sys.table_id = s->sys.table_id;
                   1132: }
                   1133: 
                   1134: 
                   1135: /* KIF misc code */
                   1136: 
                   1137: void
                   1138: kif_sys_start(struct kif_proto *p UNUSED)
                   1139: {
                   1140: }
                   1141: 
                   1142: void
                   1143: kif_sys_shutdown(struct kif_proto *p)
                   1144: {
                   1145:   krt_buffer_release(&p->p);
                   1146: }
                   1147: 
                   1148: int
                   1149: kif_update_sysdep_addr(struct iface *i)
                   1150: {
                   1151:   static int fd = -1;
                   1152: 
                   1153:   if (fd < 0)
                   1154:     fd = socket(AF_INET, SOCK_DGRAM, 0);
                   1155: 
                   1156:   struct ifreq ifr;
                   1157:   memset(&ifr, 0, sizeof(ifr));
                   1158:   strncpy(ifr.ifr_name, i->name, IFNAMSIZ);
                   1159: 
                   1160:   int rv = ioctl(fd, SIOCGIFADDR, (char *) &ifr);
                   1161:   if (rv < 0)
                   1162:     return 0;
                   1163: 
                   1164:   ip4_addr old = i->sysdep;
                   1165:   i->sysdep = ipa_to_ip4(ipa_from_sa4(&ifr.ifr_addr));
                   1166: 
                   1167:   return !ip4_equal(i->sysdep, old);
                   1168: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>