www.pudn.com > myrip.rar > myrip.cpp
#include "myrip.h"
void rp_inverse_ntoh()
{
void * tempptr = & current_rip_packet.command;
unsigned short * temp = (unsigned short *)( tempptr );
*temp = ntohs(* temp);
for(int i=0; i < current_rip_count; i++)
{
current_rip_packet.rip_entries[i].metric = ntohl(current_rip_packet.rip_entries[i].metric);
}
}
void rp_inverse_hton()
{
void * tempptr = & current_rip_packet.command;
unsigned short * temp = (unsigned short *)( tempptr );
//unsigned short * temp = (unsigned short *)( & current_rip_packet);
*temp = htons(* temp);
//current_rip_packet.version = htons(current_rip_packet.version);
for(int i=0; i < current_rip_count; i++)
{
current_rip_packet.rip_entries[i].metric = htonl(current_rip_packet.rip_entries[i].metric);
}
}
void print_routing_table()
{
char buf[INET_ADDRSTRLEN];
size_t buf_len = sizeof(buf);
const char* buf_ptr;
printf("--------current routing table----------------\n");
for (int i = 0; i < current_route_count; i++)
{
printf("%dth re:\n", i);
buf_ptr = inet_ntop(AF_INET, &routing_table[i].dest, buf, buf_len);
printf("destination: %s ", buf);
buf_ptr = inet_ntop(AF_INET, &routing_table[i].dest, buf, buf_len);
printf("next: %s ", buf);
printf("metric: %d\n\n", routing_table[i].metric);
}
printf("---------------------------------------------\n");
}
void print_message(const char* title, const char* content)
{
printf("\n----------- %s ---------------\n", title);
printf("- %s -\n", content);
printf("---------- end of message -----------\n");
}
void print_rip_packet()
{
printf("----------rip packet contains %d entries: -------------\n", current_rip_count);
printf("command: %s ",((current_rip_packet.command == RIP_RESPONSE)?"RESPONSE":"REQUEST"));
printf("version: %d\n",current_rip_packet.version);
for(int i = 0; i < current_rip_count; i++)
{
printf("entry %d: ",i);
printf("ip: %s ",inet_ntoa(current_rip_packet.rip_entries[i].ip));
printf("metric: %d\n",current_rip_packet.rip_entries[i].metric);
}
printf("--------------------------------------------------------\n");
}
int check_rip_packet()
{
if (current_rip_packet.version == 2)
return RIP_CHECK_OK;
if (current_rip_packet.version == 0)
return RIP_CHECK_FAIL;
//check mbz
if (current_rip_packet.zero)
return RIP_CHECK_FAIL;
for (int i = 0; i < current_rip_count; i++)
{
if (current_rip_packet.rip_entries[i].zero1 ||
current_rip_packet.rip_entries[i].zero2 ||
current_rip_packet.rip_entries[i].zero3)
{
return RIP_CHECK_FAIL;
}
return RIP_CHECK_OK;
}
}
int calculate_rip_metric(int rip_entry_number)
{
if (current_rip_packet.rip_entries[rip_entry_number].metric + 1 > RIP_INFINITY)
return RIP_INFINITY;
return current_rip_packet.rip_entries[rip_entry_number].metric + 1;
}
void reset_rip_packet(int command)
{
current_rip_count = 0;
current_rip_packet.command = command;
current_rip_packet.version = 1;
current_rip_packet.zero = 0;
for (int i = 0; i < RIP_MAX_ENTRY; i++)
{
current_rip_packet.rip_entries[0].family = 2;
current_rip_packet.rip_entries[0].zero1 = 0;
current_rip_packet.rip_entries[0].ip.s_addr = 0;
current_rip_packet.rip_entries[0].zero2 = 0;
current_rip_packet.rip_entries[0].zero3 = 0;
current_rip_packet.rip_entries[0].metric = 0;
}
}
void reset_routing_table()
{
current_route_count = 0;
for (int i = 0; i < ROUTE_MAX_ENTRY; i++)
{
routing_table[i].dest.s_addr = 0;
routing_table[i].next.s_addr = 0;
routing_table[i].metric = 0;
routing_table[i].valid = 1;
routing_table[i].timer = 0;
routing_table[i].flag = 0;
}
}
void init_routing_table()
{
reset_routing_table();
for (int i = 0; i < LOCAL_ROUTE_ENTRY; i++)
{
if (inet_pton(AF_INET, local_ip[i], &(routing_table[i].dest)) <= 0)
{
printf("inet_pton error\n");
}
if (inet_pton(AF_INET, local_ip[i], &(routing_table[i].next)) <= 0)
{
printf("inet_pton error\n");
}
routing_table[i].metric = 1;
routing_table[i].timer = time(NULL);
routing_table[i].valid = ROUTE_VALID;
routing_table[i].flag = 0;
}
current_route_count = LOCAL_ROUTE_ENTRY;
}
void get_local_ip()
{
char ac[80];
if (gethostname(ac, sizeof(ac)) == -1) {
// cerr << "Error " << WSAGetLastError() <<
// " when getting local host name." << endl;
return ;
}
printf("Host name is %s, ", ac);
struct hostent *phe = gethostbyname(ac);
if (phe == 0) {
//cerr << "Yow! Bad host lookup." << endl;
return ;
}
for (int i = 0; phe->h_addr_list[i] != 0; ++i) {
local_addr;
memcpy(&local_addr, phe->h_addr_list[i], sizeof(struct in_addr));
printf("Address %d: %s \n=======================================\n",i, inet_ntoa(local_addr));
}
}
void init_all()
{
get_local_ip();
reset_rip_packet(RIP_RESPONSE);
init_routing_table();
}
void gen_request_all()
{
current_rip_count = 1;
current_rip_packet.command = RIP_REQUEST;
current_rip_packet.version = 1;
current_rip_packet.zero = 0;
current_rip_packet.rip_entries[0].family = 0;
current_rip_packet.rip_entries[0].zero1 = 0;
current_rip_packet.rip_entries[0].ip.s_addr = 0;
current_rip_packet.rip_entries[0].zero2 = 0;
current_rip_packet.rip_entries[0].zero3 = 0;
current_rip_packet.rip_entries[0].metric = RIP_INFINITY;
}
void send_rip_packet_to(struct in_addr &dest_ip)
{
printf("begin sending rip packet:\n");
print_rip_packet();
rp_inverse_hton();
struct sockaddr_in addr;
int addr_len = sizeof(sockaddr_in);
bzero(&addr, addr_len);
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(dest_ip.s_addr);
//addr.sin_port = htons(RIP_PORT);
addr.sin_port = htons(RIP_PORT);
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
int val = 1;
//bind(sockfd, (struct sockaddr*)&addr, sizeof(addr));
setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &val, sizeof(val));
// reverseMessage();
if (sendto(sockfd, ¤t_rip_packet, RIP_PACKET_HEAD+
current_rip_count*sizeof(rip_entry)
, 0,
(const struct sockaddr*)&addr, addr_len) < 0)
printf("sent green in send_rip_packet_to\n");
close(sockfd);
return;
}
void broadcast_rip_packet()
{
printf("begin broadcasting rip packet:\n");
print_rip_packet();
rp_inverse_hton();
struct sockaddr_in addr;
int addr_len = sizeof(struct sockaddr_in);
bzero(&addr, addr_len);
addr.sin_family = AF_INET;
//inet_aton("59.66.132.170", &addr.sin_addr);
addr.sin_addr.s_addr = htonl(INADDR_BROADCAST);
//addr.sin_addr.s_addr=htonl(addr.sin_addr.s_addr);
addr.sin_port = htons(520);
//printf("sending rip packet...\n");
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
int val = 1;
//bind(sockfd, (struct sockaddr*)&addr, sizeof(addr));
setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &val, sizeof(val));
if (sendto(sockfd, ¤t_rip_packet,
RIP_PACKET_HEAD+current_rip_count*sizeof(rip_entry),
//sizeof(current_rip_packet),
0, (struct sockaddr*)&addr, addr_len) < 0)
{
printf("broadcast error in broadcast_rip_packet\n");
}
close(sockfd);
return;
}
void receive_rip_packet()
{
struct sockaddr_in addr;
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
{
printf("open socket error in start_rip_daemon\n");
exit(-1);
}
bzero(&addr, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(RIP_PORT);
if(bind(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0)
{
printf("bind error in start_rip\n");
exit(-1);
}
//struct sockaddr_in addr;
int addr_len = sizeof(sockaddr_in);
int packet_len = 0;
packet_len = recvfrom(sockfd, ¤t_rip_packet, RIP_PACKET_HEAD + RIP_MAX_PACKET, 0,
(struct sockaddr*)&addr, (socklen_t*)&addr_len);
if (packet_len < 0)
{
printf("rip packet bad!!!\n");
return;
}
current_rip_count = (packet_len - RIP_PACKET_HEAD) / sizeof(rip_entry);
//--------------inverse
rp_inverse_ntoh();
//--------------end inverse
struct in_addr source_addr;
source_addr.s_addr = addr.sin_addr.s_addr;
//char * temptemp="000.000.000.000";
//inet_ntop(AF_INET, &source_addr.s_addr, temptemp, sizeof(temptemp));
//printf("-----------%s\n",inet_ntoa(source_addr));
if((source_addr.s_addr != local_addr.s_addr))
{
printf("packet received from %s\n", inet_ntoa(source_addr));
print_rip_packet();
if ((check_rip_packet() == RIP_CHECK_OK))
{
pthread_mutex_lock(&rt_mutex);
switch(current_rip_packet.command)
{
case RIP_REQUEST:
handle_request(source_addr);
break;
case RIP_RESPONSE:
handle_response(source_addr);
break;
default:
break;
}
pthread_mutex_unlock(&rt_mutex);
}
else
{
print_message("error:", "packet check error");
}
}
}
void handle_request(struct in_addr &source_ip)
{
if (current_route_count <= 0)
{
print_message("warnning:", "the route table is empty");
return;
}
// reset_rip_packet(RIP_RESPONSE);
//request for the whole route_table
if (current_rip_count == 1 &&
current_rip_packet.rip_entries[0].family == 0 &&
current_rip_packet.rip_entries[0].metric == 16)
{
int route_iterator = 0;
int sended_route_entry = 0;
for(sended_route_entry = 0;
sended_route_entry < current_route_count;
sended_route_entry += RIP_MAX_ENTRY)
{
reset_rip_packet(RIP_RESPONSE);
current_rip_count = 0;
while((route_iterator < current_route_count)&&(current_rip_count < RIP_MAX_ENTRY))
{
//printf("test!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
if (routing_table[route_iterator].dest.s_addr != source_ip.s_addr &&
routing_table[route_iterator].next.s_addr != source_ip.s_addr &&
routing_table[route_iterator].valid)
{
current_rip_packet.rip_entries[current_rip_count].ip.s_addr
= routing_table[route_iterator].dest.s_addr;
current_rip_packet.rip_entries[current_rip_count].metric
= routing_table[route_iterator].metric;
current_rip_count++;
}
route_iterator++;
}
current_rip_packet.command = RIP_RESPONSE;
printf("respond to request----------------------------------\n");
send_rip_packet_to(source_ip);
// printf("----------------------------------------------------\n");
}
return;
}
//request for certain route entry
for (int i = 0; i < current_rip_count; i++)
{
int j;
for (j = 0; j < current_route_count; j++)
{
if (routing_table[j].dest.s_addr == current_rip_packet.rip_entries[i].ip.s_addr &&
routing_table[j].valid)
{
current_rip_packet.rip_entries[current_rip_count].ip.s_addr
= routing_table[j].dest.s_addr;
current_rip_packet.rip_entries[current_rip_count].metric
= routing_table[j].metric;
//current_rip_count++;
break;
}
}
if(j == current_rip_count)
{
current_rip_packet.rip_entries[i].metric
= RIP_INFINITY;
}
}
current_rip_packet.command = RIP_RESPONSE;
//send_rip_packet_to(source_ip);
printf("respond to request----------------------------------\n");
send_rip_packet_to(source_ip);
// printf("----------------------------------------------------\n");
return;
}
void handle_response(struct in_addr &source_ip)
{
int route_exist = 0;
int old_route_count = current_route_count;
for (int i = 0; i < current_rip_count; i++)
{
route_exist = 0;
for (int j = 0; j < old_route_count; j++)
{
if (routing_table[j].dest.s_addr == current_rip_packet.rip_entries[i].ip.s_addr)
{
route_exist = 1;
if((routing_table[j].next.s_addr == current_rip_packet.rip_entries[i].ip.s_addr)
||(routing_table[j].metric > calculate_rip_metric(i)))
{
routing_table[j].next.s_addr = source_ip.s_addr;
routing_table[j].metric = calculate_rip_metric(i);
}
routing_table[j].timer = time(NULL);
routing_table[j].valid = 1;
routing_table[j].flag = 1;///to be trigger...
break;
}
}
if (route_exist == 0 && calculate_rip_metric(i) != RIP_INFINITY)
{
routing_table[current_route_count].dest.s_addr = current_rip_packet.rip_entries[i].ip.s_addr;
routing_table[current_route_count].next.s_addr = source_ip.s_addr;
routing_table[current_route_count].metric = calculate_rip_metric(i);
routing_table[current_route_count].timer = time(NULL);
routing_table[current_route_count].valid = 1;
routing_table[current_route_count].flag = 1;//to be trigger...
current_route_count++;
}
}
current_rip_count = 0;
reset_rip_packet(RIP_RESPONSE);
for (int n = 0; n < current_route_count; n++)
{
if( routing_table[n].flag == 1 )
{
current_rip_packet.rip_entries[current_rip_count].ip.s_addr
= routing_table[n].dest.s_addr;
current_rip_packet.rip_entries[current_rip_count].metric
= routing_table[n].metric;
current_rip_count++;
current_rip_packet.command = RIP_RESPONSE;
routing_table[n].flag = 0;
}
}
printf("update routing table caused by respond--------------\n");
send_rip_packet_to(source_ip);
// printf("----------------------------------------------------\n");
//send_rip_packet_to(source_ip);
}
void * timer_routine(void *)
{
int broadcasted_rip_count;
time_t time_prev;
time_t time_after;
time_prev = time(NULL);
while(1)
{
sleep(5);
time_after = time(NULL);
pthread_mutex_lock(&rt_mutex);
update_routing_table();
pthread_mutex_unlock(&rt_mutex);
if ((time_after - time_prev) >= (time_t)BROADCAST_INTERVAL )
{
printf("begin broadcasting...\n");
//pthread_mutex_lock(&crp_mutex);
current_rip_packet.command = RIP_RESPONSE;
current_rip_packet.version = 1;
broadcasted_rip_count = 0;
for(broadcasted_rip_count = 0;
broadcasted_rip_count < current_route_count;
broadcasted_rip_count += RIP_MAX_ENTRY)
{
reset_rip_packet(RIP_RESPONSE);
current_rip_count = 0;
for (int i = 0; (i < current_route_count)&&(i < RIP_MAX_ENTRY); i++)
{
current_rip_packet.rip_entries[current_rip_count].ip
= routing_table[i].dest;
current_rip_packet.rip_entries[current_rip_count].metric
= routing_table[i].metric;
current_rip_count++;
}
broadcast_rip_packet();
//pthread_mutex_unlock(&crp_mutex);
//printf("broadcast 25 rip packets...\n");
}
printf("broadcast green...\n");
time_prev = time(NULL);
}
}
}
void start_rip_daemon()
{
pthread_t timer_thread;
gen_request_all();
broadcast_rip_packet();
printf("broadcast over in start_rip\n");
//print_route_table();
pthread_create(&timer_thread,NULL,timer_routine,NULL);
while(1)
{
printf("begin receiving...\n");
//pthread_mutex_lock(&crp_mutex);
receive_rip_packet();
//pthread_mutex_unlock(&crp_mutex);
printf("receive green...\n");
close(sockfd);
}
pthread_join(timer_thread, NULL);
}
void update_routing_table()
{
time_t time_after = time(NULL);
int old_pos = 0, new_pos=0;
int old_route_count = current_route_count;
//old_pos rember the ending of block that should be removed from routing table
//new_pos remver the beginning of block that should be removed frome routing table
int count;//number of entries in the block that should stay in routing table
int update = 0;
while(old_pos < current_route_count)
{
count = 0;
while((time_after-routing_table[old_pos+count].timer) < (time_t)GARBAGE_REMOVE_TIMEOUT
&& old_pos+count < current_route_count)
{
//need to be set to invalid
if (routing_table[old_pos+count].valid &&
(time_after-routing_table[old_pos+count].timer) >= (time_t)CLOCK_TIMEOUT)
{
routing_table[old_pos+count].valid = 0;
update++;
}
count++;
}
if (old_pos+count < current_route_count && old_pos != new_pos)
{
//need to remove bad entries from routing table
for (int i=0; i < count; i++)
{
routing_table[new_pos+i].dest.s_addr = routing_table[old_pos+i].dest.s_addr;
routing_table[new_pos+i].next.s_addr = routing_table[old_pos+i].next.s_addr;
routing_table[new_pos+i].metric = routing_table[old_pos+i].metric;
routing_table[new_pos+i].timer = routing_table[old_pos+i].timer;
routing_table[new_pos+i].valid = routing_table[old_pos+i].valid;
routing_table[new_pos+i].flag = routing_table[old_pos+i].flag;
}
}
new_pos += count;
old_pos += count;
while((time_after-routing_table[old_pos+count].timer) >= (time_t)GARBAGE_REMOVE_TIMEOUT
&& old_pos < current_route_count)
old_pos ++;
}
current_route_count = new_pos;
if (old_route_count != new_pos || update > 0)
{
printf("--- Route Table Updated ---\n");
print_routing_table();
}
}
int main()
{
init_all();
printf("init green\n");
start_rip_daemon();
return 0;
}