예제 #1
0
파일: ethernet.c 프로젝트: rasco/armnet
// Passes the received forward to the appropriate handler
void ethernet_recv_frame(char *buf, int len)
{
    ethernet_header *head = (ethernet_header*)buf;
    
    dprintf("received frame of length %d\n", len);
    //printf("type: %02x%02x", head->ether_type[0], head->ether_type[1]);
    //if ( memcmp(ethernet_opt_address, head->dest_addr, 6) != 0 )
    //    return;
    
    // ARP
    if ( head->ether_type[0] == 0x08 && head->ether_type[1] == 0x06 )
    {
        arp_recv(buf, len);
    }
    // IP
    else if ( head->ether_type[0] == 0x08 && head->ether_type[1] == 0x00 )
    {
        // Pass over the IP packet without the ethernet header and checksum
        ip_input(buf+sizeof(ethernet_header), len-sizeof(ethernet_header)-4);
    }
}
예제 #2
0
파일: arp.c 프로젝트: forest1040/kozos
static int arp_proc(struct netbuf *buf)
{
  int ret = 0;

  switch (buf->cmd) {
  case ARP_CMD_MACADDR:
    memcpy(my_macaddr, buf->option.common.macaddr.addr, MACADDR_SIZE);
    break;
  case ARP_CMD_IPADDR:
    my_ipaddr = buf->option.common.ipaddr.addr;
    break;
  case ARP_CMD_RECV:
    ret = arp_recv(buf);
    break;
  case ARP_CMD_SEND:
    ret = arp_send(buf);
    break;
  default:
    break;
  }

  return ret;
}
예제 #3
0
파일: arp.c 프로젝트: WiseMan787/ralink_sdk
void *arp(char *ifname) 
{
  int sock,i;
  struct sockaddr_ll ifs;
  struct ifreq ifr;

  pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
  pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);

  sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP));

  if(sock == -1) {
    fprintf(stderr, "Socket error %d.\n", errno);
    exit(1);
  }

  /* Get the hwaddr and ifindex of the interface */
  memset(ifr.ifr_name, 0, IFNAMSIZ);
  strncpy(ifr.ifr_name, (char *) ifname, IFNAMSIZ);
  if(ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) {
    syslog(LOG_ERR, "error: ioctl SIOCGIFHWADDR for %s: %s\n", (char *) ifname, strerror(errno));
    abort();
  }

  memset(ifs.sll_addr, 0, ETH_ALEN);
  memcpy(ifs.sll_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);

  if(ioctl(sock, SIOCGIFINDEX, &ifr) < 0) {
    syslog(LOG_ERR, "error: ioctl SIOCGIFINDEX for %s: %s", (char *) ifname, strerror(errno));
    abort();
  }

  ifs.sll_family = AF_PACKET;
  ifs.sll_protocol = htons(ETH_P_ARP);
  ifs.sll_ifindex = ifr.ifr_ifindex;
  ifs.sll_hatype = ARPHRD_ETHER;
  ifs.sll_pkttype = PACKET_BROADCAST;
  ifs.sll_halen = ETH_ALEN;
  
  if(bind(sock, (struct sockaddr *)&ifs, sizeof(struct sockaddr_ll)) < 0) {
    fprintf(stderr, "Bind %s: %d\n", (char *) ifname, errno);
    abort();
  }

  while (1) {
    ether_arp_frame frame;
    unsigned long src;
    unsigned long dst;
    struct in_addr sia;
    struct in_addr dia;

    do {
      pthread_testcancel();
      /* Sleep a bit in order not to overload the system */
      usleep(300);

      if (arp_recv(sock, &frame) <= 0)
    	    continue;
      /* Insert all the replies into ARP table */
      if (frame.arp.arp_op == ntohs(ARPOP_REPLY)) {

    	  /* Received frame is an ARP reply */
	  
	  struct arpreq k_arpreq;
	  int arpsock;
	  struct sockaddr_in *sin;
	  
	  if ((arpsock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
		syslog(LOG_ERR, "error: ARP socket for %s: %s", (char *) ifname, strerror(errno));
	        continue;
	  }
	  
          k_arpreq.arp_ha.sa_family = ARPHRD_ETHER;
          memcpy(&k_arpreq.arp_ha.sa_data, &frame.arp.arp_sha, sizeof(frame.arp.arp_sha));
	  k_arpreq.arp_flags = ATF_COM;
	  if (option_arpperm)
	      k_arpreq.arp_flags = k_arpreq.arp_flags | ATF_PERM;
	  strncpy(k_arpreq.arp_dev, ifname, sizeof(k_arpreq.arp_dev));

	  k_arpreq.arp_pa.sa_family = AF_INET;
	  sin = (struct sockaddr_in *) &k_arpreq.arp_pa;
	  memcpy(&sin->sin_addr.s_addr, &frame.arp.arp_spa, sizeof(sin->sin_addr));

	  /* Update kernel ARP table with the data from reply */
	  
	  if (debug)
	      printf("Received reply: updating kernel ARP table for %s(%s).\n", inet_ntoa(sin->sin_addr), (char *) ifname);
	  if (ioctl(arpsock, SIOCSARP, &k_arpreq) < 0) {
		syslog(LOG_ERR, "error: ioctl SIOCSARP for %s(%s): %s", inet_ntoa(sin->sin_addr), (char *) ifname, strerror(errno));
		close(arpsock);
	        continue;
	  }
	  close(arpsock);

	  /* Check if reply is for one of the requests in request queue */
	  rq_process(sin->sin_addr, ifs.sll_ifindex);

	/* send gratuitous arp request to all other interfaces to let them
	 * update their ARP tables quickly */ 	  
	for (i=0; i <= last_iface_idx; i++) {
	    if (strcmp(ifaces[i], ifname)) {
		arp_req(ifaces[i], sin->sin_addr, 1);
	    }
	}
      }
    } while (frame.arp.arp_op != htons(ARPOP_REQUEST));

    /* Received frame is an ARP request */

    memcpy(&src,(char *)frame.arp.arp_spa,4);
    memcpy(&dst,(char *)frame.arp.arp_tpa,4);
    
    dia.s_addr = dst;
    sia.s_addr = src;
    
    if (debug)
	  printf("Received ARP request for %s on iface %s\n", inet_ntoa(dia), (char *) ifname);

    if (memcmp(&dia,&sia,sizeof(dia)) && dia.s_addr != 0) {
        pthread_mutex_lock(&arptab_mutex);
        /* Relay the ARP request to all other interfaces */
	for (i=0; i <= last_iface_idx; i++) {
    	    if (strcmp(ifaces[i], ifname)) {
		arp_req(ifaces[i], dia, 0);
	    }
	}
	/* Add the request to the request queue */
	if (debug)
    	    printf("Adding %s to request queue\n", inet_ntoa(sia));
	rq_add(&frame, &ifs);
	pthread_mutex_unlock(&arptab_mutex);
    }    
  }
}