64-bit changes -- ioctl cmds are u_longs.
[unix-history] / usr / src / sys / netns / ns_ip.c
index 50bc857..a4cf595 100644 (file)
@@ -1,9 +1,10 @@
 /*
 /*
- * Copyright (c) 1985 Regents of the University of California.
- * All rights reserved.  The Berkeley software License Agreement
- * specifies the terms and conditions for redistribution.
+ * Copyright (c) 1984, 1985, 1986, 1987, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  *
- *     @(#)ns_ip.c     6.10 (Berkeley) %G%
+ * %sccs.include.redist.c%
+ *
+ *     @(#)ns_ip.c     8.2 (Berkeley) %G%
  */
 
 /*
  */
 
 /*
  */
 
 #ifdef NSIP
  */
 
 #ifdef NSIP
-#include "param.h"
-#include "systm.h"
-#include "mbuf.h"
-#include "socket.h"
-#include "socketvar.h"
-#include "errno.h"
-#include "ioctl.h"
-#include "protosw.h"
-
-#include "../net/if.h"
-#include "../net/netisr.h"
-#include "../net/route.h"
-
-#include "../netinet/in.h"
-#include "../netinet/in_systm.h"
-#include "../netinet/in_var.h"
-#include "../netinet/ip.h"
-#include "../netinet/ip_var.h"
-
-#ifdef vax
-#include "../vax/mtpr.h"
-#endif
-
-#include "../netns/ns.h"
-#include "../netns/ns_if.h"
-#include "../netns/idp.h"
-
-#ifdef BBNNET
-#include "../bbnnet/in_pcb.h"
-#include "../bbnnet/nopcb.h"
-#endif
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/errno.h>
+#include <sys/ioctl.h>
+#include <sys/protosw.h>
+
+#include <net/if.h>
+#include <net/netisr.h>
+#include <net/route.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+
+#include <machine/mtpr.h>
+
+#include <netns/ns.h>
+#include <netns/ns_if.h>
+#include <netns/idp.h>
 
 struct ifnet_en {
        struct ifnet ifen_ifnet;
        struct route ifen_route;
        struct in_addr ifen_src;
        struct in_addr ifen_dst;
 
 struct ifnet_en {
        struct ifnet ifen_ifnet;
        struct route ifen_route;
        struct in_addr ifen_src;
        struct in_addr ifen_dst;
+       struct ifnet_en *ifen_next;
 };
 
 };
 
-int    nsipoutput(), nsipioctl();
+int    nsipoutput(), nsipioctl(), nsipstart();
 #define LOMTU  (1024+512);
 
 struct ifnet nsipif;
 #define LOMTU  (1024+512);
 
 struct ifnet nsipif;
-union ns_net nsip_net;
-struct mbuf *nsip_list;                /* list of all hosts and gateways or
+struct ifnet_en *nsip_list;            /* list of all hosts and gateways or
                                        broadcast addrs */
 
                                        broadcast addrs */
 
-struct mbuf *
+struct ifnet_en *
 nsipattach()
 {
 nsipattach()
 {
-       register struct mbuf *m = m_getclr(M_DONTWAIT, MT_PCB);
+       register struct ifnet_en *m;
        register struct ifnet *ifp;
 
        register struct ifnet *ifp;
 
-       if (m==0) return (0);
-       m->m_off = MMINOFF;
-       m->m_len = sizeof(struct ifnet_en);
-       m->m_next = nsip_list;
+       if (nsipif.if_mtu == 0) {
+               ifp = &nsipif;
+               ifp->if_name = "nsip";
+               ifp->if_mtu = LOMTU;
+               ifp->if_ioctl = nsipioctl;
+               ifp->if_output = nsipoutput;
+               ifp->if_start = nsipstart;
+               ifp->if_flags = IFF_POINTOPOINT;
+       }
+
+       MALLOC((m), struct ifnet_en *, sizeof(*m), M_PCB, M_NOWAIT);
+       if (m == NULL) return (NULL);
+       m->ifen_next = nsip_list;
        nsip_list = m;
        nsip_list = m;
-       ifp = mtod(m, struct ifnet *);
+       ifp = &m->ifen_ifnet;
 
        ifp->if_name = "nsip";
        ifp->if_mtu = LOMTU;
        ifp->if_ioctl = nsipioctl;
        ifp->if_output = nsipoutput;
 
        ifp->if_name = "nsip";
        ifp->if_mtu = LOMTU;
        ifp->if_ioctl = nsipioctl;
        ifp->if_output = nsipoutput;
+       ifp->if_start = nsipstart;
        ifp->if_flags = IFF_POINTOPOINT;
        ifp->if_unit = nsipif.if_unit++;
        if_attach(ifp);
        ifp->if_flags = IFF_POINTOPOINT;
        ifp->if_unit = nsipif.if_unit++;
        if_attach(ifp);
-       return(dtom(ifp));
+
+       return (m);
 }
 
 
 }
 
 
