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.
 
 
 
 

1755 lines
48 KiB

  1. /*
  2. netcfg-common.c - Shared functions used to configure the network for
  3. the debian-installer.
  4. Copyright (C) 2000-2002 David Kimdon <dwhedon@debian.org>
  5. and others (see debian/copyright)
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  17. */
  18. #include "netcfg.h"
  19. #if defined(WIRELESS)
  20. #include <iwlib.h>
  21. #endif
  22. #include <net/if_arp.h>
  23. #include <net/ethernet.h>
  24. #include <net/if.h>
  25. #include <errno.h>
  26. #include <assert.h>
  27. #include <ctype.h>
  28. #include <sys/socket.h>
  29. #include <sys/ioctl.h>
  30. #include <string.h>
  31. #include <stdlib.h>
  32. #include <stdio.h>
  33. #include <unistd.h>
  34. #include <sys/types.h>
  35. #include <sys/stat.h>
  36. #include <fcntl.h>
  37. #include <cdebconf/debconfclient.h>
  38. #include <debian-installer.h>
  39. #include <time.h>
  40. #include <netdb.h>
  41. #include <ifaddrs.h>
  42. #ifdef __linux__
  43. #include <netpacket/packet.h>
  44. #define SYSCLASSNET "/sys/class/net/"
  45. #endif /* __linux__ */
  46. #ifdef __FreeBSD_kernel__
  47. #include <net/if_dl.h>
  48. #define LO_IF "lo0"
  49. #else
  50. #define LO_IF "lo"
  51. #endif
  52. /* network config */
  53. char hostname[MAXHOSTNAMELEN + 1];
  54. char domain[MAXHOSTNAMELEN + 1];
  55. int have_domain = 0;
  56. /* File descriptors for ioctls and such */
  57. int skfd = 0;
  58. #ifdef WIRELESS
  59. int wfd = 0;
  60. #endif
  61. /* Count the number of contiguous 1 bits in a 32-bit integer, starting from
  62. * the MSB. */
  63. static unsigned int count_bits(uint32_t num)
  64. {
  65. int count = 0;
  66. while (num & 0x80000000) {
  67. count++;
  68. num <<= 1;
  69. }
  70. return count;
  71. }
  72. /* convert a netmask string (eg 255.255.255.0 or ffff:ff::) in +src+ into
  73. * the length (24) in +dst+. Return 0 if some sort of failure, or 1 on
  74. * success.
  75. */
  76. int inet_ptom (int af, const char *src, unsigned int *dst)
  77. {
  78. union inX_addr addr;
  79. if (!empty_str(src)) {
  80. if (inet_pton (af, src, &addr) < 0) {
  81. *dst = 0;
  82. return 0;
  83. }
  84. }
  85. if (af == AF_INET) {
  86. *dst = count_bits(ntohl(addr.in4.s_addr));
  87. return 1;
  88. } else if (af == AF_INET6) {
  89. int i, count;
  90. for (i = 0, *dst = 0; i < 4; i++) {
  91. count = count_bits(htonl(addr.in6.s6_addr32[i]));
  92. *dst += count;
  93. if (count != 32) break; /* Don't go any further if the mask has finished */
  94. }
  95. return 1;
  96. } else {
  97. *dst = 0;
  98. return 0;
  99. }
  100. }
  101. /* convert a length (24) in +src+ into the string netmask (255.255.255.0) in
  102. * +dst+. The length of +dst+ is given in +len+, to ensure we don't
  103. * overrun the buffer +dst+. +dst+ should always be at least NETCFG_ADDRSTRLEN
  104. * bytes long.
  105. *
  106. * Returns the address of +dst+ on success, and NULL on failure.
  107. */
  108. const char *inet_mtop (int af, unsigned int src, char *dst, socklen_t len)
  109. {
  110. struct in_addr addr;
  111. inet_mton(AF_INET, src, &addr);
  112. return inet_ntop (af, &addr, dst, len);
  113. }
  114. /* convert a mask length (eg 24) in +src+ into the struct in_addr it corresponds
  115. * to.
  116. */
  117. void inet_mton (int af, unsigned int src, void *dst)
  118. {
  119. in_addr_t mask = 0;
  120. struct in_addr *addr;
  121. struct in6_addr *addr6;
  122. if (af == AF_INET) {
  123. addr = (struct in_addr *)dst;
  124. for(; src; src--)
  125. mask |= 1 << (32 - src);
  126. addr->s_addr = htonl(mask);
  127. } else if (af == AF_INET6) {
  128. unsigned int byte = 0;
  129. addr6 = (struct in6_addr *)dst;
  130. /* Clear out the address */
  131. memset(addr6->s6_addr, 0, 16);
  132. while (src > 7) {
  133. addr6->s6_addr[byte++] = 0xff;
  134. src -= 8;
  135. }
  136. for (; src; src--)
  137. addr6->s6_addr[byte] |= 1 << (8 - src);
  138. }
  139. }
  140. void open_sockets (void)
  141. {
  142. #ifdef WIRELESS
  143. wfd = iw_sockets_open();
  144. #endif
  145. skfd = socket (AF_INET, SOCK_DGRAM, 0);
  146. }
  147. #ifdef __linux__
  148. /* Returns non-zero if this interface has an enabled kill switch, otherwise
  149. * zero.
  150. */
  151. int check_kill_switch(const char *if_name)
  152. {
  153. char *temp, *linkbuf;
  154. const char *killname;
  155. char killstate;
  156. size_t len;
  157. int linklen, killlen;
  158. int fd = -1;
  159. int ret = 0;
  160. /* longest string we need */
  161. len = strlen(SYSCLASSNET) + strlen(if_name) + strlen("/device/rf_kill") + 1;
  162. temp = malloc(len);
  163. snprintf(temp, len, SYSCLASSNET "%s/driver", if_name);
  164. linkbuf = malloc(1024); /* probably OK ... I hate readlink() */
  165. linklen = readlink(temp, linkbuf, 1024);
  166. if (linklen < 0)
  167. goto out;
  168. if (strncmp(linkbuf + linklen - 8, "/ipw2100", 8) == 0)
  169. killname = "rf_kill";
  170. else if (strncmp(linkbuf + linklen - 8, "/ipw2200", 8) == 0)
  171. killname = "rf_kill";
  172. else
  173. goto out;
  174. snprintf(temp, len, SYSCLASSNET "%s/device/%s", if_name, killname);
  175. di_info("Checking RF kill switch: %s", temp);
  176. fd = open(temp, O_RDONLY);
  177. if (fd == -1)
  178. goto out;
  179. killlen = read(fd, &killstate, 1);
  180. if (killlen < 0) {
  181. di_error("Failed to read RF kill state: %s", strerror(errno));
  182. goto out;
  183. } else if (killlen == 0) {
  184. di_warning("RF kill state file empty");
  185. goto out;
  186. }
  187. if (killstate == '2') {
  188. di_info("RF kill switch enabled");
  189. ret = 1;
  190. }
  191. out:
  192. free(temp);
  193. free(linkbuf);
  194. if (fd != -1)
  195. close(fd);
  196. return ret;
  197. }
  198. #else /* !__linux__ */
  199. int check_kill_switch(const char *if_name)
  200. {
  201. (void)if_name;
  202. return 0;
  203. }
  204. #endif /* __linux__ */
  205. #if defined(WIRELESS)
  206. int is_raw_80211(const char *iface)
  207. {
  208. struct ifreq ifr;
  209. struct sockaddr sa;
  210. strncpy(ifr.ifr_name, iface, IFNAMSIZ);
  211. if (skfd && ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0) {
  212. di_warning("Unable to retrieve interface type.");
  213. return 0;
  214. }
  215. sa = * (struct sockaddr *) &ifr.ifr_hwaddr;
  216. switch (sa.sa_family) {
  217. case ARPHRD_IEEE80211:
  218. case ARPHRD_IEEE80211_PRISM:
  219. case ARPHRD_IEEE80211_RADIOTAP:
  220. return 1;
  221. default:
  222. return 0;
  223. }
  224. }
  225. #endif
  226. #if defined(__s390__)
  227. // Layer 3 qeth on s390(x) cannot do arping to test gateway reachability.
  228. int is_layer3_qeth(const char *iface)
  229. {
  230. const int bufsize = 1024;
  231. int retval = 0;
  232. char* path;
  233. char* buf;
  234. size_t len;
  235. ssize_t slen;
  236. char* driver;
  237. int fd;
  238. // This is sufficient for both /driver and /layer2.
  239. len = strlen(SYSCLASSNET) + strlen(iface) + strlen("/device/driver") + 1;
  240. path = malloc(len);
  241. snprintf(path, len, SYSCLASSNET "%s/device/driver", iface);
  242. // lstat() on sysfs symlinks does not provide size information.
  243. buf = malloc(bufsize);
  244. slen = readlink(path, buf, bufsize - 1);
  245. if (slen < 0) {
  246. di_error("Symlink %s cannot be resolved: %s", path, strerror(errno));
  247. goto out;
  248. }
  249. buf[slen] = '\0';
  250. driver = strrchr(buf, '/') + 1;
  251. if (strcmp(driver, "qeth") != 0) {
  252. di_info("no qeth found: %s", driver);
  253. goto out;
  254. }
  255. snprintf(path, len, SYSCLASSNET "%s/device/layer2", iface);
  256. fd = open(path, O_RDONLY);
  257. if (fd == -1) {
  258. di_error("%s cannot be opened: %s", path, strerror(errno));
  259. goto out;
  260. }
  261. slen = read(fd, buf, 1);
  262. if (slen == -1) {
  263. di_error("Read from %s failed: %s", path, strerror(errno));
  264. close(fd);
  265. goto out;
  266. }
  267. if (buf[0] == '0') {
  268. // driver == 'qeth' && layer2 == 0
  269. retval = 1;
  270. }
  271. close(fd);
  272. out:
  273. free(buf);
  274. free(path);
  275. return retval;
  276. }
  277. #else
  278. int is_layer3_qeth(const char *iface __attribute__((unused)))
  279. {
  280. return 0;
  281. }
  282. #endif
  283. int qsort_strcmp(const void *a, const void *b)
  284. {
  285. const char **ia = (const char **)a;
  286. const char **ib = (const char **)b;
  287. return strcmp(*ia, *ib);
  288. }
  289. #ifdef __GNU__
  290. #include <mach.h>
  291. #include <device/device.h>
  292. #include <hurd.h>
  293. /* On Hurd, the IP stack (pfinet) does not know the list of network interfaces
  294. * before we configure them, so we cannot use getifaddrs(). Instead we try
  295. * possible names for network interfaces and check whether they exists by
  296. * attempting to open the kernel device. */
  297. int get_all_ifs (int all __attribute__ ((unused)), char*** ptr)
  298. {
  299. static const char *const fmt[] = { "eth%d", "wl%d", NULL };
  300. mach_port_t device_master, file_master;
  301. device_t device;
  302. int err;
  303. char **list;
  304. int num, i, j;
  305. char name[3 + 3 * sizeof (int) + 1];
  306. char devname[5 + sizeof(name)];
  307. err = get_privileged_ports (0, &device_master);
  308. if (err)
  309. return 0;
  310. num = 0;
  311. list = malloc(sizeof *list);
  312. for (i = 0; fmt[i]; i++)
  313. for (j = 0;; j++) {
  314. char *thename;
  315. sprintf (name, fmt[i], j);
  316. sprintf (devname, "/dev/%s", name);
  317. err = device_open (device_master, D_READ, name, &device);
  318. if (err == 0)
  319. thename = name;
  320. else
  321. {
  322. file_master = file_name_lookup (devname, O_READ | O_WRITE, 0);
  323. if (file_master == MACH_PORT_NULL)
  324. break;
  325. err = device_open (file_master, D_READ, name, &device);
  326. mach_port_deallocate (mach_task_self (), file_master);
  327. if (err != 0)
  328. break;
  329. thename = devname;
  330. }
  331. device_close (device);
  332. mach_port_deallocate (mach_task_self (), device);
  333. list = realloc (list, (num + 2) * sizeof *list);
  334. list[num++] = strdup(thename);
  335. }
  336. list[num] = NULL;
  337. mach_port_deallocate (mach_task_self (), device_master);
  338. *ptr = list;
  339. return num;
  340. }
  341. #else
  342. int get_all_ifs (int all, char*** ptr)
  343. {
  344. struct ifaddrs *ifap, *ifa;
  345. char ibuf[512];
  346. char** list = NULL;
  347. size_t len = 0;
  348. if (getifaddrs(&ifap) == -1)
  349. return 0;
  350. for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
  351. strncpy(ibuf, ifa->ifa_name, sizeof(ibuf));
  352. if (ifa->ifa_flags & IFF_LOOPBACK) /* ignore loopback devices */
  353. continue;
  354. #if defined(__linux__)
  355. if (!strncmp(ibuf, "sit", 3)) /* ignore tunnel devices */
  356. continue;
  357. #endif
  358. #if defined(__FreeBSD_kernel__)
  359. if (!strncmp(ibuf, "pfsync", 6)) /* ignore pfsync devices */
  360. continue;
  361. if (!strncmp(ibuf, "pflog", 5)) /* ignore pflog devices */
  362. continue;
  363. if (!strncmp(ibuf, "usbus", 5)) /* ignore usbus devices */
  364. continue;
  365. #endif
  366. #if defined(WIRELESS)
  367. if (is_raw_80211(ibuf))
  368. continue;
  369. #endif
  370. if (all || ifa->ifa_flags & IFF_UP) {
  371. int found = 0;
  372. size_t i;
  373. for (i = 0 ; i < len ; i++) {
  374. if (!strcmp(ibuf, list[i])) {
  375. found = 1;
  376. }
  377. }
  378. if (!found) {
  379. list = realloc(list, sizeof(char*) * (len + 2));
  380. list[len] = strdup(ibuf);
  381. len++;
  382. }
  383. }
  384. }
  385. /* OK, now sort the list and terminate it if necessary */
  386. if (list != NULL) {
  387. qsort(list, len, sizeof(char *), qsort_strcmp);
  388. list[len] = NULL;
  389. }
  390. freeifaddrs(ifap);
  391. *ptr = list;
  392. return len;
  393. }
  394. #endif
  395. #ifdef __linux__
  396. short find_in_stab(const char *if_name)
  397. {
  398. FILE *dn = NULL;
  399. char buf[128];
  400. size_t len = strlen(if_name);
  401. if (access(STAB, F_OK) == -1)
  402. return 0;
  403. if (!(dn = popen("grep -v '^Socket' " STAB " | cut -f5", "r")))
  404. return 0;
  405. while (fgets (buf, 128, dn) != NULL) {
  406. if (!strncmp(buf, if_name, len)) {
  407. pclose(dn);
  408. return 1;
  409. }
  410. }
  411. pclose(dn);
  412. return 0;
  413. }
  414. #else /* !__linux__ */
  415. /* Stub function for platforms not supporting /var/run/stab. */
  416. short find_in_stab(const char *if_name)
  417. {
  418. (void)if_name;
  419. return 0;
  420. }
  421. #endif /* __linux__ */
  422. char *find_in_devnames(const char* iface)
  423. {
  424. FILE* dn = NULL;
  425. char buf[512], *result = NULL;
  426. size_t len = strlen(iface);
  427. if (!(dn = fopen(DEVNAMES, "r")))
  428. return NULL;
  429. while (fgets(buf, 512, dn) != NULL) {
  430. char *ptr = strchr(buf, ':'), *desc = ptr + 1;
  431. if (!ptr) {
  432. result = NULL; /* corrupt */
  433. break;
  434. }
  435. else if (!strncmp(buf, iface, len)) {
  436. result = strdup(desc);
  437. break;
  438. }
  439. }
  440. fclose(dn);
  441. if (result) {
  442. len = strlen(result);
  443. if (result[len - 1] == '\n')
  444. result[len - 1] = '\0';
  445. }
  446. return result;
  447. }
  448. char *get_ifdsc(struct debconfclient *client, const char *if_name)
  449. {
  450. char template[256], *ptr = NULL;
  451. if ((ptr = find_in_devnames(if_name)) != NULL) {
  452. debconf_metaget(client, "netcfg/internal-wireless", "description");
  453. if (is_wireless_iface(if_name)) {
  454. size_t len = strlen(ptr) + strlen(client->value) + 4;
  455. ptr = realloc(ptr, len);
  456. di_snprintfcat(ptr, len, " (%s)", client->value);
  457. }
  458. return ptr; /* already strdup'd */
  459. }
  460. if (strlen(if_name) < 100) {
  461. if (!is_wireless_iface(if_name)) {
  462. /* strip away the number from the interface (eth0 -> eth) */
  463. char *ifp = strdup(if_name), *ptr = ifp;
  464. while ((*ptr < '0' || *ptr > '9') && *ptr != '\0')
  465. ptr++;
  466. *ptr = '\0';
  467. sprintf(template, "netcfg/internal-%s", ifp);
  468. free(ifp);
  469. if (debconf_metaget(client, template, "description") ==
  470. CMD_SUCCESS && client->value != NULL) {
  471. return strdup(client->value);
  472. }
  473. } else {
  474. strcpy(template, "netcfg/internal-wifi");
  475. debconf_metaget(client, template, "description");
  476. return strdup(client->value);
  477. }
  478. }
  479. debconf_metaget(client, "netcfg/internal-unknown-iface", "description");
  480. if (client->value != NULL)
  481. return strdup(client->value);
  482. else
  483. return strdup("Unknown interface");
  484. }
  485. int iface_is_hotpluggable(const char *if_name)
  486. {
  487. FILE* f = NULL;
  488. char buf[256];
  489. size_t len = strlen(if_name);
  490. if (!(f = fopen(DEVHOTPLUG, "r"))) {
  491. di_info("No hotpluggable devices are present in the system.");
  492. return 0;
  493. }
  494. while (fgets(buf, 256, f) != NULL) {
  495. if (!strncmp(buf, if_name, len)) {
  496. di_info("Detected %s as a hotpluggable device", if_name);
  497. fclose(f);
  498. return 1;
  499. }
  500. }
  501. fclose(f);
  502. di_info("Hotpluggable devices available, but %s is not one of them", if_name);
  503. return 0;
  504. }
  505. FILE *file_open(char *path, const char *opentype)
  506. {
  507. FILE *fp;
  508. if ((fp = fopen(path, opentype)))
  509. return fp;
  510. else {
  511. fprintf(stderr, "%s\n", path);
  512. perror("fopen");
  513. return NULL;
  514. }
  515. }
  516. static char *get_bootif(void)
  517. {
  518. #ifdef __linux__
  519. #define PROC_CMDLINE "/proc/cmdline"
  520. FILE *cmdline_file;
  521. char *cmdline = NULL;
  522. size_t dummy;
  523. const char *s;
  524. char *bootif = NULL;
  525. /* Look for BOOTIF= entry in kernel command line. */
  526. cmdline_file = file_open(PROC_CMDLINE, "r");
  527. if (!cmdline_file) {
  528. di_error("Failed to open " PROC_CMDLINE ": %s", strerror(errno));
  529. return NULL;
  530. }
  531. if (getline(&cmdline, &dummy, cmdline_file) < 0) {
  532. di_error("Failed to read line from " PROC_CMDLINE ": %s",
  533. strerror(errno));
  534. fclose(cmdline_file);
  535. return NULL;
  536. }
  537. s = cmdline;
  538. while ((s = strstr(s, "BOOTIF=")) != NULL) {
  539. if (s == cmdline || s[-1] == ' ') {
  540. size_t bootif_len;
  541. char *subst;
  542. s += sizeof("BOOTIF=") - 1;
  543. bootif_len = strcspn(s, " \n");
  544. if (bootif_len != (ETH_ALEN * 3 - 1) + 3)
  545. continue;
  546. bootif = strndup(s + 3, bootif_len - 3); /* skip hardware type */
  547. for (subst = bootif; *subst; subst++)
  548. if (*subst == '-')
  549. *subst = ':';
  550. break;
  551. }
  552. s++;
  553. }
  554. free(cmdline);
  555. fclose(cmdline_file);
  556. if (!bootif)
  557. di_info("Could not find valid BOOTIF= entry in " PROC_CMDLINE);
  558. return bootif;
  559. #undef PROC_CMDLINE
  560. #else /* !__linux__ */
  561. return NULL;
  562. #endif /* __linux__ */
  563. }
  564. static unsigned char *parse_bootif(const char *bootif, int quiet)
  565. {
  566. int i;
  567. const char *s;
  568. unsigned char *bootif_addr = malloc(ETH_ALEN);
  569. /* Parse supplied address. */
  570. for (i = 0, s = bootif; i < ETH_ALEN && s; i++) {
  571. unsigned long bootif_byte;
  572. errno = 0;
  573. bootif_byte = strtol(s, (char **) &s, 16);
  574. if (errno || bootif_byte >= 256) {
  575. if (!quiet)
  576. di_error("couldn't parse link-layer address '%s'", bootif);
  577. free(bootif_addr);
  578. return NULL;
  579. }
  580. bootif_addr[i] = (unsigned char) bootif_byte;
  581. if (i < ETH_ALEN - 1 && *s++ != ':') {
  582. if (!quiet)
  583. di_error("couldn't parse link-layer address '%s'", bootif);
  584. free(bootif_addr);
  585. return NULL;
  586. }
  587. }
  588. return bootif_addr;
  589. }
  590. static char *find_bootif_iface(const char *bootif,
  591. const unsigned char *bootif_addr)
  592. {
  593. #ifdef __GNU__
  594. /* TODO: Use device_get_status(NET_ADDRESS), see pfinet/ethernet.c */
  595. (void)bootif;
  596. (void)bootif_addr;
  597. return NULL;
  598. #else
  599. struct ifaddrs *ifap, *ifa;
  600. char *ret = NULL;
  601. /* TODO: this won't work on the Hurd as getifaddrs doesn't return
  602. * unconfigured interfaces. See comment to get_all_ifs.
  603. */
  604. if (getifaddrs(&ifap) < 0) {
  605. di_error("getifaddrs failed: %s", strerror(errno));
  606. return NULL;
  607. }
  608. for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
  609. #if defined(__FreeBSD_kernel__)
  610. struct sockaddr_dl *sdl;
  611. #else
  612. struct sockaddr_ll *sll;
  613. #endif
  614. if (ifa->ifa_flags & IFF_LOOPBACK)
  615. continue;
  616. #if defined(__linux__)
  617. if (!strncmp(ifa->ifa_name, "sit", 3)) /* ignore tunnel devices */
  618. continue;
  619. #endif
  620. #if defined(WIRELESS)
  621. if (is_raw_80211(ifa->ifa_name))
  622. continue;
  623. #endif
  624. #if defined(__FreeBSD_kernel__)
  625. if (ifa->ifa_addr->sa_family != AF_LINK)
  626. continue;
  627. sdl = (struct sockaddr_dl *) ifa->ifa_addr;
  628. if (!sdl) /* no link-layer address */
  629. continue;
  630. if (sdl->sdl_alen != ETH_ALEN) /* not Ethernet */
  631. continue;
  632. if (memcmp(bootif_addr, LLADDR(sdl), ETH_ALEN) != 0)
  633. continue;
  634. #else
  635. if (ifa->ifa_addr->sa_family != AF_PACKET)
  636. continue;
  637. sll = (struct sockaddr_ll *) ifa->ifa_addr;
  638. if (!sll) /* no link-layer address */
  639. continue;
  640. if ((sll->sll_hatype != ARPHRD_ETHER &&
  641. sll->sll_hatype != ARPHRD_IEEE802) ||
  642. sll->sll_halen != ETH_ALEN) /* not Ethernet */
  643. continue;
  644. if (memcmp(bootif_addr, sll->sll_addr, ETH_ALEN) != 0)
  645. continue;
  646. #endif
  647. di_info("Found interface %s with link-layer address %s",
  648. ifa->ifa_name, bootif);
  649. ret = strdup(ifa->ifa_name);
  650. break;
  651. }
  652. freeifaddrs(ifap);
  653. if (!ret)
  654. di_error("Could not find any interface with address %s", bootif);
  655. return ret;
  656. #endif
  657. }
  658. void netcfg_die(struct debconfclient *client)
  659. {
  660. debconf_progress_stop(client);
  661. debconf_capb(client);
  662. debconf_input(client, "high", "netcfg/error");
  663. debconf_go(client);
  664. exit(1);
  665. }
  666. /**
  667. * @brief Ask which interface to configure
  668. * @param client - client
  669. * @param interface - set the +name+ field to the answer
  670. * @param numif - number of interfaces found.
  671. * @param defif - default interface from link detection.
  672. */
  673. int netcfg_get_interface(struct debconfclient *client, char **interface,
  674. int *numif, const char *defif)
  675. {
  676. char *inter = NULL, **ifs;
  677. size_t len;
  678. int ret, i, asked;
  679. int num_interfaces = 0;
  680. unsigned char *bootif_addr;
  681. char *bootif_iface = NULL;
  682. char *ptr = NULL;
  683. char *ifdsc = NULL;
  684. char *old_selection = NULL;
  685. if (*interface) {
  686. free(*interface);
  687. *interface = NULL;
  688. }
  689. if (!(ptr = malloc(128)))
  690. goto error;
  691. len = 128;
  692. *ptr = '\0';
  693. num_interfaces = get_all_ifs(1, &ifs);
  694. /* Remember old interface selection, in case it's preseeded. */
  695. debconf_get(client, "netcfg/choose_interface");
  696. old_selection = strdup(client->value);
  697. /* If netcfg/choose_interface is preseeded to a link-layer address in
  698. * the form aa:bb:cc:dd:ee:ff, or if BOOTIF is set and matches an
  699. * interface, override any provided default from link detection. */
  700. bootif_addr = parse_bootif(old_selection, 1);
  701. if (bootif_addr) {
  702. bootif_iface = find_bootif_iface(old_selection, bootif_addr);
  703. if (bootif_iface) {
  704. free(old_selection);
  705. old_selection = strdup(bootif_iface);
  706. }
  707. free(bootif_addr);
  708. } else {
  709. char *bootif = get_bootif();
  710. if (bootif) {
  711. bootif_addr = parse_bootif(bootif, 0);
  712. if (bootif_addr) {
  713. bootif_iface = find_bootif_iface(bootif, bootif_addr);
  714. free(bootif_addr);
  715. }
  716. free(bootif);
  717. }
  718. }
  719. if (bootif_iface) {
  720. /* Did we actually get back an interface we know about? */
  721. for (i = 0; i < num_interfaces; i++) {
  722. if (strcmp(ifs[i], bootif_iface) == 0) {
  723. defif = ifs[i];
  724. break;
  725. }
  726. }
  727. free (bootif_iface);
  728. }
  729. /* If no default was provided, use the first in the list of interfaces. */
  730. if (! defif && num_interfaces > 0) {
  731. defif = ifs[0];
  732. }
  733. for (i = 0; i < num_interfaces; i++) {
  734. size_t newchars;
  735. char *temp = NULL;
  736. inter = ifs[i];
  737. interface_down(inter);
  738. ifdsc = get_ifdsc(client, inter);
  739. newchars = strlen(inter) + strlen(ifdsc) + 5; /* ": , " + NUL */
  740. if (len < (strlen(ptr) + newchars)) {
  741. if (!(ptr = realloc(ptr, len + newchars + 128)))
  742. goto error;
  743. len += newchars + 128;
  744. }
  745. temp = malloc(newchars);
  746. snprintf(temp, newchars, "%s: %s", inter, ifdsc);
  747. if (num_interfaces > 1 &&
  748. ((strcmp(defif, inter) == 0) || (strcmp(defif, temp) == 0)))
  749. debconf_set(client, "netcfg/choose_interface", temp);
  750. di_snprintfcat(ptr, len, "%s, ", temp);
  751. free(temp);
  752. free(ifdsc);
  753. }
  754. if (num_interfaces == 0) {
  755. debconf_input(client, "high", "netcfg/no_interfaces");
  756. ret = debconf_go(client);
  757. free(ptr);
  758. free(old_selection);
  759. *numif = 0;
  760. return ret;
  761. }
  762. else if (num_interfaces == 1) {
  763. inter = ptr;
  764. *numif = 1;
  765. free(old_selection);
  766. }
  767. else if (num_interfaces > 1) {
  768. *numif = num_interfaces;
  769. /* remove the trailing ", ", which confuses cdebconf */
  770. ptr[strlen(ptr) - 2] = '\0';
  771. debconf_subst(client, "netcfg/choose_interface", "ifchoices", ptr);
  772. free(ptr);
  773. asked = (debconf_input(client, "critical", "netcfg/choose_interface") == CMD_SUCCESS);
  774. ret = debconf_go(client);
  775. /* If the question is not asked, honor preseeded interface name.
  776. * However, if it was preseeded to "auto", or there was no old value,
  777. * leave it set to defif. */
  778. if (!asked && strlen(old_selection) && strcmp(old_selection, "auto") != 0) {
  779. debconf_set(client, "netcfg/choose_interface", old_selection);
  780. }
  781. free(old_selection);
  782. if (ret)
  783. return ret;
  784. debconf_get(client, "netcfg/choose_interface");
  785. inter = client->value;
  786. if (!inter)
  787. netcfg_die(client);
  788. }
  789. /* grab just the interface name, not the description too */
  790. *interface = inter;
  791. /* Note that the question may be preseeded to just the interface name,
  792. * with no colon after it. Allow for this case. */
  793. ptr = strchr(inter, ':');
  794. if (ptr != NULL) {
  795. *ptr = '\0';
  796. }
  797. *interface = strdup(*interface);
  798. /* Free allocated memory */
  799. while (ifs && *ifs)
  800. free(*ifs++);
  801. return 0;
  802. error:
  803. if (ptr)
  804. free(ptr);
  805. netcfg_die(client);
  806. return RETURN_TO_MAIN; /* unreachable */
  807. }
  808. /*
  809. * Verify that the hostname conforms to RFC 1123 s2.1,
  810. * and RFC 1034 s3.5.
  811. * @return 1 on success, 0 on failure.
  812. */
  813. short valid_hostname (const char *hname)
  814. {
  815. static const char *valid_chars =
  816. "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-";
  817. size_t len;
  818. assert(hname != NULL);
  819. len = strlen(hname);
  820. if ((len < 1) ||
  821. (len > MAXHOSTNAMELEN) ||
  822. (strspn(hname, valid_chars) != len) ||
  823. (hname[len - 1] == '-') ||
  824. (hname[0] == '-')) {
  825. return 0;
  826. }
  827. else
  828. return 1;
  829. }
  830. /*
  831. * Verify that the domain name (or FQDN) conforms to RFC 1123 s2.1, and
  832. * RFC1034 s3.5.
  833. * @return 1 on success, 0 on failure.
  834. */
  835. short valid_domain (const char *dname)
  836. {
  837. static const char *valid_chars =
  838. "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-.";
  839. size_t len;
  840. assert(dname != NULL);
  841. len = strlen(dname);
  842. if ((len < 1) ||
  843. (len > MAXHOSTNAMELEN) ||
  844. (strspn(dname, valid_chars) != len) ||
  845. (dname[len - 1] == '-') ||
  846. (dname[0] == '-') ||
  847. (dname[len - 1] == '.') ||
  848. (dname[0] == '.') ||
  849. strstr(dname, "..")) {
  850. return 0;
  851. }
  852. else
  853. return 1;
  854. }
  855. /*
  856. * Write the hostname to the given string (must be capable of storing at
  857. * least MAXHOSTNAMELEN bytes.
  858. *
  859. * @return 0 on success, 30 on BACKUP being selected.
  860. */
  861. int netcfg_get_hostname(struct debconfclient *client, char *template, char *hostname, short accept_domain)
  862. {
  863. char *s, buf[1024];
  864. for(;;) {
  865. if (accept_domain)
  866. have_domain = 0;
  867. debconf_input(client, "high", template);
  868. if (debconf_go(client) == CMD_GOBACK)
  869. return GO_BACK;
  870. debconf_get(client, template);
  871. strncpy(hostname, client->value, MAXHOSTNAMELEN);
  872. if (!valid_domain(hostname)) {
  873. di_info("%s is an invalid domain", hostname);
  874. debconf_subst(client, "netcfg/invalid_hostname",
  875. "hostname", hostname);
  876. snprintf(buf, sizeof(buf), "%i", MAXHOSTNAMELEN);
  877. debconf_subst(client, "netcfg/invalid_hostname",
  878. "maxhostnamelen", buf);
  879. debconf_input(client, "high", "netcfg/invalid_hostname");
  880. debconf_go(client);
  881. debconf_set(client, template, "debian");
  882. *hostname = '\0';
  883. continue;
  884. }
  885. if (accept_domain && (s = strchr(hostname, '.'))) {
  886. di_info("Detected we have an FQDN; splitting and setting domain");
  887. if (s[1] == '\0') { /* "somehostname." <- . should be ignored */
  888. *s = '\0';
  889. } else { /* assume we have a valid domain name given */
  890. strncpy(domain, s + 1, MAXHOSTNAMELEN);
  891. debconf_set(client, "netcfg/get_domain", domain);
  892. have_domain = 1;
  893. *s = '\0';
  894. }
  895. }
  896. if (!valid_hostname(hostname)) {
  897. di_info("%s is an invalid hostname", hostname);
  898. debconf_subst(client, "netcfg/invalid_hostname",
  899. "hostname", hostname);
  900. snprintf(buf, sizeof(buf), "%i", MAXHOSTNAMELEN);
  901. debconf_subst(client, "netcfg/invalid_hostname",
  902. "maxhostnamelen", buf);
  903. debconf_input(client, "high", "netcfg/invalid_hostname");
  904. debconf_go(client);
  905. debconf_set(client, template, "debian");
  906. *hostname = '\0';
  907. } else {
  908. break;
  909. }
  910. }
  911. return 0;
  912. }
  913. /* @brief Get the domainname.
  914. * @return 0 for success, with *domain = domain, GO_BACK for 'goback',
  915. */
  916. int netcfg_get_domain(struct debconfclient *client, char domain[])
  917. {
  918. int ret;
  919. if (have_domain == 1)
  920. {
  921. debconf_get(client, "netcfg/get_domain");
  922. assert (!empty_str(client->value));
  923. strncpy(domain, client->value, MAXHOSTNAMELEN);
  924. return 0;
  925. }
  926. debconf_input (client, "high", "netcfg/get_domain");
  927. ret = debconf_go(client);
  928. if (ret)
  929. return ret;
  930. debconf_get (client, "netcfg/get_domain");
  931. *domain = '\0';
  932. if (!empty_str(client->value)) {
  933. const char *start = client->value;
  934. while (*start == '.')
  935. ++start; /* trim leading dots */
  936. strncpy(domain, start, MAXHOSTNAMELEN);
  937. }
  938. return 0;
  939. }
  940. void netcfg_write_loopback (void)
  941. {
  942. struct netcfg_interface lo;
  943. netcfg_interface_init(&lo);
  944. lo.name = LO_IF;
  945. lo.loopback = 1;
  946. netcfg_write_interface(NULL);
  947. netcfg_write_interface(&lo);
  948. }
  949. /*
  950. * ipaddress.s_addr may be 0
  951. * domain may be null
  952. * interface may be null
  953. * hostname may _not_ be null
  954. */
  955. void netcfg_write_common(const char *ipaddress, const char *hostname, const char *domain)
  956. {
  957. FILE *fp;
  958. char *domain_nodot = NULL;
  959. if (empty_str(hostname))
  960. return;
  961. if (domain) {
  962. char *end;
  963. /* strip trailing dots */
  964. domain_nodot = strdup(domain);
  965. end = domain_nodot + strlen(domain_nodot) - 1;
  966. while (end >= domain_nodot && *end == '.')
  967. *end-- = '\0';
  968. }
  969. /* Currently busybox, hostname is not available. */
  970. if (sethostname (hostname, strlen(hostname) + 1) < 0) {
  971. /* ignore errors */
  972. }
  973. if ((fp = file_open(HOSTNAME_FILE, "w"))) {
  974. fprintf(fp, "%s\n", hostname);
  975. fclose(fp);
  976. }
  977. if ((fp = file_open(HOSTS_FILE, "w"))) {
  978. fprintf(fp, "127.0.0.1\tlocalhost");
  979. if (!empty_str(ipaddress)) {
  980. if (domain_nodot && !empty_str(domain_nodot))
  981. fprintf(fp, "\n%s\t%s.%s\t%s\n", ipaddress, hostname, domain_nodot, hostname);
  982. else
  983. fprintf(fp, "\n%s\t%s\n", ipaddress, hostname);
  984. } else {
  985. #if defined(__linux__) || defined(__GNU__)
  986. if (domain_nodot && !empty_str(domain_nodot))
  987. fprintf(fp, "\n127.0.1.1\t%s.%s\t%s\n", hostname, domain_nodot, hostname);
  988. else
  989. fprintf(fp, "\n127.0.1.1\t%s\n", hostname);
  990. #else
  991. fprintf(fp, "\t%s\n", hostname);
  992. #endif
  993. }
  994. fprintf(fp, "\n" IPV6_HOSTS);
  995. fclose(fp);
  996. }
  997. free(domain_nodot);
  998. }
  999. void deconfigure_network(struct netcfg_interface *iface)
  1000. {
  1001. /* deconfiguring network interfaces */
  1002. interface_down(LO_IF);
  1003. if (iface)
  1004. interface_down(iface->name);
  1005. }
  1006. void loop_setup(void)
  1007. {
  1008. static int afpacket_notloaded = 1;
  1009. deconfigure_network(NULL);
  1010. #if defined(__FreeBSD_kernel__)
  1011. (void)afpacket_notloaded;
  1012. /* GNU/kFreeBSD currently uses the ifconfig command */
  1013. di_exec_shell_log("ifconfig "LO_IF" up");
  1014. di_exec_shell_log("ifconfig "LO_IF" 127.0.0.1 netmask 255.0.0.0");
  1015. #else
  1016. if (afpacket_notloaded)
  1017. afpacket_notloaded = di_exec_shell("modprobe af_packet"); /* should become 0 */
  1018. di_exec_shell_log("ip link set "LO_IF" up");
  1019. di_exec_shell_log("ip -f inet addr flush dev "LO_IF);
  1020. di_exec_shell_log("ip addr add 127.0.0.1/8 dev "LO_IF);
  1021. #endif
  1022. }
  1023. /* Determines the IP address of the interface (either from the static
  1024. * configuration, or by querying the interface directly if using some sort
  1025. * of autoconfiguration), then uses that address to request rDNS lookup
  1026. * using the currently configured nameservers. We return the name in
  1027. * +hostname+ if one is found, and return 1, otherwise we leave the
  1028. * +hostname+ alone and return 0.
  1029. */
  1030. int get_hostname_from_dns (const struct netcfg_interface *interface, char *hostname, const size_t max_hostname_len)
  1031. {
  1032. int err = 1;
  1033. if (!empty_str(interface->ipaddress)) {
  1034. /* Static configuration assumed */
  1035. struct sockaddr_in sin;
  1036. struct sockaddr_in6 sin6;
  1037. di_debug("Getting default hostname from rDNS lookup of static-configured address %s", interface->ipaddress);
  1038. if (interface->address_family == AF_INET) {
  1039. sin.sin_family = AF_INET;
  1040. sin.sin_port = 0;
  1041. inet_pton(AF_INET, interface->ipaddress, &sin.sin_addr);
  1042. err = getnameinfo((struct sockaddr *) &sin, sizeof(sin),
  1043. hostname, max_hostname_len, NULL, 0, NI_NAMEREQD);
  1044. } else if (interface->address_family == AF_INET6) {
  1045. sin6.sin6_family = AF_INET6;
  1046. sin6.sin6_port = 0;
  1047. inet_pton(AF_INET6, interface->ipaddress, &sin6.sin6_addr);
  1048. err = getnameinfo((struct sockaddr *) &sin6, sizeof(sin6),
  1049. hostname, max_hostname_len, NULL, 0, NI_NAMEREQD);
  1050. } else {
  1051. di_warning("Unknown address family in interface passed to seed_hostname_from_dns(): %i", interface->address_family);
  1052. return 0;
  1053. }
  1054. if (err) {
  1055. di_debug("getnameinfo() returned %i (%s)", err, err == EAI_SYSTEM ? strerror(errno) : gai_strerror(err));
  1056. }
  1057. if (err == 0) {
  1058. /* We found a name! We found a name! */
  1059. di_debug("Hostname found: %s", hostname);
  1060. }
  1061. } else {
  1062. /* Autoconfigured interface; we need to find the IP address ourselves
  1063. */
  1064. struct ifaddrs *ifa_head, *ifa;
  1065. char tmpbuf[NETCFG_ADDRSTRLEN];
  1066. if (getifaddrs(&ifa_head) == -1) {
  1067. di_warning("getifaddrs() failed: %s", strerror(errno));
  1068. return 0;
  1069. }
  1070. for (ifa = ifa_head; ifa != NULL; ifa = ifa->ifa_next) {
  1071. if (strcmp(ifa->ifa_name, interface->name) != 0) {
  1072. /* This isn't the interface you're looking for */
  1073. continue;
  1074. }
  1075. if (!ifa->ifa_addr) {
  1076. /* This isn't even a record with an address... bugger that */
  1077. continue;
  1078. }
  1079. if (ifa->ifa_addr->sa_family != AF_INET && ifa->ifa_addr->sa_family != AF_INET6) {
  1080. /* Not an IPv4 or IPv6 address... don't know what to do with it */
  1081. continue;
  1082. }
  1083. di_debug("Getting default hostname from rDNS lookup of autoconfigured address %s",
  1084. inet_ntop(ifa->ifa_addr->sa_family,
  1085. (ifa->ifa_addr->sa_family == AF_INET) ?
  1086. (void *)(&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr)
  1087. : (void *)(&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr),
  1088. tmpbuf, sizeof(tmpbuf)
  1089. )
  1090. );
  1091. err = getnameinfo(ifa->ifa_addr,
  1092. (ifa->ifa_addr->sa_family == AF_INET) ?
  1093. sizeof(struct sockaddr_in)
  1094. : sizeof(struct sockaddr_in6),
  1095. hostname, max_hostname_len, NULL, 0, NI_NAMEREQD);
  1096. if (err) {
  1097. di_debug("getnameinfo() returned %i (%s)", err, err == EAI_SYSTEM ? strerror(errno) : gai_strerror(err));
  1098. }
  1099. if (err == 0) {
  1100. /* We found a name! We found a name! */
  1101. di_debug("Hostname found: %s", hostname);
  1102. break;
  1103. }
  1104. }
  1105. }
  1106. return !err;
  1107. }
  1108. void interface_up (const char *if_name)
  1109. {
  1110. struct ifreq ifr;
  1111. strncpy(ifr.ifr_name, if_name, IFNAMSIZ);
  1112. if (skfd && ioctl(skfd, SIOCGIFFLAGS, &ifr) >= 0) {
  1113. di_info("Activating interface %s", if_name);
  1114. strncpy(ifr.ifr_name, if_name, IFNAMSIZ);
  1115. ifr.ifr_flags |= (IFF_UP | IFF_RUNNING);
  1116. ioctl(skfd, SIOCSIFFLAGS, &ifr);
  1117. } else {
  1118. di_info("Getting flags for interface %s failed, not activating interface.", if_name);
  1119. }
  1120. }
  1121. void interface_down (const char *if_name)
  1122. {
  1123. struct ifreq ifr;
  1124. strncpy(ifr.ifr_name, if_name, IFNAMSIZ);
  1125. if (skfd && ioctl(skfd, SIOCGIFFLAGS, &ifr) >= 0) {
  1126. di_info("Taking down interface %s", if_name);
  1127. strncpy(ifr.ifr_name, if_name, IFNAMSIZ);
  1128. ifr.ifr_flags &= ~IFF_UP;
  1129. ioctl(skfd, SIOCSIFFLAGS, &ifr);
  1130. } else {
  1131. di_info("Getting flags for interface %s failed, not taking down interface.", if_name);
  1132. }
  1133. }
  1134. void parse_args (int argc, char ** argv)
  1135. {
  1136. if (argc == 2) {
  1137. if (!strcmp(basename(argv[0]), "ptom")) {
  1138. unsigned int ret;
  1139. if (inet_ptom(AF_INET, argv[1], &ret) > 0) {
  1140. printf("%d\n", ret);
  1141. exit(EXIT_SUCCESS);
  1142. }
  1143. }
  1144. if (!strcmp(argv[1], "write_loopback")) {
  1145. netcfg_write_loopback();
  1146. exit(EXIT_SUCCESS);
  1147. }
  1148. exit(EXIT_FAILURE);
  1149. }
  1150. }
  1151. void reap_old_files (void)
  1152. {
  1153. static char* remove[] =
  1154. { INTERFACES_FILE, HOSTS_FILE, HOSTNAME_FILE, NETWORKS_FILE,
  1155. RESOLV_FILE, DHCLIENT_CONF, DOMAIN_FILE, 0 };
  1156. char **ptr = remove;
  1157. while (*ptr)
  1158. unlink(*ptr++);
  1159. }
  1160. /* Convert a space-separated list of nameservers in a single string (as might
  1161. * be entered into, say, debconf), and store them in the interface.
  1162. */
  1163. void netcfg_nameservers_to_array(const char *nameservers, struct netcfg_interface *interface)
  1164. {
  1165. char *save, *ptr, *ns;
  1166. unsigned int i;
  1167. union inX_addr addr;
  1168. if (nameservers) {
  1169. save = ptr = strdup(nameservers);
  1170. for (i = 0; i < NETCFG_NAMESERVERS_MAX; i++) {
  1171. int af;
  1172. ns = strtok_r(ptr, " \n\t", &ptr);
  1173. if (ns) {
  1174. /* The double conversion here is to both validate that we've
  1175. * been given an IP address, and to ensure that the address
  1176. * is in it's canonical form and will fit in the size of the
  1177. * array element provided.
  1178. */
  1179. if (inet_pton (AF_INET, ns, &addr)) {
  1180. /* v4! */
  1181. af = AF_INET;
  1182. } else {
  1183. /* v6? */
  1184. if (inet_pton (AF_INET6, ns, &addr)) {
  1185. af = AF_INET6;
  1186. } else {
  1187. af = -1;
  1188. fprintf(stderr, "Failed to parse %s as an IP address", ns);
  1189. }
  1190. }
  1191. if (af != -1) {
  1192. inet_ntop (af, &addr, interface->nameservers[i], NETCFG_ADDRSTRLEN);
  1193. } else {
  1194. /* Dud in this slot; empty it */
  1195. *(interface->nameservers[i]) = '\0';
  1196. }
  1197. } else
  1198. *(interface->nameservers[i]) = '\0';
  1199. }
  1200. free(save);
  1201. } else {
  1202. /* Empty out all the nameserver strings */
  1203. for (i = 0; i < NETCFG_NAMESERVERS_MAX; i++) *(interface->nameservers[i]) = '\0';
  1204. }
  1205. }
  1206. int netcfg_get_nameservers (struct debconfclient *client, char **nameservers, char *default_nameservers)
  1207. {
  1208. char *ptr;
  1209. int ret;
  1210. debconf_get(client,"netcfg/get_nameservers");
  1211. if (*nameservers)
  1212. ptr = *nameservers;
  1213. else if (strlen(client->value))
  1214. ptr = client->value;
  1215. else if (default_nameservers)
  1216. ptr = default_nameservers;
  1217. else
  1218. ptr = "";
  1219. debconf_set(client, "netcfg/get_nameservers", ptr);
  1220. debconf_input(client, "critical", "netcfg/get_nameservers");
  1221. ret = debconf_go(client);
  1222. if (ret)
  1223. return ret;
  1224. debconf_get(client, "netcfg/get_nameservers");
  1225. ptr = client->value;
  1226. if (*nameservers)
  1227. free(*nameservers);
  1228. *nameservers = NULL;
  1229. if (ptr)
  1230. *nameservers = strdup(ptr);
  1231. return 0;
  1232. }
  1233. void netcfg_update_entropy (void)
  1234. {
  1235. #ifdef __linux__
  1236. di_exec_shell("ip addr show >/dev/random");
  1237. #endif
  1238. }
  1239. /* Attempt to find out whether we've got link on an interface. Don't try to
  1240. * bring the interface up or down, we leave that to the caller. Use a
  1241. * progress bar so the user knows what's going on. Return true if we got
  1242. * link, and false otherwise.
  1243. */
  1244. int netcfg_detect_link(struct debconfclient *client, const struct netcfg_interface *interface)
  1245. {
  1246. char arping[256];
  1247. int count, rv = 0;
  1248. int link_waits = 12; /* default for netcfg/link_wait_timeout times 4 */
  1249. int gw_tries = NETCFG_GATEWAY_REACHABILITY_TRIES;
  1250. const char *if_name = interface->name;
  1251. const char *gateway = interface->gateway;
  1252. if (!empty_str(gateway))
  1253. sprintf(arping, "arping -c 1 -w 1 -f -I %s %s", if_name, gateway);
  1254. /* Ask for link detection timeout. */
  1255. int ok = 0;
  1256. debconf_capb(client, "");
  1257. while (!ok) {
  1258. debconf_input(client, "low", "netcfg/link_wait_timeout");
  1259. debconf_go(client);
  1260. debconf_get(client, "netcfg/link_wait_timeout");
  1261. char *ptr, *end_ptr;
  1262. ptr = client->value;
  1263. if (!empty_str(ptr)) {
  1264. link_waits = strtol(ptr, &end_ptr, 10);
  1265. /* The input contains a single positive integer. */
  1266. if (*end_ptr == '\0' && link_waits > 0) {
  1267. ok = 1;
  1268. link_waits *= 4;
  1269. }
  1270. }
  1271. if (!ok) {
  1272. if (!empty_str(ptr)) {
  1273. di_info("The value %s provided is not valid", ptr);
  1274. }
  1275. else {
  1276. di_info("No value provided");
  1277. }
  1278. debconf_input (client, "critical", "netcfg/bad_link_wait_timeout");
  1279. debconf_go (client);
  1280. debconf_set(client, "netcfg/link_wait_timeout", "3");
  1281. }
  1282. }
  1283. di_info("Waiting time set to %d", link_waits / 4);
  1284. debconf_capb(client, "progresscancel");
  1285. debconf_subst(client, "netcfg/link_detect_progress", "interface", if_name);
  1286. debconf_progress_start(client, 0, link_waits, "netcfg/link_detect_progress");
  1287. for (count = 0; count < link_waits; count++) {
  1288. usleep(250000);
  1289. if (debconf_progress_set(client, count) == CMD_PROGRESSCANCELLED) {
  1290. /* User cancelled on us... bugger */
  1291. rv = 0;
  1292. di_info("Detecting link on %s was cancelled", if_name);
  1293. break;
  1294. }
  1295. if (ethtool_lite(if_name) == 1) /* ethtool-lite's CONNECTED */ {
  1296. di_info("Found link on %s", if_name);
  1297. if (!empty_str(gateway) && !is_wireless_iface(if_name) && !is_layer3_qeth(if_name)) {
  1298. for (count = 0; count < gw_tries; count++) {
  1299. if (di_exec_shell_log(arping) == 0)
  1300. break;
  1301. }
  1302. di_info("Gateway reachable on %s", if_name);
  1303. }
  1304. rv = 1;
  1305. break;
  1306. }
  1307. }
  1308. if (count == link_waits) {
  1309. di_info("Reached timeout for link detection on %s", if_name);
  1310. }
  1311. debconf_progress_stop(client);
  1312. debconf_capb(client, "backup");
  1313. return rv;
  1314. }
  1315. void netcfg_interface_init(struct netcfg_interface *iface)
  1316. {
  1317. memset(iface, 0, sizeof(*iface));
  1318. iface->name = NULL;
  1319. iface->dhcp = -1;
  1320. iface->dhcpv6 = -1;
  1321. iface->address_family = -1; /* I hope nobody uses -1 for AF_INET */
  1322. iface->slaac = -1;
  1323. iface->v6_stateful_config = -1;
  1324. iface->v6_stateless_config = -1;
  1325. iface->loopback = -1;
  1326. iface->mode = MANAGED;
  1327. }
  1328. /* Parse an IP address (v4 or v6), with optional CIDR netmask, into
  1329. * +interface+. Return 1 if all went well, and return 0 if something
  1330. * went wrong (the "IP address" wasn't, for example). In the event
  1331. * something went wrong, +interface+ is guaranteed to remain
  1332. * unchanged.
  1333. */
  1334. int netcfg_parse_cidr_address(const char *address, struct netcfg_interface *interface)
  1335. {
  1336. struct in_addr addr;
  1337. struct in6_addr addr6;
  1338. int ok;
  1339. char *maskptr, *addrstr, addrbuf[NETCFG_ADDRSTRLEN];
  1340. int i;
  1341. strncpy(addrbuf, address, NETCFG_ADDRSTRLEN);
  1342. addrstr = strtrim(addrbuf);
  1343. if ((maskptr = strchr(addrstr, '/'))) {
  1344. /* Houston, we have a netmask; split it into bits */
  1345. *maskptr = '\0';
  1346. maskptr++;
  1347. /* Verify that the mask is OK */
  1348. for (i = 0; maskptr[i]; i++) {
  1349. if (!isdigit(maskptr[i])) {
  1350. /* That's not good; bomb out early */
  1351. return 0;
  1352. }
  1353. }
  1354. }
  1355. ok = inet_pton (AF_INET, addrstr, &addr);
  1356. if (ok) {
  1357. interface->address_family = AF_INET;
  1358. inet_ntop(AF_INET, &addr, interface->ipaddress, INET_ADDRSTRLEN);
  1359. } else {
  1360. /* Potential IPv6 address */
  1361. ok = inet_pton (AF_INET6, addrstr, &addr6);
  1362. if (ok) {
  1363. interface->address_family = AF_INET6;
  1364. inet_ntop(AF_INET6, &addr6, interface->ipaddress, INET6_ADDRSTRLEN);
  1365. }
  1366. }
  1367. if (ok && maskptr) {
  1368. interface->masklen = atoi(maskptr);
  1369. } else {
  1370. interface->masklen = 0;
  1371. }
  1372. return ok;
  1373. }
  1374. void netcfg_network_address(const struct netcfg_interface *interface,
  1375. char *network)
  1376. {
  1377. union inX_addr ipaddr, mask, net;
  1378. inet_pton(interface->address_family, interface->ipaddress, &ipaddr);
  1379. inet_mton(interface->address_family, interface->masklen, &mask);
  1380. if (interface->address_family == AF_INET) {
  1381. net.in4.s_addr = ipaddr.in4.s_addr & mask.in4.s_addr;
  1382. } else if (interface->address_family == AF_INET6) {
  1383. int i;
  1384. for (i = 0; i < 4; i++) {
  1385. net.in6.s6_addr32[i] = ipaddr.in6.s6_addr32[i] & mask.in6.s6_addr32[i];
  1386. }
  1387. }
  1388. inet_ntop(interface->address_family, &net, network, NETCFG_ADDRSTRLEN);
  1389. }
  1390. void netcfg_broadcast_address(const struct netcfg_interface *interface,
  1391. char *broadcast)
  1392. {
  1393. struct in_addr broad, net, mask;
  1394. char network[INET_ADDRSTRLEN];
  1395. /* IPv6 has no concept of broadcast addresses */
  1396. if (interface->address_family != AF_INET) {
  1397. broadcast[0] = '\0';
  1398. return;
  1399. }
  1400. netcfg_network_address(interface, network);
  1401. inet_pton(AF_INET, network, &net);
  1402. inet_mton(AF_INET, interface->masklen, &mask);
  1403. broad.s_addr = (net.s_addr | ~mask.s_addr);
  1404. inet_ntop(AF_INET, &broad, broadcast, INET_ADDRSTRLEN);
  1405. }
  1406. /* Validate that the given gateway address actually lies within the given
  1407. * network. Standard boolean return.
  1408. */
  1409. int netcfg_gateway_reachable(const struct netcfg_interface *interface)
  1410. {
  1411. union inX_addr net, mask, gw_addr;
  1412. char network[NETCFG_ADDRSTRLEN];
  1413. netcfg_network_address(interface, network);
  1414. inet_pton(interface->address_family, network, &net);
  1415. inet_mton(interface->address_family, interface->masklen, &mask);
  1416. inet_pton(interface->address_family, interface->gateway, &gw_addr);
  1417. if (interface->address_family == AF_INET) {
  1418. return (gw_addr.in4.s_addr && ((gw_addr.in4.s_addr & mask.in4.s_addr) == net.in4.s_addr));
  1419. } else if (interface->address_family == AF_INET6) {
  1420. int i;
  1421. for (i = 0; i < 4; i++) {
  1422. if ((gw_addr.in6.s6_addr32[i] & mask.in6.s6_addr32[i]) != net.in6.s6_addr32[i]) {
  1423. return 0;
  1424. }
  1425. }
  1426. return 1;
  1427. } else {
  1428. /* Unknown address family */
  1429. fprintf(stderr, "Unknown address family given to netcfg_gateway_unreachable\n");
  1430. return 0;
  1431. }
  1432. }
  1433. /* Take an FQDN (or possibly a bare hostname) and use it to preseed the get_hostname
  1434. * and get_domain debconf variables.
  1435. */
  1436. void preseed_hostname_from_fqdn(struct debconfclient *client, char *buf)
  1437. {
  1438. char *dom;
  1439. if (valid_domain(buf)) {
  1440. di_debug("%s is a valid FQDN", buf);
  1441. dom = strchr(buf, '.');
  1442. if (dom) {
  1443. di_debug("We have a real FQDN");
  1444. *dom++ = '\0';
  1445. }
  1446. debconf_set(client, "netcfg/get_hostname", buf);
  1447. if (!have_domain && dom != NULL) {
  1448. di_debug("Preseeding domain as well: %s", dom);
  1449. debconf_set(client, "netcfg/get_domain", dom);
  1450. have_domain = 1;
  1451. } else if (have_domain && !empty_str(domain)) {
  1452. /* Global var 'domain' is holding a temporary domain name,
  1453. * presumably glommed from DHCP. Use it as default instead.
  1454. */
  1455. di_debug("Preseeding domain from global: %s", domain);
  1456. debconf_set(client, "netcfg/get_domain", domain);
  1457. }
  1458. }
  1459. }
  1460. /* Classic rtrim... strip off trailing whitespace from a string */
  1461. void rtrim(char *s)
  1462. {
  1463. int n;
  1464. n = strlen(s) - 1;
  1465. while (n >= 0 && isspace(s[n])) {
  1466. s[n] = '\0';
  1467. n--;
  1468. }
  1469. }
  1470. char *strtrim(char *s)
  1471. {
  1472. size_t len;
  1473. len = strlen(s);
  1474. if (!len)
  1475. return s;
  1476. rtrim(s);
  1477. while (*s && isspace(*s))
  1478. s++;
  1479. return s;
  1480. }