3 #include "utils/includes.h"
4 #include "utils/common.h"
5 #include "utils/ucode.h"
7 #include "ap_drv_ops.h"
8 #include <libubox/uloop.h>
10 static uc_resource_type_t
*global_type
, *bss_type
, *iface_type
;
11 static struct hapd_interfaces
*interfaces
;
12 static uc_value_t
*global
, *bss_registry
, *iface_registry
;
16 hostapd_ucode_bss_get_uval(struct hostapd_data
*hapd
)
21 return wpa_ucode_registry_get(bss_registry
, hapd
->ucode
.idx
);
23 val
= uc_resource_new(bss_type
, hapd
);
24 wpa_ucode_registry_add(bss_registry
, val
, &hapd
->ucode
.idx
);
30 hostapd_ucode_iface_get_uval(struct hostapd_iface
*hapd
)
35 return wpa_ucode_registry_get(iface_registry
, hapd
->ucode
.idx
);
37 val
= uc_resource_new(iface_type
, hapd
);
38 wpa_ucode_registry_add(iface_registry
, val
, &hapd
->ucode
.idx
);
44 hostapd_ucode_update_bss_list(struct hostapd_iface
*iface
)
46 uc_value_t
*ifval
, *list
;
49 list
= ucv_array_new(vm
);
50 for (i
= 0; i
< iface
->num_bss
; i
++) {
51 struct hostapd_data
*hapd
= iface
->bss
[i
];
52 uc_value_t
*val
= hostapd_ucode_bss_get_uval(hapd
);
53 uc_value_t
*proto
= ucv_prototype_get(val
);
55 ucv_object_add(proto
, "name", ucv_get(ucv_string_new(hapd
->conf
->iface
)));
56 ucv_object_add(proto
, "index", ucv_int64_new(i
));
57 ucv_array_set(list
, i
, ucv_get(val
));
60 ifval
= hostapd_ucode_iface_get_uval(iface
);
61 ucv_object_add(ucv_prototype_get(ifval
), "bss", ucv_get(list
));
65 hostapd_ucode_update_interfaces(void)
67 uc_value_t
*ifs
= ucv_object_new(vm
);
70 for (i
= 0; i
< interfaces
->count
; i
++) {
71 struct hostapd_iface
*iface
= interfaces
->iface
[i
];
73 ucv_object_add(ifs
, iface
->phy
, ucv_get(hostapd_ucode_iface_get_uval(iface
)));
74 hostapd_ucode_update_bss_list(iface
);
77 ucv_object_add(ucv_prototype_get(global
), "interfaces", ucv_get(ifs
));
82 uc_hostapd_add_iface(uc_vm_t
*vm
, size_t nargs
)
84 uc_value_t
*iface
= uc_fn_arg(0);
87 if (ucv_type(iface
) != UC_STRING
)
88 return ucv_int64_new(-1);
90 ret
= hostapd_add_iface(interfaces
, ucv_string_get(iface
));
91 hostapd_ucode_update_interfaces();
93 return ucv_int64_new(ret
);
97 uc_hostapd_remove_iface(uc_vm_t
*vm
, size_t nargs
)
99 uc_value_t
*iface
= uc_fn_arg(0);
101 if (ucv_type(iface
) != UC_STRING
)
104 hostapd_remove_iface(interfaces
, ucv_string_get(iface
));
105 hostapd_ucode_update_interfaces();
111 uc_hostapd_bss_set_config(uc_vm_t
*vm
, size_t nargs
)
113 struct hostapd_data
*hapd
= uc_fn_thisval("hostapd.bss");
114 struct hostapd_bss_config
*old_bss
;
115 struct hostapd_iface
*iface
;
116 struct hostapd_config
*conf
;
117 uc_value_t
*file
= uc_fn_arg(0);
118 uc_value_t
*index
= uc_fn_arg(1);
119 unsigned int i
, idx
= 0;
122 if (!hapd
|| ucv_type(file
) != UC_STRING
)
125 if (ucv_type(index
) == UC_INTEGER
)
126 idx
= ucv_int64_get(index
);
129 conf
= interfaces
->config_read_cb(ucv_string_get(file
));
130 if (!conf
|| idx
> conf
->num_bss
|| !conf
->bss
[idx
])
133 hostapd_bss_deinit_no_free(hapd
);
134 hostapd_drv_stop_ap(hapd
);
135 hostapd_free_hapd_data(hapd
);
137 old_bss
= hapd
->conf
;
138 for (i
= 0; i
< iface
->conf
->num_bss
; i
++)
139 if (iface
->conf
->bss
[i
] == hapd
->conf
)
140 iface
->conf
->bss
[i
] = conf
->bss
[idx
];
141 hapd
->conf
= conf
->bss
[idx
];
142 conf
->bss
[idx
] = old_bss
;
143 hostapd_config_free(conf
);
145 hostapd_setup_bss(hapd
, hapd
== iface
->bss
[0], !iface
->conf
->mbssid
);
150 return ucv_int64_new(ret
);
154 hostapd_remove_iface_bss_conf(struct hostapd_config
*iconf
,
155 struct hostapd_bss_config
*conf
)
159 for (i
= 0; i
< iconf
->num_bss
; i
++)
160 if (iconf
->bss
[i
] == conf
)
163 if (i
== iconf
->num_bss
)
166 for (i
++; i
< iconf
->num_bss
; i
++)
167 iconf
->bss
[i
- 1] = iconf
->bss
[i
];
173 uc_hostapd_bss_delete(uc_vm_t
*vm
, size_t nargs
)
175 struct hostapd_data
*hapd
= uc_fn_thisval("hostapd.bss");
176 struct hostapd_iface
*iface
;
179 if (!hapd
|| hapd
== hapd
->iface
->bss
[0])
183 for (idx
= 0; idx
< iface
->num_bss
; idx
++)
184 if (iface
->bss
[idx
] == hapd
)
187 if (idx
== iface
->num_bss
)
190 for (i
= idx
+ 1; i
< iface
->num_bss
; i
++)
191 iface
->bss
[i
- 1] = iface
->bss
[i
];
194 hostapd_drv_stop_ap(hapd
);
195 hostapd_bss_deinit(hapd
);
196 hostapd_remove_iface_bss_conf(iface
->conf
, hapd
->conf
);
197 hostapd_config_free_bss(hapd
->conf
);
200 hostapd_ucode_update_bss_list(iface
);
207 uc_hostapd_iface_add_bss(uc_vm_t
*vm
, size_t nargs
)
209 struct hostapd_iface
*iface
= uc_fn_thisval("hostapd.iface");
210 struct hostapd_bss_config
*bss
;
211 struct hostapd_config
*conf
;
212 struct hostapd_data
*hapd
;
213 uc_value_t
*file
= uc_fn_arg(0);
214 uc_value_t
*index
= uc_fn_arg(1);
215 unsigned int idx
= 0;
216 uc_value_t
*ret
= NULL
;
218 if (!iface
|| ucv_type(file
) != UC_STRING
)
221 if (ucv_type(index
) == UC_INTEGER
)
222 idx
= ucv_int64_get(index
);
224 conf
= interfaces
->config_read_cb(ucv_string_get(file
));
225 if (!conf
|| idx
> conf
->num_bss
|| !conf
->bss
[idx
])
228 bss
= conf
->bss
[idx
];
229 hapd
= hostapd_alloc_bss_data(iface
, iface
->conf
, bss
);
233 hapd
->driver
= iface
->bss
[0]->driver
;
234 hapd
->drv_priv
= iface
->bss
[0]->drv_priv
;
235 if (interfaces
->ctrl_iface_init
&&
236 interfaces
->ctrl_iface_init(hapd
) < 0)
239 if (iface
->state
== HAPD_IFACE_ENABLED
&&
240 hostapd_setup_bss(hapd
, -1, true))
243 iface
->bss
= os_realloc_array(iface
->bss
, iface
->num_bss
+ 1,
244 sizeof(*iface
->bss
));
245 iface
->bss
[iface
->num_bss
++] = hapd
;
247 iface
->conf
->bss
= os_realloc_array(iface
->conf
->bss
,
248 iface
->conf
->num_bss
+ 1,
249 sizeof(*iface
->conf
->bss
));
250 iface
->conf
->bss
[iface
->conf
->num_bss
] = bss
;
251 conf
->bss
[idx
] = NULL
;
252 ret
= hostapd_ucode_bss_get_uval(hapd
);
253 hostapd_ucode_update_bss_list(iface
);
257 if (interfaces
->ctrl_iface_deinit
)
258 interfaces
->ctrl_iface_deinit(hapd
);
260 hostapd_free_hapd_data(hapd
);
263 hostapd_config_free(conf
);
268 uc_hostapd_bss_ctrl(uc_vm_t
*vm
, size_t nargs
)
270 struct hostapd_data
*hapd
= uc_fn_thisval("hostapd.bss");
271 uc_value_t
*arg
= uc_fn_arg(0);
272 struct sockaddr_storage from
= {};
273 static char reply
[4096];
276 if (!hapd
|| !interfaces
->ctrl_iface_recv
||
277 ucv_type(arg
) != UC_STRING
)
280 reply_len
= interfaces
->ctrl_iface_recv(hapd
, ucv_string_get(arg
),
281 reply
, sizeof(reply
),
282 &from
, sizeof(from
));
286 if (reply_len
&& reply
[reply_len
- 1] == '\n')
289 return ucv_string_new_length(reply
, reply_len
);
292 int hostapd_ucode_init(struct hapd_interfaces
*ifaces
)
294 static const uc_function_list_t global_fns
[] = {
295 { "printf", uc_wpa_printf
},
296 { "getpid", uc_wpa_getpid
},
297 { "sha1", uc_wpa_sha1
},
298 { "add_iface", uc_hostapd_add_iface
},
299 { "remove_iface", uc_hostapd_remove_iface
},
301 static const uc_function_list_t bss_fns
[] = {
302 { "ctrl", uc_hostapd_bss_ctrl
},
303 { "set_config", uc_hostapd_bss_set_config
},
304 { "delete", uc_hostapd_bss_delete
},
306 static const uc_function_list_t iface_fns
[] = {
307 { "add_bss", uc_hostapd_iface_add_bss
}
309 uc_value_t
*data
, *proto
;
312 vm
= wpa_ucode_create_vm();
314 global_type
= uc_type_declare(vm
, "hostapd.global", global_fns
, NULL
);
315 bss_type
= uc_type_declare(vm
, "hostapd.bss", bss_fns
, NULL
);
316 iface_type
= uc_type_declare(vm
, "hostapd.iface", iface_fns
, NULL
);
318 bss_registry
= ucv_array_new(vm
);
319 uc_vm_registry_set(vm
, "hostap.bss_registry", bss_registry
);
321 iface_registry
= ucv_array_new(vm
);
322 uc_vm_registry_set(vm
, "hostap.iface_registry", iface_registry
);
324 global
= wpa_ucode_global_init("hostapd", global_type
);
326 if (wpa_ucode_run(HOSTAPD_UC_PATH
"hostapd.uc"))
337 void hostapd_ucode_free(void)
339 if (wpa_ucode_call_prepare("shutdown") == 0)
340 ucv_put(wpa_ucode_call(0));
344 void hostapd_ucode_free_iface(struct hostapd_iface
*iface
)
346 wpa_ucode_registry_remove(iface_registry
, iface
->ucode
.idx
);
349 void hostapd_ucode_add_bss(struct hostapd_data
*hapd
)
353 if (wpa_ucode_call_prepare("bss_add"))
356 val
= hostapd_ucode_bss_get_uval(hapd
);
357 uc_value_push(ucv_get(ucv_string_new(hapd
->conf
->iface
)));
358 uc_value_push(ucv_get(val
));
359 ucv_put(wpa_ucode_call(2));
363 void hostapd_ucode_reload_bss(struct hostapd_data
*hapd
, int reconf
)
367 if (wpa_ucode_call_prepare("bss_reload"))
370 val
= hostapd_ucode_bss_get_uval(hapd
);
371 uc_value_push(ucv_get(ucv_string_new(hapd
->conf
->iface
)));
372 uc_value_push(ucv_get(val
));
373 uc_value_push(ucv_int64_new(reconf
));
374 ucv_put(wpa_ucode_call(3));
378 void hostapd_ucode_free_bss(struct hostapd_data
*hapd
)
382 val
= wpa_ucode_registry_remove(bss_registry
, hapd
->ucode
.idx
);
387 if (wpa_ucode_call_prepare("bss_remove"))
390 uc_value_push(ucv_string_new(hapd
->conf
->iface
));
391 uc_value_push(ucv_get(val
));
392 ucv_put(wpa_ucode_call(2));