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