xref: /csrg-svn/sys/net/if_loop.c (revision 18815)
1*18815Ssklower /*	if_loop.c	6.4	85/04/27	*/
25122Swnj 
35122Swnj /*
45122Swnj  * Loopback interface driver for protocol testing and timing.
55122Swnj  */
65122Swnj 
717058Sbloom #include "param.h"
817058Sbloom #include "systm.h"
917058Sbloom #include "mbuf.h"
1017058Sbloom #include "socket.h"
1117058Sbloom #include "errno.h"
1217058Sbloom #include "ioctl.h"
1310907Ssam 
1410907Ssam #include "../net/if.h"
1510907Ssam #include "../net/netisr.h"
1610907Ssam #include "../net/route.h"
1710907Ssam 
1817058Sbloom #include "in.h"
1917058Sbloom #include "in_systm.h"
2017058Sbloom #include "ip.h"
2117058Sbloom #include "ip_var.h"
225122Swnj 
2312460Ssam #ifdef vax
2412460Ssam #include "../vax/mtpr.h"
2512460Ssam #endif
2610907Ssam 
27*18815Ssklower #ifdef NS
28*18815Ssklower #include "../netns/ns.h"
29*18815Ssklower #include "../netns/ns_if.h"
30*18815Ssklower #endif
31*18815Ssklower 
325296Sroot #define	LONET	127
3312761Ssam #define	LOHOST	1			/* can't be 0, that's broadcast */
345207Swnj #define	LOMTU	(1024+512)
355122Swnj 
365122Swnj struct	ifnet loif;
3713066Ssam int	looutput(), loioctl();
385122Swnj 
395122Swnj loattach()
405122Swnj {
415122Swnj 	register struct ifnet *ifp = &loif;
426337Ssam 	register struct sockaddr_in *sin;
435122Swnj 
445172Swnj 	ifp->if_name = "lo";
455122Swnj 	ifp->if_mtu = LOMTU;
4613066Ssam 	ifp->if_ioctl = loioctl;
475122Swnj 	ifp->if_output = looutput;
485161Swnj 	if_attach(ifp);
495122Swnj }
505122Swnj 
516337Ssam looutput(ifp, m0, dst)
525122Swnj 	struct ifnet *ifp;
535122Swnj 	struct mbuf *m0;
546337Ssam 	struct sockaddr *dst;
555122Swnj {
565122Swnj 	int s = splimp();
576209Swnj 	register struct ifqueue *ifq;
585122Swnj 
595172Swnj 	ifp->if_opackets++;
606337Ssam 	switch (dst->sa_family) {
615122Swnj 
625122Swnj #ifdef INET
636337Ssam 	case AF_INET:
646209Swnj 		ifq = &ipintrq;
656209Swnj 		if (IF_QFULL(ifq)) {
666209Swnj 			IF_DROP(ifq);
676337Ssam 			m_freem(m0);
686209Swnj 			splx(s);
696544Sfeldman 			return (ENOBUFS);
706209Swnj 		}
716209Swnj 		IF_ENQUEUE(ifq, m0);
726262Swnj 		schednetisr(NETISR_IP);
735122Swnj 		break;
745122Swnj #endif
75*18815Ssklower #ifdef NS
76*18815Ssklower 	case AF_NS:
77*18815Ssklower 		ifq = &nsintrq;
78*18815Ssklower 		if (IF_QFULL(ifq)) {
79*18815Ssklower 			IF_DROP(ifq);
80*18815Ssklower 			m_freem(m0);
81*18815Ssklower 			splx(s);
82*18815Ssklower 			return (ENOBUFS);
83*18815Ssklower 		}
84*18815Ssklower 		IF_ENQUEUE(ifq, m0);
85*18815Ssklower 		schednetisr(NETISR_NS);
86*18815Ssklower 		break;
87*18815Ssklower #endif
885122Swnj 	default:
895122Swnj 		splx(s);
906337Ssam 		printf("lo%d: can't handle af%d\n", ifp->if_unit,
916337Ssam 			dst->sa_family);
926337Ssam 		m_freem(m0);
936544Sfeldman 		return (EAFNOSUPPORT);
945122Swnj 	}
955172Swnj 	ifp->if_ipackets++;
965122Swnj 	splx(s);
976544Sfeldman 	return (0);
985122Swnj }
9913066Ssam 
10013066Ssam /*
10113066Ssam  * Process an ioctl request.
10213066Ssam  */
10318370Skarels /* ARGSUSED */
10413066Ssam loioctl(ifp, cmd, data)
10513066Ssam 	register struct ifnet *ifp;
10613066Ssam 	int cmd;
10713066Ssam 	caddr_t data;
10813066Ssam {
10918370Skarels 	int error = 0;
11013066Ssam 
11113066Ssam 	switch (cmd) {
11213066Ssam 
11313066Ssam 	case SIOCSIFADDR:
11418370Skarels 		ifp->if_flags |= IFF_UP;
11518370Skarels 		/*
11618370Skarels 		 * Everything else is done at a higher level.
11718370Skarels 		 */
11813066Ssam 		break;
11913066Ssam 
12013066Ssam 	default:
12113066Ssam 		error = EINVAL;
12213066Ssam 	}
12313066Ssam 	return (error);
12413066Ssam }
125