Example #1
0
static int addr2mac_add(const int ifindex, const int type, const void *ipraw,
			const void *macraw, const time_t expire)
{
  const int mt = SCAMPER_ADDR_TYPE_ETHERNET;
  scamper_addr_t *mac = NULL;
  scamper_addr_t *ip  = NULL;
  addr2mac_t *addr2mac = NULL;
  char ipstr[128], macstr[128];

  if((ip = scamper_addrcache_get(addrcache, type, ipraw)) == NULL)
    {
      printerror(errno, strerror, __func__, "could not get ip");
      goto err;
    }

  if((mac = scamper_addrcache_get(addrcache, mt, macraw)) == NULL)
    {
      printerror(errno, strerror, __func__, "could not get mac");
      goto err;
    }

  if((addr2mac = addr2mac_alloc(ifindex, ip, mac, expire)) == NULL)
    {
      goto err;
    }

  scamper_addr_free(ip);  ip  = NULL;
  scamper_addr_free(mac); mac = NULL;

  if(splaytree_insert(tree, addr2mac) == NULL)
    {
      printerror(errno, strerror, __func__, "could not add %s:%s to tree",
		 scamper_addr_tostr(addr2mac->ip, ipstr, sizeof(ipstr)),
		 scamper_addr_tostr(addr2mac->mac, macstr, sizeof(macstr)));
      goto err;
    }

  scamper_debug(__func__, "ifindex %d ip %s mac %s expire %d", ifindex,
		scamper_addr_tostr(addr2mac->ip, ipstr, sizeof(ipstr)),
		scamper_addr_tostr(addr2mac->mac, macstr, sizeof(macstr)),
		expire);
  return 0;

 err:
  if(addr2mac != NULL) addr2mac_free(addr2mac);
  if(mac != NULL) scamper_addr_free(mac);
  if(ip != NULL) scamper_addr_free(ip);
  return -1;
}
Example #2
0
/*
 * scamper_getsrc
 *
 * given a destination address, determine the src address used in the IP
 * header to transmit probes to it.
 */
scamper_addr_t *scamper_getsrc(const scamper_addr_t *dst, int ifindex)
{
  struct sockaddr_storage sas;
  scamper_addr_t *src;
  socklen_t socklen, sockleno;
  int sock;
  void *addr;
  char buf[64];

  if(dst->type == SCAMPER_ADDR_TYPE_IPV4)
    {
      if(udp4 == -1 && (udp4 = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
	{
	  printerror(errno, strerror, __func__, "could not open udp4 sock");
	  return NULL;
	}

      sock = udp4;
      addr = &((struct sockaddr_in *)&sas)->sin_addr;
      socklen = sizeof(struct sockaddr_in);

      sockaddr_compose((struct sockaddr *)&sas, AF_INET, dst->addr, 80);
    }
  else if(dst->type == SCAMPER_ADDR_TYPE_IPV6)
    {
      if(udp6 == -1 && (udp6 = socket(AF_INET6, SOCK_DGRAM,IPPROTO_UDP)) == -1)
	{
	  printerror(errno, strerror, __func__, "could not open udp6 sock");
	  return NULL;
	}

      sock = udp6;
      addr = &((struct sockaddr_in6 *)&sas)->sin6_addr;
      socklen = sizeof(struct sockaddr_in6);

      sockaddr_compose((struct sockaddr *)&sas, AF_INET6, dst->addr, 80);

      if(scamper_addr_islinklocal(dst) != 0)
	{
	  ((struct sockaddr_in6 *)&sas)->sin6_scope_id = ifindex;
	}
    }
  else return NULL;

  if(connect(sock, (struct sockaddr *)&sas, socklen) != 0)
    {
      printerror(errno, strerror, __func__, "connect to dst failed for %s",
		 scamper_addr_tostr(dst, buf, sizeof(buf)));
      return NULL;
    }

  sockleno = socklen;
  if(getsockname(sock, (struct sockaddr *)&sas, &sockleno) != 0)
    {
      printerror(errno, strerror, __func__, "could not getsockname for %s",
		 scamper_addr_tostr(dst, buf, sizeof(buf)));
      return NULL;
    }

  src = scamper_addrcache_get(addrcache, dst->type, addr);

  memset(&sas, 0, sizeof(sas));
  connect(sock, (struct sockaddr *)&sas, socklen);
  return src;
}
static void rtsock_parsemsg(uint8_t *buf, size_t len)
{
  struct rt_msghdr   *rtm;
  struct sockaddr    *addrs[RTAX_MAX];
  struct sockaddr_dl *sdl;
  struct sockaddr    *sa;
  struct in6_addr    *ip6;
  size_t              off, tmp, x;
  int                 i, ifindex;
  void               *addr;
  scamper_addr_t     *gw;
  rtsock_pair_t      *pair;
  scamper_route_t    *route;

  x = 0;
  while(x < len)
    {
      if(len - x < sizeof(struct rt_msghdr))
	{
	  scamper_debug(__func__,"len %d != %d",len,sizeof(struct rt_msghdr));
	  return;
	}

      /*
       * check if the message is something we want, and that we have
       * a pair for it
       */
      rtm = (struct rt_msghdr *)(buf + x);
      if(rtm->rtm_pid != pid ||
	 rtm->rtm_msglen > len - x ||
	 rtm->rtm_type != RTM_GET ||
	 (rtm->rtm_flags & RTF_DONE) == 0 ||
	 (pair = rtsock_pair_get(rtm->rtm_seq)) == NULL)
	{
	  x += rtm->rtm_msglen;
	  continue;
	}

      route = pair->route;
      rtsock_pair_free(pair);

      ifindex = -1;
      addr = NULL;
      gw = NULL;

      if(rtm->rtm_errno != 0)
	{
	  route->error = rtm->rtm_errno;
	  goto done;
	}

      off = sizeof(struct rt_msghdr);
      memset(addrs, 0, sizeof(addrs));
      for(i=0; i<RTAX_MAX; i++)
	{
	  if(rtm->rtm_addrs & (1 << i))
	    {
	      addrs[i] = sa = (struct sockaddr *)(buf + x + off);
	      if((tmp = sockaddr_len(sa)) == -1)
		{
		  printerror(0,NULL,__func__,"unhandled af %d",sa->sa_family);
		  route->error = EINVAL;
		  goto done;
		}
	      off += scamper_rtsock_roundup(tmp);
	    }
	}

      if((sdl = (struct sockaddr_dl *)addrs[RTAX_IFP]) != NULL)
	{
	  if(sdl->sdl_family != AF_LINK)
	    {
	      printerror(0, NULL, __func__, "sdl_family %d", sdl->sdl_family);
	      route->error = EINVAL;
	      goto done;
	    }
	  ifindex = sdl->sdl_index;
	}

      if((sa = addrs[RTAX_GATEWAY]) != NULL)
	{
	  if(sa->sa_family == AF_INET)
	    {
	      i = SCAMPER_ADDR_TYPE_IPV4;
	      addr = &((struct sockaddr_in *)sa)->sin_addr;
	    }
	  else if(sa->sa_family == AF_INET6)
	    {
	      /*
	       * check to see if the gw address is a link local address.  if
	       * it is, then drop the embedded index from the gateway address
	       */
	      ip6 = &((struct sockaddr_in6 *)sa)->sin6_addr;
	      if(IN6_IS_ADDR_LINKLOCAL(ip6))
		{
		  ip6->s6_addr[2] = 0;
		  ip6->s6_addr[3] = 0;
		}
	      i = SCAMPER_ADDR_TYPE_IPV6;
	      addr = ip6;
	    }
	  else if(sa->sa_family == AF_LINK)
	    {
	      sdl = (struct sockaddr_dl *)sa;
	      if(sdl->sdl_type == IFT_ETHER && sdl->sdl_alen == ETHER_ADDR_LEN)
		{
		  i = SCAMPER_ADDR_TYPE_ETHERNET;
		  addr = sdl->sdl_data + sdl->sdl_nlen;
		}
	    }

	  /*
	   * if we have got a gateway address that we know what to do with,
	   * then store it here.
	   */
	  if(addr != NULL &&
	     (gw = scamper_addrcache_get(addrcache, i, addr)) == NULL)
	    {
	      scamper_debug(__func__, "could not get rtsmsg->rr.gw");
	      route->error = EINVAL;
	      goto done;
	    }
	}

    done:
      route->gw      = gw;
      route->ifindex = ifindex;
      route->cb(route);
      x += rtm->rtm_msglen;
    }

  return;
}