Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/netinet PR/25622: IPV6 return RST and through cloned int...



details:   https://anonhg.NetBSD.org/src/rev/9f15065e121b
branches:  trunk
changeset: 566768:9f15065e121b
user:      christos <christos%NetBSD.org@localhost>
date:      Thu May 20 13:55:31 2004 +0000

description:
PR/25622: IPV6 return RST and through cloned interfaces was broken.
- checksum was computed incorrectly.
- ipv6 packet was not initialized properly.
- fixed code to be more similar to the v4 counterpart.

diffstat:

 sys/netinet/fil.c           |    7 +-
 sys/netinet/ip_fil_netbsd.c |  142 ++++++++++++++++++++++++++-----------------
 2 files changed, 89 insertions(+), 60 deletions(-)

diffs (truncated from 376 to 300 lines):

diff -r dd0680196d65 -r 9f15065e121b sys/netinet/fil.c
--- a/sys/netinet/fil.c Thu May 20 13:54:19 2004 +0000
+++ b/sys/netinet/fil.c Thu May 20 13:55:31 2004 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: fil.c,v 1.64 2004/05/10 01:34:59 christos Exp $        */
+/*     $NetBSD: fil.c,v 1.65 2004/05/20 13:55:31 christos Exp $        */
 
 /*
  * Copyright (C) 1993-2003 by Darren Reed.
@@ -135,7 +135,7 @@
 #if !defined(lint)
 #if defined(__NetBSD__)
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fil.c,v 1.64 2004/05/10 01:34:59 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fil.c,v 1.65 2004/05/20 13:55:31 christos Exp $");
 #else
 static const char sccsid[] = "@(#)fil.c        1.36 6/5/96 (C) 1993-2000 Darren Reed";
 static const char rcsid[] = "@(#)Id: fil.c,v 2.243.2.7 2004/03/23 12:06:56 darrenr Exp";
@@ -2657,7 +2657,7 @@
                ip6 = (ip6_t *)ip;
                hlen = sizeof(*ip6);
                slen = ntohs(ip6->ip6_plen);
-               sum = htons((u_short)ip6->ip6_nxt);
+               sum = htons((u_short)l4proto);
                sum += htons(slen);
                sp = (u_short *)&ip6->ip6_src;
                sum += *sp++;   /* ip6_src */
@@ -2675,6 +2675,7 @@
                sum += *sp++;
                sum += *sp++;
                sum += *sp++;
+               sum += *sp++;
        }
 #endif
 
diff -r dd0680196d65 -r 9f15065e121b sys/netinet/ip_fil_netbsd.c
--- a/sys/netinet/ip_fil_netbsd.c       Thu May 20 13:54:19 2004 +0000
+++ b/sys/netinet/ip_fil_netbsd.c       Thu May 20 13:55:31 2004 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ip_fil_netbsd.c,v 1.9 2004/05/18 21:47:45 christos Exp $       */
+/*     $NetBSD: ip_fil_netbsd.c,v 1.10 2004/05/20 13:55:32 christos Exp $      */
 
 /*
  * Copyright (C) 1993-2003 by Darren Reed.
@@ -693,8 +693,6 @@
 
        m = m_gethdr(M_DONTWAIT, MT_HEADER);
        if (m == NULL)
-               return ENOBUFS;
-       if (m == NULL)
                return -1;
 
        tlen = fin->fin_dlen - (TCP_OFF(tcp) << 2) +
@@ -716,23 +714,32 @@
 #endif
        bzero((char *)ip, sizeof(*tcp2) + hlen);
        tcp2 = (struct tcphdr *)((char *)ip + hlen);
-
        tcp2->th_sport = tcp->th_dport;
        tcp2->th_dport = tcp->th_sport;
+
        if (tcp->th_flags & TH_ACK) {
                tcp2->th_seq = tcp->th_ack;
                tcp2->th_flags = TH_RST;
+               tcp2->th_ack = 0;
        } else {
+               tcp2->th_seq = 0;
                tcp2->th_ack = ntohl(tcp->th_seq);
                tcp2->th_ack += tlen;
                tcp2->th_ack = htonl(tcp2->th_ack);
                tcp2->th_flags = TH_RST|TH_ACK;
        }
+       tcp2->th_x2 = 0;
        TCP_OFF_A(tcp2, sizeof(*tcp2) >> 2);
+       tcp2->th_win = tcp->th_win;
+       tcp2->th_sum = 0;
+       tcp2->th_urp = 0;
+
 #ifdef USE_INET6
        if (fin->fin_v == 6) {
+               ip6->ip6_flow = 0;
                ip6->ip6_plen = htons(sizeof(struct tcphdr));
                ip6->ip6_nxt = IPPROTO_TCP;
+               ip6->ip6_hlim = 0;
                ip6->ip6_src = fin->fin_dst6;
                ip6->ip6_dst = fin->fin_src6;
                tcp2->th_sum = in6_cksum(m, IPPROTO_TCP,
@@ -750,6 +757,26 @@
 }
 
 
+/* ------------------------------------------------------------------------ */
+/* Function:    fr_nextipid                                                 */
+/* Returns:     int - 0 == success, -1 == error (packet should be droppped) */
+/* Parameters:  fin(I) - pointer to packet information                      */
+/*                                                                          */
+/* Returns the next IPv4 ID to use for this packet.                         */
+/* ------------------------------------------------------------------------ */
+INLINE u_short fr_nextipid(fin)
+fr_info_t *fin;
+{
+       static u_short ipid = 0;
+       u_short id;
+
+       MUTEX_ENTER(&ipf_rw);
+       id = ipid++;
+       MUTEX_EXIT(&ipf_rw);
+
+       return id;
+}
+
 static int fr_send_ip(fin, m, mpp)
 fr_info_t *fin;
 mb_t *m, **mpp;
