OSDN Git Service

2013.10.24
[uclinux-h8/uClinux-dist.git] / freeswan / lib / ttosubnet.c
1 /*
2  * convert from text form of subnet specification to binary
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: ttosubnet.c,v 1.5 2000/08/17 04:14:27 henry Exp $
16  */
17 #include "internal.h"
18 #include "freeswan.h"
19
20 #ifndef DEFAULTSUBNET
21 #define DEFAULTSUBNET   "%default"
22 #endif
23
24 /*
25  - ttosubnet - convert text "addr/mask" to address and mask
26  * Mask can be integer bit count.
27  */
28 err_t
29 ttosubnet(src, srclen, af, dst)
30 const char *src;
31 size_t srclen;                  /* 0 means "apply strlen" */
32 int af;                         /* AF_INET or AF_INET6 */
33 ip_subnet *dst;
34 {
35         const char *slash;
36         const char *mask;
37         size_t mlen;
38         const char *oops;
39         unsigned long bc;
40         static char def[] = DEFAULTSUBNET;
41 #       define  DEFLEN  (sizeof(def) - 1)       /* -1 for NUL */
42         static char defis4[] = "0/0";
43 #       define  DEFIS4LEN       (sizeof(defis4) - 1)
44         static char defis6[] = "::/0";
45 #       define  DEFIS6LEN       (sizeof(defis6) - 1)
46         ip_address addrtmp;
47         ip_address masktmp;
48         int nbits;
49         int i;
50
51         if (srclen == 0)
52                 srclen = strlen(src);
53         if (srclen == 0)
54                 return "empty string";
55
56         switch (af) {
57         case AF_INET:
58                 nbits = 32;
59                 break;
60         case AF_INET6:
61                 nbits = 128;
62                 break;
63         default:
64                 return "unknown address family in ttosubnet";
65                 break;
66         }
67
68         if (srclen == DEFLEN && strncmp(src, def, srclen) == 0) {
69                 src = (af == AF_INET) ? defis4 : defis6;
70                 srclen = (af == AF_INET) ? DEFIS4LEN : DEFIS6LEN;
71         }
72
73         slash = memchr(src, '/', srclen);
74         if (slash == NULL)
75                 return "no / in subnet specification";
76         mask = slash + 1;
77         mlen = srclen - (mask - src);
78
79         oops = ttoaddr(src, slash-src, af, &addrtmp);
80         if (oops != NULL)
81                 return oops;
82
83         oops = ttoul(mask, mlen, 10, &bc);
84         if (oops == NULL) {
85                 /* ttoul succeeded, it's a bit-count mask */
86                 if (bc > nbits)
87                         return "subnet mask bit count too large";
88                 i = bc;
89         } else {
90                 oops = ttoaddr(mask, mlen, af, &masktmp);
91                 if (oops != NULL)
92                         return oops;
93                 i = masktocount(&masktmp);
94                 if (i < 0)
95                         return "non-contiguous or otherwise erroneous mask";
96         }
97
98         return initsubnet(&addrtmp, i, '0', dst);
99 }
100
101
102
103 #ifdef TTOSUBNET_MAIN
104
105 #include <stdio.h>
106
107 void regress();
108
109 int
110 main(argc, argv)
111 int argc;
112 char *argv[];
113 {
114         ip_address a;
115         ip_subnet s;
116         char buf[100];
117         char buf2[100];
118         const char *oops;
119         size_t n;
120         int af;
121         char *p;
122
123         if (argc < 2) {
124                 fprintf(stderr, "Usage: %s [-6] addr/mask\n", argv[0]);
125                 fprintf(stderr, "   or: %s -r\n", argv[0]);
126                 exit(2);
127         }
128
129         if (strcmp(argv[1], "-r") == 0) {
130                 regress();
131                 fprintf(stderr, "regress() returned?!?\n");
132                 exit(1);
133         }
134
135         af = AF_INET;
136         p = argv[1];
137         if (strcmp(argv[1], "-6") == 0) {
138                 af = AF_INET6;
139                 p = argv[2];
140         } else if (strchr(argv[1], ':') != NULL)
141                 af = AF_INET6;
142
143         oops = ttosubnet(p, 0, af, &s);
144         if (oops != NULL) {
145                 fprintf(stderr, "%s: conversion failed: %s\n", argv[0], oops);
146                 exit(1);
147         }
148         n = subnettot(&s, 0, buf, sizeof(buf));
149         if (n > sizeof(buf)) {
150                 fprintf(stderr, "%s: reverse conversion of ", argv[0]);
151                 (void) addrtot(&s.addr, 0, buf2, sizeof(buf2));
152                 fprintf(stderr, "%s/", buf2);
153                 fprintf(stderr, "%d", s.maskbits);
154                 fprintf(stderr, " failed: need %ld bytes, have only %ld\n",
155                                                 (long)n, (long)sizeof(buf));
156                 exit(1);
157         }
158         printf("%s\n", buf);
159
160         exit(0);
161 }
162
163 struct rtab {
164         int family;
165         char *input;
166         char *output;                   /* NULL means error expected */
167 } rtab[] = {
168         4, "1.2.3.0/255.255.255.0",     "1.2.3.0/24",
169         4, "1.2.3.0/24",                "1.2.3.0/24",
170         4, "1.2.3.1/255.255.255.240",   "1.2.3.0/28",
171         4, "1.2.3.1/32",                "1.2.3.1/32",
172         4, "1.2.3.1/0",                 "0.0.0.0/0",
173 /*      4, "1.2.3.1/255.255.127.0",     "1.2.3.0/255.255.127.0",        */
174         4, "1.2.3.1/255.255.127.0",     NULL,
175         4, "128.009.000.032/32",        "128.9.0.32/32",
176         4, "128.0x9.0.32/32",           NULL,
177         4, "0x80090020/32",             "128.9.0.32/32",
178         4, "0x800x0020/32",             NULL,
179         4, "128.9.0.32/0xffFF0000",     "128.9.0.0/16",
180         4, "128.9.0.32/0xff0000FF",     NULL,
181         4, "128.9.0.32/0x0000ffFF",     NULL,
182         4, "128.9.0.32/0x00ffFF0000",   NULL,
183         4, "128.9.0.32/0xffFF",         NULL,
184         4, "128.9.0.32.27/32",          NULL,
185         4, "128.9.0k32/32",             NULL,
186         4, "328.9.0.32/32",             NULL,
187         4, "128.9..32/32",              NULL,
188         4, "10/8",                      "10.0.0.0/8",
189         4, "10.0/8",                    "10.0.0.0/8",
190         4, "10.0.0/8",                  "10.0.0.0/8",
191         4, "10.0.1/24",                 "10.0.1.0/24",
192         4, "_",                         NULL,
193         4, "_/_",                       NULL,
194         4, "1.2.3.1",                   NULL,
195         4, "1.2.3.1/_",                 NULL,
196         4, "1.2.3.1/24._",              NULL,
197         4, "1.2.3.1/99",                NULL,
198         4, "localhost./32",             "127.0.0.1/32",
199         4, "%default",                  "0.0.0.0/0",
200         6, "3049:1::8007:2040/0",       "::/0",
201         6, "3049:1::8007:2040/128",     "3049:1::8007:2040/128",
202         6, "3049:1::192.168.0.1/128", NULL,     /*"3049:1::c0a8:1/128",*/
203         6, "3049:1::8007::2040/128",    NULL,
204         6, "3049:1::8007:2040/ffff::0", "3049::/16",
205         6, "3049:1::8007:2040/64",      "3049:1::/64",
206         6, "3049:1::8007:2040/ffff::",  "3049::/16",
207         6, "3049:1::8007:2040/0000:ffff::0",    NULL,
208         6, "3049:1::8007:2040/ff1f::0", NULL,
209         6, "3049:1::8007:x:2040/128",   NULL,
210         6, "3049:1t::8007:2040/128",    NULL,
211         6, "3049:1::80071:2040/128",    NULL,
212         6, "::/21",                     "::/21",
213         6, "::1/128",                   "::1/128",
214         6, "1::/21",                    "1::/21",
215         6, "1::2/128",                  "1::2/128",
216         6, "1:0:0:0:0:0:0:2/128",       "1::2/128",
217         6, "1:0:0:0:3:0:0:2/128",       "1::3:0:0:2/128",
218         6, "1:0:0:3:0:0:0:2/128",       "1::3:0:0:0:2/128",
219         6, "1:0:3:0:0:0:0:2/128",       "1:0:3::2/128",
220         6, "abcd:ef01:2345:6789:0:00a:000:20/128",      "abcd:ef01:2345:6789:0:a:0:20/128",
221         6, "3049:1::8007:2040/ffff:ffff:",      NULL,
222         6, "3049:1::8007:2040/ffff:88::",       NULL,
223         6, "3049:12::9000:3200/ffff:fff0::",    "3049:10::/28",
224         6, "3049:12::9000:3200/28",     "3049:10::/28",
225         6, "3049:12::9000:3200/ff00:::",        NULL,
226         6, "3049:12::9000:3200/ffff:::",        NULL,
227         6, "3049:12::9000:3200/128_",   NULL,
228         6, "3049:12::9000:3200/",       NULL,
229         6, "%default",                  "::/0",
230         4, NULL,                        NULL
231 };
232
233 void
234 regress()
235 {
236         struct rtab *r;
237         int status = 0;
238         ip_address a;
239         ip_subnet s;
240         char in[100];
241         char buf[100];
242         const char *oops;
243         size_t n;
244         int af;
245
246         for (r = rtab; r->input != NULL; r++) {
247                 af = (r->family == 4) ? AF_INET : AF_INET6;
248                 strcpy(in, r->input);
249                 oops = ttosubnet(in, 0, af, &s);
250                 if (oops != NULL && r->output == NULL)
251                         {}              /* okay, error expected */
252                 else if (oops != NULL) {
253                         printf("`%s' ttosubnet failed: %s\n", r->input, oops);
254                         status = 1;
255                 } else if (r->output == NULL) {
256                         printf("`%s' ttosubnet succeeded unexpectedly\n",
257                                                                 r->input);
258                         status = 1;
259                 } else {
260                         n = subnettot(&s, 0, buf, sizeof(buf));
261                         if (n > sizeof(buf)) {
262                                 printf("`%s' subnettot failed:  need %ld\n",
263                                                         r->input, (long)n);
264                                 status = 1;
265                         } else if (strcmp(r->output, buf) != 0) {
266                                 printf("`%s' gave `%s', expected `%s'\n",
267                                                 r->input, buf, r->output);
268                                 status = 1;
269                         }
270                 }
271         }
272         exit(status);
273 }
274
275 #endif /* TTOSUBNET_MAIN */