xref: /dragonfly/usr.sbin/dntpd/socket.c (revision 19fe1c42)
1 /*
2  * Copyright (c) 2005 The DragonFly Project.  All rights reserved.
3  *
4  * This code is derived from software contributed to The DragonFly Project
5  * by Matthew Dillon <dillon@backplane.com>
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  * 3. Neither the name of The DragonFly Project nor the names of its
18  *    contributors may be used to endorse or promote products derived
19  *    from this software without specific, prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  *
34  * $DragonFly: src/usr.sbin/dntpd/socket.c,v 1.4 2007/06/25 21:33:36 dillon Exp $
35  */
36 
37 #include "defs.h"
38 
39 int
40 udp_socket(const char *target, int port, struct sockaddr *sam)
41 {
42     struct addrinfo hints, *res, *res0;
43     char servname[128];
44     const char *cause = NULL;
45     int error;
46     int fd;
47     int tos;
48 
49     memset(&hints, 0, sizeof(hints));
50     hints.ai_family = family;
51     hints.ai_socktype = SOCK_DGRAM;
52     snprintf(servname, sizeof(servname), "%d", port);
53     error = getaddrinfo(target, servname, &hints, &res0);
54     if (error) {
55         logerr("getaddrinfo (%s) init error", target, gai_strerror(error));
56         return(-1);
57     }
58 
59     fd = -1;
60     for (res = res0; res; res = res->ai_next) {
61         fd = socket(res->ai_family, res->ai_socktype,
62         res->ai_protocol);
63         if (fd < 0) {
64            cause = "socket";
65            continue;
66         }
67 
68         if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
69             logerr("%s: unable to set non-blocking mode", target);
70             close(fd);
71             fd = -1;
72             continue;
73         }
74 
75         if (connect(fd, res->ai_addr, res->ai_addrlen) < 0) {
76            cause = "connect";
77            close(fd);
78            fd = -1;
79            continue;
80         }
81 
82         break;  /* okay we got one */
83     }
84 
85     if (fd < 0) {
86         logerr("Unable to establish a connection with %s: %s", target, cause);
87         return(-1);
88     }
89     memcpy(sam, res->ai_addr, res->ai_addr->sa_len);
90     freeaddrinfo(res0);
91 
92 #ifdef IPTOS_LOWDELAY
93     tos = IPTOS_LOWDELAY;
94     setsockopt(fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
95 #endif
96 #if 0
97 #ifdef IP_PORTRANGE
98     tos = IP_PORTRANGE_HIGH;
99     setsockopt(fd, IPPROTO_IP, IP_PORTRANGE, &tos, sizeof(tos));
100 #endif
101 #endif
102     return(fd);
103 }
104