@@ -98,6 +104,9 @@ nsipioctl(ifp, cmd, data)
 
        case SIOCSIFADDR:
                ifp->if_flags |= IFF_UP;
 
        case SIOCSIFADDR:
                ifp->if_flags |= IFF_UP;
+               /* fall into: */
+
+       case SIOCSIFDSTADDR:
                /*
                 * Everything else is done at a higher level.
                 */
                /*
                 * Everything else is done at a higher level.
                 */
@@ -128,49 +137,48 @@ idpip_input(m, ifp)
        register struct ifqueue *ifq = &nsintrq;
        int len, s;
 
        register struct ifqueue *ifq = &nsintrq;
        int len, s;
 
-       if(nsip_hold_input) {
-               if(nsip_lastin) {
+       if (nsip_hold_input) {
+               if (nsip_lastin) {
                        m_freem(nsip_lastin);
                }
                        m_freem(nsip_lastin);
                }
-               nsip_lastin = m_copy(m, 0, (int)M_COPYALL);
+               nsip_lastin = m_copym(m, 0, (int)M_COPYALL, M_DONTWAIT);
        }
        /*
         * Get IP and IDP header together in first mbuf.
         */
        nsipif.if_ipackets++;
        s = sizeof (struct ip) + sizeof (struct idp);
        }
        /*
         * Get IP and IDP header together in first mbuf.
         */
        nsipif.if_ipackets++;
        s = sizeof (struct ip) + sizeof (struct idp);
-       if ((m->m_off > MMAXOFF || m->m_len < s) &&
-           (m = m_pullup(m, s))==0) {
+       if (((m->m_flags & M_EXT) || m->m_len < s) &&
+           (m = m_pullup(m, s)) == 0) {
                nsipif.if_ierrors++;
                return;
        }
        ip = mtod(m, struct ip *);
                nsipif.if_ierrors++;
                return;
        }
        ip = mtod(m, struct ip *);
-#ifndef        BBNNET
        if (ip->ip_hl > (sizeof (struct ip) >> 2)) {
        if (ip->ip_hl > (sizeof (struct ip) >> 2)) {
-               ip_stripoptions(ip, (struct mbuf *)0);
+               ip_stripoptions(m, (struct mbuf *)0);
                if (m->m_len < s) {
                if (m->m_len < s) {
-                       if ((m = m_pullup(m, s))==0) {
+                       if ((m = m_pullup(m, s)) == 0) {
                                nsipif.if_ierrors++;
                                return;
                        }
                        ip = mtod(m, struct ip *);
                }
        }
                                nsipif.if_ierrors++;
                                return;
                        }
                        ip = mtod(m, struct ip *);
                }
        }
-#endif
 
        /*
         * Make mbuf data length reflect IDP length.
         * If not enough data to reflect IDP length, drop.
         */
 
        /*
         * Make mbuf data length reflect IDP length.
         * If not enough data to reflect IDP length, drop.
         */
-       m->m_off += sizeof (struct ip);
+       m->m_data += sizeof (struct ip);
        m->m_len -= sizeof (struct ip);
        m->m_len -= sizeof (struct ip);
