xref: /csrg-svn/sys/net/if_loop.c (revision 35795)
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*35795Skarels  *	@(#)if_loop.c	7.5 (Berkeley) 10/12/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 
66*35795Skarels struct mbuf *Loop_Sanity;
67*35795Skarels 
68*35795Skarels looutput(ifp, m, dst)
695122Swnj 	struct ifnet *ifp;
70*35795Skarels 	register struct mbuf *m;
716337Ssam 	struct sockaddr *dst;
725122Swnj {
7324771Skarels 	int s;
746209Swnj 	register struct ifqueue *ifq;
755122Swnj 
76*35795Skarels 	if ((m->m_flags & M_PKTHDR) == 0)
77*35795Skarels 		panic("looutput no HDR");
78*35795Skarels 	m->m_pkthdr.rcvif = ifp;
79*35795Skarels 
80*35795Skarels {struct mbuf *mm; int mlen = 0;
81*35795Skarels for (mm = m; m; m = m->m_next) /* XXX debugging code -- sklwoer */
82*35795Skarels     mlen += m->m_len;
83*35795Skarels m = mm;
84*35795Skarels if (mlen != m->m_pkthdr.len) {
85*35795Skarels 	if (Loop_Sanity)
86*35795Skarels 		m_freem(Loop_Sanity);
87*35795Skarels 	Loop_Sanity = m_copy(m, 0, M_COPYALL);
88*35795Skarels }
89*35795Skarels }
90*35795Skarels 
9124771Skarels 	s = splimp();
925172Swnj 	ifp->if_opackets++;
936337Ssam 	switch (dst->sa_family) {
945122Swnj 
955122Swnj #ifdef INET
966337Ssam 	case AF_INET:
976209Swnj 		ifq = &ipintrq;
986209Swnj 		if (IF_QFULL(ifq)) {
996209Swnj 			IF_DROP(ifq);
100*35795Skarels 			m_freem(m);
1016209Swnj 			splx(s);
1026544Sfeldman 			return (ENOBUFS);
1036209Swnj 		}
104*35795Skarels 		IF_ENQUEUE(ifq, m);
1056262Swnj 		schednetisr(NETISR_IP);
1065122Swnj 		break;
1075122Swnj #endif
10818815Ssklower #ifdef NS
10918815Ssklower 	case AF_NS:
11018815Ssklower 		ifq = &nsintrq;
11118815Ssklower 		if (IF_QFULL(ifq)) {
11218815Ssklower 			IF_DROP(ifq);
113*35795Skarels 			m_freem(m);
11418815Ssklower 			splx(s);
11518815Ssklower 			return (ENOBUFS);
11618815Ssklower 		}
117*35795Skarels 		IF_ENQUEUE(ifq, m);
11818815Ssklower 		schednetisr(NETISR_NS);
11918815Ssklower 		break;
12018815Ssklower #endif
1215122Swnj 	default:
1225122Swnj 		splx(s);
1236337Ssam 		printf("lo%d: can't handle af%d\n", ifp->if_unit,
1246337Ssam 			dst->sa_family);
125*35795Skarels 		m_freem(m);
1266544Sfeldman 		return (EAFNOSUPPORT);
1275122Swnj 	}
1285172Swnj 	ifp->if_ipackets++;
1295122Swnj 	splx(s);
1306544Sfeldman 	return (0);
1315122Swnj }
13213066Ssam 
13313066Ssam /*
13413066Ssam  * Process an ioctl request.
13513066Ssam  */
13618370Skarels /* ARGSUSED */
13713066Ssam loioctl(ifp, cmd, data)
13813066Ssam 	register struct ifnet *ifp;
13913066Ssam 	int cmd;
14013066Ssam 	caddr_t data;
14113066Ssam {
14218370Skarels 	int error = 0;
14313066Ssam 
14413066Ssam 	switch (cmd) {
14513066Ssam 
14613066Ssam 	case SIOCSIFADDR:
14718370Skarels 		ifp->if_flags |= IFF_UP;
14818370Skarels 		/*
14918370Skarels 		 * Everything else is done at a higher level.
15018370Skarels 		 */
15113066Ssam 		break;
15213066Ssam 
15313066Ssam 	default:
15413066Ssam 		error = EINVAL;
15513066Ssam 	}
15613066Ssam 	return (error);
15713066Ssam }
158