xref: /csrg-svn/sys/net/if_loop.c (revision 44464)
123174Smckusick /*
229071Skarels  * Copyright (c) 1982, 1986 Regents of the University of California.
333183Sbostic  * All rights reserved.
423174Smckusick  *
5*44464Sbostic  * %sccs.include.redist.c%
633183Sbostic  *
7*44464Sbostic  *	@(#)if_loop.c	7.10 (Berkeley) 06/28/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 
6535795Skarels struct mbuf *Loop_Sanity;
6635795Skarels 
6735795Skarels looutput(ifp, m, dst)
685122Swnj 	struct ifnet *ifp;
6935795Skarels 	register struct mbuf *m;
706337Ssam 	struct sockaddr *dst;
715122Swnj {
7224771Skarels 	int s;
736209Swnj 	register struct ifqueue *ifq;
745122Swnj 
7535795Skarels 	if ((m->m_flags & M_PKTHDR) == 0)
7635795Skarels 		panic("looutput no HDR");
7735795Skarels 	m->m_pkthdr.rcvif = ifp;
7835795Skarels 
7935795Skarels {struct mbuf *mm; int mlen = 0;
8037472Ssklower for (mm = m; m; m = m->m_next) /* XXX debugging code -- sklower */
8135795Skarels     mlen += m->m_len;
8235795Skarels m = mm;
8335795Skarels if (mlen != m->m_pkthdr.len) {
8435795Skarels 	if (Loop_Sanity)
8535795Skarels 		m_freem(Loop_Sanity);
8637472Ssklower 	Loop_Sanity = m_copy(m, 0, (int)M_COPYALL);
8735795Skarels }
8835795Skarels }
8935795Skarels 
9024771Skarels 	s = splimp();
915172Swnj 	ifp->if_opackets++;
9239187Ssklower 	ifp->if_obytes += m->m_pkthdr.len;
936337Ssam 	switch (dst->sa_family) {
945122Swnj 
955122Swnj #ifdef INET
966337Ssam 	case AF_INET:
976209Swnj 		ifq = &ipintrq;
986209Swnj 		if (IF_QFULL(ifq)) {
996209Swnj 			IF_DROP(ifq);
10035795Skarels 			m_freem(m);
1016209Swnj 			splx(s);
1026544Sfeldman 			return (ENOBUFS);
1036209Swnj 		}
10435795Skarels 		IF_ENQUEUE(ifq, m);
1056262Swnj 		schednetisr(NETISR_IP);
1065122Swnj 		break;
1075122Swnj #endif
10818815Ssklower #ifdef NS
10918815Ssklower 	case AF_NS:
11018815Ssklower 		ifq = &nsintrq;
11118815Ssklower 		if (IF_QFULL(ifq)) {
11218815Ssklower 			IF_DROP(ifq);
11335795Skarels 			m_freem(m);
11418815Ssklower 			splx(s);
11518815Ssklower 			return (ENOBUFS);
11618815Ssklower 		}
11735795Skarels 		IF_ENQUEUE(ifq, m);
11818815Ssklower 		schednetisr(NETISR_NS);
11918815Ssklower 		break;
12018815Ssklower #endif
12137472Ssklower #ifdef ISO
12237472Ssklower 	case AF_ISO:
12337472Ssklower 		ifq = &clnlintrq;
12437472Ssklower 		if (IF_QFULL(ifq)) {
12537472Ssklower 			IF_DROP(ifq);
12637472Ssklower 			m_freem(m);
12737472Ssklower 			splx(s);
12837472Ssklower 			return (ENOBUFS);
12937472Ssklower 		}
13037472Ssklower 		IF_ENQUEUE(ifq, m);
13137472Ssklower 		schednetisr(NETISR_ISO);
13237472Ssklower 		break;
13337472Ssklower #endif
1345122Swnj 	default:
1355122Swnj 		splx(s);
1366337Ssam 		printf("lo%d: can't handle af%d\n", ifp->if_unit,
1376337Ssam 			dst->sa_family);
13835795Skarels 		m_freem(m);
1396544Sfeldman 		return (EAFNOSUPPORT);
1405122Swnj 	}
1415172Swnj 	ifp->if_ipackets++;
14239187Ssklower 	ifp->if_ibytes += m->m_pkthdr.len;
1435122Swnj 	splx(s);
1446544Sfeldman 	return (0);
1455122Swnj }
14613066Ssam 
14713066Ssam /*
14813066Ssam  * Process an ioctl request.
14913066Ssam  */
15018370Skarels /* ARGSUSED */
15113066Ssam loioctl(ifp, cmd, data)
15213066Ssam 	register struct ifnet *ifp;
15313066Ssam 	int cmd;
15413066Ssam 	caddr_t data;
15513066Ssam {
15618370Skarels 	int error = 0;
15713066Ssam 
15813066Ssam 	switch (cmd) {
15913066Ssam 
16013066Ssam 	case SIOCSIFADDR:
16118370Skarels 		ifp->if_flags |= IFF_UP;
16218370Skarels 		/*
16318370Skarels 		 * Everything else is done at a higher level.
16418370Skarels 		 */
16513066Ssam 		break;
16613066Ssam 
16713066Ssam 	default:
16813066Ssam 		error = EINVAL;
16913066Ssam 	}
17013066Ssam 	return (error);
17113066Ssam }
172