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