1311b41454dc445639924c691a949bd15fbfab0cbshemminger/* 2311b41454dc445639924c691a949bd15fbfab0cbshemminger * em_nbyte.c N-Byte 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_nbyte.h> 25311b41454dc445639924c691a949bd15fbfab0cbshemminger 26311b41454dc445639924c691a949bd15fbfab0cbshemmingerextern struct ematch_util nbyte_ematch_util; 27311b41454dc445639924c691a949bd15fbfab0cbshemminger 28311b41454dc445639924c691a949bd15fbfab0cbshemmingerstatic void nbyte_print_usage(FILE *fd) 29311b41454dc445639924c691a949bd15fbfab0cbshemminger{ 30311b41454dc445639924c691a949bd15fbfab0cbshemminger fprintf(fd, 31311b41454dc445639924c691a949bd15fbfab0cbshemminger "Usage: nbyte(NEEDLE at OFFSET [layer LAYER])\n" \ 32311b41454dc445639924c691a949bd15fbfab0cbshemminger "where: NEEDLE := { string | \"c-escape-sequence\" }\n" \ 33311b41454dc445639924c691a949bd15fbfab0cbshemminger " OFFSET := int\n" \ 34bc45ded42ca835a735dcd934e69c17f90442d790Lionel Elie Mamane " LAYER := { link | network | transport | 0..%d }\n" \ 35311b41454dc445639924c691a949bd15fbfab0cbshemminger "\n" \ 36311b41454dc445639924c691a949bd15fbfab0cbshemminger "Example: nbyte(\"ababa\" at 12 layer 1)\n", 37311b41454dc445639924c691a949bd15fbfab0cbshemminger TCF_LAYER_MAX); 38311b41454dc445639924c691a949bd15fbfab0cbshemminger} 39311b41454dc445639924c691a949bd15fbfab0cbshemminger 40311b41454dc445639924c691a949bd15fbfab0cbshemmingerstatic int nbyte_parse_eopt(struct nlmsghdr *n, struct tcf_ematch_hdr *hdr, 41311b41454dc445639924c691a949bd15fbfab0cbshemminger struct bstr *args) 42311b41454dc445639924c691a949bd15fbfab0cbshemminger{ 43311b41454dc445639924c691a949bd15fbfab0cbshemminger struct bstr *a; 44311b41454dc445639924c691a949bd15fbfab0cbshemminger struct bstr *needle = args; 45311b41454dc445639924c691a949bd15fbfab0cbshemminger unsigned long offset = 0, layer = TCF_LAYER_NETWORK; 46311b41454dc445639924c691a949bd15fbfab0cbshemminger int offset_present = 0; 47311b41454dc445639924c691a949bd15fbfab0cbshemminger struct tcf_em_nbyte nb; 48311b41454dc445639924c691a949bd15fbfab0cbshemminger 49311b41454dc445639924c691a949bd15fbfab0cbshemminger memset(&nb, 0, sizeof(nb)); 50311b41454dc445639924c691a949bd15fbfab0cbshemminger 51311b41454dc445639924c691a949bd15fbfab0cbshemminger#define PARSE_ERR(CARG, FMT, ARGS...) \ 52311b41454dc445639924c691a949bd15fbfab0cbshemminger em_parse_error(EINVAL, args, CARG, &nbyte_ematch_util, FMT ,##ARGS) 53311b41454dc445639924c691a949bd15fbfab0cbshemminger 54311b41454dc445639924c691a949bd15fbfab0cbshemminger if (args == NULL) 55311b41454dc445639924c691a949bd15fbfab0cbshemminger return PARSE_ERR(args, "nbyte: missing arguments"); 56311b41454dc445639924c691a949bd15fbfab0cbshemminger 57311b41454dc445639924c691a949bd15fbfab0cbshemminger if (needle->len <= 0) 58311b41454dc445639924c691a949bd15fbfab0cbshemminger return PARSE_ERR(args, "nbyte: needle length is 0"); 59311b41454dc445639924c691a949bd15fbfab0cbshemminger 60311b41454dc445639924c691a949bd15fbfab0cbshemminger for (a = bstr_next(args); a; a = bstr_next(a)) { 61311b41454dc445639924c691a949bd15fbfab0cbshemminger if (!bstrcmp(a, "at")) { 62311b41454dc445639924c691a949bd15fbfab0cbshemminger if (a->next == NULL) 63311b41454dc445639924c691a949bd15fbfab0cbshemminger return PARSE_ERR(a, "nbyte: missing argument"); 64311b41454dc445639924c691a949bd15fbfab0cbshemminger a = bstr_next(a); 65311b41454dc445639924c691a949bd15fbfab0cbshemminger 66311b41454dc445639924c691a949bd15fbfab0cbshemminger offset = bstrtoul(a); 67311b41454dc445639924c691a949bd15fbfab0cbshemminger if (offset == ULONG_MAX) 68311b41454dc445639924c691a949bd15fbfab0cbshemminger return PARSE_ERR(a, "nbyte: invalid offset, " \ 69311b41454dc445639924c691a949bd15fbfab0cbshemminger "must be numeric"); 70311b41454dc445639924c691a949bd15fbfab0cbshemminger 71311b41454dc445639924c691a949bd15fbfab0cbshemminger offset_present = 1; 72311b41454dc445639924c691a949bd15fbfab0cbshemminger } else if (!bstrcmp(a, "layer")) { 73311b41454dc445639924c691a949bd15fbfab0cbshemminger if (a->next == NULL) 74311b41454dc445639924c691a949bd15fbfab0cbshemminger return PARSE_ERR(a, "nbyte: missing argument"); 75311b41454dc445639924c691a949bd15fbfab0cbshemminger a = bstr_next(a); 76311b41454dc445639924c691a949bd15fbfab0cbshemminger 77311b41454dc445639924c691a949bd15fbfab0cbshemminger layer = parse_layer(a); 78311b41454dc445639924c691a949bd15fbfab0cbshemminger if (layer == INT_MAX) { 79311b41454dc445639924c691a949bd15fbfab0cbshemminger layer = bstrtoul(a); 80311b41454dc445639924c691a949bd15fbfab0cbshemminger if (layer == ULONG_MAX) 81311b41454dc445639924c691a949bd15fbfab0cbshemminger return PARSE_ERR(a, "nbyte: invalid " \ 82311b41454dc445639924c691a949bd15fbfab0cbshemminger "layer"); 83311b41454dc445639924c691a949bd15fbfab0cbshemminger } 84311b41454dc445639924c691a949bd15fbfab0cbshemminger 85311b41454dc445639924c691a949bd15fbfab0cbshemminger if (layer > TCF_LAYER_MAX) 86311b41454dc445639924c691a949bd15fbfab0cbshemminger return PARSE_ERR(a, "nbyte: illegal layer, " \ 87311b41454dc445639924c691a949bd15fbfab0cbshemminger "must be in 0..%d", TCF_LAYER_MAX); 88311b41454dc445639924c691a949bd15fbfab0cbshemminger } else 89311b41454dc445639924c691a949bd15fbfab0cbshemminger return PARSE_ERR(a, "nbyte: unknown parameter"); 90311b41454dc445639924c691a949bd15fbfab0cbshemminger } 91311b41454dc445639924c691a949bd15fbfab0cbshemminger 92311b41454dc445639924c691a949bd15fbfab0cbshemminger if (offset_present == 0) 93311b41454dc445639924c691a949bd15fbfab0cbshemminger return PARSE_ERR(a, "nbyte: offset required"); 94ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger 95311b41454dc445639924c691a949bd15fbfab0cbshemminger nb.len = needle->len; 96311b41454dc445639924c691a949bd15fbfab0cbshemminger nb.layer = (__u8) layer; 97311b41454dc445639924c691a949bd15fbfab0cbshemminger nb.off = (__u16) offset; 98311b41454dc445639924c691a949bd15fbfab0cbshemminger 99311b41454dc445639924c691a949bd15fbfab0cbshemminger addraw_l(n, MAX_MSG, hdr, sizeof(*hdr)); 100311b41454dc445639924c691a949bd15fbfab0cbshemminger addraw_l(n, MAX_MSG, &nb, sizeof(nb)); 101311b41454dc445639924c691a949bd15fbfab0cbshemminger addraw_l(n, MAX_MSG, needle->data, needle->len); 102311b41454dc445639924c691a949bd15fbfab0cbshemminger 103311b41454dc445639924c691a949bd15fbfab0cbshemminger#undef PARSE_ERR 104311b41454dc445639924c691a949bd15fbfab0cbshemminger return 0; 105311b41454dc445639924c691a949bd15fbfab0cbshemminger} 106311b41454dc445639924c691a949bd15fbfab0cbshemminger 107311b41454dc445639924c691a949bd15fbfab0cbshemmingerstatic int nbyte_print_eopt(FILE *fd, struct tcf_ematch_hdr *hdr, void *data, 108311b41454dc445639924c691a949bd15fbfab0cbshemminger int data_len) 109311b41454dc445639924c691a949bd15fbfab0cbshemminger{ 110311b41454dc445639924c691a949bd15fbfab0cbshemminger int i; 111311b41454dc445639924c691a949bd15fbfab0cbshemminger struct tcf_em_nbyte *nb = data; 112311b41454dc445639924c691a949bd15fbfab0cbshemminger __u8 *needle; 113311b41454dc445639924c691a949bd15fbfab0cbshemminger 114311b41454dc445639924c691a949bd15fbfab0cbshemminger if (data_len < sizeof(*nb)) { 115311b41454dc445639924c691a949bd15fbfab0cbshemminger fprintf(stderr, "NByte header size mismatch\n"); 116311b41454dc445639924c691a949bd15fbfab0cbshemminger return -1; 117311b41454dc445639924c691a949bd15fbfab0cbshemminger } 118311b41454dc445639924c691a949bd15fbfab0cbshemminger 119311b41454dc445639924c691a949bd15fbfab0cbshemminger if (data_len < sizeof(*nb) + nb->len) { 120311b41454dc445639924c691a949bd15fbfab0cbshemminger fprintf(stderr, "NByte payload size mismatch\n"); 121311b41454dc445639924c691a949bd15fbfab0cbshemminger return -1; 122311b41454dc445639924c691a949bd15fbfab0cbshemminger } 123311b41454dc445639924c691a949bd15fbfab0cbshemminger 124311b41454dc445639924c691a949bd15fbfab0cbshemminger needle = data + sizeof(*nb); 125311b41454dc445639924c691a949bd15fbfab0cbshemminger 126311b41454dc445639924c691a949bd15fbfab0cbshemminger for (i = 0; i < nb->len; i++) 127311b41454dc445639924c691a949bd15fbfab0cbshemminger fprintf(fd, "%02x ", needle[i]); 128311b41454dc445639924c691a949bd15fbfab0cbshemminger 129311b41454dc445639924c691a949bd15fbfab0cbshemminger fprintf(fd, "\""); 130311b41454dc445639924c691a949bd15fbfab0cbshemminger for (i = 0; i < nb->len; i++) 131311b41454dc445639924c691a949bd15fbfab0cbshemminger fprintf(fd, "%c", isprint(needle[i]) ? needle[i] : '.'); 132311b41454dc445639924c691a949bd15fbfab0cbshemminger fprintf(fd, "\" at %d layer %d", nb->off, nb->layer); 133ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger 134311b41454dc445639924c691a949bd15fbfab0cbshemminger return 0; 135311b41454dc445639924c691a949bd15fbfab0cbshemminger} 136311b41454dc445639924c691a949bd15fbfab0cbshemminger 137311b41454dc445639924c691a949bd15fbfab0cbshemmingerstruct ematch_util nbyte_ematch_util = { 138311b41454dc445639924c691a949bd15fbfab0cbshemminger .kind = "nbyte", 139311b41454dc445639924c691a949bd15fbfab0cbshemminger .kind_num = TCF_EM_NBYTE, 140311b41454dc445639924c691a949bd15fbfab0cbshemminger .parse_eopt = nbyte_parse_eopt, 141311b41454dc445639924c691a949bd15fbfab0cbshemminger .print_eopt = nbyte_print_eopt, 142311b41454dc445639924c691a949bd15fbfab0cbshemminger .print_usage = nbyte_print_usage 143311b41454dc445639924c691a949bd15fbfab0cbshemminger}; 144