~ubuntu-branches/ubuntu/gutsy/net-snmp/gutsy-security

« back to all changes in this revision

Viewing changes to snmplib/inet_pton.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2004-09-13 12:06:21 UTC
  • Revision ID: james.westby@ubuntu.com-20040913120621-g952ntonlleihcvm
Tags: upstream-5.1.1
ImportĀ upstreamĀ versionĀ 5.1.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*      Id: inet_pton.c,v 1.5 2001/04/13 15:24:35 lukem Exp     */
 
2
/*      $NetBSD: inet_pton.c,v 1.16 2000/02/07 18:51:02 itojun Exp $    */
 
3
 
 
4
/* Copyright (c) 1996 by Internet Software Consortium.
 
5
 *
 
6
 * Permission to use, copy, modify, and distribute this software for any
 
7
 * purpose with or without fee is hereby granted, provided that the above
 
8
 * copyright notice and this permission notice appear in all copies.
 
9
 *
 
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
 
11
 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
 
12
 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
 
13
 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
 
14
 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
 
15
 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
 
16
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 
17
 * SOFTWARE.
 
18
 */
 
19
 
 
20
#include <net-snmp/net-snmp-config.h>
 
21
 
 
22
#ifndef HAVE_INET_PTON
 
23
 
 
24
#if HAVE_ARPA_NAMESER_H
 
25
#include <arpa/nameser.h>
 
26
#endif
 
27
 
 
28
  /*
 
29
   * Net-SNMP Win32 additions
 
30
   */
 
31
#if HAVE_WINSOCK_H
 
32
#include <winsock2.h>
 
33
#include <errno.h>
 
34
#include <stdio.h>
 
35
#endif
 
36
 
 
37
#ifndef EAFNOSUPPORT
 
38
#define EAFNOSUPPORT            WSAEAFNOSUPPORT
 
39
#endif
 
40
#ifndef INET6
 
41
#define INET6
 
42
#endif
 
43
 
 
44
#ifndef IN6ADDRSZ
 
45
#define IN6ADDRSZ       16
 
46
#endif
 
47
 
 
48
#ifndef INT16SZ
 
49
#define INT16SZ         2
 
50
#endif
 
51
  /*
 
52
   * End of Net-SNMP Win32 additions
 
53
   */
 
54
 
 
55
#ifndef INADDRSZ
 
56
#define INADDRSZ        4
 
57
#endif
 
58
 
 
59
/*
 
60
 * WARNING: Don't even consider trying to compile this on a system where
 
61
 * sizeof(int) < 4.  sizeof(int) > 4 is fine; all the world's not a VAX.
 
62
 */
 
63
 
 
64
static int      inet_pton4(const char *src, u_char *dst, int pton);
 
65
#ifdef INET6
 
66
static int      inet_pton6(const char *src, u_char *dst);
 
67
#endif
 
68
 
 
69
/* int
 
70
 * inet_pton(af, src, dst)
 
71
 *      convert from presentation format (which usually means ASCII printable)
 
72
 *      to network format (which is usually some kind of binary format).
 
73
 * return:
 
74
 *      1 if the address was valid for the specified address family
 
75
 *      0 if the address wasn't valid (`dst' is untouched in this case)
 
76
 *      -1 if some other error occurred (`dst' is untouched in this case, too)
 
77
 * author:
 
78
 *      Paul Vixie, 1996.
 
79
 */
 
80
int
 
81
inet_pton(af, src, dst)
 
82
        int af;
 
83
        const char *src;
 
84
        void *dst;
 
85
{
 
86
 
 
87
        switch (af) {
 
88
        case AF_INET:
 
89
                return (inet_pton4(src, dst, 1));
 
90
#ifdef INET6
 
91
        case AF_INET6:
 
92
                return (inet_pton6(src, dst));
 
93
#endif
 
94
        default:
 
95
                errno = EAFNOSUPPORT;
 
96
                return (-1);
 
97
        }
 
98
        /* NOTREACHED */
 
99
}
 
