Esempio n. 1
0
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);
}
Esempio n. 2
0
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);
}
Esempio n. 3
0
// 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();
                }
            }

        }
    }
}