1dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat/* 2dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * f_flow.c Flow filter 3dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * 4dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * This program is free software; you can redistribute it and/or 5dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * modify it under the terms of the GNU General Public License 6dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * as published by the Free Software Foundation; either version 7dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * 2 of the License, or (at your option) any later version. 8dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * 9dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * Authors: Patrick McHardy <kaber@trash.net> 10dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat */ 11dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <stdio.h> 12dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <stdlib.h> 13dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <unistd.h> 14dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <string.h> 15dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <errno.h> 16dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 17dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include "utils.h" 18dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include "tc_util.h" 19dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include "m_ematch.h" 20dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 21dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic void explain(void) 22dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 23dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, 24dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat"Usage: ... flow ...\n" 25dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat"\n" 26dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat" [mapping mode]: map key KEY [ OPS ] ...\n" 27dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat" [hashing mode]: hash keys KEY-LIST ... [ perturb SECS ]\n" 28dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat"\n" 29dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat" [ divisor NUM ] [ baseclass ID ] [ match EMATCH_TREE ]\n" 30dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat" [ police POLICE_SPEC ] [ action ACTION_SPEC ]\n" 31dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat"\n" 32dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat"KEY-LIST := [ KEY-LIST , ] KEY\n" 33dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat"KEY := [ src | dst | proto | proto-src | proto-dst | iif | priority | \n" 34dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat" mark | nfct | nfct-src | nfct-dst | nfct-proto-src | \n" 35dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat" nfct-proto-dst | rt-classid | sk-uid | sk-gid |\n" 36dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat" vlan-tag ]\n" 37dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat"OPS := [ or NUM | and NUM | xor NUM | rshift NUM | addend NUM ]\n" 38dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat"ID := X:Y\n" 39dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat ); 40dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 41dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 42dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic const char *flow_keys[FLOW_KEY_MAX+1] = { 43dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat [FLOW_KEY_SRC] = "src", 44dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat [FLOW_KEY_DST] = "dst", 45dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat [FLOW_KEY_PROTO] = "proto", 46dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat [FLOW_KEY_PROTO_SRC] = "proto-src", 47dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat [FLOW_KEY_PROTO_DST] = "proto-dst", 48dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat [FLOW_KEY_IIF] = "iif", 49dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat [FLOW_KEY_PRIORITY] = "priority", 50dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat [FLOW_KEY_MARK] = "mark", 51dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat [FLOW_KEY_NFCT] = "nfct", 52dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat [FLOW_KEY_NFCT_SRC] = "nfct-src", 53dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat [FLOW_KEY_NFCT_DST] = "nfct-dst", 54dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat [FLOW_KEY_NFCT_PROTO_SRC] = "nfct-proto-src", 55dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat [FLOW_KEY_NFCT_PROTO_DST] = "nfct-proto-dst", 56dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat [FLOW_KEY_RTCLASSID] = "rt-classid", 57dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat [FLOW_KEY_SKUID] = "sk-uid", 58dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat [FLOW_KEY_SKGID] = "sk-gid", 59dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat [FLOW_KEY_VLAN_TAG] = "vlan-tag", 60dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}; 61dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 62dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic int flow_parse_keys(__u32 *keys, __u32 *nkeys, char *argv) 63dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 64dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat char *s, *sep; 65dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat unsigned int i; 66dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 67dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *keys = 0; 68dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *nkeys = 0; 69dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat s = argv; 70dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat while (s != NULL) { 71dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat sep = strchr(s, ','); 72dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (sep) 73dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *sep = '\0'; 74dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 75dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat for (i = 0; i <= FLOW_KEY_MAX; i++) { 76dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (matches(s, flow_keys[i]) == 0) { 77dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *keys |= 1 << i; 78dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat (*nkeys)++; 79dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat break; 80dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 81dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 82dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (i > FLOW_KEY_MAX) { 83dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "Unknown flow key \"%s\"\n", s); 84dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 85dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 86dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat s = sep ? sep + 1 : NULL; 87dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 88dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return 0; 89dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 90dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 91dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic void transfer_bitop(__u32 *mask, __u32 *xor, __u32 m, __u32 x) 92dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 93dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *xor = x ^ (*xor & m); 94dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *mask &= m; 95dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 96dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 97dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic int get_addend(__u32 *addend, char *argv, __u32 keys) 98dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 99dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat inet_prefix addr; 100dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int sign = 0; 101dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __u32 tmp; 102dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 103dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (*argv == '-') { 104dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat sign = 1; 105dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat argv++; 106dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 107dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 108dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (get_u32(&tmp, argv, 0) == 0) 109dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat goto out; 110dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 111dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (keys & (FLOW_KEY_SRC | FLOW_KEY_DST | 112dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat FLOW_KEY_NFCT_SRC | FLOW_KEY_NFCT_DST) && 113dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat get_addr(&addr, argv, AF_UNSPEC) == 0) { 114dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat switch (addr.family) { 115dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat case AF_INET: 116dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat tmp = ntohl(addr.data[0]); 117dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat goto out; 118dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat case AF_INET6: 119dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat tmp = ntohl(addr.data[3]); 120dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat goto out; 121dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 122dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 123dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 124dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 125dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatout: 126dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (sign) 127dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat tmp = -tmp; 128dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *addend = tmp; 129dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return 0; 130dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 131dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 132dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic int flow_parse_opt(struct filter_util *fu, char *handle, 133dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int argc, char **argv, struct nlmsghdr *n) 134dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 135dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct tc_police tp; 136dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct tcmsg *t = NLMSG_DATA(n); 137dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct rtattr *tail; 138dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __u32 mask = ~0U, xor = 0; 139dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __u32 keys = 0, nkeys = 0; 140dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __u32 mode = FLOW_MODE_MAP; 141dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __u32 tmp; 142dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 143dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat memset(&tp, 0, sizeof(tp)); 144dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 145dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (handle) { 146dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (get_u32(&t->tcm_handle, handle, 0)) { 147dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "Illegal \"handle\"\n"); 148dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 149dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 150dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 151dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 152dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat tail = NLMSG_TAIL(n); 153dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat addattr_l(n, 4096, TCA_OPTIONS, NULL, 0); 154dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 155dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat while (argc > 0) { 156dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (matches(*argv, "map") == 0) { 157dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat mode = FLOW_MODE_MAP; 158dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else if (matches(*argv, "hash") == 0) { 159dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat mode = FLOW_MODE_HASH; 160dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else if (matches(*argv, "keys") == 0) { 161dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat NEXT_ARG(); 162dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (flow_parse_keys(&keys, &nkeys, *argv)) 163dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 164dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat addattr32(n, 4096, TCA_FLOW_KEYS, keys); 165dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else if (matches(*argv, "and") == 0) { 166dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat NEXT_ARG(); 167dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (get_u32(&tmp, *argv, 0)) { 168dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "Illegal \"mask\"\n"); 169dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 170dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 171dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat transfer_bitop(&mask, &xor, tmp, 0); 172dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else if (matches(*argv, "or") == 0) { 173dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat NEXT_ARG(); 174dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (get_u32(&tmp, *argv, 0)) { 175dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "Illegal \"or\"\n"); 176dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 177dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 178dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat transfer_bitop(&mask, &xor, ~tmp, tmp); 179dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else if (matches(*argv, "xor") == 0) { 180dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat NEXT_ARG(); 181dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (get_u32(&tmp, *argv, 0)) { 182dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "Illegal \"xor\"\n"); 183dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 184dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 185dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat transfer_bitop(&mask, &xor, ~0, tmp); 186dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else if (matches(*argv, "rshift") == 0) { 187dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat NEXT_ARG(); 188dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (get_u32(&tmp, *argv, 0)) { 189dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "Illegal \"rshift\"\n"); 190dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 191dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 192dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat addattr32(n, 4096, TCA_FLOW_RSHIFT, tmp); 193dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else if (matches(*argv, "addend") == 0) { 194dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat NEXT_ARG(); 195dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (get_addend(&tmp, *argv, keys)) { 196dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "Illegal \"addend\"\n"); 197dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 198dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 199dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat addattr32(n, 4096, TCA_FLOW_ADDEND, tmp); 200dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else if (matches(*argv, "divisor") == 0) { 201dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat NEXT_ARG(); 202dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (get_u32(&tmp, *argv, 0)) { 203dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "Illegal \"divisor\"\n"); 204dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 205dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 206dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat addattr32(n, 4096, TCA_FLOW_DIVISOR, tmp); 207dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else if (matches(*argv, "baseclass") == 0) { 208dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat NEXT_ARG(); 209dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (get_tc_classid(&tmp, *argv) || TC_H_MIN(tmp) == 0) { 210dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "Illegal \"baseclass\"\n"); 211dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 212dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 213dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat addattr32(n, 4096, TCA_FLOW_BASECLASS, tmp); 214dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else if (matches(*argv, "perturb") == 0) { 215dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat NEXT_ARG(); 216dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (get_u32(&tmp, *argv, 0)) { 217dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "Illegal \"perturb\"\n"); 218dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 219dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 220dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat addattr32(n, 4096, TCA_FLOW_PERTURB, tmp); 221dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else if (matches(*argv, "police") == 0) { 222dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat NEXT_ARG(); 223dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (parse_police(&argc, &argv, TCA_FLOW_POLICE, n)) { 224dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "Illegal \"police\"\n"); 225dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 226dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 227dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat continue; 228dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else if (matches(*argv, "action") == 0) { 229dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat NEXT_ARG(); 230dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (parse_action(&argc, &argv, TCA_FLOW_ACT, n)) { 231dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "Illegal \"action\"\n"); 232dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 233dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 234dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat continue; 235dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else if (matches(*argv, "match") == 0) { 236dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat NEXT_ARG(); 237dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (parse_ematch(&argc, &argv, TCA_FLOW_EMATCHES, n)) { 238dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "Illegal \"ematch\"\n"); 239dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 240dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 241dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat continue; 242dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else if (matches(*argv, "help") == 0) { 243dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat explain(); 244dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 245dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else { 246dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "What is \"%s\"?\n", *argv); 247dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat explain(); 248dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 249dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 250dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat argv++, argc--; 251dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 252dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 253dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (nkeys > 1 && mode != FLOW_MODE_HASH) { 254dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "Invalid mode \"map\" for multiple keys\n"); 255dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 256dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 257dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat addattr32(n, 4096, TCA_FLOW_MODE, mode); 258dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 259dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (mask != ~0 || xor != 0) { 260dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat addattr32(n, 4096, TCA_FLOW_MASK, mask); 261dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat addattr32(n, 4096, TCA_FLOW_XOR, xor); 262dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 263dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 264dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat tail->rta_len = (void *)NLMSG_TAIL(n) - (void *)tail; 265dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return 0; 266dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 267dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 268dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic int flow_print_opt(struct filter_util *fu, FILE *f, struct rtattr *opt, 269dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __u32 handle) 270dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 271dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct rtattr *tb[TCA_FLOW_MAX+1]; 272dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat SPRINT_BUF(b1); 273dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat unsigned int i; 274dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __u32 mask = ~0, val = 0; 275dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 276dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (opt == NULL) 277dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -EINVAL; 278dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 279dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat parse_rtattr_nested(tb, TCA_FLOW_MAX, opt); 280dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 281dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(f, "handle 0x%x ", handle); 282dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 283dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (tb[TCA_FLOW_MODE]) { 284dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __u32 mode = *(__u32 *)RTA_DATA(tb[TCA_FLOW_MODE]); 285dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 286dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat switch (mode) { 287dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat case FLOW_MODE_MAP: 288dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(f, "map "); 289dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat break; 290dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat case FLOW_MODE_HASH: 291dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(f, "hash "); 292dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat break; 293dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 294dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 295dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 296dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (tb[TCA_FLOW_KEYS]) { 297dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __u32 keymask = *(__u32 *)RTA_DATA(tb[TCA_FLOW_KEYS]); 298dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat char *sep = ""; 299dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 300dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(f, "keys "); 301dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat for (i = 0; i <= FLOW_KEY_MAX; i++) { 302dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (keymask & (1 << i)) { 303dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(f, "%s%s", sep, flow_keys[i]); 304dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat sep = ","; 305dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 306dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 307dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(f, " "); 308dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 309dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 310dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (tb[TCA_FLOW_MASK]) 311dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat mask = *(__u32 *)RTA_DATA(tb[TCA_FLOW_MASK]); 312dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (tb[TCA_FLOW_XOR]) 313dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat val = *(__u32 *)RTA_DATA(tb[TCA_FLOW_XOR]); 314dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 315dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (mask != ~0 || val != 0) { 316dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __u32 or = (mask & val) ^ val; 317dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __u32 xor = mask & val; 318dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 319dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (mask != ~0) 320dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(f, "and 0x%.8x ", mask); 321dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (xor != 0) 322dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(f, "xor 0x%.8x ", xor); 323dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (or != 0) 324dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(f, "or 0x%.8x ", or); 325dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 326dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 327dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (tb[TCA_FLOW_RSHIFT]) 328dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(f, "rshift %u ", 329dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *(__u32 *)RTA_DATA(tb[TCA_FLOW_RSHIFT])); 330dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (tb[TCA_FLOW_ADDEND]) 331dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(f, "addend 0x%x ", 332dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *(__u32 *)RTA_DATA(tb[TCA_FLOW_ADDEND])); 333dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 334dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (tb[TCA_FLOW_DIVISOR]) 335dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(f, "divisor %u ", 336dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *(__u32 *)RTA_DATA(tb[TCA_FLOW_DIVISOR])); 337dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (tb[TCA_FLOW_BASECLASS]) 338dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(f, "baseclass %s ", 339dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat sprint_tc_classid(*(__u32 *)RTA_DATA(tb[TCA_FLOW_BASECLASS]), b1)); 340dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 341dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (tb[TCA_FLOW_PERTURB]) 342dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(f, "perturb %usec ", 343dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *(__u32 *)RTA_DATA(tb[TCA_FLOW_PERTURB])); 344dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 345dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (tb[TCA_FLOW_EMATCHES]) 346dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat print_ematch(f, tb[TCA_FLOW_EMATCHES]); 347dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (tb[TCA_FLOW_POLICE]) 348dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat tc_print_police(f, tb[TCA_FLOW_POLICE]); 349dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (tb[TCA_FLOW_ACT]) { 350dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(f, "\n"); 351dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat tc_print_action(f, tb[TCA_FLOW_ACT]); 352dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 353dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return 0; 354dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 355dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 356dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstruct filter_util flow_filter_util = { 357dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat .id = "flow", 358dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat .parse_fopt = flow_parse_opt, 359dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat .print_fopt = flow_print_opt, 360dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}; 361