100
 
 
101
/* int
 
102
 * inet_pton4(src, dst, pton)
 
103
 *      when last arg is 0: inet_aton(). with hexadecimal, octal and shorthand.
 
104
 *      when last arg is 1: inet_pton(). decimal dotted-quad only.
 
105
 * return:
 
106
 *      1 if `src' is a valid input, else 0.
 
107
 * notice:
 
108
 *      does not touch `dst' unless it's returning 1.
 
109
 * author:
 
110
 *      Paul Vixie, 1996.
 
111
 */
 
112
static int
 
113
inet_pton4(src, dst, pton)
 
114
        const char *src;
 
115
        u_char *dst;
 
116
        int pton;
 
117
{
 
118
        u_int val;
 
119
        u_int digit;
 
120
        int base, n;
 
121
        unsigned char c;
 
122
        u_int parts[4];
 
123
        register u_int *pp = parts;
 
124
 
 
125
        c = *src;
 
126
        for (;;) {
 
127
                /*
 
128
                 * Collect number up to ``.''.
 
129
                 * Values are specified as for C:
 
130
                 * 0x=hex, 0=octal, isdigit=decimal.
 
131
                 */
 
132
                if (!isdigit(c))
 
133
                        return (0);
 
134
                val = 0; base = 10;
 
135
                if (c == '0') {
 
136
                        c = *++src;
 
137
                        if (c == 'x' || c == 'X')
 
138
                                base = 16, c = *++src;
 
139
                        else if (isdigit(c) && c != '9')
 
140
                                base = 8;
 
141
                }
 
142
                /* inet_pton() takes decimal only */
 
143
                if (pton && base != 10)
 
144
                        return (0);
 
145
                for (;;) {
 
146
                        if (isdigit(c)) {
 
147
                                digit = c - '0';
 
148
                                if (digit >= base)
 
149
                                        break;
 
150
                                val = (val * base) + digit;
 
151
                                c = *++src;
 
152
                        } else if (base == 16 && isxdigit(c)) {
 
153
                                digit = c + 10 - (islower(c) ? 'a' : 'A');
 
154
                                if (digit >= 16)
 
155
                                        break;
 
156
                                val = (val << 4) | digit;
 
157
                                c = *++src;
 
158
                        } else
 
159
                                break;
 
160
                }
 
161
                if (c == '.') {
 
162
                        /*
 
163
                         * Internet format:
 
164
                         *      a.b.c.d
 
165
                         *      a.b.c   (with c treated as 16 bits)
 
166
                         *      a.b     (with b treated as 24 bits)
 
167
                         *      a       (with a treated as 32 bits)
 
168
                         */
 
169
                        if (pp >= parts + 3)
 
170
                                return (0);
 
171
                        *pp++ = val;
 
172
                        c = *++src;
 
173
                } else
 
174
                        break;
 
175
        }
 
176
        /*
 
177
         * Check for trailing characters.
 
178
         */
 
179
        if (c != '\0' && !isspace(c))
 
180
                return (0);
 
181
        /*
 
182
         * Concoct the address according to
 
183
         * the number of parts specified.
 
184
         */
 
185
        n = pp - parts + 1;
 
186
        /* inet_pton() takes dotted-quad only.  it does not take shorthand. */
 
187
        if (pton && n != 4)
 
188
                return (0);
 
189
        switch (n) {
 
190
 
 
191
        case 0:
 
192
                return (0);             /* initial nondigit */
 
193
 
 
194
        case 1:                         /* a -- 32 bits */
 
195
                break;
 
196
 
 
197
        case 2:                         /* a.b -- 8.24 bits */
 
198
                if (parts[0] > 0xff || val > 0xffffff)
 
199
                        return (0);
 
200
                val |= parts[0] << 24;
 
201
                break;
 
202
 
 
203
        case 3:                         /* a.b.c -- 8.8.16 bits */
 
204
                if ((parts[0] | parts[1]) > 0xff || val > 0xffff)
 
205
                        return (0);
 
206
                val |= (parts[0] << 24) | (parts[1] << 16);
 
207
                break;
 
208
 
 
209
        case 4:                         /* a.b.c.d -- 8.8.8.8 bits */
 
210
                if ((parts[0] | parts[1] | parts[2] | val) > 0xff)
 
211
                        return (0);
 
212
                val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
 
213
                break;
 
214
        }
 
215
        if (dst) {
 
216
                val = htonl(val);
 
217
                memcpy(dst, &val, INADDRSZ);
 
218
        }
 
219
        return (1);
 
220
}
 
