00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <netlink-local.h>
00020 #include <netlink-tc.h>
00021 #include <netlink/netlink.h>
00022 #include <netlink/route/cls/ematch.h>
00023 #include <netlink/route/cls/ematch/nbyte.h>
00024
00025 struct nbyte_data
00026 {
00027 struct tcf_em_nbyte cfg;
00028 uint8_t * pattern;
00029 };
00030
00031 void rtnl_ematch_nbyte_set_offset(struct rtnl_ematch *e, uint8_t layer,
00032 uint16_t offset)
00033 {
00034 struct nbyte_data *n = rtnl_ematch_data(e);
00035 n->cfg.off = offset;
00036 n->cfg.layer = layer;
00037 }
00038
00039 uint16_t rtnl_ematch_nbyte_get_offset(struct rtnl_ematch *e)
00040 {
00041 return ((struct nbyte_data *) rtnl_ematch_data(e))->cfg.off;
00042 }
00043
00044 uint8_t rtnl_ematch_nbyte_get_layer(struct rtnl_ematch *e)
00045 {
00046 return ((struct nbyte_data *) rtnl_ematch_data(e))->cfg.layer;
00047 }
00048
00049 void rtnl_ematch_nbyte_set_pattern(struct rtnl_ematch *e,
00050 uint8_t *pattern, size_t len)
00051 {
00052 struct nbyte_data *n = rtnl_ematch_data(e);
00053
00054 if (n->pattern)
00055 free(n->pattern);
00056
00057 n->pattern = pattern;
00058 n->cfg.len = len;
00059 }
00060
00061 uint8_t *rtnl_ematch_nbyte_get_pattern(struct rtnl_ematch *e)
00062 {
00063 return ((struct nbyte_data *) rtnl_ematch_data(e))->pattern;
00064 }
00065
00066 size_t rtnl_ematch_nbyte_get_len(struct rtnl_ematch *e)
00067 {
00068 return ((struct nbyte_data *) rtnl_ematch_data(e))->cfg.len;
00069 }
00070
00071 static const char *layer_txt(struct tcf_em_nbyte *nbyte)
00072 {
00073 switch (nbyte->layer) {
00074 case TCF_LAYER_LINK:
00075 return "link";
00076 case TCF_LAYER_NETWORK:
00077 return "net";
00078 case TCF_LAYER_TRANSPORT:
00079 return "trans";
00080 default:
00081 return "?";
00082 }
00083 }
00084
00085 static int nbyte_parse(struct rtnl_ematch *e, void *data, size_t len)
00086 {
00087 struct nbyte_data *n = rtnl_ematch_data(e);
00088 size_t hdrlen = sizeof(struct tcf_em_nbyte);
00089 size_t plen = len - hdrlen;
00090
00091 memcpy(&n->cfg, data, hdrlen);
00092 if (plen > 0) {
00093 if (!(n->pattern = calloc(1, plen)))
00094 return -NLE_NOMEM;
00095
00096 memcpy(n->pattern, data + hdrlen, plen);
00097 }
00098
00099 return 0;
00100 }
00101
00102 static void nbyte_dump(struct rtnl_ematch *e, struct nl_dump_params *p)
00103 {
00104 struct nbyte_data *n = rtnl_ematch_data(e);
00105 int i;
00106
00107 nl_dump(p, "pattern(%u:[", n->cfg.len);
00108
00109 for (i = 0; i < n->cfg.len; i++) {
00110 nl_dump(p, "%02x", n->pattern[i]);
00111 if (i+1 < n->cfg.len)
00112 nl_dump(p, " ");
00113 }
00114
00115 nl_dump(p, "] at %s+%u)", layer_txt(&n->cfg), n->cfg.off);
00116 }
00117
00118 static void nbyte_free(struct rtnl_ematch *e)
00119 {
00120 struct nbyte_data *n = rtnl_ematch_data(e);
00121 free(n->pattern);
00122 }
00123
00124 static struct rtnl_ematch_ops nbyte_ops = {
00125 .eo_kind = TCF_EM_NBYTE,
00126 .eo_name = "nbyte",
00127 .eo_minlen = sizeof(struct tcf_em_nbyte),
00128 .eo_datalen = sizeof(struct nbyte_data),
00129 .eo_parse = nbyte_parse,
00130 .eo_dump = nbyte_dump,
00131 .eo_free = nbyte_free,
00132 };
00133
00134 static void __init nbyte_init(void)
00135 {
00136 rtnl_ematch_register(&nbyte_ops);
00137 }
00138
00139