1 /* $Id: ipsec_dump_policy.c,v 1.7.4.2 2005/06/29 13:01:27 manubsd Exp $ */
4 * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 #include <sys/types.h>
37 #include <sys/param.h>
38 #include <sys/socket.h>
40 #include <netinet/in.h>
41 #ifdef HAVE_NETINET6_IPSEC
42 # include <netinet6/ipsec.h>
44 # include <netinet/ipsec.h>
47 #include <arpa/inet.h>
54 #include "ipsec_strerror.h"
57 static const char *ipsp_dir_strs
[] = {
58 "any", "in", "out", "fwd"
61 static const char *ipsp_policy_strs
[] = {
62 "discard", "none", "ipsec", "entrust", "bypass", "generate",
65 static char *ipsec_dump_ipsecrequest
__P((char *, size_t,
66 struct sadb_x_ipsecrequest
*, size_t, int));
67 static char *ipsec_dump_policy1
__P((void *, const char *, int));
68 static int set_addresses
__P((char *, size_t, struct sockaddr
*,
69 struct sockaddr
*, int));
70 static char *set_address
__P((char *, size_t, struct sockaddr
*, int));
73 * policy is sadb_x_policy buffer.
74 * Must call free() later.
75 * When delimiter == NULL, alternatively ' '(space) is applied.
78 ipsec_dump_policy(policy
, delimiter
)
79 ipsec_policy_t policy
;
80 __ipsec_const
char *delimiter
;
82 return ipsec_dump_policy1(policy
, delimiter
, 0);
86 ipsec_dump_policy_withports(policy
, delimiter
)
88 const char *delimiter
;
90 return ipsec_dump_policy1(policy
, delimiter
, 1);
94 ipsec_dump_policy1(policy
, delimiter
, withports
)
96 const char *delimiter
;
99 struct sadb_x_policy
*xpl
= policy
;
100 struct sadb_x_ipsecrequest
*xisr
;
106 #ifdef HAVE_PFKEY_POLICY_PRIORITY
107 int32_t priority_offset
;
115 if (xpl
->sadb_x_policy_exttype
!= SADB_X_EXT_POLICY
) {
116 __ipsec_errcode
= EIPSEC_INVAL_EXTTYPE
;
121 if (delimiter
== NULL
)
124 #ifdef HAVE_PFKEY_POLICY_PRIORITY
125 if (xpl
->sadb_x_policy_priority
== 0)
130 /* find which constant the priority is closest to */
131 else if (xpl
->sadb_x_policy_priority
<
132 (u_int32_t
) (PRIORITY_DEFAULT
/ 4) * 3)
134 priority_offset
= xpl
->sadb_x_policy_priority
- PRIORITY_HIGH
;
135 priority_str
= "prio high";
137 else if (xpl
->sadb_x_policy_priority
>=
138 (u_int32_t
) (PRIORITY_DEFAULT
/ 4) * 3 &&
139 xpl
->sadb_x_policy_priority
<
140 (u_int32_t
) (PRIORITY_DEFAULT
/ 4) * 5)
142 priority_offset
= xpl
->sadb_x_policy_priority
- PRIORITY_DEFAULT
;
143 priority_str
= "prio def";
147 priority_offset
= xpl
->sadb_x_policy_priority
- PRIORITY_LOW
;
148 priority_str
= "prio low";
151 /* fix sign to match the way it is input */
152 priority_offset
*= -1;
153 if (priority_offset
< 0)
156 priority_offset
*= -1;
164 switch (xpl
->sadb_x_policy_dir
) {
166 case IPSEC_DIR_INBOUND
:
167 case IPSEC_DIR_OUTBOUND
:
168 #ifdef HAVE_POLICY_FWD
173 __ipsec_errcode
= EIPSEC_INVAL_DIR
;
177 switch (xpl
->sadb_x_policy_type
) {
178 case IPSEC_POLICY_DISCARD
:
179 case IPSEC_POLICY_GENERATE
:
180 case IPSEC_POLICY_NONE
:
181 case IPSEC_POLICY_IPSEC
:
182 case IPSEC_POLICY_BYPASS
:
183 case IPSEC_POLICY_ENTRUST
:
186 __ipsec_errcode
= EIPSEC_INVAL_POLICY
;
190 buflen
= strlen(ipsp_dir_strs
[xpl
->sadb_x_policy_dir
])
192 #ifdef HAVE_PFKEY_POLICY_PRIORITY
193 + strlen(priority_str
)
194 + ((priority_offset
!= 0) ? 13 : 0) /* [space operator space int] */
195 + ((strlen(priority_str
) != 0) ? 1 : 0) /* space */
197 + strlen(ipsp_policy_strs
[xpl
->sadb_x_policy_type
])
200 if ((buf
= malloc(buflen
)) == NULL
) {
201 __ipsec_errcode
= EIPSEC_NO_BUFS
;
204 #ifdef HAVE_PFKEY_POLICY_PRIORITY
205 if (priority_offset
!= 0)
207 snprintf(buf
, buflen
, "%s %s %c %u %s",
208 ipsp_dir_strs
[xpl
->sadb_x_policy_dir
], priority_str
, operator,
209 priority_offset
, ipsp_policy_strs
[xpl
->sadb_x_policy_type
]);
211 else if (strlen (priority_str
) != 0)
213 snprintf(buf
, buflen
, "%s %s %s",
214 ipsp_dir_strs
[xpl
->sadb_x_policy_dir
], priority_str
,
215 ipsp_policy_strs
[xpl
->sadb_x_policy_type
]);
219 snprintf(buf
, buflen
, "%s %s",
220 ipsp_dir_strs
[xpl
->sadb_x_policy_dir
],
221 ipsp_policy_strs
[xpl
->sadb_x_policy_type
]);
224 snprintf(buf
, buflen
, "%s %s", ipsp_dir_strs
[xpl
->sadb_x_policy_dir
],
225 ipsp_policy_strs
[xpl
->sadb_x_policy_type
]);
228 if (xpl
->sadb_x_policy_type
!= IPSEC_POLICY_IPSEC
) {
229 __ipsec_errcode
= EIPSEC_NO_ERROR
;
233 /* count length of buffer for use */
235 while (off
< PFKEY_EXTLEN(xpl
)) {
236 xisr
= (void *)((caddr_t
)(void *)xpl
+ off
);
237 off
+= xisr
->sadb_x_ipsecrequest_len
;
241 if (off
!= PFKEY_EXTLEN(xpl
)) {
242 __ipsec_errcode
= EIPSEC_INVAL_SADBMSG
;
248 while (off
< PFKEY_EXTLEN(xpl
)) {
250 xisr
= (void *)((caddr_t
)(void *)xpl
+ off
);
252 if (ipsec_dump_ipsecrequest(isrbuf
, sizeof(isrbuf
), xisr
,
253 PFKEY_EXTLEN(xpl
) - off
, withports
) == NULL
) {
258 offset
= strlen(buf
);
259 buflen
= offset
+ strlen(delimiter
) + strlen(isrbuf
) + 1;
260 newbuf
= (char *)realloc(buf
, buflen
);
261 if (newbuf
== NULL
) {
262 __ipsec_errcode
= EIPSEC_NO_BUFS
;
267 snprintf(buf
+offset
, buflen
-offset
, "%s%s", delimiter
, isrbuf
);
269 off
+= xisr
->sadb_x_ipsecrequest_len
;
272 __ipsec_errcode
= EIPSEC_NO_ERROR
;
277 ipsec_dump_ipsecrequest(buf
, len
, xisr
, bound
, withports
)
280 struct sadb_x_ipsecrequest
*xisr
;
281 size_t bound
; /* boundary */
284 const char *proto
, *mode
, *level
;
285 char abuf
[NI_MAXHOST
* 2 + 2];
287 if (xisr
->sadb_x_ipsecrequest_len
> bound
) {
288 __ipsec_errcode
= EIPSEC_INVAL_PROTO
;
292 switch (xisr
->sadb_x_ipsecrequest_proto
) {
303 __ipsec_errcode
= EIPSEC_INVAL_PROTO
;
307 switch (xisr
->sadb_x_ipsecrequest_mode
) {
311 case IPSEC_MODE_TRANSPORT
:
314 case IPSEC_MODE_TUNNEL
:
318 __ipsec_errcode
= EIPSEC_INVAL_MODE
;
323 if (xisr
->sadb_x_ipsecrequest_len
> sizeof(*xisr
)) {
324 struct sockaddr
*sa1
, *sa2
;
327 p
= (void *)(xisr
+ 1);
329 sa2
= (void *)(p
+ sysdep_sa_len(sa1
));
330 if (sizeof(*xisr
) + sysdep_sa_len(sa1
) + sysdep_sa_len(sa2
) !=
331 xisr
->sadb_x_ipsecrequest_len
) {
332 __ipsec_errcode
= EIPSEC_INVAL_ADDRESS
;
335 if (set_addresses(abuf
, sizeof(abuf
),
336 sa1
, sa2
, withports
) != 0) {
337 __ipsec_errcode
= EIPSEC_INVAL_ADDRESS
;
342 switch (xisr
->sadb_x_ipsecrequest_level
) {
343 case IPSEC_LEVEL_DEFAULT
:
346 case IPSEC_LEVEL_USE
:
349 case IPSEC_LEVEL_REQUIRE
:
352 case IPSEC_LEVEL_UNIQUE
:
356 __ipsec_errcode
= EIPSEC_INVAL_LEVEL
;
360 if (xisr
->sadb_x_ipsecrequest_reqid
== 0)
361 snprintf(buf
, len
, "%s/%s/%s/%s", proto
, mode
, abuf
, level
);
365 if (xisr
->sadb_x_ipsecrequest_reqid
> IPSEC_MANUAL_REQID_MAX
)
369 snprintf(buf
, len
, "%s/%s/%s/%s%c%u", proto
, mode
, abuf
, level
,
370 ch
, xisr
->sadb_x_ipsecrequest_reqid
);
377 set_addresses(buf
, len
, sa1
, sa2
, withports
)
380 struct sockaddr
*sa1
;
381 struct sockaddr
*sa2
;
384 char tmp1
[NI_MAXHOST
], tmp2
[NI_MAXHOST
];
386 if (set_address(tmp1
, sizeof(tmp1
), sa1
, withports
) == NULL
||
387 set_address(tmp2
, sizeof(tmp2
), sa2
, withports
) == NULL
)
389 if (strlen(tmp1
) + 1 + strlen(tmp2
) + 1 > len
)
391 snprintf(buf
, len
, "%s-%s", tmp1
, tmp2
);
396 set_address(buf
, len
, sa
, withports
)
402 const int niflags
= NI_NUMERICHOST
| NI_NUMERICSERV
;
403 char host
[NI_MAXHOST
];
404 char serv
[NI_MAXSERV
];
409 if (getnameinfo(sa
, (socklen_t
)sysdep_sa_len(sa
), host
, sizeof(host
),
410 serv
, sizeof(serv
), niflags
) != 0)
414 snprintf(buf
, len
, "%s[%s]", host
, serv
);
416 snprintf(buf
, len
, "%s", host
);