162306a36Sopenharmony_ci// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 262306a36Sopenharmony_ci// Copyright (C) 2020 Facebook 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci#ifndef _GNU_SOURCE 562306a36Sopenharmony_ci#define _GNU_SOURCE 662306a36Sopenharmony_ci#endif 762306a36Sopenharmony_ci#include <errno.h> 862306a36Sopenharmony_ci#include <unistd.h> 962306a36Sopenharmony_ci#include <linux/err.h> 1062306a36Sopenharmony_ci#include <bpf/libbpf.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include "main.h" 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_cistatic int do_pin(int argc, char **argv) 1562306a36Sopenharmony_ci{ 1662306a36Sopenharmony_ci DECLARE_LIBBPF_OPTS(bpf_iter_attach_opts, iter_opts); 1762306a36Sopenharmony_ci union bpf_iter_link_info linfo; 1862306a36Sopenharmony_ci const char *objfile, *path; 1962306a36Sopenharmony_ci struct bpf_program *prog; 2062306a36Sopenharmony_ci struct bpf_object *obj; 2162306a36Sopenharmony_ci struct bpf_link *link; 2262306a36Sopenharmony_ci int err = -1, map_fd = -1; 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci if (!REQ_ARGS(2)) 2562306a36Sopenharmony_ci usage(); 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci objfile = GET_ARG(); 2862306a36Sopenharmony_ci path = GET_ARG(); 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci /* optional arguments */ 3162306a36Sopenharmony_ci if (argc) { 3262306a36Sopenharmony_ci if (is_prefix(*argv, "map")) { 3362306a36Sopenharmony_ci NEXT_ARG(); 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci if (!REQ_ARGS(2)) { 3662306a36Sopenharmony_ci p_err("incorrect map spec"); 3762306a36Sopenharmony_ci return -1; 3862306a36Sopenharmony_ci } 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci map_fd = map_parse_fd(&argc, &argv); 4162306a36Sopenharmony_ci if (map_fd < 0) 4262306a36Sopenharmony_ci return -1; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci memset(&linfo, 0, sizeof(linfo)); 4562306a36Sopenharmony_ci linfo.map.map_fd = map_fd; 4662306a36Sopenharmony_ci iter_opts.link_info = &linfo; 4762306a36Sopenharmony_ci iter_opts.link_info_len = sizeof(linfo); 4862306a36Sopenharmony_ci } 4962306a36Sopenharmony_ci } 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci obj = bpf_object__open(objfile); 5262306a36Sopenharmony_ci if (!obj) { 5362306a36Sopenharmony_ci err = -errno; 5462306a36Sopenharmony_ci p_err("can't open objfile %s", objfile); 5562306a36Sopenharmony_ci goto close_map_fd; 5662306a36Sopenharmony_ci } 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci err = bpf_object__load(obj); 5962306a36Sopenharmony_ci if (err) { 6062306a36Sopenharmony_ci p_err("can't load objfile %s", objfile); 6162306a36Sopenharmony_ci goto close_obj; 6262306a36Sopenharmony_ci } 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci prog = bpf_object__next_program(obj, NULL); 6562306a36Sopenharmony_ci if (!prog) { 6662306a36Sopenharmony_ci err = -errno; 6762306a36Sopenharmony_ci p_err("can't find bpf program in objfile %s", objfile); 6862306a36Sopenharmony_ci goto close_obj; 6962306a36Sopenharmony_ci } 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci link = bpf_program__attach_iter(prog, &iter_opts); 7262306a36Sopenharmony_ci if (!link) { 7362306a36Sopenharmony_ci err = -errno; 7462306a36Sopenharmony_ci p_err("attach_iter failed for program %s", 7562306a36Sopenharmony_ci bpf_program__name(prog)); 7662306a36Sopenharmony_ci goto close_obj; 7762306a36Sopenharmony_ci } 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci err = mount_bpffs_for_pin(path, false); 8062306a36Sopenharmony_ci if (err) 8162306a36Sopenharmony_ci goto close_link; 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci err = bpf_link__pin(link, path); 8462306a36Sopenharmony_ci if (err) { 8562306a36Sopenharmony_ci p_err("pin_iter failed for program %s to path %s", 8662306a36Sopenharmony_ci bpf_program__name(prog), path); 8762306a36Sopenharmony_ci goto close_link; 8862306a36Sopenharmony_ci } 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ciclose_link: 9162306a36Sopenharmony_ci bpf_link__destroy(link); 9262306a36Sopenharmony_ciclose_obj: 9362306a36Sopenharmony_ci bpf_object__close(obj); 9462306a36Sopenharmony_ciclose_map_fd: 9562306a36Sopenharmony_ci if (map_fd >= 0) 9662306a36Sopenharmony_ci close(map_fd); 9762306a36Sopenharmony_ci return err; 9862306a36Sopenharmony_ci} 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_cistatic int do_help(int argc, char **argv) 10162306a36Sopenharmony_ci{ 10262306a36Sopenharmony_ci fprintf(stderr, 10362306a36Sopenharmony_ci "Usage: %1$s %2$s pin OBJ PATH [map MAP]\n" 10462306a36Sopenharmony_ci " %1$s %2$s help\n" 10562306a36Sopenharmony_ci "\n" 10662306a36Sopenharmony_ci " " HELP_SPEC_MAP "\n" 10762306a36Sopenharmony_ci " " HELP_SPEC_OPTIONS " }\n" 10862306a36Sopenharmony_ci "", 10962306a36Sopenharmony_ci bin_name, "iter"); 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci return 0; 11262306a36Sopenharmony_ci} 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_cistatic const struct cmd cmds[] = { 11562306a36Sopenharmony_ci { "help", do_help }, 11662306a36Sopenharmony_ci { "pin", do_pin }, 11762306a36Sopenharmony_ci { 0 } 11862306a36Sopenharmony_ci}; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ciint do_iter(int argc, char **argv) 12162306a36Sopenharmony_ci{ 12262306a36Sopenharmony_ci return cmd_select(cmds, argc, argv, do_help); 12362306a36Sopenharmony_ci} 124