]>
git.saurik.com Git - apple/xnu.git/blob - bsd/netns/ns_ip.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_ip.c 8.1 (Berkeley) 6/10/93
58 * Software interface driver for encapsulating ns in ip.
62 #include <sys/param.h>
63 #include <sys/systm.h>
64 #include <sys/malloc.h>
66 #include <sys/socket.h>
67 #include <sys/socketvar.h>
68 #include <sys/errno.h>
69 #include <sys/ioctl.h>
70 #include <sys/protosw.h>
73 #include <net/netisr.h>
74 #include <net/route.h>
76 #include <netinet/in.h>
77 #include <netinet/in_systm.h>
78 #include <netinet/in_var.h>
79 #include <netinet/ip.h>
80 #include <netinet/ip_var.h>
82 #include <machine/mtpr.h>
85 #include <netns/ns_if.h>
86 #include <netns/idp.h>
89 struct ifnet ifen_ifnet
;
90 struct route ifen_route
;
91 struct in_addr ifen_src
;
92 struct in_addr ifen_dst
;
93 struct ifnet_en
*ifen_next
;
96 int nsipoutput(), nsipioctl(), nsipstart();
97 #define LOMTU (1024+512);
100 struct ifnet_en
*nsip_list
; /* list of all hosts and gateways or
106 register struct ifnet_en
*m
;
107 register struct ifnet
*ifp
;
109 if (nsipif
.if_mtu
== 0) {
111 ifp
->if_name
= "nsip";
113 ifp
->if_ioctl
= nsipioctl
;
114 ifp
->if_output
= nsipoutput
;
115 ifp
->if_start
= nsipstart
;
116 ifp
->if_flags
= IFF_POINTOPOINT
;
119 MALLOC((m
), struct ifnet_en
*, sizeof(*m
), M_PCB
, M_NOWAIT
);
120 if (m
== NULL
) return (NULL
);
121 m
->ifen_next
= nsip_list
;
123 ifp
= &m
->ifen_ifnet
;
125 ifp
->if_name
= "nsip";
127 ifp
->if_ioctl
= nsipioctl
;
128 ifp
->if_output
= nsipoutput
;
129 ifp
->if_start
= nsipstart
;
130 ifp
->if_flags
= IFF_POINTOPOINT
;
131 ifp
->if_unit
= nsipif
.if_unit
++;
139 * Process an ioctl request.
142 nsipioctl(ifp
, cmd
, data
)
143 register struct ifnet
*ifp
;
153 ifp
->if_flags
|= IFF_UP
;
158 * Everything else is done at a higher level.
163 ifr
= (struct ifreq
*)data
;
164 if ((ifr
->ifr_flags
& IFF_UP
) == 0)
165 error
= nsip_free(ifp
);
174 struct mbuf
*nsip_badlen
;
175 struct mbuf
*nsip_lastin
;
179 register struct mbuf
*m
;
182 register struct ip
*ip
;
183 register struct idp
*idp
;
184 register struct ifqueue
*ifq
= &nsintrq
;
187 if (nsip_hold_input
) {
189 m_freem(nsip_lastin
);
191 nsip_lastin
= m_copym(m
, 0, (int)M_COPYALL
, M_DONTWAIT
);
194 * Get IP and IDP header together in first mbuf.
196 nsipif
.if_ipackets
++;
197 s
= sizeof (struct ip
) + sizeof (struct idp
);
198 if (((m
->m_flags
& M_EXT
) || m
->m_len
< s
) &&
199 (m
= m_pullup(m
, s
)) == 0) {
203 ip
= mtod(m
, struct ip
*);
204 if (ip
->ip_hl
> (sizeof (struct ip
) >> 2)) {
205 ip_stripoptions(m
, (struct mbuf
*)0);
207 if ((m
= m_pullup(m
, s
)) == 0) {
211 ip
= mtod(m
, struct ip
*);
216 * Make mbuf data length reflect IDP length.
217 * If not enough data to reflect IDP length, drop.
219 m
->m_data
+= sizeof (struct ip
);
220 m
->m_len
-= sizeof (struct ip
);
221 m
->m_pkthdr
.len
-= sizeof (struct ip
);
222 idp
= mtod(m
, struct idp
*);
223 len
= ntohs(idp
->idp_len
);
224 if (len
& 1) len
++; /* Preserve Garbage Byte */
225 if (ip
->ip_len
!= len
) {
226 if (len
> ip
->ip_len
) {
228 if (nsip_badlen
) m_freem(nsip_badlen
);
232 /* Any extra will be trimmed off by the NS routines */
236 * Place interface pointer before the data
237 * for the receiving protocol.
239 m
->m_pkthdr
.rcvif
= ifp
;
252 schednetisr(NETISR_NS
);
258 nsipoutput(ifn
, m
, dst
)
259 struct ifnet_en
*ifn
;
260 register struct mbuf
*m
;
261 struct sockaddr
*dst
;
264 register struct ip
*ip
;
265 register struct route
*ro
= &(ifn
->ifen_route
);
266 register int len
= 0;
267 register struct idp
*idp
= mtod(m
, struct idp
*);
270 ifn
->ifen_ifnet
.if_opackets
++;
271 nsipif
.if_opackets
++;
275 * Calculate data length and make space
278 len
= ntohs(idp
->idp_len
);
279 if (len
& 1) len
++; /* Preserve Garbage Byte */
280 /* following clause not necessary on vax */
281 if (3 & (int)m
->m_data
) {
282 /* force longword alignment of ip hdr */
283 struct mbuf
*m0
= m_gethdr(MT_HEADER
, M_DONTWAIT
);
288 MH_ALIGN(m0
, sizeof (struct ip
));
289 m0
->m_flags
= m
->m_flags
& M_COPYFLAGS
;
291 m0
->m_len
= sizeof (struct ip
);
292 m0
->m_pkthdr
.len
= m0
->m_len
+ m
->m_len
;
293 m
->m_flags
&= ~M_PKTHDR
;
295 M_PREPEND(m
, sizeof (struct ip
), M_DONTWAIT
);
302 ip
= mtod(m
, struct ip
*);
304 ip
->ip_p
= IPPROTO_IDP
;
305 ip
->ip_src
= ifn
->ifen_src
;
306 ip
->ip_dst
= ifn
->ifen_dst
;
307 ip
->ip_len
= (u_short
)len
+ sizeof (struct ip
);
311 * Output final datagram.
313 error
= (ip_output(m
, (struct mbuf
*)0, ro
, SO_BROADCAST
, NULL
));
315 ifn
->ifen_ifnet
.if_oerrors
++;
316 ifn
->ifen_ifnet
.if_ierrors
= error
;
321 return (ENETUNREACH
);
327 panic("nsip_start called\n");
330 struct ifreq ifr
= {"nsip0"};
333 register struct mbuf
*m
;
335 register struct nsip_req
*rq
= mtod(m
, struct nsip_req
*);
336 struct sockaddr_ns
*ns_dst
= (struct sockaddr_ns
*)&rq
->rq_ns
;
337 struct sockaddr_in
*ip_dst
= (struct sockaddr_in
*)&rq
->rq_ip
;
339 struct ifnet_en
*ifn
;
340 struct sockaddr_in
*src
;
343 * First, make sure we already have an ns address:
345 if (ns_hosteqnh(ns_thishost
, ns_zerohost
))
346 return (EADDRNOTAVAIL
);
348 * Now, determine if we can get to the destination
350 bzero((caddr_t
)&ro
, sizeof (ro
));
351 ro
.ro_dst
= *(struct sockaddr
*)ip_dst
;
353 if (ro
.ro_rt
== 0 || ro
.ro_rt
->rt_ifp
== 0) {
354 return (ENETUNREACH
);
358 * And see how he's going to get back to us:
359 * i.e., what return ip address do we use?
362 register struct in_ifaddr
*ia
;
363 struct ifnet
*ifp
= ro
.ro_rt
->rt_ifp
;
365 for (ia
= in_ifaddr
; ia
; ia
= ia
->ia_next
)
366 if (ia
->ia_ifp
== ifp
)
372 return (EADDRNOTAVAIL
);
374 src
= (struct sockaddr_in
*)&ia
->ia_addr
;
378 * Is there a free (pseudo-)interface or space?
380 for (ifn
= nsip_list
; ifn
; ifn
= ifn
->ifen_next
) {
381 if ((ifn
->ifen_ifnet
.if_flags
& IFF_UP
) == 0)
390 ifn
->ifen_route
= ro
;
391 ifn
->ifen_dst
= ip_dst
->sin_addr
;
392 ifn
->ifen_src
= src
->sin_addr
;
395 * now configure this as a point to point link
397 ifr
.ifr_name
[4] = '0' + nsipif
.if_unit
- 1;
398 ifr
.ifr_dstaddr
= * (struct sockaddr
*) ns_dst
;
399 (void)ns_control((struct socket
*)0, (int)SIOCSIFDSTADDR
, (caddr_t
)&ifr
,
400 (struct ifnet
*)ifn
);
401 satons_addr(ifr
.ifr_addr
).x_host
= ns_thishost
;
402 return (ns_control((struct socket
*)0, (int)SIOCSIFADDR
, (caddr_t
)&ifr
,
403 (struct ifnet
*)ifn
));
409 register struct ifnet_en
*ifn
= (struct ifnet_en
*)ifp
;
410 struct route
*ro
= & ifn
->ifen_route
;
416 ifp
->if_flags
&= ~IFF_UP
;
420 nsip_ctlinput(cmd
, sa
)
424 extern u_char inetctlerrmap
[];
425 struct sockaddr_in
*sin
;
428 if ((unsigned)cmd
>= PRC_NCMDS
)
430 if (sa
->sa_family
!= AF_INET
&& sa
->sa_family
!= AF_IMPLINK
)
432 sin
= (struct sockaddr_in
*)sa
;
433 if (sin
->sin_addr
.s_addr
== INADDR_ANY
)
439 case PRC_REDIRECT_NET
:
440 case PRC_REDIRECT_HOST
:
441 case PRC_REDIRECT_TOSNET
:
442 case PRC_REDIRECT_TOSHOST
:
443 nsip_rtchange(&sin
->sin_addr
);
449 register struct in_addr
*dst
;
451 register struct ifnet_en
*ifn
;
453 for (ifn
= nsip_list
; ifn
; ifn
= ifn
->ifen_next
) {
454 if (ifn
->ifen_dst
.s_addr
== dst
->s_addr
&&
455 ifn
->ifen_route
.ro_rt
) {
456 RTFREE(ifn
->ifen_route
.ro_rt
);
457 ifn
->ifen_route
.ro_rt
= 0;