]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Many changes in (mainly) kernel syncers.
authorOndrej Zajicek <santiago@crfreenet.org>
Fri, 26 Feb 2010 09:55:58 +0000 (10:55 +0100)
committerOndrej Zajicek <santiago@crfreenet.org>
Fri, 26 Feb 2010 09:55:58 +0000 (10:55 +0100)
- BSD kernel syncer is now self-conscious and can learn alien routes
- important bugfix in BSD kernel syncer (crash after protocol restart)
- many minor changes and bugfixes in kernel syncers and neighbor cache
- direct protocol does not generate host and link local routes
- min_scope check is removed, all routes have SCOPE_UNIVERSE by default
- also fixes some remaining compiler warnings

19 files changed:
doc/bird.sgml
lib/ip.h
nest/iface.h
nest/neighbor.c
nest/proto.c
nest/protocol.h
nest/rt-dev.c
nest/rt-table.c
proto/bgp/packets.c
proto/ospf/ospf.c
proto/ospf/rt.c
sysdep/bsd/krt-sock.c
sysdep/cf/bsd-v6.h
sysdep/cf/bsd.h
sysdep/linux/netlink/netlink.c
sysdep/unix/io.c
sysdep/unix/krt.c
sysdep/unix/krt.h
sysdep/unix/unix.h

index 3d82e45bd9e35025978ae23757b1175b78e65963..b70f0345a966aac40f787893e29c3e4aa91f63ba 100644 (file)
@@ -824,7 +824,14 @@ defined by using the <cf>defined( <m>attribute</m> )</cf> operator.
        Network the route is talking about. Read-only. (See the chapter about routing tables.)
 
        <tag><m/enum/ scope</tag>
-       Address scope of the network (<cf/SCOPE_HOST/ for addresses local to this host, <cf/SCOPE_LINK/ for those specific for a physical link, <cf/SCOPE_SITE/ and <cf/SCOPE_ORGANIZATION/ for private addresses, <cf/SCOPE_UNIVERSE/ for globally visible addresses).
+       The scope of the route. Possible values: <cf/SCOPE_HOST/ for
+       routes local to this host, <cf/SCOPE_LINK/ for those specific
+       for a physical link, <cf/SCOPE_SITE/ and
+       <cf/SCOPE_ORGANIZATION/ for private routes and
+       <cf/SCOPE_UNIVERSE/ for globally visible routes. This
+       attribute is not interpreted by BIRD and can be used to mark
+       routes in filters. The default value for new routes is
+       <cf/SCOPE_UNIVERSE/.
 
        <tag><m/int/ preference</tag>
        Preference of the route. Valid values are 0-65535. (See the chapter about routing tables.)
@@ -842,7 +849,11 @@ defined by using the <cf>defined( <m>attribute</m> )</cf> operator.
        what protocol has told me about this route. Possible values: <cf/RTS_DUMMY/, <cf/RTS_STATIC/, <cf/RTS_INHERIT/, <cf/RTS_DEVICE/, <cf/RTS_STATIC_DEVICE/, <cf/RTS_REDIRECT/, <cf/RTS_RIP/, <cf/RTS_OSPF/, <cf/RTS_OSPF_IA/, <cf/RTS_OSPF_EXT/, <cf/RTS_BGP/, <cf/RTS_PIPE/.
 
        <tag><m/enum/ cast</tag>
-       Route type (<cf/RTC_UNICAST/ for normal routes, <cf/RTC_BROADCAST/, <cf/RTC_MULTICAST/, <cf/RTC_ANYCAST/ for broadcast, multicast and anycast routes). Read-only.
+
+       Route type (Currently <cf/RTC_UNICAST/ for normal routes,
+       <cf/RTC_BROADCAST/, <cf/RTC_MULTICAST/, <cf/RTC_ANYCAST/ will
+       be used in the future for broadcast, multicast and anycast
+       routes). Read-only.
 
        <tag><m/enum/ dest</tag>
        Type of destination the packets should be sent to (<cf/RTD_ROUTER/ for forwarding to a neighboring router, <cf/RTD_NETWORK/ for routing to a directly-connected network, <cf/RTD_BLACKHOLE/ for packets to be silently discarded, <cf/RTD_UNREACHABLE/, <cf/RTD_PROHIBIT/ for packets that should be returned with ICMP host unreachable / ICMP administratively prohibited messages). Read-only.
index 5dc9191b05a502674caa31630e23a814ce9893e9..e9923e2fda68aeafe21e749ff3ea62ffc5add5e5 100644 (file)
--- a/lib/ip.h
+++ b/lib/ip.h
@@ -50,6 +50,10 @@ struct prefix {
 };
 
 #define ip_is_prefix(a,l) (!ipa_nonzero(ipa_and(a, ipa_not(ipa_mkmask(l)))))
+#define ipa_zero(x) (!ipa_nonzero(x))
+
+static inline int ipa_classify_net(ip_addr a)
+{ return ipa_zero(a) ? (IADDR_HOST | SCOPE_UNIVERSE) : ipa_classify(a); }
 
 /*
  *     Conversions between internal and string representation
index a982c17f4bf370fc4e6a7f07b400b15702271b13..02129ac6efaa5f0f7a83032fc6b859473d1bfa7b 100644 (file)
@@ -97,6 +97,7 @@ typedef struct neighbor {
 } neighbor;
 
 #define NEF_STICKY 1
+#define NEF_ONLINK 2
 
 neighbor *neigh_find(struct proto *, ip_addr *, unsigned flags);
 neighbor *neigh_find2(struct proto *p, ip_addr *a, struct iface *ifa, unsigned flags);
index a44667f504173c12ac7e81e0319e2976dc2a9774..25b98dbd91a187eeceda2b0597b61915e58fd9f3 100644 (file)
@@ -112,12 +112,12 @@ neighbor *
 neigh_find2(struct proto *p, ip_addr *a, struct iface *ifa, unsigned flags)
 {
   neighbor *n;
-  int class, scope = SCOPE_HOST;
+  int class, scope = -1;       ;
   unsigned int h = neigh_hash(p, a);
   struct iface *i;
 
   WALK_LIST(n, neigh_hash_table[h])    /* Search the cache */
-    if (n->proto == p && ipa_equal(*a, n->addr))
+    if (n->proto == p && ipa_equal(*a, n->addr) && (!ifa || (ifa == n->iface)))
       return n;
 
   class = ipa_classify(*a);
