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