lint
[unix-history] / usr / src / sys / netinet / ip_output.c
index 0ec8574..5b759ce 100644 (file)
@@ -1,25 +1,28 @@
-/*     ip_output.c     1.36    82/10/09        */
+/*     ip_output.c     1.49    83/05/27        */
 
 #include "../h/param.h"
 #include "../h/mbuf.h"
 
 #include "../h/param.h"
 #include "../h/mbuf.h"
-#include "../h/mtpr.h"
+#include "../h/errno.h"
 #include "../h/socket.h"
 #include "../h/socketvar.h"
 #include "../h/socket.h"
 #include "../h/socketvar.h"
+
+#include "../net/if.h"
+#include "../net/route.h"
+
 #include "../netinet/in.h"
 #include "../netinet/in_systm.h"
 #include "../netinet/in.h"
 #include "../netinet/in_systm.h"
-#include "../net/if.h"
 #include "../netinet/ip.h"
 #include "../netinet/ip_var.h"
 #include "../netinet/ip.h"
 #include "../netinet/ip_var.h"
-#include "../net/route.h"
-#include <errno.h>
 
 
-int    ipnorouteprint = 0;
+#ifdef vax
+#include "../vax/mtpr.h"
+#endif
 
 
-ip_output(m, opt, ro, allowbroadcast)
+ip_output(m, opt, ro, flags)
        struct mbuf *m;
        struct mbuf *opt;
        struct route *ro;
        struct mbuf *m;
        struct mbuf *opt;
        struct route *ro;
-       int allowbroadcast;
+       int flags;
 {
        register struct ip *ip = mtod(m, struct ip *);
        register struct ifnet *ifp;
 {
        register struct ip *ip = mtod(m, struct ip *);
        register struct ifnet *ifp;
@@ -32,10 +35,12 @@ ip_output(m, opt, ro, allowbroadcast)
        /*
         * Fill in IP header.
         */
        /*
         * Fill in IP header.
         */
-       ip->ip_v = IPVERSION;
        ip->ip_hl = hlen >> 2;
        ip->ip_hl = hlen >> 2;
-       ip->ip_off &= IP_DF;
-       ip->ip_id = htons(ip_id++);
+       if ((flags & IP_FORWARDING) == 0) {
+               ip->ip_v = IPVERSION;
+               ip->ip_off &= IP_DF;
+               ip->ip_id = htons(ip_id++);
+       }
 
        /*
         * Route packet.
 
        /*
         * Route packet.
@@ -49,53 +54,64 @@ ip_output(m, opt, ro, allowbroadcast)
                ro->ro_dst.sa_family = AF_INET;
                ((struct sockaddr_in *)&ro->ro_dst)->sin_addr = ip->ip_dst;
                /*
                ro->ro_dst.sa_family = AF_INET;
                ((struct sockaddr_in *)&ro->ro_dst)->sin_addr = ip->ip_dst;
                /*
-                * If routing to interface only, short circuit routing lookup.
+                * If routing to interface only,
+                * short circuit routing lookup.
                 */
                 */
-               if (ro == &routetoif) {
-                       /* check ifp is AF_INET??? */
-                       ifp = if_ifonnetof(IN_NETOF(ip->ip_dst));
-                       if (ifp == 0)
-                               goto unreachable;
+               if (flags & IP_ROUTETOIF) {
+                       ifp = if_ifonnetof(in_netof(ip->ip_dst));
+                       if (ifp == 0) {
+                               error = ENETUNREACH;
+                               goto bad;
+                       }
                        goto gotif;
                }
                rtalloc(ro);
        }
                        goto gotif;
                }
                rtalloc(ro);
        }
-       if (ro->ro_rt == 0 || (ifp = ro->ro_rt->rt_ifp) == 0)
-               goto unreachable;
+       if (ro->ro_rt == 0 || (ifp = ro->ro_rt->rt_ifp) == 0) {
+               error = ENETUNREACH;
+               goto bad;
+       }
        ro->ro_rt->rt_use++;
        if (ro->ro_rt->rt_flags & RTF_GATEWAY)
                dst = &ro->ro_rt->rt_gateway;
 gotif:
        ro->ro_rt->rt_use++;
        if (ro->ro_rt->rt_flags & RTF_GATEWAY)
                dst = &ro->ro_rt->rt_gateway;
 gotif:
+#ifndef notdef
        /*
         * If source address not specified yet, use address
         * of outgoing interface.
         */
        /*
         * If source address not specified yet, use address
         * of outgoing interface.
         */
-       if (ip->ip_src.s_addr == 0)
+       if (in_lnaof(ip->ip_src) == INADDR_ANY)
                ip->ip_src.s_addr =
                    ((struct sockaddr_in *)&ifp->if_addr)->sin_addr.s_addr;
                ip->ip_src.s_addr =
                    ((struct sockaddr_in *)&ifp->if_addr)->sin_addr.s_addr;
