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); } }
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); } }