1 #include "utils/includes.h"
2 #include "utils/common.h"
3 #include "utils/ucode.h"
4 #include "drivers/driver.h"
5 #include "ap/hostapd.h"
6 #include "wpa_supplicant_i.h"
7 #include "wps_supplicant.h"
11 static struct wpa_global
*wpa_global
;
12 static uc_resource_type_t
*global_type
, *iface_type
;
13 static uc_value_t
*global
, *iface_registry
;
17 wpas_ucode_iface_get_uval(struct wpa_supplicant
*wpa_s
)
22 return wpa_ucode_registry_get(iface_registry
, wpa_s
->ucode
.idx
);
24 val
= uc_resource_new(iface_type
, wpa_s
);
25 wpa_s
->ucode
.idx
= wpa_ucode_registry_add(iface_registry
, val
);
31 wpas_ucode_update_interfaces(void)
33 uc_value_t
*ifs
= ucv_object_new(vm
);
34 struct wpa_supplicant
*wpa_s
;
37 for (wpa_s
= wpa_global
->ifaces
; wpa_s
; wpa_s
= wpa_s
->next
)
38 ucv_object_add(ifs
, wpa_s
->ifname
, ucv_get(wpas_ucode_iface_get_uval(wpa_s
)));
40 ucv_object_add(ucv_prototype_get(global
), "interfaces", ucv_get(ifs
));
44 void wpas_ucode_add_bss(struct wpa_supplicant
*wpa_s
)
48 if (wpa_ucode_call_prepare("iface_add"))
51 uc_value_push(ucv_get(ucv_string_new(wpa_s
->ifname
)));
52 uc_value_push(ucv_get(wpas_ucode_iface_get_uval(wpa_s
)));
53 ucv_put(wpa_ucode_call(2));
57 void wpas_ucode_free_bss(struct wpa_supplicant
*wpa_s
)
61 val
= wpa_ucode_registry_remove(iface_registry
, wpa_s
->ucode
.idx
);
66 if (wpa_ucode_call_prepare("iface_remove"))
69 uc_value_push(ucv_get(ucv_string_new(wpa_s
->ifname
)));
70 uc_value_push(ucv_get(val
));
71 ucv_put(wpa_ucode_call(2));
75 void wpas_ucode_update_state(struct wpa_supplicant
*wpa_s
)
80 val
= wpa_ucode_registry_get(iface_registry
, wpa_s
->ucode
.idx
);
84 if (wpa_ucode_call_prepare("state"))
87 state
= wpa_supplicant_state_txt(wpa_s
->wpa_state
);
88 uc_value_push(ucv_get(ucv_string_new(wpa_s
->ifname
)));
89 uc_value_push(ucv_get(val
));
90 uc_value_push(ucv_get(ucv_string_new(state
)));
91 ucv_put(wpa_ucode_call(3));
95 void wpas_ucode_event(struct wpa_supplicant
*wpa_s
, int event
, union wpa_event_data
*data
)
100 if (event
!= EVENT_CH_SWITCH_STARTED
)
103 val
= wpa_ucode_registry_get(iface_registry
, wpa_s
->ucode
.idx
);
107 if (wpa_ucode_call_prepare("event"))
110 uc_value_push(ucv_get(ucv_string_new(wpa_s
->ifname
)));
111 uc_value_push(ucv_get(val
));
112 uc_value_push(ucv_get(ucv_string_new(event_to_string(event
))));
113 val
= ucv_object_new(vm
);
114 uc_value_push(ucv_get(val
));
116 if (event
== EVENT_CH_SWITCH_STARTED
) {
117 ucv_object_add(val
, "csa_count", ucv_int64_new(data
->ch_switch
.count
));
118 ucv_object_add(val
, "frequency", ucv_int64_new(data
->ch_switch
.freq
));
119 ucv_object_add(val
, "sec_chan_offset", ucv_int64_new(data
->ch_switch
.ch_offset
));
120 ucv_object_add(val
, "center_freq1", ucv_int64_new(data
->ch_switch
.cf1
));
121 ucv_object_add(val
, "center_freq2", ucv_int64_new(data
->ch_switch
.cf2
));
124 ucv_put(wpa_ucode_call(4));
128 static const char *obj_stringval(uc_value_t
*obj
, const char *name
)
130 uc_value_t
*val
= ucv_object_get(obj
, name
, NULL
);
132 return ucv_string_get(val
);
136 uc_wpas_add_iface(uc_vm_t
*vm
, size_t nargs
)
138 uc_value_t
*info
= uc_fn_arg(0);
139 uc_value_t
*driver
= ucv_object_get(info
, "driver", NULL
);
140 uc_value_t
*ifname
= ucv_object_get(info
, "iface", NULL
);
141 uc_value_t
*bridge
= ucv_object_get(info
, "bridge", NULL
);
142 uc_value_t
*config
= ucv_object_get(info
, "config", NULL
);
143 uc_value_t
*ctrl
= ucv_object_get(info
, "ctrl", NULL
);
144 struct wpa_interface iface
;
147 if (ucv_type(info
) != UC_OBJECT
)
150 iface
= (struct wpa_interface
){
152 .ifname
= ucv_string_get(ifname
),
153 .bridge_ifname
= ucv_string_get(bridge
),
154 .confname
= ucv_string_get(config
),
155 .ctrl_interface
= ucv_string_get(ctrl
),
160 if (ucv_type(driver
) != UC_STRING
)
164 drvname
= ucv_string_get(driver
);
165 for (int i
= 0; wpa_drivers
[i
]; i
++) {
166 if (!strcmp(drvname
, wpa_drivers
[i
]->name
))
167 iface
.driver
= wpa_drivers
[i
]->name
;
174 if (!iface
.ifname
|| !iface
.confname
)
177 ret
= wpa_supplicant_add_iface(wpa_global
, &iface
, 0) ? 0 : -1;
178 wpas_ucode_update_interfaces();
181 return ucv_int64_new(ret
);
185 uc_wpas_remove_iface(uc_vm_t
*vm
, size_t nargs
)
187 struct wpa_supplicant
*wpa_s
= NULL
;
188 uc_value_t
*ifname_arg
= uc_fn_arg(0);
189 const char *ifname
= ucv_string_get(ifname_arg
);
195 for (wpa_s
= wpa_global
->ifaces
; wpa_s
; wpa_s
= wpa_s
->next
)
196 if (!strcmp(wpa_s
->ifname
, ifname
))
202 ret
= wpa_supplicant_remove_iface(wpa_global
, wpa_s
, 0);
203 wpas_ucode_update_interfaces();
206 return ucv_int64_new(ret
);
210 uc_wpas_iface_status(uc_vm_t
*vm
, size_t nargs
)
212 struct wpa_supplicant
*wpa_s
= uc_fn_thisval("wpas.iface");
214 uc_value_t
*ret
, *val
;
219 ret
= ucv_object_new(vm
);
221 val
= ucv_string_new(wpa_supplicant_state_txt(wpa_s
->wpa_state
));
222 ucv_object_add(ret
, "state", ucv_get(val
));
224 bss
= wpa_s
->current_bss
;
229 ie
= wpa_bss_get_ie(bss
, WLAN_EID_HT_OPERATION
);
230 if (ie
&& ie
[1] >= 2) {
231 const struct ieee80211_ht_operation
*ht_oper
;
234 ht_oper
= (const void *) (ie
+ 2);
235 sec
= ht_oper
->ht_param
& HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK
;
236 if (sec
== HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE
)
238 else if (sec
== HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW
)
242 ucv_object_add(ret
, "sec_chan_offset", ucv_int64_new(sec_chan
));
243 ucv_object_add(ret
, "frequency", ucv_int64_new(bss
->freq
));
248 struct hostapd_iface
*ifmsh
= wpa_s
->ifmsh
;
250 ucv_object_add(ret
, "sec_chan_offset", ucv_int64_new(ifmsh
->conf
->secondary_channel
));
251 ucv_object_add(ret
, "frequency", ucv_int64_new(ifmsh
->freq
));
258 int wpas_ucode_init(struct wpa_global
*gl
)
260 static const uc_function_list_t global_fns
[] = {
261 { "printf", uc_wpa_printf
},
262 { "getpid", uc_wpa_getpid
},
263 { "add_iface", uc_wpas_add_iface
},
264 { "remove_iface", uc_wpas_remove_iface
},
266 static const uc_function_list_t iface_fns
[] = {
267 { "status", uc_wpas_iface_status
},
269 uc_value_t
*data
, *proto
;
272 vm
= wpa_ucode_create_vm();
274 global_type
= uc_type_declare(vm
, "wpas.global", global_fns
, NULL
);
275 iface_type
= uc_type_declare(vm
, "wpas.iface", iface_fns
, NULL
);
277 iface_registry
= ucv_array_new(vm
);
278 uc_vm_registry_set(vm
, "wpas.iface_registry", iface_registry
);
280 global
= wpa_ucode_global_init("wpas", global_type
);
282 if (wpa_ucode_run(HOSTAPD_UC_PATH
"wpa_supplicant.uc"))
293 void wpas_ucode_free(void)
295 if (wpa_ucode_call_prepare("shutdown") == 0)
296 ucv_put(wpa_ucode_call(0));