Annotation of sys/net/if_loop.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: if_loop.c,v 1.41 2007/06/06 10:04:36 henning Exp $ */
2: /* $NetBSD: if_loop.c,v 1.15 1996/05/07 02:40:33 thorpej Exp $ */
3:
4: /*
5: * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6: * All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. Neither the name of the project nor the names of its contributors
17: * may be used to endorse or promote products derived from this software
18: * without specific prior written permission.
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23: * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30: * SUCH DAMAGE.
31: */
32:
33: /*
34: * Copyright (c) 1982, 1986, 1993
35: * The Regents of the University of California. All rights reserved.
36: *
37: * Redistribution and use in source and binary forms, with or without
38: * modification, are permitted provided that the following conditions
39: * are met:
40: * 1. Redistributions of source code must retain the above copyright
41: * notice, this list of conditions and the following disclaimer.
42: * 2. Redistributions in binary form must reproduce the above copyright
43: * notice, this list of conditions and the following disclaimer in the
44: * documentation and/or other materials provided with the distribution.
45: * 3. Neither the name of the University nor the names of its contributors
46: * may be used to endorse or promote products derived from this software
47: * without specific prior written permission.
48: *
49: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59: * SUCH DAMAGE.
60: *
61: * @(#)if_loop.c 8.1 (Berkeley) 6/10/93
62: */
63:
64: /*
65: * @(#)COPYRIGHT 1.1 (NRL) 17 January 1995
66: *
67: * NRL grants permission for redistribution and use in source and binary
68: * forms, with or without modification, of the software and documentation
69: * created at NRL provided that the following conditions are met:
70: *
71: * 1. Redistributions of source code must retain the above copyright
72: * notice, this list of conditions and the following disclaimer.
73: * 2. Redistributions in binary form must reproduce the above copyright
74: * notice, this list of conditions and the following disclaimer in the
75: * documentation and/or other materials provided with the distribution.
76: * 3. All advertising materials mentioning features or use of this software
77: * must display the following acknowledgements:
78: * This product includes software developed by the University of
79: * California, Berkeley and its contributors.
80: * This product includes software developed at the Information
81: * Technology Division, US Naval Research Laboratory.
82: * 4. Neither the name of the NRL nor the names of its contributors
83: * may be used to endorse or promote products derived from this software
84: * without specific prior written permission.
85: *
86: * THE SOFTWARE PROVIDED BY NRL IS PROVIDED BY NRL AND CONTRIBUTORS ``AS
87: * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
88: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
89: * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NRL OR
90: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
91: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
92: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
93: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
94: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
95: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
96: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
97: *
98: * The views and conclusions contained in the software and documentation
99: * are those of the authors and should not be interpreted as representing
100: * official policies, either expressed or implied, of the US Naval
101: * Research Laboratory (NRL).
102: */
103:
104: /*
105: * Loopback interface driver for protocol testing and timing.
106: */
107:
108: #include "bpfilter.h"
109:
110: #include <sys/param.h>
111: #include <sys/systm.h>
112: #include <sys/kernel.h>
113: #include <sys/mbuf.h>
114: #include <sys/socket.h>
115: #include <sys/errno.h>
116: #include <sys/ioctl.h>
117: #include <sys/time.h>
118:
119: #include <machine/cpu.h>
120:
121: #include <net/if.h>
122: #include <net/if_types.h>
123: #include <net/netisr.h>
124: #include <net/route.h>
125:
126: #ifdef INET
127: #include <netinet/in.h>
128: #include <netinet/in_systm.h>
129: #include <netinet/in_var.h>
130: #include <netinet/ip.h>
131: #endif
132:
133: #ifdef INET6
134: #ifndef INET
135: #include <netinet/in.h>
136: #endif
137: #include <netinet6/in6_var.h>
138: #include <netinet/ip6.h>
139: #endif
140:
141: #ifdef NETATALK
142: #include <netinet/if_ether.h>
143: #include <netatalk/at.h>
144: #include <netatalk/at_var.h>
145: #endif
146:
147: #if NBPFILTER > 0
148: #include <net/bpf.h>
149: #endif
150:
151: #if defined(LARGE_LOMTU)
152: #define LOMTU (131072 + MHLEN + MLEN)
153: #else
154: #define LOMTU (32768 + MHLEN + MLEN)
155: #endif
156:
157: #ifdef ALTQ
158: static void lo_altqstart(struct ifnet *);
159: #endif
160:
161: int loop_clone_create(struct if_clone *, int);
162: int loop_clone_destroy(struct ifnet *);
163:
164: struct if_clone loop_cloner =
165: IF_CLONE_INITIALIZER("lo", loop_clone_create, loop_clone_destroy);
166:
167: /* ARGSUSED */
168: void
169: loopattach(n)
170: int n;
171: {
172: (void) loop_clone_create(&loop_cloner, 0);
173: if_clone_attach(&loop_cloner);
174: }
175:
176: int
177: loop_clone_create(ifc, unit)
178: struct if_clone *ifc;
179: int unit;
180: {
181: struct ifnet *ifp;
182:
183: MALLOC(ifp, struct ifnet *, sizeof(*ifp), M_DEVBUF, M_NOWAIT);
184: if (ifp == NULL)
185: return (ENOMEM);
186: bzero(ifp, sizeof(struct ifnet));
187:
188: snprintf(ifp->if_xname, sizeof ifp->if_xname, "lo%d", unit);
189: ifp->if_softc = NULL;
190: ifp->if_mtu = LOMTU;
191: ifp->if_flags = IFF_LOOPBACK | IFF_MULTICAST;
192: ifp->if_ioctl = loioctl;
193: ifp->if_output = looutput;
194: ifp->if_type = IFT_LOOP;
195: ifp->if_hdrlen = sizeof(u_int32_t);
196: ifp->if_addrlen = 0;
197: IFQ_SET_READY(&ifp->if_snd);
198: #ifdef ALTQ
199: ifp->if_start = lo_altqstart;
200: #endif
201: if (unit == 0) {
202: lo0ifp = ifp;
203: if_attachhead(ifp);
204: if_addgroup(lo0ifp, ifc->ifc_name);
205: } else
206: if_attach(ifp);
207: if_alloc_sadl(ifp);
208: #if NBPFILTER > 0
209: bpfattach(&ifp->if_bpf, ifp, DLT_LOOP, sizeof(u_int32_t));
210: #endif
211: return (0);
212: }
213:
214: int
215: loop_clone_destroy(ifp)
216: struct ifnet *ifp;
217: {
218: if (ifp == lo0ifp)
219: return (EPERM);
220:
221: if_detach(ifp);
222:
223: free(ifp, M_DEVBUF);
224: return (0);
225: }
226:
227: int
228: looutput(ifp, m, dst, rt)
229: struct ifnet *ifp;
230: struct mbuf *m;
231: struct sockaddr *dst;
232: struct rtentry *rt;
233: {
234: int s, isr;
235: struct ifqueue *ifq = 0;
236:
237: if ((m->m_flags & M_PKTHDR) == 0)
238: panic("looutput: no header mbuf");
239: #if NBPFILTER > 0
240: /*
241: * only send packets to bpf if they are real loopback packets;
242: * looutput() is also called for SIMPLEX interfaces to duplicate
243: * packets for local use. But don't dup them to bpf.
244: */
245: if (ifp->if_bpf && (ifp->if_flags & IFF_LOOPBACK))
246: bpf_mtap_af(ifp->if_bpf, htonl(dst->sa_family), m,
247: BPF_DIRECTION_OUT);
248: #endif
249: m->m_pkthdr.rcvif = ifp;
250:
251: if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) {
252: m_freem(m);
253: return (rt->rt_flags & RTF_BLACKHOLE ? 0 :
254: rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH);
255: }
256:
257: ifp->if_opackets++;
258: ifp->if_obytes += m->m_pkthdr.len;
259: #ifdef ALTQ
260: /*
261: * altq for loop is just for debugging.
262: * only used when called for loop interface (not for
263: * a simplex interface).
264: */
265: if ((ALTQ_IS_ENABLED(&ifp->if_snd) || TBR_IS_ENABLED(&ifp->if_snd))
266: && ifp->if_start == lo_altqstart) {
267: int32_t *afp;
268: int error;
269:
270: M_PREPEND(m, sizeof(int32_t), M_DONTWAIT);
271: if (m == 0)
272: return (ENOBUFS);
273: afp = mtod(m, int32_t *);
274: *afp = (int32_t)dst->sa_family;
275:
276: s = splnet();
277: IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error);
278: (*ifp->if_start)(ifp);
279: splx(s);
280: return (error);
281: }
282: #endif /* ALTQ */
283: switch (dst->sa_family) {
284:
285: #ifdef INET
286: case AF_INET:
287: ifq = &ipintrq;
288: isr = NETISR_IP;
289: break;
290: #endif
291: #ifdef INET6
292: case AF_INET6:
293: ifq = &ip6intrq;
294: isr = NETISR_IPV6;
295: break;
296: #endif /* INET6 */
297: #ifdef NETATALK
298: case AF_APPLETALK:
299: ifq = &atintrq2;
300: isr = NETISR_ATALK;
301: break;
302: #endif /* NETATALK */
303: default:
304: printf("%s: can't handle af%d\n", ifp->if_xname,
305: dst->sa_family);
306: m_freem(m);
307: return (EAFNOSUPPORT);
308: }
309: s = splnet();
310: if (IF_QFULL(ifq)) {
311: IF_DROP(ifq);
312: m_freem(m);
313: splx(s);
314: return (ENOBUFS);
315: }
316: IF_ENQUEUE(ifq, m);
317: schednetisr(isr);
318: ifp->if_ipackets++;
319: ifp->if_ibytes += m->m_pkthdr.len;
320: splx(s);
321: return (0);
322: }
323:
324: #ifdef ALTQ
325: static void
326: lo_altqstart(ifp)
327: struct ifnet *ifp;
328: {
329: struct ifqueue *ifq;
330: struct mbuf *m;
331: int32_t af, *afp;
332: int s, isr;
333:
334: while (1) {
335: s = splnet();
336: IFQ_DEQUEUE(&ifp->if_snd, m);
337: splx(s);
338: if (m == NULL)
339: return;
340:
341: afp = mtod(m, int32_t *);
342: af = *afp;
343: m_adj(m, sizeof(int32_t));
344:
345: switch (af) {
346: #ifdef INET
347: case AF_INET:
348: ifq = &ipintrq;
349: isr = NETISR_IP;
350: break;
351: #endif
352: #ifdef INET6
353: case AF_INET6:
354: m->m_flags |= M_LOOP;
355: ifq = &ip6intrq;
356: isr = NETISR_IPV6;
357: break;
358: #endif
359: #ifdef NETATALK
360: case AF_APPLETALK:
361: ifq = &atintrq2;
362: isr = NETISR_ATALK;
363: break;
364: #endif /* NETATALK */
365: default:
366: printf("lo_altqstart: can't handle af%d\n", af);
367: m_freem(m);
368: return;
369: }
370:
371: s = splnet();
372: if (IF_QFULL(ifq)) {
373: IF_DROP(ifq);
374: m_freem(m);
375: splx(s);
376: return;
377: }
378: IF_ENQUEUE(ifq, m);
379: schednetisr(isr);
380: ifp->if_ipackets++;
381: ifp->if_ibytes += m->m_pkthdr.len;
382: splx(s);
383: }
384: }
385: #endif /* ALTQ */
386:
387: /* ARGSUSED */
388: void
389: lortrequest(cmd, rt, info)
390: int cmd;
391: struct rtentry *rt;
392: struct rt_addrinfo *info;
393: {
394:
395: if (rt)
396: rt->rt_rmx.rmx_mtu = LOMTU;
397: }
398:
399: /*
400: * Process an ioctl request.
401: */
402: /* ARGSUSED */
403: int
404: loioctl(ifp, cmd, data)
405: struct ifnet *ifp;
406: u_long cmd;
407: caddr_t data;
408: {
409: struct ifaddr *ifa;
410: struct ifreq *ifr;
411: int error = 0;
412:
413: switch (cmd) {
414:
415: case SIOCSIFADDR:
416: ifp->if_flags |= IFF_UP | IFF_RUNNING;
417: ifa = (struct ifaddr *)data;
418: if (ifa != 0)
419: ifa->ifa_rtrequest = lortrequest;
420: /*
421: * Everything else is done at a higher level.
422: */
423: break;
424:
425: case SIOCADDMULTI:
426: case SIOCDELMULTI:
427: ifr = (struct ifreq *)data;
428: if (ifr == 0) {
429: error = EAFNOSUPPORT; /* XXX */
430: break;
431: }
432: switch (ifr->ifr_addr.sa_family) {
433:
434: #ifdef INET
435: case AF_INET:
436: break;
437: #endif
438: #ifdef INET6
439: case AF_INET6:
440: break;
441: #endif /* INET6 */
442:
443: default:
444: error = EAFNOSUPPORT;
445: break;
446: }
447: break;
448:
449: case SIOCSIFMTU:
450: ifr = (struct ifreq *)data;
451: ifp->if_mtu = ifr->ifr_mtu;
452: break;
453:
454: default:
455: error = EINVAL;
456: }
457: return (error);
458: }
CVSweb