Exemple #1
0
int
main(int argc, char **argv)
{
    int					sockfd;
    char				*buf;
    pid_t				pid;
    ssize_t				n;
    struct rt_msghdr	*rtm;
    struct sockaddr		*sa, *rti_info[RTAX_MAX];
    struct sockaddr_in	*sin;

    if (argc != 2)
        err_quit("usage: getrt <IPaddress>");

    sockfd = Socket(AF_ROUTE, SOCK_RAW, 0);	/* need superuser privileges */

    buf = Calloc(1, BUFLEN);	/* and initialized to 0 */

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

    sin = (struct sockaddr_in *) (rtm + 1);
    sin->sin_len = sizeof(struct sockaddr_in);
    sin->sin_family = AF_INET;
    Inet_pton(AF_INET, argv[1], &sin->sin_addr);

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

    do {
        n = Read(sockfd, rtm, BUFLEN);
    } while (rtm->rtm_type != RTM_GET || rtm->rtm_seq != SEQ ||
             rtm->rtm_pid != pid);
    /* end getrt1 */

    /* include getrt2 */
    rtm = (struct rt_msghdr *) buf;
    sa = (struct sockaddr *) (rtm + 1);
    get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
    if ( (sa = rti_info[RTAX_DST]) != NULL)
        printf("dest: %s\n", Sock_ntop_host(sa, sa->sa_len));

    if ( (sa = rti_info[RTAX_GATEWAY]) != NULL)
        printf("gateway: %s\n", Sock_ntop_host(sa, sa->sa_len));

    if ( (sa = rti_info[RTAX_NETMASK]) != NULL)
        printf("netmask: %s\n", Sock_masktop(sa, sa->sa_len));

    if ( (sa = rti_info[RTAX_GENMASK]) != NULL)
        printf("genmask: %s\n", Sock_masktop(sa, sa->sa_len));

    exit(0);
}
Exemple #2
0
struct in6_addr *
get_addr(char *buf)
{
	struct rt_msghdr *rtm = (struct rt_msghdr *)buf;
	struct sockaddr *sa, *rti_info[RTAX_MAX];

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

	return (&SIN6(rti_info[RTAX_DST])->sin6_addr);
}
Exemple #3
0
struct sockaddr_dl *
if_nametosdl(char *name)
{
	int mib[6] = {CTL_NET, AF_ROUTE, 0, 0, NET_RT_IFLIST, 0};
	char *buf, *next, *lim;
	size_t len;
	struct if_msghdr *ifm;
	struct sockaddr *sa, *rti_info[RTAX_MAX];
	struct sockaddr_dl *sdl = NULL, *ret_sdl;

	if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0)
		return(NULL);
	if ((buf = malloc(len)) == NULL)
		return(NULL);
	if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
		free(buf);
		return (NULL);
	}

	lim = buf + len;
	for (next = buf; next < lim; next += ifm->ifm_msglen) {
		ifm = (struct if_msghdr *)next;
		if (ifm->ifm_type == RTM_IFINFO) {
			sa = (struct sockaddr *)(ifm + 1);
			get_rtaddrs(ifm->ifm_addrs, sa, rti_info);
			if ((sa = rti_info[RTAX_IFP]) != NULL) {
				if (sa->sa_family == AF_LINK) {
					sdl = (struct sockaddr_dl *)sa;
					if (strlen(name) != sdl->sdl_nlen)
						continue; /* not same len */
					if (strncmp(&sdl->sdl_data[0],
						    name,
						    sdl->sdl_nlen) == 0) {
						break;
					}
				}
			}
		}
	}
	if (next == lim) {
		/* search failed */
		free(buf);
		return (NULL);
	}

	if ((ret_sdl = malloc(sdl->sdl_len)) == NULL) {
		free(buf);
		return (NULL);
	}
	memcpy((caddr_t)ret_sdl, (caddr_t)sdl, sdl->sdl_len);

	free(buf);
	return (ret_sdl);
}
Exemple #4
0
int
get_rtm_ifindex(char *buf)
{
	struct rt_msghdr *rtm = (struct rt_msghdr *)buf;
	struct sockaddr *sa, *rti_info[RTAX_MAX];

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

	return (((struct sockaddr_dl *)rti_info[RTAX_GATEWAY])->sdl_index);
}
Exemple #5
0
int
get_prefixlen(char *buf)
{
	struct rt_msghdr *rtm = (struct rt_msghdr *)buf;
	struct sockaddr *sa, *rti_info[RTAX_MAX];
	char *p, *lim;

	sa = (struct sockaddr *)(rtm + 1);
	get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
	sa = rti_info[RTAX_NETMASK];

	p = (char *)(&SIN6(sa)->sin6_addr);
	lim = (char *)sa + sa->sa_len;
	return prefixlen(p, lim);
}
Exemple #6
0
unsigned int if_nametoindex(const char *name)
{
    unsigned int        idx, namelen;
    char                *buf, *next, *lim;
    size_t               len;
    struct if_msghdr    *ifm;
    struct sockaddr     *sa, *rti_info[RTAX_MAX];
    struct sockaddr_dl  *sdl;

    // 获取接口列表
    if ((buf = net_rt_iflist(0, 0, &len)) == NULL) {
        return(0);
    }

    // 查找符合给定名称的接口,并返回其索引
    namelen = strlen(name);
    lim = buf + len;
    for (next = buf; next < lim; next += ifm->ifm_msglen) {
        ifm = (struct if_msghdr *) next;
        if (ifm->ifm_type == RTM_IFINFO) {
            sa = (struct sockaddr *) (ifm + 1);
            get_rtaddrs(ifm->ifm_addrs, sa, rti_info);
            if ((sa = rti_info[RTAX_IFP]) != NULL) {
                if (sa->sa_family == AF_LINK) {
                    sdl = (struct sockaddr_d *) sa;
                    if (sdl->sdl_nlen == namelen && strncmp(&sdl->sdl_data[0], name, sdl->sdl_nlen) == 0) {
                        idx = sdl->sdl_index; // save before free()
                        free(buf);
                        return(idx);
                    }
                }
            }
        }
    }
    free(buf);
    return(0);  // no match for name
}
Exemple #7
0
// interface name to index
unsigned int if_nametoindex(const char *name)
{
  unsigned int index;
  char *buf, *next, *lim;
  size_t len;
  struct if_msghdr *ifm;
  struct sockaddr *sa, *rti_info[RTAX_MAX];
  struct sockaddr_dl *sdl;

  if ((buf = net_rt_iflist(0, 0, &len)) == NULL)
    return 0;
  lim = buf + len;
  for (next = buf; next < lim; next += ifm->ifm_msglen) 
    {
      ifm = (struct if_msghdr *) next;
      if (ifm->ifm_type == RTM_IFINFO)
	{
	  sa = (struct sockaddr *) (ifm + 1);
	  get_rtaddrs(ifm->ifm_addrs, sa, rti_info);
	  if ((sa = rti_info[RTAX_IFP]) != NULL)
	    {
	      if (sa->sa_family == AF_LINK)
		{
		  sdl = (struct sockaddr_dl *) sa;
		  if (strncmp(&sdl->sdl_data[0], name, sdl->sdl_nlen) == 0) 
		    {
		      index = sdl->sdl_index;
		      free(buf);
		      return index;
		    }
		}
	    }
	}
    }
  free(buf);
  return 0;
}
Exemple #8
0
char *
if_indextoname(unsigned int idx, char *name)
{
	char				*buf, *next, *lim;
	size_t				len;
	struct if_msghdr	*ifm;
	struct sockaddr		*sa, *rti_info[RTAX_MAX];
	struct sockaddr_dl	*sdl;

	if ( (buf = net_rt_iflist(0, idx, &len)) == NULL)
		return(NULL);

	lim = buf + len;
	for (next = buf; next < lim; next += ifm->ifm_msglen) {
		ifm = (struct if_msghdr *) next;
		if (ifm->ifm_type == RTM_IFINFO) {
			sa = (struct sockaddr *) (ifm + 1);
			get_rtaddrs(ifm->ifm_addrs, sa, rti_info);
			if ( (sa = rti_info[RTAX_IFP]) != NULL) {
				if (sa->sa_family == AF_LINK) {
					sdl = (struct sockaddr_dl *) sa;
					if (sdl->sdl_index == idx) {
						int slen = min(IFNAMSIZ - 1, sdl->sdl_nlen);
						strncpy(name, sdl->sdl_data, slen);
						name[slen] = 0;	/* null terminate */
						free(buf);
						return(name);
					}
				}
			}

		}
	}
	free(buf);
	return(NULL);		/* no match for index */
}
Exemple #9
0
struct sockaddr_in *default_gw()
{
	int mib[6];
    size_t needed;
    char *buf, *next, *lim;
    struct rt_msghdr2 *rtm;
    struct sockaddr *sa;
    struct sockaddr *rti_info[RTAX_MAX];
	struct sockaddr_in *sin;
	bool found = false;
	
