www.pudn.com > rip.rar > Exp2_RIP2.c
#include#include #include #include #include #include #include #include #include #include #include #include #include #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(); } } } }