summaryrefslogtreecommitdiffstats
path: root/tools/regression/netinet/ipbroadcast
diff options
context:
space:
mode:
authorbms <bms@FreeBSD.org>2007-03-08 14:27:24 +0000
committerbms <bms@FreeBSD.org>2007-03-08 14:27:24 +0000
commitd292337f1f6582ce0d7bc3e8b50f98a488d57f15 (patch)
treec83db792a9ab0d636b55b870d7e5f185e2550209 /tools/regression/netinet/ipbroadcast
parentf13438e4575bae4230c329d8eba4b98b94d35c8d (diff)
downloadFreeBSD-src-d292337f1f6582ce0d7bc3e8b50f98a488d57f15.zip
FreeBSD-src-d292337f1f6582ce0d7bc3e8b50f98a488d57f15.tar.gz
Support IP_SENDIF in -CURRENT.
Diffstat (limited to 'tools/regression/netinet/ipbroadcast')
-rw-r--r--tools/regression/netinet/ipbroadcast/ipbroadcast.c78
1 files changed, 68 insertions, 10 deletions
diff --git a/tools/regression/netinet/ipbroadcast/ipbroadcast.c b/tools/regression/netinet/ipbroadcast/ipbroadcast.c
index d27ad13..c1b48d5 100644
--- a/tools/regression/netinet/ipbroadcast/ipbroadcast.c
+++ b/tools/regression/netinet/ipbroadcast/ipbroadcast.c
@@ -36,6 +36,8 @@ __FBSDID("$FreeBSD$");
#include <sys/ioctl.h>
#include <sys/socket.h>
+#include <net/if.h>
+#include <net/if_dl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
@@ -54,10 +56,17 @@ __FBSDID("$FreeBSD$");
#include <netdb.h>
#include <libgen.h>
+#ifndef IP_SENDIF
+#define IP_SENDIF 24 /* XXX */
+#endif
+
#define DEFAULT_PORT 6698
#define DEFAULT_PAYLOAD_SIZE 24
#define DEFAULT_TTL 1
-#define MY_CMSG_SIZE CMSG_SPACE(sizeof(struct in_addr))
+
+#define MY_CMSG_SIZE \
+ CMSG_SPACE(sizeof(struct in_addr)) + \
+ CMSG_SPACE(sizeof(struct sockaddr_dl))
static char *progname = NULL;
@@ -66,8 +75,8 @@ usage(void)
{
fprintf(stderr,
-"usage: %s [-1] [-b] [-B] [-d] [-l len] [-p port] [-r] [-s srcaddr] [-t ttl]\n"
-" <dest>\n",
+"usage: %s [-1] [-b] [-B] [-d] [-i iface] [-l len] [-p port] [-r]\n"
+" [-s srcaddr] [-t ttl] <dest>\n",
progname);
fprintf(stderr, "IPv4 broadcast test program. Sends a %d byte UDP "
"datagram to <dest>:<port>.\n", DEFAULT_PAYLOAD_SIZE);
@@ -75,12 +84,13 @@ usage(void)
fprintf(stderr, "-b: bind socket to INADDR_ANY:<sport>\n");
fprintf(stderr, "-B: Set SO_BROADCAST\n");
fprintf(stderr, "-d: Set SO_DONTROUTE\n");
-#if 0
- fprintf(stderr, "-r: Fill datagram with random bytes\n");
-#endif
+ fprintf(stderr, "-i: Set IP_SENDIF <iface>\n");
fprintf(stderr, "-l: Set payload size to <len>\n");
fprintf(stderr, "-p: Set source and destination port (default: %d)\n",
DEFAULT_PORT);
+#if 0
+ fprintf(stderr, "-r: Fill datagram with random bytes\n");
+#endif
fprintf(stderr, "-s: Set IP_SENDSRCADDR to <srcaddr>\n");
fprintf(stderr, "-t: Set IP_TTL to <ttl>\n");
@@ -95,9 +105,11 @@ main(int argc, char *argv[])
struct iovec iov[1];
struct msghdr msg;
struct sockaddr_in dsin;
+ struct sockaddr_dl *sdl;
struct cmsghdr *cmsgp;
struct in_addr dstaddr;
struct in_addr *srcaddrp;
+ char *ifname;
char *srcaddr_s;
int ch;
int dobind;
@@ -120,6 +132,7 @@ main(int argc, char *argv[])
doonesbcast = 0;
dorandom = 0;
+ ifname = NULL;
dstaddr.s_addr = INADDR_ANY;
srcaddr_s = NULL;
portno = DEFAULT_PORT;
@@ -129,7 +142,7 @@ main(int argc, char *argv[])
buflen = DEFAULT_PAYLOAD_SIZE;
progname = basename(argv[0]);
- while ((ch = getopt(argc, argv, "1bBdl:p:rs:t:")) != -1) {
+ while ((ch = getopt(argc, argv, "1bBdi:l:p:rs:t:")) != -1) {
switch (ch) {
case '1':
doonesbcast = 1;
@@ -143,6 +156,9 @@ main(int argc, char *argv[])
case 'd':
dontroute = 1;
break;
+ case 'i':
+ ifname = optarg;
+ break;
case 'l':
buflen = atoi(optarg);
break;
@@ -170,6 +186,9 @@ main(int argc, char *argv[])
usage();
if (argv[0] == NULL || inet_aton(argv[0], &dstaddr) == 0)
usage();
+ /* IP_SENDSRCADDR and IP_SENDIF are mutually exclusive just now. */
+ if (srcaddr_s != NULL && ifname != NULL)
+ usage();
s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (s == -1) {
perror("socket");
@@ -257,10 +276,14 @@ main(int argc, char *argv[])
msg.msg_iov = iov;
msg.msg_iovlen = 1;
+ /* Assume we fill out a control msg; macros need to see buf ptr */
+ msg.msg_control = cmsgbuf;
+ msg.msg_controllen = 0;
+ memset(cmsgbuf, 0, MY_CMSG_SIZE);
+
+ /* IP_SENDSRCADDR and IP_SENDIF are mutually exclusive just now. */
if (srcaddr_s != NULL) {
- memset(cmsgbuf, 0, MY_CMSG_SIZE);
- msg.msg_control = cmsgbuf;
- msg.msg_controllen = sizeof(cmsgbuf);
+ msg.msg_controllen += CMSG_SPACE(sizeof(struct in_addr));
cmsgp = CMSG_FIRSTHDR(&msg);
cmsgp->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
cmsgp->cmsg_level = IPPROTO_IP;
@@ -269,6 +292,41 @@ main(int argc, char *argv[])
srcaddrp->s_addr = inet_addr(srcaddr_s);
}
+ if (ifname != NULL) {
+#ifdef IP_SENDIF
+ msg.msg_controllen += CMSG_SPACE(sizeof(struct sockaddr_dl));
+ cmsgp = CMSG_FIRSTHDR(&msg);
+ cmsgp->cmsg_len = CMSG_LEN(sizeof(struct sockaddr_dl));
+ cmsgp->cmsg_level = IPPROTO_IP;
+ cmsgp->cmsg_type = IP_SENDIF;
+
+#ifdef DIAGNOSTIC
+ fprintf(stderr, "DEBUG: cmsgp->cmsg_len is %d\n",
+ cmsgp->cmsg_len);
+#endif
+
+ sdl = (struct sockaddr_dl *)CMSG_DATA(cmsgp);
+ memset(sdl, 0, sizeof(struct sockaddr_dl));
+ sdl->sdl_family = AF_LINK;
+ sdl->sdl_len = sizeof(struct sockaddr_dl);
+ sdl->sdl_index = if_nametoindex(ifname);
+
+#ifdef DIAGNOSTIC
+ fprintf(stderr, "DEBUG: sdl->sdl_family is %d\n",
+ sdl->sdl_family);
+ fprintf(stderr, "DEBUG: sdl->sdl_len is %d\n",
+ sdl->sdl_len);
+ fprintf(stderr, "DEBUG: sdl->sdl_index is %d\n",
+ sdl->sdl_index);
+#endif
+#else
+ fprintf(stderr, "WARNING: IP_SENDIF not supported, ignored.\n");
+#endif
+ }
+
+ if (msg.msg_controllen == 0)
+ msg.msg_control = NULL;
+
nbytes = sendmsg(s, &msg, (dontroute ? MSG_DONTROUTE : 0));
if (nbytes == -1) {
perror("sendmsg");
OpenPOWER on IntegriCloud