~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/bpf/bpftool/main.c

Version: ~ [ linux-5.0-rc6 ] ~ [ linux-4.20.10 ] ~ [ linux-4.19.23 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.101 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.158 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.174 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.134 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.63 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.39.4 ] ~ [ linux-2.6.38.8 ] ~ [ linux-2.6.37.6 ] ~ [ linux-2.6.36.4 ] ~ [ linux-2.6.35.14 ] ~ [ linux-2.6.34.15 ] ~ [ linux-2.6.33.20 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
  2 /* Copyright (C) 2017-2018 Netronome Systems, Inc. */
  3 
  4 #include <ctype.h>
  5 #include <errno.h>
  6 #include <getopt.h>
  7 #include <linux/bpf.h>
  8 #include <stdio.h>
  9 #include <stdlib.h>
 10 #include <string.h>
 11 
 12 #include <bpf.h>
 13 
 14 #include "main.h"
 15 
 16 #define BATCH_LINE_LEN_MAX 65536
 17 #define BATCH_ARG_NB_MAX 4096
 18 
 19 const char *bin_name;
 20 static int last_argc;
 21 static char **last_argv;
 22 static int (*last_do_help)(int argc, char **argv);
 23 json_writer_t *json_wtr;
 24 bool pretty_output;
 25 bool json_output;
 26 bool show_pinned;
 27 bool block_mount;
 28 int bpf_flags;
 29 struct pinned_obj_table prog_table;
 30 struct pinned_obj_table map_table;
 31 
 32 static void __noreturn clean_and_exit(int i)
 33 {
 34         if (json_output)
 35                 jsonw_destroy(&json_wtr);
 36 
 37         exit(i);
 38 }
 39 
 40 void usage(void)
 41 {
 42         last_do_help(last_argc - 1, last_argv + 1);
 43 
 44         clean_and_exit(-1);
 45 }
 46 
 47 static int do_help(int argc, char **argv)
 48 {
 49         if (json_output) {
 50                 jsonw_null(json_wtr);
 51                 return 0;
 52         }
 53 
 54         fprintf(stderr,
 55                 "Usage: %s [OPTIONS] OBJECT { COMMAND | help }\n"
 56                 "       %s batch file FILE\n"
 57                 "       %s version\n"
 58                 "\n"
 59                 "       OBJECT := { prog | map | cgroup | perf | net }\n"
 60                 "       " HELP_SPEC_OPTIONS "\n"
 61                 "",
 62                 bin_name, bin_name, bin_name);
 63 
 64         return 0;
 65 }
 66 
 67 static int do_version(int argc, char **argv)
 68 {
 69         if (json_output) {
 70                 jsonw_start_object(json_wtr);
 71                 jsonw_name(json_wtr, "version");
 72                 jsonw_printf(json_wtr, "\"%s\"", BPFTOOL_VERSION);
 73                 jsonw_end_object(json_wtr);
 74         } else {
 75                 printf("%s v%s\n", bin_name, BPFTOOL_VERSION);
 76         }
 77         return 0;
 78 }
 79 
 80 int cmd_select(const struct cmd *cmds, int argc, char **argv,
 81                int (*help)(int argc, char **argv))
 82 {
 83         unsigned int i;
 84 
 85         last_argc = argc;
 86         last_argv = argv;
 87         last_do_help = help;
 88 
 89         if (argc < 1 && cmds[0].func)
 90                 return cmds[0].func(argc, argv);
 91 
 92         for (i = 0; cmds[i].func; i++)
 93                 if (is_prefix(*argv, cmds[i].cmd))
 94                         return cmds[i].func(argc - 1, argv + 1);
 95 
 96         help(argc - 1, argv + 1);
 97 
 98         return -1;
 99 }
100 
101 bool is_prefix(const char *pfx, const char *str)
102 {
103         if (!pfx)
104                 return false;
105         if (strlen(str) < strlen(pfx))
106                 return false;
107 
108         return !memcmp(str, pfx, strlen(pfx));
109 }
110 
111 void fprint_hex(FILE *f, void *arg, unsigned int n, const char *sep)
112 {
113         unsigned char *data = arg;
114         unsigned int i;
115 
116         for (i = 0; i < n; i++) {
117                 const char *pfx = "";
118 
119                 if (!i)
120                         /* nothing */;
121                 else if (!(i % 16))
122                         fprintf(f, "\n");
123                 else if (!(i % 8))
124                         fprintf(f, "  ");
125                 else
126                         pfx = sep;
127 
128                 fprintf(f, "%s%02hhx", i ? pfx : "", data[i]);
129         }
130 }
131 
132 /* Split command line into argument vector. */
133 static int make_args(char *line, char *n_argv[], int maxargs, int cmd_nb)
134 {
135         static const char ws[] = " \t\r\n";
136         char *cp = line;
137         int n_argc = 0;
138 
139         while (*cp) {
140                 /* Skip leading whitespace. */
141                 cp += strspn(cp, ws);
142 
143                 if (*cp == '\0')
144                         break;
145 
146                 if (n_argc >= (maxargs - 1)) {
147                         p_err("too many arguments to command %d", cmd_nb);
148                         return -1;
149                 }
150 
151                 /* Word begins with quote. */
152                 if (*cp == '\'' || *cp == '"') {
153                         char quote = *cp++;
154 
155                         n_argv[n_argc++] = cp;
156                         /* Find ending quote. */
157                         cp = strchr(cp, quote);
158                         if (!cp) {
159                                 p_err("unterminated quoted string in command %d",
160                                       cmd_nb);
161                                 return -1;
162                         }
163                 } else {
164                         n_argv[n_argc++] = cp;
165 
166                         /* Find end of word. */
167                         cp += strcspn(cp, ws);
168                         if (*cp == '\0')
169                                 break;
170                 }
171 
172                 /* Separate words. */
173                 *cp++ = 0;
174         }
175         n_argv[n_argc] = NULL;
176 
177         return n_argc;
178 }
179 
180 static int do_batch(int argc, char **argv);
181 
182 static const struct cmd cmds[] = {
183         { "help",       do_help },
184         { "batch",      do_batch },
185         { "prog",       do_prog },
186         { "map",        do_map },
187         { "cgroup",     do_cgroup },
188         { "perf",       do_perf },
189         { "net",        do_net },
190         { "version",    do_version },
191         { 0 }
192 };
193 
194 static int do_batch(int argc, char **argv)
195 {
196         char buf[BATCH_LINE_LEN_MAX], contline[BATCH_LINE_LEN_MAX];
197         char *n_argv[BATCH_ARG_NB_MAX];
198         unsigned int lines = 0;
199         int n_argc;
200         FILE *fp;
201         char *cp;
202         int err;
203         int i;
204 
205         if (argc < 2) {
206                 p_err("too few parameters for batch");
207                 return -1;
208         } else if (!is_prefix(*argv, "file")) {
209                 p_err("expected 'file', got: %s", *argv);
210                 return -1;
211         } else if (argc > 2) {
212                 p_err("too many parameters for batch");
213                 return -1;
214         }
215         NEXT_ARG();
216 
217         if (!strcmp(*argv, "-"))
218                 fp = stdin;
219         else
220                 fp = fopen(*argv, "r");
221         if (!fp) {
222                 p_err("Can't open file (%s): %s", *argv, strerror(errno));
223                 return -1;
224         }
225 
226         if (json_output)
227                 jsonw_start_array(json_wtr);
228         while (fgets(buf, sizeof(buf), fp)) {
229                 cp = strchr(buf, '#');
230                 if (cp)
231                         *cp = '\0';
232 
233                 if (strlen(buf) == sizeof(buf) - 1) {
234                         errno = E2BIG;
235                         break;
236                 }
237 
238                 /* Append continuation lines if any (coming after a line ending
239                  * with '\' in the batch file).
240                  */
241                 while ((cp = strstr(buf, "\\\n")) != NULL) {
242                         if (!fgets(contline, sizeof(contline), fp) ||
243                             strlen(contline) == 0) {
244                                 p_err("missing continuation line on command %d",
245                                       lines);
246                                 err = -1;
247                                 goto err_close;
248                         }
249 
250                         cp = strchr(contline, '#');
251                         if (cp)
252                                 *cp = '\0';
253 
254                         if (strlen(buf) + strlen(contline) + 1 > sizeof(buf)) {
255                                 p_err("command %d is too long", lines);
256                                 err = -1;
257                                 goto err_close;
258                         }
259                         buf[strlen(buf) - 2] = '\0';
260                         strcat(buf, contline);
261                 }
262 
263                 n_argc = make_args(buf, n_argv, BATCH_ARG_NB_MAX, lines);
264                 if (!n_argc)
265                         continue;
266                 if (n_argc < 0)
267                         goto err_close;
268 
269                 if (json_output) {
270                         jsonw_start_object(json_wtr);
271                         jsonw_name(json_wtr, "command");
272                         jsonw_start_array(json_wtr);
273                         for (i = 0; i < n_argc; i++)
274                                 jsonw_string(json_wtr, n_argv[i]);
275                         jsonw_end_array(json_wtr);
276                         jsonw_name(json_wtr, "output");
277                 }
278 
279                 err = cmd_select(cmds, n_argc, n_argv, do_help);
280 
281                 if (json_output)
282                         jsonw_end_object(json_wtr);
283 
284                 if (err)
285                         goto err_close;
286 
287                 lines++;
288         }
289 
290         if (errno && errno != ENOENT) {
291                 p_err("reading batch file failed: %s", strerror(errno));
292                 err = -1;
293         } else {
294                 if (!json_output)
295                         printf("processed %d commands\n", lines);
296                 err = 0;
297         }
298 err_close:
299         if (fp != stdin)
300                 fclose(fp);
301 
302         if (json_output)
303                 jsonw_end_array(json_wtr);
304 
305         return err;
306 }
307 
308 int main(int argc, char **argv)
309 {
310         static const struct option options[] = {
311                 { "json",       no_argument,    NULL,   'j' },
312                 { "help",       no_argument,    NULL,   'h' },
313                 { "pretty",     no_argument,    NULL,   'p' },
314                 { "version",    no_argument,    NULL,   'V' },
315                 { "bpffs",      no_argument,    NULL,   'f' },
316                 { "mapcompat",  no_argument,    NULL,   'm' },
317                 { "nomount",    no_argument,    NULL,   'n' },
318                 { 0 }
319         };
320         int opt, ret;
321 
322         last_do_help = do_help;
323         pretty_output = false;
324         json_output = false;
325         show_pinned = false;
326         block_mount = false;
327         bin_name = argv[0];
328 
329         hash_init(prog_table.table);
330         hash_init(map_table.table);
331 
332         opterr = 0;
333         while ((opt = getopt_long(argc, argv, "Vhpjfmn",
334                                   options, NULL)) >= 0) {
335                 switch (opt) {
336                 case 'V':
337                         return do_version(argc, argv);
338                 case 'h':
339                         return do_help(argc, argv);
340                 case 'p':
341                         pretty_output = true;
342                         /* fall through */
343                 case 'j':
344                         if (!json_output) {
345                                 json_wtr = jsonw_new(stdout);
346                                 if (!json_wtr) {
347                                         p_err("failed to create JSON writer");
348                                         return -1;
349                                 }
350                                 json_output = true;
351                         }
352                         jsonw_pretty(json_wtr, pretty_output);
353                         break;
354                 case 'f':
355                         show_pinned = true;
356                         break;
357                 case 'm':
358                         bpf_flags = MAPS_RELAX_COMPAT;
359                         break;
360                 case 'n':
361                         block_mount = true;
362                         break;
363                 default:
364                         p_err("unrecognized option '%s'", argv[optind - 1]);
365                         if (json_output)
366                                 clean_and_exit(-1);
367                         else
368                                 usage();
369                 }
370         }
371 
372         argc -= optind;
373         argv += optind;
374         if (argc < 0)
375                 usage();
376 
377         ret = cmd_select(cmds, argc, argv, do_help);
378 
379         if (json_output)
380                 jsonw_destroy(&json_wtr);
381 
382         if (show_pinned) {
383                 delete_pinned_obj_table(&prog_table);
384                 delete_pinned_obj_table(&map_table);
385         }
386 
387         return ret;
388 }
389 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp