xref: /original-bsd/sys/net/if_loop.c (revision bdc0a208)
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.13 (Berkeley) 04/26/91
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, isr;
72 	register struct ifqueue *ifq = 0;
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 	ifp->if_opackets++;
83 	ifp->if_obytes += m->m_pkthdr.len;
84 	switch (dst->sa_family) {
85 
86 #ifdef INET
87 	case AF_INET:
88 		ifq = &ipintrq;
89 		isr = NETISR_IP;
90 		break;
91 #endif
92 #ifdef NS
93 	case AF_NS:
94 		ifq = &nsintrq;
95 		isr = NETISR_NS;
96 		break;
97 #endif
98 #ifdef ISO
99 	case AF_ISO:
100 		ifq = &clnlintrq;
101 		isr = NETISR_ISO;
102 		break;
103 #endif
104 	default:
105 		printf("lo%d: can't handle af%d\n", ifp->if_unit,
106 			dst->sa_family);
107 		m_freem(m);
108 		return (EAFNOSUPPORT);
109 	}
110 	s = splimp();
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(isr);
119 	ifp->if_ipackets++;
120 	ifp->if_ibytes += m->m_pkthdr.len;
121 	splx(s);
122 	return (0);
123 }
124 
125 /* ARGSUSED */
126 lortrequest(cmd, rt, sa)
127 struct rtentry *rt;
128 struct sockaddr *sa;
129 {
130 	if (rt)
131 		rt->rt_rmx.rmx_mtu = LOMTU;
132 }
133 
134 /*
135  * Process an ioctl request.
136  */
137 /* ARGSUSED */
138 loioctl(ifp, cmd, data)
139 	register struct ifnet *ifp;
140 	int cmd;
141 	caddr_t data;
142 {
143 	register struct ifaddr *ifa;
144 	int error = 0;
145 
146 	switch (cmd) {
147 
148 	case SIOCSIFADDR:
149 		ifp->if_flags |= IFF_UP;
150 		ifa = (struct ifaddr *)data;
151 		if (ifa != 0 && ifa->ifa_addr->sa_family == AF_ISO)
152 			ifa->ifa_rtrequest = lortrequest;
153 		/*
154 		 * Everything else is done at a higher level.
155 		 */
156 		break;
157 
158 	default:
159 		error = EINVAL;
160 	}
161 	return (error);
162 }
163