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>
17 #include <sys/socket.h>
18 #include <netinet/in.h>
19 #include <arpa/inet.h>
26 extern struct ematch_util u32_ematch_util;
28 static void u32_print_usage(FILE *fd)
31 "Usage: u32(ALIGN VALUE MASK at [ nexthdr+ ] OFFSET)\n" \
32 "where: ALIGN := { u8 | u16 | u32 }\n" \
34 "Example: u32(u16 0x1122 0xffff at nexthdr+4)\n");
37 static int u32_parse_eopt(struct nlmsghdr *n, struct tcf_ematch_hdr *hdr,
42 unsigned long key, mask, offmask = 0, offset;
43 struct tc_u32_key u_key;
45 memset(&u_key, 0, sizeof(u_key));
47 #define PARSE_ERR(CARG, FMT, ARGS...) \
48 em_parse_error(EINVAL, args, CARG, &u32_ematch_util, FMT ,##ARGS)
51 return PARSE_ERR(args, "u32: missing arguments");
53 if (!bstrcmp(args, "u8"))
55 else if (!bstrcmp(args, "u16"))
57 else if (!bstrcmp(args, "u32"))
60 return PARSE_ERR(args, "u32: invalid alignment");
64 return PARSE_ERR(a, "u32: missing key");
68 return PARSE_ERR(a, "u32: invalid key, must be numeric");
72 return PARSE_ERR(a, "u32: missing mask");
75 if (mask == ULONG_MAX)
76 return PARSE_ERR(a, "u32: invalid mask, must be numeric");
79 if (a == NULL || bstrcmp(a, "at") != 0)
80 return PARSE_ERR(a, "u32: missing \"at\"");
84 return PARSE_ERR(a, "u32: missing offset");
86 nh_len = strlen("nexthdr+");
87 if (a->len > nh_len && !memcmp(a->data, "nexthdr+", nh_len)) {
88 char buf[a->len - nh_len + 1];
90 memcpy(buf, a->data + nh_len, a->len - nh_len);
91 offset = strtoul(buf, NULL, 0);
92 } else if (!bstrcmp(a, "nexthdr+")) {
95 return PARSE_ERR(a, "u32: missing offset");
100 if (offset == ULONG_MAX)
101 return PARSE_ERR(a, "u32: invalid offset");
104 return PARSE_ERR(a->next, "u32: unexpected trailer");
109 return PARSE_ERR(a, "Illegal key (>0xFF)");
111 return PARSE_ERR(a, "Illegal mask (>0xFF)");
113 key <<= 24 - ((offset & 3) * 8);
114 mask <<= 24 - ((offset & 3) * 8);
120 return PARSE_ERR(a, "Illegal key (>0xFFFF)");
122 return PARSE_ERR(a, "Illegal mask (>0xFFFF)");
124 if ((offset & 3) == 0) {
136 return PARSE_ERR(a, "u32: invalid offset alignment, " \
137 "must be aligned to 4.");
144 u_key.offmask = offmask;
146 addraw_l(n, MAX_MSG, hdr, sizeof(*hdr));
147 addraw_l(n, MAX_MSG, &u_key, sizeof(u_key));
153 static int u32_print_eopt(FILE *fd, struct tcf_ematch_hdr *hdr, void *data,
156 struct tc_u32_key *u_key = data;
158 if (data_len < sizeof(*u_key)) {
159 fprintf(stderr, "U32 header size mismatch\n");
163 fprintf(fd, "%08x/%08x at %s%d",
164 (unsigned int) ntohl(u_key->val),
165 (unsigned int) ntohl(u_key->mask),
166 u_key->offmask ? "nexthdr+" : "",
172 struct ematch_util u32_ematch_util = {
174 .kind_num = TCF_EM_U32,
175 .parse_eopt = u32_parse_eopt,
176 .print_eopt = u32_print_eopt,
177 .print_usage = u32_print_usage