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