xref: /freebsd-src/tools/regression/netinet/ipbroadcast/ipbroadcast.c (revision 6bfca4dcab07dad45a805879d954876b353c0810)
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 
60*f6c0136cSBruce M Simpson #ifndef IPPROTO_ZEROHOP
61*f6c0136cSBruce M Simpson #define IPPROTO_ZEROHOP	114		/* any 0-hop protocol */
62*f6c0136cSBruce M Simpson #endif
63*f6c0136cSBruce 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"
82*f6c0136cSBruce 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);
93*f6c0136cSBruce M Simpson 	fprintf(stderr, "-R: Use raw IP (protocol %d)\n", IPPROTO_ZEROHOP);
94f3bb407bSBruce M Simpson #if 0
95f3bb407bSBruce M Simpson 	fprintf(stderr, "-r: Fill datagram with random bytes\n");
96f3bb407bSBruce M Simpson #endif
97df7babd6SBruce M Simpson 	fprintf(stderr, "-s: Set IP_SENDSRCADDR to <srcaddr>\n");
98df7babd6SBruce M Simpson 	fprintf(stderr, "-t: Set IP_TTL to <ttl>\n");
992b743a9eSBruce M Simpson 
1002b743a9eSBruce M Simpson 	exit(EXIT_FAILURE);
1012b743a9eSBruce M Simpson }
1022b743a9eSBruce M Simpson 
1032b743a9eSBruce M Simpson int
main(int argc,char * argv[])1042b743a9eSBruce M Simpson main(int argc, char *argv[])
1052b743a9eSBruce M Simpson {
1062b743a9eSBruce M Simpson 	char			*buf;
1072b743a9eSBruce M Simpson 	char			 cmsgbuf[MY_CMSG_SIZE];
1082b743a9eSBruce M Simpson 	struct iovec		 iov[1];
1092b743a9eSBruce M Simpson 	struct msghdr		 msg;
1102b743a9eSBruce M Simpson 	struct sockaddr_in	 dsin;
11148451912SBruce M Simpson 	struct sockaddr_in	 laddr;
112f3bb407bSBruce M Simpson 	struct sockaddr_dl	*sdl;
1132b743a9eSBruce M Simpson 	struct cmsghdr		*cmsgp;
1142b743a9eSBruce M Simpson 	struct in_addr		 dstaddr;
1152b743a9eSBruce M Simpson 	struct in_addr		*srcaddrp;
116f3bb407bSBruce M Simpson 	char			*ifname;
11748451912SBruce M Simpson 	char			*laddr_s;
1182b743a9eSBruce M Simpson 	char			*srcaddr_s;
1192b743a9eSBruce M Simpson 	int			 ch;
1202b743a9eSBruce M Simpson 	int			 dobind;
1212b743a9eSBruce M Simpson 	int			 dobroadcast;
1222b743a9eSBruce M Simpson 	int			 dontroute;
1232b743a9eSBruce M Simpson 	int			 doonesbcast;
1242b743a9eSBruce M Simpson 	int			 dorandom;
125*f6c0136cSBruce M Simpson 	int			 dorawip;
1262b743a9eSBruce M Simpson 	size_t			 buflen;
1272b743a9eSBruce M Simpson 	ssize_t			 nbytes;
1282b743a9eSBruce M Simpson 	int			 portno;
1292b743a9eSBruce M Simpson 	int			 ret;
1302b743a9eSBruce M Simpson 	int			 s;
1312b743a9eSBruce M Simpson 	socklen_t		 soptlen;
1322b743a9eSBruce M Simpson 	int			 soptval;
133df7babd6SBruce M Simpson 	int			 ttl;
1342b743a9eSBruce M Simpson 
1352b743a9eSBruce M Simpson 	dobind = 0;
1362b743a9eSBruce M Simpson 	dobroadcast = 0;
1372b743a9eSBruce M Simpson 	dontroute = 0;
1382b743a9eSBruce M Simpson 	doonesbcast = 0;
1392b743a9eSBruce M Simpson 	dorandom = 0;
140*f6c0136cSBruce M Simpson 	dorawip = 0;
1412b743a9eSBruce M Simpson 
142f3bb407bSBruce M Simpson 	ifname = NULL;
1432b743a9eSBruce M Simpson 	dstaddr.s_addr = INADDR_ANY;
14448451912SBruce M Simpson 	laddr_s = NULL;
1452b743a9eSBruce M Simpson 	srcaddr_s = NULL;
1462b743a9eSBruce M Simpson 	portno = DEFAULT_PORT;
147df7babd6SBruce M Simpson 	ttl = DEFAULT_TTL;
1482b743a9eSBruce M Simpson 
1492b743a9eSBruce M Simpson 	buf = NULL;
1502b743a9eSBruce M Simpson 	buflen = DEFAULT_PAYLOAD_SIZE;
1512b743a9eSBruce M Simpson 
1522b743a9eSBruce M Simpson 	progname = basename(argv[0]);
153*f6c0136cSBruce M Simpson 	while ((ch = getopt(argc, argv, "1A:bBdi:l:p:Rrs:t:")) != -1) {
1542b743a9eSBruce M Simpson 		switch (ch) {
1552b743a9eSBruce M Simpson 		case '1':
1562b743a9eSBruce M Simpson 			doonesbcast = 1;
1572b743a9eSBruce M Simpson 			break;
15848451912SBruce M Simpson 		case 'A':
15948451912SBruce M Simpson 			laddr_s = optarg;
16048451912SBruce M Simpson 			break;
1612b743a9eSBruce M Simpson 		case 'b':
1622b743a9eSBruce M Simpson 			dobind = 1;
1632b743a9eSBruce M Simpson 			break;
1642b743a9eSBruce M Simpson 		case 'B':
1652b743a9eSBruce M Simpson 			dobroadcast = 1;
1662b743a9eSBruce M Simpson 			break;
1672b743a9eSBruce M Simpson 		case 'd':
1682b743a9eSBruce M Simpson 			dontroute = 1;
1692b743a9eSBruce M Simpson 			break;
170f3bb407bSBruce M Simpson 		case 'i':
171f3bb407bSBruce M Simpson 			ifname = optarg;
172f3bb407bSBruce M Simpson 			break;
1732b743a9eSBruce M Simpson 		case 'l':
1742b743a9eSBruce M Simpson 			buflen = atoi(optarg);
1752b743a9eSBruce M Simpson 			break;
1762b743a9eSBruce M Simpson 		case 'p':
1772b743a9eSBruce M Simpson 			portno = atoi(optarg);
1782b743a9eSBruce M Simpson 			break;
179*f6c0136cSBruce M Simpson 		case 'R':
180*f6c0136cSBruce M Simpson 			dorawip = 1;
181*f6c0136cSBruce M Simpson 			break;
1822b743a9eSBruce M Simpson 		case 'r':
1832b743a9eSBruce M Simpson 			dorandom = 1;
1842b743a9eSBruce M Simpson 			break;
1852b743a9eSBruce M Simpson 		case 's':
1862b743a9eSBruce M Simpson 			srcaddr_s = optarg;
1872b743a9eSBruce M Simpson 			break;
188df7babd6SBruce M Simpson 		case 't':
189df7babd6SBruce M Simpson 			ttl = atoi(optarg);
190df7babd6SBruce M Simpson 			break;
1912b743a9eSBruce M Simpson 		default:
1922b743a9eSBruce M Simpson 			usage();
1932b743a9eSBruce M Simpson 			break;
1942b743a9eSBruce M Simpson 		}
1952b743a9eSBruce M Simpson 	}
1962b743a9eSBruce M Simpson 	argc -= optind;
1972b743a9eSBruce M Simpson 	argv += optind;
1982b743a9eSBruce M Simpson 
1992b743a9eSBruce M Simpson 	if (argc != 1)
2002b743a9eSBruce M Simpson 		usage();
2012b743a9eSBruce M Simpson 	if (argv[0] == NULL || inet_aton(argv[0], &dstaddr) == 0)
2022b743a9eSBruce M Simpson 		usage();
203f3bb407bSBruce M Simpson 	/* IP_SENDSRCADDR and IP_SENDIF are mutually exclusive just now. */
204f3bb407bSBruce M Simpson 	if (srcaddr_s != NULL && ifname != NULL)
205f3bb407bSBruce M Simpson 		usage();
206*f6c0136cSBruce M Simpson 	if (dorawip) {
207*f6c0136cSBruce M Simpson 		if (geteuid() != 0)
208*f6c0136cSBruce M Simpson 			fprintf(stderr, "WARNING: not running as root.\n");
209*f6c0136cSBruce M Simpson 		s = socket(PF_INET, SOCK_RAW, IPPROTO_ZEROHOP);
210*f6c0136cSBruce M Simpson 	} else {
2112b743a9eSBruce M Simpson 		s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
212*f6c0136cSBruce M Simpson 	}
2132b743a9eSBruce M Simpson 	if (s == -1) {
2142b743a9eSBruce M Simpson 		perror("socket");
2152b743a9eSBruce M Simpson 		exit(EXIT_FAILURE);
2162b743a9eSBruce M Simpson 	}
2172b743a9eSBruce M Simpson 
2182b743a9eSBruce M Simpson 	if (dontroute) {
2192b743a9eSBruce M Simpson 		soptval = 1;
2202b743a9eSBruce M Simpson 		soptlen = sizeof(soptval);
2212b743a9eSBruce M Simpson 		ret = setsockopt(s, SOL_SOCKET, SO_DONTROUTE, &soptval,
2222b743a9eSBruce M Simpson 		    soptlen);
2232b743a9eSBruce M Simpson 		if (ret == -1) {
2242b743a9eSBruce M Simpson 			perror("setsockopt SO_DONTROUTE");
2252b743a9eSBruce M Simpson 			close(s);
2262b743a9eSBruce M Simpson 			exit(EXIT_FAILURE);
2272b743a9eSBruce M Simpson 		}
2282b743a9eSBruce M Simpson 	}
2292b743a9eSBruce M Simpson 
2302b743a9eSBruce M Simpson 	if (dobroadcast) {
2312b743a9eSBruce M Simpson 		soptval = 1;
2322b743a9eSBruce M Simpson 		soptlen = sizeof(soptval);
2332b743a9eSBruce M Simpson 		ret = setsockopt(s, SOL_SOCKET, SO_BROADCAST, &soptval,
2342b743a9eSBruce M Simpson 		    soptlen);
2352b743a9eSBruce M Simpson 		if (ret == -1) {
2362b743a9eSBruce M Simpson 			perror("setsockopt SO_BROADCAST");
2372b743a9eSBruce M Simpson 			close(s);
2382b743a9eSBruce M Simpson 			exit(EXIT_FAILURE);
2392b743a9eSBruce M Simpson 		}
2402b743a9eSBruce M Simpson 	}
2412b743a9eSBruce M Simpson 
242df7babd6SBruce M Simpson 	soptval = ttl;
243df7babd6SBruce M Simpson 	soptlen = sizeof(soptval);
244df7babd6SBruce M Simpson 	ret = setsockopt(s, IPPROTO_IP, IP_TTL, &soptval, soptlen);
245df7babd6SBruce M Simpson 	if (ret == -1) {
246df7babd6SBruce M Simpson 		perror("setsockopt IPPROTO_IP IP_TTL");
247df7babd6SBruce M Simpson 		close(s);
248df7babd6SBruce M Simpson 		exit(EXIT_FAILURE);
249df7babd6SBruce M Simpson 	}
250df7babd6SBruce M Simpson 
2512b743a9eSBruce M Simpson 	if (doonesbcast) {
2522b743a9eSBruce M Simpson 		soptval = 1;
2532b743a9eSBruce M Simpson 		soptlen = sizeof(soptval);
2542b743a9eSBruce M Simpson 		ret = setsockopt(s, IPPROTO_IP, IP_ONESBCAST, &soptval,
2552b743a9eSBruce M Simpson 		    soptlen);
2562b743a9eSBruce M Simpson 		if (ret == -1) {
2572b743a9eSBruce M Simpson 			perror("setsockopt IP_ONESBCAST");
2582b743a9eSBruce M Simpson 			close(s);
2592b743a9eSBruce M Simpson 			exit(EXIT_FAILURE);
2602b743a9eSBruce M Simpson 		}
2612b743a9eSBruce M Simpson 	}
2622b743a9eSBruce M Simpson 
2632b743a9eSBruce M Simpson 	if (dobind) {
26448451912SBruce M Simpson 		memset(&laddr, 0, sizeof(struct sockaddr_in));
26548451912SBruce M Simpson 		laddr.sin_family = AF_INET;
26648451912SBruce M Simpson 		laddr.sin_len = sizeof(struct sockaddr_in);
26748451912SBruce M Simpson 		if (laddr_s != NULL) {
26848451912SBruce M Simpson 			laddr.sin_addr.s_addr = inet_addr(laddr_s);
26948451912SBruce M Simpson 		} else
27048451912SBruce M Simpson 			laddr.sin_addr.s_addr = INADDR_ANY;
27148451912SBruce M Simpson 		laddr.sin_port = htons(portno);
27248451912SBruce M Simpson 		ret = bind(s, (struct sockaddr *)&laddr, sizeof(laddr));
2732b743a9eSBruce M Simpson 		if (ret == -1) {
2742b743a9eSBruce M Simpson 			perror("bind");
2752b743a9eSBruce M Simpson 			close(s);
2762b743a9eSBruce M Simpson 			exit(EXIT_FAILURE);
2772b743a9eSBruce M Simpson 		}
2782b743a9eSBruce M Simpson 	}
2792b743a9eSBruce M Simpson 
2802b743a9eSBruce M Simpson 	memset(&dsin, 0, sizeof(struct sockaddr_in));
2812b743a9eSBruce M Simpson 	dsin.sin_family = AF_INET;
2822b743a9eSBruce M Simpson 	dsin.sin_len = sizeof(struct sockaddr_in);
2832b743a9eSBruce M Simpson 	dsin.sin_addr.s_addr = dstaddr.s_addr;
2842b743a9eSBruce M Simpson 	dsin.sin_port = htons(portno);
2852b743a9eSBruce M Simpson 
2862b743a9eSBruce M Simpson 	buf = malloc(buflen);
2872b743a9eSBruce M Simpson 	if (buf == NULL) {
2882b743a9eSBruce M Simpson 		perror("malloc");
2892b743a9eSBruce M Simpson 		close(s);
2902b743a9eSBruce M Simpson 		exit(EXIT_FAILURE);
2912b743a9eSBruce M Simpson 	}
2922b743a9eSBruce M Simpson 	memset(iov, 0, sizeof(iov));
2932b743a9eSBruce M Simpson 	iov[0].iov_base = buf;
2942b743a9eSBruce M Simpson 	iov[0].iov_len = buflen;
2952b743a9eSBruce M Simpson 
2962b743a9eSBruce M Simpson 	memset(&msg, 0, sizeof(struct msghdr));
2972b743a9eSBruce M Simpson 	msg.msg_name = &dsin;
2982b743a9eSBruce M Simpson 	msg.msg_namelen = sizeof(dsin);
2992b743a9eSBruce M Simpson 	msg.msg_iov = iov;
3002b743a9eSBruce M Simpson 	msg.msg_iovlen = 1;
3012b743a9eSBruce M Simpson 
302f3bb407bSBruce M Simpson 	/* Assume we fill out a control msg; macros need to see buf ptr */
3032b743a9eSBruce M Simpson 	msg.msg_control = cmsgbuf;
304f3bb407bSBruce M Simpson 	msg.msg_controllen = 0;
305f3bb407bSBruce M Simpson 	memset(cmsgbuf, 0, MY_CMSG_SIZE);
306f3bb407bSBruce M Simpson 
307f3bb407bSBruce M Simpson 	/* IP_SENDSRCADDR and IP_SENDIF are mutually exclusive just now. */
308f3bb407bSBruce M Simpson 	if (srcaddr_s != NULL) {
309f3bb407bSBruce M Simpson 		msg.msg_controllen += CMSG_SPACE(sizeof(struct in_addr));
3102b743a9eSBruce M Simpson 		cmsgp = CMSG_FIRSTHDR(&msg);
3112b743a9eSBruce M Simpson 		cmsgp->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
3122b743a9eSBruce M Simpson 		cmsgp->cmsg_level = IPPROTO_IP;
3132b743a9eSBruce M Simpson 		cmsgp->cmsg_type = IP_SENDSRCADDR;
3142b743a9eSBruce M Simpson 		srcaddrp = (struct in_addr *)CMSG_DATA(cmsgp);
3152b743a9eSBruce M Simpson 		srcaddrp->s_addr = inet_addr(srcaddr_s);
3162b743a9eSBruce M Simpson 	}
3172b743a9eSBruce M Simpson 
318f3bb407bSBruce M Simpson 	if (ifname != NULL) {
319f3bb407bSBruce M Simpson #ifdef IP_SENDIF
320f3bb407bSBruce M Simpson 		msg.msg_controllen += CMSG_SPACE(sizeof(struct sockaddr_dl));
321f3bb407bSBruce M Simpson 		cmsgp = CMSG_FIRSTHDR(&msg);
322f3bb407bSBruce M Simpson 		cmsgp->cmsg_len = CMSG_LEN(sizeof(struct sockaddr_dl));
323f3bb407bSBruce M Simpson 		cmsgp->cmsg_level = IPPROTO_IP;
324f3bb407bSBruce M Simpson 		cmsgp->cmsg_type = IP_SENDIF;
325f3bb407bSBruce M Simpson 
326f3bb407bSBruce M Simpson #ifdef DIAGNOSTIC
327f3bb407bSBruce M Simpson 		fprintf(stderr, "DEBUG: cmsgp->cmsg_len is %d\n",
328f3bb407bSBruce M Simpson 		    cmsgp->cmsg_len);
329f3bb407bSBruce M Simpson #endif
330f3bb407bSBruce M Simpson 
331f3bb407bSBruce M Simpson 		sdl = (struct sockaddr_dl *)CMSG_DATA(cmsgp);
332f3bb407bSBruce M Simpson 		memset(sdl, 0, sizeof(struct sockaddr_dl));
333f3bb407bSBruce M Simpson 		sdl->sdl_family = AF_LINK;
334f3bb407bSBruce M Simpson 		sdl->sdl_len = sizeof(struct sockaddr_dl);
335f3bb407bSBruce M Simpson 		sdl->sdl_index = if_nametoindex(ifname);
336f3bb407bSBruce M Simpson 
337f3bb407bSBruce M Simpson #ifdef DIAGNOSTIC
338f3bb407bSBruce M Simpson 		fprintf(stderr, "DEBUG: sdl->sdl_family is %d\n",
339f3bb407bSBruce M Simpson 		    sdl->sdl_family);
340f3bb407bSBruce M Simpson 		fprintf(stderr, "DEBUG: sdl->sdl_len is %d\n",
341f3bb407bSBruce M Simpson 		    sdl->sdl_len);
342f3bb407bSBruce M Simpson 		fprintf(stderr, "DEBUG: sdl->sdl_index is %d\n",
343f3bb407bSBruce M Simpson 		    sdl->sdl_index);
344f3bb407bSBruce M Simpson #endif
345f3bb407bSBruce M Simpson #else
346f3bb407bSBruce M Simpson 		fprintf(stderr, "WARNING: IP_SENDIF not supported, ignored.\n");
347f3bb407bSBruce M Simpson #endif
348f3bb407bSBruce M Simpson 	}
349f3bb407bSBruce M Simpson 
350f3bb407bSBruce M Simpson 	if (msg.msg_controllen == 0)
351f3bb407bSBruce M Simpson 		msg.msg_control = NULL;
352f3bb407bSBruce M Simpson 
3532b743a9eSBruce M Simpson 	nbytes = sendmsg(s, &msg, (dontroute ? MSG_DONTROUTE : 0));
3542b743a9eSBruce M Simpson 	if (nbytes == -1) {
3552b743a9eSBruce M Simpson 		perror("sendmsg");
3562b743a9eSBruce M Simpson 		close(s);
3572b743a9eSBruce M Simpson 		exit(EXIT_FAILURE);
3582b743a9eSBruce M Simpson 	}
3592b743a9eSBruce M Simpson 
3602b743a9eSBruce M Simpson 	close(s);
3612b743a9eSBruce M Simpson 
3622b743a9eSBruce M Simpson 	exit(EXIT_SUCCESS);
3632b743a9eSBruce M Simpson }
364