2 * $Id: ether_mod-2.5.c,v 1.1.1.1 2000/05/25 00:28:49 route Exp $
5 * OpenBSD 2.5 ether_mod.c - lkm replacement for ether_output
7 * Copyright (c) 1999, 2000 Trevor Scheroeder <tschroed@zweknu.org>
8 * Copyright (c) 1998, 1999, 2000 Mike D. Schiffman <mike@infonexus.com>
9 * Original code and idea 1997 Thomas Ptacek <tqbf@pobox.com
11 * Copyright (c) 1982, 1989, 1993
12 * The Regents of the University of California. All rights reserved.
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 * 3. All advertising materials mentioning features or use of this software
23 * must display the following acknowledgement:
24 * This product includes software developed by the University of
25 * California, Berkeley and its contributors.
26 * 4. Neither the name of the University nor the names of its contributors
27 * may be used to endorse or promote products derived from this software
28 * without specific prior written permission.
30 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
31 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
34 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
36 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
42 * @(#)if_ethersubr.c 8.1 (Berkeley) 6/10/93
48 %%% portions-copyright-nrl-95
49 Portions of this software are Copyright 1995-1998 by Randall Atkinson,
50 Ronald Lee, Daniel McDonald, Bao Phan, and Chris Winters. All Rights
51 Reserved. All rights under this copyright have been assigned to the US
52 Naval Research Laboratory (NRL). The NRL Copyright Notice and License
53 Agreement Version 1.1 (January 17, 1995) applies to these portions of the
55 You should have received a copy of the license with this software. If you
56 didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>.
59 #include <sys/param.h>
60 #include <sys/systm.h>
61 #include <sys/kernel.h>
62 #include <sys/malloc.h>
64 #include <sys/protosw.h>
65 #include <sys/socket.h>
66 #include <sys/ioctl.h>
67 #include <sys/errno.h>
68 #include <sys/syslog.h>
70 #include <machine/cpu.h>
73 #include <net/netisr.h>
74 #include <net/route.h>
75 #include <net/if_llc.h>
76 #include <net/if_dl.h>
77 #include <net/if_types.h>
79 #include <netinet/in.h>
81 #include <netinet/in_var.h>
83 #include <netinet/if_ether.h>
85 /*#include "bridge.h"*/
87 #include <net/if_bridge.h>
92 #include <netns/ns_if.h>
96 #include <netipx/ipx.h>
97 #include <netipx/ipx_if.h>
101 #include <netiso/argo_debug.h>
102 #include <netiso/iso.h>
103 #include <netiso/iso_var.h>
104 #include <netiso/iso_snpac.h>
107 #include <netccitt/x25.h>
108 #include <netccitt/pk.h>
109 #include <netccitt/pk_extern.h>
110 #include <netccitt/dll.h>
111 #include <netccitt/llc_var.h>
114 #include <netatalk/at.h>
115 #include <netatalk/at_var.h>
116 #include <netatalk/at_extern.h>
118 #define llc_snap_org_code llc_un.type_snap.org_code
119 #define llc_snap_ether_type llc_un.type_snap.ether_type
121 extern u_char at_org_code[ 3 ];
122 extern u_char aarp_org_code[ 3 ];
123 #endif /* NETATALK */
126 #include <sys/socketvar.h>
130 #include <netinet6/in6.h>
131 #include <netinet6/in6_var.h>
134 #define senderr(e) { error = (e); goto bad;}
138 * Ethernet output routine.
139 * Encapsulate a packet of type family for the local net.
140 * Assumes that ifp is actually pointer to arpcom structure.
143 ether_output_spoof(ifp, m0, dst, rt0)
144 register struct ifnet *ifp;
146 struct sockaddr *dst;
151 u_char edst[6], esrc[6];
152 register struct mbuf *m = m0;
153 register struct rtentry *rt;
154 struct mbuf *mcopy = (struct mbuf *)0;
155 register struct ether_header *eh;
156 struct arpcom *ac = (struct arpcom *)ifp;
158 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
160 ifp->if_lastchange = time;
161 if ((rt = rt0) != NULL) {
162 if ((rt->rt_flags & RTF_UP) == 0) {
163 if ((rt0 = rt = rtalloc1(dst, 1)) != NULL)
166 senderr(EHOSTUNREACH);
168 if (rt->rt_flags & RTF_GATEWAY) {
169 if (rt->rt_gwroute == 0)
171 if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
172 rtfree(rt); rt = rt0;
173 lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1);
174 if ((rt = rt->rt_gwroute) == 0)
175 senderr(EHOSTUNREACH);
178 if (rt->rt_flags & RTF_REJECT)
179 if (rt->rt_rmx.rmx_expire == 0 ||
180 time.tv_sec < rt->rt_rmx.rmx_expire)
181 senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
183 switch (dst->sa_family) {
187 if (!arpresolve(ac, rt, m, dst, edst))
188 return (0); /* if not yet resolved */
189 /* If broadcasting on a simplex interface, loopback a copy */
190 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
191 mcopy = m_copy(m, 0, (int)M_COPYALL);
192 etype = htons(ETHERTYPE_IP);
193 bcopy(ac->ac_enaddr, esrc, sizeof (edst));
198 etype = htons(ETHERTYPE_NS);
199 bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
200 (caddr_t)edst, sizeof (edst));
201 if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst)))
202 return (looutput(ifp, m, dst, rt));
203 /* If broadcasting on a simplex interface, loopback a copy */
204 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
205 mcopy = m_copy(m, 0, (int)M_COPYALL);
210 etype = htons(ETHERTYPE_IPX);
211 bcopy((caddr_t)&satosipx(dst)->sipx_addr.ipx_host,
212 (caddr_t)edst, sizeof (edst));
213 if (!bcmp((caddr_t)edst, (caddr_t)&ipx_thishost, sizeof(edst)))
214 return (looutput(ifp, m, dst, rt));
215 /* If broadcasting on a simplex interface, loopback a copy */
216 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
217 mcopy = m_copy(m, 0, (int)M_COPYALL);
223 * The bottom line here is to either queue the outgoing packet
224 * in the discovery engine, or fill in edst with something
227 if (m->m_flags & M_MCAST) {
229 * If multicast dest., then use IPv6 -> Ethernet
230 * mcast mapping. Really simple.
232 ETHER_MAP_IN6_MULTICAST(((struct sockaddr_in6 *)dst)->sin6_addr,
235 /* Do unicast neighbor discovery stuff. */
236 if (!ipv6_discov_resolve(ifp, rt, m, dst, edst))
239 etype = htons(ETHERTYPE_IPV6);
244 struct at_ifaddr *aa;
246 if (!aarpresolve(ac, m, (struct sockaddr_at *)dst, edst)) {
248 extern char *prsockaddr(struct sockaddr *);
249 printf("aarpresolv: failed for %s\n", prsockaddr(dst));
250 #endif /* NETATALKDEBUG */
255 * ifaddr is the first thing in at_ifaddr
257 aa = (struct at_ifaddr *)at_ifawithnet(
258 (struct sockaddr_at *)dst,
259 ifp->if_addrlist.tqh_first);
264 * In the phase 2 case, we need to prepend an mbuf for the llc
265 * header. Since we must preserve the value of m, which is
266 * passed to us by value, we m_copy() the first mbuf,
267 * and use it for our llc header.
269 if ( aa->aa_flags & AFA_PHASE2 ) {
272 /* XXX Really this should use netisr too */
273 M_PREPEND(m, AT_LLC_SIZE, M_WAIT);
275 * FreeBSD doesn't count the LLC len in
276 * ifp->obytes, so they increment a length
277 * field here. We don't do this.
279 llc.llc_dsap = llc.llc_ssap = LLC_SNAP_LSAP;
280 llc.llc_control = LLC_UI;
281 bcopy(at_org_code, llc.llc_snap_org_code,
282 sizeof(at_org_code));
283 llc.llc_snap_ether_type = htons( ETHERTYPE_AT );
284 bcopy(&llc, mtod(m, caddr_t), AT_LLC_SIZE);
285 etype = htons(m->m_pkthdr.len);
287 etype = htons(ETHERTYPE_AT);
290 #endif /* NETATALK */
295 register struct sockaddr_dl *sdl;
297 if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway) &&
298 sdl->sdl_family == AF_LINK && sdl->sdl_alen > 0) {
299 bcopy(LLADDR(sdl), (caddr_t)edst, sizeof(edst));
301 error = iso_snparesolve(ifp, (struct sockaddr_iso *)dst,
302 (char *)edst, &snpalen);
304 goto bad; /* Not Resolved */
306 /* If broadcasting on a simplex interface, loopback a copy */
308 m->m_flags |= (M_BCAST|M_MCAST);
309 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX) &&
310 (mcopy = m_copy(m, 0, (int)M_COPYALL))) {
311 M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT);
313 eh = mtod(mcopy, struct ether_header *);
314 bcopy(edst, eh->ether_dhost, sizeof (edst));
315 bcopy(ac->ac_enaddr, eh->ether_shost,
319 M_PREPEND(m, 3, M_DONTWAIT);
322 etype = htons(m->m_pkthdr.len);
323 l = mtod(m, struct llc *);
324 l->llc_dsap = l->llc_ssap = LLC_ISO_LSAP;
325 l->llc_control = LLC_UI;
327 if (argo_debug[D_ETHER]) {
329 printf("unoutput: sending pkt to: ");
331 printf("%x ", edst[i] & 0xff);
339 register struct sockaddr_dl *sdl =
340 (struct sockaddr_dl *) rt -> rt_gateway;
342 if (sdl && sdl->sdl_family == AF_LINK
343 && sdl->sdl_alen > 0) {
344 bcopy(LLADDR(sdl), (char *)edst,
346 } else goto bad; /* Not a link interface ? Funny ... */
347 if ((ifp->if_flags & IFF_SIMPLEX) && (*edst & 1) &&
348 (mcopy = m_copy(m, 0, (int)M_COPYALL))) {
349 M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT);
351 eh = mtod(mcopy, struct ether_header *);
352 bcopy(edst, eh->ether_dhost, sizeof (edst));
353 bcopy(esrc,eh->ether_shost,
357 etype = htons(m->m_pkthdr.len);
361 register struct llc *l = mtod(m, struct llc *);
363 printf("ether_output: sending LLC2 pkt to: ");
365 printf("%x ", edst[i] & 0xff);
366 printf(" len 0x%x dsap 0x%x ssap 0x%x control 0x%x\n",
367 m->m_pkthdr.len, l->llc_dsap & 0xff, l->llc_ssap &0xff,
368 l->llc_control & 0xff);
371 #endif /* LLC_DEBUG */
375 eh = (struct ether_header *)dst->sa_data;
376 bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst));
377 bcopy((caddr_t)eh->ether_shost, (caddr_t)esrc, sizeof (edst));
378 /* AF_UNSPEC doesn't swap the byte order of the ether_type. */
379 etype = eh->ether_type;
383 printf("%s: can't handle af%d\n", ifp->if_xname,
385 senderr(EAFNOSUPPORT);
389 (void) looutput(ifp, mcopy, dst, rt);
392 * Add local net header. If no space in first mbuf,
395 M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT);
398 eh = mtod(m, struct ether_header *);
399 bcopy((caddr_t)&etype,(caddr_t)&eh->ether_type,
400 sizeof(eh->ether_type));
401 bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst));
402 bcopy((caddr_t)esrc, (caddr_t)eh->ether_shost,
403 sizeof(eh->ether_shost));
404 /* bcopy((caddr_t)ac->ac_enaddr, (caddr_t)eh->ether_shost,
405 sizeof(eh->ether_shost)); */
409 * Interfaces that are bridge members need special handling
412 if (ifp->if_bridge) {
413 bridge_output(ifp, m, NULL, NULL);
420 * Queue message on interface, and start output if interface
423 if (IF_QFULL(&ifp->if_snd)) {
424 IF_DROP(&ifp->if_snd);
428 ifp->if_obytes += m->m_pkthdr.len;
429 IF_ENQUEUE(&ifp->if_snd, m);
430 if (m->m_flags & M_MCAST)
432 if ((ifp->if_flags & IFF_OACTIVE) == 0)
433 (*ifp->if_start)(ifp);