Esempio n. 1
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);
}
Esempio n. 2
0
int
main(int argc, char *argv[])
{
	struct event recv_ev;
	char *dev;
	int c, debug;
	FILE *fp;

	dev = NULL;
	debug = 0;
	
	while ((c = getopt(argc, argv, "di:h?")) != -1) {
		switch (c) {
		case 'd':
			debug = 1;
			break;
		case 'i':
			dev = optarg;
			break;
		default:
			usage();
			break;
		}
	}
	argc -= optind;
	argv += optind;

	if (argc == 0)
		arpd_init(dev, 0, NULL);
	else
		arpd_init(dev, argc, argv);
	
	if ((fp = fopen(PIDFILE, "w")) == NULL)
		err(1, "fopen");
	
	if (!debug) {
		setlogmask(LOG_UPTO(LOG_INFO));
		
		if (daemon(1, 0) < 0) {
			unlink(PIDFILE);
			err(1, "daemon");
		}
	}
	fprintf(fp, "%d\n", getpid());
	fclose(fp);
	
	chmod(PIDFILE, 0644);

	event_init();
	
	event_set(&recv_ev, pcap_fileno(arpd_pcap), EV_READ,
	    arpd_recv, &recv_ev);
	event_add(&recv_ev, NULL);
	
	/* Setup signal handler */
	if (signal(SIGINT, terminate_handler) == SIG_ERR) {
		perror("signal");
		return (-1);
	}
	if (signal(SIGTERM, terminate_handler) == SIG_ERR) {
		perror("signal");
		return (-1);
	}
	
	event_dispatch();

	return (0);
}