localize header files
[unix-history] / usr / src / sys / netinet / ip_input.c
index ae0f881..cf9864f 100644 (file)
@@ -1,18 +1,19 @@
-/*     ip_input.c      1.41    82/04/24        */
+/*     ip_input.c      1.51    82/10/09        */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
-#include "../h/clock.h"
 #include "../h/mbuf.h"
 #include "../h/protosw.h"
 #include "../h/socket.h"
 #include "../h/mbuf.h"
 #include "../h/protosw.h"
 #include "../h/socket.h"
-#include "../net/in.h"
-#include "../net/in_systm.h"
+#include "../netinet/in.h"
+#include "../netinet/in_systm.h"
 #include "../net/if.h"
 #include "../net/if.h"
-#include "../net/ip.h"                 /* belongs before in.h */
-#include "../net/ip_var.h"
-#include "../net/ip_icmp.h"
-#include "../net/tcp.h"
+#include "../netinet/ip.h"                     /* belongs before in.h */
+#include "../netinet/ip_var.h"
+#include "../netinet/ip_icmp.h"
+#include "../netinet/tcp.h"
+#include <time.h>
+#include "../h/kernel.h"
 #include <errno.h>
 
 u_char ip_protox[IPPROTO_MAX];
 #include <errno.h>
 
 u_char ip_protox[IPPROTO_MAX];
@@ -28,7 +29,6 @@ ip_init()
        register struct protosw *pr;
        register int i;
 
        register struct protosw *pr;
        register int i;
 
-COUNT(IP_INIT);
        pr = pffindproto(PF_INET, IPPROTO_RAW);
        if (pr == 0)
                panic("ip_init");
        pr = pffindproto(PF_INET, IPPROTO_RAW);
        if (pr == 0)
                panic("ip_init");
@@ -39,7 +39,7 @@ COUNT(IP_INIT);
                    pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW)
                        ip_protox[pr->pr_protocol] = pr - protosw;
        ipq.next = ipq.prev = &ipq;
                    pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW)
                        ip_protox[pr->pr_protocol] = pr - protosw;
        ipq.next = ipq.prev = &ipq;
-       ip_id = time & 0xffff;
+       ip_id = time.tv_sec & 0xffff;
        ipintrq.ifq_maxlen = ipqmaxlen;
        ifinet = if_ifwithaf(AF_INET);
 }
        ipintrq.ifq_maxlen = ipqmaxlen;
        ifinet = if_ifwithaf(AF_INET);
 }
@@ -62,7 +62,6 @@ ipintr()
        register struct ipq *fp;
        int hlen, s;
 
        register struct ipq *fp;
        int hlen, s;
 
