isisd: add Google's changes to IS-IS
diff --git a/isisd/isis_pfpacket.c b/isisd/isis_pfpacket.c
index 9e4165e..42947b2 100644
--- a/isisd/isis_pfpacket.c
+++ b/isisd/isis_pfpacket.c
@@ -134,7 +134,7 @@
 
   circuit->fd = fd;
 
-  if (circuit->circ_type == CIRCUIT_T_BROADCAST)
+  if (if_is_broadcast (circuit->interface))
     {
       /*
        * Join to multicast groups
@@ -142,24 +142,22 @@
        * 8.4.2 - Broadcast subnetwork IIH PDUs
        * FIXME: is there a case only one will fail??
        */
-      if (circuit->circuit_is_type & IS_LEVEL_1)
-	{
-	  /* joining ALL_L1_ISS */
-	  retval = isis_multicast_join (circuit->fd, 1,
-					circuit->interface->ifindex);
-	  /* joining ALL_ISS */
-	  retval = isis_multicast_join (circuit->fd, 3,
-					circuit->interface->ifindex);
-	}
-      if (circuit->circuit_is_type & IS_LEVEL_2)
-	/* joining ALL_L2_ISS */
-	retval = isis_multicast_join (circuit->fd, 2,
-				      circuit->interface->ifindex);
+      if (circuit->is_type & IS_LEVEL_1)
+        /* joining ALL_L1_ISS */
+        retval = isis_multicast_join (circuit->fd, 1,
+                                      circuit->interface->ifindex);
+      if (circuit->is_type & IS_LEVEL_2)
+        /* joining ALL_L2_ISS */
+        retval = isis_multicast_join (circuit->fd, 2,
+                                      circuit->interface->ifindex);
+      /* joining ALL_ISS (used in RFC 5309 p2p-over-lan as well) */
+      retval = isis_multicast_join (circuit->fd, 3,
+                                    circuit->interface->ifindex);
     }
   else
     {
       retval =
-	isis_multicast_join (circuit->fd, 0, circuit->interface->ifindex);
+        isis_multicast_join (circuit->fd, 0, circuit->interface->ifindex);
     }
 
   return retval;
@@ -184,12 +182,13 @@
       goto end;
     }
 
-  if (circuit->circ_type == CIRCUIT_T_BROADCAST)
+  /* Assign Rx and Tx callbacks are based on real if type */
+  if (if_is_broadcast (circuit->interface))
     {
       circuit->tx = isis_send_pdu_bcast;
       circuit->rx = isis_recv_pdu_bcast;
     }
-  else if (circuit->circ_type == CIRCUIT_T_P2P)
+  else if (if_is_pointopoint (circuit->interface))
     {
       circuit->tx = isis_send_pdu_p2p;
       circuit->rx = isis_recv_pdu_p2p;
@@ -234,13 +233,14 @@
 
   if (bytesread < 0)
     {
-      zlog_warn ("isis_recv_packet_bcast(): fd %d, recvfrom (): %s",
-		 circuit->fd, safe_strerror (errno));
-      zlog_warn ("circuit is %s", circuit->interface->name);
-      zlog_warn ("circuit fd %d", circuit->fd);
-      zlog_warn ("bytesread %d", bytesread);
+      zlog_warn ("isis_recv_packet_bcast(): ifname %s, fd %d, bytesread %d, "
+                 "recvfrom(): %s",
+                 circuit->interface->name, circuit->fd, bytesread,
+                 safe_strerror (errno));
       /* get rid of the packet */
-      bytesread = read (circuit->fd, discard_buff, sizeof (discard_buff));
+      bytesread = recvfrom (circuit->fd, discard_buff, sizeof (discard_buff),
+                            MSG_DONTWAIT, (struct sockaddr *) &s_addr,
+                            (socklen_t *) &addr_len);
       return ISIS_WARNING;
     }
   /*
@@ -249,15 +249,22 @@
   if (!llc_check (llc) || s_addr.sll_pkttype == PACKET_OUTGOING)
     {
       /*  Read the packet into discard buff */
-      bytesread = read (circuit->fd, discard_buff, sizeof (discard_buff));
+      bytesread = recvfrom (circuit->fd, discard_buff, sizeof (discard_buff),
+                            MSG_DONTWAIT, (struct sockaddr *) &s_addr,
+                            (socklen_t *) &addr_len);
       if (bytesread < 0)
-	zlog_warn ("isis_recv_pdu_bcast(): read() failed");
+	zlog_warn ("isis_recv_pdu_bcast(): recvfrom() failed");
       return ISIS_WARNING;
     }
 
   /* on lan we have to read to the static buff first */
