xref: /csrg-svn/sys/net/if_loop.c (revision 34844)
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.4 (Berkeley) 06/27/88
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/netisr.h"
33 #include "../net/route.h"
34 
35 #include "../machine/mtpr.h"
36 
37 #ifdef	INET
38 #include "../netinet/in.h"
39 #include "../netinet/in_systm.h"
40 #include "../netinet/in_var.h"
41 #include "../netinet/ip.h"
42 #endif
43 
44 #ifdef NS
45 #include "../netns/ns.h"
46 #include "../netns/ns_if.h"
47 #endif
48 
49 #define	LOMTU	(1024+512)
50 
51 struct	ifnet loif;
52 int	looutput(), loioctl();
53 
54 loattach()
55 {
56 	register struct ifnet *ifp = &loif;
57 
58 	ifp->if_name = "lo";
59 	ifp->if_mtu = LOMTU;
60 	ifp->if_flags = IFF_LOOPBACK;
61 	ifp->if_ioctl = loioctl;
62 	ifp->if_output = looutput;
63 	if_attach(ifp);
64 }
65 
66 looutput(ifp, m0, dst)
67 	struct ifnet *ifp;
68 	register struct mbuf *m0;
69 	struct sockaddr *dst;
70 {
71 	int s;
72 	register struct ifqueue *ifq;
73 	struct mbuf *m;
74 
75 	/*
76 	 * Place interface pointer before the data
77 	 * for the receiving protocol.
78 	 */
79 	if (m0->m_off <= MMAXOFF &&
80 	    m0->m_off >= MMINOFF + sizeof(struct ifnet *)) {
81 		m0->m_off -= sizeof(struct ifnet *);
82 		m0->m_len += sizeof(struct ifnet *);
83 	} else {
84 		MGET(m, M_DONTWAIT, MT_HEADER);
85 		if (m == (struct mbuf *)0)
86 			return (ENOBUFS);
87 		m->m_off = MMINOFF;
88 		m->m_len = sizeof(struct ifnet *);
89 		m->m_next = m0;
90 		m0 = m;
91 	}
92 	*(mtod(m0, struct ifnet **)) = ifp;
93 	s = splimp();
94 	ifp->if_opackets++;
95 	switch (dst->sa_family) {
96 
97 #ifdef INET
98 	case AF_INET:
99 		ifq = &ipintrq;
100 		if (IF_QFULL(ifq)) {
101 			IF_DROP(ifq);
102 			m_freem(m0);
103 			splx(s);
104 			return (ENOBUFS);
105 		}
106 		IF_ENQUEUE(ifq, m0);
107 		schednetisr(NETISR_IP);
108 		break;
109 #endif
110 #ifdef NS
111 	case AF_NS:
112 		ifq = &nsintrq;
113 		if (IF_QFULL(ifq)) {
114 			IF_DROP(ifq);
115 			m_freem(m0);
116 			splx(s);
117 			return (ENOBUFS);
118 		}
119 		IF_ENQUEUE(ifq, m0);
120 		schednetisr(NETISR_NS);
121 		break;
122 #endif
123 	default:
124 		splx(s);
125 		printf("lo%d: can't handle af%d\n", ifp->if_unit,
126 			dst->sa_family);
127 		m_freem(m0);
128 		return (EAFNOSUPPORT);
129 	}
130 	ifp->if_ipackets++;
131 	splx(s);
132 	return (0);
133 }
134 
135 /*
136  * Process an ioctl request.
137  */
138 /* ARGSUSED */
139 loioctl(ifp, cmd, data)
140 	register struct ifnet *ifp;
141 	int cmd;
142 	caddr_t data;
143 {
144 	int error = 0;
145 
146 	switch (cmd) {
147 
148 	case SIOCSIFADDR:
149 		ifp->if_flags |= IFF_UP;
150 		/*
151 		 * Everything else is done at a higher level.
152 		 */
153 		break;
154 
155 	default:
156 		error = EINVAL;
157 	}
158 	return (error);
159 }
160