@@ -129,7 +129,12 @@ neigh_find2(struct proto *p, ip_addr *a, struct iface *ifa, unsigned flags)
     return NULL;                       /* Bad scope or a somecast */
 
   if (ifa)
-    scope = if_connected(a, ifa);
+    {
+      scope = if_connected(a, ifa);
+
+      if ((scope < 0) && (flags & NEF_ONLINK))
+       scope = class & IADDR_SCOPE_MASK;
+    }
   else
     WALK_LIST(i, iface_list)
       if ((scope = if_connected(a, i)) >= 0)
@@ -138,22 +143,28 @@ neigh_find2(struct proto *p, ip_addr *a, struct iface *ifa, unsigned flags)
          break;
        }
 
-  if (!ifa && !(flags & NEF_STICKY))
+  /* scope < 0 means i don't know neighbor */
+  /* scope >= 0 implies ifa != NULL */
+
+  if ((scope < 0) && !(flags & NEF_STICKY))
     return NULL;
 
   n = sl_alloc(neigh_slab);
   n->addr = *a;
-  n->iface = ifa;
-  if (ifa)
+  if (scope >= 0)
     {
       add_tail(&neigh_hash_table[h], &n->n);
       add_tail(&ifa->neighbors, &n->if_n);
     }
   else
     {
+      /* sticky flag does not work for link-local neighbors;
+        fortunately, we don't use this combination */
       add_tail(&sticky_neigh_list, &n->n);
+      ifa = NULL;
       scope = 0;
     }
+  n->iface = ifa;
   n->proto = p;
   n->data = NULL;
   n->aux = 0;
index 488370552c125f645c71279bd54dc44fa9bdba32..db6bf9bf94037659c229c51537f1f82815a1c6e1 100644 (file)
@@ -113,7 +113,6 @@ proto_new(struct proto_config *c, unsigned size)
   p->table = c->table->table;
   p->in_filter = c->in_filter;
   p->out_filter = c->out_filter;
-  p->min_scope = SCOPE_SITE;
   p->hash_key = random_u32();
   c->proto = p;
   return p;
index 99356a3d26e24654cb78a55491ce7a11d5540960..d94873e4630f85ccee5273f7d25e4e1307a40299 100644 (file)
@@ -130,7 +130,6 @@ struct proto {
   u32 debug;                           /* Debugging flags */
   u32 mrtdump;                         /* MRTDump flags */
   unsigned preference;                 /* Default route preference */
-  int min_scope;                       /* Minimal route scope accepted */
   unsigned accept_ra_types;            /* Which types of route announcements are accepted (RA_OPTIMAL or RA_ANY) */
   unsigned disabled;                   /* Manually disabled */
   unsigned proto_state;                        /* Protocol state machine (see below) */
index b86015df7ab8e7d698538a154ea76d3acbb8c320..bb8eb8ee1d369399ca024c432c5e5db5603ccbfd 100644 (file)
@@ -33,6 +33,10 @@ dev_ifa_notify(struct proto *p, unsigned c, struct ifa *ad)
       !iface_patt_find(&P->iface_list, ad->iface))
     /* Empty list is automagically treated as "*" */
     return;
+
+  if (ad->scope <= SCOPE_LINK)
+    return;
+
   if (c & IF_CHANGE_DOWN)
     {
       net *n;
@@ -56,7 +60,7 @@ dev_ifa_notify(struct proto *p, unsigned c, struct ifa *ad)
       bzero(&A, sizeof(A));
       A.proto = p;
       A.source = RTS_DEVICE;
-      A.scope = ad->scope;
+      A.scope = SCOPE_UNIVERSE;
       A.cast = RTC_UNICAST;
       A.dest = RTD_DEVICE;
       A.iface = ad->iface;
@@ -76,7 +80,6 @@ dev_init(struct proto_config *c)
   struct proto *p = proto_new(c, sizeof(struct proto));
 
   p->ifa_notify = dev_ifa_notify;
-  p->min_scope = SCOPE_HOST;
   return p;
 }
 
index 41ecf64610ccf1d95974ca141c440157a9581200..1860b1a1f8cc955c6a05819bb6558f1f1413bd25 100644 (file)
@@ -158,7 +158,7 @@ rte_trace_out(unsigned int flag, struct proto *p, rte *e, char *msg)
 }
 
 static inline void
-do_rte_announce(struct announce_hook *a, int type UNUSED, net *net, rte *new, rte *old, ea_list *tmpa, int class, int refeed)
+do_rte_announce(struct announce_hook *a, int type UNUSED, net *net, rte *new, rte *old, ea_list *tmpa, int refeed)
 {
   struct proto *p = a->proto;
   struct filter *filter = p->out_filter;
@@ -183,13 +183,7 @@ do_rte_announce(struct announce_hook *a, int type UNUSED, net *net, rte *new, rt
       stats->exp_updates_received++;
 
       char *drop_reason = NULL;
-      if ((class & IADDR_SCOPE_MASK) < p->min_scope)
-       {
-         stats->exp_updates_rejected++;
-         drop_reason = "out of scope";
-         fast_exit_hack = 1;
-       }
-      else if ((ok = p->import_control ? p->import_control(p, &new, &tmpa, rte_update_pool) : 0) < 0)
+      if ((ok = p->import_control ? p->import_control(p, &new, &tmpa, rte_update_pool) : 0) < 0)
        {
          stats->exp_updates_rejected++;
          drop_reason = "rejected by protocol";
@@ -332,7 +326,6 @@ static void
 rte_announce(rtable *tab, unsigned type, net *net, rte *new, rte *old, ea_list *tmpa)
 {
   struct announce_hook *a;
-  int class = ipa_classify(net->n.prefix);
 
   if (type == RA_OPTIMAL)
     {
@@ -346,7 +339,7 @@ rte_announce(rtable *tab, unsigned type, net *net, rte *new, rte *old, ea_list *
     {
       ASSERT(a->proto->core_state == FS_HAPPY || a->proto->core_state == FS_FEEDING);
       if (a->proto->accept_ra_types == type)
-       do_rte_announce(a, type, net, new, old, tmpa, class, 0);
+       do_rte_announce(a, type, net, new, old, tmpa, 0);
     }
 }
 
@@ -362,33 +355,15 @@ rte_validate(rte *e)
          n->n.prefix, n->n.pxlen, e->sender->name);
       return 0;
     }
-  if (n->n.pxlen)
+
+  c = ipa_classify_net(n->n.prefix);
+  if ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK))
     {
-      c = ipa_classify(n->n.prefix);
-      if (c < 0 || !(c & IADDR_HOST))
-       {
-         if (!ipa_nonzero(n->n.prefix))
-           {
-             /* Various default routes */
-#ifdef IPV6
-             if (n->n.pxlen == 96)
-#else
-             if (n->n.pxlen <= 1)
-#endif
-               return 1;
-           }
-         log(L_WARN "Ignoring bogus route %I/%d received via %s",
-             n->n.prefix, n->n.pxlen, e->sender->name);
-         return 0;
-       }
-      if ((c & IADDR_SCOPE_MASK) < e->sender->min_scope)
-       {
-         log(L_WARN "Ignoring %s scope route %I/%d received from %I via %s",
-             ip_scope_text(c & IADDR_SCOPE_MASK),
-             n->n.prefix, n->n.pxlen, e->attrs->from, e->sender->name);
-         return 0;
-       }
+      log(L_WARN "Ignoring bogus route %I/%d received via %s",
+         n->n.prefix, n->n.pxlen, e->sender->name);
+      return 0;
     }
+
   return 1;
 }
 
