OSDN Git Service

2013.10.24
[uclinux-h8/uClinux-dist.git] / freeswan / lib / 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.8 2000/09/12 04:56:39 henry 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);
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 static size_t reverse62(const unsigned char *s, size_t len, char *b, char **dp);
30
31 /*
32  - addrtot - convert binary address to text (dotted decimal or IPv6 string)
33  */
34 size_t                          /* space needed for full conversion */
35 addrtot(src, format, dst, dstlen)
36 const ip_address *src;
37 int format;                     /* character */
38 char *dst;                      /* need not be valid if dstlen is 0 */
39 size_t dstlen;
40 {
41         const unsigned char *b;
42         size_t n;
43         char buf[1+ADDRTOT_BUF+1];      /* :address: */
44         char *p;
45         int t = addrtypeof(src);
46 #       define  TF(t, f)        (((t)<<8) | (f))
47
48         n = addrbytesptr(src, &b);
49         if (n == 0)
50                 return 0;
51
52         switch (TF(t, format)) {
53         case TF(AF_INET, 0):
54                 n = normal4(b, n, buf, &p);
55                 break;
56         case TF(AF_INET6, 0):
57                 n = normal6(b, n, buf, &p);
58                 break;
59         case TF(AF_INET, 'r'):
60                 n = reverse4(b, n, buf, &p);
61                 break;
62         case TF(AF_INET6, 'r'):
63                 n = reverse6(b, n, buf, &p);
64                 break;
65         case TF(AF_INET6, 'R'):
66                 n = reverse62(b, n, buf, &p);
67                 break;
68         default:                /* including (AF_INET, 'R') */
69                 return 0;
70                 break;
71         }
72
73         if (dstlen > 0) {
74                 if (dstlen < n)
75                         p[dstlen - 1] = '\0';
76                 strcpy(dst, p);
77         }
78         return n;
79 }
80
81 /*
82  - normal4 - normal IPv4 address-text conversion
83  */
84 static size_t                   /* size of text, including NUL */
85 normal4(srcp, srclen, buf, dstp)
86 const unsigned char *srcp;
87 size_t srclen;
88 char *buf;                      /* guaranteed large enough */
89 char **dstp;                    /* where to put result pointer */
90 {
91         int i;
92         char *p;
93
94         if (srclen != IP4BYTES) /* "can't happen" */
95                 return 0;
96         p = buf;
97         for (i = 0; i < IP4BYTES; i++) {
98                 p += ultot(srcp[i], 10, p, PERBYTE);
99                 if (i != IP4BYTES - 1)
100                         *(p-1) = '.';   /* overwrites the NUL */
101         }
102         *dstp = buf;
103         return p - buf;
104 }
105
106 /*
107  - normal6 - normal IPv6 address-text conversion
108  */
109 static size_t                   /* size of text, including NUL */
110 normal6(srcp, srclen, buf, dstp)
111 const unsigned char *srcp;
112 size_t srclen;
113 char *buf;                      /* guaranteed large enough, plus 2 */
114 char **dstp;                    /* where to put result pointer */
115 {
116         int i;
117         unsigned long piece;
118         char *p;
119         char *q;
120
121         if (srclen != IP6BYTES) /* "can't happen" */
122                 return 0;
123         p = buf;
124         *p++ = ':';
125         for (i = 0; i < IP6BYTES/2; i++) {
126                 piece = (srcp[2*i] << 8) + srcp[2*i + 1];
127                 p += ultot(piece, 16, p, 5);    /* 5 = abcd + NUL */
128                 *(p-1) = ':';   /* overwrites the NUL */
129         }
130         *p = '\0';
131         q = strstr(buf, ":0:0:");
132         if (q != NULL) {        /* zero squishing is possible */
133                 p = q + 1;
134                 while (*p == '0' && *(p+1) == ':')
135                         p += 2;
136                 q++;
137                 *q++ = ':';     /* overwrite first 0 */
138                 while (*p != '\0')
139                         *q++ = *p++;
140                 *q = '\0';
141                 if (!(*(q-1) == ':' && *(q-2) == ':'))
142                         *--q = '\0';    /* strip final : unless :: */
143                 p = buf;
144                 if (!(*p == ':' && *(p+1) == ':'))
145                         p++;    /* skip initial : unless :: */
146         } else {
147                 q = p;
148                 *--q = '\0';    /* strip final : */
149                 p = buf + 1;    /* skip initial : */
150         }
151         *dstp = p;
152         return q - p + 1;
153 }
154
155 /*
156  - reverse4 - IPv4 reverse-lookup conversion
157  */
158 static size_t                   /* size of text, including NUL */
159 reverse4(srcp, srclen, buf, dstp)
160 const unsigned char *srcp;
161 size_t srclen;
162 char *buf;                      /* guaranteed large enough */
163 char **dstp;                    /* where to put result pointer */
164 {
165         int i;
166         char *p;
167
168         if (srclen != IP4BYTES) /* "can't happen" */
169                 return 0;
170         p = buf;
171         for (i = IP4BYTES-1; i >= 0; i--) {
172                 p += ultot(srcp[i], 10, p, PERBYTE);
173                 *(p-1) = '.';   /* overwrites the NUL */
174         }
175         strcpy(p, "IN-ADDR.ARPA.");
176         *dstp = buf;
177         return strlen(buf) + 1;
178 }
179
180 /*
181  - reverse62 - obsolete IPv6 reverse-lookup conversion (RFC 1886)
182  * A trifle inefficient, really shouldn't use ultot...
183  */
184 static size_t                   /* size of text, including NUL */
185 reverse62(srcp, srclen, buf, dstp)
186 const unsigned char *srcp;
187 size_t srclen;
188 char *buf;                      /* guaranteed large enough */
189 char **dstp;                    /* where to put result pointer */
190 {
191         int i;
192         unsigned long piece;
193         char *p;
194
195         if (srclen != IP6BYTES) /* "can't happen" */
196                 return 0;
197         p = buf;
198         for (i = IP6BYTES-1; i >= 0; i--) {
199                 piece = srcp[i];
200                 p += ultot(piece&0xf, 16, p, 2);
201                 *(p-1) = '.';
202                 p += ultot(piece>>4, 16, p, 2);
203                 *(p-1) = '.';
204         }
205         strcpy(p, "IP6.INT.");
206         *dstp = buf;
207         return strlen(buf) + 1;
208 }
209
210 /*
211  - reverse6 - modern IPv6 reverse-lookup conversion (RFC 2874)
212  */
213 static size_t                   /* size of text, including NUL */
214 reverse6(srcp, srclen, buf, dstp)
215 const unsigned char *srcp;
216 size_t srclen;
217 char *buf;                      /* guaranteed large enough */
218 char **dstp;                    /* where to put result pointer */
219 {
220         char *p;
221
222         if (srclen != IP6BYTES) /* "can't happen" */
223                 return 0;
224         strcpy(buf, "\\[x");
225         p = buf + strlen(buf);
226         (void) datatot((const char *)srcp, srclen, 16, p, IP6BYTES*2 + 1);
227         strcat(buf, "].IP6.ARPA.");     /* leave count implicit */
228         *dstp = buf;
229         return strlen(buf) + 1;
230 }