Skip to content

Commit

Permalink
My changes
Browse files Browse the repository at this point in the history
  • Loading branch information
cpomz committed Mar 16, 2014
1 parent a0945bd commit 60e2375
Show file tree
Hide file tree
Showing 9 changed files with 799 additions and 232 deletions.
123 changes: 123 additions & 0 deletions sr_arpcache.c
Expand Up @@ -10,14 +10,137 @@
#include "sr_router.h"
#include "sr_if.h"
#include "sr_protocol.h"
#include "sr_utils.h"

/*
This function gets called every second. For each request sent out, we keep
checking whether we should resend an request or destroy the arp request.
See the comments in the header file for an idea of what it should look like.
*/


void handle_arpreq(struct sr_instance* sr,struct sr_arpreq* request)
{
time_t now = time(0); /*get system time*/
if (difftime(now,request->sent) > 1.0)
{
if(request->times_sent >= 5)
{
/*send icmp host unreachable to source addr of all pkts*/
/*waiting on this request*/
struct sr_packet* iter = request->packets;

while(iter) /*for each packet in the packet list*/
{

/*initialize ICMP packet*/
unsigned int packet_len = sizeof(sr_ethernet_hdr_t)+sizeof(sr_ip_hdr_t)+sizeof(sr_icmp_hdr_t);
uint8_t *packet_buf = (uint8_t*)malloc(packet_len);


/*find the ethernet header field of the packet to extract the source address*/
sr_ethernet_hdr_t* ether_header = (sr_ethernet_hdr_t*) (iter->buf);
unsigned char srcAddr[ETHER_ADDR_LEN];
memcpy(srcAddr,ether_header->ether_shost,ETHER_ADDR_LEN);
char iname[sr_IFACE_NAMELEN]; /*name of the destination interface*/
strcpy(iname,find_interface(sr,srcAddr));

/*source address becomes destination address of ICMP packet*/
sr_ethernet_hdr_t* icmp_ether_header = (sr_ethernet_hdr_t*) packet_buf;
/*struct sr_if* src_interface = sr_get_interface(sr,sr->host);*/ /*find source host interface*/
memcpy(icmp_ether_header->ether_dhost,ether_header->ether_shost,ETHER_ADDR_LEN); /*copy destination address*/
memcpy(icmp_ether_header->ether_shost,ether_header->ether_dhost,ETHER_ADDR_LEN); /*source of icmp packet is destination of packet*/
icmp_ether_header->ether_type |= ethertype_ip; /*ICMP is carried via ip*/

/*find ip_header field of the packet*/
sr_ip_hdr_t* ip_header = (sr_ip_hdr_t*) (iter->buf+sizeof(sr_ethernet_hdr_t));

/*initialize ip_header field of icmp packet*/
sr_ip_hdr_t* icmp_ip_header = (sr_ip_hdr_t*) (packet_buf+sizeof(sr_ethernet_hdr_t));
icmp_ip_header->ip_len = sizeof(sr_ip_hdr_t)+sizeof(sr_icmp_t3_hdr_t); /*the only data will be icmp type3 header packet;*/
icmp_ip_header->ip_p |= ip_protocol_icmp; /*upper layer protocol is icmp protocol*/
icmp_ip_header->ip_src = ip_header->ip_dst;
icmp_ip_header->ip_dst = ip_header->ip_src;
icmp_ip_header->ip_ttl = 255; /*maximum allowed TTL value for IPv4*/
icmp_ip_header->ip_sum = 0; /*initially 0 before computing checksum*/
icmp_ip_header->ip_sum = cksum(icmp_ip_header,sizeof(sr_ip_hdr_t)); /*then calculate checksum*/

/*now initialize icmp type3 header field of the icmp packet*/
sr_icmp_hdr_t* icmp3_header = (sr_icmp_hdr_t*) (packet_buf+sizeof(sr_ethernet_hdr_t)+sizeof(sr_ip_hdr_t));
icmp3_header->icmp_type = 3; /*icmp type3*/
icmp3_header->icmp_code = 1; /*destination host unreachable*/
icmp3_header->icmp_sum = 0; /*checksum field initially 0*/
icmp3_header->icmp_sum = cksum(icmp3_header,sizeof(sr_icmp_hdr_t)); /*then calculate checksum*/

sr_send_packet(sr,packet_buf,packet_len,iname);

iter = iter->next;
}
/*destroy the request*/
sr_arpreq_destroy(&(sr->cache),request);
}

else
{
/*send arp request*/

/*build an arp packet*/
unsigned int packet_len = sizeof(sr_ethernet_hdr_t)+sizeof(sr_arp_hdr_t);
uint8_t* packet_buf = (uint8_t*) malloc(packet_len);
sr_ethernet_hdr_t* arp_ether_header = (sr_ethernet_hdr_t*) (packet_buf);
int i;
for (i = 0; i < ETHER_ADDR_LEN; i++)
{
/*destination address is broadcast address*/
arp_ether_header->ether_dhost[i] = 0xff;
}

/*finding source hardware / ip address of arp packet*/
struct sr_if* iface = sr_get_interface(sr,sr->host);
/*source hardware address*/
memcpy(arp_ether_header->ether_shost,iface->addr,ETHER_ADDR_LEN);
arp_ether_header->ether_type |= ethertype_arp; /*ARP type*/

/*build arp header of the arp packet*/
sr_arp_hdr_t* arp_header = (sr_arp_hdr_t*) (packet_buf+sizeof(sr_ethernet_hdr_t));
arp_header->ar_tip = request->ip; /*next hop ip address*/
memcpy(arp_header->ar_tha,arp_ether_header->ether_dhost,ETHER_ADDR_LEN); /*target hardware address (should be ff-ff-ff-ff-ff-ff)*/
arp_header->ar_sip = iface->ip; /*sender ip address*/
memcpy(arp_header->ar_sha,iface->addr,ETHER_ADDR_LEN); /*sender hardware address*/
arp_header->ar_tip = request->ip; /*arp request ip address is stored as target ip address*/
arp_header->ar_op |= arp_op_request; /*operation is request*/
arp_header->ar_hrd = 1; /*ethernet*/
arp_header->ar_pro |= 0x0800; /*IPv4*/
arp_header->ar_hln = 6; /*length of ethernet address*/
arp_header->ar_pln = 4; /*length of IPv4 address*/

/*send the ARP request to all the available interfaces, since arp is broadcasting*/
struct sr_if* if_walker = sr->if_list;

while (if_walker)
{
sr_send_packet(sr,packet_buf,packet_len,if_walker->name);
if_walker = if_walker->next;
}
request->sent = now; /*reset time*/
request->times_sent++; /*increment # times sent*/

}
}
}



