This source file includes following definitions.
- loopattach
- loop_clone_create
- loop_clone_destroy
- looutput
- lo_altqstart
- lortrequest
- loioctl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
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
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
242
243
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
262
263
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
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
297 #ifdef NETATALK
298 case AF_APPLETALK:
299 ifq = &atintrq2;
300 isr = NETISR_ATALK;
301 break;
302 #endif
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
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
386
387
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
401
402
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
422
423 break;
424
425 case SIOCADDMULTI:
426 case SIOCDELMULTI:
427 ifr = (struct ifreq *)data;
428 if (ifr == 0) {
429 error = EAFNOSUPPORT;
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
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 }