if_disc.c revision 113255
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 3450477Speter * $FreeBSD: head/sys/net/if_disc.c 113255 2003-04-08 14:25:47Z des $ 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> 4597290Sbrooks#include <sys/malloc.h> 4671862Speter#include <sys/module.h> 475191Swollman#include <sys/mbuf.h> 485191Swollman#include <sys/socket.h> 4924204Sbde#include <sys/sockio.h> 505191Swollman 515191Swollman#include <net/if.h> 525191Swollman#include <net/if_types.h> 535191Swollman#include <net/route.h> 545191Swollman#include <net/bpf.h> 555191Swollman 5632350Seivind#include "opt_inet.h" 5754263Sshin#include "opt_inet6.h" 585191Swollman 595191Swollman#ifdef TINY_DSMTU 605191Swollman#define DSMTU (1024+512) 615191Swollman#else 625191Swollman#define DSMTU 65532 635191Swollman#endif 645191Swollman 6597290Sbrooks#define DISCNAME "disc" 6610429Sbde 6797290Sbrooksstruct disc_softc { 6897290Sbrooks struct ifnet sc_if; /* must be first */ 6997290Sbrooks LIST_ENTRY(disc_softc) sc_list; 7097290Sbrooks}; 715191Swollman 7297290Sbrooksstatic int discoutput(struct ifnet *, struct mbuf *, 7397290Sbrooks struct sockaddr *, struct rtentry *); 7497290Sbrooksstatic void discrtrequest(int, struct rtentry *, struct rt_addrinfo *); 7597290Sbrooksstatic int discioctl(struct ifnet *, u_long, caddr_t); 7697290Sbrooksstatic int disc_clone_create(struct if_clone *, int); 7797290Sbrooksstatic void disc_clone_destroy(struct ifnet *); 7897290Sbrooks 7997290Sbrooksstatic MALLOC_DEFINE(M_DISC, DISCNAME, "Discard interface"); 8097290Sbrooksstatic LIST_HEAD(, disc_softc) disc_softc_list; 8197290Sbrooksstatic struct if_clone disc_cloner = IF_CLONE_INITIALIZER(DISCNAME, 8297290Sbrooks disc_clone_create, disc_clone_destroy, 0, IF_MAXUNIT); 8397290Sbrooks 8497290Sbrooksstatic int 8597290Sbrooksdisc_clone_create(struct if_clone *ifc, int unit) 865191Swollman{ 8797290Sbrooks struct ifnet *ifp; 8897290Sbrooks struct disc_softc *sc; 895191Swollman 90111119Simp sc = malloc(sizeof(struct disc_softc), M_DISC, M_WAITOK); 9197290Sbrooks bzero(sc, sizeof(struct disc_softc)); 9297290Sbrooks 9397290Sbrooks ifp = &sc->sc_if; 9497290Sbrooks 9597290Sbrooks ifp->if_softc = sc; 9697290Sbrooks ifp->if_name = DISCNAME; 9797290Sbrooks ifp->if_unit = unit; 985191Swollman ifp->if_mtu = DSMTU; 995191Swollman ifp->if_flags = IFF_LOOPBACK | IFF_MULTICAST; 10041757Seivind ifp->if_ioctl = discioctl; 10141757Seivind ifp->if_output = discoutput; 1025191Swollman ifp->if_type = IFT_LOOP; 1035191Swollman ifp->if_hdrlen = 0; 1045191Swollman ifp->if_addrlen = 0; 10553115Sphk ifp->if_snd.ifq_maxlen = 20; 1065191Swollman if_attach(ifp); 10713937Swollman bpfattach(ifp, DLT_NULL, sizeof(u_int)); 10897290Sbrooks LIST_INSERT_HEAD(&disc_softc_list, sc, sc_list); 10997290Sbrooks 11097290Sbrooks return (0); 1115191Swollman} 1125191Swollman 11397290Sbrooksstatic void 11497290Sbrooksdisc_clone_destroy(struct ifnet *ifp) 11597290Sbrooks{ 11697290Sbrooks struct disc_softc *sc; 11797290Sbrooks 11897290Sbrooks sc = ifp->if_softc; 11997290Sbrooks 12097290Sbrooks LIST_REMOVE(sc, sc_list); 12197290Sbrooks bpfdetach(ifp); 12297290Sbrooks if_detach(ifp); 12397290Sbrooks 12497290Sbrooks free(sc, M_DISC); 12597290Sbrooks} 12697290Sbrooks 1275191Swollmanstatic int 12871862Speterdisc_modevent(module_t mod, int type, void *data) 12971862Speter{ 13071862Speter switch (type) { 13171862Speter case MOD_LOAD: 13297290Sbrooks LIST_INIT(&disc_softc_list); 13397290Sbrooks if_clone_attach(&disc_cloner); 13471862Speter break; 13571862Speter case MOD_UNLOAD: 13697290Sbrooks if_clone_detach(&disc_cloner); 13797290Sbrooks 13897290Sbrooks while (!LIST_EMPTY(&disc_softc_list)) 13997290Sbrooks disc_clone_destroy( 14097290Sbrooks &LIST_FIRST(&disc_softc_list)->sc_if); 14197290Sbrooks break; 14271862Speter } 14371862Speter return 0; 14471862Speter} 14571862Speter 14671862Speterstatic moduledata_t disc_mod = { 14771862Speter "if_disc", 14871862Speter disc_modevent, 14971862Speter NULL 15071862Speter}; 15171862Speter 15271862SpeterDECLARE_MODULE(if_disc, disc_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); 15371862Speter 15471862Speterstatic int 15578351Smarkmdiscoutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, 15678351Smarkm struct rtentry *rt) 1575191Swollman{ 158113255Sdes M_ASSERTPKTHDR(m); 15910957Swollman /* BPF write needs to be handled specially */ 16010957Swollman if (dst->sa_family == AF_UNSPEC) { 16110957Swollman dst->sa_family = *(mtod(m, int *)); 16210957Swollman m->m_len -= sizeof(int); 16310957Swollman m->m_pkthdr.len -= sizeof(int); 16410957Swollman m->m_data += sizeof(int); 16510957Swollman } 16610957Swollman 16797290Sbrooks if (ifp->if_bpf) { 1685191Swollman /* 1695191Swollman * We need to prepend the address family as 1705191Swollman * a four byte field. Cons up a dummy header 1715191Swollman * to pacify bpf. This is safe because bpf 1725191Swollman * will only read from the mbuf (i.e., it won't 1735191Swollman * try to free it or keep a pointer a to it). 1745191Swollman */ 1755191Swollman struct mbuf m0; 1765191Swollman u_int af = dst->sa_family; 1775191Swollman 1785191Swollman m0.m_next = m; 1795191Swollman m0.m_len = 4; 1805191Swollman m0.m_data = (char *)⁡ 1818876Srgrimes 182106939Ssam BPF_MTAP(ifp, &m0); 1835191Swollman } 1845191Swollman m->m_pkthdr.rcvif = ifp; 1855191Swollman 1865191Swollman ifp->if_opackets++; 1875191Swollman ifp->if_obytes += m->m_pkthdr.len; 1885191Swollman 1895191Swollman m_freem(m); 1905191Swollman return 0; 1915191Swollman} 1925191Swollman 1935191Swollman/* ARGSUSED */ 1945191Swollmanstatic void 19585074Srudiscrtrequest(int cmd, struct rtentry *rt, struct rt_addrinfo *info) 1965191Swollman{ 1975191Swollman if (rt) 1985191Swollman rt->rt_rmx.rmx_mtu = DSMTU; 1995191Swollman} 2005191Swollman 2015191Swollman/* 2025191Swollman * Process an ioctl request. 2035191Swollman */ 20412611Sbdestatic int 20578351Smarkmdiscioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 2065191Swollman{ 20778351Smarkm struct ifaddr *ifa; 20878351Smarkm struct ifreq *ifr = (struct ifreq *)data; 20978351Smarkm int error = 0; 2105191Swollman 2115191Swollman switch (cmd) { 2125191Swollman 2135191Swollman case SIOCSIFADDR: 2145191Swollman ifp->if_flags |= IFF_UP; 2155191Swollman ifa = (struct ifaddr *)data; 2165191Swollman if (ifa != 0) 21741757Seivind ifa->ifa_rtrequest = discrtrequest; 2185191Swollman /* 2195191Swollman * Everything else is done at a higher level. 2205191Swollman */ 2215191Swollman break; 2225191Swollman 2235191Swollman case SIOCADDMULTI: 2245191Swollman case SIOCDELMULTI: 2255191Swollman if (ifr == 0) { 2265191Swollman error = EAFNOSUPPORT; /* XXX */ 2275191Swollman break; 2285191Swollman } 2295191Swollman switch (ifr->ifr_addr.sa_family) { 2305191Swollman 2315191Swollman#ifdef INET 2325191Swollman case AF_INET: 2335191Swollman break; 2345191Swollman#endif 23554263Sshin#ifdef INET6 23654263Sshin case AF_INET6: 23754263Sshin break; 23854263Sshin#endif 2395191Swollman 2405191Swollman default: 2415191Swollman error = EAFNOSUPPORT; 2425191Swollman break; 2435191Swollman } 2445191Swollman break; 2455191Swollman 2465191Swollman case SIOCSIFMTU: 2475191Swollman ifp->if_mtu = ifr->ifr_mtu; 2485191Swollman break; 2495191Swollman 2505191Swollman default: 2515191Swollman error = EINVAL; 2525191Swollman } 25387912Sjlemon return (error); 2545191Swollman} 255