xref: /csrg-svn/sys/net/if_loop.c (revision 35795)
1 /*
2  * Copyright (c) 1982, 1986 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  *
17  *	@(#)if_loop.c	7.5 (Berkeley) 10/12/88
18  */
19 
20 /*
21  * Loopback interface driver for protocol testing and timing.
22  */
23 
24 #include "param.h"
25 #include "systm.h"
26 #include "mbuf.h"
27 #include "socket.h"
28 #include "errno.h"
29 #include "ioctl.h"
30 
31 #include "../net/if.h"
32 #include "../net/netisr.h"
33 #include "../net/route.h"
34 
35 #include "../machine/mtpr.h"
36 
37 #ifdef	INET
38 #include "../netinet/in.h"
39 #include "../netinet/in_systm.h"
40 #include "../netinet/in_var.h"
41 #include "../netinet/ip.h"
42 #endif
43 
44 #ifdef NS
45 #include "../netns/ns.h"
46 #include "../netns/ns_if.h"
47 #endif
48 
49 #define	LOMTU	(1024+512)
50 
51 struct	ifnet loif;
52 int	looutput(), loioctl();
53 
54 loattach()
55 {
56 	register struct ifnet *ifp = &loif;
57 
58 	ifp->if_name = "lo";
59 	ifp->if_mtu = LOMTU;
60 	ifp->if_flags = IFF_LOOPBACK;
61 	ifp->if_ioctl = loioctl;
62 	ifp->if_output = looutput;
63 	if_attach(ifp);
64 }
65 
66 struct mbuf *Loop_Sanity;
67 
68 looutput(ifp, m, dst)
69 	struct ifnet *ifp;
70 	register struct mbuf *m;
71 	struct sockaddr *dst;
72 {
73 	int s;
74 	register struct ifqueue *ifq;
75 
76 	if ((m->m_flags & M_PKTHDR) == 0)
77 		panic("looutput no HDR");
78 	m->m_pkthdr.rcvif = ifp;
79 
80 {struct mbuf *mm; int mlen = 0;
81 for (mm = m; m; m = m->m_next) /* XXX debugging code -- sklwoer */
82     mlen += m->m_len;
83 m = mm;
84 if (mlen != m->m_pkthdr.len) {
85 	if (Loop_Sanity)
86 		m_freem(Loop_Sanity);
87 	Loop_Sanity = m_copy(m, 0, M_COPYALL);
88 }
89 }
90 
91 	s = splimp();
92 	ifp->if_opackets++;
93 	switch (dst->sa_family) {
94 
95 #ifdef INET
96 	case AF_INET:
97 		ifq = &ipintrq;
98 		if (IF_QFULL(ifq)) {
99 			IF_DROP(ifq);
100 			m_freem(m);
101 			splx(s);
102 			return (ENOBUFS);
103 		}
104 		IF_ENQUEUE(ifq, m);
105 		schednetisr(NETISR_IP);
106 		break;
107 #endif
108 #ifdef NS
109 	case AF_NS:
110 		ifq = &nsintrq;
111 		if (IF_QFULL(ifq)) {
112 			IF_DROP(ifq);
113 			m_freem(m);
114 			splx(s);
115 			return (ENOBUFS);
116 		}
117 		IF_ENQUEUE(ifq, m);
118 		schednetisr(NETISR_NS);
119 		break;
120 #endif
121 	default:
122 		splx(s);
123 		printf("lo%d: can't handle af%d\n", ifp->if_unit,
124 			dst->sa_family);
125 		m_freem(m);
126 		return (EAFNOSUPPORT);
127 	}
128 	ifp->if_ipackets++;
129 	splx(s);
130 	return (0);
131 }
132 
133 /*
134  * Process an ioctl request.
135  */
136 /* ARGSUSED */
137 loioctl(ifp, cmd, data)
138 	register struct ifnet *ifp;
139 	int cmd;
140 	caddr_t data;
141 {
142 	int error = 0;
143 
144 	switch (cmd) {
145 
146 	case SIOCSIFADDR:
147 		ifp->if_flags |= IFF_UP;
148 		/*
149 		 * Everything else is done at a higher level.
150 		 */
151 		break;
152 
153 	default:
154 		error = EINVAL;
155 	}
156 	return (error);
157 }
158