Beispiel #1
0
void *icmp6_listen(void *arg)
{
    uint8_t msg[MAX_PKT_LEN];
    struct sockaddr_in6 addr;
    struct in6_addr *saddr, *daddr;
    struct in6_pktinfo pkt_info;
    struct icmp6_hdr *ih;
    int iif, hoplimit;
    ssize_t len;
	int *fd_arg = (int *)arg;
	int sock_fd = *fd_arg;
//    struct icmp6_handler *h;

    while (1)
	{
        pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
        len = icmp6_recv(sock_fd, msg, sizeof(msg),
                 &addr, &pkt_info, &hoplimit);
        /* check if socket has closed */
        if (len == -EBADF)
            break;
        /* common validity check */
        if (len < sizeof(struct icmp6_hdr))
            continue;
        saddr = &addr.sin6_addr;
        daddr = &pkt_info.ipi6_addr;
        iif = pkt_info.ipi6_ifindex;

        ih = (struct icmp6_hdr *)msg;
        /* multiplex to right handler */
//        pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
//        pthread_rwlock_rdlock(&handler_lock);
/*        if ((h = icmp6_handler_get(ih->icmp6_type)) != NULL)*/
		if(conf.mode == MAPD_MODE_CLIENT)
	        mapd_client_recv(ih, len, saddr, daddr, iif, hoplimit, sock_fd);
		else if(conf.mode == MAPD_MODE_SERVER)
			mapd_server_recv(ih, len, saddr, daddr, iif, hoplimit, sock_fd);
//        pthread_rwlock_unlock(&handler_lock);
    }
    pthread_exit(NULL);
}
Beispiel #2
0
static void *icmp6_listen(void *arg)
{
	uint8_t msg[MAX_PKT_LEN];
	struct sockaddr_in6 addr;
	struct in6_addr *saddr, *daddr;
	struct in6_pktinfo pkt_info;
	struct icmp6_hdr *ih;
	int iif, hoplimit;
	ssize_t len;
	struct icmp6_handler *h;

	pthread_dbg("thread started");

	while (1) {
		pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
		len = icmp6_recv(icmp6_sock.fd, msg, sizeof(msg),
				 &addr, &pkt_info, &hoplimit);
		/* check if socket has closed */
		if (len == -EBADF)
			break;
		/* common validity check */
		if (len < sizeof(struct icmp6_hdr))
			continue;
		saddr = &addr.sin6_addr;
		daddr = &pkt_info.ipi6_addr;
		iif = pkt_info.ipi6_ifindex;

		ih = (struct icmp6_hdr *)msg;
		/* multiplex to right handler */
		pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
		pthread_rwlock_rdlock(&handler_lock);
		if ((h = icmp6_handler_get(ih->icmp6_type)) != NULL)
			h->recv(ih, len, saddr, daddr, iif, hoplimit);
		pthread_rwlock_unlock(&handler_lock);
	}
	pthread_exit(NULL);
}
Beispiel #3
0
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;
}