header file dependencies fixed up and untested changes to raw interface
[unix-history] / usr / src / sys / netinet / ip_icmp.c
index e1dc6ae..705526b 100644 (file)
-/*     ip_icmp.c       4.11    81/12/22        */
+/*     ip_icmp.c       4.18    82/09/12        */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 #include "../h/mbuf.h"
 #include "../h/protosw.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
 #include "../h/mbuf.h"
 #include "../h/protosw.h"
-#include "../h/clock.h"
+#include "../h/socket.h"
 #include "../net/in.h"
 #include "../net/in_systm.h"
 #include "../net/ip.h"
 #include "../net/ip_icmp.h"
 #include "../net/in.h"
 #include "../net/in_systm.h"
 #include "../net/ip.h"
 #include "../net/ip_icmp.h"
+#include <time.h>
+#include "../h/kernel.h"
 
 /*
  * ICMP routines: error generation, receive packet processing, and
  * routines to turnaround packets back to the originator, and
  * host table maintenance routines.
  */
 
 /*
  * ICMP routines: error generation, receive packet processing, and
  * routines to turnaround packets back to the originator, and
  * host table maintenance routines.
  */
+int    icmpprintfs = 0;
 
 /*
 
 /*
- * Generate an error packet of type error in response to bad packet ip.
+ * Generate an error packet of type error
+ * in response to bad packet ip.
  */
 icmp_error(oip, type, code)
        struct ip *oip;
  */
 icmp_error(oip, type, code)
        struct ip *oip;
-       int type;
+       int type, code;
 {
 {
-       unsigned oiplen = oip->ip_hl << 2;
-       struct icmp *icp = (struct icmp *)((int)oip + oiplen);
+       register unsigned oiplen = oip->ip_hl << 2;
+       register struct icmp *icp;
        struct mbuf *m;
        struct ip *nip;
        struct mbuf *m;
        struct ip *nip;
-COUNT(ICMP_ERROR);
 
 
+       if (icmpprintfs)
+               printf("icmp_error(%x, %d, %d)\n", oip, type, code);
        /*
         * Make sure that the old IP packet had 8 bytes of data to return;
         * if not, don't bother.  Also don't EVER error if the old
         * packet protocol was ICMP.
         */
        /*
         * Make sure that the old IP packet had 8 bytes of data to return;
         * if not, don't bother.  Also don't EVER error if the old
         * packet protocol was ICMP.
         */
-       if (oip->ip_len - oiplen < 8 || oip->ip_p == IPPROTO_ICMP)
+       if (oip->ip_len < 8 || oip->ip_p == IPPROTO_ICMP)
                goto free;
 
        /*
                goto free;
 
        /*
-        * Get a new mbuf, and fill in a ICMP header at the bottom
-        * of the mbuf, followed by the old IP header and 8 bytes
-        * of its data.
+        * First, formulate icmp message
         */
         */
-       m = m_get(0);
+       m = m_get(M_DONTWAIT);
        if (m == 0)
                goto free;
        if (m == 0)
                goto free;
-       m->m_off = MMAXOFF - (oiplen + 8);
+       m->m_len = oiplen + 8 + ICMP_MINLEN;
+       m->m_off = MMAXOFF - m->m_len;
+       icp = mtod(m, struct icmp *);
        icp->icmp_type = type;
        icp->icmp_type = type;
+       icp->icmp_void = 0;
        if (type == ICMP_PARAMPROB) {
        if (type == ICMP_PARAMPROB) {
-               icp->icmp_code = 0;
                icp->icmp_pptr = code;
                icp->icmp_pptr = code;
-       } else
-               icp->icmp_code = code;
+               code = 0;
+       }
+       icp->icmp_code = code;
        bcopy((caddr_t)oip, (caddr_t)&icp->icmp_ip, oiplen + 8);
        bcopy((caddr_t)oip, (caddr_t)&icp->icmp_ip, oiplen + 8);
+       nip = &icp->icmp_ip;
+       nip->ip_len += oiplen;
+#if vax || pdp11
+       nip->ip_len = htons((u_short)nip->ip_len);
+#endif
 
        /*
 
        /*
-        * Now prepend an IP header and reflect this packet back to
-        * the source.
+        * Now, copy old ip header in front of icmp
+        * message.  This allows us to reuse any source
+        * routing info present.
         */
         */
-       m->m_off -= sizeof (struct ip);
-       m->m_len += sizeof (struct ip);
-       nip = (struct ip *)mtod(m, struct ip *);
-       *nip = *oip;
+       m->m_off -= oiplen;
+       nip = mtod(m, struct ip *);
+       bcopy((caddr_t)oip, (caddr_t)nip, oiplen);
+       nip->ip_len = m->m_len + oiplen;
+       nip->ip_p = IPPROTO_ICMP;
+       /* icmp_send adds ip header to m_off and m_len, so we deduct here */
+       m->m_off += oiplen;
        icmp_reflect(nip);
        icmp_reflect(nip);
-       return;
 
 
-       /*
-        * Discard mbufs of original datagram
-        */
 free:
        m_freem(dtom(oip));
 }
 
 free:
        m_freem(dtom(oip));
 }
 
