| /* Copyright (c) 2017 Facebook |
| * |
| * This program is free software; you can redistribute it and/or |
| * modify it under the terms of version 2 of the GNU General Public |
| * License as published by the Free Software Foundation. |
| */ |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <linux/bpf.h> |
| #include "libbpf.h" |
| #include "bpf_load.h" |
| #include <unistd.h> |
| #include <errno.h> |
| #include <fcntl.h> |
| #include <linux/unistd.h> |
| |
| static void usage(char *pname) |
| { |
| printf("USAGE:\n %s [-l] <cg-path> <prog filename>\n", pname); |
| printf("\tLoad and attach a sock_ops program to the specified " |
| "cgroup\n"); |
| printf("\tIf \"-l\" is used, the program will continue to run\n"); |
| printf("\tprinting the BPF log buffer\n"); |
| printf("\tIf the specified filename does not end in \".o\", it\n"); |
| printf("\tappends \"_kern.o\" to the name\n"); |
| printf("\n"); |
| printf(" %s -r <cg-path>\n", pname); |
| printf("\tDetaches the currently attached sock_ops program\n"); |
| printf("\tfrom the specified cgroup\n"); |
| printf("\n"); |
| exit(1); |
| } |
| |
| int main(int argc, char **argv) |
| { |
| int logFlag = 0; |
| int error = 0; |
| char *cg_path; |
| char fn[500]; |
| char *prog; |
| int cg_fd; |
| |
| if (argc < 3) |
| usage(argv[0]); |
| |
| if (!strcmp(argv[1], "-r")) { |
| cg_path = argv[2]; |
| cg_fd = open(cg_path, O_DIRECTORY, O_RDONLY); |
| error = bpf_prog_detach(cg_fd, BPF_CGROUP_SOCK_OPS); |
| if (error) { |
| printf("ERROR: bpf_prog_detach: %d (%s)\n", |
| error, strerror(errno)); |
| return 2; |
| } |
| return 0; |
| } else if (!strcmp(argv[1], "-h")) { |
| usage(argv[0]); |
| } else if (!strcmp(argv[1], "-l")) { |
| logFlag = 1; |
| if (argc < 4) |
| usage(argv[0]); |
| } |
| |
| prog = argv[argc - 1]; |
| cg_path = argv[argc - 2]; |
| if (strlen(prog) > 480) { |
| fprintf(stderr, "ERROR: program name too long (> 480 chars)\n"); |
| return 3; |
| } |
| cg_fd = open(cg_path, O_DIRECTORY, O_RDONLY); |
| |
| if (!strcmp(prog + strlen(prog)-2, ".o")) |
| strcpy(fn, prog); |
| else |
| sprintf(fn, "%s_kern.o", prog); |
| if (logFlag) |
| printf("loading bpf file:%s\n", fn); |
| if (load_bpf_file(fn)) { |
| printf("ERROR: load_bpf_file failed for: %s\n", fn); |
| printf("%s", bpf_log_buf); |
| return 4; |
| } |
| if (logFlag) |
| printf("TCP BPF Loaded %s\n", fn); |
| |
| error = bpf_prog_attach(prog_fd[0], cg_fd, BPF_CGROUP_SOCK_OPS, 0); |
| if (error) { |
| printf("ERROR: bpf_prog_attach: %d (%s)\n", |
| error, strerror(errno)); |
| return 5; |
| } else if (logFlag) { |
| read_trace_pipe(); |
| } |
| |
| return error; |
| } |