1311b41454dc445639924c691a949bd15fbfab0cbshemminger/* 2311b41454dc445639924c691a949bd15fbfab0cbshemminger * em_meta.c Metadata Ematch 3311b41454dc445639924c691a949bd15fbfab0cbshemminger * 4311b41454dc445639924c691a949bd15fbfab0cbshemminger * This program is free software; you can distribute it and/or 5311b41454dc445639924c691a949bd15fbfab0cbshemminger * modify it under the terms of the GNU General Public License 6311b41454dc445639924c691a949bd15fbfab0cbshemminger * as published by the Free Software Foundation; either version 7311b41454dc445639924c691a949bd15fbfab0cbshemminger * 2 of the License, or (at your option) any later version. 8311b41454dc445639924c691a949bd15fbfab0cbshemminger * 9311b41454dc445639924c691a949bd15fbfab0cbshemminger * Authors: Thomas Graf <tgraf@suug.ch> 10311b41454dc445639924c691a949bd15fbfab0cbshemminger */ 11311b41454dc445639924c691a949bd15fbfab0cbshemminger 12311b41454dc445639924c691a949bd15fbfab0cbshemminger#include <stdio.h> 13311b41454dc445639924c691a949bd15fbfab0cbshemminger#include <stdlib.h> 14311b41454dc445639924c691a949bd15fbfab0cbshemminger#include <unistd.h> 15311b41454dc445639924c691a949bd15fbfab0cbshemminger#include <syslog.h> 16311b41454dc445639924c691a949bd15fbfab0cbshemminger#include <fcntl.h> 17311b41454dc445639924c691a949bd15fbfab0cbshemminger#include <sys/socket.h> 18311b41454dc445639924c691a949bd15fbfab0cbshemminger#include <netinet/in.h> 19311b41454dc445639924c691a949bd15fbfab0cbshemminger#include <arpa/inet.h> 20311b41454dc445639924c691a949bd15fbfab0cbshemminger#include <string.h> 21311b41454dc445639924c691a949bd15fbfab0cbshemminger#include <errno.h> 22311b41454dc445639924c691a949bd15fbfab0cbshemminger 23311b41454dc445639924c691a949bd15fbfab0cbshemminger#include "m_ematch.h" 24311b41454dc445639924c691a949bd15fbfab0cbshemminger#include <linux/tc_ematch/tc_em_meta.h> 25311b41454dc445639924c691a949bd15fbfab0cbshemminger 26311b41454dc445639924c691a949bd15fbfab0cbshemmingerextern struct ematch_util meta_ematch_util; 27311b41454dc445639924c691a949bd15fbfab0cbshemminger 28311b41454dc445639924c691a949bd15fbfab0cbshemmingerstatic void meta_print_usage(FILE *fd) 29311b41454dc445639924c691a949bd15fbfab0cbshemminger{ 30311b41454dc445639924c691a949bd15fbfab0cbshemminger fprintf(fd, 31311b41454dc445639924c691a949bd15fbfab0cbshemminger "Usage: meta(OBJECT { eq | lt | gt } OBJECT)\n" \ 32311b41454dc445639924c691a949bd15fbfab0cbshemminger "where: OBJECT := { META_ID | VALUE }\n" \ 33311b41454dc445639924c691a949bd15fbfab0cbshemminger " META_ID := id [ shift SHIFT ] [ mask MASK ]\n" \ 34311b41454dc445639924c691a949bd15fbfab0cbshemminger "\n" \ 35311b41454dc445639924c691a949bd15fbfab0cbshemminger "Example: meta(nfmark gt 24)\n" \ 36ba26a6e853aeadc609238bf2f6258249fb2f47ceStephen Hemminger " meta(indev shift 1 eq \"ppp\")\n" \ 37311b41454dc445639924c691a949bd15fbfab0cbshemminger " meta(tcindex mask 0xf0 eq 0xf0)\n" \ 38311b41454dc445639924c691a949bd15fbfab0cbshemminger "\n" \ 39311b41454dc445639924c691a949bd15fbfab0cbshemminger "For a list of meta identifiers, use meta(list).\n"); 40311b41454dc445639924c691a949bd15fbfab0cbshemminger} 41311b41454dc445639924c691a949bd15fbfab0cbshemminger 42311b41454dc445639924c691a949bd15fbfab0cbshemmingerstruct meta_entry { 43311b41454dc445639924c691a949bd15fbfab0cbshemminger int id; 44311b41454dc445639924c691a949bd15fbfab0cbshemminger char * kind; 45311b41454dc445639924c691a949bd15fbfab0cbshemminger char * mask; 46311b41454dc445639924c691a949bd15fbfab0cbshemminger char * desc; 47311b41454dc445639924c691a949bd15fbfab0cbshemminger} meta_table[] = { 48311b41454dc445639924c691a949bd15fbfab0cbshemminger#define TCF_META_ID_SECTION 0 49311b41454dc445639924c691a949bd15fbfab0cbshemminger#define __A(id, name, mask, desc) { TCF_META_ID_##id, name, mask, desc } 50311b41454dc445639924c691a949bd15fbfab0cbshemminger __A(SECTION, "Generic", "", ""), 51311b41454dc445639924c691a949bd15fbfab0cbshemminger __A(RANDOM, "random", "i", 52311b41454dc445639924c691a949bd15fbfab0cbshemminger "Random value (32 bit)"), 53311b41454dc445639924c691a949bd15fbfab0cbshemminger __A(LOADAVG_0, "loadavg_1", "i", 54311b41454dc445639924c691a949bd15fbfab0cbshemminger "Load average in last minute"), 55311b41454dc445639924c691a949bd15fbfab0cbshemminger __A(LOADAVG_1, "loadavg_5", "i", 56311b41454dc445639924c691a949bd15fbfab0cbshemminger "Load average in last 5 minutes"), 57311b41454dc445639924c691a949bd15fbfab0cbshemminger __A(LOADAVG_2, "loadavg_15", "i", 58311b41454dc445639924c691a949bd15fbfab0cbshemminger "Load average in last 15 minutes"), 59311b41454dc445639924c691a949bd15fbfab0cbshemminger 60311b41454dc445639924c691a949bd15fbfab0cbshemminger __A(SECTION, "Interfaces", "", ""), 61311b41454dc445639924c691a949bd15fbfab0cbshemminger __A(DEV, "dev", "iv", 62311b41454dc445639924c691a949bd15fbfab0cbshemminger "Device the packet is on"), 63311b41454dc445639924c691a949bd15fbfab0cbshemminger __A(SECTION, "Packet attributes", "", ""), 64311b41454dc445639924c691a949bd15fbfab0cbshemminger __A(PRIORITY, "priority", "i", 65311b41454dc445639924c691a949bd15fbfab0cbshemminger "Priority of packet"), 66311b41454dc445639924c691a949bd15fbfab0cbshemminger __A(PROTOCOL, "protocol", "i", 67311b41454dc445639924c691a949bd15fbfab0cbshemminger "Link layer protocol"), 68311b41454dc445639924c691a949bd15fbfab0cbshemminger __A(PKTTYPE, "pkt_type", "i", 69311b41454dc445639924c691a949bd15fbfab0cbshemminger "Packet type (uni|multi|broad|...)cast"), 70311b41454dc445639924c691a949bd15fbfab0cbshemminger __A(PKTLEN, "pkt_len", "i", 71311b41454dc445639924c691a949bd15fbfab0cbshemminger "Length of packet"), 72311b41454dc445639924c691a949bd15fbfab0cbshemminger __A(DATALEN, "data_len", "i", 73311b41454dc445639924c691a949bd15fbfab0cbshemminger "Length of data in packet"), 74311b41454dc445639924c691a949bd15fbfab0cbshemminger __A(MACLEN, "mac_len", "i", 75311b41454dc445639924c691a949bd15fbfab0cbshemminger "Length of link layer header"), 76311b41454dc445639924c691a949bd15fbfab0cbshemminger 77311b41454dc445639924c691a949bd15fbfab0cbshemminger __A(SECTION, "Netfilter", "", ""), 78311b41454dc445639924c691a949bd15fbfab0cbshemminger __A(NFMARK, "nf_mark", "i", 79311b41454dc445639924c691a949bd15fbfab0cbshemminger "Netfilter mark"), 80311b41454dc445639924c691a949bd15fbfab0cbshemminger __A(NFMARK, "fwmark", "i", 81311b41454dc445639924c691a949bd15fbfab0cbshemminger "Alias for nf_mark"), 82311b41454dc445639924c691a949bd15fbfab0cbshemminger 83311b41454dc445639924c691a949bd15fbfab0cbshemminger __A(SECTION, "Traffic Control", "", ""), 84311b41454dc445639924c691a949bd15fbfab0cbshemminger __A(TCINDEX, "tc_index", "i", "TC Index"), 85311b41454dc445639924c691a949bd15fbfab0cbshemminger __A(SECTION, "Routing", "", ""), 86311b41454dc445639924c691a949bd15fbfab0cbshemminger __A(RTCLASSID, "rt_classid", "i", 87311b41454dc445639924c691a949bd15fbfab0cbshemminger "Routing ClassID (cls_route)"), 88311b41454dc445639924c691a949bd15fbfab0cbshemminger __A(RTIIF, "rt_iif", "i", 89311b41454dc445639924c691a949bd15fbfab0cbshemminger "Incoming interface index"), 905e76a87d4c87d15467a13268bac7380ee7acc9b7Stephen Hemminger __A(VLAN_TAG, "vlan", "i", "Vlan tag"), 91311b41454dc445639924c691a949bd15fbfab0cbshemminger 92311b41454dc445639924c691a949bd15fbfab0cbshemminger __A(SECTION, "Sockets", "", ""), 93311b41454dc445639924c691a949bd15fbfab0cbshemminger __A(SK_FAMILY, "sk_family", "i", "Address family"), 94311b41454dc445639924c691a949bd15fbfab0cbshemminger __A(SK_STATE, "sk_state", "i", "State"), 95311b41454dc445639924c691a949bd15fbfab0cbshemminger __A(SK_REUSE, "sk_reuse", "i", "Reuse Flag"), 96311b41454dc445639924c691a949bd15fbfab0cbshemminger __A(SK_BOUND_IF, "sk_bind_if", "iv", "Bound interface"), 97311b41454dc445639924c691a949bd15fbfab0cbshemminger __A(SK_REFCNT, "sk_refcnt", "i", "Reference counter"), 98311b41454dc445639924c691a949bd15fbfab0cbshemminger __A(SK_SHUTDOWN, "sk_shutdown", "i", "Shutdown mask"), 99311b41454dc445639924c691a949bd15fbfab0cbshemminger __A(SK_PROTO, "sk_proto", "i", "Protocol"), 100311b41454dc445639924c691a949bd15fbfab0cbshemminger __A(SK_TYPE, "sk_type", "i", "Type"), 101311b41454dc445639924c691a949bd15fbfab0cbshemminger __A(SK_RCVBUF, "sk_rcvbuf", "i", "Receive buffer size"), 102311b41454dc445639924c691a949bd15fbfab0cbshemminger __A(SK_RMEM_ALLOC, "sk_rmem", "i", "RMEM"), 103311b41454dc445639924c691a949bd15fbfab0cbshemminger __A(SK_WMEM_ALLOC, "sk_wmem", "i", "WMEM"), 104311b41454dc445639924c691a949bd15fbfab0cbshemminger __A(SK_OMEM_ALLOC, "sk_omem", "i", "OMEM"), 105311b41454dc445639924c691a949bd15fbfab0cbshemminger __A(SK_WMEM_QUEUED, "sk_wmem_queue","i", "WMEM queue"), 106311b41454dc445639924c691a949bd15fbfab0cbshemminger __A(SK_SND_QLEN, "sk_snd_queue", "i", "Send queue length"), 107311b41454dc445639924c691a949bd15fbfab0cbshemminger __A(SK_RCV_QLEN, "sk_rcv_queue", "i", "Receive queue length"), 108311b41454dc445639924c691a949bd15fbfab0cbshemminger __A(SK_ERR_QLEN, "sk_err_queue", "i", "Error queue length"), 109311b41454dc445639924c691a949bd15fbfab0cbshemminger __A(SK_FORWARD_ALLOCS, "sk_fwd_alloc", "i", "Forward allocations"), 110311b41454dc445639924c691a949bd15fbfab0cbshemminger __A(SK_SNDBUF, "sk_sndbuf", "i", "Send buffer size"), 111311b41454dc445639924c691a949bd15fbfab0cbshemminger#undef __A 112311b41454dc445639924c691a949bd15fbfab0cbshemminger}; 113311b41454dc445639924c691a949bd15fbfab0cbshemminger 114311b41454dc445639924c691a949bd15fbfab0cbshemmingerstatic inline int map_type(char k) 115311b41454dc445639924c691a949bd15fbfab0cbshemminger{ 116311b41454dc445639924c691a949bd15fbfab0cbshemminger switch (k) { 117311b41454dc445639924c691a949bd15fbfab0cbshemminger case 'i': return TCF_META_TYPE_INT; 118311b41454dc445639924c691a949bd15fbfab0cbshemminger case 'v': return TCF_META_TYPE_VAR; 119311b41454dc445639924c691a949bd15fbfab0cbshemminger } 120311b41454dc445639924c691a949bd15fbfab0cbshemminger 121311b41454dc445639924c691a949bd15fbfab0cbshemminger fprintf(stderr, "BUG: Unknown map character '%c'\n", k); 122311b41454dc445639924c691a949bd15fbfab0cbshemminger return INT_MAX; 123311b41454dc445639924c691a949bd15fbfab0cbshemminger} 124311b41454dc445639924c691a949bd15fbfab0cbshemminger 125311b41454dc445639924c691a949bd15fbfab0cbshemmingerstatic struct meta_entry * lookup_meta_entry(struct bstr *kind) 126311b41454dc445639924c691a949bd15fbfab0cbshemminger{ 127311b41454dc445639924c691a949bd15fbfab0cbshemminger int i; 128311b41454dc445639924c691a949bd15fbfab0cbshemminger 129311b41454dc445639924c691a949bd15fbfab0cbshemminger for (i = 0; i < (sizeof(meta_table)/sizeof(meta_table[0])); i++) 130311b41454dc445639924c691a949bd15fbfab0cbshemminger if (!bstrcmp(kind, meta_table[i].kind) && 131311b41454dc445639924c691a949bd15fbfab0cbshemminger meta_table[i].id != 0) 132311b41454dc445639924c691a949bd15fbfab0cbshemminger return &meta_table[i]; 133ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger 134311b41454dc445639924c691a949bd15fbfab0cbshemminger return NULL; 135311b41454dc445639924c691a949bd15fbfab0cbshemminger} 136311b41454dc445639924c691a949bd15fbfab0cbshemminger 137311b41454dc445639924c691a949bd15fbfab0cbshemmingerstatic struct meta_entry * lookup_meta_entry_byid(int id) 138311b41454dc445639924c691a949bd15fbfab0cbshemminger{ 139311b41454dc445639924c691a949bd15fbfab0cbshemminger int i; 140311b41454dc445639924c691a949bd15fbfab0cbshemminger 141311b41454dc445639924c691a949bd15fbfab0cbshemminger for (i = 0; i < (sizeof(meta_table)/sizeof(meta_table[0])); i++) 142311b41454dc445639924c691a949bd15fbfab0cbshemminger if (meta_table[i].id == id) 143311b41454dc445639924c691a949bd15fbfab0cbshemminger return &meta_table[i]; 144ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger 145311b41454dc445639924c691a949bd15fbfab0cbshemminger return NULL; 146311b41454dc445639924c691a949bd15fbfab0cbshemminger} 147311b41454dc445639924c691a949bd15fbfab0cbshemminger 148311b41454dc445639924c691a949bd15fbfab0cbshemmingerstatic inline void dump_value(struct nlmsghdr *n, int tlv, unsigned long val, 149311b41454dc445639924c691a949bd15fbfab0cbshemminger struct tcf_meta_val *hdr) 150311b41454dc445639924c691a949bd15fbfab0cbshemminger{ 151311b41454dc445639924c691a949bd15fbfab0cbshemminger __u32 t; 152311b41454dc445639924c691a949bd15fbfab0cbshemminger 153311b41454dc445639924c691a949bd15fbfab0cbshemminger switch (TCF_META_TYPE(hdr->kind)) { 154311b41454dc445639924c691a949bd15fbfab0cbshemminger case TCF_META_TYPE_INT: 155311b41454dc445639924c691a949bd15fbfab0cbshemminger t = val; 156311b41454dc445639924c691a949bd15fbfab0cbshemminger addattr_l(n, MAX_MSG, tlv, &t, sizeof(t)); 157311b41454dc445639924c691a949bd15fbfab0cbshemminger break; 158311b41454dc445639924c691a949bd15fbfab0cbshemminger 159311b41454dc445639924c691a949bd15fbfab0cbshemminger case TCF_META_TYPE_VAR: 160311b41454dc445639924c691a949bd15fbfab0cbshemminger if (TCF_META_ID(hdr->kind) == TCF_META_ID_VALUE) { 161311b41454dc445639924c691a949bd15fbfab0cbshemminger struct bstr *a = (struct bstr *) val; 162311b41454dc445639924c691a949bd15fbfab0cbshemminger addattr_l(n, MAX_MSG, tlv, a->data, a->len); 163311b41454dc445639924c691a949bd15fbfab0cbshemminger } 164311b41454dc445639924c691a949bd15fbfab0cbshemminger break; 165311b41454dc445639924c691a949bd15fbfab0cbshemminger } 166311b41454dc445639924c691a949bd15fbfab0cbshemminger} 167311b41454dc445639924c691a949bd15fbfab0cbshemminger 168311b41454dc445639924c691a949bd15fbfab0cbshemmingerstatic inline int is_compatible(struct tcf_meta_val *what, 169311b41454dc445639924c691a949bd15fbfab0cbshemminger struct tcf_meta_val *needed) 170311b41454dc445639924c691a949bd15fbfab0cbshemminger{ 171311b41454dc445639924c691a949bd15fbfab0cbshemminger char *p; 172311b41454dc445639924c691a949bd15fbfab0cbshemminger struct meta_entry *entry; 173ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger 174311b41454dc445639924c691a949bd15fbfab0cbshemminger entry = lookup_meta_entry_byid(TCF_META_ID(what->kind)); 175311b41454dc445639924c691a949bd15fbfab0cbshemminger 176311b41454dc445639924c691a949bd15fbfab0cbshemminger if (entry == NULL) 177311b41454dc445639924c691a949bd15fbfab0cbshemminger return 0; 178ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger 179311b41454dc445639924c691a949bd15fbfab0cbshemminger for (p = entry->mask; p; p++) 180311b41454dc445639924c691a949bd15fbfab0cbshemminger if (map_type(*p) == TCF_META_TYPE(needed->kind)) 181311b41454dc445639924c691a949bd15fbfab0cbshemminger return 1; 182311b41454dc445639924c691a949bd15fbfab0cbshemminger 183311b41454dc445639924c691a949bd15fbfab0cbshemminger return 0; 184311b41454dc445639924c691a949bd15fbfab0cbshemminger} 185311b41454dc445639924c691a949bd15fbfab0cbshemminger 186311b41454dc445639924c691a949bd15fbfab0cbshemmingerstatic void list_meta_ids(FILE *fd) 187311b41454dc445639924c691a949bd15fbfab0cbshemminger{ 188311b41454dc445639924c691a949bd15fbfab0cbshemminger int i; 189311b41454dc445639924c691a949bd15fbfab0cbshemminger 190311b41454dc445639924c691a949bd15fbfab0cbshemminger fprintf(fd, 191311b41454dc445639924c691a949bd15fbfab0cbshemminger "--------------------------------------------------------\n" \ 192311b41454dc445639924c691a949bd15fbfab0cbshemminger " ID Type Description\n" \ 193311b41454dc445639924c691a949bd15fbfab0cbshemminger "--------------------------------------------------------"); 194311b41454dc445639924c691a949bd15fbfab0cbshemminger 195311b41454dc445639924c691a949bd15fbfab0cbshemminger for (i = 0; i < (sizeof(meta_table)/sizeof(meta_table[0])); i++) { 196311b41454dc445639924c691a949bd15fbfab0cbshemminger if (meta_table[i].id == TCF_META_ID_SECTION) { 197311b41454dc445639924c691a949bd15fbfab0cbshemminger fprintf(fd, "\n%s:\n", meta_table[i].kind); 198311b41454dc445639924c691a949bd15fbfab0cbshemminger } else { 199311b41454dc445639924c691a949bd15fbfab0cbshemminger char *p = meta_table[i].mask; 200311b41454dc445639924c691a949bd15fbfab0cbshemminger char buf[64] = {0}; 201311b41454dc445639924c691a949bd15fbfab0cbshemminger 202311b41454dc445639924c691a949bd15fbfab0cbshemminger fprintf(fd, " %-16s ", meta_table[i].kind); 203311b41454dc445639924c691a949bd15fbfab0cbshemminger 204311b41454dc445639924c691a949bd15fbfab0cbshemminger while (*p) { 205311b41454dc445639924c691a949bd15fbfab0cbshemminger int type = map_type(*p); 206311b41454dc445639924c691a949bd15fbfab0cbshemminger 207311b41454dc445639924c691a949bd15fbfab0cbshemminger switch (type) { 208311b41454dc445639924c691a949bd15fbfab0cbshemminger case TCF_META_TYPE_INT: 209311b41454dc445639924c691a949bd15fbfab0cbshemminger strcat(buf, "INT"); 210311b41454dc445639924c691a949bd15fbfab0cbshemminger break; 211311b41454dc445639924c691a949bd15fbfab0cbshemminger 212311b41454dc445639924c691a949bd15fbfab0cbshemminger case TCF_META_TYPE_VAR: 213311b41454dc445639924c691a949bd15fbfab0cbshemminger strcat(buf, "VAR"); 214311b41454dc445639924c691a949bd15fbfab0cbshemminger break; 215311b41454dc445639924c691a949bd15fbfab0cbshemminger } 216311b41454dc445639924c691a949bd15fbfab0cbshemminger 217311b41454dc445639924c691a949bd15fbfab0cbshemminger if (*(++p)) 218311b41454dc445639924c691a949bd15fbfab0cbshemminger strcat(buf, ","); 219311b41454dc445639924c691a949bd15fbfab0cbshemminger } 220311b41454dc445639924c691a949bd15fbfab0cbshemminger 221311b41454dc445639924c691a949bd15fbfab0cbshemminger fprintf(fd, "%-10s %s\n", buf, meta_table[i].desc); 222311b41454dc445639924c691a949bd15fbfab0cbshemminger } 223311b41454dc445639924c691a949bd15fbfab0cbshemminger } 224311b41454dc445639924c691a949bd15fbfab0cbshemminger 225311b41454dc445639924c691a949bd15fbfab0cbshemminger fprintf(fd, 226311b41454dc445639924c691a949bd15fbfab0cbshemminger "--------------------------------------------------------\n"); 227311b41454dc445639924c691a949bd15fbfab0cbshemminger} 228311b41454dc445639924c691a949bd15fbfab0cbshemminger 229311b41454dc445639924c691a949bd15fbfab0cbshemminger#undef TCF_META_ID_SECTION 230311b41454dc445639924c691a949bd15fbfab0cbshemminger 231311b41454dc445639924c691a949bd15fbfab0cbshemminger#define PARSE_FAILURE ((void *) (-1)) 232311b41454dc445639924c691a949bd15fbfab0cbshemminger 233311b41454dc445639924c691a949bd15fbfab0cbshemminger#define PARSE_ERR(CARG, FMT, ARGS...) \ 234311b41454dc445639924c691a949bd15fbfab0cbshemminger em_parse_error(EINVAL, args, CARG, &meta_ematch_util, FMT ,##ARGS) 235311b41454dc445639924c691a949bd15fbfab0cbshemminger 236311b41454dc445639924c691a949bd15fbfab0cbshemmingerstatic inline int can_adopt(struct tcf_meta_val *val) 237311b41454dc445639924c691a949bd15fbfab0cbshemminger{ 238311b41454dc445639924c691a949bd15fbfab0cbshemminger return !!TCF_META_ID(val->kind); 239311b41454dc445639924c691a949bd15fbfab0cbshemminger} 240311b41454dc445639924c691a949bd15fbfab0cbshemminger 241311b41454dc445639924c691a949bd15fbfab0cbshemmingerstatic inline int overwrite_type(struct tcf_meta_val *src, 242311b41454dc445639924c691a949bd15fbfab0cbshemminger struct tcf_meta_val *dst) 243311b41454dc445639924c691a949bd15fbfab0cbshemminger{ 244311b41454dc445639924c691a949bd15fbfab0cbshemminger return (TCF_META_TYPE(dst->kind) << 12) | TCF_META_ID(src->kind); 245311b41454dc445639924c691a949bd15fbfab0cbshemminger} 246ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger 247311b41454dc445639924c691a949bd15fbfab0cbshemminger 248311b41454dc445639924c691a949bd15fbfab0cbshemmingerstatic inline struct bstr * 249311b41454dc445639924c691a949bd15fbfab0cbshemmingerparse_object(struct bstr *args, struct bstr *arg, struct tcf_meta_val *obj, 250311b41454dc445639924c691a949bd15fbfab0cbshemminger unsigned long *dst, struct tcf_meta_val *left) 251311b41454dc445639924c691a949bd15fbfab0cbshemminger{ 252311b41454dc445639924c691a949bd15fbfab0cbshemminger struct meta_entry *entry; 253311b41454dc445639924c691a949bd15fbfab0cbshemminger unsigned long num; 254311b41454dc445639924c691a949bd15fbfab0cbshemminger struct bstr *a; 255311b41454dc445639924c691a949bd15fbfab0cbshemminger 256311b41454dc445639924c691a949bd15fbfab0cbshemminger if (arg->quoted) { 257311b41454dc445639924c691a949bd15fbfab0cbshemminger obj->kind = TCF_META_TYPE_VAR << 12; 258311b41454dc445639924c691a949bd15fbfab0cbshemminger obj->kind |= TCF_META_ID_VALUE; 259311b41454dc445639924c691a949bd15fbfab0cbshemminger *dst = (unsigned long) arg; 260311b41454dc445639924c691a949bd15fbfab0cbshemminger return bstr_next(arg); 261311b41454dc445639924c691a949bd15fbfab0cbshemminger } 262311b41454dc445639924c691a949bd15fbfab0cbshemminger 263311b41454dc445639924c691a949bd15fbfab0cbshemminger num = bstrtoul(arg); 26411bbe7fd11d5b39e2a136f9d29acef02ce33bf00Denys Fedoryshchenko if (num != ULONG_MAX) { 265311b41454dc445639924c691a949bd15fbfab0cbshemminger obj->kind = TCF_META_TYPE_INT << 12; 266311b41454dc445639924c691a949bd15fbfab0cbshemminger obj->kind |= TCF_META_ID_VALUE; 267311b41454dc445639924c691a949bd15fbfab0cbshemminger *dst = (unsigned long) num; 268311b41454dc445639924c691a949bd15fbfab0cbshemminger return bstr_next(arg); 269311b41454dc445639924c691a949bd15fbfab0cbshemminger } 270311b41454dc445639924c691a949bd15fbfab0cbshemminger 271311b41454dc445639924c691a949bd15fbfab0cbshemminger entry = lookup_meta_entry(arg); 272311b41454dc445639924c691a949bd15fbfab0cbshemminger 273311b41454dc445639924c691a949bd15fbfab0cbshemminger if (entry == NULL) { 274311b41454dc445639924c691a949bd15fbfab0cbshemminger PARSE_ERR(arg, "meta: unknown meta id\n"); 275311b41454dc445639924c691a949bd15fbfab0cbshemminger return PARSE_FAILURE; 276311b41454dc445639924c691a949bd15fbfab0cbshemminger } 277311b41454dc445639924c691a949bd15fbfab0cbshemminger 278311b41454dc445639924c691a949bd15fbfab0cbshemminger obj->kind = entry->id | (map_type(entry->mask[0]) << 12); 279311b41454dc445639924c691a949bd15fbfab0cbshemminger 280311b41454dc445639924c691a949bd15fbfab0cbshemminger if (left) { 281311b41454dc445639924c691a949bd15fbfab0cbshemminger struct tcf_meta_val *right = obj; 282ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger 283311b41454dc445639924c691a949bd15fbfab0cbshemminger if (TCF_META_TYPE(right->kind) == TCF_META_TYPE(left->kind)) 284311b41454dc445639924c691a949bd15fbfab0cbshemminger goto compatible; 285311b41454dc445639924c691a949bd15fbfab0cbshemminger 286311b41454dc445639924c691a949bd15fbfab0cbshemminger if (can_adopt(left) && !can_adopt(right)) { 287311b41454dc445639924c691a949bd15fbfab0cbshemminger if (is_compatible(left, right)) 288311b41454dc445639924c691a949bd15fbfab0cbshemminger left->kind = overwrite_type(left, right); 289311b41454dc445639924c691a949bd15fbfab0cbshemminger else 290311b41454dc445639924c691a949bd15fbfab0cbshemminger goto not_compatible; 291311b41454dc445639924c691a949bd15fbfab0cbshemminger } else if (can_adopt(right) && !can_adopt(left)) { 292311b41454dc445639924c691a949bd15fbfab0cbshemminger if (is_compatible(right, left)) 293311b41454dc445639924c691a949bd15fbfab0cbshemminger right->kind = overwrite_type(right, left); 294311b41454dc445639924c691a949bd15fbfab0cbshemminger else 295311b41454dc445639924c691a949bd15fbfab0cbshemminger goto not_compatible; 296311b41454dc445639924c691a949bd15fbfab0cbshemminger } else if (can_adopt(left) && can_adopt(right)) { 297311b41454dc445639924c691a949bd15fbfab0cbshemminger if (is_compatible(left, right)) 298311b41454dc445639924c691a949bd15fbfab0cbshemminger left->kind = overwrite_type(left, right); 299311b41454dc445639924c691a949bd15fbfab0cbshemminger else if (is_compatible(right, left)) 300311b41454dc445639924c691a949bd15fbfab0cbshemminger right->kind = overwrite_type(right, left); 301311b41454dc445639924c691a949bd15fbfab0cbshemminger else 302311b41454dc445639924c691a949bd15fbfab0cbshemminger goto not_compatible; 303ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger } else 304311b41454dc445639924c691a949bd15fbfab0cbshemminger goto not_compatible; 305311b41454dc445639924c691a949bd15fbfab0cbshemminger } 306311b41454dc445639924c691a949bd15fbfab0cbshemminger 307311b41454dc445639924c691a949bd15fbfab0cbshemmingercompatible: 308311b41454dc445639924c691a949bd15fbfab0cbshemminger 309311b41454dc445639924c691a949bd15fbfab0cbshemminger a = bstr_next(arg); 310311b41454dc445639924c691a949bd15fbfab0cbshemminger 311311b41454dc445639924c691a949bd15fbfab0cbshemminger while(a) { 312311b41454dc445639924c691a949bd15fbfab0cbshemminger if (!bstrcmp(a, "shift")) { 313311b41454dc445639924c691a949bd15fbfab0cbshemminger unsigned long shift; 314311b41454dc445639924c691a949bd15fbfab0cbshemminger 315311b41454dc445639924c691a949bd15fbfab0cbshemminger if (a->next == NULL) { 316311b41454dc445639924c691a949bd15fbfab0cbshemminger PARSE_ERR(a, "meta: missing argument"); 317311b41454dc445639924c691a949bd15fbfab0cbshemminger return PARSE_FAILURE; 318311b41454dc445639924c691a949bd15fbfab0cbshemminger } 319311b41454dc445639924c691a949bd15fbfab0cbshemminger a = bstr_next(a); 320ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger 321311b41454dc445639924c691a949bd15fbfab0cbshemminger shift = bstrtoul(a); 32211bbe7fd11d5b39e2a136f9d29acef02ce33bf00Denys Fedoryshchenko if (shift == ULONG_MAX) { 323311b41454dc445639924c691a949bd15fbfab0cbshemminger PARSE_ERR(a, "meta: invalid shift, must " \ 324311b41454dc445639924c691a949bd15fbfab0cbshemminger "be numeric"); 325311b41454dc445639924c691a949bd15fbfab0cbshemminger return PARSE_FAILURE; 326311b41454dc445639924c691a949bd15fbfab0cbshemminger } 327311b41454dc445639924c691a949bd15fbfab0cbshemminger 328311b41454dc445639924c691a949bd15fbfab0cbshemminger obj->shift = (__u8) shift; 329311b41454dc445639924c691a949bd15fbfab0cbshemminger a = bstr_next(a); 330311b41454dc445639924c691a949bd15fbfab0cbshemminger } else if (!bstrcmp(a, "mask")) { 331311b41454dc445639924c691a949bd15fbfab0cbshemminger unsigned long mask; 332311b41454dc445639924c691a949bd15fbfab0cbshemminger 333311b41454dc445639924c691a949bd15fbfab0cbshemminger if (a->next == NULL) { 334311b41454dc445639924c691a949bd15fbfab0cbshemminger PARSE_ERR(a, "meta: missing argument"); 335311b41454dc445639924c691a949bd15fbfab0cbshemminger return PARSE_FAILURE; 336311b41454dc445639924c691a949bd15fbfab0cbshemminger } 337311b41454dc445639924c691a949bd15fbfab0cbshemminger a = bstr_next(a); 338ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger 339311b41454dc445639924c691a949bd15fbfab0cbshemminger mask = bstrtoul(a); 34011bbe7fd11d5b39e2a136f9d29acef02ce33bf00Denys Fedoryshchenko if (mask == ULONG_MAX) { 341311b41454dc445639924c691a949bd15fbfab0cbshemminger PARSE_ERR(a, "meta: invalid mask, must be " \ 342311b41454dc445639924c691a949bd15fbfab0cbshemminger "numeric"); 343311b41454dc445639924c691a949bd15fbfab0cbshemminger return PARSE_FAILURE; 344311b41454dc445639924c691a949bd15fbfab0cbshemminger } 345311b41454dc445639924c691a949bd15fbfab0cbshemminger *dst = (unsigned long) mask; 346311b41454dc445639924c691a949bd15fbfab0cbshemminger a = bstr_next(a); 347311b41454dc445639924c691a949bd15fbfab0cbshemminger } else 348311b41454dc445639924c691a949bd15fbfab0cbshemminger break; 349311b41454dc445639924c691a949bd15fbfab0cbshemminger } 350311b41454dc445639924c691a949bd15fbfab0cbshemminger 351311b41454dc445639924c691a949bd15fbfab0cbshemminger return a; 352311b41454dc445639924c691a949bd15fbfab0cbshemminger 353311b41454dc445639924c691a949bd15fbfab0cbshemmingernot_compatible: 354311b41454dc445639924c691a949bd15fbfab0cbshemminger PARSE_ERR(arg, "lvalue and rvalue are not compatible."); 355311b41454dc445639924c691a949bd15fbfab0cbshemminger return PARSE_FAILURE; 356311b41454dc445639924c691a949bd15fbfab0cbshemminger} 357311b41454dc445639924c691a949bd15fbfab0cbshemminger 358311b41454dc445639924c691a949bd15fbfab0cbshemmingerstatic int meta_parse_eopt(struct nlmsghdr *n, struct tcf_ematch_hdr *hdr, 359311b41454dc445639924c691a949bd15fbfab0cbshemminger struct bstr *args) 360311b41454dc445639924c691a949bd15fbfab0cbshemminger{ 361311b41454dc445639924c691a949bd15fbfab0cbshemminger int opnd; 362311b41454dc445639924c691a949bd15fbfab0cbshemminger struct bstr *a; 363311b41454dc445639924c691a949bd15fbfab0cbshemminger struct tcf_meta_hdr meta_hdr; 364311b41454dc445639924c691a949bd15fbfab0cbshemminger unsigned long lvalue = 0, rvalue = 0; 365311b41454dc445639924c691a949bd15fbfab0cbshemminger 366311b41454dc445639924c691a949bd15fbfab0cbshemminger memset(&meta_hdr, 0, sizeof(meta_hdr)); 367311b41454dc445639924c691a949bd15fbfab0cbshemminger 368311b41454dc445639924c691a949bd15fbfab0cbshemminger if (args == NULL) 369311b41454dc445639924c691a949bd15fbfab0cbshemminger return PARSE_ERR(args, "meta: missing arguments"); 370311b41454dc445639924c691a949bd15fbfab0cbshemminger 371311b41454dc445639924c691a949bd15fbfab0cbshemminger if (!bstrcmp(args, "list")) { 372311b41454dc445639924c691a949bd15fbfab0cbshemminger list_meta_ids(stderr); 373311b41454dc445639924c691a949bd15fbfab0cbshemminger return -1; 374311b41454dc445639924c691a949bd15fbfab0cbshemminger } 375311b41454dc445639924c691a949bd15fbfab0cbshemminger 376311b41454dc445639924c691a949bd15fbfab0cbshemminger a = parse_object(args, args, &meta_hdr.left, &lvalue, NULL); 377311b41454dc445639924c691a949bd15fbfab0cbshemminger if (a == PARSE_FAILURE) 378311b41454dc445639924c691a949bd15fbfab0cbshemminger return -1; 379311b41454dc445639924c691a949bd15fbfab0cbshemminger else if (a == NULL) 380311b41454dc445639924c691a949bd15fbfab0cbshemminger return PARSE_ERR(args, "meta: missing operand"); 381311b41454dc445639924c691a949bd15fbfab0cbshemminger 382311b41454dc445639924c691a949bd15fbfab0cbshemminger if (!bstrcmp(a, "eq")) 383311b41454dc445639924c691a949bd15fbfab0cbshemminger opnd = TCF_EM_OPND_EQ; 384311b41454dc445639924c691a949bd15fbfab0cbshemminger else if (!bstrcmp(a, "gt")) 385311b41454dc445639924c691a949bd15fbfab0cbshemminger opnd = TCF_EM_OPND_GT; 386311b41454dc445639924c691a949bd15fbfab0cbshemminger else if (!bstrcmp(a, "lt")) 387311b41454dc445639924c691a949bd15fbfab0cbshemminger opnd = TCF_EM_OPND_LT; 388311b41454dc445639924c691a949bd15fbfab0cbshemminger else 389311b41454dc445639924c691a949bd15fbfab0cbshemminger return PARSE_ERR(a, "meta: invalid operand"); 390311b41454dc445639924c691a949bd15fbfab0cbshemminger 391311b41454dc445639924c691a949bd15fbfab0cbshemminger meta_hdr.left.op = (__u8) opnd; 392311b41454dc445639924c691a949bd15fbfab0cbshemminger 393311b41454dc445639924c691a949bd15fbfab0cbshemminger if (a->next == NULL) 394311b41454dc445639924c691a949bd15fbfab0cbshemminger return PARSE_ERR(args, "meta: missing rvalue"); 395311b41454dc445639924c691a949bd15fbfab0cbshemminger a = bstr_next(a); 396311b41454dc445639924c691a949bd15fbfab0cbshemminger 397311b41454dc445639924c691a949bd15fbfab0cbshemminger a = parse_object(args, a, &meta_hdr.right, &rvalue, &meta_hdr.left); 398311b41454dc445639924c691a949bd15fbfab0cbshemminger if (a == PARSE_FAILURE) 399311b41454dc445639924c691a949bd15fbfab0cbshemminger return -1; 400311b41454dc445639924c691a949bd15fbfab0cbshemminger else if (a != NULL) 401311b41454dc445639924c691a949bd15fbfab0cbshemminger return PARSE_ERR(a, "meta: unexpected trailer"); 402ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger 403311b41454dc445639924c691a949bd15fbfab0cbshemminger 404311b41454dc445639924c691a949bd15fbfab0cbshemminger addraw_l(n, MAX_MSG, hdr, sizeof(*hdr)); 405311b41454dc445639924c691a949bd15fbfab0cbshemminger 406311b41454dc445639924c691a949bd15fbfab0cbshemminger addattr_l(n, MAX_MSG, TCA_EM_META_HDR, &meta_hdr, sizeof(meta_hdr)); 407311b41454dc445639924c691a949bd15fbfab0cbshemminger 4086140785236f9dcddde0c61542dcbe9593e7ab650Patrick McHardy dump_value(n, TCA_EM_META_LVALUE, lvalue, &meta_hdr.left); 4096140785236f9dcddde0c61542dcbe9593e7ab650Patrick McHardy dump_value(n, TCA_EM_META_RVALUE, rvalue, &meta_hdr.right); 410311b41454dc445639924c691a949bd15fbfab0cbshemminger 411311b41454dc445639924c691a949bd15fbfab0cbshemminger return 0; 412311b41454dc445639924c691a949bd15fbfab0cbshemminger} 413311b41454dc445639924c691a949bd15fbfab0cbshemminger#undef PARSE_ERR 414311b41454dc445639924c691a949bd15fbfab0cbshemminger 415311b41454dc445639924c691a949bd15fbfab0cbshemmingerstatic inline void print_binary(FILE *fd, unsigned char *str, int len) 416311b41454dc445639924c691a949bd15fbfab0cbshemminger{ 417311b41454dc445639924c691a949bd15fbfab0cbshemminger int i; 418311b41454dc445639924c691a949bd15fbfab0cbshemminger 419311b41454dc445639924c691a949bd15fbfab0cbshemminger for (i = 0; i < len; i++) 420311b41454dc445639924c691a949bd15fbfab0cbshemminger if (!isprint(str[i])) 421311b41454dc445639924c691a949bd15fbfab0cbshemminger goto binary; 422311b41454dc445639924c691a949bd15fbfab0cbshemminger 423311b41454dc445639924c691a949bd15fbfab0cbshemminger for (i = 0; i < len; i++) 424311b41454dc445639924c691a949bd15fbfab0cbshemminger fprintf(fd, "%c", str[i]); 425311b41454dc445639924c691a949bd15fbfab0cbshemminger return; 426311b41454dc445639924c691a949bd15fbfab0cbshemminger 427311b41454dc445639924c691a949bd15fbfab0cbshemmingerbinary: 428311b41454dc445639924c691a949bd15fbfab0cbshemminger for (i = 0; i < len; i++) 429311b41454dc445639924c691a949bd15fbfab0cbshemminger fprintf(fd, "%02x ", str[i]); 430311b41454dc445639924c691a949bd15fbfab0cbshemminger 431311b41454dc445639924c691a949bd15fbfab0cbshemminger fprintf(fd, "\""); 432311b41454dc445639924c691a949bd15fbfab0cbshemminger for (i = 0; i < len; i++) 433311b41454dc445639924c691a949bd15fbfab0cbshemminger fprintf(fd, "%c", isprint(str[i]) ? str[i] : '.'); 434311b41454dc445639924c691a949bd15fbfab0cbshemminger fprintf(fd, "\""); 435311b41454dc445639924c691a949bd15fbfab0cbshemminger} 436311b41454dc445639924c691a949bd15fbfab0cbshemminger 437311b41454dc445639924c691a949bd15fbfab0cbshemmingerstatic inline int print_value(FILE *fd, int type, struct rtattr *rta) 438311b41454dc445639924c691a949bd15fbfab0cbshemminger{ 439311b41454dc445639924c691a949bd15fbfab0cbshemminger if (rta == NULL) { 440311b41454dc445639924c691a949bd15fbfab0cbshemminger fprintf(stderr, "Missing value TLV\n"); 441311b41454dc445639924c691a949bd15fbfab0cbshemminger return -1; 442311b41454dc445639924c691a949bd15fbfab0cbshemminger } 443311b41454dc445639924c691a949bd15fbfab0cbshemminger 444311b41454dc445639924c691a949bd15fbfab0cbshemminger switch(type) { 445311b41454dc445639924c691a949bd15fbfab0cbshemminger case TCF_META_TYPE_INT: 446311b41454dc445639924c691a949bd15fbfab0cbshemminger if (RTA_PAYLOAD(rta) < sizeof(__u32)) { 447311b41454dc445639924c691a949bd15fbfab0cbshemminger fprintf(stderr, "meta int type value TLV " \ 448311b41454dc445639924c691a949bd15fbfab0cbshemminger "size mismatch.\n"); 449311b41454dc445639924c691a949bd15fbfab0cbshemminger return -1; 450311b41454dc445639924c691a949bd15fbfab0cbshemminger } 451ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger fprintf(fd, "%d", rta_getattr_u32(rta)); 452311b41454dc445639924c691a949bd15fbfab0cbshemminger break; 453311b41454dc445639924c691a949bd15fbfab0cbshemminger 454311b41454dc445639924c691a949bd15fbfab0cbshemminger case TCF_META_TYPE_VAR: 455311b41454dc445639924c691a949bd15fbfab0cbshemminger print_binary(fd, RTA_DATA(rta), RTA_PAYLOAD(rta)); 456311b41454dc445639924c691a949bd15fbfab0cbshemminger break; 457311b41454dc445639924c691a949bd15fbfab0cbshemminger } 458311b41454dc445639924c691a949bd15fbfab0cbshemminger 459311b41454dc445639924c691a949bd15fbfab0cbshemminger return 0; 460311b41454dc445639924c691a949bd15fbfab0cbshemminger} 461311b41454dc445639924c691a949bd15fbfab0cbshemminger 462311b41454dc445639924c691a949bd15fbfab0cbshemmingerstatic int print_object(FILE *fd, struct tcf_meta_val *obj, struct rtattr *rta) 463311b41454dc445639924c691a949bd15fbfab0cbshemminger{ 464311b41454dc445639924c691a949bd15fbfab0cbshemminger int id = TCF_META_ID(obj->kind); 465311b41454dc445639924c691a949bd15fbfab0cbshemminger int type = TCF_META_TYPE(obj->kind); 466311b41454dc445639924c691a949bd15fbfab0cbshemminger struct meta_entry *entry; 467311b41454dc445639924c691a949bd15fbfab0cbshemminger 468311b41454dc445639924c691a949bd15fbfab0cbshemminger if (id == TCF_META_ID_VALUE) 469311b41454dc445639924c691a949bd15fbfab0cbshemminger return print_value(fd, type, rta); 470311b41454dc445639924c691a949bd15fbfab0cbshemminger 471311b41454dc445639924c691a949bd15fbfab0cbshemminger entry = lookup_meta_entry_byid(id); 472311b41454dc445639924c691a949bd15fbfab0cbshemminger 473311b41454dc445639924c691a949bd15fbfab0cbshemminger if (entry == NULL) 474311b41454dc445639924c691a949bd15fbfab0cbshemminger fprintf(fd, "[unknown meta id %d]", id); 475311b41454dc445639924c691a949bd15fbfab0cbshemminger else 476311b41454dc445639924c691a949bd15fbfab0cbshemminger fprintf(fd, "%s", entry->kind); 477311b41454dc445639924c691a949bd15fbfab0cbshemminger 478311b41454dc445639924c691a949bd15fbfab0cbshemminger if (obj->shift) 479311b41454dc445639924c691a949bd15fbfab0cbshemminger fprintf(fd, " shift %d", obj->shift); 480311b41454dc445639924c691a949bd15fbfab0cbshemminger 481311b41454dc445639924c691a949bd15fbfab0cbshemminger switch (type) { 482311b41454dc445639924c691a949bd15fbfab0cbshemminger case TCF_META_TYPE_INT: 483311b41454dc445639924c691a949bd15fbfab0cbshemminger if (rta) { 484311b41454dc445639924c691a949bd15fbfab0cbshemminger if (RTA_PAYLOAD(rta) < sizeof(__u32)) 485311b41454dc445639924c691a949bd15fbfab0cbshemminger goto size_mismatch; 486311b41454dc445639924c691a949bd15fbfab0cbshemminger 487311b41454dc445639924c691a949bd15fbfab0cbshemminger fprintf(fd, " mask 0x%08x", 488ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger rta_getattr_u32(rta)); 489311b41454dc445639924c691a949bd15fbfab0cbshemminger } 490311b41454dc445639924c691a949bd15fbfab0cbshemminger break; 491311b41454dc445639924c691a949bd15fbfab0cbshemminger } 492311b41454dc445639924c691a949bd15fbfab0cbshemminger 493311b41454dc445639924c691a949bd15fbfab0cbshemminger return 0; 494311b41454dc445639924c691a949bd15fbfab0cbshemminger 495311b41454dc445639924c691a949bd15fbfab0cbshemmingersize_mismatch: 496311b41454dc445639924c691a949bd15fbfab0cbshemminger fprintf(stderr, "meta int type mask TLV size mismatch\n"); 497311b41454dc445639924c691a949bd15fbfab0cbshemminger return -1; 498311b41454dc445639924c691a949bd15fbfab0cbshemminger} 499311b41454dc445639924c691a949bd15fbfab0cbshemminger 500311b41454dc445639924c691a949bd15fbfab0cbshemminger 501311b41454dc445639924c691a949bd15fbfab0cbshemmingerstatic int meta_print_eopt(FILE *fd, struct tcf_ematch_hdr *hdr, void *data, 502311b41454dc445639924c691a949bd15fbfab0cbshemminger int data_len) 503311b41454dc445639924c691a949bd15fbfab0cbshemminger{ 504311b41454dc445639924c691a949bd15fbfab0cbshemminger struct rtattr *tb[TCA_EM_META_MAX+1]; 505311b41454dc445639924c691a949bd15fbfab0cbshemminger struct tcf_meta_hdr *meta_hdr; 506311b41454dc445639924c691a949bd15fbfab0cbshemminger 507311b41454dc445639924c691a949bd15fbfab0cbshemminger if (parse_rtattr(tb, TCA_EM_META_MAX, data, data_len) < 0) 508311b41454dc445639924c691a949bd15fbfab0cbshemminger return -1; 509311b41454dc445639924c691a949bd15fbfab0cbshemminger 510311b41454dc445639924c691a949bd15fbfab0cbshemminger if (tb[TCA_EM_META_HDR] == NULL) { 511311b41454dc445639924c691a949bd15fbfab0cbshemminger fprintf(stderr, "Missing meta header\n"); 512311b41454dc445639924c691a949bd15fbfab0cbshemminger return -1; 513311b41454dc445639924c691a949bd15fbfab0cbshemminger } 514311b41454dc445639924c691a949bd15fbfab0cbshemminger 515311b41454dc445639924c691a949bd15fbfab0cbshemminger if (RTA_PAYLOAD(tb[TCA_EM_META_HDR]) < sizeof(*meta_hdr)) { 516311b41454dc445639924c691a949bd15fbfab0cbshemminger fprintf(stderr, "Meta header size mismatch\n"); 517311b41454dc445639924c691a949bd15fbfab0cbshemminger return -1; 518311b41454dc445639924c691a949bd15fbfab0cbshemminger } 519311b41454dc445639924c691a949bd15fbfab0cbshemminger 520311b41454dc445639924c691a949bd15fbfab0cbshemminger meta_hdr = RTA_DATA(tb[TCA_EM_META_HDR]); 521311b41454dc445639924c691a949bd15fbfab0cbshemminger 522311b41454dc445639924c691a949bd15fbfab0cbshemminger if (print_object(fd, &meta_hdr->left, tb[TCA_EM_META_LVALUE]) < 0) 523311b41454dc445639924c691a949bd15fbfab0cbshemminger return -1; 524311b41454dc445639924c691a949bd15fbfab0cbshemminger 525311b41454dc445639924c691a949bd15fbfab0cbshemminger switch (meta_hdr->left.op) { 526311b41454dc445639924c691a949bd15fbfab0cbshemminger case TCF_EM_OPND_EQ: 527311b41454dc445639924c691a949bd15fbfab0cbshemminger fprintf(fd, " eq "); 528311b41454dc445639924c691a949bd15fbfab0cbshemminger break; 529311b41454dc445639924c691a949bd15fbfab0cbshemminger case TCF_EM_OPND_LT: 530311b41454dc445639924c691a949bd15fbfab0cbshemminger fprintf(fd, " lt "); 531311b41454dc445639924c691a949bd15fbfab0cbshemminger break; 532311b41454dc445639924c691a949bd15fbfab0cbshemminger case TCF_EM_OPND_GT: 533311b41454dc445639924c691a949bd15fbfab0cbshemminger fprintf(fd, " gt "); 534311b41454dc445639924c691a949bd15fbfab0cbshemminger break; 535311b41454dc445639924c691a949bd15fbfab0cbshemminger } 536311b41454dc445639924c691a949bd15fbfab0cbshemminger 537311b41454dc445639924c691a949bd15fbfab0cbshemminger return print_object(fd, &meta_hdr->right, tb[TCA_EM_META_RVALUE]); 538311b41454dc445639924c691a949bd15fbfab0cbshemminger} 539311b41454dc445639924c691a949bd15fbfab0cbshemminger 540311b41454dc445639924c691a949bd15fbfab0cbshemmingerstruct ematch_util meta_ematch_util = { 541311b41454dc445639924c691a949bd15fbfab0cbshemminger .kind = "meta", 542311b41454dc445639924c691a949bd15fbfab0cbshemminger .kind_num = TCF_EM_META, 543311b41454dc445639924c691a949bd15fbfab0cbshemminger .parse_eopt = meta_parse_eopt, 544311b41454dc445639924c691a949bd15fbfab0cbshemminger .print_eopt = meta_print_eopt, 545311b41454dc445639924c691a949bd15fbfab0cbshemminger .print_usage = meta_print_usage 546311b41454dc445639924c691a949bd15fbfab0cbshemminger}; 547