ctrl_iface_unix.c revision 209158
1239310Sdim/*
2239310Sdim * WPA Supplicant / UNIX domain socket -based control interface
3239310Sdim * Copyright (c) 2004-2005, Jouni Malinen <j@w1.fi>
4239310Sdim *
5239310Sdim * This program is free software; you can redistribute it and/or modify
6239310Sdim * it under the terms of the GNU General Public License version 2 as
7239310Sdim * published by the Free Software Foundation.
8239310Sdim *
9239310Sdim * Alternatively, this software may be distributed under the terms of BSD
10239310Sdim * license.
11239310Sdim *
12239310Sdim * See README and COPYING for more details.
13239310Sdim */
14239310Sdim
15252723Sdim#include "includes.h"
16239310Sdim#include <sys/un.h>
17252723Sdim#include <sys/stat.h>
18252723Sdim#include <grp.h>
19239310Sdim#include <stddef.h>
20252723Sdim
21239310Sdim#include "common.h"
22239310Sdim#include "eloop.h"
23239310Sdim#include "config.h"
24239310Sdim#include "eapol_supp/eapol_supp_sm.h"
25239310Sdim#include "wpa_supplicant_i.h"
26239310Sdim#include "ctrl_iface.h"
27239310Sdim
28252723Sdim/* Per-interface ctrl_iface */
29239310Sdim
30239310Sdim/**
31239310Sdim * struct wpa_ctrl_dst - Internal data structure of control interface monitors
32239310Sdim *
33252723Sdim * This structure is used to store information about registered control
34252723Sdim * interface monitors into struct wpa_supplicant. This data is private to
35252723Sdim * ctrl_iface_unix.c and should not be touched directly from other files.
36252723Sdim */
37239310Sdimstruct wpa_ctrl_dst {
38239310Sdim	struct wpa_ctrl_dst *next;
39239310Sdim	struct sockaddr_un addr;
40239310Sdim	socklen_t addrlen;
41239310Sdim	int debug_level;
42239310Sdim	int errors;
43239310Sdim};
44239310Sdim
45239310Sdim
46239310Sdimstruct ctrl_iface_priv {
47239310Sdim	struct wpa_supplicant *wpa_s;
48239310Sdim	int sock;
49239310Sdim	struct wpa_ctrl_dst *ctrl_dst;
50252723Sdim};
51252723Sdim
52252723Sdim
53252723Sdimstatic void wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv,
54239310Sdim					   int level, const char *buf,
55239310Sdim					   size_t len);
56239310Sdim
57239310Sdim
58239310Sdimstatic int wpa_supplicant_ctrl_iface_attach(struct ctrl_iface_priv *priv,
59239310Sdim					    struct sockaddr_un *from,
60252723Sdim					    socklen_t fromlen)
61252723Sdim{
62252723Sdim	struct wpa_ctrl_dst *dst;
63252723Sdim
64239310Sdim	dst = os_zalloc(sizeof(*dst));
65239310Sdim	if (dst == NULL)
66252723Sdim		return -1;
67252723Sdim	os_memcpy(&dst->addr, from, sizeof(struct sockaddr_un));
68252723Sdim	dst->addrlen = fromlen;
69252723Sdim	dst->debug_level = MSG_INFO;
70252723Sdim	dst->next = priv->ctrl_dst;
71252723Sdim	priv->ctrl_dst = dst;
72252723Sdim	wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached",
73252723Sdim		    (u8 *) from->sun_path,
74263509Sdim		    fromlen - offsetof(struct sockaddr_un, sun_path));
75263509Sdim	return 0;
76263509Sdim}
77239310Sdim
78239310Sdim
79239310Sdimstatic int wpa_supplicant_ctrl_iface_detach(struct ctrl_iface_priv *priv,
80252723Sdim					    struct sockaddr_un *from,
81252723Sdim					    socklen_t fromlen)
82252723Sdim{
83252723Sdim	struct wpa_ctrl_dst *dst, *prev = NULL;
84252723Sdim
85239310Sdim	dst = priv->ctrl_dst;
86239310Sdim	while (dst) {
87239310Sdim		if (fromlen == dst->addrlen &&
88252723Sdim		    os_memcmp(from->sun_path, dst->addr.sun_path,
89252723Sdim			      fromlen - offsetof(struct sockaddr_un, sun_path))
90252723Sdim		    == 0) {
91252723Sdim			if (prev == NULL)
92252723Sdim				priv->ctrl_dst = dst->next;
93239310Sdim			else
94263509Sdim				prev->next = dst->next;
95239310Sdim			os_free(dst);
96239310Sdim			wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor detached",
97239310Sdim				    (u8 *) from->sun_path,
98252723Sdim				    fromlen -
99239310Sdim				    offsetof(struct sockaddr_un, sun_path));
100239310Sdim			return 0;
101239310Sdim		}
102239310Sdim		prev = dst;
103239310Sdim		dst = dst->next;
104252723Sdim	}
105239310Sdim	return -1;
106239310Sdim}
107263509Sdim
108263509Sdim
109263509Sdimstatic int wpa_supplicant_ctrl_iface_level(struct ctrl_iface_priv *priv,
110263509Sdim					   struct sockaddr_un *from,
111263509Sdim					   socklen_t fromlen,
112239310Sdim					   char *level)
113263509Sdim{
114239310Sdim	struct wpa_ctrl_dst *dst;
115239310Sdim
116239310Sdim	wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level);
117239310Sdim
118239310Sdim	dst = priv->ctrl_dst;
119239310Sdim	while (dst) {
120252723Sdim		if (fromlen == dst->addrlen &&
121263509Sdim		    os_memcmp(from->sun_path, dst->addr.sun_path,
122263509Sdim			      fromlen - offsetof(struct sockaddr_un, sun_path))
123263509Sdim		    == 0) {
124263509Sdim			wpa_hexdump(MSG_DEBUG, "CTRL_IFACE changed monitor "
125263509Sdim				    "level", (u8 *) from->sun_path,
126263509Sdim				    fromlen -
127263509Sdim				    offsetof(struct sockaddr_un, sun_path));
128263509Sdim			dst->debug_level = atoi(level);
129263509Sdim			return 0;
130263509Sdim		}
131252723Sdim		dst = dst->next;
132252723Sdim	}
133252723Sdim
134252723Sdim	return -1;
135239310Sdim}
136239310Sdim
137239310Sdim
138239310Sdimstatic void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx,
139239310Sdim					      void *sock_ctx)
140239310Sdim{
141239310Sdim	struct wpa_supplicant *wpa_s = eloop_ctx;
142239310Sdim	struct ctrl_iface_priv *priv = sock_ctx;
143252723Sdim	char buf[256];
144263509Sdim	int res;
145263509Sdim	struct sockaddr_un from;
146263509Sdim	socklen_t fromlen = sizeof(from);
147263509Sdim	char *reply = NULL;
148263509Sdim	size_t reply_len = 0;
149263509Sdim	int new_attached = 0;
150263509Sdim
151263509Sdim	res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
152263509Sdim		       (struct sockaddr *) &from, &fromlen);
153263509Sdim	if (res < 0) {
154263509Sdim		perror("recvfrom(ctrl_iface)");
155263509Sdim		return;
156263509Sdim	}
157263509Sdim	buf[res] = '\0';
158263509Sdim
159263509Sdim	if (os_strcmp(buf, "ATTACH") == 0) {
160263509Sdim		if (wpa_supplicant_ctrl_iface_attach(priv, &from, fromlen))
161263509Sdim			reply_len = 1;
162263509Sdim		else {
163263509Sdim			new_attached = 1;
164263509Sdim			reply_len = 2;
165263509Sdim		}
166263509Sdim	} else if (os_strcmp(buf, "DETACH") == 0) {
167263509Sdim		if (wpa_supplicant_ctrl_iface_detach(priv, &from, fromlen))
168263509Sdim			reply_len = 1;
169263509Sdim		else
170263509Sdim			reply_len = 2;
171263509Sdim	} else if (os_strncmp(buf, "LEVEL ", 6) == 0) {
172263509Sdim		if (wpa_supplicant_ctrl_iface_level(priv, &from, fromlen,
173263509Sdim						    buf + 6))
174263509Sdim			reply_len = 1;
175263509Sdim		else
176263509Sdim			reply_len = 2;
177263509Sdim	} else {
178263509Sdim		reply = wpa_supplicant_ctrl_iface_process(wpa_s, buf,
179263509Sdim							  &reply_len);
180263509Sdim	}
181263509Sdim
182	if (reply) {
183		sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
184		       fromlen);
185		os_free(reply);
186	} else if (reply_len == 1) {
187		sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
188		       fromlen);
189	} else if (reply_len == 2) {
190		sendto(sock, "OK\n", 3, 0, (struct sockaddr *) &from,
191		       fromlen);
192	}
193
194	if (new_attached)
195		eapol_sm_notify_ctrl_attached(wpa_s->eapol);
196}
197
198
199static char * wpa_supplicant_ctrl_iface_path(struct wpa_supplicant *wpa_s)
200{
201	char *buf;
202	size_t len;
203	char *pbuf, *dir = NULL, *gid_str = NULL;
204	int res;
205
206	if (wpa_s->conf->ctrl_interface == NULL)
207		return NULL;
208
209	pbuf = os_strdup(wpa_s->conf->ctrl_interface);
210	if (pbuf == NULL)
211		return NULL;
212	if (os_strncmp(pbuf, "DIR=", 4) == 0) {
213		dir = pbuf + 4;
214		gid_str = os_strstr(dir, " GROUP=");
215		if (gid_str) {
216			*gid_str = '\0';
217			gid_str += 7;
218		}
219	} else
220		dir = pbuf;
221
222	len = os_strlen(dir) + os_strlen(wpa_s->ifname) + 2;
223	buf = os_malloc(len);
224	if (buf == NULL) {
225		os_free(pbuf);
226		return NULL;
227	}
228
229	res = os_snprintf(buf, len, "%s/%s", dir, wpa_s->ifname);
230	if (res < 0 || (size_t) res >= len) {
231		os_free(pbuf);
232		os_free(buf);
233		return NULL;
234	}
235#ifdef __CYGWIN__
236	{
237		/* Windows/WinPcap uses interface names that are not suitable
238		 * as a file name - convert invalid chars to underscores */
239		char *pos = buf;
240		while (*pos) {
241			if (*pos == '\\')
242				*pos = '_';
243			pos++;
244		}
245	}
246#endif /* __CYGWIN__ */
247	os_free(pbuf);
248	return buf;
249}
250
251
252static void wpa_supplicant_ctrl_iface_msg_cb(void *ctx, int level,
253					     const char *txt, size_t len)
254{
255	struct wpa_supplicant *wpa_s = ctx;
256	if (wpa_s == NULL || wpa_s->ctrl_iface == NULL)
257		return;
258	wpa_supplicant_ctrl_iface_send(wpa_s->ctrl_iface, level, txt, len);
259}
260
261
262struct ctrl_iface_priv *
263wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s)
264{
265	struct ctrl_iface_priv *priv;
266	struct sockaddr_un addr;
267	char *fname = NULL;
268	gid_t gid = 0;
269	int gid_set = 0;
270	char *buf, *dir = NULL, *gid_str = NULL;
271	struct group *grp;
272	char *endp;
273
274	priv = os_zalloc(sizeof(*priv));
275	if (priv == NULL)
276		return NULL;
277	priv->wpa_s = wpa_s;
278	priv->sock = -1;
279
280	if (wpa_s->conf->ctrl_interface == NULL)
281		return priv;
282
283	buf = os_strdup(wpa_s->conf->ctrl_interface);
284	if (buf == NULL)
285		goto fail;
286	if (os_strncmp(buf, "DIR=", 4) == 0) {
287		dir = buf + 4;
288		gid_str = os_strstr(dir, " GROUP=");
289		if (gid_str) {
290			*gid_str = '\0';
291			gid_str += 7;
292		}
293	} else {
294		dir = buf;
295		gid_str = wpa_s->conf->ctrl_interface_group;
296	}
297
298	if (mkdir(dir, S_IRWXU | S_IRWXG) < 0) {
299		if (errno == EEXIST) {
300			wpa_printf(MSG_DEBUG, "Using existing control "
301				   "interface directory.");
302		} else {
303			perror("mkdir[ctrl_interface]");
304			goto fail;
305		}
306	}
307
308	if (gid_str) {
309		grp = getgrnam(gid_str);
310		if (grp) {
311			gid = grp->gr_gid;
312			gid_set = 1;
313			wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d"
314				   " (from group name '%s')",
315				   (int) gid, gid_str);
316		} else {
317			/* Group name not found - try to parse this as gid */
318			gid = strtol(gid_str, &endp, 10);
319			if (*gid_str == '\0' || *endp != '\0') {
320				wpa_printf(MSG_ERROR, "CTRL: Invalid group "
321					   "'%s'", gid_str);
322				goto fail;
323			}
324			gid_set = 1;
325			wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d",
326				   (int) gid);
327		}
328	}
329
330	if (gid_set && chown(dir, -1, gid) < 0) {
331		perror("chown[ctrl_interface]");
332		goto fail;
333	}
334
335	/* Make sure the group can enter and read the directory */
336	if (gid_set &&
337	    chmod(dir, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP) < 0) {
338		wpa_printf(MSG_ERROR, "CTRL: chmod[ctrl_interface]: %s",
339			   strerror(errno));
340		goto fail;
341	}
342
343	if (os_strlen(dir) + 1 + os_strlen(wpa_s->ifname) >=
344	    sizeof(addr.sun_path)) {
345		wpa_printf(MSG_ERROR, "ctrl_iface path limit exceeded");
346		goto fail;
347	}
348
349	priv->sock = socket(PF_UNIX, SOCK_DGRAM, 0);
350	if (priv->sock < 0) {
351		perror("socket(PF_UNIX)");
352		goto fail;
353	}
354
355	os_memset(&addr, 0, sizeof(addr));
356#ifdef __FreeBSD__
357	addr.sun_len = sizeof(addr);
358#endif /* __FreeBSD__ */
359	addr.sun_family = AF_UNIX;
360	fname = wpa_supplicant_ctrl_iface_path(wpa_s);
361	if (fname == NULL)
362		goto fail;
363	os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
364	if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
365		wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
366			   strerror(errno));
367		if (connect(priv->sock, (struct sockaddr *) &addr,
368			    sizeof(addr)) < 0) {
369			wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
370				   " allow connections - assuming it was left"
371				   "over from forced program termination");
372			if (unlink(fname) < 0) {
373				perror("unlink[ctrl_iface]");
374				wpa_printf(MSG_ERROR, "Could not unlink "
375					   "existing ctrl_iface socket '%s'",
376					   fname);
377				goto fail;
378			}
379			if (bind(priv->sock, (struct sockaddr *) &addr,
380				 sizeof(addr)) < 0) {
381				perror("bind(PF_UNIX)");
382				goto fail;
383			}
384			wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
385				   "ctrl_iface socket '%s'", fname);
386		} else {
387			wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
388				   "be in use - cannot override it");
389			wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
390				   "not used anymore", fname);
391			os_free(fname);
392			fname = NULL;
393			goto fail;
394		}
395	}
396
397	if (gid_set && chown(fname, -1, gid) < 0) {
398		perror("chown[ctrl_interface/ifname]");
399		goto fail;
400	}
401
402	if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
403		perror("chmod[ctrl_interface/ifname]");
404		goto fail;
405	}
406	os_free(fname);
407
408	eloop_register_read_sock(priv->sock, wpa_supplicant_ctrl_iface_receive,
409				 wpa_s, priv);
410	wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb);
411
412	os_free(buf);
413	return priv;
414
415fail:
416	if (priv->sock >= 0)
417		close(priv->sock);
418	os_free(priv);
419	if (fname) {
420		unlink(fname);
421		os_free(fname);
422	}
423	os_free(buf);
424	return NULL;
425}
426
427
428void wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv)
429{
430	struct wpa_ctrl_dst *dst, *prev;
431
432	if (priv->sock > -1) {
433		char *fname;
434		char *buf, *dir = NULL, *gid_str = NULL;
435		eloop_unregister_read_sock(priv->sock);
436		if (priv->ctrl_dst) {
437			/*
438			 * Wait a second before closing the control socket if
439			 * there are any attached monitors in order to allow
440			 * them to receive any pending messages.
441			 */
442			wpa_printf(MSG_DEBUG, "CTRL_IFACE wait for attached "
443				   "monitors to receive messages");
444			os_sleep(1, 0);
445		}
446		close(priv->sock);
447		priv->sock = -1;
448		fname = wpa_supplicant_ctrl_iface_path(priv->wpa_s);
449		if (fname) {
450			unlink(fname);
451			os_free(fname);
452		}
453
454		buf = os_strdup(priv->wpa_s->conf->ctrl_interface);
455		if (buf == NULL)
456			goto free_dst;
457		if (os_strncmp(buf, "DIR=", 4) == 0) {
458			dir = buf + 4;
459			gid_str = os_strstr(dir, " GROUP=");
460			if (gid_str) {
461				*gid_str = '\0';
462				gid_str += 7;
463			}
464		} else
465			dir = buf;
466
467		if (rmdir(dir) < 0) {
468			if (errno == ENOTEMPTY) {
469				wpa_printf(MSG_DEBUG, "Control interface "
470					   "directory not empty - leaving it "
471					   "behind");
472			} else {
473				perror("rmdir[ctrl_interface]");
474			}
475		}
476		os_free(buf);
477	}
478
479free_dst:
480	dst = priv->ctrl_dst;
481	while (dst) {
482		prev = dst;
483		dst = dst->next;
484		os_free(prev);
485	}
486	os_free(priv);
487}
488
489
490/**
491 * wpa_supplicant_ctrl_iface_send - Send a control interface packet to monitors
492 * @priv: Pointer to private data from wpa_supplicant_ctrl_iface_init()
493 * @level: Priority level of the message
494 * @buf: Message data
495 * @len: Message length
496 *
497 * Send a packet to all monitor programs attached to the control interface.
498 */
499static void wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv,
500					   int level, const char *buf,
501					   size_t len)
502{
503	struct wpa_ctrl_dst *dst, *next;
504	char levelstr[10];
505	int idx, res;
506	struct msghdr msg;
507	struct iovec io[2];
508
509	dst = priv->ctrl_dst;
510	if (priv->sock < 0 || dst == NULL)
511		return;
512
513	res = os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
514	if (res < 0 || (size_t) res >= sizeof(levelstr))
515		return;
516	io[0].iov_base = levelstr;
517	io[0].iov_len = os_strlen(levelstr);
518	io[1].iov_base = (char *) buf;
519	io[1].iov_len = len;
520	os_memset(&msg, 0, sizeof(msg));
521	msg.msg_iov = io;
522	msg.msg_iovlen = 2;
523
524	idx = 0;
525	while (dst) {
526		next = dst->next;
527		if (level >= dst->debug_level) {
528			wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send",
529				    (u8 *) dst->addr.sun_path, dst->addrlen -
530				    offsetof(struct sockaddr_un, sun_path));
531			msg.msg_name = (void *) &dst->addr;
532			msg.msg_namelen = dst->addrlen;
533			if (sendmsg(priv->sock, &msg, 0) < 0) {
534				int _errno = errno;
535				wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: "
536					   "%d - %s",
537					   idx, errno, strerror(errno));
538				dst->errors++;
539				if (dst->errors > 10 || _errno == ENOENT) {
540					wpa_supplicant_ctrl_iface_detach(
541						priv, &dst->addr,
542						dst->addrlen);
543				}
544			} else
545				dst->errors = 0;
546		}
547		idx++;
548		dst = next;
549	}
550}
551
552
553void wpa_supplicant_ctrl_iface_wait(struct ctrl_iface_priv *priv)
554{
555	char buf[256];
556	int res;
557	struct sockaddr_un from;
558	socklen_t fromlen = sizeof(from);
559
560	for (;;) {
561		wpa_printf(MSG_DEBUG, "CTRL_IFACE - %s - wait for monitor to "
562			   "attach", priv->wpa_s->ifname);
563		eloop_wait_for_read_sock(priv->sock);
564
565		res = recvfrom(priv->sock, buf, sizeof(buf) - 1, 0,
566			       (struct sockaddr *) &from, &fromlen);
567		if (res < 0) {
568			perror("recvfrom(ctrl_iface)");
569			continue;
570		}
571		buf[res] = '\0';
572
573		if (os_strcmp(buf, "ATTACH") == 0) {
574			/* handle ATTACH signal of first monitor interface */
575			if (!wpa_supplicant_ctrl_iface_attach(priv, &from,
576							      fromlen)) {
577				sendto(priv->sock, "OK\n", 3, 0,
578				       (struct sockaddr *) &from, fromlen);
579				/* OK to continue */
580				return;
581			} else {
582				sendto(priv->sock, "FAIL\n", 5, 0,
583				       (struct sockaddr *) &from, fromlen);
584			}
585		} else {
586			/* return FAIL for all other signals */
587			sendto(priv->sock, "FAIL\n", 5, 0,
588			       (struct sockaddr *) &from, fromlen);
589		}
590	}
591}
592
593
594/* Global ctrl_iface */
595
596struct ctrl_iface_global_priv {
597	struct wpa_global *global;
598	int sock;
599};
600
601
602static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx,
603						     void *sock_ctx)
604{
605	struct wpa_global *global = eloop_ctx;
606	char buf[256];
607	int res;
608	struct sockaddr_un from;
609	socklen_t fromlen = sizeof(from);
610	char *reply;
611	size_t reply_len;
612
613	res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
614		       (struct sockaddr *) &from, &fromlen);
615	if (res < 0) {
616		perror("recvfrom(ctrl_iface)");
617		return;
618	}
619	buf[res] = '\0';
620
621	reply = wpa_supplicant_global_ctrl_iface_process(global, buf,
622							 &reply_len);
623
624	if (reply) {
625		sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
626		       fromlen);
627		os_free(reply);
628	} else if (reply_len) {
629		sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
630		       fromlen);
631	}
632}
633
634
635struct ctrl_iface_global_priv *
636wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global)
637{
638	struct ctrl_iface_global_priv *priv;
639	struct sockaddr_un addr;
640
641	priv = os_zalloc(sizeof(*priv));
642	if (priv == NULL)
643		return NULL;
644	priv->global = global;
645	priv->sock = -1;
646
647	if (global->params.ctrl_interface == NULL)
648		return priv;
649
650	wpa_printf(MSG_DEBUG, "Global control interface '%s'",
651		   global->params.ctrl_interface);
652
653	priv->sock = socket(PF_UNIX, SOCK_DGRAM, 0);
654	if (priv->sock < 0) {
655		perror("socket(PF_UNIX)");
656		goto fail;
657	}
658
659	os_memset(&addr, 0, sizeof(addr));
660#ifdef __FreeBSD__
661	addr.sun_len = sizeof(addr);
662#endif /* __FreeBSD__ */
663	addr.sun_family = AF_UNIX;
664	os_strlcpy(addr.sun_path, global->params.ctrl_interface,
665		   sizeof(addr.sun_path));
666	if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
667		perror("bind(PF_UNIX)");
668		if (connect(priv->sock, (struct sockaddr *) &addr,
669			    sizeof(addr)) < 0) {
670			wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
671				   " allow connections - assuming it was left"
672				   "over from forced program termination");
673			if (unlink(global->params.ctrl_interface) < 0) {
674				perror("unlink[ctrl_iface]");
675				wpa_printf(MSG_ERROR, "Could not unlink "
676					   "existing ctrl_iface socket '%s'",
677					   global->params.ctrl_interface);
678				goto fail;
679			}
680			if (bind(priv->sock, (struct sockaddr *) &addr,
681				 sizeof(addr)) < 0) {
682				perror("bind(PF_UNIX)");
683				goto fail;
684			}
685			wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
686				   "ctrl_iface socket '%s'",
687				   global->params.ctrl_interface);
688		} else {
689			wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
690				   "be in use - cannot override it");
691			wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
692				   "not used anymore",
693				   global->params.ctrl_interface);
694			goto fail;
695		}
696	}
697
698	eloop_register_read_sock(priv->sock,
699				 wpa_supplicant_global_ctrl_iface_receive,
700				 global, NULL);
701
702	return priv;
703
704fail:
705	if (priv->sock >= 0)
706		close(priv->sock);
707	os_free(priv);
708	return NULL;
709}
710
711
712void
713wpa_supplicant_global_ctrl_iface_deinit(struct ctrl_iface_global_priv *priv)
714{
715	if (priv->sock >= 0) {
716		eloop_unregister_read_sock(priv->sock);
717		close(priv->sock);
718	}
719	if (priv->global->params.ctrl_interface)
720		unlink(priv->global->params.ctrl_interface);
721	os_free(priv);
722}
723