]>
git.saurik.com Git - apple/xnu.git/blob - bsd/netns/ns_input.c
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 * @(#)ns_input.c 8.1 (Berkeley) 6/10/93
57 #include <sys/param.h>
58 #include <sys/systm.h>
59 #include <sys/malloc.h>
61 #include <sys/domain.h>
62 #include <sys/protosw.h>
63 #include <sys/socket.h>
64 #include <sys/socketvar.h>
65 #include <sys/errno.h>
67 #include <sys/kernel.h>
70 #include <net/route.h>
71 #include <net/raw_cb.h>
74 #include <netns/ns_if.h>
75 #include <netns/ns_pcb.h>
76 #include <netns/idp.h>
77 #include <netns/idp_var.h>
78 #include <netns/ns_error.h>
83 union ns_host ns_thishost
;
84 union ns_host ns_zerohost
;
85 union ns_host ns_broadhost
;
86 union ns_net ns_zeronet
;
87 union ns_net ns_broadnet
;
88 struct sockaddr_ns ns_netmask
, ns_hostmask
;
90 static u_short allones
[] = {-1, -1, -1};
93 struct nspcb nsrawpcb
;
95 struct ifqueue nsintrq
;
96 int nsqmaxlen
= IFQ_MAXLEN
;
103 extern struct timeval time
;
105 ns_broadhost
= * (union ns_host
*) allones
;
106 ns_broadnet
= * (union ns_net
*) allones
;
107 nspcb
.nsp_next
= nspcb
.nsp_prev
= &nspcb
;
108 nsrawpcb
.nsp_next
= nsrawpcb
.nsp_prev
= &nsrawpcb
;
109 nsintrq
.ifq_maxlen
= nsqmaxlen
;
110 ns_pexseq
= time
.tv_usec
;
111 ns_netmask
.sns_len
= 6;
112 ns_netmask
.sns_addr
.x_net
= ns_broadnet
;
113 ns_hostmask
.sns_len
= 12;
114 ns_hostmask
.sns_addr
.x_net
= ns_broadnet
;
115 ns_hostmask
.sns_addr
.x_host
= ns_broadhost
;
119 * Idp input routine. Pass to next level.
121 int nsintr_getpck
= 0;
122 int nsintr_swtch
= 0;
125 register struct idp
*idp
;
126 register struct mbuf
*m
;
127 register struct nspcb
*nsp
;
134 * Get next datagram off input queue and get IDP header
138 IF_DEQUEUE(&nsintrq
, m
);
143 if ((m
->m_flags
& M_EXT
|| m
->m_len
< sizeof (struct idp
)) &&
144 (m
= m_pullup(m
, sizeof (struct idp
))) == 0) {
145 idpstat
.idps_toosmall
++;
150 * Give any raw listeners a crack at the packet
152 for (nsp
= nsrawpcb
.nsp_next
; nsp
!= &nsrawpcb
; nsp
= nsp
->nsp_next
) {
153 struct mbuf
*m1
= m_copy(m
, 0, (int)M_COPYALL
);
154 if (m1
) idp_input(m1
, nsp
);
157 idp
= mtod(m
, struct idp
*);
158 len
= ntohs(idp
->idp_len
);
159 if (oddpacketp
= len
& 1) {
160 len
++; /* If this packet is of odd length,
161 preserve garbage byte for checksum */
165 * Check that the amount of data in the buffers
166 * is as at least much as the IDP header would have us expect.
167 * Trim mbufs if longer than we expect.
168 * Drop packet if shorter than we expect.
170 if (m
->m_pkthdr
.len
< len
) {
171 idpstat
.idps_tooshort
++;
174 if (m
->m_pkthdr
.len
> len
) {
175 if (m
->m_len
== m
->m_pkthdr
.len
) {
177 m
->m_pkthdr
.len
= len
;
179 m_adj(m
, len
- m
->m_pkthdr
.len
);
181 if (idpcksum
&& ((i
= idp
->idp_sum
)!=0xffff)) {
183 if (i
!= (idp
->idp_sum
= ns_cksum(m
, len
))) {
184 idpstat
.idps_badsum
++;
186 if (ns_hosteqnh(ns_thishost
, idp
->idp_dna
.x_host
))
187 error
= NS_ERR_BADSUM
;
189 error
= NS_ERR_BADSUM_T
;
190 ns_error(m
, error
, 0);
195 * Is this a directed broadcast?
197 if (ns_hosteqnh(ns_broadhost
,idp
->idp_dna
.x_host
)) {
198 if ((!ns_neteq(idp
->idp_dna
, idp
->idp_sna
)) &&
199 (!ns_neteqnn(idp
->idp_dna
.x_net
, ns_broadnet
)) &&
200 (!ns_neteqnn(idp
->idp_sna
.x_net
, ns_zeronet
)) &&
201 (!ns_neteqnn(idp
->idp_dna
.x_net
, ns_zeronet
)) ) {
203 * Look to see if I need to eat this packet.
204 * Algorithm is to forward all young packets
205 * and prematurely age any packets which will
206 * by physically broadcasted.
207 * Any very old packets eaten without forwarding
210 * Suggestion of Bill Nesheim, Cornell U.
212 if (idp
->idp_tc
< NS_MAXHOPS
) {
218 * Is this our packet? If not, forward.
220 } else if (!ns_hosteqnh(ns_thishost
,idp
->idp_dna
.x_host
)) {
225 * Locate pcb for datagram.
227 nsp
= ns_pcblookup(&idp
->idp_sna
, idp
->idp_dna
.x_port
, NS_WILDCARD
);
229 * Switch out to protocol's input routine.
236 if ((nsp
->nsp_flags
& NSP_ALL_PACKETS
)==0)
237 switch (idp
->idp_pt
) {
249 ns_error(m
, NS_ERR_NOSOCK
, 0);
258 u_char nsctlerrmap
[PRC_NCMDS
] = {
259 ECONNABORTED
, ECONNABORTED
, 0, 0,
260 0, 0, EHOSTDOWN
, EHOSTUNREACH
,
261 ENETUNREACH
, EHOSTUNREACH
, ECONNREFUSED
, ECONNREFUSED
,
266 int idp_donosocks
= 1;
268 idp_ctlinput(cmd
, arg
)
274 struct ns_errp
*errp
;
276 extern struct nspcb
*idp_drop();
279 if (cmd
< 0 || cmd
> PRC_NCMDS
)
281 if (nsctlerrmap
[cmd
] == 0)
283 type
= NS_ERR_UNREACH_HOST
;
285 struct sockaddr_ns
*sns
;
289 case PRC_HOSTUNREACH
:
290 sns
= (struct sockaddr_ns
*)arg
;
291 if (sns
->sns_family
!= AF_NS
)
297 errp
= (struct ns_errp
*)arg
;
298 ns
= &errp
->ns_err_idp
.idp_dna
;
299 type
= errp
->ns_err_num
;
300 type
= ntohs((u_short
)type
);
304 case NS_ERR_UNREACH_HOST
:
305 ns_pcbnotify(ns
, (int)nsctlerrmap
[cmd
], idp_abort
, (long)0);
309 nsp
= ns_pcblookup(ns
, errp
->ns_err_idp
.idp_sna
.x_port
,
311 if(nsp
&& idp_donosocks
&& ! ns_nullhost(nsp
->nsp_faddr
))
312 (void) idp_drop(nsp
, (int)nsctlerrmap
[cmd
]);
317 int idpforwarding
= 1;
319 * Forward a packet. If some error occurs return the sender
320 * an error packet. Note we can't always generate a meaningful
321 * error message because the NS errors don't have a large enough repetoire
322 * of codes and types.
324 struct route idp_droute
;
325 struct route idp_sroute
;
330 register struct idp
*idp
= mtod(m
, struct idp
*);
331 register int error
, type
, code
;
332 struct mbuf
*mcopy
= NULL
;
334 int flags
= NS_FORWARDING
;
339 printf("forward: src ");
340 ns_printhost(&idp
->idp_sna
);
342 ns_printhost(&idp
->idp_dna
);
343 printf("hop count %d\n", idp
->idp_tc
);
345 if (idpforwarding
== 0) {
346 /* can't tell difference between net and host */
347 type
= NS_ERR_UNREACH_HOST
, code
= 0;
351 if (idp
->idp_tc
> NS_MAXHOPS
) {
352 type
= NS_ERR_TOO_OLD
, code
= 0;
356 * Save at most 42 bytes of the packet in case
357 * we need to generate an NS error message to the src.
359 mcopy
= m_copy(m
, 0, imin((int)ntohs(idp
->idp_len
), 42));
361 if ((ok_there
= idp_do_route(&idp
->idp_dna
,&idp_droute
))==0) {
362 type
= NS_ERR_UNREACH_HOST
, code
= 0;
366 * Here we think about forwarding broadcast packets,
367 * so we try to insure that it doesn't go back out
368 * on the interface it came in on. Also, if we
369 * are going to physically broadcast this, let us
370 * age the packet so we can eat it safely the second time around.
372 if (idp
->idp_dna
.x_host
.c_host
[0] & 0x1) {
373 struct ns_ifaddr
*ia
= ns_iaonnetof(&idp
->idp_dna
);
376 /* I'm gonna hafta eat this packet */
377 agedelta
+= NS_MAXHOPS
- idp
->idp_tc
;
378 idp
->idp_tc
= NS_MAXHOPS
;
380 if ((ok_back
= idp_do_route(&idp
->idp_sna
,&idp_sroute
))==0) {
381 /* error = ENETUNREACH; He'll never get it! */
385 if (idp_droute
.ro_rt
&&
386 (ifp
=idp_droute
.ro_rt
->rt_ifp
) &&
388 (ifp
!=idp_sroute
.ro_rt
->rt_ifp
)) {
389 flags
|= NS_ALLOWBROADCAST
;
391 type
= NS_ERR_UNREACH_HOST
, code
= 0;
395 /* need to adjust checksum */
396 if (idp
->idp_sum
!=0xffff) {
403 x
.l
= 0; x
.c
[0] = agedelta
;
404 shift
= (((((int)ntohs(idp
->idp_len
))+1)>>1)-2) & 0xf;
405 x
.l
= idp
->idp_sum
+ (x
.s
[0] << shift
);
406 x
.l
= x
.s
[0] + x
.s
[1];
407 x
.l
= x
.s
[0] + x
.s
[1];
408 if (x
.l
==0xffff) idp
->idp_sum
= 0; else idp
->idp_sum
= x
.l
;
410 if ((error
= ns_output(m
, &idp_droute
, flags
)) &&
412 idp
= mtod(mcopy
, struct idp
*);
413 type
= NS_ERR_UNSPEC_T
, code
= 0;
421 type
= NS_ERR_UNREACH_HOST
;
425 type
= NS_ERR_TOO_BIG
;
426 code
= 576; /* too hard to figure out mtu here */
430 type
= NS_ERR_UNSPEC_T
;
435 ns_error(m
, type
, code
);
439 idp_undo_route(&idp_droute
);
441 idp_undo_route(&idp_sroute
);
446 idp_do_route(src
, ro
)
451 struct sockaddr_ns
*dst
;
453 bzero((caddr_t
)ro
, sizeof (*ro
));
454 dst
= (struct sockaddr_ns
*)&ro
->ro_dst
;
456 dst
->sns_len
= sizeof(*dst
);
457 dst
->sns_family
= AF_NS
;
458 dst
->sns_addr
= *src
;
459 dst
->sns_addr
.x_port
= 0;
461 if (ro
->ro_rt
== 0 || ro
->ro_rt
->rt_ifp
== 0) {
469 register struct route
*ro
;
471 if (ro
->ro_rt
) {RTFREE(ro
->ro_rt
);}
474 ns_watch_output(m
, ifp
)
478 register struct nspcb
*nsp
;
479 register struct ifaddr
*ifa
;
481 * Give any raw listeners a crack at the packet
483 for (nsp
= nsrawpcb
.nsp_next
; nsp
!= &nsrawpcb
; nsp
= nsp
->nsp_next
) {
484 struct mbuf
*m0
= m_copy(m
, 0, (int)M_COPYALL
);
486 register struct idp
*idp
;
488 M_PREPEND(m0
, sizeof (*idp
), M_DONTWAIT
);
491 idp
= mtod(m0
, struct idp
*);
492 idp
->idp_sna
.x_net
= ns_zeronet
;
493 idp
->idp_sna
.x_host
= ns_thishost
;
494 if (ifp
&& (ifp
->if_flags
& IFF_POINTOPOINT
))
495 for(ifa
= ifp
->if_addrlist
; ifa
;
496 ifa
= ifa
->ifa_next
) {
497 if (ifa
->ifa_addr
->sa_family
==AF_NS
) {
498 idp
->idp_sna
= IA_SNS(ifa
)->sns_addr
;
502 idp
->idp_len
= ntohl(m0
->m_pkthdr
.len
);