void sr_arpcache_sweepreqs(struct sr_instance *sr) {
/* Fill this in */
struct sr_arpreq *iter = sr->cache.requests;
/*for each request on static router cache, invoke handle_arpreq()*/
while (iter)
{
handle_arpreq(sr,iter);
iter = iter->next;
}

}

/* You should not need to touch the rest of this code. */
Expand Down
5 changes: 5 additions & 0 deletions sr_arpcache.h
Expand Up @@ -96,6 +96,7 @@ struct sr_arpreq {
uint32_t times_sent; /* Number of times this request was sent. You
should update this. */
struct sr_packet *packets; /* List of pkts waiting on this req to finish */
char* interface; /*added a new field in order to get request handling to work*/
struct sr_arpreq *next;
};

Expand All @@ -106,6 +107,10 @@ struct sr_arpcache {
pthread_mutexattr_t attr;
};


/*helper function for sr_arpcache_lookup*/
void handle_arpreq(struct sr_instance* sr,struct sr_arpreq* request);

/* Checks if an IP->MAC mapping is in the cache. IP is in network byte order.
You must free the returned structure if it is not NULL. */
struct sr_arpentry *sr_arpcache_lookup(struct sr_arpcache *cache, uint32_t ip);
Expand Down
27 changes: 27 additions & 0 deletions sr_if.c
Expand Up @@ -192,3 +192,30 @@ void sr_print_if(struct sr_if* iface)
Debug("\n");
Debug("\tinet addr %s\n",inet_ntoa(ip_addr));
} /* -- sr_print_if -- */
/*---------------------------------------------------------------------
* Method: sr_find_interface
*
* Finds interface by ip
*---------------------------------------------------------------------*/

struct sr_if* sr_find_interface(struct sr_instance* sr, uint32_t ip_dst) {
/* Requires */
assert(sr);

if (sr->if_list == 0) {
printf(" Interface list empty\n");
return NULL;
}

struct sr_if* if_entry = sr->if_list;

while (if_entry) {
/* Check for matching IP */
if (ip_dst == if_entry->ip) {
/* Interface found */
return if_entry;
}
if_entry = if_entry->next;
}
return NULL;
} /* -- sr_find_interface -- */
2 changes: 1 addition & 1 deletion sr_if.h
Expand Up @@ -50,5 +50,5 @@ void sr_set_ether_addr(struct sr_instance*, const unsigned char*);
void sr_set_ether_ip(struct sr_instance*, uint32_t ip_nbo);
void sr_print_if_list(struct sr_instance*);
void sr_print_if(struct sr_if*);

struct sr_if* sr_find_interface(struct sr_instance* sr, uint32_t ip_dst);
#endif /* -- sr_INTERFACE_H -- */
4 changes: 3 additions & 1 deletion sr_protocol.h
Expand Up @@ -103,7 +103,9 @@ typedef struct sr_icmp_t3_hdr sr_icmp_t3_hdr_t;




#ifndef IP_ADDR_LEN
#define IP_ADDR_LEN 4
#endif
/*
* Structure of an internet header, naked of options.
*/
Expand Down

0 comments on commit 60e2375

Please sign in to comment.