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