1 /* $OpenBSD: tlv.c,v 1.15 2016/10/10 02:26:24 gsoares Exp $ */ 2 3 /* 4 * Copyright (c) 2015 Renato Westphal <renato@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 <sys/types.h> 20 #include <sys/utsname.h> 21 22 #include <stdio.h> 23 #include <stdlib.h> 24 #include <string.h> 25 26 #include "eigrpd.h" 27 #include "eigrpe.h" 28 #include "log.h" 29 30 int 31 gen_parameter_tlv(struct ibuf *buf, struct eigrp_iface *ei, int peerterm) 32 { 33 struct tlv_parameter tp; 34 35 tp.type = htons(TLV_TYPE_PARAMETER); 36 tp.length = htons(TLV_TYPE_PARAMETER_LEN); 37 if (peerterm) { 38 tp.kvalues[0] = 255; 39 tp.kvalues[1] = 255; 40 tp.kvalues[2] = 255; 41 tp.kvalues[3] = 255; 42 tp.kvalues[4] = 255; 43 tp.kvalues[5] = 0; 44 } else 45 memcpy(tp.kvalues, ei->eigrp->kvalues, 6); 46 tp.holdtime = htons(ei->hello_holdtime); 47 48 return (ibuf_add(buf, &tp, sizeof(tp))); 49 } 50 51 int 52 gen_sequence_tlv(struct ibuf *buf, struct seq_addr_head *seq_addr_list) 53 { 54 struct tlv tlv, *tlvp; 55 struct seq_addr_entry *sa; 56 uint8_t alen; 57 uint16_t len = TLV_HDR_LEN; 58 size_t original_size = ibuf_size(buf); 59 60 tlv.type = htons(TLV_TYPE_SEQ); 61 if (ibuf_add(buf, &tlv, sizeof(tlv))) { 62 log_warn("%s: ibuf_add failed", __func__); 63 return (-1); 64 } 65 66 TAILQ_FOREACH(sa, seq_addr_list, entry) { 67 switch (sa->af) { 68 case AF_INET: 69 alen = INADDRSZ; 70 break; 71 case AF_INET6: 72 alen = IN6ADDRSZ; 73 break; 74 default: 75 fatalx("gen_sequence_tlv: unknown address family"); 76 } 77 if (ibuf_add(buf, &alen, sizeof(alen))) 78 return (-1); 79 if (ibuf_add(buf, &sa->addr, alen)) { 80 log_warn("%s: ibuf_add failed", __func__); 81 return (-1); 82 } 83 84 len += (sizeof(alen) + alen); 85 } 86 87 /* adjust tlv length */ 88 if ((tlvp = ibuf_seek(buf, original_size, sizeof(*tlvp))) == NULL) 89 fatalx("gen_sequence_tlv: buf_seek failed"); 90 tlvp->length = htons(len); 91 92 return (0); 93 } 94 95 int 96 gen_sw_version_tlv(struct ibuf *buf) 97 { 98 struct tlv_sw_version ts; 99 struct utsname u; 100 unsigned int vendor_os_major; 101 unsigned int vendor_os_minor; 102 103 memset(&ts, 0, sizeof(ts)); 104 ts.type = htons(TLV_TYPE_SW_VERSION); 105 ts.length = htons(TLV_TYPE_SW_VERSION_LEN); 106 if (uname(&u) >= 0) { 107 if (sscanf(u.release, "%u.%u", &vendor_os_major, 108 &vendor_os_minor) == 2) { 109 ts.vendor_os_major = (uint8_t) vendor_os_major; 110 ts.vendor_os_minor = (uint8_t) vendor_os_minor; 111 } 112 } 113 ts.eigrp_major = EIGRP_VERSION_MAJOR; 114 ts.eigrp_minor = EIGRP_VERSION_MINOR; 115 116 return (ibuf_add(buf, &ts, sizeof(ts))); 117 } 118 119 int 120 gen_mcast_seq_tlv(struct ibuf *buf, uint32_t seq) 121 { 122 struct tlv_mcast_seq tm; 123 124 tm.type = htons(TLV_TYPE_MCAST_SEQ); 125 tm.length = htons(TLV_TYPE_MCAST_SEQ_LEN); 126 tm.seq = htonl(seq); 127 128 return (ibuf_add(buf, &tm, sizeof(tm))); 129 } 130 131 uint16_t 132 len_route_tlv(struct rinfo *ri) 133 { 134 uint16_t len = TLV_HDR_LEN; 135 136 switch (ri->af) { 137 case AF_INET: 138 len += sizeof(ri->nexthop.v4); 139 len += PREFIX_SIZE4(ri->prefixlen); 140 break; 141 case AF_INET6: 142 len += sizeof(ri->nexthop.v6); 143 len += PREFIX_SIZE6(ri->prefixlen); 144 break; 145 default: 146 break; 147 } 148 149 len += sizeof(ri->metric); 150 if (ri->type == EIGRP_ROUTE_EXTERNAL) 151 len += sizeof(ri->emetric); 152 153 len += sizeof(ri->prefixlen); 154 155 return (len); 156 } 157 158 int 159 gen_route_tlv(struct ibuf *buf, struct rinfo *ri) 160 { 161 struct tlv tlv, *tlvp; 162 struct in_addr addr; 163 struct classic_metric metric; 164 struct classic_emetric emetric; 165 uint16_t tlvlen; 166 uint8_t pflen; 167 size_t original_size = ibuf_size(buf); 168 169 switch (ri->af) { 170 case AF_INET: 171 tlv.type = TLV_PROTO_IPV4; 172 break; 173 case AF_INET6: 174 tlv.type = TLV_PROTO_IPV6; 175 break; 176 default: 177 fatalx("gen_route_tlv: unknown af"); 178 } 179 180 switch (ri->type) { 181 case EIGRP_ROUTE_INTERNAL: 182 tlv.type |= TLV_ROUTE_INTERNAL; 183 break; 184 case EIGRP_ROUTE_EXTERNAL: 185 tlv.type |= TLV_ROUTE_EXTERNAL; 186 break; 187 default: 188 fatalx("gen_route_tlv: unknown type"); 189 } 190 tlv.type = htons(tlv.type); 191 192 if (ibuf_add(buf, &tlv, sizeof(tlv))) 193 return (-1); 194 tlvlen = TLV_HDR_LEN; 195 196 /* nexthop */ 197 switch (ri->af) { 198 case AF_INET: 199 addr.s_addr = htonl(ri->nexthop.v4.s_addr); 200 if (ibuf_add(buf, &addr, sizeof(addr))) 201 return (-1); 202 tlvlen += sizeof(ri->nexthop.v4); 203 break; 204 case AF_INET6: 205 if (ibuf_add(buf, &ri->nexthop.v6, sizeof(ri->nexthop.v6))) 206 return (-1); 207 tlvlen += sizeof(ri->nexthop.v6); 208 break; 209 default: 210 fatalx("gen_route_tlv: unknown af"); 211 } 212 213 /* exterior metric */ 214 if (ri->type == EIGRP_ROUTE_EXTERNAL) { 215 emetric = ri->emetric; 216 emetric.routerid = htonl(emetric.routerid); 217 emetric.as = htonl(emetric.as); 218 emetric.tag = htonl(emetric.tag); 219 emetric.metric = htonl(emetric.metric); 220 emetric.reserved = htons(emetric.reserved); 221 if (ibuf_add(buf, &emetric, sizeof(emetric))) 222 return (-1); 223 tlvlen += sizeof(emetric); 224 } 225 226 /* metric */ 227 metric = ri->metric; 228 metric.delay = htonl(metric.delay); 229 metric.bandwidth = htonl(metric.bandwidth); 230 if (ibuf_add(buf, &metric, sizeof(metric))) 231 return (-1); 232 tlvlen += sizeof(metric); 233 234 /* destination */ 235 if (ibuf_add(buf, &ri->prefixlen, sizeof(ri->prefixlen))) 236 return (-1); 237 switch (ri->af) { 238 case AF_INET: 239 pflen = PREFIX_SIZE4(ri->prefixlen); 240 if (ibuf_add(buf, &ri->prefix.v4, pflen)) 241 return (-1); 242 break; 243 case AF_INET6: 244 pflen = PREFIX_SIZE6(ri->prefixlen); 245 if (ibuf_add(buf, &ri->prefix.v6, pflen)) 246 return (-1); 247 break; 248 default: 249 fatalx("gen_route_tlv: unknown af"); 250 } 251 tlvlen += sizeof(pflen) + pflen; 252 253 /* adjust tlv length */ 254 if ((tlvp = ibuf_seek(buf, original_size, sizeof(*tlvp))) == NULL) 255 fatalx("gen_route_tlv: buf_seek failed"); 256 tlvp->length = htons(tlvlen); 257 258 return (0); 259 } 260 261 struct tlv_parameter * 262 tlv_decode_parameter(struct tlv *tlv, char *buf) 263 { 264 struct tlv_parameter *tp; 265 266 if (ntohs(tlv->length) != TLV_TYPE_PARAMETER_LEN) { 267 log_debug("%s: malformed tlv (bad length)", __func__); 268 return (NULL); 269 } 270 tp = (struct tlv_parameter *)buf; 271 return (tp); 272 } 273 274 int 275 tlv_decode_seq(int af, struct tlv *tlv, char *buf, 276 struct seq_addr_head *seq_addr_list) 277 { 278 uint16_t len; 279 uint8_t alen; 280 struct seq_addr_entry *sa; 281 282 len = ntohs(tlv->length); 283 if (len < TLV_HDR_LEN) { 284 log_debug("%s: malformed tlv (bad length)", __func__); 285 return (-1); 286 } 287 buf += TLV_HDR_LEN; 288 len -= TLV_HDR_LEN; 289 290 while (len > 0) { 291 memcpy(&alen, buf, sizeof(alen)); 292 buf += sizeof(alen); 293 len -= sizeof(alen); 294 if (alen > len) { 295 log_debug("%s: malformed tlv (bad length)", __func__); 296 return (-1); 297 } 298 299 switch (af) { 300 case AF_INET: 301 if (alen != INADDRSZ) { 302 log_debug("%s: invalid address length", 303 __func__); 304 return (-1); 305 } 306 break; 307 case AF_INET6: 308 if (alen != IN6ADDRSZ) { 309 log_debug("%s: invalid address length", 310 __func__); 311 return (-1); 312 } 313 break; 314 default: 315 fatalx("tlv_decode_seq: unknown af"); 316 } 317 if ((sa = calloc(1, sizeof(*sa))) == NULL) 318 fatal("tlv_decode_seq"); 319 sa->af = af; 320 memcpy(&sa->addr, buf, alen); 321 TAILQ_INSERT_TAIL(seq_addr_list, sa, entry); 322 323 buf += alen; 324 len -= alen; 325 } 326 327 return (0); 328 } 329 330 struct tlv_sw_version * 331 tlv_decode_sw_version(struct tlv *tlv, char *buf) 332 { 333 struct tlv_sw_version *tv; 334 335 if (ntohs(tlv->length) != TLV_TYPE_SW_VERSION_LEN) { 336 log_debug("%s: malformed tlv (bad length)", __func__); 337 return (NULL); 338 } 339 tv = (struct tlv_sw_version *)buf; 340 return (tv); 341 } 342 343 struct tlv_mcast_seq * 344 tlv_decode_mcast_seq(struct tlv *tlv, char *buf) 345 { 346 struct tlv_mcast_seq *tm; 347 348 if (ntohs(tlv->length) != TLV_TYPE_MCAST_SEQ_LEN) { 349 log_debug("%s: malformed tlv (bad length)", __func__); 350 return (NULL); 351 } 352 tm = (struct tlv_mcast_seq *)buf; 353 return (tm); 354 } 355 356 int 357 tlv_decode_route(int af, struct tlv *tlv, char *buf, struct rinfo *ri) 358 { 359 unsigned int tlv_len, min_len, max_plen, plen, offset; 360 361 ri->af = af; 362 switch (ri->af) { 363 case AF_INET: 364 min_len = TLV_TYPE_IPV4_INT_MIN_LEN; 365 max_plen = sizeof(ri->prefix.v4); 366 break; 367 case AF_INET6: 368 min_len = TLV_TYPE_IPV6_INT_MIN_LEN; 369 max_plen = sizeof(ri->prefix.v6); 370 break; 371 default: 372 fatalx("tlv_decode_route: unknown af"); 373 } 374 375 switch (ntohs(tlv->type) & TLV_TYPE_MASK) { 376 case TLV_ROUTE_INTERNAL: 377 ri->type = EIGRP_ROUTE_INTERNAL; 378 break; 379 case TLV_ROUTE_EXTERNAL: 380 ri->type = EIGRP_ROUTE_EXTERNAL; 381 min_len += sizeof(struct classic_emetric); 382 break; 383 default: 384 fatalx("tlv_decode_route: unknown type"); 385 } 386 387 tlv_len = ntohs(tlv->length); 388 if (tlv_len < min_len) { 389 log_debug("%s: malformed tlv (bad length)", __func__); 390 return (-1); 391 } 392 393 /* nexthop */ 394 offset = TLV_HDR_LEN; 395 switch (af) { 396 case AF_INET: 397 memcpy(&ri->nexthop.v4, buf + offset, sizeof(ri->nexthop.v4)); 398 offset += sizeof(ri->nexthop.v4); 399 break; 400 case AF_INET6: 401 memcpy(&ri->nexthop.v6, buf + offset, sizeof(ri->nexthop.v6)); 402 offset += sizeof(ri->nexthop.v6); 403 break; 404 default: 405 fatalx("tlv_decode_route: unknown af"); 406 } 407 408 /* exterior metric */ 409 if (ri->type == EIGRP_ROUTE_EXTERNAL) { 410 memcpy(&ri->emetric, buf + offset, sizeof(ri->emetric)); 411 ri->emetric.routerid = ntohl(ri->emetric.routerid); 412 ri->emetric.as = ntohl(ri->emetric.as); 413 ri->emetric.tag = ntohl(ri->emetric.tag); 414 ri->emetric.metric = ntohl(ri->emetric.metric); 415 ri->emetric.reserved = ntohs(ri->emetric.reserved); 416 offset += sizeof(ri->emetric); 417 } 418 419 /* metric */ 420 memcpy(&ri->metric, buf + offset, sizeof(ri->metric)); 421 ri->metric.delay = ntohl(ri->metric.delay); 422 ri->metric.bandwidth = ntohl(ri->metric.bandwidth); 423 offset += sizeof(ri->metric); 424 425 /* prefixlen */ 426 memcpy(&ri->prefixlen, buf + offset, sizeof(ri->prefixlen)); 427 offset += sizeof(ri->prefixlen); 428 429 /* 430 * Different versions of IOS can use a different number of bytes to 431 * encode the same IPv6 prefix. This sucks but we have to deal with it. 432 * Instead of calculating the number of bytes based on the value of the 433 * prefixlen field, let's get this number by subtracting the size of all 434 * other fields from the total size of the TLV. It works because all 435 * the other fields have a fixed length. 436 */ 437 plen = tlv_len - min_len; 438 439 /* safety check */ 440 if (plen > max_plen) { 441 log_debug("%s: malformed tlv", __func__); 442 return (-1); 443 } 444 445 /* destination */ 446 switch (af) { 447 case AF_INET: 448 memset(&ri->prefix.v4, 0, sizeof(ri->prefix.v4)); 449 memcpy(&ri->prefix.v4, buf + offset, plen); 450 break; 451 case AF_INET6: 452 memset(&ri->prefix.v6, 0, sizeof(ri->prefix.v6)); 453 memcpy(&ri->prefix.v6, buf + offset, plen); 454 break; 455 default: 456 fatalx("tlv_decode_route: unknown af"); 457 } 458 459 /* check if the network is valid */ 460 if (bad_addr(af, &ri->prefix) || 461 (af == AF_INET6 && IN6_IS_SCOPE_EMBED(&ri->prefix.v6))) { 462 log_debug("%s: malformed tlv (invalid prefix): %s", __func__, 463 log_addr(af, &ri->prefix)); 464 return (-1); 465 } 466 467 /* just in case... */ 468 eigrp_applymask(af, &ri->prefix, &ri->prefix, ri->prefixlen); 469 470 return (0); 471 } 472 473 void 474 metric_encode_mtu(uint8_t *dst, int mtu) 475 { 476 dst[0] = (mtu & 0x00FF0000) >> 16; 477 dst[1] = (mtu & 0x0000FF00) >> 8; 478 dst[2] = (mtu & 0x000000FF); 479 } 480 481 int 482 metric_decode_mtu(uint8_t *mtu) 483 { 484 return ((mtu[0] << 16) + (mtu[1] << 8) + mtu[2]); 485 } 486