Bug Summary

File:src/usr.sbin/traceroute/traceroute.c
Warning:line 885, column 1
Address of stack memory associated with local variable 'rcviov' is still referred to by the global variable 'rcvmhdr' upon returning to the caller. This will be a dangling reference

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 traceroute.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/traceroute/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.sbin/traceroute -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/traceroute/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/traceroute/traceroute.c
1/* $OpenBSD: traceroute.c,v 1.168 2021/09/03 09:13:00 florian Exp $ */
2/* $NetBSD: traceroute.c,v 1.10 1995/05/21 15:50:45 mycroft Exp $ */
3
4/*
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the project nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33/*-
34 * Copyright (c) 1990, 1993
35 * The Regents of the University of California. All rights reserved.
36 *
37 * This code is derived from software contributed to Berkeley by
38 * Van Jacobson.
39 *
40 * Redistribution and use in source and binary forms, with or without
41 * modification, are permitted provided that the following conditions
42 * are met:
43 * 1. Redistributions of source code must retain the above copyright
44 * notice, this list of conditions and the following disclaimer.
45 * 2. Redistributions in binary form must reproduce the above copyright
46 * notice, this list of conditions and the following disclaimer in the
47 * documentation and/or other materials provided with the distribution.
48 * 3. Neither the name of the University nor the names of its contributors
49 * may be used to endorse or promote products derived from this software
50 * without specific prior written permission.
51 *
52 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62 * SUCH DAMAGE.
63 */
64
65/*
66 * traceroute host - trace the route ip packets follow going to "host".
67 *
68 * Attempt to trace the route an ip packet would follow to some
69 * internet host. We find out intermediate hops by launching probe
70 * packets with a small ttl (time to live) then listening for an
71 * icmp "time exceeded" reply from a gateway. We start our probes
72 * with a ttl of one and increase by one until we get an icmp "port
73 * unreachable" (which means we got to "host") or hit a max (which
74 * defaults to 64 hops & can be changed with the -m flag). Three
75 * probes (change with -q flag) are sent at each ttl setting and a
76 * line is printed showing the ttl, address of the gateway and
77 * round trip time of each probe. If the probe answers come from
78 * different gateways, the address of each responding system will
79 * be printed. If there is no response within a 5 sec. timeout
80 * interval (changed with the -w flag), a "*" is printed for that
81 * probe.
82 *
83 * Probe packets are UDP format. We don't want the destination
84 * host to process them so the destination port is set to an
85 * unlikely value (if some clod on the destination is using that
86 * value, it can be changed with the -p flag).
87 *
88 * A sample use might be:
89 *
90 * [yak 71]% traceroute nis.nsf.net.
91 * traceroute to nis.nsf.net (35.1.1.48), 64 hops max, 56 byte packet
92 * 1 helios.ee.lbl.gov (128.3.112.1) 19 ms 19 ms 0 ms
93 * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms
94 * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms
95 * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 39 ms
96 * 5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 39 ms 39 ms 39 ms
97 * 6 128.32.197.4 (128.32.197.4) 40 ms 59 ms 59 ms
98 * 7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 59 ms
99 * 8 129.140.70.13 (129.140.70.13) 99 ms 99 ms 80 ms
100 * 9 129.140.71.6 (129.140.71.6) 139 ms 239 ms 319 ms
101 * 10 129.140.81.7 (129.140.81.7) 220 ms 199 ms 199 ms
102 * 11 nic.merit.edu (35.1.1.48) 239 ms 239 ms 239 ms
103 *
104 * Note that lines 2 & 3 are the same. This is due to a buggy
105 * kernel on the 2nd hop system -- lbl-csam.arpa -- that forwards
106 * packets with a zero ttl.
107 *
108 * A more interesting example is:
109 *
110 * [yak 72]% traceroute allspice.lcs.mit.edu.
111 * traceroute to allspice.lcs.mit.edu (18.26.0.115), 64 hops max
112 * 1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms
113 * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 19 ms 19 ms
114 * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 19 ms
115 * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 19 ms 39 ms 39 ms
116 * 5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 20 ms 39 ms 39 ms
117 * 6 128.32.197.4 (128.32.197.4) 59 ms 119 ms 39 ms
118 * 7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 39 ms
119 * 8 129.140.70.13 (129.140.70.13) 80 ms 79 ms 99 ms
120 * 9 129.140.71.6 (129.140.71.6) 139 ms 139 ms 159 ms
121 * 10 129.140.81.7 (129.140.81.7) 199 ms 180 ms 300 ms
122 * 11 129.140.72.17 (129.140.72.17) 300 ms 239 ms 239 ms
123 * 12 * * *
124 * 13 128.121.54.72 (128.121.54.72) 259 ms 499 ms 279 ms
125 * 14 * * *
126 * 15 * * *
127 * 16 * * *
128 * 17 * * *
129 * 18 ALLSPICE.LCS.MIT.EDU (18.26.0.115) 339 ms 279 ms 279 ms
130 *
131 * (I start to see why I'm having so much trouble with mail to
132 * MIT.) Note that the gateways 12, 14, 15, 16 & 17 hops away
133 * either don't send ICMP "time exceeded" messages or send them
134 * with a ttl too small to reach us. 14 - 17 are running the
135 * MIT C Gateway code that doesn't send "time exceeded"s. God
136 * only knows what's going on with 12.
137 *
138 * The silent gateway 12 in the above may be the result of a bug in
139 * the 4.[23]BSD network code (and its derivatives): 4.x (x <= 3)
140 * sends an unreachable message using whatever ttl remains in the
141 * original datagram. Since, for gateways, the remaining ttl is
142 * zero, the icmp "time exceeded" is guaranteed to not make it back
143 * to us. The behavior of this bug is slightly more interesting
144 * when it appears on the destination system:
145 *
146 * 1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms
147 * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 39 ms
148 * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 39 ms 19 ms
149 * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 19 ms
150 * 5 ccn-nerif35.Berkeley.EDU (128.32.168.35) 39 ms 39 ms 39 ms
151 * 6 csgw.Berkeley.EDU (128.32.133.254) 39 ms 59 ms 39 ms
152 * 7 * * *
153 * 8 * * *
154 * 9 * * *
155 * 10 * * *
156 * 11 * * *
157 * 12 * * *
158 * 13 rip.Berkeley.EDU (128.32.131.22) 59 ms ! 39 ms ! 39 ms !
159 *
160 * Notice that there are 12 "gateways" (13 is the final
161 * destination) and exactly the last half of them are "missing".
162 * What's really happening is that rip (a Sun-3 running Sun OS3.5)
163 * is using the ttl from our arriving datagram as the ttl in its
164 * icmp reply. So, the reply will time out on the return path
165 * (with no notice sent to anyone since icmp's aren't sent for
166 * icmp's) until we probe with a ttl that's at least twice the path
167 * length. I.e., rip is really only 7 hops away. A reply that
168 * returns with a ttl of 1 is a clue this problem exists.
169 * Traceroute prints a "!" after the time if the ttl is <= 1.
170 * Since vendors ship a lot of obsolete (DEC's Ultrix, Sun 3.x) or
171 * non-standard (HPUX) software, expect to see this problem
172 * frequently and/or take care picking the target host of your
173 * probes.
174 *
175 * Other possible annotations after the time are !H, !N, !P (got a host,
176 * network or protocol unreachable, respectively), !S or !F (source
177 * route failed or fragmentation needed -- neither of these should
178 * ever occur and the associated gateway is busted if you see one). If
179 * almost all the probes result in some kind of unreachable, traceroute
180 * will give up and exit.
181 *
182 * Notes
183 * -----
184 * This program must be run by root or be setuid. (I suggest that
185 * you *don't* make it setuid -- casual use could result in a lot
186 * of unnecessary traffic on our poor, congested nets.)
187 *
188 * This program requires a kernel mod that does not appear in any
189 * system available from Berkeley: A raw ip socket using proto
190 * IPPROTO_RAW must interpret the data sent as an ip datagram (as
191 * opposed to data to be wrapped in a ip datagram). See the README
192 * file that came with the source to this program for a description
193 * of the mods I made to /sys/netinet/raw_ip.c. Your mileage may
194 * vary. But, again, ANY 4.x (x < 4) BSD KERNEL WILL HAVE TO BE
195 * MODIFIED TO RUN THIS PROGRAM.
196 *
197 * The udp port usage may appear bizarre (well, ok, it is bizarre).
198 * The problem is that an icmp message only contains 8 bytes of
199 * data from the original datagram. 8 bytes is the size of a udp
200 * header so, if we want to associate replies with the original
201 * datagram, the necessary information must be encoded into the
202 * udp header (the ip id could be used but there's no way to
203 * interlock with the kernel's assignment of ip id's and, anyway,
204 * it would have taken a lot more kernel hacking to allow this
205 * code to set the ip id). So, to allow two or more users to
206 * use traceroute simultaneously, we use this task's pid as the
207 * source port (the high bit is set to move the port number out
208 * of the "likely" range). To keep track of which probe is being
209 * replied to (so times and/or hop counts don't get confused by a
210 * reply that was delayed in transit), we increment the destination
211 * port number before each probe.
212 *
213 * Don't use this as a coding example. I was trying to find a
214 * routing problem and this code sort-of popped out after 48 hours
215 * without sleep. I was amazed it ever compiled, much less ran.
216 *
217 * I stole the idea for this program from Steve Deering. Since
218 * the first release, I've learned that had I attended the right
219 * IETF working group meetings, I also could have stolen it from Guy
220 * Almes or Matt Mathis. I don't know (or care) who came up with
221 * the idea first. I envy the originators' perspicacity and I'm
222 * glad they didn't keep the idea a secret.
223 *
224 * Tim Seaver, Ken Adelman and C. Philip Wood provided bug fixes and/or
225 * enhancements to the original distribution.
226 *
227 * I've hacked up a round-trip-route version of this that works by
228 * sending a loose-source-routed udp datagram through the destination
229 * back to yourself. Unfortunately, SO many gateways botch source
230 * routing, the thing is almost worthless. Maybe one day...
231 *
232 * -- Van Jacobson (van@helios.ee.lbl.gov)
233 * Tue Dec 20 03:50:13 PST 1988
234 */
235
236#include <sys/socket.h>
237#include <sys/sysctl.h>
238#include <sys/time.h>
239#include <sys/uio.h>
240
241#include <netinet/in.h>
242#include <netinet/ip.h>
243#include <netinet/ip6.h>
244#include <netinet/ip_icmp.h>
245#include <netinet/icmp6.h>
246#include <netinet/udp.h>
247
248#include <arpa/inet.h>
249
250#include <err.h>
251#include <errno(*__errno()).h>
252#include <event.h>
253#include <limits.h>
254#include <netdb.h>
255#include <pwd.h>
256#include <stdio.h>
257#include <stdlib.h>
258#include <string.h>
259#include <unistd.h>
260
261#include "traceroute.h"
262
263int32_t sec_perturb;
264int32_t usec_perturb;
265
266u_char packet[512];
267u_char *outpacket; /* last inbound (icmp) packet */
268
269int rcvsock; /* receive (icmp) socket file descriptor */
270int sndsock; /* send (udp) socket file descriptor */
271
272int rcvhlim;
273struct in6_pktinfo *rcvpktinfo;
274
275int datalen; /* How much data */
276
277char *hostname;
278
279u_int16_t srcport;
280
281void usage(void);
282
283#define TRACEROUTE_USER"_traceroute" "_traceroute"
284
285void sock_read(int, short, void *);
286void send_timer(int, short, void *);
287
288struct tr_conf *conf; /* configuration defaults */
289struct tr_result *tr_results;
290struct sockaddr_in from4, to4;
291struct sockaddr_in6 from6, to6;
292struct sockaddr *from, *to;
293struct msghdr rcvmhdr;
294struct event timer_ev;
295int v6flag;
296int *waiting_ttls;
297int last_tos = 0;
298
299int
300main(int argc, char *argv[])
301{
302 int mib[4] = { CTL_NET4, PF_INET2, IPPROTO_IP0, IPCTL_DEFTTL3 };
303 char hbuf[NI_MAXHOST256];
304
305 struct addrinfo hints, *res;
306 struct hostent *hp;
307 struct ip *ip = NULL((void *)0);
308 struct iovec rcviov[2];
309 static u_char *rcvcmsgbuf;
310 struct passwd *pw;
311 struct event sock_ev;
312 struct timeval tv = {0, 0};
313
314 long l;
315 socklen_t len;
316 size_t size;
317
318 int ch;
319 int on = 1;
320 int error;
321 int headerlen; /* How long packet's header is */
322 int i;
323 int packetlen;
324 int rcvcmsglen;
325 int rcvsock4, rcvsock6;
326 int sndsock4, sndsock6;
327 u_int32_t tmprnd;
328 int v4sock_errno, v6sock_errno;
329
330 char *dest;
331 const char *errstr;
332
333 uid_t ouid, uid;
334 gid_t gid;
335
336 /* Cannot pledge due to special setsockopt()s below */
337 if (unveil("/", "r") == -1)
1
Assuming the condition is false
2
Taking false branch
338 err(1, "unveil /");
339 if (unveil(NULL((void *)0), NULL((void *)0)) == -1)
3
Assuming the condition is false
4
Taking false branch
340 err(1, "unveil");
341
342 if ((conf = calloc(1, sizeof(*conf))) == NULL((void *)0))
5
Assuming the condition is false
6
Taking false branch
343 err(1,NULL((void *)0));
344
345 conf->first_ttl = 1;
346 conf->proto = IPPROTO_UDP17;
347 conf->max_ttl = IPDEFTTL64;
348 conf->nprobes = 3;
349 conf->expected_responses = 2; /* icmp + DNS */
350
351 /* start udp dest port # for probe packets */
352 conf->port = 32768+666;
353
354 memset(&rcvmhdr, 0, sizeof(rcvmhdr));
355 memset(&rcviov, 0, sizeof(rcviov));
356
357 rcvsock4 = rcvsock6 = sndsock4 = sndsock6 = -1;
358 v4sock_errno = v6sock_errno = 0;
359
360 conf->waittime = 3 * 1000;
361
362 if ((rcvsock6 = socket(AF_INET624, SOCK_RAW3, IPPROTO_ICMPV658)) == -1)
7
Assuming the condition is true
8
Taking true branch
363 v6sock_errno = errno(*__errno());
364 else if ((sndsock6 = socket(AF_INET624, SOCK_DGRAM2, 0)) == -1)
365 v6sock_errno = errno(*__errno());
366
367 if ((rcvsock4 = socket(AF_INET2, SOCK_RAW3, IPPROTO_ICMP1)) == -1)
9
Assuming the condition is false
10
Taking false branch
368 v4sock_errno = errno(*__errno());
369 else if ((sndsock4 = socket(AF_INET2, SOCK_RAW3, IPPROTO_RAW255)) == -1)
11
Assuming the condition is false
12
Taking false branch
370 v4sock_errno = errno(*__errno());
371
372 /* revoke privs */
373 ouid = getuid();
374 if (ouid == 0 && (pw = getpwnam(TRACEROUTE_USER"_traceroute")) != NULL((void *)0)) {
13
Assuming 'ouid' is not equal to 0
375 uid = pw->pw_uid;
376 gid = pw->pw_gid;
377 } else {
378 uid = getuid();
379 gid = getgid();
380 }
381 if (ouid
13.1
'ouid' is not equal to 0
&& (setgroups(1, &gid) ||
14
Assuming the condition is false
17
Taking false branch
382 setresgid(gid, gid, gid) ||
15
Assuming the condition is false
383 setresuid(uid, uid, uid)))
16
Assuming the condition is false
384 err(1, "unable to revoke privs");
385
386 if (strcmp("traceroute6", __progname) == 0) {
18
Assuming the condition is false
19
Taking false branch
387 v6flag = 1;
388 if (v6sock_errno != 0)
389 errc(5, v6sock_errno, rcvsock6 < 0 ? "socket(ICMPv6)" :
390 "socket(SOCK_DGRAM)");
391 rcvsock = rcvsock6;
392 sndsock = sndsock6;
393 if (rcvsock4 >= 0)
394 close(rcvsock4);
395 if (sndsock4 >= 0)
396 close(sndsock4);
397 } else {
398 if (v4sock_errno
19.1
'v4sock_errno' is equal to 0
!= 0)
20
Taking false branch
399 errc(5, v4sock_errno, rcvsock4 < 0 ? "icmp socket" :
400 "raw socket");
401 rcvsock = rcvsock4;
402 sndsock = sndsock4;
403 if (rcvsock6
20.1
'rcvsock6' is < 0
>= 0)
21
Taking false branch
404 close(rcvsock6);
405 if (sndsock6
21.1
'sndsock6' is < 0
>= 0)
22
Taking false branch
406 close(sndsock6);
407 }
408
409 if (v6flag) {
23
Assuming 'v6flag' is 0
24
Taking false branch
410 mib[1] = PF_INET624;
411 mib[2] = IPPROTO_IPV641;
412 mib[3] = IPV6CTL_DEFHLIM3;
413 /* specify to tell receiving interface */
414 if (setsockopt(rcvsock, IPPROTO_IPV641, IPV6_RECVPKTINFO36, &on,
415 sizeof(on)) == -1)
416 err(1, "setsockopt(IPV6_RECVPKTINFO)");
417
418 /* specify to tell hoplimit field of received IP6 hdr */
419 if (setsockopt(rcvsock, IPPROTO_IPV641, IPV6_RECVHOPLIMIT37, &on,
420 sizeof(on)) == -1)
421 err(1, "setsockopt(IPV6_RECVHOPLIMIT)");
422 }
423
424 size = sizeof(i);
425 if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), &i, &size, NULL((void *)0), 0) == -1)
25
Assuming the condition is false
26
Taking false branch
426 err(1, "sysctl");
427 conf->max_ttl = i;
428
429 while ((ch = getopt(argc, argv, v6flag
26.1
'v6flag' is 0
? "ADdf:Ilm:np:q:Ss:t:w:vV:" :
27
'?' condition is false
28
Assuming the condition is false
29
Loop condition is false. Execution continues on line 574
430 "ADdf:g:Ilm:nP:p:q:Ss:t:V:vw:x")) != -1)
431 switch (ch) {
432 case 'A':
433 conf->Aflag = 1;
434 conf->expected_responses++;
435 break;
436 case 'd':
437 conf->dflag = 1;
438 break;
439 case 'D':
440 conf->dump = 1;
441 break;
442 case 'f':
443 conf->first_ttl = strtonum(optarg, 1, conf->max_ttl,
444 &errstr);
445 if (errstr)
446 errx(1, "min ttl must be 1 to %u.",
447 conf->max_ttl);
448 break;
449 case 'g':
450 if (conf->lsrr >= MAX_LSRR((40 - 4) / 4))
451 errx(1, "too many gateways; max %d", MAX_LSRR((40 - 4) / 4));
452 if (inet_aton(optarg, &conf->gateway[conf->lsrr]) ==
453 0) {
454 hp = gethostbyname(optarg);
455 if (hp == 0)
456 errx(1, "unknown host %s", optarg);
457 memcpy(&conf->gateway[conf->lsrr], hp->h_addrh_addr_list[0],
458 hp->h_length);
459 }
460 if (++conf->lsrr == 1)
461 conf->lsrrlen = 4;
462 conf->lsrrlen += 4;
463 break;
464 case 'I':
465 if (conf->protoset)
466 errx(1, "protocol already set with -P");
467 conf->protoset = 1;
468 conf->proto = IPPROTO_ICMP1;
469 break;
470 case 'l':
471 conf->ttl_flag = 1;
472 break;
473 case 'm':
474 conf->max_ttl = strtonum(optarg, conf->first_ttl,
475 MAXTTL255, &errstr);
476 if (errstr)
477 errx(1, "max ttl must be %u to %u.",
478 conf->first_ttl, MAXTTL255);
479 break;
480 case 'n':
481 conf->nflag = 1;
482 conf->expected_responses--;
483 break;
484 case 'p':
485 conf->port = strtonum(optarg, 1, 65535, &errstr);
486 if (errstr)
487 errx(1, "port must be >0, <65536.");
488 break;
489 case 'P':
490 if (conf->protoset)
491 errx(1, "protocol already set with -I");
492 conf->protoset = 1;
493 conf->proto = strtonum(optarg, 1, IPPROTO_MAX256 - 1,
494 &errstr);
495 if (errstr) {
496 struct protoent *pent;
497
498 pent = getprotobyname(optarg);
499 if (pent)
500 conf->proto = pent->p_proto;
501 else
502 errx(1, "proto must be >=1, or a "
503 "name.");
504 }
505 break;
506 case 'q':
507 conf->nprobes = strtonum(optarg, 1, 1024, &errstr);
508 if (errstr)
509 errx(1, "nprobes must be >0.");
510 break;
511 case 's':
512 /*
513 * set the ip source address of the outbound
514 * probe (e.g., on a multi-homed host).
515 */
516 conf->source = optarg;
517 break;
518 case 'S':
519 conf->sump = 1;
520 break;
521 case 't':
522 if (!map_tos(optarg, &conf->tos)) {
523 if (strlen(optarg) > 1 && optarg[0] == '0' &&
524 optarg[1] == 'x') {
525 char *ep;
526 errno(*__errno()) = 0;
527 ep = NULL((void *)0);
528 l = strtol(optarg, &ep, 16);
529 if (errno(*__errno()) || !*optarg || *ep ||
530 l < 0 || l > 255)
531 errx(1, "illegal tos value %s",
532 optarg);
533 conf->tos = (int)l;
534 } else {
535 conf->tos = strtonum(optarg, 0, 255,
536 &errstr);
537 if (errstr)
538 errx(1, "illegal tos value %s",
539 optarg);
540 }
541 }
542 conf->tflag = 1;
543 last_tos = conf->tos;
544 break;
545 case 'v':
546 conf->verbose = 1;
547 break;
548 case 'V':
549 conf->rtableid = (unsigned int)strtonum(optarg, 0,
550 RT_TABLEID_MAX255, &errstr);
551 if (errstr)
552 errx(1, "rtable value is %s: %s",
553 errstr, optarg);
554 if (setsockopt(sndsock, SOL_SOCKET0xffff, SO_RTABLE0x1021,
555 &conf->rtableid, sizeof(conf->rtableid)) == -1)
556 err(1, "setsockopt SO_RTABLE");
557 if (setsockopt(rcvsock, SOL_SOCKET0xffff, SO_RTABLE0x1021,
558 &conf->rtableid, sizeof(conf->rtableid)) == -1)
559 err(1, "setsockopt SO_RTABLE");
560 break;
561 case 'w':
562 conf->waittime = strtonum(optarg, 1, INT_MAX2147483647, &errstr);
563 if (errstr)
564 errx(1, "wait must be >=1 sec.");
565 conf->waittime *= 1000;
566 break;
567 case 'x':
568 conf->xflag = 1;
569 break;
570 default:
571 usage();
572 }
573
574 if (ouid
29.1
'ouid' is not equal to 0
== 0 && (setgroups(1, &gid) ||
575 setresgid(gid, gid, gid) ||
576 setresuid(uid, uid, uid)))
577 err(1, "unable to revoke privs");
578
579 argc -= optind;
580 argv += optind;
581
582 if (argc < 1 || argc > 2)
30
Assuming 'argc' is >= 1
31
Assuming 'argc' is <= 2
32
Taking false branch
583 usage();
584
585 tr_results = calloc(sizeof(struct tr_result), conf->max_ttl *
586 conf->nprobes);
587 if (tr_results == NULL((void *)0))
33
Assuming 'tr_results' is not equal to NULL
34
Taking false branch
588 err(1, NULL((void *)0));
589
590 waiting_ttls = calloc(sizeof(int), conf->max_ttl);
591 for (i = 0; i < conf->max_ttl; i++)
35
Assuming 'i' is >= field 'max_ttl'
36
Loop condition is false. Execution continues on line 594
592 waiting_ttls[i] = conf->nprobes * conf->expected_responses;
593
594 setvbuf(stdout(&__sF[1]), NULL((void *)0), _IOLBF1, 0);
595
596 conf->ident = (getpid() & 0xffff) | 0x8000;
597 tmprnd = arc4random();
598 sec_perturb = (tmprnd & 0x80000000) ? -(tmprnd & 0x7ff) :
37
Assuming the condition is false
38
'?' condition is false
599 (tmprnd & 0x7ff);
600 usec_perturb = arc4random();
601
602 memset(&to4, 0, sizeof(to4));
603 memset(&to6, 0, sizeof(to6));
604
605 dest = *argv;
606
607 memset(&hints, 0, sizeof(hints));
608 hints.ai_family = v6flag
38.1
'v6flag' is 0
? PF_INET624 : PF_INET2;
39
'?' condition is false
609 hints.ai_socktype = SOCK_RAW3;
610 hints.ai_protocol = 0;
611 hints.ai_flags = AI_CANONNAME2;
612 if ((error = getaddrinfo(dest, NULL((void *)0), &hints, &res)))
40
Assuming 'error' is 0
41
Taking false branch
613 errx(1, "%s", gai_strerror(error));
614
615 switch (res->ai_family) {
42
Control jumps to 'case 24:' at line 620
616 case AF_INET2:
617 to = (struct sockaddr *)&to4;
618 from = (struct sockaddr *)&from4;
619 break;
620 case AF_INET624:
621 to = (struct sockaddr *)&to6;
622 from = (struct sockaddr *)&from6;
623 break;
43
Execution continues on line 629
624 default:
625 errx(1, "unsupported AF: %d", res->ai_family);
626 break;
627 }
628
629 memcpy(to, res->ai_addr, res->ai_addrlen);
630
631 if (!hostname) {
44
Assuming 'hostname' is non-null
45
Taking false branch
632 hostname = res->ai_canonname ? strdup(res->ai_canonname) : dest;
633 if (!hostname)
634 errx(1, "malloc");
635 }
636
637 if (res->ai_next) {
46
Assuming field 'ai_next' is null
47
Taking false branch
638 if (getnameinfo(res->ai_addr, res->ai_addrlen, hbuf,
639 sizeof(hbuf), NULL((void *)0), 0, NI_NUMERICHOST1) != 0)
640 strlcpy(hbuf, "?", sizeof(hbuf));
641 warnx("Warning: %s has multiple "
642 "addresses; using %s", hostname, hbuf);
643 }
644 freeaddrinfo(res);
645
646 if (*++argv) {
48
Assuming the condition is false
49
Taking false branch
647 datalen = strtonum(*argv, 0, INT_MAX2147483647, &errstr);
648 if (errstr)
649 errx(1, "datalen out of range");
650 }
651
652 switch (to->sa_family) {
50
Control jumps to 'case 2:' at line 653
653 case AF_INET2:
654 switch (conf->proto) {
51
Control jumps to 'case 17:' at line 655
655 case IPPROTO_UDP17:
656 headerlen = (sizeof(struct ip) + conf->lsrrlen +
657 sizeof(struct udphdr) + sizeof(struct packetdata));
658 break;
52
Execution continues on line 668
659 case IPPROTO_ICMP1:
660 headerlen = (sizeof(struct ip) + conf->lsrrlen +
661 sizeof(struct icmp) + sizeof(struct packetdata));
662 break;
663 default:
664 headerlen = (sizeof(struct ip) + conf->lsrrlen +
665 sizeof(struct packetdata));
666 }
667
668 if (datalen < 0 || datalen > IP_MAXPACKET65535 - headerlen)
53
Assuming 'datalen' is >= 0
54
Assuming the condition is false
55
Taking false branch
669 errx(1, "packet size must be 0 to %d.",
670 IP_MAXPACKET65535 - headerlen);
671
672 datalen += headerlen;
673
674 if ((outpacket = calloc(1, datalen)) == NULL((void *)0))
56
Assuming the condition is false
57
Taking false branch
675 err(1, "calloc");
676
677 rcviov[0].iov_base = (caddr_t)packet;
678 rcviov[0].iov_len = sizeof(packet);
679 rcvmhdr.msg_name = (caddr_t)&from4;
680 rcvmhdr.msg_namelen = sizeof(from4);
681 rcvmhdr.msg_iov = rcviov;
682 rcvmhdr.msg_iovlen = 1;
683 rcvmhdr.msg_control = NULL((void *)0);
684 rcvmhdr.msg_controllen = 0;
685
686 ip = (struct ip *)outpacket;
687 if (conf->lsrr
57.1
Field 'lsrr' is equal to 0
!= 0) {
58
Taking false branch
688 u_char *p = (u_char *)(ip + 1);
689
690 *p++ = IPOPT_NOP1;
691 *p++ = IPOPT_LSRR131;
692 *p++ = conf->lsrrlen - 1;
693 *p++ = IPOPT_MINOFF4;
694 conf->gateway[conf->lsrr] = to4.sin_addr;
695 for (i = 1; i <= conf->lsrr; i++) {
696 memcpy(p, &conf->gateway[i],
697 sizeof(struct in_addr));
698 p += sizeof(struct in_addr);
699 }
700 ip->ip_dst = conf->gateway[0];
701 } else
702 ip->ip_dst = to4.sin_addr;
703 ip->ip_off = htons(0)(__uint16_t)(__builtin_constant_p(0) ? (__uint16_t)(((__uint16_t
)(0) & 0xffU) << 8 | ((__uint16_t)(0) & 0xff00U
) >> 8) : __swap16md(0))
;
59
'?' condition is true
704 ip->ip_hl = (sizeof(struct ip) + conf->lsrrlen) >> 2;
705 ip->ip_p = conf->proto;
706 ip->ip_v = IPVERSION4;
707 ip->ip_tos = conf->tos;
708
709 if (setsockopt(sndsock, IPPROTO_IP0, IP_HDRINCL2,
60
Assuming the condition is false
61
Taking false branch
710 &on, sizeof(on)) == -1)
711 err(6, "IP_HDRINCL");
712
713 if (conf->source
61.1
Field 'source' is null
) {
62
Taking false branch
714 memset(&from4, 0, sizeof(from4));
715 from4.sin_family = AF_INET2;
716 if (inet_aton(conf->source, &from4.sin_addr) == 0)
717 errx(1, "unknown host %s", conf->source);
718 ip->ip_src = from4.sin_addr;
719 if (ouid != 0 &&
720 (ntohl(from4.sin_addr.s_addr)(__uint32_t)(__builtin_constant_p(from4.sin_addr.s_addr) ? (__uint32_t
)(((__uint32_t)(from4.sin_addr.s_addr) & 0xff) << 24
| ((__uint32_t)(from4.sin_addr.s_addr) & 0xff00) <<
8 | ((__uint32_t)(from4.sin_addr.s_addr) & 0xff0000) >>
8 | ((__uint32_t)(from4.sin_addr.s_addr) & 0xff000000) >>
24) : __swap32md(from4.sin_addr.s_addr))
& 0xff000000U) ==
721 0x7f000000U && (ntohl(to4.sin_addr.s_addr)(__uint32_t)(__builtin_constant_p(to4.sin_addr.s_addr) ? (__uint32_t
)(((__uint32_t)(to4.sin_addr.s_addr) & 0xff) << 24 |
((__uint32_t)(to4.sin_addr.s_addr) & 0xff00) << 8 |
((__uint32_t)(to4.sin_addr.s_addr) & 0xff0000) >> 8
| ((__uint32_t)(to4.sin_addr.s_addr) & 0xff000000) >>
24) : __swap32md(to4.sin_addr.s_addr))
&
722 0xff000000U) != 0x7f000000U)
723 errx(1, "source is on 127/8, destination is"
724 " not");
725 if (ouid && bind(sndsock, (struct sockaddr *)&from4,
726 sizeof(from4)) == -1)
727 err(1, "bind");
728 }
729 packetlen = datalen;
730 break;
63
Execution continues on line 846
731 case AF_INET624:
732 /*
733 * packetlen is the size of the complete IP packet sent and
734 * reported in the first line of output.
735 * For IPv4 this is equal to datalen since we are constructing
736 * a raw packet.
737 * For IPv6 we need to always add the size of the IP6 header
738 * and for UDP packets the size of the UDP header since they
739 * are prepended to the packet by the kernel
740 */
741 packetlen = sizeof(struct ip6_hdr);
742 switch (conf->proto) {
743 case IPPROTO_UDP17:
744 headerlen = sizeof(struct packetdata);
745 packetlen += sizeof(struct udphdr);
746 break;
747 case IPPROTO_ICMP1:
748 headerlen = sizeof(struct icmp6_hdr) +
749 sizeof(struct packetdata);
750 break;
751 default:
752 errx(1, "Unsupported proto: %hhu", conf->proto);
753 break;
754 }
755
756 if (datalen < 0 || datalen > IP_MAXPACKET65535 - headerlen)
757 errx(1, "packet size must be 0 to %d.",
758 IP_MAXPACKET65535 - headerlen);
759
760 datalen += headerlen;
761 packetlen += datalen;
762
763 if ((outpacket = calloc(1, datalen)) == NULL((void *)0))
764 err(1, "calloc");
765
766 /* initialize msghdr for receiving packets */
767 rcviov[0].iov_base = (caddr_t)packet;
768 rcviov[0].iov_len = sizeof(packet);
769 rcvmhdr.msg_name = (caddr_t)&from6;
770 rcvmhdr.msg_namelen = sizeof(from6);
771 rcvmhdr.msg_iov = rcviov;
772 rcvmhdr.msg_iovlen = 1;
773 rcvcmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo))((((unsigned long)(sizeof(struct cmsghdr)) + (sizeof(long) - 1
)) &~(sizeof(long) - 1)) + (((unsigned long)(sizeof(struct
in6_pktinfo)) + (sizeof(long) - 1)) &~(sizeof(long) - 1)
))
+
774 CMSG_SPACE(sizeof(int))((((unsigned long)(sizeof(struct cmsghdr)) + (sizeof(long) - 1
)) &~(sizeof(long) - 1)) + (((unsigned long)(sizeof(int))
+ (sizeof(long) - 1)) &~(sizeof(long) - 1)))
;
775
776 if ((rcvcmsgbuf = malloc(rcvcmsglen)) == NULL((void *)0))
777 errx(1, "malloc");
778 rcvmhdr.msg_control = (caddr_t) rcvcmsgbuf;
779 rcvmhdr.msg_controllen = rcvcmsglen;
780
781 /*
782 * Send UDP or ICMP
783 */
784 if (conf->proto == IPPROTO_ICMP1) {
785 close(sndsock);
786 sndsock = rcvsock;
787 }
788
789 /*
790 * Source selection
791 */
792 memset(&from6, 0, sizeof(from6));
793 if (conf->source) {
794 memset(&hints, 0, sizeof(hints));
795 hints.ai_family = AF_INET624;
796 hints.ai_socktype = SOCK_DGRAM2; /*dummy*/
797 hints.ai_flags = AI_NUMERICHOST4;
798 if ((error = getaddrinfo(conf->source, "0", &hints,
799 &res)))
800 errx(1, "%s: %s", conf->source,
801 gai_strerror(error));
802 memcpy(&from6, res->ai_addr, res->ai_addrlen);
803 freeaddrinfo(res);
804 } else {
805 struct sockaddr_in6 nxt;
806 int dummy;
807
808 nxt = to6;
809 nxt.sin6_port = htons(DUMMY_PORT)(__uint16_t)(__builtin_constant_p(10010) ? (__uint16_t)(((__uint16_t
)(10010) & 0xffU) << 8 | ((__uint16_t)(10010) &
0xff00U) >> 8) : __swap16md(10010))
;
810 if ((dummy = socket(AF_INET624, SOCK_DGRAM2, 0)) == -1)
811 err(1, "socket");
812 if (conf->rtableid > 0 &&
813 setsockopt(dummy, SOL_SOCKET0xffff, SO_RTABLE0x1021,
814 &conf->rtableid, sizeof(conf->rtableid)) == -1)
815 err(1, "setsockopt(SO_RTABLE)");
816 if (connect(dummy, (struct sockaddr *)&nxt,
817 nxt.sin6_len) == -1)
818 err(1, "connect");
819 len = sizeof(from6);
820 if (getsockname(dummy, (struct sockaddr *)&from6,
821 &len) == -1)
822 err(1, "getsockname");
823 close(dummy);
824 }
825
826 from6.sin6_port = htons(0)(__uint16_t)(__builtin_constant_p(0) ? (__uint16_t)(((__uint16_t
)(0) & 0xffU) << 8 | ((__uint16_t)(0) & 0xff00U
) >> 8) : __swap16md(0))
;
827 if (bind(sndsock, (struct sockaddr *)&from6, from6.sin6_len) == -1)
828 err(1, "bind sndsock");
829
830 if (conf->tflag) {
831 if (setsockopt(sndsock, IPPROTO_IPV641, IPV6_TCLASS61,
832 &conf->tos, sizeof(conf->tos)) == -1)
833 err(6, "IPV6_TCLASS");
834 }
835
836 len = sizeof(from6);
837 if (getsockname(sndsock, (struct sockaddr *)&from6, &len) == -1)
838 err(1, "getsockname");
839 srcport = ntohs(from6.sin6_port)(__uint16_t)(__builtin_constant_p(from6.sin6_port) ? (__uint16_t
)(((__uint16_t)(from6.sin6_port) & 0xffU) << 8 | ((
__uint16_t)(from6.sin6_port) & 0xff00U) >> 8) : __swap16md
(from6.sin6_port))
;
840 break;
841 default:
842 errx(1, "unsupported AF: %d", to->sa_family);
843 break;
844 }
845
846 if (conf->dflag
63.1
Field 'dflag' is 0
) {
64
Taking false branch
847 (void) setsockopt(rcvsock, SOL_SOCKET0xffff, SO_DEBUG0x0001,
848 &on, sizeof(on));
849 (void) setsockopt(sndsock, SOL_SOCKET0xffff, SO_DEBUG0x0001,
850 &on, sizeof(on));
851 }
852
853 if (setsockopt(sndsock, SOL_SOCKET0xffff, SO_SNDBUF0x1001,
65
Assuming the condition is false
66
Taking false branch
854 &datalen, sizeof(datalen)) == -1)
855 err(6, "SO_SNDBUF");
856
857 if (conf->nflag
66.1
Field 'nflag' is 0
&& !conf->Aflag) {
858 if (pledge("stdio inet", NULL((void *)0)) == -1)
859 err(1, "pledge");
860 } else {
861 if (pledge("stdio inet dns", NULL((void *)0)) == -1)
67
Assuming the condition is false
68
Taking false branch
862 err(1, "pledge");
863 }
864
865 if (getnameinfo(to, to->sa_len, hbuf,
69
Assuming the condition is false
70
Taking false branch
866 sizeof(hbuf), NULL((void *)0), 0, NI_NUMERICHOST1))
867 strlcpy(hbuf, "(invalid)", sizeof(hbuf));
868 fprintf(stderr(&__sF[2]), "%s to %s (%s)", __progname, hostname, hbuf);
869 if (conf->source
70.1
Field 'source' is null
)
71
Taking false branch
870 fprintf(stderr(&__sF[2]), " from %s", conf->source);
871 fprintf(stderr(&__sF[2]), ", %u hops max, %d byte packets\n", conf->max_ttl,
872 packetlen);
873 (void) fflush(stderr(&__sF[2]));
874
875 if (conf->first_ttl
71.1
Field 'first_ttl' is <= 1
> 1)
72
Taking false branch
876 printf("Skipping %u intermediate hops\n", conf->first_ttl - 1);
877
878 event_init();
879
880 event_set(&sock_ev, rcvsock, EV_READ0x02 | EV_PERSIST0x10, sock_read, NULL((void *)0));
881 event_add(&sock_ev, NULL((void *)0));
882 evtimer_set(&timer_ev, send_timer, &timer_ev)event_set(&timer_ev, -1, 0, send_timer, &timer_ev);
883 evtimer_add(&timer_ev, &tv)event_add(&timer_ev, &tv);
884 event_dispatch();
885}
73
Address of stack memory associated with local variable 'rcviov' is still referred to by the global variable 'rcvmhdr' upon returning to the caller. This will be a dangling reference
886
887void
888usage(void)
889{
890 if (v6flag) {
891 fprintf(stderr(&__sF[2]), "usage: %s "
892 "[-ADdIlnSv] [-f first_hop] [-m max_hop] [-p port]\n"
893 "\t[-q nqueries] [-s sourceaddr] [-t toskeyword] [-V rtable] "
894 "[-w waittime]\n\thost [datalen]\n", __progname);
895 } else {
896 fprintf(stderr(&__sF[2]),
897 "usage: %s [-ADdIlnSvx] [-f first_ttl] [-g gateway_addr] "
898 "[-m max_ttl]\n"
899 "\t[-P proto] [-p port] [-q nqueries] [-s sourceaddr]\n"
900 "\t[-t toskeyword] "
901 "[-V rtable] [-w waittime] host [datalen]\n",
902 __progname);
903 }
904 exit(1);
905}
906
907void
908sock_read(int fd, short events, void *arg)
909{
910 struct ip *ip;
911 struct timeval t2, tv = {0, 0};
912 int pkg_ok, cc, recv_seq, recv_seq_row;
913 char hbuf[NI_MAXHOST256];
914
915 cc = recvmsg(rcvsock, &rcvmhdr, 0);
916
917 if (cc == 0)
918 return;
919
920 evtimer_add(&timer_ev, &tv)event_add(&timer_ev, &tv);
921
922 gettime(&t2);
923
924 pkg_ok = packet_ok(conf, to->sa_family, &rcvmhdr, cc, &recv_seq);
925
926 /* Skip wrong packet */
927 if (pkg_ok == 0)
928 goto out;
929
930 /* skip corrupt sequence number */
931 if (recv_seq < 0 || recv_seq >= conf->max_ttl * conf->nprobes)
932 goto out;
933
934 recv_seq_row = recv_seq / conf->nprobes;
935
936 /* skipping dup */
937 if (tr_results[recv_seq].dup++)
938 goto out;
939
940 switch (to->sa_family) {
941 case AF_INET2:
942 ip = (struct ip *)packet;
943
944 print(conf, from, cc - (ip->ip_hl << 2), inet_ntop(AF_INET2,
945 &ip->ip_dst, hbuf, sizeof(hbuf)), &tr_results[recv_seq]);
946 break;
947 case AF_INET624:
948 print(conf, from, cc, rcvpktinfo ? inet_ntop(AF_INET624,
949 &rcvpktinfo->ipi6_addr, hbuf, sizeof(hbuf)) : "?",
950 &tr_results[recv_seq]);
951 break;
952 default:
953 errx(1, "unsupported AF: %d", to->sa_family);
954 }
955
956 tr_results[recv_seq].t2 = t2;
957 tr_results[recv_seq].resp_ttl = v6flag ? rcvhlim : ip->ip_ttl;
958
959 waiting_ttls[recv_seq_row]--;
960
961 if (pkg_ok == -2) {
962 if ((v6flag && rcvhlim <= 1) ||
963 (!v6flag && ip->ip_ttl <=1))
964 snprintf(tr_results[recv_seq].icmp_code,
965 sizeof(tr_results[recv_seq].icmp_code), "%s", " !");
966 tr_results[recv_seq].got_there++;
967 } else {
968 if (to->sa_family == AF_INET2 && conf->tflag)
969 check_tos(ip, &last_tos, &tr_results[recv_seq]);
970 if (pkg_ok != -1) {
971 icmp_code(to->sa_family, pkg_ok - 1,
972 &tr_results[recv_seq].got_there,
973 &tr_results[recv_seq].unreachable,
974 &tr_results[recv_seq]);
975 }
976 }
977
978 if (cc && ((recv_seq + 1) % conf->nprobes) == 0 &&
979 (conf->xflag || conf->verbose))
980 print_exthdr(packet, cc, &tr_results[recv_seq]);
981 out:
982 catchup_result_rows(tr_results, conf);
983}
984
985void
986send_timer(int fd, short events, void *arg)
987{
988 static int seq;
989 struct timeval tv = {0, 30000}, t1;
990 struct event *ev = arg;
991 int ttl;
992
993 evtimer_add(ev, &tv)event_add(ev, &tv);
994
995 ttl = conf->first_ttl + seq / conf->nprobes;
996 if (ttl <= conf->max_ttl) {
997 gettime(&t1);
998 tr_results[seq].seq = seq;
999 tr_results[seq].row = seq / conf->nprobes;
1000 tr_results[seq].ttl = ttl;
1001 tr_results[seq].t1 = t1;
1002 send_probe(conf, seq, ttl, to);
1003 seq++;
1004 }
1005
1006 catchup_result_rows(tr_results, conf);
1007
1008}