Пример #1
0
PRIVATE_EXTERN int
inet6_linklocal_stop(const char * ifname)
{
    int ret = 0;
    int s = inet6_dgram_socket();

    if (s < 0) {
	ret = errno;
	my_log(LOG_ERR, 
	       "inet6_linklocal_stop(%s): socket() failed, %s (%d)",
	       ifname, strerror(ret), ret);
	goto done;
    }
    if (siocll_stop(s, ifname) < 0) {
	ret = errno;
	if (errno != ENXIO) {
	    my_log(LOG_ERR, "siocll_stop(%s) failed, %s (%d)",
		   ifname, strerror(errno), errno);
	}
    }
    close(s);

 done:
    return (ret);
}
Пример #2
0
PRIVATE_EXTERN int
inet6_linklocal_start(const char * ifname, boolean_t use_cga)
{
    int ret = 0;
    int s = inet6_dgram_socket();

    if (s < 0) {
	ret = errno;
	my_log(LOG_ERR, 
	       "inet6_linklocal_start(%s): socket() failed, %s (%d)",
	       ifname, strerror(ret), ret);
	goto done;
    }
    nd_flags_set_with_socket(s, ifname, 0, ND6_IFF_IFDISABLED);
    if (ll_start(s, ifname, use_cga) < 0) {
	ret = errno;
	if (errno != ENXIO) {
	    my_log(LOG_ERR, "siocll_start(%s) failed, %s (%d)",
		   ifname, strerror(errno), errno);
	}
    }
    close(s);
 done:
    return (ret);
}
Пример #3
0
PRIVATE_EXTERN int
inet6_detach_interface(const char * ifname)
{
    int ret = 0;
    int s = inet6_dgram_socket();

    if (s < 0) {
	ret = errno;
	my_log(LOG_ERR, 
	       "inet6_detach_interface(%s): socket() failed, %s (%d)",
	       ifname, strerror(ret), ret);
	goto done;
    }
    if (siocprotodetach_in6(s, ifname) < 0) {
	ret = errno;
	if (ret != ENXIO) {
	    my_log(LOG_DEBUG, "siocprotodetach_in6(%s) failed, %s (%d)",
		   ifname, strerror(errno), errno);
	}
    }
    close(s);

 done:
    return (ret);
}
Пример #4
0
STATIC boolean_t
nd_flags_set(const char * if_name, uint32_t set_flags, uint32_t clear_flags)
{
    int			s;
    boolean_t		success = FALSE;

    s = inet6_dgram_socket();
    if (s < 0) {
	my_log_fl(LOG_ERR, "socket failed, %s", strerror(errno));
    }
    else {
	success = nd_flags_set_with_socket(s, if_name, set_flags, clear_flags);
	close(s);
    }
    return (success);
}
Пример #5
0
PRIVATE_EXTERN boolean_t
inet6_set_perform_nud(const char * if_name, boolean_t perform_nud)
{
    boolean_t		need_set = FALSE;
    struct in6_ndireq 	nd;
    int			s;
    boolean_t		success = FALSE;

    s = inet6_dgram_socket();
    if (s < 0) {
        my_log_fl(LOG_ERR, "socket failed, %s", strerror(errno));
        goto done;
    }
    bzero(&nd, sizeof(nd));
    strncpy(nd.ifname, if_name, sizeof(nd.ifname));
    if (ioctl(s, SIOCGIFINFO_IN6, &nd)) {
        my_log_fl(LOG_ERR, "SIOCGIFINFO_IN6(%s) failed, %s",
                  if_name, strerror(errno));
        goto done;
    }
    if (perform_nud) {
        if ((nd.ndi.flags & ND6_IFF_PERFORMNUD) == 0) {
            nd.ndi.flags |= ND6_IFF_PERFORMNUD;
            need_set = TRUE;
        }
    }
    else if ((nd.ndi.flags & ND6_IFF_PERFORMNUD) != 0) {
        nd.ndi.flags &= ~ND6_IFF_PERFORMNUD;
        need_set = TRUE;
    }
    if (need_set) {
        if (ioctl(s, SIOCSIFINFO_FLAGS, (caddr_t)&nd)) {
            my_log_fl(LOG_ERR, "SIOCSIFINFO_FLAGS(%s) failed, %s",
                      if_name, strerror(errno));
            goto done;
        }
    }
    success = TRUE;
done:
    if (s >= 0) {
        close(s);
    }
    return (success);
}
Пример #6
0
STATIC int
inet6_if_ioctl(const char * ifname, unsigned long request)
{
    struct in6_ifreq	ifr;
    int 		ret = 0;
    int			s;

    s = inet6_dgram_socket();
    if (s < 0) {
	ret = errno;
	goto done;
    }
    bzero(&ifr, sizeof(ifr));
    strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));

    if (ioctl(s, request, &ifr) < 0) {
	ret = errno;
    }
 done:
    if (s >=0) {
	close(s);
    }
    return (ret);
}
Пример #7
0
PRIVATE_EXTERN int
inet6_rtadv_enable(const char * if_name)
{
    int			ret = 0;
    int			s = inet6_dgram_socket();

    if (s < 0) {
	ret = errno;
	my_log(LOG_ERR, 
	       "inet6_rtadv_enable(%s): socket() failed, %s (%d)",
	       if_name, strerror(ret), ret);
	goto done;
    }
    if (siocautoconf_start(s, if_name) < 0) {
	ret = errno;
	if (errno != ENXIO) {
	    my_log(LOG_ERR, "siocautoconf_start(%s) failed, %s (%d)",
		   if_name, strerror(errno), errno);
	}
    }
    close(s);
 done:
    return (ret);
}
Пример #8
0
PRIVATE_EXTERN void
inet6_addrlist_copy(inet6_addrlist_t * addr_list_p, int if_index)
{
    int				addr_index = 0;
    char *			buf = NULL;
    char *			buf_end;
    int				buf_len;
    int				count;
    int				error;
    int				i;
    char			ifname[IFNAMSIZ + 1];
    inet6_addrinfo_t *		linklocal = NULL;
    inet6_addrinfo_t *		list = NULL;
    char *			scan;
    struct rt_msghdr *		rtm;
    int				s = -1;

    buf = get_if_info(if_index, AF_INET6, &buf_len);
    if (buf == NULL) {
	goto done;
    }
    buf_end = buf + buf_len;

    /* figure out how many IPv6 addresses there are */
    count = 0;
    ifname[0] = '\0';
    for (scan = buf; scan < buf_end; scan += rtm->rtm_msglen) {
	struct if_msghdr * 	ifm;
	
	/* ALIGN: buf aligned (from calling get_if_info), scan aligned, 
	 * cast ok. */
	rtm = (struct rt_msghdr *)(void *)scan;
	if (rtm->rtm_version != RTM_VERSION) {
	    continue;
	}
	switch (rtm->rtm_type) {
	case RTM_IFINFO:
	    ifm = (struct if_msghdr *)rtm;
	    if (ifm->ifm_addrs & RTA_IFP) {
		struct sockaddr_dl *	dl_p;
		
		dl_p = (struct sockaddr_dl *)(ifm + 1);
		if (dl_p->sdl_nlen == 0 
		    || dl_p->sdl_nlen >= sizeof(ifname)) {
		    goto done;
		}
		bcopy(dl_p->sdl_data, ifname, dl_p->sdl_nlen);
		ifname[dl_p->sdl_nlen] = '\0';
	    }
	    break;
	case RTM_NEWADDR:
	    count++;
	    break;
	default:
	    break;
	}
    }
    if (ifname[0] == '\0') {
	goto done;
    }
    if (count == 0) {
	goto done;
    }
    if (count > INET6_ADDRLIST_N_STATIC) {
	list = (inet6_addrinfo_t *)malloc(sizeof(*list) * count);
	if (list == NULL) {
	    goto done;
	}
    }
    else {
	list = addr_list_p->list_static;
    }
    for (scan = buf; scan < buf_end; scan += rtm->rtm_msglen) {
	boolean_t		got_address = FALSE;
	struct ifa_msghdr *	ifam;
	struct rt_addrinfo	info;

	rtm = (struct rt_msghdr *)(void *)scan;
	if (rtm->rtm_version != RTM_VERSION) {
	    continue;
	}
	if (rtm->rtm_type == RTM_NEWADDR) {
	    ifam = (struct ifa_msghdr *)rtm;
	    info.rti_addrs = ifam->ifam_addrs;
	    error = rt_xaddrs((char *)(ifam + 1),
			      ((char *)ifam) + ifam->ifam_msglen,
			      &info);
	    if (error) {
		fprintf(stderr, "couldn't extract rt_addrinfo %s (%d)\n",
			strerror(error), error);
		goto done;
	    }
	    for (i = 0; i < RTAX_MAX; i++) {
		struct sockaddr_in6 *	sin6_p;
		
		/* ALIGN: info.rti_info aligned (sockaddr), cast ok. */
		sin6_p = (struct sockaddr_in6 *)(void *)info.rti_info[i];
		if (sin6_p == NULL
		    || sin6_p->sin6_len < sizeof(struct sockaddr_in6)) {
		    continue;
		}
		switch (i) {
		case RTAX_NETMASK:
		    list[addr_index].prefix_length 
			= count_prefix_bits(&sin6_p->sin6_addr,
					    sizeof(sin6_p->sin6_addr));
		    break;
		case RTAX_IFA:
		    list[addr_index].addr = sin6_p->sin6_addr;
		    got_address = TRUE;
		    break;
		default:
		    break;
		}
	    }
	    if (got_address) {
		if (s < 0) {
		    s = inet6_dgram_socket();
		}
		if (s >= 0) {
		    siocgifaflag_in6(s, ifname, 
				     &list[addr_index].addr,
				     &list[addr_index].addr_flags);
		    siocgifalifetime_in6(s, ifname, 
					 &list[addr_index].addr,
					 &list[addr_index].valid_lifetime,
					 &list[addr_index].preferred_lifetime);
		}
		/* Mask the v6 LL scope id */
		if (IN6_IS_ADDR_LINKLOCAL(&list[addr_index].addr)) {
		    list[addr_index].addr.s6_addr16[1] = 0;
		    if (linklocal == NULL) {
			linklocal = &list[addr_index];
		    }
		}
		addr_index++;
	    }
	}
    }
    if (addr_index == 0) {
	if (list != addr_list_p->list_static) {
	    free(list);
	}
	list = NULL;
    }

 done:
    if (s >= 0) {
	close(s);
    }
    if (buf != NULL) {
	free(buf);
    }
    addr_list_p->list = list;
    addr_list_p->count = addr_index;
    addr_list_p->linklocal = linklocal;
    return;
}