]> git.ipfire.org Git - people/ms/strongswan.git/blob - lib/libipsecpolicy/policyquery.c
- import of strongswan-2.7.0
[people/ms/strongswan.git] / lib / libipsecpolicy / policyquery.c
1 /* routines that interface with pluto to get policy information
2 * Copyright (C) 2003 Michael Richardson <mcr@freeswan.org>
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * for more details.
13 *
14 * RCSID $Id: policyquery.c,v 1.1 2004/03/15 20:35:25 as Exp $
15 */
16
17 #include <stddef.h>
18 #include <string.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <errno.h>
22 #include <wait.h>
23 #include <unistd.h>
24 #include <fcntl.h>
25
26 #include <sys/socket.h>
27 #include <sys/un.h>
28 #include <netinet/in.h>
29 #include <arpa/inet.h>
30
31 #include <freeswan.h>
32 #include <freeswan/ipsec_policy.h>
33
34 #include "libipsecpolicy.h"
35
36 static int policy_query_socket = -1;
37 static u_int32_t policy_seq = 1;
38
39 u_int32_t ipsec_policy_seq(void)
40 {
41 return ++policy_seq;
42 }
43
44 err_t ipsec_policy_init(void)
45 {
46 struct sockaddr_un sn;
47
48 if(policy_query_socket != -1) {
49 return NULL;
50 }
51
52 policy_query_socket = socket(PF_UNIX, SOCK_STREAM, 0);
53 if(policy_query_socket == -1) {
54 return "failed to open policy socket";
55 }
56
57 /* now connect it */
58 sn.sun_family = AF_UNIX;
59 strcpy(sn.sun_path, IPSEC_POLICY_SOCKET);
60
61 if(connect(policy_query_socket, (struct sockaddr *)&sn, sizeof(sn)) != 0) {
62 int saveerrno = errno;
63 close(policy_query_socket);
64 policy_query_socket=-1;
65 errno = saveerrno;
66 return "failed to connect policy socket";
67 }
68
69 /* okay, I think we are done */
70 return NULL;
71 }
72
73 err_t ipsec_policy_final(void)
74 {
75 if(policy_query_socket != -1) {
76 close(policy_query_socket);
77 policy_query_socket = -1;
78 }
79
80 return NULL;
81 }
82
83 err_t ipsec_policy_readmsg(int policysock,
84 unsigned char *buf,
85 size_t buflen)
86 {
87 struct ipsec_policy_msg_head ipmh;
88
89 if(read(policysock, &ipmh, sizeof(ipmh))
90 != sizeof(ipmh)) {
91 return "read failed";
92 }
93
94 /* got the header, sanitize it, and find out how much more to read */
95 switch(ipmh.ipm_version) {
96 case IPSEC_POLICY_MSG_REVISION:
97 break;
98
99 default:
100 /* XXX go deal with older versions, error for now */
101 fprintf(stderr, "Bad magic header: %u\n", ipmh.ipm_version);
102 return "bad policy msg version magic";
103 }
104
105 if(ipmh.ipm_msg_len > buflen) {
106 return "buffer too small for this message";
107 }
108
109 buflen = ipmh.ipm_msg_len;
110 memcpy(buf, &ipmh, sizeof(ipmh));
111 buf += sizeof(ipmh);
112 buflen -= sizeof(ipmh);
113
114 if(read(policysock, buf, buflen) != buflen) {
115 return "short read from socket";
116 }
117
118 return NULL;
119 }
120
121 err_t ipsec_policy_sendrecv(unsigned char *buf,
122 size_t buflen)
123 {
124 err_t ret;
125 ipsec_policy_init();
126
127 if(write(policy_query_socket, buf, buflen)
128 != buflen) {
129 return "write failed";
130 }
131
132 ret = ipsec_policy_readmsg(policy_query_socket,
133 buf, buflen);
134
135 ipsec_policy_final();
136
137 return ret;
138 }
139
140
141 err_t ipsec_policy_lookup(int fd, struct ipsec_policy_cmd_query *result)
142 {
143 int len;
144
145 /* clear it out */
146 memset(result, 0, sizeof(*result));
147
148 /* setup it up */
149 result->head.ipm_version = IPSEC_POLICY_MSG_REVISION;
150 result->head.ipm_msg_len = sizeof(*result);
151 result->head.ipm_msg_type = IPSEC_CMD_QUERY_HOSTPAIR;
152 result->head.ipm_msg_seq = ipsec_policy_seq();
153
154 /* suck out the data on the sockets */
155 len = sizeof(result->query_local);
156 if(getsockname(fd, (struct sockaddr *)&result->query_local, &len) != 0) {
157 return "getsockname failed";
158 }
159
160 len = sizeof(result->query_remote);
161 if(getpeername(fd, (struct sockaddr *)&result->query_remote, &len) != 0) {
162 return "getpeername failed";
163 }
164
165 return ipsec_policy_sendrecv((unsigned char *)result, sizeof(*result));
166 }
167