nbyte.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  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. * @ingroup ematch
  13. * @defgroup em_nbyte N-Byte Comparison
  14. *
  15. * @{
  16. */
  17. #include <netlink-private/netlink.h>
  18. #include <netlink-private/tc.h>
  19. #include <netlink/netlink.h>
  20. #include <netlink/route/cls/ematch.h>
  21. #include <netlink/route/cls/ematch/nbyte.h>
  22. struct nbyte_data
  23. {
  24. struct tcf_em_nbyte cfg;
  25. uint8_t * pattern;
  26. };
  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. uint16_t rtnl_ematch_nbyte_get_offset(struct rtnl_ematch *e)
  35. {
  36. return ((struct nbyte_data *) rtnl_ematch_data(e))->cfg.off;
  37. }
  38. uint8_t rtnl_ematch_nbyte_get_layer(struct rtnl_ematch *e)
  39. {
  40. return ((struct nbyte_data *) rtnl_ematch_data(e))->cfg.layer;
  41. }
  42. void rtnl_ematch_nbyte_set_pattern(struct rtnl_ematch *e,
  43. uint8_t *pattern, size_t len)
  44. {
  45. struct nbyte_data *n = rtnl_ematch_data(e);
  46. if (n->pattern)
  47. free(n->pattern);
  48. n->pattern = pattern;
  49. n->cfg.len = len;
  50. }
  51. uint8_t *rtnl_ematch_nbyte_get_pattern(struct rtnl_ematch *e)
  52. {
  53. return ((struct nbyte_data *) rtnl_ematch_data(e))->pattern;
  54. }
  55. size_t rtnl_ematch_nbyte_get_len(struct rtnl_ematch *e)
  56. {
  57. return ((struct nbyte_data *) rtnl_ematch_data(e))->cfg.len;
  58. }
  59. static const char *layer_txt(struct tcf_em_nbyte *nbyte)
  60. {
  61. switch (nbyte->layer) {
  62. case TCF_LAYER_LINK:
  63. return "link";
  64. case TCF_LAYER_NETWORK:
  65. return "net";
  66. case TCF_LAYER_TRANSPORT:
  67. return "trans";
  68. default:
  69. return "?";
  70. }
  71. }
  72. static int nbyte_parse(struct rtnl_ematch *e, void *data, size_t len)
  73. {
  74. struct nbyte_data *n = rtnl_ematch_data(e);
  75. size_t hdrlen = sizeof(struct tcf_em_nbyte);
  76. size_t plen = len - hdrlen;
  77. memcpy(&n->cfg, data, hdrlen);
  78. if (plen > 0) {
  79. if (!(n->pattern = calloc(1, plen)))
  80. return -NLE_NOMEM;
  81. memcpy(n->pattern, data + hdrlen, plen);
  82. }
  83. return 0;
  84. }
  85. static void nbyte_dump(struct rtnl_ematch *e, struct nl_dump_params *p)
  86. {
  87. struct nbyte_data *n = rtnl_ematch_data(e);
  88. int i;
  89. nl_dump(p, "pattern(%u:[", n->cfg.len);
  90. for (i = 0; i < n->cfg.len; i++) {
  91. nl_dump(p, "%02x", n->pattern[i]);
  92. if (i+1 < n->cfg.len)
  93. nl_dump(p, " ");
  94. }
  95. nl_dump(p, "] at %s+%u)", layer_txt(&n->cfg), n->cfg.off);
  96. }
  97. static void nbyte_free(struct rtnl_ematch *e)
  98. {
  99. struct nbyte_data *n = rtnl_ematch_data(e);
  100. free(n->pattern);
  101. }
  102. static struct rtnl_ematch_ops nbyte_ops = {
  103. .eo_kind = TCF_EM_NBYTE,
  104. .eo_name = "nbyte",
  105. .eo_minlen = sizeof(struct tcf_em_nbyte),
  106. .eo_datalen = sizeof(struct nbyte_data),
  107. .eo_parse = nbyte_parse,
  108. .eo_dump = nbyte_dump,
  109. .eo_free = nbyte_free,
  110. };
  111. static void __init nbyte_init(void)
  112. {
  113. rtnl_ematch_register(&nbyte_ops);
  114. }
  115. /** @} */