]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Temporary OSPFv3 development commit (changing multicast support).
authorOndrej Zajicek <santiago@crfreenet.org>
Fri, 4 Sep 2009 09:06:51 +0000 (11:06 +0200)
committerOndrej Zajicek <santiago@crfreenet.org>
Fri, 4 Sep 2009 09:06:51 +0000 (11:06 +0200)
18 files changed:
lib/socket.h
proto/ospf/dbdes.c
proto/ospf/hello.c
proto/ospf/iface.c
proto/ospf/lsack.c
proto/ospf/lsalib.c
proto/ospf/lsreq.c
proto/ospf/lsupd.c
proto/ospf/neighbor.c
proto/ospf/ospf.h
proto/ospf/packet.c
proto/ospf/packet.h
proto/ospf/rt.c
proto/ospf/topology.c
proto/rip/rip.c
sysdep/bsd/sysio.h
sysdep/linux/sysio.h
sysdep/unix/io.c

index f1922607398f48bf0d656727e86e9c7bad75534e..0ab7d951698691c0ba846144cbf48a82d5d0d974 100644 (file)
@@ -50,7 +50,15 @@ int sk_send_to(sock *, unsigned len, ip_addr to, unsigned port); /* sk_send to g
 void sk_reallocate(sock *);            /* Free and allocate tbuf & rbuf */
 void sk_dump_all(void);
 int sk_set_ttl(sock *s, int ttl);      /* Set TTL for given socket */
-int sk_set_md5_auth(sock *s, ip_addr a, char *passwd); /* Add or remove security associations for given passive socket */
+
+/* Add or remove security associations for given passive socket */
+int sk_set_md5_auth(sock *s, ip_addr a, char *passwd);
+
+/* Prepare UDP or IP socket to multicasting. s->iface and s->ttl must be set */
+int sk_setup_multicast(sock *s);       
+int sk_join_group(sock *s, ip_addr maddr);
+int sk_leave_group(sock *s, ip_addr maddr);
+
 
 static inline int
 sk_send_buffer_empty(sock *sk)
@@ -72,9 +80,7 @@ sk_send_buffer_empty(sock *sk)
 #define SK_TCP_ACTIVE  1          /* ?  ?  *  *  -  ?   -      */
 #define SK_TCP         2
 #define SK_UDP         3          /* ?  ?  -  -  -  ?   ?      */
-#define SK_UDP_MC       4          /* ?  ?  *  *  *  *   -     */
 #define SK_IP          5          /* ?  -  -  *  -  ?   ?      */
-#define SK_IP_MC       6          /* ?  -  *  *  *  *   -      */
 #define SK_MAGIC       7          /* Internal use by sysdep code */
 #define SK_UNIX_PASSIVE        8
 #define SK_UNIX                9
index 9be8e61f2d59d97eb00a03a2ad1b4e385d9aa322..c9d318c65ec10be2885eea5ce6d028a160f8496d 100644 (file)
@@ -93,7 +93,7 @@ ospf_dbdes_send(struct ospf_neighbor *n, int next)
   {
   case NEIGHBOR_EXSTART:       /* Send empty packets */
     n->myimms.bit.i = 1;
-    pkt = (struct ospf_dbdes_packet *) (ifa->ip_sk->tbuf);
+    pkt = (struct ospf_dbdes_packet *) (ifa->sk->tbuf);
     op = (struct ospf_packet *) pkt;
     ospf_pkt_fill_hdr(ifa, pkt, DBDES_P);
     pkt->iface_mtu = htons(ifa->iface->mtu);
@@ -104,7 +104,7 @@ ospf_dbdes_send(struct ospf_neighbor *n, int next)
     op->length = htons(length);
 
     OSPF_PACKET(ospf_dump_dbdes, pkt, "DBDES packet sent to %I via %s", n->ip, ifa->iface->name);
-    ospf_send_to(ifa->ip_sk, n->ip, ifa);
+    ospf_send_to(ifa, n->ip);
     break;
 
   case NEIGHBOR_EXCHANGE:
@@ -185,11 +185,11 @@ ospf_dbdes_send(struct ospf_neighbor *n, int next)
     }
 
     /* Copy last sent packet again */
-    memcpy(ifa->ip_sk->tbuf, n->ldbdes, length);
+    memcpy(ifa->sk->tbuf, n->ldbdes, length);
 
-    OSPF_PACKET(ospf_dump_dbdes, (struct ospf_dbdes_packet *) ifa->ip_sk->tbuf,
+    OSPF_PACKET(ospf_dump_dbdes, (struct ospf_dbdes_packet *) ifa->sk->tbuf,
                "DBDES packet sent to %I via %s", n->ip, ifa->iface->name);
-    ospf_send_to(ifa->ip_sk, n->ip, n->ifa);
+    ospf_send_to(ifa, n->ip);
 
     if(n->myimms.bit.ms) tm_start(n->rxmt_timer, n->ifa->rxmtint);             /* Restart timer */
 
index cce256fcbadff5e8d3e3b84b8458f85071f92d36..783761fe1dfc8ae329e9d6706a41ec7215916fdd 100644 (file)
@@ -56,7 +56,7 @@ ospf_hello_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
       (ifa->type == OSPF_IT_VLINK ? "vlink-" : ""), ifa->iface->name);
 
 #ifdef OSPFv2
-  mask = ps->netmask;
+  ip_addr mask = ps->netmask;
   ipa_ntoh(mask);
   if (ifa->type != OSPF_IT_VLINK)
     {
@@ -198,7 +198,7 @@ ospf_hello_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
   if (n->state >= NEIGHBOR_2WAY)
   {
 #ifdef OSPFv2
-    u32 rid = n->ip;
+    u32 rid = ipa_to_u32(n->ip);
 #else /* OSPFv3 */
     u32 rid = p->cf->global->router_id;
 #endif
@@ -266,20 +266,12 @@ ospf_hello_send(timer *timer, int poll, struct ospf_neighbor *dirn)
   p = (struct proto *) (ifa->oa->po);
   DBG("%s: Hello/Poll timer fired on interface %s.\n",
       p->name, ifa->iface->name);
-  /* Now we should send a hello packet */
-  /* First a common packet header */
-  if ((ifa->type == OSPF_IT_NBMA) || (ifa->type == OSPF_IT_VLINK))
-  {
-    pkt = (struct ospf_hello_packet *) (ifa->ip_sk->tbuf);
-  }
-  else
-  {
-    pkt = (struct ospf_hello_packet *) (ifa->hello_sk->tbuf);
-  }
 
-  /* Now fill ospf_hello header */
+  /* Now we should send a hello packet */
+  pkt = (struct ospf_hello_packet *) (ifa->sk->tbuf);
   op = (struct ospf_packet *) pkt;
 
+  /* Now fill ospf_hello header */
   ospf_pkt_fill_hdr(ifa, pkt, HELLO_P);
 
 #ifdef OSPFv2
@@ -332,7 +324,7 @@ ospf_hello_send(timer *timer, int poll, struct ospf_neighbor *dirn)
     case OSPF_IT_NBMA:
       if (timer == NULL)               /* Response to received hello */
       {
-        ospf_send_to(ifa->ip_sk, dirn->ip, ifa);
+        ospf_send_to(ifa, dirn->ip);
       }
       else
       {
@@ -357,7 +349,7 @@ ospf_hello_send(timer *timer, int poll, struct ospf_neighbor *dirn)
           if ((poll == 1) && (send))
           {
             if (toall || (meeli && nb->eligible))
-              ospf_send_to(ifa->ip_sk, nb->ip, ifa);
+              ospf_send_to(ifa, nb->ip);
           }
         }
         if (poll == 0)
@@ -366,16 +358,16 @@ ospf_hello_send(timer *timer, int poll, struct ospf_neighbor *dirn)
           {
             if (toall || (n1->rid == ifa->drid) || (n1->rid == ifa->bdrid) ||
                 (meeli && (n1->priority > 0)))
-              ospf_send_to(ifa->ip_sk, n1->ip, ifa);
+              ospf_send_to(ifa, n1->ip);
           }
         }
       }
       break;
     case OSPF_IT_VLINK:
