d6_dhcpc.c 63 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * DHCPv6 client.
  4. *
  5. * Copyright (C) 2011-2017 Denys Vlasenko.
  6. *
  7. * Licensed under GPLv2, see file LICENSE in this source tree.
  8. */
  9. //config:config UDHCPC6
  10. //config: bool "udhcpc6 (21 kb)"
  11. //config: default y
  12. //config: depends on FEATURE_IPV6
  13. //config: help
  14. //config: udhcpc6 is a DHCPv6 client
  15. //config:
  16. //config:config FEATURE_UDHCPC6_RFC3646
  17. //config: bool "Support RFC 3646 (DNS server and search list)"
  18. //config: default y
  19. //config: depends on UDHCPC6
  20. //config: help
  21. //config: List of DNS servers and domain search list can be requested with
  22. //config: "-O dns" and "-O search". If server gives these values,
  23. //config: they will be set in environment variables "dns" and "search".
  24. //config:
  25. //config:config FEATURE_UDHCPC6_RFC4704
  26. //config: bool "Support RFC 4704 (Client FQDN)"
  27. //config: default y
  28. //config: depends on UDHCPC6
  29. //config: help
  30. //config: You can request FQDN to be given by server using "-O fqdn".
  31. //config:
  32. //config:config FEATURE_UDHCPC6_RFC4833
  33. //config: bool "Support RFC 4833 (Timezones)"
  34. //config: default y
  35. //config: depends on UDHCPC6
  36. //config: help
  37. //config: You can request POSIX timezone with "-O tz" and timezone name
  38. //config: with "-O timezone".
  39. //config:
  40. //config:config FEATURE_UDHCPC6_RFC5970
  41. //config: bool "Support RFC 5970 (Network Boot)"
  42. //config: default y
  43. //config: depends on UDHCPC6
  44. //config: help
  45. //config: You can request bootfile-url with "-O bootfile_url" and
  46. //config: bootfile-params with "-O bootfile_params".
  47. //applet:IF_UDHCPC6(APPLET(udhcpc6, BB_DIR_USR_BIN, BB_SUID_DROP))
  48. //kbuild:lib-$(CONFIG_UDHCPC6) += d6_dhcpc.o d6_packet.o d6_socket.o common.o socket.o signalpipe.o
  49. //kbuild:lib-$(CONFIG_FEATURE_UDHCPC6_RFC3646) += domain_codec.o
  50. //kbuild:lib-$(CONFIG_FEATURE_UDHCPC6_RFC4704) += domain_codec.o
  51. #include <syslog.h>
  52. /* Override ENABLE_FEATURE_PIDFILE - ifupdown needs our pidfile to always exist */
  53. #define WANT_PIDFILE 1
  54. #include "common.h"
  55. #include "dhcpd.h"
  56. #include "dhcpc.h"
  57. #include "d6_common.h"
  58. #include <netinet/if_ether.h>
  59. #include <netpacket/packet.h>
  60. #include <linux/filter.h>
  61. /* "struct client_data_t client_data" is in bb_common_bufsiz1 */
  62. static const struct dhcp_optflag d6_optflags[] ALIGN2 = {
  63. #if ENABLE_FEATURE_UDHCPC6_RFC3646
  64. { OPTION_6RD | OPTION_LIST | OPTION_REQ, D6_OPT_DNS_SERVERS },
  65. { OPTION_DNS_STRING | OPTION_LIST | OPTION_REQ, D6_OPT_DOMAIN_LIST },
  66. #endif
  67. #if ENABLE_FEATURE_UDHCPC6_RFC4704
  68. { OPTION_DNS_STRING, D6_OPT_CLIENT_FQDN },
  69. #endif
  70. #if ENABLE_FEATURE_UDHCPC6_RFC4833
  71. { OPTION_STRING, D6_OPT_TZ_POSIX },
  72. { OPTION_STRING, D6_OPT_TZ_NAME },
  73. #endif
  74. #if ENABLE_FEATURE_UDHCPC6_RFC5970
  75. { OPTION_STRING, D6_OPT_BOOT_URL },
  76. { OPTION_STRING, D6_OPT_BOOT_PARAM },
  77. #endif
  78. { OPTION_STRING, 0xd1 }, /* DHCP_PXE_CONF_FILE */
  79. { OPTION_STRING, 0xd2 }, /* DHCP_PXE_PATH_PREFIX */
  80. { 0, 0 }
  81. };
  82. /* Must match d6_optflags[] order */
  83. static const char d6_option_strings[] ALIGN1 =
  84. #if ENABLE_FEATURE_UDHCPC6_RFC3646
  85. "dns" "\0" /* D6_OPT_DNS_SERVERS */
  86. "search" "\0" /* D6_OPT_DOMAIN_LIST */
  87. #endif
  88. #if ENABLE_FEATURE_UDHCPC6_RFC4704
  89. "fqdn" "\0" /* D6_OPT_CLIENT_FQDN */
  90. #endif
  91. #if ENABLE_FEATURE_UDHCPC6_RFC4833
  92. "tz" "\0" /* D6_OPT_TZ_POSIX */
  93. "timezone" "\0" /* D6_OPT_TZ_NAME */
  94. #endif
  95. #if ENABLE_FEATURE_UDHCPC6_RFC5970
  96. "bootfile_url" "\0" /* D6_OPT_BOOT_URL */
  97. "bootfile_param" "\0" /* D6_OPT_BOOT_PARAM */
  98. #endif
  99. "pxeconffile" "\0" /* DHCP_PXE_CONF_FILE */
  100. "pxepathprefix" "\0" /* DHCP_PXE_PATH_PREFIX */
  101. "\0";
  102. #if ENABLE_LONG_OPTS
  103. static const char udhcpc6_longopts[] ALIGN1 =
  104. "interface\0" Required_argument "i"
  105. "now\0" No_argument "n"
  106. "pidfile\0" Required_argument "p"
  107. "quit\0" No_argument "q"
  108. "release\0" No_argument "R"
  109. "request\0" Required_argument "r"
  110. "requestprefix\0" No_argument "d"
  111. "script\0" Required_argument "s"
  112. "timeout\0" Required_argument "T"
  113. "retries\0" Required_argument "t"
  114. "tryagain\0" Required_argument "A"
  115. "syslog\0" No_argument "S"
  116. "request-option\0" Required_argument "O"
  117. "no-default-options\0" No_argument "o"
  118. "foreground\0" No_argument "f"
  119. "stateless\0" No_argument "l"
  120. USE_FOR_MMU(
  121. "background\0" No_argument "b"
  122. )
  123. /// IF_FEATURE_UDHCPC_ARPING("arping\0" No_argument "a")
  124. IF_FEATURE_UDHCP_PORT("client-port\0" Required_argument "P")
  125. ;
  126. #endif
  127. /* Must match getopt32 option string order */
  128. enum {
  129. OPT_i = 1 << 0,
  130. OPT_n = 1 << 1,
  131. OPT_p = 1 << 2,
  132. OPT_q = 1 << 3,
  133. OPT_R = 1 << 4,
  134. OPT_r = 1 << 5,
  135. OPT_s = 1 << 6,
  136. OPT_T = 1 << 7,
  137. OPT_t = 1 << 8,
  138. OPT_S = 1 << 9,
  139. OPT_A = 1 << 10,
  140. OPT_O = 1 << 11,
  141. OPT_o = 1 << 12,
  142. OPT_x = 1 << 13,
  143. OPT_f = 1 << 14,
  144. OPT_l = 1 << 15,
  145. OPT_d = 1 << 16,
  146. /* The rest has variable bit positions, need to be clever */
  147. OPTBIT_d = 16,
  148. USE_FOR_MMU( OPTBIT_b,)
  149. ///IF_FEATURE_UDHCPC_ARPING(OPTBIT_a,)
  150. IF_FEATURE_UDHCP_PORT( OPTBIT_P,)
  151. USE_FOR_MMU( OPT_b = 1 << OPTBIT_b,)
  152. ///IF_FEATURE_UDHCPC_ARPING(OPT_a = 1 << OPTBIT_a,)
  153. IF_FEATURE_UDHCP_PORT( OPT_P = 1 << OPTBIT_P,)
  154. };
  155. #if ENABLE_FEATURE_UDHCPC6_RFC4704
  156. static const char opt_fqdn_req[] = {
  157. (D6_OPT_CLIENT_FQDN >> 8), (D6_OPT_CLIENT_FQDN & 0xff),
  158. 0, 2, /* optlen */
  159. 0, /* flags: */
  160. /* S=0: server SHOULD NOT perform AAAA RR updates */
  161. /* O=0: client MUST set this bit to 0 */
  162. /* N=0: server SHOULD perform updates (PTR RR only in our case, since S=0) */
  163. 0 /* empty DNS-encoded name */
  164. };
  165. #endif
  166. /*** Utility functions ***/
  167. static void *d6_find_option(uint8_t *option, uint8_t *option_end, unsigned code)
  168. {
  169. /* "length minus 4" */
  170. int len_m4 = option_end - option - 4;
  171. while (len_m4 >= 0) {
  172. /* Next option's len is too big? */
  173. if (option[3] > len_m4)
  174. return NULL; /* yes. bogus packet! */
  175. /* So far we treat any opts with code >255
  176. * or len >255 as bogus, and stop at once.
  177. * This simplifies big-endian handling.
  178. */
  179. if (option[0] != 0 || option[2] != 0)
  180. return NULL;
  181. /* Option seems to be valid */
  182. /* Does its code match? */
  183. if (option[1] == code)
  184. return option; /* yes! */
  185. len_m4 -= option[3] + 4;
  186. option += option[3] + 4;
  187. }
  188. return NULL;
  189. }
  190. static void *d6_copy_option(uint8_t *option, uint8_t *option_end, unsigned code)
  191. {
  192. uint8_t *opt = d6_find_option(option, option_end, code);
  193. if (!opt)
  194. return opt;
  195. return xmemdup(opt, opt[3] + 4);
  196. }
  197. /*** Script execution code ***/
  198. static char** new_env(void)
  199. {
  200. client6_data.env_ptr = xrealloc_vector(client6_data.env_ptr, 3, client6_data.env_idx);
  201. return &client6_data.env_ptr[client6_data.env_idx++];
  202. }
  203. static char *string_option_to_env(const uint8_t *option,
  204. const uint8_t *option_end)
  205. {
  206. const char *ptr, *name = NULL;
  207. unsigned val_len;
  208. int i;
  209. ptr = d6_option_strings;
  210. i = 0;
  211. while (*ptr) {
  212. if (d6_optflags[i].code == option[1]) {
  213. name = ptr;
  214. goto found;
  215. }
  216. ptr += strlen(ptr) + 1;
  217. i++;
  218. }
  219. bb_error_msg("can't find option name for 0x%x, skipping", option[1]);
  220. return NULL;
  221. found:
  222. val_len = (option[2] << 8) | option[3];
  223. if (val_len + &option[D6_OPT_DATA] > option_end) {
  224. bb_simple_error_msg("option data exceeds option length");
  225. return NULL;
  226. }
  227. return xasprintf("%s=%.*s", name, val_len, (char*)option + 4);
  228. }
  229. /* put all the parameters into the environment */
  230. static void option_to_env(const uint8_t *option, const uint8_t *option_end)
  231. {
  232. #if ENABLE_FEATURE_UDHCPC6_RFC3646
  233. int addrs, option_offset;
  234. #endif
  235. /* "length minus 4" */
  236. int len_m4 = option_end - option - 4;
  237. while (len_m4 >= 0) {
  238. uint32_t v32;
  239. char ipv6str[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")];
  240. if (option[0] != 0 || option[2] != 0)
  241. break;
  242. /* Check if option-length exceeds size of option */
  243. if (option[3] > len_m4)
  244. break;
  245. switch (option[1]) {
  246. //case D6_OPT_CLIENTID:
  247. //case D6_OPT_SERVERID:
  248. case D6_OPT_IA_NA:
  249. case D6_OPT_IA_PD:
  250. option_to_env(option + 16, option + 4 + option[3]);
  251. break;
  252. //case D6_OPT_IA_TA:
  253. case D6_OPT_IAADDR:
  254. /* 0 1 2 3
  255. * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  256. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  257. * | OPTION_IAADDR | option-len |
  258. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  259. * | |
  260. * | IPv6 address |
  261. * | |
  262. * | |
  263. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  264. * | preferred-lifetime |
  265. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  266. * | valid-lifetime |
  267. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  268. */
  269. /* Make sure payload contains an address */
  270. if (option[3] < 24)
  271. break;
  272. sprint_nip6(ipv6str, option + 4);
  273. *new_env() = xasprintf("ipv6=%s", ipv6str);
  274. move_from_unaligned32(v32, option + 4 + 16 + 4);
  275. v32 = ntohl(v32);
  276. *new_env() = xasprintf("lease=%u", (unsigned)v32);
  277. break;
  278. //case D6_OPT_ORO:
  279. //case D6_OPT_PREFERENCE:
  280. //case D6_OPT_ELAPSED_TIME:
  281. //case D6_OPT_RELAY_MSG:
  282. //case D6_OPT_AUTH:
  283. //case D6_OPT_UNICAST:
  284. //case D6_OPT_STATUS_CODE:
  285. //case D6_OPT_RAPID_COMMIT:
  286. //case D6_OPT_USER_CLASS:
  287. //case D6_OPT_VENDOR_CLASS:
  288. //case D6_OPT_VENDOR_OPTS:
  289. //case D6_OPT_INTERFACE_ID:
  290. //case D6_OPT_RECONF_MSG:
  291. //case D6_OPT_RECONF_ACCEPT:
  292. case D6_OPT_IAPREFIX:
  293. /* 0 1 2 3
  294. * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  295. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  296. * | OPTION_IAPREFIX | option-length |
  297. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  298. * | preferred-lifetime |
  299. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  300. * | valid-lifetime |
  301. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  302. * | prefix-length | |
  303. * +-+-+-+-+-+-+-+-+ IPv6 prefix |
  304. * | (16 octets) |
  305. * | |
  306. * | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  307. * | |
  308. * +-+-+-+-+-+-+-+-+
  309. */
  310. move_from_unaligned32(v32, option + 4 + 4);
  311. v32 = ntohl(v32);
  312. *new_env() = xasprintf("ipv6prefix_lease=%u", (unsigned)v32);
  313. sprint_nip6(ipv6str, option + 4 + 4 + 4 + 1);
  314. *new_env() = xasprintf("ipv6prefix=%s/%u", ipv6str, (unsigned)(option[4 + 4 + 4]));
  315. break;
  316. #if ENABLE_FEATURE_UDHCPC6_RFC3646
  317. case D6_OPT_DNS_SERVERS: {
  318. char *dlist;
  319. /* Make sure payload-size is a multiple of 16 */
  320. if ((option[3] & 0x0f) != 0)
  321. break;
  322. /* Get the number of addresses on the option */
  323. addrs = option[3] >> 4;
  324. /* Setup environment variable */
  325. *new_env() = dlist = xmalloc(4 + addrs * 40 - 1);
  326. dlist = stpcpy(dlist, "dns=");
  327. option_offset = 0;
  328. while (addrs--) {
  329. sprint_nip6(dlist, option + 4 + option_offset);
  330. dlist += 39;
  331. option_offset += 16;
  332. if (addrs)
  333. *dlist++ = ' ';
  334. }
  335. break;
  336. }
  337. case D6_OPT_DOMAIN_LIST: {
  338. char *dlist;
  339. dlist = dname_dec(option + 4, (option[2] << 8) | option[3], "search=");
  340. if (!dlist)
  341. break;
  342. *new_env() = dlist;
  343. break;
  344. }
  345. #endif
  346. #if ENABLE_FEATURE_UDHCPC6_RFC4704
  347. case D6_OPT_CLIENT_FQDN: {
  348. char *dlist;
  349. if (option[3] == 0)
  350. break;
  351. /* Work around broken ISC DHCPD6.
  352. * ISC DHCPD6 does not implement RFC 4704 correctly: It says the first
  353. * byte of option-payload should contain flags where the bits 7-3 are
  354. * reserved for future use and MUST be zero. Instead ISC DHCPD6 just
  355. * writes the entire FQDN as string to option-payload. We assume a
  356. * broken server here if any of the reserved bits are set.
  357. */
  358. if (option[4] & 0xf8) {
  359. *new_env() = xasprintf("fqdn=%.*s", (int)option[3], (char*)option + 4);
  360. break;
  361. }
  362. dlist = dname_dec(option + 5, (/*(option[2] << 8) |*/ option[3]) - 1, "fqdn=");
  363. if (!dlist)
  364. break;
  365. *new_env() = dlist;
  366. break;
  367. }
  368. #endif
  369. #if ENABLE_FEATURE_UDHCPC6_RFC4833
  370. /* RFC 4833 Timezones */
  371. case D6_OPT_TZ_POSIX:
  372. *new_env() = xasprintf("tz=%.*s", (int)option[3], (char*)option + 4);
  373. break;
  374. case D6_OPT_TZ_NAME:
  375. *new_env() = xasprintf("tz_name=%.*s", (int)option[3], (char*)option + 4);
  376. break;
  377. #endif
  378. case D6_OPT_BOOT_URL:
  379. case D6_OPT_BOOT_PARAM:
  380. case 0xd1: /* DHCP_PXE_CONF_FILE */
  381. case 0xd2: /* DHCP_PXE_PATH_PREFIX */
  382. {
  383. char *tmp = string_option_to_env(option, option_end);
  384. if (tmp)
  385. *new_env() = tmp;
  386. break;
  387. }
  388. }
  389. len_m4 -= 4 + option[3];
  390. option += 4 + option[3];
  391. }
  392. }
  393. static char **fill_envp(const uint8_t *option, const uint8_t *option_end)
  394. {
  395. char **envp, **curr;
  396. client6_data.env_ptr = NULL;
  397. client6_data.env_idx = 0;
  398. *new_env() = xasprintf("interface=%s", client_data.interface);
  399. if (option)
  400. option_to_env(option, option_end);
  401. envp = curr = client6_data.env_ptr;
  402. while (*curr)
  403. putenv(*curr++);
  404. return envp;
  405. }
  406. /* Call a script with env vars */
  407. static void d6_run_script(const uint8_t *option, const uint8_t *option_end,
  408. const char *name)
  409. {
  410. char **envp, **curr;
  411. char *argv[3];
  412. envp = fill_envp(option, option_end);
  413. /* call script */
  414. log1("executing %s %s", client_data.script, name);
  415. argv[0] = (char*) client_data.script;
  416. argv[1] = (char*) name;
  417. argv[2] = NULL;
  418. spawn_and_wait(argv);
  419. for (curr = envp; *curr; curr++) {
  420. log2(" %s", *curr);
  421. bb_unsetenv_and_free(*curr);
  422. }
  423. free(envp);
  424. }
  425. /* Call a script with no env var */
  426. static void d6_run_script_no_option(const char *name)
  427. {
  428. d6_run_script(NULL, NULL, name);
  429. }
  430. /*** Sending/receiving packets ***/
  431. static ALWAYS_INLINE uint32_t random_xid(void)
  432. {
  433. uint32_t t = rand() & htonl(0x00ffffff);
  434. return t;
  435. }
  436. /* Initialize the packet with the proper defaults */
  437. static uint8_t *init_d6_packet(struct d6_packet *packet, char type)
  438. {
  439. uint8_t *ptr;
  440. unsigned secs;
  441. memset(packet, 0, sizeof(*packet));
  442. packet->d6_xid32 = client_data.xid;
  443. packet->d6_msg_type = type; /* union, overwrites lowest byte of d6_xid32 */
  444. /* ELAPSED_TIME option is required to be present by the RFC,
  445. * and some servers do check for its presense. [which?]
  446. */
  447. ptr = packet->d6_options; /* NB: it is 32-bit aligned */
  448. *((uint32_t*)ptr) = htonl((D6_OPT_ELAPSED_TIME << 16) + 2);
  449. ptr += 4;
  450. client_data.last_secs = monotonic_sec();
  451. if (client_data.first_secs == 0)
  452. client_data.first_secs = client_data.last_secs;
  453. secs = client_data.last_secs - client_data.first_secs;
  454. *((uint16_t*)ptr) = (secs < 0xffff) ? htons(secs) : 0xffff;
  455. ptr += 2;
  456. return ptr;
  457. }
  458. static uint8_t *add_d6_client_options(uint8_t *ptr)
  459. {
  460. struct option_set *curr;
  461. uint8_t *start = ptr;
  462. unsigned option;
  463. uint16_t len;
  464. ptr += 4;
  465. for (option = 1; option < 256; option++) {
  466. if (client_data.opt_mask[option >> 3] & (1 << (option & 7))) {
  467. ptr[0] = (option >> 8);
  468. ptr[1] = option;
  469. ptr += 2;
  470. }
  471. }
  472. if ((ptr - start - 4) != 0) {
  473. start[0] = (D6_OPT_ORO >> 8);
  474. start[1] = D6_OPT_ORO;
  475. start[2] = ((ptr - start - 4) >> 8);
  476. start[3] = (ptr - start - 4);
  477. } else
  478. ptr = start;
  479. #if ENABLE_FEATURE_UDHCPC6_RFC4704
  480. ptr = mempcpy(ptr, &opt_fqdn_req, sizeof(opt_fqdn_req));
  481. #endif
  482. /* Add -x options if any */
  483. curr = client_data.options;
  484. while (curr) {
  485. len = (curr->data[D6_OPT_LEN] << 8) | curr->data[D6_OPT_LEN + 1];
  486. ptr = mempcpy(ptr, curr->data, D6_OPT_DATA + len);
  487. curr = curr->next;
  488. }
  489. return ptr;
  490. }
  491. static int d6_mcast_from_client_data_ifindex(struct d6_packet *packet, uint8_t *end)
  492. {
  493. /* FF02::1:2 is "All_DHCP_Relay_Agents_and_Servers" address */
  494. static const uint8_t FF02__1_2[16] ALIGNED(sizeof(long)) = {
  495. 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  496. 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02,
  497. };
  498. /* IPv6 requires different multicast contents in Ethernet Frame (RFC 2464) */
  499. static const uint8_t MAC_DHCP6MCAST_ADDR[6] ALIGN2 = {
  500. 0x33, 0x33, 0x00, 0x01, 0x00, 0x02,
  501. };
  502. return d6_send_raw_packet_from_client_data_ifindex(
  503. packet, (end - (uint8_t*) packet),
  504. /*src*/ &client6_data.ll_ip6, CLIENT_PORT6,
  505. /*dst*/ (struct in6_addr*)FF02__1_2, SERVER_PORT6, MAC_DHCP6MCAST_ADDR
  506. );
  507. }
  508. /* RFC 3315 18.1.5. Creation and Transmission of Information-request Messages
  509. *
  510. * The client uses an Information-request message to obtain
  511. * configuration information without having addresses assigned to it.
  512. *
  513. * The client sets the "msg-type" field to INFORMATION-REQUEST. The
  514. * client generates a transaction ID and inserts this value in the
  515. * "transaction-id" field.
  516. *
  517. * The client SHOULD include a Client Identifier option to identify
  518. * itself to the server. If the client does not include a Client
  519. * Identifier option, the server will not be able to return any client-
  520. * specific options to the client, or the server may choose not to
  521. * respond to the message at all. The client MUST include a Client
  522. * Identifier option if the Information-Request message will be
  523. * authenticated.
  524. *
  525. * The client MUST include an Option Request option (see section 22.7)
  526. * to indicate the options the client is interested in receiving. The
  527. * client MAY include options with data values as hints to the server
  528. * about parameter values the client would like to have returned.
  529. */
  530. /* NOINLINE: limit stack usage in caller */
  531. static NOINLINE int send_d6_info_request(void)
  532. {
  533. struct d6_packet packet;
  534. uint8_t *opt_ptr;
  535. /* Fill in: msg type, xid, ELAPSED_TIME */
  536. opt_ptr = init_d6_packet(&packet, D6_MSG_INFORMATION_REQUEST);
  537. /* Add options: client-id,
  538. * "param req" option according to -O, options specified with -x
  539. */
  540. opt_ptr = add_d6_client_options(opt_ptr);
  541. bb_error_msg("sending %s", "info request");
  542. return d6_mcast_from_client_data_ifindex(&packet, opt_ptr);
  543. }
  544. /* Multicast a DHCPv6 Solicit packet to the network, with an optionally requested IP.
  545. *
  546. * RFC 3315 17.1.1. Creation of Solicit Messages
  547. *
  548. * The client MUST include a Client Identifier option to identify itself
  549. * to the server. The client includes IA options for any IAs to which
  550. * it wants the server to assign addresses. The client MAY include
  551. * addresses in the IAs as a hint to the server about addresses for
  552. * which the client has a preference. ...
  553. *
  554. * The client uses IA_NA options to request the assignment of non-
  555. * temporary addresses and uses IA_TA options to request the assignment
  556. * of temporary addresses. Either IA_NA or IA_TA options, or a
  557. * combination of both, can be included in DHCP messages.
  558. *
  559. * The client SHOULD include an Option Request option (see section 22.7)
  560. * to indicate the options the client is interested in receiving. The
  561. * client MAY additionally include instances of those options that are
  562. * identified in the Option Request option, with data values as hints to
  563. * the server about parameter values the client would like to have
  564. * returned.
  565. *
  566. * The client includes a Reconfigure Accept option (see section 22.20)
  567. * if the client is willing to accept Reconfigure messages from the
  568. * server.
  569. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  570. | OPTION_CLIENTID | option-len |
  571. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  572. . .
  573. . DUID .
  574. . (variable length) .
  575. . .
  576. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  577. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  578. | OPTION_IA_NA | option-len |
  579. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  580. | IAID (4 octets) |
  581. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  582. | T1 |
  583. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  584. | T2 |
  585. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  586. | |
  587. . IA_NA-options .
  588. . .
  589. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  590. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  591. | OPTION_IAADDR | option-len |
  592. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  593. | |
  594. | IPv6 address |
  595. | |
  596. | |
  597. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  598. | preferred-lifetime |
  599. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  600. | valid-lifetime |
  601. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  602. . .
  603. . IAaddr-options .
  604. . .
  605. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  606. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  607. | OPTION_ORO | option-len |
  608. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  609. | requested-option-code-1 | requested-option-code-2 |
  610. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  611. | ... |
  612. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  613. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  614. | OPTION_RECONF_ACCEPT | 0 |
  615. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  616. */
  617. /* NOINLINE: limit stack usage in caller */
  618. static NOINLINE int send_d6_discover(struct in6_addr *requested_ipv6)
  619. {
  620. struct d6_packet packet;
  621. uint8_t *opt_ptr;
  622. unsigned len;
  623. /* Fill in: msg type, xid, ELAPSED_TIME */
  624. opt_ptr = init_d6_packet(&packet, D6_MSG_SOLICIT);
  625. /* Create new IA_NA, optionally with included IAADDR with requested IP */
  626. free(client6_data.ia_na);
  627. client6_data.ia_na = NULL;
  628. if (option_mask32 & OPT_r) {
  629. len = requested_ipv6 ? 2+2+4+4+4 + 2+2+16+4+4 : 2+2+4+4+4;
  630. client6_data.ia_na = xzalloc(len);
  631. client6_data.ia_na->code = D6_OPT_IA_NA;
  632. client6_data.ia_na->len = len - 4;
  633. *(bb__aliased_uint32_t*)client6_data.ia_na->data = rand(); /* IAID */
  634. if (requested_ipv6) {
  635. struct d6_option *iaaddr = (void*)(client6_data.ia_na->data + 4+4+4);
  636. iaaddr->code = D6_OPT_IAADDR;
  637. iaaddr->len = 16+4+4;
  638. memcpy(iaaddr->data, requested_ipv6, 16);
  639. }
  640. opt_ptr = mempcpy(opt_ptr, client6_data.ia_na, len);
  641. }
  642. /* IA_PD */
  643. free(client6_data.ia_pd);
  644. client6_data.ia_pd = NULL;
  645. if (option_mask32 & OPT_d) {
  646. len = 2+2+4+4+4;
  647. client6_data.ia_pd = xzalloc(len);
  648. client6_data.ia_pd->code = D6_OPT_IA_PD;
  649. client6_data.ia_pd->len = len - 4;
  650. *(bb__aliased_uint32_t*)client6_data.ia_pd->data = rand(); /* IAID */
  651. opt_ptr = mempcpy(opt_ptr, client6_data.ia_pd, len);
  652. }
  653. /* Add options: client-id,
  654. * "param req" option according to -O, options specified with -x
  655. */
  656. opt_ptr = add_d6_client_options(opt_ptr);
  657. bb_info_msg("sending %s", "discover");
  658. return d6_mcast_from_client_data_ifindex(&packet, opt_ptr);
  659. }
  660. /* Multicast a DHCPv6 request message
  661. *
  662. * RFC 3315 18.1.1. Creation and Transmission of Request Messages
  663. *
  664. * The client uses a Request message to populate IAs with addresses and
  665. * obtain other configuration information. The client includes one or
  666. * more IA options in the Request message. The server then returns
  667. * addresses and other information about the IAs to the client in IA
  668. * options in a Reply message.
  669. *
  670. * The client generates a transaction ID and inserts this value in the
  671. * "transaction-id" field.
  672. *
  673. * The client places the identifier of the destination server in a
  674. * Server Identifier option.
  675. *
  676. * The client MUST include a Client Identifier option to identify itself
  677. * to the server. The client adds any other appropriate options,
  678. * including one or more IA options (if the client is requesting that
  679. * the server assign it some network addresses).
  680. *
  681. * The client MUST include an Option Request option (see section 22.7)
  682. * to indicate the options the client is interested in receiving. The
  683. * client MAY include options with data values as hints to the server
  684. * about parameter values the client would like to have returned.
  685. *
  686. * The client includes a Reconfigure Accept option (see section 22.20)
  687. * indicating whether or not the client is willing to accept Reconfigure
  688. * messages from the server.
  689. */
  690. /* NOINLINE: limit stack usage in caller */
  691. static NOINLINE int send_d6_select(void)
  692. {
  693. struct d6_packet packet;
  694. uint8_t *opt_ptr;
  695. /* Fill in: msg type, xid, ELAPSED_TIME */
  696. opt_ptr = init_d6_packet(&packet, D6_MSG_REQUEST);
  697. /* server id */
  698. opt_ptr = mempcpy(opt_ptr, client6_data.server_id, client6_data.server_id->len + 2+2);
  699. /* IA NA (contains requested IP) */
  700. if (client6_data.ia_na)
  701. opt_ptr = mempcpy(opt_ptr, client6_data.ia_na, client6_data.ia_na->len + 2+2);
  702. /* IA PD */
  703. if (client6_data.ia_pd)
  704. opt_ptr = mempcpy(opt_ptr, client6_data.ia_pd, client6_data.ia_pd->len + 2+2);
  705. /* Add options: client-id,
  706. * "param req" option according to -O, options specified with -x
  707. */
  708. opt_ptr = add_d6_client_options(opt_ptr);
  709. bb_info_msg("sending %s", "select");
  710. return d6_mcast_from_client_data_ifindex(&packet, opt_ptr);
  711. }
  712. /* Unicast or broadcast a DHCP renew message
  713. *
  714. * RFC 3315 18.1.3. Creation and Transmission of Renew Messages
  715. *
  716. * To extend the valid and preferred lifetimes for the addresses
  717. * associated with an IA, the client sends a Renew message to the server
  718. * from which the client obtained the addresses in the IA containing an
  719. * IA option for the IA. The client includes IA Address options in the
  720. * IA option for the addresses associated with the IA. The server
  721. * determines new lifetimes for the addresses in the IA according to the
  722. * administrative configuration of the server. The server may also add
  723. * new addresses to the IA. The server may remove addresses from the IA
  724. * by setting the preferred and valid lifetimes of those addresses to
  725. * zero.
  726. *
  727. * The server controls the time at which the client contacts the server
  728. * to extend the lifetimes on assigned addresses through the T1 and T2
  729. * parameters assigned to an IA.
  730. *
  731. * At time T1 for an IA, the client initiates a Renew/Reply message
  732. * exchange to extend the lifetimes on any addresses in the IA. The
  733. * client includes an IA option with all addresses currently assigned to
  734. * the IA in its Renew message.
  735. *
  736. * If T1 or T2 is set to 0 by the server (for an IA_NA) or there are no
  737. * T1 or T2 times (for an IA_TA), the client may send a Renew or Rebind
  738. * message, respectively, at the client's discretion.
  739. *
  740. * The client sets the "msg-type" field to RENEW. The client generates
  741. * a transaction ID and inserts this value in the "transaction-id"
  742. * field.
  743. *
  744. * The client places the identifier of the destination server in a
  745. * Server Identifier option.
  746. *
  747. * The client MUST include a Client Identifier option to identify itself
  748. * to the server. The client adds any appropriate options, including
  749. * one or more IA options. The client MUST include the list of
  750. * addresses the client currently has associated with the IAs in the
  751. * Renew message.
  752. *
  753. * The client MUST include an Option Request option (see section 22.7)
  754. * to indicate the options the client is interested in receiving. The
  755. * client MAY include options with data values as hints to the server
  756. * about parameter values the client would like to have returned.
  757. */
  758. /* NOINLINE: limit stack usage in caller */
  759. static NOINLINE int send_d6_renew(struct in6_addr *server_ipv6, struct in6_addr *our_cur_ipv6)
  760. {
  761. struct d6_packet packet;
  762. uint8_t *opt_ptr;
  763. /* Fill in: msg type, xid, ELAPSED_TIME */
  764. opt_ptr = init_d6_packet(&packet, D6_MSG_RENEW);
  765. /* server id */
  766. opt_ptr = mempcpy(opt_ptr, client6_data.server_id, client6_data.server_id->len + 2+2);
  767. /* IA NA (contains requested IP) */
  768. if (client6_data.ia_na)
  769. opt_ptr = mempcpy(opt_ptr, client6_data.ia_na, client6_data.ia_na->len + 2+2);
  770. /* IA PD */
  771. if (client6_data.ia_pd)
  772. opt_ptr = mempcpy(opt_ptr, client6_data.ia_pd, client6_data.ia_pd->len + 2+2);
  773. /* Add options: client-id,
  774. * "param req" option according to -O, options specified with -x
  775. */
  776. opt_ptr = add_d6_client_options(opt_ptr);
  777. bb_info_msg("sending %s", "renew");
  778. if (server_ipv6)
  779. return d6_send_kernel_packet_from_client_data_ifindex(
  780. &packet, (opt_ptr - (uint8_t*) &packet),
  781. our_cur_ipv6, CLIENT_PORT6,
  782. server_ipv6, SERVER_PORT6
  783. );
  784. return d6_mcast_from_client_data_ifindex(&packet, opt_ptr);
  785. }
  786. /* Unicast a DHCP release message */
  787. static
  788. ALWAYS_INLINE /* one caller, help compiler to use this fact */
  789. int send_d6_release(struct in6_addr *server_ipv6, struct in6_addr *our_cur_ipv6)
  790. {
  791. struct d6_packet packet;
  792. uint8_t *opt_ptr;
  793. struct option_set *ci;
  794. /* Fill in: msg type, xid, ELAPSED_TIME */
  795. opt_ptr = init_d6_packet(&packet, D6_MSG_RELEASE);
  796. /* server id */
  797. opt_ptr = mempcpy(opt_ptr, client6_data.server_id, client6_data.server_id->len + 2+2);
  798. /* IA NA (contains our current IP) */
  799. if (client6_data.ia_na)
  800. opt_ptr = mempcpy(opt_ptr, client6_data.ia_na, client6_data.ia_na->len + 2+2);
  801. /* IA PD */
  802. if (client6_data.ia_pd)
  803. opt_ptr = mempcpy(opt_ptr, client6_data.ia_pd, client6_data.ia_pd->len + 2+2);
  804. /* Client-id */
  805. ci = udhcp_find_option(client_data.options, D6_OPT_CLIENTID, /*dhcpv6:*/ 1);
  806. if (ci)
  807. opt_ptr = mempcpy(opt_ptr, ci->data, D6_OPT_DATA + 2+2 + 6);
  808. bb_info_msg("sending %s", "release");
  809. return d6_send_kernel_packet_from_client_data_ifindex(
  810. &packet, (opt_ptr - (uint8_t*) &packet),
  811. our_cur_ipv6, CLIENT_PORT6,
  812. server_ipv6, SERVER_PORT6
  813. );
  814. }
  815. /* Returns -1 on errors that are fatal for the socket, -2 for those that aren't */
  816. /* NOINLINE: limit stack usage in caller */
  817. static NOINLINE int d6_recv_raw_packet(struct in6_addr *peer_ipv6, struct d6_packet *d6_pkt, int fd)
  818. {
  819. int bytes;
  820. struct ip6_udp_d6_packet packet;
  821. bytes = safe_read(fd, &packet, sizeof(packet));
  822. if (bytes < 0) {
  823. log1s("packet read error, ignoring");
  824. /* NB: possible down interface, etc. Caller should pause. */
  825. return bytes; /* returns -1 */
  826. }
  827. if (bytes < (int) (sizeof(packet.ip6) + sizeof(packet.udp))) {
  828. log1s("packet is too short, ignoring");
  829. return -2;
  830. }
  831. if (bytes < sizeof(packet.ip6) + ntohs(packet.ip6.ip6_plen)) {
  832. /* packet is bigger than sizeof(packet), we did partial read */
  833. log1s("oversized packet, ignoring");
  834. return -2;
  835. }
  836. /* ignore any extra garbage bytes */
  837. bytes = sizeof(packet.ip6) + ntohs(packet.ip6.ip6_plen);
  838. /* make sure its the right packet for us, and that it passes sanity checks */
  839. if (packet.ip6.ip6_nxt != IPPROTO_UDP
  840. || (packet.ip6.ip6_vfc >> 4) != 6
  841. || packet.udp.dest != htons(CLIENT_PORT6)
  842. /* || bytes > (int) sizeof(packet) - can't happen */
  843. || packet.udp.len != packet.ip6.ip6_plen
  844. ) {
  845. log1s("unrelated/bogus packet, ignoring");
  846. return -2;
  847. }
  848. //How to do this for ipv6?
  849. // /* verify UDP checksum. IP header has to be modified for this */
  850. // memset(&packet.ip, 0, offsetof(struct iphdr, protocol));
  851. // /* ip.xx fields which are not memset: protocol, check, saddr, daddr */
  852. // packet.ip.tot_len = packet.udp.len; /* yes, this is needed */
  853. // check = packet.udp.check;
  854. // packet.udp.check = 0;
  855. // if (check && check != inet_cksum(&packet, bytes)) {
  856. // log1("packet with bad UDP checksum received, ignoring");
  857. // return -2;
  858. // }
  859. if (peer_ipv6)
  860. *peer_ipv6 = packet.ip6.ip6_src; /* struct copy */
  861. log2("received %s", "a packet");
  862. /* log2 because more informative msg for valid packets is printed later at log1 level */
  863. d6_dump_packet(&packet.data);
  864. bytes -= sizeof(packet.ip6) + sizeof(packet.udp);
  865. memset(d6_pkt, 0, sizeof(*d6_pkt));
  866. memcpy(d6_pkt, &packet.data, bytes);
  867. return bytes;
  868. }
  869. /*** Main ***/
  870. /* Values for client_data.listen_mode */
  871. #define LISTEN_NONE 0
  872. #define LISTEN_KERNEL 1
  873. #define LISTEN_RAW 2
  874. /* Values for client_data.state */
  875. /* initial state: (re)start DHCP negotiation */
  876. #define INIT_SELECTING 0
  877. /* discover was sent, DHCPOFFER reply received */
  878. #define REQUESTING 1
  879. /* select/renew was sent, DHCPACK reply received */
  880. #define BOUND 2
  881. /* half of lease passed, want to renew it by sending unicast renew requests */
  882. #define RENEWING 3
  883. /* renew requests were not answered, lease is almost over, send broadcast renew */
  884. #define REBINDING 4
  885. /* manually requested renew (SIGUSR1) */
  886. #define RENEW_REQUESTED 5
  887. /* release, possibly manually requested (SIGUSR2) */
  888. #define RELEASED 6
  889. static int d6_raw_socket(int ifindex)
  890. {
  891. int fd;
  892. struct sockaddr_ll sock;
  893. /*
  894. * Comment:
  895. *
  896. * I've selected not to see LL header, so BPF doesn't see it, too.
  897. * The filter may also pass non-IP and non-ARP packets, but we do
  898. * a more complete check when receiving the message in userspace.
  899. *
  900. * and filter shamelessly stolen from:
  901. *
  902. * http://www.flamewarmaster.de/software/dhcpclient/
  903. *
  904. * There are a few other interesting ideas on that page (look under
  905. * "Motivation"). Use of netlink events is most interesting. Think
  906. * of various network servers listening for events and reconfiguring.
  907. * That would obsolete sending HUP signals and/or make use of restarts.
  908. *
  909. * Copyright: 2006, 2007 Stefan Rompf <sux@loplof.de>.
  910. * License: GPL v2.
  911. *
  912. * TODO: make conditional?
  913. */
  914. #if 0
  915. static const struct sock_filter filter_instr[] = {
  916. /* load 9th byte (protocol) */
  917. BPF_STMT(BPF_LD|BPF_B|BPF_ABS, 9),
  918. /* jump to L1 if it is IPPROTO_UDP, else to L4 */
  919. BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, IPPROTO_UDP, 0, 6),
  920. /* L1: load halfword from offset 6 (flags and frag offset) */
  921. BPF_STMT(BPF_LD|BPF_H|BPF_ABS, 6),
  922. /* jump to L4 if any bits in frag offset field are set, else to L2 */
  923. BPF_JUMP(BPF_JMP|BPF_JSET|BPF_K, 0x1fff, 4, 0),
  924. /* L2: skip IP header (load index reg with header len) */
  925. BPF_STMT(BPF_LDX|BPF_B|BPF_MSH, 0),
  926. /* load udp destination port from halfword[header_len + 2] */
  927. BPF_STMT(BPF_LD|BPF_H|BPF_IND, 2),
  928. /* jump to L3 if udp dport is CLIENT_PORT6, else to L4 */
  929. BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 68, 0, 1),
  930. /* L3: accept packet */
  931. BPF_STMT(BPF_RET|BPF_K, 0x7fffffff),
  932. /* L4: discard packet */
  933. BPF_STMT(BPF_RET|BPF_K, 0),
  934. };
  935. static const struct sock_fprog filter_prog = {
  936. .len = sizeof(filter_instr) / sizeof(filter_instr[0]),
  937. /* casting const away: */
  938. .filter = (struct sock_filter *) filter_instr,
  939. };
  940. #endif
  941. log2("opening raw socket on ifindex %d", ifindex);
  942. fd = xsocket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IPV6));
  943. memset(&sock, 0, sizeof(sock)); /* let's be deterministic */
  944. sock.sll_family = AF_PACKET;
  945. sock.sll_protocol = htons(ETH_P_IPV6);
  946. sock.sll_ifindex = ifindex;
  947. /*sock.sll_hatype = ARPHRD_???;*/
  948. /*sock.sll_pkttype = PACKET_???;*/
  949. /*sock.sll_halen = ???;*/
  950. /*sock.sll_addr[8] = ???;*/
  951. xbind(fd, (struct sockaddr *) &sock, sizeof(sock));
  952. #if 0
  953. if (CLIENT_PORT6 == 546) {
  954. /* Use only if standard port is in use */
  955. /* Ignoring error (kernel may lack support for this) */
  956. if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter_prog,
  957. sizeof(filter_prog)) >= 0)
  958. log1("attached filter to raw socket fd %d", fd); // log?
  959. }
  960. #endif
  961. return fd;
  962. }
  963. static void change_listen_mode(int new_mode)
  964. {
  965. log1("entering listen mode: %s",
  966. new_mode != LISTEN_NONE
  967. ? (new_mode == LISTEN_KERNEL ? "kernel" : "raw")
  968. : "none"
  969. );
  970. client_data.listen_mode = new_mode;
  971. if (client_data.sockfd >= 0) {
  972. close(client_data.sockfd);
  973. client_data.sockfd = -1;
  974. }
  975. if (new_mode == LISTEN_KERNEL)
  976. client_data.sockfd = d6_listen_socket(CLIENT_PORT6, client_data.interface);
  977. else if (new_mode != LISTEN_NONE)
  978. client_data.sockfd = d6_raw_socket(client_data.ifindex);
  979. /* else LISTEN_NONE: client_data.sockfd stays closed */
  980. }
  981. static void perform_d6_release(struct in6_addr *server_ipv6, struct in6_addr *our_cur_ipv6)
  982. {
  983. change_listen_mode(LISTEN_NONE);
  984. /* send release packet */
  985. if (client_data.state == BOUND
  986. || client_data.state == RENEWING
  987. || client_data.state == REBINDING
  988. || client_data.state == RENEW_REQUESTED
  989. ) {
  990. bb_simple_info_msg("unicasting a release");
  991. client_data.xid = random_xid(); //TODO: can omit?
  992. send_d6_release(server_ipv6, our_cur_ipv6); /* unicast */
  993. }
  994. bb_simple_info_msg("entering released state");
  995. /*
  996. * We can be here on: SIGUSR2,
  997. * or on exit (SIGTERM) and -R "release on quit" is specified.
  998. * Users requested to be notified in all cases, even if not in one
  999. * of the states above.
  1000. */
  1001. d6_run_script_no_option("deconfig");
  1002. client_data.state = RELEASED;
  1003. }
  1004. #if BB_MMU
  1005. static void client_background(void)
  1006. {
  1007. bb_daemonize(0);
  1008. logmode &= ~LOGMODE_STDIO;
  1009. /* rewrite pidfile, as our pid is different now */
  1010. write_pidfile(client_data.pidfile);
  1011. }
  1012. #endif
  1013. //usage:#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1
  1014. //usage:# define IF_UDHCP_VERBOSE(...) __VA_ARGS__
  1015. //usage:#else
  1016. //usage:# define IF_UDHCP_VERBOSE(...)
  1017. //usage:#endif
  1018. //usage:#define udhcpc6_trivial_usage
  1019. //usage: "[-fbq"IF_UDHCP_VERBOSE("v")"R] [-t N] [-T SEC] [-A SEC|-n] [-i IFACE] [-s PROG]\n"
  1020. //usage: " [-p PIDFILE]"IF_FEATURE_UDHCP_PORT(" [-P PORT]")" [-ldo] [-r IPv6] [-x OPT:VAL]... [-O OPT]..."
  1021. //usage:#define udhcpc6_full_usage "\n"
  1022. //usage: "\n -i IFACE Interface to use (default "CONFIG_UDHCPC_DEFAULT_INTERFACE")"
  1023. //usage: "\n -p FILE Create pidfile"
  1024. //usage: "\n -s PROG Run PROG at DHCP events (default "CONFIG_UDHCPC6_DEFAULT_SCRIPT")"
  1025. //usage: "\n -B Request broadcast replies"
  1026. //usage: "\n -t N Send up to N discover packets"
  1027. //usage: "\n -T SEC Pause between packets (default 3)"
  1028. //usage: "\n -A SEC Wait if lease is not obtained (default 20)"
  1029. //usage: USE_FOR_MMU(
  1030. //usage: "\n -b Background if lease is not obtained"
  1031. //usage: )
  1032. //usage: "\n -n Exit if lease is not obtained"
  1033. //usage: "\n -q Exit after obtaining lease"
  1034. //usage: "\n -R Release IP on exit"
  1035. //usage: "\n -f Run in foreground"
  1036. //usage: "\n -S Log to syslog too"
  1037. //usage: IF_FEATURE_UDHCP_PORT(
  1038. //usage: "\n -P PORT Use PORT (default 546)"
  1039. //usage: )
  1040. ////usage: IF_FEATURE_UDHCPC_ARPING(
  1041. ////usage: "\n -a Use arping to validate offered address"
  1042. ////usage: )
  1043. //usage: "\n -l Send 'information request' instead of 'solicit'"
  1044. //usage: "\n (used for servers which do not assign IPv6 addresses)"
  1045. //usage: "\n -r IPv6 Request this address ('no' to not request any IP)"
  1046. //usage: "\n -d Request prefix"
  1047. //usage: "\n -o Don't request any options (unless -O is given)"
  1048. //usage: "\n -O OPT Request option OPT from server (cumulative)"
  1049. //usage: "\n -x OPT:VAL Include option OPT in sent packets (cumulative)"
  1050. //usage: "\n Examples of string, numeric, and hex byte opts:"
  1051. //usage: "\n -x hostname:bbox - option 12"
  1052. //usage: "\n -x lease:3600 - option 51 (lease time)"
  1053. //usage: "\n -x 0x3d:0100BEEFC0FFEE - option 61 (client id)"
  1054. //usage: "\n -x 14:'\"dumpfile\"' - option 14 (shell-quoted)"
  1055. //usage: IF_UDHCP_VERBOSE(
  1056. //usage: "\n -v Verbose"
  1057. //usage: )
  1058. //usage: "\nSignals:"
  1059. //usage: "\n USR1 Renew lease"
  1060. //usage: "\n USR2 Release lease"
  1061. int udhcpc6_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  1062. int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
  1063. {
  1064. const char *str_r;
  1065. IF_FEATURE_UDHCP_PORT(char *str_P;)
  1066. uint8_t *clientid_mac_ptr;
  1067. llist_t *list_O = NULL;
  1068. llist_t *list_x = NULL;
  1069. int tryagain_timeout = 20;
  1070. int discover_timeout = 3;
  1071. int discover_retries = 3;
  1072. struct in6_addr srv6_buf;
  1073. struct in6_addr ipv6_buf;
  1074. struct in6_addr *requested_ipv6;
  1075. int packet_num;
  1076. int timeout; /* must be signed */
  1077. int lease_remaining; /* must be signed */
  1078. unsigned opt;
  1079. int retval;
  1080. setup_common_bufsiz();
  1081. /* We want random_xid to be random */
  1082. srand(monotonic_us());
  1083. /* Default options */
  1084. IF_FEATURE_UDHCP_PORT(SERVER_PORT6 = 547;)
  1085. IF_FEATURE_UDHCP_PORT(CLIENT_PORT6 = 546;)
  1086. client_data.interface = CONFIG_UDHCPC_DEFAULT_INTERFACE;
  1087. client_data.script = CONFIG_UDHCPC6_DEFAULT_SCRIPT;
  1088. client_data.sockfd = -1;
  1089. /* Make sure fd 0,1,2 are open */
  1090. /* Set up the signal pipe on fds 3,4 - must be before openlog() */
  1091. udhcp_sp_setup();
  1092. /* Parse command line */
  1093. opt = getopt32long(argv, "^"
  1094. /* O,x: list; -T,-t,-A take numeric param */
  1095. "i:np:qRr:s:T:+t:+SA:+O:*ox:*fld"
  1096. USE_FOR_MMU("b")
  1097. ///IF_FEATURE_UDHCPC_ARPING("a")
  1098. IF_FEATURE_UDHCP_PORT("P:")
  1099. "v"
  1100. "\0" IF_UDHCP_VERBOSE("vv") /* -v is a counter */
  1101. , udhcpc6_longopts
  1102. , &client_data.interface, &client_data.pidfile, &str_r /* i,p */
  1103. , &client_data.script /* s */
  1104. , &discover_timeout, &discover_retries, &tryagain_timeout /* T,t,A */
  1105. , &list_O
  1106. , &list_x
  1107. IF_FEATURE_UDHCP_PORT(, &str_P)
  1108. IF_UDHCP_VERBOSE(, &dhcp_verbose)
  1109. );
  1110. requested_ipv6 = NULL;
  1111. option_mask32 |= OPT_r;
  1112. if (opt & OPT_l) {
  1113. /* for -l, do not require IPv6 assignment from server */
  1114. option_mask32 &= ~OPT_r;
  1115. } else if (opt & OPT_r) {
  1116. /* explicit "-r ARG" given */
  1117. if (strcmp(str_r, "no") == 0) {
  1118. option_mask32 &= ~OPT_r;
  1119. } else {
  1120. if (inet_pton(AF_INET6, str_r, &ipv6_buf) <= 0)
  1121. bb_error_msg_and_die("bad IPv6 address '%s'", str_r);
  1122. requested_ipv6 = &ipv6_buf;
  1123. }
  1124. }
  1125. #if ENABLE_FEATURE_UDHCP_PORT
  1126. if (opt & OPT_P) {
  1127. CLIENT_PORT6 = xatou16(str_P);
  1128. SERVER_PORT6 = CLIENT_PORT6 + 1;
  1129. }
  1130. #endif
  1131. while (list_O) {
  1132. char *optstr = llist_pop(&list_O);
  1133. unsigned n = bb_strtou(optstr, NULL, 0);
  1134. if (errno || n > 254) {
  1135. n = udhcp_option_idx(optstr, d6_option_strings);
  1136. n = d6_optflags[n].code;
  1137. }
  1138. client_data.opt_mask[n >> 3] |= 1 << (n & 7);
  1139. }
  1140. if (!(opt & OPT_o)) {
  1141. unsigned i, n;
  1142. for (i = 0; (n = d6_optflags[i].code) != 0; i++) {
  1143. if (d6_optflags[i].flags & OPTION_REQ) {
  1144. client_data.opt_mask[n >> 3] |= 1 << (n & 7);
  1145. }
  1146. }
  1147. }
  1148. while (list_x) {
  1149. char *optstr = xstrdup(llist_pop(&list_x));
  1150. udhcp_str2optset(optstr, &client_data.options,
  1151. d6_optflags, d6_option_strings,
  1152. /*dhcpv6:*/ 1
  1153. );
  1154. free(optstr);
  1155. }
  1156. clientid_mac_ptr = NULL;
  1157. if (!udhcp_find_option(client_data.options, D6_OPT_CLIENTID, /*dhcpv6:*/ 1)) {
  1158. /* not set, set the default client ID */
  1159. clientid_mac_ptr = udhcp_insert_new_option(
  1160. &client_data.options, D6_OPT_CLIENTID,
  1161. 2+2 + 6, /*dhcp6:*/ 1);
  1162. clientid_mac_ptr += 2+2; /* skip option code, len */
  1163. clientid_mac_ptr[1] = 3; /* DUID-LL */
  1164. clientid_mac_ptr[3] = 1; /* type: ethernet */
  1165. clientid_mac_ptr += 2+2; /* skip DUID-LL, ethernet */
  1166. }
  1167. if (d6_read_interface(client_data.interface,
  1168. &client_data.ifindex,
  1169. &client6_data.ll_ip6,
  1170. client_data.client_mac)
  1171. ) {
  1172. return 1;
  1173. }
  1174. #if !BB_MMU
  1175. /* on NOMMU reexec (i.e., background) early */
  1176. if (!(opt & OPT_f)) {
  1177. bb_daemonize_or_rexec(0 /* flags */, argv);
  1178. logmode = LOGMODE_NONE;
  1179. }
  1180. #endif
  1181. if (opt & OPT_S) {
  1182. openlog(applet_name, LOG_PID, LOG_DAEMON);
  1183. logmode |= LOGMODE_SYSLOG;
  1184. }
  1185. /* Create pidfile */
  1186. write_pidfile(client_data.pidfile);
  1187. /* Goes to stdout (unless NOMMU) and possibly syslog */
  1188. bb_simple_info_msg("started, v"BB_VER);
  1189. client_data.state = INIT_SELECTING;
  1190. d6_run_script_no_option("deconfig");
  1191. packet_num = 0;
  1192. timeout = 0;
  1193. lease_remaining = 0;
  1194. /* Main event loop. select() waits on signal pipe and possibly
  1195. * on sockfd.
  1196. * "continue" statements in code below jump to the top of the loop.
  1197. */
  1198. for (;;) {
  1199. struct pollfd pfds[2];
  1200. struct d6_packet packet;
  1201. uint8_t *packet_end;
  1202. //bb_error_msg("sockfd:%d, listen_mode:%d", client_data.sockfd, client_data.listen_mode);
  1203. /* Was opening raw or udp socket here
  1204. * if (client_data.listen_mode != LISTEN_NONE && client_data.sockfd < 0),
  1205. * but on fast network renew responses return faster
  1206. * than we open sockets. Thus this code is moved
  1207. * to change_listen_mode(). Thus we open listen socket
  1208. * BEFORE we send renew request (see "case BOUND:"). */
  1209. udhcp_sp_fd_set(pfds, client_data.sockfd);
  1210. retval = 0;
  1211. /* If we already timed out, fall through with retval = 0, else... */
  1212. if (timeout > 0) {
  1213. unsigned diff;
  1214. if (timeout > INT_MAX/1000)
  1215. timeout = INT_MAX/1000;
  1216. log1("waiting %u seconds", timeout);
  1217. diff = (unsigned)monotonic_sec();
  1218. retval = poll(pfds, 2, timeout * 1000);
  1219. diff = (unsigned)monotonic_sec() - diff;
  1220. lease_remaining -= diff;
  1221. if (lease_remaining < 0)
  1222. lease_remaining = 0;
  1223. timeout -= diff;
  1224. if (timeout < 0)
  1225. timeout = 0;
  1226. if (retval < 0) {
  1227. /* EINTR? A signal was caught, don't panic */
  1228. if (errno == EINTR) {
  1229. continue;
  1230. }
  1231. /* Else: an error occured, panic! */
  1232. bb_simple_perror_msg_and_die("poll");
  1233. }
  1234. }
  1235. /* If timeout dropped to zero, time to become active:
  1236. * resend discover/renew/whatever
  1237. */
  1238. if (retval == 0) {
  1239. /* When running on a bridge, the ifindex may have changed
  1240. * (e.g. if member interfaces were added/removed
  1241. * or if the status of the bridge changed).
  1242. * Refresh ifindex and client_mac:
  1243. */
  1244. if (d6_read_interface(client_data.interface,
  1245. &client_data.ifindex,
  1246. &client6_data.ll_ip6,
  1247. client_data.client_mac)
  1248. ) {
  1249. goto ret0; /* iface is gone? */
  1250. }
  1251. if (clientid_mac_ptr)
  1252. memcpy(clientid_mac_ptr, client_data.client_mac, 6);
  1253. switch (client_data.state) {
  1254. case INIT_SELECTING:
  1255. if (!discover_retries || packet_num < discover_retries) {
  1256. if (packet_num == 0) {
  1257. change_listen_mode(LISTEN_RAW);
  1258. client_data.xid = random_xid();
  1259. }
  1260. /* multicast */
  1261. if (opt & OPT_l)
  1262. send_d6_info_request();
  1263. else
  1264. send_d6_discover(requested_ipv6);
  1265. timeout = discover_timeout;
  1266. packet_num++;
  1267. continue;
  1268. }
  1269. leasefail:
  1270. change_listen_mode(LISTEN_NONE);
  1271. d6_run_script_no_option("leasefail");
  1272. #if BB_MMU /* -b is not supported on NOMMU */
  1273. if (opt & OPT_b) { /* background if no lease */
  1274. bb_simple_info_msg("no lease, forking to background");
  1275. client_background();
  1276. /* do not background again! */
  1277. opt = ((opt & ~(OPT_b|OPT_n)) | OPT_f);
  1278. /* ^^^ also disables -n (-b takes priority over -n):
  1279. * ifup's default udhcpc options are -R -n,
  1280. * and users want to be able to add -b
  1281. * (in a config file) to make it background
  1282. * _and not exit_.
  1283. */
  1284. } else
  1285. #endif
  1286. if (opt & OPT_n) { /* abort if no lease */
  1287. bb_simple_info_msg("no lease, failing");
  1288. retval = 1;
  1289. goto ret;
  1290. }
  1291. /* Wait before trying again */
  1292. timeout = tryagain_timeout;
  1293. packet_num = 0;
  1294. continue;
  1295. case REQUESTING:
  1296. if (!discover_retries || packet_num < discover_retries) {
  1297. /* send multicast select packet */
  1298. send_d6_select();
  1299. timeout = discover_timeout;
  1300. packet_num++;
  1301. continue;
  1302. }
  1303. /* Timed out, go back to init state.
  1304. * "discover...select...discover..." loops
  1305. * were seen in the wild. Treat them similarly
  1306. * to "no response to discover" case */
  1307. client_data.state = INIT_SELECTING;
  1308. goto leasefail;
  1309. case BOUND:
  1310. /* 1/2 lease passed, enter renewing state */
  1311. client_data.state = RENEWING;
  1312. client_data.first_secs = 0; /* make secs field count from 0 */
  1313. got_SIGUSR1:
  1314. log1s("entering renew state");
  1315. change_listen_mode(LISTEN_KERNEL);
  1316. /* fall right through */
  1317. case RENEW_REQUESTED: /* in manual (SIGUSR1) renew */
  1318. case RENEWING:
  1319. if (packet_num == 0) {
  1320. /* Send an unicast renew request */
  1321. /* Sometimes observed to fail (EADDRNOTAVAIL) to bind
  1322. * a new UDP socket for sending inside send_renew.
  1323. * I hazard to guess existing listening socket
  1324. * is somehow conflicting with it, but why is it
  1325. * not deterministic then?! Strange.
  1326. * Anyway, it does recover by eventually failing through
  1327. * into INIT_SELECTING state.
  1328. */
  1329. if (opt & OPT_l)
  1330. send_d6_info_request();
  1331. else
  1332. send_d6_renew(&srv6_buf, requested_ipv6);
  1333. timeout = discover_timeout;
  1334. packet_num++;
  1335. continue;
  1336. } /* else: we had sent one packet, but got no reply */
  1337. log1s("no response to renew");
  1338. if (lease_remaining > 30) {
  1339. /* Some lease time remains, try to renew later */
  1340. change_listen_mode(LISTEN_NONE);
  1341. goto BOUND_for_half_lease;
  1342. }
  1343. /* Enter rebinding state */
  1344. client_data.state = REBINDING;
  1345. log1s("entering rebinding state");
  1346. /* Switch to bcast receive */
  1347. change_listen_mode(LISTEN_RAW);
  1348. packet_num = 0;
  1349. /* fall right through */
  1350. case REBINDING:
  1351. /* Lease is *really* about to run out,
  1352. * try to find DHCP server using broadcast */
  1353. if (lease_remaining > 0 && packet_num < 3) {
  1354. if (opt & OPT_l)
  1355. send_d6_info_request();
  1356. else /* send a broadcast renew request */
  1357. //TODO: send_d6_renew uses D6_MSG_RENEW message, should we use D6_MSG_REBIND here instead?
  1358. send_d6_renew(/*server_ipv6:*/ NULL, requested_ipv6);
  1359. timeout = discover_timeout;
  1360. packet_num++;
  1361. continue;
  1362. }
  1363. /* Timed out, enter init state */
  1364. change_listen_mode(LISTEN_NONE);
  1365. bb_simple_info_msg("lease lost, entering init state");
  1366. d6_run_script_no_option("deconfig");
  1367. client_data.state = INIT_SELECTING;
  1368. client_data.first_secs = 0; /* make secs field count from 0 */
  1369. timeout = 0;
  1370. packet_num = 0;
  1371. continue;
  1372. /* case RELEASED: */
  1373. }
  1374. /* RELEASED state (when we got SIGUSR2) ends up here.
  1375. * (wait for SIGUSR1 to re-init, or for TERM, etc)
  1376. */
  1377. timeout = INT_MAX;
  1378. continue; /* back to main loop */
  1379. } /* if poll timed out */
  1380. /* poll() didn't timeout, something happened */
  1381. /* Is it a signal? */
  1382. switch (udhcp_sp_read()) {
  1383. case SIGUSR1:
  1384. if (client_data.state <= REQUESTING)
  1385. /* Initial negotiations in progress, do not disturb */
  1386. break;
  1387. if (client_data.state == REBINDING)
  1388. /* Do not go back from rebind to renew state */
  1389. break;
  1390. if (lease_remaining > 30) /* if renew fails, do not go back to BOUND */
  1391. lease_remaining = 30;
  1392. client_data.first_secs = 0; /* make secs field count from 0 */
  1393. packet_num = 0;
  1394. switch (client_data.state) {
  1395. case BOUND:
  1396. case RENEWING:
  1397. /* Try to renew/rebind */
  1398. change_listen_mode(LISTEN_KERNEL);
  1399. client_data.state = RENEW_REQUESTED;
  1400. goto got_SIGUSR1;
  1401. case RENEW_REQUESTED:
  1402. /* Two SIGUSR1 received, start things over */
  1403. change_listen_mode(LISTEN_NONE);
  1404. d6_run_script_no_option("deconfig");
  1405. default:
  1406. /* case RELEASED: */
  1407. /* Wake from SIGUSR2-induced deconfigured state */
  1408. change_listen_mode(LISTEN_NONE);
  1409. }
  1410. client_data.state = INIT_SELECTING;
  1411. /* Kill any timeouts, user wants this to hurry along */
  1412. timeout = 0;
  1413. continue;
  1414. case SIGUSR2:
  1415. perform_d6_release(&srv6_buf, requested_ipv6);
  1416. /* ^^^ switches to LISTEN_NONE */
  1417. timeout = INT_MAX;
  1418. continue;
  1419. case SIGTERM:
  1420. bb_info_msg("received %s", "SIGTERM");
  1421. goto ret0;
  1422. }
  1423. /* Is it a packet? */
  1424. if (!pfds[1].revents)
  1425. continue; /* no */
  1426. {
  1427. int len;
  1428. /* A packet is ready, read it */
  1429. if (client_data.listen_mode == LISTEN_KERNEL)
  1430. len = d6_recv_kernel_packet(&srv6_buf, &packet, client_data.sockfd);
  1431. else
  1432. len = d6_recv_raw_packet(&srv6_buf, &packet, client_data.sockfd);
  1433. if (len == -1) {
  1434. /* Error is severe, reopen socket */
  1435. bb_error_msg("read error: "STRERROR_FMT", reopening socket" STRERROR_ERRNO);
  1436. sleep(discover_timeout); /* 3 seconds by default */
  1437. change_listen_mode(client_data.listen_mode); /* just close and reopen */
  1438. }
  1439. if (len < 0)
  1440. continue;
  1441. packet_end = (uint8_t*)&packet + len;
  1442. }
  1443. if ((packet.d6_xid32 & htonl(0x00ffffff)) != client_data.xid) {
  1444. log1("xid %x (our is %x)%s",
  1445. (unsigned)(packet.d6_xid32 & htonl(0x00ffffff)), (unsigned)client_data.xid,
  1446. ", ignoring packet"
  1447. );
  1448. continue;
  1449. }
  1450. switch (client_data.state) {
  1451. case INIT_SELECTING:
  1452. if (packet.d6_msg_type == D6_MSG_ADVERTISE)
  1453. goto type_is_ok;
  1454. /* DHCPv6 has "Rapid Commit", when instead of Advertise,
  1455. * server sends Reply right away.
  1456. * Fall through to check for this case.
  1457. */
  1458. case REQUESTING:
  1459. case RENEWING:
  1460. case RENEW_REQUESTED:
  1461. case REBINDING:
  1462. if (packet.d6_msg_type == D6_MSG_REPLY) {
  1463. unsigned start;
  1464. uint32_t lease_seconds;
  1465. struct d6_option *option;
  1466. unsigned address_timeout;
  1467. unsigned prefix_timeout;
  1468. type_is_ok:
  1469. change_listen_mode(LISTEN_NONE);
  1470. address_timeout = 0;
  1471. prefix_timeout = 0;
  1472. option = d6_find_option(packet.d6_options, packet_end, D6_OPT_STATUS_CODE);
  1473. if (option && (option->data[0] | option->data[1]) != 0) {
  1474. ///FIXME:
  1475. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  1476. // | OPTION_STATUS_CODE | option-len |
  1477. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  1478. // | status-code | |
  1479. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
  1480. // . status-message .
  1481. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  1482. // so why do we think it's NAK if data[0] is zero but data[1] is not? That's wrong...
  1483. // we should also check that option->len is ok (i.e. not 0), right?
  1484. /* return to init state */
  1485. bb_info_msg("received DHCP NAK (%u)", option->data[4]);
  1486. d6_run_script(packet.d6_options,
  1487. packet_end, "nak");
  1488. if (client_data.state != REQUESTING)
  1489. d6_run_script_no_option("deconfig");
  1490. sleep(3); /* avoid excessive network traffic */
  1491. client_data.state = INIT_SELECTING;
  1492. client_data.first_secs = 0; /* make secs field count from 0 */
  1493. requested_ipv6 = NULL;
  1494. timeout = 0;
  1495. packet_num = 0;
  1496. continue;
  1497. }
  1498. option = d6_copy_option(packet.d6_options, packet_end, D6_OPT_SERVERID);
  1499. if (!option) {
  1500. bb_simple_info_msg("no server ID, ignoring packet");
  1501. continue;
  1502. /* still selecting - this server looks bad */
  1503. }
  1504. //Note: we do not bother comparing server IDs in Advertise and Reply msgs.
  1505. //server_id variable is used solely for creation of proper server_id option
  1506. //in outgoing packets. (why DHCPv6 even introduced it is a mystery).
  1507. free(client6_data.server_id);
  1508. client6_data.server_id = option;
  1509. if (packet.d6_msg_type == D6_MSG_ADVERTISE) {
  1510. /* enter requesting state */
  1511. change_listen_mode(LISTEN_RAW);
  1512. client_data.state = REQUESTING;
  1513. timeout = 0;
  1514. packet_num = 0;
  1515. continue;
  1516. }
  1517. /* It's a D6_MSG_REPLY */
  1518. /*
  1519. * RFC 3315 18.1.8. Receipt of Reply Messages
  1520. *
  1521. * Upon the receipt of a valid Reply message in response to a Solicit
  1522. * (with a Rapid Commit option), Request, Confirm, Renew, Rebind or
  1523. * Information-request message, the client extracts the configuration
  1524. * information contained in the Reply. The client MAY choose to report
  1525. * any status code or message from the status code option in the Reply
  1526. * message.
  1527. *
  1528. * The client SHOULD perform duplicate address detection [17] on each of
  1529. * the addresses in any IAs it receives in the Reply message before
  1530. * using that address for traffic. If any of the addresses are found to
  1531. * be in use on the link, the client sends a Decline message to the
  1532. * server as described in section 18.1.7.
  1533. *
  1534. * If the Reply was received in response to a Solicit (with a Rapid
  1535. * Commit option), Request, Renew or Rebind message, the client updates
  1536. * the information it has recorded about IAs from the IA options
  1537. * contained in the Reply message:
  1538. *
  1539. * - Record T1 and T2 times.
  1540. *
  1541. * - Add any new addresses in the IA option to the IA as recorded by
  1542. * the client.
  1543. *
  1544. * - Update lifetimes for any addresses in the IA option that the
  1545. * client already has recorded in the IA.
  1546. *
  1547. * - Discard any addresses from the IA, as recorded by the client, that
  1548. * have a valid lifetime of 0 in the IA Address option.
  1549. *
  1550. * - Leave unchanged any information about addresses the client has
  1551. * recorded in the IA but that were not included in the IA from the
  1552. * server.
  1553. *
  1554. * Management of the specific configuration information is detailed in
  1555. * the definition of each option in section 22.
  1556. *
  1557. * If the client receives a Reply message with a Status Code containing
  1558. * UnspecFail, the server is indicating that it was unable to process
  1559. * the message due to an unspecified failure condition. If the client
  1560. * retransmits the original message to the same server to retry the
  1561. * desired operation, the client MUST limit the rate at which it
  1562. * retransmits the message and limit the duration of the time during
  1563. * which it retransmits the message.
  1564. *
  1565. * When the client receives a Reply message with a Status Code option
  1566. * with the value UseMulticast, the client records the receipt of the
  1567. * message and sends subsequent messages to the server through the
  1568. * interface on which the message was received using multicast. The
  1569. * client resends the original message using multicast.
  1570. *
  1571. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  1572. * | OPTION_IA_NA | option-len |
  1573. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  1574. * | IAID (4 octets) |
  1575. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  1576. * | T1 |
  1577. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  1578. * | T2 |
  1579. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  1580. * | |
  1581. * . IA_NA-options .
  1582. * . .
  1583. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  1584. *
  1585. *
  1586. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  1587. * | OPTION_IAADDR | option-len |
  1588. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  1589. * | |
  1590. * | IPv6 address |
  1591. * | |
  1592. * | |
  1593. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  1594. * | preferred-lifetime |
  1595. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  1596. * | valid-lifetime |
  1597. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  1598. * . .
  1599. * . IAaddr-options .
  1600. * . .
  1601. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  1602. */
  1603. if (option_mask32 & OPT_r) {
  1604. struct d6_option *iaaddr;
  1605. free(client6_data.ia_na);
  1606. client6_data.ia_na = d6_copy_option(packet.d6_options, packet_end, D6_OPT_IA_NA);
  1607. if (!client6_data.ia_na) {
  1608. bb_info_msg("no %s option%s", "IA_NA", ", ignoring packet");
  1609. continue;
  1610. }
  1611. if (client6_data.ia_na->len < (4 + 4 + 4) + (2 + 2 + 16 + 4 + 4)) {
  1612. bb_info_msg("%s option is too short:%d bytes",
  1613. "IA_NA", client6_data.ia_na->len);
  1614. continue;
  1615. }
  1616. iaaddr = d6_find_option(client6_data.ia_na->data + 4 + 4 + 4,
  1617. client6_data.ia_na->data + client6_data.ia_na->len,
  1618. D6_OPT_IAADDR
  1619. );
  1620. if (!iaaddr) {
  1621. bb_info_msg("no %s option%s", "IAADDR", ", ignoring packet");
  1622. continue;
  1623. }
  1624. if (iaaddr->len < (16 + 4 + 4)) {
  1625. bb_info_msg("%s option is too short:%d bytes",
  1626. "IAADDR", iaaddr->len);
  1627. continue;
  1628. }
  1629. /* Note: the address is sufficiently aligned for cast:
  1630. * we _copied_ IA-NA, and copy is always well-aligned.
  1631. */
  1632. requested_ipv6 = (struct in6_addr*) iaaddr->data;
  1633. move_from_unaligned32(lease_seconds, iaaddr->data + 16 + 4);
  1634. lease_seconds = ntohl(lease_seconds);
  1635. /// TODO: check for 0 lease time?
  1636. bb_info_msg("%s obtained, lease time %u",
  1637. "IPv6", /*inet_ntoa(temp_addr),*/ (unsigned)lease_seconds);
  1638. address_timeout = lease_seconds;
  1639. }
  1640. if (option_mask32 & OPT_d) {
  1641. struct d6_option *iaprefix;
  1642. free(client6_data.ia_pd);
  1643. client6_data.ia_pd = d6_copy_option(packet.d6_options, packet_end, D6_OPT_IA_PD);
  1644. if (!client6_data.ia_pd) {
  1645. bb_info_msg("no %s option%s", "IA_PD", ", ignoring packet");
  1646. continue;
  1647. }
  1648. if (client6_data.ia_pd->len < (4 + 4 + 4) + (2 + 2 + 4 + 4 + 1 + 16)) {
  1649. bb_info_msg("%s option is too short:%d bytes",
  1650. "IA_PD", client6_data.ia_pd->len);
  1651. continue;
  1652. }
  1653. iaprefix = d6_find_option(client6_data.ia_pd->data + 4 + 4 + 4,
  1654. client6_data.ia_pd->data + client6_data.ia_pd->len,
  1655. D6_OPT_IAPREFIX
  1656. );
  1657. if (!iaprefix) {
  1658. bb_info_msg("no %s option%s", "IAPREFIX", ", ignoring packet");
  1659. continue;
  1660. }
  1661. if (iaprefix->len < (4 + 4 + 1 + 16)) {
  1662. bb_info_msg("%s option is too short:%d bytes",
  1663. "IAPREFIX", iaprefix->len);
  1664. continue;
  1665. }
  1666. move_from_unaligned32(lease_seconds, iaprefix->data + 4);
  1667. lease_seconds = ntohl(lease_seconds);
  1668. bb_info_msg("%s obtained, lease time %u",
  1669. "prefix", /*inet_ntoa(temp_addr),*/ (unsigned)lease_seconds);
  1670. prefix_timeout = lease_seconds;
  1671. }
  1672. if (!address_timeout)
  1673. address_timeout = prefix_timeout;
  1674. if (!prefix_timeout)
  1675. prefix_timeout = address_timeout;
  1676. lease_remaining = (prefix_timeout < address_timeout ? prefix_timeout : address_timeout);
  1677. if (lease_remaining < 0) /* signed overflow? */
  1678. lease_remaining = INT_MAX;
  1679. if (opt & OPT_l) {
  1680. /* TODO: request OPTION_INFORMATION_REFRESH_TIME (32)
  1681. * and use its value instead of the default 1 day.
  1682. */
  1683. lease_remaining = 24 * 60 * 60;
  1684. }
  1685. /* paranoia: must not be too small */
  1686. if (lease_remaining < 30)
  1687. lease_remaining = 30;
  1688. /* enter bound state */
  1689. start = monotonic_sec();
  1690. d6_run_script(packet.d6_options, packet_end,
  1691. (client_data.state == REQUESTING ? "bound" : "renew"));
  1692. lease_remaining -= (unsigned)monotonic_sec() - start;
  1693. if (lease_remaining < 0)
  1694. lease_remaining = 0;
  1695. if (opt & OPT_q) { /* quit after lease */
  1696. goto ret0;
  1697. }
  1698. /* future renew failures should not exit (JM) */
  1699. opt &= ~OPT_n;
  1700. #if BB_MMU /* NOMMU case backgrounded earlier */
  1701. if (!(opt & OPT_f)) {
  1702. client_background();
  1703. /* do not background again! */
  1704. opt = ((opt & ~OPT_b) | OPT_f);
  1705. }
  1706. #endif
  1707. BOUND_for_half_lease:
  1708. timeout = (unsigned)lease_remaining / 2;
  1709. client_data.state = BOUND;
  1710. packet_num = 0;
  1711. continue; /* back to main loop */
  1712. }
  1713. continue;
  1714. /* case BOUND: - ignore all packets */
  1715. /* case RELEASED: - ignore all packets */
  1716. }
  1717. /* back to main loop */
  1718. } /* for (;;) - main loop ends */
  1719. ret0:
  1720. if (opt & OPT_R) /* release on quit */
  1721. perform_d6_release(&srv6_buf, requested_ipv6);
  1722. retval = 0;
  1723. ret:
  1724. /*if (client_data.pidfile) - remove_pidfile has its own check */
  1725. remove_pidfile(client_data.pidfile);
  1726. return retval;
  1727. }