-COUNT(IPINTR);
 next:
        /*
         * Get next datagram off input queue and get IP header
 next:
        /*
         * Get next datagram off input queue and get IP header
@@ -220,7 +219,6 @@ ip_reass(ip, fp)
        struct mbuf *t;
        int hlen = ip->ip_hl << 2;
        int i, next;
        struct mbuf *t;
        int hlen = ip->ip_hl << 2;
        int i, next;
-COUNT(IP_REASS);
 
        /*
         * Presence of header sizes in mbufs
 
        /*
         * Presence of header sizes in mbufs
@@ -235,7 +233,6 @@ COUNT(IP_REASS);
        if (fp == 0) {
                if ((t = m_get(M_WAIT)) == NULL)
                        goto dropfrag;
        if (fp == 0) {
                if ((t = m_get(M_WAIT)) == NULL)
                        goto dropfrag;
-               t->m_off = MMINOFF;
                fp = mtod(t, struct ipq *);
                insque(fp, &ipq);
                fp->ipq_ttl = IPFRAGTTL;
                fp = mtod(t, struct ipq *);
                insque(fp, &ipq);
                fp->ipq_ttl = IPFRAGTTL;
@@ -350,7 +347,6 @@ ip_freef(fp)
 {
        register struct ipasfrag *q;
        struct mbuf *m;
 {
        register struct ipasfrag *q;
        struct mbuf *m;
-COUNT(IP_FREEF);
 
        for (q = fp->ipq_next; q != (struct ipasfrag *)fp; q = q->ipf_next)
                m_freem(dtom(q));
 
        for (q = fp->ipq_next; q != (struct ipasfrag *)fp; q = q->ipf_next)
                m_freem(dtom(q));
@@ -369,7 +365,6 @@ ip_enq(p, prev)
        register struct ipasfrag *p, *prev;
 {
 
        register struct ipasfrag *p, *prev;
 {
 
-COUNT(IP_ENQ);
        p->ipf_prev = prev;
        p->ipf_next = prev->ipf_next;
        prev->ipf_next->ipf_prev = p;
        p->ipf_prev = prev;
        p->ipf_next = prev->ipf_next;
        prev->ipf_next->ipf_prev = p;
@@ -383,7 +378,6 @@ ip_deq(p)
        register struct ipasfrag *p;
 {
 
        register struct ipasfrag *p;
 {
 
-COUNT(IP_DEQ);
        p->ipf_prev->ipf_next = p->ipf_next;
        p->ipf_next->ipf_prev = p->ipf_prev;
 }
        p->ipf_prev->ipf_next = p->ipf_next;
        p->ipf_next->ipf_prev = p->ipf_prev;
 }
@@ -398,7 +392,6 @@ ip_slowtimo()
        register struct ipq *fp;
        int s = splnet();
 
        register struct ipq *fp;
        int s = splnet();
 
-COUNT(IP_SLOWTIMO);
        fp = ipq.next;
        if (fp == 0) {
                splx(s);
        fp = ipq.next;
        if (fp == 0) {
                splx(s);
@@ -418,7 +411,6 @@ COUNT(IP_SLOWTIMO);
 ip_drain()
 {
 
 ip_drain()
 {
 
-COUNT(IP_DRAIN);
        while (ipq.next != &ipq)
                (void) ip_freef(ipq.next);
 }
        while (ipq.next != &ipq)
                (void) ip_freef(ipq.next);
 }
@@ -438,7 +430,6 @@ ip_dooptions(ip)
        register struct ifnet *ifp;
        struct in_addr t;
 
        register struct ifnet *ifp;
        struct in_addr t;
 
-COUNT(IP_DOOPTIONS);
        cp = (u_char *)(ip + 1);
        cnt = (ip->ip_hl << 2) - sizeof (struct ip);
        for (; cnt > 0; cnt -= optlen, cp += optlen) {
        cp = (u_char *)(ip + 1);
        cnt = (ip->ip_hl << 2) - sizeof (struct ip);
        for (; cnt > 0; cnt -= optlen, cp += optlen) {
@@ -464,6 +455,7 @@ COUNT(IP_DOOPTIONS);
                 * address on directly accessible net.
                 */
                case IPOPT_LSRR:
                 * address on directly accessible net.
                 */
                case IPOPT_LSRR:
+               case IPOPT_SSRR:
                        if (cp[2] < 4 || cp[2] > optlen - (sizeof (long) - 1))
                                break;
                        sin = (struct in_addr *)(cp + cp[2]);
                        if (cp[2] < 4 || cp[2] > optlen - (sizeof (long) - 1))
                                break;
                        sin = (struct in_addr *)(cp + cp[2]);
@@ -481,7 +473,7 @@ COUNT(IP_DOOPTIONS);
                                break;
                        ip->ip_dst = sin[1];
                        if (opt == IPOPT_SSRR &&
                                break;
                        ip->ip_dst = sin[1];
                        if (opt == IPOPT_SSRR &&
-                           if_ifonnetof(ip->ip_dst.s_net) == 0)
+                           if_ifonnetof(in_netof(ip->ip_dst)) == 0)
                                goto bad;
                        break;
 
                                goto bad;
                        break;
 
@@ -545,7 +537,6 @@ ip_stripoptions(ip, mopt)
        register int i;
        register struct mbuf *m;
        int olen;
        register int i;
        register struct mbuf *m;
        int olen;
-COUNT(IP_STRIPOPTIONS);
 
        olen = (ip->ip_hl<<2) - sizeof (struct ip);
        m = dtom(ip);
 
        olen = (ip->ip_hl<<2) - sizeof (struct ip);
        m = dtom(ip);
@@ -560,14 +551,10 @@ COUNT(IP_STRIPOPTIONS);
        m->m_len -= olen;
 }
 
        m->m_len -= olen;
 }
 
-static u_char ctlerrmap[] = {
+u_char inetctlerrmap[] = {
        ECONNABORTED,   ECONNABORTED,   0,              0,
        ECONNABORTED,   ECONNABORTED,   0,              0,
-       0,
-#ifdef notdef
-       EHOSTUNREACH,   EHOSTDOWN,      ENETUNREACH,    EHOSTUNREACH,
-#else
-       ENETUNREACH,    ENETUNREACH,    ENETUNREACH,    ENETUNREACH,
-#endif
+       0,              0,
+       EHOSTDOWN,      EHOSTUNREACH,   ENETUNREACH,    EHOSTUNREACH,
        ECONNREFUSED,   ECONNREFUSED,   EMSGSIZE,       0,
        0,              0,              0,              0
 };
        ECONNREFUSED,   ECONNREFUSED,   EMSGSIZE,       0,
        0,              0,              0,              0
 };
