예제 #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));
}
예제 #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);
}
예제 #3
0
void
arp_print(netdissect_options *ndo,
	  const u_char *bp, u_int length, u_int caplen)
{
	const struct arp_pkthdr *ap;
	u_short pro, hrd, op, linkaddr;

	ap = (const struct arp_pkthdr *)bp;
	ND_TCHECK(*ap);

	hrd = HRD(ap);
	pro = PRO(ap);
	op = OP(ap);

        
        /* if its ATM then call the ATM ARP printer
           for Frame-relay ARP most of the fields
           are similar to Ethernet so overload the Ethernet Printer
           and set the linkaddr type for linkaddr_string() accordingly */

        switch(hrd) {
        case ARPHRD_ATM2225:
            atmarp_print(ndo, bp, length, caplen);
            return;
        case ARPHRD_FRELAY:
            linkaddr = LINKADDR_FRELAY;
            break;
        default:
            linkaddr = LINKADDR_ETHER;
            break;
	}

	if (!ND_TTEST2(*ar_tpa(ap), PROTO_LEN(ap))) {
		ND_PRINT((ndo, "[|ARP]"));
		ND_DEFAULTPRINT((const u_char *)ap, length);
		return;
	}

        if (!ndo->ndo_eflag) {
            ND_PRINT((ndo, "ARP, "));
        }

        /* print hardware type/len and proto type/len */
        if ((pro != ETHERTYPE_IP && pro != ETHERTYPE_TRAIL) ||
	    PROTO_LEN(ap) != 4 ||
            HRD_LEN(ap) == 0 ||
            ndo->ndo_vflag) {
            ND_PRINT((ndo, "%s (len %u), %s (len %u)",
                      tok2str(arphrd_values, "Unknown Hardware (%u)", hrd),
                      HRD_LEN(ap),
                      tok2str(ethertype_values, "Unknown Protocol (0x%04x)", pro),
                      PROTO_LEN(ap)));

            /* don't know know about the address formats */
            if (!ndo->ndo_vflag) {
                goto out;
            }
	}

        /* print operation */
        printf("%s%s ",
               ndo->ndo_vflag ? ", " : "", 
               tok2str(arpop_values, "Unknown (%u)", op));

	switch (op) {

	case ARPOP_REQUEST:
		ND_PRINT((ndo, "who-has %s", ipaddr_string(TPA(ap))));
		if (memcmp((const char *)ezero, (const char *)THA(ap), HRD_LEN(ap)) != 0)
			ND_PRINT((ndo, " (%s)",
				  linkaddr_string(THA(ap), linkaddr, HRD_LEN(ap))));
		ND_PRINT((ndo, " tell %s", ipaddr_string(SPA(ap))));
		break;

	case ARPOP_REPLY:
		ND_PRINT((ndo, "%s is-at %s",
                          ipaddr_string(SPA(ap)),
                          linkaddr_string(SHA(ap), linkaddr, HRD_LEN(ap))));
		break;

	case ARPOP_REVREQUEST:
		ND_PRINT((ndo, "who-is %s tell %s",
			  linkaddr_string(THA(ap), linkaddr, HRD_LEN(ap)),
			  linkaddr_string(SHA(ap), linkaddr, HRD_LEN(ap))));
		break;

	case ARPOP_REVREPLY:
		ND_PRINT((ndo, "%s at %s",
			  linkaddr_string(THA(ap), linkaddr, HRD_LEN(ap)),
			  ipaddr_string(TPA(ap))));
		break;

	case ARPOP_INVREQUEST:
		ND_PRINT((ndo, "who-is %s tell %s",
			  linkaddr_string(THA(ap), linkaddr, HRD_LEN(ap)),
			  linkaddr_string(SHA(ap), linkaddr, HRD_LEN(ap))));
		break;

	case ARPOP_INVREPLY:
		ND_PRINT((ndo,"%s at %s",
			  linkaddr_string(THA(ap), linkaddr, HRD_LEN(ap)),
			  ipaddr_string(TPA(ap))));
		break;

	default:
		ND_DEFAULTPRINT((const u_char *)ap, caplen);
		return;
	}

 out:
        ND_PRINT((ndo, ", length %u", length));

	return;
trunc:
	ND_PRINT((ndo, "[|ARP]"));
}
예제 #4
0
static int
firewire_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
    struct route *ro)
{
	struct fw_com *fc = IFP2FWC(ifp);
	int error, type;
	struct m_tag *mtag;
	union fw_encap *enc;
	struct fw_hwaddr *destfw;
	uint8_t speed;
	uint16_t psize, fsize, dsize;
	struct mbuf *mtail;
	int unicast, dgl, foff;
	static int next_dgl;
#if defined(INET) || defined(INET6)
	struct llentry *lle;
#endif

#ifdef MAC
	error = mac_ifnet_check_transmit(ifp, m);
	if (error)
		goto bad;
#endif