+static char icmpmap[] = {
+       -1,              -1,            -1,
+       PRC_UNREACH_NET, PRC_QUENCH,    PRC_REDIRECT_NET,
+       -1,              -1,            -1,
+       -1,              -1,            PRC_TIMXCEED_INTRANS,
+       PRC_PARAMPROB,   -1,            -1,
+       -1,              -1
+};
+
+static struct sockproto icmproto = { AF_INET, IPPROTO_ICMP };
+static struct sockaddr_in icmpsrc = { AF_INET };
+static struct sockaddr_in icmpdst = { AF_INET };
+
 /*
  * Process a received ICMP message.
  */
 /*
  * Process a received ICMP message.
  */
@@ -80,42 +104,54 @@ icmp_input(m)
 {
        register struct icmp *icp;
        register struct ip *ip = mtod(m, struct ip *);
 {
        register struct icmp *icp;
        register struct ip *ip = mtod(m, struct ip *);
-       int hlen = ip->ip_hl << 2;
-       int icmplen = ip->ip_len - hlen;
-       int i;
+       int icmplen = ip->ip_len, hlen = ip->ip_hl << 2, i, (*ctlfunc)();
        extern u_char ip_protox[];
        extern u_char ip_protox[];
-COUNT(ICMP_INPUT);
 
        /*
         * Locate icmp structure in mbuf, and check
         * that not corrupted and of at least minimum length.
         */
 
        /*
         * Locate icmp structure in mbuf, and check
         * that not corrupted and of at least minimum length.
         */
+       if (icmpprintfs)
+               printf("icmp_input from %x, len %d\n", ip->ip_src, icmplen);
+       if (icmplen < ICMP_MINLEN)
+               goto free;
        m->m_len -= hlen;
        m->m_off += hlen;
        /* need routine to make sure header is in this mbuf here */
        m->m_len -= hlen;
        m->m_off += hlen;
        /* need routine to make sure header is in this mbuf here */
-       icp = (struct icmp *)mtod(m, struct icmp *);
+       icp = mtod(m, struct icmp *);
        i = icp->icmp_cksum;
        icp->icmp_cksum = 0;
        i = icp->icmp_cksum;
        icp->icmp_cksum = 0;
-       if (i != in_cksum(m, icmplen) || icmplen < ICMP_MINLEN)
+       if (i != in_cksum(m, icmplen)) {
+               printf("icmp: cksum %x\n", i);
                goto free;
                goto free;
+       }
 
        /*
         * Message type specific processing.
         */
 
        /*
         * Message type specific processing.
         */
-       switch (icp->icmp_type) {
+       if (icmpprintfs)
+               printf("icmp_input, type %d code %d\n", icp->icmp_type,
+                       icp->icmp_code);
+       switch (i = icp->icmp_type) {
 
        case ICMP_UNREACH:
        case ICMP_TIMXCEED:
        case ICMP_PARAMPROB:
 
        case ICMP_UNREACH:
        case ICMP_TIMXCEED:
        case ICMP_PARAMPROB:
-       case ICMP_SOURCEQUENCH:
        case ICMP_REDIRECT:
        case ICMP_REDIRECT:
+       case ICMP_SOURCEQUENCH:
                /*
                 * Problem with previous datagram; advise
                 * higher level routines.
                 */
                /*
                 * Problem with previous datagram; advise
                 * higher level routines.
                 */
+#if vax || pdp11
+               icp->icmp_ip.ip_len = ntohs(icp->icmp_ip.ip_len);
+#endif
                if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp))
                        goto free;
                if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp))
                        goto free;
