// SPDX-License-Identifier: GPL-2.0 
 | 
/* Copyright (c) 2020 Facebook */ 
 | 
#include <argp.h> 
 | 
#include <stdio.h> 
 | 
#include <stdlib.h> 
 | 
#include <string.h> 
 | 
#include <unistd.h> 
 | 
#include <fcntl.h> 
 | 
#include <sys/resource.h> 
 | 
#include <bpf/libbpf.h> 
 | 
#include <bpf/bpf.h> 
 | 
#include <sys/mount.h> 
 | 
#include "iterators.skel.h" 
 | 
#include "bpf_preload_common.h" 
 | 
  
 | 
int to_kernel = -1; 
 | 
int from_kernel = 0; 
 | 
  
 | 
static int send_link_to_kernel(struct bpf_link *link, const char *link_name) 
 | 
{ 
 | 
    struct bpf_preload_info obj = {}; 
 | 
    struct bpf_link_info info = {}; 
 | 
    __u32 info_len = sizeof(info); 
 | 
    int err; 
 | 
  
 | 
    err = bpf_obj_get_info_by_fd(bpf_link__fd(link), &info, &info_len); 
 | 
    if (err) 
 | 
        return err; 
 | 
    obj.link_id = info.id; 
 | 
    if (strlen(link_name) >= sizeof(obj.link_name)) 
 | 
        return -E2BIG; 
 | 
    strcpy(obj.link_name, link_name); 
 | 
    if (write(to_kernel, &obj, sizeof(obj)) != sizeof(obj)) 
 | 
        return -EPIPE; 
 | 
    return 0; 
 | 
} 
 | 
  
 | 
int main(int argc, char **argv) 
 | 
{ 
 | 
    struct rlimit rlim = { RLIM_INFINITY, RLIM_INFINITY }; 
 | 
    struct iterators_bpf *skel; 
 | 
    int err, magic; 
 | 
    int debug_fd; 
 | 
  
 | 
    debug_fd = open("/dev/console", O_WRONLY | O_NOCTTY | O_CLOEXEC); 
 | 
    if (debug_fd < 0) 
 | 
        return 1; 
 | 
    to_kernel = dup(1); 
 | 
    close(1); 
 | 
    dup(debug_fd); 
 | 
    /* now stdin and stderr point to /dev/console */ 
 | 
  
 | 
    read(from_kernel, &magic, sizeof(magic)); 
 | 
    if (magic != BPF_PRELOAD_START) { 
 | 
        printf("bad start magic %d\n", magic); 
 | 
        return 1; 
 | 
    } 
 | 
    setrlimit(RLIMIT_MEMLOCK, &rlim); 
 | 
    /* libbpf opens BPF object and loads it into the kernel */ 
 | 
    skel = iterators_bpf__open_and_load(); 
 | 
    if (!skel) { 
 | 
        /* iterators.skel.h is little endian. 
 | 
         * libbpf doesn't support automatic little->big conversion 
 | 
         * of BPF bytecode yet. 
 | 
         * The program load will fail in such case. 
 | 
         */ 
 | 
        printf("Failed load could be due to wrong endianness\n"); 
 | 
        return 1; 
 | 
    } 
 | 
    err = iterators_bpf__attach(skel); 
 | 
    if (err) 
 | 
        goto cleanup; 
 | 
  
 | 
    /* send two bpf_link IDs with names to the kernel */ 
 | 
    err = send_link_to_kernel(skel->links.dump_bpf_map, "maps.debug"); 
 | 
    if (err) 
 | 
        goto cleanup; 
 | 
    err = send_link_to_kernel(skel->links.dump_bpf_prog, "progs.debug"); 
 | 
    if (err) 
 | 
        goto cleanup; 
 | 
  
 | 
    /* The kernel will proceed with pinnging the links in bpffs. 
 | 
     * UMD will wait on read from pipe. 
 | 
     */ 
 | 
    read(from_kernel, &magic, sizeof(magic)); 
 | 
    if (magic != BPF_PRELOAD_END) { 
 | 
        printf("bad final magic %d\n", magic); 
 | 
        err = -EINVAL; 
 | 
    } 
 | 
cleanup: 
 | 
    iterators_bpf__destroy(skel); 
 | 
  
 | 
    return err != 0; 
 | 
} 
 |