if_loop.c revision 1.2 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 "param.h"
41 #include "systm.h"
42 #include "mbuf.h"
43 #include "socket.h"
44 #include "errno.h"
45 #include "ioctl.h"
46
47 #include "../net/if.h"
48 #include "../net/if_types.h"
49 #include "../net/netisr.h"
50 #include "../net/route.h"
51
52 #include "machine/mtpr.h"
53
54 #ifdef INET
55 #include "../netinet/in.h"
56 #include "../netinet/in_systm.h"
57 #include "../netinet/in_var.h"
58 #include "../netinet/ip.h"
59 #endif
60
61 #ifdef NS
62 #include "../netns/ns.h"
63 #include "../netns/ns_if.h"
64 #endif
65
66 #ifdef ISO
67 #include "../netiso/iso.h"
68 #include "../netiso/iso_var.h"
69 #endif
70
71 #include "bpfilter.h"
72 #if NBPFILTER > 0
73 #include <sys/time.h>
74 #include <net/bpf.h>
75 static caddr_t lo_bpf;
76 #endif
77
78 #define LOMTU (1024+512)
79
80 struct ifnet loif;
81 int looutput(), loioctl();
82
83 loattach()
84 {
85 register struct ifnet *ifp = &loif;
86
87 ifp->if_name = "lo";
88 ifp->if_mtu = LOMTU;
89 ifp->if_flags = IFF_LOOPBACK;
90 ifp->if_ioctl = loioctl;
91 ifp->if_output = looutput;
92 ifp->if_type = IFT_LOOP;
93 ifp->if_hdrlen = 0;
94 ifp->if_addrlen = 0;
95 if_attach(ifp);
96 #if NBPFILTER > 0
97 bpfattach(&lo_bpf, ifp, DLT_NULL, sizeof(u_int));
98 #endif
99 }
100
101 looutput(ifp, m, dst, rt)
102 struct ifnet *ifp;
103 register struct mbuf *m;
104 struct sockaddr *dst;
105 register struct rtentry *rt;
106 {
107 int s, isr;
108 register struct ifqueue *ifq = 0;
109
110 if ((m->m_flags & M_PKTHDR) == 0)
111 panic("looutput no HDR");
112 #if NBPFILTER > 0
113 if (lo_bpf) {
114 /*
115 * We need to prepend the address family as
116 * a four byte field. Cons up a dummy header
117 * to pacify bpf. This is safe because bpf
118 * will only read from the mbuf (i.e., it won't
119 * try to free it or keep a pointer to it).
120 */
121 struct mbuf m0;
122 u_int af = dst->sa_family;
123
124 m0.m_next = m;
125 m0.m_len = 4;
126 m0.m_data = (char *)⁡
127
128 bpf_mtap(lo_bpf, &m0);
129 }
130 #endif
131 m->m_pkthdr.rcvif = ifp;
132
133 if (rt && rt->rt_flags & RTF_REJECT) {
134 m_freem(m);
135 return (rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH);
136 }
137 ifp->if_opackets++;
138 ifp->if_obytes += m->m_pkthdr.len;
139 switch (dst->sa_family) {
140
141 #ifdef INET
142 case AF_INET:
143 ifq = &ipintrq;
144 isr = NETISR_IP;
145 break;
146 #endif
147 #ifdef NS
148 case AF_NS:
149 ifq = &nsintrq;
150 isr = NETISR_NS;
151 break;
152 #endif
153 #ifdef ISO
154 case AF_ISO:
155 ifq = &clnlintrq;
156 isr = NETISR_ISO;
157 break;
158 #endif
159 default:
160 printf("lo%d: can't handle af%d\n", ifp->if_unit,
161 dst->sa_family);
162 m_freem(m);
163 return (EAFNOSUPPORT);
164 }
165 s = splimp();
166 if (IF_QFULL(ifq)) {
167 IF_DROP(ifq);
168 m_freem(m);
169 splx(s);
170 return (ENOBUFS);
171 }
172 IF_ENQUEUE(ifq, m);
173 schednetisr(isr);
174 ifp->if_ipackets++;
175 ifp->if_ibytes += m->m_pkthdr.len;
176 splx(s);
177 return (0);
178 }
179
180 /* ARGSUSED */
181 lortrequest(cmd, rt, sa)
182 struct rtentry *rt;
183 struct sockaddr *sa;
184 {
185 if (rt)
186 rt->rt_rmx.rmx_mtu = LOMTU;
187 }
188
189 /*
190 * Process an ioctl request.
191 */
192 /* ARGSUSED */
193 loioctl(ifp, cmd, data)
194 register struct ifnet *ifp;
195 int cmd;
196 caddr_t data;
197 {
198 register struct ifaddr *ifa;
199 int error = 0;
200
201 switch (cmd) {
202
203 case SIOCSIFADDR:
204 ifp->if_flags |= IFF_UP;
205 ifa = (struct ifaddr *)data;
206 if (ifa != 0 && ifa->ifa_addr->sa_family == AF_ISO)
207 ifa->ifa_rtrequest = lortrequest;
208 /*
209 * Everything else is done at a higher level.
210 */
211 break;
212
213 default:
214 error = EINVAL;
215 }
216 return (error);
217 }
218