iproute2/lib/bpf_glue.c
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2/*
   3 * bpf_glue.c:  BPF code to call both legacy and libbpf code
   4 * Authors:     Hangbin Liu <haliu@redhat.com>
   5 *
   6 */
   7#include <sys/syscall.h>
   8#include <limits.h>
   9#include <unistd.h>
  10#include <errno.h>
  11
  12#include "bpf_util.h"
  13#ifdef HAVE_LIBBPF
  14#include <bpf/bpf.h>
  15#endif
  16
  17int bpf(int cmd, union bpf_attr *attr, unsigned int size)
  18{
  19#ifdef __NR_bpf
  20        return syscall(__NR_bpf, cmd, attr, size);
  21#else
  22        fprintf(stderr, "No bpf syscall, kernel headers too old?\n");
  23        errno = ENOSYS;
  24        return -1;
  25#endif
  26}
  27
  28int bpf_program_attach(int prog_fd, int target_fd, enum bpf_attach_type type)
  29{
  30#ifdef HAVE_LIBBPF
  31        return bpf_prog_attach(prog_fd, target_fd, type, 0);
  32#else
  33        return bpf_prog_attach_fd(prog_fd, target_fd, type);
  34#endif
  35}
  36
  37#ifdef HAVE_LIBBPF
  38static const char *_libbpf_compile_version = LIBBPF_VERSION;
  39static char _libbpf_version[10] = {};
  40
  41const char *get_libbpf_version(void)
  42{
  43        /* Start by copying compile-time version into buffer so we have a
  44         * fallback value in case we are dynamically linked, or can't find a
  45         * version in /proc/self/maps below.
  46         */
  47        strncpy(_libbpf_version, _libbpf_compile_version,
  48                sizeof(_libbpf_version)-1);
  49#ifdef LIBBPF_DYNAMIC
  50        char buf[PATH_MAX], *s;
  51        bool found = false;
  52        FILE *fp;
  53
  54        /* When dynamically linking against libbpf, we can't be sure that the
  55         * version we discovered at compile time is actually the one we are
  56         * using at runtime. This can lead to hard-to-debug errors, so we try to
  57         * discover the correct version at runtime.
  58         *
  59         * The simple solution to this would be if libbpf itself exported a
  60         * version in its API. But since it doesn't, we work around this by
  61         * parsing the mappings of the binary at runtime, looking for the full
  62         * filename of libbpf.so and using that.
  63         */
  64        fp = fopen("/proc/self/maps", "r");
  65        if (fp == NULL)
  66                goto out;
  67
  68        while (fgets(buf, sizeof(buf), fp) != NULL) {
  69                if ((s = strstr(buf, "libbpf.so.")) != NULL) {
  70                        strncpy(_libbpf_version, s+10, sizeof(_libbpf_version)-1);
  71                        strtok(_libbpf_version, "\n");
  72                        found = true;
  73                        break;
  74                }
  75        }
  76
  77        fclose(fp);
  78out:
  79        if (!found)
  80                fprintf(stderr, "Couldn't find runtime libbpf version - falling back to compile-time value!\n");
  81#endif /* LIBBPF_DYNAMIC */
  82
  83        _libbpf_version[sizeof(_libbpf_version)-1] = '\0';
  84        return _libbpf_version;
  85}
  86#else
  87const char *get_libbpf_version(void)
  88{
  89        return NULL;
  90}
  91#endif /* HAVE_LIBBPF */
  92