xref: /csrg-svn/sys/net/if_loop.c (revision 34844)
123174Smckusick /*
229071Skarels  * Copyright (c) 1982, 1986 Regents of the University of California.
333183Sbostic  * All rights reserved.
423174Smckusick  *
533183Sbostic  * Redistribution and use in source and binary forms are permitted
6*34844Sbostic  * provided that the above copyright notice and this paragraph are
7*34844Sbostic  * duplicated in all such forms and that any documentation,
8*34844Sbostic  * advertising materials, and other materials related to such
9*34844Sbostic  * distribution and use acknowledge that the software was developed
10*34844Sbostic  * by the University of California, Berkeley.  The name of the
11*34844Sbostic  * University may not be used to endorse or promote products derived
12*34844Sbostic  * from this software without specific prior written permission.
13*34844Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14*34844Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15*34844Sbostic  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1633183Sbostic  *
17*34844Sbostic  *	@(#)if_loop.c	7.4 (Berkeley) 06/27/88
1823174Smckusick  */
195122Swnj 
205122Swnj /*
215122Swnj  * Loopback interface driver for protocol testing and timing.
225122Swnj  */
235122Swnj 
2417058Sbloom #include "param.h"
2517058Sbloom #include "systm.h"
2617058Sbloom #include "mbuf.h"
2717058Sbloom #include "socket.h"
2817058Sbloom #include "errno.h"
2917058Sbloom #include "ioctl.h"
3010907Ssam 
3110907Ssam #include "../net/if.h"
3210907Ssam #include "../net/netisr.h"
3310907Ssam #include "../net/route.h"
3410907Ssam 
3529922Skarels #include "../machine/mtpr.h"
3629922Skarels 
3724771Skarels #ifdef	INET
3824771Skarels #include "../netinet/in.h"
3924771Skarels #include "../netinet/in_systm.h"
4029071Skarels #include "../netinet/in_var.h"
4124771Skarels #include "../netinet/ip.h"
4224771Skarels #endif
435122Swnj 
4418815Ssklower #ifdef NS
4518815Ssklower #include "../netns/ns.h"
4618815Ssklower #include "../netns/ns_if.h"
4718815Ssklower #endif
4818815Ssklower 
495207Swnj #define	LOMTU	(1024+512)
505122Swnj 
515122Swnj struct	ifnet loif;
5213066Ssam int	looutput(), loioctl();
535122Swnj 
545122Swnj loattach()
555122Swnj {
565122Swnj 	register struct ifnet *ifp = &loif;
575122Swnj 
585172Swnj 	ifp->if_name = "lo";
595122Swnj 	ifp->if_mtu = LOMTU;
6026091Skarels 	ifp->if_flags = IFF_LOOPBACK;
6113066Ssam 	ifp->if_ioctl = loioctl;
625122Swnj 	ifp->if_output = looutput;
635161Swnj 	if_attach(ifp);
645122Swnj }
655122Swnj 
666337Ssam looutput(ifp, m0, dst)
675122Swnj 	struct ifnet *ifp;
6824771Skarels 	register struct mbuf *m0;
696337Ssam 	struct sockaddr *dst;
705122Swnj {
7124771Skarels 	int s;
726209Swnj 	register struct ifqueue *ifq;
7324771Skarels 	struct mbuf *m;
745122Swnj 
7524771Skarels 	/*
7624771Skarels 	 * Place interface pointer before the data
7724771Skarels 	 * for the receiving protocol.
7824771Skarels 	 */
7924771Skarels 	if (m0->m_off <= MMAXOFF &&
8024771Skarels 	    m0->m_off >= MMINOFF + sizeof(struct ifnet *)) {
8124771Skarels 		m0->m_off -= sizeof(struct ifnet *);
8224771Skarels 		m0->m_len += sizeof(struct ifnet *);
8324771Skarels 	} else {
8424771Skarels 		MGET(m, M_DONTWAIT, MT_HEADER);
8524771Skarels 		if (m == (struct mbuf *)0)
8624771Skarels 			return (ENOBUFS);
8724771Skarels 		m->m_off = MMINOFF;
8824771Skarels 		m->m_len = sizeof(struct ifnet *);
8924771Skarels 		m->m_next = m0;
9024771Skarels 		m0 = m;
9124771Skarels 	}
9224771Skarels 	*(mtod(m0, struct ifnet **)) = ifp;
9324771Skarels 	s = splimp();
945172Swnj 	ifp->if_opackets++;
956337Ssam 	switch (dst->sa_family) {
965122Swnj 
975122Swnj #ifdef INET
986337Ssam 	case AF_INET:
996209Swnj 		ifq = &ipintrq;
1006209Swnj 		if (IF_QFULL(ifq)) {
1016209Swnj 			IF_DROP(ifq);
1026337Ssam 			m_freem(m0);
1036209Swnj 			splx(s);
1046544Sfeldman 			return (ENOBUFS);
1056209Swnj 		}
1066209Swnj 		IF_ENQUEUE(ifq, m0);
1076262Swnj 		schednetisr(NETISR_IP);
1085122Swnj 		break;
1095122Swnj #endif
11018815Ssklower #ifdef NS
11118815Ssklower 	case AF_NS:
11218815Ssklower 		ifq = &nsintrq;
11318815Ssklower 		if (IF_QFULL(ifq)) {
11418815Ssklower 			IF_DROP(ifq);
11518815Ssklower 			m_freem(m0);
11618815Ssklower 			splx(s);
11718815Ssklower 			return (ENOBUFS);
11818815Ssklower 		}
11918815Ssklower 		IF_ENQUEUE(ifq, m0);
12018815Ssklower 		schednetisr(NETISR_NS);
12118815Ssklower 		break;
12218815Ssklower #endif
1235122Swnj 	default:
1245122Swnj 		splx(s);
1256337Ssam 		printf("lo%d: can't handle af%d\n", ifp->if_unit,
1266337Ssam 			dst->sa_family);
1276337Ssam 		m_freem(m0);
1286544Sfeldman 		return (EAFNOSUPPORT);
1295122Swnj 	}
1305172Swnj 	ifp->if_ipackets++;
1315122Swnj 	splx(s);
1326544Sfeldman 	return (0);
1335122Swnj }
13413066Ssam 
13513066Ssam /*
13613066Ssam  * Process an ioctl request.
13713066Ssam  */
13818370Skarels /* ARGSUSED */
13913066Ssam loioctl(ifp, cmd, data)
14013066Ssam 	register struct ifnet *ifp;
14113066Ssam 	int cmd;
14213066Ssam 	caddr_t data;
14313066Ssam {
14418370Skarels 	int error = 0;
14513066Ssam 
14613066Ssam 	switch (cmd) {
14713066Ssam 
14813066Ssam 	case SIOCSIFADDR:
14918370Skarels 		ifp->if_flags |= IFF_UP;
15018370Skarels 		/*
15118370Skarels 		 * Everything else is done at a higher level.
15218370Skarels 		 */
15313066Ssam 		break;
15413066Ssam 
15513066Ssam 	default:
15613066Ssam 		error = EINVAL;
15713066Ssam 	}
15813066Ssam 	return (error);
15913066Ssam }
160