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.
 
 
 
 

694 lines
23 KiB

  1. /* Static network configurator module for netcfg.
  2. *
  3. * Licensed under the terms of the GNU General Public License
  4. */
  5. #include "netcfg.h"
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <arpa/inet.h>
  9. #include <debian-installer.h>
  10. #include <assert.h>
  11. static int netcfg_get_ipaddress(struct debconfclient *client, struct netcfg_interface *interface)
  12. {
  13. int ret, ok = 0;
  14. while (!ok) {
  15. debconf_input (client, "critical", "netcfg/get_ipaddress");
  16. ret = debconf_go (client);
  17. if (ret)
  18. return ret;
  19. debconf_get(client, "netcfg/get_ipaddress");
  20. ok = netcfg_parse_cidr_address(client->value, interface);
  21. if (!ok) {
  22. debconf_capb(client);
  23. debconf_input (client, "critical", "netcfg/bad_ipaddress");
  24. debconf_capb(client, "backup");
  25. debconf_go (client);
  26. }
  27. }
  28. return 0;
  29. }
  30. static int netcfg_get_pointopoint(struct debconfclient *client, struct netcfg_interface *interface)
  31. {
  32. int ret, ok = 0;
  33. union inX_addr addr;
  34. char *ptr;
  35. while (!ok) {
  36. debconf_input(client, "critical", "netcfg/get_pointopoint");
  37. ret = debconf_go(client);
  38. if (ret)
  39. return ret;
  40. debconf_get(client, "netcfg/get_pointopoint");
  41. ptr = strtrim(client->value);
  42. if (empty_str(ptr)) { /* No P-P is ok */
  43. interface->pointopoint[0] = '\0';
  44. return 0;
  45. }
  46. ok = inet_pton (interface->address_family, ptr, &addr);
  47. if (!ok) {
  48. debconf_capb(client);
  49. debconf_input (client, "critical", "netcfg/bad_ipaddress");
  50. debconf_go (client);
  51. debconf_capb(client, "backup");
  52. }
  53. }
  54. inet_ntop(interface->address_family, &addr, interface->pointopoint, NETCFG_ADDRSTRLEN);
  55. return 0;
  56. }
  57. static int netcfg_get_netmask(struct debconfclient *client, struct netcfg_interface *interface)
  58. {
  59. int ret, ok = 0;
  60. union inX_addr addr;
  61. char *ptr;
  62. /* Preseed a vaguely sensible looking default netmask if one wasn't
  63. * provided.
  64. */
  65. debconf_get (client, "netcfg/get_netmask");
  66. ptr = strtrim(client->value);
  67. if (empty_str(ptr)) {
  68. if (interface->address_family == AF_INET) {
  69. debconf_set(client, "netcfg/get_netmask", "255.255.255.0");
  70. } else if (interface->address_family == AF_INET6) {
  71. debconf_set(client, "netcfg/get_netmask", "ffff:ffff:ffff:ffff::");
  72. }
  73. }
  74. while (!ok) {
  75. debconf_input (client, "critical", "netcfg/get_netmask");
  76. ret = debconf_go(client);
  77. if (ret)
  78. return ret;
  79. debconf_get (client, "netcfg/get_netmask");
  80. ptr = strtrim(client->value);
  81. ok = inet_pton (interface->address_family, ptr, &addr);
  82. if (!ok) {
  83. debconf_capb(client);
  84. debconf_input (client, "critical", "netcfg/bad_ipaddress");
  85. debconf_go (client);
  86. debconf_capb(client, "backup");
  87. }
  88. }
  89. inet_ptom(interface->address_family, ptr, &(interface->masklen));
  90. return 0;
  91. }
  92. static void netcfg_preseed_gateway(struct debconfclient *client,
  93. struct netcfg_interface *iface)
  94. {
  95. char ptr1[NETCFG_ADDRSTRLEN];
  96. union inX_addr gw_addr, ipaddr, mask;
  97. inet_pton(iface->address_family, iface->ipaddress, &ipaddr);
  98. inet_mton(iface->address_family, iface->masklen, &mask);
  99. /* Calculate a potentially-sensible 'default' default gateway,
  100. * based on 'the first IP in the subnet' */
  101. if (iface->address_family == AF_INET) {
  102. gw_addr.in4.s_addr = ipaddr.in4.s_addr & mask.in4.s_addr;
  103. gw_addr.in4.s_addr |= htonl(1);
  104. } else if (iface->address_family == AF_INET6) {
  105. int i;
  106. for (i = 0; i < 4; i++) {
  107. gw_addr.in6.s6_addr32[i] = ipaddr.in6.s6_addr32[i] & mask.in6.s6_addr32[i];
  108. }
  109. gw_addr.in6.s6_addr32[3] |= htonl(1);
  110. }
  111. inet_ntop (iface->address_family, &gw_addr, ptr1, NETCFG_ADDRSTRLEN);
  112. /* if your chosen static IP address happens to be what we calculated for
  113. * the 'default' gateway, obviously that isn't going to work, so stop
  114. * guessing, just chop off the last octet, and let the user fill in the blank.
  115. *
  116. * This won't *quite* work with anything shorter than a /24; such is life.
  117. */
  118. if (!strcmp(iface->ipaddress, ptr1)) {
  119. char *ptr = strrchr(ptr1, iface->address_family == AF_INET6 ? ':' : '.');
  120. assert (ptr); /* if there's no separator in ptr1 we're in deep shit */
  121. ptr[1] = '\0';
  122. }
  123. debconf_get(client, "netcfg/get_gateway");
  124. if (empty_str(client->value))
  125. debconf_set(client, "netcfg/get_gateway", ptr1);
  126. }
  127. static int netcfg_get_gateway(struct debconfclient *client, struct netcfg_interface *interface)
  128. {
  129. union inX_addr gw_addr;
  130. int ret, ok = 0;
  131. char *ptr;
  132. while (!ok) {
  133. debconf_input (client, "critical", "netcfg/get_gateway");
  134. ret = debconf_go(client);
  135. if (ret)
  136. return ret;
  137. debconf_get(client, "netcfg/get_gateway");
  138. ptr = strtrim(client->value);
  139. if (empty_str(ptr) || /* No gateway, that's fine */
  140. (strcmp(ptr, "none") == 0)) /* special case for preseeding */ {
  141. /* clear existing gateway setting */
  142. interface->gateway[0] = '\0';
  143. return 0;
  144. }
  145. ok = inet_pton (interface->address_family, ptr, &gw_addr);
  146. if (!ok) {
  147. debconf_capb(client);
  148. debconf_input (client, "critical", "netcfg/bad_ipaddress");
  149. debconf_go (client);
  150. debconf_capb(client, "backup");
  151. } else {
  152. /* Double conversion to ensure that the address is in a normalised,
  153. * more readable form, in case the user entered something weird
  154. * looking.
  155. */
  156. inet_ntop(interface->address_family, &gw_addr, interface->gateway, NETCFG_ADDRSTRLEN);
  157. }
  158. }
  159. return 0;
  160. }
  161. static int netcfg_write_etc_networks(char *network)
  162. {
  163. FILE *fp;
  164. if ((fp = file_open(NETWORKS_FILE, "w"))) {
  165. fprintf(fp, "default\t\t0.0.0.0\n");
  166. fprintf(fp, "loopback\t127.0.0.0\n");
  167. fprintf(fp, "link-local\t169.254.0.0\n");
  168. if (network) {
  169. fprintf(fp, "localnet\t%s\n", network);
  170. }
  171. fclose(fp);
  172. return 1;
  173. } else {
  174. return 0;
  175. }
  176. }
  177. static int netcfg_write_resolvconf_options(const char *domain,
  178. const struct netcfg_interface *interface
  179. )
  180. {
  181. FILE *fp;
  182. if (!(fp = file_open(INTERFACES_FILE, "a"))) {
  183. return 0;
  184. }
  185. /*
  186. * Write resolvconf options
  187. *
  188. * This is useful for users who intend to install resolvconf
  189. * after the initial installation.
  190. *
  191. * This code should be kept in sync with the code that writes
  192. * this information to the /etc/resolv.conf file. If netcfg
  193. * becomes capable of configuring multiple network interfaces
  194. * then the user should be asked for dns information on a
  195. * per-interface basis so that per-interface dns options
  196. * can be written here.
  197. */
  198. if (!empty_str(interface->nameservers[0]) || (domain && !empty_str(domain))) {
  199. unsigned int i = 0;
  200. fprintf(fp, "\t# dns-* options are implemented by the resolvconf package, if installed\n");
  201. if (!empty_str(interface->nameservers[0])) {
  202. fprintf(fp, "\tdns-nameservers");
  203. for (i = 0; i < NETCFG_NAMESERVERS_MAX; i++) {
  204. if (!empty_str(interface->nameservers[i])) {
  205. fprintf(fp, " %s", interface->nameservers[i]);
  206. }
  207. }
  208. fprintf(fp, "\n");
  209. }
  210. if (domain && !empty_str(domain))
  211. fprintf(fp, "\tdns-search %s\n", domain);
  212. }
  213. fclose(fp);
  214. return 1;
  215. }
  216. int netcfg_write_resolv (const char *domain, const struct netcfg_interface *interface)
  217. {
  218. FILE* fp = NULL;
  219. if ((fp = file_open(RESOLV_FILE, "w"))) {
  220. unsigned int i = 0;
  221. if (domain && !empty_str(domain))
  222. fprintf(fp, "search %s\n", domain);
  223. for (i = 0; i < NETCFG_NAMESERVERS_MAX; i++)
  224. if (!empty_str(interface->nameservers[i]))
  225. fprintf(fp, "nameserver %s\n", interface->nameservers[i]);
  226. fclose(fp);
  227. return 1;
  228. }
  229. else
  230. return 0;
  231. }
  232. static int netcfg_activate_static_ipv4(struct debconfclient *client,
  233. const struct netcfg_interface *interface)
  234. {
  235. int rv = 0;
  236. char buf[256];
  237. char network[INET_ADDRSTRLEN];
  238. char broadcast[INET_ADDRSTRLEN];
  239. char netmask[INET_ADDRSTRLEN];
  240. netcfg_network_address(interface, network);
  241. netcfg_broadcast_address(interface, broadcast);
  242. inet_mtop(AF_INET, interface->masklen, netmask, INET_ADDRSTRLEN);
  243. #ifdef __GNU__
  244. snprintf(buf, sizeof(buf),
  245. "settrans -fgap /servers/socket/2 /hurd/pfinet --interface=%s --address=%s",
  246. interface->name, interface->ipaddress);
  247. di_snprintfcat(buf, sizeof(buf), " --netmask=%s", netmask);
  248. if (!empty_str(interface->gateway))
  249. di_snprintfcat(buf, sizeof(buf), " --gateway=%s", interface->gateway);
  250. buf[sizeof(buf) - 1] = '\0';
  251. /* NB: unfortunately we cannot use di_exec_shell_log() here, as the active
  252. * translator would capture its pipe and make it hang forever. */
  253. rv |= di_exec_shell(buf);
  254. #elif defined(__FreeBSD_kernel__)
  255. deconfigure_network(NULL);
  256. loop_setup();
  257. interface_up(interface->name);
  258. /* Flush all previous addresses, routes */
  259. snprintf(buf, sizeof(buf), "ifconfig %s inet 0 down", interface->name);
  260. rv |= di_exec_shell_log(buf);
  261. snprintf(buf, sizeof(buf), "ifconfig %s up", interface->name);
  262. rv |= di_exec_shell_log(buf);
  263. snprintf(buf, sizeof(buf), "ifconfig %s %s",
  264. interface->name, interface->ipaddress);
  265. /* avoid using a second buffer */
  266. di_snprintfcat(buf, sizeof(buf), " netmask %s",
  267. empty_str(interface->pointopoint) ? netmask : "255.255.255.255");
  268. /* avoid using a third buffer */
  269. di_snprintfcat(buf, sizeof(buf), " broadcast %s", broadcast);
  270. di_info("executing: %s", buf);
  271. rv |= di_exec_shell_log(buf);
  272. if (!empty_str(interface->pointopoint)) {
  273. snprintf(buf, sizeof(buf), "route add %s", interface->pointopoint);
  274. /* avoid using a second buffer */
  275. di_snprintfcat(buf, sizeof(buf), "%s", interface->ipaddress);
  276. rv |= di_exec_shell_log(buf);
  277. } else if (!empty_str(interface->gateway)) {
  278. snprintf(buf, sizeof(buf), "route add default %s", interface->gateway);
  279. rv |= di_exec_shell_log(buf);
  280. }
  281. #else
  282. deconfigure_network(NULL);
  283. loop_setup();
  284. interface_up(interface->name);
  285. /* Flush all previous addresses, routes */
  286. snprintf(buf, sizeof(buf), "ip -f inet addr flush dev %s", interface->name);
  287. rv |= di_exec_shell_log(buf);
  288. snprintf(buf, sizeof(buf), "ip -f inet route flush dev %s", interface->name);
  289. rv |= di_exec_shell_log(buf);
  290. /* Add the new IP address, P-t-P peer (if necessary) and netmask */
  291. snprintf(buf, sizeof(buf), "ip addr add %s/%d ", interface->ipaddress, interface->masklen);
  292. /* avoid using a second buffer */
  293. di_snprintfcat(buf, sizeof(buf), "broadcast %s dev %s", broadcast, interface->name);
  294. if (!empty_str(interface->pointopoint))
  295. di_snprintfcat(buf, sizeof(buf), " peer %s", interface->pointopoint);
  296. di_info("executing: %s", buf);
  297. rv |= di_exec_shell_log(buf);
  298. if (!empty_str(interface->pointopoint))
  299. {
  300. snprintf(buf, sizeof(buf), "ip route add default dev %s", interface->name);
  301. rv |= di_exec_shell_log(buf);
  302. }
  303. else if (!empty_str(interface->gateway)) {
  304. snprintf(buf, sizeof(buf), "ip route add default via %s", interface->gateway);
  305. rv |= di_exec_shell_log(buf);
  306. }
  307. #endif
  308. if (rv != 0) {
  309. debconf_capb(client);
  310. debconf_input(client, "high", "netcfg/error");
  311. debconf_go(client);
  312. debconf_capb(client, "backup");
  313. return -1;
  314. }
  315. return 0;
  316. }
  317. static int netcfg_activate_static_ipv6(struct debconfclient *client,
  318. const struct netcfg_interface *interface)
  319. {
  320. int rv = 0;
  321. char buf[1024];
  322. #ifdef __GNU__
  323. snprintf(buf, sizeof(buf),
  324. "settrans -fgap /servers/socket/2 /hurd/pfinet --interface=%s -A %s/%i",
  325. interface->name, interface->ipaddress, interface->masklen);
  326. if (!empty_str(interface->gateway))
  327. di_snprintfcat(buf, sizeof(buf), " -G %s", interface->gateway);
  328. buf[sizeof(buf) - 1] = '\0';
  329. /* NB: unfortunately we cannot use di_exec_shell_log() here, as the active
  330. * translator would capture its pipe and make it hang forever. */
  331. rv |= di_exec_shell(buf);
  332. /* Apparently you need to setup the same thing on two separate sockets
  333. * if you're doing IPv6. No wonder nobody uses Hurd.
  334. */
  335. snprintf(buf, sizeof(buf),
  336. "settrans -fgap /servers/socket/26 /hurd/pfinet --interface=%s -A %s/%i",
  337. interface->name, interface->ipaddress, interface->masklen);
  338. if (!empty_str(interface->gateway))
  339. di_snprintfcat(buf, sizeof(buf), " -G %s", interface->gateway);
  340. buf[sizeof(buf) - 1] = '\0';
  341. rv |= di_exec_shell(buf);
  342. #elif defined(__FreeBSD_kernel__)
  343. deconfigure_network(NULL);
  344. loop_setup();
  345. interface_up(interface->name);
  346. /* Flush all previous addresses, routes */
  347. snprintf(buf, sizeof(buf), "ifconfig %s inet 0 down", interface->name);
  348. rv |= di_exec_shell_log(buf);
  349. snprintf(buf, sizeof(buf), "ifconfig %s up", interface->name);
  350. rv |= di_exec_shell_log(buf);
  351. snprintf(buf, sizeof(buf), "ifconfig %s inet6 %s prefixlen %i",
  352. interface->name, interface->ipaddress, interface->masklen);
  353. di_info("executing: %s", buf);
  354. rv |= di_exec_shell_log(buf);
  355. if (!empty_str(interface->gateway)) {
  356. snprintf(buf, sizeof(buf), "/lib/freebsd/route add -inet6 default %s", interface->gateway);
  357. rv |= di_exec_shell_log(buf);
  358. }
  359. #else
  360. deconfigure_network(NULL);
  361. loop_setup();
  362. interface_up(interface->name);
  363. /* Flush all previous addresses, routes */
  364. snprintf(buf, sizeof(buf), "ip -f inet6 addr flush dev %s", interface->name);
  365. rv |= di_exec_shell_log(buf);
  366. snprintf(buf, sizeof(buf), "ip -f inet6 route flush dev %s", interface->name);
  367. rv |= di_exec_shell_log(buf);
  368. /* Now down and up the interface, to get LL and SLAAC addresses back,
  369. * since flushing the addresses and routes gets rid of all that
  370. * sort of thing. */
  371. interface_down(interface->name);
  372. interface_up(interface->name);
  373. /* Add the new IP address and netmask */
  374. snprintf(buf, sizeof(buf), "ip addr add %s/%d dev %s",
  375. interface->ipaddress,
  376. interface->masklen,
  377. interface->name);
  378. di_info("executing: %s", buf);
  379. rv |= di_exec_shell_log(buf);
  380. if (!empty_str(interface->gateway)) {
  381. snprintf(buf, sizeof(buf), "ip route add default via %s", interface->gateway);
  382. rv |= di_exec_shell_log(buf);
  383. }
  384. #endif
  385. if (rv != 0) {
  386. debconf_capb(client);
  387. debconf_input(client, "high", "netcfg/error");
  388. debconf_go(client);
  389. debconf_capb(client, "backup");
  390. return -1;
  391. }
  392. return 0;
  393. }
  394. static int netcfg_activate_static(struct debconfclient *client,
  395. const struct netcfg_interface *interface)
  396. {
  397. int rv = -1;
  398. if (interface->address_family == AF_INET) {
  399. rv = netcfg_activate_static_ipv4(client, interface);
  400. } else if (interface->address_family == AF_INET6) {
  401. rv = netcfg_activate_static_ipv6(client, interface);
  402. } else {
  403. fprintf(stderr, "Can't happen: unknown address family");
  404. rv = -1;
  405. }
  406. if (rv != 0) {
  407. /* No point looking for link if the address configuration didn't
  408. * work.
  409. */
  410. return -1;
  411. }
  412. /* Wait to detect link. Don't error out if we fail, though; link detection
  413. * may not work on this NIC or something.
  414. */
  415. netcfg_detect_link(client, interface);
  416. /* Configuration appeared to go OK. Now we need to wait until the
  417. * interface is actually configured by the kernel. For IPv4, this
  418. * *should* be close to instantaneous, but for IPv6 there can be an
  419. * appreciable delay because the kernel does duplicate address detection
  420. * before making the interface active. The delay in activating the
  421. * interface can cause untold grief and misery for later parts of the
  422. * network configuration process that expect to have a working network
  423. * (rDNS preseeding of the hostname is the one that has caused this code
  424. * to be written).
  425. */
  426. if (interface->address_family == AF_INET6) {
  427. nc_v6_wait_for_complete_configuration(interface);
  428. }
  429. return 0;
  430. }
  431. int netcfg_get_static(struct debconfclient *client, struct netcfg_interface *iface)
  432. {
  433. char *nameservers = NULL;
  434. char *none;
  435. char netmask[INET_ADDRSTRLEN];
  436. enum { BACKUP, GET_HOSTNAME, GET_IPADDRESS, GET_POINTOPOINT, GET_NETMASK,
  437. GET_GATEWAY, GATEWAY_UNREACHABLE, GET_NAMESERVERS, CONFIRM,
  438. GET_DOMAIN, QUIT }
  439. state = GET_IPADDRESS;
  440. debconf_metaget(client, "netcfg/internal-none", "description");
  441. none = client->value ? strdup(client->value) : strdup("<none>");
  442. for (;;) {
  443. switch (state) {
  444. case BACKUP:
  445. return RETURN_TO_MAIN;
  446. break;
  447. case GET_IPADDRESS:
  448. if (netcfg_get_ipaddress (client, iface)) {
  449. state = BACKUP;
  450. } else {
  451. if (strncmp(iface->name, "plip", 4) == 0
  452. || strncmp(iface->name, "slip", 4) == 0
  453. || strncmp(iface->name, "ctc", 3) == 0
  454. || strncmp(iface->name, "escon", 5) == 0
  455. || strncmp(iface->name, "iucv", 4) == 0)
  456. state = GET_POINTOPOINT;
  457. else if (iface->masklen == 0) {
  458. state = GET_NETMASK;
  459. } else {
  460. state = GET_GATEWAY;
  461. }
  462. }
  463. break;
  464. case GET_POINTOPOINT:
  465. if (iface->address_family == AF_INET6) {
  466. debconf_capb(client); /* Turn off backup */
  467. debconf_input(client, "high", "netcfg/no_ipv6_pointopoint");
  468. debconf_go(client);
  469. state = GET_IPADDRESS;
  470. debconf_capb(client, "backup");
  471. break;
  472. }
  473. state = netcfg_get_pointopoint(client, iface) ?
  474. GET_IPADDRESS : GET_NAMESERVERS;
  475. break;
  476. case GET_NETMASK:
  477. state = netcfg_get_netmask(client, iface) ?
  478. GET_IPADDRESS : GET_GATEWAY;
  479. break;
  480. case GET_GATEWAY:
  481. netcfg_preseed_gateway(client, iface);
  482. if (netcfg_get_gateway(client, iface))
  483. state = GET_NETMASK;
  484. else
  485. if (strlen(iface->gateway) > 0 && !netcfg_gateway_reachable(iface))
  486. state = GATEWAY_UNREACHABLE;
  487. else
  488. state = GET_NAMESERVERS;
  489. break;
  490. case GATEWAY_UNREACHABLE:
  491. debconf_capb(client); /* Turn off backup */
  492. debconf_input(client, "high", "netcfg/gateway_unreachable");
  493. debconf_go(client);
  494. state = GET_GATEWAY;
  495. debconf_capb(client, "backup");
  496. break;
  497. case GET_NAMESERVERS:
  498. if (nameservers) free(nameservers);
  499. state = (netcfg_get_nameservers (client, &nameservers, iface->gateway)) ?
  500. GET_GATEWAY : CONFIRM;
  501. break;
  502. case GET_HOSTNAME:
  503. {
  504. char buf[MAXHOSTNAMELEN + 1] = { 0 };
  505. debconf_get(client, "netcfg/hostname");
  506. if (!empty_str(client->value))
  507. {
  508. strncpy(buf, client->value, MAXHOSTNAMELEN);
  509. preseed_hostname_from_fqdn(client, buf);
  510. }
  511. else if (get_hostname_from_dns(iface, buf, sizeof(buf)))
  512. preseed_hostname_from_fqdn(client, buf);
  513. }
  514. state = (netcfg_get_hostname(client, "netcfg/get_hostname", hostname, 1)) ?
  515. GET_NAMESERVERS : GET_DOMAIN;
  516. break;
  517. case GET_DOMAIN:
  518. if (!have_domain) {
  519. state = (netcfg_get_domain (client, domain)) ?
  520. GET_HOSTNAME : QUIT;
  521. } else {
  522. di_info("domain = %s", domain);
  523. state = QUIT;
  524. }
  525. break;
  526. case CONFIRM:
  527. inet_mtop(AF_INET, iface->masklen, netmask, INET_ADDRSTRLEN);
  528. debconf_subst(client, "netcfg/confirm_static", "interface", iface->name);
  529. debconf_subst(client, "netcfg/confirm_static", "ipaddress", empty_str(iface->ipaddress) ? none : iface->ipaddress);
  530. debconf_subst(client, "netcfg/confirm_static", "pointopoint", empty_str(iface->pointopoint) ? none : iface->pointopoint);
  531. debconf_subst(client, "netcfg/confirm_static", "netmask", empty_str(netmask) ? none : netmask);
  532. debconf_subst(client, "netcfg/confirm_static", "gateway", empty_str(iface->gateway) ? none : iface->gateway);
  533. debconf_subst(client, "netcfg/confirm_static", "nameservers",
  534. (nameservers ? nameservers : none));
  535. netcfg_nameservers_to_array(nameservers, iface);
  536. free(nameservers);
  537. nameservers = NULL;
  538. debconf_capb(client); /* Turn off backup for yes/no confirmation */
  539. debconf_input(client, "medium", "netcfg/confirm_static");
  540. debconf_go(client);
  541. debconf_get(client, "netcfg/confirm_static");
  542. if (strstr(client->value, "true")) {
  543. state = GET_HOSTNAME;
  544. netcfg_write_resolv(domain, iface);
  545. netcfg_activate_static(client, iface);
  546. }
  547. else
  548. state = GET_IPADDRESS;
  549. debconf_capb(client, "backup");
  550. break;
  551. case QUIT:
  552. {
  553. char network[INET_ADDRSTRLEN];
  554. if (iface->address_family == AF_INET) {
  555. netcfg_network_address(iface, network);
  556. netcfg_write_etc_networks(network);
  557. } else {
  558. netcfg_write_etc_networks(NULL);
  559. }
  560. netcfg_write_common(iface->ipaddress, hostname, domain);
  561. netcfg_write_loopback();
  562. netcfg_write_interface(iface);
  563. netcfg_write_resolvconf_options(domain, iface);
  564. netcfg_write_resolv(domain, iface);
  565. }
  566. return 0;
  567. break;
  568. }
  569. }
  570. return 0;
  571. }