Example #1
0
int start_client()
{
	struct icmp6_filter filter;
	int val;
//	pthread_mutexattr_t mattrs;
//	pthread_t chart;

	init_my_npm();
//	pthread_create(&chart, NULL, input_thread, (void *)NULL);

	sock_fd = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);

	if (sock_fd < 0)
	{
        printf("Unable to open ICMPv6 socket! "
               "Do you have root permissions?\n");
    }

	val = 1;

	if (setsockopt(sock_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &val, sizeof(val)) < 0)
	{
		printf("Setsockopt() failed in client.c -- 1\n") ;
        return -1;
	}
    if (setsockopt(sock_fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &val, sizeof(val)) < 0)
	{
		printf("Setsockopt() failed in client.c -- 2\n") ;
        return -1;
	}

    ICMP6_FILTER_SETBLOCKALL(&filter);
//    ICMP6_FILTER_SETPASS(ICMP6_DST_UNREACH, &filter);

	ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filter);
	ICMP6_FILTER_SETPASS(ND_NEIGHBOR_SOLICIT, &filter);
//	ICMP6_FILTER_SETPASS(ND_NEIGHBOR_ADVERT, &filter);


	if (setsockopt(sock_fd, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, sizeof(struct icmp6_filter)) < 0)
	{
		printf("Setsockopt() failed in client.c -- 3\n") ;
        return -1;
	}

	val = 2 ;

	/* create ICMP listener thread */
//    pthread_mutexattr_init(&mattrs);
//    pthread_mutexattr_settype(&mattrs, PTHREAD_MUTEX_NORMAL);
/*    if (pthread_mutex_init(&send_mutex, &mattrs) ||
        pthread_rwlock_init(&handler_lock, NULL) ||
        pthread_create(&icmp6_listener, NULL, icmp6_listen, &sock_fd))*/
	if(pthread_create(&icmp6_listener, NULL, icmp6_listen, &sock_fd))
	{
        return -1;
	}

    return 0;
}
Example #2
0
int icmp6_init(void)
{
	struct icmp6_filter filter;
	pthread_mutexattr_t mattrs;
	int val;

	icmp6_sock.fd = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
	if (icmp6_sock.fd < 0) {
		syslog(LOG_ERR,
		       "Unable to open ICMPv6 socket! "
		       "Do you have root permissions?");
		return icmp6_sock.fd;
	}
	val = 1;
	if (setsockopt(icmp6_sock.fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, 
		       &val, sizeof(val)) < 0)
		return -1;
	if (setsockopt(icmp6_sock.fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT,
		       &val, sizeof(val)) < 0)
		return -1;
	ICMP6_FILTER_SETBLOCKALL(&filter);
	ICMP6_FILTER_SETPASS(ICMP6_DST_UNREACH, &filter);

	if (is_ha()) {
		ICMP6_FILTER_SETPASS(MIP_PREFIX_SOLICIT, &filter);
		ICMP6_FILTER_SETPASS(MIP_HA_DISCOVERY_REQUEST, &filter);
		ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filter);
	}

	if (is_mn()) {
		ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filter);
		ICMP6_FILTER_SETPASS(ND_NEIGHBOR_ADVERT, &filter);
		ICMP6_FILTER_SETPASS(MIP_PREFIX_ADVERT, &filter);
		ICMP6_FILTER_SETPASS(MIP_HA_DISCOVERY_REPLY, &filter);
		ICMP6_FILTER_SETPASS(ICMP6_PARAM_PROB, &filter);
	}

	if (setsockopt(icmp6_sock.fd, IPPROTO_ICMPV6, ICMP6_FILTER, 
		       &filter, sizeof(struct icmp6_filter)) < 0)
		return -1;
	val = 2;
	if (setsockopt(icmp6_sock.fd, IPPROTO_RAW, IPV6_CHECKSUM, 
		       &val, sizeof(val)) < 0)
		return -1;
	/* create ICMP listener thread */
	pthread_mutexattr_init(&mattrs);
	pthread_mutexattr_settype(&mattrs, PTHREAD_MUTEX_FAST_NP);
	if (pthread_mutex_init(&icmp6_sock.send_mutex, &mattrs) ||
	    pthread_rwlock_init(&handler_lock, NULL) ||
	    pthread_create(&icmp6_listener, NULL, icmp6_listen, NULL))
		return -1;
	return 0;
}
Example #3
0
STATIC int
open_rtadv_socket(void)
{
    struct icmp6_filter	filt;
    int			sockfd;

    /* open socket */
    sockfd = ICMPv6SocketOpen(TRUE);
    if (sockfd < 0) {
	my_log_fl(LOG_ERR, "error opening socket: %s",
		  strerror(errno));
	goto failed;
    }

    /* accept only router advertisement messages */
    ICMP6_FILTER_SETBLOCKALL(&filt);
    ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filt);
    if (setsockopt(sockfd, IPPROTO_ICMPV6, ICMP6_FILTER, &filt,
		   sizeof(filt)) == -1) {
	my_log_fl(LOG_ERR, "setsockopt(ICMP6_FILTER): %s",
		  strerror(errno));
	goto failed;
    }
    return (sockfd);

 failed:
    if (sockfd >= 0) {
	close(sockfd);
    }
    return (-1);
}
Example #4
0
int init_router(void)
{
	// Open ICMPv6 socket
	int sock = socket(AF_INET6, SOCK_RAW | SOCK_CLOEXEC, IPPROTO_ICMPV6);
	if (sock < 0 && errno != EAFNOSUPPORT) {
		syslog(LOG_ERR, "Failed to open RAW-socket: %s", strerror(errno));
		return -1;
	}

	// Let the kernel compute our checksums
	int val = 2;
	setsockopt(sock, IPPROTO_RAW, IPV6_CHECKSUM, &val, sizeof(val));

	// This is required by RFC 4861
	val = 255;
	setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &val, sizeof(val));
	setsockopt(sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &val, sizeof(val));

	// We need to know the source interface
	val = 1;
	setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &val, sizeof(val));
	setsockopt(sock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &val, sizeof(val));

	// Don't loop back
	val = 0;
	setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &val, sizeof(val));

	// Filter ICMPv6 package types
	struct icmp6_filter filt;
	ICMP6_FILTER_SETBLOCKALL(&filt);
	ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filt);
	ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &filt);
	setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filt, sizeof(filt));

	// Register socket
	router_event.uloop.fd = sock;
	odhcpd_register(&router_event);

	if (!(fp_route = fopen("/proc/net/ipv6_route", "r")))
		syslog(LOG_ERR, "Failed to open routing table: %s",
				strerror(errno));

	signal(SIGUSR1, sigusr1_refresh);
	return 0;
}
Example #5
0
	filter(bool block, uint except_value_type)
	{
		if (block) {
			ICMP6_FILTER_SETBLOCKALL(&_filter);
			ICMP6_FILTER_SETPASS(except_value_type, &_filter);
		} else {
			ICMP6_FILTER_SETPASSALL(&_filter);
			ICMP6_FILTER_SETBLOCK(except_value_type, &_filter);
		}
	}
