/* * Parse IPv4 routes from strings to NMIP4Route stucture. * ip_str is the IPv4 route in the form of address/prefix * next_hop_str is the next_hop address * metric_str is the route metric */ NMIP4Route * nmc_parse_and_build_ip4_route (const char *ip_str, const char *next_hop_str, const char *metric_str, GError **error) { NMIP4Route *route = NULL; guint32 ip4_addr, next_hop_addr; char *tmp; char *plen; long int prefix, metric; g_return_val_if_fail (ip_str != NULL, NULL); g_return_val_if_fail (next_hop_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_INET, tmp, &ip4_addr) < 1) { g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT, _("invalid IPv4 route '%s'"), tmp); goto finish; } prefix = 32; if (plen) { if (!nmc_string_to_int (plen, TRUE, 0, 32, &prefix)) { g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT, _("invalid prefix '%s'; <0-32> allowed"), plen); goto finish; } } if (inet_pton (AF_INET, next_hop_str, &next_hop_addr) < 1) { g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT, _("invalid next hop address '%s'"), next_hop_str); goto finish; } metric = 0; if (metric_str) { if (!nmc_string_to_int (metric_str, TRUE, 0, G_MAXUINT32, &metric)) { g_set_error (error, 1, 0, _("invalid metric '%s'"), metric_str); goto finish; } } route = nm_ip4_route_new (); nm_ip4_route_set_dest (route, ip4_addr); nm_ip4_route_set_prefix (route, (guint32) prefix); nm_ip4_route_set_next_hop (route, next_hop_addr); nm_ip4_route_set_metric (route, (guint32) metric); finish: g_free (tmp); return route; }
/** * nm_ip4_route_dup: * @source: the #NMIP4Route object to copy * * Copies a given #NMIP4Route object and returns the copy. * * Returns: (transfer full): the copy of the given #NMIP4Route copy **/ NMIP4Route * nm_ip4_route_dup (NMIP4Route *source) { NMIP4Route *route; g_return_val_if_fail (source != NULL, NULL); g_return_val_if_fail (source->refcount > 0, NULL); route = nm_ip4_route_new (); route->dest = source->dest; route->prefix = source->prefix; route->next_hop = source->next_hop; route->metric = source->metric; return route; }
static void process_classful_routes (GHashTable *options, NMIP4Config *ip4_config) { const char *str; char **searches, **s; str = g_hash_table_lookup (options, "new_static_routes"); if (!str) return; searches = g_strsplit (str, " ", 0); if ((g_strv_length (searches) % 2)) { nm_log_info (LOGD_DHCP, " static routes provided, but invalid"); goto out; } for (s = searches; *s; s += 2) { NMIP4Route *route; struct in_addr rt_addr; struct in_addr rt_route; if (inet_pton (AF_INET, *s, &rt_addr) <= 0) { nm_log_warn (LOGD_DHCP, "DHCP provided invalid static route address: '%s'", *s); continue; } if (inet_pton (AF_INET, *(s + 1), &rt_route) <= 0) { nm_log_warn (LOGD_DHCP, "DHCP provided invalid static route gateway: '%s'", *(s + 1)); continue; } // FIXME: ensure the IP addresse and route are sane route = nm_ip4_route_new (); nm_ip4_route_set_dest (route, (guint32) rt_addr.s_addr); nm_ip4_route_set_prefix (route, 32); /* 255.255.255.255 */ nm_ip4_route_set_next_hop (route, (guint32) rt_route.s_addr); nm_ip4_config_take_route (ip4_config, route); nm_log_info (LOGD_DHCP, " static route %s gw %s", *s, *(s + 1)); } out: g_strfreev (searches); }
static gboolean ip4_process_dhcpcd_rfc3442_routes (const char *str, NMIP4Config *ip4_config, guint32 *gwaddr) { char **routes, **r; gboolean have_routes = FALSE; routes = g_strsplit (str, " ", 0); if (g_strv_length (routes) == 0) goto out; if ((g_strv_length (routes) % 2) != 0) { nm_log_warn (LOGD_DHCP4, " classless static routes provided, but invalid"); goto out; } for (r = routes; *r; r += 2) { char *slash; NMIP4Route *route; int rt_cidr = 32; struct in_addr rt_addr; struct in_addr rt_route; slash = strchr(*r, '/'); if (slash) { *slash = '\0'; errno = 0; rt_cidr = strtol (slash + 1, NULL, 10); if ((errno == EINVAL) || (errno == ERANGE)) { nm_log_warn (LOGD_DHCP4, "DHCP provided invalid classless static route cidr: '%s'", slash + 1); continue; } } if (inet_pton (AF_INET, *r, &rt_addr) <= 0) { nm_log_warn (LOGD_DHCP4, "DHCP provided invalid classless static route address: '%s'", *r); continue; } if (inet_pton (AF_INET, *(r + 1), &rt_route) <= 0) { nm_log_warn (LOGD_DHCP4, "DHCP provided invalid classless static route gateway: '%s'", *(r + 1)); continue; } have_routes = TRUE; if (rt_cidr == 0 && rt_addr.s_addr == 0) { /* FIXME: how to handle multiple routers? */ *gwaddr = rt_route.s_addr; } else { route = nm_ip4_route_new (); nm_ip4_route_set_dest (route, (guint32) rt_addr.s_addr); nm_ip4_route_set_prefix (route, rt_cidr); nm_ip4_route_set_next_hop (route, (guint32) rt_route.s_addr); nm_ip4_config_take_route (ip4_config, route); nm_log_info (LOGD_DHCP4, " classless static route %s/%d gw %s", *r, rt_cidr, *(r + 1)); } } out: g_strfreev (routes); return have_routes; }
void ip4_routes_dialog_update_setting (GtkWidget *dialog, NMSettingIP4Config *s_ip4) { GtkBuilder *builder; GtkWidget *widget; GtkTreeModel *model; GtkTreeIter tree_iter; gboolean iter_valid; g_return_if_fail (dialog != NULL); g_return_if_fail (s_ip4 != NULL); builder = g_object_get_data (G_OBJECT (dialog), "builder"); g_return_if_fail (builder != NULL); g_return_if_fail (GTK_IS_BUILDER (builder)); widget = GTK_WIDGET (gtk_builder_get_object (builder, "ip4_routes")); model = gtk_tree_view_get_model (GTK_TREE_VIEW (widget)); iter_valid = gtk_tree_model_get_iter_first (model, &tree_iter); nm_setting_ip4_config_clear_routes (s_ip4); while (iter_valid) { guint32 addr = 0, prefix = 0, next_hop = 0, metric = 0; NMIP4Route *route; /* Address */ if (!get_one_addr (model, &tree_iter, COL_ADDRESS, TRUE, &addr)) { g_warning ("%s: IPv4 address missing or invalid!", __func__); goto next; } /* Prefix */ if (!get_one_prefix (model, &tree_iter, COL_PREFIX, TRUE, &prefix)) { g_warning ("%s: IPv4 prefix/netmask missing or invalid!", __func__); goto next; } /* Next hop (optional) */ if (!get_one_addr (model, &tree_iter, COL_NEXT_HOP, FALSE, &next_hop)) { g_warning ("%s: IPv4 next hop invalid!", __func__); goto next; } /* Metric (optional) */ if (!get_one_int (model, &tree_iter, COL_METRIC, G_MAXUINT32, FALSE, &metric)) { g_warning ("%s: IPv4 metric invalid!", __func__); goto next; } route = nm_ip4_route_new (); nm_ip4_route_set_dest (route, addr); nm_ip4_route_set_prefix (route, prefix); nm_ip4_route_set_next_hop (route, next_hop); nm_ip4_route_set_metric (route, metric); nm_setting_ip4_config_add_route (s_ip4, route); nm_ip4_route_unref (route); next: iter_valid = gtk_tree_model_iter_next (model, &tree_iter); } widget = GTK_WIDGET (gtk_builder_get_object (builder, "ip4_ignore_auto_routes")); g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_IGNORE_AUTO_ROUTES, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)), NULL); widget = GTK_WIDGET (gtk_builder_get_object (builder, "ip4_never_default")); g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_NEVER_DEFAULT, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)), NULL); }