if_loop.c revision 105194
1209908Sraj/*
2209908Sraj * Copyright (c) 1982, 1986, 1993
3209908Sraj *	The Regents of the University of California.  All rights reserved.
4209908Sraj *
5209908Sraj * Redistribution and use in source and binary forms, with or without
6209908Sraj * modification, are permitted provided that the following conditions
7209908Sraj * are met:
8209908Sraj * 1. Redistributions of source code must retain the above copyright
9209908Sraj *    notice, this list of conditions and the following disclaimer.
10209908Sraj * 2. Redistributions in binary form must reproduce the above copyright
11209908Sraj *    notice, this list of conditions and the following disclaimer in the
12209908Sraj *    documentation and/or other materials provided with the distribution.
13209908Sraj * 3. All advertising materials mentioning features or use of this software
14209908Sraj *    must display the following acknowledgement:
15209908Sraj *	This product includes software developed by the University of
16209908Sraj *	California, Berkeley and its contributors.
17209908Sraj * 4. Neither the name of the University nor the names of its contributors
18209908Sraj *    may be used to endorse or promote products derived from this software
19209908Sraj *    without specific prior written permission.
20209908Sraj *
21209908Sraj * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22209908Sraj * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23209908Sraj * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24209908Sraj * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25209908Sraj * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26209908Sraj * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27209908Sraj * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28209908Sraj * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29209908Sraj * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30209908Sraj * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31209908Sraj * SUCH DAMAGE.
32209908Sraj *
33209908Sraj *	@(#)if_loop.c	8.2 (Berkeley) 1/9/95
34209908Sraj * $FreeBSD: head/sys/net/if_loop.c 105194 2002-10-16 01:54:46Z sam $
35209908Sraj */
36209908Sraj
37209908Sraj/*
38209908Sraj * Loopback interface driver for protocol testing and timing.
39209908Sraj */
40209908Sraj
41209908Sraj#include "opt_atalk.h"
42209908Sraj#include "opt_inet.h"
43209908Sraj#include "opt_inet6.h"
44209908Sraj#include "opt_ipx.h"
45209908Sraj
46209908Sraj#include <sys/param.h>
47209908Sraj#include <sys/systm.h>
48209908Sraj#include <sys/kernel.h>
49209908Sraj#include <sys/malloc.h>
50209908Sraj#include <sys/mbuf.h>
51209908Sraj#include <sys/module.h>
52209908Sraj#include <machine/bus.h>
53209908Sraj#include <sys/rman.h>
54209908Sraj#include <sys/socket.h>
55209908Sraj#include <sys/sockio.h>
56209908Sraj#include <sys/sysctl.h>
57209908Sraj
58209908Sraj#include <net/if.h>
59209908Sraj#include <net/if_types.h>
60209908Sraj#include <net/netisr.h>
61209908Sraj#include <net/route.h>
62209908Sraj#include <net/bpf.h>
63209908Sraj#include <net/bpfdesc.h>
64209908Sraj
65209908Sraj#ifdef	INET
66209908Sraj#include <netinet/in.h>
67209908Sraj#include <netinet/in_var.h>
68209908Sraj#endif
69209908Sraj
70209908Sraj#ifdef IPX
71209908Sraj#include <netipx/ipx.h>
72209908Sraj#include <netipx/ipx_if.h>
73209908Sraj#endif
74209908Sraj
75209908Sraj#ifdef INET6
76209908Sraj#ifndef INET
77209908Sraj#include <netinet/in.h>
78209908Sraj#endif
79209908Sraj#include <netinet6/in6_var.h>
80209908Sraj#include <netinet/ip6.h>
81209908Sraj#endif
82209908Sraj
83209908Sraj#ifdef NS
84209908Sraj#include <netns/ns.h>
85209908Sraj#include <netns/ns_if.h>
86209908Sraj#endif
87209908Sraj
88209908Sraj#ifdef NETATALK
89209908Sraj#include <netatalk/at.h>
90209908Sraj#include <netatalk/at_var.h>
91209908Sraj#endif
92209908Sraj
93227843Smarius#ifdef TINY_LOMTU
94227843Smarius#define	LOMTU	(1024+512)
95209908Sraj#elif defined(LARGE_LOMTU)
96209908Sraj#define LOMTU	131072
97209908Sraj#else
98209908Sraj#define LOMTU	16384
99209908Sraj#endif
100209908Sraj
101209908Sraj#define LONAME	"lo"
102209908Sraj
103209908Srajstruct lo_softc {
104209908Sraj	struct	ifnet sc_if;		/* network-visible interface */
105209908Sraj	LIST_ENTRY(lo_softc) sc_next;
106209908Sraj};
107209908Sraj
108209908Srajint		loioctl(struct ifnet *, u_long, caddr_t);
109209908Srajstatic void	lortrequest(int, struct rtentry *, struct rt_addrinfo *);
110209908Srajint		looutput(struct ifnet *ifp, struct mbuf *m,
111209908Sraj		    struct sockaddr *dst, struct rtentry *rt);
112209908Srajint		lo_clone_create(struct if_clone *, int);
113209908Srajvoid		lo_clone_destroy(struct ifnet *);
114209908Sraj
115209908Srajstruct ifnet *loif = NULL;			/* Used externally */
116209908Sraj
117209908Srajstatic MALLOC_DEFINE(M_LO, LONAME, "Loopback Interface");
118209908Sraj
119209908Srajstatic LIST_HEAD(lo_list, lo_softc) lo_list;
120209908Sraj
121209908Srajstruct if_clone lo_cloner = IF_CLONE_INITIALIZER(LONAME,
122209908Sraj    lo_clone_create, lo_clone_destroy, 1, IF_MAXUNIT);
123209908Sraj
124209908Srajvoid
125209908Srajlo_clone_destroy(ifp)
126209908Sraj	struct ifnet *ifp;
127209908Sraj{
128209908Sraj	struct lo_softc *sc;
129209908Sraj
130209908Sraj	sc = ifp->if_softc;
131209908Sraj
132209908Sraj	/* XXX: destroying lo0 will lead to panics. */
133209908Sraj	KASSERT(loif != ifp, ("%s: destroying lo0", __func__));
134209908Sraj
135209908Sraj	bpfdetach(ifp);
136209908Sraj	if_detach(ifp);
137209908Sraj	LIST_REMOVE(sc, sc_next);
138209908Sraj	free(sc, M_LO);
139209908Sraj}
140209908Sraj
141209908Srajint
142209908Srajlo_clone_create(ifc, unit)
143209908Sraj	struct if_clone *ifc;
144209908Sraj	int unit;
145209908Sraj{
146209908Sraj	struct lo_softc *sc;
147209908Sraj
148209908Sraj	MALLOC(sc, struct lo_softc *, sizeof(*sc), M_LO, M_WAITOK | M_ZERO);
149209908Sraj
150209908Sraj	sc->sc_if.if_name = LONAME;
151209908Sraj	sc->sc_if.if_unit = unit;
152209908Sraj	sc->sc_if.if_mtu = LOMTU;
153209908Sraj	sc->sc_if.if_flags = IFF_LOOPBACK | IFF_MULTICAST;
154209908Sraj	sc->sc_if.if_ioctl = loioctl;
155209908Sraj	sc->sc_if.if_output = looutput;
156209908Sraj	sc->sc_if.if_type = IFT_LOOP;
157209908Sraj	sc->sc_if.if_snd.ifq_maxlen = ifqmaxlen;
158232518Sraj	sc->sc_if.if_softc = sc;
159232518Sraj	if_attach(&sc->sc_if);
160209908Sraj	bpfattach(&sc->sc_if, DLT_NULL, sizeof(u_int));
161209908Sraj	LIST_INSERT_HEAD(&lo_list, sc, sc_next);
162209908Sraj	if (loif == NULL)
163209908Sraj		loif = &sc->sc_if;
164209908Sraj
165209908Sraj	return (0);
166209908Sraj}
167209908Sraj
168209908Srajstatic int
169209908Srajloop_modevent(module_t mod, int type, void *data)
170209908Sraj{
171209908Sraj	switch (type) {
172209908Sraj	case MOD_LOAD:
173209908Sraj		LIST_INIT(&lo_list);
174209908Sraj		if_clone_attach(&lo_cloner);
175209908Sraj		break;
176209908Sraj	case MOD_UNLOAD:
177209908Sraj		printf("loop module unload - not possible for this module type\n");
178209908Sraj		return EINVAL;
179209908Sraj	}
180209908Sraj	return 0;
181209908Sraj}
182209908Sraj
183209908Srajstatic moduledata_t loop_mod = {
184209908Sraj	"loop",
185209908Sraj	loop_modevent,
186209908Sraj	0
187209908Sraj};
188209908Sraj
189209908SrajDECLARE_MODULE(loop, loop_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
190209908Sraj
191209908Srajint
192209908Srajlooutput(ifp, m, dst, rt)
193209908Sraj	struct ifnet *ifp;
194209908Sraj	register struct mbuf *m;
195209908Sraj	struct sockaddr *dst;
196209908Sraj	register struct rtentry *rt;
197209908Sraj{
198209908Sraj	if ((m->m_flags & M_PKTHDR) == 0)
199209908Sraj		panic("looutput no HDR");
200209908Sraj
201209908Sraj	if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) {
202209908Sraj		m_freem(m);
203209908Sraj		return (rt->rt_flags & RTF_BLACKHOLE ? 0 :
204209908Sraj		        rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH);
205209908Sraj	}
206209908Sraj	/*
207209908Sraj	 * KAME requires that the packet to be contiguous on the
208209908Sraj	 * mbuf.  We need to make that sure.
209209908Sraj	 * this kind of code should be avoided.
210209908Sraj	 * XXX: fails to join if interface MTU > MCLBYTES.  jumbogram?
211209908Sraj	 */
212209908Sraj	if (m && m->m_next != NULL && m->m_pkthdr.len < MCLBYTES) {
213209908Sraj		struct mbuf *n;
214209908Sraj
215209908Sraj		MGETHDR(n, M_DONTWAIT, MT_HEADER);
216209908Sraj		if (!n)
217209908Sraj			goto contiguousfail;
218209908Sraj		MCLGET(n, M_DONTWAIT);
219209908Sraj		if (! (n->m_flags & M_EXT)) {
220209908Sraj			m_freem(n);
221209908Sraj			goto contiguousfail;
222209908Sraj		}
223209908Sraj
224209908Sraj		m_copydata(m, 0, m->m_pkthdr.len, mtod(n, caddr_t));
225209908Sraj		n->m_pkthdr = m->m_pkthdr;
226209908Sraj		n->m_len = m->m_pkthdr.len;
227209908Sraj		SLIST_INIT(&m->m_pkthdr.tags);
228209908Sraj		m_freem(m);
229209908Sraj		m = n;
230209908Sraj	}
231209908Sraj	if (0) {
232209908Srajcontiguousfail:
233209908Sraj		printf("looutput: mbuf allocation failed\n");
234209908Sraj	}
235209908Sraj
236209908Sraj	ifp->if_opackets++;
237209908Sraj	ifp->if_obytes += m->m_pkthdr.len;
238209908Sraj#if 1	/* XXX */
239209908Sraj	switch (dst->sa_family) {
240209908Sraj	case AF_INET:
241209908Sraj	case AF_INET6:
242209908Sraj	case AF_IPX:
243209908Sraj	case AF_NS:
244209908Sraj	case AF_APPLETALK:
245209908Sraj		break;
246209908Sraj	default:
247209908Sraj		printf("looutput: af=%d unexpected\n", dst->sa_family);
248209908Sraj		m_freem(m);
249209908Sraj		return (EAFNOSUPPORT);
250209908Sraj	}
251209908Sraj#endif
252209908Sraj	return(if_simloop(ifp, m, dst->sa_family, 0));
253209908Sraj}
254209908Sraj
255209908Sraj/*
256209908Sraj * if_simloop()
257209908Sraj *
258209908Sraj * This function is to support software emulation of hardware loopback,
259209908Sraj * i.e., for interfaces with the IFF_SIMPLEX attribute. Since they can't
260209908Sraj * hear their own broadcasts, we create a copy of the packet that we
261209908Sraj * would normally receive via a hardware loopback.
262209908Sraj *
263209908Sraj * This function expects the packet to include the media header of length hlen.
264209908Sraj */
265209908Sraj
266209908Srajint
267209908Srajif_simloop(ifp, m, af, hlen)
268209908Sraj	struct ifnet *ifp;
269209908Sraj	struct mbuf *m;
270209908Sraj	int af;
271209908Sraj	int hlen;
272209908Sraj{
273209908Sraj	int isr;
274209908Sraj	struct ifqueue *inq = 0;
275209908Sraj
276209908Sraj	KASSERT((m->m_flags & M_PKTHDR) != 0, ("if_simloop: no HDR"));
277209908Sraj	m->m_pkthdr.rcvif = ifp;
278209908Sraj
279209908Sraj	/* BPF write needs to be handled specially */
280209908Sraj	if (af == AF_UNSPEC) {
281209908Sraj		KASSERT(m->m_len >= sizeof(int), ("if_simloop: m_len"));
282209908Sraj		af = *(mtod(m, int *));
283209908Sraj		m->m_len -= sizeof(int);
284209908Sraj		m->m_pkthdr.len -= sizeof(int);
285209908Sraj		m->m_data += sizeof(int);
286209908Sraj	}
287209908Sraj
288209908Sraj	/* Let BPF see incoming packet */
289209908Sraj	if (ifp->if_bpf) {
290209908Sraj		struct mbuf m0, *n = m;
291209908Sraj
292209908Sraj		if (ifp->if_bpf->bif_dlt == DLT_NULL) {
293209908Sraj			/*
294209908Sraj			 * We need to prepend the address family as
295209908Sraj			 * a four byte field.  Cons up a dummy header
296209908Sraj			 * to pacify bpf.  This is safe because bpf
297209908Sraj			 * will only read from the mbuf (i.e., it won't
298209908Sraj			 * try to free it or keep a pointer a to it).
299209908Sraj			 */
300209908Sraj			m0.m_next = m;
301209908Sraj			m0.m_len = 4;
302209908Sraj			m0.m_data = (char *)&af;
303209908Sraj			n = &m0;
304209908Sraj		}
305209908Sraj		bpf_mtap(ifp, n);
306209908Sraj	}
307209908Sraj
308209908Sraj	/* Strip away media header */
309209908Sraj	if (hlen > 0) {
310209908Sraj		m_adj(m, hlen);
311209908Sraj#if defined(__alpha__) || defined(__ia64__) || defined(__sparc64__)
312209908Sraj		/* The alpha doesn't like unaligned data.
313209908Sraj		 * We move data down in the first mbuf */
314209908Sraj		if (mtod(m, vm_offset_t) & 3) {
315218050Smarcel			KASSERT(hlen >= 3, ("if_simloop: hlen too small"));
316209908Sraj			bcopy(m->m_data,
317209908Sraj			    (char *)(mtod(m, vm_offset_t)
318218050Smarcel				- (mtod(m, vm_offset_t) & 3)),
319218050Smarcel			    m->m_len);
320218050Smarcel			mtod(m,vm_offset_t) -= (mtod(m, vm_offset_t) & 3);
321218050Smarcel		}
322218050Smarcel#endif
323218050Smarcel	}
324209908Sraj
325209908Sraj	/* Deliver to upper layer protocol */
326209908Sraj	switch (af) {
327209908Sraj#ifdef INET
328209908Sraj	case AF_INET:
329209908Sraj		inq = &ipintrq;
330209908Sraj		isr = NETISR_IP;
331218050Smarcel		break;
332218050Smarcel#endif
333209908Sraj#ifdef INET6
334218050Smarcel	case AF_INET6:
335209908Sraj		m->m_flags |= M_LOOP;
336		inq = &ip6intrq;
337		isr = NETISR_IPV6;
338		break;
339#endif
340#ifdef IPX
341	case AF_IPX:
342		inq = &ipxintrq;
343		isr = NETISR_IPX;
344		break;
345#endif
346#ifdef NS
347	case AF_NS:
348		inq = &nsintrq;
349		isr = NETISR_NS;
350		break;
351#endif
352#ifdef NETATALK
353	case AF_APPLETALK:
354	        inq = &atintrq2;
355		isr = NETISR_ATALK;
356		break;
357#endif
358	default:
359		printf("if_simloop: can't handle af=%d\n", af);
360		m_freem(m);
361		return (EAFNOSUPPORT);
362	}
363	ifp->if_ipackets++;
364	ifp->if_ibytes += m->m_pkthdr.len;
365	(void) IF_HANDOFF(inq, m, NULL);
366	schednetisr(isr);
367	return (0);
368}
369
370/* ARGSUSED */
371static void
372lortrequest(cmd, rt, info)
373	int cmd;
374	struct rtentry *rt;
375	struct rt_addrinfo *info;
376{
377	if (rt) {
378		rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu; /* for ISO */
379		/*
380		 * For optimal performance, the send and receive buffers
381		 * should be at least twice the MTU plus a little more for
382		 * overhead.
383		 */
384		rt->rt_rmx.rmx_recvpipe =
385			rt->rt_rmx.rmx_sendpipe = 3 * LOMTU;
386	}
387}
388
389/*
390 * Process an ioctl request.
391 */
392/* ARGSUSED */
393int
394loioctl(ifp, cmd, data)
395	register struct ifnet *ifp;
396	u_long cmd;
397	caddr_t data;
398{
399	register struct ifaddr *ifa;
400	register struct ifreq *ifr = (struct ifreq *)data;
401	register int error = 0;
402
403	switch (cmd) {
404
405	case SIOCSIFADDR:
406		ifp->if_flags |= IFF_UP | IFF_RUNNING;
407		ifa = (struct ifaddr *)data;
408		ifa->ifa_rtrequest = lortrequest;
409		/*
410		 * Everything else is done at a higher level.
411		 */
412		break;
413
414	case SIOCADDMULTI:
415	case SIOCDELMULTI:
416		if (ifr == 0) {
417			error = EAFNOSUPPORT;		/* XXX */
418			break;
419		}
420		switch (ifr->ifr_addr.sa_family) {
421
422#ifdef INET
423		case AF_INET:
424			break;
425#endif
426#ifdef INET6
427		case AF_INET6:
428			break;
429#endif
430
431		default:
432			error = EAFNOSUPPORT;
433			break;
434		}
435		break;
436
437	case SIOCSIFMTU:
438		ifp->if_mtu = ifr->ifr_mtu;
439		break;
440
441	case SIOCSIFFLAGS:
442		break;
443
444	default:
445		error = EINVAL;
446	}
447	return (error);
448}
449