Bug Summary

File:src/usr.sbin/eigrpd/packet.c
Warning:line 362, 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.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name packet.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -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 -fno-rounding-math -mconstructor-aliases -munwind-tables -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/lib/clang/13.0.0 -I /usr/src/usr.sbin/eigrpd -internal-isystem /usr/local/lib/clang/13.0.0/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 -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/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.sbin/eigrpd/packet.c
1/* $OpenBSD: packet.c,v 1.20 2021/01/19 11:49:26 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 <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30
31#include "eigrpd.h"
32#include "eigrpe.h"
33#include "log.h"
34
35static int send_packet_v4(struct iface *, struct nbr *, struct ibuf *);
36static int send_packet_v6(struct iface *, struct nbr *, struct ibuf *);
37static int recv_packet_nbr(struct nbr *, struct eigrp_hdr *,
38 struct seq_addr_head *, struct tlv_mcast_seq *);
39static void recv_packet_eigrp(int, union eigrpd_addr *,
40 union eigrpd_addr *, struct iface *, struct eigrp_hdr *,
41 char *, uint16_t);
42static int eigrp_hdr_sanity_check(int, union eigrpd_addr *,
43 struct eigrp_hdr *, uint16_t, const struct iface *);
44static struct iface *find_iface(unsigned int, int, union eigrpd_addr *);
45
46int
47gen_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_VERSION2;
54 eigrp_hdr.opcode = opcode;
55 /* chksum will be set later */
56 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))
;
57 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))
;
58 /* ack_num will be set later */
59 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))
;
60 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))
;
61
62 return (ibuf_add(buf, &eigrp_hdr, sizeof(eigrp_hdr)));
63}
64
65/* send and receive packets */
66static int
67send_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_INET2;
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 = IPVERSION4;
85 ip_hdr.ip_hl = sizeof(ip_hdr) >> 2;
86 ip_hdr.ip_tos = IPTOS_PREC_INTERNETCONTROL0xc0;
87 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)))
;
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_TTL2;
91 ip_hdr.ip_p = IPPROTO_EIGRP88;
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))(((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)
))
)
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
124static int
125send_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_INET624;
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)((&sa6.sin6_addr)->__u6_addr.__u6_addr8[0] == 0xff))
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
157int
158send_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_UP0x1) || !LINK_STATE_IS_UP(iface->linkstate)((iface->linkstate) >= 4 || (iface->linkstate) == 0))
166 return (-1);
167
168 /* update ack number, flags and checksum */
169 if ((eigrp_hdr = ibuf_seek(buf, 0, sizeof(*eigrp_hdr))) == NULL((void *)0))
170 fatalx("send_packet: buf_seek failed");
171 if (nbr) {
172 eigrp_hdr->ack_num = htonl(nbr->recv_seq)(__uint32_t)(__builtin_constant_p(nbr->recv_seq) ? (__uint32_t
)(((__uint32_t)(nbr->recv_seq) & 0xff) << 24 | (
(__uint32_t)(nbr->recv_seq) & 0xff00) << 8 | ((__uint32_t
)(nbr->recv_seq) & 0xff0000) >> 8 | ((__uint32_t
)(nbr->recv_seq) & 0xff000000) >> 24) : __swap32md
(nbr->recv_seq))
;
173 rtp_ack_stop_timer(nbr);
174 }
175 if (flags) {
176 eigrp_hdr->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))
| flags;
177 eigrp_hdr->flags = htonl(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))
;
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_HELLO5) {
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)(__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))
,
195 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))
);
196 }
197
198 switch (eigrp->af) {
199 case AF_INET2:
200 if (send_packet_v4(iface, nbr, buf) < 0)
201 return (-1);
202 break;
203 case AF_INET624:
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_HELLO5:
213 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)
214 ei->eigrp->stats.hellos_sent++;
215 else
216 ei->eigrp->stats.acks_sent++;
217 break;
218 case EIGRP_OPC_UPDATE1:
219 ei->eigrp->stats.updates_sent++;
220 break;
221 case EIGRP_OPC_QUERY3:
222 ei->eigrp->stats.queries_sent++;
223 break;
224 case EIGRP_OPC_REPLY4:
225 ei->eigrp->stats.replies_sent++;
226 break;
227 case EIGRP_OPC_SIAQUERY10:
228 ei->eigrp->stats.squeries_sent++;
229 break;
230 case EIGRP_OPC_SIAREPLY11:
231 ei->eigrp->stats.sreplies_sent++;
232 break;
233 default:
234 break;
235 }
236
237 return (0);
238}
239
240static int
241recv_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)(__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))
;
248 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))
;
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_HELLO5 &&
259 !TAILQ_EMPTY(seq_addr_list)(((seq_addr_list)->tqh_first) == ((void *)0))) {
260 nbr->flags |= F_EIGRP_NBR_CR_MODE0x04;
261
262 TAILQ_FOREACH(sa, seq_addr_list, entry)for((sa) = ((seq_addr_list)->tqh_first); (sa) != ((void *)
0); (sa) = ((sa)->entry.tqe_next))
{
263 switch (sa->af) {
264 case AF_INET2:
265 if (sa->addr.v4.s_addr ==
266 if_primary_addr(nbr->ei->iface)) {
267 nbr->flags &= ~F_EIGRP_NBR_CR_MODE0x04;
268 break;
269 }
270 break;
271 case AF_INET624:
272 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)
273 &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)
) {
274 nbr->flags &= ~F_EIGRP_NBR_CR_MODE0x04;
275 break;
276 }
277 break;
278 default:
279 break;
280 }
281 }
282 if (tm)
283 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))
;
284 }
285
286 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)) {
287 if (!(nbr->flags & F_EIGRP_NBR_CR_MODE0x04))
288 return (-1);
289 nbr->flags &= ~F_EIGRP_NBR_CR_MODE0x04;
290 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)
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_MAX0xffffffffU && 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
311static void
312recv_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((void *)0);
318 struct tlv_sw_version *tv = NULL((void *)0);
319 struct tlv_mcast_seq *tm = NULL((void *)0);
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)do { (&seq_addr_list)->tqh_first = ((void *)0); (&
seq_addr_list)->tqh_last = &(&seq_addr_list)->tqh_first
; } while (0)
;
333 TAILQ_INIT(&rinfo_list)do { (&rinfo_list)->tqh_first = ((void *)0); (&rinfo_list
)->tqh_last = &(&rinfo_list)->tqh_first; } while
(0)
;
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)(__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) {
346 log_debug("%s: malformed packet (bad length)",
347 __func__);
348 goto error;
349 }
350
351 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))
;
352 switch (tlv_type) {
353 case TLV_TYPE_PARAMETER(0x0000 | 0x0001):
354 if ((tp = tlv_decode_parameter(&tlv, buf)) == NULL((void *)0))
355 goto error;
356 break;
357 case TLV_TYPE_SEQ(0x0000 | 0x0003):
358 if (tlv_decode_seq(af, &tlv, buf, &seq_addr_list) < 0)
359 goto error;
360 break;
361 case TLV_TYPE_SW_VERSION(0x0000 | 0x0004):
362 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'
363 goto error;
364 break;
365 case TLV_TYPE_MCAST_SEQ(0x0000 | 0x0005):
366 if ((tm = tlv_decode_mcast_seq(&tlv, buf)) == NULL((void *)0))
367 goto error;
368 break;
369 case TLV_TYPE_IPV4_INTERNAL(0x0100 | 0x0002):
370 case TLV_TYPE_IPV4_EXTERNAL(0x0100 | 0x0003):
371 case TLV_TYPE_IPV6_INTERNAL(0x0400 | 0x0002):
372 case TLV_TYPE_IPV6_EXTERNAL(0x0400 | 0x0003):
373 /* silently ignore TLV from different address-family */
374 if ((tlv_type & TLV_PROTO_MASK0xff00) == TLV_PROTO_IPV40x0100 &&
375 af != AF_INET2)
376 break;
377 if ((tlv_type & TLV_PROTO_MASK0xff00) == TLV_PROTO_IPV60x0400 &&
378 af != AF_INET624)
379 break;
380
381 if (tlv_decode_route(af, &tlv, buf, &ri) < 0)
382 goto error;
383 if ((re = calloc(1, sizeof(*re))) == NULL((void *)0))
384 fatal("recv_packet_eigrp");
385 re->rinfo = ri;
386 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)
;
387 break;
388 case TLV_TYPE_AUTH(0x0000 | 0x0002):
389 case TLV_TYPE_PEER_TERM(0x0000 | 0x0007):
390 /*
391 * XXX There is no enough information in the draft
392 * to implement these TLVs properly.
393 */
394 case TLV_TYPE_IPV4_COMMUNITY(0x0100 | 0x0004):
395 case TLV_TYPE_IPV6_COMMUNITY(0x0400 | 0x0004):
396 /* TODO */
397 default:
398 /* ignore unknown tlv */
399 break;
400 }
401 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
))
;
402 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
))
;
403 }
404
405 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))
);
406 if (ei == NULL((void *)0) || ei->passive)
407 goto error;
408
409 nbr = nbr_find(ei, src);
410 if (nbr == NULL((void *)0) && (eigrp_hdr->opcode != EIGRP_OPC_HELLO5 ||
411 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)) {
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_HELLO5)
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)(__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))
,
423 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))
);
424
425 /* switch EIGRP packet type */
426 switch (eigrp_hdr->opcode) {
427 case EIGRP_OPC_HELLO5:
428 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) {
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_UPDATE1:
435 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))
);
436 ei->eigrp->stats.updates_recv++;
437 break;
438 case EIGRP_OPC_QUERY3:
439 recv_query(nbr, &rinfo_list, 0);
440 ei->eigrp->stats.queries_recv++;
441 break;
442 case EIGRP_OPC_REPLY4:
443 recv_reply(nbr, &rinfo_list, 0);
444 ei->eigrp->stats.replies_recv++;
445 break;
446 case EIGRP_OPC_SIAQUERY10:
447 recv_query(nbr, &rinfo_list, 1);
448 ei->eigrp->stats.squeries_recv++;
449 break;
450 case EIGRP_OPC_SIAREPLY11:
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
459error:
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((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
)))
467void
468recv_packet(int fd, short event, void *bula)
469{
470 union {
471 struct cmsghdr hdr;
472 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)))
];
473 } cmsgbuf;
474 struct msghdr msg;
475 struct sockaddr_storage from;
476 struct iovec iov;
477 struct ip ip_hdr;
478 char pkt[READ_BUF_SIZE65535];
479 char *buf;
480 struct cmsghdr *cmsg;
481 ssize_t r;
482 uint16_t len;
483 int af;
484 union eigrpd_addr src, dest;
485 unsigned int ifindex = 0;
486 struct iface *iface;
487 struct eigrp_hdr *eigrp_hdr;
488
489 if (event != EV_READ0x02)
490 return;
491
492 /* setup buffer */
493 memset(&msg, 0, sizeof(msg));
494 iov.iov_base = buf = pkt;
495 iov.iov_len = READ_BUF_SIZE65535;
496 msg.msg_name = &from;
497 msg.msg_namelen = sizeof(from);
498 msg.msg_iov = &iov;
499 msg.msg_iovlen = 1;
500 msg.msg_control = &cmsgbuf.buf;
501 msg.msg_controllen = sizeof(cmsgbuf.buf);
502
503 if ((r = recvmsg(fd, &msg, 0)) == -1) {
504 if (errno(*__errno()) != EAGAIN35 && errno(*__errno()) != EINTR4)
505 log_debug("%s: read error: %s", __func__,
506 strerror(errno(*__errno())));
507 return;
508 }
509 len = (uint16_t)r;
510
511 sa2addr((struct sockaddr *)&from, &af, &src);
512 if (bad_addr(af, &src)) {
513 log_debug("%s: invalid source address: %s", __func__,
514 log_addr(af, &src));
515 return;
516 }
517
518 for (cmsg = CMSG_FIRSTHDR(&msg)((&msg)->msg_controllen >= sizeof(struct cmsghdr) ?
(struct cmsghdr *)(&msg)->msg_control : (struct cmsghdr
*)((void *)0))
; cmsg != NULL((void *)0);
519 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))))
) {
520 if (af == AF_INET2 && cmsg->cmsg_level == IPPROTO_IP0 &&
521 cmsg->cmsg_type == IP_RECVIF30) {
522 ifindex = ((struct sockaddr_dl *)
523 CMSG_DATA(cmsg)((unsigned char *)(cmsg) + (((unsigned long)(sizeof(struct cmsghdr
)) + (sizeof(long) - 1)) &~(sizeof(long) - 1)))
)->sdl_index;
524 break;
525 }
526 if (af == AF_INET624 && cmsg->cmsg_level == IPPROTO_IPV641 &&
527 cmsg->cmsg_type == IPV6_PKTINFO46) {
528 ifindex = ((struct in6_pktinfo *)
529 CMSG_DATA(cmsg)((unsigned char *)(cmsg) + (((unsigned long)(sizeof(struct cmsghdr
)) + (sizeof(long) - 1)) &~(sizeof(long) - 1)))
)->ipi6_ifindex;
530 dest.v6 = ((struct in6_pktinfo *)
531 CMSG_DATA(cmsg)((unsigned char *)(cmsg) + (((unsigned long)(sizeof(struct cmsghdr
)) + (sizeof(long) - 1)) &~(sizeof(long) - 1)))
)->ipi6_addr;
532 break;
533 }
534 }
535
536 /* find a matching interface */
537 if ((iface = find_iface(ifindex, af, &src)) == NULL((void *)0))
538 return;
539
540 /* the IPv4 raw sockets API gives us direct access to the IP header */
541 if (af == AF_INET2) {
542 if (len < sizeof(ip_hdr)) {
543 log_debug("%s: bad packet size", __func__);
544 return;
545 }
546 memcpy(&ip_hdr, buf, sizeof(ip_hdr));
547 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) {
548 log_debug("%s: invalid IP packet length %u", __func__,
549 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))
);
550 return;
551 }
552 buf += ip_hdr.ip_hl << 2;
553 len -= ip_hdr.ip_hl << 2;
554 dest.v4 = ip_hdr.ip_dst;
555 }
556
557 /* validate destination address */
558 switch (af) {
559 case AF_INET2:
560 /*
561 * Packet needs to be sent to 224.0.0.10 or to one of the
562 * interface addresses.
563 */
564 if (dest.v4.s_addr != global.mcast_addr_v4.s_addr) {
565 struct if_addr *if_addr;
566 int found = 0;
567
568 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
))
569 if (if_addr->af == AF_INET2 &&
570 dest.v4.s_addr == if_addr->addr.v4.s_addr) {
571 found = 1;
572 break;
573 }
574 if (found == 0) {
575 log_debug("%s: packet sent to wrong address "
576 "%s, interface %s", __func__,
577 inet_ntoa(dest.v4), iface->name);
578 return;
579 }
580 }
581 break;
582 case AF_INET624:
583 /*
584 * Packet needs to be sent to ff02::a or to the link local
585 * address of the interface.
586 */
587 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)
&&
588 !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)
) {
589 log_debug("%s: packet sent to wrong address %s, "
590 "interface %s", __func__, log_in6addr(&dest.v6),
591 iface->name);
592 return;
593 }
594 break;
595 default:
596 fatalx("recv_packet: unknown af");
597 break;
598 }
599
600 if (len < sizeof(*eigrp_hdr)) {
601 log_debug("%s: bad packet size", __func__);
602 return;
603 }
604 eigrp_hdr = (struct eigrp_hdr *)buf;
605
606 recv_packet_eigrp(af, &src, &dest, iface, eigrp_hdr, buf, len);
607}
608
609static int
610eigrp_hdr_sanity_check(int af, union eigrpd_addr *addr,
611 struct eigrp_hdr *eigrp_hdr, uint16_t len, const struct iface *iface)
612{
613 if (in_cksum(eigrp_hdr, len)) {
614 log_debug("%s: invalid checksum, interface %s", __func__,
615 iface->name);
616 return (-1);
617 }
618
619 if (eigrp_hdr->version != EIGRP_HEADER_VERSION2) {
620 log_debug("%s: invalid EIGRP version %d, interface %s",
621 __func__, eigrp_hdr->version, iface->name);
622 return (-1);
623 }
624
625 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) {
626 log_debug("%s: unknown or unsupported vrid %u, interface %s",
627 __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);
628 return (-1);
629 }
630
631 if (eigrp_hdr->opcode == EIGRP_OPC_HELLO5 &&
632 eigrp_hdr->ack_num != 0) {
633 switch (af) {
634 case AF_INET2:
635 if (IN_MULTICAST(addr->v4.s_addr)(((u_int32_t)(addr->v4.s_addr) & ((u_int32_t)(0xf0000000
))) == ((u_int32_t)(0xe0000000)))
) {
636 log_debug("%s: multicast ack (ipv4), "
637 "interface %s", __func__, iface->name);
638 return (-1);
639 }
640 break;
641 case AF_INET624:
642 if (IN6_IS_ADDR_MULTICAST(&addr->v6)((&addr->v6)->__u6_addr.__u6_addr8[0] == 0xff)) {
643 log_debug("%s: multicast ack (ipv6), "
644 "interface %s", __func__, iface->name);
645 return (-1);
646 }
647 break;
648 default:
649 fatalx("eigrp_hdr_sanity_check: unknown af");
650 }
651 }
652
653 return (0);
654}
655
656static struct iface *
657find_iface(unsigned int ifindex, int af, union eigrpd_addr *src)
658{
659 struct iface *iface;
660 struct if_addr *if_addr;
661 in_addr_t mask;
662
663 iface = if_lookup(econf, ifindex);
664 if (iface == NULL((void *)0))
665 return (NULL((void *)0));
666
667 switch (af) {
668 case AF_INET2:
669 /*
670 * From CCNP ROUTE 642-902 OCG:
671 * "EIGRP's rules about neighbor IP addresses being in the same
672 * subnet are less exact than OSPF. OSPF requires matching
673 * subnet numbers and masks. EIGRP just asks the question of
674 * whether the neighbor's IP address is in the range of
675 * addresses for the subnet as known to the local router."
676 */
677 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
))
{
678 if (if_addr->af == AF_INET2) {
679 mask = prefixlen2mask(if_addr->prefixlen);
680
681 if ((if_addr->addr.v4.s_addr & mask) ==
682 (src->v4.s_addr & mask))
683 return (iface);
684 }
685 }
686 break;
687 case AF_INET624:
688 /*
689 * draft-savage-eigrp-04 - Section 10.1:
690 * "EIGRP IPv6 will check that a received HELLO contains a valid
691 * IPv6 link-local source address."
692 */
693 if (IN6_IS_ADDR_LINKLOCAL(&src->v6)(((&src->v6)->__u6_addr.__u6_addr8[0] == 0xfe) &&
(((&src->v6)->__u6_addr.__u6_addr8[1] & 0xc0) ==
0x80))
)
694 return (iface);
695 break;
696 default:
697 fatalx("find_iface: unknown af");
698 }
699
700 return (NULL((void *)0));
701}