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         op = ntohs(ea->aarp_op);
  358         bcopy(ea->aarp_tpnet, &net, sizeof(net));
  359 
  360         if (net != 0) {
  361                 /* Should be ATADDR_ANYNET? */
  362                 sat.sat_len = sizeof(struct sockaddr_at);
  363                 sat.sat_family = AF_APPLETALK;
  364                 sat.sat_addr.s_net = net;
  365                 if ((aa = at_ifawithnet(&sat)) == NULL) {
  366                         m_freem(m);
  367                         return;
  368                 }
  369                 bcopy(ea->aarp_spnet, &spa.s_net, sizeof(spa.s_net));
  370                 bcopy(ea->aarp_tpnet, &tpa.s_net, sizeof(tpa.s_net));
  371         } else {
  372                 /*
  373                  * Since we don't know the net, we just look for the first
  374                  * phase 1 address on the interface.
  375                  */
  376                 for (aa = (struct at_ifaddr *)TAILQ_FIRST(&ifp->if_addrhead);
  377                     aa;
  378                     aa = (struct at_ifaddr *)aa->aa_ifa.ifa_link.tqe_next) {
  379                         if (AA_SAT(aa)->sat_family == AF_APPLETALK &&
  380                             (aa->aa_flags & AFA_PHASE2) == 0) {
  381                                 break;
  382                         }
  383                 }
  384                 if (aa == NULL) {
  385                         m_freem(m);
  386                         return;
  387                 }
  388                 tpa.s_net = spa.s_net = AA_SAT(aa)->sat_addr.s_net;
  389         }
  390 
  391         spa.s_node = ea->aarp_spnode;
  392         tpa.s_node = ea->aarp_tpnode;
  393         ma.s_net = AA_SAT(aa)->sat_addr.s_net;
  394         ma.s_node = AA_SAT(aa)->sat_addr.s_node;
  395 
  396         /*
  397          * This looks like it's from us.
  398          */
  399         if (spa.s_net == ma.s_net && spa.s_node == ma.s_node) {
  400                 if (aa->aa_flags & AFA_PROBING) {
  401                         /*
  402                          * We're probing, someone either responded to our
  403                          * probe, or probed for the same address we'd like to
  404                          * use. Change the address we're probing for.
  405                          */
  406                         callout_stop(&aa->aa_callout);
  407                         wakeup(aa);
  408                         m_freem(m);
  409                         return;
  410                 } else if (op != AARPOP_PROBE) {
  411                         /*
  412                          * This is not a probe, and we're not probing.  This
  413                          * means that someone's saying they have the same
  414                          * source address as the one we're using.  Get upset.
  415                          */
  416                         log(LOG_ERR,
  417                             "aarp: duplicate AT address!! %x:%x:%x:%x:%x:%x\n",
  418                             ea->aarp_sha[0], ea->aarp_sha[1],
  419                             ea->aarp_sha[2], ea->aarp_sha[3],
  420                             ea->aarp_sha[4], ea->aarp_sha[5]);
  421                         m_freem(m);
  422                         return;
  423                 }
  424         }
  425 
  426         AARPTAB_LOCK();
  427         AARPTAB_LOOK(aat, spa);
  428         if (aat != NULL) {
  429                 if (op == AARPOP_PROBE) {
  430                         /*
  431                          * Someone's probing for spa, dealocate the one we've
  432                          * got, so that if the prober keeps the address,
  433                          * we'll be able to arp for him.
  434                          */
  435                         aarptfree(aat);
  436                         AARPTAB_UNLOCK();
  437                         m_freem(m);
  438                         return;
  439                 }
  440 
  441                 bcopy((caddr_t)ea->aarp_sha, (caddr_t)aat->aat_enaddr,
  442                     sizeof(ea->aarp_sha));
  443                 aat->aat_flags |= ATF_COM;
  444                 if (aat->aat_hold) {
  445                         struct mbuf *mhold = aat->aat_hold;
  446                         aat->aat_hold = NULL;
  447                         AARPTAB_UNLOCK();
  448                         sat.sat_len = sizeof(struct sockaddr_at);
  449                         sat.sat_family = AF_APPLETALK;
  450                         sat.sat_addr = spa;
  451                         (*ifp->if_output)(ifp, mhold,
  452                             (struct sockaddr *)&sat, NULL); /* XXX */
  453                 } else
  454                         AARPTAB_UNLOCK();
  455         } else if ((tpa.s_net == ma.s_net) && (tpa.s_node == ma.s_node)
  456             && (op != AARPOP_PROBE) && ((aat = aarptnew(&spa)) != NULL)) {
  457                 bcopy((caddr_t)ea->aarp_sha, (caddr_t)aat->aat_enaddr,
  458                     sizeof(ea->aarp_sha));
  459                 aat->aat_flags |= ATF_COM;
  460                 AARPTAB_UNLOCK();
  461         } else
  462                 AARPTAB_UNLOCK();
  463 
  464         /*
  465          * Don't respond to responses, and never respond if we're still
  466          * probing.
  467          */
  468         if (tpa.s_net != ma.s_net || tpa.s_node != ma.s_node ||
  469             op == AARPOP_RESPONSE || (aa->aa_flags & AFA_PROBING)) {
  470                 m_freem(m);
  471                 return;
  472         }
  473 
  474         bcopy((caddr_t)ea->aarp_sha, (caddr_t)ea->aarp_tha,
  475             sizeof(ea->aarp_sha));
  476         bcopy(IF_LLADDR(ifp), (caddr_t)ea->aarp_sha, sizeof(ea->aarp_sha));
  477 
  478         /* XXX */
  479         eh = (struct ether_header *)sa.sa_data;
  480         bcopy((caddr_t)ea->aarp_tha, (caddr_t)eh->ether_dhost,
  481             sizeof(eh->ether_dhost));
  482 
  483         if (aa->aa_flags & AFA_PHASE2) {
  484                 eh->ether_type = htons(sizeof(struct llc) +
  485                     sizeof(struct ether_aarp));
  486                 M_PREPEND(m, sizeof(struct llc), M_DONTWAIT);
  487                 if (m == NULL)
  488                         return;
  489                 llc = mtod(m, struct llc *);
  490                 llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
  491                 llc->llc_control = LLC_UI;
  492                 bcopy(aarp_org_code, llc->llc_org_code,
  493                     sizeof(aarp_org_code));
  494                 llc->llc_ether_type = htons(ETHERTYPE_AARP);
  495 
  496                 bcopy(ea->aarp_spnet, ea->aarp_tpnet,
  497                     sizeof(ea->aarp_tpnet));
  498                 bcopy(&ma.s_net, ea->aarp_spnet, sizeof(ea->aarp_spnet));
  499         } else
  500                 eh->ether_type = htons(ETHERTYPE_AARP);
  501 
  502         ea->aarp_tpnode = ea->aarp_spnode;
  503         ea->aarp_spnode = ma.s_node;
  504         ea->aarp_op = htons(AARPOP_RESPONSE);
  505 
  506         sa.sa_len = sizeof(struct sockaddr);
  507         sa.sa_family = AF_UNSPEC;
  508         (*ifp->if_output)(ifp, m, &sa, NULL); /* XXX */
  509         return;
  510 }
  511 
  512 static void
  513 aarptfree(struct aarptab *aat)
  514 {
  515 
  516         AARPTAB_LOCK_ASSERT();
  517         if (aat->aat_hold)
  518                 m_freem(aat->aat_hold);
  519         aat->aat_hold = NULL;
  520         aat->aat_timer = aat->aat_flags = 0;
  521         aat->aat_ataddr.s_net = 0;
  522         aat->aat_ataddr.s_node = 0;
  523 }
  524 
  525 struct aarptab *
  526 aarptnew(struct at_addr *addr)
  527 {
  528         int n;
  529         int oldest = -1;
  530         struct aarptab *aat, *aato = NULL;
  531         static int first = 1;
  532 
  533         AARPTAB_LOCK_ASSERT();
  534         if (first) {
  535                 first = 0;
  536                 aarptimer_ch = timeout(aarptimer, (caddr_t)0, hz);
  537         }
  538         aat = &aarptab[AARPTAB_HASH(*addr) * AARPTAB_BSIZ];
  539         for (n = 0; n < AARPTAB_BSIZ; n++, aat++) {
  540                 if (aat->aat_flags == 0)
  541                         goto out;
  542                 if (aat->aat_flags & ATF_PERM)
  543                         continue;
  544                 if ((int) aat->aat_timer > oldest) {
  545                         oldest = aat->aat_timer;
  546                         aato = aat;
  547                 }
  548         }
  549         if (aato == NULL)
  550                 return (NULL);
  551         aat = aato;
  552         aarptfree(aat);
  553 out:
  554         aat->aat_ataddr = *addr;
  555         aat->aat_flags = ATF_INUSE;
  556         return (aat);
  557 }
  558 
  559 
  560 void
  561 aarpprobe(void *arg)
  562 {
  563         struct ifnet *ifp = arg;
  564         struct mbuf *m;
  565         struct ether_header *eh;
  566         struct ether_aarp *ea;
  567         struct at_ifaddr *aa;
  568         struct llc *llc;
  569         struct sockaddr sa;
  570 
  571         /*
  572          * We need to check whether the output ethernet type should be phase
  573          * 1 or 2.  We have the interface that we'll be sending the aarp out.
  574          * We need to find an AppleTalk network on that interface with the
  575          * same address as we're looking for.  If the net is phase 2,
  576          * generate an 802.2 and SNAP header.
  577          */
  578         AARPTAB_LOCK();
  579         for (aa = (struct at_ifaddr *)TAILQ_FIRST(&ifp->if_addrhead); aa;
  580             aa = (struct at_ifaddr *)aa->aa_ifa.ifa_link.tqe_next) {
  581                 if (AA_SAT(aa)->sat_family == AF_APPLETALK &&
  582                     (aa->aa_flags & AFA_PROBING))
  583                         break;
  584         }
  585         if (aa == NULL) {
  586                 /* Serious error XXX. */
  587                 AARPTAB_UNLOCK();
  588                 printf("aarpprobe why did this happen?!\n");
  589                 return;
  590         }
  591 
  592         if (aa->aa_probcnt <= 0) {
  593                 aa->aa_flags &= ~AFA_PROBING;
  594                 wakeup(aa);
  595                 AARPTAB_UNLOCK();
  596                 return;
  597         } else
  598                 callout_reset(&aa->aa_callout, hz / 5, aarpprobe, ifp);
  599         AARPTAB_UNLOCK();
  600 
  601         m = m_gethdr(M_DONTWAIT, MT_DATA);
  602         if (m == NULL)
  603                 return;
  604 #ifdef MAC
  605         mac_create_mbuf_linklayer(ifp, m);
  606 #endif
  607         m->m_len = sizeof(*ea);
  608         m->m_pkthdr.len = sizeof(*ea);
  609         MH_ALIGN(m, sizeof(*ea));
  610 
  611         ea = mtod(m, struct ether_aarp *);
  612         bzero((caddr_t)ea, sizeof(*ea));
  613 
  614         ea->aarp_hrd = htons(AARPHRD_ETHER);
  615         ea->aarp_pro = htons(ETHERTYPE_AT);
  616         ea->aarp_hln = sizeof(ea->aarp_sha);
  617         ea->aarp_pln = sizeof(ea->aarp_spu);
  618         ea->aarp_op = htons(AARPOP_PROBE);
  619         bcopy(IF_LLADDR(ifp), (caddr_t)ea->aarp_sha,
  620             sizeof(ea->aarp_sha));
  621 
  622         eh = (struct ether_header *)sa.sa_data;
  623 
  624         if (aa->aa_flags & AFA_PHASE2) {
  625                 bcopy(atmulticastaddr, eh->ether_dhost,
  626                     sizeof(eh->ether_dhost));
  627                 eh->ether_type = htons(sizeof(struct llc) +
  628                     sizeof(struct ether_aarp));
  629                 M_PREPEND(m, sizeof(struct llc), M_TRYWAIT);
  630                 if (m == NULL)
  631                         return;
  632                 llc = mtod(m, struct llc *);
  633                 llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
  634                 llc->llc_control = LLC_UI;
  635                 bcopy(aarp_org_code, llc->llc_org_code,
  636                     sizeof(aarp_org_code));
  637                 llc->llc_ether_type = htons(ETHERTYPE_AARP);
  638 
  639                 bcopy(&AA_SAT(aa)->sat_addr.s_net, ea->aarp_spnet,
  640                     sizeof(ea->aarp_spnet));
  641                 bcopy(&AA_SAT(aa)->sat_addr.s_net, ea->aarp_tpnet,
  642                     sizeof(ea->aarp_tpnet));
  643                 ea->aarp_spnode = ea->aarp_tpnode =
  644                     AA_SAT(aa)->sat_addr.s_node;
  645         } else {
  646                 bcopy(ifp->if_broadcastaddr, (caddr_t)eh->ether_dhost,
  647                     sizeof(eh->ether_dhost));
  648                 eh->ether_type = htons(ETHERTYPE_AARP);
  649                 ea->aarp_spa = ea->aarp_tpa = AA_SAT(aa)->sat_addr.s_node;
  650         }
  651 
  652 #ifdef NETATALKDEBUG
  653         printf("aarp: sending probe for %u.%u\n",
  654             ntohs(AA_SAT(aa)->sat_addr.s_net), AA_SAT(aa)->sat_addr.s_node);
  655 #endif /* NETATALKDEBUG */
  656 
  657         sa.sa_len = sizeof(struct sockaddr);
  658         sa.sa_family = AF_UNSPEC;
  659         (*ifp->if_output)(ifp, m, &sa, NULL); /* XXX */
  660         aa->aa_probcnt--;
  661 }
  662 
  663 void
  664 aarp_clean(void)
  665 {
  666         struct aarptab *aat;
  667         int i;
  668 
  669         untimeout(aarptimer, 0, aarptimer_ch);
  670         AARPTAB_LOCK();
  671         for (i = 0, aat = aarptab; i < AARPTAB_SIZE; i++, aat++) {
  672                 if (aat->aat_hold) {
  673                         m_freem(aat->aat_hold);
  674                         aat->aat_hold = NULL;
  675                 }
  676         }
  677         AARPTAB_UNLOCK();
  678 }

Cache object: 79ae1a7861dcc97802319a63b23da891


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