Example #6
0
int dhcp_network_icmp6_bind_router_solicitation(int index)
{
        struct icmp6_filter filter = { };
        struct ipv6_mreq mreq = {
                .ipv6mr_multiaddr = IN6ADDR_ALL_NODES_MULTICAST_INIT,
                .ipv6mr_interface = index,
        };
        _cleanup_close_ int s = -1;
        int r, zero = 0, hops = 255;

        s = socket(AF_INET6, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK,
                   IPPROTO_ICMPV6);
        if (s < 0)
                return -errno;

        ICMP6_FILTER_SETBLOCKALL(&filter);
        ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filter);
        r = setsockopt(s, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
                       sizeof(filter));
        if (r < 0)
                return -errno;

        /* RFC 3315, section 6.7, bullet point 2 may indicate that an
           IPV6_PKTINFO socket option also applies for ICMPv6 multicast.
           Empirical experiments indicates otherwise and therefore an
           IPV6_MULTICAST_IF socket option is used here instead */
        r = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_IF, &index,
                       sizeof(index));
        if (r < 0)
                return -errno;

        r = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &zero,
                       sizeof(zero));
        if (r < 0)
                return -errno;

        r = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hops,
                       sizeof(hops));
        if (r < 0)
                return -errno;

        r = setsockopt(s, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq,
                       sizeof(mreq));
        if (r < 0)
                return -errno;

        r = s;
        s = -1;
        return r;
}
Example #7
0
static int icmp_socket(char *name)
{
    struct icmp6_filter filter;
    int sock = -1;

    sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
    if ( sock > 0 )
    {

        ICMP6_FILTER_SETBLOCKALL(&filter);
        ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT,&filter);

        if (setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER,
                       &filter, sizeof(struct icmp6_filter)) < 0 )
        {
            perror("setsockopt: %s");
            close(sock);
            sock = -1;
        }
        else
        {
            if ( name )
            {
                if (setsockopt(sock, SOL_SOCKET,
                               SO_BINDTODEVICE, name,
                               strlen(name)+1) < 0 )
                {
                    perror("setsockopt:");
                    close(sock);
                    sock = -1;
                }
            }
        }
    }
    else
    {
        perror("socket");
    }

    return sock;
}
Example #8
0
File: init_v6.c Project: geektcp/C
void init_v6()
{
#ifdef IPV6
    int on = 1;
    if (verbose == 0) {
        /* install a filter that only passes ICMP6_ECHO_REPLY unless verbose */
        struct icmp6_filter myfilt;
        ICMP6_FILTER_SETBLOCKALL(&myfilt);
        ICMP6_FILTER_SETPASS(ICMP6_ECHO_REPLY, &myfilt);
        setsockopt(sockfd, IPPROTO_IPV6, ICMP6_FILTER, &myfilt,
                   sizeof(myfilt));
        /* ignore error return; the filter is an optimization */
    }
    /* ignore error returned below; we just won't receive the hop limit */
#ifdef IPV6_RECVHOPLIMIT
    /* RFC 3542 */
    setsockopt(sockfd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on, sizeof(on));
#else
    /* RFC 2292 */
    setsockopt(sockfd, IPPROTO_IPV6, IPV6_HOPLIMIT, &on, sizeof(on));
#endif
#endif
}
Example #9
0
int
main(int argc, char *argv[])
{
	int i;
	struct icmp6_filter filt;
	u_int hlim = 1;
	fd_set fdset;
	struct itimerval itimer;
	u_int type;
	int ch;

	type = MLD6_LISTENER_QUERY;
	while ((ch = getopt(argc, argv, "dr")) != -1) {
		switch (ch) {
		case 'd':
			type = MLD6_LISTENER_DONE;
			break;
		case 'r':
			type = MLD6_LISTENER_REPORT;
			break;
		default:
			usage();
			/*NOTREACHED*/
		}
	}

	argv += optind;
	argc -= optind;
	
	if (argc != 1 && argc != 2)
		usage();

	ifindex = (u_short)if_nametoindex(argv[0]);
	if (ifindex == 0)
		usage();
	if (argc == 2 && inet_pton(AF_INET6, argv[1], &maddr) != 1)
		usage();

	if ((s = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0)
		err(1, "socket");

	if (setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hlim,
		       sizeof(hlim)) == -1)
		err(1, "setsockopt(IPV6_MULTICAST_HOPS)");

	mreq.ipv6mr_multiaddr = any;
	mreq.ipv6mr_interface = ifindex;
	if (setsockopt(s, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq,
		       sizeof(mreq)) == -1)
		err(1, "setsockopt(IPV6_JOIN_GROUP)");

	ICMP6_FILTER_SETBLOCKALL(&filt);
	ICMP6_FILTER_SETPASS(ICMP6_MEMBERSHIP_QUERY, &filt);
	ICMP6_FILTER_SETPASS(ICMP6_MEMBERSHIP_REPORT, &filt);
	ICMP6_FILTER_SETPASS(ICMP6_MEMBERSHIP_REDUCTION, &filt);
	if (setsockopt(s, IPPROTO_ICMPV6, ICMP6_FILTER, &filt,
			sizeof(filt)) < 0)
		err(1, "setsockopt(ICMP6_FILTER)");

	make_msg(ifindex, &maddr, type);

	if (sendmsg(s, &m, 0) < 0)
		err(1, "sendmsg");

	itimer.it_value.tv_sec =  QUERY_RESPONSE_INTERVAL / 1000;
	itimer.it_interval.tv_sec = 0;
	itimer.it_interval.tv_usec = 0;
	itimer.it_value.tv_usec = 0;

	signal(SIGALRM, quit);
	setitimer(ITIMER_REAL, &itimer, NULL);

	FD_ZERO(&fdset);
	for (;;) {
		FD_SET(s, &fdset);
		if ((i = select(s + 1, &fdset, NULL, NULL, NULL)) < 0)
			perror("select");
		if (i == 0)
			continue;
		else
			dump(s);
	}
}
Example #10
0
File: ndisc.c Project: jlanza/umip
int ndisc_do_dad(int ifi, struct in6_addr *addr, int do_ll)
{
	struct in6_pktinfo pinfo;
	struct sockaddr_in6 saddr;
	struct nd_neighbor_advert *hdr;
	struct icmp6_filter filter;
	struct in6_addr solicit, ll;
	unsigned char msg[MAX_PKT_LEN];
	int hoplimit, sock = -1, ret, val = 1, err = -1;
	fd_set rset;
	struct timeval tv;

	ICMP6_FILTER_SETBLOCKALL(&filter);
	ICMP6_FILTER_SETPASS(ND_NEIGHBOR_ADVERT, &filter);

	sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
	if (sock < 0) {
		dbg("socket: %s\n", strerror(errno));
		goto end;
	}

	if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO,
		       &val, sizeof(val)) < 0) {
		dbg("cannot set IPV6_RECVPKTINFO: %s\n", strerror(errno));
		goto end;
	}
	if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT,
		       &val, sizeof(val)) < 0) {
		dbg("cannot set IPV6_RECVHOPLIMIT: %s\n", strerror(errno));
		goto end;
	}
	if (setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
		       sizeof(struct icmp6_filter)) < 0) {
		dbg("cannot set ICMPV6_FILTER: %s\n", strerror(errno));
		goto end;
	}

	ipv6_addr_solict_mult(addr, &solicit);
	if (if_mc_group(sock, ifi, &in6addr_all_nodes_mc, IPV6_JOIN_GROUP)) {
		dbg("cannot join all node mc\n");
		goto end;
	}
	if (if_mc_group(sock, ifi, &solicit, IPV6_JOIN_GROUP)) {
		dbg("cannot joing slicit node mc\n");
		goto end;
	}
	if (ndisc_send_ns(ifi, addr) <= 0) {
		dbg("Error at sending NS\n");
		goto end;
	}

	if (do_ll) {
		ipv6_addr_llocal(addr, &ll);
		if (ndisc_send_ns(ifi, &ll) <= 0) {
			dbg("Error at sending NS (link-local target)\n");
			goto end;
		}
	}

	FD_ZERO(&rset);
	FD_SET(sock, &rset);
	tv.tv_sec = DAD_TIMEOUT;
	tv.tv_usec = 0;
	for (;;) {
		/* Note on portability: we assume that tv is modified to show
		   the time left which is AFAIK true only in Linux 
		   timeout 
		*/
		if (select(sock+1, &rset, NULL, NULL, &tv) == 0) {
			dbg("Dad success\n");
			err = 0;
			break;
		}
		if (!FD_ISSET(sock, &rset))
			continue;
		/* We got an ICMPv6 packet */
		ret = icmp6_recv(sock, msg, sizeof(msg), &saddr, 
				 &pinfo, &hoplimit);
		if (ret < 0)
			continue;
		hdr = (struct nd_neighbor_advert *)msg;
		if (hdr->nd_na_code != 0)
			continue;
		if (IN6_ARE_ADDR_EQUAL(addr, &hdr->nd_na_target) ||
		    (do_ll && IN6_ARE_ADDR_EQUAL(&ll, &hdr->nd_na_target))) {
			dbg("Failure\n");
			break;
		}
	}
 end:
	if (sock >= 0)
		close(sock);
	return err;
}
Example #11
0
int
setup_ra_socket()
{
    int s, i, rc, one = 1, ff = 255;
    struct icmp6_filter filter;

    if(ra_socket >= 0) {
        close(ra_socket);
        ra_socket = -1;
    }

    s = socket(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
    if(s < 0)
        return -1;

    rc = setsockopt(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ff, sizeof(ff));
    if(rc < 0)
        goto fail;

    rc = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ff, sizeof(ff));
    if(rc < 0)
        goto fail;

    rc = setsockopt(s, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &one, sizeof(one));
    if(rc < 0)
        goto fail;

    for(i = 0; i < numinterfaces; i++) {
        struct ipv6_mreq mreq;
        const unsigned char all_routers[16] =
            {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02};
        if(interfaces[i].ifindex <= 0)
            continue;
        memset(&mreq, 0, sizeof(mreq));
        memcpy(&mreq.ipv6mr_multiaddr, &all_routers, 16);
        mreq.ipv6mr_interface = interfaces[i].ifindex;
        rc = setsockopt(s, IPPROTO_IPV6, IPV6_JOIN_GROUP,
                        (char*)&mreq, sizeof(mreq));
        if(rc < 0)
            goto fail;
    }

    ICMP6_FILTER_SETBLOCKALL(&filter);
    ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &filter);

    rc = setsockopt(s, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, sizeof(filter));
    if(rc < 0)
        goto fail;

    rc = fcntl(s, F_GETFD, 0);
    if(rc < 0)
        goto fail;

    rc = fcntl(s, F_SETFD, rc | FD_CLOEXEC);
    if(rc < 0)
        goto fail;

    rc = fcntl(s, F_GETFL, 0);
    if(rc < 0)
        goto fail;

    rc = fcntl(s, F_SETFL, (rc | O_NONBLOCK));
    if(rc < 0)
        goto fail;

    ra_socket = s;
    return s;

