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>
24 extern struct ematch_util u32_ematch_util
;
26 static void u32_print_usage(FILE *fd
)
29 "Usage: u32(ALIGN VALUE MASK at [ nexthdr+ ] OFFSET)\n" \
30 "where: ALIGN := { u8 | u16 | u32 }\n" \
32 "Example: u32(u16 0x1122 0xffff at nexthdr+4)\n");
35 static int u32_parse_eopt(struct nlmsghdr
*n
, struct tcf_ematch_hdr
*hdr
,
40 unsigned long key
, mask
, offmask
= 0, offset
;
41 struct tc_u32_key u_key
= {};
43 #define PARSE_ERR(CARG, FMT, ARGS...) \
44 em_parse_error(EINVAL, args, CARG, &u32_ematch_util, FMT, ##ARGS)
47 return PARSE_ERR(args
, "u32: missing arguments");
49 if (!bstrcmp(args
, "u8"))
51 else if (!bstrcmp(args
, "u16"))
53 else if (!bstrcmp(args
, "u32"))
56 return PARSE_ERR(args
, "u32: invalid alignment");
60 return PARSE_ERR(a
, "u32: missing key");
64 return PARSE_ERR(a
, "u32: invalid key, must be numeric");
68 return PARSE_ERR(a
, "u32: missing mask");
71 if (mask
== ULONG_MAX
)
72 return PARSE_ERR(a
, "u32: invalid mask, must be numeric");
75 if (a
== NULL
|| bstrcmp(a
, "at") != 0)
76 return PARSE_ERR(a
, "u32: missing \"at\"");
80 return PARSE_ERR(a
, "u32: missing offset");
82 nh_len
= strlen("nexthdr+");
83 if (a
->len
> nh_len
&& !memcmp(a
->data
, "nexthdr+", nh_len
)) {
84 char buf
[a
->len
- nh_len
+ 1];
87 memcpy(buf
, a
->data
+ nh_len
, a
->len
- nh_len
);
88 offset
= strtoul(buf
, NULL
, 0);
89 } else if (!bstrcmp(a
, "nexthdr+")) {
92 return PARSE_ERR(a
, "u32: missing offset");
97 if (offset
== ULONG_MAX
)
98 return PARSE_ERR(a
, "u32: invalid offset");
101 return PARSE_ERR(a
->next
, "u32: unexpected trailer");
106 return PARSE_ERR(a
, "Illegal key (>0xFF)");
108 return PARSE_ERR(a
, "Illegal mask (>0xFF)");
110 key
<<= 24 - ((offset
& 3) * 8);
111 mask
<<= 24 - ((offset
& 3) * 8);
117 return PARSE_ERR(a
, "Illegal key (>0xFFFF)");
119 return PARSE_ERR(a
, "Illegal mask (>0xFFFF)");
121 if ((offset
& 3) == 0) {
133 return PARSE_ERR(a
, "u32: invalid offset alignment, " \
134 "must be aligned to 4.");
141 u_key
.offmask
= offmask
;
143 addraw_l(n
, MAX_MSG
, hdr
, sizeof(*hdr
));
144 addraw_l(n
, MAX_MSG
, &u_key
, sizeof(u_key
));
150 static int u32_print_eopt(FILE *fd
, struct tcf_ematch_hdr
*hdr
, void *data
,
153 struct tc_u32_key
*u_key
= data
;
155 if (data_len
< sizeof(*u_key
)) {
156 fprintf(stderr
, "U32 header size mismatch\n");
160 fprintf(fd
, "%08x/%08x at %s%d",
161 (unsigned int) ntohl(u_key
->val
),
162 (unsigned int) ntohl(u_key
->mask
),
163 u_key
->offmask
? "nexthdr+" : "",
169 struct ematch_util u32_ematch_util
= {
171 .kind_num
= TCF_EM_U32
,
172 .parse_eopt
= u32_parse_eopt
,
173 .print_eopt
= u32_print_eopt
,
174 .print_usage
= u32_print_usage