    mib[0] = CTL_NET;
    mib[1] = PF_ROUTE;
    mib[2] = 0;
    mib[3] = 0;
    mib[4] = NET_RT_DUMP2;
    mib[5] = 0;
	
    if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) 
	{
		err(1, "sysctl: net.route.0.0.dump estimate");
    }
	
    buf = malloc(needed);
	
    if (buf == 0) 
	{
		err(2, "malloc");
    }
	
    if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) 
	{
		err(1, "sysctl: net.route.0.0.dump");
    }
	
    lim = buf + needed;
	
    for (next = buf; next < lim; next += rtm->rtm_msglen) 
	{
		rtm = (struct rt_msghdr2 *)next;
		sa = (struct sockaddr *)(rtm + 1);
		
		if (sa->sa_family == AF_INET) 
		{
            sin = (struct sockaddr_in *)sa;
			struct sockaddr addr, mask;
			
			get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
			bzero(&addr, sizeof(addr));
			
			if (rtm->rtm_addrs & RTA_DST)
				bcopy(rti_info[RTAX_DST], &addr, rti_info[RTAX_DST]->sa_len);
				
			bzero(&mask, sizeof(mask));
			
			if (rtm->rtm_addrs & RTA_NETMASK)
				bcopy(rti_info[RTAX_NETMASK], &mask, rti_info[RTAX_NETMASK]->sa_len);
			
			if (rtm->rtm_addrs & RTA_GATEWAY &&
				is_default_route(&addr, &mask)) 
			{					
				if (rti_info[RTAX_GATEWAY]) {
					struct sockaddr_in *rti_sin = (struct sockaddr_in *)rti_info[RTAX_GATEWAY];
					sin = (struct sockaddr_in *)(malloc(sizeof(struct sockaddr_in)));
					
					sin->sin_family = rti_sin->sin_family;
					sin->sin_port = rti_sin->sin_port;
					sin->sin_addr.s_addr = rti_sin->sin_addr.s_addr;
					memcpy(sin, rti_info[RTAX_GATEWAY], sizeof(struct sockaddr_in));
					
					found = true;
					break;
				}
			}
		}
		
		rtm = (struct rt_msghdr2 *)next;
    }
	
	free(buf);
	
    return (found ? sin : NULL);
}
Exemple #10
0
void
print_routing(char *proto)
{
	int	mib[6];
	int	i = 0;
	int	rt_len;
	int	if_len;
	int	if_num;
	char	*rt_buf;
	char	*if_buf;
	char	*next;
	char	*lim;
	struct	rt_msghdr *rtm;
	struct	if_msghdr *ifm;
	struct	if_msghdr **ifm_table;
	struct	ifa_msghdr *ifam;
	struct	sockaddr *sa;
	struct	sockaddr *sa1;
	struct	sockaddr *rti_info[RTAX_MAX];
	struct	sockaddr **if_table;
	struct	rt_metrics rm;
	char	fbuf[50];

	/* keep a copy of statistics here for future use */
	static unsigned *base_stats = NULL ;
	static unsigned base_len = 0 ;

	/* Get the routing table */
	mib[0] = CTL_NET;
	mib[1] = PF_ROUTE;
	mib[2] = 0;
	mib[3] = 0;
	mib[4] = NET_RT_DUMP;
	mib[5] = 0;

	/*Estimate the size of table */
	if (sysctl(mib, 6, NULL, &rt_len, NULL, 0) == -1) {
		perror("sysctl size");
		exit(-1);
	}
	if ((rt_buf = (char *)malloc(rt_len)) == NULL) {
		perror("malloc");
		exit(-1);
	}

	/* Now get it. */
	if (sysctl(mib, 6, rt_buf, &rt_len, NULL, 0) == -1) {
		perror("sysctl get");
		exit(-1);
	}

	/* Get the interfaces table */
	mib[0] = CTL_NET;
	mib[1] = PF_ROUTE;
	mib[2] = 0;
	mib[3] = 0;
	mib[4] = NET_RT_IFLIST;
	mib[5] = 0;

	/* Estimate the size of table */
	if (sysctl(mib, 6, NULL, &if_len, NULL, 0) == -1) {
		perror("sysctl size");
		exit(-1);
	}
	if ((if_buf = (char *)malloc(if_len)) == NULL) {
		perror("malloc");
		exit(-1);
	}

	/* Now get it. */
	if (sysctl(mib, 6, if_buf, &if_len, NULL, 0) == -1) {
		perror("sysctl get");
		exit(-1);
	}
	lim = if_buf + if_len;
	i = 0;
	for (next = if_buf, i = 0; next < lim; next += ifm->ifm_msglen) {
		ifm = (struct if_msghdr *)next;
		i++;
	}
	if_num = i;
	if_table = (struct sockaddr **)calloc(i, sizeof(struct sockaddr));
	ifm_table = (struct if_msghdr **)calloc(i, sizeof(struct if_msghdr));
	if (iflag) {
		printf("\nInterface table:\n");
		printf("----------------\n");
		printf("Name  Mtu   Network       Address            "
		    "Ipkts Ierrs    Opkts Oerrs  Coll\n");
	}
        /* scan the list and store base values */
	i = 0 ;
	for (next = if_buf; next < lim; next += ifm->ifm_msglen) {
		ifm = (struct if_msghdr *)next;
		i++ ;
	}
	if (base_stats == NULL || i != base_len) {
		base_stats = calloc(i*5, sizeof(unsigned));
		base_len = i ;
	}
	i = 0;
	for (next = if_buf; next < lim; next += ifm->ifm_msglen) {
		ifm = (struct if_msghdr *)next;
		if_table[i] = (struct sockaddr *)(ifm + 1);
		ifm_table[i] = ifm;

		sa = if_table[i];
		if (iflag && sa->sa_family == AF_LINK) {
			struct	sockaddr_dl *sdl = (struct sockaddr_dl *)sa;
			unsigned *bp = &base_stats[i*5];

			printf("%-4s  %-5d <Link>   ",
			    sock_ntop(if_table[i], if_table[i]->sa_len),
			    ifm->ifm_data.ifi_mtu);
			if (sdl->sdl_alen == 6) {
				unsigned char *p =
				    sdl->sdl_data + sdl->sdl_nlen;
				printf("%02x:%02x:%02x:%02x:%02x:%02x   ",
				    p[0], p[1], p[2], p[3], p[4], p[5]);
			} else
				printf("                    ");
			printf("%9d%6d%9d%6d%6d\n",
			    ifm->ifm_data.ifi_ipackets - bp[0],
			    ifm->ifm_data.ifi_ierrors - bp[1],
			    ifm->ifm_data.ifi_opackets - bp[2],
			    ifm->ifm_data.ifi_oerrors - bp[3],
			    ifm->ifm_data.ifi_collisions -bp[4]);
			if (delta > 0) {
			    bp[0] = ifm->ifm_data.ifi_ipackets ;
			    bp[1] = ifm->ifm_data.ifi_ierrors ;
			    bp[2] = ifm->ifm_data.ifi_opackets ;
			    bp[3] = ifm->ifm_data.ifi_oerrors ;
			    bp[4] = ifm->ifm_data.ifi_collisions ;
			}
		}
		i++;
	}
	if (!rflag) {
		free(rt_buf);
		free(if_buf);
		free(if_table);
		free(ifm_table);
		return;
	}

	/* Now dump the routing table */
	printf("\nRouting table:\n");
	printf("--------------\n");
	printf
	    ("Destination        Gateway            Flags       Netif  Use\n");
	lim = rt_buf + rt_len;
	for (next = rt_buf; next < lim; next += rtm->rtm_msglen) {
		rtm = (struct rt_msghdr *)next;
		sa = (struct sockaddr *)(rtm + 1);
		get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
		if ((sa = rti_info[RTAX_DST]) != NULL) {
			sprintf(fbuf, "%s", sock_ntop(sa, sa->sa_len));
			if (((sa1 = rti_info[RTAX_NETMASK]) != NULL)
			    && sa1->sa_family == 255) {
				strcat(fbuf, sock_ntop(sa1, sa1->sa_len));
			}
			printf("%-19s", fbuf);
		}
		if ((sa = rti_info[RTAX_GATEWAY]) != NULL) {
			printf("%-19s", sock_ntop(sa, sa->sa_len));
		}
		memset(fbuf, 0, sizeof(fbuf));
		get_flags(fbuf, rtm->rtm_flags);
		printf("%-10s", fbuf);
		for (i = 0; i < if_num; i++) {
			ifm = ifm_table[i];
			if ((ifm->ifm_index == rtm->rtm_index) &&
			    (ifm->ifm_data.ifi_type > 0)) {
				sa = if_table[i];
				break;
			}
		}
		if (ifm->ifm_type == RTM_IFINFO) {
			get_rtaddrs(ifm->ifm_addrs, sa, rti_info);
			printf("  %s", Sock_ntop(sa, sa->sa_len));
		} else if (ifm->ifm_type == RTM_NEWADDR) {
			ifam =
			    (struct ifa_msghdr *)ifm_table[rtm->rtm_index - 1];
			sa = (struct sockaddr *)(ifam + 1);
			get_rtaddrs(ifam->ifam_addrs, sa, rti_info);
			printf("  %s", Sock_ntop(sa, sa->sa_len));
		}
		/* printf("    %u", rtm->rtm_use); */
		printf("\n");
	}
	free(rt_buf);
	free(if_buf);
	free(if_table);
	free(ifm_table);
}
Exemple #11
0
int
fetchifs(int ifindex)
{
	size_t			 len;
	int			 mib[6];
	char			*buf, *next, *lim;
	struct if_msghdr	 ifm;
	struct kif_node		*kif;
	struct sockaddr		*sa, *rti_info[RTAX_MAX];
	struct sockaddr_dl	*sdl;

	mib[0] = CTL_NET;
	mib[1] = AF_ROUTE;
	mib[2] = 0;
	mib[3] = AF_INET;
	mib[4] = NET_RT_IFLIST;
	mib[5] = ifindex;

	if (sysctl(mib, 6, NULL, &len, NULL, 0) == -1) {
		log_warn("sysctl");
		return (-1);
	}
	if ((buf = malloc(len)) == NULL) {
		log_warn("fetchif");
		return (-1);
	}
	if (sysctl(mib, 6, buf, &len, NULL, 0) == -1) {
		log_warn("sysctl");
		free(buf);
		return (-1);
	}

	lim = buf + len;
	for (next = buf; next < lim; next += ifm.ifm_msglen) {
		memcpy(&ifm, next, sizeof(ifm));
		if (ifm.ifm_version != RTM_VERSION)
			continue;
		if (ifm.ifm_type != RTM_IFINFO)
			continue;

		sa = (struct sockaddr *)(next + sizeof(ifm));
		get_rtaddrs(ifm.ifm_addrs, sa, rti_info);

		if ((kif = calloc(1, sizeof(struct kif_node))) == NULL) {
			log_warn("fetchifs");
			free(buf);
			return (-1);
		}

		kif->k.ifindex = ifm.ifm_index;
		kif->k.flags = ifm.ifm_flags;
		kif->k.link_state = ifm.ifm_data.ifi_link_state;
		kif->k.media_type = ifm.ifm_data.ifi_type;
		kif->k.baudrate = ifm.ifm_data.ifi_baudrate;
		kif->k.mtu = ifm.ifm_data.ifi_mtu;
		if ((sa = rti_info[RTAX_IFP]) != NULL)
			if (sa->sa_family == AF_LINK) {
				sdl = (struct sockaddr_dl *)sa;
				if (sdl->sdl_nlen >= sizeof(kif->k.ifname))
					memcpy(kif->k.ifname, sdl->sdl_data,
					    sizeof(kif->k.ifname) - 1);
				else if (sdl->sdl_nlen > 0)
					memcpy(kif->k.ifname, sdl->sdl_data,
					    sdl->sdl_nlen);
				/* string already terminated via calloc() */
			}
		kif_insert(kif);
	}
	free(buf);
	return (0);
}
Exemple #12
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);
}
Exemple #13
0
void
refresh_netif_metrics(void)
{
    int			sts;
    static int		name[] = { CTL_NET, AF_ROUTE, 0, 0, NET_RT_IFLIST, 0 };
    u_int		namelen = sizeof(name) / sizeof(name[0]);
    static size_t	buflen = 0;
    static char		*buf = NULL;
    char		*bufend;
    char		*next;
    size_t		new_buflen;
    struct rt_msghdr	*rtm;
    struct if_msghdr	*ifm;
    struct if_data	*ifd = NULL;
    struct sockaddr	*sa;
    struct sockaddr	*rti_info[RTAX_MAX];
    struct sockaddr_dl	*sdl;
    char		if_name[IF_NAMESIZE];

    if (valid == -1) {
	/* one-trip reload */
	pmdaCacheOp(indomtab[NETIF_INDOM].it_indom, PMDA_CACHE_LOAD);
    }
    else {
	/*
	 * Not sure that the order of chained netif structs is invariant,
	 * especially if interfaces are added to the configuration after
	 * initial system boot ... so mark all the instances as inactive
	 * and re-match based on the interface name
	 */
	pmdaCacheOp(indomtab[NETIF_INDOM].it_indom, PMDA_CACHE_INACTIVE);
    }

    valid = 0;

    /* get number of if_data structs available */
    if ((sts = sysctl(name, namelen, NULL, &new_buflen, NULL, 0)) != 0) {
	fprintf(stderr, "refresh_netif_metrics: new_buflen sysctl(): %s\n", strerror(errno));
	return;
    }
    if (new_buflen != buflen) {
	/*
	 * one trip ... not sure if it can change thereafter, but just
	 * in case
	 */
	if (buf != NULL)
	    free(buf);
	buf = (char *)malloc(new_buflen);
	if (buf == NULL) {
	    __pmNoMem("refresh_disk_metrics: stats", new_buflen, PM_FATAL_ERR);
	    /* NOTREACHED */
	}
	buflen = new_buflen;
    }
    if ((sts = sysctl(name, namelen, buf, &buflen, NULL, 0)) != 0) {
	fprintf(stderr, "refresh_netif_metrics: buf sysctl(): %s\n", strerror(errno));
	return;
    }

    bufend = buf + buflen;
    for (next = buf; next < bufend; next += rtm->rtm_msglen) {
	rtm = (struct rt_msghdr *)next;
	if (rtm->rtm_version != RTM_VERSION)
	    continue;
	switch (rtm->rtm_type) {
	case RTM_IFINFO:
	    ifm = (struct if_msghdr *)next;
	    ifd = &ifm->ifm_data;
	    sa = (struct sockaddr *)(ifm + 1);
	    get_rtaddrs(ifm->ifm_addrs, sa, rti_info);
	    sdl = (struct sockaddr_dl *)rti_info[RTAX_IFP];
	    if (sdl == NULL || sdl->sdl_family != AF_LINK)
		continue;
	    if (sdl->sdl_nlen < IF_NAMESIZE) {
		memcpy(if_name, sdl->sdl_data, sdl->sdl_nlen);
		if_name[sdl->sdl_nlen] = '\0';
	    }
	    else {
		memcpy(if_name, sdl->sdl_data, IF_NAMESIZE-1);
		if_name[IF_NAMESIZE-1] = '\0';
	    }
	    /* skip network interfaces that are not interesting ...  */
	    if (strcmp(if_name, "lo0") == 0)
		continue;
#ifdef PCP_DEBUG
	    if (pmDebug & DBG_TRACE_APPL0) {
		sts = pmdaCacheLookupName(indomtab[NETIF_INDOM].it_indom, if_name, NULL, NULL);
		if (sts < 0)
		    fprintf(stderr, "Info: found network interface %s\n", if_name);
	    }
#endif
	    if ((sts = pmdaCacheStore(indomtab[NETIF_INDOM].it_indom, PMDA_CACHE_ADD, if_name, (void *)ifm)) < 0) {
		fprintf(stderr, "refresh_netif_metrics: pmdaCacheStore(%s) failed: %s\n", if_name, pmErrStr(sts));
		continue;
	    }
	    valid++;
	    break;
	}
    }
    if (valid)
	pmdaCacheOp(indomtab[NETIF_INDOM].it_indom, PMDA_CACHE_SAVE);
}
Exemple #14
0
static void
fetchifs(void)
{
	struct if_msghdr ifm;
	int mib[6] = { CTL_NET, AF_ROUTE, 0, 0, NET_RT_IFLIST, 0 };
	struct rt_msghdr *rtm;
	struct if_data *ifd;
	struct sockaddr *sa, *rti_info[RTAX_MAX];
	struct sockaddr_dl *sdl;
	char *buf, *next, *lim;
	char name[IFNAMSIZ];
	size_t len;
	int takeit = 0;
	int foundone = 0;

	if (sysctl(mib, 6, NULL, &len, NULL, 0) == -1)
		err(1, "sysctl");
	if ((buf = malloc(len)) == NULL)
		err(1, NULL);
	if (sysctl(mib, 6, buf, &len, NULL, 0) == -1)
		err(1, "sysctl");

	memset(&ip_cur, 0, sizeof(ip_cur));
	lim = buf + len;
	for (next = buf; next < lim; next += rtm->rtm_msglen) {
		rtm = (struct rt_msghdr *)next;
		if (rtm->rtm_version != RTM_VERSION)
			continue;
		switch (rtm->rtm_type) {
		case RTM_IFINFO:
			bcopy(next, &ifm, sizeof ifm);
			ifd = &ifm.ifm_data;

			sa = (struct sockaddr *)(next + rtm->rtm_hdrlen);
			get_rtaddrs(ifm.ifm_addrs, sa, rti_info);

			sdl = (struct sockaddr_dl *)rti_info[RTAX_IFP];
			if (sdl == NULL || sdl->sdl_family != AF_LINK)
				continue;
			bzero(name, sizeof(name));
			if (sdl->sdl_nlen >= IFNAMSIZ)
				memcpy(name, sdl->sdl_data, IFNAMSIZ - 1);
			else if (sdl->sdl_nlen > 0) 
				memcpy(name, sdl->sdl_data, sdl->sdl_nlen);

			if (interface != NULL && !strcmp(name, interface)) {
				takeit = 1;
			} else if (interface == NULL && foundone == 0 &&
			    isegress(name)) {
				takeit = 1;
				foundone = 1;
			} else
				takeit = 0;
			if (takeit) {
				strlcpy(ip_cur.ift_name, name,
				    sizeof(ip_cur.ift_name));
				ip_cur.ift_ip = ifd->ifi_ipackets;
				ip_cur.ift_ib = ifd->ifi_ibytes;
				ip_cur.ift_ie = ifd->ifi_ierrors;
				ip_cur.ift_op = ifd->ifi_opackets;
				ip_cur.ift_ob = ifd->ifi_obytes;
				ip_cur.ift_oe = ifd->ifi_oerrors;
				ip_cur.ift_co = ifd->ifi_collisions;
				ip_cur.ift_dr = 0;
				    /* XXX ifnet.if_snd.ifq_drops */
			}

			sum_cur.ift_ip += ifd->ifi_ipackets;
			sum_cur.ift_ib += ifd->ifi_ibytes;
			sum_cur.ift_ie += ifd->ifi_ierrors;
			sum_cur.ift_op += ifd->ifi_opackets;
			sum_cur.ift_ob += ifd->ifi_obytes;
			sum_cur.ift_oe += ifd->ifi_oerrors;
			sum_cur.ift_co += ifd->ifi_collisions;
			sum_cur.ift_dr += 0; /* XXX ifnet.if_snd.ifq_drops */
			break;
		}
	}
	if (interface == NULL && foundone == 0) {
		strlcpy(ip_cur.ift_name, name,
		    sizeof(ip_cur.ift_name));
		ip_cur.ift_ip = ifd->ifi_ipackets;
		ip_cur.ift_ib = ifd->ifi_ibytes;
		ip_cur.ift_ie = ifd->ifi_ierrors;
		ip_cur.ift_op = ifd->ifi_opackets;
		ip_cur.ift_ob = ifd->ifi_obytes;
		ip_cur.ift_oe = ifd->ifi_oerrors;
		ip_cur.ift_co = ifd->ifi_collisions;
		ip_cur.ift_dr = 0;
		    /* XXX ifnet.if_snd.ifq_drops */
	}
	free(buf);
}
Exemple #15
0
/*
 * Print a description of the network interfaces.
 * NOTE: ifnetaddr is the location of the kernel global "ifnet",
 * which is a TAILQ_HEAD.
 */
