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$ 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_route.h" 42 43 #include <sys/param.h> 44 #include <sys/systm.h> 45 #include <sys/kernel.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 #include <sys/vimage.h> 54 55 #include <net/if.h> 56 #include <net/if_clone.h> 57 #include <net/if_types.h> 58 #include <net/netisr.h> 59 #include <net/route.h> 60 #include <net/bpf.h> 61 #include <net/vnet.h> 62 63 #ifdef INET 64 #include <netinet/in.h> 65 #include <netinet/in_var.h> 66 #endif 67 68 #ifdef IPX 69 #include <netipx/ipx.h> 70 #include <netipx/ipx_if.h> 71 #endif 72 73 #ifdef INET6 74 #ifndef INET 75 #include <netinet/in.h> 76 #endif 77 #include <netinet6/in6_var.h> 78 #include <netinet/ip6.h> 79 #endif 80 81 #ifdef NETATALK 82 #include <netatalk/at.h> 83 #include <netatalk/at_var.h> 84 #endif 85 86 #include <security/mac/mac_framework.h> 87 88 #ifdef TINY_LOMTU 89 #define LOMTU (1024+512) 90 #elif defined(LARGE_LOMTU) 91 #define LOMTU 131072 92 #else 93 #define LOMTU 16384 94 #endif 95 96 #define LO_CSUM_FEATURES (CSUM_IP | CSUM_TCP | CSUM_UDP | CSUM_SCTP) 97 #define LO_CSUM_SET (CSUM_DATA_VALID | CSUM_PSEUDO_HDR | \ 98 CSUM_IP_CHECKED | CSUM_IP_VALID | \ 99 CSUM_SCTP_VALID) 100 101 int loioctl(struct ifnet *, u_long, caddr_t); 102 static void lortrequest(int, struct rtentry *, struct rt_addrinfo *); 103 int looutput(struct ifnet *ifp, struct mbuf *m, 104 struct sockaddr *dst, struct route *ro); 105 static int lo_clone_create(struct if_clone *, int, caddr_t); 106 static void lo_clone_destroy(struct ifnet *); 107 static int vnet_loif_iattach(const void *); 108 109 #ifdef VIMAGE_GLOBALS 110 struct ifnet *loif; /* Used externally */ 111 #endif 112 113 #ifdef VIMAGE 114 MALLOC_DEFINE(M_LO_CLONER, "lo_cloner", "lo_cloner"); 115 #endif 116 117 #ifndef VIMAGE_GLOBALS 118 static const vnet_modinfo_t vnet_loif_modinfo = { 119 .vmi_id = VNET_MOD_LOIF, 120 .vmi_dependson = VNET_MOD_IF_CLONE, 121 .vmi_name = "loif", 122 .vmi_iattach = vnet_loif_iattach 123 }; 124 #endif /* !VIMAGE_GLOBALS */ 125 126 IFC_SIMPLE_DECLARE(lo, 1); 127 128 static void 129 lo_clone_destroy(struct ifnet *ifp) 130 { 131 #ifdef INVARIANTS 132 INIT_VNET_NET(ifp->if_vnet); 133 #endif 134 135 /* XXX: destroying lo0 will lead to panics. */ 136 KASSERT(V_loif != ifp, ("%s: destroying lo0", __func__)); 137 138 bpfdetach(ifp); 139 if_detach(ifp); 140 if_free(ifp); 141 } 142 143 static int 144 lo_clone_create(struct if_clone *ifc, int unit, caddr_t params) 145 { 146 INIT_VNET_NET(curvnet); 147 struct ifnet *ifp; 148 149 ifp = if_alloc(IFT_LOOP); 150 if (ifp == NULL) 151 return (ENOSPC); 152 153 if_initname(ifp, ifc->ifc_name, unit); 154 ifp->if_mtu = LOMTU; 155 ifp->if_flags = IFF_LOOPBACK | IFF_MULTICAST; 156 ifp->if_ioctl = loioctl; 157 ifp->if_output = looutput; 158 ifp->if_snd.ifq_maxlen = ifqmaxlen; 159 ifp->if_capabilities = ifp->if_capenable = IFCAP_HWCSUM; 160 ifp->if_hwassist = LO_CSUM_FEATURES; 161 if_attach(ifp); 162 bpfattach(ifp, DLT_NULL, sizeof(u_int32_t)); 163 if (V_loif == NULL) 164 V_loif = ifp; 165 166 return (0); 167 } 168 169 static int vnet_loif_iattach(const void *unused __unused) 170 { 171 INIT_VNET_NET(curvnet); 172 173 V_loif = NULL; 174 175 #ifdef VIMAGE 176 V_lo_cloner = malloc(sizeof(*V_lo_cloner), M_LO_CLONER, 177 M_WAITOK | M_ZERO); 178 bcopy(&lo_cloner, V_lo_cloner, sizeof(*V_lo_cloner)); 179 if_clone_attach(V_lo_cloner); 180 #else 181 if_clone_attach(&lo_cloner); 182 #endif 183 return (0); 184 } 185 186 static int 187 loop_modevent(module_t mod, int type, void *data) 188 { 189 190 switch (type) { 191 case MOD_LOAD: 192 #ifndef VIMAGE_GLOBALS 193 vnet_mod_register(&vnet_loif_modinfo); 194 #else 195 vnet_loif_iattach(NULL); 196 #endif 197 break; 198 199 case MOD_UNLOAD: 200 printf("loop module unload - not possible for this module type\n"); 201 return (EINVAL); 202 203 default: 204 return (EOPNOTSUPP); 205 } 206 return (0); 207 } 208 209 static moduledata_t loop_mod = { 210 "loop", 211 loop_modevent, 212 0 213 }; 214 215 DECLARE_MODULE(loop, loop_mod, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY); 216 217 int 218 looutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, 219 struct route *ro) 220 { 221 u_int32_t af; 222 struct rtentry *rt = NULL; 223 #ifdef MAC 224 int error; 225 #endif 226 227 M_ASSERTPKTHDR(m); /* check if we have the packet header */ 228 229 if (ro != NULL) 230 rt = ro->ro_rt; 231 #ifdef MAC 232 error = mac_ifnet_check_transmit(ifp, m); 233 if (error) { 234 m_freem(m); 235 return (error); 236 } 237 #endif 238 239 if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) { 240 m_freem(m); 241 return (rt->rt_flags & RTF_BLACKHOLE ? 0 : 242 rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH); 243 } 244 245 ifp->if_opackets++; 246 ifp->if_obytes += m->m_pkthdr.len; 247 248 /* BPF writes need to be handled specially. */ 249 if (dst->sa_family == AF_UNSPEC) { 250 bcopy(dst->sa_data, &af, sizeof(af)); 251 dst->sa_family = af; 252 } 253 254 #if 1 /* XXX */ 255 switch (dst->sa_family) { 256 case AF_INET: 257 if (ifp->if_capenable & IFCAP_RXCSUM) { 258 m->m_pkthdr.csum_data = 0xffff; 259 m->m_pkthdr.csum_flags = LO_CSUM_SET; 260 } 261 m->m_pkthdr.csum_flags &= ~LO_CSUM_FEATURES; 262 case AF_INET6: 263 case AF_IPX: 264 case AF_APPLETALK: 265 break; 266 default: 267 printf("looutput: af=%d unexpected\n", dst->sa_family); 268 m_freem(m); 269 return (EAFNOSUPPORT); 270 } 271 #endif 272 return (if_simloop(ifp, m, dst->sa_family, 0)); 273 } 274 275 /* 276 * if_simloop() 277 * 278 * This function is to support software emulation of hardware loopback, 279 * i.e., for interfaces with the IFF_SIMPLEX attribute. Since they can't 280 * hear their own broadcasts, we create a copy of the packet that we 281 * would normally receive via a hardware loopback. 282 * 283 * This function expects the packet to include the media header of length hlen. 284 */ 285 int 286 if_simloop(struct ifnet *ifp, struct mbuf *m, int af, int hlen) 287 { 288 INIT_VNET_NET(ifp->if_vnet); 289 int isr; 290 291 M_ASSERTPKTHDR(m); 292 m_tag_delete_nonpersistent(m); 293 m->m_pkthdr.rcvif = ifp; 294 295 #ifdef MAC 296 mac_ifnet_create_mbuf(ifp, m); 297 #endif 298 299 /* 300 * Let BPF see incoming packet in the following manner: 301 * - Emulated packet loopback for a simplex interface 302 * (net/if_ethersubr.c) 303 * -> passes it to ifp's BPF 304 * - IPv4/v6 multicast packet loopback (netinet(6)/ip(6)_output.c) 305 * -> not passes it to any BPF 306 * - Normal packet loopback from myself to myself (net/if_loop.c) 307 * -> passes to lo0's BPF (even in case of IPv6, where ifp!=lo0) 308 */ 309 if (hlen > 0) { 310 if (bpf_peers_present(ifp->if_bpf)) { 311 bpf_mtap(ifp->if_bpf, m); 312 } 313 } else { 314 if (bpf_peers_present(V_loif->if_bpf)) { 315 if ((m->m_flags & M_MCAST) == 0 || V_loif == ifp) { 316 /* XXX beware sizeof(af) != 4 */ 317 u_int32_t af1 = af; 318 319 /* 320 * We need to prepend the address family. 321 */ 322 bpf_mtap2(V_loif->if_bpf, &af1, sizeof(af1), m); 323 } 324 } 325 } 326 327 /* Strip away media header */ 328 if (hlen > 0) { 329 m_adj(m, hlen); 330 #ifndef __NO_STRICT_ALIGNMENT 331 /* 332 * Some archs do not like unaligned data, so 333 * we move data down in the first mbuf. 334 */ 335 if (mtod(m, vm_offset_t) & 3) { 336 KASSERT(hlen >= 3, ("if_simloop: hlen too small")); 337 bcopy(m->m_data, 338 (char *)(mtod(m, vm_offset_t) 339 - (mtod(m, vm_offset_t) & 3)), 340 m->m_len); 341 m->m_data -= (mtod(m,vm_offset_t) & 3); 342 } 343 #endif 344 } 345 346 /* Deliver to upper layer protocol */ 347 switch (af) { 348 #ifdef INET 349 case AF_INET: 350 isr = NETISR_IP; 351 break; 352 #endif 353 #ifdef INET6 354 case AF_INET6: 355 m->m_flags |= M_LOOP; 356 isr = NETISR_IPV6; 357 break; 358 #endif 359 #ifdef IPX 360 case AF_IPX: 361 isr = NETISR_IPX; 362 break; 363 #endif 364 #ifdef NETATALK 365 case AF_APPLETALK: 366 isr = NETISR_ATALK2; 367 break; 368 #endif 369 default: 370 printf("if_simloop: can't handle af=%d\n", af); 371 m_freem(m); 372 return (EAFNOSUPPORT); 373 } 374 ifp->if_ipackets++; 375 ifp->if_ibytes += m->m_pkthdr.len; 376 netisr_queue(isr, m); /* mbuf is free'd on failure. */ 377 return (0); 378 } 379 380 /* ARGSUSED */ 381 static void 382 lortrequest(int cmd, struct rtentry *rt, struct rt_addrinfo *info) 383 { 384 385 RT_LOCK_ASSERT(rt); 386 rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu; 387 } 388 389 /* 390 * Process an ioctl request. 391 */ 392 /* ARGSUSED */ 393 int 394 loioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 395 { 396 struct ifaddr *ifa; 397 struct ifreq *ifr = (struct ifreq *)data; 398 int error = 0, mask; 399 400 switch (cmd) { 401 case SIOCSIFADDR: 402 ifp->if_flags |= IFF_UP; 403 ifp->if_drv_flags |= IFF_DRV_RUNNING; 404 ifa = (struct ifaddr *)data; 405 ifa->ifa_rtrequest = lortrequest; 406 /* 407 * Everything else is done at a higher level. 408 */ 409 break; 410 411 case SIOCADDMULTI: 412 case SIOCDELMULTI: 413 if (ifr == 0) { 414 error = EAFNOSUPPORT; /* XXX */ 415 break; 416 } 417 switch (ifr->ifr_addr.sa_family) { 418 419 #ifdef INET 420 case AF_INET: 421 break; 422 #endif 423 #ifdef INET6 424 case AF_INET6: 425 break; 426 #endif 427 428 default: 429 error = EAFNOSUPPORT; 430 break; 431 } 432 break; 433 434 case SIOCSIFMTU: 435 ifp->if_mtu = ifr->ifr_mtu; 436 break; 437 438 case SIOCSIFFLAGS: 439 break; 440 441 case SIOCSIFCAP: 442 mask = ifp->if_capenable ^ ifr->ifr_reqcap; 443 if ((mask & IFCAP_RXCSUM) != 0) 444 ifp->if_capenable ^= IFCAP_RXCSUM; 445 if ((mask & IFCAP_TXCSUM) != 0) 446 ifp->if_capenable ^= IFCAP_TXCSUM; 447 if (ifp->if_capenable & IFCAP_TXCSUM) 448 ifp->if_hwassist = LO_CSUM_FEATURES; 449 else 450 ifp->if_hwassist = 0; 451 break; 452 453 default: 454 error = EINVAL; 455 } 456 return (error); 457 } 458