Index: lib/sockopt.c =================================================================== RCS file: /var/cvsroot/quagga/lib/sockopt.c,v retrieving revision 1.7 diff -u -r1.7 sockopt.c --- lib/sockopt.c 26 Sep 2004 16:08:11 -0000 1.7 +++ lib/sockopt.c 30 Sep 2004 13:36:45 -0000 @@ -360,3 +360,29 @@ return (ifindex = 0); } } + +/* swab iph between order system uses for IP_HDRINCL and host order */ +void +sockopt_iphdrincl_swab_htosys (struct ip *iph) +{ + /* BSD and derived take iph in network order, except for + * ip_len and ip_off + */ +#ifndef HAVE_IP_HDRINCL_BSD_ORDER + iph->ip_len = htons(iph->ip_len); + iph->ip_off = htons(iph->ip_off); +#endif /* HAVE_IP_HDRINCL_BSD_ORDER */ + + iph->ip_id = htons(iph->ip_id); +} + +void +sockopt_iphdrincl_swab_systoh (struct ip *iph) +{ +#ifndef HAVE_IP_HDRINCL_BSD_ORDER + iph->ip_len = ntohs(iph->ip_len); + iph->ip_off = ntohs(iph->ip_off); +#endif /* HAVE_IP_HDRINCL_BSD_ORDER */ + + iph->ip_id = ntohs(iph->ip_id); +} Index: lib/sockopt.h =================================================================== RCS file: /var/cvsroot/quagga/lib/sockopt.h,v retrieving revision 1.6 diff -u -r1.6 sockopt.h --- lib/sockopt.h 17 Sep 2004 08:39:08 -0000 1.6 +++ lib/sockopt.h 30 Sep 2004 13:36:45 -0000 @@ -92,4 +92,11 @@ /* Ask for, and get, ifindex, by whatever method is supported. */ int setsockopt_ifindex (int, int, int); int getsockopt_ifindex (int, struct msghdr *); + +/* swab the fields in iph between the host order and system order expected + * for IP_HDRINCL. + */ +void sockopt_iphdrincl_swab_htosys (struct ip *iph); +void sockopt_iphdrincl_swab_systoh (struct ip *iph); + #endif /*_ZEBRA_SOCKOPT_H */ Index: lib/ChangeLog =================================================================== RCS file: /var/cvsroot/quagga/lib/ChangeLog,v retrieving revision 1.36 diff -u -r1.36 ChangeLog --- lib/ChangeLog 27 Sep 2004 12:46:37 -0000 1.36 +++ lib/ChangeLog 30 Sep 2004 13:36:48 -0000 @@ -1,3 +1,9 @@ +2004-09-30 Paul Jakma + + * sockopt.{c,h}: add sockopt_iphdrincl_swab_{htosys,systoh}, + functions to change byte order between system IP_HDRINCL order + and host order. + 2004-09-27 Paul Jakma * zebra.h: Add WANT_OSPF_WRITE_FRAGMENT for ospfd Index: ospfd/ChangeLog =================================================================== RCS file: /var/cvsroot/quagga/ospfd/ChangeLog,v retrieving revision 1.49 diff -u -r1.49 ChangeLog --- ospfd/ChangeLog 27 Sep 2004 12:56:30 -0000 1.49 +++ ospfd/ChangeLog 30 Sep 2004 13:36:52 -0000 @@ -1,3 +1,8 @@ +2004-09-30 Paul Jakma + + * ospf_packet.c: replace ospf_swap_iph_to... with + sockopt_iphdrincl_swab_... + 2004-09-27 Paul Jakma * ospf_dump.c: (ospf_ip_header_dump) Use HAVE_IP_HDRINCL_BSD_ORDER Index: ospfd/ospf_dump.c =================================================================== RCS file: /var/cvsroot/quagga/ospfd/ospf_dump.c,v retrieving revision 1.9 diff -u -r1.9 ospf_dump.c --- ospfd/ospf_dump.c 27 Sep 2004 12:56:30 -0000 1.9 +++ ospfd/ospf_dump.c 30 Sep 2004 13:36:52 -0000 @@ -607,14 +607,8 @@ iph = (struct ip *) STREAM_PNT (s); -#ifdef HAVE_IP_HDRINCL_BSD_ORDER - length = iph->ip_len; - offset = iph->ip_off; -#else /* !HAVE_IP_HDRINCL_BSD_ORDER */ - length = ntohs (iph->ip_len); - offset = ntohs (iph->ip_off); -#endif /* HAVE_IP_HDRINCL_BSD_ORDER */ - + sockopt_iphdrincl_swab_systoh (iph); + /* IP Header dump. */ zlog_info ("ip_v %d", iph->ip_v); zlog_info ("ip_hl %d", iph->ip_hl); Index: ospfd/ospf_packet.c =================================================================== RCS file: /var/cvsroot/quagga/ospfd/ospf_packet.c,v retrieving revision 1.42 diff -u -r1.42 ospf_packet.c --- ospfd/ospf_packet.c 27 Sep 2004 12:56:30 -0000 1.42 +++ ospfd/ospf_packet.c 30 Sep 2004 13:36:56 -0000 @@ -482,33 +482,6 @@ return 0; } -/* swab ip header fields to required order for sendmsg */ -void -ospf_swab_iph_ton (struct ip *iph) -{ - /* BSD and derived take iph in network order, except for - * ip_len and ip_off - */ -#ifndef HAVE_IP_HDRINCL_BSD_ORDER - iph->ip_len = htons(iph->ip_len); - iph->ip_off = htons(iph->ip_off); -#endif /* HAVE_IP_HDRINCL_BSD_ORDER */ - - iph->ip_id = htons(iph->ip_id); -} - -/* swab ip header fields to host order, as required */ -void -ospf_swab_iph_toh (struct ip *iph) -{ -#ifdef HAVE_IP_HDRINCL_BSD_ORDER - iph->ip_len = ntohs(iph->ip_len); - iph->ip_off = ntohs(iph->ip_off); -#endif /* HAVE_IP_HDRINCL_BSD_ORDER */ - - iph->ip_id = ntohs(iph->ip_id); -} - #ifdef WANT_OSPF_WRITE_FRAGMENT void ospf_write_frags (int fd, struct ospf_packet *op, struct ip *iph, @@ -549,11 +522,11 @@ iph->ip_len = iov[1]->iov_len + sizeof (struct ip); assert (iph->ip_len <= mtu); - ospf_swab_iph_ton (iph); + sockopt_iphdrincl_swab_htosys (iph); ret = sendmsg (fd, msg, flags); - ospf_swab_iph_toh (iph); + sockopt_iphdrincl_swab_systoh (iph); if (ret < 0) zlog_warn ("*** sendmsg in ospf_write to %s," @@ -692,9 +665,9 @@ #endif /* WANT_OSPF_WRITE_FRAGMENT */ /* send final fragment (could be first) */ - ospf_swab_iph_ton (&iph); + sockopt_iphdrincl_swab_htosys (&iph); ret = sendmsg (ospf->fd, &msg, flags); - ospf_swab_iph_toh (&iph); + sockopt_iphdrincl_swab_htosys (&iph); if (ret < 0) zlog_warn ("*** sendmsg in ospf_write to %s failed with %s", @@ -2040,13 +2013,9 @@ zlog_warn ("ospf_recv_packet packet smaller than ip header"); return NULL; } - -#ifdef HAVE_IP_HDRINCL_BSD_ORDER - ip_len = iph.ip_len; -#else - ip_len = ntohs (iph.ip_len); -#endif - + + sockopt_iphdrincl_swab_systoh (&iph); + #if !defined(GNU_LINUX) && (OpenBSD < 200311) /* * Kernel network code touches incoming IP header parameters, Index: zebra/ChangeLog =================================================================== RCS file: /var/cvsroot/quagga/zebra/ChangeLog,v retrieving revision 1.37 diff -u -r1.37 ChangeLog --- zebra/ChangeLog 26 Sep 2004 16:09:34 -0000 1.37 +++ zebra/ChangeLog 30 Sep 2004 13:36:57 -0000 @@ -1,3 +1,17 @@ +2004-09-24 Paul Jakma + + * irdp_packet.c: (parse_irdp_packet) style issues. + Use sockopt_iphdrincl_swab_systoh. + Try unbork the code. Checksum the ICMP data and actually + compare it to received checksum. Check data length against + claimed length in header. + Always use ntoh.. when accessing addresses, even when the + comparison happens to be endian-safe. + (send_packet) minor style isues. Use + sockopt_iphdrincl_swab_htosys. + (irdp_iph_hton/ntoh) IP header to/from network/host order. + + 2004-09-26 Hasso Tepper * irdp_interface.c, irdp_main.c, irdp_packet.c, rt_netlink.c, Index: zebra/irdp_packet.c =================================================================== RCS file: /var/cvsroot/quagga/zebra/irdp_packet.c,v retrieving revision 1.5 diff -u -r1.5 irdp_packet.c --- zebra/irdp_packet.c 26 Sep 2004 16:09:34 -0000 1.5 +++ zebra/irdp_packet.c 30 Sep 2004 13:36:59 -0000 @@ -82,79 +82,88 @@ 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 */ + + 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: 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 (! ((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; - } + zlog_warn ("IRDP: Please correct settings\n"); + return; + } switch (icmp->type) { @@ -182,7 +191,6 @@ { struct msghdr msg; struct iovec iov; - struct cmsghdr *ptr; char adata[CMSG_SPACE( SOPT_SIZE_CMSG_PKTINFO_IPV4() )]; int ret; @@ -255,10 +263,12 @@ } parse_irdp_packet(buf, ret, ifp); + return ret; } -void send_packet(struct interface *ifp, +void +send_packet(struct interface *ifp, struct stream *s, u_int32_t dst, struct prefix *p, @@ -276,10 +286,13 @@ 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; @@ -290,7 +303,7 @@ 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 */ @@ -343,6 +356,8 @@ 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)); }