void
intpr(int interval, int repeatcount)
{
	struct if_msghdr ifm;
	int mib[6] = { CTL_NET, AF_ROUTE, 0, 0, NET_RT_IFLIST, 0 };
	char name[IFNAMSIZ + 1];	/* + 1 for the '*' */
	char *buf, *next, *lim, *cp;
	struct rt_msghdr *rtm;
	struct ifa_msghdr *ifam;
	struct if_data *ifd;
	struct sockaddr *sa, *rti_info[RTAX_MAX];
	struct sockaddr_dl *sdl;
	u_int64_t total = 0;
	size_t len;

	if (interval) {
		sidewaysintpr((unsigned)interval, repeatcount);
		return;
	}

	if (sysctl(mib, 6, NULL, &len, NULL, 0) == -1)
		err(1, "sysctl");
	if ((buf = malloc(len)) == NULL)
		err(1, NULL);
	if (sysctl(mib, 6, buf, &len, NULL, 0) == -1)
		err(1, "sysctl");

	printf("%-7.7s %-5.5s %-11.11s %-17.17s ",
	    "Name", "Mtu", "Network", "Address");
	if (bflag)
		printf("%10.10s %10.10s", "Ibytes", "Obytes");
	else
		printf("%8.8s %5.5s %8.8s %5.5s %5.5s",
		    "Ipkts", "Ierrs", "Opkts", "Oerrs", "Colls");
	if (tflag)
		printf(" %s", "Time");
	if (dflag)
		printf(" %s", "Drop");
	putchar('\n');

	lim = buf + len;
	for (next = buf; next < lim; next += rtm->rtm_msglen) {
		rtm = (struct rt_msghdr *)next;
		if (rtm->rtm_version != RTM_VERSION)
			continue;
		switch (rtm->rtm_type) {
		case RTM_IFINFO:
			total = 0;
			bcopy(next, &ifm, sizeof ifm);
			ifd = &ifm.ifm_data;

			sa = (struct sockaddr *)(next + rtm->rtm_hdrlen);
			get_rtaddrs(ifm.ifm_addrs, sa, rti_info);

			sdl = (struct sockaddr_dl *)rti_info[RTAX_IFP];
			if (sdl == NULL || sdl->sdl_family != AF_LINK)
				continue;
			bzero(name, sizeof(name));
			if (sdl->sdl_nlen >= IFNAMSIZ)
				memcpy(name, sdl->sdl_data, IFNAMSIZ - 1);
			else if (sdl->sdl_nlen > 0) 
				memcpy(name, sdl->sdl_data, sdl->sdl_nlen);

			if (interface != 0 && strcmp(name, interface) != 0)
				continue;

			/* mark inactive interfaces with a '*' */
			cp = strchr(name, '\0');
			if ((ifm.ifm_flags & IFF_UP) == 0)
				*cp++ = '*';
			*cp = '\0';

			if (qflag) {
				total = ifd->ifi_ibytes + ifd->ifi_obytes +
				    ifd->ifi_ipackets + ifd->ifi_ierrors +
				    ifd->ifi_opackets + ifd->ifi_oerrors +
				    ifd->ifi_collisions;
				if (tflag)
					total += 0; // XXX ifnet.if_timer;
				if (dflag)
					total += 0; // XXX ifnet.if_snd.ifq_drops;
				if (total == 0)
					continue;
			}

			printf("%-7s %-5d ", name, ifd->ifi_mtu);
			print_addr(rti_info[RTAX_IFP], rti_info, ifd);
			break;
		case RTM_NEWADDR:
			if (qflag && total == 0)
				continue;
			if (interface != 0 && strcmp(name, interface) != 0)
				continue;

			ifam = (struct ifa_msghdr *)next;
			if ((ifam->ifam_addrs & (RTA_NETMASK | RTA_IFA |
			    RTA_BRD)) == 0)
				break;

			sa = (struct sockaddr *)(next + rtm->rtm_hdrlen);
			get_rtaddrs(ifam->ifam_addrs, sa, rti_info);

			printf("%-7s %-5d ", name, ifd->ifi_mtu);
			print_addr(rti_info[RTAX_IFA], rti_info, ifd);
			break;
		}
	}
	free(buf);
}
Exemple #16
0
/* include get_ifi_info1 */
struct ifi_info *
get_ifi_info(int family, int doaliases)
{
  int         flags;
  char        *buf, *next, *lim;
  size_t        len;
  struct if_msghdr  *ifm;
  struct ifa_msghdr *ifam;
  struct sockaddr   *sa, *rti_info[RTAX_MAX];
  struct sockaddr_dl  *sdl;
  struct ifi_info   *ifi, *ifisave, *ifihead, **ifipnext;

  buf = Net_rt_iflist(family, 0, &len);

  ifihead = NULL;
  ifipnext = &ifihead;

  lim = buf + len;
  for (next = buf; next < lim; next += ifm->ifm_msglen) {
    ifm = (struct if_msghdr *) next;
    if (ifm->ifm_type == RTM_IFINFO) {
      if ( ((flags = ifm->ifm_flags) & IFF_UP) == 0)
        continue; /* ignore if interface not up */

      sa = (struct sockaddr *) (ifm + 1);
      get_rtaddrs(ifm->ifm_addrs, sa, rti_info);
      if ( (sa = rti_info[RTAX_IFP]) != NULL) {
        ifi = Calloc(1, sizeof(struct ifi_info));
        *ifipnext = ifi;      /* prev points to this new one */
        ifipnext = &ifi->ifi_next;  /* ptr to next one goes here */

        ifi->ifi_flags = flags;
        if (sa->sa_family == AF_LINK) {
          sdl = (struct sockaddr_dl *) sa;
          ifi->ifi_index = sdl->sdl_index;
          if (sdl->sdl_nlen > 0)
            snprintf(ifi->ifi_name, IFI_NAME, "%*s",
                 sdl->sdl_nlen, &sdl->sdl_data[0]);
          else
            snprintf(ifi->ifi_name, IFI_NAME, "index %d",
                 sdl->sdl_index);

          if ( (ifi->ifi_hlen = sdl->sdl_alen) > 0)
            memcpy(ifi->ifi_haddr, LLADDR(sdl),
                 min(IFI_HADDR, sdl->sdl_alen));
        }
      }
/* end get_ifi_info1 */

/* include get_ifi_info3 */
    } else if (ifm->ifm_type == RTM_NEWADDR) {
      if (ifi->ifi_addr) {  /* already have an IP addr for i/f */
        if (doaliases == 0)
          continue;

          /* 4we have a new IP addr for existing interface */
        ifisave = ifi;
        ifi = Calloc(1, sizeof(struct ifi_info));
        *ifipnext = ifi;      /* prev points to this new one */
        ifipnext = &ifi->ifi_next;  /* ptr to next one goes here */
        ifi->ifi_flags = ifisave->ifi_flags;
        ifi->ifi_index = ifisave->ifi_index;
        ifi->ifi_hlen = ifisave->ifi_hlen;
        memcpy(ifi->ifi_name, ifisave->ifi_name, IFI_NAME);
        memcpy(ifi->ifi_haddr, ifisave->ifi_haddr, IFI_HADDR);
      }

      ifam = (struct ifa_msghdr *) next;
      sa = (struct sockaddr *) (ifam + 1);
      get_rtaddrs(ifam->ifam_addrs, sa, rti_info);

      if ( (sa = rti_info[RTAX_IFA]) != NULL) {
        ifi->ifi_addr = Calloc(1, sa->sa_len);
        memcpy(ifi->ifi_addr, sa, sa->sa_len);
      }

      if ((flags & IFF_BROADCAST) &&
        (sa = rti_info[RTAX_BRD]) != NULL) {
        ifi->ifi_brdaddr = Calloc(1, sa->sa_len);
        memcpy(ifi->ifi_brdaddr, sa, sa->sa_len);
      }

      if ((flags & IFF_POINTOPOINT) &&
        (sa = rti_info[RTAX_BRD]) != NULL) {
        ifi->ifi_dstaddr = Calloc(1, sa->sa_len);
        memcpy(ifi->ifi_dstaddr, sa, sa->sa_len);
      }

    } else
      err_quit("unexpected message type %d", ifm->ifm_type);
  }
  /* "ifihead" points to the first structure in the linked list */
  return(ifihead);  /* ptr to first structure in linked list */
}
Exemple #17
0
struct ifinfo *
update_ifinfo(struct ifilist_head_t *ifi_head, int ifindex)
{
	struct if_msghdr *ifm;
	struct ifinfo *ifi = NULL;
	struct sockaddr *sa;
	struct sockaddr *rti_info[RTAX_MAX];
	char *msg;
	size_t len;
	char *lim;
	int mib[] = { CTL_NET, PF_ROUTE, 0, AF_INET6, NET_RT_IFLIST, 0 };
	int error;

	syslog(LOG_DEBUG, "<%s> enter", __func__);

	if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), NULL, &len, NULL, 0) <
	    0) {
		syslog(LOG_ERR,
		    "<%s> sysctl: NET_RT_IFLIST size get failed", __func__);
		exit(1);
	}
	if ((msg = malloc(len)) == NULL) {
		syslog(LOG_ERR, "<%s> malloc failed", __func__);
		exit(1);
	}
	if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), msg, &len, NULL, 0) <
	    0) {
		syslog(LOG_ERR,
		    "<%s> sysctl: NET_RT_IFLIST get failed", __func__);
		exit(1);
	}

	lim = msg + len;
	for (ifm = (struct if_msghdr *)msg;
	     ifm != NULL && ifm < (struct if_msghdr *)lim;
	     ifm = get_next_msghdr(ifm,(struct if_msghdr *)lim)) {
		int ifi_new;

		syslog(LOG_DEBUG, "<%s> ifm = %p, lim = %p, diff = %zu",
		    __func__, ifm, lim, (char *)lim - (char *)ifm);

		if (ifm->ifm_version != RTM_VERSION) {
			syslog(LOG_ERR,
			    "<%s> ifm_vesrion mismatch", __func__);
			exit(1);
		}
		if (ifm->ifm_msglen == 0) {
			syslog(LOG_WARNING,
			    "<%s> ifm_msglen is 0", __func__);
			free(msg);
			return (NULL);
		}

		ifi_new = 0;
		if (ifm->ifm_type == RTM_IFINFO) {
			struct ifreq ifr;
			int s;
			char ifname[IFNAMSIZ];

			syslog(LOG_DEBUG, "<%s> RTM_IFINFO found. "
			    "ifm_index = %d, ifindex = %d",
			    __func__, ifm->ifm_index, ifindex);

			/* when ifindex is specified */
			if (ifindex != UPDATE_IFINFO_ALL &&
			    ifindex != ifm->ifm_index)
				continue;

			/* ifname */
			if (if_indextoname(ifm->ifm_index, ifname) == NULL) {
				syslog(LOG_WARNING,
				    "<%s> ifname not found (idx=%d)",
				    __func__, ifm->ifm_index);
				continue;
			}

			/* lookup an entry with the same ifindex */
			TAILQ_FOREACH(ifi, ifi_head, ifi_next) {
				if (ifm->ifm_index == ifi->ifi_ifindex)
					break;
				if (strncmp(ifname, ifi->ifi_ifname,
					sizeof(ifname)) == 0)
					break;
			}
			if (ifi == NULL) {
				syslog(LOG_DEBUG,
				    "<%s> new entry for idx=%d",
				    __func__, ifm->ifm_index);
				ELM_MALLOC(ifi, exit(1));
				ifi->ifi_rainfo = NULL;
				ifi->ifi_state = IFI_STATE_UNCONFIGURED;
				ifi->ifi_persist = 0;
				ifi_new = 1;
			}
			/* ifindex */
			ifi->ifi_ifindex = ifm->ifm_index;

			/* ifname */
			strlcpy(ifi->ifi_ifname, ifname, IFNAMSIZ);

			if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
				syslog(LOG_ERR,
				    "<%s> socket() failed.", __func__);
				if (ifi_new)
					free(ifi);
				continue;
			}

			/* MTU  */
			ifi->ifi_phymtu = ifm->ifm_data.ifi_mtu;
			if (ifi->ifi_phymtu == 0) {
				memset(&ifr, 0, sizeof(ifr));
				ifr.ifr_addr.sa_family = AF_INET6;
				strlcpy(ifr.ifr_name, ifi->ifi_ifname,
				    sizeof(ifr.ifr_name));
				error = ioctl(s, SIOCGIFMTU, (caddr_t)&ifr);
				if (error) {
					close(s);
					syslog(LOG_ERR,
					    "<%s> ioctl() failed.",
					    __func__);
					if (ifi_new)
						free(ifi);
					continue;
				}
				ifi->ifi_phymtu = ifr.ifr_mtu;
				if (ifi->ifi_phymtu == 0) {
					syslog(LOG_WARNING,
					    "<%s> no interface mtu info"
					    " on %s.  %d will be used.",
					    __func__, ifi->ifi_ifname,
					    IPV6_MMTU);
					ifi->ifi_phymtu = IPV6_MMTU;
				}
			}
			close(s);

			/* ND flags */
			error = update_ifinfo_nd_flags(ifi);
			if (error) {
				if (ifi_new)
					free(ifi);
				continue;
			}

			/* SDL */
			sa = (struct sockaddr *)(ifm + 1);
			get_rtaddrs(ifm->ifm_addrs, sa, rti_info);
			if ((sa = rti_info[RTAX_IFP]) != NULL) {
				if (sa->sa_family == AF_LINK) {
					memcpy(&ifi->ifi_sdl,
					    (struct sockaddr_dl *)sa,
					    sizeof(ifi->ifi_sdl));
				}
			} else
				memset(&ifi->ifi_sdl, 0,
				    sizeof(ifi->ifi_sdl));

			/* flags */
			ifi->ifi_flags = ifm->ifm_flags;

			/* type */
			ifi->ifi_type = ifm->ifm_type;
		} else {
			syslog(LOG_ERR,
			    "out of sync parsing NET_RT_IFLIST\n"
			    "expected %d, got %d\n msglen = %d\n",
			    RTM_IFINFO, ifm->ifm_type, ifm->ifm_msglen);
			exit(1);
		}

		if (ifi_new) {
			syslog(LOG_DEBUG,
			    "<%s> adding %s(idx=%d) to ifilist",
			    __func__, ifi->ifi_ifname, ifi->ifi_ifindex);
			TAILQ_INSERT_TAIL(ifi_head, ifi, ifi_next);
		}
	}
