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