Libnet is a generic networking API that provides access to several protocols. It is not designed as

源代码在线查看: ether_mod-2.4.c

软件大小: 548 K
上传用户: focuslocus
关键词: networking protocols designed provides
下载地址: 免注册下载 普通下载 VIP

相关代码

				/*
				 *  $Id: ether_mod-2.4.c,v 1.1.1.1 2002/09/16 12:58:06 robertol Exp $
				 *
				 *  libnet
				 *  OpenBSD 2.4 ether_mod.c - lkm replacement for ether_output
				 *
				 *  Copyright (c) 1998, 1999, 2000 Mike D. Schiffman 
				 *
				 *  Original code and idea 1997 Thomas Ptacek 
				 *  All rights reserved.
				 *
				 * Redistribution and use in source and binary forms, with or without
				 * modification, are permitted provided that the following conditions
				 * are met:
				 * 1. Redistributions of source code must retain the above copyright
				 *    notice, this list of conditions and the following disclaimer.
				 * 2. Redistributions in binary form must reproduce the above copyright
				 *    notice, this list of conditions and the following disclaimer in the
				 *    documentation and/or other materials provided with the distribution.
				 *
				 *
				 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
				 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
				 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
				 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
				 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
				 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
				 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
				 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
				 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
				 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
				 * SUCH DAMAGE.
				 *
				 */
				
				#define INET
				
				#include 
				#include 
				#include 
				#include 
				#include 
				#include 
				#include 
				#include 
				#include 
				#include 
				
				#include 
				
				#include 
				#include 
				#include 
				#include 
				#include 
				#include 
				
				#include 
				#ifdef INET
				#include 
				#endif
				#include 
				
				#ifdef NS
				#include 
				#include 
				#endif
				
				#ifdef IPX
				#include 
				#include 
				#endif
				
				#ifdef ISO
				#include 
				#include 
				#include 
				#include 
				#endif
				
				#include 
				#include 
				#include 
				#include 
				#include 
				
				#ifdef NETATALK
				#include 
				#include 
				#include 
				
				#define llc_snap_org_code llc_un.type_snap.org_code
				#define llc_snap_ether_type llc_un.type_snap.ether_type
				
				extern u_char	at_org_code[ 3 ];
				extern u_char	aarp_org_code[ 3 ];
				#endif /* NETATALK */
				
				#if defined(CCITT)
				#include 
				#endif
				
				#define senderr(e) { error = (e); goto bad;}
				
				
				int ether_output_spoof(register struct ifnet *, struct mbuf *,
				                        struct sockaddr *, struct rtentry *);
				
				/*
				 * Ethernet output routine.
				 * Encapsulate a packet of type family for the local net.
				 * Assumes that ifp is actually pointer to arpcom structure.
				 */
				int
				ether_output_spoof(ifp, m0, dst, rt0)
					register struct ifnet *ifp;
					struct mbuf *m0;
					struct sockaddr *dst;
					struct rtentry *rt0;
				{
					u_int16_t etype;
					int s, error = 0;
				 	u_char edst[6], esrc[6];
					register struct mbuf *m = m0;
					register struct rtentry *rt;
					struct mbuf *mcopy = (struct mbuf *)0;
					register struct ether_header *eh;
					struct arpcom *ac = (struct arpcom *)ifp;
				
					if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
						senderr(ENETDOWN);
					ifp->if_lastchange = time;
					if ((rt = rt0) != NULL) {
						if ((rt->rt_flags & RTF_UP) == 0) {
							if ((rt0 = rt = rtalloc1(dst, 1)) != NULL)
								rt->rt_refcnt--;
							else 
								senderr(EHOSTUNREACH);
						}
						if (rt->rt_flags & RTF_GATEWAY) {
							if (rt->rt_gwroute == 0)
								goto lookup;
							if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
								rtfree(rt); rt = rt0;
							lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1);
								if ((rt = rt->rt_gwroute) == 0)
									senderr(EHOSTUNREACH);
							}
						}
						if (rt->rt_flags & RTF_REJECT)
							if (rt->rt_rmx.rmx_expire == 0 ||
							    time.tv_sec < rt->rt_rmx.rmx_expire)
								senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
					}
					switch (dst->sa_family) {
				
				#ifdef INET
					case AF_INET:
						if (!arpresolve(ac, rt, m, dst, edst))
							return (0);	/* if not yet resolved */
						/* If broadcasting on a simplex interface, loopback a copy */
						if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
							mcopy = m_copy(m, 0, (int)M_COPYALL);
						etype = htons(ETHERTYPE_IP);
				                bcopy((caddr_t)ac->ac_enaddr,esrc,sizeof(esrc));
						break;
				#endif
				#ifdef NS
					case AF_NS:
						etype = htons(ETHERTYPE_NS);
				 		bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
						    (caddr_t)edst, sizeof (edst));
						if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst)))
							return (looutput(ifp, m, dst, rt));
						/* If broadcasting on a simplex interface, loopback a copy */
						if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
							mcopy = m_copy(m, 0, (int)M_COPYALL);
						break;
				#endif
				#ifdef IPX
					case AF_IPX:
						etype = htons(ETHERTYPE_IPX);
				 		bcopy((caddr_t)&satosipx(dst)->sipx_addr.ipx_host,
						    (caddr_t)edst, sizeof (edst));
						if (!bcmp((caddr_t)edst, (caddr_t)&ipx_thishost, sizeof(edst)))
							return (looutput(ifp, m, dst, rt));
						/* If broadcasting on a simplex interface, loopback a copy */
						if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
							mcopy = m_copy(m, 0, (int)M_COPYALL);
						break;
				#endif
				#ifdef NETATALK
					case AF_APPLETALK: {
						struct at_ifaddr *aa;
				
						if (!aarpresolve(ac, m, (struct sockaddr_at *)dst, edst)) {
				#ifdef NETATALKDEBUG
							extern char *prsockaddr(struct sockaddr *);
							printf("aarpresolv: failed for %s\n", prsockaddr(dst));
				#endif /* NETATALKDEBUG */
							return (0);
						}
				
						/*
						 * ifaddr is the first thing in at_ifaddr
						 */
						aa = (struct at_ifaddr *)at_ifawithnet(
							(struct sockaddr_at *)dst,
							ifp->if_addrlist.tqh_first);
						if (aa == 0)
							goto bad;
				
						/*
						 * In the phase 2 case, we need to prepend an mbuf for the llc
						 * header. Since we must preserve the value of m, which is
						 * passed to us by value, we m_copy() the first mbuf,
						 * and use it for our llc header.
						 */
						if ( aa->aa_flags & AFA_PHASE2 ) {
							struct llc llc;
				
							/* XXX Really this should use netisr too */
							M_PREPEND(m, AT_LLC_SIZE, M_WAIT);
							/*
							 * FreeBSD doesn't count the LLC len in
							 * ifp->obytes, so they increment a length
							 * field here. We don't do this.
							 */
							llc.llc_dsap = llc.llc_ssap = LLC_SNAP_LSAP;
							llc.llc_control = LLC_UI;
							bcopy(at_org_code, llc.llc_snap_org_code,
								sizeof(at_org_code));
							llc.llc_snap_ether_type = htons( ETHERTYPE_AT );
							bcopy(&llc, mtod(m, caddr_t), AT_LLC_SIZE);
							etype = htons(m->m_pkthdr.len);
						} else {
							etype = htons(ETHERTYPE_AT);
						}
						} break;
				#endif /* NETATALK */
				#ifdef	ISO
					case AF_ISO: {
						int	snpalen;
						struct	llc *l;
						register struct sockaddr_dl *sdl;
				
						if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway) &&
						    sdl->sdl_family == AF_LINK && sdl->sdl_alen > 0) {
							bcopy(LLADDR(sdl), (caddr_t)edst, sizeof(edst));
						} else {
							error = iso_snparesolve(ifp, (struct sockaddr_iso *)dst,
										(char *)edst, &snpalen);
							if (error)
								goto bad; /* Not Resolved */
						}
						/* If broadcasting on a simplex interface, loopback a copy */
						if (*edst & 1)
							m->m_flags |= (M_BCAST|M_MCAST);
						if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX) &&
						    (mcopy = m_copy(m, 0, (int)M_COPYALL))) {
							M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT);
							if (mcopy) {
								eh = mtod(mcopy, struct ether_header *);
								bcopy((caddr_t)edst,
								      (caddr_t)eh->ether_dhost, sizeof (edst));
								bcopy((caddr_t)ac->ac_enaddr,
								      (caddr_t)eh->ether_shost, sizeof (edst));
							}
						}
						M_PREPEND(m, 3, M_DONTWAIT);
						if (m == NULL)
							return (0);
						etype = htons(m->m_pkthdr.len);
						l = mtod(m, struct llc *);
						l->llc_dsap = l->llc_ssap = LLC_ISO_LSAP;
						l->llc_control = LLC_UI;
				#ifdef ARGO_DEBUG
						if (argo_debug[D_ETHER]) {
							int i;
							printf("unoutput: sending pkt to: ");
							for (i=0; i								printf("%x ", edst[i] & 0xff);
							printf("\n");
						}
				#endif
						} break;
				#endif /* ISO */
				/*	case AF_NSAP: */
					case AF_CCITT: {
						register struct sockaddr_dl *sdl = 
							(struct sockaddr_dl *) rt -> rt_gateway;
				
						if (sdl && sdl->sdl_family == AF_LINK
						    && sdl->sdl_alen > 0) {
							bcopy(LLADDR(sdl), (char *)edst,
								sizeof(edst));
						} else goto bad; /* Not a link interface ? Funny ... */
						if ((ifp->if_flags & IFF_SIMPLEX) && (*edst & 1) &&
						    (mcopy = m_copy(m, 0, (int)M_COPYALL))) {
							M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT);
							if (mcopy) {
								eh = mtod(mcopy, struct ether_header *);
								bcopy((caddr_t)edst,
								      (caddr_t)eh->ether_dhost, sizeof (edst));
								bcopy((caddr_t)ac->ac_enaddr,
								      (caddr_t)eh->ether_shost, sizeof (edst));
							}
						}
						etype = htons(m->m_pkthdr.len);
				#ifdef LLC_DEBUG
						{
							int i;
							register struct llc *l = mtod(m, struct llc *);
				
							printf("ether_output: sending LLC2 pkt to: ");
							for (i=0; i								printf("%x ", edst[i] & 0xff);
							printf(" len 0x%x dsap 0x%x ssap 0x%x control 0x%x\n", 
							    m->m_pkthdr.len, l->llc_dsap & 0xff, l->llc_ssap &0xff,
							    l->llc_control & 0xff);
				
						}
				#endif /* LLC_DEBUG */
						} break;
				
					case AF_UNSPEC:
						eh = (struct ether_header *)dst->sa_data;
				 		bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst));
				                bcopy((caddr_t)eh->ether_shost, (caddr_t)esrc, sizeof (esrc));
						/* AF_UNSPEC doesn't swap the byte order of the ether_type. */
						etype = eh->ether_type;
						break;
				
					default:
						printf("%s: can't handle af%d\n", ifp->if_xname,
							dst->sa_family);
						senderr(EAFNOSUPPORT);
					}
				
					if (mcopy)
						(void) looutput(ifp, mcopy, dst, rt);
				
					/*
					 * Add local net header.  If no space in first mbuf,
					 * allocate another.
					 */
					M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT);
					if (m == 0)
						senderr(ENOBUFS);
					eh = mtod(m, struct ether_header *);
					bcopy((caddr_t)&etype,(caddr_t)&eh->ether_type, sizeof(eh->ether_type));
				 	bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst));
				 	bcopy((caddr_t)esrc, (caddr_t)eh->ether_shost, sizeof (esrc));
				
					s = splimp();
					/*
					 * Queue message on interface, and start output if interface
					 * not yet active.
					 */
					if (IF_QFULL(&ifp->if_snd)) {
						IF_DROP(&ifp->if_snd);
						splx(s);
						senderr(ENOBUFS);
					}
					ifp->if_obytes += m->m_pkthdr.len;
					IF_ENQUEUE(&ifp->if_snd, m);
					if (m->m_flags & M_MCAST)
						ifp->if_omcasts++;
					if ((ifp->if_flags & IFF_OACTIVE) == 0)
						(*ifp->if_start)(ifp);
					splx(s);
					return (error);
				
				bad:
					if (m)
						m_freem(m);
					return (error);
				}
							

相关资源