udp: Merge udp_send and udp_output
[dragonfly.git] / contrib / hostapd / src / drivers / driver_ps3.c
1 /*
2  * WPA Supplicant - PS3 Linux wireless extension driver interface
3  * Copyright 2007, 2008 Sony Corporation
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 #include <sys/ioctl.h>
17 #include "wireless_copy.h"
18 #include "common.h"
19 #include "wpa_common.h"
20 #include "driver.h"
21 #include "eloop.h"
22 #include "driver_wext.h"
23 #include "ieee802_11_defs.h"
24
25 static int wpa_driver_ps3_set_wpa_key(struct wpa_driver_wext_data *drv,
26                                 struct wpa_driver_associate_params *params)
27 {
28         int ret, i;
29         struct iwreq iwr;
30         char *buf, *str;
31
32         if (!params->psk && !params->passphrase) {
33                 wpa_printf(MSG_INFO, "%s:no PSK error", __func__);
34                 return -EINVAL;
35         }
36
37         os_memset(&iwr, 0, sizeof(iwr));
38         if (params->psk) {
39                 /* includes null */
40                 iwr.u.data.length = PMK_LEN * 2 + 1;
41                 buf = os_malloc(iwr.u.data.length);
42                 if (!buf)
43                         return -ENOMEM;
44                 str = buf;
45                 for (i = 0; i < PMK_LEN; i++) {
46                         str += snprintf(str, iwr.u.data.length - (str - buf),
47                                         "%02x", params->psk[i]);
48                 }
49         } else if (params->passphrase) {
50                 /* including quotations and null */
51                 iwr.u.data.length = strlen(params->passphrase) + 3;
52                 buf = os_malloc(iwr.u.data.length);
53                 if (!buf)
54                         return -ENOMEM;
55                 buf[0] = '"';
56                 os_memcpy(buf + 1, params->passphrase, iwr.u.data.length - 3);
57                 buf[iwr.u.data.length - 2] = '"';
58                 buf[iwr.u.data.length - 1] = '\0';
59         } else
60                 return -EINVAL;
61         iwr.u.data.pointer = (caddr_t) buf;
62         os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
63         ret = ioctl(drv->ioctl_sock, SIOCIWFIRSTPRIV, &iwr);
64         os_free(buf);
65
66         return ret;
67 }
68
69 static int wpa_driver_ps3_set_wep_keys(struct wpa_driver_wext_data *drv,
70                                 struct wpa_driver_associate_params *params)
71 {
72         int ret, i;
73         struct iwreq iwr;
74
75         for (i = 0; i < 4; i++) {
76                 os_memset(&iwr, 0, sizeof(iwr));
77                 os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
78                 iwr.u.encoding.flags = i + 1;
79                 if (params->wep_key_len[i]) {
80                         iwr.u.encoding.pointer = (caddr_t) params->wep_key[i];
81                         iwr.u.encoding.length = params->wep_key_len[i];
82                 } else
83                         iwr.u.encoding.flags = IW_ENCODE_NOKEY |
84                                 IW_ENCODE_DISABLED;
85
86                 if (ioctl(drv->ioctl_sock, SIOCSIWENCODE, &iwr) < 0) {
87                         perror("ioctl[SIOCSIWENCODE]");
88                         ret = -1;
89                 }
90         }
91         return ret;
92 }
93
94 static int wpa_driver_ps3_associate(void *priv,
95                                     struct wpa_driver_associate_params *params)
96 {
97         struct wpa_driver_wext_data *drv = priv;
98         int ret, value;
99
100         wpa_printf(MSG_DEBUG, "%s: <-", __func__);
101
102         /* clear BSSID */
103         if (!params->bssid &&
104             wpa_driver_wext_set_bssid(drv, NULL) < 0)
105                 ret = -1;
106
107         if (wpa_driver_wext_set_mode(drv, params->mode) < 0)
108                 ret = -1;
109
110         if (params->wpa_ie == NULL || params->wpa_ie_len == 0)
111                 value = IW_AUTH_WPA_VERSION_DISABLED;
112         else if (params->wpa_ie[0] == WLAN_EID_RSN)
113                 value = IW_AUTH_WPA_VERSION_WPA2;
114         else
115                 value = IW_AUTH_WPA_VERSION_WPA;
116         if (wpa_driver_wext_set_auth_param(drv,
117                                            IW_AUTH_WPA_VERSION, value) < 0)
118                 ret = -1;
119         value = wpa_driver_wext_cipher2wext(params->pairwise_suite);
120         if (wpa_driver_wext_set_auth_param(drv,
121                                            IW_AUTH_CIPHER_PAIRWISE, value) < 0)
122                 ret = -1;
123         value = wpa_driver_wext_cipher2wext(params->group_suite);
124         if (wpa_driver_wext_set_auth_param(drv,
125                                            IW_AUTH_CIPHER_GROUP, value) < 0)
126                 ret = -1;
127         value = wpa_driver_wext_keymgmt2wext(params->key_mgmt_suite);
128         if (wpa_driver_wext_set_auth_param(drv, IW_AUTH_KEY_MGMT, value) < 0)
129                 ret = -1;
130
131         /* set selected BSSID */
132         if (params->bssid &&
133             wpa_driver_wext_set_bssid(drv, params->bssid) < 0)
134                 ret = -1;
135
136         switch (params->group_suite) {
137         case CIPHER_NONE:
138                 ret = 0;
139                 break;
140         case CIPHER_WEP40:
141         case CIPHER_WEP104:
142                 ret = wpa_driver_ps3_set_wep_keys(drv, params);
143                 break;
144         case CIPHER_TKIP:
145         case CIPHER_CCMP:
146                 ret = wpa_driver_ps3_set_wpa_key(drv, params);
147                 break;
148         }
149
150         /* start to associate */
151         ret = wpa_driver_wext_set_ssid(drv, params->ssid, params->ssid_len);
152
153         wpa_printf(MSG_DEBUG, "%s: ->", __func__);
154
155         return ret;
156 }
157
158 static int wpa_driver_ps3_get_capa(void *priv, struct wpa_driver_capa *capa)
159 {
160         int ret;
161         wpa_printf(MSG_DEBUG, "%s:<-", __func__);
162
163         ret = wpa_driver_wext_get_capa(priv, capa);
164         if (ret) {
165                 wpa_printf(MSG_INFO, "%s: base wext returns error %d",
166                            __func__, ret);
167                 return ret;
168         }
169         /* PS3 hypervisor does association and 4way handshake by itself */
170         capa->flags |= WPA_DRIVER_FLAGS_4WAY_HANDSHAKE;
171         wpa_printf(MSG_DEBUG, "%s:->", __func__);
172         return 0;
173 }
174
175 const struct wpa_driver_ops wpa_driver_ps3_ops = {
176         .name = "ps3",
177         .desc = "PLAYSTATION3 Linux wireless extension driver",
178         .get_bssid = wpa_driver_wext_get_bssid,
179         .get_ssid = wpa_driver_wext_get_ssid,
180         .scan = wpa_driver_wext_scan,
181         .get_scan_results2 = wpa_driver_wext_get_scan_results,
182         .associate = wpa_driver_ps3_associate, /* PS3 */
183         .init = wpa_driver_wext_init,
184         .deinit = wpa_driver_wext_deinit,
185         .get_capa = wpa_driver_ps3_get_capa, /* PS3 */
186 };