xref: /linux/tools/bpf/bpftool/main.c (revision 83a37b3292f4aca799b355179ad6fbdd78a08e10)
1 /*
2  * Copyright (C) 2017 Netronome Systems, Inc.
3  *
4  * This software is dual licensed under the GNU General License Version 2,
5  * June 1991 as shown in the file COPYING in the top-level directory of this
6  * source tree or the BSD 2-Clause License provided below.  You have the
7  * option to license this software under the complete terms of either license.
8  *
9  * The BSD 2-Clause License:
10  *
11  *     Redistribution and use in source and binary forms, with or
12  *     without modification, are permitted provided that the following
13  *     conditions are met:
14  *
15  *      1. Redistributions of source code must retain the above
16  *         copyright notice, this list of conditions and the following
17  *         disclaimer.
18  *
19  *      2. Redistributions in binary form must reproduce the above
20  *         copyright notice, this list of conditions and the following
21  *         disclaimer in the documentation and/or other materials
22  *         provided with the distribution.
23  *
24  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31  * SOFTWARE.
32  */
33 
34 /* Author: Jakub Kicinski <kubakici@wp.pl> */
35 
36 #include <bfd.h>
37 #include <ctype.h>
38 #include <errno.h>
39 #include <linux/bpf.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 
44 #include <bpf.h>
45 
46 #include "main.h"
47 
48 const char *bin_name;
49 static int last_argc;
50 static char **last_argv;
51 static int (*last_do_help)(int argc, char **argv);
52 
53 void usage(void)
54 {
55 	last_do_help(last_argc - 1, last_argv + 1);
56 
57 	exit(-1);
58 }
59 
60 static int do_help(int argc, char **argv)
61 {
62 	fprintf(stderr,
63 		"Usage: %s OBJECT { COMMAND | help }\n"
64 		"       %s batch file FILE\n"
65 		"\n"
66 		"       OBJECT := { prog | map }\n",
67 		bin_name, bin_name);
68 
69 	return 0;
70 }
71 
72 int cmd_select(const struct cmd *cmds, int argc, char **argv,
73 	       int (*help)(int argc, char **argv))
74 {
75 	unsigned int i;
76 
77 	last_argc = argc;
78 	last_argv = argv;
79 	last_do_help = help;
80 
81 	if (argc < 1 && cmds[0].func)
82 		return cmds[0].func(argc, argv);
83 
84 	for (i = 0; cmds[i].func; i++)
85 		if (is_prefix(*argv, cmds[i].cmd))
86 			return cmds[i].func(argc - 1, argv + 1);
87 
88 	help(argc - 1, argv + 1);
89 
90 	return -1;
91 }
92 
93 bool is_prefix(const char *pfx, const char *str)
94 {
95 	if (!pfx)
96 		return false;
97 	if (strlen(str) < strlen(pfx))
98 		return false;
99 
100 	return !memcmp(str, pfx, strlen(pfx));
101 }
102 
103 void print_hex(void *arg, unsigned int n, const char *sep)
104 {
105 	unsigned char *data = arg;
106 	unsigned int i;
107 
108 	for (i = 0; i < n; i++) {
109 		const char *pfx = "";
110 
111 		if (!i)
112 			/* nothing */;
113 		else if (!(i % 16))
114 			printf("\n");
115 		else if (!(i % 8))
116 			printf("  ");
117 		else
118 			pfx = sep;
119 
120 		printf("%s%02hhx", i ? pfx : "", data[i]);
121 	}
122 }
123 
124 static int do_batch(int argc, char **argv);
125 
126 static const struct cmd cmds[] = {
127 	{ "help",	do_help },
128 	{ "batch",	do_batch },
129 	{ "prog",	do_prog },
130 	{ "map",	do_map },
131 	{ 0 }
132 };
133 
134 static int do_batch(int argc, char **argv)
135 {
136 	unsigned int lines = 0;
137 	char *n_argv[4096];
138 	char buf[65536];
139 	int n_argc;
140 	FILE *fp;
141 	int err;
142 
143 	if (argc < 2) {
144 		err("too few parameters for batch\n");
145 		return -1;
146 	} else if (!is_prefix(*argv, "file")) {
147 		err("expected 'file', got: %s\n", *argv);
148 		return -1;
149 	} else if (argc > 2) {
150 		err("too many parameters for batch\n");
151 		return -1;
152 	}
153 	NEXT_ARG();
154 
155 	fp = fopen(*argv, "r");
156 	if (!fp) {
157 		err("Can't open file (%s): %s\n", *argv, strerror(errno));
158 		return -1;
159 	}
160 
161 	while (fgets(buf, sizeof(buf), fp)) {
162 		if (strlen(buf) == sizeof(buf) - 1) {
163 			errno = E2BIG;
164 			break;
165 		}
166 
167 		n_argc = 0;
168 		n_argv[n_argc] = strtok(buf, " \t\n");
169 
170 		while (n_argv[n_argc]) {
171 			n_argc++;
172 			if (n_argc == ARRAY_SIZE(n_argv)) {
173 				err("line %d has too many arguments, skip\n",
174 				    lines);
175 				n_argc = 0;
176 				break;
177 			}
178 			n_argv[n_argc] = strtok(NULL, " \t\n");
179 		}
180 
181 		if (!n_argc)
182 			continue;
183 
184 		err = cmd_select(cmds, n_argc, n_argv, do_help);
185 		if (err)
186 			goto err_close;
187 
188 		lines++;
189 	}
190 
191 	if (errno && errno != ENOENT) {
192 		perror("reading batch file failed");
193 		err = -1;
194 	} else {
195 		info("processed %d lines\n", lines);
196 		err = 0;
197 	}
198 err_close:
199 	fclose(fp);
200 
201 	return err;
202 }
203 
204 int main(int argc, char **argv)
205 {
206 	bin_name = argv[0];
207 	NEXT_ARG();
208 
209 	bfd_init();
210 
211 	return cmd_select(cmds, argc, argv, do_help);
212 }
213