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