char * nm_dhcp_dhclient_create_config (const char *interface, gboolean is_ip6, GBytes *client_id, const char *anycast_addr, const char *hostname, const char *fqdn, const char *orig_path, const char *orig_contents, GBytes **out_new_client_id) { GString *new_contents; GPtrArray *alsoreq; int i; g_return_val_if_fail (!anycast_addr || nm_utils_hwaddr_valid (anycast_addr, ETH_ALEN), NULL); new_contents = g_string_new (_("# Created by NetworkManager\n")); alsoreq = g_ptr_array_sized_new (5); if (orig_contents) { char **lines, **line; gboolean in_alsoreq = FALSE; g_string_append_printf (new_contents, _("# Merged from %s\n\n"), orig_path); lines = g_strsplit_set (orig_contents, "\n\r", 0); for (line = lines; lines && *line; line++) { char *p = *line; if (!strlen (g_strstrip (p))) continue; if (!strncmp (p, CLIENTID_TAG, strlen (CLIENTID_TAG))) { /* Override config file "dhcp-client-id" and use one from the connection */ if (client_id) continue; /* Otherwise capture and return the existing client id */ if (out_new_client_id) *out_new_client_id = read_client_id (p); } /* Override config file hostname and use one from the connection */ if (hostname || fqdn) { if (strncmp (p, HOSTNAME4_TAG, strlen (HOSTNAME4_TAG)) == 0) continue; if (strncmp (p, FQDN_TAG, strlen (FQDN_TAG)) == 0) continue; } /* Ignore 'script' since we pass our own */ if (g_str_has_prefix (p, "script ")) continue; /* Check for "also require" */ if (!strncmp (p, ALSOREQ_TAG, strlen (ALSOREQ_TAG))) { in_alsoreq = TRUE; p += strlen (ALSOREQ_TAG); } if (in_alsoreq) { char **areq, **aiter; /* Grab each 'also require' option and save for later */ areq = g_strsplit_set (p, "\t ,", -1); for (aiter = areq; aiter && *aiter; aiter++) { if (!strlen (g_strstrip (*aiter))) continue; if (*aiter[0] == ';') { /* all done */ in_alsoreq = FALSE; break; } if (!g_ascii_isalnum ((*aiter)[0])) continue; if ((*aiter)[strlen (*aiter) - 1] == ';') { /* Remove the EOL marker */ (*aiter)[strlen (*aiter) - 1] = '\0'; in_alsoreq = FALSE; } add_also_request (alsoreq, *aiter); } if (areq) g_strfreev (areq); continue; } /* Existing configuration line is OK, add it to new configuration */ g_string_append (new_contents, *line); g_string_append_c (new_contents, '\n'); } if (lines) g_strfreev (lines); } else g_string_append_c (new_contents, '\n'); if (is_ip6) { add_hostname6 (new_contents, hostname); add_also_request (alsoreq, "dhcp6.name-servers"); add_also_request (alsoreq, "dhcp6.domain-search"); add_also_request (alsoreq, "dhcp6.client-id"); } else { add_ip4_config (new_contents, client_id, hostname, fqdn); add_also_request (alsoreq, "rfc3442-classless-static-routes"); add_also_request (alsoreq, "ms-classless-static-routes"); add_also_request (alsoreq, "static-routes"); add_also_request (alsoreq, "wpad"); add_also_request (alsoreq, "ntp-servers"); } /* And add it to the dhclient configuration */ for (i = 0; i < alsoreq->len; i++) { char *t = g_ptr_array_index (alsoreq, i); g_string_append_printf (new_contents, "also request %s;\n", t); g_free (t); } g_ptr_array_free (alsoreq, TRUE); g_string_append_c (new_contents, '\n'); if (anycast_addr) { g_string_append_printf (new_contents, "interface \"%s\" {\n" " initial-interval 1; \n" " anycast-mac ethernet %s;\n" "}\n", interface, anycast_addr); } return g_string_free (new_contents, FALSE); }
char * nm_dhcp_dhclient_create_config (const char *interface, gboolean is_ip6, GBytes *client_id, const char *anycast_addr, const char *hostname, const char *fqdn, const char *orig_path, const char *orig_contents, GBytes **out_new_client_id) { GString *new_contents; GPtrArray *fqdn_opts, *reqs; int i; g_return_val_if_fail (!anycast_addr || nm_utils_hwaddr_valid (anycast_addr, ETH_ALEN), NULL); new_contents = g_string_new (_("# Created by NetworkManager\n")); fqdn_opts = g_ptr_array_sized_new (5); reqs = g_ptr_array_new_full (5, g_free); if (orig_contents) { char **lines, **line; gboolean in_alsoreq = FALSE; gboolean in_req = FALSE; g_string_append_printf (new_contents, _("# Merged from %s\n\n"), orig_path); lines = g_strsplit_set (orig_contents, "\n\r", 0); for (line = lines; lines && *line; line++) { char *p = *line; if (!strlen (g_strstrip (p))) continue; if (!strncmp (p, CLIENTID_TAG, strlen (CLIENTID_TAG))) { /* Override config file "dhcp-client-id" and use one from the connection */ if (client_id) continue; /* Otherwise capture and return the existing client id */ if (out_new_client_id) *out_new_client_id = read_client_id (p); } /* Override config file hostname and use one from the connection */ if (hostname || fqdn) { if (strncmp (p, HOSTNAME4_TAG, strlen (HOSTNAME4_TAG)) == 0) continue; if (strncmp (p, FQDN_TAG, strlen (FQDN_TAG)) == 0) continue; } /* To let user's FQDN options (except "fqdn.fqdn") override the * default ones set by NM, add them later */ if (!strncmp (p, FQDN_TAG_PREFIX, NM_STRLEN (FQDN_TAG_PREFIX))) { g_ptr_array_add (fqdn_opts, g_strdup (p + NM_STRLEN (FQDN_TAG_PREFIX))); continue; } /* Ignore 'script' since we pass our own */ if (g_str_has_prefix (p, "script ")) continue; /* Check for "request" */ if (!strncmp (p, REQ_TAG, strlen (REQ_TAG))) { in_req = TRUE; p += strlen (REQ_TAG); g_ptr_array_set_size (reqs, 0); } /* Save all request options for later use */ if (in_req) { in_req = !grab_request_options (reqs, p); continue; } /* Check for "also require" */ if (!strncmp (p, ALSOREQ_TAG, strlen (ALSOREQ_TAG))) { in_alsoreq = TRUE; p += strlen (ALSOREQ_TAG); } if (in_alsoreq) { in_alsoreq = !grab_request_options (reqs, p); continue; } /* Existing configuration line is OK, add it to new configuration */ g_string_append (new_contents, *line); g_string_append_c (new_contents, '\n'); } if (lines) g_strfreev (lines); } else g_string_append_c (new_contents, '\n'); if (is_ip6) { add_hostname6 (new_contents, hostname); add_request (reqs, "dhcp6.name-servers"); add_request (reqs, "dhcp6.domain-search"); add_request (reqs, "dhcp6.client-id"); } else { add_ip4_config (new_contents, client_id, hostname, fqdn); add_request (reqs, "rfc3442-classless-static-routes"); add_request (reqs, "ms-classless-static-routes"); add_request (reqs, "static-routes"); add_request (reqs, "wpad"); add_request (reqs, "ntp-servers"); } /* And add it to the dhclient configuration */ for (i = 0; i < reqs->len; i++) g_string_append_printf (new_contents, "also request %s;\n", (char *) reqs->pdata[i]); g_ptr_array_free (reqs, TRUE); for (i = 0; i < fqdn_opts->len; i++) { char *t = g_ptr_array_index (fqdn_opts, i); if (i == 0) g_string_append_printf (new_contents, "\n# FQDN options from %s\n", orig_path); g_string_append_printf (new_contents, FQDN_TAG_PREFIX "%s\n", t); g_free (t); } g_ptr_array_free (fqdn_opts, TRUE); g_string_append_c (new_contents, '\n'); if (anycast_addr) { g_string_append_printf (new_contents, "interface \"%s\" {\n" " initial-interval 1; \n" " anycast-mac ethernet %s;\n" "}\n", interface, anycast_addr); } return g_string_free (new_contents, FALSE); }