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 *)&af;
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