159d8d13fSGarrett Wollman /* 259d8d13fSGarrett Wollman * Copyright (c) 1982, 1986, 1993 359d8d13fSGarrett Wollman * The Regents of the University of California. All rights reserved. 459d8d13fSGarrett Wollman * 559d8d13fSGarrett Wollman * Redistribution and use in source and binary forms, with or without 659d8d13fSGarrett Wollman * modification, are permitted provided that the following conditions 759d8d13fSGarrett Wollman * are met: 859d8d13fSGarrett Wollman * 1. Redistributions of source code must retain the above copyright 959d8d13fSGarrett Wollman * notice, this list of conditions and the following disclaimer. 1059d8d13fSGarrett Wollman * 2. Redistributions in binary form must reproduce the above copyright 1159d8d13fSGarrett Wollman * notice, this list of conditions and the following disclaimer in the 1259d8d13fSGarrett Wollman * documentation and/or other materials provided with the distribution. 1359d8d13fSGarrett Wollman * 3. All advertising materials mentioning features or use of this software 1459d8d13fSGarrett Wollman * must display the following acknowledgement: 1559d8d13fSGarrett Wollman * This product includes software developed by the University of 1659d8d13fSGarrett Wollman * California, Berkeley and its contributors. 1759d8d13fSGarrett Wollman * 4. Neither the name of the University nor the names of its contributors 1859d8d13fSGarrett Wollman * may be used to endorse or promote products derived from this software 1959d8d13fSGarrett Wollman * without specific prior written permission. 2059d8d13fSGarrett Wollman * 2159d8d13fSGarrett Wollman * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2259d8d13fSGarrett Wollman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2359d8d13fSGarrett Wollman * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2459d8d13fSGarrett Wollman * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2559d8d13fSGarrett Wollman * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2659d8d13fSGarrett Wollman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2759d8d13fSGarrett Wollman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2859d8d13fSGarrett Wollman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2959d8d13fSGarrett Wollman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3059d8d13fSGarrett Wollman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3159d8d13fSGarrett Wollman * SUCH DAMAGE. 3259d8d13fSGarrett Wollman * 3359d8d13fSGarrett Wollman * From: @(#)if_loop.c 8.1 (Berkeley) 6/10/93 34963e4c2aSGarrett Wollman * $Id: if_disc.c,v 1.6 1995/09/09 18:10:21 davidg Exp $ 3559d8d13fSGarrett Wollman */ 3659d8d13fSGarrett Wollman 3759d8d13fSGarrett Wollman /* 3859d8d13fSGarrett Wollman * Discard interface driver for protocol testing and timing. 3959d8d13fSGarrett Wollman * (Based on the loopback.) 4059d8d13fSGarrett Wollman */ 4159d8d13fSGarrett Wollman 4259d8d13fSGarrett Wollman #include <sys/param.h> 4359d8d13fSGarrett Wollman #include <sys/systm.h> 4459d8d13fSGarrett Wollman #include <sys/kernel.h> 4559d8d13fSGarrett Wollman #include <sys/mbuf.h> 4659d8d13fSGarrett Wollman #include <sys/socket.h> 4759d8d13fSGarrett Wollman #include <sys/errno.h> 4859d8d13fSGarrett Wollman #include <sys/ioctl.h> 4959d8d13fSGarrett Wollman #include <sys/time.h> 5059d8d13fSGarrett Wollman #include <machine/cpu.h> 5159d8d13fSGarrett Wollman 5259d8d13fSGarrett Wollman #include <net/if.h> 5359d8d13fSGarrett Wollman #include <net/if_types.h> 5459d8d13fSGarrett Wollman #include <net/netisr.h> 5559d8d13fSGarrett Wollman #include <net/route.h> 5659d8d13fSGarrett Wollman #include <net/bpf.h> 5759d8d13fSGarrett Wollman 5859d8d13fSGarrett Wollman #ifdef INET 5959d8d13fSGarrett Wollman #include <netinet/in.h> 6059d8d13fSGarrett Wollman #include <netinet/in_systm.h> 6159d8d13fSGarrett Wollman #include <netinet/in_var.h> 6259d8d13fSGarrett Wollman #include <netinet/ip.h> 6359d8d13fSGarrett Wollman #endif 6459d8d13fSGarrett Wollman 6559d8d13fSGarrett Wollman #ifdef NS 6659d8d13fSGarrett Wollman #include <netns/ns.h> 6759d8d13fSGarrett Wollman #include <netns/ns_if.h> 6859d8d13fSGarrett Wollman #endif 6959d8d13fSGarrett Wollman 7059d8d13fSGarrett Wollman #ifdef ISO 7159d8d13fSGarrett Wollman #include <netiso/iso.h> 7259d8d13fSGarrett Wollman #include <netiso/iso_var.h> 7359d8d13fSGarrett Wollman #endif 7459d8d13fSGarrett Wollman 7559d8d13fSGarrett Wollman #include "bpfilter.h" 7659d8d13fSGarrett Wollman 7759d8d13fSGarrett Wollman #ifdef TINY_DSMTU 7859d8d13fSGarrett Wollman #define DSMTU (1024+512) 7959d8d13fSGarrett Wollman #else 8059d8d13fSGarrett Wollman #define DSMTU 65532 8159d8d13fSGarrett Wollman #endif 8259d8d13fSGarrett Wollman 834590fd3aSDavid Greenman static void discattach __P((void *udata)); 84b6f5c0b8SBruce Evans PSEUDO_SET(discattach, if_disc); 85b6f5c0b8SBruce Evans 8659d8d13fSGarrett Wollman static struct ifnet dsif; 8759d8d13fSGarrett Wollman static int dsoutput(struct ifnet *, struct mbuf *, struct sockaddr *, 8859d8d13fSGarrett Wollman struct rtentry *); 8959d8d13fSGarrett Wollman static int dsioctl(struct ifnet *, int, caddr_t); 9059d8d13fSGarrett Wollman 9159d8d13fSGarrett Wollman /* ARGSUSED */ 9259d8d13fSGarrett Wollman static void 93b6f5c0b8SBruce Evans discattach(udata) 944590fd3aSDavid Greenman void *udata; 9559d8d13fSGarrett Wollman { 9659d8d13fSGarrett Wollman register struct ifnet *ifp = &dsif; 9759d8d13fSGarrett Wollman 9859d8d13fSGarrett Wollman ifp->if_name = "ds"; 9959d8d13fSGarrett Wollman ifp->if_mtu = DSMTU; 10059d8d13fSGarrett Wollman ifp->if_flags = IFF_LOOPBACK | IFF_MULTICAST; 10159d8d13fSGarrett Wollman ifp->if_ioctl = dsioctl; 10259d8d13fSGarrett Wollman ifp->if_output = dsoutput; 10359d8d13fSGarrett Wollman ifp->if_type = IFT_LOOP; 10459d8d13fSGarrett Wollman ifp->if_hdrlen = 0; 10559d8d13fSGarrett Wollman ifp->if_addrlen = 0; 10659d8d13fSGarrett Wollman if_attach(ifp); 10759d8d13fSGarrett Wollman #if NBPFILTER > 0 10859d8d13fSGarrett Wollman bpfattach(&ifp->if_bpf, ifp, DLT_NULL, sizeof(u_int)); 10959d8d13fSGarrett Wollman #endif 11059d8d13fSGarrett Wollman } 11159d8d13fSGarrett Wollman 11259d8d13fSGarrett Wollman static int 11359d8d13fSGarrett Wollman dsoutput(ifp, m, dst, rt) 11459d8d13fSGarrett Wollman struct ifnet *ifp; 11559d8d13fSGarrett Wollman register struct mbuf *m; 11659d8d13fSGarrett Wollman struct sockaddr *dst; 11759d8d13fSGarrett Wollman register struct rtentry *rt; 11859d8d13fSGarrett Wollman { 11959d8d13fSGarrett Wollman int s, isr; 12059d8d13fSGarrett Wollman register struct ifqueue *ifq = 0; 12159d8d13fSGarrett Wollman 12259d8d13fSGarrett Wollman if ((m->m_flags & M_PKTHDR) == 0) 12359d8d13fSGarrett Wollman panic("dsoutput no HDR"); 12459d8d13fSGarrett Wollman ifp->if_lastchange = time; 12559d8d13fSGarrett Wollman #if NBPFILTER > 0 126963e4c2aSGarrett Wollman /* BPF write needs to be handled specially */ 127963e4c2aSGarrett Wollman if (dst->sa_family == AF_UNSPEC) { 128963e4c2aSGarrett Wollman dst->sa_family = *(mtod(m, int *)); 129963e4c2aSGarrett Wollman m->m_len -= sizeof(int); 130963e4c2aSGarrett Wollman m->m_pkthdr.len -= sizeof(int); 131963e4c2aSGarrett Wollman m->m_data += sizeof(int); 132963e4c2aSGarrett Wollman } 133963e4c2aSGarrett Wollman 13459d8d13fSGarrett Wollman if (dsif.if_bpf) { 13559d8d13fSGarrett Wollman /* 13659d8d13fSGarrett Wollman * We need to prepend the address family as 13759d8d13fSGarrett Wollman * a four byte field. Cons up a dummy header 13859d8d13fSGarrett Wollman * to pacify bpf. This is safe because bpf 13959d8d13fSGarrett Wollman * will only read from the mbuf (i.e., it won't 14059d8d13fSGarrett Wollman * try to free it or keep a pointer a to it). 14159d8d13fSGarrett Wollman */ 14259d8d13fSGarrett Wollman struct mbuf m0; 14359d8d13fSGarrett Wollman u_int af = dst->sa_family; 14459d8d13fSGarrett Wollman 14559d8d13fSGarrett Wollman m0.m_next = m; 14659d8d13fSGarrett Wollman m0.m_len = 4; 14759d8d13fSGarrett Wollman m0.m_data = (char *)⁡ 14859d8d13fSGarrett Wollman 14959d8d13fSGarrett Wollman bpf_mtap(dsif.if_bpf, &m0); 15059d8d13fSGarrett Wollman } 15159d8d13fSGarrett Wollman #endif 15259d8d13fSGarrett Wollman m->m_pkthdr.rcvif = ifp; 15359d8d13fSGarrett Wollman 15459d8d13fSGarrett Wollman if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) { 15559d8d13fSGarrett Wollman m_freem(m); 15659d8d13fSGarrett Wollman return (rt->rt_flags & RTF_BLACKHOLE ? 0 : 15759d8d13fSGarrett Wollman rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH); 15859d8d13fSGarrett Wollman } 15959d8d13fSGarrett Wollman ifp->if_opackets++; 16059d8d13fSGarrett Wollman ifp->if_obytes += m->m_pkthdr.len; 16159d8d13fSGarrett Wollman 16259d8d13fSGarrett Wollman m_freem(m); 16359d8d13fSGarrett Wollman return 0; 16459d8d13fSGarrett Wollman } 16559d8d13fSGarrett Wollman 16659d8d13fSGarrett Wollman /* ARGSUSED */ 16759d8d13fSGarrett Wollman static void 16859d8d13fSGarrett Wollman dsrtrequest(cmd, rt, sa) 16959d8d13fSGarrett Wollman int cmd; 17059d8d13fSGarrett Wollman struct rtentry *rt; 17159d8d13fSGarrett Wollman struct sockaddr *sa; 17259d8d13fSGarrett Wollman { 17359d8d13fSGarrett Wollman if (rt) 17459d8d13fSGarrett Wollman rt->rt_rmx.rmx_mtu = DSMTU; 17559d8d13fSGarrett Wollman } 17659d8d13fSGarrett Wollman 17759d8d13fSGarrett Wollman /* 17859d8d13fSGarrett Wollman * Process an ioctl request. 17959d8d13fSGarrett Wollman */ 18059d8d13fSGarrett Wollman /* ARGSUSED */ 18159d8d13fSGarrett Wollman int 18259d8d13fSGarrett Wollman dsioctl(ifp, cmd, data) 18359d8d13fSGarrett Wollman register struct ifnet *ifp; 18459d8d13fSGarrett Wollman int cmd; 18559d8d13fSGarrett Wollman caddr_t data; 18659d8d13fSGarrett Wollman { 18759d8d13fSGarrett Wollman register struct ifaddr *ifa; 18859d8d13fSGarrett Wollman register struct ifreq *ifr = (struct ifreq *)data; 18959d8d13fSGarrett Wollman register int error = 0; 19059d8d13fSGarrett Wollman 19159d8d13fSGarrett Wollman switch (cmd) { 19259d8d13fSGarrett Wollman 19359d8d13fSGarrett Wollman case SIOCSIFADDR: 19459d8d13fSGarrett Wollman ifp->if_flags |= IFF_UP; 19559d8d13fSGarrett Wollman ifa = (struct ifaddr *)data; 19659d8d13fSGarrett Wollman if (ifa != 0) 19759d8d13fSGarrett Wollman ifa->ifa_rtrequest = dsrtrequest; 19859d8d13fSGarrett Wollman /* 19959d8d13fSGarrett Wollman * Everything else is done at a higher level. 20059d8d13fSGarrett Wollman */ 20159d8d13fSGarrett Wollman break; 20259d8d13fSGarrett Wollman 20359d8d13fSGarrett Wollman case SIOCADDMULTI: 20459d8d13fSGarrett Wollman case SIOCDELMULTI: 20559d8d13fSGarrett Wollman if (ifr == 0) { 20659d8d13fSGarrett Wollman error = EAFNOSUPPORT; /* XXX */ 20759d8d13fSGarrett Wollman break; 20859d8d13fSGarrett Wollman } 20959d8d13fSGarrett Wollman switch (ifr->ifr_addr.sa_family) { 21059d8d13fSGarrett Wollman 21159d8d13fSGarrett Wollman #ifdef INET 21259d8d13fSGarrett Wollman case AF_INET: 21359d8d13fSGarrett Wollman break; 21459d8d13fSGarrett Wollman #endif 21559d8d13fSGarrett Wollman 21659d8d13fSGarrett Wollman default: 21759d8d13fSGarrett Wollman error = EAFNOSUPPORT; 21859d8d13fSGarrett Wollman break; 21959d8d13fSGarrett Wollman } 22059d8d13fSGarrett Wollman break; 22159d8d13fSGarrett Wollman 22259d8d13fSGarrett Wollman case SIOCSIFMTU: 22359d8d13fSGarrett Wollman ifp->if_mtu = ifr->ifr_mtu; 22459d8d13fSGarrett Wollman break; 22559d8d13fSGarrett Wollman 22659d8d13fSGarrett Wollman default: 22759d8d13fSGarrett Wollman error = EINVAL; 22859d8d13fSGarrett Wollman } 22959d8d13fSGarrett Wollman return (error); 23059d8d13fSGarrett Wollman } 231