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