int parse_ip(char *str, char **ipstr, unsigned int *mask) { int ret; char *maskstr; unsigned int ip[4]; char dst[65]; int family; if ((maskstr = strchr(str, '/')) != NULL) *maskstr++ = 0; if ((family = get_netaddr(str, ip)) == -1) return -1; if ((inet_ntop(family, ip, dst, sizeof(dst) - 1)) == NULL) return -1; *mask = 0; if (maskstr != NULL) { if (check_ipv4(maskstr)) { if (get_netaddr(maskstr, ip) == -1) return -1; *mask = ip[0]; } else { ret = parse_int(maskstr, (int *)mask); if (ret || *mask > 128 || *mask < 0) return -1; if (family == AF_INET) *mask = htonl(~0 << (32 - *mask)); } } *ipstr = strdup(dst); return 0; }
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; }
// TODO and for non NTP packets? (ie 1588) // FIXME: the ip pointer is dirty and will break with IPv6 packets int get_valid_ntp_payload(radpcap_packet_t *packet, struct ntp_pkt **ntp, struct sockaddr_storage *ss_src, struct sockaddr_storage *ss_dst, int *ttl) { struct sockaddr_in *sin; struct sockaddr_in6 *sin6; struct ip *iph; struct ip6_hdr *ip6h; struct udphdr *udph; linux_sll_header_t *sllh; uint16_t proto; int remaining; int err; JDEBUG remaining = ((struct pcap_pkthdr *)packet->header)->caplen; switch (packet->type) { /* * This is format #1, skip 14 bytes ethernet header. Only NTP packets ever * captured in this format are IPv4 */ case DLT_EN10MB: iph = (struct ip *)(packet->payload + sizeof(struct ether_header)); remaining -= sizeof(struct ether_header); ip6h = NULL; break; /* * This is format #2 and #3. Here we take advantage of a bug in bytes order in * libtrace-3.0-beta3 to identify the formats. * - if sllh->hatype = ARPHRD_ETHER (0x0001), we have format 3. * - if sllh->hatype is 256 (0x0100) it's a libtrace format. */ case DLT_LINUX_SLL: sllh = (linux_sll_header_t*) packet->payload; /* Format #2 */ if (ntohs(sllh->hatype) != 0x0001) { iph = (struct ip *)(packet->payload + sizeof(struct ether_header) + sizeof(linux_sll_header_t)); remaining -= sizeof(struct ether_header); ip6h = NULL; break; } /* This is format 3 */ proto = ntohs(sllh->protocol); switch (proto) { /* IPv4 */ case (ETHERTYPE_IP): ip6h = NULL; iph = (struct ip *)(packet->payload + sizeof(linux_sll_header_t)); remaining -= sizeof(linux_sll_header_t); err = check_ipv4(iph, remaining); if (err) return (1); ss_src->ss_family = AF_INET; ss_dst->ss_family = AF_INET; sin = (struct sockaddr_in *)ss_src; sin->sin_addr = iph->ip_src; sin = (struct sockaddr_in *)ss_dst; sin->sin_addr = iph->ip_dst; *ttl = iph->ip_ttl; udph = (struct udphdr *)((char *)iph + (iph->ip_hl * 4)); remaining -= sizeof(struct ip); break; /* IPv6 */ case (ETHERTYPE_IPV6): iph = NULL; ip6h = (struct ip6_hdr *)(packet->payload + sizeof(linux_sll_header_t)); remaining -= sizeof(linux_sll_header_t); err = check_ipv6(ip6h, remaining); if (err) return (1); ss_src->ss_family = AF_INET6; ss_dst->ss_family = AF_INET6; sin6 = (struct sockaddr_in6 *)ss_src; sin6->sin6_addr = ip6h->ip6_src; sin6 = (struct sockaddr_in6 *)ss_dst; sin6->sin6_addr = ip6h->ip6_dst; *ttl = ip6h->ip6_hops; udph = (struct udphdr *)((char *)ip6h + sizeof(struct ip6_hdr)); remaining -= sizeof(struct ip6_hdr); break; /* IEEE 1588 over Ethernet */ case (0x88F7): verbose(LOG_ERR, "1588 over Ethernet not implemented"); return (1); default: verbose(LOG_ERR, "Unsupported protocol in SLL header %u", proto); return(1); } break; default: verbose(LOG_ERR, "MAC layer type not supported yet."); return (1); break; } if (remaining < sizeof(struct udphdr)) { verbose(LOG_WARNING, "Broken UDP datagram"); return (1); } *ntp = (struct ntp_pkt *)((char *)udph + sizeof(struct udphdr)); remaining -= sizeof(struct udphdr); /* * Make sure the NTP packet is not truncated. A normal NTP packet is at * least 48 bytes long, but a control or private request is as small as 12 * bytes. */ if (remaining < 12) { verbose(LOG_WARNING, "NTP packet truncated, payload is %d bytes " "instead of at least 12 bytes", remaining); return (1); } return (0); }