static gboolean parse_netmask (const char *str, guint32 *prefix) { struct in_addr tmp_addr; glong tmp_prefix; if (!str || !*str) return FALSE; errno = 0; /* Is it a prefix? */ if (!strchr (str, '.')) { tmp_prefix = strtol (str, NULL, 10); if (!errno && tmp_prefix > 0 && tmp_prefix <= 32) { *prefix = tmp_prefix; return TRUE; } } /* Is it a netmask? */ if (inet_pton (AF_INET, str, &tmp_addr) > 0) { *prefix = nm_utils_ip4_netmask_to_prefix (tmp_addr.s_addr); return TRUE; } return FALSE; }
static ip_block * create_ip4_block (gchar * ip) { ip_block *iblock = g_slice_new0 (ip_block); guint32 tmp_ip4_addr; int i; guint length; gchar **ip_mask; /* prefix format */ if (strstr (ip, "/")) { gchar *prefix; ip_mask = g_strsplit (ip, "/", 0); length = g_strv_length (ip_mask); if (!nm_utils_ipaddr_valid (AF_INET, ip_mask[0])) goto error; iblock->ip = g_strdup (ip_mask[0]); prefix = ip_mask[1]; i = 0; while (i < length && g_ascii_isdigit (prefix[i])) i++; prefix[i] = '\0'; iblock->prefix = (guint32) atoi (ip_mask[1]); } else if (strstr (ip, "netmask")) { ip_mask = g_strsplit (ip, " ", 0); length = g_strv_length (ip_mask); if (!nm_utils_ipaddr_valid (AF_INET, ip_mask[0])) goto error; iblock->ip = g_strdup (ip_mask[0]); i = 0; while (i < length && !strstr (ip_mask[++i], "netmask")) ; while (i < length && ip_mask[++i][0] == '\0') ; if (i >= length) goto error; if (!inet_pton (AF_INET, ip_mask[i], &tmp_ip4_addr)) goto error; iblock->prefix = nm_utils_ip4_netmask_to_prefix (tmp_ip4_addr); } else { g_slice_free (ip_block, iblock); if (!is_ip6_address (ip) && !strstr (ip, "dhcp")) nm_log_warn (LOGD_SETTINGS, "Can't handle ipv4 address: %s, missing netmask or prefix", ip); return NULL; } if (iblock->prefix == 0 || iblock->prefix > 32) { nm_log_warn (LOGD_SETTINGS, "Can't handle ipv4 address: %s, invalid prefix", ip); goto error; } g_strfreev (ip_mask); return iblock; error: if (!is_ip6_address (ip)) nm_log_warn (LOGD_SETTINGS, "Can't handle IPv4 address: %s", ip); g_strfreev (ip_mask); g_free (iblock->ip); g_slice_free (ip_block, iblock); return NULL; }
void NetInfoIPv4::set_netmask(uint32_t mask) { netdev_netmask = mask; memset(netmask_string, 0, sizeof(netmask_string)); if (AM_UNLIKELY(NULL == inet_ntop(AF_INET, (void*)&netdev_netmask, netmask_string, INET_ADDRSTRLEN))) { PERROR("inet_ntop"); } netdev_prefix = nm_utils_ip4_netmask_to_prefix (netdev_netmask); }
void NetInfoIPv4::set_netmask(const char* mask) { memset(netmask_string, 0, sizeof(netmask_string)); netdev_netmask = 0; if (AM_LIKELY(mask)) { if (AM_LIKELY(inet_pton(AF_INET, mask, &netdev_netmask) > 0)) { strncpy(netmask_string, mask, strlen(mask)); } else { PERROR("inet_pton"); } } netdev_prefix = nm_utils_ip4_netmask_to_prefix (netdev_netmask); }
static gboolean get_one_prefix (GtkTreeModel *model, GtkTreeIter *iter, int column, gboolean fail_if_missing, guint32 *out) { char *item = NULL; struct in_addr tmp_addr = { 0 }; gboolean success = FALSE; glong tmp_prefix; gtk_tree_model_get (model, iter, column, &item, -1); if (!item || !strlen (item)) { g_free (item); return fail_if_missing ? FALSE : TRUE; } errno = 0; /* Is it a prefix? */ if (!strchr (item, '.')) { tmp_prefix = strtol (item, NULL, 10); if (!errno && tmp_prefix >= 0 && tmp_prefix <= 32) { *out = tmp_prefix; success = TRUE; goto out; } } /* Is it a netmask? */ if (inet_pton (AF_INET, item, &tmp_addr) > 0) { *out = nm_utils_ip4_netmask_to_prefix (tmp_addr.s_addr); success = TRUE; } out: g_free (item); return success; }
static gboolean update_ip4_setting_from_if_block(NMConnection *connection, if_block *block, GError **error) { NMSettingIPConfig *s_ip4 = NM_SETTING_IP_CONFIG (nm_setting_ip4_config_new()); const char *type = ifparser_getkey(block, "inet"); gboolean is_static = type && !strcmp("static", type); if (!is_static) { g_object_set (s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); } else { guint32 tmp_mask; NMIPAddress *addr; const char *address_v; const char *netmask_v; const char *gateway_v; const char *nameserver_v; const char *nameservers_v; const char *search_v; char **list, **iter; guint32 netmask_int = 32; /* Address */ address_v = ifparser_getkey (block, "address"); if (!address_v) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Missing IPv4 address"); goto error; } /* mask/prefix */ netmask_v = ifparser_getkey (block, "netmask"); if (netmask_v) { if (strlen (netmask_v) < 7) { netmask_int = atoi (netmask_v); } else if (!inet_pton (AF_INET, netmask_v, &tmp_mask)) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Invalid IPv4 netmask '%s'", netmask_v); goto error; } else { netmask_int = nm_utils_ip4_netmask_to_prefix (tmp_mask); } } /* Add the new address to the setting */ addr = nm_ip_address_new (AF_INET, address_v, netmask_int, error); if (!addr) goto error; if (nm_setting_ip_config_add_address (s_ip4, addr)) { nm_log_info (LOGD_SETTINGS, "addresses count: %d", nm_setting_ip_config_get_num_addresses (s_ip4)); } else { nm_log_info (LOGD_SETTINGS, "ignoring duplicate IP4 address"); } nm_ip_address_unref (addr); /* gateway */ gateway_v = ifparser_getkey (block, "gateway"); if (gateway_v) { if (!nm_utils_ipaddr_valid (AF_INET, gateway_v)) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Invalid IPv4 gateway '%s'", gateway_v); goto error; } if (!nm_setting_ip_config_get_gateway (s_ip4)) g_object_set (s_ip4, NM_SETTING_IP_CONFIG_GATEWAY, gateway_v, NULL); } nameserver_v = ifparser_getkey (block, "dns-nameserver"); ifupdown_ip4_add_dns (s_ip4, nameserver_v); nameservers_v = ifparser_getkey (block, "dns-nameservers"); ifupdown_ip4_add_dns (s_ip4, nameservers_v); if (!nm_setting_ip_config_get_num_dns (s_ip4)) nm_log_info (LOGD_SETTINGS, "No dns-nameserver configured in /etc/network/interfaces"); /* DNS searches */ search_v = ifparser_getkey (block, "dns-search"); if (search_v) { list = g_strsplit_set (search_v, " \t", -1); for (iter = list; iter && *iter; iter++) { g_strstrip (*iter); if (g_ascii_isspace (*iter[0])) continue; if (!nm_setting_ip_config_add_dns_search (s_ip4, *iter)) nm_log_warn (LOGD_SETTINGS, " duplicate DNS domain '%s'", *iter); } g_strfreev (list); } g_object_set (s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, NULL); } nm_connection_add_setting (connection, NM_SETTING (s_ip4)); return TRUE; error: g_object_unref (s_ip4); return FALSE; }
static NMIP4Config * lease_to_ip4_config (const char *iface, int ifindex, sd_dhcp_lease *lease, GHashTable *options, guint32 default_priority, gboolean log_lease, GError **error) { NMIP4Config *ip4_config = NULL; struct in_addr tmp_addr; const struct in_addr *addr_list; char buf[INET_ADDRSTRLEN]; const char *str; guint32 lifetime = 0, i; NMPlatformIP4Address address; GString *l; gs_free sd_dhcp_route **routes = NULL; guint16 mtu; int r, num; guint64 end_time; const void *data; gsize data_len; gboolean metered = FALSE; gboolean static_default_gateway = FALSE; g_return_val_if_fail (lease != NULL, NULL); ip4_config = nm_ip4_config_new (ifindex); /* Address */ sd_dhcp_lease_get_address (lease, &tmp_addr); memset (&address, 0, sizeof (address)); address.address = tmp_addr.s_addr; address.peer_address = tmp_addr.s_addr; str = nm_utils_inet4_ntop (tmp_addr.s_addr, NULL); LOG_LEASE (LOGD_DHCP4, " address %s", str); add_option (options, dhcp4_requests, DHCP_OPTION_IP_ADDRESS, str); /* Prefix/netmask */ sd_dhcp_lease_get_netmask (lease, &tmp_addr); address.plen = nm_utils_ip4_netmask_to_prefix (tmp_addr.s_addr); LOG_LEASE (LOGD_DHCP4, " plen %d", address.plen); add_option (options, dhcp4_requests, SD_DHCP_OPTION_SUBNET_MASK, nm_utils_inet4_ntop (tmp_addr.s_addr, NULL)); /* Lease time */ sd_dhcp_lease_get_lifetime (lease, &lifetime); address.timestamp = nm_utils_get_monotonic_timestamp_s (); address.lifetime = address.preferred = lifetime; end_time = (guint64) time (NULL) + lifetime; LOG_LEASE (LOGD_DHCP4, " expires in %" G_GUINT32_FORMAT " seconds", lifetime); add_option_u64 (options, dhcp4_requests, SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME, end_time); address.addr_source = NM_IP_CONFIG_SOURCE_DHCP; nm_ip4_config_add_address (ip4_config, &address); /* DNS Servers */ num = sd_dhcp_lease_get_dns (lease, &addr_list); if (num > 0) { l = g_string_sized_new (30); for (i = 0; i < num; i++) { if (addr_list[i].s_addr) { nm_ip4_config_add_nameserver (ip4_config, addr_list[i].s_addr); str = nm_utils_inet4_ntop (addr_list[i].s_addr, NULL); LOG_LEASE (LOGD_DHCP4, " nameserver '%s'", str); g_string_append_printf (l, "%s%s", l->len ? " " : "", str); } } if (l->len) add_option (options, dhcp4_requests, SD_DHCP_OPTION_DOMAIN_NAME_SERVER, l->str); g_string_free (l, TRUE); } /* Domain Name */ r = sd_dhcp_lease_get_domainname (lease, &str); if (r == 0) { /* Multiple domains sometimes stuffed into option 15 "Domain Name". * As systemd escapes such characters, split them at \\032. */ char **domains = g_strsplit (str, "\\032", 0); char **s; for (s = domains; *s; s++) { LOG_LEASE (LOGD_DHCP4, " domain name '%s'", *s); nm_ip4_config_add_domain (ip4_config, *s); } g_strfreev (domains); add_option (options, dhcp4_requests, SD_DHCP_OPTION_DOMAIN_NAME, str); } /* Hostname */ r = sd_dhcp_lease_get_hostname (lease, &str); if (r == 0) { LOG_LEASE (LOGD_DHCP4, " hostname '%s'", str); add_option (options, dhcp4_requests, SD_DHCP_OPTION_HOST_NAME, str); } /* Routes */ num = sd_dhcp_lease_get_routes (lease, &routes); if (num > 0) { l = g_string_sized_new (30); for (i = 0; i < num; i++) { NMPlatformIP4Route route = { 0 }; const char *gw_str; guint8 plen; struct in_addr a; if (sd_dhcp_route_get_destination (routes[i], &a) < 0) continue; route.network = a.s_addr; if ( sd_dhcp_route_get_destination_prefix_length (routes[i], &plen) < 0 || plen > 32) continue; route.plen = plen; if (sd_dhcp_route_get_gateway (routes[i], &a) < 0) continue; route.gateway = a.s_addr; if (route.plen) { route.rt_source = NM_IP_CONFIG_SOURCE_DHCP; route.metric = default_priority; nm_ip4_config_add_route (ip4_config, &route); str = nm_utils_inet4_ntop (route.network, buf); gw_str = nm_utils_inet4_ntop (route.gateway, NULL); LOG_LEASE (LOGD_DHCP4, " static route %s/%d gw %s", str, route.plen, gw_str); g_string_append_printf (l, "%s%s/%d %s", l->len ? " " : "", str, route.plen, gw_str); } else { if (!static_default_gateway) { static_default_gateway = TRUE; nm_ip4_config_set_gateway (ip4_config, route.gateway); str = nm_utils_inet4_ntop (route.gateway, NULL); LOG_LEASE (LOGD_DHCP4, " gateway %s", str); add_option (options, dhcp4_requests, SD_DHCP_OPTION_ROUTER, str); } } } if (l->len) add_option (options, dhcp4_requests, SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE, l->str); g_string_free (l, TRUE); } /* If the DHCP server returns both a Classless Static Routes option and a * Router option, the DHCP client MUST ignore the Router option [RFC 3442]. * Be more lenient and ignore the Router option only if Classless Static * Routes contain a default gateway (as other DHCP backends do). */ /* Gateway */ if (!static_default_gateway) { r = sd_dhcp_lease_get_router (lease, &tmp_addr); if (r == 0) { nm_ip4_config_set_gateway (ip4_config, tmp_addr.s_addr); str = nm_utils_inet4_ntop (tmp_addr.s_addr, NULL); LOG_LEASE (LOGD_DHCP4, " gateway %s", str); add_option (options, dhcp4_requests, SD_DHCP_OPTION_ROUTER, str); } } /* MTU */ r = sd_dhcp_lease_get_mtu (lease, &mtu); if (r == 0 && mtu) { nm_ip4_config_set_mtu (ip4_config, mtu, NM_IP_CONFIG_SOURCE_DHCP); add_option_u32 (options, dhcp4_requests, SD_DHCP_OPTION_INTERFACE_MTU, mtu); LOG_LEASE (LOGD_DHCP4, " mtu %u", mtu); } /* NTP servers */ num = sd_dhcp_lease_get_ntp (lease, &addr_list); if (num > 0) { l = g_string_sized_new (30); for (i = 0; i < num; i++) { str = nm_utils_inet4_ntop (addr_list[i].s_addr, buf); LOG_LEASE (LOGD_DHCP4, " ntp server '%s'", str); g_string_append_printf (l, "%s%s", l->len ? " " : "", str); } add_option (options, dhcp4_requests, SD_DHCP_OPTION_NTP_SERVER, l->str); g_string_free (l, TRUE); } r = sd_dhcp_lease_get_vendor_specific (lease, &data, &data_len); if (r >= 0) metered = !!memmem (data, data_len, "ANDROID_METERED", NM_STRLEN ("ANDROID_METERED")); nm_ip4_config_set_metered (ip4_config, metered); return ip4_config; }
static gboolean nm_openssh_send_ip4_config (sshtun_handle_t handle) { DBusGConnection *connection; GError *err = NULL; GHashTable *config; GValue *val; struct in_addr temp_addr; const char *tmp; connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &err); if (!connection) return FALSE; config = g_hash_table_new (g_str_hash, g_str_equal); /* Gateway */ val = addr_to_gvalue (sshtun_get_param (handle, SSHTUN_PARAM_GW_ADDR)); if (val) g_hash_table_insert (config, NM_VPN_PLUGIN_IP4_CONFIG_GATEWAY, val); else { helper_failed (connection, "VPN Gateway"); dbus_g_connection_unref (connection); return FALSE; } /* Tunnel device */ val = str_to_gvalue (sshtun_get_param (handle, SSHTUN_PARAM_TUN_DEV), FALSE); if (val) g_hash_table_insert (config, NM_VPN_PLUGIN_IP4_CONFIG_TUNDEV, val); else { helper_failed (connection, "Tunnel Device"); dbus_g_connection_unref (connection); return FALSE; } /* IP address */ val = addr_to_gvalue (sshtun_get_param (handle, SSHTUN_PARAM_ADDR)); if (val) g_hash_table_insert (config, NM_VPN_PLUGIN_IP4_CONFIG_ADDRESS, val); else { helper_failed (connection, "IP4 Address"); dbus_g_connection_unref (connection); return FALSE; } /* PTP address */ val = addr_to_gvalue (sshtun_get_param (handle, SSHTUN_PARAM_PEER_ADDR)); if (val) g_hash_table_insert (config, NM_VPN_PLUGIN_IP4_CONFIG_PTP, val); /* Netmask */ tmp = sshtun_get_param (handle, SSHTUN_PARAM_NETMASK); if (tmp && inet_pton (AF_INET, tmp, &temp_addr) > 0) { val = uint_to_gvalue (nm_utils_ip4_netmask_to_prefix (temp_addr.s_addr)); g_hash_table_insert (config, NM_VPN_PLUGIN_IP4_CONFIG_PREFIX, val); } /* MTU */ tmp = sshtun_get_param (handle, SSHTUN_PARAM_MTU); if (tmp && strlen (tmp)) { long int mtu; errno = 0; mtu = strtol (tmp, NULL, 10); if (errno || mtu < 0 || mtu > 20000) { nm_warning ("Ignoring invalid tunnel MTU '%s'", tmp); } else { val = uint_to_gvalue ((guint32) mtu); g_hash_table_insert (config, NM_VPN_PLUGIN_IP4_CONFIG_MTU, val); } } send_ip4_config (connection, config); dbus_g_connection_unref (connection); return TRUE; }
NMIP4Config * nm_dhcp_utils_ip4_config_from_options (int ifindex, const char *iface, GHashTable *options, guint32 priority) { NMIP4Config *ip4_config = NULL; guint32 tmp_addr; in_addr_t addr; NMPlatformIP4Address address; char *str = NULL; guint32 gwaddr = 0; guint8 plen = 0; g_return_val_if_fail (options != NULL, NULL); ip4_config = nm_ip4_config_new (ifindex); memset (&address, 0, sizeof (address)); address.timestamp = nm_utils_get_monotonic_timestamp_s (); str = g_hash_table_lookup (options, "ip_address"); if (str && (inet_pton (AF_INET, str, &addr) > 0)) nm_log_info (LOGD_DHCP4, " address %s", str); else goto error; str = g_hash_table_lookup (options, "subnet_mask"); if (str && (inet_pton (AF_INET, str, &tmp_addr) > 0)) { plen = nm_utils_ip4_netmask_to_prefix (tmp_addr); nm_log_info (LOGD_DHCP4, " plen %d (%s)", plen, str); } else { /* Get default netmask for the IP according to appropriate class. */ plen = nm_utils_ip4_get_default_prefix (addr); nm_log_info (LOGD_DHCP4, " plen %d (default)", plen); } nm_platform_ip4_address_set_addr (&address, addr, plen); /* Routes: if the server returns classless static routes, we MUST ignore * the 'static_routes' option. */ if (!ip4_process_classless_routes (options, priority, ip4_config, &gwaddr)) process_classful_routes (options, priority, ip4_config); if (gwaddr) { nm_log_info (LOGD_DHCP4, " gateway %s", nm_utils_inet4_ntop (gwaddr, NULL)); nm_ip4_config_set_gateway (ip4_config, gwaddr); } else { /* If the gateway wasn't provided as a classless static route with a * subnet length of 0, try to find it using the old-style 'routers' option. */ str = g_hash_table_lookup (options, "routers"); if (str) { char **routers = g_strsplit (str, " ", 0); char **s; for (s = routers; *s; s++) { /* FIXME: how to handle multiple routers? */ if (inet_pton (AF_INET, *s, &gwaddr) > 0) { nm_ip4_config_set_gateway (ip4_config, gwaddr); nm_log_info (LOGD_DHCP4, " gateway %s", *s); break; } else nm_log_warn (LOGD_DHCP4, "ignoring invalid gateway '%s'", *s); } g_strfreev (routers); } } /* * RFC 2132, section 9.7 * DHCP clients use the contents of the 'server identifier' field * as the destination address for any DHCP messages unicast to * the DHCP server. * * Some ISP's provide leases from central servers that are on * different subnets that the address offered. If the host * does not configure the interface as the default route, the * dhcp server may not be reachable via unicast, and a host * specific route is needed. **/ str = g_hash_table_lookup (options, "dhcp_server_identifier"); if (str) { if (inet_pton (AF_INET, str, &tmp_addr) > 0) { nm_log_info (LOGD_DHCP4, " server identifier %s", str); if ( nm_utils_ip4_address_clear_host_address(tmp_addr, address.plen) != nm_utils_ip4_address_clear_host_address(address.address, address.plen) && !nm_ip4_config_get_direct_route_for_host (ip4_config, tmp_addr)) { /* DHCP server not on assigned subnet and the no direct route was returned. Add route */ NMPlatformIP4Route route = { 0 }; route.network = tmp_addr; route.plen = 32; /* this will be a device route if gwaddr is 0 */ route.gateway = gwaddr; route.source = NM_IP_CONFIG_SOURCE_DHCP; route.metric = priority; nm_ip4_config_add_route (ip4_config, &route); nm_log_dbg (LOGD_IP, "adding route for server identifier: %s", nm_platform_ip4_route_to_string (&route, NULL, 0)); } } else nm_log_warn (LOGD_DHCP4, "ignoring invalid server identifier '%s'", str); } str = g_hash_table_lookup (options, "dhcp_lease_time"); if (str) { address.lifetime = address.preferred = strtoul (str, NULL, 10); nm_log_info (LOGD_DHCP4, " lease time %u", address.lifetime); } address.source = NM_IP_CONFIG_SOURCE_DHCP; nm_ip4_config_add_address (ip4_config, &address); str = g_hash_table_lookup (options, "host_name"); if (str) nm_log_info (LOGD_DHCP4, " hostname '%s'", str); str = g_hash_table_lookup (options, "domain_name_servers"); if (str) { char **dns = g_strsplit (str, " ", 0); char **s; for (s = dns; *s; s++) { if (inet_pton (AF_INET, *s, &tmp_addr) > 0) { if (tmp_addr) { nm_ip4_config_add_nameserver (ip4_config, tmp_addr); nm_log_info (LOGD_DHCP4, " nameserver '%s'", *s); } } else nm_log_warn (LOGD_DHCP4, "ignoring invalid nameserver '%s'", *s); } g_strfreev (dns); } str = g_hash_table_lookup (options, "domain_name"); if (str) { char **domains = g_strsplit (str, " ", 0); char **s; for (s = domains; *s; s++) { nm_log_info (LOGD_DHCP4, " domain name '%s'", *s); nm_ip4_config_add_domain (ip4_config, *s); } g_strfreev (domains); } str = g_hash_table_lookup (options, "domain_search"); if (str) process_domain_search (str, ip4_add_domain_search, ip4_config); str = g_hash_table_lookup (options, "netbios_name_servers"); if (str) { char **nbns = g_strsplit (str, " ", 0); char **s; for (s = nbns; *s; s++) { if (inet_pton (AF_INET, *s, &tmp_addr) > 0) { if (tmp_addr) { nm_ip4_config_add_wins (ip4_config, tmp_addr); nm_log_info (LOGD_DHCP4, " wins '%s'", *s); } } else nm_log_warn (LOGD_DHCP4, "ignoring invalid WINS server '%s'", *s); } g_strfreev (nbns); } str = g_hash_table_lookup (options, "interface_mtu"); if (str) { int int_mtu; errno = 0; int_mtu = strtol (str, NULL, 10); if ((errno == EINVAL) || (errno == ERANGE)) goto error; if (int_mtu > 576) nm_ip4_config_set_mtu (ip4_config, int_mtu, NM_IP_CONFIG_SOURCE_DHCP); } str = g_hash_table_lookup (options, "nis_domain"); if (str) { nm_log_info (LOGD_DHCP4, " NIS domain '%s'", str); nm_ip4_config_set_nis_domain (ip4_config, str); } str = g_hash_table_lookup (options, "nis_servers"); if (str) { char **nis = g_strsplit (str, " ", 0); char **s; for (s = nis; *s; s++) { if (inet_pton (AF_INET, *s, &tmp_addr) > 0) { if (tmp_addr) { nm_ip4_config_add_nis_server (ip4_config, tmp_addr); nm_log_info (LOGD_DHCP4, " nis '%s'", *s); } } else nm_log_warn (LOGD_DHCP4, "ignoring invalid NIS server '%s'", *s); } g_strfreev (nis); } str = g_hash_table_lookup (options, "vendor_encapsulated_options"); nm_ip4_config_set_metered (ip4_config, str && strstr (str, "ANDROID_METERED")); return ip4_config; error: g_object_unref (ip4_config); return NULL; }
int main (int argc, char *argv[]) { GDBusProxy *proxy; GVariantBuilder builder, ip4builder, ip6builder; GVariant *ip4config, *ip6config; char *tmp; GVariant *val; int i; GError *err = NULL; GPtrArray *dns4_list, *dns6_list; GPtrArray *nbns_list; GPtrArray *dns_domains; struct in_addr temp_addr; int tapdev = -1; char **iter; int shift = 0; gboolean is_restart; gboolean has_ip4_prefix = FALSE; gboolean has_ip4_address = FALSE; gboolean has_ip6_address = FALSE; gchar *bus_name = NM_DBUS_SERVICE_OPENVPN; #if !GLIB_CHECK_VERSION (2, 35, 0) g_type_init (); #endif for (i = 1; i < argc; i++) { if (!strcmp (argv[i], "--")) { i++; break; } if (nm_streq (argv[i], "--debug")) { if (i + 2 >= argc) { g_printerr ("Missing debug arguments (requires <LEVEL> <PREFIX_TOKEN>)\n"); exit (1); } gl.log_level = _nm_utils_ascii_str_to_int64 (argv[++i], 10, 0, LOG_DEBUG, 0); gl.log_prefix_token = argv[++i]; } else if (!strcmp (argv[i], "--tun")) tapdev = 0; else if (!strcmp (argv[i], "--tap")) tapdev = 1; else if (!strcmp (argv[i], "--bus-name")) { if (++i == argc) { g_printerr ("Missing bus name argument\n"); exit (1); } if (!g_dbus_is_name (argv[i])) { g_printerr ("Invalid bus name\n"); exit (1); } bus_name = argv[i]; } else break; } shift = i - 1; if (_LOGD_enabled ()) { GString *args; args = g_string_new (NULL); for (i = 0; i < argc; i++) { if (i > 0) g_string_append_c (args, ' '); if (shift && 1 + shift == i) g_string_append (args, " "); tmp = g_strescape (argv[i], NULL); g_string_append_printf (args, "\"%s\"", tmp); g_free (tmp); } _LOGD ("command line: %s", args->str); g_string_free (args, TRUE); for (iter = environ; iter && *iter; iter++) _LOGD ("environment: %s", *iter); } /* shift the arguments to the right leaving only those provided by openvpn */ argv[shift] = argv[0]; argv += shift; argc -= shift; is_restart = argc >= 7 && !g_strcmp0 (argv[6], "restart"); proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL, bus_name, NM_VPN_DBUS_PLUGIN_PATH, NM_VPN_DBUS_PLUGIN_INTERFACE, NULL, &err); if (!proxy) { _LOGW ("Could not create a D-Bus proxy: %s", err->message); g_error_free (err); exit (1); } g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT); g_variant_builder_init (&ip4builder, G_VARIANT_TYPE_VARDICT); g_variant_builder_init (&ip6builder, G_VARIANT_TYPE_VARDICT); /* External world-visible VPN gateway */ val = trusted_remote_to_gvariant (); if (val) g_variant_builder_add (&builder, "{sv}", NM_VPN_PLUGIN_CONFIG_EXT_GATEWAY, val); else helper_failed (proxy, "VPN Gateway"); /* Internal VPN subnet gateway */ tmp = getenv ("route_vpn_gateway"); val = addr4_to_gvariant (tmp); if (val) g_variant_builder_add (&ip4builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_INT_GATEWAY, val); else { val = addr6_to_gvariant (tmp); if (val) g_variant_builder_add (&ip6builder, "{sv}", NM_VPN_PLUGIN_IP6_CONFIG_INT_GATEWAY, val); } /* VPN device */ tmp = getenv ("dev"); val = str_to_gvariant (tmp, FALSE); if (val) g_variant_builder_add (&builder, "{sv}", NM_VPN_PLUGIN_CONFIG_TUNDEV, val); else helper_failed (proxy, "Tunnel Device"); if (tapdev == -1) tapdev = strncmp (tmp, "tap", 3) == 0; /* IPv4 address */ tmp = getenv ("ifconfig_local"); if (!tmp && is_restart) tmp = argv[4]; if (tmp && strlen (tmp)) { val = addr4_to_gvariant (tmp); if (val) { has_ip4_address = TRUE; g_variant_builder_add (&ip4builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_ADDRESS, val); } else helper_failed (proxy, "IP4 Address"); } /* PTP address; for vpnc PTP address == internal IP4 address */ tmp = getenv ("ifconfig_remote"); if (!tmp && is_restart) tmp = argv[5]; val = addr4_to_gvariant (tmp); if (val) { /* Sigh. Openvpn added 'topology' stuff in 2.1 that changes the meaning * of the ifconfig bits without actually telling you what they are * supposed to mean; basically relying on specific 'ifconfig' behavior. */ if (tmp && !strncmp (tmp, "255.", 4)) { guint32 addr; /* probably a netmask, not a PTP address; topology == subnet */ addr = g_variant_get_uint32 (val); g_variant_unref (val); val = g_variant_new_uint32 (nm_utils_ip4_netmask_to_prefix (addr)); g_variant_builder_add (&ip4builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_PREFIX, val); has_ip4_prefix = TRUE; } else g_variant_builder_add (&ip4builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_PTP, val); } /* Netmask * * Either TAP or TUN modes can have an arbitrary netmask in newer versions * of openvpn, while in older versions only TAP mode would. So accept a * netmask if passed, otherwise default to /32 for TUN devices since they * are usually point-to-point. */ tmp = getenv ("ifconfig_netmask"); if (tmp && inet_pton (AF_INET, tmp, &temp_addr) > 0) { val = g_variant_new_uint32 (nm_utils_ip4_netmask_to_prefix (temp_addr.s_addr)); g_variant_builder_add (&ip4builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_PREFIX, val); } else if (!tapdev) { if (has_ip4_address && !has_ip4_prefix) { val = g_variant_new_uint32 (32); g_variant_builder_add (&ip4builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_PREFIX, val); } } else _LOGW ("No IP4 netmask/prefix (missing or invalid 'ifconfig_netmask')"); val = get_ip4_routes (); if (val) g_variant_builder_add (&ip4builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_ROUTES, val); else if (is_restart) { g_variant_builder_add (&ip4builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_PRESERVE_ROUTES, g_variant_new_boolean (TRUE)); } /* IPv6 address */ tmp = getenv ("ifconfig_ipv6_local"); if (tmp && strlen (tmp)) { val = addr6_to_gvariant (tmp); if (val) { g_variant_builder_add (&ip6builder, "{sv}", NM_VPN_PLUGIN_IP6_CONFIG_ADDRESS, val); has_ip6_address = TRUE; } else helper_failed (proxy, "IP6 Address"); } /* IPv6 remote address */ tmp = getenv ("ifconfig_ipv6_remote"); if (tmp && strlen (tmp)) { val = addr6_to_gvariant (tmp); if (val) g_variant_builder_add (&ip6builder, "{sv}", NM_VPN_PLUGIN_IP6_CONFIG_PTP, val); else helper_failed (proxy, "IP6 PTP Address"); } /* IPv6 netbits */ tmp = getenv ("ifconfig_ipv6_netbits"); if (tmp && strlen (tmp)) { long int netbits; errno = 0; netbits = strtol (tmp, NULL, 10); if (errno || netbits < 0 || netbits > 128) { _LOGW ("Ignoring invalid prefix '%s'", tmp); } else { val = g_variant_new_uint32 ((guint32) netbits); g_variant_builder_add (&ip6builder, "{sv}", NM_VPN_PLUGIN_IP6_CONFIG_PREFIX, val); } } val = get_ip6_routes (); if (val) g_variant_builder_add (&ip6builder, "{sv}", NM_VPN_PLUGIN_IP6_CONFIG_ROUTES, val); else if (is_restart) { g_variant_builder_add (&ip6builder, "{sv}", NM_VPN_PLUGIN_IP6_CONFIG_PRESERVE_ROUTES, g_variant_new_boolean (TRUE)); } /* DNS and WINS servers */ dns_domains = g_ptr_array_sized_new (3); dns4_list = g_ptr_array_new (); dns6_list = g_ptr_array_new (); nbns_list = g_ptr_array_new (); for (i = 1; i < 256; i++) { char *env_name; env_name = g_strdup_printf ("foreign_option_%d", i); tmp = getenv (env_name); g_free (env_name); if (!tmp || strlen (tmp) < 1) break; if (!g_str_has_prefix (tmp, "dhcp-option ")) continue; tmp += 12; /* strlen ("dhcp-option ") */ if (g_str_has_prefix (tmp, "DNS ")) parse_addr_list (dns4_list, dns6_list, tmp + 4); else if (g_str_has_prefix (tmp, "WINS ")) parse_addr_list (nbns_list, NULL, tmp + 5); else if (g_str_has_prefix (tmp, "DOMAIN ") && is_domain_valid (tmp + 7)) g_ptr_array_add (dns_domains, tmp + 7); } if (dns4_list->len) { val = g_variant_new_array (G_VARIANT_TYPE_UINT32, (GVariant **) dns4_list->pdata, dns4_list->len); g_variant_builder_add (&ip4builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_DNS, val); } if (has_ip6_address && dns6_list->len) { val = g_variant_new_array (G_VARIANT_TYPE ("ay"), (GVariant **) dns6_list->pdata, dns6_list->len); g_variant_builder_add (&ip6builder, "{sv}", NM_VPN_PLUGIN_IP6_CONFIG_DNS, val); } if (nbns_list->len) { val = g_variant_new_array (G_VARIANT_TYPE_UINT32, (GVariant **) nbns_list->pdata, nbns_list->len); g_variant_builder_add (&ip4builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_NBNS, val); } if (dns_domains->len) { val = g_variant_new_strv ((const gchar **) dns_domains->pdata, dns_domains->len); g_variant_builder_add (&ip4builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_DOMAINS, val); /* Domains apply to both IPv4 and IPv6 configurations */ if (has_ip6_address) { val = g_variant_new_strv ((const gchar **) dns_domains->pdata, dns_domains->len); g_variant_builder_add (&ip6builder, "{sv}", NM_VPN_PLUGIN_IP6_CONFIG_DOMAINS, val); } } g_ptr_array_unref (dns4_list); g_ptr_array_unref (dns6_list); g_ptr_array_unref (nbns_list); g_ptr_array_unref (dns_domains); /* Tunnel MTU */ tmp = getenv ("tun_mtu"); if (tmp && strlen (tmp)) { long int mtu; errno = 0; mtu = strtol (tmp, NULL, 10); if (errno || mtu < 0 || mtu > 20000) { _LOGW ("Ignoring invalid tunnel MTU '%s'", tmp); } else { val = g_variant_new_uint32 ((guint32) mtu); g_variant_builder_add (&builder, "{sv}", NM_VPN_PLUGIN_CONFIG_MTU, val); } } ip4config = g_variant_builder_end (&ip4builder); if (g_variant_n_children (ip4config)) { val = g_variant_new_boolean (TRUE); g_variant_builder_add (&builder, "{sv}", NM_VPN_PLUGIN_CONFIG_HAS_IP4, val); } else { g_variant_unref (ip4config); ip4config = NULL; } ip6config = g_variant_builder_end (&ip6builder); if (g_variant_n_children (ip6config)) { val = g_variant_new_boolean (TRUE); g_variant_builder_add (&builder, "{sv}", NM_VPN_PLUGIN_CONFIG_HAS_IP6, val); } else { g_variant_unref (ip6config); ip6config = NULL; } if (!ip4config && !ip6config) helper_failed (proxy, "IPv4 or IPv6 configuration"); /* Send the config info to nm-openvpn-service */ send_config (proxy, g_variant_builder_end (&builder), ip4config, ip6config); g_object_unref (proxy); return 0; }
static GVariant * get_ip4_routes (void) { GVariantBuilder builder; GVariant *value; char *tmp; int i, size = 0; g_variant_builder_init (&builder, G_VARIANT_TYPE ("aau")); for (i = 1; i < 256; i++) { GVariantBuilder array; char buf[BUFLEN]; struct in_addr network; struct in_addr netmask; struct in_addr gateway = { 0, }; guint32 prefix, metric = 0; snprintf (buf, BUFLEN, "route_network_%d", i); tmp = getenv (buf); if (!tmp || strlen (tmp) < 1) break; if (inet_pton (AF_INET, tmp, &network) <= 0) { _LOGW ("Ignoring invalid static route address '%s'", tmp ? tmp : "NULL"); continue; } snprintf (buf, BUFLEN, "route_netmask_%d", i); tmp = getenv (buf); if (!tmp || inet_pton (AF_INET, tmp, &netmask) <= 0) { _LOGW ("Ignoring invalid static route netmask '%s'", tmp ? tmp : "NULL"); continue; } snprintf (buf, BUFLEN, "route_gateway_%d", i); tmp = getenv (buf); /* gateway can be missing */ if (tmp && (inet_pton (AF_INET, tmp, &gateway) <= 0)) { _LOGW ("Ignoring invalid static route gateway '%s'", tmp ? tmp : "NULL"); continue; } snprintf (buf, BUFLEN, "route_metric_%d", i); tmp = getenv (buf); /* metric can be missing */ if (tmp && strlen (tmp)) { long int tmp_metric; errno = 0; tmp_metric = strtol (tmp, NULL, 10); if (errno || tmp_metric < 0 || tmp_metric > G_MAXUINT32) { _LOGW ("Ignoring invalid static route metric '%s'", tmp); continue; } metric = (guint32) tmp_metric; } g_variant_builder_init (&array, G_VARIANT_TYPE ("au")); g_variant_builder_add_value (&array, g_variant_new_uint32 (network.s_addr)); prefix = nm_utils_ip4_netmask_to_prefix (netmask.s_addr); g_variant_builder_add_value (&array, g_variant_new_uint32 (prefix)); g_variant_builder_add_value (&array, g_variant_new_uint32 (gateway.s_addr)); g_variant_builder_add_value (&array, g_variant_new_uint32 (metric)); g_variant_builder_add_value (&builder, g_variant_builder_end (&array)); size++; } value = g_variant_builder_end (&builder); if (size > 0) return value; g_variant_unref (value); return NULL; }
static NMIP4Config * lease_to_ip4_config (const char *iface, int ifindex, sd_dhcp_lease *lease, GHashTable *options, guint32 default_priority, gboolean log_lease, GError **error) { NMIP4Config *ip4_config = NULL; struct in_addr tmp_addr; const struct in_addr *addr_list; char buf[INET_ADDRSTRLEN]; const char *str; guint32 lifetime = 0, i; NMPlatformIP4Address address; GString *l; struct sd_dhcp_route *routes; guint16 mtu; int r, num; guint64 end_time; const void *data; gsize data_len; gboolean metered = FALSE; g_return_val_if_fail (lease != NULL, NULL); ip4_config = nm_ip4_config_new (ifindex); /* Address */ sd_dhcp_lease_get_address (lease, &tmp_addr); memset (&address, 0, sizeof (address)); address.address = tmp_addr.s_addr; address.peer_address = tmp_addr.s_addr; str = nm_utils_inet4_ntop (tmp_addr.s_addr, NULL); LOG_LEASE (LOGD_DHCP4, " address %s", str); add_option (options, dhcp4_requests, DHCP_OPTION_IP_ADDRESS, str); /* Prefix/netmask */ sd_dhcp_lease_get_netmask (lease, &tmp_addr); address.plen = nm_utils_ip4_netmask_to_prefix (tmp_addr.s_addr); LOG_LEASE (LOGD_DHCP4, " plen %d", address.plen); add_option (options, dhcp4_requests, DHCP_OPTION_SUBNET_MASK, nm_utils_inet4_ntop (tmp_addr.s_addr, NULL)); /* Lease time */ sd_dhcp_lease_get_lifetime (lease, &lifetime); address.timestamp = nm_utils_get_monotonic_timestamp_s (); address.lifetime = address.preferred = lifetime; end_time = (guint64) time (NULL) + lifetime; LOG_LEASE (LOGD_DHCP4, " expires in %" G_GUINT32_FORMAT " seconds", lifetime); add_option_u64 (options, dhcp4_requests, DHCP_OPTION_IP_ADDRESS_LEASE_TIME, end_time); address.source = NM_IP_CONFIG_SOURCE_DHCP; nm_ip4_config_add_address (ip4_config, &address); /* Gateway */ r = sd_dhcp_lease_get_router (lease, &tmp_addr); if (r == 0) { nm_ip4_config_set_gateway (ip4_config, tmp_addr.s_addr); str = nm_utils_inet4_ntop (tmp_addr.s_addr, NULL); LOG_LEASE (LOGD_DHCP4, " gateway %s", str); add_option (options, dhcp4_requests, DHCP_OPTION_ROUTER, str); } /* DNS Servers */ num = sd_dhcp_lease_get_dns (lease, &addr_list); if (num > 0) { l = g_string_sized_new (30); for (i = 0; i < num; i++) { if (addr_list[i].s_addr) { nm_ip4_config_add_nameserver (ip4_config, addr_list[i].s_addr); str = nm_utils_inet4_ntop (addr_list[i].s_addr, NULL); LOG_LEASE (LOGD_DHCP4, " nameserver '%s'", str); g_string_append_printf (l, "%s%s", l->len ? " " : "", str); } } if (l->len) add_option (options, dhcp4_requests, DHCP_OPTION_DOMAIN_NAME_SERVER, l->str); g_string_free (l, TRUE); } /* Domain Name */ r = sd_dhcp_lease_get_domainname (lease, &str); if (r == 0) { /* Multiple domains sometimes stuffed into the option */ char **domains = g_strsplit (str, " ", 0); char **s; for (s = domains; *s; s++) { LOG_LEASE (LOGD_DHCP4, " domain name '%s'", *s); nm_ip4_config_add_domain (ip4_config, *s); } g_strfreev (domains); add_option (options, dhcp4_requests, DHCP_OPTION_DOMAIN_NAME, str); } /* Hostname */ r = sd_dhcp_lease_get_hostname (lease, &str); if (r == 0) { LOG_LEASE (LOGD_DHCP4, " hostname '%s'", str); add_option (options, dhcp4_requests, DHCP_OPTION_HOST_NAME, str); } /* Routes */ num = sd_dhcp_lease_get_routes (lease, &routes); if (num > 0) { l = g_string_sized_new (30); for (i = 0; i < num; i++) { NMPlatformIP4Route route; const char *gw_str; memset (&route, 0, sizeof (route)); route.network = routes[i].dst_addr.s_addr; route.plen = routes[i].dst_prefixlen; route.gateway = routes[i].gw_addr.s_addr; route.source = NM_IP_CONFIG_SOURCE_DHCP; route.metric = default_priority; nm_ip4_config_add_route (ip4_config, &route); str = nm_utils_inet4_ntop (route.network, buf); gw_str = nm_utils_inet4_ntop (route.gateway, NULL); LOG_LEASE (LOGD_DHCP4, " static route %s/%d gw %s", str, route.plen, gw_str); g_string_append_printf (l, "%s%s/%d %s", l->len ? " " : "", str, route.plen, gw_str); } add_option (options, dhcp4_requests, DHCP_OPTION_RFC3442_ROUTES, l->str); g_string_free (l, TRUE); } /* MTU */ r = sd_dhcp_lease_get_mtu (lease, &mtu); if (r == 0 && mtu) { nm_ip4_config_set_mtu (ip4_config, mtu, NM_IP_CONFIG_SOURCE_DHCP); add_option_u32 (options, dhcp4_requests, DHCP_OPTION_INTERFACE_MTU, mtu); LOG_LEASE (LOGD_DHCP4, " mtu %u", mtu); } /* NTP servers */ num = sd_dhcp_lease_get_ntp (lease, &addr_list); if (num > 0) { l = g_string_sized_new (30); for (i = 0; i < num; i++) { str = nm_utils_inet4_ntop (addr_list[i].s_addr, buf); LOG_LEASE (LOGD_DHCP4, " ntp server '%s'", str); g_string_append_printf (l, "%s%s", l->len ? " " : "", str); } add_option (options, dhcp4_requests, DHCP_OPTION_NTP_SERVER, l->str); g_string_free (l, TRUE); } r = sd_dhcp_lease_get_vendor_specific (lease, &data, &data_len); if (r >= 0) metered = !!memmem (data, data_len, "ANDROID_METERED", STRLEN ("ANDROID_METERED")); nm_ip4_config_set_metered (ip4_config, metered); return ip4_config; }
/* Given a table of DHCP options from the client, convert into an IP4Config */ static NMIP4Config * ip4_options_to_config (NMDHCPClient *self) { NMDHCPClientPrivate *priv; NMIP4Config *ip4_config = NULL; struct in_addr tmp_addr; NMIP4Address *addr = NULL; char *str = NULL; guint32 gwaddr = 0, prefix = 0; g_return_val_if_fail (self != NULL, NULL); g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), NULL); priv = NM_DHCP_CLIENT_GET_PRIVATE (self); g_return_val_if_fail (priv->options != NULL, NULL); ip4_config = nm_ip4_config_new (); if (!ip4_config) { nm_log_warn (LOGD_DHCP4, "(%s): couldn't allocate memory for an IP4Config!", priv->iface); return NULL; } addr = nm_ip4_address_new (); if (!addr) { nm_log_warn (LOGD_DHCP4, "(%s): couldn't allocate memory for an IP4 Address!", priv->iface); goto error; } str = g_hash_table_lookup (priv->options, "new_ip_address"); if (str && (inet_pton (AF_INET, str, &tmp_addr) > 0)) { nm_ip4_address_set_address (addr, tmp_addr.s_addr); nm_log_info (LOGD_DHCP4, " address %s", str); } else goto error; str = g_hash_table_lookup (priv->options, "new_subnet_mask"); if (str && (inet_pton (AF_INET, str, &tmp_addr) > 0)) { prefix = nm_utils_ip4_netmask_to_prefix (tmp_addr.s_addr); nm_log_info (LOGD_DHCP4, " prefix %d (%s)", prefix, str); } else { /* Get default netmask for the IP according to appropriate class. */ prefix = nm_utils_ip4_get_default_prefix (nm_ip4_address_get_address (addr)); nm_log_info (LOGD_DHCP4, " prefix %d (default)", prefix); } nm_ip4_address_set_prefix (addr, prefix); /* Routes: if the server returns classless static routes, we MUST ignore * the 'static_routes' option. */ if (!ip4_process_classless_routes (priv->options, ip4_config, &gwaddr)) process_classful_routes (priv->options, ip4_config); if (gwaddr) { char buf[INET_ADDRSTRLEN + 1]; inet_ntop (AF_INET, &gwaddr, buf, sizeof (buf)); nm_log_info (LOGD_DHCP4, " gateway %s", buf); nm_ip4_address_set_gateway (addr, gwaddr); } else { /* If the gateway wasn't provided as a classless static route with a * subnet length of 0, try to find it using the old-style 'routers' option. */ str = g_hash_table_lookup (priv->options, "new_routers"); if (str) { char **routers = g_strsplit (str, " ", 0); char **s; for (s = routers; *s; s++) { /* FIXME: how to handle multiple routers? */ if (inet_pton (AF_INET, *s, &tmp_addr) > 0) { nm_ip4_address_set_gateway (addr, tmp_addr.s_addr); nm_log_info (LOGD_DHCP4, " gateway %s", *s); break; } else nm_log_warn (LOGD_DHCP4, "ignoring invalid gateway '%s'", *s); } g_strfreev (routers); } } nm_ip4_config_take_address (ip4_config, addr); addr = NULL; str = g_hash_table_lookup (priv->options, "new_host_name"); if (str) nm_log_info (LOGD_DHCP4, " hostname '%s'", str); str = g_hash_table_lookup (priv->options, "new_domain_name_servers"); if (str) { char **searches = g_strsplit (str, " ", 0); char **s; for (s = searches; *s; s++) { if (inet_pton (AF_INET, *s, &tmp_addr) > 0) { nm_ip4_config_add_nameserver (ip4_config, tmp_addr.s_addr); nm_log_info (LOGD_DHCP4, " nameserver '%s'", *s); } else nm_log_warn (LOGD_DHCP4, "ignoring invalid nameserver '%s'", *s); } g_strfreev (searches); } str = g_hash_table_lookup (priv->options, "new_domain_name"); if (str) { char **domains = g_strsplit (str, " ", 0); char **s; for (s = domains; *s; s++) { nm_log_info (LOGD_DHCP4, " domain name '%s'", *s); nm_ip4_config_add_domain (ip4_config, *s); } g_strfreev (domains); } str = g_hash_table_lookup (priv->options, "new_domain_search"); if (str) process_domain_search (str, ip4_add_domain_search, ip4_config); str = g_hash_table_lookup (priv->options, "new_netbios_name_servers"); if (str) { char **searches = g_strsplit (str, " ", 0); char **s; for (s = searches; *s; s++) { if (inet_pton (AF_INET, *s, &tmp_addr) > 0) { nm_ip4_config_add_wins (ip4_config, tmp_addr.s_addr); nm_log_info (LOGD_DHCP4, " wins '%s'", *s); } else nm_log_warn (LOGD_DHCP4, "ignoring invalid WINS server '%s'", *s); } g_strfreev (searches); } str = g_hash_table_lookup (priv->options, "new_interface_mtu"); if (str) { int int_mtu; errno = 0; int_mtu = strtol (str, NULL, 10); if ((errno == EINVAL) || (errno == ERANGE)) goto error; if (int_mtu > 576) nm_ip4_config_set_mtu (ip4_config, int_mtu); } str = g_hash_table_lookup (priv->options, "new_nis_domain"); if (str) { nm_log_info (LOGD_DHCP4, " NIS domain '%s'", str); nm_ip4_config_set_nis_domain (ip4_config, str); } str = g_hash_table_lookup (priv->options, "new_nis_servers"); if (str) { char **searches = g_strsplit (str, " ", 0); char **s; for (s = searches; *s; s++) { if (inet_pton (AF_INET, *s, &tmp_addr) > 0) { nm_ip4_config_add_nis_server (ip4_config, tmp_addr.s_addr); nm_log_info (LOGD_DHCP4, " nis '%s'", *s); } else nm_log_warn (LOGD_DHCP4, "ignoring invalid NIS server '%s'", *s); } g_strfreev (searches); } return ip4_config; error: if (addr) nm_ip4_address_unref (addr); g_object_unref (ip4_config); return NULL; }