You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

761 lines
25 KiB

  1. /*
  2. * DHCP module for netcfg/netcfg-dhcp.
  3. *
  4. * Licensed under the terms of the GNU General Public License
  5. */
  6. #include "netcfg.h"
  7. #include <errno.h>
  8. #include <stdlib.h>
  9. #include <unistd.h>
  10. #include <debian-installer.h>
  11. #include <stdio.h>
  12. #include <assert.h>
  13. #include <sys/param.h>
  14. #include <sys/socket.h>
  15. #include <sys/stat.h>
  16. #include <sys/utsname.h>
  17. #include <sys/wait.h>
  18. #include <arpa/inet.h>
  19. #include <net/if.h>
  20. #include <ifaddrs.h>
  21. #include <time.h>
  22. #include <netdb.h>
  23. #define DHCP_OPTION_LEN 1236 /* pump 0.8.24 defines a max option size of 57,
  24. dhcp 2.0pl5 uses 1222, dhcp3 3.0.6 uses 1236 */
  25. const char* dhclient_request_options_dhclient[] = { "subnet-mask",
  26. "broadcast-address",
  27. "time-offset",
  28. "routers",
  29. "domain-name",
  30. "domain-name-servers",
  31. "host-name",
  32. "ntp-servers", /* extra */
  33. NULL };
  34. const char* dhclient_request_options_udhcpc[] = { "subnet",
  35. "broadcast",
  36. "router",
  37. "domain",
  38. "hostname",
  39. "dns",
  40. "ntpsrv", /* extra */
  41. NULL };
  42. static int dhcp_exit_status = 1;
  43. static pid_t dhcp_pid = -1;
  44. /* Returns 1 if no default route is available */
  45. static short no_default_route (void)
  46. {
  47. #if defined(__FreeBSD_kernel__)
  48. int status4, status6;
  49. status4 = system("exec /lib/freebsd/route show default >/dev/null 2>&1");
  50. status6 = system("exec /lib/freebsd/route show -inet6 default >/dev/null 2>&1");
  51. return (WEXITSTATUS(status4) != 0) && (WEXITSTATUS(status6) != 0);
  52. #elif defined(__GNU__)
  53. FILE* pfinet = NULL;
  54. char buf[1024] = { 0 };
  55. pfinet = popen("fsysopts /servers/socket/2", "r");
  56. if (!pfinet)
  57. return 1;
  58. if (fgets (buf, 1024, pfinet) == NULL) {
  59. pclose (pfinet);
  60. return 1;
  61. }
  62. pclose (pfinet);
  63. return !strstr (buf, "--gateway=");
  64. #else
  65. FILE* iproute = NULL;
  66. char buf[256] = { 0 };
  67. /* IPv4 default route? */
  68. if ((iproute = popen("ip route", "r")) != NULL) {
  69. while (fgets (buf, 256, iproute) != NULL) {
  70. if (strncmp(buf, "default via ", 12) == 0) {
  71. pclose(iproute);
  72. return 0;
  73. }
  74. }
  75. pclose(iproute);
  76. }
  77. /* IPv6 default route? */
  78. if ((iproute = popen("ip -6 route", "r")) != NULL) {
  79. while (fgets (buf, 256, iproute) != NULL) {
  80. if (strncmp(buf, "default via ", 12) == 0) {
  81. pclose(iproute);
  82. return 0;
  83. }
  84. }
  85. pclose(iproute);
  86. }
  87. return 1;
  88. #endif
  89. }
  90. /*
  91. * Signal handler for DHCP client child
  92. *
  93. * When the child exits (either because it failed to obtain a
  94. * lease or because it succeeded and daemonized itself), this
  95. * gets the child's exit status and sets dhcp_pid to -1
  96. */
  97. static void cleanup_dhcp_client(void)
  98. {
  99. if (dhcp_pid <= 0)
  100. /* Already cleaned up */
  101. return;
  102. if (waitpid(dhcp_pid, &dhcp_exit_status, WNOHANG) != dhcp_pid)
  103. /* Wasn't us */
  104. return;
  105. if (WIFEXITED(dhcp_exit_status))
  106. dhcp_pid = -1;
  107. }
  108. /* Run through the available client process handlers we're running, and tell
  109. * them to cleanup if required.
  110. */
  111. void sigchld_handler(int sig __attribute__ ((unused)))
  112. {
  113. cleanup_dhcp_client();
  114. cleanup_rdnssd();
  115. cleanup_dhcpv6_client();
  116. }
  117. /*
  118. * This function will start whichever DHCP client is available
  119. * using the provided DHCP hostname, if supplied
  120. *
  121. * The client's PID is stored in dhcp_pid.
  122. */
  123. int start_dhcp_client (struct debconfclient *client, char* dhostname, const char *if_name)
  124. {
  125. FILE *dc = NULL;
  126. const char **ptr;
  127. char **arguments;
  128. int options_count;
  129. enum { DHCLIENT, PUMP, UDHCPC } dhcp_client;
  130. int dhcp_seconds;
  131. char dhcp_seconds_str[16];
  132. int dhostnamelen = strnlen(dhostname, MAXHOSTNAMELEN - 1);
  133. dhostname[dhostnamelen] = '\0';
  134. if (access("/sbin/dhclient", F_OK) == 0)
  135. dhcp_client = DHCLIENT;
  136. else if (access("/sbin/pump", F_OK) == 0)
  137. dhcp_client = PUMP;
  138. else if (access("/sbin/udhcpc", F_OK) == 0)
  139. dhcp_client = UDHCPC;
  140. else {
  141. debconf_input(client, "critical", "netcfg/no_dhcp_client");
  142. debconf_go(client);
  143. exit(1);
  144. }
  145. debconf_get(client, "netcfg/dhcp_timeout");
  146. dhcp_seconds = atoi(client->value);
  147. snprintf(dhcp_seconds_str, sizeof dhcp_seconds_str, "%d", dhcp_seconds-1);
  148. if ((dhcp_pid = fork()) == 0) { /* child */
  149. /* disassociate from debconf */
  150. fclose(client->out);
  151. /* get dhcp lease */
  152. switch (dhcp_client) {
  153. case PUMP:
  154. if (dhostnamelen > 0)
  155. execlp("pump", "pump", "-i", if_name, "-h", dhostname, NULL);
  156. else
  157. execlp("pump", "pump", "-i", if_name, NULL);
  158. break;
  159. case DHCLIENT:
  160. /* First, set up dhclient.conf */
  161. if ((dc = file_open(DHCLIENT_CONF, "w"))) {
  162. fprintf(dc, "send vendor-class-identifier \"d-i\";\n" );
  163. fprintf(dc, "request ");
  164. for (ptr = dhclient_request_options_dhclient; *ptr; ptr++) {
  165. fprintf(dc, "%s", *ptr);
  166. /* look ahead to see if it is the last entry */
  167. if (*(ptr + 1))
  168. fprintf(dc, ", ");
  169. else
  170. fprintf(dc, ";\n");
  171. }
  172. if (dhostnamelen > 0) {
  173. fprintf(dc, "send host-name \"%s\";\n", dhostname);
  174. }
  175. fprintf(dc, "timeout %d;\n", dhcp_seconds);
  176. fprintf(dc, "initial-interval 1;\n");
  177. fclose(dc);
  178. }
  179. execlp("dhclient", "dhclient", "-1", if_name, "-cf", DHCLIENT_CONF, NULL);
  180. break;
  181. case UDHCPC:
  182. /* figure how many options we have */
  183. options_count = 0;
  184. for (ptr = dhclient_request_options_udhcpc; *ptr; ptr++)
  185. options_count++;
  186. arguments = malloc((options_count * 2 /* -O <option> repeatedly */
  187. + 9 /* Other arguments (listed below) */
  188. + 2 /* dhostname (maybe) */
  189. + 1 /* NULL */
  190. ) * sizeof(char **));
  191. /* set the command options */
  192. options_count = 0;
  193. arguments[options_count++] = "udhcpc";
  194. arguments[options_count++] = "-i";
  195. arguments[options_count++] = (char *)if_name;
  196. arguments[options_count++] = "-V";
  197. arguments[options_count++] = "d-i";
  198. arguments[options_count++] = "-T";
  199. arguments[options_count++] = "1";
  200. arguments[options_count++] = "-t";
  201. arguments[options_count++] = dhcp_seconds_str;
  202. for (ptr = dhclient_request_options_udhcpc; *ptr; ptr++) {
  203. arguments[options_count++] = "-O";
  204. arguments[options_count++] = (char *)*ptr;
  205. }
  206. if (dhostnamelen > 0) {
  207. arguments[options_count++] = "-H";
  208. arguments[options_count++] = dhostname;
  209. }
  210. arguments[options_count] = NULL;
  211. execvp("udhcpc", arguments);
  212. free(arguments);
  213. break;
  214. }
  215. if (errno != 0)
  216. di_error("Could not exec dhcp client: %s", strerror(errno));
  217. return 1; /* should NEVER EVER get here */
  218. }
  219. else if (dhcp_pid == -1) {
  220. di_warning("DHCP fork failed; this is unlikely to end well");
  221. return 1;
  222. } else {
  223. /* dhcp_pid contains the child's PID */
  224. di_warning("Started DHCP client; PID is %i", dhcp_pid);
  225. signal(SIGCHLD, &sigchld_handler);
  226. return 0;
  227. }
  228. }
  229. static int kill_dhcp_client(void)
  230. {
  231. if (system("kill-all-dhcp")) {
  232. /* We can't do much about errors anyway, so ignore them. */
  233. }
  234. return 0;
  235. }
  236. /*
  237. * Poll the started DHCP client for netcfg/dhcp_timeout seconds (def. 15)
  238. * and return true if a lease is known to have been acquired, 0 otherwise.
  239. *
  240. * The client should be run such that it exits once a lease is acquired
  241. * (although its child continues to run as a daemon)
  242. *
  243. * This function will NOT kill the child if time runs out. This allows
  244. * the user to choose to wait longer for the lease to be acquired.
  245. */
  246. int poll_dhcp_client (struct debconfclient *client)
  247. {
  248. int seconds_slept = 0;
  249. int ret = 0;
  250. int dhcp_seconds;
  251. debconf_get(client, "netcfg/dhcp_timeout");
  252. dhcp_seconds = atoi(client->value);
  253. /* show progress bar */
  254. debconf_capb(client, "backup progresscancel");
  255. debconf_progress_start(client, 0, dhcp_seconds, "netcfg/dhcp_progress");
  256. if (debconf_progress_info(client, "netcfg/dhcp_progress_note") ==
  257. CMD_PROGRESSCANCELLED) {
  258. kill_dhcp_client();
  259. goto stop;
  260. }
  261. /* wait between 2 and dhcp_seconds seconds for a DHCP lease */
  262. while ( ((dhcp_pid > 0) || (seconds_slept < 2))
  263. && (seconds_slept < dhcp_seconds) ) {
  264. sleep(1);
  265. seconds_slept++; /* Not exact but close enough */
  266. if (debconf_progress_step(client, 1) == CMD_PROGRESSCANCELLED)
  267. goto stop;
  268. }
  269. /* Either the client exited or time ran out */
  270. /* got a lease? display a success message */
  271. if (!(dhcp_pid > 0) && (dhcp_exit_status == 0)) {
  272. ret = 1;
  273. debconf_capb(client, "backup"); /* stop displaying cancel button */
  274. if (debconf_progress_set(client, dhcp_seconds) ==
  275. CMD_PROGRESSCANCELLED)
  276. goto stop;
  277. if (debconf_progress_info(client, "netcfg/dhcp_success_note") ==
  278. CMD_PROGRESSCANCELLED)
  279. goto stop;
  280. sleep(2);
  281. }
  282. stop:
  283. /* stop progress bar */
  284. debconf_progress_stop(client);
  285. debconf_capb(client, "backup");
  286. return ret;
  287. }
  288. #define REPLY_RETRY_AUTOCONFIG 0
  289. #define REPLY_RETRY_WITH_HOSTNAME 1
  290. #define REPLY_CONFIGURE_MANUALLY 2
  291. #define REPLY_DONT_CONFIGURE 3
  292. #define REPLY_RECONFIGURE_WIFI 4
  293. #define REPLY_LOOP_BACK 5
  294. #define REPLY_CHECK_DHCP 6
  295. #define REPLY_ASK_OPTIONS 7
  296. int ask_dhcp_options (struct debconfclient *client, const char *if_name)
  297. {
  298. if (is_wireless_iface(if_name)) {
  299. debconf_metaget(client, "netcfg/internal-wifireconf", "description");
  300. debconf_subst(client, "netcfg/dhcp_options", "wifireconf", client->value);
  301. }
  302. else /* blank from last time */
  303. debconf_subst(client, "netcfg/dhcp_options", "wifireconf", "");
  304. /* critical, we don't want to enter a loop */
  305. debconf_input(client, "critical", "netcfg/dhcp_options");
  306. if (debconf_go(client) == CMD_GOBACK)
  307. return GO_BACK;
  308. debconf_get(client, "netcfg/dhcp_options");
  309. /* strcmp sucks */
  310. if (client->value[0] == 'R') { /* _R_etry ... or _R_econfigure ... */
  311. size_t len = strlen(client->value);
  312. if (client->value[len - 1] == 'e') /* ... with DHCP hostnam_e_ */
  313. return REPLY_RETRY_WITH_HOSTNAME;
  314. else if (client->value[len - 1] == 'k') /* ... wireless networ_k_ */
  315. return REPLY_RECONFIGURE_WIFI;
  316. else
  317. return REPLY_RETRY_AUTOCONFIG;
  318. }
  319. else if (client->value[0] == 'C') /* _C_onfigure ... */
  320. return REPLY_CONFIGURE_MANUALLY;
  321. else if (empty_str(client->value))
  322. return REPLY_LOOP_BACK;
  323. else
  324. return REPLY_DONT_CONFIGURE;
  325. }
  326. int ask_wifi_configuration (struct debconfclient *client, struct netcfg_interface *interface)
  327. {
  328. enum { ABORT, ESSID, SECURITY_TYPE, WEP, WPA, START, DONE } wifistate = ESSID;
  329. if (interface->wpa_supplicant_status != WPA_UNAVAIL)
  330. kill_wpa_supplicant();
  331. for (;;) {
  332. switch (wifistate) {
  333. case ESSID:
  334. if (interface->wpa_supplicant_status == WPA_UNAVAIL)
  335. wifistate = (netcfg_wireless_set_essid(client, interface) == GO_BACK) ?
  336. ABORT : WEP;
  337. else
  338. wifistate = (netcfg_wireless_set_essid(client, interface) == GO_BACK) ?
  339. ABORT : SECURITY_TYPE;
  340. break;
  341. case SECURITY_TYPE:
  342. {
  343. int ret;
  344. ret = wireless_security_type(client, interface->name);
  345. if (ret == GO_BACK)
  346. wifistate = ESSID;
  347. else if (ret == REPLY_WPA) {
  348. wifistate = WPA;
  349. interface->wifi_security = REPLY_WPA;
  350. }
  351. else {
  352. wifistate = WEP;
  353. interface->wifi_security = REPLY_WEP;
  354. }
  355. break;
  356. }
  357. case WEP:
  358. if (interface->wpa_supplicant_status == WPA_UNAVAIL)
  359. wifistate = (netcfg_wireless_set_wep(client, interface) == GO_BACK) ?
  360. ESSID : DONE;
  361. else
  362. wifistate = (netcfg_wireless_set_wep(client, interface) == GO_BACK) ?
  363. SECURITY_TYPE : DONE;
  364. break;
  365. case WPA:
  366. wifistate = (netcfg_set_passphrase(client, interface) == GO_BACK) ?
  367. SECURITY_TYPE : START;
  368. break;
  369. case START:
  370. wifistate = (wpa_supplicant_start(client, interface) == GO_BACK) ?
  371. ESSID : DONE;
  372. break;
  373. case ABORT:
  374. return REPLY_ASK_OPTIONS;
  375. break;
  376. case DONE:
  377. return REPLY_CHECK_DHCP;
  378. break;
  379. }
  380. }
  381. }
  382. /* Back in the day, this function was the main entry point for DHCP-enabled
  383. * netcfg; now it's slowly dying, doing quadruple duty handling all manner of
  384. * autoconfiguration and the associated stuffing around, much of which is
  385. * duplicated with static configuration. Eventually, this whole mess will be
  386. * merged with the static configuration code, and there will be much
  387. * rejoicing.
  388. */
  389. int netcfg_activate_dhcp (struct debconfclient *client, struct netcfg_interface *interface)
  390. {
  391. enum { AUTOCONFIG, DEFAULT_GATEWAY, NAMESERVERS,
  392. ASK_OPTIONS, DHCP_HOSTNAME, HOSTNAME, DOMAIN, HOSTNAME_SANS_NETWORK
  393. } state = AUTOCONFIG;
  394. char *if_name = interface->name;
  395. kill_dhcp_client();
  396. loop_setup();
  397. interface_up(interface->name);
  398. for (;;) {
  399. di_debug("State is now %i", state);
  400. switch (state) {
  401. case AUTOCONFIG:
  402. if (!netcfg_autoconfig(client, interface)) {
  403. /* autoconfiguration has most definitely failed */
  404. debconf_capb(client, "");
  405. debconf_input(client, "critical", "netcfg/dhcp_failed");
  406. debconf_go(client);
  407. debconf_capb(client, "backup");
  408. state = ASK_OPTIONS;
  409. } else {
  410. state = DEFAULT_GATEWAY;
  411. }
  412. break;
  413. case DEFAULT_GATEWAY:
  414. if (no_default_route()) {
  415. debconf_input(client, "critical", "netcfg/no_default_route");
  416. debconf_go(client);
  417. debconf_get(client, "netcfg/no_default_route");
  418. if (!strcmp(client->value, "false")) {
  419. state = ASK_OPTIONS;
  420. break;
  421. }
  422. }
  423. state = NAMESERVERS;
  424. break;
  425. case NAMESERVERS:
  426. /* Make sure we have NS going if the DHCP server didn't serve it up */
  427. if (nameserver_count(interface) == 0) {
  428. char *nameservers = NULL;
  429. if (netcfg_get_nameservers (client, &nameservers, NULL) == GO_BACK) {
  430. state = ASK_OPTIONS;
  431. break;
  432. }
  433. netcfg_nameservers_to_array (nameservers, interface);
  434. free(nameservers);
  435. nameservers = NULL;
  436. }
  437. /* We don't have a domain name yet, but we need to write out the
  438. * nameservers now so we can do rDNS lookups later to possibly
  439. * find out the domain.
  440. */
  441. netcfg_write_resolv(NULL, interface);
  442. state = HOSTNAME;
  443. break;
  444. case ASK_OPTIONS:
  445. /* DHCP client may still be running */
  446. switch (ask_dhcp_options (client, if_name)) {
  447. case GO_BACK:
  448. kill_dhcp_client();
  449. stop_rdnssd();
  450. interface->dhcp = 0;
  451. return RETURN_TO_MAIN;
  452. case REPLY_RETRY_WITH_HOSTNAME:
  453. state = DHCP_HOSTNAME;
  454. break;
  455. case REPLY_CONFIGURE_MANUALLY:
  456. kill_dhcp_client();
  457. stop_rdnssd();
  458. interface->dhcp = 0;
  459. return CONFIGURE_MANUALLY;
  460. case REPLY_DONT_CONFIGURE:
  461. kill_dhcp_client();
  462. stop_rdnssd();
  463. state = HOSTNAME_SANS_NETWORK;
  464. break;
  465. case REPLY_RETRY_AUTOCONFIG:
  466. state = AUTOCONFIG;
  467. break;
  468. case REPLY_RECONFIGURE_WIFI:
  469. if (ask_wifi_configuration(client, interface) == REPLY_CHECK_DHCP) {
  470. state = AUTOCONFIG;
  471. }
  472. else
  473. state = ASK_OPTIONS;
  474. break;
  475. }
  476. break;
  477. case DHCP_HOSTNAME:
  478. /* DHCP client may still be running */
  479. if (netcfg_get_hostname(client, "netcfg/dhcp_hostname", interface->dhcp_hostname, 0))
  480. state = ASK_OPTIONS;
  481. else {
  482. kill_dhcp_client();
  483. stop_rdnssd();
  484. state = AUTOCONFIG;
  485. }
  486. break;
  487. case HOSTNAME:
  488. {
  489. char buf[MAXHOSTNAMELEN + 1] = { 0 };
  490. /*
  491. * If the netcfg/hostname preseed value is set use that
  492. * otherwise default to the hostname returned via DHCP, if any,
  493. * otherwise to the requested DHCP hostname
  494. * otherwise to the hostname found in DNS for the IP address
  495. * of the interface
  496. */
  497. debconf_get(client, "netcfg/hostname");
  498. if (!empty_str(client->value)) {
  499. strncpy(buf, client->value, MAXHOSTNAMELEN);
  500. di_debug("Using preseeded hostname");
  501. preseed_hostname_from_fqdn(client, buf);
  502. }
  503. else if (gethostname(buf, sizeof(buf)) == 0
  504. && !empty_str(buf)
  505. && strcmp(buf, "(none)")
  506. ) {
  507. di_info("DHCP hostname: \"%s\"", buf);
  508. preseed_hostname_from_fqdn(client, buf);
  509. }
  510. else if (!empty_str(interface->dhcp_hostname)) {
  511. di_debug("Defaulting hostname to provided DHCP hostname");
  512. debconf_set(client, "netcfg/get_hostname", interface->dhcp_hostname);
  513. } else {
  514. di_debug("Using DNS to try and obtain default hostname");
  515. if (get_hostname_from_dns(interface, buf, sizeof(buf)))
  516. preseed_hostname_from_fqdn(client, buf);
  517. }
  518. if (netcfg_get_hostname (client, "netcfg/get_hostname", hostname, 1)) {
  519. /*
  520. * Going back to POLL wouldn't make much sense.
  521. * However, it does make sense to go to the retry
  522. * screen where the user can elect to retry DHCP with
  523. * a requested DHCP hostname, etc.
  524. */
  525. state = ASK_OPTIONS;
  526. }
  527. else
  528. state = DOMAIN;
  529. }
  530. break;
  531. case DOMAIN:
  532. if (!have_domain && netcfg_get_domain (client, domain))
  533. state = HOSTNAME;
  534. else {
  535. di_debug("Network config complete");
  536. netcfg_write_common("", hostname, domain);
  537. netcfg_write_loopback();
  538. netcfg_write_interface(interface);
  539. netcfg_write_resolv(domain, interface);
  540. #if !defined(__FreeBSD_kernel__)
  541. kill_dhcp_client();
  542. #endif
  543. stop_rdnssd();
  544. return 0;
  545. }
  546. break;
  547. case HOSTNAME_SANS_NETWORK:
  548. if (netcfg_get_hostname (client, "netcfg/get_hostname", hostname, 0))
  549. state = ASK_OPTIONS;
  550. else {
  551. netcfg_write_common("", hostname, NULL);
  552. interface->dhcp = 0;
  553. return 0;
  554. }
  555. break;
  556. }
  557. }
  558. }
  559. /* Count the number of actual entries in the nameservers array */
  560. int nameserver_count (const struct netcfg_interface *interface)
  561. {
  562. unsigned int count = 0, i;
  563. for (i = 0; i < NETCFG_NAMESERVERS_MAX; i++) {
  564. if (!empty_str(interface->nameservers[i])) count++;
  565. }
  566. return count;
  567. }
  568. /* Read the nameserver entries out of resolv.conf and stick them into
  569. * array, so we can write out a newer, shinier resolv.conf
  570. */
  571. int read_resolv_conf_nameservers(char *resolv_conf_file, struct netcfg_interface *interface)
  572. {
  573. FILE *f;
  574. unsigned int i = 0;
  575. di_debug("Reading nameservers from %s", resolv_conf_file);
  576. if ((f = fopen(resolv_conf_file, "r")) != NULL) {
  577. char buf[256];
  578. while (fgets(buf, 256, f) != NULL) {
  579. char *ptr;
  580. if (strncmp(buf, "nameserver ", strlen("nameserver ")) == 0) {
  581. rtrim(buf);
  582. ptr = buf + strlen("nameserver ");
  583. memcpy(interface->nameservers[i], ptr, NETCFG_ADDRSTRLEN-1);
  584. interface->nameservers[i][NETCFG_ADDRSTRLEN-1]='\0';
  585. di_debug("Read nameserver %s", interface->nameservers[i]);
  586. i++;
  587. if (i >= NETCFG_NAMESERVERS_MAX) {
  588. /* We can only hold so many nameservers, and we've reached
  589. * our limit. Sorry.
  590. */
  591. break;
  592. }
  593. }
  594. }
  595. fclose(f);
  596. /* Null out any remaining elements in array */
  597. for (; i < NETCFG_NAMESERVERS_MAX; i++) *(interface->nameservers[i]) = '\0';
  598. return 1;
  599. }
  600. else
  601. return 0;
  602. }
  603. /* Start a DHCP(v4) client, and see if we get a meaningful response back.
  604. *
  605. * Return 1 if the DHCP client appears to have worked, or 0 if we should
  606. * use another method to get our network configuration.
  607. */
  608. int netcfg_dhcp(struct debconfclient *client, struct netcfg_interface *interface)
  609. {
  610. FILE *d;
  611. if (start_dhcp_client(client, interface->dhcp_hostname, interface->name)) {
  612. di_warning("DHCP client failed to start. Aborting DHCP configuration.");
  613. return 0;
  614. }
  615. interface->dhcp = poll_dhcp_client(client);
  616. /*
  617. * Default to the domain name returned via DHCP, if any
  618. */
  619. if (!have_domain && (d = fopen(DOMAIN_FILE, "r")) != NULL) {
  620. di_debug("Reading domain name returned via DHCP");
  621. domain[0] = '\0';
  622. while (fgets(domain, sizeof(domain), d) != NULL) {
  623. rtrim(domain);
  624. di_debug("DHCP domain name is '%s'", domain);
  625. if (!empty_str(domain)) {
  626. have_domain = 1;
  627. }
  628. }
  629. fclose(d);
  630. unlink(DOMAIN_FILE);
  631. }
  632. /*
  633. * Record any ntp server information from DHCP for later
  634. * verification and use by clock-setup
  635. */
  636. if ((d = fopen(NTP_SERVER_FILE, "r")) != NULL) {
  637. char ntpservers[DHCP_OPTION_LEN + 1] = { 0 }, *ptr, *srv;
  638. int i;
  639. di_debug("Reading NTP servers from DHCP info");
  640. while (fgets(ntpservers, DHCP_OPTION_LEN, d) != NULL) {
  641. rtrim(ntpservers);
  642. }
  643. fclose(d);
  644. unlink(NTP_SERVER_FILE);
  645. if (!empty_str(ntpservers)) {
  646. ptr = ntpservers;
  647. for (i = 0; i < NETCFG_NTPSERVERS_MAX; i++) {
  648. srv = strtok_r(ptr, " \n\t", &ptr);
  649. if (srv) {
  650. di_debug("Read NTP server %s", srv);
  651. strncpy(interface->ntp_servers[i], srv, NETCFG_ADDRSTRLEN);
  652. } else {
  653. *(interface->ntp_servers[i]) = '\0';
  654. }
  655. }
  656. }
  657. }
  658. /* Get a copy of the DNS servers that the DHCP server got */
  659. read_resolv_conf_nameservers(RESOLV_FILE, interface);
  660. return interface->dhcp;
  661. }