xref: /csrg-svn/sys/net/if_loop.c (revision 29922)
123174Smckusick /*
229071Skarels  * Copyright (c) 1982, 1986 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*29922Skarels  *	@(#)if_loop.c	7.2 (Berkeley) 10/28/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 
24*29922Skarels #include "../machine/mtpr.h"
25*29922Skarels 
2624771Skarels #ifdef	INET
2724771Skarels #include "../netinet/in.h"
2824771Skarels #include "../netinet/in_systm.h"
2929071Skarels #include "../netinet/in_var.h"
3024771Skarels #include "../netinet/ip.h"
3124771Skarels #endif
325122Swnj 
3318815Ssklower #ifdef NS
3418815Ssklower #include "../netns/ns.h"
3518815Ssklower #include "../netns/ns_if.h"
3618815Ssklower #endif
3718815Ssklower 
385207Swnj #define	LOMTU	(1024+512)
395122Swnj 
405122Swnj struct	ifnet loif;
4113066Ssam int	looutput(), loioctl();
425122Swnj 
435122Swnj loattach()
445122Swnj {
455122Swnj 	register struct ifnet *ifp = &loif;
465122Swnj 
475172Swnj 	ifp->if_name = "lo";
485122Swnj 	ifp->if_mtu = LOMTU;
4926091Skarels 	ifp->if_flags = IFF_LOOPBACK;
5013066Ssam 	ifp->if_ioctl = loioctl;
515122Swnj 	ifp->if_output = looutput;
525161Swnj 	if_attach(ifp);
535122Swnj }
545122Swnj 
556337Ssam looutput(ifp, m0, dst)
565122Swnj 	struct ifnet *ifp;
5724771Skarels 	register struct mbuf *m0;
586337Ssam 	struct sockaddr *dst;
595122Swnj {
6024771Skarels 	int s;
616209Swnj 	register struct ifqueue *ifq;
6224771Skarels 	struct mbuf *m;
635122Swnj 
6424771Skarels 	/*
6524771Skarels 	 * Place interface pointer before the data
6624771Skarels 	 * for the receiving protocol.
6724771Skarels 	 */
6824771Skarels 	if (m0->m_off <= MMAXOFF &&
6924771Skarels 	    m0->m_off >= MMINOFF + sizeof(struct ifnet *)) {
7024771Skarels 		m0->m_off -= sizeof(struct ifnet *);
7124771Skarels 		m0->m_len += sizeof(struct ifnet *);
7224771Skarels 	} else {
7324771Skarels 		MGET(m, M_DONTWAIT, MT_HEADER);
7424771Skarels 		if (m == (struct mbuf *)0)
7524771Skarels 			return (ENOBUFS);
7624771Skarels 		m->m_off = MMINOFF;
7724771Skarels 		m->m_len = sizeof(struct ifnet *);
7824771Skarels 		m->m_next = m0;
7924771Skarels 		m0 = m;
8024771Skarels 	}
8124771Skarels 	*(mtod(m0, struct ifnet **)) = ifp;
8224771Skarels 	s = splimp();
835172Swnj 	ifp->if_opackets++;
846337Ssam 	switch (dst->sa_family) {
855122Swnj 
865122Swnj #ifdef INET
876337Ssam 	case AF_INET:
886209Swnj 		ifq = &ipintrq;
896209Swnj 		if (IF_QFULL(ifq)) {
906209Swnj 			IF_DROP(ifq);
916337Ssam 			m_freem(m0);
926209Swnj 			splx(s);
936544Sfeldman 			return (ENOBUFS);
946209Swnj 		}
956209Swnj 		IF_ENQUEUE(ifq, m0);
966262Swnj 		schednetisr(NETISR_IP);
975122Swnj 		break;
985122Swnj #endif
9918815Ssklower #ifdef NS
10018815Ssklower 	case AF_NS:
10118815Ssklower 		ifq = &nsintrq;
10218815Ssklower 		if (IF_QFULL(ifq)) {
10318815Ssklower 			IF_DROP(ifq);
10418815Ssklower 			m_freem(m0);
10518815Ssklower 			splx(s);
10618815Ssklower 			return (ENOBUFS);
10718815Ssklower 		}
10818815Ssklower 		IF_ENQUEUE(ifq, m0);
10918815Ssklower 		schednetisr(NETISR_NS);
11018815Ssklower 		break;
11118815Ssklower #endif
1125122Swnj 	default:
1135122Swnj 		splx(s);
1146337Ssam 		printf("lo%d: can't handle af%d\n", ifp->if_unit,
1156337Ssam 			dst->sa_family);
1166337Ssam 		m_freem(m0);
1176544Sfeldman 		return (EAFNOSUPPORT);
1185122Swnj 	}
1195172Swnj 	ifp->if_ipackets++;
1205122Swnj 	splx(s);
1216544Sfeldman 	return (0);
1225122Swnj }
12313066Ssam 
12413066Ssam /*
12513066Ssam  * Process an ioctl request.
12613066Ssam  */
12718370Skarels /* ARGSUSED */
12813066Ssam loioctl(ifp, cmd, data)
12913066Ssam 	register struct ifnet *ifp;
13013066Ssam 	int cmd;
13113066Ssam 	caddr_t data;
13213066Ssam {
13318370Skarels 	int error = 0;
13413066Ssam 
13513066Ssam 	switch (cmd) {
13613066Ssam 
13713066Ssam 	case SIOCSIFADDR:
13818370Skarels 		ifp->if_flags |= IFF_UP;
13918370Skarels 		/*
14018370Skarels 		 * Everything else is done at a higher level.
14118370Skarels 		 */
14213066Ssam 		break;
14313066Ssam 
14413066Ssam 	default:
14513066Ssam 		error = EINVAL;
14613066Ssam 	}
14713066Ssam 	return (error);
14813066Ssam }
149