ioam6_parser.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Author: Justin Iurman (justin.iurman@uliege.be)
  4. *
  5. * IOAM tester for IPv6, see ioam6.sh for details on each test case.
  6. */
  7. #include <arpa/inet.h>
  8. #include <errno.h>
  9. #include <limits.h>
  10. #include <linux/const.h>
  11. #include <linux/if_ether.h>
  12. #include <linux/ioam6.h>
  13. #include <linux/ipv6.h>
  14. #include <stdbool.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <unistd.h>
  18. struct ioam_config {
  19. __u32 id;
  20. __u64 wide;
  21. __u16 ingr_id;
  22. __u16 egr_id;
  23. __u32 ingr_wide;
  24. __u32 egr_wide;
  25. __u32 ns_data;
  26. __u64 ns_wide;
  27. __u32 sc_id;
  28. __u8 hlim;
  29. char *sc_data;
  30. };
  31. /*
  32. * Be careful if you modify structs below - everything MUST be kept synchronized
  33. * with configurations inside ioam6.sh and always reflect the same.
  34. */
  35. static struct ioam_config node1 = {
  36. .id = 1,
  37. .wide = 11111111,
  38. .ingr_id = 0xffff, /* default value */
  39. .egr_id = 101,
  40. .ingr_wide = 0xffffffff, /* default value */
  41. .egr_wide = 101101,
  42. .ns_data = 0xdeadbeef,
  43. .ns_wide = 0xcafec0caf00dc0de,
  44. .sc_id = 777,
  45. .sc_data = "something that will be 4n-aligned",
  46. .hlim = 64,
  47. };
  48. static struct ioam_config node2 = {
  49. .id = 2,
  50. .wide = 22222222,
  51. .ingr_id = 201,
  52. .egr_id = 202,
  53. .ingr_wide = 201201,
  54. .egr_wide = 202202,
  55. .ns_data = 0xffffffff, /* default value */
  56. .ns_wide = 0xffffffffffffffff, /* default value */
  57. .sc_id = 0xffffff, /* default value */
  58. .sc_data = NULL,
  59. .hlim = 63,
  60. };
  61. enum {
  62. /**********
  63. * OUTPUT *
  64. **********/
  65. __TEST_OUT_MIN,
  66. TEST_OUT_UNDEF_NS,
  67. TEST_OUT_NO_ROOM,
  68. TEST_OUT_NO_ROOM_OSS,
  69. TEST_OUT_BIT0,
  70. TEST_OUT_BIT1,
  71. TEST_OUT_BIT2,
  72. TEST_OUT_BIT3,
  73. TEST_OUT_BIT4,
  74. TEST_OUT_BIT5,
  75. TEST_OUT_BIT6,
  76. TEST_OUT_BIT7,
  77. TEST_OUT_BIT8,
  78. TEST_OUT_BIT9,
  79. TEST_OUT_BIT10,
  80. TEST_OUT_BIT11,
  81. TEST_OUT_BIT22,
  82. TEST_OUT_SIZE4,
  83. TEST_OUT_SIZE8,
  84. TEST_OUT_SIZE12,
  85. TEST_OUT_SIZE16,
  86. TEST_OUT_SIZE20,
  87. TEST_OUT_SIZE24,
  88. TEST_OUT_SIZE28,
  89. TEST_OUT_SIZE32,
  90. TEST_OUT_SIZE36,
  91. TEST_OUT_SIZE40,
  92. TEST_OUT_SIZE44,
  93. TEST_OUT_SIZE48,
  94. TEST_OUT_SIZE52,
  95. TEST_OUT_SIZE56,
  96. TEST_OUT_SIZE60,
  97. TEST_OUT_SIZE64,
  98. TEST_OUT_SIZE68,
  99. TEST_OUT_SIZE72,
  100. TEST_OUT_SIZE76,
  101. TEST_OUT_SIZE80,
  102. TEST_OUT_SIZE84,
  103. TEST_OUT_SIZE88,
  104. TEST_OUT_SIZE92,
  105. TEST_OUT_SIZE96,
  106. TEST_OUT_SIZE100,
  107. TEST_OUT_SIZE104,
  108. TEST_OUT_SIZE108,
  109. TEST_OUT_SIZE112,
  110. TEST_OUT_SIZE116,
  111. TEST_OUT_SIZE120,
  112. TEST_OUT_SIZE124,
  113. TEST_OUT_SIZE128,
  114. TEST_OUT_SIZE132,
  115. TEST_OUT_SIZE136,
  116. TEST_OUT_SIZE140,
  117. TEST_OUT_SIZE144,
  118. TEST_OUT_SIZE148,
  119. TEST_OUT_SIZE152,
  120. TEST_OUT_SIZE156,
  121. TEST_OUT_SIZE160,
  122. TEST_OUT_SIZE164,
  123. TEST_OUT_SIZE168,
  124. TEST_OUT_SIZE172,
  125. TEST_OUT_SIZE176,
  126. TEST_OUT_SIZE180,
  127. TEST_OUT_SIZE184,
  128. TEST_OUT_SIZE188,
  129. TEST_OUT_SIZE192,
  130. TEST_OUT_SIZE196,
  131. TEST_OUT_SIZE200,
  132. TEST_OUT_SIZE204,
  133. TEST_OUT_SIZE208,
  134. TEST_OUT_SIZE212,
  135. TEST_OUT_SIZE216,
  136. TEST_OUT_SIZE220,
  137. TEST_OUT_SIZE224,
  138. TEST_OUT_SIZE228,
  139. TEST_OUT_SIZE232,
  140. TEST_OUT_SIZE236,
  141. TEST_OUT_SIZE240,
  142. TEST_OUT_SIZE244,
  143. TEST_OUT_FULL_SUPP_TRACE,
  144. __TEST_OUT_MAX,
  145. /*********
  146. * INPUT *
  147. *********/
  148. __TEST_IN_MIN,
  149. TEST_IN_UNDEF_NS,
  150. TEST_IN_NO_ROOM,
  151. TEST_IN_NO_ROOM_OSS,
  152. TEST_IN_DISABLED,
  153. TEST_IN_OFLAG,
  154. TEST_IN_BIT0,
  155. TEST_IN_BIT1,
  156. TEST_IN_BIT2,
  157. TEST_IN_BIT3,
  158. TEST_IN_BIT4,
  159. TEST_IN_BIT5,
  160. TEST_IN_BIT6,
  161. TEST_IN_BIT7,
  162. TEST_IN_BIT8,
  163. TEST_IN_BIT9,
  164. TEST_IN_BIT10,
  165. TEST_IN_BIT11,
  166. TEST_IN_BIT22,
  167. TEST_IN_SIZE4,
  168. TEST_IN_SIZE8,
  169. TEST_IN_SIZE12,
  170. TEST_IN_SIZE16,
  171. TEST_IN_SIZE20,
  172. TEST_IN_SIZE24,
  173. TEST_IN_SIZE28,
  174. TEST_IN_SIZE32,
  175. TEST_IN_SIZE36,
  176. TEST_IN_SIZE40,
  177. TEST_IN_SIZE44,
  178. TEST_IN_SIZE48,
  179. TEST_IN_SIZE52,
  180. TEST_IN_SIZE56,
  181. TEST_IN_SIZE60,
  182. TEST_IN_SIZE64,
  183. TEST_IN_SIZE68,
  184. TEST_IN_SIZE72,
  185. TEST_IN_SIZE76,
  186. TEST_IN_SIZE80,
  187. TEST_IN_SIZE84,
  188. TEST_IN_SIZE88,
  189. TEST_IN_SIZE92,
  190. TEST_IN_SIZE96,
  191. TEST_IN_SIZE100,
  192. TEST_IN_SIZE104,
  193. TEST_IN_SIZE108,
  194. TEST_IN_SIZE112,
  195. TEST_IN_SIZE116,
  196. TEST_IN_SIZE120,
  197. TEST_IN_SIZE124,
  198. TEST_IN_SIZE128,
  199. TEST_IN_SIZE132,
  200. TEST_IN_SIZE136,
  201. TEST_IN_SIZE140,
  202. TEST_IN_SIZE144,
  203. TEST_IN_SIZE148,
  204. TEST_IN_SIZE152,
  205. TEST_IN_SIZE156,
  206. TEST_IN_SIZE160,
  207. TEST_IN_SIZE164,
  208. TEST_IN_SIZE168,
  209. TEST_IN_SIZE172,
  210. TEST_IN_SIZE176,
  211. TEST_IN_SIZE180,
  212. TEST_IN_SIZE184,
  213. TEST_IN_SIZE188,
  214. TEST_IN_SIZE192,
  215. TEST_IN_SIZE196,
  216. TEST_IN_SIZE200,
  217. TEST_IN_SIZE204,
  218. TEST_IN_SIZE208,
  219. TEST_IN_SIZE212,
  220. TEST_IN_SIZE216,
  221. TEST_IN_SIZE220,
  222. TEST_IN_SIZE224,
  223. TEST_IN_SIZE228,
  224. TEST_IN_SIZE232,
  225. TEST_IN_SIZE236,
  226. TEST_IN_SIZE240,
  227. TEST_IN_SIZE244,
  228. TEST_IN_FULL_SUPP_TRACE,
  229. __TEST_IN_MAX,
  230. __TEST_MAX,
  231. };
  232. static int check_header(int tid, struct ioam6_trace_hdr *trace,
  233. __u32 trace_type, __u8 trace_size, __u16 ioam_ns)
  234. {
  235. if (__be16_to_cpu(trace->namespace_id) != ioam_ns ||
  236. __be32_to_cpu(trace->type_be32) != (trace_type << 8))
  237. return 1;
  238. switch (tid) {
  239. case TEST_OUT_UNDEF_NS:
  240. case TEST_IN_UNDEF_NS:
  241. case TEST_IN_DISABLED:
  242. return trace->overflow == 1 ||
  243. trace->nodelen != 1 ||
  244. trace->remlen != 1;
  245. case TEST_OUT_NO_ROOM:
  246. case TEST_IN_NO_ROOM:
  247. case TEST_IN_OFLAG:
  248. return trace->overflow == 0 ||
  249. trace->nodelen != 2 ||
  250. trace->remlen != 1;
  251. case TEST_OUT_NO_ROOM_OSS:
  252. return trace->overflow == 0 ||
  253. trace->nodelen != 0 ||
  254. trace->remlen != 1;
  255. case TEST_IN_NO_ROOM_OSS:
  256. case TEST_OUT_BIT22:
  257. case TEST_IN_BIT22:
  258. return trace->overflow == 1 ||
  259. trace->nodelen != 0 ||
  260. trace->remlen != 0;
  261. case TEST_OUT_BIT0:
  262. case TEST_IN_BIT0:
  263. case TEST_OUT_BIT1:
  264. case TEST_IN_BIT1:
  265. case TEST_OUT_BIT2:
  266. case TEST_IN_BIT2:
  267. case TEST_OUT_BIT3:
  268. case TEST_IN_BIT3:
  269. case TEST_OUT_BIT4:
  270. case TEST_IN_BIT4:
  271. case TEST_OUT_BIT5:
  272. case TEST_IN_BIT5:
  273. case TEST_OUT_BIT6:
  274. case TEST_IN_BIT6:
  275. case TEST_OUT_BIT7:
  276. case TEST_IN_BIT7:
  277. case TEST_OUT_BIT11:
  278. case TEST_IN_BIT11:
  279. return trace->overflow == 1 ||
  280. trace->nodelen != 1 ||
  281. trace->remlen != 0;
  282. case TEST_OUT_BIT8:
  283. case TEST_IN_BIT8:
  284. case TEST_OUT_BIT9:
  285. case TEST_IN_BIT9:
  286. case TEST_OUT_BIT10:
  287. case TEST_IN_BIT10:
  288. return trace->overflow == 1 ||
  289. trace->nodelen != 2 ||
  290. trace->remlen != 0;
  291. case TEST_OUT_SIZE4:
  292. case TEST_OUT_SIZE8:
  293. case TEST_OUT_SIZE12:
  294. case TEST_OUT_SIZE16:
  295. case TEST_OUT_SIZE20:
  296. case TEST_OUT_SIZE24:
  297. case TEST_OUT_SIZE28:
  298. case TEST_OUT_SIZE32:
  299. case TEST_OUT_SIZE36:
  300. case TEST_OUT_SIZE40:
  301. case TEST_OUT_SIZE44:
  302. case TEST_OUT_SIZE48:
  303. case TEST_OUT_SIZE52:
  304. case TEST_OUT_SIZE56:
  305. case TEST_OUT_SIZE60:
  306. case TEST_OUT_SIZE64:
  307. case TEST_OUT_SIZE68:
  308. case TEST_OUT_SIZE72:
  309. case TEST_OUT_SIZE76:
  310. case TEST_OUT_SIZE80:
  311. case TEST_OUT_SIZE84:
  312. case TEST_OUT_SIZE88:
  313. case TEST_OUT_SIZE92:
  314. case TEST_OUT_SIZE96:
  315. case TEST_OUT_SIZE100:
  316. case TEST_OUT_SIZE104:
  317. case TEST_OUT_SIZE108:
  318. case TEST_OUT_SIZE112:
  319. case TEST_OUT_SIZE116:
  320. case TEST_OUT_SIZE120:
  321. case TEST_OUT_SIZE124:
  322. case TEST_OUT_SIZE128:
  323. case TEST_OUT_SIZE132:
  324. case TEST_OUT_SIZE136:
  325. case TEST_OUT_SIZE140:
  326. case TEST_OUT_SIZE144:
  327. case TEST_OUT_SIZE148:
  328. case TEST_OUT_SIZE152:
  329. case TEST_OUT_SIZE156:
  330. case TEST_OUT_SIZE160:
  331. case TEST_OUT_SIZE164:
  332. case TEST_OUT_SIZE168:
  333. case TEST_OUT_SIZE172:
  334. case TEST_OUT_SIZE176:
  335. case TEST_OUT_SIZE180:
  336. case TEST_OUT_SIZE184:
  337. case TEST_OUT_SIZE188:
  338. case TEST_OUT_SIZE192:
  339. case TEST_OUT_SIZE196:
  340. case TEST_OUT_SIZE200:
  341. case TEST_OUT_SIZE204:
  342. case TEST_OUT_SIZE208:
  343. case TEST_OUT_SIZE212:
  344. case TEST_OUT_SIZE216:
  345. case TEST_OUT_SIZE220:
  346. case TEST_OUT_SIZE224:
  347. case TEST_OUT_SIZE228:
  348. case TEST_OUT_SIZE232:
  349. case TEST_OUT_SIZE236:
  350. case TEST_OUT_SIZE240:
  351. case TEST_OUT_SIZE244:
  352. return trace->overflow == 1 ||
  353. trace->nodelen != 1 ||
  354. trace->remlen != trace_size / 4;
  355. case TEST_IN_SIZE4:
  356. case TEST_IN_SIZE8:
  357. case TEST_IN_SIZE12:
  358. case TEST_IN_SIZE16:
  359. case TEST_IN_SIZE20:
  360. case TEST_IN_SIZE24:
  361. case TEST_IN_SIZE28:
  362. case TEST_IN_SIZE32:
  363. case TEST_IN_SIZE36:
  364. case TEST_IN_SIZE40:
  365. case TEST_IN_SIZE44:
  366. case TEST_IN_SIZE48:
  367. case TEST_IN_SIZE52:
  368. case TEST_IN_SIZE56:
  369. case TEST_IN_SIZE60:
  370. case TEST_IN_SIZE64:
  371. case TEST_IN_SIZE68:
  372. case TEST_IN_SIZE72:
  373. case TEST_IN_SIZE76:
  374. case TEST_IN_SIZE80:
  375. case TEST_IN_SIZE84:
  376. case TEST_IN_SIZE88:
  377. case TEST_IN_SIZE92:
  378. case TEST_IN_SIZE96:
  379. case TEST_IN_SIZE100:
  380. case TEST_IN_SIZE104:
  381. case TEST_IN_SIZE108:
  382. case TEST_IN_SIZE112:
  383. case TEST_IN_SIZE116:
  384. case TEST_IN_SIZE120:
  385. case TEST_IN_SIZE124:
  386. case TEST_IN_SIZE128:
  387. case TEST_IN_SIZE132:
  388. case TEST_IN_SIZE136:
  389. case TEST_IN_SIZE140:
  390. case TEST_IN_SIZE144:
  391. case TEST_IN_SIZE148:
  392. case TEST_IN_SIZE152:
  393. case TEST_IN_SIZE156:
  394. case TEST_IN_SIZE160:
  395. case TEST_IN_SIZE164:
  396. case TEST_IN_SIZE168:
  397. case TEST_IN_SIZE172:
  398. case TEST_IN_SIZE176:
  399. case TEST_IN_SIZE180:
  400. case TEST_IN_SIZE184:
  401. case TEST_IN_SIZE188:
  402. case TEST_IN_SIZE192:
  403. case TEST_IN_SIZE196:
  404. case TEST_IN_SIZE200:
  405. case TEST_IN_SIZE204:
  406. case TEST_IN_SIZE208:
  407. case TEST_IN_SIZE212:
  408. case TEST_IN_SIZE216:
  409. case TEST_IN_SIZE220:
  410. case TEST_IN_SIZE224:
  411. case TEST_IN_SIZE228:
  412. case TEST_IN_SIZE232:
  413. case TEST_IN_SIZE236:
  414. case TEST_IN_SIZE240:
  415. case TEST_IN_SIZE244:
  416. return trace->overflow == 1 ||
  417. trace->nodelen != 1 ||
  418. trace->remlen != (trace_size / 4) - trace->nodelen;
  419. case TEST_OUT_FULL_SUPP_TRACE:
  420. case TEST_IN_FULL_SUPP_TRACE:
  421. return trace->overflow == 1 ||
  422. trace->nodelen != 15 ||
  423. trace->remlen != 0;
  424. default:
  425. break;
  426. }
  427. return 1;
  428. }
  429. static int check_data(struct ioam6_trace_hdr *trace, __u8 trace_size,
  430. const struct ioam_config cnf, bool is_output)
  431. {
  432. unsigned int len, i;
  433. __u8 aligned;
  434. __u64 raw64;
  435. __u32 raw32;
  436. __u8 *p;
  437. if (trace->type.bit12 | trace->type.bit13 | trace->type.bit14 |
  438. trace->type.bit15 | trace->type.bit16 | trace->type.bit17 |
  439. trace->type.bit18 | trace->type.bit19 | trace->type.bit20 |
  440. trace->type.bit21 | trace->type.bit23)
  441. return 1;
  442. for (i = 0; i < trace->remlen * 4; i++) {
  443. if (trace->data[i] != 0)
  444. return 1;
  445. }
  446. if (trace->remlen * 4 == trace_size)
  447. return 0;
  448. p = trace->data + trace->remlen * 4;
  449. if (trace->type.bit0) {
  450. raw32 = __be32_to_cpu(*((__u32 *)p));
  451. if (cnf.hlim != (raw32 >> 24) || cnf.id != (raw32 & 0xffffff))
  452. return 1;
  453. p += sizeof(__u32);
  454. }
  455. if (trace->type.bit1) {
  456. raw32 = __be32_to_cpu(*((__u32 *)p));
  457. if (cnf.ingr_id != (raw32 >> 16) ||
  458. cnf.egr_id != (raw32 & 0xffff))
  459. return 1;
  460. p += sizeof(__u32);
  461. }
  462. if (trace->type.bit2) {
  463. raw32 = __be32_to_cpu(*((__u32 *)p));
  464. if ((is_output && raw32 != 0xffffffff) ||
  465. (!is_output && (raw32 == 0 || raw32 == 0xffffffff)))
  466. return 1;
  467. p += sizeof(__u32);
  468. }
  469. if (trace->type.bit3) {
  470. raw32 = __be32_to_cpu(*((__u32 *)p));
  471. if ((is_output && raw32 != 0xffffffff) ||
  472. (!is_output && (raw32 == 0 || raw32 == 0xffffffff)))
  473. return 1;
  474. p += sizeof(__u32);
  475. }
  476. if (trace->type.bit4) {
  477. if (__be32_to_cpu(*((__u32 *)p)) != 0xffffffff)
  478. return 1;
  479. p += sizeof(__u32);
  480. }
  481. if (trace->type.bit5) {
  482. if (__be32_to_cpu(*((__u32 *)p)) != cnf.ns_data)
  483. return 1;
  484. p += sizeof(__u32);
  485. }
  486. if (trace->type.bit6) {
  487. if (__be32_to_cpu(*((__u32 *)p)) == 0xffffffff)
  488. return 1;
  489. p += sizeof(__u32);
  490. }
  491. if (trace->type.bit7) {
  492. if (__be32_to_cpu(*((__u32 *)p)) != 0xffffffff)
  493. return 1;
  494. p += sizeof(__u32);
  495. }
  496. if (trace->type.bit8) {
  497. raw64 = __be64_to_cpu(*((__u64 *)p));
  498. if (cnf.hlim != (raw64 >> 56) ||
  499. cnf.wide != (raw64 & 0xffffffffffffff))
  500. return 1;
  501. p += sizeof(__u64);
  502. }
  503. if (trace->type.bit9) {
  504. if (__be32_to_cpu(*((__u32 *)p)) != cnf.ingr_wide)
  505. return 1;
  506. p += sizeof(__u32);
  507. if (__be32_to_cpu(*((__u32 *)p)) != cnf.egr_wide)
  508. return 1;
  509. p += sizeof(__u32);
  510. }
  511. if (trace->type.bit10) {
  512. if (__be64_to_cpu(*((__u64 *)p)) != cnf.ns_wide)
  513. return 1;
  514. p += sizeof(__u64);
  515. }
  516. if (trace->type.bit11) {
  517. if (__be32_to_cpu(*((__u32 *)p)) != 0xffffffff)
  518. return 1;
  519. p += sizeof(__u32);
  520. }
  521. if (trace->type.bit22) {
  522. len = cnf.sc_data ? strlen(cnf.sc_data) : 0;
  523. aligned = cnf.sc_data ? __ALIGN_KERNEL(len, 4) : 0;
  524. raw32 = __be32_to_cpu(*((__u32 *)p));
  525. if (aligned != (raw32 >> 24) * 4 ||
  526. cnf.sc_id != (raw32 & 0xffffff))
  527. return 1;
  528. p += sizeof(__u32);
  529. if (cnf.sc_data) {
  530. if (strncmp((char *)p, cnf.sc_data, len))
  531. return 1;
  532. p += len;
  533. aligned -= len;
  534. while (aligned--) {
  535. if (*p != '\0')
  536. return 1;
  537. p += sizeof(__u8);
  538. }
  539. }
  540. }
  541. return 0;
  542. }
  543. static int check_ioam_trace(int tid, struct ioam6_trace_hdr *trace,
  544. __u32 trace_type, __u8 trace_size, __u16 ioam_ns)
  545. {
  546. if (check_header(tid, trace, trace_type, trace_size, ioam_ns))
  547. return 1;
  548. if (tid > __TEST_OUT_MIN && tid < __TEST_OUT_MAX)
  549. return check_data(trace, trace_size, node1, true);
  550. if (tid > __TEST_IN_MIN && tid < __TEST_IN_MAX)
  551. return check_data(trace, trace_size, node2, false);
  552. return 1;
  553. }
  554. static int str2id(const char *tname)
  555. {
  556. if (!strcmp("output_undef_ns", tname))
  557. return TEST_OUT_UNDEF_NS;
  558. if (!strcmp("output_no_room", tname))
  559. return TEST_OUT_NO_ROOM;
  560. if (!strcmp("output_no_room_oss", tname))
  561. return TEST_OUT_NO_ROOM_OSS;
  562. if (!strcmp("output_bit0", tname))
  563. return TEST_OUT_BIT0;
  564. if (!strcmp("output_bit1", tname))
  565. return TEST_OUT_BIT1;
  566. if (!strcmp("output_bit2", tname))
  567. return TEST_OUT_BIT2;
  568. if (!strcmp("output_bit3", tname))
  569. return TEST_OUT_BIT3;
  570. if (!strcmp("output_bit4", tname))
  571. return TEST_OUT_BIT4;
  572. if (!strcmp("output_bit5", tname))
  573. return TEST_OUT_BIT5;
  574. if (!strcmp("output_bit6", tname))
  575. return TEST_OUT_BIT6;
  576. if (!strcmp("output_bit7", tname))
  577. return TEST_OUT_BIT7;
  578. if (!strcmp("output_bit8", tname))
  579. return TEST_OUT_BIT8;
  580. if (!strcmp("output_bit9", tname))
  581. return TEST_OUT_BIT9;
  582. if (!strcmp("output_bit10", tname))
  583. return TEST_OUT_BIT10;
  584. if (!strcmp("output_bit11", tname))
  585. return TEST_OUT_BIT11;
  586. if (!strcmp("output_bit22", tname))
  587. return TEST_OUT_BIT22;
  588. if (!strcmp("output_size4", tname))
  589. return TEST_OUT_SIZE4;
  590. if (!strcmp("output_size8", tname))
  591. return TEST_OUT_SIZE8;
  592. if (!strcmp("output_size12", tname))
  593. return TEST_OUT_SIZE12;
  594. if (!strcmp("output_size16", tname))
  595. return TEST_OUT_SIZE16;
  596. if (!strcmp("output_size20", tname))
  597. return TEST_OUT_SIZE20;
  598. if (!strcmp("output_size24", tname))
  599. return TEST_OUT_SIZE24;
  600. if (!strcmp("output_size28", tname))
  601. return TEST_OUT_SIZE28;
  602. if (!strcmp("output_size32", tname))
  603. return TEST_OUT_SIZE32;
  604. if (!strcmp("output_size36", tname))
  605. return TEST_OUT_SIZE36;
  606. if (!strcmp("output_size40", tname))
  607. return TEST_OUT_SIZE40;
  608. if (!strcmp("output_size44", tname))
  609. return TEST_OUT_SIZE44;
  610. if (!strcmp("output_size48", tname))
  611. return TEST_OUT_SIZE48;
  612. if (!strcmp("output_size52", tname))
  613. return TEST_OUT_SIZE52;
  614. if (!strcmp("output_size56", tname))
  615. return TEST_OUT_SIZE56;
  616. if (!strcmp("output_size60", tname))
  617. return TEST_OUT_SIZE60;
  618. if (!strcmp("output_size64", tname))
  619. return TEST_OUT_SIZE64;
  620. if (!strcmp("output_size68", tname))
  621. return TEST_OUT_SIZE68;
  622. if (!strcmp("output_size72", tname))
  623. return TEST_OUT_SIZE72;
  624. if (!strcmp("output_size76", tname))
  625. return TEST_OUT_SIZE76;
  626. if (!strcmp("output_size80", tname))
  627. return TEST_OUT_SIZE80;
  628. if (!strcmp("output_size84", tname))
  629. return TEST_OUT_SIZE84;
  630. if (!strcmp("output_size88", tname))
  631. return TEST_OUT_SIZE88;
  632. if (!strcmp("output_size92", tname))
  633. return TEST_OUT_SIZE92;
  634. if (!strcmp("output_size96", tname))
  635. return TEST_OUT_SIZE96;
  636. if (!strcmp("output_size100", tname))
  637. return TEST_OUT_SIZE100;
  638. if (!strcmp("output_size104", tname))
  639. return TEST_OUT_SIZE104;
  640. if (!strcmp("output_size108", tname))
  641. return TEST_OUT_SIZE108;
  642. if (!strcmp("output_size112", tname))
  643. return TEST_OUT_SIZE112;
  644. if (!strcmp("output_size116", tname))
  645. return TEST_OUT_SIZE116;
  646. if (!strcmp("output_size120", tname))
  647. return TEST_OUT_SIZE120;
  648. if (!strcmp("output_size124", tname))
  649. return TEST_OUT_SIZE124;
  650. if (!strcmp("output_size128", tname))
  651. return TEST_OUT_SIZE128;
  652. if (!strcmp("output_size132", tname))
  653. return TEST_OUT_SIZE132;
  654. if (!strcmp("output_size136", tname))
  655. return TEST_OUT_SIZE136;
  656. if (!strcmp("output_size140", tname))
  657. return TEST_OUT_SIZE140;
  658. if (!strcmp("output_size144", tname))
  659. return TEST_OUT_SIZE144;
  660. if (!strcmp("output_size148", tname))
  661. return TEST_OUT_SIZE148;
  662. if (!strcmp("output_size152", tname))
  663. return TEST_OUT_SIZE152;
  664. if (!strcmp("output_size156", tname))
  665. return TEST_OUT_SIZE156;
  666. if (!strcmp("output_size160", tname))
  667. return TEST_OUT_SIZE160;
  668. if (!strcmp("output_size164", tname))
  669. return TEST_OUT_SIZE164;
  670. if (!strcmp("output_size168", tname))
  671. return TEST_OUT_SIZE168;
  672. if (!strcmp("output_size172", tname))
  673. return TEST_OUT_SIZE172;
  674. if (!strcmp("output_size176", tname))
  675. return TEST_OUT_SIZE176;
  676. if (!strcmp("output_size180", tname))
  677. return TEST_OUT_SIZE180;
  678. if (!strcmp("output_size184", tname))
  679. return TEST_OUT_SIZE184;
  680. if (!strcmp("output_size188", tname))
  681. return TEST_OUT_SIZE188;
  682. if (!strcmp("output_size192", tname))
  683. return TEST_OUT_SIZE192;
  684. if (!strcmp("output_size196", tname))
  685. return TEST_OUT_SIZE196;
  686. if (!strcmp("output_size200", tname))
  687. return TEST_OUT_SIZE200;
  688. if (!strcmp("output_size204", tname))
  689. return TEST_OUT_SIZE204;
  690. if (!strcmp("output_size208", tname))
  691. return TEST_OUT_SIZE208;
  692. if (!strcmp("output_size212", tname))
  693. return TEST_OUT_SIZE212;
  694. if (!strcmp("output_size216", tname))
  695. return TEST_OUT_SIZE216;
  696. if (!strcmp("output_size220", tname))
  697. return TEST_OUT_SIZE220;
  698. if (!strcmp("output_size224", tname))
  699. return TEST_OUT_SIZE224;
  700. if (!strcmp("output_size228", tname))
  701. return TEST_OUT_SIZE228;
  702. if (!strcmp("output_size232", tname))
  703. return TEST_OUT_SIZE232;
  704. if (!strcmp("output_size236", tname))
  705. return TEST_OUT_SIZE236;
  706. if (!strcmp("output_size240", tname))
  707. return TEST_OUT_SIZE240;
  708. if (!strcmp("output_size244", tname))
  709. return TEST_OUT_SIZE244;
  710. if (!strcmp("output_full_supp_trace", tname))
  711. return TEST_OUT_FULL_SUPP_TRACE;
  712. if (!strcmp("input_undef_ns", tname))
  713. return TEST_IN_UNDEF_NS;
  714. if (!strcmp("input_no_room", tname))
  715. return TEST_IN_NO_ROOM;
  716. if (!strcmp("input_no_room_oss", tname))
  717. return TEST_IN_NO_ROOM_OSS;
  718. if (!strcmp("input_disabled", tname))
  719. return TEST_IN_DISABLED;
  720. if (!strcmp("input_oflag", tname))
  721. return TEST_IN_OFLAG;
  722. if (!strcmp("input_bit0", tname))
  723. return TEST_IN_BIT0;
  724. if (!strcmp("input_bit1", tname))
  725. return TEST_IN_BIT1;
  726. if (!strcmp("input_bit2", tname))
  727. return TEST_IN_BIT2;
  728. if (!strcmp("input_bit3", tname))
  729. return TEST_IN_BIT3;
  730. if (!strcmp("input_bit4", tname))
  731. return TEST_IN_BIT4;
  732. if (!strcmp("input_bit5", tname))
  733. return TEST_IN_BIT5;
  734. if (!strcmp("input_bit6", tname))
  735. return TEST_IN_BIT6;
  736. if (!strcmp("input_bit7", tname))
  737. return TEST_IN_BIT7;
  738. if (!strcmp("input_bit8", tname))
  739. return TEST_IN_BIT8;
  740. if (!strcmp("input_bit9", tname))
  741. return TEST_IN_BIT9;
  742. if (!strcmp("input_bit10", tname))
  743. return TEST_IN_BIT10;
  744. if (!strcmp("input_bit11", tname))
  745. return TEST_IN_BIT11;
  746. if (!strcmp("input_bit22", tname))
  747. return TEST_IN_BIT22;
  748. if (!strcmp("input_size4", tname))
  749. return TEST_IN_SIZE4;
  750. if (!strcmp("input_size8", tname))
  751. return TEST_IN_SIZE8;
  752. if (!strcmp("input_size12", tname))
  753. return TEST_IN_SIZE12;
  754. if (!strcmp("input_size16", tname))
  755. return TEST_IN_SIZE16;
  756. if (!strcmp("input_size20", tname))
  757. return TEST_IN_SIZE20;
  758. if (!strcmp("input_size24", tname))
  759. return TEST_IN_SIZE24;
  760. if (!strcmp("input_size28", tname))
  761. return TEST_IN_SIZE28;
  762. if (!strcmp("input_size32", tname))
  763. return TEST_IN_SIZE32;
  764. if (!strcmp("input_size36", tname))
  765. return TEST_IN_SIZE36;
  766. if (!strcmp("input_size40", tname))
  767. return TEST_IN_SIZE40;
  768. if (!strcmp("input_size44", tname))
  769. return TEST_IN_SIZE44;
  770. if (!strcmp("input_size48", tname))
  771. return TEST_IN_SIZE48;
  772. if (!strcmp("input_size52", tname))
  773. return TEST_IN_SIZE52;
  774. if (!strcmp("input_size56", tname))
  775. return TEST_IN_SIZE56;
  776. if (!strcmp("input_size60", tname))
  777. return TEST_IN_SIZE60;
  778. if (!strcmp("input_size64", tname))
  779. return TEST_IN_SIZE64;
  780. if (!strcmp("input_size68", tname))
  781. return TEST_IN_SIZE68;
  782. if (!strcmp("input_size72", tname))
  783. return TEST_IN_SIZE72;
  784. if (!strcmp("input_size76", tname))
  785. return TEST_IN_SIZE76;
  786. if (!strcmp("input_size80", tname))
  787. return TEST_IN_SIZE80;
  788. if (!strcmp("input_size84", tname))
  789. return TEST_IN_SIZE84;
  790. if (!strcmp("input_size88", tname))
  791. return TEST_IN_SIZE88;
  792. if (!strcmp("input_size92", tname))
  793. return TEST_IN_SIZE92;
  794. if (!strcmp("input_size96", tname))
  795. return TEST_IN_SIZE96;
  796. if (!strcmp("input_size100", tname))
  797. return TEST_IN_SIZE100;
  798. if (!strcmp("input_size104", tname))
  799. return TEST_IN_SIZE104;
  800. if (!strcmp("input_size108", tname))
  801. return TEST_IN_SIZE108;
  802. if (!strcmp("input_size112", tname))
  803. return TEST_IN_SIZE112;
  804. if (!strcmp("input_size116", tname))
  805. return TEST_IN_SIZE116;
  806. if (!strcmp("input_size120", tname))
  807. return TEST_IN_SIZE120;
  808. if (!strcmp("input_size124", tname))
  809. return TEST_IN_SIZE124;
  810. if (!strcmp("input_size128", tname))
  811. return TEST_IN_SIZE128;
  812. if (!strcmp("input_size132", tname))
  813. return TEST_IN_SIZE132;
  814. if (!strcmp("input_size136", tname))
  815. return TEST_IN_SIZE136;
  816. if (!strcmp("input_size140", tname))
  817. return TEST_IN_SIZE140;
  818. if (!strcmp("input_size144", tname))
  819. return TEST_IN_SIZE144;
  820. if (!strcmp("input_size148", tname))
  821. return TEST_IN_SIZE148;
  822. if (!strcmp("input_size152", tname))
  823. return TEST_IN_SIZE152;
  824. if (!strcmp("input_size156", tname))
  825. return TEST_IN_SIZE156;
  826. if (!strcmp("input_size160", tname))
  827. return TEST_IN_SIZE160;
  828. if (!strcmp("input_size164", tname))
  829. return TEST_IN_SIZE164;
  830. if (!strcmp("input_size168", tname))
  831. return TEST_IN_SIZE168;
  832. if (!strcmp("input_size172", tname))
  833. return TEST_IN_SIZE172;
  834. if (!strcmp("input_size176", tname))
  835. return TEST_IN_SIZE176;
  836. if (!strcmp("input_size180", tname))
  837. return TEST_IN_SIZE180;
  838. if (!strcmp("input_size184", tname))
  839. return TEST_IN_SIZE184;
  840. if (!strcmp("input_size188", tname))
  841. return TEST_IN_SIZE188;
  842. if (!strcmp("input_size192", tname))
  843. return TEST_IN_SIZE192;
  844. if (!strcmp("input_size196", tname))
  845. return TEST_IN_SIZE196;
  846. if (!strcmp("input_size200", tname))
  847. return TEST_IN_SIZE200;
  848. if (!strcmp("input_size204", tname))
  849. return TEST_IN_SIZE204;
  850. if (!strcmp("input_size208", tname))
  851. return TEST_IN_SIZE208;
  852. if (!strcmp("input_size212", tname))
  853. return TEST_IN_SIZE212;
  854. if (!strcmp("input_size216", tname))
  855. return TEST_IN_SIZE216;
  856. if (!strcmp("input_size220", tname))
  857. return TEST_IN_SIZE220;
  858. if (!strcmp("input_size224", tname))
  859. return TEST_IN_SIZE224;
  860. if (!strcmp("input_size228", tname))
  861. return TEST_IN_SIZE228;
  862. if (!strcmp("input_size232", tname))
  863. return TEST_IN_SIZE232;
  864. if (!strcmp("input_size236", tname))
  865. return TEST_IN_SIZE236;
  866. if (!strcmp("input_size240", tname))
  867. return TEST_IN_SIZE240;
  868. if (!strcmp("input_size244", tname))
  869. return TEST_IN_SIZE244;
  870. if (!strcmp("input_full_supp_trace", tname))
  871. return TEST_IN_FULL_SUPP_TRACE;
  872. return -1;
  873. }
  874. static int ipv6_addr_equal(const struct in6_addr *a1, const struct in6_addr *a2)
  875. {
  876. return ((a1->s6_addr32[0] ^ a2->s6_addr32[0]) |
  877. (a1->s6_addr32[1] ^ a2->s6_addr32[1]) |
  878. (a1->s6_addr32[2] ^ a2->s6_addr32[2]) |
  879. (a1->s6_addr32[3] ^ a2->s6_addr32[3])) == 0;
  880. }
  881. static int get_u32(__u32 *val, const char *arg, int base)
  882. {
  883. unsigned long res;
  884. char *ptr;
  885. if (!arg || !*arg)
  886. return -1;
  887. res = strtoul(arg, &ptr, base);
  888. if (!ptr || ptr == arg || *ptr)
  889. return -1;
  890. if (res == ULONG_MAX && errno == ERANGE)
  891. return -1;
  892. if (res > 0xFFFFFFFFUL)
  893. return -1;
  894. *val = res;
  895. return 0;
  896. }
  897. static int get_u16(__u16 *val, const char *arg, int base)
  898. {
  899. unsigned long res;
  900. char *ptr;
  901. if (!arg || !*arg)
  902. return -1;
  903. res = strtoul(arg, &ptr, base);
  904. if (!ptr || ptr == arg || *ptr)
  905. return -1;
  906. if (res == ULONG_MAX && errno == ERANGE)
  907. return -1;
  908. if (res > 0xFFFFUL)
  909. return -1;
  910. *val = res;
  911. return 0;
  912. }
  913. static int get_u8(__u8 *val, const char *arg, int base)
  914. {
  915. unsigned long res;
  916. char *ptr;
  917. if (!arg || !*arg)
  918. return -1;
  919. res = strtoul(arg, &ptr, base);
  920. if (!ptr || ptr == arg || *ptr)
  921. return -1;
  922. if (res == ULONG_MAX && errno == ERANGE)
  923. return -1;
  924. if (res > 0xFFUL)
  925. return -1;
  926. *val = res;
  927. return 0;
  928. }
  929. int main(int argc, char **argv)
  930. {
  931. __u8 buffer[512], *ptr, nexthdr, tr_size;
  932. struct ioam6_trace_hdr *trace;
  933. unsigned int hoplen, ret = 1;
  934. struct ipv6_hopopt_hdr *hbh;
  935. int fd, size, testname_id;
  936. struct in6_addr src, dst;
  937. struct ioam6_hdr *ioam6;
  938. struct timeval timeout;
  939. struct ipv6hdr *ipv6;
  940. __u32 tr_type;
  941. __u16 ioam_ns;
  942. if (argc != 9)
  943. goto out;
  944. testname_id = str2id(argv[2]);
  945. if (testname_id < 0 ||
  946. inet_pton(AF_INET6, argv[3], &src) != 1 ||
  947. inet_pton(AF_INET6, argv[4], &dst) != 1 ||
  948. get_u32(&tr_type, argv[5], 16) ||
  949. get_u8(&tr_size, argv[6], 0) ||
  950. get_u16(&ioam_ns, argv[7], 0))
  951. goto out;
  952. nexthdr = (!strcmp(argv[8], "encap") ? IPPROTO_IPV6 : IPPROTO_ICMPV6);
  953. hoplen = sizeof(*hbh);
  954. hoplen += 2; // 2-byte padding for alignment
  955. hoplen += sizeof(*ioam6); // IOAM option header
  956. hoplen += sizeof(*trace); // IOAM trace header
  957. hoplen += tr_size; // IOAM trace size
  958. hoplen += (tr_size % 8); // optional padding
  959. fd = socket(AF_PACKET, SOCK_DGRAM, __cpu_to_be16(ETH_P_IPV6));
  960. if (fd < 0)
  961. goto out;
  962. if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE,
  963. argv[1], strlen(argv[1])))
  964. goto close;
  965. timeout.tv_sec = 1;
  966. timeout.tv_usec = 0;
  967. if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO,
  968. (const char *)&timeout, sizeof(timeout)))
  969. goto close;
  970. recv:
  971. size = recv(fd, buffer, sizeof(buffer), 0);
  972. if (size <= 0)
  973. goto close;
  974. ipv6 = (struct ipv6hdr *)buffer;
  975. /* Skip packets that do not have the expected src/dst address or that
  976. * do not have a Hop-by-hop.
  977. */
  978. if (!ipv6_addr_equal(&ipv6->saddr, &src) ||
  979. !ipv6_addr_equal(&ipv6->daddr, &dst) ||
  980. ipv6->nexthdr != IPPROTO_HOPOPTS)
  981. goto recv;
  982. /* Check Hbh's Next Header and Size. */
  983. hbh = (struct ipv6_hopopt_hdr *)(buffer + sizeof(*ipv6));
  984. if (hbh->nexthdr != nexthdr || hbh->hdrlen != (hoplen >> 3) - 1)
  985. goto close;
  986. /* Check we have a 2-byte padding for alignment. */
  987. ptr = (__u8 *)hbh + sizeof(*hbh);
  988. if (ptr[0] != IPV6_TLV_PADN && ptr[1] != 0)
  989. goto close;
  990. /* Check we now have the IOAM option. */
  991. ptr += 2;
  992. if (ptr[0] != IPV6_TLV_IOAM)
  993. goto close;
  994. /* Check its size and the IOAM option type. */
  995. ioam6 = (struct ioam6_hdr *)ptr;
  996. if (ioam6->opt_len != sizeof(*ioam6) - 2 + sizeof(*trace) + tr_size ||
  997. ioam6->type != IOAM6_TYPE_PREALLOC)
  998. goto close;
  999. trace = (struct ioam6_trace_hdr *)(ptr + sizeof(*ioam6));
  1000. /* Check the trailing 4-byte padding (potentially). */
  1001. ptr = (__u8 *)trace + sizeof(*trace) + tr_size;
  1002. if (tr_size % 8 && ptr[0] != IPV6_TLV_PADN && ptr[1] != 2 &&
  1003. ptr[2] != 0 && ptr[3] != 0)
  1004. goto close;
  1005. /* Check the IOAM header and data. */
  1006. ret = check_ioam_trace(testname_id, trace, tr_type, tr_size, ioam_ns);
  1007. close:
  1008. close(fd);
  1009. out:
  1010. return ret;
  1011. }