]> git.saurik.com Git - apple/xnu.git/blob - bsd/net/if_dummy.c
xnu-344.21.73.tar.gz
[apple/xnu.git] / bsd / net / if_dummy.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25 /*
26 * Copyright (c) 1982, 1986, 1993
27 * The Regents of the University of California. All rights reserved.
28 *
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions
31 * are met:
32 * 1. Redistributions of source code must retain the above copyright
33 * notice, this list of conditions and the following disclaimer.
34 * 2. Redistributions in binary form must reproduce the above copyright
35 * notice, this list of conditions and the following disclaimer in the
36 * documentation and/or other materials provided with the distribution.
37 * 3. All advertising materials mentioning features or use of this software
38 * must display the following acknowledgement:
39 * This product includes software developed by the University of
40 * California, Berkeley and its contributors.
41 * 4. Neither the name of the University nor the names of its contributors
42 * may be used to endorse or promote products derived from this software
43 * without specific prior written permission.
44 *
45 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55 * SUCH DAMAGE.
56 */
57 /*
58 * derived from
59 * @(#)if_loop.c 8.1 (Berkeley) 6/10/93
60 * Id: if_loop.c,v 1.22 1996/06/19 16:24:10 wollman Exp
61 */
62
63 /*
64 * Loopback interface driver for protocol testing and timing.
65 */
66 #if BSD310
67 #include "opt_inet.h"
68 #endif
69 #include "dummy.h"
70 #if NDUMMY > 0
71
72 #include <sys/param.h>
73 #include <sys/systm.h>
74 #include <sys/kernel.h>
75 #include <sys/mbuf.h>
76 #include <sys/socket.h>
77 #include <sys/sockio.h>
78 #include <sys/errno.h>
79 #include <sys/time.h>
80
81 #include <net/if.h>
82 #include <net/if_types.h>
83 #include <net/netisr.h>
84 #include <net/route.h>
85 #include <net/bpf.h>
86
87 #if INET
88 #include <netinet/in.h>
89 #include <netinet/in_systm.h>
90 #include <netinet/in_var.h>
91 #include <netinet/ip.h>
92 #endif
93
94 #if IPX
95 #include <netipx/ipx.h>
96 #include <netipx/ipx_if.h>
97 #endif
98
99 #if INET6
100 #ifndef INET
101 #include <netinet/in.h>
102 #endif
103 #include <netinet6/in6_var.h>
104 #include <netinet6/ip6.h>
105 #endif
106
107 #if NETATALK
108 #include <netinet/if_ether.h>
109 #include <netatalk/at.h>
110 #include <netatalk/at_var.h>
111 #endif NETATALK
112
113 #include "bpfilter.h"
114
115 static int dummyioctl __P((struct ifnet *, u_long, caddr_t));
116 int dummyoutput __P((struct ifnet *, register struct mbuf *, struct sockaddr *,
117 register struct rtentry *));
118 static void dummyrtrequest __P((int, struct rtentry *, struct sockaddr *));
119
120 static void dummyattach __P((void *));
121 PSEUDO_SET(dummyattach, if_dummy);
122
123 #if TINY_DUMMYMTU
124 #define DUMMYMTU (1024+512)
125 #else
126 #define DUMMYMTU 16384
127 #endif
128 #define HAVE_OLD_BPF 1
129
130 static struct ifnet dummyif[NDUMMY];
131
132 /* ARGSUSED */
133 static void
134 dummyattach(dummy)
135 void *dummy;
136 {
137 register struct ifnet *ifp;
138 register int i = 0;
139
140 for (i = 0; i < NDUMMY; i++) {
141 ifp = &dummyif[i];
142 #if defined(__NetBSD__) || defined(__OpenBSD__)
143 sprintf(ifp->if_xname, "dummy%d", i);
144 #else
145 ifp->if_name = "dummy";
146 ifp->if_unit = i;
147 #endif
148 #ifndef __bsdi__
149 ifp->if_softc = NULL;
150 #endif
151 ifp->if_mtu = DUMMYMTU;
152 /* Change to BROADCAST experimentaly to announce its prefix. */
153 ifp->if_flags = /* IFF_LOOPBACK */ IFF_BROADCAST | IFF_MULTICAST;
154 ifp->if_ioctl = dummyioctl;
155 ifp->if_output = dummyoutput;
156 ifp->if_type = IFT_DUMMY;
157 ifp->if_hdrlen = 0;
158 ifp->if_addrlen = 0;
159 if_attach(ifp);
160 #if NBPFILTER > 0
161 #ifdef HAVE_OLD_BPF
162 bpfattach(ifp, DLT_NULL, sizeof(u_int));
163 #else
164 bpfattach(&ifp->if_bpf, ifp, DLT_NULL, sizeof(u_int));
165 #endif
166 #endif
167 }
168 }
169
170 int
171 dummyoutput(ifp, m, dst, rt)
172 struct ifnet *ifp;
173 register struct mbuf *m;
174 struct sockaddr *dst;
175 register struct rtentry *rt;
176 {
177 int s, isr;
178 register struct ifqueue *ifq = 0;
179
180 if ((m->m_flags & M_PKTHDR) == 0)
181 panic("dummyoutput no HDR");
182 #if NBPFILTER > 0
183 /* BPF write needs to be handled specially */
184 if (dst->sa_family == AF_UNSPEC) {
185 dst->sa_family = *(mtod(m, int *));
186 m->m_len -= sizeof(int);
187 m->m_pkthdr.len -= sizeof(int);
188 m->m_data += sizeof(int);
189 }
190
191 if (ifp->if_bpf) {
192 /*
193 * We need to prepend the address family as
194 * a four byte field. Cons up a dummy header
195 * to pacify bpf. This is safe because bpf
196 * will only read from the mbuf (i.e., it won't
197 * try to free it or keep a pointer a to it).
198 */
199 struct mbuf m0;
200 u_int af = dst->sa_family;
201
202 m0.m_next = m;
203 m0.m_len = 4;
204 m0.m_data = (char *)&af;
205
206 #ifdef HAVE_OLD_BPF
207 bpf_mtap(ifp, &m0);
208 #else
209 bpf_mtap(ifp->if_bpf, &m0);
210 #endif
211 }
212 #endif
213 m->m_pkthdr.rcvif = ifp;
214
215 if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) {
216 m_freem(m);
217 return (rt->rt_flags & RTF_BLACKHOLE ? 0 :
218 rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH);
219 }
220 ifp->if_opackets++;
221 ifp->if_obytes += m->m_pkthdr.len;
222 switch (dst->sa_family) {
223
224 #if INET
225 case AF_INET:
226 ifq = &ipintrq;
227 isr = NETISR_IP;
228 break;
229 #endif
230 #if IPX
231 case AF_IPX:
232 ifq = &ipxintrq;
233 isr = NETISR_IPX;
234 break;
235 #endif
236 #if INET6
237 case AF_INET6:
238 ifq = &ip6intrq;
239 isr = NETISR_IPV6;
240 break;
241 #endif
242 #if NS
243 case AF_NS:
244 ifq = &nsintrq;
245 isr = NETISR_NS;
246 break;
247 #endif
248 #if ISO
249 case AF_ISO:
250 ifq = &clnlintrq;
251 isr = NETISR_ISO;
252 break;
253 #endif
254 #if NETATALK
255 case AF_APPLETALK:
256 ifq = &atintrq2;
257 isr = NETISR_ATALK;
258 break;
259 #endif NETATALK
260 default:
261 printf("%s: can't handle af%d\n",
262 if_name(ifp), dst->sa_family);
263 m_freem(m);
264 return (EAFNOSUPPORT);
265 }
266 s = splimp();
267 if (IF_QFULL(ifq)) {
268 IF_DROP(ifq);
269 m_freem(m);
270 splx(s);
271 return (ENOBUFS);
272 }
273 IF_ENQUEUE(ifq, m);
274 schednetisr(isr);
275 ifp->if_ipackets++;
276 ifp->if_ibytes += m->m_pkthdr.len;
277 splx(s);
278 return (0);
279 }
280
281 /* ARGSUSED */
282 static void
283 dummyrtrequest(cmd, rt, sa)
284 int cmd;
285 struct rtentry *rt;
286 struct sockaddr *sa;
287 {
288 if (rt) {
289 rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu; /* for ISO */
290 /*
291 * For optimal performance, the send and receive buffers
292 * should be at least twice the MTU plus a little more for
293 * overhead.
294 */
295 rt->rt_rmx.rmx_recvpipe =
296 rt->rt_rmx.rmx_sendpipe = 3 * DUMMYMTU;
297 }
298 }
299
300 /*
301 * Process an ioctl request.
302 */
303 /* ARGSUSED */
304 static int
305 dummyioctl(ifp, cmd, data)
306 register struct ifnet *ifp;
307 u_long cmd;
308 caddr_t data;
309 {
310 register struct ifaddr *ifa;
311 register struct ifreq *ifr = (struct ifreq *)data;
312 register int error = 0;
313
314 switch (cmd) {
315
316 case SIOCSIFADDR:
317 ifp->if_flags |= IFF_UP | IFF_RUNNING;
318 ifa = (struct ifaddr *)data;
319 ifa->ifa_rtrequest = dummyrtrequest;
320 /*
321 * Everything else is done at a higher level.
322 */
323 break;
324
325 case SIOCADDMULTI:
326 case SIOCDELMULTI:
327 if (ifr == 0) {
328 error = EAFNOSUPPORT; /* XXX */
329 break;
330 }
331 switch (ifr->ifr_addr.sa_family) {
332
333 #if INET
334 case AF_INET:
335 break;
336 #endif
337 #if INET6
338 case AF_INET6:
339 break;
340 #endif
341
342 default:
343 error = EAFNOSUPPORT;
344 break;
345 }
346 break;
347
348 case SIOCSIFMTU:
349 ifp->if_mtu = ifr->ifr_mtu;
350 break;
351
352 case SIOCSIFFLAGS:
353 break;
354
355 default:
356 error = EINVAL;
357 }
358 return (error);
359 }
360 #endif /* NDUMMY > 0 */