~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to lib/replace/inet_pton.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 1996-2001  Internet Software Consortium.
 
3
 *
 
4
 * Permission to use, copy, modify, and distribute this software for any
 
5
 * purpose with or without fee is hereby granted, provided that the above
 
6
 * copyright notice and this permission notice appear in all copies.
 
7
 *
 
8
 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
 
9
 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
 
10
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
 
11
 * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
 
12
 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
 
13
 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
 
14
 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
 
15
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
16
 */
 
17
 
 
18
#include "replace.h"
 
19
#include "system/network.h"
 
20
 
 
21
#define NS_INT16SZ       2
 
22
#define NS_INADDRSZ      4
 
23
#define NS_IN6ADDRSZ    16
 
24
 
 
25
/*
 
26
 * WARNING: Don't even consider trying to compile this on a system where
 
27
 * sizeof(int) < 4.  sizeof(int) > 4 is fine; all the world's not a VAX.
 
28
 */
 
29
 
 
30
static int inet_pton4(const char *src, unsigned char *dst);
 
31
#ifdef AF_INET6
 
32
static int inet_pton6(const char *src, unsigned char *dst);
 
33
#endif
 
34
 
 
35
/* int
 
36
 * inet_pton(af, src, dst)
 
37
 *      convert from presentation format (which usually means ASCII printable)
 
38
 *      to network format (which is usually some kind of binary format).
 
39
 * return:
 
40
 *      1 if the address was valid for the specified address family
 
41
 *      0 if the address wasn't valid (`dst' is untouched in this case)
 
42
 *      -1 if some other error occurred (`dst' is untouched in this case, too)
 
43
 * author:
 
44
 *      Paul Vixie, 1996.
 
45
 */
 
46
int
 
47
rep_inet_pton(int af,
 
48
          const char *src,
 
49
          void *dst)
 
50
{
 
51
        switch (af) {
 
52
        case AF_INET:
 
53
                return (inet_pton4(src, dst));
 
54
#ifdef AF_INET6
 
55
        case AF_INET6:
 
56
                return (inet_pton6(src, dst));
 
57
#endif
 
58
        default:
 
59
                errno = EAFNOSUPPORT;
 
60
                return (-1);
 
61
        }
 
62
        /* NOTREACHED */
 
63
}
 
64
 
 
65
/* int
 
66
 * inet_pton4(src, dst)
 
67
 *      like inet_aton() but without all the hexadecimal and shorthand.
 
68
 * return:
 
69
 *      1 if `src' is a valid dotted quad, else 0.
 
70
 * notice:
 
71
 *      does not touch `dst' unless it's returning 1.
 
72
 * author:
 
73
 *      Paul Vixie, 1996.
 
74
 */
 
75
static int
 
76
inet_pton4(src, dst)
 
77
        const char *src;
 
78
        unsigned char *dst;
 
79
{
 
80
        static const char digits[] = "0123456789";
 
81
        int saw_digit, octets, ch;
 
82
        unsigned char tmp[NS_INADDRSZ], *tp;
 
83
 
 
84
        saw_digit = 0;
 
85
        octets = 0;
 
86
        *(tp = tmp) = 0;
 
87
        while ((ch = *src++) != '\0') {
 
88
                const char *pch;
 
89
 
 
90
                if ((pch = strchr(digits, ch)) != NULL) {
 
91
                        unsigned int new = *tp * 10 + (pch - digits);
 
92
 
 
93
                        if (new > 255)
 
94
                                return (0);
 
95
                        *tp = new;
 
96
                        if (! saw_digit) {
 
97
                                if (++octets > 4)
 
98
                                        return (0);
 
99
                                saw_digit = 1;
 
100
                        }
 
101
                } else if (ch == '.' && saw_digit) {
 
102
                        if (octets == 4)
 
103
                                return (0);
 
104
                        *++tp = 0;
 
105
                        saw_digit = 0;
 
106
                } else
 
107
                        return (0);
 
108
        }
 
109
        if (octets < 4)
 
110
                return (0);
 
111
        memcpy(dst, tmp, NS_INADDRSZ);
 
112
        return (1);
 
113
}
 
