"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "test/mping.c" between
mrouted-4.3.tar.gz and mrouted-4.4.tar.gz

About: mrouted is an implementation of the DVMRP multicast routing protocol.

mping.c  (mrouted-4.3):mping.c  (mrouted-4.4)
skipping to change at line 22 skipping to change at line 22
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#define _GNU_SOURCE /* For TIMESPEC_TO_TIMEVAL() in GLIBC */
#include <err.h> #include <err.h>
#include <errno.h> #include <errno.h>
#include <ifaddrs.h> #include <ifaddrs.h>
#include <netdb.h> #include <netdb.h>
#include <signal.h> #include <signal.h>
#include <stdlib.h> #include <stdlib.h>
#include <getopt.h> #include <getopt.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <signal.h> #include <signal.h>
#include <time.h>
#include <unistd.h> #include <unistd.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <net/if.h> #include <net/if.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/types.h> #include <sys/types.h>
#ifndef VERSION
#define VERSION "1.6"
#endif
#define dbg(fmt,args...) do { if (debug) printf(fmt "\n", ##args); } while (0)
#define sig(s,c) do { struct sigaction a = {.sa_handler=c};sigaction(s,&a,0);
} while(0)
#define MC_GROUP_DEFAULT "225.1.2.3" #define MC_GROUP_DEFAULT "225.1.2.3"
#define MC_PORT_DEFAULT 4321 #define MC_PORT_DEFAULT 4321
#define MC_TTL_DEFAULT 1 #define MC_TTL_DEFAULT 1
#define RESPONSES_MAX 100 #define RESPONSES_MAX 100
#define MAX_BUF_LEN 1024 #define MAX_BUF_LEN 1024
#define MAX_HOSTNAME_LEN 256 #define MAX_HOSTNAME_LEN 256
#define SENDER 's' #define SENDER 's'
skipping to change at line 68 skipping to change at line 77
unsigned char type; unsigned char type;
unsigned char ttl; unsigned char ttl;
struct in_addr src_host; struct in_addr src_host;
struct in_addr dest_host; struct in_addr dest_host;
unsigned int seq_no; unsigned int seq_no;
pid_t pid; pid_t pid;
struct timeval tv; struct timeval tv;
struct timeval delay;
} mping; } mping;
struct resp {
struct mping pkt;
struct timeval send_time;
} *responses[RESPONSES_MAX];
int empty_response = 0;
/*#define BANDWIDTH 10000.0 */ /* bw in bytes/sec for mping */ /*#define BANDWIDTH 10000.0 */ /* bw in bytes/sec for mping */
#define BANDWIDTH 100.0 /* bw in bytes/sec for mping */ #define BANDWIDTH 100.0 /* bw in bytes/sec for mping */
unsigned int last_pkt_count = 0; /* packets heard in last full second */
unsigned int curr_pkt_count = 0; /* packets heard so far this second */
/* pointer to mping packet buffer */ /* pointer to mping packet buffer */
struct mping *rcvd_pkt; struct mping *rcvd_pkt;
int sd; /* socket descriptor */ int sd; /* socket descriptor */
pid_t pid; /* our process id */ pid_t pid; /* our process id */
struct sockaddr_in mcaddr; struct sockaddr_in mcaddr;
struct ip_mreqn imr; struct ip_mreqn imr;
struct in_addr myaddr; struct in_addr myaddr;
struct timeval start; /* start time for sender */ struct timeval start; /* start time for sender */
/* Cleared by signal handler */
volatile sig_atomic_t running = 1;
/* counters and statistics variables */ /* counters and statistics variables */
int packets_sent = 0; int packets_sent = 0;
int packets_rcvd = 0; int packets_rcvd = 0;
double rtt_total = 0; double rtt_total = 0;
double rtt_max = 0; double rtt_max = 0;
double rtt_min = 999999999.0; double rtt_min = 999999999.0;
/* default command-line arguments */ /* default command-line arguments */
char arg_mcaddr[16] = MC_GROUP_DEFAULT; char arg_mcaddr[16] = MC_GROUP_DEFAULT;
skipping to change at line 123 skipping to change at line 124
int debug = 0; int debug = 0;
int quiet = 0; int quiet = 0;
void init_socket(int ifindex) void init_socket(int ifindex)
{ {
int off = 0; int off = 0;
int on = 1; int on = 1;
/* create a UDP socket */ /* create a UDP socket */
if ((sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) if ((sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
err(1, "receive socket() failed"); err(1, "failed creating UDP socket");
/* set reuse port to on to allow multiple binds per host */ /* set reuse port to on to allow multiple binds per host */
if ((setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) < 0) if ((setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) < 0)
err(1, "setsockopt() failed"); err(1, "Failed enabling SO_REUSEADDR");
if (setsockopt(sd, IPPROTO_IP, IP_MULTICAST_TTL, &arg_ttl, sizeof(arg_ttl )) < 0) if (setsockopt(sd, IPPROTO_IP, IP_MULTICAST_TTL, &arg_ttl, sizeof(arg_ttl )) < 0)
err(1, "Failed setting IP_MULTICAST_TTL"); err(1, "Failed setting IP_MULTICAST_TTL");
if (setsockopt(sd, IPPROTO_IP, IP_MULTICAST_LOOP, &off, sizeof(off)) < 0) if (setsockopt(sd, IPPROTO_IP, IP_MULTICAST_LOOP, &off, sizeof(off)) < 0)
err(1, "Failed disabling IP_MULTICAST_LOOP"); err(1, "Failed disabling IP_MULTICAST_LOOP");
/* construct a multicast address structure */ /* construct a multicast address structure */
mcaddr.sin_family = AF_INET; mcaddr.sin_family = AF_INET;
mcaddr.sin_addr.s_addr = inet_addr(arg_mcaddr); mcaddr.sin_addr.s_addr = inet_addr(arg_mcaddr);
skipping to change at line 150 skipping to change at line 151
/* bind to multicast address to socket */ /* bind to multicast address to socket */
if ((bind(sd, (struct sockaddr *)&mcaddr, sizeof(mcaddr))) < 0) if ((bind(sd, (struct sockaddr *)&mcaddr, sizeof(mcaddr))) < 0)
err(1, "bind() failed"); err(1, "bind() failed");
/* construct a IGMP join request structure */ /* construct a IGMP join request structure */
imr.imr_multiaddr.s_addr = inet_addr(arg_mcaddr); imr.imr_multiaddr.s_addr = inet_addr(arg_mcaddr);
imr.imr_ifindex = ifindex; imr.imr_ifindex = ifindex;
/* send an ADD MEMBERSHIP message via setsockopt */ /* send an ADD MEMBERSHIP message via setsockopt */
if ((setsockopt(sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &imr, sizeof(imr))) < 0) if ((setsockopt(sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &imr, sizeof(imr))) < 0)
err(1, "setsockopt() failed"); err(1, "failed joining group %s on ifindex %d", arg_mcaddr, ifind ex);
if (setsockopt(sd, IPPROTO_IP, IP_MULTICAST_IF, &imr, sizeof(imr))) if (setsockopt(sd, IPPROTO_IP, IP_MULTICAST_IF, &imr, sizeof(imr)))
err(1, "Failed setting IP_MULTICAST_IF %d", ifindex); err(1, "Failed setting IP_MULTICAST_IF %d", ifindex);
} }
static size_t strlencpy(char *dst, const char *src, size_t len) static size_t strlencpy(char *dst, const char *src, size_t len)
{ {
const char *p = src; const char *p = src;
size_t num = len; size_t num = len;
skipping to change at line 212 skipping to change at line 213
if (!(ifa->ifa_flags & IFF_UP)) if (!(ifa->ifa_flags & IFF_UP))
continue; continue;
if (!(ifa->ifa_flags & IFF_RUNNING)) if (!(ifa->ifa_flags & IFF_RUNNING))
continue; continue;
if (!(ifa->ifa_flags & IFF_MULTICAST)) if (!(ifa->ifa_flags & IFF_MULTICAST))
continue; continue;
ifindex = if_nametoindex(ifa->ifa_name); ifindex = if_nametoindex(ifa->ifa_name);
if (debug) dbg("Found iface %s, ifindex %d", ifa->ifa_name, ifindex);
printf("Found iface %s, ifindex %d\n", ifa->ifa_name, if strlencpy(iface, ifa->ifa_name, len);
index);
strncpy(iface, ifa->ifa_name, len);
iface[len] = 0; iface[len] = 0;
break; break;
} }
freeifaddrs(ifaddr); freeifaddrs(ifaddr);
return iface; return iface;
} }
/* The BSD's or SVR4 systems like Solaris don't have /proc/net/route */ /* The BSD's or SVR4 systems like Solaris don't have /proc/net/route */
static char *altdefault(char *iface, size_t len) static char *altdefault(char *iface, size_t len)
skipping to change at line 242 skipping to change at line 242
while (fgets(buf, sizeof(buf), fp)) { while (fgets(buf, sizeof(buf), fp)) {
char *token; char *token;
if (strncmp(buf, "default", 7) && strncmp(buf, "0.0.0.0", 7)) if (strncmp(buf, "default", 7) && strncmp(buf, "0.0.0.0", 7))
continue; continue;
token = strtok(buf, " \t\n"); token = strtok(buf, " \t\n");
while (token) { while (token) {
if (if_nametoindex(token)) { if (if_nametoindex(token)) {
strncpy(iface, token, len); strlencpy(iface, token, len);
pclose(fp); pclose(fp);
return iface; return iface;
} }
token = strtok(NULL, " \t\n"); token = strtok(NULL, " \t\n");
} }
} }
pclose(fp); pclose(fp);
skipping to change at line 295 skipping to change at line 295
if (rc < 10 || !(flags & 1)) /* IFF_UP */ if (rc < 10 || !(flags & 1)) /* IFF_UP */
continue; continue;
if (dest != 0 || mask != 0) if (dest != 0 || mask != 0)
continue; continue;
if (!iface[0] || !strncmp(iface, "tun", 3)) { if (!iface[0] || !strncmp(iface, "tun", 3)) {
if (metric >= best) if (metric >= best)
continue; continue;
strncpy(iface, ifname, len); strlencpy(iface, ifname, len);
iface[len] = 0; iface[len] = 0;
best = metric; best = metric;
found = 1; found = 1;
if (debug) dbg("Found default inteface %s", iface);
printf("Found default intefaces %s\n", iface);
} }
} }
end: end:
fclose(fp); fclose(fp);
if (found) if (found)
return iface; return iface;
fallback: fallback:
return ifany(iface, len); return ifany(iface, len);
} }
/* Find IP address of default outbound LAN interface */ /* Find IP address of default outbound LAN interface */
int ifinfo(char *iface, inet_addr_t *addr, int family) int ifinfo(char *iface, inet_addr_t *addr, int family)
{ {
struct ifaddrs *ifaddr, *ifa;
char ifname[17] = { 0 };
char buf[INET_ADDRSTR_LEN] = { 0 }; char buf[INET_ADDRSTR_LEN] = { 0 };
struct ifaddrs *ifaddr, *ifa;
char ifname[16] = { 0 };
int found = 0;
int rc = -1; int rc = -1;
if (!iface || !iface[0]) if (!iface || !iface[0])
iface = ifdefault(ifname, sizeof(ifname)); iface = ifdefault(ifname, sizeof(ifname));
if (!iface) if (!iface || !iface[0])
return -2; errx(1, "no suitable default interface available");
rc = getifaddrs(&ifaddr); rc = getifaddrs(&ifaddr);
if (rc == -1) if (rc == -1)
return -3; err(1, "failed querying available interfaces");
rc = -1; /* Return -1 if iface with family is not found */ rc = -1; /* Return -1 if iface with family is not found */
for (ifa = ifaddr; ifa; ifa = ifa->ifa_next) { for (ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
if (!ifa->ifa_addr) if (strcmp(iface, ifa->ifa_name))
continue; continue;
if (!(ifa->ifa_flags & IFF_MULTICAST)) found = 1;
if (!(ifa->ifa_flags & IFF_UP)) {
dbg("%s is not UP, skipping ...", iface);
continue;
}
if (!ifa->ifa_addr) {
dbg("%s has no address, skipping ...", iface);
continue; continue;
}
if (family == AF_UNSPEC) { if (family == AF_UNSPEC) {
if (ifa->ifa_addr->sa_family != AF_INET && if (ifa->ifa_addr->sa_family != AF_INET &&
ifa->ifa_addr->sa_family != AF_INET6) ifa->ifa_addr->sa_family != AF_INET6)
dbg("%s no IPv4 or IPv6 address, skipping ...", i face);
continue; continue;
} else if (ifa->ifa_addr->sa_family != family) } else if (ifa->ifa_addr->sa_family != family) {
dbg("%s not matching address family, skipping ...", iface
);
continue; continue;
}
if (iface && strcmp(iface, ifa->ifa_name)) if (!(ifa->ifa_flags & IFF_MULTICAST)) {
continue; warnx("%s is not multicast capable, check interface flags
.", iface);
break;
}
if (debug) dbg("Found %s addr %s", ifa->ifa_name, inet_address((inet_addr_t
printf("Found %s addr %s\n", ifa->ifa_name, *)ifa->ifa_addr, buf, sizeof(buf)));
inet_address((inet_addr_t *)ifa->ifa_addr, buf, s
izeof(buf)));
*addr = *(inet_addr_t *)ifa->ifa_addr; *addr = *(inet_addr_t *)ifa->ifa_addr;
rc = if_nametoindex(ifa->ifa_name); rc = if_nametoindex(ifa->ifa_name);
if (debug) dbg("iface %s, ifindex %d, addr %s", ifa->ifa_name, rc, buf);
printf("iface %s, ifindex %d, addr %s\n", ifa->ifa_name,
rc, buf);
break; break;
} }
freeifaddrs(ifaddr); freeifaddrs(ifaddr);
if (!found)
warnx("no such interface %s.", iface);
return rc; return rc;
} }
/* subtract sub from val and leave result in val */ /* subtract sub from val and leave result in val */
void subtract_timeval(struct timeval *val, const struct timeval *sub) void subtract_timeval(struct timeval *val, const struct timeval *sub)
{ {
val->tv_sec -= sub->tv_sec; val->tv_sec -= sub->tv_sec;
val->tv_usec -= sub->tv_usec; val->tv_usec -= sub->tv_usec;
if (val->tv_usec < 0) { if (val->tv_usec < 0) {
val->tv_sec--; val->tv_sec--;
val->tv_usec += 1000000; val->tv_usec += 1000000;
} }
} }
/* return the timeval converted to a number of milliseconds */ /* return the timeval converted to a number of milliseconds */
double timeval_to_ms(const struct timeval *val) double timeval_to_ms(const struct timeval *val)
{ {
return val->tv_sec * 1000.0 + val->tv_usec / 1000.0; return val->tv_sec * 1000.0 + val->tv_usec / 1000.0;
} }
static void clean_exit(int signo) static int cleanup(void)
{ {
(void)signo;
if ((setsockopt(sd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &imr, sizeof(imr))) < 0) if ((setsockopt(sd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &imr, sizeof(imr))) < 0)
err(1, "setsockopt() failed"); err(1, "setsockopt() failed");
close(sd); close(sd);
printf("\n--- %s mping statistics ---\n", arg_mcaddr); printf("\n--- %s mping statistics ---\n", arg_mcaddr);
printf("%d packets transmitted, %d packets received\n", packets_sent, pac kets_rcvd); printf("%d packets transmitted, %d packets received\n", packets_sent, pac kets_rcvd);
if (packets_rcvd == 0) if (packets_rcvd == 0)
printf("round-trip min/avg/max = NA/NA/NA ms\n"); printf("round-trip min/avg/max = NA/NA/NA ms\n");
else else
printf("round-trip min/avg/max = %.3f/%.3f/%.3f ms\n", printf("round-trip min/avg/max = %.3f/%.3f/%.3f ms\n",
rtt_min, (rtt_total / packets_rcvd), rtt_max); rtt_min, (rtt_total / packets_rcvd), rtt_max);
if (arg_count > 0 && arg_count > packets_rcvd) if (arg_count > 0 && arg_count > packets_rcvd)
exit(1); return 1;
exit(0);
return 0;
}
static void clean_exit(int signo)
{
(void)signo;
running = 0;
} }
void send_packet(struct mping *packet) void send_packet(struct mping *packet)
{ {
int pkt_len = sizeof(struct mping); int pkt_len = sizeof(struct mping);
if ((sendto(sd, packet, pkt_len, 0, (struct sockaddr *)&mcaddr, sizeof(mc addr))) != pkt_len) if ((sendto(sd, packet, pkt_len, 0, (struct sockaddr *)&mcaddr, sizeof(mc addr))) != pkt_len)
err(1, "sendto() sent incorrect number of bytes"); err(1, "sendto() sent incorrect number of bytes");
packets_sent++; packets_sent++;
} }
void send_mping(int signo) void send_mping(int signo)
{ {
static int seqno = 0; static int seqno = 0;
struct timeval now; struct timespec now;
(void)signo; (void)signo;
clock_gettime(CLOCK_MONOTONIC, &now);
/* /*
* Tracks number of sent mpings. If deadline mode is enabled we * Tracks number of sent mpings. If deadline mode is enabled we
* ignore this exit and wait for arg_count number of replies or * ignore this exit and wait for arg_count number of replies or
* deadline timeout. * deadline timeout.
*/ */
if (arg_deadline) { if (arg_deadline) {
if (arg_count > 0 && packets_rcvd >= arg_count) struct timeval tv;
clean_exit(0);
TIMESPEC_TO_TIMEVAL(&tv, &now);
subtract_timeval(&tv, &start);
gettimeofday(&now, NULL); if ((arg_count > 0 && packets_rcvd >= arg_count) ||
subtract_timeval(&now, &start); (tv.tv_sec >= arg_deadline)) {
if (now.tv_sec >= arg_deadline) running = 0;
clean_exit(0); return;
}
} else if (arg_count > 0 && seqno >= arg_count) { } else if (arg_count > 0 && seqno >= arg_count) {
/* set another alarm call to exit in 5 second */ sig(SIGALRM, clean_exit);
signal(SIGALRM, clean_exit);
alarm(arg_timeout); alarm(arg_timeout);
return; return;
} }
gettimeofday(&now, NULL); TIMESPEC_TO_TIMEVAL(&mping.tv, &now);
strlencpy(mping.version, VERSION, sizeof(mping.version)); strlencpy(mping.version, VERSION, sizeof(mping.version));
mping.type = SENDER; mping.type = SENDER;
mping.ttl = arg_ttl; mping.ttl = arg_ttl;
mping.src_host.s_addr = myaddr.s_addr; mping.src_host = myaddr;
mping.dest_host.s_addr = inet_addr(arg_mcaddr); mping.dest_host = mcaddr.sin_addr;
mping.seq_no = htonl(seqno); mping.seq_no = htonl(seqno);
mping.pid = pid; mping.pid = pid;
mping.tv.tv_sec = htonl(now.tv_sec); mping.tv.tv_sec = htonl(mping.tv.tv_sec);
mping.tv.tv_usec = htonl(now.tv_usec); mping.tv.tv_usec = htonl(mping.tv.tv_usec);
mping.delay.tv_sec = 0;
mping.delay.tv_usec = 0;
send_packet(&mping); send_packet(&mping);
seqno++; seqno++;
/* set another alarm call to send in 1 second */ /* set another alarm call to send in 1 second */
signal(SIGALRM, send_mping); sig(SIGALRM, send_mping);
alarm(1); alarm(1);
} }
int process_mping(char *packet, int len, unsigned char type) int process_mping(char *packet, int len, unsigned char type)
{ {
if (len < (int)sizeof(struct mping)) { if (len < (int)sizeof(struct mping)) {
if (debug) dbg("Discarding packet: too small (%zu bytes)", strlen(packet));
printf("Discarding packet: too small (%zu bytes)\n", strl
en(packet));
return -1; return -1;
} }
rcvd_pkt = (struct mping *)packet; rcvd_pkt = (struct mping *)packet;
rcvd_pkt->seq_no = ntohl(rcvd_pkt->seq_no); rcvd_pkt->seq_no = ntohl(rcvd_pkt->seq_no);
rcvd_pkt->tv.tv_sec = ntohl(rcvd_pkt->tv.tv_sec); rcvd_pkt->tv.tv_sec = ntohl(rcvd_pkt->tv.tv_sec);
rcvd_pkt->tv.tv_usec = ntohl(rcvd_pkt->tv.tv_usec); rcvd_pkt->tv.tv_usec = ntohl(rcvd_pkt->tv.tv_usec);
rcvd_pkt->delay.tv_sec = ntohl(rcvd_pkt->delay.tv_sec);
rcvd_pkt->delay.tv_usec = ntohl(rcvd_pkt->delay.tv_usec);
if (strcmp(rcvd_pkt->version, VERSION)) { if (strcmp(rcvd_pkt->version, VERSION)) {
if (debug) dbg("Discarding packet: version mismatch (%s)", rcvd_pkt->version
printf("Discarding packet: version mismatch (%s)\n", rcvd );
_pkt->version);
return -1; return -1;
} }
curr_pkt_count++;
if (rcvd_pkt->type != type) { if (rcvd_pkt->type != type) {
if (debug) { if (debug) {
switch (rcvd_pkt->type) { switch (rcvd_pkt->type) {
case SENDER: case SENDER:
printf("Discarding sender packet\n"); printf("Discarding sender packet\n");
break; break;
case RECEIVER: case RECEIVER:
printf("Discarding receiver packet\n"); printf("Discarding receiver packet\n");
break; break;
skipping to change at line 505 skipping to change at line 517
printf("Discarding packet: unknown type(%c)\n", r cvd_pkt->type); printf("Discarding packet: unknown type(%c)\n", r cvd_pkt->type);
break; break;
} }
} }
return -1; return -1;
} }
if (rcvd_pkt->type == RECEIVER) { if (rcvd_pkt->type == RECEIVER) {
if (rcvd_pkt->pid != pid) { if (rcvd_pkt->pid != pid) {
if (debug) dbg("Discarding packet: pid mismatch (%u/%u)", pid, rcvd_
printf("Discarding packet: pid mismatch (%u/%u)\n pkt->pid);
", pid, rcvd_pkt->pid);
return -1; return -1;
} }
} }
packets_rcvd++; packets_rcvd++;
return 0; return 0;
} }
void sender_listen_loop() void sender_listen_loop(void)
{ {
while (1) { send_mping(0);
while (running) {
char recv_packet[MAX_BUF_LEN + 1] = { 0 }; char recv_packet[MAX_BUF_LEN + 1] = { 0 };
int len; int len;
if ((len = recvfrom(sd, recv_packet, MAX_BUF_LEN, 0, NULL, 0)) < 0) { if ((len = recvfrom(sd, recv_packet, MAX_BUF_LEN, 0, NULL, 0)) < 0) {
if (errno == EINTR) if (errno == EINTR)
continue; /* interrupt is ok */ continue; /* interrupt is ok */
err(1, "recvfrom() failed"); err(1, "recvfrom() failed");
} }
if (process_mping(recv_packet, len, RECEIVER) == 0) { if (process_mping(recv_packet, len, RECEIVER) == 0) {
struct timeval now; struct timespec now;
double actual_rtt; /* rtt - send interval delay */ struct timeval tv;
double rtt; /* round trip time */ double rtt; /* round trip time */
gettimeofday(&now, NULL); clock_gettime(CLOCK_MONOTONIC, &now);
TIMESPEC_TO_TIMEVAL(&tv, &now);
/* calculate round trip time in milliseconds */ /* calculate round trip time in milliseconds */
subtract_timeval(&now, &rcvd_pkt->tv); subtract_timeval(&tv, &rcvd_pkt->tv);
rtt = timeval_to_ms(&now); rtt = timeval_to_ms(&tv);
/* remove the backoff delay to determine actual rtt */
subtract_timeval(&now, &rcvd_pkt->delay);
actual_rtt = timeval_to_ms(&now);
/* keep rtt total, min and max */ /* keep rtt total, min and max */
rtt_total += actual_rtt; rtt_total += rtt;
if (actual_rtt > rtt_max) if (rtt > rtt_max)
rtt_max = actual_rtt; rtt_max = rtt;
if (actual_rtt < rtt_min) if (rtt < rtt_min)
rtt_min = actual_rtt; rtt_min = rtt;
/* output received packet information */ /* output received packet information */
if (!quiet) { if (!quiet) {
printf("%d bytes from %s: seqno=%u ttl=%d ", printf("%d bytes from %s: seqno=%u ttl=%d time=% .1f ms\n",
len, inet_ntoa(rcvd_pkt->src_host), len, inet_ntoa(rcvd_pkt->src_host),
rcvd_pkt->seq_no, rcvd_pkt->ttl); rcvd_pkt->seq_no, rcvd_pkt->ttl, rtt);
printf("etime=%.1f ms atime=%.3f ms\n", rtt, act
ual_rtt);
} }
} }
} }
} }
void check_send(int i) void receiver_listen_loop(void)
{
struct timeval now;
gettimeofday(&now, NULL);
if ((responses[i]->send_time.tv_sec < now.tv_sec) ||
((responses[i]->send_time.tv_sec == now.tv_sec) &&
(responses[i]->send_time.tv_usec <= now.tv_usec))) {
size_t len = sizeof(responses[i]->pkt);
if (!quiet)
printf("Reply to mping from %s bytes=%zu seqno=%u ttl=%d
\n",
inet_ntoa(responses[i]->pkt.dest_host), len,
ntohl(responses[i]->pkt.seq_no), responses[i]->pk
t.ttl);
subtract_timeval(&now, &responses[i]->pkt.delay);
responses[i]->pkt.delay.tv_sec = htonl(now.tv_sec);
responses[i]->pkt.delay.tv_usec = htonl(now.tv_usec);
send_packet(&responses[i]->pkt);
free(responses[i]);
responses[i] = NULL;
}
}
void received_packet_count(int signo)
{
(void)signo;
/* update the packet count for the last full second */
last_pkt_count = curr_pkt_count;
curr_pkt_count = 0;
/* check if the packets in the send buffer are ready to send */
for (int i = empty_response; i < RESPONSES_MAX; i++) {
if (responses[i] != NULL)
check_send(i);
}
if (empty_response != 0) {
for (int i = 0; i < empty_response; i++) {
if (responses[i] != NULL)
check_send(i);
}
}
if (arg_count > 0 && packets_sent >= arg_count)
exit(0);
signal(SIGALRM, received_packet_count);
alarm(1);
}
void receiver_listen_loop()
{ {
printf("Listening on %s:%d\n", arg_mcaddr, arg_mcport); printf("Listening on %s:%d\n", arg_mcaddr, arg_mcport);
while (1) { while (running) {
char recv_packet[MAX_BUF_LEN + 1]; char recv_packet[MAX_BUF_LEN + 1];
int len; int len;
if ((len = recvfrom(sd, recv_packet, MAX_BUF_LEN, 0, NULL, 0)) < 0) { if ((len = recvfrom(sd, recv_packet, MAX_BUF_LEN, 0, NULL, 0)) < 0) {
if (errno == EINTR) if (errno == EINTR)
continue; /* interrupt is ok */ continue; /* interrupt is ok */
err(1, "recvfrom() failed"); err(1, "recvfrom() failed");
} }
if (process_mping(recv_packet, len, SENDER) == 0) { if (process_mping(recv_packet, len, SENDER) == 0) {
int i;
if (!quiet) if (!quiet)
printf("Received mping from %s bytes=%d seqno=%u ttl=%d\n", printf("Received mping from %s bytes=%d seqno=%u ttl=%d\n",
inet_ntoa(rcvd_pkt->src_host), len, inet_ntoa(rcvd_pkt->src_host), len,
rcvd_pkt->seq_no, rcvd_pkt->ttl); rcvd_pkt->seq_no, rcvd_pkt->ttl);
i = empty_response; rcvd_pkt->type = RECEIVER;
if (responses[i] != NULL) { rcvd_pkt->src_host = myaddr;
if (debug) rcvd_pkt->dest_host = rcvd_pkt->src_host;
printf("Buffer full, packet dropped\n"); rcvd_pkt->seq_no = htonl(rcvd_pkt->seq_no);
continue; rcvd_pkt->tv.tv_sec = htonl(rcvd_pkt->tv.tv_sec);
} rcvd_pkt->tv.tv_usec = htonl(rcvd_pkt->tv.tv_usec);
responses[i] = (struct resp *)malloc(sizeof(struct resp))
;
if (responses[i] == NULL)
err(1, "Failed allocating response %d", i);
strlencpy(responses[i]->pkt.version, VERSION, sizeof(resp
onses[i]->pkt.version));
responses[i]->pkt.type = RECEIVER;
responses[i]->pkt.ttl = rcvd_pkt->ttl;
responses[i]->pkt.src_host.s_addr = myaddr.s_addr;
responses[i]->pkt.dest_host.s_addr = rcvd_pkt->src_host.s
_addr;
responses[i]->pkt.seq_no = htonl(rcvd_pkt->seq_
no);
responses[i]->pkt.pid = rcvd_pkt->pid;
responses[i]->pkt.tv.tv_sec = htonl(rcvd_pkt->tv.t
v_sec);
responses[i]->pkt.tv.tv_usec = htonl(rcvd_pkt->tv.t
v_usec);
gettimeofday(&responses[i]->send_time, NULL);
responses[i]->pkt.delay = responses[i]->send_time;
/* send reply immediately */ /* send reply immediately */
received_packet_count(0); send_packet(rcvd_pkt);
/* increment response buffer pointer */ if (arg_count > 0 && packets_sent >= arg_count)
empty_response++; exit(0);
if (empty_response >= RESPONSES_MAX)
empty_response = 0;
} }
} }
} }
int usage(void) int usage(void)
{ {
fprintf(stderr, fprintf(stderr,
"Usage:\n" "Usage:\n"
" mping [-dhqrsv] [-c COUNT] [-i IFNAME] [-p PORT] [-t TTL] [-w SEC] [-W SEC] [GROUP]\n" " mping [-dhqrsv] [-c COUNT] [-i IFNAME] [-p PORT] [-t TTL] [-w SEC] [-W SEC] [GROUP]\n"
"\n" "\n"
skipping to change at line 706 skipping to change at line 640
return 0; return 0;
} }
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
char *iface = NULL; char *iface = NULL;
inet_addr_t addr; inet_addr_t addr;
char ifname[16]; char ifname[16];
int mode = 'r'; int mode = 'r';
int ifindex;
int c; int c;
while ((c = getopt(argc, argv, "c:dh?i:p:qrst:vW:w:")) != -1) { while ((c = getopt(argc, argv, "c:dh?i:p:qrst:vW:w:")) != -1) {
switch (c) { switch (c) {
case 'c': case 'c':
arg_count = atoi(optarg); arg_count = atoi(optarg);
break; break;
case 'd': case 'd':
debug = 1; debug = 1;
skipping to change at line 750 skipping to change at line 685
arg_ttl = atoi(optarg); arg_ttl = atoi(optarg);
break; break;
case 'v': case 'v':
printf("mping version %s\n" printf("mping version %s\n"
"\n" "\n"
"Bug report address: https://github.com/troglobit /mping/issues\n" "Bug report address: https://github.com/troglobit /mping/issues\n"
"Project homepage: https://github.com/troglobit /mping/\n", VERSION); "Project homepage: https://github.com/troglobit /mping/\n", VERSION);
return 0; return 0;
case 'W':
arg_timeout = atoi(optarg);
break;
case 'w': case 'w':
arg_deadline = atoi(optarg); arg_deadline = atoi(optarg);
break; break;
case 'W':
arg_timeout = atoi(optarg);
break;
case '?': case '?':
case 'h': case 'h':
default: default:
return usage(); return usage();
} }
} }
if (optind < argc) if (optind < argc)
strlencpy(arg_mcaddr, argv[optind], sizeof(arg_mcaddr)); strlencpy(arg_mcaddr, argv[optind], sizeof(arg_mcaddr));
pid = getpid(); pid = getpid();
init_socket(ifinfo(iface, &addr, AF_INET)); ifindex = ifinfo(iface, &addr, AF_INET);
if (ifindex <= 0)
exit(1);
init_socket(ifindex);
if (addr.ss_family == AF_INET) { if (addr.ss_family == AF_INET) {
struct sockaddr_in *sin = (struct sockaddr_in *)&addr; struct sockaddr_in *sin = (struct sockaddr_in *)&addr;
myaddr = sin->sin_addr; myaddr = sin->sin_addr;
} }
if (mode == 's') { if (mode == 's') {
gettimeofday(&start, NULL); struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
TIMESPEC_TO_TIMEVAL(&start, &now);
printf("MPING %s:%d (ttl %d)\n", arg_mcaddr, arg_mcport, arg_ttl) ; printf("MPING %s:%d (ttl %d)\n", arg_mcaddr, arg_mcport, arg_ttl) ;
signal(SIGINT, clean_exit); sig(SIGINT, clean_exit);
signal(SIGALRM, send_mping); sig(SIGALRM, send_mping);
send_mping(SIGALRM);
sender_listen_loop(); sender_listen_loop();
} else { } else
for (int i = 0; i < RESPONSES_MAX; i++)
responses[i] = NULL;
signal(SIGALRM, received_packet_count);
alarm(1);
receiver_listen_loop(); receiver_listen_loop();
}
return 0; return cleanup();
} }
/** /**
* Local Variables: * Local Variables:
* indent-tabs-mode: t * indent-tabs-mode: t
* c-file-style: "linux" * c-file-style: "linux"
* End: * End:
*/ */
 End of changes. 67 change blocks. 
211 lines changed or deleted 136 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)