void cli_ip_arp_add(router_state *rs, cli_request *req) { char *ip_str; unsigned char mac[ETH_ADDR_LEN]; unsigned int mac_int[ETH_ADDR_LEN]; if (sscanf(req->command, "ip arp add %as %2X:%2X:%2X:%2X:%2X:%2X", &ip_str, mac_int, (mac_int+1), (mac_int+2), (mac_int+3), (mac_int+4), (mac_int+5)) != 7) { send_to_socket(req->sockfd, "Failure reading arguments.\n", strlen("Failure reading arguments.\n")); return; } int i; for (i = 0; i < 6; ++i) { mac[i] = (unsigned char)mac_int[i]; } struct in_addr ip; if (inet_pton(AF_INET, ip_str, &ip) != 1) { send_to_socket(req->sockfd, "Failure reading ip.\n", strlen("Failure reading ip.\n")); return; } lock_arp_cache_wr(rs); int result = update_arp_cache(rs->sr, &ip, mac, 1); unlock_arp_cache(rs); char* message; if (result != 0) { message = "Failure adding arp cache entry.\n"; } else { message = "Successfully added arp cache entry.\n"; } send_to_socket(req->sockfd, message, strlen(message)); free(ip_str); }
void process_arp_reply( struct sr_instance *sr, const uint8_t *packet, unsigned int len, const char *interface) { assert(sr); assert(packet); assert(interface); router_state *rs = get_router_state(sr); /* update the arp cache */ arp_hdr *arp = get_arp_hdr(packet, len); lock_arp_cache_wr(rs); update_arp_cache(sr, &(arp->arp_sip), arp->arp_sha, 0); unlock_arp_cache(rs); lock_arp_cache_rd(rs); lock_arp_queue_wr(rs); send_queued_packets(sr, &(arp->arp_sip), arp->arp_sha); unlock_arp_queue(rs); unlock_arp_cache(rs); }
// public function definitions void *arpd(void *threadarg) { assert(threadarg); struct thread_context *context; struct thread_context *contexts; struct arpd_data *data; struct in_addr *my_addr; int rv; struct transaction *transaction = NULL; struct ethernet_pkt *etherpkt; struct arp_pkt *arp; struct netmap_ring *rxring; void *ring_idx; uint32_t dispatcher_idx; struct msg_hdr *msg_hdr; context = (struct thread_context *)threadarg; contexts = context->shared->contexts; data = context->data; rxring = data->rxring; dispatcher_idx = context->shared->dispatcher_idx; my_addr = &context->shared->inet_info->addr; rv = arpd_init(context); if (!rv) { pthread_exit(NULL); } printf("arpd[%d]: initialized\n", context->thread_id); // signal to main() that we are initialized atomic_store_explicit(&context->initialized, 1, memory_order_release); // main event loop for (;;) { // read all the incoming packets while (tqueue_remove(context->pkt_recv_q, &transaction, &ring_idx) > 0) { etherpkt = (struct ethernet_pkt *) NETMAP_BUF(rxring, rxring->slot[(uint32_t)ring_idx].buf_idx); arp = (struct arp_pkt*) etherpkt->data; if (!arp_is_valid(arp)) { send_msg_transaction_update_single(&contexts[dispatcher_idx], (uint32_t)ring_idx); continue; } if (arp->arp_h.ar_op == ARP_OP_REQUEST) { if (arp->tpa.s_addr != my_addr->s_addr) { send_msg_transaction_update_single(&contexts[dispatcher_idx], (uint32_t) ring_idx); continue; } printf("R)"); arp_print_line(arp); // send_pkt_arp_reply could fail when xmit queue is full, // however, the sender should just resend a request send_pkt_arp_reply(context->pkt_xmit_q, &arp->spa, &arp->sha); } else { // ARP_OP_REPLY if (!arp_reply_filter(arp, my_addr)) { send_msg_transaction_update_single(&contexts[dispatcher_idx], (uint32_t) ring_idx); continue; } printf("R)"); arp_print_line(arp); // TODO: also check against a list of my outstanding arp requests // prior to insertion in the arp cache recv_pkt_arp_reply(arp, data->arp_cache, contexts); } send_msg_transaction_update_single(&contexts[dispatcher_idx], (uint32_t) ring_idx); } // while (packets) // resend outstanding requests and refresh expiring entries update_arp_cache(data->arp_cache, contexts, context->pkt_xmit_q); // TODO: read all the messages rv = squeue_enter(context->msg_q, 1); if (!rv) continue; while ((msg_hdr = squeue_get_next_pop_slot(context->msg_q)) != NULL) { switch (msg_hdr->msg_type) { case MSG_ARPD_GET_MAC: recv_msg_get_mac((void *)msg_hdr, data->arp_cache, contexts, context->pkt_xmit_q); break; default: printf("arpd: unknown message %hu\n", msg_hdr->msg_type); } } squeue_exit(context->msg_q); usleep(ARP_CACHE_RETRY_INTERVAL); } // for (;;) pthread_exit(NULL); }
void main() { struct hw_ip_pair *hi_pair; char IP_str[20], cache_hw_addr[6]; fd_set rset; int cache_ifindex, cache_hatype; struct hw_addr HWaddr; hi_pair = malloc(sizeof(struct hw_ip_pair)); get_hw_ip_pair(hi_pair); printf("My IP :%s,\t HW addr", hi_pair->ip_addr); print_mac_to_string(hi_pair->hw_addr); printf("\n"); int pf_pack_sockfd = create_pf_pack_socket(); void* buffer = (void*)malloc(ETH_FRAME_LEN); int listen_sockfd, conn_sockfd, clilen, n; struct sockaddr_un servaddr, cliaddr; char sendline[MAXLINE], recvline[MAXLINE]; struct sockaddr_in *destIP = malloc(sizeof(struct sockaddr_in)); char ip_addr[20]; struct arp_packet *arp_req = malloc(sizeof(struct arp_packet)); struct arp_packet *arp_rep = malloc(sizeof(struct arp_packet)); struct arp_packet *arp_recv = malloc(sizeof(struct arp_packet)); struct sockaddr_ll socket_address; int ll_len = sizeof(struct sockaddr_ll); int i=0; listen_sockfd = Socket(AF_LOCAL, SOCK_STREAM, 0); unlink(SUN_PATH_ARP); bzero(&servaddr, sizeof(servaddr)); servaddr.sun_family = AF_LOCAL; strcpy(servaddr.sun_path, SUN_PATH_ARP); Bind(listen_sockfd, (SA *) &servaddr, sizeof(servaddr)); Listen(listen_sockfd, LISTENQ); int lookup_flag=0; clilen = sizeof(struct sockaddr_un); while(1) { FD_ZERO(&rset); FD_SET(listen_sockfd, &rset); FD_SET(pf_pack_sockfd, &rset); FD_SET(conn_sockfd, &rset); int max; if(conn_sockfd != 0) max = max(max(listen_sockfd, conn_sockfd),pf_pack_sockfd); else max = max(listen_sockfd,pf_pack_sockfd); int ret = select(max+1, &rset, NULL, NULL, NULL); if(FD_ISSET(listen_sockfd, &rset)) { conn_sockfd = Accept(listen_sockfd, (SA *) &cliaddr, &clilen); /* n = read(conn_sockfd, destIP, sizeof(struct sockaddr_in)); Inet_ntop(AF_INET, &(destIP->sin_addr), ip_addr, 20); // Lookup for the <HW,IP> pair in the ARP cache lookup_arp_cache(ip_addr, cache_hw_addr, &cache_ifindex, &cache_hatype,&lookup_flag); if(lookup_flag == 0) { printf("Entry not found from cache\n"); create_arp_request_packet(arp_req, ip_addr, hi_pair); send_arp_request(pf_pack_sockfd, arp_req, hi_pair, conn_sockfd); } else{ printf("Entry found from cache\n"); // Send from cache HWaddr.sll_ifindex = cache_ifindex; HWaddr.sll_hatype = cache_hatype; HWaddr.sll_halen = sizeof(cache_hatype); memcpy(HWaddr.mac_addr, cache_hw_addr,6); print_mac_to_string(HWaddr.mac_addr); Write(conn_sockfd, (void *)&HWaddr, sizeof(HWaddr)); close(conn_sockfd); } printf("Sent ARP request\n"); */ } else if(ret!= -1 && FD_ISSET(conn_sockfd, &rset)) { n = read(conn_sockfd, destIP, sizeof(struct sockaddr_in)); Inet_ntop(AF_INET, &(destIP->sin_addr), ip_addr, 20); // Lookup for the <HW,IP> pair in the ARP cache lookup_arp_cache(ip_addr, cache_hw_addr, &cache_ifindex, &cache_hatype,&lookup_flag); if(lookup_flag == 0) { create_arp_request_packet(arp_req, ip_addr, hi_pair); printf("send 1\n"); send_arp_request(pf_pack_sockfd, arp_req, hi_pair, conn_sockfd); } else{ // Send from cache HWaddr.sll_ifindex = cache_ifindex; HWaddr.sll_hatype = cache_hatype; HWaddr.sll_halen = sizeof(cache_hatype); memcpy(HWaddr.mac_addr, cache_hw_addr,6); // print_mac_to_string(HWaddr.mac_addr); Write(conn_sockfd, (void *)&HWaddr, sizeof(HWaddr)); close(conn_sockfd); conn_sockfd = 0; } } else if(FD_ISSET(pf_pack_sockfd, &rset)) { Recvfrom(pf_pack_sockfd, buffer, ETH_FRAME_LEN, 0, (SA *)&socket_address, &ll_len); void *data = buffer + 14; arp_rep = (struct arp_packet *)data; if (arp_rep->id == ARP_ID){ if(arp_rep->op == ARP_REQ) { if(strcmp(arp_rep->dest_IP, hi_pair->ip_addr) == 0) { printf("Printing Ethernet Header and ARP Request Packet Received\n"); print_ethernet_and_arp(arp_rep->src_mac, arp_rep->dest_mac, arp_rep); add_to_arp_cache_list(arp_rep->src_IP, arp_rep->src_mac, socket_address.sll_ifindex, socket_address.sll_hatype, conn_sockfd, 1); // print_arp_cache_list(); create_arp_reply_packet(arp_recv, arp_rep->src_IP, hi_pair, arp_rep->src_mac, arp_rep->id); send_arp_reply(pf_pack_sockfd, arp_recv, hi_pair, socket_address.sll_ifindex); } else { update_arp_cache(arp_rep->src_IP, arp_rep->src_mac, socket_address.sll_ifindex, 0, conn_sockfd); } continue; } else if(arp_rep->op == ARP_REP) { if(ret == -1) { delete_from_arp_cache(arp_rep->src_IP); // print_arp_cache_list(); continue; } printf("Printing Ethernet Header and ARP Reply Packet Received\n"); print_ethernet_and_arp(arp_rep->src_mac, arp_rep->dest_mac, arp_rep); update_arp_cache(arp_rep->src_IP, arp_rep->src_mac, socket_address.sll_ifindex, 0, conn_sockfd); // print_arp_cache_list(); HWaddr.sll_ifindex = socket_address.sll_ifindex; HWaddr.sll_hatype = socket_address.sll_hatype; HWaddr.sll_halen = socket_address.sll_halen; memcpy(HWaddr.mac_addr, arp_rep->src_mac,6); // print_mac_to_string(HWaddr.mac_addr); Write(conn_sockfd, (void *)&HWaddr, sizeof(HWaddr)); close(conn_sockfd); conn_sockfd = 0; update_arp_cache(arp_rep->src_IP, arp_rep->src_mac, socket_address.sll_ifindex, 0, -1); // print_arp_cache_list(); } } } } }