if_loop.c revision 131177
10Sstevel@tonic-gate/*
20Sstevel@tonic-gate * Copyright (c) 1982, 1986, 1993
30Sstevel@tonic-gate *	The Regents of the University of California.  All rights reserved.
40Sstevel@tonic-gate *
50Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without
60Sstevel@tonic-gate * modification, are permitted provided that the following conditions
70Sstevel@tonic-gate * are met:
80Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright
90Sstevel@tonic-gate *    notice, this list of conditions and the following disclaimer.
100Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright
110Sstevel@tonic-gate *    notice, this list of conditions and the following disclaimer in the
120Sstevel@tonic-gate *    documentation and/or other materials provided with the distribution.
130Sstevel@tonic-gate * 4. Neither the name of the University nor the names of its contributors
140Sstevel@tonic-gate *    may be used to endorse or promote products derived from this software
150Sstevel@tonic-gate *    without specific prior written permission.
160Sstevel@tonic-gate *
170Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
180Sstevel@tonic-gate * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
190Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
200Sstevel@tonic-gate * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
210Sstevel@tonic-gate * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
220Sstevel@tonic-gate * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
230Sstevel@tonic-gate * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
240Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
250Sstevel@tonic-gate * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
260Sstevel@tonic-gate * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
270Sstevel@tonic-gate * SUCH DAMAGE.
280Sstevel@tonic-gate *
290Sstevel@tonic-gate *	@(#)if_loop.c	8.2 (Berkeley) 1/9/95
300Sstevel@tonic-gate * $FreeBSD: head/sys/net/if_loop.c 131177 2004-06-27 09:03:22Z pjd $
310Sstevel@tonic-gate */
320Sstevel@tonic-gate
330Sstevel@tonic-gate/*
340Sstevel@tonic-gate * Loopback interface driver for protocol testing and timing.
350Sstevel@tonic-gate */
360Sstevel@tonic-gate
370Sstevel@tonic-gate#include "opt_atalk.h"
380Sstevel@tonic-gate#include "opt_inet.h"
390Sstevel@tonic-gate#include "opt_inet6.h"
400Sstevel@tonic-gate#include "opt_ipx.h"
410Sstevel@tonic-gate
420Sstevel@tonic-gate#include <sys/param.h>
430Sstevel@tonic-gate#include <sys/systm.h>
440Sstevel@tonic-gate#include <sys/kernel.h>
450Sstevel@tonic-gate#include <sys/mac.h>
460Sstevel@tonic-gate#include <sys/malloc.h>
470Sstevel@tonic-gate#include <sys/mbuf.h>
480Sstevel@tonic-gate#include <sys/module.h>
490Sstevel@tonic-gate#include <machine/bus.h>
500Sstevel@tonic-gate#include <sys/rman.h>
510Sstevel@tonic-gate#include <sys/socket.h>
520Sstevel@tonic-gate#include <sys/sockio.h>
530Sstevel@tonic-gate#include <sys/sysctl.h>
540Sstevel@tonic-gate
550Sstevel@tonic-gate#include <net/if.h>
560Sstevel@tonic-gate#include <net/if_clone.h>
570Sstevel@tonic-gate#include <net/if_types.h>
580Sstevel@tonic-gate#include <net/netisr.h>
590Sstevel@tonic-gate#include <net/route.h>
600Sstevel@tonic-gate#include <net/bpf.h>
610Sstevel@tonic-gate#include <net/bpfdesc.h>
620Sstevel@tonic-gate
630Sstevel@tonic-gate#ifdef	INET
640Sstevel@tonic-gate#include <netinet/in.h>
650Sstevel@tonic-gate#include <netinet/in_var.h>
660Sstevel@tonic-gate#endif
670Sstevel@tonic-gate
680Sstevel@tonic-gate#ifdef IPX
690Sstevel@tonic-gate#include <netipx/ipx.h>
700Sstevel@tonic-gate#include <netipx/ipx_if.h>
710Sstevel@tonic-gate#endif
720Sstevel@tonic-gate
730Sstevel@tonic-gate#ifdef INET6
740Sstevel@tonic-gate#ifndef INET
750Sstevel@tonic-gate#include <netinet/in.h>
760Sstevel@tonic-gate#endif
770Sstevel@tonic-gate#include <netinet6/in6_var.h>
780Sstevel@tonic-gate#include <netinet/ip6.h>
790Sstevel@tonic-gate#endif
800Sstevel@tonic-gate
810Sstevel@tonic-gate#ifdef NETATALK
820Sstevel@tonic-gate#include <netatalk/at.h>
830Sstevel@tonic-gate#include <netatalk/at_var.h>
840Sstevel@tonic-gate#endif
850Sstevel@tonic-gate
860Sstevel@tonic-gate#ifdef TINY_LOMTU
870Sstevel@tonic-gate#define	LOMTU	(1024+512)
880Sstevel@tonic-gate#elif defined(LARGE_LOMTU)
890Sstevel@tonic-gate#define LOMTU	131072
900Sstevel@tonic-gate#else
910Sstevel@tonic-gate#define LOMTU	16384
920Sstevel@tonic-gate#endif
930Sstevel@tonic-gate
940Sstevel@tonic-gate#define LONAME	"lo"
950Sstevel@tonic-gate
960Sstevel@tonic-gatestruct lo_softc {
970Sstevel@tonic-gate	struct	ifnet sc_if;		/* network-visible interface */
980Sstevel@tonic-gate	LIST_ENTRY(lo_softc) sc_next;
990Sstevel@tonic-gate};
1000Sstevel@tonic-gate
1010Sstevel@tonic-gateint		loioctl(struct ifnet *, u_long, caddr_t);
1020Sstevel@tonic-gatestatic void	lortrequest(int, struct rtentry *, struct rt_addrinfo *);
1030Sstevel@tonic-gateint		looutput(struct ifnet *ifp, struct mbuf *m,
1040Sstevel@tonic-gate		    struct sockaddr *dst, struct rtentry *rt);
1050Sstevel@tonic-gatestatic int	lo_clone_create(struct if_clone *, int);
1060Sstevel@tonic-gatestatic void	lo_clone_destroy(struct ifnet *);
1070Sstevel@tonic-gate
1080Sstevel@tonic-gatestruct ifnet *loif = NULL;			/* Used externally */
1090Sstevel@tonic-gate
1100Sstevel@tonic-gatestatic MALLOC_DEFINE(M_LO, LONAME, "Loopback Interface");
1110Sstevel@tonic-gate
1120Sstevel@tonic-gatestatic struct mtx lo_mtx;
1130Sstevel@tonic-gatestatic LIST_HEAD(lo_list, lo_softc) lo_list;
1140Sstevel@tonic-gate
1150Sstevel@tonic-gateIFC_SIMPLE_DECLARE(lo, 1);
1160Sstevel@tonic-gate
1170Sstevel@tonic-gatestatic void
1180Sstevel@tonic-gatelo_clone_destroy(ifp)
1190Sstevel@tonic-gate	struct ifnet *ifp;
1200Sstevel@tonic-gate{
1210Sstevel@tonic-gate	struct lo_softc *sc;
1220Sstevel@tonic-gate
1230Sstevel@tonic-gate	sc = ifp->if_softc;
1240Sstevel@tonic-gate
1250Sstevel@tonic-gate	/* XXX: destroying lo0 will lead to panics. */
1260Sstevel@tonic-gate	KASSERT(loif != ifp, ("%s: destroying lo0", __func__));
1270Sstevel@tonic-gate
1280Sstevel@tonic-gate	mtx_lock(&lo_mtx);
1290Sstevel@tonic-gate	LIST_REMOVE(sc, sc_next);
1300Sstevel@tonic-gate	mtx_unlock(&lo_mtx);
1310Sstevel@tonic-gate	bpfdetach(ifp);
1320Sstevel@tonic-gate	if_detach(ifp);
1330Sstevel@tonic-gate	free(sc, M_LO);
1340Sstevel@tonic-gate}
1350Sstevel@tonic-gate
1360Sstevel@tonic-gatestatic int
1370Sstevel@tonic-gatelo_clone_create(ifc, unit)
1380Sstevel@tonic-gate	struct if_clone *ifc;
1390Sstevel@tonic-gate	int unit;
1400Sstevel@tonic-gate{
1410Sstevel@tonic-gate	struct lo_softc *sc;
1420Sstevel@tonic-gate
1430Sstevel@tonic-gate	MALLOC(sc, struct lo_softc *, sizeof(*sc), M_LO, M_WAITOK | M_ZERO);
1440Sstevel@tonic-gate
1450Sstevel@tonic-gate	if_initname(&sc->sc_if, ifc->ifc_name, unit);
1460Sstevel@tonic-gate	sc->sc_if.if_mtu = LOMTU;
1470Sstevel@tonic-gate	sc->sc_if.if_flags = IFF_LOOPBACK | IFF_MULTICAST;
1480Sstevel@tonic-gate	sc->sc_if.if_ioctl = loioctl;
1490Sstevel@tonic-gate	sc->sc_if.if_output = looutput;
1500Sstevel@tonic-gate	sc->sc_if.if_type = IFT_LOOP;
1510Sstevel@tonic-gate	sc->sc_if.if_snd.ifq_maxlen = ifqmaxlen;
1520Sstevel@tonic-gate	sc->sc_if.if_softc = sc;
1530Sstevel@tonic-gate	if_attach(&sc->sc_if);
1540Sstevel@tonic-gate	bpfattach(&sc->sc_if, DLT_NULL, sizeof(u_int));
1550Sstevel@tonic-gate	mtx_lock(&lo_mtx);
156	LIST_INSERT_HEAD(&lo_list, sc, sc_next);
157	mtx_unlock(&lo_mtx);
158	if (loif == NULL)
159		loif = &sc->sc_if;
160
161	return (0);
162}
163
164static int
165loop_modevent(module_t mod, int type, void *data)
166{
167	switch (type) {
168	case MOD_LOAD:
169		mtx_init(&lo_mtx, "lo_mtx", NULL, MTX_DEF);
170		LIST_INIT(&lo_list);
171		if_clone_attach(&lo_cloner);
172		break;
173	case MOD_UNLOAD:
174		printf("loop module unload - not possible for this module type\n");
175		return EINVAL;
176	}
177	return 0;
178}
179
180static moduledata_t loop_mod = {
181	"loop",
182	loop_modevent,
183	0
184};
185
186DECLARE_MODULE(loop, loop_mod, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY);
187
188int
189looutput(ifp, m, dst, rt)
190	struct ifnet *ifp;
191	register struct mbuf *m;
192	struct sockaddr *dst;
193	register struct rtentry *rt;
194{
195	M_ASSERTPKTHDR(m); /* check if we have the packet header */
196
197	if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) {
198		m_freem(m);
199		return (rt->rt_flags & RTF_BLACKHOLE ? 0 :
200		        rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH);
201	}
202
203	ifp->if_opackets++;
204	ifp->if_obytes += m->m_pkthdr.len;
205#if 1	/* XXX */
206	switch (dst->sa_family) {
207	case AF_INET:
208	case AF_INET6:
209	case AF_IPX:
210	case AF_APPLETALK:
211		break;
212	default:
213		printf("looutput: af=%d unexpected\n", dst->sa_family);
214		m_freem(m);
215		return (EAFNOSUPPORT);
216	}
217#endif
218	return(if_simloop(ifp, m, dst->sa_family, 0));
219}
220
221/*
222 * if_simloop()
223 *
224 * This function is to support software emulation of hardware loopback,
225 * i.e., for interfaces with the IFF_SIMPLEX attribute. Since they can't
226 * hear their own broadcasts, we create a copy of the packet that we
227 * would normally receive via a hardware loopback.
228 *
229 * This function expects the packet to include the media header of length hlen.
230 */
231
232int
233if_simloop(ifp, m, af, hlen)
234	struct ifnet *ifp;
235	struct mbuf *m;
236	int af;
237	int hlen;
238{
239	int isr;
240
241	M_ASSERTPKTHDR(m);
242	m_tag_delete_nonpersistent(m);
243	m->m_pkthdr.rcvif = ifp;
244
245	/* BPF write needs to be handled specially */
246	if (af == AF_UNSPEC) {
247		KASSERT(m->m_len >= sizeof(int), ("if_simloop: m_len"));
248		af = *(mtod(m, int *));
249		m->m_len -= sizeof(int);
250		m->m_pkthdr.len -= sizeof(int);
251		m->m_data += sizeof(int);
252	}
253
254	/* Let BPF see incoming packet */
255	if (ifp->if_bpf) {
256		if (ifp->if_bpf->bif_dlt == DLT_NULL) {
257			u_int32_t af1 = af;	/* XXX beware sizeof(af) != 4 */
258			/*
259			 * We need to prepend the address family.
260			 */
261			bpf_mtap2(ifp->if_bpf, &af1, sizeof(af1), m);
262		} else
263			bpf_mtap(ifp->if_bpf, m);
264	}
265
266	/* Strip away media header */
267	if (hlen > 0) {
268		m_adj(m, hlen);
269#if defined(__alpha__) || defined(__ia64__) || defined(__sparc64__)
270		/* The alpha doesn't like unaligned data.
271		 * We move data down in the first mbuf */
272		if (mtod(m, vm_offset_t) & 3) {
273			KASSERT(hlen >= 3, ("if_simloop: hlen too small"));
274			bcopy(m->m_data,
275			    (char *)(mtod(m, vm_offset_t)
276				- (mtod(m, vm_offset_t) & 3)),
277			    m->m_len);
278			mtod(m,vm_offset_t) -= (mtod(m, vm_offset_t) & 3);
279		}
280#endif
281	}
282
283	/* Deliver to upper layer protocol */
284	switch (af) {
285#ifdef INET
286	case AF_INET:
287		isr = NETISR_IP;
288		break;
289#endif
290#ifdef INET6
291	case AF_INET6:
292		m->m_flags |= M_LOOP;
293		isr = NETISR_IPV6;
294		break;
295#endif
296#ifdef IPX
297	case AF_IPX:
298		isr = NETISR_IPX;
299		break;
300#endif
301#ifdef NETATALK
302	case AF_APPLETALK:
303		isr = NETISR_ATALK2;
304		break;
305#endif
306	default:
307		printf("if_simloop: can't handle af=%d\n", af);
308		m_freem(m);
309		return (EAFNOSUPPORT);
310	}
311	ifp->if_ipackets++;
312	ifp->if_ibytes += m->m_pkthdr.len;
313	netisr_queue(isr, m);
314	return (0);
315}
316
317/* ARGSUSED */
318static void
319lortrequest(cmd, rt, info)
320	int cmd;
321	struct rtentry *rt;
322	struct rt_addrinfo *info;
323{
324	RT_LOCK_ASSERT(rt);
325	if (rt)
326		rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu;
327}
328
329/*
330 * Process an ioctl request.
331 */
332/* ARGSUSED */
333int
334loioctl(ifp, cmd, data)
335	register struct ifnet *ifp;
336	u_long cmd;
337	caddr_t data;
338{
339	register struct ifaddr *ifa;
340	register struct ifreq *ifr = (struct ifreq *)data;
341	register int error = 0;
342
343	switch (cmd) {
344
345	case SIOCSIFADDR:
346		ifp->if_flags |= IFF_UP | IFF_RUNNING;
347		ifa = (struct ifaddr *)data;
348		ifa->ifa_rtrequest = lortrequest;
349		/*
350		 * Everything else is done at a higher level.
351		 */
352		break;
353
354	case SIOCADDMULTI:
355	case SIOCDELMULTI:
356		if (ifr == 0) {
357			error = EAFNOSUPPORT;		/* XXX */
358			break;
359		}
360		switch (ifr->ifr_addr.sa_family) {
361
362#ifdef INET
363		case AF_INET:
364			break;
365#endif
366#ifdef INET6
367		case AF_INET6:
368			break;
369#endif
370
371		default:
372			error = EAFNOSUPPORT;
373			break;
374		}
375		break;
376
377	case SIOCSIFMTU:
378		ifp->if_mtu = ifr->ifr_mtu;
379		break;
380
381	case SIOCSIFFLAGS:
382		break;
383
384	default:
385		error = EINVAL;
386	}
387	return (error);
388}
389