-      ospf_send_to(ifa->ip_sk, ifa->vip, ifa);
+      ospf_send_to(ifa, ifa->vip);
       break;
     default:
-      ospf_send_to(ifa->hello_sk, IPA_NONE, ifa);
+      ospf_send_to(ifa, AllSPFRouters);
   }
 
   OSPF_TRACE(D_PACKETS, "HELLO packet sent via %s%s",
index 439a29c55486437371175bc7cc33a045cd233f6a..fc1cf2a247dff0ec1ebb3c1382ec42a866ad3845 100644 (file)
@@ -59,7 +59,7 @@ rxbufsize(struct ospf_iface *ifa)
 }
 
 static sock *
-ospf_open_ip_socket(struct ospf_iface *ifa)
+ospf_open_socket(struct ospf_iface *ifa, int mc)
 {
   sock *ipsk;
   struct proto *p = &ifa->oa->po->proto;
@@ -69,7 +69,8 @@ ospf_open_ip_socket(struct ospf_iface *ifa)
   ipsk->dport = OSPF_PROTO;
 
 #ifdef OSPFv2
-  ipsk->saddr = ifa->iface->addr->ip;
+  //  ipsk->saddr = ifa->iface->addr->ip;
+  ipsk->saddr = IPA_NONE;
 #else /* OSPFv3 */
   ipsk->saddr = ifa->lladdr;
 #endif
@@ -86,12 +87,22 @@ ospf_open_ip_socket(struct ospf_iface *ifa)
   ipsk->tbsize = ifa->iface->mtu;
   ipsk->data = (void *) ifa;
   if (sk_open(ipsk) != 0)
+    goto err;
+
+  if (mc)
   {
-    DBG("%s: SK_OPEN: ip open failed.\n", p->name);
-    return (NULL);
+    if (sk_setup_multicast(ipsk) < 0)
+      goto err;
+
+    if (sk_join_group(ipsk, AllSPFRouters) < 0)
+      goto err;
   }
-  DBG("%s: SK_OPEN: ip opened.\n", p->name);
-  return (ipsk);
+
+  return ipsk;
+
+ err:
+  rfree(ipsk);
+  return NULL;
 }
 
 
@@ -122,7 +133,7 @@ ospf_iface_chstate(struct ospf_iface *ifa, u8 state)
                 ifa->vid, ospf_is[oldstate], ospf_is[state]);
       if (state == OSPF_IS_PTP)
       {
-        ifa->ip_sk = ospf_open_ip_socket(ifa);
+        ifa->sk = ospf_open_socket(ifa, 0);
       }
     }
     else
@@ -132,43 +143,17 @@ ospf_iface_chstate(struct ospf_iface *ifa, u8 state)
                 ifa->iface->name, ospf_is[oldstate], ospf_is[state]);
       if (ifa->iface->flags & IF_MULTICAST)
       {
-       if ((state == OSPF_IS_BACKUP) || (state == OSPF_IS_DR))
+       if ((ifa->type != OSPF_IT_NBMA) && (ifa->ioprob == OSPF_I_OK) &&
+           ((state == OSPF_IS_BACKUP) || (state == OSPF_IS_DR)))
        {
-         if ((ifa->dr_sk == NULL) && (ifa->type != OSPF_IT_NBMA))
-         {
-           DBG("%s: Adding new multicast socket for (B)DR\n", p->name);
-           ifa->dr_sk = sk_new(p->pool);
-           ifa->dr_sk->type = SK_IP_MC;
-           ifa->dr_sk->sport = 0;
-           ifa->dr_sk->dport = OSPF_PROTO;
-
-#ifdef OSPFv2
-           ifa->dr_sk->saddr = AllDRouters;
-#else /* OSPFv3 */
-           // ifa->dr_sk->saddr = AllDRouters;
-           ifa->dr_sk->saddr = ifa->lladdr;
-#endif
-
-           ifa->dr_sk->daddr = AllDRouters;
-           ifa->dr_sk->tos = IP_PREC_INTERNET_CONTROL;
-           ifa->dr_sk->ttl = 1;
-           ifa->dr_sk->rx_hook = ospf_rx_hook;
-           ifa->dr_sk->tx_hook = ospf_tx_hook;
-           ifa->dr_sk->err_hook = ospf_err_hook;
-           ifa->dr_sk->iface = ifa->iface;
-           ifa->dr_sk->rbsize = rxbufsize(ifa);
-           ifa->dr_sk->tbsize = ifa->iface->mtu;
-           ifa->dr_sk->data = (void *) ifa;
-           if (sk_open(ifa->dr_sk) != 0)
-           {
-             DBG("%s: SK_OPEN: new? mc open failed.\n", p->name);
-           }
-         }
+         /* FIXME some error handing ? */
+         sk_join_group(ifa->sk, AllDRouters);
+         ifa->dr_up = 1;
        }
-       else
+       else if (ifa->dr_up)
        {
-         rfree(ifa->dr_sk);
-         ifa->dr_sk = NULL;
+         sk_leave_group(ifa->sk, AllDRouters);
+         ifa->dr_up = 0;
        }
        if ((oldstate == OSPF_IS_DR) && (ifa->net_lsa != NULL))
        {
@@ -209,13 +194,12 @@ ospf_iface_down(struct ospf_iface *ifa)
     OSPF_TRACE(D_EVENTS, "Removing neighbor %I", n->ip);
     ospf_neigh_remove(n);
   }
-  rfree(ifa->hello_sk);
-  rfree(ifa->dr_sk);
-  rfree(ifa->ip_sk);
+
+  rfree(ifa->sk);
+  ifa->sk = NULL;
 
   if (ifa->type == OSPF_IT_VLINK)
   {
-    ifa->ip_sk = NULL;
     ifa->iface = NULL;
     return;
   }
@@ -311,6 +295,7 @@ ospf_iface_sm(struct ospf_iface *ifa, int event)
 
 }
 
+#if 0
 static sock *
 ospf_open_mc_socket(struct ospf_iface *ifa)
 {
@@ -347,6 +332,7 @@ ospf_open_mc_socket(struct ospf_iface *ifa)
   DBG("%s: SK_OPEN: mc opened.\n", p->name);
   return (mcsk);
 }
+#endif
 
 u8
 ospf_iface_clasify(struct iface * ifa)
@@ -383,20 +369,8 @@ ospf_iface_add(struct object_lock *lock)
 
   ifa->ioprob = OSPF_I_OK;
 
