xref: /original-bsd/sys/net/if_loop.c (revision b485b642)
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.9 (Berkeley) 09/20/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/if_types.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 	ifp->if_obytes += m->m_pkthdr.len;
103 	switch (dst->sa_family) {
104 
105 #ifdef INET
106 	case AF_INET:
107 		ifq = &ipintrq;
108 		if (IF_QFULL(ifq)) {
109 			IF_DROP(ifq);
110 			m_freem(m);
111 			splx(s);
112 			return (ENOBUFS);
113 		}
114 		IF_ENQUEUE(ifq, m);
115 		schednetisr(NETISR_IP);
116 		break;
117 #endif
118 #ifdef NS
119 	case AF_NS:
120 		ifq = &nsintrq;
121 		if (IF_QFULL(ifq)) {
122 			IF_DROP(ifq);
123 			m_freem(m);
124 			splx(s);
125 			return (ENOBUFS);
126 		}
127 		IF_ENQUEUE(ifq, m);
128 		schednetisr(NETISR_NS);
129 		break;
130 #endif
131 #ifdef ISO
132 	case AF_ISO:
133 		ifq = &clnlintrq;
134 		if (IF_QFULL(ifq)) {
135 			IF_DROP(ifq);
136 			m_freem(m);
137 			splx(s);
138 			return (ENOBUFS);
139 		}
140 		IF_ENQUEUE(ifq, m);
141 		schednetisr(NETISR_ISO);
142 		break;
143 #endif
144 	default:
145 		splx(s);
146 		printf("lo%d: can't handle af%d\n", ifp->if_unit,
147 			dst->sa_family);
148 		m_freem(m);
149 		return (EAFNOSUPPORT);
150 	}
151 	ifp->if_ipackets++;
152 	ifp->if_ibytes += m->m_pkthdr.len;
153 	splx(s);
154 	return (0);
155 }
156 
157 /*
158  * Process an ioctl request.
159  */
160 /* ARGSUSED */
161 loioctl(ifp, cmd, data)
162 	register struct ifnet *ifp;
163 	int cmd;
164 	caddr_t data;
165 {
166 	int error = 0;
167 
168 	switch (cmd) {
169 
170 	case SIOCSIFADDR:
171 		ifp->if_flags |= IFF_UP;
172 		/*
173 		 * Everything else is done at a higher level.
174 		 */
175 		break;
176 
177 	default:
178 		error = EINVAL;
179 	}
180 	return (error);
181 }
182