4.3BSD/usr/guest/karels/tests/udpsrcrt.c
#include <stdio.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/signal.h>
#include <sys/time.h>
#include <sys/errno.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#define MAXHOPS 10
char srcrt[4 + MAXHOPS * sizeof(struct in_addr)];
struct sockaddr_in dst = { AF_INET };
int nhops;
int sock;
int send();
int sent, recvd;
extern int errno;
char *service = "echo";
struct {
struct timeval t;
int n;
char sbuf[100];
} rbuf, sbuf = { {0}, "Hi there"};
main(argc, argv)
char *argv[];
{
int n, i;
struct hostent *hp;
struct servent *sp;
struct protoent *pp;
char buf[4096];
char *cp = srcrt;
struct sockaddr_in from;
struct in_addr in;
struct timeval now;
int noopt = 0, loose = 0;
argc--, argv++;
while (argc && argv[0][0] == '-') {
switch (argv[0][1]) {
case 'l':
loose++;
break;
case 'n':
noopt++;
break;
default:
goto usage;
}
argc--, argv++;
}
if (argc == 0) {
usage:
fprintf(stderr, "usage: ipsrcrt [ -n ] [ gateway ... ] dest\n");
exit(1);
}
*cp++ = IPOPT_NOP;
if (loose)
*cp++ = IPOPT_LSRR;
else
*cp++ = IPOPT_SSRR;
*cp++ = 3;
*cp++ = IPOPT_MINOFF;
while (argc) {
if (nhops == MAXHOPS) {
fprintf(stderr, "too many hops, limit %d\n", MAXHOPS);
exit(1);
}
if ((in.s_addr = inet_addr(*argv)) != -1)
bcopy((char *)&in, cp, sizeof(struct in_addr));
else {
hp = gethostbyname(*argv);
if (hp == 0) {
fprintf(stderr, "%s: unknown host\n", *argv);
exit(1);
}
bcopy(hp->h_addr, cp, sizeof(struct in_addr));
}
cp += sizeof(struct in_addr);
nhops++;
argc--; argv++;
}
if ((sp = getservbyname(service, "udp")) == 0) {
fprintf(stderr, "%s: unknown service\n", service);
exit(10);
}
dst.sin_port = sp->s_port;
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0) {
perror("socket");
exit(10);
}
if ((pp = getprotobyname("ip")) == 0) {
fprintf(stderr, "ip: unknown protocol\n");
exit(10);
}
srcrt[IPOPT_OLEN + 1] = cp - srcrt - 1; /* -1 is NOP */
/* *cp++ = IPOPT_EOL; */
if (!noopt) {
n = 4 + nhops * sizeof(struct in_addr);
printf("options %d long\n", n);
for (i = 0; i < (n+3)/4; i++)
printf("%x ", ((int *)srcrt)[i]);
printf("\n");
if (setsockopt(sock, pp->p_proto, IP_OPTIONS, srcrt,
4 + nhops * sizeof(struct in_addr)) < 0) {
perror("setsockopt");
exit(10);
}
n = sizeof(buf);
if (getsockopt(sock, pp->p_proto, IP_OPTIONS, buf, &n) < 0)
perror("getsockopt");
else {
printf("options now %d long\n", n);
for (i = 0; i < (n+3)/4; i++)
printf("%x ", ((int *)buf)[i]);
printf("\n");
}
}
bcopy(cp - sizeof(struct in_addr), &dst.sin_addr,
sizeof(struct in_addr));
signal(SIGALRM, send);
send();
for (;;) {
if ((n = recvfrom(sock, &rbuf, sizeof(rbuf), 0, &from,
sizeof(from))) < 0) {
if (errno != EINTR)
perror("recvfrom");
} else {
gettimeofday(&now);
recvd++;
printf("%d bytes from %s: seq=%d. time=", n,
inet_ntoa(from.sin_addr), rbuf.n);
timevalsub(&now, &rbuf.t);
if (now.tv_sec)
printf("%d.%03d sec.\n", now.tv_sec,
now.tv_usec/1000);
else
printf("%d.%d ms\n", now.tv_usec/1000,
now.tv_usec/10000);
}
}
}
send()
{
alarm(1);
sbuf.n = sent++;
gettimeofday(&sbuf.t);
if (sendto(sock, &sbuf, sizeof(sbuf), 0, &dst, sizeof(dst)) < 0)
perror("sendto");
}
timevalsub(t1, t2)
struct timeval *t1, *t2;
{
t1->tv_sec -= t2->tv_sec;
t1->tv_usec -= t2->tv_usec;
timevalfix(t1);
}
timevalfix(t1)
struct timeval *t1;
{
if (t1->tv_usec < 0) {
t1->tv_sec--;
t1->tv_usec += 1000000;
}
while (t1->tv_usec >= 1000000) {
t1->tv_sec++;
t1->tv_usec -= 1000000;
}
}