xref: /csrg-svn/sys/net/if_loop.c (revision 26091)
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*26091Skarels  *	@(#)if_loop.c	6.9 (Berkeley) 02/06/86
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 
2010907Ssam #include "../net/if.h"
2110907Ssam #include "../net/netisr.h"
2210907Ssam #include "../net/route.h"
2310907Ssam 
2424771Skarels #ifdef	INET
2524771Skarels #include "../netinet/in.h"
2624771Skarels #include "../netinet/in_systm.h"
2724771Skarels #include "../netinet/ip.h"
2824771Skarels #include "../netinet/ip_var.h"
2924771Skarels #endif
305122Swnj 
3112460Ssam #ifdef vax
3212460Ssam #include "../vax/mtpr.h"
3312460Ssam #endif
3410907Ssam 
3518815Ssklower #ifdef NS
3618815Ssklower #include "../netns/ns.h"
3718815Ssklower #include "../netns/ns_if.h"
3818815Ssklower #endif
3918815Ssklower 
405207Swnj #define	LOMTU	(1024+512)
415122Swnj 
425122Swnj struct	ifnet loif;
4313066Ssam int	looutput(), loioctl();
445122Swnj 
455122Swnj loattach()
465122Swnj {
475122Swnj 	register struct ifnet *ifp = &loif;
485122Swnj 
495172Swnj 	ifp->if_name = "lo";
505122Swnj 	ifp->if_mtu = LOMTU;
51*26091Skarels 	ifp->if_flags = IFF_LOOPBACK;
5213066Ssam 	ifp->if_ioctl = loioctl;
535122Swnj 	ifp->if_output = looutput;
545161Swnj 	if_attach(ifp);
555122Swnj }
565122Swnj 
576337Ssam looutput(ifp, m0, dst)
585122Swnj 	struct ifnet *ifp;
5924771Skarels 	register struct mbuf *m0;
606337Ssam 	struct sockaddr *dst;
615122Swnj {
6224771Skarels 	int s;
636209Swnj 	register struct ifqueue *ifq;
6424771Skarels 	struct mbuf *m;
655122Swnj 
6624771Skarels 	/*
6724771Skarels 	 * Place interface pointer before the data
6824771Skarels 	 * for the receiving protocol.
6924771Skarels 	 */
7024771Skarels 	if (m0->m_off <= MMAXOFF &&
7124771Skarels 	    m0->m_off >= MMINOFF + sizeof(struct ifnet *)) {
7224771Skarels 		m0->m_off -= sizeof(struct ifnet *);
7324771Skarels 		m0->m_len += sizeof(struct ifnet *);
7424771Skarels 	} else {
7524771Skarels 		MGET(m, M_DONTWAIT, MT_HEADER);
7624771Skarels 		if (m == (struct mbuf *)0)
7724771Skarels 			return (ENOBUFS);
7824771Skarels 		m->m_off = MMINOFF;
7924771Skarels 		m->m_len = sizeof(struct ifnet *);
8024771Skarels 		m->m_next = m0;
8124771Skarels 		m0 = m;
8224771Skarels 	}
8324771Skarels 	*(mtod(m0, struct ifnet **)) = ifp;
8424771Skarels 	s = splimp();
855172Swnj 	ifp->if_opackets++;
866337Ssam 	switch (dst->sa_family) {
875122Swnj 
885122Swnj #ifdef INET
896337Ssam 	case AF_INET:
906209Swnj 		ifq = &ipintrq;
916209Swnj 		if (IF_QFULL(ifq)) {
926209Swnj 			IF_DROP(ifq);
936337Ssam 			m_freem(m0);
946209Swnj 			splx(s);
956544Sfeldman 			return (ENOBUFS);
966209Swnj 		}
976209Swnj 		IF_ENQUEUE(ifq, m0);
986262Swnj 		schednetisr(NETISR_IP);
995122Swnj 		break;
1005122Swnj #endif
10118815Ssklower #ifdef NS
10218815Ssklower 	case AF_NS:
10318815Ssklower 		ifq = &nsintrq;
10418815Ssklower 		if (IF_QFULL(ifq)) {
10518815Ssklower 			IF_DROP(ifq);
10618815Ssklower 			m_freem(m0);
10718815Ssklower 			splx(s);
10818815Ssklower 			return (ENOBUFS);
10918815Ssklower 		}
11018815Ssklower 		IF_ENQUEUE(ifq, m0);
11118815Ssklower 		schednetisr(NETISR_NS);
11218815Ssklower 		break;
11318815Ssklower #endif
1145122Swnj 	default:
1155122Swnj 		splx(s);
1166337Ssam 		printf("lo%d: can't handle af%d\n", ifp->if_unit,
1176337Ssam 			dst->sa_family);
1186337Ssam 		m_freem(m0);
1196544Sfeldman 		return (EAFNOSUPPORT);
1205122Swnj 	}
1215172Swnj 	ifp->if_ipackets++;
1225122Swnj 	splx(s);
1236544Sfeldman 	return (0);
1245122Swnj }
12513066Ssam 
12613066Ssam /*
12713066Ssam  * Process an ioctl request.
12813066Ssam  */
12918370Skarels /* ARGSUSED */
13013066Ssam loioctl(ifp, cmd, data)
13113066Ssam 	register struct ifnet *ifp;
13213066Ssam 	int cmd;
13313066Ssam 	caddr_t data;
13413066Ssam {
13518370Skarels 	int error = 0;
13613066Ssam 
13713066Ssam 	switch (cmd) {
13813066Ssam 
13913066Ssam 	case SIOCSIFADDR:
14018370Skarels 		ifp->if_flags |= IFF_UP;
14118370Skarels 		/*
14218370Skarels 		 * Everything else is done at a higher level.
14318370Skarels 		 */
14413066Ssam 		break;
14513066Ssam 
14613066Ssam 	default:
14713066Ssam 		error = EINVAL;
14813066Ssam 	}
14913066Ssam 	return (error);
15013066Ssam }
151