]>
git.saurik.com Git - apple/xnu.git/blob - bsd/netns/idp_usrreq.c
7814c0cc3245d0cad0550d79056b7df5ae2bd163
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 * Copyright (c) 1984, 1985, 1986, 1987, 1993
24 * The Regents of the University of California. All rights reserved.
26 * Redistribution and use in source and binary forms, with or without
27 * modification, are permitted provided that the following conditions
29 * 1. Redistributions of source code must retain the above copyright
30 * notice, this list of conditions and the following disclaimer.
31 * 2. Redistributions in binary form must reproduce the above copyright
32 * notice, this list of conditions and the following disclaimer in the
33 * documentation and/or other materials provided with the distribution.
34 * 3. All advertising materials mentioning features or use of this software
35 * must display the following acknowledgement:
36 * This product includes software developed by the University of
37 * California, Berkeley and its contributors.
38 * 4. Neither the name of the University nor the names of its contributors
39 * may be used to endorse or promote products derived from this software
40 * without specific prior written permission.
42 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
43 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
46 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
48 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
50 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
51 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
54 * @(#)idp_usrreq.c 8.1 (Berkeley) 6/10/93
57 #include <sys/param.h>
58 #include <sys/malloc.h>
60 #include <sys/protosw.h>
61 #include <sys/socket.h>
62 #include <sys/socketvar.h>
63 #include <sys/errno.h>
67 #include <net/route.h>
70 #include <netns/ns_pcb.h>
71 #include <netns/ns_if.h>
72 #include <netns/idp.h>
73 #include <netns/idp_var.h>
74 #include <netns/ns_error.h>
77 * IDP protocol implementation.
80 struct sockaddr_ns idp_ns
= { sizeof(idp_ns
), AF_NS
};
83 * This may also be called for raw listeners.
87 register struct nspcb
*nsp
;
89 register struct idp
*idp
= mtod(m
, struct idp
*);
90 struct ifnet
*ifp
= m
->m_pkthdr
.rcvif
;
95 * Construct sockaddr format source address.
96 * Stuff source address and datagram in user buffer.
98 idp_ns
.sns_addr
= idp
->idp_sna
;
99 if (ns_neteqnn(idp
->idp_sna
.x_net
, ns_zeronet
) && ifp
) {
100 register struct ifaddr
*ifa
;
102 for (ifa
= ifp
->if_addrlist
; ifa
; ifa
= ifa
->ifa_next
) {
103 if (ifa
->ifa_addr
->sa_family
== AF_NS
) {
104 idp_ns
.sns_addr
.x_net
=
105 IA_SNS(ifa
)->sns_addr
.x_net
;
110 nsp
->nsp_rpt
= idp
->idp_pt
;
111 if ( ! (nsp
->nsp_flags
& NSP_RAWIN
) ) {
112 m
->m_len
-= sizeof (struct idp
);
113 m
->m_pkthdr
.len
-= sizeof (struct idp
);
114 m
->m_data
+= sizeof (struct idp
);
116 if (sbappendaddr(&nsp
->nsp_socket
->so_rcv
, (struct sockaddr
*)&idp_ns
,
117 m
, (struct mbuf
*)0) == 0)
119 sorwakeup(nsp
->nsp_socket
);
128 struct socket
*so
= nsp
->nsp_socket
;
130 ns_pcbdisconnect(nsp
);
131 soisdisconnected(so
);
134 * Drop connection, reporting
135 * the specified error.
139 register struct nspcb
*nsp
;
142 struct socket
*so
= nsp
->nsp_socket
;
145 * someday, in the xerox world
146 * we will generate error protocol packets
147 * announcing that the socket has gone away.
149 /*if (TCPS_HAVERCVDSYN(tp->t_state)) {
150 tp->t_state = TCPS_CLOSED;
151 (void) tcp_output(tp);
153 so
->so_error
= errno
;
154 ns_pcbdisconnect(nsp
);
155 soisdisconnected(so
);
163 register struct mbuf
*m
;
164 register struct idp
*idp
;
165 register struct socket
*so
;
166 register int len
= 0;
167 register struct route
*ro
;
172 * Calculate data length.
174 for (m
= m0
; m
; m
= m
->m_next
) {
179 * Make sure packet is actually of even length.
184 if ((m
->m_flags
& M_EXT
) == 0 &&
185 (m
->m_len
+ m
->m_data
< &m
->m_dat
[MLEN
])) {
188 struct mbuf
*m1
= m_get(M_DONTWAIT
, MT_DATA
);
195 * mtod(m1
, char *) = 0;
202 * Fill in mbuf with extended IDP header
203 * and addresses and length put into network format.
206 if (nsp
->nsp_flags
& NSP_RAWOUT
) {
207 idp
= mtod(m
, struct idp
*);
209 M_PREPEND(m
, sizeof (struct idp
), M_DONTWAIT
);
212 idp
= mtod(m
, struct idp
*);
214 idp
->idp_pt
= nsp
->nsp_dpt
;
215 idp
->idp_sna
= nsp
->nsp_laddr
;
216 idp
->idp_dna
= nsp
->nsp_faddr
;
217 len
+= sizeof (struct idp
);
220 idp
->idp_len
= htons((u_short
)len
);
224 len
= ((len
- 1) | 1) + 1;
225 idp
->idp_sum
= ns_cksum(m
, len
);
227 idp
->idp_sum
= 0xffff;
232 so
= nsp
->nsp_socket
;
233 if (so
->so_options
& SO_DONTROUTE
)
234 return (ns_output(m
, (struct route
*)0,
235 (so
->so_options
& SO_BROADCAST
) | NS_ROUTETOIF
));
237 * Use cached route for previous datagram if
238 * possible. If the previous net was the same
239 * and the interface was a broadcast medium, or
240 * if the previous destination was identical,
243 * NB: We don't handle broadcasts because that
244 * would require 3 subroutine calls.
246 ro
= &nsp
->nsp_route
;
247 #ifdef ancient_history
249 * I think that this will all be handled in ns_pcbconnect!
252 if(ns_neteq(nsp
->nsp_lastdst
, idp
->idp_dna
)) {
254 * This assumes we have no GH type routes
256 if (ro
->ro_rt
->rt_flags
& RTF_HOST
) {
257 if (!ns_hosteq(nsp
->nsp_lastdst
, idp
->idp_dna
))
261 if ((ro
->ro_rt
->rt_flags
& RTF_GATEWAY
) == 0) {
262 register struct ns_addr
*dst
=
263 &satons_addr(ro
->ro_dst
);
264 dst
->x_host
= idp
->idp_dna
.x_host
;
267 * Otherwise, we go through the same gateway
268 * and dst is already set up.
273 ro
->ro_rt
= (struct rtentry
*)0;
276 nsp
->nsp_lastdst
= idp
->idp_dna
;
277 #endif /* ancient_history */
278 if (noIdpRoute
) ro
= 0;
279 return (ns_output(m
, ro
, so
->so_options
& SO_BROADCAST
));
282 idp_ctloutput(req
, so
, level
, name
, value
)
288 register struct mbuf
*m
;
289 struct nspcb
*nsp
= sotonspcb(so
);
291 extern long ns_pexseq
;
301 m
= m_get(M_DONTWAIT
, MT_DATA
);
307 mask
= NSP_ALL_PACKETS
;
310 case SO_HEADERS_ON_INPUT
:
314 case SO_HEADERS_ON_OUTPUT
:
317 m
->m_len
= sizeof(short);
318 *mtod(m
, short *) = nsp
->nsp_flags
& mask
;
321 case SO_DEFAULT_HEADERS
:
322 m
->m_len
= sizeof(struct idp
);
324 register struct idp
*idp
= mtod(m
, struct idp
*);
328 idp
->idp_pt
= nsp
->nsp_dpt
;
329 idp
->idp_dna
= nsp
->nsp_faddr
;
330 idp
->idp_sna
= nsp
->nsp_laddr
;
335 m
->m_len
= sizeof(long);
336 *mtod(m
, long *) = ns_pexseq
++;
350 mask
= NSP_ALL_PACKETS
;
353 case SO_HEADERS_ON_INPUT
:
357 case SO_HEADERS_ON_OUTPUT
:
360 if (value
&& *value
) {
361 ok
= mtod(*value
, int *);
363 nsp
->nsp_flags
|= mask
;
365 nsp
->nsp_flags
&= ~mask
;
366 } else error
= EINVAL
;
369 case SO_DEFAULT_HEADERS
:
371 register struct idp
*idp
372 = mtod(*value
, struct idp
*);
373 nsp
->nsp_dpt
= idp
->idp_pt
;
379 error
= nsip_route(*value
);
393 idp_usrreq(so
, req
, m
, nam
, control
)
396 struct mbuf
*m
, *nam
, *control
;
398 struct nspcb
*nsp
= sotonspcb(so
);
401 if (req
== PRU_CONTROL
)
402 return (ns_control(so
, (int)m
, (caddr_t
)nam
,
403 (struct ifnet
*)control
));
404 if (control
&& control
->m_len
) {
408 if (nsp
== NULL
&& req
!= PRU_ATTACH
) {
419 error
= ns_pcballoc(so
, &nspcb
);
422 error
= soreserve(so
, (u_long
) 2048, (u_long
) 2048);
436 error
= ns_pcbbind(nsp
, nam
);
444 if (!ns_nullhost(nsp
->nsp_faddr
)) {
448 error
= ns_pcbconnect(nsp
, nam
);
462 if (ns_nullhost(nsp
->nsp_faddr
)) {
466 ns_pcbdisconnect(nsp
);
467 soisdisconnected(so
);
476 struct ns_addr laddr
;
480 laddr
= nsp
->nsp_laddr
;
481 if (!ns_nullhost(nsp
->nsp_faddr
)) {
486 * Must block input while temporarily connected.
489 error
= ns_pcbconnect(nsp
, nam
);
495 if (ns_nullhost(nsp
->nsp_faddr
)) {
500 error
= idp_output(nsp
, m
);
503 ns_pcbdisconnect(nsp
);
505 nsp
->nsp_laddr
.x_host
= laddr
.x_host
;
506 nsp
->nsp_laddr
.x_port
= laddr
.x_port
;
514 soisdisconnected(so
);
518 ns_setsockaddr(nsp
, nam
);
522 ns_setpeeraddr(nsp
, nam
);
527 * stat: don't bother with a blocksize.
542 return (EOPNOTSUPP
); /* do not free mbuf's */
555 idp_raw_usrreq(so
, req
, m
, nam
, control
)
558 struct mbuf
*m
, *nam
, *control
;
561 struct nspcb
*nsp
= sotonspcb(so
);
562 extern struct nspcb nsrawpcb
;
568 if (!(so
->so_state
& SS_PRIV
) || (nsp
!= NULL
)) {
572 error
= ns_pcballoc(so
, &nsrawpcb
);
575 error
= soreserve(so
, (u_long
) 2048, (u_long
) 2048);
579 nsp
->nsp_faddr
.x_host
= ns_broadhost
;
580 nsp
->nsp_flags
= NSP_RAWIN
| NSP_RAWOUT
;
583 error
= idp_usrreq(so
, req
, m
, nam
, control
);