@@ -1018,7 +993,7 @@ do_feed_baby(struct proto *p, int type, struct announce_hook *h, net *n, rte *e)
 
   rte_update_lock();
   tmpa = q->make_tmp_attrs ? q->make_tmp_attrs(e, rte_update_pool) : NULL;
-  do_rte_announce(h, type, n, e, p->refeeding ? e : NULL, tmpa, ipa_classify(n->n.prefix), p->refeeding);
+  do_rte_announce(h, type, n, e, p->refeeding ? e : NULL, tmpa, p->refeeding);
   rte_update_unlock();
 }
 
@@ -1190,11 +1165,8 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
       if (p2 && p2 != p0) ok = 0;
       if (ok && d->export_mode)
        {
-         int class = ipa_classify(n->n.prefix);
          int ic;
-         if ((class & IADDR_SCOPE_MASK) < p1->min_scope)
-           ok = 0;
-         else if ((ic = p1->import_control ? p1->import_control(p1, &e, &tmpa, rte_update_pool) : 0) < 0)
+         if ((ic = p1->import_control ? p1->import_control(p1, &e, &tmpa, rte_update_pool) : 0) < 0)
            ok = 0;
          else if (!ic && d->export_mode > 1)
            {
index 3609c5681c01b7bdea3c66d664100e604fd63b07..2baa6e348ec5f57c0df6543d0c67a5267b70e6a5 100644 (file)
@@ -914,7 +914,6 @@ bgp_do_rx_update(struct bgp_conn *conn,
   rta *a = NULL;
   ip_addr prefix;
   net *n;
-  rte e;
   int err = 0, pxlen;
 
   p->mp_reach_len = 0;
@@ -936,8 +935,6 @@ bgp_do_rx_update(struct bgp_conn *conn,
 
   DO_NLRI(mp_reach)
     {
-      int i;
-
       /* Create fake NEXT_HOP attribute */
       if (len < 1 || (*x != 16 && *x != 32) || len < *x + 2)
        goto bad;
index edca5959b7c28105f0ecb4e75bf805ea85c16a45..191aa4563f1e2b02be5690fe9486f3da6602d05f 100644 (file)
@@ -1234,7 +1234,6 @@ show_lsa_sum_rt(struct top_hash_entry *he)
 static inline void
 show_lsa_external(struct top_hash_entry *he)
 {
-  struct ospf_lsa_header *lsa = &(he->lsa);
   struct ospf_lsa_ext *ext = he->lsa_body;
   char str_via[STD_ADDRESS_P_LENGTH + 8] = "";
   char str_tag[16] = "";
@@ -1245,7 +1244,7 @@ show_lsa_external(struct top_hash_entry *he)
   rt_metric = ext->metric & METRIC_MASK;
   ebit = ext->metric & LSA_EXT_EBIT;
 #ifdef OSPFv2
-  ip = ipa_and(ipa_from_u32(lsa->id), ext->netmask);
+  ip = ipa_and(ipa_from_u32(he->lsa.id), ext->netmask);
   pxlen = ipa_mklen(ext->netmask);
   rt_fwaddr = ext->fwaddr;
   rt_fwaddr_valid = !ipa_equal(rt_fwaddr, IPA_NONE);
@@ -1282,10 +1281,7 @@ show_lsa_external(struct top_hash_entry *he)
 static inline void
 show_lsa_prefix(struct top_hash_entry *he, struct ospf_lsa_header *olsa)
 {
-  struct ospf_lsa_header *lsa = &(he->lsa);
   struct ospf_lsa_prefix *px = he->lsa_body;
-  struct ospf_lsa_ext *ext = he->lsa_body;
-  char *msg;
   ip_addr pxa;
   int pxlen;
   u8 pxopts;
@@ -1504,8 +1500,10 @@ ospf_sh_lsadb(struct proto *p)
          break;
 #ifdef OSPFv3
        case LSA_SCOPE_LINK:
-         struct iface *ifa = if_find_by_index(hea[i]->domain);
-         cli_msg(-1017, "Link %s", (ifa != NULL) ? ifa->name : "?");
+         {
+           struct iface *ifa = if_find_by_index(hea[i]->domain);
+           cli_msg(-1017, "Link %s", (ifa != NULL) ? ifa->name : "?");
+         }
          break;
 #endif
       }
index 84e472526f4d5cb1846af2a3b656aa8d4d6f2784..c856eea1f8ee8a29defd3c0b4bcb4b3aa89292a5 100644 (file)
@@ -170,7 +170,7 @@ static void
 process_prefixes(struct ospf_area *oa)
 {
   struct proto_ospf *po = oa->po;
-  struct proto *p = &po->proto;
+  // struct proto *p = &po->proto;
   struct top_hash_entry *en, *src;
   struct ospf_lsa_prefix *px;
   ip_addr pxa;
@@ -228,7 +228,6 @@ ospf_rt_spfa_rtlinks(struct ospf_area *oa, struct top_hash_entry *act, struct to
 {
   // struct proto *p = &oa->po->proto;
   struct proto_ospf *po = oa->po;
-  orta nf;
   u32 i;
 
   struct ospf_lsa_rt *rt = en->lsa_body;
@@ -249,6 +248,7 @@ ospf_rt_spfa_rtlinks(struct ospf_area *oa, struct top_hash_entry *act, struct to
           */
          DBG("\n");
 
+         orta nf;
          nf.type = RTS_OSPF;
          nf.options = 0;
          nf.metric1 = act->dist + rtl->metric;
@@ -571,7 +571,7 @@ ospf_rt_sum_tr(struct ospf_area *oa)
       type = ORT_NET;
       re = (ort *) fib_find(&po->rtf, &ip, pxlen);
     }
-    else if (en->lsa.type == LSA_T_SUM_RT)
+    else // en->lsa.type == LSA_T_SUM_RT
     {
 #ifdef OSPFv2
       struct ospf_lsa_sum *ls = en->lsa_body;
index a5279657692edbf939f382c64772623b197e4a78..dac2c2e6090e034bb8ddd32f2822942771f7f347 100644 (file)
 #include "lib/string.h"
 #include "lib/socket.h"
 
-#ifdef IPV6
-#define HOST_MASK 128
-#else
-#define HOST_MASK 32
-#endif
-
 int rt_sock = 0;
 
-#define CHECK_FAMILY(sa) \
-  ((((struct sockaddr *)sa)->sa_family) == BIRD_AF)
-
-static struct iface *
-krt_temp_iface_index(struct krt_proto *p, unsigned index)
-{
-  struct iface *i, *j;
-
-  WALK_LIST(i, p->scan.temp_ifs)
-    if (i->index == index)
-      return i;
-  i = mb_allocz(p->p.pool, sizeof(struct iface));
-  if (j = if_find_by_index(index))
-  {
-    strcpy(i->name, j->name);
-    i->addr = j->addr;
-  }
-  else
-    strcpy(i->name, "?");
-  i->index = index;
-  add_tail(&p->scan.temp_ifs, &i->n);
-  return i;
-}
-
-
 int
 krt_capable(rte *e)
 {
@@ -83,7 +52,7 @@ krt_capable(rte *e)
      || a->dest == RTD_UNREACHABLE
 #endif
 #ifdef RTF_BLACKHOLE
-     || a->dest == RTD_BLACKHOLE       /* FIXME Prohibited? */
+     || a->dest == RTD_BLACKHOLE
 #endif
      );
 }
@@ -96,6 +65,13 @@ krt_capable(rte *e)
           l = ROUNDUP(((struct sockaddr *)&(u))->sa_len);\
           memmove(body, &(u), l); body += l;}
 
+#define GETADDR(p, F) \
+  bzero(p, sizeof(*p));\
+  if ((addrs & (F)) && ((struct sockaddr *)body)->sa_len) {\
+    unsigned int l = ROUNDUP(((struct sockaddr *)body)->sa_len);\
+    memcpy(p, body, (l > sizeof(*p) ? sizeof(*p) : l));\
+    body += l;}
+
 static void
 krt_sock_send(int cmd, rte *e)
 {
@@ -108,7 +84,7 @@ krt_sock_send(int cmd, rte *e)
   char *body = (char *)msg.buf;
   sockaddr gate, mask, dst;
 
-  DBG("krt-sock: send %I/%d via %I", net->n.prefix, net->n.pxlen, a->gw);
+  DBG("krt-sock: send %I/%d via %I\n", net->n.prefix, net->n.pxlen, a->gw);
 
   fill_in_sockaddr(&dst, net->n.prefix, 0);
   fill_in_sockaddr(&mask, ipa_mkmask(net->n.pxlen), 0);
@@ -119,9 +95,9 @@ krt_sock_send(int cmd, rte *e)
   msg.rtm.rtm_type = cmd;
   msg.rtm.rtm_seq = msg_seq++;
   msg.rtm.rtm_addrs = RTA_DST;
-  msg.rtm.rtm_flags = RTF_UP;
+  msg.rtm.rtm_flags = RTF_UP | RTF_PROTO1;
 
-  if (net->n.pxlen == HOST_MASK)
+  if (net->n.pxlen == MAX_PREFIX_LENGTH)
   {
     msg.rtm.rtm_flags |= RTF_HOST;
   }
@@ -200,12 +176,12 @@ krt_sock_send(int cmd, rte *e)
   msg.rtm.rtm_msglen = l;
 
   if ((l = write(rt_sock, (char *)&msg, l)) < 0) {
-          log(L_ERR "KIF: error writting route to socket (%I/%d)", net->n.prefix, net->n.pxlen);
+    log(L_ERR "KIF: Error sending route %I/%d to kernel", net->n.prefix, net->n.pxlen);
   }
 }
 
 void
-krt_set_notify(struct krt_proto *p UNUSED, net *net UNUSED, rte *new, rte *old)
+krt_set_notify(struct krt_proto *p UNUSED, net *net, rte *new, rte *old)
 {
   if (old)
     {
@@ -258,68 +234,87 @@ krt_set_start(struct krt_proto *x, int first UNUSED)
     bug("krt-sock: sk_open failed");
 }
 
+#define SKIP(ARG...) do { DBG("KRT: Ignoring route - " ARG); return; } while(0)
+
 static void
 krt_read_rt(struct ks_msg *msg, struct krt_proto *p, int scan)
 {
-  sockaddr gate, mask, dst;
   rta a;
   rte *e;
   net *net;
+  sockaddr dst, gate, mask;
   ip_addr idst, igate, imask;
   void *body = (char *)msg->buf;
   int new = (msg->rtm.rtm_type == RTM_ADD);
   int src;
+  char *errmsg = "KRT: Invalid route received";
   int flags = msg->rtm.rtm_flags;
   int addrs = msg->rtm.rtm_addrs;
-  int masklen = -1;
-
-  if (!(flags & RTF_UP))
-  {
-    DBG("Down.\n");
-    return;
-  }
 
-  if (flags & RTF_HOST)
-    masklen = HOST_MASK;
+  if (!(flags & RTF_UP) && scan)
+    SKIP("not up in scan\n");
 
-  if(!CHECK_FAMILY(body)) return;
+  if (!(flags & RTF_DONE) && !scan)
+    SKIP("not done in async\n");
 
-  if(msg->rtm.rtm_flags & RTF_LLINFO) return;  /* ARPs etc. */
+  if (flags & RTF_LLINFO)
+    SKIP("link-local\n");
 
-#define GETADDR(p, F) \
-  bzero(p, sizeof(*p));\
-  if ((addrs & (F)) && ((struct sockaddr *)body)->sa_len) {\
-    unsigned int l = ROUNDUP(((struct sockaddr *)body)->sa_len);\
-    memcpy(p, body, (l > sizeof(*p) ? sizeof(*p) : l));\
-    body += l;}
+  GETADDR(&dst, RTA_DST);
+  GETADDR(&gate, RTA_GATEWAY);
+  GETADDR(&mask, RTA_NETMASK);
 
-  GETADDR (&dst, RTA_DST);
-  GETADDR (&gate, RTA_GATEWAY);
-  GETADDR (&mask, RTA_NETMASK);
+  if (sa_family_check(&dst))
+    get_sockaddr(&dst, &idst, NULL, 0);
+  else
+    SKIP("invalid DST");
 
-  idst = IPA_NONE;
-  igate = IPA_NONE;
-  imask = IPA_NONE;
+  /* We will check later whether we have valid gateway addr */
+  if (sa_family_check(&gate))
+    get_sockaddr(&gate, &igate, NULL, 0);
+  else
+    igate = IPA_NONE;
 
-  get_sockaddr(&dst, &idst, NULL, 0);
-  if(CHECK_FAMILY(&gate)) get_sockaddr(&gate, &igate, NULL, 0);
+  /* We do not test family for RTA_NETMASK, because BSD sends us
+     some strange values, but interpreting them as IPv4/IPv6 works */
   get_sockaddr(&mask, &imask, NULL, 0);
 
-  if (masklen < 0) masklen = ipa_mklen(imask);
+  int c = ipa_classify_net(idst);
+  if ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK))
+    SKIP("strange class/scope\n");
 
-  if (flags & (RTF_DYNAMIC | RTF_MODIFIED))
-  {
-    log(L_WARN "krt: Ignoring redirect to %I/%d via %I", idst, masklen, igate);
-    return;
-  }
+  int pxlen = (flags & RTF_HOST) ? MAX_PREFIX_LENGTH : ipa_mklen(imask);
+  if (pxlen < 0)
+    { log(L_ERR "%s (%I) - netmask %I", errmsg, idst, imask); return; }
 
-  if (masklen < 0)
-  {
-    log(L_WARN "krt: Got invalid route from kernel!");
-    return;
-  }
+  if ((flags & RTF_GATEWAY) && ipa_zero(igate))
+    { log(L_ERR "%s (%I/%d) - missing gateway", errmsg, idst, pxlen); return; }
+
+  u32 self_mask = RTF_PROTO1;
+  u32 alien_mask = RTF_STATIC | RTF_PROTO1;
+
+#ifdef RTF_PROTO2
+  alien_mask |= RTF_PROTO2;
+#endif
 
-  net = net_get(p->p.table, idst, masklen);
+#ifdef RTF_PROTO3
+  alien_mask |= RTF_PROTO3;
+#endif
+
+  if (flags & (RTF_DYNAMIC | RTF_MODIFIED))
+    src = KRT_SRC_REDIRECT;
+  else if (flags & self_mask)
+    {
+      if (!scan)
+       SKIP("echo\n");
+      src = KRT_SRC_BIRD;
+    }
+  else if (flags & alien_mask)
+    src = KRT_SRC_ALIEN;
+  else
+    src = KRT_SRC_KERNEL;
+
+  net = net_get(p->p.table, idst, pxlen);
 
   bzero(&a, sizeof(a));
 
@@ -333,56 +328,56 @@ krt_read_rt(struct ks_msg *msg, struct krt_proto *p, int scan)
   a.iface = NULL;
   a.eattrs = NULL;
 
-  a.dest = RTD_NONE;
-
-  if (flags & RTF_GATEWAY)
-  {
-    neighbor *ng = neigh_find(&p->p, &igate, 0);
-    if (ng && ng->scope)
-      a.iface = ng->iface;
-    else
-      {
-       log(L_WARN "Kernel told us to use non-neighbor %I for %I/%d", igate, net->n.prefix, net->n.pxlen);
-       return;
-      }
-
-    a.dest = RTD_ROUTER;
-    a.gw = igate;
-  }
-  else
-  {
-    a.dest = RTD_DEVICE;
-    a.gw = IPA_NONE;
-    a.iface = krt_temp_iface_index(p, msg->rtm.rtm_index);
-  }
+  /* reject/blackhole routes have also set RTF_GATEWAY,
+     we wil check them first. */
 
 #ifdef RTF_REJECT
   if(flags & RTF_REJECT) {
     a.dest = RTD_UNREACHABLE;
-    a.gw = IPA_NONE;
+    goto done;
   }
 #endif
 
 #ifdef RTF_BLACKHOLE
   if(flags & RTF_BLACKHOLE) {
     a.dest = RTD_BLACKHOLE;
-    a.gw = IPA_NONE;
+    goto done;
   }
 #endif
 
-  if (a.dest == RTD_NONE)
+  a.iface = if_find_by_index(msg->rtm.rtm_index);
+  if (!a.iface)
+    {
+      log(L_ERR "KRT: Received route %I/%d with unknown ifindex %u",
+         net->n.prefix, net->n.pxlen, msg->rtm.rtm_index);
+      return;
+    }
+
+  if (flags & RTF_GATEWAY)
   {
-    log(L_WARN "Kernel reporting unknown route type to %I/%d", net->n.prefix, net->n.pxlen);
-    return;
-  }
+    neighbor *ng;
+    a.dest = RTD_ROUTER;
+    a.gw = igate;
 
-  src = KRT_SRC_UNKNOWN;       /* FIXME */
+    ng = neigh_find2(&p->p, &a.gw, a.iface, 0);
+    if (!ng || (ng->scope == SCOPE_HOST))
+      {
+       log(L_ERR "KRT: Received route %I/%d with strange next-hop %I",
+           net->n.prefix, net->n.pxlen, a.gw);
+       return;
+      }
+  }
+  else
+    a.dest = RTD_DEVICE;
 
+ done:
   e = rte_get_temp(&a);
   e->net = net;
   e->u.krt.src = src;
-  //e->u.krt.proto = i->rtm_protocol;
-  //e->u.krt.type = i->rtm_type;
+
+  /* These are probably too Linux-specific */
+  e->u.krt.proto = 0;
+  e->u.krt.type = 0;
   e->u.krt.metric = 0;
 
   if (scan)
@@ -471,6 +466,10 @@ krt_read_addr(struct ks_msg *msg)
   int scope, masklen = -1;
   int new = (ifam->ifam_type == RTM_NEWADDR);
 
+  /* Strange messages with zero (invalid) ifindex appear on OpenBSD */
+  if (ifam->ifam_index == 0)
+    return;
+
   if(!(iface = if_find_by_index(ifam->ifam_index)))
   {
     log(L_ERR "KIF: Received address message for unknown interface %d", ifam->ifam_index);
@@ -486,7 +485,9 @@ krt_read_addr(struct ks_msg *msg)
   GETADDR (&null, RTA_AUTHOR);
   GETADDR (&brd, RTA_BRD);
 
-  if(!CHECK_FAMILY(&addr)) return; /* Some other family address */
+  /* Some other family address */
+  if (!sa_family_check(&addr))
+    return;
 
   get_sockaddr(&addr, &iaddr, NULL, 0);
   get_sockaddr(&mask, &imask, NULL, 0);
@@ -593,27 +594,27 @@ krt_sysctl_scan(struct proto *p, pool *pool, byte **buf, size_t *bl, int cmd)
   mib[4] = cmd;
   mib[5] = 0;
 
-  ifsysctl(mib, 6 , NULL , &needed, NULL, 0) < 0)
+  if (sysctl(mib, 6 , NULL , &needed, NULL, 0) < 0)
   {
     die("RT scan...");
   }
 
   obl = *bl;
 
-  while(needed > *bl) *bl *= 2;
-  while(needed < (*bl/2)) *bl /= 2;
+  while (needed > *bl) *bl *= 2;
+  while (needed < (*bl/2)) *bl /= 2;
 
-  if(obl!=*bl) || !*buf)
+  if ((obl!=*bl) || !*buf)
   {
-    if(*buf) mb_free(*buf);
-    if( (*buf = mb_alloc(pool, *bl)) == NULL ) die("RT scan buf alloc");
+    if (*buf) mb_free(*buf);
+    if ((*buf = mb_alloc(pool, *bl)) == NULL) die("RT scan buf alloc");
   }
 
   on = needed;
 
-  ifsysctl(mib, 6 , *buf, &needed, NULL, 0) < 0)
+  if (sysctl(mib, 6 , *buf, &needed, NULL, 0) < 0)
   {
-    if(on != needed) return;   /* The buffer size changed since last sysctl */
+    if (on != needed) return;  /* The buffer size changed since last sysctl */
     die("RT scan 2");
   }
 
@@ -624,22 +625,23 @@ krt_sysctl_scan(struct proto *p, pool *pool, byte **buf, size_t *bl, int cmd)
   }
 }
 
+static byte *krt_buffer = NULL;
+static byte *kif_buffer = NULL;
+static size_t krt_buflen = 32768;
+static size_t kif_buflen = 4096;
+
 void
 krt_scan_fire(struct krt_proto *p)
 {
-  static byte *buf = NULL;
-  static size_t bl = 32768;
-  krt_sysctl_scan((struct proto *)p , p->krt_pool, &buf, &bl, NET_RT_DUMP);
+  krt_sysctl_scan((struct proto *)p, p->krt_pool, &krt_buffer, &krt_buflen, NET_RT_DUMP);
 }
 
 void
 krt_if_scan(struct kif_proto *p)
 {
-  static byte *buf = NULL;
-  static size_t bl = 4096;
   struct proto *P = (struct proto *)p;
   if_start_update();
-  krt_sysctl_scan(P, P->pool, &buf, &bl, NET_RT_IFLIST);
+  krt_sysctl_scan(P, P->pool, &kif_buffer, &kif_buflen, NET_RT_IFLIST);
   if_end_update();
 }
 
@@ -652,7 +654,9 @@ krt_set_construct(struct krt_config *c UNUSED)
 void
 krt_set_shutdown(struct krt_proto *x UNUSED, int last UNUSED)
 {
-} 
+  mb_free(krt_buffer);
+  krt_buffer = NULL;
+}
 
 void
 krt_if_io_init(void)
@@ -672,5 +676,7 @@ krt_if_start(struct kif_proto *p UNUSED)
 void
 krt_if_shutdown(struct kif_proto *p UNUSED)
 {
+  mb_free(kif_buffer);
+  kif_buffer = NULL;
 }
 
index f3aefeb4b58f69996f7b8cd03a01d343168085d0..66985abfc78e9ed292fbba70a739fbff419631da 100644 (file)
@@ -9,7 +9,7 @@
 #define IPV6
 
 #define CONFIG_AUTO_ROUTES
-#undef CONFIG_SELF_CONSCIOUS
+#define CONFIG_SELF_CONSCIOUS
 #undef CONFIG_MULTIPLE_TABLES
 
 #undef CONFIG_UNIX_IFACE
index 72b24720bfb209c9f0994e61c450730fbe98086c..acd1b58b722eb323d55ff327f022d7f0ece72ee7 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #define CONFIG_AUTO_ROUTES
-#undef CONFIG_SELF_CONSCIOUS
+#define CONFIG_SELF_CONSCIOUS
 #undef CONFIG_MULTIPLE_TABLES
 
 #undef CONFIG_UNIX_IFACE
index f45fe1596f394000472a070b4b62ed97706c1f97..b59b32f38da78a2652abbe930a3f2dc1665e9340 100644 (file)
@@ -52,7 +52,6 @@ struct nl_sock
 static struct nl_sock nl_scan = {.fd = -1};    /* Netlink socket for synchronous scan */
 static struct nl_sock nl_req  = {.fd = -1};    /* Netlink socket for requests */
 
-
 static void
 nl_open_sock(struct nl_sock *nl)
 {
@@ -555,23 +554,7 @@ krt_set_notify(struct krt_proto *p, net *n UNUSED, rte *new, rte *old)
     nl_send_route(p, new, 1);
 }
 
-static struct iface *
-krt_temp_iface(struct krt_proto *p, unsigned index)
-{
-  struct iface *i, *j;
-
-  WALK_LIST(i, p->scan.temp_ifs)
-    if (i->index == index)
-      return i;
-  i = mb_allocz(p->p.pool, sizeof(struct iface));
-  if (j = if_find_by_index(index))
-    strcpy(i->name, j->name);
-  else
-    strcpy(i->name, "?");
-  i->index = index;
-  add_tail(&p->scan.temp_ifs, &i->n);
-  return i;
-}
+#define SKIP(ARG...) do { DBG("KRT: Ignoring route - " ARG); return; } while(0)
 
 static void
 nl_parse_route(struct nlmsghdr *h, int scan)
@@ -599,31 +582,7 @@ nl_parse_route(struct nlmsghdr *h, int scan)
 #endif
       (a[RTA_GATEWAY] && RTA_PAYLOAD(a[RTA_GATEWAY]) != sizeof(ip_addr)))
     {
-      log(L_ERR "nl_parse_route: Malformed message received");
-      return;
-    }
-
-  p = nl_table_map[i->rtm_table];      /* Do we know this table? */
-  if (!p)
-    return;
-
-#ifdef IPV6
-  if (a[RTA_IIF])
-    {
-      DBG("KRT: Ignoring route with IIF set\n");
-      return;
-    }
-#else
-  if (i->rtm_tos != 0)                 /* We don't support TOS */
-    {
-      DBG("KRT: Ignoring route with TOS %02x\n", i->rtm_tos);
-      return;
-    }
-#endif
-
-  if (scan && !new)
-    {
-      DBG("KRT: Ignoring route deletion\n");
+      log(L_ERR "KRT: Malformed message received");
       return;
     }
 
@@ -634,33 +593,57 @@ nl_parse_route(struct nlmsghdr *h, int scan)
     }
   else
     dst = IPA_NONE;
