Example #1
0
/*
 * Builds and sends a single ARP request to locate the server
 *
 * Return value:
 *	0 on success
 *	errno on error
 */
static int
netdump_send_arp(in_addr_t dst)
{
	struct ether_addr bcast;
	struct mbuf *m;
	struct arphdr *ah;
	int pktlen;

	MPASS(nd_ifp != NULL);

	/* Fill-up a broadcast address. */
	memset(&bcast, 0xFF, ETHER_ADDR_LEN);
	m = m_gethdr(M_NOWAIT, MT_DATA);
	if (m == NULL) {
		printf("netdump_send_arp: Out of mbufs\n");
		return (ENOBUFS);
	}
	pktlen = arphdr_len2(ETHER_ADDR_LEN, sizeof(struct in_addr));
	m->m_len = pktlen;
	m->m_pkthdr.len = pktlen;
	MH_ALIGN(m, pktlen);
	ah = mtod(m, struct arphdr *);
	ah->ar_hrd = htons(ARPHRD_ETHER);
	ah->ar_pro = htons(ETHERTYPE_IP);
	ah->ar_hln = ETHER_ADDR_LEN;
	ah->ar_pln = sizeof(struct in_addr);
	ah->ar_op = htons(ARPOP_REQUEST);
	memcpy(ar_sha(ah), IF_LLADDR(nd_ifp), ETHER_ADDR_LEN);
	((struct in_addr *)ar_spa(ah))->s_addr = nd_client.s_addr;
	bzero(ar_tha(ah), ETHER_ADDR_LEN);
	((struct in_addr *)ar_tpa(ah))->s_addr = dst;
	return (netdump_ether_output(m, nd_ifp, bcast, ETHERTYPE_ARP));
}
Example #2
0
static int send_arp (interface_t *iface, int op, struct in_addr sip,
					 unsigned char *taddr, struct in_addr tip)
{
	struct arphdr *arp;
	int arpsize = arphdr_len2 (iface->hwlen, sizeof (struct in_addr));
	int retval;

	arp = xmalloc (arpsize);
	memset (arp, 0, arpsize);

	arp->ar_hrd = htons (iface->family);
	arp->ar_pro = htons (ETHERTYPE_IP);
	arp->ar_hln = iface->hwlen;
	arp->ar_pln = sizeof (struct in_addr);
	arp->ar_op = htons (op);
	memcpy (ar_sha (arp), &iface->hwaddr, arp->ar_hln);
	memcpy (ar_spa (arp), &sip, arp->ar_pln);
	if (taddr)
		memcpy (ar_tha (arp), taddr, arp->ar_hln); 
	memcpy (ar_tpa (arp), &tip, arp->ar_pln);

	retval = send_packet (iface, ETHERTYPE_ARP,
						  (unsigned char *) arp, arphdr_len (arp));
	free (arp);
	return (retval);
}
Example #3
0
int arp_check (interface_t *iface, struct in_addr address)
{
  if (! iface->arpable)
    {
      logger (LOG_DEBUG, "arp_check: interface `%s' is not ARPable",
	      iface->name);
      return 0;
    }

  unsigned char buf[256];
  struct arphdr *ah = (struct arphdr *) buf;

  memset (buf, 0, sizeof (buf));

  ah->ar_hrd = htons (ARPHRD_ETHER);
  ah->ar_pro = htons (ETHERTYPE_IP);
  ah->ar_hln = ETHER_ADDR_LEN;
  ah->ar_pln = sizeof (struct in_addr);
  ah->ar_op = htons (ARPOP_REQUEST);
  memcpy (ar_sha (ah), &iface->ethernet_address, ah->ar_hln);
  memcpy (ar_tpa (ah), &address, ah->ar_pln);

  logger (LOG_INFO, "checking %s is available on attached networks", inet_ntoa
	  (address));

  open_socket (iface, true);
  send_packet (iface, ETHERTYPE_ARP, (unsigned char *) &buf, arphdr_len(ah));

  unsigned char reply[4096];
  int bytes;
  unsigned char buffer[iface->buffer_length];

  struct timeval tv;
  long timeout = 0;
  fd_set rset;

  timeout = uptime() + TIMEOUT;
  while (1)
    {
      tv.tv_sec = timeout - uptime ();
      tv.tv_usec = 0;

      if (tv.tv_sec < 1)
	break; /* Time out */

      FD_ZERO (&rset);
      FD_SET (iface->fd, &rset);

      if (select (iface->fd + 1, &rset, NULL, NULL, &tv) == 0)
	break;

      if (! FD_ISSET (iface->fd, &rset))
	continue;

      memset (buffer, 0, sizeof (buffer));
      int buflen = sizeof (buffer);
      int bufpos = -1;

      while (bufpos != 0)
	{
	  memset (reply, 0, sizeof (reply));
	  if ((bytes = get_packet (iface, (unsigned char *) &reply, buffer,
				   &buflen, &bufpos)) < 0)
	    break;

	  ah = (struct arphdr *) reply;

	  /* Only these types are recognised */
	  if (ah->ar_op != htons(ARPOP_REPLY)
	      || ah->ar_hrd != htons (ARPHRD_ETHER))
	    continue;

	  /* Protocol must be IP. */
	  if (ah->ar_pro != htons (ETHERTYPE_IP))
	    continue;
	  if (ah->ar_pln != sizeof (struct in_addr))
	    continue;

	  if (ah->ar_hln != ETHER_ADDR_LEN)
	    continue;
	  if (bytes < sizeof (*ah) + 2 * (4 + ah->ar_hln))
	    continue;

	  logger (LOG_ERR, "ARPOP_REPLY received from %s (%s)",
		  inet_ntoa (* (struct in_addr *) ar_spa (ah)),
		  ether_ntoa ((struct ether_addr *) ar_sha (ah)));
	  close (iface->fd);
	  iface->fd = -1;
	  return 1;
	}
    }

  close (iface->fd);
  iface->fd = -1;
  return 0;
}
Example #4
0
int arp_check (interface_t *iface, struct in_addr address)
{
	union {
		unsigned char buffer[iface->buffer_length];
		struct arphdr ah;
	} arp;

	int bytes;
	struct timeval tv;
	long timeout = 0;
	fd_set rset;

	if (! iface->arpable) {
		logger (LOG_DEBUG, "arp_check: interface `%s' is not ARPable",
				iface->name);
		return 0;
	}

	memset (arp.buffer, 0, sizeof (arp.buffer));

	arp.ah.ar_hrd = htons (iface->family);
	arp.ah.ar_pro = htons (ETHERTYPE_IP);
	arp.ah.ar_hln = iface->hwlen;
	arp.ah.ar_pln = sizeof (struct in_addr);
	arp.ah.ar_op = htons (ARPOP_REQUEST);
	memcpy (ar_sha (&arp.ah), &iface->hwaddr, arp.ah.ar_hln);
	memcpy (ar_tpa (&arp.ah), &address, arp.ah.ar_pln);

	logger (LOG_INFO, "checking %s is available on attached networks",
			inet_ntoa (address));

	open_socket (iface, true);
	send_packet (iface, ETHERTYPE_ARP, (unsigned char *) &arp.buffer,
				 arphdr_len (&arp.ah));

	timeout = uptime() + TIMEOUT;
	while (1) {
		int buflen = sizeof (arp.buffer);
		int bufpos = -1;

		tv.tv_sec = timeout - uptime ();
		tv.tv_usec = 0;

		if (tv.tv_sec < 1)
			break; /* Time out */

		FD_ZERO (&rset);
		FD_SET (iface->fd, &rset);

		if (select (iface->fd + 1, &rset, NULL, NULL, &tv) == 0)
			break;

		if (! FD_ISSET (iface->fd, &rset))
			continue;

		memset (arp.buffer, 0, sizeof (arp.buffer));

		while (bufpos != 0)	{
			union {
				unsigned char buffer[buflen];
				struct arphdr hdr;
			} reply;
			union {
				unsigned char *c;
				struct in_addr *a;
			} rp;
			union {
				unsigned char *c;
				struct ether_addr *a;
			} rh;

			memset (reply.buffer, 0, sizeof (reply.buffer));
			if ((bytes = get_packet (iface, reply.buffer, arp.buffer,
									 &buflen, &bufpos)) < 0)
				break;

			/* Only these types are recognised */
			if (reply.hdr.ar_op != htons(ARPOP_REPLY))
				continue;

			/* Protocol must be IP. */
			if (reply.hdr.ar_pro != htons (ETHERTYPE_IP))
				continue;
			if (reply.hdr.ar_pln != sizeof (struct in_addr))
				continue;

			if (reply.hdr.ar_hln != ETHER_ADDR_LEN)
				continue;
			if ((unsigned) bytes < sizeof (reply.hdr) + 
				2 * (4 + reply.hdr.ar_hln))
				continue;

			rp.c = (unsigned char *) ar_spa (&reply.hdr);
			rh.c = (unsigned char *) ar_sha (&reply.hdr);
			logger (LOG_ERR, "ARPOP_REPLY received from %s (%s)",
					inet_ntoa (*rp.a), ether_ntoa (rh.a));
			close (iface->fd);
			iface->fd = -1;
			return 1;
		}
	}

	close (iface->fd);
	iface->fd = -1;
	return 0;
}
Example #5
0
int arp_claim (interface_t *iface, struct in_addr address)
{
	struct arphdr *reply = NULL;
	long timeout = 0;
	unsigned char *buffer;
	int retval = -1;
	int nprobes = 0;
	int nclaims = 0;
	struct in_addr null_address;

	if (! iface->arpable) {
		logger (LOG_DEBUG, "interface `%s' is not ARPable", iface->name);
		return (0);
	}

	logger (LOG_INFO, "checking %s is available on attached networks",
			inet_ntoa (address));

	if (! open_socket (iface, true))
		return (0);

	memset (&null_address, 0, sizeof (null_address));

	buffer = xmalloc (sizeof (char *) * iface->buffer_length);

	/* Our ARP packets are always smaller - hopefully */
	reply = xmalloc (IP_MIN_FRAME_LENGTH);

	while (1) {
		struct timeval tv;
		int bufpos = -1;
		int buflen = sizeof (char *) * iface->buffer_length;
		fd_set rset;
		int bytes;
		int s;

		tv.tv_sec = 0; 
		tv.tv_usec = timeout;

		FD_ZERO (&rset);
		FD_SET (iface->fd, &rset);
		errno = 0;
		if ((s = select (FD_SETSIZE, &rset, NULL, NULL, &tv)) == -1) {
			if (errno != EINTR)
				logger (LOG_ERR, "select: `%s'", strerror (errno));
			break;
		} else if (s == 0) {
			/* Timed out */
			if (nprobes < NPROBES) {
				nprobes ++;
				timeout = PROBE_INTERVAL;
				logger (LOG_DEBUG, "sending ARP probe #%d", nprobes);
				send_arp (iface, ARPOP_REQUEST, null_address, NULL, address);
			} else if (nclaims < NCLAIMS) {
				nclaims ++;
				timeout = CLAIM_INTERVAL;
				logger (LOG_DEBUG, "sending ARP claim #%d", nclaims);
				send_arp (iface, ARPOP_REQUEST, address, iface->hwaddr, address);
			} else {
				/* No replies, so done */
				retval = 0;
				break;
			}
		}
		
		if (! FD_ISSET (iface->fd, &rset))
			continue;

		memset (buffer, 0, buflen);
		while (bufpos != 0)	{
			union {
				unsigned char *c;
				struct in_addr *a;
			} rp;
			union {
				unsigned char *c;
				struct ether_addr *a;
			} rh;

			memset (reply, 0, IP_MIN_FRAME_LENGTH);
			if ((bytes = get_packet (iface, (unsigned char *) reply,
									 buffer,
									 &buflen, &bufpos)) == -1)
				break;

			/* Only these types are recognised */
			if (reply->ar_op != htons (ARPOP_REPLY))
				continue;

			/* Protocol must be IP. */
			if (reply->ar_pro != htons (ETHERTYPE_IP))
				continue;
			if (reply->ar_pln != sizeof (struct in_addr))
				continue;
			if ((unsigned) bytes < sizeof (reply) + 
				2 * (4 + reply->ar_hln))
				continue;

			rp.c = (unsigned char *) ar_spa (reply);
			rh.c = (unsigned char *) ar_sha (reply);
			
			/* Ensure the ARP reply is for the address we asked for */
			if (rp.a->s_addr != address.s_addr)
				continue;

			/* Some systems send a reply back from our hwaddress - weird */
			if (reply->ar_hln == iface->hwlen &&
				memcmp (rh.c, iface->hwaddr, iface->hwlen) == 0)
				continue;

			logger (LOG_ERR, "ARPOP_REPLY received from %s (%s)",
					inet_ntoa (*rp.a),
					hwaddr_ntoa (rh.c, reply->ar_hln));
			retval = -1;
			goto eexit;
		}
	}

eexit:
	close (iface->fd);
	iface->fd = -1;
	free (buffer);
	free (reply);
	return (retval);
}