-  bytesread = recvfrom (circuit->fd, sock_buff, circuit->interface->mtu, 0,
+  bytesread = recvfrom (circuit->fd, sock_buff, sizeof (sock_buff), MSG_DONTWAIT,
 			(struct sockaddr *) &s_addr, (socklen_t *) &addr_len);
+  if (bytesread < 0)
+    {
+      zlog_warn ("isis_recv_pdu_bcast(): recvfrom() failed");
+      return ISIS_WARNING;
+    }
 
   /* then we lose the LLC */
   stream_write (circuit->rcv_stream, sock_buff + LLC_LEN, bytesread - LLC_LEN);
@@ -285,9 +292,11 @@
   if (s_addr.sll_pkttype == PACKET_OUTGOING)
     {
       /*  Read the packet into discard buff */
-      bytesread = read (circuit->fd, discard_buff, sizeof (discard_buff));
+      bytesread = recvfrom (circuit->fd, discard_buff, sizeof (discard_buff),
+                            MSG_DONTWAIT, (struct sockaddr *) &s_addr,
+                            (socklen_t *) &addr_len);
       if (bytesread < 0)
-	zlog_warn ("isis_recv_pdu_p2p(): read() failed");
+	zlog_warn ("isis_recv_pdu_p2p(): recvfrom() failed");
       return ISIS_WARNING;
     }
 
@@ -309,6 +318,9 @@
 int
 isis_send_pdu_bcast (struct isis_circuit *circuit, int level)
 {
+  struct msghdr msg;
+  struct iovec iov[2];
+
   /* we need to do the LLC in here because of P2P circuits, which will
    * not need it
    */
@@ -321,7 +333,10 @@
   sa.sll_protocol = htons (stream_get_endp (circuit->snd_stream) + LLC_LEN);
   sa.sll_ifindex = circuit->interface->ifindex;
   sa.sll_halen = ETH_ALEN;
-  if (level == 1)
+  /* RFC5309 section 4.1 recommends ALL_ISS */
+  if (circuit->circ_type == CIRCUIT_T_P2P)
+    memcpy (&sa.sll_addr, ALL_ISS, ETH_ALEN);
+  else if (level == 1)
     memcpy (&sa.sll_addr, ALL_L1_ISS, ETH_ALEN);
   else
     memcpy (&sa.sll_addr, ALL_L2_ISS, ETH_ALEN);
@@ -332,14 +347,17 @@
   sock_buff[1] = 0xFE;
   sock_buff[2] = 0x03;
 
-  /* then we copy the data */
-  memcpy (sock_buff + LLC_LEN, circuit->snd_stream->data,
-	  stream_get_endp (circuit->snd_stream));
+  memset (&msg, 0, sizeof (msg));
+  msg.msg_name = &sa;
+  msg.msg_namelen = sizeof (struct sockaddr_ll);
+  msg.msg_iov = iov;
+  msg.msg_iovlen = 2;
+  iov[0].iov_base = sock_buff;
+  iov[0].iov_len = LLC_LEN;
+  iov[1].iov_base = circuit->snd_stream->data;
+  iov[1].iov_len = stream_get_endp (circuit->snd_stream);
 
-  /* now we can send this */
-  written = sendto (circuit->fd, sock_buff,
-		    stream_get_endp(circuit->snd_stream) + LLC_LEN, 0,
-		    (struct sockaddr *) &sa, sizeof (struct sockaddr_ll));
+  written = sendmsg (circuit->fd, &msg, 0);
 
   return ISIS_OK;
 }
@@ -347,7 +365,6 @@
 int
 isis_send_pdu_p2p (struct isis_circuit *circuit, int level)
 {
-
   int written = 1;
   struct sockaddr_ll sa;