+#endif
 
        /*
 
        /*
-        * Have interface for packet.  Allow
-        * broadcasts only by authorized users.
+        * Look for broadcast address and
+        * and verify user is allowed to send
+        * such a packet.
         */
         */
-       if (!allowbroadcast && (ifp->if_flags & IFF_BROADCAST)) {
-               struct sockaddr_in *sin;
-
-               sin = (struct sockaddr_in *)&ifp->if_broadaddr;
-               if (sin->sin_addr.s_addr == ip->ip_dst.s_addr) {
+       if (in_lnaof(((struct sockaddr_in *)dst)->sin_addr) == INADDR_ANY) {
+               if ((ifp->if_flags & IFF_BROADCAST) == 0) {
+                       error = EADDRNOTAVAIL;
+                       goto bad;
+               }
+               if ((flags & IP_ALLOWBROADCAST) == 0) {
                        error = EACCES;
                        goto bad;
                }
                        error = EACCES;
                        goto bad;
                }
+               /* don't allow broadcast messages to be fragmented */
+               if (ip->ip_len > ifp->if_mtu) {
+                       error = EMSGSIZE;
+                       goto bad;
+               }
        }
 
        /*
         * If small enough for interface, can just send directly.
         */
        if (ip->ip_len <= ifp->if_mtu) {
        }
 
        /*
         * If small enough for interface, can just send directly.
         */
        if (ip->ip_len <= ifp->if_mtu) {
-#if vax
                ip->ip_len = htons((u_short)ip->ip_len);
                ip->ip_off = htons((u_short)ip->ip_off);
                ip->ip_len = htons((u_short)ip->ip_len);
                ip->ip_off = htons((u_short)ip->ip_off);
-#endif
                ip->ip_sum = 0;
                ip->ip_sum = in_cksum(m, hlen);
                error = (*ifp->if_output)(ifp, m, dst);
                ip->ip_sum = 0;
                ip->ip_sum = in_cksum(m, hlen);
                error = (*ifp->if_output)(ifp, m, dst);
@@ -124,7 +140,7 @@ gotif:
        m->m_len -= sizeof (struct ip);
        m->m_off += sizeof (struct ip);
        for (off = 0; off < ip->ip_len-hlen; off += len) {
        m->m_len -= sizeof (struct ip);
        m->m_off += sizeof (struct ip);
        for (off = 0; off < ip->ip_len-hlen; off += len) {
-               struct mbuf *mh = m_get(M_DONTWAIT);
+               struct mbuf *mh = m_get(M_DONTWAIT, MT_HEADER);
                struct ip *mhip;
 
                if (mh == 0) {
                struct ip *mhip;
 
                if (mh == 0) {
@@ -147,18 +163,14 @@ gotif:
                        mhip->ip_off |= IP_MF;
                }
                mhip->ip_len += sizeof (struct ip);
                        mhip->ip_off |= IP_MF;
                }
                mhip->ip_len += sizeof (struct ip);
-#if vax
                mhip->ip_len = htons((u_short)mhip->ip_len);
                mhip->ip_len = htons((u_short)mhip->ip_len);
-#endif
                mh->m_next = m_copy(m, off, len);
                if (mh->m_next == 0) {
                        (void) m_free(mh);
                        error = ENOBUFS;        /* ??? */
                        goto bad;
                }
                mh->m_next = m_copy(m, off, len);
                if (mh->m_next == 0) {
                        (void) m_free(mh);
                        error = ENOBUFS;        /* ??? */
                        goto bad;
                }
-#if vax
                mhip->ip_off = htons((u_short)mhip->ip_off);
                mhip->ip_off = htons((u_short)mhip->ip_off);
-#endif
                mhip->ip_sum = 0;
                mhip->ip_sum = in_cksum(mh, hlen);
                if (error = (*ifp->if_output)(ifp, mh, dst))
                mhip->ip_sum = 0;
                mhip->ip_sum = in_cksum(mh, hlen);
                if (error = (*ifp->if_output)(ifp, mh, dst))
@@ -167,15 +179,10 @@ gotif:
        m_freem(m);
        goto done;
 
        m_freem(m);
        goto done;
 
-unreachable:
-       if (ipnorouteprint)
-               printf("no route to %x (from %x, len %d)\n",
-                   ip->ip_dst.s_addr, ip->ip_src.s_addr, ip->ip_len);
-       error = ENETUNREACH;
 bad:
        m_freem(m);
 done:
 bad:
        m_freem(m);
 done:
-       if (ro == &iproute && ro->ro_rt)
+       if (ro == &iproute && (flags & IP_ROUTETOIF) == 0 && ro->ro_rt)
                RTFREE(ro->ro_rt);
        return (error);
 }
                RTFREE(ro->ro_rt);
        return (error);
 }