if_loop.c revision 139823
1252190Srpaulo/*- 2252190Srpaulo * Copyright (c) 1982, 1986, 1993 3252190Srpaulo * The Regents of the University of California. All rights reserved. 4252190Srpaulo * 5252190Srpaulo * Redistribution and use in source and binary forms, with or without 6252190Srpaulo * modification, are permitted provided that the following conditions 7252190Srpaulo * are met: 8252190Srpaulo * 1. Redistributions of source code must retain the above copyright 9252190Srpaulo * notice, this list of conditions and the following disclaimer. 10252190Srpaulo * 2. Redistributions in binary form must reproduce the above copyright 11252190Srpaulo * notice, this list of conditions and the following disclaimer in the 12252190Srpaulo * documentation and/or other materials provided with the distribution. 13252190Srpaulo * 4. Neither the name of the University nor the names of its contributors 14252190Srpaulo * may be used to endorse or promote products derived from this software 15252190Srpaulo * without specific prior written permission. 16252190Srpaulo * 17252190Srpaulo * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18252190Srpaulo * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19252190Srpaulo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20252190Srpaulo * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21252190Srpaulo * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22252190Srpaulo * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23252190Srpaulo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24252190Srpaulo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25252190Srpaulo * 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 139823 2005-01-07 01:45:51Z imp $ 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 42#include <sys/param.h> 43#include <sys/systm.h> 44#include <sys/kernel.h> 45#include <sys/malloc.h> 46#include <sys/mbuf.h> 47#include <sys/module.h> 48#include <machine/bus.h> 49#include <sys/rman.h> 50#include <sys/socket.h> 51#include <sys/sockio.h> 52#include <sys/sysctl.h> 53 54#include <net/if.h> 55#include <net/if_clone.h> 56#include <net/if_types.h> 57#include <net/netisr.h> 58#include <net/route.h> 59#include <net/bpf.h> 60#include <net/bpfdesc.h> 61 62#ifdef INET 63#include <netinet/in.h> 64#include <netinet/in_var.h> 65#endif 66 67#ifdef IPX 68#include <netipx/ipx.h> 69#include <netipx/ipx_if.h> 70#endif 71 72#ifdef INET6 73#ifndef INET 74#include <netinet/in.h> 75#endif 76#include <netinet6/in6_var.h> 77#include <netinet/ip6.h> 78#endif 79 80#ifdef NETATALK 81#include <netatalk/at.h> 82#include <netatalk/at_var.h> 83#endif 84 85#ifdef TINY_LOMTU 86#define LOMTU (1024+512) 87#elif defined(LARGE_LOMTU) 88#define LOMTU 131072 89#else 90#define LOMTU 16384 91#endif 92 93#define LONAME "lo" 94 95struct lo_softc { 96 struct ifnet sc_if; /* network-visible interface */ 97 LIST_ENTRY(lo_softc) sc_next; 98}; 99 100int loioctl(struct ifnet *, u_long, caddr_t); 101static void lortrequest(int, struct rtentry *, struct rt_addrinfo *); 102int looutput(struct ifnet *ifp, struct mbuf *m, 103 struct sockaddr *dst, struct rtentry *rt); 104static int lo_clone_create(struct if_clone *, int); 105static void lo_clone_destroy(struct ifnet *); 106 107struct ifnet *loif = NULL; /* Used externally */ 108 109static MALLOC_DEFINE(M_LO, LONAME, "Loopback Interface"); 110 111static struct mtx lo_mtx; 112static LIST_HEAD(lo_list, lo_softc) lo_list; 113 114IFC_SIMPLE_DECLARE(lo, 1); 115 116static void 117lo_clone_destroy(ifp) 118 struct ifnet *ifp; 119{ 120 struct lo_softc *sc; 121 122 sc = ifp->if_softc; 123 124 /* XXX: destroying lo0 will lead to panics. */ 125 KASSERT(loif != ifp, ("%s: destroying lo0", __func__)); 126 127 mtx_lock(&lo_mtx); 128 LIST_REMOVE(sc, sc_next); 129 mtx_unlock(&lo_mtx); 130 bpfdetach(ifp); 131 if_detach(ifp); 132 free(sc, M_LO); 133} 134 135static int 136lo_clone_create(ifc, unit) 137 struct if_clone *ifc; 138 int unit; 139{ 140 struct lo_softc *sc; 141 142 MALLOC(sc, struct lo_softc *, sizeof(*sc), M_LO, M_WAITOK | M_ZERO); 143 144 if_initname(&sc->sc_if, ifc->ifc_name, unit); 145 sc->sc_if.if_mtu = LOMTU; 146 sc->sc_if.if_flags = IFF_LOOPBACK | IFF_MULTICAST; 147 sc->sc_if.if_ioctl = loioctl; 148 sc->sc_if.if_output = looutput; 149 sc->sc_if.if_type = IFT_LOOP; 150 sc->sc_if.if_snd.ifq_maxlen = ifqmaxlen; 151 sc->sc_if.if_softc = sc; 152 if_attach(&sc->sc_if); 153 bpfattach(&sc->sc_if, DLT_NULL, sizeof(u_int)); 154 mtx_lock(&lo_mtx); 155 LIST_INSERT_HEAD(&lo_list, sc, sc_next); 156 mtx_unlock(&lo_mtx); 157 if (loif == NULL) 158 loif = &sc->sc_if; 159 160 return (0); 161} 162 163static int 164loop_modevent(module_t mod, int type, void *data) 165{ 166 switch (type) { 167 case MOD_LOAD: 168 mtx_init(&lo_mtx, "lo_mtx", NULL, MTX_DEF); 169 LIST_INIT(&lo_list); 170 if_clone_attach(&lo_cloner); 171 break; 172 case MOD_UNLOAD: 173 printf("loop module unload - not possible for this module type\n"); 174 return EINVAL; 175 default: 176 return EOPNOTSUPP; 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 m->m_data -= (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); /* mbuf is free'd on failure. */ 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} 390