Bug Summary

File:src/usr.sbin/eigrpd/packet.c
Warning:line 375, column 9
Although the value stored to 'tv' is used in the enclosing expression, the value is never actually read from 'tv'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name packet.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.sbin/eigrpd/obj -resource-dir /usr/local/llvm16/lib/clang/16 -I /usr/src/usr.sbin/eigrpd -internal-isystem /usr/local/llvm16/lib/clang/16/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/eigrpd/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fno-jump-tables -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/scan/2024-01-11-140451-98009-1 -x c /usr/src/usr.sbin/eigrpd/packet.c
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(*__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
36static int send_packet_v4(struct iface *, struct nbr *, struct ibuf *);
37static int send_packet_v6(struct iface *, struct nbr *, struct ibuf *);
38static int recv_packet_nbr(struct nbr *, struct eigrp_hdr *,
39 struct seq_addr_head *, struct tlv_mcast_seq *);
40static void recv_packet_eigrp(int, union eigrpd_addr *,
41 union eigrpd_addr *, struct iface *, struct eigrp_hdr *,
42 char *, uint16_t);
43static int eigrp_hdr_sanity_check(int, union eigrpd_addr *,
44 struct eigrp_hdr *, uint16_t, const struct iface *);
45static struct iface *find_iface(unsigned int, int, union eigrpd_addr *);
46
47int
48gen_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_VERSION2;
55 eigrp_hdr.opcode = opcode;
56 /* chksum will be set later */
57 eigrp_hdr.flags = htonl(flags)(__uint32_t)(__builtin_constant_p(flags) ? (__uint32_t)(((__uint32_t
)(flags) & 0xff) << 24 | ((__uint32_t)(flags) &
0xff00) << 8 | ((__uint32_t)(flags) & 0xff0000) >>
8 | ((__uint32_t)(flags) & 0xff000000) >> 24) : __swap32md
(flags))
;
58 eigrp_hdr.seq_num = htonl(seq_num)(__uint32_t)(__builtin_constant_p(seq_num) ? (__uint32_t)(((__uint32_t
)(seq_num) & 0xff) << 24 | ((__uint32_t)(seq_num) &
0xff00) << 8 | ((__uint32_t)(seq_num) & 0xff0000) >>
8 | ((__uint32_t)(seq_num) & 0xff000000) >> 24) : __swap32md
(seq_num))
;
59 /* ack_num will be set later */
60 eigrp_hdr.vrid = htons(EIGRP_VRID_UNICAST_AF)(__uint16_t)(__builtin_constant_p(0x0000) ? (__uint16_t)(((__uint16_t
)(0x0000) & 0xffU) << 8 | ((__uint16_t)(0x0000) &
0xff00U) >> 8) : __swap16md(0x0000))
;
61 eigrp_hdr.as = htons(as)(__uint16_t)(__builtin_constant_p(as) ? (__uint16_t)(((__uint16_t
)(as) & 0xffU) << 8 | ((__uint16_t)(as) & 0xff00U
) >> 8) : __swap16md(as))
;
62
63 return (ibuf_add(buf, &eigrp_hdr, sizeof(eigrp_hdr)));
64}
65
66/* send and receive packets */
67static int
68send_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_INET2;
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 = IPVERSION4;
86 ip_hdr.ip_hl = sizeof(ip_hdr) >> 2;
87 ip_hdr.ip_tos = IPTOS_PREC_INTERNETCONTROL0xc0;
88 ip_hdr.ip_len = htons(ibuf_size(buf) + sizeof(ip_hdr))(__uint16_t)(__builtin_constant_p(ibuf_size(buf) + sizeof(ip_hdr
)) ? (__uint16_t)(((__uint16_t)(ibuf_size(buf) + sizeof(ip_hdr
)) & 0xffU) << 8 | ((__uint16_t)(ibuf_size(buf) + sizeof
(ip_hdr)) & 0xff00U) >> 8) : __swap16md(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_TTL2;
92 ip_hdr.ip_p = IPPROTO_EIGRP88;
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))(((u_int32_t)((__uint32_t)(__builtin_constant_p(dst.sin_addr.
s_addr) ? (__uint32_t)(((__uint32_t)(dst.sin_addr.s_addr) &
0xff) << 24 | ((__uint32_t)(dst.sin_addr.s_addr) &
0xff00) << 8 | ((__uint32_t)(dst.sin_addr.s_addr) &
0xff0000) >> 8 | ((__uint32_t)(dst.sin_addr.s_addr) &
0xff000000) >> 24) : __swap32md(dst.sin_addr.s_addr)))
& ((u_int32_t)(0xf0000000))) == ((u_int32_t)(0xe0000000)
))
)
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
125static int
126send_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_INET624;
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)((&sa6.sin6_addr)->__u6_addr.__u6_addr8[0] == 0xff))
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
158int
159send_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_UP0x1) || !LINK_STATE_IS_UP(iface->linkstate)((iface->linkstate) >= 4 || (iface->linkstate) == 0))
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)__builtin_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)(__uint32_t)(__builtin_constant_p(eigrp_hdr.flags) ? (__uint32_t
)(((__uint32_t)(eigrp_hdr.flags) & 0xff) << 24 | ((
__uint32_t)(eigrp_hdr.flags) & 0xff00) << 8 | ((__uint32_t
)(eigrp_hdr.flags) & 0xff0000) >> 8 | ((__uint32_t)
(eigrp_hdr.flags) & 0xff000000) >> 24) : __swap32md
(eigrp_hdr.flags))
;
184 if (ibuf_set_n32(buf, offsetof(struct eigrp_hdr, flags)__builtin_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)__builtin_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)__builtin_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_HELLO5) {
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)(__uint16_t)(__builtin_constant_p(eigrp_hdr.as) ? (__uint16_t
)(((__uint16_t)(eigrp_hdr.as) & 0xffU) << 8 | ((__uint16_t
)(eigrp_hdr.as) & 0xff00U) >> 8) : __swap16md(eigrp_hdr
.as))
, ntohl(eigrp_hdr.seq_num)(__uint32_t)(__builtin_constant_p(eigrp_hdr.seq_num) ? (__uint32_t
)(((__uint32_t)(eigrp_hdr.seq_num) & 0xff) << 24 | (
(__uint32_t)(eigrp_hdr.seq_num) & 0xff00) << 8 | ((
__uint32_t)(eigrp_hdr.seq_num) & 0xff0000) >> 8 | (
(__uint32_t)(eigrp_hdr.seq_num) & 0xff000000) >> 24
) : __swap32md(eigrp_hdr.seq_num))
,
208 ntohl(eigrp_hdr.ack_num)(__uint32_t)(__builtin_constant_p(eigrp_hdr.ack_num) ? (__uint32_t
)(((__uint32_t)(eigrp_hdr.ack_num) & 0xff) << 24 | (
(__uint32_t)(eigrp_hdr.ack_num) & 0xff00) << 8 | ((
__uint32_t)(eigrp_hdr.ack_num) & 0xff0000) >> 8 | (
(__uint32_t)(eigrp_hdr.ack_num) & 0xff000000) >> 24
) : __swap32md(eigrp_hdr.ack_num))
);
209 }
210
211 switch (eigrp->af) {
212 case AF_INET2:
213 if (send_packet_v4(iface, nbr, buf) < 0)
214 return (-1);
215 break;
216 case AF_INET624:
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_HELLO5:
226 if (ntohl(eigrp_hdr.ack_num)(__uint32_t)(__builtin_constant_p(eigrp_hdr.ack_num) ? (__uint32_t
)(((__uint32_t)(eigrp_hdr.ack_num) & 0xff) << 24 | (
(__uint32_t)(eigrp_hdr.ack_num) & 0xff00) << 8 | ((
__uint32_t)(eigrp_hdr.ack_num) & 0xff0000) >> 8 | (
(__uint32_t)(eigrp_hdr.ack_num) & 0xff000000) >> 24
) : __swap32md(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_UPDATE1:
232 ei->eigrp->stats.updates_sent++;
233 break;
234 case EIGRP_OPC_QUERY3:
235 ei->eigrp->stats.queries_sent++;
236 break;
237 case EIGRP_OPC_REPLY4:
238 ei->eigrp->stats.replies_sent++;
239 break;
240 case EIGRP_OPC_SIAQUERY10:
241 ei->eigrp->stats.squeries_sent++;
242 break;
243 case EIGRP_OPC_SIAREPLY11:
244 ei->eigrp->stats.sreplies_sent++;
245 break;
246 default:
247 break;
248 }
249
250 return (0);
251}
252
253static int
254recv_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)(__uint32_t)(__builtin_constant_p(eigrp_hdr->seq_num) ? (__uint32_t
)(((__uint32_t)(eigrp_hdr->seq_num) & 0xff) << 24
| ((__uint32_t)(eigrp_hdr->seq_num) & 0xff00) <<
8 | ((__uint32_t)(eigrp_hdr->seq_num) & 0xff0000) >>
8 | ((__uint32_t)(eigrp_hdr->seq_num) & 0xff000000) >>
24) : __swap32md(eigrp_hdr->seq_num))
;
261 ack = ntohl(eigrp_hdr->ack_num)(__uint32_t)(__builtin_constant_p(eigrp_hdr->ack_num) ? (__uint32_t
)(((__uint32_t)(eigrp_hdr->ack_num) & 0xff) << 24
| ((__uint32_t)(eigrp_hdr->ack_num) & 0xff00) <<
8 | ((__uint32_t)(eigrp_hdr->ack_num) & 0xff0000) >>
8 | ((__uint32_t)(eigrp_hdr->ack_num) & 0xff000000) >>
24) : __swap32md(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_HELLO5 &&
272 !TAILQ_EMPTY(seq_addr_list)(((seq_addr_list)->tqh_first) == ((void *)0))) {
273 nbr->flags |= F_EIGRP_NBR_CR_MODE0x04;
274
275 TAILQ_FOREACH(sa, seq_addr_list, entry)for((sa) = ((seq_addr_list)->tqh_first); (sa) != ((void *)
0); (sa) = ((sa)->entry.tqe_next))
{
276 switch (sa->af) {
277 case AF_INET2:
278 if (sa->addr.v4.s_addr ==
279 if_primary_addr(nbr->ei->iface)) {
280 nbr->flags &= ~F_EIGRP_NBR_CR_MODE0x04;
281 break;
282 }
283 break;
284 case AF_INET624:
285 if (IN6_ARE_ADDR_EQUAL(&sa->addr.v6,(memcmp(&(&sa->addr.v6)->__u6_addr.__u6_addr8[0
], &(&nbr->ei->iface->linklocal)->__u6_addr
.__u6_addr8[0], sizeof(struct in6_addr)) == 0)
286 &nbr->ei->iface->linklocal)(memcmp(&(&sa->addr.v6)->__u6_addr.__u6_addr8[0
], &(&nbr->ei->iface->linklocal)->__u6_addr
.__u6_addr8[0], sizeof(struct in6_addr)) == 0)
) {
287 nbr->flags &= ~F_EIGRP_NBR_CR_MODE0x04;
288 break;
289 }
290 break;
291 default:
292 break;
293 }
294 }
295 if (tm)
296 nbr->next_mcast_seq = ntohl(tm->seq)(__uint32_t)(__builtin_constant_p(tm->seq) ? (__uint32_t)(
((__uint32_t)(tm->seq) & 0xff) << 24 | ((__uint32_t
)(tm->seq) & 0xff00) << 8 | ((__uint32_t)(tm->
seq) & 0xff0000) >> 8 | ((__uint32_t)(tm->seq) &
0xff000000) >> 24) : __swap32md(tm->seq))
;
297 }
298
299 if ((ntohl(eigrp_hdr->flags)(__uint32_t)(__builtin_constant_p(eigrp_hdr->flags) ? (__uint32_t
)(((__uint32_t)(eigrp_hdr->flags) & 0xff) << 24 |
((__uint32_t)(eigrp_hdr->flags) & 0xff00) << 8 |
((__uint32_t)(eigrp_hdr->flags) & 0xff0000) >> 8
| ((__uint32_t)(eigrp_hdr->flags) & 0xff000000) >>
24) : __swap32md(eigrp_hdr->flags))
& EIGRP_HDR_FLAG_CR0x02)) {
300 if (!(nbr->flags & F_EIGRP_NBR_CR_MODE0x04))
301 return (-1);
302 nbr->flags &= ~F_EIGRP_NBR_CR_MODE0x04;
303 if (ntohl(eigrp_hdr->seq_num)(__uint32_t)(__builtin_constant_p(eigrp_hdr->seq_num) ? (__uint32_t
)(((__uint32_t)(eigrp_hdr->seq_num) & 0xff) << 24
| ((__uint32_t)(eigrp_hdr->seq_num) & 0xff00) <<
8 | ((__uint32_t)(eigrp_hdr->seq_num) & 0xff0000) >>
8 | ((__uint32_t)(eigrp_hdr->seq_num) & 0xff000000) >>
24) : __swap32md(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_MAX0xffffffffU && 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
324static void
325recv_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((void *)0);
331 struct tlv_sw_version *tv = NULL((void *)0);
332 struct tlv_mcast_seq *tm = NULL((void *)0);
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)do { (&seq_addr_list)->tqh_first = ((void *)0); (&
seq_addr_list)->tqh_last = &(&seq_addr_list)->tqh_first
; } while (0)
;
346 TAILQ_INIT(&rinfo_list)do { (&rinfo_list)->tqh_first = ((void *)0); (&rinfo_list
)->tqh_last = &(&rinfo_list)->tqh_first; } while
(0)
;
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)(__uint16_t)(__builtin_constant_p(tlv.length) ? (__uint16_t)(
((__uint16_t)(tlv.length) & 0xffU) << 8 | ((__uint16_t
)(tlv.length) & 0xff00U) >> 8) : __swap16md(tlv.length
))
> len) {
359 log_debug("%s: malformed packet (bad length)",
360 __func__);
361 goto error;
362 }
363
364 tlv_type = ntohs(tlv.type)(__uint16_t)(__builtin_constant_p(tlv.type) ? (__uint16_t)(((
__uint16_t)(tlv.type) & 0xffU) << 8 | ((__uint16_t)
(tlv.type) & 0xff00U) >> 8) : __swap16md(tlv.type))
;
365 switch (tlv_type) {
366 case TLV_TYPE_PARAMETER(0x0000 | 0x0001):
367 if ((tp = tlv_decode_parameter(&tlv, buf)) == NULL((void *)0))
368 goto error;
369 break;
370 case TLV_TYPE_SEQ(0x0000 | 0x0003):
371 if (tlv_decode_seq(af, &tlv, buf, &seq_addr_list) < 0)
372 goto error;
373 break;
374 case TLV_TYPE_SW_VERSION(0x0000 | 0x0004):
375 if ((tv = tlv_decode_sw_version(&tlv, buf)) == NULL((void *)0))
Although the value stored to 'tv' is used in the enclosing expression, the value is never actually read from 'tv'
376 goto error;
377 break;
378 case TLV_TYPE_MCAST_SEQ(0x0000 | 0x0005):
379 if ((tm = tlv_decode_mcast_seq(&tlv, buf)) == NULL((void *)0))
380 goto error;
381 break;
382 case TLV_TYPE_IPV4_INTERNAL(0x0100 | 0x0002):
383 case TLV_TYPE_IPV4_EXTERNAL(0x0100 | 0x0003):
384 case TLV_TYPE_IPV6_INTERNAL(0x0400 | 0x0002):
385 case TLV_TYPE_IPV6_EXTERNAL(0x0400 | 0x0003):
386 /* silently ignore TLV from different address-family */
387 if ((tlv_type & TLV_PROTO_MASK0xff00) == TLV_PROTO_IPV40x0100 &&
388 af != AF_INET2)
389 break;
390 if ((tlv_type & TLV_PROTO_MASK0xff00) == TLV_PROTO_IPV60x0400 &&
391 af != AF_INET624)
392 break;
393
394 if (tlv_decode_route(af, &tlv, buf, &ri) < 0)
395 goto error;
396 if ((re = calloc(1, sizeof(*re))) == NULL((void *)0))
397 fatal("recv_packet_eigrp");
398 re->rinfo = ri;
399 TAILQ_INSERT_TAIL(&rinfo_list, re, entry)do { (re)->entry.tqe_next = ((void *)0); (re)->entry.tqe_prev
= (&rinfo_list)->tqh_last; *(&rinfo_list)->tqh_last
= (re); (&rinfo_list)->tqh_last = &(re)->entry
.tqe_next; } while (0)
;
400 break;
401 case TLV_TYPE_AUTH(0x0000 | 0x0002):
402 case TLV_TYPE_PEER_TERM(0x0000 | 0x0007):
403 /*
404 * XXX There is no enough information in the draft
405 * to implement these TLVs properly.
406 */
407 case TLV_TYPE_IPV4_COMMUNITY(0x0100 | 0x0004):
408 case TLV_TYPE_IPV6_COMMUNITY(0x0400 | 0x0004):
409 /* TODO */
410 default:
411 /* ignore unknown tlv */
412 break;
413 }
414 buf += ntohs(tlv.length)(__uint16_t)(__builtin_constant_p(tlv.length) ? (__uint16_t)(
((__uint16_t)(tlv.length) & 0xffU) << 8 | ((__uint16_t
)(tlv.length) & 0xff00U) >> 8) : __swap16md(tlv.length
))
;
415 len -= ntohs(tlv.length)(__uint16_t)(__builtin_constant_p(tlv.length) ? (__uint16_t)(
((__uint16_t)(tlv.length) & 0xffU) << 8 | ((__uint16_t
)(tlv.length) & 0xff00U) >> 8) : __swap16md(tlv.length
))
;
416 }
417
418 ei = eigrp_if_lookup(iface, af, ntohs(eigrp_hdr->as)(__uint16_t)(__builtin_constant_p(eigrp_hdr->as) ? (__uint16_t
)(((__uint16_t)(eigrp_hdr->as) & 0xffU) << 8 | (
(__uint16_t)(eigrp_hdr->as) & 0xff00U) >> 8) : __swap16md
(eigrp_hdr->as))
);
419 if (ei == NULL((void *)0) || ei->passive)
420 goto error;
421
422 nbr = nbr_find(ei, src);
423 if (nbr == NULL((void *)0) && (eigrp_hdr->opcode != EIGRP_OPC_HELLO5 ||
424 ntohl(eigrp_hdr->ack_num)(__uint32_t)(__builtin_constant_p(eigrp_hdr->ack_num) ? (__uint32_t
)(((__uint32_t)(eigrp_hdr->ack_num) & 0xff) << 24
| ((__uint32_t)(eigrp_hdr->ack_num) & 0xff00) <<
8 | ((__uint32_t)(eigrp_hdr->ack_num) & 0xff0000) >>
8 | ((__uint32_t)(eigrp_hdr->ack_num) & 0xff000000) >>
24) : __swap32md(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_HELLO5)
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)(__uint32_t)(__builtin_constant_p(eigrp_hdr->seq_num) ? (__uint32_t
)(((__uint32_t)(eigrp_hdr->seq_num) & 0xff) << 24
| ((__uint32_t)(eigrp_hdr->seq_num) & 0xff00) <<
8 | ((__uint32_t)(eigrp_hdr->seq_num) & 0xff0000) >>
8 | ((__uint32_t)(eigrp_hdr->seq_num) & 0xff000000) >>
24) : __swap32md(eigrp_hdr->seq_num))
,
436 ntohl(eigrp_hdr->ack_num)(__uint32_t)(__builtin_constant_p(eigrp_hdr->ack_num) ? (__uint32_t
)(((__uint32_t)(eigrp_hdr->ack_num) & 0xff) << 24
| ((__uint32_t)(eigrp_hdr->ack_num) & 0xff00) <<
8 | ((__uint32_t)(eigrp_hdr->ack_num) & 0xff0000) >>
8 | ((__uint32_t)(eigrp_hdr->ack_num) & 0xff000000) >>
24) : __swap32md(eigrp_hdr->ack_num))
);
437
438 /* switch EIGRP packet type */
439 switch (eigrp_hdr->opcode) {
440 case EIGRP_OPC_HELLO5:
441 if (ntohl(eigrp_hdr->ack_num)(__uint32_t)(__builtin_constant_p(eigrp_hdr->ack_num) ? (__uint32_t
)(((__uint32_t)(eigrp_hdr->ack_num) & 0xff) << 24
| ((__uint32_t)(eigrp_hdr->ack_num) & 0xff00) <<
8 | ((__uint32_t)(eigrp_hdr->ack_num) & 0xff0000) >>
8 | ((__uint32_t)(eigrp_hdr->ack_num) & 0xff000000) >>
24) : __swap32md(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_UPDATE1:
448 recv_update(nbr, &rinfo_list, ntohl(eigrp_hdr->flags)(__uint32_t)(__builtin_constant_p(eigrp_hdr->flags) ? (__uint32_t
)(((__uint32_t)(eigrp_hdr->flags) & 0xff) << 24 |
((__uint32_t)(eigrp_hdr->flags) & 0xff00) << 8 |
((__uint32_t)(eigrp_hdr->flags) & 0xff0000) >> 8
| ((__uint32_t)(eigrp_hdr->flags) & 0xff000000) >>
24) : __swap32md(eigrp_hdr->flags))
);
449 ei->eigrp->stats.updates_recv++;
450 break;
451 case EIGRP_OPC_QUERY3:
452 recv_query(nbr, &rinfo_list, 0);
453 ei->eigrp->stats.queries_recv++;
454 break;
455 case EIGRP_OPC_REPLY4:
456 recv_reply(nbr, &rinfo_list, 0);
457 ei->eigrp->stats.replies_recv++;
458 break;
459 case EIGRP_OPC_SIAQUERY10:
460 recv_query(nbr, &rinfo_list, 1);
461 ei->eigrp->stats.squeries_recv++;
462 break;
463 case EIGRP_OPC_SIAREPLY11:
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
472error:
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((sizeof(struct sockaddr_dl)) > (sizeof(struct in6_pktinfo
)) ? (sizeof(struct sockaddr_dl)) : (sizeof(struct in6_pktinfo
)))
max(sizeof(struct sockaddr_dl), sizeof(struct in6_pktinfo))((sizeof(struct sockaddr_dl)) > (sizeof(struct in6_pktinfo
)) ? (sizeof(struct sockaddr_dl)) : (sizeof(struct in6_pktinfo
)))
480void
481recv_packet(int fd, short event, void *bula)
482{
483 union {
484 struct cmsghdr hdr;
485 char buf[CMSG_SPACE(CMSG_MAXLEN)((((unsigned long)(sizeof(struct cmsghdr)) + (sizeof(long) - 1
)) &~(sizeof(long) - 1)) + (((unsigned long)(((sizeof(struct
sockaddr_dl)) > (sizeof(struct in6_pktinfo)) ? (sizeof(struct
sockaddr_dl)) : (sizeof(struct in6_pktinfo)))) + (sizeof(long
) - 1)) &~(sizeof(long) - 1)))
];
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_SIZE65535];
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_READ0x02)
503 return;
504
505 /* setup buffer */
506 memset(&msg, 0, sizeof(msg));
507 iov.iov_base = buf = pkt;
508 iov.iov_len = READ_BUF_SIZE65535;
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(*__errno()) != EAGAIN35 && errno(*__errno()) != EINTR4)
518 log_debug("%s: read error: %s", __func__,
519 strerror(errno(*__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)((&msg)->msg_controllen >= sizeof(struct cmsghdr) ?
(struct cmsghdr *)(&msg)->msg_control : (struct cmsghdr
*)((void *)0))
; cmsg != NULL((void *)0);
532 cmsg = CMSG_NXTHDR(&msg, cmsg)(((char *)(cmsg) + (((unsigned long)((cmsg)->cmsg_len) + (
sizeof(long) - 1)) &~(sizeof(long) - 1)) + (((unsigned long
)(sizeof(struct cmsghdr)) + (sizeof(long) - 1)) &~(sizeof
(long) - 1)) > ((char *)(&msg)->msg_control) + (&
msg)->msg_controllen) ? (struct cmsghdr *)((void *)0) : (struct
cmsghdr *)((char *)(cmsg) + (((unsigned long)((cmsg)->cmsg_len
) + (sizeof(long) - 1)) &~(sizeof(long) - 1))))
) {
533 if (af == AF_INET2 && cmsg->cmsg_level == IPPROTO_IP0 &&
534 cmsg->cmsg_type == IP_RECVIF30) {
535 ifindex = ((struct sockaddr_dl *)
536 CMSG_DATA(cmsg)((unsigned char *)(cmsg) + (((unsigned long)(sizeof(struct cmsghdr
)) + (sizeof(long) - 1)) &~(sizeof(long) - 1)))
)->sdl_index;
537 break;
538 }
539 if (af == AF_INET624 && cmsg->cmsg_level == IPPROTO_IPV641 &&
540 cmsg->cmsg_type == IPV6_PKTINFO46) {
541 ifindex = ((struct in6_pktinfo *)
542 CMSG_DATA(cmsg)((unsigned char *)(cmsg) + (((unsigned long)(sizeof(struct cmsghdr
)) + (sizeof(long) - 1)) &~(sizeof(long) - 1)))
)->ipi6_ifindex;
543 dest.v6 = ((struct in6_pktinfo *)
544 CMSG_DATA(cmsg)((unsigned char *)(cmsg) + (((unsigned long)(sizeof(struct cmsghdr
)) + (sizeof(long) - 1)) &~(sizeof(long) - 1)))
)->ipi6_addr;
545 break;
546 }
547 }
548
549 /* find a matching interface */
550 if ((iface = find_iface(ifindex, af, &src)) == NULL((void *)0))
551 return;
552
553 /* the IPv4 raw sockets API gives us direct access to the IP header */
554 if (af == AF_INET2) {
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)(__uint16_t)(__builtin_constant_p(ip_hdr.ip_len) ? (__uint16_t
)(((__uint16_t)(ip_hdr.ip_len) & 0xffU) << 8 | ((__uint16_t
)(ip_hdr.ip_len) & 0xff00U) >> 8) : __swap16md(ip_hdr
.ip_len))
!= len) {
561 log_debug("%s: invalid IP packet length %u", __func__,
562 ntohs(ip_hdr.ip_len)(__uint16_t)(__builtin_constant_p(ip_hdr.ip_len) ? (__uint16_t
)(((__uint16_t)(ip_hdr.ip_len) & 0xffU) << 8 | ((__uint16_t
)(ip_hdr.ip_len) & 0xff00U) >> 8) : __swap16md(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_INET2:
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)for((if_addr) = ((&iface->addr_list)->tqh_first); (
if_addr) != ((void *)0); (if_addr) = ((if_addr)->entry.tqe_next
))
582 if (if_addr->af == AF_INET2 &&
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_INET624:
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)(memcmp(&(&dest.v6)->__u6_addr.__u6_addr8[0], &
(&global.mcast_addr_v6)->__u6_addr.__u6_addr8[0], sizeof
(struct in6_addr)) == 0)
&&
601 !IN6_ARE_ADDR_EQUAL(&dest.v6, &iface->linklocal)(memcmp(&(&dest.v6)->__u6_addr.__u6_addr8[0], &
(&iface->linklocal)->__u6_addr.__u6_addr8[0], sizeof
(struct in6_addr)) == 0)
) {
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
622static int
623eigrp_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_VERSION2) {
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)(__uint16_t)(__builtin_constant_p(eigrp_hdr->vrid) ? (__uint16_t
)(((__uint16_t)(eigrp_hdr->vrid) & 0xffU) << 8 |
((__uint16_t)(eigrp_hdr->vrid) & 0xff00U) >> 8)
: __swap16md(eigrp_hdr->vrid))
!= EIGRP_VRID_UNICAST_AF0x0000) {
639 log_debug("%s: unknown or unsupported vrid %u, interface %s",
640 __func__, ntohs(eigrp_hdr->vrid)(__uint16_t)(__builtin_constant_p(eigrp_hdr->vrid) ? (__uint16_t
)(((__uint16_t)(eigrp_hdr->vrid) & 0xffU) << 8 |
((__uint16_t)(eigrp_hdr->vrid) & 0xff00U) >> 8)
: __swap16md(eigrp_hdr->vrid))
, iface->name);
641 return (-1);
642 }
643
644 if (eigrp_hdr->opcode == EIGRP_OPC_HELLO5 &&
645 eigrp_hdr->ack_num != 0) {
646 switch (af) {
647 case AF_INET2:
648 if (IN_MULTICAST(addr->v4.s_addr)(((u_int32_t)(addr->v4.s_addr) & ((u_int32_t)(0xf0000000
))) == ((u_int32_t)(0xe0000000)))
) {
649 log_debug("%s: multicast ack (ipv4), "
650 "interface %s", __func__, iface->name);
651 return (-1);
652 }
653 break;
654 case AF_INET624:
655 if (IN6_IS_ADDR_MULTICAST(&addr->v6)((&addr->v6)->__u6_addr.__u6_addr8[0] == 0xff)) {
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
669static struct iface *
670find_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((void *)0))
678 return (NULL((void *)0));
679
680 switch (af) {
681 case AF_INET2:
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)for((if_addr) = ((&iface->addr_list)->tqh_first); (
if_addr) != ((void *)0); (if_addr) = ((if_addr)->entry.tqe_next
))
{
691 if (if_addr->af == AF_INET2) {
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_INET624:
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)(((&src->v6)->__u6_addr.__u6_addr8[0] == 0xfe) &&
(((&src->v6)->__u6_addr.__u6_addr8[1] & 0xc0) ==
0x80))
)
707 return (iface);
708 break;
709 default:
710 fatalx("find_iface: unknown af");
711 }
712
713 return (NULL((void *)0));
714}