xref: /original-bsd/sys/net/if_loop.c (revision baf24c0d)
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.12 (Berkeley) 11/06/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 #ifdef CCITT
46 #include "../netccitt/x25.h"
47 #include "../netccitt/hdlc.h"
48 #include "../netccitt/hd_var.h"
49 #endif
50 
51 #define	LOMTU	(1024+512)
52 
53 struct	ifnet loif;
54 int	looutput(), loioctl();
55 
56 loattach()
57 {
58 	register struct ifnet *ifp = &loif;
59 
60 	ifp->if_name = "lo";
61 	ifp->if_mtu = LOMTU;
62 	ifp->if_flags = IFF_LOOPBACK;
63 	ifp->if_ioctl = loioctl;
64 	ifp->if_output = looutput;
65 	ifp->if_type = IFT_LOOP;
66 	ifp->if_hdrlen = 0;
67 	ifp->if_addrlen = 0;
68 	if_attach(ifp);
69 }
70 
71 looutput(ifp, m, dst, rt)
72 	struct ifnet *ifp;
73 	register struct mbuf *m;
74 	struct sockaddr *dst;
75 	register struct rtentry *rt;
76 {
77 	int s, isr;
78 	register struct ifqueue *ifq = 0;
79 
80 	if ((m->m_flags & M_PKTHDR) == 0)
81 		panic("looutput no HDR");
82 	m->m_pkthdr.rcvif = ifp;
83 
84 	if (rt && rt->rt_flags & RTF_REJECT) {
85 		m_freem(m);
86 		return (rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH);
87 	}
88 	s = splimp();
89 	ifp->if_opackets++;
90 	ifp->if_obytes += m->m_pkthdr.len;
91 	switch (dst->sa_family) {
92 
93 #ifdef INET
94 	case AF_INET:
95 		ifq = &ipintrq;
96 		isr = NETISR_IP;
97 		break;
98 #endif
99 #ifdef NS
100 	case AF_NS:
101 		ifq = &nsintrq;
102 		isr = NETISR_NS;
103 		break;
104 #endif
105 #ifdef ISO
106 	case AF_ISO:
107 		ifq = &clnlintrq;
108 		isr = NETISR_ISO;
109 		break;
110 #endif
111 #ifdef CCITT
112 	case AF_CCITT:
113 		ifq = &hdintrq;
114 		isr = NETISR_CCITT;
115 		break;
116 #endif
117 	default:
118 		splx(s);
119 		printf("lo%d: can't handle af%d\n", ifp->if_unit,
120 			dst->sa_family);
121 		m_freem(m);
122 		return (EAFNOSUPPORT);
123 	}
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(isr);
132 	ifp->if_ipackets++;
133 	ifp->if_ibytes += m->m_pkthdr.len;
134 	splx(s);
135 	return (0);
136 }
137 
138 /*
139  * Process an ioctl request.
140  */
141 /* ARGSUSED */
142 loioctl(ifp, cmd, data)
143 	register struct ifnet *ifp;
144 	int cmd;
145 	caddr_t data;
146 {
147 	int error = 0;
148 
149 	switch (cmd) {
150 
151 #ifdef CCITT
152 	case SIOCSIFCONF_X25:
153 #endif
154 	case SIOCSIFADDR:
155 		ifp->if_flags |= IFF_UP;
156 		/*
157 		 * Everything else is done at a higher level.
158 		 */
159 		break;
160 
161 	default:
162 		error = EINVAL;
163 	}
164 	return (error);
165 }
166