xref: /original-bsd/sys/net/if_loop.c (revision 72b8f354)
1 /*
2  * Copyright (c) 1982, 1986 Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)if_loop.c	7.10 (Berkeley) 06/28/90
8  */
9 
10 /*
11  * Loopback interface driver for protocol testing and timing.
12  */
13 
14 #include "param.h"
15 #include "systm.h"
16 #include "mbuf.h"
17 #include "socket.h"
18 #include "errno.h"
19 #include "ioctl.h"
20 
21 #include "../net/if.h"
22 #include "../net/if_types.h"
23 #include "../net/netisr.h"
24 #include "../net/route.h"
25 
26 #include "machine/mtpr.h"
27 
28 #ifdef	INET
29 #include "../netinet/in.h"
30 #include "../netinet/in_systm.h"
31 #include "../netinet/in_var.h"
32 #include "../netinet/ip.h"
33 #endif
34 
35 #ifdef NS
36 #include "../netns/ns.h"
37 #include "../netns/ns_if.h"
38 #endif
39 
40 #ifdef ISO
41 #include "../netiso/iso.h"
42 #include "../netiso/iso_var.h"
43 #endif
44 
45 #define	LOMTU	(1024+512)
46 
47 struct	ifnet loif;
48 int	looutput(), loioctl();
49 
50 loattach()
51 {
52 	register struct ifnet *ifp = &loif;
53 
54 	ifp->if_name = "lo";
55 	ifp->if_mtu = LOMTU;
56 	ifp->if_flags = IFF_LOOPBACK;
57 	ifp->if_ioctl = loioctl;
58 	ifp->if_output = looutput;
59 	ifp->if_type = IFT_LOOP;
60 	ifp->if_hdrlen = 0;
61 	ifp->if_addrlen = 0;
62 	if_attach(ifp);
63 }
64 
65 struct mbuf *Loop_Sanity;
66 
67 looutput(ifp, m, dst)
68 	struct ifnet *ifp;
69 	register struct mbuf *m;
70 	struct sockaddr *dst;
71 {
72 	int s;
73 	register struct ifqueue *ifq;
74 
75 	if ((m->m_flags & M_PKTHDR) == 0)
76 		panic("looutput no HDR");
77 	m->m_pkthdr.rcvif = ifp;
78 
79 {struct mbuf *mm; int mlen = 0;
80 for (mm = m; m; m = m->m_next) /* XXX debugging code -- sklower */
81     mlen += m->m_len;
82 m = mm;
83 if (mlen != m->m_pkthdr.len) {
84 	if (Loop_Sanity)
85 		m_freem(Loop_Sanity);
86 	Loop_Sanity = m_copy(m, 0, (int)M_COPYALL);
87 }
88 }
89 
90 	s = splimp();
91 	ifp->if_opackets++;
92 	ifp->if_obytes += m->m_pkthdr.len;
93 	switch (dst->sa_family) {
94 
95 #ifdef INET
96 	case AF_INET:
97 		ifq = &ipintrq;
98 		if (IF_QFULL(ifq)) {
99 			IF_DROP(ifq);
100 			m_freem(m);
101 			splx(s);
102 			return (ENOBUFS);
103 		}
104 		IF_ENQUEUE(ifq, m);
105 		schednetisr(NETISR_IP);
106 		break;
107 #endif
108 #ifdef NS
109 	case AF_NS:
110 		ifq = &nsintrq;
111 		if (IF_QFULL(ifq)) {
112 			IF_DROP(ifq);
113 			m_freem(m);
114 			splx(s);
115 			return (ENOBUFS);
116 		}
117 		IF_ENQUEUE(ifq, m);
118 		schednetisr(NETISR_NS);
119 		break;
120 #endif
121 #ifdef ISO
122 	case AF_ISO:
123 		ifq = &clnlintrq;
124 		if (IF_QFULL(ifq)) {
125 			IF_DROP(ifq);
126 			m_freem(m);
127 			splx(s);
128 			return (ENOBUFS);
129 		}
130 		IF_ENQUEUE(ifq, m);
131 		schednetisr(NETISR_ISO);
132 		break;
133 #endif
134 	default:
135 		splx(s);
136 		printf("lo%d: can't handle af%d\n", ifp->if_unit,
137 			dst->sa_family);
138 		m_freem(m);
139 		return (EAFNOSUPPORT);
140 	}
141 	ifp->if_ipackets++;
142 	ifp->if_ibytes += m->m_pkthdr.len;
143 	splx(s);
144 	return (0);
145 }
146 
147 /*
148  * Process an ioctl request.
149  */
150 /* ARGSUSED */
151 loioctl(ifp, cmd, data)
152 	register struct ifnet *ifp;
153 	int cmd;
154 	caddr_t data;
155 {
156 	int error = 0;
157 
158 	switch (cmd) {
159 
160 	case SIOCSIFADDR:
161 		ifp->if_flags |= IFF_UP;
162 		/*
163 		 * Everything else is done at a higher level.
164 		 */
165 		break;
166 
167 	default:
168 		error = EINVAL;
169 	}
170 	return (error);
171 }
172