1 /* $NetBSD: ipsec_dump_policy.c,v 1.7 2006/09/09 16:22:09 manu Exp $ */
3 /* Id: ipsec_dump_policy.c,v 1.10 2005/06/29 09:12:37 manubsd Exp */
6 * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
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.
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
38 #include <sys/types.h>
39 #include <sys/param.h>
40 #include <sys/socket.h>
42 #include <netinet/in.h>
45 #include <arpa/inet.h>
52 #include "ipsec_strerror.h"
55 static const char *ipsp_dir_strs
[] = {
56 "any", "in", "out", "fwd"
59 static const char *ipsp_policy_strs
[] = {
60 "discard", "none", "ipsec", "entrust", "bypass",
63 static char *ipsec_dump_ipsecrequest
__P((char *, size_t,
64 struct sadb_x_ipsecrequest
*, size_t, int));
65 static char *ipsec_dump_policy1
__P((void *, const char *, int));
66 static int set_addresses
__P((char *, size_t, struct sockaddr
*,
67 struct sockaddr
*, int));
68 static char *set_address
__P((char *, size_t, struct sockaddr
*, int));
71 * policy is sadb_x_policy buffer.
72 * Must call free() later.
73 * When delimiter == NULL, alternatively ' '(space) is applied.
76 ipsec_dump_policy(policy
, delimiter
)
77 ipsec_policy_t policy
;
78 __ipsec_const
char *delimiter
;
80 return ipsec_dump_policy1(policy
, delimiter
, 0);
84 ipsec_dump_policy_withports(policy
, delimiter
)
86 const char *delimiter
;
88 return ipsec_dump_policy1(policy
, delimiter
, 1);
92 ipsec_dump_policy1(policy
, delimiter
, withports
)
94 const char *delimiter
;
97 struct sadb_x_policy
*xpl
= policy
;
98 struct sadb_x_ipsecrequest
*xisr
;
104 #ifdef HAVE_PFKEY_POLICY_PRIORITY
105 int32_t priority_offset
;
113 if (xpl
->sadb_x_policy_exttype
!= SADB_X_EXT_POLICY
) {
114 __ipsec_errcode
= EIPSEC_INVAL_EXTTYPE
;
119 if (delimiter
== NULL
)
122 #ifdef HAVE_PFKEY_POLICY_PRIORITY
123 if (xpl
->sadb_x_policy_priority
== 0)
128 /* find which constant the priority is closest to */
129 else if (xpl
->sadb_x_policy_priority
<
130 (u_int32_t
) (PRIORITY_DEFAULT
/ 4) * 3)
132 priority_offset
= xpl
->sadb_x_policy_priority
- PRIORITY_HIGH
;
133 priority_str
= "prio high";
135 else if (xpl
->sadb_x_policy_priority
>=
136 (u_int32_t
) (PRIORITY_DEFAULT
/ 4) * 3 &&
137 xpl
->sadb_x_policy_priority
<
138 (u_int32_t
) (PRIORITY_DEFAULT
/ 4) * 5)
140 priority_offset
= xpl
->sadb_x_policy_priority
- PRIORITY_DEFAULT
;
141 priority_str
= "prio def";
145 priority_offset
= xpl
->sadb_x_policy_priority
- PRIORITY_LOW
;
146 priority_str
= "prio low";
149 /* fix sign to match the way it is input */
150 priority_offset
*= -1;
151 if (priority_offset
< 0)
154 priority_offset
*= -1;
162 switch (xpl
->sadb_x_policy_dir
) {
164 case IPSEC_DIR_INBOUND
:
165 case IPSEC_DIR_OUTBOUND
:
166 #ifdef HAVE_POLICY_FWD
171 __ipsec_errcode
= EIPSEC_INVAL_DIR
;
175 switch (xpl
->sadb_x_policy_type
) {
176 case IPSEC_POLICY_DISCARD
:
177 case IPSEC_POLICY_NONE
:
178 case IPSEC_POLICY_IPSEC
:
179 case IPSEC_POLICY_BYPASS
:
180 case IPSEC_POLICY_ENTRUST
:
183 __ipsec_errcode
= EIPSEC_INVAL_POLICY
;
187 buflen
= strlen(ipsp_dir_strs
[xpl
->sadb_x_policy_dir
])
189 #ifdef HAVE_PFKEY_POLICY_PRIORITY
190 + strlen(priority_str
)
191 + ((priority_offset
!= 0) ? 13 : 0) /* [space operator space int] */
192 + ((strlen(priority_str
) != 0) ? 1 : 0) /* space */
194 + strlen(ipsp_policy_strs
[xpl
->sadb_x_policy_type
])
197 if ((buf
= malloc(buflen
)) == NULL
) {
198 __ipsec_errcode
= EIPSEC_NO_BUFS
;
201 #ifdef HAVE_PFKEY_POLICY_PRIORITY
202 if (priority_offset
!= 0)
204 snprintf(buf
, buflen
, "%s %s %c %u %s",
205 ipsp_dir_strs
[xpl
->sadb_x_policy_dir
], priority_str
, operator,
206 priority_offset
, ipsp_policy_strs
[xpl
->sadb_x_policy_type
]);
208 else if (strlen (priority_str
) != 0)
210 snprintf(buf
, buflen
, "%s %s %s",
211 ipsp_dir_strs
[xpl
->sadb_x_policy_dir
], priority_str
,
212 ipsp_policy_strs
[xpl
->sadb_x_policy_type
]);
216 snprintf(buf
, buflen
, "%s %s",
217 ipsp_dir_strs
[xpl
->sadb_x_policy_dir
],
218 ipsp_policy_strs
[xpl
->sadb_x_policy_type
]);
221 snprintf(buf
, buflen
, "%s %s", ipsp_dir_strs
[xpl
->sadb_x_policy_dir
],
222 ipsp_policy_strs
[xpl
->sadb_x_policy_type
]);
225 if (xpl
->sadb_x_policy_type
!= IPSEC_POLICY_IPSEC
) {
226 __ipsec_errcode
= EIPSEC_NO_ERROR
;
230 /* count length of buffer for use */
232 while (off
< PFKEY_EXTLEN(xpl
)) {
233 xisr
= (void *)((caddr_t
)(void *)xpl
+ off
);
234 off
+= xisr
->sadb_x_ipsecrequest_len
;
238 if (off
!= PFKEY_EXTLEN(xpl
)) {
239 __ipsec_errcode
= EIPSEC_INVAL_SADBMSG
;
245 while (off
< PFKEY_EXTLEN(xpl
)) {
247 xisr
= (void *)((caddr_t
)(void *)xpl
+ off
);
249 if (ipsec_dump_ipsecrequest(isrbuf
, sizeof(isrbuf
), xisr
,
250 PFKEY_EXTLEN(xpl
) - off
, withports
) == NULL
) {
255 offset
= strlen(buf
);
256 buflen
= offset
+ strlen(delimiter
) + strlen(isrbuf
) + 1;
257 newbuf
= (char *)realloc(buf
, buflen
);
258 if (newbuf
== NULL
) {
259 __ipsec_errcode
= EIPSEC_NO_BUFS
;
264 snprintf(buf
+offset
, buflen
-offset
, "%s%s", delimiter
, isrbuf
);
266 off
+= xisr
->sadb_x_ipsecrequest_len
;
269 __ipsec_errcode
= EIPSEC_NO_ERROR
;
274 ipsec_dump_ipsecrequest(buf
, len
, xisr
, bound
, withports
)
277 struct sadb_x_ipsecrequest
*xisr
;
278 size_t bound
; /* boundary */
281 const char *proto
, *mode
, *level
;
282 char abuf
[NI_MAXHOST
* 2 + 2];
284 if (xisr
->sadb_x_ipsecrequest_len
> bound
) {
285 __ipsec_errcode
= EIPSEC_INVAL_PROTO
;
289 switch (xisr
->sadb_x_ipsecrequest_proto
) {
300 __ipsec_errcode
= EIPSEC_INVAL_PROTO
;
304 switch (xisr
->sadb_x_ipsecrequest_mode
) {
308 case IPSEC_MODE_TRANSPORT
:
311 case IPSEC_MODE_TUNNEL
:
315 __ipsec_errcode
= EIPSEC_INVAL_MODE
;
320 if (xisr
->sadb_x_ipsecrequest_len
> sizeof(*xisr
)) {
321 struct sockaddr
*sa1
, *sa2
;
324 p
= (void *)(xisr
+ 1);
326 sa2
= (void *)(p
+ sysdep_sa_len(sa1
));
327 if (sizeof(*xisr
) + sysdep_sa_len(sa1
) + sysdep_sa_len(sa2
) !=
328 xisr
->sadb_x_ipsecrequest_len
) {
329 __ipsec_errcode
= EIPSEC_INVAL_ADDRESS
;
332 if (set_addresses(abuf
, sizeof(abuf
),
333 sa1
, sa2
, withports
) != 0) {
334 __ipsec_errcode
= EIPSEC_INVAL_ADDRESS
;
339 switch (xisr
->sadb_x_ipsecrequest_level
) {
340 case IPSEC_LEVEL_DEFAULT
:
343 case IPSEC_LEVEL_USE
:
346 case IPSEC_LEVEL_REQUIRE
:
349 case IPSEC_LEVEL_UNIQUE
:
353 __ipsec_errcode
= EIPSEC_INVAL_LEVEL
;
357 if (xisr
->sadb_x_ipsecrequest_reqid
== 0)
358 snprintf(buf
, len
, "%s/%s/%s/%s", proto
, mode
, abuf
, level
);
362 if (xisr
->sadb_x_ipsecrequest_reqid
> IPSEC_MANUAL_REQID_MAX
)
366 snprintf(buf
, len
, "%s/%s/%s/%s%c%u", proto
, mode
, abuf
, level
,
367 ch
, xisr
->sadb_x_ipsecrequest_reqid
);
374 set_addresses(buf
, len
, sa1
, sa2
, withports
)
377 struct sockaddr
*sa1
;
378 struct sockaddr
*sa2
;
381 char tmp1
[NI_MAXHOST
], tmp2
[NI_MAXHOST
];
383 if (set_address(tmp1
, sizeof(tmp1
), sa1
, withports
) == NULL
||
384 set_address(tmp2
, sizeof(tmp2
), sa2
, withports
) == NULL
)
386 if (strlen(tmp1
) + 1 + strlen(tmp2
) + 1 > len
)
388 snprintf(buf
, len
, "%s-%s", tmp1
, tmp2
);
393 set_address(buf
, len
, sa
, withports
)
399 const int niflags
= NI_NUMERICHOST
| NI_NUMERICSERV
;
400 char host
[NI_MAXHOST
];
401 char serv
[NI_MAXSERV
];
406 if (getnameinfo(sa
, (socklen_t
)sysdep_sa_len(sa
), host
, sizeof(host
),
407 serv
, sizeof(serv
), niflags
) != 0)
411 snprintf(buf
, len
, "%s[%s]", host
, serv
);
413 snprintf(buf
, len
, "%s", host
);