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(); 
            } 
        } 
    } 
}