rework socket handling
This commit is contained in:
parent
5cb5a6ffc3
commit
542563babd
|
@ -132,21 +132,57 @@ static int config_parse_listen(
|
|||
void *userdata) {
|
||||
|
||||
int r;
|
||||
SocketPort *p;
|
||||
Socket *s;
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
assert(data);
|
||||
|
||||
if ((r = address_parse(data, rvalue)) < 0) {
|
||||
log_error("[%s:%u] Failed to parse address value: %s", filename, line, rvalue);
|
||||
return r;
|
||||
s = (Socket*) data;
|
||||
|
||||
if (!(p = new0(SocketPort, 1)))
|
||||
return -ENOMEM;
|
||||
|
||||
if (streq(lvalue, "ListenFIFO")) {
|
||||
p->type = SOCKET_FIFO;
|
||||
|
||||
if (!(p->path = strdup(rvalue))) {
|
||||
free(p);
|
||||
return -ENOMEM;
|
||||
}
|
||||
} else {
|
||||
p->type = SOCKET_SOCKET;
|
||||
|
||||
if ((r = socket_address_parse(&p->address, rvalue)) < 0) {
|
||||
log_error("[%s:%u] Failed to parse address value: %s", filename, line, rvalue);
|
||||
free(p);
|
||||
return r;
|
||||
}
|
||||
|
||||
if (streq(lvalue, "ListenStream"))
|
||||
p->address.type = SOCK_STREAM;
|
||||
else if (streq(lvalue, "ListenDatagram"))
|
||||
p->address.type = SOCK_DGRAM;
|
||||
else {
|
||||
assert(streq(lvalue, "ListenSequentialPacket"));
|
||||
p->address.type = SOCK_SEQPACKET;
|
||||
}
|
||||
|
||||
if (socket_address_family(&p->address) != AF_LOCAL && p->address.type == SOCK_SEQPACKET) {
|
||||
free(p);
|
||||
return -EPROTONOSUPPORT;
|
||||
}
|
||||
}
|
||||
|
||||
p->fd = -1;
|
||||
LIST_PREPEND(SocketPort, s->ports, p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int config_parse_type(
|
||||
static int config_parse_bind(
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
|
@ -155,22 +191,23 @@ static int config_parse_type(
|
|||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
int *type = data;
|
||||
int r;
|
||||
Socket *s;
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
assert(data);
|
||||
|
||||
if (streq(rvalue, "stream"))
|
||||
*type = SOCK_STREAM;
|
||||
else if (streq(rvalue, "dgram"))
|
||||
*type = SOCK_DGRAM;
|
||||
else {
|
||||
log_error("[%s:%u] Failed to parse socket type value: %s", filename, line, rvalue);
|
||||
return -EINVAL;
|
||||
s = (Socket*) data;
|
||||
|
||||
if ((r = parse_boolean(rvalue)) < 0) {
|
||||
log_error("[%s:%u] Failed to parse bind IPv6 only value: %s", filename, line, rvalue);
|
||||
return r;
|
||||
}
|
||||
|
||||
s->bind_ipv6_only = r ? SOCKET_ADDRESS_IPV6_ONLY : SOCKET_ADDRESS_BOTH;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -188,18 +225,22 @@ int name_load_fragment(Name *n) {
|
|||
};
|
||||
|
||||
const ConfigItem items[] = {
|
||||
{ "Names", config_parse_names, &n->meta.names, "Meta" },
|
||||
{ "Description", config_parse_string, &n->meta.description, "Meta" },
|
||||
{ "Requires", config_parse_deps, n->meta.dependencies+NAME_REQUIRES, "Meta" },
|
||||
{ "SoftRequires", config_parse_deps, n->meta.dependencies+NAME_SOFT_REQUIRES, "Meta" },
|
||||
{ "Wants", config_parse_deps, n->meta.dependencies+NAME_WANTS, "Meta" },
|
||||
{ "Requisite", config_parse_deps, n->meta.dependencies+NAME_REQUISITE, "Meta" },
|
||||
{ "SoftRequisite", config_parse_deps, n->meta.dependencies+NAME_SOFT_REQUISITE, "Meta" },
|
||||
{ "Conflicts", config_parse_deps, n->meta.dependencies+NAME_CONFLICTS, "Meta" },
|
||||
{ "Before", config_parse_deps, n->meta.dependencies+NAME_BEFORE, "Meta" },
|
||||
{ "After", config_parse_deps, n->meta.dependencies+NAME_AFTER, "Meta" },
|
||||
{ "Listen", config_parse_listen, &n->socket.address, "Socket" },
|
||||
{ "Type", config_parse_type, &n->socket.address.type, "Socket" },
|
||||
{ "Names", config_parse_names, &n->meta.names, "Meta" },
|
||||
{ "Description", config_parse_string, &n->meta.description, "Meta" },
|
||||
{ "Requires", config_parse_deps, n->meta.dependencies+NAME_REQUIRES, "Meta" },
|
||||
{ "SoftRequires", config_parse_deps, n->meta.dependencies+NAME_SOFT_REQUIRES, "Meta" },
|
||||
{ "Wants", config_parse_deps, n->meta.dependencies+NAME_WANTS, "Meta" },
|
||||
{ "Requisite", config_parse_deps, n->meta.dependencies+NAME_REQUISITE, "Meta" },
|
||||
{ "SoftRequisite", config_parse_deps, n->meta.dependencies+NAME_SOFT_REQUISITE, "Meta" },
|
||||
{ "Conflicts", config_parse_deps, n->meta.dependencies+NAME_CONFLICTS, "Meta" },
|
||||
{ "Before", config_parse_deps, n->meta.dependencies+NAME_BEFORE, "Meta" },
|
||||
{ "After", config_parse_deps, n->meta.dependencies+NAME_AFTER, "Meta" },
|
||||
{ "ListenStream", config_parse_listen, &n->socket, "Socket" },
|
||||
{ "ListenDatagram", config_parse_listen, &n->socket, "Socket" },
|
||||
{ "ListenSequentialPacket", config_parse_listen, &n->socket, "Socket" },
|
||||
{ "ListenFIFO", config_parse_listen, &n->socket, "Socket" },
|
||||
{ "BindIPv6Only", config_parse_bind, &n->socket, "Socket" },
|
||||
{ "Backlog", config_parse_unsigned, &n->socket.backlog, "Socket" },
|
||||
{ NULL, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
|
|
14
manager.c
14
manager.c
|
@ -699,28 +699,28 @@ static int transaction_add_job_and_dependencies(Manager *m, JobType type, Name *
|
|||
/* Finally, recursively add in all dependencies. */
|
||||
if (type == JOB_START || type == JOB_RELOAD_OR_START) {
|
||||
SET_FOREACH(dep, ret->name->meta.dependencies[NAME_REQUIRES], state)
|
||||
if ((r = transaction_add_job_and_dependencies(m, JOB_START, dep, ret, true, force, NULL)) != -EBADR)
|
||||
if ((r = transaction_add_job_and_dependencies(m, JOB_START, dep, ret, true, force, NULL)) < 0 && r != -EBADR)
|
||||
goto fail;
|
||||
SET_FOREACH(dep, ret->name->meta.dependencies[NAME_SOFT_REQUIRES], state)
|
||||
if ((r = transaction_add_job_and_dependencies(m, JOB_START, dep, ret, !force, force, NULL)) != -EBADR)
|
||||
if ((r = transaction_add_job_and_dependencies(m, JOB_START, dep, ret, !force, force, NULL)) < 0 && r != -EBADR)
|
||||
goto fail;
|
||||
SET_FOREACH(dep, ret->name->meta.dependencies[NAME_WANTS], state)
|
||||
if ((r = transaction_add_job_and_dependencies(m, JOB_START, dep, ret, false, force, NULL)) != -EBADR)
|
||||
if ((r = transaction_add_job_and_dependencies(m, JOB_START, dep, ret, false, force, NULL)) < 0 && r != -EBADR)
|
||||
goto fail;
|
||||
SET_FOREACH(dep, ret->name->meta.dependencies[NAME_REQUISITE], state)
|
||||
if ((r = transaction_add_job_and_dependencies(m, JOB_VERIFY_ACTIVE, dep, ret, true, force, NULL)) != -EBADR)
|
||||
if ((r = transaction_add_job_and_dependencies(m, JOB_VERIFY_ACTIVE, dep, ret, true, force, NULL)) < 0 && r != -EBADR)
|
||||
goto fail;
|
||||
SET_FOREACH(dep, ret->name->meta.dependencies[NAME_SOFT_REQUISITE], state)
|
||||
if ((r = transaction_add_job_and_dependencies(m, JOB_VERIFY_ACTIVE, dep, ret, !force, force, NULL)) != -EBADR)
|
||||
if ((r = transaction_add_job_and_dependencies(m, JOB_VERIFY_ACTIVE, dep, ret, !force, force, NULL)) < 0 && r != -EBADR)
|
||||
goto fail;
|
||||
SET_FOREACH(dep, ret->name->meta.dependencies[NAME_CONFLICTS], state)
|
||||
if ((r = transaction_add_job_and_dependencies(m, JOB_STOP, dep, ret, true, force, NULL)) != -EBADR)
|
||||
if ((r = transaction_add_job_and_dependencies(m, JOB_STOP, dep, ret, true, force, NULL)) < 0 && r != -EBADR)
|
||||
goto fail;
|
||||
|
||||
} else if (type == JOB_STOP || type == JOB_RESTART || type == JOB_TRY_RESTART) {
|
||||
|
||||
SET_FOREACH(dep, ret->name->meta.dependencies[NAME_REQUIRED_BY], state)
|
||||
if ((r = transaction_add_job_and_dependencies(m, type, dep, ret, true, force, NULL)) != -EBADR)
|
||||
if ((r = transaction_add_job_and_dependencies(m, type, dep, ret, true, force, NULL)) < 0 && r != -EBADR)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
|
1
name.c
1
name.c
|
@ -367,6 +367,7 @@ void name_dump(Name *n, FILE *f, const char *prefix) {
|
|||
[NAME_SOFT_REQUISITE] = "SoftRequisite",
|
||||
[NAME_REQUIRED_BY] = "RequiredBy",
|
||||
[NAME_SOFT_REQUIRED_BY] = "SoftRequiredBy",
|
||||
[NAME_WANTED_BY] = "WantedBy",
|
||||
[NAME_CONFLICTS] = "Conflicts",
|
||||
[NAME_BEFORE] = "Before",
|
||||
[NAME_AFTER] = "After",
|
||||
|
|
|
@ -7,12 +7,13 @@
|
|||
#include <stdlib.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <stdio.h>
|
||||
#include <net/if.h>
|
||||
|
||||
#include "macro.h"
|
||||
#include "util.h"
|
||||
#include "socket-util.h"
|
||||
|
||||
int address_parse(Address *a, const char *s) {
|
||||
int socket_address_parse(SocketAddress *a, const char *s) {
|
||||
int r;
|
||||
char *e, *n;
|
||||
unsigned u;
|
||||
|
@ -21,6 +22,7 @@ int address_parse(Address *a, const char *s) {
|
|||
assert(s);
|
||||
|
||||
memset(a, 0, sizeof(*a));
|
||||
a->type = SOCK_STREAM;
|
||||
|
||||
if (*s == '[') {
|
||||
/* IPv6 in [x:.....:z]:p notation */
|
||||
|
@ -53,7 +55,6 @@ int address_parse(Address *a, const char *s) {
|
|||
a->sockaddr.in6.sin6_family = AF_INET6;
|
||||
a->sockaddr.in6.sin6_port = htons((uint16_t) u);
|
||||
a->size = sizeof(struct sockaddr_in6);
|
||||
a->bind_ipv6_only = true;
|
||||
|
||||
} else if (*s == '/') {
|
||||
/* AF_UNIX socket */
|
||||
|
@ -83,29 +84,46 @@ int address_parse(Address *a, const char *s) {
|
|||
} else {
|
||||
|
||||
if ((e = strchr(s, ':'))) {
|
||||
int r;
|
||||
|
||||
/* IPv4 in w.x.y.z:p notation */
|
||||
if (!(n = strndup(s, e-s)))
|
||||
return -ENOMEM;
|
||||
|
||||
errno = 0;
|
||||
if (inet_pton(AF_INET, n, &a->sockaddr.in4.sin_addr) <= 0) {
|
||||
free(n);
|
||||
return errno != 0 ? -errno : -EINVAL;
|
||||
}
|
||||
|
||||
free(n);
|
||||
|
||||
e++;
|
||||
if ((r = safe_atou(e, &u)) < 0)
|
||||
if ((r = safe_atou(e+1, &u)) < 0)
|
||||
return r;
|
||||
|
||||
if (u <= 0 || u > 0xFFFF)
|
||||
return -EINVAL;
|
||||
|
||||
a->sockaddr.in4.sin_family = AF_INET;
|
||||
a->sockaddr.in4.sin_port = htons((uint16_t) u);
|
||||
a->size = sizeof(struct sockaddr_in);
|
||||
if (!(n = strndup(s, e-s)))
|
||||
return -ENOMEM;
|
||||
|
||||
/* IPv4 in w.x.y.z:p notation? */
|
||||
if ((r = inet_pton(AF_INET, n, &a->sockaddr.in4.sin_addr)) < 0) {
|
||||
free(n);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (r > 0) {
|
||||
/* Gotcha, it's a traditional IPv4 address */
|
||||
free(n);
|
||||
|
||||
a->sockaddr.in4.sin_family = AF_INET;
|
||||
a->sockaddr.in4.sin_port = htons((uint16_t) u);
|
||||
a->size = sizeof(struct sockaddr_in);
|
||||
} else {
|
||||
unsigned idx;
|
||||
|
||||
/* Uh, our last resort, an interface name */
|
||||
idx = if_nametoindex(n);
|
||||
free(n);
|
||||
|
||||
if (n == 0)
|
||||
return -EINVAL;
|
||||
|
||||
a->sockaddr.in6.sin6_family = AF_INET6;
|
||||
a->sockaddr.in6.sin6_port = htons((uint16_t) u);
|
||||
a->sockaddr.in6.sin6_scope_id = idx;
|
||||
memcpy(&a->sockaddr.in6.sin6_addr, &in6addr_any, INET6_ADDRSTRLEN);
|
||||
a->size = sizeof(struct sockaddr_in6);
|
||||
}
|
||||
} else {
|
||||
|
||||
/* Just a port */
|
||||
|
@ -116,8 +134,8 @@ int address_parse(Address *a, const char *s) {
|
|||
return -EINVAL;
|
||||
|
||||
a->sockaddr.in6.sin6_family = AF_INET6;
|
||||
memcpy(&a->sockaddr.in6.sin6_addr, &in6addr_any, INET6_ADDRSTRLEN);
|
||||
a->sockaddr.in6.sin6_port = htons((uint16_t) u);
|
||||
memcpy(&a->sockaddr.in6.sin6_addr, &in6addr_any, INET6_ADDRSTRLEN);
|
||||
a->size = sizeof(struct sockaddr_in6);
|
||||
}
|
||||
}
|
||||
|
@ -125,10 +143,10 @@ int address_parse(Address *a, const char *s) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int address_verify(const Address *a) {
|
||||
int socket_address_verify(const SocketAddress *a) {
|
||||
assert(a);
|
||||
|
||||
switch (address_family(a)) {
|
||||
switch (socket_address_family(a)) {
|
||||
case AF_INET:
|
||||
if (a->size != sizeof(struct sockaddr_in))
|
||||
return -EINVAL;
|
||||
|
@ -176,15 +194,15 @@ int address_verify(const Address *a) {
|
|||
}
|
||||
}
|
||||
|
||||
int address_print(const Address *a, char **p) {
|
||||
int socket_address_print(const SocketAddress *a, char **p) {
|
||||
int r;
|
||||
assert(a);
|
||||
assert(p);
|
||||
|
||||
if ((r = address_verify(a)) < 0)
|
||||
if ((r = socket_address_verify(a)) < 0)
|
||||
return r;
|
||||
|
||||
switch (address_family(a)) {
|
||||
switch (socket_address_family(a)) {
|
||||
case AF_INET: {
|
||||
char *ret;
|
||||
|
||||
|
@ -256,16 +274,25 @@ int address_print(const Address *a, char **p) {
|
|||
}
|
||||
}
|
||||
|
||||
int address_listen(const Address *a, int backlog) {
|
||||
int socket_address_listen(const SocketAddress *a, int backlog, SocketAddressBindIPv6Only only) {
|
||||
int r, fd;
|
||||
assert(a);
|
||||
|
||||
if ((r = address_verify(a)) < 0)
|
||||
if ((r = socket_address_verify(a)) < 0)
|
||||
return r;
|
||||
|
||||
if ((fd = socket(address_family(a), a->type, 0)) < 0)
|
||||
if ((fd = socket(socket_address_family(a), a->type | SOCK_NONBLOCK | SOCK_CLOEXEC, 0)) < 0)
|
||||
return -errno;
|
||||
|
||||
if (socket_address_family(a) == AF_INET6 && only != SOCKET_ADDRESS_DEFAULT) {
|
||||
int flag = only == SOCKET_ADDRESS_IPV6_ONLY;
|
||||
|
||||
if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &flag, sizeof(flag)) < 0) {
|
||||
close_nointr(fd);
|
||||
return -errno;
|
||||
}
|
||||
}
|
||||
|
||||
if (bind(fd, &a->sockaddr.sa, a->size) < 0) {
|
||||
close_nointr(fd);
|
||||
return -errno;
|
||||
|
@ -277,14 +304,5 @@ int address_listen(const Address *a, int backlog) {
|
|||
return -errno;
|
||||
}
|
||||
|
||||
if (address_family(a) == AF_INET6) {
|
||||
int flag = a->bind_ipv6_only;
|
||||
|
||||
if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &flag, sizeof(flag)) < 0) {
|
||||
close_nointr(fd);
|
||||
return -errno;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#include "macro.h"
|
||||
#include "util.h"
|
||||
|
||||
typedef struct Address {
|
||||
typedef struct SocketAddress {
|
||||
union {
|
||||
struct sockaddr sa;
|
||||
struct sockaddr_in in4;
|
||||
|
@ -25,16 +25,19 @@ typedef struct Address {
|
|||
|
||||
/* Socket type, i.e. SOCK_STREAM, SOCK_DGRAM, ... */
|
||||
int type;
|
||||
} SocketAddress;
|
||||
|
||||
/* Only for INET6 sockets: issue IPV6_V6ONLY sockopt */
|
||||
bool bind_ipv6_only;
|
||||
} Address;
|
||||
typedef enum SocketAddressBindIPv6Only {
|
||||
SOCKET_ADDRESS_DEFAULT,
|
||||
SOCKET_ADDRESS_BOTH,
|
||||
SOCKET_ADDRESS_IPV6_ONLY
|
||||
} SocketAddressBindIPv6Only;
|
||||
|
||||
#define address_family(a) ((a)->sockaddr.sa.sa_family)
|
||||
#define socket_address_family(a) ((a)->sockaddr.sa.sa_family)
|
||||
|
||||
int address_parse(Address *a, const char *s);
|
||||
int address_print(const Address *a, char **p);
|
||||
int address_verify(const Address *a);
|
||||
int address_listen(const Address *a, int backlog);
|
||||
int socket_address_parse(SocketAddress *a, const char *s);
|
||||
int socket_address_print(const SocketAddress *a, char **p);
|
||||
int socket_address_verify(const SocketAddress *a);
|
||||
int socket_address_listen(const SocketAddress *a, int backlog, SocketAddressBindIPv6Only only);
|
||||
|
||||
#endif
|
||||
|
|
71
socket.c
71
socket.c
|
@ -7,10 +7,24 @@ static int socket_load(Name *n) {
|
|||
Socket *s = SOCKET(n);
|
||||
|
||||
exec_context_defaults(&s->exec_context);
|
||||
s->backlog = SOMAXCONN;
|
||||
|
||||
return name_load_fragment_and_dropin(n);
|
||||
}
|
||||
|
||||
static const char* listen_lookup(int type) {
|
||||
|
||||
if (type == SOCK_STREAM)
|
||||
return "ListenStream";
|
||||
else if (type == SOCK_DGRAM)
|
||||
return "ListenDatagram";
|
||||
else if (type == SOCK_SEQPACKET)
|
||||
return "ListenSequentialPacket";
|
||||
|
||||
assert_not_reached("Unkown socket type");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void socket_dump(Name *n, FILE *f, const char *prefix) {
|
||||
|
||||
static const char* const state_table[_SOCKET_STATE_MAX] = {
|
||||
|
@ -33,24 +47,35 @@ static void socket_dump(Name *n, FILE *f, const char *prefix) {
|
|||
|
||||
SocketExecCommand c;
|
||||
Socket *s = SOCKET(n);
|
||||
const char *t;
|
||||
int r;
|
||||
char *k;
|
||||
SocketPort *p;
|
||||
|
||||
assert(s);
|
||||
|
||||
if ((r = address_print(&n->socket.address, &k)) < 0)
|
||||
t = strerror(-r);
|
||||
else
|
||||
t = k;
|
||||
|
||||
fprintf(f,
|
||||
"%sSocket State: %s\n"
|
||||
"%sAddress: %s\n",
|
||||
"%sBindIPv6Only: %s\n"
|
||||
"%sBacklog: %u\n",
|
||||
prefix, state_table[s->state],
|
||||
prefix, t);
|
||||
prefix, yes_no(s->bind_ipv6_only),
|
||||
prefix, s->backlog);
|
||||
|
||||
free(k);
|
||||
LIST_FOREACH(p, s->ports) {
|
||||
|
||||
if (p->type == SOCKET_SOCKET) {
|
||||
const char *t;
|
||||
int r;
|
||||
char *k;
|
||||
|
||||
if ((r = socket_address_print(&p->address, &k)) < 0)
|
||||
t = strerror(-r);
|
||||
else
|
||||
t = k;
|
||||
|
||||
fprintf(f, "%s%s: %s\n", prefix, listen_lookup(p->address.type), k);
|
||||
free(k);
|
||||
} else
|
||||
fprintf(f, "%sListenFIFO: %s\n", prefix, p->path);
|
||||
}
|
||||
|
||||
exec_context_dump(&s->exec_context, f, prefix);
|
||||
|
||||
|
@ -62,6 +87,14 @@ static void socket_dump(Name *n, FILE *f, const char *prefix) {
|
|||
}
|
||||
}
|
||||
|
||||
static int socket_start(Name *n) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int socket_stop(Name *n) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static NameActiveState socket_active_state(Name *n) {
|
||||
|
||||
static const NameActiveState table[_SOCKET_STATE_MAX] = {
|
||||
|
@ -79,14 +112,20 @@ static NameActiveState socket_active_state(Name *n) {
|
|||
}
|
||||
|
||||
static void socket_free_hook(Name *n) {
|
||||
unsigned i;
|
||||
SocketExecCommand c;
|
||||
Socket *s = SOCKET(n);
|
||||
SocketPort *p;
|
||||
|
||||
assert(s);
|
||||
|
||||
for (i = 0; i < s->n_fds; i++)
|
||||
close_nointr(s->fds[i]);
|
||||
while ((p = s->ports)) {
|
||||
LIST_REMOVE(SocketPort, s->ports, p);
|
||||
|
||||
if (p->fd >= 0)
|
||||
close_nointr(p->fd);
|
||||
free(p->path);
|
||||
free(p);
|
||||
}
|
||||
|
||||
exec_context_free(&s->exec_context);
|
||||
|
||||
|
@ -103,8 +142,8 @@ const NameVTable socket_vtable = {
|
|||
.load = socket_load,
|
||||
.dump = socket_dump,
|
||||
|
||||
.start = NULL,
|
||||
.stop = NULL,
|
||||
.start = socket_start,
|
||||
.stop = socket_stop,
|
||||
.reload = NULL,
|
||||
|
||||
.active_state = socket_active_state,
|
||||
|
|
27
socket.h
27
socket.h
|
@ -6,6 +6,7 @@
|
|||
typedef struct Socket Socket;
|
||||
|
||||
#include "name.h"
|
||||
#include "socket-util.h"
|
||||
|
||||
typedef enum SocketState {
|
||||
SOCKET_DEAD,
|
||||
|
@ -27,14 +28,34 @@ typedef enum SocketExecCommand {
|
|||
_SOCKET_EXEC_MAX
|
||||
} SocketExecCommand;
|
||||
|
||||
typedef enum SocketType {
|
||||
SOCKET_SOCKET,
|
||||
SOCKET_FIFO
|
||||
} SocketType;
|
||||
|
||||
typedef struct SocketPort SocketPort;
|
||||
|
||||
struct SocketPort {
|
||||
SocketType type;
|
||||
|
||||
SocketAddress address;
|
||||
char *path;
|
||||
|
||||
int fd;
|
||||
|
||||
LIST_FIELDS(SocketPort);
|
||||
};
|
||||
|
||||
struct Socket {
|
||||
Meta meta;
|
||||
|
||||
SocketState state;
|
||||
|
||||
Address address;
|
||||
int *fds;
|
||||
unsigned n_fds;
|
||||
LIST_HEAD(SocketPort, ports);
|
||||
|
||||
/* Only for INET6 sockets: issue IPV6_V6ONLY sockopt */
|
||||
bool bind_ipv6_only;
|
||||
unsigned backlog;
|
||||
|
||||
ExecCommand* exec_command[_SOCKET_EXEC_MAX];
|
||||
ExecContext exec_context;
|
||||
|
|
|
@ -2,5 +2,5 @@
|
|||
Description=Postfix SMTP Socket
|
||||
|
||||
[Socket]
|
||||
Listen=25
|
||||
Type=stream
|
||||
ListenStream=25
|
||||
ListenFIFO=/dev/test
|
||||
|
|
|
@ -2,5 +2,5 @@
|
|||
Description=Syslog Socket
|
||||
|
||||
[Socket]
|
||||
Listen=/dev/log
|
||||
Type=dgram
|
||||
ListenDatagram=/dev/log
|
||||
ListenStream=eth0:4711
|
||||
|
|
Loading…
Reference in New Issue