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