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

📄 net-ip.cc

📁 柯老师网站上找到的
💻 CC
📖 第 1 页 / 共 2 页
字号:
/*- * Copyright (c) 1993-1994, 1998 * The 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 University of *      California, Berkeley and the Network Research Group at *      Lawrence Berkeley 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/net-ip.cc,v 1.17 2000/02/08 23:35:13 salehi Exp $ (LBL)";#endif#include <stdio.h>#ifndef WIN32#include <unistd.h>#endif#include <time.h>#include <errno.h>#include <string.h>#ifdef WIN32#include <io.h>#define close closesocket#else#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>typedef int Socket;#endif#if defined(sun) && defined(__svr4__)#include <sys/systeminfo.h>#endif#include "config.h"#include "net.h"#include "inet.h"#include "tclcl.h"#include "scheduler.h"//#define	NIPDEBUG	1#ifdef NIPDEBUG#define NIDEBUG(x) { if (NIPDEBUG) fprintf(stderr, (x)); }#define NIDEBUG2(x,y) { if (NIPDEBUG) fprintf(stderr, (x), (y)); }#define NIDEBUG3(x,y,z) { if (NIPDEBUG) fprintf(stderr, (x), (y), (z)); }#define NIDEBUG4(w,x,y,z) { if (NIPDEBUG) fprintf(stderr, (w), (x), (y), (z)); }#define NIDEBUG5(v,w,x,y,z) { if (NIPDEBUG) fprintf(stderr, (v), (w), (x), (y), (z)); }#else#define NIDEBUG(x) { }#define NIDEBUG2(x,y) { }#define NIDEBUG3(x,y,z) { }#define NIDEBUG4(w,x,y,z) { }#define NIDEBUG5(v,w,x,y,z) { }#endif/* * Net-ip.cc: this file defines the IP and IP/UDP network * objects.  IP provides a raw IP interface and support functions * [such as setting multicast parameters].  IP/UDP provides a standard * UDP datagram interface. *///// IPNetwork: a low-level (raw) IP network object//class IPNetwork : public Network {public:	IPNetwork();        inline int ttl() const { return (mttl_); }	// current mcast ttl	inline int noloopback_broken() {		// no loopback filter?		return (noloopback_broken_);	}	int setmttl(Socket, int);			// set mcast ttl	int setmloop(Socket, int);			// set mcast loopback	int command(int argc, const char*const* argv);	// virtual in Network	inline Socket rchannel() { return(rsock_); }	// virtual in Network	inline Socket schannel() { return(ssock_); }	// virtual in Network        int send(u_char* buf, int len);			// virtual in Network        int recv(u_char* buf, int len, sockaddr& from, double& ); // virtual in Network        inline in_addr& laddr() { return (localaddr_); }        inline in_addr& dstaddr() { return (destaddr_); }	int add_membership(Socket, in_addr& grp);	// join mcast	int drop_membership(Socket, in_addr& grp);	// leave mcast	/* generally useful routines */	static int bindsock(Socket, in_addr&, u_int16_t, sockaddr_in&);	static int connectsock(Socket, in_addr&, u_int16_t, sockaddr_in&);	static int rbufsize(Socket, int);	static int sbufsize(Socket, int);protected:	in_addr destaddr_;		// remote side, if set (network order)	in_addr localaddr_;		// local side (network order)        int mttl_;			// multicast ttl to use	Socket rsock_;			// socket to receive on	Socket ssock_;			// socket to send on        int noloopback_broken_;		// couldn't turn (off) mcast loopback	int loop_;			// do we want loopbacks?					// (system usually assumes yes)	void reset(int reconfigure);			// reset + reconfig?	virtual int open(int mode);	// open sockets/endpoints	virtual void reconfigure();	// restore state after reset	int close();	time_t last_reset_;};class UDPIPNetwork : public IPNetwork {public:	UDPIPNetwork();	int send(u_char*, int);	int recv(u_char*, int, sockaddr&, double&);	int open(int mode);			// mode only	int command(int argc, const char*const* argv);	void reconfigure();	void add_membership(Socket, in_addr&, u_int16_t); // udp versionprotected:	int bind(in_addr&, u_int16_t port);	// bind to addr/port, mcast ok	int connect(in_addr& remoteaddr, u_int16_t port);	// connect()        u_int16_t lport_;	// local port (network order)        u_int16_t port_;	// remote (dst) port (network order)};static class IPNetworkClass : public TclClass {    public:	IPNetworkClass() : TclClass("Network/IP") {}	TclObject* create(int, const char*const*) {		return (new IPNetwork);	}} nm_ip;static class UDPIPNetworkClass : public TclClass {    public:	UDPIPNetworkClass() : TclClass("Network/IP/UDP") {}	TclObject* create(int, const char*const*) {		return (new UDPIPNetwork);	}} nm_ip_udp;IPNetwork::IPNetwork() :	mttl_(0),        rsock_(-1),         ssock_(-1),        noloopback_broken_(0),	loop_(1){	localaddr_.s_addr = 0L;	destaddr_.s_addr = 0L;	NIDEBUG("IPNetwork: ctor\n");}UDPIPNetwork::UDPIPNetwork() :        lport_(htons(0)),         port_(htons(0)){	NIDEBUG("UDPIPNetwork: ctor\n");}/* * UDPIP::send -- send "len" bytes in buffer "buf" out the sending * channel. * * returns the number of bytes written */intUDPIPNetwork::send(u_char* buf, int len){	int cc = ::send(schannel(), (char*)buf, len, 0);	NIDEBUG5("UDPIPNetwork(%s): ::send(%d, buf, %d) returned %d\n",		name(), schannel(), len, cc);	if (cc < 0) {		switch (errno) {		case ECONNREFUSED:			/* no one listening at some site - ignore */#if defined(__osf__) || defined(_AIX) || defined(__FreeBSD__)			/*			 * Here's an old comment...			 *			 * Due to a bug in kern/uipc_socket.c, on several			 * systems, datagram sockets incorrectly persist			 * in an error state on receipt of an ICMP			 * port-unreachable.  This causes unicast connection			 * rendezvous problems, and worse, multicast			 * transmission problems because several systems			 * incorrectly send port unreachables for 			 * multicast destinations.  Our work around			 * is to simply close and reopen the socket			 * (by calling reset() below).			 *			 * This bug originated at CSRG in Berkeley			 * and was present in the BSD Reno networking			 * code release.  It has since been fixed			 * in 4.4BSD and OSF-3.x.  It is known to remain			 * in AIX-4.1.3.			 *			 * A fix is to change the following lines from			 * kern/uipc_socket.c:			 *			 *	if (so_serror)			 *		snderr(so->so_error);			 *			 * to:			 *			 *	if (so->so_error) {			 * 		error = so->so_error;			 *		so->so_error = 0;			 *		splx(s);			 *		goto release;			 *	}			 *			 */			reset(1);#endif			break;		case ENETUNREACH:		case EHOSTUNREACH:			/*			 * These "errors" are totally meaningless.			 * There is some broken host sending			 * icmp unreachables for multicast destinations.			 * UDP probably aborted the send because of them --			 * try exactly once more.  E.g., the send we			 * just did cleared the errno for the previous			 * icmp unreachable, so we should be able to			 * send now.			 */			cc = ::send(schannel(), (char*)buf, len, 0);			break;		default:			fprintf(stderr, "UDPIPNetwork(%s): send failed: %s\n",				name(), strerror(errno));			return (-1);		}	}	return cc;	// bytes sent}intUDPIPNetwork::recv(u_char* buf, int len, sockaddr& from, double& ts){	sockaddr_in sfrom;	int fromlen = sizeof(sfrom);	int cc = ::recvfrom(rsock_, (char*)buf, len, 0,			    (sockaddr*)&sfrom, &fromlen);	NIDEBUG5("UDPIPNetwork(%s): ::recvfrom(%d, buf, %d) returned %d\n",		name(), rsock_, len, cc);	if (cc < 0) {		if (errno != EWOULDBLOCK) {			fprintf(stderr,				"UDPIPNetwork(%s): recvfrom failed: %s\n",				name(), strerror(errno));		}		return (-1);	}	from = *((sockaddr*)&sfrom);	/*	 * if we received multicast data and we don't want the look,	 * there is a chance it is	 * what we sent if "noloopback_broken_" is set.	 * If so, filter out the stuff we don't want right here.	 */ 	if (!loop_ && noloopback_broken_ &&	    sfrom.sin_addr.s_addr == localaddr_.s_addr &&	    sfrom.sin_port == lport_) {	NIDEBUG2("UDPIPNetwork(%s): filtered out our own pkt\n", name());		return (0);	// empty	}	ts = Scheduler::instance().clock();	return (cc);	// number of bytes received}intUDPIPNetwork::open(int mode){	if (mode == O_RDONLY || mode == O_RDWR) {		rsock_ = socket(AF_INET, SOCK_DGRAM, 0);		if (rsock_ < 0) {			fprintf(stderr,	"UDPIPNetwork(%s): open: couldn't open rcv sock\n",				name());		}		nonblock(rsock_);		int on = 1;		if (::setsockopt(rsock_, SOL_SOCKET, SO_REUSEADDR, (char *)&on,				sizeof(on)) < 0) {			fprintf(stderr,	"UDPIPNetwork(%s): open: warning: unable set REUSEADDR: %s\n",				name(), strerror(errno));		}#ifdef SO_REUSEPORT		on = 1;		if (::setsockopt(rsock_, SOL_SOCKET, SO_REUSEPORT, (char *)&on,			       sizeof(on)) < 0) {			fprintf(stderr,	"UDPIPNetwork(%s): open: warning: unable set REUSEPORT: %s\n",				name(), strerror(errno));		}#endif		/*		 * XXX don't need this for the session socket.		 */			if (rbufsize(rsock_, 80*1024) < 0) {			if (rbufsize(rsock_, 32*1024) < 0) {				fprintf(stderr,		"UDPIPNetwork(%s): open: unable to set r bufsize to %d: %s\n",					name(), 32*1024, strerror(errno));			}		}	}	if (mode == O_WRONLY || mode == O_RDWR) {		ssock_ = socket(AF_INET, SOCK_DGRAM, 0);		if (ssock_ < 0) {			fprintf(stderr,	"UDPIPNetwork(%s): open: couldn't open snd sock\n",				name());		}		nonblock(ssock_);		int firsttry = 80 * 1024;		int secondtry = 48 * 1024;				if (sbufsize(ssock_, firsttry) < 0) {			if (sbufsize(ssock_, secondtry) < 0) {				fprintf(stderr,  "UDPIPNetwork(%s): open: cannot set send sockbuf size to %d bytes, using default\n",  				name(), secondtry);			}		}	}	mode_ = mode;	NIDEBUG5("UDPIPNetwork(%s): opened network w/mode %d, ssock:%d, rsock:%d\n",		name(), mode_, rsock_, ssock_);	return (0);}//// IP/UDP version of add_membership: try binding//voidUDPIPNetwork::add_membership(Socket sock, in_addr& addr, u_int16_t port){	int failure = 0;	sockaddr_in sin;	if (bindsock(sock, addr, port, sin) < 0)		failure = 1;	if (failure) {		in_addr addr2 = addr;		addr2.s_addr = INADDR_ANY;		if (bindsock(sock, addr2, port, sin) < 0)			failure = 1;		else			failure = 0;	}	if (IPNetwork::add_membership(sock, addr) < 0)		failure = 1;	if (failure) {		fprintf(stderr,		"UDPIPNetwork(%s): add_membership: failed bind on mcast addr %s and INADDR_ANY\n",			name(), inet_ntoa(addr));	}}//// server-side bind (or mcast subscription)//intUDPIPNetwork::bind(in_addr& addr, u_int16_t port){	NIDEBUG4("UDPIPNetwork(%s): attempt to bind to addr %s, port %d [net order]\n",		name(), inet_ntoa(addr), ntohs(port));	if (rsock_ < 0) {		fprintf(stderr,		"UDPIPNetwork(%s): bind/listen called before net is open\n",			name());		return (-1);	}	if (mode_ == O_WRONLY) {		fprintf(stderr,		"UDPIPNetwork(%s): attempted bind/listen but net is write-only\n",			name());		return (-1);	}#ifdef IP_ADD_MEMBERSHIP        if (IN_CLASSD(ntohl(addr.s_addr))) {		// MULTICAST case, call UDPIP vers of add_membership                add_membership(rsock_, addr, port);        } else#endif        {		// UNICAST case                sockaddr_in sin;                if (bindsock(rsock_, addr, port, sin) < 0) {                        port = ntohs(port);                        fprintf(stderr,        "UDPIPNetwork(%s): bind: unable to bind %s [port:%hu]: %s\n",                                name(), inet_ntoa(addr),                                port, strerror(errno));			return (-1);                }                /*                 * MS Windows currently doesn't compy with the Internet Host                 * Requirements standard (RFC-1122) and won't let us include                 * the source address in the receive socket demux state.                 */#ifndef WIN32                /*                 * (try to) connect the foreign host's address to this socket.                 */                (void)connectsock(rsock_, addr, 0, sin);#endif        }	localaddr_ = addr;	lport_ = port;	return (0);}//// client-side connect//intUDPIPNetwork::connect(in_addr& addr, u_int16_t port){	sockaddr_in sin;	if (ssock_ < 0) {		fprintf(stderr,		"UDPIPNetwork(%s): connect called before net is open\n",			name());

⌨️ 快捷键说明

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