~ubuntu-branches/debian/squeeze/ntp/squeeze-201010051545

« back to all changes in this revision

Viewing changes to libntp/ntp_rfc2553.c

  • Committer: Bazaar Package Importer
  • Author(s): Matt Zimmerman
  • Date: 2004-10-11 16:10:27 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20041011161027-icyjbji8ujym633o
Tags: 1:4.2.0a-10ubuntu2
Use ntp.ubuntulinux.org instead of pool.ntp.org

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
 
3
 * All rights reserved.
 
4
 *
 
5
 * Redistribution and use in source and binary forms, with or without
 
6
 * modification, are permitted provided that the following conditions
 
7
 * are met:
 
8
 * 1. Redistributions of source code must retain the above copyright
 
9
 *    notice, this list of conditions and the following disclaimer.
 
10
 * 2. Redistributions in binary form must reproduce the above copyright
 
11
 *    notice, this list of conditions and the following disclaimer in the
 
12
 *    documentation and/or other materials provided with the distribution.
 
13
 * 3. Neither the name of the project nor the names of its contributors
 
14
 *    may be used to endorse or promote products derived from this software
 
15
 *    without specific prior written permission.
 
16
 *
 
17
 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
 
18
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
19
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
20
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
 
21
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 
22
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 
23
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
24
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 
25
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 
26
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 
27
 * SUCH DAMAGE.
 
28
 */
 
29
 
 
30
/*
 
31
 * Copyright (c) 1982, 1986, 1990, 1993
 
32
 *      The Regents of the University of California.  All rights reserved.
 
33
 *
 
34
 * Redistribution and use in source and binary forms, with or without
 
35
 * modification, are permitted provided that the following conditions
 
36
 * are met:
 
37
 * 1. Redistributions of source code must retain the above copyright
 
38
 *    notice, this list of conditions and the following disclaimer.
 
39
 * 2. Redistributions in binary form must reproduce the above copyright
 
40
 *    notice, this list of conditions and the following disclaimer in the
 
41
 *    documentation and/or other materials provided with the distribution.
 
42
 * 3. All advertising materials mentioning features or use of this software
 
43
 *    must display the following acknowledgement:
 
44
 *      This product includes software developed by the University of
 
45
 *      California, Berkeley and its contributors.
 
46
 * 4. Neither the name of the University nor the names of its contributors
 
47
 *    may be used to endorse or promote products derived from this software
 
48
 *    without specific prior written permission.
 
49
 *
 
50
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 
51
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
52
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
53
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 
54
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 
55
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 
56
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
57
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 
58
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 
59
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 
60
 * SUCH DAMAGE.
 
61
 *
 
62
 */
 
63
 
 
64
/*
 
65
 * Compatability shims with the rfc2553 API to simplify ntp.
 
66
 */
 
67
 
 
68
#ifdef HAVE_CONFIG_H
 
69
#include <config.h>
 
70
#endif
 
71
 
 
72
#include <sys/types.h>
 
73
#include <ctype.h>
 
74
#include <sys/socket.h>
 
75
#include "ntp_rfc2553.h"
 
76
#ifdef HAVE_NETINET_IN_H
 
77
#include <netinet/in.h>
 
78
#endif
 
79
#include <netdb.h>
 
80
 
 
81
#include "ntpd.h"
 
82
#include "ntp_malloc.h"
 
83
#include "ntp_stdlib.h"
 
84
#include "ntp_string.h"
 
85
 
 
86
#ifndef ISC_PLATFORM_HAVEIPV6
 
87
 
 
88
#if defined(SYS_WINNT)
 
89
/* XXX This is the preferred way, but for some reason the SunOS compiler
 
90
 * does not like it.
 
91
 */
 
92
const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
 
93
#else
 
94
const struct in6_addr in6addr_any;
 
95
#endif
 
96
 
 
97
static char *ai_errlist[] = {
 
98
        "Success",
 
99
        "Address family for hostname not supported",    /* EAI_ADDRFAMILY */
 
100
        "Temporary failure in name resolution",         /* EAI_AGAIN      */
 
101
        "Invalid value for ai_flags",                   /* EAI_BADFLAGS   */
 
102
        "Non-recoverable failure in name resolution",   /* EAI_FAIL       */
 
103
        "ai_family not supported",                      /* EAI_FAMILY     */
 
104
        "Memory allocation failure",                    /* EAI_MEMORY     */
 
105
        "No address associated with hostname",          /* EAI_NODATA     */
 
106
        "hostname nor servname provided, or not known", /* EAI_NONAME     */
 
107
        "servname not supported for ai_socktype",       /* EAI_SERVICE    */
 
108
        "ai_socktype not supported",                    /* EAI_SOCKTYPE   */
 
109
        "System error returned in errno",               /* EAI_SYSTEM     */
 
110
        "Invalid value for hints",                      /* EAI_BADHINTS   */
 
111
        "Resolved protocol is unknown",                 /* EAI_PROTOCOL   */
 
112
        "Unknown error",                                /* EAI_MAX        */
 
113
};
 
