if_disc.c revision 12611
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
3412611Sbde *	$Id: if_disc.c,v 1.9 1995/12/02 17:11:09 bde 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
8312569Sbdestatic void discattach __P((void *dummy));
8410429SbdePSEUDO_SET(discattach, if_disc);
8510429Sbde
865191Swollmanstatic struct	ifnet dsif;
875191Swollmanstatic int dsoutput(struct ifnet *, struct mbuf *, struct sockaddr *,
885191Swollman		    struct rtentry *);
8912611Sbdestatic void dsrtrequest(int cmd, struct rtentry *rt, struct sockaddr *sa);
905191Swollmanstatic int dsioctl(struct ifnet *, int, caddr_t);
915191Swollman
925191Swollman/* ARGSUSED */
935191Swollmanstatic void
9412569Sbdediscattach(dummy)
9512569Sbde	void *dummy;
965191Swollman{
975191Swollman	register struct ifnet *ifp = &dsif;
985191Swollman
995191Swollman	ifp->if_name = "ds";
1005191Swollman	ifp->if_mtu = DSMTU;
1015191Swollman	ifp->if_flags = IFF_LOOPBACK | IFF_MULTICAST;
1025191Swollman	ifp->if_ioctl = dsioctl;
1035191Swollman	ifp->if_output = dsoutput;
1045191Swollman	ifp->if_type = IFT_LOOP;
1055191Swollman	ifp->if_hdrlen = 0;
1065191Swollman	ifp->if_addrlen = 0;
1075191Swollman	if_attach(ifp);
1085191Swollman#if NBPFILTER > 0
1095191Swollman	bpfattach(&ifp->if_bpf, ifp, DLT_NULL, sizeof(u_int));
1105191Swollman#endif
1115191Swollman}
1125191Swollman
1135191Swollmanstatic int
1145191Swollmandsoutput(ifp, m, dst, rt)
1155191Swollman	struct ifnet *ifp;
1165191Swollman	register struct mbuf *m;
1175191Swollman	struct sockaddr *dst;
1185191Swollman	register struct rtentry *rt;
1195191Swollman{
1205191Swollman	if ((m->m_flags & M_PKTHDR) == 0)
1215191Swollman		panic("dsoutput no HDR");
1225191Swollman	ifp->if_lastchange = time;
1235191Swollman#if NBPFILTER > 0
12410957Swollman	/* BPF write needs to be handled specially */
12510957Swollman	if (dst->sa_family == AF_UNSPEC) {
12610957Swollman		dst->sa_family = *(mtod(m, int *));
12710957Swollman		m->m_len -= sizeof(int);
12810957Swollman		m->m_pkthdr.len -= sizeof(int);
12910957Swollman		m->m_data += sizeof(int);
13010957Swollman	}
13110957Swollman
1325191Swollman	if (dsif.if_bpf) {
1335191Swollman		/*
1345191Swollman		 * We need to prepend the address family as
1355191Swollman		 * a four byte field.  Cons up a dummy header
1365191Swollman		 * to pacify bpf.  This is safe because bpf
1375191Swollman		 * will only read from the mbuf (i.e., it won't
1385191Swollman		 * try to free it or keep a pointer a to it).
1395191Swollman		 */
1405191Swollman		struct mbuf m0;
1415191Swollman		u_int af = dst->sa_family;
1425191Swollman
1435191Swollman		m0.m_next = m;
1445191Swollman		m0.m_len = 4;
1455191Swollman		m0.m_data = (char *)&af;
1468876Srgrimes
1475191Swollman		bpf_mtap(dsif.if_bpf, &m0);
1485191Swollman	}
1495191Swollman#endif
1505191Swollman	m->m_pkthdr.rcvif = ifp;
1515191Swollman
1525191Swollman	if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) {
1535191Swollman		m_freem(m);
1545191Swollman		return (rt->rt_flags & RTF_BLACKHOLE ? 0 :
1555191Swollman		        rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH);
1565191Swollman	}
1575191Swollman	ifp->if_opackets++;
1585191Swollman	ifp->if_obytes += m->m_pkthdr.len;
1595191Swollman
1605191Swollman	m_freem(m);
1615191Swollman	return 0;
1625191Swollman}
1635191Swollman
1645191Swollman/* ARGSUSED */
1655191Swollmanstatic void
1665191Swollmandsrtrequest(cmd, rt, sa)
1675191Swollman	int cmd;
1685191Swollman	struct rtentry *rt;
1695191Swollman	struct sockaddr *sa;
1705191Swollman{
1715191Swollman	if (rt)
1725191Swollman		rt->rt_rmx.rmx_mtu = DSMTU;
1735191Swollman}
1745191Swollman
1755191Swollman/*
1765191Swollman * Process an ioctl request.
1775191Swollman */
1785191Swollman/* ARGSUSED */
17912611Sbdestatic int
1805191Swollmandsioctl(ifp, cmd, data)
1815191Swollman	register struct ifnet *ifp;
1825191Swollman	int cmd;
1835191Swollman	caddr_t data;
1845191Swollman{
1855191Swollman	register struct ifaddr *ifa;
1865191Swollman	register struct ifreq *ifr = (struct ifreq *)data;
1875191Swollman	register int error = 0;
1885191Swollman
1895191Swollman	switch (cmd) {
1905191Swollman
1915191Swollman	case SIOCSIFADDR:
1925191Swollman		ifp->if_flags |= IFF_UP;
1935191Swollman		ifa = (struct ifaddr *)data;
1945191Swollman		if (ifa != 0)
1955191Swollman			ifa->ifa_rtrequest = dsrtrequest;
1965191Swollman		/*
1975191Swollman		 * Everything else is done at a higher level.
1985191Swollman		 */
1995191Swollman		break;
2005191Swollman
2015191Swollman	case SIOCADDMULTI:
2025191Swollman	case SIOCDELMULTI:
2035191Swollman		if (ifr == 0) {
2045191Swollman			error = EAFNOSUPPORT;		/* XXX */
2055191Swollman			break;
2065191Swollman		}
2075191Swollman		switch (ifr->ifr_addr.sa_family) {
2085191Swollman
2095191Swollman#ifdef INET
2105191Swollman		case AF_INET:
2115191Swollman			break;
2125191Swollman#endif
2135191Swollman
2145191Swollman		default:
2155191Swollman			error = EAFNOSUPPORT;
2165191Swollman			break;
2175191Swollman		}
2185191Swollman		break;
2195191Swollman
2205191Swollman	case SIOCSIFMTU:
2215191Swollman		ifp->if_mtu = ifr->ifr_mtu;
2225191Swollman		break;
2235191Swollman
2245191Swollman	default:
2255191Swollman		error = EINVAL;
2265191Swollman	}
2275191Swollman	return (error);
2285191Swollman}
229