xref: /csrg-svn/sys/net/if_loop.c (revision 52947)
123174Smckusick /*
229071Skarels  * Copyright (c) 1982, 1986 Regents of the University of California.
333183Sbostic  * All rights reserved.
423174Smckusick  *
544464Sbostic  * %sccs.include.redist.c%
633183Sbostic  *
7*52947Storek  *	@(#)if_loop.c	7.16 (Berkeley) 03/15/92
823174Smckusick  */
95122Swnj 
105122Swnj /*
115122Swnj  * Loopback interface driver for protocol testing and timing.
125122Swnj  */
135122Swnj 
1417058Sbloom #include "param.h"
1517058Sbloom #include "systm.h"
1617058Sbloom #include "mbuf.h"
1717058Sbloom #include "socket.h"
1817058Sbloom #include "errno.h"
1917058Sbloom #include "ioctl.h"
2052270Storek #include "machine/cpu.h"
2110907Ssam 
2252270Storek #include "if.h"
2352270Storek #include "if_types.h"
2452270Storek #include "netisr.h"
2552270Storek #include "route.h"
2610907Ssam 
2724771Skarels #ifdef	INET
2852271Ssklower #include "netinet/in.h"
2952271Ssklower #include "netinet/in_systm.h"
3052271Ssklower #include "netinet/in_var.h"
3152271Ssklower #include "netinet/ip.h"
3224771Skarels #endif
335122Swnj 
3418815Ssklower #ifdef NS
3552271Ssklower #include "netns/ns.h"
3652271Ssklower #include "netns/ns_if.h"
3718815Ssklower #endif
3818815Ssklower 
3937472Ssklower #ifdef ISO
4052271Ssklower #include "netiso/iso.h"
4152271Ssklower #include "netiso/iso_var.h"
4237472Ssklower #endif
4337472Ssklower 
445207Swnj #define	LOMTU	(1024+512)
455122Swnj 
465122Swnj struct	ifnet loif;
4713066Ssam int	looutput(), loioctl();
485122Swnj 
495122Swnj loattach()
505122Swnj {
515122Swnj 	register struct ifnet *ifp = &loif;
525122Swnj 
535172Swnj 	ifp->if_name = "lo";
545122Swnj 	ifp->if_mtu = LOMTU;
5526091Skarels 	ifp->if_flags = IFF_LOOPBACK;
5613066Ssam 	ifp->if_ioctl = loioctl;
575122Swnj 	ifp->if_output = looutput;
5837472Ssklower 	ifp->if_type = IFT_LOOP;
5937472Ssklower 	ifp->if_hdrlen = 0;
6037472Ssklower 	ifp->if_addrlen = 0;
615161Swnj 	if_attach(ifp);
625122Swnj }
635122Swnj 
6445198Ssklower looutput(ifp, m, dst, rt)
655122Swnj 	struct ifnet *ifp;
6635795Skarels 	register struct mbuf *m;
676337Ssam 	struct sockaddr *dst;
6845198Ssklower 	register struct rtentry *rt;
695122Swnj {
7045523Ssklower 	int s, isr;
7145523Ssklower 	register struct ifqueue *ifq = 0;
725122Swnj 
7335795Skarels 	if ((m->m_flags & M_PKTHDR) == 0)
7435795Skarels 		panic("looutput no HDR");
7535795Skarels 	m->m_pkthdr.rcvif = ifp;
7635795Skarels 
7745198Ssklower 	if (rt && rt->rt_flags & RTF_REJECT) {
7845198Ssklower 		m_freem(m);
7945198Ssklower 		return (rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH);
8045198Ssklower 	}
815172Swnj 	ifp->if_opackets++;
8239187Ssklower 	ifp->if_obytes += m->m_pkthdr.len;
836337Ssam 	switch (dst->sa_family) {
845122Swnj 
855122Swnj #ifdef INET
866337Ssam 	case AF_INET:
876209Swnj 		ifq = &ipintrq;
8845523Ssklower 		isr = NETISR_IP;
895122Swnj 		break;
905122Swnj #endif
9118815Ssklower #ifdef NS
9218815Ssklower 	case AF_NS:
9318815Ssklower 		ifq = &nsintrq;
9445523Ssklower 		isr = NETISR_NS;
9518815Ssklower 		break;
9618815Ssklower #endif
9737472Ssklower #ifdef ISO
9837472Ssklower 	case AF_ISO:
9937472Ssklower 		ifq = &clnlintrq;
10045523Ssklower 		isr = NETISR_ISO;
10137472Ssklower 		break;
10237472Ssklower #endif
1035122Swnj 	default:
1046337Ssam 		printf("lo%d: can't handle af%d\n", ifp->if_unit,
1056337Ssam 			dst->sa_family);
10635795Skarels 		m_freem(m);
1076544Sfeldman 		return (EAFNOSUPPORT);
1085122Swnj 	}
10948727Ssklower 	s = splimp();
11045523Ssklower 	if (IF_QFULL(ifq)) {
11145523Ssklower 		IF_DROP(ifq);
11245523Ssklower 		m_freem(m);
11345523Ssklower 		splx(s);
11445523Ssklower 		return (ENOBUFS);
11545523Ssklower 	}
11645523Ssklower 	IF_ENQUEUE(ifq, m);
11745523Ssklower 	schednetisr(isr);
1185172Swnj 	ifp->if_ipackets++;
11939187Ssklower 	ifp->if_ibytes += m->m_pkthdr.len;
1205122Swnj 	splx(s);
1216544Sfeldman 	return (0);
1225122Swnj }
12313066Ssam 
12448727Ssklower /* ARGSUSED */
12548727Ssklower lortrequest(cmd, rt, sa)
126*52947Storek 	int cmd;
127*52947Storek 	struct rtentry *rt;
128*52947Storek 	struct sockaddr *sa;
12948727Ssklower {
130*52947Storek 
13148727Ssklower 	if (rt)
13248727Ssklower 		rt->rt_rmx.rmx_mtu = LOMTU;
13348727Ssklower }
13448727Ssklower 
13513066Ssam /*
13613066Ssam  * Process an ioctl request.
13713066Ssam  */
13818370Skarels /* ARGSUSED */
13913066Ssam loioctl(ifp, cmd, data)
14013066Ssam 	register struct ifnet *ifp;
14113066Ssam 	int cmd;
14213066Ssam 	caddr_t data;
14313066Ssam {
14448727Ssklower 	register struct ifaddr *ifa;
14518370Skarels 	int error = 0;
14613066Ssam 
14713066Ssam 	switch (cmd) {
14813066Ssam 
14913066Ssam 	case SIOCSIFADDR:
15018370Skarels 		ifp->if_flags |= IFF_UP;
15148727Ssklower 		ifa = (struct ifaddr *)data;
15248727Ssklower 		if (ifa != 0 && ifa->ifa_addr->sa_family == AF_ISO)
15348727Ssklower 			ifa->ifa_rtrequest = lortrequest;
15418370Skarels 		/*
15518370Skarels 		 * Everything else is done at a higher level.
15618370Skarels 		 */
15713066Ssam 		break;
15813066Ssam 
15913066Ssam 	default:
16013066Ssam 		error = EINVAL;
16113066Ssam 	}
16213066Ssam 	return (error);
16313066Ssam }
164