]> git.ipfire.org Git - people/ms/strongswan.git/blob - src/libcharon/plugins/whitelist/whitelist_control.c
libcharon: Use lib->ns instead of charon->name
[people/ms/strongswan.git] / src / libcharon / plugins / whitelist / whitelist_control.c
1 /*
2 * Copyright (C) 2011 Martin Willi
3 * Copyright (C) 2011 revosec AG
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include "whitelist_control.h"
17
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <sys/socket.h>
21 #include <sys/un.h>
22 #include <unistd.h>
23 #include <errno.h>
24
25 #include <daemon.h>
26 #include <collections/linked_list.h>
27
28 #include "whitelist_msg.h"
29
30 typedef struct private_whitelist_control_t private_whitelist_control_t;
31
32 /**
33 * Private data of an whitelist_control_t object.
34 */
35 struct private_whitelist_control_t {
36
37 /**
38 * Public whitelist_control_t interface.
39 */
40 whitelist_control_t public;
41
42 /**
43 * Whitelist
44 */
45 whitelist_listener_t *listener;
46
47 /**
48 * Whitelist stream service
49 */
50 stream_service_t *service;
51 };
52
53 /*
54 * List whitelist entries using a read-copy
55 */
56 static void list(private_whitelist_control_t *this,
57 stream_t *stream, identification_t *id)
58 {
59 identification_t *current;
60 enumerator_t *enumerator;
61 linked_list_t *list;
62 whitelist_msg_t msg = {
63 .type = htonl(WHITELIST_LIST),
64 };
65
66 list = linked_list_create();
67 enumerator = this->listener->create_enumerator(this->listener);
68 while (enumerator->enumerate(enumerator, &current))
69 {
70 if (current->matches(current, id))
71 {
72 list->insert_last(list, current->clone(current));
73 }
74 }
75 enumerator->destroy(enumerator);
76
77 while (list->remove_first(list, (void**)&current) == SUCCESS)
78 {
79 snprintf(msg.id, sizeof(msg.id), "%Y", current);
80 current->destroy(current);
81 if (!stream->write_all(stream, &msg, sizeof(msg)))
82 {
83 DBG1(DBG_CFG, "listing whitelist failed: %s", strerror(errno));
84 break;
85 }
86 }
87 list->destroy_offset(list, offsetof(identification_t, destroy));
88
89 msg.type = htonl(WHITELIST_END);
90 memset(msg.id, 0, sizeof(msg.id));
91 stream->write_all(stream, &msg, sizeof(msg));
92 }
93
94 /**
95 * Dispatch a received message
96 */
97 static bool on_accept(private_whitelist_control_t *this, stream_t *stream)
98 {
99 identification_t *id;
100 whitelist_msg_t msg;
101
102 while (stream->read_all(stream, &msg, sizeof(msg)))
103 {
104 msg.id[sizeof(msg.id) - 1] = 0;
105 id = identification_create_from_string(msg.id);
106 switch (ntohl(msg.type))
107 {
108 case WHITELIST_ADD:
109 this->listener->add(this->listener, id);
110 break;
111 case WHITELIST_REMOVE:
112 this->listener->remove(this->listener, id);
113 break;
114 case WHITELIST_LIST:
115 list(this, stream, id);
116 break;
117 case WHITELIST_FLUSH:
118 this->listener->flush(this->listener, id);
119 break;
120 case WHITELIST_ENABLE:
121 this->listener->set_active(this->listener, TRUE);
122 break;
123 case WHITELIST_DISABLE:
124 this->listener->set_active(this->listener, FALSE);
125 break;
126 default:
127 DBG1(DBG_CFG, "received unknown whitelist command");
128 break;
129 }
130 id->destroy(id);
131 }
132
133 return FALSE;
134 }
135
136 METHOD(whitelist_control_t, destroy, void,
137 private_whitelist_control_t *this)
138 {
139 this->service->destroy(this->service);
140 free(this);
141 }
142
143 /**
144 * See header
145 */
146 whitelist_control_t *whitelist_control_create(whitelist_listener_t *listener)
147 {
148 private_whitelist_control_t *this;
149 char *uri;
150
151 INIT(this,
152 .public = {
153 .destroy = _destroy,
154 },
155 .listener = listener,
156 );
157
158 uri = lib->settings->get_str(lib->settings,
159 "%s.plugins.whitelist.socket", "unix://" WHITELIST_SOCKET,
160 lib->ns);
161 this->service = lib->streams->create_service(lib->streams, uri, 10);
162 if (!this->service)
163 {
164 DBG1(DBG_CFG, "creating whitelist socket failed");
165 free(this);
166 return NULL;
167 }
168
169 this->service->on_accept(this->service, (stream_service_cb_t)on_accept,
170 this, JOB_PRIO_CRITICAL, 0);
171
172 return &this->public;
173 }