• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

schweikert / fping / 26721634668

31 May 2026 07:01PM UTC coverage: 87.992% (-0.008%) from 88.0%
26721634668

Pull #470

github

web-flow
Merge cb15cc514 into 780ec4674
Pull Request #470: Fix getprotobyname missing on Android preventing use

14 of 16 new or added lines in 2 files covered. (87.5%)

2 existing lines in 1 file now uncovered.

1678 of 1907 relevant lines covered (87.99%)

348.0 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

87.95
/src/socket6.c
1
/*
2
 * fping: fast-ping, file-ping, favorite-ping, funky-ping
3
 *
4
 *   Ping a list of target hosts in a round robin fashion.
5
 *   A better ping overall.
6
 *
7
 * fping website:  http://www.fping.org
8
 *
9
 * Current maintainer of fping: David Schweikert
10
 * Please send suggestions and patches to: david@schweikert.ch
11
 *
12
 *
13
 * Original author:  Roland Schemers  <schemers@stanford.edu>
14
 * IPv6 Support:     Jeroen Massar    <jeroen@unfix.org / jeroen@ipng.nl>
15
 * Improved main loop: David Schweikert <david@schweikert.ch>
16
 * Debian Merge, TOS settings: Tobi Oetiker <tobi@oetiker.ch>
17
 * Bugfixes, byte order & senseful seq.-numbers: Stephan Fuhrmann (stephan.fuhrmann AT 1und1.de)
18
 *
19
 *
20
 * Redistribution and use in source and binary forms are permitted
21
 * provided that the above copyright notice and this paragraph are
22
 * duplicated in all such forms and that any documentation,
23
 * advertising materials, and other materials related to such
24
 * distribution and use acknowledge that the software was developed
25
 * by Stanford University.  The name of the University may not be used
26
 * to endorse or promote products derived from this software without
27
 * specific prior written permission.
28
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
29
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
30
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
31
 */
32

33
#include "config.h"
34
#include "fping.h"
35
#include "flags.h"
36

37
#include <fcntl.h>
38
#include <netdb.h>
39
#include <netinet/in.h>
40
#include <net/if.h>
41
#include <stdio.h>
42
#include <stdlib.h>
43
#include <string.h>
44
#include <sys/socket.h>
45

46
#include <netinet/icmp6.h>
47

48
char* ping_buffer_ipv6 = 0;
49
size_t ping_pkt_size_ipv6;
50

51
/* Interface index for outgoing packets (0 = not set, use routing table) */
52
static int outgoing_iface_idx_ipv6 = 0;
53

54
/* Source address for outgoing packets (used to populate ipi6_addr) */
55
static struct in6_addr outgoing_src_addr_ipv6;
56
static int outgoing_src_addr_set_ipv6 = 0;
57

58
int open_ping_socket_ipv6(int *socktype)
881✔
59
{
60
    int s = -1;
881✔
61
    int p_proto = IPPROTO_ICMPV6;
881✔
62

63
#ifdef USE_GETPROTOBYNAME
64
    {
65
        /* confirm that ICMP6 is available on this machine */
66
        struct protoent* proto = getprotobyname("ipv6-icmp");
881✔
67
        if (proto == NULL) {
881✔
NEW
68
            crash_and_burn("ipv6-icmp: unknown protocol");
×
69
        }
70
        p_proto = proto->p_proto;
881✔
71
    }
72
#endif
73

74
    /* create raw socket for ICMP6 calls (ping) */
75
    *socktype = SOCK_RAW;
881✔
76
    s = socket(AF_INET6, *socktype, p_proto);
881✔
77
    if (s < 0) {
881✔
78
        /* try non-privileged icmp6 (works on Mac OSX without privileges, for example) */
79
        *socktype = SOCK_DGRAM;
12✔
80
        s = socket(AF_INET6, *socktype, p_proto);
12✔
81
        if (s < 0) {
12✔
82
            return -1;
×
83
        }
84
    } else {
85
        /* receive only ICMP6 messages relevant for fping on raw socket */
86
        struct icmp6_filter recv_filter;
87

88
        ICMP6_FILTER_SETBLOCKALL(&recv_filter);
869✔
89
        ICMP6_FILTER_SETPASS(ICMP6_ECHO_REPLY, &recv_filter);
869✔
90
        ICMP6_FILTER_SETPASS(ICMP6_DST_UNREACH, &recv_filter);
869✔
91
        ICMP6_FILTER_SETPASS(ICMP6_PACKET_TOO_BIG, &recv_filter);
869✔
92
        ICMP6_FILTER_SETPASS(ICMP6_TIME_EXCEEDED, &recv_filter);
869✔
93
        ICMP6_FILTER_SETPASS(ICMP6_PARAM_PROB, &recv_filter);
869✔
94

95
        if (setsockopt(s, IPPROTO_ICMPV6, ICMP6_FILTER, &recv_filter, sizeof(recv_filter))) {
869✔
96
            errno_crash_and_burn("cannot set icmp6 message type filter");
×
97
        }
98
    }
99

100
    /* Make sure that we use non-blocking IO */
101
    {
102
        int flags;
103

104
        if ((flags = fcntl(s, F_GETFL, 0)) < 0)
881✔
105
            perror("fcntl");
×
106

107
        if (fcntl(s, F_SETFL, flags | O_NONBLOCK) < 0)
881✔
108
            perror("fcntl");
×
109
    }
110

111
    return s;
881✔
112
}
239✔
113