-  if (ifa->type != OSPF_IT_NBMA)
-  {
-    if ((ifa->hello_sk = ospf_open_mc_socket(ifa)) == NULL)
-    {
-      log("%s: Huh? could not open mc socket on interface %s?", p->name,
-         iface->name);
-      log("%s: Declaring as stub.", p->name);
-      ifa->stub = 1;
-      ifa->ioprob += OSPF_I_MC;
-    }
-    ifa->dr_sk = NULL;
-  }
-
-  if ((ifa->ip_sk = ospf_open_ip_socket(ifa)) == NULL)
+  ifa->sk = ospf_open_socket(ifa, ifa->type != OSPF_IT_NBMA);
+  if (ifa->sk == NULL)
   {
     log("%s: Huh? could not open ip socket on interface %s?", p->name,
        iface->name);
@@ -546,23 +520,12 @@ ospf_iface_change_mtu(struct proto_ospf *po, struct ospf_iface *ifa)
   struct ospf_packet *op;
   struct ospf_neighbor *n;
   OSPF_TRACE(D_EVENTS, "Changing MTU on interface %s.", ifa->iface->name);
-  if (ifa->hello_sk)
-  {
-    ifa->hello_sk->rbsize = rxbufsize(ifa);
-    ifa->hello_sk->tbsize = ifa->iface->mtu;
-    sk_reallocate(ifa->hello_sk);
-  }
-  if (ifa->dr_sk)
-  {
-    ifa->dr_sk->rbsize = rxbufsize(ifa);
-    ifa->dr_sk->tbsize = ifa->iface->mtu;
-    sk_reallocate(ifa->dr_sk);
-  }
-  if (ifa->ip_sk)
+
+  if (ifa->sk)
   {
-    ifa->ip_sk->rbsize = rxbufsize(ifa);
-    ifa->ip_sk->tbsize = ifa->iface->mtu;
-    sk_reallocate(ifa->ip_sk);
+    ifa->sk->rbsize = rxbufsize(ifa);
+    ifa->sk->tbsize = ifa->iface->mtu;
+    sk_reallocate(ifa->sk);
   }
 
   WALK_LIST(n, ifa->neigh_list)
index dc9421973b74380279ad5f07307463ac9f43bb61..2aafd9d4496b9cfcfb564b76ab761c02f28d0785 100644 (file)
@@ -57,7 +57,6 @@ ospf_lsack_send(struct ospf_neighbor *n, int queue)
 {
   struct ospf_packet *op;
   struct ospf_lsack_packet *pk;
-  sock *sk;
   u16 len, i = 0;
   struct ospf_lsa_header *h;
   struct lsah_n *no;
@@ -67,13 +66,8 @@ ospf_lsack_send(struct ospf_neighbor *n, int queue)
   if (EMPTY_LIST(n->ackl[queue]))
     return;
 
-  if (ifa->type == OSPF_IT_BCAST)
-    sk = ifa->hello_sk;
-  else
-    sk = ifa->ip_sk;
-
-  pk = (struct ospf_lsack_packet *) sk->tbuf;
-  op = (struct ospf_packet *) sk->tbuf;
+  pk = (struct ospf_lsack_packet *) ifa->sk->tbuf;
+  op = (struct ospf_packet *) ifa->sk->tbuf;
 
   ospf_pkt_fill_hdr(n->ifa, pk, LSACK_P);
   h = pk->lsh;
@@ -98,22 +92,22 @@ ospf_lsack_send(struct ospf_neighbor *n, int queue)
        op->length = htons(len);
        DBG("Sending and continuing! Len=%u\n", len);
 
-       OSPF_PACKET(ospf_dump_lsack, (struct ospf_lsack_packet *) sk->tbuf,
+       OSPF_PACKET(ospf_dump_lsack, (struct ospf_lsack_packet *) ifa->sk->tbuf,
                    "LSACK packet sent via %s", ifa->iface->name);
 
        if (ifa->type == OSPF_IT_BCAST)
        {
          if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP))
-           ospf_send_to(sk, AllSPFRouters, ifa);
+           ospf_send_to(ifa, AllSPFRouters);
          else
-           ospf_send_to(sk, AllDRouters, ifa);
+           ospf_send_to(ifa, AllDRouters);
        }
        else
        {
          if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP))
-           ospf_send_to_agt(sk, ifa, NEIGHBOR_EXCHANGE);
+           ospf_send_to_agt(ifa, NEIGHBOR_EXCHANGE);
          else
-           ospf_send_to_bdr(sk, ifa);
+           ospf_send_to_bdr(ifa);
        }
 
        ospf_pkt_fill_hdr(n->ifa, pk, LSACK_P);
@@ -126,24 +120,18 @@ ospf_lsack_send(struct ospf_neighbor *n, int queue)
   op->length = htons(len);
   DBG("Sending! Len=%u\n", len);
 
-  OSPF_PACKET(ospf_dump_lsack, (struct ospf_lsack_packet *) sk->tbuf,
+  OSPF_PACKET(ospf_dump_lsack, (struct ospf_lsack_packet *) ifa->sk->tbuf,
              "LSACK packet sent via %s", ifa->iface->name);
 
   if (ifa->type == OSPF_IT_BCAST)
   {
     if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP))
-    {
-      ospf_send_to(sk, AllSPFRouters, ifa);
-    }
+      ospf_send_to(ifa, AllSPFRouters);
     else
-    {
-      ospf_send_to(sk, AllDRouters, ifa);
-    }
+      ospf_send_to(ifa, AllDRouters);
   }
   else
-  {
-    ospf_send_to_agt(sk, ifa, NEIGHBOR_EXCHANGE);
-  }
+    ospf_send_to_agt(ifa, NEIGHBOR_EXCHANGE);
 }
 
 void
index 3bc5986c55726fee2844f39d7e14c17514f56bbc..8442882cc72e434a23418a12f79a94691f4928a0 100644 (file)
@@ -126,6 +126,7 @@ void
 htonlsab(void *h, void *n, u16 type, u16 len)
 {
   unsigned int i;
+
   switch (type)
   {
   case LSA_T_RT:
@@ -138,10 +139,9 @@ htonlsab(void *h, void *n, u16 type, u16 len)
       hrt = h;
 
 #ifdef OSPFv2
-      nrt->veb.byte = hrt->veb.byte;
-      nrt->padding = 0;
-      nrt->links = htons(hrt->links);
       links = hrt->links;
+      nrt->options = htons(hrt->options);
+      nrt->links = htons(hrt->links);
 #else /* OSPFv3 */
       nrt->options = htonl(hrt->options);
       links = (len - sizeof(struct ospf_lsa_rt)) /
@@ -211,8 +211,7 @@ ntohlsab(void *n, void *h, u16 type, u16 len)
       hrt = h;
 
 #ifdef OSPFv2
-      hrt->veb.byte = nrt->veb.byte;
-      hrt->padding = 0;
+      hrt->options = ntohs(nrt->options);
       links = hrt->links = ntohs(nrt->links);
 #else /* OSPFv3 */
       hrt->options = ntohl(nrt->options);
@@ -308,19 +307,20 @@ lsasum_calculate(struct ospf_lsa_header *h, void *body)
   u16 length = h->length;
   u16 type = h->type;
 
-  log(L_WARN "Checksum %R %R %d start (len %d)", h->id, h->rt, h->type, length);
+  //  log(L_WARN "Checksum %R %R %d start (len %d)", h->id, h->rt, h->type, length);
   htonlsah(h, h);
-
   htonlsab(body, body, type, length - sizeof(struct ospf_lsa_header));
 
+  /*
   char buf[1024];
   memcpy(buf, h, sizeof(struct ospf_lsa_header));
   memcpy(buf + sizeof(struct ospf_lsa_header), body, length - sizeof(struct ospf_lsa_header));
   buf_dump("CALC", buf, length);
+  */
 
   (void) lsasum_check(h, body);
 
-  log(L_WARN "Checksum result %4x", h->checksum);
+  //  log(L_WARN "Checksum result %4x", h->checksum);
 
   ntohlsah(h, h);
   ntohlsab(body, body, type, length - sizeof(struct ospf_lsa_header));
index aafc190e55027f1ce09b1ed2b78d998a67e25113..1b5da273f13a0068c5da3ff904319224034c1d2d 100644 (file)
@@ -28,8 +28,8 @@ static void ospf_dump_lsreq(struct proto *p, struct ospf_lsreq_packet *pkt)
     sizeof(struct ospf_lsreq_header);
 
   for (i = 0; i < j; i++)
-    log(L_TRACE "%s:     LSR      Id: %R, Rt: %R, Type: %u", p->name,
-       htonl(pkt->lsh[i].id), htonl(pkt->lsh[i].rt), pkt->lsh[i].type);
+    log(L_TRACE "%s:     LSR      Id: %R, Rt: %R, Type: 0x%x", p->name,
+       htonl(pkt->lsh[i].id), htonl(pkt->lsh[i].rt), htonl(pkt->lsh[i].type));
 }
 
 void
@@ -44,8 +44,8 @@ ospf_lsreq_send(struct ospf_neighbor *n)
   int i, j;
   struct proto *p = &n->ifa->oa->po->proto;
 
-  pk = (struct ospf_lsreq_packet *) n->ifa->ip_sk->tbuf;
-  op = (struct ospf_packet *) n->ifa->ip_sk->tbuf;
+  pk = (struct ospf_lsreq_packet *) n->ifa->sk->tbuf;
+  op = (struct ospf_packet *) n->ifa->sk->tbuf;
 
   ospf_pkt_fill_hdr(n->ifa, pk, LSREQ_P);
 
@@ -82,9 +82,9 @@ ospf_lsreq_send(struct ospf_neighbor *n)
                                        i) * sizeof(struct ospf_lsreq_header);
   op->length = htons(length);
 
