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

Cache object: e3c97861b4c52a02e9624a35dc2a04db


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