1311b41454dc445639924c691a949bd15fbfab0cbshemminger/* 2bc45ded42ca835a735dcd934e69c17f90442d790Lionel Elie Mamane * em_cmp.c Simple comparison 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_cmp.h> 25311b41454dc445639924c691a949bd15fbfab0cbshemminger 26311b41454dc445639924c691a949bd15fbfab0cbshemmingerextern struct ematch_util cmp_ematch_util; 27311b41454dc445639924c691a949bd15fbfab0cbshemminger 28311b41454dc445639924c691a949bd15fbfab0cbshemmingerstatic void cmp_print_usage(FILE *fd) 29311b41454dc445639924c691a949bd15fbfab0cbshemminger{ 30311b41454dc445639924c691a949bd15fbfab0cbshemminger fprintf(fd, 31311b41454dc445639924c691a949bd15fbfab0cbshemminger "Usage: cmp(ALIGN at OFFSET [ ATTRS ] { eq | lt | gt } VALUE)\n" \ 32311b41454dc445639924c691a949bd15fbfab0cbshemminger "where: ALIGN := { u8 | u16 | u32 }\n" \ 33311b41454dc445639924c691a949bd15fbfab0cbshemminger " ATTRS := [ layer LAYER ] [ mask MASK ] [ trans ]\n" \ 34bc45ded42ca835a735dcd934e69c17f90442d790Lionel Elie Mamane " LAYER := { link | network | transport | 0..%d }\n" \ 35311b41454dc445639924c691a949bd15fbfab0cbshemminger "\n" \ 36311b41454dc445639924c691a949bd15fbfab0cbshemminger "Example: cmp(u16 at 3 layer 2 mask 0xff00 gt 20)\n", 37311b41454dc445639924c691a949bd15fbfab0cbshemminger TCF_LAYER_MAX); 38311b41454dc445639924c691a949bd15fbfab0cbshemminger} 39311b41454dc445639924c691a949bd15fbfab0cbshemminger 40311b41454dc445639924c691a949bd15fbfab0cbshemmingerstatic int cmp_parse_eopt(struct nlmsghdr *n, struct tcf_ematch_hdr *hdr, 41311b41454dc445639924c691a949bd15fbfab0cbshemminger struct bstr *args) 42311b41454dc445639924c691a949bd15fbfab0cbshemminger{ 43311b41454dc445639924c691a949bd15fbfab0cbshemminger struct bstr *a; 44311b41454dc445639924c691a949bd15fbfab0cbshemminger int align, opnd = 0; 45311b41454dc445639924c691a949bd15fbfab0cbshemminger unsigned long offset = 0, layer = TCF_LAYER_NETWORK, mask = 0, value = 0; 46311b41454dc445639924c691a949bd15fbfab0cbshemminger int offset_present = 0, value_present = 0; 47311b41454dc445639924c691a949bd15fbfab0cbshemminger struct tcf_em_cmp cmp; 48311b41454dc445639924c691a949bd15fbfab0cbshemminger 49311b41454dc445639924c691a949bd15fbfab0cbshemminger memset(&cmp, 0, sizeof(cmp)); 50311b41454dc445639924c691a949bd15fbfab0cbshemminger 51311b41454dc445639924c691a949bd15fbfab0cbshemminger#define PARSE_ERR(CARG, FMT, ARGS...) \ 52311b41454dc445639924c691a949bd15fbfab0cbshemminger em_parse_error(EINVAL, args, CARG, &cmp_ematch_util, FMT ,##ARGS) 53311b41454dc445639924c691a949bd15fbfab0cbshemminger 54311b41454dc445639924c691a949bd15fbfab0cbshemminger if (args == NULL) 55311b41454dc445639924c691a949bd15fbfab0cbshemminger return PARSE_ERR(args, "cmp: missing arguments"); 56311b41454dc445639924c691a949bd15fbfab0cbshemminger 57311b41454dc445639924c691a949bd15fbfab0cbshemminger if (!bstrcmp(args, "u8")) 58311b41454dc445639924c691a949bd15fbfab0cbshemminger align = TCF_EM_ALIGN_U8; 59311b41454dc445639924c691a949bd15fbfab0cbshemminger else if (!bstrcmp(args, "u16")) 60311b41454dc445639924c691a949bd15fbfab0cbshemminger align = TCF_EM_ALIGN_U16; 61311b41454dc445639924c691a949bd15fbfab0cbshemminger else if (!bstrcmp(args, "u32")) 62311b41454dc445639924c691a949bd15fbfab0cbshemminger align = TCF_EM_ALIGN_U32; 63311b41454dc445639924c691a949bd15fbfab0cbshemminger else 64311b41454dc445639924c691a949bd15fbfab0cbshemminger return PARSE_ERR(args, "cmp: invalid alignment"); 65ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger 66311b41454dc445639924c691a949bd15fbfab0cbshemminger for (a = bstr_next(args); a; a = bstr_next(a)) { 67311b41454dc445639924c691a949bd15fbfab0cbshemminger if (!bstrcmp(a, "at")) { 68311b41454dc445639924c691a949bd15fbfab0cbshemminger if (a->next == NULL) 69311b41454dc445639924c691a949bd15fbfab0cbshemminger return PARSE_ERR(a, "cmp: missing argument"); 70311b41454dc445639924c691a949bd15fbfab0cbshemminger a = bstr_next(a); 71311b41454dc445639924c691a949bd15fbfab0cbshemminger 72311b41454dc445639924c691a949bd15fbfab0cbshemminger offset = bstrtoul(a); 73311b41454dc445639924c691a949bd15fbfab0cbshemminger if (offset == ULONG_MAX) 74311b41454dc445639924c691a949bd15fbfab0cbshemminger return PARSE_ERR(a, "cmp: invalid offset, " \ 75311b41454dc445639924c691a949bd15fbfab0cbshemminger "must be numeric"); 76311b41454dc445639924c691a949bd15fbfab0cbshemminger 77311b41454dc445639924c691a949bd15fbfab0cbshemminger offset_present = 1; 78311b41454dc445639924c691a949bd15fbfab0cbshemminger } else if (!bstrcmp(a, "layer")) { 79311b41454dc445639924c691a949bd15fbfab0cbshemminger if (a->next == NULL) 80311b41454dc445639924c691a949bd15fbfab0cbshemminger return PARSE_ERR(a, "cmp: missing argument"); 81311b41454dc445639924c691a949bd15fbfab0cbshemminger a = bstr_next(a); 82311b41454dc445639924c691a949bd15fbfab0cbshemminger 83311b41454dc445639924c691a949bd15fbfab0cbshemminger layer = parse_layer(a); 84311b41454dc445639924c691a949bd15fbfab0cbshemminger if (layer == INT_MAX) { 85311b41454dc445639924c691a949bd15fbfab0cbshemminger layer = bstrtoul(a); 86311b41454dc445639924c691a949bd15fbfab0cbshemminger if (layer == ULONG_MAX) 87311b41454dc445639924c691a949bd15fbfab0cbshemminger return PARSE_ERR(a, "cmp: invalid " \ 88311b41454dc445639924c691a949bd15fbfab0cbshemminger "layer"); 89311b41454dc445639924c691a949bd15fbfab0cbshemminger } 90311b41454dc445639924c691a949bd15fbfab0cbshemminger 91311b41454dc445639924c691a949bd15fbfab0cbshemminger if (layer > TCF_LAYER_MAX) 92311b41454dc445639924c691a949bd15fbfab0cbshemminger return PARSE_ERR(a, "cmp: illegal layer, " \ 93311b41454dc445639924c691a949bd15fbfab0cbshemminger "must be in 0..%d", TCF_LAYER_MAX); 94311b41454dc445639924c691a949bd15fbfab0cbshemminger } else if (!bstrcmp(a, "mask")) { 95311b41454dc445639924c691a949bd15fbfab0cbshemminger if (a->next == NULL) 96311b41454dc445639924c691a949bd15fbfab0cbshemminger return PARSE_ERR(a, "cmp: missing argument"); 97311b41454dc445639924c691a949bd15fbfab0cbshemminger a = bstr_next(a); 98311b41454dc445639924c691a949bd15fbfab0cbshemminger 99311b41454dc445639924c691a949bd15fbfab0cbshemminger mask = bstrtoul(a); 100311b41454dc445639924c691a949bd15fbfab0cbshemminger if (mask == ULONG_MAX) 101311b41454dc445639924c691a949bd15fbfab0cbshemminger return PARSE_ERR(a, "cmp: invalid mask"); 102311b41454dc445639924c691a949bd15fbfab0cbshemminger } else if (!bstrcmp(a, "trans")) { 103311b41454dc445639924c691a949bd15fbfab0cbshemminger cmp.flags |= TCF_EM_CMP_TRANS; 104311b41454dc445639924c691a949bd15fbfab0cbshemminger } else if (!bstrcmp(a, "eq") || !bstrcmp(a, "gt") || 105311b41454dc445639924c691a949bd15fbfab0cbshemminger !bstrcmp(a, "lt")) { 106311b41454dc445639924c691a949bd15fbfab0cbshemminger 107311b41454dc445639924c691a949bd15fbfab0cbshemminger if (!bstrcmp(a, "eq")) 108311b41454dc445639924c691a949bd15fbfab0cbshemminger opnd = TCF_EM_OPND_EQ; 109311b41454dc445639924c691a949bd15fbfab0cbshemminger else if (!bstrcmp(a, "gt")) 110311b41454dc445639924c691a949bd15fbfab0cbshemminger opnd = TCF_EM_OPND_GT; 111311b41454dc445639924c691a949bd15fbfab0cbshemminger else if (!bstrcmp(a, "lt")) 112311b41454dc445639924c691a949bd15fbfab0cbshemminger opnd = TCF_EM_OPND_LT; 113ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger 114311b41454dc445639924c691a949bd15fbfab0cbshemminger if (a->next == NULL) 115311b41454dc445639924c691a949bd15fbfab0cbshemminger return PARSE_ERR(a, "cmp: missing argument"); 116311b41454dc445639924c691a949bd15fbfab0cbshemminger a = bstr_next(a); 117311b41454dc445639924c691a949bd15fbfab0cbshemminger 118311b41454dc445639924c691a949bd15fbfab0cbshemminger value = bstrtoul(a); 119311b41454dc445639924c691a949bd15fbfab0cbshemminger if (value == ULONG_MAX) 120311b41454dc445639924c691a949bd15fbfab0cbshemminger return PARSE_ERR(a, "cmp: invalid value"); 121311b41454dc445639924c691a949bd15fbfab0cbshemminger 122311b41454dc445639924c691a949bd15fbfab0cbshemminger value_present = 1; 123311b41454dc445639924c691a949bd15fbfab0cbshemminger } else 124311b41454dc445639924c691a949bd15fbfab0cbshemminger return PARSE_ERR(a, "nbyte: unknown parameter"); 125311b41454dc445639924c691a949bd15fbfab0cbshemminger } 126311b41454dc445639924c691a949bd15fbfab0cbshemminger 127311b41454dc445639924c691a949bd15fbfab0cbshemminger if (offset_present == 0 || value_present == 0) 128311b41454dc445639924c691a949bd15fbfab0cbshemminger return PARSE_ERR(a, "cmp: offset and value required"); 129311b41454dc445639924c691a949bd15fbfab0cbshemminger 130311b41454dc445639924c691a949bd15fbfab0cbshemminger cmp.val = (__u32) value; 131311b41454dc445639924c691a949bd15fbfab0cbshemminger cmp.mask = (__u32) mask; 132311b41454dc445639924c691a949bd15fbfab0cbshemminger cmp.off = (__u16) offset; 133311b41454dc445639924c691a949bd15fbfab0cbshemminger cmp.align = (__u8) align; 134311b41454dc445639924c691a949bd15fbfab0cbshemminger cmp.layer = (__u8) layer; 135311b41454dc445639924c691a949bd15fbfab0cbshemminger cmp.opnd = (__u8) opnd; 136311b41454dc445639924c691a949bd15fbfab0cbshemminger 137311b41454dc445639924c691a949bd15fbfab0cbshemminger addraw_l(n, MAX_MSG, hdr, sizeof(*hdr)); 138311b41454dc445639924c691a949bd15fbfab0cbshemminger addraw_l(n, MAX_MSG, &cmp, sizeof(cmp)); 139311b41454dc445639924c691a949bd15fbfab0cbshemminger 140311b41454dc445639924c691a949bd15fbfab0cbshemminger#undef PARSE_ERR 141311b41454dc445639924c691a949bd15fbfab0cbshemminger return 0; 142311b41454dc445639924c691a949bd15fbfab0cbshemminger} 143311b41454dc445639924c691a949bd15fbfab0cbshemminger 144311b41454dc445639924c691a949bd15fbfab0cbshemmingerstatic int cmp_print_eopt(FILE *fd, struct tcf_ematch_hdr *hdr, void *data, 145311b41454dc445639924c691a949bd15fbfab0cbshemminger int data_len) 146311b41454dc445639924c691a949bd15fbfab0cbshemminger{ 147311b41454dc445639924c691a949bd15fbfab0cbshemminger struct tcf_em_cmp *cmp = data; 148311b41454dc445639924c691a949bd15fbfab0cbshemminger 149311b41454dc445639924c691a949bd15fbfab0cbshemminger if (data_len < sizeof(*cmp)) { 150311b41454dc445639924c691a949bd15fbfab0cbshemminger fprintf(stderr, "CMP header size mismatch\n"); 151311b41454dc445639924c691a949bd15fbfab0cbshemminger return -1; 152311b41454dc445639924c691a949bd15fbfab0cbshemminger } 153311b41454dc445639924c691a949bd15fbfab0cbshemminger 154311b41454dc445639924c691a949bd15fbfab0cbshemminger if (cmp->align == TCF_EM_ALIGN_U8) 155311b41454dc445639924c691a949bd15fbfab0cbshemminger fprintf(fd, "u8 "); 156311b41454dc445639924c691a949bd15fbfab0cbshemminger else if (cmp->align == TCF_EM_ALIGN_U16) 157311b41454dc445639924c691a949bd15fbfab0cbshemminger fprintf(fd, "u16 "); 1586d5ee98a7c47644308ccb167faa93e07bb702fd8Thomas Jarosch else if (cmp->align == TCF_EM_ALIGN_U32) 159311b41454dc445639924c691a949bd15fbfab0cbshemminger fprintf(fd, "u32 "); 160311b41454dc445639924c691a949bd15fbfab0cbshemminger 161311b41454dc445639924c691a949bd15fbfab0cbshemminger fprintf(fd, "at %d layer %d ", cmp->off, cmp->layer); 162311b41454dc445639924c691a949bd15fbfab0cbshemminger 163311b41454dc445639924c691a949bd15fbfab0cbshemminger if (cmp->mask) 164311b41454dc445639924c691a949bd15fbfab0cbshemminger fprintf(fd, "mask 0x%x ", cmp->mask); 165311b41454dc445639924c691a949bd15fbfab0cbshemminger 166311b41454dc445639924c691a949bd15fbfab0cbshemminger if (cmp->flags & TCF_EM_CMP_TRANS) 167311b41454dc445639924c691a949bd15fbfab0cbshemminger fprintf(fd, "trans "); 168311b41454dc445639924c691a949bd15fbfab0cbshemminger 169311b41454dc445639924c691a949bd15fbfab0cbshemminger if (cmp->opnd == TCF_EM_OPND_EQ) 170311b41454dc445639924c691a949bd15fbfab0cbshemminger fprintf(fd, "eq "); 171311b41454dc445639924c691a949bd15fbfab0cbshemminger else if (cmp->opnd == TCF_EM_OPND_LT) 172311b41454dc445639924c691a949bd15fbfab0cbshemminger fprintf(fd, "lt "); 173311b41454dc445639924c691a949bd15fbfab0cbshemminger else if (cmp->opnd == TCF_EM_OPND_GT) 174311b41454dc445639924c691a949bd15fbfab0cbshemminger fprintf(fd, "gt "); 175311b41454dc445639924c691a949bd15fbfab0cbshemminger 176311b41454dc445639924c691a949bd15fbfab0cbshemminger fprintf(fd, "%d", cmp->val); 177311b41454dc445639924c691a949bd15fbfab0cbshemminger 178311b41454dc445639924c691a949bd15fbfab0cbshemminger return 0; 179311b41454dc445639924c691a949bd15fbfab0cbshemminger} 180311b41454dc445639924c691a949bd15fbfab0cbshemminger 181311b41454dc445639924c691a949bd15fbfab0cbshemmingerstruct ematch_util cmp_ematch_util = { 182311b41454dc445639924c691a949bd15fbfab0cbshemminger .kind = "cmp", 183311b41454dc445639924c691a949bd15fbfab0cbshemminger .kind_num = TCF_EM_CMP, 184311b41454dc445639924c691a949bd15fbfab0cbshemminger .parse_eopt = cmp_parse_eopt, 185311b41454dc445639924c691a949bd15fbfab0cbshemminger .print_eopt = cmp_print_eopt, 186311b41454dc445639924c691a949bd15fbfab0cbshemminger .print_usage = cmp_print_usage 187311b41454dc445639924c691a949bd15fbfab0cbshemminger}; 188