Commit 21c8a6b2 authored by Dan Winship's avatar Dan Winship

libnm-core, all: merge IPv4 and IPv6 address/route types

Merge NMIP4Address and NMIP6Address into NMIPAddress, and NMIP4Route
and NMIP6Route into NMIPRoute. The new types represent IP addresses as
strings, rather than in binary, and so are address-family agnostic.
parent 303e84e6
......@@ -95,8 +95,6 @@ construct_ip4_items (GSList *items, GVariant *ip4_config, const char *prefix)
char **dns, **wins;
GString *tmp;
GVariant *val;
char str_addr[INET_ADDRSTRLEN];
char str_gw[INET_ADDRSTRLEN];
int i;
if (ip4_config == NULL)
......@@ -111,14 +109,18 @@ construct_ip4_items (GSList *items, GVariant *ip4_config, const char *prefix)
addresses = nm_utils_ip4_addresses_from_variant (val);
for (i = 0; i < addresses->len; i++) {
NMIP4Address *addr = addresses->pdata[i];
guint32 ip_prefix = nm_ip4_address_get_prefix (addr);
NMIPAddress *addr = addresses->pdata[i];
const char *gw;
char *addrtmp;
nm_utils_inet4_ntop (nm_ip4_address_get_address (addr), str_addr);
nm_utils_inet4_ntop (nm_ip4_address_get_gateway (addr), str_gw);
gw = nm_ip_address_get_gateway (addr);
if (!gw)
gw = "0.0.0.0";
addrtmp = g_strdup_printf ("%sIP4_ADDRESS_%d=%s/%d %s", prefix, i, str_addr, ip_prefix, str_gw);
addrtmp = g_strdup_printf ("%sIP4_ADDRESS_%d=%s/%d %s", prefix, i,
nm_ip_address_get_address (addr),
nm_ip_address_get_prefix (addr),
gw);
items = g_slist_prepend (items, addrtmp);
}
if (addresses->len)
......@@ -177,15 +179,19 @@ construct_ip4_items (GSList *items, GVariant *ip4_config, const char *prefix)
routes = nm_utils_ip4_routes_from_variant (val);
for (i = 0; i < routes->len; i++) {
NMIP4Route *route = routes->pdata[i];
guint32 ip_prefix = nm_ip4_route_get_prefix (route);
guint32 metric = nm_ip4_route_get_metric (route);
NMIPRoute *route = routes->pdata[i];
const char *next_hop;
char *routetmp;
nm_utils_inet4_ntop (nm_ip4_route_get_dest (route), str_addr);
nm_utils_inet4_ntop (nm_ip4_route_get_next_hop (route), str_gw);
next_hop = nm_ip_route_get_next_hop (route);
if (!next_hop)
next_hop = "0.0.0.0";
routetmp = g_strdup_printf ("%sIP4_ROUTE_%d=%s/%d %s %d", prefix, i, str_addr, ip_prefix, str_gw, metric);
routetmp = g_strdup_printf ("%sIP4_ROUTE_%d=%s/%d %s %d", prefix, i,
nm_ip_route_get_dest (route),
nm_ip_route_get_prefix (route),
next_hop,
nm_ip_route_get_metric (route));
items = g_slist_prepend (items, routetmp);
}
items = g_slist_prepend (items, g_strdup_printf ("%sIP4_NUM_ROUTES=%d", prefix, routes->len));
......@@ -225,8 +231,6 @@ construct_ip6_items (GSList *items, GVariant *ip6_config, const char *prefix)
char **dns;
GString *tmp;
GVariant *val;
char str_addr[INET6_ADDRSTRLEN];
char str_gw[INET6_ADDRSTRLEN];
int i;
if (ip6_config == NULL)
......@@ -241,14 +245,18 @@ construct_ip6_items (GSList *items, GVariant *ip6_config, const char *prefix)
addresses = nm_utils_ip6_addresses_from_variant (val);
for (i = 0; i < addresses->len; i++) {
NMIP6Address *addr = addresses->pdata[i];
guint32 ip_prefix = nm_ip6_address_get_prefix (addr);
NMIPAddress *addr = addresses->pdata[i];
const char *gw;
char *addrtmp;
nm_utils_inet6_ntop (nm_ip6_address_get_address (addr), str_addr);
nm_utils_inet6_ntop (nm_ip6_address_get_gateway (addr), str_gw);
gw = nm_ip_address_get_gateway (addr);
if (!gw)
gw = "::";
addrtmp = g_strdup_printf ("%sIP6_ADDRESS_%d=%s/%d %s", prefix, i, str_addr, ip_prefix, str_gw);
addrtmp = g_strdup_printf ("%sIP6_ADDRESS_%d=%s/%d %s", prefix, i,
nm_ip_address_get_address (addr),
nm_ip_address_get_prefix (addr),
gw);
items = g_slist_prepend (items, addrtmp);
}
if (addresses->len)
......@@ -287,15 +295,19 @@ construct_ip6_items (GSList *items, GVariant *ip6_config, const char *prefix)
routes = nm_utils_ip6_routes_from_variant (val);
for (i = 0; i < routes->len; i++) {
NMIP6Route *route = routes->pdata[i];
guint32 ip_prefix = nm_ip6_route_get_prefix (route);
guint32 metric = nm_ip6_route_get_metric (route);
NMIPRoute *route = routes->pdata[i];
const char *next_hop;
char *routetmp;
nm_utils_inet6_ntop (nm_ip6_route_get_dest (route), str_addr);
nm_utils_inet6_ntop (nm_ip6_route_get_next_hop (route), str_gw);
next_hop = nm_ip_route_get_next_hop (route);
if (!next_hop)
next_hop = "::";
routetmp = g_strdup_printf ("%sIP6_ROUTE_%d=%s/%d %s %d", prefix, i, str_addr, ip_prefix, str_gw, metric);
routetmp = g_strdup_printf ("%sIP6_ROUTE_%d=%s/%d %s %d", prefix, i,
nm_ip_route_get_dest (route),
nm_ip_route_get_prefix (route),
next_hop,
nm_ip_route_get_metric (route));
items = g_slist_prepend (items, routetmp);
}
if (routes->len)
......
......@@ -218,32 +218,29 @@ parse_ip4 (GKeyFile *kf, GVariant **out_props, const char *section, GError **err
g_free (tmp);
if (g_strv_length (split) > 0) {
addresses = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip4_address_unref);
addresses = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip_address_unref);
for (iter = split; iter && *iter; iter++) {
NMIP4Address *addr;
guint32 a;
char *p;
NMIPAddress *addr;
char *ip, *prefix, *gw;
if (strlen (g_strstrip (*iter)) == 0)
continue;
addr = nm_ip4_address_new ();
ip = *iter;
p = strchr (*iter, '/');
g_assert (p);
*p++ = '\0';
prefix = strchr (ip, '/');
g_assert (prefix);
*prefix++ = '\0';
g_assert_cmpint (inet_pton (AF_INET, *iter, &a), ==, 1);
nm_ip4_address_set_address (addr, a);
nm_ip4_address_set_prefix (addr, (guint) atoi (p));
p = strchr (p, ' ');
g_assert (p);
p++;
g_assert_cmpint (inet_pton (AF_INET, p, &a), ==, 1);
nm_ip4_address_set_gateway (addr, a);
gw = strchr (prefix, ' ');
g_assert (gw);
gw++;
addr = nm_ip_address_new (AF_INET, ip, (guint) atoi (prefix), gw, error);
if (!addr) {
g_ptr_array_unref (addresses);
return FALSE;
}
g_ptr_array_add (addresses, addr);
}
......@@ -261,37 +258,36 @@ parse_ip4 (GKeyFile *kf, GVariant **out_props, const char *section, GError **err
g_free (tmp);
if (g_strv_length (split) > 0) {
routes = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip4_route_unref);
routes = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip_route_unref);
for (iter = split; iter && *iter; iter++) {
NMIP4Route *route;
guint32 a;
char *p;
NMIPRoute *route;
char *dest, *prefix, *next_hop, *metric;
if (strlen (g_strstrip (*iter)) == 0)
continue;
route = nm_ip4_route_new ();
p = strchr (*iter, '/');
g_assert (p);
*p++ = '\0';
g_assert_cmpint (inet_pton (AF_INET, *iter, &a), ==, 1);
nm_ip4_route_set_dest (route, a);
nm_ip4_route_set_prefix (route, (guint) atoi (p));
dest = *iter;
p = strchr (p, ' ');
g_assert (p);
p++;
prefix = strchr (dest, '/');
g_assert (prefix);
*prefix++ = '\0';
g_assert_cmpint (inet_pton (AF_INET, p, &a), ==, 1);
nm_ip4_route_set_next_hop (route, a);
next_hop = strchr (prefix, ' ');
g_assert (next_hop);
next_hop++;
p = strchr (p, ' ');
g_assert (p);
p++;
nm_ip4_route_set_metric (route, (guint) atoi (p));
metric = strchr (next_hop, ' ');
g_assert (metric);
metric++;
route = nm_ip_route_new (AF_INET,
dest, (guint) atoi (prefix),
next_hop, (guint) atoi (metric),
error);
if (!route) {
g_ptr_array_unref (routes);
return FALSE;
}
g_ptr_array_add (routes, route);
}
......
......@@ -30,6 +30,8 @@
#include <readline/readline.h>
#include <readline/history.h>
#include "nm-glib-compat.h"
#include "common.h"
#include "utils.h"
......@@ -104,17 +106,17 @@ print_ip4_config (NMIP4Config *cfg4,
if (ptr_array) {
addr_arr = g_new (char *, ptr_array->len + 1);
for (i = 0; i < ptr_array->len; i++) {
NMIP4Address *addr = (NMIP4Address *) g_ptr_array_index (ptr_array, i);
guint32 prefix;
char *ip_str, *gw_str;
NMIPAddress *addr = (NMIPAddress *) g_ptr_array_index (ptr_array, i);
const char *gw;
ip_str = nmc_ip4_address_as_string (nm_ip4_address_get_address (addr), NULL);
prefix = nm_ip4_address_get_prefix (addr);
gw_str = nmc_ip4_address_as_string (nm_ip4_address_get_gateway (addr), NULL);
gw = nm_ip_address_get_gateway (addr);
if (!gw)
gw = "0.0.0.0";
addr_arr[i] = g_strdup_printf ("ip = %s/%u, gw = %s", ip_str, prefix, gw_str);
g_free (ip_str);
g_free (gw_str);
addr_arr[i] = g_strdup_printf ("ip = %s/%u, gw = %s",
nm_ip_address_get_address (addr),
nm_ip_address_get_prefix (addr),
gw);
}
addr_arr[i] = NULL;
}
......@@ -124,18 +126,18 @@ print_ip4_config (NMIP4Config *cfg4,
if (ptr_array) {
route_arr = g_new (char *, ptr_array->len + 1);
for (i = 0; i < ptr_array->len; i++) {
NMIP4Route *route = (NMIP4Route *) g_ptr_array_index (ptr_array, i);
guint32 prefix, metric;
char *dest_str, *nexthop_str;
dest_str = nmc_ip4_address_as_string (nm_ip4_route_get_dest (route), NULL);
nexthop_str = nmc_ip4_address_as_string (nm_ip4_route_get_next_hop (route), NULL);
prefix = nm_ip4_route_get_prefix (route);
metric = nm_ip4_route_get_metric (route);
route_arr[i] = g_strdup_printf ("dst = %s/%u, nh = %s, mt = %u", dest_str, prefix, nexthop_str, metric);
g_free (dest_str);
g_free (nexthop_str);
NMIPRoute *route = (NMIPRoute *) g_ptr_array_index (ptr_array, i);
const char *next_hop;
next_hop = nm_ip_route_get_next_hop (route);
if (!next_hop)
next_hop = "0.0.0.0";
route_arr[i] = g_strdup_printf ("dst = %s/%u, nh = %s, mt = %u",
nm_ip_route_get_dest (route),
nm_ip_route_get_prefix (route),
next_hop,
nm_ip_route_get_metric (route));
}
route_arr[i] = NULL;
}
......@@ -196,17 +198,17 @@ print_ip6_config (NMIP6Config *cfg6,
if (ptr_array) {
addr_arr = g_new (char *, ptr_array->len + 1);
for (i = 0; i < ptr_array->len; i++) {
NMIP6Address *addr = (NMIP6Address *) g_ptr_array_index (ptr_array, i);
guint32 prefix;
char *ip_str, *gw_str;
NMIPAddress *addr = (NMIPAddress *) g_ptr_array_index (ptr_array, i);
const char *gw;
ip_str = nmc_ip6_address_as_string (nm_ip6_address_get_address (addr), NULL);
prefix = nm_ip6_address_get_prefix (addr);
gw_str = nmc_ip6_address_as_string (nm_ip6_address_get_gateway (addr), NULL);
gw = nm_ip_address_get_gateway (addr);
if (!gw)
gw = "::";
addr_arr[i] = g_strdup_printf ("ip = %s/%u, gw = %s", ip_str, prefix, gw_str);
g_free (ip_str);
g_free (gw_str);
addr_arr[i] = g_strdup_printf ("ip = %s/%u, gw = %s",
nm_ip_address_get_address (addr),
nm_ip_address_get_prefix (addr),
gw);
}
addr_arr[i] = NULL;
}
......@@ -216,18 +218,18 @@ print_ip6_config (NMIP6Config *cfg6,
if (ptr_array) {
route_arr = g_new (char *, ptr_array->len + 1);
for (i = 0; i < ptr_array->len; i++) {
NMIP6Route *route = (NMIP6Route *) g_ptr_array_index (ptr_array, i);
guint32 prefix, metric;
char *dest_str, *nexthop_str;
dest_str = nmc_ip6_address_as_string (nm_ip6_route_get_dest (route), NULL);
nexthop_str = nmc_ip6_address_as_string (nm_ip6_route_get_next_hop (route), NULL);
prefix = nm_ip6_route_get_prefix (route);
metric = nm_ip6_route_get_metric (route);
route_arr[i] = g_strdup_printf ("dst = %s/%u, nh = %s, mt = %u", dest_str, prefix, nexthop_str, metric);
g_free (dest_str);
g_free (nexthop_str);
NMIPRoute *route = (NMIPRoute *) g_ptr_array_index (ptr_array, i);
const char *next_hop;
next_hop = nm_ip_route_get_next_hop (route);
if (!next_hop)
next_hop = "::";
route_arr[i] = g_strdup_printf ("dst = %s/%u, nh = %s, mt = %u",
nm_ip_route_get_dest (route),
nm_ip_route_get_prefix (route),
next_hop,
nm_ip_route_get_metric (route));
}
route_arr[i] = NULL;
}
......@@ -351,18 +353,20 @@ print_dhcp6_config (NMDhcp6Config *dhcp6,
}
/*
* Parse IPv4 address from string to NMIP4Address stucture.
* ip_str is the IPv4 address in the form address/prefix
* Parse IP address from string to NMIPAddress stucture.
* ip_str is the IP address in the form address/prefix
* gw_str is the gateway address (it is optional)
*/
NMIP4Address *
nmc_parse_and_build_ip4_address (const char *ip_str, const char *gw_str, GError **error)
NMIPAddress *
nmc_parse_and_build_address (int family, const char *ip_str, const char *gw_str, GError **error)
{
NMIP4Address *addr = NULL;
guint32 ip4_addr, gw_addr;
int max_prefix = (family == AF_INET) ? 32 : 128;
NMIPAddress *addr = NULL;
const char *ip;
char *tmp;
char *plen;
long int prefix;
GError *local = NULL;
g_return_val_if_fail (ip_str != NULL, NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
......@@ -372,158 +376,71 @@ nmc_parse_and_build_ip4_address (const char *ip_str, const char *gw_str, GError
if (plen)
*plen++ = '\0';
if (inet_pton (AF_INET, tmp, &ip4_addr) < 1) {
g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
_("invalid IPv4 address '%s'"), tmp);
goto finish;
}
ip = tmp;
prefix = 32;
prefix = max_prefix;
if (plen) {
if (!nmc_string_to_int (plen, TRUE, 1, 32, &prefix)) {
if (!nmc_string_to_int (plen, TRUE, 1, max_prefix, &prefix)) {
g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
_("invalid prefix '%s'; <1-32> allowed"), plen);
_("invalid prefix '%s'; <1-%d> allowed"), plen, max_prefix);
goto finish;
}
}
if (inet_pton (AF_INET, gw_str ? gw_str : "0.0.0.0", &gw_addr) < 1) {
addr = nm_ip_address_new (family, ip, (guint32) prefix, gw_str, &local);
if (!addr) {
g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
_("invalid gateway '%s'"), gw_str);
goto finish;
_("invalid IP address: %s"), local->message);
g_clear_error (&local);
}
addr = nm_ip4_address_new ();
nm_ip4_address_set_address (addr, ip4_addr);
nm_ip4_address_set_prefix (addr, (guint32) prefix);
nm_ip4_address_set_gateway (addr, gw_addr);
finish:
g_free (tmp);
return addr;
}
/*
* Parse IPv6 address from string to NMIP6Address stucture.
* ip_str is the IPv6 address in the form address/prefix
* gw_str is the gateway address (it is optional)
*/
NMIP6Address *
nmc_parse_and_build_ip6_address (const char *ip_str, const char *gw_str, GError **error)
{
NMIP6Address *addr = NULL;
struct in6_addr ip_addr, gw_addr;
char *tmp;
char *plen;
long int prefix;
g_return_val_if_fail (ip_str != NULL, NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
tmp = g_strdup (ip_str);
plen = strchr (tmp, '/'); /* prefix delimiter */
if (plen)
*plen++ = '\0';
if (inet_pton (AF_INET6, tmp, &ip_addr) < 1) {
g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
_("invalid IPv6 address '%s'"), tmp);
goto finish;
}
prefix = 128;
if (plen) {
if (!nmc_string_to_int (plen, TRUE, 1, 128, &prefix)) {
g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
_("invalid prefix '%s'; <1-128> allowed"), plen);
goto finish;
}
}
if (inet_pton (AF_INET6, gw_str ? gw_str : "::", &gw_addr) < 1) {
g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
_("invalid gateway '%s'"), gw_str);
goto finish;
}
addr = nm_ip6_address_new ();
nm_ip6_address_set_address (addr, &ip_addr);
nm_ip6_address_set_prefix (addr, (guint32) prefix);
nm_ip6_address_set_gateway (addr, &gw_addr);
finish:
g_free (tmp);
return addr;
}
typedef struct {
long int prefix;
long int metric;
union _IpDest {
guint32 ip4_dst;
struct in6_addr ip6_dst;
} dst;
union _IpNextHop {
guint32 ip4_nh;
struct in6_addr ip6_nh;
} nh;
} ParsedRoute;
/*
* _parse_and_build_route:
* nmc_parse_and_build_route:
* @family: AF_INET or AF_INET6
* @first: the route destination in the form of "address/prefix"
(/prefix is optional)
* @second: (allow-none): next hop address, if third is not NULL. Otherwise it could be
either next hop address or metric. (It can be NULL when @third is NULL).
* @third: (allow-none): route metric
* @out: (out): route struct to fill
* @error: location to store GError
*
* Parse route from strings and fill @out parameter.
* Parse route from strings and return an #NMIPRoute
*
* Returns: %TRUE on success, %FALSE on failure
*/
static gboolean
_parse_and_build_route (int family,
const char *first,
const char *second,
const char *third,
ParsedRoute *out,
GError **error)
NMIPRoute *
nmc_parse_and_build_route (int family,
const char *first,
const char *second,
const char *third,
GError **error)
{
int max_prefix;
char *tmp, *plen;
int max_prefix = (family == AF_INET) ? 32 : 128;
char *dest = NULL, *plen = NULL;
const char *next_hop = NULL;
const char *canon_dest;
long int prefix = max_prefix, metric = 0;
NMIPRoute *route = NULL;
gboolean success = FALSE;
GError *local = NULL;
g_return_val_if_fail (family == AF_INET || family == AF_INET6, FALSE);
g_return_val_if_fail (first != NULL, FALSE);
g_return_val_if_fail (second || !third, FALSE);
g_return_val_if_fail (out, FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
max_prefix = (family == AF_INET) ? 32 : 128;
/* initialize default values */
out->prefix = max_prefix;
out->metric = 0;
if (family == AF_INET)
out->nh.ip4_nh = 0;
else
out->nh.ip6_nh = in6addr_any;
tmp = g_strdup (first);
plen = strchr (tmp, '/'); /* prefix delimiter */
dest = g_strdup (first);
plen = strchr (dest, '/'); /* prefix delimiter */
if (plen)
*plen++ = '\0';
if (inet_pton (family, tmp, family == AF_INET ? (void *) &out->dst.ip4_dst : (void *) &out->dst.ip6_dst) < 1) {
g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
_("invalid route destination address '%s'"), tmp);
goto finish;
}
if (plen) {
if (!nmc_string_to_int (plen, TRUE, 1, max_prefix, &out->prefix)) {
if (!nmc_string_to_int (plen, TRUE, 1, max_prefix, &prefix)) {
g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
_("invalid prefix '%s'; <1-%d> allowed"),
plen, max_prefix);
......@@ -532,113 +449,49 @@ _parse_and_build_route (int family,
}
if (second) {
if (inet_pton (family, second, family == AF_INET ? (void *) &out->nh.ip4_nh : (void *) &out->nh.ip6_nh) < 1) {
if (third) {
g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
_("invalid next hop address '%s'"), second);
if (third || nm_utils_ipaddr_valid (family, second))
next_hop = second;
else {
/* 'second' can be a metric */
if (!nmc_string_to_int (second, TRUE, 0, G_MAXUINT32, &metric)) {
g_set_error (error, 1, 0, _("the second component of route ('%s') is neither "
"a next hop address nor a metric"), second);
goto finish;
} else {
/* 'second' can be a metric */
if (!nmc_string_to_int (second, TRUE, 0, G_MAXUINT32, &out->metric)) {
g_set_error (error, 1, 0, _("the second component of route ('%s') is neither "
"a next hop address nor a metric"), second);
goto finish;
}
}
}
}
if (third) {
if (!nmc_string_to_int (third, TRUE, 0, G_MAXUINT32, &out->metric)) {
if (!nmc_string_to_int (third, TRUE, 0, G_MAXUINT32, &metric)) {
g_set_error (error, 1, 0, _("invalid metric '%s'"), third);
goto finish;
}
}
/* We don't accept default routes as NetworkManager handles it itself */
if ( (family == AF_INET && out->dst.ip4_dst == 0)
|| (family == AF_INET6 && IN6_IS_ADDR_UNSPECIFIED (&out->dst.ip6_dst))) {
route = nm_ip_route_new (family, dest, prefix, next_hop, metric, &local);
if (!route) {
g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
_("invalid route: %s"), local->message);
g_clear_error (&local);
goto finish;
}