correct bounds check; don't fall off IP header if optlen is bogus
[unix-history] / usr / src / sys / netinet / ip_input.c
index 4277165..1867ef3 100644 (file)
@@ -1,25 +1,25 @@
-/*     ip_input.c      6.1     83/07/29        */
-
-#include "../h/param.h"
-#include "../h/systm.h"
-#include "../h/mbuf.h"
-#include "../h/domain.h"
-#include "../h/protosw.h"
-#include "../h/socket.h"
-#include "../h/errno.h"
-#include "../h/time.h"
-#include "../h/kernel.h"
+/*     ip_input.c      6.8     84/12/20        */
+
+#include "param.h"
+#include "systm.h"
+#include "mbuf.h"
+#include "domain.h"
+#include "protosw.h"
+#include "socket.h"
+#include "errno.h"
+#include "time.h"
+#include "kernel.h"
 
 #include "../net/if.h"
 #include "../net/route.h"
 
 
 #include "../net/if.h"
 #include "../net/route.h"
 
-#include "../netinet/in.h"
-#include "../netinet/in_pcb.h"
-#include "../netinet/in_systm.h"
-#include "../netinet/ip.h"
-#include "../netinet/ip_var.h"
-#include "../netinet/ip_icmp.h"
-#include "../netinet/tcp.h"
+#include "in.h"
+#include "in_pcb.h"
+#include "in_systm.h"
+#include "ip.h"
+#include "ip_var.h"
+#include "ip_icmp.h"
+#include "tcp.h"
 
 u_char ip_protox[IPPROTO_MAX];
 int    ipqmaxlen = IFQ_MAXLEN;
 
 u_char ip_protox[IPPROTO_MAX];
 int    ipqmaxlen = IFQ_MAXLEN;
@@ -40,8 +40,8 @@ ip_init()
        for (i = 0; i < IPPROTO_MAX; i++)
                ip_protox[i] = pr - inetsw;
        for (pr = inetdomain.dom_protosw;
        for (i = 0; i < IPPROTO_MAX; i++)
                ip_protox[i] = pr - inetsw;
        for (pr = inetdomain.dom_protosw;
-           pr <= inetdomain.dom_protoswNPROTOSW; pr++)
-               if (pr->pr_family == PF_INET &&
+           pr < inetdomain.dom_protoswNPROTOSW; pr++)
+               if (pr->pr_domain->dom_family == PF_INET &&
                    pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW)
                        ip_protox[pr->pr_protocol] = pr - inetsw;
        ipq.next = ipq.prev = &ipq;
                    pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW)
                        ip_protox[pr->pr_protocol] = pr - inetsw;
        ipq.next = ipq.prev = &ipq;
@@ -125,6 +125,7 @@ next:
        if (i != 0) {
                if (i < 0) {
                        ipstat.ips_tooshort++;
        if (i != 0) {
                if (i < 0) {
                        ipstat.ips_tooshort++;
+                       m = m0;
                        goto bad;
                }
                if (i <= m->m_len)
                        goto bad;
                }
                if (i <= m->m_len)
@@ -158,20 +159,6 @@ next:
                    sin->sin_addr.s_addr == ip->ip_dst.s_addr)
                        goto ours;
        }
                    sin->sin_addr.s_addr == ip->ip_dst.s_addr)
                        goto ours;
        }