-               (*protosw[ip_protox[ip->ip_p]].pr_ctlinput)(m);
+               if (icmpprintfs)
+                       printf("deliver to protocol %d\n", icp->icmp_ip.ip_p);
+               if (ctlfunc = protosw[ip_protox[icp->icmp_ip.ip_p]].pr_ctlinput)
+                       (*ctlfunc)(icmpmap[i] + icp->icmp_code, (caddr_t)icp);
                goto free;
 
        case ICMP_ECHO:
                goto free;
 
        case ICMP_ECHO:
@@ -139,7 +175,10 @@ COUNT(ICMP_INPUT);
        case ICMP_IREQREPLY:
                if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp))
                        goto free;
        case ICMP_IREQREPLY:
                if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp))
                        goto free;
-               icmp_gotreply(icp);
+               icmpsrc.sin_addr = ip->ip_src;
+               icmpdst.sin_addr = ip->ip_dst;
+               raw_input(dtom(icp), &icmproto, (struct sockaddr *)&icmpsrc,
+                 (struct sockaddr *)&icmpdst);
                goto free;
 
        default:
                goto free;
 
        default:
@@ -153,57 +192,42 @@ free:
 
 /*
  * Reflect the ip packet back to the source
 
 /*
  * Reflect the ip packet back to the source
+ * TODO: rearrange ip source routing options.
  */
 icmp_reflect(ip)
        struct ip *ip;
 {
        struct in_addr t;
  */
 icmp_reflect(ip)
        struct ip *ip;
 {
        struct in_addr t;
-COUNT(ICMP_REFLECT);
 
 
-       t = ip->ip_src; ip->ip_dst = ip->ip_src; ip->ip_src = t;
-       /*
-        * This is a little naive... do we have to munge the options
-        * to reverse source routing?
-        */
+       t = ip->ip_dst;
+       ip->ip_dst = ip->ip_src;
+       ip->ip_src = t;
        icmp_send(ip);
 }
 
        icmp_send(ip);
 }
 
+int    generateicmpmsgs = 1;
+
 /*
 /*
- * Send an icmp packet back to the ip level, after
- * supplying a checksum.
+ * Send an icmp packet back to the ip level,
+ * after supplying a checksum.
  */
 icmp_send(ip)
        struct ip *ip;
 {
  */
 icmp_send(ip)
        struct ip *ip;
 {
-COUNT(ICMP_SEND);
-
-       m_freem(dtom(ip));
-}
-
-icmp_ctlinput(m)
-       struct mbuf *m;
-{
-COUNT(ICMP_CTLINPUT);
-
-       m_freem(m);
-}
-
-/*
- * Got a reply, e.g. to an echo message or a timestamp
- * message; nothing is done with these yet.
- */
-/*ARGSUSED*/
-icmp_gotreply(icp)
-       struct icmp *icp;
-{
-
-COUNT(ICMP_GOTREPLY);
-}
-
-icmp_drain()
-{
+       register int hlen = ip->ip_hl << 2;
+       register struct icmp *icp;
+       register struct mbuf *m = dtom(ip);
 
 
-COUNT(ICMP_DRAIN);
+       if (!generateicmpmsgs)
+               return;
+       icp = mtod(m, struct icmp *);
+       icp->icmp_cksum = 0;
+       icp->icmp_cksum = in_cksum(m, ip->ip_len - hlen);
+       m->m_off -= hlen;
+       m->m_len += hlen;
+       if (icmpprintfs)
+               printf("icmp_send dst %x src %x\n", ip->ip_dst, ip->ip_src);
+       (void) ip_output(m, 0, 0, 0);
 }
 
 n_time
 }
 
 n_time
@@ -212,8 +236,7 @@ iptime()
        int s = spl6();
        u_long t;
 
        int s = spl6();
        u_long t;
 
-COUNT(IPTIME);
-       t = (time % SECDAY) * 1000 + lbolt * hz;
+       t = (time.tv_sec % (24*60*60)) * 1000 + time.tv_usec / 1000;
        splx(s);
        return (htonl(t));
 }
        splx(s);
        return (htonl(t));
 }