PageRenderTime 50ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/rc/udhcpc.c

http://wl500g.googlecode.com/
C | 481 lines | 361 code | 76 blank | 44 comment | 63 complexity | c442978afab22b307988e79d407dd436 MD5 | raw file
Possible License(s): GPL-2.0
  1. /*
  2. * udhcpc scripts
  3. *
  4. * Copyright 2004, Broadcom Corporation
  5. * All Rights Reserved.
  6. *
  7. * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
  8. * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
  9. * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
  10. * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
  11. *
  12. * $Id$
  13. */
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <net/route.h>
  18. #include <sys/socket.h>
  19. #include <netinet/in.h>
  20. #include <net/if.h>
  21. #include <arpa/inet.h>
  22. #include <errno.h>
  23. #include <time.h>
  24. #include <unistd.h>
  25. #include "rc.h"
  26. static char udhcpstate[12];
  27. static int start_zcip(const char *wan_ifname);
  28. static void stop_zcip(void);
  29. static int expires(const char *wan_ifname, unsigned int in)
  30. {
  31. time_t now;
  32. FILE *fp;
  33. char tmp[100], prefix[sizeof("wanXXXXXXXXXX_")];
  34. int unit;
  35. if ((unit = wan_prefix(wan_ifname, prefix)) < 0)
  36. return -1;
  37. time(&now);
  38. snprintf(tmp, sizeof(tmp), "/tmp/udhcpc%d.expires", unit);
  39. if (!(fp = fopen(tmp, "w"))) {
  40. perror(tmp);
  41. return errno;
  42. }
  43. fprintf(fp, "%d", (unsigned int) now + in);
  44. fclose(fp);
  45. return 0;
  46. }
  47. /*
  48. * deconfig: This argument is used when udhcpc starts, and when a
  49. * leases is lost. The script should put the interface in an up, but
  50. * deconfigured state.
  51. */
  52. static int deconfig(const char *wan_ifname, int zcip)
  53. {
  54. const char *client = zcip ? "zcip client" : "dhcp client";
  55. char tmp[100], prefix[sizeof("wanXXXXXXXXXX_")];
  56. char wanprefix[sizeof("wanXXXXXXXXXX_")];
  57. if (wans_prefix(wan_ifname, wanprefix, prefix) < 0)
  58. return EINVAL;
  59. if (nvram_match(strcat_r(wanprefix, "proto", tmp), "l2tp") ||
  60. nvram_match(strcat_r(wanprefix, "proto", tmp), "pptp")) {
  61. /* fix kernel route-loop issue */
  62. logmessage(client, "skipping resetting IP address to 0.0.0.0");
  63. } else
  64. ifconfig(wan_ifname, IFUP, "0.0.0.0", NULL);
  65. expires(wan_ifname, 0);
  66. wan_down(wan_ifname);
  67. logmessage(client, "%s: lease is lost", udhcpstate);
  68. wanmessage("lost IP from server");
  69. dprintf("done\n");
  70. return 0;
  71. }
  72. /*
  73. * bound: This argument is used when udhcpc moves from an unbound, to
  74. * a bound state. All of the paramaters are set in enviromental
  75. * variables, The script should configure the interface, and set any
  76. * other relavent parameters (default gateway, dns server, etc).
  77. */
  78. static int bound(const char *wan_ifname)
  79. {
  80. char *value;
  81. char tmp[100], prefix[sizeof("wanXXXXXXXXXX_")];
  82. char wanprefix[sizeof("wanXXXXXXXXXX_")];
  83. char route[sizeof("255.255.255.255/255")];
  84. int changed = 0;
  85. int gateway = 0;
  86. stop_zcip();
  87. if (wans_prefix(wan_ifname, wanprefix, prefix) < 0)
  88. return EINVAL;
  89. if ((value = getenv("ip"))) {
  90. changed = nvram_invmatch(strcat_r(prefix, "ipaddr", tmp), value);
  91. nvram_set(strcat_r(prefix, "ipaddr", tmp), trim_r(value));
  92. }
  93. if ((value = getenv("subnet")))
  94. nvram_set(strcat_r(prefix, "netmask", tmp), trim_r(value));
  95. if ((value = getenv("router"))) {
  96. gateway = 1;
  97. nvram_set(strcat_r(prefix, "gateway", tmp), trim_r(value));
  98. }
  99. if ((value = getenv("dns")))
  100. nvram_set(strcat_r(prefix, "dns", tmp), trim_r(value));
  101. if ((value = getenv("wins")))
  102. nvram_set(strcat_r(prefix, "wins", tmp), trim_r(value));
  103. /* classful static routes */
  104. nvram_set(strcat_r(prefix, "routes", tmp), getenv("routes"));
  105. /* ms classless static routes */
  106. nvram_set(strcat_r(prefix, "routes_ms", tmp), getenv("msstaticroutes"));
  107. /* rfc3442 classless static routes */
  108. nvram_set(strcat_r(prefix, "routes_rfc", tmp), getenv("staticroutes"));
  109. if (!gateway) {
  110. foreach(route, nvram_safe_get(strcat_r(prefix, "routes_rfc", tmp)), value) {
  111. if (gateway) {
  112. nvram_set(strcat_r(prefix, "gateway", tmp), route);
  113. break;
  114. } else
  115. gateway = !strcmp(route, "0.0.0.0/0");
  116. }
  117. }
  118. #if 0
  119. if ((value = getenv("hostname")))
  120. sethostname(trim_r(value), strlen(value) + 1);
  121. #endif
  122. if ((value = getenv("domain")))
  123. nvram_set(strcat_r(prefix, "domain", tmp), trim_r(value));
  124. if ((value = getenv("lease"))) {
  125. nvram_set(strcat_r(prefix, "lease", tmp), trim_r(value));
  126. expires(wan_ifname, atoi(value));
  127. }
  128. #ifdef __CONFIG_IPV6__
  129. if ((value = getenv("ip6rd"))) {
  130. char ip6rd[sizeof("32 128 FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF 255.255.255.255 ")];
  131. char addrstr[INET6_ADDRSTRLEN];
  132. char *values[4];
  133. int i;
  134. value = strncpy(ip6rd, value, sizeof(ip6rd));
  135. for (i = 0; i < 4 && value; i++)
  136. values[i] = strsep(&value, " ");
  137. if (i == 4) {
  138. nvram_set(strcat_r(wanprefix, "ipv6_ip4size", tmp), values[0]);
  139. snprintf(addrstr, sizeof(addrstr), "%s/%s", values[2], values[1]);
  140. nvram_set(strcat_r(wanprefix, "ipv6_addr", tmp), addrstr);
  141. nvram_set(strcat_r(wanprefix, "ipv6_relay", tmp), values[3]);
  142. }
  143. }
  144. #endif
  145. if (changed &&
  146. nvram_invmatch(strcat_r(wanprefix, "proto", tmp), "l2tp") &&
  147. nvram_invmatch(strcat_r(wanprefix, "proto", tmp), "pptp"))
  148. ifconfig(wan_ifname, IFUP, "0.0.0.0", NULL);
  149. ifconfig(wan_ifname, IFUP,
  150. nvram_safe_get(strcat_r(prefix, "ipaddr", tmp)),
  151. nvram_safe_get(strcat_r(prefix, "netmask", tmp)));
  152. wan_up(wan_ifname);
  153. logmessage("dhcp client", "%s IP : %s from %s",
  154. udhcpstate,
  155. nvram_safe_get(strcat_r(prefix, "ipaddr", tmp)),
  156. nvram_safe_get(strcat_r(prefix, "gateway", tmp)));
  157. wanmessage("");
  158. dprintf("done\n");
  159. return 0;
  160. }
  161. /*
  162. * renew: This argument is used when a DHCP lease is renewed. All of
  163. * the paramaters are set in enviromental variables. This argument is
  164. * used when the interface is already configured, so the IP address,
  165. * will not change, however, the other DHCP paramaters, such as the
  166. * default gateway, subnet mask, and dns server may change.
  167. */
  168. static int renew(const char *wan_ifname)
  169. {
  170. char *value;
  171. char tmp[100], prefix[sizeof("wanXXXXXXXXXX_")];
  172. char wanprefix[sizeof("wanXXXXXXXXXX_")];
  173. int metric;
  174. int changed = 0;
  175. stop_zcip();
  176. if (wans_prefix(wan_ifname, wanprefix, prefix) < 0)
  177. return EINVAL;
  178. if (!(value = getenv("subnet")) || nvram_invmatch(strcat_r(prefix, "netmask", tmp), trim_r(value)))
  179. return bound(wan_ifname);
  180. if (!(value = getenv("router")) || nvram_invmatch(strcat_r(prefix, "gateway", tmp), trim_r(value)))
  181. return bound(wan_ifname);
  182. if ((value = getenv("dns"))) {
  183. changed = nvram_invmatch(strcat_r(prefix, "dns", tmp), trim_r(value));
  184. nvram_set(strcat_r(prefix, "dns", tmp), trim_r(value));
  185. }
  186. if ((value = getenv("wins")))
  187. nvram_set(strcat_r(prefix, "wins", tmp), trim_r(value));
  188. #if 0
  189. if ((value = getenv("hostname")))
  190. sethostname(trim_r(value), strlen(value) + 1);
  191. #endif
  192. if ((value = getenv("domain")))
  193. nvram_set(strcat_r(prefix, "domain", tmp), trim_r(value));
  194. if ((value = getenv("lease"))) {
  195. nvram_set(strcat_r(prefix, "lease", tmp), trim_r(value));
  196. expires(wan_ifname, atoi(value));
  197. }
  198. if (changed) {
  199. metric = nvram_get_int(strcat_r(wanprefix, "priority", tmp));
  200. update_resolvconf(wan_ifname, metric, 1);
  201. }
  202. if (changed &&
  203. nvram_invmatch(strcat_r(wanprefix, "proto", tmp), "l2tp") &&
  204. nvram_invmatch(strcat_r(wanprefix, "proto", tmp), "pptp") &&
  205. nvram_invmatch(strcat_r(wanprefix, "proto", tmp), "pppoe"))
  206. update_wan_status(1);
  207. //logmessage("dhcp client", "%s IP : %s from %s",
  208. // udhcpstate,
  209. // nvram_safe_get(strcat_r(prefix, "ipaddr", tmp)),
  210. // nvram_safe_get(strcat_r(prefix, "gateway", tmp)));
  211. wanmessage("");
  212. dprintf("done\n");
  213. return 0;
  214. }
  215. static int leasefail(const char *wan_ifname)
  216. {
  217. char tmp[100], prefix[sizeof("wanXXXXXXXXXX_")];
  218. if (wanx_prefix(wan_ifname, prefix) < 0)
  219. return EINVAL;
  220. if ((ip_addr(nvram_safe_get(strcat_r(prefix, "ipaddr", tmp))) &
  221. ip_addr(nvram_safe_get(strcat_r(prefix, "netmask", tmp)))) ==
  222. ip_addr("169.254.0.0"))
  223. return 0;
  224. return start_zcip(wan_ifname);
  225. }
  226. int udhcpc_main(int argc, char **argv)
  227. {
  228. const char *wan_ifname;
  229. if (argc<2 || !argv[1])
  230. return EINVAL;
  231. wan_ifname = safe_getenv("interface");
  232. strcpy(udhcpstate, argv[1]);
  233. if (!strcmp(argv[1], "deconfig"))
  234. return deconfig(wan_ifname, 0);
  235. else if (!strcmp(argv[1], "bound"))
  236. return bound(wan_ifname);
  237. else if (!strcmp(argv[1], "renew"))
  238. return renew(wan_ifname);
  239. else if (!strcmp(argv[1], "leasefail"))
  240. return leasefail(wan_ifname);
  241. /* nak */
  242. else
  243. return 0;
  244. }
  245. int start_dhcpc(const char *wan_ifname, int unit)
  246. {
  247. char tmp[100], prefix[sizeof("wanXXXXXXXXXX_")];
  248. char pid[sizeof("/var/run/udhcpcXXXXXXXXXX.pid")];
  249. char *wan_hostname;
  250. char *dhcp_argv[] = {
  251. "/sbin/udhcpc",
  252. "-i", (char *)wan_ifname,
  253. "-p", (snprintf(pid, sizeof(pid), "/var/run/udhcpc%d.pid", unit), pid),
  254. "-b",
  255. NULL, NULL, /* -H wan_hostname */
  256. NULL, /* -O routes */
  257. NULL, /* -O staticroutes */
  258. NULL, /* -O msstaticroutes */
  259. #ifdef __CONFIG_IPV6__
  260. NULL, /* -O 6rd */
  261. NULL, /* -O comcast6rd */
  262. #endif
  263. #ifdef DEBUG
  264. NULL, /* -vvS */
  265. #endif
  266. NULL
  267. };
  268. int index = 6; /* first NULL index */
  269. /* We have to trust unit */
  270. snprintf(prefix, sizeof(prefix), "wan%d_", unit);
  271. wan_hostname = nvram_safe_get(strcat_r(prefix, "hostname", tmp));
  272. if (*wan_hostname) {
  273. dhcp_argv[index++] = "-H";
  274. dhcp_argv[index++] = wan_hostname;
  275. }
  276. if (nvram_match("dr_enable_x", "1")) {
  277. dhcp_argv[index++] = "-O33"; /* "routes" */
  278. dhcp_argv[index++] = "-O121"; /* "staticroutes" */
  279. dhcp_argv[index++] = "-O249"; /* "msstaticroutes" */
  280. }
  281. #ifdef __CONFIG_IPV6__
  282. if (nvram_match("ipv6_proto", "tun6rd")) {
  283. dhcp_argv[index++] = "-O212"; /* "6rd" */
  284. dhcp_argv[index++] = "-O150"; /* "comcast6rd" */
  285. }
  286. #endif
  287. #ifdef DEBUG
  288. dhcp_argv[index++] = "-vvS";
  289. #endif
  290. return _eval(dhcp_argv, NULL, 0, NULL);
  291. }
  292. static int config(const char *wan_ifname)
  293. {
  294. char *value;
  295. char tmp[100], prefix[sizeof("wanXXXXXXXXXX_")];
  296. char wanprefix[sizeof("wanXXXXXXXXXX_")];
  297. int changed = 0;
  298. if (wans_prefix(wan_ifname, wanprefix, prefix) < 0)
  299. return EINVAL;
  300. if ((value = getenv("ip"))) {
  301. changed = nvram_invmatch(strcat_r(prefix, "ipaddr", tmp), value);
  302. nvram_set(strcat_r(prefix, "ipaddr", tmp), trim_r(value));
  303. }
  304. nvram_set(strcat_r(prefix, "netmask", tmp), "255.255.0.0");
  305. nvram_set(strcat_r(prefix, "gateway", tmp), "");
  306. nvram_set(strcat_r(prefix, "dns", tmp), "");
  307. if (changed &&
  308. nvram_invmatch(strcat_r(wanprefix, "proto", tmp), "l2tp") &&
  309. nvram_invmatch(strcat_r(wanprefix, "proto", tmp), "pptp"))
  310. ifconfig(wan_ifname, IFUP, "0.0.0.0", NULL);
  311. ifconfig(wan_ifname, IFUP,
  312. nvram_safe_get(strcat_r(prefix, "ipaddr", tmp)),
  313. nvram_safe_get(strcat_r(prefix, "netmask", tmp)));
  314. wan_up(wan_ifname);
  315. logmessage("zcip client", "%s IP : %s",
  316. udhcpstate,
  317. nvram_safe_get(strcat_r(prefix, "ipaddr", tmp)));
  318. wanmessage("");
  319. dprintf("done\n");
  320. return 0;
  321. }
  322. int zcip_main(int argc, char **argv)
  323. {
  324. const char *wan_ifname;
  325. if (argc<2 || !argv[1])
  326. return EINVAL;
  327. wan_ifname = safe_getenv("interface");
  328. strcpy(udhcpstate, argv[1]);
  329. if (!strcmp(argv[1], "deconfig"))
  330. return deconfig(wan_ifname, 1);
  331. else if (!strcmp(argv[1], "config"))
  332. return config(wan_ifname);
  333. /* init */
  334. else return 0;
  335. }
  336. static int start_zcip(const char *wan_ifname)
  337. {
  338. char *zcip_argv[] = { "/sbin/zcip", "-q", (char *)wan_ifname, "/tmp/zcip.script", NULL };
  339. return _eval(zcip_argv, NULL, 0, NULL);
  340. }
  341. static void stop_zcip(void)
  342. {
  343. killall_s("zcip.script", SIGTERM);
  344. killall("zcip");
  345. }
  346. #ifdef __CONFIG_IPV6__
  347. int dhcp6c_main(int argc, char **argv)
  348. {
  349. char *wan_ifname = safe_getenv("interface");
  350. char *dns6 = getenv("new_domain_name_servers");
  351. if (dns6) {
  352. //TODO: Process new DNS records and correct metric
  353. update_resolvconf(wan_ifname, 2, 1);
  354. }
  355. // notify radvd of possible change
  356. killall_s("radvd", SIGHUP);
  357. return 0;
  358. }
  359. int start_dhcp6c(const char *wan_ifname)
  360. {
  361. FILE *fp;
  362. pid_t pid;
  363. int sla_len, ret, is_wan6_valid;
  364. struct in6_addr wan6_addr;
  365. char *dhcp6c_argv[] = { "/sbin/dhcp6c", "-v", "-D", "LL", (char *)wan_ifname, NULL };
  366. if (!nvram_match("ipv6_proto", "dhcp6")) return 1;
  367. stop_dhcp6c();
  368. sla_len = 64 - nvram_get_int("ipv6_lan_netsize");
  369. if (sla_len <= 0)
  370. sla_len = 0;
  371. else if (sla_len > 16)
  372. sla_len = 16;
  373. is_wan6_valid = ipv6_addr(nvram_safe_get("wan0_ipv6_addr"), &wan6_addr);
  374. if ((fp = fopen("/etc/dhcp6c.conf", "w")) == NULL) {
  375. perror("/etc/dhcp6c.conf");
  376. return 2;
  377. }
  378. fprintf(fp, "interface %s {\n"
  379. " send ia-pd 0;\n"
  380. "%s"
  381. " send rapid-commit;\n" /* May cause unexpected advertise in case of server don't support rapid-commit */
  382. " request domain-name-servers;\n"
  383. " script \"/tmp/dhcp6c.script\";\n"
  384. "};\n"
  385. "id-assoc pd 0 {\n"
  386. " prefix-interface %s {\n"
  387. " sla-id 0;\n"
  388. " sla-len %d;\n"
  389. " };\n"
  390. "};\n"
  391. "id-assoc na 0 { };\n",
  392. wan_ifname,
  393. (is_wan6_valid > 0) ? "" : " send ia-na 0;\n",
  394. nvram_safe_get("lan_ifname"), sla_len
  395. );
  396. fclose(fp);
  397. ret = _eval(dhcp6c_argv, NULL, 0, &pid);
  398. return ret;
  399. }
  400. void stop_dhcp6c(void)
  401. {
  402. killall_s("dhcp6c.script", SIGTERM);
  403. kill_pidfile("/var/run/dhcp6c.pid");
  404. }
  405. #endif