if_disc.c revision 10957
15191Swollman/* 25191Swollman * Copyright (c) 1982, 1986, 1993 35191Swollman * The Regents of the University of California. All rights reserved. 45191Swollman * 55191Swollman * Redistribution and use in source and binary forms, with or without 65191Swollman * modification, are permitted provided that the following conditions 75191Swollman * are met: 85191Swollman * 1. Redistributions of source code must retain the above copyright 95191Swollman * notice, this list of conditions and the following disclaimer. 105191Swollman * 2. Redistributions in binary form must reproduce the above copyright 115191Swollman * notice, this list of conditions and the following disclaimer in the 125191Swollman * documentation and/or other materials provided with the distribution. 135191Swollman * 3. All advertising materials mentioning features or use of this software 145191Swollman * must display the following acknowledgement: 155191Swollman * This product includes software developed by the University of 165191Swollman * California, Berkeley and its contributors. 175191Swollman * 4. Neither the name of the University nor the names of its contributors 185191Swollman * may be used to endorse or promote products derived from this software 195191Swollman * without specific prior written permission. 205191Swollman * 215191Swollman * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 225191Swollman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 235191Swollman * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 245191Swollman * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 255191Swollman * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 265191Swollman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 275191Swollman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 285191Swollman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 295191Swollman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 305191Swollman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 315191Swollman * SUCH DAMAGE. 325191Swollman * 335191Swollman * From: @(#)if_loop.c 8.1 (Berkeley) 6/10/93 3410957Swollman * $Id: if_disc.c,v 1.6 1995/09/09 18:10:21 davidg Exp $ 355191Swollman */ 365191Swollman 375191Swollman/* 385191Swollman * Discard interface driver for protocol testing and timing. 395191Swollman * (Based on the loopback.) 405191Swollman */ 415191Swollman 425191Swollman#include <sys/param.h> 435191Swollman#include <sys/systm.h> 445191Swollman#include <sys/kernel.h> 455191Swollman#include <sys/mbuf.h> 465191Swollman#include <sys/socket.h> 475191Swollman#include <sys/errno.h> 485191Swollman#include <sys/ioctl.h> 495191Swollman#include <sys/time.h> 505191Swollman#include <machine/cpu.h> 515191Swollman 525191Swollman#include <net/if.h> 535191Swollman#include <net/if_types.h> 545191Swollman#include <net/netisr.h> 555191Swollman#include <net/route.h> 565191Swollman#include <net/bpf.h> 575191Swollman 585191Swollman#ifdef INET 595191Swollman#include <netinet/in.h> 605191Swollman#include <netinet/in_systm.h> 615191Swollman#include <netinet/in_var.h> 625191Swollman#include <netinet/ip.h> 635191Swollman#endif 645191Swollman 655191Swollman#ifdef NS 665191Swollman#include <netns/ns.h> 675191Swollman#include <netns/ns_if.h> 685191Swollman#endif 695191Swollman 705191Swollman#ifdef ISO 715191Swollman#include <netiso/iso.h> 725191Swollman#include <netiso/iso_var.h> 735191Swollman#endif 745191Swollman 755191Swollman#include "bpfilter.h" 765191Swollman 775191Swollman#ifdef TINY_DSMTU 785191Swollman#define DSMTU (1024+512) 795191Swollman#else 805191Swollman#define DSMTU 65532 815191Swollman#endif 825191Swollman 8310653Sdgstatic void discattach __P((void *udata)); 8410429SbdePSEUDO_SET(discattach, if_disc); 8510429Sbde 865191Swollmanstatic struct ifnet dsif; 875191Swollmanstatic int dsoutput(struct ifnet *, struct mbuf *, struct sockaddr *, 885191Swollman struct rtentry *); 895191Swollmanstatic int dsioctl(struct ifnet *, int, caddr_t); 905191Swollman 915191Swollman/* ARGSUSED */ 925191Swollmanstatic void 9310429Sbdediscattach(udata) 9410653Sdg void *udata; 955191Swollman{ 965191Swollman register struct ifnet *ifp = &dsif; 975191Swollman 985191Swollman ifp->if_name = "ds"; 995191Swollman ifp->if_mtu = DSMTU; 1005191Swollman ifp->if_flags = IFF_LOOPBACK | IFF_MULTICAST; 1015191Swollman ifp->if_ioctl = dsioctl; 1025191Swollman ifp->if_output = dsoutput; 1035191Swollman ifp->if_type = IFT_LOOP; 1045191Swollman ifp->if_hdrlen = 0; 1055191Swollman ifp->if_addrlen = 0; 1065191Swollman if_attach(ifp); 1075191Swollman#if NBPFILTER > 0 1085191Swollman bpfattach(&ifp->if_bpf, ifp, DLT_NULL, sizeof(u_int)); 1095191Swollman#endif 1105191Swollman} 1115191Swollman 1125191Swollmanstatic int 1135191Swollmandsoutput(ifp, m, dst, rt) 1145191Swollman struct ifnet *ifp; 1155191Swollman register struct mbuf *m; 1165191Swollman struct sockaddr *dst; 1175191Swollman register struct rtentry *rt; 1185191Swollman{ 1195191Swollman int s, isr; 1205191Swollman register struct ifqueue *ifq = 0; 1215191Swollman 1225191Swollman if ((m->m_flags & M_PKTHDR) == 0) 1235191Swollman panic("dsoutput no HDR"); 1245191Swollman ifp->if_lastchange = time; 1255191Swollman#if NBPFILTER > 0 12610957Swollman /* BPF write needs to be handled specially */ 12710957Swollman if (dst->sa_family == AF_UNSPEC) { 12810957Swollman dst->sa_family = *(mtod(m, int *)); 12910957Swollman m->m_len -= sizeof(int); 13010957Swollman m->m_pkthdr.len -= sizeof(int); 13110957Swollman m->m_data += sizeof(int); 13210957Swollman } 13310957Swollman 1345191Swollman if (dsif.if_bpf) { 1355191Swollman /* 1365191Swollman * We need to prepend the address family as 1375191Swollman * a four byte field. Cons up a dummy header 1385191Swollman * to pacify bpf. This is safe because bpf 1395191Swollman * will only read from the mbuf (i.e., it won't 1405191Swollman * try to free it or keep a pointer a to it). 1415191Swollman */ 1425191Swollman struct mbuf m0; 1435191Swollman u_int af = dst->sa_family; 1445191Swollman 1455191Swollman m0.m_next = m; 1465191Swollman m0.m_len = 4; 1475191Swollman m0.m_data = (char *)⁡ 1488876Srgrimes 1495191Swollman bpf_mtap(dsif.if_bpf, &m0); 1505191Swollman } 1515191Swollman#endif 1525191Swollman m->m_pkthdr.rcvif = ifp; 1535191Swollman 1545191Swollman if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) { 1555191Swollman m_freem(m); 1565191Swollman return (rt->rt_flags & RTF_BLACKHOLE ? 0 : 1575191Swollman rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH); 1585191Swollman } 1595191Swollman ifp->if_opackets++; 1605191Swollman ifp->if_obytes += m->m_pkthdr.len; 1615191Swollman 1625191Swollman m_freem(m); 1635191Swollman return 0; 1645191Swollman} 1655191Swollman 1665191Swollman/* ARGSUSED */ 1675191Swollmanstatic void 1685191Swollmandsrtrequest(cmd, rt, sa) 1695191Swollman int cmd; 1705191Swollman struct rtentry *rt; 1715191Swollman struct sockaddr *sa; 1725191Swollman{ 1735191Swollman if (rt) 1745191Swollman rt->rt_rmx.rmx_mtu = DSMTU; 1755191Swollman} 1765191Swollman 1775191Swollman/* 1785191Swollman * Process an ioctl request. 1795191Swollman */ 1805191Swollman/* ARGSUSED */ 1815191Swollmanint 1825191Swollmandsioctl(ifp, cmd, data) 1835191Swollman register struct ifnet *ifp; 1845191Swollman int cmd; 1855191Swollman caddr_t data; 1865191Swollman{ 1875191Swollman register struct ifaddr *ifa; 1885191Swollman register struct ifreq *ifr = (struct ifreq *)data; 1895191Swollman register int error = 0; 1905191Swollman 1915191Swollman switch (cmd) { 1925191Swollman 1935191Swollman case SIOCSIFADDR: 1945191Swollman ifp->if_flags |= IFF_UP; 1955191Swollman ifa = (struct ifaddr *)data; 1965191Swollman if (ifa != 0) 1975191Swollman ifa->ifa_rtrequest = dsrtrequest; 1985191Swollman /* 1995191Swollman * Everything else is done at a higher level. 2005191Swollman */ 2015191Swollman break; 2025191Swollman 2035191Swollman case SIOCADDMULTI: 2045191Swollman case SIOCDELMULTI: 2055191Swollman if (ifr == 0) { 2065191Swollman error = EAFNOSUPPORT; /* XXX */ 2075191Swollman break; 2085191Swollman } 2095191Swollman switch (ifr->ifr_addr.sa_family) { 2105191Swollman 2115191Swollman#ifdef INET 2125191Swollman case AF_INET: 2135191Swollman break; 2145191Swollman#endif 2155191Swollman 2165191Swollman default: 2175191Swollman error = EAFNOSUPPORT; 2185191Swollman break; 2195191Swollman } 2205191Swollman break; 2215191Swollman 2225191Swollman case SIOCSIFMTU: 2235191Swollman ifp->if_mtu = ifr->ifr_mtu; 2245191Swollman break; 2255191Swollman 2265191Swollman default: 2275191Swollman error = EINVAL; 2285191Swollman } 2295191Swollman return (error); 2305191Swollman} 231