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/ddp_usrreq.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: ddp_usrreq.c,v 1.33 2008/05/04 07:22:14 thorpej 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: ddp_usrreq.c,v 1.33 2008/05/04 07:22:14 thorpej Exp $");
   31 
   32 #include "opt_mbuftrace.h"
   33 
   34 #include <sys/param.h>
   35 #include <sys/errno.h>
   36 #include <sys/systm.h>
   37 #include <sys/proc.h>
   38 #include <sys/mbuf.h>
   39 #include <sys/ioctl.h>
   40 #include <sys/queue.h>
   41 #include <sys/socket.h>
   42 #include <sys/socketvar.h>
   43 #include <sys/protosw.h>
   44 #include <sys/kauth.h>
   45 #include <sys/sysctl.h>
   46 #include <net/if.h>
   47 #include <net/route.h>
   48 #include <net/if_ether.h>
   49 #include <net/net_stats.h>
   50 #include <netinet/in.h>
   51 
   52 #include <netatalk/at.h>
   53 #include <netatalk/at_var.h>
   54 #include <netatalk/ddp_var.h>
   55 #include <netatalk/ddp_private.h>
   56 #include <netatalk/aarp.h>
   57 #include <netatalk/at_extern.h>
   58 
   59 static void at_pcbdisconnect __P((struct ddpcb *));
   60 static void at_sockaddr __P((struct ddpcb *, struct mbuf *));
   61 static int at_pcbsetaddr __P((struct ddpcb *, struct mbuf *, struct lwp *));
   62 static int at_pcbconnect __P((struct ddpcb *, struct mbuf *, struct lwp *));
   63 static void at_pcbdetach __P((struct socket *, struct ddpcb *));
   64 static int at_pcballoc __P((struct socket *));
   65 
   66 struct ifqueue atintrq1, atintrq2;
   67 struct ddpcb   *ddp_ports[ATPORT_LAST];
   68 struct ddpcb   *ddpcb = NULL;
   69 percpu_t *ddpstat_percpu;
   70 struct at_ifaddrhead at_ifaddr;         /* Here as inited in this file */
   71 u_long ddp_sendspace = DDP_MAXSZ;       /* Max ddp size + 1 (ddp_type) */
   72 u_long ddp_recvspace = 25 * (587 + sizeof(struct sockaddr_at));
   73 
   74 #ifdef MBUFTRACE
   75 struct mowner atalk_rx_mowner = MOWNER_INIT("atalk", "rx");
   76 struct mowner atalk_tx_mowner = MOWNER_INIT("atalk", "tx");
   77 #endif
   78 
   79 /* ARGSUSED */
   80 int
   81 ddp_usrreq(so, req, m, addr, rights, l)
   82         struct socket  *so;
   83         int             req;
   84         struct mbuf    *m;
   85         struct mbuf    *addr;
   86         struct mbuf    *rights;
   87         struct lwp *l;
   88 {
   89         struct ddpcb   *ddp;
   90         int             error = 0;
   91 
   92         ddp = sotoddpcb(so);
   93 
   94         if (req == PRU_CONTROL) {
   95                 return (at_control((long) m, (void *) addr,
   96                     (struct ifnet *) rights, l));
   97         }
   98         if (req == PRU_PURGEIF) {
   99                 mutex_enter(softnet_lock);
  100                 at_purgeif((struct ifnet *) rights);
  101                 mutex_exit(softnet_lock);
  102                 return (0);
  103         }
  104         if (rights && rights->m_len) {
  105                 error = EINVAL;
  106                 goto release;
  107         }
  108         if (ddp == NULL && req != PRU_ATTACH) {
  109                 error = EINVAL;
  110                 goto release;
  111         }
  112         switch (req) {
  113         case PRU_ATTACH:
  114                 if (ddp != NULL) {
  115                         error = EINVAL;
  116                         break;
  117                 }
  118                 sosetlock(so);
  119                 if ((error = at_pcballoc(so)) != 0) {
  120                         break;
  121                 }
  122                 error = soreserve(so, ddp_sendspace, ddp_recvspace);
  123                 break;
  124 
  125         case PRU_DETACH:
  126                 at_pcbdetach(so, ddp);
  127                 break;
  128 
  129         case PRU_BIND:
  130                 error = at_pcbsetaddr(ddp, addr, l);
  131                 break;
  132 
  133         case PRU_SOCKADDR:
  134                 at_sockaddr(ddp, addr);
  135                 break;
  136 
  137         case PRU_CONNECT:
  138                 if (ddp->ddp_fsat.sat_port != ATADDR_ANYPORT) {
  139                         error = EISCONN;
  140                         break;
  141                 }
  142                 error = at_pcbconnect(ddp, addr, l);
  143                 if (error == 0)
  144                         soisconnected(so);
  145                 break;
  146 
  147         case PRU_DISCONNECT:
  148                 if (ddp->ddp_fsat.sat_addr.s_node == ATADDR_ANYNODE) {
  149                         error = ENOTCONN;
  150                         break;
  151                 }
  152                 at_pcbdisconnect(ddp);
  153                 soisdisconnected(so);
  154                 break;
  155 
  156         case PRU_SHUTDOWN:
  157                 socantsendmore(so);
  158                 break;
  159 
  160         case PRU_SEND:{
  161                         int s = 0;
  162 
  163                         if (addr) {
  164                                 if (ddp->ddp_fsat.sat_port != ATADDR_ANYPORT) {
  165                                         error = EISCONN;
  166                                         break;
  167                                 }
  168                                 s = splnet();
  169                                 error = at_pcbconnect(ddp, addr, l);
  170                                 if (error) {
  171                                         splx(s);
  172                                         break;
  173                                 }
  174                         } else {
  175                                 if (ddp->ddp_fsat.sat_port == ATADDR_ANYPORT) {
  176                                         error = ENOTCONN;
  177                                         break;
  178                                 }
  179                         }
  180 
  181                         error = ddp_output(m, ddp);
  182                         m = NULL;
  183                         if (addr) {
  184                                 at_pcbdisconnect(ddp);
  185                                 splx(s);
  186                         }
  187                 }
  188                 break;
  189 
  190         case PRU_ABORT:
  191                 soisdisconnected(so);
  192                 at_pcbdetach(so, ddp);
  193                 break;
  194 
  195         case PRU_LISTEN:
  196         case PRU_CONNECT2:
  197         case PRU_ACCEPT:
  198         case PRU_SENDOOB:
  199         case PRU_FASTTIMO:
  200         case PRU_SLOWTIMO:
  201         case PRU_PROTORCV:
  202         case PRU_PROTOSEND:
  203                 error = EOPNOTSUPP;
  204                 break;
  205 
  206         case PRU_RCVD:
  207         case PRU_RCVOOB:
  208                 /*
  209                  * Don't mfree. Good architecture...
  210                  */
  211                 return (EOPNOTSUPP);
  212 
  213         case PRU_SENSE:
  214                 /*
  215                  * 1. Don't return block size.
  216                  * 2. Don't mfree.
  217                  */
  218                 return (0);
  219 
  220         default:
  221                 error = EOPNOTSUPP;
  222         }
  223 
  224 release:
  225         if (m != NULL) {
  226                 m_freem(m);
  227         }
  228         return (error);
  229 }
  230 
  231 static void
  232 at_sockaddr(ddp, addr)
  233         struct ddpcb   *ddp;
  234         struct mbuf    *addr;
  235 {
  236         struct sockaddr_at *sat;
  237 
  238         addr->m_len = sizeof(struct sockaddr_at);
  239         sat = mtod(addr, struct sockaddr_at *);
  240         *sat = ddp->ddp_lsat;
  241 }
  242 
  243 static int
  244 at_pcbsetaddr(ddp, addr, l)
  245         struct ddpcb   *ddp;
  246         struct mbuf    *addr;
  247         struct lwp      *l;
  248 {
  249         struct sockaddr_at lsat, *sat;
  250         struct at_ifaddr *aa;
  251         struct ddpcb   *ddpp;
  252 
  253         if (ddp->ddp_lsat.sat_port != ATADDR_ANYPORT) { /* shouldn't be bound */
  254                 return (EINVAL);
  255         }
  256         if (addr != 0) {        /* validate passed address */
  257                 sat = mtod(addr, struct sockaddr_at *);
  258                 if (addr->m_len != sizeof(*sat))
  259                         return (EINVAL);
  260 
  261                 if (sat->sat_family != AF_APPLETALK)
  262                         return (EAFNOSUPPORT);
  263 
  264                 if (sat->sat_addr.s_node != ATADDR_ANYNODE ||
  265                     sat->sat_addr.s_net != ATADDR_ANYNET) {
  266                         TAILQ_FOREACH(aa, &at_ifaddr, aa_list) {
  267                                 if ((sat->sat_addr.s_net ==
  268                                     AA_SAT(aa)->sat_addr.s_net) &&
  269                                     (sat->sat_addr.s_node ==
  270                                     AA_SAT(aa)->sat_addr.s_node))
  271                                         break;
  272                         }
  273                         if (!aa)
  274                                 return (EADDRNOTAVAIL);
  275                 }
  276                 if (sat->sat_port != ATADDR_ANYPORT) {
  277                         if (sat->sat_port < ATPORT_FIRST ||
  278                             sat->sat_port >= ATPORT_LAST)
  279                                 return (EINVAL);
  280 
  281                         if (sat->sat_port < ATPORT_RESERVED && l &&
  282                             kauth_authorize_generic(l->l_cred,
  283                             KAUTH_GENERIC_ISSUSER, NULL))
  284                                 return (EACCES);
  285                 }
  286         } else {
  287                 bzero((void *) & lsat, sizeof(struct sockaddr_at));
  288                 lsat.sat_len = sizeof(struct sockaddr_at);
  289                 lsat.sat_addr.s_node = ATADDR_ANYNODE;
  290                 lsat.sat_addr.s_net = ATADDR_ANYNET;
  291                 lsat.sat_family = AF_APPLETALK;
  292                 sat = &lsat;
  293         }
  294 
  295         if (sat->sat_addr.s_node == ATADDR_ANYNODE &&
  296             sat->sat_addr.s_net == ATADDR_ANYNET) {
  297                 if (TAILQ_EMPTY(&at_ifaddr))
  298                         return EADDRNOTAVAIL;
  299                 sat->sat_addr = AA_SAT(TAILQ_FIRST(&at_ifaddr))->sat_addr;
  300         }
  301         ddp->ddp_lsat = *sat;
  302 
  303         /*
  304          * Choose port.
  305          */
  306         if (sat->sat_port == ATADDR_ANYPORT) {
  307                 for (sat->sat_port = ATPORT_RESERVED;
  308                      sat->sat_port < ATPORT_LAST; sat->sat_port++) {
  309                         if (ddp_ports[sat->sat_port - 1] == 0)
  310                                 break;
  311                 }
  312                 if (sat->sat_port == ATPORT_LAST) {
  313                         return (EADDRNOTAVAIL);
  314                 }
  315                 ddp->ddp_lsat.sat_port = sat->sat_port;
  316                 ddp_ports[sat->sat_port - 1] = ddp;
  317         } else {
  318                 for (ddpp = ddp_ports[sat->sat_port - 1]; ddpp;
  319                      ddpp = ddpp->ddp_pnext) {
  320                         if (ddpp->ddp_lsat.sat_addr.s_net ==
  321                             sat->sat_addr.s_net &&
  322                             ddpp->ddp_lsat.sat_addr.s_node ==
  323                             sat->sat_addr.s_node)
  324                                 break;
  325                 }
  326                 if (ddpp != NULL)
  327                         return (EADDRINUSE);
  328 
  329                 ddp->ddp_pnext = ddp_ports[sat->sat_port - 1];
  330                 ddp_ports[sat->sat_port - 1] = ddp;
  331                 if (ddp->ddp_pnext)
  332                         ddp->ddp_pnext->ddp_pprev = ddp;
  333         }
  334 
  335         return 0;
  336 }
  337 
  338 static int
  339 at_pcbconnect(ddp, addr, l)
  340         struct ddpcb   *ddp;
  341         struct mbuf    *addr;
  342         struct lwp     *l;
  343 {
  344         struct rtentry *rt;
  345         const struct sockaddr_at *cdst;
  346         struct sockaddr_at *sat = mtod(addr, struct sockaddr_at *);
  347         struct route *ro;
  348         struct at_ifaddr *aa;
  349         struct ifnet   *ifp;
  350         u_short         hintnet = 0, net;
  351 
  352         if (addr->m_len != sizeof(*sat))
  353                 return EINVAL;
  354         if (sat->sat_family != AF_APPLETALK) {
  355                 return EAFNOSUPPORT;
  356         }
  357         /*
  358          * Under phase 2, network 0 means "the network".  We take "the
  359          * network" to mean the network the control block is bound to.
  360          * If the control block is not bound, there is an error.
  361          */
  362         if (sat->sat_addr.s_net == ATADDR_ANYNET
  363             && sat->sat_addr.s_node != ATADDR_ANYNODE) {
  364                 if (ddp->ddp_lsat.sat_port == ATADDR_ANYPORT) {
  365                         return EADDRNOTAVAIL;
  366                 }
  367                 hintnet = ddp->ddp_lsat.sat_addr.s_net;
  368         }
  369         ro = &ddp->ddp_route;
  370         /*
  371          * If we've got an old route for this pcb, check that it is valid.
  372          * If we've changed our address, we may have an old "good looking"
  373          * route here.  Attempt to detect it.
  374          */
  375         if ((rt = rtcache_validate(ro)) != NULL ||
  376             (rt = rtcache_update(ro, 1)) != NULL) {
  377                 if (hintnet) {
  378                         net = hintnet;
  379                 } else {
  380                         net = sat->sat_addr.s_net;
  381                 }
  382                 if ((ifp = rt->rt_ifp) != NULL) {
  383                         TAILQ_FOREACH(aa, &at_ifaddr, aa_list) {
  384                                 if (aa->aa_ifp == ifp &&
  385                                     ntohs(net) >= ntohs(aa->aa_firstnet) &&
  386                                     ntohs(net) <= ntohs(aa->aa_lastnet)) {
  387                                         break;
  388                                 }
  389                         }
  390                 } else
  391                         aa = NULL;
  392                 cdst = satocsat(rtcache_getdst(ro));
  393                 if (aa == NULL || (cdst->sat_addr.s_net !=
  394                     (hintnet ? hintnet : sat->sat_addr.s_net) ||
  395                     cdst->sat_addr.s_node != sat->sat_addr.s_node)) {
  396                         rtcache_free(ro);
  397                         rt = NULL;
  398                 }
  399         }
  400         /*
  401          * If we've got no route for this interface, try to find one.
  402          */
  403         if (rt == NULL) {
  404                 union {
  405                         struct sockaddr         dst;
  406                         struct sockaddr_at      dsta;
  407                 } u;
  408 
  409                 sockaddr_at_init(&u.dsta, &sat->sat_addr, 0);
  410                 if (hintnet)
  411                         u.dsta.sat_addr.s_net = hintnet;
  412                 rt = rtcache_lookup(ro, &u.dst);
  413         }
  414         /*
  415          * Make sure any route that we have has a valid interface.
  416          */
  417         if (rt != NULL && (ifp = rt->rt_ifp) != NULL) {
  418                 TAILQ_FOREACH(aa, &at_ifaddr, aa_list) {
  419                         if (aa->aa_ifp == ifp)
  420                                 break;
  421                 }
  422         } else
  423                 aa = NULL;
  424         if (aa == NULL)
  425                 return ENETUNREACH;
  426         ddp->ddp_fsat = *sat;
  427         if (ddp->ddp_lsat.sat_port == ATADDR_ANYPORT)
  428                 return at_pcbsetaddr(ddp, NULL, l);
  429         return 0;
  430 }
  431 
  432 static void
  433 at_pcbdisconnect(ddp)
  434         struct ddpcb   *ddp;
  435 {
  436         ddp->ddp_fsat.sat_addr.s_net = ATADDR_ANYNET;
  437         ddp->ddp_fsat.sat_addr.s_node = ATADDR_ANYNODE;
  438         ddp->ddp_fsat.sat_port = ATADDR_ANYPORT;
  439 }
  440 
  441 static int
  442 at_pcballoc(so)
  443         struct socket  *so;
  444 {
  445         struct ddpcb   *ddp;
  446 
  447         MALLOC(ddp, struct ddpcb *, sizeof(*ddp), M_PCB, M_WAITOK|M_ZERO);
  448         if (!ddp)
  449                 panic("at_pcballoc");
  450         ddp->ddp_lsat.sat_port = ATADDR_ANYPORT;
  451 
  452         ddp->ddp_next = ddpcb;
  453         ddp->ddp_prev = NULL;
  454         ddp->ddp_pprev = NULL;
  455         ddp->ddp_pnext = NULL;
  456         if (ddpcb) {
  457                 ddpcb->ddp_prev = ddp;
  458         }
  459         ddpcb = ddp;
  460 
  461         ddp->ddp_socket = so;
  462         so->so_pcb = (void *) ddp;
  463 #ifdef MBUFTRACE
  464         so->so_rcv.sb_mowner = &atalk_rx_mowner;
  465         so->so_snd.sb_mowner = &atalk_tx_mowner;
  466 #endif
  467         return 0;
  468 }
  469 
  470 static void
  471 at_pcbdetach(so, ddp)
  472         struct socket  *so;
  473         struct ddpcb   *ddp;
  474 {
  475         soisdisconnected(so);
  476         so->so_pcb = 0;
  477         /* sofree drops the lock */
  478         sofree(so);
  479         mutex_enter(softnet_lock);
  480 
  481         /* remove ddp from ddp_ports list */
  482         if (ddp->ddp_lsat.sat_port != ATADDR_ANYPORT &&
  483             ddp_ports[ddp->ddp_lsat.sat_port - 1] != NULL) {
  484                 if (ddp->ddp_pprev != NULL) {
  485                         ddp->ddp_pprev->ddp_pnext = ddp->ddp_pnext;
  486                 } else {
  487                         ddp_ports[ddp->ddp_lsat.sat_port - 1] = ddp->ddp_pnext;
  488                 }
  489                 if (ddp->ddp_pnext != NULL) {
  490                         ddp->ddp_pnext->ddp_pprev = ddp->ddp_pprev;
  491                 }
  492         }
  493         rtcache_free(&ddp->ddp_route);
  494         if (ddp->ddp_prev) {
  495                 ddp->ddp_prev->ddp_next = ddp->ddp_next;
  496         } else {
  497                 ddpcb = ddp->ddp_next;
  498         }
  499         if (ddp->ddp_next) {
  500                 ddp->ddp_next->ddp_prev = ddp->ddp_prev;
  501         }
  502         free(ddp, M_PCB);
  503 }
  504 
  505 /*
  506  * For the moment, this just find the pcb with the correct local address.
  507  * In the future, this will actually do some real searching, so we can use
  508  * the sender's address to do de-multiplexing on a single port to many
  509  * sockets (pcbs).
  510  */
  511 struct ddpcb   *
  512 ddp_search(
  513     struct sockaddr_at *from,
  514     struct sockaddr_at *to,
  515     struct at_ifaddr *aa)
  516 {
  517         struct ddpcb   *ddp;
  518 
  519         /*
  520          * Check for bad ports.
  521          */
  522         if (to->sat_port < ATPORT_FIRST || to->sat_port >= ATPORT_LAST)
  523                 return NULL;
  524 
  525         /*
  526          * Make sure the local address matches the sent address.  What about
  527          * the interface?
  528          */
  529         for (ddp = ddp_ports[to->sat_port - 1]; ddp; ddp = ddp->ddp_pnext) {
  530                 /* XXX should we handle 0.YY? */
  531 
  532                 /* XXXX.YY to socket on destination interface */
  533                 if (to->sat_addr.s_net == ddp->ddp_lsat.sat_addr.s_net &&
  534                     to->sat_addr.s_node == ddp->ddp_lsat.sat_addr.s_node) {
  535                         break;
  536                 }
  537                 /* 0.255 to socket on receiving interface */
  538                 if (to->sat_addr.s_node == ATADDR_BCAST &&
  539                     (to->sat_addr.s_net == 0 ||
  540                     to->sat_addr.s_net == ddp->ddp_lsat.sat_addr.s_net) &&
  541                 ddp->ddp_lsat.sat_addr.s_net == AA_SAT(aa)->sat_addr.s_net) {
  542                         break;
  543                 }
  544                 /* XXXX.0 to socket on destination interface */
  545                 if (to->sat_addr.s_net == aa->aa_firstnet &&
  546                     to->sat_addr.s_node == 0 &&
  547                     ntohs(ddp->ddp_lsat.sat_addr.s_net) >=
  548                     ntohs(aa->aa_firstnet) &&
  549                     ntohs(ddp->ddp_lsat.sat_addr.s_net) <=
  550                     ntohs(aa->aa_lastnet)) {
  551                         break;
  552                 }
  553         }
  554         return (ddp);
  555 }
  556 
  557 /*
  558  * Initialize all the ddp & appletalk stuff
  559  */
  560 void
  561 ddp_init(void)
  562 {
  563 
  564         ddpstat_percpu = percpu_alloc(sizeof(uint64_t) * DDP_NSTATS);
  565 
  566         TAILQ_INIT(&at_ifaddr);
  567         atintrq1.ifq_maxlen = IFQ_MAXLEN;
  568         atintrq2.ifq_maxlen = IFQ_MAXLEN;
  569 
  570         MOWNER_ATTACH(&atalk_tx_mowner);
  571         MOWNER_ATTACH(&atalk_rx_mowner);
  572 }
  573 
  574 #if 0
  575 static void
  576 ddp_clean()
  577 {
  578         struct ddpcb   *ddp;
  579 
  580         for (ddp = ddpcb; ddp; ddp = ddp->ddp_next)
  581                 at_pcbdetach(ddp->ddp_socket, ddp);
  582 }
  583 #endif
  584 
  585 static int
  586 sysctl_net_atalk_ddp_stats(SYSCTLFN_ARGS)
  587 {
  588 
  589         return (NETSTAT_SYSCTL(ddpstat_percpu, DDP_NSTATS));
  590 }
  591 
  592 /*
  593  * Sysctl for DDP variables.
  594  */
  595 SYSCTL_SETUP(sysctl_net_atalk_ddp_setup, "sysctl net.atalk.ddp subtree setup")
  596 {
  597 
  598         sysctl_createv(clog, 0, NULL, NULL,
  599                        CTLFLAG_PERMANENT,
  600                        CTLTYPE_NODE, "net", NULL,
  601                        NULL, 0, NULL, 0,
  602                        CTL_NET, CTL_EOL);
  603         sysctl_createv(clog, 0, NULL, NULL,
  604                        CTLFLAG_PERMANENT,
  605                        CTLTYPE_NODE, "atalk", NULL,
  606                        NULL, 0, NULL, 0,
  607                        CTL_NET, PF_APPLETALK, CTL_EOL);
  608         sysctl_createv(clog, 0, NULL, NULL,
  609                        CTLFLAG_PERMANENT,
  610                        CTLTYPE_NODE, "ddp",
  611                        SYSCTL_DESCR("DDP related settings"),
  612                        NULL, 0, NULL, 0,
  613                        CTL_NET, PF_APPLETALK, ATPROTO_DDP, CTL_EOL);
  614         
  615         sysctl_createv(clog, 0, NULL, NULL,
  616                        CTLFLAG_PERMANENT,
  617                        CTLTYPE_STRUCT, "stats",
  618                        SYSCTL_DESCR("DDP statistics"),
  619                        sysctl_net_atalk_ddp_stats, 0, NULL, 0,
  620                        CTL_NET, PF_APPLETALK, ATPROTO_DDP, CTL_CREATE,
  621                        CTL_EOL);
  622 }

Cache object: 07559dbf0319ac90f7b0d6cd75657b5d


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