Home | History | Annotate | Download | only in ematch
      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