]> git.proxmox.com Git - mirror_iproute2.git/blob - tc/em_nbyte.c
tc: flower: fix json output with mpls lse
[mirror_iproute2.git] / tc / em_nbyte.c
1 /*
2 * em_nbyte.c N-Byte Ematch
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: Thomas Graf <tgraf@suug.ch>
10 */
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <unistd.h>
15 #include <fcntl.h>
16 #include <sys/socket.h>
17 #include <netinet/in.h>
18 #include <arpa/inet.h>
19 #include <string.h>
20 #include <errno.h>
21
22 #include "m_ematch.h"
23 #include <linux/tc_ematch/tc_em_nbyte.h>
24
25 extern struct ematch_util nbyte_ematch_util;
26
27 static void nbyte_print_usage(FILE *fd)
28 {
29 fprintf(fd,
30 "Usage: nbyte(NEEDLE at OFFSET [layer LAYER])\n" \
31 "where: NEEDLE := { string | \"c-escape-sequence\" }\n" \
32 " OFFSET := int\n" \
33 " LAYER := { link | network | transport | 0..%d }\n" \
34 "\n" \
35 "Example: nbyte(\"ababa\" at 12 layer 1)\n",
36 TCF_LAYER_MAX);
37 }
38
39 static int nbyte_parse_eopt(struct nlmsghdr *n, struct tcf_ematch_hdr *hdr,
40 struct bstr *args)
41 {
42 struct bstr *a;
43 struct bstr *needle = args;
44 unsigned long offset = 0, layer = TCF_LAYER_NETWORK;
45 int offset_present = 0;
46 struct tcf_em_nbyte nb = {};
47
48 #define PARSE_ERR(CARG, FMT, ARGS...) \
49 em_parse_error(EINVAL, args, CARG, &nbyte_ematch_util, FMT, ##ARGS)
50
51 if (args == NULL)
52 return PARSE_ERR(args, "nbyte: missing arguments");
53
54 if (needle->len <= 0)
55 return PARSE_ERR(args, "nbyte: needle length is 0");
56
57 for (a = bstr_next(args); a; a = bstr_next(a)) {
58 if (!bstrcmp(a, "at")) {
59 if (a->next == NULL)
60 return PARSE_ERR(a, "nbyte: missing argument");
61 a = bstr_next(a);
62
63 offset = bstrtoul(a);
64 if (offset == ULONG_MAX)
65 return PARSE_ERR(a, "nbyte: invalid offset, " \
66 "must be numeric");
67
68 offset_present = 1;
69 } else if (!bstrcmp(a, "layer")) {
70 if (a->next == NULL)
71 return PARSE_ERR(a, "nbyte: missing argument");
72 a = bstr_next(a);
73
74 layer = parse_layer(a);
75 if (layer == INT_MAX) {
76 layer = bstrtoul(a);
77 if (layer == ULONG_MAX)
78 return PARSE_ERR(a, "nbyte: invalid " \
79 "layer");
80 }
81
82 if (layer > TCF_LAYER_MAX)
83 return PARSE_ERR(a, "nbyte: illegal layer, " \
84 "must be in 0..%d", TCF_LAYER_MAX);
85 } else
86 return PARSE_ERR(a, "nbyte: unknown parameter");
87 }
88
89 if (offset_present == 0)
90 return PARSE_ERR(a, "nbyte: offset required");
91
92 nb.len = needle->len;
93 nb.layer = (__u8) layer;
94 nb.off = (__u16) offset;
95
96 addraw_l(n, MAX_MSG, hdr, sizeof(*hdr));
97 addraw_l(n, MAX_MSG, &nb, sizeof(nb));
98 addraw_l(n, MAX_MSG, needle->data, needle->len);
99
100 #undef PARSE_ERR
101 return 0;
102 }
103
104 static int nbyte_print_eopt(FILE *fd, struct tcf_ematch_hdr *hdr, void *data,
105 int data_len)
106 {
107 int i;
108 struct tcf_em_nbyte *nb = data;
109 __u8 *needle;
110
111 if (data_len < sizeof(*nb)) {
112 fprintf(stderr, "NByte header size mismatch\n");
113 return -1;
114 }
115
116 if (data_len < sizeof(*nb) + nb->len) {
117 fprintf(stderr, "NByte payload size mismatch\n");
118 return -1;
119 }
120
121 needle = data + sizeof(*nb);
122
123 for (i = 0; i < nb->len; i++)
124 fprintf(fd, "%02x ", needle[i]);
125
126 fprintf(fd, "\"");
127 for (i = 0; i < nb->len; i++)
128 fprintf(fd, "%c", isprint(needle[i]) ? needle[i] : '.');
129 fprintf(fd, "\" at %d layer %d", nb->off, nb->layer);
130
131 return 0;
132 }
133
134 struct ematch_util nbyte_ematch_util = {
135 .kind = "nbyte",
136 .kind_num = TCF_EM_NBYTE,
137 .parse_eopt = nbyte_parse_eopt,
138 .print_eopt = nbyte_print_eopt,
139 .print_usage = nbyte_print_usage
140 };