LMS 2012
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
wpa_ctrl.c
Go to the documentation of this file.
1 /*
2  * wpa_supplicant/hostapd control interface library
3  * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14 
15 #include "includes.h"
16 
17 // HER_PER
18 #define CONFIG_CTRL_IFACE
19 #define CONFIG_CTRL_IFACE_UNIX
20 // HER_TIL PER
21 #ifdef CONFIG_CTRL_IFACE
22 
23 #ifdef CONFIG_CTRL_IFACE_UNIX
24 #include <sys/un.h>
25 #endif /* CONFIG_CTRL_IFACE_UNIX */
26 
27 #include "wpa_ctrl.h"
28 #include "common.h"
29 
30 
31 #if defined(CONFIG_CTRL_IFACE_UNIX) || defined(CONFIG_CTRL_IFACE_UDP)
32 #define CTRL_IFACE_SOCKET
33 #endif /* CONFIG_CTRL_IFACE_UNIX || CONFIG_CTRL_IFACE_UDP */
34 
35 
45 struct wpa_ctrl {
46 #ifdef CONFIG_CTRL_IFACE_UDP
47  int s;
48  struct sockaddr_in local;
49  struct sockaddr_in dest;
50  char *cookie;
51 #endif /* CONFIG_CTRL_IFACE_UDP */
52 #ifdef CONFIG_CTRL_IFACE_UNIX
53  int s;
54  struct sockaddr_un local;
55  struct sockaddr_un dest;
56 #endif /* CONFIG_CTRL_IFACE_UNIX */
57 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
58  HANDLE pipe;
59 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
60 };
61 
62 
63 #ifdef CONFIG_CTRL_IFACE_UNIX
64 
65 struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
66 {
67  struct wpa_ctrl *ctrl;
68  static int counter = 0;
69  int ret;
70  // HER_PER size_t res;
71  int tries = 0;
72 
73  ctrl = malloc(sizeof(*ctrl));
74  if (ctrl == NULL)
75  return NULL;
76  memset(ctrl, 0, sizeof(*ctrl));
77 
78  ctrl->s = socket(PF_UNIX, SOCK_DGRAM, 0);
79  if (ctrl->s < 0) {
80  free(ctrl);
81  return NULL;
82  }
83 
84  ctrl->local.sun_family = AF_UNIX;
85  counter++;
86 try_again:
87  ret = snprintf(ctrl->local.sun_path, sizeof(ctrl->local.sun_path),
88  "/tmp/wpa_ctrl_%d-%d", getpid(), counter);
89  if (ret < 0 || (size_t) ret >= sizeof(ctrl->local.sun_path)) {
90  close(ctrl->s);
91  free(ctrl);
92  return NULL;
93  }
94  tries++;
95  if (bind(ctrl->s, (struct sockaddr *) &ctrl->local,
96  sizeof(ctrl->local)) < 0) {
97  if (errno == EADDRINUSE && tries < 2) {
98  /*
99  * getpid() returns unique identifier for this instance
100  * of wpa_ctrl, so the existing socket file must have
101  * been left by unclean termination of an earlier run.
102  * Remove the file and try again.
103  */
104  unlink(ctrl->local.sun_path);
105  goto try_again;
106  }
107  close(ctrl->s);
108  free(ctrl);
109  return NULL;
110  }
111 
112  ctrl->dest.sun_family = AF_UNIX;
113  /* HER_PER
114  res = strlcpy(ctrl->dest.sun_path, ctrl_path,
115  sizeof(ctrl->dest.sun_path));*/
116  // HER_PER strcpy insted of - above better function
117 // printf("\n\rctrl_path = %s\n\r", ctrl_path);
118  strcpy(ctrl->dest.sun_path, ctrl_path);
119 
120 /* if (res >= sizeof(ctrl->dest.sun_path)) {
121  close(ctrl->s);
122  free(ctrl);
123  return NULL;
124  }*/
125  if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest,
126  sizeof(ctrl->dest)) < 0) {
127  close(ctrl->s);
128  unlink(ctrl->local.sun_path);
129  free(ctrl);
130  return NULL;
131  }
132 
133  return ctrl;
134 }
135 
136 
137 void wpa_ctrl_close(struct wpa_ctrl *ctrl)
138 {
139  unlink(ctrl->local.sun_path);
140  close(ctrl->s);
141  free(ctrl);
142 }
143 
144 #endif /* CONFIG_CTRL_IFACE_UNIX */
145 
146 
147 #ifdef CONFIG_CTRL_IFACE_UDP
148 
149 struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
150 {
151  struct wpa_ctrl *ctrl;
152  char buf[128];
153  size_t len;
154 
155  ctrl = os_malloc(sizeof(*ctrl));
156  if (ctrl == NULL)
157  return NULL;
158  os_memset(ctrl, 0, sizeof(*ctrl));
159 
160  ctrl->s = socket(PF_INET, SOCK_DGRAM, 0);
161  if (ctrl->s < 0) {
162  perror("socket");
163  os_free(ctrl);
164  return NULL;
165  }
166 
167  ctrl->local.sin_family = AF_INET;
168  ctrl->local.sin_addr.s_addr = htonl((127 << 24) | 1);
169  if (bind(ctrl->s, (struct sockaddr *) &ctrl->local,
170  sizeof(ctrl->local)) < 0) {
171  close(ctrl->s);
172  os_free(ctrl);
173  return NULL;
174  }
175 
176  ctrl->dest.sin_family = AF_INET;
177  ctrl->dest.sin_addr.s_addr = htonl((127 << 24) | 1);
178  ctrl->dest.sin_port = htons(WPA_CTRL_IFACE_PORT);
179  if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest,
180  sizeof(ctrl->dest)) < 0) {
181  perror("connect");
182  close(ctrl->s);
183  os_free(ctrl);
184  return NULL;
185  }
186 
187  len = sizeof(buf) - 1;
188  if (wpa_ctrl_request(ctrl, "GET_COOKIE", 10, buf, &len, NULL) == 0) {
189  buf[len] = '\0';
190  ctrl->cookie = os_strdup(buf);
191  }
192 
193  return ctrl;
194 }
195 
196 
197 void wpa_ctrl_close(struct wpa_ctrl *ctrl)
198 {
199  close(ctrl->s);
200  os_free(ctrl->cookie);
201  os_free(ctrl);
202 }
203 
204 #endif /* CONFIG_CTRL_IFACE_UDP */
205 
206 
207 #ifdef CTRL_IFACE_SOCKET
208 int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
209  char *reply, size_t *reply_len,
210  void (*msg_cb)(char *msg, size_t len))
211 {
212  struct timeval tv;
213  int res;
214  fd_set rfds;
215  const char *_cmd;
216  char *cmd_buf = NULL;
217  size_t _cmd_len;
218 
219 #ifdef CONFIG_CTRL_IFACE_UDP
220  if (ctrl->cookie) {
221  char *pos;
222  _cmd_len = os_strlen(ctrl->cookie) + 1 + cmd_len;
223  cmd_buf = os_malloc(_cmd_len);
224  if (cmd_buf == NULL)
225  return -1;
226  _cmd = cmd_buf;
227  pos = cmd_buf;
228  os_strlcpy(pos, ctrl->cookie, _cmd_len);
229  pos += os_strlen(ctrl->cookie);
230  *pos++ = ' ';
231  os_memcpy(pos, cmd, cmd_len);
232  } else
233 #endif /* CONFIG_CTRL_IFACE_UDP */
234  {
235  _cmd = cmd;
236  _cmd_len = cmd_len;
237  }
238 
239  if (send(ctrl->s, _cmd, _cmd_len, 0) < 0) {
240  os_free(cmd_buf);
241  return -1;
242  }
243  os_free(cmd_buf);
244 
245  for (;;) {
246  tv.tv_sec = 2;
247  tv.tv_usec = 0;
248  FD_ZERO(&rfds);
249  FD_SET(ctrl->s, &rfds);
250  res = select(ctrl->s + 1, &rfds, NULL, NULL, &tv);
251  if (FD_ISSET(ctrl->s, &rfds)) {
252  res = recv(ctrl->s, reply, *reply_len, 0);
253  if (res < 0)
254  return res;
255  if (res > 0 && reply[0] == '<') {
256  /* This is an unsolicited message from
257  * wpa_supplicant, not the reply to the
258  * request. Use msg_cb to report this to the
259  * caller. */
260  if (msg_cb) {
261  /* Make sure the message is nul
262  * terminated. */
263  if ((size_t) res == *reply_len)
264  res = (*reply_len) - 1;
265  reply[res] = '\0';
266  msg_cb(reply, res);
267  }
268  continue;
269  }
270  *reply_len = res;
271  break;
272  } else {
273  return -2;
274  }
275  }
276  return 0;
277 }
278 #endif /* CTRL_IFACE_SOCKET */
279 
280 
281 static int wpa_ctrl_attach_helper(struct wpa_ctrl *ctrl, int attach)
282 {
283  char buf[10];
284  int ret;
285  size_t len = 10;
286 
287  ret = wpa_ctrl_request(ctrl, attach ? "ATTACH" : "DETACH", 6,
288  buf, &len, NULL);
289  if (ret < 0)
290  return ret;
291  if (len == 3 && os_memcmp(buf, "OK\n", 3) == 0)
292  return 0;
293  return -1;
294 }
295 
296 
297 int wpa_ctrl_attach(struct wpa_ctrl *ctrl)
298 {
299  return wpa_ctrl_attach_helper(ctrl, 1);
300 }
301 
302 
303 int wpa_ctrl_detach(struct wpa_ctrl *ctrl)
304 {
305  return wpa_ctrl_attach_helper(ctrl, 0);
306 }
307 
308 
309 #ifdef CTRL_IFACE_SOCKET
310 
311 int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len)
312 {
313  int res;
314 
315  res = recv(ctrl->s, reply, *reply_len, 0);
316  if (res < 0)
317  return res;
318  *reply_len = res;
319  return 0;
320 }
321 
322 
323 int wpa_ctrl_pending(struct wpa_ctrl *ctrl)
324 {
325  struct timeval tv;
326  fd_set rfds;
327  tv.tv_sec = 0;
328  tv.tv_usec = 0;
329  FD_ZERO(&rfds);
330  FD_SET(ctrl->s, &rfds);
331  select(ctrl->s + 1, &rfds, NULL, NULL, &tv);
332  return FD_ISSET(ctrl->s, &rfds);
333 }
334 
335 
336 int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl)
337 {
338  return ctrl->s;
339 }
340 
341 #endif /* CTRL_IFACE_SOCKET */
342 
343 
344 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
345 
346 #ifndef WPA_SUPPLICANT_NAMED_PIPE
347 #define WPA_SUPPLICANT_NAMED_PIPE "WpaSupplicant"
348 #endif
349 #define NAMED_PIPE_PREFIX TEXT("\\\\.\\pipe\\") TEXT(WPA_SUPPLICANT_NAMED_PIPE)
350 
351 struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
352 {
353  struct wpa_ctrl *ctrl;
354  DWORD mode;
355  TCHAR name[256];
356  int i, ret;
357 
358  ctrl = os_malloc(sizeof(*ctrl));
359  if (ctrl == NULL)
360  return NULL;
361  os_memset(ctrl, 0, sizeof(*ctrl));
362 
363 #ifdef UNICODE
364  if (ctrl_path == NULL)
365  ret = _snwprintf(name, 256, NAMED_PIPE_PREFIX);
366  else
367  ret = _snwprintf(name, 256, NAMED_PIPE_PREFIX TEXT("-%S"),
368  ctrl_path);
369 #else /* UNICODE */
370  if (ctrl_path == NULL)
371  ret = os_snprintf(name, 256, NAMED_PIPE_PREFIX);
372  else
373  ret = os_snprintf(name, 256, NAMED_PIPE_PREFIX "-%s",
374  ctrl_path);
375 #endif /* UNICODE */
376  if (ret < 0 || ret >= 256) {
377  os_free(ctrl);
378  return NULL;
379  }
380 
381  for (i = 0; i < 10; i++) {
382  ctrl->pipe = CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0,
383  NULL, OPEN_EXISTING, 0, NULL);
384  /*
385  * Current named pipe server side in wpa_supplicant is
386  * re-opening the pipe for new clients only after the previous
387  * one is taken into use. This leaves a small window for race
388  * conditions when two connections are being opened at almost
389  * the same time. Retry if that was the case.
390  */
391  if (ctrl->pipe != INVALID_HANDLE_VALUE ||
392  GetLastError() != ERROR_PIPE_BUSY)
393  break;
394  WaitNamedPipe(name, 1000);
395  }
396  if (ctrl->pipe == INVALID_HANDLE_VALUE) {
397  os_free(ctrl);
398  return NULL;
399  }
400 
401  mode = PIPE_READMODE_MESSAGE;
402  if (!SetNamedPipeHandleState(ctrl->pipe, &mode, NULL, NULL)) {
403  CloseHandle(ctrl->pipe);
404  os_free(ctrl);
405  return NULL;
406  }
407 
408  return ctrl;
409 }
410 
411 
412 void wpa_ctrl_close(struct wpa_ctrl *ctrl)
413 {
414  CloseHandle(ctrl->pipe);
415  os_free(ctrl);
416 }
417 
418 
419 int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
420  char *reply, size_t *reply_len,
421  void (*msg_cb)(char *msg, size_t len))
422 {
423  DWORD written;
424  DWORD readlen = *reply_len;
425 
426  if (!WriteFile(ctrl->pipe, cmd, cmd_len, &written, NULL))
427  return -1;
428 
429  if (!ReadFile(ctrl->pipe, reply, *reply_len, &readlen, NULL))
430  return -1;
431  *reply_len = readlen;
432 
433  return 0;
434 }
435 
436 
437 int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len)
438 {
439  DWORD len = *reply_len;
440  if (!ReadFile(ctrl->pipe, reply, *reply_len, &len, NULL))
441  return -1;
442  *reply_len = len;
443  return 0;
444 }
445 
446 
447 int wpa_ctrl_pending(struct wpa_ctrl *ctrl)
448 {
449  DWORD left;
450 
451  if (!PeekNamedPipe(ctrl->pipe, NULL, 0, NULL, &left, NULL))
452  return -1;
453  return left ? 1 : 0;
454 }
455 
456 
457 int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl)
458 {
459  return -1;
460 }
461 
462 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
463 
464 #endif /* CONFIG_CTRL_IFACE */
int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl)
Definition: wpa_ctrl.c:336
#define snprintf
Definition: c_input.c:141
int wpa_ctrl_pending(struct wpa_ctrl *ctrl)
Definition: wpa_ctrl.c:323
#define os_memset(s, c, n)
Definition: os.h:413
#define os_snprintf
Definition: os.h:459
#define os_strdup(s)
Definition: os.h:401
struct sockaddr_un dest
Definition: wpa_ctrl.c:55
int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len, void(*msg_cb)(char *msg, size_t len))
Definition: wpa_ctrl.c:208
int s
Definition: wpa_ctrl.c:53
void wpa_ctrl_close(struct wpa_ctrl *ctrl)
Definition: wpa_ctrl.c:137
#define os_malloc(s)
Definition: os.h:389
#define os_memcpy(d, s, n)
Definition: os.h:407
struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
Definition: wpa_ctrl.c:65
size_t os_strlcpy(char *dest, const char *src, size_t siz)
Definition: os_unix.c:323
int wpa_ctrl_attach(struct wpa_ctrl *ctrl)
Definition: wpa_ctrl.c:297
struct sockaddr_un local
Definition: wpa_ctrl.c:54
#define os_strlen(s)
Definition: os.h:420
#define os_free(p)
Definition: os.h:395
int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len)
Definition: wpa_ctrl.c:311
int wpa_ctrl_detach(struct wpa_ctrl *ctrl)
Definition: wpa_ctrl.c:303
#define os_memcmp(s1, s2, n)
Definition: os.h:416
#define NULL