fail:
    return -1;
}
Example #12
0
int SetICMPv6SockOpt(int iSockfd)
{
    int val;
    int ret = -1;
    struct icmp6_filter stIcmpFlt;

    /* 接收其他报文信息 */
    val = 1;
    ret = setsockopt(iSockfd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &val, sizeof(val));
    if (0 > ret)
    {
        perror("setsockopt (IPV6_RECVPKTINFO) error ");
        return (-1);
    }

    /* 设置成2表示由内核完成校验和检查???? */
#if 0
    val = 2;
    ret = setsockopt(iSockfd, SOL_IPV6, IPV6_CHECKSUM, &val, sizeof(val));
    if (0 > ret)
    {
        perror("setsockopt (IPV6_CHECKSUM) error");
        return (-1);
    }
#endif

    /* 控制本socket发送出去的报文的跳数为255 */
    val = 255;
    ret = setsockopt(iSockfd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &val, sizeof(val));
    if (0 > ret)
    {
        perror("setsockopt (IPV6_UNICAST_HOPS) error");
        return (-1);
    }

    /* 设置本socket发送出去的所有多播报文的跳数为255 */
    val = 255;
    ret = setsockopt(iSockfd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &val, sizeof(val));
    if (0 > ret)
    {
        perror("setsockopt (IPV6_MULTICAST_HOPS) error");
        return (-1);
    }

    /* 设置本属性从而告诉recvmsg函数将收到的报文的hop也带上来给用户态,本属性默认没开启从而用户态收不到对应的hop */
    val = 1;
    ret = setsockopt(iSockfd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &val, sizeof(val));
    if (0 > ret)
    {
        perror("setsockopt (IPV6_RECVHOPLIMIT) error");
        return (-1);
    }

    /* 设置RAW过滤,只接收RA报文 */
    /*BEGIN 2032203980  m00182044 2012-06-10 modify*/
	#if 1
    /*END 2032203980  m00182044 2012-06-10 modify*/
	ICMP6_FILTER_SETBLOCKALL(&stIcmpFlt);
    ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &stIcmpFlt);
    ret = setsockopt(iSockfd, IPPROTO_ICMPV6, ICMP6_FILTER, &stIcmpFlt, sizeof(stIcmpFlt));
    if (0 > ret)
    {
        perror("setsockopt (ICMP6_FILTER) error");
        return (-1);
    }
	#endif

    // TODO: set socket no-block
    
    return 0;
}
Example #13
0
static PING *
ping_init (int type, int ident)
{
  int fd, err;
  const int on = 1;
  PING *p;
  struct icmp6_filter filter;

  /* Initialize raw ICMPv6 socket */
  fd = socket (PF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
  if (fd < 0)
    {
      if (errno == EPERM)
        error (EXIT_FAILURE, errno, NULL);

      return NULL;
    }

  /* Tell which ICMPs we are interested in.  */
  ICMP6_FILTER_SETBLOCKALL (&filter);
  ICMP6_FILTER_SETPASS (ICMP6_ECHO_REPLY, &filter);
  ICMP6_FILTER_SETPASS (ICMP6_DST_UNREACH, &filter);
  ICMP6_FILTER_SETPASS (ICMP6_PACKET_TOO_BIG, &filter);
  ICMP6_FILTER_SETPASS (ICMP6_TIME_EXCEEDED, &filter);
  ICMP6_FILTER_SETPASS (ICMP6_PARAM_PROB, &filter);

  err =
    setsockopt (fd, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, sizeof (filter));
  if (err)
    {
      close (fd);
      return NULL;
    }

  err = setsockopt (fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on, sizeof (on));
  if (err)
    {
      close (fd);
      return NULL;
    }

  /* Allocate PING structure and initialize it to default values */
  p = malloc (sizeof (*p));
  if (!p)
    {
      close (fd);
      return NULL;
    }

  memset (p, 0, sizeof (*p));

  p->ping_fd = fd;
  p->ping_count = DEFAULT_PING_COUNT;
  p->ping_interval = PING_DEFAULT_INTERVAL;
  p->ping_datalen = sizeof (struct icmp6_hdr);
  /* Make sure we use only 16 bits in this field, id for icmp is a u_short.  */
  p->ping_ident = ident & 0xFFFF;
  p->ping_cktab_size = PING_CKTABSIZE;
  gettimeofday (&p->ping_start_time, NULL);
  return p;
}
Example #14
0
static void ping(const char *host)
{
	char packet[datalen + MAXIPLEN + MAXICMPLEN];
	char buf[INET6_ADDRSTRLEN];
	int sockopt;
	struct msghdr msg;
	struct sockaddr_in6 from;
	struct iovec iov;
	char control_buf[CMSG_SPACE(36)];

	pingsock = create_icmp6_socket();

	memset(&pingaddr, 0, sizeof(struct sockaddr_in));

	pingaddr.sin6_family = AF_INET6;
	hostent = xgethostbyname2(host, AF_INET6);
	if (hostent->h_addrtype != AF_INET6)
		bb_error_msg_and_die("unknown address type; only AF_INET6 is currently supported.");

	memcpy(&pingaddr.sin6_addr, hostent->h_addr, sizeof(pingaddr.sin6_addr));

#ifdef ICMP6_FILTER
	{
		struct icmp6_filter filt;
		if (!(options & O_VERBOSE)) {
			ICMP6_FILTER_SETBLOCKALL(&filt);
#if 0
			if ((options & F_FQDN) || (options & F_FQDNOLD) ||
				(options & F_NODEADDR) || (options & F_SUPTYPES))
				ICMP6_FILTER_SETPASS(ICMP6_NI_REPLY, &filt);
			else
#endif
				ICMP6_FILTER_SETPASS(ICMP6_ECHO_REPLY, &filt);
		} else {
			ICMP6_FILTER_SETPASSALL(&filt);
		}
		if (setsockopt(pingsock, IPPROTO_ICMPV6, ICMP6_FILTER, &filt,
					   sizeof(filt)) < 0)
			bb_error_msg_and_die("setsockopt(ICMP6_FILTER)");
	}
#endif /*ICMP6_FILTER*/

	/* enable broadcast pings */
	sockopt = 1;
	setsockopt(pingsock, SOL_SOCKET, SO_BROADCAST, (char *) &sockopt,
			   sizeof(sockopt));

	/* set recv buf for broadcast pings */
	sockopt = 48 * 1024;
	setsockopt(pingsock, SOL_SOCKET, SO_RCVBUF, (char *) &sockopt,
			   sizeof(sockopt));

	sockopt = offsetof(struct icmp6_hdr, icmp6_cksum);
	setsockopt(pingsock, SOL_RAW, IPV6_CHECKSUM, (char *) &sockopt,
			   sizeof(sockopt));

	sockopt = 1;
	setsockopt(pingsock, SOL_IPV6, IPV6_HOPLIMIT, (char *) &sockopt,
			   sizeof(sockopt));

	if (ifname) {
		if ((pingaddr.sin6_scope_id = if_nametoindex(ifname)) == 0)
			bb_error_msg_and_die("%s: invalid interface name", ifname);
	}

	printf("PING %s (%s): %d data bytes\n",
	           hostent->h_name,
			   inet_ntop(AF_INET6, (struct in_addr6 *) &pingaddr.sin6_addr,
						 buf, sizeof(buf)),
		   datalen);

	signal(SIGINT, pingstats);

	/* start the ping's going ... */
	sendping(0);

	/* listen for replies */
	msg.msg_name=&from;
	msg.msg_namelen=sizeof(from);
	msg.msg_iov=&iov;
	msg.msg_iovlen=1;
	msg.msg_control=control_buf;
	iov.iov_base=packet;
	iov.iov_len=sizeof(packet);
	while (1) {
		int c;
		struct cmsghdr *cmsgptr = NULL;
		int hoplimit=-1;
		msg.msg_controllen=sizeof(control_buf);

		if ((c = recvmsg(pingsock, &msg, 0)) < 0) {
			if (errno == EINTR)
				continue;
			bb_perror_msg("recvfrom");
			continue;
		}
		for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL;
			 cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
			if (cmsgptr->cmsg_level == SOL_IPV6 &&
				cmsgptr->cmsg_type == IPV6_HOPLIMIT ) {
				hoplimit=*(int*)CMSG_DATA(cmsgptr);
			}
		}
		unpack(packet, c, &from, hoplimit);
		if (pingcount > 0 && nreceived >= pingcount)
			break;
	}
	pingstats(0);
}
Example #15
0
/* functional tests */
void icmp6_ft(void)
{
	struct icmp6_filter i6f;
	int sall, sf;
	int i;

	sall = socket(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
	if (sall < 0) {
		tst_resm(TBROK | TERRNO,
			 "icmp6_ft socket: can't create sall socket");
		return;
	}
	ICMP6_FILTER_SETPASSALL(&i6f);
	if (setsockopt(sall, IPPROTO_ICMPV6, ICMP6_FILTER, &i6f,
		       sizeof(i6f)) < 0) {
		tst_resm(TBROK | TERRNO,
			 "setsockopt pass all ICMP6_FILTER failed");
	}

	sf = socket(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
	if (sf < 0) {
		tst_resm(TBROK | TERRNO,
			 "icmp6_ft socket: can't create test socket");
		return;
	}

	int rv;

	for (i = 0; i < FTCOUNT; ++i) {

		rv = -1;

		switch (ftab[i].ft_test) {
		case T_SETPASS:
			ICMP6_FILTER_SETBLOCKALL(&i6f);
			ICMP6_FILTER_SETPASS(ftab[i].ft_flttype, &i6f);
			break;
		case T_SETPASSALL:
			ICMP6_FILTER_SETPASSALL(&i6f);
			break;
		case T_SETBLOCK:
			ICMP6_FILTER_SETPASSALL(&i6f);
			ICMP6_FILTER_SETBLOCK(ftab[i].ft_flttype, &i6f);
			break;
		case T_SETBLOCKALL:
			ICMP6_FILTER_SETBLOCKALL(&i6f);
			break;
		case T_WILLBLOCK:
			ICMP6_FILTER_SETPASSALL(&i6f);
			ICMP6_FILTER_SETBLOCK(ftab[i].ft_flttype, &i6f);
			rv = ICMP6_FILTER_WILLBLOCK(ftab[i].ft_sndtype, &i6f);
			break;
		case T_WILLPASS:
			ICMP6_FILTER_SETBLOCKALL(&i6f);
			ICMP6_FILTER_SETPASS(ftab[i].ft_flttype, &i6f);
			rv = ICMP6_FILTER_WILLPASS(ftab[i].ft_sndtype, &i6f);
			break;
		default:
			tst_resm(TBROK, "%s: unknown test type %d",
				 ftab[i].ft_tname, ftab[i].ft_test);
			continue;
		}
		if (ftab[i].ft_test != T_WILLBLOCK &&
		    ftab[i].ft_test != T_WILLPASS) {
			if (setsockopt(sf, IPPROTO_ICMPV6, ICMP6_FILTER, &i6f,
				       sizeof(i6f)) < 0) {
				tst_resm(TFAIL | TERRNO,
					 "setsockopt ICMP6_FILTER");
				continue;
			}
			if (ic6_send1(ftab[i].ft_tname, ftab[i].ft_sndtype))
				continue;
			rv = ic6_recv1(ftab[i].ft_tname, sall, sf);
		} else
			rv = -1;

		if (rv < 0)
			continue;
		if (rv != ftab[i].ft_expected)
			tst_resm(TFAIL, "%s: rv %d != expected %d",
				 ftab[i].ft_tname, rv, ftab[i].ft_expected);
		else
			tst_resm(TPASS, ftab[i].ft_tname);
	}
}
Example #16
0
/*******************************************************************************
 函数名称  :    healthy_check_ipping_init
 功能描述  :    ping 检测启动函数
 输入参数  :    hc_ping_s *ping_cfg: 当前ip 配置结构
 输出参数  :    无
 返回值        :    ERROR_SUCCESS                               处理成功
                               HC_ERR_SOCKET_INIT_FAIL            socket 建立失败
                               HC_ERR_SET_SOCK_OPT_FAIL        设置socket 选项失败
--------------------------------------------------------------------------------
 最近一次修改记录 :
 修改作者   :       王宗发
 修改目的   :       新增函数
 修改日期   :       20101020
********************************************************************************/
s32 healthy_check_ipping_init(hc_ping_s *ping_cfg)
{
    s32 fd;
    s32 val = 1;
	s32 var = 0;
    s32 err_tmp = ERROR_SUCCESS;
    struct ifreq ifreq;
    struct icmp6_filter filter;

    fd = socket (AF_INET6, SOCK_RAW, g_hc_ping_checker.proto);
    if (fd < 0)
    {
        ping_cfg->ping_check_flag = HC_ERR_SOCKET_INIT_FAIL;
        if (errno == EPERM)
        {
            printf("ping: ping must run as root\n");
        }
        return !ERROR_SUCCESS;
    }
    
    ping_cfg->fd = fd;
	
	var = fcntl(fd, F_GETFL, 0);
    fcntl(fd, F_SETFL, O_NONBLOCK | var);
    
    ICMP6_FILTER_SETBLOCKALL (&filter);
    ICMP6_FILTER_SETPASS (ICMP6_ECHO_REPLY, &filter);
    
    err_tmp = setsockopt (fd, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, sizeof (filter));
    if(ERROR_SUCCESS != err_tmp)
    {
        close (fd);
        ping_cfg->ping_check_flag = HC_ERR_SET_SOCK_OPT_FAIL;
        return err_tmp;
    }
    /*
    err_tmp = setsockopt (fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, (char *)&val, sizeof(val));
    if(ERROR_SUCCESS != err_tmp)
    {
        close (fd);
        ping_cfg->ping_check_flag = HC_ERR_SET_SOCK_OPT_FAIL;
        return err_tmp;
    }
    */
    err_tmp = setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (char *) &val, sizeof(val));
    if(ERROR_SUCCESS != err_tmp)
    {
        close(fd);
        ping_cfg->ping_check_flag = HC_ERR_SET_SOCK_OPT_FAIL;
        return err_tmp;
    }

    /*检查是否指定接口*/
    if('\0' != *(ping_cfg->if_name))
    {
        memset(&ifreq, 0, sizeof(ifreq));
        strncpy((char *)&ifreq.ifr_name, (s8 *)(ping_cfg->if_name), sizeof (ifreq.ifr_name));
        err_tmp = setsockopt (fd, SOL_SOCKET, SO_BINDTODEVICE, &ifreq, sizeof (ifreq)); 
        if(ERROR_SUCCESS != err_tmp)
        {
            close(fd);
            ping_cfg->ping_check_flag = HC_ERR_SET_SOCK_OPT_FAIL;
            return err_tmp;
        }
    }
    
    /*入参中有端口参数时,设置tos字段,走策略路由 */
    /*
    if(0 != ping_cfg->tos)
    {
        err_tmp = setsockopt(ping_cfg->fd, IPPROTO_IPV6, IP_TOS, (const char *)&(ping_cfg->tos), sizeof(ping_cfg->tos));
        if(ERROR_SUCCESS != err_tmp)
        {
            close(fd);
            ping_cfg->ping_check_flag = HC_ERR_SET_SOCK_OPT_FAIL;
            return err_tmp;
        }
    }
    */
    return err_tmp;
}
Example #17
0
void
traceloop(void)
{
	int seq, code, done;
	double rtt;
	struct rec *rec;
	struct timeval tvrecv;

	recvfd = socket(pr->sasend->sa_family, SOCK_RAW, pr->icmpproto);
	setuid(getuid());		/* don't need special permissions anymore */

#ifdef	IPV6
	if (pr->sasend->sa_family == AF_INET6 && verbose == 0) {
		struct icmp6_filter myfilt;
		ICMP6_FILTER_SETBLOCKALL(&myfilt);
		ICMP6_FILTER_SETPASS(ICMP6_TIME_EXCEEDED, &myfilt);
		ICMP6_FILTER_SETPASS(ICMP6_DST_UNREACH, &myfilt);
		setsockopt(recvfd, IPPROTO_IPV6, ICMP6_FILTER,
					&myfilt, sizeof(myfilt));
	}
#endif

	sendfd = socket(pr->sasend->sa_family, SOCK_DGRAM, 0);

	pr->sabind->sa_family = pr->sasend->sa_family;
	sport = (getpid() & 0xffff) | 0x8000;	/* our source UDP port # */
	sock_set_port(pr->sabind, pr->salen, htons(sport));
	bind(sendfd, pr->sabind, pr->salen);

	sig_alrm(SIGALRM);

	seq = 0;
	done = 0;
	for (ttl = 1; ttl <= max_ttl && done == 0; ttl++) {
		setsockopt(sendfd, pr->ttllevel, pr->ttloptname, &ttl, sizeof(int));
		bzero(pr->salast, pr->salen);

		printf("%2d ", ttl);
		fflush(stdout);

		for (probe = 0; probe < nprobes; probe++) {
			rec = (struct rec *) sendbuf;
			rec->rec_seq = ++seq;
			rec->rec_ttl = ttl;
			gettimeofday(&rec->rec_tv, NULL);

			sock_set_port(pr->sasend, pr->salen, htons(dport + seq));
			sendto(sendfd, sendbuf, datalen, 0, pr->sasend, pr->salen);

			if ( (code = (*pr->recv)(seq, &tvrecv)) == -3)
				printf(" *");		/* timeout, no reply */
			else {
				char	str[NI_MAXHOST];

				if (sock_cmp_addr(pr->sarecv, pr->salast, pr->salen) != 0) {
					if (getnameinfo(pr->sarecv, pr->salen, str, sizeof(str),
						NULL, 0, 0) == 0)
						printf(" %s (%s)", str,
							sock_ntop_host(pr->sarecv, pr->salen, ipstr, sizeof(ipstr)));
					else
						printf(" %s",
							sock_ntop_host(pr->sarecv, pr->salen, ipstr, sizeof(ipstr)));
					memcpy(pr->salast, pr->sarecv, pr->salen);
				}
				tv_sub(&tvrecv, &rec->rec_tv);
				rtt = tvrecv.tv_sec * 1000.0 + tvrecv.tv_usec / 1000.0;
				printf("  %.3f ms", rtt);

				if (code == -1)		/* port unreachable; at destination */
					done++;
				else if (code >= 0)
					printf(" (ICMP %s)", (*pr->icmpcode)(code));
			}
			fflush(stdout);
		}
		printf("\n");
	}
}
Example #18
0
static int
ipv6ns_open(void)
{
	int on;
	int len;
	struct icmp6_filter filt;
#ifdef IPV6_SEND_DAD
	union {
		struct sockaddr sa;
		struct sockaddr_in6 sin;
	} su;
#endif

	if (sock != -1)
		return sock;

	sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
	if (sock == -1)
		return -1;
	on = 1;
	if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO,
	    &on, sizeof(on)) == -1)
		goto eexit;

	on = 1;
	if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT,
	    &on, sizeof(on)) == -1)
		goto eexit;

	ICMP6_FILTER_SETBLOCKALL(&filt);

