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

📄 ripin.c

📁 一个模拟RIP协议的简单实现
💻 C
字号:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <net/if.h>

#define RIPHSIZE     4
#define RIP_VERSION  1

#define RIP_REQUEST  1
#define RIP_RESPONSE 2

#define RIP_PORT       520

typedef struct 
{
  unsigned short rr_family;
  unsigned short rr_mbz1;
  struct in_addr rr_ipa;
  unsigned int rr_mbz2;
  unsigned int rr_mbz3;
  unsigned int rr_metric;
}riprt;

#define MAXRIPROUTES 25
#define RIP_INFINITY 16

#define RIPRTTL  12
#define RIPZTIME 18
#define RIPINT   30

typedef struct
{
	char rip_cmd;
	char rip_vers;
	unsigned short rip_mbz;
	riprt rip_rts[MAXRIPROUTES];
}rip; 

#define MAXROUTENUM 100
#define RT_INF      999

typedef struct
{
	riprt rt_route;
	unsigned long rt_gw;
	int rt_isvalid;
	long rt_ttl;
	int rt_status;
}routelist;

rip replPacket;
rip recvPacket;
riprt *rTable;
rip reqPacket;
routelist myList[MAXROUTENUM];

int routeNum;
int sock;
struct sockaddr_in to, from, server;
fd_set rfds;
struct timeval timer;
long timeoff;


void newRoute(riprt* rt_route, char* ipAddr,unsigned short newAFI, unsigned int newMetric)
{
	rt_route->rr_family=htons(newAFI);
	rt_route->rr_mbz1=0;
	inet_aton(ipAddr,&rt_route->rr_ipa);
	rt_route->rr_mbz2=0;
	rt_route->rr_mbz3=0;
	rt_route->rr_metric=htonl(newMetric);
}
void printRoute(riprt *rt_route)
{
	printf("Address Family Identifier: %d\n",ntohs(rt_route->rr_family));
	printf("IPv4 Address: %s\n",inet_ntoa(rt_route->rr_ipa));
	printf("Metric: %d\n",ntohl(rt_route->rr_metric));
	printf("\n");
}

void printList(){	int i;	printf("Num\tIP\t\tAFI\tMetric\tStatus\tNexthop\n");	for(i=0;i<MAXROUTENUM;i++)	{		if(myList[i].rt_isvalid!=1)			continue;		printf("%d\t%s\t%d\t%d\t%d\t",i,			inet_ntoa(myList[i].rt_route.rr_ipa),		ntohs(myList[i].rt_route.rr_family),ntohl(myList[i].rt_route.rr_metric),		myList[i].rt_status);		printf("%s\n",inet_ntoa(myList[i].rt_gw));	}}

void copyRoute(riprt *d,riprt *s)
{
	d->rr_family=s->rr_family;
	d->rr_ipa.s_addr=s->rr_ipa.s_addr;
	d->rr_metric=s->rr_metric;
}
int readFile(char* filename)
{
	FILE * file;
	file=fopen(filename,"r");
	if(file==NULL)
	{	
		printf("File Not Found.\n");
		return -1;
	}
	char ip[16];
	int afi, metric;
	while(fscanf(file,"%s %d %d\n",ip,&afi,&metric)!=EOF)
	{
		newRoute(&rTable[routeNum],ip,afi,metric);
		newRoute(&myList[routeNum].rt_route,ip,afi,metric);
		myList[routeNum].rt_ttl=RT_INF;
		myList[routeNum].rt_isvalid=1;
		myList[routeNum].rt_status=0;
		routeNum++;
	}
	fclose(file);
	return 1;
}
int settimer(void)
{
	int i;
	for(i=0;i<MAXROUTENUM;i++)
	{
		if(myList[i].rt_ttl == RT_INF) 
			continue;
		if(myList[i].rt_isvalid==1)
		{
			myList[i].rt_ttl-=timeoff;
			if(myList[i].rt_ttl<=0)
			{
				if(myList[i].rt_status==0)
				{
					printf("List[%d] is invalid.\n",i);
					myList[i].rt_status=1;
					myList[i].rt_ttl+=RIPZTIME;
				}
				else if(myList[i].rt_status==1)
				{
					printf("List[%d] to be deleted.\n",i);
					myList[i].rt_isvalid=0;
					routeNum--;
				}
			}
		}
	}
}

int ripinit()
{
	int length,temp=1,error,i;
	struct sockaddr_in tempip;
	routeNum=0;


	for(i=0;i<MAXROUTENUM;i++)
	{	
		newRoute(&myList[i].rt_route,"0.0.0.0",0,0);
		myList[i].rt_gw=0;
		myList[i].rt_isvalid=0;
		myList[i].rt_ttl=0;
		myList[i].rt_status=0;
	}

	//REQUEST packet
	reqPacket.rip_cmd=RIP_REQUEST;
	reqPacket.rip_vers=RIP_VERSION;
	reqPacket.rip_mbz=0;
	newRoute(&reqPacket.rip_rts[0],"0.0.0.0",0,RIP_INFINITY);
	
	//RESPONSE packet
	replPacket.rip_cmd=RIP_RESPONSE;
	replPacket.rip_vers=RIP_VERSION;
	replPacket.rip_mbz=0;
	rTable=replPacket.rip_rts;
	if(readFile("test.txt")<0)
	{
		printf("File not found.\n");
		return -1;
	}

	//timer
	timer.tv_sec=RIPINT;
	timer.tv_usec=0;

	//setup to
	to.sin_family=AF_INET;
	inet_aton("255.255.255.255",&to.sin_addr);
	to.sin_port=htons(RIP_PORT);

	//setup server
	server.sin_family=AF_INET;
	server.sin_addr.s_addr=htonl(INADDR_ANY);
	server.sin_port=htons(RIP_PORT);

	//create socket
	sock=socket(AF_INET,SOCK_DGRAM,0);
	if(sock<0)
	{
		printf("Can't create socket!\n");
		return -1;	
	}
	
	//open broadcast
	if(setsockopt(sock,SOL_SOCKET,SO_BROADCAST,&temp,sizeof(int))!=0)
	{
		printf("Can't enable Broadcast.\n");
		close(sock);
		return -1;
	}

	//bind
	if(bind(sock,(struct sockaddr *)&server,sizeof server)<0)
	{
		printf("Can't bind.\n");
		close(sock);
		return -1;
	}
	
	FD_ZERO(&rfds);
	FD_SET(sock,&rfds);

	error=sendto(sock,&reqPacket,RIPHSIZE+sizeof(riprt),0,(struct sockaddr*)(&to),sizeof(to));
	if(error<0)
		printf("Can't broadcast.\n");
	return 1;
}

