new stats; change keepalives to use rcv_nxt instead of rcv_nxt-1
[unix-history] / usr / src / sys / netinet / ip_output.c
index 58fb8ca..a40cf06 100644 (file)
@@ -1,9 +1,9 @@
 /*
 /*
- * Copyright (c) 1982 Regents of the University of California.
+ * Copyright (c) 1982, 1986 Regents of the University of California.
  * All rights reserved.  The Berkeley software License Agreement
  * specifies the terms and conditions for redistribution.
  *
  * All rights reserved.  The Berkeley software License Agreement
  * specifies the terms and conditions for redistribution.
  *
- *     @(#)ip_output.c 6.10 (Berkeley) %G%
+ *     @(#)ip_output.c 7.2 (Berkeley) %G%
  */
 
 #include "param.h"
  */
 
 #include "param.h"
@@ -24,7 +24,7 @@
 #include "ip_var.h"
 
 #ifdef vax
 #include "ip_var.h"
 
 #ifdef vax
-#include "../vax/mtpr.h"
+#include "../machine/mtpr.h"
 #endif
 
 struct mbuf *ip_insertoptions();
 #endif
 
 struct mbuf *ip_insertoptions();
@@ -68,40 +68,46 @@ ip_output(m, opt, ro, flags)
                bzero((caddr_t)ro, sizeof (*ro));
        }
        dst = (struct sockaddr_in *)&ro->ro_dst;
                bzero((caddr_t)ro, sizeof (*ro));
        }
        dst = (struct sockaddr_in *)&ro->ro_dst;
+       /*
+        * If there is a cached route,
+        * check that it is to the same destination
+        * and is still up.  If not, free it and try again.
+        */
+       if (ro->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 ||
+          dst->sin_addr.s_addr != ip->ip_dst.s_addr)) {
+               RTFREE(ro->ro_rt);
+               ro->ro_rt = (struct rtentry *)0;
+       }
        if (ro->ro_rt == 0) {
                dst->sin_family = AF_INET;
                dst->sin_addr = ip->ip_dst;
        if (ro->ro_rt == 0) {
                dst->sin_family = AF_INET;
                dst->sin_addr = ip->ip_dst;
-               /*
-                * If routing to interface only,
-                * short circuit routing lookup.
-                */
-               if (flags & IP_ROUTETOIF) {
-                       struct in_ifaddr *ia;
+       }
+       /*
+        * If routing to interface only,
+        * short circuit routing lookup.
+        */
+       if (flags & IP_ROUTETOIF) {
+               struct in_ifaddr *ia;
+
+               ia = (struct in_ifaddr *)ifa_ifwithdstaddr(dst);
+               if (ia == 0)
                        ia = in_iaonnetof(in_netof(ip->ip_dst));
                        ia = in_iaonnetof(in_netof(ip->ip_dst));
-                       if (ia == 0) {
-                               error = ENETUNREACH;
-                               goto bad;
-                       }
-                       ifp = ia->ia_ifp;
-                       goto gotif;
+               if (ia == 0) {
+                       error = ENETUNREACH;
+                       goto bad;
                }
                }
-               rtalloc(ro);
-       } else if ((ro->ro_rt->rt_flags & RTF_UP) == 0) {
-               /*
-                * The old route has gone away; try for a new one.
-                */
-               rtfree(ro->ro_rt);
-               ro->ro_rt = NULL;
-               rtalloc(ro);
-       }
-       if (ro->ro_rt == 0 || (ifp = ro->ro_rt->rt_ifp) == 0) {
-               error = ENETUNREACH;
-               goto bad;
+               ifp = ia->ia_ifp;
+       } else {
+               if (ro->ro_rt == 0)
+                       rtalloc(ro);
+               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|RTF_HOST))
+                       dst = (struct sockaddr_in *)&ro->ro_rt->rt_gateway;
        }
        }
