|
|
1.1 root 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: * @(#)if_loop.c 8.1 (Berkeley) 6/10/93
55: */
56:
57: /*
58: * Loopback interface driver for protocol testing and timing.
59: */
60: #include "loop.h"
61: #if NLOOP > 0
62:
63: #include <sys/param.h>
64: #include <sys/systm.h>
65: #include <sys/kernel.h>
66: #include <sys/mbuf.h>
67: #include <sys/socket.h>
68: #include <sys/sockio.h>
69:
70: #include <net/if.h>
71: #include <net/if_types.h>
72: #include <net/netisr.h>
73: #include <net/route.h>
74: #include <net/bpf.h>
75: #include <sys/malloc.h>
76:
77: #if INET
78: #include <netinet/in.h>
79: #include <netinet/in_var.h>
80: #endif
81:
82: #if IPX
83: #include <netipx/ipx.h>
84: #include <netipx/ipx_if.h>
85: #endif
86:
87: #if NS
88: #include <netns/ns.h>
89: #include <netns/ns_if.h>
90: #endif
91:
92: #if ISO
93: #include <netiso/iso.h>
94: #include <netiso/iso_var.h>
95: #endif
96:
97: #include <net/dlil.h>
98:
99: #if NETAT
100: extern struct ifqueue atalkintrq;
101: #endif
102:
103: #include "bpfilter.h"
104: #if NBPFILTER > 0
105: #include <net/bpfdesc.h>
106: #endif
107:
108:
109: #define NLOOP_ATTACHMENTS (NLOOP * 12)
110:
111: struct lo_statics_str {
112: int bpf_mode;
113: int (*bpf_callback)(struct ifnet *, struct mbuf *);
114: };
115:
116: static struct if_proto *lo_array[NLOOP_ATTACHMENTS];
117: static struct lo_statics_str lo_statics[NLOOP];
118: static lo_count = 0;
119:
120:
121: #ifdef TINY_LOMTU
122: #define LOMTU (1024+512)
123: #else
124: #define LOMTU 16384
125: #endif
126:
127: struct ifnet loif[NLOOP];
128:
129: void lo_reg_if_mods();
130:
131:
132:
133:
134: int lo_demux(ifp, m, frame_header, proto)
135: struct ifnet *ifp;
136: struct mbuf *m;
137: char *frame_header;
138: struct if_proto **proto;
139: {
140: int i;
141: struct if_proto **proto_ptr;
142:
143: proto_ptr = mtod(m, struct if_proto **);
144: *proto = *proto_ptr;
145: m_adj(m, sizeof(u_long));
146: return 0;
147: }
148:
149:
150: int lo_framer(ifp, m, dest, dest_linkaddr, frame_type)
151: struct ifnet *ifp;
152: struct mbuf **m;
153: struct sockaddr *dest;
154: char *dest_linkaddr;
155: char *frame_type;
156:
157: {
158: char *to_ptr;
159:
160: M_PREPEND(*m, (4 * sizeof(u_long)), M_WAITOK);
161: to_ptr = mtod(*m, char *);
162: bcopy(dest_linkaddr, to_ptr, (4 * sizeof(u_long)));
163: return 0;
164: }
165:
166: static
167: int lo_add_if(struct ifnet *ifp)
168: {
169: ifp->if_demux = lo_demux;
170: ifp->if_framer = lo_framer;
171: return 0;
172: }
173:
174: static
175: int lo_del_if(struct ifnet *ifp)
176: {
177: return 0;
178: }
179:
180:
181:
182:
183: static
184: int lo_add_proto(struct ddesc_head_str *desc_head, struct if_proto *proto, u_long dl_tag)
185: {
186: int i;
187:
188: for (i=0; i < lo_count; i++)
189: if (lo_array[i] == 0) {
190: lo_array[lo_count] = proto;
191: return 0;
192: }
193:
194: if ((i == lo_count) && (lo_count == NLOOP_ATTACHMENTS))
195: panic("lo_add_proto -- Too many attachments\n");
196:
197: lo_array[lo_count++] = proto;
198: return 0;
199: }
200:
201:
202: static
203: int lo_del_proto(struct if_proto *proto, u_long dl_tag)
204: {
205: int i;
206:
207: for (i=0; i < lo_count; i++)
208: if (lo_array[i] == proto) {
209: lo_array[i] = 0;
210: return 0;
211: }
212:
213: return ENOENT;
214: }
215:
216: static int
217: lo_output(ifp, m)
218: struct ifnet *ifp;
219: register struct mbuf *m;
220: { u_int *prepend_ptr;
221: u_int af;
222: u_long saved_header[3];
223:
224: if ((m->m_flags & M_PKTHDR) == 0)
225: panic("lo_output: no HDR");
226:
227: m->m_pkthdr.rcvif = ifp;
228:
229: prepend_ptr = mtod(m, u_int *);
230: af = *prepend_ptr;
231: m_adj(m, sizeof(u_int));
232:
233:
234: #if NBPFILTER > 0
235: if (lo_statics[ifp->if_unit].bpf_mode != BPF_TAP_DISABLE) {
236: struct mbuf m0, *n;
237:
238: bcopy(mtod(m, caddr_t), &saved_header[0], (3 * sizeof(u_long)));
239: m_adj(m, (3 * sizeof(u_long)));
240:
241: n = m;
242: if (ifp->if_bpf->bif_dlt == DLT_NULL) {
243: /*
244: * We need to prepend the address family as
245: * a four byte field. Cons up a dummy header
246: * to pacify bpf. This is safe because bpf
247: * will only read from the mbuf (i.e., it won't
248: * try to free it or keep a pointer a to it).
249: */
250: m0.m_next = m;
251: m0.m_len = 4;
252: m0.m_data = (char *)⁡
253: n = &m0;
254: }
255:
256: (*lo_statics[ifp->if_unit].bpf_callback)(ifp, n);
257:
258: M_PREPEND(m, (3 * sizeof(u_long)), M_WAITOK);
259: bcopy(&saved_header[0], mtod(m, caddr_t), (3 * sizeof(u_long)));
260:
261: }
262: #endif
263:
264: /*
265: * Turn this code back on when iokit starts incrementing these counters.
266: /*
267: /*
268: ifp->if_ibytes += m->m_pkthdr.len;
269: ifp->if_obytes += m->m_pkthdr.len;
270: */
271: ifp->if_opackets++;
272: ifp->if_ipackets++;
273:
274: return dlil_input(ifp, m, mtod(m, char *));
275: }
276:
277:
278: /*
279: * This is a common pre-output route used by INET, AT, etc. This could
280: * (should?) be split into separate pre-output routines for each protocol.
281: */
282:
283: static int
284: lo_pre_output(ifp, m, dst, route, frame_type, dst_addr, dl_tag)
285: struct ifnet *ifp;
286: register struct mbuf **m;
287: struct sockaddr *dst;
288: void *route;
289: char *frame_type;
290: char *dst_addr;
291: u_long dl_tag;
292:
293: {
294: int s, isr;
295: register struct ifqueue *ifq = 0;
296: u_long *prepend_ptr;
297: register struct rtentry *rt = (struct rtentry *) route;
298:
299: prepend_ptr = (u_long *) dst_addr;
300: if (((*m)->m_flags & M_PKTHDR) == 0)
301: panic("looutput no HDR");
302:
303: if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) {
304: if (rt->rt_flags & RTF_BLACKHOLE) {
305: m_freem(*m);
306: return EJUSTRETURN;
307: }
308: else
309: return ((rt->rt_flags & RTF_HOST) ? EHOSTUNREACH : ENETUNREACH);
310: }
311:
312: switch (dst->sa_family) {
313: #if INET
314: case AF_INET:
315: ifq = &ipintrq;
316: isr = NETISR_IP;
317: break;
318: #endif
319: #if IPX
320: case AF_IPX:
321: ifq = &ipxintrq;
322: isr = NETISR_IPX;
323: break;
324: #endif
325: #if NS
326: case AF_NS:
327: ifq = &nsintrq;
328: isr = NETISR_NS;
329: break;
330: #endif
331: #if ISO
332: case AF_ISO:
333: ifq = &clnlintrq;
334: isr = NETISR_ISO;
335: break;
336: #endif
337: #if NETAT
338: case AF_APPLETALK:
339: ifq = &atalkintrq;
340: isr = NETISR_APPLETALK;
341: break;
342: #endif NETAT
343: default:
344: return (EAFNOSUPPORT);
345: }
346:
347: *prepend_ptr++ = dst->sa_family; /* For lo_output(BPF) */
348: *prepend_ptr++ = dlttoproto(dl_tag); /* For lo_demux */
349: *prepend_ptr++ = (u_long) ifq; /* For lo_input */
350: *prepend_ptr = isr; /* For lo_input */
351:
352: return 0;
353: }
354:
355:
356:
357:
358: /*
359: * lo_input - This should work for all attached protocols that use the
360: * ifq/schednetisr input mechanism.
361: */
362:
363:
364: int
365: lo_input(m, fh, ifp, dl_tag, sync_ok)
366: register struct mbuf *m;
367: char *fh;
368: struct ifnet *ifp;
369: u_long dl_tag;
370: int sync_ok;
371:
372: {
373: u_long *prepend_ptr;
374: int s, isr;
375: register struct ifqueue *ifq = 0;
376:
377: prepend_ptr = mtod(m, u_long *);
378: ifq = (struct ifqueue *) *prepend_ptr++;
379: isr = *prepend_ptr;
380: m_adj(m, (2 * sizeof(u_long)));
381:
382: s = splimp();
383: if (IF_QFULL(ifq)) {
384: IF_DROP(ifq);
385: m_freem(m);
386: splx(s);
387: return (EJUSTRETURN);
388: }
389:
390: IF_ENQUEUE(ifq, m);
391: schednetisr(isr);
392: splx(s);
393: return (0);
394: }
395:
396:
397:
398:
399: /* ARGSUSED */
400: static void
401: lortrequest(cmd, rt, sa)
402: int cmd;
403: struct rtentry *rt;
404: struct sockaddr *sa;
405: {
406: if (rt) {
407: rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu; /* for ISO */
408: /*
409: * For optimal performance, the send and receive buffers
410: * should be at least twice the MTU plus a little more for
411: * overhead.
412: */
413: rt->rt_rmx.rmx_recvpipe =
414: rt->rt_rmx.rmx_sendpipe = 3 * LOMTU;
415: }
416: }
417:
418: /*
419: * Process an ioctl request.
420: */
421: /* ARGSUSED */
422: static int
423: loioctl(ifp, cmd, data)
424: register struct ifnet *ifp;
425: u_long cmd;
426: void *data;
427: {
428: register struct ifaddr *ifa;
429: register struct ifreq *ifr = (struct ifreq *)data;
430: register int error = 0;
431:
432: switch (cmd) {
433:
434: case SIOCSIFADDR:
435: ifp->if_flags |= IFF_UP | IFF_RUNNING;
436: ifa = (struct ifaddr *)data;
437: ifa->ifa_rtrequest = lortrequest;
438: /*
439: * Everything else is done at a higher level.
440: */
441: break;
442:
443: case SIOCADDMULTI:
444: case SIOCDELMULTI:
445: if (ifr == 0) {
446: error = EAFNOSUPPORT; /* XXX */
447: break;
448: }
449: switch (ifr->ifr_addr.sa_family) {
450:
451: #if INET
452: case AF_INET:
453: break;
454: #endif
455:
456: default:
457: error = EAFNOSUPPORT;
458: break;
459: }
460: break;
461:
462: case SIOCSIFMTU:
463: ifp->if_mtu = ifr->ifr_mtu;
464: break;
465:
466: case SIOCSIFFLAGS:
467: break;
468:
469: default:
470: error = EINVAL;
471: }
472: return (error);
473: }
474: #endif /* NLOOP > 0 */
475:
476:
477: int lo_shutdown()
478: {
479: return 0;
480: }
481:
482:
483: void lo_reg_if_mods()
484: {
485:
486: if (dlil_reg_if_modules(APPLE_IF_FAM_LOOPBACK, lo_add_if, lo_del_if,
487: lo_add_proto, lo_del_proto,
488: lo_shutdown))
489: panic("Couldn't register lo modules\n");
490:
491: }
492:
493:
494: u_long lo_attach_inet(struct ifnet *ifp)
495: {
496: struct dlil_proto_reg_str reg;
497: struct dlil_demux_desc desc;
498: u_long dl_tag=0;
499: short native=0;
500: int stat;
501: int i;
502:
503: for (i=0; i < lo_count; i++) {
504: if ((lo_array[i]) && (lo_array[i]->ifp == ifp)) {
505: if (lo_array[i]->protocol_family == PF_INET)
506: return lo_array[i]->dl_tag;
507: }
508: }
509:
510: TAILQ_INIT(®.demux_desc_head);
511: desc.type = DLIL_DESC_RAW;
512: desc.variants.bitmask.proto_id_length = 0;
513: desc.variants.bitmask.proto_id = 0;
514: desc.variants.bitmask.proto_id_mask = 0;
515: desc.native_type = (char *) &native;
516: TAILQ_INSERT_TAIL(®.demux_desc_head, &desc, next);
517: reg.interface_family = ifp->if_family;
518: reg.unit_number = ifp->if_unit;
519: reg.input = lo_input;
520: reg.pre_output = lo_pre_output;
521: reg.event = 0;
522: reg.offer = 0;
523: reg.ioctl = loioctl;
524: reg.default_proto = 0;
525: reg.protocol_family = PF_INET;
526:
527: stat = dlil_attach_protocol(®, &dl_tag);
528: if (stat) {
529: panic("ether_attach_inet can't attach interface\n");
530: }
531:
532: return dl_tag;
533: }
534:
535:
536: int lo_set_bpf_tap(struct ifnet *ifp, int mode, int (*bpf_callback)(struct ifnet *, struct mbuf *))
537: {
538:
539: /*
540: * NEED MUTEX HERE XXX
541: */
542: if (mode == BPF_TAP_DISABLE) {
543: lo_statics[ifp->if_unit].bpf_mode = mode;
544: lo_statics[ifp->if_unit].bpf_callback = bpf_callback;
545: }
546: else {
547: lo_statics[ifp->if_unit].bpf_callback = bpf_callback;
548: lo_statics[ifp->if_unit].bpf_mode = mode;
549: }
550:
551: return 0;
552: }
553:
554:
555: /* ARGSUSED */
556: void
557: loopattach(dummy)
558: void *dummy;
559: {
560: register struct ifnet *ifp;
561: register int i = 0;
562:
563: lo_reg_if_mods();
564:
565: for (ifp = loif; i < NLOOP; ifp++) {
566: lo_statics[i].bpf_callback = 0;
567: lo_statics[i].bpf_mode = BPF_TAP_DISABLE;
568: ifp->if_name = "lo";
569: ifp->if_family = APPLE_IF_FAM_LOOPBACK;
570: ifp->if_unit = i++;
571: ifp->if_mtu = LOMTU;
572: ifp->if_flags = IFF_LOOPBACK | IFF_MULTICAST;
573: ifp->if_ioctl = 0;
574: ifp->if_set_bpf_tap = lo_set_bpf_tap;
575: ifp->if_output = lo_output;
576: ifp->if_type = IFT_LOOP;
577: dlil_if_attach(ifp);
578: #if NBPFILTER > 0
579: bpfattach(ifp, DLT_NULL, sizeof(u_int));
580: #endif
581: }
582: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.