+       m->m_pkthdr.len -= sizeof (struct ip);
        idp = mtod(m, struct idp *);
        len = ntohs(idp->idp_len);
        if (len & 1) len++;             /* Preserve Garbage Byte */
        if (ip->ip_len != len) {
                if (len > ip->ip_len) {
                        nsipif.if_ierrors++;
        idp = mtod(m, struct idp *);
        len = ntohs(idp->idp_len);
        if (len & 1) len++;             /* Preserve Garbage Byte */
        if (ip->ip_len != len) {
                if (len > ip->ip_len) {
                        nsipif.if_ierrors++;
-                       if(nsip_badlen) m_freem(nsip_badlen);
+                       if (nsip_badlen) m_freem(nsip_badlen);
                        nsip_badlen = m;
                        return;
                }
                        nsip_badlen = m;
                        return;
                }
@@ -181,22 +189,7 @@ idpip_input(m, ifp)
         * Place interface pointer before the data
         * for the receiving protocol.
         */
         * Place interface pointer before the data
         * for the receiving protocol.
         */
-       if (m->m_off >= MMINOFF + sizeof(struct ifnet *)) {
-               m->m_off -= sizeof(struct ifnet *);
-               m->m_len += sizeof(struct ifnet *);
-       } else {
-               struct mbuf *n;
-
-               n = m_get(M_DONTWAIT, MT_HEADER);
-               if (n == (struct mbuf *)0)
-                       goto bad;
-               n->m_off = MMINOFF;
-               n->m_len = sizeof(struct ifnet *);
-               n->m_next = m;
-               m = n;
-       }
-       *(mtod(m, struct ifnet **)) = ifp;
-
+       m->m_pkthdr.rcvif = ifp;
        /*
         * Deliver to NS
         */
        /*
         * Deliver to NS
         */
@@ -215,23 +208,18 @@ bad:
 }
 
 /* ARGSUSED */
 }
 
 /* ARGSUSED */
-nsipoutput(ifn, m0, dst)
+nsipoutput(ifn, m, dst)
        struct ifnet_en *ifn;
        struct ifnet_en *ifn;
