2 * em_nbyte.c N-Byte Ematch
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.
9 * Authors: Thomas Graf <tgraf@suug.ch>
16 #include <sys/socket.h>
17 #include <netinet/in.h>
18 #include <arpa/inet.h>
23 #include <linux/tc_ematch/tc_em_nbyte.h>
25 extern struct ematch_util nbyte_ematch_util
;
27 static void nbyte_print_usage(FILE *fd
)
30 "Usage: nbyte(NEEDLE at OFFSET [layer LAYER])\n" \
31 "where: NEEDLE := { string | \"c-escape-sequence\" }\n" \
33 " LAYER := { link | network | transport | 0..%d }\n" \
35 "Example: nbyte(\"ababa\" at 12 layer 1)\n",
39 static int nbyte_parse_eopt(struct nlmsghdr
*n
, struct tcf_ematch_hdr
*hdr
,
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
= {};
48 #define PARSE_ERR(CARG, FMT, ARGS...) \
49 em_parse_error(EINVAL, args, CARG, &nbyte_ematch_util, FMT, ##ARGS)
52 return PARSE_ERR(args
, "nbyte: missing arguments");
55 return PARSE_ERR(args
, "nbyte: needle length is 0");
57 for (a
= bstr_next(args
); a
; a
= bstr_next(a
)) {
58 if (!bstrcmp(a
, "at")) {
60 return PARSE_ERR(a
, "nbyte: missing argument");
64 if (offset
== ULONG_MAX
)
65 return PARSE_ERR(a
, "nbyte: invalid offset, " \
69 } else if (!bstrcmp(a
, "layer")) {
71 return PARSE_ERR(a
, "nbyte: missing argument");
74 layer
= parse_layer(a
);
75 if (layer
== INT_MAX
) {
77 if (layer
== ULONG_MAX
)
78 return PARSE_ERR(a
, "nbyte: invalid " \
82 if (layer
> TCF_LAYER_MAX
)
83 return PARSE_ERR(a
, "nbyte: illegal layer, " \
84 "must be in 0..%d", TCF_LAYER_MAX
);
86 return PARSE_ERR(a
, "nbyte: unknown parameter");
89 if (offset_present
== 0)
90 return PARSE_ERR(a
, "nbyte: offset required");
93 nb
.layer
= (__u8
) layer
;
94 nb
.off
= (__u16
) offset
;
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
);
104 static int nbyte_print_eopt(FILE *fd
, struct tcf_ematch_hdr
*hdr
, void *data
,
108 struct tcf_em_nbyte
*nb
= data
;
111 if (data_len
< sizeof(*nb
)) {
112 fprintf(stderr
, "NByte header size mismatch\n");
116 if (data_len
< sizeof(*nb
) + nb
->len
) {
117 fprintf(stderr
, "NByte payload size mismatch\n");
121 needle
= data
+ sizeof(*nb
);
123 for (i
= 0; i
< nb
->len
; i
++)
124 fprintf(fd
, "%02x ", needle
[i
]);
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
);
134 struct ematch_util nbyte_ematch_util
= {
136 .kind_num
= TCF_EM_NBYTE
,
137 .parse_eopt
= nbyte_parse_eopt
,
138 .print_eopt
= nbyte_print_eopt
,
139 .print_usage
= nbyte_print_usage