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