xref: /freebsd/tools/regression/netinet/ipbroadcast/ipbroadcast.c (revision e71fff28550bb0256851835b271acfac4bae59f1)
12b743a9eSBruce M Simpson /*-
22b743a9eSBruce M Simpson  * Copyright (c) 2007 Bruce M. Simpson
32b743a9eSBruce M Simpson  * All rights reserved.
42b743a9eSBruce M Simpson  *
52b743a9eSBruce M Simpson  * Redistribution and use in source and binary forms, with or without
62b743a9eSBruce M Simpson  * modification, are permitted provided that the following conditions
72b743a9eSBruce M Simpson  * are met:
82b743a9eSBruce M Simpson  * 1. Redistributions of source code must retain the above copyright
92b743a9eSBruce M Simpson  *    notice, this list of conditions and the following disclaimer.
102b743a9eSBruce M Simpson  * 2. Redistributions in binary form must reproduce the above copyright
112b743a9eSBruce M Simpson  *    notice, this list of conditions and the following disclaimer in the
122b743a9eSBruce M Simpson  *    documentation and/or other materials provided with the distribution.
132b743a9eSBruce M Simpson  *
142b743a9eSBruce M Simpson  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
152b743a9eSBruce M Simpson  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
162b743a9eSBruce M Simpson  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
172b743a9eSBruce M Simpson  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
182b743a9eSBruce M Simpson  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
192b743a9eSBruce M Simpson  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
202b743a9eSBruce M Simpson  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
212b743a9eSBruce M Simpson  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
222b743a9eSBruce M Simpson  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
232b743a9eSBruce M Simpson  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
242b743a9eSBruce M Simpson  * SUCH DAMAGE.
252b743a9eSBruce M Simpson  */
262b743a9eSBruce M Simpson 
272b743a9eSBruce M Simpson /*
282b743a9eSBruce M Simpson  * Test utility for IPv4 broadcast sockets.
292b743a9eSBruce M Simpson  */
302b743a9eSBruce M Simpson 
312b743a9eSBruce M Simpson #include <sys/param.h>
322b743a9eSBruce M Simpson #include <sys/types.h>
332b743a9eSBruce M Simpson #include <sys/ioctl.h>
342b743a9eSBruce M Simpson #include <sys/socket.h>
352b743a9eSBruce M Simpson 
36f3bb407bSBruce M Simpson #include <net/if.h>
37f3bb407bSBruce M Simpson #include <net/if_dl.h>
382b743a9eSBruce M Simpson #include <netinet/in.h>
392b743a9eSBruce M Simpson #include <arpa/inet.h>
402b743a9eSBruce M Simpson 
412b743a9eSBruce M Simpson #include <signal.h>
422b743a9eSBruce M Simpson #include <stddef.h>
432b743a9eSBruce M Simpson #include <stdio.h>
442b743a9eSBruce M Simpson #include <stdlib.h>
452b743a9eSBruce M Simpson #include <string.h>
462b743a9eSBruce M Simpson #include <time.h>
472b743a9eSBruce M Simpson 
482b743a9eSBruce M Simpson #include <err.h>
492b743a9eSBruce M Simpson #include <errno.h>
502b743a9eSBruce M Simpson #include <getopt.h>
512b743a9eSBruce M Simpson #include <pwd.h>
522b743a9eSBruce M Simpson #include <unistd.h>
532b743a9eSBruce M Simpson #include <netdb.h>
542b743a9eSBruce M Simpson #include <libgen.h>
552b743a9eSBruce M Simpson 
56f3bb407bSBruce M Simpson #ifndef IP_SENDIF
57f3bb407bSBruce M Simpson #define IP_SENDIF	24		/* XXX */
58f3bb407bSBruce M Simpson #endif
59f3bb407bSBruce M Simpson 
60f6c0136cSBruce M Simpson #ifndef IPPROTO_ZEROHOP
61f6c0136cSBruce M Simpson #define IPPROTO_ZEROHOP	114		/* any 0-hop protocol */
62f6c0136cSBruce M Simpson #endif
63f6c0136cSBruce M Simpson 
642b743a9eSBruce M Simpson #define DEFAULT_PORT		6698
652b743a9eSBruce M Simpson #define DEFAULT_PAYLOAD_SIZE	24
66df7babd6SBruce M Simpson #define DEFAULT_TTL		1
67f3bb407bSBruce M Simpson 
68f3bb407bSBruce M Simpson #define MY_CMSG_SIZE				\
69f3bb407bSBruce M Simpson 	CMSG_SPACE(sizeof(struct in_addr)) +	\
70f3bb407bSBruce M Simpson 	CMSG_SPACE(sizeof(struct sockaddr_dl))
712b743a9eSBruce M Simpson 
722b743a9eSBruce M Simpson static char *progname = NULL;
732b743a9eSBruce M Simpson 
742b743a9eSBruce M Simpson static void
usage(void)752b743a9eSBruce M Simpson usage(void)
762b743a9eSBruce M Simpson {
772b743a9eSBruce M Simpson 
782b743a9eSBruce M Simpson 	fprintf(stderr, "IPv4 broadcast test program. Sends a %d byte UDP "
7948451912SBruce M Simpson 	        "datagram to <dest>:<port>.\n\n", DEFAULT_PAYLOAD_SIZE);
8048451912SBruce M Simpson 	fprintf(stderr,
8148451912SBruce M Simpson "usage: %s [-1] [-A laddr] [-b] [-B] [-d] [-i iface] [-l len]\n"
82f6c0136cSBruce M Simpson "                   [-p port] [-R] [-s srcaddr] [-t ttl] <dest>\n",
8348451912SBruce M Simpson 	    progname);
842b743a9eSBruce M Simpson 	fprintf(stderr, "-1: Set IP_ONESBCAST\n");
8548451912SBruce M Simpson 	fprintf(stderr, "-A: specify laddr (default: INADDR_ANY)\n");
8648451912SBruce M Simpson 	fprintf(stderr, "-b: bind socket to <laddr>:<lport>\n");
872b743a9eSBruce M Simpson 	fprintf(stderr, "-B: Set SO_BROADCAST\n");
882b743a9eSBruce M Simpson 	fprintf(stderr, "-d: Set SO_DONTROUTE\n");
8948451912SBruce M Simpson 	fprintf(stderr, "-i: Set IP_SENDIF <iface> (if supported)\n");
902b743a9eSBruce M Simpson 	fprintf(stderr, "-l: Set payload size to <len>\n");
9148451912SBruce M Simpson 	fprintf(stderr, "-p: Set local and remote port (default: %d)\n",
922b743a9eSBruce M Simpson 	    DEFAULT_PORT);
93f6c0136cSBruce M Simpson 	fprintf(stderr, "-R: Use raw IP (protocol %d)\n", IPPROTO_ZEROHOP);
94df7babd6SBruce M Simpson 	fprintf(stderr, "-s: Set IP_SENDSRCADDR to <srcaddr>\n");
95df7babd6SBruce M Simpson 	fprintf(stderr, "-t: Set IP_TTL to <ttl>\n");
962b743a9eSBruce M Simpson 
972b743a9eSBruce M Simpson 	exit(EXIT_FAILURE);
982b743a9eSBruce M Simpson }
992b743a9eSBruce M Simpson 
1002b743a9eSBruce M Simpson int
main(int argc,char * argv[])1012b743a9eSBruce M Simpson main(int argc, char *argv[])
1022b743a9eSBruce M Simpson {
1032b743a9eSBruce M Simpson 	char			*buf;
1042b743a9eSBruce M Simpson 	char			 cmsgbuf[MY_CMSG_SIZE];
1052b743a9eSBruce M Simpson 	struct iovec		 iov[1];
1062b743a9eSBruce M Simpson 	struct msghdr		 msg;
1072b743a9eSBruce M Simpson 	struct sockaddr_in	 dsin;
10848451912SBruce M Simpson 	struct sockaddr_in	 laddr;
1092b743a9eSBruce M Simpson 	struct cmsghdr		*cmsgp;
1102b743a9eSBruce M Simpson 	struct in_addr		 dstaddr;
111f3bb407bSBruce M Simpson 	char			*ifname;
11248451912SBruce M Simpson 	char			*laddr_s;
1132b743a9eSBruce M Simpson 	char			*srcaddr_s;
1142b743a9eSBruce M Simpson 	int			 ch;
1152b743a9eSBruce M Simpson 	int			 dobind;
1162b743a9eSBruce M Simpson 	int			 dobroadcast;
1172b743a9eSBruce M Simpson 	int			 dontroute;
1182b743a9eSBruce M Simpson 	int			 doonesbcast;
119f6c0136cSBruce M Simpson 	int			 dorawip;
1202b743a9eSBruce M Simpson 	size_t			 buflen;
1212b743a9eSBruce M Simpson 	ssize_t			 nbytes;
1222b743a9eSBruce M Simpson 	int			 portno;
1232b743a9eSBruce M Simpson 	int			 ret;
1242b743a9eSBruce M Simpson 	int			 s;
1252b743a9eSBruce M Simpson 	socklen_t		 soptlen;
1262b743a9eSBruce M Simpson 	int			 soptval;
127df7babd6SBruce M Simpson 	int			 ttl;
1282b743a9eSBruce M Simpson 
1292b743a9eSBruce M Simpson 	dobind = 0;
1302b743a9eSBruce M Simpson 	dobroadcast = 0;
1312b743a9eSBruce M Simpson 	dontroute = 0;
1322b743a9eSBruce M Simpson 	doonesbcast = 0;
133f6c0136cSBruce M Simpson 	dorawip = 0;
1342b743a9eSBruce M Simpson 
135f3bb407bSBruce M Simpson 	ifname = NULL;
1362b743a9eSBruce M Simpson 	dstaddr.s_addr = INADDR_ANY;
13748451912SBruce M Simpson 	laddr_s = NULL;
1382b743a9eSBruce M Simpson 	srcaddr_s = NULL;
1392b743a9eSBruce M Simpson 	portno = DEFAULT_PORT;
140df7babd6SBruce M Simpson 	ttl = DEFAULT_TTL;
1412b743a9eSBruce M Simpson 
1422b743a9eSBruce M Simpson 	buf = NULL;
1432b743a9eSBruce M Simpson 	buflen = DEFAULT_PAYLOAD_SIZE;
1442b743a9eSBruce M Simpson 
1452b743a9eSBruce M Simpson 	progname = basename(argv[0]);
146*e71fff28SGleb Smirnoff 	while ((ch = getopt(argc, argv, "1A:bBdi:l:p:Rs:t:")) != -1) {
1472b743a9eSBruce M Simpson 		switch (ch) {
1482b743a9eSBruce M Simpson 		case '1':
1492b743a9eSBruce M Simpson 			doonesbcast = 1;
1502b743a9eSBruce M Simpson 			break;
15148451912SBruce M Simpson 		case 'A':
15248451912SBruce M Simpson 			laddr_s = optarg;
15348451912SBruce M Simpson 			break;
1542b743a9eSBruce M Simpson 		case 'b':
1552b743a9eSBruce M Simpson 			dobind = 1;
1562b743a9eSBruce M Simpson 			break;
1572b743a9eSBruce M Simpson 		case 'B':
1582b743a9eSBruce M Simpson 			dobroadcast = 1;
1592b743a9eSBruce M Simpson 			break;
1602b743a9eSBruce M Simpson 		case 'd':
1612b743a9eSBruce M Simpson 			dontroute = 1;
1622b743a9eSBruce M Simpson 			break;
163f3bb407bSBruce M Simpson 		case 'i':
164f3bb407bSBruce M Simpson 			ifname = optarg;
165f3bb407bSBruce M Simpson 			break;
1662b743a9eSBruce M Simpson 		case 'l':
1672b743a9eSBruce M Simpson 			buflen = atoi(optarg);
1682b743a9eSBruce M Simpson 			break;
1692b743a9eSBruce M Simpson 		case 'p':
1702b743a9eSBruce M Simpson 			portno = atoi(optarg);
1712b743a9eSBruce M Simpson 			break;
172f6c0136cSBruce M Simpson 		case 'R':
173f6c0136cSBruce M Simpson 			dorawip = 1;
174f6c0136cSBruce M Simpson 			break;
1752b743a9eSBruce M Simpson 		case 's':
1762b743a9eSBruce M Simpson 			srcaddr_s = optarg;
1772b743a9eSBruce M Simpson 			break;
178df7babd6SBruce M Simpson 		case 't':
179df7babd6SBruce M Simpson 			ttl = atoi(optarg);
180df7babd6SBruce M Simpson 			break;
1812b743a9eSBruce M Simpson 		default:
1822b743a9eSBruce M Simpson 			usage();
1832b743a9eSBruce M Simpson 			break;
1842b743a9eSBruce M Simpson 		}
1852b743a9eSBruce M Simpson 	}
1862b743a9eSBruce M Simpson 	argc -= optind;
1872b743a9eSBruce M Simpson 	argv += optind;
1882b743a9eSBruce M Simpson 
1892b743a9eSBruce M Simpson 	if (argc != 1)
1902b743a9eSBruce M Simpson 		usage();
1912b743a9eSBruce M Simpson 	if (argv[0] == NULL || inet_aton(argv[0], &dstaddr) == 0)
1922b743a9eSBruce M Simpson 		usage();
193f3bb407bSBruce M Simpson 	/* IP_SENDSRCADDR and IP_SENDIF are mutually exclusive just now. */
194f3bb407bSBruce M Simpson 	if (srcaddr_s != NULL && ifname != NULL)
195f3bb407bSBruce M Simpson 		usage();
196f6c0136cSBruce M Simpson 	if (dorawip) {
197f6c0136cSBruce M Simpson 		if (geteuid() != 0)
198f6c0136cSBruce M Simpson 			fprintf(stderr, "WARNING: not running as root.\n");
199f6c0136cSBruce M Simpson 		s = socket(PF_INET, SOCK_RAW, IPPROTO_ZEROHOP);
200f6c0136cSBruce M Simpson 	} else {
2012b743a9eSBruce M Simpson 		s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
202f6c0136cSBruce M Simpson 	}
2032b743a9eSBruce M Simpson 	if (s == -1) {
2042b743a9eSBruce M Simpson 		perror("socket");
2052b743a9eSBruce M Simpson 		exit(EXIT_FAILURE);
2062b743a9eSBruce M Simpson 	}
2072b743a9eSBruce M Simpson 
2082b743a9eSBruce M Simpson 	if (dontroute) {
2092b743a9eSBruce M Simpson 		soptval = 1;
2102b743a9eSBruce M Simpson 		soptlen = sizeof(soptval);
2112b743a9eSBruce M Simpson 		ret = setsockopt(s, SOL_SOCKET, SO_DONTROUTE, &soptval,
2122b743a9eSBruce M Simpson 		    soptlen);
2132b743a9eSBruce M Simpson 		if (ret == -1) {
2142b743a9eSBruce M Simpson 			perror("setsockopt SO_DONTROUTE");
2152b743a9eSBruce M Simpson 			close(s);
2162b743a9eSBruce M Simpson 			exit(EXIT_FAILURE);
2172b743a9eSBruce M Simpson 		}
2182b743a9eSBruce M Simpson 	}
2192b743a9eSBruce M Simpson 
2202b743a9eSBruce M Simpson 	if (dobroadcast) {
2212b743a9eSBruce M Simpson 		soptval = 1;
2222b743a9eSBruce M Simpson 		soptlen = sizeof(soptval);
2232b743a9eSBruce M Simpson 		ret = setsockopt(s, SOL_SOCKET, SO_BROADCAST, &soptval,
2242b743a9eSBruce M Simpson 		    soptlen);
2252b743a9eSBruce M Simpson 		if (ret == -1) {
2262b743a9eSBruce M Simpson 			perror("setsockopt SO_BROADCAST");
2272b743a9eSBruce M Simpson 			close(s);
2282b743a9eSBruce M Simpson 			exit(EXIT_FAILURE);
2292b743a9eSBruce M Simpson 		}
2302b743a9eSBruce M Simpson 	}
2312b743a9eSBruce M Simpson 
232df7babd6SBruce M Simpson 	soptval = ttl;
233df7babd6SBruce M Simpson 	soptlen = sizeof(soptval);
234df7babd6SBruce M Simpson 	ret = setsockopt(s, IPPROTO_IP, IP_TTL, &soptval, soptlen);
235df7babd6SBruce M Simpson 	if (ret == -1) {
236df7babd6SBruce M Simpson 		perror("setsockopt IPPROTO_IP IP_TTL");
237df7babd6SBruce M Simpson 		close(s);
238df7babd6SBruce M Simpson 		exit(EXIT_FAILURE);
239df7babd6SBruce M Simpson 	}
240df7babd6SBruce M Simpson 
2412b743a9eSBruce M Simpson 	if (doonesbcast) {
2422b743a9eSBruce M Simpson 		soptval = 1;
2432b743a9eSBruce M Simpson 		soptlen = sizeof(soptval);
2442b743a9eSBruce M Simpson 		ret = setsockopt(s, IPPROTO_IP, IP_ONESBCAST, &soptval,
2452b743a9eSBruce M Simpson 		    soptlen);
2462b743a9eSBruce M Simpson 		if (ret == -1) {
2472b743a9eSBruce M Simpson 			perror("setsockopt IP_ONESBCAST");
2482b743a9eSBruce M Simpson 			close(s);
2492b743a9eSBruce M Simpson 			exit(EXIT_FAILURE);
2502b743a9eSBruce M Simpson 		}
2512b743a9eSBruce M Simpson 	}
2522b743a9eSBruce M Simpson 
2532b743a9eSBruce M Simpson 	if (dobind) {
25448451912SBruce M Simpson 		memset(&laddr, 0, sizeof(struct sockaddr_in));
25548451912SBruce M Simpson 		laddr.sin_family = AF_INET;
25648451912SBruce M Simpson 		laddr.sin_len = sizeof(struct sockaddr_in);
25748451912SBruce M Simpson 		if (laddr_s != NULL) {
25848451912SBruce M Simpson 			laddr.sin_addr.s_addr = inet_addr(laddr_s);
25948451912SBruce M Simpson 		} else
26048451912SBruce M Simpson 			laddr.sin_addr.s_addr = INADDR_ANY;
26148451912SBruce M Simpson 		laddr.sin_port = htons(portno);
26248451912SBruce M Simpson 		ret = bind(s, (struct sockaddr *)&laddr, sizeof(laddr));
2632b743a9eSBruce M Simpson 		if (ret == -1) {
2642b743a9eSBruce M Simpson 			perror("bind");
2652b743a9eSBruce M Simpson 			close(s);
2662b743a9eSBruce M Simpson 			exit(EXIT_FAILURE);
2672b743a9eSBruce M Simpson 		}
2682b743a9eSBruce M Simpson 	}
2692b743a9eSBruce M Simpson 
2702b743a9eSBruce M Simpson 	memset(&dsin, 0, sizeof(struct sockaddr_in));
2712b743a9eSBruce M Simpson 	dsin.sin_family = AF_INET;
2722b743a9eSBruce M Simpson 	dsin.sin_len = sizeof(struct sockaddr_in);
2732b743a9eSBruce M Simpson 	dsin.sin_addr.s_addr = dstaddr.s_addr;
2742b743a9eSBruce M Simpson 	dsin.sin_port = htons(portno);
2752b743a9eSBruce M Simpson 
2762b743a9eSBruce M Simpson 	buf = malloc(buflen);
2772b743a9eSBruce M Simpson 	if (buf == NULL) {
2782b743a9eSBruce M Simpson 		perror("malloc");
2792b743a9eSBruce M Simpson 		close(s);
2802b743a9eSBruce M Simpson 		exit(EXIT_FAILURE);
2812b743a9eSBruce M Simpson 	}
2822b743a9eSBruce M Simpson 	memset(iov, 0, sizeof(iov));
2832b743a9eSBruce M Simpson 	iov[0].iov_base = buf;
2842b743a9eSBruce M Simpson 	iov[0].iov_len = buflen;
2852b743a9eSBruce M Simpson 
2862b743a9eSBruce M Simpson 	memset(&msg, 0, sizeof(struct msghdr));
2872b743a9eSBruce M Simpson 	msg.msg_name = &dsin;
2882b743a9eSBruce M Simpson 	msg.msg_namelen = sizeof(dsin);
2892b743a9eSBruce M Simpson 	msg.msg_iov = iov;
2902b743a9eSBruce M Simpson 	msg.msg_iovlen = 1;
2912b743a9eSBruce M Simpson 
292f3bb407bSBruce M Simpson 	/* Assume we fill out a control msg; macros need to see buf ptr */
2932b743a9eSBruce M Simpson 	msg.msg_control = cmsgbuf;
294f3bb407bSBruce M Simpson 	msg.msg_controllen = 0;
295f3bb407bSBruce M Simpson 	memset(cmsgbuf, 0, MY_CMSG_SIZE);
296f3bb407bSBruce M Simpson 
297f3bb407bSBruce M Simpson 	/* IP_SENDSRCADDR and IP_SENDIF are mutually exclusive just now. */
298f3bb407bSBruce M Simpson 	if (srcaddr_s != NULL) {
299f3bb407bSBruce M Simpson 		msg.msg_controllen += CMSG_SPACE(sizeof(struct in_addr));
3002b743a9eSBruce M Simpson 		cmsgp = CMSG_FIRSTHDR(&msg);
3012b743a9eSBruce M Simpson 		cmsgp->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
3022b743a9eSBruce M Simpson 		cmsgp->cmsg_level = IPPROTO_IP;
3032b743a9eSBruce M Simpson 		cmsgp->cmsg_type = IP_SENDSRCADDR;
304*e71fff28SGleb Smirnoff 		memcpy(CMSG_DATA(cmsgp),
305*e71fff28SGleb Smirnoff 		    &(struct in_addr){ inet_addr(srcaddr_s) },
306*e71fff28SGleb Smirnoff 		    sizeof(struct in_addr));
3072b743a9eSBruce M Simpson 	}
3082b743a9eSBruce M Simpson 
309f3bb407bSBruce M Simpson 	if (ifname != NULL) {
310f3bb407bSBruce M Simpson #ifdef IP_SENDIF
311f3bb407bSBruce M Simpson 		msg.msg_controllen += CMSG_SPACE(sizeof(struct sockaddr_dl));
312f3bb407bSBruce M Simpson 		cmsgp = CMSG_FIRSTHDR(&msg);
313f3bb407bSBruce M Simpson 		cmsgp->cmsg_len = CMSG_LEN(sizeof(struct sockaddr_dl));
314f3bb407bSBruce M Simpson 		cmsgp->cmsg_level = IPPROTO_IP;
315f3bb407bSBruce M Simpson 		cmsgp->cmsg_type = IP_SENDIF;
316f3bb407bSBruce M Simpson 
317f3bb407bSBruce M Simpson #ifdef DIAGNOSTIC
318f3bb407bSBruce M Simpson 		fprintf(stderr, "DEBUG: cmsgp->cmsg_len is %d\n",
319f3bb407bSBruce M Simpson 		    cmsgp->cmsg_len);
320f3bb407bSBruce M Simpson #endif
321*e71fff28SGleb Smirnoff 		memcpy(CMSG_DATA(cmsgp), &(struct sockaddr_dl){
322*e71fff28SGleb Smirnoff 		    .sdl_family = AF_LINK,
323*e71fff28SGleb Smirnoff 		    .sdl_len = sizeof(struct sockaddr_dl),
324*e71fff28SGleb Smirnoff 		    .sdl_index = if_nametoindex(ifname) },
325*e71fff28SGleb Smirnoff 		    sizeof(struct sockaddr_dl));
326f3bb407bSBruce M Simpson #ifdef DIAGNOSTIC
327f3bb407bSBruce M Simpson 		fprintf(stderr, "DEBUG: sdl->sdl_family is %d\n",
328f3bb407bSBruce M Simpson 		    sdl->sdl_family);
329f3bb407bSBruce M Simpson 		fprintf(stderr, "DEBUG: sdl->sdl_len is %d\n",
330f3bb407bSBruce M Simpson 		    sdl->sdl_len);
331f3bb407bSBruce M Simpson 		fprintf(stderr, "DEBUG: sdl->sdl_index is %d\n",
332f3bb407bSBruce M Simpson 		    sdl->sdl_index);
333f3bb407bSBruce M Simpson #endif
334f3bb407bSBruce M Simpson #else
335f3bb407bSBruce M Simpson 		fprintf(stderr, "WARNING: IP_SENDIF not supported, ignored.\n");
336f3bb407bSBruce M Simpson #endif
337f3bb407bSBruce M Simpson 	}
338f3bb407bSBruce M Simpson 
339f3bb407bSBruce M Simpson 	if (msg.msg_controllen == 0)
340f3bb407bSBruce M Simpson 		msg.msg_control = NULL;
341f3bb407bSBruce M Simpson 
3422b743a9eSBruce M Simpson 	nbytes = sendmsg(s, &msg, (dontroute ? MSG_DONTROUTE : 0));
3432b743a9eSBruce M Simpson 	if (nbytes == -1) {
3442b743a9eSBruce M Simpson 		perror("sendmsg");
3452b743a9eSBruce M Simpson 		close(s);
3462b743a9eSBruce M Simpson 		exit(EXIT_FAILURE);
3472b743a9eSBruce M Simpson 	}
3482b743a9eSBruce M Simpson 
3492b743a9eSBruce M Simpson 	close(s);
3502b743a9eSBruce M Simpson 
3512b743a9eSBruce M Simpson 	exit(EXIT_SUCCESS);
3522b743a9eSBruce M Simpson }
353