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/netipx/ipx_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.
    4  * Copyright (c) 2004-2009 Robert N. M. Watson
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 4. Neither the name of the University nor the names of its contributors
   16  *    may be used to endorse or promote products derived from this software
   17  *    without specific prior written permission.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29  * SUCH DAMAGE.
   30  *
   31  * Copyright (c) 1995, Mike Mitchell
   32  * All rights reserved.
   33  *
   34  * Redistribution and use in source and binary forms, with or without
   35  * modification, are permitted provided that the following conditions
   36  * are met:
   37  * 1. Redistributions of source code must retain the above copyright
   38  *    notice, this list of conditions and the following disclaimer.
   39  * 2. Redistributions in binary form must reproduce the above copyright
   40  *    notice, this list of conditions and the following disclaimer in the
   41  *    documentation and/or other materials provided with the distribution.
   42  * 3. All advertising materials mentioning features or use of this software
   43  *    must display the following acknowledgement:
   44  *      This product includes software developed by the University of
   45  *      California, Berkeley and its contributors.
   46  * 4. Neither the name of the University nor the names of its contributors
   47  *    may be used to endorse or promote products derived from this software
   48  *    without specific prior written permission.
   49  *
   50  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   51  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   52  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   53  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   54  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   55  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   56  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   57  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   58  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   59  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   60  * SUCH DAMAGE.
   61  *
   62  *      @(#)ipx_input.c
   63  */
   64 
   65 #include <sys/cdefs.h>
   66 __FBSDID("$FreeBSD: releng/8.3/sys/netipx/ipx_input.c 199583 2009-11-20 15:27:52Z jhb $");
   67 
   68 #include <sys/param.h>
   69 #include <sys/systm.h>
   70 #include <sys/mbuf.h>
   71 #include <sys/protosw.h>
   72 #include <sys/socket.h>
   73 #include <sys/kernel.h>
   74 #include <sys/random.h>
   75 #include <sys/lock.h>
   76 #include <sys/rwlock.h>
   77 #include <sys/sysctl.h>
   78 
   79 #include <net/if.h>
   80 #include <net/route.h>
   81 #include <net/netisr.h>
   82 
   83 #include <netipx/ipx.h>
   84 #include <netipx/spx.h>
   85 #include <netipx/ipx_if.h>
   86 #include <netipx/ipx_pcb.h>
   87 #include <netipx/ipx_var.h>
   88 
   89 int     ipxcksum = 0;
   90 SYSCTL_INT(_net_ipx_ipx, OID_AUTO, checksum, CTLFLAG_RW,
   91            &ipxcksum, 0, "Compute ipx checksum");
   92 
   93 static int      ipxprintfs = 0;         /* printing forwarding information */
   94 SYSCTL_INT(_net_ipx_ipx, OID_AUTO, ipxprintfs, CTLFLAG_RW,
   95            &ipxprintfs, 0, "Printing forwarding information");
   96 
   97 static int      ipxforwarding = 0;
   98 SYSCTL_INT(_net_ipx_ipx, OID_AUTO, ipxforwarding, CTLFLAG_RW,
   99             &ipxforwarding, 0, "Enable ipx forwarding");
  100 
  101 static int      ipxnetbios = 0;
  102 SYSCTL_INT(_net_ipx, OID_AUTO, ipxnetbios, CTLFLAG_RW,
  103            &ipxnetbios, 0, "Propagate netbios over ipx");
  104 
  105 static  int ipx_do_route(struct ipx_addr *src, struct route *ro);
  106 static  void ipx_undo_route(struct route *ro);
  107 static  void ipx_forward(struct mbuf *m);
  108 static  void ipxintr(struct mbuf *m);
  109 
  110 const union     ipx_net ipx_zeronet;
  111 
  112 const union     ipx_net ipx_broadnet = { .s_net[0] = 0xffff,
  113                                             .s_net[1] = 0xffff };
  114 const union     ipx_host ipx_broadhost = { .s_host[0] = 0xffff,
  115                                             .s_host[1] = 0xffff,
  116                                             .s_host[2] = 0xffff };
  117 
  118 struct  ipxstat ipxstat;
  119 struct  sockaddr_ipx ipx_netmask, ipx_hostmask;
  120 
  121 /*
  122  * IPX protocol control block (pcb) lists.
  123  */
  124 struct mtx              ipxpcb_list_mtx;
  125 struct ipxpcbhead       ipxpcb_list;
  126 struct ipxpcbhead       ipxrawpcb_list;
  127 
  128 static struct netisr_handler ipx_nh = {
  129         .nh_name = "ipx",
  130         .nh_handler = ipxintr,
  131         .nh_proto = NETISR_IPX,
  132         .nh_policy = NETISR_POLICY_SOURCE,
  133 };
  134 
  135 long    ipx_pexseq;             /* Locked with ipxpcb_list_mtx. */
  136 
  137 /*
  138  * IPX initialization.
  139  */
  140 
  141 void
  142 ipx_init(void)
  143 {
  144 
  145         read_random(&ipx_pexseq, sizeof ipx_pexseq);
  146 
  147         LIST_INIT(&ipxpcb_list);
  148         LIST_INIT(&ipxrawpcb_list);
  149         TAILQ_INIT(&ipx_ifaddrhead);
  150 
  151         IPX_LIST_LOCK_INIT();
  152         IPX_IFADDR_LOCK_INIT();
  153 
  154         ipx_netmask.sipx_len = 6;
  155         ipx_netmask.sipx_addr.x_net = ipx_broadnet;
  156 
  157         ipx_hostmask.sipx_len = 12;
  158         ipx_hostmask.sipx_addr.x_net = ipx_broadnet;
  159         ipx_hostmask.sipx_addr.x_host = ipx_broadhost;
  160 
  161         netisr_register(&ipx_nh);
  162 }
  163 
  164 /*
  165  * IPX input routine.  Pass to next level.
  166  */
  167 static void
  168 ipxintr(struct mbuf *m)
  169 {
  170         struct ipx *ipx;
  171         struct ipxpcb *ipxp;
  172         struct ipx_ifaddr *ia;
  173         int len;
  174 
  175         /*
  176          * If no IPX addresses have been set yet but the interfaces
  177          * are receiving, can't do anything with incoming packets yet.
  178          */
  179         if (TAILQ_EMPTY(&ipx_ifaddrhead)) {
  180                 m_freem(m);
  181                 return;
  182         }
  183 
  184         ipxstat.ipxs_total++;
  185 
  186         if ((m->m_flags & M_EXT || m->m_len < sizeof(struct ipx)) &&
  187             (m = m_pullup(m, sizeof(struct ipx))) == NULL) {
  188                 ipxstat.ipxs_toosmall++;
  189                 return;
  190         }
  191 
  192         /*
  193          * Give any raw listeners a crack at the packet
  194          */
  195         IPX_LIST_LOCK();
  196         LIST_FOREACH(ipxp, &ipxrawpcb_list, ipxp_list) {
  197                 struct mbuf *m1 = m_copy(m, 0, (int)M_COPYALL);
  198                 if (m1 != NULL) {
  199                         IPX_LOCK(ipxp);
  200                         ipx_input(m1, ipxp);
  201                         IPX_UNLOCK(ipxp);
  202                 }
  203         }
  204         IPX_LIST_UNLOCK();
  205 
  206         ipx = mtod(m, struct ipx *);
  207         len = ntohs(ipx->ipx_len);
  208         /*
  209          * Check that the amount of data in the buffers
  210          * is as at least much as the IPX header would have us expect.
  211          * Trim mbufs if longer than we expect.
  212          * Drop packet if shorter than we expect.
  213          */
  214         if (m->m_pkthdr.len < len) {
  215                 ipxstat.ipxs_tooshort++;
  216                 m_freem(m);
  217                 return;
  218         }
  219         if (m->m_pkthdr.len > len) {
  220                 if (m->m_len == m->m_pkthdr.len) {
  221                         m->m_len = len;
  222                         m->m_pkthdr.len = len;
  223                 } else
  224                         m_adj(m, len - m->m_pkthdr.len);
  225         }
  226         if (ipxcksum && ipx->ipx_sum != 0xffff) {
  227                 if (ipx->ipx_sum != ipx_cksum(m, len)) {
  228                         ipxstat.ipxs_badsum++;
  229                         m_freem(m);
  230                         return;
  231                 }
  232         }
  233 
  234         /*
  235          * Propagated (Netbios) packets (type 20) has to be handled
  236          * different. :-(
  237          */
  238         if (ipx->ipx_pt == IPXPROTO_NETBIOS) {
  239                 if (ipxnetbios) {
  240                         ipx_output_type20(m);
  241                         return;
  242                 } else {
  243                         m_freem(m);
  244                         return;
  245                 }
  246         }
  247 
  248         /*
  249          * Is this a directed broadcast?
  250          */
  251         if (ipx_hosteqnh(ipx_broadhost,ipx->ipx_dna.x_host)) {
  252                 if ((!ipx_neteq(ipx->ipx_dna, ipx->ipx_sna)) &&
  253                     (!ipx_neteqnn(ipx->ipx_dna.x_net, ipx_broadnet)) &&
  254                     (!ipx_neteqnn(ipx->ipx_sna.x_net, ipx_zeronet)) &&
  255                     (!ipx_neteqnn(ipx->ipx_dna.x_net, ipx_zeronet)) ) {
  256                         /*
  257                          * If it is a broadcast to the net where it was
  258                          * received from, treat it as ours.
  259                          */
  260                         IPX_IFADDR_RLOCK();
  261                         TAILQ_FOREACH(ia, &ipx_ifaddrhead, ia_link) {
  262                                 if ((ia->ia_ifa.ifa_ifp == m->m_pkthdr.rcvif)
  263                                     && ipx_neteq(ia->ia_addr.sipx_addr,
  264                                     ipx->ipx_dna)) {
  265                                         IPX_IFADDR_RUNLOCK();
  266                                         goto ours;
  267                                 }
  268                         }
  269                         IPX_IFADDR_RUNLOCK();
  270 
  271                         /*
  272                          * Look to see if I need to eat this packet.
  273                          * Algorithm is to forward all young packets
  274                          * and prematurely age any packets which will
  275                          * by physically broadcasted.
  276                          * Any very old packets eaten without forwarding
  277                          * would die anyway.
  278                          *
  279                          * Suggestion of Bill Nesheim, Cornell U.
  280                          */
  281                         if (ipx->ipx_tc < IPX_MAXHOPS) {
  282                                 ipx_forward(m);
  283                                 return;
  284                         }
  285                 }
  286         /*
  287          * Is this our packet? If not, forward.
  288          */
  289         } else {
  290                 IPX_IFADDR_RLOCK();
  291                 TAILQ_FOREACH(ia, &ipx_ifaddrhead, ia_link) {
  292                         if (ipx_hosteq(ipx->ipx_dna, ia->ia_addr.sipx_addr) &&
  293                             (ipx_neteq(ipx->ipx_dna, ia->ia_addr.sipx_addr) ||
  294                              ipx_neteqnn(ipx->ipx_dna.x_net, ipx_zeronet)))
  295                                 break;
  296                 }
  297                 IPX_IFADDR_RUNLOCK();
  298                 if (ia == NULL) {
  299                         ipx_forward(m);
  300                         return;
  301                 }
  302         }
  303 ours:
  304         /*
  305          * Locate pcb for datagram.
  306          */
  307         IPX_LIST_LOCK();
  308         ipxp = ipx_pcblookup(&ipx->ipx_sna, ipx->ipx_dna.x_port, IPX_WILDCARD);
  309         /*
  310          * Switch out to protocol's input routine.
  311          */
  312         if (ipxp != NULL) {
  313                 ipxstat.ipxs_delivered++;
  314                 if ((ipxp->ipxp_flags & IPXP_ALL_PACKETS) == 0)
  315                         switch (ipx->ipx_pt) {
  316                         case IPXPROTO_SPX:
  317                                 IPX_LOCK(ipxp);
  318                                 /* Will release both locks. */
  319                                 spx_input(m, ipxp);
  320                                 return;
  321                         }
  322                 IPX_LOCK(ipxp);
  323                 ipx_input(m, ipxp);
  324                 IPX_UNLOCK(ipxp);
  325         } else
  326                 m_freem(m);
  327         IPX_LIST_UNLOCK();
  328 }
  329 
  330 void
  331 ipx_ctlinput(cmd, arg_as_sa, dummy)
  332         int cmd;
  333         struct sockaddr *arg_as_sa;     /* XXX should be swapped with dummy */
  334         void *dummy;
  335 {
  336 
  337         /* Currently, nothing. */
  338 }
  339 
  340 /*
  341  * Forward a packet. If some error occurs drop the packet. IPX don't
  342  * have a way to return errors to the sender.
  343  */
  344 
  345 static struct route ipx_droute;
  346 static struct route ipx_sroute;
  347 
  348 static void
  349 ipx_forward(struct mbuf *m)
  350 {
  351         struct ipx *ipx = mtod(m, struct ipx *);
  352         int error;
  353         int agedelta = 1;
  354         int flags = IPX_FORWARDING;
  355         int ok_there = 0;
  356         int ok_back = 0;
  357 
  358         if (ipxforwarding == 0) {
  359                 /* can't tell difference between net and host */
  360                 ipxstat.ipxs_cantforward++;
  361                 m_freem(m);
  362                 goto cleanup;
  363         }
  364         ipx->ipx_tc++;
  365         if (ipx->ipx_tc > IPX_MAXHOPS) {
  366                 ipxstat.ipxs_cantforward++;
  367                 m_freem(m);
  368                 goto cleanup;
  369         }
  370 
  371         if ((ok_there = ipx_do_route(&ipx->ipx_dna,&ipx_droute)) == 0) {
  372                 ipxstat.ipxs_noroute++;
  373                 m_freem(m);
  374                 goto cleanup;
  375         }
  376         /*
  377          * Here we think about  forwarding  broadcast packets,
  378          * so we try to insure that it doesn't go back out
  379          * on the interface it came in on.  Also, if we
  380          * are going to physically broadcast this, let us
  381          * age the packet so we can eat it safely the second time around.
  382          */
  383         if (ipx->ipx_dna.x_host.c_host[0] & 0x1) {
  384                 struct ipx_ifaddr *ia;
  385                 struct ifnet *ifp;
  386 
  387                 IPX_IFADDR_RLOCK();
  388                 ia = ipx_iaonnetof(&ipx->ipx_dna);
  389                 if (ia != NULL) {
  390                         /* I'm gonna hafta eat this packet */
  391                         agedelta += IPX_MAXHOPS - ipx->ipx_tc;
  392                         ipx->ipx_tc = IPX_MAXHOPS;
  393                 }
  394                 IPX_IFADDR_RUNLOCK();
  395                 if ((ok_back = ipx_do_route(&ipx->ipx_sna,&ipx_sroute)) == 0) {
  396                         /* error = ENETUNREACH; He'll never get it! */
  397                         ipxstat.ipxs_noroute++;
  398                         m_freem(m);
  399                         goto cleanup;
  400                 }
  401                 if (ipx_droute.ro_rt &&
  402                     (ifp = ipx_droute.ro_rt->rt_ifp) &&
  403                     ipx_sroute.ro_rt &&
  404                     (ifp != ipx_sroute.ro_rt->rt_ifp)) {
  405                         flags |= IPX_ALLOWBROADCAST;
  406                 } else {
  407                         ipxstat.ipxs_noroute++;
  408                         m_freem(m);
  409                         goto cleanup;
  410                 }
  411         }
  412         /*
  413          * We don't need to recompute checksum because ipx_tc field
  414          * is ignored by checksum calculation routine, however
  415          * it may be desirable to reset checksum if ipxcksum == 0
  416          */
  417 #if 0
  418         if (!ipxcksum)
  419                 ipx->ipx_sum = 0xffff;
  420 #endif
  421 
  422         error = ipx_outputfl(m, &ipx_droute, flags);
  423         if (error == 0) {
  424                 ipxstat.ipxs_forward++;
  425 
  426                 if (ipxprintfs) {
  427                         printf("forward: ");
  428                         ipx_printhost(&ipx->ipx_sna);
  429                         printf(" to ");
  430                         ipx_printhost(&ipx->ipx_dna);
  431                         printf(" hops %d\n", ipx->ipx_tc);
  432                 }
  433         } 
  434 cleanup:
  435         if (ok_there)
  436                 ipx_undo_route(&ipx_droute);
  437         if (ok_back)
  438                 ipx_undo_route(&ipx_sroute);
  439 }
  440 
  441 static int
  442 ipx_do_route(struct ipx_addr *src, struct route *ro)
  443 {
  444         struct sockaddr_ipx *dst;
  445 
  446         bzero((caddr_t)ro, sizeof(*ro));
  447         dst = (struct sockaddr_ipx *)&ro->ro_dst;
  448 
  449         dst->sipx_len = sizeof(*dst);
  450         dst->sipx_family = AF_IPX;
  451         dst->sipx_addr = *src;
  452         dst->sipx_addr.x_port = 0;
  453         rtalloc_ign(ro, 0);
  454         if (ro->ro_rt == NULL || ro->ro_rt->rt_ifp == NULL) {
  455                 return (0);
  456         }
  457         ro->ro_rt->rt_use++;
  458         return (1);
  459 }
  460 
  461 static void
  462 ipx_undo_route(struct route *ro)
  463 {
  464 
  465         if (ro->ro_rt != NULL) {
  466                 RTFREE(ro->ro_rt);
  467         }
  468 }

Cache object: 1edfcf62ae98ab043b2e169126df6f93


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