xref: /csrg-svn/sys/net/if_loop.c (revision 24771)
123174Smckusick /*
223174Smckusick  * Copyright (c) 1982 Regents of the University of California.
323174Smckusick  * All rights reserved.  The Berkeley software License Agreement
423174Smckusick  * specifies the terms and conditions for redistribution.
523174Smckusick  *
6*24771Skarels  *	@(#)if_loop.c	6.7 (Berkeley) 09/16/85
723174Smckusick  */
85122Swnj 
95122Swnj /*
105122Swnj  * Loopback interface driver for protocol testing and timing.
115122Swnj  */
125122Swnj 
1317058Sbloom #include "param.h"
1417058Sbloom #include "systm.h"
1517058Sbloom #include "mbuf.h"
1617058Sbloom #include "socket.h"
1717058Sbloom #include "errno.h"
1817058Sbloom #include "ioctl.h"
1910907Ssam 
20*24771Skarels #ifdef	BBNNET
21*24771Skarels #define INET
22*24771Skarels #endif
2310907Ssam #include "../net/if.h"
2410907Ssam #include "../net/netisr.h"
2510907Ssam #include "../net/route.h"
2610907Ssam 
27*24771Skarels #ifdef	INET
28*24771Skarels #include "../netinet/in.h"
29*24771Skarels #include "../netinet/in_systm.h"
30*24771Skarels #include "../netinet/ip.h"
31*24771Skarels #include "../netinet/ip_var.h"
32*24771Skarels #endif
335122Swnj 
3412460Ssam #ifdef vax
3512460Ssam #include "../vax/mtpr.h"
3612460Ssam #endif
3710907Ssam 
3818815Ssklower #ifdef NS
3918815Ssklower #include "../netns/ns.h"
4018815Ssklower #include "../netns/ns_if.h"
4118815Ssklower #endif
4218815Ssklower 
435207Swnj #define	LOMTU	(1024+512)
445122Swnj 
455122Swnj struct	ifnet loif;
4613066Ssam int	looutput(), loioctl();
475122Swnj 
485122Swnj loattach()
495122Swnj {
505122Swnj 	register struct ifnet *ifp = &loif;
515122Swnj 
525172Swnj 	ifp->if_name = "lo";
535122Swnj 	ifp->if_mtu = LOMTU;
5413066Ssam 	ifp->if_ioctl = loioctl;
555122Swnj 	ifp->if_output = looutput;
565161Swnj 	if_attach(ifp);
575122Swnj }
585122Swnj 
596337Ssam looutput(ifp, m0, dst)
605122Swnj 	struct ifnet *ifp;
61*24771Skarels 	register struct mbuf *m0;
626337Ssam 	struct sockaddr *dst;
635122Swnj {
64*24771Skarels 	int s;
656209Swnj 	register struct ifqueue *ifq;
66*24771Skarels 	struct mbuf *m;
675122Swnj 
68*24771Skarels 	/*
69*24771Skarels 	 * Place interface pointer before the data
70*24771Skarels 	 * for the receiving protocol.
71*24771Skarels 	 */
72*24771Skarels 	if (m0->m_off <= MMAXOFF &&
73*24771Skarels 	    m0->m_off >= MMINOFF + sizeof(struct ifnet *)) {
74*24771Skarels 		m0->m_off -= sizeof(struct ifnet *);
75*24771Skarels 		m0->m_len += sizeof(struct ifnet *);
76*24771Skarels 	} else {
77*24771Skarels 		MGET(m, M_DONTWAIT, MT_HEADER);
78*24771Skarels 		if (m == (struct mbuf *)0)
79*24771Skarels 			return (ENOBUFS);
80*24771Skarels 		m->m_off = MMINOFF;
81*24771Skarels 		m->m_len = sizeof(struct ifnet *);
82*24771Skarels 		m->m_next = m0;
83*24771Skarels 		m0 = m;
84*24771Skarels 	}
85*24771Skarels 	*(mtod(m0, struct ifnet **)) = ifp;
86*24771Skarels 	s = splimp();
875172Swnj 	ifp->if_opackets++;
886337Ssam 	switch (dst->sa_family) {
895122Swnj 
905122Swnj #ifdef INET
916337Ssam 	case AF_INET:
926209Swnj 		ifq = &ipintrq;
936209Swnj 		if (IF_QFULL(ifq)) {
946209Swnj 			IF_DROP(ifq);
956337Ssam 			m_freem(m0);
966209Swnj 			splx(s);
976544Sfeldman 			return (ENOBUFS);
986209Swnj 		}
996209Swnj 		IF_ENQUEUE(ifq, m0);
1006262Swnj 		schednetisr(NETISR_IP);
1015122Swnj 		break;
1025122Swnj #endif
10318815Ssklower #ifdef NS
10418815Ssklower 	case AF_NS:
10518815Ssklower 		ifq = &nsintrq;
10618815Ssklower 		if (IF_QFULL(ifq)) {
10718815Ssklower 			IF_DROP(ifq);
10818815Ssklower 			m_freem(m0);
10918815Ssklower 			splx(s);
11018815Ssklower 			return (ENOBUFS);
11118815Ssklower 		}
11218815Ssklower 		IF_ENQUEUE(ifq, m0);
11318815Ssklower 		schednetisr(NETISR_NS);
11418815Ssklower 		break;
11518815Ssklower #endif
1165122Swnj 	default:
1175122Swnj 		splx(s);
1186337Ssam 		printf("lo%d: can't handle af%d\n", ifp->if_unit,
1196337Ssam 			dst->sa_family);
1206337Ssam 		m_freem(m0);
1216544Sfeldman 		return (EAFNOSUPPORT);
1225122Swnj 	}
1235172Swnj 	ifp->if_ipackets++;
1245122Swnj 	splx(s);
1256544Sfeldman 	return (0);
1265122Swnj }
12713066Ssam 
12813066Ssam /*
12913066Ssam  * Process an ioctl request.
13013066Ssam  */
13118370Skarels /* ARGSUSED */
13213066Ssam loioctl(ifp, cmd, data)
13313066Ssam 	register struct ifnet *ifp;
13413066Ssam 	int cmd;
13513066Ssam 	caddr_t data;
13613066Ssam {
13718370Skarels 	int error = 0;
13813066Ssam 
13913066Ssam 	switch (cmd) {
14013066Ssam 
14113066Ssam 	case SIOCSIFADDR:
14218370Skarels 		ifp->if_flags |= IFF_UP;
14318370Skarels 		/*
14418370Skarels 		 * Everything else is done at a higher level.
14518370Skarels 		 */
14613066Ssam 		break;
14713066Ssam 
14813066Ssam 	default:
14913066Ssam 		error = EINVAL;
15013066Ssam 	}
15113066Ssam 	return (error);
15213066Ssam }
153