]> git.saurik.com Git - apple/xnu.git/blob - bsd/net/if_dummy.c
xnu-123.5.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 * 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.
11 *
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
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22 /*
23 * Copyright (c) 1982, 1986, 1993
24 * The Regents of the University of California. All rights reserved.
25 *
26 * Redistribution and use in source and binary forms, with or without
27 * modification, are permitted provided that the following conditions
28 * are met:
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.
41 *
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
52 * SUCH DAMAGE.
53 */
54 /*
55 * derived from
56 * @(#)if_loop.c 8.1 (Berkeley) 6/10/93
57 * Id: if_loop.c,v 1.22 1996/06/19 16:24:10 wollman Exp
58 */
59
60 /*
61 * Loopback interface driver for protocol testing and timing.
62 */
63 #if BSD310
64 #include "opt_inet.h"
65 #endif
66 #include "dummy.h"
67 #if NDUMMY > 0
68
69 #include <sys/param.h>
70 #include <sys/systm.h>
71 #include <sys/kernel.h>
72 #include <sys/mbuf.h>
73 #include <sys/socket.h>
74 #include <sys/sockio.h>
75 #include <sys/errno.h>
76 #include <sys/time.h>
77
78 #include <net/if.h>
79 #include <net/if_types.h>
80 #include <net/netisr.h>
81 #include <net/route.h>
82 #include <net/bpf.h>
83
84 #if INET
85 #include <netinet/in.h>
86 #include <netinet/in_systm.h>
87 #include <netinet/in_var.h>
88 #include <netinet/ip.h>
89 #endif
90
91 #if IPX
92 #include <netipx/ipx.h>
93 #include <netipx/ipx_if.h>
94 #endif
95
96 #if INET6
97 #ifndef INET
98 #include <netinet/in.h>
99 #endif
100 #include <netinet6/in6_var.h>
101 #include <netinet6/ip6.h>
102 #endif
103
104 #if NS
105 #include <netns/ns.h>
106 #include <netns/ns_if.h>
107 #endif
108
109 #if ISO
110 #include <netiso/iso.h>
111 #include <netiso/iso_var.h>
112 #endif
113
114 #if NETATALK
115 #include <netinet/if_ether.h>
116 #include <netatalk/at.h>
117 #include <netatalk/at_var.h>
118 #endif NETATALK
119
120 #include "bpfilter.h"
121
122 static int dummyioctl __P((struct ifnet *, u_long, caddr_t));
123 int dummyoutput __P((struct ifnet *, register struct mbuf *, struct sockaddr *,
124 register struct rtentry *));
125 static void dummyrtrequest __P((int, struct rtentry *, struct sockaddr *));
126
127 static void dummyattach __P((void *));
128 PSEUDO_SET(dummyattach, if_dummy);
129
130 #if TINY_DUMMYMTU
131 #define DUMMYMTU (1024+512)
132 #else
133 #define DUMMYMTU 16384
134 #endif
135 #define HAVE_OLD_BPF 1
136
137 static struct ifnet dummyif[NDUMMY];
138
139 /* ARGSUSED */
140 static void
141 dummyattach(dummy)
142 void *dummy;
143 {
144 register struct ifnet *ifp;
145 register int i = 0;
146
147 for (i = 0; i < NDUMMY; i++) {
148 ifp = &dummyif[i];
149 #if defined(__NetBSD__) || defined(__OpenBSD__)
150 sprintf(ifp->if_xname, "dummy%d", i);
151 #else
152 ifp->if_name = "dummy";
153 ifp->if_unit = i;
154 #endif
155 #ifndef __bsdi__
156 ifp->if_softc = NULL;
157 #endif
158 ifp->if_mtu = DUMMYMTU;
159 /* Change to BROADCAST experimentaly to announce its prefix. */
160 ifp->if_flags = /* IFF_LOOPBACK */ IFF_BROADCAST | IFF_MULTICAST;
161 ifp->if_ioctl = dummyioctl;
162 ifp->if_output = dummyoutput;
163 ifp->if_type = IFT_DUMMY;
164 ifp->if_hdrlen = 0;
165 ifp->if_addrlen = 0;
166 if_attach(ifp);
167 #if NBPFILTER > 0
168 #ifdef HAVE_OLD_BPF
169 bpfattach(ifp, DLT_NULL, sizeof(u_int));
170 #else
171 bpfattach(&ifp->if_bpf, ifp, DLT_NULL, sizeof(u_int));
172 #endif
173 #endif
174 }
175 }
176
177 int
178 dummyoutput(ifp, m, dst, rt)
179 struct ifnet *ifp;
180 register struct mbuf *m;
181 struct sockaddr *dst;
182 register struct rtentry *rt;
183 {
184 int s, isr;
185 register struct ifqueue *ifq = 0;
186
187 if ((m->m_flags & M_PKTHDR) == 0)
188 panic("dummyoutput no HDR");
189 #if NBPFILTER > 0
190 /* BPF write needs to be handled specially */
191 if (dst->sa_family == AF_UNSPEC) {
192 dst->sa_family = *(mtod(m, int *));
193 m->m_len -= sizeof(int);
194 m->m_pkthdr.len -= sizeof(int);
195 m->m_data += sizeof(int);
196 }
197
198 if (ifp->if_bpf) {
199 /*
200 * We need to prepend the address family as
201 * a four byte field. Cons up a dummy header
202 * to pacify bpf. This is safe because bpf
203 * will only read from the mbuf (i.e., it won't
204 * try to free it or keep a pointer a to it).
205 */
206 struct mbuf m0;
207 u_int af = dst->sa_family;
208
209 m0.m_next = m;
210 m0.m_len = 4;
211 m0.m_data = (char *)&af;
212
213 #ifdef HAVE_OLD_BPF
214 bpf_mtap(ifp, &m0);
215 #else
216 bpf_mtap(ifp->if_bpf, &m0);
217 #endif
218 }
219 #endif
220 m->m_pkthdr.rcvif = ifp;
221
222 if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) {
223 m_freem(m);
224 return (rt->rt_flags & RTF_BLACKHOLE ? 0 :
225 rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH);
226 }
227 ifp->if_opackets++;
228 ifp->if_obytes += m->m_pkthdr.len;
229 switch (dst->sa_family) {
230
231 #if INET
232 case AF_INET:
233 ifq = &ipintrq;
234 isr = NETISR_IP;
235 break;
236 #endif
237 #if IPX
238 case AF_IPX:
239 ifq = &ipxintrq;
240 isr = NETISR_IPX;
241 break;
242 #endif
243 #if INET6
244 case AF_INET6:
245 ifq = &ip6intrq;
246 isr = NETISR_IPV6;
247 break;
248 #endif
249 #if NS
250 case AF_NS:
251 ifq = &nsintrq;
252 isr = NETISR_NS;
253 break;
254 #endif
255 #if ISO
256 case AF_ISO:
257 ifq = &clnlintrq;
258 isr = NETISR_ISO;
259 break;
260 #endif
261 #if NETATALK
262 case AF_APPLETALK:
263 ifq = &atintrq2;
264 isr = NETISR_ATALK;
265 break;
266 #endif NETATALK
267 default:
268 printf("%s: can't handle af%d\n",
269 if_name(ifp), dst->sa_family);
270 m_freem(m);
271 return (EAFNOSUPPORT);
272 }
273 s = splimp();
274 if (IF_QFULL(ifq)) {
275 IF_DROP(ifq);
276 m_freem(m);
277 splx(s);
278 return (ENOBUFS);
279 }
280 IF_ENQUEUE(ifq, m);
281 schednetisr(isr);
282 ifp->if_ipackets++;
283 ifp->if_ibytes += m->m_pkthdr.len;
284 splx(s);
285 return (0);
286 }
287
288 /* ARGSUSED */
289 static void
290 dummyrtrequest(cmd, rt, sa)
291 int cmd;
292 struct rtentry *rt;
293 struct sockaddr *sa;
294 {
295 if (rt) {
296 rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu; /* for ISO */
297 /*
298 * For optimal performance, the send and receive buffers
299 * should be at least twice the MTU plus a little more for
300 * overhead.
301 */
302 rt->rt_rmx.rmx_recvpipe =
303 rt->rt_rmx.rmx_sendpipe = 3 * DUMMYMTU;
304 }
305 }
306
307 /*
308 * Process an ioctl request.
309 */
310 /* ARGSUSED */
311 static int
312 dummyioctl(ifp, cmd, data)
313 register struct ifnet *ifp;
314 u_long cmd;
315 caddr_t data;
316 {
317 register struct ifaddr *ifa;
318 register struct ifreq *ifr = (struct ifreq *)data;
319 register int error = 0;
320
321 switch (cmd) {
322
323 case SIOCSIFADDR:
324 ifp->if_flags |= IFF_UP | IFF_RUNNING;
325 ifa = (struct ifaddr *)data;
326 ifa->ifa_rtrequest = dummyrtrequest;
327 /*
328 * Everything else is done at a higher level.
329 */
330 break;
331
332 case SIOCADDMULTI:
333 case SIOCDELMULTI:
334 if (ifr == 0) {
335 error = EAFNOSUPPORT; /* XXX */
336 break;
337 }
338 switch (ifr->ifr_addr.sa_family) {
339
340 #if INET
341 case AF_INET:
342 break;
343 #endif
344 #if INET6
345 case AF_INET6:
346 break;
347 #endif
348
349 default:
350 error = EAFNOSUPPORT;
351 break;
352 }
353 break;
354
355 case SIOCSIFMTU:
356 ifp->if_mtu = ifr->ifr_mtu;
357 break;
358
359 case SIOCSIFFLAGS:
360 break;
361
362 default:
363 error = EINVAL;
364 }
365 return (error);
366 }
367 #endif /* NDUMMY > 0 */