ctrl_iface_udp.c 18 KB

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