114
 
 
115
static  int ipv4_aton P((const char *, struct sockaddr_storage *));
 
116
static  int do_nodename P((const char *nodename, struct addrinfo *ai,
 
117
    const struct addrinfo *hints));
 
118
 
 
119
int
 
120
getaddrinfo (const char *nodename, const char *servname,
 
121
        const struct addrinfo *hints, struct addrinfo **res)
 
122
{
 
123
        int rval;
 
124
        struct addrinfo *ai;
 
125
        struct sockaddr_in *sockin;
 
126
 
 
127
        ai = calloc(sizeof(struct addrinfo), 1);
 
128
        if (ai == NULL)
 
129
                return (EAI_MEMORY);
 
130
 
 
131
        if (nodename != NULL) {
 
132
                rval = do_nodename(nodename, ai, hints);
 
133
                if (rval != 0) {
 
134
                        freeaddrinfo(ai);
 
135
                        return (rval);
 
136
                }
 
137
        }
 
138
        if (nodename == NULL && hints != NULL) {
 
139
                ai->ai_addr = calloc(sizeof(struct sockaddr_storage), 1);
 
140
                if (ai->ai_addr == NULL) {
 
141
                        freeaddrinfo(ai);
 
142
                        return (EAI_MEMORY);
 
143
                }
 
144
                ai->ai_family = AF_INET;
 
145
                ai->ai_addrlen = sizeof(struct sockaddr_storage);
 
146
                sockin = (struct sockaddr_in *)ai->ai_addr;
 
147
                sockin->sin_family = AF_INET;
 
148
                sockin->sin_addr.s_addr = htonl(INADDR_ANY);
 
149
#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
 
150
                ai->ai_addr->sa_len = SOCKLEN(ai->ai_addr);
 
151
#endif
 
152
        }
 
153
        if (servname != NULL) {
 
154
                ai->ai_family = AF_INET;
 
155
                ai->ai_socktype = SOCK_DGRAM;
 
156
                if (strcmp(servname, "ntp") != 0) {
 
157
                        freeaddrinfo(ai);
 
158
                        return (EAI_SERVICE);
 
159
                }
 
160
                sockin = (struct sockaddr_in *)ai->ai_addr;
 
161
                sockin->sin_port = htons(NTP_PORT);
 
162
        }
 
163
        *res = ai;
 
164
        return (0);
 
165
}
 
166
 
 
167
void
 
168
freeaddrinfo(struct addrinfo *ai)
 
169
{
 
170
        if (ai->ai_canonname != NULL)
 
171
                free(ai->ai_canonname);
 
172
        if (ai->ai_addr != NULL)
 
173
                free(ai->ai_addr);
 
174
        free(ai);
 
175
}
 
176
 
 
177
int
 
178
getnameinfo (const struct sockaddr *sa, u_int salen, char *host,
 
179
        size_t hostlen, char *serv, size_t servlen, int flags)
 
180
{
 
181
        struct hostent *hp;
 
182
 
 
183
        if (sa->sa_family != AF_INET)
 
184
                return (EAI_FAMILY);
 
185
        hp = gethostbyaddr(
 
186
            (const char *)&((const struct sockaddr_in *)sa)->sin_addr,
 
187
            4, AF_INET);
 
188
        if (hp == NULL) {
 
189
                if (h_errno == TRY_AGAIN)
 
190
                        return (EAI_AGAIN);
 
191
                else
 
192
                        return (EAI_FAIL);
 
193
        }
 
194
        if (host != NULL) {
 
195
                strncpy(host, hp->h_name, hostlen);
 
196
                host[hostlen] = '\0';
 
197
        }
 
198
        return (0);
 
199
}
 
200
 
 
201
char *
 
202
gai_strerror(int ecode)
 
203
{
 
204
        if (ecode < 0 || ecode > EAI_MAX)
 
205
                ecode = EAI_MAX;
 
206
        return ai_errlist[ecode];
 
207
}
 
208
 
 
209
static int
 
210
do_nodename(
 
211
        const char *nodename,
 
212
        struct addrinfo *ai,
 
213
        const struct addrinfo *hints)
 
