2 * Copyright (C) 2011 Martin Willi
3 * Copyright (C) 2011 revosec AG
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>.
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
16 #include "whitelist_control.h"
18 #include <sys/types.h>
20 #include <sys/socket.h>
26 #include <collections/linked_list.h>
28 #include "whitelist_msg.h"
30 typedef struct private_whitelist_control_t private_whitelist_control_t
;
33 * Private data of an whitelist_control_t object.
35 struct private_whitelist_control_t
{
38 * Public whitelist_control_t interface.
40 whitelist_control_t
public;
45 whitelist_listener_t
*listener
;
48 * Whitelist stream service
50 stream_service_t
*service
;
54 * List whitelist entries using a read-copy
56 static void list(private_whitelist_control_t
*this,
57 stream_t
*stream
, identification_t
*id
)
59 identification_t
*current
;
60 enumerator_t
*enumerator
;
62 whitelist_msg_t msg
= {
63 .type
= htonl(WHITELIST_LIST
),
66 list
= linked_list_create();
67 enumerator
= this->listener
->create_enumerator(this->listener
);
68 while (enumerator
->enumerate(enumerator
, ¤t
))
70 if (current
->matches(current
, id
))
72 list
->insert_last(list
, current
->clone(current
));
75 enumerator
->destroy(enumerator
);
77 while (list
->remove_first(list
, (void**)¤t
) == SUCCESS
)
79 snprintf(msg
.id
, sizeof(msg
.id
), "%Y", current
);
80 current
->destroy(current
);
81 if (!stream
->write_all(stream
, &msg
, sizeof(msg
)))
83 DBG1(DBG_CFG
, "listing whitelist failed: %s", strerror(errno
));
87 list
->destroy_offset(list
, offsetof(identification_t
, destroy
));
89 msg
.type
= htonl(WHITELIST_END
);
90 memset(msg
.id
, 0, sizeof(msg
.id
));
91 stream
->write_all(stream
, &msg
, sizeof(msg
));
95 * Dispatch a received message
97 static bool on_accept(private_whitelist_control_t
*this, stream_t
*stream
)
102 while (stream
->read_all(stream
, &msg
, sizeof(msg
)))
104 msg
.id
[sizeof(msg
.id
) - 1] = 0;
105 id
= identification_create_from_string(msg
.id
);
106 switch (ntohl(msg
.type
))
109 this->listener
->add(this->listener
, id
);
111 case WHITELIST_REMOVE
:
112 this->listener
->remove(this->listener
, id
);
115 list(this, stream
, id
);
117 case WHITELIST_FLUSH
:
118 this->listener
->flush(this->listener
, id
);
120 case WHITELIST_ENABLE
:
121 this->listener
->set_active(this->listener
, TRUE
);
123 case WHITELIST_DISABLE
:
124 this->listener
->set_active(this->listener
, FALSE
);
127 DBG1(DBG_CFG
, "received unknown whitelist command");
136 METHOD(whitelist_control_t
, destroy
, void,
137 private_whitelist_control_t
*this)
139 this->service
->destroy(this->service
);
146 whitelist_control_t
*whitelist_control_create(whitelist_listener_t
*listener
)
148 private_whitelist_control_t
*this;
155 .listener
= listener
,
158 uri
= lib
->settings
->get_str(lib
->settings
,
159 "%s.plugins.whitelist.socket", "unix://" WHITELIST_SOCKET
,
161 this->service
= lib
->streams
->create_service(lib
->streams
, uri
, 10);
164 DBG1(DBG_CFG
, "creating whitelist socket failed");
169 this->service
->on_accept(this->service
, (stream_service_cb_t
)on_accept
,
170 this, JOB_PRIO_CRITICAL
, 0);
172 return &this->public;