Exemple #18
0
char *
get_next_msg(char *buf, char *lim, size_t *lenp)
{
	struct rt_msghdr *rtm;
	struct ifa_msghdr *ifam;
	struct sockaddr *sa, *dst, *ifa, *rti_info[RTAX_MAX];

	*lenp = 0;
	for (rtm = (struct rt_msghdr *)buf;
	     rtm < (struct rt_msghdr *)lim;
	     rtm = (struct rt_msghdr *)((char *)rtm + rtm->rtm_msglen)) {
		/* just for safety */
		if (!rtm->rtm_msglen) {
			log_warnx("rtm_msglen is 0 (buf=%p lim=%p rtm=%p)",
			    buf, lim, rtm);
			break;
		}
		if (rtm->rtm_version != RTM_VERSION)
			continue;

		switch (rtm->rtm_type) {
		case RTM_ADD:
		case RTM_DELETE:
			if (rtm->rtm_tableid != 0)
				continue;

			/* address related checks */
			sa = (struct sockaddr *)((char *)rtm + rtm->rtm_hdrlen);
			get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
			if ((dst = rti_info[RTAX_DST]) == NULL ||
			    dst->sa_family != AF_INET6)
				continue;

			if (IN6_IS_ADDR_LINKLOCAL(&SIN6(dst)->sin6_addr) ||
			    IN6_IS_ADDR_MULTICAST(&SIN6(dst)->sin6_addr))
				continue;

			if (rti_info[RTAX_NETMASK] == NULL)
				continue;

			/* found */
			*lenp = rtm->rtm_msglen;
			return (char *)rtm;
			/* NOTREACHED */
		case RTM_NEWADDR:
		case RTM_DELADDR:
			ifam = (struct ifa_msghdr *)rtm;

			/* address related checks */
			sa = (struct sockaddr *)((char *)rtm + rtm->rtm_hdrlen);
			get_rtaddrs(ifam->ifam_addrs, sa, rti_info);
			if ((ifa = rti_info[RTAX_IFA]) == NULL ||
			    (ifa->sa_family != AF_INET &&
			     ifa->sa_family != AF_INET6))
				continue;

			if (ifa->sa_family == AF_INET6 &&
			    (IN6_IS_ADDR_LINKLOCAL(&SIN6(ifa)->sin6_addr) ||
			     IN6_IS_ADDR_MULTICAST(&SIN6(ifa)->sin6_addr)))
				continue;

			/* found */
			*lenp = rtm->rtm_msglen;
			return (char *)rtm;
			/* NOTREACHED */
		case RTM_IFINFO:
			/* found */
			*lenp = rtm->rtm_msglen;
			return (char *)rtm;
			/* NOTREACHED */
		}
	}

	return (char *)rtm;
}
Exemple #19
0
static void np_rtentry(struct rt_msghdr* rtm)
{
    char ifname[IFNAMSIZ + 1];
    struct sockaddr *rti_info[RTAX_MAX];
    struct sockaddr_in* dest = NULL;
    struct sockaddr_in* mask = NULL;
	struct sockaddr* sa;
    char flags[33];
    char* bp = flags;
    char rbuf[18];
	char workbuf[20];
	int len;

	sa = (struct sockaddr*)(rtm + 1);
    if (sa->sa_family != AF_INET)
    	return;

    if (rtm->rtm_flags & RTF_UP)
    	*bp++ = 'U';
    if (rtm->rtm_flags & RTF_GATEWAY)
		*bp++ = 'G';
    if (rtm->rtm_flags & RTF_HOST)
		*bp++ = 'H';
    if (rtm->rtm_flags & RTF_STATIC)
		*bp++ = 'S';
    if (bp == flags)
		return;
    *bp = '\0';

    get_rtaddrs(rtm->rtm_addrs, sa, rti_info);

    if ((rtm->rtm_addrs & RTA_DST) &&
		    rti_info[RTAX_DST]->sa_family == AF_INET) {
		dest = (struct sockaddr_in*)rti_info[RTAX_DST];
    }

    if ((rtm->rtm_addrs & RTA_NETMASK) &&
            rti_info[RTAX_NETMASK]->sa_len != 0) {
        mask = (struct sockaddr_in*)rti_info[RTAX_NETMASK];
    }

	memset(workbuf, 0, sizeof(workbuf));
    if (rtm->rtm_addrs & RTA_GATEWAY) {
		len = so_getnameinfo(rti_info[RTAX_GATEWAY], rti_info[RTAX_GATEWAY]->sa_len,
							 workbuf, sizeof(workbuf), NULL, 0, NI_NUMERICHOST, NULL);
		if (len < 0) {
			strcpy(workbuf, "invalid");
		}
    }

    so_ifindextoname(rtm->rtm_index, ifname);

    printf("%-16s ", dest != NULL ? inet_ntop(AF_INET, &dest->sin_addr, rbuf, sizeof(rbuf)) : "-");
    printf("%-16s ", mask != NULL ? inet_ntop(AF_INET, &mask->sin_addr, rbuf, sizeof(rbuf)) : "-");
    printf("%-18s ", workbuf[0] != '\0' ? workbuf : "-");
    printf(" %-8s ", flags);
    printf(" %-6s ", ifname);
    printf(" %d ", rtm->rtm_index);

    printf("\n");
}
Exemple #20
0
char *
get_next_msg(char *buf, char *lim, int ifindex, size_t *lenp, int filter)
{
	struct rt_msghdr *rtm;
	struct ifa_msghdr *ifam;
	struct sockaddr *sa, *dst, *gw, *ifa, *rti_info[RTAX_MAX];

	*lenp = 0;
	for (rtm = (struct rt_msghdr *)buf;
	     rtm < (struct rt_msghdr *)lim;
	     rtm = (struct rt_msghdr *)(((char *)rtm) + rtm->rtm_msglen)) {
		/* just for safety */
		if (!rtm->rtm_msglen) {
			syslog(LOG_WARNING, "<%s> rtm_msglen is 0 "
			    "(buf=%p lim=%p rtm=%p)", __func__,
			    buf, lim, rtm);
			break;
		}
		if (((struct rt_msghdr *)buf)->rtm_version != RTM_VERSION) {
			syslog(LOG_WARNING,
			    "<%s> routing message version mismatch "
			    "(buf=%p lim=%p rtm=%p)", __func__,
			    buf, lim, rtm);
			continue;
		}

		if (FILTER_MATCH(rtm->rtm_type, filter) == 0)
			continue;

		switch (rtm->rtm_type) {
		case RTM_GET:
		case RTM_ADD:
		case RTM_DELETE:
			/* address related checks */
			sa = (struct sockaddr *)(rtm + 1);
			get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
			if ((dst = rti_info[RTAX_DST]) == NULL ||
			    dst->sa_family != AF_INET6)
				continue;

			if (IN6_IS_ADDR_LINKLOCAL(&SIN6(dst)->sin6_addr) ||
			    IN6_IS_ADDR_MULTICAST(&SIN6(dst)->sin6_addr))
				continue;

			if ((gw = rti_info[RTAX_GATEWAY]) == NULL ||
			    gw->sa_family != AF_LINK)
				continue;
			if (ifindex && SDL(gw)->sdl_index != ifindex)
				continue;

			if (rti_info[RTAX_NETMASK] == NULL)
				continue;

			/* found */
			*lenp = rtm->rtm_msglen;
			return (char *)rtm;
			/* NOTREACHED */
		case RTM_NEWADDR:
		case RTM_DELADDR:
			ifam = (struct ifa_msghdr *)rtm;

			/* address related checks */
			sa = (struct sockaddr *)(ifam + 1);
			get_rtaddrs(ifam->ifam_addrs, sa, rti_info);
			if ((ifa = rti_info[RTAX_IFA]) == NULL ||
			    (ifa->sa_family != AF_INET &&
			     ifa->sa_family != AF_INET6))
				continue;

			if (ifa->sa_family == AF_INET6 &&
			    (IN6_IS_ADDR_LINKLOCAL(&SIN6(ifa)->sin6_addr) ||
			     IN6_IS_ADDR_MULTICAST(&SIN6(ifa)->sin6_addr)))
				continue;

			if (ifindex && ifam->ifam_index != ifindex)
				continue;

			/* found */
			*lenp = ifam->ifam_msglen;
			return (char *)rtm;
			/* NOTREACHED */
		case RTM_IFINFO:
		case RTM_IFANNOUNCE:
			/* found */
			*lenp = rtm->rtm_msglen;
			return (char *)rtm;
			/* NOTREACHED */
		}
	}

	return ((char *)rtm);
}
Exemple #21
0
// function used to configure a route to "daddr" by specifying either
// the gateway address "gaddr" or the interface name "ifname"; 
// a mask given by "maddr" can also be specified
// the command codes "cmd" indicate the type of operation
// Note: addresses are given as 4-byte words (c.f. rtctl)
int rtctl2(uint32_t *daddr,	/* destination IP address */
	   uint32_t *gaddr,	/* gateway IP address */
	   uint32_t *maddr,	/* subnet mask */
	   char *ifname,	/* network interface name */
	   u_char cmd)		/* RTM_ADD RTM_DELETE RTM_CHANGE */
{
  int sockfd, mib[6], len;
  char *buf, rta_cmd[RTCTL_CMD_LEN], *ifbuf;
  char dstaddr[16], gateaddr[16], maskaddr[16];
  u_char flag;
  pid_t pid;
  struct rt_msghdr *rtm;
  struct sockaddr_in *dst, *gate, *mask;
  struct sockaddr_dl *ifp, *sdl;
  struct if_msghdr *ifm;

#ifdef RTCTL_PRINT_RESPONSE
  ssize_t			n;
  struct sockaddr		*sa, *rti_info[RTAX_MAX];
#endif	

  /* check the arguments */
  if (daddr == NULL)
    {
      fprintf(stderr, "Invalid destination IP address\n");
      return -1;
    }
  flag = 0;
  if (cmd == RTM_ADD)
    {
      flag |= RTCTL_ADD;
      strncpy(rta_cmd, "add", sizeof("add"));
      if (gaddr == NULL)
	{
	  if (ifname == NULL)
	    flag |= RTCTL_UNKNOWN;
	  else if (maddr != NULL)
	    flag |= RTCTL_UNKNOWN;
	  else
	    flag |= RTCTL_IF;
	}
      else
	{
	  flag |= RTCTL_GATEWAY;
	  if (ifname != NULL)
	    flag |= RTCTL_UNKNOWN;
	  else if (maddr != NULL)
	    flag |= RTCTL_NETMASK;
	}
    }
  else if (cmd == RTM_DELETE)
    {
      flag |= RTCTL_DELETE;
      strncpy(rta_cmd, "delete", sizeof("delete"));
      if ((ifname != NULL) | (gaddr != NULL) | (maddr != NULL))
	flag |= RTCTL_UNKNOWN;
    }
  else if (cmd == RTM_CHANGE)
    {
      flag |= RTCTL_CHANGE;
      strncpy(rta_cmd, "change", sizeof("change"));
      if (gaddr == NULL)
	{
	  if (ifname == NULL)
	    flag |= RTCTL_UNKNOWN;
	  else if (maddr != NULL)
	    flag |= RTCTL_UNKNOWN;
	  else
	    flag |= RTCTL_IF;
	}
      else
	{
	  flag |= RTCTL_GATEWAY;
	  if (ifname != NULL)
	    flag |= RTCTL_UNKNOWN;
	  else if (maddr != NULL)
	    flag |= RTCTL_NETMASK;
	}
    }
  else
    {
      fprintf(stderr, "Invalid command name\n");
      return -1;
    }

  if (flag & RTCTL_UNKNOWN)
    {
      fprintf(stderr, "Unknown arguments are inputed.\n");
      return -1;
    }
  
  if ((buf = calloc(1, BUFLEN)) == NULL)
    {
      perror("calloc");
      return -1;
    }

  /* set address of rt messages */
  rtm = (struct rt_msghdr *) buf;
  rtm->rtm_version = RTM_VERSION;
  rtm->rtm_type = cmd;
  rtm->rtm_pid = pid = getpid();
  rtm->rtm_seq = ++rtm_seq;
  rtm->rtm_errno = 0;
  if ((flag & RTCTL_ADD) | (flag & RTCTL_CHANGE))
    {
      if (flag & RTCTL_IF)
	{
	  rtm->rtm_msglen = sizeof(struct rt_msghdr) +
	    sizeof(struct sockaddr_in) + 
	    sizeof(struct sockaddr_dl);
	  rtm->rtm_addrs = RTA_DST | RTA_GATEWAY;
	  rtm->rtm_flags = RTF_UP | RTF_HOST | RTF_LLINFO
	    | RTF_STATIC;
	}
      else if (flag & RTCTL_NETMASK)
	{
	  rtm->rtm_msglen = sizeof(struct rt_msghdr) +
	    3 * sizeof(struct sockaddr_in);
	  rtm->rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
	  rtm->rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC;
	}
      else
	{
	  rtm->rtm_msglen = sizeof(struct rt_msghdr) +
	    2 * sizeof(struct sockaddr_in);
	  rtm->rtm_addrs = RTA_DST | RTA_GATEWAY;
	  rtm->rtm_flags = RTF_UP | RTF_HOST | RTF_GATEWAY
	    | RTF_STATIC;
	}
    }
  else if (flag & RTCTL_DELETE)
    {
      rtm->rtm_msglen = sizeof(struct rt_msghdr) +
	sizeof(struct sockaddr_in);
      rtm->rtm_addrs = RTA_DST;
    }

  /* set destination RTA_GATEWAY */
  dst = (struct sockaddr_in *) (rtm + 1);
  dst->sin_len = sizeof(struct sockaddr_in);
  dst->sin_family = AF_INET;
  fflush(stderr);
  dst->sin_addr.s_addr = *daddr;
  if (flag & RTCTL_GATEWAY)
    {
      /* set gateway */
      gate = (struct sockaddr_in *) (dst + 1);
      gate->sin_len = sizeof(struct sockaddr_in);
      gate->sin_family = AF_INET;
      gate->sin_addr.s_addr = *gaddr;
      if (flag & RTCTL_NETMASK)
	{
	  mask = (struct sockaddr_in *) (gate + 1);
	  mask->sin_len = sizeof(struct sockaddr_in);
	  mask->sin_family = AF_INET;
	  mask->sin_addr.s_addr = *maddr;
	}
    }
  else if (flag & RTCTL_IF)
    {
      /* get sockaddr_dl info */
      mib[0] = CTL_NET;
      mib[1] = AF_ROUTE;
      mib[2] = 0;
      mib[3] = AF_LINK;
      mib[4] = NET_RT_IFLIST;
      if ((mib[5] = if_nametoindex(ifname)) == 0) 
	{
	  perror("if_nametoindex");
	  return -1;
	}
      if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) 
	{
	  perror("sysctl");
	  return -1;
	}
      if ((ifbuf = calloc(1, len)) == NULL)
	{
	  perror("calloc");
	  return -1;
	}
      if (sysctl(mib, 6, ifbuf, &len, NULL, 0) < 0) 
	{
	  perror("sysctl2");
	  return -1;
	}
      ifm = (struct if_msghdr *) ifbuf;
      sdl = (struct sockaddr_dl *) (ifm + 1);

      /* set network interface */
      ifp = (struct sockaddr_dl *) (dst + 1);
      bcopy(sdl, ifp, sizeof(struct sockaddr_dl));
      ifp->sdl_len = sizeof(struct sockaddr_dl);
    }

  if ((sockfd = socket(PF_ROUTE, SOCK_RAW, 0)) < 0)
    {
      perror("socket");
      return -1;
    }
  if (write(sockfd, rtm, rtm->rtm_msglen) < 0)
    {
      perror("write");
      //return -1;
    }
  else
    {
      strncpy(dstaddr, "", sizeof(dstaddr));
      strncpy(gateaddr, "", sizeof(gateaddr));
      strncpy(maskaddr, "", sizeof(maskaddr));
      strncpy(dstaddr, inet_ntoa(dst->sin_addr), sizeof(dstaddr));
      if (gaddr != NULL)
	strncpy(gateaddr, inet_ntoa(gate->sin_addr), sizeof(gateaddr));
      if (maddr != NULL)
	strncpy(maskaddr, inet_ntoa(mask->sin_addr), sizeof(maskaddr));
      fprintf(stderr, "\troute %s dst:%s gate:%s mask:%s ifp:%s\n",
	      rta_cmd, dstaddr, gateaddr, maskaddr, ifname);


/* A chunk of lines like this: */
	
/*  strncpy(dstaddr, "", sizeof(dstaddr));                                   */
/*  strncpy(gateaddr, "", sizeof(gateaddr));                                 */
/*  strncpy(maskaddr, "", sizeof(maskaddr));                                 */
/*  strncpy(dstaddr, inet_ntoa(dst->sin_addr), sizeof(dstaddr));             */
/*  if (gaddr != NULL)                                                       */
/*    strncpy(gateaddr, inet_ntoa(gate->sin_addr),                     */
/* 	   sizeof(gateaddr));                                               */
/*  if (maddr != NULL)                                                       */
/*    strncpy(maskaddr, inet_ntoa(mask->sin_addr),                     */
/* 	   sizeof(maskaddr));                                               */
/*  fprintf(stderr, "\troute %s dst:%s gate:%s mask:%s ifp:%s\n",            */
/* 	 rta_cmd, dstaddr, gateaddr, maskaddr, ifname);                   */
 
/* can be rewritten as: */
  
/*   fprintf(stderr, "\troute %s dst:%s gate:%s ", rta_cmd, dstaddr,         */
/* 	  (gaddr != NULL) : inet_ntoa(gate->sin_addr) ? "");                 */
/*  fprintf(stderr, "mask:%s ifp:%s\n",                                      */
/* 	 (maddr != NULL) : inet_ntoa(mask->sin_addr) ? "", ifname);          */

    }
  