214
{
 
215
        struct hostent *hp;
 
216
        struct sockaddr_in *sockin;
 
217
 
 
218
        ai->ai_addr = calloc(sizeof(struct sockaddr_storage), 1);
 
219
        if (ai->ai_addr == NULL)
 
220
                return (EAI_MEMORY);
 
221
 
 
222
        if (hints != NULL && hints->ai_flags & AI_NUMERICHOST) {
 
223
                if (ipv4_aton(nodename,
 
224
                    (struct sockaddr_storage *)ai->ai_addr) == 1) {
 
225
                        ai->ai_family = AF_INET;
 
226
                        ai->ai_addrlen = sizeof(struct sockaddr_in);
 
227
                        return (0);
 
228
                }
 
229
                return (EAI_NONAME);
 
230
        }
 
231
        hp = gethostbyname(nodename);
 
232
        if (hp == NULL) {
 
233
                if (h_errno == TRY_AGAIN)
 
234
                        return (EAI_AGAIN);
 
235
                else {
 
236
                        if (ipv4_aton(nodename,
 
237
                            (struct sockaddr_storage *)ai->ai_addr) == 1) {
 
238
                                ai->ai_family = AF_INET;
 
239
                                ai->ai_addrlen = sizeof(struct sockaddr_in);
 
240
                                return (0);
 
241
                        }
 
242
                        return (EAI_FAIL);
 
243
                }
 
244
        }
 
245
        ai->ai_family = hp->h_addrtype;
 
246
        ai->ai_addrlen = sizeof(struct sockaddr);
 
247
        sockin = (struct sockaddr_in *)ai->ai_addr;
 
248
        memcpy(&sockin->sin_addr, hp->h_addr, hp->h_length);
 
249
        ai->ai_addr->sa_family = hp->h_addrtype;
 
250
#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
 
251
        ai->ai_addr->sa_len = sizeof(struct sockaddr);
 
252
#endif
 
253
        if (hints != NULL && hints->ai_flags & AI_CANONNAME) {
 
254
                ai->ai_canonname = malloc(strlen(hp->h_name) + 1);
 
255
                if (ai->ai_canonname == NULL)
 
256
                        return (EAI_MEMORY);
 
257
                strcpy(ai->ai_canonname, hp->h_name);
 
258
        }
 
259
        return (0);
 
260
}
 
261
 
 
262
/*
 
263
 * ipv4_aton - return a net number (this is crude, but careful)
 
264
 */
 
265
static int
 
266
ipv4_aton(
 
267
        const char *num,
 
268
        struct sockaddr_storage *saddr
 
269
        )
 
270
{
 
271
        const char *cp;
 
272
        char *bp;
 
273
        int i;
 
274
        int temp;
 
275
        char buf[80];           /* will core dump on really stupid stuff */
 
276
        u_int32 netnum;
 
277
        struct sockaddr_in *addr;
 
278
 
 
279
        cp = num;
 
280
        netnum = 0;
 
281
        for (i = 0; i < 4; i++) {
 
282
                bp = buf;
 
283
                while (isdigit((int)*cp))
 
284
                        *bp++ = *cp++;
 
285
                if (bp == buf)
 
286
                        break;
 
287
 
 
288
                if (i < 3) {
 
289
                        if (*cp++ != '.')
 
290
                                break;
 
291
                } else if (*cp != '\0')
 
292
                        break;
 
293
 
 
294
                *bp = '\0';
 
295
                temp = atoi(buf);
 
296
                if (temp > 255)
 
297
                        break;
 
298
                netnum <<= 8;
 
299
                netnum += temp;
 
300
#ifdef DEBUG
 
301
                if (debug > 3)
 
302
                        printf("ipv4_aton %s step %d buf %s temp %d netnum %lu\n",
 
303
                           num, i, buf, temp, (u_long)netnum);
 
304
#endif
 
305
        }
 
306
 
 
307
        if (i < 4) {
 
308
#ifdef DEBUG
 
309
                if (debug > 3)
 
310
                        printf(
 
311
                                "ipv4_aton: \"%s\" invalid host number, line ignored\n",
 
312
                                num);
 
313
#endif
 
314
                return (0);
 
315
        }
 
316
 
 
317
        /*
 
318
         * make up socket address.      Clear it out for neatness.
 
319
         */
 
320
        memset((void *)saddr, 0, sizeof(struct sockaddr_storage));
 
321
        addr = (struct sockaddr_in *)saddr;
 
322
        addr->sin_family = AF_INET;
 
323
        addr->sin_port = htons(NTP_PORT);
 
324
        addr->sin_addr.s_addr = htonl(netnum);
 
325
#ifdef DEBUG
 
326
        if (debug > 1)
 
327
                printf("ipv4_aton given %s, got %s.\n", num, ntoa(saddr));
 
328
#endif
 
329
        return (1);
 
330
}
 
331
#endif /* !ISC_PLATFORM_HAVEIPV6 */