if_loop.c revision 190787
1139823Simp/*-
21541Srgrimes * Copyright (c) 1982, 1986, 1993
31541Srgrimes *	The Regents of the University of California.  All rights reserved.
41541Srgrimes *
51541Srgrimes * Redistribution and use in source and binary forms, with or without
61541Srgrimes * modification, are permitted provided that the following conditions
71541Srgrimes * are met:
81541Srgrimes * 1. Redistributions of source code must retain the above copyright
91541Srgrimes *    notice, this list of conditions and the following disclaimer.
101541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111541Srgrimes *    notice, this list of conditions and the following disclaimer in the
121541Srgrimes *    documentation and/or other materials provided with the distribution.
131541Srgrimes * 4. Neither the name of the University nor the names of its contributors
141541Srgrimes *    may be used to endorse or promote products derived from this software
151541Srgrimes *    without specific prior written permission.
161541Srgrimes *
171541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
181541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
191541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
201541Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
211541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
221541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
231541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
241541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
251541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
261541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
271541Srgrimes * SUCH DAMAGE.
281541Srgrimes *
2985051Sru *	@(#)if_loop.c	8.2 (Berkeley) 1/9/95
3050477Speter * $FreeBSD: head/sys/net/if_loop.c 190787 2009-04-06 22:29:41Z zec $
311541Srgrimes */
321541Srgrimes
331541Srgrimes/*
341541Srgrimes * Loopback interface driver for protocol testing and timing.
351541Srgrimes */
361541Srgrimes
3732356Seivind#include "opt_atalk.h"
3832350Seivind#include "opt_inet.h"
3954263Sshin#include "opt_inet6.h"
4031742Seivind#include "opt_ipx.h"
41189106Sbz#include "opt_route.h"
42187039Srwatson#include "opt_mac.h"
4331742Seivind
441541Srgrimes#include <sys/param.h>
451541Srgrimes#include <sys/systm.h>
461541Srgrimes#include <sys/kernel.h>
471541Srgrimes#include <sys/mbuf.h>
4871862Speter#include <sys/module.h>
4991648Sbrooks#include <machine/bus.h>
5091648Sbrooks#include <sys/rman.h>
511541Srgrimes#include <sys/socket.h>
5224204Sbde#include <sys/sockio.h>
5371791Speter#include <sys/sysctl.h>
54181803Sbz#include <sys/vimage.h>
551541Srgrimes
561541Srgrimes#include <net/if.h>
57130933Sbrooks#include <net/if_clone.h>
581541Srgrimes#include <net/if_types.h>
591541Srgrimes#include <net/netisr.h>
601541Srgrimes#include <net/route.h>
611541Srgrimes#include <net/bpf.h>
62185571Sbz#include <net/vnet.h>
631541Srgrimes
641541Srgrimes#ifdef	INET
651541Srgrimes#include <netinet/in.h>
661541Srgrimes#include <netinet/in_var.h>
671541Srgrimes#endif
681541Srgrimes
6911819Sjulian#ifdef IPX
7011819Sjulian#include <netipx/ipx.h>
7111819Sjulian#include <netipx/ipx_if.h>
7211819Sjulian#endif
7311819Sjulian
7453541Sshin#ifdef INET6
7553541Sshin#ifndef INET
7653541Sshin#include <netinet/in.h>
7753541Sshin#endif
7853541Sshin#include <netinet6/in6_var.h>
7962587Sitojun#include <netinet/ip6.h>
8053541Sshin#endif
8153541Sshin
8215885Sjulian#ifdef NETATALK
8315885Sjulian#include <netatalk/at.h>
8415885Sjulian#include <netatalk/at_var.h>
8583268Speter#endif
8615885Sjulian
87187039Srwatson#include <security/mac/mac_framework.h>
88187039Srwatson
891622Sdg#ifdef TINY_LOMTU
901541Srgrimes#define	LOMTU	(1024+512)
9153541Sshin#elif defined(LARGE_LOMTU)
9253541Sshin#define LOMTU	131072
931622Sdg#else
946876Sdg#define LOMTU	16384
951622Sdg#endif
961541Srgrimes
97189873Srwatson#define	LO_CSUM_FEATURES	(CSUM_IP | CSUM_TCP | CSUM_UDP | CSUM_SCTP)
98189873Srwatson#define	LO_CSUM_SET		(CSUM_DATA_VALID | CSUM_PSEUDO_HDR | \
99189873Srwatson				    CSUM_IP_CHECKED | CSUM_IP_VALID | \
100189873Srwatson				    CSUM_SCTP_VALID)
101189873Srwatson
10291648Sbrooksint		loioctl(struct ifnet *, u_long, caddr_t);
10391648Sbrooksstatic void	lortrequest(int, struct rtentry *, struct rt_addrinfo *);
10491648Sbrooksint		looutput(struct ifnet *ifp, struct mbuf *m,
10591648Sbrooks		    struct sockaddr *dst, struct rtentry *rt);
106160195Ssamstatic int	lo_clone_create(struct if_clone *, int, caddr_t);
107128209Sbrooksstatic void	lo_clone_destroy(struct ifnet *);
108190787Szecstatic int	vnet_loif_iattach(const void *);
10991648Sbrooks
110185088Szec#ifdef VIMAGE_GLOBALS
111185088Szecstruct ifnet *loif;			/* Used externally */
112185088Szec#endif
11391648Sbrooks
114130933SbrooksIFC_SIMPLE_DECLARE(lo, 1);
11591648Sbrooks
116128209Sbrooksstatic void
117177965Srwatsonlo_clone_destroy(struct ifnet *ifp)
11891648Sbrooks{
119185348Szec#ifdef INVARIANTS
120185348Szec	INIT_VNET_NET(ifp->if_vnet);
121185348Szec#endif
12291648Sbrooks
12397289Sbrooks	/* XXX: destroying lo0 will lead to panics. */
124181803Sbz	KASSERT(V_loif != ifp, ("%s: destroying lo0", __func__));
12591648Sbrooks
12691648Sbrooks	bpfdetach(ifp);
12791648Sbrooks	if_detach(ifp);
128147256Sbrooks	if_free(ifp);
12991648Sbrooks}
13091648Sbrooks
131128209Sbrooksstatic int
132177965Srwatsonlo_clone_create(struct if_clone *ifc, int unit, caddr_t params)
13371791Speter{
134183550Szec	INIT_VNET_NET(curvnet);
135147256Sbrooks	struct ifnet *ifp;
13671791Speter
137180094Sed	ifp = if_alloc(IFT_LOOP);
138180094Sed	if (ifp == NULL)
139147256Sbrooks		return (ENOSPC);
14071791Speter
141147256Sbrooks	if_initname(ifp, ifc->ifc_name, unit);
142147256Sbrooks	ifp->if_mtu = LOMTU;
143147256Sbrooks	ifp->if_flags = IFF_LOOPBACK | IFF_MULTICAST;
144147256Sbrooks	ifp->if_ioctl = loioctl;
145147256Sbrooks	ifp->if_output = looutput;
146147256Sbrooks	ifp->if_snd.ifq_maxlen = ifqmaxlen;
147189871Srwatson	ifp->if_capabilities = ifp->if_capenable = IFCAP_HWCSUM;
148189873Srwatson	ifp->if_hwassist = LO_CSUM_FEATURES;
149147256Sbrooks	if_attach(ifp);
150147611Sdwmalone	bpfattach(ifp, DLT_NULL, sizeof(u_int32_t));
151181803Sbz	if (V_loif == NULL)
152181803Sbz		V_loif = ifp;
15392081Smux
15492081Smux	return (0);
15571791Speter}
15671791Speter
157190787Szecstatic int vnet_loif_iattach(const void *unused __unused)
158190787Szec{
159190787Szec	INIT_VNET_NET(curvnet);
160190787Szec
161190787Szec	V_loif = NULL;
162190787Szec	if_clone_attach(&lo_cloner);
163190787Szec	return (0);
164190787Szec}
165190787Szec
16671791Speterstatic int
167178883Srwatsonloop_modevent(module_t mod, int type, void *data)
168178883Srwatson{
169185348Szec	INIT_VNET_NET(curvnet);
170177965Srwatson
171178883Srwatson	switch (type) {
172178883Srwatson	case MOD_LOAD:
173190787Szec		vnet_loif_iattach(NULL);
174178883Srwatson		break;
175177965Srwatson
176178883Srwatson	case MOD_UNLOAD:
177178883Srwatson		printf("loop module unload - not possible for this module type\n");
178177965Srwatson		return (EINVAL);
179177965Srwatson
180132199Sphk	default:
181177965Srwatson		return (EOPNOTSUPP);
182178883Srwatson	}
183177965Srwatson	return (0);
184178883Srwatson}
1851541Srgrimes
186178883Srwatsonstatic moduledata_t loop_mod = {
187178883Srwatson	"loop",
188178883Srwatson	loop_modevent,
18971862Speter	0
190178883Srwatson};
19171862Speter
192121596SkanDECLARE_MODULE(loop, loop_mod, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY);
19371862Speter
19454263Sshinint
195177965Srwatsonlooutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
196177965Srwatson    struct rtentry *rt)
1971541Srgrimes{
198147611Sdwmalone	u_int32_t af;
199187039Srwatson#ifdef MAC
200187039Srwatson	int error;
201187039Srwatson#endif
202147611Sdwmalone
203113255Sdes	M_ASSERTPKTHDR(m); /* check if we have the packet header */
204113255Sdes
205187039Srwatson#ifdef MAC
206187039Srwatson	error = mac_ifnet_check_transmit(ifp, m);
207187039Srwatson	if (error) {
208187039Srwatson		m_freem(m);
209187039Srwatson		return (error);
210187039Srwatson	}
211187039Srwatson#endif
212187039Srwatson
21336908Sjulian	if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) {
21436908Sjulian		m_freem(m);
21536908Sjulian		return (rt->rt_flags & RTF_BLACKHOLE ? 0 :
21636908Sjulian		        rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH);
21736908Sjulian	}
21853541Sshin
21936908Sjulian	ifp->if_opackets++;
22036908Sjulian	ifp->if_obytes += m->m_pkthdr.len;
221147611Sdwmalone
222147611Sdwmalone	/* BPF writes need to be handled specially. */
223147611Sdwmalone	if (dst->sa_family == AF_UNSPEC) {
224147611Sdwmalone		bcopy(dst->sa_data, &af, sizeof(af));
225147611Sdwmalone		dst->sa_family = af;
226147611Sdwmalone	}
227147611Sdwmalone
22836992Sjulian#if 1	/* XXX */
22936992Sjulian	switch (dst->sa_family) {
23036992Sjulian	case AF_INET:
231189863Srwatson		if (ifp->if_capenable & IFCAP_RXCSUM) {
232189863Srwatson			m->m_pkthdr.csum_data = 0xffff;
233189873Srwatson			m->m_pkthdr.csum_flags = LO_CSUM_SET;
234189863Srwatson		}
235189873Srwatson		m->m_pkthdr.csum_flags &= ~LO_CSUM_FEATURES;
23653541Sshin	case AF_INET6:
23736992Sjulian	case AF_IPX:
23836992Sjulian	case AF_APPLETALK:
23936994Sjulian		break;
24036992Sjulian	default:
24165454Srwatson		printf("looutput: af=%d unexpected\n", dst->sa_family);
24236992Sjulian		m_freem(m);
24336992Sjulian		return (EAFNOSUPPORT);
24436992Sjulian	}
24536992Sjulian#endif
246177965Srwatson	return (if_simloop(ifp, m, dst->sa_family, 0));
24736908Sjulian}
24836908Sjulian
24936908Sjulian/*
25036908Sjulian * if_simloop()
25136908Sjulian *
25236908Sjulian * This function is to support software emulation of hardware loopback,
25336908Sjulian * i.e., for interfaces with the IFF_SIMPLEX attribute. Since they can't
25436908Sjulian * hear their own broadcasts, we create a copy of the packet that we
25536908Sjulian * would normally receive via a hardware loopback.
25636908Sjulian *
25736908Sjulian * This function expects the packet to include the media header of length hlen.
25836908Sjulian */
25936908Sjulianint
260177965Srwatsonif_simloop(struct ifnet *ifp, struct mbuf *m, int af, int hlen)
26136908Sjulian{
262183550Szec	INIT_VNET_NET(ifp->if_vnet);
26369152Sjlemon	int isr;
2641541Srgrimes
265113255Sdes	M_ASSERTPKTHDR(m);
266121645Ssam	m_tag_delete_nonpersistent(m);
26736908Sjulian	m->m_pkthdr.rcvif = ifp;
26860889Sarchie
269187039Srwatson#ifdef MAC
270187039Srwatson	mac_ifnet_create_mbuf(ifp, m);
271187039Srwatson#endif
272187039Srwatson
273162539Ssuz	/*
274162539Ssuz	 * Let BPF see incoming packet in the following manner:
275178883Srwatson	 *  - Emulated packet loopback for a simplex interface
276162539Ssuz	 *    (net/if_ethersubr.c)
277162539Ssuz	 *	-> passes it to ifp's BPF
278162539Ssuz	 *  - IPv4/v6 multicast packet loopback (netinet(6)/ip(6)_output.c)
279162539Ssuz	 *	-> not passes it to any BPF
280162539Ssuz	 *  - Normal packet loopback from myself to myself (net/if_loop.c)
281162539Ssuz	 *	-> passes to lo0's BPF (even in case of IPv6, where ifp!=lo0)
282162539Ssuz	 */
283162539Ssuz	if (hlen > 0) {
284162539Ssuz		if (bpf_peers_present(ifp->if_bpf)) {
285123922Ssam			bpf_mtap(ifp->if_bpf, m);
286162539Ssuz		}
287162539Ssuz	} else {
288181803Sbz		if (bpf_peers_present(V_loif->if_bpf)) {
289181803Sbz			if ((m->m_flags & M_MCAST) == 0 || V_loif == ifp) {
290162539Ssuz				/* XXX beware sizeof(af) != 4 */
291181118Srwatson				u_int32_t af1 = af;
292162539Ssuz
293162539Ssuz				/*
294162539Ssuz				 * We need to prepend the address family.
295162539Ssuz				 */
296181803Sbz				bpf_mtap2(V_loif->if_bpf, &af1, sizeof(af1), m);
297162539Ssuz			}
298162539Ssuz		}
2991541Srgrimes	}
3001541Srgrimes
30136908Sjulian	/* Strip away media header */
30237600Sdfr	if (hlen > 0) {
30360952Sgallatin		m_adj(m, hlen);
304166577Scognet#ifndef __NO_STRICT_ALIGNMENT
305158471Sjhb		/*
306158471Sjhb		 * Some archs do not like unaligned data, so
307158471Sjhb		 * we move data down in the first mbuf.
308158471Sjhb		 */
30960952Sgallatin		if (mtod(m, vm_offset_t) & 3) {
31061181Smjacob			KASSERT(hlen >= 3, ("if_simloop: hlen too small"));
311178883Srwatson			bcopy(m->m_data,
312178883Srwatson			    (char *)(mtod(m, vm_offset_t)
31360952Sgallatin				- (mtod(m, vm_offset_t) & 3)),
31460952Sgallatin			    m->m_len);
315132780Skan			m->m_data -= (mtod(m,vm_offset_t) & 3);
31660952Sgallatin		}
31737600Sdfr#endif
31837600Sdfr	}
31936908Sjulian
32060889Sarchie	/* Deliver to upper layer protocol */
32160889Sarchie	switch (af) {
3221541Srgrimes#ifdef INET
3231541Srgrimes	case AF_INET:
3241541Srgrimes		isr = NETISR_IP;
3251541Srgrimes		break;
3261541Srgrimes#endif
32753541Sshin#ifdef INET6
32853541Sshin	case AF_INET6:
32953541Sshin		m->m_flags |= M_LOOP;
33053541Sshin		isr = NETISR_IPV6;
33153541Sshin		break;
33253541Sshin#endif
33311819Sjulian#ifdef IPX
33411819Sjulian	case AF_IPX:
33511819Sjulian		isr = NETISR_IPX;
33611819Sjulian		break;
33711819Sjulian#endif
33815885Sjulian#ifdef NETATALK
33915885Sjulian	case AF_APPLETALK:
340111888Sjlemon		isr = NETISR_ATALK2;
34115885Sjulian		break;
34283268Speter#endif
3431541Srgrimes	default:
34460889Sarchie		printf("if_simloop: can't handle af=%d\n", af);
3451541Srgrimes		m_freem(m);
3461541Srgrimes		return (EAFNOSUPPORT);
3471541Srgrimes	}
3481541Srgrimes	ifp->if_ipackets++;
3491541Srgrimes	ifp->if_ibytes += m->m_pkthdr.len;
350134391Sandre	netisr_queue(isr, m);	/* mbuf is free'd on failure. */
3511541Srgrimes	return (0);
3521541Srgrimes}
3531541Srgrimes
3541541Srgrimes/* ARGSUSED */
35512706Sphkstatic void
356177965Srwatsonlortrequest(int cmd, struct rtentry *rt, struct rt_addrinfo *info)
3571541Srgrimes{
358177965Srwatson
359120727Ssam	RT_LOCK_ASSERT(rt);
360142352Ssam	rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu;
3611541Srgrimes}
3621541Srgrimes
3631541Srgrimes/*
3641541Srgrimes * Process an ioctl request.
3651541Srgrimes */
3661541Srgrimes/* ARGSUSED */
36754263Sshinint
368177965Srwatsonloioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
3691541Srgrimes{
370177965Srwatson	struct ifaddr *ifa;
371177965Srwatson	struct ifreq *ifr = (struct ifreq *)data;
372189863Srwatson	int error = 0, mask;
3731541Srgrimes
3741541Srgrimes	switch (cmd) {
3751541Srgrimes	case SIOCSIFADDR:
376148887Srwatson		ifp->if_flags |= IFF_UP;
377148887Srwatson		ifp->if_drv_flags |= IFF_DRV_RUNNING;
3781541Srgrimes		ifa = (struct ifaddr *)data;
37913928Swollman		ifa->ifa_rtrequest = lortrequest;
3801541Srgrimes		/*
3811541Srgrimes		 * Everything else is done at a higher level.
3821541Srgrimes		 */
3831541Srgrimes		break;
3841541Srgrimes
3851541Srgrimes	case SIOCADDMULTI:
3861541Srgrimes	case SIOCDELMULTI:
3871541Srgrimes		if (ifr == 0) {
3881541Srgrimes			error = EAFNOSUPPORT;		/* XXX */
3891541Srgrimes			break;
3901541Srgrimes		}
3911541Srgrimes		switch (ifr->ifr_addr.sa_family) {
3921541Srgrimes
3931541Srgrimes#ifdef INET
3941541Srgrimes		case AF_INET:
3951541Srgrimes			break;
3961541Srgrimes#endif
39753541Sshin#ifdef INET6
39853541Sshin		case AF_INET6:
39953541Sshin			break;
40053541Sshin#endif
4011541Srgrimes
4021541Srgrimes		default:
4031541Srgrimes			error = EAFNOSUPPORT;
4041541Srgrimes			break;
4051541Srgrimes		}
4061541Srgrimes		break;
4071541Srgrimes
4081944Sdg	case SIOCSIFMTU:
40949468Sbrian		ifp->if_mtu = ifr->ifr_mtu;
4101944Sdg		break;
4111944Sdg
41235563Sphk	case SIOCSIFFLAGS:
41335563Sphk		break;
41435563Sphk
415189863Srwatson	case SIOCSIFCAP:
416189863Srwatson		mask = ifp->if_capenable ^ ifr->ifr_reqcap;
417189863Srwatson		if ((mask & IFCAP_RXCSUM) != 0)
418189863Srwatson			ifp->if_capenable ^= IFCAP_RXCSUM;
419189863Srwatson		if ((mask & IFCAP_TXCSUM) != 0)
420189863Srwatson			ifp->if_capenable ^= IFCAP_TXCSUM;
421189863Srwatson		if (ifp->if_capenable & IFCAP_TXCSUM)
422189873Srwatson			ifp->if_hwassist = LO_CSUM_FEATURES;
423189863Srwatson		else
424189863Srwatson			ifp->if_hwassist = 0;
425189863Srwatson		break;
426189863Srwatson
4271541Srgrimes	default:
4281541Srgrimes		error = EINVAL;
4291541Srgrimes	}
4301541Srgrimes	return (error);
4311541Srgrimes}
432