2 * $Id: ether_mod-2.7.c,v 1.1.1.1 2000/05/25 00:28:49 route Exp $
5 * OpenBSD 2.7 ether_mod.c - lkm replacement for ether_output
6 * update by obecian <obecian@subterrain.net>
8 * Copyright (c) 1999, 2000 Trevor Scheroeder <tschroed@zweknu.org>
9 * Copyright (c) 1998, 1999, 2000 Mike D. Schiffman <mike@infonexus.com>
10 * Original code and idea 1997 Thomas Ptacek <tqbf@pobox.com
12 * Copyright (c) 1982, 1989, 1993
13 * The Regents of the University of California. All rights reserved.
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
18 * 1. Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in the
22 * documentation and/or other materials provided with the distribution.
23 * 3. All advertising materials mentioning features or use of this software
24 * must display the following acknowledgement:
25 * This product includes software developed by the University of
26 * California, Berkeley and its contributors.
27 * 4. Neither the name of the University nor the names of its contributors
28 * may be used to endorse or promote products derived from this software
29 * without specific prior written permission.
31 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
32 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
33 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
34 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
35 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
39 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
40 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43 * @(#)if_ethersubr.c 8.1 (Berkeley) 6/10/93
49 %%% portions-copyright-nrl-95
50 Portions of this software are Copyright 1995-1998 by Randall Atkinson,
51 Ronald Lee, Daniel McDonald, Bao Phan, and Chris Winters. All Rights
52 Reserved. All rights under this copyright have been assigned to the US
53 Naval Research Laboratory (NRL). The NRL Copyright Notice and License
54 Agreement Version 1.1 (January 17, 1995) applies to these portions of the
56 You should have received a copy of the license with this software. If you
57 didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>.
60 #include <sys/param.h>
61 #include <sys/systm.h>
62 #include <sys/kernel.h>
63 #include <sys/malloc.h>
65 #include <sys/protosw.h>
66 #include <sys/socket.h>
67 #include <sys/ioctl.h>
68 #include <sys/errno.h>
69 #include <sys/syslog.h>
71 #include <machine/cpu.h>
74 #include <net/netisr.h>
75 #include <net/route.h>
76 #include <net/if_llc.h>
77 #include <net/if_dl.h>
78 #include <net/if_types.h>
80 #include <netinet/in.h>
82 #include <netinet/in_var.h>
84 #include <netinet/if_ether.h>
86 /*#include "bridge.h"*/
88 #include <net/if_bridge.h>
93 #include <netns/ns_if.h>
97 #include <netipx/ipx.h>
98 #include <netipx/ipx_if.h>
102 #include <netiso/argo_debug.h>
103 #include <netiso/iso.h>
104 #include <netiso/iso_var.h>
105 #include <netiso/iso_snpac.h>
108 #include <netccitt/x25.h>
109 #include <netccitt/pk.h>
110 #include <netccitt/pk_extern.h>
111 #include <netccitt/dll.h>
112 #include <netccitt/llc_var.h>
115 #include <netatalk/at.h>
116 #include <netatalk/at_var.h>
117 #include <netatalk/at_extern.h>
119 #define llc_snap_org_code llc_un.type_snap.org_code
120 #define llc_snap_ether_type llc_un.type_snap.ether_type
122 extern u_char at_org_code[ 3 ];
123 extern u_char aarp_org_code[ 3 ];
124 #endif /* NETATALK */
127 #include <sys/socketvar.h>
131 #include <netinet6/in6.h>
132 #include <netinet6/in6_var.h>
135 #define senderr(e) { error = (e); goto bad;}
139 * Ethernet output routine.
140 * Encapsulate a packet of type family for the local net.
141 * Assumes that ifp is actually pointer to arpcom structure.
144 ether_output_spoof(ifp, m0, dst, rt0)
145 register struct ifnet *ifp;
147 struct sockaddr *dst;
152 u_char edst[6], esrc[6];
153 register struct mbuf *m = m0;
154 register struct rtentry *rt;
155 struct mbuf *mcopy = (struct mbuf *)0;
156 register struct ether_header *eh;
157 struct arpcom *ac = (struct arpcom *)ifp;
159 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
161 ifp->if_lastchange = time;
162 if ((rt = rt0) != NULL) {
163 if ((rt->rt_flags & RTF_UP) == 0) {
164 if ((rt0 = rt = rtalloc1(dst, 1)) != NULL)
167 senderr(EHOSTUNREACH);
169 if (rt->rt_flags & RTF_GATEWAY) {
170 if (rt->rt_gwroute == 0)
172 if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
173 rtfree(rt); rt = rt0;
174 lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1);
175 if ((rt = rt->rt_gwroute) == 0)
176 senderr(EHOSTUNREACH);
179 if (rt->rt_flags & RTF_REJECT)
180 if (rt->rt_rmx.rmx_expire == 0 ||
181 time.tv_sec < rt->rt_rmx.rmx_expire)
182 senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
184 switch (dst->sa_family) {
188 if (!arpresolve(ac, rt, m, dst, edst))
189 return (0); /* if not yet resolved */
190 /* If broadcasting on a simplex interface, loopback a copy */
191 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
192 mcopy = m_copy(m, 0, (int)M_COPYALL);
193 etype = htons(ETHERTYPE_IP);
194 bcopy(ac->ac_enaddr, esrc, sizeof (edst));
199 etype = htons(ETHERTYPE_NS);
200 bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
201 (caddr_t)edst, sizeof (edst));
202 if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst)))
203 return (looutput(ifp, m, dst, rt));
204 /* If broadcasting on a simplex interface, loopback a copy */
205 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
206 mcopy = m_copy(m, 0, (int)M_COPYALL);
211 etype = htons(ETHERTYPE_IPX);
212 bcopy((caddr_t)&satosipx(dst)->sipx_addr.ipx_host,
213 (caddr_t)edst, sizeof (edst));
214 if (!bcmp((caddr_t)edst, (caddr_t)&ipx_thishost, sizeof(edst)))
215 return (looutput(ifp, m, dst, rt));
216 /* If broadcasting on a simplex interface, loopback a copy */
217 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
218 mcopy = m_copy(m, 0, (int)M_COPYALL);
224 * The bottom line here is to either queue the outgoing packet
225 * in the discovery engine, or fill in edst with something
228 if (m->m_flags & M_MCAST) {
230 * If multicast dest., then use IPv6 -> Ethernet
231 * mcast mapping. Really simple.
233 ETHER_MAP_IN6_MULTICAST(((struct sockaddr_in6 *)dst)->sin6_addr,
236 /* Do unicast neighbor discovery stuff. */
237 if (!ipv6_discov_resolve(ifp, rt, m, dst, edst))
240 etype = htons(ETHERTYPE_IPV6);
245 struct at_ifaddr *aa;
247 if (!aarpresolve(ac, m, (struct sockaddr_at *)dst, edst)) {
249 extern char *prsockaddr(struct sockaddr *);
250 printf("aarpresolv: failed for %s\n", prsockaddr(dst));
251 #endif /* NETATALKDEBUG */
256 * ifaddr is the first thing in at_ifaddr
258 aa = (struct at_ifaddr *)at_ifawithnet(
259 (struct sockaddr_at *)dst,
260 ifp->if_addrlist.tqh_first);
265 * In the phase 2 case, we need to prepend an mbuf for the llc
266 * header. Since we must preserve the value of m, which is
267 * passed to us by value, we m_copy() the first mbuf,
268 * and use it for our llc header.
270 if ( aa->aa_flags & AFA_PHASE2 ) {
273 /* XXX Really this should use netisr too */
274 M_PREPEND(m, AT_LLC_SIZE, M_WAIT);
276 * FreeBSD doesn't count the LLC len in
277 * ifp->obytes, so they increment a length
278 * field here. We don't do this.
280 llc.llc_dsap = llc.llc_ssap = LLC_SNAP_LSAP;
281 llc.llc_control = LLC_UI;
282 bcopy(at_org_code, llc.llc_snap_org_code,
283 sizeof(at_org_code));
284 llc.llc_snap_ether_type = htons( ETHERTYPE_AT );
285 bcopy(&llc, mtod(m, caddr_t), AT_LLC_SIZE);
286 etype = htons(m->m_pkthdr.len);
288 etype = htons(ETHERTYPE_AT);
291 #endif /* NETATALK */
296 register struct sockaddr_dl *sdl;
298 if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway) &&
299 sdl->sdl_family == AF_LINK && sdl->sdl_alen > 0) {
300 bcopy(LLADDR(sdl), (caddr_t)edst, sizeof(edst));
302 error = iso_snparesolve(ifp, (struct sockaddr_iso *)dst,
303 (char *)edst, &snpalen);
305 goto bad; /* Not Resolved */
307 /* If broadcasting on a simplex interface, loopback a copy */
309 m->m_flags |= (M_BCAST|M_MCAST);
310 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX) &&
311 (mcopy = m_copy(m, 0, (int)M_COPYALL))) {
312 M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT);
314 eh = mtod(mcopy, struct ether_header *);
315 bcopy(edst, eh->ether_dhost, sizeof (edst));
316 bcopy(ac->ac_enaddr, eh->ether_shost,
320 M_PREPEND(m, 3, M_DONTWAIT);
323 etype = htons(m->m_pkthdr.len);
324 l = mtod(m, struct llc *);
325 l->llc_dsap = l->llc_ssap = LLC_ISO_LSAP;
326 l->llc_control = LLC_UI;
328 if (argo_debug[D_ETHER]) {
330 printf("unoutput: sending pkt to: ");
332 printf("%x ", edst[i] & 0xff);
340 register struct sockaddr_dl *sdl =
341 (struct sockaddr_dl *) rt -> rt_gateway;
343 if (sdl && sdl->sdl_family == AF_LINK
344 && sdl->sdl_alen > 0) {
345 bcopy(LLADDR(sdl), (char *)edst,
347 } else goto bad; /* Not a link interface ? Funny ... */
348 if ((ifp->if_flags & IFF_SIMPLEX) && (*edst & 1) &&
349 (mcopy = m_copy(m, 0, (int)M_COPYALL))) {
350 M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT);
352 eh = mtod(mcopy, struct ether_header *);
353 bcopy(edst, eh->ether_dhost, sizeof (edst));
354 bcopy(esrc,eh->ether_shost,
358 etype = htons(m->m_pkthdr.len);
362 register struct llc *l = mtod(m, struct llc *);
364 printf("ether_output: sending LLC2 pkt to: ");
366 printf("%x ", edst[i] & 0xff);
367 printf(" len 0x%x dsap 0x%x ssap 0x%x control 0x%x\n",
368 m->m_pkthdr.len, l->llc_dsap & 0xff, l->llc_ssap &0xff,
369 l->llc_control & 0xff);
372 #endif /* LLC_DEBUG */
376 eh = (struct ether_header *)dst->sa_data;
377 bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst));
378 bcopy((caddr_t)eh->ether_shost, (caddr_t)esrc, sizeof (edst));
379 /* AF_UNSPEC doesn't swap the byte order of the ether_type. */
380 etype = eh->ether_type;
384 printf("%s: can't handle af%d\n", ifp->if_xname,
386 senderr(EAFNOSUPPORT);
390 (void) looutput(ifp, mcopy, dst, rt);
393 * Add local net header. If no space in first mbuf,
396 M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT);
399 eh = mtod(m, struct ether_header *);
400 bcopy((caddr_t)&etype,(caddr_t)&eh->ether_type,
401 sizeof(eh->ether_type));
402 bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst));
403 bcopy((caddr_t)esrc, (caddr_t)eh->ether_shost,
404 sizeof(eh->ether_shost));
405 /* bcopy((caddr_t)ac->ac_enaddr, (caddr_t)eh->ether_shost,
406 sizeof(eh->ether_shost)); */
410 * Interfaces that are bridge members need special handling
413 if (ifp->if_bridge) {
414 bridge_output(ifp, m, NULL, NULL);
421 * Queue message on interface, and start output if interface
424 if (IF_QFULL(&ifp->if_snd)) {
425 IF_DROP(&ifp->if_snd);
429 ifp->if_obytes += m->m_pkthdr.len;
430 IF_ENQUEUE(&ifp->if_snd, m);
431 if (m->m_flags & M_MCAST)
433 if ((ifp->if_flags & IFF_OACTIVE) == 0)
434 (*ifp->if_start)(ifp);