fix dom_init prototype (no args => __P((void)), not empty)
[unix-history] / usr / src / sys / net / if_loop.c
CommitLineData
8ae0e4b4 1/*
21622db8 2 * Copyright (c) 1982, 1986 Regents of the University of California.
5b519e94 3 * All rights reserved.
8ae0e4b4 4 *
dbf0c423 5 * %sccs.include.redist.c%
5b519e94 6 *
5548a02f 7 * @(#)if_loop.c 7.18 (Berkeley) %G%
8ae0e4b4 8 */
0a486d2b
BJ
9
10/*
11 * Loopback interface driver for protocol testing and timing.
12 */
13
5548a02f
KB
14#include <sys/param.h>
15#include <sys/systm.h>
16#include <sys/kernel.h>
17#include <sys/mbuf.h>
18#include <sys/socket.h>
19#include <sys/errno.h>
20#include <sys/ioctl.h>
21#include <sys/time.h>
22#include <machine/cpu.h>
1cc8c949 23
5548a02f
KB
24#include <net/if.h>
25#include <net/if_types.h>
26#include <net/netisr.h>
27#include <net/route.h>
28#include <net/bpf.h>
2e62d00d 29
dbc42650 30#ifdef INET
5548a02f
KB
31#include <netinet/in.h>
32#include <netinet/in_systm.h>
33#include <netinet/in_var.h>
34#include <netinet/ip.h>
dbc42650 35#endif
1cc8c949 36
edecfd58 37#ifdef NS
5548a02f
KB
38#include <netns/ns.h>
39#include <netns/ns_if.h>
edecfd58
KS
40#endif
41
b72a6efb 42#ifdef ISO
5548a02f
KB
43#include <netiso/iso.h>
44#include <netiso/iso_var.h>
b72a6efb
KS
45#endif
46
78cafbd4
KS
47#include "bpfilter.h"
48
56e0df97 49#define LOMTU (1024+512)
0a486d2b
BJ
50
51struct ifnet loif;
639a8848 52int looutput(), loioctl();
0a486d2b
BJ
53
54loattach()
55{
56 register struct ifnet *ifp = &loif;
57
b454c3ea 58 ifp->if_name = "lo";
0a486d2b 59 ifp->if_mtu = LOMTU;
78cafbd4
KS
60#ifdef MULTICAST
61 ifp->if_flags = IFF_LOOPBACK | IFF_MULTICAST;
62#else
484ee22e 63 ifp->if_flags = IFF_LOOPBACK;
78cafbd4 64#endif
639a8848 65 ifp->if_ioctl = loioctl;
0a486d2b 66 ifp->if_output = looutput;
b72a6efb
KS
67 ifp->if_type = IFT_LOOP;
68 ifp->if_hdrlen = 0;
69 ifp->if_addrlen = 0;
405c9168 70 if_attach(ifp);
78cafbd4
KS
71#if NBPFILTER > 0
72 bpfattach(&ifp->if_bpf, ifp, DLT_NULL, sizeof(u_int));
73#endif
0a486d2b
BJ
74}
75
9c5bb641 76looutput(ifp, m, dst, rt)
0a486d2b 77 struct ifnet *ifp;
38a81509 78 register struct mbuf *m;
ee787340 79 struct sockaddr *dst;
9c5bb641 80 register struct rtentry *rt;
0a486d2b 81{
98fb6aa9
KS
82 int s, isr;
83 register struct ifqueue *ifq = 0;
38a81509
MK
84
85 if ((m->m_flags & M_PKTHDR) == 0)
86 panic("looutput no HDR");
78cafbd4
KS
87 ifp->if_lastchange = time;
88#if NBPFILTER > 0
89 if (loif.if_bpf) {
90 /*
91 * We need to prepend the address family as
92 * a four byte field. Cons up a dummy header
93 * to pacify bpf. This is safe because bpf
94 * will only read from the mbuf (i.e., it won't
95 * try to free it or keep a pointer a to it).
96 */
97 struct mbuf m0;
98 u_int af = dst->sa_family;
99
100 m0.m_next = m;
101 m0.m_len = 4;
102 m0.m_data = (char *)&af;
103
104 bpf_mtap(loif.if_bpf, &m0);
105 }
106#endif
38a81509
MK
107 m->m_pkthdr.rcvif = ifp;
108
9c5bb641
KS
109 if (rt && rt->rt_flags & RTF_REJECT) {
110 m_freem(m);
111 return (rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH);
112 }
b454c3ea 113 ifp->if_opackets++;
5f08a978 114 ifp->if_obytes += m->m_pkthdr.len;
ee787340 115 switch (dst->sa_family) {
0a486d2b
BJ
116
117#ifdef INET
ee787340 118 case AF_INET:
1e977657 119 ifq = &ipintrq;
98fb6aa9 120 isr = NETISR_IP;
0a486d2b 121 break;
edecfd58
KS
122#endif
123#ifdef NS
124 case AF_NS:
125 ifq = &nsintrq;
98fb6aa9 126 isr = NETISR_NS;
edecfd58 127 break;
b72a6efb
KS
128#endif
129#ifdef ISO
130 case AF_ISO:
131 ifq = &clnlintrq;
98fb6aa9
KS
132 isr = NETISR_ISO;
133 break;
0a486d2b 134#endif
0a486d2b 135 default:
ee787340
SL
136 printf("lo%d: can't handle af%d\n", ifp->if_unit,
137 dst->sa_family);
38a81509 138 m_freem(m);
4c5902e0 139 return (EAFNOSUPPORT);
0a486d2b 140 }
ee85cf85 141 s = splimp();
98fb6aa9
KS
142 if (IF_QFULL(ifq)) {
143 IF_DROP(ifq);
144 m_freem(m);
145 splx(s);
146 return (ENOBUFS);
147 }
148 IF_ENQUEUE(ifq, m);
149 schednetisr(isr);
b454c3ea 150 ifp->if_ipackets++;
5f08a978 151 ifp->if_ibytes += m->m_pkthdr.len;
0a486d2b 152 splx(s);
4c5902e0 153 return (0);
0a486d2b 154}
639a8848 155
ee85cf85 156/* ARGSUSED */
78cafbd4 157void
ee85cf85 158lortrequest(cmd, rt, sa)
64f72726
CT
159 int cmd;
160 struct rtentry *rt;
161 struct sockaddr *sa;
ee85cf85 162{
64f72726 163
ee85cf85
KS
164 if (rt)
165 rt->rt_rmx.rmx_mtu = LOMTU;
166}
167
639a8848
SL
168/*
169 * Process an ioctl request.
170 */
bba52753 171/* ARGSUSED */
639a8848
SL
172loioctl(ifp, cmd, data)
173 register struct ifnet *ifp;
174 int cmd;
175 caddr_t data;
176{
ee85cf85 177 register struct ifaddr *ifa;
78cafbd4
KS
178#ifdef MULTICAST
179 register struct ifreq *ifr;
180#endif
181 register int error = 0;
639a8848
SL
182
183 switch (cmd) {
184
185 case SIOCSIFADDR:
bba52753 186 ifp->if_flags |= IFF_UP;
ee85cf85
KS
187 ifa = (struct ifaddr *)data;
188 if (ifa != 0 && ifa->ifa_addr->sa_family == AF_ISO)
189 ifa->ifa_rtrequest = lortrequest;
bba52753
MK
190 /*
191 * Everything else is done at a higher level.
192 */
639a8848
SL
193 break;
194
78cafbd4
KS
195#ifdef MULTICAST
196 case SIOCADDMULTI:
197 case SIOCDELMULTI:
198 ifr = (struct ifreq *)data;
199 if (ifr == 0) {
200 error = EAFNOSUPPORT; /* XXX */
201 break;
202 }
203 switch (ifr->ifr_addr.sa_family) {
204
205#ifdef INET
206 case AF_INET:
207 break;
208#endif
209
210 default:
211 error = EAFNOSUPPORT;
212 break;
213 }
214 break;
215#endif
216
639a8848
SL
217 default:
218 error = EINVAL;
219 }
639a8848
SL
220 return (error);
221}