	if (!((ifp->if_flags & IFF_UP) &&
	   (ifp->if_drv_flags & IFF_DRV_RUNNING))) {
		error = ENETDOWN;
		goto bad;
	}

	/*
	 * For unicast, we make a tag to store the lladdr of the
	 * destination. This might not be the first time we have seen
	 * the packet (for instance, the arp code might be trying to
	 * re-send it after receiving an arp reply) so we only
	 * allocate a tag if there isn't one there already. For
	 * multicast, we will eventually use a different tag to store
	 * the channel number.
	 */
	unicast = !(m->m_flags & (M_BCAST | M_MCAST));
	if (unicast) {
		mtag = m_tag_locate(m, MTAG_FIREWIRE, MTAG_FIREWIRE_HWADDR, NULL);
		if (!mtag) {
			mtag = m_tag_alloc(MTAG_FIREWIRE, MTAG_FIREWIRE_HWADDR,
			    sizeof (struct fw_hwaddr), M_NOWAIT);
			if (!mtag) {
				error = ENOMEM;
				goto bad;
			}
			m_tag_prepend(m, mtag);
		}
		destfw = (struct fw_hwaddr *)(mtag + 1);
	} else {
		destfw = 0;
	}

	switch (dst->sa_family) {
#ifdef INET
	case AF_INET:
		/*
		 * Only bother with arp for unicast. Allocation of
		 * channels etc. for firewire is quite different and
		 * doesn't fit into the arp model.
		 */
		if (unicast) {
			error = arpresolve(ifp, ro ? ro->ro_rt : NULL, m, dst, (u_char *) destfw, &lle);
			if (error)
				return (error == EWOULDBLOCK ? 0 : error);
		}
		type = ETHERTYPE_IP;
		break;

	case AF_ARP:
	{
		struct arphdr *ah;
		ah = mtod(m, struct arphdr *);
		ah->ar_hrd = htons(ARPHRD_IEEE1394);
		type = ETHERTYPE_ARP;
		if (unicast)
			*destfw = *(struct fw_hwaddr *) ar_tha(ah);

		/*
		 * The standard arp code leaves a hole for the target
		 * hardware address which we need to close up.
		 */
		bcopy(ar_tpa(ah), ar_tha(ah), ah->ar_pln);
		m_adj(m, -ah->ar_hln);
		break;
	}
#endif

#ifdef INET6
	case AF_INET6:
		if (unicast) {
			error = nd6_storelladdr(fc->fc_ifp, m, dst,
			    (u_char *) destfw, &lle);
			if (error)
				return (error);
		}
		type = ETHERTYPE_IPV6;
		break;
#endif

	default:
		if_printf(ifp, "can't handle af%d\n", dst->sa_family);
		error = EAFNOSUPPORT;
		goto bad;
	}

	/*
	 * Let BPF tap off a copy before we encapsulate.
	 */
	if (bpf_peers_present(ifp->if_bpf)) {
		struct fw_bpfhdr h;
		if (unicast)
			bcopy(destfw, h.firewire_dhost, 8);
		else
			bcopy(&firewire_broadcastaddr, h.firewire_dhost, 8);
		bcopy(&fc->fc_hwaddr, h.firewire_shost, 8);
		h.firewire_type = htons(type);
		bpf_mtap2(ifp->if_bpf, &h, sizeof(h), m);
	}

	/*
	 * Punt on MCAP for now and send all multicast packets on the
	 * broadcast channel.
	 */
	if (m->m_flags & M_MCAST)
		m->m_flags |= M_BCAST;

	/*
	 * Figure out what speed to use and what the largest supported
	 * packet size is. For unicast, this is the minimum of what we
	 * can speak and what they can hear. For broadcast, lets be
	 * conservative and use S100. We could possibly improve that
	 * by examining the bus manager's speed map or similar. We
	 * also reduce the packet size for broadcast to account for
	 * the GASP header.
	 */
	if (unicast) {
		speed = min(fc->fc_speed, destfw->sspd);
		psize = min(512 << speed, 2 << destfw->sender_max_rec);
	} else {
		speed = 0;
		psize = 512 - 2*sizeof(uint32_t);
	}

	/*
	 * Next, we encapsulate, possibly fragmenting the original
	 * datagram if it won't fit into a single packet.
	 */
	if (m->m_pkthdr.len <= psize - sizeof(uint32_t)) {
		/*
		 * No fragmentation is necessary.
		 */
		M_PREPEND(m, sizeof(uint32_t), M_NOWAIT);
		if (!m) {
			error = ENOBUFS;
			goto bad;
		}
		enc = mtod(m, union fw_encap *);
		enc->unfrag.ether_type = type;
		enc->unfrag.lf = FW_ENCAP_UNFRAG;
		enc->unfrag.reserved = 0;

		/*
		 * Byte swap the encapsulation header manually.
		 */
		enc->ul[0] = htonl(enc->ul[0]);

		error = (ifp->if_transmit)(ifp, m);
		return (error);
	} else {
예제 #5
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;
}
예제 #6
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;
}