1 /* $OpenBSD: packet.c,v 1.18 2016/09/02 16:44:33 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 <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 = buf->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, buf->buf, buf->wpos, 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 = ntohl(eigrp_hdr->flags) | flags; 177 eigrp_hdr->flags = htonl(eigrp_hdr->flags); 178 } 179 eigrp_hdr->chksum = 0; 180 eigrp_hdr->chksum = in_cksum(buf->buf, ibuf_size(buf)); 181 182 /* log packet being sent */ 183 if (eigrp_hdr->opcode != EIGRP_OPC_HELLO) { 184 char buffer[64]; 185 186 if (nbr) 187 snprintf(buffer, sizeof(buffer), "nbr %s", 188 log_addr(eigrp->af, &nbr->addr)); 189 else 190 snprintf(buffer, sizeof(buffer), "(multicast)"); 191 192 log_debug("%s: type %s iface %s %s AS %u seq %u ack %u", 193 __func__, opcode_name(eigrp_hdr->opcode), iface->name, 194 buffer, ntohs(eigrp_hdr->as), ntohl(eigrp_hdr->seq_num), 195 ntohl(eigrp_hdr->ack_num)); 196 } 197 198 switch (eigrp->af) { 199 case AF_INET: 200 if (send_packet_v4(iface, nbr, buf) < 0) 201 return (-1); 202 break; 203 case AF_INET6: 204 if (send_packet_v6(iface, nbr, buf) < 0) 205 return (-1); 206 break; 207 default: 208 fatalx("send_packet: unknown af"); 209 } 210 211 switch (eigrp_hdr->opcode) { 212 case EIGRP_OPC_HELLO: 213 if (ntohl(eigrp_hdr->ack_num) == 0) 214 ei->eigrp->stats.hellos_sent++; 215 else 216 ei->eigrp->stats.acks_sent++; 217 break; 218 case EIGRP_OPC_UPDATE: 219 ei->eigrp->stats.updates_sent++; 220 break; 221 case EIGRP_OPC_QUERY: 222 ei->eigrp->stats.queries_sent++; 223 break; 224 case EIGRP_OPC_REPLY: 225 ei->eigrp->stats.replies_sent++; 226 break; 227 case EIGRP_OPC_SIAQUERY: 228 ei->eigrp->stats.squeries_sent++; 229 break; 230 case EIGRP_OPC_SIAREPLY: 231 ei->eigrp->stats.sreplies_sent++; 232 break; 233 default: 234 break; 235 } 236 237 return (0); 238 } 239 240 static int 241 recv_packet_nbr(struct nbr *nbr, struct eigrp_hdr *eigrp_hdr, 242 struct seq_addr_head *seq_addr_list, struct tlv_mcast_seq *tm) 243 { 244 uint32_t seq, ack; 245 struct seq_addr_entry *sa; 246 247 seq = ntohl(eigrp_hdr->seq_num); 248 ack = ntohl(eigrp_hdr->ack_num); 249 250 /* 251 * draft-savage-eigrp-04 - Section 5.3.1: 252 * "In addition to the HELLO packet, if any packet is received within 253 * the hold time period, then the Hold Time period will be reset." 254 */ 255 nbr_start_timeout(nbr); 256 257 /* handle the sequence tlv */ 258 if (eigrp_hdr->opcode == EIGRP_OPC_HELLO && 259 !TAILQ_EMPTY(seq_addr_list)) { 260 nbr->flags |= F_EIGRP_NBR_CR_MODE; 261 262 TAILQ_FOREACH(sa, seq_addr_list, entry) { 263 switch (sa->af) { 264 case AF_INET: 265 if (sa->addr.v4.s_addr == 266 if_primary_addr(nbr->ei->iface)) { 267 nbr->flags &= ~F_EIGRP_NBR_CR_MODE; 268 break; 269 } 270 break; 271 case AF_INET6: 272 if (IN6_ARE_ADDR_EQUAL(&sa->addr.v6, 273 &nbr->ei->iface->linklocal)) { 274 nbr->flags &= ~F_EIGRP_NBR_CR_MODE; 275 break; 276 } 277 break; 278 default: 279 break; 280 } 281 } 282 if (tm) 283 nbr->next_mcast_seq = ntohl(tm->seq); 284 } 285 286 if ((ntohl(eigrp_hdr->flags) & EIGRP_HDR_FLAG_CR)) { 287 if (!(nbr->flags & F_EIGRP_NBR_CR_MODE)) 288 return (-1); 289 nbr->flags &= ~F_EIGRP_NBR_CR_MODE; 290 if (ntohl(eigrp_hdr->seq_num) != nbr->next_mcast_seq) 291 return (-1); 292 } 293 294 /* ack processing */ 295 if (ack != 0) 296 rtp_process_ack(nbr, ack); 297 if (seq != 0) { 298 /* check for sequence wraparound */ 299 if (nbr->recv_seq >= seq && 300 !(nbr->recv_seq == UINT32_MAX && seq == 1)) { 301 log_debug("%s: duplicate packet", __func__); 302 rtp_send_ack(nbr); 303 return (-1); 304 } 305 nbr->recv_seq = seq; 306 } 307 308 return (0); 309 } 310 311 static void 312 recv_packet_eigrp(int af, union eigrpd_addr *src, union eigrpd_addr *dest, 313 struct iface *iface, struct eigrp_hdr *eigrp_hdr, char *buf, uint16_t len) 314 { 315 struct eigrp_iface *ei; 316 struct nbr *nbr; 317 struct tlv_parameter *tp = NULL; 318 struct tlv_sw_version *tv = NULL; 319 struct tlv_mcast_seq *tm = NULL; 320 struct rinfo ri; 321 struct rinfo_entry *re; 322 struct seq_addr_head seq_addr_list; 323 struct rinfo_head rinfo_list; 324 325 /* EIGRP header sanity checks */ 326 if (eigrp_hdr_sanity_check(af, dest, eigrp_hdr, len, iface) == -1) 327 return; 328 329 buf += sizeof(*eigrp_hdr); 330 len -= sizeof(*eigrp_hdr); 331 332 TAILQ_INIT(&seq_addr_list); 333 TAILQ_INIT(&rinfo_list); 334 while (len > 0) { 335 struct tlv tlv; 336 uint16_t tlv_type; 337 338 if (len < sizeof(tlv)) { 339 log_debug("%s: malformed packet (bad length)", 340 __func__); 341 goto error; 342 } 343 344 memcpy(&tlv, buf, sizeof(tlv)); 345 if (ntohs(tlv.length) > len) { 346 log_debug("%s: malformed packet (bad length)", 347 __func__); 348 goto error; 349 } 350 351 tlv_type = ntohs(tlv.type); 352 switch (tlv_type) { 353 case TLV_TYPE_PARAMETER: 354 if ((tp = tlv_decode_parameter(&tlv, buf)) == NULL) 355 goto error; 356 break; 357 case TLV_TYPE_SEQ: 358 if (tlv_decode_seq(af, &tlv, buf, &seq_addr_list) < 0) 359 goto error; 360 break; 361 case TLV_TYPE_SW_VERSION: 362 if ((tv = tlv_decode_sw_version(&tlv, buf)) == NULL) 363 goto error; 364 break; 365 case TLV_TYPE_MCAST_SEQ: 366 if ((tm = tlv_decode_mcast_seq(&tlv, buf)) == NULL) 367 goto error; 368 break; 369 case TLV_TYPE_IPV4_INTERNAL: 370 case TLV_TYPE_IPV4_EXTERNAL: 371 case TLV_TYPE_IPV6_INTERNAL: 372 case TLV_TYPE_IPV6_EXTERNAL: 373 /* silently ignore TLV from different address-family */ 374 if ((tlv_type & TLV_PROTO_MASK) == TLV_PROTO_IPV4 && 375 af != AF_INET) 376 break; 377 if ((tlv_type & TLV_PROTO_MASK) == TLV_PROTO_IPV6 && 378 af != AF_INET6) 379 break; 380 381 if (tlv_decode_route(af, &tlv, buf, &ri) < 0) 382 goto error; 383 if ((re = calloc(1, sizeof(*re))) == NULL) 384 fatal("recv_packet_eigrp"); 385 re->rinfo = ri; 386 TAILQ_INSERT_TAIL(&rinfo_list, re, entry); 387 break; 388 case TLV_TYPE_AUTH: 389 case TLV_TYPE_PEER_TERM: 390 /* 391 * XXX There is no enough information in the draft 392 * to implement these TLVs properly. 393 */ 394 case TLV_TYPE_IPV4_COMMUNITY: 395 case TLV_TYPE_IPV6_COMMUNITY: 396 /* TODO */ 397 default: 398 /* ignore unknown tlv */ 399 break; 400 } 401 buf += ntohs(tlv.length); 402 len -= ntohs(tlv.length); 403 } 404 405 ei = eigrp_if_lookup(iface, af, ntohs(eigrp_hdr->as)); 406 if (ei == NULL || ei->passive) 407 goto error; 408 409 nbr = nbr_find(ei, src); 410 if (nbr == NULL && (eigrp_hdr->opcode != EIGRP_OPC_HELLO || 411 ntohl(eigrp_hdr->ack_num) != 0)) { 412 log_debug("%s: unknown neighbor", __func__); 413 goto error; 414 } else if (nbr && recv_packet_nbr(nbr, eigrp_hdr, &seq_addr_list, 415 tm) < 0) 416 goto error; 417 418 /* log packet being received */ 419 if (eigrp_hdr->opcode != EIGRP_OPC_HELLO) 420 log_debug("%s: type %s nbr %s AS %u seq %u ack %u", __func__, 421 opcode_name(eigrp_hdr->opcode), log_addr(af, &nbr->addr), 422 ei->eigrp->as, ntohl(eigrp_hdr->seq_num), 423 ntohl(eigrp_hdr->ack_num)); 424 425 /* switch EIGRP packet type */ 426 switch (eigrp_hdr->opcode) { 427 case EIGRP_OPC_HELLO: 428 if (ntohl(eigrp_hdr->ack_num) == 0) { 429 recv_hello(ei, src, nbr, tp); 430 ei->eigrp->stats.hellos_recv++; 431 } else 432 ei->eigrp->stats.acks_recv++; 433 break; 434 case EIGRP_OPC_UPDATE: 435 recv_update(nbr, &rinfo_list, ntohl(eigrp_hdr->flags)); 436 ei->eigrp->stats.updates_recv++; 437 break; 438 case EIGRP_OPC_QUERY: 439 recv_query(nbr, &rinfo_list, 0); 440 ei->eigrp->stats.queries_recv++; 441 break; 442 case EIGRP_OPC_REPLY: 443 recv_reply(nbr, &rinfo_list, 0); 444 ei->eigrp->stats.replies_recv++; 445 break; 446 case EIGRP_OPC_SIAQUERY: 447 recv_query(nbr, &rinfo_list, 1); 448 ei->eigrp->stats.squeries_recv++; 449 break; 450 case EIGRP_OPC_SIAREPLY: 451 recv_reply(nbr, &rinfo_list, 1); 452 ei->eigrp->stats.sreplies_recv++; 453 break; 454 default: 455 log_debug("%s: unknown EIGRP packet type, interface %s", 456 __func__, iface->name); 457 } 458 459 error: 460 /* free rinfo tlvs */ 461 message_list_clr(&rinfo_list); 462 /* free seq addresses tlvs */ 463 seq_addr_list_clr(&seq_addr_list); 464 } 465 466 #define CMSG_MAXLEN max(sizeof(struct sockaddr_dl), sizeof(struct in6_pktinfo)) 467 void 468 recv_packet(int fd, short event, void *bula) 469 { 470 union { 471 struct cmsghdr hdr; 472 char buf[CMSG_SPACE(CMSG_MAXLEN)]; 473 } cmsgbuf; 474 struct msghdr msg; 475 struct sockaddr_storage from; 476 struct iovec iov; 477 struct ip ip_hdr; 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_ptr; 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