-       ro->ro_rt->rt_use++;
-       if (ro->ro_rt->rt_flags & (RTF_GATEWAY|RTF_HOST))
-               dst = (struct sockaddr_in *)&ro->ro_rt->rt_gateway;
-gotif:
 #ifndef notdef
        /*
         * If source address not specified yet, use address
 #ifndef notdef
        /*
         * If source address not specified yet, use address
@@ -187,7 +193,7 @@ gotif:
                        mh->m_len = sizeof (struct ip) + olen;
                } else
                        mh->m_len = sizeof (struct ip);
                        mh->m_len = sizeof (struct ip) + olen;
                } else
                        mh->m_len = sizeof (struct ip);
-               mhip->ip_off = off >> 3;
+               mhip->ip_off = (off >> 3) + (ip->ip_off & ~IP_MF);
                if (ip->ip_off & IP_MF)
                        mhip->ip_off |= IP_MF;
                if (off + len >= ip->ip_len-hlen)
                if (ip->ip_off & IP_MF)
                        mhip->ip_off |= IP_MF;
                if (off + len >= ip->ip_len-hlen)
@@ -232,7 +238,7 @@ ip_insertoptions(m, opt, phlen)
        register struct ipoption *p = mtod(opt, struct ipoption *);
        struct mbuf *n;
        register struct ip *ip = mtod(m, struct ip *);
        register struct ipoption *p = mtod(opt, struct ipoption *);
        struct mbuf *n;
        register struct ip *ip = mtod(m, struct ip *);
-       int optlen;
+       unsigned optlen;
 
        optlen = opt->m_len - sizeof(p->ipopt_dst);
        if (p->ipopt_dst.s_addr)
 
        optlen = opt->m_len - sizeof(p->ipopt_dst);
        if (p->ipopt_dst.s_addr)
@@ -254,7 +260,7 @@ ip_insertoptions(m, opt, phlen)
                ovbcopy((caddr_t)ip, mtod(m, caddr_t), sizeof(struct ip));
        }
        ip = mtod(m, struct ip *);
                ovbcopy((caddr_t)ip, mtod(m, caddr_t), sizeof(struct ip));
        }
        ip = mtod(m, struct ip *);
-       bcopy((caddr_t)p->ipopt_list, (caddr_t)(ip + 1), optlen);
+       bcopy((caddr_t)p->ipopt_list, (caddr_t)(ip + 1), (unsigned)optlen);
        *phlen = sizeof(struct ip) + optlen;
        ip->ip_len += optlen;
        return (m);
        *phlen = sizeof(struct ip) + optlen;
        ip->ip_len += optlen;
        return (m);
@@ -330,7 +336,7 @@ ip_ctloutput(op, so, level, optname, m)
                                (*m)->m_off = inp->inp_options->m_off;
                                (*m)->m_len = inp->inp_options->m_len;
                                bcopy(mtod(inp->inp_options, caddr_t),
                                (*m)->m_off = inp->inp_options->m_off;
                                (*m)->m_len = inp->inp_options->m_len;
                                bcopy(mtod(inp->inp_options, caddr_t),
-                                   mtod(*m, caddr_t), (*m)->m_len);
+                                   mtod(*m, caddr_t), (unsigned)(*m)->m_len);
                        } else
                                (*m)->m_len = 0;
                        break;
                        } else
                                (*m)->m_len = 0;
                        break;
@@ -341,7 +347,7 @@ ip_ctloutput(op, so, level, optname, m)
                break;
        }
        if (op == PRCO_SETOPT)
                break;
        }
        if (op == PRCO_SETOPT)
-               m_free(*m);
+               (void)m_free(*m);
        return (error);
 }
 
        return (error);
 }
 
@@ -360,14 +366,14 @@ ip_pcbopts(pcbopt, m)
 
        /* turn off any old options */
        if (*pcbopt)
 
        /* turn off any old options */
        if (*pcbopt)
-               m_free(*pcbopt);
+               (void)m_free(*pcbopt);
        *pcbopt = 0;
        if (m == (struct mbuf *)0 || m->m_len == 0) {
                /*
                 * Only turning off any previous options.
                 */
                if (m)
        *pcbopt = 0;
        if (m == (struct mbuf *)0 || m->m_len == 0) {
                /*
                 * Only turning off any previous options.
                 */
                if (m)
-                       m_free(m);
+                       (void)m_free(m);
                return (0);
        }
 
                return (0);
        }
 
@@ -390,7 +396,7 @@ ip_pcbopts(pcbopt, m)
        cnt = m->m_len;
        m->m_len += sizeof(struct in_addr);
        cp = mtod(m, u_char *) + sizeof(struct in_addr);
        cnt = m->m_len;
        m->m_len += sizeof(struct in_addr);
        cp = mtod(m, u_char *) + sizeof(struct in_addr);
-       ovbcopy(mtod(m, caddr_t), cp, cnt);
+       ovbcopy(mtod(m, caddr_t), (caddr_t)cp, (unsigned)cnt);
        bzero(mtod(m, caddr_t), sizeof(struct in_addr));
 
        for (; cnt > 0; cnt -= optlen, cp += optlen) {
        bzero(mtod(m, caddr_t), sizeof(struct in_addr));
 
        for (; cnt > 0; cnt -= optlen, cp += optlen) {
@@ -428,14 +434,16 @@ ip_pcbopts(pcbopt, m)
                        /*
                         * Move first hop before start of options.
                         */
                        /*
                         * Move first hop before start of options.
                         */
-                       bcopy(&cp[IPOPT_OFFSET+1], mtod(m, caddr_t),
+                       bcopy((caddr_t)&cp[IPOPT_OFFSET+1], mtod(m, caddr_t),
                            sizeof(struct in_addr));
                        /*
                         * Then copy rest of options back
                         * to close up the deleted entry.
                         */
                            sizeof(struct in_addr));
                        /*
                         * Then copy rest of options back
                         * to close up the deleted entry.
                         */
-                       ovbcopy(&cp[IPOPT_OFFSET+1] + sizeof(struct in_addr),
-                           &cp[IPOPT_OFFSET+1], cnt + sizeof(struct in_addr));
+                       ovbcopy((caddr_t)(&cp[IPOPT_OFFSET+1] +
+                           sizeof(struct in_addr)),
+                           (caddr_t)&cp[IPOPT_OFFSET+1],
+                           (unsigned)cnt + sizeof(struct in_addr));
                        break;
                }
        }
                        break;
                }
        }
@@ -443,6 +451,6 @@ ip_pcbopts(pcbopt, m)
        return (0);
 
 bad:
        return (0);
 
 bad:
-       m_free(m);
+       (void)m_free(m);
        return (EINVAL);
 }
        return (EINVAL);
 }