#ifdef IPV6_SEND_DAD
	/* We send DAD requests from the unspecified address. */
	unspec_sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
	if (unspec_sock == -1)
		goto eexit;
	if (setsockopt(unspec_sock, IPPROTO_ICMPV6, ICMP6_FILTER,
	    &filt, sizeof(filt)) == -1)
		goto eexit;
	memset(&su, 0, sizeof(su));
	su.sin.sin6_family = AF_INET6;
#ifdef SIN6_LEN
	su.sin.sin6_len = sizeof(su.sin);
#endif
	if (bind(unspec_sock, &su.sa, sizeof(su.sin)) == -1)
		goto eexit;
#endif

	ICMP6_FILTER_SETPASS(ND_NEIGHBOR_ADVERT, &filt);
	if (setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER,
	    &filt, sizeof(filt)) == -1)
		goto eexit;

	set_cloexec(sock);
#if DEBUG_MEMORY
	atexit(ipv6ns_cleanup);
#endif

#ifdef LISTEN_DAD
	syslog(LOG_WARNING, "kernel does not report DAD results to userland");
	syslog(LOG_WARNING,
	    "warning listening to duplicated addresses on the wire");
#endif

	len = CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(sizeof(int));
	sndbuf = calloc(1, len);
	if (sndbuf == NULL)
		goto eexit;
	sndhdr.msg_namelen = sizeof(struct sockaddr_in6);
	sndhdr.msg_iov = sndiov;
	sndhdr.msg_iovlen = 1;
	sndhdr.msg_control = sndbuf;
	sndhdr.msg_controllen = len;
	rcvbuf = calloc(1, len);
	if (rcvbuf == NULL)
		goto eexit;
	rcvhdr.msg_name = &from;
	rcvhdr.msg_namelen = sizeof(from);
	rcvhdr.msg_iov = rcviov;
	rcvhdr.msg_iovlen = 1;
	rcvhdr.msg_control = rcvbuf;
	rcvhdr.msg_controllen = len;
	rcviov[0].iov_base = ansbuf;
	rcviov[0].iov_len = sizeof(ansbuf);

	eloop_event_add(sock, ipv6ns_handledata, NULL);
	return sock;

eexit:
	syslog(LOG_ERR, "%s: %m", __func__);
	close(sock);
	sock = -1;
	free(sndbuf);
	sndbuf = NULL;
	free(rcvbuf);
	rcvbuf = NULL;
	return -1;
}
Example #19
0
/**
 *  Entry point.
 */
