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 * 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 8.2 (Berkeley) 1/9/95 34 * $FreeBSD$ 35 */ 36 37 /* 38 * Loopback interface driver for protocol testing and timing. 39 */ 40 41 #include "opt_atalk.h" 42 #include "opt_inet.h" 43 #include "opt_inet6.h" 44 #include "opt_ipx.h" 45 46 #include <sys/param.h> 47 #include <sys/systm.h> 48 #include <sys/kernel.h> 49 #include <sys/malloc.h> 50 #include <sys/mbuf.h> 51 #include <sys/module.h> 52 #include <machine/bus.h> 53 #include <sys/rman.h> 54 #include <sys/socket.h> 55 #include <sys/sockio.h> 56 #include <sys/sysctl.h> 57 58 #include <net/if.h> 59 #include <net/if_types.h> 60 #include <net/netisr.h> 61 #include <net/route.h> 62 #include <net/bpf.h> 63 #include <net/bpfdesc.h> 64 65 #ifdef INET 66 #include <netinet/in.h> 67 #include <netinet/in_var.h> 68 #endif 69 70 #ifdef IPX 71 #include <netipx/ipx.h> 72 #include <netipx/ipx_if.h> 73 #endif 74 75 #ifdef INET6 76 #ifndef INET 77 #include <netinet/in.h> 78 #endif 79 #include <netinet6/in6_var.h> 80 #include <netinet/ip6.h> 81 #endif 82 83 #ifdef NS 84 #include <netns/ns.h> 85 #include <netns/ns_if.h> 86 #endif 87 88 #ifdef NETATALK 89 #include <netatalk/at.h> 90 #include <netatalk/at_var.h> 91 #endif 92 93 #ifdef TINY_LOMTU 94 #define LOMTU (1024+512) 95 #elif defined(LARGE_LOMTU) 96 #define LOMTU 131072 97 #else 98 #define LOMTU 16384 99 #endif 100 101 #define LONAME "lo" 102 #define LOMAXUNIT 0x7fff /* ifp->if_unit is only 15 bits */ 103 104 struct lo_softc { 105 struct ifnet sc_if; /* network-visible interface */ 106 LIST_ENTRY(lo_softc) sc_next; 107 struct resource *r_unit; 108 }; 109 110 int loioctl(struct ifnet *, u_long, caddr_t); 111 static void lortrequest(int, struct rtentry *, struct rt_addrinfo *); 112 int looutput(struct ifnet *ifp, struct mbuf *m, 113 struct sockaddr *dst, struct rtentry *rt); 114 int lo_clone_create(struct if_clone *, int *); 115 int lo_clone_destroy(struct ifnet *); 116 static void locreate(int, struct resource *); 117 118 struct ifnet *loif = NULL; /* Used externally */ 119 120 static MALLOC_DEFINE(M_LO, LONAME, "Loopback Interface"); 121 122 static LIST_HEAD(lo_list, lo_softc) lo_list; 123 124 struct if_clone lo_cloner = 125 IF_CLONE_INITIALIZER(LONAME, lo_clone_create, lo_clone_destroy); 126 127 static struct rman lounits[1]; 128 129 int 130 lo_clone_create(ifc, unit) 131 struct if_clone *ifc; 132 int *unit; 133 { 134 struct resource *r; 135 136 if (*unit > LOMAXUNIT) 137 return (ENXIO); 138 139 if (*unit < 0) { 140 r = rman_reserve_resource(lounits, 0, LOMAXUNIT, 1, 141 RF_ALLOCATED | RF_ACTIVE, NULL); 142 if (r == NULL) 143 return (ENOSPC); 144 *unit = rman_get_start(r); 145 } else { 146 r = rman_reserve_resource(lounits, *unit, *unit, 1, 147 RF_ALLOCATED | RF_ACTIVE, NULL); 148 if (r == NULL) 149 return (EEXIST); 150 } 151 locreate(*unit, r); 152 return (0); 153 } 154 155 int 156 lo_clone_destroy(ifp) 157 struct ifnet *ifp; 158 { 159 int err; 160 struct lo_softc *sc; 161 162 sc = ifp->if_softc; 163 164 /* 165 * Prevent lo0 from being destroyed. 166 */ 167 if (loif == ifp) 168 return (EINVAL); 169 170 err = rman_release_resource(sc->r_unit); 171 KASSERT(err == 0, ("Unexpected error freeing resource")); 172 173 bpfdetach(ifp); 174 if_detach(ifp); 175 LIST_REMOVE(sc, sc_next); 176 FREE(sc, M_LO); 177 return (0); 178 } 179 180 static void 181 locreate(int unit, struct resource *r) 182 { 183 struct lo_softc *sc; 184 185 MALLOC(sc, struct lo_softc *, sizeof(*sc), M_LO, M_WAITOK | M_ZERO); 186 187 sc->sc_if.if_name = LONAME; 188 sc->sc_if.if_unit = unit; 189 sc->sc_if.if_mtu = LOMTU; 190 sc->sc_if.if_flags = IFF_LOOPBACK | IFF_MULTICAST; 191 sc->sc_if.if_ioctl = loioctl; 192 sc->sc_if.if_output = looutput; 193 sc->sc_if.if_type = IFT_LOOP; 194 sc->sc_if.if_snd.ifq_maxlen = ifqmaxlen; 195 sc->sc_if.if_softc = sc; 196 sc->r_unit = r; 197 if_attach(&sc->sc_if); 198 bpfattach(&sc->sc_if, DLT_NULL, sizeof(u_int)); 199 LIST_INSERT_HEAD(&lo_list, sc, sc_next); 200 if (loif == NULL) 201 loif = &sc->sc_if; 202 } 203 204 static int 205 loop_modevent(module_t mod, int type, void *data) 206 { 207 int err; 208 int unit; 209 210 switch (type) { 211 case MOD_LOAD: 212 lounits->rm_type = RMAN_ARRAY; 213 lounits->rm_descr = "configurable if_loop units"; 214 err = rman_init(lounits); 215 if (err != 0) 216 return (err); 217 err = rman_manage_region(lounits, 0, LOMAXUNIT); 218 if (err != 0) { 219 printf("%s: lounits: rman_manage_region: Failed %d\n", 220 LONAME, err); 221 rman_fini(lounits); 222 return (err); 223 } 224 LIST_INIT(&lo_list); 225 if_clone_attach(&lo_cloner); 226 227 /* Create lo0 */ 228 unit = 0; 229 err = lo_clone_create(NULL, &unit); 230 KASSERT(err == 0, ("%s: can't create lo0", __func__)); 231 break; 232 case MOD_UNLOAD: 233 printf("loop module unload - not possible for this module type\n"); 234 return EINVAL; 235 } 236 return 0; 237 } 238 239 static moduledata_t loop_mod = { 240 "loop", 241 loop_modevent, 242 0 243 }; 244 245 DECLARE_MODULE(loop, loop_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); 246 247 int 248 looutput(ifp, m, dst, rt) 249 struct ifnet *ifp; 250 register struct mbuf *m; 251 struct sockaddr *dst; 252 register struct rtentry *rt; 253 { 254 if ((m->m_flags & M_PKTHDR) == 0) 255 panic("looutput no HDR"); 256 257 if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) { 258 m_freem(m); 259 return (rt->rt_flags & RTF_BLACKHOLE ? 0 : 260 rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH); 261 } 262 /* 263 * KAME requires that the packet to be contiguous on the 264 * mbuf. We need to make that sure. 265 * this kind of code should be avoided. 266 * XXX: fails to join if interface MTU > MCLBYTES. jumbogram? 267 */ 268 if (m && m->m_next != NULL && m->m_pkthdr.len < MCLBYTES) { 269 struct mbuf *n; 270 271 MGETHDR(n, M_DONTWAIT, MT_HEADER); 272 if (!n) 273 goto contiguousfail; 274 MCLGET(n, M_DONTWAIT); 275 if (! (n->m_flags & M_EXT)) { 276 m_freem(n); 277 goto contiguousfail; 278 } 279 280 m_copydata(m, 0, m->m_pkthdr.len, mtod(n, caddr_t)); 281 n->m_pkthdr = m->m_pkthdr; 282 n->m_len = m->m_pkthdr.len; 283 n->m_pkthdr.aux = m->m_pkthdr.aux; 284 m->m_pkthdr.aux = (struct mbuf *)NULL; 285 m_freem(m); 286 m = n; 287 } 288 if (0) { 289 contiguousfail: 290 printf("looutput: mbuf allocation failed\n"); 291 } 292 293 ifp->if_opackets++; 294 ifp->if_obytes += m->m_pkthdr.len; 295 #if 1 /* XXX */ 296 switch (dst->sa_family) { 297 case AF_INET: 298 case AF_INET6: 299 case AF_IPX: 300 case AF_NS: 301 case AF_APPLETALK: 302 break; 303 default: 304 printf("looutput: af=%d unexpected\n", dst->sa_family); 305 m_freem(m); 306 return (EAFNOSUPPORT); 307 } 308 #endif 309 return(if_simloop(ifp, m, dst->sa_family, 0)); 310 } 311 312 /* 313 * if_simloop() 314 * 315 * This function is to support software emulation of hardware loopback, 316 * i.e., for interfaces with the IFF_SIMPLEX attribute. Since they can't 317 * hear their own broadcasts, we create a copy of the packet that we 318 * would normally receive via a hardware loopback. 319 * 320 * This function expects the packet to include the media header of length hlen. 321 */ 322 323 int 324 if_simloop(ifp, m, af, hlen) 325 struct ifnet *ifp; 326 struct mbuf *m; 327 int af; 328 int hlen; 329 { 330 int isr; 331 struct ifqueue *inq = 0; 332 333 KASSERT((m->m_flags & M_PKTHDR) != 0, ("if_simloop: no HDR")); 334 m->m_pkthdr.rcvif = ifp; 335 336 /* BPF write needs to be handled specially */ 337 if (af == AF_UNSPEC) { 338 KASSERT(m->m_len >= sizeof(int), ("if_simloop: m_len")); 339 af = *(mtod(m, int *)); 340 m->m_len -= sizeof(int); 341 m->m_pkthdr.len -= sizeof(int); 342 m->m_data += sizeof(int); 343 } 344 345 /* Let BPF see incoming packet */ 346 if (ifp->if_bpf) { 347 struct mbuf m0, *n = m; 348 349 if (ifp->if_bpf->bif_dlt == DLT_NULL) { 350 /* 351 * We need to prepend the address family as 352 * a four byte field. Cons up a dummy header 353 * to pacify bpf. This is safe because bpf 354 * will only read from the mbuf (i.e., it won't 355 * try to free it or keep a pointer a to it). 356 */ 357 m0.m_next = m; 358 m0.m_len = 4; 359 m0.m_data = (char *)⁡ 360 n = &m0; 361 } 362 bpf_mtap(ifp, n); 363 } 364 365 /* Strip away media header */ 366 if (hlen > 0) { 367 m_adj(m, hlen); 368 #if defined(__alpha__) || defined(__ia64__) || defined(__sparc64__) 369 /* The alpha doesn't like unaligned data. 370 * We move data down in the first mbuf */ 371 if (mtod(m, vm_offset_t) & 3) { 372 KASSERT(hlen >= 3, ("if_simloop: hlen too small")); 373 bcopy(m->m_data, 374 (char *)(mtod(m, vm_offset_t) 375 - (mtod(m, vm_offset_t) & 3)), 376 m->m_len); 377 mtod(m,vm_offset_t) -= (mtod(m, vm_offset_t) & 3); 378 } 379 #endif 380 } 381 382 /* Deliver to upper layer protocol */ 383 switch (af) { 384 #ifdef INET 385 case AF_INET: 386 inq = &ipintrq; 387 isr = NETISR_IP; 388 break; 389 #endif 390 #ifdef INET6 391 case AF_INET6: 392 m->m_flags |= M_LOOP; 393 inq = &ip6intrq; 394 isr = NETISR_IPV6; 395 break; 396 #endif 397 #ifdef IPX 398 case AF_IPX: 399 inq = &ipxintrq; 400 isr = NETISR_IPX; 401 break; 402 #endif 403 #ifdef NS 404 case AF_NS: 405 inq = &nsintrq; 406 isr = NETISR_NS; 407 break; 408 #endif 409 #ifdef NETATALK 410 case AF_APPLETALK: 411 inq = &atintrq2; 412 isr = NETISR_ATALK; 413 break; 414 #endif 415 default: 416 printf("if_simloop: can't handle af=%d\n", af); 417 m_freem(m); 418 return (EAFNOSUPPORT); 419 } 420 ifp->if_ipackets++; 421 ifp->if_ibytes += m->m_pkthdr.len; 422 (void) IF_HANDOFF(inq, m, NULL); 423 schednetisr(isr); 424 return (0); 425 } 426 427 /* ARGSUSED */ 428 static void 429 lortrequest(cmd, rt, info) 430 int cmd; 431 struct rtentry *rt; 432 struct rt_addrinfo *info; 433 { 434 if (rt) { 435 rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu; /* for ISO */ 436 /* 437 * For optimal performance, the send and receive buffers 438 * should be at least twice the MTU plus a little more for 439 * overhead. 440 */ 441 rt->rt_rmx.rmx_recvpipe = 442 rt->rt_rmx.rmx_sendpipe = 3 * LOMTU; 443 } 444 } 445 446 /* 447 * Process an ioctl request. 448 */ 449 /* ARGSUSED */ 450 int 451 loioctl(ifp, cmd, data) 452 register struct ifnet *ifp; 453 u_long cmd; 454 caddr_t data; 455 { 456 register struct ifaddr *ifa; 457 register struct ifreq *ifr = (struct ifreq *)data; 458 register int error = 0; 459 460 switch (cmd) { 461 462 case SIOCSIFADDR: 463 ifp->if_flags |= IFF_UP | IFF_RUNNING; 464 ifa = (struct ifaddr *)data; 465 ifa->ifa_rtrequest = lortrequest; 466 /* 467 * Everything else is done at a higher level. 468 */ 469 break; 470 471 case SIOCADDMULTI: 472 case SIOCDELMULTI: 473 if (ifr == 0) { 474 error = EAFNOSUPPORT; /* XXX */ 475 break; 476 } 477 switch (ifr->ifr_addr.sa_family) { 478 479 #ifdef INET 480 case AF_INET: 481 break; 482 #endif 483 #ifdef INET6 484 case AF_INET6: 485 break; 486 #endif 487 488 default: 489 error = EAFNOSUPPORT; 490 break; 491 } 492 break; 493 494 case SIOCSIFMTU: 495 ifp->if_mtu = ifr->ifr_mtu; 496 break; 497 498 case SIOCSIFFLAGS: 499 break; 500 501 default: 502 error = EINVAL; 503 } 504 return (error); 505 } 506