if_ethersubr.c revision 1.57 1 1.57 mycroft /* $NetBSD: if_ethersubr.c,v 1.57 2000/06/14 05:10:27 mycroft Exp $ */
2 1.44 itojun
3 1.44 itojun /*
4 1.44 itojun * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 1.44 itojun * All rights reserved.
6 1.44 itojun *
7 1.44 itojun * Redistribution and use in source and binary forms, with or without
8 1.44 itojun * modification, are permitted provided that the following conditions
9 1.44 itojun * are met:
10 1.44 itojun * 1. Redistributions of source code must retain the above copyright
11 1.44 itojun * notice, this list of conditions and the following disclaimer.
12 1.44 itojun * 2. Redistributions in binary form must reproduce the above copyright
13 1.44 itojun * notice, this list of conditions and the following disclaimer in the
14 1.44 itojun * documentation and/or other materials provided with the distribution.
15 1.44 itojun * 3. Neither the name of the project nor the names of its contributors
16 1.44 itojun * may be used to endorse or promote products derived from this software
17 1.44 itojun * without specific prior written permission.
18 1.44 itojun *
19 1.44 itojun * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 1.44 itojun * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 1.44 itojun * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 1.44 itojun * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 1.44 itojun * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 1.44 itojun * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 1.44 itojun * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 1.44 itojun * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 1.44 itojun * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 1.44 itojun * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 1.44 itojun * SUCH DAMAGE.
30 1.44 itojun */
31 1.9 cgd
32 1.1 cgd /*
33 1.8 mycroft * Copyright (c) 1982, 1989, 1993
34 1.8 mycroft * The Regents of the University of California. All rights reserved.
35 1.1 cgd *
36 1.1 cgd * Redistribution and use in source and binary forms, with or without
37 1.1 cgd * modification, are permitted provided that the following conditions
38 1.1 cgd * are met:
39 1.1 cgd * 1. Redistributions of source code must retain the above copyright
40 1.1 cgd * notice, this list of conditions and the following disclaimer.
41 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright
42 1.1 cgd * notice, this list of conditions and the following disclaimer in the
43 1.1 cgd * documentation and/or other materials provided with the distribution.
44 1.1 cgd * 3. All advertising materials mentioning features or use of this software
45 1.1 cgd * must display the following acknowledgement:
46 1.1 cgd * This product includes software developed by the University of
47 1.1 cgd * California, Berkeley and its contributors.
48 1.1 cgd * 4. Neither the name of the University nor the names of its contributors
49 1.1 cgd * may be used to endorse or promote products derived from this software
50 1.1 cgd * without specific prior written permission.
51 1.1 cgd *
52 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
53 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
56 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62 1.1 cgd * SUCH DAMAGE.
63 1.1 cgd *
64 1.27 fvdl * @(#)if_ethersubr.c 8.2 (Berkeley) 4/4/96
65 1.1 cgd */
66 1.1 cgd
67 1.33 jonathan #include "opt_inet.h"
68 1.33 jonathan #include "opt_atalk.h"
69 1.34 jonathan #include "opt_ccitt.h"
70 1.35 jonathan #include "opt_llc.h"
71 1.36 jonathan #include "opt_iso.h"
72 1.37 jonathan #include "opt_ns.h"
73 1.30 matt #include "opt_gateway.h"
74 1.30 matt
75 1.4 mycroft #include <sys/param.h>
76 1.4 mycroft #include <sys/systm.h>
77 1.4 mycroft #include <sys/kernel.h>
78 1.4 mycroft #include <sys/malloc.h>
79 1.4 mycroft #include <sys/mbuf.h>
80 1.4 mycroft #include <sys/protosw.h>
81 1.4 mycroft #include <sys/socket.h>
82 1.4 mycroft #include <sys/ioctl.h>
83 1.4 mycroft #include <sys/errno.h>
84 1.4 mycroft #include <sys/syslog.h>
85 1.4 mycroft
86 1.8 mycroft #include <machine/cpu.h>
87 1.8 mycroft
88 1.4 mycroft #include <net/if.h>
89 1.4 mycroft #include <net/netisr.h>
90 1.4 mycroft #include <net/route.h>
91 1.4 mycroft #include <net/if_llc.h>
92 1.4 mycroft #include <net/if_dl.h>
93 1.8 mycroft #include <net/if_types.h>
94 1.1 cgd
95 1.22 is #include <net/if_ether.h>
96 1.22 is
97 1.15 phil #include <netinet/in.h>
98 1.1 cgd #ifdef INET
99 1.4 mycroft #include <netinet/in_var.h>
100 1.1 cgd #endif
101 1.22 is #include <netinet/if_inarp.h>
102 1.1 cgd
103 1.44 itojun #ifdef INET6
104 1.44 itojun #ifndef INET
105 1.44 itojun #include <netinet/in.h>
106 1.44 itojun #endif
107 1.44 itojun #include <netinet6/in6_var.h>
108 1.44 itojun #include <netinet6/nd6.h>
109 1.44 itojun #endif
110 1.44 itojun
111 1.1 cgd #ifdef NS
112 1.4 mycroft #include <netns/ns.h>
113 1.4 mycroft #include <netns/ns_if.h>
114 1.1 cgd #endif
115 1.1 cgd
116 1.32 christos #ifdef IPX
117 1.32 christos #include <netipx/ipx.h>
118 1.32 christos #include <netipx/ipx_if.h>
119 1.32 christos #endif
120 1.32 christos
121 1.1 cgd #ifdef ISO
122 1.4 mycroft #include <netiso/argo_debug.h>
123 1.4 mycroft #include <netiso/iso.h>
124 1.4 mycroft #include <netiso/iso_var.h>
125 1.4 mycroft #include <netiso/iso_snpac.h>
126 1.1 cgd #endif
127 1.4 mycroft
128 1.8 mycroft #ifdef LLC
129 1.8 mycroft #include <netccitt/dll.h>
130 1.8 mycroft #include <netccitt/llc_var.h>
131 1.8 mycroft #endif
132 1.8 mycroft
133 1.8 mycroft #if defined(LLC) && defined(CCITT)
134 1.8 mycroft extern struct ifqueue pkintrq;
135 1.8 mycroft #endif
136 1.1 cgd
137 1.23 christos #ifdef NETATALK
138 1.23 christos #include <netatalk/at.h>
139 1.23 christos #include <netatalk/at_var.h>
140 1.23 christos #include <netatalk/at_extern.h>
141 1.23 christos
142 1.23 christos #define llc_snap_org_code llc_un.type_snap.org_code
143 1.23 christos #define llc_snap_ether_type llc_un.type_snap.ether_type
144 1.23 christos
145 1.23 christos extern u_char at_org_code[3];
146 1.23 christos extern u_char aarp_org_code[3];
147 1.23 christos #endif /* NETATALK */
148 1.23 christos
149 1.1 cgd u_char etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
150 1.8 mycroft #define senderr(e) { error = (e); goto bad;}
151 1.1 cgd
152 1.22 is #define SIN(x) ((struct sockaddr_in *)x)
153 1.22 is
154 1.42 thorpej static int ether_output __P((struct ifnet *, struct mbuf *,
155 1.42 thorpej struct sockaddr *, struct rtentry *));
156 1.42 thorpej static void ether_input __P((struct ifnet *, struct mbuf *));
157 1.42 thorpej
158 1.1 cgd /*
159 1.1 cgd * Ethernet output routine.
160 1.1 cgd * Encapsulate a packet of type family for the local net.
161 1.22 is * Assumes that ifp is actually pointer to ethercom structure.
162 1.1 cgd */
163 1.42 thorpej static int
164 1.8 mycroft ether_output(ifp, m0, dst, rt0)
165 1.29 mrg struct ifnet *ifp;
166 1.1 cgd struct mbuf *m0;
167 1.1 cgd struct sockaddr *dst;
168 1.8 mycroft struct rtentry *rt0;
169 1.1 cgd {
170 1.49 matt u_int16_t etype = 0;
171 1.31 thorpej int s, error = 0, hdrcmplt = 0;
172 1.31 thorpej u_char esrc[6], edst[6];
173 1.29 mrg struct mbuf *m = m0;
174 1.29 mrg struct rtentry *rt;
175 1.1 cgd struct mbuf *mcopy = (struct mbuf *)0;
176 1.29 mrg struct ether_header *eh;
177 1.24 christos #ifdef INET
178 1.22 is struct arphdr *ah;
179 1.24 christos #endif /* INET */
180 1.23 christos #ifdef NETATALK
181 1.23 christos struct at_ifaddr *aa;
182 1.23 christos #endif /* NETATALK */
183 1.1 cgd
184 1.8 mycroft if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
185 1.8 mycroft senderr(ENETDOWN);
186 1.8 mycroft ifp->if_lastchange = time;
187 1.18 christos if ((rt = rt0) != NULL) {
188 1.8 mycroft if ((rt->rt_flags & RTF_UP) == 0) {
189 1.27 fvdl if ((rt0 = rt = rtalloc1(dst, 1)) != NULL) {
190 1.8 mycroft rt->rt_refcnt--;
191 1.27 fvdl if (rt->rt_ifp != ifp)
192 1.27 fvdl return (*rt->rt_ifp->if_output)
193 1.27 fvdl (ifp, m0, dst, rt);
194 1.27 fvdl } else
195 1.8 mycroft senderr(EHOSTUNREACH);
196 1.8 mycroft }
197 1.27 fvdl if ((rt->rt_flags & RTF_GATEWAY) && dst->sa_family != AF_NS) {
198 1.8 mycroft if (rt->rt_gwroute == 0)
199 1.8 mycroft goto lookup;
200 1.8 mycroft if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
201 1.8 mycroft rtfree(rt); rt = rt0;
202 1.8 mycroft lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1);
203 1.8 mycroft if ((rt = rt->rt_gwroute) == 0)
204 1.8 mycroft senderr(EHOSTUNREACH);
205 1.27 fvdl /* the "G" test below also prevents rt == rt0 */
206 1.27 fvdl if ((rt->rt_flags & RTF_GATEWAY) ||
207 1.27 fvdl (rt->rt_ifp != ifp)) {
208 1.27 fvdl rt->rt_refcnt--;
209 1.27 fvdl rt0->rt_gwroute = 0;
210 1.27 fvdl senderr(EHOSTUNREACH);
211 1.27 fvdl }
212 1.8 mycroft }
213 1.8 mycroft }
214 1.8 mycroft if (rt->rt_flags & RTF_REJECT)
215 1.8 mycroft if (rt->rt_rmx.rmx_expire == 0 ||
216 1.8 mycroft time.tv_sec < rt->rt_rmx.rmx_expire)
217 1.8 mycroft senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
218 1.1 cgd }
219 1.1 cgd switch (dst->sa_family) {
220 1.1 cgd
221 1.1 cgd #ifdef INET
222 1.1 cgd case AF_INET:
223 1.22 is if (m->m_flags & M_BCAST)
224 1.22 is bcopy((caddr_t)etherbroadcastaddr, (caddr_t)edst,
225 1.22 is sizeof(edst));
226 1.22 is
227 1.22 is else if (m->m_flags & M_MCAST) {
228 1.22 is ETHER_MAP_IP_MULTICAST(&SIN(dst)->sin_addr,
229 1.22 is (caddr_t)edst)
230 1.22 is
231 1.22 is } else if (!arpresolve(ifp, rt, m, dst, edst))
232 1.1 cgd return (0); /* if not yet resolved */
233 1.3 hpeyerl /* If broadcasting on a simplex interface, loopback a copy */
234 1.3 hpeyerl if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
235 1.1 cgd mcopy = m_copy(m, 0, (int)M_COPYALL);
236 1.17 mycroft etype = htons(ETHERTYPE_IP);
237 1.8 mycroft break;
238 1.22 is
239 1.22 is case AF_ARP:
240 1.22 is ah = mtod(m, struct arphdr *);
241 1.22 is if (m->m_flags & M_BCAST)
242 1.22 is bcopy((caddr_t)etherbroadcastaddr, (caddr_t)edst,
243 1.22 is sizeof(edst));
244 1.22 is else
245 1.22 is bcopy((caddr_t)ar_tha(ah),
246 1.22 is (caddr_t)edst, sizeof(edst));
247 1.22 is
248 1.22 is ah->ar_hrd = htons(ARPHRD_ETHER);
249 1.22 is
250 1.22 is switch(ntohs(ah->ar_op)) {
251 1.22 is case ARPOP_REVREQUEST:
252 1.22 is case ARPOP_REVREPLY:
253 1.22 is etype = htons(ETHERTYPE_REVARP);
254 1.22 is break;
255 1.22 is
256 1.22 is case ARPOP_REQUEST:
257 1.22 is case ARPOP_REPLY:
258 1.22 is default:
259 1.22 is etype = htons(ETHERTYPE_ARP);
260 1.22 is }
261 1.22 is
262 1.22 is break;
263 1.1 cgd #endif
264 1.44 itojun #ifdef INET6
265 1.44 itojun case AF_INET6:
266 1.51 itojun #ifdef OLDIP6OUTPUT
267 1.44 itojun if (!nd6_resolve(ifp, rt, m, dst, (u_char *)edst))
268 1.44 itojun return(0); /* if not yet resolves */
269 1.51 itojun #else
270 1.51 itojun if (!nd6_storelladdr(ifp, rt, m, dst, (u_char *)edst)){
271 1.51 itojun /* this must be impossible, so we bark */
272 1.51 itojun printf("nd6_storelladdr failed\n");
273 1.51 itojun return(0);
274 1.51 itojun }
275 1.51 itojun #endif /* OLDIP6OUTPUT */
276 1.44 itojun etype = htons(ETHERTYPE_IPV6);
277 1.44 itojun break;
278 1.44 itojun #endif
279 1.23 christos #ifdef NETATALK
280 1.23 christos case AF_APPLETALK:
281 1.23 christos if (!aarpresolve(ifp, m, (struct sockaddr_at *)dst, edst)) {
282 1.23 christos #ifdef NETATALKDEBUG
283 1.23 christos printf("aarpresolv failed\n");
284 1.23 christos #endif /* NETATALKDEBUG */
285 1.23 christos return (0);
286 1.23 christos }
287 1.23 christos /*
288 1.23 christos * ifaddr is the first thing in at_ifaddr
289 1.23 christos */
290 1.23 christos aa = (struct at_ifaddr *) at_ifawithnet(
291 1.25 christos (struct sockaddr_at *)dst, ifp);
292 1.23 christos if (aa == NULL)
293 1.23 christos goto bad;
294 1.23 christos
295 1.23 christos /*
296 1.23 christos * In the phase 2 case, we need to prepend an mbuf for the
297 1.23 christos * llc header. Since we must preserve the value of m,
298 1.23 christos * which is passed to us by value, we m_copy() the first
299 1.23 christos * mbuf, and use it for our llc header.
300 1.23 christos */
301 1.23 christos if (aa->aa_flags & AFA_PHASE2) {
302 1.23 christos struct llc llc;
303 1.23 christos
304 1.43 bouyer M_PREPEND(m, sizeof(struct llc), M_DONTWAIT);
305 1.23 christos llc.llc_dsap = llc.llc_ssap = LLC_SNAP_LSAP;
306 1.23 christos llc.llc_control = LLC_UI;
307 1.23 christos bcopy(at_org_code, llc.llc_snap_org_code,
308 1.23 christos sizeof(llc.llc_snap_org_code));
309 1.38 kim llc.llc_snap_ether_type = htons(ETHERTYPE_ATALK);
310 1.23 christos bcopy(&llc, mtod(m, caddr_t), sizeof(struct llc));
311 1.23 christos } else {
312 1.38 kim etype = htons(ETHERTYPE_ATALK);
313 1.23 christos }
314 1.23 christos break;
315 1.23 christos #endif /* NETATALK */
316 1.1 cgd #ifdef NS
317 1.1 cgd case AF_NS:
318 1.17 mycroft etype = htons(ETHERTYPE_NS);
319 1.1 cgd bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
320 1.1 cgd (caddr_t)edst, sizeof (edst));
321 1.1 cgd if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst)))
322 1.1 cgd return (looutput(ifp, m, dst, rt));
323 1.3 hpeyerl /* If broadcasting on a simplex interface, loopback a copy */
324 1.3 hpeyerl if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
325 1.1 cgd mcopy = m_copy(m, 0, (int)M_COPYALL);
326 1.8 mycroft break;
327 1.1 cgd #endif
328 1.32 christos #ifdef IPX
329 1.32 christos case AF_IPX:
330 1.39 christos etype = htons(ETHERTYPE_IPX);
331 1.39 christos bcopy((caddr_t)&(((struct sockaddr_ipx *)dst)->sipx_addr.x_host),
332 1.32 christos (caddr_t)edst, sizeof (edst));
333 1.32 christos /* If broadcasting on a simplex interface, loopback a copy */
334 1.32 christos if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
335 1.32 christos mcopy = m_copy(m, 0, (int)M_COPYALL);
336 1.32 christos break;
337 1.32 christos #endif
338 1.1 cgd #ifdef ISO
339 1.1 cgd case AF_ISO: {
340 1.1 cgd int snpalen;
341 1.1 cgd struct llc *l;
342 1.29 mrg struct sockaddr_dl *sdl;
343 1.1 cgd
344 1.8 mycroft if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway) &&
345 1.8 mycroft sdl->sdl_family == AF_LINK && sdl->sdl_alen > 0) {
346 1.8 mycroft bcopy(LLADDR(sdl), (caddr_t)edst, sizeof(edst));
347 1.18 christos } else {
348 1.18 christos error = iso_snparesolve(ifp, (struct sockaddr_iso *)dst,
349 1.18 christos (char *)edst, &snpalen);
350 1.18 christos if (error)
351 1.18 christos goto bad; /* Not Resolved */
352 1.18 christos }
353 1.3 hpeyerl /* If broadcasting on a simplex interface, loopback a copy */
354 1.8 mycroft if (*edst & 1)
355 1.8 mycroft m->m_flags |= (M_BCAST|M_MCAST);
356 1.3 hpeyerl if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX) &&
357 1.1 cgd (mcopy = m_copy(m, 0, (int)M_COPYALL))) {
358 1.1 cgd M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT);
359 1.1 cgd if (mcopy) {
360 1.1 cgd eh = mtod(mcopy, struct ether_header *);
361 1.1 cgd bcopy((caddr_t)edst,
362 1.1 cgd (caddr_t)eh->ether_dhost, sizeof (edst));
363 1.22 is bcopy(LLADDR(ifp->if_sadl),
364 1.1 cgd (caddr_t)eh->ether_shost, sizeof (edst));
365 1.1 cgd }
366 1.1 cgd }
367 1.1 cgd M_PREPEND(m, 3, M_DONTWAIT);
368 1.1 cgd if (m == NULL)
369 1.1 cgd return (0);
370 1.1 cgd l = mtod(m, struct llc *);
371 1.1 cgd l->llc_dsap = l->llc_ssap = LLC_ISO_LSAP;
372 1.1 cgd l->llc_control = LLC_UI;
373 1.18 christos #ifdef ARGO_DEBUG
374 1.18 christos if (argo_debug[D_ETHER]) {
375 1.1 cgd int i;
376 1.21 christos printf("unoutput: sending pkt to: ");
377 1.1 cgd for (i=0; i<6; i++)
378 1.21 christos printf("%x ", edst[i] & 0xff);
379 1.21 christos printf("\n");
380 1.18 christos }
381 1.18 christos #endif
382 1.8 mycroft } break;
383 1.8 mycroft #endif /* ISO */
384 1.8 mycroft #ifdef LLC
385 1.8 mycroft /* case AF_NSAP: */
386 1.8 mycroft case AF_CCITT: {
387 1.29 mrg struct sockaddr_dl *sdl =
388 1.8 mycroft (struct sockaddr_dl *) rt -> rt_gateway;
389 1.8 mycroft
390 1.8 mycroft if (sdl && sdl->sdl_family == AF_LINK
391 1.8 mycroft && sdl->sdl_alen > 0) {
392 1.8 mycroft bcopy(LLADDR(sdl), (char *)edst,
393 1.8 mycroft sizeof(edst));
394 1.8 mycroft } else goto bad; /* Not a link interface ? Funny ... */
395 1.8 mycroft if ((ifp->if_flags & IFF_SIMPLEX) && (*edst & 1) &&
396 1.8 mycroft (mcopy = m_copy(m, 0, (int)M_COPYALL))) {
397 1.8 mycroft M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT);
398 1.8 mycroft if (mcopy) {
399 1.8 mycroft eh = mtod(mcopy, struct ether_header *);
400 1.8 mycroft bcopy((caddr_t)edst,
401 1.8 mycroft (caddr_t)eh->ether_dhost, sizeof (edst));
402 1.22 is bcopy(LLADDR(ifp->if_sadl),
403 1.8 mycroft (caddr_t)eh->ether_shost, sizeof (edst));
404 1.8 mycroft }
405 1.3 hpeyerl }
406 1.8 mycroft #ifdef LLC_DEBUG
407 1.8 mycroft {
408 1.8 mycroft int i;
409 1.29 mrg struct llc *l = mtod(m, struct llc *);
410 1.8 mycroft
411 1.21 christos printf("ether_output: sending LLC2 pkt to: ");
412 1.8 mycroft for (i=0; i<6; i++)
413 1.21 christos printf("%x ", edst[i] & 0xff);
414 1.21 christos printf(" len 0x%x dsap 0x%x ssap 0x%x control 0x%x\n",
415 1.17 mycroft m->m_pkthdr.len, l->llc_dsap & 0xff, l->llc_ssap &0xff,
416 1.17 mycroft l->llc_control & 0xff);
417 1.8 mycroft
418 1.8 mycroft }
419 1.8 mycroft #endif /* LLC_DEBUG */
420 1.8 mycroft } break;
421 1.8 mycroft #endif /* LLC */
422 1.1 cgd
423 1.31 thorpej case pseudo_AF_HDRCMPLT:
424 1.31 thorpej hdrcmplt = 1;
425 1.31 thorpej eh = (struct ether_header *)dst->sa_data;
426 1.31 thorpej bcopy((caddr_t)eh->ether_shost, (caddr_t)esrc, sizeof (esrc));
427 1.31 thorpej /* FALLTHROUGH */
428 1.31 thorpej
429 1.1 cgd case AF_UNSPEC:
430 1.1 cgd eh = (struct ether_header *)dst->sa_data;
431 1.1 cgd bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst));
432 1.8 mycroft /* AF_UNSPEC doesn't swap the byte order of the ether_type. */
433 1.17 mycroft etype = eh->ether_type;
434 1.8 mycroft break;
435 1.1 cgd
436 1.1 cgd default:
437 1.21 christos printf("%s: can't handle af%d\n", ifp->if_xname,
438 1.1 cgd dst->sa_family);
439 1.8 mycroft senderr(EAFNOSUPPORT);
440 1.1 cgd }
441 1.1 cgd
442 1.1 cgd if (mcopy)
443 1.1 cgd (void) looutput(ifp, mcopy, dst, rt);
444 1.16 mycroft
445 1.50 matt /* If no ether type is set, this must be a 802.2 formatted packet.
446 1.50 matt */
447 1.50 matt if (etype == 0)
448 1.50 matt etype = htons(m->m_pkthdr.len);
449 1.1 cgd /*
450 1.1 cgd * Add local net header. If no space in first mbuf,
451 1.1 cgd * allocate another.
452 1.1 cgd */
453 1.1 cgd M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT);
454 1.8 mycroft if (m == 0)
455 1.8 mycroft senderr(ENOBUFS);
456 1.1 cgd eh = mtod(m, struct ether_header *);
457 1.8 mycroft bcopy((caddr_t)&etype,(caddr_t)&eh->ether_type,
458 1.1 cgd sizeof(eh->ether_type));
459 1.1 cgd bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst));
460 1.31 thorpej if (hdrcmplt)
461 1.31 thorpej bcopy((caddr_t)esrc, (caddr_t)eh->ether_shost,
462 1.31 thorpej sizeof(eh->ether_shost));
463 1.31 thorpej else
464 1.31 thorpej bcopy(LLADDR(ifp->if_sadl), (caddr_t)eh->ether_shost,
465 1.31 thorpej sizeof(eh->ether_shost));
466 1.1 cgd s = splimp();
467 1.1 cgd /*
468 1.1 cgd * Queue message on interface, and start output if interface
469 1.1 cgd * not yet active.
470 1.1 cgd */
471 1.1 cgd if (IF_QFULL(&ifp->if_snd)) {
472 1.1 cgd IF_DROP(&ifp->if_snd);
473 1.1 cgd splx(s);
474 1.8 mycroft senderr(ENOBUFS);
475 1.1 cgd }
476 1.14 mycroft ifp->if_obytes += m->m_pkthdr.len;
477 1.57 mycroft if (m->m_flags & M_MCAST)
478 1.57 mycroft ifp->if_omcasts++;
479 1.1 cgd IF_ENQUEUE(&ifp->if_snd, m);
480 1.1 cgd if ((ifp->if_flags & IFF_OACTIVE) == 0)
481 1.1 cgd (*ifp->if_start)(ifp);
482 1.1 cgd splx(s);
483 1.1 cgd return (error);
484 1.1 cgd
485 1.1 cgd bad:
486 1.1 cgd if (m)
487 1.1 cgd m_freem(m);
488 1.1 cgd return (error);
489 1.1 cgd }
490 1.1 cgd
491 1.1 cgd /*
492 1.1 cgd * Process a received Ethernet packet;
493 1.42 thorpej * the packet is in the mbuf chain m with
494 1.42 thorpej * the ether header.
495 1.1 cgd */
496 1.42 thorpej static void
497 1.42 thorpej ether_input(ifp, m)
498 1.1 cgd struct ifnet *ifp;
499 1.1 cgd struct mbuf *m;
500 1.1 cgd {
501 1.29 mrg struct ifqueue *inq;
502 1.18 christos u_int16_t etype;
503 1.18 christos int s;
504 1.42 thorpej struct ether_header *eh;
505 1.23 christos #if defined (ISO) || defined (LLC) || defined(NETATALK)
506 1.29 mrg struct llc *l;
507 1.18 christos #endif
508 1.1 cgd
509 1.8 mycroft if ((ifp->if_flags & IFF_UP) == 0) {
510 1.8 mycroft m_freem(m);
511 1.8 mycroft return;
512 1.8 mycroft }
513 1.42 thorpej
514 1.42 thorpej eh = mtod(m, struct ether_header *);
515 1.42 thorpej
516 1.1 cgd ifp->if_lastchange = time;
517 1.42 thorpej ifp->if_ibytes += m->m_pkthdr.len;
518 1.8 mycroft if (eh->ether_dhost[0] & 1) {
519 1.8 mycroft if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
520 1.8 mycroft sizeof(etherbroadcastaddr)) == 0)
521 1.8 mycroft m->m_flags |= M_BCAST;
522 1.8 mycroft else
523 1.8 mycroft m->m_flags |= M_MCAST;
524 1.8 mycroft }
525 1.1 cgd if (m->m_flags & (M_BCAST|M_MCAST))
526 1.1 cgd ifp->if_imcasts++;
527 1.1 cgd
528 1.5 deraadt etype = ntohs(eh->ether_type);
529 1.42 thorpej
530 1.42 thorpej /* Strip off the Ethernet header. */
531 1.42 thorpej m_adj(m, sizeof(struct ether_header));
532 1.45 thorpej
533 1.45 thorpej /* If the CRC is still on the packet, trim it off. */
534 1.46 thorpej if (m->m_flags & M_HASFCS)
535 1.45 thorpej m_adj(m, -ETHER_CRC_LEN);
536 1.42 thorpej
537 1.5 deraadt switch (etype) {
538 1.1 cgd #ifdef INET
539 1.1 cgd case ETHERTYPE_IP:
540 1.30 matt #ifdef GATEWAY
541 1.30 matt if (ipflow_fastforward(m))
542 1.30 matt return;
543 1.30 matt #endif
544 1.1 cgd schednetisr(NETISR_IP);
545 1.1 cgd inq = &ipintrq;
546 1.1 cgd break;
547 1.1 cgd
548 1.1 cgd case ETHERTYPE_ARP:
549 1.8 mycroft schednetisr(NETISR_ARP);
550 1.8 mycroft inq = &arpintrq;
551 1.8 mycroft break;
552 1.7 glass
553 1.7 glass case ETHERTYPE_REVARP:
554 1.8 mycroft revarpinput(m); /* XXX queue? */
555 1.1 cgd return;
556 1.1 cgd #endif
557 1.44 itojun #ifdef INET6
558 1.44 itojun case ETHERTYPE_IPV6:
559 1.44 itojun schednetisr(NETISR_IPV6);
560 1.44 itojun inq = &ip6intrq;
561 1.44 itojun break;
562 1.44 itojun #endif
563 1.1 cgd #ifdef NS
564 1.1 cgd case ETHERTYPE_NS:
565 1.1 cgd schednetisr(NETISR_NS);
566 1.1 cgd inq = &nsintrq;
567 1.1 cgd break;
568 1.1 cgd
569 1.32 christos #endif
570 1.32 christos #ifdef IPX
571 1.32 christos case ETHERTYPE_IPX:
572 1.32 christos schednetisr(NETISR_IPX);
573 1.32 christos inq = &ipxintrq;
574 1.32 christos break;
575 1.1 cgd #endif
576 1.23 christos #ifdef NETATALK
577 1.38 kim case ETHERTYPE_ATALK:
578 1.23 christos schednetisr(NETISR_ATALK);
579 1.23 christos inq = &atintrq1;
580 1.23 christos break;
581 1.23 christos case ETHERTYPE_AARP:
582 1.23 christos /* probably this should be done with a NETISR as well */
583 1.23 christos aarpinput(ifp, m); /* XXX */
584 1.23 christos return;
585 1.23 christos #endif /* NETATALK */
586 1.1 cgd default:
587 1.23 christos #if defined (ISO) || defined (LLC) || defined (NETATALK)
588 1.11 mycroft if (etype > ETHERMTU)
589 1.1 cgd goto dropanyway;
590 1.1 cgd l = mtod(m, struct llc *);
591 1.8 mycroft switch (l->llc_dsap) {
592 1.23 christos #ifdef NETATALK
593 1.23 christos case LLC_SNAP_LSAP:
594 1.23 christos switch (l->llc_control) {
595 1.23 christos case LLC_UI:
596 1.23 christos if (l->llc_ssap != LLC_SNAP_LSAP) {
597 1.23 christos goto dropanyway;
598 1.23 christos }
599 1.23 christos
600 1.23 christos if (Bcmp(&(l->llc_snap_org_code)[0],
601 1.23 christos at_org_code, sizeof(at_org_code)) == 0 &&
602 1.23 christos ntohs(l->llc_snap_ether_type) ==
603 1.38 kim ETHERTYPE_ATALK) {
604 1.23 christos inq = &atintrq2;
605 1.23 christos m_adj(m, sizeof(struct llc));
606 1.23 christos schednetisr(NETISR_ATALK);
607 1.23 christos break;
608 1.23 christos }
609 1.23 christos
610 1.23 christos if (Bcmp(&(l->llc_snap_org_code)[0],
611 1.23 christos aarp_org_code,
612 1.23 christos sizeof(aarp_org_code)) == 0 &&
613 1.23 christos ntohs(l->llc_snap_ether_type) ==
614 1.23 christos ETHERTYPE_AARP) {
615 1.23 christos m_adj( m, sizeof(struct llc));
616 1.23 christos aarpinput(ifp, m); /* XXX */
617 1.23 christos return;
618 1.23 christos }
619 1.23 christos
620 1.23 christos default:
621 1.23 christos goto dropanyway;
622 1.23 christos }
623 1.23 christos break;
624 1.23 christos #endif /* NETATALK */
625 1.8 mycroft #ifdef ISO
626 1.8 mycroft case LLC_ISO_LSAP:
627 1.8 mycroft switch (l->llc_control) {
628 1.8 mycroft case LLC_UI:
629 1.8 mycroft /* LLC_UI_P forbidden in class 1 service */
630 1.8 mycroft if ((l->llc_dsap == LLC_ISO_LSAP) &&
631 1.8 mycroft (l->llc_ssap == LLC_ISO_LSAP)) {
632 1.8 mycroft /* LSAP for ISO */
633 1.11 mycroft if (m->m_pkthdr.len > etype)
634 1.11 mycroft m_adj(m, etype - m->m_pkthdr.len);
635 1.8 mycroft m->m_data += 3; /* XXX */
636 1.8 mycroft m->m_len -= 3; /* XXX */
637 1.8 mycroft m->m_pkthdr.len -= 3; /* XXX */
638 1.8 mycroft M_PREPEND(m, sizeof *eh, M_DONTWAIT);
639 1.8 mycroft if (m == 0)
640 1.8 mycroft return;
641 1.8 mycroft *mtod(m, struct ether_header *) = *eh;
642 1.18 christos #ifdef ARGO_DEBUG
643 1.18 christos if (argo_debug[D_ETHER])
644 1.21 christos printf("clnp packet");
645 1.18 christos #endif
646 1.8 mycroft schednetisr(NETISR_ISO);
647 1.8 mycroft inq = &clnlintrq;
648 1.8 mycroft break;
649 1.8 mycroft }
650 1.8 mycroft goto dropanyway;
651 1.8 mycroft
652 1.8 mycroft case LLC_XID:
653 1.8 mycroft case LLC_XID_P:
654 1.8 mycroft if(m->m_len < 6)
655 1.8 mycroft goto dropanyway;
656 1.8 mycroft l->llc_window = 0;
657 1.8 mycroft l->llc_fid = 9;
658 1.8 mycroft l->llc_class = 1;
659 1.8 mycroft l->llc_dsap = l->llc_ssap = 0;
660 1.8 mycroft /* Fall through to */
661 1.8 mycroft case LLC_TEST:
662 1.8 mycroft case LLC_TEST_P:
663 1.8 mycroft {
664 1.8 mycroft struct sockaddr sa;
665 1.29 mrg struct ether_header *eh2;
666 1.8 mycroft int i;
667 1.8 mycroft u_char c = l->llc_dsap;
668 1.8 mycroft
669 1.8 mycroft l->llc_dsap = l->llc_ssap;
670 1.8 mycroft l->llc_ssap = c;
671 1.8 mycroft if (m->m_flags & (M_BCAST | M_MCAST))
672 1.22 is bcopy(LLADDR(ifp->if_sadl),
673 1.8 mycroft (caddr_t)eh->ether_dhost, 6);
674 1.8 mycroft sa.sa_family = AF_UNSPEC;
675 1.8 mycroft sa.sa_len = sizeof(sa);
676 1.8 mycroft eh2 = (struct ether_header *)sa.sa_data;
677 1.8 mycroft for (i = 0; i < 6; i++) {
678 1.22 is eh2->ether_shost[i] = c =
679 1.22 is eh->ether_dhost[i];
680 1.8 mycroft eh2->ether_dhost[i] =
681 1.22 is eh->ether_dhost[i] =
682 1.22 is eh->ether_shost[i];
683 1.8 mycroft eh->ether_shost[i] = c;
684 1.8 mycroft }
685 1.8 mycroft ifp->if_output(ifp, m, &sa, NULL);
686 1.8 mycroft return;
687 1.8 mycroft }
688 1.8 mycroft default:
689 1.8 mycroft m_freem(m);
690 1.8 mycroft return;
691 1.8 mycroft }
692 1.8 mycroft break;
693 1.8 mycroft #endif /* ISO */
694 1.8 mycroft #ifdef LLC
695 1.8 mycroft case LLC_X25_LSAP:
696 1.8 mycroft {
697 1.11 mycroft if (m->m_pkthdr.len > etype)
698 1.11 mycroft m_adj(m, etype - m->m_pkthdr.len);
699 1.8 mycroft M_PREPEND(m, sizeof(struct sdl_hdr) , M_DONTWAIT);
700 1.1 cgd if (m == 0)
701 1.1 cgd return;
702 1.8 mycroft if ( !sdl_sethdrif(ifp, eh->ether_shost, LLC_X25_LSAP,
703 1.8 mycroft eh->ether_dhost, LLC_X25_LSAP, 6,
704 1.8 mycroft mtod(m, struct sdl_hdr *)))
705 1.8 mycroft panic("ETHER cons addr failure");
706 1.11 mycroft mtod(m, struct sdl_hdr *)->sdlhdr_len = etype;
707 1.8 mycroft #ifdef LLC_DEBUG
708 1.21 christos printf("llc packet\n");
709 1.8 mycroft #endif /* LLC_DEBUG */
710 1.8 mycroft schednetisr(NETISR_CCITT);
711 1.8 mycroft inq = &llcintrq;
712 1.1 cgd break;
713 1.1 cgd }
714 1.8 mycroft #endif /* LLC */
715 1.1 cgd dropanyway:
716 1.1 cgd default:
717 1.8 mycroft m_freem(m);
718 1.8 mycroft return;
719 1.8 mycroft }
720 1.23 christos #else /* ISO || LLC || NETATALK*/
721 1.1 cgd m_freem(m);
722 1.1 cgd return;
723 1.23 christos #endif /* ISO || LLC || NETATALK*/
724 1.1 cgd }
725 1.1 cgd
726 1.1 cgd s = splimp();
727 1.1 cgd if (IF_QFULL(inq)) {
728 1.1 cgd IF_DROP(inq);
729 1.1 cgd m_freem(m);
730 1.1 cgd } else
731 1.1 cgd IF_ENQUEUE(inq, m);
732 1.1 cgd splx(s);
733 1.1 cgd }
734 1.1 cgd
735 1.1 cgd /*
736 1.1 cgd * Convert Ethernet address to printable (loggable) representation.
737 1.1 cgd */
738 1.1 cgd static char digits[] = "0123456789abcdef";
739 1.1 cgd char *
740 1.1 cgd ether_sprintf(ap)
741 1.40 thorpej const u_char *ap;
742 1.1 cgd {
743 1.1 cgd static char etherbuf[18];
744 1.29 mrg char *cp = etherbuf;
745 1.29 mrg int i;
746 1.1 cgd
747 1.1 cgd for (i = 0; i < 6; i++) {
748 1.1 cgd *cp++ = digits[*ap >> 4];
749 1.1 cgd *cp++ = digits[*ap++ & 0xf];
750 1.1 cgd *cp++ = ':';
751 1.1 cgd }
752 1.1 cgd *--cp = 0;
753 1.1 cgd return (etherbuf);
754 1.1 cgd }
755 1.8 mycroft
756 1.8 mycroft /*
757 1.8 mycroft * Perform common duties while attaching to interface list
758 1.8 mycroft */
759 1.8 mycroft void
760 1.22 is ether_ifattach(ifp, lla)
761 1.29 mrg struct ifnet *ifp;
762 1.41 thorpej const u_int8_t *lla;
763 1.8 mycroft {
764 1.29 mrg struct sockaddr_dl *sdl;
765 1.8 mycroft
766 1.8 mycroft ifp->if_type = IFT_ETHER;
767 1.8 mycroft ifp->if_addrlen = 6;
768 1.8 mycroft ifp->if_hdrlen = 14;
769 1.8 mycroft ifp->if_mtu = ETHERMTU;
770 1.12 mycroft ifp->if_output = ether_output;
771 1.42 thorpej ifp->if_input = ether_input;
772 1.54 thorpej if (ifp->if_baudrate == 0)
773 1.54 thorpej ifp->if_baudrate = IF_Mbps(10); /* just a default */
774 1.22 is if ((sdl = ifp->if_sadl) &&
775 1.22 is sdl->sdl_family == AF_LINK) {
776 1.22 is sdl->sdl_type = IFT_ETHER;
777 1.22 is sdl->sdl_alen = ifp->if_addrlen;
778 1.41 thorpej bcopy(lla, LLADDR(sdl), ifp->if_addrlen);
779 1.22 is }
780 1.22 is LIST_INIT(&((struct ethercom *)ifp)->ec_multiaddrs);
781 1.26 is ifp->if_broadcastaddr = etherbroadcastaddr;
782 1.52 thorpej }
783 1.52 thorpej
784 1.52 thorpej void
785 1.52 thorpej ether_ifdetach(ifp)
786 1.52 thorpej struct ifnet *ifp;
787 1.52 thorpej {
788 1.52 thorpej
789 1.52 thorpej /* Nothing. */
790 1.53 thorpej }
791 1.53 thorpej
792 1.56 thorpej #if 0
793 1.56 thorpej /*
794 1.56 thorpej * This is for reference. We have a table-driven version
795 1.56 thorpej * of the little-endian crc32 generator, which is faster
796 1.56 thorpej * than the double-loop.
797 1.56 thorpej */
798 1.53 thorpej u_int32_t
799 1.53 thorpej ether_crc32_le(buf, len)
800 1.53 thorpej const u_int8_t *buf;
801 1.53 thorpej size_t len;
802 1.53 thorpej {
803 1.53 thorpej u_int32_t c, crc, carry;
804 1.53 thorpej size_t i, j;
805 1.53 thorpej
806 1.53 thorpej crc = 0xffffffffU; /* initial value */
807 1.53 thorpej
808 1.53 thorpej for (i = 0; i < len; i++) {
809 1.53 thorpej c = buf[i];
810 1.53 thorpej for (j = 0; j < 8; j++) {
811 1.53 thorpej carry = ((crc & 0x01) ? 1 : 0) ^ (c & 0x01);
812 1.53 thorpej crc >>= 1;
813 1.53 thorpej c >>= 1;
814 1.53 thorpej if (carry)
815 1.56 thorpej crc = (crc ^ ETHER_CRC_POLY_LE);
816 1.53 thorpej }
817 1.53 thorpej }
818 1.53 thorpej
819 1.53 thorpej return (crc);
820 1.53 thorpej }
821 1.56 thorpej #else
822 1.56 thorpej u_int32_t
823 1.56 thorpej ether_crc32_le(buf, len)
824 1.56 thorpej const u_int8_t *buf;
825 1.56 thorpej size_t len;
826 1.56 thorpej {
827 1.56 thorpej static const u_int32_t crctab[] = {
828 1.56 thorpej 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
829 1.56 thorpej 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
830 1.56 thorpej 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
831 1.56 thorpej 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
832 1.56 thorpej };
833 1.56 thorpej u_int32_t crc;
834 1.56 thorpej int i;
835 1.56 thorpej
836 1.56 thorpej crc = 0xffffffffU; /* initial value */
837 1.56 thorpej
838 1.56 thorpej for (i = 0; i < len; i++) {
839 1.56 thorpej crc ^= buf[i];
840 1.56 thorpej crc = (crc >> 4) ^ crctab[crc & 0xf];
841 1.56 thorpej crc = (crc >> 4) ^ crctab[crc & 0xf];
842 1.56 thorpej }
843 1.56 thorpej
844 1.56 thorpej return (crc);
845 1.56 thorpej }
846 1.56 thorpej #endif
847 1.53 thorpej
848 1.53 thorpej u_int32_t
849 1.53 thorpej ether_crc32_be(buf, len)
850 1.53 thorpej const u_int8_t *buf;
851 1.53 thorpej size_t len;
852 1.53 thorpej {
853 1.53 thorpej u_int32_t c, crc, carry;
854 1.53 thorpej size_t i, j;
855 1.53 thorpej
856 1.53 thorpej crc = 0xffffffffU; /* initial value */
857 1.53 thorpej
858 1.53 thorpej for (i = 0; i < len; i++) {
859 1.53 thorpej c = buf[i];
860 1.53 thorpej for (j = 0; j < 8; j++) {
861 1.53 thorpej carry = ((crc & 0x80000000U) ? 1 : 0) ^ (c & 0x01);
862 1.53 thorpej crc <<= 1;
863 1.53 thorpej c >>= 1;
864 1.53 thorpej if (carry)
865 1.53 thorpej crc = (crc ^ ETHER_CRC_POLY_BE) | carry;
866 1.53 thorpej }
867 1.53 thorpej }
868 1.53 thorpej
869 1.53 thorpej return (crc);
870 1.8 mycroft }
871 1.8 mycroft
872 1.48 is #ifdef INET
873 1.3 hpeyerl u_char ether_ipmulticast_min[6] = { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 };
874 1.3 hpeyerl u_char ether_ipmulticast_max[6] = { 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xff };
875 1.48 is #endif
876 1.44 itojun #ifdef INET6
877 1.44 itojun u_char ether_ip6multicast_min[6] = { 0x33, 0x33, 0x00, 0x00, 0x00, 0x00 };
878 1.44 itojun u_char ether_ip6multicast_max[6] = { 0x33, 0x33, 0xff, 0xff, 0xff, 0xff };
879 1.44 itojun #endif
880 1.3 hpeyerl /*
881 1.3 hpeyerl * Add an Ethernet multicast address or range of addresses to the list for a
882 1.3 hpeyerl * given interface.
883 1.3 hpeyerl */
884 1.3 hpeyerl int
885 1.22 is ether_addmulti(ifr, ec)
886 1.3 hpeyerl struct ifreq *ifr;
887 1.29 mrg struct ethercom *ec;
888 1.3 hpeyerl {
889 1.29 mrg struct ether_multi *enm;
890 1.24 christos #ifdef INET
891 1.3 hpeyerl struct sockaddr_in *sin;
892 1.24 christos #endif /* INET */
893 1.44 itojun #ifdef INET6
894 1.44 itojun struct sockaddr_in6 *sin6;
895 1.44 itojun #endif /* INET6 */
896 1.3 hpeyerl u_char addrlo[6];
897 1.3 hpeyerl u_char addrhi[6];
898 1.3 hpeyerl int s = splimp();
899 1.3 hpeyerl
900 1.3 hpeyerl switch (ifr->ifr_addr.sa_family) {
901 1.3 hpeyerl
902 1.3 hpeyerl case AF_UNSPEC:
903 1.3 hpeyerl bcopy(ifr->ifr_addr.sa_data, addrlo, 6);
904 1.3 hpeyerl bcopy(addrlo, addrhi, 6);
905 1.3 hpeyerl break;
906 1.3 hpeyerl
907 1.3 hpeyerl #ifdef INET
908 1.3 hpeyerl case AF_INET:
909 1.3 hpeyerl sin = (struct sockaddr_in *)&(ifr->ifr_addr);
910 1.3 hpeyerl if (sin->sin_addr.s_addr == INADDR_ANY) {
911 1.3 hpeyerl /*
912 1.3 hpeyerl * An IP address of INADDR_ANY means listen to all
913 1.3 hpeyerl * of the Ethernet multicast addresses used for IP.
914 1.3 hpeyerl * (This is for the sake of IP multicast routers.)
915 1.3 hpeyerl */
916 1.3 hpeyerl bcopy(ether_ipmulticast_min, addrlo, 6);
917 1.3 hpeyerl bcopy(ether_ipmulticast_max, addrhi, 6);
918 1.3 hpeyerl }
919 1.3 hpeyerl else {
920 1.3 hpeyerl ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo);
921 1.3 hpeyerl bcopy(addrlo, addrhi, 6);
922 1.3 hpeyerl }
923 1.3 hpeyerl break;
924 1.3 hpeyerl #endif
925 1.44 itojun #ifdef INET6
926 1.44 itojun case AF_INET6:
927 1.44 itojun sin6 = (struct sockaddr_in6 *)
928 1.44 itojun &(((struct in6_ifreq *)ifr)->ifr_addr);
929 1.47 itojun if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
930 1.44 itojun /*
931 1.44 itojun * An IP6 address of 0 means listen to all
932 1.44 itojun * of the Ethernet multicast address used for IP6.
933 1.44 itojun * (This is used for multicast routers.)
934 1.44 itojun */
935 1.44 itojun bcopy(ether_ip6multicast_min, addrlo, ETHER_ADDR_LEN);
936 1.44 itojun bcopy(ether_ip6multicast_max, addrhi, ETHER_ADDR_LEN);
937 1.44 itojun #if 0
938 1.44 itojun set_allmulti = 1;
939 1.44 itojun #endif
940 1.44 itojun } else {
941 1.44 itojun ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, addrlo);
942 1.44 itojun bcopy(addrlo, addrhi, ETHER_ADDR_LEN);
943 1.44 itojun }
944 1.44 itojun break;
945 1.44 itojun #endif
946 1.3 hpeyerl
947 1.3 hpeyerl default:
948 1.3 hpeyerl splx(s);
949 1.3 hpeyerl return (EAFNOSUPPORT);
950 1.3 hpeyerl }
951 1.3 hpeyerl
952 1.3 hpeyerl /*
953 1.3 hpeyerl * Verify that we have valid Ethernet multicast addresses.
954 1.3 hpeyerl */
955 1.3 hpeyerl if ((addrlo[0] & 0x01) != 1 || (addrhi[0] & 0x01) != 1) {
956 1.3 hpeyerl splx(s);
957 1.3 hpeyerl return (EINVAL);
958 1.3 hpeyerl }
959 1.3 hpeyerl /*
960 1.3 hpeyerl * See if the address range is already in the list.
961 1.3 hpeyerl */
962 1.22 is ETHER_LOOKUP_MULTI(addrlo, addrhi, ec, enm);
963 1.3 hpeyerl if (enm != NULL) {
964 1.3 hpeyerl /*
965 1.3 hpeyerl * Found it; just increment the reference count.
966 1.3 hpeyerl */
967 1.3 hpeyerl ++enm->enm_refcount;
968 1.3 hpeyerl splx(s);
969 1.3 hpeyerl return (0);
970 1.3 hpeyerl }
971 1.3 hpeyerl /*
972 1.3 hpeyerl * New address or range; malloc a new multicast record
973 1.3 hpeyerl * and link it into the interface's multicast list.
974 1.3 hpeyerl */
975 1.3 hpeyerl enm = (struct ether_multi *)malloc(sizeof(*enm), M_IFMADDR, M_NOWAIT);
976 1.3 hpeyerl if (enm == NULL) {
977 1.3 hpeyerl splx(s);
978 1.3 hpeyerl return (ENOBUFS);
979 1.3 hpeyerl }
980 1.3 hpeyerl bcopy(addrlo, enm->enm_addrlo, 6);
981 1.3 hpeyerl bcopy(addrhi, enm->enm_addrhi, 6);
982 1.22 is enm->enm_ec = ec;
983 1.3 hpeyerl enm->enm_refcount = 1;
984 1.22 is LIST_INSERT_HEAD(&ec->ec_multiaddrs, enm, enm_list);
985 1.22 is ec->ec_multicnt++;
986 1.3 hpeyerl splx(s);
987 1.3 hpeyerl /*
988 1.3 hpeyerl * Return ENETRESET to inform the driver that the list has changed
989 1.3 hpeyerl * and its reception filter should be adjusted accordingly.
990 1.3 hpeyerl */
991 1.3 hpeyerl return (ENETRESET);
992 1.3 hpeyerl }
993 1.3 hpeyerl
994 1.3 hpeyerl /*
995 1.3 hpeyerl * Delete a multicast address record.
996 1.3 hpeyerl */
997 1.3 hpeyerl int
998 1.22 is ether_delmulti(ifr, ec)
999 1.3 hpeyerl struct ifreq *ifr;
1000 1.29 mrg struct ethercom *ec;
1001 1.3 hpeyerl {
1002 1.29 mrg struct ether_multi *enm;
1003 1.24 christos #ifdef INET
1004 1.3 hpeyerl struct sockaddr_in *sin;
1005 1.24 christos #endif /* INET */
1006 1.44 itojun #ifdef INET6
1007 1.44 itojun struct sockaddr_in6 *sin6;
1008 1.44 itojun #endif /* INET6 */
1009 1.3 hpeyerl u_char addrlo[6];
1010 1.3 hpeyerl u_char addrhi[6];
1011 1.3 hpeyerl int s = splimp();
1012 1.3 hpeyerl
1013 1.3 hpeyerl switch (ifr->ifr_addr.sa_family) {
1014 1.3 hpeyerl
1015 1.3 hpeyerl case AF_UNSPEC:
1016 1.3 hpeyerl bcopy(ifr->ifr_addr.sa_data, addrlo, 6);
1017 1.3 hpeyerl bcopy(addrlo, addrhi, 6);
1018 1.3 hpeyerl break;
1019 1.3 hpeyerl
1020 1.3 hpeyerl #ifdef INET
1021 1.3 hpeyerl case AF_INET:
1022 1.3 hpeyerl sin = (struct sockaddr_in *)&(ifr->ifr_addr);
1023 1.3 hpeyerl if (sin->sin_addr.s_addr == INADDR_ANY) {
1024 1.3 hpeyerl /*
1025 1.3 hpeyerl * An IP address of INADDR_ANY means stop listening
1026 1.3 hpeyerl * to the range of Ethernet multicast addresses used
1027 1.3 hpeyerl * for IP.
1028 1.3 hpeyerl */
1029 1.3 hpeyerl bcopy(ether_ipmulticast_min, addrlo, 6);
1030 1.3 hpeyerl bcopy(ether_ipmulticast_max, addrhi, 6);
1031 1.3 hpeyerl }
1032 1.3 hpeyerl else {
1033 1.3 hpeyerl ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo);
1034 1.3 hpeyerl bcopy(addrlo, addrhi, 6);
1035 1.44 itojun }
1036 1.44 itojun break;
1037 1.44 itojun #endif
1038 1.44 itojun #ifdef INET6
1039 1.44 itojun case AF_INET6:
1040 1.44 itojun sin6 = (struct sockaddr_in6 *)&(ifr->ifr_addr);
1041 1.47 itojun if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
1042 1.44 itojun /*
1043 1.44 itojun * An IP6 address of all 0 means stop listening
1044 1.44 itojun * to the range of Ethernet multicast addresses used
1045 1.44 itojun * for IP6
1046 1.44 itojun */
1047 1.44 itojun bcopy(ether_ip6multicast_min, addrlo, ETHER_ADDR_LEN);
1048 1.44 itojun bcopy(ether_ip6multicast_max, addrhi, ETHER_ADDR_LEN);
1049 1.44 itojun } else {
1050 1.44 itojun ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, addrlo);
1051 1.44 itojun bcopy(addrlo, addrhi, ETHER_ADDR_LEN);
1052 1.3 hpeyerl }
1053 1.3 hpeyerl break;
1054 1.3 hpeyerl #endif
1055 1.3 hpeyerl
1056 1.3 hpeyerl default:
1057 1.3 hpeyerl splx(s);
1058 1.3 hpeyerl return (EAFNOSUPPORT);
1059 1.3 hpeyerl }
1060 1.3 hpeyerl
1061 1.3 hpeyerl /*
1062 1.3 hpeyerl * Look up the address in our list.
1063 1.3 hpeyerl */
1064 1.22 is ETHER_LOOKUP_MULTI(addrlo, addrhi, ec, enm);
1065 1.3 hpeyerl if (enm == NULL) {
1066 1.3 hpeyerl splx(s);
1067 1.3 hpeyerl return (ENXIO);
1068 1.3 hpeyerl }
1069 1.3 hpeyerl if (--enm->enm_refcount != 0) {
1070 1.3 hpeyerl /*
1071 1.3 hpeyerl * Still some claims to this record.
1072 1.3 hpeyerl */
1073 1.3 hpeyerl splx(s);
1074 1.3 hpeyerl return (0);
1075 1.3 hpeyerl }
1076 1.3 hpeyerl /*
1077 1.3 hpeyerl * No remaining claims to this record; unlink and free it.
1078 1.3 hpeyerl */
1079 1.13 mycroft LIST_REMOVE(enm, enm_list);
1080 1.3 hpeyerl free(enm, M_IFMADDR);
1081 1.22 is ec->ec_multicnt--;
1082 1.3 hpeyerl splx(s);
1083 1.3 hpeyerl /*
1084 1.3 hpeyerl * Return ENETRESET to inform the driver that the list has changed
1085 1.3 hpeyerl * and its reception filter should be adjusted accordingly.
1086 1.3 hpeyerl */
1087 1.3 hpeyerl return (ENETRESET);
1088 1.3 hpeyerl }
1089