extern "C" DECLEXPORT(int) TrustedMain(int argc, char **argv, char **envp)
{
    int rc;

    LogFlowFuncEnter();

    NOREF(envp);

#ifdef RT_OS_WINDOWS
    WSADATA wsaData;
    int err;

    err = WSAStartup(MAKEWORD(2,2), &wsaData);
    if (err)
    {
        fprintf(stderr, "wsastartup: failed (%d)\n", err);
        return 1;
    }
#endif

    SOCKET icmpsock4 = INVALID_SOCKET;
    SOCKET icmpsock6 = INVALID_SOCKET;
#ifndef RT_OS_DARWIN
    const int icmpstype = SOCK_RAW;
#else
    /* on OS X it's not privileged */
    const int icmpstype = SOCK_DGRAM;
#endif

    icmpsock4 = socket(AF_INET, icmpstype, IPPROTO_ICMP);
    if (icmpsock4 == INVALID_SOCKET)
    {
        perror("IPPROTO_ICMP");
#ifdef VBOX_RAWSOCK_DEBUG_HELPER
        icmpsock4 = getrawsock(AF_INET);
#endif
    }

    if (icmpsock4 != INVALID_SOCKET)
    {
#ifdef ICMP_FILTER              //  Linux specific
        struct icmp_filter flt = {
            ~(uint32_t)(
                  (1U << ICMP_ECHOREPLY)
                | (1U << ICMP_DEST_UNREACH)
                | (1U << ICMP_TIME_EXCEEDED)
            )
        };

        int status = setsockopt(icmpsock4, SOL_RAW, ICMP_FILTER,
                                &flt, sizeof(flt));
        if (status < 0)
        {
            perror("ICMP_FILTER");
        }
#endif
    }

    icmpsock6 = socket(AF_INET6, icmpstype, IPPROTO_ICMPV6);
    if (icmpsock6 == INVALID_SOCKET)
    {
        perror("IPPROTO_ICMPV6");
#ifdef VBOX_RAWSOCK_DEBUG_HELPER
        icmpsock6 = getrawsock(AF_INET6);
#endif
    }

    if (icmpsock6 != INVALID_SOCKET)
    {
#ifdef ICMP6_FILTER             // Windows doesn't support RFC 3542 API
        /*
         * XXX: We do this here for now, not in pxping.c, to avoid
         * name clashes between lwIP and system headers.
         */
        struct icmp6_filter flt;
        ICMP6_FILTER_SETBLOCKALL(&flt);

        ICMP6_FILTER_SETPASS(ICMP6_ECHO_REPLY, &flt);

        ICMP6_FILTER_SETPASS(ICMP6_DST_UNREACH, &flt);
        ICMP6_FILTER_SETPASS(ICMP6_PACKET_TOO_BIG, &flt);
        ICMP6_FILTER_SETPASS(ICMP6_TIME_EXCEEDED, &flt);
        ICMP6_FILTER_SETPASS(ICMP6_PARAM_PROB, &flt);

        int status = setsockopt(icmpsock6, IPPROTO_ICMPV6, ICMP6_FILTER,
                                &flt, sizeof(flt));
        if (status < 0)
        {
            perror("ICMP6_FILTER");
        }
#endif
    }

    HRESULT hrc = com::Initialize();
    if (FAILED(hrc))
    {
#ifdef VBOX_WITH_XPCOM
        if (hrc == NS_ERROR_FILE_ACCESS_DENIED)
        {
            char szHome[RTPATH_MAX] = "";
            int vrc = com::GetVBoxUserHomeDirectory(szHome, sizeof(szHome), false);
            if (RT_SUCCESS(vrc))
            {
                return RTMsgErrorExit(RTEXITCODE_FAILURE,
                                      "Failed to initialize COM: %s: %Rhrf",
                                      szHome, hrc);
            }
        }
#endif  // VBOX_WITH_XPCOM
        return RTMsgErrorExit(RTEXITCODE_FAILURE,
                              "Failed to initialize COM: %Rhrf", hrc);
    }

    rc = vboxNetNATLogInit(argc, argv);
    // shall we bail if we failed to init logging?

    g_pLwipNat = new VBoxNetLwipNAT(icmpsock4, icmpsock6);

    Log2(("NAT: initialization\n"));
    rc = g_pLwipNat->parseArgs(argc - 1, argv + 1);
    rc = (rc == 0) ? VINF_SUCCESS : VERR_GENERAL_FAILURE; /* XXX: FIXME */

    if (RT_SUCCESS(rc))
        rc = g_pLwipNat->init();

    if (RT_SUCCESS(rc))
        g_pLwipNat->run();

    delete g_pLwipNat;
    return 0;
}
Example #20
0
int
sockopen(void)
{
	static u_char *rcvcmsgbuf = NULL, *sndcmsgbuf = NULL;
	int sndcmsglen, on;
	static u_char answer[1500];
	struct icmp6_filter filt;

	sndcmsglen = rcvcmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)) +
	    CMSG_SPACE(sizeof(int));
	if (rcvcmsgbuf == NULL && (rcvcmsgbuf = malloc(rcvcmsglen)) == NULL) {
		warnmsg(LOG_ERR, __func__,
		    "malloc for receive msghdr failed");
		return (-1);
	}
	if (sndcmsgbuf == NULL && (sndcmsgbuf = malloc(sndcmsglen)) == NULL) {
		warnmsg(LOG_ERR, __func__,
		    "malloc for send msghdr failed");
		return (-1);
	}
	if ((rssock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) {
		warnmsg(LOG_ERR, __func__, "socket: %s", strerror(errno));
		return (-1);
	}

	/* specify to tell receiving interface */
	on = 1;
	if (setsockopt(rssock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on,
	    sizeof(on)) < 0) {
		warnmsg(LOG_ERR, __func__, "IPV6_RECVPKTINFO: %s",
		    strerror(errno));
		exit(1);
	}

	/* specify to tell value of hoplimit field of received IP6 hdr */
	on = 1;
	if (setsockopt(rssock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on,
	    sizeof(on)) < 0) {
		warnmsg(LOG_ERR, __func__, "IPV6_RECVHOPLIMIT: %s",
		    strerror(errno));
		exit(1);
	}

	/* specfiy to accept only router advertisements on the socket */
	ICMP6_FILTER_SETBLOCKALL(&filt);
	ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filt);
	if (setsockopt(rssock, IPPROTO_ICMPV6, ICMP6_FILTER, &filt,
	    sizeof(filt)) == -1) {
		warnmsg(LOG_ERR, __func__, "setsockopt(ICMP6_FILTER): %s",
		    strerror(errno));
		return(-1);
	}

	/* initialize msghdr for receiving packets */
	rcviov[0].iov_base = (caddr_t)answer;
	rcviov[0].iov_len = sizeof(answer);
	rcvmhdr.msg_name = (caddr_t)&from;
	rcvmhdr.msg_iov = rcviov;
	rcvmhdr.msg_iovlen = 1;
	rcvmhdr.msg_control = (caddr_t) rcvcmsgbuf;

	/* initialize msghdr for sending packets */
	sndmhdr.msg_namelen = sizeof(struct sockaddr_in6);
	sndmhdr.msg_iov = sndiov;
	sndmhdr.msg_iovlen = 1;
	sndmhdr.msg_control = (caddr_t)sndcmsgbuf;
	sndmhdr.msg_controllen = sndcmsglen;

	return (rssock);
}
Example #21
0
STATUS init_mproxy6(mcast_proxy *p_mp)
{
    struct icmp6_filter filt;
    int             on;


#ifdef ENABLE_IMP_MLD
    if (p_mp->mld_version != IM_DISABLE) {

        struct in6_addr all_ipv6_router;
        imp_interface* p_if = NULL;

        p_mp->mld_socket = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);

        if(p_mp->mld_socket == -1)
        {
            IMP_LOG_ERROR("can't create mld socket\n");
            return STATUS_NOK;
        }

        /* filter all non-MLD ICMP messages */
        ICMP6_FILTER_SETBLOCKALL(&filt);
        ICMP6_FILTER_SETPASS(MLD_LISTENER_REPORT, &filt);
        ICMP6_FILTER_SETPASS(MLD_LISTENER_REDUCTION, &filt);
        ICMP6_FILTER_SETPASS(MLD_V2_LISTENER_REPORT, &filt);

        if (setsockopt(p_mp->mld_socket, IPPROTO_ICMPV6, ICMP6_FILTER, &filt,
               sizeof(filt)) < 0)
            IMP_LOG_ERROR("ICMP6_FILTER: %s\n", strerror(errno));

        /* specify to tell receiving interface */
        on = 1;
        if (setsockopt(p_mp->mld_socket, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on,
               sizeof(on)) < 0)
            IMP_LOG_ERROR("IPV6_RECVPKTINFO: %s\n", strerror(errno));

        on = 1;
        if (setsockopt(p_mp->mld_socket, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &on,
               sizeof(on)) < 0)
            IMP_LOG_ERROR("IPV6_MULTICAST_HOPS: %s\n", strerror(errno));

        on = 0;
        if (setsockopt(p_mp->mld_socket, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &on,
               sizeof(on)) < 0)
            IMP_LOG_ERROR("IPV6_MULTICAST_LOOP: %s\n", strerror(errno));

        on = 1;
        if (setsockopt(p_mp->mld_socket, IPPROTO_IPV6, IPV6_RECVHOPOPTS, &on,
               sizeof(on)) < 0)
            IMP_LOG_ERROR("IPV6_RECVHOPOPTS: %s\n", strerror(errno));


        if (k_start6_mproxy(p_mp->mld_socket) < 0 )
            return STATUS_NOK;

        IMP_LOG_DEBUG("p_mp->mld_socket = %d\n", p_mp->mld_socket);
        p_mp->mld_udp_socket = socket(AF_INET6, SOCK_DGRAM, 0);
        if(p_mp->mld_udp_socket == -1)
        {
            IMP_LOG_ERROR("can't create mld udp socket\n");
            return STATUS_NOK;
        }

        for(p_if = imp_interface_first(); p_if; p_if = LIST_NEXT(p_if, link)){

            if(p_if->if_addr.ss.ss_family != AF_INET6 ||
                p_if->type != INTERFACE_DOWNSTREAM)
                continue;

            if(inet_pton(AF_INET6, "FF02::2", &all_ipv6_router) == 1) {

                pi_addr pir;
                imp_build_piaddr(AF_INET6, &all_ipv6_router, &pir);

                if(k_mcast_join(&pir, p_if->if_name) < 0)
                    IMP_LOG_DEBUG("k_mcast_join: %s\n", strerror(errno));

            }
            if(inet_pton(AF_INET6, "FF02::16", &all_ipv6_router) == 1) {

                pi_addr pir;
                imp_build_piaddr(AF_INET6, &all_ipv6_router, &pir);

                if(k_mcast_join(&pir, p_if->if_name) < 0)
                    IMP_LOG_DEBUG("k_mcast_join: %s\n", strerror(errno));

            }
        }
    }
