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

Cache object: ad755682d7f3d840fb896bdcf02c529d


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