xref: /openbsd-src/usr.sbin/eigrpd/packet.c (revision 0b7734b3d77bb9b21afec6f4621cae6c805dbd45)
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