source: rtems-libbsd/freebsd/lib/libipsec/ipsec_dump_policy.c @ f41a394

55-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since f41a394 was 3d1e767, checked in by Sebastian Huber <sebastian.huber@…>, on 04/27/16 at 08:25:22

Directly use <sys/types.h> provided by Newlib

  • Property mode set to 100644
File size: 7.5 KB
Line 
1#include <machine/rtems-bsd-user-space.h>
2
3/*      $KAME: ipsec_dump_policy.c,v 1.13 2002/06/27 14:35:11 itojun Exp $      */
4
5/*
6 * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the project nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include <sys/cdefs.h>
35__FBSDID("$FreeBSD$");
36
37#include <sys/types.h>
38#include <rtems/bsd/sys/param.h>
39#include <sys/socket.h>
40
41#include <netipsec/key_var.h>
42#include <netinet/in.h>
43#include <netipsec/ipsec.h>
44
45#include <arpa/inet.h>
46
47#include <stdio.h>
48#include <stdlib.h>
49#include <string.h>
50#include <netdb.h>
51
52#include "ipsec_strerror.h"
53
54static const char *ipsp_dir_strs[] = {
55        "any", "in", "out",
56};
57
58static const char *ipsp_policy_strs[] = {
59        "discard", "none", "ipsec", "entrust", "bypass",
60};
61
62static char *ipsec_dump_ipsecrequest(char *, size_t,
63        struct sadb_x_ipsecrequest *, size_t);
64static int set_addresses(char *, size_t, struct sockaddr *, struct sockaddr *);
65static char *set_address(char *, size_t, struct sockaddr *);
66
67/*
68 * policy is sadb_x_policy buffer.
69 * Must call free() later.
70 * When delimiter == NULL, alternatively ' '(space) is applied.
71 */
72char *
73ipsec_dump_policy(policy, delimiter)
74        caddr_t policy;
75        char *delimiter;
76{
77        struct sadb_x_policy *xpl = (struct sadb_x_policy *)policy;
78        struct sadb_x_ipsecrequest *xisr;
79        size_t off, buflen;
80        char *buf;
81        char isrbuf[1024];
82        char *newbuf;
83
84        /* sanity check */
85        if (policy == NULL)
86                return NULL;
87        if (xpl->sadb_x_policy_exttype != SADB_X_EXT_POLICY) {
88                __ipsec_errcode = EIPSEC_INVAL_EXTTYPE;
89                return NULL;
90        }
91
92        /* set delimiter */
93        if (delimiter == NULL)
94                delimiter = " ";
95
96        switch (xpl->sadb_x_policy_dir) {
97        case IPSEC_DIR_ANY:
98        case IPSEC_DIR_INBOUND:
99        case IPSEC_DIR_OUTBOUND:
100                break;
101        default:
102                __ipsec_errcode = EIPSEC_INVAL_DIR;
103                return NULL;
104        }
105
106        switch (xpl->sadb_x_policy_type) {
107        case IPSEC_POLICY_DISCARD:
108        case IPSEC_POLICY_NONE:
109        case IPSEC_POLICY_IPSEC:
110        case IPSEC_POLICY_BYPASS:
111        case IPSEC_POLICY_ENTRUST:
112                break;
113        default:
114                __ipsec_errcode = EIPSEC_INVAL_POLICY;
115                return NULL;
116        }
117
118        buflen = strlen(ipsp_dir_strs[xpl->sadb_x_policy_dir])
119                + 1     /* space */
120                + strlen(ipsp_policy_strs[xpl->sadb_x_policy_type])
121                + 1;    /* NUL */
122
123        if ((buf = malloc(buflen)) == NULL) {
124                __ipsec_errcode = EIPSEC_NO_BUFS;
125                return NULL;
126        }
127        snprintf(buf, buflen, "%s %s", ipsp_dir_strs[xpl->sadb_x_policy_dir],
128            ipsp_policy_strs[xpl->sadb_x_policy_type]);
129
130        if (xpl->sadb_x_policy_type != IPSEC_POLICY_IPSEC) {
131                __ipsec_errcode = EIPSEC_NO_ERROR;
132                return buf;
133        }
134
135        /* count length of buffer for use */
136        off = sizeof(*xpl);
137        while (off < PFKEY_EXTLEN(xpl)) {
138                xisr = (struct sadb_x_ipsecrequest *)((caddr_t)xpl + off);
139                off += xisr->sadb_x_ipsecrequest_len;
140        }
141
142        /* validity check */
143        if (off != PFKEY_EXTLEN(xpl)) {
144                __ipsec_errcode = EIPSEC_INVAL_SADBMSG;
145                free(buf);
146                return NULL;
147        }
148
149        off = sizeof(*xpl);
150        while (off < PFKEY_EXTLEN(xpl)) {
151                xisr = (struct sadb_x_ipsecrequest *)((caddr_t)xpl + off);
152
153                if (ipsec_dump_ipsecrequest(isrbuf, sizeof(isrbuf), xisr,
154                    PFKEY_EXTLEN(xpl) - off) == NULL) {
155                        free(buf);
156                        return NULL;
157                }
158
159                buflen = strlen(buf) + strlen(delimiter) + strlen(isrbuf) + 1;
160                newbuf = (char *)realloc(buf, buflen);
161                if (newbuf == NULL) {
162                        __ipsec_errcode = EIPSEC_NO_BUFS;
163                        free(buf);
164                        return NULL;
165                }
166                buf = newbuf;
167                snprintf(buf + strlen(buf), buflen - strlen(buf),
168                    "%s%s", delimiter, isrbuf);
169
170                off += xisr->sadb_x_ipsecrequest_len;
171        }
172
173        __ipsec_errcode = EIPSEC_NO_ERROR;
174        return buf;
175}
176
177static char *
178ipsec_dump_ipsecrequest(buf, len, xisr, bound)
179        char *buf;
180        size_t len;
181        struct sadb_x_ipsecrequest *xisr;
182        size_t bound;   /* boundary */
183{
184        const char *proto, *mode, *level;
185        char abuf[NI_MAXHOST * 2 + 2];
186
187        if (xisr->sadb_x_ipsecrequest_len > bound) {
188                __ipsec_errcode = EIPSEC_INVAL_PROTO;
189                return NULL;
190        }
191
192        switch (xisr->sadb_x_ipsecrequest_proto) {
193        case IPPROTO_ESP:
194                proto = "esp";
195                break;
196        case IPPROTO_AH:
197                proto = "ah";
198                break;
199        case IPPROTO_IPCOMP:
200                proto = "ipcomp";
201                break;
202        case IPPROTO_TCP:
203                proto = "tcp";
204                break;
205        default:
206                __ipsec_errcode = EIPSEC_INVAL_PROTO;
207                return NULL;
208        }
209
210        switch (xisr->sadb_x_ipsecrequest_mode) {
211        case IPSEC_MODE_ANY:
212                mode = "any";
213                break;
214        case IPSEC_MODE_TRANSPORT:
215                mode = "transport";
216                break;
217        case IPSEC_MODE_TUNNEL:
218                mode = "tunnel";
219                break;
220        default:
221                __ipsec_errcode = EIPSEC_INVAL_MODE;
222                return NULL;
223        }
224
225        abuf[0] = '\0';
226        if (xisr->sadb_x_ipsecrequest_len > sizeof(*xisr)) {
227                struct sockaddr *sa1, *sa2;
228                caddr_t p;
229
230                p = (caddr_t)(xisr + 1);
231                sa1 = (struct sockaddr *)p;
232                sa2 = (struct sockaddr *)(p + sa1->sa_len);
233                if (sizeof(*xisr) + sa1->sa_len + sa2->sa_len !=
234                    xisr->sadb_x_ipsecrequest_len) {
235                        __ipsec_errcode = EIPSEC_INVAL_ADDRESS;
236                        return NULL;
237                }
238                if (set_addresses(abuf, sizeof(abuf), sa1, sa2) != 0) {
239                        __ipsec_errcode = EIPSEC_INVAL_ADDRESS;
240                        return NULL;
241                }
242        }
243
244        switch (xisr->sadb_x_ipsecrequest_level) {
245        case IPSEC_LEVEL_DEFAULT:
246                level = "default";
247                break;
248        case IPSEC_LEVEL_USE:
249                level = "use";
250                break;
251        case IPSEC_LEVEL_REQUIRE:
252                level = "require";
253                break;
254        case IPSEC_LEVEL_UNIQUE:
255                level = "unique";
256                break;
257        default:
258                __ipsec_errcode = EIPSEC_INVAL_LEVEL;
259                return NULL;
260        }
261
262        if (xisr->sadb_x_ipsecrequest_reqid == 0)
263                snprintf(buf, len, "%s/%s/%s/%s", proto, mode, abuf, level);
264        else {
265                int ch;
266
267                if (xisr->sadb_x_ipsecrequest_reqid > IPSEC_MANUAL_REQID_MAX)
268                        ch = '#';
269                else
270                        ch = ':';
271                snprintf(buf, len, "%s/%s/%s/%s%c%u", proto, mode, abuf, level,
272                    ch, xisr->sadb_x_ipsecrequest_reqid);
273        }
274
275        return buf;
276}
277
278static int
279set_addresses(buf, len, sa1, sa2)
280        char *buf;
281        size_t len;
282        struct sockaddr *sa1;
283        struct sockaddr *sa2;
284{
285        char tmp1[NI_MAXHOST], tmp2[NI_MAXHOST];
286
287        if (set_address(tmp1, sizeof(tmp1), sa1) == NULL ||
288            set_address(tmp2, sizeof(tmp2), sa2) == NULL)
289                return -1;
290        if (strlen(tmp1) + 1 + strlen(tmp2) + 1 > len)
291                return -1;
292        snprintf(buf, len, "%s-%s", tmp1, tmp2);
293        return 0;
294}
295
296static char *
297set_address(buf, len, sa)
298        char *buf;
299        size_t len;
300        struct sockaddr *sa;
301{
302        const int niflags = NI_NUMERICHOST;
303
304        if (len < 1)
305                return NULL;
306        buf[0] = '\0';
307        if (getnameinfo(sa, sa->sa_len, buf, len, NULL, 0, niflags) != 0)
308                return NULL;
309        return buf;
310}
Note: See TracBrowser for help on using the repository browser.