if_disc.c revision 18796
1235474Sbz/*
2235474Sbz * Copyright (c) 1982, 1986, 1993
3235474Sbz *	The Regents of the University of California.  All rights reserved.
4235944Sbz *
5235474Sbz * Redistribution and use in source and binary forms, with or without
6235474Sbz * modification, are permitted provided that the following conditions
7235944Sbz * are met:
8235944Sbz * 1. Redistributions of source code must retain the above copyright
9235944Sbz *    notice, this list of conditions and the following disclaimer.
10235474Sbz * 2. Redistributions in binary form must reproduce the above copyright
11235474Sbz *    notice, this list of conditions and the following disclaimer in the
12235474Sbz *    documentation and/or other materials provided with the distribution.
13235474Sbz * 3. All advertising materials mentioning features or use of this software
14235474Sbz *    must display the following acknowledgement:
15235474Sbz *	This product includes software developed by the University of
16235474Sbz *	California, Berkeley and its contributors.
17235474Sbz * 4. Neither the name of the University nor the names of its contributors
18235474Sbz *    may be used to endorse or promote products derived from this software
19235474Sbz *    without specific prior written permission.
20235474Sbz *
21235474Sbz * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22235474Sbz * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23235474Sbz * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24235474Sbz * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25235474Sbz * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26235474Sbz * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27235474Sbz * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28235474Sbz * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29235474Sbz * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30235474Sbz * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31179737Sjfv * SUCH DAMAGE.
32235944Sbz *
33235944Sbz *	From: @(#)if_loop.c	8.1 (Berkeley) 6/10/93
34235944Sbz *	$Id: if_disc.c,v 1.13 1996/06/10 23:07:29 gpalmer Exp $
35235944Sbz */
36235944Sbz
37235944Sbz/*
38179737Sjfv * Discard interface driver for protocol testing and timing.
39179737Sjfv * (Based on the loopback.)
40179737Sjfv */
41179737Sjfv
42179737Sjfv#include <sys/param.h>
43179737Sjfv#include <sys/systm.h>
44179737Sjfv#include <sys/kernel.h>
45235944Sbz#include <sys/mbuf.h>
46179737Sjfv#include <sys/socket.h>
47236394Sbz#include <sys/errno.h>
48179737Sjfv#include <sys/ioctl.h>
49179737Sjfv#include <sys/time.h>
50179737Sjfv
51235944Sbz#include <net/if.h>
52179737Sjfv#include <net/if_types.h>
53235981Sbz#include <net/netisr.h>
54179737Sjfv#include <net/route.h>
55179737Sjfv#include <net/bpf.h>
56179737Sjfv
57235981Sbz#ifdef	INET
58235981Sbz#include <netinet/in.h>
59179737Sjfv#include <netinet/in_systm.h>
60179737Sjfv#include <netinet/in_var.h>
61235944Sbz#include <netinet/ip.h>
62235944Sbz#endif
63235944Sbz
64179737Sjfv#ifdef NS
65235944Sbz#include <netns/ns.h>
66235944Sbz#include <netns/ns_if.h>
67235944Sbz#endif
68235944Sbz
69179737Sjfv#ifdef ISO
70179737Sjfv#include <netiso/iso.h>
71235944Sbz#include <netiso/iso_var.h>
72179737Sjfv#endif
73235944Sbz
74235944Sbz#include "bpfilter.h"
75179737Sjfv
76235944Sbz#ifdef TINY_DSMTU
77235944Sbz#define	DSMTU	(1024+512)
78235944Sbz#else
79235944Sbz#define DSMTU	65532
80235944Sbz#endif
81235944Sbz
82179737Sjfvstatic void discattach __P((void *dummy));
83235944SbzPSEUDO_SET(discattach, if_disc);
84179737Sjfv
85235944Sbzstatic struct	ifnet dsif;
86235944Sbzstatic int dsoutput(struct ifnet *, struct mbuf *, struct sockaddr *,
87235944Sbz		    struct rtentry *);
88179737Sjfvstatic void dsrtrequest(int cmd, struct rtentry *rt, struct sockaddr *sa);
89179737Sjfvstatic int dsioctl(struct ifnet *, int, caddr_t);
90179737Sjfv
91179737Sjfv/* ARGSUSED */
92235944Sbzstatic void
93235944Sbzdiscattach(dummy)
94179737Sjfv	void *dummy;
95179737Sjfv{
96179737Sjfv	register struct ifnet *ifp = &dsif;
97179737Sjfv
98179737Sjfv	ifp->if_name = "ds";
99179737Sjfv	ifp->if_mtu = DSMTU;
100235944Sbz	ifp->if_flags = IFF_LOOPBACK | IFF_MULTICAST;
101179737Sjfv	ifp->if_ioctl = dsioctl;
102235944Sbz	ifp->if_output = dsoutput;
103179737Sjfv	ifp->if_type = IFT_LOOP;
104235944Sbz	ifp->if_hdrlen = 0;
105235944Sbz	ifp->if_addrlen = 0;
106235944Sbz	if_attach(ifp);
107235944Sbz#if NBPFILTER > 0
108179737Sjfv	bpfattach(ifp, DLT_NULL, sizeof(u_int));
109179737Sjfv#endif
110179737Sjfv}
111235944Sbz
112235944Sbzstatic int
113235944Sbzdsoutput(ifp, m, dst, rt)
114235944Sbz	struct ifnet *ifp;
115235944Sbz	register struct mbuf *m;
116235944Sbz	struct sockaddr *dst;
117235944Sbz	register struct rtentry *rt;
118235944Sbz{
119235944Sbz	if ((m->m_flags & M_PKTHDR) == 0)
120235944Sbz		panic("dsoutput no HDR");
121235944Sbz#if NBPFILTER > 0
122235944Sbz	/* BPF write needs to be handled specially */
123235944Sbz	if (dst->sa_family == AF_UNSPEC) {
124235944Sbz		dst->sa_family = *(mtod(m, int *));
125235944Sbz		m->m_len -= sizeof(int);
126235944Sbz		m->m_pkthdr.len -= sizeof(int);
127235944Sbz		m->m_data += sizeof(int);
128235944Sbz	}
129235944Sbz
130235944Sbz	if (dsif.if_bpf) {
131235944Sbz		/*
132235944Sbz		 * We need to prepend the address family as
133235944Sbz		 * a four byte field.  Cons up a dummy header
134235944Sbz		 * to pacify bpf.  This is safe because bpf
135235944Sbz		 * will only read from the mbuf (i.e., it won't
136235944Sbz		 * try to free it or keep a pointer a to it).
137235944Sbz		 */
138235944Sbz		struct mbuf m0;
139235944Sbz		u_int af = dst->sa_family;
140235944Sbz
141235944Sbz		m0.m_next = m;
142235944Sbz		m0.m_len = 4;
143235944Sbz		m0.m_data = (char *)&af;
144235944Sbz
145235944Sbz		bpf_mtap(&dsif, &m0);
146235944Sbz	}
147235944Sbz#endif
148235944Sbz	m->m_pkthdr.rcvif = ifp;
149235944Sbz
150235944Sbz	ifp->if_opackets++;
151235944Sbz	ifp->if_obytes += m->m_pkthdr.len;
152235944Sbz
153235944Sbz	m_freem(m);
154235944Sbz	return 0;
155235944Sbz}
156235944Sbz
157235944Sbz/* ARGSUSED */
158235944Sbzstatic void
159235944Sbzdsrtrequest(cmd, rt, sa)
160235944Sbz	int cmd;
161235944Sbz	struct rtentry *rt;
162235944Sbz	struct sockaddr *sa;
163235944Sbz{
164235944Sbz	if (rt)
165235944Sbz		rt->rt_rmx.rmx_mtu = DSMTU;
166235944Sbz}
167235944Sbz
168235944Sbz/*
169235944Sbz * Process an ioctl request.
170235944Sbz */
171235944Sbz/* ARGSUSED */
172235944Sbzstatic int
173235944Sbzdsioctl(ifp, cmd, data)
174235944Sbz	register struct ifnet *ifp;
175235944Sbz	int cmd;
176235944Sbz	caddr_t data;
177235944Sbz{
178235944Sbz	register struct ifaddr *ifa;
179235944Sbz	register struct ifreq *ifr = (struct ifreq *)data;
180235944Sbz	register int error = 0;
181235944Sbz
182235944Sbz	switch (cmd) {
183235944Sbz
184235944Sbz	case SIOCSIFADDR:
185235944Sbz		ifp->if_flags |= IFF_UP;
186235944Sbz		ifa = (struct ifaddr *)data;
187235944Sbz		if (ifa != 0)
188235944Sbz			ifa->ifa_rtrequest = dsrtrequest;
189235944Sbz		/*
190235944Sbz		 * Everything else is done at a higher level.
191235944Sbz		 */
192235944Sbz		break;
193235944Sbz
194235944Sbz	case SIOCADDMULTI:
195235944Sbz	case SIOCDELMULTI:
196179737Sjfv		if (ifr == 0) {
197255010Snp			error = EAFNOSUPPORT;		/* XXX */
198255010Snp			break;
199255010Snp		}
200255010Snp		switch (ifr->ifr_addr.sa_family) {
201255010Snp
202255010Snp#ifdef INET
203255010Snp		case AF_INET:
204255010Snp			break;
205255010Snp#endif
206255010Snp
207255010Snp		default:
208255010Snp			error = EAFNOSUPPORT;
209255010Snp			break;
210255010Snp		}
211255010Snp		break;
212255010Snp
213255010Snp	case SIOCSIFMTU:
214255010Snp		ifp->if_mtu = ifr->ifr_mtu;
215255010Snp		break;
216235944Sbz
217179737Sjfv	default:
218179737Sjfv		error = EINVAL;
219235944Sbz	}
220235944Sbz	return (error);
221235944Sbz}
222179737Sjfv