#ifdef RTCTL_PRINT_RESPONSE
  fprintf(stderr, "---print response\n");
  do
    {
      n = read(sockfd, rtm, BUFLEN);
    }
  while (rtm->rtm_seq != rtm_seq || rtm->rtm_pid != pid);

  /* handle response */
  rtm = (struct rt_msghdr *) buf;
  sa = (struct sockaddr *) (rtm + 1);
  get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
  if ((sa = rti_info[RTAX_DST]) != NULL)
    fprintf(stderr, "dest: %s\n", sock_ntop_host(sa, sa->sa_len));
  if ((sa = rti_info[RTAX_GATEWAY]) != NULL)
    fprintf(stderr, "gateway: %s\n", sock_ntop_host(sa, sa->sa_len));
  if ((sa = rti_info[RTAX_NETMASK]) != NULL)
    fprintf(stderr, "netmask: %s\n", sock_masktop(sa, sa->sa_len));
  if ((sa = rti_info[RTAX_GENMASK]) != NULL)
    fprintf(stderr, "genmask: %s\n", sock_masktop(sa, sa->sa_len));
  if ((sa = rti_info[RTAX_IFP]) != NULL)
    fprintf(stderr, "ifp: len:%d fami:%d data:%s\n", sa->sa_len, 
	    sa->sa_family, sa->sa_data);
  if ((sa = rti_info[RTAX_IFA]) != NULL)
    fprintf(stderr, "ifa: len:%d fami:%d data:%s\n", sa->sa_len, 
	    sa->sa_family, sa->sa_data);
  if ((sa = rti_info[RTAX_AUTHOR]) != NULL)
    fprintf(stderr, "author: len:%d fami:%d data:%s\n", sa->sa_len, 
	    sa->sa_family, sa->sa_data);
  if ((sa = rti_info[RTAX_BRD]) != NULL)
    fprintf(stderr, "brd: len:%d fami:%d data:%s\n", sa->sa_len, 
	    sa->sa_family, sa->sa_data);
