libnet的unix/linux版本

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

软件大小: 137 K
上传用户: albert333
关键词: libnet linux unix 版本
下载地址: 免注册下载 普通下载 VIP

相关代码

				/*				 *  $Id: ether_mod-2.4.c,v 1.1.1.1 2000/05/25 00:28:49 route 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);				}							

相关资源