bpf.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814
  1. #include <sys/resource.h>
  2. #include <sys/types.h>
  3. #include <sys/socket.h>
  4. #include <net/if.h>
  5. #include <stdint.h>
  6. #include <stdio.h>
  7. #include <errno.h>
  8. #include <unistd.h>
  9. #include <bpf/bpf.h>
  10. #include <bpf/libbpf.h>
  11. #include "ucode/module.h"
  12. #define err_return_int(err, ...) do { set_error(err, __VA_ARGS__); return -1; } while(0)
  13. #define err_return(err, ...) do { set_error(err, __VA_ARGS__); return NULL; } while(0)
  14. #define TRUE ucv_boolean_new(true)
  15. static uc_resource_type_t *module_type, *map_type, *map_iter_type, *program_type;
  16. static uc_value_t *registry;
  17. static uc_vm_t *debug_vm;
  18. static struct {
  19. int code;
  20. char *msg;
  21. } last_error;
  22. struct uc_bpf_fd {
  23. int fd;
  24. bool close;
  25. };
  26. struct uc_bpf_map {
  27. struct uc_bpf_fd fd; /* must be first */
  28. unsigned int key_size, val_size;
  29. };
  30. struct uc_bpf_map_iter {
  31. int fd;
  32. unsigned int key_size;
  33. bool has_next;
  34. uint8_t key[];
  35. };
  36. __attribute__((format(printf, 2, 3))) static void
  37. set_error(int errcode, const char *fmt, ...)
  38. {
  39. va_list ap;
  40. free(last_error.msg);
  41. last_error.code = errcode;
  42. last_error.msg = NULL;
  43. if (fmt) {
  44. va_start(ap, fmt);
  45. xvasprintf(&last_error.msg, fmt, ap);
  46. va_end(ap);
  47. }
  48. }
  49. static void init_env(void)
  50. {
  51. static bool init_done = false;
  52. struct rlimit limit = {
  53. .rlim_cur = RLIM_INFINITY,
  54. .rlim_max = RLIM_INFINITY,
  55. };
  56. if (init_done)
  57. return;
  58. setrlimit(RLIMIT_MEMLOCK, &limit);
  59. init_done = true;
  60. }
  61. static uc_value_t *
  62. uc_bpf_error(uc_vm_t *vm, size_t nargs)
  63. {
  64. uc_value_t *numeric = uc_fn_arg(0);
  65. const char *msg = last_error.msg;
  66. int code = last_error.code;
  67. uc_stringbuf_t *buf;
  68. const char *s;
  69. if (last_error.code == 0)
  70. return NULL;
  71. set_error(0, NULL);
  72. if (ucv_is_truish(numeric))
  73. return ucv_int64_new(code);
  74. buf = ucv_stringbuf_new();
  75. if (code < 0 && msg) {
  76. ucv_stringbuf_addstr(buf, msg, strlen(msg));
  77. } else {
  78. s = strerror(code);
  79. ucv_stringbuf_addstr(buf, s, strlen(s));
  80. if (msg)
  81. ucv_stringbuf_printf(buf, ": %s", msg);
  82. }
  83. return ucv_stringbuf_finish(buf);
  84. }
  85. static int
  86. uc_bpf_module_set_opts(struct bpf_object *obj, uc_value_t *opts)
  87. {
  88. uc_value_t *val;
  89. if (!opts)
  90. return 0;
  91. if (ucv_type(opts) != UC_OBJECT)
  92. err_return_int(EINVAL, "options argument");
  93. if ((val = ucv_object_get(opts, "rodata", NULL)) != NULL) {
  94. struct bpf_map *map = NULL;
  95. if (ucv_type(val) != UC_STRING)
  96. err_return_int(EINVAL, "rodata type");
  97. while ((map = bpf_object__next_map(obj, map)) != NULL) {
  98. if (!strstr(bpf_map__name(map), ".rodata"))
  99. continue;
  100. break;
  101. }
  102. if (!map)
  103. err_return_int(errno, "rodata map");
  104. if (bpf_map__set_initial_value(map, ucv_string_get(val),
  105. ucv_string_length(val)))
  106. err_return_int(errno, "rodata");
  107. }
  108. if ((val = ucv_object_get(opts, "program-type", NULL)) != NULL) {
  109. if (ucv_type(val) != UC_OBJECT)
  110. err_return_int(EINVAL, "prog_types argument");
  111. ucv_object_foreach(val, name, type) {
  112. struct bpf_program *prog;
  113. if (ucv_type(type) != UC_INTEGER)
  114. err_return_int(EINVAL, "program %s type", name);
  115. prog = bpf_object__find_program_by_name(obj, name);
  116. if (!prog)
  117. err_return_int(-1, "program %s not found", name);
  118. bpf_program__set_type(prog, ucv_int64_get(type));
  119. }
  120. }
  121. return 0;
  122. }
  123. static uc_value_t *
  124. uc_bpf_open_module(uc_vm_t *vm, size_t nargs)
  125. {
  126. DECLARE_LIBBPF_OPTS(bpf_object_open_opts, bpf_opts);
  127. uc_value_t *path = uc_fn_arg(0);
  128. uc_value_t *opts = uc_fn_arg(1);
  129. struct bpf_object *obj;
  130. if (ucv_type(path) != UC_STRING)
  131. err_return(EINVAL, "module path");
  132. init_env();
  133. obj = bpf_object__open_file(ucv_string_get(path), &bpf_opts);
  134. if (libbpf_get_error(obj))
  135. err_return(errno, NULL);
  136. if (uc_bpf_module_set_opts(obj, opts)) {
  137. bpf_object__close(obj);
  138. return NULL;
  139. }
  140. if (bpf_object__load(obj)) {
  141. bpf_object__close(obj);
  142. err_return(errno, NULL);
  143. }
  144. return uc_resource_new(module_type, obj);
  145. }
  146. static uc_value_t *
  147. uc_bpf_map_create(int fd, unsigned int key_size, unsigned int val_size, bool close)
  148. {
  149. struct uc_bpf_map *uc_map;
  150. uc_map = xalloc(sizeof(*uc_map));
  151. uc_map->fd.fd = fd;
  152. uc_map->key_size = key_size;
  153. uc_map->val_size = val_size;
  154. uc_map->fd.close = close;
  155. return uc_resource_new(map_type, uc_map);
  156. }
  157. static uc_value_t *
  158. uc_bpf_open_map(uc_vm_t *vm, size_t nargs)
  159. {
  160. struct bpf_map_info info;
  161. uc_value_t *path = uc_fn_arg(0);
  162. __u32 len = sizeof(info);
  163. int err;
  164. int fd;
  165. if (ucv_type(path) != UC_STRING)
  166. err_return(EINVAL, "module path");
  167. fd = bpf_obj_get(ucv_string_get(path));
  168. if (fd < 0)
  169. err_return(errno, NULL);
  170. err = bpf_obj_get_info_by_fd(fd, &info, &len);
  171. if (err) {
  172. close(fd);
  173. err_return(errno, NULL);
  174. }
  175. return uc_bpf_map_create(fd, info.key_size, info.value_size, true);
  176. }
  177. static uc_value_t *
  178. uc_bpf_open_program(uc_vm_t *vm, size_t nargs)
  179. {
  180. uc_value_t *path = uc_fn_arg(0);
  181. struct uc_bpf_fd *f;
  182. int fd;
  183. if (ucv_type(path) != UC_STRING)
  184. err_return(EINVAL, "module path");
  185. fd = bpf_obj_get(ucv_string_get(path));
  186. if (fd < 0)
  187. err_return(errno, NULL);
  188. f = xalloc(sizeof(*f));
  189. f->fd = fd;
  190. f->close = true;
  191. return uc_resource_new(program_type, f);
  192. }
  193. static uc_value_t *
  194. uc_bpf_module_get_maps(uc_vm_t *vm, size_t nargs)
  195. {
  196. struct bpf_object *obj = uc_fn_thisval("bpf.module");
  197. struct bpf_map *map = NULL;
  198. uc_value_t *rv;
  199. int i = 0;
  200. if (!obj)
  201. err_return(EINVAL, NULL);
  202. rv = ucv_array_new(vm);
  203. bpf_object__for_each_map(map, obj)
  204. ucv_array_set(rv, i++, ucv_string_new(bpf_map__name(map)));
  205. return rv;
  206. }
  207. static uc_value_t *
  208. uc_bpf_module_get_map(uc_vm_t *vm, size_t nargs)
  209. {
  210. struct bpf_object *obj = uc_fn_thisval("bpf.module");
  211. struct bpf_map *map;
  212. uc_value_t *name = uc_fn_arg(0);
  213. int fd;
  214. if (!obj || ucv_type(name) != UC_STRING)
  215. err_return(EINVAL, NULL);
  216. map = bpf_object__find_map_by_name(obj, ucv_string_get(name));
  217. if (!map)
  218. err_return(errno, NULL);
  219. fd = bpf_map__fd(map);
  220. if (fd < 0)
  221. err_return(EINVAL, NULL);
  222. return uc_bpf_map_create(fd, bpf_map__key_size(map), bpf_map__value_size(map), false);
  223. }
  224. static uc_value_t *
  225. uc_bpf_module_get_programs(uc_vm_t *vm, size_t nargs)
  226. {
  227. struct bpf_object *obj = uc_fn_thisval("bpf.module");
  228. struct bpf_program *prog = NULL;
  229. uc_value_t *rv;
  230. int i = 0;
  231. if (!obj)
  232. err_return(EINVAL, NULL);
  233. rv = ucv_array_new(vm);
  234. bpf_object__for_each_program(prog, obj)
  235. ucv_array_set(rv, i++, ucv_string_new(bpf_program__name(prog)));
  236. return rv;
  237. }
  238. static uc_value_t *
  239. uc_bpf_module_get_program(uc_vm_t *vm, size_t nargs)
  240. {
  241. struct bpf_object *obj = uc_fn_thisval("bpf.module");
  242. struct bpf_program *prog;
  243. uc_value_t *name = uc_fn_arg(0);
  244. struct uc_bpf_fd *f;
  245. int fd;
  246. if (!obj || !name || ucv_type(name) != UC_STRING)
  247. err_return(EINVAL, NULL);
  248. prog = bpf_object__find_program_by_name(obj, ucv_string_get(name));
  249. if (!prog)
  250. err_return(errno, NULL);
  251. fd = bpf_program__fd(prog);
  252. if (fd < 0)
  253. err_return(EINVAL, NULL);
  254. f = xalloc(sizeof(*f));
  255. f->fd = fd;
  256. return uc_resource_new(program_type, f);
  257. }
  258. static void *
  259. uc_bpf_map_arg(uc_value_t *val, const char *kind, unsigned int size)
  260. {
  261. static union {
  262. uint32_t u32;
  263. uint64_t u64;
  264. } val_int;
  265. switch (ucv_type(val)) {
  266. case UC_INTEGER:
  267. if (size == 4)
  268. val_int.u32 = ucv_int64_get(val);
  269. else if (size == 8)
  270. val_int.u64 = ucv_int64_get(val);
  271. else
  272. break;
  273. return &val_int;
  274. case UC_STRING:
  275. if (size != ucv_string_length(val))
  276. break;
  277. return ucv_string_get(val);
  278. default:
  279. err_return(EINVAL, "%s type", kind);
  280. }
  281. err_return(EINVAL, "%s size mismatch (expected: %d)", kind, size);
  282. }
  283. static uc_value_t *
  284. uc_bpf_map_get(uc_vm_t *vm, size_t nargs)
  285. {
  286. struct uc_bpf_map *map = uc_fn_thisval("bpf.map");
  287. uc_value_t *a_key = uc_fn_arg(0);
  288. void *key, *val;
  289. if (!map)
  290. err_return(EINVAL, NULL);
  291. key = uc_bpf_map_arg(a_key, "key", map->key_size);
  292. if (!key)
  293. return NULL;
  294. val = alloca(map->val_size);
  295. if (bpf_map_lookup_elem(map->fd.fd, key, val))
  296. return NULL;
  297. return ucv_string_new_length(val, map->val_size);
  298. }
  299. static uc_value_t *
  300. uc_bpf_map_set(uc_vm_t *vm, size_t nargs)
  301. {
  302. struct uc_bpf_map *map = uc_fn_thisval("bpf.map");
  303. uc_value_t *a_key = uc_fn_arg(0);
  304. uc_value_t *a_val = uc_fn_arg(1);
  305. uc_value_t *a_flags = uc_fn_arg(2);
  306. uint64_t flags;
  307. void *key, *val;
  308. if (!map)
  309. err_return(EINVAL, NULL);
  310. key = uc_bpf_map_arg(a_key, "key", map->key_size);
  311. if (!key)
  312. return NULL;
  313. val = uc_bpf_map_arg(a_val, "value", map->val_size);
  314. if (!val)
  315. return NULL;
  316. if (!a_flags)
  317. flags = BPF_ANY;
  318. else if (ucv_type(a_flags) != UC_INTEGER)
  319. err_return(EINVAL, "flags");
  320. else
  321. flags = ucv_int64_get(a_flags);
  322. if (bpf_map_update_elem(map->fd.fd, key, val, flags))
  323. return NULL;
  324. return ucv_string_new_length(val, map->val_size);
  325. }
  326. static uc_value_t *
  327. uc_bpf_map_delete(uc_vm_t *vm, size_t nargs)
  328. {
  329. struct uc_bpf_map *map = uc_fn_thisval("bpf.map");
  330. uc_value_t *a_key = uc_fn_arg(0);
  331. uc_value_t *a_return = uc_fn_arg(1);
  332. void *key, *val = NULL;
  333. int ret;
  334. if (!map)
  335. err_return(EINVAL, NULL);
  336. key = uc_bpf_map_arg(a_key, "key", map->key_size);
  337. if (!key)
  338. return NULL;
  339. if (!ucv_is_truish(a_return)) {
  340. ret = bpf_map_delete_elem(map->fd.fd, key);
  341. return ucv_boolean_new(ret == 0);
  342. }
  343. val = alloca(map->val_size);
  344. if (bpf_map_lookup_and_delete_elem(map->fd.fd, key, val))
  345. return NULL;
  346. return ucv_string_new_length(val, map->val_size);
  347. }
  348. static uc_value_t *
  349. uc_bpf_map_delete_all(uc_vm_t *vm, size_t nargs)
  350. {
  351. struct uc_bpf_map *map = uc_fn_thisval("bpf.map");
  352. uc_value_t *filter = uc_fn_arg(0);
  353. bool has_next;
  354. void *key, *next;
  355. if (!map)
  356. err_return(EINVAL, NULL);
  357. key = alloca(map->key_size);
  358. next = alloca(map->key_size);
  359. has_next = !bpf_map_get_next_key(map->fd.fd, NULL, next);
  360. while (has_next) {
  361. bool skip = false;
  362. memcpy(key, next, map->key_size);
  363. has_next = !bpf_map_get_next_key(map->fd.fd, next, next);
  364. if (ucv_is_callable(filter)) {
  365. uc_value_t *rv;
  366. uc_value_push(ucv_get(filter));
  367. uc_value_push(ucv_string_new_length((const char *)key, map->key_size));
  368. if (uc_call(1) != EXCEPTION_NONE)
  369. break;
  370. rv = uc_vm_stack_pop(vm);
  371. if (!rv)
  372. break;
  373. skip = !ucv_is_truish(rv);
  374. ucv_put(rv);
  375. }
  376. if (!skip)
  377. bpf_map_delete_elem(map->fd.fd, key);
  378. }
  379. return TRUE;
  380. }
  381. static uc_value_t *
  382. uc_bpf_map_iterator(uc_vm_t *vm, size_t nargs)
  383. {
  384. struct uc_bpf_map *map = uc_fn_thisval("bpf.map");
  385. struct uc_bpf_map_iter *iter;
  386. if (!map)
  387. err_return(EINVAL, NULL);
  388. iter = xalloc(sizeof(*iter) + map->key_size);
  389. iter->fd = map->fd.fd;
  390. iter->key_size = map->key_size;
  391. iter->has_next = !bpf_map_get_next_key(iter->fd, NULL, &iter->key);
  392. return uc_resource_new(map_iter_type, iter);
  393. }
  394. static uc_value_t *
  395. uc_bpf_map_iter_next(uc_vm_t *vm, size_t nargs)
  396. {
  397. struct uc_bpf_map_iter *iter = uc_fn_thisval("bpf.map_iter");
  398. uc_value_t *rv;
  399. if (!iter->has_next)
  400. return NULL;
  401. rv = ucv_string_new_length((const char *)iter->key, iter->key_size);
  402. iter->has_next = !bpf_map_get_next_key(iter->fd, &iter->key, &iter->key);
  403. return rv;
  404. }
  405. static uc_value_t *
  406. uc_bpf_map_iter_next_int(uc_vm_t *vm, size_t nargs)
  407. {
  408. struct uc_bpf_map_iter *iter = uc_fn_thisval("bpf.map_iter");
  409. uint64_t intval;
  410. uc_value_t *rv;
  411. if (!iter->has_next)
  412. return NULL;
  413. if (iter->key_size == 4)
  414. intval = *(uint32_t *)iter->key;
  415. else if (iter->key_size == 8)
  416. intval = *(uint64_t *)iter->key;
  417. else
  418. return NULL;
  419. rv = ucv_int64_new(intval);
  420. iter->has_next = !bpf_map_get_next_key(iter->fd, &iter->key, &iter->key);
  421. return rv;
  422. }
  423. static uc_value_t *
  424. uc_bpf_map_foreach(uc_vm_t *vm, size_t nargs)
  425. {
  426. struct uc_bpf_map *map = uc_fn_thisval("bpf.map");
  427. uc_value_t *func = uc_fn_arg(0);
  428. bool has_next;
  429. void *key, *next;
  430. bool ret = false;
  431. key = alloca(map->key_size);
  432. next = alloca(map->key_size);
  433. has_next = !bpf_map_get_next_key(map->fd.fd, NULL, next);
  434. while (has_next) {
  435. uc_value_t *rv;
  436. bool stop;
  437. memcpy(key, next, map->key_size);
  438. has_next = !bpf_map_get_next_key(map->fd.fd, next, next);
  439. uc_value_push(ucv_get(func));
  440. uc_value_push(ucv_string_new_length((const char *)key, map->key_size));
  441. if (uc_call(1) != EXCEPTION_NONE)
  442. break;
  443. rv = uc_vm_stack_pop(vm);
  444. stop = (ucv_type(rv) == UC_BOOLEAN && !ucv_boolean_get(rv));
  445. ucv_put(rv);
  446. if (stop)
  447. break;
  448. ret = true;
  449. }
  450. return ucv_boolean_new(ret);
  451. }
  452. static uc_value_t *
  453. uc_bpf_obj_pin(uc_vm_t *vm, size_t nargs, const char *type)
  454. {
  455. struct uc_bpf_fd *f = uc_fn_thisval(type);
  456. uc_value_t *path = uc_fn_arg(0);
  457. if (ucv_type(path) != UC_STRING)
  458. err_return(EINVAL, NULL);
  459. if (bpf_obj_pin(f->fd, ucv_string_get(path)))
  460. err_return(errno, NULL);
  461. return TRUE;
  462. }
  463. static uc_value_t *
  464. uc_bpf_program_pin(uc_vm_t *vm, size_t nargs)
  465. {
  466. return uc_bpf_obj_pin(vm, nargs, "bpf.program");
  467. }
  468. static uc_value_t *
  469. uc_bpf_map_pin(uc_vm_t *vm, size_t nargs)
  470. {
  471. return uc_bpf_obj_pin(vm, nargs, "bpf.map");
  472. }
  473. static uc_value_t *
  474. uc_bpf_set_tc_hook(uc_value_t *ifname, uc_value_t *type, uc_value_t *prio,
  475. int fd)
  476. {
  477. DECLARE_LIBBPF_OPTS(bpf_tc_hook, hook);
  478. DECLARE_LIBBPF_OPTS(bpf_tc_opts, attach_tc,
  479. .handle = 1);
  480. const char *type_str;
  481. uint64_t prio_val;
  482. if (ucv_type(ifname) != UC_STRING || ucv_type(type) != UC_STRING ||
  483. ucv_type(prio) != UC_INTEGER)
  484. err_return(EINVAL, NULL);
  485. prio_val = ucv_int64_get(prio);
  486. if (prio_val > 0xffff)
  487. err_return(EINVAL, NULL);
  488. type_str = ucv_string_get(type);
  489. if (!strcmp(type_str, "ingress"))
  490. hook.attach_point = BPF_TC_INGRESS;
  491. else if (!strcmp(type_str, "egress"))
  492. hook.attach_point = BPF_TC_EGRESS;
  493. else
  494. err_return(EINVAL, NULL);
  495. hook.ifindex = if_nametoindex(ucv_string_get(ifname));
  496. if (!hook.ifindex)
  497. goto error;
  498. bpf_tc_hook_create(&hook);
  499. attach_tc.priority = prio_val;
  500. if (bpf_tc_detach(&hook, &attach_tc) < 0 && fd < 0)
  501. goto error;
  502. if (fd < 0)
  503. goto out;
  504. attach_tc.prog_fd = fd;
  505. if (bpf_tc_attach(&hook, &attach_tc) < 0)
  506. goto error;
  507. out:
  508. return TRUE;
  509. error:
  510. if (fd >= 0)
  511. err_return(ENOENT, NULL);
  512. return NULL;
  513. }
  514. static uc_value_t *
  515. uc_bpf_program_tc_attach(uc_vm_t *vm, size_t nargs)
  516. {
  517. struct uc_bpf_fd *f = uc_fn_thisval("bpf.program");
  518. uc_value_t *ifname = uc_fn_arg(0);
  519. uc_value_t *type = uc_fn_arg(1);
  520. uc_value_t *prio = uc_fn_arg(2);
  521. if (!f)
  522. err_return(EINVAL, NULL);
  523. return uc_bpf_set_tc_hook(ifname, type, prio, f->fd);
  524. }
  525. static uc_value_t *
  526. uc_bpf_tc_detach(uc_vm_t *vm, size_t nargs)
  527. {
  528. uc_value_t *ifname = uc_fn_arg(0);
  529. uc_value_t *type = uc_fn_arg(1);
  530. uc_value_t *prio = uc_fn_arg(2);
  531. return uc_bpf_set_tc_hook(ifname, type, prio, -1);
  532. }
  533. static int
  534. uc_bpf_debug_print(enum libbpf_print_level level, const char *format,
  535. va_list args)
  536. {
  537. char buf[256], *str = NULL;
  538. uc_value_t *val;
  539. va_list ap;
  540. int size;
  541. va_copy(ap, args);
  542. size = vsnprintf(buf, sizeof(buf), format, ap);
  543. va_end(ap);
  544. if (size > 0 && (unsigned long)size < ARRAY_SIZE(buf) - 1) {
  545. val = ucv_string_new(buf);
  546. goto out;
  547. }
  548. if (vasprintf(&str, format, args) < 0)
  549. return 0;
  550. val = ucv_string_new(str);
  551. free(str);
  552. out:
  553. uc_vm_stack_push(debug_vm, ucv_get(ucv_array_get(registry, 0)));
  554. uc_vm_stack_push(debug_vm, ucv_int64_new(level));
  555. uc_vm_stack_push(debug_vm, val);
  556. if (uc_vm_call(debug_vm, false, 2) == EXCEPTION_NONE)
  557. ucv_put(uc_vm_stack_pop(debug_vm));
  558. return 0;
  559. }
  560. static uc_value_t *
  561. uc_bpf_set_debug_handler(uc_vm_t *vm, size_t nargs)
  562. {
  563. uc_value_t *handler = uc_fn_arg(0);
  564. if (handler && !ucv_is_callable(handler))
  565. err_return(EINVAL, NULL);
  566. debug_vm = vm;
  567. libbpf_set_print(handler ? uc_bpf_debug_print : NULL);
  568. ucv_array_set(registry, 0, ucv_get(handler));
  569. return NULL;
  570. }
  571. static void
  572. register_constants(uc_vm_t *vm, uc_value_t *scope)
  573. {
  574. #define ADD_CONST(x) ucv_object_add(scope, #x, ucv_int64_new(x))
  575. ADD_CONST(BPF_PROG_TYPE_SCHED_CLS);
  576. ADD_CONST(BPF_PROG_TYPE_SCHED_ACT);
  577. ADD_CONST(BPF_ANY);
  578. ADD_CONST(BPF_NOEXIST);
  579. ADD_CONST(BPF_EXIST);
  580. ADD_CONST(BPF_F_LOCK);
  581. }
  582. static const uc_function_list_t module_fns[] = {
  583. { "get_map", uc_bpf_module_get_map },
  584. { "get_maps", uc_bpf_module_get_maps },
  585. { "get_programs", uc_bpf_module_get_programs },
  586. { "get_program", uc_bpf_module_get_program },
  587. };
  588. static void module_free(void *ptr)
  589. {
  590. struct bpf_object *obj = ptr;
  591. bpf_object__close(obj);
  592. }
  593. static const uc_function_list_t map_fns[] = {
  594. { "pin", uc_bpf_map_pin },
  595. { "get", uc_bpf_map_get },
  596. { "set", uc_bpf_map_set },
  597. { "delete", uc_bpf_map_delete },
  598. { "delete_all", uc_bpf_map_delete_all },
  599. { "foreach", uc_bpf_map_foreach },
  600. { "iterator", uc_bpf_map_iterator },
  601. };
  602. static void uc_bpf_fd_free(void *ptr)
  603. {
  604. struct uc_bpf_fd *f = ptr;
  605. if (f->close)
  606. close(f->fd);
  607. free(f);
  608. }
  609. static const uc_function_list_t map_iter_fns[] = {
  610. { "next", uc_bpf_map_iter_next },
  611. { "next_int", uc_bpf_map_iter_next_int },
  612. };
  613. static const uc_function_list_t prog_fns[] = {
  614. { "pin", uc_bpf_program_pin },
  615. { "tc_attach", uc_bpf_program_tc_attach },
  616. };
  617. static const uc_function_list_t global_fns[] = {
  618. { "error", uc_bpf_error },
  619. { "set_debug_handler", uc_bpf_set_debug_handler },
  620. { "open_module", uc_bpf_open_module },
  621. { "open_map", uc_bpf_open_map },
  622. { "open_program", uc_bpf_open_program },
  623. { "tc_detach", uc_bpf_tc_detach },
  624. };
  625. void uc_module_init(uc_vm_t *vm, uc_value_t *scope)
  626. {
  627. uc_function_list_register(scope, global_fns);
  628. register_constants(vm, scope);
  629. registry = ucv_array_new(vm);
  630. uc_vm_registry_set(vm, "bpf.registry", registry);
  631. module_type = uc_type_declare(vm, "bpf.module", module_fns, module_free);
  632. map_type = uc_type_declare(vm, "bpf.map", map_fns, uc_bpf_fd_free);
  633. map_iter_type = uc_type_declare(vm, "bpf.map_iter", map_iter_fns, free);
  634. program_type = uc_type_declare(vm, "bpf.program", prog_fns, uc_bpf_fd_free);
  635. }