static void update_iface_times(struct Interface * iface) { struct timespec last_time = iface->times.last_ra_time; clock_gettime(CLOCK_MONOTONIC, &iface->times.last_ra_time); time_t secs_since_last_ra = timespecdiff(&iface->times.last_ra_time, &last_time); if (secs_since_last_ra < 0) { secs_since_last_ra = 0; flog(LOG_WARNING, "clock_gettime(CLOCK_MONOTONIC) went backwards!"); } struct AdvPrefix *prefix = iface->AdvPrefixList; while (prefix) { if (prefix->enabled && (!prefix->DecrementLifetimesFlag || prefix->curr_preferredlft > 0)) { if (!(iface->state_info.cease_adv && prefix->DeprecatePrefixFlag)) { if (prefix->DecrementLifetimesFlag) { decrement_lifetime(secs_since_last_ra, &prefix->curr_validlft); decrement_lifetime(secs_since_last_ra, &prefix->curr_preferredlft); if (prefix->curr_preferredlft == 0) { char pfx_str[INET6_ADDRSTRLEN]; addrtostr(&prefix->Prefix, pfx_str, sizeof(pfx_str)); dlog(LOG_DEBUG, 3, "Will cease advertising %s/%u%%%s, preferred lifetime is 0", pfx_str, prefix->PrefixLen, iface->props.name); } } } } prefix = prefix->next; } }
const char *TCPSocket::remoteaddr() { if(state != CONNECTED) throw ERR_NOT_CONNECTED; return addrtostr(&addr); }
static void check_ipv6(void) { int err; char *buf[2]; struct sockaddr_in6 addr, addrck; memset(&addr, 0, sizeof(struct sockaddr_in6)); memset(&addrck, 0, sizeof(struct sockaddr_in6)); printf("Checking strtoaddr on [fd00::1]:50000\n"); addrck.sin6_family = AF_INET6; addrck.sin6_addr.s6_addr16[0] = htons(0xfd00); /* fd00::1 */ addrck.sin6_addr.s6_addr16[7] = htons(0x0001); addrck.sin6_port = htons(50000); err = strtoaddr("fd00::1", "50000", (struct sockaddr *) &addr, sizeof(struct sockaddr_in6)); if (err != 0) { printf("Unable to convert [fd00::1]:50000\n"); exit(EXIT_FAILURE); } if (memcmp(&addr, &addrck, sizeof(struct sockaddr_in6)) != 0) { errno = EINVAL; printf("Check on 192.168.0.1:50000 failed\n"); exit(EXIT_FAILURE); } printf("Checking addrtostr on [fd00::1]:50000\n"); err = addrtostr((struct sockaddr *) &addrck, sizeof(struct sockaddr_in6), buf); if (err != 0) { printf("Unable to convert 192.168.0.1:50000\n"); exit(EXIT_FAILURE); } if (strcmp(buf[0], "fd00::1") != 0) { errno = EINVAL; printf("Wrong address conversion: %s\n", buf[0]); exit(EXIT_FAILURE); } if (strcmp(buf[1], "50000") != 0) { errno = EINVAL; printf("Wrong port conversion: %s\n", buf[1]); exit(EXIT_FAILURE); } addrtostr_free(buf); }
static void *vty_accept_thread(void *arg) { struct knet_vty *vty = (struct knet_vty *)&knet_vtys[*(int *)arg]; char *src_ip[2]; int err; knet_vty_print_banner(vty); if (vty->got_epipe) goto out_clean; src_ip[0] = NULL; err = addrtostr((struct sockaddr *)&vty->src_sa, vty->src_sa_len, src_ip); if (!err) { strncpy(vty->ip, src_ip[0], sizeof(vty->ip)); } else { strcpy(vty->ip, "unknown"); } if (src_ip[0]) addrtostr_free(src_ip); if ((knet_vty_auth_user(vty, NULL) < 0) && (!vty->got_epipe)) { log_info("User failed to authenticate (ip: %s)", vty->ip); goto out_clean; } if (vty->got_epipe) goto out_clean; log_info("User %s connected from %s", vty->username, vty->ip); knet_vty_write(vty, "Welcome %s (%s) on vty(%d)\n\n", vty->username, vty->ip, vty->conn_num); if (vty->got_epipe) goto out_clean; if (knet_vty_set_iacs(vty) < 0) { knet_vty_write(vty, "Unable to set telnet session preferences"); goto out_clean; } if (vty->got_epipe) goto out_clean; knet_vty_cli_bind(vty); out_clean: pthread_mutex_lock(&knet_vty_mutex); knet_vty_close(vty); pthread_mutex_unlock(&knet_vty_mutex); return NULL; }
static int acceptClient(int handle, void *context) { int newHandle = 0; int opts; struct sockaddr_in6 addr; socklen_t addrlen = sizeof(addr); newHandle = accept(handle, (struct sockaddr *) &addr, &addrlen); if (newHandle < 0) { perror("accept"); goto error; } opts = fcntl(newHandle, F_GETFL); if (opts < 0) { perror("fcntl(F_GETFL)"); goto error; } opts = opts | O_NONBLOCK; if (fcntl(newHandle, F_SETFL, opts) < 0) { perror("fcntl(F_SETFL)"); goto error; } ClientRef client = createClient(newHandle); if (client == NULL) { fputs("failed to create client\n", stderr); goto error; } fprintf(stdout, "client [%s]:%d connected\n", addrtostr((struct sockaddr *) &addr, addrlen, NULL, 0), addr.sin6_port); appendDescriptor( createDescriptor(newHandle, client, handleClient), (SocketDescriptorListRef) context); return 1; error: if (client != NULL) disposeClient(client); if (newHandle >= 0) close(newHandle); return -1; }
static void reset_prefix_lifetimes_foo(struct Interface *iface, void *data) { flog(LOG_INFO, "Resetting prefix lifetimes on %s", iface->props.name); for (struct AdvPrefix * prefix = iface->AdvPrefixList; prefix; prefix = prefix->next) { if (prefix->DecrementLifetimesFlag) { char pfx_str[INET6_ADDRSTRLEN]; addrtostr(&prefix->Prefix, pfx_str, sizeof(pfx_str)); dlog(LOG_DEBUG, 4, "%s/%u%%%s plft reset from %u to %u secs", pfx_str, prefix->PrefixLen, iface->props.name, prefix->curr_preferredlft, prefix->AdvPreferredLifetime); dlog(LOG_DEBUG, 4, "%s/%u%%%s vlft reset from %u to %u secs", pfx_str, prefix->PrefixLen, iface->props.name, prefix->curr_validlft, prefix->AdvValidLifetime); prefix->curr_validlft = prefix->AdvValidLifetime; prefix->curr_preferredlft = prefix->AdvPreferredLifetime; } } }
static void disconnectClient(ClientRef client) { struct sockaddr_in6 addr; socklen_t addrlen = sizeof(addr); if (getpeername(client->handle, (struct sockaddr *) &addr, &addrlen) < 0) { perror("getpeername"); goto done; } fprintf(stdout, "client [%s]:%d disconnected\n", addrtostr((struct sockaddr *) &addr, addrlen, NULL, 0), addr.sin6_port); done: disposeClient(client); }
int main(int argc, char *argv[]) { int err; char *buf[2]; struct sockaddr_storage address; if (argc == 1) { /* automated tests */ check_ipv4(); check_ipv6(); check_resolve(); exit(EXIT_SUCCESS); } else if (argc != 3) { printf("usage: %s [host] [port]\n", argv[0]); exit(EXIT_SUCCESS); } err = strtoaddr(argv[1], argv[2], (struct sockaddr *) &address, sizeof(struct sockaddr_storage)); if (err != 0) { printf("Unable to convert strings to sockaddr\n"); exit(EXIT_FAILURE); } err = addrtostr((struct sockaddr *) &address, sizeof(struct sockaddr_storage), buf); if (err != 0) { printf("Unable to convert sockaddr to strings\n"); exit(EXIT_FAILURE); } printf("host: %s port: %s\n", buf[0], buf[1]); addrtostr_free(buf); return 0; }
static int gre_sre_ip_print(netdissect_options *ndo, uint8_t sreoff, uint8_t srelen, const u_char *bp, u_int len) { const u_char *up = bp; char buf[INET_ADDRSTRLEN]; if (sreoff & 3) { ND_PRINT(", badoffset=%u", sreoff); return (1); } if (srelen & 3) { ND_PRINT(", badlength=%u", srelen); return (1); } if (sreoff >= srelen) { ND_PRINT(", badoff/len=%u/%u", sreoff, srelen); return (1); } while (srelen != 0) { if (!ND_TTEST_4(bp)) return (0); if (len < 4) return (0); addrtostr(bp, buf, sizeof(buf)); ND_PRINT(" %s%s", ((bp - up) == sreoff) ? "*" : "", buf); bp += 4; len -= 4; srelen -= 4; } return (1); }
/* * Convert IPv6 binary address into presentation (printable) format. */ const char * addrtostr6 (const void *src, char *dst, size_t size) { /* * Note that int32_t and int16_t need only be "at least" large enough * to contain a value of the specified size. On some systems, like * Crays, there is no such thing as an integer variable with 16 bits. * Keep this in mind if you think this function should have been coded * to use pointer overlays. All the world's not a VAX. */ const u_char *srcaddr = (const u_char *)src; char *dp; size_t space_left, added_space; int snprintfed; struct { int base; int len; } best, cur; uint16_t words [IN6ADDRSZ / INT16SZ]; int i; /* Preprocess: * Copy the input (bytewise) array into a wordwise array. * Find the longest run of 0x00's in src[] for :: shorthanding. */ for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) words[i] = (srcaddr[2*i] << 8) | srcaddr[2*i + 1]; best.len = 0; best.base = -1; cur.len = 0; cur.base = -1; for (i = 0; i < (int)(IN6ADDRSZ / INT16SZ); i++) { if (words[i] == 0) { if (cur.base == -1) cur.base = i, cur.len = 1; else cur.len++; } else if (cur.base != -1) { if (best.base == -1 || cur.len > best.len) best = cur; cur.base = -1; } } if ((cur.base != -1) && (best.base == -1 || cur.len > best.len)) best = cur; if (best.base != -1 && best.len < 2) best.base = -1; /* Format the result. */ dp = dst; space_left = size; #define APPEND_CHAR(c) \ { \ if (space_left == 0) { \ errno = ENOSPC; \ return (NULL); \ } \ *dp++ = c; \ space_left--; \ } for (i = 0; i < (int)(IN6ADDRSZ / INT16SZ); i++) { /* Are we inside the best run of 0x00's? */ if (best.base != -1 && i >= best.base && i < (best.base + best.len)) { if (i == best.base) APPEND_CHAR(':'); continue; } /* Are we following an initial run of 0x00s or any real hex? */ if (i != 0) APPEND_CHAR(':'); /* Is this address an encapsulated IPv4? */ if (i == 6 && best.base == 0 && (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) { if (!addrtostr(srcaddr+12, dp, space_left)) { errno = ENOSPC; return (NULL); } added_space = strlen(dp); dp += added_space; space_left -= added_space; break; } snprintfed = snprintf (dp, space_left, "%x", words[i]); if (snprintfed < 0) return (NULL); if ((size_t) snprintfed >= space_left) { errno = ENOSPC; return (NULL); } dp += snprintfed; space_left -= snprintfed; } /* Was it a trailing run of 0x00's? */ if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ)) APPEND_CHAR(':'); APPEND_CHAR('\0'); return (dst); }
static void add_pvd(struct safe_buffer * sb, struct AdvPvd const *pvd, int cease_adv) { while (pvd) { /* create a temporary buffer to write the encapsulated options to until we calculate the total length of the outer PVD_CO option */ size_t total_len = 0; struct safe_buffer pvd_sb = SAFE_BUFFER_INIT; struct AdvPrefix *prefix = pvd->AdvPrefixList; while (prefix) { char pfx_str[INET6_ADDRSTRLEN]; addrtostr(&prefix->Prefix, pfx_str, sizeof(pfx_str)); prefix = prefix->next; } struct nd_opt_pvd pvdinfo; memset(&pvdinfo, 0, sizeof(pvdinfo)); /* create PVD_CO container option */ pvdinfo.nd_opt_pvd_container_type = ND_OPT_PVD_CONTAINER; /* initial length of PVD_CO option without encapsulated options */ pvdinfo.nd_opt_pvd_container_len = 1; total_len += pvdinfo.nd_opt_pvd_container_len; pvdinfo.nd_opt_pvd_container_s = 0; pvdinfo.nd_opt_pvd_container_nametype = 0; /* add PVD_ID option */ pvdinfo.nd_opt_pvd_id_type = ND_OPT_PVD_ID; pvdinfo.nd_opt_pvd_id_len = 5; total_len += pvdinfo.nd_opt_pvd_id_len; pvdinfo.nd_opt_pvd_id_idtype = 4; pvdinfo.nd_opt_pvd_id_idlen = 36; memcpy(&pvdinfo.nd_opt_pvd_id_pvdid, pvd->pvdid, sizeof(pvdinfo.nd_opt_pvd_id_pvdid));; /* add encapsulated ND options if specified */ if (pvd->AdvPrefixList) { total_len += add_prefix(&pvd_sb, pvd->AdvPrefixList, cease_adv); } if (pvd->AdvRouteList) { total_len += add_route(&pvd_sb, pvd->AdvRouteList, cease_adv); } if (pvd->AdvRDNSSList) { total_len += add_rdnss(&pvd_sb, pvd->AdvRDNSSList, cease_adv); } if (pvd->AdvDNSSLList) { total_len += add_dnssl(&pvd_sb, pvd->AdvDNSSLList, cease_adv); } /* if (iface->AdvLinkMTU != 0) { add_mtu(sb, iface->AdvLinkMTU); } if (iface->AdvSourceLLAddress && iface->sllao.if_hwaddr_len > 0) { add_sllao(sb, &iface->sllao); } if (iface->mipv6.AdvIntervalOpt) { add_mipv6_rtr_adv_interval(sb, iface->MaxRtrAdvInterval); } if (iface->mipv6.AdvHomeAgentInfo && (iface->mipv6.AdvMobRtrSupportFlag || iface->mipv6.HomeAgentPreference != 0 || iface->mipv6.HomeAgentLifetime != iface->ra_header_info.AdvDefaultLifetime)) { add_mipv6_home_agent_info(sb, &iface->mipv6); } */ if (pvd->AdvLowpanCoList) { total_len += add_lowpanco(&pvd_sb, pvd->AdvLowpanCoList); } if (pvd->AdvAbroList) { total_len += add_abro(&pvd_sb, pvd->AdvAbroList); } /* write out PVD_CO container option + PVD_ID option */ pvdinfo.nd_opt_pvd_container_len = total_len; safe_buffer_append(sb, &pvdinfo, sizeof(pvdinfo)); /* write out encapsulated ND options */ safe_buffer_append(sb, pvd_sb.buffer, pvd_sb.used); /* destroy a temporary buffer */ safe_buffer_free(&pvd_sb); pvd = pvd->next; } }
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); } }
/* * check router advertisements according to RFC 4861, 6.2.7 */ static void process_ra(struct Interface *iface, unsigned char *msg, int len, struct sockaddr_in6 *addr) { char addr_str[INET6_ADDRSTRLEN]; addrtostr(&addr->sin6_addr, addr_str, sizeof(addr_str)); struct nd_router_advert *radvert = (struct nd_router_advert *)msg; if ((radvert->nd_ra_curhoplimit && iface->ra_header_info.AdvCurHopLimit) && (radvert->nd_ra_curhoplimit != iface->ra_header_info.AdvCurHopLimit)) { flog(LOG_WARNING, "our AdvCurHopLimit on %s doesn't agree with %s", iface->props.name, addr_str); } if ((radvert->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED) && !iface->ra_header_info.AdvManagedFlag) { flog(LOG_WARNING, "our AdvManagedFlag on %s doesn't agree with %s", iface->props.name, addr_str); } if ((radvert->nd_ra_flags_reserved & ND_RA_FLAG_OTHER) && !iface->ra_header_info.AdvOtherConfigFlag) { flog(LOG_WARNING, "our AdvOtherConfigFlag on %s doesn't agree with %s", iface->props.name, addr_str); } /* note: we don't check the default router preference here, because they're likely different */ if ((radvert->nd_ra_reachable && iface->ra_header_info.AdvReachableTime) && (ntohl(radvert->nd_ra_reachable) != iface->ra_header_info.AdvReachableTime)) { flog(LOG_WARNING, "our AdvReachableTime on %s doesn't agree with %s", iface->props.name, addr_str); } if ((radvert->nd_ra_retransmit && iface->ra_header_info.AdvRetransTimer) && (ntohl(radvert->nd_ra_retransmit) != iface->ra_header_info.AdvRetransTimer)) { flog(LOG_WARNING, "our AdvRetransTimer on %s doesn't agree with %s", iface->props.name, addr_str); } len -= sizeof(struct nd_router_advert); if (len == 0) return; uint8_t *opt_str = (uint8_t *) (msg + sizeof(struct nd_router_advert)); while (len > 0) { if (len < 2) { flog(LOG_ERR, "trailing garbage in RA on %s from %s", iface->props.name, addr_str); break; } int optlen = (opt_str[1] << 3); if (optlen == 0) { flog(LOG_ERR, "zero length option in RA on %s from %s", iface->props.name, addr_str); break; } else if (optlen > len) { flog(LOG_ERR, "option length (%d) greater than total" " length (%d) in RA on %s from %s", optlen, len, iface->props.name, addr_str); break; } switch (*opt_str) { case ND_OPT_MTU: { struct nd_opt_mtu *mtu = (struct nd_opt_mtu *)opt_str; if (len < sizeof(*mtu)) return; if (iface->AdvLinkMTU && (ntohl(mtu->nd_opt_mtu_mtu) != iface->AdvLinkMTU)) { flog(LOG_WARNING, "our AdvLinkMTU on %s doesn't agree with %s", iface->props.name, addr_str); } break; } case ND_OPT_PREFIX_INFORMATION: { struct nd_opt_prefix_info *pinfo = (struct nd_opt_prefix_info *)opt_str; if (len < sizeof(*pinfo)) return; int preferred = ntohl(pinfo->nd_opt_pi_preferred_time); int valid = ntohl(pinfo->nd_opt_pi_valid_time); struct AdvPrefix *prefix = iface->AdvPrefixList; while (prefix) { char prefix_str[INET6_ADDRSTRLEN]; if ((prefix->PrefixLen == pinfo->nd_opt_pi_prefix_len) && addr_match(&prefix->Prefix, &pinfo->nd_opt_pi_prefix, prefix->PrefixLen)) { addrtostr(&prefix->Prefix, prefix_str, sizeof(prefix_str)); if (!prefix->DecrementLifetimesFlag && valid != prefix->AdvValidLifetime) { flog(LOG_WARNING, "our AdvValidLifetime on" " %s for %s doesn't agree with %s", iface->props.name, prefix_str, addr_str); } if (!prefix->DecrementLifetimesFlag && preferred != prefix->AdvPreferredLifetime) { flog(LOG_WARNING, "our AdvPreferredLifetime on" " %s for %s doesn't agree with %s", iface->props.name, prefix_str, addr_str); } } prefix = prefix->next; } break; } case ND_OPT_ROUTE_INFORMATION: /* not checked: these will very likely vary a lot */ break; case ND_OPT_SOURCE_LINKADDR: /* not checked */ break; case ND_OPT_TARGET_LINKADDR: case ND_OPT_REDIRECTED_HEADER: flog(LOG_ERR, "invalid option %d in RA on %s from %s", (int)*opt_str, iface->props.name, addr_str); break; /* Mobile IPv6 extensions */ case ND_OPT_RTR_ADV_INTERVAL: case ND_OPT_HOME_AGENT_INFO: /* not checked */ break; case ND_OPT_RDNSS_INFORMATION: { char rdnss_str[INET6_ADDRSTRLEN]; struct AdvRDNSS *rdnss = 0; struct nd_opt_rdnss_info_local *rdnssinfo = (struct nd_opt_rdnss_info_local *)opt_str; if (len < sizeof(*rdnssinfo)) return; int count = rdnssinfo->nd_opt_rdnssi_len; /* Check the RNDSS addresses received */ switch (count) { case 7: rdnss = iface->AdvRDNSSList; if (!check_rdnss_presence(rdnss, &rdnssinfo->nd_opt_rdnssi_addr3)) { /* no match found in iface->AdvRDNSSList */ addrtostr(&rdnssinfo->nd_opt_rdnssi_addr3, rdnss_str, sizeof(rdnss_str)); flog(LOG_WARNING, "RDNSS address %s received on %s from %s is not advertised by us", rdnss_str, iface->props.name, addr_str); } /* FALLTHROUGH */ case 5: rdnss = iface->AdvRDNSSList; if (!check_rdnss_presence(rdnss, &rdnssinfo->nd_opt_rdnssi_addr2)) { /* no match found in iface->AdvRDNSSList */ addrtostr(&rdnssinfo->nd_opt_rdnssi_addr2, rdnss_str, sizeof(rdnss_str)); flog(LOG_WARNING, "RDNSS address %s received on %s from %s is not advertised by us", rdnss_str, iface->props.name, addr_str); } /* FALLTHROUGH */ case 3: rdnss = iface->AdvRDNSSList; if (!check_rdnss_presence(rdnss, &rdnssinfo->nd_opt_rdnssi_addr1)) { /* no match found in iface->AdvRDNSSList */ addrtostr(&rdnssinfo->nd_opt_rdnssi_addr1, rdnss_str, sizeof(rdnss_str)); flog(LOG_WARNING, "RDNSS address %s received on %s from %s is not advertised by us", rdnss_str, iface->props.name, addr_str); } break; default: flog(LOG_ERR, "invalid len %i in RDNSS option on %s from %s", count, iface->props.name, addr_str); } break; } case ND_OPT_DNSSL_INFORMATION: { struct nd_opt_dnssl_info_local *dnsslinfo = (struct nd_opt_dnssl_info_local *)opt_str; if (len < sizeof(*dnsslinfo)) return; for (int offset = 0; offset < (dnsslinfo->nd_opt_dnssli_len - 1) * 8;) { char suffix[256] = { "" }; if (&dnsslinfo->nd_opt_dnssli_suffixes[offset] - opt_str >= len) return; int label_len = dnsslinfo->nd_opt_dnssli_suffixes[offset++]; if (label_len == 0) { /* * Ignore empty suffixes. They're * probably just padding... */ if (suffix[0] == '\0') continue; if (!check_dnssl_presence(iface->AdvDNSSLList, suffix)) { flog(LOG_WARNING, "DNSSL suffix %s received on %s from %s is not advertised by us", suffix, iface->props.name, addr_str); } suffix[0] = '\0'; continue; } /* * 1) must not overflow int: label + 2, offset + label_len * 2) last byte of dnssli_suffix must not overflow opt_str + len */ if ((sizeof(suffix) - strlen(suffix)) < (label_len + 2) || label_len >= (INT_MAX-1) || &dnsslinfo->nd_opt_dnssli_suffixes[offset + label_len] - opt_str >= len || offset + label_len < offset) { flog(LOG_ERR, "oversized suffix in DNSSL option on %s from %s", iface->props.name, addr_str); break; } if (suffix[0] != '\0') strcat(suffix, "."); strncat(suffix, (char *)&dnsslinfo->nd_opt_dnssli_suffixes[offset], label_len); offset += label_len; } break; } default: dlog(LOG_DEBUG, 1, "unknown option %d in RA on %s from %s", (int)*opt_str, iface->props.name, addr_str); break; } len -= optlen; opt_str += optlen; } dlog(LOG_DEBUG, 2, "processed RA on %s", iface->props.name); }
/* * Convert IPv6 binary address into presentation (printable) format. */ const char * addrtostr6 (const void *src, char *dst, size_t size) { /* * Note that int32_t and int16_t need only be "at least" large enough * to contain a value of the specified size. On some systems, like * Crays, there is no such thing as an integer variable with 16 bits. * Keep this in mind if you think this function should have been coded * to use pointer overlays. All the world's not a VAX. */ const u_char *srcaddr = (const u_char *)src; char tmp [INET6_ADDRSTRLEN+1]; char *tp; struct { long base; long len; } best, cur; u_long words [IN6ADDRSZ / INT16SZ]; u_int i; /* Preprocess: * Copy the input (bytewise) array into a wordwise array. * Find the longest run of 0x00's in src[] for :: shorthanding. */ memset (words, 0, sizeof(words)); for (i = 0; i < IN6ADDRSZ; i++) words[i/2] |= (srcaddr[i] << ((1 - (i % 2)) << 3)); best.len = 0; best.base = -1; cur.len = 0; cur.base = -1; for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) { if (words[i] == 0) { if (cur.base == -1) cur.base = i, cur.len = 1; else cur.len++; } else if (cur.base != -1) { if (best.base == -1 || cur.len > best.len) best = cur; cur.base = -1; } } if ((cur.base != -1) && (best.base == -1 || cur.len > best.len)) best = cur; if (best.base != -1 && best.len < 2) best.base = -1; /* Format the result. */ tp = tmp; for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) { /* Are we inside the best run of 0x00's? */ if (best.base != -1 && i >= best.base && i < (best.base + best.len)) { if (i == best.base) *tp++ = ':'; continue; } /* Are we following an initial run of 0x00s or any real hex? */ if (i != 0) *tp++ = ':'; /* Is this address an encapsulated IPv4? */ if (i == 6 && best.base == 0 && (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) { if (!addrtostr(srcaddr+12, tp, sizeof(tmp) - (tp - tmp))) { errno = ENOSPC; return (NULL); } tp += strlen(tp); break; } tp += sprintf (tp, "%lx", words[i]); } /* Was it a trailing run of 0x00's? */ if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ)) *tp++ = ':'; *tp++ = '\0'; /* Check for overflow, copy, and we're done. */ if ((size_t)(tp - tmp) > size) { errno = ENOSPC; return (NULL); } return strcpy (dst, tmp); }
static int handle_udp(struct sockaddr_in *client_addr, char *pkg, int len) { ++recv_pkg_count; log_debug("recv pkg from %s, len: %d\n%s", addrtostr(client_addr), len, \ hex_dump_str(pkg, len)); int ret; char *p = pkg; int left = len; struct protocol_head head; ret = get_head(&head, (void **)&p, &left); if (ret < 0) return -__LINE__; if (head.command == COMMAND_SQL) { ret = push_sql(p, left); if (ret < 0) { log_error("push to queue fail: %d", ret); NEG_RET(reply(&head, client_addr, RESULT_INTERNAL_ERROR)); return -__LINE__; } } else { struct sockaddr_in real_client_addr; if (head.echo_len == sizeof(struct inner_addr)) { struct inner_addr *addr = (struct inner_addr *)head.echo; bzero(&real_client_addr, sizeof(real_client_addr)); real_client_addr.sin_addr.s_addr = addr->ip; real_client_addr.sin_port = addr->port; } global_sequence_has_generated = 0; uint64_t hash_key = 0; char *s = pkgtostr(&real_client_addr, p, left, &hash_key); if (s == NULL) { if (global_sequence_has_generated) { sequence_dec(); } NEG_RET(reply(&head, client_addr, RESULT_PKG_FMT_ERROR)); return -__LINE__; } ret = process_one_record(s, hash_key); if (ret < 0) { log_error("process one record fail: %d", ret); NEG_RET(reply(&head, client_addr, RESULT_INTERNAL_ERROR)); return -__LINE__; } } NEG_RET(reply(&head, client_addr, RESULT_OK)); return 0; }