xref: /386bsd/usr/src/kernel/loop/loop.c (revision a2142627)
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, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *	This product includes software developed by the University of
16  *	California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  *	@(#)if_loop.c	7.13 (Berkeley) 4/26/91
34  */
35 
36 /*
37  * Loopback interface driver for protocol testing and timing.
38  */
39 
40 #include "sys/param.h"
41 #include "sys/socket.h"
42 #include "sys/ioctl.h"
43 #include "sys/errno.h"
44 #include "mbuf.h"
45 #include "modconfig.h"
46 
47 #include "machine/cpu.h"
48 
49 #include "if.h"
50 #include "if_types.h"
51 #include "netisr.h"
52 #include "route.h"
53 
54 #ifdef	INET
55 #include "in.h"
56 #include "in_systm.h"
57 #include "in_var.h"
58 #include "ip.h"
59 #endif
60 
61 #ifdef NS
62 #include "ns.h"
63 #include "ns_if.h"
64 #endif
65 
66 #ifdef ISO
67 #include "iso.h"
68 #include "iso_var.h"
69 #endif
70 
71 #define	LOMTU	(1024+512)
72 
73 struct	ifnet loif;
74 int looutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
75 	struct rtentry *rt);
76 int	loioctl();
77 
78 loattach()
79 {
80 	register struct ifnet *ifp = &loif;
81 
82 	ifp->if_name = "lo";
83 	ifp->if_mtu = LOMTU;
84 	ifp->if_flags = IFF_LOOPBACK;
85 	ifp->if_ioctl = loioctl;
86 	ifp->if_output = looutput;
87 	ifp->if_type = IFT_LOOP;
88 	ifp->if_hdrlen = 0;
89 	ifp->if_addrlen = 0;
90 	if_attach(ifp);
91 }
92 
93 int
94 looutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
95 	struct rtentry *rt)
96 {
97 	int s, isr;
98 	register struct ifqueue *ifq = 0;
99 
100 /* printf("\nlo:%d ", getit(0,0)); */
101 	if ((m->m_flags & M_PKTHDR) == 0)
102 		panic("looutput no HDR");
103 	m->m_pkthdr.rcvif = ifp;
104 #ifdef	PKT_TRACE
105 { unsigned x = getticks();
106 printf("lo:%d ", x - m->m_pkthdr.time);
107 x = m->m_pkthdr.time;
108 }
109 #endif
110 
111 	if (rt && rt->rt_flags & RTF_REJECT) {
112 		m_freem(m);
113 		return (rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH);
114 	}
115 	ifp->if_opackets++;
116 	ifp->if_obytes += m->m_pkthdr.len;
117 	switch (dst->sa_family) {
118 
119 #ifdef INET
120 	case AF_INET:
121 		ifq = &ipintrq;
122 		isr = NETISR_IP;
123 		break;
124 #endif
125 #ifdef NS
126 	case AF_NS:
127 		ifq = &nsintrq;
128 		isr = NETISR_NS;
129 		break;
130 #endif
131 #ifdef ISO
132 	case AF_ISO:
133 		ifq = &clnlintrq;
134 		isr = NETISR_ISO;
135 		break;
136 #endif
137 	default:
138 		printf("lo%d: can't handle af%d\n", ifp->if_unit,
139 			dst->sa_family);
140 		m_freem(m);
141 		return (EAFNOSUPPORT);
142 	}
143 	s = splimp();
144 	if (IF_QFULL(ifq)) {
145 		IF_DROP(ifq);
146 		m_freem(m);
147 		splx(s);
148 		return (ENOBUFS);
149 	}
150 	IF_ENQUEUE(ifq, m);
151 	schednetisr(isr);
152 	ifp->if_ipackets++;
153 	ifp->if_ibytes += m->m_pkthdr.len;
154 	splx(s);
155 	return (0);
156 }
157 
158 /* ARGSUSED */
159 lortrequest(cmd, rt, sa)
160 struct rtentry *rt;
161 struct sockaddr *sa;
162 {
163 	if (rt)
164 		rt->rt_rmx.rmx_mtu = LOMTU;
165 }
166 
167 /*
168  * Process an ioctl request.
169  */
170 /* ARGSUSED */
171 loioctl(ifp, cmd, data)
172 	register struct ifnet *ifp;
173 	int cmd;
174 	caddr_t data;
175 {
176 	register struct ifaddr *ifa;
177 	int error = 0;
178 
179 	switch (cmd) {
180 
181 	case SIOCSIFADDR:
182 		ifp->if_flags |= IFF_UP;
183 		ifa = (struct ifaddr *)data;
184 		if (ifa != 0 && ifa->ifa_addr->sa_family == AF_ISO)
185 			ifa->ifa_rtrequest = lortrequest;
186 		/*
187 		 * Everything else is done at a higher level.
188 		 */
189 		break;
190 
191 	default:
192 		error = EINVAL;
193 	}
194 	return (error);
195 }
196 
197 LOCALNET_MODCONFIG() {
198 	loattach();
199 	route_looutput = looutput;
200 }
201 
202