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