-  OSPF_PACKET(ospf_dump_lsreq, (struct ospf_lsreq_packet *) n->ifa->ip_sk->tbuf,
+  OSPF_PACKET(ospf_dump_lsreq, (struct ospf_lsreq_packet *) n->ifa->sk->tbuf,
              "LSREQ packet sent to %I via %s", n->ip, n->ifa->iface->name);
-  ospf_send_to(n->ifa->ip_sk, n->ip, n->ifa);
+  ospf_send_to(n->ifa, n->ip);
 }
 
 void
index 72861bd533681256bb6c8a1cf919297a6705434e..bccdba8255ecefed65017cfa3d1847bbd65641d5 100644 (file)
@@ -21,7 +21,7 @@ void ospf_dump_lsahdr(struct proto *p, struct ospf_lsa_header *lsa_n)
   struct ospf_lsa_header lsa;
   ntohlsah(lsa_n, &lsa);
 
-  log(L_TRACE "%s:     LSA      Id: %R, Rt: %R, Type: %u, Age: %u, Seqno: 0x%08x, Sum: %u",
+  log(L_TRACE "%s:     LSA      Id: %R, Rt: %R, Type: 0x%04x, Age: %u, Seqno: 0x%08x, Sum: 0x%04x",
       p->name, lsa.id, lsa.rt, lsa.type, lsa.age, lsa.sn, lsa.checksum);
 }
 
@@ -70,7 +70,7 @@ ospf_lsa_flooding_allowed(struct ospf_lsa_header *lsa, u32 domain, struct ospf_i
        return 0;
       if (ifa->oa->stub)
        return 0;
-      return 1
+      return 1;
     }
   else
     return ifa->oa->areaid == domain;
@@ -262,19 +262,13 @@ ospf_lsupd_flood(struct proto_ospf *po,
     }
 
     {
-      sock *sk;
       u16 len, age;
       struct ospf_lsupd_packet *pk;
       struct ospf_packet *op;
       struct ospf_lsa_header *lh;
 
-      if ((ifa->type == OSPF_IT_NBMA) || (ifa->type == OSPF_IT_VLINK))
-       sk = ifa->ip_sk;
-      else
-       sk = ifa->hello_sk;
-
-      pk = (struct ospf_lsupd_packet *) sk->tbuf;
-      op = (struct ospf_packet *) sk->tbuf;
+      pk = (struct ospf_lsupd_packet *) ifa->sk->tbuf;
+      op = (struct ospf_packet *) ifa->sk->tbuf;
 
       ospf_pkt_fill_hdr(ifa, pk, LSUPD_P);
       pk->lsano = htonl(1);
@@ -308,28 +302,28 @@ ospf_lsupd_flood(struct proto_ospf *po,
 
       op->length = htons(len);
 
-      OSPF_PACKET(ospf_dump_lsupd,  (struct ospf_lsupd_packet *) sk->tbuf,
+      OSPF_PACKET(ospf_dump_lsupd,  (struct ospf_lsupd_packet *) ifa->sk->tbuf,
                  "LSUPD packet flooded via %s", ifa->iface->name);
 
       switch (ifa->type)
       {
       case OSPF_IT_NBMA:
        if ((ifa->state == OSPF_IS_BACKUP) || (ifa->state == OSPF_IS_DR))
-         ospf_send_to_agt(sk, ifa, NEIGHBOR_EXCHANGE);
+         ospf_send_to_agt(ifa, NEIGHBOR_EXCHANGE);
        else
-         ospf_send_to_bdr(sk, ifa);
+         ospf_send_to_bdr(ifa);
        break;
 
       case OSPF_IT_VLINK:
-       ospf_send_to(sk, ifa->vip, ifa);
+       ospf_send_to(ifa, ifa->vip);
        break;
 
       default:
        if ((ifa->state == OSPF_IS_BACKUP) || (ifa->state == OSPF_IS_DR) ||
            (ifa->type == OSPF_IT_PTP))
-         ospf_send_to(sk, AllSPFRouters, ifa);
+         ospf_send_to(ifa, AllSPFRouters);
        else
-         ospf_send_to(sk, AllDRouters, ifa);
+         ospf_send_to(ifa, AllDRouters);
       }
     }
   }
@@ -353,8 +347,8 @@ ospf_lsupd_send_list(struct ospf_neighbor *n, list * l)
   if (EMPTY_LIST(*l))
     return;
 
-  pk = (struct ospf_lsupd_packet *) n->ifa->ip_sk->tbuf;
-  op = (struct ospf_packet *) n->ifa->ip_sk->tbuf;
+  pk = (struct ospf_lsupd_packet *) n->ifa->sk->tbuf;
+  op = (struct ospf_packet *) n->ifa->sk->tbuf;
 
   DBG("LSupd: 1st packet\n");
 
@@ -378,9 +372,9 @@ ospf_lsupd_send_list(struct ospf_neighbor *n, list * l)
       pk->lsano = htonl(lsano);
       op->length = htons(len);
 
-      OSPF_PACKET(ospf_dump_lsupd,  (struct ospf_lsupd_packet *) n->ifa->ip_sk->tbuf,
+      OSPF_PACKET(ospf_dump_lsupd,  (struct ospf_lsupd_packet *) n->ifa->sk->tbuf,
                  "LSUPD packet sent to %I via %s", n->ip, n->ifa->iface->name);
-      ospf_send_to(n->ifa->ip_sk, n->ip, n->ifa);
+      ospf_send_to(n->ifa, n->ip);
 
       DBG("LSupd: next packet\n");
       ospf_pkt_fill_hdr(n->ifa, pk, LSUPD_P);
@@ -401,9 +395,9 @@ ospf_lsupd_send_list(struct ospf_neighbor *n, list * l)
     pk->lsano = htonl(lsano);
     op->length = htons(len);
 
-    OSPF_PACKET(ospf_dump_lsupd,  (struct ospf_lsupd_packet *) n->ifa->ip_sk->tbuf,
+    OSPF_PACKET(ospf_dump_lsupd,  (struct ospf_lsupd_packet *) n->ifa->sk->tbuf,
                "LSUPD packet sent to %I via %s", n->ip, n->ifa->iface->name);
-    ospf_send_to(n->ifa->ip_sk, n->ip, n->ifa);
+    ospf_send_to(n->ifa, n->ip);
   }
 }
 
index 7847654117a2fdd22ed74289472c6bbd098c16c8..aa7bc2fc826ceed39cc696bb166fe5a5906b4906 100644 (file)
@@ -478,8 +478,8 @@ bdr_election(struct ospf_iface *ifa)
       || ((ifa->bdrid != myid) && (nbdr == &me)))
   {
 #ifdef OSPFv2
-    me.dr = ndr ? ipa_to_u32(ndr->ip) : IPA_NONE;
-    me.bdr = nbdr ? ipa_to_u32(nbdr->ip) : IPA_NONE;
+    me.dr = ndr ? ipa_to_u32(ndr->ip) : 0;
+    me.bdr = nbdr ? ipa_to_u32(nbdr->ip) : 0;
 #else /* OSPFv3 */
     me.dr = ndr ? ndr->rid : 0;
     me.bdr = nbdr ? nbdr->rid : 0;
index c1d5de76c04e07cfdac5905a1ccaef752f9170c3..ae073dd5d9d240640bd5b5a8bfcaaa441b96b016 100644 (file)
@@ -18,6 +18,7 @@
                         * normally allocate 2*mtu - (I found one cisco
                         * sending packets mtu+16)
                         */
+#define LOCAL_DEBUG 1
 #ifdef LOCAL_DEBUG
 #define OSPF_FORCE_DEBUG 1
 #else
@@ -161,9 +162,7 @@ struct ospf_iface
   struct iface *iface;         /* Nest's iface */
   struct ospf_area *oa;
   struct object_lock *lock;
-  sock *hello_sk;              /* Hello socket */
-  sock *dr_sk;                 /* For states DR or BACKUP */
-  sock *ip_sk;                 /* IP socket (for DD ...) */
+  sock *sk;                    /* IP socket (for DD ...) */
   list neigh_list;             /* List of neigbours */
   u32 cost;                    /* Cost of iface */
   u32 waitint;                 /* number of sec before changing state from wait */
@@ -241,6 +240,7 @@ struct ospf_iface
   list nbma_list;
   u8 priority;                         /* A router priority for DR election */
   u8 ioprob;
+  u8 dr_up;                            /* Socket is a member of DRouters group */
   u32 rxbuf;
 };
 
