summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorGlenn Ruben Bakke <glennbakke@gmail.com>2016-12-13 20:32:54 +0100
committerGlenn Ruben Bakke <glennbakke@gmail.com>2016-12-13 20:32:54 +0100
commit4344d41b36488a8a86b5e45c0edaec1ad1fd910a (patch)
treea597edf86cc04171f9b2c03ed3bd3db1a80cf388 /lib
parentd7dc0b789d3c6987dc44b8d43f541f77c1e7f164 (diff)
lib/netutils: Adding some basic parsing and formating of ipv6 address strings. Only working with full length ipv6 strings. Short forms not supported at the moment (for example FE80::1, needs to be expressed as FE80:0000:0000:0000:0000:0000:0000:0001).
Diffstat (limited to 'lib')
-rw-r--r--lib/netutils/netutils.c85
-rw-r--r--lib/netutils/netutils.h15
2 files changed, 100 insertions, 0 deletions
diff --git a/lib/netutils/netutils.c b/lib/netutils/netutils.c
index ac4ebfa2b..b896cf0c8 100644
--- a/lib/netutils/netutils.c
+++ b/lib/netutils/netutils.c
@@ -5,6 +5,7 @@
*
* Copyright (c) 2013, 2014 Damien P. George
* Copyright (c) 2015 Daniel Campora
+ * Copyright (c) 2016 Glenn Ruben Bakke
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -28,6 +29,7 @@
#include <stdint.h>
#include <stdio.h>
#include <string.h>
+#include <stdlib.h>
#include "py/obj.h"
#include "py/nlr.h"
@@ -93,3 +95,86 @@ mp_uint_t netutils_parse_inet_addr(mp_obj_t addr_in, uint8_t *out_ip, netutils_e
netutils_parse_ipv4_addr(addr_items[0], out_ip, endian);
return mp_obj_get_int(addr_items[1]);
}
+
+
+// Takes an array with a raw IPv6 address and returns something like '2001:db8::abcd:ef01:2345'.
+mp_obj_t netutils_format_ipv6_addr(uint8_t *ip, netutils_endian_t endian) {
+ char ip_str[40];
+ mp_uint_t ip_len;
+ if (endian == NETUTILS_LITTLE) {
+ ip_len = snprintf(ip_str, 40, "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
+ ip[15], ip[14], ip[13], ip[12],
+ ip[11], ip[10], ip[9], ip[8],
+ ip[7], ip[6], ip[5], ip[4],
+ ip[3], ip[2], ip[1], ip[0]);
+ } else {
+ ip_len = snprintf(ip_str, 40, "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
+ ip[0], ip[1], ip[2], ip[3],
+ ip[4], ip[5], ip[6], ip[7],
+ ip[8], ip[9], ip[10], ip[11],
+ ip[12], ip[13], ip[14], ip[15]);
+ }
+ return mp_obj_new_str(ip_str, ip_len, false);
+}
+
+// Takes an array with a raw IP address, and a port, and returns a net-address
+// tuple such as ('2001:db8::abcd:ef01:2345', 8080).
+mp_obj_t netutils_format_inet6_addr(uint8_t *ip, mp_uint_t port, netutils_endian_t endian) {
+ mp_obj_t tuple[2] = {
+ tuple[0] = netutils_format_ipv6_addr(ip, endian),
+ tuple[1] = mp_obj_new_int(port),
+ };
+ return mp_obj_new_tuple(2, tuple);
+}
+
+void netutils_parse_ipv6_addr(mp_obj_t addr_in, uint8_t *out_ip, netutils_endian_t endian) {
+ mp_uint_t addr_len;
+ const char *addr_str = mp_obj_str_get_data(addr_in, &addr_len);
+ if (addr_len == 0) {
+ // special case of no address given
+ memset(out_ip, 0, NETUTILS_IPV6ADDR_BUFSIZE);
+ return;
+ }
+
+ const char *s = addr_str;
+ const char *s_top = addr_str + addr_len;
+
+ for (uint8_t i = 0; i <= NETUTILS_IPV6ADDR_BUFSIZE; i += 2) {
+ uint16_t val = 0;
+ for (; s < s_top && *s != ':'; s++) {
+ if ((*s >= 'a' && *s <= 'f')) {
+ val = val * 16 + (*s - 'a' + 10);
+ } else if (*s >= 'A' && *s <= 'F') {
+ val = val * 16 + (*s - 'A' + 10);
+ } else {
+ val = val * 16 + (*s - '0');
+ }
+ }
+
+// if (endian == NETUTILS_LITTLE) {
+// // not supported
+// } else
+ {
+ out_ip[i] = (val >> 8);
+ out_ip[i + 1] = (val & 0xFF);
+ }
+
+ if (s == s_top) {
+ return;
+ } else if (s < s_top && *s == ':') {
+ s++;
+ } else {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "invalid arguments"));
+ }
+ }
+}
+
+// Takes an address of the form ('2001:db8::abcd:ef01:2345', 8080), returns the port and
+// puts IP in out_ip (which must take at least IPADDR_BUF_SIZE bytes).
+mp_uint_t netutils_parse_inet6_addr(mp_obj_t addr_in, uint8_t *out_ip, netutils_endian_t endian) {
+ mp_obj_t *addr_items;
+ mp_obj_get_array_fixed_n(addr_in, 2, &addr_items);
+ netutils_parse_ipv6_addr(addr_items[0], out_ip, endian);
+ return mp_obj_get_int(addr_items[1]);
+
+}
diff --git a/lib/netutils/netutils.h b/lib/netutils/netutils.h
index 45e021640..78ffffc55 100644
--- a/lib/netutils/netutils.h
+++ b/lib/netutils/netutils.h
@@ -5,6 +5,7 @@
*
* Copyright (c) 2013, 2014 Damien P. George
* Copyright (c) 2015 Daniel Campora
+ * Copyrigth (c) 2016 Glenn Ruben Bakke
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -28,6 +29,7 @@
#define __MICROPY_INCLUDED_LIB_NETUTILS_H__
#define NETUTILS_IPV4ADDR_BUFSIZE 4
+#define NETUTILS_IPV6ADDR_BUFSIZE 16
typedef enum _netutils_endian_t {
NETUTILS_LITTLE,
@@ -47,4 +49,17 @@ void netutils_parse_ipv4_addr(mp_obj_t addr_in, uint8_t *out_ip, netutils_endian
// puts IP in out_ip (which must take at least IPADDR_BUF_SIZE bytes).
mp_uint_t netutils_parse_inet_addr(mp_obj_t addr_in, uint8_t *out_ip, netutils_endian_t endian);
+// Takes an array with a raw IPv6 address and returns something like '2001:db8::abcd:ef01:2345'.
+mp_obj_t netutils_format_ipv6_addr(uint8_t *ip, netutils_endian_t endian);
+
+// Takes an array with a raw IP address, and a port, and returns a net-address
+// tuple such as ('2001:db8::abcd:ef01:2345', 8080).
+mp_obj_t netutils_format_inet6_addr(uint8_t *ip, mp_uint_t port, netutils_endian_t endian);
+
+void netutils_parse_ipv6_addr(mp_obj_t addr_in, uint8_t *out_ip, netutils_endian_t endian);
+
+// Takes an address of the form ('2001:db8::abcd:ef01:2345', 8080), returns the port and
+// puts IP in out_ip (which must take at least IPADDR_BUF_SIZE bytes).
+mp_uint_t netutils_parse_inet6_addr(mp_obj_t addr_in, uint8_t *out_ip, netutils_endian_t endian);
+
#endif // __MICROPY_INCLUDED_LIB_NETUTILS_H__