1 /*
2 * Copyright (c) 1982, 1989, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * @(#)if_ethersubr.c 8.1 (Berkeley) 6/10/93
34 * $FreeBSD: src/sys/net/if_ethersubr.c,v 1.26.2.6 1999/09/05 08:17:36 peter Exp $
35 */
36
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/kernel.h>
40 #include <sys/malloc.h>
41 #include <sys/mbuf.h>
42 #include <sys/protosw.h>
43 #include <sys/socket.h>
44 #include <sys/ioctl.h>
45 #include <sys/errno.h>
46 #include <sys/syslog.h>
47 #include <sys/sysctl.h>
48
49 #include <net/if.h>
50 #include <net/netisr.h>
51 #include <net/route.h>
52 #include <net/if_llc.h>
53 #include <net/if_dl.h>
54 #include <net/if_types.h>
55 #include <net/ethernet.h>
56
57 #ifdef INET
58 #include <netinet/in.h>
59 #include <netinet/in_var.h>
60 #endif
61 #include <netinet/if_ether.h>
62
63 #ifdef IPX
64 #include <netipx/ipx.h>
65 #include <netipx/ipx_if.h>
66 #endif
67
68 #ifdef NS
69 #include <netns/ns.h>
70 #include <netns/ns_if.h>
71 ushort ns_nettype;
72 int ether_outputdebug = 0;
73 int ether_inputdebug = 0;
74 #endif
75
76 #ifdef ISO
77 #include <netiso/argo_debug.h>
78 #include <netiso/iso.h>
79 #include <netiso/iso_var.h>
80 #include <netiso/iso_snpac.h>
81 #endif
82
83 /*#ifdef LLC
84 #include <netccitt/dll.h>
85 #include <netccitt/llc_var.h>
86 #endif*/
87
88 #if defined(LLC) && defined(CCITT)
89 extern struct ifqueue pkintrq;
90 #endif
91
92 #ifdef NETATALK
93 #include <netatalk/at.h>
94 #include <netatalk/at_var.h>
95 #include <netatalk/at_extern.h>
96
97 #define llc_snap_org_code llc_un.type_snap.org_code
98 #define llc_snap_ether_type llc_un.type_snap.ether_type
99
100 extern u_char at_org_code[ 3 ];
101 extern u_char aarp_org_code[ 3 ];
102 #endif NETATALK
103
104 #ifdef BRIDGE
105 #include <net/bridge.h>
106 #endif
107
108 u_char etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
109 #define senderr(e) { error = (e); goto bad;}
110
111 /*
112 * Ethernet output routine.
113 * Encapsulate a packet of type family for the local net.
114 * Use trailer local net encapsulation if enough data in first
115 * packet leaves a multiple of 512 bytes of data in remainder.
116 * Assumes that ifp is actually pointer to arpcom structure.
117 */
118 int
119 ether_output(ifp, m0, dst, rt0)
120 register struct ifnet *ifp;
121 struct mbuf *m0;
122 struct sockaddr *dst;
123 struct rtentry *rt0;
124 {
125 short type;
126 int s, error = 0;
127 u_char *cp, edst[6];
128 register struct mbuf *m2, *m = m0;
129 register struct rtentry *rt;
130 struct mbuf *mcopy = (struct mbuf *)0;
131 register struct ether_header *eh;
132 int off, len = m->m_pkthdr.len;
133 struct arpcom *ac = (struct arpcom *)ifp;
134 register struct ifqueue *inq;
135 #ifdef NETATALK
136 struct at_ifaddr *aa;
137 #endif NETATALK
138
139 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
140 senderr(ENETDOWN);
141 rt = rt0;
142 if (rt) {
143 if ((rt->rt_flags & RTF_UP) == 0) {
144 rt0 = rt = rtalloc1(dst, 1, 0UL);
145 if (rt0)
146 rt->rt_refcnt--;
147 else
148 senderr(EHOSTUNREACH);
149 }
150 if (rt->rt_flags & RTF_GATEWAY) {
151 if (rt->rt_gwroute == 0)
152 goto lookup;
153 if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
154 rtfree(rt); rt = rt0;
155 lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1,
156 0UL);
157 if ((rt = rt->rt_gwroute) == 0)
158 senderr(EHOSTUNREACH);
159 }
160 }
161 if (rt->rt_flags & RTF_REJECT)
162 if (rt->rt_rmx.rmx_expire == 0 ||
163 time.tv_sec < rt->rt_rmx.rmx_expire)
164 senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
165 }
166 switch (dst->sa_family) {
167
168 #ifdef INET
169 case AF_INET:
170 if (!arpresolve(ac, rt, m, dst, edst, rt0))
171 return (0); /* if not yet resolved */
172 /* If broadcasting on a simplex interface, loopback a copy */
173 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
174 mcopy = m_copy(m, 0, (int)M_COPYALL);
175 off = m->m_pkthdr.len - m->m_len;
176 type = htons(ETHERTYPE_IP);
177 break;
178 #endif
179 #ifdef IPX
180 case AF_IPX:
181 {
182 struct ifaddr *ia;
183
184 type = htons(ETHERTYPE_IPX);
185 bcopy((caddr_t)&(((struct sockaddr_ipx *)dst)->sipx_addr.x_host),
186 (caddr_t)edst, sizeof (edst));
187 for (ia = ifp->if_addrlist; ia != NULL; ia = ia->ifa_next)
188 if(ia->ifa_addr->sa_family == AF_IPX &&
189 !bcmp((caddr_t)edst,
190 (caddr_t)&((struct ipx_ifaddr *)ia)->ia_addr.sipx_addr.x_host,
191 sizeof(edst)))
192 return (looutput(ifp, m, dst, rt));
193 /* If broadcasting on a simplex interface, loopback a copy */
194 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
195 mcopy = m_copy(m, 0, (int)M_COPYALL);
196 break;
197 }
198 #endif
199 #ifdef NETATALK
200 case AF_APPLETALK:
201 {
202 struct sockaddr_at *sat = (struct sockaddr_at *)dst;
203
204 /*
205 * super hack..
206 * Most of this loopback code should move into the appletalk
207 * code, but it's here for now.. remember to move it! [JRE]
208 * This may not get the same interface we started with
209 * fix asap. XXX
210 */
211 aa = at_ifawithnet( sat );
212 if (aa == NULL) {
213 goto bad;
214 }
215 if( aa->aa_ifa.ifa_ifp != ifp ) {
216 (*aa->aa_ifa.ifa_ifp->if_output)(aa->aa_ifa.ifa_ifp,
217 m,dst,rt);
218 }
219 if (((sat->sat_addr.s_net == ATADDR_ANYNET)
220 && (sat->sat_addr.s_node == ATADDR_ANYNODE))
221 || ((sat->sat_addr.s_net == aa->aa_addr.sat_addr.s_net )
222 && (sat->sat_addr.s_node == aa->aa_addr.sat_addr.s_node))) {
223 (void) looutput(ifp, m, dst, rt);
224 return(0);
225 }
226
227 if (!aarpresolve(ac, m, (struct sockaddr_at *)dst, edst)) {
228 #ifdef NETATALKDEBUG
229 extern char *prsockaddr(struct sockaddr *);
230 printf("aarpresolv: failed for %s\n", prsockaddr(dst));
231 #endif NETATALKDEBUG
232 return (0);
233 }
234
235 /*
236 * If broadcasting on a simplex interface, loopback a copy
237 */
238 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
239 mcopy = m_copy(m, 0, (int)M_COPYALL);
240 }
241 /*
242 * In the phase 2 case, we need to prepend an mbuf for the llc header.
243 * Since we must preserve the value of m, which is passed to us by
244 * value, we m_copy() the first mbuf, and use it for our llc header.
245 */
246 if ( aa->aa_flags & AFA_PHASE2 ) {
247 struct llc llc;
248
249 M_PREPEND(m, sizeof(struct llc), M_WAIT);
250 len += sizeof(struct llc);
251 llc.llc_dsap = llc.llc_ssap = LLC_SNAP_LSAP;
252 llc.llc_control = LLC_UI;
253 bcopy(at_org_code, llc.llc_snap_org_code, sizeof(at_org_code));
254 llc.llc_snap_ether_type = htons( ETHERTYPE_AT );
255 bcopy(&llc, mtod(m, caddr_t), sizeof(struct llc));
256 type = htons(m->m_pkthdr.len);
257 } else {
258 type = htons(ETHERTYPE_AT);
259 }
260 break;
261 #endif NETATALK
262 #ifdef NS
263 case AF_NS:
264 switch(ns_nettype){
265 default:
266 case 0x8137: /* Novell Ethernet_II Ethernet TYPE II */
267 type = 0x8137;
268 break;
269 case 0x0: /* Novell 802.3 */
270 type = htons( m->m_pkthdr.len);
271 break;
272 case 0xe0e0: /* Novell 802.2 and Token-Ring */
273 M_PREPEND(m, 3, M_WAIT);
274 type = htons( m->m_pkthdr.len);
275 cp = mtod(m, u_char *);
276 *cp++ = 0xE0;
277 *cp++ = 0xE0;
278 *cp++ = 0x03;
279 break;
280 }
281 bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
282 (caddr_t)edst, sizeof (edst));
283 if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst))){
284 m->m_pkthdr.rcvif = ifp;
285 schednetisr(NETISR_NS);
286 inq = &nsintrq;
287 s = splimp();
288 if (IF_QFULL(inq)) {
289 IF_DROP(inq);
290 m_freem(m);
291 } else
292 IF_ENQUEUE(inq, m);
293 splx(s);
294 return (error);
295 }
296 if (!bcmp((caddr_t)edst, (caddr_t)&ns_broadhost, sizeof(edst))){
297 m2 = m_copy(m, 0, (int)M_COPYALL);
298 m2->m_pkthdr.rcvif = ifp;
299 schednetisr(NETISR_NS);
300 inq = &nsintrq;
301 s = splimp();
302 if (IF_QFULL(inq)) {
303 IF_DROP(inq);
304 m_freem(m2);
305 } else
306 IF_ENQUEUE(inq, m2);
307 splx(s);
308 }
309 /* If broadcasting on a simplex interface, loopback a copy */
310 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX)){
311 mcopy = m_copy(m, 0, (int)M_COPYALL);
312 }
313 break;
314 #endif /* NS */
315 #ifdef ISO
316 case AF_ISO: {
317 int snpalen;
318 struct llc *l;
319 register struct sockaddr_dl *sdl;
320
321 if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway) &&
322 sdl->sdl_family == AF_LINK && sdl->sdl_alen > 0) {
323 bcopy(LLADDR(sdl), (caddr_t)edst, sizeof(edst));
324 } else if (error =
325 iso_snparesolve(ifp, (struct sockaddr_iso *)dst,
326 (char *)edst, &snpalen))
327 goto bad; /* Not Resolved */
328 /* If broadcasting on a simplex interface, loopback a copy */
329 if (*edst & 1)
330 m->m_flags |= (M_BCAST|M_MCAST);
331 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX) &&
332 (mcopy = m_copy(m, 0, (int)M_COPYALL))) {
333 M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT);
334 if (mcopy) {
335 eh = mtod(mcopy, struct ether_header *);
336 bcopy((caddr_t)edst,
337 (caddr_t)eh->ether_dhost, sizeof (edst));
338 bcopy((caddr_t)ac->ac_enaddr,
339 (caddr_t)eh->ether_shost, sizeof (edst));
340 }
341 }
342 M_PREPEND(m, 3, M_DONTWAIT);
343 if (m == NULL)
344 return (0);
345 type = htons(m->m_pkthdr.len);
346 l = mtod(m, struct llc *);
347 l->llc_dsap = l->llc_ssap = LLC_ISO_LSAP;
348 l->llc_control = LLC_UI;
349 len += 3;
350 IFDEBUG(D_ETHER)
351 int i;
352 printf("unoutput: sending pkt to: ");
353 for (i=0; i<6; i++)
354 printf("%x ", edst[i] & 0xff);
355 printf("\n");
356 ENDDEBUG
357 } break;
358 #endif /* ISO */
359 #ifdef LLC
360 /* case AF_NSAP: */
361 case AF_CCITT: {
362 register struct sockaddr_dl *sdl =
363 (struct sockaddr_dl *) rt -> rt_gateway;
364
365 if (sdl && sdl->sdl_family == AF_LINK
366 && sdl->sdl_alen > 0) {
367 bcopy(LLADDR(sdl), (char *)edst,
368 sizeof(edst));
369 } else goto bad; /* Not a link interface ? Funny ... */
370 if ((ifp->if_flags & IFF_SIMPLEX) && (*edst & 1) &&
371 (mcopy = m_copy(m, 0, (int)M_COPYALL))) {
372 M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT);
373 if (mcopy) {
374 eh = mtod(mcopy, struct ether_header *);
375 bcopy((caddr_t)edst,
376 (caddr_t)eh->ether_dhost, sizeof (edst));
377 bcopy((caddr_t)ac->ac_enaddr,
378 (caddr_t)eh->ether_shost, sizeof (edst));
379 }
380 }
381 type = htons(m->m_pkthdr.len);
382 #ifdef LLC_DEBUG
383 {
384 int i;
385 register struct llc *l = mtod(m, struct llc *);
386
387 printf("ether_output: sending LLC2 pkt to: ");
388 for (i=0; i<6; i++)
389 printf("%x ", edst[i] & 0xff);
390 printf(" len 0x%x dsap 0x%x ssap 0x%x control 0x%x\n",
391 type & 0xff, l->llc_dsap & 0xff, l->llc_ssap &0xff,
392 l->llc_control & 0xff);
393
394 }
395 #endif /* LLC_DEBUG */
396 } break;
397 #endif /* LLC */
398
399 case AF_UNSPEC:
400 eh = (struct ether_header *)dst->sa_data;
401 (void)memcpy(edst, eh->ether_dhost, sizeof (edst));
402 type = eh->ether_type;
403 break;
404
405 default:
406 printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit,
407 dst->sa_family);
408 senderr(EAFNOSUPPORT);
409 }
410
411
412 if (mcopy)
413 (void) looutput(ifp, mcopy, dst, rt);
414 /*
415 * Add local net header. If no space in first mbuf,
416 * allocate another.
417 */
418 M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT);
419 if (m == 0)
420 senderr(ENOBUFS);
421 eh = mtod(m, struct ether_header *);
422 (void)memcpy(&eh->ether_type, &type,
423 sizeof(eh->ether_type));
424 (void)memcpy(eh->ether_dhost, edst, sizeof (edst));
425 (void)memcpy(eh->ether_shost, ac->ac_enaddr,
426 sizeof(eh->ether_shost));
427 #ifdef BRIDGE
428 if (do_bridge) {
429 struct ifnet *old_ifp = ifp ;
430 struct mbuf *m0 = m ;
431 if (m->m_pkthdr.rcvif )
432 m->m_pkthdr.rcvif = NULL ;
433 ifp = bridge_dst_lookup(m);
434 bdg_forward(&m0, ifp);
435 if (m0)
436 m_freem(m0);
437 return 0 ;
438 }
439 #endif
440 s = splimp();
441 /*
442 * Queue message on interface, and start output if interface
443 * not yet active.
444 */
445 if (IF_QFULL(&ifp->if_snd)) {
446 IF_DROP(&ifp->if_snd);
447 splx(s);
448 senderr(ENOBUFS);
449 }
450 IF_ENQUEUE(&ifp->if_snd, m);
451 if ((ifp->if_flags & IFF_OACTIVE) == 0)
452 (*ifp->if_start)(ifp);
453 splx(s);
454 ifp->if_obytes += len + sizeof (struct ether_header);
455 if (m->m_flags & M_MCAST)
456 ifp->if_omcasts++;
457 return (error);
458
459 bad:
460 if (m)
461 m_freem(m);
462 return (error);
463 }
464
465 /*
466 * Process a received Ethernet packet;
467 * the packet is in the mbuf chain m without
468 * the ether header, which is provided separately.
469 */
470 void
471 ether_input(ifp, eh, m)
472 struct ifnet *ifp;
473 register struct ether_header *eh;
474 struct mbuf *m;
475 {
476 register struct ifqueue *inq;
477 u_short ether_type, *checksum;
478 int s;
479 #if defined (ISO) || defined (LLC) || defined(NETATALK)
480 register struct llc *l;
481 #endif
482
483 if ((ifp->if_flags & IFF_UP) == 0) {
484 m_freem(m);
485 return;
486 }
487 ifp->if_ibytes += m->m_pkthdr.len + sizeof (*eh);
488 if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
489 sizeof(etherbroadcastaddr)) == 0)
490 m->m_flags |= M_BCAST;
491 else if (eh->ether_dhost[0] & 1)
492 m->m_flags |= M_MCAST;
493 if (m->m_flags & (M_BCAST|M_MCAST))
494 ifp->if_imcasts++;
495
496 ether_type = ntohs(eh->ether_type);
497
498 switch (ether_type) {
499 #ifdef INET
500 case ETHERTYPE_IP:
501 schednetisr(NETISR_IP);
502 inq = &ipintrq;
503 break;
504
505 case ETHERTYPE_ARP:
506 schednetisr(NETISR_ARP);
507 inq = &arpintrq;
508 break;
509 #endif
510 #ifdef IPX
511 case ETHERTYPE_IPX:
512 schednetisr(NETISR_IPX);
513 inq = &ipxintrq;
514 break;
515 #endif
516 #ifdef NS
517 case 0x8137: /* Novell Ethernet_II Ethernet TYPE II */
518 schednetisr(NETISR_NS);
519 inq = &nsintrq;
520 break;
521
522 #endif /* NS */
523 #ifdef NETATALK
524 case ETHERTYPE_AT:
525 schednetisr(NETISR_ATALK);
526 inq = &atintrq1;
527 break;
528 case ETHERTYPE_AARP:
529 /* probably this should be done with a NETISR as well */
530 aarpinput((struct arpcom *)ifp, m); /* XXX */
531 return;
532 #endif NETATALK
533 default:
534 #ifdef NS
535 checksum = mtod(m, ushort *);
536 /* Novell 802.3 */
537 if ((ether_type <= ETHERMTU) &&
538 ((*checksum == 0xffff) || (*checksum == 0xE0E0))){
539 if(*checksum == 0xE0E0) {
540 m->m_pkthdr.len -= 3;
541 m->m_len -= 3;
542 m->m_data += 3;
543 }
544 schednetisr(NETISR_NS);
545 inq = &nsintrq;
546 break;
547 }
548 #endif /* NS */
549 #if defined (ISO) || defined (LLC) || defined(NETATALK)
550 if (ether_type > ETHERMTU)
551 goto dropanyway;
552 l = mtod(m, struct llc *);
553 switch (l->llc_dsap) {
554 #ifdef NETATALK
555 case LLC_SNAP_LSAP:
556 switch (l->llc_control) {
557 case LLC_UI:
558 if (l->llc_ssap != LLC_SNAP_LSAP)
559 goto dropanyway;
560
561 if (Bcmp(&(l->llc_snap_org_code)[0], at_org_code,
562 sizeof(at_org_code)) == 0 &&
563 ntohs(l->llc_snap_ether_type) == ETHERTYPE_AT) {
564 inq = &atintrq2;
565 m_adj( m, sizeof( struct llc ));
566 schednetisr(NETISR_ATALK);
567 break;
568 }
569
570 if (Bcmp(&(l->llc_snap_org_code)[0], aarp_org_code,
571 sizeof(aarp_org_code)) == 0 &&
572 ntohs(l->llc_snap_ether_type) == ETHERTYPE_AARP) {
573 m_adj( m, sizeof( struct llc ));
574 aarpinput((struct arpcom *)ifp, m); /* XXX */
575 return;
576 }
577
578 default:
579 goto dropanyway;
580 }
581 break;
582 #endif NETATALK
583 #ifdef ISO
584 case LLC_ISO_LSAP:
585 switch (l->llc_control) {
586 case LLC_UI:
587 /* LLC_UI_P forbidden in class 1 service */
588 if ((l->llc_dsap == LLC_ISO_LSAP) &&
589 (l->llc_ssap == LLC_ISO_LSAP)) {
590 /* LSAP for ISO */
591 if (m->m_pkthdr.len > ether_type)
592 m_adj(m, ether_type - m->m_pkthdr.len);
593 m->m_data += 3; /* XXX */
594 m->m_len -= 3; /* XXX */
595 m->m_pkthdr.len -= 3; /* XXX */
596 M_PREPEND(m, sizeof *eh, M_DONTWAIT);
597 if (m == 0)
598 return;
599 *mtod(m, struct ether_header *) = *eh;
600 IFDEBUG(D_ETHER)
601 printf("clnp packet");
602 ENDDEBUG
603 schednetisr(NETISR_ISO);
604 inq = &clnlintrq;
605 break;
606 }
607 goto dropanyway;
608
609 case LLC_XID:
610 case LLC_XID_P:
611 if(m->m_len < 6)
612 goto dropanyway;
613 l->llc_window = 0;
614 l->llc_fid = 9;
615 l->llc_class = 1;
616 l->llc_dsap = l->llc_ssap = 0;
617 /* Fall through to */
618 case LLC_TEST:
619 case LLC_TEST_P:
620 {
621 struct sockaddr sa;
622 register struct ether_header *eh2;
623 int i;
624 u_char c = l->llc_dsap;
625
626 l->llc_dsap = l->llc_ssap;
627 l->llc_ssap = c;
628 if (m->m_flags & (M_BCAST | M_MCAST))
629 bcopy((caddr_t)ac->ac_enaddr,
630 (caddr_t)eh->ether_dhost, 6);
631 sa.sa_family = AF_UNSPEC;
632 sa.sa_len = sizeof(sa);
633 eh2 = (struct ether_header *)sa.sa_data;
634 for (i = 0; i < 6; i++) {
635 eh2->ether_shost[i] = c = eh->ether_dhost[i];
636 eh2->ether_dhost[i] =
637 eh->ether_dhost[i] = eh->ether_shost[i];
638 eh->ether_shost[i] = c;
639 }
640 ifp->if_output(ifp, m, &sa, NULL);
641 return;
642 }
643 default:
644 m_freem(m);
645 return;
646 }
647 break;
648 #endif /* ISO */
649 #ifdef LLC
650 case LLC_X25_LSAP:
651 {
652 if (m->m_pkthdr.len > ether_type)
653 m_adj(m, ether_type - m->m_pkthdr.len);
654 M_PREPEND(m, sizeof(struct sdl_hdr) , M_DONTWAIT);
655 if (m == 0)
656 return;
657 if ( !sdl_sethdrif(ifp, eh->ether_shost, LLC_X25_LSAP,
658 eh->ether_dhost, LLC_X25_LSAP, 6,
659 mtod(m, struct sdl_hdr *)))
660 panic("ETHER cons addr failure");
661 mtod(m, struct sdl_hdr *)->sdlhdr_len = ether_type;
662 #ifdef LLC_DEBUG
663 printf("llc packet\n");
664 #endif /* LLC_DEBUG */
665 schednetisr(NETISR_CCITT);
666 inq = &llcintrq;
667 break;
668 }
669 #endif /* LLC */
670 dropanyway:
671 default:
672 m_freem(m);
673 return;
674 }
675 #else /* ISO || LLC || NETATALK */
676 m_freem(m);
677 return;
678 #endif /* ISO || LLC || NETATALK */
679 }
680
681 s = splimp();
682 if (IF_QFULL(inq)) {
683 IF_DROP(inq);
684 m_freem(m);
685 } else
686 IF_ENQUEUE(inq, m);
687 splx(s);
688 }
689
690 /*
691 * Perform common duties while attaching to interface list
692 */
693 void
694 ether_ifattach(ifp)
695 register struct ifnet *ifp;
696 {
697 register struct ifaddr *ifa;
698 register struct sockaddr_dl *sdl;
699
700 ifp->if_type = IFT_ETHER;
701 ifp->if_addrlen = 6;
702 ifp->if_hdrlen = 14;
703 ifp->if_mtu = ETHERMTU;
704 if (ifp->if_baudrate == 0)
705 ifp->if_baudrate = 10000000;
706 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
707 if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) &&
708 sdl->sdl_family == AF_LINK) {
709 sdl->sdl_type = IFT_ETHER;
710 sdl->sdl_alen = ifp->if_addrlen;
711 bcopy((caddr_t)((struct arpcom *)ifp)->ac_enaddr,
712 LLADDR(sdl), ifp->if_addrlen);
713 break;
714 }
715 }
716
717 static u_char ether_ipmulticast_min[6] =
718 { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 };
719 static u_char ether_ipmulticast_max[6] =
720 { 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xff };
721 /*
722 * Add an Ethernet multicast address or range of addresses to the list for a
723 * given interface.
724 */
725 int
726 ether_addmulti(ifr, ac)
727 struct ifreq *ifr;
728 register struct arpcom *ac;
729 {
730 register struct ether_multi *enm;
731 struct sockaddr_in *sin;
732 u_char addrlo[6];
733 u_char addrhi[6];
734 int set_allmulti = 0;
735 int s = splimp();
736
737 switch (ifr->ifr_addr.sa_family) {
738
739 case AF_UNSPEC:
740 bcopy(ifr->ifr_addr.sa_data, addrlo, 6);
741 bcopy(addrlo, addrhi, 6);
742 break;
743
744 #ifdef INET
745 case AF_INET:
746 sin = (struct sockaddr_in *)&(ifr->ifr_addr);
747 if (sin->sin_addr.s_addr == INADDR_ANY) {
748 /*
749 * An IP address of INADDR_ANY means listen to all
750 * of the Ethernet multicast addresses used for IP.
751 * (This is for the sake of IP multicast routers.)
752 */
753 bcopy(ether_ipmulticast_min, addrlo, 6);
754 bcopy(ether_ipmulticast_max, addrhi, 6);
755 set_allmulti = 1;
756 }
757 else {
758 ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo);
759 bcopy(addrlo, addrhi, 6);
760 }
761 break;
762 #endif
763
764 default:
765 splx(s);
766 return (EAFNOSUPPORT);
767 }
768
769 /*
770 * Verify that we have valid Ethernet multicast addresses.
771 */
772 if ((addrlo[0] & 0x01) != 1 || (addrhi[0] & 0x01) != 1) {
773 splx(s);
774 return (EINVAL);
775 }
776 /*
777 * See if the address range is already in the list.
778 */
779 ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm);
780 if (enm != NULL) {
781 /*
782 * Found it; just increment the reference count.
783 */
784 ++enm->enm_refcount;
785 splx(s);
786 return (0);
787 }
788 /*
789 * New address or range; malloc a new multicast record
790 * and link it into the interface's multicast list.
791 */
792 enm = (struct ether_multi *)malloc(sizeof(*enm), M_IFMADDR, M_NOWAIT);
793 if (enm == NULL) {
794 splx(s);
795 return (ENOBUFS);
796 }
797 bcopy(addrlo, enm->enm_addrlo, 6);
798 bcopy(addrhi, enm->enm_addrhi, 6);
799 enm->enm_ac = ac;
800 enm->enm_refcount = 1;
801 enm->enm_next = ac->ac_multiaddrs;
802 ac->ac_multiaddrs = enm;
803 ac->ac_multicnt++;
804 splx(s);
805 if (set_allmulti)
806 ac->ac_if.if_flags |= IFF_ALLMULTI;
807
808 /*
809 * Return ENETRESET to inform the driver that the list has changed
810 * and its reception filter should be adjusted accordingly.
811 */
812 return (ENETRESET);
813 }
814
815 /*
816 * Delete a multicast address record.
817 */
818 int
819 ether_delmulti(ifr, ac)
820 struct ifreq *ifr;
821 register struct arpcom *ac;
822 {
823 register struct ether_multi *enm;
824 register struct ether_multi **p;
825 struct sockaddr_in *sin;
826 u_char addrlo[6];
827 u_char addrhi[6];
828 int unset_allmulti = 0;
829 int s = splimp();
830
831 switch (ifr->ifr_addr.sa_family) {
832
833 case AF_UNSPEC:
834 bcopy(ifr->ifr_addr.sa_data, addrlo, 6);
835 bcopy(addrlo, addrhi, 6);
836 break;
837
838 #ifdef INET
839 case AF_INET:
840 sin = (struct sockaddr_in *)&(ifr->ifr_addr);
841 if (sin->sin_addr.s_addr == INADDR_ANY) {
842 /*
843 * An IP address of INADDR_ANY means stop listening
844 * to the range of Ethernet multicast addresses used
845 * for IP.
846 */
847 bcopy(ether_ipmulticast_min, addrlo, 6);
848 bcopy(ether_ipmulticast_max, addrhi, 6);
849 unset_allmulti = 1;
850 }
851 else {
852 ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo);
853 bcopy(addrlo, addrhi, 6);
854 }
855 break;
856 #endif
857
858 default:
859 splx(s);
860 return (EAFNOSUPPORT);
861 }
862
863 /*
864 * Look up the address in our list.
865 */
866 ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm);
867 if (enm == NULL) {
868 splx(s);
869 return (ENXIO);
870 }
871 if (--enm->enm_refcount != 0) {
872 /*
873 * Still some claims to this record.
874 */
875 splx(s);
876 return (0);
877 }
878 /*
879 * No remaining claims to this record; unlink and free it.
880 */
881 for (p = &enm->enm_ac->ac_multiaddrs;
882 *p != enm;
883 p = &(*p)->enm_next)
884 continue;
885 *p = (*p)->enm_next;
886 free(enm, M_IFMADDR);
887 ac->ac_multicnt--;
888 splx(s);
889 if (unset_allmulti)
890 ac->ac_if.if_flags &= ~IFF_ALLMULTI;
891
892 /*
893 * Return ENETRESET to inform the driver that the list has changed
894 * and its reception filter should be adjusted accordingly.
895 */
896 return (ENETRESET);
897 }
898
899 SYSCTL_NODE(_net_link, IFT_ETHER, ether, CTLFLAG_RW, 0, "Ethernet");
900
901 int
902 ether_ioctl(struct ifnet *ifp, int command, caddr_t data)
903 {
904 struct ifaddr *ifa = (struct ifaddr *) data;
905 struct ifreq *ifr = (struct ifreq *) data;
906 int error = 0;
907
908 switch (command) {
909 case SIOCSIFADDR:
910 ifp->if_flags |= IFF_UP;
911
912 switch (ifa->ifa_addr->sa_family) {
913 #ifdef INET
914 case AF_INET:
915 ifp->if_init(ifp->if_softc); /* before arpwhohas */
916 arp_ifinit((struct arpcom *)ifp, ifa);
917 break;
918 #endif
919 #ifdef IPX
920 /*
921 * XXX - This code is probably wrong
922 */
923 case AF_IPX:
924 {
925 register struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr);
926 struct arpcom *ac = (struct arpcom *) (ifp->if_softc);
927
928 if (ipx_nullhost(*ina))
929 ina->x_host =
930 *(union ipx_host *)
931 ac->ac_enaddr;
932 else {
933 bcopy((caddr_t) ina->x_host.c_host,
934 (caddr_t) ac->ac_enaddr,
935 sizeof(ac->ac_enaddr));
936 }
937
938 /*
939 * Set new address
940 */
941 ifp->if_init(ifp->if_softc);
942 break;
943 }
944 #endif
945 #ifdef NS
946 /*
947 * XXX - This code is probably wrong
948 */
949 case AF_NS:
950 {
951 register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
952 struct arpcom *ac = (struct arpcom *) (ifp->if_softc);
953
954 if (ns_nullhost(*ina))
955 ina->x_host =
956 *(union ns_host *) (ac->ac_enaddr);
957 else {
958 bcopy((caddr_t) ina->x_host.c_host,
959 (caddr_t) ac->ac_enaddr,
960 sizeof(ac->ac_enaddr));
961 }
962
963 /*
964 * Set new address
965 */
966 ifp->if_init(ifp->if_softc);
967 break;
968 }
969 #endif
970 default:
971 ifp->if_init(ifp->if_softc);
972 break;
973 }
974 break;
975
976 case SIOCGIFADDR:
977 {
978 struct sockaddr *sa;
979
980 sa = (struct sockaddr *) & ifr->ifr_data;
981 bcopy(((struct arpcom *)ifp->if_softc)->ac_enaddr,
982 (caddr_t) sa->sa_data, ETHER_ADDR_LEN);
983 }
984 break;
985
986 case SIOCSIFMTU:
987 /*
988 * Set the interface MTU.
989 */
990 if (ifr->ifr_mtu > ETHERMTU) {
991 error = EINVAL;
992 } else {
993 ifp->if_mtu = ifr->ifr_mtu;
994 }
995 break;
996 }
997 return (error);
998 }
Cache object: 1f49a8c2f423dc3904c959cb7feb760a
|