index 200ef958c93b5aba952df520a3afc36c986920ae..0bb1f511412bc0c69eab805c5a6cd14c28d323c3 100644 (file)
@@ -437,26 +437,27 @@ ospf_err_hook(sock * sk, int err)
 }
 
 void
-ospf_send_to_agt(sock * sk, struct ospf_iface *ifa, u8 state)
+ospf_send_to_agt(struct ospf_iface *ifa, u8 state)
 {
   struct ospf_neighbor *n;
 
   WALK_LIST(n, ifa->neigh_list) if (n->state >= state)
-    ospf_send_to(sk, n->ip, ifa);
+    ospf_send_to(ifa, n->ip);
 }
 
 void
-ospf_send_to_bdr(sock * sk, struct ospf_iface *ifa)
+ospf_send_to_bdr(struct ospf_iface *ifa)
 {
   if (!ipa_equal(ifa->drip, IPA_NONE))
-    ospf_send_to(sk, ifa->drip, ifa);
+    ospf_send_to(ifa, ifa->drip);
   if (!ipa_equal(ifa->bdrip, IPA_NONE))
-    ospf_send_to(sk, ifa->bdrip, ifa);
+    ospf_send_to(ifa, ifa->bdrip);
 }
 
 void
-ospf_send_to(sock *sk, ip_addr ip, struct ospf_iface *ifa)
+ospf_send_to(struct ospf_iface *ifa, ip_addr ip)
 {
+  sock *sk = ifa->sk;
   struct ospf_packet *pkt = (struct ospf_packet *) sk->tbuf;
   int len = ntohs(pkt->length);
 
index b85b608b52cf6104c3e84f502c5a6eca7c2aac57..4d5612ffe2bcb47a2ea4385f6838a3fa82826dd1 100644 (file)
@@ -15,9 +15,9 @@ unsigned ospf_pkt_maxsize(struct ospf_iface *ifa);
 int ospf_rx_hook(sock * sk, int size);
 void ospf_tx_hook(sock * sk);
 void ospf_err_hook(sock * sk, int err);
-void ospf_send_to_agt(sock * sk, struct ospf_iface *ifa, u8 state);
-void ospf_send_to_bdr(sock * sk, struct ospf_iface *ifa);
-void ospf_send_to(sock *sk, ip_addr ip, struct ospf_iface *ifa);
+void ospf_send_to_agt(struct ospf_iface *ifa, u8 state);
+void ospf_send_to_bdr(struct ospf_iface *ifa);
+void ospf_send_to(struct ospf_iface *ifa, ip_addr ip);
 
 
 #endif /* _BIRD_OSPF_PACKET_H_ */
index 27bd22665975fce9287c32df098e5fd573ad2745..0f6efd783d53a264aeac538729dafb691c62a3e6 100644 (file)
@@ -26,6 +26,8 @@ static void rt_sync(struct proto_ospf *po);
 #endif
 
 
+#ifdef OSPFv3
+
 static inline u32 *
 get_ipv6_prefix(u32 *buf, ip_addr *addr, int *pxlen, u8 *pxopts, u16 *rest)
 {
@@ -56,6 +58,9 @@ get_ipv6_addr(u32 *buf, ip_addr *addr)
   return buf + 4;
 }
 
+#endif
+
+
 static void
 fill_ri(orta * orta)
 {
@@ -839,8 +844,8 @@ ospf_ext_spf(struct proto_ospf *po)
     if (en->lsa.rt == p->cf->global->router_id)
       continue;
 
-    DBG("%s: Working on LSA. ID: %R, RT: %R, Type: %u, Mask %I\n",
-       p->name, en->lsa.id, en->lsa.rt, en->lsa.type, le->netmask);
+    DBG("%s: Working on LSA. ID: %R, RT: %R, Type: %u\n",
+       p->name, en->lsa.id, en->lsa.rt, en->lsa.type);
 
     le = en->lsa_body;
 
@@ -1056,7 +1061,7 @@ static inline int
 match_dr(struct ospf_iface *ifa, struct top_hash_entry *en)
 {
 #ifdef OSPFv2
-  return (ifa->drid == en->lsa.rt) && (ifa->drip == ipa_from_u32(en->lsa.id));
+  return (ifa->drid == en->lsa.rt) && (ipa_to_u32(ifa->drip) == en->lsa.id);
 #else /* OSPFv3 */
   return (ifa->drid == en->lsa.rt) && (ifa->dr_iface_id == en->lsa.id);
 #endif
index 8263010413124e2b048833405e1e3c80247d86a0..8f64c4cafd06fd9e26aa2723cdef4d7387ae27f8 100644 (file)
@@ -174,7 +174,7 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 *length)
   ASSERT(po->lsab_used == 0);
   rt = lsab_allocz(po, sizeof(struct ospf_lsa_rt));
 
-  rt->options = 0
+  rt->options = 0;
 
   if (po->areano > 1)
     rt->options |= OPT_RT_B;
@@ -445,7 +445,9 @@ update_rt_lsa(struct ospf_area *oa)
    */
 
   originate_rt_lsa(oa);
+#ifdef OSPFv3
   originate_prefix_rt_lsa(oa);
+#endif
 
   schedule_rtcalc(po);
   oa->origrt = 0;
@@ -577,12 +579,16 @@ update_net_lsa(struct ospf_iface *ifa)
   if ((ifa->state != OSPF_IS_DR) || (ifa->fadj == 0))
     {
       flush_net_lsa(ifa);
+#ifdef OSPFv3
       flush_prefix_net_lsa(ifa);
+#endif
     }
   else
     {
       originate_net_lsa(ifa);
+#ifdef OSPFv3
       originate_prefix_net_lsa(ifa);
+#endif
     }
 
   schedule_rtcalc(po);
@@ -1353,6 +1359,16 @@ ospf_top_rehash(struct top_graph *f, int step)
   ospf_top_ht_free(oldt);
 }
 
+#ifdef OSPFv2
+
+u32
+ospf_lsa_domain(u32 type, struct ospf_iface *ifa)
+{
+  return (type == LSA_T_EXT) ? 0 : ifa->oa->areaid;
+}
+
+#else /* OSPFv3 */
+
 u32
 ospf_lsa_domain(u32 type, struct ospf_iface *ifa)
 {
@@ -1370,6 +1386,8 @@ ospf_lsa_domain(u32 type, struct ospf_iface *ifa)
     }
 }
 
