OSDN Git Service

2013.10.24
[uclinux-h8/uClinux-dist.git] / freeswan / lib / atosubnet.c
1 /*
2  * convert from ASCII form of subnet specification to binary
3  * Copyright (C) 1998, 1999  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: atosubnet.c,v 1.12 2000/02/16 18:59:08 henry Exp $
16  */
17 #include "internal.h"
18 #include "freeswan.h"
19
20 #ifndef DEFAULTSUBNET
21 #define DEFAULTSUBNET   "%default"
22 #endif
23
24 /*
25  - atosubnet - convert ASCII "addr/mask" to address and mask
26  * Mask can be integer bit count.
27  */
28 const char *                    /* NULL for success, else string literal */
29 atosubnet(src, srclen, addrp, maskp)
30 const char *src;
31 size_t srclen;                  /* 0 means "apply strlen" */
32 struct in_addr *addrp;
33 struct in_addr *maskp;
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 defis[] = "0/0";
43 #       define  DEFILEN (sizeof(defis) - 1)
44
45         if (srclen == 0)
46                 srclen = strlen(src);
47         if (srclen == 0)
48                 return "empty string";
49
50         if (srclen == DEFLEN && strncmp(src, def, srclen) == 0) {
51                 src = defis;
52                 srclen = DEFILEN;
53         }
54
55         slash = memchr(src, '/', srclen);
56         if (slash == NULL)
57                 return "no / in subnet specification";
58         mask = slash + 1;
59         mlen = srclen - (mask - src);
60
61         oops = atoaddr(src, slash-src, addrp);
62         if (oops != NULL)
63                 return oops;
64
65         oops = atoul(mask, mlen, 10, &bc);
66         if (oops == NULL) {
67                 /* atoul succeeded, it's a bit-count mask */
68                 if (bc > ABITS)
69                         return "bit-count mask too large";
70 #ifdef NOLEADINGZEROS
71                 if (mlen > 1 && *mask == '0')
72                         return "octal not allowed in mask";
73 #endif /* NOLEADINGZEROS */
74                 *maskp = bitstomask((int)bc);
75         } else {
76                 oops = atoaddr(mask, mlen, maskp);
77                 if (oops != NULL)
78                         return oops;
79                 if (!goodmask(*maskp))
80                         return "non-contiguous mask";
81         }
82
83         addrp->s_addr &= maskp->s_addr;
84         return NULL;
85 }
86
87
88
89 #ifdef ATOSUBNET_MAIN
90
91 #include <stdio.h>
92
93 void regress();
94
95 int
96 main(argc, argv)
97 int argc;
98 char *argv[];
99 {
100         struct in_addr a;
101         struct in_addr m;
102         char buf[100];
103         const char *oops;
104         size_t n;
105
106         if (argc < 2) {
107                 fprintf(stderr, "Usage: %s {addr/mask|-r}\n", argv[0]);
108                 exit(2);
109         }
110
111         if (strcmp(argv[1], "-r") == 0) {
112                 regress();
113                 fprintf(stderr, "regress() returned?!?\n");
114                 exit(1);
115         }
116
117         oops = atosubnet(argv[1], 0, &a, &m);
118         if (oops != NULL) {
119                 fprintf(stderr, "%s: conversion failed: %s\n", argv[0], oops);
120                 exit(1);
121         }
122         n = subnettoa(a, m, 0, buf, sizeof(buf));
123         if (n > sizeof(buf)) {
124                 fprintf(stderr, "%s: reverse conversion of ", argv[0]);
125                 fprintf(stderr, "%s/", inet_ntoa(a));
126                 fprintf(stderr, "%s", inet_ntoa(m));
127                 fprintf(stderr, " failed: need %ld bytes, have only %ld\n",
128                                                 (long)n, (long)sizeof(buf));
129                 exit(1);
130         }
131         printf("%s\n", buf);
132
133         exit(0);
134 }
135
136 struct rtab {
137         char *input;
138         char *output;                   /* NULL means error expected */
139 } rtab[] = {
140         "1.2.3.0/255.255.255.0",        "1.2.3.0/24",
141         "1.2.3.0/24",                   "1.2.3.0/24",
142         "1.2.3.1/255.255.255.240",      "1.2.3.0/28",
143         "1.2.3.1/32",                   "1.2.3.1/32",
144         "1.2.3.1/0",                    "0.0.0.0/0",
145 /*      "1.2.3.1/255.255.127.0",        "1.2.3.0/255.255.127.0",        */
146         "1.2.3.1/255.255.127.0",        NULL,
147         "128.009.000.032/32",           "128.9.0.32/32",
148         "128.0x9.0.32/32",              NULL,
149         "0x80090020/32",                "128.9.0.32/32",
150         "0x800x0020/32",                NULL,
151         "128.9.0.32/0xffFF0000",        "128.9.0.0/16",
152         "128.9.0.32/0xff0000FF",        NULL,
153         "128.9.0.32/0x0000ffFF",        NULL,
154         "128.9.0.32/0x00ffFF0000",      NULL,
155         "128.9.0.32/0xffFF",            NULL,
156         "128.9.0.32.27/32",             NULL,
157         "128.9.0k32/32",                NULL,
158         "328.9.0.32/32",                NULL,
159         "128.9..32/32",                 NULL,
160         "10/8",                         "10.0.0.0/8",
161         "10.0/8",                       "10.0.0.0/8",
162         "10.0.0/8",                     "10.0.0.0/8",
163         "10.0.1/24",                    "10.0.1.0/24",
164         "_",                            NULL,
165         "_/_",                          NULL,
166         "1.2.3.1",                      NULL,
167         "1.2.3.1/_",                    NULL,
168         "1.2.3.1/24._",                 NULL,
169         "1.2.3.1/99",                   NULL,
170         "localhost./32",                "127.0.0.1/32",
171         "%default",                     "0.0.0.0/0",
172         NULL,                           NULL
173 };
174
175 void
176 regress()
177 {
178         struct rtab *r;
179         int status = 0;
180         struct in_addr a;
181         struct in_addr m;
182         char in[100];
183         char buf[100];
184         const char *oops;
185         size_t n;
186
187         for (r = rtab; r->input != NULL; r++) {
188                 strcpy(in, r->input);
189                 oops = atosubnet(in, 0, &a, &m);
190                 if (oops != NULL && r->output == NULL)
191                         {}              /* okay, error expected */
192                 else if (oops != NULL) {
193                         printf("`%s' atosubnet failed: %s\n", r->input, oops);
194                         status = 1;
195                 } else if (r->output == NULL) {
196                         printf("`%s' atosubnet succeeded unexpectedly\n",
197                                                                 r->input);
198                         status = 1;
199                 } else {
200                         n = subnettoa(a, m, 0, buf, sizeof(buf));
201                         if (n > sizeof(buf)) {
202                                 printf("`%s' subnettoa failed:  need %ld\n",
203                                                         r->input, (long)n);
204                                 status = 1;
205                         } else if (strcmp(r->output, buf) != 0) {
206                                 printf("`%s' gave `%s', expected `%s'\n",
207                                                 r->input, buf, r->output);
208                                 status = 1;
209                         }
210                 }
211         }
212         exit(status);
213 }
214
215 #endif /* ATOSUBNET_MAIN */