Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / net / if_loop.c
blobaf7b0c5c47eb66c8d115deb9123140be4d9278e3
1 /* $NetBSD: if_loop.c,v 1.69 2008/10/24 17:07:33 dyoung Exp $ */
3 /*
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
33 * Copyright (c) 1982, 1986, 1993
34 * The Regents of the University of California. All rights reserved.
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the
43 * documentation and/or other materials provided with the distribution.
44 * 3. Neither the name of the University nor the names of its contributors
45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission.
48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * SUCH DAMAGE.
60 * @(#)if_loop.c 8.2 (Berkeley) 1/9/95
64 * Loopback interface driver for protocol testing and timing.
67 #include <sys/cdefs.h>
68 __KERNEL_RCSID(0, "$NetBSD: if_loop.c,v 1.69 2008/10/24 17:07:33 dyoung Exp $");
70 #include "opt_inet.h"
71 #include "opt_atalk.h"
72 #include "opt_iso.h"
73 #include "opt_ipx.h"
74 #include "opt_mbuftrace.h"
76 #include "bpfilter.h"
78 #include <sys/param.h>
79 #include <sys/systm.h>
80 #include <sys/kernel.h>
81 #include <sys/mbuf.h>
82 #include <sys/socket.h>
83 #include <sys/errno.h>
84 #include <sys/ioctl.h>
85 #include <sys/time.h>
87 #include <sys/cpu.h>
89 #include <net/if.h>
90 #include <net/if_types.h>
91 #include <net/netisr.h>
92 #include <net/route.h>
94 #ifdef INET
95 #include <netinet/in.h>
96 #include <netinet/in_systm.h>
97 #include <netinet/in_var.h>
98 #include <netinet/ip.h>
99 #endif
101 #ifdef INET6
102 #ifndef INET
103 #include <netinet/in.h>
104 #endif
105 #include <netinet6/in6_var.h>
106 #include <netinet/ip6.h>
107 #endif
110 #ifdef IPX
111 #include <netipx/ipx.h>
112 #include <netipx/ipx_if.h>
113 #endif
115 #ifdef ISO
116 #include <netiso/iso.h>
117 #include <netiso/iso_var.h>
118 #endif
120 #ifdef NETATALK
121 #include <netatalk/at.h>
122 #include <netatalk/at_var.h>
123 #endif
125 #if NBPFILTER > 0
126 #include <net/bpf.h>
127 #endif
129 #if defined(LARGE_LOMTU)
130 #define LOMTU (131072 + MHLEN + MLEN)
131 #define LOMTU_MAX LOMTU
132 #else
133 #define LOMTU (32768 + MHLEN + MLEN)
134 #define LOMTU_MAX (65536 + MHLEN + MLEN)
135 #endif
137 #ifdef ALTQ
138 static void lostart(struct ifnet *);
139 #endif
141 static int loop_clone_create(struct if_clone *, int);
142 static int loop_clone_destroy(struct ifnet *);
144 static struct if_clone loop_cloner =
145 IF_CLONE_INITIALIZER("lo", loop_clone_create, loop_clone_destroy);
147 void
148 loopattach(int n)
151 (void)loop_clone_create(&loop_cloner, 0); /* lo0 always exists */
152 if_clone_attach(&loop_cloner);
155 static int
156 loop_clone_create(struct if_clone *ifc, int unit)
158 struct ifnet *ifp;
160 ifp = if_alloc(IFT_LOOP);
162 if_initname(ifp, ifc->ifc_name, unit);
164 ifp->if_mtu = LOMTU;
165 ifp->if_flags = IFF_LOOPBACK | IFF_MULTICAST | IFF_RUNNING;
166 ifp->if_ioctl = loioctl;
167 ifp->if_output = looutput;
168 #ifdef ALTQ
169 ifp->if_start = lostart;
170 #endif
171 ifp->if_type = IFT_LOOP;
172 ifp->if_hdrlen = 0;
173 ifp->if_addrlen = 0;
174 ifp->if_dlt = DLT_NULL;
175 IFQ_SET_READY(&ifp->if_snd);
176 if (unit == 0)
177 lo0ifp = ifp;
178 if_attach(ifp);
179 if_alloc_sadl(ifp);
180 #if NBPFILTER > 0
181 bpfattach(ifp, DLT_NULL, sizeof(u_int));
182 #endif
183 #ifdef MBUFTRACE
184 ifp->if_mowner = malloc(sizeof(struct mowner), M_DEVBUF,
185 M_WAITOK | M_ZERO);
186 strlcpy(ifp->if_mowner->mo_name, ifp->if_xname,
187 sizeof(ifp->if_mowner->mo_name));
188 MOWNER_ATTACH(ifp->if_mowner);
189 #endif
191 return (0);
194 static int
195 loop_clone_destroy(struct ifnet *ifp)
198 if (ifp == lo0ifp)
199 return (EPERM);
201 #ifdef MBUFTRACE
202 MOWNER_DETACH(ifp->if_mowner);
203 free(ifp->if_mowner, M_DEVBUF);
204 #endif
206 #if NBPFILTER > 0
207 bpfdetach(ifp);
208 #endif
209 if_detach(ifp);
211 free(ifp, M_DEVBUF);
213 return (0);
217 looutput(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
218 struct rtentry *rt)
220 int s, isr;
221 struct ifqueue *ifq = NULL;
223 MCLAIM(m, ifp->if_mowner);
224 if ((m->m_flags & M_PKTHDR) == 0)
225 panic("looutput: no header mbuf");
226 #if NBPFILTER > 0
227 if (ifp->if_bpf && (ifp->if_flags & IFF_LOOPBACK))
228 bpf_mtap_af(ifp->if_bpf, dst->sa_family, m);
229 #endif
230 m->m_pkthdr.rcvif = ifp;
232 if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) {
233 m_freem(m);
234 return (rt->rt_flags & RTF_BLACKHOLE ? 0 :
235 rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH);
238 ifp->if_opackets++;
239 ifp->if_obytes += m->m_pkthdr.len;
241 #ifdef ALTQ
243 * ALTQ on the loopback interface is just for debugging. It's
244 * used only for loopback interfaces, not for a simplex interface.
246 if ((ALTQ_IS_ENABLED(&ifp->if_snd) || TBR_IS_ENABLED(&ifp->if_snd)) &&
247 ifp->if_start == lostart) {
248 struct altq_pktattr pktattr;
249 int error;
252 * If the queueing discipline needs packet classification,
253 * do it before prepending the link headers.
255 IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family, &pktattr);
257 M_PREPEND(m, sizeof(uint32_t), M_DONTWAIT);
258 if (m == NULL)
259 return (ENOBUFS);
260 *(mtod(m, uint32_t *)) = dst->sa_family;
262 s = splnet();
263 IFQ_ENQUEUE(&ifp->if_snd, m, &pktattr, error);
264 (*ifp->if_start)(ifp);
265 splx(s);
266 return (error);
268 #endif /* ALTQ */
270 m_tag_delete_nonpersistent(m);
272 switch (dst->sa_family) {
274 #ifdef INET
275 case AF_INET:
276 ifq = &ipintrq;
277 isr = NETISR_IP;
278 break;
279 #endif
280 #ifdef INET6
281 case AF_INET6:
282 m->m_flags |= M_LOOP;
283 ifq = &ip6intrq;
284 isr = NETISR_IPV6;
285 break;
286 #endif
287 #ifdef ISO
288 case AF_ISO:
289 ifq = &clnlintrq;
290 isr = NETISR_ISO;
291 break;
292 #endif
293 #ifdef IPX
294 case AF_IPX:
295 ifq = &ipxintrq;
296 isr = NETISR_IPX;
297 break;
298 #endif
299 #ifdef NETATALK
300 case AF_APPLETALK:
301 ifq = &atintrq2;
302 isr = NETISR_ATALK;
303 break;
304 #endif
305 default:
306 printf("%s: can't handle af%d\n", ifp->if_xname,
307 dst->sa_family);
308 m_freem(m);
309 return (EAFNOSUPPORT);
311 s = splnet();
312 if (IF_QFULL(ifq)) {
313 IF_DROP(ifq);
314 m_freem(m);
315 splx(s);
316 return (ENOBUFS);
318 IF_ENQUEUE(ifq, m);
319 schednetisr(isr);
320 ifp->if_ipackets++;
321 ifp->if_ibytes += m->m_pkthdr.len;
322 splx(s);
323 return (0);
326 #ifdef ALTQ
327 static void
328 lostart(struct ifnet *ifp)
330 struct ifqueue *ifq;
331 struct mbuf *m;
332 uint32_t af;
333 int s, isr;
335 for (;;) {
336 IFQ_DEQUEUE(&ifp->if_snd, m);
337 if (m == NULL)
338 return;
340 af = *(mtod(m, uint32_t *));
341 m_adj(m, sizeof(uint32_t));
343 switch (af) {
344 #ifdef INET
345 case AF_INET:
346 ifq = &ipintrq;
347 isr = NETISR_IP;
348 break;
349 #endif
350 #ifdef INET6
351 case AF_INET6:
352 m->m_flags |= M_LOOP;
353 ifq = &ip6intrq;
354 isr = NETISR_IPV6;
355 break;
356 #endif
357 #ifdef IPX
358 case AF_IPX:
359 ifq = &ipxintrq;
360 isr = NETISR_IPX;
361 break;
362 #endif
363 #ifdef ISO
364 case AF_ISO:
365 ifq = &clnlintrq;
366 isr = NETISR_ISO;
367 break;
368 #endif
369 #ifdef NETATALK
370 case AF_APPLETALK:
371 ifq = &atintrq2;
372 isr = NETISR_ATALK;
373 break;
374 #endif
375 default:
376 printf("%s: can't handle af%d\n", ifp->if_xname, af);
377 m_freem(m);
378 return;
381 s = splnet();
382 if (IF_QFULL(ifq)) {
383 IF_DROP(ifq);
384 splx(s);
385 m_freem(m);
386 return;
388 IF_ENQUEUE(ifq, m);
389 schednetisr(isr);
390 ifp->if_ipackets++;
391 ifp->if_ibytes += m->m_pkthdr.len;
392 splx(s);
395 #endif /* ALTQ */
397 /* ARGSUSED */
398 void
399 lortrequest(int cmd, struct rtentry *rt,
400 const struct rt_addrinfo *info)
403 if (rt)
404 rt->rt_rmx.rmx_mtu = lo0ifp->if_mtu;
408 * Process an ioctl request.
410 /* ARGSUSED */
412 loioctl(struct ifnet *ifp, u_long cmd, void *data)
414 struct ifaddr *ifa;
415 struct ifreq *ifr = data;
416 int error = 0;
418 switch (cmd) {
420 case SIOCINITIFADDR:
421 ifp->if_flags |= IFF_UP;
422 ifa = (struct ifaddr *)data;
423 if (ifa != NULL /*&& ifa->ifa_addr->sa_family == AF_ISO*/)
424 ifa->ifa_rtrequest = lortrequest;
426 * Everything else is done at a higher level.
428 break;
430 case SIOCSIFMTU:
431 if ((unsigned)ifr->ifr_mtu > LOMTU_MAX)
432 error = EINVAL;
433 else if ((error = ifioctl_common(ifp, cmd, data)) == ENETRESET){
434 /* XXX update rt mtu for AF_ISO? */
435 error = 0;
437 break;
439 case SIOCADDMULTI:
440 case SIOCDELMULTI:
441 if (ifr == NULL) {
442 error = EAFNOSUPPORT; /* XXX */
443 break;
445 switch (ifreq_getaddr(cmd, ifr)->sa_family) {
447 #ifdef INET
448 case AF_INET:
449 break;
450 #endif
451 #ifdef INET6
452 case AF_INET6:
453 break;
454 #endif
456 default:
457 error = EAFNOSUPPORT;
458 break;
460 break;
462 default:
463 error = ifioctl_common(ifp, cmd, data);
465 return (error);