+#endif
+
 struct top_hash_entry *
 ospf_hash_find_header(struct top_graph *f, u32 domain, struct ospf_lsa_header *h)
 {
index c655cc361003bc819087c0563eff9a79bb01bfcd..f9a160e63c1cb5faf46d58338f1d7c36c7570c54 100644 (file)
@@ -684,7 +684,7 @@ new_iface(struct proto *p, struct iface *new, unsigned long flags, struct iface_
     DBG( "Doing multicasts!\n" );
 
   rif->sock = sk_new( p->pool );
-  rif->sock->type = rif->multicast?SK_UDP_MC:SK_UDP;
+  rif->sock->type = SK_UDP;
   rif->sock->sport = P_CF->port;
   rif->sock->rx_hook = rip_rx;
   rif->sock->data = rif;
@@ -721,19 +721,37 @@ new_iface(struct proto *p, struct iface *new, unsigned long flags, struct iface_
   if (!ipa_nonzero(rif->sock->daddr)) {
     if (rif->iface)
       log( L_WARN "%s: interface %s is too strange for me", p->name, rif->iface->name );
-  } else if (sk_open(rif->sock)<0) {
-    log( L_ERR "%s: could not create socket for %s", p->name, rif->iface ? rif->iface->name : "(dummy)" );
-    if (rif->iface) {
-      rfree(rif->sock);
-      mb_free(rif);
-      return NULL;
-    }
-    /* On dummy, we just return non-working socket, so that user gets error every time anyone requests table */
+  } else {
+
+    if (sk_open(rif->sock)<0)
+      goto err;
+
+    if (rif->multicast)
+      {
+       if (sk_setup_multicast(rif->sock) < 0)
+         goto err;
+       if (sk_join_group(rif->sock, rif->sock->daddr) < 0)
+         goto err;
+      }
+    else
+      {
+       if (sk_set_broadcast(rif->sock, 1) < 0)
+         goto err;
+      }
   }
 
   TRACE(D_EVENTS, "Listening on %s, port %d, mode %s (%I)", rif->iface ? rif->iface->name : "(dummy)", P_CF->port, rif->multicast ? "multicast" : "broadcast", rif->sock->daddr );
   
   return rif;
+
+ err:
+  log( L_ERR "%s: could not create socket for %s", p->name, rif->iface ? rif->iface->name : "(dummy)" );
+  if (rif->iface) {
+    rfree(rif->sock);
+    mb_free(rif);
+    return NULL;
+  }
+  /* On dummy, we just return non-working socket, so that user gets error every time anyone requests table */
 }
 
 static void
index b0ec456e8b4ad02eb3909d206d48f341fcd55cd4..80f8f942bc25146dc75ffa8b332699ce035a9b95 100644 (file)
@@ -27,48 +27,55 @@ set_inaddr(struct in_addr * ia, ip_addr a)
 }
 
 static inline char *
-sysio_mcast_setup(sock * s)
+sysio_setup_multicast(sock *s)
 {
-       u8              zero = 0;
-       u8              one = 1;
+       struct in_addr m;
+       u8 zero = 0;
+       u8 ttl = s->ttl;
 
-       if (ipa_nonzero(s->daddr)) {
+       if (setsockopt(s->fd, IPPROTO_IP, IP_MULTICAST_LOOP, &zero, sizeof(zero)) < 0)
+               return "IP_MULTICAST_LOOP";
 
-               if (setsockopt(s->fd, IPPROTO_IP, IP_MULTICAST_LOOP, &zero, sizeof(zero)) < 0)
-                       return "IP_MULTICAST_LOOP";
+       if (setsockopt(s->fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0)
+               return "IP_MULTICAST_TTL";
+
+       /* This defines where should we send _outgoing_ multicasts */
+        set_inaddr(&m, s->iface->addr->ip);
+       if (setsockopt(s->fd, IPPROTO_IP, IP_MULTICAST_IF, &m, sizeof(m)) < 0)
+               return "IP_MULTICAST_IF";
 
-               if (setsockopt(s->fd, IPPROTO_IP, IP_MULTICAST_TTL, &one, sizeof(one)) < 0)
-                       return "IP_MULTICAST_TTL";
-       }
        return NULL;
 }
 
 
 static inline char *
-sysio_mcast_join(sock * s)
+sysio_join_group(sock *s, ip_addr maddr)
 {
-       struct in_addr  m;
        struct ip_mreq  mreq;
-       char   *err;
-
-        set_inaddr(&m, s->iface->addr->ip );
 
        bzero(&mreq, sizeof(mreq));
        set_inaddr(&mreq.imr_interface, s->iface->addr->ip);
-       set_inaddr(&mreq.imr_multiaddr, s->daddr);
+       set_inaddr(&mreq.imr_multiaddr, maddr);
 
        /* And this one sets interface for _receiving_ multicasts from */
-       if (ipa_nonzero(s->daddr) &&
-            setsockopt(s->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
+       if (setsockopt(s->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
                return "IP_ADD_MEMBERSHIP";
 
+       return NULL;
+}
 
-       /* This defines where should we send _outgoing_ multicasts */
-       if (ipa_nonzero(s->daddr) && setsockopt(s->fd, IPPROTO_IP, IP_MULTICAST_IF, &m, sizeof(m)) < 0)
-               return "IP_MULTICAST_IF";
+static inline char *
+sysio_leave_group(sock *s, ip_addr maddr)
+{
+       struct ip_mreq mreq;
 
-       if (err = sysio_mcast_setup(s))
-               return err;
+       bzero(&mreq, sizeof(mreq));
+       set_inaddr(&mreq.imr_interface, s->iface->addr->ip);
+       set_inaddr(&mreq.imr_multiaddr, maddr);
+
+       /* And this one sets interface for _receiving_ multicasts from */
+       if (setsockopt(s->fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
+               return "IP_DROP_MEMBERSHIP";
 
        return NULL;
 }
index 2fa5f0a9e893738170561113eb95676ea02e28df..70d35ccf53828dfc0364089be51af92cd0a0de53 100644 (file)
@@ -38,27 +38,33 @@ set_inaddr(struct in_addr *ia, ip_addr a)
  *  ways. Horrible.
  */
 
-static inline char *sysio_mcast_setup(sock *s)
+
+#if defined(CONFIG_LINUX_MC_MREQ) || defined(CONFIG_LINUX_MC_MREQ_BIND)
+/*
+ *  Older kernels support only struct mreq which matches interfaces by their
+ *  addresses and thus fails on unnumbered devices. On newer 2.0 kernels
+ *  we can use SO_BINDTODEVICE to circumvent this problem.
+ */
+
+#define MREQ_IFA struct in_addr
+#define MREQ_GRP struct ip_mreq
+static inline void fill_mreq_ifa(struct in_addr *m, struct iface *ifa, UNUSED ip_addr maddr)
 {
-  int zero = 0;
+  set_inaddr(m, ifa->addr->ip);
+}
 
-  if (ipa_nonzero(s->daddr))
-    {
-      if (
-#ifdef IP_DEFAULT_MULTICAST_TTL
-         s->ttl != IP_DEFAULT_MULTICAST_TTL &&
-#endif
-         setsockopt(s->fd, SOL_IP, IP_MULTICAST_TTL, &s->ttl, sizeof(s->ttl)) < 0)
-       return "IP_MULTICAST_TTL";
-      if (
-#ifdef IP_DEFAULT_MULTICAST_LOOP
-         IP_DEFAULT_MULTICAST_LOOP &&
+static inline void fill_mreq_grp(struct ip_mreq *m, struct iface *ifa, ip_addr maddr)
+{
+  bzero(m, sizeof(*m));
+#ifdef CONFIG_LINUX_MC_MREQ_BIND
+  m->imr_interface.s_addr = INADDR_ANY;
+#else
+  set_inaddr(&m->imr_interface, ifa->addr->ip);
 #endif
-         setsockopt(s->fd, SOL_IP, IP_MULTICAST_LOOP, &zero, sizeof(zero)) < 0)
-       return "IP_MULTICAST_LOOP";
-    }
-  return NULL;
+  set_inaddr(&m->imr_multiaddr, maddr);
 }
+#endif
+
 
 #ifdef CONFIG_LINUX_MC_MREQN
 /*
@@ -76,70 +82,78 @@ struct ip_mreqn
 };
 #endif
 
-static inline char *sysio_mcast_join(sock *s)
+#define MREQ_IFA struct ip_mreqn
+#define MREQ_GRP struct ip_mreqn
+#define fill_mreq_ifa fill_mreq
+#define fill_mreq_grp fill_mreq
+
+static inline fill_mreq(struct ip_mreqn *m, struct iface *ifa, ip_addr maddr)
 {
-  struct ip_mreqn mreq;
-  char *err;
-  struct ifreq ifr;
-
-  if (err = sysio_mcast_setup(s))
-    return err;
-  strcpy(ifr.ifr_name, s->iface->name);
-  if (setsockopt(s->fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) < 0)
-    return "SO_BINDTODEVICE";
-  mreq.imr_ifindex = s->iface->index;
-  set_inaddr(&mreq.imr_address, s->iface->addr->ip);
-  set_inaddr(&mreq.imr_multiaddr, s->daddr);
-  /* This defines where should we send _outgoing_ multicasts */
-  if (ipa_nonzero(s->daddr) && setsockopt(s->fd, SOL_IP, IP_MULTICAST_IF, &mreq, sizeof(mreq)) < 0)
-    return "IP_MULTICAST_IF";
-  /* And this one sets interface for _receiving_ multicasts from */
-  if (ipa_nonzero(s->saddr) && setsockopt(s->fd, SOL_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
-    return "IP_ADD_MEMBERSHIP";
-  return NULL;
+  bzero(m, sizeof(*m));
+  m->imr_ifindex = ifa->index;
+  set_inaddr(&m->imr_address, ifa->addr->ip);
+  set_inaddr(&m->imr_multiaddr, maddr);
 }
 #endif
 
-#if defined(CONFIG_LINUX_MC_MREQ) || defined(CONFIG_LINUX_MC_MREQ_BIND)
-/*
- *  Older kernels support only struct mreq which matches interfaces by their
- *  addresses and thus fails on unnumbered devices. On newer 2.0 kernels
- *  we can use SO_BINDTODEVICE to circumvent this problem.
- */
-
-static inline char *sysio_mcast_join(sock *s)
+static inline char *
+sysio_setup_multicast(sock *s)
 {
-  struct in_addr mreq;
-  struct ip_mreq mreq_add;
-  char *err;
+  MREQ_IFA m;
+  int zero = 0;
 
-  if (err = sysio_mcast_setup(s))
-    return err;
-  set_inaddr(&mreq, s->iface->addr->ip);
-#ifdef CONFIG_LINUX_MC_MREQ_BIND
+  if (setsockopt(s->fd, SOL_IP, IP_MULTICAST_LOOP, &zero, sizeof(zero)) < 0)
+    return "IP_MULTICAST_LOOP";
+
+  if (setsockopt(s->fd, SOL_IP, IP_MULTICAST_TTL, &s->ttl, sizeof(s->ttl)) < 0)
+    return "IP_MULTICAST_TTL";
+
+  /* This defines where should we send _outgoing_ multicasts */
+  fill_mreq_ifa(&m, s->iface, IPA_NONE);
+  if (setsockopt(s->fd, SOL_IP, IP_MULTICAST_IF, &m, sizeof(m)) < 0)
+    return "IP_MULTICAST_IF";
+
+#if defined(CONFIG_LINUX_MC_MREQ_BIND) || defined(CONFIG_LINUX_MC_MREQN) 
   {
     struct ifreq ifr;
     strcpy(ifr.ifr_name, s->iface->name);
     if (setsockopt(s->fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) < 0)
       return "SO_BINDTODEVICE";
-    mreq_add.imr_interface.s_addr = INADDR_ANY;
   }
-#else
-  mreq_add.imr_interface = mreq;
 #endif
-  set_inaddr(&mreq_add.imr_multiaddr, s->daddr);
-  /* This defines where should we send _outgoing_ multicasts */
-  if (ipa_nonzero(s->daddr) && setsockopt(s->fd, SOL_IP, IP_MULTICAST_IF, &mreq, sizeof(mreq)) < 0)
-    return "IP_MULTICAST_IF";
+
+  return NULL;
+}
+
+static inline char *
+sysio_join_group(sock *s, ip_addr maddr)
+{
+  MREQ_GRP m;
+
   /* And this one sets interface for _receiving_ multicasts from */
-  if (ipa_nonzero(s->saddr) && setsockopt(s->fd, SOL_IP, IP_ADD_MEMBERSHIP, &mreq_add, sizeof(mreq_add)) < 0)
+  fill_mreq_grp(&m, s->iface, maddr);
+  if (setsockopt(s->fd, SOL_IP, IP_ADD_MEMBERSHIP, &m, sizeof(m)) < 0)
     return "IP_ADD_MEMBERSHIP";
+
+  return NULL;
+}
+
+static inline char *
+sysio_leave_group(sock *s, ip_addr maddr)
+{
+  MREQ_GRP m;
+
+  /* And this one sets interface for _receiving_ multicasts from */
+  fill_mreq_grp(&m, s->iface, maddr);
+  if (setsockopt(s->fd, SOL_IP, IP_DROP_MEMBERSHIP, &m, sizeof(m)) < 0)
+    return "IP_DROP_MEMBERSHIP";
+
   return NULL;
 }
-#endif
 
 #endif
 
+
 #include <linux/socket.h>
 #include <linux/tcp.h>
 
index d95471619c5d436fbbcf42579f6cdcd136b526e2..5cc80dcd5a213d2c274eb07377367238516e06c8 100644 (file)
@@ -690,8 +690,7 @@ sk_set_ttl_int(sock *s)
 {
   int one = 1;
 #ifdef IPV6
-  if (s->type != SK_UDP_MC && s->type != SK_IP_MC &&
-      setsockopt(s->fd, SOL_IPV6, IPV6_UNICAST_HOPS, &s->ttl, sizeof(s->ttl)) < 0)
+  if (setsockopt(s->fd, SOL_IPV6, IPV6_UNICAST_HOPS, &s->ttl, sizeof(s->ttl)) < 0)
     return "IPV6_UNICAST_HOPS";
 #else
   if (setsockopt(s->fd, SOL_IP, IP_TTL, &s->ttl, sizeof(s->ttl)) < 0)
@@ -788,6 +787,134 @@ sk_set_md5_auth(sock *s, ip_addr a, char *passwd)
   return sk_set_md5_auth_int(s, &sa, passwd);
 }
 
+int
+sk_set_broadcast(sock *s, int enable)
+{
+  if (setsockopt(s->fd, SOL_SOCKET, SO_BROADCAST, &enable, sizeof(enable)) < 0)
+    log(L_ERR "sk_set_broadcast: SO_BROADCAST: %m");
+}
+
+
+#ifdef IPV6
+
+int
+sk_setup_multicast(sock *s)
+{
+  char *err;
+  int zero = 0;
+  int index;
+
+  ASSERT(s->iface && s->iface->addr);
+
+  index = s->iface->index;
+  if (setsockopt(s->fd, SOL_IPV6, IPV6_MULTICAST_HOPS, &s->ttl, sizeof(s->ttl)) < 0)
+    ERR("IPV6_MULTICAST_HOPS");
+  if (setsockopt(s->fd, SOL_IPV6, IPV6_MULTICAST_LOOP, &zero, sizeof(zero)) < 0)
+    ERR("IPV6_MULTICAST_LOOP");
+  if (setsockopt(s->fd, SOL_IPV6, IPV6_MULTICAST_IF, &index, sizeof(index)) < 0)
+    ERR("IPV6_MULTICAST_IF");
+
+  return 0;
+
+bad:
+  log(L_ERR "sk_setup_multicast: %s: %m", err);
+  return -1;
+}
+
+int
+sk_join_group(sock *s, ip_addr maddr)
+{
+  struct ipv6_mreq mreq;
+       
+  set_inaddr(&mreq.ipv6mr_multiaddr, maddr);
+
+#ifdef CONFIG_IPV6_GLIBC_20
+  mreq.ipv6mr_ifindex = s->iface->index;
+#else
+  mreq.ipv6mr_interface = s->iface->index;
+#endif
+
+  /* RFC 2553 says IPV6_JOIN_GROUP */
+  if (setsockopt(s->fd, SOL_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
+    {
+      log(L_ERR "sk_join_group: IPV6_ADD_MEMBERSHIP: %m");
+      return -1;
+    }
+
+  return 0;
+}
+
+int
+sk_leave_group(sock *s, ip_addr maddr)
+{
+  struct ipv6_mreq mreq;
+       
+  set_inaddr(&mreq.ipv6mr_multiaddr, maddr);
+
+#ifdef CONFIG_IPV6_GLIBC_20
+  mreq.ipv6mr_ifindex = s->iface->index;
+#else
+  mreq.ipv6mr_interface = s->iface->index;
+#endif
+
+  /* RFC 2553 says IPV6_LEAVE_GROUP */
+  if (setsockopt(s->fd, SOL_IPV6, IPV6_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
+    {
+      log(L_ERR "sk_leave_group: IPV6_DROP_MEMBERSHIP: %m");
+      return -1;
+    }
+
+  return 0;
+}
+
+#else /* IPV4 */
+
+int
+sk_setup_multicast(sock *s)
+{
+  char *err;
+
+  ASSERT(s->iface && s->iface->addr);
+
+  if (err = sysio_setup_multicast(s))
+    {
+      log(L_ERR "sk_setup_multicast: %s: %m", err);
+      return -1;
+    }
+
+  return 0;
+}
+
+int
+sk_join_group(sock *s, ip_addr maddr)
+{
+ char *err;
+
+ if (err = sysio_join_group(s, maddr))
+    {
+      log(L_ERR "sk_join_group: %s: %m", err);
+      return -1;
+    }
+
+  return 0;
+}
+
+int
+sk_leave_group(sock *s, ip_addr maddr)
+{
+ char *err;
+
+ if (err = sysio_leave_group(s, maddr))
+    {
+      log(L_ERR "sk_leave_group: %s: %m", err);
+      return -1;
+    }
+
+  return 0;
+}
+
+#endif 
+
 
 static void
 sk_tcp_connected(sock *s)
@@ -861,11 +988,9 @@ sk_open(sock *s)
       fd = socket(BIRD_PF, SOCK_STREAM, IPPROTO_TCP);
       break;
     case SK_UDP:
-    case SK_UDP_MC:
       fd = socket(BIRD_PF, SOCK_DGRAM, IPPROTO_UDP);
       break;
     case SK_IP:
-    case SK_IP_MC:
       fd = socket(BIRD_PF, SOCK_RAW, s->dport);
       break;
     case SK_MAGIC:
@@ -881,59 +1006,11 @@ sk_open(sock *s)
   if (err = sk_setup(s))
     goto bad;
 
-  switch (type)
-    {
-    case SK_UDP:
-    case SK_IP:
-#ifndef IPV6
-      if (s->iface)                    /* It's a broadcast socket */
-       if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &one, sizeof(one)) < 0)
-         ERR("SO_BROADCAST");
-#endif
-      break;
-    case SK_UDP_MC:
-    case SK_IP_MC:
-      {
-#ifdef IPV6
-       /* Fortunately, IPv6 socket interface is recent enough and therefore standardized */
-       ASSERT(s->iface && s->iface->addr);
-       if (ipa_nonzero(s->daddr))
-         {
-           int t = s->iface->index;
-           int zero = 0;
-           if (setsockopt(fd, SOL_IPV6, IPV6_MULTICAST_HOPS, &s->ttl, sizeof(s->ttl)) < 0)
-             ERR("IPV6_MULTICAST_HOPS");
-           if (setsockopt(fd, SOL_IPV6, IPV6_MULTICAST_LOOP, &zero, sizeof(zero)) < 0)
-             ERR("IPV6_MULTICAST_LOOP");
-           if (setsockopt(fd, SOL_IPV6, IPV6_MULTICAST_IF, &t, sizeof(t)) < 0)
-             ERR("IPV6_MULTICAST_IF");
-         }
-       if (has_src)
-         {
-           struct ipv6_mreq mreq;
-           set_inaddr(&mreq.ipv6mr_multiaddr, s->daddr);
-#ifdef CONFIG_IPV6_GLIBC_20
-           mreq.ipv6mr_ifindex = s->iface->index;
-#else
-           mreq.ipv6mr_interface = s->iface->index;
-#endif /* CONFIG_IPV6_GLIBC_20 */
-           if (setsockopt(fd, SOL_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
-             ERR("IPV6_ADD_MEMBERSHIP");
-         }
-#else /* IPv4 */
-       /* With IPv4 there are zillions of different socket interface variants. Ugh. */
-       ASSERT(s->iface && s->iface->addr);
-       if (err = sysio_mcast_join(s))
-         goto bad;
-#endif /* IPV6 */
-      break;
-      }
-    }
   if (has_src)
     {
       int port;
 
-      if (type == SK_IP || type == SK_IP_MC)
+      if (type == SK_IP)
        port = 0;
       else
        {
@@ -943,12 +1020,7 @@ sk_open(sock *s)
        }
       fill_in_sockaddr(&sa, s->saddr, port);
       fill_in_sockifa(&sa, s->iface);
-#ifdef CONFIG_SKIP_MC_BIND
-      if ((type != SK_UDP_MC) && (type != SK_IP_MC) &&
-         bind(fd, (struct sockaddr *) &sa, sizeof(sa)) < 0)
-#else
       if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) < 0)
-#endif
        ERR("bind");
     }
   fill_in_sockaddr(&sa, s->daddr, s->dport);
@@ -1069,9 +1141,7 @@ sk_maybe_write(sock *s)
       s->ttx = s->tpos = s->tbuf;
       return 1;
     case SK_UDP:
-    case SK_UDP_MC:
     case SK_IP:
-    case SK_IP_MC:
       {
        sockaddr sa;