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

Cache object: 780716fa6c0ae9dd3fd444b8e5ca71ce


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