-/* BEGIN GROT */
-#include "nd.h"
-#if NND > 0
-       /*
-        * Diskless machines don't initially know
-        * their address, so take packets from them
-        * if we're acting as a network disk server.
-        */
-       if (in_netof(ip->ip_dst) == INADDR_ANY &&
-           (in_netof(ip->ip_src) == INADDR_ANY &&
-            in_lnaof(ip->ip_src) != INADDR_ANY))
-               goto ours;
-#endif
-/* END GROT */
        ipaddr.sin_addr = ip->ip_dst;
        if (if_ifwithaddr((struct sockaddr *)&ipaddr) == 0) {
                ip_forward(ip);
        ipaddr.sin_addr = ip->ip_dst;
        if (if_ifwithaddr((struct sockaddr *)&ipaddr) == 0) {
                ip_forward(ip);
@@ -462,8 +449,11 @@ ip_dooptions(ip)
                        break;
                if (opt == IPOPT_NOP)
                        optlen = 1;
                        break;
                if (opt == IPOPT_NOP)
                        optlen = 1;
-               else
+               else {
                        optlen = cp[1];
                        optlen = cp[1];
+                       if (optlen <= 0 || optlen >= cnt)
+                               goto bad;
+               }
                switch (opt) {
 
                default:
                switch (opt) {
 
                default:
@@ -568,18 +558,18 @@ ip_stripoptions(ip, mopt)
        if (mopt) {
                mopt->m_len = olen;
                mopt->m_off = MMINOFF;
        if (mopt) {
                mopt->m_len = olen;
                mopt->m_off = MMINOFF;
-               bcopy((caddr_t)ip, mtod(m, caddr_t), (unsigned)olen);
+               bcopy((caddr_t)ip, mtod(mopt, caddr_t), (unsigned)olen);
        }
        i = m->m_len - (sizeof (struct ip) + olen);
        bcopy((caddr_t)ip+olen, (caddr_t)ip, (unsigned)i);
        m->m_len -= olen;
 }
 
        }
        i = m->m_len - (sizeof (struct ip) + olen);
        bcopy((caddr_t)ip+olen, (caddr_t)ip, (unsigned)i);
        m->m_len -= olen;
 }
 
-u_char inetctlerrmap[] = {
+u_char inetctlerrmap[PRC_NCMDS] = {
        ECONNABORTED,   ECONNABORTED,   0,              0,
        ECONNABORTED,   ECONNABORTED,   0,              0,
-       0,              0,
-       EHOSTDOWN,      EHOSTUNREACH,   ENETUNREACH,    EHOSTUNREACH,
-       ECONNREFUSED,   ECONNREFUSED,   EMSGSIZE,       0,
+       0,              0,              EHOSTDOWN,      EHOSTUNREACH,
+       ENETUNREACH,    EHOSTUNREACH,   ECONNREFUSED,   ECONNREFUSED,
+       EMSGSIZE,       0,              0,              0,
        0,              0,              0,              0
 };
 
        0,              0,              0,              0
 };
 
@@ -588,7 +578,7 @@ ip_ctlinput(cmd, arg)
        caddr_t arg;
 {
        struct in_addr *in;
        caddr_t arg;
 {
        struct in_addr *in;
-       int tcp_abort(), udp_abort();
+       int in_rtchange(), tcp_abort(), udp_abort();
        extern struct inpcb tcb, udb;
 
        if (cmd < 0 || cmd > PRC_NCMDS)
        extern struct inpcb tcb, udb;
 
        if (cmd < 0 || cmd > PRC_NCMDS)
@@ -601,9 +591,14 @@ ip_ctlinput(cmd, arg)
                in = (struct in_addr *)arg;
        else
                in = &((struct icmp *)arg)->icmp_ip.ip_dst;
                in = (struct in_addr *)arg;
        else
                in = &((struct icmp *)arg)->icmp_ip.ip_dst;
-/* THIS IS VERY QUESTIONABLE, SHOULD HIT ALL PROTOCOLS */
-       in_pcbnotify(&tcb, in, (int)inetctlerrmap[cmd], tcp_abort);
-       in_pcbnotify(&udb, in, (int)inetctlerrmap[cmd], udp_abort);
+       /* THIS IS VERY QUESTIONABLE, SHOULD HIT ALL PROTOCOLS */
+       if (cmd == PRC_REDIRECT_NET || cmd == PRC_REDIRECT_HOST) {
+               in_pcbnotify(&tcb, in, 0, in_rtchange);
+               in_pcbnotify(&udb, in, 0, in_rtchange);
+       } else {
+               in_pcbnotify(&tcb, in, (int)inetctlerrmap[cmd], tcp_abort);
+               in_pcbnotify(&udb, in, (int)inetctlerrmap[cmd], udp_abort);
+       }
 }
 
 int    ipprintfs = 0;
 }
 
 int    ipprintfs = 0;