114
void socket_set_outgoing_iface_ipv6(const char *iface_name)
4✔
115
{
116
    unsigned int idx = if_nametoindex(iface_name);
4✔
117
    if (idx == 0) {
4✔
118
        fprintf(stderr, "fping: unknown interface '%s'\n", iface_name);
×
119
        exit(1);
×
120
    }
121
    outgoing_iface_idx_ipv6 = (int)idx;
4✔
122
}
4✔
123

124
void init_ping_buffer_ipv6(size_t ping_data_size)
392✔
125
{
126
    /* allocate ping buffer */
127
    ping_pkt_size_ipv6 = ping_data_size + sizeof(struct icmp6_hdr);
392✔
128
    ping_buffer_ipv6 = (char*)calloc(1, ping_pkt_size_ipv6);
392✔
129
    if (!ping_buffer_ipv6)
392✔
130
        crash_and_burn("can't malloc ping packet");
×
131
}
392✔
132

133
void socket_set_src_addr_ipv6(int s, struct in6_addr* src_addr, int *ident)
16✔
134
{
135
    struct sockaddr_in6 sa;
136
    socklen_t len = sizeof(sa);
16✔
137

138
    outgoing_src_addr_ipv6 = *src_addr;
16✔
139
    outgoing_src_addr_set_ipv6 = 1;
16✔
140

141
    memset(&sa, 0, sizeof(sa));
16✔
142
    sa.sin6_family = AF_INET6;
16✔
143
    sa.sin6_addr = *src_addr;
16✔
144
    if (bind(s, (struct sockaddr*)&sa, sizeof(sa)) < 0)
16✔
145
        errno_crash_and_burn("cannot bind source address");
2✔
146

147
    if (ident) {
14✔
148
        memset(&sa, 0, len);
12✔
149
        if (getsockname(s, (struct sockaddr *)&sa, &len) < 0)
12✔
150
            errno_crash_and_burn("can't get ICMP6 socket identity");
×
151

152
        if (sa.sin6_port)
12✔
153
            *ident = sa.sin6_port;
12✔
154
    }
155
}
14✔
156

157
int socket_sendto_ping_ipv6(int s, struct sockaddr* saddr, socklen_t saddr_len, uint16_t icmp_seq_nr, uint16_t icmp_id_nr)
123✔
158
{
159
    struct icmp6_hdr* icp;
160
    int n;
161

162
    icp = (struct icmp6_hdr*)ping_buffer_ipv6;
123✔
163
    icp->icmp6_type = ICMP6_ECHO_REQUEST;
123✔
164
    icp->icmp6_code = 0;
123✔
165
    icp->icmp6_seq = htons(icmp_seq_nr);
123✔
166
    icp->icmp6_id = icmp_id_nr;
123✔
167

168
    if (opt_random_data_on) {
123✔
169
        for (n = sizeof(struct icmp6_hdr); n < ping_pkt_size_ipv6; ++n) {
342✔
170
            ping_buffer_ipv6[n] = random() & 0xFF;
336✔
171
        }
172
    }
173

174
    icp->icmp6_cksum = 0; /* The IPv6 stack calculates the checksum for us... */
123✔
175

176
    if (outgoing_iface_idx_ipv6 > 0) {
123✔
177
        struct iovec iov = {
2✔
178
            .iov_base = icp,
179
            .iov_len  = ping_pkt_size_ipv6
180
        };
181

182
        char cmsg_buf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
183
        memset(cmsg_buf, 0, sizeof(cmsg_buf));
2✔
184

185
        struct msghdr msg = {
2✔
186
            .msg_name       = saddr,
187
            .msg_namelen    = saddr_len,
188
            .msg_iov        = &iov,
189
            .msg_iovlen     = 1,
190
            .msg_control    = cmsg_buf,
191
            .msg_controllen = sizeof(cmsg_buf),
192
            .msg_flags      = 0
193
        };
194

195
        struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
2✔
196
        cmsg->cmsg_level = IPPROTO_IPV6;
2✔
197
        cmsg->cmsg_type  = IPV6_PKTINFO;
2✔
198
        cmsg->cmsg_len   = CMSG_LEN(sizeof(struct in6_pktinfo));
2✔
199

200
        struct in6_pktinfo *pktinfo = (struct in6_pktinfo *)CMSG_DATA(cmsg);
2✔
201
        memset(pktinfo, 0, sizeof(*pktinfo));
2✔
202
        pktinfo->ipi6_ifindex = outgoing_iface_idx_ipv6;
2✔
203

204
        if (outgoing_src_addr_set_ipv6) {
2✔
205
            pktinfo->ipi6_addr = outgoing_src_addr_ipv6;
×
206
        }
207

208
        n = sendmsg(s, &msg, 0);
2✔
209
    } else {
210
        n = sendto(s, icp, ping_pkt_size_ipv6, 0, saddr, saddr_len);
121✔
211
    }
212

213
    return n;
123✔
214
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc