ematch_syntax.y 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501
  1. /*
  2. * lib/route/cls/ematch_syntax.y ematch expression syntax
  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. #include <netlink-private/netlink.h>
  13. #include <netlink-private/tc.h>
  14. #include <netlink/netlink.h>
  15. #include <netlink/utils.h>
  16. #include <netlink/route/pktloc.h>
  17. #include <netlink/route/cls/ematch.h>
  18. #include <netlink/route/cls/ematch/cmp.h>
  19. #include <netlink/route/cls/ematch/nbyte.h>
  20. #include <netlink/route/cls/ematch/text.h>
  21. #include <netlink/route/cls/ematch/meta.h>
  22. #define META_ALLOC rtnl_meta_value_alloc_id
  23. #define META_ID(name) TCF_META_ID_##name
  24. #define META_INT TCF_META_TYPE_INT
  25. #define META_VAR TCF_META_TYPE_VAR
  26. %}
  27. %error-verbose
  28. %define api.pure
  29. %name-prefix "ematch_"
  30. %parse-param {void *scanner}
  31. %parse-param {char **errp}
  32. %parse-param {struct nl_list_head *root}
  33. %lex-param {void *scanner}
  34. %union {
  35. struct tcf_em_cmp cmp;
  36. struct ematch_quoted q;
  37. struct rtnl_ematch * e;
  38. struct rtnl_pktloc * loc;
  39. struct rtnl_meta_value *mv;
  40. uint32_t i;
  41. uint64_t i64;
  42. char * s;
  43. }
  44. %{
  45. extern int ematch_lex(YYSTYPE *, void *);
  46. static void yyerror(void *scanner, char **errp, struct nl_list_head *root, const char *msg)
  47. {
  48. if (msg)
  49. *errp = strdup(msg);
  50. else
  51. *errp = NULL;
  52. }
  53. %}
  54. %token <i> ERROR LOGIC NOT OPERAND NUMBER ALIGN LAYER
  55. %token <i> KW_OPEN "("
  56. %token <i> KW_CLOSE ")"
  57. %token <i> KW_PLUS "+"
  58. %token <i> KW_MASK "mask"
  59. %token <i> KW_SHIFT ">>"
  60. %token <i> KW_AT "at"
  61. %token <i> EMATCH_CMP "cmp"
  62. %token <i> EMATCH_NBYTE "pattern"
  63. %token <i> EMATCH_TEXT "text"
  64. %token <i> EMATCH_META "meta"
  65. %token <i> KW_EQ "="
  66. %token <i> KW_GT ">"
  67. %token <i> KW_LT "<"
  68. %token <i> KW_FROM "from"
  69. %token <i> KW_TO "to"
  70. %token <i> META_RANDOM "random"
  71. %token <i> META_LOADAVG_0 "loadavg_0"
  72. %token <i> META_LOADAVG_1 "loadavg_1"
  73. %token <i> META_LOADAVG_2 "loadavg_2"
  74. %token <i> META_DEV "dev"
  75. %token <i> META_PRIO "prio"
  76. %token <i> META_PROTO "proto"
  77. %token <i> META_PKTTYPE "pkttype"
  78. %token <i> META_PKTLEN "pktlen"
  79. %token <i> META_DATALEN "datalen"
  80. %token <i> META_MACLEN "maclen"
  81. %token <i> META_MARK "mark"
  82. %token <i> META_TCINDEX "tcindex"
  83. %token <i> META_RTCLASSID "rtclassid"
  84. %token <i> META_RTIIF "rtiif"
  85. %token <i> META_SK_FAMILY "sk_family"
  86. %token <i> META_SK_STATE "sk_state"
  87. %token <i> META_SK_REUSE "sk_reuse"
  88. %token <i> META_SK_REFCNT "sk_refcnt"
  89. %token <i> META_SK_RCVBUF "sk_rcvbuf"
  90. %token <i> META_SK_SNDBUF "sk_sndbuf"
  91. %token <i> META_SK_SHUTDOWN "sk_shutdown"
  92. %token <i> META_SK_PROTO "sk_proto"
  93. %token <i> META_SK_TYPE "sk_type"
  94. %token <i> META_SK_RMEM_ALLOC "sk_rmem_alloc"
  95. %token <i> META_SK_WMEM_ALLOC "sk_wmem_alloc"
  96. %token <i> META_SK_WMEM_QUEUED "sk_wmem_queued"
  97. %token <i> META_SK_RCV_QLEN "sk_rcv_qlen"
  98. %token <i> META_SK_SND_QLEN "sk_snd_qlen"
  99. %token <i> META_SK_ERR_QLEN "sk_err_qlen"
  100. %token <i> META_SK_FORWARD_ALLOCS "sk_forward_allocs"
  101. %token <i> META_SK_ALLOCS "sk_allocs"
  102. %token <i> META_SK_ROUTE_CAPS "sk_route_caps"
  103. %token <i> META_SK_HASH "sk_hash"
  104. %token <i> META_SK_LINGERTIME "sk_lingertime"
  105. %token <i> META_SK_ACK_BACKLOG "sk_ack_backlog"
  106. %token <i> META_SK_MAX_ACK_BACKLOG "sk_max_ack_backlog"
  107. %token <i> META_SK_PRIO "sk_prio"
  108. %token <i> META_SK_RCVLOWAT "sk_rcvlowat"
  109. %token <i> META_SK_RCVTIMEO "sk_rcvtimeo"
  110. %token <i> META_SK_SNDTIMEO "sk_sndtimeo"
  111. %token <i> META_SK_SENDMSG_OFF "sk_sendmsg_off"
  112. %token <i> META_SK_WRITE_PENDING "sk_write_pending"
  113. %token <i> META_VLAN "vlan"
  114. %token <i> META_RXHASH "rxhash"
  115. %token <i> META_DEVNAME "devname"
  116. %token <i> META_SK_BOUND_IF "sk_bound_if"
  117. %token <s> STR
  118. %token <q> QUOTED
  119. %type <i> align operand shift meta_int_id meta_var_id
  120. %type <i64> mask
  121. %type <e> expr match ematch
  122. %type <cmp> cmp_expr cmp_match
  123. %type <loc> pktloc text_from text_to
  124. %type <q> pattern
  125. %type <mv> meta_value
  126. %destructor { free($$); NL_DBG(2, "string destructor\n"); } <s>
  127. %destructor { rtnl_pktloc_put($$); NL_DBG(2, "pktloc destructor\n"); } <loc>
  128. %destructor { free($$.data); NL_DBG(2, "quoted destructor\n"); } <q>
  129. %destructor { rtnl_meta_value_put($$); NL_DBG(2, "meta value destructor\n"); } <mv>
  130. %start input
  131. %%
  132. input:
  133. /* empty */
  134. | expr
  135. {
  136. nl_list_add_tail(root, &$1->e_list);
  137. }
  138. ;
  139. expr:
  140. match
  141. {
  142. $$ = $1;
  143. }
  144. | match LOGIC expr
  145. {
  146. rtnl_ematch_set_flags($1, $2);
  147. /* make ematch new head */
  148. nl_list_add_tail(&$1->e_list, &$3->e_list);
  149. $$ = $1;
  150. }
  151. ;
  152. match:
  153. NOT ematch
  154. {
  155. rtnl_ematch_set_flags($2, TCF_EM_INVERT);
  156. $$ = $2;
  157. }
  158. | ematch
  159. {
  160. $$ = $1;
  161. }
  162. ;
  163. ematch:
  164. /* CMP */
  165. cmp_match
  166. {
  167. struct rtnl_ematch *e;
  168. if (!(e = rtnl_ematch_alloc())) {
  169. *errp = strdup("Unable to allocate ematch object");
  170. YYABORT;
  171. }
  172. if (rtnl_ematch_set_kind(e, TCF_EM_CMP) < 0)
  173. BUG();
  174. rtnl_ematch_cmp_set(e, &$1);
  175. $$ = e;
  176. }
  177. | EMATCH_NBYTE "(" pktloc KW_EQ pattern ")"
  178. {
  179. struct rtnl_ematch *e;
  180. if (!(e = rtnl_ematch_alloc())) {
  181. *errp = strdup("Unable to allocate ematch object");
  182. YYABORT;
  183. }
  184. if (rtnl_ematch_set_kind(e, TCF_EM_NBYTE) < 0)
  185. BUG();
  186. rtnl_ematch_nbyte_set_offset(e, $3->layer, $3->offset);
  187. rtnl_pktloc_put($3);
  188. rtnl_ematch_nbyte_set_pattern(e, (uint8_t *) $5.data, $5.index);
  189. $$ = e;
  190. }
  191. | EMATCH_TEXT "(" STR QUOTED text_from text_to ")"
  192. {
  193. struct rtnl_ematch *e;
  194. if (!(e = rtnl_ematch_alloc())) {
  195. *errp = strdup("Unable to allocate ematch object");
  196. YYABORT;
  197. }
  198. if (rtnl_ematch_set_kind(e, TCF_EM_TEXT) < 0)
  199. BUG();
  200. rtnl_ematch_text_set_algo(e, $3);
  201. rtnl_ematch_text_set_pattern(e, $4.data, $4.index);
  202. if ($5) {
  203. rtnl_ematch_text_set_from(e, $5->layer, $5->offset);
  204. rtnl_pktloc_put($5);
  205. }
  206. if ($6) {
  207. rtnl_ematch_text_set_to(e, $6->layer, $6->offset);
  208. rtnl_pktloc_put($6);
  209. }
  210. $$ = e;
  211. }
  212. | EMATCH_META "(" meta_value operand meta_value ")"
  213. {
  214. struct rtnl_ematch *e;
  215. if (!(e = rtnl_ematch_alloc())) {
  216. *errp = strdup("Unable to allocate ematch object");
  217. YYABORT;
  218. }
  219. if (rtnl_ematch_set_kind(e, TCF_EM_META) < 0)
  220. BUG();
  221. rtnl_ematch_meta_set_lvalue(e, $3);
  222. rtnl_ematch_meta_set_rvalue(e, $5);
  223. rtnl_ematch_meta_set_operand(e, $4);
  224. $$ = e;
  225. }
  226. /* CONTAINER */
  227. | "(" expr ")"
  228. {
  229. struct rtnl_ematch *e;
  230. if (!(e = rtnl_ematch_alloc())) {
  231. *errp = strdup("Unable to allocate ematch object");
  232. YYABORT;
  233. }
  234. if (rtnl_ematch_set_kind(e, TCF_EM_CONTAINER) < 0)
  235. BUG();
  236. /* Make e->childs the list head of a the ematch sequence */
  237. nl_list_add_tail(&e->e_childs, &$2->e_list);
  238. $$ = e;
  239. }
  240. ;
  241. /*
  242. * CMP match
  243. *
  244. * match := cmp(expr) | expr
  245. * expr := pktloc (=|>|<) NUMBER
  246. * pktloc := alias | definition
  247. *
  248. */
  249. cmp_match:
  250. EMATCH_CMP "(" cmp_expr ")"
  251. { $$ = $3; }
  252. | cmp_expr
  253. { $$ = $1; }
  254. ;
  255. cmp_expr:
  256. pktloc operand NUMBER
  257. {
  258. if ($1->align == TCF_EM_ALIGN_U16 ||
  259. $1->align == TCF_EM_ALIGN_U32)
  260. $$.flags = TCF_EM_CMP_TRANS;
  261. memset(&$$, 0, sizeof($$));
  262. $$.mask = $1->mask;
  263. $$.off = $1->offset;
  264. $$.align = $1->align;
  265. $$.layer = $1->layer;
  266. $$.opnd = $2;
  267. $$.val = $3;
  268. rtnl_pktloc_put($1);
  269. }
  270. ;
  271. text_from:
  272. /* empty */
  273. { $$ = NULL; }
  274. | "from" pktloc
  275. { $$ = $2; }
  276. ;
  277. text_to:
  278. /* empty */
  279. { $$ = NULL; }
  280. | "to" pktloc
  281. { $$ = $2; }
  282. ;
  283. meta_value:
  284. QUOTED
  285. { $$ = rtnl_meta_value_alloc_var($1.data, $1.len); }
  286. | NUMBER
  287. { $$ = rtnl_meta_value_alloc_int($1); }
  288. | meta_int_id shift mask
  289. { $$ = META_ALLOC(META_INT, $1, $2, $3); }
  290. | meta_var_id shift
  291. { $$ = META_ALLOC(META_VAR, $1, $2, 0); }
  292. ;
  293. meta_int_id:
  294. META_RANDOM { $$ = META_ID(RANDOM); }
  295. |META_LOADAVG_0 { $$ = META_ID(LOADAVG_0); }
  296. |META_LOADAVG_1 { $$ = META_ID(LOADAVG_1); }
  297. |META_LOADAVG_2 { $$ = META_ID(LOADAVG_2); }
  298. | META_DEV { $$ = META_ID(DEV); }
  299. | META_PRIO { $$ = META_ID(PRIORITY); }
  300. | META_PROTO { $$ = META_ID(PROTOCOL); }
  301. | META_PKTTYPE { $$ = META_ID(PKTTYPE); }
  302. | META_PKTLEN { $$ = META_ID(PKTLEN); }
  303. | META_DATALEN { $$ = META_ID(DATALEN); }
  304. | META_MACLEN { $$ = META_ID(MACLEN); }
  305. | META_MARK { $$ = META_ID(NFMARK); }
  306. | META_TCINDEX { $$ = META_ID(TCINDEX); }
  307. | META_RTCLASSID { $$ = META_ID(RTCLASSID); }
  308. | META_RTIIF { $$ = META_ID(RTIIF); }
  309. | META_SK_FAMILY { $$ = META_ID(SK_FAMILY); }
  310. | META_SK_STATE { $$ = META_ID(SK_STATE); }
  311. | META_SK_REUSE { $$ = META_ID(SK_REUSE); }
  312. | META_SK_REFCNT { $$ = META_ID(SK_REFCNT); }
  313. | META_SK_RCVBUF { $$ = META_ID(SK_RCVBUF); }
  314. | META_SK_SNDBUF { $$ = META_ID(SK_SNDBUF); }
  315. | META_SK_SHUTDOWN { $$ = META_ID(SK_SHUTDOWN); }
  316. | META_SK_PROTO { $$ = META_ID(SK_PROTO); }
  317. | META_SK_TYPE { $$ = META_ID(SK_TYPE); }
  318. | META_SK_RMEM_ALLOC { $$ = META_ID(SK_RMEM_ALLOC); }
  319. | META_SK_WMEM_ALLOC { $$ = META_ID(SK_WMEM_ALLOC); }
  320. | META_SK_WMEM_QUEUED { $$ = META_ID(SK_WMEM_QUEUED); }
  321. | META_SK_RCV_QLEN { $$ = META_ID(SK_RCV_QLEN); }
  322. | META_SK_SND_QLEN { $$ = META_ID(SK_SND_QLEN); }
  323. | META_SK_ERR_QLEN { $$ = META_ID(SK_ERR_QLEN); }
  324. | META_SK_FORWARD_ALLOCS { $$ = META_ID(SK_FORWARD_ALLOCS); }
  325. | META_SK_ALLOCS { $$ = META_ID(SK_ALLOCS); }
  326. | META_SK_ROUTE_CAPS { $$ = META_ID(SK_ROUTE_CAPS); }
  327. | META_SK_HASH { $$ = META_ID(SK_HASH); }
  328. | META_SK_LINGERTIME { $$ = META_ID(SK_LINGERTIME); }
  329. | META_SK_ACK_BACKLOG { $$ = META_ID(SK_ACK_BACKLOG); }
  330. | META_SK_MAX_ACK_BACKLOG { $$ = META_ID(SK_MAX_ACK_BACKLOG); }
  331. | META_SK_PRIO { $$ = META_ID(SK_PRIO); }
  332. | META_SK_RCVLOWAT { $$ = META_ID(SK_RCVLOWAT); }
  333. | META_SK_RCVTIMEO { $$ = META_ID(SK_RCVTIMEO); }
  334. | META_SK_SNDTIMEO { $$ = META_ID(SK_SNDTIMEO); }
  335. | META_SK_SENDMSG_OFF { $$ = META_ID(SK_SENDMSG_OFF); }
  336. | META_SK_WRITE_PENDING { $$ = META_ID(SK_WRITE_PENDING); }
  337. | META_VLAN { $$ = META_ID(VLAN_TAG); }
  338. | META_RXHASH { $$ = META_ID(RXHASH); }
  339. ;
  340. meta_var_id:
  341. META_DEVNAME { $$ = META_ID(DEV); }
  342. | META_SK_BOUND_IF { $$ = META_ID(SK_BOUND_IF); }
  343. ;
  344. /*
  345. * pattern
  346. */
  347. pattern:
  348. QUOTED
  349. {
  350. $$ = $1;
  351. }
  352. | STR
  353. {
  354. struct nl_addr *addr;
  355. if (nl_addr_parse($1, AF_UNSPEC, &addr) == 0) {
  356. $$.len = nl_addr_get_len(addr);
  357. $$.index = min_t(int, $$.len, nl_addr_get_prefixlen(addr)/8);
  358. if (!($$.data = calloc(1, $$.len))) {
  359. nl_addr_put(addr);
  360. YYABORT;
  361. }
  362. memcpy($$.data, nl_addr_get_binary_addr(addr), $$.len);
  363. nl_addr_put(addr);
  364. } else {
  365. if (asprintf(errp, "invalid pattern \"%s\"", $1) == -1)
  366. *errp = NULL;
  367. YYABORT;
  368. }
  369. }
  370. ;
  371. /*
  372. * packet location
  373. */
  374. pktloc:
  375. STR
  376. {
  377. struct rtnl_pktloc *loc;
  378. if (rtnl_pktloc_lookup($1, &loc) < 0) {
  379. if (asprintf(errp, "Packet location \"%s\" not found", $1) == -1)
  380. *errp = NULL;
  381. YYABORT;
  382. }
  383. $$ = loc;
  384. }
  385. /* [u8|u16|u32|NUM at] LAYER + OFFSET [mask MASK] */
  386. | align LAYER "+" NUMBER mask
  387. {
  388. struct rtnl_pktloc *loc;
  389. if ($5 && (!$1 || $1 > TCF_EM_ALIGN_U32)) {
  390. *errp = strdup("mask only allowed for alignments u8|u16|u32");
  391. YYABORT;
  392. }
  393. if (!(loc = rtnl_pktloc_alloc())) {
  394. *errp = strdup("Unable to allocate packet location object");
  395. YYABORT;
  396. }
  397. loc->name = strdup("<USER-DEFINED>");
  398. loc->align = $1;
  399. loc->layer = $2;
  400. loc->offset = $4;
  401. loc->mask = $5;
  402. $$ = loc;
  403. }
  404. ;
  405. align:
  406. /* empty */
  407. { $$ = 0; }
  408. | ALIGN "at"
  409. { $$ = $1; }
  410. | NUMBER "at"
  411. { $$ = $1; }
  412. ;
  413. mask:
  414. /* empty */
  415. { $$ = 0; }
  416. | KW_MASK NUMBER
  417. { $$ = $2; }
  418. ;
  419. shift:
  420. /* empty */
  421. { $$ = 0; }
  422. | KW_SHIFT NUMBER
  423. { $$ = $2; }
  424. ;
  425. operand:
  426. KW_EQ
  427. { $$ = TCF_EM_OPND_EQ; }
  428. | KW_GT
  429. { $$ = TCF_EM_OPND_GT; }
  430. | KW_LT
  431. { $$ = TCF_EM_OPND_LT; }
  432. ;