LCOV - code coverage report
Current view: top level - bpfilter/cgen/prog - link.c (source / functions) Coverage Total Hit
Test: lcov.out Lines: 0.0 % 114 0
Test Date: 2025-03-25 15:17:39 Functions: 0.0 % 14 0

            Line data    Source code
       1              : // SPDX-License-Identifier: GPL-2.0-only
       2              : /*
       3              :  * Copyright (c) 2022 Meta Platforms, Inc. and affiliates.
       4              :  */
       5              : 
       6              : #include "bpfilter/cgen/prog/link.h"
       7              : 
       8              : #include <linux/bpf.h>
       9              : 
      10              : #include <errno.h>
      11              : #include <fcntl.h>
      12              : #include <stdio.h>
      13              : #include <stdlib.h>
      14              : #include <string.h>
      15              : #include <unistd.h>
      16              : 
      17              : #include "core/bpf.h"
      18              : #include "core/dump.h"
      19              : #include "core/helper.h"
      20              : #include "core/hook.h"
      21              : #include "core/logger.h"
      22              : #include "core/marsh.h"
      23              : 
      24            0 : int bf_link_new(struct bf_link **link, const char *name, enum bf_hook hook)
      25              : {
      26            0 :     _cleanup_bf_link_ struct bf_link *_link = NULL;
      27              : 
      28            0 :     bf_assert(link && name);
      29            0 :     bf_assert(name[0] != '\0');
      30              : 
      31            0 :     _link = malloc(sizeof(*_link));
      32            0 :     if (!_link)
      33              :         return -ENOMEM;
      34              : 
      35            0 :     bf_strncpy(_link->name, BPF_OBJ_NAME_LEN, name);
      36              : 
      37            0 :     _link->fd = -1;
      38            0 :     _link->hook = hook;
      39              : 
      40            0 :     *link = TAKE_PTR(_link);
      41              : 
      42            0 :     return 0;
      43              : }
      44              : 
      45            0 : int bf_link_new_from_marsh(struct bf_link **link, int dir_fd,
      46              :                            const struct bf_marsh *marsh)
      47              : {
      48            0 :     _cleanup_bf_link_ struct bf_link *_link = NULL;
      49              :     struct bf_marsh *elem = NULL;
      50              :     int r;
      51              : 
      52            0 :     bf_assert(link && marsh);
      53              : 
      54            0 :     _link = malloc(sizeof(*_link));
      55            0 :     if (!_link)
      56              :         return -ENOMEM;
      57              : 
      58            0 :     _link->fd = -1;
      59              : 
      60            0 :     if (!(elem = bf_marsh_next_child(marsh, elem)))
      61              :         return -EINVAL;
      62            0 :     memcpy(&_link->name, elem->data, BPF_OBJ_NAME_LEN);
      63              : 
      64            0 :     if (!(elem = bf_marsh_next_child(marsh, elem)))
      65              :         return -EINVAL;
      66            0 :     memcpy(&_link->hook, elem->data, sizeof(_link->hook));
      67              : 
      68            0 :     if (bf_marsh_next_child(marsh, elem))
      69            0 :         return bf_err_r(-E2BIG, "too many elements in bf_link marsh");
      70              : 
      71            0 :     if (dir_fd != -1) {
      72            0 :         r = bf_bpf_obj_get(_link->name, dir_fd, &_link->fd);
      73            0 :         if (r) {
      74            0 :             return bf_err_r(r, "failed to open pinned BPF link '%s'",
      75              :                             _link->name);
      76              :         }
      77              :     }
      78              : 
      79            0 :     *link = TAKE_PTR(_link);
      80              : 
      81            0 :     return 0;
      82              : }
      83              : 
      84            0 : void bf_link_free(struct bf_link **link)
      85              : {
      86            0 :     bf_assert(link);
      87              : 
      88            0 :     if (!*link)
      89              :         return;
      90              : 
      91              :     closep(&(*link)->fd);
      92              :     freep((void *)link);
      93              : }
      94              : 
      95            0 : int bf_link_marsh(const struct bf_link *link, struct bf_marsh **marsh)
      96              : {
      97            0 :     _cleanup_bf_marsh_ struct bf_marsh *_marsh = NULL;
      98              :     int r;
      99              : 
     100            0 :     bf_assert(link && marsh);
     101              : 
     102            0 :     r = bf_marsh_new(&_marsh, NULL, 0);
     103            0 :     if (r)
     104              :         return r;
     105              : 
     106            0 :     r = bf_marsh_add_child_raw(&_marsh, &link->name, BPF_OBJ_NAME_LEN);
     107            0 :     if (r)
     108              :         return r;
     109              : 
     110            0 :     r = bf_marsh_add_child_raw(&_marsh, &link->hook, sizeof(link->hook));
     111            0 :     if (r)
     112              :         return r;
     113              : 
     114            0 :     *marsh = TAKE_PTR(_marsh);
     115              : 
     116            0 :     return 0;
     117              : }
     118              : 
     119            0 : void bf_link_dump(const struct bf_link *link, prefix_t *prefix)
     120              : {
     121            0 :     bf_assert(link && prefix);
     122              : 
     123            0 :     DUMP(prefix, "struct bf_link at %p", link);
     124              : 
     125            0 :     bf_dump_prefix_push(prefix);
     126            0 :     DUMP(prefix, "name: %s", link->name);
     127            0 :     DUMP(prefix, "fd: %d", link->fd);
     128            0 :     DUMP(bf_dump_prefix_last(prefix), "hook: %s", bf_hook_to_str(link->hook));
     129            0 :     bf_dump_prefix_pop(prefix);
     130            0 : }
     131              : 
     132            0 : int bf_link_attach_xdp(struct bf_link *link, int prog_fd, unsigned int ifindex,
     133              :                        enum bf_xdp_attach_mode mode)
     134              : {
     135            0 :     union bpf_attr attr = {
     136              :         .link_create =
     137              :             {
     138              :                 .prog_fd = prog_fd,
     139              :                 .target_fd = ifindex,
     140              :                 .attach_type = BPF_XDP,
     141              :                 .flags = mode,
     142              :             },
     143              :     };
     144              :     int r;
     145              : 
     146            0 :     r = bf_bpf(BPF_LINK_CREATE, &attr);
     147            0 :     if (r < 0)
     148              :         return r;
     149              : 
     150            0 :     link->fd = r;
     151              : 
     152            0 :     return 0;
     153              : }
     154              : 
     155            0 : int bf_link_attach_tc(struct bf_link *link, int prog_fd, unsigned int ifindex)
     156              : {
     157            0 :     union bpf_attr attr = {
     158              :         .link_create =
     159              :             {
     160              :                 .prog_fd = prog_fd,
     161              :                 .target_fd = ifindex,
     162            0 :                 .attach_type = bf_hook_to_attach_type(link->hook),
     163              :             },
     164              :     };
     165              :     int r;
     166              : 
     167            0 :     r = bf_bpf(BPF_LINK_CREATE, &attr);
     168            0 :     if (r < 0)
     169              :         return r;
     170              : 
     171            0 :     link->fd = r;
     172              : 
     173            0 :     return 0;
     174              : }
     175              : 
     176            0 : int bf_link_attach_nf(struct bf_link *link, int prog_fd, unsigned int family,
     177              :                       int priority)
     178              : {
     179            0 :     union bpf_attr attr = {
     180              :         .link_create =
     181              :             {
     182              :                 .prog_fd = prog_fd,
     183              :                 .attach_type = BPF_NETFILTER,
     184              :                 .netfilter =
     185              :                     {
     186              :                         .pf = family,
     187            0 :                         .hooknum = bf_hook_to_nf_hook(link->hook),
     188              :                         .priority = priority,
     189              :                     },
     190              :             },
     191              :     };
     192              :     int r;
     193              : 
     194            0 :     r = bf_bpf(BPF_LINK_CREATE, &attr);
     195            0 :     if (r < 0)
     196              :         return r;
     197              : 
     198            0 :     link->fd = r;
     199              : 
     200            0 :     return 0;
     201              : }
     202              : 
     203            0 : int bf_link_attach_cgroup(struct bf_link *link, int prog_fd,
     204              :                           const char *cgroup_path)
     205              : {
     206              :     _cleanup_close_ int cgroup_fd = -1;
     207            0 :     union bpf_attr attr = {
     208              :         .link_create =
     209              :             {
     210              :                 .prog_fd = prog_fd,
     211            0 :                 .attach_type = bf_hook_to_attach_type(link->hook),
     212              :             },
     213              :     };
     214              :     int r;
     215              : 
     216            0 :     cgroup_fd = open(cgroup_path, O_DIRECTORY | O_RDONLY);
     217            0 :     if (cgroup_fd < 0)
     218            0 :         return bf_err_r(errno, "failed to open cgroup '%s'", cgroup_path);
     219              : 
     220            0 :     attr.link_create.target_fd = cgroup_fd;
     221              : 
     222            0 :     r = bf_bpf(BPF_LINK_CREATE, &attr);
     223            0 :     if (r < 0)
     224              :         return r;
     225              : 
     226            0 :     link->fd = r;
     227              : 
     228            0 :     return 0;
     229              : }
     230              : 
     231            0 : int bf_link_update(struct bf_link *link, int new_prog_fd)
     232              : {
     233            0 :     union bpf_attr attr = {
     234            0 :         .link_update.link_fd = link->fd,
     235              :         .link_update.new_prog_fd = new_prog_fd,
     236              :     };
     237              : 
     238            0 :     return bf_bpf(BPF_LINK_UPDATE, &attr);
     239              : }
     240              : 
     241            0 : int bf_link_detach(struct bf_link *link)
     242              : {
     243            0 :     union bpf_attr attr = {
     244            0 :         .link_detach.link_fd = link->fd,
     245              :     };
     246              :     int r;
     247              : 
     248            0 :     r = bf_bpf(BPF_LINK_DETACH, &attr);
     249            0 :     if (r)
     250              :         return r;
     251              : 
     252              :     closep(&link->fd);
     253              : 
     254            0 :     return 0;
     255              : }
     256              : 
     257            0 : int bf_link_pin(struct bf_link *link, int dir_fd)
     258              : {
     259              :     int r;
     260              : 
     261            0 :     bf_assert(link);
     262            0 :     bf_assert(dir_fd > 0);
     263              : 
     264            0 :     r = bf_bpf_obj_pin(link->name, link->fd, dir_fd);
     265            0 :     if (r)
     266            0 :         return bf_err_r(r, "failed to pin BPF link '%s'", link->name);
     267              : 
     268              :     return 0;
     269              : }
     270              : 
     271            0 : void bf_link_unpin(struct bf_link *link, int dir_fd)
     272              : {
     273              :     int r;
     274              : 
     275            0 :     bf_assert(link);
     276            0 :     bf_assert(dir_fd > 0);
     277              : 
     278            0 :     r = unlinkat(dir_fd, link->name, 0);
     279            0 :     if (r < 0 && errno != ENOENT) {
     280              :         // Do not warn on ENOENT, we want the file to be gone!
     281            0 :         bf_warn_r(
     282              :             errno,
     283              :             "failed to unlink BPF link '%s', assuming the link is not pinned",
     284              :             link->name);
     285              :     }
     286            0 : }
     287              : 
     288            0 : int bf_link_get_info(struct bf_link *link, struct bpf_link_info *info)
     289              : {
     290            0 :     union bpf_attr attr = {};
     291              : 
     292            0 :     bf_assert(link && info);
     293              : 
     294            0 :     if (link->fd == -1)
     295              :         return -ENOENT;
     296              : 
     297            0 :     attr.info.bpf_fd = link->fd;
     298            0 :     attr.info.info_len = sizeof(*info);
     299            0 :     attr.info.info = bf_ptr_to_u64(info);
     300              : 
     301            0 :     return bf_bpf(BPF_OBJ_GET_INFO_BY_FD, &attr);
     302              : }
        

Generated by: LCOV version 2.0-1