3 * Copyright (C) 2000 Henry Spencer.
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>.
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.
15 * RCSID $Id: addrtot.c,v 1.8 2000/09/12 04:56:39 henry Exp $
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 */
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);
32 - addrtot - convert binary address to text (dotted decimal or IPv6 string)
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 */
41 const unsigned char *b;
43 char buf[1+ADDRTOT_BUF+1]; /* :address: */
45 int t = addrtypeof(src);
46 # define TF(t, f) (((t)<<8) | (f))
48 n = addrbytesptr(src, &b);
52 switch (TF(t, format)) {
54 n = normal4(b, n, buf, &p);
57 n = normal6(b, n, buf, &p);
59 case TF(AF_INET, 'r'):
60 n = reverse4(b, n, buf, &p);
62 case TF(AF_INET6, 'r'):
63 n = reverse6(b, n, buf, &p);
65 case TF(AF_INET6, 'R'):
66 n = reverse62(b, n, buf, &p);
68 default: /* including (AF_INET, 'R') */
82 - normal4 - normal IPv4 address-text conversion
84 static size_t /* size of text, including NUL */
85 normal4(srcp, srclen, buf, dstp)
86 const unsigned char *srcp;
88 char *buf; /* guaranteed large enough */
89 char **dstp; /* where to put result pointer */
94 if (srclen != IP4BYTES) /* "can't happen" */
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 */
107 - normal6 - normal IPv6 address-text conversion
109 static size_t /* size of text, including NUL */
110 normal6(srcp, srclen, buf, dstp)
111 const unsigned char *srcp;
113 char *buf; /* guaranteed large enough, plus 2 */
114 char **dstp; /* where to put result pointer */
121 if (srclen != IP6BYTES) /* "can't happen" */
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 */
131 q = strstr(buf, ":0:0:");
132 if (q != NULL) { /* zero squishing is possible */
134 while (*p == '0' && *(p+1) == ':')
137 *q++ = ':'; /* overwrite first 0 */
141 if (!(*(q-1) == ':' && *(q-2) == ':'))
142 *--q = '\0'; /* strip final : unless :: */
144 if (!(*p == ':' && *(p+1) == ':'))
145 p++; /* skip initial : unless :: */
148 *--q = '\0'; /* strip final : */
149 p = buf + 1; /* skip initial : */
156 - reverse4 - IPv4 reverse-lookup conversion
158 static size_t /* size of text, including NUL */
159 reverse4(srcp, srclen, buf, dstp)
160 const unsigned char *srcp;
162 char *buf; /* guaranteed large enough */
163 char **dstp; /* where to put result pointer */
168 if (srclen != IP4BYTES) /* "can't happen" */
171 for (i = IP4BYTES-1; i >= 0; i--) {
172 p += ultot(srcp[i], 10, p, PERBYTE);
173 *(p-1) = '.'; /* overwrites the NUL */
175 strcpy(p, "IN-ADDR.ARPA.");
177 return strlen(buf) + 1;
181 - reverse62 - obsolete IPv6 reverse-lookup conversion (RFC 1886)
182 * A trifle inefficient, really shouldn't use ultot...
184 static size_t /* size of text, including NUL */
185 reverse62(srcp, srclen, buf, dstp)
186 const unsigned char *srcp;
188 char *buf; /* guaranteed large enough */
189 char **dstp; /* where to put result pointer */
195 if (srclen != IP6BYTES) /* "can't happen" */
198 for (i = IP6BYTES-1; i >= 0; i--) {
200 p += ultot(piece&0xf, 16, p, 2);
202 p += ultot(piece>>4, 16, p, 2);
205 strcpy(p, "IP6.INT.");
207 return strlen(buf) + 1;
211 - reverse6 - modern IPv6 reverse-lookup conversion (RFC 2874)
213 static size_t /* size of text, including NUL */
214 reverse6(srcp, srclen, buf, dstp)
215 const unsigned char *srcp;
217 char *buf; /* guaranteed large enough */
218 char **dstp; /* where to put result pointer */
222 if (srclen != IP6BYTES) /* "can't happen" */
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 */
229 return strlen(buf) + 1;