Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xdqi/19cf069a7108d96d7cf1ee7a7302d082 to your computer and use it in GitHub Desktop.
Save xdqi/19cf069a7108d96d7cf1ee7a7302d082 to your computer and use it in GitHub Desktop.
Add IPIP geolocation display to GNU inetutils
From 68a83385a5f2dd2a1f33e775366fabd2fe0c0edc Mon Sep 17 00:00:00 2001
From: Alexander Qi <xdqi@users.noreply.github.com>
Date: Tue, 18 Apr 2017 14:55:08 +0800
Subject: [PATCH] Add IPIP geolocation display to GNU inetutils
---
ping/ping_echo.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++-
src/traceroute.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++++++----
2 files changed, 198 insertions(+), 10 deletions(-)
diff --git a/ping/ping_echo.c b/ping/ping_echo.c
index aca5e42..d6c2bd1 100644
--- a/ping/ping_echo.c
+++ b/ping/ping_echo.c
@@ -64,6 +64,97 @@ void print_icmp_header (struct sockaddr_in *from,
struct ip *ip, icmphdr_t * icmp, int len);
static void print_ip_opt (struct ip *ip, int hlen);
+
+typedef unsigned char byte;
+typedef unsigned int uint;
+#define B2IL(b) (((b)[0] & 0xFF) | (((b)[1] << 8) & 0xFF00) | (((b)[2] << 16) & 0xFF0000) | (((b)[3] << 24) & 0xFF000000))
+#define B2IU(b) (((b)[3] & 0xFF) | (((b)[2] << 8) & 0xFF00) | (((b)[1] << 16) & 0xFF0000) | (((b)[0] << 24) & 0xFF000000))
+
+struct {
+ byte *data;
+ byte *index;
+ uint *flag;
+ uint offset;
+} ipip;
+
+int ipipdb_destroy() {
+ if (!ipip.offset) {
+ return 0;
+ }
+ free(ipip.flag);
+ free(ipip.index);
+ free(ipip.data);
+ ipip.offset = 0;
+ return 0;
+}
+
+int ipipdb_init(const char *ipdb) {
+ if (ipip.offset) {
+ return 0;
+ }
+ FILE *file = fopen(ipdb, "rb");
+ fseek(file, 0, SEEK_END);
+ long size = ftell(file);
+ fseek(file, 0, SEEK_SET);
+
+ ipip.data = (byte *) malloc(size * sizeof(byte));
+ size_t r = fread(ipip.data, sizeof(byte), (size_t) size, file);
+
+ if (r == 0) {
+ return 0;
+ }
+
+ fclose(file);
+
+ uint length = B2IU(ipip.data);
+
+ ipip.index = (byte *) malloc(length * sizeof(byte));
+ memcpy(ipip.index, ipip.data + 4, length);
+
+ ipip.offset = length;
+
+ ipip.flag = (uint *) malloc(256 * sizeof(uint));
+ memcpy(ipip.flag, ipip.index, 256 * sizeof(uint));
+
+ return 0;
+}
+
+int ipipdb_find(const uint32_t ip, char *result) {
+ uint ip_prefix_value = (ip & 0xFF000000) >> 24;
+ uint start = ipip.flag[ip_prefix_value];
+ uint max_comp_len = ipip.offset - 1028;
+ uint index_offset = 0;
+ uint index_length = 0;
+ for (start = start * 8 + 1024; start < max_comp_len; start += 8) {
+ if (B2IU(ipip.index + start) >= ip) {
+ index_offset = B2IL(ipip.index + start + 4) & 0x00FFFFFF;
+ index_length = ipip.index[start + 7];
+ break;
+ }
+ }
+ memcpy(result, ipip.data + ipip.offset + index_offset - 1024, index_length);
+ result[index_length] = '\0';
+ for (int i = 0; i < index_length; i++) {
+ if (result[i] == '\t') {
+ result[i] = ' ';
+ }
+ }
+ return 0;
+}
+
+
+static const char *ipip_get_location(struct in_addr *ip) {
+ ipipdb_init("/usr/local/share/17monipdb.dat");
+ static char buf[192];
+ buf[0] = '\0';
+ uint32_t res_ip = htonl(ip->s_addr);
+ strcpy(buf, " [");
+ ipipdb_find(res_ip, buf + 2);
+ strcat(buf, "]");
+ return buf;
+}
+
+
int
ping_echo (char *hostname)
{
@@ -139,9 +230,11 @@ ping_echo (char *hostname)
#endif /* IP_OPTIONS */
}
- printf ("PING %s (%s): %zu data bytes",
+ printf ("PING %s (%s)%s: %zu data bytes",
ping->ping_hostname,
- inet_ntoa (ping->ping_dest.ping_sockaddr.sin_addr), data_length);
+ inet_ntoa (ping->ping_dest.ping_sockaddr.sin_addr),
+ ipip_get_location(&ping->ping_dest.ping_sockaddr.sin_addr),
+ data_length);
if (options & OPT_VERBOSE)
printf (", id 0x%04x = %u", ping->ping_ident, ping->ping_ident);
diff --git a/src/traceroute.c b/src/traceroute.c
index 785dc6f..89098de 100644
--- a/src/traceroute.c
+++ b/src/traceroute.c
@@ -119,10 +119,11 @@ static enum trace_type opt_type = TRACE_UDP;
int opt_port = TRACE_UDP_PORT;
int opt_max_hops = 64;
static int opt_max_tries = 3;
-int opt_resolve_hostnames = 0;
+int opt_resolve_hostnames = 1;
int opt_tos = -1; /* Triggers with non-negative values. */
int opt_ttl = TRACE_TTL;
int opt_wait = TIME_INTERVAL;
+int opt_show_ipip = 1;
#ifdef IP_OPTIONS
char *opt_gateways = NULL;
#endif
@@ -134,10 +135,6 @@ const char *program_authors[] = {
NULL
};
-/* Define keys for long options that do not have short counterparts. */
-enum {
- OPT_RESOLVE = 256
-};
static struct argp_option argp_options[] = {
#define GRP 0
@@ -151,7 +148,7 @@ static struct argp_option argp_options[] = {
{"max-hop", 'm', "NUM", 0, "set maximal hop count (default: 64)", GRP+1},
{"port", 'p', "PORT", 0, "use destination PORT port (default: 33434)",
GRP+1},
- {"resolve-hostnames", OPT_RESOLVE, NULL, 0, "resolve hostnames", GRP+1},
+ {"no-resolve-hostnames", 'n', NULL, 0, "do not resolve hostnames", GRP+1},
{"tos", 't', "NUM", 0, "set type of service (TOS) to NUM", GRP+1},
{"tries", 'q', "NUM", 0, "send NUM probe packets per hop (default: 3)",
GRP+1},
@@ -159,6 +156,9 @@ static struct argp_option argp_options[] = {
"operations, defaulting to `udp'", GRP+1},
{"wait", 'w', "NUM", 0, "wait NUM seconds for response (default: 3)",
GRP+1},
+ {"no-ipip-geolocation", 'y', NULL, 0, "do not show ipip geolocation",
+ GRP+1},
+
#undef GRP
{NULL, 0, NULL, 0, NULL, 0}
};
@@ -243,8 +243,12 @@ parse_opt (int key, char *arg, struct argp_state *state)
error (EXIT_FAILURE, 0, "ridiculous waiting time `%s'", arg);
break;
- case OPT_RESOLVE:
- opt_resolve_hostnames = 1;
+ case 'n':
+ opt_resolve_hostnames = 0;
+ break;
+
+ case 'y':
+ opt_show_ipip = 0;
break;
case ARGP_KEY_ARG:
@@ -349,6 +353,95 @@ main (int argc, char **argv)
exit (EXIT_SUCCESS);
}
+typedef unsigned char byte;
+typedef unsigned int uint;
+#define B2IL(b) (((b)[0] & 0xFF) | (((b)[1] << 8) & 0xFF00) | (((b)[2] << 16) & 0xFF0000) | (((b)[3] << 24) & 0xFF000000))
+#define B2IU(b) (((b)[3] & 0xFF) | (((b)[2] << 8) & 0xFF00) | (((b)[1] << 16) & 0xFF0000) | (((b)[0] << 24) & 0xFF000000))
+
+struct {
+ byte *data;
+ byte *index;
+ uint *flag;
+ uint offset;
+} ipip;
+
+int ipipdb_destroy() {
+ if (!ipip.offset) {
+ return 0;
+ }
+ free(ipip.flag);
+ free(ipip.index);
+ free(ipip.data);
+ ipip.offset = 0;
+ return 0;
+}
+
+int ipipdb_init(const char *ipdb) {
+ if (ipip.offset) {
+ return 0;
+ }
+ FILE *file = fopen(ipdb, "rb");
+ fseek(file, 0, SEEK_END);
+ long size = ftell(file);
+ fseek(file, 0, SEEK_SET);
+
+ ipip.data = (byte *) malloc(size * sizeof(byte));
+ size_t r = fread(ipip.data, sizeof(byte), (size_t) size, file);
+
+ if (r == 0) {
+ return 0;
+ }
+
+ fclose(file);
+
+ uint length = B2IU(ipip.data);
+
+ ipip.index = (byte *) malloc(length * sizeof(byte));
+ memcpy(ipip.index, ipip.data + 4, length);
+
+ ipip.offset = length;
+
+ ipip.flag = (uint *) malloc(256 * sizeof(uint));
+ memcpy(ipip.flag, ipip.index, 256 * sizeof(uint));
+
+ return 0;
+}
+
+int ipipdb_find(const uint32_t ip, char *result) {
+ uint ip_prefix_value = (ip & 0xFF000000) >> 24;
+ uint start = ipip.flag[ip_prefix_value];
+ uint max_comp_len = ipip.offset - 1028;
+ uint index_offset = 0;
+ uint index_length = 0;
+ for (start = start * 8 + 1024; start < max_comp_len; start += 8) {
+ if (B2IU(ipip.index + start) >= ip) {
+ index_offset = B2IL(ipip.index + start + 4) & 0x00FFFFFF;
+ index_length = ipip.index[start + 7];
+ break;
+ }
+ }
+ memcpy(result, ipip.data + ipip.offset + index_offset - 1024, index_length);
+ result[index_length] = '\0';
+ for (int i = 0; i < index_length; i++) {
+ if (result[i] == '\t') {
+ result[i] = ' ';
+ }
+ }
+ return 0;
+}
+
+
+static const char *ipip_get_location(struct in_addr *ip) {
+ ipipdb_init("/usr/local/share/17monipdb.dat");
+ static char buf[192];
+ buf[0] = '\0';
+ uint32_t res_ip = htonl(ip->s_addr);
+ strcpy(buf, " [");
+ ipipdb_find(res_ip, buf + 2);
+ strcat(buf, "]");
+ return buf;
+}
+
void
do_try (trace_t * trace, const int hop,
const int max_hops _GL_UNUSED_PARAMETER,
@@ -435,6 +528,8 @@ do_try (trace_t * trace, const int hop,
if (opt_resolve_hostnames)
printf ("(%s) ",
get_hostname (&trace->from.sin_addr));
+ if (opt_show_ipip)
+ printf("%s", ipip_get_location(&trace->from.sin_addr));
}
printf (" %.3fms ", triptime);
--
2.12.2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment