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/aarp.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) 2004 Robert N. M. Watson
    3  * 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  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  */
   26 /*-
   27  * Copyright (c) 1990,1991,1994 Regents of The University of Michigan.
   28  * All Rights Reserved.
   29  *
   30  * Permission to use, copy, modify, and distribute this software and
   31  * its documentation for any purpose and without fee is hereby granted,
   32  * provided that the above copyright notice appears in all copies and
   33  * that both that copyright notice and this permission notice appear
   34  * in supporting documentation, and that the name of The University
   35  * of Michigan not be used in advertising or publicity pertaining to
   36  * distribution of the software without specific, written prior
   37  * permission. This software is supplied as is without expressed or
   38  * implied warranties of any kind.
   39  *
   40  * This product includes software developed by the University of
   41  * California, Berkeley and its contributors.
   42  *
   43  *      Research Systems Unix Group
   44  *      The University of Michigan
   45  *      c/o Wesley Craig
   46  *      535 W. William Street
   47  *      Ann Arbor, Michigan
   48  *      +1-313-764-2278
   49  *      netatalk@umich.edu
   50  *
   51  * $FreeBSD$
   52  */
   53 
   54 #include "opt_atalk.h"
   55 #include "opt_mac.h"
   56 
   57 #include <sys/param.h>
   58 #include <sys/systm.h>
   59 #include <sys/mac.h>
   60 #include <sys/mbuf.h>
   61 #include <sys/kernel.h>
   62 #include <sys/socket.h>
   63 #include <sys/syslog.h>
   64 
   65 #include <net/if.h>
   66 
   67 #include <netinet/in.h>
   68 #undef s_net
   69 #include <netinet/if_ether.h>
   70 
   71 #include <netatalk/at.h>
   72 #include <netatalk/at_var.h>
   73 #include <netatalk/aarp.h>
   74 #include <netatalk/phase2.h>
   75 #include <netatalk/at_extern.h>
   76 
   77 static void aarptfree(struct aarptab *aat);
   78 static void at_aarpinput(struct ifnet *ifp, struct mbuf *m);
   79 
   80 #define AARPTAB_BSIZ    9
   81 #define AARPTAB_NB      19
   82 #define AARPTAB_SIZE    (AARPTAB_BSIZ * AARPTAB_NB)
   83 static struct aarptab   aarptab[AARPTAB_SIZE];
   84 
   85 static struct mtx aarptab_mtx;
   86 MTX_SYSINIT(aarptab_mtx, &aarptab_mtx, "aarptab_mtx", MTX_DEF);
   87 
   88 #define AARPTAB_LOCK()          mtx_lock(&aarptab_mtx)
   89 #define AARPTAB_UNLOCK()        mtx_unlock(&aarptab_mtx)
   90 #define AARPTAB_LOCK_ASSERT()   mtx_assert(&aarptab_mtx, MA_OWNED)
   91 #define AARPTAB_UNLOCK_ASSERT() mtx_assert(&aarptab_mtx, MA_NOTOWNED)
   92 
   93 #define AARPTAB_HASH(a) \
   94     ((((a).s_net << 8) + (a).s_node) % AARPTAB_NB)
   95 
   96 #define AARPTAB_LOOK(aat, addr) { \
   97     int         n; \
   98     AARPTAB_LOCK_ASSERT(); \
   99     aat = &aarptab[ AARPTAB_HASH(addr) * AARPTAB_BSIZ ]; \
  100     for (n = 0; n < AARPTAB_BSIZ; n++, aat++) \
  101         if (aat->aat_ataddr.s_net == (addr).s_net && \
  102              aat->aat_ataddr.s_node == (addr).s_node) \
  103             break; \
  104         if (n >= AARPTAB_BSIZ) \
  105             aat = NULL; \
  106 }
  107 
  108 #define AARPT_AGE       (60 * 1)
  109 #define AARPT_KILLC     20
  110 #define AARPT_KILLI     3
  111 
  112 # if !defined(__FreeBSD__)
  113 extern u_char                   etherbroadcastaddr[6];
  114 # endif /* __FreeBSD__ */
  115 
  116 static const u_char atmulticastaddr[ 6 ] = {
  117     0x09, 0x00, 0x07, 0xff, 0xff, 0xff,
  118 };
  119 
  120 u_char  at_org_code[ 3 ] = {
  121     0x08, 0x00, 0x07,
  122 };
  123 const u_char    aarp_org_code[ 3 ] = {
  124     0x00, 0x00, 0x00,
  125 };
  126 
  127 static struct callout_handle aarptimer_ch =
  128     CALLOUT_HANDLE_INITIALIZER(&aarptimer_ch);
  129 
  130 static void
  131 aarptimer(void *ignored)
  132 {
  133     struct aarptab      *aat;
  134     int                 i;
  135 
  136     aarptimer_ch = timeout(aarptimer, (caddr_t)0, AARPT_AGE * hz);
  137     aat = aarptab;
  138     AARPTAB_LOCK();
  139     for (i = 0; i < AARPTAB_SIZE; i++, aat++) {
  140         if (aat->aat_flags == 0 || (aat->aat_flags & ATF_PERM))
  141             continue;
  142         if (++aat->aat_timer < ((aat->aat_flags & ATF_COM) ?
  143                 AARPT_KILLC : AARPT_KILLI))
  144             continue;
  145         aarptfree(aat);
  146     }
  147     AARPTAB_UNLOCK();
  148 }
  149 
  150 /* 
  151  * search through the network addresses to find one that includes
  152  * the given network.. remember to take netranges into
  153  * consideration.
  154  */
  155 struct at_ifaddr *
  156 at_ifawithnet(struct sockaddr_at  *sat)
  157 {
  158     struct at_ifaddr    *aa;
  159     struct sockaddr_at  *sat2;
  160 
  161         for (aa = at_ifaddr_list; aa != NULL; aa = aa->aa_next) {
  162                 sat2 = &(aa->aa_addr);
  163                 if (sat2->sat_addr.s_net == sat->sat_addr.s_net) {
  164                         break;
  165                 }
  166                 if((aa->aa_flags & AFA_PHASE2)
  167                 && (ntohs(aa->aa_firstnet) <= ntohs(sat->sat_addr.s_net))
  168                 && (ntohs(aa->aa_lastnet) >= ntohs(sat->sat_addr.s_net))) {
  169                         break;
  170                 }
  171         }
  172         return (aa);
  173 }
  174 
  175 static void
  176 aarpwhohas(struct ifnet *ifp, struct sockaddr_at *sat)
  177 {
  178     struct mbuf         *m;
  179     struct ether_header *eh;
  180     struct ether_aarp   *ea;
  181     struct at_ifaddr    *aa;
  182     struct llc          *llc;
  183     struct sockaddr     sa;
  184 
  185     AARPTAB_UNLOCK_ASSERT();
  186     if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL) {
  187         return;
  188     }
  189 #ifdef MAC
  190     mac_create_mbuf_linklayer(ifp, m);
  191 #endif
  192     m->m_len = sizeof(*ea);
  193     m->m_pkthdr.len = sizeof(*ea);
  194     MH_ALIGN(m, sizeof(*ea));
  195 
  196     ea = mtod(m, struct ether_aarp *);
  197     bzero((caddr_t)ea, sizeof(*ea));
  198 
  199     ea->aarp_hrd = htons(AARPHRD_ETHER);
  200     ea->aarp_pro = htons(ETHERTYPE_AT);
  201     ea->aarp_hln = sizeof(ea->aarp_sha);
  202     ea->aarp_pln = sizeof(ea->aarp_spu);
  203     ea->aarp_op = htons(AARPOP_REQUEST);
  204     bcopy(IFP2AC(ifp)->ac_enaddr, (caddr_t)ea->aarp_sha,
  205             sizeof(ea->aarp_sha));
  206 
  207     /*
  208      * We need to check whether the output ethernet type should
  209      * be phase 1 or 2. We have the interface that we'll be sending
  210      * the aarp out. We need to find an AppleTalk network on that
  211      * interface with the same address as we're looking for. If the
  212      * net is phase 2, generate an 802.2 and SNAP header.
  213      */
  214     if ((aa = at_ifawithnet(sat)) == NULL) {
  215         m_freem(m);
  216         return;
  217     }
  218 
  219     eh = (struct ether_header *)sa.sa_data;
  220 
  221     if (aa->aa_flags & AFA_PHASE2) {
  222         bcopy(atmulticastaddr, eh->ether_dhost, sizeof(eh->ether_dhost));
  223         eh->ether_type = htons(sizeof(struct llc) + sizeof(struct ether_aarp));
  224         M_PREPEND(m, sizeof(struct llc), M_DONTWAIT);
  225         if (m == NULL) {
  226             return;
  227         }
  228         llc = mtod(m, struct llc *);
  229         llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
  230         llc->llc_control = LLC_UI;
  231         bcopy(aarp_org_code, llc->llc_org_code, sizeof(aarp_org_code));
  232         llc->llc_ether_type = htons(ETHERTYPE_AARP);
  233 
  234         bcopy(&AA_SAT(aa)->sat_addr.s_net, ea->aarp_spnet,
  235                sizeof(ea->aarp_spnet));
  236         bcopy(&sat->sat_addr.s_net, ea->aarp_tpnet,
  237                sizeof(ea->aarp_tpnet));
  238         ea->aarp_spnode = AA_SAT(aa)->sat_addr.s_node;
  239         ea->aarp_tpnode = sat->sat_addr.s_node;
  240     } else {
  241         bcopy(ifp->if_broadcastaddr, (caddr_t)eh->ether_dhost,
  242                 sizeof(eh->ether_dhost));
  243         eh->ether_type = htons(ETHERTYPE_AARP);
  244 
  245         ea->aarp_spa = AA_SAT(aa)->sat_addr.s_node;
  246         ea->aarp_tpa = sat->sat_addr.s_node;
  247     }
  248 
  249 #ifdef NETATALKDEBUG
  250     printf("aarp: sending request for %u.%u\n",
  251            ntohs(AA_SAT(aa)->sat_addr.s_net),
  252            AA_SAT(aa)->sat_addr.s_node);
  253 #endif /* NETATALKDEBUG */
  254 
  255     sa.sa_len = sizeof(struct sockaddr);
  256     sa.sa_family = AF_UNSPEC;
  257     ifp->if_output(ifp, m, &sa, NULL /* route */);
  258 }
  259 
  260 int
  261 aarpresolve(ifp, m, destsat, desten)
  262     struct ifnet        *ifp;
  263     struct mbuf         *m;
  264     struct sockaddr_at  *destsat;
  265     u_char              *desten;
  266 {
  267     struct at_ifaddr    *aa;
  268     struct aarptab      *aat;
  269 
  270     if (at_broadcast(destsat)) {
  271         m->m_flags |= M_BCAST;
  272         if ((aa = at_ifawithnet(destsat)) == NULL)  {
  273             m_freem(m);
  274             return (0);
  275         }
  276         if (aa->aa_flags & AFA_PHASE2) {
  277             bcopy(atmulticastaddr, (caddr_t)desten, sizeof(atmulticastaddr));
  278         } else {
  279             bcopy(ifp->if_broadcastaddr, (caddr_t)desten,
  280                     sizeof(ifp->if_addrlen));
  281         }
  282         return (1);
  283     }
  284 
  285     AARPTAB_LOCK();
  286     AARPTAB_LOOK(aat, destsat->sat_addr);
  287     if (aat == NULL) {                  /* No entry */
  288         aat = aarptnew(&destsat->sat_addr);
  289         if (aat == NULL) { /* we should fail more gracefully! */
  290             panic("aarpresolve: no free entry");
  291         }
  292         goto done;
  293     }
  294     /* found an entry */
  295     aat->aat_timer = 0;
  296     if (aat->aat_flags & ATF_COM) {     /* entry is COMplete */
  297         bcopy((caddr_t)aat->aat_enaddr, (caddr_t)desten,
  298                 sizeof(aat->aat_enaddr));
  299         AARPTAB_UNLOCK();
  300         return (1);
  301     }
  302     /* entry has not completed */
  303     if (aat->aat_hold) {
  304         m_freem(aat->aat_hold);
  305     }
  306 done:
  307     aat->aat_hold = m;
  308     AARPTAB_UNLOCK();
  309     aarpwhohas(ifp, destsat);
  310     return (0);
  311 }
  312 
  313 void
  314 aarpintr(m)
  315     struct mbuf         *m;
  316 {
  317     struct arphdr       *ar;
  318     struct ifnet        *ifp;
  319 
  320     ifp = m->m_pkthdr.rcvif;
  321     if (ifp->if_flags & IFF_NOARP)
  322         goto out;
  323 
  324     if (m->m_len < sizeof(struct arphdr)) {
  325         goto out;
  326     }
  327 
  328     ar = mtod(m, struct arphdr *);
  329     if (ntohs(ar->ar_hrd) != AARPHRD_ETHER) {
  330         goto out;
  331     }
  332     
  333     if (m->m_len < sizeof(struct arphdr) + 2 * ar->ar_hln +
  334             2 * ar->ar_pln) {
  335         goto out;
  336     }
  337     
  338     switch(ntohs(ar->ar_pro)) {
  339     case ETHERTYPE_AT :
  340         at_aarpinput(ifp, m);
  341         return;
  342 
  343     default:
  344         break;
  345     }
  346 
  347 out:
  348     m_freem(m);
  349 }
  350 
  351 static void
  352 at_aarpinput(struct ifnet *ifp, struct mbuf *m)
  353 {
  354     struct ether_aarp   *ea;
  355     struct at_ifaddr    *aa;
  356     struct aarptab      *aat;
  357     struct ether_header *eh;
  358     struct llc          *llc;
  359     struct sockaddr_at  sat;
  360     struct sockaddr     sa;
  361     struct at_addr      spa, tpa, ma;
  362     int                 op;
  363     u_short             net;
  364 
  365     ea = mtod(m, struct ether_aarp *);
  366 
  367     /* Check to see if from my hardware address */
  368     if (!bcmp((caddr_t)ea->aarp_sha, IFP2AC(ifp)->ac_enaddr,
  369             sizeof(IFP2AC(ifp)->ac_enaddr))) {
  370         m_freem(m);
  371         return;
  372     }
  373 
  374     op = ntohs(ea->aarp_op);
  375     bcopy(ea->aarp_tpnet, &net, sizeof(net));
  376 
  377     if (net != 0) { /* should be ATADDR_ANYNET? */
  378         sat.sat_len = sizeof(struct sockaddr_at);
  379         sat.sat_family = AF_APPLETALK;
  380         sat.sat_addr.s_net = net;
  381         if ((aa = at_ifawithnet(&sat)) == NULL) {
  382             m_freem(m);
  383             return;
  384         }
  385         bcopy(ea->aarp_spnet, &spa.s_net, sizeof(spa.s_net));
  386         bcopy(ea->aarp_tpnet, &tpa.s_net, sizeof(tpa.s_net));
  387     } else {
  388         /*
  389          * Since we don't know the net, we just look for the first
  390          * phase 1 address on the interface.
  391          */
  392         for (aa = (struct at_ifaddr *)TAILQ_FIRST(&ifp->if_addrhead); aa;
  393                 aa = (struct at_ifaddr *)aa->aa_ifa.ifa_link.tqe_next) {
  394             if (AA_SAT(aa)->sat_family == AF_APPLETALK &&
  395                     (aa->aa_flags & AFA_PHASE2) == 0) {
  396                 break;
  397             }
  398         }
  399         if (aa == NULL) {
  400             m_freem(m);
  401             return;
  402         }
  403         tpa.s_net = spa.s_net = AA_SAT(aa)->sat_addr.s_net;
  404     }
  405 
  406     spa.s_node = ea->aarp_spnode;
  407     tpa.s_node = ea->aarp_tpnode;
  408     ma.s_net = AA_SAT(aa)->sat_addr.s_net;
  409     ma.s_node = AA_SAT(aa)->sat_addr.s_node;
  410 
  411     /*
  412      * This looks like it's from us.
  413      */
  414     if (spa.s_net == ma.s_net && spa.s_node == ma.s_node) {
  415         if (aa->aa_flags & AFA_PROBING) {
  416             /*
  417              * We're probing, someone either responded to our probe, or
  418              * probed for the same address we'd like to use. Change the
  419              * address we're probing for.
  420              */
  421             untimeout(aarpprobe, ifp, aa->aa_ch);
  422             wakeup(aa);
  423             m_freem(m);
  424             return;
  425         } else if (op != AARPOP_PROBE) {
  426             /*
  427              * This is not a probe, and we're not probing. This means
  428              * that someone's saying they have the same source address
  429              * as the one we're using. Get upset...
  430              */
  431             log(LOG_ERR,
  432                     "aarp: duplicate AT address!! %x:%x:%x:%x:%x:%x\n",
  433                     ea->aarp_sha[ 0 ], ea->aarp_sha[ 1 ], ea->aarp_sha[ 2 ],
  434                     ea->aarp_sha[ 3 ], ea->aarp_sha[ 4 ], ea->aarp_sha[ 5 ]);
  435             m_freem(m);
  436             return;
  437         }
  438     }
  439 
  440     AARPTAB_LOCK();
  441     AARPTAB_LOOK(aat, spa);
  442     if (aat != NULL) {
  443         if (op == AARPOP_PROBE) {
  444             /*
  445              * Someone's probing for spa, dealocate the one we've got,
  446              * so that if the prober keeps the address, we'll be able
  447              * to arp for him.
  448              */
  449             aarptfree(aat);
  450             AARPTAB_UNLOCK();
  451             m_freem(m);
  452             return;
  453         }
  454 
  455         bcopy((caddr_t)ea->aarp_sha, (caddr_t)aat->aat_enaddr,
  456                 sizeof(ea->aarp_sha));
  457         aat->aat_flags |= ATF_COM;
  458         if (aat->aat_hold) {
  459             struct mbuf *mhold = aat->aat_hold;
  460             aat->aat_hold = NULL;
  461             AARPTAB_UNLOCK();
  462             sat.sat_len = sizeof(struct sockaddr_at);
  463             sat.sat_family = AF_APPLETALK;
  464             sat.sat_addr = spa;
  465             (*ifp->if_output)(ifp, mhold,
  466                     (struct sockaddr *)&sat, NULL); /* XXX */
  467         } else
  468             AARPTAB_UNLOCK();
  469     } else if ((tpa.s_net == ma.s_net)
  470            && (tpa.s_node == ma.s_node)
  471            && (op != AARPOP_PROBE)
  472            && ((aat = aarptnew(&spa)) != NULL)) {
  473                 bcopy((caddr_t)ea->aarp_sha, (caddr_t)aat->aat_enaddr,
  474                     sizeof(ea->aarp_sha));
  475                 aat->aat_flags |= ATF_COM;
  476                 AARPTAB_UNLOCK();
  477     } else
  478         AARPTAB_UNLOCK();
  479 
  480     /*
  481      * Don't respond to responses, and never respond if we're
  482      * still probing.
  483      */
  484     if (tpa.s_net != ma.s_net || tpa.s_node != ma.s_node ||
  485             op == AARPOP_RESPONSE || (aa->aa_flags & AFA_PROBING)) {
  486         m_freem(m);
  487         return;
  488     }
  489 
  490     bcopy((caddr_t)ea->aarp_sha, (caddr_t)ea->aarp_tha,
  491             sizeof(ea->aarp_sha));
  492     bcopy(IFP2AC(ifp)->ac_enaddr, (caddr_t)ea->aarp_sha,
  493             sizeof(ea->aarp_sha));
  494 
  495     /* XXX */
  496     eh = (struct ether_header *)sa.sa_data;
  497     bcopy((caddr_t)ea->aarp_tha, (caddr_t)eh->ether_dhost,
  498             sizeof(eh->ether_dhost));
  499 
  500     if (aa->aa_flags & AFA_PHASE2) {
  501         eh->ether_type = htons(sizeof(struct llc) +
  502                 sizeof(struct ether_aarp));
  503         M_PREPEND(m, sizeof(struct llc), M_DONTWAIT);
  504         if (m == NULL) {
  505             return;
  506         }
  507         llc = mtod(m, struct llc *);
  508         llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
  509         llc->llc_control = LLC_UI;
  510         bcopy(aarp_org_code, llc->llc_org_code, sizeof(aarp_org_code));
  511         llc->llc_ether_type = htons(ETHERTYPE_AARP);
  512 
  513         bcopy(ea->aarp_spnet, ea->aarp_tpnet, sizeof(ea->aarp_tpnet));
  514         bcopy(&ma.s_net, ea->aarp_spnet, sizeof(ea->aarp_spnet));
  515     } else {
  516         eh->ether_type = htons(ETHERTYPE_AARP);
  517     }
  518 
  519     ea->aarp_tpnode = ea->aarp_spnode;
  520     ea->aarp_spnode = ma.s_node;
  521     ea->aarp_op = htons(AARPOP_RESPONSE);
  522 
  523     sa.sa_len = sizeof(struct sockaddr);
  524     sa.sa_family = AF_UNSPEC;
  525     (*ifp->if_output)(ifp, m, &sa, NULL); /* XXX */
  526     return;
  527 }
  528 
  529 static void
  530 aarptfree(struct aarptab *aat)
  531 {
  532 
  533     AARPTAB_LOCK_ASSERT();
  534     if (aat->aat_hold)
  535         m_freem(aat->aat_hold);
  536     aat->aat_hold = NULL;
  537     aat->aat_timer = aat->aat_flags = 0;
  538     aat->aat_ataddr.s_net = 0;
  539     aat->aat_ataddr.s_node = 0;
  540 }
  541 
  542 struct aarptab *
  543 aarptnew(addr)
  544     struct at_addr      *addr;
  545 {
  546     int                 n;
  547     int                 oldest = -1;
  548     struct aarptab      *aat, *aato = NULL;
  549     static int          first = 1;
  550 
  551     AARPTAB_LOCK_ASSERT();
  552     if (first) {
  553         first = 0;
  554         aarptimer_ch = timeout(aarptimer, (caddr_t)0, hz);
  555     }
  556     aat = &aarptab[ AARPTAB_HASH(*addr) * AARPTAB_BSIZ ];
  557     for (n = 0; n < AARPTAB_BSIZ; n++, aat++) {
  558         if (aat->aat_flags == 0)
  559             goto out;
  560         if (aat->aat_flags & ATF_PERM)
  561             continue;
  562         if ((int) aat->aat_timer > oldest) {
  563             oldest = aat->aat_timer;
  564             aato = aat;
  565         }
  566     }
  567     if (aato == NULL)
  568         return (NULL);
  569     aat = aato;
  570     aarptfree(aat);
  571 out:
  572     aat->aat_ataddr = *addr;
  573     aat->aat_flags = ATF_INUSE;
  574     return (aat);
  575 }
  576 
  577 
  578 void
  579 aarpprobe(void *arg)
  580 {
  581     struct ifnet        *ifp = arg;
  582     struct mbuf         *m;
  583     struct ether_header *eh;
  584     struct ether_aarp   *ea;
  585     struct at_ifaddr    *aa;
  586     struct llc          *llc;
  587     struct sockaddr     sa;
  588 
  589     /*
  590      * We need to check whether the output ethernet type should
  591      * be phase 1 or 2. We have the interface that we'll be sending
  592      * the aarp out. We need to find an AppleTalk network on that
  593      * interface with the same address as we're looking for. If the
  594      * net is phase 2, generate an 802.2 and SNAP header.
  595      */
  596     for (aa = (struct at_ifaddr *)TAILQ_FIRST(&ifp->if_addrhead); aa;
  597             aa = (struct at_ifaddr *)aa->aa_ifa.ifa_link.tqe_next) {
  598         if (AA_SAT(aa)->sat_family == AF_APPLETALK &&
  599                 (aa->aa_flags & AFA_PROBING)) {
  600             break;
  601         }
  602     }
  603     if (aa == NULL) {           /* serious error XXX */
  604         printf("aarpprobe why did this happen?!\n");
  605         return;
  606     }
  607 
  608     if (aa->aa_probcnt <= 0) {
  609         aa->aa_flags &= ~AFA_PROBING;
  610         wakeup(aa);
  611         return;
  612     } else {
  613         aa->aa_ch = timeout(aarpprobe, (caddr_t)ifp, hz / 5);
  614     }
  615 
  616     if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL) {
  617         return;
  618     }
  619 #ifdef MAC
  620     mac_create_mbuf_linklayer(ifp, m);
  621 #endif
  622     m->m_len = sizeof(*ea);
  623     m->m_pkthdr.len = sizeof(*ea);
  624     MH_ALIGN(m, sizeof(*ea));
  625 
  626     ea = mtod(m, struct ether_aarp *);
  627     bzero((caddr_t)ea, sizeof(*ea));
  628 
  629     ea->aarp_hrd = htons(AARPHRD_ETHER);
  630     ea->aarp_pro = htons(ETHERTYPE_AT);
  631     ea->aarp_hln = sizeof(ea->aarp_sha);
  632     ea->aarp_pln = sizeof(ea->aarp_spu);
  633     ea->aarp_op = htons(AARPOP_PROBE);
  634     bcopy(IFP2AC(ifp)->ac_enaddr, (caddr_t)ea->aarp_sha,
  635             sizeof(ea->aarp_sha));
  636 
  637     eh = (struct ether_header *)sa.sa_data;
  638 
  639     if (aa->aa_flags & AFA_PHASE2) {
  640         bcopy(atmulticastaddr, eh->ether_dhost, sizeof(eh->ether_dhost));
  641         eh->ether_type = htons(sizeof(struct llc) +
  642                 sizeof(struct ether_aarp));
  643         M_PREPEND(m, sizeof(struct llc), M_TRYWAIT);
  644         if (m == NULL) {
  645             return;
  646         }
  647         llc = mtod(m, struct llc *);
  648         llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
  649         llc->llc_control = LLC_UI;
  650         bcopy(aarp_org_code, llc->llc_org_code, sizeof(aarp_org_code));
  651         llc->llc_ether_type = htons(ETHERTYPE_AARP);
  652 
  653         bcopy(&AA_SAT(aa)->sat_addr.s_net, ea->aarp_spnet,
  654                 sizeof(ea->aarp_spnet));
  655         bcopy(&AA_SAT(aa)->sat_addr.s_net, ea->aarp_tpnet,
  656                 sizeof(ea->aarp_tpnet));
  657         ea->aarp_spnode = ea->aarp_tpnode = AA_SAT(aa)->sat_addr.s_node;
  658     } else {
  659         bcopy(ifp->if_broadcastaddr, (caddr_t)eh->ether_dhost,
  660                 sizeof(eh->ether_dhost));
  661         eh->ether_type = htons(ETHERTYPE_AARP);
  662         ea->aarp_spa = ea->aarp_tpa = AA_SAT(aa)->sat_addr.s_node;
  663     }
  664 
  665 #ifdef NETATALKDEBUG
  666     printf("aarp: sending probe for %u.%u\n",
  667            ntohs(AA_SAT(aa)->sat_addr.s_net),
  668            AA_SAT(aa)->sat_addr.s_node);
  669 #endif /* NETATALKDEBUG */
  670 
  671     sa.sa_len = sizeof(struct sockaddr);
  672     sa.sa_family = AF_UNSPEC;
  673     (*ifp->if_output)(ifp, m, &sa, NULL); /* XXX */
  674     aa->aa_probcnt--;
  675 }
  676 
  677 void
  678 aarp_clean(void)
  679 {
  680     struct aarptab      *aat;
  681     int                 i;
  682 
  683     untimeout(aarptimer, 0, aarptimer_ch);
  684     AARPTAB_LOCK();
  685     for (i = 0, aat = aarptab; i < AARPTAB_SIZE; i++, aat++) {
  686         if (aat->aat_hold) {
  687             m_freem(aat->aat_hold);
  688             aat->aat_hold = NULL;
  689         }
  690     }
  691     AARPTAB_UNLOCK();
  692 }

Cache object: 0b0f2f250f1da271b01b00626bfd73ad


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