1 /* $OpenBSD: rde_community_test.c,v 1.2 2019/07/04 10:20:59 claudio Exp $ */ 2 3 /* 4 * Copyright (c) 2019 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 #include <err.h> 19 #include <stdio.h> 20 #include <stdlib.h> 21 #include <string.h> 22 23 #include "rde.h" 24 #include "log.h" 25 26 #include "rde_community_test.h" 27 28 struct rde_memstats rdemem; 29 struct rde_community comm; 30 struct rde_peer peer = { 31 .conf.remote_as = 22512, 32 .conf.local_as = 42, 33 }; 34 35 static void 36 dump(uint8_t *b, size_t len) 37 { 38 size_t l; 39 40 printf("\n\t{\n\t\t.data = \""); 41 for (l = 0; l < len; l++) { 42 printf("\\x%02x", b[l]); 43 if (l % 12 == 0 && l != 0) 44 printf("\"\n\t\t \""); 45 } 46 printf("\",\n\t\t.size = %zu\n\t},\n", len); 47 } 48 49 static int 50 test_parsing(size_t num, uint8_t *in, size_t inlen) 51 { 52 const char *func = "community"; 53 uint8_t flags, type, attr[256]; 54 size_t skip = 2; 55 uint16_t attr_len; 56 int r; 57 58 communities_clean(&comm); 59 60 flags = in[0]; 61 type = in[1]; 62 if (flags & ATTR_EXTLEN) { 63 memcpy(&attr_len, in + 2, sizeof(attr_len)); 64 attr_len = ntohs(attr_len); 65 skip += 2; 66 } else { 67 attr_len = in[2]; 68 skip += 1; 69 } 70 71 switch (type) { 72 case ATTR_COMMUNITIES: 73 r = community_add(&comm, flags, in + skip, attr_len); 74 break; 75 case ATTR_EXT_COMMUNITIES: 76 r = community_ext_add(&comm, flags, in + skip, attr_len); 77 break; 78 case ATTR_LARGE_COMMUNITIES: 79 r = community_large_add(&comm, flags, in + skip, attr_len); 80 break; 81 } 82 if (r == -1) { 83 printf("Test %zu: %s_add failed\n", num, func); 84 return -1; 85 } 86 87 switch (type) { 88 case ATTR_COMMUNITIES: 89 r = community_write(&comm, attr, sizeof(attr)); 90 break; 91 case ATTR_EXT_COMMUNITIES: 92 r = community_ext_write(&comm, 0, attr, sizeof(attr)); 93 break; 94 case ATTR_LARGE_COMMUNITIES: 95 r = community_large_write(&comm, attr, sizeof(attr)); 96 break; 97 } 98 99 if (r != inlen) { 100 printf("Test %zu: %s_write return value %d != %zd\n", 101 num, func, r, inlen); 102 return -1; 103 } 104 if (r != -1 && memcmp(attr, in, inlen) != 0) { 105 printf("Test %zu: %s_write unexpected encoding: ", num, func); 106 dump(attr, inlen); 107 printf("expected: "); 108 dump(in, inlen); 109 return -1; 110 } 111 112 return 0; 113 } 114 115 static int 116 test_filter(size_t num, struct testfilter *f) 117 { 118 size_t l; 119 int r; 120 121 communities_clean(&comm); 122 for (l = 0; f->in[l] != -1; l++) { 123 r = community_set(&comm, &filters[f->in[l]], &peer); 124 if (r != 1) { 125 printf("Test %zu: community_set %zu " 126 "unexpected return %d != 1\n", 127 num, l, r); 128 return -1; 129 } 130 } 131 132 r = community_match(&comm, &filters[f->match], &peer); 133 if (r != f->mout) { 134 printf("Test %zu: community_match " 135 "unexpected return %d != %d\n", num, r, f->mout); 136 return -1; 137 } 138 139 if (f->delete == -1) 140 return 0; 141 142 community_delete(&comm, &filters[f->delete], &peer); 143 144 if (community_match(&comm, &filters[f->delete], &peer) != 0) { 145 printf("Test %zu: community_delete still around\n", num); 146 return -1; 147 } 148 149 return 0; 150 } 151 152 int 153 main(int argc, char *argv[]) 154 { 155 size_t t; 156 int error = 0; 157 158 for (t = 0; t < sizeof(vectors) / sizeof(*vectors); t++) { 159 if (test_parsing(t, vectors[t].data, vectors[t].size) == -1) 160 error = 1; 161 } 162 163 for (t = 0; t < sizeof(testfilters) / sizeof(*testfilters); t++) { 164 if (test_filter(t, &testfilters[t]) == -1) 165 error = 1; 166 } 167 168 if (!error) 169 printf("OK\n"); 170 return error; 171 } 172 173 __dead void 174 fatalx(const char *emsg, ...) 175 { 176 va_list ap; 177 va_start(ap, emsg); 178 verrx(2, emsg, ap); 179 } 180 181 __dead void 182 fatal(const char *emsg, ...) 183 { 184 va_list ap; 185 va_start(ap, emsg); 186 verr(2, emsg, ap); 187 } 188 189 void 190 log_warnx(const char *emsg, ...) 191 { 192 va_list ap; 193 va_start(ap, emsg); 194 vwarnx(emsg, ap); 195 va_end(ap); 196 } 197 198 int 199 attr_write(void *p, u_int16_t p_len, u_int8_t flags, u_int8_t type, 200 void *data, u_int16_t data_len) 201 { 202 u_char *b = p; 203 u_int16_t tmp, tot_len = 2; /* attribute header (without len) */ 204 205 flags &= ~ATTR_DEFMASK; 206 if (data_len > 255) { 207 tot_len += 2 + data_len; 208 flags |= ATTR_EXTLEN; 209 } else { 210 tot_len += 1 + data_len; 211 } 212 213 if (tot_len > p_len) 214 return (-1); 215 216 *b++ = flags; 217 *b++ = type; 218 if (data_len > 255) { 219 tmp = htons(data_len); 220 memcpy(b, &tmp, sizeof(tmp)); 221 b += 2; 222 } else 223 *b++ = (u_char)data_len; 224 225 if (data == NULL) 226 return (tot_len - data_len); 227 228 if (data_len != 0) 229 memcpy(b, data, data_len); 230 231 return (tot_len); 232 } 233 234 int 235 attr_writebuf(struct ibuf *buf, u_int8_t flags, u_int8_t type, void *data, 236 u_int16_t data_len) 237 { 238 return (-1); 239 } 240