1/* 2 * Copyright (c) 1982, 1986, 1993 3 * The Regents of the University of California. 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 * 4. Neither the name of the University nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * @(#)if_loop.c 8.2 (Berkeley) 1/9/95
|
30 * $FreeBSD: head/sys/net/if_loop.c 128209 2004-04-14 00:57:49Z brooks $
|
30 * $FreeBSD: head/sys/net/if_loop.c 130933 2004-06-22 20:13:25Z brooks $ |
31 */ 32 33/* 34 * Loopback interface driver for protocol testing and timing. 35 */ 36 37#include "opt_atalk.h" 38#include "opt_inet.h" 39#include "opt_inet6.h" 40#include "opt_ipx.h" 41#include "opt_mac.h" 42 43#include <sys/param.h> 44#include <sys/systm.h> 45#include <sys/kernel.h> 46#include <sys/mac.h> 47#include <sys/malloc.h> 48#include <sys/mbuf.h> 49#include <sys/module.h> 50#include <machine/bus.h> 51#include <sys/rman.h> 52#include <sys/socket.h> 53#include <sys/sockio.h> 54#include <sys/sysctl.h> 55 56#include <net/if.h>
|
57#include <net/if_clone.h> |
58#include <net/if_types.h> 59#include <net/netisr.h> 60#include <net/route.h> 61#include <net/bpf.h> 62#include <net/bpfdesc.h> 63 64#ifdef INET 65#include <netinet/in.h> 66#include <netinet/in_var.h> 67#endif 68 69#ifdef IPX 70#include <netipx/ipx.h> 71#include <netipx/ipx_if.h> 72#endif 73 74#ifdef INET6 75#ifndef INET 76#include <netinet/in.h> 77#endif 78#include <netinet6/in6_var.h> 79#include <netinet/ip6.h> 80#endif 81 82#ifdef NETATALK 83#include <netatalk/at.h> 84#include <netatalk/at_var.h> 85#endif 86 87#ifdef TINY_LOMTU 88#define LOMTU (1024+512) 89#elif defined(LARGE_LOMTU) 90#define LOMTU 131072 91#else 92#define LOMTU 16384 93#endif 94 95#define LONAME "lo" 96 97struct lo_softc { 98 struct ifnet sc_if; /* network-visible interface */ 99 LIST_ENTRY(lo_softc) sc_next; 100}; 101 102int loioctl(struct ifnet *, u_long, caddr_t); 103static void lortrequest(int, struct rtentry *, struct rt_addrinfo *); 104int looutput(struct ifnet *ifp, struct mbuf *m, 105 struct sockaddr *dst, struct rtentry *rt); 106static int lo_clone_create(struct if_clone *, int); 107static void lo_clone_destroy(struct ifnet *); 108 109struct ifnet *loif = NULL; /* Used externally */ 110 111static MALLOC_DEFINE(M_LO, LONAME, "Loopback Interface"); 112 113static struct mtx lo_mtx; 114static LIST_HEAD(lo_list, lo_softc) lo_list; 115
|
115struct if_clone lo_cloner = IF_CLONE_INITIALIZER(LONAME,
116 lo_clone_create, lo_clone_destroy, 1, IF_MAXUNIT);
|
116IFC_SIMPLE_DECLARE(lo, 1); |
117 118static void 119lo_clone_destroy(ifp) 120 struct ifnet *ifp; 121{ 122 struct lo_softc *sc; 123 124 sc = ifp->if_softc; 125 126 /* XXX: destroying lo0 will lead to panics. */ 127 KASSERT(loif != ifp, ("%s: destroying lo0", __func__)); 128 129 mtx_lock(&lo_mtx); 130 LIST_REMOVE(sc, sc_next); 131 mtx_unlock(&lo_mtx); 132 bpfdetach(ifp); 133 if_detach(ifp); 134 free(sc, M_LO); 135} 136 137static int 138lo_clone_create(ifc, unit) 139 struct if_clone *ifc; 140 int unit; 141{ 142 struct lo_softc *sc; 143 144 MALLOC(sc, struct lo_softc *, sizeof(*sc), M_LO, M_WAITOK | M_ZERO); 145 146 if_initname(&sc->sc_if, ifc->ifc_name, unit); 147 sc->sc_if.if_mtu = LOMTU; 148 sc->sc_if.if_flags = IFF_LOOPBACK | IFF_MULTICAST; 149 sc->sc_if.if_ioctl = loioctl; 150 sc->sc_if.if_output = looutput; 151 sc->sc_if.if_type = IFT_LOOP; 152 sc->sc_if.if_snd.ifq_maxlen = ifqmaxlen; 153 sc->sc_if.if_softc = sc; 154 if_attach(&sc->sc_if); 155 bpfattach(&sc->sc_if, DLT_NULL, sizeof(u_int)); 156 mtx_lock(&lo_mtx); 157 LIST_INSERT_HEAD(&lo_list, sc, sc_next); 158 mtx_unlock(&lo_mtx); 159 if (loif == NULL) 160 loif = &sc->sc_if; 161 162 return (0); 163} 164 165static int 166loop_modevent(module_t mod, int type, void *data) 167{ 168 switch (type) { 169 case MOD_LOAD: 170 mtx_init(&lo_mtx, "lo_mtx", NULL, MTX_DEF); 171 LIST_INIT(&lo_list); 172 if_clone_attach(&lo_cloner); 173 break; 174 case MOD_UNLOAD: 175 printf("loop module unload - not possible for this module type\n"); 176 return EINVAL; 177 } 178 return 0; 179} 180 181static moduledata_t loop_mod = { 182 "loop", 183 loop_modevent, 184 0 185}; 186 187DECLARE_MODULE(loop, loop_mod, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY); 188 189int 190looutput(ifp, m, dst, rt) 191 struct ifnet *ifp; 192 register struct mbuf *m; 193 struct sockaddr *dst; 194 register struct rtentry *rt; 195{ 196 M_ASSERTPKTHDR(m); /* check if we have the packet header */ 197 198 if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) { 199 m_freem(m); 200 return (rt->rt_flags & RTF_BLACKHOLE ? 0 : 201 rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH); 202 } 203 204 ifp->if_opackets++; 205 ifp->if_obytes += m->m_pkthdr.len; 206#if 1 /* XXX */ 207 switch (dst->sa_family) { 208 case AF_INET: 209 case AF_INET6: 210 case AF_IPX: 211 case AF_APPLETALK: 212 break; 213 default: 214 printf("looutput: af=%d unexpected\n", dst->sa_family); 215 m_freem(m); 216 return (EAFNOSUPPORT); 217 } 218#endif 219 return(if_simloop(ifp, m, dst->sa_family, 0)); 220} 221 222/* 223 * if_simloop() 224 * 225 * This function is to support software emulation of hardware loopback, 226 * i.e., for interfaces with the IFF_SIMPLEX attribute. Since they can't 227 * hear their own broadcasts, we create a copy of the packet that we 228 * would normally receive via a hardware loopback. 229 * 230 * This function expects the packet to include the media header of length hlen. 231 */ 232 233int 234if_simloop(ifp, m, af, hlen) 235 struct ifnet *ifp; 236 struct mbuf *m; 237 int af; 238 int hlen; 239{ 240 int isr; 241 242 M_ASSERTPKTHDR(m); 243 m_tag_delete_nonpersistent(m); 244 m->m_pkthdr.rcvif = ifp; 245 246 /* BPF write needs to be handled specially */ 247 if (af == AF_UNSPEC) { 248 KASSERT(m->m_len >= sizeof(int), ("if_simloop: m_len")); 249 af = *(mtod(m, int *)); 250 m->m_len -= sizeof(int); 251 m->m_pkthdr.len -= sizeof(int); 252 m->m_data += sizeof(int); 253 } 254 255 /* Let BPF see incoming packet */ 256 if (ifp->if_bpf) { 257 if (ifp->if_bpf->bif_dlt == DLT_NULL) { 258 u_int32_t af1 = af; /* XXX beware sizeof(af) != 4 */ 259 /* 260 * We need to prepend the address family. 261 */ 262 bpf_mtap2(ifp->if_bpf, &af1, sizeof(af1), m); 263 } else 264 bpf_mtap(ifp->if_bpf, m); 265 } 266 267 /* Strip away media header */ 268 if (hlen > 0) { 269 m_adj(m, hlen); 270#if defined(__alpha__) || defined(__ia64__) || defined(__sparc64__) 271 /* The alpha doesn't like unaligned data. 272 * We move data down in the first mbuf */ 273 if (mtod(m, vm_offset_t) & 3) { 274 KASSERT(hlen >= 3, ("if_simloop: hlen too small")); 275 bcopy(m->m_data, 276 (char *)(mtod(m, vm_offset_t) 277 - (mtod(m, vm_offset_t) & 3)), 278 m->m_len); 279 mtod(m,vm_offset_t) -= (mtod(m, vm_offset_t) & 3); 280 } 281#endif 282 } 283 284 /* Deliver to upper layer protocol */ 285 switch (af) { 286#ifdef INET 287 case AF_INET: 288 isr = NETISR_IP; 289 break; 290#endif 291#ifdef INET6 292 case AF_INET6: 293 m->m_flags |= M_LOOP; 294 isr = NETISR_IPV6; 295 break; 296#endif 297#ifdef IPX 298 case AF_IPX: 299 isr = NETISR_IPX; 300 break; 301#endif 302#ifdef NETATALK 303 case AF_APPLETALK: 304 isr = NETISR_ATALK2; 305 break; 306#endif 307 default: 308 printf("if_simloop: can't handle af=%d\n", af); 309 m_freem(m); 310 return (EAFNOSUPPORT); 311 } 312 ifp->if_ipackets++; 313 ifp->if_ibytes += m->m_pkthdr.len; 314 netisr_queue(isr, m); 315 return (0); 316} 317 318/* ARGSUSED */ 319static void 320lortrequest(cmd, rt, info) 321 int cmd; 322 struct rtentry *rt; 323 struct rt_addrinfo *info; 324{ 325 RT_LOCK_ASSERT(rt); 326 if (rt) 327 rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu; 328} 329 330/* 331 * Process an ioctl request. 332 */ 333/* ARGSUSED */ 334int 335loioctl(ifp, cmd, data) 336 register struct ifnet *ifp; 337 u_long cmd; 338 caddr_t data; 339{ 340 register struct ifaddr *ifa; 341 register struct ifreq *ifr = (struct ifreq *)data; 342 register int error = 0; 343 344 switch (cmd) { 345 346 case SIOCSIFADDR: 347 ifp->if_flags |= IFF_UP | IFF_RUNNING; 348 ifa = (struct ifaddr *)data; 349 ifa->ifa_rtrequest = lortrequest; 350 /* 351 * Everything else is done at a higher level. 352 */ 353 break; 354 355 case SIOCADDMULTI: 356 case SIOCDELMULTI: 357 if (ifr == 0) { 358 error = EAFNOSUPPORT; /* XXX */ 359 break; 360 } 361 switch (ifr->ifr_addr.sa_family) { 362 363#ifdef INET 364 case AF_INET: 365 break; 366#endif 367#ifdef INET6 368 case AF_INET6: 369 break; 370#endif 371 372 default: 373 error = EAFNOSUPPORT; 374 break; 375 } 376 break; 377 378 case SIOCSIFMTU: 379 ifp->if_mtu = ifr->ifr_mtu; 380 break; 381 382 case SIOCSIFFLAGS: 383 break; 384 385 default: 386 error = EINVAL; 387 } 388 return (error); 389}
|