]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/net/if_loop.c
Add a workaround for a deadlock between the rt_setgate() and rt_check()
[FreeBSD/FreeBSD.git] / sys / net / if_loop.c
1 /*-
2  * Copyright (c) 1982, 1986, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 4. Neither the name of the University nor the names of its contributors
14  *    may be used to endorse or promote products derived from this software
15  *    without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  *      @(#)if_loop.c   8.2 (Berkeley) 1/9/95
30  * $FreeBSD$
31  */
32
33 /*
34  * Loopback interface driver for protocol testing and timing.
35  */
36
37 #include "opt_atalk.h"
38 #include "opt_inet.h"
39 #include "opt_inet6.h"
40 #include "opt_ipx.h"
41
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/kernel.h>
45 #include <sys/malloc.h>
46 #include <sys/mbuf.h>
47 #include <sys/module.h>
48 #include <machine/bus.h>
49 #include <sys/rman.h>
50 #include <sys/socket.h>
51 #include <sys/sockio.h>
52 #include <sys/sysctl.h>
53
54 #include <net/if.h>
55 #include <net/if_clone.h>
56 #include <net/if_types.h>
57 #include <net/netisr.h>
58 #include <net/route.h>
59 #include <net/bpf.h>
60 #include <net/bpfdesc.h>
61
62 #ifdef  INET
63 #include <netinet/in.h>
64 #include <netinet/in_var.h>
65 #endif
66
67 #ifdef IPX
68 #include <netipx/ipx.h>
69 #include <netipx/ipx_if.h>
70 #endif
71
72 #ifdef INET6
73 #ifndef INET
74 #include <netinet/in.h>
75 #endif
76 #include <netinet6/in6_var.h>
77 #include <netinet/ip6.h>
78 #endif
79
80 #ifdef NETATALK
81 #include <netatalk/at.h>
82 #include <netatalk/at_var.h>
83 #endif
84
85 #ifdef TINY_LOMTU
86 #define LOMTU   (1024+512)
87 #elif defined(LARGE_LOMTU)
88 #define LOMTU   131072
89 #else
90 #define LOMTU   16384
91 #endif
92
93 #define LONAME  "lo"
94
95 struct lo_softc {
96         struct  ifnet *sc_ifp;
97 };
98
99 int             loioctl(struct ifnet *, u_long, caddr_t);
100 static void     lortrequest(int, struct rtentry *, struct rt_addrinfo *);
101 int             looutput(struct ifnet *ifp, struct mbuf *m,
102                     struct sockaddr *dst, struct rtentry *rt);
103 static int      lo_clone_create(struct if_clone *, int, caddr_t);
104 static void     lo_clone_destroy(struct ifnet *);
105
106 struct ifnet *loif = NULL;                      /* Used externally */
107
108 static MALLOC_DEFINE(M_LO, LONAME, "Loopback Interface");
109
110 IFC_SIMPLE_DECLARE(lo, 1);
111
112 static void
113 lo_clone_destroy(ifp)
114         struct ifnet *ifp;
115 {
116         struct lo_softc *sc;
117         
118         sc = ifp->if_softc;
119
120         /* XXX: destroying lo0 will lead to panics. */
121         KASSERT(loif != ifp, ("%s: destroying lo0", __func__));
122
123         bpfdetach(ifp);
124         if_detach(ifp);
125         if_free(ifp);
126         free(sc, M_LO);
127 }
128
129 static int
130 lo_clone_create(ifc, unit, params)
131         struct if_clone *ifc;
132         int unit;
133         caddr_t params;
134 {
135         struct ifnet *ifp;
136         struct lo_softc *sc;
137
138         MALLOC(sc, struct lo_softc *, sizeof(*sc), M_LO, M_WAITOK | M_ZERO);
139         ifp = sc->sc_ifp = if_alloc(IFT_LOOP);
140         if (ifp == NULL) {
141                 free(sc, M_LO);
142                 return (ENOSPC);
143         }
144
145         if_initname(ifp, ifc->ifc_name, unit);
146         ifp->if_mtu = LOMTU;
147         ifp->if_flags = IFF_LOOPBACK | IFF_MULTICAST;
148         ifp->if_ioctl = loioctl;
149         ifp->if_output = looutput;
150         ifp->if_snd.ifq_maxlen = ifqmaxlen;
151         ifp->if_softc = sc;
152         if_attach(ifp);
153         bpfattach(ifp, DLT_NULL, sizeof(u_int32_t));
154         if (loif == NULL)
155                 loif = ifp;
156
157         return (0);
158 }
159
160 static int
161 loop_modevent(module_t mod, int type, void *data) 
162
163         switch (type) { 
164         case MOD_LOAD: 
165                 if_clone_attach(&lo_cloner);
166                 break; 
167         case MOD_UNLOAD: 
168                 printf("loop module unload - not possible for this module type\n"); 
169                 return EINVAL; 
170         default:
171                 return EOPNOTSUPP;
172         } 
173         return 0; 
174
175
176 static moduledata_t loop_mod = { 
177         "loop", 
178         loop_modevent, 
179         0
180 }; 
181
182 DECLARE_MODULE(loop, loop_mod, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY);
183
184 int
185 looutput(ifp, m, dst, rt)
186         struct ifnet *ifp;
187         register struct mbuf *m;
188         struct sockaddr *dst;
189         register struct rtentry *rt;
190 {
191         u_int32_t af;
192
193         M_ASSERTPKTHDR(m); /* check if we have the packet header */
194
195         if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) {
196                 m_freem(m);
197                 return (rt->rt_flags & RTF_BLACKHOLE ? 0 :
198                         rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH);
199         }
200
201         ifp->if_opackets++;
202         ifp->if_obytes += m->m_pkthdr.len;
203
204         /* BPF writes need to be handled specially. */
205         if (dst->sa_family == AF_UNSPEC) {
206                 bcopy(dst->sa_data, &af, sizeof(af));
207                 dst->sa_family = af;
208         }
209
210 #if 1   /* XXX */
211         switch (dst->sa_family) {
212         case AF_INET:
213         case AF_INET6:
214         case AF_IPX:
215         case AF_APPLETALK:
216                 break;
217         default:
218                 printf("looutput: af=%d unexpected\n", dst->sa_family);
219                 m_freem(m);
220                 return (EAFNOSUPPORT);
221         }
222 #endif
223         return(if_simloop(ifp, m, dst->sa_family, 0));
224 }
225
226 /*
227  * if_simloop()
228  *
229  * This function is to support software emulation of hardware loopback,
230  * i.e., for interfaces with the IFF_SIMPLEX attribute. Since they can't
231  * hear their own broadcasts, we create a copy of the packet that we
232  * would normally receive via a hardware loopback.
233  *
234  * This function expects the packet to include the media header of length hlen.
235  */
236
237 int
238 if_simloop(ifp, m, af, hlen)
239         struct ifnet *ifp;
240         struct mbuf *m;
241         int af;
242         int hlen;
243 {
244         int isr;
245
246         M_ASSERTPKTHDR(m);
247         m_tag_delete_nonpersistent(m);
248         m->m_pkthdr.rcvif = ifp;
249
250         /*
251          * Let BPF see incoming packet in the following manner:
252          *  - Emulated packet loopback for a simplex interface 
253          *    (net/if_ethersubr.c)
254          *      -> passes it to ifp's BPF
255          *  - IPv4/v6 multicast packet loopback (netinet(6)/ip(6)_output.c)
256          *      -> not passes it to any BPF
257          *  - Normal packet loopback from myself to myself (net/if_loop.c)
258          *      -> passes to lo0's BPF (even in case of IPv6, where ifp!=lo0)
259          */
260         if (hlen > 0) {
261                 if (bpf_peers_present(ifp->if_bpf)) {
262                         bpf_mtap(ifp->if_bpf, m);
263                 }
264         } else {
265                 if (bpf_peers_present(loif->if_bpf)) {
266                         if ((m->m_flags & M_MCAST) == 0 || loif == ifp) {
267                                 /* XXX beware sizeof(af) != 4 */
268                                 u_int32_t af1 = af;     
269
270                                 /*
271                                  * We need to prepend the address family.
272                                  */
273                                 bpf_mtap2(loif->if_bpf, &af1, sizeof(af1), m);
274                         }
275                 }
276         }
277
278         /* Strip away media header */
279         if (hlen > 0) {
280                 m_adj(m, hlen);
281 #ifndef __NO_STRICT_ALIGNMENT
282                 /*
283                  * Some archs do not like unaligned data, so
284                  * we move data down in the first mbuf.
285                  */
286                 if (mtod(m, vm_offset_t) & 3) {
287                         KASSERT(hlen >= 3, ("if_simloop: hlen too small"));
288                         bcopy(m->m_data, 
289                             (char *)(mtod(m, vm_offset_t) 
290                                 - (mtod(m, vm_offset_t) & 3)),
291                             m->m_len);
292                         m->m_data -= (mtod(m,vm_offset_t) & 3);
293                 }
294 #endif
295         }
296
297         /* Deliver to upper layer protocol */
298         switch (af) {
299 #ifdef INET
300         case AF_INET:
301                 isr = NETISR_IP;
302                 break;
303 #endif
304 #ifdef INET6
305         case AF_INET6:
306                 m->m_flags |= M_LOOP;
307                 isr = NETISR_IPV6;
308                 break;
309 #endif
310 #ifdef IPX
311         case AF_IPX:
312                 isr = NETISR_IPX;
313                 break;
314 #endif
315 #ifdef NETATALK
316         case AF_APPLETALK:
317                 isr = NETISR_ATALK2;
318                 break;
319 #endif
320         default:
321                 printf("if_simloop: can't handle af=%d\n", af);
322                 m_freem(m);
323                 return (EAFNOSUPPORT);
324         }
325         ifp->if_ipackets++;
326         ifp->if_ibytes += m->m_pkthdr.len;
327         netisr_queue(isr, m);   /* mbuf is free'd on failure. */
328         return (0);
329 }
330
331 /* ARGSUSED */
332 static void
333 lortrequest(cmd, rt, info)
334         int cmd;
335         struct rtentry *rt;
336         struct rt_addrinfo *info;
337 {
338         RT_LOCK_ASSERT(rt);
339         rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu;
340 }
341
342 /*
343  * Process an ioctl request.
344  */
345 /* ARGSUSED */
346 int
347 loioctl(ifp, cmd, data)
348         register struct ifnet *ifp;
349         u_long cmd;
350         caddr_t data;
351 {
352         register struct ifaddr *ifa;
353         register struct ifreq *ifr = (struct ifreq *)data;
354         register int error = 0;
355
356         switch (cmd) {
357
358         case SIOCSIFADDR:
359                 ifp->if_flags |= IFF_UP;
360                 ifp->if_drv_flags |= IFF_DRV_RUNNING;
361                 ifa = (struct ifaddr *)data;
362                 ifa->ifa_rtrequest = lortrequest;
363                 /*
364                  * Everything else is done at a higher level.
365                  */
366                 break;
367
368         case SIOCADDMULTI:
369         case SIOCDELMULTI:
370                 if (ifr == 0) {
371                         error = EAFNOSUPPORT;           /* XXX */
372                         break;
373                 }
374                 switch (ifr->ifr_addr.sa_family) {
375
376 #ifdef INET
377                 case AF_INET:
378                         break;
379 #endif
380 #ifdef INET6
381                 case AF_INET6:
382                         break;
383 #endif
384
385                 default:
386                         error = EAFNOSUPPORT;
387                         break;
388                 }
389                 break;
390
391         case SIOCSIFMTU:
392                 ifp->if_mtu = ifr->ifr_mtu;
393                 break;
394
395         case SIOCSIFFLAGS:
396                 break;
397
398         default:
399                 error = EINVAL;
400         }
401         return (error);
402 }