+
   if (a[RTA_OIF])
     memcpy(&oif, RTA_DATA(a[RTA_OIF]), sizeof(oif));
   else
     oif = ~0;
 
-  DBG("Got %I/%d, type=%d, oif=%d, table=%d, prid=%d, proto=%s\n", dst, i->rtm_dst_len, i->rtm_type, oif, i->rtm_table, i->rtm_protocol, p->p.name);
+  DBG("KRT: Got %I/%d, type=%d, oif=%d, table=%d, prid=%d, proto=%s\n", dst, i->rtm_dst_len, i->rtm_type, oif, i->rtm_table, i->rtm_protocol, p->p.name);
+
+  p = nl_table_map[i->rtm_table];      /* Do we know this table? */
+  if (!p)
+    SKIP("unknown table %d", i->rtm_table);
+
+#ifdef IPV6
+  if (a[RTA_IIF])
+    SKIP("IIF set\n");
+#else
+  if (i->rtm_tos != 0)                 /* We don't support TOS */
+    SKIP("TOS %02x\n", i->rtm_tos);
+#endif
+
+  if (scan && !new)
+    SKIP("RTM_DELROUTE in scan\n");
+
+  int c = ipa_classify_net(dst);
+  if ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK))
+    SKIP("strange class/scope\n");
+
+  // ignore rtm_scope, it is not a real scope
+  // if (i->rtm_scope != RT_SCOPE_UNIVERSE)
+  //   SKIP("scope %u\n", i->rtm_scope);
 
   switch (i->rtm_protocol)
     {
+    case RTPROT_UNSPEC:
+      SKIP("proto unspec\n");
+
     case RTPROT_REDIRECT:
       src = KRT_SRC_REDIRECT;
       break;
+
     case RTPROT_KERNEL:
-      DBG("Route originated in kernel, ignoring\n");
+      src = KRT_SRC_KERNEL;
       return;
+
     case RTPROT_BIRD:
-#ifdef IPV6
-    case RTPROT_BOOT:
-      /* Current Linux kernels don't remember rtm_protocol for IPv6 routes and supply RTPROT_BOOT instead */
-#endif
       if (!scan)
-       {
-         DBG("Echo of our own route, ignoring\n");
-         return;
-       }
+       SKIP("echo\n");
       src = KRT_SRC_BIRD;
       break;
+
+    case RTPROT_BOOT:
     default:
       src = KRT_SRC_ALIEN;
     }
