libnl  3.2.24-rc1
nbyte.c
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 
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 /** @} */