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. 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.1 (Berkeley) 6/10/93 30 * $FreeBSD: src/sys/net/if_loop.c,v 1.47.2.9 2004/02/08 08:40:24 silby Exp $ 31 */ 32 33 /* 34 * Loopback interface driver for protocol testing and timing. 35 */ 36 #include "use_loop.h" 37 38 #include "opt_inet.h" 39 #include "opt_inet6.h" 40 41 #include <sys/param.h> 42 #include <sys/systm.h> 43 #include <sys/kernel.h> 44 #include <sys/lock.h> 45 #include <sys/malloc.h> 46 #include <sys/mbuf.h> 47 #include <sys/socket.h> 48 #include <sys/sockio.h> 49 50 #include <sys/mplock2.h> 51 52 #include <net/if.h> 53 #include <net/if_types.h> 54 #include <net/if_clone.h> 55 #include <net/ifq_var.h> 56 #include <net/netisr.h> 57 #include <net/route.h> 58 #include <net/bpf.h> 59 #include <net/bpfdesc.h> 60 61 #ifdef INET 62 #include <netinet/in.h> 63 #include <netinet/in_var.h> 64 #endif 65 66 #ifdef INET6 67 #ifndef INET 68 #include <netinet/in.h> 69 #endif 70 #include <netinet6/in6_var.h> 71 #include <netinet/ip6.h> 72 #endif 73 74 static int lo_clone_create(struct if_clone *, int, caddr_t); 75 static int lo_clone_destroy(struct ifnet *); 76 77 static int lo_output(struct ifnet *, struct mbuf *, struct sockaddr *, 78 struct rtentry *); 79 static int lo_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *); 80 static void lo_rtrequest(int, struct rtentry *); 81 #ifdef ALTQ 82 static void lo_altqstart(struct ifnet *, struct ifaltq_subque *); 83 #endif 84 85 #if defined(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 LO_CSUM_FEATURES (CSUM_IP | CSUM_UDP | CSUM_TCP) 94 95 struct ifnet *loif; 96 97 static struct if_clone lo_cloner = IF_CLONE_INITIALIZER("lo", 98 lo_clone_create, lo_clone_destroy, NLOOP, IF_MAXUNIT); 99 100 static void 101 lo_sysinit(void *dummy __unused) 102 { 103 if_clone_attach(&lo_cloner); 104 } 105 SYSINIT(lo_sysinit, SI_SUB_PSEUDO, SI_ORDER_ANY, lo_sysinit, NULL); 106 107 static int 108 lo_clone_create(struct if_clone *ifc, int unit, caddr_t param __unused) 109 { 110 struct ifnet *ifp; 111 112 ifp = kmalloc(sizeof(*ifp), M_IFNET, M_WAITOK | M_ZERO); 113 if_initname(ifp, ifc->ifc_name, unit); 114 ifp->if_mtu = LOMTU; 115 ifp->if_flags = IFF_LOOPBACK | IFF_MULTICAST; 116 ifp->if_capabilities = IFCAP_HWCSUM | IFCAP_RSS; 117 ifp->if_hwassist = LO_CSUM_FEATURES; 118 ifp->if_capenable = ifp->if_capabilities; 119 ifp->if_ioctl = lo_ioctl; 120 ifp->if_output = lo_output; 121 ifp->if_type = IFT_LOOP; 122 ifq_set_maxlen(&ifp->if_snd, ifqmaxlen); 123 ifq_set_ready(&ifp->if_snd); 124 #ifdef ALTQ 125 ifp->if_start = lo_altqstart; 126 #endif 127 if_attach(ifp, NULL); 128 bpfattach(ifp, DLT_NULL, sizeof(u_int)); 129 130 if (loif == NULL) { 131 KASSERT(unit == 0, ("loif is %s", ifp->if_xname)); 132 loif = ifp; 133 } 134 return (0); 135 } 136 137 static int 138 lo_clone_destroy(struct ifnet *ifp) 139 { 140 if (loif == ifp) 141 return (EPERM); 142 143 bpfdetach(ifp); 144 if_detach(ifp); 145 kfree(ifp, M_IFNET); 146 return (0); 147 } 148 149 static int 150 lo_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, 151 struct rtentry *rt) 152 { 153 M_ASSERTPKTHDR(m); 154 155 if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) { 156 m_freem(m); 157 return (rt->rt_flags & RTF_BLACKHOLE ? 0 : 158 rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH); 159 } 160 161 IFNET_STAT_INC(ifp, opackets, 1); 162 IFNET_STAT_INC(ifp, obytes, m->m_pkthdr.len); 163 #if 1 /* XXX */ 164 switch (dst->sa_family) { 165 case AF_INET: 166 case AF_INET6: 167 break; 168 default: 169 kprintf("lo_output: af=%d unexpected\n", dst->sa_family); 170 m_freem(m); 171 return (EAFNOSUPPORT); 172 } 173 #endif 174 175 if (ifp->if_capenable & IFCAP_RXCSUM) { 176 int csum_flags = 0; 177 178 if (m->m_pkthdr.csum_flags & CSUM_IP) 179 csum_flags |= (CSUM_IP_CHECKED | CSUM_IP_VALID); 180 if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) 181 csum_flags |= (CSUM_DATA_VALID | CSUM_PSEUDO_HDR); 182 183 m->m_pkthdr.csum_flags |= csum_flags; 184 if (csum_flags & CSUM_DATA_VALID) 185 m->m_pkthdr.csum_data = 0xffff; 186 } 187 if ((ifp->if_capenable & IFCAP_RSS) == 0) 188 m->m_flags &= ~M_HASH; 189 return (if_simloop(ifp, m, dst->sa_family, 0)); 190 } 191 192 /* 193 * if_simloop() 194 * 195 * This function is to support software emulation of hardware loopback, 196 * i.e., for interfaces with the IFF_SIMPLEX attribute. Since they can't 197 * hear their own broadcasts, we create a copy of the packet that we 198 * would normally receive via a hardware loopback. 199 * 200 * This function expects the packet to include the media header of length hlen. 201 */ 202 int 203 if_simloop(struct ifnet *ifp, struct mbuf *m, int af, int hlen) 204 { 205 int isr; 206 207 KASSERT((m->m_flags & M_PKTHDR) != 0, ("if_simloop: no HDR")); 208 m->m_pkthdr.rcvif = ifp; 209 210 /* BPF write needs to be handled specially */ 211 if (af == AF_UNSPEC) { 212 KASSERT(m->m_len >= sizeof(int), ("if_simloop: m_len")); 213 af = *(mtod(m, int *)); 214 m->m_len -= sizeof(int); 215 m->m_pkthdr.len -= sizeof(int); 216 m->m_data += sizeof(int); 217 } 218 219 if (ifp->if_bpf) { 220 bpf_gettoken(); 221 222 /* Re-check */ 223 if (ifp->if_bpf == NULL) 224 goto rel; 225 226 if (ifp->if_bpf->bif_dlt == DLT_NULL) { 227 uint32_t bpf_af = (uint32_t)af; 228 bpf_ptap(ifp->if_bpf, m, &bpf_af, 4); 229 } else { 230 bpf_mtap(ifp->if_bpf, m); 231 } 232 rel: 233 bpf_reltoken(); 234 } 235 236 /* Strip away media header */ 237 if (hlen > 0) 238 m_adj(m, hlen); 239 240 #ifdef ALTQ 241 /* 242 * altq for loop is just for debugging. 243 * only used when called for loop interface (not for 244 * a simplex interface). 245 */ 246 if (ifq_is_enabled(&ifp->if_snd) && ifp->if_start == lo_altqstart) { 247 struct altq_pktattr pktattr; 248 int32_t *afp; 249 250 /* 251 * if the queueing discipline needs packet classification, 252 * do it before prepending link headers. 253 */ 254 ifq_classify(&ifp->if_snd, m, af, &pktattr); 255 256 M_PREPEND(m, sizeof(int32_t), M_NOWAIT); 257 if (m == NULL) 258 return(ENOBUFS); 259 afp = mtod(m, int32_t *); 260 *afp = (int32_t)af; 261 262 return ifq_dispatch(ifp, m, &pktattr); 263 } 264 #endif /* ALTQ */ 265 266 /* Deliver to upper layer protocol */ 267 switch (af) { 268 #ifdef INET 269 case AF_INET: 270 isr = NETISR_IP; 271 break; 272 #endif 273 #ifdef INET6 274 case AF_INET6: 275 m->m_flags |= M_LOOP; 276 isr = NETISR_IPV6; 277 break; 278 #endif 279 default: 280 kprintf("if_simloop: can't handle af=%d\n", af); 281 m_freem(m); 282 return (EAFNOSUPPORT); 283 } 284 285 IFNET_STAT_INC(ifp, ipackets, 1); 286 IFNET_STAT_INC(ifp, ibytes, m->m_pkthdr.len); 287 netisr_queue(isr, m); 288 return (0); 289 } 290 291 #ifdef ALTQ 292 static void 293 lo_altqstart(struct ifnet *ifp, struct ifaltq_subque *ifsq) 294 { 295 struct mbuf *m; 296 int32_t af, *afp; 297 int isr; 298 299 while (1) { 300 crit_enter(); 301 m = ifsq_dequeue(ifsq); 302 crit_exit(); 303 if (m == NULL) 304 return; 305 306 afp = mtod(m, int32_t *); 307 af = *afp; 308 m_adj(m, sizeof(int32_t)); 309 310 switch (af) { 311 #ifdef INET 312 case AF_INET: 313 isr = NETISR_IP; 314 break; 315 #endif 316 #ifdef INET6 317 case AF_INET6: 318 m->m_flags |= M_LOOP; 319 isr = NETISR_IPV6; 320 break; 321 #endif 322 default: 323 kprintf("lo_altqstart: can't handle af%d\n", af); 324 m_freem(m); 325 return; 326 } 327 328 IFNET_STAT_INC(ifp, ipackets, 1); 329 IFNET_STAT_INC(ifp, ibytes, m->m_pkthdr.len); 330 netisr_queue(isr, m); 331 } 332 } 333 #endif /* ALTQ */ 334 335 /* ARGSUSED */ 336 static void 337 lo_rtrequest(int cmd, struct rtentry *rt) 338 { 339 if (rt) { 340 rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu; /* for ISO */ 341 /* 342 * For optimal performance, the send and receive buffers 343 * should be at least twice the MTU plus a little more for 344 * overhead. 345 */ 346 rt->rt_rmx.rmx_recvpipe = rt->rt_rmx.rmx_sendpipe = 3 * LOMTU; 347 } 348 } 349 350 /* 351 * Process an ioctl request. 352 */ 353 /* ARGSUSED */ 354 static int 355 lo_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr) 356 { 357 struct ifaddr *ifa; 358 struct ifreq *ifr = (struct ifreq *)data; 359 int error = 0, mask; 360 361 switch (cmd) { 362 case SIOCSIFADDR: 363 ifp->if_flags |= IFF_UP | IFF_RUNNING; 364 ifa = (struct ifaddr *)data; 365 ifa->ifa_rtrequest = lo_rtrequest; 366 /* 367 * Everything else is done at a higher level. 368 */ 369 break; 370 371 case SIOCADDMULTI: 372 case SIOCDELMULTI: 373 if (ifr == NULL) { 374 error = EAFNOSUPPORT; /* XXX */ 375 break; 376 } 377 switch (ifr->ifr_addr.sa_family) { 378 379 #ifdef INET 380 case AF_INET: 381 break; 382 #endif 383 #ifdef INET6 384 case AF_INET6: 385 break; 386 #endif 387 388 default: 389 error = EAFNOSUPPORT; 390 break; 391 } 392 break; 393 394 case SIOCSIFMTU: 395 ifp->if_mtu = ifr->ifr_mtu; 396 break; 397 398 case SIOCSIFFLAGS: 399 break; 400 401 case SIOCSIFCAP: 402 mask = ifr->ifr_reqcap ^ ifp->if_capenable; 403 if (mask & IFCAP_HWCSUM) { 404 ifp->if_capenable ^= (mask & IFCAP_HWCSUM); 405 if (IFCAP_TXCSUM & ifp->if_capenable) 406 ifp->if_hwassist = LO_CSUM_FEATURES; 407 else 408 ifp->if_hwassist = 0; 409 } 410 if (mask & IFCAP_RSS) 411 ifp->if_capenable ^= IFCAP_RSS; 412 break; 413 414 default: 415 error = EINVAL; 416 } 417 return (error); 418 } 419