@@ -679,52 +662,48 @@ nl_parse_route(struct nlmsghdr *h, int scan)
   switch (i->rtm_type)
     {
     case RTN_UNICAST:
-      if (oif == ~0U)
+      ra.iface = if_find_by_index(oif);
+      if (!ra.iface)
        {
-         log(L_ERR "KRT: Mysterious route with no OIF (%I/%d)", net->n.prefix, net->n.pxlen);
+         log(L_ERR "KRT: Received route %I/%d with unknown ifindex %u",
+             net->n.prefix, net->n.pxlen, oif);
          return;
        }
+
       if (a[RTA_GATEWAY])
        {
-         struct iface *ifa = if_find_by_index(oif);
          neighbor *ng;
          ra.dest = RTD_ROUTER;
          memcpy(&ra.gw, RTA_DATA(a[RTA_GATEWAY]), sizeof(ra.gw));
          ipa_ntoh(ra.gw);
 
-         if (i->rtm_flags & RTNH_F_ONLINK)
-           {
-             /* route with 'onlink' attribute */
-             ra.iface = if_find_by_index(oif);
-             if (ra.iface == NULL)
-               {
-                 log(L_WARN "Kernel told us to use unknown interface %u for %I/%d",
-                     oif, net->n.prefix, net->n.pxlen);
-                 return;
-               }
-           }
-         else
+         ng = neigh_find2(&p->p, &ra.gw, ra.iface,
+                          (i->rtm_flags & RTNH_F_ONLINK) ? NEF_ONLINK : 0);
+         if (!ng || (ng->scope == SCOPE_HOST))
            {
-             ng = neigh_find2(&p->p, &ra.gw, ifa, 0);
-             if (ng && ng->scope)
-               {
-                 if (ng->iface != ifa)
-                   log(L_WARN "KRT: Route with unexpected iface for %I/%d", net->n.prefix, net->n.pxlen);
-                 ra.iface = ng->iface;
-               }
-             else
-               {
-                 log(L_WARN "Kernel told us to use non-neighbor %I for %I/%d", ra.gw, net->n.prefix, net->n.pxlen);
-                 return;
-               }
-
+             log(L_ERR "KRT: Received route %I/%d with strange next-hop %I",
+                 net->n.prefix, net->n.pxlen, ra.gw);
+             return;
            }
        }
       else
        {
          ra.dest = RTD_DEVICE;
-         ra.iface = krt_temp_iface(p, oif);
+
+         /*
+          * In Linux IPv6, 'native' device routes have proto
+          * RTPROT_BOOT and not RTPROT_KERNEL (which they have in
+          * IPv4 and which is expected). We cannot distinguish
+          * 'native' and user defined device routes, so we ignore all
+          * such device routes and for consistency, we have the same
+          * behavior in IPv4. Anyway, users should use RTPROT_STATIC
+          * for their 'alien' routes.
+          */
+
+         if (i->rtm_protocol == RTPROT_BOOT)
+           src = KRT_SRC_KERNEL;
        }
+
       break;
     case RTN_BLACKHOLE:
       ra.dest = RTD_BLACKHOLE;
@@ -737,13 +716,7 @@ nl_parse_route(struct nlmsghdr *h, int scan)
       break;
     /* FIXME: What about RTN_THROW? */
     default:
-      DBG("KRT: Ignoring route with type=%d\n", i->rtm_type);
-      return;
-    }
-
-  if (i->rtm_scope != RT_SCOPE_UNIVERSE)
-    {
-      DBG("KRT: Ignoring route with scope=%d\n", i->rtm_scope);
+      SKIP("type %d\n", i->rtm_type);
       return;
     }
 