@@ -765,7 +792,7 @@
                oip = fin->fin_ip;
                IP_HL_A(ip, sizeof(*oip) >> 2);
                ip->ip_tos = oip->ip_tos;
-               ip->ip_id = fin->fin_ip->ip_id;
+               ip->ip_id = fr_nextipid(fin);
                ip->ip_off = ip_mtudisc ? IP_DF : 0;
                ip->ip_ttl = ip_defttl;
                ip->ip_sum = 0;
@@ -775,7 +802,10 @@
        {
                ip6_t *ip6 = (ip6_t *)ip;
 
+               ip6->ip6_vfc = 0x60;
                ip6->ip6_hlim = IPDEFTTL;
+
+               break;
        }
 #endif
        default :
@@ -793,7 +823,7 @@
 fr_info_t *fin;
 int dst;
 {
-       int err, hlen, xtra, ohlen, iclen, avail, code;
+       int err, hlen, xtra, iclen, ohlen, avail, code;
        struct in_addr dst4;
        struct icmp *icmp;
        struct mbuf *m;
@@ -841,7 +871,7 @@
                avail = MHLEN;
                m = m_gethdr(M_DONTWAIT, MT_HEADER);
                if (m == NULL)
-                       return ENOBUFS;
+                       return -1;
 
                if (dst == 0) {
                        if (fr_ifpaddr(4, FRI_NORMAL, ifp,
@@ -853,6 +883,7 @@
                        dst4.s_addr = fin->fin_daddr;
 
                hlen = sizeof(ip_t);
+               ohlen = fin->fin_hlen;
                if (fin->fin_hlen < fin->fin_plen)
                        xtra = MIN(fin->fin_dlen, 8);
                else
@@ -869,13 +900,13 @@
 
                MGETHDR(m, M_DONTWAIT, MT_HEADER);
                if (m == NULL)
-                       return ENOBUFS;
+                       return -1;
 
                MCLGET(m, M_DONTWAIT);
                if (m == NULL)
-                       return ENOBUFS;
+                       return -1;
                avail = (m->m_flags & M_EXT) ? MCLBYTES : MHLEN;
-               xtra = MIN(fin->fin_plen + sizeof(ip6_t),
+               xtra = MIN(fin->fin_plen,
                           avail - hlen - sizeof(*icmp) - max_linkhdr);
                if (dst == 0) {
                        if (fr_ifpaddr(6, FRI_NORMAL, ifp,
@@ -887,6 +918,8 @@
                        dst6 = fin->fin_dst6;
        }
 #endif
+       else
+               return -1;
 
        iclen = hlen + sizeof(*icmp) + xtra;
        avail -= (max_linkhdr + iclen);
@@ -898,13 +931,12 @@
        m->m_pkthdr.len = iclen;
        if (avail < 0) {
                m_freem(m);
-               return ENOBUFS;
+               return -1;
        }
        m->m_len = iclen;
        ip = mtod(m, ip_t *);
        icmp = (struct icmp *)((char *)ip + hlen);
        ip2 = (ip_t *)&icmp->icmp_ip;
-       bzero((char *)ip, iclen);
 
        icmp->icmp_type = type;
        icmp->icmp_code = fin->fin_icode;
@@ -915,7 +947,7 @@
                icmp->icmp_nextmtu = htons(((struct ifnet *)ifp)->if_mtu);
 #endif
 
-       bcopy((char *)fin->fin_ip, (char *)ip2, fin->fin_hlen);
+       bcopy((char *)fin->fin_ip, (char *)ip2, ohlen);
 
 #if defined(M_CSUM_IPv4)
        /*
@@ -928,7 +960,6 @@
        ip6 = (ip6_t *)ip;
        if (fin->fin_v == 6) {
                ip62 = (ip6_t *)ip2;
-               ip62->ip6_plen = htons(ip62->ip6_plen);
 
                ip6->ip6_flow = 0;
                ip6->ip6_plen = htons(iclen - hlen);
@@ -944,15 +975,13 @@
        } else
 #endif
        {
-               ip2->ip_len = htons(ip2->ip_len);
-
                ip->ip_p = IPPROTO_ICMP;
                ip->ip_src.s_addr = dst4.s_addr;
                ip->ip_dst.s_addr = fin->fin_saddr;
 
                if (xtra > 0)
-                       bcopy(fin->fin_dp,
-                             (char *)&icmp->icmp_ip + fin->fin_hlen, xtra);
+                       bcopy((char *)fin->fin_ip + ohlen,
+                             (char *)&icmp->icmp_ip + ohlen, xtra);
                icmp->icmp_cksum = ipf_cksum((u_short *)icmp,
                                             sizeof(*icmp) + 8);
                ip->ip_len = iclen;
@@ -1026,7 +1055,7 @@
        dst->sin_addr = ip->ip_dst;
 
        fr = fin->fin_fr;
-       if (fdp)
+       if (fdp != NULL)
                ifp = fdp->fd_ifp;
        else
                ifp = fin->fin_ifp;
@@ -1082,8 +1111,22 @@
 
                        (void) fr_checkstate(fin, &pass);
                }
-               (void) fr_checknatout(fin, NULL);
+
+               switch (fr_checknatout(fin, NULL))
+               {
+               case 0 :
+                       break;
+               case 1 :
+                       ip->ip_sum = 0;
+                       break;
+               case -1 :
+                       error = -1;
+                       goto done;
+                       break;
+               }
+
                fin->fin_ifp = sifp;
+               fin->fin_out = 0;
        } else
                ip->ip_sum = 0;
        /*
@@ -1238,7 +1281,7 @@
        dst6 = (struct sockaddr_in6 *)&ro->ro_dst;
        dst6->sin6_family = AF_INET6;
        dst6->sin6_len = sizeof(struct sockaddr_in6);
-       dst6->sin6_addr = fin->fin_fi.fi_dst.in6;
+       dst6->sin6_addr = fin->fin_fi.fi_src.in6;
 
        if (fdp != NULL)
                ifp = fdp->fd_ifp;
@@ -1252,43 +1295,44 @@
                if (IP6_NOTZERO(&fdp->fd_ip6))
                        dst6->sin6_addr = fdp->fd_ip6.in6;
        }
-       if (ifp == NULL)
-               return EHOSTUNREACH;
 
-       /* KAME */
-       if (IN6_IS_ADDR_LINKLOCAL(&dst6->sin6_addr))
-               dst6->sin6_addr.s6_addr16[1] = htons(ifp->if_index);
        rtalloc((struct route *)ro);
 
        if ((ifp == NULL) && (ro->ro_rt != NULL))
                ifp = ro->ro_rt->rt_ifp;
 
-       if ((ro->ro_rt == NULL) || (ifp == NULL) ||
-           (ifp != ro->ro_rt->rt_ifp)) {
+       if ((ro->ro_rt == NULL) || (ifp == NULL)) {
                error = EHOSTUNREACH;
-       } else {
+               goto bad;
+       }



Home | Main Index | Thread Index | Old Index