]> git.ipfire.org Git - people/ms/strongswan.git/blob - linux/lib/libfreeswan/addrtot.c
f229789f0cb55d2ef8d3d16182c3f95fed6a8d93
[people/ms/strongswan.git] / linux / lib / libfreeswan / addrtot.c
1 /*
2 * addresses to text
3 * Copyright (C) 2000 Henry Spencer.
4 *
5 * This library is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU Library General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
9 *
10 * This library is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
13 * License for more details.
14 *
15 * RCSID $Id: addrtot.c,v 1.1 2004/03/15 20:35:25 as Exp $
16 */
17 #include "internal.h"
18 #include "freeswan.h"
19
20 #define IP4BYTES 4 /* bytes in an IPv4 address */
21 #define PERBYTE 4 /* three digits plus a dot or NUL */
22 #define IP6BYTES 16 /* bytes in an IPv6 address */
23
24 /* forwards */
25 static size_t normal4(const unsigned char *s, size_t len, char *b, char **dp);
26 static size_t normal6(const unsigned char *s, size_t len, char *b, char **dp, int squish);
27 static size_t reverse4(const unsigned char *s, size_t len, char *b, char **dp);
28 static size_t reverse6(const unsigned char *s, size_t len, char *b, char **dp);
29
30 /*
31 - addrtot - convert binary address to text (dotted decimal or IPv6 string)
32 */
33 size_t /* space needed for full conversion */
34 addrtot(src, format, dst, dstlen)
35 const ip_address *src;
36 int format; /* character */
37 char *dst; /* need not be valid if dstlen is 0 */
38 size_t dstlen;
39 {
40 const unsigned char *b;
41 size_t n;
42 char buf[1+ADDRTOT_BUF+1]; /* :address: */
43 char *p;
44 int t = addrtypeof(src);
45 # define TF(t, f) (((t)<<8) | (f))
46
47 n = addrbytesptr(src, &b);
48 if (n == 0)
49 return 0;
50
51 switch (TF(t, format)) {
52 case TF(AF_INET, 0):
53 n = normal4(b, n, buf, &p);
54 break;
55 case TF(AF_INET6, 0):
56 n = normal6(b, n, buf, &p, 1);
57 break;
58 case TF(AF_INET, 'Q'):
59 n = normal4(b, n, buf, &p);
60 break;
61 case TF(AF_INET6, 'Q'):
62 n = normal6(b, n, buf, &p, 0);
63 break;
64 case TF(AF_INET, 'r'):
65 n = reverse4(b, n, buf, &p);
66 break;
67 case TF(AF_INET6, 'r'):
68 n = reverse6(b, n, buf, &p);
69 break;
70 default: /* including (AF_INET, 'R') */
71 return 0;
72 break;
73 }
74
75 if (dstlen > 0) {
76 if (dstlen < n)
77 p[dstlen - 1] = '\0';
78 strcpy(dst, p);
79 }
80 return n;
81 }
82
83 /*
84 - normal4 - normal IPv4 address-text conversion
85 */
86 static size_t /* size of text, including NUL */
87 normal4(srcp, srclen, buf, dstp)
88 const unsigned char *srcp;
89 size_t srclen;
90 char *buf; /* guaranteed large enough */
91 char **dstp; /* where to put result pointer */
92 {
93 int i;
94 char *p;
95
96 if (srclen != IP4BYTES) /* "can't happen" */
97 return 0;
98 p = buf;
99 for (i = 0; i < IP4BYTES; i++) {
100 p += ultot(srcp[i], 10, p, PERBYTE);
101 if (i != IP4BYTES - 1)
102 *(p-1) = '.'; /* overwrites the NUL */
103 }
104 *dstp = buf;
105 return p - buf;
106 }
107
108 /*
109 - normal6 - normal IPv6 address-text conversion
110 */
111 static size_t /* size of text, including NUL */
112 normal6(srcp, srclen, buf, dstp, squish)
113 const unsigned char *srcp;
114 size_t srclen;
115 char *buf; /* guaranteed large enough, plus 2 */
116 char **dstp; /* where to put result pointer */
117 int squish; /* whether to squish out 0:0 */
118 {
119 int i;
120 unsigned long piece;
121 char *p;
122 char *q;
123
124 if (srclen != IP6BYTES) /* "can't happen" */
125 return 0;
126 p = buf;
127 *p++ = ':';
128 for (i = 0; i < IP6BYTES/2; i++) {
129 piece = (srcp[2*i] << 8) + srcp[2*i + 1];
130 p += ultot(piece, 16, p, 5); /* 5 = abcd + NUL */
131 *(p-1) = ':'; /* overwrites the NUL */
132 }
133 *p = '\0';
134 q = strstr(buf, ":0:0:");
135 if (squish && q != NULL) { /* zero squishing is possible */
136 p = q + 1;
137 while (*p == '0' && *(p+1) == ':')
138 p += 2;
139 q++;
140 *q++ = ':'; /* overwrite first 0 */
141 while (*p != '\0')
142 *q++ = *p++;
143 *q = '\0';
144 if (!(*(q-1) == ':' && *(q-2) == ':'))
145 *--q = '\0'; /* strip final : unless :: */
146 p = buf;
147 if (!(*p == ':' && *(p+1) == ':'))
148 p++; /* skip initial : unless :: */
149 } else {
150 q = p;
151 *--q = '\0'; /* strip final : */
152 p = buf + 1; /* skip initial : */
153 }
154 *dstp = p;
155 return q - p + 1;
156 }
157
158 /*
159 - reverse4 - IPv4 reverse-lookup conversion
160 */
161 static size_t /* size of text, including NUL */
162 reverse4(srcp, srclen, buf, dstp)
163 const unsigned char *srcp;
164 size_t srclen;
165 char *buf; /* guaranteed large enough */
166 char **dstp; /* where to put result pointer */
167 {
168 int i;
169 char *p;
170
171 if (srclen != IP4BYTES) /* "can't happen" */
172 return 0;
173 p = buf;
174 for (i = IP4BYTES-1; i >= 0; i--) {
175 p += ultot(srcp[i], 10, p, PERBYTE);
176 *(p-1) = '.'; /* overwrites the NUL */
177 }
178 strcpy(p, "IN-ADDR.ARPA.");
179 *dstp = buf;
180 return strlen(buf) + 1;
181 }
182
183 /*
184 - reverse6 - IPv6 reverse-lookup conversion (RFC 1886)
185 * A trifle inefficient, really shouldn't use ultot...
186 */
187 static size_t /* size of text, including NUL */
188 reverse6(srcp, srclen, buf, dstp)
189 const unsigned char *srcp;
190 size_t srclen;
191 char *buf; /* guaranteed large enough */
192 char **dstp; /* where to put result pointer */
193 {
194 int i;
195 unsigned long piece;
196 char *p;
197
198 if (srclen != IP6BYTES) /* "can't happen" */
199 return 0;
200 p = buf;
201 for (i = IP6BYTES-1; i >= 0; i--) {
202 piece = srcp[i];
203 p += ultot(piece&0xf, 16, p, 2);
204 *(p-1) = '.';
205 p += ultot(piece>>4, 16, p, 2);
206 *(p-1) = '.';
207 }
208 strcpy(p, "IP6.ARPA.");
209 *dstp = buf;
210 return strlen(buf) + 1;
211 }
212
213 /*
214 - reverse6 - modern IPv6 reverse-lookup conversion (RFC 2874)
215 * this version removed as it was obsoleted in the end.
216 */
217
218 #ifdef ADDRTOT_MAIN
219
220 #include <stdio.h>
221 #include <sys/socket.h>
222 #include <netinet/in.h>
223 #include <arpa/inet.h>
224
225 void regress(void);
226
227 int
228 main(int argc, char *argv[])
229 {
230 if (argc < 2) {
231 fprintf(stderr, "Usage: %s {addr|net/mask|begin...end|-r}\n",
232 argv[0]);
233 exit(2);
234 }
235
236 if (strcmp(argv[1], "-r") == 0) {
237 regress();
238 fprintf(stderr, "regress() returned?!?\n");
239 exit(1);
240 }
241 exit(0);
242 }
243
244 struct rtab {
245 char *input;
246 char format;
247 char *output; /* NULL means error expected */
248 } rtab[] = {
249 {"1.2.3.0", 0, "1.2.3.0"},
250 {"1:2::3:4", 0, "1:2::3:4"},
251 {"1:2::3:4", 'Q', "1:2:0:0:0:0:3:4"},
252 {"1:2:0:0:3:4:0:0", 0, "1:2::3:4:0:0"},
253 {"1.2.3.4", 'r' , "4.3.2.1.IN-ADDR.ARPA."},
254 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f 0 1 2 3 4 5 6 7 8 9 a b c d e f */
255 {"1:2::3:4", 'r', "4.0.0.0.3.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.2.0.0.0.1.0.0.0.IP6.ARPA."},
256 {NULL, 0, NULL}
257 };
258
259 void
260 regress()
261 {
262 struct rtab *r;
263 int status = 0;
264 ip_address a;
265 char in[100];
266 char buf[100];
267 const char *oops;
268 size_t n;
269
270 for (r = rtab; r->input != NULL; r++) {
271 strcpy(in, r->input);
272
273 /* convert it *to* internal format */
274 oops = ttoaddr(in, strlen(in), 0, &a);
275
276 /* now convert it back */
277
278 n = addrtot(&a, r->format, buf, sizeof(buf));
279
280 if (n == 0 && r->output == NULL)
281 {} /* okay, error expected */
282
283 else if (n == 0) {
284 printf("`%s' atoasr failed\n", r->input);
285 status = 1;
286
287 } else if (r->output == NULL) {
288 printf("`%s' atoasr succeeded unexpectedly '%c'\n",
289 r->input, r->format);
290 status = 1;
291 } else {
292 if (strcasecmp(r->output, buf) != 0) {
293 printf("`%s' '%c' gave `%s', expected `%s'\n",
294 r->input, r->format, buf, r->output);
295 status = 1;
296 }
297 }
298 }
299 exit(status);
300 }
301
302 #endif /* ADDRTOT_MAIN */