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/netatalk/ddp_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 /*      $NetBSD: ddp_input.c,v 1.9 2004/06/24 04:15:51 jonathan Exp $    */
    2 
    3 /*
    4  * Copyright (c) 1990,1994 Regents of The University of Michigan.
    5  * All Rights Reserved.
    6  *
    7  * Permission to use, copy, modify, and distribute this software and
    8  * its documentation for any purpose and without fee is hereby granted,
    9  * provided that the above copyright notice appears in all copies and
   10  * that both that copyright notice and this permission notice appear
   11  * in supporting documentation, and that the name of The University
   12  * of Michigan not be used in advertising or publicity pertaining to
   13  * distribution of the software without specific, written prior
   14  * permission. This software is supplied as is without expressed or
   15  * implied warranties of any kind.
   16  *
   17  * This product includes software developed by the University of
   18  * California, Berkeley and its contributors.
   19  *
   20  *      Research Systems Unix Group
   21  *      The University of Michigan
   22  *      c/o Wesley Craig
   23  *      535 W. William Street
   24  *      Ann Arbor, Michigan
   25  *      +1-313-764-2278
   26  *      netatalk@umich.edu
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __KERNEL_RCSID(0, "$NetBSD: ddp_input.c,v 1.9 2004/06/24 04:15:51 jonathan Exp $");
   31 
   32 #include <sys/param.h>
   33 #include <sys/systm.h>
   34 #include <sys/kernel.h>
   35 #include <net/netisr.h>
   36 #include <sys/mbuf.h>
   37 #include <sys/socket.h>
   38 #include <sys/socketvar.h>
   39 #include <sys/syslog.h>
   40 #include <net/if.h>
   41 #include <net/route.h>
   42 #include <net/if_ether.h>
   43 #include <netinet/in.h>
   44 
   45 #include <netatalk/at.h>
   46 #include <netatalk/at_var.h>
   47 #include <netatalk/ddp.h>
   48 #include <netatalk/ddp_var.h>
   49 #include <netatalk/at_extern.h>
   50 
   51 int             ddp_forward = 1;
   52 int             ddp_firewall = 0;
   53 extern int      ddp_cksum;
   54 void            ddp_input __P((struct mbuf *, struct ifnet *,
   55     struct elaphdr *, int));
   56 
   57 /*
   58  * Could probably merge these two code segments a little better...
   59  */
   60 void
   61 atintr()
   62 {
   63         struct elaphdr *elhp, elh;
   64         struct ifnet   *ifp;
   65         struct mbuf    *m;
   66         struct at_ifaddr *aa;
   67         int             s;
   68 
   69         for (;;) {
   70                 s = splnet();
   71 
   72                 IF_DEQUEUE(&atintrq2, m);
   73 
   74                 splx(s);
   75 
   76                 if (m == 0)     /* no more queued packets */
   77                         break;
   78 
   79                 m_claimm(m, &atalk_rx_mowner);
   80                 ifp = m->m_pkthdr.rcvif;
   81                 for (aa = at_ifaddr.tqh_first; aa; aa = aa->aa_list.tqe_next) {
   82                         if (aa->aa_ifp == ifp && (aa->aa_flags & AFA_PHASE2))
   83                                 break;
   84                 }
   85                 if (aa == NULL) {       /* ifp not an appletalk interface */
   86                         m_freem(m);
   87                         continue;
   88                 }
   89                 ddp_input(m, ifp, (struct elaphdr *) NULL, 2);
   90         }
   91 
   92         for (;;) {
   93                 s = splnet();
   94 
   95                 IF_DEQUEUE(&atintrq1, m);
   96 
   97                 splx(s);
   98 
   99                 if (m == 0)     /* no more queued packets */
  100 
  101                         break;
  102 
  103                 m_claimm(m, &atalk_rx_mowner);
  104                 ifp = m->m_pkthdr.rcvif;
  105                 for (aa = at_ifaddr.tqh_first; aa; aa = aa->aa_list.tqe_next) {
  106                         if (aa->aa_ifp == ifp &&
  107                             (aa->aa_flags & AFA_PHASE2) == 0)
  108                                 break;
  109                 }
  110                 if (aa == NULL) {       /* ifp not an appletalk interface */
  111                         m_freem(m);
  112                         continue;
  113                 }
  114                 if (m->m_len < SZ_ELAPHDR &&
  115                     ((m = m_pullup(m, SZ_ELAPHDR)) == 0)) {
  116                         ddpstat.ddps_tooshort++;
  117                         continue;
  118                 }
  119                 elhp = mtod(m, struct elaphdr *);
  120                 m_adj(m, SZ_ELAPHDR);
  121 
  122                 if (elhp->el_type == ELAP_DDPEXTEND) {
  123                         ddp_input(m, ifp, (struct elaphdr *) NULL, 1);
  124                 } else {
  125                         bcopy((caddr_t) elhp, (caddr_t) & elh, SZ_ELAPHDR);
  126                         ddp_input(m, ifp, &elh, 1);
  127                 }
  128         }
  129 }
  130 
  131 struct route    forwro;
  132 
  133 void
  134 ddp_input(m, ifp, elh, phase)
  135         struct mbuf    *m;
  136         struct ifnet   *ifp;
  137         struct elaphdr *elh;
  138         int             phase;
  139 {
  140         struct sockaddr_at from, to;
  141         struct ddpshdr *dsh, ddps;
  142         struct at_ifaddr *aa;
  143         struct ddpehdr *deh = NULL, ddpe;
  144         struct ddpcb   *ddp;
  145         int             dlen, mlen;
  146         u_short         cksum = 0;
  147 
  148         bzero((caddr_t) & from, sizeof(struct sockaddr_at));
  149         if (elh) {
  150                 ddpstat.ddps_short++;
  151 
  152                 if (m->m_len < sizeof(struct ddpshdr) &&
  153                     ((m = m_pullup(m, sizeof(struct ddpshdr))) == 0)) {
  154                         ddpstat.ddps_tooshort++;
  155                         return;
  156                 }
  157                 dsh = mtod(m, struct ddpshdr *);
  158                 bcopy((caddr_t) dsh, (caddr_t) & ddps, sizeof(struct ddpshdr));
  159                 ddps.dsh_bytes = ntohl(ddps.dsh_bytes);
  160                 dlen = ddps.dsh_len;
  161 
  162                 to.sat_addr.s_net = ATADDR_ANYNET;
  163                 to.sat_addr.s_node = elh->el_dnode;
  164                 to.sat_port = ddps.dsh_dport;
  165                 from.sat_addr.s_net = ATADDR_ANYNET;
  166                 from.sat_addr.s_node = elh->el_snode;
  167                 from.sat_port = ddps.dsh_sport;
  168 
  169                 for (aa = at_ifaddr.tqh_first; aa; aa = aa->aa_list.tqe_next) {
  170                         if (aa->aa_ifp == ifp &&
  171                             (aa->aa_flags & AFA_PHASE2) == 0 &&
  172                             (AA_SAT(aa)->sat_addr.s_node ==
  173                              to.sat_addr.s_node ||
  174                              to.sat_addr.s_node == ATADDR_BCAST))
  175                                 break;
  176                 }
  177                 if (aa == NULL) {
  178                         m_freem(m);
  179                         return;
  180                 }
  181         } else {
  182                 ddpstat.ddps_long++;
  183 
  184                 if (m->m_len < sizeof(struct ddpehdr) &&
  185                     ((m = m_pullup(m, sizeof(struct ddpehdr))) == 0)) {
  186                         ddpstat.ddps_tooshort++;
  187                         return;
  188                 }
  189                 deh = mtod(m, struct ddpehdr *);
  190                 bcopy((caddr_t) deh, (caddr_t) & ddpe, sizeof(struct ddpehdr));
  191                 ddpe.deh_bytes = ntohl(ddpe.deh_bytes);
  192                 dlen = ddpe.deh_len;
  193 
  194                 if ((cksum = ddpe.deh_sum) == 0) {
  195                         ddpstat.ddps_nosum++;
  196                 }
  197                 from.sat_addr.s_net = ddpe.deh_snet;
  198                 from.sat_addr.s_node = ddpe.deh_snode;
  199                 from.sat_port = ddpe.deh_sport;
  200                 to.sat_addr.s_net = ddpe.deh_dnet;
  201                 to.sat_addr.s_node = ddpe.deh_dnode;
  202                 to.sat_port = ddpe.deh_dport;
  203 
  204                 if (to.sat_addr.s_net == ATADDR_ANYNET) {
  205                         for (aa = at_ifaddr.tqh_first; aa;
  206                             aa = aa->aa_list.tqe_next) {
  207                                 if (phase == 1 && (aa->aa_flags & AFA_PHASE2))
  208                                         continue;
  209 
  210                                 if (phase == 2 &&
  211                                     (aa->aa_flags & AFA_PHASE2) == 0)
  212                                         continue;
  213 
  214                                 if (aa->aa_ifp == ifp &&
  215                                     (AA_SAT(aa)->sat_addr.s_node ==
  216                                      to.sat_addr.s_node ||
  217                                      to.sat_addr.s_node == ATADDR_BCAST ||
  218                                      (ifp->if_flags & IFF_LOOPBACK)))
  219                                         break;
  220                         }
  221                 } else {
  222                         for (aa = at_ifaddr.tqh_first; aa;
  223                             aa = aa->aa_list.tqe_next) {
  224                                 if (to.sat_addr.s_net == aa->aa_firstnet &&
  225                                     to.sat_addr.s_node == 0)
  226                                         break;
  227 
  228                                 if ((ntohs(to.sat_addr.s_net) <
  229                                      ntohs(aa->aa_firstnet) ||
  230                                      ntohs(to.sat_addr.s_net) >
  231                                      ntohs(aa->aa_lastnet)) &&
  232                                     (ntohs(to.sat_addr.s_net) < 0xff00 ||
  233                                      ntohs(to.sat_addr.s_net) > 0xfffe))
  234                                         continue;
  235 
  236                                 if (to.sat_addr.s_node !=
  237                                     AA_SAT(aa)->sat_addr.s_node &&
  238                                     to.sat_addr.s_node != ATADDR_BCAST)
  239                                         continue;
  240 
  241                                 break;
  242                         }
  243                 }
  244         }
  245 
  246         /*
  247          * Adjust the length, removing any padding that may have been added
  248          * at a link layer.  We do this before we attempt to forward a packet,
  249          * possibly on a different media.
  250          */
  251         mlen = m->m_pkthdr.len;
  252         if (mlen < dlen) {
  253                 ddpstat.ddps_toosmall++;
  254                 m_freem(m);
  255                 return;
  256         }
  257         if (mlen > dlen) {
  258                 m_adj(m, dlen - mlen);
  259         }
  260         /*
  261          * XXX Should we deliver broadcasts locally, also, or rely on the
  262          * link layer to give us a copy?  For the moment, the latter.
  263          */
  264         if (aa == NULL || (to.sat_addr.s_node == ATADDR_BCAST &&
  265                 aa->aa_ifp != ifp && (ifp->if_flags & IFF_LOOPBACK) == 0)) {
  266                 if (ddp_forward == 0) {
  267                         m_freem(m);
  268                         return;
  269                 }
  270                 if (forwro.ro_rt &&
  271                     (satosat(&forwro.ro_dst)->sat_addr.s_net !=
  272                      to.sat_addr.s_net ||
  273                      satosat(&forwro.ro_dst)->sat_addr.s_node !=
  274                      to.sat_addr.s_node)) {
  275                         RTFREE(forwro.ro_rt);
  276                         forwro.ro_rt = (struct rtentry *) 0;
  277                 }
  278                 if (forwro.ro_rt == (struct rtentry *) 0 ||
  279                     forwro.ro_rt->rt_ifp == (struct ifnet *) 0) {
  280                         bzero(&forwro.ro_dst, sizeof(struct sockaddr_at));
  281                         forwro.ro_dst.sa_len = sizeof(struct sockaddr_at);
  282                         forwro.ro_dst.sa_family = AF_APPLETALK;
  283                         satosat(&forwro.ro_dst)->sat_addr.s_net =
  284                             to.sat_addr.s_net;
  285                         satosat(&forwro.ro_dst)->sat_addr.s_node =
  286                             to.sat_addr.s_node;
  287                         rtalloc(&forwro);
  288                 }
  289                 if (to.sat_addr.s_net !=
  290                     satosat(&forwro.ro_dst)->sat_addr.s_net &&
  291                     ddpe.deh_hops == DDP_MAXHOPS) {
  292                         m_freem(m);
  293                         return;
  294                 }
  295                 if (ddp_firewall &&
  296                     (forwro.ro_rt == NULL || forwro.ro_rt->rt_ifp != ifp)) {
  297                         m_freem(m);
  298                         return;
  299                 }
  300                 ddpe.deh_hops++;
  301                 ddpe.deh_bytes = htonl(ddpe.deh_bytes);
  302                 bcopy((caddr_t) & ddpe, (caddr_t) deh, sizeof(u_short));/*XXX*/
  303                 if (ddp_route(m, &forwro)) {
  304                         ddpstat.ddps_cantforward++;
  305                 } else {
  306                         ddpstat.ddps_forward++;
  307                 }
  308                 return;
  309         }
  310         from.sat_len = sizeof(struct sockaddr_at);
  311         from.sat_family = AF_APPLETALK;
  312 
  313         if (elh) {
  314                 m_adj(m, sizeof(struct ddpshdr));
  315         } else {
  316                 if (ddp_cksum && cksum && cksum != at_cksum(m, sizeof(int))) {
  317                         ddpstat.ddps_badsum++;
  318                         m_freem(m);
  319                         return;
  320                 }
  321                 m_adj(m, sizeof(struct ddpehdr));
  322         }
  323 
  324         if ((ddp = ddp_search(&from, &to, aa)) == NULL) {
  325                 m_freem(m);
  326                 return;
  327         }
  328         if (sbappendaddr(&ddp->ddp_socket->so_rcv, (struct sockaddr *) & from,
  329                          m, (struct mbuf *) 0) == 0) {
  330                 ddpstat.ddps_nosockspace++;
  331                 m_freem(m);
  332                 return;
  333         }
  334 #if IFA_STATS
  335         if (aa)
  336                 aa->aa_ifa.ifa_data.ifad_inbytes += dlen;
  337 #endif
  338         sorwakeup(ddp->ddp_socket);
  339 }
  340 
  341 #if 0
  342 
  343 #define BPXLEN  48
  344 #define BPALEN  16
  345 #include <ctype.h>
  346 char            hexdig[] = "0123456789ABCDEF";
  347 
  348 static void
  349 bprint(data, len)
  350         char *data;
  351         int len;
  352 {
  353         char            xout[BPXLEN], aout[BPALEN];
  354         int             i = 0;
  355 
  356         bzero(xout, BPXLEN);
  357         bzero(aout, BPALEN);
  358 
  359         for (;;) {
  360                 if (len < 1) {
  361                         if (i != 0) {
  362                                 printf("%s\t%s\n", xout, aout);
  363                         }
  364                         printf("%s\n", "(end)");
  365                         break;
  366                 }
  367                 xout[(i * 3)] = hexdig[(*data & 0xf0) >> 4];
  368                 xout[(i * 3) + 1] = hexdig[*data & 0x0f];
  369 
  370                 if ((u_char) * data < 0x7f && (u_char) * data > 0x20) {
  371                         aout[i] = *data;
  372                 } else {
  373                         aout[i] = '.';
  374                 }
  375 
  376                 xout[(i * 3) + 2] = ' ';
  377 
  378                 i++;
  379                 len--;
  380                 data++;
  381 
  382                 if (i > BPALEN - 2) {
  383                         printf("%s\t%s\n", xout, aout);
  384                         bzero(xout, BPXLEN);
  385                         bzero(aout, BPALEN);
  386                         i = 0;
  387                         continue;
  388                 }
  389         }
  390 }
  391 
  392 static void
  393 m_printm(m)
  394         struct mbuf *m;
  395 {
  396         for (; m; m = m->m_next)
  397                 bprint(mtod(m, char *), m->m_len);
  398 }
  399 #endif

Cache object: 569c1fe62afd5894c3302ee9c75c12a7


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