1 /* $OpenBSD: labelmapping.c,v 1.18 2010/12/31 21:22:42 guenther Exp $ */ 2 3 /* 4 * Copyright (c) 2009 Michele Marchetto <michele@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/socket.h> 21 #include <sys/uio.h> 22 23 #include <netinet/in.h> 24 #include <netinet/in_systm.h> 25 #include <netinet/ip.h> 26 #include <arpa/inet.h> 27 #include <net/if_dl.h> 28 #include <unistd.h> 29 30 #include <errno.h> 31 #include <event.h> 32 #include <limits.h> 33 #include <stdlib.h> 34 #include <string.h> 35 36 #include "ldpd.h" 37 #include "ldp.h" 38 #include "log.h" 39 #include "ldpe.h" 40 41 void gen_label_tlv(struct ibuf *, u_int32_t); 42 void gen_reqid_tlv(struct ibuf *, u_int32_t); 43 void gen_fec_tlv(struct ibuf *, struct in_addr, u_int8_t); 44 45 int tlv_decode_label(char *, u_int16_t, u_int32_t *); 46 int tlv_decode_reqid(char *, u_int16_t, u_int32_t *); 47 int tlv_decode_fec_elm(char *, u_int16_t, u_int8_t *, u_int32_t *, 48 u_int8_t *); 49 50 /* Label Mapping Message */ 51 void 52 send_labelmapping(struct nbr *nbr) 53 { 54 struct ibuf *buf; 55 struct mapping_entry *me; 56 struct ldp_hdr *ldp_hdr; 57 u_int16_t tlv_size, size; 58 59 if (nbr->iface->passive) 60 return; 61 62 if ((buf = ibuf_open(LDP_MAX_LEN)) == NULL) 63 fatal("send_labelmapping"); 64 65 /* real size will be set up later */ 66 gen_ldp_hdr(buf, nbr->iface, 0); 67 68 size = LDP_HDR_SIZE - TLV_HDR_LEN; 69 70 TAILQ_FOREACH(me, &nbr->mapping_list, entry) { 71 tlv_size = BASIC_LABEL_MAP_LEN + PREFIX_SIZE(me->map.prefixlen); 72 if (me->map.flags & F_MAP_REQ_ID) 73 tlv_size += REQID_TLV_LEN; 74 size += tlv_size; 75 76 gen_msg_tlv(buf, MSG_TYPE_LABELMAPPING, tlv_size); 77 gen_fec_tlv(buf, me->map.prefix, me->map.prefixlen); 78 gen_label_tlv(buf, me->map.label); 79 if (me->map.flags & F_MAP_REQ_ID) 80 gen_reqid_tlv(buf, me->map.requestid); 81 } 82 83 /* XXX: should we remove them first? */ 84 nbr_mapping_list_clr(nbr, &nbr->mapping_list); 85 86 ldp_hdr = ibuf_seek(buf, 0, sizeof(struct ldp_hdr)); 87 ldp_hdr->length = htons(size); 88 89 evbuf_enqueue(&nbr->wbuf, buf); 90 } 91 92 int 93 recv_labelmapping(struct nbr *nbr, char *buf, u_int16_t len) 94 { 95 struct ldp_msg lm; 96 struct fec_tlv ft; 97 struct map map; 98 u_int32_t label; 99 int feclen, lbllen, tlen; 100 u_int8_t addr_type; 101 102 if (nbr->state != NBR_STA_OPER) { 103 log_debug("recv_labelmapping: neighbor ID %s not operational", 104 inet_ntoa(nbr->id)); 105 return (-1); 106 } 107 108 bcopy(buf, &lm, sizeof(lm)); 109 110 buf += sizeof(struct ldp_msg); 111 len -= sizeof(struct ldp_msg); 112 113 if (len < sizeof(ft)) { 114 session_shutdown(nbr, S_BAD_TLV_LEN, lm.msgid, lm.type); 115 return (-1); 116 } 117 118 bcopy(buf, &ft, sizeof(ft)); 119 feclen = ntohs(ft.length); 120 121 if (feclen > len - TLV_HDR_LEN) { 122 session_shutdown(nbr, S_BAD_TLV_LEN, lm.msgid, lm.type); 123 return (-1); 124 } 125 126 buf += TLV_HDR_LEN; /* just advance to the end of the fec header */ 127 len -= TLV_HDR_LEN; 128 129 lbllen = tlv_decode_label(buf + feclen, len - feclen, &label); 130 if (lbllen == -1) { 131 session_shutdown(nbr, S_BAD_TLV_LEN, lm.msgid, lm.type); 132 return (-1); 133 } 134 if (label == NO_LABEL) { 135 session_shutdown(nbr, S_BAD_TLV_VAL, lm.msgid, lm.type); 136 return (-1); 137 } 138 139 /* TODO opt label request msg id, hop cnt and path vektor TLV */ 140 141 bzero(&map, sizeof(map)); 142 map.messageid = lm.msgid; 143 map.label = label; 144 do { 145 if ((tlen = tlv_decode_fec_elm(buf, feclen, &addr_type, 146 &map.prefix.s_addr, &map.prefixlen)) == -1 || 147 addr_type == FEC_WILDCARD) { 148 session_shutdown(nbr, S_BAD_TLV_VAL, lm.msgid, lm.type); 149 return (-1); 150 } 151 152 ldpe_imsg_compose_lde(IMSG_LABEL_MAPPING, nbr->peerid, 0, &map, 153 sizeof(map)); 154 155 buf += tlen; 156 feclen -= tlen; 157 } while (feclen > 0); 158 159 nbr_fsm(nbr, NBR_EVT_PDU_RCVD); 160 161 return (ntohs(lm.length)); 162 } 163 164 /* Label Request Message */ 165 void 166 send_labelrequest(struct nbr *nbr) 167 { 168 struct ibuf *buf; 169 struct mapping_entry *me; 170 struct ldp_hdr *ldp_hdr; 171 u_int16_t tlv_size, size; 172 173 if (nbr->iface->passive) 174 return; 175 176 if ((buf = ibuf_open(LDP_MAX_LEN)) == NULL) 177 fatal("send_labelrequest"); 178 179 /* real size will be set up later */ 180 gen_ldp_hdr(buf, nbr->iface, 0); 181 182 size = LDP_HDR_SIZE - TLV_HDR_LEN; 183 184 TAILQ_FOREACH(me, &nbr->request_list, entry) { 185 tlv_size = PREFIX_SIZE(me->map.prefixlen); 186 size += tlv_size; 187 188 gen_msg_tlv(buf, MSG_TYPE_LABELREQUEST, tlv_size); 189 gen_fec_tlv(buf, me->map.prefix, me->map.prefixlen); 190 } 191 192 /* XXX: should we remove them first? */ 193 nbr_mapping_list_clr(nbr, &nbr->request_list); 194 195 ldp_hdr = ibuf_seek(buf, 0, sizeof(struct ldp_hdr)); 196 ldp_hdr->length = htons(size); 197 198 evbuf_enqueue(&nbr->wbuf, buf); 199 } 200 201 int 202 recv_labelrequest(struct nbr *nbr, char *buf, u_int16_t len) 203 { 204 struct ldp_msg lr; 205 struct fec_tlv ft; 206 struct map map; 207 int feclen, tlen; 208 u_int8_t addr_type; 209 210 if (nbr->state != NBR_STA_OPER) { 211 log_debug("recv_labelrequest: neighbor ID %s not operational", 212 inet_ntoa(nbr->id)); 213 return (-1); 214 } 215 216 bcopy(buf, &lr, sizeof(lr)); 217 218 buf += sizeof(struct ldp_msg); 219 len -= sizeof(struct ldp_msg); 220 221 if (len < sizeof(ft)) { 222 session_shutdown(nbr, S_BAD_MSG_LEN, lr.msgid, lr.type); 223 return (-1); 224 } 225 226 bcopy(buf, &ft, sizeof(ft)); 227 feclen = ntohs(ft.length); 228 229 if (feclen > len - TLV_HDR_LEN) { 230 session_shutdown(nbr, S_BAD_TLV_LEN, lr.msgid, lr.type); 231 return (-1); 232 } 233 234 buf += TLV_HDR_LEN; /* just advance to the end of the fec header */ 235 len -= TLV_HDR_LEN; 236 237 /* TODO opt hop cnt and path vektor TLV */ 238 239 bzero(&map, sizeof(map)); 240 map.messageid = lr.msgid; 241 do { 242 if ((tlen = tlv_decode_fec_elm(buf, feclen, &addr_type, 243 &map.prefix.s_addr, &map.prefixlen)) == -1 || 244 addr_type == FEC_WILDCARD) { 245 session_shutdown(nbr, S_BAD_TLV_VAL, lr.msgid, lr.type); 246 return (-1); 247 } 248 249 ldpe_imsg_compose_lde(IMSG_LABEL_REQUEST, nbr->peerid, 0, &map, 250 sizeof(map)); 251 252 buf += tlen; 253 feclen -= tlen; 254 } while (feclen > 0); 255 256 nbr_fsm(nbr, NBR_EVT_PDU_RCVD); 257 258 return (ntohs(lr.length)); 259 } 260 261 /* Label Withdraw Message */ 262 void 263 send_labelwithdraw(struct nbr *nbr) 264 { 265 struct ibuf *buf; 266 struct mapping_entry *me; 267 struct ldp_hdr *ldp_hdr; 268 u_int16_t tlv_size, size; 269 270 if (nbr->iface->passive) 271 return; 272 273 if ((buf = ibuf_open(LDP_MAX_LEN)) == NULL) 274 fatal("send_labelwithdraw"); 275 276 /* real size will be set up later */ 277 gen_ldp_hdr(buf, nbr->iface, 0); 278 279 size = LDP_HDR_SIZE - TLV_HDR_LEN; 280 281 TAILQ_FOREACH(me, &nbr->withdraw_list, entry) { 282 if (me->map.label == NO_LABEL) 283 tlv_size = PREFIX_SIZE(me->map.prefixlen); 284 else 285 tlv_size = BASIC_LABEL_MAP_LEN + 286 PREFIX_SIZE(me->map.prefixlen); 287 288 size += tlv_size; 289 290 gen_msg_tlv(buf, MSG_TYPE_LABELWITHDRAW, tlv_size); 291 gen_fec_tlv(buf, me->map.prefix, me->map.prefixlen); 292 293 if (me->map.label != NO_LABEL) 294 gen_label_tlv(buf, me->map.label); 295 } 296 297 /* XXX: should we remove them first? */ 298 nbr_mapping_list_clr(nbr, &nbr->withdraw_list); 299 300 ldp_hdr = ibuf_seek(buf, 0, sizeof(struct ldp_hdr)); 301 ldp_hdr->length = htons(size); 302 303 evbuf_enqueue(&nbr->wbuf, buf); 304 } 305 306 int 307 recv_labelwithdraw(struct nbr *nbr, char *buf, u_int16_t len) 308 { 309 struct map map; 310 struct ldp_msg lw; 311 struct fec_tlv ft; 312 u_int32_t label = NO_LABEL; 313 int feclen, tlen, numfec = 0; 314 u_int8_t addr_type; 315 316 if (nbr->state != NBR_STA_OPER) { 317 log_debug("recv_labelwithdraw: neighbor ID %s not operational", 318 inet_ntoa(nbr->id)); 319 return (-1); 320 } 321 322 bcopy(buf, &lw, sizeof(lw)); 323 324 buf += sizeof(struct ldp_msg); 325 len -= sizeof(struct ldp_msg); 326 327 if (len < sizeof(ft)) { 328 session_shutdown(nbr, S_BAD_MSG_LEN, lw.msgid, lw.type); 329 return (-1); 330 } 331 332 bcopy(buf, &ft, sizeof(ft)); 333 feclen = ntohs(ft.length); 334 335 if (feclen > len - TLV_HDR_LEN) { 336 session_shutdown(nbr, S_BAD_TLV_LEN, lw.msgid, lw.type); 337 return (-1); 338 } 339 340 buf += TLV_HDR_LEN; /* just advance to the end of the fec header */ 341 len -= TLV_HDR_LEN; 342 343 /* withdraw may include optional label */ 344 if (len > feclen) { 345 int r; 346 347 r = tlv_decode_label(buf + feclen, len - feclen, &label); 348 if (r == -1 || len != feclen + r) { 349 session_shutdown(nbr, S_BAD_TLV_VAL, lw.msgid, 350 lw.type); 351 return (-1); 352 } 353 } 354 355 bzero(&map, sizeof(map)); 356 map.messageid = lw.msgid; 357 if (label != NO_LABEL) { 358 map.label = label; 359 map.flags = F_MAP_OPTLABEL; 360 } 361 do { 362 if ((tlen = tlv_decode_fec_elm(buf, feclen, &addr_type, 363 &map.prefix.s_addr, &map.prefixlen)) == -1) { 364 session_shutdown(nbr, S_BAD_TLV_VAL, lw.msgid, lw.type); 365 return (-1); 366 } 367 368 if (addr_type == FEC_WILDCARD) { 369 /* Wildcard FEC must be the only FEC element */ 370 if (numfec != 0) { 371 session_shutdown(nbr, S_BAD_TLV_VAL, lw.msgid, 372 lw.type); 373 return (-1); 374 } 375 map.prefix.s_addr = 0; 376 map.prefixlen = 0; 377 map.flags |= F_MAP_WILDCARD; 378 numfec = -1; 379 } else { 380 /* Wildcard FEC must be the only FEC element */ 381 if (numfec == -1) { 382 session_shutdown(nbr, S_BAD_TLV_VAL, lw.msgid, 383 lw.type); 384 return (-1); 385 } 386 numfec++; 387 map.flags &= ~F_MAP_WILDCARD; 388 } 389 390 ldpe_imsg_compose_lde(IMSG_LABEL_WITHDRAW, nbr->peerid, 0, &map, 391 sizeof(map)); 392 393 buf += tlen; 394 feclen -= tlen; 395 } while (feclen > 0); 396 397 nbr_fsm(nbr, NBR_EVT_PDU_RCVD); 398 399 return (ntohs(lw.length)); 400 } 401 402 /* Label Release Message */ 403 void 404 send_labelrelease(struct nbr *nbr) 405 { 406 struct ibuf *buf; 407 struct mapping_entry *me; 408 struct ldp_hdr *ldp_hdr; 409 u_int16_t tlv_size, size; 410 411 if (nbr->iface->passive) 412 return; 413 414 if ((buf = ibuf_open(LDP_MAX_LEN)) == NULL) 415 fatal("send_labelrelease"); 416 417 /* real size will be set up later */ 418 gen_ldp_hdr(buf, nbr->iface, 0); 419 420 size = LDP_HDR_SIZE - TLV_HDR_LEN; 421 422 TAILQ_FOREACH(me, &nbr->release_list, entry) { 423 if (me->map.label == NO_LABEL) 424 tlv_size = PREFIX_SIZE(me->map.prefixlen); 425 else 426 tlv_size = BASIC_LABEL_MAP_LEN + 427 PREFIX_SIZE(me->map.prefixlen); 428 429 size += tlv_size; 430 431 gen_msg_tlv(buf, MSG_TYPE_LABELRELEASE, tlv_size); 432 gen_fec_tlv(buf, me->map.prefix, me->map.prefixlen); 433 434 if (me->map.label != NO_LABEL) 435 gen_label_tlv(buf, me->map.label); 436 } 437 438 /* XXX: should we remove them first? */ 439 nbr_mapping_list_clr(nbr, &nbr->release_list); 440 441 ldp_hdr = ibuf_seek(buf, 0, sizeof(struct ldp_hdr)); 442 ldp_hdr->length = htons(size); 443 444 evbuf_enqueue(&nbr->wbuf, buf); 445 } 446 447 int 448 recv_labelrelease(struct nbr *nbr, char *buf, u_int16_t len) 449 { 450 struct map map; 451 struct ldp_msg lr; 452 struct fec_tlv ft; 453 u_int32_t label = NO_LABEL; 454 int feclen, tlen, numfec = 0; 455 u_int8_t addr_type; 456 457 if (nbr->state != NBR_STA_OPER) { 458 log_debug("recv_labelrelease: neighbor ID %s not operational", 459 inet_ntoa(nbr->id)); 460 return (-1); 461 } 462 463 bcopy(buf, &lr, sizeof(lr)); 464 465 buf += sizeof(struct ldp_msg); 466 len -= sizeof(struct ldp_msg); 467 468 if (len < sizeof(ft)) { 469 session_shutdown(nbr, S_BAD_MSG_LEN, lr.msgid, lr.type); 470 return (-1); 471 } 472 473 bcopy(buf, &ft, sizeof(ft)); 474 feclen = ntohs(ft.length); 475 476 if (feclen > len - TLV_HDR_LEN) { 477 session_shutdown(nbr, S_BAD_TLV_LEN, lr.msgid, lr.type); 478 return (-1); 479 } 480 481 buf += TLV_HDR_LEN; /* just advance to the end of the fec header */ 482 len -= TLV_HDR_LEN; 483 484 /* release may include optional label */ 485 if (len > feclen) { 486 int r; 487 488 r = tlv_decode_label(buf + feclen, len - feclen, &label); 489 if (r == -1 || len != feclen + r) { 490 session_shutdown(nbr, S_BAD_TLV_VAL, lr.msgid, 491 lr.type); 492 return (-1); 493 } 494 } 495 496 bzero(&map, sizeof(map)); 497 map.messageid = lr.msgid; 498 if (label != NO_LABEL) { 499 map.label = label; 500 map.flags = F_MAP_OPTLABEL; 501 } 502 do { 503 if ((tlen = tlv_decode_fec_elm(buf, feclen, &addr_type, 504 &map.prefix.s_addr, &map.prefixlen)) == -1) { 505 session_shutdown(nbr, S_BAD_TLV_VAL, lr.msgid, lr.type); 506 return (-1); 507 } 508 509 if (addr_type == FEC_WILDCARD) { 510 /* Wildcard FEC must be the only FEC element */ 511 if (numfec != 0) { 512 session_shutdown(nbr, S_BAD_TLV_VAL, lr.msgid, 513 lr.type); 514 return (-1); 515 } 516 map.prefix.s_addr = 0; 517 map.prefixlen = 0; 518 map.flags |= F_MAP_WILDCARD; 519 520 } else { 521 /* Wildcard FEC must be the only FEC element */ 522 if (numfec == -1) { 523 session_shutdown(nbr, S_BAD_TLV_VAL, lr.msgid, 524 lr.type); 525 return (-1); 526 } 527 map.flags &= ~F_MAP_WILDCARD; 528 } 529 530 ldpe_imsg_compose_lde(IMSG_LABEL_RELEASE, nbr->peerid, 0, &map, 531 sizeof(map)); 532 533 buf += tlen; 534 feclen -= tlen; 535 } while (feclen > 0); 536 537 nbr_fsm(nbr, NBR_EVT_PDU_RCVD); 538 539 return (ntohs(lr.length)); 540 } 541 542 /* Label Abort Req Message */ 543 void 544 send_labelabortreq(struct nbr *nbr) 545 { 546 struct ibuf *buf; 547 u_int16_t size; 548 549 if (nbr->iface->passive) 550 return; 551 552 if ((buf = ibuf_open(LDP_MAX_LEN)) == NULL) 553 fatal("send_labelabortreq"); 554 555 size = LDP_HDR_SIZE + sizeof(struct ldp_msg); 556 557 gen_ldp_hdr(buf, nbr->iface, size); 558 559 size -= LDP_HDR_SIZE; 560 561 gen_msg_tlv(buf, MSG_TYPE_LABELABORTREQ, size); 562 563 evbuf_enqueue(&nbr->wbuf, buf); 564 } 565 566 int 567 recv_labelabortreq(struct nbr *nbr, char *buf, u_int16_t len) 568 { 569 struct map map; 570 struct ldp_msg la; 571 struct fec_tlv ft; 572 int feclen, tlen; 573 u_int8_t addr_type; 574 575 if (nbr->state != NBR_STA_OPER) { 576 log_debug("recv_labelabortreq: neighbor ID %s not operational", 577 inet_ntoa(nbr->id)); 578 return (-1); 579 } 580 581 log_debug("recv_labelabortreq: neighbor ID %s", inet_ntoa(nbr->id)); 582 583 bcopy(buf, &la, sizeof(la)); 584 585 buf += sizeof(struct ldp_msg); 586 len -= sizeof(struct ldp_msg); 587 588 if (len < sizeof(ft)) { 589 session_shutdown(nbr, S_BAD_MSG_LEN, la.msgid, la.type); 590 return (-1); 591 } 592 593 bcopy(buf, &ft, sizeof(ft)); 594 feclen = ntohs(ft.length); 595 596 if (feclen > len - TLV_HDR_LEN) { 597 session_shutdown(nbr, S_BAD_TLV_LEN, la.msgid, la.type); 598 return (-1); 599 } 600 601 buf += TLV_HDR_LEN; /* just advance to the end of the fec header */ 602 len -= TLV_HDR_LEN; 603 604 bzero(&map, sizeof(map)); 605 map.messageid = la.msgid; 606 607 /* abort request may include optional request msg id */ 608 if (len > feclen) { 609 int r; 610 611 r = tlv_decode_reqid(buf + feclen, len - feclen, 612 &map.requestid); 613 if (r == -1 || len != feclen + r) { 614 session_shutdown(nbr, S_BAD_TLV_VAL, la.msgid, 615 la.type); 616 return (-1); 617 } 618 map.flags = F_MAP_REQ_ID; 619 } 620 621 do { 622 if ((tlen = tlv_decode_fec_elm(buf, feclen, &addr_type, 623 &map.prefix.s_addr, &map.prefixlen)) == -1 || 624 addr_type == FEC_WILDCARD) { 625 session_shutdown(nbr, S_BAD_TLV_VAL, la.msgid, la.type); 626 return (-1); 627 } 628 629 ldpe_imsg_compose_lde(IMSG_LABEL_ABORT, nbr->peerid, 0, &map, 630 sizeof(map)); 631 632 buf += tlen; 633 feclen -= tlen; 634 } while (feclen > 0); 635 636 nbr_fsm(nbr, NBR_EVT_PDU_RCVD); 637 638 return (ntohs(la.length)); 639 } 640 641 /* Other TLV related functions */ 642 void 643 gen_label_tlv(struct ibuf *buf, u_int32_t label) 644 { 645 struct label_tlv lt; 646 647 lt.type = htons(TLV_TYPE_GENERICLABEL); 648 lt.length = htons(sizeof(label)); 649 lt.label = htonl(label); 650 651 ibuf_add(buf, <, sizeof(lt)); 652 } 653 654 int 655 tlv_decode_label(char *buf, u_int16_t len, u_int32_t *label) 656 { 657 struct label_tlv lt; 658 659 if (len < sizeof(lt)) 660 return (-1); 661 bcopy(buf, <, sizeof(lt)); 662 663 if (ntohs(lt.length) != sizeof(lt) - TLV_HDR_LEN) 664 return (-1); 665 666 if (lt.type != htons(TLV_TYPE_GENERICLABEL)) 667 return (-1); 668 669 *label = ntohl(lt.label); 670 671 return (sizeof(lt)); 672 } 673 674 void 675 gen_reqid_tlv(struct ibuf *buf, u_int32_t reqid) 676 { 677 struct reqid_tlv rt; 678 679 rt.type = htons(TLV_TYPE_LABELREQUEST); 680 rt.length = htons(sizeof(reqid)); 681 rt.reqid = htonl(reqid); 682 683 ibuf_add(buf, &rt, sizeof(rt)); 684 } 685 686 int 687 tlv_decode_reqid(char *buf, u_int16_t len, u_int32_t *reqid) 688 { 689 struct reqid_tlv rt; 690 691 if (len < sizeof(rt)) 692 return (-1); 693 bcopy(buf, &rt, sizeof(rt)); 694 695 if (ntohs(rt.length) != sizeof(rt) - TLV_HDR_LEN) 696 return (-1); 697 698 if (rt.type != htons(TLV_TYPE_LABELREQUEST)) 699 return (-1); 700 701 *reqid = ntohl(rt.reqid); 702 703 return (sizeof(rt)); 704 } 705 706 707 void 708 gen_fec_tlv(struct ibuf *buf, struct in_addr prefix, u_int8_t prefixlen) 709 { 710 struct fec_tlv ft; 711 u_int8_t type; 712 u_int16_t family; 713 u_int8_t len; 714 715 len = PREFIX_SIZE(prefixlen); 716 ft.type = htons(TLV_TYPE_FEC); 717 ft.length = htons(sizeof(type) + sizeof(family) + sizeof(prefixlen) + 718 len); 719 720 ibuf_add(buf, &ft, sizeof(ft)); 721 722 type = FEC_PREFIX; 723 family = htons(FEC_IPV4); 724 725 ibuf_add(buf, &type, sizeof(type)); 726 ibuf_add(buf, &family, sizeof(family)); 727 ibuf_add(buf, &prefixlen, sizeof(prefixlen)); 728 if (len) 729 ibuf_add(buf, &prefix, len); 730 } 731 732 int 733 tlv_decode_fec_elm(char *buf, u_int16_t len, u_int8_t *type, u_int32_t *prefix, 734 u_int8_t *prefixlen) 735 { 736 u_int16_t family, off = 0; 737 738 *type = *buf; 739 off += sizeof(u_int8_t); 740 741 if (*type == FEC_WILDCARD) { 742 if (len == 0) 743 return (off); 744 else 745 return (-1); /* XXX Malformed TLV Value */ 746 } 747 748 if (*type != FEC_PREFIX) 749 return (-1); /* XXX "Unknown FEC" Notification */ 750 751 if (len < FEC_ELM_MIN_LEN) 752 return (-1); /* XXX Bad TLV Length */ 753 754 bcopy(buf + off, &family, sizeof(family)); 755 off += sizeof(family); 756 757 if (family != htons(FEC_IPV4)) 758 return (-1); /* XXX "Unsupported Address Family" */ 759 760 *prefixlen = buf[off]; 761 off += sizeof(u_int8_t); 762 763 if (len < off + PREFIX_SIZE(*prefixlen)) 764 return (-1); /* XXX Bad TLV Length */ 765 766 *prefix = 0; 767 bcopy(buf + off, prefix, PREFIX_SIZE(*prefixlen)); 768 769 return (off + PREFIX_SIZE(*prefixlen)); 770 } 771