1dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat/* 2dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * em_meta.c Metadata Ematch 3dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * 4dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * This program is free software; you can distribute 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: Thomas Graf <tgraf@suug.ch> 10dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat */ 11dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 12dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <stdio.h> 13dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <stdlib.h> 14dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <unistd.h> 15dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <syslog.h> 16dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <fcntl.h> 17dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <sys/socket.h> 18dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <netinet/in.h> 19dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <arpa/inet.h> 20dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <string.h> 21dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <errno.h> 22dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 23dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include "m_ematch.h" 24dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <linux/tc_ematch/tc_em_meta.h> 25dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 26dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatextern struct ematch_util meta_ematch_util; 27dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 28dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic void meta_print_usage(FILE *fd) 29dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 30dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(fd, 31dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat "Usage: meta(OBJECT { eq | lt | gt } OBJECT)\n" \ 32dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat "where: OBJECT := { META_ID | VALUE }\n" \ 33dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat " META_ID := id [ shift SHIFT ] [ mask MASK ]\n" \ 34dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat "\n" \ 35dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat "Example: meta(nfmark gt 24)\n" \ 36dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat " meta(indev shift 1 eq \"ppp\")\n" \ 37dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat " meta(tcindex mask 0xf0 eq 0xf0)\n" \ 38dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat "\n" \ 39dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat "For a list of meta identifiers, use meta(list).\n"); 40dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 41dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 42dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstruct meta_entry { 43dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int id; 44dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat char * kind; 45dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat char * mask; 46dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat char * desc; 47dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} meta_table[] = { 48dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#define TCF_META_ID_SECTION 0 49dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#define __A(id, name, mask, desc) { TCF_META_ID_##id, name, mask, desc } 50dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __A(SECTION, "Generic", "", ""), 51dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __A(RANDOM, "random", "i", 52dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat "Random value (32 bit)"), 53dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __A(LOADAVG_0, "loadavg_1", "i", 54dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat "Load average in last minute"), 55dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __A(LOADAVG_1, "loadavg_5", "i", 56dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat "Load average in last 5 minutes"), 57dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __A(LOADAVG_2, "loadavg_15", "i", 58dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat "Load average in last 15 minutes"), 59dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 60dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __A(SECTION, "Interfaces", "", ""), 61dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __A(DEV, "dev", "iv", 62dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat "Device the packet is on"), 63dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __A(SECTION, "Packet attributes", "", ""), 64dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __A(PRIORITY, "priority", "i", 65dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat "Priority of packet"), 66dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __A(PROTOCOL, "protocol", "i", 67dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat "Link layer protocol"), 68dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __A(PKTTYPE, "pkt_type", "i", 69dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat "Packet type (uni|multi|broad|...)cast"), 70dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __A(PKTLEN, "pkt_len", "i", 71dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat "Length of packet"), 72dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __A(DATALEN, "data_len", "i", 73dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat "Length of data in packet"), 74dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __A(MACLEN, "mac_len", "i", 75dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat "Length of link layer header"), 76dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 77dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __A(SECTION, "Netfilter", "", ""), 78dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __A(NFMARK, "nf_mark", "i", 79dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat "Netfilter mark"), 80dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __A(NFMARK, "fwmark", "i", 81dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat "Alias for nf_mark"), 82dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 83dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __A(SECTION, "Traffic Control", "", ""), 84dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __A(TCINDEX, "tc_index", "i", "TC Index"), 85dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __A(SECTION, "Routing", "", ""), 86dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __A(RTCLASSID, "rt_classid", "i", 87dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat "Routing ClassID (cls_route)"), 88dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __A(RTIIF, "rt_iif", "i", 89dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat "Incoming interface index"), 90dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __A(VLAN_TAG, "vlan", "i", "Vlan tag"), 91dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 92dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __A(SECTION, "Sockets", "", ""), 93dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __A(SK_FAMILY, "sk_family", "i", "Address family"), 94dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __A(SK_STATE, "sk_state", "i", "State"), 95dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __A(SK_REUSE, "sk_reuse", "i", "Reuse Flag"), 96dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __A(SK_BOUND_IF, "sk_bind_if", "iv", "Bound interface"), 97dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __A(SK_REFCNT, "sk_refcnt", "i", "Reference counter"), 98dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __A(SK_SHUTDOWN, "sk_shutdown", "i", "Shutdown mask"), 99dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __A(SK_PROTO, "sk_proto", "i", "Protocol"), 100dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __A(SK_TYPE, "sk_type", "i", "Type"), 101dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __A(SK_RCVBUF, "sk_rcvbuf", "i", "Receive buffer size"), 102dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __A(SK_RMEM_ALLOC, "sk_rmem", "i", "RMEM"), 103dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __A(SK_WMEM_ALLOC, "sk_wmem", "i", "WMEM"), 104dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __A(SK_OMEM_ALLOC, "sk_omem", "i", "OMEM"), 105dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __A(SK_WMEM_QUEUED, "sk_wmem_queue","i", "WMEM queue"), 106dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __A(SK_SND_QLEN, "sk_snd_queue", "i", "Send queue length"), 107dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __A(SK_RCV_QLEN, "sk_rcv_queue", "i", "Receive queue length"), 108dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __A(SK_ERR_QLEN, "sk_err_queue", "i", "Error queue length"), 109dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __A(SK_FORWARD_ALLOCS, "sk_fwd_alloc", "i", "Forward allocations"), 110dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __A(SK_SNDBUF, "sk_sndbuf", "i", "Send buffer size"), 111dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#undef __A 112dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}; 113dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 114dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic inline int map_type(char k) 115dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 116dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat switch (k) { 117dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat case 'i': return TCF_META_TYPE_INT; 118dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat case 'v': return TCF_META_TYPE_VAR; 119dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 120dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 121dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "BUG: Unknown map character '%c'\n", k); 122dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return INT_MAX; 123dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 124dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 125dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic struct meta_entry * lookup_meta_entry(struct bstr *kind) 126dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 127dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int i; 128dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 129dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat for (i = 0; i < (sizeof(meta_table)/sizeof(meta_table[0])); i++) 130dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (!bstrcmp(kind, meta_table[i].kind) && 131dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat meta_table[i].id != 0) 132dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return &meta_table[i]; 133dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 134dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return NULL; 135dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 136dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 137dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic struct meta_entry * lookup_meta_entry_byid(int id) 138dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 139dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int i; 140dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 141dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat for (i = 0; i < (sizeof(meta_table)/sizeof(meta_table[0])); i++) 142dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (meta_table[i].id == id) 143dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return &meta_table[i]; 144dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 145dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return NULL; 146dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 147dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 148dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic inline void dump_value(struct nlmsghdr *n, int tlv, unsigned long val, 149dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct tcf_meta_val *hdr) 150dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 151dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __u32 t; 152dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 153dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat switch (TCF_META_TYPE(hdr->kind)) { 154dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat case TCF_META_TYPE_INT: 155dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat t = val; 156dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat addattr_l(n, MAX_MSG, tlv, &t, sizeof(t)); 157dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat break; 158dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 159dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat case TCF_META_TYPE_VAR: 160dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (TCF_META_ID(hdr->kind) == TCF_META_ID_VALUE) { 161dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct bstr *a = (struct bstr *) val; 162dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat addattr_l(n, MAX_MSG, tlv, a->data, a->len); 163dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 164dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat break; 165dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 166dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 167dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 168dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic inline int is_compatible(struct tcf_meta_val *what, 169dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct tcf_meta_val *needed) 170dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 171dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat char *p; 172dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct meta_entry *entry; 173dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 174dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat entry = lookup_meta_entry_byid(TCF_META_ID(what->kind)); 175dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 176dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (entry == NULL) 177dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return 0; 178dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 179dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat for (p = entry->mask; p; p++) 180dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (map_type(*p) == TCF_META_TYPE(needed->kind)) 181dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return 1; 182dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 183dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return 0; 184dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 185dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 186dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic void list_meta_ids(FILE *fd) 187dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 188dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int i; 189dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 190dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(fd, 191dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat "--------------------------------------------------------\n" \ 192dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat " ID Type Description\n" \ 193dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat "--------------------------------------------------------"); 194dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 195dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat for (i = 0; i < (sizeof(meta_table)/sizeof(meta_table[0])); i++) { 196dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (meta_table[i].id == TCF_META_ID_SECTION) { 197dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(fd, "\n%s:\n", meta_table[i].kind); 198dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else { 199dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat char *p = meta_table[i].mask; 200dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat char buf[64] = {0}; 201dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 202dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(fd, " %-16s ", meta_table[i].kind); 203dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 204dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat while (*p) { 205dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int type = map_type(*p); 206dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 207dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat switch (type) { 208dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat case TCF_META_TYPE_INT: 209dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat strcat(buf, "INT"); 210dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat break; 211dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 212dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat case TCF_META_TYPE_VAR: 213dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat strcat(buf, "VAR"); 214dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat break; 215dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 216dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 217dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (*(++p)) 218dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat strcat(buf, ","); 219dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 220dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 221dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(fd, "%-10s %s\n", buf, meta_table[i].desc); 222dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 223dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 224dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 225dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(fd, 226dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat "--------------------------------------------------------\n"); 227dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 228dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 229dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#undef TCF_META_ID_SECTION 230dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 231dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#define PARSE_FAILURE ((void *) (-1)) 232dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 233dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#define PARSE_ERR(CARG, FMT, ARGS...) \ 234dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat em_parse_error(EINVAL, args, CARG, &meta_ematch_util, FMT ,##ARGS) 235dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 236dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic inline int can_adopt(struct tcf_meta_val *val) 237dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 238dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return !!TCF_META_ID(val->kind); 239dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 240dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 241dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic inline int overwrite_type(struct tcf_meta_val *src, 242dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct tcf_meta_val *dst) 243dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 244dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return (TCF_META_TYPE(dst->kind) << 12) | TCF_META_ID(src->kind); 245dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 246dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 247dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 248dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic inline struct bstr * 249dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatparse_object(struct bstr *args, struct bstr *arg, struct tcf_meta_val *obj, 250dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat unsigned long *dst, struct tcf_meta_val *left) 251dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 252dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct meta_entry *entry; 253dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat unsigned long num; 254dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct bstr *a; 255dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 256dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (arg->quoted) { 257dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat obj->kind = TCF_META_TYPE_VAR << 12; 258dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat obj->kind |= TCF_META_ID_VALUE; 259dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *dst = (unsigned long) arg; 260dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return bstr_next(arg); 261dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 262dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 263dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat num = bstrtoul(arg); 264dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (num != ULONG_MAX) { 265dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat obj->kind = TCF_META_TYPE_INT << 12; 266dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat obj->kind |= TCF_META_ID_VALUE; 267dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *dst = (unsigned long) num; 268dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return bstr_next(arg); 269dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 270dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 271dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat entry = lookup_meta_entry(arg); 272dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 273dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (entry == NULL) { 274dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat PARSE_ERR(arg, "meta: unknown meta id\n"); 275dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return PARSE_FAILURE; 276dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 277dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 278dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat obj->kind = entry->id | (map_type(entry->mask[0]) << 12); 279dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 280dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (left) { 281dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct tcf_meta_val *right = obj; 282dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 283dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (TCF_META_TYPE(right->kind) == TCF_META_TYPE(left->kind)) 284dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat goto compatible; 285dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 286dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (can_adopt(left) && !can_adopt(right)) { 287dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (is_compatible(left, right)) 288dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat left->kind = overwrite_type(left, right); 289dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat else 290dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat goto not_compatible; 291dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else if (can_adopt(right) && !can_adopt(left)) { 292dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (is_compatible(right, left)) 293dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat right->kind = overwrite_type(right, left); 294dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat else 295dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat goto not_compatible; 296dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else if (can_adopt(left) && can_adopt(right)) { 297dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (is_compatible(left, right)) 298dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat left->kind = overwrite_type(left, right); 299dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat else if (is_compatible(right, left)) 300dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat right->kind = overwrite_type(right, left); 301dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat else 302dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat goto not_compatible; 303dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else 304dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat goto not_compatible; 305dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 306dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 307dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatcompatible: 308dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 309dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat a = bstr_next(arg); 310dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 311dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat while(a) { 312dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (!bstrcmp(a, "shift")) { 313dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat unsigned long shift; 314dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 315dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (a->next == NULL) { 316dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat PARSE_ERR(a, "meta: missing argument"); 317dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return PARSE_FAILURE; 318dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 319dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat a = bstr_next(a); 320dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 321dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat shift = bstrtoul(a); 322dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (shift == ULONG_MAX) { 323dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat PARSE_ERR(a, "meta: invalid shift, must " \ 324dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat "be numeric"); 325dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return PARSE_FAILURE; 326dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 327dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 328dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat obj->shift = (__u8) shift; 329dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat a = bstr_next(a); 330dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else if (!bstrcmp(a, "mask")) { 331dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat unsigned long mask; 332dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 333dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (a->next == NULL) { 334dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat PARSE_ERR(a, "meta: missing argument"); 335dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return PARSE_FAILURE; 336dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 337dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat a = bstr_next(a); 338dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 339dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat mask = bstrtoul(a); 340dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (mask == ULONG_MAX) { 341dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat PARSE_ERR(a, "meta: invalid mask, must be " \ 342dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat "numeric"); 343dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return PARSE_FAILURE; 344dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 345dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *dst = (unsigned long) mask; 346dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat a = bstr_next(a); 347dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else 348dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat break; 349dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 350dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 351dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return a; 352dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 353dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatnot_compatible: 354dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat PARSE_ERR(arg, "lvalue and rvalue are not compatible."); 355dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return PARSE_FAILURE; 356dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 357dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 358dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic int meta_parse_eopt(struct nlmsghdr *n, struct tcf_ematch_hdr *hdr, 359dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct bstr *args) 360dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 361dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int opnd; 362dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct bstr *a; 363dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct tcf_meta_hdr meta_hdr; 364dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat unsigned long lvalue = 0, rvalue = 0; 365dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 366dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat memset(&meta_hdr, 0, sizeof(meta_hdr)); 367dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 368dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (args == NULL) 369dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return PARSE_ERR(args, "meta: missing arguments"); 370dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 371dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (!bstrcmp(args, "list")) { 372dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat list_meta_ids(stderr); 373dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 374dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 375dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 376dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat a = parse_object(args, args, &meta_hdr.left, &lvalue, NULL); 377dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (a == PARSE_FAILURE) 378dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 379dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat else if (a == NULL) 380dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return PARSE_ERR(args, "meta: missing operand"); 381dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 382dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (!bstrcmp(a, "eq")) 383dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat opnd = TCF_EM_OPND_EQ; 384dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat else if (!bstrcmp(a, "gt")) 385dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat opnd = TCF_EM_OPND_GT; 386dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat else if (!bstrcmp(a, "lt")) 387dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat opnd = TCF_EM_OPND_LT; 388dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat else 389dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return PARSE_ERR(a, "meta: invalid operand"); 390dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 391dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat meta_hdr.left.op = (__u8) opnd; 392dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 393dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (a->next == NULL) 394dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return PARSE_ERR(args, "meta: missing rvalue"); 395dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat a = bstr_next(a); 396dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 397dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat a = parse_object(args, a, &meta_hdr.right, &rvalue, &meta_hdr.left); 398dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (a == PARSE_FAILURE) 399dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 400dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat else if (a != NULL) 401dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return PARSE_ERR(a, "meta: unexpected trailer"); 402dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 403dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 404dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat addraw_l(n, MAX_MSG, hdr, sizeof(*hdr)); 405dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 406dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat addattr_l(n, MAX_MSG, TCA_EM_META_HDR, &meta_hdr, sizeof(meta_hdr)); 407dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 408dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat dump_value(n, TCA_EM_META_LVALUE, lvalue, &meta_hdr.left); 409dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat dump_value(n, TCA_EM_META_RVALUE, rvalue, &meta_hdr.right); 410dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 411dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return 0; 412dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 413dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#undef PARSE_ERR 414dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 415dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic inline void print_binary(FILE *fd, unsigned char *str, int len) 416dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 417dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int i; 418dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 419dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat for (i = 0; i < len; i++) 420dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (!isprint(str[i])) 421dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat goto binary; 422dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 423dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat for (i = 0; i < len; i++) 424dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(fd, "%c", str[i]); 425dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return; 426dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 427dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatbinary: 428dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat for (i = 0; i < len; i++) 429dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(fd, "%02x ", str[i]); 430dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 431dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(fd, "\""); 432dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat for (i = 0; i < len; i++) 433dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(fd, "%c", isprint(str[i]) ? str[i] : '.'); 434dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(fd, "\""); 435dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 436dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 437dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic inline int print_value(FILE *fd, int type, struct rtattr *rta) 438dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 439dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (rta == NULL) { 440dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "Missing value TLV\n"); 441dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 442dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 443dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 444dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat switch(type) { 445dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat case TCF_META_TYPE_INT: 446dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (RTA_PAYLOAD(rta) < sizeof(__u32)) { 447dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "meta int type value TLV " \ 448dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat "size mismatch.\n"); 449dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 450dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 451dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(fd, "%d", *(__u32 *) RTA_DATA(rta)); 452dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat break; 453dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 454dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat case TCF_META_TYPE_VAR: 455dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat print_binary(fd, RTA_DATA(rta), RTA_PAYLOAD(rta)); 456dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat break; 457dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 458dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 459dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return 0; 460dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 461dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 462dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic int print_object(FILE *fd, struct tcf_meta_val *obj, struct rtattr *rta) 463dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 464dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int id = TCF_META_ID(obj->kind); 465dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int type = TCF_META_TYPE(obj->kind); 466dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct meta_entry *entry; 467dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 468dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (id == TCF_META_ID_VALUE) 469dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return print_value(fd, type, rta); 470dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 471dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat entry = lookup_meta_entry_byid(id); 472dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 473dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (entry == NULL) 474dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(fd, "[unknown meta id %d]", id); 475dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat else 476dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(fd, "%s", entry->kind); 477dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 478dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (obj->shift) 479dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(fd, " shift %d", obj->shift); 480dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 481dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat switch (type) { 482dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat case TCF_META_TYPE_INT: 483dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (rta) { 484dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (RTA_PAYLOAD(rta) < sizeof(__u32)) 485dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat goto size_mismatch; 486dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 487dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(fd, " mask 0x%08x", 488dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *(__u32*) RTA_DATA(rta)); 489dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 490dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat break; 491dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 492dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 493dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return 0; 494dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 495dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatsize_mismatch: 496dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "meta int type mask TLV size mismatch\n"); 497dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 498dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 499dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 500dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 501dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic int meta_print_eopt(FILE *fd, struct tcf_ematch_hdr *hdr, void *data, 502dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int data_len) 503dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 504dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct rtattr *tb[TCA_EM_META_MAX+1]; 505dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct tcf_meta_hdr *meta_hdr; 506dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 507dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (parse_rtattr(tb, TCA_EM_META_MAX, data, data_len) < 0) 508dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 509dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 510dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (tb[TCA_EM_META_HDR] == NULL) { 511dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "Missing meta header\n"); 512dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 513dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 514dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 515dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (RTA_PAYLOAD(tb[TCA_EM_META_HDR]) < sizeof(*meta_hdr)) { 516dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "Meta header size mismatch\n"); 517dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 518dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 519dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 520dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat meta_hdr = RTA_DATA(tb[TCA_EM_META_HDR]); 521dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 522dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (print_object(fd, &meta_hdr->left, tb[TCA_EM_META_LVALUE]) < 0) 523dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 524dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 525dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat switch (meta_hdr->left.op) { 526dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat case TCF_EM_OPND_EQ: 527dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(fd, " eq "); 528dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat break; 529dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat case TCF_EM_OPND_LT: 530dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(fd, " lt "); 531dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat break; 532dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat case TCF_EM_OPND_GT: 533dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(fd, " gt "); 534dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat break; 535dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 536dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 537dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return print_object(fd, &meta_hdr->right, tb[TCA_EM_META_RVALUE]); 538dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 539dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 540dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstruct ematch_util meta_ematch_util = { 541dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat .kind = "meta", 542dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat .kind_num = TCF_EM_META, 543dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat .parse_eopt = meta_parse_eopt, 544dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat .print_eopt = meta_print_eopt, 545dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat .print_usage = meta_print_usage 546dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}; 547