a92913aedc8674804438c1c1a16f8a24ce153534
3 #include "utils/eloop.h"
4 #include "crypto/crypto.h"
5 #include "crypto/sha1.h"
6 #include <libubox/uloop.h>
7 #include <ucode/compiler.h>
9 static uc_value_t
*registry
;
11 static struct uloop_timeout gc_timer
;
13 static void uc_gc_timer(struct uloop_timeout
*timeout
)
18 uc_value_t
*uc_wpa_printf(uc_vm_t
*vm
, size_t nargs
)
20 uc_value_t
*level
= uc_fn_arg(0);
21 uc_value_t
*ret
, **args
;
22 uc_cfn_ptr_t _sprintf
;
26 _sprintf
= uc_stdlib_function("sprintf");
30 if (ucv_type(level
) == UC_INTEGER
) {
31 l
= ucv_int64_get(level
);
38 ret
= _sprintf(vm
, nargs
- start
);
39 if (ucv_type(ret
) != UC_STRING
)
42 wpa_printf(l
, "%s", ucv_string_get(ret
));
48 uc_value_t
*uc_wpa_getpid(uc_vm_t
*vm
, size_t nargs
)
50 return ucv_int64_new(getpid());
53 uc_value_t
*uc_wpa_sha1(uc_vm_t
*vm
, size_t nargs
)
55 u8 hash
[SHA1_MAC_LEN
];
56 char hash_hex
[2 * ARRAY_SIZE(hash
) + 1];
65 args
= alloca(nargs
* sizeof(*args
));
66 lens
= alloca(nargs
* sizeof(*lens
));
67 for (i
= 0; i
< nargs
; i
++) {
69 if (ucv_type(val
) != UC_STRING
)
72 args
[i
] = ucv_string_get(val
);
73 lens
[i
] = ucv_string_length(val
);
76 if (sha1_vector(nargs
, args
, lens
, hash
))
79 for (i
= 0; i
< ARRAY_SIZE(hash
); i
++)
80 sprintf(hash_hex
+ 2 * i
, "%02x", hash
[i
]);
82 return ucv_string_new_length(hash_hex
, 2 * ARRAY_SIZE(hash
));
85 uc_vm_t
*wpa_ucode_create_vm(void)
87 static uc_parse_config_t config
= {
88 .strict_declarations
= true,
89 .lstrip_blocks
= true,
94 uc_search_path_init(&config
.module_search_path
);
95 uc_search_path_add(&config
.module_search_path
, HOSTAPD_UC_PATH
"*.so");
96 uc_search_path_add(&config
.module_search_path
, HOSTAPD_UC_PATH
"*.uc");
98 uc_vm_init(&vm
, &config
);
100 uc_stdlib_load(uc_vm_scope_get(&vm
));
102 gc_timer
.cb
= uc_gc_timer
;
107 int wpa_ucode_run(const char *script
)
115 source
= uc_source_new_file(script
);
119 prog
= uc_compile(vm
.config
, source
, &err
);
120 uc_source_put(source
);
122 wpa_printf(MSG_ERROR
, "Error loading ucode: %s\n", err
);
126 ret
= uc_vm_execute(&vm
, prog
, &ops
);
127 uc_program_put(prog
);
131 registry
= ucv_array_new(&vm
);
132 uc_vm_registry_set(&vm
, "hostap.registry", registry
);
133 ucv_array_set(registry
, 0, ucv_get(ops
));
138 int wpa_ucode_call_prepare(const char *fname
)
140 uc_value_t
*obj
, *func
;
145 obj
= ucv_array_get(registry
, 0);
149 func
= ucv_object_get(obj
, fname
, NULL
);
150 if (!ucv_is_callable(func
))
153 uc_vm_stack_push(&vm
, ucv_get(obj
));
154 uc_vm_stack_push(&vm
, ucv_get(func
));
159 uc_value_t
*wpa_ucode_global_init(const char *name
, uc_resource_type_t
*global_type
)
161 uc_value_t
*global
= uc_resource_new(global_type
, NULL
);
164 uc_vm_registry_set(&vm
, "hostap.global", global
);
165 proto
= ucv_prototype_get(global
);
166 ucv_object_add(proto
, "data", ucv_get(ucv_object_new(&vm
)));
168 #define ADD_CONST(x) ucv_object_add(proto, #x, ucv_int64_new(x))
169 ADD_CONST(MSG_EXCESSIVE
);
170 ADD_CONST(MSG_MSGDUMP
);
171 ADD_CONST(MSG_DEBUG
);
173 ADD_CONST(MSG_WARNING
);
174 ADD_CONST(MSG_ERROR
);
177 ucv_object_add(uc_vm_scope_get(&vm
), name
, ucv_get(global
));
182 static uc_value_t
*wpa_ucode_prototype_clone(uc_value_t
*uval
)
184 uc_value_t
*proto
, *proto_new
;
186 proto
= ucv_prototype_get(uval
);
187 proto_new
= ucv_object_new(&vm
);
189 ucv_object_foreach(proto
, key
, val
)
190 ucv_object_add(proto_new
, key
, ucv_get(val
));
191 ucv_prototype_set(uval
, ucv_get(proto
));
196 void wpa_ucode_registry_add(uc_value_t
*reg
, uc_value_t
*val
, int *idx
)
201 while (ucv_array_get(reg
, i
))
204 ucv_array_set(reg
, i
, ucv_get(val
));
206 data
= ucv_object_new(&vm
);
207 ucv_object_add(wpa_ucode_prototype_clone(val
), "data", ucv_get(data
));
212 uc_value_t
*wpa_ucode_registry_get(uc_value_t
*reg
, int idx
)
217 return ucv_array_get(reg
, idx
- 1);
220 uc_value_t
*wpa_ucode_registry_remove(uc_value_t
*reg
, int idx
)
222 uc_value_t
*val
= wpa_ucode_registry_get(reg
, idx
);
225 ucv_array_set(reg
, idx
- 1, NULL
);
231 uc_value_t
*wpa_ucode_call(size_t nargs
)
233 if (uc_vm_call(&vm
, true, nargs
) != EXCEPTION_NONE
)
236 if (!gc_timer
.pending
)
237 uloop_timeout_set(&gc_timer
, 10);
239 return uc_vm_stack_pop(&vm
);
242 void wpa_ucode_free_vm(void)
247 uc_search_path_free(&vm
.config
->module_search_path
);