2 * Copyright (c) 1984, 1985, 1986, 1987, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * @(#)idp_usrreq.c 8.1 (Berkeley) 6/10/93
34 * $FreeBSD: src/sys/netns/idp_usrreq.c,v 1.9 1999/08/28 00:49:47 peter Exp $
35 * $DragonFly: src/sys/netproto/ns/idp_usrreq.c,v 1.14 2007/04/22 01:13:16 dillon Exp $
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/malloc.h>
42 #include <sys/protosw.h>
43 #include <sys/socket.h>
44 #include <sys/socketvar.h>
45 #include <sys/errno.h>
47 #include <sys/thread2.h>
50 #include <net/route.h>
59 extern int idpcksum
; /* from ns_input.c */
60 extern long ns_pexseq
; /* from ns_input.c */
61 extern struct nspcb nsrawpcb
; /* from ns_input.c */
63 struct idpstat idpstat
;
66 * IDP protocol implementation.
69 struct sockaddr_ns idp_ns
= { sizeof(idp_ns
), AF_NS
};
72 * This may also be called for raw listeners.
75 idp_input(struct mbuf
*m
, ...)
77 struct idp
*idp
= mtod(m
, struct idp
*);
78 struct ifnet
*ifp
= m
->m_pkthdr
.rcvif
;
83 nsp
= __va_arg(ap
, struct nspcb
*);
89 * Construct sockaddr format source address.
90 * Stuff source address and datagram in user buffer.
92 idp_ns
.sns_addr
= idp
->idp_sna
;
93 if (ns_neteqnn(idp
->idp_sna
.x_net
, ns_zeronet
) && ifp
) {
97 TAILQ_FOREACH(ifa
, &ifp
->if_addrhead
, ifa_link
)
98 if (ifa
->ifa_addr
->sa_family
== AF_NS
) {
99 idp_ns
.sns_addr
.x_net
=
100 IA_SNS(ifa
)->sns_addr
.x_net
;
105 nsp
->nsp_rpt
= idp
->idp_pt
;
106 if ( ! (nsp
->nsp_flags
& NSP_RAWIN
) ) {
107 m
->m_len
-= sizeof (struct idp
);
108 m
->m_pkthdr
.len
-= sizeof (struct idp
);
109 m
->m_data
+= sizeof (struct idp
);
111 if (ssb_appendaddr(&nsp
->nsp_socket
->so_rcv
, (struct sockaddr
*)&idp_ns
,
112 m
, (struct mbuf
*)0) == 0)
114 sorwakeup(nsp
->nsp_socket
);
121 idp_abort(struct nspcb
*nsp
)
123 struct socket
*so
= nsp
->nsp_socket
;
125 ns_pcbdisconnect(nsp
);
126 soisdisconnected(so
);
129 * Drop connection, reporting
130 * the specified error.
133 idp_drop(struct nspcb
*nsp
, int errno
)
135 struct socket
*so
= nsp
->nsp_socket
;
138 * someday, in the xerox world
139 * we will generate error protocol packets
140 * announcing that the socket has gone away.
142 /*if (TCPS_HAVERCVDSYN(tp->t_state)) {
143 tp->t_state = TCPS_CLOSED;
146 so
->so_error
= errno
;
147 ns_pcbdisconnect(nsp
);
148 soisdisconnected(so
);
154 idp_output(struct mbuf
*m0
, struct socket
*so
, ...)
156 struct nspcb
*nsp
= sotonspcb(so
);
161 struct mbuf
*mprev
= NULL
;
164 * Calculate data length.
166 for (m
= m0
; m
; m
= m
->m_next
) {
171 * Make sure packet is actually of even length.
176 if ((m
->m_flags
& M_EXT
) == 0 &&
177 (m
->m_len
+ m
->m_data
< &m
->m_dat
[MLEN
])) {
180 struct mbuf
*m1
= m_get(MB_DONTWAIT
, MT_DATA
);
187 * mtod(m1
, char *) = 0;
194 * Fill in mbuf with extended IDP header
195 * and addresses and length put into network format.
198 if (nsp
->nsp_flags
& NSP_RAWOUT
) {
199 idp
= mtod(m
, struct idp
*);
201 M_PREPEND(m
, sizeof (struct idp
), MB_DONTWAIT
);
204 idp
= mtod(m
, struct idp
*);
206 idp
->idp_pt
= nsp
->nsp_dpt
;
207 idp
->idp_sna
= nsp
->nsp_laddr
;
208 idp
->idp_dna
= nsp
->nsp_faddr
;
209 len
+= sizeof (struct idp
);
212 idp
->idp_len
= htons((u_short
)len
);
216 len
= ((len
- 1) | 1) + 1;
217 idp
->idp_sum
= ns_cksum(m
, len
);
219 idp
->idp_sum
= 0xffff;
224 if (so
->so_options
& SO_DONTROUTE
)
225 return (ns_output(m
, (struct route
*)0,
226 (so
->so_options
& SO_BROADCAST
) | NS_ROUTETOIF
));
228 * Use cached route for previous datagram if
229 * possible. If the previous net was the same
230 * and the interface was a broadcast medium, or
231 * if the previous destination was identical,
234 * NB: We don't handle broadcasts because that
235 * would require 3 subroutine calls.
237 ro
= &nsp
->nsp_route
;
238 #ifdef ancient_history
240 * I think that this will all be handled in ns_pcbconnect!
243 if(ns_neteq(nsp
->nsp_lastdst
, idp
->idp_dna
)) {
245 * This assumes we have no GH type routes
247 if (ro
->ro_rt
->rt_flags
& RTF_HOST
) {
248 if (!ns_hosteq(nsp
->nsp_lastdst
, idp
->idp_dna
))
252 if ((ro
->ro_rt
->rt_flags
& RTF_GATEWAY
) == 0) {
253 struct ns_addr
*dst
=
254 &satons_addr(ro
->ro_dst
);
255 dst
->x_host
= idp
->idp_dna
.x_host
;
258 * Otherwise, we go through the same gateway
259 * and dst is already set up.
264 ro
->ro_rt
= (struct rtentry
*)0;
267 nsp
->nsp_lastdst
= idp
->idp_dna
;
268 #endif /* ancient_history */
269 if (noIdpRoute
) ro
= 0;
270 return (ns_output(m
, ro
, so
->so_options
& SO_BROADCAST
));
275 idp_ctloutput(int req
, struct socket
*so
, int level
, int name
,
279 struct nspcb
*nsp
= sotonspcb(so
);
290 m
= m_get(MB_DONTWAIT
, MT_DATA
);
296 mask
= NSP_ALL_PACKETS
;
299 case SO_HEADERS_ON_INPUT
:
303 case SO_HEADERS_ON_OUTPUT
:
306 m
->m_len
= sizeof(short);
307 *mtod(m
, short *) = nsp
->nsp_flags
& mask
;
310 case SO_DEFAULT_HEADERS
:
311 m
->m_len
= sizeof(struct idp
);
313 struct idp
*idp
= mtod(m
, struct idp
*);
317 idp
->idp_pt
= nsp
->nsp_dpt
;
318 idp
->idp_dna
= nsp
->nsp_faddr
;
319 idp
->idp_sna
= nsp
->nsp_laddr
;
324 m
->m_len
= sizeof(long);
325 *mtod(m
, long *) = ns_pexseq
++;
339 mask
= NSP_ALL_PACKETS
;
342 case SO_HEADERS_ON_INPUT
:
346 case SO_HEADERS_ON_OUTPUT
:
349 if (value
&& *value
) {
350 ok
= mtod(*value
, int *);
352 nsp
->nsp_flags
|= mask
;
354 nsp
->nsp_flags
&= ~mask
;
355 } else error
= EINVAL
;
358 case SO_DEFAULT_HEADERS
:
361 = mtod(*value
, struct idp
*);
362 nsp
->nsp_dpt
= idp
->idp_pt
;
368 error
= nsip_route(*value
);
383 * IDP_USRREQ PROCEDURES
387 idp_usr_abort(struct socket
*so
)
389 struct nspcb
*nsp
= sotonspcb(so
);
395 soisdisconnected(so
);
404 idp_attach(struct socket
*so
, int proto
, struct pru_attach_info
*ai
)
406 struct nspcb
*nsp
= sotonspcb(so
);
411 if ((error
= ns_pcballoc(so
, &nspcb
)) != 0)
413 error
= soreserve(so
, 2048, 2048, ai
->sb_rlimit
);
418 idp_raw_attach(struct socket
*so
, int proto
, struct pru_attach_info
*ai
)
420 struct nspcb
*nsp
= sotonspcb(so
);
423 #ifdef NS_PRIV_SOCKETS
424 if ((so
->so_state
& SS_PRIV
) == 0)
429 if ((error
= ns_pcballoc(so
, &nsrawpcb
)) != 0)
431 if ((error
= soreserve(so
, 2048, 2048, ai
->sb_rlimit
)) != 0)
434 nsp
->nsp_faddr
.x_host
= ns_broadhost
;
435 nsp
->nsp_flags
= NSP_RAWIN
| NSP_RAWOUT
;
440 idp_bind(struct socket
*so
, struct sockaddr
*nam
, struct thread
*td
)
442 struct nspcb
*nsp
= sotonspcb(so
);
446 error
= ns_pcbbind(nsp
, nam
);
453 idp_connect(struct socket
*so
, struct sockaddr
*nam
, struct thread
*td
)
455 struct nspcb
*nsp
= sotonspcb(so
);
459 if (!ns_nullhost(nsp
->nsp_faddr
))
461 else if ((error
= ns_pcbconnect(nsp
, nam
)) == 0)
470 idp_detach(struct socket
*so
)
472 struct nspcb
*nsp
= sotonspcb(so
);
485 idp_usr_disconnect(struct socket
*so
)
487 struct nspcb
*nsp
= sotonspcb(so
);
491 if (ns_nullhost(nsp
->nsp_faddr
)) {
495 ns_pcbdisconnect(nsp
);
496 soisdisconnected(so
);
505 idp_peeraddr(struct socket
*so
, struct sockaddr
**pnam
)
507 struct nspcb
*nsp
= sotonspcb(so
);
511 ns_setpeeraddr(nsp
, pnam
);
520 idp_send(struct socket
*so
, int flags
, struct mbuf
*m
,
521 struct sockaddr
*addr
, struct mbuf
*control
,
524 struct nspcb
*nsp
= sotonspcb(so
);
525 struct ns_addr laddr
;
530 if (control
&& control
->m_len
) {
537 laddr
= nsp
->nsp_laddr
;
538 if (!ns_nullhost(nsp
->nsp_faddr
))
541 error
= ns_pcbconnect(nsp
, addr
);
543 if (ns_nullhost(nsp
->nsp_faddr
))
549 error
= idp_output(m
, so
);
552 ns_pcbdisconnect(nsp
);
553 nsp
->nsp_laddr
.x_host
= laddr
.x_host
;
554 nsp
->nsp_laddr
.x_port
= laddr
.x_port
;
567 idp_sockaddr(struct socket
*so
, struct sockaddr
**pnam
)
569 struct nspcb
*nsp
= sotonspcb(so
);
573 ns_setsockaddr(nsp
, pnam
);
582 idp_shutdown(struct socket
*so
)
588 struct pr_usrreqs idp_usrreqs
= {
589 .pru_abort
= idp_usr_abort
,
590 .pru_accept
= pru_accept_notsupp
,
591 .pru_attach
= idp_attach
,
592 .pru_bind
= idp_bind
,
593 .pru_connect
= idp_connect
,
594 .pru_connect2
= pru_connect2_notsupp
,
595 .pru_control
= ns_control
,
596 .pru_detach
= idp_detach
,
597 .pru_disconnect
= idp_usr_disconnect
,
598 .pru_listen
= pru_listen_notsupp
,
599 .pru_peeraddr
= idp_peeraddr
,
600 .pru_rcvd
= pru_rcvd_notsupp
,
601 .pru_rcvoob
= pru_rcvoob_notsupp
,
602 .pru_send
= idp_send
,
603 .pru_sense
= pru_sense_null
,
604 .pru_shutdown
= idp_shutdown
,
605 .pru_sockaddr
= idp_sockaddr
,
606 .pru_sosend
= sosend
,
607 .pru_soreceive
= soreceive
,
611 struct pr_usrreqs idp_raw_usrreqs
= {
612 .pru_abort
= idp_usr_abort
,
613 .pru_accept
= pru_accept_notsupp
,
614 .pru_attach
= idp_raw_attach
,
615 .pru_bind
= idp_bind
,
616 .pru_connect
= idp_connect
,
617 .pru_connect2
= pru_connect2_notsupp
,
618 .pru_control
= ns_control
,
619 .pru_detach
= idp_detach
,
620 .pru_disconnect
= idp_usr_disconnect
,
621 .pru_listen
= pru_listen_notsupp
,
622 .pru_peeraddr
= idp_peeraddr
,
623 .pru_rcvd
= pru_rcvd_notsupp
,
624 .pru_rcvoob
= pru_rcvoob_notsupp
,
625 .pru_send
= idp_send
,
626 .pru_sense
= pru_sense_null
,
627 .pru_shutdown
= idp_shutdown
,
628 .pru_sockaddr
= idp_sockaddr
,
629 .pru_sosend
= sosend
,
630 .pru_soreceive
= soreceive
,