#endif
    return STATUS_OK;
}
Example #22
0
	void pass(uint type_value)
	{
		ICMP6_FILTER_SETPASS(type_value, &_filter);
	}
Example #23
0
static void
sock6_open(struct flags *flags
#ifdef IPSEC_POLICY_IPSEC
	   , char *policy
#endif /* IPSEC_POLICY_IPSEC */
	   )
{
	struct icmp6_filter filt;
	int on;
#ifdef IPSEC
#ifndef IPSEC_POLICY_IPSEC
	int optval;
#endif
#endif

	if (with_v6dest == 0)
		return;
	if (with_v6dest &&
	    (s6 = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) {
		syslog(LOG_ERR, "<%s> socket(v6): %s", __func__,
		       strerror(errno));
		exit(1);
	}

	/*
	 * join all routers multicast addresses.
	 */
#if 0 /* XXX: not necessary ?? */
	join_multi(LL_ALLROUTERS);
	join_multi(SL_ALLROUTERS);
#endif

	/* set icmpv6 filter */
	ICMP6_FILTER_SETBLOCKALL(&filt);
	ICMP6_FILTER_SETPASS(ICMP6_ROUTER_RENUMBERING, &filt);
	if (setsockopt(s6, IPPROTO_ICMPV6, ICMP6_FILTER, &filt,
		       sizeof(filt)) < 0) {
		syslog(LOG_ERR, "<%s> IICMP6_FILTER: %s",
		       __func__, strerror(errno));
		exit(1);
	}

	/* specify to tell receiving interface */
	on = 1;
	if (setsockopt(s6, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on,
		       sizeof(on)) < 0) {
		syslog(LOG_ERR, "<%s> IPV6_RECVPKTINFO: %s",
		       __func__, strerror(errno));
		exit(1);
	}

#ifdef IPSEC
#ifdef IPSEC_POLICY_IPSEC
	if (flags->policy) {
		char *buf;
		buf = ipsec_set_policy(policy, strlen(policy));
		if (buf == NULL)
			errx(1, "%s", ipsec_strerror());
		/* XXX should handle in/out bound policy. */
		if (setsockopt(s6, IPPROTO_IPV6, IPV6_IPSEC_POLICY,
				buf, ipsec_get_policylen(buf)) < 0)
			err(1, "setsockopt(IPV6_IPSEC_POLICY)");
		free(buf);
	}
#else /* IPSEC_POLICY_IPSEC */
	if (flags->auth) {
		optval = IPSEC_LEVEL_REQUIRE;
		if (setsockopt(s6, IPPROTO_IPV6, IPV6_AUTH_TRANS_LEVEL,
			       &optval, sizeof(optval)) == -1) {
			syslog(LOG_ERR, "<%s> IPV6_AUTH_TRANS_LEVEL: %s",
			       __func__, strerror(errno));
			exit(1);
		}
	}
	if (flags->encrypt) {
		optval = IPSEC_LEVEL_REQUIRE;
		if (setsockopt(s6, IPPROTO_IPV6, IPV6_ESP_TRANS_LEVEL,
				&optval, sizeof(optval)) == -1) {
			syslog(LOG_ERR, "<%s> IPV6_ESP_TRANS_LEVEL: %s",
			       __func__, strerror(errno));
			exit(1);
		}
	}
#endif /* IPSEC_POLICY_IPSEC */
#endif /* IPSEC */

	return;
}
int main(int argc, char *argv[])
{
	int ch, hold, packlen;
	u_char *packet;
	char *target;
	struct addrinfo hints, *ai;
	int gai;
	struct sockaddr_in6 firsthop;
	int socket_errno = 0;
	struct icmp6_filter filter;
	int err;
#ifdef __linux__
	int csum_offset, sz_opt;
#endif
	static uint32_t scope_id = 0;

#ifdef ANDROID
	android_check_security();
#endif

	limit_capabilities();

#ifdef USE_IDN
	setlocale(LC_ALL, "");
#endif

	icmp_sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_ICMPV6);
	if (icmp_sock < 0) {
		enable_capability_raw();
		icmp_sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
		socket_errno = errno;
		disable_capability_raw();
		using_ping_socket = 0;
	}

	source.sin6_family = AF_INET6;
	memset(&firsthop, 0, sizeof(firsthop));
	firsthop.sin6_family = AF_INET6;

	preload = 1;
	while ((ch = getopt(argc, argv, COMMON_OPTSTR "F:N:")) != EOF) {
		switch(ch) {
		case 'F':
			flowlabel = hextoui(optarg);
			if (errno || (flowlabel & ~IPV6_FLOWINFO_FLOWLABEL)) {
				fprintf(stderr, "ping: Invalid flowinfo %s\n", optarg);
				exit(2);
			}
			options |= F_FLOWINFO;
			break;
		case 'Q':
			tclass = hextoui(optarg);
			if (errno || (tclass & ~0xff)) {
				fprintf(stderr, "ping: Invalid tclass %s\n", optarg);
				exit(2);
			}
			options |= F_TCLASS;
			break;
		case 'I':
			if (strchr(optarg, ':')) {
				char *p, *addr = strdup(optarg);

				if (!addr) {
					fprintf(stderr, "ping: out of memory\n");
					exit(2);
				}

				p = strchr(addr, SCOPE_DELIMITER);
				if (p) {
					*p = '\0';
					device = optarg + (p - addr) + 1;
				}

				if (inet_pton(AF_INET6, addr, (char*)&source.sin6_addr) <= 0) {
					fprintf(stderr, "ping: invalid source address %s\n", optarg);
					exit(2);
				}

				options |= F_STRICTSOURCE;

				free(addr);
			} else {
				device = optarg;
			}
			break;
		case 'M':
			if (strcmp(optarg, "do") == 0)
				pmtudisc = IPV6_PMTUDISC_DO;
			else if (strcmp(optarg, "dont") == 0)
				pmtudisc = IPV6_PMTUDISC_DONT;
			else if (strcmp(optarg, "want") == 0)
				pmtudisc = IPV6_PMTUDISC_WANT;
			else {
				fprintf(stderr, "ping: wrong value for -M: do, dont, want are valid ones.\n");
				exit(2);
			}
			break;
		case 'V':
			printf("ping6 utility, iputils-%s\n", SNAPSHOT);
			exit(0);
		case 'N':
			if (using_ping_socket) {
				fprintf(stderr, "ping: -N requires raw socket permissions\n");
				exit(2);
			}
			if (niquery_option_handler(optarg) < 0) {
				usage();
				break;
			}
			break;
		COMMON_OPTIONS
			common_options(ch);
			break;
		default:
			usage();
		}
	}
	argc -= optind;
	argv += optind;

#ifdef ENABLE_PING6_RTHDR
	while (argc > 1) {
		struct in6_addr *addr;

		if (srcrt == NULL) {
			int space;

			fprintf(stderr, "ping6: Warning: "
					"Source routing is deprecated by RFC5095.\n");

#ifdef ENABLE_PING6_RTHDR_RFC3542
			space = inet6_rth_space(IPV6_RTHDR_TYPE_0, argc - 1);
#else
			space = inet6_srcrt_space(IPV6_SRCRT_TYPE_0, argc - 1);
#endif
			if (space == 0)	{
				fprintf(stderr, "srcrt_space failed\n");
				exit(2);
			}
#ifdef ENABLE_PING6_RTHDR_RFC3542
			if (cmsglen + CMSG_SPACE(space) > sizeof(cmsgbuf)) {
				fprintf(stderr, "no room for options\n");
				exit(2);
			}
#else
			if (space + cmsglen > sizeof(cmsgbuf)) {
				fprintf(stderr, "no room for options\n");
				exit(2);
			}
#endif
			srcrt = (struct cmsghdr*)(cmsgbuf+cmsglen);
#ifdef ENABLE_PING6_RTHDR_RFC3542
			memset(srcrt, 0, CMSG_SPACE(0));
			srcrt->cmsg_len = CMSG_LEN(space);
			srcrt->cmsg_level = IPPROTO_IPV6;
			srcrt->cmsg_type = IPV6_RTHDR;
			inet6_rth_init(CMSG_DATA(srcrt), space, IPV6_RTHDR_TYPE_0, argc - 1);
			cmsglen += CMSG_SPACE(space);
#else
			cmsglen += CMSG_ALIGN(space);
			inet6_srcrt_init(srcrt, IPV6_SRCRT_TYPE_0);
#endif
		}

		target = *argv;

		memset(&hints, 0, sizeof(hints));
		hints.ai_family = AF_INET6;
#ifdef USE_IDN
		hints.ai_flags = AI_IDN;
#endif
		gai = getaddrinfo(target, NULL, &hints, &ai);
		if (gai) {
			fprintf(stderr, "unknown host\n");
			exit(2);
		}
		addr = &((struct sockaddr_in6 *)(ai->ai_addr))->sin6_addr;
#ifdef ENABLE_PING6_RTHDR_RFC3542
		inet6_rth_add(CMSG_DATA(srcrt), addr);
#else
		inet6_srcrt_add(srcrt, addr);
#endif
		if (IN6_IS_ADDR_UNSPECIFIED(&firsthop.sin6_addr)) {
			memcpy(&firsthop.sin6_addr, addr, 16);
#ifdef HAVE_SIN6_SCOPEID
			firsthop.sin6_scope_id = ((struct sockaddr_in6 *)(ai->ai_addr))->sin6_scope_id;
			/* Verify scope_id is the same as previous nodes */
			if (firsthop.sin6_scope_id && scope_id && firsthop.sin6_scope_id != scope_id) {
				fprintf(stderr, "scope discrepancy among the nodes\n");
				exit(2);
			} else if (!scope_id) {
				scope_id = firsthop.sin6_scope_id;
			}
#endif
		}
		freeaddrinfo(ai);

		argv++;
		argc--;
	}
#endif

	if (niquery_is_enabled()) {
		niquery_init_nonce();

		if (!niquery_is_subject_valid()) {
			ni_subject = &whereto.sin6_addr;
			ni_subject_len = sizeof(whereto.sin6_addr);
			ni_subject_type = NI_SUBJ_IPV6;
		}
	}

	if (argc > 1) {
#ifndef ENABLE_PING6_RTHDR
		fprintf(stderr, "ping6: Source routing is deprecated by RFC5095.\n");
#endif
		usage();
	} else if (argc == 1) {
		target = *argv;
	} else {
		if (ni_query < 0 && ni_subject_type != NI_SUBJ_NAME)
			usage();
		target = ni_group;
	}

	memset(&hints, 0, sizeof(hints));
	hints.ai_family = AF_INET6;
#ifdef USE_IDN
	hints.ai_flags = AI_IDN;
#endif
	gai = getaddrinfo(target, NULL, &hints, &ai);
	if (gai) {
		fprintf(stderr, "unknown host\n");
		exit(2);
	}

	memcpy(&whereto, ai->ai_addr, sizeof(whereto));
	whereto.sin6_port = htons(IPPROTO_ICMPV6);

	if (memchr(target, ':', strlen(target)))
		options |= F_NUMERIC;

	freeaddrinfo(ai);

	if (IN6_IS_ADDR_UNSPECIFIED(&firsthop.sin6_addr)) {
		memcpy(&firsthop.sin6_addr, &whereto.sin6_addr, 16);
#ifdef HAVE_SIN6_SCOPEID
		firsthop.sin6_scope_id = whereto.sin6_scope_id;
		/* Verify scope_id is the same as intermediate nodes */
		if (firsthop.sin6_scope_id && scope_id && firsthop.sin6_scope_id != scope_id) {
			fprintf(stderr, "scope discrepancy among the nodes\n");
			exit(2);
		} else if (!scope_id) {
			scope_id = firsthop.sin6_scope_id;
		}
#endif
	}

	hostname = target;

	if (IN6_IS_ADDR_UNSPECIFIED(&source.sin6_addr)) {
		socklen_t alen;
		int probe_fd = socket(AF_INET6, SOCK_DGRAM, 0);

		if (probe_fd < 0) {
			perror("socket");
			exit(2);
		}
		if (device) {
#if defined(IPV6_RECVPKTINFO) || defined(HAVE_SIN6_SCOPEID)
			unsigned int iface = if_name2index(device);
#endif
#ifdef IPV6_RECVPKTINFO
			struct in6_pktinfo ipi;

			memset(&ipi, 0, sizeof(ipi));
			ipi.ipi6_ifindex = iface;
#endif

#ifdef HAVE_SIN6_SCOPEID
			if (IN6_IS_ADDR_LINKLOCAL(&firsthop.sin6_addr) ||
			    IN6_IS_ADDR_MC_LINKLOCAL(&firsthop.sin6_addr))
				firsthop.sin6_scope_id = iface;
#endif
			enable_capability_raw();
			if (
#ifdef IPV6_RECVPKTINFO
			    setsockopt(probe_fd, IPPROTO_IPV6, IPV6_PKTINFO, &ipi, sizeof(ipi)) == -1 &&
#endif
			    setsockopt(probe_fd, SOL_SOCKET, SO_BINDTODEVICE, device, strlen(device)+1) == -1) {
				perror("setsockopt(SO_BINDTODEVICE)");
				exit(2);
			}
			disable_capability_raw();
		}
		firsthop.sin6_port = htons(1025);
		if (connect(probe_fd, (struct sockaddr*)&firsthop, sizeof(firsthop)) == -1) {
			perror("connect");
			exit(2);
		}
		alen = sizeof(source);
		if (getsockname(probe_fd, (struct sockaddr*)&source, &alen) == -1) {
			perror("getsockname");
			exit(2);
		}
		source.sin6_port = 0;
		close(probe_fd);

#ifndef WITHOUT_IFADDRS
		if (device) {
			struct ifaddrs *ifa0, *ifa;

			if (getifaddrs(&ifa0)) {
				perror("getifaddrs");
				exit(2);
			}

			for (ifa = ifa0; ifa; ifa = ifa->ifa_next) {
				if (!ifa->ifa_addr || ifa->ifa_addr->sa_family != AF_INET6)
					continue;
				if (!strncmp(ifa->ifa_name, device, sizeof(device) - 1) &&
				    IN6_ARE_ADDR_EQUAL(&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr,
						       &source.sin6_addr))
					break;
			}
			if (!ifa)
				fprintf(stderr, "ping6: Warning: source address might be selected on device other than %s.\n", device);

			freeifaddrs(ifa0);
		}
#endif
	}
#ifdef HAVE_SIN6_SCOPEID
	else if (device && (IN6_IS_ADDR_LINKLOCAL(&source.sin6_addr) ||
			    IN6_IS_ADDR_MC_LINKLOCAL(&source.sin6_addr)))
		source.sin6_scope_id = if_name2index(device);
#endif

	if (icmp_sock < 0) {
		errno = socket_errno;
		perror("ping: icmp open socket");
		exit(2);
	}

	if (device) {
		struct cmsghdr *cmsg;
		struct in6_pktinfo *ipi;

		cmsg = (struct cmsghdr*)(cmsgbuf+cmsglen);
		cmsglen += CMSG_SPACE(sizeof(*ipi));
		cmsg->cmsg_len = CMSG_LEN(sizeof(*ipi));
		cmsg->cmsg_level = SOL_IPV6;
		cmsg->cmsg_type = IPV6_PKTINFO;

		ipi = (struct in6_pktinfo*)CMSG_DATA(cmsg);
		memset(ipi, 0, sizeof(*ipi));
		ipi->ipi6_ifindex = if_name2index(device);
	}

	if ((whereto.sin6_addr.s6_addr16[0]&htons(0xff00)) == htons (0xff00)) {
		if (uid) {
			if (interval < 1000) {
				fprintf(stderr, "ping: multicast ping with too short interval.\n");
				exit(2);
			}
			if (pmtudisc >= 0 && pmtudisc != IPV6_PMTUDISC_DO) {
				fprintf(stderr, "ping: multicast ping does not fragment.\n");
				exit(2);
			}
		}
		if (pmtudisc < 0)
			pmtudisc = IPV6_PMTUDISC_DO;
	}

	if (pmtudisc >= 0) {
		if (setsockopt(icmp_sock, SOL_IPV6, IPV6_MTU_DISCOVER, &pmtudisc, sizeof(pmtudisc)) == -1) {
			perror("ping: IPV6_MTU_DISCOVER");
			exit(2);
		}
	}

	if ((options&F_STRICTSOURCE) &&
	    bind(icmp_sock, (struct sockaddr*)&source, sizeof(source)) == -1) {
		perror("ping: bind icmp socket");
		exit(2);
	}

	if (datalen >= sizeof(struct timeval) && (ni_query < 0)) {
		/* can we time transfer */
		timing = 1;
	}
	packlen = datalen + 8 + 4096 + 40 + 8; /* 4096 for rthdr */
	if (!(packet = (u_char *)malloc((u_int)packlen))) {
		fprintf(stderr, "ping: out of memory.\n");
		exit(2);
	}

	working_recverr = 1;
	hold = 1;
	if (setsockopt(icmp_sock, SOL_IPV6, IPV6_RECVERR, (char *)&hold, sizeof(hold))) {
		fprintf(stderr, "WARNING: your kernel is veeery old. No problems.\n");
		working_recverr = 0;
	}

	/* Estimate memory eaten by single packet. It is rough estimate.
	 * Actually, for small datalen's it depends on kernel side a lot. */
	hold = datalen+8;
	hold += ((hold+511)/512)*(40+16+64+160);
	sock_setbufs(icmp_sock, hold);

	if (!using_ping_socket) {
#ifdef __linux__
		csum_offset = 2;
		sz_opt = sizeof(int);

		err = setsockopt(icmp_sock, SOL_RAW, IPV6_CHECKSUM,
				 &csum_offset, sz_opt);
		if (err < 0) {
			/* checksum should be enabled by default and setting
			 * this option might fail anyway.
			 */
			fprintf(stderr, "setsockopt(RAW_CHECKSUM) failed"
				" - try to continue.");
		}
#endif

		/*
		 *	select icmp echo reply as icmp type to receive
		 */

		ICMP6_FILTER_SETBLOCKALL(&filter);

		if (!working_recverr) {
			ICMP6_FILTER_SETPASS(ICMP6_DST_UNREACH, &filter);
			ICMP6_FILTER_SETPASS(ICMP6_PACKET_TOO_BIG, &filter);
			ICMP6_FILTER_SETPASS(ICMP6_TIME_EXCEEDED, &filter);
			ICMP6_FILTER_SETPASS(ICMP6_PARAM_PROB, &filter);
		}

		if (niquery_is_enabled())
			ICMP6_FILTER_SETPASS(ICMPV6_NI_REPLY, &filter);
		else
			ICMP6_FILTER_SETPASS(ICMP6_ECHO_REPLY, &filter);

		err = setsockopt(icmp_sock, IPPROTO_ICMPV6, ICMP6_FILTER,
				 &filter, sizeof(struct icmp6_filter));

		if (err < 0) {
			perror("setsockopt(ICMP6_FILTER)");
			exit(2);
		}
	}

	if (options & F_NOLOOP) {
		int loop = 0;
		if (setsockopt(icmp_sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
				&loop, sizeof(loop)) == -1) {
			perror ("can't disable multicast loopback");
			exit(2);
		}
	}
	if (options & F_TTL) {
		if (setsockopt(icmp_sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
			       &ttl, sizeof(ttl)) == -1) {
			perror ("can't set multicast hop limit");
			exit(2);
		}
		if (setsockopt(icmp_sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
			       &ttl, sizeof(ttl)) == -1) {
			perror ("can't set unicast hop limit");
			exit(2);
		}
	}

	if (1) {
		int on = 1;
		if (
#ifdef IPV6_RECVHOPLIMIT
		    setsockopt(icmp_sock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT,
			       &on, sizeof(on)) == -1 &&
		    setsockopt(icmp_sock, IPPROTO_IPV6, IPV6_2292HOPLIMIT,
			       &on, sizeof(on)) == -1
#else
		    setsockopt(icmp_sock, IPPROTO_IPV6, IPV6_HOPLIMIT,
			       &on, sizeof(on)) == -1
#endif
		   ){
			perror ("can't receive hop limit");
			exit(2);
		}
	}

	if (options & F_TCLASS) {
#ifdef IPV6_TCLASS
		if (setsockopt(icmp_sock, IPPROTO_IPV6, IPV6_TCLASS,
			       &tclass, sizeof(tclass)) == -1) {
			perror ("setsockopt(IPV6_TCLASS)");
			exit(2);
		}
#else
		fprintf(stderr, "Traffic class is not supported.\n");
#endif
	}

	if (options&F_FLOWINFO) {
#ifdef IPV6_FLOWINFO_SEND
		int on = 1;
#endif
#ifdef IPV6_FLOWLABEL_MGR
		char freq_buf[CMSG_ALIGN(sizeof(struct in6_flowlabel_req)) + cmsglen];
		struct in6_flowlabel_req *freq = (struct in6_flowlabel_req *)freq_buf;
		int freq_len = sizeof(*freq);
#ifdef ENABLE_PING6_RTHDR
		if (srcrt)
			freq_len = CMSG_ALIGN(sizeof(*freq)) + srcrt->cmsg_len;
#endif
		memset(freq, 0, sizeof(*freq));
		freq->flr_label = htonl(flowlabel & IPV6_FLOWINFO_FLOWLABEL);
		freq->flr_action = IPV6_FL_A_GET;
		freq->flr_flags = IPV6_FL_F_CREATE;
		freq->flr_share = IPV6_FL_S_EXCL;
		memcpy(&freq->flr_dst, &whereto.sin6_addr, 16);
#ifdef ENABLE_PING6_RTHDR
		if (srcrt)
			memcpy(freq_buf + CMSG_ALIGN(sizeof(*freq)), srcrt, srcrt->cmsg_len);
#endif
		if (setsockopt(icmp_sock, IPPROTO_IPV6, IPV6_FLOWLABEL_MGR,
			       freq, freq_len) == -1) {
			perror ("can't set flowlabel");
			exit(2);
		}
		flowlabel = freq->flr_label;
#ifdef ENABLE_PING6_RTHDR
		if (srcrt) {
			cmsglen = (char*)srcrt - (char*)cmsgbuf;
			srcrt = NULL;
		}
#endif
#else
		fprintf(stderr, "Flow labels are not supported.\n");
		exit(2);
#endif

#ifdef IPV6_FLOWINFO_SEND
		whereto.sin6_flowinfo = flowlabel;
		if (setsockopt(icmp_sock, IPPROTO_IPV6, IPV6_FLOWINFO_SEND,
			       &on, sizeof(on)) == -1) {
			perror ("can't send flowinfo");
			exit(2);
		}
#else
		fprintf(stderr, "Flowinfo is not supported.\n");
		exit(2);
#endif
	}

	printf("PING %s(%s) ", hostname, pr_addr(&whereto.sin6_addr));
	if (flowlabel)
		printf(", flow 0x%05x, ", (unsigned)ntohl(flowlabel));
	if (device || (options&F_STRICTSOURCE)) {
		printf("from %s %s: ",
		       pr_addr_n(&source.sin6_addr), device ? : "");
	}
Example #25
0
int open_icmpv6_socket(void)
{
	int sock;
	struct icmp6_filter filter;
	int err, val;

        sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
	if (sock < 0) {
		flog(LOG_ERR, "can't create socket(AF_INET6): %s", strerror(errno));
		return -1;
	}

	val = 1;
	err = setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &val, sizeof(val));
	if (err < 0) {
		flog(LOG_ERR, "setsockopt(IPV6_RECVPKTINFO): %s", strerror(errno));
		return -1;
	}

	val = 2;
#ifdef __linux__
	err = setsockopt(sock, IPPROTO_RAW, IPV6_CHECKSUM, &val, sizeof(val));
#else
	err = setsockopt(sock, IPPROTO_IPV6, IPV6_CHECKSUM, &val, sizeof(val));
#endif
	if (err < 0) {
		flog(LOG_ERR, "setsockopt(IPV6_CHECKSUM): %s", strerror(errno));
		return -1;
	}

	val = 255;
	err = setsockopt(sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &val, sizeof(val));
	if (err < 0) {
		flog(LOG_ERR, "setsockopt(IPV6_UNICAST_HOPS): %s", strerror(errno));
		return -1;
	}

	val = 255;
	err = setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &val, sizeof(val));
	if (err < 0) {
		flog(LOG_ERR, "setsockopt(IPV6_MULTICAST_HOPS): %s", strerror(errno));
		return -1;
	}

