]> git.proxmox.com Git - mirror_frr.git/blobdiff - zebra/irdp_packet.c
Add comment questioning part of previous change (Denis?).
[mirror_frr.git] / zebra / irdp_packet.c
index 8cd3dad659b6a509caa6c95fe9b70fec6ebcd19f..3c5f1559caaf495b4f486451f153ebad637227d6 100644 (file)
 
 /* GLOBAL VARS */
 
-int irdp_sock;
+int irdp_sock = -1;
 char b1[16], b2[16], b3[16], b4[16];  /* For inet_2a */
 
 extern struct zebra_t zebrad;
 extern struct thread *t_irdp_raw;
-extern struct interface *get_iflist_ifp(int idx);
 int in_cksum (void *ptr, int nbytes);
 void process_solicit (struct interface *ifp);
 
-void parse_irdp_packet(char *p, 
+static void
+parse_irdp_packet(char *p, 
                  int len, 
                  struct interface *ifp)
 {
   struct ip *ip = (struct ip *)p ;
   struct icmphdr *icmp;
   struct in_addr src;
-  int ip_hlen, ip_len;
+  int ip_hlen, iplen, datalen;
   struct zebra_if *zi;
   struct irdp_interface *irdp;
 
   zi = ifp->info;
-  if(!zi) return;
+  if (!zi) 
+    return;
 
   irdp = &zi->irdp;
-  if(!irdp) return;
+  if (!irdp) 
+    return;
 
-  ip_hlen = ip->ip_hl*4; 
-  ip_len = ntohs(ip->ip_len);
-  len = len - ip_hlen;
+  ip_hlen = ip->ip_hl << 2;
+  
+  sockopt_iphdrincl_swab_systoh (ip);
+  
+  iplen = ip->ip_len;
+  datalen = len - ip_hlen;
   src = ip->ip_src;
 
-  if(ip_len < ICMP_MINLEN) {
-    zlog_err ("IRDP: RX ICMP packet too short from %s\n",
-             inet_ntoa (src));
-    return;
-  }
+  if (len != iplen)
+    {
+      zlog_err ("IRDP: RX length doesnt match IP length");
+      return;
+    }
 
+  if (iplen < ICMP_MINLEN) 
+    {
+      zlog_err ("IRDP: RX ICMP packet too short from %s\n",
+             inet_ntoa (src));
+      return;
+    }
+    
+  /* XXX: RAW doesnt receive link-layer, surely? ??? */
   /* Check so we don't checksum packets longer than oure RX_BUF - (ethlen +
    len of IP-header) 14+20 */
-
-  if(ip_len > IRDP_RX_BUF-34) {
-    zlog_err ("IRDP: RX ICMP packet too long from %s\n",
-             inet_ntoa (src));
-    return;
-  }
-
-
-  if (in_cksum (ip, ip_len)) {
-    zlog_warn ("IRDP: RX ICMP packet from %s. Bad checksum, silently ignored",
-              inet_ntoa (src));
-    return;
-  }
+  if (iplen > IRDP_RX_BUF-34) 
+    {
+      zlog_err ("IRDP: RX ICMP packet too long from %s\n",
+               inet_ntoa (src));
+      return;
+    }
 
   icmp = (struct icmphdr *) (p+ip_hlen);
 
-
+  /* check icmp checksum */    
+  if (in_cksum (icmp, datalen) != icmp->checksum) 
+    {
+      zlog_warn ("IRDP: RX ICMP packet from %s. Bad checksum, silently ignored",
+                 inet_ntoa (src));
+      return;
+    }
+  
   /* Handle just only IRDP */
-
-  if( icmp->type == ICMP_ROUTERADVERT);
-  else if( icmp->type == ICMP_ROUTERSOLICIT);
-  else return;
-
-  if (icmp->code != 0) {
-    zlog_warn ("IRDP: RX packet type %d from %s. Bad ICMP type code, silently ignored",
-              icmp->type,
-              inet_ntoa (src));
+  if (!(icmp->type == ICMP_ROUTERADVERT
+        || icmp->type == ICMP_ROUTERSOLICIT))
     return;
-  }
-
-  if(ip->ip_dst.s_addr == INADDR_BROADCAST && 
-     irdp->flags & IF_BROADCAST);
-
-  else if ( ntohl(ip->ip_dst.s_addr) == INADDR_ALLRTRS_GROUP && 
-           ! (irdp->flags &  IF_BROADCAST));
-
-  else { /* ERROR */
-
-    zlog_warn ("IRDP: RX illegal from %s to %s while %s operates in %s\n",
-              inet_ntoa (src), 
-              ntohl(ip->ip_dst.s_addr) == INADDR_ALLRTRS_GROUP? 
-              "multicast" : inet_ntoa(ip->ip_dst),
-              ifp->name,
-              irdp->flags &  IF_BROADCAST? 
-              "broadcast" : "multicast");
+  
+  if (icmp->code != 0) 
+    {
+      zlog_warn ("IRDP: RX packet type %d from %s. Bad ICMP type code,"
+                 " silently ignored",
+                 icmp->type, inet_ntoa (src));
+      return;
+    }
 
-    zlog_warn ("IRDP: Please correct settings\n");
-    return;
-  }
+  if (! ((ntohl (ip->ip_dst.s_addr) == INADDR_BROADCAST)
+         && (irdp->flags & IF_BROADCAST))
+        ||
+        (ntohl (ip->ip_dst.s_addr) == INADDR_ALLRTRS_GROUP
+         && !(irdp->flags & IF_BROADCAST)))
+    {
+      zlog_warn ("IRDP: RX illegal from %s to %s while %s operates in %s\n",
+                 inet_ntoa (src),
+                 ntohl (ip->ip_dst.s_addr) == INADDR_ALLRTRS_GROUP ?
+                 "multicast" : inet_ntoa (ip->ip_dst),
+                 ifp->name,
+                 irdp->flags & IF_BROADCAST ? "broadcast" : "multicast");
+
+      zlog_warn ("IRDP: Please correct settings\n");
+      return;
+    }
 
   switch (icmp->type) 
     {
@@ -164,9 +173,9 @@ void parse_irdp_packet(char *p,
     case ICMP_ROUTERSOLICIT:
 
       if(irdp->flags & IF_DEBUG_MESSAGES) 
-       zlog_warn ("IRDP: RX Solicit on %s from %s\n",
-                  ifp->name,
-                  inet_ntoa (src));
+       zlog_debug ("IRDP: RX Solicit on %s from %s\n",
+                   ifp->name,
+                   inet_ntoa (src));
 
       process_solicit(ifp);
       break;
@@ -178,14 +187,11 @@ void parse_irdp_packet(char *p,
     }
 }
 \f
-int irdp_recvmsg (int sock, 
-             u_char *buf, 
-             int size, 
-             int *ifindex)
+static int
+irdp_recvmsg (int sock, u_char *buf, int size, int *ifindex)
 {
   struct msghdr msg;
   struct iovec iov;
-  struct cmsghdr *ptr;
   char adata[CMSG_SPACE( SOPT_SIZE_CMSG_PKTINFO_IPV4() )];
   int ret;
 
@@ -201,7 +207,7 @@ int irdp_recvmsg (int sock,
 
   ret = recvmsg (sock, &msg, 0);
   if (ret < 0) {
-    zlog_warn("IRDP: recvmsg: read error %s", strerror(errno));
+    zlog_warn("IRDP: recvmsg: read error %s", safe_strerror(errno));
     return ret;
   }
 
@@ -214,7 +220,7 @@ int irdp_recvmsg (int sock,
     return ret;
   }
 
-  ifindex = getsockopt_ifindex (AF_INET, &msg);
+  *ifindex = getsockopt_ifindex (AF_INET, &msg);
 
   return ret;
 }
@@ -230,11 +236,11 @@ int irdp_read_raw(struct thread *r)
   int irdp_sock = THREAD_FD (r);
   t_irdp_raw = thread_add_read (zebrad.master, irdp_read_raw, NULL, irdp_sock);
   
-  ret = irdp_recvmsg (irdp_sock, buf, IRDP_RX_BUF,  &ifindex);
+  ret = irdp_recvmsg (irdp_sock, (u_char *) buf, IRDP_RX_BUF,  &ifindex);
  
   if (ret < 0) zlog_warn ("IRDP: RX Error length = %d", ret);
 
-  ifp = get_iflist_ifp(ifindex);
+  ifp = if_lookup_by_index(ifindex);
   if(! ifp ) return ret;
 
   zi= ifp->info;
@@ -246,22 +252,23 @@ int irdp_read_raw(struct thread *r)
   if(! (irdp->flags & IF_ACTIVE)) {
 
     if(irdp->flags & IF_DEBUG_MISC) 
-      zlog_warn("IRDP: RX ICMP for disabled interface %s\n",
-               ifp->name);
+      zlog_debug("IRDP: RX ICMP for disabled interface %s\n", ifp->name);
     return 0;
   }
 
   if(irdp->flags & IF_DEBUG_PACKET) {
     int i;
-    zlog_warn("IRDP: RX (idx %d) ", ifindex);
-    for(i=0; i < ret; i++) zlog_warn( "IRDP: RX %x ", buf[i]&0xFF);
+    zlog_debug("IRDP: RX (idx %d) ", ifindex);
+    for(i=0; i < ret; i++) zlog_debug( "IRDP: RX %x ", buf[i]&0xFF);
   }
 
   parse_irdp_packet(buf, ret, ifp);
+
   return ret;
 }
 \f
-void send_packet(struct interface *ifp, 
+void 
+send_packet(struct interface *ifp, 
            struct stream *s,
            u_int32_t dst,
            struct prefix *p,
@@ -279,10 +286,13 @@ void send_packet(struct interface *ifp,
   u_long src;
   int on;
  
-  if (! (ifp->flags & IFF_UP)) return;
+  if (!(ifp->flags & IFF_UP))
+    return;
 
-  if(!p) src = ntohl(p->u.prefix4.s_addr);
-  else src = 0; /* Is filled in */
+  if (!p) 
+    src = ntohl(p->u.prefix4.s_addr);
+  else 
+    src = 0; /* Is filled in */
   
   ip = (struct ip *) buf;
   ip->ip_hl = sizeof(struct ip) >> 2;
@@ -293,34 +303,33 @@ void send_packet(struct interface *ifp,
   ip->ip_ttl = ttl;
   ip->ip_src.s_addr = src;
   ip->ip_dst.s_addr = dst;
-  icmp = (struct icmphdr *) (buf + 20);
+  icmp = (struct icmphdr *) (buf + sizeof (struct ip));
 
   /* Merge IP header with icmp packet */
-
-  stream_get(icmp, s, s->putp);
+  assert (stream_get_endp(s) < (sizeof (buf) - sizeof (struct ip)));
+  stream_get(icmp, s, stream_get_endp(s));
 
   /* icmp->checksum is already calculated */
-  ip->ip_len  = sizeof(struct ip) + s->putp;
-  stream_free(s); 
+  ip->ip_len  = sizeof(struct ip) + stream_get_endp(s);
 
   on = 1;
   if (setsockopt(irdp_sock, IPPROTO_IP, IP_HDRINCL,
                 (char *) &on, sizeof(on)) < 0)
-    zlog_warn("sendto %s", strerror (errno));
+    zlog_warn("sendto %s", safe_strerror (errno));
 
 
   if(dst == INADDR_BROADCAST ) {
     on = 1;
     if (setsockopt(irdp_sock, SOL_SOCKET, SO_BROADCAST,
                   (char *) &on, sizeof(on)) < 0)
-      zlog_warn("sendto %s", strerror (errno));
+      zlog_warn("sendto %s", safe_strerror (errno));
   }
 
   if(dst !=  INADDR_BROADCAST) {
       on = 0; 
       if( setsockopt(irdp_sock,IPPROTO_IP, IP_MULTICAST_LOOP, 
                     (char *)&on,sizeof(on)) < 0)
-       zlog_warn("sendto %s", strerror (errno));
+       zlog_warn("sendto %s", safe_strerror (errno));
   }
 
   bzero(&sockdst,sizeof(sockdst));
@@ -346,8 +355,10 @@ void send_packet(struct interface *ifp,
   msg->msg_control = cmsg;
   msg->msg_controllen = cmsg->cmsg_len;
  
+  sockopt_iphdrincl_swab_htosys (ip);
+  
   if (sendmsg(irdp_sock, msg, 0) < 0) {
-    zlog_warn("sendto %s", strerror (errno));
+    zlog_warn("sendto %s", safe_strerror (errno));
   }
   /*   printf("TX on %s idx %d\n", ifp->name, ifp->ifindex); */
 }