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.
 
 
 
 

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