• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@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 
rtnl_ematch_nbyte_set_offset(struct rtnl_ematch * e,uint8_t layer,uint16_t offset)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 
rtnl_ematch_nbyte_get_offset(struct rtnl_ematch * e)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 
rtnl_ematch_nbyte_get_layer(struct rtnl_ematch * e)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 
rtnl_ematch_nbyte_set_pattern(struct rtnl_ematch * e,uint8_t * pattern,size_t len)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 
rtnl_ematch_nbyte_get_pattern(struct rtnl_ematch * e)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 
rtnl_ematch_nbyte_get_len(struct rtnl_ematch * e)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 
layer_txt(struct tcf_em_nbyte * nbyte)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 
nbyte_parse(struct rtnl_ematch * e,void * data,size_t len)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 
nbyte_dump(struct rtnl_ematch * e,struct nl_dump_params * p)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 
nbyte_free(struct rtnl_ematch * e)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 
nbyte_init(void)134 static void __init nbyte_init(void)
135 {
136 	rtnl_ematch_register(&nbyte_ops);
137 }
138 
139 /** @} */
140