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.19 2008/04/24 11:38:37 ad 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.19 2008/04/24 11:38:37 ad 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/ddp_private.h>
   50 #include <netatalk/at_extern.h>
   51 
   52 int             ddp_forward = 1;
   53 int             ddp_firewall = 0;
   54 extern int      ddp_cksum;
   55 void            ddp_input __P((struct mbuf *, struct ifnet *,
   56     struct elaphdr *, int));
   57 
   58 /*
   59  * Could probably merge these two code segments a little better...
   60  */
   61 void
   62 atintr()
   63 {
   64         struct elaphdr *elhp, elh;
   65         struct ifnet   *ifp;
   66         struct mbuf    *m;
   67         struct at_ifaddr *aa;
   68         int             s;
   69 
   70         mutex_enter(softnet_lock);
   71         for (;;) {
   72                 s = splnet();
   73 
   74                 IF_DEQUEUE(&atintrq2, m);
   75 
   76                 splx(s);
   77 
   78                 if (m == 0)     /* no more queued packets */
   79                         break;
   80 
   81                 m_claimm(m, &atalk_rx_mowner);
   82                 ifp = m->m_pkthdr.rcvif;
   83                 for (aa = at_ifaddr.tqh_first; aa; aa = aa->aa_list.tqe_next) {
   84                         if (aa->aa_ifp == ifp && (aa->aa_flags & AFA_PHASE2))
   85                                 break;
   86                 }
   87                 if (aa == NULL) {       /* ifp not an appletalk interface */
   88                         m_freem(m);
   89                         continue;
   90                 }
   91                 ddp_input(m, ifp, (struct elaphdr *) NULL, 2);
   92         }
   93 
   94         for (;;) {
   95                 s = splnet();
   96 
   97                 IF_DEQUEUE(&atintrq1, m);
   98 
   99                 splx(s);
  100 
  101                 if (m == 0)     /* no more queued packets */
  102 
  103                         break;
  104 
  105                 m_claimm(m, &atalk_rx_mowner);
  106                 ifp = m->m_pkthdr.rcvif;
  107                 for (aa = at_ifaddr.tqh_first; aa; aa = aa->aa_list.tqe_next) {
  108                         if (aa->aa_ifp == ifp &&
  109                             (aa->aa_flags & AFA_PHASE2) == 0)
  110                                 break;
  111                 }
  112                 if (aa == NULL) {       /* ifp not an appletalk interface */
  113                         m_freem(m);
  114                         continue;
  115                 }
  116                 if (m->m_len < SZ_ELAPHDR &&
  117                     ((m = m_pullup(m, SZ_ELAPHDR)) == 0)) {
  118                         DDP_STATINC(DDP_STAT_TOOSHORT);
  119                         continue;
  120                 }
  121                 elhp = mtod(m, struct elaphdr *);
  122                 m_adj(m, SZ_ELAPHDR);
  123 
  124                 if (elhp->el_type == ELAP_DDPEXTEND) {
  125                         ddp_input(m, ifp, (struct elaphdr *) NULL, 1);
  126                 } else {
  127                         bcopy((void *) elhp, (void *) & elh, SZ_ELAPHDR);
  128                         ddp_input(m, ifp, &elh, 1);
  129                 }
  130         }
  131         mutex_exit(softnet_lock);
  132 }
  133 
  134 struct route    forwro;
  135 
  136 void
  137 ddp_input(m, ifp, elh, phase)
  138         struct mbuf    *m;
  139         struct ifnet   *ifp;
  140         struct elaphdr *elh;
  141         int             phase;
  142 {
  143         struct rtentry *rt;
  144         struct sockaddr_at from, to;
  145         struct ddpshdr *dsh, ddps;
  146         struct at_ifaddr *aa;
  147         struct ddpehdr *deh = NULL, ddpe;
  148         struct ddpcb   *ddp;
  149         int             dlen, mlen;
  150         u_short         cksum = 0;
  151         union {
  152                 struct sockaddr         dst;
  153                 struct sockaddr_at      dsta;
  154         } u;
  155 
  156         bzero((void *) & from, sizeof(struct sockaddr_at));
  157         if (elh) {
  158                 DDP_STATINC(DDP_STAT_SHORT);
  159 
  160                 if (m->m_len < sizeof(struct ddpshdr) &&
  161                     ((m = m_pullup(m, sizeof(struct ddpshdr))) == 0)) {
  162                         DDP_STATINC(DDP_STAT_TOOSHORT);
  163                         return;
  164                 }
  165                 dsh = mtod(m, struct ddpshdr *);
  166                 bcopy((void *) dsh, (void *) & ddps, sizeof(struct ddpshdr));
  167                 ddps.dsh_bytes = ntohl(ddps.dsh_bytes);
  168                 dlen = ddps.dsh_len;
  169 
  170                 to.sat_addr.s_net = ATADDR_ANYNET;
  171                 to.sat_addr.s_node = elh->el_dnode;
  172                 to.sat_port = ddps.dsh_dport;
  173                 from.sat_addr.s_net = ATADDR_ANYNET;
  174                 from.sat_addr.s_node = elh->el_snode;
  175                 from.sat_port = ddps.dsh_sport;
  176 
  177                 for (aa = at_ifaddr.tqh_first; aa; aa = aa->aa_list.tqe_next) {
  178                         if (aa->aa_ifp == ifp &&
  179                             (aa->aa_flags & AFA_PHASE2) == 0 &&
  180                             (AA_SAT(aa)->sat_addr.s_node ==
  181                              to.sat_addr.s_node ||
  182                              to.sat_addr.s_node == ATADDR_BCAST))
  183                                 break;
  184                 }
  185                 if (aa == NULL) {
  186                         m_freem(m);
  187                         return;
  188                 }
  189         } else {
  190                 DDP_STATINC(DDP_STAT_LONG);
  191 
  192                 if (m->m_len < sizeof(struct ddpehdr) &&
  193                     ((m = m_pullup(m, sizeof(struct ddpehdr))) == 0)) {
  194                         DDP_STATINC(DDP_STAT_TOOSHORT);
  195                         return;
  196                 }
  197                 deh = mtod(m, struct ddpehdr *);
  198                 bcopy((void *) deh, (void *) & ddpe, sizeof(struct ddpehdr));
  199                 ddpe.deh_bytes = ntohl(ddpe.deh_bytes);
  200                 dlen = ddpe.deh_len;
  201 
  202                 if ((cksum = ddpe.deh_sum) == 0) {
  203                         DDP_STATINC(DDP_STAT_NOSUM);
  204                 }
  205                 from.sat_addr.s_net = ddpe.deh_snet;
  206                 from.sat_addr.s_node = ddpe.deh_snode;
  207                 from.sat_port = ddpe.deh_sport;
  208                 to.sat_addr.s_net = ddpe.deh_dnet;
  209                 to.sat_addr.s_node = ddpe.deh_dnode;
  210                 to.sat_port = ddpe.deh_dport;
  211 
  212                 if (to.sat_addr.s_net == ATADDR_ANYNET) {
  213                         for (aa = at_ifaddr.tqh_first; aa;
  214                             aa = aa->aa_list.tqe_next) {
  215                                 if (phase == 1 && (aa->aa_flags & AFA_PHASE2))
  216                                         continue;
  217 
  218                                 if (phase == 2 &&
  219                                     (aa->aa_flags & AFA_PHASE2) == 0)
  220                                         continue;
  221 
  222                                 if (aa->aa_ifp == ifp &&
  223                                     (AA_SAT(aa)->sat_addr.s_node ==
  224                                      to.sat_addr.s_node ||
  225                                      to.sat_addr.s_node == ATADDR_BCAST ||
  226                                      (ifp->if_flags & IFF_LOOPBACK)))
  227                                         break;
  228                         }
  229                 } else {
  230                         for (aa = at_ifaddr.tqh_first; aa;
  231                             aa = aa->aa_list.tqe_next) {
  232                                 if (to.sat_addr.s_net == aa->aa_firstnet &&
  233                                     to.sat_addr.s_node == 0)
  234                                         break;
  235 
  236                                 if ((ntohs(to.sat_addr.s_net) <
  237                                      ntohs(aa->aa_firstnet) ||
  238                                      ntohs(to.sat_addr.s_net) >
  239                                      ntohs(aa->aa_lastnet)) &&
  240                                     (ntohs(to.sat_addr.s_net) < 0xff00 ||
  241                                      ntohs(to.sat_addr.s_net) > 0xfffe))
  242                                         continue;
  243 
  244                                 if (to.sat_addr.s_node !=
  245                                     AA_SAT(aa)->sat_addr.s_node &&
  246                                     to.sat_addr.s_node != ATADDR_BCAST)
  247                                         continue;
  248 
  249                                 break;
  250                         }
  251                 }
  252         }
  253 
  254         /*
  255          * Adjust the length, removing any padding that may have been added
  256          * at a link layer.  We do this before we attempt to forward a packet,
  257          * possibly on a different media.
  258          */
  259         mlen = m->m_pkthdr.len;
  260         if (mlen < dlen) {
  261                 DDP_STATINC(DDP_STAT_TOOSMALL);
  262                 m_freem(m);
  263                 return;
  264         }
  265         if (mlen > dlen) {
  266                 m_adj(m, dlen - mlen);
  267         }
  268         /*
  269          * XXX Should we deliver broadcasts locally, also, or rely on the
  270          * link layer to give us a copy?  For the moment, the latter.
  271          */
  272         if (aa == NULL || (to.sat_addr.s_node == ATADDR_BCAST &&
  273                 aa->aa_ifp != ifp && (ifp->if_flags & IFF_LOOPBACK) == 0)) {
  274                 if (ddp_forward == 0) {
  275                         m_freem(m);
  276                         return;
  277                 }
  278                 sockaddr_at_init(&u.dsta, &to.sat_addr, 0);
  279                 rt = rtcache_lookup(&forwro, &u.dst);
  280 #if 0           /* XXX The if-condition is always false.  What was this
  281                  * actually trying to test?
  282                  */
  283                 if (to.sat_addr.s_net !=
  284                     satocsat(rtcache_getdst(&forwro))->sat_addr.s_net &&
  285                     ddpe.deh_hops == DDP_MAXHOPS) {
  286                         m_freem(m);
  287                         return;
  288                 }
  289 #endif
  290                 if (ddp_firewall && (rt == NULL || rt->rt_ifp != ifp)) {
  291                         m_freem(m);
  292                         return;
  293                 }
  294                 ddpe.deh_hops++;
  295                 ddpe.deh_bytes = htonl(ddpe.deh_bytes);
  296                 bcopy((void *) & ddpe, (void *) deh, sizeof(u_short));/*XXX*/
  297                 if (ddp_route(m, &forwro)) {
  298                         DDP_STATINC(DDP_STAT_CANTFORWARD);
  299                 } else {
  300                         DDP_STATINC(DDP_STAT_FORWARD);
  301                 }
  302                 return;
  303         }
  304         from.sat_len = sizeof(struct sockaddr_at);
  305         from.sat_family = AF_APPLETALK;
  306 
  307         if (elh) {
  308                 m_adj(m, sizeof(struct ddpshdr));
  309         } else {
  310                 if (ddp_cksum && cksum && cksum != at_cksum(m, sizeof(int))) {
  311                         DDP_STATINC(DDP_STAT_BADSUM);
  312                         m_freem(m);
  313                         return;
  314                 }
  315                 m_adj(m, sizeof(struct ddpehdr));
  316         }
  317 
  318         if ((ddp = ddp_search(&from, &to, aa)) == NULL) {
  319                 m_freem(m);
  320                 return;
  321         }
  322         if (sbappendaddr(&ddp->ddp_socket->so_rcv, (struct sockaddr *) & from,
  323                          m, (struct mbuf *) 0) == 0) {
  324                 DDP_STATINC(DDP_STAT_NOSOCKSPACE);
  325                 m_freem(m);
  326                 return;
  327         }
  328 #if IFA_STATS
  329         if (aa)
  330                 aa->aa_ifa.ifa_data.ifad_inbytes += dlen;
  331 #endif
  332         sorwakeup(ddp->ddp_socket);
  333 }
  334 
  335 #if 0
  336 
  337 #define BPXLEN  48
  338 #define BPALEN  16
  339 #include <ctype.h>
  340 
  341 static void
  342 bprint(data, len)
  343         char *data;
  344         int len;
  345 {
  346         char            xout[BPXLEN], aout[BPALEN];
  347         int             i = 0;
  348 
  349         bzero(xout, BPXLEN);
  350         bzero(aout, BPALEN);
  351 
  352         for (;;) {
  353                 if (len < 1) {
  354                         if (i != 0) {
  355                                 printf("%s\t%s\n", xout, aout);
  356                         }
  357                         printf("%s\n", "(end)");
  358                         break;
  359                 }
  360                 xout[(i * 3)] = hexdigits[(*data & 0xf0) >> 4];
  361                 xout[(i * 3) + 1] = hexdigits[*data & 0x0f];
  362 
  363                 if ((u_char) * data < 0x7f && (u_char) * data > 0x20) {
  364                         aout[i] = *data;
  365                 } else {
  366                         aout[i] = '.';
  367                 }
  368 
  369                 xout[(i * 3) + 2] = ' ';
  370 
  371                 i++;
  372                 len--;
  373                 data++;
  374 
  375                 if (i > BPALEN - 2) {
  376                         printf("%s\t%s\n", xout, aout);
  377                         bzero(xout, BPXLEN);
  378                         bzero(aout, BPALEN);
  379                         i = 0;
  380                         continue;
  381                 }
  382         }
  383 }
  384 
  385 static void
  386 m_printm(m)
  387         struct mbuf *m;
  388 {
  389         for (; m; m = m->m_next)
  390                 bprint(mtod(m, char *), m->m_len);
  391 }
  392 #endif

Cache object: 4e10ed9d04bd520e1a9af70898eb48a3


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