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.

nm-conf.c 14 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470
  1. #include <arpa/inet.h>
  2. #include <ctype.h>
  3. #include <errno.h>
  4. #include <netinet/in.h>
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include <sys/socket.h>
  8. #include <sys/stat.h>
  9. #ifdef WIRELESS
  10. #include <iwlib.h>
  11. #endif
  12. #include <debian-installer.h>
  13. #include "nm-conf.h"
  14. /* Linux provides a lightweight facility that can generate UUIDs for us. */
  15. static void get_uuid(char* target)
  16. {
  17. FILE* fp = fopen("/proc/sys/kernel/random/uuid", "r");
  18. if (fgets(target, NM_MAX_LEN_UUID, fp) == NULL)
  19. {
  20. di_error("get_uuid() failed: %s", strerror(errno));
  21. exit(1);
  22. }
  23. target[NM_MAX_LEN_UUID-1] = '\0'; // clear the newline
  24. fclose(fp);
  25. }
  26. /* Functions for printing informations in Network Manager format. */
  27. static void nm_write_connection(FILE *config_file, nm_connection connection)
  28. {
  29. fprintf(config_file, "\n%s\n", NM_SETTINGS_CONNECTION);
  30. fprintf(config_file, "id=%s\n", connection.id);
  31. fprintf(config_file, "uuid=%s\n", connection.uuid);
  32. fprintf(config_file, "type=%s\n", (connection.type == WIFI) ?
  33. NM_DEFAULT_WIRELESS : NM_DEFAULT_WIRED);
  34. }
  35. #ifdef WIRELESS
  36. static void nm_write_wireless_specific_options(FILE *config_file,
  37. struct nm_config_info *nmconf)
  38. {
  39. nm_wireless wireless = nmconf->wireless;
  40. fprintf(config_file, "\n%s\n", NM_SETTINGS_WIRELESS);
  41. fprintf(config_file, "ssid=%s\n", wireless.ssid);
  42. fprintf(config_file, "mode=%s\n", (wireless.mode == AD_HOC) ?
  43. "adhoc" : "infrastructure");
  44. if (strcmp(wireless.mac_addr, "") && nmconf->connection.manual == 1) {
  45. fprintf(config_file, "mac=%s\n", wireless.mac_addr);
  46. }
  47. if (wireless.is_secured == TRUE) {
  48. fprintf(config_file, "security=%s\n", NM_DEFAULT_WIRELESS_SECURITY);
  49. }
  50. }
  51. #endif
  52. static void nm_write_wired_specific_options(FILE *config_file,
  53. struct nm_config_info *nmconf)
  54. {
  55. nm_wired wired = nmconf->wired;
  56. fprintf(config_file, "\n%s\n", NM_SETTINGS_WIRED);
  57. if (strcmp(wired.mac_addr, "") && nmconf->connection.manual == 1) {
  58. fprintf(config_file, "mac=%s\n", wired.mac_addr);
  59. }
  60. }
  61. #ifdef WIRELESS
  62. static void nm_write_wireless_security(FILE *config_file, nm_wireless_security
  63. wireless_security)
  64. {
  65. fprintf(config_file, "\n%s\n", NM_SETTINGS_WIRELESS_SECURITY);
  66. if (wireless_security.key_mgmt == WPA_PSK) {
  67. fprintf(config_file, "key-mgmt=%s\n", "wpa-psk");
  68. fprintf(config_file, "psk=%s\n", wireless_security.psk);
  69. }
  70. else {
  71. fprintf(config_file, "key-mgmt=%s\n", "none");
  72. fprintf(config_file, "auth-alg=%s\n",
  73. (wireless_security.auth_alg == OPEN) ? "open" : "shared");
  74. fprintf(config_file, "wep-key0=%s\n", wireless_security.wep_key0);
  75. fprintf(config_file, "wep-key-type=%d\n",
  76. wireless_security.wep_key_type);
  77. }
  78. }
  79. #endif
  80. static void nm_write_static_ipvX(FILE *config_file, nm_ipvX ipvx)
  81. {
  82. char buffer[NM_MAX_LEN_BUF], addr[NM_MAX_LEN_IPV4];
  83. int i;
  84. /* Get DNS in printable format. */
  85. memset(buffer, 0, NM_MAX_LEN_BUF);
  86. for (i = 0; (i < NETCFG_NAMESERVERS_MAX) &&
  87. (!empty_str(ipvx.nameservers[i])); i++) {
  88. strcat(buffer, ipvx.nameservers[i]);
  89. strcat(buffer, ";");
  90. }
  91. if (strcmp(buffer, "")) {
  92. fprintf(config_file, "dns=%s\n", buffer);
  93. }
  94. /* Get addresses in printable format. */
  95. memset(buffer, 0, NM_MAX_LEN_BUF);
  96. /* Write IP address to the buffer. */
  97. strcat(buffer, ipvx.ip_address);
  98. strcat(buffer, ";");
  99. /* Write netmask to the buffer. */
  100. sprintf(addr, "%d", ipvx.masklen);
  101. strcat(buffer, addr);
  102. strcat(buffer, ";");
  103. /* Write gateway address to the buffer. */
  104. memset(addr, 0, NM_MAX_LEN_IPV4);
  105. if (!empty_str(ipvx.gateway)) {
  106. strncpy(addr, ipvx.gateway, NM_MAX_LEN_IPV4 - 1);
  107. }
  108. else {
  109. strcpy(addr, "0");
  110. }
  111. strcat(buffer, addr);
  112. strcat(buffer, ";");
  113. /* Write config to the configuration file. */
  114. fprintf(config_file, "addresses1=%s\n", buffer);
  115. }
  116. static void nm_write_ipv4(FILE *config_file, nm_ipvX ipv4)
  117. {
  118. fprintf(config_file, "\n%s\n", NM_SETTINGS_IPV4);
  119. if (ipv4.method == AUTO) {
  120. fprintf(config_file, "method=%s\n", "auto");
  121. }
  122. else {
  123. fprintf(config_file, "method=%s\n", "manual");
  124. nm_write_static_ipvX(config_file, ipv4);
  125. }
  126. }
  127. static void nm_write_ipv6(FILE *config_file, nm_ipvX ipv6)
  128. {
  129. fprintf(config_file, "\n%s\n", NM_SETTINGS_IPV6);
  130. if (ipv6.method == AUTO) {
  131. fprintf(config_file, "method=%s\n", "auto");
  132. fprintf(config_file, "ip6-privacy=2\n");
  133. }
  134. else if (ipv6.method == MANUAL) {
  135. fprintf(config_file, "method=%s\n", "manual");
  136. nm_write_static_ipvX(config_file, ipv6);
  137. }
  138. else if (ipv6.method == IGNORE) {
  139. fprintf(config_file, "method=%s\n", "ignore");
  140. }
  141. }
  142. /* Write info about how the network was configured to a specific file, in
  143. * order to be used in the finish install script. */
  144. static void nm_write_connection_type(struct nm_config_info nmconf)
  145. {
  146. FILE *f = fopen(NM_CONNECTION_FILE, "w");
  147. if (nmconf.connection.type == WIFI) {
  148. fprintf(f, "connection type: wireless\n");
  149. }
  150. else {
  151. fprintf(f, "connection type: wired\n");
  152. }
  153. if (nmconf.connection.type == WIFI && nmconf.wireless.is_secured) {
  154. fprintf(f, "security: secured\n");
  155. }
  156. else {
  157. fprintf(f, "security: unsecured\n");
  158. }
  159. fclose(f);
  160. }
  161. /* Write Network Manager config file. */
  162. void nm_write_configuration(struct nm_config_info nmconf)
  163. {
  164. FILE *config_file;
  165. char buffer[NM_MAX_LEN_BUF];
  166. /* Create the directory for the config file and clear any possible
  167. * previous files found there. */
  168. sprintf(buffer, "mkdir -p %s", NM_CONFIG_FILE_PATH);
  169. di_exec_shell(buffer);
  170. /* If the directory exist mkdir will do nothing, so just remove every file
  171. * there. Rely on the fact that for now netcfg only does config for one
  172. * interface. */
  173. sprintf(buffer, "rm %s/*", NM_CONFIG_FILE_PATH);
  174. di_exec_shell(buffer);
  175. /* Open file using its full path. */
  176. sprintf(buffer, "%s/%s", NM_CONFIG_FILE_PATH, nmconf.connection.id);
  177. config_file = fopen(buffer, "w");
  178. if (config_file == NULL) {
  179. di_info("Unable to open file for writing network-manager "
  180. "configuration. The connection id (%s) might not be "
  181. "set to a proper value.", nmconf.connection.id);
  182. return;
  183. }
  184. if (fchmod(fileno(config_file), 0600) != 0) {
  185. di_error("network-manager connection file cannot be protected "
  186. "from reading: %s", strerror(errno));
  187. exit(1);
  188. }
  189. nm_write_connection(config_file, nmconf.connection);
  190. if (nmconf.connection.type == WIRED) {
  191. nm_write_wired_specific_options(config_file, &nmconf);
  192. }
  193. #ifdef WIRELESS
  194. else {
  195. nm_write_wireless_specific_options(config_file, &nmconf);
  196. if (nmconf.wireless.is_secured) {
  197. nm_write_wireless_security(config_file, nmconf.wireless_security);
  198. }
  199. }
  200. #endif
  201. nm_write_ipv4(config_file, nmconf.ipv4);
  202. nm_write_ipv6(config_file, nmconf.ipv6);
  203. fclose(config_file);
  204. nm_write_connection_type(nmconf);
  205. }
  206. /* Functions for extracting information from netcfg variables. */
  207. /* Get info for the connection setting for wireless networks. */
  208. #ifdef WIRELESS
  209. static void nm_get_wireless_connection(struct netcfg_interface *niface, nm_connection *connection)
  210. {
  211. /* Use the wireless network name for connection id. */
  212. snprintf(connection->id, NM_MAX_LEN_ID, "%s", niface->essid);
  213. /* Generate uuid. */
  214. get_uuid(connection->uuid);
  215. connection->type = WIFI;
  216. }
  217. #endif
  218. /* Get info for the connection setting for wired networks. */
  219. static void nm_get_wired_connection(nm_connection *connection)
  220. {
  221. /* This is the first wired connection. */
  222. snprintf(connection->id, NM_MAX_LEN_ID, NM_DEFAULT_WIRED_NAME);
  223. /* Generate uuid. */
  224. get_uuid(connection->uuid);
  225. connection->type = WIRED;
  226. }
  227. /* Get MAC address from default file. */
  228. static void nm_get_mac_address(char *interface, char *mac_addr)
  229. {
  230. char file_name[NM_MAX_LEN_PATH];
  231. FILE *file;
  232. snprintf(file_name, NM_MAX_LEN_PATH, NM_DEFAULT_PATH_FOR_MAC, interface);
  233. file = fopen(file_name, "r");
  234. if (file == NULL) {
  235. mac_addr[0] = '\0'; /* Empty string means don't write MAC. */
  236. }
  237. else {
  238. int i;
  239. if (fscanf(file, "%s\n", mac_addr) != EOF) {
  240. /* Should be upper case. */
  241. for (i = 0; mac_addr[i]; i++) {
  242. mac_addr[i] = toupper(mac_addr[i]);
  243. }
  244. }
  245. }
  246. }
  247. #ifdef WIRELESS
  248. static void nm_get_wireless_specific_options(struct netcfg_interface *niface, nm_wireless *wireless)
  249. {
  250. strncpy(wireless->ssid, niface->essid, NM_MAX_LEN_SSID);
  251. nm_get_mac_address(niface->name, wireless->mac_addr);
  252. /* Decide mode. */
  253. if (niface->mode == ADHOC) {
  254. wireless->mode = AD_HOC;
  255. }
  256. else {
  257. wireless->mode = INFRASTRUCTURE;
  258. }
  259. /* In netcfg, you have to chose WEP and leave the key empty for an
  260. * unsecure connection. */
  261. if (niface->wifi_security == REPLY_WEP && niface->wepkey == NULL) {
  262. wireless->is_secured = FALSE;
  263. }
  264. else {
  265. wireless->is_secured = TRUE;
  266. }
  267. }
  268. #endif
  269. /* Only set MAC address, the others have good defaults in NM. */
  270. static void nm_get_wired_specific_options(struct netcfg_interface *niface, nm_wired *wired)
  271. {
  272. nm_get_mac_address(niface->name, wired->mac_addr);
  273. }
  274. /* Security type for wireless networks. */
  275. #ifdef WIRELESS
  276. static void nm_get_wireless_security(struct netcfg_interface *niface, nm_wireless_security *wireless_security)
  277. {
  278. if (niface->wifi_security == REPLY_WPA) {
  279. wireless_security->key_mgmt = WPA_PSK;
  280. memset(wireless_security->psk, 0, NM_MAX_LEN_WPA_PSK);
  281. strncpy(wireless_security->psk, niface->passphrase, NM_MAX_LEN_WPA_PSK - 1);
  282. }
  283. else {
  284. wireless_security->key_mgmt = WEP_KEY;
  285. memset(wireless_security->wep_key0, 0, NM_MAX_LEN_WEP_KEY);
  286. iw_in_key(niface->wepkey, wireless_security->wep_key0);
  287. /* Only options supported by netcfg for now. */
  288. wireless_security->wep_key_type = HEX_ASCII;
  289. wireless_security->auth_alg = OPEN;
  290. }
  291. }
  292. #endif
  293. /* Save IPv4 settings. */
  294. static void nm_get_ipv4(struct netcfg_interface *niface, nm_ipvX *ipv4)
  295. {
  296. /* DHCP wasn't used and there is no IPv4 address saved => didn't use ipv4
  297. * so won't use it in the future. */
  298. if (niface->dhcp == 0 && niface->address_family != AF_INET) {
  299. ipv4->used = 0;
  300. }
  301. else {
  302. ipv4->used = 1;
  303. }
  304. if (niface->dhcp == 1) {
  305. ipv4->method = AUTO;
  306. }
  307. else if (niface->address_family == AF_INET) {
  308. int i;
  309. ipv4->method = MANUAL;
  310. ipv4->ip_address = niface->ipaddress;
  311. ipv4->gateway = niface->gateway;
  312. ipv4->masklen = niface->masklen;
  313. for (i = 0; i < NETCFG_NAMESERVERS_MAX; i++) {
  314. ipv4->nameservers[i] = niface->nameservers[i];
  315. }
  316. }
  317. else {
  318. /* IPv4 might always be activated in the future. */
  319. ipv4->method = AUTO;
  320. }
  321. }
  322. /* For the moment, just set it to ignore. */
  323. static void nm_get_ipv6(struct netcfg_interface *niface, nm_ipvX *ipv6)
  324. {
  325. /* No IPv6 address, no dhcpv6, nor slaac, so wasn't used. */
  326. if (niface->address_family != AF_INET6 && niface->dhcpv6 == 0 &&
  327. niface->slaac == 0) {
  328. ipv6->used = 0;
  329. }
  330. else {
  331. ipv6->used = 1;
  332. }
  333. if (niface->dhcpv6 == 1 || niface->slaac == 1) {
  334. ipv6->method = AUTO;
  335. }
  336. else if (niface->address_family == AF_INET6) {
  337. int i;
  338. ipv6->method = MANUAL;
  339. ipv6->ip_address = niface->ipaddress;
  340. ipv6->gateway = niface->gateway;
  341. ipv6->masklen = niface->masklen;
  342. for (i = 0; i < NETCFG_NAMESERVERS_MAX; i++) {
  343. ipv6->nameservers[i] = niface->nameservers[i];
  344. }
  345. }
  346. else {
  347. /* IPv6 might always be activated in the future. */
  348. ipv6->method = AUTO;
  349. }
  350. }
  351. /* Extract all configs for a wireless interface, from both global netcfg
  352. * values and other resources. */
  353. #ifdef WIRELESS
  354. static void nm_get_wireless_config(struct netcfg_interface *niface, struct nm_config_info *nmconf)
  355. {
  356. nm_get_wireless_connection(niface, &(nmconf->connection));
  357. nm_get_wireless_specific_options(niface, &(nmconf->wireless));
  358. if (nmconf->wireless.is_secured == TRUE) {
  359. nm_get_wireless_security(niface, &(nmconf->wireless_security));
  360. }
  361. nm_get_ipv4(niface, &(nmconf->ipv4));
  362. nm_get_ipv6(niface, &(nmconf->ipv6));
  363. }
  364. #endif
  365. /* Extract all configs for a wired interface. */
  366. static void nm_get_wired_config(struct netcfg_interface *niface, struct nm_config_info *nmconf)
  367. {
  368. nm_get_wired_connection(&(nmconf->connection));
  369. nm_get_wired_specific_options(niface, &(nmconf->wired));
  370. nm_get_ipv4(niface, &(nmconf->ipv4));
  371. nm_get_ipv6(niface, &(nmconf->ipv6));
  372. }
  373. /* Getting configurations for NM relies on netcfrg global variables. */
  374. void nm_get_configuration(struct netcfg_interface *niface, struct nm_config_info *nmconf)
  375. {
  376. /* Decide if wireless configuration is needed. */
  377. if (!is_wireless_iface(niface->name)) {
  378. nm_get_wired_config(niface, nmconf);
  379. }
  380. #ifdef WIRELESS
  381. else {
  382. nm_get_wireless_config(niface, nmconf);
  383. }
  384. #endif
  385. if (nmconf->ipv4.method == MANUAL || nmconf->ipv6.method == MANUAL) {
  386. /* Manual address family configuration should be bound to a MAC
  387. * address. Hence record this fact globally for the connection. */
  388. nmconf->connection.manual = 1;
  389. }
  390. else {
  391. nmconf->connection.manual = 0;
  392. }
  393. }