1 /* 2 * lib/route/cls/ematch/nbyte.c Nbyte comparison 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation version 2.1 7 * of the License. 8 * 9 * Copyright (c) 2010-2013 Thomas Graf <tgraf (at) suug.ch> 10 */ 11 12 /** 13 * @ingroup ematch 14 * @defgroup em_nbyte N-Byte Comparison 15 * 16 * @{ 17 */ 18 19 #include <netlink-private/netlink.h> 20 #include <netlink-private/tc.h> 21 #include <netlink/netlink.h> 22 #include <netlink/route/cls/ematch.h> 23 #include <netlink/route/cls/ematch/nbyte.h> 24 25 struct nbyte_data 26 { 27 struct tcf_em_nbyte cfg; 28 uint8_t * pattern; 29 }; 30 31 void rtnl_ematch_nbyte_set_offset(struct rtnl_ematch *e, uint8_t layer, 32 uint16_t offset) 33 { 34 struct nbyte_data *n = rtnl_ematch_data(e); 35 n->cfg.off = offset; 36 n->cfg.layer = layer; 37 } 38 39 uint16_t rtnl_ematch_nbyte_get_offset(struct rtnl_ematch *e) 40 { 41 return ((struct nbyte_data *) rtnl_ematch_data(e))->cfg.off; 42 } 43 44 uint8_t rtnl_ematch_nbyte_get_layer(struct rtnl_ematch *e) 45 { 46 return ((struct nbyte_data *) rtnl_ematch_data(e))->cfg.layer; 47 } 48 49 void rtnl_ematch_nbyte_set_pattern(struct rtnl_ematch *e, 50 uint8_t *pattern, size_t len) 51 { 52 struct nbyte_data *n = rtnl_ematch_data(e); 53 54 if (n->pattern) 55 free(n->pattern); 56 57 n->pattern = pattern; 58 n->cfg.len = len; 59 } 60 61 uint8_t *rtnl_ematch_nbyte_get_pattern(struct rtnl_ematch *e) 62 { 63 return ((struct nbyte_data *) rtnl_ematch_data(e))->pattern; 64 } 65 66 size_t rtnl_ematch_nbyte_get_len(struct rtnl_ematch *e) 67 { 68 return ((struct nbyte_data *) rtnl_ematch_data(e))->cfg.len; 69 } 70 71 static const char *layer_txt(struct tcf_em_nbyte *nbyte) 72 { 73 switch (nbyte->layer) { 74 case TCF_LAYER_LINK: 75 return "link"; 76 case TCF_LAYER_NETWORK: 77 return "net"; 78 case TCF_LAYER_TRANSPORT: 79 return "trans"; 80 default: 81 return "?"; 82 } 83 } 84 85 static int nbyte_parse(struct rtnl_ematch *e, void *data, size_t len) 86 { 87 struct nbyte_data *n = rtnl_ematch_data(e); 88 size_t hdrlen = sizeof(struct tcf_em_nbyte); 89 size_t plen = len - hdrlen; 90 91 memcpy(&n->cfg, data, hdrlen); 92 if (plen > 0) { 93 if (!(n->pattern = calloc(1, plen))) 94 return -NLE_NOMEM; 95 96 memcpy(n->pattern, data + hdrlen, plen); 97 } 98 99 return 0; 100 } 101 102 static void nbyte_dump(struct rtnl_ematch *e, struct nl_dump_params *p) 103 { 104 struct nbyte_data *n = rtnl_ematch_data(e); 105 int i; 106 107 nl_dump(p, "pattern(%u:[", n->cfg.len); 108 109 for (i = 0; i < n->cfg.len; i++) { 110 nl_dump(p, "%02x", n->pattern[i]); 111 if (i+1 < n->cfg.len) 112 nl_dump(p, " "); 113 } 114 115 nl_dump(p, "] at %s+%u)", layer_txt(&n->cfg), n->cfg.off); 116 } 117 118 static void nbyte_free(struct rtnl_ematch *e) 119 { 120 struct nbyte_data *n = rtnl_ematch_data(e); 121 free(n->pattern); 122 } 123 124 static struct rtnl_ematch_ops nbyte_ops = { 125 .eo_kind = TCF_EM_NBYTE, 126 .eo_name = "nbyte", 127 .eo_minlen = sizeof(struct tcf_em_nbyte), 128 .eo_datalen = sizeof(struct nbyte_data), 129 .eo_parse = nbyte_parse, 130 .eo_dump = nbyte_dump, 131 .eo_free = nbyte_free, 132 }; 133 134 static void __init nbyte_init(void) 135 { 136 rtnl_ematch_register(&nbyte_ops); 137 } 138 139 /** @} */ 140