| @@ -1,1629 +1,1639 @@ | | | @@ -1,1629 +1,1639 @@ |
1 | /* $NetBSD: if_ethersubr.c,v 1.242.6.4 2018/03/08 14:37:58 martin Exp $ */ | | 1 | /* $NetBSD: if_ethersubr.c,v 1.242.6.5 2018/03/13 15:40:25 martin Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. | | 4 | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | | 7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions | | 8 | * modification, are permitted provided that the following conditions |
9 | * are met: | | 9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright | | 10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. | | 11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright | | 12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the | | 13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. | | 14 | * documentation and/or other materials provided with the distribution. |
15 | * 3. Neither the name of the project nor the names of its contributors | | 15 | * 3. Neither the name of the project nor the names of its contributors |
16 | * may be used to endorse or promote products derived from this software | | 16 | * may be used to endorse or promote products derived from this software |
17 | * without specific prior written permission. | | 17 | * without specific prior written permission. |
18 | * | | 18 | * |
19 | * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND | | 19 | * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND |
20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE | | 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE |
23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
29 | * SUCH DAMAGE. | | 29 | * SUCH DAMAGE. |
30 | */ | | 30 | */ |
31 | | | 31 | |
32 | /* | | 32 | /* |
33 | * Copyright (c) 1982, 1989, 1993 | | 33 | * Copyright (c) 1982, 1989, 1993 |
34 | * The Regents of the University of California. All rights reserved. | | 34 | * The Regents of the University of California. All rights reserved. |
35 | * | | 35 | * |
36 | * Redistribution and use in source and binary forms, with or without | | 36 | * Redistribution and use in source and binary forms, with or without |
37 | * modification, are permitted provided that the following conditions | | 37 | * modification, are permitted provided that the following conditions |
38 | * are met: | | 38 | * are met: |
39 | * 1. Redistributions of source code must retain the above copyright | | 39 | * 1. Redistributions of source code must retain the above copyright |
40 | * notice, this list of conditions and the following disclaimer. | | 40 | * notice, this list of conditions and the following disclaimer. |
41 | * 2. Redistributions in binary form must reproduce the above copyright | | 41 | * 2. Redistributions in binary form must reproduce the above copyright |
42 | * notice, this list of conditions and the following disclaimer in the | | 42 | * notice, this list of conditions and the following disclaimer in the |
43 | * documentation and/or other materials provided with the distribution. | | 43 | * documentation and/or other materials provided with the distribution. |
44 | * 3. Neither the name of the University nor the names of its contributors | | 44 | * 3. Neither the name of the University nor the names of its contributors |
45 | * may be used to endorse or promote products derived from this software | | 45 | * may be used to endorse or promote products derived from this software |
46 | * without specific prior written permission. | | 46 | * without specific prior written permission. |
47 | * | | 47 | * |
48 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | | 48 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
49 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | 49 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
50 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 50 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
51 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | | 51 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
52 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 52 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
53 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 53 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
54 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 54 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
55 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 55 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
56 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 56 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
57 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 57 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
58 | * SUCH DAMAGE. | | 58 | * SUCH DAMAGE. |
59 | * | | 59 | * |
60 | * @(#)if_ethersubr.c 8.2 (Berkeley) 4/4/96 | | 60 | * @(#)if_ethersubr.c 8.2 (Berkeley) 4/4/96 |
61 | */ | | 61 | */ |
62 | | | 62 | |
63 | #include <sys/cdefs.h> | | 63 | #include <sys/cdefs.h> |
64 | __KERNEL_RCSID(0, "$NetBSD: if_ethersubr.c,v 1.242.6.4 2018/03/08 14:37:58 martin Exp $"); | | 64 | __KERNEL_RCSID(0, "$NetBSD: if_ethersubr.c,v 1.242.6.5 2018/03/13 15:40:25 martin Exp $"); |
65 | | | 65 | |
66 | #ifdef _KERNEL_OPT | | 66 | #ifdef _KERNEL_OPT |
67 | #include "opt_inet.h" | | 67 | #include "opt_inet.h" |
68 | #include "opt_atalk.h" | | 68 | #include "opt_atalk.h" |
69 | #include "opt_mbuftrace.h" | | 69 | #include "opt_mbuftrace.h" |
70 | #include "opt_mpls.h" | | 70 | #include "opt_mpls.h" |
71 | #include "opt_gateway.h" | | 71 | #include "opt_gateway.h" |
72 | #include "opt_pppoe.h" | | 72 | #include "opt_pppoe.h" |
73 | #include "opt_net_mpsafe.h" | | 73 | #include "opt_net_mpsafe.h" |
74 | #endif | | 74 | #endif |
75 | | | 75 | |
76 | #include "vlan.h" | | 76 | #include "vlan.h" |
77 | #include "pppoe.h" | | 77 | #include "pppoe.h" |
78 | #include "bridge.h" | | 78 | #include "bridge.h" |
79 | #include "arp.h" | | 79 | #include "arp.h" |
80 | #include "agr.h" | | 80 | #include "agr.h" |
81 | | | 81 | |
82 | #include <sys/sysctl.h> | | 82 | #include <sys/sysctl.h> |
83 | #include <sys/mbuf.h> | | 83 | #include <sys/mbuf.h> |
84 | #include <sys/mutex.h> | | 84 | #include <sys/mutex.h> |
85 | #include <sys/ioctl.h> | | 85 | #include <sys/ioctl.h> |
86 | #include <sys/errno.h> | | 86 | #include <sys/errno.h> |
87 | #include <sys/device.h> | | 87 | #include <sys/device.h> |
88 | #include <sys/rnd.h> | | 88 | #include <sys/rnd.h> |
89 | #include <sys/rndsource.h> | | 89 | #include <sys/rndsource.h> |
90 | #include <sys/cpu.h> | | 90 | #include <sys/cpu.h> |
91 | #include <sys/kmem.h> | | 91 | #include <sys/kmem.h> |
92 | | | 92 | |
93 | #include <net/if.h> | | 93 | #include <net/if.h> |
94 | #include <net/netisr.h> | | 94 | #include <net/netisr.h> |
95 | #include <net/route.h> | | 95 | #include <net/route.h> |
96 | #include <net/if_llc.h> | | 96 | #include <net/if_llc.h> |
97 | #include <net/if_dl.h> | | 97 | #include <net/if_dl.h> |
98 | #include <net/if_types.h> | | 98 | #include <net/if_types.h> |
99 | #include <net/pktqueue.h> | | 99 | #include <net/pktqueue.h> |
100 | | | 100 | |
101 | #include <net/if_media.h> | | 101 | #include <net/if_media.h> |
102 | #include <dev/mii/mii.h> | | 102 | #include <dev/mii/mii.h> |
103 | #include <dev/mii/miivar.h> | | 103 | #include <dev/mii/miivar.h> |
104 | | | 104 | |
105 | #if NARP == 0 | | 105 | #if NARP == 0 |
106 | /* | | 106 | /* |
107 | * XXX there should really be a way to issue this warning from within config(8) | | 107 | * XXX there should really be a way to issue this warning from within config(8) |
108 | */ | | 108 | */ |
109 | #error You have included NETATALK or a pseudo-device in your configuration that depends on the presence of ethernet interfaces, but have no such interfaces configured. Check if you really need pseudo-device bridge, pppoe, vlan or options NETATALK. | | 109 | #error You have included NETATALK or a pseudo-device in your configuration that depends on the presence of ethernet interfaces, but have no such interfaces configured. Check if you really need pseudo-device bridge, pppoe, vlan or options NETATALK. |
110 | #endif | | 110 | #endif |
111 | | | 111 | |
112 | #include <net/bpf.h> | | 112 | #include <net/bpf.h> |
113 | | | 113 | |
114 | #include <net/if_ether.h> | | 114 | #include <net/if_ether.h> |
115 | #include <net/if_vlanvar.h> | | 115 | #include <net/if_vlanvar.h> |
116 | | | 116 | |
117 | #if NPPPOE > 0 | | 117 | #if NPPPOE > 0 |
118 | #include <net/if_pppoe.h> | | 118 | #include <net/if_pppoe.h> |
119 | #endif | | 119 | #endif |
120 | | | 120 | |
121 | #if NAGR > 0 | | 121 | #if NAGR > 0 |
122 | #include <net/agr/ieee8023_slowprotocols.h> /* XXX */ | | 122 | #include <net/agr/ieee8023_slowprotocols.h> /* XXX */ |
123 | #include <net/agr/ieee8023ad.h> | | 123 | #include <net/agr/ieee8023ad.h> |
124 | #include <net/agr/if_agrvar.h> | | 124 | #include <net/agr/if_agrvar.h> |
125 | #endif | | 125 | #endif |
126 | | | 126 | |
127 | #if NBRIDGE > 0 | | 127 | #if NBRIDGE > 0 |
128 | #include <net/if_bridgevar.h> | | 128 | #include <net/if_bridgevar.h> |
129 | #endif | | 129 | #endif |
130 | | | 130 | |
131 | #include <netinet/in.h> | | 131 | #include <netinet/in.h> |
132 | #ifdef INET | | 132 | #ifdef INET |
133 | #include <netinet/in_var.h> | | 133 | #include <netinet/in_var.h> |
134 | #endif | | 134 | #endif |
135 | #include <netinet/if_inarp.h> | | 135 | #include <netinet/if_inarp.h> |
136 | | | 136 | |
137 | #ifdef INET6 | | 137 | #ifdef INET6 |
138 | #ifndef INET | | 138 | #ifndef INET |
139 | #include <netinet/in.h> | | 139 | #include <netinet/in.h> |
140 | #endif | | 140 | #endif |
141 | #include <netinet6/in6_var.h> | | 141 | #include <netinet6/in6_var.h> |
142 | #include <netinet6/nd6.h> | | 142 | #include <netinet6/nd6.h> |
143 | #endif | | 143 | #endif |
144 | | | 144 | |
145 | | | 145 | |
146 | #include "carp.h" | | 146 | #include "carp.h" |
147 | #if NCARP > 0 | | 147 | #if NCARP > 0 |
148 | #include <netinet/ip_carp.h> | | 148 | #include <netinet/ip_carp.h> |
149 | #endif | | 149 | #endif |
150 | | | 150 | |
151 | #ifdef NETATALK | | 151 | #ifdef NETATALK |
152 | #include <netatalk/at.h> | | 152 | #include <netatalk/at.h> |
153 | #include <netatalk/at_var.h> | | 153 | #include <netatalk/at_var.h> |
154 | #include <netatalk/at_extern.h> | | 154 | #include <netatalk/at_extern.h> |
155 | | | 155 | |
156 | #define llc_snap_org_code llc_un.type_snap.org_code | | 156 | #define llc_snap_org_code llc_un.type_snap.org_code |
157 | #define llc_snap_ether_type llc_un.type_snap.ether_type | | 157 | #define llc_snap_ether_type llc_un.type_snap.ether_type |
158 | | | 158 | |
159 | extern u_char at_org_code[3]; | | 159 | extern u_char at_org_code[3]; |
160 | extern u_char aarp_org_code[3]; | | 160 | extern u_char aarp_org_code[3]; |
161 | #endif /* NETATALK */ | | 161 | #endif /* NETATALK */ |
162 | | | 162 | |
163 | #ifdef MPLS | | 163 | #ifdef MPLS |
164 | #include <netmpls/mpls.h> | | 164 | #include <netmpls/mpls.h> |
165 | #include <netmpls/mpls_var.h> | | 165 | #include <netmpls/mpls_var.h> |
166 | #endif | | 166 | #endif |
167 | | | 167 | |
168 | static struct timeval bigpktppslim_last; | | 168 | static struct timeval bigpktppslim_last; |
169 | static int bigpktppslim = 2; /* XXX */ | | 169 | static int bigpktppslim = 2; /* XXX */ |
170 | static int bigpktpps_count; | | 170 | static int bigpktpps_count; |
171 | static kmutex_t bigpktpps_lock __cacheline_aligned; | | 171 | static kmutex_t bigpktpps_lock __cacheline_aligned; |
172 | | | 172 | |
173 | | | 173 | |
174 | const uint8_t etherbroadcastaddr[ETHER_ADDR_LEN] = | | 174 | const uint8_t etherbroadcastaddr[ETHER_ADDR_LEN] = |
175 | { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; | | 175 | { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; |
176 | const uint8_t ethermulticastaddr_slowprotocols[ETHER_ADDR_LEN] = | | 176 | const uint8_t ethermulticastaddr_slowprotocols[ETHER_ADDR_LEN] = |
177 | { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x02 }; | | 177 | { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x02 }; |
178 | #define senderr(e) { error = (e); goto bad;} | | 178 | #define senderr(e) { error = (e); goto bad;} |
179 | | | 179 | |
180 | static int ether_output(struct ifnet *, struct mbuf *, | | 180 | static int ether_output(struct ifnet *, struct mbuf *, |
181 | const struct sockaddr *, const struct rtentry *); | | 181 | const struct sockaddr *, const struct rtentry *); |
182 | | | 182 | |
183 | /* | | 183 | /* |
184 | * Ethernet output routine. | | 184 | * Ethernet output routine. |
185 | * Encapsulate a packet of type family for the local net. | | 185 | * Encapsulate a packet of type family for the local net. |
186 | * Assumes that ifp is actually pointer to ethercom structure. | | 186 | * Assumes that ifp is actually pointer to ethercom structure. |
187 | */ | | 187 | */ |
188 | static int | | 188 | static int |
189 | ether_output(struct ifnet * const ifp0, struct mbuf * const m0, | | 189 | ether_output(struct ifnet * const ifp0, struct mbuf * const m0, |
190 | const struct sockaddr * const dst, | | 190 | const struct sockaddr * const dst, |
191 | const struct rtentry *rt) | | 191 | const struct rtentry *rt) |
192 | { | | 192 | { |
193 | uint16_t etype = 0; | | 193 | uint16_t etype = 0; |
194 | int error = 0, hdrcmplt = 0; | | 194 | int error = 0, hdrcmplt = 0; |
195 | uint8_t esrc[6], edst[6]; | | 195 | uint8_t esrc[6], edst[6]; |
196 | struct mbuf *m = m0; | | 196 | struct mbuf *m = m0; |
197 | struct mbuf *mcopy = NULL; | | 197 | struct mbuf *mcopy = NULL; |
198 | struct ether_header *eh; | | 198 | struct ether_header *eh; |
199 | struct ifnet *ifp = ifp0; | | 199 | struct ifnet *ifp = ifp0; |
200 | #ifdef INET | | 200 | #ifdef INET |
201 | struct arphdr *ah; | | 201 | struct arphdr *ah; |
202 | #endif /* INET */ | | 202 | #endif /* INET */ |
203 | #ifdef NETATALK | | 203 | #ifdef NETATALK |
204 | struct at_ifaddr *aa; | | 204 | struct at_ifaddr *aa; |
205 | #endif /* NETATALK */ | | 205 | #endif /* NETATALK */ |
206 | | | 206 | |
207 | #ifdef MBUFTRACE | | 207 | #ifdef MBUFTRACE |
208 | m_claimm(m, ifp->if_mowner); | | 208 | m_claimm(m, ifp->if_mowner); |
209 | #endif | | 209 | #endif |
210 | | | 210 | |
211 | #if NCARP > 0 | | 211 | #if NCARP > 0 |
212 | if (ifp->if_type == IFT_CARP) { | | 212 | if (ifp->if_type == IFT_CARP) { |
213 | struct ifaddr *ifa; | | 213 | struct ifaddr *ifa; |
214 | int s = pserialize_read_enter(); | | 214 | int s = pserialize_read_enter(); |
215 | | | 215 | |
216 | /* loop back if this is going to the carp interface */ | | 216 | /* loop back if this is going to the carp interface */ |
217 | if (dst != NULL && ifp0->if_link_state == LINK_STATE_UP && | | 217 | if (dst != NULL && ifp0->if_link_state == LINK_STATE_UP && |
218 | (ifa = ifa_ifwithaddr(dst)) != NULL) { | | 218 | (ifa = ifa_ifwithaddr(dst)) != NULL) { |
219 | if (ifa->ifa_ifp == ifp0) { | | 219 | if (ifa->ifa_ifp == ifp0) { |
220 | pserialize_read_exit(s); | | 220 | pserialize_read_exit(s); |
221 | return looutput(ifp0, m, dst, rt); | | 221 | return looutput(ifp0, m, dst, rt); |
222 | } | | 222 | } |
223 | } | | 223 | } |
224 | pserialize_read_exit(s); | | 224 | pserialize_read_exit(s); |
225 | | | 225 | |
226 | ifp = ifp->if_carpdev; | | 226 | ifp = ifp->if_carpdev; |
227 | /* ac = (struct arpcom *)ifp; */ | | 227 | /* ac = (struct arpcom *)ifp; */ |
228 | | | 228 | |
229 | if ((ifp0->if_flags & (IFF_UP | IFF_RUNNING)) != | | 229 | if ((ifp0->if_flags & (IFF_UP | IFF_RUNNING)) != |
230 | (IFF_UP | IFF_RUNNING)) | | 230 | (IFF_UP | IFF_RUNNING)) |
231 | senderr(ENETDOWN); | | 231 | senderr(ENETDOWN); |
232 | } | | 232 | } |
233 | #endif /* NCARP > 0 */ | | 233 | #endif /* NCARP > 0 */ |
234 | | | 234 | |
235 | if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) != (IFF_UP | IFF_RUNNING)) | | 235 | if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) != (IFF_UP | IFF_RUNNING)) |
236 | senderr(ENETDOWN); | | 236 | senderr(ENETDOWN); |
237 | | | 237 | |
238 | switch (dst->sa_family) { | | 238 | switch (dst->sa_family) { |
239 | | | 239 | |
240 | #ifdef INET | | 240 | #ifdef INET |
241 | case AF_INET: | | 241 | case AF_INET: |
242 | if (m->m_flags & M_BCAST) | | 242 | if (m->m_flags & M_BCAST) |
243 | (void)memcpy(edst, etherbroadcastaddr, sizeof(edst)); | | 243 | (void)memcpy(edst, etherbroadcastaddr, sizeof(edst)); |
244 | else if (m->m_flags & M_MCAST) | | 244 | else if (m->m_flags & M_MCAST) |
245 | ETHER_MAP_IP_MULTICAST(&satocsin(dst)->sin_addr, edst); | | 245 | ETHER_MAP_IP_MULTICAST(&satocsin(dst)->sin_addr, edst); |
246 | else if ((error = arpresolve(ifp, rt, m, dst, edst, | | 246 | else if ((error = arpresolve(ifp, rt, m, dst, edst, |
247 | sizeof(edst))) != 0) { | | 247 | sizeof(edst))) != 0) { |
248 | return error == EWOULDBLOCK ? 0 : error; | | 248 | return error == EWOULDBLOCK ? 0 : error; |
249 | } | | 249 | } |
250 | /* If broadcasting on a simplex interface, loopback a copy */ | | 250 | /* If broadcasting on a simplex interface, loopback a copy */ |
251 | if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX)) | | 251 | if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX)) |
252 | mcopy = m_copy(m, 0, (int)M_COPYALL); | | 252 | mcopy = m_copy(m, 0, (int)M_COPYALL); |
253 | etype = htons(ETHERTYPE_IP); | | 253 | etype = htons(ETHERTYPE_IP); |
254 | break; | | 254 | break; |
255 | | | 255 | |
256 | case AF_ARP: | | 256 | case AF_ARP: |
257 | ah = mtod(m, struct arphdr *); | | 257 | ah = mtod(m, struct arphdr *); |
258 | if (m->m_flags & M_BCAST) | | 258 | if (m->m_flags & M_BCAST) |
259 | (void)memcpy(edst, etherbroadcastaddr, sizeof(edst)); | | 259 | (void)memcpy(edst, etherbroadcastaddr, sizeof(edst)); |
260 | else { | | 260 | else { |
261 | void *tha = ar_tha(ah); | | 261 | void *tha = ar_tha(ah); |
262 | | | 262 | |
263 | if (tha == NULL) { | | 263 | if (tha == NULL) { |
264 | /* fake with ARPHDR_IEEE1394 */ | | 264 | /* fake with ARPHDR_IEEE1394 */ |
265 | m_freem(m); | | 265 | m_freem(m); |
266 | return 0; | | 266 | return 0; |
267 | } | | 267 | } |
268 | memcpy(edst, tha, sizeof(edst)); | | 268 | memcpy(edst, tha, sizeof(edst)); |
269 | } | | 269 | } |
270 | | | 270 | |
271 | ah->ar_hrd = htons(ARPHRD_ETHER); | | 271 | ah->ar_hrd = htons(ARPHRD_ETHER); |
272 | | | 272 | |
273 | switch (ntohs(ah->ar_op)) { | | 273 | switch (ntohs(ah->ar_op)) { |
274 | case ARPOP_REVREQUEST: | | 274 | case ARPOP_REVREQUEST: |
275 | case ARPOP_REVREPLY: | | 275 | case ARPOP_REVREPLY: |
276 | etype = htons(ETHERTYPE_REVARP); | | 276 | etype = htons(ETHERTYPE_REVARP); |
277 | break; | | 277 | break; |
278 | | | 278 | |
279 | case ARPOP_REQUEST: | | 279 | case ARPOP_REQUEST: |
280 | case ARPOP_REPLY: | | 280 | case ARPOP_REPLY: |
281 | default: | | 281 | default: |
282 | etype = htons(ETHERTYPE_ARP); | | 282 | etype = htons(ETHERTYPE_ARP); |
283 | } | | 283 | } |
284 | | | 284 | |
285 | break; | | 285 | break; |
286 | #endif | | 286 | #endif |
287 | #ifdef INET6 | | 287 | #ifdef INET6 |
288 | case AF_INET6: | | 288 | case AF_INET6: |
289 | if (m->m_flags & M_BCAST) | | 289 | if (m->m_flags & M_BCAST) |
290 | (void)memcpy(edst, etherbroadcastaddr, sizeof(edst)); | | 290 | (void)memcpy(edst, etherbroadcastaddr, sizeof(edst)); |
291 | else if (m->m_flags & M_MCAST) { | | 291 | else if (m->m_flags & M_MCAST) { |
292 | ETHER_MAP_IPV6_MULTICAST(&satocsin6(dst)->sin6_addr, | | 292 | ETHER_MAP_IPV6_MULTICAST(&satocsin6(dst)->sin6_addr, |
293 | edst); | | 293 | edst); |
294 | } else { | | 294 | } else { |
295 | error = nd6_resolve(ifp, rt, m, dst, edst, | | 295 | error = nd6_resolve(ifp, rt, m, dst, edst, |
296 | sizeof(edst)); | | 296 | sizeof(edst)); |
297 | if (error != 0) | | 297 | if (error != 0) |
298 | return error == EWOULDBLOCK ? 0 : error; | | 298 | return error == EWOULDBLOCK ? 0 : error; |
299 | } | | 299 | } |
300 | etype = htons(ETHERTYPE_IPV6); | | 300 | etype = htons(ETHERTYPE_IPV6); |
301 | break; | | 301 | break; |
302 | #endif | | 302 | #endif |
303 | #ifdef NETATALK | | 303 | #ifdef NETATALK |
304 | case AF_APPLETALK: { | | 304 | case AF_APPLETALK: { |
305 | struct ifaddr *ifa; | | 305 | struct ifaddr *ifa; |
306 | int s; | | 306 | int s; |
307 | | | 307 | |
308 | KERNEL_LOCK(1, NULL); | | 308 | KERNEL_LOCK(1, NULL); |
309 | if (!aarpresolve(ifp, m, (const struct sockaddr_at *)dst, edst)) { | | 309 | if (!aarpresolve(ifp, m, (const struct sockaddr_at *)dst, edst)) { |
310 | #ifdef NETATALKDEBUG | | 310 | #ifdef NETATALKDEBUG |
311 | printf("aarpresolv failed\n"); | | 311 | printf("aarpresolv failed\n"); |
312 | #endif /* NETATALKDEBUG */ | | 312 | #endif /* NETATALKDEBUG */ |
313 | KERNEL_UNLOCK_ONE(NULL); | | 313 | KERNEL_UNLOCK_ONE(NULL); |
314 | return (0); | | 314 | return (0); |
315 | } | | 315 | } |
316 | /* | | 316 | /* |
317 | * ifaddr is the first thing in at_ifaddr | | 317 | * ifaddr is the first thing in at_ifaddr |
318 | */ | | 318 | */ |
319 | s = pserialize_read_enter(); | | 319 | s = pserialize_read_enter(); |
320 | ifa = at_ifawithnet((const struct sockaddr_at *)dst, ifp); | | 320 | ifa = at_ifawithnet((const struct sockaddr_at *)dst, ifp); |
321 | if (ifa == NULL) { | | 321 | if (ifa == NULL) { |
322 | pserialize_read_exit(s); | | 322 | pserialize_read_exit(s); |
323 | KERNEL_UNLOCK_ONE(NULL); | | 323 | KERNEL_UNLOCK_ONE(NULL); |
324 | goto bad; | | 324 | goto bad; |
325 | } | | 325 | } |
326 | aa = (struct at_ifaddr *)ifa; | | 326 | aa = (struct at_ifaddr *)ifa; |
327 | | | 327 | |
328 | /* | | 328 | /* |
329 | * In the phase 2 case, we need to prepend an mbuf for the | | 329 | * In the phase 2 case, we need to prepend an mbuf for the |
330 | * llc header. Since we must preserve the value of m, | | 330 | * llc header. Since we must preserve the value of m, |
331 | * which is passed to us by value, we m_copy() the first | | 331 | * which is passed to us by value, we m_copy() the first |
332 | * mbuf, and use it for our llc header. | | 332 | * mbuf, and use it for our llc header. |
333 | */ | | 333 | */ |
334 | if (aa->aa_flags & AFA_PHASE2) { | | 334 | if (aa->aa_flags & AFA_PHASE2) { |
335 | struct llc llc; | | 335 | struct llc llc; |
336 | | | 336 | |
337 | M_PREPEND(m, sizeof(struct llc), M_DONTWAIT); | | 337 | M_PREPEND(m, sizeof(struct llc), M_DONTWAIT); |
338 | llc.llc_dsap = llc.llc_ssap = LLC_SNAP_LSAP; | | 338 | llc.llc_dsap = llc.llc_ssap = LLC_SNAP_LSAP; |
339 | llc.llc_control = LLC_UI; | | 339 | llc.llc_control = LLC_UI; |
340 | memcpy(llc.llc_snap_org_code, at_org_code, | | 340 | memcpy(llc.llc_snap_org_code, at_org_code, |
341 | sizeof(llc.llc_snap_org_code)); | | 341 | sizeof(llc.llc_snap_org_code)); |
342 | llc.llc_snap_ether_type = htons(ETHERTYPE_ATALK); | | 342 | llc.llc_snap_ether_type = htons(ETHERTYPE_ATALK); |
343 | memcpy(mtod(m, void *), &llc, sizeof(struct llc)); | | 343 | memcpy(mtod(m, void *), &llc, sizeof(struct llc)); |
344 | } else { | | 344 | } else { |
345 | etype = htons(ETHERTYPE_ATALK); | | 345 | etype = htons(ETHERTYPE_ATALK); |
346 | } | | 346 | } |
347 | pserialize_read_exit(s); | | 347 | pserialize_read_exit(s); |
348 | KERNEL_UNLOCK_ONE(NULL); | | 348 | KERNEL_UNLOCK_ONE(NULL); |
349 | break; | | 349 | break; |
350 | } | | 350 | } |
351 | #endif /* NETATALK */ | | 351 | #endif /* NETATALK */ |
352 | case pseudo_AF_HDRCMPLT: | | 352 | case pseudo_AF_HDRCMPLT: |
353 | hdrcmplt = 1; | | 353 | hdrcmplt = 1; |
354 | memcpy(esrc, | | 354 | memcpy(esrc, |
355 | ((const struct ether_header *)dst->sa_data)->ether_shost, | | 355 | ((const struct ether_header *)dst->sa_data)->ether_shost, |
356 | sizeof(esrc)); | | 356 | sizeof(esrc)); |
357 | /* FALLTHROUGH */ | | 357 | /* FALLTHROUGH */ |
358 | | | 358 | |
359 | case AF_UNSPEC: | | 359 | case AF_UNSPEC: |
360 | memcpy(edst, | | 360 | memcpy(edst, |
361 | ((const struct ether_header *)dst->sa_data)->ether_dhost, | | 361 | ((const struct ether_header *)dst->sa_data)->ether_dhost, |
362 | sizeof(edst)); | | 362 | sizeof(edst)); |
363 | /* AF_UNSPEC doesn't swap the byte order of the ether_type. */ | | 363 | /* AF_UNSPEC doesn't swap the byte order of the ether_type. */ |
364 | etype = ((const struct ether_header *)dst->sa_data)->ether_type; | | 364 | etype = ((const struct ether_header *)dst->sa_data)->ether_type; |
365 | break; | | 365 | break; |
366 | | | 366 | |
367 | default: | | 367 | default: |
368 | printf("%s: can't handle af%d\n", ifp->if_xname, | | 368 | printf("%s: can't handle af%d\n", ifp->if_xname, |
369 | dst->sa_family); | | 369 | dst->sa_family); |
370 | senderr(EAFNOSUPPORT); | | 370 | senderr(EAFNOSUPPORT); |
371 | } | | 371 | } |
372 | | | 372 | |
373 | #ifdef MPLS | | 373 | #ifdef MPLS |
374 | KERNEL_LOCK(1, NULL); | | 374 | KERNEL_LOCK(1, NULL); |
375 | { | | 375 | { |
376 | struct m_tag *mtag; | | 376 | struct m_tag *mtag; |
377 | mtag = m_tag_find(m, PACKET_TAG_MPLS, NULL); | | 377 | mtag = m_tag_find(m, PACKET_TAG_MPLS, NULL); |
378 | if (mtag != NULL) { | | 378 | if (mtag != NULL) { |
379 | /* Having the tag itself indicates it's MPLS */ | | 379 | /* Having the tag itself indicates it's MPLS */ |
380 | etype = htons(ETHERTYPE_MPLS); | | 380 | etype = htons(ETHERTYPE_MPLS); |
381 | m_tag_delete(m, mtag); | | 381 | m_tag_delete(m, mtag); |
382 | } | | 382 | } |
383 | } | | 383 | } |
384 | KERNEL_UNLOCK_ONE(NULL); | | 384 | KERNEL_UNLOCK_ONE(NULL); |
385 | #endif | | 385 | #endif |
386 | | | 386 | |
387 | if (mcopy) | | 387 | if (mcopy) |
388 | (void)looutput(ifp, mcopy, dst, rt); | | 388 | (void)looutput(ifp, mcopy, dst, rt); |
389 | | | 389 | |
390 | /* If no ether type is set, this must be a 802.2 formatted packet. | | 390 | /* If no ether type is set, this must be a 802.2 formatted packet. |
391 | */ | | 391 | */ |
392 | if (etype == 0) | | 392 | if (etype == 0) |
393 | etype = htons(m->m_pkthdr.len); | | 393 | etype = htons(m->m_pkthdr.len); |
394 | /* | | 394 | /* |
395 | * Add local net header. If no space in first mbuf, | | 395 | * Add local net header. If no space in first mbuf, |
396 | * allocate another. | | 396 | * allocate another. |
397 | */ | | 397 | */ |
398 | M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT); | | 398 | M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT); |
399 | if (m == 0) | | 399 | if (m == 0) |
400 | senderr(ENOBUFS); | | 400 | senderr(ENOBUFS); |
401 | eh = mtod(m, struct ether_header *); | | 401 | eh = mtod(m, struct ether_header *); |
402 | /* Note: etype is already in network byte order. */ | | 402 | /* Note: etype is already in network byte order. */ |
403 | (void)memcpy(&eh->ether_type, &etype, sizeof(eh->ether_type)); | | 403 | (void)memcpy(&eh->ether_type, &etype, sizeof(eh->ether_type)); |
404 | memcpy(eh->ether_dhost, edst, sizeof(edst)); | | 404 | memcpy(eh->ether_dhost, edst, sizeof(edst)); |
405 | if (hdrcmplt) | | 405 | if (hdrcmplt) |
406 | memcpy(eh->ether_shost, esrc, sizeof(eh->ether_shost)); | | 406 | memcpy(eh->ether_shost, esrc, sizeof(eh->ether_shost)); |
407 | else | | 407 | else |
408 | memcpy(eh->ether_shost, CLLADDR(ifp->if_sadl), | | 408 | memcpy(eh->ether_shost, CLLADDR(ifp->if_sadl), |
409 | sizeof(eh->ether_shost)); | | 409 | sizeof(eh->ether_shost)); |
410 | | | 410 | |
411 | #if NCARP > 0 | | 411 | #if NCARP > 0 |
412 | if (ifp0 != ifp && ifp0->if_type == IFT_CARP) { | | 412 | if (ifp0 != ifp && ifp0->if_type == IFT_CARP) { |
413 | memcpy(eh->ether_shost, CLLADDR(ifp0->if_sadl), | | 413 | memcpy(eh->ether_shost, CLLADDR(ifp0->if_sadl), |
414 | sizeof(eh->ether_shost)); | | 414 | sizeof(eh->ether_shost)); |
415 | } | | 415 | } |
416 | #endif /* NCARP > 0 */ | | 416 | #endif /* NCARP > 0 */ |
417 | | | 417 | |
418 | if ((error = pfil_run_hooks(ifp->if_pfil, &m, ifp, PFIL_OUT)) != 0) | | 418 | if ((error = pfil_run_hooks(ifp->if_pfil, &m, ifp, PFIL_OUT)) != 0) |
419 | return (error); | | 419 | return (error); |
420 | if (m == NULL) | | 420 | if (m == NULL) |
421 | return (0); | | 421 | return (0); |
422 | | | 422 | |
423 | #if NBRIDGE > 0 | | 423 | #if NBRIDGE > 0 |
424 | /* | | 424 | /* |
425 | * Bridges require special output handling. | | 425 | * Bridges require special output handling. |
426 | */ | | 426 | */ |
427 | if (ifp->if_bridge) | | 427 | if (ifp->if_bridge) |
428 | return (bridge_output(ifp, m, NULL, NULL)); | | 428 | return (bridge_output(ifp, m, NULL, NULL)); |
429 | #endif | | 429 | #endif |
430 | | | 430 | |
431 | #if NCARP > 0 | | 431 | #if NCARP > 0 |
432 | if (ifp != ifp0) | | 432 | if (ifp != ifp0) |
433 | ifp0->if_obytes += m->m_pkthdr.len + ETHER_HDR_LEN; | | 433 | ifp0->if_obytes += m->m_pkthdr.len + ETHER_HDR_LEN; |
434 | #endif /* NCARP > 0 */ | | 434 | #endif /* NCARP > 0 */ |
435 | | | 435 | |
436 | #ifdef ALTQ | | 436 | #ifdef ALTQ |
437 | KERNEL_LOCK(1, NULL); | | 437 | KERNEL_LOCK(1, NULL); |
438 | /* | | 438 | /* |
439 | * If ALTQ is enabled on the parent interface, do | | 439 | * If ALTQ is enabled on the parent interface, do |
440 | * classification; the queueing discipline might not | | 440 | * classification; the queueing discipline might not |
441 | * require classification, but might require the | | 441 | * require classification, but might require the |
442 | * address family/header pointer in the pktattr. | | 442 | * address family/header pointer in the pktattr. |
443 | */ | | 443 | */ |
444 | if (ALTQ_IS_ENABLED(&ifp->if_snd)) | | 444 | if (ALTQ_IS_ENABLED(&ifp->if_snd)) |
445 | altq_etherclassify(&ifp->if_snd, m); | | 445 | altq_etherclassify(&ifp->if_snd, m); |
446 | KERNEL_UNLOCK_ONE(NULL); | | 446 | KERNEL_UNLOCK_ONE(NULL); |
447 | #endif | | 447 | #endif |
448 | return ifq_enqueue(ifp, m); | | 448 | return ifq_enqueue(ifp, m); |
449 | | | 449 | |
450 | bad: | | 450 | bad: |
451 | if (m) | | 451 | if (m) |
452 | m_freem(m); | | 452 | m_freem(m); |
453 | return (error); | | 453 | return (error); |
454 | } | | 454 | } |
455 | | | 455 | |
456 | #ifdef ALTQ | | 456 | #ifdef ALTQ |
457 | /* | | 457 | /* |
458 | * This routine is a slight hack to allow a packet to be classified | | 458 | * This routine is a slight hack to allow a packet to be classified |
459 | * if the Ethernet headers are present. It will go away when ALTQ's | | 459 | * if the Ethernet headers are present. It will go away when ALTQ's |
460 | * classification engine understands link headers. | | 460 | * classification engine understands link headers. |
461 | */ | | 461 | */ |
462 | void | | 462 | void |
463 | altq_etherclassify(struct ifaltq *ifq, struct mbuf *m) | | 463 | altq_etherclassify(struct ifaltq *ifq, struct mbuf *m) |
464 | { | | 464 | { |
465 | struct ether_header *eh; | | 465 | struct ether_header *eh; |
466 | uint16_t ether_type; | | 466 | uint16_t ether_type; |
467 | int hlen, af, hdrsize; | | 467 | int hlen, af, hdrsize; |
468 | void *hdr; | | 468 | void *hdr; |
469 | | | 469 | |
470 | hlen = ETHER_HDR_LEN; | | 470 | hlen = ETHER_HDR_LEN; |
471 | eh = mtod(m, struct ether_header *); | | 471 | eh = mtod(m, struct ether_header *); |
472 | | | 472 | |
473 | ether_type = htons(eh->ether_type); | | 473 | ether_type = htons(eh->ether_type); |
474 | | | 474 | |
475 | if (ether_type < ETHERMTU) { | | 475 | if (ether_type < ETHERMTU) { |
476 | /* LLC/SNAP */ | | 476 | /* LLC/SNAP */ |
477 | struct llc *llc = (struct llc *)(eh + 1); | | 477 | struct llc *llc = (struct llc *)(eh + 1); |
478 | hlen += 8; | | 478 | hlen += 8; |
479 | | | 479 | |
480 | if (m->m_len < hlen || | | 480 | if (m->m_len < hlen || |
481 | llc->llc_dsap != LLC_SNAP_LSAP || | | 481 | llc->llc_dsap != LLC_SNAP_LSAP || |
482 | llc->llc_ssap != LLC_SNAP_LSAP || | | 482 | llc->llc_ssap != LLC_SNAP_LSAP || |
483 | llc->llc_control != LLC_UI) { | | 483 | llc->llc_control != LLC_UI) { |
484 | /* Not SNAP. */ | | 484 | /* Not SNAP. */ |
485 | goto bad; | | 485 | goto bad; |
486 | } | | 486 | } |
487 | | | 487 | |
488 | ether_type = htons(llc->llc_un.type_snap.ether_type); | | 488 | ether_type = htons(llc->llc_un.type_snap.ether_type); |
489 | } | | 489 | } |
490 | | | 490 | |
491 | switch (ether_type) { | | 491 | switch (ether_type) { |
492 | case ETHERTYPE_IP: | | 492 | case ETHERTYPE_IP: |
493 | af = AF_INET; | | 493 | af = AF_INET; |
494 | hdrsize = 20; /* sizeof(struct ip) */ | | 494 | hdrsize = 20; /* sizeof(struct ip) */ |
495 | break; | | 495 | break; |
496 | | | 496 | |
497 | case ETHERTYPE_IPV6: | | 497 | case ETHERTYPE_IPV6: |
498 | af = AF_INET6; | | 498 | af = AF_INET6; |
499 | hdrsize = 40; /* sizeof(struct ip6_hdr) */ | | 499 | hdrsize = 40; /* sizeof(struct ip6_hdr) */ |
500 | break; | | 500 | break; |
501 | | | 501 | |
502 | default: | | 502 | default: |
503 | af = AF_UNSPEC; | | 503 | af = AF_UNSPEC; |
504 | hdrsize = 0; | | 504 | hdrsize = 0; |
505 | break; | | 505 | break; |
506 | } | | 506 | } |
507 | | | 507 | |
508 | while (m->m_len <= hlen) { | | 508 | while (m->m_len <= hlen) { |
509 | hlen -= m->m_len; | | 509 | hlen -= m->m_len; |
510 | m = m->m_next; | | 510 | m = m->m_next; |
511 | } | | 511 | } |
512 | if (m->m_len < (hlen + hdrsize)) { | | 512 | if (m->m_len < (hlen + hdrsize)) { |
513 | /* | | 513 | /* |
514 | * protocol header not in a single mbuf. | | 514 | * protocol header not in a single mbuf. |
515 | * We can't cope with this situation right | | 515 | * We can't cope with this situation right |
516 | * now (but it shouldn't ever happen, really, anyhow). | | 516 | * now (but it shouldn't ever happen, really, anyhow). |
517 | */ | | 517 | */ |
518 | #ifdef DEBUG | | 518 | #ifdef DEBUG |
519 | printf("altq_etherclassify: headers span multiple mbufs: " | | 519 | printf("altq_etherclassify: headers span multiple mbufs: " |
520 | "%d < %d\n", m->m_len, (hlen + hdrsize)); | | 520 | "%d < %d\n", m->m_len, (hlen + hdrsize)); |
521 | #endif | | 521 | #endif |
522 | goto bad; | | 522 | goto bad; |
523 | } | | 523 | } |
524 | | | 524 | |
525 | m->m_data += hlen; | | 525 | m->m_data += hlen; |
526 | m->m_len -= hlen; | | 526 | m->m_len -= hlen; |
527 | | | 527 | |
528 | hdr = mtod(m, void *); | | 528 | hdr = mtod(m, void *); |
529 | | | 529 | |
530 | if (ALTQ_NEEDS_CLASSIFY(ifq)) | | 530 | if (ALTQ_NEEDS_CLASSIFY(ifq)) |
531 | m->m_pkthdr.pattr_class = | | 531 | m->m_pkthdr.pattr_class = |
532 | (*ifq->altq_classify)(ifq->altq_clfier, m, af); | | 532 | (*ifq->altq_classify)(ifq->altq_clfier, m, af); |
533 | m->m_pkthdr.pattr_af = af; | | 533 | m->m_pkthdr.pattr_af = af; |
534 | m->m_pkthdr.pattr_hdr = hdr; | | 534 | m->m_pkthdr.pattr_hdr = hdr; |
535 | | | 535 | |
536 | m->m_data -= hlen; | | 536 | m->m_data -= hlen; |
537 | m->m_len += hlen; | | 537 | m->m_len += hlen; |
538 | | | 538 | |
539 | return; | | 539 | return; |
540 | | | 540 | |
541 | bad: | | 541 | bad: |
542 | m->m_pkthdr.pattr_class = NULL; | | 542 | m->m_pkthdr.pattr_class = NULL; |
543 | m->m_pkthdr.pattr_hdr = NULL; | | 543 | m->m_pkthdr.pattr_hdr = NULL; |
544 | m->m_pkthdr.pattr_af = AF_UNSPEC; | | 544 | m->m_pkthdr.pattr_af = AF_UNSPEC; |
545 | } | | 545 | } |
546 | #endif /* ALTQ */ | | 546 | #endif /* ALTQ */ |
547 | | | 547 | |
548 | /* | | 548 | /* |
549 | * Process a received Ethernet packet; | | 549 | * Process a received Ethernet packet; |
550 | * the packet is in the mbuf chain m with | | 550 | * the packet is in the mbuf chain m with |
551 | * the ether header. | | 551 | * the ether header. |
552 | */ | | 552 | */ |
553 | void | | 553 | void |
554 | ether_input(struct ifnet *ifp, struct mbuf *m) | | 554 | ether_input(struct ifnet *ifp, struct mbuf *m) |
555 | { | | 555 | { |
556 | struct ethercom *ec = (struct ethercom *) ifp; | | 556 | struct ethercom *ec = (struct ethercom *) ifp; |
557 | pktqueue_t *pktq = NULL; | | 557 | pktqueue_t *pktq = NULL; |
558 | struct ifqueue *inq = NULL; | | 558 | struct ifqueue *inq = NULL; |
559 | uint16_t etype; | | 559 | uint16_t etype; |
560 | struct ether_header *eh; | | 560 | struct ether_header *eh; |
561 | size_t ehlen; | | 561 | size_t ehlen; |
562 | static int earlypkts; | | 562 | static int earlypkts; |
563 | int isr = 0; | | 563 | int isr = 0; |
564 | #if defined (LLC) || defined(NETATALK) | | 564 | #if defined (LLC) || defined(NETATALK) |
565 | struct llc *l; | | 565 | struct llc *l; |
566 | #endif | | 566 | #endif |
567 | | | 567 | |
568 | KASSERT(!cpu_intr_p()); | | 568 | KASSERT(!cpu_intr_p()); |
569 | | | 569 | |
570 | if ((ifp->if_flags & IFF_UP) == 0) { | | 570 | if ((ifp->if_flags & IFF_UP) == 0) { |
571 | m_freem(m); | | 571 | m_freem(m); |
572 | return; | | 572 | return; |
573 | } | | 573 | } |
574 | | | 574 | |
575 | #ifdef MBUFTRACE | | 575 | #ifdef MBUFTRACE |
576 | m_claimm(m, &ec->ec_rx_mowner); | | 576 | m_claimm(m, &ec->ec_rx_mowner); |
577 | #endif | | 577 | #endif |
578 | eh = mtod(m, struct ether_header *); | | 578 | eh = mtod(m, struct ether_header *); |
579 | etype = ntohs(eh->ether_type); | | 579 | etype = ntohs(eh->ether_type); |
580 | ehlen = sizeof(*eh); | | 580 | ehlen = sizeof(*eh); |
581 | | | 581 | |
582 | if(__predict_false(earlypkts < 100 || !rnd_initial_entropy)) { | | 582 | if (__predict_false(earlypkts < 100 || !rnd_initial_entropy)) { |
583 | rnd_add_data(NULL, eh, ehlen, 0); | | 583 | rnd_add_data(NULL, eh, ehlen, 0); |
584 | earlypkts++; | | 584 | earlypkts++; |
585 | } | | 585 | } |
586 | | | 586 | |
587 | /* | | 587 | /* |
588 | * Determine if the packet is within its size limits. | | 588 | * Determine if the packet is within its size limits. |
589 | */ | | 589 | */ |
590 | if (etype != ETHERTYPE_MPLS && m->m_pkthdr.len > | | 590 | if (etype != ETHERTYPE_MPLS && m->m_pkthdr.len > |
591 | ETHER_MAX_FRAME(ifp, etype, m->m_flags & M_HASFCS)) { | | 591 | ETHER_MAX_FRAME(ifp, etype, m->m_flags & M_HASFCS)) { |
592 | mutex_enter(&bigpktpps_lock); | | 592 | mutex_enter(&bigpktpps_lock); |
593 | if (ppsratecheck(&bigpktppslim_last, &bigpktpps_count, | | 593 | if (ppsratecheck(&bigpktppslim_last, &bigpktpps_count, |
594 | bigpktppslim)) { | | 594 | bigpktppslim)) { |
595 | printf("%s: discarding oversize frame (len=%d)\n", | | 595 | printf("%s: discarding oversize frame (len=%d)\n", |
596 | ifp->if_xname, m->m_pkthdr.len); | | 596 | ifp->if_xname, m->m_pkthdr.len); |
597 | } | | 597 | } |
598 | mutex_exit(&bigpktpps_lock); | | 598 | mutex_exit(&bigpktpps_lock); |
599 | m_freem(m); | | 599 | m_freem(m); |
600 | return; | | 600 | return; |
601 | } | | 601 | } |
602 | | | 602 | |
603 | if (ETHER_IS_MULTICAST(eh->ether_dhost)) { | | 603 | if (ETHER_IS_MULTICAST(eh->ether_dhost)) { |
604 | /* | | 604 | /* |
605 | * If this is not a simplex interface, drop the packet | | 605 | * If this is not a simplex interface, drop the packet |
606 | * if it came from us. | | 606 | * if it came from us. |
607 | */ | | 607 | */ |
608 | if ((ifp->if_flags & IFF_SIMPLEX) == 0 && | | 608 | if ((ifp->if_flags & IFF_SIMPLEX) == 0 && |
609 | memcmp(CLLADDR(ifp->if_sadl), eh->ether_shost, | | 609 | memcmp(CLLADDR(ifp->if_sadl), eh->ether_shost, |
610 | ETHER_ADDR_LEN) == 0) { | | 610 | ETHER_ADDR_LEN) == 0) { |
611 | m_freem(m); | | 611 | m_freem(m); |
612 | return; | | 612 | return; |
613 | } | | 613 | } |
614 | | | 614 | |
615 | if (memcmp(etherbroadcastaddr, | | 615 | if (memcmp(etherbroadcastaddr, |
616 | eh->ether_dhost, ETHER_ADDR_LEN) == 0) | | 616 | eh->ether_dhost, ETHER_ADDR_LEN) == 0) |
617 | m->m_flags |= M_BCAST; | | 617 | m->m_flags |= M_BCAST; |
618 | else | | 618 | else |
619 | m->m_flags |= M_MCAST; | | 619 | m->m_flags |= M_MCAST; |
620 | ifp->if_imcasts++; | | 620 | ifp->if_imcasts++; |
621 | } | | 621 | } |
622 | | | 622 | |
623 | /* If the CRC is still on the packet, trim it off. */ | | 623 | /* If the CRC is still on the packet, trim it off. */ |
624 | if (m->m_flags & M_HASFCS) { | | 624 | if (m->m_flags & M_HASFCS) { |
625 | m_adj(m, -ETHER_CRC_LEN); | | 625 | m_adj(m, -ETHER_CRC_LEN); |
626 | m->m_flags &= ~M_HASFCS; | | 626 | m->m_flags &= ~M_HASFCS; |
627 | } | | 627 | } |
628 | | | 628 | |
629 | ifp->if_ibytes += m->m_pkthdr.len; | | 629 | ifp->if_ibytes += m->m_pkthdr.len; |
630 | | | 630 | |
631 | #if NCARP > 0 | | 631 | #if NCARP > 0 |
632 | if (__predict_false(ifp->if_carp && ifp->if_type != IFT_CARP)) { | | 632 | if (__predict_false(ifp->if_carp && ifp->if_type != IFT_CARP)) { |
633 | /* | | 633 | /* |
634 | * clear M_PROMISC, in case the packets comes from a | | 634 | * clear M_PROMISC, in case the packets comes from a |
635 | * vlan | | 635 | * vlan |
636 | */ | | 636 | */ |
637 | m->m_flags &= ~M_PROMISC; | | 637 | m->m_flags &= ~M_PROMISC; |
638 | if (carp_input(m, (uint8_t *)&eh->ether_shost, | | 638 | if (carp_input(m, (uint8_t *)&eh->ether_shost, |
639 | (uint8_t *)&eh->ether_dhost, eh->ether_type) == 0) | | 639 | (uint8_t *)&eh->ether_dhost, eh->ether_type) == 0) |
640 | return; | | 640 | return; |
641 | } | | 641 | } |
642 | #endif /* NCARP > 0 */ | | 642 | #endif /* NCARP > 0 */ |
| | | 643 | |
643 | if ((m->m_flags & (M_BCAST | M_MCAST | M_PROMISC)) == 0 && | | 644 | if ((m->m_flags & (M_BCAST | M_MCAST | M_PROMISC)) == 0 && |
644 | (ifp->if_flags & IFF_PROMISC) != 0 && | | 645 | (ifp->if_flags & IFF_PROMISC) != 0 && |
645 | memcmp(CLLADDR(ifp->if_sadl), eh->ether_dhost, | | 646 | memcmp(CLLADDR(ifp->if_sadl), eh->ether_dhost, |
646 | ETHER_ADDR_LEN) != 0) { | | 647 | ETHER_ADDR_LEN) != 0) { |
647 | m->m_flags |= M_PROMISC; | | 648 | m->m_flags |= M_PROMISC; |
648 | } | | 649 | } |
649 | | | 650 | |
650 | if ((m->m_flags & M_PROMISC) == 0) { | | 651 | if ((m->m_flags & M_PROMISC) == 0) { |
651 | if (pfil_run_hooks(ifp->if_pfil, &m, ifp, PFIL_IN) != 0) | | 652 | if (pfil_run_hooks(ifp->if_pfil, &m, ifp, PFIL_IN) != 0) |
652 | return; | | 653 | return; |
653 | if (m == NULL) | | 654 | if (m == NULL) |
654 | return; | | 655 | return; |
655 | | | 656 | |
656 | eh = mtod(m, struct ether_header *); | | 657 | eh = mtod(m, struct ether_header *); |
657 | etype = ntohs(eh->ether_type); | | 658 | etype = ntohs(eh->ether_type); |
658 | ehlen = sizeof(*eh); | | 659 | ehlen = sizeof(*eh); |
659 | } | | 660 | } |
660 | | | 661 | |
661 | #if NAGR > 0 | | 662 | #if NAGR > 0 |
662 | if (ifp->if_agrprivate && | | 663 | if (ifp->if_agrprivate && |
663 | __predict_true(etype != ETHERTYPE_SLOWPROTOCOLS)) { | | 664 | __predict_true(etype != ETHERTYPE_SLOWPROTOCOLS)) { |
664 | m->m_flags &= ~M_PROMISC; | | 665 | m->m_flags &= ~M_PROMISC; |
665 | agr_input(ifp, m); | | 666 | agr_input(ifp, m); |
666 | return; | | 667 | return; |
667 | } | | 668 | } |
668 | #endif /* NAGR > 0 */ | | 669 | #endif /* NAGR > 0 */ |
669 | | | 670 | |
670 | /* | | 671 | /* |
671 | * If VLANs are configured on the interface, check to | | 672 | * If VLANs are configured on the interface, check to |
672 | * see if the device performed the decapsulation and | | 673 | * see if the device performed the decapsulation and |
673 | * provided us with the tag. | | 674 | * provided us with the tag. |
674 | */ | | 675 | */ |
675 | if (ec->ec_nvlans && vlan_has_tag(m)) { | | 676 | if (ec->ec_nvlans && vlan_has_tag(m)) { |
676 | #if NVLAN > 0 | | 677 | #if NVLAN > 0 |
677 | /* | | 678 | /* |
678 | * vlan_input() will either recursively call ether_input() | | 679 | * vlan_input() will either recursively call ether_input() |
679 | * or drop the packet. | | 680 | * or drop the packet. |
680 | */ | | 681 | */ |
681 | vlan_input(ifp, m); | | 682 | vlan_input(ifp, m); |
682 | #else | | 683 | #else |
683 | m_freem(m); | | 684 | m_freem(m); |
684 | #endif | | 685 | #endif |
685 | return; | | 686 | return; |
686 | } | | 687 | } |
687 | | | 688 | |
688 | /* | | 689 | /* |
689 | * Handle protocols that expect to have the Ethernet header | | 690 | * Handle protocols that expect to have the Ethernet header |
690 | * (and possibly FCS) intact. | | 691 | * (and possibly FCS) intact. |
691 | */ | | 692 | */ |
692 | switch (etype) { | | 693 | switch (etype) { |
693 | case ETHERTYPE_VLAN: { | | 694 | case ETHERTYPE_VLAN: { |
694 | struct ether_vlan_header *evl = (void *)eh; | | 695 | struct ether_vlan_header *evl = (void *)eh; |
695 | /* | | 696 | /* |
696 | * If there is a tag of 0, then the VLAN header was probably | | 697 | * If there is a tag of 0, then the VLAN header was probably |
697 | * just being used to store the priority. Extract the ether | | 698 | * just being used to store the priority. Extract the ether |
698 | * type, and if IP or IPV6, let them deal with it. | | 699 | * type, and if IP or IPV6, let them deal with it. |
699 | */ | | 700 | */ |
700 | if (m->m_len <= sizeof(*evl) | | 701 | if (m->m_len <= sizeof(*evl) |
701 | && EVL_VLANOFTAG(evl->evl_tag) == 0) { | | 702 | && EVL_VLANOFTAG(evl->evl_tag) == 0) { |
702 | etype = ntohs(evl->evl_proto); | | 703 | etype = ntohs(evl->evl_proto); |
703 | ehlen = sizeof(*evl); | | 704 | ehlen = sizeof(*evl); |
704 | if ((m->m_flags & M_PROMISC) == 0 | | 705 | if ((m->m_flags & M_PROMISC) == 0 |
705 | && (etype == ETHERTYPE_IP | | 706 | && (etype == ETHERTYPE_IP |
706 | || etype == ETHERTYPE_IPV6)) | | 707 | || etype == ETHERTYPE_IPV6)) |
707 | break; | | 708 | break; |
708 | } | | 709 | } |
709 | #if NVLAN > 0 | | 710 | #if NVLAN > 0 |
710 | /* | | 711 | /* |
711 | * vlan_input() will either recursively call ether_input() | | 712 | * vlan_input() will either recursively call ether_input() |
712 | * or drop the packet. | | 713 | * or drop the packet. |
713 | */ | | 714 | */ |
714 | if (((struct ethercom *)ifp)->ec_nvlans != 0) | | 715 | if (((struct ethercom *)ifp)->ec_nvlans != 0) |
715 | vlan_input(ifp, m); | | 716 | vlan_input(ifp, m); |
716 | else | | 717 | else |
717 | #endif /* NVLAN > 0 */ | | 718 | #endif /* NVLAN > 0 */ |
718 | m_freem(m); | | 719 | m_freem(m); |
719 | return; | | 720 | return; |
720 | } | | 721 | } |
721 | #if NPPPOE > 0 | | 722 | #if NPPPOE > 0 |
722 | case ETHERTYPE_PPPOEDISC: | | 723 | case ETHERTYPE_PPPOEDISC: |
723 | pppoedisc_input(ifp, m); | | 724 | pppoedisc_input(ifp, m); |
724 | return; | | 725 | return; |
725 | case ETHERTYPE_PPPOE: | | 726 | case ETHERTYPE_PPPOE: |
726 | pppoe_input(ifp, m); | | 727 | pppoe_input(ifp, m); |
727 | return; | | 728 | return; |
728 | #endif /* NPPPOE > 0 */ | | 729 | #endif /* NPPPOE > 0 */ |
729 | case ETHERTYPE_SLOWPROTOCOLS: { | | 730 | case ETHERTYPE_SLOWPROTOCOLS: { |
730 | uint8_t subtype; | | 731 | uint8_t subtype; |
731 | | | 732 | |
732 | #if defined(DIAGNOSTIC) | | 733 | #if defined(DIAGNOSTIC) |
733 | if (m->m_pkthdr.len < sizeof(*eh) + sizeof(subtype)) { | | 734 | if (m->m_pkthdr.len < sizeof(*eh) + sizeof(subtype)) { |
734 | panic("ether_input: too short slow protocol packet"); | | 735 | panic("ether_input: too short slow protocol packet"); |
735 | } | | 736 | } |
736 | #endif | | 737 | #endif |
737 | m_copydata(m, sizeof(*eh), sizeof(subtype), &subtype); | | 738 | m_copydata(m, sizeof(*eh), sizeof(subtype), &subtype); |
738 | switch (subtype) { | | 739 | switch (subtype) { |
739 | #if NAGR > 0 | | 740 | #if NAGR > 0 |
740 | case SLOWPROTOCOLS_SUBTYPE_LACP: | | 741 | case SLOWPROTOCOLS_SUBTYPE_LACP: |
741 | if (ifp->if_agrprivate) { | | 742 | if (ifp->if_agrprivate) { |
742 | ieee8023ad_lacp_input(ifp, m); | | 743 | ieee8023ad_lacp_input(ifp, m); |
743 | return; | | 744 | return; |
744 | } | | 745 | } |
745 | break; | | 746 | break; |
746 | | | 747 | |
747 | case SLOWPROTOCOLS_SUBTYPE_MARKER: | | 748 | case SLOWPROTOCOLS_SUBTYPE_MARKER: |
748 | if (ifp->if_agrprivate) { | | 749 | if (ifp->if_agrprivate) { |
749 | ieee8023ad_marker_input(ifp, m); | | 750 | ieee8023ad_marker_input(ifp, m); |
750 | return; | | 751 | return; |
751 | } | | 752 | } |
752 | break; | | 753 | break; |
753 | #endif /* NAGR > 0 */ | | 754 | #endif /* NAGR > 0 */ |
754 | default: | | 755 | default: |
755 | if (subtype == 0 || subtype > 10) { | | 756 | if (subtype == 0 || subtype > 10) { |
756 | /* illegal value */ | | 757 | /* illegal value */ |
757 | m_freem(m); | | 758 | m_freem(m); |
758 | return; | | 759 | return; |
759 | } | | 760 | } |
760 | /* unknown subtype */ | | 761 | /* unknown subtype */ |
761 | break; | | 762 | break; |
762 | } | | 763 | } |
763 | /* FALLTHROUGH */ | | 764 | /* FALLTHROUGH */ |
764 | } | | 765 | } |
765 | default: | | 766 | default: |
766 | if (m->m_flags & M_PROMISC) { | | 767 | if (m->m_flags & M_PROMISC) { |
767 | m_freem(m); | | 768 | m_freem(m); |
768 | return; | | 769 | return; |
769 | } | | 770 | } |
770 | } | | 771 | } |
771 | | | 772 | |
772 | /* If the CRC is still on the packet, trim it off. */ | | 773 | /* If the CRC is still on the packet, trim it off. */ |
773 | if (m->m_flags & M_HASFCS) { | | 774 | if (m->m_flags & M_HASFCS) { |
774 | m_adj(m, -ETHER_CRC_LEN); | | 775 | m_adj(m, -ETHER_CRC_LEN); |
775 | m->m_flags &= ~M_HASFCS; | | 776 | m->m_flags &= ~M_HASFCS; |
776 | } | | 777 | } |
777 | | | 778 | |
778 | if (etype > ETHERMTU + sizeof (struct ether_header)) { | | 779 | if (etype > ETHERMTU + sizeof (struct ether_header)) { |
779 | /* Strip off the Ethernet header. */ | | 780 | /* Strip off the Ethernet header. */ |
780 | m_adj(m, ehlen); | | 781 | m_adj(m, ehlen); |
781 | | | 782 | |
782 | switch (etype) { | | 783 | switch (etype) { |
783 | #ifdef INET | | 784 | #ifdef INET |
784 | case ETHERTYPE_IP: | | 785 | case ETHERTYPE_IP: |
785 | #ifdef GATEWAY | | 786 | #ifdef GATEWAY |
786 | if (ipflow_fastforward(m)) | | 787 | if (ipflow_fastforward(m)) |
787 | return; | | 788 | return; |
788 | #endif | | 789 | #endif |
789 | pktq = ip_pktq; | | 790 | pktq = ip_pktq; |
790 | break; | | 791 | break; |
791 | | | 792 | |
792 | case ETHERTYPE_ARP: | | 793 | case ETHERTYPE_ARP: |
793 | isr = NETISR_ARP; | | 794 | isr = NETISR_ARP; |
794 | inq = &arpintrq; | | 795 | inq = &arpintrq; |
795 | break; | | 796 | break; |
796 | | | 797 | |
797 | case ETHERTYPE_REVARP: | | 798 | case ETHERTYPE_REVARP: |
798 | revarpinput(m); /* XXX queue? */ | | 799 | revarpinput(m); /* XXX queue? */ |
799 | return; | | 800 | return; |
800 | #endif | | 801 | #endif |
801 | #ifdef INET6 | | 802 | #ifdef INET6 |
802 | case ETHERTYPE_IPV6: | | 803 | case ETHERTYPE_IPV6: |
803 | if (__predict_false(!in6_present)) { | | 804 | if (__predict_false(!in6_present)) { |
804 | m_freem(m); | | 805 | m_freem(m); |
805 | return; | | 806 | return; |
806 | } | | 807 | } |
807 | #ifdef GATEWAY | | 808 | #ifdef GATEWAY |
808 | if (ip6flow_fastforward(&m)) | | 809 | if (ip6flow_fastforward(&m)) |
809 | return; | | 810 | return; |
810 | #endif | | 811 | #endif |
811 | pktq = ip6_pktq; | | 812 | pktq = ip6_pktq; |
812 | break; | | 813 | break; |
813 | #endif | | 814 | #endif |
814 | #ifdef NETATALK | | 815 | #ifdef NETATALK |
815 | case ETHERTYPE_ATALK: | | 816 | case ETHERTYPE_ATALK: |
816 | isr = NETISR_ATALK; | | 817 | isr = NETISR_ATALK; |
817 | inq = &atintrq1; | | 818 | inq = &atintrq1; |
818 | break; | | 819 | break; |
819 | case ETHERTYPE_AARP: | | 820 | case ETHERTYPE_AARP: |
820 | /* probably this should be done with a NETISR as well */ | | 821 | /* probably this should be done with a NETISR as well */ |
821 | aarpinput(ifp, m); /* XXX */ | | 822 | aarpinput(ifp, m); /* XXX */ |
822 | return; | | 823 | return; |
823 | #endif /* NETATALK */ | | 824 | #endif /* NETATALK */ |
824 | #ifdef MPLS | | 825 | #ifdef MPLS |
825 | case ETHERTYPE_MPLS: | | 826 | case ETHERTYPE_MPLS: |
826 | isr = NETISR_MPLS; | | 827 | isr = NETISR_MPLS; |
827 | inq = &mplsintrq; | | 828 | inq = &mplsintrq; |
828 | break; | | 829 | break; |
829 | #endif | | 830 | #endif |
830 | default: | | 831 | default: |
831 | m_freem(m); | | 832 | m_freem(m); |
832 | return; | | 833 | return; |
833 | } | | 834 | } |
834 | } else { | | 835 | } else { |
835 | #if defined (LLC) || defined (NETATALK) | | 836 | #if defined (LLC) || defined (NETATALK) |
836 | if (m->m_len < ehlen + sizeof(struct llc)) { | | 837 | if (m->m_len < ehlen + sizeof(struct llc)) { |
837 | goto dropanyway; | | 838 | goto dropanyway; |
838 | } | | 839 | } |
839 | l = (struct llc *)(eh+1); | | 840 | l = (struct llc *)(eh+1); |
840 | switch (l->llc_dsap) { | | 841 | switch (l->llc_dsap) { |
841 | #ifdef NETATALK | | 842 | #ifdef NETATALK |
842 | case LLC_SNAP_LSAP: | | 843 | case LLC_SNAP_LSAP: |
843 | switch (l->llc_control) { | | 844 | switch (l->llc_control) { |
844 | case LLC_UI: | | 845 | case LLC_UI: |
845 | if (l->llc_ssap != LLC_SNAP_LSAP) { | | 846 | if (l->llc_ssap != LLC_SNAP_LSAP) { |
846 | goto dropanyway; | | 847 | goto dropanyway; |
847 | } | | 848 | } |
848 | | | 849 | |
849 | if (memcmp(&(l->llc_snap_org_code)[0], | | 850 | if (memcmp(&(l->llc_snap_org_code)[0], |
850 | at_org_code, sizeof(at_org_code)) == 0 && | | 851 | at_org_code, sizeof(at_org_code)) == 0 && |
851 | ntohs(l->llc_snap_ether_type) == | | 852 | ntohs(l->llc_snap_ether_type) == |
852 | ETHERTYPE_ATALK) { | | 853 | ETHERTYPE_ATALK) { |
853 | inq = &atintrq2; | | 854 | inq = &atintrq2; |
854 | m_adj(m, sizeof(struct ether_header) | | 855 | m_adj(m, sizeof(struct ether_header) |
855 | + sizeof(struct llc)); | | 856 | + sizeof(struct llc)); |
856 | isr = NETISR_ATALK; | | 857 | isr = NETISR_ATALK; |
857 | break; | | 858 | break; |
858 | } | | 859 | } |
859 | | | 860 | |
860 | if (memcmp(&(l->llc_snap_org_code)[0], | | 861 | if (memcmp(&(l->llc_snap_org_code)[0], |
861 | aarp_org_code, | | 862 | aarp_org_code, |
862 | sizeof(aarp_org_code)) == 0 && | | 863 | sizeof(aarp_org_code)) == 0 && |
863 | ntohs(l->llc_snap_ether_type) == | | 864 | ntohs(l->llc_snap_ether_type) == |
864 | ETHERTYPE_AARP) { | | 865 | ETHERTYPE_AARP) { |
865 | m_adj( m, sizeof(struct ether_header) | | 866 | m_adj( m, sizeof(struct ether_header) |
866 | + sizeof(struct llc)); | | 867 | + sizeof(struct llc)); |
867 | aarpinput(ifp, m); /* XXX */ | | 868 | aarpinput(ifp, m); /* XXX */ |
868 | return; | | 869 | return; |
869 | } | | 870 | } |
870 | | | 871 | |
871 | default: | | 872 | default: |
872 | goto dropanyway; | | 873 | goto dropanyway; |
873 | } | | 874 | } |
874 | break; | | 875 | break; |
875 | #endif | | 876 | #endif |
876 | dropanyway: | | 877 | dropanyway: |
877 | default: | | 878 | default: |
878 | m_freem(m); | | 879 | m_freem(m); |
879 | return; | | 880 | return; |
880 | } | | 881 | } |
881 | #else /* ISO || LLC || NETATALK*/ | | 882 | #else /* LLC || NETATALK */ |
882 | m_freem(m); | | 883 | m_freem(m); |
883 | return; | | 884 | return; |
884 | #endif /* ISO || LLC || NETATALK*/ | | 885 | #endif /* LLC || NETATALK */ |
885 | } | | 886 | } |
886 | | | 887 | |
887 | if (__predict_true(pktq)) { | | 888 | if (__predict_true(pktq)) { |
888 | #ifdef NET_MPSAFE | | 889 | #ifdef NET_MPSAFE |
889 | const u_int h = curcpu()->ci_index; | | 890 | const u_int h = curcpu()->ci_index; |
890 | #else | | 891 | #else |
891 | const uint32_t h = pktq_rps_hash(m); | | 892 | const uint32_t h = pktq_rps_hash(m); |
892 | #endif | | 893 | #endif |
893 | if (__predict_false(!pktq_enqueue(pktq, m, h))) { | | 894 | if (__predict_false(!pktq_enqueue(pktq, m, h))) { |
894 | m_freem(m); | | 895 | m_freem(m); |
895 | } | | 896 | } |
896 | return; | | 897 | return; |
897 | } | | 898 | } |
898 | | | 899 | |
899 | if (__predict_false(!inq)) { | | 900 | if (__predict_false(!inq)) { |
900 | /* Should not happen. */ | | 901 | /* Should not happen. */ |
901 | m_freem(m); | | 902 | m_freem(m); |
902 | return; | | 903 | return; |
903 | } | | 904 | } |
904 | | | 905 | |
905 | IFQ_LOCK(inq); | | 906 | IFQ_LOCK(inq); |
906 | if (IF_QFULL(inq)) { | | 907 | if (IF_QFULL(inq)) { |
907 | IF_DROP(inq); | | 908 | IF_DROP(inq); |
908 | IFQ_UNLOCK(inq); | | 909 | IFQ_UNLOCK(inq); |
909 | m_freem(m); | | 910 | m_freem(m); |
910 | } else { | | 911 | } else { |
911 | IF_ENQUEUE(inq, m); | | 912 | IF_ENQUEUE(inq, m); |
912 | IFQ_UNLOCK(inq); | | 913 | IFQ_UNLOCK(inq); |
913 | schednetisr(isr); | | 914 | schednetisr(isr); |
914 | } | | 915 | } |
915 | } | | 916 | } |
916 | | | 917 | |
917 | /* | | 918 | /* |
918 | * Convert Ethernet address to printable (loggable) representation. | | 919 | * Convert Ethernet address to printable (loggable) representation. |
919 | */ | | 920 | */ |
920 | char * | | 921 | char * |
921 | ether_sprintf(const u_char *ap) | | 922 | ether_sprintf(const u_char *ap) |
922 | { | | 923 | { |
923 | static char etherbuf[3 * ETHER_ADDR_LEN]; | | 924 | static char etherbuf[3 * ETHER_ADDR_LEN]; |
924 | return ether_snprintf(etherbuf, sizeof(etherbuf), ap); | | 925 | return ether_snprintf(etherbuf, sizeof(etherbuf), ap); |
925 | } | | 926 | } |
926 | | | 927 | |
927 | char * | | 928 | char * |
928 | ether_snprintf(char *buf, size_t len, const u_char *ap) | | 929 | ether_snprintf(char *buf, size_t len, const u_char *ap) |
929 | { | | 930 | { |
930 | char *cp = buf; | | 931 | char *cp = buf; |
931 | size_t i; | | 932 | size_t i; |
932 | | | 933 | |
933 | for (i = 0; i < len / 3; i++) { | | 934 | for (i = 0; i < len / 3; i++) { |
934 | *cp++ = hexdigits[*ap >> 4]; | | 935 | *cp++ = hexdigits[*ap >> 4]; |
935 | *cp++ = hexdigits[*ap++ & 0xf]; | | 936 | *cp++ = hexdigits[*ap++ & 0xf]; |
936 | *cp++ = ':'; | | 937 | *cp++ = ':'; |
937 | } | | 938 | } |
938 | *--cp = '\0'; | | 939 | *--cp = '\0'; |
939 | return buf; | | 940 | return buf; |
940 | } | | 941 | } |
941 | | | 942 | |
942 | /* | | 943 | /* |
943 | * Perform common duties while attaching to interface list | | 944 | * Perform common duties while attaching to interface list |
944 | */ | | 945 | */ |
945 | void | | 946 | void |
946 | ether_ifattach(struct ifnet *ifp, const uint8_t *lla) | | 947 | ether_ifattach(struct ifnet *ifp, const uint8_t *lla) |
947 | { | | 948 | { |
948 | struct ethercom *ec = (struct ethercom *)ifp; | | 949 | struct ethercom *ec = (struct ethercom *)ifp; |
949 | | | 950 | |
950 | ifp->if_type = IFT_ETHER; | | 951 | ifp->if_type = IFT_ETHER; |
951 | ifp->if_hdrlen = ETHER_HDR_LEN; | | 952 | ifp->if_hdrlen = ETHER_HDR_LEN; |
952 | ifp->if_dlt = DLT_EN10MB; | | 953 | ifp->if_dlt = DLT_EN10MB; |
953 | ifp->if_mtu = ETHERMTU; | | 954 | ifp->if_mtu = ETHERMTU; |
954 | ifp->if_output = ether_output; | | 955 | ifp->if_output = ether_output; |
955 | ifp->_if_input = ether_input; | | 956 | ifp->_if_input = ether_input; |
956 | if (ifp->if_baudrate == 0) | | 957 | if (ifp->if_baudrate == 0) |
957 | ifp->if_baudrate = IF_Mbps(10); /* just a default */ | | 958 | ifp->if_baudrate = IF_Mbps(10); /* just a default */ |
958 | | | 959 | |
959 | if (lla != NULL) | | 960 | if (lla != NULL) |
960 | if_set_sadl(ifp, lla, ETHER_ADDR_LEN, !ETHER_IS_LOCAL(lla)); | | 961 | if_set_sadl(ifp, lla, ETHER_ADDR_LEN, !ETHER_IS_LOCAL(lla)); |
961 | | | 962 | |
962 | LIST_INIT(&ec->ec_multiaddrs); | | 963 | LIST_INIT(&ec->ec_multiaddrs); |
963 | ec->ec_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NET); | | 964 | ec->ec_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NET); |
964 | ifp->if_broadcastaddr = etherbroadcastaddr; | | 965 | ifp->if_broadcastaddr = etherbroadcastaddr; |
965 | bpf_attach(ifp, DLT_EN10MB, sizeof(struct ether_header)); | | 966 | bpf_attach(ifp, DLT_EN10MB, sizeof(struct ether_header)); |
966 | #ifdef MBUFTRACE | | 967 | #ifdef MBUFTRACE |
967 | strlcpy(ec->ec_tx_mowner.mo_name, ifp->if_xname, | | 968 | strlcpy(ec->ec_tx_mowner.mo_name, ifp->if_xname, |
968 | sizeof(ec->ec_tx_mowner.mo_name)); | | 969 | sizeof(ec->ec_tx_mowner.mo_name)); |
969 | strlcpy(ec->ec_tx_mowner.mo_descr, "tx", | | 970 | strlcpy(ec->ec_tx_mowner.mo_descr, "tx", |
970 | sizeof(ec->ec_tx_mowner.mo_descr)); | | 971 | sizeof(ec->ec_tx_mowner.mo_descr)); |
971 | strlcpy(ec->ec_rx_mowner.mo_name, ifp->if_xname, | | 972 | strlcpy(ec->ec_rx_mowner.mo_name, ifp->if_xname, |
972 | sizeof(ec->ec_rx_mowner.mo_name)); | | 973 | sizeof(ec->ec_rx_mowner.mo_name)); |
973 | strlcpy(ec->ec_rx_mowner.mo_descr, "rx", | | 974 | strlcpy(ec->ec_rx_mowner.mo_descr, "rx", |
974 | sizeof(ec->ec_rx_mowner.mo_descr)); | | 975 | sizeof(ec->ec_rx_mowner.mo_descr)); |
975 | MOWNER_ATTACH(&ec->ec_tx_mowner); | | 976 | MOWNER_ATTACH(&ec->ec_tx_mowner); |
976 | MOWNER_ATTACH(&ec->ec_rx_mowner); | | 977 | MOWNER_ATTACH(&ec->ec_rx_mowner); |
977 | ifp->if_mowner = &ec->ec_tx_mowner; | | 978 | ifp->if_mowner = &ec->ec_tx_mowner; |
978 | #endif | | 979 | #endif |
979 | } | | 980 | } |
980 | | | 981 | |
981 | void | | 982 | void |
982 | ether_ifdetach(struct ifnet *ifp) | | 983 | ether_ifdetach(struct ifnet *ifp) |
983 | { | | 984 | { |
984 | struct ethercom *ec = (void *) ifp; | | 985 | struct ethercom *ec = (void *) ifp; |
985 | struct ether_multi *enm; | | 986 | struct ether_multi *enm; |
986 | | | 987 | |
987 | /* | | 988 | /* |
988 | * Prevent further calls to ioctl (for example turning off | | 989 | * Prevent further calls to ioctl (for example turning off |
989 | * promiscuous mode from the bridge code), which eventually can | | 990 | * promiscuous mode from the bridge code), which eventually can |
990 | * call if_init() which can cause panics because the interface | | 991 | * call if_init() which can cause panics because the interface |
991 | * is in the process of being detached. Return device not configured | | 992 | * is in the process of being detached. Return device not configured |
992 | * instead. | | 993 | * instead. |
993 | */ | | 994 | */ |
994 | ifp->if_ioctl = (int (*)(struct ifnet *, u_long, void *))enxio; | | 995 | ifp->if_ioctl = (int (*)(struct ifnet *, u_long, void *))enxio; |
995 | | | 996 | |
996 | #if NBRIDGE > 0 | | 997 | #if NBRIDGE > 0 |
997 | if (ifp->if_bridge) | | 998 | if (ifp->if_bridge) |
998 | bridge_ifdetach(ifp); | | 999 | bridge_ifdetach(ifp); |
999 | #endif | | 1000 | #endif |
1000 | | | | |
1001 | bpf_detach(ifp); | | 1001 | bpf_detach(ifp); |
1002 | | | | |
1003 | #if NVLAN > 0 | | 1002 | #if NVLAN > 0 |
1004 | if (ec->ec_nvlans) | | 1003 | if (ec->ec_nvlans) |
1005 | vlan_ifdetach(ifp); | | 1004 | vlan_ifdetach(ifp); |
1006 | #endif | | 1005 | #endif |
1007 | | | 1006 | |
1008 | ETHER_LOCK(ec); | | 1007 | ETHER_LOCK(ec); |
1009 | while ((enm = LIST_FIRST(&ec->ec_multiaddrs)) != NULL) { | | 1008 | while ((enm = LIST_FIRST(&ec->ec_multiaddrs)) != NULL) { |
1010 | LIST_REMOVE(enm, enm_list); | | 1009 | LIST_REMOVE(enm, enm_list); |
1011 | kmem_intr_free(enm, sizeof(*enm)); | | 1010 | kmem_free(enm, sizeof(*enm)); |
1012 | ec->ec_multicnt--; | | 1011 | ec->ec_multicnt--; |
1013 | } | | 1012 | } |
1014 | ETHER_UNLOCK(ec); | | 1013 | ETHER_UNLOCK(ec); |
1015 | | | 1014 | |
1016 | mutex_destroy(ec->ec_lock); | | 1015 | mutex_obj_free(ec->ec_lock); |
1017 | | | 1016 | |
1018 | ifp->if_mowner = NULL; | | 1017 | ifp->if_mowner = NULL; |
1019 | MOWNER_DETACH(&ec->ec_rx_mowner); | | 1018 | MOWNER_DETACH(&ec->ec_rx_mowner); |
1020 | MOWNER_DETACH(&ec->ec_tx_mowner); | | 1019 | MOWNER_DETACH(&ec->ec_tx_mowner); |
1021 | } | | 1020 | } |
1022 | | | 1021 | |
1023 | #if 0 | | 1022 | #if 0 |
1024 | /* | | 1023 | /* |
1025 | * This is for reference. We have a table-driven version | | 1024 | * This is for reference. We have a table-driven version |
1026 | * of the little-endian crc32 generator, which is faster | | 1025 | * of the little-endian crc32 generator, which is faster |
1027 | * than the double-loop. | | 1026 | * than the double-loop. |
1028 | */ | | 1027 | */ |
1029 | uint32_t | | 1028 | uint32_t |
1030 | ether_crc32_le(const uint8_t *buf, size_t len) | | 1029 | ether_crc32_le(const uint8_t *buf, size_t len) |
1031 | { | | 1030 | { |
1032 | uint32_t c, crc, carry; | | 1031 | uint32_t c, crc, carry; |
1033 | size_t i, j; | | 1032 | size_t i, j; |
1034 | | | 1033 | |
1035 | crc = 0xffffffffU; /* initial value */ | | 1034 | crc = 0xffffffffU; /* initial value */ |
1036 | | | 1035 | |
1037 | for (i = 0; i < len; i++) { | | 1036 | for (i = 0; i < len; i++) { |
1038 | c = buf[i]; | | 1037 | c = buf[i]; |
1039 | for (j = 0; j < 8; j++) { | | 1038 | for (j = 0; j < 8; j++) { |
1040 | carry = ((crc & 0x01) ? 1 : 0) ^ (c & 0x01); | | 1039 | carry = ((crc & 0x01) ? 1 : 0) ^ (c & 0x01); |
1041 | crc >>= 1; | | 1040 | crc >>= 1; |
1042 | c >>= 1; | | 1041 | c >>= 1; |
1043 | if (carry) | | 1042 | if (carry) |
1044 | crc = (crc ^ ETHER_CRC_POLY_LE); | | 1043 | crc = (crc ^ ETHER_CRC_POLY_LE); |
1045 | } | | 1044 | } |
1046 | } | | 1045 | } |
1047 | | | 1046 | |
1048 | return (crc); | | 1047 | return (crc); |
1049 | } | | 1048 | } |
1050 | #else | | 1049 | #else |
1051 | uint32_t | | 1050 | uint32_t |
1052 | ether_crc32_le(const uint8_t *buf, size_t len) | | 1051 | ether_crc32_le(const uint8_t *buf, size_t len) |
1053 | { | | 1052 | { |
1054 | static const uint32_t crctab[] = { | | 1053 | static const uint32_t crctab[] = { |
1055 | 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, | | 1054 | 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, |
1056 | 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, | | 1055 | 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, |
1057 | 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, | | 1056 | 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, |
1058 | 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c | | 1057 | 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c |
1059 | }; | | 1058 | }; |
1060 | uint32_t crc; | | 1059 | uint32_t crc; |
1061 | size_t i; | | 1060 | size_t i; |
1062 | | | 1061 | |
1063 | crc = 0xffffffffU; /* initial value */ | | 1062 | crc = 0xffffffffU; /* initial value */ |
1064 | | | 1063 | |
1065 | for (i = 0; i < len; i++) { | | 1064 | for (i = 0; i < len; i++) { |
1066 | crc ^= buf[i]; | | 1065 | crc ^= buf[i]; |
1067 | crc = (crc >> 4) ^ crctab[crc & 0xf]; | | 1066 | crc = (crc >> 4) ^ crctab[crc & 0xf]; |
1068 | crc = (crc >> 4) ^ crctab[crc & 0xf]; | | 1067 | crc = (crc >> 4) ^ crctab[crc & 0xf]; |
1069 | } | | 1068 | } |
1070 | | | 1069 | |
1071 | return (crc); | | 1070 | return (crc); |
1072 | } | | 1071 | } |
1073 | #endif | | 1072 | #endif |
1074 | | | 1073 | |
1075 | uint32_t | | 1074 | uint32_t |
1076 | ether_crc32_be(const uint8_t *buf, size_t len) | | 1075 | ether_crc32_be(const uint8_t *buf, size_t len) |
1077 | { | | 1076 | { |
1078 | uint32_t c, crc, carry; | | 1077 | uint32_t c, crc, carry; |
1079 | size_t i, j; | | 1078 | size_t i, j; |
1080 | | | 1079 | |
1081 | crc = 0xffffffffU; /* initial value */ | | 1080 | crc = 0xffffffffU; /* initial value */ |
1082 | | | 1081 | |
1083 | for (i = 0; i < len; i++) { | | 1082 | for (i = 0; i < len; i++) { |
1084 | c = buf[i]; | | 1083 | c = buf[i]; |
1085 | for (j = 0; j < 8; j++) { | | 1084 | for (j = 0; j < 8; j++) { |
1086 | carry = ((crc & 0x80000000U) ? 1 : 0) ^ (c & 0x01); | | 1085 | carry = ((crc & 0x80000000U) ? 1 : 0) ^ (c & 0x01); |
1087 | crc <<= 1; | | 1086 | crc <<= 1; |
1088 | c >>= 1; | | 1087 | c >>= 1; |
1089 | if (carry) | | 1088 | if (carry) |
1090 | crc = (crc ^ ETHER_CRC_POLY_BE) | carry; | | 1089 | crc = (crc ^ ETHER_CRC_POLY_BE) | carry; |
1091 | } | | 1090 | } |
1092 | } | | 1091 | } |
1093 | | | 1092 | |
1094 | return (crc); | | 1093 | return (crc); |
1095 | } | | 1094 | } |
1096 | | | 1095 | |
1097 | #ifdef INET | | 1096 | #ifdef INET |
1098 | const uint8_t ether_ipmulticast_min[ETHER_ADDR_LEN] = | | 1097 | const uint8_t ether_ipmulticast_min[ETHER_ADDR_LEN] = |
1099 | { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 }; | | 1098 | { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 }; |
1100 | const uint8_t ether_ipmulticast_max[ETHER_ADDR_LEN] = | | 1099 | const uint8_t ether_ipmulticast_max[ETHER_ADDR_LEN] = |
1101 | { 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xff }; | | 1100 | { 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xff }; |
1102 | #endif | | 1101 | #endif |
1103 | #ifdef INET6 | | 1102 | #ifdef INET6 |
1104 | const uint8_t ether_ip6multicast_min[ETHER_ADDR_LEN] = | | 1103 | const uint8_t ether_ip6multicast_min[ETHER_ADDR_LEN] = |
1105 | { 0x33, 0x33, 0x00, 0x00, 0x00, 0x00 }; | | 1104 | { 0x33, 0x33, 0x00, 0x00, 0x00, 0x00 }; |
1106 | const uint8_t ether_ip6multicast_max[ETHER_ADDR_LEN] = | | 1105 | const uint8_t ether_ip6multicast_max[ETHER_ADDR_LEN] = |
1107 | { 0x33, 0x33, 0xff, 0xff, 0xff, 0xff }; | | 1106 | { 0x33, 0x33, 0xff, 0xff, 0xff, 0xff }; |
1108 | #endif | | 1107 | #endif |
1109 | | | 1108 | |
1110 | /* | | 1109 | /* |
1111 | * ether_aton implementation, not using a static buffer. | | 1110 | * ether_aton implementation, not using a static buffer. |
1112 | */ | | 1111 | */ |
1113 | int | | 1112 | int |
1114 | ether_aton_r(u_char *dest, size_t len, const char *str) | | 1113 | ether_aton_r(u_char *dest, size_t len, const char *str) |
1115 | { | | 1114 | { |
1116 | const u_char *cp = (const void *)str; | | 1115 | const u_char *cp = (const void *)str; |
1117 | u_char *ep; | | 1116 | u_char *ep; |
1118 | | | 1117 | |
1119 | #define atox(c) (((c) <= '9') ? ((c) - '0') : ((toupper(c) - 'A') + 10)) | | 1118 | #define atox(c) (((c) <= '9') ? ((c) - '0') : ((toupper(c) - 'A') + 10)) |
1120 | | | 1119 | |
1121 | if (len < ETHER_ADDR_LEN) | | 1120 | if (len < ETHER_ADDR_LEN) |
1122 | return ENOSPC; | | 1121 | return ENOSPC; |
1123 | | | 1122 | |
1124 | ep = dest + ETHER_ADDR_LEN; | | 1123 | ep = dest + ETHER_ADDR_LEN; |
1125 | | | 1124 | |
1126 | while (*cp) { | | 1125 | while (*cp) { |
1127 | if (!isxdigit(*cp)) | | 1126 | if (!isxdigit(*cp)) |
1128 | return EINVAL; | | 1127 | return EINVAL; |
| | | 1128 | |
1129 | *dest = atox(*cp); | | 1129 | *dest = atox(*cp); |
1130 | cp++; | | 1130 | cp++; |
1131 | if (isxdigit(*cp)) { | | 1131 | if (isxdigit(*cp)) { |
1132 | *dest = (*dest << 4) | atox(*cp); | | 1132 | *dest = (*dest << 4) | atox(*cp); |
1133 | dest++; | | | |
1134 | cp++; | | 1133 | cp++; |
1135 | } else | | 1134 | } |
1136 | dest++; | | 1135 | dest++; |
| | | 1136 | |
1137 | if (dest == ep) | | 1137 | if (dest == ep) |
1138 | return *cp == '\0' ? 0 : ENAMETOOLONG; | | 1138 | return (*cp == '\0') ? 0 : ENAMETOOLONG; |
| | | 1139 | |
1139 | switch (*cp) { | | 1140 | switch (*cp) { |
1140 | case ':': | | 1141 | case ':': |
1141 | case '-': | | 1142 | case '-': |
1142 | case '.': | | 1143 | case '.': |
1143 | cp++; | | 1144 | cp++; |
1144 | break; | | 1145 | break; |
1145 | } | | 1146 | } |
1146 | } | | 1147 | } |
1147 | return ENOBUFS; | | 1148 | return ENOBUFS; |
1148 | } | | 1149 | } |
1149 | | | 1150 | |
1150 | /* | | 1151 | /* |
1151 | * Convert a sockaddr into an Ethernet address or range of Ethernet | | 1152 | * Convert a sockaddr into an Ethernet address or range of Ethernet |
1152 | * addresses. | | 1153 | * addresses. |
1153 | */ | | 1154 | */ |
1154 | int | | 1155 | int |
1155 | ether_multiaddr(const struct sockaddr *sa, uint8_t addrlo[ETHER_ADDR_LEN], | | 1156 | ether_multiaddr(const struct sockaddr *sa, uint8_t addrlo[ETHER_ADDR_LEN], |
1156 | uint8_t addrhi[ETHER_ADDR_LEN]) | | 1157 | uint8_t addrhi[ETHER_ADDR_LEN]) |
1157 | { | | 1158 | { |
1158 | #ifdef INET | | 1159 | #ifdef INET |
1159 | const struct sockaddr_in *sin; | | 1160 | const struct sockaddr_in *sin; |
1160 | #endif /* INET */ | | 1161 | #endif /* INET */ |
1161 | #ifdef INET6 | | 1162 | #ifdef INET6 |
1162 | const struct sockaddr_in6 *sin6; | | 1163 | const struct sockaddr_in6 *sin6; |
1163 | #endif /* INET6 */ | | 1164 | #endif /* INET6 */ |
1164 | | | 1165 | |
1165 | switch (sa->sa_family) { | | 1166 | switch (sa->sa_family) { |
1166 | | | 1167 | |
1167 | case AF_UNSPEC: | | 1168 | case AF_UNSPEC: |
1168 | memcpy(addrlo, sa->sa_data, ETHER_ADDR_LEN); | | 1169 | memcpy(addrlo, sa->sa_data, ETHER_ADDR_LEN); |
1169 | memcpy(addrhi, addrlo, ETHER_ADDR_LEN); | | 1170 | memcpy(addrhi, addrlo, ETHER_ADDR_LEN); |
1170 | break; | | 1171 | break; |
1171 | | | 1172 | |
1172 | #ifdef INET | | 1173 | #ifdef INET |
1173 | case AF_INET: | | 1174 | case AF_INET: |
1174 | sin = satocsin(sa); | | 1175 | sin = satocsin(sa); |
1175 | if (sin->sin_addr.s_addr == INADDR_ANY) { | | 1176 | if (sin->sin_addr.s_addr == INADDR_ANY) { |
1176 | /* | | 1177 | /* |
1177 | * An IP address of INADDR_ANY means listen to | | 1178 | * An IP address of INADDR_ANY means listen to |
1178 | * or stop listening to all of the Ethernet | | 1179 | * or stop listening to all of the Ethernet |
1179 | * multicast addresses used for IP. | | 1180 | * multicast addresses used for IP. |
1180 | * (This is for the sake of IP multicast routers.) | | 1181 | * (This is for the sake of IP multicast routers.) |
1181 | */ | | 1182 | */ |
1182 | memcpy(addrlo, ether_ipmulticast_min, ETHER_ADDR_LEN); | | 1183 | memcpy(addrlo, ether_ipmulticast_min, ETHER_ADDR_LEN); |
1183 | memcpy(addrhi, ether_ipmulticast_max, ETHER_ADDR_LEN); | | 1184 | memcpy(addrhi, ether_ipmulticast_max, ETHER_ADDR_LEN); |
1184 | } | | 1185 | } else { |
1185 | else { | | | |
1186 | ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo); | | 1186 | ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo); |
1187 | memcpy(addrhi, addrlo, ETHER_ADDR_LEN); | | 1187 | memcpy(addrhi, addrlo, ETHER_ADDR_LEN); |
1188 | } | | 1188 | } |
1189 | break; | | 1189 | break; |
1190 | #endif | | 1190 | #endif |
1191 | #ifdef INET6 | | 1191 | #ifdef INET6 |
1192 | case AF_INET6: | | 1192 | case AF_INET6: |
1193 | sin6 = satocsin6(sa); | | 1193 | sin6 = satocsin6(sa); |
1194 | if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { | | 1194 | if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { |
1195 | /* | | 1195 | /* |
1196 | * An IP6 address of 0 means listen to or stop | | 1196 | * An IP6 address of 0 means listen to or stop |
1197 | * listening to all of the Ethernet multicast | | 1197 | * listening to all of the Ethernet multicast |
1198 | * address used for IP6. | | 1198 | * address used for IP6. |
1199 | * (This is used for multicast routers.) | | 1199 | * (This is used for multicast routers.) |
1200 | */ | | 1200 | */ |
1201 | memcpy(addrlo, ether_ip6multicast_min, ETHER_ADDR_LEN); | | 1201 | memcpy(addrlo, ether_ip6multicast_min, ETHER_ADDR_LEN); |
1202 | memcpy(addrhi, ether_ip6multicast_max, ETHER_ADDR_LEN); | | 1202 | memcpy(addrhi, ether_ip6multicast_max, ETHER_ADDR_LEN); |
1203 | } else { | | 1203 | } else { |
1204 | ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, addrlo); | | 1204 | ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, addrlo); |
1205 | memcpy(addrhi, addrlo, ETHER_ADDR_LEN); | | 1205 | memcpy(addrhi, addrlo, ETHER_ADDR_LEN); |
1206 | } | | 1206 | } |
1207 | break; | | 1207 | break; |
1208 | #endif | | 1208 | #endif |
1209 | | | 1209 | |
1210 | default: | | 1210 | default: |
1211 | return EAFNOSUPPORT; | | 1211 | return EAFNOSUPPORT; |
1212 | } | | 1212 | } |
1213 | return 0; | | 1213 | return 0; |
1214 | } | | 1214 | } |
1215 | | | 1215 | |
1216 | /* | | 1216 | /* |
1217 | * Add an Ethernet multicast address or range of addresses to the list for a | | 1217 | * Add an Ethernet multicast address or range of addresses to the list for a |
1218 | * given interface. | | 1218 | * given interface. |
1219 | */ | | 1219 | */ |
1220 | int | | 1220 | int |
1221 | ether_addmulti(const struct sockaddr *sa, struct ethercom *ec) | | 1221 | ether_addmulti(const struct sockaddr *sa, struct ethercom *ec) |
1222 | { | | 1222 | { |
1223 | struct ether_multi *enm, *_enm; | | 1223 | struct ether_multi *enm, *_enm; |
1224 | u_char addrlo[ETHER_ADDR_LEN]; | | 1224 | u_char addrlo[ETHER_ADDR_LEN]; |
1225 | u_char addrhi[ETHER_ADDR_LEN]; | | 1225 | u_char addrhi[ETHER_ADDR_LEN]; |
1226 | int error = 0; | | 1226 | int error = 0; |
1227 | | | 1227 | |
1228 | /* Allocate out of lock */ | | 1228 | /* Allocate out of lock */ |
1229 | /* XXX still can be called in softint */ | | 1229 | enm = kmem_alloc(sizeof(*enm), KM_SLEEP); |
1230 | enm = kmem_intr_alloc(sizeof(*enm), KM_SLEEP); | | | |
1231 | if (enm == NULL) | | | |
1232 | return ENOBUFS; | | | |
1233 | | | 1230 | |
1234 | ETHER_LOCK(ec); | | 1231 | ETHER_LOCK(ec); |
1235 | error = ether_multiaddr(sa, addrlo, addrhi); | | 1232 | error = ether_multiaddr(sa, addrlo, addrhi); |
1236 | if (error != 0) | | 1233 | if (error != 0) |
1237 | goto out; | | 1234 | goto out; |
1238 | | | 1235 | |
1239 | /* | | 1236 | /* |
1240 | * Verify that we have valid Ethernet multicast addresses. | | 1237 | * Verify that we have valid Ethernet multicast addresses. |
1241 | */ | | 1238 | */ |
1242 | if (!ETHER_IS_MULTICAST(addrlo) || !ETHER_IS_MULTICAST(addrhi)) { | | 1239 | if (!ETHER_IS_MULTICAST(addrlo) || !ETHER_IS_MULTICAST(addrhi)) { |
1243 | error = EINVAL; | | 1240 | error = EINVAL; |
1244 | goto out; | | 1241 | goto out; |
1245 | } | | 1242 | } |
| | | 1243 | |
1246 | /* | | 1244 | /* |
1247 | * See if the address range is already in the list. | | 1245 | * See if the address range is already in the list. |
1248 | */ | | 1246 | */ |
1249 | ETHER_LOOKUP_MULTI(addrlo, addrhi, ec, _enm); | | 1247 | ETHER_LOOKUP_MULTI(addrlo, addrhi, ec, _enm); |
1250 | if (_enm != NULL) { | | 1248 | if (_enm != NULL) { |
1251 | /* | | 1249 | /* |
1252 | * Found it; just increment the reference count. | | 1250 | * Found it; just increment the reference count. |
1253 | */ | | 1251 | */ |
1254 | ++_enm->enm_refcount; | | 1252 | ++_enm->enm_refcount; |
1255 | error = 0; | | 1253 | error = 0; |
1256 | goto out; | | 1254 | goto out; |
1257 | } | | 1255 | } |
| | | 1256 | |
1258 | /* | | 1257 | /* |
1259 | * Link a new multicast record into the interface's multicast list. | | 1258 | * Link a new multicast record into the interface's multicast list. |
1260 | */ | | 1259 | */ |
1261 | memcpy(enm->enm_addrlo, addrlo, 6); | | 1260 | memcpy(enm->enm_addrlo, addrlo, ETHER_ADDR_LEN); |
1262 | memcpy(enm->enm_addrhi, addrhi, 6); | | 1261 | memcpy(enm->enm_addrhi, addrhi, ETHER_ADDR_LEN); |
1263 | enm->enm_refcount = 1; | | 1262 | enm->enm_refcount = 1; |
1264 | LIST_INSERT_HEAD(&ec->ec_multiaddrs, enm, enm_list); | | 1263 | LIST_INSERT_HEAD(&ec->ec_multiaddrs, enm, enm_list); |
1265 | ec->ec_multicnt++; | | 1264 | ec->ec_multicnt++; |
| | | 1265 | |
1266 | /* | | 1266 | /* |
1267 | * Return ENETRESET to inform the driver that the list has changed | | 1267 | * Return ENETRESET to inform the driver that the list has changed |
1268 | * and its reception filter should be adjusted accordingly. | | 1268 | * and its reception filter should be adjusted accordingly. |
1269 | */ | | 1269 | */ |
1270 | error = ENETRESET; | | 1270 | error = ENETRESET; |
1271 | enm = NULL; | | 1271 | enm = NULL; |
| | | 1272 | |
1272 | out: | | 1273 | out: |
1273 | ETHER_UNLOCK(ec); | | 1274 | ETHER_UNLOCK(ec); |
1274 | if (enm != NULL) | | 1275 | if (enm != NULL) |
1275 | kmem_intr_free(enm, sizeof(*enm)); | | 1276 | kmem_free(enm, sizeof(*enm)); |
1276 | return error; | | 1277 | return error; |
1277 | } | | 1278 | } |
1278 | | | 1279 | |
1279 | /* | | 1280 | /* |
1280 | * Delete a multicast address record. | | 1281 | * Delete a multicast address record. |
1281 | */ | | 1282 | */ |
1282 | int | | 1283 | int |
1283 | ether_delmulti(const struct sockaddr *sa, struct ethercom *ec) | | 1284 | ether_delmulti(const struct sockaddr *sa, struct ethercom *ec) |
1284 | { | | 1285 | { |
1285 | struct ether_multi *enm; | | 1286 | struct ether_multi *enm; |
1286 | u_char addrlo[ETHER_ADDR_LEN]; | | 1287 | u_char addrlo[ETHER_ADDR_LEN]; |
1287 | u_char addrhi[ETHER_ADDR_LEN]; | | 1288 | u_char addrhi[ETHER_ADDR_LEN]; |
1288 | int error; | | 1289 | int error; |
1289 | | | 1290 | |
1290 | ETHER_LOCK(ec); | | 1291 | ETHER_LOCK(ec); |
1291 | error = ether_multiaddr(sa, addrlo, addrhi); | | 1292 | error = ether_multiaddr(sa, addrlo, addrhi); |
1292 | if (error != 0) | | 1293 | if (error != 0) |
1293 | goto error; | | 1294 | goto error; |
1294 | | | 1295 | |
1295 | /* | | 1296 | /* |
1296 | * Look ur the address in our list. | | 1297 | * Look up the address in our list. |
1297 | */ | | 1298 | */ |
1298 | ETHER_LOOKUP_MULTI(addrlo, addrhi, ec, enm); | | 1299 | ETHER_LOOKUP_MULTI(addrlo, addrhi, ec, enm); |
1299 | if (enm == NULL) { | | 1300 | if (enm == NULL) { |
1300 | error = ENXIO; | | 1301 | error = ENXIO; |
1301 | goto error; | | 1302 | goto error; |
1302 | } | | 1303 | } |
1303 | if (--enm->enm_refcount != 0) { | | 1304 | if (--enm->enm_refcount != 0) { |
1304 | /* | | 1305 | /* |
1305 | * Still some claims to this record. | | 1306 | * Still some claims to this record. |
1306 | */ | | 1307 | */ |
1307 | error = 0; | | 1308 | error = 0; |
1308 | goto error; | | 1309 | goto error; |
1309 | } | | 1310 | } |
| | | 1311 | |
1310 | /* | | 1312 | /* |
1311 | * No remaining claims to this record; unlink and free it. | | 1313 | * No remaining claims to this record; unlink and free it. |
1312 | */ | | 1314 | */ |
1313 | LIST_REMOVE(enm, enm_list); | | 1315 | LIST_REMOVE(enm, enm_list); |
1314 | ec->ec_multicnt--; | | 1316 | ec->ec_multicnt--; |
1315 | ETHER_UNLOCK(ec); | | 1317 | ETHER_UNLOCK(ec); |
| | | 1318 | kmem_free(enm, sizeof(*enm)); |
1316 | | | 1319 | |
1317 | kmem_intr_free(enm, sizeof(*enm)); | | | |
1318 | /* | | 1320 | /* |
1319 | * Return ENETRESET to inform the driver that the list has changed | | 1321 | * Return ENETRESET to inform the driver that the list has changed |
1320 | * and its reception filter should be adjusted accordingly. | | 1322 | * and its reception filter should be adjusted accordingly. |
1321 | */ | | 1323 | */ |
1322 | return ENETRESET; | | 1324 | return ENETRESET; |
| | | 1325 | |
1323 | error: | | 1326 | error: |
1324 | ETHER_UNLOCK(ec); | | 1327 | ETHER_UNLOCK(ec); |
1325 | return error; | | 1328 | return error; |
1326 | } | | 1329 | } |
1327 | | | 1330 | |
1328 | void | | 1331 | void |
1329 | ether_set_ifflags_cb(struct ethercom *ec, ether_cb_t cb) | | 1332 | ether_set_ifflags_cb(struct ethercom *ec, ether_cb_t cb) |
1330 | { | | 1333 | { |
1331 | ec->ec_ifflags_cb = cb; | | 1334 | ec->ec_ifflags_cb = cb; |
1332 | } | | 1335 | } |
1333 | | | 1336 | |
1334 | /* | | 1337 | /* |
1335 | * Common ioctls for Ethernet interfaces. Note, we must be | | 1338 | * Common ioctls for Ethernet interfaces. Note, we must be |
1336 | * called at splnet(). | | 1339 | * called at splnet(). |
1337 | */ | | 1340 | */ |
1338 | int | | 1341 | int |
1339 | ether_ioctl(struct ifnet *ifp, u_long cmd, void *data) | | 1342 | ether_ioctl(struct ifnet *ifp, u_long cmd, void *data) |
1340 | { | | 1343 | { |
1341 | struct ethercom *ec = (void *) ifp; | | 1344 | struct ethercom *ec = (void *) ifp; |
1342 | struct eccapreq *eccr; | | 1345 | struct eccapreq *eccr; |
1343 | struct ifreq *ifr = (struct ifreq *)data; | | 1346 | struct ifreq *ifr = (struct ifreq *)data; |
1344 | struct if_laddrreq *iflr = data; | | 1347 | struct if_laddrreq *iflr = data; |
1345 | const struct sockaddr_dl *sdl; | | 1348 | const struct sockaddr_dl *sdl; |
1346 | static const uint8_t zero[ETHER_ADDR_LEN]; | | 1349 | static const uint8_t zero[ETHER_ADDR_LEN]; |
1347 | int error; | | 1350 | int error; |
1348 | | | 1351 | |
1349 | switch (cmd) { | | 1352 | switch (cmd) { |
1350 | case SIOCINITIFADDR: | | 1353 | case SIOCINITIFADDR: |
1351 | { | | 1354 | { |
1352 | struct ifaddr *ifa = (struct ifaddr *)data; | | 1355 | struct ifaddr *ifa = (struct ifaddr *)data; |
1353 | if (ifa->ifa_addr->sa_family != AF_LINK | | 1356 | if (ifa->ifa_addr->sa_family != AF_LINK |
1354 | && (ifp->if_flags & (IFF_UP | IFF_RUNNING)) != | | 1357 | && (ifp->if_flags & (IFF_UP | IFF_RUNNING)) != |
1355 | (IFF_UP | IFF_RUNNING)) { | | 1358 | (IFF_UP | IFF_RUNNING)) { |
1356 | ifp->if_flags |= IFF_UP; | | 1359 | ifp->if_flags |= IFF_UP; |
1357 | if ((error = (*ifp->if_init)(ifp)) != 0) | | 1360 | if ((error = (*ifp->if_init)(ifp)) != 0) |
1358 | return error; | | 1361 | return error; |
1359 | } | | 1362 | } |
1360 | #ifdef INET | | 1363 | #ifdef INET |
1361 | if (ifa->ifa_addr->sa_family == AF_INET) | | 1364 | if (ifa->ifa_addr->sa_family == AF_INET) |
1362 | arp_ifinit(ifp, ifa); | | 1365 | arp_ifinit(ifp, ifa); |
1363 | #endif /* INET */ | | 1366 | #endif |
1364 | return 0; | | 1367 | return 0; |
1365 | } | | 1368 | } |
1366 | | | 1369 | |
1367 | case SIOCSIFMTU: | | 1370 | case SIOCSIFMTU: |
1368 | { | | 1371 | { |
1369 | int maxmtu; | | 1372 | int maxmtu; |
1370 | | | 1373 | |
1371 | if (ec->ec_capabilities & ETHERCAP_JUMBO_MTU) | | 1374 | if (ec->ec_capabilities & ETHERCAP_JUMBO_MTU) |
1372 | maxmtu = ETHERMTU_JUMBO; | | 1375 | maxmtu = ETHERMTU_JUMBO; |
1373 | else | | 1376 | else |
1374 | maxmtu = ETHERMTU; | | 1377 | maxmtu = ETHERMTU; |
1375 | | | 1378 | |
1376 | if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > maxmtu) | | 1379 | if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > maxmtu) |
1377 | return EINVAL; | | 1380 | return EINVAL; |
1378 | else if ((error = ifioctl_common(ifp, cmd, data)) != ENETRESET) | | 1381 | else if ((error = ifioctl_common(ifp, cmd, data)) != ENETRESET) |
1379 | return error; | | 1382 | return error; |
1380 | else if (ifp->if_flags & IFF_UP) { | | 1383 | else if (ifp->if_flags & IFF_UP) { |
1381 | /* Make sure the device notices the MTU change. */ | | 1384 | /* Make sure the device notices the MTU change. */ |
1382 | return (*ifp->if_init)(ifp); | | 1385 | return (*ifp->if_init)(ifp); |
1383 | } else | | 1386 | } else |
1384 | return 0; | | 1387 | return 0; |
1385 | } | | 1388 | } |
1386 | | | 1389 | |
1387 | case SIOCSIFFLAGS: | | 1390 | case SIOCSIFFLAGS: |
1388 | if ((error = ifioctl_common(ifp, cmd, data)) != 0) | | 1391 | if ((error = ifioctl_common(ifp, cmd, data)) != 0) |
1389 | return error; | | 1392 | return error; |
1390 | switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) { | | 1393 | switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) { |
1391 | case IFF_RUNNING: | | 1394 | case IFF_RUNNING: |
1392 | /* | | 1395 | /* |
1393 | * If interface is marked down and it is running, | | 1396 | * If interface is marked down and it is running, |
1394 | * then stop and disable it. | | 1397 | * then stop and disable it. |
1395 | */ | | 1398 | */ |
1396 | (*ifp->if_stop)(ifp, 1); | | 1399 | (*ifp->if_stop)(ifp, 1); |
1397 | break; | | 1400 | break; |
1398 | case IFF_UP: | | 1401 | case IFF_UP: |
1399 | /* | | 1402 | /* |
1400 | * If interface is marked up and it is stopped, then | | 1403 | * If interface is marked up and it is stopped, then |
1401 | * start it. | | 1404 | * start it. |
1402 | */ | | 1405 | */ |
1403 | return (*ifp->if_init)(ifp); | | 1406 | return (*ifp->if_init)(ifp); |
1404 | case IFF_UP | IFF_RUNNING: | | 1407 | case IFF_UP | IFF_RUNNING: |
1405 | error = 0; | | 1408 | error = 0; |
1406 | if (ec->ec_ifflags_cb != NULL) { | | 1409 | if (ec->ec_ifflags_cb != NULL) { |
1407 | error = (*ec->ec_ifflags_cb)(ec); | | 1410 | error = (*ec->ec_ifflags_cb)(ec); |
1408 | if (error == ENETRESET) { | | 1411 | if (error == ENETRESET) { |
1409 | /* | | 1412 | /* |
1410 | * Reset the interface to pick up | | 1413 | * Reset the interface to pick up |
1411 | * changes in any other flags that | | 1414 | * changes in any other flags that |
1412 | * affect the hardware state. | | 1415 | * affect the hardware state. |
1413 | */ | | 1416 | */ |
1414 | return (*ifp->if_init)(ifp); | | 1417 | return (*ifp->if_init)(ifp); |
1415 | } | | 1418 | } |
1416 | } else | | 1419 | } else |
1417 | error = (*ifp->if_init)(ifp); | | 1420 | error = (*ifp->if_init)(ifp); |
1418 | return error; | | 1421 | return error; |
1419 | case 0: | | 1422 | case 0: |
1420 | break; | | 1423 | break; |
1421 | } | | 1424 | } |
1422 | return 0; | | 1425 | return 0; |
1423 | case SIOCGETHERCAP: | | 1426 | case SIOCGETHERCAP: |
1424 | eccr = (struct eccapreq *)data; | | 1427 | eccr = (struct eccapreq *)data; |
1425 | eccr->eccr_capabilities = ec->ec_capabilities; | | 1428 | eccr->eccr_capabilities = ec->ec_capabilities; |
1426 | eccr->eccr_capenable = ec->ec_capenable; | | 1429 | eccr->eccr_capenable = ec->ec_capenable; |
1427 | return 0; | | 1430 | return 0; |
1428 | case SIOCADDMULTI: | | 1431 | case SIOCADDMULTI: |
1429 | return ether_addmulti(ifreq_getaddr(cmd, ifr), ec); | | 1432 | return ether_addmulti(ifreq_getaddr(cmd, ifr), ec); |
1430 | case SIOCDELMULTI: | | 1433 | case SIOCDELMULTI: |
1431 | return ether_delmulti(ifreq_getaddr(cmd, ifr), ec); | | 1434 | return ether_delmulti(ifreq_getaddr(cmd, ifr), ec); |
1432 | case SIOCSIFMEDIA: | | 1435 | case SIOCSIFMEDIA: |
1433 | case SIOCGIFMEDIA: | | 1436 | case SIOCGIFMEDIA: |
1434 | if (ec->ec_mii == NULL) | | 1437 | if (ec->ec_mii == NULL) |
1435 | return ENOTTY; | | 1438 | return ENOTTY; |
1436 | return ifmedia_ioctl(ifp, ifr, &ec->ec_mii->mii_media, cmd); | | 1439 | return ifmedia_ioctl(ifp, ifr, &ec->ec_mii->mii_media, cmd); |
1437 | case SIOCALIFADDR: | | 1440 | case SIOCALIFADDR: |
1438 | sdl = satocsdl(sstocsa(&iflr->addr)); | | 1441 | sdl = satocsdl(sstocsa(&iflr->addr)); |
1439 | if (sdl->sdl_family != AF_LINK) | | 1442 | if (sdl->sdl_family != AF_LINK) |
1440 | ; | | 1443 | ; |
1441 | else if (ETHER_IS_MULTICAST(CLLADDR(sdl))) | | 1444 | else if (ETHER_IS_MULTICAST(CLLADDR(sdl))) |
1442 | return EINVAL; | | 1445 | return EINVAL; |
1443 | else if (memcmp(zero, CLLADDR(sdl), sizeof(zero)) == 0) | | 1446 | else if (memcmp(zero, CLLADDR(sdl), sizeof(zero)) == 0) |
1444 | return EINVAL; | | 1447 | return EINVAL; |
1445 | /*FALLTHROUGH*/ | | 1448 | /*FALLTHROUGH*/ |
1446 | default: | | 1449 | default: |
1447 | return ifioctl_common(ifp, cmd, data); | | 1450 | return ifioctl_common(ifp, cmd, data); |
1448 | } | | 1451 | } |
1449 | return 0; | | 1452 | return 0; |
1450 | } | | 1453 | } |
1451 | | | 1454 | |
1452 | /* | | 1455 | /* |
1453 | * Enable/disable passing VLAN packets if the parent interface supports it. | | 1456 | * Enable/disable passing VLAN packets if the parent interface supports it. |
1454 | * Return: | | 1457 | * Return: |
1455 | * 0: Ok | | 1458 | * 0: Ok |
1456 | * -1: Parent interface does not support vlans | | 1459 | * -1: Parent interface does not support vlans |
1457 | * >0: Error | | 1460 | * >0: Error |
1458 | */ | | 1461 | */ |
1459 | int | | 1462 | int |
1460 | ether_enable_vlan_mtu(struct ifnet *ifp) | | 1463 | ether_enable_vlan_mtu(struct ifnet *ifp) |
1461 | { | | 1464 | { |
1462 | int error; | | 1465 | int error; |
1463 | struct ethercom *ec = (void *)ifp; | | 1466 | struct ethercom *ec = (void *)ifp; |
1464 | | | 1467 | |
1465 | /* Parent does not support VLAN's */ | | 1468 | /* Parent does not support VLAN's */ |
1466 | if ((ec->ec_capabilities & ETHERCAP_VLAN_MTU) == 0) | | 1469 | if ((ec->ec_capabilities & ETHERCAP_VLAN_MTU) == 0) |
1467 | return -1; | | 1470 | return -1; |
1468 | | | 1471 | |
1469 | /* | | 1472 | /* |
1470 | * Parent supports the VLAN_MTU capability, | | 1473 | * Parent supports the VLAN_MTU capability, |
1471 | * i.e. can Tx/Rx larger than ETHER_MAX_LEN frames; | | 1474 | * i.e. can Tx/Rx larger than ETHER_MAX_LEN frames; |
1472 | * enable it. | | 1475 | * enable it. |
1473 | */ | | 1476 | */ |
1474 | ec->ec_capenable |= ETHERCAP_VLAN_MTU; | | 1477 | ec->ec_capenable |= ETHERCAP_VLAN_MTU; |
1475 | | | 1478 | |
1476 | /* Interface is down, defer for later */ | | 1479 | /* Interface is down, defer for later */ |
1477 | if ((ifp->if_flags & IFF_UP) == 0) | | 1480 | if ((ifp->if_flags & IFF_UP) == 0) |
1478 | return 0; | | 1481 | return 0; |
1479 | | | 1482 | |
1480 | if ((error = if_flags_set(ifp, ifp->if_flags)) == 0) | | 1483 | if ((error = if_flags_set(ifp, ifp->if_flags)) == 0) |
1481 | return 0; | | 1484 | return 0; |
1482 | | | 1485 | |
1483 | ec->ec_capenable &= ~ETHERCAP_VLAN_MTU; | | 1486 | ec->ec_capenable &= ~ETHERCAP_VLAN_MTU; |
1484 | return error; | | 1487 | return error; |
1485 | } | | 1488 | } |
1486 | | | 1489 | |
1487 | int | | 1490 | int |
1488 | ether_disable_vlan_mtu(struct ifnet *ifp) | | 1491 | ether_disable_vlan_mtu(struct ifnet *ifp) |
1489 | { | | 1492 | { |
1490 | int error; | | 1493 | int error; |
1491 | struct ethercom *ec = (void *)ifp; | | 1494 | struct ethercom *ec = (void *)ifp; |
1492 | | | 1495 | |
1493 | /* We still have VLAN's, defer for later */ | | 1496 | /* We still have VLAN's, defer for later */ |
1494 | if (ec->ec_nvlans != 0) | | 1497 | if (ec->ec_nvlans != 0) |
1495 | return 0; | | 1498 | return 0; |
1496 | | | 1499 | |
1497 | /* Parent does not support VLAB's, nothing to do. */ | | 1500 | /* Parent does not support VLAB's, nothing to do. */ |
1498 | if ((ec->ec_capenable & ETHERCAP_VLAN_MTU) == 0) | | 1501 | if ((ec->ec_capenable & ETHERCAP_VLAN_MTU) == 0) |
1499 | return -1; | | 1502 | return -1; |
1500 | | | 1503 | |
1501 | /* | | 1504 | /* |
1502 | * Disable Tx/Rx of VLAN-sized frames. | | 1505 | * Disable Tx/Rx of VLAN-sized frames. |
1503 | */ | | 1506 | */ |
1504 | ec->ec_capenable &= ~ETHERCAP_VLAN_MTU; | | 1507 | ec->ec_capenable &= ~ETHERCAP_VLAN_MTU; |
1505 | | | 1508 | |
1506 | /* Interface is down, defer for later */ | | 1509 | /* Interface is down, defer for later */ |
1507 | if ((ifp->if_flags & IFF_UP) == 0) | | 1510 | if ((ifp->if_flags & IFF_UP) == 0) |
1508 | return 0; | | 1511 | return 0; |
1509 | | | 1512 | |
1510 | if ((error = if_flags_set(ifp, ifp->if_flags)) == 0) | | 1513 | if ((error = if_flags_set(ifp, ifp->if_flags)) == 0) |
1511 | return 0; | | 1514 | return 0; |
1512 | | | 1515 | |
1513 | ec->ec_capenable |= ETHERCAP_VLAN_MTU; | | 1516 | ec->ec_capenable |= ETHERCAP_VLAN_MTU; |
1514 | return error; | | 1517 | return error; |
1515 | } | | 1518 | } |
1516 | | | 1519 | |
1517 | static int | | 1520 | static int |
1518 | ether_multicast_sysctl(SYSCTLFN_ARGS) | | 1521 | ether_multicast_sysctl(SYSCTLFN_ARGS) |
1519 | { | | 1522 | { |
1520 | struct ether_multi *enm; | | 1523 | struct ether_multi *enm; |
1521 | struct ifnet *ifp; | | 1524 | struct ifnet *ifp; |
1522 | struct ethercom *ec; | | 1525 | struct ethercom *ec; |
1523 | int error = 0; | | 1526 | int error = 0; |
1524 | size_t written; | | 1527 | size_t written; |
1525 | struct psref psref; | | 1528 | struct psref psref; |
1526 | int bound; | | 1529 | int bound; |
1527 | unsigned int multicnt; | | 1530 | unsigned int multicnt; |
1528 | struct ether_multi_sysctl *addrs; | | 1531 | struct ether_multi_sysctl *addrs; |
1529 | int i; | | 1532 | int i; |
1530 | | | 1533 | |
1531 | if (namelen != 1) | | 1534 | if (namelen != 1) |
1532 | return EINVAL; | | 1535 | return EINVAL; |
1533 | | | 1536 | |
1534 | bound = curlwp_bind(); | | 1537 | bound = curlwp_bind(); |
1535 | ifp = if_get_byindex(name[0], &psref); | | 1538 | ifp = if_get_byindex(name[0], &psref); |
1536 | if (ifp == NULL) { | | 1539 | if (ifp == NULL) { |
1537 | error = ENODEV; | | 1540 | error = ENODEV; |
1538 | goto out; | | 1541 | goto out; |
1539 | } | | 1542 | } |
1540 | if (ifp->if_type != IFT_ETHER) { | | 1543 | if (ifp->if_type != IFT_ETHER) { |
1541 | if_put(ifp, &psref); | | 1544 | if_put(ifp, &psref); |
1542 | *oldlenp = 0; | | 1545 | *oldlenp = 0; |
1543 | goto out; | | 1546 | goto out; |
1544 | } | | 1547 | } |
1545 | ec = (struct ethercom *)ifp; | | 1548 | ec = (struct ethercom *)ifp; |
1546 | | | 1549 | |
1547 | if (oldp == NULL) { | | 1550 | if (oldp == NULL) { |
1548 | if_put(ifp, &psref); | | 1551 | if_put(ifp, &psref); |
1549 | *oldlenp = ec->ec_multicnt * sizeof(*addrs); | | 1552 | *oldlenp = ec->ec_multicnt * sizeof(*addrs); |
1550 | goto out; | | 1553 | goto out; |
1551 | } | | 1554 | } |
1552 | | | 1555 | |
1553 | /* | | 1556 | /* |
1554 | * ec->ec_lock is a spin mutex so we cannot call sysctl_copyout, which | | 1557 | * ec->ec_lock is a spin mutex so we cannot call sysctl_copyout, which |
1555 | * is sleepable, with holding it. Copy data to a local buffer first | | 1558 | * is sleepable, while holding it. Copy data to a local buffer first |
1556 | * with holding it and then call sysctl_copyout without holding it. | | 1559 | * with the lock taken and then call sysctl_copyout without holding it. |
1557 | */ | | 1560 | */ |
1558 | retry: | | 1561 | retry: |
1559 | multicnt = ec->ec_multicnt; | | 1562 | multicnt = ec->ec_multicnt; |
1560 | addrs = kmem_alloc(sizeof(*addrs) * multicnt, KM_SLEEP); | | 1563 | |
| | | 1564 | if (multicnt == 0) { |
| | | 1565 | if_put(ifp, &psref); |
| | | 1566 | *oldlenp = 0; |
| | | 1567 | goto out; |
| | | 1568 | } |
| | | 1569 | |
| | | 1570 | addrs = kmem_zalloc(sizeof(*addrs) * multicnt, KM_SLEEP); |
1561 | | | 1571 | |
1562 | ETHER_LOCK(ec); | | 1572 | ETHER_LOCK(ec); |
1563 | if (multicnt < ec->ec_multicnt) { | | 1573 | if (multicnt != ec->ec_multicnt) { |
1564 | /* The number of multicast addresses have increased */ | | 1574 | /* The number of multicast addresses has changed */ |
1565 | ETHER_UNLOCK(ec); | | 1575 | ETHER_UNLOCK(ec); |
1566 | kmem_free(addrs, sizeof(*addrs) * multicnt); | | 1576 | kmem_free(addrs, sizeof(*addrs) * multicnt); |
1567 | goto retry; | | 1577 | goto retry; |
1568 | } | | 1578 | } |
1569 | | | 1579 | |
1570 | i = 0; | | 1580 | i = 0; |
1571 | LIST_FOREACH(enm, &ec->ec_multiaddrs, enm_list) { | | 1581 | LIST_FOREACH(enm, &ec->ec_multiaddrs, enm_list) { |
1572 | struct ether_multi_sysctl *addr = &addrs[i]; | | 1582 | struct ether_multi_sysctl *addr = &addrs[i]; |
1573 | addr->enm_refcount = enm->enm_refcount; | | 1583 | addr->enm_refcount = enm->enm_refcount; |
1574 | memcpy(addr->enm_addrlo, enm->enm_addrlo, ETHER_ADDR_LEN); | | 1584 | memcpy(addr->enm_addrlo, enm->enm_addrlo, ETHER_ADDR_LEN); |
1575 | memcpy(addr->enm_addrhi, enm->enm_addrhi, ETHER_ADDR_LEN); | | 1585 | memcpy(addr->enm_addrhi, enm->enm_addrhi, ETHER_ADDR_LEN); |
1576 | i++; | | 1586 | i++; |
1577 | } | | 1587 | } |
1578 | ETHER_UNLOCK(ec); | | 1588 | ETHER_UNLOCK(ec); |
1579 | | | 1589 | |
1580 | error = 0; | | 1590 | error = 0; |
1581 | written = 0; | | 1591 | written = 0; |
1582 | for (i = 0; i < multicnt; i++) { | | 1592 | for (i = 0; i < multicnt; i++) { |
1583 | struct ether_multi_sysctl *addr = &addrs[i]; | | 1593 | struct ether_multi_sysctl *addr = &addrs[i]; |
1584 | | | 1594 | |
1585 | if (written + sizeof(*addr) > *oldlenp) | | 1595 | if (written + sizeof(*addr) > *oldlenp) |
1586 | break; | | 1596 | break; |
1587 | error = sysctl_copyout(l, addr, oldp, sizeof(*addr)); | | 1597 | error = sysctl_copyout(l, addr, oldp, sizeof(*addr)); |
1588 | if (error) | | 1598 | if (error) |
1589 | break; | | 1599 | break; |
1590 | written += sizeof(*addr); | | 1600 | written += sizeof(*addr); |
1591 | oldp = (char *)oldp + sizeof(*addr); | | 1601 | oldp = (char *)oldp + sizeof(*addr); |
1592 | } | | 1602 | } |
1593 | kmem_free(addrs, sizeof(*addrs) * multicnt); | | 1603 | kmem_free(addrs, sizeof(*addrs) * multicnt); |
1594 | | | 1604 | |
1595 | if_put(ifp, &psref); | | 1605 | if_put(ifp, &psref); |
1596 | | | 1606 | |
1597 | *oldlenp = written; | | 1607 | *oldlenp = written; |
1598 | out: | | 1608 | out: |
1599 | curlwp_bindx(bound); | | 1609 | curlwp_bindx(bound); |
1600 | return error; | | 1610 | return error; |
1601 | } | | 1611 | } |
1602 | | | 1612 | |
1603 | static void | | 1613 | static void |
1604 | ether_sysctl_setup(struct sysctllog **clog) | | 1614 | ether_sysctl_setup(struct sysctllog **clog) |
1605 | { | | 1615 | { |
1606 | const struct sysctlnode *rnode = NULL; | | 1616 | const struct sysctlnode *rnode = NULL; |
1607 | | | 1617 | |
1608 | sysctl_createv(clog, 0, NULL, &rnode, | | 1618 | sysctl_createv(clog, 0, NULL, &rnode, |
1609 | CTLFLAG_PERMANENT, | | 1619 | CTLFLAG_PERMANENT, |
1610 | CTLTYPE_NODE, "ether", | | 1620 | CTLTYPE_NODE, "ether", |
1611 | SYSCTL_DESCR("Ethernet-specific information"), | | 1621 | SYSCTL_DESCR("Ethernet-specific information"), |
1612 | NULL, 0, NULL, 0, | | 1622 | NULL, 0, NULL, 0, |
1613 | CTL_NET, CTL_CREATE, CTL_EOL); | | 1623 | CTL_NET, CTL_CREATE, CTL_EOL); |
1614 | | | 1624 | |
1615 | sysctl_createv(clog, 0, &rnode, NULL, | | 1625 | sysctl_createv(clog, 0, &rnode, NULL, |
1616 | CTLFLAG_PERMANENT, | | 1626 | CTLFLAG_PERMANENT, |
1617 | CTLTYPE_NODE, "multicast", | | 1627 | CTLTYPE_NODE, "multicast", |
1618 | SYSCTL_DESCR("multicast addresses"), | | 1628 | SYSCTL_DESCR("multicast addresses"), |
1619 | ether_multicast_sysctl, 0, NULL, 0, | | 1629 | ether_multicast_sysctl, 0, NULL, 0, |
1620 | CTL_CREATE, CTL_EOL); | | 1630 | CTL_CREATE, CTL_EOL); |
1621 | } | | 1631 | } |
1622 | | | 1632 | |
1623 | void | | 1633 | void |
1624 | etherinit(void) | | 1634 | etherinit(void) |
1625 | { | | 1635 | { |
1626 | | | 1636 | |
1627 | mutex_init(&bigpktpps_lock, MUTEX_DEFAULT, IPL_NET); | | 1637 | mutex_init(&bigpktpps_lock, MUTEX_DEFAULT, IPL_NET); |
1628 | ether_sysctl_setup(NULL); | | 1638 | ether_sysctl_setup(NULL); |
1629 | } | | 1639 | } |