if_disc.c revision 32350
1221163Sadrian/* 2221163Sadrian * Copyright (c) 1982, 1986, 1993 3221163Sadrian * The Regents of the University of California. All rights reserved. 4221163Sadrian * 5221163Sadrian * Redistribution and use in source and binary forms, with or without 6221163Sadrian * modification, are permitted provided that the following conditions 7221163Sadrian * are met: 8221163Sadrian * 1. Redistributions of source code must retain the above copyright 9221163Sadrian * notice, this list of conditions and the following disclaimer. 10221163Sadrian * 2. Redistributions in binary form must reproduce the above copyright 11221163Sadrian * notice, this list of conditions and the following disclaimer in the 12221163Sadrian * documentation and/or other materials provided with the distribution. 13221163Sadrian * 3. All advertising materials mentioning features or use of this software 14221163Sadrian * must display the following acknowledgement: 15221163Sadrian * This product includes software developed by the University of 16221163Sadrian * California, Berkeley and its contributors. 17221163Sadrian * 4. Neither the name of the University nor the names of its contributors 18221163Sadrian * may be used to endorse or promote products derived from this software 19221163Sadrian * without specific prior written permission. 20221163Sadrian * 21221163Sadrian * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22221163Sadrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23221163Sadrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24221163Sadrian * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25221163Sadrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26221163Sadrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27221163Sadrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28221163Sadrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29221163Sadrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30221163Sadrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31221163Sadrian * SUCH DAMAGE. 32221163Sadrian * 33221163Sadrian * From: @(#)if_loop.c 8.1 (Berkeley) 6/10/93 34221163Sadrian * $Id: if_disc.c,v 1.18 1997/08/02 14:32:36 bde Exp $ 35221163Sadrian */ 36221163Sadrian 37221163Sadrian/* 38221163Sadrian * Discard interface driver for protocol testing and timing. 39221163Sadrian * (Based on the loopback.) 40221163Sadrian */ 41221163Sadrian 42221163Sadrian#include <sys/param.h> 43221163Sadrian#include <sys/systm.h> 44221163Sadrian#include <sys/kernel.h> 45221163Sadrian#include <sys/mbuf.h> 46221163Sadrian#include <sys/socket.h> 47221163Sadrian#include <sys/sockio.h> 48221163Sadrian 49221163Sadrian#include <net/if.h> 50221163Sadrian#include <net/if_types.h> 51221163Sadrian#include <net/route.h> 52221163Sadrian#include <net/bpf.h> 53221163Sadrian 54221163Sadrian#include "bpfilter.h" 55221163Sadrian#include "opt_inet.h" 56221163Sadrian 57221163Sadrian#ifdef TINY_DSMTU 58221163Sadrian#define DSMTU (1024+512) 59221163Sadrian#else 60221163Sadrian#define DSMTU 65532 61221163Sadrian#endif 62221163Sadrian 63221163Sadrianstatic void discattach __P((void *dummy)); 64221163SadrianPSEUDO_SET(discattach, if_disc); 65221163Sadrian 66221163Sadrianstatic struct ifnet dsif; 67221163Sadrianstatic int dsoutput(struct ifnet *, struct mbuf *, struct sockaddr *, 68221163Sadrian struct rtentry *); 69221163Sadrianstatic void dsrtrequest(int cmd, struct rtentry *rt, struct sockaddr *sa); 70221163Sadrianstatic int dsioctl(struct ifnet *, int, caddr_t); 71221163Sadrian 72221163Sadrian/* ARGSUSED */ 73221163Sadrianstatic void 74221163Sadriandiscattach(dummy) 75221163Sadrian void *dummy; 76221163Sadrian{ 77221163Sadrian register struct ifnet *ifp = &dsif; 78221163Sadrian 79221163Sadrian ifp->if_name = "ds"; 80221163Sadrian ifp->if_mtu = DSMTU; 81221163Sadrian ifp->if_flags = IFF_LOOPBACK | IFF_MULTICAST; 82221163Sadrian ifp->if_ioctl = dsioctl; 83221163Sadrian ifp->if_output = dsoutput; 84221163Sadrian ifp->if_type = IFT_LOOP; 85221163Sadrian ifp->if_hdrlen = 0; 86221163Sadrian ifp->if_addrlen = 0; 87221163Sadrian if_attach(ifp); 88221163Sadrian#if NBPFILTER > 0 89221163Sadrian bpfattach(ifp, DLT_NULL, sizeof(u_int)); 90221163Sadrian#endif 91221163Sadrian} 92221163Sadrian 93221163Sadrianstatic int 94221163Sadriandsoutput(ifp, m, dst, rt) 95221163Sadrian struct ifnet *ifp; 96221163Sadrian register struct mbuf *m; 97221163Sadrian struct sockaddr *dst; 98221163Sadrian register struct rtentry *rt; 99221163Sadrian{ 100221163Sadrian if ((m->m_flags & M_PKTHDR) == 0) 101221163Sadrian panic("dsoutput no HDR"); 102221163Sadrian#if NBPFILTER > 0 103221163Sadrian /* BPF write needs to be handled specially */ 104221163Sadrian if (dst->sa_family == AF_UNSPEC) { 105221163Sadrian dst->sa_family = *(mtod(m, int *)); 106221163Sadrian m->m_len -= sizeof(int); 107221163Sadrian m->m_pkthdr.len -= sizeof(int); 108221163Sadrian m->m_data += sizeof(int); 109221163Sadrian } 110221163Sadrian 111221163Sadrian if (dsif.if_bpf) { 112221163Sadrian /* 113221163Sadrian * We need to prepend the address family as 114221163Sadrian * a four byte field. Cons up a dummy header 115221163Sadrian * to pacify bpf. This is safe because bpf 116221163Sadrian * will only read from the mbuf (i.e., it won't 117221163Sadrian * try to free it or keep a pointer a to it). 118221163Sadrian */ 119221163Sadrian struct mbuf m0; 120221163Sadrian u_int af = dst->sa_family; 121221163Sadrian 122221163Sadrian m0.m_next = m; 123221163Sadrian m0.m_len = 4; 124221163Sadrian m0.m_data = (char *)⁡ 125221163Sadrian 126221163Sadrian bpf_mtap(&dsif, &m0); 127221163Sadrian } 128221163Sadrian#endif 129221163Sadrian m->m_pkthdr.rcvif = ifp; 130221163Sadrian 131221163Sadrian ifp->if_opackets++; 132221163Sadrian ifp->if_obytes += m->m_pkthdr.len; 133221163Sadrian 134221163Sadrian m_freem(m); 135221163Sadrian return 0; 136221163Sadrian} 137221163Sadrian 138221163Sadrian/* ARGSUSED */ 139221163Sadrianstatic void 140221163Sadriandsrtrequest(cmd, rt, sa) 141221163Sadrian int cmd; 142221163Sadrian struct rtentry *rt; 143221163Sadrian struct sockaddr *sa; 144221163Sadrian{ 145221163Sadrian if (rt) 146221163Sadrian rt->rt_rmx.rmx_mtu = DSMTU; 147221163Sadrian} 148221163Sadrian 149221163Sadrian/* 150221163Sadrian * Process an ioctl request. 151221163Sadrian */ 152221163Sadrian/* ARGSUSED */ 153221163Sadrianstatic int 154221163Sadriandsioctl(ifp, cmd, data) 155221163Sadrian register struct ifnet *ifp; 156221163Sadrian int cmd; 157221163Sadrian caddr_t data; 158221163Sadrian{ 159221163Sadrian register struct ifaddr *ifa; 160221163Sadrian register struct ifreq *ifr = (struct ifreq *)data; 161221163Sadrian register int error = 0; 162221163Sadrian 163221163Sadrian switch (cmd) { 164221163Sadrian 165221163Sadrian case SIOCSIFADDR: 166221163Sadrian ifp->if_flags |= IFF_UP; 167221163Sadrian ifa = (struct ifaddr *)data; 168221163Sadrian if (ifa != 0) 169221163Sadrian ifa->ifa_rtrequest = dsrtrequest; 170221163Sadrian /* 171221163Sadrian * Everything else is done at a higher level. 172221163Sadrian */ 173221163Sadrian break; 174221163Sadrian 175221163Sadrian case SIOCADDMULTI: 176221163Sadrian case SIOCDELMULTI: 177221163Sadrian if (ifr == 0) { 178221163Sadrian error = EAFNOSUPPORT; /* XXX */ 179221163Sadrian break; 180221163Sadrian } 181221163Sadrian switch (ifr->ifr_addr.sa_family) { 182221163Sadrian 183221163Sadrian#ifdef INET 184221163Sadrian case AF_INET: 185221163Sadrian break; 186221163Sadrian#endif 187221163Sadrian 188221163Sadrian default: 189221163Sadrian error = EAFNOSUPPORT; 190221163Sadrian break; 191221163Sadrian } 192221163Sadrian break; 193221163Sadrian 194221163Sadrian case SIOCSIFMTU: 195221163Sadrian ifp->if_mtu = ifr->ifr_mtu; 196221163Sadrian break; 197221163Sadrian 198221163Sadrian default: 199221163Sadrian error = EINVAL; 200221163Sadrian } 201221163Sadrian return (error); 202221163Sadrian} 203221163Sadrian