Ejemplo n.º 1
0
void
process(int sock, struct Interface *ifacel, unsigned char *msg, int len, 
	struct sockaddr_in6 *addr, struct in6_pktinfo *pkt_info, int hoplimit)
{
	struct Interface *iface;
	struct icmp6_hdr *icmph;
	char addr_str[INET6_ADDRSTRLEN];

	if ( ! pkt_info )
	{
		flog(LOG_WARNING, "received packet with no pkt_info!" );
		return;
	}

	/*
	 * can this happen?
	 */

	if (len < sizeof(struct icmp6_hdr))
	{
		flog(LOG_WARNING, "received icmpv6 packet with invalid length: %d",
			len);
		return;
	}

	icmph = (struct icmp6_hdr *) msg;

	if (icmph->icmp6_type != ND_ROUTER_SOLICIT &&
	    icmph->icmp6_type != ND_ROUTER_ADVERT)
	{
		/*
		 *	We just want to listen to RSs and RAs
		 */
		
		flog(LOG_ERR, "icmpv6 filter failed");
		return;
	}

	if (icmph->icmp6_type == ND_ROUTER_ADVERT)
	{
		if (len < sizeof(struct nd_router_advert)) {
			flog(LOG_WARNING, "received icmpv6 RA packet with invalid length: %d",
				len);
			return;
		}

		if (!IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr)) {
			flog(LOG_WARNING, "received icmpv6 RA packet with non-linklocal source address");
			return;
		}
	}			
	
	if (icmph->icmp6_type == ND_ROUTER_SOLICIT)
	{
		if (len < sizeof(struct nd_router_solicit)) {
			flog(LOG_WARNING, "received icmpv6 RS packet with invalid length: %d",
				len);
			return;
		}
	}			

	if (icmph->icmp6_code != 0)
	{
		flog(LOG_WARNING, "received icmpv6 RS/RA packet with invalid code: %d",
			icmph->icmp6_code);
		return;
	}
	
	dlog(LOG_DEBUG, 4, "if_index %u", pkt_info->ipi6_ifindex);

	/* get iface by received if_index */

	for (iface = ifacel; iface; iface=iface->next)
	{
		if (iface->if_index == pkt_info->ipi6_ifindex)
		{
			break;
		}
	}

	if (iface == NULL)
	{
		dlog(LOG_DEBUG, 2, "received packet from unknown interface: %d",
			pkt_info->ipi6_ifindex);
		return;
	}
	
	if (hoplimit != 255)
	{
		print_addr(&addr->sin6_addr, addr_str);
		flog(LOG_WARNING, "received RS or RA with invalid hoplimit %d from %s",
			hoplimit, addr_str);
		return;
	}
	
	if (!iface->AdvSendAdvert)
	{
		dlog(LOG_DEBUG, 2, "AdvSendAdvert is off for %s", iface->Name);
		return;
	}

	dlog(LOG_DEBUG, 4, "found Interface: %s", iface->Name);

	if (icmph->icmp6_type == ND_ROUTER_SOLICIT)
	{
		process_rs(sock, iface, msg, len, addr);
	}
	else if (icmph->icmp6_type == ND_ROUTER_ADVERT)
	{
		process_ra(iface, msg, len, addr);
	}
}
Ejemplo n.º 2
0
void process(int sock, struct Interface *interfaces, unsigned char *msg, int len, struct sockaddr_in6 *addr,
             struct in6_pktinfo *pkt_info, int hoplimit)
{
    char if_namebuf[IF_NAMESIZE] = { "" };
    char *if_name = if_indextoname(pkt_info->ipi6_ifindex, if_namebuf);
    if (!if_name) {
        if_name = "unknown interface";
    }
    dlog(LOG_DEBUG, 4, "%s received a packet", if_name);

    char addr_str[INET6_ADDRSTRLEN];
    addrtostr(&addr->sin6_addr, addr_str, sizeof(addr_str));

    if (!pkt_info) {
        flog(LOG_WARNING, "%s received packet with no pkt_info from %s!", if_name, addr_str);
        return;
    }

    /*
     * can this happen?
     */

    if (len < sizeof(struct icmp6_hdr)) {
        flog(LOG_WARNING, "%s received icmpv6 packet with invalid length (%d) from %s", if_name, len, addr_str);
        return;
    }

    struct icmp6_hdr *icmph = (struct icmp6_hdr *)msg;

    if (icmph->icmp6_type != ND_ROUTER_SOLICIT && icmph->icmp6_type != ND_ROUTER_ADVERT) {
        /*
         *      We just want to listen to RSs and RAs
         */

        flog(LOG_ERR, "%s icmpv6 filter failed", if_name);
        return;
    }

    if (icmph->icmp6_type == ND_ROUTER_ADVERT) {
        if (len < sizeof(struct nd_router_advert)) {
            flog(LOG_WARNING, "%s received icmpv6 RA packet with invalid length (%d) from %s", if_name, len, addr_str);
            return;
        }

        if (!IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr)) {
            flog(LOG_WARNING, "%s received icmpv6 RA packet with non-linklocal source address from %s", if_name, addr_str);
            return;
        }
    }

    if (icmph->icmp6_type == ND_ROUTER_SOLICIT) {
        if (len < sizeof(struct nd_router_solicit)) {
            flog(LOG_WARNING, "%s received icmpv6 RS packet with invalid length (%d) from %s", if_name, len, addr_str);
            return;
        }
    }

    if (icmph->icmp6_code != 0) {
        flog(LOG_WARNING, "%s received icmpv6 RS/RA packet with invalid code (%d) from %s", if_name, icmph->icmp6_code,
             addr_str);
        return;
    }

    /* get iface by received if_index */
    struct Interface *iface = find_iface_by_index(interfaces, pkt_info->ipi6_ifindex);

    if (iface == NULL) {
        dlog(LOG_WARNING, 4, "%s received icmpv6 RS/RA packet on an unknown interface with index %d", if_name,
             pkt_info->ipi6_ifindex);
        return;
    }

    if (!iface->state_info.ready && (0 != setup_iface(sock, iface))) {
        flog(LOG_WARNING, "%s received RS or RA on %s but %s is not ready and setup_iface failed", if_name, iface->props.name,
             iface->props.name);
        return;
    }

    if (hoplimit != 255) {
        flog(LOG_WARNING, "%s received RS or RA with invalid hoplimit %d from %s", if_name, hoplimit, addr_str);
        return;
    }

    if (icmph->icmp6_type == ND_ROUTER_SOLICIT) {
        dlog(LOG_DEBUG, 3, "%s received RS from: %s", if_name, addr_str);
        process_rs(sock, iface, msg, len, addr);
    } else if (icmph->icmp6_type == ND_ROUTER_ADVERT) {
        if (0 == memcmp(&addr->sin6_addr, &iface->props.if_addr, sizeof(iface->props.if_addr))) {
            dlog(LOG_DEBUG, 3, "%s received RA from: %s (myself)", if_name, addr_str);
        } else {
            dlog(LOG_DEBUG, 3, "%s received RA from: %s", if_name, addr_str);
        }
        process_ra(iface, msg, len, addr);
    }
}