~ubuntu-branches/ubuntu/lucid/wpasupplicant/lucid

« back to all changes in this revision

Viewing changes to wpa_ctrl.c

  • Committer: Bazaar Package Importer
  • Author(s): Kyle McMartin
  • Date: 2005-02-15 00:51:28 UTC
  • Revision ID: james.westby@ubuntu.com-20050215005128-xr4m8owiunur2008
Tags: upstream-0.3.8
ImportĀ upstreamĀ versionĀ 0.3.8

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * WPA Supplicant - wpa_supplicant control interface library
 
3
 * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.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 <stdlib.h>
 
16
#include <stdio.h>
 
17
#include <string.h>
 
18
#include <unistd.h>
 
19
#include <sys/types.h>
 
20
#include <sys/time.h>
 
21
#ifndef CONFIG_NATIVE_WINDOWS
 
22
#include <sys/socket.h>
 
23
#include <sys/un.h>
 
24
#endif /* CONFIG_NATIVE_WINDOWS */
 
25
 
 
26
#include "wpa_ctrl.h"
 
27
#ifdef CONFIG_NATIVE_WINDOWS
 
28
#include "common.h"
 
29
#endif /* CONFIG_NATIVE_WINDOWS */
 
30
 
 
31
 
 
32
struct wpa_ctrl {
 
33
        int s;
 
34
#ifdef CONFIG_CTRL_IFACE_UDP
 
35
        struct sockaddr_in local;
 
36
        struct sockaddr_in dest;
 
37
#else /* CONFIG_CTRL_IFACE_UDP */
 
38
        struct sockaddr_un local;
 
39
        struct sockaddr_un dest;
 
40
#endif /* CONFIG_CTRL_IFACE_UDP */
 
41
};
 
42
 
 
43
 
 
44
struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
 
45
{
 
46
        struct wpa_ctrl *ctrl;
 
47
#ifndef CONFIG_CTRL_IFACE_UDP
 
48
        static int counter = 0;
 
49
#endif /* CONFIG_CTRL_IFACE_UDP */
 
50
 
 
51
        ctrl = malloc(sizeof(*ctrl));
 
52
        if (ctrl == NULL)
 
53
                return NULL;
 
54
        memset(ctrl, 0, sizeof(*ctrl));
 
55
 
 
56
#ifdef CONFIG_CTRL_IFACE_UDP
 
57
        ctrl->s = socket(PF_INET, SOCK_DGRAM, 0);
 
58
        if (ctrl->s < 0) {
 
59
                perror("socket");
 
60
                free(ctrl);
 
61
                return NULL;
 
62
        }
 
63
 
 
64
        ctrl->local.sin_family = AF_INET;
 
65
        ctrl->local.sin_addr.s_addr = htonl((127 << 24) | 1);
 
66
        if (bind(ctrl->s, (struct sockaddr *) &ctrl->local,
 
67
                 sizeof(ctrl->local)) < 0) {
 
68
                close(ctrl->s);
 
69
                free(ctrl);
 
70
                return NULL;
 
71
        }
 
72
 
 
73
        ctrl->dest.sin_family = AF_INET;
 
74
        ctrl->dest.sin_addr.s_addr = htonl((127 << 24) | 1);
 
75
        ctrl->dest.sin_port = htons(9877);
 
76
        if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest,
 
77
                    sizeof(ctrl->dest)) < 0) {
 
78
                perror("connect");
 
79
                close(ctrl->s);
 
80
                free(ctrl);
 
81
                return NULL;
 
82
        }
 
83
#else /* CONFIG_CTRL_IFACE_UDP */
 
84
        ctrl->s = socket(PF_UNIX, SOCK_DGRAM, 0);
 
85
        if (ctrl->s < 0) {
 
86
                free(ctrl);
 
87
                return NULL;
 
88
        }
 
89
 
 
90
        ctrl->local.sun_family = AF_UNIX;
 
91
        snprintf(ctrl->local.sun_path, sizeof(ctrl->local.sun_path),
 
92
                 "/tmp/wpa_ctrl_%d-%d", getpid(), counter++);
 
93
        if (bind(ctrl->s, (struct sockaddr *) &ctrl->local,
 
94
                    sizeof(ctrl->local.sun_family) +
 
95
                 strlen(ctrl->local.sun_path)) < 0) {
 
96
                close(ctrl->s);
 
97
                free(ctrl);
 
98
                return NULL;
 
99
        }
 
100
 
 
101
        ctrl->dest.sun_family = AF_UNIX;
 
102
        strncpy(ctrl->dest.sun_path, ctrl_path, sizeof(ctrl->dest.sun_path));
 
103
        if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest,
 
104
                    sizeof(ctrl->dest.sun_family) +
 
