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

Cache object: 9d2effe50d48def861b21472ee9d2c2c


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