221
 
 
222
#ifdef INET6
 
223
/* int
 
224
 * inet_pton6(src, dst)
 
225
 *      convert presentation level address to network order binary form.
 
226
 * return:
 
227
 *      1 if `src' is a valid [RFC1884 2.2] address, else 0.
 
228
 * notice:
 
229
 *      (1) does not touch `dst' unless it's returning 1.
 
230
 *      (2) :: in a full address is silently ignored.
 
231
 * credit:
 
232
 *      inspired by Mark Andrews.
 
233
 * author:
 
234
 *      Paul Vixie, 1996.
 
235
 */
 
236
static int
 
237
inet_pton6(src, dst)
 
238
        const char *src;
 
239
        u_char *dst;
 
240
{
 
241
        static const char xdigits_l[] = "0123456789abcdef",
 
242
                          xdigits_u[] = "0123456789ABCDEF";
 
243
        u_char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
 
244
        const char *xdigits, *curtok;
 
245
        int ch, saw_xdigit;
 
246
        u_int val;
 
247
 
 
248
        memset((tp = tmp), '\0', IN6ADDRSZ);
 
249
        endp = tp + IN6ADDRSZ;
 
250
        colonp = NULL;
 
251
        /* Leading :: requires some special handling. */
 
252
        if (*src == ':')
 
253
                if (*++src != ':')
 
254
                        return (0);
 
255
        curtok = src;
 
256
        saw_xdigit = 0;
 
257
        val = 0;
 
258
        while ((ch = *src++) != '\0') {
 
259
                const char *pch;
 
260
 
 
261
                if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
 
262
                        pch = strchr((xdigits = xdigits_u), ch);
 
263
                if (pch != NULL) {
 
264
                        val <<= 4;
 
265
                        val |= (pch - xdigits);
 
266
                        if (val > 0xffff)
 
267
                                return (0);
 
268
                        saw_xdigit = 1;
 
269
                        continue;
 
270
                }
 
271
                if (ch == ':') {
 
272
                        curtok = src;
 
273
                        if (!saw_xdigit) {
 
274
                                if (colonp)
 
275
                                        return (0);
 
276
                                colonp = tp;
 
277
                                continue;
 
278
                        } else if (*src == '\0')
 
279
                                return (0);
 
280
                        if (tp + INT16SZ > endp)
 
281
                                return (0);
 
282
                        *tp++ = (u_char) (val >> 8) & 0xff;
 
283
                        *tp++ = (u_char) val & 0xff;
 
284
                        saw_xdigit = 0;
 
285
                        val = 0;
 
286
                        continue;
 
287
                }
 
288
                if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
 
289
                    inet_pton4(curtok, tp, 1) > 0) {
 
290
                        tp += INADDRSZ;
 
291
                        saw_xdigit = 0;
 
292
                        break;  /* '\0' was seen by inet_pton4(). */
 
293
                }
 
294
                return (0);
 
295
        }
 
296
        if (saw_xdigit) {
 
297
                if (tp + INT16SZ > endp)
 
298
                        return (0);
 
299
                *tp++ = (u_char) (val >> 8) & 0xff;
 
300
                *tp++ = (u_char) val & 0xff;
 
301
        }
 
302
        if (colonp != NULL) {
 
303
                /*
 
304
                 * Since some memmove()'s erroneously fail to handle
 
305
                 * overlapping regions, we'll do the shift by hand.
 
306
                 */
 
307
                const int n = tp - colonp;
 
308
                int i;
 
309
 
 
310
                if (tp == endp)
 
311
                        return (0);
 
312
                for (i = 1; i <= n; i++) {
 
313
                        endp[- i] = colonp[n - i];
 
314
                        colonp[n - i] = 0;
 
315
                }
 
316
                tp = endp;
 
317
        }
 
318
        if (tp != endp)
 
319
                return (0);
 
320
        memcpy(dst, tmp, IN6ADDRSZ);
 
321
        return (1);
 
322
}
 
323
#endif
 
324
 
 
325
#endif /* HAVE_INET_PTON */