]> git.proxmox.com Git - mirror_iproute2.git/blame - tc/tc_bpf.c
update kernel headers to net-next 4.0-rc5
[mirror_iproute2.git] / tc / tc_bpf.c
CommitLineData
1d129d19
JP
1/*
2 * tc_bpf.c BPF common code
3 *
4 * This program is free software; you can distribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 *
9 * Authors: Daniel Borkmann <dborkman@redhat.com>
10 * Jiri Pirko <jiri@resnulli.us>
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <unistd.h>
16#include <string.h>
17#include <stdbool.h>
18#include <errno.h>
19#include <linux/filter.h>
20#include <linux/netlink.h>
21#include <linux/rtnetlink.h>
22
23#include "utils.h"
24#include "tc_util.h"
25#include "tc_bpf.h"
26
27int bpf_parse_string(char *arg, bool from_file, __u16 *bpf_len,
28 char **bpf_string, bool *need_release,
29 const char separator)
30{
31 char sp;
32
33 if (from_file) {
34 size_t tmp_len, op_len = sizeof("65535 255 255 4294967295,");
35 char *tmp_string;
36 FILE *fp;
37
38 tmp_len = sizeof("4096,") + BPF_MAXINSNS * op_len;
39 tmp_string = malloc(tmp_len);
40 if (tmp_string == NULL)
41 return -ENOMEM;
42
43 memset(tmp_string, 0, tmp_len);
44
45 fp = fopen(arg, "r");
46 if (fp == NULL) {
47 perror("Cannot fopen");
48 free(tmp_string);
49 return -ENOENT;
50 }
51
52 if (!fgets(tmp_string, tmp_len, fp)) {
53 free(tmp_string);
54 fclose(fp);
55 return -EIO;
56 }
57
58 fclose(fp);
59
60 *need_release = true;
61 *bpf_string = tmp_string;
62 } else {
63 *need_release = false;
64 *bpf_string = arg;
65 }
66
67 if (sscanf(*bpf_string, "%hu%c", bpf_len, &sp) != 2 ||
68 sp != separator) {
69 if (*need_release)
70 free(*bpf_string);
71 return -EINVAL;
72 }
73
74 return 0;
75}
76
77int bpf_parse_ops(int argc, char **argv, struct sock_filter *bpf_ops,
78 bool from_file)
79{
80 char *bpf_string, *token, separator = ',';
81 int ret = 0, i = 0;
82 bool need_release;
83 __u16 bpf_len = 0;
84
85 if (argc < 1)
86 return -EINVAL;
87 if (bpf_parse_string(argv[0], from_file, &bpf_len, &bpf_string,
88 &need_release, separator))
89 return -EINVAL;
90 if (bpf_len == 0 || bpf_len > BPF_MAXINSNS) {
91 ret = -EINVAL;
92 goto out;
93 }
94
95 token = bpf_string;
96 while ((token = strchr(token, separator)) && (++token)[0]) {
97 if (i >= bpf_len) {
98 fprintf(stderr, "Real program length exceeds encoded "
99 "length parameter!\n");
100 ret = -EINVAL;
101 goto out;
102 }
103
104 if (sscanf(token, "%hu %hhu %hhu %u,",
105 &bpf_ops[i].code, &bpf_ops[i].jt,
106 &bpf_ops[i].jf, &bpf_ops[i].k) != 4) {
107 fprintf(stderr, "Error at instruction %d!\n", i);
108 ret = -EINVAL;
109 goto out;
110 }
111
112 i++;
113 }
114
115 if (i != bpf_len) {
116 fprintf(stderr, "Parsed program length is less than encoded"
117 "length parameter!\n");
118 ret = -EINVAL;
119 goto out;
120 }
121 ret = bpf_len;
122
123out:
124 if (need_release)
125 free(bpf_string);
126
127 return ret;
128}
129
130void bpf_print_ops(FILE *f, struct rtattr *bpf_ops, __u16 len)
131{
132 struct sock_filter *ops = (struct sock_filter *) RTA_DATA(bpf_ops);
133 int i;
134
135 if (len == 0)
136 return;
137
138 fprintf(f, "bytecode \'%u,", len);
139
140 for (i = 0; i < len - 1; i++)
141 fprintf(f, "%hu %hhu %hhu %u,", ops[i].code, ops[i].jt,
142 ops[i].jf, ops[i].k);
143
144 fprintf(f, "%hu %hhu %hhu %u\'\n", ops[i].code, ops[i].jt,
145 ops[i].jf, ops[i].k);
146}