105
                    strlen(ctrl->dest.sun_path)) < 0) {
 
106
                close(ctrl->s);
 
107
                unlink(ctrl->local.sun_path);
 
108
                free(ctrl);
 
109
                return NULL;
 
110
        }
 
111
#endif /* CONFIG_CTRL_IFACE_UDP */
 
112
 
 
113
        return ctrl;
 
114
}
 
115
 
 
116
 
 
117
void wpa_ctrl_close(struct wpa_ctrl *ctrl)
 
118
{
 
119
#ifndef CONFIG_CTRL_IFACE_UDP
 
120
        unlink(ctrl->local.sun_path);
 
121
#endif /* CONFIG_CTRL_IFACE_UDP */
 
122
        close(ctrl->s);
 
123
        free(ctrl);
 
124
}
 
125
 
 
126
 
 
127
int wpa_ctrl_request(struct wpa_ctrl *ctrl, char *cmd, size_t cmd_len,
 
128
                     char *reply, size_t *reply_len,
 
129
                     void (*msg_cb)(char *msg, size_t len))
 
130
{
 
131
        struct timeval tv;
 
132
        int res;
 
133
        fd_set rfds;
 
134
 
 
135
        if (send(ctrl->s, cmd, cmd_len, 0) < 0)
 
136
                return -1;
 
137
 
 
138
        for (;;) {
 
139
                tv.tv_sec = 2;
 
140
                tv.tv_usec = 0;
 
141
                FD_ZERO(&rfds);
 
142
                FD_SET(ctrl->s, &rfds);
 
143
                res = select(ctrl->s + 1, &rfds, NULL, NULL, &tv);
 
144
                if (FD_ISSET(ctrl->s, &rfds)) {
 
145
                        res = recv(ctrl->s, reply, *reply_len, 0);
 
146
                        if (res < 0)
 
147
                                return res;
 
148
                        if (res > 0 && reply[0] == '<') {
 
149
                                /* This is an unsolicited message from
 
150
                                 * wpa_supplicant, not the reply to the
 
151
                                 * request. Use msg_cb to report this to the
 
152
                                 * caller. */
 
153
                                if (msg_cb) {
 
154
                                        /* Make sure the message is nul
 
155
                                         * terminated. */
 
156
                                        if (res == *reply_len)
 
157
                                                res = (*reply_len) - 1;
 
158
                                        reply[res] = '\0';
 
159
                                        msg_cb(reply, res);
 
160
                                }
 
161
                                continue;
 
162
                        }
 
163
                        *reply_len = res;
 
164
                        break;
 
165
                } else {
 
166
                        return -2;
 
167
                }
 
168
        }
 
169
        return 0;
 
170
}
 
171
 
 
172
 
 
173
static int wpa_ctrl_attach_helper(struct wpa_ctrl *ctrl, int attach)
 
174
{
 
175
        char buf[10];
 
176
        int ret;
 
177
        size_t len = 10;
 
178
 
 
179
        ret = wpa_ctrl_request(ctrl, attach ? "ATTACH" : "DETACH", 6,
 
180
                               buf, &len, NULL);
 
181
        if (ret < 0)
 
182
                return ret;
 
183
        if (len == 3 && memcmp(buf, "OK\n", 3) == 0)
 
184
                return 0;
 
185
        return -1;
 
186
}
 
187
 
 
188
 
 
189
int wpa_ctrl_attach(struct wpa_ctrl *ctrl)
 
190
{
 
191
        return wpa_ctrl_attach_helper(ctrl, 1);
 
192
}
 
193
 
 
194
 
 
195
int wpa_ctrl_detach(struct wpa_ctrl *ctrl)
 
196
{
 
197
        return wpa_ctrl_attach_helper(ctrl, 0);
 
198
}
 
199
 
 
200
 
 
201
int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len)
 
202
{
 
203
        int res;
 
204
 
 
205
        res = recv(ctrl->s, reply, *reply_len, 0);
 
206
        if (res < 0)
 
207
                return res;
 
208
        *reply_len = res;
 
209
        return 0;
 
210
}
 
211
 
 
212
 
 
213
int wpa_ctrl_pending(struct wpa_ctrl *ctrl)
 
214
{
 
215
        struct timeval tv;
 
216
        int res;
 
217
        fd_set rfds;
 
218
        tv.tv_sec = 0;
 
219
        tv.tv_usec = 0;
 
220
        FD_ZERO(&rfds);
 
221
        FD_SET(ctrl->s, &rfds);
 
222
        res = select(ctrl->s + 1, &rfds, NULL, NULL, &tv);
 
223
        return FD_ISSET(ctrl->s, &rfds);
 
224
}
 
225
 
 
226
 
 
227
int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl)
 
228
{
 
229
        return ctrl->s;
 
230
}