1/* $OpenBSD: rde_flowspec_test.c,v 1.2 2023/04/18 06:41:00 claudio Exp $ */ 2 3/* 4 * Copyright (c) 2023 Claudio Jeker <claudio@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19#include <err.h> 20#include <stdio.h> 21 22#include "bgpd.h" 23#include "rde.h" 24 25const uint8_t ordered0[] = { 0x01, 0x00, 0x02, 0x00, 0x03, 0x80, 0x00 }; 26const uint8_t ordered1[] = { 0x02, 0x00, 0x01, 0x00, 0x03, 0x80, 0x00 }; 27const uint8_t ordered2[] = { 0x02, 0x00, 0x03, 0x80, 0x00, 0x01, 0x00 }; 28const uint8_t ordered3[] = { 0x01, 0x00, 0x01, 0x00, 0x03, 0x80, 0x00 }; 29 30const uint8_t minmax0[] = { 0x00, 0x00 }; 31const uint8_t minmax1[] = { 0x0e, 0x00 }; 32const uint8_t minmax2[] = { 0xfe, 0x00 }; 33 34const uint8_t flow[] = { 0x0d, 0x80, 0x00 }; 35 36const uint8_t badand[] = { 0x04, 0xc0, 0x00 }; 37const uint8_t goodand[] = { 0x04, 0x00, 0x00, 0xc0, 0x00 }; 38 39const uint8_t overflow0[] = { 0x04 }; 40const uint8_t overflow1[] = { 0x04, 0x80 }; 41const uint8_t overflow2[] = { 0x04, 0x90, 0x00 }; 42const uint8_t overflow3[] = { 0x04, 0xc0, 0x00, 0x00, 0x00 }; 43const uint8_t overflow4[] = { 0x04, 0x00, 0x00 }; 44const uint8_t overflow5[] = { 0x04, 0x00, 0x00, 0x80 }; 45const uint8_t overflow6[] = { 0x04, 0x10, 0x00, 0x80 }; 46const uint8_t prefix0[] = { 0x01 }; 47const uint8_t prefix1[] = { 0x01, 0x07 }; 48const uint8_t prefix2[] = { 0x01, 0x0a, 0xef }; 49const uint8_t prefix3[] = { 0x01, 0x11, 0xef, 0x00 }; 50const uint8_t prefix4[] = { 0x01, 0x21, 0xef, 0x00, 0x00, 0x01, 0x00 }; 51const uint8_t prefix60[] = { 0x01 }; 52const uint8_t prefix61[] = { 0x01, 0x07 }; 53const uint8_t prefix62[] = { 0x01, 0x10, 0x1 }; 54const uint8_t prefix63[] = { 0x01, 0x10, 0x01, 0x20 }; 55const uint8_t prefix64[] = { 0x01, 0x81, 0x73, 0x20, 0x01 }; 56const uint8_t prefix65[] = { 0x01, 0x80, 0x83, 0x20, 0x01 }; 57const uint8_t prefix66[] = { 0x01, 0x40, 0x40, 0x20, 0x01 }; 58 59static void 60test_flowspec_valid(void) 61{ 62 /* empty NLRI is invalid */ 63 if (flowspec_valid(NULL, 0, 0) != -1) 64 errx(1, "empty NLRI is not invalid"); 65 66 /* ensure that type range is checked */ 67 if (flowspec_valid(minmax0, sizeof(minmax0), 0) != -1 || 68 flowspec_valid(minmax1, sizeof(minmax1), 0) != -1 || 69 flowspec_valid(minmax2, sizeof(minmax2), 0) != -1) 70 errx(1, "out of range type is not invalid"); 71 72 /* ensure that types are ordered */ 73 if (flowspec_valid(ordered0, sizeof(ordered0), 0) != 0) 74 errx(1, "in order NLRI is not valid"); 75 if (flowspec_valid(ordered1, sizeof(ordered1), 0) != -1 || 76 flowspec_valid(ordered2, sizeof(ordered2), 0) != -1 || 77 flowspec_valid(ordered3, sizeof(ordered3), 0) != -1) 78 errx(1, "out of order types are not invalid"); 79 80 /* flow is only valid in the IPv6 case */ 81 if (flowspec_valid(flow, sizeof(flow), 0) != -1) 82 errx(1, "FLOW type for IPv4 is not invalid"); 83 if (flowspec_valid(flow, sizeof(flow), 1) != 0) 84 errx(1, "FLOW type for IPv4 is not valid"); 85 86 /* first component cannot have and flag set */ 87 if (flowspec_valid(badand, sizeof(badand), 0) != -1) 88 errx(1, "AND in first element is not invalid"); 89 if (flowspec_valid(goodand, sizeof(goodand), 0) != 0) 90 errx(1, "AND in other element is not valid"); 91 92 /* various overflows */ 93 if (flowspec_valid(overflow0, sizeof(overflow0), 0) != -1 || 94 flowspec_valid(overflow1, sizeof(overflow1), 0) != -1 || 95 flowspec_valid(overflow2, sizeof(overflow2), 0) != -1 || 96 flowspec_valid(overflow3, sizeof(overflow3), 0) != -1 || 97 flowspec_valid(overflow4, sizeof(overflow4), 0) != -1 || 98 flowspec_valid(overflow5, sizeof(overflow5), 0) != -1 || 99 flowspec_valid(overflow6, sizeof(overflow6), 0) != -1) 100 errx(1, "overflow not detected"); 101 102 if (flowspec_valid(prefix0, sizeof(prefix0), 0) != -1 || 103 flowspec_valid(prefix1, sizeof(prefix1), 0) != -1 || 104 flowspec_valid(prefix2, sizeof(prefix2), 0) != -1 || 105 flowspec_valid(prefix3, sizeof(prefix3), 0) != -1 || 106 flowspec_valid(prefix4, sizeof(prefix4), 0) != -1) 107 errx(1, "bad prefix encoding is not invalid"); 108 109 if (flowspec_valid(prefix60, sizeof(prefix60), 1) != -1 || 110 flowspec_valid(prefix61, sizeof(prefix61), 1) != -1 || 111 flowspec_valid(prefix62, sizeof(prefix62), 1) != -1 || 112 flowspec_valid(prefix63, sizeof(prefix63), 1) != -1 || 113 flowspec_valid(prefix64, sizeof(prefix64), 1) != -1 || 114 flowspec_valid(prefix65, sizeof(prefix65), 1) != -1 || 115 flowspec_valid(prefix66, sizeof(prefix66), 1) != -1) 116 errx(1, "bad IPv6 prefix encoding is not invalid"); 117} 118 119static int 120do_cmp(const uint8_t *a, int alen, const uint8_t *b, int blen, int is_v6) 121{ 122 if (flowspec_cmp(a, alen, b, blen, is_v6) != -1 || 123 flowspec_cmp(b, blen, a, alen, is_v6) != 1) 124 return -1; 125 return 0; 126} 127 128const uint8_t cmp1[] = { 0x01, 0x00 }; 129const uint8_t cmp2[] = { 0x02, 0x00 }; 130const uint8_t cmp3[] = { 0x01, 0x00, 0x2, 0x00 }; 131const uint8_t cmp4[] = { 0x04, 0x80, 0x2 }; 132const uint8_t cmp5[] = { 0x04, 0x80, 0x3 }; 133const uint8_t cmp6[] = { 0x04, 0x00, 0x3, 0x80, 0x02 }; 134 135const uint8_t cmp41[] = { 0x01, 24, 192, 168, 16 }; 136const uint8_t cmp42[] = { 0x01, 24, 192, 168, 32 }; 137const uint8_t cmp43[] = { 0x01, 24, 192, 168, 42 }; 138const uint8_t cmp44[] = { 0x01, 20, 192, 168, 32 }; 139 140const uint8_t cmp61[] = { 0x01, 48, 0, 0x20, 0x01, 0x0d, 0xb8, 0xc0, 0xfe }; 141const uint8_t cmp62[] = { 0x01, 48, 8, 0x01, 0x0d, 0xb8, 0xc0, 0xfe }; 142const uint8_t cmp63[] = { 0x01, 40, 0, 0x20, 0x01, 0x0d, 0xb8, 0xc0 }; 143const uint8_t cmp64[] = { 0x01, 40, 0, 0x20, 0x01, 0x0d, 0xb8, 0xd0 }; 144 145static void 146test_flowspec_cmp(void) 147{ 148 if (do_cmp(cmp1, sizeof(cmp1), cmp2, sizeof(cmp2), 0) != 0) 149 errx(1, "cmp on type failed"); 150 if (do_cmp(cmp3, sizeof(cmp3), cmp1, sizeof(cmp1), 0) != 0) 151 errx(1, "cmp on more components failed"); 152 if (do_cmp(cmp4, sizeof(cmp4), cmp5, sizeof(cmp5), 0) != 0) 153 errx(1, "cmp on lowest common component failed"); 154 if (do_cmp(cmp6, sizeof(cmp6), cmp5, sizeof(cmp5), 0) != 0) 155 errx(1, "cmp on lowest common component failed"); 156 if (do_cmp(cmp6, sizeof(cmp6), cmp4, sizeof(cmp4), 0) != 0) 157 errx(1, "cmp on lowest common component failed"); 158 159 if (do_cmp(cmp41, sizeof(cmp41), cmp42, sizeof(cmp42), 0) != 0) 160 errx(1, "cmp 1 on prefix component failed"); 161 if (do_cmp(cmp41, sizeof(cmp41), cmp43, sizeof(cmp43), 0) != 0) 162 errx(1, "cmp 2 on prefix component failed"); 163 if (do_cmp(cmp41, sizeof(cmp41), cmp44, sizeof(cmp44), 0) != 0) 164 errx(1, "cmp 3 on prefix component failed"); 165 if (do_cmp(cmp42, sizeof(cmp42), cmp43, sizeof(cmp43), 0) != 0) 166 errx(1, "cmp 4 on prefix component failed"); 167 if (do_cmp(cmp42, sizeof(cmp42), cmp44, sizeof(cmp44), 0) != 0) 168 errx(1, "cmp 5 on prefix component failed"); 169 if (do_cmp(cmp43, sizeof(cmp43), cmp44, sizeof(cmp44), 0) != 0) 170 errx(1, "cmp 6 on prefix component failed"); 171 172 if (do_cmp(cmp61, sizeof(cmp61), cmp62, sizeof(cmp62), 1) != 0) 173 errx(1, "cmp 1 on inet6 prefix component failed"); 174 if (do_cmp(cmp61, sizeof(cmp61), cmp63, sizeof(cmp63), 1) != 0) 175 errx(1, "cmp 1 on inet6 prefix component failed"); 176 if (do_cmp(cmp61, sizeof(cmp61), cmp64, sizeof(cmp64), 1) != 0) 177 errx(1, "cmp 1 on inet6 prefix component failed"); 178 if (do_cmp(cmp63, sizeof(cmp63), cmp64, sizeof(cmp64), 1) != 0) 179 errx(1, "cmp 1 on inet6 prefix component failed"); 180} 181 182int 183main(int argc, char **argv) 184{ 185 test_flowspec_valid(); 186 test_flowspec_cmp(); 187 printf("OK\n"); 188 return 0; 189} 190 191__dead void 192fatalx(const char *emsg, ...) 193{ 194 va_list ap; 195 va_start(ap, emsg); 196 verrx(2, emsg, ap); 197} 198 199