xref: /csrg-svn/sys/net/if_loop.c (revision 48727)
123174Smckusick /*
229071Skarels  * Copyright (c) 1982, 1986 Regents of the University of California.
333183Sbostic  * All rights reserved.
423174Smckusick  *
544464Sbostic  * %sccs.include.redist.c%
633183Sbostic  *
7*48727Ssklower  *	@(#)if_loop.c	7.13 (Berkeley) 04/26/91
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"
2010907Ssam 
2110907Ssam #include "../net/if.h"
2238988Skarels #include "../net/if_types.h"
2310907Ssam #include "../net/netisr.h"
2410907Ssam #include "../net/route.h"
2510907Ssam 
2637500Smckusick #include "machine/mtpr.h"
2729922Skarels 
2824771Skarels #ifdef	INET
2924771Skarels #include "../netinet/in.h"
3024771Skarels #include "../netinet/in_systm.h"
3129071Skarels #include "../netinet/in_var.h"
3224771Skarels #include "../netinet/ip.h"
3324771Skarels #endif
345122Swnj 
3518815Ssklower #ifdef NS
3618815Ssklower #include "../netns/ns.h"
3718815Ssklower #include "../netns/ns_if.h"
3818815Ssklower #endif
3918815Ssklower 
4037472Ssklower #ifdef ISO
4137472Ssklower #include "../netiso/iso.h"
4237472Ssklower #include "../netiso/iso_var.h"
4337472Ssklower #endif
4437472Ssklower 
455207Swnj #define	LOMTU	(1024+512)
465122Swnj 
475122Swnj struct	ifnet loif;
4813066Ssam int	looutput(), loioctl();
495122Swnj 
505122Swnj loattach()
515122Swnj {
525122Swnj 	register struct ifnet *ifp = &loif;
535122Swnj 
545172Swnj 	ifp->if_name = "lo";
555122Swnj 	ifp->if_mtu = LOMTU;
5626091Skarels 	ifp->if_flags = IFF_LOOPBACK;
5713066Ssam 	ifp->if_ioctl = loioctl;
585122Swnj 	ifp->if_output = looutput;
5937472Ssklower 	ifp->if_type = IFT_LOOP;
6037472Ssklower 	ifp->if_hdrlen = 0;
6137472Ssklower 	ifp->if_addrlen = 0;
625161Swnj 	if_attach(ifp);
635122Swnj }
645122Swnj 
6545198Ssklower looutput(ifp, m, dst, rt)
665122Swnj 	struct ifnet *ifp;
6735795Skarels 	register struct mbuf *m;
686337Ssam 	struct sockaddr *dst;
6945198Ssklower 	register struct rtentry *rt;
705122Swnj {
7145523Ssklower 	int s, isr;
7245523Ssklower 	register struct ifqueue *ifq = 0;
735122Swnj 
7435795Skarels 	if ((m->m_flags & M_PKTHDR) == 0)
7535795Skarels 		panic("looutput no HDR");
7635795Skarels 	m->m_pkthdr.rcvif = ifp;
7735795Skarels 
7845198Ssklower 	if (rt && rt->rt_flags & RTF_REJECT) {
7945198Ssklower 		m_freem(m);
8045198Ssklower 		return (rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH);
8145198Ssklower 	}
825172Swnj 	ifp->if_opackets++;
8339187Ssklower 	ifp->if_obytes += m->m_pkthdr.len;
846337Ssam 	switch (dst->sa_family) {
855122Swnj 
865122Swnj #ifdef INET
876337Ssam 	case AF_INET:
886209Swnj 		ifq = &ipintrq;
8945523Ssklower 		isr = NETISR_IP;
905122Swnj 		break;
915122Swnj #endif
9218815Ssklower #ifdef NS
9318815Ssklower 	case AF_NS:
9418815Ssklower 		ifq = &nsintrq;
9545523Ssklower 		isr = NETISR_NS;
9618815Ssklower 		break;
9718815Ssklower #endif
9837472Ssklower #ifdef ISO
9937472Ssklower 	case AF_ISO:
10037472Ssklower 		ifq = &clnlintrq;
10145523Ssklower 		isr = NETISR_ISO;
10237472Ssklower 		break;
10337472Ssklower #endif
1045122Swnj 	default:
1056337Ssam 		printf("lo%d: can't handle af%d\n", ifp->if_unit,
1066337Ssam 			dst->sa_family);
10735795Skarels 		m_freem(m);
1086544Sfeldman 		return (EAFNOSUPPORT);
1095122Swnj 	}
110*48727Ssklower 	s = splimp();
11145523Ssklower 	if (IF_QFULL(ifq)) {
11245523Ssklower 		IF_DROP(ifq);
11345523Ssklower 		m_freem(m);
11445523Ssklower 		splx(s);
11545523Ssklower 		return (ENOBUFS);
11645523Ssklower 	}
11745523Ssklower 	IF_ENQUEUE(ifq, m);
11845523Ssklower 	schednetisr(isr);
1195172Swnj 	ifp->if_ipackets++;
12039187Ssklower 	ifp->if_ibytes += m->m_pkthdr.len;
1215122Swnj 	splx(s);
1226544Sfeldman 	return (0);
1235122Swnj }
12413066Ssam 
125*48727Ssklower /* ARGSUSED */
126*48727Ssklower lortrequest(cmd, rt, sa)
127*48727Ssklower struct rtentry *rt;
128*48727Ssklower struct sockaddr *sa;
129*48727Ssklower {
130*48727Ssklower 	if (rt)
131*48727Ssklower 		rt->rt_rmx.rmx_mtu = LOMTU;
132*48727Ssklower }
133*48727Ssklower 
13413066Ssam /*
13513066Ssam  * Process an ioctl request.
13613066Ssam  */
13718370Skarels /* ARGSUSED */
13813066Ssam loioctl(ifp, cmd, data)
13913066Ssam 	register struct ifnet *ifp;
14013066Ssam 	int cmd;
14113066Ssam 	caddr_t data;
14213066Ssam {
143*48727Ssklower 	register struct ifaddr *ifa;
14418370Skarels 	int error = 0;
14513066Ssam 
14613066Ssam 	switch (cmd) {
14713066Ssam 
14813066Ssam 	case SIOCSIFADDR:
14918370Skarels 		ifp->if_flags |= IFF_UP;
150*48727Ssklower 		ifa = (struct ifaddr *)data;
151*48727Ssklower 		if (ifa != 0 && ifa->ifa_addr->sa_family == AF_ISO)
152*48727Ssklower 			ifa->ifa_rtrequest = lortrequest;
15318370Skarels 		/*
15418370Skarels 		 * Everything else is done at a higher level.
15518370Skarels 		 */
15613066Ssam 		break;
15713066Ssam 
15813066Ssam 	default:
15913066Ssam 		error = EINVAL;
16013066Ssam 	}
16113066Ssam 	return (error);
16213066Ssam }
163