xref: /csrg-svn/sys/net/if_loop.c (revision 45523)
123174Smckusick /*
229071Skarels  * Copyright (c) 1982, 1986 Regents of the University of California.
333183Sbostic  * All rights reserved.
423174Smckusick  *
544464Sbostic  * %sccs.include.redist.c%
633183Sbostic  *
7*45523Ssklower  *	@(#)if_loop.c	7.12 (Berkeley) 11/06/90
823174Smckusick  */
95122Swnj 
105122Swnj /*
115122Swnj  * Loopback interface driver for protocol testing and timing.
125122Swnj  */
135122Swnj 
1417058Sbloom #include "param.h"
1517058Sbloom #include "systm.h"
1617058Sbloom #include "mbuf.h"
1717058Sbloom #include "socket.h"
1817058Sbloom #include "errno.h"
1917058Sbloom #include "ioctl.h"
2010907Ssam 
2110907Ssam #include "../net/if.h"
2238988Skarels #include "../net/if_types.h"
2310907Ssam #include "../net/netisr.h"
2410907Ssam #include "../net/route.h"
2510907Ssam 
2637500Smckusick #include "machine/mtpr.h"
2729922Skarels 
2824771Skarels #ifdef	INET
2924771Skarels #include "../netinet/in.h"
3024771Skarels #include "../netinet/in_systm.h"
3129071Skarels #include "../netinet/in_var.h"
3224771Skarels #include "../netinet/ip.h"
3324771Skarels #endif
345122Swnj 
3518815Ssklower #ifdef NS
3618815Ssklower #include "../netns/ns.h"
3718815Ssklower #include "../netns/ns_if.h"
3818815Ssklower #endif
3918815Ssklower 
4037472Ssklower #ifdef ISO
4137472Ssklower #include "../netiso/iso.h"
4237472Ssklower #include "../netiso/iso_var.h"
4337472Ssklower #endif
4437472Ssklower 
45*45523Ssklower #ifdef CCITT
46*45523Ssklower #include "../netccitt/x25.h"
47*45523Ssklower #include "../netccitt/hdlc.h"
48*45523Ssklower #include "../netccitt/hd_var.h"
49*45523Ssklower #endif
50*45523Ssklower 
515207Swnj #define	LOMTU	(1024+512)
525122Swnj 
535122Swnj struct	ifnet loif;
5413066Ssam int	looutput(), loioctl();
555122Swnj 
565122Swnj loattach()
575122Swnj {
585122Swnj 	register struct ifnet *ifp = &loif;
595122Swnj 
605172Swnj 	ifp->if_name = "lo";
615122Swnj 	ifp->if_mtu = LOMTU;
6226091Skarels 	ifp->if_flags = IFF_LOOPBACK;
6313066Ssam 	ifp->if_ioctl = loioctl;
645122Swnj 	ifp->if_output = looutput;
6537472Ssklower 	ifp->if_type = IFT_LOOP;
6637472Ssklower 	ifp->if_hdrlen = 0;
6737472Ssklower 	ifp->if_addrlen = 0;
685161Swnj 	if_attach(ifp);
695122Swnj }
705122Swnj 
7145198Ssklower looutput(ifp, m, dst, rt)
725122Swnj 	struct ifnet *ifp;
7335795Skarels 	register struct mbuf *m;
746337Ssam 	struct sockaddr *dst;
7545198Ssklower 	register struct rtentry *rt;
765122Swnj {
77*45523Ssklower 	int s, isr;
78*45523Ssklower 	register struct ifqueue *ifq = 0;
795122Swnj 
8035795Skarels 	if ((m->m_flags & M_PKTHDR) == 0)
8135795Skarels 		panic("looutput no HDR");
8235795Skarels 	m->m_pkthdr.rcvif = ifp;
8335795Skarels 
8445198Ssklower 	if (rt && rt->rt_flags & RTF_REJECT) {
8545198Ssklower 		m_freem(m);
8645198Ssklower 		return (rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH);
8745198Ssklower 	}
8824771Skarels 	s = splimp();
895172Swnj 	ifp->if_opackets++;
9039187Ssklower 	ifp->if_obytes += m->m_pkthdr.len;
916337Ssam 	switch (dst->sa_family) {
925122Swnj 
935122Swnj #ifdef INET
946337Ssam 	case AF_INET:
956209Swnj 		ifq = &ipintrq;
96*45523Ssklower 		isr = NETISR_IP;
975122Swnj 		break;
985122Swnj #endif
9918815Ssklower #ifdef NS
10018815Ssklower 	case AF_NS:
10118815Ssklower 		ifq = &nsintrq;
102*45523Ssklower 		isr = NETISR_NS;
10318815Ssklower 		break;
10418815Ssklower #endif
10537472Ssklower #ifdef ISO
10637472Ssklower 	case AF_ISO:
10737472Ssklower 		ifq = &clnlintrq;
108*45523Ssklower 		isr = NETISR_ISO;
10937472Ssklower 		break;
11037472Ssklower #endif
111*45523Ssklower #ifdef CCITT
112*45523Ssklower 	case AF_CCITT:
113*45523Ssklower 		ifq = &hdintrq;
114*45523Ssklower 		isr = NETISR_CCITT;
115*45523Ssklower 		break;
116*45523Ssklower #endif
1175122Swnj 	default:
1185122Swnj 		splx(s);
1196337Ssam 		printf("lo%d: can't handle af%d\n", ifp->if_unit,
1206337Ssam 			dst->sa_family);
12135795Skarels 		m_freem(m);
1226544Sfeldman 		return (EAFNOSUPPORT);
1235122Swnj 	}
124*45523Ssklower 	if (IF_QFULL(ifq)) {
125*45523Ssklower 		IF_DROP(ifq);
126*45523Ssklower 		m_freem(m);
127*45523Ssklower 		splx(s);
128*45523Ssklower 		return (ENOBUFS);
129*45523Ssklower 	}
130*45523Ssklower 	IF_ENQUEUE(ifq, m);
131*45523Ssklower 	schednetisr(isr);
1325172Swnj 	ifp->if_ipackets++;
13339187Ssklower 	ifp->if_ibytes += m->m_pkthdr.len;
1345122Swnj 	splx(s);
1356544Sfeldman 	return (0);
1365122Swnj }
13713066Ssam 
13813066Ssam /*
13913066Ssam  * Process an ioctl request.
14013066Ssam  */
14118370Skarels /* ARGSUSED */
14213066Ssam loioctl(ifp, cmd, data)
14313066Ssam 	register struct ifnet *ifp;
14413066Ssam 	int cmd;
14513066Ssam 	caddr_t data;
14613066Ssam {
14718370Skarels 	int error = 0;
14813066Ssam 
14913066Ssam 	switch (cmd) {
15013066Ssam 
151*45523Ssklower #ifdef CCITT
152*45523Ssklower 	case SIOCSIFCONF_X25:
153*45523Ssklower #endif
15413066Ssam 	case SIOCSIFADDR:
15518370Skarels 		ifp->if_flags |= IFF_UP;
15618370Skarels 		/*
15718370Skarels 		 * Everything else is done at a higher level.
15818370Skarels 		 */
15913066Ssam 		break;
16013066Ssam 
16113066Ssam 	default:
16213066Ssam 		error = EINVAL;
16313066Ssam 	}
16413066Ssam 	return (error);
16513066Ssam }
166