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 "duplicheck_notify.h"
18 #include <sys/types.h>
20 #include <sys/socket.h>
26 #include <threading/mutex.h>
27 #include <threading/thread.h>
28 #include <utils/linked_list.h>
29 #include <processing/jobs/callback_job.h>
31 #define DUPLICHECK_SOCKET IPSEC_PIDDIR "/charon.dck"
33 typedef struct private_duplicheck_notify_t private_duplicheck_notify_t
;
36 * Private data of an duplicheck_notify_t object.
38 struct private_duplicheck_notify_t
{
41 * Public duplicheck_notify_t interface.
43 duplicheck_notify_t
public;
46 * Callback job dispatching connections
56 * List of connected sockets
58 linked_list_t
*connected
;
61 * Socket dispatching connections
67 * Open duplicheck unix socket
69 static bool open_socket(private_duplicheck_notify_t
*this)
71 struct sockaddr_un addr
;
74 addr
.sun_family
= AF_UNIX
;
75 strcpy(addr
.sun_path
, DUPLICHECK_SOCKET
);
77 this->socket
= socket(AF_UNIX
, SOCK_SEQPACKET
, 0);
78 if (this->socket
== -1)
80 DBG1(DBG_CFG
, "creating duplicheck socket failed");
83 unlink(addr
.sun_path
);
84 old
= umask(~(S_IRWXU
| S_IRWXG
));
85 if (bind(this->socket
, (struct sockaddr
*)&addr
, sizeof(addr
)) < 0)
87 DBG1(DBG_CFG
, "binding duplicheck socket failed: %s", strerror(errno
));
92 if (chown(addr
.sun_path
, charon
->uid
, charon
->gid
) != 0)
94 DBG1(DBG_CFG
, "changing duplicheck socket permissions failed: %s",
97 if (listen(this->socket
, 3) < 0)
99 DBG1(DBG_CFG
, "listening on duplicheck socket failed: %s",
102 unlink(addr
.sun_path
);
109 * Accept duplicheck notification connections
111 static job_requeue_t
receive(private_duplicheck_notify_t
*this)
113 struct sockaddr_un addr
;
114 int len
= sizeof(addr
);
118 oldstate
= thread_cancelability(TRUE
);
119 fd
= accept(this->socket
, (struct sockaddr
*)&addr
, &len
);
120 thread_cancelability(oldstate
);
124 this->mutex
->lock(this->mutex
);
125 this->connected
->insert_last(this->connected
, (void*)fd
);
126 this->mutex
->unlock(this->mutex
);
130 DBG1(DBG_CFG
, "accepting duplicheck connection failed: %s",
133 return JOB_REQUEUE_FAIR
;
136 METHOD(duplicheck_notify_t
, send_
, void,
137 private_duplicheck_notify_t
*this, identification_t
*id
)
140 enumerator_t
*enumerator
;
144 len
= snprintf(buf
, sizeof(buf
), "%Y", id
);
145 if (len
> 0 && len
< sizeof(buf
))
147 this->mutex
->lock(this->mutex
);
148 enumerator
= this->connected
->create_enumerator(this->connected
);
149 while (enumerator
->enumerate(enumerator
, &fd
))
151 if (send(fd
, &buf
, len
+ 1, 0) != len
+ 1)
153 DBG1(DBG_CFG
, "sending duplicheck notify failed: %s",
155 this->connected
->remove_at(this->connected
, enumerator
);
159 enumerator
->destroy(enumerator
);
160 this->mutex
->unlock(this->mutex
);
164 METHOD(duplicheck_notify_t
, destroy
, void,
165 private_duplicheck_notify_t
*this)
167 enumerator_t
*enumerator
;
172 this->job
->cancel(this->job
);
174 enumerator
= this->connected
->create_enumerator(this->connected
);
175 while (enumerator
->enumerate(enumerator
, &fd
))
179 enumerator
->destroy(enumerator
);
180 this->connected
->destroy(this->connected
);
181 this->mutex
->destroy(this->mutex
);
188 duplicheck_notify_t
*duplicheck_notify_create()
190 private_duplicheck_notify_t
*this;
197 .connected
= linked_list_create(),
198 .mutex
= mutex_create(MUTEX_TYPE_DEFAULT
),
201 if (!open_socket(this))
206 this->job
= callback_job_create((callback_job_cb_t
)receive
,
208 lib
->processor
->queue_job(lib
->processor
, (job_t
*)this->job
);
210 return &this->public;