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$
35 */
36
37 #include "opt_atalk.h"
38 #include "opt_inet.h"
39 #include "opt_ipx.h"
40 #include "opt_bdg.h"
41 #include "opt_netgraph.h"
42
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/kernel.h>
46 #include <sys/malloc.h>
47 #include <sys/mbuf.h>
48 #include <sys/socket.h>
49 #include <sys/sockio.h>
50 #include <sys/sysctl.h>
51
52 #include <net/if.h>
53 #include <net/netisr.h>
54 #include <net/route.h>
55 #include <net/if_llc.h>
56 #include <net/if_dl.h>
57 #include <net/if_types.h>
58
59 #ifdef INET
60 #include <netinet/in.h>
61 #include <netinet/in_var.h>
62 #include <netinet/if_ether.h>
63 #endif
64
65 #ifdef IPX
66 #include <netipx/ipx.h>
67 #include <netipx/ipx_if.h>
68 #endif
69
70 #ifdef NS
71 #include <netns/ns.h>
72 #include <netns/ns_if.h>
73 ushort ns_nettype;
74 int ether_outputdebug = 0;
75 int ether_inputdebug = 0;
76 #endif
77
78 #ifdef ISO
79 #include <netiso/argo_debug.h>
80 #include <netiso/iso.h>
81 #include <netiso/iso_var.h>
82 #include <netiso/iso_snpac.h>
83 #endif
84
85 /*#ifdef LLC
86 #include <netccitt/dll.h>
87 #include <netccitt/llc_var.h>
88 #endif*/
89
90 #if defined(LLC) && defined(CCITT)
91 extern struct ifqueue pkintrq;
92 #endif
93
94 #ifdef NETATALK
95 #include <netatalk/at.h>
96 #include <netatalk/at_var.h>
97 #include <netatalk/at_extern.h>
98
99 #define llc_snap_org_code llc_un.type_snap.org_code
100 #define llc_snap_ether_type llc_un.type_snap.ether_type
101
102 extern u_char at_org_code[3];
103 extern u_char aarp_org_code[3];
104 #endif /* NETATALK */
105
106 #ifdef BRIDGE
107 #include <net/bridge.h>
108 #endif
109
110 #include "vlan.h"
111 #if NVLAN > 0
112 #include <net/if_vlan_var.h>
113 #endif /* NVLAN > 0 */
114
115 static int ether_resolvemulti __P((struct ifnet *, struct sockaddr **,
116 struct sockaddr *));
117 u_char etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
118 #define senderr(e) { error = (e); goto bad;}
119 #define IFP2AC(IFP) ((struct arpcom *)IFP)
120
121 #ifdef NETGRAPH
122 #include <netgraph/ng_ether.h>
123 #include <netgraph/ng_message.h>
124 #include <netgraph/netgraph.h>
125
126 static void ngether_init(void* ignored);
127 static void ngether_send(struct arpcom *ac,
128 struct ether_header *eh, struct mbuf *m);
129 static ng_constructor_t ngether_constructor;
130 static ng_rcvmsg_t ngether_rcvmsg;
131 static ng_shutdown_t ngether_rmnode;
132 static ng_newhook_t ngether_newhook;
133 static ng_connect_t ngether_connect;
134 static ng_rcvdata_t ngether_rcvdata;
135 static ng_disconnect_t ngether_disconnect;
136
137 static struct ng_type typestruct = {
138 NG_VERSION,
139 NG_ETHER_NODE_TYPE,
140 NULL,
141 ngether_constructor,
142 ngether_rcvmsg,
143 ngether_rmnode,
144 ngether_newhook,
145 NULL,
146 ngether_connect,
147 ngether_rcvdata,
148 ngether_rcvdata,
149 ngether_disconnect,
150 NULL
151 };
152
153 #define AC2NG(AC) ((node_p)((AC)->ac_ng))
154 #define NGEF_DIVERT NGF_TYPE1 /* all packets sent to netgraph */
155 #endif /* NETGRAPH */
156
157 /*
158 * Ethernet output routine.
159 * Encapsulate a packet of type family for the local net.
160 * Use trailer local net encapsulation if enough data in first
161 * packet leaves a multiple of 512 bytes of data in remainder.
162 * Assumes that ifp is actually pointer to arpcom structure.
163 */
164 int
165 ether_output(ifp, m0, dst, rt0)
166 register struct ifnet *ifp;
167 struct mbuf *m0;
168 struct sockaddr *dst;
169 struct rtentry *rt0;
170 {
171 short type;
172 int s, error = 0;
173 u_char edst[6];
174 register struct mbuf *m = m0;
175 register struct rtentry *rt;
176 register struct ether_header *eh;
177 int off, len = m->m_pkthdr.len, loop_copy = 0;
178 int hlen; /* link layer header lenght */
179 struct arpcom *ac = (struct arpcom *)ifp;
180
181 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
182 senderr(ENETDOWN);
183 rt = rt0;
184 if (rt) {
185 if ((rt->rt_flags & RTF_UP) == 0) {
186 rt0 = rt = rtalloc1(dst, 1, 0UL);
187 if (rt0)
188 rt->rt_refcnt--;
189 else
190 senderr(EHOSTUNREACH);
191 }
192 if (rt->rt_flags & RTF_GATEWAY) {
193 if (rt->rt_gwroute == 0)
194 goto lookup;
195 if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
196 rtfree(rt); rt = rt0;
197 lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1,
198 0UL);
199 if ((rt = rt->rt_gwroute) == 0)
200 senderr(EHOSTUNREACH);
201 }
202 }
203 if (rt->rt_flags & RTF_REJECT)
204 if (rt->rt_rmx.rmx_expire == 0 ||
205 time_second < rt->rt_rmx.rmx_expire)
206 senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
207 }
208 hlen = ETHER_HDR_LEN;
209 switch (dst->sa_family) {
210 #ifdef INET
211 case AF_INET:
212 if (!arpresolve(ac, rt, m, dst, edst, rt0))
213 return (0); /* if not yet resolved */
214 off = m->m_pkthdr.len - m->m_len;
215 type = htons(ETHERTYPE_IP);
216 break;
217 #endif
218 #ifdef IPX
219 case AF_IPX:
220 type = htons(ETHERTYPE_IPX);
221 bcopy((caddr_t)&(((struct sockaddr_ipx *)dst)->sipx_addr.x_host),
222 (caddr_t)edst, sizeof (edst));
223 break;
224 #endif
225 #ifdef NETATALK
226 case AF_APPLETALK:
227 {
228 struct at_ifaddr *aa;
229
230 if ((aa = at_ifawithnet((struct sockaddr_at *)dst)) == NULL) {
231 goto bad;
232 }
233 if (!aarpresolve(ac, m, (struct sockaddr_at *)dst, edst))
234 return (0);
235 /*
236 * In the phase 2 case, need to prepend an mbuf for the llc header.
237 * Since we must preserve the value of m, which is passed to us by
238 * value, we m_copy() the first mbuf, and use it for our llc header.
239 */
240 if ( aa->aa_flags & AFA_PHASE2 ) {
241 struct llc llc;
242
243 M_PREPEND(m, sizeof(struct llc), M_WAIT);
244 len += sizeof(struct llc);
245 llc.llc_dsap = llc.llc_ssap = LLC_SNAP_LSAP;
246 llc.llc_control = LLC_UI;
247 bcopy(at_org_code, llc.llc_snap_org_code, sizeof(at_org_code));
248 llc.llc_snap_ether_type = htons( ETHERTYPE_AT );
249 bcopy(&llc, mtod(m, caddr_t), sizeof(struct llc));
250 type = htons(m->m_pkthdr.len);
251 hlen = sizeof(struct llc) + ETHER_HDR_LEN;
252 } else {
253 type = htons(ETHERTYPE_AT);
254 }
255 break;
256 }
257 #endif NETATALK
258 #ifdef NS
259 case AF_NS:
260 switch(ns_nettype){
261 default:
262 case 0x8137: /* Novell Ethernet_II Ethernet TYPE II */
263 type = 0x8137;
264 break;
265 case 0x0: /* Novell 802.3 */
266 type = htons( m->m_pkthdr.len);
267 break;
268 case 0xe0e0: /* Novell 802.2 and Token-Ring */
269 M_PREPEND(m, 3, M_WAIT);
270 type = htons( m->m_pkthdr.len);
271 cp = mtod(m, u_char *);
272 *cp++ = 0xE0;
273 *cp++ = 0xE0;
274 *cp++ = 0x03;
275 break;
276 }
277 bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
278 (caddr_t)edst, sizeof (edst));
279 if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst))){
280 m->m_pkthdr.rcvif = ifp;
281 schednetisr(NETISR_NS);
282 inq = &nsintrq;
283 s = splimp();
284 if (IF_QFULL(inq)) {
285 IF_DROP(inq);
286 m_freem(m);
287 } else
288 IF_ENQUEUE(inq, m);
289 splx(s);
290 return (error);
291 }
292 if (!bcmp((caddr_t)edst, (caddr_t)&ns_broadhost, sizeof(edst))){
293 m2 = m_copy(m, 0, (int)M_COPYALL);
294 m2->m_pkthdr.rcvif = ifp;
295 schednetisr(NETISR_NS);
296 inq = &nsintrq;
297 s = splimp();
298 if (IF_QFULL(inq)) {
299 IF_DROP(inq);
300 m_freem(m2);
301 } else
302 IF_ENQUEUE(inq, m2);
303 splx(s);
304 }
305 break;
306 #endif /* NS */
307 #ifdef ISO
308 case AF_ISO: {
309 int snpalen;
310 struct llc *l;
311 register struct sockaddr_dl *sdl;
312
313 if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway) &&
314 sdl->sdl_family == AF_LINK && sdl->sdl_alen > 0) {
315 bcopy(LLADDR(sdl), (caddr_t)edst, sizeof(edst));
316 } else if (error =
317 iso_snparesolve(ifp, (struct sockaddr_iso *)dst,
318 (char *)edst, &snpalen))
319 goto bad; /* Not Resolved */
320 /* If broadcasting on a simplex interface, loopback a copy */
321 if (*edst & 1)
322 m->m_flags |= (M_BCAST|M_MCAST);
323 M_PREPEND(m, 3, M_DONTWAIT);
324 if (m == NULL)
325 return (0);
326 type = htons(m->m_pkthdr.len);
327 l = mtod(m, struct llc *);
328 l->llc_dsap = l->llc_ssap = LLC_ISO_LSAP;
329 l->llc_control = LLC_UI;
330 len += 3;
331 IFDEBUG(D_ETHER)
332 int i;
333 printf("unoutput: sending pkt to: ");
334 for (i=0; i<6; i++)
335 printf("%x ", edst[i] & 0xff);
336 printf("\n");
337 ENDDEBUG
338 } break;
339 #endif /* ISO */
340 #ifdef LLC
341 /* case AF_NSAP: */
342 case AF_CCITT: {
343 register struct sockaddr_dl *sdl =
344 (struct sockaddr_dl *) rt -> rt_gateway;
345
346 if (sdl && sdl->sdl_family == AF_LINK
347 && sdl->sdl_alen > 0) {
348 bcopy(LLADDR(sdl), (char *)edst, sizeof(edst));
349 } else goto bad; /* Not a link interface ? Funny ... */
350 if (*edst & 1)
351 loop_copy = 1;
352 type = htons(m->m_pkthdr.len);
353 #ifdef LLC_DEBUG
354 {
355 int i;
356 register struct llc *l = mtod(m, struct llc *);
357
358 printf("ether_output: sending LLC2 pkt to: ");
359 for (i=0; i<6; i++)
360 printf("%x ", edst[i] & 0xff);
361 printf(" len 0x%x dsap 0x%x ssap 0x%x control 0x%x\n",
362 type & 0xff, l->llc_dsap & 0xff, l->llc_ssap &0xff,
363 l->llc_control & 0xff);
364
365 }
366 #endif /* LLC_DEBUG */
367 } break;
368 #endif /* LLC */
369
370 case AF_UNSPEC:
371 loop_copy = -1; /* if this is for us, don't do it */
372 eh = (struct ether_header *)dst->sa_data;
373 (void)memcpy(edst, eh->ether_dhost, sizeof (edst));
374 type = eh->ether_type;
375 break;
376
377 default:
378 printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit,
379 dst->sa_family);
380 senderr(EAFNOSUPPORT);
381 }
382
383 /*
384 * Add local net header. If no space in first mbuf,
385 * allocate another.
386 */
387 M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT);
388 if (m == 0)
389 senderr(ENOBUFS);
390 eh = mtod(m, struct ether_header *);
391 (void)memcpy(&eh->ether_type, &type,
392 sizeof(eh->ether_type));
393 (void)memcpy(eh->ether_dhost, edst, sizeof (edst));
394 (void)memcpy(eh->ether_shost, ac->ac_enaddr,
395 sizeof(eh->ether_shost));
396
397 /*
398 * If a simplex interface, and the packet is being sent to our
399 * Ethernet address or a broadcast address, loopback a copy.
400 * XXX To make a simplex device behave exactly like a duplex
401 * device, we should copy in the case of sending to our own
402 * ethernet address (thus letting the original actually appear
403 * on the wire). However, we don't do that here for security
404 * reasons and compatibility with the original behavior.
405 */
406 if ((ifp->if_flags & IFF_SIMPLEX) &&
407 (loop_copy != -1)) {
408 if ((m->m_flags & M_BCAST) || (loop_copy > 0)) {
409 struct mbuf *n = m_copy(m, 0, (int)M_COPYALL);
410
411 (void) if_simloop(ifp, n, dst, hlen);
412 } else if (bcmp(eh->ether_dhost,
413 eh->ether_shost, ETHER_ADDR_LEN) == 0) {
414 (void) if_simloop(ifp, m, dst, hlen);
415 return (0); /* XXX */
416 }
417 }
418 #ifdef BRIDGE
419 if (do_bridge) {
420 struct mbuf *m0 = m ;
421
422 if (m->m_pkthdr.rcvif)
423 m->m_pkthdr.rcvif = NULL ;
424 ifp = bridge_dst_lookup(m);
425 bdg_forward(&m0, ifp);
426 if (m0)
427 m_freem(m0);
428 return (0);
429 }
430 #endif
431 s = splimp();
432 /*
433 * Queue message on interface, and start output if interface
434 * not yet active.
435 */
436 if (IF_QFULL(&ifp->if_snd)) {
437 IF_DROP(&ifp->if_snd);
438 splx(s);
439 senderr(ENOBUFS);
440 }
441 IF_ENQUEUE(&ifp->if_snd, m);
442 if ((ifp->if_flags & IFF_OACTIVE) == 0)
443 (*ifp->if_start)(ifp);
444 splx(s);
445 ifp->if_obytes += len + sizeof (struct ether_header);
446 if (m->m_flags & M_MCAST)
447 ifp->if_omcasts++;
448 return (error);
449
450 bad:
451 if (m)
452 m_freem(m);
453 return (error);
454 }
455
456 /*
457 * Process a received Ethernet packet;
458 * the packet is in the mbuf chain m without
459 * the ether header, which is provided separately.
460 */
461 void
462 ether_input(ifp, eh, m)
463 struct ifnet *ifp;
464 register struct ether_header *eh;
465 struct mbuf *m;
466 {
467 register struct ifqueue *inq;
468 u_short ether_type;
469 int s;
470 #if defined (ISO) || defined (LLC) || defined(NETATALK)
471 register struct llc *l;
472 #endif
473
474 if ((ifp->if_flags & IFF_UP) == 0) {
475 m_freem(m);
476 return;
477 }
478 ifp->if_ibytes += m->m_pkthdr.len + sizeof (*eh);
479 if (eh->ether_dhost[0] & 1) {
480 if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
481 sizeof(etherbroadcastaddr)) == 0)
482 m->m_flags |= M_BCAST;
483 else
484 m->m_flags |= M_MCAST;
485 }
486 if (m->m_flags & (M_BCAST|M_MCAST))
487 ifp->if_imcasts++;
488
489 ether_type = ntohs(eh->ether_type);
490
491 #ifdef NETGRAPH
492 {
493 struct arpcom *ac = IFP2AC(ifp);
494 if (AC2NG(ac) && (AC2NG(ac)->flags & NGEF_DIVERT)) {
495 ngether_send(ac, eh, m);
496 return;
497 }
498 }
499 #endif /* NETGRAPH */
500
501 #if NVLAN > 0
502 if (ether_type == vlan_proto) {
503 if (vlan_input(eh, m) < 0)
504 ifp->if_data.ifi_noproto++;
505 return;
506 }
507 #endif /* NVLAN > 0 */
508
509 switch (ether_type) {
510 #ifdef INET
511 case ETHERTYPE_IP:
512 if (ipflow_fastforward(m))
513 return;
514 schednetisr(NETISR_IP);
515 inq = &ipintrq;
516 break;
517
518 case ETHERTYPE_ARP:
519 schednetisr(NETISR_ARP);
520 inq = &arpintrq;
521 break;
522 #endif
523 #ifdef IPX
524 case ETHERTYPE_IPX:
525 schednetisr(NETISR_IPX);
526 inq = &ipxintrq;
527 break;
528 #endif
529 #ifdef NS
530 case 0x8137: /* Novell Ethernet_II Ethernet TYPE II */
531 schednetisr(NETISR_NS);
532 inq = &nsintrq;
533 break;
534
535 #endif /* NS */
536 #ifdef NETATALK
537 case ETHERTYPE_AT:
538 schednetisr(NETISR_ATALK);
539 inq = &atintrq1;
540 break;
541 case ETHERTYPE_AARP:
542 /* probably this should be done with a NETISR as well */
543 aarpinput((struct arpcom *)ifp, m); /* XXX */
544 return;
545 #endif NETATALK
546 default:
547 #ifdef NS
548 checksum = mtod(m, ushort *);
549 /* Novell 802.3 */
550 if ((ether_type <= ETHERMTU) &&
551 ((*checksum == 0xffff) || (*checksum == 0xE0E0))){
552 if(*checksum == 0xE0E0) {
553 m->m_pkthdr.len -= 3;
554 m->m_len -= 3;
555 m->m_data += 3;
556 }
557 schednetisr(NETISR_NS);
558 inq = &nsintrq;
559 break;
560 }
561 #endif /* NS */
562 #if defined (ISO) || defined (LLC) || defined(NETATALK)
563 if (ether_type > ETHERMTU)
564 goto dropanyway;
565 l = mtod(m, struct llc *);
566 switch (l->llc_dsap) {
567 #ifdef NETATALK
568 case LLC_SNAP_LSAP:
569 switch (l->llc_control) {
570 case LLC_UI:
571 if (l->llc_ssap != LLC_SNAP_LSAP)
572 goto dropanyway;
573
574 if (Bcmp(&(l->llc_snap_org_code)[0], at_org_code,
575 sizeof(at_org_code)) == 0 &&
576 ntohs(l->llc_snap_ether_type) == ETHERTYPE_AT) {
577 inq = &atintrq2;
578 m_adj( m, sizeof( struct llc ));
579 schednetisr(NETISR_ATALK);
580 break;
581 }
582
583 if (Bcmp(&(l->llc_snap_org_code)[0], aarp_org_code,
584 sizeof(aarp_org_code)) == 0 &&
585 ntohs(l->llc_snap_ether_type) == ETHERTYPE_AARP) {
586 m_adj( m, sizeof( struct llc ));
587 aarpinput((struct arpcom *)ifp, m); /* XXX */
588 return;
589 }
590
591 default:
592 goto dropanyway;
593 }
594 break;
595 #endif NETATALK
596 #ifdef ISO
597 case LLC_ISO_LSAP:
598 switch (l->llc_control) {
599 case LLC_UI:
600 /* LLC_UI_P forbidden in class 1 service */
601 if ((l->llc_dsap == LLC_ISO_LSAP) &&
602 (l->llc_ssap == LLC_ISO_LSAP)) {
603 /* LSAP for ISO */
604 if (m->m_pkthdr.len > ether_type)
605 m_adj(m, ether_type - m->m_pkthdr.len);
606 m->m_data += 3; /* XXX */
607 m->m_len -= 3; /* XXX */
608 m->m_pkthdr.len -= 3; /* XXX */
609 M_PREPEND(m, sizeof *eh, M_DONTWAIT);
610 if (m == 0)
611 return;
612 *mtod(m, struct ether_header *) = *eh;
613 IFDEBUG(D_ETHER)
614 printf("clnp packet");
615 ENDDEBUG
616 schednetisr(NETISR_ISO);
617 inq = &clnlintrq;
618 break;
619 }
620 goto dropanyway;
621
622 case LLC_XID:
623 case LLC_XID_P:
624 if(m->m_len < 6)
625 goto dropanyway;
626 l->llc_window = 0;
627 l->llc_fid = 9;
628 l->llc_class = 1;
629 l->llc_dsap = l->llc_ssap = 0;
630 /* Fall through to */
631 case LLC_TEST:
632 case LLC_TEST_P:
633 {
634 struct sockaddr sa;
635 register struct ether_header *eh2;
636 int i;
637 u_char c = l->llc_dsap;
638
639 l->llc_dsap = l->llc_ssap;
640 l->llc_ssap = c;
641 if (m->m_flags & (M_BCAST | M_MCAST))
642 bcopy((caddr_t)ac->ac_enaddr,
643 (caddr_t)eh->ether_dhost, 6);
644 sa.sa_family = AF_UNSPEC;
645 sa.sa_len = sizeof(sa);
646 eh2 = (struct ether_header *)sa.sa_data;
647 for (i = 0; i < 6; i++) {
648 eh2->ether_shost[i] = c = eh->ether_dhost[i];
649 eh2->ether_dhost[i] =
650 eh->ether_dhost[i] = eh->ether_shost[i];
651 eh->ether_shost[i] = c;
652 }
653 ifp->if_output(ifp, m, &sa, NULL);
654 return;
655 }
656 default:
657 m_freem(m);
658 return;
659 }
660 break;
661 #endif /* ISO */
662 #ifdef LLC
663 case LLC_X25_LSAP:
664 {
665 if (m->m_pkthdr.len > ether_type)
666 m_adj(m, ether_type - m->m_pkthdr.len);
667 M_PREPEND(m, sizeof(struct sdl_hdr) , M_DONTWAIT);
668 if (m == 0)
669 return;
670 if ( !sdl_sethdrif(ifp, eh->ether_shost, LLC_X25_LSAP,
671 eh->ether_dhost, LLC_X25_LSAP, 6,
672 mtod(m, struct sdl_hdr *)))
673 panic("ETHER cons addr failure");
674 mtod(m, struct sdl_hdr *)->sdlhdr_len = ether_type;
675 #ifdef LLC_DEBUG
676 printf("llc packet\n");
677 #endif /* LLC_DEBUG */
678 schednetisr(NETISR_CCITT);
679 inq = &llcintrq;
680 break;
681 }
682 #endif /* LLC */
683 dropanyway:
684 default:
685 #ifdef NETGRAPH
686 ngether_send(IFP2AC(ifp), eh, m);
687 #else /* NETGRAPH */
688 m_freem(m);
689 #endif /* NETGRAPH */
690 return;
691 }
692 #else /* ISO || LLC || NETATALK */
693 #ifdef NETGRAPH
694 ngether_send(IFP2AC(ifp), eh, m);
695 #else /* NETGRAPH */
696 m_freem(m);
697 #endif /* NETGRAPH */
698 return;
699 #endif /* ISO || LLC || NETATALK */
700 }
701
702 s = splimp();
703 if (IF_QFULL(inq)) {
704 IF_DROP(inq);
705 m_freem(m);
706 } else
707 IF_ENQUEUE(inq, m);
708 splx(s);
709 }
710
711 /*
712 * Perform common duties while attaching to interface list
713 */
714 void
715 ether_ifattach(ifp)
716 register struct ifnet *ifp;
717 {
718 register struct ifaddr *ifa;
719 register struct sockaddr_dl *sdl;
720
721 ifp->if_type = IFT_ETHER;
722 ifp->if_addrlen = 6;
723 ifp->if_hdrlen = 14;
724 ifp->if_mtu = ETHERMTU;
725 ifp->if_resolvemulti = ether_resolvemulti;
726 if (ifp->if_baudrate == 0)
727 ifp->if_baudrate = 10000000;
728 ifa = ifnet_addrs[ifp->if_index - 1];
729 if (ifa == 0) {
730 printf("ether_ifattach: no lladdr!\n");
731 return;
732 }
733 sdl = (struct sockaddr_dl *)ifa->ifa_addr;
734 sdl->sdl_type = IFT_ETHER;
735 sdl->sdl_alen = ifp->if_addrlen;
736 bcopy(((struct arpcom *)ifp)->ac_enaddr, LLADDR(sdl), ifp->if_addrlen);
737 #ifdef NETGRAPH
738 ngether_init(ifp);
739 #endif /* NETGRAPH */
740 }
741
742 SYSCTL_NODE(_net_link, IFT_ETHER, ether, CTLFLAG_RW, 0, "Ethernet");
743
744 int
745 ether_ioctl(ifp, command, data)
746 struct ifnet *ifp;
747 int command;
748 caddr_t data;
749 {
750 struct ifaddr *ifa = (struct ifaddr *) data;
751 struct ifreq *ifr = (struct ifreq *) data;
752 int error = 0;
753
754 switch (command) {
755 case SIOCSIFADDR:
756 ifp->if_flags |= IFF_UP;
757
758 switch (ifa->ifa_addr->sa_family) {
759 #ifdef INET
760 case AF_INET:
761 ifp->if_init(ifp->if_softc); /* before arpwhohas */
762 arp_ifinit((struct arpcom *)ifp, ifa);
763 break;
764 #endif
765 #ifdef IPX
766 /*
767 * XXX - This code is probably wrong
768 */
769 case AF_IPX:
770 {
771 register struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr);
772 struct arpcom *ac = (struct arpcom *) (ifp->if_softc);
773
774 if (ipx_nullhost(*ina))
775 ina->x_host =
776 *(union ipx_host *)
777 ac->ac_enaddr;
778 else {
779 bcopy((caddr_t) ina->x_host.c_host,
780 (caddr_t) ac->ac_enaddr,
781 sizeof(ac->ac_enaddr));
782 }
783
784 /*
785 * Set new address
786 */
787 ifp->if_init(ifp->if_softc);
788 break;
789 }
790 #endif
791 #ifdef NS
792 /*
793 * XXX - This code is probably wrong
794 */
795 case AF_NS:
796 {
797 register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
798 struct arpcom *ac = (struct arpcom *) (ifp->if_softc);
799
800 if (ns_nullhost(*ina))
801 ina->x_host =
802 *(union ns_host *) (ac->ac_enaddr);
803 else {
804 bcopy((caddr_t) ina->x_host.c_host,
805 (caddr_t) ac->ac_enaddr,
806 sizeof(ac->ac_enaddr));
807 }
808
809 /*
810 * Set new address
811 */
812 ifp->if_init(ifp->if_softc);
813 break;
814 }
815 #endif
816 default:
817 ifp->if_init(ifp->if_softc);
818 break;
819 }
820 break;
821
822 case SIOCGIFADDR:
823 {
824 struct sockaddr *sa;
825
826 sa = (struct sockaddr *) & ifr->ifr_data;
827 bcopy(((struct arpcom *)ifp->if_softc)->ac_enaddr,
828 (caddr_t) sa->sa_data, ETHER_ADDR_LEN);
829 }
830 break;
831
832 case SIOCSIFMTU:
833 /*
834 * Set the interface MTU.
835 */
836 if (ifr->ifr_mtu > ETHERMTU) {
837 error = EINVAL;
838 } else {
839 ifp->if_mtu = ifr->ifr_mtu;
840 }
841 break;
842 }
843 return (error);
844 }
845
846 int
847 ether_resolvemulti(ifp, llsa, sa)
848 struct ifnet *ifp;
849 struct sockaddr **llsa;
850 struct sockaddr *sa;
851 {
852 struct sockaddr_dl *sdl;
853 struct sockaddr_in *sin;
854 u_char *e_addr;
855
856 switch(sa->sa_family) {
857 case AF_LINK:
858 /*
859 * No mapping needed. Just check that it's a valid MC address.
860 */
861 sdl = (struct sockaddr_dl *)sa;
862 e_addr = LLADDR(sdl);
863 if ((e_addr[0] & 1) != 1)
864 return EADDRNOTAVAIL;
865 *llsa = 0;
866 return 0;
867
868 #ifdef INET
869 case AF_INET:
870 sin = (struct sockaddr_in *)sa;
871 if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr)))
872 return EADDRNOTAVAIL;
873 MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR,
874 M_WAITOK);
875 sdl->sdl_len = sizeof *sdl;
876 sdl->sdl_family = AF_LINK;
877 sdl->sdl_index = ifp->if_index;
878 sdl->sdl_type = IFT_ETHER;
879 sdl->sdl_nlen = 0;
880 sdl->sdl_alen = ETHER_ADDR_LEN;
881 sdl->sdl_slen = 0;
882 e_addr = LLADDR(sdl);
883 ETHER_MAP_IP_MULTICAST(&sin->sin_addr, e_addr);
884 *llsa = (struct sockaddr *)sdl;
885 return 0;
886 #endif
887
888 default:
889 /*
890 * Well, the text isn't quite right, but it's the name
891 * that counts...
892 */
893 return EAFNOSUPPORT;
894 }
895 }
896
897 #ifdef NETGRAPH
898
899 /***********************************************************************
900 * This section contains the methods for the Netgraph interface
901 ***********************************************************************/
902 /* It's Ascii-art time!
903 * The ifnet is the first part of the arpcom which must be
904 * the first part of the device's softc.. yuk.
905 *
906 * +--------------------------+-----+---------+
907 * | struct ifnet (*ifp) | | |
908 * | | | |
909 * +--------------------------+ | |
910 * +--|[ac_ng] struct arpcom (*ac) | |
911 * | +--------------------------------+ |
912 * | | struct softc (*ifp->if_softc) (device) |
913 * | +------------------------------------------+
914 * | ^
915 * AC2NG() |
916 * | v
917 * | +----------------------+
918 * | | [private] [flags] |
919 * +------>| struct ng_node |
920 * | [hooks] | ** we only allow one hook
921 * +----------------------+
922 * ^
923 * |
924 * v
925 * +-------------+
926 * | [node] |
927 * | hook |
928 * | [private]|-- *unused*
929 * +-------------+
930 */
931
932 /*
933 * called during interface attaching
934 */
935 static void
936 ngether_init(void *ifpvoid)
937 {
938 struct ifnet *ifp = ifpvoid;
939 struct arpcom *ac = IFP2AC(ifp);
940 static int ngether_done_init;
941 char namebuf[32];
942 node_p node;
943
944 /*
945 * we have found a node, make sure our 'type' is availabe.
946 */
947 if (ngether_done_init == 0) {
948 if (ng_newtype(&typestruct)) {
949 printf("ngether install failed\n");
950 return;
951 }
952 ngether_done_init = 1;
953 }
954 if (ng_make_node_common(&typestruct, &node) != 0)
955 return;
956 ac->ac_ng = node;
957 node->private = ifp;
958 sprintf(namebuf, "%s%d", ifp->if_name, ifp->if_unit);
959 ng_name_node(AC2NG(ac), namebuf);
960 }
961
962 /*
963 * It is not possible or allowable to create a node of this type.
964 * If the hardware exists, it will already have created it.
965 */
966 static int
967 ngether_constructor(node_p *nodep)
968 {
969 return (EINVAL);
970 }
971
972 /*
973 * Give our ok for a hook to be added...
974 *
975 * Allow one hook at a time (rawdata).
976 * It can eiteh rdivert everything or only unclaimed packets.
977 */
978 static int
979 ngether_newhook(node_p node, hook_p hook, const char *name)
980 {
981
982 /* check if there is already a hook */
983 if (LIST_FIRST(&(node->hooks)))
984 return(EISCONN);
985 /*
986 * Check for which mode hook we want.
987 */
988 if (strcmp(name, NG_ETHER_HOOK_ORPHAN) != 0) {
989 if (strcmp(name, NG_ETHER_HOOK_DIVERT) != 0) {
990 return (EINVAL);
991 }
992 node->flags |= NGEF_DIVERT;
993 } else {
994 node->flags &= ~NGEF_DIVERT;
995 }
996 return (0);
997 }
998
999 /*
1000 * incoming messages.
1001 * Just respond to the generic TEXT_STATUS message
1002 */
1003 static int
1004 ngether_rcvmsg(node_p node,
1005 struct ng_mesg *msg, const char *retaddr, struct ng_mesg **resp)
1006 {
1007 struct ifnet *ifp;
1008 int error = 0;
1009
1010 ifp = node->private;
1011 switch (msg->header.typecookie) {
1012 case NGM_ETHER_COOKIE:
1013 error = EINVAL;
1014 break;
1015 case NGM_GENERIC_COOKIE:
1016 switch(msg->header.cmd) {
1017 case NGM_TEXT_STATUS: {
1018 char *arg;
1019 int pos = 0;
1020 int resplen = sizeof(struct ng_mesg) + 512;
1021 MALLOC(*resp, struct ng_mesg *, resplen,
1022 M_NETGRAPH, M_NOWAIT);
1023 if (*resp == NULL) {
1024 error = ENOMEM;
1025 break;
1026 }
1027 bzero(*resp, resplen);
1028 arg = (*resp)->data;
1029
1030 /*
1031 * Put in the throughput information.
1032 */
1033 pos = sprintf(arg, "%ld bytes in, %ld bytes out\n",
1034 ifp->if_ibytes, ifp->if_obytes);
1035 pos += sprintf(arg + pos,
1036 "%ld output errors\n",
1037 ifp->if_oerrors);
1038 pos += sprintf(arg + pos,
1039 "ierrors = %ld\n",
1040 ifp->if_ierrors);
1041
1042 (*resp)->header.version = NG_VERSION;
1043 (*resp)->header.arglen = strlen(arg) + 1;
1044 (*resp)->header.token = msg->header.token;
1045 (*resp)->header.typecookie = NGM_ETHER_COOKIE;
1046 (*resp)->header.cmd = msg->header.cmd;
1047 strncpy((*resp)->header.cmdstr, "status",
1048 NG_CMDSTRLEN);
1049 }
1050 break;
1051 default:
1052 error = EINVAL;
1053 break;
1054 }
1055 break;
1056 default:
1057 error = EINVAL;
1058 break;
1059 }
1060 free(msg, M_NETGRAPH);
1061 return (error);
1062 }
1063
1064 /*
1065 * Receive a completed ethernet packet.
1066 * Queue it for output.
1067 */
1068 static int
1069 ngether_rcvdata(hook_p hook, struct mbuf *m, meta_p meta)
1070 {
1071 struct ifnet *ifp;
1072 int error = 0;
1073 int s;
1074 struct ether_header *eh;
1075
1076 ifp = hook->node->private;
1077
1078 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
1079 senderr(ENETDOWN);
1080 /* drop in the MAC address */
1081 eh = mtod(m, struct ether_header *);
1082 bcopy(IFP2AC(ifp)->ac_enaddr, eh->ether_shost, 6);
1083 /*
1084 * If a simplex interface, and the packet is being sent to our
1085 * Ethernet address or a broadcast address, loopback a copy.
1086 * XXX To make a simplex device behave exactly like a duplex
1087 * device, we should copy in the case of sending to our own
1088 * ethernet address (thus letting the original actually appear
1089 * on the wire). However, we don't do that here for security
1090 * reasons and compatibility with the original behavior.
1091 */
1092 if (ifp->if_flags & IFF_SIMPLEX) {
1093 if (m->m_flags & M_BCAST) {
1094 struct mbuf *n = m_copy(m, 0, (int)M_COPYALL);
1095
1096 ng_queue_data(hook, n, meta);
1097 } else if (bcmp(eh->ether_dhost,
1098 eh->ether_shost, ETHER_ADDR_LEN) == 0) {
1099 ng_queue_data(hook, m, meta);
1100 return (0); /* XXX */
1101 }
1102 }
1103 s = splimp();
1104 /*
1105 * Queue message on interface, and start output if interface
1106 * not yet active.
1107 * XXX if we lookead at the priority in the meta data we could
1108 * queue high priority items at the head.
1109 */
1110 if (IF_QFULL(&ifp->if_snd)) {
1111 IF_DROP(&ifp->if_snd);
1112 splx(s);
1113 senderr(ENOBUFS);
1114 }
1115 IF_ENQUEUE(&ifp->if_snd, m);
1116 if ((ifp->if_flags & IFF_OACTIVE) == 0)
1117 (*ifp->if_start)(ifp);
1118 splx(s);
1119 ifp->if_obytes += m->m_pkthdr.len;
1120 if (m->m_flags & M_MCAST)
1121 ifp->if_omcasts++;
1122 return (error);
1123
1124 bad:
1125 NG_FREE_DATA(m, meta);
1126 return (error);
1127 }
1128
1129 /*
1130 * pass an mbuf out to the connected hook
1131 * More complicated than just an m_prepend, as it tries to save later nodes
1132 * from needing to do lots of m_pullups.
1133 */
1134 static void
1135 ngether_send(struct arpcom *ac, struct ether_header *eh, struct mbuf *m)
1136 {
1137 int room;
1138 node_p node = AC2NG(ac);
1139 struct ether_header *eh2;
1140
1141 if (node && LIST_FIRST(&(node->hooks))) {
1142 /*
1143 * Possibly the header is already on the front,
1144 */
1145 eh2 = mtod(m, struct ether_header *) - 1;
1146 if ( eh == eh2) {
1147 /*
1148 * This is the case so just move the markers back to
1149 * re-include it. We lucked out.
1150 * This allows us to avoid a yucky m_pullup
1151 * in later nodes if it works.
1152 */
1153 m->m_len += sizeof(*eh);
1154 m->m_data -= sizeof(*eh);
1155 m->m_pkthdr.len += sizeof(*eh);
1156 } else {
1157 /*
1158 * Alternatively there may be room even though
1159 * it is stored somewhere else. If so, copy it in.
1160 * This only safe because we KNOW that this packet has
1161 * just been generated by an ethernet card, so there
1162 * are no aliases to the buffer. (unlike in outgoing
1163 * packets).
1164 * Nearly all ethernet cards will end up producing mbufs
1165 * that fall into these cases. So we are not optimising
1166 * contorted cases.
1167 */
1168
1169 if (m->m_flags & M_EXT) {
1170 room = (mtod(m, caddr_t) - m->m_ext.ext_buf);
1171 if (room > m->m_ext.ext_size) /* garbage */
1172 room = 0; /* fail immediatly */
1173 } else {
1174 room = (mtod(m, caddr_t) - m->m_pktdat);
1175 }
1176 if (room > sizeof (*eh)) {
1177 /* we have room, just copy it and adjust */
1178 m->m_len += sizeof(*eh);
1179 m->m_data -= sizeof(*eh);
1180 m->m_pkthdr.len += sizeof(*eh);
1181 } else {
1182 /*
1183 * Doing anything more is likely to get more
1184 * expensive than it's worth..
1185 * it's probable that everything else is in one
1186 * big lump. The next node will do an m_pullup()
1187 * for exactly the amount of data it needs and
1188 * hopefully everything after that will not
1189 * need one. So let's just use M_PREPEND.
1190 */
1191 M_PREPEND(m, sizeof (*eh), M_DONTWAIT);
1192 if (m == NULL)
1193 return;
1194 }
1195 bcopy ((caddr_t)eh, mtod(m, struct ether_header *),
1196 sizeof(*eh));
1197 }
1198 ng_queue_data(LIST_FIRST(&(node->hooks)), m, NULL);
1199 } else {
1200 m_freem(m);
1201 }
1202 }
1203
1204 /*
1205 * do local shutdown processing..
1206 * This node will refuse to go away, unless the hardware says to..
1207 * don't unref the node, or remove our name. just clear our links up.
1208 */
1209 static int
1210 ngether_rmnode(node_p node)
1211 {
1212 ng_cutlinks(node);
1213 node->flags &= ~NG_INVALID; /* bounce back to life */
1214 return (0);
1215 }
1216
1217 /* already linked */
1218 static int
1219 ngether_connect(hook_p hook)
1220 {
1221 /* be really amiable and just say "YUP that's OK by me! " */
1222 return (0);
1223 }
1224
1225 /*
1226 * notify on hook disconnection (destruction)
1227 *
1228 * For this type, removal of the last lins no effect. The interface can run
1229 * independently.
1230 * Since we have no per-hook information, this is rather simple.
1231 */
1232 static int
1233 ngether_disconnect(hook_p hook)
1234 {
1235 hook->node->flags &= ~NGEF_DIVERT;
1236 return (0);
1237 }
1238 #endif /* NETGRAPH */
1239
1240 /********************************** END *************************************/
Cache object: 7501c7e3460fa79ec881b9a932f1bbd4
|