xref: /csrg-svn/sys/net/if_loop.c (revision 45198)
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.11 (Berkeley) 09/04/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 looutput(ifp, m, dst, rt)
66 	struct ifnet *ifp;
67 	register struct mbuf *m;
68 	struct sockaddr *dst;
69 	register struct rtentry *rt;
70 {
71 	int s;
72 	register struct ifqueue *ifq;
73 
74 	if ((m->m_flags & M_PKTHDR) == 0)
75 		panic("looutput no HDR");
76 	m->m_pkthdr.rcvif = ifp;
77 
78 	if (rt && rt->rt_flags & RTF_REJECT) {
79 		m_freem(m);
80 		return (rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH);
81 	}
82 	s = splimp();
83 	ifp->if_opackets++;
84 	ifp->if_obytes += m->m_pkthdr.len;
85 	switch (dst->sa_family) {
86 
87 #ifdef INET
88 	case AF_INET:
89 		ifq = &ipintrq;
90 		if (IF_QFULL(ifq)) {
91 			IF_DROP(ifq);
92 			m_freem(m);
93 			splx(s);
94 			return (ENOBUFS);
95 		}
96 		IF_ENQUEUE(ifq, m);
97 		schednetisr(NETISR_IP);
98 		break;
99 #endif
100 #ifdef NS
101 	case AF_NS:
102 		ifq = &nsintrq;
103 		if (IF_QFULL(ifq)) {
104 			IF_DROP(ifq);
105 			m_freem(m);
106 			splx(s);
107 			return (ENOBUFS);
108 		}
109 		IF_ENQUEUE(ifq, m);
110 		schednetisr(NETISR_NS);
111 		break;
112 #endif
113 #ifdef ISO
114 	case AF_ISO:
115 		ifq = &clnlintrq;
116 		if (IF_QFULL(ifq)) {
117 			IF_DROP(ifq);
118 			m_freem(m);
119 			splx(s);
120 			return (ENOBUFS);
121 		}
122 		IF_ENQUEUE(ifq, m);
123 		schednetisr(NETISR_ISO);
124 		break;
125 #endif
126 	default:
127 		splx(s);
128 		printf("lo%d: can't handle af%d\n", ifp->if_unit,
129 			dst->sa_family);
130 		m_freem(m);
131 		return (EAFNOSUPPORT);
132 	}
133 	ifp->if_ipackets++;
134 	ifp->if_ibytes += m->m_pkthdr.len;
135 	splx(s);
136 	return (0);
137 }
138 
139 /*
140  * Process an ioctl request.
141  */
142 /* ARGSUSED */
143 loioctl(ifp, cmd, data)
144 	register struct ifnet *ifp;
145 	int cmd;
146 	caddr_t data;
147 {
148 	int error = 0;
149 
150 	switch (cmd) {
151 
152 	case SIOCSIFADDR:
153 		ifp->if_flags |= IFF_UP;
154 		/*
155 		 * Everything else is done at a higher level.
156 		 */
157 		break;
158 
159 	default:
160 		error = EINVAL;
161 	}
162 	return (error);
163 }
164