^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* eBPF example program:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * - Loads eBPF program
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * The eBPF program sets the sk_bound_dev_if index in new AF_INET{6}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * sockets opened by processes in the cgroup.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * - Attaches the new program to a cgroup using BPF_PROG_ATTACH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #define _GNU_SOURCE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <stddef.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <assert.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <fcntl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <net/if.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <inttypes.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/bpf.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <bpf/bpf.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include "bpf_insn.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) char bpf_log_buf[BPF_LOG_BUF_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) static int prog_load(__u32 idx, __u32 mark, __u32 prio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) /* save pointer to context */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) struct bpf_insn prog_start[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) struct bpf_insn prog_end[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) BPF_MOV64_IMM(BPF_REG_0, 1), /* r0 = verdict */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) BPF_EXIT_INSN(),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) /* set sk_bound_dev_if on socket */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) struct bpf_insn prog_dev[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) BPF_MOV64_IMM(BPF_REG_3, idx),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) BPF_MOV64_IMM(BPF_REG_2, offsetof(struct bpf_sock, bound_dev_if)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_3, offsetof(struct bpf_sock, bound_dev_if)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) /* set mark on socket */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) struct bpf_insn prog_mark[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) /* get uid of process */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) BPF_FUNC_get_current_uid_gid),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 0xffffffff),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) /* if uid is 0, use given mark, else use the uid as the mark */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) BPF_MOV64_REG(BPF_REG_3, BPF_REG_0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) BPF_MOV64_IMM(BPF_REG_3, mark),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) /* set the mark on the new socket */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) BPF_MOV64_IMM(BPF_REG_2, offsetof(struct bpf_sock, mark)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_3, offsetof(struct bpf_sock, mark)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) /* set priority on socket */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) struct bpf_insn prog_prio[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) BPF_MOV64_IMM(BPF_REG_3, prio),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) BPF_MOV64_IMM(BPF_REG_2, offsetof(struct bpf_sock, priority)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_3, offsetof(struct bpf_sock, priority)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) struct bpf_insn *prog;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) size_t insns_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) void *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) insns_cnt = sizeof(prog_start) + sizeof(prog_end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) if (idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) insns_cnt += sizeof(prog_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) if (mark)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) insns_cnt += sizeof(prog_mark);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) if (prio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) insns_cnt += sizeof(prog_prio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) p = prog = malloc(insns_cnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) if (!prog) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) fprintf(stderr, "Failed to allocate memory for instructions\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) return EXIT_FAILURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) memcpy(p, prog_start, sizeof(prog_start));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) p += sizeof(prog_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) if (idx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) memcpy(p, prog_dev, sizeof(prog_dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) p += sizeof(prog_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) if (mark) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) memcpy(p, prog_mark, sizeof(prog_mark));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) p += sizeof(prog_mark);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) if (prio) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) memcpy(p, prog_prio, sizeof(prog_prio));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) p += sizeof(prog_prio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) memcpy(p, prog_end, sizeof(prog_end));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) p += sizeof(prog_end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) insns_cnt /= sizeof(struct bpf_insn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) ret = bpf_load_program(BPF_PROG_TYPE_CGROUP_SOCK, prog, insns_cnt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) "GPL", 0, bpf_log_buf, BPF_LOG_BUF_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) free(prog);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) static int get_bind_to_device(int sd, char *name, size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) socklen_t optlen = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) name[0] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) rc = getsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, name, &optlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) perror("setsockopt(SO_BINDTODEVICE)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) static unsigned int get_somark(int sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) unsigned int mark = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) socklen_t optlen = sizeof(mark);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) rc = getsockopt(sd, SOL_SOCKET, SO_MARK, &mark, &optlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) perror("getsockopt(SO_MARK)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) return mark;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) static unsigned int get_priority(int sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) unsigned int prio = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) socklen_t optlen = sizeof(prio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) rc = getsockopt(sd, SOL_SOCKET, SO_PRIORITY, &prio, &optlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) perror("getsockopt(SO_PRIORITY)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) return prio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) static int show_sockopts(int family)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) unsigned int mark, prio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) char name[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) int sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) sd = socket(family, SOCK_DGRAM, 17);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) if (sd < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) perror("socket");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) if (get_bind_to_device(sd, name, sizeof(name)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) mark = get_somark(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) prio = get_priority(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) close(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) printf("sd %d: dev %s, mark %u, priority %u\n", sd, name, mark, prio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) static int usage(const char *argv0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) printf("Usage:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) printf(" Attach a program\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) printf(" %s -b bind-to-dev -m mark -p prio cg-path\n", argv0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) printf("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) printf(" Detach a program\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) printf(" %s -d cg-path\n", argv0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) printf("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) printf(" Show inherited socket settings (mark, priority, and device)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) printf(" %s [-6]\n", argv0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) return EXIT_FAILURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) int main(int argc, char **argv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) __u32 idx = 0, mark = 0, prio = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) const char *cgrp_path = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) int cg_fd, prog_fd, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) int family = PF_INET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) int do_attach = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) while ((rc = getopt(argc, argv, "db:m:p:6")) != -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) switch (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) case 'd':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) do_attach = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) case 'b':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) idx = if_nametoindex(optarg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) if (!idx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) idx = strtoumax(optarg, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if (!idx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) printf("Invalid device name\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) return EXIT_FAILURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) case 'm':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) mark = strtoumax(optarg, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) case 'p':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) prio = strtoumax(optarg, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) case '6':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) family = PF_INET6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) return usage(argv[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) if (optind == argc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) return show_sockopts(family);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) cgrp_path = argv[optind];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) if (!cgrp_path) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) fprintf(stderr, "cgroup path not given\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) return EXIT_FAILURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) if (do_attach && !idx && !mark && !prio) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) fprintf(stderr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) "One of device, mark or priority must be given\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) return EXIT_FAILURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) cg_fd = open(cgrp_path, O_DIRECTORY | O_RDONLY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) if (cg_fd < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) printf("Failed to open cgroup path: '%s'\n", strerror(errno));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) return EXIT_FAILURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (do_attach) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) prog_fd = prog_load(idx, mark, prio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) if (prog_fd < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) printf("Failed to load prog: '%s'\n", strerror(errno));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) printf("Output from kernel verifier:\n%s\n-------\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) bpf_log_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) return EXIT_FAILURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) ret = bpf_prog_attach(prog_fd, cg_fd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) BPF_CGROUP_INET_SOCK_CREATE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) printf("Failed to attach prog to cgroup: '%s'\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) strerror(errno));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) return EXIT_FAILURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) ret = bpf_prog_detach(cg_fd, BPF_CGROUP_INET_SOCK_CREATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) printf("Failed to detach prog from cgroup: '%s'\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) strerror(errno));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) return EXIT_FAILURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) close(cg_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) return EXIT_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) }