avoid assigning used ports in implicit bind in in_pcbbind (net2/sys/15)
[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 *
0fe7c40f 7 * @(#)if_loop.c 7.19 (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 60 ifp->if_flags = IFF_LOOPBACK | IFF_MULTICAST;
639a8848 61 ifp->if_ioctl = loioctl;
0a486d2b 62 ifp->if_output = looutput;
b72a6efb
KS
63 ifp->if_type = IFT_LOOP;
64 ifp->if_hdrlen = 0;
65 ifp->if_addrlen = 0;
405c9168 66 if_attach(ifp);
78cafbd4
KS
67#if NBPFILTER > 0
68 bpfattach(&ifp->if_bpf, ifp, DLT_NULL, sizeof(u_int));
69#endif
0a486d2b
BJ
70}
71
9c5bb641 72looutput(ifp, m, dst, rt)
0a486d2b 73 struct ifnet *ifp;
38a81509 74 register struct mbuf *m;
ee787340 75 struct sockaddr *dst;
9c5bb641 76 register struct rtentry *rt;
0a486d2b 77{
98fb6aa9
KS
78 int s, isr;
79 register struct ifqueue *ifq = 0;
38a81509
MK
80
81 if ((m->m_flags & M_PKTHDR) == 0)
82 panic("looutput no HDR");
78cafbd4
KS
83 ifp->if_lastchange = time;
84#if NBPFILTER > 0
85 if (loif.if_bpf) {
86 /*
87 * We need to prepend the address family as
88 * a four byte field. Cons up a dummy header
89 * to pacify bpf. This is safe because bpf
90 * will only read from the mbuf (i.e., it won't
91 * try to free it or keep a pointer a to it).
92 */
93 struct mbuf m0;
94 u_int af = dst->sa_family;
95
96 m0.m_next = m;
97 m0.m_len = 4;
98 m0.m_data = (char *)&af;
99
100 bpf_mtap(loif.if_bpf, &m0);
101 }
102#endif
38a81509
MK
103 m->m_pkthdr.rcvif = ifp;
104
9c5bb641
KS
105 if (rt && rt->rt_flags & RTF_REJECT) {
106 m_freem(m);
107 return (rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH);
108 }
b454c3ea 109 ifp->if_opackets++;
5f08a978 110 ifp->if_obytes += m->m_pkthdr.len;
ee787340 111 switch (dst->sa_family) {
0a486d2b
BJ
112
113#ifdef INET
ee787340 114 case AF_INET:
1e977657 115 ifq = &ipintrq;
98fb6aa9 116 isr = NETISR_IP;
0a486d2b 117 break;
edecfd58
KS
118#endif
119#ifdef NS
120 case AF_NS:
121 ifq = &nsintrq;
98fb6aa9 122 isr = NETISR_NS;
edecfd58 123 break;
b72a6efb
KS
124#endif
125#ifdef ISO
126 case AF_ISO:
127 ifq = &clnlintrq;
98fb6aa9
KS
128 isr = NETISR_ISO;
129 break;
0a486d2b 130#endif
0a486d2b 131 default:
ee787340
SL
132 printf("lo%d: can't handle af%d\n", ifp->if_unit,
133 dst->sa_family);
38a81509 134 m_freem(m);
4c5902e0 135 return (EAFNOSUPPORT);
0a486d2b 136 }
ee85cf85 137 s = splimp();
98fb6aa9
KS
138 if (IF_QFULL(ifq)) {
139 IF_DROP(ifq);
140 m_freem(m);
141 splx(s);
142 return (ENOBUFS);
143 }
144 IF_ENQUEUE(ifq, m);
145 schednetisr(isr);
b454c3ea 146 ifp->if_ipackets++;
5f08a978 147 ifp->if_ibytes += m->m_pkthdr.len;
0a486d2b 148 splx(s);
4c5902e0 149 return (0);
0a486d2b 150}
639a8848 151
ee85cf85 152/* ARGSUSED */
78cafbd4 153void
ee85cf85 154lortrequest(cmd, rt, sa)
64f72726
CT
155 int cmd;
156 struct rtentry *rt;
157 struct sockaddr *sa;
ee85cf85 158{
64f72726 159
ee85cf85
KS
160 if (rt)
161 rt->rt_rmx.rmx_mtu = LOMTU;
162}
163
639a8848
SL
164/*
165 * Process an ioctl request.
166 */
bba52753 167/* ARGSUSED */
639a8848
SL
168loioctl(ifp, cmd, data)
169 register struct ifnet *ifp;
170 int cmd;
171 caddr_t data;
172{
ee85cf85 173 register struct ifaddr *ifa;
78cafbd4 174 register struct ifreq *ifr;
78cafbd4 175 register int error = 0;
639a8848
SL
176
177 switch (cmd) {
178
179 case SIOCSIFADDR:
bba52753 180 ifp->if_flags |= IFF_UP;
ee85cf85
KS
181 ifa = (struct ifaddr *)data;
182 if (ifa != 0 && ifa->ifa_addr->sa_family == AF_ISO)
183 ifa->ifa_rtrequest = lortrequest;
bba52753
MK
184 /*
185 * Everything else is done at a higher level.
186 */
639a8848
SL
187 break;
188
78cafbd4
KS
189 case SIOCADDMULTI:
190 case SIOCDELMULTI:
191 ifr = (struct ifreq *)data;
192 if (ifr == 0) {
193 error = EAFNOSUPPORT; /* XXX */
194 break;
195 }
196 switch (ifr->ifr_addr.sa_family) {
197
198#ifdef INET
199 case AF_INET:
200 break;
201#endif
202
203 default:
204 error = EAFNOSUPPORT;
205 break;
206 }
207 break;
78cafbd4 208
639a8848
SL
209 default:
210 error = EINVAL;
211 }
639a8848
SL
212 return (error);
213}