]>
Commit | Line | Data |
---|---|---|
997358a6 MW |
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.1 2004/03/15 20:35:26 as 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 | #include <sys/socket.h> | |
93 | #include <netinet/in.h> | |
94 | #include <arpa/inet.h> | |
95 | ||
96 | void regress(void); | |
97 | ||
98 | int | |
99 | main(int argc, char *argv[]) | |
100 | { | |
101 | struct in_addr a; | |
102 | struct in_addr m; | |
103 | char buf[100]; | |
104 | const char *oops; | |
105 | size_t n; | |
106 | ||
107 | if (argc < 2) { | |
108 | fprintf(stderr, "Usage: %s {addr/mask|-r}\n", argv[0]); | |
109 | exit(2); | |
110 | } | |
111 | ||
112 | if (strcmp(argv[1], "-r") == 0) { | |
113 | regress(); | |
114 | fprintf(stderr, "regress() returned?!?\n"); | |
115 | exit(1); | |
116 | } | |
117 | ||
118 | oops = atosubnet(argv[1], 0, &a, &m); | |
119 | if (oops != NULL) { | |
120 | fprintf(stderr, "%s: conversion failed: %s\n", argv[0], oops); | |
121 | exit(1); | |
122 | } | |
123 | n = subnettoa(a, m, 0, buf, sizeof(buf)); | |
124 | if (n > sizeof(buf)) { | |
125 | fprintf(stderr, "%s: reverse conversion of ", argv[0]); | |
126 | fprintf(stderr, "%s/", inet_ntoa(a)); | |
127 | fprintf(stderr, "%s", inet_ntoa(m)); | |
128 | fprintf(stderr, " failed: need %ld bytes, have only %ld\n", | |
129 | (long)n, (long)sizeof(buf)); | |
130 | exit(1); | |
131 | } | |
132 | printf("%s\n", buf); | |
133 | ||
134 | exit(0); | |
135 | } | |
136 | ||
137 | struct rtab { | |
138 | char *input; | |
139 | char *output; /* NULL means error expected */ | |
140 | } rtab[] = { | |
141 | {"1.2.3.0/255.255.255.0", "1.2.3.0/24"}, | |
142 | {"1.2.3.0/24", "1.2.3.0/24"}, | |
143 | {"1.2.3.1/255.255.255.240", "1.2.3.0/28"}, | |
144 | {"1.2.3.1/32", "1.2.3.1/32"}, | |
145 | {"1.2.3.1/0", "0.0.0.0/0"}, | |
146 | /* "1.2.3.1/255.255.127.0", "1.2.3.0/255.255.127.0", */ | |
147 | {"1.2.3.1/255.255.127.0", NULL}, | |
148 | {"128.009.000.032/32", "128.9.0.32/32"}, | |
149 | {"128.0x9.0.32/32", NULL}, | |
150 | {"0x80090020/32", "128.9.0.32/32"}, | |
151 | {"0x800x0020/32", NULL}, | |
152 | {"128.9.0.32/0xffFF0000", "128.9.0.0/16"}, | |
153 | {"128.9.0.32/0xff0000FF", NULL}, | |
154 | {"128.9.0.32/0x0000ffFF", NULL}, | |
155 | {"128.9.0.32/0x00ffFF0000", NULL}, | |
156 | {"128.9.0.32/0xffFF", NULL}, | |
157 | {"128.9.0.32.27/32", NULL}, | |
158 | {"128.9.0k32/32", NULL}, | |
159 | {"328.9.0.32/32", NULL}, | |
160 | {"128.9..32/32", NULL}, | |
161 | {"10/8", "10.0.0.0/8"}, | |
162 | {"10.0/8", "10.0.0.0/8"}, | |
163 | {"10.0.0/8", "10.0.0.0/8"}, | |
164 | {"10.0.1/24", "10.0.1.0/24"}, | |
165 | {"_", NULL}, | |
166 | {"_/_", NULL}, | |
167 | {"1.2.3.1", NULL}, | |
168 | {"1.2.3.1/_", NULL}, | |
169 | {"1.2.3.1/24._", NULL}, | |
170 | {"1.2.3.1/99", NULL}, | |
171 | {"localhost/32", "127.0.0.1/32"}, | |
172 | {"%default", "0.0.0.0/0"}, | |
173 | {NULL, NULL} | |
174 | }; | |
175 | ||
176 | void | |
177 | regress() | |
178 | { | |
179 | struct rtab *r; | |
180 | int status = 0; | |
181 | struct in_addr a; | |
182 | struct in_addr m; | |
183 | char in[100]; | |
184 | char buf[100]; | |
185 | const char *oops; | |
186 | size_t n; | |
187 | ||
188 | for (r = rtab; r->input != NULL; r++) { | |
189 | strcpy(in, r->input); | |
190 | oops = atosubnet(in, 0, &a, &m); | |
191 | if (oops != NULL && r->output == NULL) | |
192 | {} /* okay, error expected */ | |
193 | else if (oops != NULL) { | |
194 | printf("`%s' atosubnet failed: %s\n", r->input, oops); | |
195 | status = 1; | |
196 | } else if (r->output == NULL) { | |
197 | printf("`%s' atosubnet succeeded unexpectedly\n", | |
198 | r->input); | |
199 | status = 1; | |
200 | } else { | |
201 | n = subnettoa(a, m, 0, buf, sizeof(buf)); | |
202 | if (n > sizeof(buf)) { | |
203 | printf("`%s' subnettoa failed: need %ld\n", | |
204 | r->input, (long)n); | |
205 | status = 1; | |
206 | } else if (strcmp(r->output, buf) != 0) { | |
207 | printf("`%s' gave `%s', expected `%s'\n", | |
208 | r->input, buf, r->output); | |
209 | status = 1; | |
210 | } | |
211 | } | |
212 | } | |
213 | exit(status); | |
214 | } | |
215 | ||
216 | #endif /* ATOSUBNET_MAIN */ |