xref: /original-bsd/sys/net/if_loop.c (revision 792e4f5f)
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 are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  *
17  *	@(#)if_loop.c	7.7 (Berkeley) 04/25/89
18  */
19 
20 /*
21  * Loopback interface driver for protocol testing and timing.
22  */
23 
24 #include "param.h"
25 #include "systm.h"
26 #include "mbuf.h"
27 #include "socket.h"
28 #include "errno.h"
29 #include "ioctl.h"
30 
31 #include "../net/if.h"
32 #include "../net/iftypes.h"
33 #include "../net/netisr.h"
34 #include "../net/route.h"
35 
36 #include "machine/mtpr.h"
37 
38 #ifdef	INET
39 #include "../netinet/in.h"
40 #include "../netinet/in_systm.h"
41 #include "../netinet/in_var.h"
42 #include "../netinet/ip.h"
43 #endif
44 
45 #ifdef NS
46 #include "../netns/ns.h"
47 #include "../netns/ns_if.h"
48 #endif
49 
50 #ifdef ISO
51 #include "../netiso/iso.h"
52 #include "../netiso/iso_var.h"
53 #endif
54 
55 #define	LOMTU	(1024+512)
56 
57 struct	ifnet loif;
58 int	looutput(), loioctl();
59 
60 loattach()
61 {
62 	register struct ifnet *ifp = &loif;
63 
64 	ifp->if_name = "lo";
65 	ifp->if_mtu = LOMTU;
66 	ifp->if_flags = IFF_LOOPBACK;
67 	ifp->if_ioctl = loioctl;
68 	ifp->if_output = looutput;
69 	ifp->if_type = IFT_LOOP;
70 	ifp->if_hdrlen = 0;
71 	ifp->if_addrlen = 0;
72 	if_attach(ifp);
73 }
74 
75 struct mbuf *Loop_Sanity;
76 
77 looutput(ifp, m, dst)
78 	struct ifnet *ifp;
79 	register struct mbuf *m;
80 	struct sockaddr *dst;
81 {
82 	int s;
83 	register struct ifqueue *ifq;
84 
85 	if ((m->m_flags & M_PKTHDR) == 0)
86 		panic("looutput no HDR");
87 	m->m_pkthdr.rcvif = ifp;
88 
89 {struct mbuf *mm; int mlen = 0;
90 for (mm = m; m; m = m->m_next) /* XXX debugging code -- sklower */
91     mlen += m->m_len;
92 m = mm;
93 if (mlen != m->m_pkthdr.len) {
94 	if (Loop_Sanity)
95 		m_freem(Loop_Sanity);
96 	Loop_Sanity = m_copy(m, 0, (int)M_COPYALL);
97 }
98 }
99 
100 	s = splimp();
101 	ifp->if_opackets++;
102 	switch (dst->sa_family) {
103 
104 #ifdef INET
105 	case AF_INET:
106 		ifq = &ipintrq;
107 		if (IF_QFULL(ifq)) {
108 			IF_DROP(ifq);
109 			m_freem(m);
110 			splx(s);
111 			return (ENOBUFS);
112 		}
113 		IF_ENQUEUE(ifq, m);
114 		schednetisr(NETISR_IP);
115 		break;
116 #endif
117 #ifdef NS
118 	case AF_NS:
119 		ifq = &nsintrq;
120 		if (IF_QFULL(ifq)) {
121 			IF_DROP(ifq);
122 			m_freem(m);
123 			splx(s);
124 			return (ENOBUFS);
125 		}
126 		IF_ENQUEUE(ifq, m);
127 		schednetisr(NETISR_NS);
128 		break;
129 #endif
130 #ifdef ISO
131 	case AF_ISO:
132 		ifq = &clnlintrq;
133 		if (IF_QFULL(ifq)) {
134 			IF_DROP(ifq);
135 			m_freem(m);
136 			splx(s);
137 			return (ENOBUFS);
138 		}
139 		IF_ENQUEUE(ifq, m);
140 		schednetisr(NETISR_ISO);
141 		break;
142 #endif
143 	default:
144 		splx(s);
145 		printf("lo%d: can't handle af%d\n", ifp->if_unit,
146 			dst->sa_family);
147 		m_freem(m);
148 		return (EAFNOSUPPORT);
149 	}
150 	ifp->if_ipackets++;
151 	splx(s);
152 	return (0);
153 }
154 
155 /*
156  * Process an ioctl request.
157  */
158 /* ARGSUSED */
159 loioctl(ifp, cmd, data)
160 	register struct ifnet *ifp;
161 	int cmd;
162 	caddr_t data;
163 {
164 	int error = 0;
165 
166 	switch (cmd) {
167 
168 	case SIOCSIFADDR:
169 		ifp->if_flags |= IFF_UP;
170 		/*
171 		 * Everything else is done at a higher level.
172 		 */
173 		break;
174 
175 	default:
176 		error = EINVAL;
177 	}
178 	return (error);
179 }
180