GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/eigrpd/packet.c Lines: 0 345 0.0 %
Date: 2017-11-07 Branches: 0 223 0.0 %

Line Branch Exec Source
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
}