if (listen (self->fd, 20) == -1)
abort ();
+ self->rxpd_socket_addr = rxpd_socket_tcp4addr;
+
event_set (&self->ev, self->fd, EV_READ, rxpd_socket_accept, self);
llist_insert_tail (&base->sockets, &self->node);
return self;
}
+int
+rxpd_socket_tcp4addr (struct rxpd_connection* conn, char* dst, const char* pfx, size_t size)
+{
+ struct sockaddr_in peer;
+ socklen_t len = sizeof (peer);
+ getpeername (conn->fd, (struct sockaddr*)&peer, &len);
+
+ char* addr;
+ addr = inet_ntoa (peer.sin_addr);
+ if (sizeof (":tcp4:") + strlen (pfx) + strlen (addr) > size)
+ return 0;
+
+ strcat (dst, pfx);
+ strcat (dst, ":tcp4:");
+ strcat (dst, addr);
+ return 1;
+}
+
+
void
rxpd_socket_delete (struct rxpd_socket* self)
struct rxpd_socket* self = ptr;
struct rxpd_connection* conn =
- rxpd_connection_new (self->base, fd);
+ rxpd_connection_new (self, fd);
rxpd_connection_schedule (conn);
rxpd_socket_schedule (self);
///
struct rxpd_connection*
-rxpd_connection_new (struct rxpd_base* base, int fd)
+rxpd_connection_new (struct rxpd_socket* socket, int fd)
{
struct rxpd_connection* self;
self = rxpd_malloc (sizeof (struct rxpd_connection));
- socklen_t addr_sz = sizeof (self->peer_addr);
- self->fd = accept (fd, (struct sockaddr*)&self->peer_addr, &addr_sz);
+ self->fd = accept (fd, NULL, 0);
if (self->fd == -1)
abort ();
- //static int yes = 1;
- //if (setsockopt (self->fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
- // abort ();
-
-
-
- self->base = base;
+ self->socket = socket;
self->file = NULL;
self->tmp_str = NULL;
llist_init (&self->tmp_list);
event_set (&self->ev, self->fd, EV_READ, rxpd_connection_parse_cmd, self);
// TODO more info
- rxpd_log (base, LOG_INFO, "incoming connection\n");
+ rxpd_log (socket->base, LOG_INFO, "incoming connection\n");
return self;
}
return self;
}
+int
+rxpd_connection_check_policy (struct rxpd_connection* self, char* line)
+{
+ struct rxpd_base* base = self->socket->base;
+ if (base->policy)
+ {
+ char buf[256];
+ buf[0] = '\0';
+
+ if (!self->socket->rxpd_socket_addr (self, buf, line, 256))
+ {
+ rxpd_log (base, LOG_ERR, "policy line too long\n");
+ return 0;
+ }
+
+ rxpd_log (base, LOG_DEBUG, "policy check '%s'\n", buf);
+
+ char* match = NULL;
+ LLIST_FOREACH (&base->policy->rules, n)
+ {
+ struct rxpd_rule* rule = (struct rxpd_rule*)n;
+ if (rule->string[0] != '#')
+ {
+ if (regexec (&rule->rx, buf, 0, NULL, 0) == 0)
+ {
+ match = rule->string;
+ break;
+ }
+ }
+ }
+
+ if (!match || strncmp("ACCEPT:", match, sizeof("ACCEPT:")-1) != 0)
+ {
+ rxpd_log (base, LOG_WARNING, "access denied '%s'\n", buf);
+ return 0;
+ }
+ }
+ return 1;
+}
void
rxpd_connection_parse_cmd (int fd, short event, void* ptr)
{
(void) event;
struct rxpd_connection* self = (struct rxpd_connection*) ptr;
+ struct rxpd_base* base = self->socket->base;
char* line;
line = rxpd_buffer_readline (&self->in, 0);
if (!line)
{
- rxpd_log (self->base, LOG_ERR, "no data\n");
+ rxpd_log (base, LOG_ERR, "no data\n");
rxpd_buffer_printf (&self->out, "#ERROR: no data\n");
close (fd);
return;
}
- rxpd_log (self->base, LOG_DEBUG, "parse command '%s'\n", line);
+ rxpd_log (base, LOG_DEBUG, "parse command '%s'\n", line);
static const struct cmd_table
{
break;
if (!i->cmd)
{
- rxpd_log (self->base, LOG_ERR, "no command\n");
+ rxpd_log (base, LOG_ERR, "no command\n");
rxpd_buffer_printf (&self->out, "#ERROR: no command\n");
rxpd_connection_delete (self);
return;
}
- // TODO policy check here
+
+ if (!rxpd_connection_check_policy (self, line))
+ {
+ rxpd_buffer_printf (&self->out, "#ERROR: access denied\n");
+ rxpd_connection_delete (self);
+ return;
+ }
if (line[i->sz])
{
// rulename provided
- self->file = (struct rxpd_file*) psplay_find (&self->base->files, &line[i->sz]);
+ self->file = (struct rxpd_file*) psplay_find (&base->files, &line[i->sz]);
if (!self->file)
{
- self->file = rxpd_file_new (self->base, &line[i->sz]);
+ self->file = rxpd_file_new (base, &line[i->sz]);
if (!self->file)
{
- rxpd_log (self->base, LOG_ERR, "illeagal filename\n");
+ rxpd_log (base, LOG_ERR, "illeagal filename\n");
rxpd_buffer_printf (&self->out, "#ERROR: illegal filename\n");
rxpd_connection_delete (self);
return;
(void) fd;
(void) event;
struct rxpd_connection* self = (struct rxpd_connection*) ptr;
+ struct rxpd_base* base = self->socket->base;
- if (psplay_isempty_root (&self->base->files))
+ if (psplay_isempty_root (&base->files))
rxpd_buffer_printf (&self->out, "#OK:\n");
else
- psplay_walk (&self->base->files, NULL, walk_LIST, 0, ptr);
+ psplay_walk (&base->files, NULL, walk_LIST, 0, ptr);
rxpd_connection_delete (self);
}
(void) fd;
(void) event;
struct rxpd_connection* self = (struct rxpd_connection*) ptr;
+ struct rxpd_base* base = self->socket->base;
// destroy all sockets
- LLIST_WHILE_HEAD (&self->base->sockets, n)
+ LLIST_WHILE_HEAD (&base->sockets, n)
{
struct rxpd_socket* socket = (struct rxpd_socket*)n;
rxpd_socket_delete (socket);