if_disc.c revision 87912
117683Spst/* 239291Sfenner * Copyright (c) 1982, 1986, 1993 317683Spst * The Regents of the University of California. All rights reserved. 417683Spst * 517683Spst * Redistribution and use in source and binary forms, with or without 617683Spst * modification, are permitted provided that the following conditions 717683Spst * are met: 817683Spst * 1. Redistributions of source code must retain the above copyright 917683Spst * notice, this list of conditions and the following disclaimer. 1017683Spst * 2. Redistributions in binary form must reproduce the above copyright 1117683Spst * notice, this list of conditions and the following disclaimer in the 1217683Spst * documentation and/or other materials provided with the distribution. 1317683Spst * 3. All advertising materials mentioning features or use of this software 1417683Spst * must display the following acknowledgement: 1517683Spst * This product includes software developed by the University of 1617683Spst * California, Berkeley and its contributors. 1717683Spst * 4. Neither the name of the University nor the names of its contributors 1817683Spst * may be used to endorse or promote products derived from this software 1917683Spst * without specific prior written permission. 2017683Spst * 2117683Spst * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22127664Sbms * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23214518Srpaulo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2417683Spst * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2517683Spst * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2675107Sfenner * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2775107Sfenner * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2875107Sfenner * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2975107Sfenner * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3017683Spst * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3117683Spst * SUCH DAMAGE. 3217683Spst * 3317683Spst * From: @(#)if_loop.c 8.1 (Berkeley) 6/10/93 3417683Spst * $FreeBSD: head/sys/net/if_disc.c 87912 2001-12-14 19:28:06Z jlemon $ 3517683Spst */ 3617683Spst 3717683Spst/* 3817683Spst * Discard interface driver for protocol testing and timing. 3917683Spst * (Based on the loopback.) 4017683Spst */ 4117683Spst 4217683Spst#include <sys/param.h> 4317683Spst#include <sys/systm.h> 4417683Spst#include <sys/kernel.h> 4517683Spst#include <sys/module.h> 4617683Spst#include <sys/mbuf.h> 4717683Spst#include <sys/socket.h> 4817683Spst#include <sys/sockio.h> 4917683Spst 5017683Spst#include <net/if.h> 5117683Spst#include <net/if_types.h> 5217683Spst#include <net/route.h> 5317683Spst#include <net/bpf.h> 5417683Spst 5517683Spst#include "opt_inet.h" 5617683Spst#include "opt_inet6.h" 5717683Spst 5817683Spst#ifdef TINY_DSMTU 5917683Spst#define DSMTU (1024+512) 6017683Spst#else 61127664Sbms#define DSMTU 65532 62127664Sbms#endif 6317683Spst 6417683Spststatic void discattach(void); 6517683Spst 66146768Ssamstatic struct ifnet discif; 67146768Ssamstatic int discoutput(struct ifnet *, struct mbuf *, 6817683Spst struct sockaddr *, struct rtentry *); 6917683Spststatic void discrtrequest(int, struct rtentry *, struct rt_addrinfo *); 7017683Spststatic int discioctl(struct ifnet *, u_long, caddr_t); 71127664Sbms 72127664Sbmsstatic void 73127664Sbmsdiscattach(void) 74127664Sbms{ 75127664Sbms struct ifnet *ifp = &discif; 76127664Sbms 77127664Sbms ifp->if_name = "ds"; 78127664Sbms ifp->if_mtu = DSMTU; 79127664Sbms ifp->if_flags = IFF_LOOPBACK | IFF_MULTICAST; 80127664Sbms ifp->if_ioctl = discioctl; 81127664Sbms ifp->if_output = discoutput; 82127664Sbms ifp->if_type = IFT_LOOP; 8317683Spst ifp->if_hdrlen = 0; 8417683Spst ifp->if_addrlen = 0; 8517683Spst ifp->if_snd.ifq_maxlen = 20; 8617683Spst if_attach(ifp); 8717683Spst bpfattach(ifp, DLT_NULL, sizeof(u_int)); 8817683Spst} 89127664Sbms 9017683Spststatic int 9117683Spstdisc_modevent(module_t mod, int type, void *data) 9217683Spst{ 9317683Spst switch (type) { 9475107Sfenner case MOD_LOAD: 9575107Sfenner discattach(); 9617683Spst break; 9717683Spst case MOD_UNLOAD: 9817683Spst printf("if_disc module unload - not possible for this module type\n"); 9917683Spst return EINVAL; 100146768Ssam } 101146768Ssam return 0; 102146768Ssam} 103240725Skevlo 104146768Ssamstatic moduledata_t disc_mod = { 105146768Ssam "if_disc", 106146768Ssam disc_modevent, 107146768Ssam NULL 108146768Ssam}; 109146768Ssam 11017683SpstDECLARE_MODULE(if_disc, disc_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); 11117683Spst 11217683Spststatic int 113127664Sbmsdiscoutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, 114127664Sbms struct rtentry *rt) 115127664Sbms{ 116127664Sbms if ((m->m_flags & M_PKTHDR) == 0) 117127664Sbms panic("discoutput no HDR"); 118127664Sbms /* BPF write needs to be handled specially */ 119127664Sbms if (dst->sa_family == AF_UNSPEC) { 120127664Sbms dst->sa_family = *(mtod(m, int *)); 121127664Sbms m->m_len -= sizeof(int); 122127664Sbms m->m_pkthdr.len -= sizeof(int); 123127664Sbms m->m_data += sizeof(int); 12417683Spst } 12517683Spst 12617683Spst if (discif.if_bpf) { 12717683Spst /* 128127664Sbms * We need to prepend the address family as 129127664Sbms * a four byte field. Cons up a dummy header 13017683Spst * to pacify bpf. This is safe because bpf 13117683Spst * will only read from the mbuf (i.e., it won't 13217683Spst * try to free it or keep a pointer a to it). 13317683Spst */ 13417683Spst struct mbuf m0; 13517683Spst u_int af = dst->sa_family; 13617683Spst 13717683Spst m0.m_next = m; 138127664Sbms m0.m_len = 4; 139146768Ssam m0.m_data = (char *)⁡ 140146768Ssam 141146768Ssam bpf_mtap(&discif, &m0); 142146768Ssam } 143146768Ssam m->m_pkthdr.rcvif = ifp; 144146768Ssam 145146768Ssam ifp->if_opackets++; 146146768Ssam ifp->if_obytes += m->m_pkthdr.len; 147146768Ssam 148146768Ssam m_freem(m); 149146768Ssam return 0; 150146768Ssam} 151146768Ssam 152146768Ssam/* ARGSUSED */ 153146768Ssamstatic void 154146768Ssamdiscrtrequest(int cmd, struct rtentry *rt, struct rt_addrinfo *info) 155146768Ssam{ 156146768Ssam if (rt) 157127664Sbms rt->rt_rmx.rmx_mtu = DSMTU; 15817683Spst} 15917683Spst 16017683Spst/* 16117683Spst * Process an ioctl request. 16217683Spst */ 16375107Sfennerstatic int 16417683Spstdiscioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 16575107Sfenner{ 16675107Sfenner struct ifaddr *ifa; 16717683Spst struct ifreq *ifr = (struct ifreq *)data; 16817683Spst int error = 0; 16917683Spst 17098530Sfenner switch (cmd) { 17198530Sfenner 17298530Sfenner case SIOCSIFADDR: 17398530Sfenner ifp->if_flags |= IFF_UP; 17498530Sfenner ifa = (struct ifaddr *)data; 17598530Sfenner if (ifa != 0) 17698530Sfenner ifa->ifa_rtrequest = discrtrequest; 17798530Sfenner /* 17898530Sfenner * Everything else is done at a higher level. 17998530Sfenner */ 18098530Sfenner break; 18198530Sfenner 18298530Sfenner case SIOCADDMULTI: 18317683Spst case SIOCDELMULTI: 18417683Spst if (ifr == 0) { 18517683Spst error = EAFNOSUPPORT; /* XXX */ 18617683Spst break; 18798530Sfenner } 18898530Sfenner switch (ifr->ifr_addr.sa_family) { 18998530Sfenner 19098530Sfenner#ifdef INET 19198530Sfenner case AF_INET: 19217683Spst break; 19317683Spst#endif 19417683Spst#ifdef INET6 19517683Spst case AF_INET6: 19617683Spst break; 197190225Srpaulo#endif 198190225Srpaulo 19917683Spst default: 20017683Spst error = EAFNOSUPPORT; 20117683Spst break; 20217683Spst } 20317683Spst break; 20475107Sfenner 20575107Sfenner case SIOCSIFMTU: 20675107Sfenner ifp->if_mtu = ifr->ifr_mtu; 20717683Spst break; 20817683Spst 20917683Spst default: 210190225Srpaulo error = EINVAL; 21175107Sfenner } 21217683Spst return (error); 21317683Spst} 21417683Spst