xref: /csrg-svn/sys/net/if_loop.c (revision 38988)
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
634844Sbostic  * provided that the above copyright notice and this paragraph are
734844Sbostic  * duplicated in all such forms and that any documentation,
834844Sbostic  * advertising materials, and other materials related to such
934844Sbostic  * distribution and use acknowledge that the software was developed
1034844Sbostic  * by the University of California, Berkeley.  The name of the
1134844Sbostic  * University may not be used to endorse or promote products derived
1234844Sbostic  * from this software without specific prior written permission.
1334844Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1434844Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1534844Sbostic  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1633183Sbostic  *
17*38988Skarels  *	@(#)if_loop.c	7.8 (Berkeley) 09/04/89
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"
32*38988Skarels #include "../net/if_types.h"
3310907Ssam #include "../net/netisr.h"
3410907Ssam #include "../net/route.h"
3510907Ssam 
3637500Smckusick #include "machine/mtpr.h"
3729922Skarels 
3824771Skarels #ifdef	INET
3924771Skarels #include "../netinet/in.h"
4024771Skarels #include "../netinet/in_systm.h"
4129071Skarels #include "../netinet/in_var.h"
4224771Skarels #include "../netinet/ip.h"
4324771Skarels #endif
445122Swnj 
4518815Ssklower #ifdef NS
4618815Ssklower #include "../netns/ns.h"
4718815Ssklower #include "../netns/ns_if.h"
4818815Ssklower #endif
4918815Ssklower 
5037472Ssklower #ifdef ISO
5137472Ssklower #include "../netiso/iso.h"
5237472Ssklower #include "../netiso/iso_var.h"
5337472Ssklower #endif
5437472Ssklower 
555207Swnj #define	LOMTU	(1024+512)
565122Swnj 
575122Swnj struct	ifnet loif;
5813066Ssam int	looutput(), loioctl();
595122Swnj 
605122Swnj loattach()
615122Swnj {
625122Swnj 	register struct ifnet *ifp = &loif;
635122Swnj 
645172Swnj 	ifp->if_name = "lo";
655122Swnj 	ifp->if_mtu = LOMTU;
6626091Skarels 	ifp->if_flags = IFF_LOOPBACK;
6713066Ssam 	ifp->if_ioctl = loioctl;
685122Swnj 	ifp->if_output = looutput;
6937472Ssklower 	ifp->if_type = IFT_LOOP;
7037472Ssklower 	ifp->if_hdrlen = 0;
7137472Ssklower 	ifp->if_addrlen = 0;
725161Swnj 	if_attach(ifp);
735122Swnj }
745122Swnj 
7535795Skarels struct mbuf *Loop_Sanity;
7635795Skarels 
7735795Skarels looutput(ifp, m, dst)
785122Swnj 	struct ifnet *ifp;
7935795Skarels 	register struct mbuf *m;
806337Ssam 	struct sockaddr *dst;
815122Swnj {
8224771Skarels 	int s;
836209Swnj 	register struct ifqueue *ifq;
845122Swnj 
8535795Skarels 	if ((m->m_flags & M_PKTHDR) == 0)
8635795Skarels 		panic("looutput no HDR");
8735795Skarels 	m->m_pkthdr.rcvif = ifp;
8835795Skarels 
8935795Skarels {struct mbuf *mm; int mlen = 0;
9037472Ssklower for (mm = m; m; m = m->m_next) /* XXX debugging code -- sklower */
9135795Skarels     mlen += m->m_len;
9235795Skarels m = mm;
9335795Skarels if (mlen != m->m_pkthdr.len) {
9435795Skarels 	if (Loop_Sanity)
9535795Skarels 		m_freem(Loop_Sanity);
9637472Ssklower 	Loop_Sanity = m_copy(m, 0, (int)M_COPYALL);
9735795Skarels }
9835795Skarels }
9935795Skarels 
10024771Skarels 	s = splimp();
1015172Swnj 	ifp->if_opackets++;
1026337Ssam 	switch (dst->sa_family) {
1035122Swnj 
1045122Swnj #ifdef INET
1056337Ssam 	case AF_INET:
1066209Swnj 		ifq = &ipintrq;
1076209Swnj 		if (IF_QFULL(ifq)) {
1086209Swnj 			IF_DROP(ifq);
10935795Skarels 			m_freem(m);
1106209Swnj 			splx(s);
1116544Sfeldman 			return (ENOBUFS);
1126209Swnj 		}
11335795Skarels 		IF_ENQUEUE(ifq, m);
1146262Swnj 		schednetisr(NETISR_IP);
1155122Swnj 		break;
1165122Swnj #endif
11718815Ssklower #ifdef NS
11818815Ssklower 	case AF_NS:
11918815Ssklower 		ifq = &nsintrq;
12018815Ssklower 		if (IF_QFULL(ifq)) {
12118815Ssklower 			IF_DROP(ifq);
12235795Skarels 			m_freem(m);
12318815Ssklower 			splx(s);
12418815Ssklower 			return (ENOBUFS);
12518815Ssklower 		}
12635795Skarels 		IF_ENQUEUE(ifq, m);
12718815Ssklower 		schednetisr(NETISR_NS);
12818815Ssklower 		break;
12918815Ssklower #endif
13037472Ssklower #ifdef ISO
13137472Ssklower 	case AF_ISO:
13237472Ssklower 		ifq = &clnlintrq;
13337472Ssklower 		if (IF_QFULL(ifq)) {
13437472Ssklower 			IF_DROP(ifq);
13537472Ssklower 			m_freem(m);
13637472Ssklower 			splx(s);
13737472Ssklower 			return (ENOBUFS);
13837472Ssklower 		}
13937472Ssklower 		IF_ENQUEUE(ifq, m);
14037472Ssklower 		schednetisr(NETISR_ISO);
14137472Ssklower 		break;
14237472Ssklower #endif
1435122Swnj 	default:
1445122Swnj 		splx(s);
1456337Ssam 		printf("lo%d: can't handle af%d\n", ifp->if_unit,
1466337Ssam 			dst->sa_family);
14735795Skarels 		m_freem(m);
1486544Sfeldman 		return (EAFNOSUPPORT);
1495122Swnj 	}
1505172Swnj 	ifp->if_ipackets++;
1515122Swnj 	splx(s);
1526544Sfeldman 	return (0);
1535122Swnj }
15413066Ssam 
15513066Ssam /*
15613066Ssam  * Process an ioctl request.
15713066Ssam  */
15818370Skarels /* ARGSUSED */
15913066Ssam loioctl(ifp, cmd, data)
16013066Ssam 	register struct ifnet *ifp;
16113066Ssam 	int cmd;
16213066Ssam 	caddr_t data;
16313066Ssam {
16418370Skarels 	int error = 0;
16513066Ssam 
16613066Ssam 	switch (cmd) {
16713066Ssam 
16813066Ssam 	case SIOCSIFADDR:
16918370Skarels 		ifp->if_flags |= IFF_UP;
17018370Skarels 		/*
17118370Skarels 		 * Everything else is done at a higher level.
17218370Skarels 		 */
17313066Ssam 		break;
17413066Ssam 
17513066Ssam 	default:
17613066Ssam 		error = EINVAL;
17713066Ssam 	}
17813066Ssam 	return (error);
17913066Ssam }
180