| @@ -1,1604 +1,1605 @@ | | | @@ -1,1604 +1,1605 @@ |
1 | /* $NetBSD: if_ethersubr.c,v 1.242.6.6 2019/10/08 18:09:41 martin Exp $ */ | | 1 | /* $NetBSD: if_ethersubr.c,v 1.242.6.7 2019/10/08 18:12:44 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.6 2019/10/08 18:09:41 martin Exp $"); | | 64 | __KERNEL_RCSID(0, "$NetBSD: if_ethersubr.c,v 1.242.6.7 2019/10/08 18:12:44 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 | struct mbuf *mtop = m; | | 466 | struct mbuf *mtop = m; |
467 | uint16_t ether_type; | | 467 | uint16_t ether_type; |
468 | int hlen, af, hdrsize; | | 468 | int hlen, af, hdrsize; |
469 | void *hdr; | | 469 | void *hdr; |
470 | | | 470 | |
471 | KASSERT((mtop->m_flags & M_PKTHDR) != 0); | | 471 | KASSERT((mtop->m_flags & M_PKTHDR) != 0); |
472 | | | 472 | |
473 | hlen = ETHER_HDR_LEN; | | 473 | hlen = ETHER_HDR_LEN; |
474 | eh = mtod(m, struct ether_header *); | | 474 | eh = mtod(m, struct ether_header *); |
475 | | | 475 | |
476 | ether_type = htons(eh->ether_type); | | 476 | ether_type = htons(eh->ether_type); |
477 | | | 477 | |
478 | if (ether_type < ETHERMTU) { | | 478 | if (ether_type < ETHERMTU) { |
479 | /* LLC/SNAP */ | | 479 | /* LLC/SNAP */ |
480 | struct llc *llc = (struct llc *)(eh + 1); | | 480 | struct llc *llc = (struct llc *)(eh + 1); |
481 | hlen += 8; | | 481 | hlen += 8; |
482 | | | 482 | |
483 | if (m->m_len < hlen || | | 483 | if (m->m_len < hlen || |
484 | llc->llc_dsap != LLC_SNAP_LSAP || | | 484 | llc->llc_dsap != LLC_SNAP_LSAP || |
485 | llc->llc_ssap != LLC_SNAP_LSAP || | | 485 | llc->llc_ssap != LLC_SNAP_LSAP || |
486 | llc->llc_control != LLC_UI) { | | 486 | llc->llc_control != LLC_UI) { |
487 | /* Not SNAP. */ | | 487 | /* Not SNAP. */ |
488 | goto bad; | | 488 | goto bad; |
489 | } | | 489 | } |
490 | | | 490 | |
491 | ether_type = htons(llc->llc_un.type_snap.ether_type); | | 491 | ether_type = htons(llc->llc_un.type_snap.ether_type); |
492 | } | | 492 | } |
493 | | | 493 | |
494 | switch (ether_type) { | | 494 | switch (ether_type) { |
495 | case ETHERTYPE_IP: | | 495 | case ETHERTYPE_IP: |
496 | af = AF_INET; | | 496 | af = AF_INET; |
497 | hdrsize = 20; /* sizeof(struct ip) */ | | 497 | hdrsize = 20; /* sizeof(struct ip) */ |
498 | break; | | 498 | break; |
499 | | | 499 | |
500 | case ETHERTYPE_IPV6: | | 500 | case ETHERTYPE_IPV6: |
501 | af = AF_INET6; | | 501 | af = AF_INET6; |
502 | hdrsize = 40; /* sizeof(struct ip6_hdr) */ | | 502 | hdrsize = 40; /* sizeof(struct ip6_hdr) */ |
503 | break; | | 503 | break; |
504 | | | 504 | |
505 | default: | | 505 | default: |
506 | af = AF_UNSPEC; | | 506 | af = AF_UNSPEC; |
507 | hdrsize = 0; | | 507 | hdrsize = 0; |
508 | break; | | 508 | break; |
509 | } | | 509 | } |
510 | | | 510 | |
511 | while (m->m_len <= hlen) { | | 511 | while (m->m_len <= hlen) { |
512 | hlen -= m->m_len; | | 512 | hlen -= m->m_len; |
513 | m = m->m_next; | | 513 | m = m->m_next; |
514 | if (m == NULL) | | 514 | if (m == NULL) |
515 | goto bad; | | 515 | goto bad; |
516 | } | | 516 | } |
517 | | | 517 | |
518 | if (m->m_len < (hlen + hdrsize)) { | | 518 | if (m->m_len < (hlen + hdrsize)) { |
519 | /* | | 519 | /* |
520 | * protocol header not in a single mbuf. | | 520 | * protocol header not in a single mbuf. |
521 | * We can't cope with this situation right | | 521 | * We can't cope with this situation right |
522 | * now (but it shouldn't ever happen, really, anyhow). | | 522 | * now (but it shouldn't ever happen, really, anyhow). |
523 | */ | | 523 | */ |
524 | #ifdef DEBUG | | 524 | #ifdef DEBUG |
525 | printf("altq_etherclassify: headers span multiple mbufs: " | | 525 | printf("altq_etherclassify: headers span multiple mbufs: " |
526 | "%d < %d\n", m->m_len, (hlen + hdrsize)); | | 526 | "%d < %d\n", m->m_len, (hlen + hdrsize)); |
527 | #endif | | 527 | #endif |
528 | goto bad; | | 528 | goto bad; |
529 | } | | 529 | } |
530 | | | 530 | |
531 | m->m_data += hlen; | | 531 | m->m_data += hlen; |
532 | m->m_len -= hlen; | | 532 | m->m_len -= hlen; |
533 | | | 533 | |
534 | hdr = mtod(m, void *); | | 534 | hdr = mtod(m, void *); |
535 | | | 535 | |
536 | if (ALTQ_NEEDS_CLASSIFY(ifq)) { | | 536 | if (ALTQ_NEEDS_CLASSIFY(ifq)) { |
537 | mtop->m_pkthdr.pattr_class = | | 537 | mtop->m_pkthdr.pattr_class = |
538 | (*ifq->altq_classify)(ifq->altq_clfier, m, af); | | 538 | (*ifq->altq_classify)(ifq->altq_clfier, m, af); |
539 | } | | 539 | } |
540 | mtop->m_pkthdr.pattr_af = af; | | 540 | mtop->m_pkthdr.pattr_af = af; |
541 | mtop->m_pkthdr.pattr_hdr = hdr; | | 541 | mtop->m_pkthdr.pattr_hdr = hdr; |
542 | | | 542 | |
543 | m->m_data -= hlen; | | 543 | m->m_data -= hlen; |
544 | m->m_len += hlen; | | 544 | m->m_len += hlen; |
545 | | | 545 | |
546 | return; | | 546 | return; |
547 | | | 547 | |
548 | bad: | | 548 | bad: |
549 | mtop->m_pkthdr.pattr_class = NULL; | | 549 | mtop->m_pkthdr.pattr_class = NULL; |
550 | mtop->m_pkthdr.pattr_hdr = NULL; | | 550 | mtop->m_pkthdr.pattr_hdr = NULL; |
551 | mtop->m_pkthdr.pattr_af = AF_UNSPEC; | | 551 | mtop->m_pkthdr.pattr_af = AF_UNSPEC; |
552 | } | | 552 | } |
553 | #endif /* ALTQ */ | | 553 | #endif /* ALTQ */ |
554 | | | 554 | |
555 | /* | | 555 | /* |
556 | * Process a received Ethernet packet; | | 556 | * Process a received Ethernet packet; |
557 | * the packet is in the mbuf chain m with | | 557 | * the packet is in the mbuf chain m with |
558 | * the ether header. | | 558 | * the ether header. |
559 | */ | | 559 | */ |
560 | void | | 560 | void |
561 | ether_input(struct ifnet *ifp, struct mbuf *m) | | 561 | ether_input(struct ifnet *ifp, struct mbuf *m) |
562 | { | | 562 | { |
563 | struct ethercom *ec = (struct ethercom *) ifp; | | 563 | struct ethercom *ec = (struct ethercom *) ifp; |
564 | pktqueue_t *pktq = NULL; | | 564 | pktqueue_t *pktq = NULL; |
565 | struct ifqueue *inq = NULL; | | 565 | struct ifqueue *inq = NULL; |
566 | uint16_t etype; | | 566 | uint16_t etype; |
567 | struct ether_header *eh; | | 567 | struct ether_header *eh; |
568 | size_t ehlen; | | 568 | size_t ehlen; |
569 | static int earlypkts; | | 569 | static int earlypkts; |
570 | int isr = 0; | | 570 | int isr = 0; |
571 | #if defined (LLC) || defined(NETATALK) | | 571 | #if defined (LLC) || defined(NETATALK) |
572 | struct llc *l; | | 572 | struct llc *l; |
573 | #endif | | 573 | #endif |
574 | | | 574 | |
575 | KASSERT(!cpu_intr_p()); | | 575 | KASSERT(!cpu_intr_p()); |
576 | | | 576 | |
577 | if ((ifp->if_flags & IFF_UP) == 0) { | | 577 | if ((ifp->if_flags & IFF_UP) == 0) { |
578 | m_freem(m); | | 578 | m_freem(m); |
579 | return; | | 579 | return; |
580 | } | | 580 | } |
581 | | | 581 | |
582 | #ifdef MBUFTRACE | | 582 | #ifdef MBUFTRACE |
583 | m_claimm(m, &ec->ec_rx_mowner); | | 583 | m_claimm(m, &ec->ec_rx_mowner); |
584 | #endif | | 584 | #endif |
585 | eh = mtod(m, struct ether_header *); | | 585 | eh = mtod(m, struct ether_header *); |
586 | etype = ntohs(eh->ether_type); | | 586 | etype = ntohs(eh->ether_type); |
587 | ehlen = sizeof(*eh); | | 587 | ehlen = sizeof(*eh); |
588 | | | 588 | |
589 | if (__predict_false(earlypkts < 100 || !rnd_initial_entropy)) { | | 589 | if (__predict_false(earlypkts < 100 || !rnd_initial_entropy)) { |
590 | rnd_add_data(NULL, eh, ehlen, 0); | | 590 | rnd_add_data(NULL, eh, ehlen, 0); |
591 | earlypkts++; | | 591 | earlypkts++; |
592 | } | | 592 | } |
593 | | | 593 | |
594 | /* | | 594 | /* |
595 | * Determine if the packet is within its size limits. | | 595 | * Determine if the packet is within its size limits. |
596 | */ | | 596 | */ |
597 | if (etype != ETHERTYPE_MPLS && m->m_pkthdr.len > | | 597 | if (etype != ETHERTYPE_MPLS && m->m_pkthdr.len > |
598 | ETHER_MAX_FRAME(ifp, etype, m->m_flags & M_HASFCS)) { | | 598 | ETHER_MAX_FRAME(ifp, etype, m->m_flags & M_HASFCS)) { |
599 | mutex_enter(&bigpktpps_lock); | | 599 | mutex_enter(&bigpktpps_lock); |
600 | if (ppsratecheck(&bigpktppslim_last, &bigpktpps_count, | | 600 | if (ppsratecheck(&bigpktppslim_last, &bigpktpps_count, |
601 | bigpktppslim)) { | | 601 | bigpktppslim)) { |
602 | printf("%s: discarding oversize frame (len=%d)\n", | | 602 | printf("%s: discarding oversize frame (len=%d)\n", |
603 | ifp->if_xname, m->m_pkthdr.len); | | 603 | ifp->if_xname, m->m_pkthdr.len); |
604 | } | | 604 | } |
605 | mutex_exit(&bigpktpps_lock); | | 605 | mutex_exit(&bigpktpps_lock); |
| | | 606 | ifp->if_iqdrops++; |
606 | m_freem(m); | | 607 | m_freem(m); |
607 | return; | | 608 | return; |
608 | } | | 609 | } |
609 | | | 610 | |
610 | if (ETHER_IS_MULTICAST(eh->ether_dhost)) { | | 611 | if (ETHER_IS_MULTICAST(eh->ether_dhost)) { |
611 | /* | | 612 | /* |
612 | * If this is not a simplex interface, drop the packet | | 613 | * If this is not a simplex interface, drop the packet |
613 | * if it came from us. | | 614 | * if it came from us. |
614 | */ | | 615 | */ |
615 | if ((ifp->if_flags & IFF_SIMPLEX) == 0 && | | 616 | if ((ifp->if_flags & IFF_SIMPLEX) == 0 && |
616 | memcmp(CLLADDR(ifp->if_sadl), eh->ether_shost, | | 617 | memcmp(CLLADDR(ifp->if_sadl), eh->ether_shost, |
617 | ETHER_ADDR_LEN) == 0) { | | 618 | ETHER_ADDR_LEN) == 0) { |
618 | m_freem(m); | | 619 | m_freem(m); |
619 | return; | | 620 | return; |
620 | } | | 621 | } |
621 | | | 622 | |
622 | if (memcmp(etherbroadcastaddr, | | 623 | if (memcmp(etherbroadcastaddr, |
623 | eh->ether_dhost, ETHER_ADDR_LEN) == 0) | | 624 | eh->ether_dhost, ETHER_ADDR_LEN) == 0) |
624 | m->m_flags |= M_BCAST; | | 625 | m->m_flags |= M_BCAST; |
625 | else | | 626 | else |
626 | m->m_flags |= M_MCAST; | | 627 | m->m_flags |= M_MCAST; |
627 | ifp->if_imcasts++; | | 628 | ifp->if_imcasts++; |
628 | } | | 629 | } |
629 | | | 630 | |
630 | /* If the CRC is still on the packet, trim it off. */ | | 631 | /* If the CRC is still on the packet, trim it off. */ |
631 | if (m->m_flags & M_HASFCS) { | | 632 | if (m->m_flags & M_HASFCS) { |
632 | m_adj(m, -ETHER_CRC_LEN); | | 633 | m_adj(m, -ETHER_CRC_LEN); |
633 | m->m_flags &= ~M_HASFCS; | | 634 | m->m_flags &= ~M_HASFCS; |
634 | } | | 635 | } |
635 | | | 636 | |
636 | ifp->if_ibytes += m->m_pkthdr.len; | | 637 | ifp->if_ibytes += m->m_pkthdr.len; |
637 | | | 638 | |
638 | #if NCARP > 0 | | 639 | #if NCARP > 0 |
639 | if (__predict_false(ifp->if_carp && ifp->if_type != IFT_CARP)) { | | 640 | if (__predict_false(ifp->if_carp && ifp->if_type != IFT_CARP)) { |
640 | /* | | 641 | /* |
641 | * clear M_PROMISC, in case the packets comes from a | | 642 | * clear M_PROMISC, in case the packets comes from a |
642 | * vlan | | 643 | * vlan |
643 | */ | | 644 | */ |
644 | m->m_flags &= ~M_PROMISC; | | 645 | m->m_flags &= ~M_PROMISC; |
645 | if (carp_input(m, (uint8_t *)&eh->ether_shost, | | 646 | if (carp_input(m, (uint8_t *)&eh->ether_shost, |
646 | (uint8_t *)&eh->ether_dhost, eh->ether_type) == 0) | | 647 | (uint8_t *)&eh->ether_dhost, eh->ether_type) == 0) |
647 | return; | | 648 | return; |
648 | } | | 649 | } |
649 | #endif /* NCARP > 0 */ | | 650 | #endif /* NCARP > 0 */ |
650 | | | 651 | |
651 | if ((m->m_flags & (M_BCAST | M_MCAST | M_PROMISC)) == 0 && | | 652 | if ((m->m_flags & (M_BCAST | M_MCAST | M_PROMISC)) == 0 && |
652 | (ifp->if_flags & IFF_PROMISC) != 0 && | | 653 | (ifp->if_flags & IFF_PROMISC) != 0 && |
653 | memcmp(CLLADDR(ifp->if_sadl), eh->ether_dhost, | | 654 | memcmp(CLLADDR(ifp->if_sadl), eh->ether_dhost, |
654 | ETHER_ADDR_LEN) != 0) { | | 655 | ETHER_ADDR_LEN) != 0) { |
655 | m->m_flags |= M_PROMISC; | | 656 | m->m_flags |= M_PROMISC; |
656 | } | | 657 | } |
657 | | | 658 | |
658 | if ((m->m_flags & M_PROMISC) == 0) { | | 659 | if ((m->m_flags & M_PROMISC) == 0) { |
659 | if (pfil_run_hooks(ifp->if_pfil, &m, ifp, PFIL_IN) != 0) | | 660 | if (pfil_run_hooks(ifp->if_pfil, &m, ifp, PFIL_IN) != 0) |
660 | return; | | 661 | return; |
661 | if (m == NULL) | | 662 | if (m == NULL) |
662 | return; | | 663 | return; |
663 | | | 664 | |
664 | eh = mtod(m, struct ether_header *); | | 665 | eh = mtod(m, struct ether_header *); |
665 | etype = ntohs(eh->ether_type); | | 666 | etype = ntohs(eh->ether_type); |
666 | ehlen = sizeof(*eh); | | 667 | ehlen = sizeof(*eh); |
667 | } | | 668 | } |
668 | | | 669 | |
669 | #if NAGR > 0 | | 670 | #if NAGR > 0 |
670 | if (ifp->if_agrprivate && | | 671 | if (ifp->if_agrprivate && |
671 | __predict_true(etype != ETHERTYPE_SLOWPROTOCOLS)) { | | 672 | __predict_true(etype != ETHERTYPE_SLOWPROTOCOLS)) { |
672 | m->m_flags &= ~M_PROMISC; | | 673 | m->m_flags &= ~M_PROMISC; |
673 | agr_input(ifp, m); | | 674 | agr_input(ifp, m); |
674 | return; | | 675 | return; |
675 | } | | 676 | } |
676 | #endif /* NAGR > 0 */ | | 677 | #endif /* NAGR > 0 */ |
677 | | | 678 | |
678 | /* | | 679 | /* |
679 | * If VLANs are configured on the interface, check to | | 680 | * If VLANs are configured on the interface, check to |
680 | * see if the device performed the decapsulation and | | 681 | * see if the device performed the decapsulation and |
681 | * provided us with the tag. | | 682 | * provided us with the tag. |
682 | */ | | 683 | */ |
683 | if (ec->ec_nvlans && vlan_has_tag(m)) { | | 684 | if (ec->ec_nvlans && vlan_has_tag(m)) { |
684 | #if NVLAN > 0 | | 685 | #if NVLAN > 0 |
685 | /* | | 686 | /* |
686 | * vlan_input() will either recursively call ether_input() | | 687 | * vlan_input() will either recursively call ether_input() |
687 | * or drop the packet. | | 688 | * or drop the packet. |
688 | */ | | 689 | */ |
689 | vlan_input(ifp, m); | | 690 | vlan_input(ifp, m); |
690 | #else | | 691 | #else |
691 | m_freem(m); | | 692 | m_freem(m); |
692 | #endif | | 693 | #endif |
693 | return; | | 694 | return; |
694 | } | | 695 | } |
695 | | | 696 | |
696 | /* | | 697 | /* |
697 | * Handle protocols that expect to have the Ethernet header | | 698 | * Handle protocols that expect to have the Ethernet header |
698 | * (and possibly FCS) intact. | | 699 | * (and possibly FCS) intact. |
699 | */ | | 700 | */ |
700 | switch (etype) { | | 701 | switch (etype) { |
701 | case ETHERTYPE_VLAN: { | | 702 | case ETHERTYPE_VLAN: { |
702 | struct ether_vlan_header *evl = (void *)eh; | | 703 | struct ether_vlan_header *evl = (void *)eh; |
703 | /* | | 704 | /* |
704 | * If there is a tag of 0, then the VLAN header was probably | | 705 | * If there is a tag of 0, then the VLAN header was probably |
705 | * just being used to store the priority. Extract the ether | | 706 | * just being used to store the priority. Extract the ether |
706 | * type, and if IP or IPV6, let them deal with it. | | 707 | * type, and if IP or IPV6, let them deal with it. |
707 | */ | | 708 | */ |
708 | if (m->m_len <= sizeof(*evl) | | 709 | if (m->m_len <= sizeof(*evl) |
709 | && EVL_VLANOFTAG(evl->evl_tag) == 0) { | | 710 | && EVL_VLANOFTAG(evl->evl_tag) == 0) { |
710 | etype = ntohs(evl->evl_proto); | | 711 | etype = ntohs(evl->evl_proto); |
711 | ehlen = sizeof(*evl); | | 712 | ehlen = sizeof(*evl); |
712 | if ((m->m_flags & M_PROMISC) == 0 | | 713 | if ((m->m_flags & M_PROMISC) == 0 |
713 | && (etype == ETHERTYPE_IP | | 714 | && (etype == ETHERTYPE_IP |
714 | || etype == ETHERTYPE_IPV6)) | | 715 | || etype == ETHERTYPE_IPV6)) |
715 | break; | | 716 | break; |
716 | } | | 717 | } |
717 | #if NVLAN > 0 | | 718 | #if NVLAN > 0 |
718 | /* | | 719 | /* |
719 | * vlan_input() will either recursively call ether_input() | | 720 | * vlan_input() will either recursively call ether_input() |
720 | * or drop the packet. | | 721 | * or drop the packet. |
721 | */ | | 722 | */ |
722 | if (((struct ethercom *)ifp)->ec_nvlans != 0) | | 723 | if (((struct ethercom *)ifp)->ec_nvlans != 0) |
723 | vlan_input(ifp, m); | | 724 | vlan_input(ifp, m); |
724 | else | | 725 | else |
725 | #endif /* NVLAN > 0 */ | | 726 | #endif /* NVLAN > 0 */ |
726 | m_freem(m); | | 727 | m_freem(m); |
727 | return; | | 728 | return; |
728 | } | | 729 | } |
729 | #if NPPPOE > 0 | | 730 | #if NPPPOE > 0 |
730 | case ETHERTYPE_PPPOEDISC: | | 731 | case ETHERTYPE_PPPOEDISC: |
731 | pppoedisc_input(ifp, m); | | 732 | pppoedisc_input(ifp, m); |
732 | return; | | 733 | return; |
733 | case ETHERTYPE_PPPOE: | | 734 | case ETHERTYPE_PPPOE: |
734 | pppoe_input(ifp, m); | | 735 | pppoe_input(ifp, m); |
735 | return; | | 736 | return; |
736 | #endif /* NPPPOE > 0 */ | | 737 | #endif /* NPPPOE > 0 */ |
737 | case ETHERTYPE_SLOWPROTOCOLS: { | | 738 | case ETHERTYPE_SLOWPROTOCOLS: { |
738 | uint8_t subtype; | | 739 | uint8_t subtype; |
739 | | | 740 | |
740 | #if defined(DIAGNOSTIC) | | 741 | #if defined(DIAGNOSTIC) |
741 | if (m->m_pkthdr.len < sizeof(*eh) + sizeof(subtype)) { | | 742 | if (m->m_pkthdr.len < sizeof(*eh) + sizeof(subtype)) { |
742 | panic("ether_input: too short slow protocol packet"); | | 743 | panic("ether_input: too short slow protocol packet"); |
743 | } | | 744 | } |
744 | #endif | | 745 | #endif |
745 | m_copydata(m, sizeof(*eh), sizeof(subtype), &subtype); | | 746 | m_copydata(m, sizeof(*eh), sizeof(subtype), &subtype); |
746 | switch (subtype) { | | 747 | switch (subtype) { |
747 | #if NAGR > 0 | | 748 | #if NAGR > 0 |
748 | case SLOWPROTOCOLS_SUBTYPE_LACP: | | 749 | case SLOWPROTOCOLS_SUBTYPE_LACP: |
749 | if (ifp->if_agrprivate) { | | 750 | if (ifp->if_agrprivate) { |
750 | ieee8023ad_lacp_input(ifp, m); | | 751 | ieee8023ad_lacp_input(ifp, m); |
751 | return; | | 752 | return; |
752 | } | | 753 | } |
753 | break; | | 754 | break; |
754 | | | 755 | |
755 | case SLOWPROTOCOLS_SUBTYPE_MARKER: | | 756 | case SLOWPROTOCOLS_SUBTYPE_MARKER: |
756 | if (ifp->if_agrprivate) { | | 757 | if (ifp->if_agrprivate) { |
757 | ieee8023ad_marker_input(ifp, m); | | 758 | ieee8023ad_marker_input(ifp, m); |
758 | return; | | 759 | return; |
759 | } | | 760 | } |
760 | break; | | 761 | break; |
761 | #endif /* NAGR > 0 */ | | 762 | #endif /* NAGR > 0 */ |
762 | default: | | 763 | default: |
763 | if (subtype == 0 || subtype > 10) { | | 764 | if (subtype == 0 || subtype > 10) { |
764 | /* illegal value */ | | 765 | /* illegal value */ |
765 | m_freem(m); | | 766 | m_freem(m); |
766 | return; | | 767 | return; |
767 | } | | 768 | } |
768 | /* unknown subtype */ | | 769 | /* unknown subtype */ |
769 | break; | | 770 | break; |
770 | } | | 771 | } |
771 | /* FALLTHROUGH */ | | 772 | /* FALLTHROUGH */ |
772 | } | | 773 | } |
773 | default: | | 774 | default: |
774 | if (m->m_flags & M_PROMISC) { | | 775 | if (m->m_flags & M_PROMISC) { |
775 | m_freem(m); | | 776 | m_freem(m); |
776 | return; | | 777 | return; |
777 | } | | 778 | } |
778 | } | | 779 | } |
779 | | | 780 | |
780 | /* If the CRC is still on the packet, trim it off. */ | | 781 | /* If the CRC is still on the packet, trim it off. */ |
781 | if (m->m_flags & M_HASFCS) { | | 782 | if (m->m_flags & M_HASFCS) { |
782 | m_adj(m, -ETHER_CRC_LEN); | | 783 | m_adj(m, -ETHER_CRC_LEN); |
783 | m->m_flags &= ~M_HASFCS; | | 784 | m->m_flags &= ~M_HASFCS; |
784 | } | | 785 | } |
785 | | | 786 | |
786 | if (etype > ETHERMTU + sizeof (struct ether_header)) { | | 787 | if (etype > ETHERMTU + sizeof (struct ether_header)) { |
787 | /* Strip off the Ethernet header. */ | | 788 | /* Strip off the Ethernet header. */ |
788 | m_adj(m, ehlen); | | 789 | m_adj(m, ehlen); |
789 | | | 790 | |
790 | switch (etype) { | | 791 | switch (etype) { |
791 | #ifdef INET | | 792 | #ifdef INET |
792 | case ETHERTYPE_IP: | | 793 | case ETHERTYPE_IP: |
793 | #ifdef GATEWAY | | 794 | #ifdef GATEWAY |
794 | if (ipflow_fastforward(m)) | | 795 | if (ipflow_fastforward(m)) |
795 | return; | | 796 | return; |
796 | #endif | | 797 | #endif |
797 | pktq = ip_pktq; | | 798 | pktq = ip_pktq; |
798 | break; | | 799 | break; |
799 | | | 800 | |
800 | case ETHERTYPE_ARP: | | 801 | case ETHERTYPE_ARP: |
801 | isr = NETISR_ARP; | | 802 | isr = NETISR_ARP; |
802 | inq = &arpintrq; | | 803 | inq = &arpintrq; |
803 | break; | | 804 | break; |
804 | | | 805 | |
805 | case ETHERTYPE_REVARP: | | 806 | case ETHERTYPE_REVARP: |
806 | revarpinput(m); /* XXX queue? */ | | 807 | revarpinput(m); /* XXX queue? */ |
807 | return; | | 808 | return; |
808 | #endif | | 809 | #endif |
809 | #ifdef INET6 | | 810 | #ifdef INET6 |
810 | case ETHERTYPE_IPV6: | | 811 | case ETHERTYPE_IPV6: |
811 | if (__predict_false(!in6_present)) { | | 812 | if (__predict_false(!in6_present)) { |
812 | m_freem(m); | | 813 | m_freem(m); |
813 | return; | | 814 | return; |
814 | } | | 815 | } |
815 | #ifdef GATEWAY | | 816 | #ifdef GATEWAY |
816 | if (ip6flow_fastforward(&m)) | | 817 | if (ip6flow_fastforward(&m)) |
817 | return; | | 818 | return; |
818 | #endif | | 819 | #endif |
819 | pktq = ip6_pktq; | | 820 | pktq = ip6_pktq; |
820 | break; | | 821 | break; |
821 | #endif | | 822 | #endif |
822 | #ifdef NETATALK | | 823 | #ifdef NETATALK |
823 | case ETHERTYPE_ATALK: | | 824 | case ETHERTYPE_ATALK: |
824 | isr = NETISR_ATALK; | | 825 | isr = NETISR_ATALK; |
825 | inq = &atintrq1; | | 826 | inq = &atintrq1; |
826 | break; | | 827 | break; |
827 | case ETHERTYPE_AARP: | | 828 | case ETHERTYPE_AARP: |
828 | /* probably this should be done with a NETISR as well */ | | 829 | /* probably this should be done with a NETISR as well */ |
829 | aarpinput(ifp, m); /* XXX */ | | 830 | aarpinput(ifp, m); /* XXX */ |
830 | return; | | 831 | return; |
831 | #endif /* NETATALK */ | | 832 | #endif /* NETATALK */ |
832 | #ifdef MPLS | | 833 | #ifdef MPLS |
833 | case ETHERTYPE_MPLS: | | 834 | case ETHERTYPE_MPLS: |
834 | isr = NETISR_MPLS; | | 835 | isr = NETISR_MPLS; |
835 | inq = &mplsintrq; | | 836 | inq = &mplsintrq; |
836 | break; | | 837 | break; |
837 | #endif | | 838 | #endif |
838 | default: | | 839 | default: |
839 | m_freem(m); | | 840 | m_freem(m); |
840 | return; | | 841 | return; |
841 | } | | 842 | } |
842 | } else { | | 843 | } else { |
843 | #if defined (LLC) || defined (NETATALK) | | 844 | #if defined (LLC) || defined (NETATALK) |
844 | if (m->m_len < ehlen + sizeof(struct llc)) { | | 845 | if (m->m_len < ehlen + sizeof(struct llc)) { |
845 | goto dropanyway; | | 846 | goto dropanyway; |
846 | } | | 847 | } |
847 | l = (struct llc *)(eh+1); | | 848 | l = (struct llc *)(eh+1); |
848 | switch (l->llc_dsap) { | | 849 | switch (l->llc_dsap) { |
849 | #ifdef NETATALK | | 850 | #ifdef NETATALK |
850 | case LLC_SNAP_LSAP: | | 851 | case LLC_SNAP_LSAP: |
851 | switch (l->llc_control) { | | 852 | switch (l->llc_control) { |
852 | case LLC_UI: | | 853 | case LLC_UI: |
853 | if (l->llc_ssap != LLC_SNAP_LSAP) { | | 854 | if (l->llc_ssap != LLC_SNAP_LSAP) { |
854 | goto dropanyway; | | 855 | goto dropanyway; |
855 | } | | 856 | } |
856 | | | 857 | |
857 | if (memcmp(&(l->llc_snap_org_code)[0], | | 858 | if (memcmp(&(l->llc_snap_org_code)[0], |
858 | at_org_code, sizeof(at_org_code)) == 0 && | | 859 | at_org_code, sizeof(at_org_code)) == 0 && |
859 | ntohs(l->llc_snap_ether_type) == | | 860 | ntohs(l->llc_snap_ether_type) == |
860 | ETHERTYPE_ATALK) { | | 861 | ETHERTYPE_ATALK) { |
861 | inq = &atintrq2; | | 862 | inq = &atintrq2; |
862 | m_adj(m, sizeof(struct ether_header) | | 863 | m_adj(m, sizeof(struct ether_header) |
863 | + sizeof(struct llc)); | | 864 | + sizeof(struct llc)); |
864 | isr = NETISR_ATALK; | | 865 | isr = NETISR_ATALK; |
865 | break; | | 866 | break; |
866 | } | | 867 | } |
867 | | | 868 | |
868 | if (memcmp(&(l->llc_snap_org_code)[0], | | 869 | if (memcmp(&(l->llc_snap_org_code)[0], |
869 | aarp_org_code, | | 870 | aarp_org_code, |
870 | sizeof(aarp_org_code)) == 0 && | | 871 | sizeof(aarp_org_code)) == 0 && |
871 | ntohs(l->llc_snap_ether_type) == | | 872 | ntohs(l->llc_snap_ether_type) == |
872 | ETHERTYPE_AARP) { | | 873 | ETHERTYPE_AARP) { |
873 | m_adj( m, sizeof(struct ether_header) | | 874 | m_adj( m, sizeof(struct ether_header) |
874 | + sizeof(struct llc)); | | 875 | + sizeof(struct llc)); |
875 | aarpinput(ifp, m); /* XXX */ | | 876 | aarpinput(ifp, m); /* XXX */ |
876 | return; | | 877 | return; |
877 | } | | 878 | } |
878 | | | 879 | |
879 | default: | | 880 | default: |
880 | goto dropanyway; | | 881 | goto dropanyway; |
881 | } | | 882 | } |
882 | break; | | 883 | break; |
883 | #endif | | 884 | #endif |
884 | dropanyway: | | 885 | dropanyway: |
885 | default: | | 886 | default: |
886 | m_freem(m); | | 887 | m_freem(m); |
887 | return; | | 888 | return; |
888 | } | | 889 | } |
889 | #else /* LLC || NETATALK */ | | 890 | #else /* LLC || NETATALK */ |
890 | m_freem(m); | | 891 | m_freem(m); |
891 | return; | | 892 | return; |
892 | #endif /* LLC || NETATALK */ | | 893 | #endif /* LLC || NETATALK */ |
893 | } | | 894 | } |
894 | | | 895 | |
895 | if (__predict_true(pktq)) { | | 896 | if (__predict_true(pktq)) { |
896 | #ifdef NET_MPSAFE | | 897 | #ifdef NET_MPSAFE |
897 | const u_int h = curcpu()->ci_index; | | 898 | const u_int h = curcpu()->ci_index; |
898 | #else | | 899 | #else |
899 | const uint32_t h = pktq_rps_hash(m); | | 900 | const uint32_t h = pktq_rps_hash(m); |
900 | #endif | | 901 | #endif |
901 | if (__predict_false(!pktq_enqueue(pktq, m, h))) { | | 902 | if (__predict_false(!pktq_enqueue(pktq, m, h))) { |
902 | m_freem(m); | | 903 | m_freem(m); |
903 | } | | 904 | } |
904 | return; | | 905 | return; |
905 | } | | 906 | } |
906 | | | 907 | |
907 | if (__predict_false(!inq)) { | | 908 | if (__predict_false(!inq)) { |
908 | /* Should not happen. */ | | 909 | /* Should not happen. */ |
909 | m_freem(m); | | 910 | m_freem(m); |
910 | return; | | 911 | return; |
911 | } | | 912 | } |
912 | | | 913 | |
913 | IFQ_LOCK(inq); | | 914 | IFQ_LOCK(inq); |
914 | if (IF_QFULL(inq)) { | | 915 | if (IF_QFULL(inq)) { |
915 | IF_DROP(inq); | | 916 | IF_DROP(inq); |
916 | IFQ_UNLOCK(inq); | | 917 | IFQ_UNLOCK(inq); |
917 | m_freem(m); | | 918 | m_freem(m); |
918 | } else { | | 919 | } else { |
919 | IF_ENQUEUE(inq, m); | | 920 | IF_ENQUEUE(inq, m); |
920 | IFQ_UNLOCK(inq); | | 921 | IFQ_UNLOCK(inq); |
921 | schednetisr(isr); | | 922 | schednetisr(isr); |
922 | } | | 923 | } |
923 | } | | 924 | } |
924 | | | 925 | |
925 | /* | | 926 | /* |
926 | * Convert Ethernet address to printable (loggable) representation. | | 927 | * Convert Ethernet address to printable (loggable) representation. |
927 | */ | | 928 | */ |
928 | char * | | 929 | char * |
929 | ether_sprintf(const u_char *ap) | | 930 | ether_sprintf(const u_char *ap) |
930 | { | | 931 | { |
931 | static char etherbuf[3 * ETHER_ADDR_LEN]; | | 932 | static char etherbuf[3 * ETHER_ADDR_LEN]; |
932 | return ether_snprintf(etherbuf, sizeof(etherbuf), ap); | | 933 | return ether_snprintf(etherbuf, sizeof(etherbuf), ap); |
933 | } | | 934 | } |
934 | | | 935 | |
935 | char * | | 936 | char * |
936 | ether_snprintf(char *buf, size_t len, const u_char *ap) | | 937 | ether_snprintf(char *buf, size_t len, const u_char *ap) |
937 | { | | 938 | { |
938 | char *cp = buf; | | 939 | char *cp = buf; |
939 | size_t i; | | 940 | size_t i; |
940 | | | 941 | |
941 | for (i = 0; i < len / 3; i++) { | | 942 | for (i = 0; i < len / 3; i++) { |
942 | *cp++ = hexdigits[*ap >> 4]; | | 943 | *cp++ = hexdigits[*ap >> 4]; |
943 | *cp++ = hexdigits[*ap++ & 0xf]; | | 944 | *cp++ = hexdigits[*ap++ & 0xf]; |
944 | *cp++ = ':'; | | 945 | *cp++ = ':'; |
945 | } | | 946 | } |
946 | *--cp = '\0'; | | 947 | *--cp = '\0'; |
947 | return buf; | | 948 | return buf; |
948 | } | | 949 | } |
949 | | | 950 | |
950 | /* | | 951 | /* |
951 | * Perform common duties while attaching to interface list | | 952 | * Perform common duties while attaching to interface list |
952 | */ | | 953 | */ |
953 | void | | 954 | void |
954 | ether_ifattach(struct ifnet *ifp, const uint8_t *lla) | | 955 | ether_ifattach(struct ifnet *ifp, const uint8_t *lla) |
955 | { | | 956 | { |
956 | struct ethercom *ec = (struct ethercom *)ifp; | | 957 | struct ethercom *ec = (struct ethercom *)ifp; |
957 | | | 958 | |
958 | ifp->if_type = IFT_ETHER; | | 959 | ifp->if_type = IFT_ETHER; |
959 | ifp->if_hdrlen = ETHER_HDR_LEN; | | 960 | ifp->if_hdrlen = ETHER_HDR_LEN; |
960 | ifp->if_dlt = DLT_EN10MB; | | 961 | ifp->if_dlt = DLT_EN10MB; |
961 | ifp->if_mtu = ETHERMTU; | | 962 | ifp->if_mtu = ETHERMTU; |
962 | ifp->if_output = ether_output; | | 963 | ifp->if_output = ether_output; |
963 | ifp->_if_input = ether_input; | | 964 | ifp->_if_input = ether_input; |
964 | if (ifp->if_baudrate == 0) | | 965 | if (ifp->if_baudrate == 0) |
965 | ifp->if_baudrate = IF_Mbps(10); /* just a default */ | | 966 | ifp->if_baudrate = IF_Mbps(10); /* just a default */ |
966 | | | 967 | |
967 | if (lla != NULL) | | 968 | if (lla != NULL) |
968 | if_set_sadl(ifp, lla, ETHER_ADDR_LEN, !ETHER_IS_LOCAL(lla)); | | 969 | if_set_sadl(ifp, lla, ETHER_ADDR_LEN, !ETHER_IS_LOCAL(lla)); |
969 | | | 970 | |
970 | LIST_INIT(&ec->ec_multiaddrs); | | 971 | LIST_INIT(&ec->ec_multiaddrs); |
971 | ec->ec_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NET); | | 972 | ec->ec_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NET); |
972 | ifp->if_broadcastaddr = etherbroadcastaddr; | | 973 | ifp->if_broadcastaddr = etherbroadcastaddr; |
973 | bpf_attach(ifp, DLT_EN10MB, sizeof(struct ether_header)); | | 974 | bpf_attach(ifp, DLT_EN10MB, sizeof(struct ether_header)); |
974 | #ifdef MBUFTRACE | | 975 | #ifdef MBUFTRACE |
975 | strlcpy(ec->ec_tx_mowner.mo_name, ifp->if_xname, | | 976 | strlcpy(ec->ec_tx_mowner.mo_name, ifp->if_xname, |
976 | sizeof(ec->ec_tx_mowner.mo_name)); | | 977 | sizeof(ec->ec_tx_mowner.mo_name)); |
977 | strlcpy(ec->ec_tx_mowner.mo_descr, "tx", | | 978 | strlcpy(ec->ec_tx_mowner.mo_descr, "tx", |
978 | sizeof(ec->ec_tx_mowner.mo_descr)); | | 979 | sizeof(ec->ec_tx_mowner.mo_descr)); |
979 | strlcpy(ec->ec_rx_mowner.mo_name, ifp->if_xname, | | 980 | strlcpy(ec->ec_rx_mowner.mo_name, ifp->if_xname, |
980 | sizeof(ec->ec_rx_mowner.mo_name)); | | 981 | sizeof(ec->ec_rx_mowner.mo_name)); |
981 | strlcpy(ec->ec_rx_mowner.mo_descr, "rx", | | 982 | strlcpy(ec->ec_rx_mowner.mo_descr, "rx", |
982 | sizeof(ec->ec_rx_mowner.mo_descr)); | | 983 | sizeof(ec->ec_rx_mowner.mo_descr)); |
983 | MOWNER_ATTACH(&ec->ec_tx_mowner); | | 984 | MOWNER_ATTACH(&ec->ec_tx_mowner); |
984 | MOWNER_ATTACH(&ec->ec_rx_mowner); | | 985 | MOWNER_ATTACH(&ec->ec_rx_mowner); |
985 | ifp->if_mowner = &ec->ec_tx_mowner; | | 986 | ifp->if_mowner = &ec->ec_tx_mowner; |
986 | #endif | | 987 | #endif |
987 | } | | 988 | } |
988 | | | 989 | |
989 | void | | 990 | void |
990 | ether_ifdetach(struct ifnet *ifp) | | 991 | ether_ifdetach(struct ifnet *ifp) |
991 | { | | 992 | { |
992 | struct ethercom *ec = (void *) ifp; | | 993 | struct ethercom *ec = (void *) ifp; |
993 | struct ether_multi *enm; | | 994 | struct ether_multi *enm; |
994 | | | 995 | |
995 | /* | | 996 | /* |
996 | * Prevent further calls to ioctl (for example turning off | | 997 | * Prevent further calls to ioctl (for example turning off |
997 | * promiscuous mode from the bridge code), which eventually can | | 998 | * promiscuous mode from the bridge code), which eventually can |
998 | * call if_init() which can cause panics because the interface | | 999 | * call if_init() which can cause panics because the interface |
999 | * is in the process of being detached. Return device not configured | | 1000 | * is in the process of being detached. Return device not configured |
1000 | * instead. | | 1001 | * instead. |
1001 | */ | | 1002 | */ |
1002 | ifp->if_ioctl = (int (*)(struct ifnet *, u_long, void *))enxio; | | 1003 | ifp->if_ioctl = (int (*)(struct ifnet *, u_long, void *))enxio; |
1003 | | | 1004 | |
1004 | #if NBRIDGE > 0 | | 1005 | #if NBRIDGE > 0 |
1005 | if (ifp->if_bridge) | | 1006 | if (ifp->if_bridge) |
1006 | bridge_ifdetach(ifp); | | 1007 | bridge_ifdetach(ifp); |
1007 | #endif | | 1008 | #endif |
1008 | bpf_detach(ifp); | | 1009 | bpf_detach(ifp); |
1009 | #if NVLAN > 0 | | 1010 | #if NVLAN > 0 |
1010 | if (ec->ec_nvlans) | | 1011 | if (ec->ec_nvlans) |
1011 | vlan_ifdetach(ifp); | | 1012 | vlan_ifdetach(ifp); |
1012 | #endif | | 1013 | #endif |
1013 | | | 1014 | |
1014 | ETHER_LOCK(ec); | | 1015 | ETHER_LOCK(ec); |
1015 | while ((enm = LIST_FIRST(&ec->ec_multiaddrs)) != NULL) { | | 1016 | while ((enm = LIST_FIRST(&ec->ec_multiaddrs)) != NULL) { |
1016 | LIST_REMOVE(enm, enm_list); | | 1017 | LIST_REMOVE(enm, enm_list); |
1017 | kmem_free(enm, sizeof(*enm)); | | 1018 | kmem_free(enm, sizeof(*enm)); |
1018 | ec->ec_multicnt--; | | 1019 | ec->ec_multicnt--; |
1019 | } | | 1020 | } |
1020 | ETHER_UNLOCK(ec); | | 1021 | ETHER_UNLOCK(ec); |
1021 | | | 1022 | |
1022 | mutex_obj_free(ec->ec_lock); | | 1023 | mutex_obj_free(ec->ec_lock); |
1023 | | | 1024 | |
1024 | ifp->if_mowner = NULL; | | 1025 | ifp->if_mowner = NULL; |
1025 | MOWNER_DETACH(&ec->ec_rx_mowner); | | 1026 | MOWNER_DETACH(&ec->ec_rx_mowner); |
1026 | MOWNER_DETACH(&ec->ec_tx_mowner); | | 1027 | MOWNER_DETACH(&ec->ec_tx_mowner); |
1027 | } | | 1028 | } |
1028 | | | 1029 | |
1029 | #if 0 | | 1030 | #if 0 |
1030 | /* | | 1031 | /* |
1031 | * This is for reference. We have a table-driven version | | 1032 | * This is for reference. We have a table-driven version |
1032 | * of the little-endian crc32 generator, which is faster | | 1033 | * of the little-endian crc32 generator, which is faster |
1033 | * than the double-loop. | | 1034 | * than the double-loop. |
1034 | */ | | 1035 | */ |
1035 | uint32_t | | 1036 | uint32_t |
1036 | ether_crc32_le(const uint8_t *buf, size_t len) | | 1037 | ether_crc32_le(const uint8_t *buf, size_t len) |
1037 | { | | 1038 | { |
1038 | uint32_t c, crc, carry; | | 1039 | uint32_t c, crc, carry; |
1039 | size_t i, j; | | 1040 | size_t i, j; |
1040 | | | 1041 | |
1041 | crc = 0xffffffffU; /* initial value */ | | 1042 | crc = 0xffffffffU; /* initial value */ |
1042 | | | 1043 | |
1043 | for (i = 0; i < len; i++) { | | 1044 | for (i = 0; i < len; i++) { |
1044 | c = buf[i]; | | 1045 | c = buf[i]; |
1045 | for (j = 0; j < 8; j++) { | | 1046 | for (j = 0; j < 8; j++) { |
1046 | carry = ((crc & 0x01) ? 1 : 0) ^ (c & 0x01); | | 1047 | carry = ((crc & 0x01) ? 1 : 0) ^ (c & 0x01); |
1047 | crc >>= 1; | | 1048 | crc >>= 1; |
1048 | c >>= 1; | | 1049 | c >>= 1; |
1049 | if (carry) | | 1050 | if (carry) |
1050 | crc = (crc ^ ETHER_CRC_POLY_LE); | | 1051 | crc = (crc ^ ETHER_CRC_POLY_LE); |
1051 | } | | 1052 | } |
1052 | } | | 1053 | } |
1053 | | | 1054 | |
1054 | return (crc); | | 1055 | return (crc); |
1055 | } | | 1056 | } |
1056 | #else | | 1057 | #else |
1057 | uint32_t | | 1058 | uint32_t |
1058 | ether_crc32_le(const uint8_t *buf, size_t len) | | 1059 | ether_crc32_le(const uint8_t *buf, size_t len) |
1059 | { | | 1060 | { |
1060 | static const uint32_t crctab[] = { | | 1061 | static const uint32_t crctab[] = { |
1061 | 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, | | 1062 | 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, |
1062 | 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, | | 1063 | 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, |
1063 | 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, | | 1064 | 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, |
1064 | 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c | | 1065 | 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c |
1065 | }; | | 1066 | }; |
1066 | uint32_t crc; | | 1067 | uint32_t crc; |
1067 | size_t i; | | 1068 | size_t i; |
1068 | | | 1069 | |
1069 | crc = 0xffffffffU; /* initial value */ | | 1070 | crc = 0xffffffffU; /* initial value */ |
1070 | | | 1071 | |
1071 | for (i = 0; i < len; i++) { | | 1072 | for (i = 0; i < len; i++) { |
1072 | crc ^= buf[i]; | | 1073 | crc ^= buf[i]; |
1073 | crc = (crc >> 4) ^ crctab[crc & 0xf]; | | 1074 | crc = (crc >> 4) ^ crctab[crc & 0xf]; |
1074 | crc = (crc >> 4) ^ crctab[crc & 0xf]; | | 1075 | crc = (crc >> 4) ^ crctab[crc & 0xf]; |
1075 | } | | 1076 | } |
1076 | | | 1077 | |
1077 | return (crc); | | 1078 | return (crc); |
1078 | } | | 1079 | } |
1079 | #endif | | 1080 | #endif |
1080 | | | 1081 | |
1081 | uint32_t | | 1082 | uint32_t |
1082 | ether_crc32_be(const uint8_t *buf, size_t len) | | 1083 | ether_crc32_be(const uint8_t *buf, size_t len) |
1083 | { | | 1084 | { |
1084 | uint32_t c, crc, carry; | | 1085 | uint32_t c, crc, carry; |
1085 | size_t i, j; | | 1086 | size_t i, j; |
1086 | | | 1087 | |
1087 | crc = 0xffffffffU; /* initial value */ | | 1088 | crc = 0xffffffffU; /* initial value */ |
1088 | | | 1089 | |
1089 | for (i = 0; i < len; i++) { | | 1090 | for (i = 0; i < len; i++) { |
1090 | c = buf[i]; | | 1091 | c = buf[i]; |
1091 | for (j = 0; j < 8; j++) { | | 1092 | for (j = 0; j < 8; j++) { |
1092 | carry = ((crc & 0x80000000U) ? 1 : 0) ^ (c & 0x01); | | 1093 | carry = ((crc & 0x80000000U) ? 1 : 0) ^ (c & 0x01); |
1093 | crc <<= 1; | | 1094 | crc <<= 1; |
1094 | c >>= 1; | | 1095 | c >>= 1; |
1095 | if (carry) | | 1096 | if (carry) |
1096 | crc = (crc ^ ETHER_CRC_POLY_BE) | carry; | | 1097 | crc = (crc ^ ETHER_CRC_POLY_BE) | carry; |
1097 | } | | 1098 | } |
1098 | } | | 1099 | } |
1099 | | | 1100 | |
1100 | return (crc); | | 1101 | return (crc); |
1101 | } | | 1102 | } |
1102 | | | 1103 | |
1103 | #ifdef INET | | 1104 | #ifdef INET |
1104 | const uint8_t ether_ipmulticast_min[ETHER_ADDR_LEN] = | | 1105 | const uint8_t ether_ipmulticast_min[ETHER_ADDR_LEN] = |
1105 | { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 }; | | 1106 | { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 }; |
1106 | const uint8_t ether_ipmulticast_max[ETHER_ADDR_LEN] = | | 1107 | const uint8_t ether_ipmulticast_max[ETHER_ADDR_LEN] = |
1107 | { 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xff }; | | 1108 | { 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xff }; |
1108 | #endif | | 1109 | #endif |
1109 | #ifdef INET6 | | 1110 | #ifdef INET6 |
1110 | const uint8_t ether_ip6multicast_min[ETHER_ADDR_LEN] = | | 1111 | const uint8_t ether_ip6multicast_min[ETHER_ADDR_LEN] = |
1111 | { 0x33, 0x33, 0x00, 0x00, 0x00, 0x00 }; | | 1112 | { 0x33, 0x33, 0x00, 0x00, 0x00, 0x00 }; |
1112 | const uint8_t ether_ip6multicast_max[ETHER_ADDR_LEN] = | | 1113 | const uint8_t ether_ip6multicast_max[ETHER_ADDR_LEN] = |
1113 | { 0x33, 0x33, 0xff, 0xff, 0xff, 0xff }; | | 1114 | { 0x33, 0x33, 0xff, 0xff, 0xff, 0xff }; |
1114 | #endif | | 1115 | #endif |
1115 | | | 1116 | |
1116 | /* | | 1117 | /* |
1117 | * ether_aton implementation, not using a static buffer. | | 1118 | * ether_aton implementation, not using a static buffer. |
1118 | */ | | 1119 | */ |
1119 | int | | 1120 | int |
1120 | ether_aton_r(u_char *dest, size_t len, const char *str) | | 1121 | ether_aton_r(u_char *dest, size_t len, const char *str) |
1121 | { | | 1122 | { |
1122 | const u_char *cp = (const void *)str; | | 1123 | const u_char *cp = (const void *)str; |
1123 | u_char *ep; | | 1124 | u_char *ep; |
1124 | | | 1125 | |
1125 | #define atox(c) (((c) <= '9') ? ((c) - '0') : ((toupper(c) - 'A') + 10)) | | 1126 | #define atox(c) (((c) <= '9') ? ((c) - '0') : ((toupper(c) - 'A') + 10)) |
1126 | | | 1127 | |
1127 | if (len < ETHER_ADDR_LEN) | | 1128 | if (len < ETHER_ADDR_LEN) |
1128 | return ENOSPC; | | 1129 | return ENOSPC; |
1129 | | | 1130 | |
1130 | ep = dest + ETHER_ADDR_LEN; | | 1131 | ep = dest + ETHER_ADDR_LEN; |
1131 | | | 1132 | |
1132 | while (*cp) { | | 1133 | while (*cp) { |
1133 | if (!isxdigit(*cp)) | | 1134 | if (!isxdigit(*cp)) |
1134 | return EINVAL; | | 1135 | return EINVAL; |
1135 | | | 1136 | |
1136 | *dest = atox(*cp); | | 1137 | *dest = atox(*cp); |
1137 | cp++; | | 1138 | cp++; |
1138 | if (isxdigit(*cp)) { | | 1139 | if (isxdigit(*cp)) { |
1139 | *dest = (*dest << 4) | atox(*cp); | | 1140 | *dest = (*dest << 4) | atox(*cp); |
1140 | cp++; | | 1141 | cp++; |
1141 | } | | 1142 | } |
1142 | dest++; | | 1143 | dest++; |
1143 | | | 1144 | |
1144 | if (dest == ep) | | 1145 | if (dest == ep) |
1145 | return (*cp == '\0') ? 0 : ENAMETOOLONG; | | 1146 | return (*cp == '\0') ? 0 : ENAMETOOLONG; |
1146 | | | 1147 | |
1147 | switch (*cp) { | | 1148 | switch (*cp) { |
1148 | case ':': | | 1149 | case ':': |
1149 | case '-': | | 1150 | case '-': |
1150 | case '.': | | 1151 | case '.': |
1151 | cp++; | | 1152 | cp++; |
1152 | break; | | 1153 | break; |
1153 | } | | 1154 | } |
1154 | } | | 1155 | } |
1155 | return ENOBUFS; | | 1156 | return ENOBUFS; |
1156 | } | | 1157 | } |
1157 | | | 1158 | |
1158 | /* | | 1159 | /* |
1159 | * Convert a sockaddr into an Ethernet address or range of Ethernet | | 1160 | * Convert a sockaddr into an Ethernet address or range of Ethernet |
1160 | * addresses. | | 1161 | * addresses. |
1161 | */ | | 1162 | */ |
1162 | int | | 1163 | int |
1163 | ether_multiaddr(const struct sockaddr *sa, uint8_t addrlo[ETHER_ADDR_LEN], | | 1164 | ether_multiaddr(const struct sockaddr *sa, uint8_t addrlo[ETHER_ADDR_LEN], |
1164 | uint8_t addrhi[ETHER_ADDR_LEN]) | | 1165 | uint8_t addrhi[ETHER_ADDR_LEN]) |
1165 | { | | 1166 | { |
1166 | #ifdef INET | | 1167 | #ifdef INET |
1167 | const struct sockaddr_in *sin; | | 1168 | const struct sockaddr_in *sin; |
1168 | #endif /* INET */ | | 1169 | #endif /* INET */ |
1169 | #ifdef INET6 | | 1170 | #ifdef INET6 |
1170 | const struct sockaddr_in6 *sin6; | | 1171 | const struct sockaddr_in6 *sin6; |
1171 | #endif /* INET6 */ | | 1172 | #endif /* INET6 */ |
1172 | | | 1173 | |
1173 | switch (sa->sa_family) { | | 1174 | switch (sa->sa_family) { |
1174 | | | 1175 | |
1175 | case AF_UNSPEC: | | 1176 | case AF_UNSPEC: |
1176 | memcpy(addrlo, sa->sa_data, ETHER_ADDR_LEN); | | 1177 | memcpy(addrlo, sa->sa_data, ETHER_ADDR_LEN); |
1177 | memcpy(addrhi, addrlo, ETHER_ADDR_LEN); | | 1178 | memcpy(addrhi, addrlo, ETHER_ADDR_LEN); |
1178 | break; | | 1179 | break; |
1179 | | | 1180 | |
1180 | #ifdef INET | | 1181 | #ifdef INET |
1181 | case AF_INET: | | 1182 | case AF_INET: |
1182 | sin = satocsin(sa); | | 1183 | sin = satocsin(sa); |
1183 | if (sin->sin_addr.s_addr == INADDR_ANY) { | | 1184 | if (sin->sin_addr.s_addr == INADDR_ANY) { |
1184 | /* | | 1185 | /* |
1185 | * An IP address of INADDR_ANY means listen to | | 1186 | * An IP address of INADDR_ANY means listen to |
1186 | * or stop listening to all of the Ethernet | | 1187 | * or stop listening to all of the Ethernet |
1187 | * multicast addresses used for IP. | | 1188 | * multicast addresses used for IP. |
1188 | * (This is for the sake of IP multicast routers.) | | 1189 | * (This is for the sake of IP multicast routers.) |
1189 | */ | | 1190 | */ |
1190 | memcpy(addrlo, ether_ipmulticast_min, ETHER_ADDR_LEN); | | 1191 | memcpy(addrlo, ether_ipmulticast_min, ETHER_ADDR_LEN); |
1191 | memcpy(addrhi, ether_ipmulticast_max, ETHER_ADDR_LEN); | | 1192 | memcpy(addrhi, ether_ipmulticast_max, ETHER_ADDR_LEN); |
1192 | } else { | | 1193 | } else { |
1193 | ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo); | | 1194 | ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo); |
1194 | memcpy(addrhi, addrlo, ETHER_ADDR_LEN); | | 1195 | memcpy(addrhi, addrlo, ETHER_ADDR_LEN); |
1195 | } | | 1196 | } |
1196 | break; | | 1197 | break; |
1197 | #endif | | 1198 | #endif |
1198 | #ifdef INET6 | | 1199 | #ifdef INET6 |
1199 | case AF_INET6: | | 1200 | case AF_INET6: |
1200 | sin6 = satocsin6(sa); | | 1201 | sin6 = satocsin6(sa); |
1201 | if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { | | 1202 | if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { |
1202 | /* | | 1203 | /* |
1203 | * An IP6 address of 0 means listen to or stop | | 1204 | * An IP6 address of 0 means listen to or stop |
1204 | * listening to all of the Ethernet multicast | | 1205 | * listening to all of the Ethernet multicast |
1205 | * address used for IP6. | | 1206 | * address used for IP6. |
1206 | * (This is used for multicast routers.) | | 1207 | * (This is used for multicast routers.) |
1207 | */ | | 1208 | */ |
1208 | memcpy(addrlo, ether_ip6multicast_min, ETHER_ADDR_LEN); | | 1209 | memcpy(addrlo, ether_ip6multicast_min, ETHER_ADDR_LEN); |
1209 | memcpy(addrhi, ether_ip6multicast_max, ETHER_ADDR_LEN); | | 1210 | memcpy(addrhi, ether_ip6multicast_max, ETHER_ADDR_LEN); |
1210 | } else { | | 1211 | } else { |
1211 | ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, addrlo); | | 1212 | ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, addrlo); |
1212 | memcpy(addrhi, addrlo, ETHER_ADDR_LEN); | | 1213 | memcpy(addrhi, addrlo, ETHER_ADDR_LEN); |
1213 | } | | 1214 | } |
1214 | break; | | 1215 | break; |
1215 | #endif | | 1216 | #endif |
1216 | | | 1217 | |
1217 | default: | | 1218 | default: |
1218 | return EAFNOSUPPORT; | | 1219 | return EAFNOSUPPORT; |
1219 | } | | 1220 | } |
1220 | return 0; | | 1221 | return 0; |
1221 | } | | 1222 | } |
1222 | | | 1223 | |
1223 | /* | | 1224 | /* |
1224 | * Add an Ethernet multicast address or range of addresses to the list for a | | 1225 | * Add an Ethernet multicast address or range of addresses to the list for a |
1225 | * given interface. | | 1226 | * given interface. |
1226 | */ | | 1227 | */ |
1227 | int | | 1228 | int |
1228 | ether_addmulti(const struct sockaddr *sa, struct ethercom *ec) | | 1229 | ether_addmulti(const struct sockaddr *sa, struct ethercom *ec) |
1229 | { | | 1230 | { |
1230 | struct ether_multi *enm, *_enm; | | 1231 | struct ether_multi *enm, *_enm; |
1231 | u_char addrlo[ETHER_ADDR_LEN]; | | 1232 | u_char addrlo[ETHER_ADDR_LEN]; |
1232 | u_char addrhi[ETHER_ADDR_LEN]; | | 1233 | u_char addrhi[ETHER_ADDR_LEN]; |
1233 | int error = 0; | | 1234 | int error = 0; |
1234 | | | 1235 | |
1235 | /* Allocate out of lock */ | | 1236 | /* Allocate out of lock */ |
1236 | enm = kmem_alloc(sizeof(*enm), KM_SLEEP); | | 1237 | enm = kmem_alloc(sizeof(*enm), KM_SLEEP); |
1237 | | | 1238 | |
1238 | ETHER_LOCK(ec); | | 1239 | ETHER_LOCK(ec); |
1239 | error = ether_multiaddr(sa, addrlo, addrhi); | | 1240 | error = ether_multiaddr(sa, addrlo, addrhi); |
1240 | if (error != 0) | | 1241 | if (error != 0) |
1241 | goto out; | | 1242 | goto out; |
1242 | | | 1243 | |
1243 | /* | | 1244 | /* |
1244 | * Verify that we have valid Ethernet multicast addresses. | | 1245 | * Verify that we have valid Ethernet multicast addresses. |
1245 | */ | | 1246 | */ |
1246 | if (!ETHER_IS_MULTICAST(addrlo) || !ETHER_IS_MULTICAST(addrhi)) { | | 1247 | if (!ETHER_IS_MULTICAST(addrlo) || !ETHER_IS_MULTICAST(addrhi)) { |
1247 | error = EINVAL; | | 1248 | error = EINVAL; |
1248 | goto out; | | 1249 | goto out; |
1249 | } | | 1250 | } |
1250 | | | 1251 | |
1251 | /* | | 1252 | /* |
1252 | * See if the address range is already in the list. | | 1253 | * See if the address range is already in the list. |
1253 | */ | | 1254 | */ |
1254 | ETHER_LOOKUP_MULTI(addrlo, addrhi, ec, _enm); | | 1255 | ETHER_LOOKUP_MULTI(addrlo, addrhi, ec, _enm); |
1255 | if (_enm != NULL) { | | 1256 | if (_enm != NULL) { |
1256 | /* | | 1257 | /* |
1257 | * Found it; just increment the reference count. | | 1258 | * Found it; just increment the reference count. |
1258 | */ | | 1259 | */ |
1259 | ++_enm->enm_refcount; | | 1260 | ++_enm->enm_refcount; |
1260 | error = 0; | | 1261 | error = 0; |
1261 | goto out; | | 1262 | goto out; |
1262 | } | | 1263 | } |
1263 | | | 1264 | |
1264 | /* | | 1265 | /* |
1265 | * Link a new multicast record into the interface's multicast list. | | 1266 | * Link a new multicast record into the interface's multicast list. |
1266 | */ | | 1267 | */ |
1267 | memcpy(enm->enm_addrlo, addrlo, ETHER_ADDR_LEN); | | 1268 | memcpy(enm->enm_addrlo, addrlo, ETHER_ADDR_LEN); |
1268 | memcpy(enm->enm_addrhi, addrhi, ETHER_ADDR_LEN); | | 1269 | memcpy(enm->enm_addrhi, addrhi, ETHER_ADDR_LEN); |
1269 | enm->enm_refcount = 1; | | 1270 | enm->enm_refcount = 1; |
1270 | LIST_INSERT_HEAD(&ec->ec_multiaddrs, enm, enm_list); | | 1271 | LIST_INSERT_HEAD(&ec->ec_multiaddrs, enm, enm_list); |
1271 | ec->ec_multicnt++; | | 1272 | ec->ec_multicnt++; |
1272 | | | 1273 | |
1273 | /* | | 1274 | /* |
1274 | * Return ENETRESET to inform the driver that the list has changed | | 1275 | * Return ENETRESET to inform the driver that the list has changed |
1275 | * and its reception filter should be adjusted accordingly. | | 1276 | * and its reception filter should be adjusted accordingly. |
1276 | */ | | 1277 | */ |
1277 | error = ENETRESET; | | 1278 | error = ENETRESET; |
1278 | enm = NULL; | | 1279 | enm = NULL; |
1279 | | | 1280 | |
1280 | out: | | 1281 | out: |
1281 | ETHER_UNLOCK(ec); | | 1282 | ETHER_UNLOCK(ec); |
1282 | if (enm != NULL) | | 1283 | if (enm != NULL) |
1283 | kmem_free(enm, sizeof(*enm)); | | 1284 | kmem_free(enm, sizeof(*enm)); |
1284 | return error; | | 1285 | return error; |
1285 | } | | 1286 | } |
1286 | | | 1287 | |
1287 | /* | | 1288 | /* |
1288 | * Delete a multicast address record. | | 1289 | * Delete a multicast address record. |
1289 | */ | | 1290 | */ |
1290 | int | | 1291 | int |
1291 | ether_delmulti(const struct sockaddr *sa, struct ethercom *ec) | | 1292 | ether_delmulti(const struct sockaddr *sa, struct ethercom *ec) |
1292 | { | | 1293 | { |
1293 | struct ether_multi *enm; | | 1294 | struct ether_multi *enm; |
1294 | u_char addrlo[ETHER_ADDR_LEN]; | | 1295 | u_char addrlo[ETHER_ADDR_LEN]; |
1295 | u_char addrhi[ETHER_ADDR_LEN]; | | 1296 | u_char addrhi[ETHER_ADDR_LEN]; |
1296 | int error; | | 1297 | int error; |
1297 | | | 1298 | |
1298 | ETHER_LOCK(ec); | | 1299 | ETHER_LOCK(ec); |
1299 | error = ether_multiaddr(sa, addrlo, addrhi); | | 1300 | error = ether_multiaddr(sa, addrlo, addrhi); |
1300 | if (error != 0) | | 1301 | if (error != 0) |
1301 | goto error; | | 1302 | goto error; |
1302 | | | 1303 | |
1303 | /* | | 1304 | /* |
1304 | * Look up the address in our list. | | 1305 | * Look up the address in our list. |
1305 | */ | | 1306 | */ |
1306 | ETHER_LOOKUP_MULTI(addrlo, addrhi, ec, enm); | | 1307 | ETHER_LOOKUP_MULTI(addrlo, addrhi, ec, enm); |
1307 | if (enm == NULL) { | | 1308 | if (enm == NULL) { |
1308 | error = ENXIO; | | 1309 | error = ENXIO; |
1309 | goto error; | | 1310 | goto error; |
1310 | } | | 1311 | } |
1311 | if (--enm->enm_refcount != 0) { | | 1312 | if (--enm->enm_refcount != 0) { |
1312 | /* | | 1313 | /* |
1313 | * Still some claims to this record. | | 1314 | * Still some claims to this record. |
1314 | */ | | 1315 | */ |
1315 | error = 0; | | 1316 | error = 0; |
1316 | goto error; | | 1317 | goto error; |
1317 | } | | 1318 | } |
1318 | | | 1319 | |
1319 | /* | | 1320 | /* |
1320 | * No remaining claims to this record; unlink and free it. | | 1321 | * No remaining claims to this record; unlink and free it. |
1321 | */ | | 1322 | */ |
1322 | LIST_REMOVE(enm, enm_list); | | 1323 | LIST_REMOVE(enm, enm_list); |
1323 | ec->ec_multicnt--; | | 1324 | ec->ec_multicnt--; |
1324 | ETHER_UNLOCK(ec); | | 1325 | ETHER_UNLOCK(ec); |
1325 | kmem_free(enm, sizeof(*enm)); | | 1326 | kmem_free(enm, sizeof(*enm)); |
1326 | | | 1327 | |
1327 | /* | | 1328 | /* |
1328 | * Return ENETRESET to inform the driver that the list has changed | | 1329 | * Return ENETRESET to inform the driver that the list has changed |
1329 | * and its reception filter should be adjusted accordingly. | | 1330 | * and its reception filter should be adjusted accordingly. |
1330 | */ | | 1331 | */ |
1331 | return ENETRESET; | | 1332 | return ENETRESET; |
1332 | | | 1333 | |
1333 | error: | | 1334 | error: |
1334 | ETHER_UNLOCK(ec); | | 1335 | ETHER_UNLOCK(ec); |
1335 | return error; | | 1336 | return error; |
1336 | } | | 1337 | } |
1337 | | | 1338 | |
1338 | void | | 1339 | void |
1339 | ether_set_ifflags_cb(struct ethercom *ec, ether_cb_t cb) | | 1340 | ether_set_ifflags_cb(struct ethercom *ec, ether_cb_t cb) |
1340 | { | | 1341 | { |
1341 | ec->ec_ifflags_cb = cb; | | 1342 | ec->ec_ifflags_cb = cb; |
1342 | } | | 1343 | } |
1343 | | | 1344 | |
1344 | /* | | 1345 | /* |
1345 | * Common ioctls for Ethernet interfaces. Note, we must be | | 1346 | * Common ioctls for Ethernet interfaces. Note, we must be |
1346 | * called at splnet(). | | 1347 | * called at splnet(). |
1347 | */ | | 1348 | */ |
1348 | int | | 1349 | int |
1349 | ether_ioctl(struct ifnet *ifp, u_long cmd, void *data) | | 1350 | ether_ioctl(struct ifnet *ifp, u_long cmd, void *data) |
1350 | { | | 1351 | { |
1351 | struct ethercom *ec = (void *) ifp; | | 1352 | struct ethercom *ec = (void *) ifp; |
1352 | struct eccapreq *eccr; | | 1353 | struct eccapreq *eccr; |
1353 | struct ifreq *ifr = (struct ifreq *)data; | | 1354 | struct ifreq *ifr = (struct ifreq *)data; |
1354 | struct if_laddrreq *iflr = data; | | 1355 | struct if_laddrreq *iflr = data; |
1355 | const struct sockaddr_dl *sdl; | | 1356 | const struct sockaddr_dl *sdl; |
1356 | static const uint8_t zero[ETHER_ADDR_LEN]; | | 1357 | static const uint8_t zero[ETHER_ADDR_LEN]; |
1357 | int error; | | 1358 | int error; |
1358 | | | 1359 | |
1359 | switch (cmd) { | | 1360 | switch (cmd) { |
1360 | case SIOCINITIFADDR: | | 1361 | case SIOCINITIFADDR: |
1361 | { | | 1362 | { |
1362 | struct ifaddr *ifa = (struct ifaddr *)data; | | 1363 | struct ifaddr *ifa = (struct ifaddr *)data; |
1363 | if (ifa->ifa_addr->sa_family != AF_LINK | | 1364 | if (ifa->ifa_addr->sa_family != AF_LINK |
1364 | && (ifp->if_flags & (IFF_UP | IFF_RUNNING)) != | | 1365 | && (ifp->if_flags & (IFF_UP | IFF_RUNNING)) != |
1365 | (IFF_UP | IFF_RUNNING)) { | | 1366 | (IFF_UP | IFF_RUNNING)) { |
1366 | ifp->if_flags |= IFF_UP; | | 1367 | ifp->if_flags |= IFF_UP; |
1367 | if ((error = (*ifp->if_init)(ifp)) != 0) | | 1368 | if ((error = (*ifp->if_init)(ifp)) != 0) |
1368 | return error; | | 1369 | return error; |
1369 | } | | 1370 | } |
1370 | #ifdef INET | | 1371 | #ifdef INET |
1371 | if (ifa->ifa_addr->sa_family == AF_INET) | | 1372 | if (ifa->ifa_addr->sa_family == AF_INET) |
1372 | arp_ifinit(ifp, ifa); | | 1373 | arp_ifinit(ifp, ifa); |
1373 | #endif | | 1374 | #endif |
1374 | return 0; | | 1375 | return 0; |
1375 | } | | 1376 | } |
1376 | | | 1377 | |
1377 | case SIOCSIFMTU: | | 1378 | case SIOCSIFMTU: |
1378 | { | | 1379 | { |
1379 | int maxmtu; | | 1380 | int maxmtu; |
1380 | | | 1381 | |
1381 | if (ec->ec_capabilities & ETHERCAP_JUMBO_MTU) | | 1382 | if (ec->ec_capabilities & ETHERCAP_JUMBO_MTU) |
1382 | maxmtu = ETHERMTU_JUMBO; | | 1383 | maxmtu = ETHERMTU_JUMBO; |
1383 | else | | 1384 | else |
1384 | maxmtu = ETHERMTU; | | 1385 | maxmtu = ETHERMTU; |
1385 | | | 1386 | |
1386 | if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > maxmtu) | | 1387 | if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > maxmtu) |
1387 | return EINVAL; | | 1388 | return EINVAL; |
1388 | else if ((error = ifioctl_common(ifp, cmd, data)) != ENETRESET) | | 1389 | else if ((error = ifioctl_common(ifp, cmd, data)) != ENETRESET) |
1389 | return error; | | 1390 | return error; |
1390 | else if (ifp->if_flags & IFF_UP) { | | 1391 | else if (ifp->if_flags & IFF_UP) { |
1391 | /* Make sure the device notices the MTU change. */ | | 1392 | /* Make sure the device notices the MTU change. */ |
1392 | return (*ifp->if_init)(ifp); | | 1393 | return (*ifp->if_init)(ifp); |
1393 | } else | | 1394 | } else |
1394 | return 0; | | 1395 | return 0; |
1395 | } | | 1396 | } |
1396 | | | 1397 | |
1397 | case SIOCSIFFLAGS: | | 1398 | case SIOCSIFFLAGS: |
1398 | if ((error = ifioctl_common(ifp, cmd, data)) != 0) | | 1399 | if ((error = ifioctl_common(ifp, cmd, data)) != 0) |
1399 | return error; | | 1400 | return error; |
1400 | switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) { | | 1401 | switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) { |
1401 | case IFF_RUNNING: | | 1402 | case IFF_RUNNING: |
1402 | /* | | 1403 | /* |
1403 | * If interface is marked down and it is running, | | 1404 | * If interface is marked down and it is running, |
1404 | * then stop and disable it. | | 1405 | * then stop and disable it. |
1405 | */ | | 1406 | */ |
1406 | (*ifp->if_stop)(ifp, 1); | | 1407 | (*ifp->if_stop)(ifp, 1); |
1407 | break; | | 1408 | break; |
1408 | case IFF_UP: | | 1409 | case IFF_UP: |
1409 | /* | | 1410 | /* |
1410 | * If interface is marked up and it is stopped, then | | 1411 | * If interface is marked up and it is stopped, then |
1411 | * start it. | | 1412 | * start it. |
1412 | */ | | 1413 | */ |
1413 | return (*ifp->if_init)(ifp); | | 1414 | return (*ifp->if_init)(ifp); |
1414 | case IFF_UP | IFF_RUNNING: | | 1415 | case IFF_UP | IFF_RUNNING: |
1415 | error = 0; | | 1416 | error = 0; |
1416 | if (ec->ec_ifflags_cb != NULL) { | | 1417 | if (ec->ec_ifflags_cb != NULL) { |
1417 | error = (*ec->ec_ifflags_cb)(ec); | | 1418 | error = (*ec->ec_ifflags_cb)(ec); |
1418 | if (error == ENETRESET) { | | 1419 | if (error == ENETRESET) { |
1419 | /* | | 1420 | /* |
1420 | * Reset the interface to pick up | | 1421 | * Reset the interface to pick up |
1421 | * changes in any other flags that | | 1422 | * changes in any other flags that |
1422 | * affect the hardware state. | | 1423 | * affect the hardware state. |
1423 | */ | | 1424 | */ |
1424 | return (*ifp->if_init)(ifp); | | 1425 | return (*ifp->if_init)(ifp); |
1425 | } | | 1426 | } |
1426 | } else | | 1427 | } else |
1427 | error = (*ifp->if_init)(ifp); | | 1428 | error = (*ifp->if_init)(ifp); |
1428 | return error; | | 1429 | return error; |
1429 | case 0: | | 1430 | case 0: |
1430 | break; | | 1431 | break; |
1431 | } | | 1432 | } |
1432 | return 0; | | 1433 | return 0; |
1433 | case SIOCGETHERCAP: | | 1434 | case SIOCGETHERCAP: |
1434 | eccr = (struct eccapreq *)data; | | 1435 | eccr = (struct eccapreq *)data; |
1435 | eccr->eccr_capabilities = ec->ec_capabilities; | | 1436 | eccr->eccr_capabilities = ec->ec_capabilities; |
1436 | eccr->eccr_capenable = ec->ec_capenable; | | 1437 | eccr->eccr_capenable = ec->ec_capenable; |
1437 | return 0; | | 1438 | return 0; |
1438 | case SIOCADDMULTI: | | 1439 | case SIOCADDMULTI: |
1439 | return ether_addmulti(ifreq_getaddr(cmd, ifr), ec); | | 1440 | return ether_addmulti(ifreq_getaddr(cmd, ifr), ec); |
1440 | case SIOCDELMULTI: | | 1441 | case SIOCDELMULTI: |
1441 | return ether_delmulti(ifreq_getaddr(cmd, ifr), ec); | | 1442 | return ether_delmulti(ifreq_getaddr(cmd, ifr), ec); |
1442 | case SIOCSIFMEDIA: | | 1443 | case SIOCSIFMEDIA: |
1443 | case SIOCGIFMEDIA: | | 1444 | case SIOCGIFMEDIA: |
1444 | if (ec->ec_mii == NULL) | | 1445 | if (ec->ec_mii == NULL) |
1445 | return ENOTTY; | | 1446 | return ENOTTY; |
1446 | return ifmedia_ioctl(ifp, ifr, &ec->ec_mii->mii_media, cmd); | | 1447 | return ifmedia_ioctl(ifp, ifr, &ec->ec_mii->mii_media, cmd); |
1447 | case SIOCALIFADDR: | | 1448 | case SIOCALIFADDR: |
1448 | sdl = satocsdl(sstocsa(&iflr->addr)); | | 1449 | sdl = satocsdl(sstocsa(&iflr->addr)); |
1449 | if (sdl->sdl_family != AF_LINK) | | 1450 | if (sdl->sdl_family != AF_LINK) |
1450 | ; | | 1451 | ; |
1451 | else if (ETHER_IS_MULTICAST(CLLADDR(sdl))) | | 1452 | else if (ETHER_IS_MULTICAST(CLLADDR(sdl))) |
1452 | return EINVAL; | | 1453 | return EINVAL; |
1453 | else if (memcmp(zero, CLLADDR(sdl), sizeof(zero)) == 0) | | 1454 | else if (memcmp(zero, CLLADDR(sdl), sizeof(zero)) == 0) |
1454 | return EINVAL; | | 1455 | return EINVAL; |
1455 | /*FALLTHROUGH*/ | | 1456 | /*FALLTHROUGH*/ |
1456 | default: | | 1457 | default: |
1457 | return ifioctl_common(ifp, cmd, data); | | 1458 | return ifioctl_common(ifp, cmd, data); |
1458 | } | | 1459 | } |
1459 | return 0; | | 1460 | return 0; |
1460 | } | | 1461 | } |
1461 | | | 1462 | |
1462 | /* | | 1463 | /* |
1463 | * Enable/disable passing VLAN packets if the parent interface supports it. | | 1464 | * Enable/disable passing VLAN packets if the parent interface supports it. |
1464 | * Return: | | 1465 | * Return: |
1465 | * 0: Ok | | 1466 | * 0: Ok |
1466 | * -1: Parent interface does not support vlans | | 1467 | * -1: Parent interface does not support vlans |
1467 | * >0: Error | | 1468 | * >0: Error |
1468 | */ | | 1469 | */ |
1469 | int | | 1470 | int |
1470 | ether_enable_vlan_mtu(struct ifnet *ifp) | | 1471 | ether_enable_vlan_mtu(struct ifnet *ifp) |
1471 | { | | 1472 | { |
1472 | int error; | | 1473 | int error; |
1473 | struct ethercom *ec = (void *)ifp; | | 1474 | struct ethercom *ec = (void *)ifp; |
1474 | | | 1475 | |
1475 | /* Parent does not support VLAN's */ | | 1476 | /* Parent does not support VLAN's */ |
1476 | if ((ec->ec_capabilities & ETHERCAP_VLAN_MTU) == 0) | | 1477 | if ((ec->ec_capabilities & ETHERCAP_VLAN_MTU) == 0) |
1477 | return -1; | | 1478 | return -1; |
1478 | | | 1479 | |
1479 | /* | | 1480 | /* |
1480 | * Parent supports the VLAN_MTU capability, | | 1481 | * Parent supports the VLAN_MTU capability, |
1481 | * i.e. can Tx/Rx larger than ETHER_MAX_LEN frames; | | 1482 | * i.e. can Tx/Rx larger than ETHER_MAX_LEN frames; |
1482 | * enable it. | | 1483 | * enable it. |
1483 | */ | | 1484 | */ |
1484 | ec->ec_capenable |= ETHERCAP_VLAN_MTU; | | 1485 | ec->ec_capenable |= ETHERCAP_VLAN_MTU; |
1485 | | | 1486 | |
1486 | /* Interface is down, defer for later */ | | 1487 | /* Interface is down, defer for later */ |
1487 | if ((ifp->if_flags & IFF_UP) == 0) | | 1488 | if ((ifp->if_flags & IFF_UP) == 0) |
1488 | return 0; | | 1489 | return 0; |
1489 | | | 1490 | |
1490 | if ((error = if_flags_set(ifp, ifp->if_flags)) == 0) | | 1491 | if ((error = if_flags_set(ifp, ifp->if_flags)) == 0) |
1491 | return 0; | | 1492 | return 0; |
1492 | | | 1493 | |
1493 | ec->ec_capenable &= ~ETHERCAP_VLAN_MTU; | | 1494 | ec->ec_capenable &= ~ETHERCAP_VLAN_MTU; |
1494 | return error; | | 1495 | return error; |
1495 | } | | 1496 | } |
1496 | | | 1497 | |
1497 | int | | 1498 | int |
1498 | ether_disable_vlan_mtu(struct ifnet *ifp) | | 1499 | ether_disable_vlan_mtu(struct ifnet *ifp) |
1499 | { | | 1500 | { |
1500 | int error; | | 1501 | int error; |
1501 | struct ethercom *ec = (void *)ifp; | | 1502 | struct ethercom *ec = (void *)ifp; |
1502 | | | 1503 | |
1503 | /* We still have VLAN's, defer for later */ | | 1504 | /* We still have VLAN's, defer for later */ |
1504 | if (ec->ec_nvlans != 0) | | 1505 | if (ec->ec_nvlans != 0) |
1505 | return 0; | | 1506 | return 0; |
1506 | | | 1507 | |
1507 | /* Parent does not support VLAB's, nothing to do. */ | | 1508 | /* Parent does not support VLAB's, nothing to do. */ |
1508 | if ((ec->ec_capenable & ETHERCAP_VLAN_MTU) == 0) | | 1509 | if ((ec->ec_capenable & ETHERCAP_VLAN_MTU) == 0) |
1509 | return -1; | | 1510 | return -1; |
1510 | | | 1511 | |
1511 | /* | | 1512 | /* |
1512 | * Disable Tx/Rx of VLAN-sized frames. | | 1513 | * Disable Tx/Rx of VLAN-sized frames. |
1513 | */ | | 1514 | */ |
1514 | ec->ec_capenable &= ~ETHERCAP_VLAN_MTU; | | 1515 | ec->ec_capenable &= ~ETHERCAP_VLAN_MTU; |
1515 | | | 1516 | |
1516 | /* Interface is down, defer for later */ | | 1517 | /* Interface is down, defer for later */ |
1517 | if ((ifp->if_flags & IFF_UP) == 0) | | 1518 | if ((ifp->if_flags & IFF_UP) == 0) |
1518 | return 0; | | 1519 | return 0; |
1519 | | | 1520 | |
1520 | if ((error = if_flags_set(ifp, ifp->if_flags)) == 0) | | 1521 | if ((error = if_flags_set(ifp, ifp->if_flags)) == 0) |
1521 | return 0; | | 1522 | return 0; |
1522 | | | 1523 | |
1523 | ec->ec_capenable |= ETHERCAP_VLAN_MTU; | | 1524 | ec->ec_capenable |= ETHERCAP_VLAN_MTU; |
1524 | return error; | | 1525 | return error; |
1525 | } | | 1526 | } |
1526 | | | 1527 | |
1527 | static int | | 1528 | static int |
1528 | ether_multicast_sysctl(SYSCTLFN_ARGS) | | 1529 | ether_multicast_sysctl(SYSCTLFN_ARGS) |
1529 | { | | 1530 | { |
1530 | struct ether_multi *enm; | | 1531 | struct ether_multi *enm; |
1531 | struct ifnet *ifp; | | 1532 | struct ifnet *ifp; |
1532 | struct ethercom *ec; | | 1533 | struct ethercom *ec; |
1533 | int error = 0; | | 1534 | int error = 0; |
1534 | size_t written; | | 1535 | size_t written; |
1535 | struct psref psref; | | 1536 | struct psref psref; |
1536 | int bound; | | 1537 | int bound; |
1537 | unsigned int multicnt; | | 1538 | unsigned int multicnt; |
1538 | struct ether_multi_sysctl *addrs; | | 1539 | struct ether_multi_sysctl *addrs; |
1539 | int i; | | 1540 | int i; |
1540 | | | 1541 | |
1541 | if (namelen != 1) | | 1542 | if (namelen != 1) |
1542 | return EINVAL; | | 1543 | return EINVAL; |
1543 | | | 1544 | |
1544 | bound = curlwp_bind(); | | 1545 | bound = curlwp_bind(); |
1545 | ifp = if_get_byindex(name[0], &psref); | | 1546 | ifp = if_get_byindex(name[0], &psref); |
1546 | if (ifp == NULL) { | | 1547 | if (ifp == NULL) { |
1547 | error = ENODEV; | | 1548 | error = ENODEV; |
1548 | goto out; | | 1549 | goto out; |
1549 | } | | 1550 | } |
1550 | if (ifp->if_type != IFT_ETHER) { | | 1551 | if (ifp->if_type != IFT_ETHER) { |
1551 | if_put(ifp, &psref); | | 1552 | if_put(ifp, &psref); |
1552 | *oldlenp = 0; | | 1553 | *oldlenp = 0; |
1553 | goto out; | | 1554 | goto out; |
1554 | } | | 1555 | } |
1555 | ec = (struct ethercom *)ifp; | | 1556 | ec = (struct ethercom *)ifp; |
1556 | | | 1557 | |
1557 | if (oldp == NULL) { | | 1558 | if (oldp == NULL) { |
1558 | if_put(ifp, &psref); | | 1559 | if_put(ifp, &psref); |
1559 | *oldlenp = ec->ec_multicnt * sizeof(*addrs); | | 1560 | *oldlenp = ec->ec_multicnt * sizeof(*addrs); |
1560 | goto out; | | 1561 | goto out; |
1561 | } | | 1562 | } |
1562 | | | 1563 | |
1563 | /* | | 1564 | /* |
1564 | * ec->ec_lock is a spin mutex so we cannot call sysctl_copyout, which | | 1565 | * ec->ec_lock is a spin mutex so we cannot call sysctl_copyout, which |
1565 | * is sleepable, while holding it. Copy data to a local buffer first | | 1566 | * is sleepable, while holding it. Copy data to a local buffer first |
1566 | * with the lock taken and then call sysctl_copyout without holding it. | | 1567 | * with the lock taken and then call sysctl_copyout without holding it. |
1567 | */ | | 1568 | */ |
1568 | retry: | | 1569 | retry: |
1569 | multicnt = ec->ec_multicnt; | | 1570 | multicnt = ec->ec_multicnt; |
1570 | | | 1571 | |
1571 | if (multicnt == 0) { | | 1572 | if (multicnt == 0) { |
1572 | if_put(ifp, &psref); | | 1573 | if_put(ifp, &psref); |
1573 | *oldlenp = 0; | | 1574 | *oldlenp = 0; |
1574 | goto out; | | 1575 | goto out; |
1575 | } | | 1576 | } |
1576 | | | 1577 | |
1577 | addrs = kmem_zalloc(sizeof(*addrs) * multicnt, KM_SLEEP); | | 1578 | addrs = kmem_zalloc(sizeof(*addrs) * multicnt, KM_SLEEP); |
1578 | | | 1579 | |
1579 | ETHER_LOCK(ec); | | 1580 | ETHER_LOCK(ec); |
1580 | if (multicnt != ec->ec_multicnt) { | | 1581 | if (multicnt != ec->ec_multicnt) { |
1581 | /* The number of multicast addresses has changed */ | | 1582 | /* The number of multicast addresses has changed */ |
1582 | ETHER_UNLOCK(ec); | | 1583 | ETHER_UNLOCK(ec); |
1583 | kmem_free(addrs, sizeof(*addrs) * multicnt); | | 1584 | kmem_free(addrs, sizeof(*addrs) * multicnt); |
1584 | goto retry; | | 1585 | goto retry; |
1585 | } | | 1586 | } |
1586 | | | 1587 | |
1587 | i = 0; | | 1588 | i = 0; |
1588 | LIST_FOREACH(enm, &ec->ec_multiaddrs, enm_list) { | | 1589 | LIST_FOREACH(enm, &ec->ec_multiaddrs, enm_list) { |
1589 | struct ether_multi_sysctl *addr = &addrs[i]; | | 1590 | struct ether_multi_sysctl *addr = &addrs[i]; |
1590 | addr->enm_refcount = enm->enm_refcount; | | 1591 | addr->enm_refcount = enm->enm_refcount; |
1591 | memcpy(addr->enm_addrlo, enm->enm_addrlo, ETHER_ADDR_LEN); | | 1592 | memcpy(addr->enm_addrlo, enm->enm_addrlo, ETHER_ADDR_LEN); |
1592 | memcpy(addr->enm_addrhi, enm->enm_addrhi, ETHER_ADDR_LEN); | | 1593 | memcpy(addr->enm_addrhi, enm->enm_addrhi, ETHER_ADDR_LEN); |
1593 | i++; | | 1594 | i++; |
1594 | } | | 1595 | } |
1595 | ETHER_UNLOCK(ec); | | 1596 | ETHER_UNLOCK(ec); |
1596 | | | 1597 | |
1597 | error = 0; | | 1598 | error = 0; |
1598 | written = 0; | | 1599 | written = 0; |
1599 | for (i = 0; i < multicnt; i++) { | | 1600 | for (i = 0; i < multicnt; i++) { |
1600 | struct ether_multi_sysctl *addr = &addrs[i]; | | 1601 | struct ether_multi_sysctl *addr = &addrs[i]; |
1601 | | | 1602 | |
1602 | if (written + sizeof(*addr) > *oldlenp) | | 1603 | if (written + sizeof(*addr) > *oldlenp) |
1603 | break; | | 1604 | break; |
1604 | error = sysctl_copyout(l, addr, oldp, sizeof(*addr)); | | 1605 | error = sysctl_copyout(l, addr, oldp, sizeof(*addr)); |