int ripsend()
{
	int error,i,j,k;
	timer.tv_sec=RIPINT;
	timer.tv_usec=0;

	if(routeNum==0)
	{	
		printf("Route table is null.\n");
		return -1;
	}
	
	for(i=0,j=0,k=0;i<routeNum;i++)
	{
		while(myList[j].rt_isvalid!=1)
			j++;
		if(myList[j].rt_status!=0)
		{
			j++;
			continue;
		}
		copyRoute(&rTable[k],&myList[j].rt_route);
		j++;k++;
		if(j>MAXROUTENUM)
			printf("Out of Route list!\n");
	}
	if(k==0)
	{
		printf("Route list is null.\n");
		return -1;
	}
	error=sendto(sock,&replPacket,RIPHSIZE+k*sizeof(riprt),0,(struct sockaddr*)(&to),sizeof(to));
	if(error<0)
	{
		printf("Can't broadcast. Error %d\n",error);
	}
	return 1;
}
int riprecv()
{
	int recvLen,len,i,j,m,error;
	len=recvfrom(sock,&recvPacket,sizeof(recvPacket),0,(struct sockaddr*)&from,&recvLen);
	printf("%d recieved from %s.\n",len,inet_ntoa(from.sin_addr.s_addr));

	if((len-RIPHSIZE)%sizeof(riprt)!=0)
	{
		printf("Wrong packet.\n");
		return -2;
	}
	if(recvPacket.rip_vers!=RIP_VERSION||recvPacket.rip_mbz!=0)
	{
		printf("Packet not match.\n");
		return -3;
	}
	if(recvPacket.rip_cmd==RIP_REQUEST)
	{
		//request
		printf("Request\n");
		ripsend();
	}
	else if(recvPacket.rip_cmd==RIP_RESPONSE)
	{
		//response
		printf("Response\n");
		for(i=0;i<(len-RIPHSIZE)/sizeof(riprt);i++)
		{	
			m=ntohl(recvPacket.rip_rts[i].rr_metric);
			m++;
			if(m>=RIP_INFINITY)
				continue;
			recvPacket.rip_rts[i].rr_metric=htonl(m);
			for(j=0;j<MAXROUTENUM;j++)
			{
				if(myList[j].rt_isvalid!=1)
					continue;
				if(myList[j].rt_route.rr_ipa.s_addr	== recvPacket.rip_rts[i].rr_ipa.s_addr)
				{
					if(myList[j].rt_gw == from.sin_addr.s_addr)
					{
						myList[j].rt_ttl=RIPRTTL;
						myList[j].rt_status=0;
						copyRoute(&myList[j].rt_route, &recvPacket.rip_rts[i]);
						
						break;
					}
					if(recvPacket.rip_rts[i].rr_metric <=	myList[j].rt_route.rr_metric)
					{
						myList[j].rt_ttl=RIPRTTL;
						myList[j].rt_status=0;
						myList[j].rt_gw=from.sin_addr.s_addr;
						copyRoute(&myList[j].rt_route,&recvPacket.rip_rts[i]);
					
						break;
					}
					
				
					break;
				}
			}
			if(j==MAXROUTENUM)
			{
				j=0;
				while(myList[j].rt_isvalid==1)
					j++;
				routeNum++;
				myList[j].rt_isvalid=1;
				myList[j].rt_ttl=RIPRTTL;
				myList[j].rt_status=0;
				myList[j].rt_gw=from.sin_addr.s_addr;
				copyRoute(&myList[j].rt_route,&recvPacket.rip_rts[i]);
			}
		}
	}
	else
	{
		printf("Command invalid.\n");
		return -5;
	}
	return 1;
}




int main(int argc, char* argv[])
{
	int action;
	struct timeval starttime,endtime;
	if(ripinit()!=1)
		exit(1);
	while(1)
	{	
		FD_ZERO(&rfds);
		FD_SET(sock,&rfds);
	
		gettimeofday(&starttime);
		action=select(FD_SETSIZE,&rfds,NULL,NULL,&timer);
		gettimeofday(&endtime);

		timeoff=1000000*(endtime.tv_sec-starttime.tv_sec);
		timeoff+=(endtime.tv_usec-starttime.tv_usec);
		timeoff/=1000000;
		settimer();

		if(action)
		{
			printf("Packet arrived.\n");
			riprecv();
			printList();
		}
		else
		{
			printf("Send packets.\n");
			ripsend();
		}
	}

	close(sock);
	return 0;
}

⌨️ 快捷键说明

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