⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 arp.cc

📁 柯老师网站上找到的
💻 CC
字号:
/* * Copyright (c) 1998 Regents of the University of California. * 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. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *      This product includes software developed by the Network Research *      Group at Lawrence Berkeley National Laboratory. * 4. Neither the name of the University nor of the Laboratory may be used *    to endorse or promote products derived from this software without *    specific prior written permission. *    * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. */  #ifndef lintstatic const char rcsid[] =    "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/emulate/arp.cc,v 1.6 2000/02/08 23:35:12 salehi Exp $";#endif#include "object.h"#include "packet.h"#include <sys/types.h>#include <sys/param.h>#include <sys/socket.h>#include <sys/ioctl.h>#include <netinet/in.h>#include <netinet/in_systm.h>#include <netinet/ip.h>#include <net/if.h>#include <net/ethernet.h>#include <net/if_arp.h>#include <netinet/if_ether.h>#include <arpa/inet.h>#include <memory.h>#include <stdio.h>#include <errno.h>#include "emulate/net.h"#include "emulate/ether.h"#include "emulate/internet.h"//// arp.cc -- this object may be used within nse as// an ARP requestor/responder.  Only the request side// is implemented now [5/98]// class ArpAgent : public NsObject, public IOHandler {public:	ArpAgent();	~ArpAgent();protected:	struct acache_entry {		in_addr	ip;		ether_addr ether;		char code;	// 'D' - dynamic, 'P' - publish	};			char	icode(const char*);	acache_entry* find(in_addr&);	void 	insert(in_addr&, ether_addr&, char code);	void	dispatch(int);	int	sendreq(in_addr&);	int	sendresp(ether_addr&, in_addr&, ether_addr&);	int	resolve(const char* host, char*& result, int sendreq);	void	doreq(ether_arp*);	void	doreply(ether_arp*);	void recv(Packet*, Handler*) { abort(); }	int command(int, const char*const*);	Network*	net_;	ether_header	eh_template_;	ether_arp	ea_template_;	ether_addr	my_ether_;	in_addr		my_ip_;	int		base_size_;	// size of rcv buf	u_char*		rcv_buf_;	acache_entry*	acache_;	// arp mapping cache	int		nacache_;	// # entries in cache	int		cur_;		// cur posn in cache	int		pending_;	// resolve pending?};static class ArpAgentClass : public TclClass { public:        ArpAgentClass() : TclClass("ArpAgent") {}        TclObject* create(int , const char*const*) {                return (new ArpAgent());        } } class_arpagent;ArpAgent::ArpAgent() : net_(NULL), pending_(0){	/* dest addr is broadcast */	eh_template_.ether_dhost[0] = 0xff;	eh_template_.ether_dhost[1] = 0xff;	eh_template_.ether_dhost[2] = 0xff;	eh_template_.ether_dhost[3] = 0xff;	eh_template_.ether_dhost[4] = 0xff;	eh_template_.ether_dhost[5] = 0xff;	/* src addr is mine */	memcpy(&eh_template_.ether_shost, &my_ether_, ETHER_ADDR_LEN);	/* type is ARP */	eh_template_.ether_type = htons(ETHERTYPE_ARP);	ea_template_.ea_hdr.ar_hrd = htons(ARPHRD_ETHER);	ea_template_.ea_hdr.ar_pro = htons(ETHERTYPE_IP);	ea_template_.ea_hdr.ar_hln = ETHER_ADDR_LEN;	ea_template_.ea_hdr.ar_pln = 4;			/* ip addr len */	ea_template_.ea_hdr.ar_op = htons(ARPOP_REQUEST);		memcpy(&ea_template_.arp_sha, &my_ether_, ETHER_ADDR_LEN);	/* sender hw */	memset(&ea_template_.arp_spa, 0, 4);			/* sender IP */	memset(&ea_template_.arp_tha, 0, ETHER_ADDR_LEN);	/* target hw */	memset(&ea_template_.arp_tpa, 0, 4);			/* target hw */	base_size_ = sizeof(eh_template_) + sizeof(ea_template_);	rcv_buf_ = new u_char[base_size_];	bind("cachesize_", &nacache_);	acache_ = new acache_entry[nacache_];	memset(acache_, 0, nacache_*sizeof(acache_entry));	cur_ = nacache_;}ArpAgent::~ArpAgent(){	delete[] rcv_buf_;	delete[] acache_;}ArpAgent::acache_entry*ArpAgent::find(in_addr& target){	int n = nacache_;	acache_entry* ae = &acache_[n-1];	while (--n >= 0) {		if (ae->ip.s_addr == target.s_addr) {			return (ae);		}		--ae;	}	return (NULL);}charArpAgent::icode(const char *how){	if (strcmp(how, "publish") == 0)		return 'P';	return 'D';}voidArpAgent::insert(in_addr& target, ether_addr& eaddr, char code){	acache_entry* ae;	if (--cur_ < 0)		cur_ = nacache_ - 1;	ae = &acache_[cur_];	ae->ip = target;	ae->ether = eaddr;	ae->code = code;//printf("INSERTED inet %s, ether %s\n",//inet_ntoa(target), Ethernet::etheraddr_string((u_char*)&eaddr));	return;}		intArpAgent::sendreq(in_addr& target){	int pktsz = sizeof(eh_template_) + sizeof(ea_template_);	if (pktsz < 64)		pktsz = 64;	u_char* buf = new u_char[pktsz];	memset(buf, 0, pktsz);	ether_header* eh = (ether_header*) buf;	ether_arp* ea = (ether_arp*) (buf + sizeof(eh_template_));	*eh = eh_template_;	/* set ether header */	*ea = ea_template_;	/* set ether/IP arp pkt */	memcpy(ea->arp_tpa, &target, sizeof(target));	if (net_->send(buf, pktsz) < 0) {                fprintf(stderr,                    "ArpAgent(%s): sendpkt (%p, %d): %s\n",                    name(), buf, pktsz, strerror(errno));                return (-1);	}	delete[] buf;	return (0);}/* * resp: who to send response to * tip: the IP address we are responding for * tea: the ether address we want to advertise with tip */intArpAgent::sendresp(ether_addr& dest, in_addr& tip, ether_addr& tea){	int pktsz = sizeof(eh_template_) + sizeof(ea_template_);	if (pktsz < 64)		pktsz = 64;	u_char* buf = new u_char[pktsz];	memset(buf, 0, pktsz);	ether_header* eh = (ether_header*) buf;	ether_arp* ea = (ether_arp*) (buf + sizeof(eh_template_));	// destination link layer address is back to sender	// (called dest here)	*eh = eh_template_;	/* set ether header */	memcpy(eh->ether_dhost, &dest, ETHER_ADDR_LEN);	// set code as ARP reply	*ea = ea_template_;	/* set ether/IP arp pkt */	ea->ea_hdr.ar_op = htons(ARPOP_REPLY);	// make it look like a regular arp reply	memcpy(ea->arp_tpa, ea->arp_spa, sizeof(in_addr));	memcpy(ea->arp_tha, ea->arp_sha, sizeof(in_addr));	memcpy(ea->arp_sha, &tea, ETHER_ADDR_LEN);	memcpy(ea->arp_spa, &tip, ETHER_ADDR_LEN);	if (net_->send(buf, pktsz) < 0) {                fprintf(stderr,                    "ArpAgent(%s): sendpkt (%p, %d): %s\n",                    name(), buf, pktsz, strerror(errno));                return (-1);	}	delete[] buf;	return (0);}/* * receive pkt from network: *	note that net->recv() gives us the pkt starting *	just BEYOND the frame header */voidArpAgent::dispatch(int){	double ts;	sockaddr sa;	int cc = net_->recv(rcv_buf_, base_size_, sa, ts);	if (cc < int(base_size_ - sizeof(ether_header))) {		if (cc == 0)			return;                fprintf(stderr,                    "ArpAgent(%s): recv small pkt (%d) [base sz:%d]: %s\n",                    name(), cc, base_size_, strerror(errno));		return;	}	ether_arp* ea = (ether_arp*) rcv_buf_;	int op = ntohs(ea->ea_hdr.ar_op);	switch (op) {	case ARPOP_REPLY:		doreply(ea);		break;	case ARPOP_REQUEST:		doreq(ea);		break;	default:		fprintf(stderr,		    "ArpAgent(%s): cannot interpret ARP op %d\n",		    name(), op);		return;	}	return;}/* * process an ARP reply frame -- insert into cache */voidArpAgent::doreply(ether_arp* ea){	/*	 * reply will be from the replier's point of view,	 * so, look in the sender ha/pa fields for the info	 * we want	 */	in_addr t;	ether_addr e;	memcpy(&t, ea->arp_spa, 4);	// copy IP address	memcpy(&e, ea->arp_sha, ETHER_ADDR_LEN);	insert(t, e, 'D');	return;}/* * process an ARP request frame */voidArpAgent::doreq(ether_arp* ea){	in_addr t;	memcpy(&t, ea->arp_tpa, 4);	// requested IP addr	acache_entry *ae;	if ((ae = find(t)) == NULL) {//printf("doreq: didn't find mapping for IP addr %s\n",//inet_ntoa(t));		return;	}	if (ae->code == 'P') {		// return answer to the sender's hardware addr		ether_addr dst;		memcpy(&dst, ea->arp_sha, ETHER_ADDR_LEN);		sendresp(dst, t, ae->ether);	}	return;}extern "C" {ether_addr* ether_aton();}intArpAgent::command(int argc, const char*const* argv){	Tcl& tcl = Tcl::instance();	if (argc == 2) {                if (strcmp(argv[1], "network") == 0) { 			if (net_ == NULL)				tcl.result("");			else				tcl.result(net_->name());			return (TCL_OK);		}	} else if (argc == 3) {                if (strcmp(argv[1], "network") == 0) {                         net_ = (Network *)TclObject::lookup(argv[2]);                        if (net_ != 0) { 				link(net_->rchannel(), TCL_READABLE);				return (TCL_OK);                        } else {                                fprintf(stderr,                                "ArpAgent(%s): unknown network %s\n",                                    name(), argv[2]);                                return (TCL_ERROR);                        }                               return(TCL_OK);                }       		if (strcmp(argv[1], "myether") == 0) {			my_ether_ = *(::ether_aton(argv[2]));			memcpy(&eh_template_.ether_shost, &my_ether_,				ETHER_ADDR_LEN);			memcpy(&ea_template_.arp_sha,				&my_ether_, ETHER_ADDR_LEN);			return (TCL_OK);		}		if (strcmp(argv[1], "myip") == 0) {			u_long a = inet_addr(argv[2]);			if (a == 0)				return (TCL_ERROR);			in_addr ia;			ia.s_addr = a;			my_ip_ = ia;			memcpy(&ea_template_.arp_spa,				&my_ip_, 4);			return (TCL_OK);		}		if (strcmp(argv[1], "lookup") == 0) {			char *p = NULL;			if (resolve(argv[2], p, 0) < 0)				return (TCL_ERROR);			if (p)				tcl.result(p);			return (TCL_OK);		}		if (strcmp(argv[1], "resolve") == 0) {			char *p = NULL;			if (resolve(argv[2], p, 1) < 0)				return (TCL_ERROR);			if (p)				tcl.resultf("%s", p);			return (TCL_OK);		}	} else if (argc == 5) {		// $obj insert iaddr eaddr how		if (strcmp(argv[1], "insert") == 0) {			u_long a = inet_addr(argv[2]);			if (a == 0)				return (TCL_ERROR);			in_addr ia;			ia.s_addr = a;			ether_addr ea = *(::ether_aton(argv[3]));			insert(ia, ea, icode(argv[4]));			return (TCL_OK);		}	}	return (NsObject::command(argc, argv));}intArpAgent::resolve(const char* host, char*& result, int doreq){	u_long a = inet_addr(host);	in_addr ia;	ia.s_addr = a;	acache_entry* ae;	if ((ae = find(ia)) == NULL) {		result = NULL;		if (doreq)			return(sendreq(ia));		return (0);	}	result = Ethernet::etheraddr_string((u_char*) &ae->ether);	return (1);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -