Example #1
0
void
get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info)
{
  int	i;
#ifndef HAVE_SOCKADDR_SA_LEN
  char  *p = (char *)sa;
  size_t len;
#endif

  for (i = 0; i < RTAX_MAX; i++) {
    if (addrs & (1 << i)) {
      rti_info[i] = sa;
#ifdef HAVE_SOCKADDR_SA_LEN
      NEXT_SA(sa);
#else
      switch(sa->sa_family) {
      case AF_INET:
	len = sizeof(struct sockaddr_in);
	break;
      case AF_LINK:
	len = sizeof(struct sockaddr_dl);
	break;
      default:
	len = 0;
      }
      sa = (struct sockaddr *) (p + len);
      p = (char *)sa;
#endif
    } else
      rti_info[i] = NULL;
  }
}
Example #2
0
void get_rtaddr(int flags,struct sockaddr *sa,struct sockaddr **rt_info)
{
	int i;
	for(i=0 ; i < RTAX_MAX; i++){
		if( flags & (1 << i)){
			rt_info[i] = sa;
			NEXT_SA(sa);
		}else{
			rt_info[i] = NULL;
		}
	}
}
Example #3
0
File: ns.c Project: 2asoft/freebsd
void
get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info)
{
	int	i;

	for (i = 0; i < RTAX_MAX; i++) {
		if (addrs & (1 << i)) {
			rti_info[i] = sa;
			NEXT_SA(sa);
		} else
			rti_info[i] = NULL;
	}
}
Example #4
0
int get_bind_addr(bin_addr *dest, struct addrinfo *ba)
{

  /* list interface name/address
   *   fixed size buffer limits number of recognizable interfaces.
   *   buf size = sizeof(struct ifreq) * 256 interface = 8192
   */
  int			i, ent, sockfd, len;
  char			*ptr, buf[sizeof(struct ifreq) * MAXNUM_IF];
  struct ifconf		ifc;
  struct ifreq		*ifr;
  struct sockaddr_in	*sinptr;
  struct if_list        ifl[MAXNUM_IF];

  pid_t			pid;
  ssize_t		n;
  struct rt_msghdr	*rtm;
  struct sockaddr	*sa, *rti_info[RTAX_MAX];
  struct sockaddr_in	*sin;
  struct sockaddr_dl    *sdl;
  struct in_addr        ia;

  struct addrinfo hints, *res, *res0;
  int    error;
  char   host[256];
  int found = 0;


  /* IPv6 routing is not implemented yet */
  switch (dest->atype) {
  case S5ATIPV4:
    memcpy(&ia, &(dest->v4_addr), 4);
    break;
  case S5ATIPV6:
    return -1;
  case S5ATFQDN:
    memset(&hints, 0, sizeof(hints));
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_family = AF_INET;
    memcpy(host, &dest->fqdn, dest->len_fqdn);
    host[dest->len_fqdn] = '\0';
    error = getaddrinfo(host, NULL, &hints, &res0);
    if (error) {
      return -1;
    }
    for (res = res0; res; res = res->ai_next) {
      if (res->ai_family != AF_INET)
	continue;
      sin = (struct sockaddr_in *)res->ai_addr;
      memcpy(&ia, &(sin->sin_addr), sizeof(ia));
      found++; break;
    }
    freeaddrinfo(res0);
    if (!found)
      return -1;
    break;
  default:
    return -1;
  }

  sockfd = socket(AF_INET, SOCK_DGRAM, 0);

  ifc.ifc_len = sizeof(buf);
  ifc.ifc_req = (struct ifreq *) buf;
  ioctl(sockfd, SIOCGIFCONF, &ifc);

  close(sockfd);

  i = ent = 0;
  for (ptr = buf; ptr < buf + ifc.ifc_len; ) {
    ifr = (struct ifreq *) ptr;
    len = sizeof(struct sockaddr);
#ifdef	HAVE_SOCKADDR_SA_LEN
    if (ifr->ifr_addr.sa_len > len)
      len = ifr->ifr_addr.sa_len;		/* length > 16 */
#endif
    ptr += sizeof(ifr->ifr_name) + len;	/* for next one in buffer */

    switch (ifr->ifr_addr.sa_family) {
    case AF_INET:
      strncpy(ifl[i].if_name, ifr->ifr_name, IFNAMSIZ);
      sinptr = (struct sockaddr_in *) &ifr->ifr_addr;
      memcpy(&ifl[i].if_addr, &sinptr->sin_addr, sizeof(struct in_addr));
      i++;
      break;

    default:
      break;
    }
  }
  ent = i; /* number of interfaces */

  /* get routing */
  setreuid(PROCUID, 0);
  sockfd = socket(AF_ROUTE, SOCK_RAW, 0);	/* need superuser privileges */
  setreuid(0, PROCUID);
  if (sockfd < 0) {
    /* socket error */
    return(-1);
  }

  memset(buf, 0, sizeof buf);

  rtm = (struct rt_msghdr *) buf;
  rtm->rtm_msglen = sizeof(struct rt_msghdr)
                  + sizeof(struct sockaddr_in)
                  + sizeof(struct sockaddr_dl);
  rtm->rtm_version = RTM_VERSION;
  rtm->rtm_type = RTM_GET;
  rtm->rtm_addrs = RTA_DST|RTA_IFP;
  rtm->rtm_pid = pid = getpid();
  rtm->rtm_seq = SEQ;

  sin = (struct sockaddr_in *) (buf + sizeof(struct rt_msghdr));
  sin->sin_family = AF_INET;
#ifdef HAVE_SOCKADDR_SA_LEN
  sin->sin_len = sizeof(struct sockaddr_in);
#endif

  memcpy(&(sin->sin_addr), &ia, sizeof(struct in_addr));

#ifdef HAVE_SOCKADDR_SA_LEN
  sa = (struct sockaddr *)sin;
  NEXT_SA(sa);
  sdl = (struct sockaddr_dl *)sa;
  sdl->sdl_len = sizeof(struct sockaddr_dl);
#else
  sdl = (struct sockaddr_dl *) (buf
		+ ROUNDUP(sizeof(struct rt_msghdr), sizeof(u_long))
		+ ROUNDUP(sizeof(struct sockaddr_in), sizeof(u_long)));
#endif
  sdl->sdl_family = AF_LINK;

  write(sockfd, rtm, rtm->rtm_msglen);

  do {
    n = read(sockfd, rtm, sizeof buf);
  } while (rtm->rtm_type != RTM_GET || rtm->rtm_seq != SEQ ||
	   rtm->rtm_pid != pid);

  close(sockfd);

  rtm = (struct rt_msghdr *) buf;
  sa = (struct sockaddr *) (rtm + 1);
  get_rtaddrs(rtm->rtm_addrs, sa, rti_info);

  ba->ai_family = AF_INET;          /* IPv4 */
  ba->ai_socktype = SOCK_STREAM;
  ba->ai_protocol = IPPROTO_TCP;
  sin = (struct sockaddr_in *)ba->ai_addr;
  sin->sin_family = AF_INET;
#ifdef HAVE_SOCKADDR_SA_LEN
  sin->sin_len = sizeof(struct sockaddr_in);
#endif
  ba->ai_addrlen = sizeof(struct sockaddr_in);

  if ( (sa = rti_info[RTAX_IFP]) != NULL) {
    sdl = (struct sockaddr_dl *)sa;
    if (sdl->sdl_nlen > 0) {
      for (i=0; i<ent; i++) {
	if (memcmp(ifl[i].if_name, sdl->sdl_data, sdl->sdl_nlen) == 0) {
	  memcpy(&sin->sin_addr, &ifl[i].if_addr, sizeof(struct in_addr));
	  return(0);
	}
      }
    }
  }
  return(-1);
}