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