#endif

  free(buf);
  if (flag & RTCTL_IF)
    free(ifbuf);
  return 0;
}
Exemple #22
0
int getrt(char *ipaddr)
{
  int sockfd;
  char *buf;
  pid_t pid;
  ssize_t n;
  struct rt_msghdr *rtm;
  struct sockaddr *sa, *rti_info[RTAX_MAX];
  struct sockaddr_in *sin;

  if (ipaddr == NULL)
    {
      fprintf(stderr, "getrt: IP address.\n");
      return -1;
    }
  if ((sockfd = socket(AF_ROUTE, SOCK_RAW, 0)) < 0)
    {
      perror("socket");
      return -1;
    }
  buf = calloc(1, BUFLEN);
  rtm = (struct rt_msghdr *) buf;
  rtm->rtm_msglen = sizeof(struct rt_msghdr) + sizeof(struct sockaddr_in);
  rtm->rtm_version = RTM_VERSION;
  rtm->rtm_type = RTM_GET;
  rtm->rtm_addrs = RTA_DST;
  rtm->rtm_pid = pid = getpid();
  rtm->rtm_seq = SEQ;
  sin = (struct sockaddr_in *) (rtm + 1);
  sin->sin_len = sizeof(struct sockaddr_in);
  sin->sin_family = AF_INET;
  inet_pton(AF_INET, ipaddr, &sin->sin_addr);
  if (write(sockfd, rtm, rtm->rtm_msglen) < 0)
    {
      perror("write");
      exit(1);
    }
  do
    {
      n = read(sockfd, rtm, BUFLEN);
    }
  while (rtm->rtm_type != RTM_GET || rtm->rtm_seq != SEQ ||
	 rtm->rtm_pid != pid);

  /* handle response */
  rtm = (struct rt_msghdr *) buf;
  sa = (struct sockaddr *) (rtm + 1);
  get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
  if ((sa = rti_info[RTAX_DST]) != NULL)
    fprintf(stderr, "dest: %s\n", sock_ntop_host(sa, sa->sa_len));
  if ((sa = rti_info[RTAX_GATEWAY]) != NULL)
    fprintf(stderr, "gateway: %s\n", sock_ntop_host(sa, sa->sa_len));
  if ((sa = rti_info[RTAX_NETMASK]) != NULL)
    fprintf(stderr, "netmask: %s\n", sock_masktop(sa, sa->sa_len));
  if ((sa = rti_info[RTAX_GENMASK]) != NULL)
    fprintf(stderr, "genmask: %s\n", sock_masktop(sa, sa->sa_len));
  if ((sa = rti_info[RTAX_IFP]) != NULL)
    fprintf(stderr, "ifp: len:%d fami:%d data:%s\n", sa->sa_len, 
	    sa->sa_family, sa->sa_data);
  if ((sa = rti_info[RTAX_IFA]) != NULL)
    fprintf(stderr, "ifa: len:%d fami:%d data:%s\n", sa->sa_len, 
	    sa->sa_family, sa->sa_data);
  return 0;
}