[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]

FreeBSD/Linux Kernel Cross Reference
sys/netipx/ipx_usrreq.c

Version: -  FREEBSD  -  FREEBSD7  -  FREEBSD70  -  FREEBSD6  -  FREEBSD63  -  FREEBSD62  -  FREEBSD61  -  FREEBSD60  -  FREEBSD5  -  FREEBSD55  -  FREEBSD54  -  FREEBSD53  -  FREEBSD52  -  FREEBSD51  -  FREEBSD50  -  FREEBSD4  -  FREEBSD3  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  OPENSOLARIS  -  minix-3-1-1  -  TRUSTEDBSD-SEBSD  -  FREEBSD-LIBC  -  FREEBSD7-LIBC  -  FREEBSD6-LIBC  -  GLIBC27 
SearchContext: -  none  -  excerpts  -  bigexcerpts 

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

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.