1 /* $OpenBSD: packet.c,v 1.14 2016/04/15 13:21:45 renato Exp $ */ 2 3 /* 4 * Copyright (c) 2015 Renato Westphal <renato@openbsd.org> 5 * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org> 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include <stdlib.h> 21 #include <stdio.h> 22 #include <arpa/inet.h> 23 #include <net/if_dl.h> 24 #include <errno.h> 25 #include <string.h> 26 27 #include "eigrpd.h" 28 #include "eigrp.h" 29 #include "log.h" 30 #include "eigrpe.h" 31 32 extern struct eigrpd_conf *econf; 33 34 int ip_hdr_sanity_check(const struct ip *, uint16_t); 35 int eigrp_hdr_sanity_check(int, union eigrpd_addr *, 36 struct eigrp_hdr *, uint16_t, const struct iface *); 37 struct iface *find_iface(unsigned int, int, union eigrpd_addr *); 38 39 int 40 gen_eigrp_hdr(struct ibuf *buf, uint16_t opcode, uint8_t flags, 41 uint32_t seq_num, uint16_t as) 42 { 43 struct eigrp_hdr eigrp_hdr; 44 45 memset(&eigrp_hdr, 0, sizeof(eigrp_hdr)); 46 eigrp_hdr.version = EIGRP_VERSION; 47 eigrp_hdr.opcode = opcode; 48 /* chksum will be set later */ 49 eigrp_hdr.flags = htonl(flags); 50 eigrp_hdr.seq_num = htonl(seq_num); 51 /* ack_num will be set later */ 52 eigrp_hdr.vrid = htons(EIGRP_VRID_UNICAST_AF); 53 eigrp_hdr.as = htons(as); 54 55 return (ibuf_add(buf, &eigrp_hdr, sizeof(eigrp_hdr))); 56 } 57 58 /* send and receive packets */ 59 static int 60 send_packet_v4(struct iface *iface, struct nbr *nbr, struct ibuf *buf) 61 { 62 struct sockaddr_in dst; 63 struct msghdr msg; 64 struct iovec iov[2]; 65 struct ip ip_hdr; 66 67 /* setup sockaddr */ 68 dst.sin_family = AF_INET; 69 dst.sin_len = sizeof(struct sockaddr_in); 70 if (nbr) 71 dst.sin_addr = nbr->addr.v4; 72 else 73 dst.sin_addr.s_addr = AllEIGRPRouters_v4; 74 75 /* setup IP hdr */ 76 memset(&ip_hdr, 0, sizeof(ip_hdr)); 77 ip_hdr.ip_v = IPVERSION; 78 ip_hdr.ip_hl = sizeof(ip_hdr) >> 2; 79 ip_hdr.ip_tos = IPTOS_PREC_INTERNETCONTROL; 80 ip_hdr.ip_len = htons(ibuf_size(buf) + sizeof(ip_hdr)); 81 ip_hdr.ip_id = 0; /* 0 means kernel set appropriate value */ 82 ip_hdr.ip_off = 0; 83 ip_hdr.ip_ttl = EIGRP_IP_TTL; 84 ip_hdr.ip_p = IPPROTO_EIGRP; 85 ip_hdr.ip_sum = 0; 86 ip_hdr.ip_src.s_addr = if_primary_addr(iface); 87 ip_hdr.ip_dst = dst.sin_addr; 88 89 /* setup buffer */ 90 memset(&msg, 0, sizeof(msg)); 91 iov[0].iov_base = &ip_hdr; 92 iov[0].iov_len = sizeof(ip_hdr); 93 iov[1].iov_base = buf->buf; 94 iov[1].iov_len = ibuf_size(buf); 95 msg.msg_name = &dst; 96 msg.msg_namelen = sizeof(dst); 97 msg.msg_iov = iov; 98 msg.msg_iovlen = 2; 99 100 /* set outgoing interface for multicast traffic */ 101 if (IN_MULTICAST(ntohl(dst.sin_addr.s_addr))) 102 if (if_set_ipv4_mcast(iface) == -1) { 103 log_warn("%s: error setting multicast interface, %s", 104 __func__, iface->name); 105 return (-1); 106 } 107 108 if (sendmsg(global.eigrp_socket_v4, &msg, 0) == -1) { 109 log_warn("%s: error sending packet on interface %s", 110 __func__, iface->name); 111 return (-1); 112 } 113 114 return (0); 115 } 116 117 static int 118 send_packet_v6(struct iface *iface, struct nbr *nbr, struct ibuf *buf) 119 { 120 struct sockaddr_in6 sa6; 121 struct in6_addr maddr = AllEIGRPRouters_v6; 122 123 /* setup sockaddr */ 124 memset(&sa6, 0, sizeof(sa6)); 125 sa6.sin6_family = AF_INET6; 126 sa6.sin6_len = sizeof(struct sockaddr_in6); 127 if (nbr) { 128 sa6.sin6_addr = nbr->addr.v6; 129 addscope(&sa6, iface->ifindex); 130 } else 131 sa6.sin6_addr = maddr; 132 133 /* set outgoing interface for multicast traffic */ 134 if (IN6_IS_ADDR_MULTICAST(&sa6.sin6_addr)) 135 if (if_set_ipv6_mcast(iface) == -1) { 136 log_warn("%s: error setting multicast interface, %s", 137 __func__, iface->name); 138 return (-1); 139 } 140 141 if (sendto(global.eigrp_socket_v6, buf->buf, buf->wpos, 0, 142 (struct sockaddr *)&sa6, sizeof(sa6)) == -1) { 143 log_warn("%s: error sending packet on interface %s", 144 __func__, iface->name); 145 return (-1); 146 } 147 148 return (0); 149 } 150 151 int 152 send_packet(struct eigrp_iface *ei, struct nbr *nbr, uint32_t flags, 153 struct ibuf *buf) 154 { 155 struct eigrp *eigrp = ei->eigrp; 156 struct iface *iface = ei->iface; 157 struct eigrp_hdr *eigrp_hdr; 158 159 if (!(iface->flags & IFF_UP) || !LINK_STATE_IS_UP(iface->linkstate)) 160 return (-1); 161 162 /* update ack number, flags and checksum */ 163 if ((eigrp_hdr = ibuf_seek(buf, 0, sizeof(*eigrp_hdr))) == NULL) 164 fatalx("send_packet: buf_seek failed"); 165 if (nbr) { 166 eigrp_hdr->ack_num = htonl(nbr->recv_seq); 167 rtp_ack_stop_timer(nbr); 168 } 169 if (flags) { 170 eigrp_hdr->flags = ntohl(eigrp_hdr->flags) | flags; 171 eigrp_hdr->flags = htonl(eigrp_hdr->flags); 172 } 173 eigrp_hdr->chksum = 0; 174 eigrp_hdr->chksum = in_cksum(buf->buf, ibuf_size(buf)); 175 176 /* log packet being sent */ 177 if (eigrp_hdr->opcode != EIGRP_OPC_HELLO) { 178 char buffer[64]; 179 180 if (nbr) 181 snprintf(buffer, sizeof(buffer), "nbr %s", 182 log_addr(eigrp->af, &nbr->addr)); 183 else 184 snprintf(buffer, sizeof(buffer), "(multicast)"); 185 186 log_debug("%s: type %s iface %s %s AS %u seq %u ack %u", 187 __func__, opcode_name(eigrp_hdr->opcode), iface->name, 188 buffer, ntohs(eigrp_hdr->as), ntohl(eigrp_hdr->seq_num), 189 ntohl(eigrp_hdr->ack_num)); 190 } 191 192 switch (eigrp->af) { 193 case AF_INET: 194 if (send_packet_v4(iface, nbr, buf) < 0) 195 return (-1); 196 break; 197 case AF_INET6: 198 if (send_packet_v6(iface, nbr, buf) < 0) 199 return (-1); 200 break; 201 default: 202 fatalx("send_packet: unknown af"); 203 } 204 205 switch (eigrp_hdr->opcode) { 206 case EIGRP_OPC_HELLO: 207 if (ntohl(eigrp_hdr->ack_num) == 0) 208 ei->eigrp->stats.hellos_sent++; 209 else 210 ei->eigrp->stats.acks_sent++; 211 break; 212 case EIGRP_OPC_UPDATE: 213 ei->eigrp->stats.updates_sent++; 214 break; 215 case EIGRP_OPC_QUERY: 216 ei->eigrp->stats.queries_sent++; 217 break; 218 case EIGRP_OPC_REPLY: 219 ei->eigrp->stats.replies_sent++; 220 break; 221 case EIGRP_OPC_SIAQUERY: 222 ei->eigrp->stats.squeries_sent++; 223 break; 224 case EIGRP_OPC_SIAREPLY: 225 ei->eigrp->stats.sreplies_sent++; 226 break; 227 default: 228 break; 229 } 230 231 return (0); 232 } 233 234 static int 235 recv_packet_nbr(struct nbr *nbr, struct eigrp_hdr *eigrp_hdr, 236 struct seq_addr_head *seq_addr_list, struct tlv_mcast_seq *tm) 237 { 238 uint32_t seq, ack; 239 struct seq_addr_entry *sa; 240 241 seq = ntohl(eigrp_hdr->seq_num); 242 ack = ntohl(eigrp_hdr->ack_num); 243 244 /* 245 * draft-savage-eigrp-04 - Section 5.3.1: 246 * "In addition to the HELLO packet, if any packet is received within 247 * the hold time period, then the Hold Time period will be reset." 248 */ 249 nbr_start_timeout(nbr); 250 251 /* handle the sequence tlv */ 252 if (eigrp_hdr->opcode == EIGRP_OPC_HELLO && 253 !TAILQ_EMPTY(seq_addr_list)) { 254 nbr->flags |= F_EIGRP_NBR_CR_MODE; 255 256 TAILQ_FOREACH(sa, seq_addr_list, entry) { 257 switch (sa->af) { 258 case AF_INET: 259 if (sa->addr.v4.s_addr == 260 if_primary_addr(nbr->ei->iface)) { 261 nbr->flags &= ~F_EIGRP_NBR_CR_MODE; 262 break; 263 } 264 break; 265 case AF_INET6: 266 if (IN6_ARE_ADDR_EQUAL(&sa->addr.v6, 267 &nbr->ei->iface->linklocal)) { 268 nbr->flags &= ~F_EIGRP_NBR_CR_MODE; 269 break; 270 } 271 break; 272 default: 273 break; 274 } 275 } 276 if (tm) 277 nbr->next_mcast_seq = ntohl(tm->seq); 278 } 279 280 if ((ntohl(eigrp_hdr->flags) & EIGRP_HDR_FLAG_CR)) { 281 if (!(nbr->flags & F_EIGRP_NBR_CR_MODE)) 282 return (-1); 283 nbr->flags &= ~F_EIGRP_NBR_CR_MODE; 284 if (ntohl(eigrp_hdr->seq_num) != nbr->next_mcast_seq) 285 return (-1); 286 } 287 288 /* ack processing */ 289 if (ack != 0) 290 rtp_process_ack(nbr, ack); 291 if (seq != 0) { 292 /* check for sequence wraparound */ 293 if (nbr->recv_seq >= seq && 294 !(nbr->recv_seq == UINT32_MAX && seq == 1)) { 295 log_debug("%s: duplicate packet", __func__); 296 rtp_send_ack(nbr); 297 return (-1); 298 } 299 nbr->recv_seq = seq; 300 } 301 302 return (0); 303 } 304 305 static void 306 recv_packet(int af, union eigrpd_addr *src, union eigrpd_addr *dest, 307 struct iface *iface, struct eigrp_hdr *eigrp_hdr, char *buf, uint16_t len) 308 { 309 struct eigrp_iface *ei; 310 struct nbr *nbr; 311 struct tlv_parameter *tp = NULL; 312 struct tlv_sw_version *tv = NULL; 313 struct tlv_mcast_seq *tm = NULL; 314 struct rinfo ri; 315 struct rinfo_entry *re; 316 struct seq_addr_head seq_addr_list; 317 struct rinfo_head rinfo_list; 318 319 /* EIGRP header sanity checks */ 320 if (eigrp_hdr_sanity_check(af, dest, eigrp_hdr, len, iface) == -1) 321 return; 322 323 buf += sizeof(*eigrp_hdr); 324 len -= sizeof(*eigrp_hdr); 325 326 TAILQ_INIT(&seq_addr_list); 327 TAILQ_INIT(&rinfo_list); 328 while (len > 0) { 329 struct tlv tlv; 330 uint16_t tlv_type; 331 332 if (len < sizeof(tlv)) { 333 log_debug("%s: malformed packet (bad length)", 334 __func__); 335 goto error; 336 } 337 338 memcpy(&tlv, buf, sizeof(tlv)); 339 if (ntohs(tlv.length) > len) { 340 log_debug("%s: malformed packet (bad length)", 341 __func__); 342 goto error; 343 } 344 345 tlv_type = ntohs(tlv.type); 346 switch (tlv_type) { 347 case TLV_TYPE_PARAMETER: 348 if ((tp = tlv_decode_parameter(&tlv, buf)) == NULL) 349 goto error; 350 break; 351 case TLV_TYPE_SEQ: 352 if (tlv_decode_seq(af, &tlv, buf, &seq_addr_list) < 0) 353 goto error; 354 break; 355 case TLV_TYPE_SW_VERSION: 356 if ((tv = tlv_decode_sw_version(&tlv, buf)) == NULL) 357 goto error; 358 break; 359 case TLV_TYPE_MCAST_SEQ: 360 if ((tm = tlv_decode_mcast_seq(&tlv, buf)) == NULL) 361 goto error; 362 break; 363 case TLV_TYPE_IPV4_INTERNAL: 364 case TLV_TYPE_IPV4_EXTERNAL: 365 case TLV_TYPE_IPV6_INTERNAL: 366 case TLV_TYPE_IPV6_EXTERNAL: 367 /* silently ignore TLV from different address-family */ 368 if ((tlv_type & TLV_PROTO_MASK) == TLV_PROTO_IPV4 && 369 af != AF_INET) 370 break; 371 if ((tlv_type & TLV_PROTO_MASK) == TLV_PROTO_IPV6 && 372 af != AF_INET6) 373 break; 374 375 if (tlv_decode_route(af, &tlv, buf, &ri) < 0) 376 goto error; 377 if ((re = calloc(1, sizeof(*re))) == NULL) 378 fatal("recv_packet"); 379 re->rinfo = ri; 380 TAILQ_INSERT_TAIL(&rinfo_list, re, entry); 381 break; 382 case TLV_TYPE_AUTH: 383 case TLV_TYPE_PEER_TERM: 384 /* 385 * XXX There is no enough information in the draft 386 * to implement these TLVs properly. 387 */ 388 case TLV_TYPE_IPV4_COMMUNITY: 389 case TLV_TYPE_IPV6_COMMUNITY: 390 /* TODO */ 391 default: 392 /* ignore unknown tlv */ 393 break; 394 } 395 buf += ntohs(tlv.length); 396 len -= ntohs(tlv.length); 397 } 398 399 ei = eigrp_if_lookup(iface, af, ntohs(eigrp_hdr->as)); 400 if (ei == NULL || ei->passive) 401 goto error; 402 403 nbr = nbr_find(ei, src); 404 if (nbr == NULL && (eigrp_hdr->opcode != EIGRP_OPC_HELLO || 405 ntohl(eigrp_hdr->ack_num) != 0)) { 406 log_debug("%s: unknown neighbor", __func__); 407 goto error; 408 } else if (nbr && recv_packet_nbr(nbr, eigrp_hdr, &seq_addr_list, 409 tm) < 0) 410 goto error; 411 412 /* log packet being received */ 413 if (eigrp_hdr->opcode != EIGRP_OPC_HELLO) 414 log_debug("%s: type %s nbr %s AS %u seq %u ack %u", __func__, 415 opcode_name(eigrp_hdr->opcode), log_addr(af, &nbr->addr), 416 ei->eigrp->as, ntohl(eigrp_hdr->seq_num), 417 ntohl(eigrp_hdr->ack_num)); 418 419 /* switch EIGRP packet type */ 420 switch (eigrp_hdr->opcode) { 421 case EIGRP_OPC_HELLO: 422 if (ntohl(eigrp_hdr->ack_num) == 0) { 423 recv_hello(ei, src, nbr, tp); 424 ei->eigrp->stats.hellos_recv++; 425 } else 426 ei->eigrp->stats.acks_recv++; 427 break; 428 case EIGRP_OPC_UPDATE: 429 recv_update(nbr, &rinfo_list, ntohl(eigrp_hdr->flags)); 430 ei->eigrp->stats.updates_recv++; 431 break; 432 case EIGRP_OPC_QUERY: 433 recv_query(nbr, &rinfo_list, 0); 434 ei->eigrp->stats.queries_recv++; 435 break; 436 case EIGRP_OPC_REPLY: 437 recv_reply(nbr, &rinfo_list, 0); 438 ei->eigrp->stats.replies_recv++; 439 break; 440 case EIGRP_OPC_SIAQUERY: 441 recv_query(nbr, &rinfo_list, 1); 442 ei->eigrp->stats.squeries_recv++; 443 break; 444 case EIGRP_OPC_SIAREPLY: 445 recv_reply(nbr, &rinfo_list, 1); 446 ei->eigrp->stats.sreplies_recv++; 447 break; 448 default: 449 log_debug("%s: unknown EIGRP packet type, interface %s", 450 __func__, iface->name); 451 } 452 453 error: 454 /* free rinfo tlvs */ 455 message_list_clr(&rinfo_list); 456 /* free seq addresses tlvs */ 457 seq_addr_list_clr(&seq_addr_list); 458 } 459 460 void 461 recv_packet_v4(int fd, short event, void *bula) 462 { 463 union { 464 struct cmsghdr hdr; 465 char buf[CMSG_SPACE(sizeof(struct sockaddr_dl))]; 466 } cmsgbuf; 467 struct msghdr msg; 468 struct iovec iov; 469 struct ip ip_hdr; 470 struct eigrp_hdr *eigrp_hdr; 471 struct iface *iface; 472 char *buf; 473 struct cmsghdr *cmsg; 474 ssize_t r; 475 uint16_t len; 476 int l; 477 unsigned int ifindex = 0; 478 union eigrpd_addr src, dest; 479 480 if (event != EV_READ) 481 return; 482 483 /* setup buffer */ 484 memset(&msg, 0, sizeof(msg)); 485 iov.iov_base = buf = pkt_ptr; 486 iov.iov_len = READ_BUF_SIZE; 487 msg.msg_iov = &iov; 488 msg.msg_iovlen = 1; 489 msg.msg_control = &cmsgbuf.buf; 490 msg.msg_controllen = sizeof(cmsgbuf.buf); 491 492 if ((r = recvmsg(fd, &msg, 0)) == -1) { 493 if (errno != EAGAIN && errno != EINTR) 494 log_debug("%s: read error: %s", __func__, 495 strerror(errno)); 496 return; 497 } 498 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; 499 cmsg = CMSG_NXTHDR(&msg, cmsg)) { 500 if (cmsg->cmsg_level == IPPROTO_IP && 501 cmsg->cmsg_type == IP_RECVIF) { 502 ifindex = ((struct sockaddr_dl *) 503 CMSG_DATA(cmsg))->sdl_index; 504 break; 505 } 506 } 507 508 len = (uint16_t)r; 509 510 /* IP header sanity checks */ 511 if (len < sizeof(ip_hdr)) { 512 log_debug("%s: bad packet size", __func__); 513 return; 514 } 515 memcpy(&ip_hdr, buf, sizeof(ip_hdr)); 516 if ((l = ip_hdr_sanity_check(&ip_hdr, len)) == -1) 517 return; 518 buf += l; 519 len -= l; 520 521 src.v4 = ip_hdr.ip_src; 522 dest.v4 = ip_hdr.ip_dst; 523 524 /* find a matching interface */ 525 if ((iface = find_iface(ifindex, AF_INET, &src)) == NULL) 526 return; 527 528 /* 529 * Packet needs to be sent to AllEIGRPRouters_v4 or to one 530 * of the interface addresses. 531 */ 532 if (ip_hdr.ip_dst.s_addr != AllEIGRPRouters_v4) { 533 struct if_addr *if_addr; 534 int found = 0; 535 536 TAILQ_FOREACH(if_addr, &iface->addr_list, entry) 537 if (if_addr->af == AF_INET && 538 ip_hdr.ip_dst.s_addr == if_addr->addr.v4.s_addr) { 539 found = 1; 540 break; 541 } 542 if (found == 0) { 543 log_debug("%s: packet sent to wrong address %s, " 544 "interface %s", __func__, inet_ntoa(ip_hdr.ip_dst), 545 iface->name); 546 return; 547 } 548 } 549 550 if (len < sizeof(*eigrp_hdr)) { 551 log_debug("%s: bad packet size", __func__); 552 return; 553 } 554 eigrp_hdr = (struct eigrp_hdr *)buf; 555 556 recv_packet(AF_INET, &src, &dest, iface, eigrp_hdr, buf, len); 557 } 558 559 void 560 recv_packet_v6(int fd, short event, void *bula) 561 { 562 union { 563 struct cmsghdr hdr; 564 char buf[CMSG_SPACE(sizeof(struct in6_pktinfo))]; 565 } cmsgbuf; 566 struct msghdr msg; 567 struct iovec iov; 568 struct sockaddr_in6 sin6; 569 struct eigrp_hdr *eigrp_hdr; 570 struct iface *iface; 571 char *buf; 572 struct cmsghdr *cmsg; 573 ssize_t r; 574 uint16_t len; 575 unsigned int ifindex = 0; 576 union eigrpd_addr src, dest; 577 struct in6_addr maddr = AllEIGRPRouters_v6; 578 579 if (event != EV_READ) 580 return; 581 582 /* setup buffer */ 583 memset(&msg, 0, sizeof(msg)); 584 iov.iov_base = buf = pkt_ptr; 585 iov.iov_len = READ_BUF_SIZE; 586 msg.msg_name = &sin6; 587 msg.msg_namelen = sizeof(sin6); 588 msg.msg_iov = &iov; 589 msg.msg_iovlen = 1; 590 msg.msg_control = &cmsgbuf.buf; 591 msg.msg_controllen = sizeof(cmsgbuf.buf); 592 593 if ((r = recvmsg(fd, &msg, 0)) == -1) { 594 if (errno != EAGAIN && errno != EINTR) 595 log_debug("%s: read error: %s", __func__, 596 strerror(errno)); 597 return; 598 } 599 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; 600 cmsg = CMSG_NXTHDR(&msg, cmsg)) { 601 if (cmsg->cmsg_level == IPPROTO_IPV6 && 602 cmsg->cmsg_type == IPV6_PKTINFO) { 603 ifindex = ((struct in6_pktinfo *) 604 CMSG_DATA(cmsg))->ipi6_ifindex; 605 dest.v6 = ((struct in6_pktinfo *) 606 CMSG_DATA(cmsg))->ipi6_addr; 607 break; 608 } 609 } 610 src.v6 = sin6.sin6_addr; 611 612 /* validate source address */ 613 if (bad_addr_v6(&src.v6)) { 614 log_debug("%s: invalid source address: %s", __func__, 615 log_addr(AF_INET, &src)); 616 return; 617 } 618 619 /* find a matching interface */ 620 if ((iface = find_iface(ifindex, AF_INET6, &src)) == NULL) 621 return; 622 623 /* 624 * Packet needs to be sent to AllEIGRPRouters_v6 or to the 625 * link local address of the interface. 626 */ 627 if (!IN6_ARE_ADDR_EQUAL(&dest.v6, &maddr) && 628 !IN6_ARE_ADDR_EQUAL(&dest.v6, &iface->linklocal)) { 629 log_debug("%s: packet sent to wrong address %s, interface %s", 630 __func__, log_in6addr(&dest.v6), iface->name); 631 return; 632 } 633 634 len = (uint16_t)r; 635 if (len < sizeof(*eigrp_hdr)) { 636 log_debug("%s: bad packet size", __func__); 637 return; 638 } 639 eigrp_hdr = (struct eigrp_hdr *)buf; 640 641 recv_packet(AF_INET6, &src, &dest, iface, eigrp_hdr, buf, len); 642 } 643 644 int 645 ip_hdr_sanity_check(const struct ip *ip_hdr, uint16_t len) 646 { 647 if (ntohs(ip_hdr->ip_len) != len) { 648 log_debug("%s: invalid IP packet length %u", __func__, 649 ntohs(ip_hdr->ip_len)); 650 return (-1); 651 } 652 653 /* validate source address */ 654 if (bad_addr_v4(ip_hdr->ip_src)) { 655 log_debug("%s: invalid source address: %s", __func__, 656 inet_ntoa(ip_hdr->ip_src)); 657 return (-1); 658 } 659 660 if (ip_hdr->ip_p != IPPROTO_EIGRP) 661 /* this is enforced by the socket itself */ 662 fatalx("ip_hdr_sanity_check: invalid IP proto"); 663 664 return (ip_hdr->ip_hl << 2); 665 } 666 667 int 668 eigrp_hdr_sanity_check(int af, union eigrpd_addr *addr, 669 struct eigrp_hdr *eigrp_hdr, uint16_t len, const struct iface *iface) 670 { 671 if (in_cksum(eigrp_hdr, len)) { 672 log_debug("%s: invalid checksum, interface %s", __func__, 673 iface->name); 674 return (-1); 675 } 676 677 if (eigrp_hdr->version != EIGRP_HEADER_VERSION) { 678 log_debug("%s: invalid EIGRP version %d, interface %s", 679 __func__, eigrp_hdr->version, iface->name); 680 return (-1); 681 } 682 683 if (ntohs(eigrp_hdr->vrid) != EIGRP_VRID_UNICAST_AF) { 684 log_debug("%s: unknown or unsupported vrid %u, interface %s", 685 __func__, ntohs(eigrp_hdr->vrid), iface->name); 686 return (-1); 687 } 688 689 if (eigrp_hdr->opcode == EIGRP_OPC_HELLO && 690 eigrp_hdr->ack_num != 0) { 691 switch (af) { 692 case AF_INET: 693 if (IN_MULTICAST(addr->v4.s_addr)) { 694 log_debug("%s: multicast ack (ipv4), " 695 "interface %s", __func__, iface->name); 696 return (-1); 697 } 698 break; 699 case AF_INET6: 700 if (IN6_IS_ADDR_MULTICAST(&addr->v6)) { 701 log_debug("%s: multicast ack (ipv6), " 702 "interface %s", __func__, iface->name); 703 return (-1); 704 } 705 break; 706 default: 707 fatalx("eigrp_hdr_sanity_check: unknown af"); 708 } 709 } 710 711 return (0); 712 } 713 714 struct iface * 715 find_iface(unsigned int ifindex, int af, union eigrpd_addr *src) 716 { 717 struct iface *iface; 718 struct if_addr *if_addr; 719 in_addr_t mask; 720 721 iface = if_lookup(econf, ifindex); 722 if (iface == NULL) 723 return (NULL); 724 725 switch (af) { 726 case AF_INET: 727 /* 728 * From CCNP ROUTE 642-902 OCG: 729 * "EIGRP's rules about neighbor IP addresses being in the same 730 * subnet are less exact than OSPF. OSPF requires matching 731 * subnet numbers and masks. EIGRP just asks the question of 732 * whether the neighbor's IP address is in the range of 733 * addresses for the subnet as known to the local router." 734 */ 735 TAILQ_FOREACH(if_addr, &iface->addr_list, entry) { 736 if (if_addr->af == AF_INET) { 737 mask = prefixlen2mask(if_addr->prefixlen); 738 739 if ((if_addr->addr.v4.s_addr & mask) == 740 (src->v4.s_addr & mask)) 741 return (iface); 742 } 743 } 744 break; 745 case AF_INET6: 746 /* 747 * draft-savage-eigrp-04 - Section 10.1: 748 * "EIGRP IPv6 will check that a received HELLO contains a valid 749 * IPv6 link-local source address." 750 */ 751 if (IN6_IS_ADDR_LINKLOCAL(&src->v6)) 752 return (iface); 753 break; 754 default: 755 fatalx("find_iface: unknown af"); 756 } 757 758 return (NULL); 759 } 760