xref: /csrg-svn/sys/net/if_loop.c (revision 45198)
123174Smckusick /*
229071Skarels  * Copyright (c) 1982, 1986 Regents of the University of California.
333183Sbostic  * All rights reserved.
423174Smckusick  *
544464Sbostic  * %sccs.include.redist.c%
633183Sbostic  *
7*45198Ssklower  *	@(#)if_loop.c	7.11 (Berkeley) 09/04/90
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 
65*45198Ssklower looutput(ifp, m, dst, rt)
665122Swnj 	struct ifnet *ifp;
6735795Skarels 	register struct mbuf *m;
686337Ssam 	struct sockaddr *dst;
69*45198Ssklower 	register struct rtentry *rt;
705122Swnj {
7124771Skarels 	int s;
726209Swnj 	register struct ifqueue *ifq;
735122Swnj 
7435795Skarels 	if ((m->m_flags & M_PKTHDR) == 0)
7535795Skarels 		panic("looutput no HDR");
7635795Skarels 	m->m_pkthdr.rcvif = ifp;
7735795Skarels 
78*45198Ssklower 	if (rt && rt->rt_flags & RTF_REJECT) {
79*45198Ssklower 		m_freem(m);
80*45198Ssklower 		return (rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH);
81*45198Ssklower 	}
8224771Skarels 	s = splimp();
835172Swnj 	ifp->if_opackets++;
8439187Ssklower 	ifp->if_obytes += m->m_pkthdr.len;
856337Ssam 	switch (dst->sa_family) {
865122Swnj 
875122Swnj #ifdef INET
886337Ssam 	case AF_INET:
896209Swnj 		ifq = &ipintrq;
906209Swnj 		if (IF_QFULL(ifq)) {
916209Swnj 			IF_DROP(ifq);
9235795Skarels 			m_freem(m);
936209Swnj 			splx(s);
946544Sfeldman 			return (ENOBUFS);
956209Swnj 		}
9635795Skarels 		IF_ENQUEUE(ifq, m);
976262Swnj 		schednetisr(NETISR_IP);
985122Swnj 		break;
995122Swnj #endif
10018815Ssklower #ifdef NS
10118815Ssklower 	case AF_NS:
10218815Ssklower 		ifq = &nsintrq;
10318815Ssklower 		if (IF_QFULL(ifq)) {
10418815Ssklower 			IF_DROP(ifq);
10535795Skarels 			m_freem(m);
10618815Ssklower 			splx(s);
10718815Ssklower 			return (ENOBUFS);
10818815Ssklower 		}
10935795Skarels 		IF_ENQUEUE(ifq, m);
11018815Ssklower 		schednetisr(NETISR_NS);
11118815Ssklower 		break;
11218815Ssklower #endif
11337472Ssklower #ifdef ISO
11437472Ssklower 	case AF_ISO:
11537472Ssklower 		ifq = &clnlintrq;
11637472Ssklower 		if (IF_QFULL(ifq)) {
11737472Ssklower 			IF_DROP(ifq);
11837472Ssklower 			m_freem(m);
11937472Ssklower 			splx(s);
12037472Ssklower 			return (ENOBUFS);
12137472Ssklower 		}
12237472Ssklower 		IF_ENQUEUE(ifq, m);
12337472Ssklower 		schednetisr(NETISR_ISO);
12437472Ssklower 		break;
12537472Ssklower #endif
1265122Swnj 	default:
1275122Swnj 		splx(s);
1286337Ssam 		printf("lo%d: can't handle af%d\n", ifp->if_unit,
1296337Ssam 			dst->sa_family);
13035795Skarels 		m_freem(m);
1316544Sfeldman 		return (EAFNOSUPPORT);
1325122Swnj 	}
1335172Swnj 	ifp->if_ipackets++;
13439187Ssklower 	ifp->if_ibytes += m->m_pkthdr.len;
1355122Swnj 	splx(s);
1366544Sfeldman 	return (0);
1375122Swnj }
13813066Ssam 
13913066Ssam /*
14013066Ssam  * Process an ioctl request.
14113066Ssam  */
14218370Skarels /* ARGSUSED */
14313066Ssam loioctl(ifp, cmd, data)
14413066Ssam 	register struct ifnet *ifp;
14513066Ssam 	int cmd;
14613066Ssam 	caddr_t data;
14713066Ssam {
14818370Skarels 	int error = 0;
14913066Ssam 
15013066Ssam 	switch (cmd) {
15113066Ssam 
15213066Ssam 	case SIOCSIFADDR:
15318370Skarels 		ifp->if_flags |= IFF_UP;
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