ctrl_iface_udp.c 17 KB

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