ipx_usrreq.c revision 169462
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: head/sys/netipx/ipx_usrreq.c 169462 2007-05-11 10:20:51Z rwatson $"); 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_ip.h> 91#include <netipx/ipx_pcb.h> 92#include <netipx/ipx_var.h> 93 94/* 95 * IPX protocol implementation. 96 */ 97 98static int ipxsendspace = IPXSNDQ; 99SYSCTL_INT(_net_ipx_ipx, OID_AUTO, ipxsendspace, CTLFLAG_RW, 100 &ipxsendspace, 0, ""); 101static int ipxrecvspace = IPXRCVQ; 102SYSCTL_INT(_net_ipx_ipx, OID_AUTO, ipxrecvspace, CTLFLAG_RW, 103 &ipxrecvspace, 0, ""); 104 105static void ipx_usr_abort(struct socket *so); 106static int ipx_attach(struct socket *so, int proto, struct thread *td); 107static int ipx_bind(struct socket *so, struct sockaddr *nam, struct thread *td); 108static int ipx_connect(struct socket *so, struct sockaddr *nam, 109 struct thread *td); 110static void ipx_detach(struct socket *so); 111static int ipx_disconnect(struct socket *so); 112static int ipx_send(struct socket *so, int flags, struct mbuf *m, 113 struct sockaddr *addr, struct mbuf *control, 114 struct thread *td); 115static int ipx_shutdown(struct socket *so); 116static int ripx_attach(struct socket *so, int proto, struct thread *td); 117static int ipx_output(struct ipxpcb *ipxp, struct mbuf *m0); 118static void ipx_usr_close(struct socket *so); 119 120struct pr_usrreqs ipx_usrreqs = { 121 .pru_abort = ipx_usr_abort, 122 .pru_attach = ipx_attach, 123 .pru_bind = ipx_bind, 124 .pru_connect = ipx_connect, 125 .pru_control = ipx_control, 126 .pru_detach = ipx_detach, 127 .pru_disconnect = ipx_disconnect, 128 .pru_peeraddr = ipx_peeraddr, 129 .pru_send = ipx_send, 130 .pru_shutdown = ipx_shutdown, 131 .pru_sockaddr = ipx_sockaddr, 132 .pru_close = ipx_usr_close, 133}; 134 135struct pr_usrreqs ripx_usrreqs = { 136 .pru_abort = ipx_usr_abort, 137 .pru_attach = ripx_attach, 138 .pru_bind = ipx_bind, 139 .pru_connect = ipx_connect, 140 .pru_control = ipx_control, 141 .pru_detach = ipx_detach, 142 .pru_disconnect = ipx_disconnect, 143 .pru_peeraddr = ipx_peeraddr, 144 .pru_send = ipx_send, 145 .pru_shutdown = ipx_shutdown, 146 .pru_sockaddr = ipx_sockaddr, 147 .pru_close = ipx_usr_close, 148}; 149 150/* 151 * This may also be called for raw listeners. 152 */ 153void 154ipx_input(m, ipxp) 155 struct mbuf *m; 156 register struct ipxpcb *ipxp; 157{ 158 register struct ipx *ipx = mtod(m, struct ipx *); 159 struct ifnet *ifp = m->m_pkthdr.rcvif; 160 struct sockaddr_ipx ipx_ipx; 161 162 KASSERT(ipxp != NULL, ("ipx_input: NULL ipxpcb")); 163 IPX_LOCK_ASSERT(ipxp); 164 /* 165 * Construct sockaddr format source address. 166 * Stuff source address and datagram in user buffer. 167 */ 168 ipx_ipx.sipx_len = sizeof(ipx_ipx); 169 ipx_ipx.sipx_family = AF_IPX; 170 ipx_ipx.sipx_addr = ipx->ipx_sna; 171 ipx_ipx.sipx_zero[0] = '\0'; 172 ipx_ipx.sipx_zero[1] = '\0'; 173 if (ipx_neteqnn(ipx->ipx_sna.x_net, ipx_zeronet) && ifp != NULL) { 174 register struct ifaddr *ifa; 175 176 for (ifa = TAILQ_FIRST(&ifp->if_addrhead); ifa != NULL; 177 ifa = TAILQ_NEXT(ifa, ifa_link)) { 178 if (ifa->ifa_addr->sa_family == AF_IPX) { 179 ipx_ipx.sipx_addr.x_net = 180 IA_SIPX(ifa)->sipx_addr.x_net; 181 break; 182 } 183 } 184 } 185 ipxp->ipxp_rpt = ipx->ipx_pt; 186 if ((ipxp->ipxp_flags & IPXP_RAWIN) == 0) { 187 m->m_len -= sizeof(struct ipx); 188 m->m_pkthdr.len -= sizeof(struct ipx); 189 m->m_data += sizeof(struct ipx); 190 } 191 if (sbappendaddr(&ipxp->ipxp_socket->so_rcv, 192 (struct sockaddr *)&ipx_ipx, m, NULL) == 0) 193 m_freem(m); 194 else 195 sorwakeup(ipxp->ipxp_socket); 196} 197 198/* 199 * Drop connection, reporting 200 * the specified error. 201 */ 202void 203ipx_drop(ipxp, errno) 204 register struct ipxpcb *ipxp; 205 int errno; 206{ 207 struct socket *so = ipxp->ipxp_socket; 208 209 IPX_LIST_LOCK_ASSERT(); 210 IPX_LOCK_ASSERT(ipxp); 211 212 /* 213 * someday, in the IPX world 214 * we will generate error protocol packets 215 * announcing that the socket has gone away. 216 * 217 * XXX Probably never. IPX does not have error packets. 218 */ 219 /*if (TCPS_HAVERCVDSYN(tp->t_state)) { 220 tp->t_state = TCPS_CLOSED; 221 tcp_output(tp); 222 }*/ 223 so->so_error = errno; 224 ipx_pcbdisconnect(ipxp); 225 soisdisconnected(so); 226} 227 228static int 229ipx_output(ipxp, m0) 230 struct ipxpcb *ipxp; 231 struct mbuf *m0; 232{ 233 register struct ipx *ipx; 234 register struct socket *so; 235 register int len = 0; 236 register struct route *ro; 237 struct mbuf *m; 238 struct mbuf *mprev = NULL; 239 240 IPX_LOCK_ASSERT(ipxp); 241 242 /* 243 * Calculate data length. 244 */ 245 for (m = m0; m != NULL; m = m->m_next) { 246 mprev = m; 247 len += m->m_len; 248 } 249 /* 250 * Make sure packet is actually of even length. 251 */ 252 253 if (len & 1) { 254 m = mprev; 255 if ((m->m_flags & M_EXT) == 0 && 256 (m->m_len + m->m_data < &m->m_dat[MLEN])) { 257 mtod(m, char*)[m->m_len++] = 0; 258 } else { 259 struct mbuf *m1 = m_get(M_DONTWAIT, MT_DATA); 260 261 if (m1 == NULL) { 262 m_freem(m0); 263 return (ENOBUFS); 264 } 265 m1->m_len = 1; 266 * mtod(m1, char *) = 0; 267 m->m_next = m1; 268 } 269 m0->m_pkthdr.len++; 270 } 271 272 /* 273 * Fill in mbuf with extended IPX header 274 * and addresses and length put into network format. 275 */ 276 m = m0; 277 if (ipxp->ipxp_flags & IPXP_RAWOUT) { 278 ipx = mtod(m, struct ipx *); 279 } else { 280 M_PREPEND(m, sizeof(struct ipx), M_DONTWAIT); 281 if (m == NULL) 282 return (ENOBUFS); 283 ipx = mtod(m, struct ipx *); 284 ipx->ipx_tc = 0; 285 ipx->ipx_pt = ipxp->ipxp_dpt; 286 ipx->ipx_sna = ipxp->ipxp_laddr; 287 ipx->ipx_dna = ipxp->ipxp_faddr; 288 len += sizeof(struct ipx); 289 } 290 291 ipx->ipx_len = htons((u_short)len); 292 293 if (ipxp->ipxp_flags & IPXP_CHECKSUM) { 294 ipx->ipx_sum = ipx_cksum(m, len); 295 } else 296 ipx->ipx_sum = 0xffff; 297 298 /* 299 * Output datagram. 300 */ 301 so = ipxp->ipxp_socket; 302 if (so->so_options & SO_DONTROUTE) 303 return (ipx_outputfl(m, (struct route *)NULL, 304 (so->so_options & SO_BROADCAST) | IPX_ROUTETOIF)); 305 /* 306 * Use cached route for previous datagram if 307 * possible. If the previous net was the same 308 * and the interface was a broadcast medium, or 309 * if the previous destination was identical, 310 * then we are ok. 311 * 312 * NB: We don't handle broadcasts because that 313 * would require 3 subroutine calls. 314 */ 315 ro = &ipxp->ipxp_route; 316#ifdef ancient_history 317 /* 318 * I think that this will all be handled in ipx_pcbconnect! 319 */ 320 if (ro->ro_rt != NULL) { 321 if(ipx_neteq(ipxp->ipxp_lastdst, ipx->ipx_dna)) { 322 /* 323 * This assumes we have no GH type routes 324 */ 325 if (ro->ro_rt->rt_flags & RTF_HOST) { 326 if (!ipx_hosteq(ipxp->ipxp_lastdst, ipx->ipx_dna)) 327 goto re_route; 328 329 } 330 if ((ro->ro_rt->rt_flags & RTF_GATEWAY) == 0) { 331 register struct ipx_addr *dst = 332 &satoipx_addr(ro->ro_dst); 333 dst->x_host = ipx->ipx_dna.x_host; 334 } 335 /* 336 * Otherwise, we go through the same gateway 337 * and dst is already set up. 338 */ 339 } else { 340 re_route: 341 RTFREE(ro->ro_rt); 342 ro->ro_rt = NULL; 343 } 344 } 345 ipxp->ipxp_lastdst = ipx->ipx_dna; 346#endif /* ancient_history */ 347 return (ipx_outputfl(m, ro, so->so_options & SO_BROADCAST)); 348} 349 350int 351ipx_ctloutput(so, sopt) 352 struct socket *so; 353 struct sockopt *sopt; 354{ 355 struct ipxpcb *ipxp = sotoipxpcb(so); 356 int mask, error, optval; 357 short soptval; 358 struct ipx ioptval; 359 long seq; 360 361 KASSERT(ipxp != NULL, ("ipx_ctloutput: ipxp == NULL")); 362 error = 0; 363 364 switch (sopt->sopt_dir) { 365 case SOPT_GET: 366 switch (sopt->sopt_name) { 367 case SO_ALL_PACKETS: 368 mask = IPXP_ALL_PACKETS; 369 goto get_flags; 370 371 case SO_HEADERS_ON_INPUT: 372 mask = IPXP_RAWIN; 373 goto get_flags; 374 375 case SO_IPX_CHECKSUM: 376 mask = IPXP_CHECKSUM; 377 goto get_flags; 378 379 case SO_HEADERS_ON_OUTPUT: 380 mask = IPXP_RAWOUT; 381 get_flags: 382 /* Unlocked read. */ 383 soptval = ipxp->ipxp_flags & mask; 384 error = sooptcopyout(sopt, &soptval, sizeof soptval); 385 break; 386 387 case SO_DEFAULT_HEADERS: 388 ioptval.ipx_len = 0; 389 ioptval.ipx_sum = 0; 390 ioptval.ipx_tc = 0; 391 IPX_LOCK(ipxp); 392 ioptval.ipx_pt = ipxp->ipxp_dpt; 393 ioptval.ipx_dna = ipxp->ipxp_faddr; 394 ioptval.ipx_sna = ipxp->ipxp_laddr; 395 IPX_UNLOCK(ipxp); 396 error = sooptcopyout(sopt, &soptval, sizeof soptval); 397 break; 398 399 case SO_SEQNO: 400 IPX_LIST_LOCK(); 401 seq = ipx_pexseq; 402 ipx_pexseq++; 403 IPX_LIST_UNLOCK(); 404 error = sooptcopyout(sopt, &seq, sizeof seq); 405 break; 406 407 default: 408 error = EINVAL; 409 } 410 break; 411 412 case SOPT_SET: 413 switch (sopt->sopt_name) { 414 case SO_ALL_PACKETS: 415 mask = IPXP_ALL_PACKETS; 416 goto set_head; 417 418 case SO_HEADERS_ON_INPUT: 419 mask = IPXP_RAWIN; 420 goto set_head; 421 422 case SO_IPX_CHECKSUM: 423 mask = IPXP_CHECKSUM; 424 425 case SO_HEADERS_ON_OUTPUT: 426 mask = IPXP_RAWOUT; 427 set_head: 428 error = sooptcopyin(sopt, &optval, sizeof optval, 429 sizeof optval); 430 if (error) 431 break; 432 IPX_LOCK(ipxp); 433 if (optval) 434 ipxp->ipxp_flags |= mask; 435 else 436 ipxp->ipxp_flags &= ~mask; 437 IPX_UNLOCK(ipxp); 438 break; 439 440 case SO_DEFAULT_HEADERS: 441 error = sooptcopyin(sopt, &ioptval, sizeof ioptval, 442 sizeof ioptval); 443 if (error) 444 break; 445 /* Unlocked write. */ 446 ipxp->ipxp_dpt = ioptval.ipx_pt; 447 break; 448#ifdef IPXIP 449 case SO_IPXIP_ROUTE: 450 error = ipxip_route(so, sopt); 451 break; 452#endif /* IPXIP */ 453 default: 454 error = EINVAL; 455 } 456 break; 457 } 458 return (error); 459} 460 461static void 462ipx_usr_abort(so) 463 struct socket *so; 464{ 465 466 /* XXXRW: Possibly ipx_disconnect() here? */ 467 soisdisconnected(so); 468} 469 470static int 471ipx_attach(so, proto, td) 472 struct socket *so; 473 int proto; 474 struct thread *td; 475{ 476#ifdef INVARIANTS 477 struct ipxpcb *ipxp = sotoipxpcb(so); 478#endif 479 int error; 480 481 KASSERT(ipxp == NULL, ("ipx_attach: ipxp != NULL")); 482 error = soreserve(so, ipxsendspace, ipxrecvspace); 483 if (error != 0) 484 return (error); 485 IPX_LIST_LOCK(); 486 error = ipx_pcballoc(so, &ipxpcb_list, td); 487 IPX_LIST_UNLOCK(); 488 return (error); 489} 490 491static int 492ipx_bind(so, nam, td) 493 struct socket *so; 494 struct sockaddr *nam; 495 struct thread *td; 496{ 497 struct ipxpcb *ipxp = sotoipxpcb(so); 498 int error; 499 500 KASSERT(ipxp != NULL, ("ipx_bind: ipxp == NULL")); 501 IPX_LIST_LOCK(); 502 IPX_LOCK(ipxp); 503 error = ipx_pcbbind(ipxp, nam, td); 504 IPX_UNLOCK(ipxp); 505 IPX_LIST_UNLOCK(); 506 return (error); 507} 508 509static void 510ipx_usr_close(so) 511 struct socket *so; 512{ 513 514 /* XXXRW: Possibly ipx_disconnect() here? */ 515 soisdisconnected(so); 516} 517 518static int 519ipx_connect(so, nam, td) 520 struct socket *so; 521 struct sockaddr *nam; 522 struct thread *td; 523{ 524 struct ipxpcb *ipxp = sotoipxpcb(so); 525 int error; 526 527 KASSERT(ipxp != NULL, ("ipx_connect: ipxp == NULL")); 528 IPX_LIST_LOCK(); 529 IPX_LOCK(ipxp); 530 if (!ipx_nullhost(ipxp->ipxp_faddr)) { 531 error = EISCONN; 532 goto out; 533 } 534 error = ipx_pcbconnect(ipxp, nam, td); 535 if (error == 0) 536 soisconnected(so); 537out: 538 IPX_UNLOCK(ipxp); 539 IPX_LIST_UNLOCK(); 540 return (error); 541} 542 543static void 544ipx_detach(so) 545 struct socket *so; 546{ 547 struct ipxpcb *ipxp = sotoipxpcb(so); 548 549 /* XXXRW: Should assert detached. */ 550 KASSERT(ipxp != NULL, ("ipx_detach: ipxp == NULL")); 551 IPX_LIST_LOCK(); 552 IPX_LOCK(ipxp); 553 ipx_pcbdetach(ipxp); 554 ipx_pcbfree(ipxp); 555 IPX_LIST_UNLOCK(); 556} 557 558static int 559ipx_disconnect(so) 560 struct socket *so; 561{ 562 struct ipxpcb *ipxp = sotoipxpcb(so); 563 int error; 564 565 KASSERT(ipxp != NULL, ("ipx_disconnect: ipxp == NULL")); 566 IPX_LIST_LOCK(); 567 IPX_LOCK(ipxp); 568 error = 0; 569 if (ipx_nullhost(ipxp->ipxp_faddr)) { 570 error = ENOTCONN; 571 goto out; 572 } 573 ipx_pcbdisconnect(ipxp); 574 soisdisconnected(so); 575out: 576 IPX_UNLOCK(ipxp); 577 IPX_LIST_UNLOCK(); 578 return (0); 579} 580 581int 582ipx_peeraddr(so, nam) 583 struct socket *so; 584 struct sockaddr **nam; 585{ 586 struct ipxpcb *ipxp = sotoipxpcb(so); 587 588 KASSERT(ipxp != NULL, ("ipx_peeraddr: ipxp == NULL")); 589 ipx_getpeeraddr(ipxp, nam); 590 return (0); 591} 592 593static int 594ipx_send(so, flags, m, nam, control, td) 595 struct socket *so; 596 int flags; 597 struct mbuf *m; 598 struct sockaddr *nam; 599 struct mbuf *control; 600 struct thread *td; 601{ 602 int error; 603 struct ipxpcb *ipxp = sotoipxpcb(so); 604 struct ipx_addr laddr; 605 606 KASSERT(ipxp != NULL, ("ipxp_send: ipxp == NULL")); 607 /* 608 * Attempt to only acquire the necessary locks: if the socket is 609 * already connected, we don't need to hold the IPX list lock to be 610 * used by ipx_pcbconnect() and ipx_pcbdisconnect(), just the IPX 611 * pcb lock. 612 */ 613 if (nam != NULL) { 614 IPX_LIST_LOCK(); 615 IPX_LOCK(ipxp); 616 laddr = ipxp->ipxp_laddr; 617 if (!ipx_nullhost(ipxp->ipxp_faddr)) { 618 IPX_UNLOCK(ipxp); 619 IPX_LIST_UNLOCK(); 620 error = EISCONN; 621 goto send_release; 622 } 623 /* 624 * Must block input while temporarily connected. 625 */ 626 error = ipx_pcbconnect(ipxp, nam, td); 627 if (error) { 628 IPX_UNLOCK(ipxp); 629 IPX_LIST_UNLOCK(); 630 goto send_release; 631 } 632 } else { 633 IPX_LOCK(ipxp); 634 if (ipx_nullhost(ipxp->ipxp_faddr)) { 635 IPX_UNLOCK(ipxp); 636 error = ENOTCONN; 637 goto send_release; 638 } 639 } 640 error = ipx_output(ipxp, m); 641 m = NULL; 642 if (nam != NULL) { 643 ipx_pcbdisconnect(ipxp); 644 ipxp->ipxp_laddr = laddr; 645 IPX_UNLOCK(ipxp); 646 IPX_LIST_UNLOCK(); 647 } else 648 IPX_UNLOCK(ipxp); 649 650send_release: 651 if (m != NULL) 652 m_freem(m); 653 return (error); 654} 655 656static int 657ipx_shutdown(so) 658 struct socket *so; 659{ 660 661 KASSERT(so->so_pcb != NULL, ("ipx_shutdown: so_pcb == NULL")); 662 socantsendmore(so); 663 return (0); 664} 665 666int 667ipx_sockaddr(so, nam) 668 struct socket *so; 669 struct sockaddr **nam; 670{ 671 struct ipxpcb *ipxp = sotoipxpcb(so); 672 673 KASSERT(ipxp != NULL, ("ipx_sockaddr: ipxp == NULL")); 674 ipx_getsockaddr(ipxp, nam); 675 return (0); 676} 677 678static int 679ripx_attach(so, proto, td) 680 struct socket *so; 681 int proto; 682 struct thread *td; 683{ 684 int error = 0; 685 struct ipxpcb *ipxp = sotoipxpcb(so); 686 687 KASSERT(ipxp == NULL, ("ripx_attach: ipxp != NULL")); 688 689 if (td != NULL) { 690 error = priv_check(td, PRIV_NETIPX_RAW); 691 if (error) 692 return (error); 693 } 694 695 /* 696 * We hold the IPX list lock for the duration as address parameters 697 * of the IPX pcb are changed. Since no one else holds a reference 698 * to the ipxpcb yet, we don't need the ipxpcb lock here. 699 */ 700 IPX_LIST_LOCK(); 701 error = ipx_pcballoc(so, &ipxrawpcb_list, td); 702 if (error) 703 goto out; 704 ipxp = sotoipxpcb(so); 705 error = soreserve(so, ipxsendspace, ipxrecvspace); 706 if (error) 707 goto out; 708 ipxp->ipxp_faddr.x_host = ipx_broadhost; 709 ipxp->ipxp_flags = IPXP_RAWIN | IPXP_RAWOUT; 710out: 711 IPX_LIST_UNLOCK(); 712 return (error); 713} 714