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