index 915baf449915a4c0b4dd7d9f82b157ace03d6aab..02d59abb98aafee2fd22e1546e1e919066a6caf6 100644 (file)
@@ -663,7 +663,6 @@ get_sockaddr(struct sockaddr_in *sa, ip_addr *a, unsigned *port, int check)
 static char *
 sk_set_ttl_int(sock *s)
 {
-  int one = 1;
 #ifdef IPV6
   if (setsockopt(s->fd, SOL_IPV6, IPV6_UNICAST_HOPS, &s->ttl, sizeof(s->ttl)) < 0)
     return "IPV6_UNICAST_HOPS";
@@ -671,6 +670,7 @@ sk_set_ttl_int(sock *s)
   if (setsockopt(s->fd, SOL_IP, IP_TTL, &s->ttl, sizeof(s->ttl)) < 0)
     return "IP_TTL";
 #ifdef CONFIG_UNIX_DONTROUTE
+  int one = 1;
   if (s->ttl == 1 && setsockopt(s->fd, SOL_SOCKET, SO_DONTROUTE, &one, sizeof(one)) < 0)
     return "SO_DONTROUTE";
 #endif 
index 6d94cada2a810c2ed03fac98dca02ed603557415..47b96217d00df7354a83ffae267e49194395c602 100644 (file)
@@ -558,32 +558,30 @@ krt_got_route(struct krt_proto *p, rte *e)
   rte *old;
   net *net = e->net;
   int verdict;
-#ifdef KRT_ALLOW_LEARN
-  int src = e->u.krt.src;
-#endif
 
-#ifdef CONFIG_AUTO_ROUTES
-  if (e->attrs->dest == RTD_DEVICE)
+#ifdef KRT_ALLOW_LEARN
+  switch (e->u.krt.src)
     {
-      /* It's a device route. Probably a kernel-generated one. */
+    case KRT_SRC_KERNEL:
       verdict = KRF_IGNORE;
       goto sentenced;
-    }
-#endif
 
-#ifdef KRT_ALLOW_LEARN
-  if (src == KRT_SRC_ALIEN)
-    {
+    case KRT_SRC_REDIRECT:
+      verdict = KRF_DELETE;
+      goto sentenced;
+
+    case  KRT_SRC_ALIEN:
       if (KRT_CF->learn)
        krt_learn_scan(p, e);
       else
        {
-         krt_trace_in_rl(&rl_alien_ignored, p, e, "alien route, ignored");
+         krt_trace_in_rl(&rl_alien_ignored, p, e, "[alien] ignored");
          rte_free(e);
        }
       return;
     }
 #endif
+  /* The rest is for KRT_SRC_BIRD (or KRT_SRC_UNKNOWN) */
 
   if (net->n.flags & KRF_VERDICT_MASK)
     {
@@ -605,7 +603,7 @@ krt_got_route(struct krt_proto *p, rte *e)
   else
     verdict = KRF_DELETE;
 
-sentenced:
+ sentenced:
   krt_trace_in(p, e, ((char *[]) { "?", "seen", "will be updated", "will be removed", "ignored" }) [verdict]);
   net->n.flags = (net->n.flags & ~KRF_VERDICT_MASK) | verdict;
   if (verdict == KRF_UPDATE || verdict == KRF_DELETE)
@@ -680,19 +678,24 @@ krt_prune(struct krt_proto *p)
 }
 
 void
-krt_got_route_async(struct krt_proto *p, rte *e, int new UNUSED)
+krt_got_route_async(struct krt_proto *p, rte *e, int new)
 {
   net *net = e->net;
-  int src = e->u.krt.src;
 
-  switch (src)
+  switch (e->u.krt.src)
     {
     case KRT_SRC_BIRD:
       ASSERT(0);                       /* Should be filtered by the back end */
+
     case KRT_SRC_REDIRECT:
-      DBG("It's a redirect, kill him! Kill! Kill!\n");
-      krt_set_notify(p, net, NULL, e);
+      if (new)
+       {
+         krt_trace_in(p, e, "[redirect] deleting");
+         krt_set_notify(p, net, NULL, e);
+       }
+      /* If !new, it is probably echo of our deletion */
       break;
+
 #ifdef KRT_ALLOW_LEARN
     case KRT_SRC_ALIEN:
       if (KRT_CF->learn)
@@ -878,7 +881,6 @@ krt_init(struct proto_config *c)
 
   p->p.accept_ra_types = RA_OPTIMAL;
   p->p.rt_notify = krt_notify;
-  p->p.min_scope = SCOPE_HOST;
   return &p->p;
 }
 
index 607e6993954a9e8e79ef13a923445795a904cdb1..1d9e1448074f0fd2ec45943c0291cef22afd4dd6 100644 (file)
@@ -83,6 +83,7 @@ void krt_got_route_async(struct krt_proto *p, struct rte *e, int new);
 #define KRT_SRC_BIRD    0      /* Our route (not passed in async mode) */
 #define KRT_SRC_REDIRECT 1     /* Redirect route, delete it */
 #define KRT_SRC_ALIEN   2      /* Route installed by someone else */
+#define KRT_SRC_KERNEL  3      /* Kernel routes, are ignored by krt syncer */
 
 extern struct protocol proto_unix_iface;
 
index 1a461ee1d34086de83e40abfe76dfe5a655d4781..0b179e001f14388753c5d6e15b23e09a44fd5628 100644 (file)
@@ -9,6 +9,8 @@
 #ifndef _BIRD_UNIX_H_
 #define _BIRD_UNIX_H_
 
+#include <sys/socket.h>
+
 struct pool;
 
 /* main.c */
@@ -29,10 +31,12 @@ volatile int async_shutdown_flag;
 #define BIRD_PF PF_INET6
 #define BIRD_AF AF_INET6
 typedef struct sockaddr_in6 sockaddr;
+static inline int sa_family_check(sockaddr *sa) { return sa->sin6_family == AF_INET6; }
 #else
 #define BIRD_PF PF_INET
 #define BIRD_AF AF_INET
 typedef struct sockaddr_in sockaddr;
+static inline int sa_family_check(sockaddr *sa) { return sa->sin_family == AF_INET; }
 #endif
 
 #ifndef SUN_LEN