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