]> git.ipfire.org Git - people/ms/strongswan.git/blame - src/libfreeswan/atosubnet.c
(no commit message)
[people/ms/strongswan.git] / src / libfreeswan / atosubnet.c
CommitLineData
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 */
28const char * /* NULL for success, else string literal */
29atosubnet(src, srclen, addrp, maskp)
30const char *src;
31size_t srclen; /* 0 means "apply strlen" */
32struct in_addr *addrp;
33struct 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
96void regress(void);
97
98int
99main(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
137struct 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
176void
177regress()
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 */