-       struct mbuf *m0;
+       register struct mbuf *m;
        struct sockaddr *dst;
 {
 
        struct sockaddr *dst;
 {
 
-       register struct mbuf *m = dtom(ifn);
        register struct ip *ip;
        register struct route *ro = &(ifn->ifen_route);
        register int len = 0;
        register struct ip *ip;
        register struct route *ro = &(ifn->ifen_route);
        register int len = 0;
-       register struct idp *idp = mtod(m0, struct idp *);
+       register struct idp *idp = mtod(m, struct idp *);
        int error;
 
        int error;
 
-       if (m->m_len != sizeof(struct ifnet_en)) {
-               printf("nsipoutput: bad dst ifp %x\n", ifn);
-               goto bad;
-       }
        ifn->ifen_ifnet.if_opackets++;
        nsipif.if_opackets++;
 
        ifn->ifen_ifnet.if_opackets++;
        nsipif.if_opackets++;
 
@@ -242,19 +230,24 @@ nsipoutput(ifn, m0, dst)
         */
        len =  ntohs(idp->idp_len);
        if (len & 1) len++;             /* Preserve Garbage Byte */
         */
        len =  ntohs(idp->idp_len);
        if (len & 1) len++;             /* Preserve Garbage Byte */
-       m = m0;
-       if(m->m_off < MMINOFF + sizeof (struct ip)) {
-               m = m_get(M_DONTWAIT, MT_HEADER);
-               if (m == 0) {
-                       m_freem(m0);
+       /* following clause not necessary on vax */
+       if (3 & (int)m->m_data) {
+               /* force longword alignment of ip hdr */
+               struct mbuf *m0 = m_gethdr(MT_HEADER, M_DONTWAIT);
+               if (m0 == 0) {
+                       m_freem(m);
                        return (ENOBUFS);
                }
                        return (ENOBUFS);
                }
-               m->m_off = MMAXOFF - sizeof (struct ip);
-               m->m_len = sizeof (struct ip);
-               m->m_next = m0;
+               MH_ALIGN(m0, sizeof (struct ip));
+               m0->m_flags = m->m_flags & M_COPYFLAGS;
+               m0->m_next = m;
+               m0->m_len = sizeof (struct ip);
+               m0->m_pkthdr.len = m0->m_len + m->m_len;
+               m->m_flags &= ~M_PKTHDR;
        } else {
        } else {
-               m->m_off -= sizeof (struct ip);
-               m->m_len += sizeof (struct ip);
+               M_PREPEND(m, sizeof (struct ip), M_DONTWAIT);
+               if (m == 0)
+                       return (ENOBUFS);
        }
        /*
         * Fill in IP header.
        }
        /*
         * Fill in IP header.
@@ -264,26 +257,27 @@ nsipoutput(ifn, m0, dst)
        ip->ip_p = IPPROTO_IDP;
        ip->ip_src = ifn->ifen_src;
        ip->ip_dst = ifn->ifen_dst;
        ip->ip_p = IPPROTO_IDP;
        ip->ip_src = ifn->ifen_src;
        ip->ip_dst = ifn->ifen_dst;
-#ifdef BBNNET
-       ip->ip_tos = 0;
-       NOPCB_IPSEND(m, len, 0, error);
-#else
        ip->ip_len = (u_short)len + sizeof (struct ip);
        ip->ip_ttl = MAXTTL;
 
        /*
         * Output final datagram.
         */
        ip->ip_len = (u_short)len + sizeof (struct ip);
        ip->ip_ttl = MAXTTL;
 
        /*
         * Output final datagram.
         */
-       error =  (ip_output(m, (struct mbuf *)0, ro, SO_BROADCAST));
-#endif
+       error =  (ip_output(m, (struct mbuf *)0, ro, SO_BROADCAST, NULL));
        if (error) {
                ifn->ifen_ifnet.if_oerrors++;
                ifn->ifen_ifnet.if_ierrors = error;
        }
        return (error);
 bad:
        if (error) {
                ifn->ifen_ifnet.if_oerrors++;
                ifn->ifen_ifnet.if_ierrors = error;
        }
        return (error);
 bad:
-       m_freem(m0);
-       return(ENETUNREACH);
+       m_freem(m);
+       return (ENETUNREACH);
+}
+
+nsipstart(ifp)
+struct ifnet *ifp;
+{
+       panic("nsip_start called\n");
 }
 
 struct ifreq ifr = {"nsip0"};
 }
 
 struct ifreq ifr = {"nsip0"};
@@ -297,8 +291,14 @@ nsip_route(m)
        struct route ro;
        struct ifnet_en *ifn;
        struct sockaddr_in *src;
        struct route ro;
        struct ifnet_en *ifn;
        struct sockaddr_in *src;
+
        /*
        /*
-        * First, determine if we can get to the destination
+        * First, make sure we already have an ns address:
+        */
+       if (ns_hosteqnh(ns_thishost, ns_zerohost))
+               return (EADDRNOTAVAIL);
+       /*
+        * Now, determine if we can get to the destination
         */
        bzero((caddr_t)&ro, sizeof (ro));
        ro.ro_dst = *(struct sockaddr *)ip_dst;
         */
        bzero((caddr_t)&ro, sizeof (ro));
        ro.ro_dst = *(struct sockaddr *)ip_dst;
@@ -306,8 +306,10 @@ nsip_route(m)
        if (ro.ro_rt == 0 || ro.ro_rt->rt_ifp == 0) {
                return (ENETUNREACH);
        }
        if (ro.ro_rt == 0 || ro.ro_rt->rt_ifp == 0) {
                return (ENETUNREACH);
        }
+
        /*
         * And see how he's going to get back to us:
        /*
         * And see how he's going to get back to us:
+        * i.e., what return ip address do we use?
         */
        {
                register struct in_ifaddr *ia;
         */
        {
                register struct in_ifaddr *ia;
@@ -319,24 +321,25 @@ nsip_route(m)
                if (ia == 0)
                        ia = in_ifaddr;
                if (ia == 0) {
                if (ia == 0)
                        ia = in_ifaddr;
                if (ia == 0) {
+                       RTFREE(ro.ro_rt);
                        return (EADDRNOTAVAIL);
                }
                src = (struct sockaddr_in *)&ia->ia_addr;
        }
                        return (EADDRNOTAVAIL);
                }
                src = (struct sockaddr_in *)&ia->ia_addr;
        }
+
        /*
         * Is there a free (pseudo-)interface or space?
         */
        /*
         * Is there a free (pseudo-)interface or space?
         */
-       for (m = nsip_list; m; m = m->m_next) {
-               struct ifnet *ifp = mtod(m, struct ifnet *);
-               if ((ifp->if_flags & IFF_UP) == 0)
+       for (ifn = nsip_list; ifn; ifn = ifn->ifen_next) {
+               if ((ifn->ifen_ifnet.if_flags & IFF_UP) == 0)
                        break;
        }
                        break;
        }
-       if (m == (struct mbuf *) 0)
-               m = nsipattach();
-       if (m==NULL) {return (ENOBUFS);}
-       ifn = mtod(m, struct ifnet_en *);
-
-       ro.ro_rt->rt_use++;
+       if (ifn == NULL)
+               ifn = nsipattach();
+       if (ifn == NULL) {
+               RTFREE(ro.ro_rt);
+               return (ENOBUFS);
+       }
        ifn->ifen_route = ro;
        ifn->ifen_dst =  ip_dst->sin_addr;
        ifn->ifen_src = src->sin_addr;
        ifn->ifen_route = ro;
        ifn->ifen_dst =  ip_dst->sin_addr;
        ifn->ifen_src = src->sin_addr;
@@ -346,7 +349,10 @@ nsip_route(m)
         */
        ifr.ifr_name[4] = '0' + nsipif.if_unit - 1;
        ifr.ifr_dstaddr = * (struct sockaddr *) ns_dst;
         */
        ifr.ifr_name[4] = '0' + nsipif.if_unit - 1;
        ifr.ifr_dstaddr = * (struct sockaddr *) ns_dst;
-       return(ns_control((struct socket *)0, (int)SIOCSIFADDR, (caddr_t)&ifr,
+       (void)ns_control((struct socket *)0, SIOCSIFDSTADDR, (caddr_t)&ifr,
+                       (struct ifnet *)ifn);
+       satons_addr(ifr.ifr_addr).x_host = ns_thishost;
+       return (ns_control((struct socket *)0, SIOCSIFADDR, (caddr_t)&ifr,
                        (struct ifnet *)ifn));
 }
 
                        (struct ifnet *)ifn));
 }
 
