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/netipx/ipx_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 /*-
    2  * Copyright (c) 2004-2005 Robert N. M. Watson
    3  * Copyright (c) 1995, Mike Mitchell
    4  * Copyright (c) 1984, 1985, 1986, 1987, 1993
    5  *      The Regents of the University of California.  All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. All advertising materials mentioning features or use of this software
   16  *    must display the following acknowledgement:
   17  *      This product includes software developed by the University of
   18  *      California, Berkeley and its contributors.
   19  * 4. Neither the name of the University nor the names of its contributors
   20  *    may be used to endorse or promote products derived from this software
   21  *    without specific prior written permission.
   22  *
   23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   33  * SUCH DAMAGE.
   34  *
   35  *      @(#)ipx_usrreq.c
   36  */
   37 
   38 #include <sys/cdefs.h>
   39 __FBSDID("$FreeBSD: releng/6.1/sys/netipx/ipx_usrreq.c 139930 2005-01-09 05:15:59Z rwatson $");
   40 
   41 #include "opt_ipx.h"
   42 
   43 #include <sys/param.h>
   44 #include <sys/kernel.h>
   45 #include <sys/lock.h>
   46 #include <sys/mbuf.h>
   47 #include <sys/protosw.h>
   48 #include <sys/signalvar.h>
   49 #include <sys/socket.h>
   50 #include <sys/socketvar.h>
   51 #include <sys/sx.h>
   52 #include <sys/sysctl.h>
   53 #include <sys/systm.h>
   54 
   55 #include <net/if.h>
   56 #include <net/route.h>
   57 
   58 #include <netinet/in.h>
   59 
   60 #include <netipx/ipx.h>
   61 #include <netipx/ipx_if.h>
   62 #include <netipx/ipx_ip.h>
   63 #include <netipx/ipx_pcb.h>
   64 #include <netipx/ipx_var.h>
   65 
   66 /*
   67  * IPX protocol implementation.
   68  */
   69 
   70 static int ipxsendspace = IPXSNDQ;
   71 SYSCTL_INT(_net_ipx_ipx, OID_AUTO, ipxsendspace, CTLFLAG_RW,
   72             &ipxsendspace, 0, "");
   73 static int ipxrecvspace = IPXRCVQ;
   74 SYSCTL_INT(_net_ipx_ipx, OID_AUTO, ipxrecvspace, CTLFLAG_RW,
   75             &ipxrecvspace, 0, "");
   76 
   77 static  int ipx_usr_abort(struct socket *so);
   78 static  int ipx_attach(struct socket *so, int proto, struct thread *td);
   79 static  int ipx_bind(struct socket *so, struct sockaddr *nam, struct thread *td);
   80 static  int ipx_connect(struct socket *so, struct sockaddr *nam,
   81                         struct thread *td);
   82 static  int ipx_detach(struct socket *so);
   83 static  int ipx_disconnect(struct socket *so);
   84 static  int ipx_send(struct socket *so, int flags, struct mbuf *m,
   85                      struct sockaddr *addr, struct mbuf *control,
   86                      struct thread *td);
   87 static  int ipx_shutdown(struct socket *so);
   88 static  int ripx_attach(struct socket *so, int proto, struct thread *td);
   89 static  int ipx_output(struct ipxpcb *ipxp, struct mbuf *m0);
   90 
   91 struct  pr_usrreqs ipx_usrreqs = {
   92         .pru_abort =            ipx_usr_abort,
   93         .pru_attach =           ipx_attach,
   94         .pru_bind =             ipx_bind,
   95         .pru_connect =          ipx_connect,
   96         .pru_control =          ipx_control,
   97         .pru_detach =           ipx_detach,
   98         .pru_disconnect =       ipx_disconnect,
   99         .pru_peeraddr =         ipx_peeraddr,
  100         .pru_send =             ipx_send,
  101         .pru_shutdown =         ipx_shutdown,
  102         .pru_sockaddr =         ipx_sockaddr,
  103 };
  104 
  105 struct  pr_usrreqs ripx_usrreqs = {
  106         .pru_abort =            ipx_usr_abort,
  107         .pru_attach =           ripx_attach,
  108         .pru_bind =             ipx_bind,
  109         .pru_connect =          ipx_connect,
  110         .pru_control =          ipx_control,
  111         .pru_detach =           ipx_detach,
  112         .pru_disconnect =       ipx_disconnect,
  113         .pru_peeraddr =         ipx_peeraddr,
  114         .pru_send =             ipx_send,
  115         .pru_shutdown =         ipx_shutdown,
  116         .pru_sockaddr =         ipx_sockaddr,
  117 };
  118 
  119 /*
  120  *  This may also be called for raw listeners.
  121  */
  122 void
  123 ipx_input(m, ipxp)
  124         struct mbuf *m;
  125         register struct ipxpcb *ipxp;
  126 {
  127         register struct ipx *ipx = mtod(m, struct ipx *);
  128         struct ifnet *ifp = m->m_pkthdr.rcvif;
  129         struct sockaddr_ipx ipx_ipx;
  130 
  131         KASSERT(ipxp != NULL, ("ipx_input: NULL ipxpcb"));
  132         IPX_LOCK_ASSERT(ipxp);
  133         /*
  134          * Construct sockaddr format source address.
  135          * Stuff source address and datagram in user buffer.
  136          */
  137         ipx_ipx.sipx_len = sizeof(ipx_ipx);
  138         ipx_ipx.sipx_family = AF_IPX;
  139         ipx_ipx.sipx_addr = ipx->ipx_sna;
  140         ipx_ipx.sipx_zero[0] = '\0';
  141         ipx_ipx.sipx_zero[1] = '\0';
  142         if (ipx_neteqnn(ipx->ipx_sna.x_net, ipx_zeronet) && ifp != NULL) {
  143                 register struct ifaddr *ifa;
  144 
  145                 for (ifa = TAILQ_FIRST(&ifp->if_addrhead); ifa != NULL;
  146                      ifa = TAILQ_NEXT(ifa, ifa_link)) {
  147                         if (ifa->ifa_addr->sa_family == AF_IPX) {
  148                                 ipx_ipx.sipx_addr.x_net =
  149                                         IA_SIPX(ifa)->sipx_addr.x_net;
  150                                 break;
  151                         }
  152                 }
  153         }
  154         ipxp->ipxp_rpt = ipx->ipx_pt;
  155         if ((ipxp->ipxp_flags & IPXP_RAWIN) == 0) {
  156                 m->m_len -= sizeof(struct ipx);
  157                 m->m_pkthdr.len -= sizeof(struct ipx);
  158                 m->m_data += sizeof(struct ipx);
  159         }
  160         if (sbappendaddr(&ipxp->ipxp_socket->so_rcv,
  161             (struct sockaddr *)&ipx_ipx, m, NULL) == 0)
  162                 m_freem(m);
  163         else
  164                 sorwakeup(ipxp->ipxp_socket);
  165 }
  166 
  167 /*
  168  * Drop connection, reporting
  169  * the specified error.
  170  */
  171 void
  172 ipx_drop(ipxp, errno)
  173         register struct ipxpcb *ipxp;
  174         int errno;
  175 {
  176         struct socket *so = ipxp->ipxp_socket;
  177 
  178         IPX_LIST_LOCK_ASSERT();
  179         IPX_LOCK_ASSERT(ipxp);
  180 
  181         /*
  182          * someday, in the IPX world
  183          * we will generate error protocol packets
  184          * announcing that the socket has gone away.
  185          *
  186          * XXX Probably never. IPX does not have error packets.
  187          */
  188         /*if (TCPS_HAVERCVDSYN(tp->t_state)) {
  189                 tp->t_state = TCPS_CLOSED;
  190                 tcp_output(tp);
  191         }*/
  192         so->so_error = errno;
  193         ipx_pcbdisconnect(ipxp);
  194         soisdisconnected(so);
  195 }
  196 
  197 static int
  198 ipx_output(ipxp, m0)
  199         struct ipxpcb *ipxp;
  200         struct mbuf *m0;
  201 {
  202         register struct ipx *ipx;
  203         register struct socket *so;
  204         register int len = 0;
  205         register struct route *ro;
  206         struct mbuf *m;
  207         struct mbuf *mprev = NULL;
  208 
  209         IPX_LOCK_ASSERT(ipxp);
  210 
  211         /*
  212          * Calculate data length.
  213          */
  214         for (m = m0; m != NULL; m = m->m_next) {
  215                 mprev = m;
  216                 len += m->m_len;
  217         }
  218         /*
  219          * Make sure packet is actually of even length.
  220          */
  221 
  222         if (len & 1) {
  223                 m = mprev;
  224                 if ((m->m_flags & M_EXT) == 0 &&
  225                         (m->m_len + m->m_data < &m->m_dat[MLEN])) {
  226                         mtod(m, char*)[m->m_len++] = 0;
  227                 } else {
  228                         struct mbuf *m1 = m_get(M_DONTWAIT, MT_DATA);
  229 
  230                         if (m1 == NULL) {
  231                                 m_freem(m0);
  232                                 return (ENOBUFS);
  233                         }
  234                         m1->m_len = 1;
  235                         * mtod(m1, char *) = 0;
  236                         m->m_next = m1;
  237                 }
  238                 m0->m_pkthdr.len++;
  239         }
  240 
  241         /*
  242          * Fill in mbuf with extended IPX header
  243          * and addresses and length put into network format.
  244          */
  245         m = m0;
  246         if (ipxp->ipxp_flags & IPXP_RAWOUT) {
  247                 ipx = mtod(m, struct ipx *);
  248         } else {
  249                 M_PREPEND(m, sizeof(struct ipx), M_DONTWAIT);
  250                 if (m == NULL)
  251                         return (ENOBUFS);
  252                 ipx = mtod(m, struct ipx *);
  253                 ipx->ipx_tc = 0;
  254                 ipx->ipx_pt = ipxp->ipxp_dpt;
  255                 ipx->ipx_sna = ipxp->ipxp_laddr;
  256                 ipx->ipx_dna = ipxp->ipxp_faddr;
  257                 len += sizeof(struct ipx);
  258         }
  259 
  260         ipx->ipx_len = htons((u_short)len);
  261 
  262         if (ipxp->ipxp_flags & IPXP_CHECKSUM) {
  263                 ipx->ipx_sum = ipx_cksum(m, len);
  264         } else
  265                 ipx->ipx_sum = 0xffff;
  266 
  267         /*
  268          * Output datagram.
  269          */
  270         so = ipxp->ipxp_socket;
  271         if (so->so_options & SO_DONTROUTE)
  272                 return (ipx_outputfl(m, (struct route *)NULL,
  273                     (so->so_options & SO_BROADCAST) | IPX_ROUTETOIF));
  274         /*
  275          * Use cached route for previous datagram if
  276          * possible.  If the previous net was the same
  277          * and the interface was a broadcast medium, or
  278          * if the previous destination was identical,
  279          * then we are ok.
  280          *
  281          * NB: We don't handle broadcasts because that
  282          *     would require 3 subroutine calls.
  283          */
  284         ro = &ipxp->ipxp_route;
  285 #ifdef ancient_history
  286         /*
  287          * I think that this will all be handled in ipx_pcbconnect!
  288          */
  289         if (ro->ro_rt != NULL) {
  290                 if(ipx_neteq(ipxp->ipxp_lastdst, ipx->ipx_dna)) {
  291                         /*
  292                          * This assumes we have no GH type routes
  293                          */
  294                         if (ro->ro_rt->rt_flags & RTF_HOST) {
  295                                 if (!ipx_hosteq(ipxp->ipxp_lastdst, ipx->ipx_dna))
  296                                         goto re_route;
  297 
  298                         }
  299                         if ((ro->ro_rt->rt_flags & RTF_GATEWAY) == 0) {
  300                                 register struct ipx_addr *dst =
  301                                                 &satoipx_addr(ro->ro_dst);
  302                                 dst->x_host = ipx->ipx_dna.x_host;
  303                         }
  304                         /*
  305                          * Otherwise, we go through the same gateway
  306                          * and dst is already set up.
  307                          */
  308                 } else {
  309                 re_route:
  310                         RTFREE(ro->ro_rt);
  311                         ro->ro_rt = NULL;
  312                 }
  313         }
  314         ipxp->ipxp_lastdst = ipx->ipx_dna;
  315 #endif /* ancient_history */
  316         return (ipx_outputfl(m, ro, so->so_options & SO_BROADCAST));
  317 }
  318 
  319 int
  320 ipx_ctloutput(so, sopt)
  321         struct socket *so;
  322         struct sockopt *sopt;
  323 {
  324         struct ipxpcb *ipxp = sotoipxpcb(so);
  325         int mask, error, optval;
  326         short soptval;
  327         struct ipx ioptval;
  328         long seq;
  329 
  330         error = 0;
  331         if (ipxp == NULL)
  332                 return (EINVAL);
  333 
  334         switch (sopt->sopt_dir) {
  335         case SOPT_GET:
  336                 switch (sopt->sopt_name) {
  337                 case SO_ALL_PACKETS:
  338                         mask = IPXP_ALL_PACKETS;
  339                         goto get_flags;
  340 
  341                 case SO_HEADERS_ON_INPUT:
  342                         mask = IPXP_RAWIN;
  343                         goto get_flags;
  344 
  345                 case SO_IPX_CHECKSUM:
  346                         mask = IPXP_CHECKSUM;
  347                         goto get_flags;
  348 
  349                 case SO_HEADERS_ON_OUTPUT:
  350                         mask = IPXP_RAWOUT;
  351                 get_flags:
  352                         /* Unlocked read. */
  353                         soptval = ipxp->ipxp_flags & mask;
  354                         error = sooptcopyout(sopt, &soptval, sizeof soptval);
  355                         break;
  356 
  357                 case SO_DEFAULT_HEADERS:
  358                         ioptval.ipx_len = 0;
  359                         ioptval.ipx_sum = 0;
  360                         ioptval.ipx_tc = 0;
  361                         IPX_LOCK(ipxp);
  362                         ioptval.ipx_pt = ipxp->ipxp_dpt;
  363                         ioptval.ipx_dna = ipxp->ipxp_faddr;
  364                         ioptval.ipx_sna = ipxp->ipxp_laddr;
  365                         IPX_UNLOCK(ipxp);
  366                         error = sooptcopyout(sopt, &soptval, sizeof soptval);
  367                         break;
  368 
  369                 case SO_SEQNO:
  370                         IPX_LIST_LOCK();
  371                         seq = ipx_pexseq;
  372                         ipx_pexseq++;
  373                         IPX_LIST_UNLOCK();
  374                         error = sooptcopyout(sopt, &seq, sizeof seq);
  375                         break;
  376 
  377                 default:
  378                         error = EINVAL;
  379                 }
  380                 break;
  381 
  382         case SOPT_SET:
  383                 switch (sopt->sopt_name) {
  384                 case SO_ALL_PACKETS:
  385                         mask = IPXP_ALL_PACKETS;
  386                         goto set_head;
  387 
  388                 case SO_HEADERS_ON_INPUT:
  389                         mask = IPXP_RAWIN;
  390                         goto set_head;
  391 
  392                 case SO_IPX_CHECKSUM:
  393                         mask = IPXP_CHECKSUM;
  394 
  395                 case SO_HEADERS_ON_OUTPUT:
  396                         mask = IPXP_RAWOUT;
  397                 set_head:
  398                         error = sooptcopyin(sopt, &optval, sizeof optval,
  399                                             sizeof optval);
  400                         if (error)
  401                                 break;
  402                         IPX_LOCK(ipxp);
  403                         if (optval)
  404                                 ipxp->ipxp_flags |= mask;
  405                         else
  406                                 ipxp->ipxp_flags &= ~mask;
  407                         IPX_UNLOCK(ipxp);
  408                         break;
  409 
  410                 case SO_DEFAULT_HEADERS:
  411                         error = sooptcopyin(sopt, &ioptval, sizeof ioptval,
  412                                             sizeof ioptval);
  413                         if (error)
  414                                 break;
  415                         /* Unlocked write. */
  416                         ipxp->ipxp_dpt = ioptval.ipx_pt;
  417                         break;
  418 #ifdef IPXIP
  419                 case SO_IPXIP_ROUTE:
  420                         error = ipxip_route(so, sopt);
  421                         break;
  422 #endif /* IPXIP */
  423                 default:
  424                         error = EINVAL;
  425                 }
  426                 break;
  427         }
  428         return (error);
  429 }
  430 
  431 static int
  432 ipx_usr_abort(so)
  433         struct socket *so;
  434 {
  435         struct ipxpcb *ipxp = sotoipxpcb(so);
  436 
  437         IPX_LIST_LOCK();
  438         IPX_LOCK(ipxp);
  439         ipx_pcbdetach(ipxp);
  440         IPX_LIST_UNLOCK();
  441         soisdisconnected(so);
  442         ACCEPT_LOCK();
  443         SOCK_LOCK(so);
  444         sotryfree(so);
  445         return (0);
  446 }
  447 
  448 static int
  449 ipx_attach(so, proto, td)
  450         struct socket *so;
  451         int proto;
  452         struct thread *td;
  453 {
  454         struct ipxpcb *ipxp = sotoipxpcb(so);
  455         int error;
  456 
  457         if (ipxp != NULL)
  458                 return (EINVAL);
  459         IPX_LIST_LOCK();
  460         error = ipx_pcballoc(so, &ipxpcb_list, td);
  461         IPX_LIST_UNLOCK();
  462         if (error == 0)
  463                 error = soreserve(so, ipxsendspace, ipxrecvspace);
  464         return (error);
  465 }
  466 
  467 static int
  468 ipx_bind(so, nam, td)
  469         struct socket *so;
  470         struct sockaddr *nam;
  471         struct thread *td;
  472 {
  473         struct ipxpcb *ipxp = sotoipxpcb(so);
  474         int error;
  475 
  476         IPX_LIST_LOCK();
  477         IPX_LOCK(ipxp);
  478         error = ipx_pcbbind(ipxp, nam, td);
  479         IPX_UNLOCK(ipxp);
  480         IPX_LIST_UNLOCK();
  481         return (error);
  482 }
  483 
  484 static int
  485 ipx_connect(so, nam, td)
  486         struct socket *so;
  487         struct sockaddr *nam;
  488         struct thread *td;
  489 {
  490         struct ipxpcb *ipxp = sotoipxpcb(so);
  491         int error;
  492 
  493         IPX_LIST_LOCK();
  494         IPX_LOCK(ipxp);
  495         if (!ipx_nullhost(ipxp->ipxp_faddr)) {
  496                 error = EISCONN;
  497                 goto out;
  498         }
  499         error = ipx_pcbconnect(ipxp, nam, td);
  500         if (error == 0)
  501                 soisconnected(so);
  502 out:
  503         IPX_UNLOCK(ipxp);
  504         IPX_LIST_UNLOCK();
  505         return (error);
  506 }
  507 
  508 static int
  509 ipx_detach(so)
  510         struct socket *so;
  511 {
  512         struct ipxpcb *ipxp = sotoipxpcb(so);
  513 
  514         if (ipxp == NULL)
  515                 return (ENOTCONN);
  516         IPX_LIST_LOCK();
  517         IPX_LOCK(ipxp);
  518         ipx_pcbdetach(ipxp);
  519         IPX_LIST_UNLOCK();
  520         return (0);
  521 }
  522 
  523 static int
  524 ipx_disconnect(so)
  525         struct socket *so;
  526 {
  527         struct ipxpcb *ipxp = sotoipxpcb(so);
  528         int error;
  529 
  530         IPX_LIST_LOCK();
  531         IPX_LOCK(ipxp);
  532         error = 0;
  533         if (ipx_nullhost(ipxp->ipxp_faddr)) {
  534                 error = ENOTCONN;
  535                 goto out;
  536         }
  537         ipx_pcbdisconnect(ipxp);
  538         soisdisconnected(so);
  539 out:
  540         IPX_UNLOCK(ipxp);
  541         IPX_LIST_UNLOCK();
  542         return (0);
  543 }
  544 
  545 int
  546 ipx_peeraddr(so, nam)
  547         struct socket *so;
  548         struct sockaddr **nam;
  549 {
  550         struct ipxpcb *ipxp = sotoipxpcb(so);
  551 
  552         ipx_setpeeraddr(ipxp, nam);
  553         return (0);
  554 }
  555 
  556 static int
  557 ipx_send(so, flags, m, nam, control, td)
  558         struct socket *so;
  559         int flags;
  560         struct mbuf *m;
  561         struct sockaddr *nam;
  562         struct mbuf *control;
  563         struct thread *td;
  564 {
  565         int error;
  566         struct ipxpcb *ipxp = sotoipxpcb(so);
  567         struct ipx_addr laddr;
  568 
  569         /*
  570          * Attempt to only acquire the necessary locks: if the socket is
  571          * already connected, we don't need to hold the IPX list lock to be
  572          * used by ipx_pcbconnect() and ipx_pcbdisconnect(), just the IPX
  573          * pcb lock.
  574          */
  575         if (nam != NULL) {
  576                 IPX_LIST_LOCK();
  577                 IPX_LOCK(ipxp);
  578                 laddr = ipxp->ipxp_laddr;
  579                 if (!ipx_nullhost(ipxp->ipxp_faddr)) {
  580                         IPX_UNLOCK(ipxp);
  581                         IPX_LIST_UNLOCK();
  582                         error = EISCONN;
  583                         goto send_release;
  584                 }
  585                 /*
  586                  * Must block input while temporarily connected.
  587                  */
  588                 error = ipx_pcbconnect(ipxp, nam, td);
  589                 if (error) {
  590                         IPX_UNLOCK(ipxp);
  591                         IPX_LIST_UNLOCK();
  592                         goto send_release;
  593                 }
  594         } else {
  595                 IPX_LOCK(ipxp);
  596                 if (ipx_nullhost(ipxp->ipxp_faddr)) {
  597                         IPX_UNLOCK(ipxp);
  598                         error = ENOTCONN;
  599                         goto send_release;
  600                 }
  601         }
  602         error = ipx_output(ipxp, m);
  603         m = NULL;
  604         if (nam != NULL) {
  605                 ipx_pcbdisconnect(ipxp);
  606                 ipxp->ipxp_laddr = laddr;
  607                 IPX_UNLOCK(ipxp);
  608                 IPX_LIST_UNLOCK();
  609         } else
  610                 IPX_UNLOCK(ipxp);
  611 
  612 send_release:
  613         if (m != NULL)
  614                 m_freem(m);
  615         return (error);
  616 }
  617 
  618 static int
  619 ipx_shutdown(so)
  620         struct socket *so;
  621 {
  622         socantsendmore(so);
  623         return (0);
  624 }
  625 
  626 int
  627 ipx_sockaddr(so, nam)
  628         struct socket *so;
  629         struct sockaddr **nam;
  630 {
  631         struct ipxpcb *ipxp = sotoipxpcb(so);
  632 
  633         ipx_setsockaddr(ipxp, nam);
  634         return (0);
  635 }
  636 
  637 static int
  638 ripx_attach(so, proto, td)
  639         struct socket *so;
  640         int proto;
  641         struct thread *td;
  642 {
  643         int error = 0;
  644         struct ipxpcb *ipxp = sotoipxpcb(so);
  645 
  646         if (td != NULL && (error = suser(td)) != 0)
  647                 return (error);
  648         /*
  649          * We hold the IPX list lock for the duration as address parameters
  650          * of the IPX pcb are changed.  Since no one else holds a reference
  651          * to the ipxpcb yet, we don't need the ipxpcb lock here.
  652          */
  653         IPX_LIST_LOCK();
  654         error = ipx_pcballoc(so, &ipxrawpcb_list, td);
  655         if (error)
  656                 goto out;
  657         ipxp = sotoipxpcb(so);
  658         error = soreserve(so, ipxsendspace, ipxrecvspace);
  659         if (error)
  660                 goto out;
  661         ipxp->ipxp_faddr.x_host = ipx_broadhost;
  662         ipxp->ipxp_flags = IPXP_RAWIN | IPXP_RAWOUT;
  663 out:
  664         IPX_LIST_UNLOCK();
  665         return (error);
  666 }

Cache object: 152846a6b7e34de4fdc6e95ee01fbd6c


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