tizen 2.4 release
[profile/mobile/platform/kernel/linux-3.10-sc7730.git] / drivers / net / wireless / sc2331 / wlan_hostapd_conf.c
1 #include <linux/types.h>
2 #include <linux/init.h>
3 #include <linux/mm.h>
4 #include <linux/fs.h>
5 #include <linux/fs_struct.h>
6 #include <linux/path.h>
7 #include <linux/uaccess.h>
8 #include <linux/slab.h>
9 #include "wlan_common.h"
10
11 static int hex2num(char c)
12 {
13         if (c >= '0' && c <= '9')
14                 return c - '0';
15
16         if (c >= 'a' && c <= 'f')
17                 return c - 'a' + 10;
18
19         if (c >= 'A' && c <= 'F')
20                 return c - 'A' + 10;
21
22         return -1;
23 }
24
25 static int hex2byte(const char *hex)
26 {
27         int a, b;
28
29         a = hex2num(*hex++);
30         if (a < 0)
31                 return -1;
32
33         b = hex2num(*hex++);
34         if (b < 0)
35                 return -1;
36
37         return (a << 4) | b;
38 }
39
40 /**
41  * hexstr2bin - Convert ASCII hex string into binary data
42  * @hex: ASCII hex string (e.g., "01ab")
43  * @buf: Buffer for the binary data
44  * @len: Length of the text to convert in bytes (of buf); hex will be double
45  * this size
46  * Returns: 0 on success, -1 on failure (invalid hex string)
47  */
48 static int hexstr2bin(const char *hex, u8 *buf, size_t len)
49 {
50         size_t i;
51         int a;
52         const char *ipos = hex;
53
54         u8 *opos = buf;
55         for (i = 0; i < len; i++) {
56                 a = hex2byte(ipos);
57                 if (a < 0)
58                         return -1;
59                 *opos++ = a;
60                 ipos += 2;
61         }
62
63         return 0;
64 }
65
66 static struct hostap_conf *hostap_conf_create(void)
67 {
68         struct hostap_conf *conf = NULL;
69         conf = kmalloc(sizeof(struct hostap_conf), GFP_KERNEL);
70
71         return conf;
72 }
73
74 static int fp_size(struct file *f)
75 {
76         int error = -EBADF;
77         struct kstat stat;
78
79 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
80         error = vfs_getattr(&f->f_path, &stat);
81 #else
82         error = vfs_getattr(f->f_path.mnt, f->f_path.dentry, &stat);
83 #endif
84
85         if (error == 0) {
86                 return stat.size;
87         } else {
88                 pr_err("get hostapd conf file stat error\n");
89                 return error;
90         }
91 }
92
93 static int hostap_conf_read(char *filename, char **buf)
94 {
95         struct file *fp;
96         mm_segment_t fs;
97         int size = 0;
98         loff_t pos = 0;
99
100         fp = filp_open(filename, O_RDONLY, 0);
101         if (IS_ERR(fp)) {
102                 pr_err("open %s file error\n", filename);
103                 goto end;
104         }
105
106         fs = get_fs();
107         set_fs(KERNEL_DS);
108         size = fp_size(fp);
109         if (size <= 0) {
110                 pr_err("load file:%s error\n", filename);
111                 goto error;
112         }
113
114         *buf = kzalloc(size + 1, GFP_KERNEL);
115         vfs_read(fp, *buf, size, &pos);
116
117 error:
118         filp_close(fp, NULL);
119         set_fs(fs);
120 end:
121         return size;
122 }
123
124 static char *get_line(char *buf, char *end)
125 {
126         if (buf == NULL || buf >= end)
127                 return NULL;
128         while (buf != end && *buf != '\n')
129                 buf++;
130
131         return buf;
132 }
133
134 static unsigned char hostap_conf_parse(char *buf, int size,
135                                        struct hostap_conf *conf)
136 {
137         unsigned char ret = 0;
138         char *spos = buf, *epos = NULL, *pos = NULL;
139         int line = 0, errors = 0;
140
141         if (!buf || !conf)
142                 return 0;
143
144         for (; (epos = get_line(spos, buf + size)); (spos = epos + 1)) {
145                 line++;
146                 if (spos[0] == '#')
147                         continue;
148                 pos = spos;
149                 while (*pos != '\0' && pos <= epos) {
150                         if (*pos == '\n') {
151                                 *pos = '\0';
152                                 break;
153                         }
154                         pos++;
155                 }
156
157                 if (spos[0] == '\0')
158                         continue;
159
160                 pos = strchr(spos, '=');
161                 if (pos == NULL) {
162                         pr_err("Line %d: invalid line '%s'", line, spos);
163                         errors++;
164                         continue;
165                 }
166
167                 *pos = '\0';
168                 pos++;
169
170                 if (strcmp(spos, "wpa_psk") == 0) {
171                         strlcpy(conf->wpa_psk, pos, sizeof(conf->wpa_psk));
172                         conf->len = strlen(pos);
173                 } else {
174                         continue;
175                 }
176         }
177
178         return ret;
179 }
180
181 int hostap_conf_load(char *filename, unsigned char *key_val)
182 {
183         struct hostap_conf *conf = NULL;
184         char *buf = NULL;
185         int size = 0;
186
187         if (filename == NULL)
188                 filename = HOSTAP_CONF_FILE_NAME;
189
190         size = hostap_conf_read(filename, &buf);
191         if (size > 0) {
192                 conf = hostap_conf_create();
193                 if (conf == NULL) {
194                         kfree(buf);
195                         pr_err("create hostap_conf struct error.\n");
196                         return -EINVAL;
197                 }
198
199                 hostap_conf_parse(buf, size, conf);
200                 if (conf->len > 64) {
201                         pr_err("wpa_psk len is error.(%d)\n", conf->len);
202                         return -EINVAL;
203                 }
204                 hexstr2bin(conf->wpa_psk, key_val, conf->len / 2);
205                 kfree(buf);
206         }
207
208         return 0;
209 }