@@ -372,7 +378,7 @@ nsip_ctlinput(cmd, sa)
        struct sockaddr_in *sin;
        int in_rtchange();
 
        struct sockaddr_in *sin;
        int in_rtchange();
 
-       if ((unsigned)cmd > PRC_NCMDS)
+       if ((unsigned)cmd >= PRC_NCMDS)
                return;
        if (sa->sa_family != AF_INET && sa->sa_family != AF_IMPLINK)
                return;
                return;
        if (sa->sa_family != AF_INET && sa->sa_family != AF_IMPLINK)
                return;
@@ -395,11 +401,9 @@ nsip_ctlinput(cmd, sa)
 nsip_rtchange(dst)
        register struct in_addr *dst;
 {
 nsip_rtchange(dst)
        register struct in_addr *dst;
 {
-       register struct mbuf *m;
        register struct ifnet_en *ifn;
 
        register struct ifnet_en *ifn;
 
-       for (m = nsip_list; m; m = m->m_next) {
-               ifn = mtod(m, struct ifnet_en *);
+       for (ifn = nsip_list; ifn; ifn = ifn->ifen_next) {
                if (ifn->ifen_dst.s_addr == dst->s_addr &&
                        ifn->ifen_route.ro_rt) {
                                RTFREE(ifn->ifen_route.ro_rt);
                if (ifn->ifen_dst.s_addr == dst->s_addr &&
                        ifn->ifen_route.ro_rt) {
                                RTFREE(ifn->ifen_route.ro_rt);