114
 
 
115
/* int
 
116
 * inet_pton6(src, dst)
 
117
 *      convert presentation level address to network order binary form.
 
118
 * return:
 
119
 *      1 if `src' is a valid [RFC1884 2.2] address, else 0.
 
120
 * notice:
 
121
 *      (1) does not touch `dst' unless it's returning 1.
 
122
 *      (2) :: in a full address is silently ignored.
 
123
 * credit:
 
124
 *      inspired by Mark Andrews.
 
125
 * author:
 
126
 *      Paul Vixie, 1996.
 
127
 */
 
128
#ifdef AF_INET6
 
129
static int
 
130
inet_pton6(src, dst)
 
131
        const char *src;
 
132
        unsigned char *dst;
 
133
{
 
134
        static const char xdigits_l[] = "0123456789abcdef",
 
135
                          xdigits_u[] = "0123456789ABCDEF";
 
136
        unsigned char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
 
137
        const char *xdigits, *curtok;
 
138
        int ch, saw_xdigit;
 
139
        unsigned int val;
 
140
 
 
141
        memset((tp = tmp), '\0', NS_IN6ADDRSZ);
 
142
        endp = tp + NS_IN6ADDRSZ;
 
143
        colonp = NULL;
 
144
        /* Leading :: requires some special handling. */
 
145
        if (*src == ':')
 
146
                if (*++src != ':')
 
147
                        return (0);
 
148
        curtok = src;
 
149
        saw_xdigit = 0;
 
150
        val = 0;
 
151
        while ((ch = *src++) != '\0') {
 
152
                const char *pch;
 
153
 
 
154
                if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
 
155
                        pch = strchr((xdigits = xdigits_u), ch);
 
156
                if (pch != NULL) {
 
157
                        val <<= 4;
 
158
                        val |= (pch - xdigits);
 
159
                        if (val > 0xffff)
 
160
                                return (0);
 
161
                        saw_xdigit = 1;
 
162
                        continue;
 
163
                }
 
164
                if (ch == ':') {
 
165
                        curtok = src;
 
166
                        if (!saw_xdigit) {
 
167
                                if (colonp)
 
168
                                        return (0);
 
169
                                colonp = tp;
 
170
                                continue;
 
171
                        }
 
172
                        if (tp + NS_INT16SZ > endp)
 
173
                                return (0);
 
174
                        *tp++ = (unsigned char) (val >> 8) & 0xff;
 
175
                        *tp++ = (unsigned char) val & 0xff;
 
176
                        saw_xdigit = 0;
 
177
                        val = 0;
 
178
                        continue;
 
179
                }
 
180
                if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
 
181
                    inet_pton4(curtok, tp) > 0) {
 
182
                        tp += NS_INADDRSZ;
 
183
                        saw_xdigit = 0;
 
184
                        break;  /* '\0' was seen by inet_pton4(). */
 
185
                }
 
186
                return (0);
 
187
        }
 
188
        if (saw_xdigit) {
 
189
                if (tp + NS_INT16SZ > endp)
 
190
                        return (0);
 
191
                *tp++ = (unsigned char) (val >> 8) & 0xff;
 
192
                *tp++ = (unsigned char) val & 0xff;
 
193
        }
 
194
        if (colonp != NULL) {
 
195
                /*
 
196
                 * Since some memmove()'s erroneously fail to handle
 
197
                 * overlapping regions, we'll do the shift by hand.
 
198
                 */
 
199
                const int n = tp - colonp;
 
200
                int i;
 
201
 
 
202
                for (i = 1; i <= n; i++) {
 
203
                        endp[- i] = colonp[n - i];
 
204
                        colonp[n - i] = 0;
 
205
                }
 
206
                tp = endp;
 
207
        }
 
208
        if (tp != endp)
 
209
                return (0);
 
210
        memcpy(dst, tmp, NS_IN6ADDRSZ);
 
211
        return (1);
 
212
}
 
213
#endif