2
* Modifed version of src/common/wpa_ctrl.c from wpa_supplicant, discarding
3
* all code paths except for CONFIG_CTRL_IFACE_UNIX. Define strlcpy inline,
4
* it is not provided by GNU libc.
5
* Copyright (c) 2008, Kel Modderman <kel@otaku42.de>
7
* wpa_supplicant/hostapd control interface library
8
* Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
10
* This program is free software; you can redistribute it and/or modify
11
* it under the terms of the GNU General Public License version 2 as
12
* published by the Free Software Foundation.
14
* Alternatively, this software may be distributed under the terms of BSD
23
#include <netinet/in.h>
24
#include <sys/socket.h>
26
#include <sys/types.h>
32
* strlcpy - Copy a string with size bound and NUL-termination
35
* @siz: Size of the target buffer
36
* Returns: Total length of the target string (length of src) (not including
39
* This function matches in behavior with the strlcpy(3) function in OpenBSD.
41
size_t strlcpy(char *dest, const char *src, size_t siz)
47
/* Copy string up to the maximum size of the dest buffer */
49
if ((*dest++ = *s++) == '\0')
55
/* Not enough room for the string; force NUL-termination */
59
; /* determine total src string length */
67
* struct wpa_ctrl - Internal structure for control interface library
69
* This structure is used by the wpa_supplicant/hostapd control interface
70
* library to store internal data. Programs using the library should not touch
71
* this data directly. They can only use the pointer to the data structure as
72
* an identifier for the control interface connection and use this as one of
73
* the arguments for most of the control interface library functions.
77
struct sockaddr_un local;
78
struct sockaddr_un dest;
82
struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
84
struct wpa_ctrl *ctrl;
85
static int counter = 0;
89
ctrl = malloc(sizeof(*ctrl));
92
memset(ctrl, 0, sizeof(*ctrl));
94
ctrl->s = socket(PF_UNIX, SOCK_DGRAM, 0);
100
ctrl->local.sun_family = AF_UNIX;
101
ret = snprintf(ctrl->local.sun_path, sizeof(ctrl->local.sun_path),
102
"/tmp/wpa_ctrl_%d-%d", getpid(), counter++);
103
if (ret < 0 || (size_t) ret >= sizeof(ctrl->local.sun_path)) {
108
if (bind(ctrl->s, (struct sockaddr *) &ctrl->local,
109
sizeof(ctrl->local)) < 0) {
115
ctrl->dest.sun_family = AF_UNIX;
116
res = strlcpy(ctrl->dest.sun_path, ctrl_path,
117
sizeof(ctrl->dest.sun_path));
118
if (res >= sizeof(ctrl->dest.sun_path)) {
123
if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest,
124
sizeof(ctrl->dest)) < 0) {
126
unlink(ctrl->local.sun_path);
135
void wpa_ctrl_close(struct wpa_ctrl *ctrl)
137
unlink(ctrl->local.sun_path);
143
int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
144
char *reply, size_t *reply_len,
145
void (*msg_cb)(char *msg, size_t len))
151
char *cmd_buf = NULL;
159
if (send(ctrl->s, _cmd, _cmd_len, 0) < 0) {
169
FD_SET(ctrl->s, &rfds);
170
res = select(ctrl->s + 1, &rfds, NULL, NULL, &tv);
171
if (FD_ISSET(ctrl->s, &rfds)) {
172
res = recv(ctrl->s, reply, *reply_len, 0);
175
if (res > 0 && reply[0] == '<') {
176
/* This is an unsolicited message from
177
* wpa_supplicant, not the reply to the
178
* request. Use msg_cb to report this to the
181
/* Make sure the message is nul
183
if ((size_t) res == *reply_len)
184
res = (*reply_len) - 1;
200
static int wpa_ctrl_attach_helper(struct wpa_ctrl *ctrl, int attach)
206
ret = wpa_ctrl_request(ctrl, attach ? "ATTACH" : "DETACH", 6,
210
if (len == 3 && memcmp(buf, "OK\n", 3) == 0)
216
int wpa_ctrl_attach(struct wpa_ctrl *ctrl)
218
return wpa_ctrl_attach_helper(ctrl, 1);
222
int wpa_ctrl_detach(struct wpa_ctrl *ctrl)
224
return wpa_ctrl_attach_helper(ctrl, 0);
228
int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len)
232
res = recv(ctrl->s, reply, *reply_len, 0);
240
int wpa_ctrl_pending(struct wpa_ctrl *ctrl)
247
FD_SET(ctrl->s, &rfds);
248
select(ctrl->s + 1, &rfds, NULL, NULL, &tv);
249
return FD_ISSET(ctrl->s, &rfds);
253
int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl)