common.c 27 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304
  1. // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
  2. /* Copyright (C) 2017-2018 Netronome Systems, Inc. */
  3. #ifndef _GNU_SOURCE
  4. #define _GNU_SOURCE
  5. #endif
  6. #include <assert.h>
  7. #include <ctype.h>
  8. #include <errno.h>
  9. #include <fcntl.h>
  10. #include <ftw.h>
  11. #include <libgen.h>
  12. #include <mntent.h>
  13. #include <stdbool.h>
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <unistd.h>
  18. #include <net/if.h>
  19. #include <sys/mount.h>
  20. #include <sys/resource.h>
  21. #include <sys/stat.h>
  22. #include <sys/vfs.h>
  23. #include <sys/utsname.h>
  24. #include <linux/filter.h>
  25. #include <linux/limits.h>
  26. #include <linux/magic.h>
  27. #include <linux/unistd.h>
  28. #include <bpf/bpf.h>
  29. #include <bpf/hashmap.h>
  30. #include <bpf/libbpf.h> /* libbpf_num_possible_cpus */
  31. #include <bpf/btf.h>
  32. #include <zlib.h>
  33. #include "main.h"
  34. #ifndef BPF_FS_MAGIC
  35. #define BPF_FS_MAGIC 0xcafe4a11
  36. #endif
  37. void p_err(const char *fmt, ...)
  38. {
  39. va_list ap;
  40. va_start(ap, fmt);
  41. if (json_output) {
  42. jsonw_start_object(json_wtr);
  43. jsonw_name(json_wtr, "error");
  44. jsonw_vprintf_enquote(json_wtr, fmt, ap);
  45. jsonw_end_object(json_wtr);
  46. } else {
  47. fprintf(stderr, "Error: ");
  48. vfprintf(stderr, fmt, ap);
  49. fprintf(stderr, "\n");
  50. }
  51. va_end(ap);
  52. }
  53. void p_info(const char *fmt, ...)
  54. {
  55. va_list ap;
  56. if (json_output)
  57. return;
  58. va_start(ap, fmt);
  59. vfprintf(stderr, fmt, ap);
  60. fprintf(stderr, "\n");
  61. va_end(ap);
  62. }
  63. static bool is_bpffs(const char *path)
  64. {
  65. struct statfs st_fs;
  66. if (statfs(path, &st_fs) < 0)
  67. return false;
  68. return (unsigned long)st_fs.f_type == BPF_FS_MAGIC;
  69. }
  70. /* Probe whether kernel switched from memlock-based (RLIMIT_MEMLOCK) to
  71. * memcg-based memory accounting for BPF maps and programs. This was done in
  72. * commit 97306be45fbe ("Merge branch 'switch to memcg-based memory
  73. * accounting'"), in Linux 5.11.
  74. *
  75. * Libbpf also offers to probe for memcg-based accounting vs rlimit, but does
  76. * so by checking for the availability of a given BPF helper and this has
  77. * failed on some kernels with backports in the past, see commit 6b4384ff1088
  78. * ("Revert "bpftool: Use libbpf 1.0 API mode instead of RLIMIT_MEMLOCK"").
  79. * Instead, we can probe by lowering the process-based rlimit to 0, trying to
  80. * load a BPF object, and resetting the rlimit. If the load succeeds then
  81. * memcg-based accounting is supported.
  82. *
  83. * This would be too dangerous to do in the library, because multithreaded
  84. * applications might attempt to load items while the rlimit is at 0. Given
  85. * that bpftool is single-threaded, this is fine to do here.
  86. */
  87. static bool known_to_need_rlimit(void)
  88. {
  89. struct rlimit rlim_init, rlim_cur_zero = {};
  90. struct bpf_insn insns[] = {
  91. BPF_MOV64_IMM(BPF_REG_0, 0),
  92. BPF_EXIT_INSN(),
  93. };
  94. size_t insn_cnt = ARRAY_SIZE(insns);
  95. union bpf_attr attr;
  96. int prog_fd, err;
  97. memset(&attr, 0, sizeof(attr));
  98. attr.prog_type = BPF_PROG_TYPE_SOCKET_FILTER;
  99. attr.insns = ptr_to_u64(insns);
  100. attr.insn_cnt = insn_cnt;
  101. attr.license = ptr_to_u64("GPL");
  102. if (getrlimit(RLIMIT_MEMLOCK, &rlim_init))
  103. return false;
  104. /* Drop the soft limit to zero. We maintain the hard limit to its
  105. * current value, because lowering it would be a permanent operation
  106. * for unprivileged users.
  107. */
  108. rlim_cur_zero.rlim_max = rlim_init.rlim_max;
  109. if (setrlimit(RLIMIT_MEMLOCK, &rlim_cur_zero))
  110. return false;
  111. /* Do not use bpf_prog_load() from libbpf here, because it calls
  112. * bump_rlimit_memlock(), interfering with the current probe.
  113. */
  114. prog_fd = syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr));
  115. err = errno;
  116. /* reset soft rlimit to its initial value */
  117. setrlimit(RLIMIT_MEMLOCK, &rlim_init);
  118. if (prog_fd < 0)
  119. return err == EPERM;
  120. close(prog_fd);
  121. return false;
  122. }
  123. void set_max_rlimit(void)
  124. {
  125. struct rlimit rinf = { RLIM_INFINITY, RLIM_INFINITY };
  126. if (known_to_need_rlimit())
  127. setrlimit(RLIMIT_MEMLOCK, &rinf);
  128. }
  129. static int
  130. mnt_fs(const char *target, const char *type, char *buff, size_t bufflen)
  131. {
  132. bool bind_done = false;
  133. while (mount("", target, "none", MS_PRIVATE | MS_REC, NULL)) {
  134. if (errno != EINVAL || bind_done) {
  135. snprintf(buff, bufflen,
  136. "mount --make-private %s failed: %s",
  137. target, strerror(errno));
  138. return -1;
  139. }
  140. if (mount(target, target, "none", MS_BIND, NULL)) {
  141. snprintf(buff, bufflen,
  142. "mount --bind %s %s failed: %s",
  143. target, target, strerror(errno));
  144. return -1;
  145. }
  146. bind_done = true;
  147. }
  148. if (mount(type, target, type, 0, "mode=0700")) {
  149. snprintf(buff, bufflen, "mount -t %s %s %s failed: %s",
  150. type, type, target, strerror(errno));
  151. return -1;
  152. }
  153. return 0;
  154. }
  155. int mount_tracefs(const char *target)
  156. {
  157. char err_str[ERR_MAX_LEN];
  158. int err;
  159. err = mnt_fs(target, "tracefs", err_str, ERR_MAX_LEN);
  160. if (err) {
  161. err_str[ERR_MAX_LEN - 1] = '\0';
  162. p_err("can't mount tracefs: %s", err_str);
  163. }
  164. return err;
  165. }
  166. int open_obj_pinned(const char *path, bool quiet,
  167. const struct bpf_obj_get_opts *opts)
  168. {
  169. char *pname;
  170. int fd = -1;
  171. pname = strdup(path);
  172. if (!pname) {
  173. if (!quiet)
  174. p_err("mem alloc failed");
  175. goto out_ret;
  176. }
  177. fd = bpf_obj_get_opts(pname, opts);
  178. if (fd < 0) {
  179. if (!quiet)
  180. p_err("bpf obj get (%s): %s", pname,
  181. errno == EACCES && !is_bpffs(dirname(pname)) ?
  182. "directory not in bpf file system (bpffs)" :
  183. strerror(errno));
  184. goto out_free;
  185. }
  186. out_free:
  187. free(pname);
  188. out_ret:
  189. return fd;
  190. }
  191. int open_obj_pinned_any(const char *path, enum bpf_obj_type exp_type,
  192. const struct bpf_obj_get_opts *opts)
  193. {
  194. enum bpf_obj_type type;
  195. int fd;
  196. fd = open_obj_pinned(path, false, opts);
  197. if (fd < 0)
  198. return -1;
  199. type = get_fd_type(fd);
  200. if (type < 0) {
  201. close(fd);
  202. return type;
  203. }
  204. if (type != exp_type) {
  205. p_err("incorrect object type: %s", get_fd_type_name(type));
  206. close(fd);
  207. return -1;
  208. }
  209. return fd;
  210. }
  211. int create_and_mount_bpffs_dir(const char *dir_name)
  212. {
  213. char err_str[ERR_MAX_LEN];
  214. bool dir_exists;
  215. int err = 0;
  216. if (is_bpffs(dir_name))
  217. return err;
  218. dir_exists = access(dir_name, F_OK) == 0;
  219. if (!dir_exists) {
  220. char *temp_name;
  221. char *parent_name;
  222. temp_name = strdup(dir_name);
  223. if (!temp_name) {
  224. p_err("mem alloc failed");
  225. return -1;
  226. }
  227. parent_name = dirname(temp_name);
  228. if (is_bpffs(parent_name)) {
  229. /* nothing to do if already mounted */
  230. free(temp_name);
  231. return err;
  232. }
  233. if (access(parent_name, F_OK) == -1) {
  234. p_err("can't create dir '%s' to pin BPF object: parent dir '%s' doesn't exist",
  235. dir_name, parent_name);
  236. free(temp_name);
  237. return -1;
  238. }
  239. free(temp_name);
  240. }
  241. if (block_mount) {
  242. p_err("no BPF file system found, not mounting it due to --nomount option");
  243. return -1;
  244. }
  245. if (!dir_exists) {
  246. err = mkdir(dir_name, S_IRWXU);
  247. if (err) {
  248. p_err("failed to create dir '%s': %s", dir_name, strerror(errno));
  249. return err;
  250. }
  251. }
  252. err = mnt_fs(dir_name, "bpf", err_str, ERR_MAX_LEN);
  253. if (err) {
  254. err_str[ERR_MAX_LEN - 1] = '\0';
  255. p_err("can't mount BPF file system on given dir '%s': %s",
  256. dir_name, err_str);
  257. if (!dir_exists)
  258. rmdir(dir_name);
  259. }
  260. return err;
  261. }
  262. int mount_bpffs_for_file(const char *file_name)
  263. {
  264. char err_str[ERR_MAX_LEN];
  265. char *temp_name;
  266. char *dir;
  267. int err = 0;
  268. if (access(file_name, F_OK) != -1) {
  269. p_err("can't pin BPF object: path '%s' already exists", file_name);
  270. return -1;
  271. }
  272. temp_name = strdup(file_name);
  273. if (!temp_name) {
  274. p_err("mem alloc failed");
  275. return -1;
  276. }
  277. dir = dirname(temp_name);
  278. if (is_bpffs(dir))
  279. /* nothing to do if already mounted */
  280. goto out_free;
  281. if (access(dir, F_OK) == -1) {
  282. p_err("can't pin BPF object: dir '%s' doesn't exist", dir);
  283. err = -1;
  284. goto out_free;
  285. }
  286. if (block_mount) {
  287. p_err("no BPF file system found, not mounting it due to --nomount option");
  288. err = -1;
  289. goto out_free;
  290. }
  291. err = mnt_fs(dir, "bpf", err_str, ERR_MAX_LEN);
  292. if (err) {
  293. err_str[ERR_MAX_LEN - 1] = '\0';
  294. p_err("can't mount BPF file system to pin the object '%s': %s",
  295. file_name, err_str);
  296. }
  297. out_free:
  298. free(temp_name);
  299. return err;
  300. }
  301. int do_pin_fd(int fd, const char *name)
  302. {
  303. int err;
  304. err = mount_bpffs_for_file(name);
  305. if (err)
  306. return err;
  307. err = bpf_obj_pin(fd, name);
  308. if (err)
  309. p_err("can't pin the object (%s): %s", name, strerror(errno));
  310. return err;
  311. }
  312. int do_pin_any(int argc, char **argv, int (*get_fd)(int *, char ***))
  313. {
  314. int err;
  315. int fd;
  316. if (!REQ_ARGS(3))
  317. return -EINVAL;
  318. fd = get_fd(&argc, &argv);
  319. if (fd < 0)
  320. return fd;
  321. err = do_pin_fd(fd, *argv);
  322. close(fd);
  323. return err;
  324. }
  325. const char *get_fd_type_name(enum bpf_obj_type type)
  326. {
  327. static const char * const names[] = {
  328. [BPF_OBJ_UNKNOWN] = "unknown",
  329. [BPF_OBJ_PROG] = "prog",
  330. [BPF_OBJ_MAP] = "map",
  331. [BPF_OBJ_LINK] = "link",
  332. };
  333. if (type < 0 || type >= ARRAY_SIZE(names) || !names[type])
  334. return names[BPF_OBJ_UNKNOWN];
  335. return names[type];
  336. }
  337. void get_prog_full_name(const struct bpf_prog_info *prog_info, int prog_fd,
  338. char *name_buff, size_t buff_len)
  339. {
  340. const char *prog_name = prog_info->name;
  341. const struct btf_type *func_type;
  342. struct bpf_func_info finfo = {};
  343. struct bpf_prog_info info = {};
  344. __u32 info_len = sizeof(info);
  345. struct btf *prog_btf = NULL;
  346. if (buff_len <= BPF_OBJ_NAME_LEN ||
  347. strlen(prog_info->name) < BPF_OBJ_NAME_LEN - 1)
  348. goto copy_name;
  349. if (!prog_info->btf_id || prog_info->nr_func_info == 0)
  350. goto copy_name;
  351. info.nr_func_info = 1;
  352. info.func_info_rec_size = prog_info->func_info_rec_size;
  353. if (info.func_info_rec_size > sizeof(finfo))
  354. info.func_info_rec_size = sizeof(finfo);
  355. info.func_info = ptr_to_u64(&finfo);
  356. if (bpf_prog_get_info_by_fd(prog_fd, &info, &info_len))
  357. goto copy_name;
  358. prog_btf = btf__load_from_kernel_by_id(info.btf_id);
  359. if (!prog_btf)
  360. goto copy_name;
  361. func_type = btf__type_by_id(prog_btf, finfo.type_id);
  362. if (!func_type || !btf_is_func(func_type))
  363. goto copy_name;
  364. prog_name = btf__name_by_offset(prog_btf, func_type->name_off);
  365. copy_name:
  366. snprintf(name_buff, buff_len, "%s", prog_name);
  367. if (prog_btf)
  368. btf__free(prog_btf);
  369. }
  370. int get_fd_type(int fd)
  371. {
  372. char path[PATH_MAX];
  373. char buf[512];
  374. ssize_t n;
  375. snprintf(path, sizeof(path), "/proc/self/fd/%d", fd);
  376. n = readlink(path, buf, sizeof(buf));
  377. if (n < 0) {
  378. p_err("can't read link type: %s", strerror(errno));
  379. return -1;
  380. }
  381. if (n == sizeof(buf)) {
  382. p_err("can't read link type: path too long!");
  383. return -1;
  384. }
  385. buf[n] = '\0';
  386. if (strstr(buf, "bpf-map"))
  387. return BPF_OBJ_MAP;
  388. else if (strstr(buf, "bpf-prog"))
  389. return BPF_OBJ_PROG;
  390. else if (strstr(buf, "bpf-link"))
  391. return BPF_OBJ_LINK;
  392. return BPF_OBJ_UNKNOWN;
  393. }
  394. char *get_fdinfo(int fd, const char *key)
  395. {
  396. char path[PATH_MAX];
  397. char *line = NULL;
  398. size_t line_n = 0;
  399. ssize_t n;
  400. FILE *fdi;
  401. snprintf(path, sizeof(path), "/proc/self/fdinfo/%d", fd);
  402. fdi = fopen(path, "r");
  403. if (!fdi)
  404. return NULL;
  405. while ((n = getline(&line, &line_n, fdi)) > 0) {
  406. char *value;
  407. int len;
  408. if (!strstr(line, key))
  409. continue;
  410. fclose(fdi);
  411. value = strchr(line, '\t');
  412. if (!value || !value[1]) {
  413. free(line);
  414. return NULL;
  415. }
  416. value++;
  417. len = strlen(value);
  418. memmove(line, value, len);
  419. line[len - 1] = '\0';
  420. return line;
  421. }
  422. free(line);
  423. fclose(fdi);
  424. return NULL;
  425. }
  426. void print_data_json(uint8_t *data, size_t len)
  427. {
  428. unsigned int i;
  429. jsonw_start_array(json_wtr);
  430. for (i = 0; i < len; i++)
  431. jsonw_printf(json_wtr, "%d", data[i]);
  432. jsonw_end_array(json_wtr);
  433. }
  434. void print_hex_data_json(uint8_t *data, size_t len)
  435. {
  436. unsigned int i;
  437. jsonw_start_array(json_wtr);
  438. for (i = 0; i < len; i++)
  439. jsonw_printf(json_wtr, "\"0x%02hhx\"", data[i]);
  440. jsonw_end_array(json_wtr);
  441. }
  442. /* extra params for nftw cb */
  443. static struct hashmap *build_fn_table;
  444. static enum bpf_obj_type build_fn_type;
  445. static int do_build_table_cb(const char *fpath, const struct stat *sb,
  446. int typeflag, struct FTW *ftwbuf)
  447. {
  448. struct bpf_prog_info pinned_info;
  449. __u32 len = sizeof(pinned_info);
  450. enum bpf_obj_type objtype;
  451. int fd, err = 0;
  452. char *path;
  453. if (typeflag != FTW_F)
  454. goto out_ret;
  455. fd = open_obj_pinned(fpath, true, NULL);
  456. if (fd < 0)
  457. goto out_ret;
  458. objtype = get_fd_type(fd);
  459. if (objtype != build_fn_type)
  460. goto out_close;
  461. memset(&pinned_info, 0, sizeof(pinned_info));
  462. if (bpf_prog_get_info_by_fd(fd, &pinned_info, &len))
  463. goto out_close;
  464. path = strdup(fpath);
  465. if (!path) {
  466. err = -1;
  467. goto out_close;
  468. }
  469. err = hashmap__append(build_fn_table, pinned_info.id, path);
  470. if (err) {
  471. p_err("failed to append entry to hashmap for ID %u, path '%s': %s",
  472. pinned_info.id, path, strerror(errno));
  473. free(path);
  474. goto out_close;
  475. }
  476. out_close:
  477. close(fd);
  478. out_ret:
  479. return err;
  480. }
  481. int build_pinned_obj_table(struct hashmap *tab,
  482. enum bpf_obj_type type)
  483. {
  484. struct mntent *mntent = NULL;
  485. FILE *mntfile = NULL;
  486. int flags = FTW_PHYS;
  487. int nopenfd = 16;
  488. int err = 0;
  489. mntfile = setmntent("/proc/mounts", "r");
  490. if (!mntfile)
  491. return -1;
  492. build_fn_table = tab;
  493. build_fn_type = type;
  494. while ((mntent = getmntent(mntfile))) {
  495. char *path = mntent->mnt_dir;
  496. if (strncmp(mntent->mnt_type, "bpf", 3) != 0)
  497. continue;
  498. err = nftw(path, do_build_table_cb, nopenfd, flags);
  499. if (err)
  500. break;
  501. }
  502. fclose(mntfile);
  503. return err;
  504. }
  505. void delete_pinned_obj_table(struct hashmap *map)
  506. {
  507. struct hashmap_entry *entry;
  508. size_t bkt;
  509. if (!map)
  510. return;
  511. hashmap__for_each_entry(map, entry, bkt)
  512. free(entry->pvalue);
  513. hashmap__free(map);
  514. }
  515. unsigned int get_page_size(void)
  516. {
  517. static int result;
  518. if (!result)
  519. result = getpagesize();
  520. return result;
  521. }
  522. unsigned int get_possible_cpus(void)
  523. {
  524. int cpus = libbpf_num_possible_cpus();
  525. if (cpus < 0) {
  526. p_err("Can't get # of possible cpus: %s", strerror(-cpus));
  527. exit(-1);
  528. }
  529. return cpus;
  530. }
  531. static char *
  532. ifindex_to_name_ns(__u32 ifindex, __u32 ns_dev, __u32 ns_ino, char *buf)
  533. {
  534. struct stat st;
  535. int err;
  536. err = stat("/proc/self/ns/net", &st);
  537. if (err) {
  538. p_err("Can't stat /proc/self: %s", strerror(errno));
  539. return NULL;
  540. }
  541. if (st.st_dev != ns_dev || st.st_ino != ns_ino)
  542. return NULL;
  543. return if_indextoname(ifindex, buf);
  544. }
  545. static int read_sysfs_hex_int(char *path)
  546. {
  547. char vendor_id_buf[8];
  548. int len;
  549. int fd;
  550. fd = open(path, O_RDONLY);
  551. if (fd < 0) {
  552. p_err("Can't open %s: %s", path, strerror(errno));
  553. return -1;
  554. }
  555. len = read(fd, vendor_id_buf, sizeof(vendor_id_buf));
  556. close(fd);
  557. if (len < 0) {
  558. p_err("Can't read %s: %s", path, strerror(errno));
  559. return -1;
  560. }
  561. if (len >= (int)sizeof(vendor_id_buf)) {
  562. p_err("Value in %s too long", path);
  563. return -1;
  564. }
  565. vendor_id_buf[len] = 0;
  566. return strtol(vendor_id_buf, NULL, 0);
  567. }
  568. static int read_sysfs_netdev_hex_int(char *devname, const char *entry_name)
  569. {
  570. char full_path[64];
  571. snprintf(full_path, sizeof(full_path), "/sys/class/net/%s/device/%s",
  572. devname, entry_name);
  573. return read_sysfs_hex_int(full_path);
  574. }
  575. const char *
  576. ifindex_to_arch(__u32 ifindex, __u64 ns_dev, __u64 ns_ino, const char **opt)
  577. {
  578. __maybe_unused int device_id;
  579. char devname[IF_NAMESIZE];
  580. int vendor_id;
  581. if (!ifindex_to_name_ns(ifindex, ns_dev, ns_ino, devname)) {
  582. p_err("Can't get net device name for ifindex %u: %s", ifindex,
  583. strerror(errno));
  584. return NULL;
  585. }
  586. vendor_id = read_sysfs_netdev_hex_int(devname, "vendor");
  587. if (vendor_id < 0) {
  588. p_err("Can't get device vendor id for %s", devname);
  589. return NULL;
  590. }
  591. switch (vendor_id) {
  592. #ifdef HAVE_LIBBFD_SUPPORT
  593. case 0x19ee:
  594. device_id = read_sysfs_netdev_hex_int(devname, "device");
  595. if (device_id != 0x4000 &&
  596. device_id != 0x6000 &&
  597. device_id != 0x6003)
  598. p_info("Unknown NFP device ID, assuming it is NFP-6xxx arch");
  599. *opt = "ctx4";
  600. return "NFP-6xxx";
  601. #endif /* HAVE_LIBBFD_SUPPORT */
  602. /* No NFP support in LLVM, we have no valid triple to return. */
  603. default:
  604. p_err("Can't get arch name for device vendor id 0x%04x",
  605. (unsigned int)vendor_id);
  606. return NULL;
  607. }
  608. }
  609. void print_dev_plain(__u32 ifindex, __u64 ns_dev, __u64 ns_inode)
  610. {
  611. char name[IF_NAMESIZE];
  612. if (!ifindex)
  613. return;
  614. printf(" offloaded_to ");
  615. if (ifindex_to_name_ns(ifindex, ns_dev, ns_inode, name))
  616. printf("%s", name);
  617. else
  618. printf("ifindex %u ns_dev %llu ns_ino %llu",
  619. ifindex, ns_dev, ns_inode);
  620. }
  621. void print_dev_json(__u32 ifindex, __u64 ns_dev, __u64 ns_inode)
  622. {
  623. char name[IF_NAMESIZE];
  624. if (!ifindex)
  625. return;
  626. jsonw_name(json_wtr, "dev");
  627. jsonw_start_object(json_wtr);
  628. jsonw_uint_field(json_wtr, "ifindex", ifindex);
  629. jsonw_uint_field(json_wtr, "ns_dev", ns_dev);
  630. jsonw_uint_field(json_wtr, "ns_inode", ns_inode);
  631. if (ifindex_to_name_ns(ifindex, ns_dev, ns_inode, name))
  632. jsonw_string_field(json_wtr, "ifname", name);
  633. jsonw_end_object(json_wtr);
  634. }
  635. int parse_u32_arg(int *argc, char ***argv, __u32 *val, const char *what)
  636. {
  637. char *endptr;
  638. NEXT_ARGP();
  639. if (*val) {
  640. p_err("%s already specified", what);
  641. return -1;
  642. }
  643. *val = strtoul(**argv, &endptr, 0);
  644. if (*endptr) {
  645. p_err("can't parse %s as %s", **argv, what);
  646. return -1;
  647. }
  648. NEXT_ARGP();
  649. return 0;
  650. }
  651. int __printf(2, 0)
  652. print_all_levels(__maybe_unused enum libbpf_print_level level,
  653. const char *format, va_list args)
  654. {
  655. return vfprintf(stderr, format, args);
  656. }
  657. static int prog_fd_by_nametag(void *nametag, int **fds, bool tag)
  658. {
  659. char prog_name[MAX_PROG_FULL_NAME];
  660. unsigned int id = 0;
  661. int fd, nb_fds = 0;
  662. void *tmp;
  663. int err;
  664. while (true) {
  665. struct bpf_prog_info info = {};
  666. __u32 len = sizeof(info);
  667. err = bpf_prog_get_next_id(id, &id);
  668. if (err) {
  669. if (errno != ENOENT) {
  670. p_err("%s", strerror(errno));
  671. goto err_close_fds;
  672. }
  673. return nb_fds;
  674. }
  675. fd = bpf_prog_get_fd_by_id(id);
  676. if (fd < 0) {
  677. p_err("can't get prog by id (%u): %s",
  678. id, strerror(errno));
  679. goto err_close_fds;
  680. }
  681. err = bpf_prog_get_info_by_fd(fd, &info, &len);
  682. if (err) {
  683. p_err("can't get prog info (%u): %s",
  684. id, strerror(errno));
  685. goto err_close_fd;
  686. }
  687. if (tag && memcmp(nametag, info.tag, BPF_TAG_SIZE)) {
  688. close(fd);
  689. continue;
  690. }
  691. if (!tag) {
  692. get_prog_full_name(&info, fd, prog_name,
  693. sizeof(prog_name));
  694. if (strncmp(nametag, prog_name, sizeof(prog_name))) {
  695. close(fd);
  696. continue;
  697. }
  698. }
  699. if (nb_fds > 0) {
  700. tmp = realloc(*fds, (nb_fds + 1) * sizeof(int));
  701. if (!tmp) {
  702. p_err("failed to realloc");
  703. goto err_close_fd;
  704. }
  705. *fds = tmp;
  706. }
  707. (*fds)[nb_fds++] = fd;
  708. }
  709. err_close_fd:
  710. close(fd);
  711. err_close_fds:
  712. while (--nb_fds >= 0)
  713. close((*fds)[nb_fds]);
  714. return -1;
  715. }
  716. int prog_parse_fds(int *argc, char ***argv, int **fds)
  717. {
  718. if (is_prefix(**argv, "id")) {
  719. unsigned int id;
  720. char *endptr;
  721. NEXT_ARGP();
  722. id = strtoul(**argv, &endptr, 0);
  723. if (*endptr) {
  724. p_err("can't parse %s as ID", **argv);
  725. return -1;
  726. }
  727. NEXT_ARGP();
  728. (*fds)[0] = bpf_prog_get_fd_by_id(id);
  729. if ((*fds)[0] < 0) {
  730. p_err("get by id (%u): %s", id, strerror(errno));
  731. return -1;
  732. }
  733. return 1;
  734. } else if (is_prefix(**argv, "tag")) {
  735. unsigned char tag[BPF_TAG_SIZE];
  736. NEXT_ARGP();
  737. if (sscanf(**argv, BPF_TAG_FMT, tag, tag + 1, tag + 2,
  738. tag + 3, tag + 4, tag + 5, tag + 6, tag + 7)
  739. != BPF_TAG_SIZE) {
  740. p_err("can't parse tag");
  741. return -1;
  742. }
  743. NEXT_ARGP();
  744. return prog_fd_by_nametag(tag, fds, true);
  745. } else if (is_prefix(**argv, "name")) {
  746. char *name;
  747. NEXT_ARGP();
  748. name = **argv;
  749. if (strlen(name) > MAX_PROG_FULL_NAME - 1) {
  750. p_err("can't parse name");
  751. return -1;
  752. }
  753. NEXT_ARGP();
  754. return prog_fd_by_nametag(name, fds, false);
  755. } else if (is_prefix(**argv, "pinned")) {
  756. char *path;
  757. NEXT_ARGP();
  758. path = **argv;
  759. NEXT_ARGP();
  760. (*fds)[0] = open_obj_pinned_any(path, BPF_OBJ_PROG, NULL);
  761. if ((*fds)[0] < 0)
  762. return -1;
  763. return 1;
  764. }
  765. p_err("expected 'id', 'tag', 'name' or 'pinned', got: '%s'?", **argv);
  766. return -1;
  767. }
  768. int prog_parse_fd(int *argc, char ***argv)
  769. {
  770. int *fds = NULL;
  771. int nb_fds, fd;
  772. fds = malloc(sizeof(int));
  773. if (!fds) {
  774. p_err("mem alloc failed");
  775. return -1;
  776. }
  777. nb_fds = prog_parse_fds(argc, argv, &fds);
  778. if (nb_fds != 1) {
  779. if (nb_fds > 1) {
  780. p_err("several programs match this handle");
  781. while (nb_fds--)
  782. close(fds[nb_fds]);
  783. }
  784. fd = -1;
  785. goto exit_free;
  786. }
  787. fd = fds[0];
  788. exit_free:
  789. free(fds);
  790. return fd;
  791. }
  792. static int map_fd_by_name(char *name, int **fds,
  793. const struct bpf_get_fd_by_id_opts *opts)
  794. {
  795. unsigned int id = 0;
  796. int fd, nb_fds = 0;
  797. void *tmp;
  798. int err;
  799. while (true) {
  800. LIBBPF_OPTS(bpf_get_fd_by_id_opts, opts_ro);
  801. struct bpf_map_info info = {};
  802. __u32 len = sizeof(info);
  803. err = bpf_map_get_next_id(id, &id);
  804. if (err) {
  805. if (errno != ENOENT) {
  806. p_err("%s", strerror(errno));
  807. goto err_close_fds;
  808. }
  809. return nb_fds;
  810. }
  811. /* Request a read-only fd to query the map info */
  812. opts_ro.open_flags = BPF_F_RDONLY;
  813. fd = bpf_map_get_fd_by_id_opts(id, &opts_ro);
  814. if (fd < 0) {
  815. p_err("can't get map by id (%u): %s",
  816. id, strerror(errno));
  817. goto err_close_fds;
  818. }
  819. err = bpf_map_get_info_by_fd(fd, &info, &len);
  820. if (err) {
  821. p_err("can't get map info (%u): %s",
  822. id, strerror(errno));
  823. goto err_close_fd;
  824. }
  825. if (strncmp(name, info.name, BPF_OBJ_NAME_LEN)) {
  826. close(fd);
  827. continue;
  828. }
  829. /* Get an fd with the requested options, if they differ
  830. * from the read-only options used to get the fd above.
  831. */
  832. if (memcmp(opts, &opts_ro, sizeof(opts_ro))) {
  833. close(fd);
  834. fd = bpf_map_get_fd_by_id_opts(id, opts);
  835. if (fd < 0) {
  836. p_err("can't get map by id (%u): %s", id,
  837. strerror(errno));
  838. goto err_close_fds;
  839. }
  840. }
  841. if (nb_fds > 0) {
  842. tmp = realloc(*fds, (nb_fds + 1) * sizeof(int));
  843. if (!tmp) {
  844. p_err("failed to realloc");
  845. goto err_close_fd;
  846. }
  847. *fds = tmp;
  848. }
  849. (*fds)[nb_fds++] = fd;
  850. }
  851. err_close_fd:
  852. close(fd);
  853. err_close_fds:
  854. while (--nb_fds >= 0)
  855. close((*fds)[nb_fds]);
  856. return -1;
  857. }
  858. int map_parse_fds(int *argc, char ***argv, int **fds, __u32 open_flags)
  859. {
  860. LIBBPF_OPTS(bpf_get_fd_by_id_opts, opts);
  861. assert((open_flags & ~BPF_F_RDONLY) == 0);
  862. opts.open_flags = open_flags;
  863. if (is_prefix(**argv, "id")) {
  864. unsigned int id;
  865. char *endptr;
  866. NEXT_ARGP();
  867. id = strtoul(**argv, &endptr, 0);
  868. if (*endptr) {
  869. p_err("can't parse %s as ID", **argv);
  870. return -1;
  871. }
  872. NEXT_ARGP();
  873. (*fds)[0] = bpf_map_get_fd_by_id_opts(id, &opts);
  874. if ((*fds)[0] < 0) {
  875. p_err("get map by id (%u): %s", id, strerror(errno));
  876. return -1;
  877. }
  878. return 1;
  879. } else if (is_prefix(**argv, "name")) {
  880. char *name;
  881. NEXT_ARGP();
  882. name = **argv;
  883. if (strlen(name) > BPF_OBJ_NAME_LEN - 1) {
  884. p_err("can't parse name");
  885. return -1;
  886. }
  887. NEXT_ARGP();
  888. return map_fd_by_name(name, fds, &opts);
  889. } else if (is_prefix(**argv, "pinned")) {
  890. char *path;
  891. LIBBPF_OPTS(bpf_obj_get_opts, get_opts);
  892. get_opts.file_flags = open_flags;
  893. NEXT_ARGP();
  894. path = **argv;
  895. NEXT_ARGP();
  896. (*fds)[0] = open_obj_pinned_any(path, BPF_OBJ_MAP, &get_opts);
  897. if ((*fds)[0] < 0)
  898. return -1;
  899. return 1;
  900. }
  901. p_err("expected 'id', 'name' or 'pinned', got: '%s'?", **argv);
  902. return -1;
  903. }
  904. int map_parse_fd(int *argc, char ***argv, __u32 open_flags)
  905. {
  906. int *fds = NULL;
  907. int nb_fds, fd;
  908. fds = malloc(sizeof(int));
  909. if (!fds) {
  910. p_err("mem alloc failed");
  911. return -1;
  912. }
  913. nb_fds = map_parse_fds(argc, argv, &fds, open_flags);
  914. if (nb_fds != 1) {
  915. if (nb_fds > 1) {
  916. p_err("several maps match this handle");
  917. while (nb_fds--)
  918. close(fds[nb_fds]);
  919. }
  920. fd = -1;
  921. goto exit_free;
  922. }
  923. fd = fds[0];
  924. exit_free:
  925. free(fds);
  926. return fd;
  927. }
  928. int map_parse_fd_and_info(int *argc, char ***argv, struct bpf_map_info *info,
  929. __u32 *info_len, __u32 open_flags)
  930. {
  931. int err;
  932. int fd;
  933. fd = map_parse_fd(argc, argv, open_flags);
  934. if (fd < 0)
  935. return -1;
  936. err = bpf_map_get_info_by_fd(fd, info, info_len);
  937. if (err) {
  938. p_err("can't get map info: %s", strerror(errno));
  939. close(fd);
  940. return err;
  941. }
  942. return fd;
  943. }
  944. size_t hash_fn_for_key_as_id(long key, void *ctx)
  945. {
  946. return key;
  947. }
  948. bool equal_fn_for_key_as_id(long k1, long k2, void *ctx)
  949. {
  950. return k1 == k2;
  951. }
  952. const char *bpf_attach_type_input_str(enum bpf_attach_type t)
  953. {
  954. switch (t) {
  955. case BPF_CGROUP_INET_INGRESS: return "ingress";
  956. case BPF_CGROUP_INET_EGRESS: return "egress";
  957. case BPF_CGROUP_INET_SOCK_CREATE: return "sock_create";
  958. case BPF_CGROUP_INET_SOCK_RELEASE: return "sock_release";
  959. case BPF_CGROUP_SOCK_OPS: return "sock_ops";
  960. case BPF_CGROUP_DEVICE: return "device";
  961. case BPF_CGROUP_INET4_BIND: return "bind4";
  962. case BPF_CGROUP_INET6_BIND: return "bind6";
  963. case BPF_CGROUP_INET4_CONNECT: return "connect4";
  964. case BPF_CGROUP_INET6_CONNECT: return "connect6";
  965. case BPF_CGROUP_INET4_POST_BIND: return "post_bind4";
  966. case BPF_CGROUP_INET6_POST_BIND: return "post_bind6";
  967. case BPF_CGROUP_INET4_GETPEERNAME: return "getpeername4";
  968. case BPF_CGROUP_INET6_GETPEERNAME: return "getpeername6";
  969. case BPF_CGROUP_INET4_GETSOCKNAME: return "getsockname4";
  970. case BPF_CGROUP_INET6_GETSOCKNAME: return "getsockname6";
  971. case BPF_CGROUP_UDP4_SENDMSG: return "sendmsg4";
  972. case BPF_CGROUP_UDP6_SENDMSG: return "sendmsg6";
  973. case BPF_CGROUP_SYSCTL: return "sysctl";
  974. case BPF_CGROUP_UDP4_RECVMSG: return "recvmsg4";
  975. case BPF_CGROUP_UDP6_RECVMSG: return "recvmsg6";
  976. case BPF_CGROUP_GETSOCKOPT: return "getsockopt";
  977. case BPF_CGROUP_SETSOCKOPT: return "setsockopt";
  978. case BPF_TRACE_RAW_TP: return "raw_tp";
  979. case BPF_TRACE_FENTRY: return "fentry";
  980. case BPF_TRACE_FEXIT: return "fexit";
  981. case BPF_MODIFY_RETURN: return "mod_ret";
  982. case BPF_TRACE_FSESSION: return "fsession";
  983. case BPF_SK_REUSEPORT_SELECT: return "sk_skb_reuseport_select";
  984. case BPF_SK_REUSEPORT_SELECT_OR_MIGRATE: return "sk_skb_reuseport_select_or_migrate";
  985. default: return libbpf_bpf_attach_type_str(t);
  986. }
  987. }
  988. int pathname_concat(char *buf, int buf_sz, const char *path,
  989. const char *name)
  990. {
  991. int len;
  992. len = snprintf(buf, buf_sz, "%s/%s", path, name);
  993. if (len < 0)
  994. return -EINVAL;
  995. if (len >= buf_sz)
  996. return -ENAMETOOLONG;
  997. return 0;
  998. }
  999. static bool read_next_kernel_config_option(gzFile file, char *buf, size_t n,
  1000. char **value)
  1001. {
  1002. char *sep;
  1003. while (gzgets(file, buf, n)) {
  1004. if (strncmp(buf, "CONFIG_", 7))
  1005. continue;
  1006. sep = strchr(buf, '=');
  1007. if (!sep)
  1008. continue;
  1009. /* Trim ending '\n' */
  1010. buf[strlen(buf) - 1] = '\0';
  1011. /* Split on '=' and ensure that a value is present. */
  1012. *sep = '\0';
  1013. if (!sep[1])
  1014. continue;
  1015. *value = sep + 1;
  1016. return true;
  1017. }
  1018. return false;
  1019. }
  1020. int read_kernel_config(const struct kernel_config_option *requested_options,
  1021. size_t num_options, char **out_values,
  1022. const char *define_prefix)
  1023. {
  1024. struct utsname utsn;
  1025. char path[PATH_MAX];
  1026. gzFile file = NULL;
  1027. char buf[4096];
  1028. char *value;
  1029. size_t i;
  1030. int ret = 0;
  1031. if (!requested_options || !out_values || num_options == 0)
  1032. return -1;
  1033. if (!uname(&utsn)) {
  1034. snprintf(path, sizeof(path), "/boot/config-%s", utsn.release);
  1035. /* gzopen also accepts uncompressed files. */
  1036. file = gzopen(path, "r");
  1037. }
  1038. if (!file) {
  1039. /* Some distributions build with CONFIG_IKCONFIG=y and put the
  1040. * config file at /proc/config.gz.
  1041. */
  1042. file = gzopen("/proc/config.gz", "r");
  1043. }
  1044. if (!file) {
  1045. p_info("skipping kernel config, can't open file: %s",
  1046. strerror(errno));
  1047. return -1;
  1048. }
  1049. if (!gzgets(file, buf, sizeof(buf)) || !gzgets(file, buf, sizeof(buf))) {
  1050. p_info("skipping kernel config, can't read from file: %s",
  1051. strerror(errno));
  1052. ret = -1;
  1053. goto end_parse;
  1054. }
  1055. if (strcmp(buf, "# Automatically generated file; DO NOT EDIT.\n")) {
  1056. p_info("skipping kernel config, can't find correct file");
  1057. ret = -1;
  1058. goto end_parse;
  1059. }
  1060. while (read_next_kernel_config_option(file, buf, sizeof(buf), &value)) {
  1061. for (i = 0; i < num_options; i++) {
  1062. if ((define_prefix && !requested_options[i].macro_dump) ||
  1063. out_values[i] || strcmp(buf, requested_options[i].name))
  1064. continue;
  1065. out_values[i] = strdup(value);
  1066. }
  1067. }
  1068. end_parse:
  1069. gzclose(file);
  1070. return ret;
  1071. }