386BSD 0.1 development
[unix-history] / usr / src / sys.386bsd / net / if_loop.c
CommitLineData
b688fc87
WJ
1/*
2 * Copyright (c) 1982, 1986 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * @(#)if_loop.c 7.13 (Berkeley) 4/26/91
34 */
35
36/*
37 * Loopback interface driver for protocol testing and timing.
38 */
39
40#include "param.h"
41#include "systm.h"
42#include "mbuf.h"
43#include "socket.h"
44#include "errno.h"
45#include "ioctl.h"
46
47#include "../net/if.h"
48#include "../net/if_types.h"
49#include "../net/netisr.h"
50#include "../net/route.h"
51
52#include "machine/mtpr.h"
53
54#ifdef INET
55#include "../netinet/in.h"
56#include "../netinet/in_systm.h"
57#include "../netinet/in_var.h"
58#include "../netinet/ip.h"
59#endif
60
61#ifdef NS
62#include "../netns/ns.h"
63#include "../netns/ns_if.h"
64#endif
65
66#ifdef ISO
67#include "../netiso/iso.h"
68#include "../netiso/iso_var.h"
69#endif
70
71#define LOMTU (1024+512)
72
73struct ifnet loif;
74int looutput(), loioctl();
75
76loattach()
77{
78 register struct ifnet *ifp = &loif;
79
80 ifp->if_name = "lo";
81 ifp->if_mtu = LOMTU;
82 ifp->if_flags = IFF_LOOPBACK;
83 ifp->if_ioctl = loioctl;
84 ifp->if_output = looutput;
85 ifp->if_type = IFT_LOOP;
86 ifp->if_hdrlen = 0;
87 ifp->if_addrlen = 0;
88 if_attach(ifp);
89}
90
91looutput(ifp, m, dst, rt)
92 struct ifnet *ifp;
93 register struct mbuf *m;
94 struct sockaddr *dst;
95 register struct rtentry *rt;
96{
97 int s, isr;
98 register struct ifqueue *ifq = 0;
99
100 if ((m->m_flags & M_PKTHDR) == 0)
101 panic("looutput no HDR");
102 m->m_pkthdr.rcvif = ifp;
103
104 if (rt && rt->rt_flags & RTF_REJECT) {
105 m_freem(m);
106 return (rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH);
107 }
108 ifp->if_opackets++;
109 ifp->if_obytes += m->m_pkthdr.len;
110 switch (dst->sa_family) {
111
112#ifdef INET
113 case AF_INET:
114 ifq = &ipintrq;
115 isr = NETISR_IP;
116 break;
117#endif
118#ifdef NS
119 case AF_NS:
120 ifq = &nsintrq;
121 isr = NETISR_NS;
122 break;
123#endif
124#ifdef ISO
125 case AF_ISO:
126 ifq = &clnlintrq;
127 isr = NETISR_ISO;
128 break;
129#endif
130 default:
131 printf("lo%d: can't handle af%d\n", ifp->if_unit,
132 dst->sa_family);
133 m_freem(m);
134 return (EAFNOSUPPORT);
135 }
136 s = splimp();
137 if (IF_QFULL(ifq)) {
138 IF_DROP(ifq);
139 m_freem(m);
140 splx(s);
141 return (ENOBUFS);
142 }
143 IF_ENQUEUE(ifq, m);
144 schednetisr(isr);
145 ifp->if_ipackets++;
146 ifp->if_ibytes += m->m_pkthdr.len;
147 splx(s);
148 return (0);
149}
150
151/* ARGSUSED */
152lortrequest(cmd, rt, sa)
153struct rtentry *rt;
154struct sockaddr *sa;
155{
156 if (rt)
157 rt->rt_rmx.rmx_mtu = LOMTU;
158}
159
160/*
161 * Process an ioctl request.
162 */
163/* ARGSUSED */
164loioctl(ifp, cmd, data)
165 register struct ifnet *ifp;
166 int cmd;
167 caddr_t data;
168{
169 register struct ifaddr *ifa;
170 int error = 0;
171
172 switch (cmd) {
173
174 case SIOCSIFADDR:
175 ifp->if_flags |= IFF_UP;
176 ifa = (struct ifaddr *)data;
177 if (ifa != 0 && ifa->ifa_addr->sa_family == AF_ISO)
178 ifa->ifa_rtrequest = lortrequest;
179 /*
180 * Everything else is done at a higher level.
181 */
182 break;
183
184 default:
185 error = EINVAL;
186 }
187 return (error);
188}