removed prng.c from libfreeswan
[strongswan.git] / src / libfreeswan / atosa.c
1 /*
2 * convert from ASCII form of SA ID 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 #include "internal.h"
16 #include "freeswan.h"
17
18 static struct satype {
19 char *prefix;
20 size_t prelen; /* strlen(prefix) */
21 int proto;
22 } satypes[] = {
23 { "ah", 2, SA_AH },
24 { "esp", 3, SA_ESP },
25 { "tun", 3, SA_IPIP },
26 { "comp", 4, SA_COMP },
27 { NULL, 0, 0, }
28 };
29
30 /*
31 - atosa - convert ASCII "ah507@10.0.0.1" to SA identifier
32 */
33 const char * /* NULL for success, else string literal */
34 atosa(src, srclen, sa)
35 const char *src;
36 size_t srclen; /* 0 means "apply strlen" */
37 struct sa_id *sa;
38 {
39 const char *at;
40 const char *addr;
41 const char *spi = NULL;
42 struct satype *sat;
43 unsigned long ul;
44 const char *oops;
45 # define MINLEN 5 /* ah0@0 is as short as it can get */
46 static char ptname[] = PASSTHROUGHNAME;
47 # define PTNLEN (sizeof(ptname)-1) /* -1 for NUL */
48
49 if (srclen == 0)
50 srclen = strlen(src);
51 if (srclen == 0)
52 return "empty string";
53 if (srclen < MINLEN)
54 return "string too short to be SA specifier";
55 if (srclen == PTNLEN && memcmp(src, ptname, PTNLEN) == 0) {
56 src = PASSTHROUGHIS;
57 srclen = strlen(src);
58 }
59
60 at = memchr(src, '@', srclen);
61 if (at == NULL)
62 return "no @ in SA specifier";
63
64 for (sat = satypes; sat->prefix != NULL; sat++)
65 if (sat->prelen < srclen &&
66 strncmp(src, sat->prefix, sat->prelen) == 0) {
67 sa->proto = sat->proto;
68 spi = src + sat->prelen;
69 break; /* NOTE BREAK OUT */
70 }
71 if (sat->prefix == NULL)
72 return "SA specifier lacks valid protocol prefix";
73
74 if (spi >= at)
75 return "no SPI in SA specifier";
76 oops = atoul(spi, at - spi, 13, &ul);
77 if (oops != NULL)
78 return oops;
79 sa->spi = htonl(ul);
80
81 addr = at + 1;
82 oops = atoaddr(addr, srclen - (addr - src), &sa->dst);
83 if (oops != NULL)
84 return oops;
85
86 return NULL;
87 }
88
89
90
91 #ifdef ATOSA_MAIN
92
93 #include <stdio.h>
94 #include <sys/socket.h>
95 #include <netinet/in.h>
96 #include <arpa/inet.h>
97
98 void regress(void);
99
100 int
101 main(int argc, char *argv[])
102 {
103 struct sa_id sa;
104 char buf[100];
105 const char *oops;
106 size_t n;
107
108 if (argc < 2) {
109 fprintf(stderr, "Usage: %s {ahnnn@aaa|-r}\n", argv[0]);
110 exit(2);
111 }
112
113 if (strcmp(argv[1], "-r") == 0) {
114 regress();
115 fprintf(stderr, "regress() returned?!?\n");
116 exit(1);
117 }
118
119 oops = atosa(argv[1], 0, &sa);
120 if (oops != NULL) {
121 fprintf(stderr, "%s: conversion failed: %s\n", argv[0], oops);
122 exit(1);
123 }
124 n = satoa(sa, 0, buf, sizeof(buf));
125 if (n > sizeof(buf)) {
126 fprintf(stderr, "%s: reverse conv of `%d'", argv[0], sa.proto);
127 fprintf(stderr, "%lu@", (long unsigned int)sa.spi);
128 fprintf(stderr, "%s", inet_ntoa(sa.dst));
129 fprintf(stderr, " failed: need %ld bytes, have only %ld\n",
130 (long)n, (long)sizeof(buf));
131 exit(1);
132 }
133 printf("%s\n", buf);
134
135 exit(0);
136 }
137
138 struct rtab {
139 char *input;
140 char *output; /* NULL means error expected */
141 } rtab[] = {
142 {"esp257@1.2.3.0", "esp257@1.2.3.0"},
143 {"ah0x20@1.2.3.4", "ah32@1.2.3.4"},
144 {"tun011@111.2.3.99", "tun11@111.2.3.99"},
145 {"", NULL},
146 {"_", NULL},
147 {"ah2.2", NULL},
148 {"goo2@1.2.3.4", NULL},
149 {"esp9@1.2.3.4", "esp9@1.2.3.4"},
150 {"espp9@1.2.3.4", NULL},
151 {"es9@1.2.3.4", NULL},
152 {"ah@1.2.3.4", NULL},
153 {"esp7x7@1.2.3.4", NULL},
154 {"esp77@1.0x2.3.4", NULL},
155 {PASSTHROUGHNAME, PASSTHROUGHNAME},
156 {NULL, NULL}
157 };
158
159 void
160 regress(void)
161 {
162 struct rtab *r;
163 int status = 0;
164 struct sa_id sa;
165 char in[100];
166 char buf[100];
167 const char *oops;
168 size_t n;
169
170 for (r = rtab; r->input != NULL; r++) {
171 strcpy(in, r->input);
172 oops = atosa(in, 0, &sa);
173 if (oops != NULL && r->output == NULL)
174 {} /* okay, error expected */
175 else if (oops != NULL) {
176 printf("`%s' atosa failed: %s\n", r->input, oops);
177 status = 1;
178 } else if (r->output == NULL) {
179 printf("`%s' atosa succeeded unexpectedly\n",
180 r->input);
181 status = 1;
182 } else {
183 n = satoa(sa, 'd', buf, sizeof(buf));
184 if (n > sizeof(buf)) {
185 printf("`%s' satoa failed: need %ld\n",
186 r->input, (long)n);
187 status = 1;
188 } else if (strcmp(r->output, buf) != 0) {
189 printf("`%s' gave `%s', expected `%s'\n",
190 r->input, buf, r->output);
191 status = 1;
192 }
193 }
194 }
195 exit(status);
196 }
197
198 #endif /* ATOSA_MAIN */