xref: /csrg-svn/sys/net/if_loop.c (revision 13066)
1*13066Ssam /*	if_loop.c	4.19	83/06/13	*/
25122Swnj 
35122Swnj /*
45122Swnj  * Loopback interface driver for protocol testing and timing.
55122Swnj  */
65122Swnj 
75122Swnj #include "../h/param.h"
85122Swnj #include "../h/systm.h"
95122Swnj #include "../h/mbuf.h"
105122Swnj #include "../h/socket.h"
1110907Ssam #include "../h/errno.h"
12*13066Ssam #include "../h/ioctl.h"
1310907Ssam 
1410907Ssam #include "../net/if.h"
1510907Ssam #include "../net/netisr.h"
1610907Ssam #include "../net/route.h"
1710907Ssam 
188397Swnj #include "../netinet/in.h"
198397Swnj #include "../netinet/in_systm.h"
208397Swnj #include "../netinet/ip.h"
218397Swnj #include "../netinet/ip_var.h"
225122Swnj 
2312460Ssam #ifdef vax
2412460Ssam #include "../vax/mtpr.h"
2512460Ssam #endif
2610907Ssam 
275296Sroot #define	LONET	127
2812761Ssam #define	LOHOST	1			/* can't be 0, that's broadcast */
295207Swnj #define	LOMTU	(1024+512)
305122Swnj 
315122Swnj struct	ifnet loif;
32*13066Ssam int	looutput(), loioctl();
335122Swnj 
345122Swnj loattach()
355122Swnj {
365122Swnj 	register struct ifnet *ifp = &loif;
376337Ssam 	register struct sockaddr_in *sin;
385122Swnj 
395172Swnj 	ifp->if_name = "lo";
405122Swnj 	ifp->if_mtu = LOMTU;
415122Swnj 	ifp->if_net = LONET;
4212761Ssam 	ifp->if_host[0] = LOHOST;
436337Ssam 	sin = (struct sockaddr_in *)&ifp->if_addr;
446337Ssam 	sin->sin_family = AF_INET;
45*13066Ssam 	sin->sin_addr = if_makeaddr(LONET, LOHOST);
46*13066Ssam 	ifp->if_flags = IFF_UP | IFF_RUNNING;
47*13066Ssam 	ifp->if_ioctl = loioctl;
485122Swnj 	ifp->if_output = looutput;
495161Swnj 	if_attach(ifp);
507154Swnj 	if_rtinit(ifp, RTF_UP);
515122Swnj }
525122Swnj 
536337Ssam looutput(ifp, m0, dst)
545122Swnj 	struct ifnet *ifp;
555122Swnj 	struct mbuf *m0;
566337Ssam 	struct sockaddr *dst;
575122Swnj {
585122Swnj 	int s = splimp();
596209Swnj 	register struct ifqueue *ifq;
605122Swnj 
615172Swnj 	ifp->if_opackets++;
626337Ssam 	switch (dst->sa_family) {
635122Swnj 
645122Swnj #ifdef INET
656337Ssam 	case AF_INET:
666209Swnj 		ifq = &ipintrq;
676209Swnj 		if (IF_QFULL(ifq)) {
686209Swnj 			IF_DROP(ifq);
696337Ssam 			m_freem(m0);
706209Swnj 			splx(s);
716544Sfeldman 			return (ENOBUFS);
726209Swnj 		}
736209Swnj 		IF_ENQUEUE(ifq, m0);
746262Swnj 		schednetisr(NETISR_IP);
755122Swnj 		break;
765122Swnj #endif
775122Swnj 	default:
785122Swnj 		splx(s);
796337Ssam 		printf("lo%d: can't handle af%d\n", ifp->if_unit,
806337Ssam 			dst->sa_family);
816337Ssam 		m_freem(m0);
826544Sfeldman 		return (EAFNOSUPPORT);
835122Swnj 	}
845172Swnj 	ifp->if_ipackets++;
855122Swnj 	splx(s);
866544Sfeldman 	return (0);
875122Swnj }
88*13066Ssam 
89*13066Ssam /*
90*13066Ssam  * Process an ioctl request.
91*13066Ssam  */
92*13066Ssam loioctl(ifp, cmd, data)
93*13066Ssam 	register struct ifnet *ifp;
94*13066Ssam 	int cmd;
95*13066Ssam 	caddr_t data;
96*13066Ssam {
97*13066Ssam 	struct ifreq *ifr = (struct ifreq *)data;
98*13066Ssam 	struct sockaddr_in *sin;
99*13066Ssam 	int s = splimp(), error = 0;
100*13066Ssam 
101*13066Ssam 	switch (cmd) {
102*13066Ssam 
103*13066Ssam 	case SIOCSIFADDR:
104*13066Ssam 		if (ifp->if_flags & IFF_RUNNING)
105*13066Ssam 			if_rtinit(ifp, -1);	/* delete previous route */
106*13066Ssam 		ifp->if_addr = ifr->ifr_addr;
107*13066Ssam 		sin = (struct sockaddr_in *)&ifp->if_addr;
108*13066Ssam 		ifp->if_net = in_netof(sin->sin_addr);
109*13066Ssam 		ifp->if_host[0] = in_lnaof(sin->sin_addr);
110*13066Ssam 		if_rtinit(ifp, RTF_UP);
111*13066Ssam 		break;
112*13066Ssam 
113*13066Ssam 	default:
114*13066Ssam 		error = EINVAL;
115*13066Ssam 	}
116*13066Ssam 	splx(s);
117*13066Ssam 	return (error);
118*13066Ssam }
119