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

📄 rip2.c

📁 基于routed的RIP2, 实现了multicast 和Broadcast
💻 C
字号:
/* * *	NX-ROUTED *	RIP-2 Routing Daemon * *      This program is free software; you can redistribute it and/or modify *      it under the terms of the GNU General Public License as published by *      the Free Software Foundation; either version 2 of the License, or *      (at your option) any later version. *   *      This program is distributed in the hope that it will be useful, *      but WITHOUT ANY WARRANTY; without even the implied warranty of *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *      GNU General Public License for more details. *   *      You should have received a copy of the GNU General Public License *      along with this program; if not, write to the Free Software *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * *	Copyright (C) 2002 Valery Kholodkov *	Copyright (C) 2002 Andy Pershin *	Copyright (C) 2002 Antony Kholodkov * */#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <time.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <netdb.h>#include <time.h>#include "ctlfile.h"#include "router.h"#include "socket.h"#include "timers.h"#include "link.h"#include "util.h"#include "rip.h"struct rip2_header {	unsigned char command;	unsigned char version;	unsigned short zero;};struct rip2_rte {	unsigned short family;	unsigned short rtag;	unsigned int address;	unsigned int netmask;	unsigned int nexthop;	unsigned int metric;};struct rip2_auth {    u_int16_t xffff;    u_int16_t type;    char password[16];};extern struct rproto rip2_proto;struct rtable *rip2_announce_table;struct socket *rip2_socket;int rip_version=2;int rip2_auth=0;int rip2_multicast=0;int rip2_unicast=0;int rip2_allowqueries=0;int rip2_silent=0;unsigned int rip2_nextpartupd=0;unsigned int rip2_nextfullupd=0;unsigned int rip2_lastrequest_time = 0;unsigned int rip2_lastrequest_count = 0;#if 1 #define RIP_PORT_DEFAULT 520#define INADDR_RIP_GROUP        0xe0000009    /* 224.0.0.9 *//* Set up a multicast socket options for IPv4 * This is here so that people only have to do their OS multicast mess  * in one place rather than all through zebra, ospfd, and ripd  * NB: This is a hookpoint for specific OS functionality */intsetsockopt_multicast_ipv4(int sock, 		int optname, 		struct in_addr if_addr,		struct in_addr mcast_addr,		unsigned int ifindex){	struct ip_mreqn mreqn;	  	switch (optname)	{		case IP_MULTICAST_IF:		case IP_ADD_MEMBERSHIP:		case IP_DROP_MEMBERSHIP:			memset (&mreqn, 0, sizeof(mreqn));			if (mcast_addr.s_addr)				mreqn.imr_multiaddr = mcast_addr;				//mreqn.imr_multiaddr.s_addr = mcast_addr;			      			if (ifindex)				mreqn.imr_ifindex = ifindex;			else				mreqn.imr_address = if_addr;			      			return setsockopt(sock, IPPROTO_IP, optname, (void *)&mreqn, sizeof(mreqn));			break;		default:			/* Can out and give an understandable error */			//errno = EINVAL;			return -1;			break;	}}/* Utility function to set boradcast option to the socket. */intsockopt_broadcast (int sock){	int ret;	int on = 1;	ret = setsockopt (sock, SOL_SOCKET, SO_BROADCAST, (char *) &on, sizeof on);	if (ret < 0)	{		error ("can't set sockopt SO_BROADCAST to socket %d", sock);		return -1;	}	  return 0;}intsockopt_reuseaddr (int sock){	int ret;	int on = 1;	ret = setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, 			(void *) &on, sizeof (on));	if (ret < 0)	{		error ( "can't set sockopt SO_REUSEADDR to socket %d", sock);		return -1;	}	return 0;}voidrip_interface_multicast_set (int sock, struct link *p){	int ret;	struct sockaddr_in from;	struct in_addr addr;	struct in_addr maddr;	addr.s_addr = htonl(p->address);	maddr.s_addr = htonl(p->multicast);	if (setsockopt_multicast_ipv4 (sock, IP_ADD_MEMBERSHIP, addr, maddr, 0) < 0) 	{		error ("Can't setsockopt IP_MULTICAST_IF to fd %d", sock);		return;	}	maddr.s_addr = htonl(0);	if (setsockopt_multicast_ipv4 (sock, IP_MULTICAST_IF, addr, maddr, 0) < 0) 	{		error ("Can't setsockopt IP_MULTICAST_IF to fd %d", sock);		return;	}	/* Bind myself. */	memset (&from, 0, sizeof (struct sockaddr_in));	/* Set RIP port. */	from.sin_port = htons (RIP_PORT_DEFAULT);	/* Address shoud be any address. */	from.sin_family = AF_INET;	from.sin_addr = addr;#ifdef HAVE_SIN_LEN	from.sin_len = sizeof (struct sockaddr_in);#endif /* HAVE_SIN_LEN */	ret = bind (sock, (struct sockaddr *) & from, sizeof (struct sockaddr_in));	if (ret < 0)	{		//error ("Can't bind socket: %s", strerror (errno));		return;	}	return;}/* RIP packet send to destination address. */intmulti_send_packet (caddr_t buf, int size, struct sockaddr_in *to,  struct link *p){	int ret;	struct sockaddr_in sin;	int sock;	/* Make destination address. */	memset (&sin, 0, sizeof (struct sockaddr_in));	sin.sin_family = AF_INET;#ifdef HAVE_SIN_LEN	sin.sin_len = sizeof (struct sockaddr_in);#endif /* HAVE_SIN_LEN */	/* When destination is specified, use it's port and address. */	if (to)	{		//sock = rip->sock;		sin.sin_port = to->sin_port;		sin.sin_addr = to->sin_addr;	}	else	{		sock = socket (AF_INET, SOCK_DGRAM, 0);		sockopt_broadcast (sock);		sockopt_reuseaddr (sock);		/*sockopt_reuseport (sock);*/		sin.sin_port = htons (RIP_PORT_DEFAULT);		sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP);		/* Set multicast interface. */		rip_interface_multicast_set (sock, p);	}	ret = sendto (sock, buf, size, 0, (struct sockaddr *)&sin,			sizeof (struct sockaddr_in));	if (ret < 0)		debug(5,"can't send packet ");	if (! to)		close (sock);	return ret;}#endif  /*agui*/struct rtable *rip2_calculate_partial_rtable(struct rtable *announce_table) {	struct rtable *rtable;	struct route *p,*q;		rtable = new_rtable();	p = announce_table->routes;		while(p) {		if(p->flags & RF_CHANGED) {			p->flags &= ~RF_CHANGED;			q = dup_route(p);			add_route(rtable,q);		}		p = p->next;	}		return rtable;}void rip2_announce(void *arg) {	struct rproto *rproto = (struct rproto *)arg;#ifdef PARTIAL_UPDATES		struct rtable *partial_rtable;#endif		debug(5, "rip2_announce 1 \n");	if(rproto == NULL)		return;		debug(5,"rip2_announce 2 \n");	// Prevent partial update now (not completed for this version)		/* this is madness.. thousends of timers!	rip2_nextpartupd = 0;	rip2_nextfullupd = time(NULL) + RIP_SUPPLYTIME;	set_timer(&rip2_announce,&rip2_proto,RIP_SUPPLYTIME);	*/	/* I loose 1 whole second somewhere, and because of that, the rip2_announce	 * timer doesn't get set again.. But where??	 * HACK: Add 1 second tolerance (thats that -1 for q;))	 */	if ((rip2_nextfullupd-1) <= time(NULL)) {		debug(5,"rip2_announce 3");		/* this was not a triggerd update (but regular 30 sec), thou shall repeate it in time again */		rip2_nextpartupd = 0;		rip2_nextfullupd = time(NULL) + RIP_SUPPLYTIME;		set_timer(&rip2_announce,&rip2_proto,RIP_SUPPLYTIME);	}	if(rip2_nextpartupd == 0) {		debug(5,"rip2_announce 4");		//if(debuglevel < 7){	       	//	printf("######");			//	dump_rtable(rip2_announce_table);		//}		rip2_announce_table = system_read_rtable(); ///				announce_routes(rproto,rip2_announce_table);		return;	}	debug(5,"rip2_announce 5");#ifdef PARTIAL_UPDATES	partial_rtable = rip2_calculate_partial_rtable(rip2_announce_table);	announce_routes(rproto,partial_rtable);	free_rtable(partial_rtable);	#endif	rip2_nextpartupd = 0;}int rip2_init_config(){	rip2_multicast = get_param_b("rip2","multicast",0);	rip2_silent = get_param_b("rip2","silent",0);		rip2_allowqueries = get_param_b("rip2","allowqueries",1);	return 0;}int rip2_init_protocol(struct rproto *rproto) {	if(rip2_silent)		log_msg("Silent mode on");	rip2_announce_table = new_rtable();	return 0;}int rip2_init() {		struct sockaddr_in	sin;	struct servent		*svp;	struct socket		*socket;		/*	 *	檩磐 握治偈 邢以	 */	        debug(5,"rip2_init run\n");			svp = getservbyname ("router", "udp");	if (svp != (struct servent *) 0)		rip2_proto.port = ntohs(svp->s_port);	// Initializing configuration files	if(rip2_init_protocol(&rip2_proto) < 0) {		error("Unable to initialize RIP2");		return -1;	}		// 蚺巧釉疑艺磐 幸显纤咸			if(register_routing_protocol(&rip2_proto) < 0) {		error("Unable to register RIP2 routing protocol");		return -1;	}		if((socket = socket_create(&rip2_proto)) == NULL) {		error("Unable to create RIP2 socket");		return -1;	}		if(socket_bind_to_local_port(socket,rip2_proto.port) < 0) {		error("Unable to bind socket to local address");		return -1;	}		if(rip2_multicast) {		debug(5,"rip2_multicast mode");		sin.sin_family = AF_INET;		sin.sin_addr.s_addr = htonl(RIP_MCAST);		sin.sin_port = htons(rip2_proto.port);			if(socket_bind_to_multicast(socket,&sin) < 0) {			error("Unable to set multicast membership");			return -1;		}		}		if(socketlist_add(socket) < 0) {		error("Unable to register RIP2 socket");		return -1;	}		// 笤磷赏 粤释乓 瘟 廖衔淤	// Full update will be in 3 seconds	// 	rip2_nextfullupd = time(NULL) + 3;	if(set_timer(&rip2_announce,&rip2_proto,3) < 0) {		error("Unable to register RIP2 broadcasting timer");		return -1;			}		// 钫 耘信邑 呐抑稍

⌨️ 快捷键说明

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