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_input.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_input.c  8.1 (Berkeley) 6/10/93
   34  * $FreeBSD$
   35  */
   36 
   37 #include <sys/param.h>
   38 #include <sys/systm.h>
   39 #include <sys/malloc.h>
   40 #include <sys/mbuf.h>
   41 #include <sys/domain.h>
   42 #include <sys/protosw.h>
   43 #include <sys/socket.h>
   44 #include <sys/socketvar.h>
   45 #include <sys/errno.h>
   46 #include <sys/time.h>
   47 #include <sys/kernel.h>
   48 
   49 #include <net/if.h>
   50 #include <net/route.h>
   51 #include <net/raw_cb.h>
   52 #include <net/netisr.h>
   53 
   54 #include <netns/ns.h>
   55 #include <netns/ns_if.h>
   56 #include <netns/ns_pcb.h>
   57 #include <netns/idp.h>
   58 #include <netns/idp_var.h>
   59 #include <netns/ns_error.h>
   60 
   61 /*
   62  * NS initialization.
   63  */
   64 union ns_host   ns_thishost;
   65 union ns_host   ns_zerohost;
   66 union ns_host   ns_broadhost;
   67 union ns_net    ns_zeronet;
   68 union ns_net    ns_broadnet;
   69 struct sockaddr_ns ns_netmask, ns_hostmask;
   70 
   71 static u_short allones[] = {-1, -1, -1};
   72 
   73 struct nspcb nspcb;
   74 struct nspcb nsrawpcb;
   75 
   76 struct ifqueue  nsintrq;
   77 int     nsqmaxlen = IFQ_MAXLEN;
   78 
   79 int     idpcksum = 1;
   80 long    ns_pexseq;
   81 
   82 ns_init()
   83 {
   84         extern struct timeval time;
   85 
   86         ns_broadhost = * (union ns_host *) allones;
   87         ns_broadnet = * (union ns_net *) allones;
   88         nspcb.nsp_next = nspcb.nsp_prev = &nspcb;
   89         nsrawpcb.nsp_next = nsrawpcb.nsp_prev = &nsrawpcb;
   90         nsintrq.ifq_maxlen = nsqmaxlen;
   91         ns_pexseq = time.tv_usec;
   92         ns_netmask.sns_len = 6;
   93         ns_netmask.sns_addr.x_net = ns_broadnet;
   94         ns_hostmask.sns_len = 12;
   95         ns_hostmask.sns_addr.x_net = ns_broadnet;
   96         ns_hostmask.sns_addr.x_host = ns_broadhost;
   97 }
   98 
   99 /*
  100  * Idp input routine.  Pass to next level.
  101  */
  102 int nsintr_getpck = 0;
  103 int nsintr_swtch = 0;
  104 void
  105 nsintr(void)
  106 {
  107         register struct idp *idp;
  108         register struct mbuf *m;
  109         register struct nspcb *nsp;
  110         register int i;
  111         int len, s, error;
  112         char oddpacketp;
  113 
  114 next:
  115         /*
  116          * Get next datagram off input queue and get IDP header
  117          * in first mbuf.
  118          */
  119         s = splimp();
  120         IF_DEQUEUE(&nsintrq, m);
  121         splx(s);
  122         nsintr_getpck++;
  123         if (m == 0)
  124                 return;
  125         if ((m->m_flags & M_EXT || m->m_len < sizeof (struct idp)) &&
  126             (m = m_pullup(m, sizeof (struct idp))) == 0) {
  127                 idpstat.idps_toosmall++;
  128                 goto next;
  129         }
  130 
  131         /*
  132          * Give any raw listeners a crack at the packet
  133          */
  134         for (nsp = nsrawpcb.nsp_next; nsp != &nsrawpcb; nsp = nsp->nsp_next) {
  135                 struct mbuf *m1 = m_copy(m, 0, (int)M_COPYALL);
  136                 if (m1) idp_input(m1, nsp);
  137         }
  138 
  139         idp = mtod(m, struct idp *);
  140         len = ntohs(idp->idp_len);
  141         if (oddpacketp = len & 1) {
  142                 len++;          /* If this packet is of odd length,
  143                                    preserve garbage byte for checksum */
  144         }
  145 
  146         /*
  147          * Check that the amount of data in the buffers
  148          * is as at least much as the IDP header would have us expect.
  149          * Trim mbufs if longer than we expect.
  150          * Drop packet if shorter than we expect.
  151          */
  152         if (m->m_pkthdr.len < len) {
  153                 idpstat.idps_tooshort++;
  154                 goto bad;
  155         }
  156         if (m->m_pkthdr.len > len) {
  157                 if (m->m_len == m->m_pkthdr.len) {
  158                         m->m_len = len;
  159                         m->m_pkthdr.len = len;
  160                 } else
  161                         m_adj(m, len - m->m_pkthdr.len);
  162         }
  163         if (idpcksum && ((i = idp->idp_sum)!=0xffff)) {
  164                 idp->idp_sum = 0;
  165                 if (i != (idp->idp_sum = ns_cksum(m, len))) {
  166                         idpstat.idps_badsum++;
  167                         idp->idp_sum = i;
  168                         if (ns_hosteqnh(ns_thishost, idp->idp_dna.x_host))
  169                                 error = NS_ERR_BADSUM;
  170                         else
  171                                 error = NS_ERR_BADSUM_T;
  172                         ns_error(m, error, 0);
  173                         goto next;
  174                 }
  175         }
  176         /*
  177          * Is this a directed broadcast?
  178          */
  179         if (ns_hosteqnh(ns_broadhost,idp->idp_dna.x_host)) {
  180                 if ((!ns_neteq(idp->idp_dna, idp->idp_sna)) &&
  181                     (!ns_neteqnn(idp->idp_dna.x_net, ns_broadnet)) &&
  182                     (!ns_neteqnn(idp->idp_sna.x_net, ns_zeronet)) &&
  183                     (!ns_neteqnn(idp->idp_dna.x_net, ns_zeronet)) ) {
  184                         /*
  185                          * Look to see if I need to eat this packet.
  186                          * Algorithm is to forward all young packets
  187                          * and prematurely age any packets which will
  188                          * by physically broadcasted.
  189                          * Any very old packets eaten without forwarding
  190                          * would die anyway.
  191                          *
  192                          * Suggestion of Bill Nesheim, Cornell U.
  193                          */
  194                         if (idp->idp_tc < NS_MAXHOPS) {
  195                                 idp_forward(m);
  196                                 goto next;
  197                         }
  198                 }
  199         /*
  200          * Is this our packet? If not, forward.
  201          */
  202         } else if (!ns_hosteqnh(ns_thishost,idp->idp_dna.x_host)) {
  203                 idp_forward(m);
  204                 goto next;
  205         }
  206         /*
  207          * Locate pcb for datagram.
  208          */
  209         nsp = ns_pcblookup(&idp->idp_sna, idp->idp_dna.x_port, NS_WILDCARD);
  210         /*
  211          * Switch out to protocol's input routine.
  212          */
  213         nsintr_swtch++;
  214         if (nsp) {
  215                 if (oddpacketp) {
  216                         m_adj(m, -1);
  217                 }
  218                 if ((nsp->nsp_flags & NSP_ALL_PACKETS)==0)
  219                         switch (idp->idp_pt) {
  220 
  221                             case NSPROTO_SPP:
  222                                     spp_input(m, nsp);
  223                                     goto next;
  224 
  225                             case NSPROTO_ERROR:
  226                                     ns_err_input(m);
  227                                     goto next;
  228                         }
  229                 idp_input(m, nsp);
  230         } else {
  231                 ns_error(m, NS_ERR_NOSOCK, 0);
  232         }
  233         goto next;
  234 
  235 bad:
  236         m_freem(m);
  237         goto next;
  238 }
  239 
  240 NETISR_SET(NETISR_NS, nsintr);
  241 
  242 u_char nsctlerrmap[PRC_NCMDS] = {
  243         ECONNABORTED,   ECONNABORTED,   0,              0,
  244         0,              0,              EHOSTDOWN,      EHOSTUNREACH,
  245         ENETUNREACH,    EHOSTUNREACH,   ECONNREFUSED,   ECONNREFUSED,
  246         EMSGSIZE,       0,              0,              0,
  247         0,              0,              0,              0
  248 };
  249 
  250 int idp_donosocks = 1;
  251 
  252 idp_ctlinput(cmd, arg)
  253         int cmd;
  254         caddr_t arg;
  255 {
  256         struct ns_addr *ns;
  257         struct nspcb *nsp;
  258         struct ns_errp *errp;
  259         int idp_abort();
  260         extern struct nspcb *idp_drop();
  261         int type;
  262 
  263         if (cmd < 0 || cmd > PRC_NCMDS)
  264                 return;
  265         if (nsctlerrmap[cmd] == 0)
  266                 return;         /* XXX */
  267         type = NS_ERR_UNREACH_HOST;
  268         switch (cmd) {
  269                 struct sockaddr_ns *sns;
  270 
  271         case PRC_IFDOWN:
  272         case PRC_HOSTDEAD:
  273         case PRC_HOSTUNREACH:
  274                 sns = (struct sockaddr_ns *)arg;
  275                 if (sns->sns_family != AF_NS)
  276                         return;
  277                 ns = &sns->sns_addr;
  278                 break;
  279 
  280         default:
  281                 errp = (struct ns_errp *)arg;
  282                 ns = &errp->ns_err_idp.idp_dna;
  283                 type = errp->ns_err_num;
  284                 type = ntohs((u_short)type);
  285         }
  286         switch (type) {
  287 
  288         case NS_ERR_UNREACH_HOST:
  289                 ns_pcbnotify(ns, (int)nsctlerrmap[cmd], idp_abort, (long)0);
  290                 break;
  291 
  292         case NS_ERR_NOSOCK:
  293                 nsp = ns_pcblookup(ns, errp->ns_err_idp.idp_sna.x_port,
  294                         NS_WILDCARD);
  295                 if(nsp && idp_donosocks && ! ns_nullhost(nsp->nsp_faddr))
  296                         (void) idp_drop(nsp, (int)nsctlerrmap[cmd]);
  297         }
  298 }
  299 
  300 int     idpprintfs = 0;
  301 int     idpforwarding = 1;
  302 /*
  303  * Forward a packet.  If some error occurs return the sender
  304  * an error packet.  Note we can't always generate a meaningful
  305  * error message because the NS errors don't have a large enough repetoire
  306  * of codes and types.
  307  */
  308 struct route idp_droute;
  309 struct route idp_sroute;
  310 
  311 idp_forward(m)
  312 struct mbuf *m;
  313 {
  314         register struct idp *idp = mtod(m, struct idp *);
  315         register int error, type, code;
  316         struct mbuf *mcopy = NULL;
  317         int agedelta = 1;
  318         int flags = NS_FORWARDING;
  319         int ok_there = 0;
  320         int ok_back = 0;
  321 
  322         if (idpprintfs) {
  323                 printf("forward: src ");
  324                 ns_printhost(&idp->idp_sna);
  325                 printf(", dst ");
  326                 ns_printhost(&idp->idp_dna);
  327                 printf("hop count %d\n", idp->idp_tc);
  328         }
  329         if (idpforwarding == 0) {
  330                 /* can't tell difference between net and host */
  331                 type = NS_ERR_UNREACH_HOST, code = 0;
  332                 goto senderror;
  333         }
  334         idp->idp_tc++;
  335         if (idp->idp_tc > NS_MAXHOPS) {
  336                 type = NS_ERR_TOO_OLD, code = 0;
  337                 goto senderror;
  338         }
  339         /*
  340          * Save at most 42 bytes of the packet in case
  341          * we need to generate an NS error message to the src.
  342          */
  343         mcopy = m_copy(m, 0, imin((int)ntohs(idp->idp_len), 42));
  344 
  345         if ((ok_there = idp_do_route(&idp->idp_dna,&idp_droute))==0) {
  346                 type = NS_ERR_UNREACH_HOST, code = 0;
  347                 goto senderror;
  348         }
  349         /*
  350          * Here we think about  forwarding  broadcast packets,
  351          * so we try to insure that it doesn't go back out
  352          * on the interface it came in on.  Also, if we
  353          * are going to physically broadcast this, let us
  354          * age the packet so we can eat it safely the second time around.
  355          */
  356         if (idp->idp_dna.x_host.c_host[0] & 0x1) {
  357                 struct ns_ifaddr *ia = ns_iaonnetof(&idp->idp_dna);
  358                 struct ifnet *ifp;
  359                 if (ia) {
  360                         /* I'm gonna hafta eat this packet */
  361                         agedelta += NS_MAXHOPS - idp->idp_tc;
  362                         idp->idp_tc = NS_MAXHOPS;
  363                 }
  364                 if ((ok_back = idp_do_route(&idp->idp_sna,&idp_sroute))==0) {
  365                         /* error = ENETUNREACH; He'll never get it! */
  366                         m_freem(m);
  367                         goto cleanup;
  368                 }
  369                 if (idp_droute.ro_rt &&
  370                     (ifp=idp_droute.ro_rt->rt_ifp) &&
  371                     idp_sroute.ro_rt &&
  372                     (ifp!=idp_sroute.ro_rt->rt_ifp)) {
  373                         flags |= NS_ALLOWBROADCAST;
  374                 } else {
  375                         type = NS_ERR_UNREACH_HOST, code = 0;
  376                         goto senderror;
  377                 }
  378         }
  379         /* need to adjust checksum */
  380         if (idp->idp_sum!=0xffff) {
  381                 union bytes {
  382                         u_char c[4];
  383                         u_short s[2];
  384                         long l;
  385                 } x;
  386                 register int shift;
  387                 x.l = 0; x.c[0] = agedelta;
  388                 shift = (((((int)ntohs(idp->idp_len))+1)>>1)-2) & 0xf;
  389                 x.l = idp->idp_sum + (x.s[0] << shift);
  390                 x.l = x.s[0] + x.s[1];
  391                 x.l = x.s[0] + x.s[1];
  392                 if (x.l==0xffff) idp->idp_sum = 0; else idp->idp_sum = x.l;
  393         }
  394         if ((error = ns_output(m, &idp_droute, flags)) &&
  395             (mcopy!=NULL)) {
  396                 idp = mtod(mcopy, struct idp *);
  397                 type = NS_ERR_UNSPEC_T, code = 0;
  398                 switch (error) {
  399 
  400                 case ENETUNREACH:
  401                 case EHOSTDOWN:
  402                 case EHOSTUNREACH:
  403                 case ENETDOWN:
  404                 case EPERM:
  405                         type = NS_ERR_UNREACH_HOST;
  406                         break;
  407 
  408                 case EMSGSIZE:
  409                         type = NS_ERR_TOO_BIG;
  410                         code = 576; /* too hard to figure out mtu here */
  411                         break;
  412 
  413                 case ENOBUFS:
  414                         type = NS_ERR_UNSPEC_T;
  415                         break;
  416                 }
  417                 mcopy = NULL;
  418         senderror:
  419                 ns_error(m, type, code);
  420         }
  421 cleanup:
  422         if (ok_there)
  423                 idp_undo_route(&idp_droute);
  424         if (ok_back)
  425                 idp_undo_route(&idp_sroute);
  426         if (mcopy != NULL)
  427                 m_freem(mcopy);
  428 }
  429 
  430 idp_do_route(src, ro)
  431 struct ns_addr *src;
  432 struct route *ro;
  433 {
  434 
  435         struct sockaddr_ns *dst;
  436 
  437         bzero((caddr_t)ro, sizeof (*ro));
  438         dst = (struct sockaddr_ns *)&ro->ro_dst;
  439 
  440         dst->sns_len = sizeof(*dst);
  441         dst->sns_family = AF_NS;
  442         dst->sns_addr = *src;
  443         dst->sns_addr.x_port = 0;
  444         rtalloc(ro);
  445         if (ro->ro_rt == 0 || ro->ro_rt->rt_ifp == 0) {
  446                 return (0);
  447         }
  448         ro->ro_rt->rt_use++;
  449         return (1);
  450 }
  451 
  452 idp_undo_route(ro)
  453 register struct route *ro;
  454 {
  455         if (ro->ro_rt) {RTFREE(ro->ro_rt);}
  456 }
  457 
  458 ns_watch_output(m, ifp)
  459 struct mbuf *m;
  460 struct ifnet *ifp;
  461 {
  462         register struct nspcb *nsp;
  463         register struct ifaddr *ifa;
  464         /*
  465          * Give any raw listeners a crack at the packet
  466          */
  467         for (nsp = nsrawpcb.nsp_next; nsp != &nsrawpcb; nsp = nsp->nsp_next) {
  468                 struct mbuf *m0 = m_copy(m, 0, (int)M_COPYALL);
  469                 if (m0) {
  470                         register struct idp *idp;
  471 
  472                         M_PREPEND(m0, sizeof (*idp), M_DONTWAIT);
  473                         if (m0 == NULL)
  474                                 continue;
  475                         idp = mtod(m0, struct idp *);
  476                         idp->idp_sna.x_net = ns_zeronet;
  477                         idp->idp_sna.x_host = ns_thishost;
  478                         if (ifp && (ifp->if_flags & IFF_POINTOPOINT))
  479                             for(ifa = ifp->if_addrlist; ifa;
  480                                                 ifa = ifa->ifa_next) {
  481                                 if (ifa->ifa_addr->sa_family==AF_NS) {
  482                                     idp->idp_sna = IA_SNS(ifa)->sns_addr;
  483                                     break;
  484                                 }
  485                             }
  486                         idp->idp_len = ntohl(m0->m_pkthdr.len);
  487                         idp_input(m0, nsp);
  488                 }
  489         }
  490 }

Cache object: bf10c8a51642ecbecc991c536aba907b


[ 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.