ctrl_iface_udp.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727
  1. /*
  2. * WPA Supplicant / UDP socket -based control interface
  3. * Copyright (c) 2004-2005, Jouni Malinen <j@w1.fi>
  4. *
  5. * This software may be distributed under the terms of the BSD license.
  6. * See README for more details.
  7. */
  8. #include "includes.h"
  9. #include "common.h"
  10. #include "eloop.h"
  11. #include "config.h"
  12. #include "eapol_supp/eapol_supp_sm.h"
  13. #include "wpa_supplicant_i.h"
  14. #include "ctrl_iface.h"
  15. #include "common/wpa_ctrl.h"
  16. #define COOKIE_LEN 8
  17. /* Per-interface ctrl_iface */
  18. /**
  19. * struct wpa_ctrl_dst - Internal data structure of control interface monitors
  20. *
  21. * This structure is used to store information about registered control
  22. * interface monitors into struct wpa_supplicant. This data is private to
  23. * ctrl_iface_udp.c and should not be touched directly from other files.
  24. */
  25. struct wpa_ctrl_dst {
  26. struct wpa_ctrl_dst *next;
  27. #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
  28. struct sockaddr_in6 addr;
  29. #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
  30. struct sockaddr_in addr;
  31. #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
  32. socklen_t addrlen;
  33. int debug_level;
  34. int errors;
  35. };
  36. struct ctrl_iface_priv {
  37. struct wpa_supplicant *wpa_s;
  38. int sock;
  39. struct wpa_ctrl_dst *ctrl_dst;
  40. u8 cookie[COOKIE_LEN];
  41. };
  42. static void wpa_supplicant_ctrl_iface_send(struct wpa_supplicant *wpa_s,
  43. const char *ifname, int sock,
  44. struct wpa_ctrl_dst **head,
  45. int level, const char *buf,
  46. size_t len);
  47. static int wpa_supplicant_ctrl_iface_attach(struct wpa_ctrl_dst **head,
  48. #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
  49. struct sockaddr_in6 *from,
  50. #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
  51. struct sockaddr_in *from,
  52. #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
  53. socklen_t fromlen)
  54. {
  55. struct wpa_ctrl_dst *dst;
  56. #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
  57. char addr[INET6_ADDRSTRLEN];
  58. #endif /* CONFIG_UDP_IPV6 */
  59. dst = os_zalloc(sizeof(*dst));
  60. if (dst == NULL)
  61. return -1;
  62. os_memcpy(&dst->addr, from, sizeof(*from));
  63. dst->addrlen = fromlen;
  64. dst->debug_level = MSG_INFO;
  65. dst->next = *head;
  66. *head = dst;
  67. #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
  68. wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor attached %s:%d",
  69. inet_ntop(AF_INET6, &from->sin6_addr, addr, sizeof(*from)),
  70. ntohs(from->sin6_port));
  71. #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
  72. wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor attached %s:%d",
  73. inet_ntoa(from->sin_addr), ntohs(from->sin_port));
  74. #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
  75. return 0;
  76. }
  77. static int wpa_supplicant_ctrl_iface_detach(struct wpa_ctrl_dst **head,
  78. #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
  79. struct sockaddr_in6 *from,
  80. #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
  81. struct sockaddr_in *from,
  82. #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
  83. socklen_t fromlen)
  84. {
  85. struct wpa_ctrl_dst *dst, *prev = NULL;
  86. #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
  87. char addr[INET6_ADDRSTRLEN];
  88. #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
  89. dst = *head;
  90. while (dst) {
  91. #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
  92. if (from->sin6_port == dst->addr.sin6_port &&
  93. !os_memcmp(&from->sin6_addr, &dst->addr.sin6_addr,
  94. sizeof(from->sin6_addr))) {
  95. wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor detached %s:%d",
  96. inet_ntop(AF_INET6, &from->sin6_addr, addr,
  97. sizeof(*from)),
  98. ntohs(from->sin6_port));
  99. #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
  100. if (from->sin_addr.s_addr == dst->addr.sin_addr.s_addr &&
  101. from->sin_port == dst->addr.sin_port) {
  102. wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor detached "
  103. "%s:%d", inet_ntoa(from->sin_addr),
  104. ntohs(from->sin_port));
  105. #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
  106. if (prev == NULL)
  107. *head = dst->next;
  108. else
  109. prev->next = dst->next;
  110. os_free(dst);
  111. return 0;
  112. }
  113. prev = dst;
  114. dst = dst->next;
  115. }
  116. return -1;
  117. }
  118. static int wpa_supplicant_ctrl_iface_level(struct ctrl_iface_priv *priv,
  119. #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
  120. struct sockaddr_in6 *from,
  121. #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
  122. struct sockaddr_in *from,
  123. #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
  124. socklen_t fromlen,
  125. char *level)
  126. {
  127. struct wpa_ctrl_dst *dst;
  128. #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
  129. char addr[INET6_ADDRSTRLEN];
  130. #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
  131. wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level);
  132. dst = priv->ctrl_dst;
  133. while (dst) {
  134. #if CONFIG_CTRL_IFACE_UDP_IPV6
  135. if (from->sin6_port == dst->addr.sin6_port &&
  136. !os_memcmp(&from->sin6_addr, &dst->addr.sin6_addr,
  137. sizeof(from->sin6_addr))) {
  138. wpa_printf(MSG_DEBUG, "CTRL_IFACE changed monitor level %s:%d",
  139. inet_ntop(AF_INET6, &from->sin6_addr, addr,
  140. sizeof(*from)),
  141. ntohs(from->sin6_port));
  142. #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
  143. if (from->sin_addr.s_addr == dst->addr.sin_addr.s_addr &&
  144. from->sin_port == dst->addr.sin_port) {
  145. wpa_printf(MSG_DEBUG, "CTRL_IFACE changed monitor "
  146. "level %s:%d", inet_ntoa(from->sin_addr),
  147. ntohs(from->sin_port));
  148. #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
  149. dst->debug_level = atoi(level);
  150. return 0;
  151. }
  152. dst = dst->next;
  153. }
  154. return -1;
  155. }
  156. static char *
  157. wpa_supplicant_ctrl_iface_get_cookie(struct ctrl_iface_priv *priv,
  158. size_t *reply_len)
  159. {
  160. char *reply;
  161. reply = os_malloc(7 + 2 * COOKIE_LEN + 1);
  162. if (reply == NULL) {
  163. *reply_len = 1;
  164. return NULL;
  165. }
  166. os_memcpy(reply, "COOKIE=", 7);
  167. wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1,
  168. priv->cookie, COOKIE_LEN);
  169. *reply_len = 7 + 2 * COOKIE_LEN;
  170. return reply;
  171. }
  172. static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx,
  173. void *sock_ctx)
  174. {
  175. struct wpa_supplicant *wpa_s = eloop_ctx;
  176. struct ctrl_iface_priv *priv = sock_ctx;
  177. char buf[256], *pos;
  178. int res;
  179. #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
  180. struct sockaddr_in6 from;
  181. #ifndef CONFIG_CTRL_IFACE_UDP_REMOTE
  182. char addr[INET6_ADDRSTRLEN];
  183. #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
  184. #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
  185. struct sockaddr_in from;
  186. #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
  187. socklen_t fromlen = sizeof(from);
  188. char *reply = NULL;
  189. size_t reply_len = 0;
  190. int new_attached = 0;
  191. u8 cookie[COOKIE_LEN];
  192. res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
  193. (struct sockaddr *) &from, &fromlen);
  194. if (res < 0) {
  195. wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s",
  196. strerror(errno));
  197. return;
  198. }
  199. #ifndef CONFIG_CTRL_IFACE_UDP_REMOTE
  200. #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
  201. inet_ntop(AF_INET6, &from.sin6_addr, addr, sizeof(from));
  202. if (os_strcmp(addr, "::1")) {
  203. wpa_printf(MSG_DEBUG, "CTRL: Drop packet from unexpected source %s",
  204. addr);
  205. }
  206. #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
  207. if (from.sin_addr.s_addr != htonl((127 << 24) | 1)) {
  208. /*
  209. * The OS networking stack is expected to drop this kind of
  210. * frames since the socket is bound to only localhost address.
  211. * Just in case, drop the frame if it is coming from any other
  212. * address.
  213. */
  214. wpa_printf(MSG_DEBUG, "CTRL: Drop packet from unexpected "
  215. "source %s", inet_ntoa(from.sin_addr));
  216. return;
  217. }
  218. #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
  219. #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
  220. buf[res] = '\0';
  221. if (os_strcmp(buf, "GET_COOKIE") == 0) {
  222. reply = wpa_supplicant_ctrl_iface_get_cookie(priv, &reply_len);
  223. goto done;
  224. }
  225. /*
  226. * Require that the client includes a prefix with the 'cookie' value
  227. * fetched with GET_COOKIE command. This is used to verify that the
  228. * client has access to a bidirectional link over UDP in order to
  229. * avoid attacks using forged localhost IP address even if the OS does
  230. * not block such frames from remote destinations.
  231. */
  232. if (os_strncmp(buf, "COOKIE=", 7) != 0) {
  233. wpa_printf(MSG_DEBUG, "CTLR: No cookie in the request - "
  234. "drop request");
  235. return;
  236. }
  237. if (hexstr2bin(buf + 7, cookie, COOKIE_LEN) < 0) {
  238. wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie format in the "
  239. "request - drop request");
  240. return;
  241. }
  242. if (os_memcmp(cookie, priv->cookie, COOKIE_LEN) != 0) {
  243. wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie in the request - "
  244. "drop request");
  245. return;
  246. }
  247. pos = buf + 7 + 2 * COOKIE_LEN;
  248. while (*pos == ' ')
  249. pos++;
  250. if (os_strcmp(pos, "ATTACH") == 0) {
  251. if (wpa_supplicant_ctrl_iface_attach(&priv->ctrl_dst,
  252. &from, fromlen))
  253. reply_len = 1;
  254. else {
  255. new_attached = 1;
  256. reply_len = 2;
  257. }
  258. } else if (os_strcmp(pos, "DETACH") == 0) {
  259. if (wpa_supplicant_ctrl_iface_detach(&priv->ctrl_dst,
  260. &from, fromlen))
  261. reply_len = 1;
  262. else
  263. reply_len = 2;
  264. } else if (os_strncmp(pos, "LEVEL ", 6) == 0) {
  265. if (wpa_supplicant_ctrl_iface_level(priv, &from, fromlen,
  266. pos + 6))
  267. reply_len = 1;
  268. else
  269. reply_len = 2;
  270. } else {
  271. reply = wpa_supplicant_ctrl_iface_process(wpa_s, pos,
  272. &reply_len);
  273. }
  274. done:
  275. if (reply) {
  276. sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
  277. fromlen);
  278. os_free(reply);
  279. } else if (reply_len == 1) {
  280. sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
  281. fromlen);
  282. } else if (reply_len == 2) {
  283. sendto(sock, "OK\n", 3, 0, (struct sockaddr *) &from,
  284. fromlen);
  285. }
  286. if (new_attached)
  287. eapol_sm_notify_ctrl_attached(wpa_s->eapol);
  288. }
  289. static void wpa_supplicant_ctrl_iface_msg_cb(void *ctx, int level,
  290. enum wpa_msg_type type,
  291. const char *txt, size_t len)
  292. {
  293. struct wpa_supplicant *wpa_s = ctx;
  294. if (wpa_s == NULL || wpa_s->ctrl_iface == NULL)
  295. return;
  296. wpa_supplicant_ctrl_iface_send(wpa_s, NULL, wpa_s->ctrl_iface->sock,
  297. &wpa_s->ctrl_iface->ctrl_dst,
  298. level, txt, len);
  299. }
  300. struct ctrl_iface_priv *
  301. wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s)
  302. {
  303. struct ctrl_iface_priv *priv;
  304. int port = WPA_CTRL_IFACE_PORT;
  305. char *pos;
  306. #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
  307. struct sockaddr_in6 addr;
  308. int domain = PF_INET6;
  309. #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
  310. struct sockaddr_in addr;
  311. int domain = PF_INET;
  312. #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
  313. priv = os_zalloc(sizeof(*priv));
  314. if (priv == NULL)
  315. return NULL;
  316. priv->wpa_s = wpa_s;
  317. priv->sock = -1;
  318. os_get_random(priv->cookie, COOKIE_LEN);
  319. if (wpa_s->conf->ctrl_interface == NULL)
  320. return priv;
  321. pos = os_strstr(wpa_s->conf->ctrl_interface, "udp:");
  322. if (pos) {
  323. pos += 4;
  324. port = atoi(pos);
  325. if (port <= 0) {
  326. wpa_printf(MSG_ERROR, "Invalid ctrl_iface UDP port: %s",
  327. wpa_s->conf->ctrl_interface);
  328. goto fail;
  329. }
  330. }
  331. priv->sock = socket(domain, SOCK_DGRAM, 0);
  332. if (priv->sock < 0) {
  333. wpa_printf(MSG_ERROR, "socket(PF_INET): %s", strerror(errno));
  334. goto fail;
  335. }
  336. os_memset(&addr, 0, sizeof(addr));
  337. #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
  338. addr.sin6_family = AF_INET6;
  339. #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
  340. addr.sin6_addr = in6addr_any;
  341. #else /* CONFIG_CTRL_IFACE_UDP_REMOTE */
  342. inet_pton(AF_INET6, "::1", &addr.sin6_addr);
  343. #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
  344. #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
  345. addr.sin_family = AF_INET;
  346. #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
  347. addr.sin_addr.s_addr = INADDR_ANY;
  348. #else /* CONFIG_CTRL_IFACE_UDP_REMOTE */
  349. addr.sin_addr.s_addr = htonl((127 << 24) | 1);
  350. #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
  351. #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
  352. try_again:
  353. #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
  354. addr.sin6_port = htons(port);
  355. #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
  356. addr.sin_port = htons(port);
  357. #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
  358. if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
  359. port--;
  360. if ((WPA_CTRL_IFACE_PORT - port) < WPA_CTRL_IFACE_PORT_LIMIT &&
  361. !pos)
  362. goto try_again;
  363. wpa_printf(MSG_ERROR, "bind(AF_INET): %s", strerror(errno));
  364. goto fail;
  365. }
  366. #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
  367. wpa_msg(wpa_s, MSG_DEBUG, "ctrl_iface_init UDP port: %d", port);
  368. #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
  369. eloop_register_read_sock(priv->sock, wpa_supplicant_ctrl_iface_receive,
  370. wpa_s, priv);
  371. wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb);
  372. return priv;
  373. fail:
  374. if (priv->sock >= 0)
  375. close(priv->sock);
  376. os_free(priv);
  377. return NULL;
  378. }
  379. void wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv)
  380. {
  381. struct wpa_ctrl_dst *dst, *prev;
  382. if (priv->sock > -1) {
  383. eloop_unregister_read_sock(priv->sock);
  384. if (priv->ctrl_dst) {
  385. /*
  386. * Wait before closing the control socket if
  387. * there are any attached monitors in order to allow
  388. * them to receive any pending messages.
  389. */
  390. wpa_printf(MSG_DEBUG, "CTRL_IFACE wait for attached "
  391. "monitors to receive messages");
  392. os_sleep(0, 100000);
  393. }
  394. close(priv->sock);
  395. priv->sock = -1;
  396. }
  397. dst = priv->ctrl_dst;
  398. while (dst) {
  399. prev = dst;
  400. dst = dst->next;
  401. os_free(prev);
  402. }
  403. os_free(priv);
  404. }
  405. static void wpa_supplicant_ctrl_iface_send(struct wpa_supplicant *wpa_s,
  406. const char *ifname, int sock,
  407. struct wpa_ctrl_dst **head,
  408. int level, const char *buf,
  409. size_t len)
  410. {
  411. struct wpa_ctrl_dst *dst, *next;
  412. char levelstr[64];
  413. int idx;
  414. char *sbuf;
  415. int llen;
  416. #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
  417. char addr[INET6_ADDRSTRLEN];
  418. #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
  419. dst = *head;
  420. if (sock < 0 || dst == NULL)
  421. return;
  422. if (ifname)
  423. os_snprintf(levelstr, sizeof(levelstr), "IFACE=%s <%d>",
  424. ifname, level);
  425. else
  426. os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
  427. llen = os_strlen(levelstr);
  428. sbuf = os_malloc(llen + len);
  429. if (sbuf == NULL)
  430. return;
  431. os_memcpy(sbuf, levelstr, llen);
  432. os_memcpy(sbuf + llen, buf, len);
  433. idx = 0;
  434. while (dst) {
  435. next = dst->next;
  436. if (level >= dst->debug_level) {
  437. #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
  438. wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor send %s:%d",
  439. inet_ntop(AF_INET6, &dst->addr.sin6_addr,
  440. addr, sizeof(dst->addr)),
  441. ntohs(dst->addr.sin6_port));
  442. #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
  443. wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor send %s:%d",
  444. inet_ntoa(dst->addr.sin_addr),
  445. ntohs(dst->addr.sin_port));
  446. #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
  447. if (sendto(sock, sbuf, llen + len, 0,
  448. (struct sockaddr *) &dst->addr,
  449. sizeof(dst->addr)) < 0) {
  450. wpa_printf(MSG_ERROR,
  451. "sendto(CTRL_IFACE monitor): %s",
  452. strerror(errno));
  453. dst->errors++;
  454. if (dst->errors > 10) {
  455. wpa_supplicant_ctrl_iface_detach(
  456. head, &dst->addr,
  457. dst->addrlen);
  458. }
  459. } else
  460. dst->errors = 0;
  461. }
  462. idx++;
  463. dst = next;
  464. }
  465. os_free(sbuf);
  466. }
  467. void wpa_supplicant_ctrl_iface_wait(struct ctrl_iface_priv *priv)
  468. {
  469. wpa_printf(MSG_DEBUG, "CTRL_IFACE - %s - wait for monitor",
  470. priv->wpa_s->ifname);
  471. eloop_wait_for_read_sock(priv->sock);
  472. }
  473. /* Global ctrl_iface */
  474. struct ctrl_iface_global_priv {
  475. int sock;
  476. u8 cookie[COOKIE_LEN];
  477. };
  478. static char *
  479. wpa_supplicant_global_get_cookie(struct ctrl_iface_global_priv *priv,
  480. size_t *reply_len)
  481. {
  482. char *reply;
  483. reply = os_malloc(7 + 2 * COOKIE_LEN + 1);
  484. if (reply == NULL) {
  485. *reply_len = 1;
  486. return NULL;
  487. }
  488. os_memcpy(reply, "COOKIE=", 7);
  489. wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1,
  490. priv->cookie, COOKIE_LEN);
  491. *reply_len = 7 + 2 * COOKIE_LEN;
  492. return reply;
  493. }
  494. static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx,
  495. void *sock_ctx)
  496. {
  497. struct wpa_global *global = eloop_ctx;
  498. struct ctrl_iface_global_priv *priv = sock_ctx;
  499. char buf[256], *pos;
  500. int res;
  501. struct sockaddr_in from;
  502. socklen_t fromlen = sizeof(from);
  503. char *reply;
  504. size_t reply_len;
  505. u8 cookie[COOKIE_LEN];
  506. res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
  507. (struct sockaddr *) &from, &fromlen);
  508. if (res < 0) {
  509. wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s",
  510. strerror(errno));
  511. return;
  512. }
  513. #ifndef CONFIG_CTRL_IFACE_UDP_REMOTE
  514. if (from.sin_addr.s_addr != htonl((127 << 24) | 1)) {
  515. /*
  516. * The OS networking stack is expected to drop this kind of
  517. * frames since the socket is bound to only localhost address.
  518. * Just in case, drop the frame if it is coming from any other
  519. * address.
  520. */
  521. wpa_printf(MSG_DEBUG, "CTRL: Drop packet from unexpected "
  522. "source %s", inet_ntoa(from.sin_addr));
  523. return;
  524. }
  525. #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
  526. buf[res] = '\0';
  527. if (os_strcmp(buf, "GET_COOKIE") == 0) {
  528. reply = wpa_supplicant_global_get_cookie(priv, &reply_len);
  529. goto done;
  530. }
  531. if (os_strncmp(buf, "COOKIE=", 7) != 0) {
  532. wpa_printf(MSG_DEBUG, "CTLR: No cookie in the request - "
  533. "drop request");
  534. return;
  535. }
  536. if (hexstr2bin(buf + 7, cookie, COOKIE_LEN) < 0) {
  537. wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie format in the "
  538. "request - drop request");
  539. return;
  540. }
  541. if (os_memcmp(cookie, priv->cookie, COOKIE_LEN) != 0) {
  542. wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie in the request - "
  543. "drop request");
  544. return;
  545. }
  546. pos = buf + 7 + 2 * COOKIE_LEN;
  547. while (*pos == ' ')
  548. pos++;
  549. reply = wpa_supplicant_global_ctrl_iface_process(global, pos,
  550. &reply_len);
  551. done:
  552. if (reply) {
  553. sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
  554. fromlen);
  555. os_free(reply);
  556. } else if (reply_len) {
  557. sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
  558. fromlen);
  559. }
  560. }
  561. struct ctrl_iface_global_priv *
  562. wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global)
  563. {
  564. struct ctrl_iface_global_priv *priv;
  565. struct sockaddr_in addr;
  566. char *pos;
  567. int port = WPA_GLOBAL_CTRL_IFACE_PORT;
  568. priv = os_zalloc(sizeof(*priv));
  569. if (priv == NULL)
  570. return NULL;
  571. priv->sock = -1;
  572. os_get_random(priv->cookie, COOKIE_LEN);
  573. if (global->params.ctrl_interface == NULL)
  574. return priv;
  575. wpa_printf(MSG_DEBUG, "Global control interface '%s'",
  576. global->params.ctrl_interface);
  577. pos = os_strstr(global->params.ctrl_interface, "udp:");
  578. if (pos) {
  579. pos += 4;
  580. port = atoi(pos);
  581. if (port <= 0) {
  582. wpa_printf(MSG_ERROR, "Invalid global ctrl UDP port %s",
  583. global->params.ctrl_interface);
  584. goto fail;
  585. }
  586. }
  587. priv->sock = socket(PF_INET, SOCK_DGRAM, 0);
  588. if (priv->sock < 0) {
  589. wpa_printf(MSG_ERROR, "socket(PF_INET): %s", strerror(errno));
  590. goto fail;
  591. }
  592. os_memset(&addr, 0, sizeof(addr));
  593. addr.sin_family = AF_INET;
  594. #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
  595. addr.sin_addr.s_addr = INADDR_ANY;
  596. #else /* CONFIG_CTRL_IFACE_UDP_REMOTE */
  597. addr.sin_addr.s_addr = htonl((127 << 24) | 1);
  598. #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
  599. try_again:
  600. addr.sin_port = htons(port);
  601. if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
  602. port++;
  603. if ((port - WPA_GLOBAL_CTRL_IFACE_PORT) <
  604. WPA_GLOBAL_CTRL_IFACE_PORT_LIMIT && !pos)
  605. goto try_again;
  606. wpa_printf(MSG_ERROR, "bind(AF_INET): %s", strerror(errno));
  607. goto fail;
  608. }
  609. #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
  610. wpa_printf(MSG_DEBUG, "global_ctrl_iface_init UDP port: %d", port);
  611. #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
  612. eloop_register_read_sock(priv->sock,
  613. wpa_supplicant_global_ctrl_iface_receive,
  614. global, priv);
  615. return priv;
  616. fail:
  617. if (priv->sock >= 0)
  618. close(priv->sock);
  619. os_free(priv);
  620. return NULL;
  621. }
  622. void
  623. wpa_supplicant_global_ctrl_iface_deinit(struct ctrl_iface_global_priv *priv)
  624. {
  625. if (priv->sock >= 0) {
  626. eloop_unregister_read_sock(priv->sock);
  627. close(priv->sock);
  628. }
  629. os_free(priv);
  630. }