📄 exp2_rip2.c
字号:
#include<sys/ipc.h>
#include<sys/shm.h>
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<sys/ioctl.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<net/if.h>
#include<time.h>
#include<unistd.h>
#include<signal.h>
#define KEY 1234
#define SIZE 1024
#define PORT 520
#define INIT_TIMER 5
#define SELECT_TIMER 3
#define TIMEOUT 10
#define MAX_NUM 50
typedef enum{NOTHING,REQUEST,RESPONSE} Command_Type;
struct ROUTE_ENTRY
{
unsigned short addrFamilyId; // Address Family Identifier(2)
unsigned short beZero1; // Must Be Zero(2)
struct in_addr ipv4Addr; // IPv4 Address(4)
unsigned int beZero2; // Must Be Zero(4)
unsigned int beZero3; // Must Be Zero(4)
unsigned int metric; // Metric(4)
};
struct RIP_PACKET
{
unsigned char command; // Command(1)
unsigned char version; // Version(1)
unsigned short beZero; // Must Be Zero(2)
struct ROUTE_ENTRY routeEntry[25]; // Route Entries(20*25)
}recvPacket,reqPacket,resPacket;
struct RIP_PACKET routePacket;
struct ROUTE_TABLE
{
struct ROUTE_ENTRY routeInfo;
int isvalid; // 1-valid 0-not valid
long timer;
int statue;
struct in_addr sourceIPAddr;
}routeTable[MAX_NUM];
fd_set fdSet; // file descriptor set
struct timeval timer;
int sock;
int routeNum;
struct sockaddr_in localSockAddr,sendSockAddr,recvSockAddr;
struct in_addr localIP;
/////////////////////////////////////////////////////////////////////////////////
int GetLocalIP()
{
int fd;
struct ifreq ifr;
if((fd=socket(AF_INET, SOCK_DGRAM, 0))==-1)
{
close(fd);
return -1;
}
strcpy(ifr.ifr_name, "eth0");
if(ioctl(fd,SIOCGIFADDR,&ifr))
{
close(fd);
return -1;
}
memcpy(&localSockAddr,&ifr.ifr_addr,sizeof(struct sockaddr_in));
localIP = localSockAddr.sin_addr;
printf("local IP is %s\n",inet_ntoa(localIP));
return 1;
}
void PrintEntry(struct ROUTE_ENTRY* entry)
{
printf("Address Family Identifier: %d\n",entry->addrFamilyId);
printf("IPv4 Address: %s\n",inet_ntoa(entry->ipv4Addr));
printf("Metric: %d\n",entry->metric);
printf("\n");
}
void PrintTable()
{
int i;
printf("IP\t\t AddrFamilyId\t metric timeout sourceIP\n");
for(i = 0; i < MAX_NUM; i++)
{
if(routeTable[i].isvalid == 1)
{
// PrintEntry(&routeTable[i].routeInfo);
printf("%s",inet_ntoa(routeTable[i].routeInfo.ipv4Addr));
printf("\t %d",ntohs(routeTable[i].routeInfo.addrFamilyId));
printf("\t\t %d",ntohl(routeTable[i].routeInfo.metric));
printf("\t %d",routeTable[i].timer);
printf(" %s\n",inet_ntoa(routeTable[i].sourceIPAddr));
}
}
printf("\n");
}
void SetRouteEntry(struct ROUTE_ENTRY* routeEntry, const char* ip,
unsigned short afid, unsigned int metric )
{
routeEntry->addrFamilyId = htons(afid);
routeEntry->metric = htonl(metric);
inet_aton(ip,&routeEntry->ipv4Addr);
routeEntry->beZero1 = 0;
routeEntry->beZero2 = 0;
routeEntry->beZero3 = 0;
}
void SetRoutePacket(struct RIP_PACKET* routePacket,Command_Type ct)
{
routePacket->command = (int)ct;
routePacket->version = 1;
routePacket->beZero = 0;
}
void EntryInit()
{
FILE* file;
char ip[16];
int afi,metric;
file = fopen("1.txt","r");
if(file == NULL)
{
printf("cannot open file.\n");
return;
}
while(fscanf(file,"%s %d %d \n",&ip,&afi,&metric)!=EOF)
{
SetRouteEntry(&routeTable[routeNum].routeInfo,(const char*)ip,afi,metric);
routeTable[routeNum].timer = TIMEOUT;
routeTable[routeNum].isvalid = 1;
routeTable[routeNum].statue = 0;
routeNum++;
}
fclose(file);
return;
}
void RouteInit()
{
int i,optval=0,length,error;
routeNum = 0;
// init local socket address and ip address
GetLocalIP();
// init route table items
for(i = 0; i < MAX_NUM; i++)
{
SetRouteEntry(&routeTable[i].routeInfo,"0.0.0.0",0,0);
routeTable[i].isvalid = 0;
routeTable[i].timer = 0;
routeTable[i].statue = 0;
inet_aton("0,0,0,0",&routeTable[i].sourceIPAddr);
}
// init request packet
SetRoutePacket(&reqPacket,REQUEST);
SetRouteEntry(&reqPacket.routeEntry[0],"0.0.0.0",0,16);
// init response packet
SetRoutePacket(&resPacket,RESPONSE);
recvSockAddr.sin_family = AF_INET;
recvSockAddr.sin_port = htons(PORT);
recvSockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
sendSockAddr.sin_family = AF_INET;
sendSockAddr.sin_port = htons(PORT);
// inet_aton("240.255.255.255",&sendSockAddr.sin_addr);
sendSockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
EntryInit();
sock = socket(AF_INET,SOCK_DGRAM,0);
if(sock<0)
{
printf("cannot create a socket!\n");
exit(1);
}
if(setsockopt(sock,SOL_SOCKET,SO_BROADCAST,&optval,sizeof(int)) != 0)
{
printf("cannot broadcast!\n");
close(sock);
exit(1);
}
if(bind(sock,(struct sockaddr*)&recvSockAddr,sizeof(recvSockAddr))<0)
{
printf("cannot bind to port\n");
close(sock);
exit(1);
}
length=sizeof recvSockAddr;
getsockname(sock,(struct sockaddr*)&recvSockAddr,&length);
printf("Port %d is opened. Listen for packet...\n",ntohs(recvSockAddr.sin_port));
FD_ZERO(&fdSet);
FD_SET(sock,&fdSet);
error = sendto(sock,&reqPacket,4+sizeof(struct ROUTE_ENTRY),0,(struct sockaddr*)(&sendSockAddr),sizeof(struct sockaddr));
if(error<0)
{
PrintEntry(&reqPacket.routeEntry[0]);
printf("broadcast request packet failed! %d,%d,%d\n",error,sock,fdSet);
}
}
void CheckTimer()
{
int i;
for(i = 0; i < MAX_NUM; i++)
{
if(routeTable[i].isvalid == 1 && routeTable[i].statue == 0)
{
routeTable[i].timer--;
if(routeTable[i].timer == 0)
routeTable[i].statue = 1;
}
else continue;
}
}
void Handler()
{
int i=0,j=0;
printf("Timeout for waiting, now broadcast route information!\n");
check_info:
for(j=0;i < MAX_NUM; i++)
{
if(routeTable[i].isvalid == 1 && routeTable[i].statue == 0)
{
memcpy(&resPacket.routeEntry[j],&routeTable[i].routeInfo,sizeof(struct ROUTE_ENTRY));
j++;
}
if(j == 25)
break;
}
if(j == 0)
{
printf("None information to broadcast.\n");
return;
}
// inet_aton("255.255.255.255",&sendSockAddr.sin_addr);
// sendSockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
sendSockAddr.sin_addr.s_addr = localSockAddr.sin_addr.s_addr;
if(sendto(sock,&resPacket,4+j*sizeof(struct ROUTE_ENTRY),0,(struct sockaddr*)(&sendSockAddr),sizeof(sendSockAddr))<0)
{
printf("broadcast request packet failed!-----%d\n",j);
return;
}
else
{
printf("broadcast %d routeInfo.\n",j);
// int k;
// for(k = 0; k < j; k++)
// PrintEntry(&resPacket+4+20*k);
}
if(j == 25) goto check_info;
return;
}
int DealRecvPacket()
{
int length,i,j,metric;
int addr_len;
addr_len = sizeof(struct sockaddr_in);
length=recvfrom(sock,&recvPacket,sizeof(recvPacket),0,(struct sockaddr*)&recvSockAddr,&addr_len);
printf("receive a packet size of %d from %s......\n",length,inet_ntoa(recvSockAddr.sin_addr));
if(recvSockAddr.sin_addr.s_addr == localIP.s_addr)
return 1;
if((length-4)%sizeof(struct ROUTE_ENTRY) != 0)
return 2;
if(recvPacket.version != 1 || recvPacket.beZero != 0)
return 3;
struct in_addr local;
inet_aton("127.0.0.1",&local);
if(recvSockAddr.sin_addr.s_addr == local.s_addr)
return 4;
if(recvPacket.command == REQUEST)
{
printf("request packet received.\n");
////////////////////////////////////////////////////////////////////////////////
printf("now send route information as response.\n");
i = 0;
check_info:
for(j=0;i < MAX_NUM; i++)
{
if(routeTable[i].isvalid == 1 && routeTable[i].statue == 0)
{
memcpy(&resPacket.routeEntry[j],&routeTable[i].routeInfo,sizeof(struct ROUTE_ENTRY));
j++;
}
if(j == 25)
break;
}
if(j == 0)
{
printf("None information to broadcast.\n");
return 5;
}
//inet_aton("255.255.255.255",&sendSockAddr.sin_addr);
sendSockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
//sendSockAddr.sin_addr.s_addr = recvSockAddr.sin_addr.s_addr;
if(sendto(sock,&resPacket,4+j*sizeof(struct ROUTE_ENTRY),0,(struct sockaddr*)(&sendSockAddr),sizeof(sendSockAddr))<0)
{
printf("send request packet failed!\n");
return 6;
}
printf("broadcast %d routeInfo.\n",j);
if(j == 25) goto check_info;
////////////////////////////////////////////////////////////////////////////////
}
else if(recvPacket.command == RESPONSE)
{
printf("response packet received.\n");
for(i = 0; i < (length-4)/sizeof(struct ROUTE_ENTRY); i++)
{
metric = ntohl(recvPacket.routeEntry[i].metric);
metric++;
if(metric>=16)continue;
recvPacket.routeEntry[i].metric = htonl(metric);
for(j = 0; j < MAX_NUM; j++)
{
if(routeTable[j].isvalid != 1)continue;
if(routeTable[j].routeInfo.ipv4Addr.s_addr==
recvPacket.routeEntry[i].ipv4Addr.s_addr)
{
if(routeTable[j].sourceIPAddr.s_addr==
recvSockAddr.sin_addr.s_addr)
{
routeTable[j].timer = TIMEOUT;
routeTable[j].statue = 0;
routeTable[j].isvalid = 1;
memcpy(&routeTable[j].routeInfo,&recvPacket.routeEntry[i],sizeof(struct ROUTE_ENTRY));
printf("modify old routeEntry.\n");
break;
}
if(routeTable[j].routeInfo.metric < recvPacket.routeEntry[i].metric)
{
routeTable[j].timer = TIMEOUT;
routeTable[j].statue = 0;
routeTable[j].isvalid = 1;
routeTable[j].sourceIPAddr.s_addr = recvSockAddr.sin_addr.s_addr;
memcpy(&routeTable[j].routeInfo,&recvPacket.routeEntry[i],sizeof(struct ROUTE_ENTRY));
printf("modify new metric and sourceIP.\n");
break;
}
printf("nothing to be modified.\n");
break;
}
}
// add new routeEntry
if(j == MAX_NUM)
{
j=0;
while(routeTable[j].isvalid == 1)
j++;
routeNum++;
routeTable[j].isvalid = 1;
routeTable[j].timer = TIMEOUT;
routeTable[j].statue = 0;
routeTable[j].sourceIPAddr.s_addr = recvSockAddr.sin_addr.s_addr;
memcpy(&routeTable[j].routeInfo,&recvPacket.routeEntry[i],sizeof(struct ROUTE_ENTRY));
printf("add a new routeEntry.\n");
}
}
}
else
{
printf("command invalid.\n");
return 7;
}
PrintTable();
printf(" the number of route entry is %d.\n",routeNum);
return 0;
}
main()
{
int temp,shmid;
int* shmNum;
int signalNum;
struct shmid_ds buf;
RouteInit();
shmid = shmget(KEY,SIZE,IPC_CREAT | 0600);
shmNum = (int*)shmat(shmid,NULL,0);
*shmNum = 0;
signalNum = 0;
shmdt(shmNum);
if(fork() == 0)
{
while(1)
{
//signal(SIGALRM,Handler);
temp = (int)(drand48()*10);
sleep(temp+INIT_TIMER);
// sleep(10);
//alarm(INIT_TIMER);
//pause();
shmNum = (int*)shmat(shmid,NULL,0);
// printf("........%d\n",*((int*)shmat(shmid,NULL,0)));
(int)*(shmNum) = (int)*(shmNum) + 1;
shmdt(shmNum);
//CheckTimer();
}
}
else
{
timer.tv_sec=SELECT_TIMER;
timer.tv_usec=0;
while(1)
{
FD_ZERO(&fdSet); // clears a file descriptor set
FD_SET(sock,&fdSet); // adds fd to the set
if(select(sock+1,&fdSet,NULL,NULL,&timer)<0) // ignore writefds and exceptfds
{
printf("cannot select readfds!\n");
}
if (FD_ISSET(sock, &fdSet))
{
//printf("receive a route packet.\n");
printf("deal type: -------- %d -------\n",DealRecvPacket());
}
sleep(1);
shmctl(shmid,IPC_STAT,&buf);
shmNum = (int*)shmat(shmid,NULL,0);
if(signalNum != *(shmNum))
{
signalNum = *(shmNum);
CheckTimer();
Handler();
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -