1 1.119 christos /* $NetBSD: if_loop.c,v 1.119 2025/09/21 15:11:52 christos Exp $ */ 2 1.26 itojun 3 1.26 itojun /* 4 1.26 itojun * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 5 1.26 itojun * All rights reserved. 6 1.55 perry * 7 1.26 itojun * Redistribution and use in source and binary forms, with or without 8 1.26 itojun * modification, are permitted provided that the following conditions 9 1.26 itojun * are met: 10 1.26 itojun * 1. Redistributions of source code must retain the above copyright 11 1.26 itojun * notice, this list of conditions and the following disclaimer. 12 1.26 itojun * 2. Redistributions in binary form must reproduce the above copyright 13 1.26 itojun * notice, this list of conditions and the following disclaimer in the 14 1.26 itojun * documentation and/or other materials provided with the distribution. 15 1.26 itojun * 3. Neither the name of the project nor the names of its contributors 16 1.26 itojun * may be used to endorse or promote products derived from this software 17 1.26 itojun * without specific prior written permission. 18 1.55 perry * 19 1.26 itojun * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 20 1.26 itojun * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 1.26 itojun * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 1.26 itojun * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 23 1.26 itojun * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 1.26 itojun * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 1.26 itojun * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 1.26 itojun * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 1.26 itojun * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 1.26 itojun * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 1.26 itojun * SUCH DAMAGE. 30 1.26 itojun */ 31 1.12 cgd 32 1.1 cgd /* 33 1.11 mycroft * Copyright (c) 1982, 1986, 1993 34 1.11 mycroft * The Regents of the University of California. All rights reserved. 35 1.1 cgd * 36 1.1 cgd * Redistribution and use in source and binary forms, with or without 37 1.1 cgd * modification, are permitted provided that the following conditions 38 1.1 cgd * are met: 39 1.1 cgd * 1. Redistributions of source code must retain the above copyright 40 1.1 cgd * notice, this list of conditions and the following disclaimer. 41 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright 42 1.1 cgd * notice, this list of conditions and the following disclaimer in the 43 1.1 cgd * documentation and/or other materials provided with the distribution. 44 1.47 agc * 3. Neither the name of the University nor the names of its contributors 45 1.1 cgd * may be used to endorse or promote products derived from this software 46 1.1 cgd * without specific prior written permission. 47 1.1 cgd * 48 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 49 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 50 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 51 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 52 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 53 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 54 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 55 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 56 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 57 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 58 1.1 cgd * SUCH DAMAGE. 59 1.1 cgd * 60 1.21 fvdl * @(#)if_loop.c 8.2 (Berkeley) 1/9/95 61 1.1 cgd */ 62 1.1 cgd 63 1.1 cgd /* 64 1.1 cgd * Loopback interface driver for protocol testing and timing. 65 1.1 cgd */ 66 1.40 lukem 67 1.40 lukem #include <sys/cdefs.h> 68 1.119 christos __KERNEL_RCSID(0, "$NetBSD: if_loop.c,v 1.119 2025/09/21 15:11:52 christos Exp $"); 69 1.23 jonathan 70 1.83 pooka #ifdef _KERNEL_OPT 71 1.23 jonathan #include "opt_inet.h" 72 1.23 jonathan #include "opt_atalk.h" 73 1.46 martin #include "opt_mbuftrace.h" 74 1.74 kefren #include "opt_mpls.h" 75 1.81 ozaki #include "opt_net_mpsafe.h" 76 1.83 pooka #endif 77 1.4 cgd 78 1.9 mycroft #include <sys/param.h> 79 1.9 mycroft #include <sys/systm.h> 80 1.11 mycroft #include <sys/kernel.h> 81 1.9 mycroft #include <sys/mbuf.h> 82 1.9 mycroft #include <sys/socket.h> 83 1.9 mycroft #include <sys/errno.h> 84 1.9 mycroft #include <sys/ioctl.h> 85 1.11 mycroft #include <sys/time.h> 86 1.90 christos #include <sys/device.h> 87 1.90 christos #include <sys/module.h> 88 1.11 mycroft 89 1.66 ad #include <sys/cpu.h> 90 1.9 mycroft 91 1.9 mycroft #include <net/if.h> 92 1.9 mycroft #include <net/if_types.h> 93 1.9 mycroft #include <net/route.h> 94 1.1 cgd 95 1.1 cgd #ifdef INET 96 1.9 mycroft #include <netinet/in.h> 97 1.9 mycroft #include <netinet/in_systm.h> 98 1.9 mycroft #include <netinet/in_var.h> 99 1.73 yamt #include <netinet/in_offload.h> 100 1.9 mycroft #include <netinet/ip.h> 101 1.117 thorpej #include <netinet/ip_var.h> 102 1.1 cgd #endif 103 1.1 cgd 104 1.26 itojun #ifdef INET6 105 1.26 itojun #ifndef INET 106 1.26 itojun #include <netinet/in.h> 107 1.26 itojun #endif 108 1.26 itojun #include <netinet6/in6_var.h> 109 1.73 yamt #include <netinet6/in6_offload.h> 110 1.29 itojun #include <netinet/ip6.h> 111 1.26 itojun #endif 112 1.26 itojun 113 1.74 kefren #ifdef MPLS 114 1.74 kefren #include <netmpls/mpls.h> 115 1.74 kefren #include <netmpls/mpls_var.h> 116 1.74 kefren #endif 117 1.74 kefren 118 1.19 christos #ifdef NETATALK 119 1.19 christos #include <netatalk/at.h> 120 1.19 christos #include <netatalk/at_var.h> 121 1.19 christos #endif 122 1.19 christos 123 1.2 cgd #include <net/bpf.h> 124 1.9 mycroft 125 1.26 itojun #if defined(LARGE_LOMTU) 126 1.26 itojun #define LOMTU (131072 + MHLEN + MLEN) 127 1.48 jonathan #define LOMTU_MAX LOMTU 128 1.26 itojun #else 129 1.20 jonathan #define LOMTU (32768 + MHLEN + MLEN) 130 1.48 jonathan #define LOMTU_MAX (65536 + MHLEN + MLEN) 131 1.26 itojun #endif 132 1.1 cgd 133 1.34 thorpej #ifdef ALTQ 134 1.57 thorpej static void lostart(struct ifnet *); 135 1.34 thorpej #endif 136 1.32 thorpej 137 1.57 thorpej static int loop_clone_create(struct if_clone *, int); 138 1.57 thorpej static int loop_clone_destroy(struct ifnet *); 139 1.52 peter 140 1.93 ozaki static void loop_rtrequest(int, struct rtentry *, const struct rt_addrinfo *); 141 1.93 ozaki 142 1.57 thorpej static struct if_clone loop_cloner = 143 1.52 peter IF_CLONE_INITIALIZER("lo", loop_clone_create, loop_clone_destroy); 144 1.52 peter 145 1.6 andrew void 146 1.62 christos loopattach(int n) 147 1.1 cgd { 148 1.52 peter 149 1.95 knakahar #ifndef _MODULE 150 1.95 knakahar loop_clone_create(&loop_cloner, 0); /* lo0 always exists */ 151 1.95 knakahar #endif 152 1.90 christos } 153 1.90 christos 154 1.91 kre void 155 1.90 christos loopinit(void) 156 1.90 christos { 157 1.90 christos 158 1.92 kre if (lo0ifp != NULL) /* can happen in rump kernel */ 159 1.92 kre return; 160 1.92 kre 161 1.95 knakahar #ifdef _MODULE 162 1.95 knakahar loop_clone_create(&loop_cloner, 0); /* lo0 always exists */ 163 1.95 knakahar #endif 164 1.52 peter if_clone_attach(&loop_cloner); 165 1.52 peter } 166 1.52 peter 167 1.57 thorpej static int 168 1.90 christos loopdetach(void) 169 1.90 christos { 170 1.90 christos /* no detach for now; we don't allow lo0 to be deleted */ 171 1.90 christos return EBUSY; 172 1.90 christos } 173 1.90 christos 174 1.90 christos static int 175 1.52 peter loop_clone_create(struct if_clone *ifc, int unit) 176 1.52 peter { 177 1.60 peter struct ifnet *ifp; 178 1.52 peter 179 1.68 christos ifp = if_alloc(IFT_LOOP); 180 1.52 peter 181 1.68 christos if_initname(ifp, ifc->ifc_name, unit); 182 1.1 cgd 183 1.60 peter ifp->if_mtu = LOMTU; 184 1.100 ozaki ifp->if_flags = IFF_LOOPBACK | IFF_MULTICAST; 185 1.101 ozaki #ifdef NET_MPSAFE 186 1.111 roy ifp->if_extflags = IFEF_MPSAFE; 187 1.101 ozaki #endif 188 1.60 peter ifp->if_ioctl = loioctl; 189 1.60 peter ifp->if_output = looutput; 190 1.34 thorpej #ifdef ALTQ 191 1.60 peter ifp->if_start = lostart; 192 1.34 thorpej #endif 193 1.60 peter ifp->if_type = IFT_LOOP; 194 1.60 peter ifp->if_hdrlen = 0; 195 1.60 peter ifp->if_addrlen = 0; 196 1.60 peter ifp->if_dlt = DLT_NULL; 197 1.60 peter IFQ_SET_READY(&ifp->if_snd); 198 1.52 peter if (unit == 0) 199 1.60 peter lo0ifp = ifp; 200 1.113 riastrad if_initialize(ifp); 201 1.112 roy ifp->if_link_state = LINK_STATE_UP; 202 1.60 peter if_alloc_sadl(ifp); 203 1.72 joerg bpf_attach(ifp, DLT_NULL, sizeof(u_int)); 204 1.42 matt #ifdef MBUFTRACE 205 1.60 peter ifp->if_mowner = malloc(sizeof(struct mowner), M_DEVBUF, 206 1.52 peter M_WAITOK | M_ZERO); 207 1.60 peter strlcpy(ifp->if_mowner->mo_name, ifp->if_xname, 208 1.60 peter sizeof(ifp->if_mowner->mo_name)); 209 1.60 peter MOWNER_ATTACH(ifp->if_mowner); 210 1.42 matt #endif 211 1.52 peter 212 1.100 ozaki ifp->if_flags |= IFF_RUNNING; 213 1.111 roy if_register(ifp); 214 1.100 ozaki 215 1.52 peter return (0); 216 1.52 peter } 217 1.52 peter 218 1.57 thorpej static int 219 1.52 peter loop_clone_destroy(struct ifnet *ifp) 220 1.52 peter { 221 1.52 peter 222 1.53 peter if (ifp == lo0ifp) 223 1.53 peter return (EPERM); 224 1.52 peter 225 1.100 ozaki ifp->if_flags &= ~IFF_RUNNING; 226 1.100 ozaki 227 1.52 peter #ifdef MBUFTRACE 228 1.52 peter MOWNER_DETACH(ifp->if_mowner); 229 1.52 peter free(ifp->if_mowner, M_DEVBUF); 230 1.52 peter #endif 231 1.52 peter 232 1.72 joerg bpf_detach(ifp); 233 1.52 peter if_detach(ifp); 234 1.52 peter 235 1.78 pooka if_free(ifp); 236 1.53 peter 237 1.53 peter return (0); 238 1.1 cgd } 239 1.1 cgd 240 1.11 mycroft int 241 1.63 dyoung looutput(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, 242 1.85 ozaki const struct rtentry *rt) 243 1.1 cgd { 244 1.79 rmind pktqueue_t *pktq = NULL; 245 1.116 thorpej int s; 246 1.73 yamt int csum_flags; 247 1.88 knakahar int error = 0; 248 1.79 rmind size_t pktlen; 249 1.1 cgd 250 1.42 matt MCLAIM(m, ifp->if_mowner); 251 1.88 knakahar 252 1.99 ozaki KERNEL_LOCK_UNLESS_NET_MPSAFE(); 253 1.77 bouyer 254 1.1 cgd if ((m->m_flags & M_PKTHDR) == 0) 255 1.14 mycroft panic("looutput: no header mbuf"); 256 1.72 joerg if (ifp->if_flags & IFF_LOOPBACK) 257 1.102 msaitoh bpf_mtap_af(ifp, dst->sa_family, m, BPF_D_OUT); 258 1.87 ozaki m_set_rcvif(m, ifp); 259 1.1 cgd 260 1.11 mycroft if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) { 261 1.1 cgd m_freem(m); 262 1.88 knakahar error = (rt->rt_flags & RTF_BLACKHOLE ? 0 : 263 1.11 mycroft rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH); 264 1.88 knakahar goto out; 265 1.1 cgd } 266 1.26 itojun 267 1.79 rmind pktlen = m->m_pkthdr.len; 268 1.110 thorpej 269 1.110 thorpej if_statadd2(ifp, if_opackets, 1, if_obytes, pktlen); 270 1.32 thorpej 271 1.32 thorpej #ifdef ALTQ 272 1.32 thorpej /* 273 1.32 thorpej * ALTQ on the loopback interface is just for debugging. It's 274 1.32 thorpej * used only for loopback interfaces, not for a simplex interface. 275 1.32 thorpej */ 276 1.32 thorpej if ((ALTQ_IS_ENABLED(&ifp->if_snd) || TBR_IS_ENABLED(&ifp->if_snd)) && 277 1.32 thorpej ifp->if_start == lostart) { 278 1.32 thorpej /* 279 1.32 thorpej * If the queueing discipline needs packet classification, 280 1.32 thorpej * do it before prepending the link headers. 281 1.32 thorpej */ 282 1.84 knakahar IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family); 283 1.32 thorpej 284 1.32 thorpej M_PREPEND(m, sizeof(uint32_t), M_DONTWAIT); 285 1.88 knakahar if (m == NULL) { 286 1.114 mlelstv if_statinc(ifp, if_oerrors); 287 1.88 knakahar error = ENOBUFS; 288 1.88 knakahar goto out; 289 1.88 knakahar } 290 1.32 thorpej *(mtod(m, uint32_t *)) = dst->sa_family; 291 1.32 thorpej 292 1.89 knakahar error = if_transmit_lock(ifp, m); 293 1.88 knakahar goto out; 294 1.32 thorpej } 295 1.32 thorpej #endif /* ALTQ */ 296 1.49 jonathan 297 1.106 maxv m_tag_delete_chain(m); 298 1.32 thorpej 299 1.75 kefren #ifdef MPLS 300 1.118 thorpej bool is_mpls = false; 301 1.75 kefren if (rt != NULL && rt_gettag(rt) != NULL && 302 1.75 kefren rt_gettag(rt)->sa_family == AF_MPLS && 303 1.75 kefren (m->m_flags & (M_MCAST | M_BCAST)) == 0) { 304 1.75 kefren union mpls_shim msh; 305 1.75 kefren msh.s_addr = MPLS_GETSADDR(rt); 306 1.75 kefren if (msh.shim.label != MPLS_LABEL_IMPLNULL) { 307 1.118 thorpej is_mpls = true; 308 1.116 thorpej pktq = mpls_pktq; 309 1.75 kefren } 310 1.75 kefren } 311 1.118 thorpej if (!is_mpls) 312 1.75 kefren #endif 313 1.1 cgd switch (dst->sa_family) { 314 1.1 cgd 315 1.1 cgd #ifdef INET 316 1.1 cgd case AF_INET: 317 1.73 yamt csum_flags = m->m_pkthdr.csum_flags; 318 1.73 yamt KASSERT((csum_flags & ~(M_CSUM_IPv4|M_CSUM_UDPv4)) == 0); 319 1.73 yamt if (csum_flags != 0 && IN_LOOPBACK_NEED_CHECKSUM(csum_flags)) { 320 1.104 maxv in_undefer_cksum(m, 0, csum_flags); 321 1.108 msaitoh m->m_pkthdr.csum_flags = 0; 322 1.108 msaitoh } else { 323 1.108 msaitoh /* 324 1.108 msaitoh * Do nothing. Pass M_CSUM_IPv4 and M_CSUM_UDPv4 as 325 1.108 msaitoh * they are to tell those are calculated and good. 326 1.108 msaitoh */ 327 1.73 yamt } 328 1.79 rmind pktq = ip_pktq; 329 1.1 cgd break; 330 1.1 cgd #endif 331 1.26 itojun #ifdef INET6 332 1.26 itojun case AF_INET6: 333 1.73 yamt csum_flags = m->m_pkthdr.csum_flags; 334 1.73 yamt KASSERT((csum_flags & ~M_CSUM_UDPv6) == 0); 335 1.73 yamt if (csum_flags != 0 && 336 1.73 yamt IN6_LOOPBACK_NEED_CHECKSUM(csum_flags)) { 337 1.105 maxv in6_undefer_cksum(m, 0, csum_flags); 338 1.108 msaitoh m->m_pkthdr.csum_flags = 0; 339 1.108 msaitoh } else { 340 1.108 msaitoh /* 341 1.109 msaitoh * Do nothing. Pass M_CSUM_UDPv6 as 342 1.108 msaitoh * they are to tell those are calculated and good. 343 1.108 msaitoh */ 344 1.73 yamt } 345 1.26 itojun m->m_flags |= M_LOOP; 346 1.79 rmind pktq = ip6_pktq; 347 1.26 itojun break; 348 1.26 itojun #endif 349 1.19 christos #ifdef NETATALK 350 1.19 christos case AF_APPLETALK: 351 1.115 thorpej pktq = at_pktq2; 352 1.1 cgd break; 353 1.1 cgd #endif 354 1.1 cgd default: 355 1.119 christos rt_unhandled(__func__, ifp, dst); 356 1.1 cgd m_freem(m); 357 1.88 knakahar error = EAFNOSUPPORT; 358 1.88 knakahar goto out; 359 1.1 cgd } 360 1.79 rmind 361 1.116 thorpej KASSERT(pktq != NULL); 362 1.116 thorpej 363 1.116 thorpej error = 0; 364 1.38 thorpej s = splnet(); 365 1.116 thorpej if (__predict_true(pktq_enqueue(pktq, m, 0))) { 366 1.116 thorpej if_statadd2(ifp, if_ipackets, 1, if_ibytes, pktlen); 367 1.116 thorpej } else { 368 1.1 cgd m_freem(m); 369 1.116 thorpej if_statinc(ifp, if_oerrors); 370 1.88 knakahar error = ENOBUFS; 371 1.1 cgd } 372 1.1 cgd splx(s); 373 1.88 knakahar out: 374 1.99 ozaki KERNEL_UNLOCK_UNLESS_NET_MPSAFE(); 375 1.88 knakahar return error; 376 1.1 cgd } 377 1.32 thorpej 378 1.32 thorpej #ifdef ALTQ 379 1.57 thorpej static void 380 1.32 thorpej lostart(struct ifnet *ifp) 381 1.32 thorpej { 382 1.79 rmind for (;;) { 383 1.79 rmind pktqueue_t *pktq = NULL; 384 1.79 rmind struct mbuf *m; 385 1.119 christos struct sockaddr sa; 386 1.79 rmind size_t pktlen; 387 1.79 rmind uint32_t af; 388 1.115 thorpej int s; 389 1.32 thorpej 390 1.32 thorpej IFQ_DEQUEUE(&ifp->if_snd, m); 391 1.32 thorpej if (m == NULL) 392 1.32 thorpej return; 393 1.32 thorpej 394 1.32 thorpej af = *(mtod(m, uint32_t *)); 395 1.32 thorpej m_adj(m, sizeof(uint32_t)); 396 1.32 thorpej 397 1.32 thorpej switch (af) { 398 1.32 thorpej #ifdef INET 399 1.32 thorpej case AF_INET: 400 1.79 rmind pktq = ip_pktq; 401 1.32 thorpej break; 402 1.32 thorpej #endif 403 1.32 thorpej #ifdef INET6 404 1.32 thorpej case AF_INET6: 405 1.32 thorpej m->m_flags |= M_LOOP; 406 1.79 rmind pktq = ip6_pktq; 407 1.32 thorpej break; 408 1.32 thorpej #endif 409 1.32 thorpej #ifdef NETATALK 410 1.32 thorpej case AF_APPLETALK: 411 1.115 thorpej pktq = at_pktq2; 412 1.32 thorpej break; 413 1.32 thorpej #endif 414 1.32 thorpej default: 415 1.119 christos memset(&sa, 0, sizeof(sa)); 416 1.119 christos sa.sa_family = af; 417 1.119 christos rt_unhandled(__func__, ifp, &sa); 418 1.32 thorpej m_freem(m); 419 1.32 thorpej return; 420 1.32 thorpej } 421 1.79 rmind pktlen = m->m_pkthdr.len; 422 1.32 thorpej 423 1.115 thorpej KASSERT(pktq != NULL); 424 1.115 thorpej 425 1.38 thorpej s = splnet(); 426 1.115 thorpej if (__predict_false(pktq_enqueue(pktq, m, 0))) { 427 1.115 thorpej m_freem(m); 428 1.79 rmind splx(s); 429 1.32 thorpej return; 430 1.32 thorpej } 431 1.110 thorpej if_statadd2(ifp, if_ipackets, 1, if_ibytes, pktlen); 432 1.32 thorpej splx(s); 433 1.32 thorpej } 434 1.32 thorpej } 435 1.32 thorpej #endif /* ALTQ */ 436 1.1 cgd 437 1.1 cgd /* ARGSUSED */ 438 1.93 ozaki static void 439 1.93 ozaki loop_rtrequest(int cmd, struct rtentry *rt, 440 1.69 dyoung const struct rt_addrinfo *info) 441 1.1 cgd { 442 1.11 mycroft 443 1.1 cgd if (rt) 444 1.52 peter rt->rt_rmx.rmx_mtu = lo0ifp->if_mtu; 445 1.1 cgd } 446 1.1 cgd 447 1.1 cgd /* 448 1.1 cgd * Process an ioctl request. 449 1.1 cgd */ 450 1.1 cgd /* ARGSUSED */ 451 1.11 mycroft int 452 1.64 christos loioctl(struct ifnet *ifp, u_long cmd, void *data) 453 1.1 cgd { 454 1.30 augustss struct ifaddr *ifa; 455 1.67 dyoung struct ifreq *ifr = data; 456 1.30 augustss int error = 0; 457 1.1 cgd 458 1.1 cgd switch (cmd) { 459 1.1 cgd 460 1.70 dyoung case SIOCINITIFADDR: 461 1.1 cgd ifp->if_flags |= IFF_UP; 462 1.1 cgd ifa = (struct ifaddr *)data; 463 1.76 joerg if (ifa != NULL) 464 1.93 ozaki ifa->ifa_rtrequest = loop_rtrequest; 465 1.1 cgd /* 466 1.1 cgd * Everything else is done at a higher level. 467 1.1 cgd */ 468 1.48 jonathan break; 469 1.48 jonathan 470 1.48 jonathan case SIOCSIFMTU: 471 1.48 jonathan if ((unsigned)ifr->ifr_mtu > LOMTU_MAX) 472 1.48 jonathan error = EINVAL; 473 1.67 dyoung else if ((error = ifioctl_common(ifp, cmd, data)) == ENETRESET){ 474 1.67 dyoung error = 0; 475 1.48 jonathan } 476 1.1 cgd break; 477 1.1 cgd 478 1.8 hpeyerl case SIOCADDMULTI: 479 1.8 hpeyerl case SIOCDELMULTI: 480 1.54 peter if (ifr == NULL) { 481 1.8 hpeyerl error = EAFNOSUPPORT; /* XXX */ 482 1.8 hpeyerl break; 483 1.8 hpeyerl } 484 1.65 dyoung switch (ifreq_getaddr(cmd, ifr)->sa_family) { 485 1.8 hpeyerl 486 1.8 hpeyerl #ifdef INET 487 1.8 hpeyerl case AF_INET: 488 1.26 itojun break; 489 1.26 itojun #endif 490 1.26 itojun #ifdef INET6 491 1.26 itojun case AF_INET6: 492 1.8 hpeyerl break; 493 1.8 hpeyerl #endif 494 1.11 mycroft 495 1.8 hpeyerl default: 496 1.8 hpeyerl error = EAFNOSUPPORT; 497 1.8 hpeyerl break; 498 1.8 hpeyerl } 499 1.8 hpeyerl break; 500 1.11 mycroft 501 1.1 cgd default: 502 1.70 dyoung error = ifioctl_common(ifp, cmd, data); 503 1.1 cgd } 504 1.1 cgd return (error); 505 1.1 cgd } 506 1.90 christos 507 1.90 christos /* 508 1.90 christos * Module infrastructure 509 1.90 christos */ 510 1.90 christos #include "if_module.h" 511 1.90 christos 512 1.107 pgoyette IF_MODULE(MODULE_CLASS_DRIVER, loop, NULL) 513