The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netns/ns_ip.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 1984, 1985, 1986, 1987, 1993
    3  *      The Regents of the University of California.  All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  * 3. All advertising materials mentioning features or use of this software
   14  *    must display the following acknowledgement:
   15  *      This product includes software developed by the University of
   16  *      California, Berkeley and its contributors.
   17  * 4. Neither the name of the University nor the names of its contributors
   18  *    may be used to endorse or promote products derived from this software
   19  *    without specific prior written permission.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   31  * SUCH DAMAGE.
   32  *
   33  *      @(#)ns_ip.c     8.1 (Berkeley) 6/10/93
   34  * $FreeBSD: releng/5.0/sys/netns/ns_ip.c 102412 2002-08-25 13:23:09Z charnier $
   35  */
   36 
   37 /*
   38  * Software interface driver for encapsulating ns in ip.
   39  */
   40 
   41 #ifdef NSIP
   42 #include <sys/param.h>
   43 #include <sys/systm.h>
   44 #include <sys/malloc.h>
   45 #include <sys/mbuf.h>
   46 #include <sys/socket.h>
   47 #include <sys/socketvar.h>
   48 #include <sys/errno.h>
   49 #include <sys/ioctl.h>
   50 #include <sys/protosw.h>
   51 
   52 #include <net/if.h>
   53 #include <net/netisr.h>
   54 #include <net/route.h>
   55 
   56 #include <netinet/in.h>
   57 #include <netinet/in_systm.h>
   58 #include <netinet/in_var.h>
   59 #include <netinet/ip.h>
   60 #include <netinet/ip_var.h>
   61 
   62 #include <machine/mtpr.h>
   63 
   64 #include <netns/ns.h>
   65 #include <netns/ns_if.h>
   66 #include <netns/idp.h>
   67 
   68 struct ifnet_en {
   69         struct ifnet ifen_ifnet;
   70         struct route ifen_route;
   71         struct in_addr ifen_src;
   72         struct in_addr ifen_dst;
   73         struct ifnet_en *ifen_next;
   74 };
   75 
   76 int     nsipoutput(), nsipioctl(), nsipstart();
   77 #define LOMTU   (1024+512);
   78 
   79 struct ifnet nsipif;
   80 struct ifnet_en *nsip_list;             /* list of all hosts and gateways or
   81                                         broadcast addrs */
   82 
   83 struct ifnet_en *
   84 nsipattach()
   85 {
   86         register struct ifnet_en *m;
   87         register struct ifnet *ifp;
   88 
   89         if (nsipif.if_mtu == 0) {
   90                 ifp = &nsipif;
   91                 ifp->if_name = "nsip";
   92                 ifp->if_mtu = LOMTU;
   93                 ifp->if_ioctl = nsipioctl;
   94                 ifp->if_output = nsipoutput;
   95                 ifp->if_start = nsipstart;
   96                 ifp->if_flags = IFF_POINTOPOINT;
   97         }
   98 
   99         MALLOC((m), struct ifnet_en *, sizeof(*m), M_PCB, M_NOWAIT);
  100         if (m == NULL) return (NULL);
  101         m->ifen_next = nsip_list;
  102         nsip_list = m;
  103         ifp = &m->ifen_ifnet;
  104 
  105         ifp->if_name = "nsip";
  106         ifp->if_mtu = LOMTU;
  107         ifp->if_ioctl = nsipioctl;
  108         ifp->if_output = nsipoutput;
  109         ifp->if_start = nsipstart;
  110         ifp->if_flags = IFF_POINTOPOINT;
  111         ifp->if_unit = nsipif.if_unit++;
  112         if_attach(ifp);
  113 
  114         return (m);
  115 }
  116 
  117 
  118 /*
  119  * Process an ioctl request.
  120  */
  121 /* ARGSUSED */
  122 nsipioctl(ifp, cmd, data)
  123         register struct ifnet *ifp;
  124         int cmd;
  125         caddr_t data;
  126 {
  127         int error = 0;
  128         struct ifreq *ifr;
  129 
  130         switch (cmd) {
  131 
  132         case SIOCSIFADDR:
  133                 ifp->if_flags |= IFF_UP;
  134                 /* FALLTHROUGH */
  135 
  136         case SIOCSIFDSTADDR:
  137                 /*
  138                  * Everything else is done at a higher level.
  139                  */
  140                 break;
  141 
  142         case SIOCSIFFLAGS:
  143                 ifr = (struct ifreq *)data;
  144                 if ((ifr->ifr_flags & IFF_UP) == 0)
  145                         error = nsip_free(ifp);
  146 
  147 
  148         default:
  149                 error = EINVAL;
  150         }
  151         return (error);
  152 }
  153 
  154 struct mbuf *nsip_badlen;
  155 struct mbuf *nsip_lastin;
  156 int nsip_hold_input;
  157 
  158 idpip_input(m, ifp)
  159         register struct mbuf *m;
  160         struct ifnet *ifp;
  161 {
  162         register struct ip *ip;
  163         register struct idp *idp;
  164         register struct ifqueue *ifq = &nsintrq;
  165         int len, s;
  166 
  167         if (nsip_hold_input) {
  168                 if (nsip_lastin) {
  169                         m_freem(nsip_lastin);
  170                 }
  171                 nsip_lastin = m_copym(m, 0, (int)M_COPYALL, M_DONTWAIT);
  172         }
  173         /*
  174          * Get IP and IDP header together in first mbuf.
  175          */
  176         nsipif.if_ipackets++;
  177         s = sizeof (struct ip) + sizeof (struct idp);
  178         if (((m->m_flags & M_EXT) || m->m_len < s) &&
  179             (m = m_pullup(m, s)) == 0) {
  180                 nsipif.if_ierrors++;
  181                 return;
  182         }
  183         ip = mtod(m, struct ip *);
  184         if (ip->ip_hl > (sizeof (struct ip) >> 2)) {
  185                 ip_stripoptions(m, (struct mbuf *)0);
  186                 if (m->m_len < s) {
  187                         if ((m = m_pullup(m, s)) == 0) {
  188                                 nsipif.if_ierrors++;
  189                                 return;
  190                         }
  191                         ip = mtod(m, struct ip *);
  192                 }
  193         }
  194 
  195         /*
  196          * Make mbuf data length reflect IDP length.
  197          * If not enough data to reflect IDP length, drop.
  198          */
  199         m->m_data += sizeof (struct ip);
  200         m->m_len -= sizeof (struct ip);
  201         m->m_pkthdr.len -= sizeof (struct ip);
  202         idp = mtod(m, struct idp *);
  203         len = ntohs(idp->idp_len);
  204         if (len & 1) len++;             /* Preserve Garbage Byte */
  205         if (ip->ip_len != len) {
  206                 if (len > ip->ip_len) {
  207                         nsipif.if_ierrors++;
  208                         if (nsip_badlen) m_freem(nsip_badlen);
  209                         nsip_badlen = m;
  210                         return;
  211                 }
  212                 /* Any extra will be trimmed off by the NS routines */
  213         }
  214 
  215         /*
  216          * Place interface pointer before the data
  217          * for the receiving protocol.
  218          */
  219         m->m_pkthdr.rcvif = ifp;
  220         /*
  221          * Deliver to NS
  222          */
  223         if (IF_HANDOFF(ifq, m, NULL))
  224                 schednetisr(NETISR_NS);
  225         return;
  226 }
  227 
  228 /* ARGSUSED */
  229 nsipoutput(ifn, m, dst)
  230         struct ifnet_en *ifn;
  231         register struct mbuf *m;
  232         struct sockaddr *dst;
  233 {
  234 
  235         register struct ip *ip;
  236         register struct route *ro = &(ifn->ifen_route);
  237         register int len = 0;
  238         register struct idp *idp = mtod(m, struct idp *);
  239         int error;
  240 
  241         ifn->ifen_ifnet.if_opackets++;
  242         nsipif.if_opackets++;
  243 
  244 
  245         /*
  246          * Calculate data length and make space
  247          * for IP header.
  248          */
  249         len =  ntohs(idp->idp_len);
  250         if (len & 1) len++;             /* Preserve Garbage Byte */
  251         /* following clause not necessary on vax */
  252         if (3 & (int)m->m_data) {
  253                 /* force longword alignment of ip hdr */
  254                 struct mbuf *m0 = m_gethdr(MT_HEADER, M_DONTWAIT);
  255                 if (m0 == 0) {
  256                         m_freem(m);
  257                         return (ENOBUFS);
  258                 }
  259                 MH_ALIGN(m0, sizeof (struct ip));
  260                 m0->m_flags = m->m_flags & M_COPYFLAGS;
  261                 m0->m_next = m;
  262                 m0->m_len = sizeof (struct ip);
  263                 m0->m_pkthdr.len = m0->m_len + m->m_len;
  264                 m->m_flags &= ~M_PKTHDR;
  265         } else {
  266                 M_PREPEND(m, sizeof (struct ip), M_DONTWAIT);
  267                 if (m == 0)
  268                         return (ENOBUFS);
  269         }
  270         /*
  271          * Fill in IP header.
  272          */
  273         ip = mtod(m, struct ip *);
  274         *(long *)ip = 0;
  275         ip->ip_p = IPPROTO_IDP;
  276         ip->ip_src = ifn->ifen_src;
  277         ip->ip_dst = ifn->ifen_dst;
  278         ip->ip_len = (u_short)len + sizeof (struct ip);
  279         ip->ip_ttl = MAXTTL;
  280 
  281         /*
  282          * Output final datagram.
  283          */
  284         error =  (ip_output(m, (struct mbuf *)0, ro, SO_BROADCAST, NULL));
  285         if (error) {
  286                 ifn->ifen_ifnet.if_oerrors++;
  287                 ifn->ifen_ifnet.if_ierrors = error;
  288         }
  289         return (error);
  290 bad:
  291         m_freem(m);
  292         return (ENETUNREACH);
  293 }
  294 
  295 nsipstart(ifp)
  296 struct ifnet *ifp;
  297 {
  298         panic("nsip_start called");
  299 }
  300 
  301 struct ifreq ifr = {"nsip0"};
  302 
  303 nsip_route(m)
  304         register struct mbuf *m;
  305 {
  306         register struct nsip_req *rq = mtod(m, struct nsip_req *);
  307         struct sockaddr_ns *ns_dst = (struct sockaddr_ns *)&rq->rq_ns;
  308         struct sockaddr_in *ip_dst = (struct sockaddr_in *)&rq->rq_ip;
  309         struct route ro;
  310         struct ifnet_en *ifn;
  311         struct sockaddr_in *src;
  312 
  313         /*
  314          * First, make sure we already have an ns address:
  315          */
  316         if (ns_hosteqnh(ns_thishost, ns_zerohost))
  317                 return (EADDRNOTAVAIL);
  318         /*
  319          * Now, determine if we can get to the destination
  320          */
  321         bzero((caddr_t)&ro, sizeof (ro));
  322         ro.ro_dst = *(struct sockaddr *)ip_dst;
  323         rtalloc(&ro);
  324         if (ro.ro_rt == 0 || ro.ro_rt->rt_ifp == 0) {
  325                 return (ENETUNREACH);
  326         }
  327 
  328         /*
  329          * And see how he's going to get back to us:
  330          * i.e., what return ip address do we use?
  331          */
  332         {
  333                 register struct in_ifaddr *ia;
  334                 struct ifnet *ifp = ro.ro_rt->rt_ifp;
  335 
  336                 for (ia = in_ifaddr; ia; ia = ia->ia_next)
  337                         if (ia->ia_ifp == ifp)
  338                                 break;
  339                 if (ia == 0)
  340                         ia = in_ifaddr;
  341                 if (ia == 0) {
  342                         RTFREE(ro.ro_rt);
  343                         return (EADDRNOTAVAIL);
  344                 }
  345                 src = (struct sockaddr_in *)&ia->ia_addr;
  346         }
  347 
  348         /*
  349          * Is there a free (pseudo-)interface or space?
  350          */
  351         for (ifn = nsip_list; ifn; ifn = ifn->ifen_next) {
  352                 if ((ifn->ifen_ifnet.if_flags & IFF_UP) == 0)
  353                         break;
  354         }
  355         if (ifn == NULL)
  356                 ifn = nsipattach();
  357         if (ifn == NULL) {
  358                 RTFREE(ro.ro_rt);
  359                 return (ENOBUFS);
  360         }
  361         ifn->ifen_route = ro;
  362         ifn->ifen_dst =  ip_dst->sin_addr;
  363         ifn->ifen_src = src->sin_addr;
  364 
  365         /*
  366          * now configure this as a point to point link
  367          */
  368         ifr.ifr_name[4] = '' + nsipif.if_unit - 1;
  369         ifr.ifr_dstaddr = * (struct sockaddr *) ns_dst;
  370         (void)ns_control((struct socket *)0, (int)SIOCSIFDSTADDR, (caddr_t)&ifr,
  371                         (struct ifnet *)ifn);
  372         satons_addr(ifr.ifr_addr).x_host = ns_thishost;
  373         return (ns_control((struct socket *)0, (int)SIOCSIFADDR, (caddr_t)&ifr,
  374                         (struct ifnet *)ifn));
  375 }
  376 
  377 nsip_free(ifp)
  378 struct ifnet *ifp;
  379 {
  380         register struct ifnet_en *ifn = (struct ifnet_en *)ifp;
  381         struct route *ro = & ifn->ifen_route;
  382 
  383         if (ro->ro_rt) {
  384                 RTFREE(ro->ro_rt);
  385                 ro->ro_rt = 0;
  386         }
  387         ifp->if_flags &= ~IFF_UP;
  388         return (0);
  389 }
  390 
  391 nsip_ctlinput(cmd, sa)
  392         int cmd;
  393         struct sockaddr *sa;
  394 {
  395         extern u_char inetctlerrmap[];
  396         struct sockaddr_in *sin;
  397         int in_rtchange();
  398 
  399         if ((unsigned)cmd >= PRC_NCMDS)
  400                 return;
  401         if (sa->sa_family != AF_INET && sa->sa_family != AF_IMPLINK)
  402                 return;
  403         sin = (struct sockaddr_in *)sa;
  404         if (sin->sin_addr.s_addr == INADDR_ANY)
  405                 return;
  406 
  407         switch (cmd) {
  408 
  409         case PRC_ROUTEDEAD:
  410         case PRC_REDIRECT_NET:
  411         case PRC_REDIRECT_HOST:
  412         case PRC_REDIRECT_TOSNET:
  413         case PRC_REDIRECT_TOSHOST:
  414                 nsip_rtchange(&sin->sin_addr);
  415                 break;
  416         }
  417 }
  418 
  419 nsip_rtchange(dst)
  420         register struct in_addr *dst;
  421 {
  422         register struct ifnet_en *ifn;
  423 
  424         for (ifn = nsip_list; ifn; ifn = ifn->ifen_next) {
  425                 if (ifn->ifen_dst.s_addr == dst->s_addr &&
  426                         ifn->ifen_route.ro_rt) {
  427                                 RTFREE(ifn->ifen_route.ro_rt);
  428                                 ifn->ifen_route.ro_rt = 0;
  429                 }
  430         }
  431 }
  432 #endif

Cache object: 0c3aef5587a9fa7f65b3fa36b1249d6d


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.