#ifdef IPV6_RECVHOPLIMIT
	val = 1;
	err = setsockopt(sock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &val, sizeof(val));
	if (err < 0) {
		flog(LOG_ERR, "setsockopt(IPV6_RECVHOPLIMIT): %s", strerror(errno));
		return -1;
	}
#endif

	/*
	 * setup ICMP filter
	 */

	ICMP6_FILTER_SETBLOCKALL(&filter);
	ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &filter);
	ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filter);

	err = setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, sizeof(filter));
	if (err < 0) {
		flog(LOG_ERR, "setsockopt(ICMPV6_FILTER): %s", strerror(errno));
		return -1;
	}

	return sock;
}
Example #26
0
static void ping(const char *host)
{
	char packet[datalen + MAXIPLEN + MAXICMPLEN];
	char buf[INET6_ADDRSTRLEN];
	int sockopt;
	struct msghdr msg;
	struct sockaddr_in6 from;
	struct iovec iov;
	char control_buf[CMSG_SPACE(36)];

	pingsock = create_icmp6_socket();

	memset(&pingaddr, 0, sizeof(struct sockaddr_in));

	pingaddr.sin6_family = AF_INET6;
	hostent = xgethostbyname2(host, AF_INET6);
	if (hostent->h_addrtype != AF_INET6)
		bb_error_msg_and_die("unknown address type; only AF_INET6 is currently supported");

	memcpy(&pingaddr.sin6_addr, hostent->h_addr, sizeof(pingaddr.sin6_addr));

#ifdef ICMP6_FILTER
	{
		struct icmp6_filter filt;
		if (!(option_mask32 & OPT_VERBOSE)) {
			ICMP6_FILTER_SETBLOCKALL(&filt);
			ICMP6_FILTER_SETPASS(ICMP6_ECHO_REPLY, &filt);
		} else {
			ICMP6_FILTER_SETPASSALL(&filt);
		}
		if (setsockopt(pingsock, IPPROTO_ICMPV6, ICMP6_FILTER, &filt,
					   sizeof(filt)) < 0)
			bb_error_msg_and_die("setsockopt(ICMP6_FILTER)");
	}
#endif /*ICMP6_FILTER*/

	/* enable broadcast pings */
	setsockopt_broadcast(pingsock);

	/* set recv buf for broadcast pings */
	sockopt = 48 * 1024; /* explain why 48k? */
	setsockopt(pingsock, SOL_SOCKET, SO_RCVBUF, (char *) &sockopt,
			   sizeof(sockopt));

	sockopt = 2; /* iputils-ss020927 does this */
	sockopt = offsetof(struct icmp6_hdr, icmp6_cksum);
	setsockopt(pingsock, SOL_RAW, IPV6_CHECKSUM, (char *) &sockopt,
			   sizeof(sockopt));

	/* request ttl info to be returned in ancillary data */
	sockopt = 1;
	setsockopt(pingsock, SOL_IPV6, IPV6_HOPLIMIT, (char *) &sockopt,
			   sizeof(sockopt));

	if (if_index)
		pingaddr.sin6_scope_id = if_index;

	printf("PING %s (%s): %d data bytes\n",
			hostent->h_name,
			inet_ntop(AF_INET6, &pingaddr.sin6_addr,
			buf, sizeof(buf)),
			datalen);

	signal(SIGINT, pingstats);

	/* start the ping's going ... */
	sendping(0);

	/* listen for replies */
	msg.msg_name = &from;
	msg.msg_namelen = sizeof(from);
	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;
	msg.msg_control = control_buf;
	iov.iov_base = packet;
	iov.iov_len = sizeof(packet);
	while (1) {
		int c;
		struct cmsghdr *mp;
		int hoplimit = -1;
		msg.msg_controllen = sizeof(control_buf);

		c = recvmsg(pingsock, &msg, 0);
		if (c < 0) {
			if (errno != EINTR)
				bb_perror_msg("recvfrom");
			continue;
		}
		for (mp = CMSG_FIRSTHDR(&msg); mp; mp = CMSG_NXTHDR(&msg, mp)) {
			if (mp->cmsg_level == SOL_IPV6
			 && mp->cmsg_type == IPV6_HOPLIMIT
			 /* don't check len - we trust the kernel: */
			 /* && mp->cmsg_len >= CMSG_LEN(sizeof(int)) */
			) {
				hoplimit = *(int*)CMSG_DATA(mp);
			}
		}
		unpack(packet, c, &from, hoplimit);
		if (pingcount > 0 && nreceived >= pingcount)
			break;
	}
	pingstats(0);
}