@@ -577,12 +564,12 @@ ip_ctlinput(cmd, arg)
        caddr_t arg;
 {
        struct in_addr *sin;
        caddr_t arg;
 {
        struct in_addr *sin;
-       extern int tcp_abort(), udp_abort();
+       int tcp_abort(), udp_abort();
        extern struct inpcb tcb, udb;
 
        if (cmd < 0 || cmd > PRC_NCMDS)
                return;
        extern struct inpcb tcb, udb;
 
        if (cmd < 0 || cmd > PRC_NCMDS)
                return;
-       if (ctlerrmap[cmd] == 0)
+       if (inetctlerrmap[cmd] == 0)
                return;         /* XXX */
        if (cmd == PRC_IFDOWN)
                sin = &((struct sockaddr_in *)arg)->sin_addr;
                return;         /* XXX */
        if (cmd == PRC_IFDOWN)
                sin = &((struct sockaddr_in *)arg)->sin_addr;
@@ -590,8 +577,8 @@ ip_ctlinput(cmd, arg)
                sin = (struct in_addr *)arg;
        else
                sin = &((struct icmp *)arg)->icmp_ip.ip_dst;
                sin = (struct in_addr *)arg;
        else
                sin = &((struct icmp *)arg)->icmp_ip.ip_dst;
-       in_pcbnotify(&tcb, sin, ctlerrmap[cmd], tcp_abort);
-       in_pcbnotify(&udb, sin, ctlerrmap[cmd], udp_abort);
+       in_pcbnotify(&tcb, sin, inetctlerrmap[cmd], tcp_abort);
+       in_pcbnotify(&udb, sin, inetctlerrmap[cmd], udp_abort);
 }
 
 int    ipprintfs = 0;
 }
 
 int    ipprintfs = 0;
@@ -606,7 +593,7 @@ ip_forward(ip)
        register struct ip *ip;
 {
        register int error, type, code;
        register struct ip *ip;
 {
        register int error, type, code;
-       struct mbuf *mopt;
+       struct mbuf *mopt, *mcopy;
 
        if (ipprintfs)
                printf("forward: src %x dst %x ttl %x\n", ip->ip_src,
 
        if (ipprintfs)
                printf("forward: src %x dst %x ttl %x\n", ip->ip_src,
@@ -626,27 +613,46 @@ ip_forward(ip)
                m_freem(dtom(ip));
                return;
        }
                m_freem(dtom(ip));
                return;
        }
+
+       /*
+        * Save at most 64 bytes of the packet in case
+        * we need to generate an ICMP message to the src.
+        */
+       mcopy = m_copy(dtom(ip), 0, imin(ip->ip_len, 64));
        ip_stripoptions(ip, mopt);
 
        /* last 0 here means no directed broadcast */
        ip_stripoptions(ip, mopt);
 
        /* last 0 here means no directed broadcast */
-       if ((error = ip_output(dtom(ip), mopt, 0, 0)) == 0)
+       if ((error = ip_output(dtom(ip), mopt, 0, 0)) == 0) {
+               if (mcopy)
+                       m_freem(mcopy);
                return;
                return;
-#ifdef notdef
-       /*
-        * Want to generate a message, but lower
-        * layers assume they can free up a message
-        * in the event of an error.  This causes
-        * the call to icmp_error to work on ``freed''
-        * mbuf's, and worse.
-        */
-       type = ICMP_UNREACH, code = 0;  /* need ``undefined'' */
-       if (error == ENETUNREACH || error == ENETDOWN)
+       }
+       ip = mtod(mcopy, struct ip *);
+       type = ICMP_UNREACH, code = 0;          /* need ``undefined'' */
+       switch (error) {
+
+       case ENETUNREACH:
+       case ENETDOWN:
                code = ICMP_UNREACH_NET;
                code = ICMP_UNREACH_NET;
-       else if (error == EMSGSIZE)
+               break;
+
+       case EMSGSIZE:
                code = ICMP_UNREACH_NEEDFRAG;
                code = ICMP_UNREACH_NEEDFRAG;
-#else
-       return;
-#endif
+               break;
+
+       case EPERM:
+               code = ICMP_UNREACH_PORT;
+               break;
+
+       case ENOBUFS:
+               type = ICMP_SOURCEQUENCH;
+               break;
+
+       case EHOSTDOWN:
+       case EHOSTUNREACH:
+               code = ICMP_UNREACH_HOST;
+               break;
+       }
 sendicmp:
        icmp_error(ip, type, code);
 }
 sendicmp:
        icmp_error(ip, type, code);
 }