root/tools/testing/selftests/bpf/test_skb_cgroup_id_user.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mk_dst_addr
  2. send_packet
  3. get_map_fd_by_prog_id
  4. check_ancestor_cgroup_ids
  5. main

   1 // SPDX-License-Identifier: GPL-2.0
   2 // Copyright (c) 2018 Facebook
   3 
   4 #include <stdlib.h>
   5 #include <string.h>
   6 #include <unistd.h>
   7 
   8 #include <arpa/inet.h>
   9 #include <net/if.h>
  10 #include <netinet/in.h>
  11 #include <sys/socket.h>
  12 #include <sys/types.h>
  13 
  14 
  15 #include <bpf/bpf.h>
  16 #include <bpf/libbpf.h>
  17 
  18 #include "bpf_rlimit.h"
  19 #include "cgroup_helpers.h"
  20 
  21 #define CGROUP_PATH             "/skb_cgroup_test"
  22 #define NUM_CGROUP_LEVELS       4
  23 
  24 /* RFC 4291, Section 2.7.1 */
  25 #define LINKLOCAL_MULTICAST     "ff02::1"
  26 
  27 static int mk_dst_addr(const char *ip, const char *iface,
  28                        struct sockaddr_in6 *dst)
  29 {
  30         memset(dst, 0, sizeof(*dst));
  31 
  32         dst->sin6_family = AF_INET6;
  33         dst->sin6_port = htons(1025);
  34 
  35         if (inet_pton(AF_INET6, ip, &dst->sin6_addr) != 1) {
  36                 log_err("Invalid IPv6: %s", ip);
  37                 return -1;
  38         }
  39 
  40         dst->sin6_scope_id = if_nametoindex(iface);
  41         if (!dst->sin6_scope_id) {
  42                 log_err("Failed to get index of iface: %s", iface);
  43                 return -1;
  44         }
  45 
  46         return 0;
  47 }
  48 
  49 static int send_packet(const char *iface)
  50 {
  51         struct sockaddr_in6 dst;
  52         char msg[] = "msg";
  53         int err = 0;
  54         int fd = -1;
  55 
  56         if (mk_dst_addr(LINKLOCAL_MULTICAST, iface, &dst))
  57                 goto err;
  58 
  59         fd = socket(AF_INET6, SOCK_DGRAM, 0);
  60         if (fd == -1) {
  61                 log_err("Failed to create UDP socket");
  62                 goto err;
  63         }
  64 
  65         if (sendto(fd, &msg, sizeof(msg), 0, (const struct sockaddr *)&dst,
  66                    sizeof(dst)) == -1) {
  67                 log_err("Failed to send datagram");
  68                 goto err;
  69         }
  70 
  71         goto out;
  72 err:
  73         err = -1;
  74 out:
  75         if (fd >= 0)
  76                 close(fd);
  77         return err;
  78 }
  79 
  80 int get_map_fd_by_prog_id(int prog_id)
  81 {
  82         struct bpf_prog_info info = {};
  83         __u32 info_len = sizeof(info);
  84         __u32 map_ids[1];
  85         int prog_fd = -1;
  86         int map_fd = -1;
  87 
  88         prog_fd = bpf_prog_get_fd_by_id(prog_id);
  89         if (prog_fd < 0) {
  90                 log_err("Failed to get fd by prog id %d", prog_id);
  91                 goto err;
  92         }
  93 
  94         info.nr_map_ids = 1;
  95         info.map_ids = (__u64) (unsigned long) map_ids;
  96 
  97         if (bpf_obj_get_info_by_fd(prog_fd, &info, &info_len)) {
  98                 log_err("Failed to get info by prog fd %d", prog_fd);
  99                 goto err;
 100         }
 101 
 102         if (!info.nr_map_ids) {
 103                 log_err("No maps found for prog fd %d", prog_fd);
 104                 goto err;
 105         }
 106 
 107         map_fd = bpf_map_get_fd_by_id(map_ids[0]);
 108         if (map_fd < 0)
 109                 log_err("Failed to get fd by map id %d", map_ids[0]);
 110 err:
 111         if (prog_fd >= 0)
 112                 close(prog_fd);
 113         return map_fd;
 114 }
 115 
 116 int check_ancestor_cgroup_ids(int prog_id)
 117 {
 118         __u64 actual_ids[NUM_CGROUP_LEVELS], expected_ids[NUM_CGROUP_LEVELS];
 119         __u32 level;
 120         int err = 0;
 121         int map_fd;
 122 
 123         expected_ids[0] = 0x100000001;  /* root cgroup */
 124         expected_ids[1] = get_cgroup_id("");
 125         expected_ids[2] = get_cgroup_id(CGROUP_PATH);
 126         expected_ids[3] = 0; /* non-existent cgroup */
 127 
 128         map_fd = get_map_fd_by_prog_id(prog_id);
 129         if (map_fd < 0)
 130                 goto err;
 131 
 132         for (level = 0; level < NUM_CGROUP_LEVELS; ++level) {
 133                 if (bpf_map_lookup_elem(map_fd, &level, &actual_ids[level])) {
 134                         log_err("Failed to lookup key %d", level);
 135                         goto err;
 136                 }
 137                 if (actual_ids[level] != expected_ids[level]) {
 138                         log_err("%llx (actual) != %llx (expected), level: %u\n",
 139                                 actual_ids[level], expected_ids[level], level);
 140                         goto err;
 141                 }
 142         }
 143 
 144         goto out;
 145 err:
 146         err = -1;
 147 out:
 148         if (map_fd >= 0)
 149                 close(map_fd);
 150         return err;
 151 }
 152 
 153 int main(int argc, char **argv)
 154 {
 155         int cgfd = -1;
 156         int err = 0;
 157 
 158         if (argc < 3) {
 159                 fprintf(stderr, "Usage: %s iface prog_id\n", argv[0]);
 160                 exit(EXIT_FAILURE);
 161         }
 162 
 163         if (setup_cgroup_environment())
 164                 goto err;
 165 
 166         cgfd = create_and_get_cgroup(CGROUP_PATH);
 167         if (cgfd < 0)
 168                 goto err;
 169 
 170         if (join_cgroup(CGROUP_PATH))
 171                 goto err;
 172 
 173         if (send_packet(argv[1]))
 174                 goto err;
 175 
 176         if (check_ancestor_cgroup_ids(atoi(argv[2])))
 177                 goto err;
 178 
 179         goto out;
 180 err:
 181         err = -1;
 182 out:
 183         close(cgfd);
 184         cleanup_cgroup_environment();
 185         printf("[%s]\n", err ? "FAIL" : "PASS");
 186         return err;
 187 }

/* [<][>][^][v][top][bottom][index][help] */