Defined sk_close() which closes the socket safely even if called from
socket hook. Replaces the SK_DELETED hack. Squashed a couple of bugs in handling of TCP sockets.
This commit is contained in:
parent
3a6337ecb2
commit
320f417357
3 changed files with 47 additions and 20 deletions
|
@ -38,10 +38,12 @@ typedef struct birdsock {
|
||||||
|
|
||||||
int fd; /* System-dependent data */
|
int fd; /* System-dependent data */
|
||||||
node n;
|
node n;
|
||||||
|
int entered;
|
||||||
} sock;
|
} sock;
|
||||||
|
|
||||||
sock *sk_new(pool *); /* Allocate new socket */
|
sock *sk_new(pool *); /* Allocate new socket */
|
||||||
int sk_open(sock *); /* Open socket */
|
int sk_open(sock *); /* Open socket */
|
||||||
|
void sk_close(sock *); /* Safe close of socket even from socket hook */
|
||||||
int sk_send(sock *, unsigned len); /* Send data, <0=err, >0=ok, 0=sleep */
|
int sk_send(sock *, unsigned len); /* Send data, <0=err, >0=ok, 0=sleep */
|
||||||
int sk_send_to(sock *, unsigned len, ip_addr to, unsigned port); /* sk_send to given destination */
|
int sk_send_to(sock *, unsigned len, ip_addr to, unsigned port); /* sk_send to given destination */
|
||||||
void sk_dump_all(void);
|
void sk_dump_all(void);
|
||||||
|
@ -66,7 +68,7 @@ sk_send_buffer_empty(sock *sk)
|
||||||
#define SK_MAGIC 7 /* Internal use by sysdep code */
|
#define SK_MAGIC 7 /* Internal use by sysdep code */
|
||||||
#define SK_UNIX_PASSIVE 8
|
#define SK_UNIX_PASSIVE 8
|
||||||
#define SK_UNIX 9
|
#define SK_UNIX 9
|
||||||
#define SK_DELETED 10 /* Set to this if you want to delete socket from err_hook */
|
#define SK_DELETED 10 /* Internal use by sk_close */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Multicast sockets are slightly different from the other ones:
|
* Multicast sockets are slightly different from the other ones:
|
||||||
|
|
|
@ -336,8 +336,11 @@ sk_free(resource *r)
|
||||||
sock *s = (sock *) r;
|
sock *s = (sock *) r;
|
||||||
|
|
||||||
if (s->fd >= 0)
|
if (s->fd >= 0)
|
||||||
|
{
|
||||||
|
close(s->fd);
|
||||||
rem_node(&s->n);
|
rem_node(&s->n);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sk_dump(resource *r)
|
sk_dump(resource *r)
|
||||||
|
@ -382,6 +385,7 @@ sk_new(pool *p)
|
||||||
s->tbsize = 0;
|
s->tbsize = 0;
|
||||||
s->err_hook = NULL;
|
s->err_hook = NULL;
|
||||||
s->fd = -1;
|
s->fd = -1;
|
||||||
|
s->entered = 0;
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -477,9 +481,9 @@ sk_alloc_bufs(sock *s)
|
||||||
static void
|
static void
|
||||||
sk_tcp_connected(sock *s)
|
sk_tcp_connected(sock *s)
|
||||||
{
|
{
|
||||||
s->rx_hook(s, 0);
|
|
||||||
s->type = SK_TCP;
|
s->type = SK_TCP;
|
||||||
sk_alloc_bufs(s);
|
sk_alloc_bufs(s);
|
||||||
|
s->tx_hook(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -524,6 +528,8 @@ sk_open(sock *s)
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case SK_TCP_ACTIVE:
|
case SK_TCP_ACTIVE:
|
||||||
|
s->ttx = ""; /* Force s->ttx != s->tpos */
|
||||||
|
/* Fall thru */
|
||||||
case SK_TCP_PASSIVE:
|
case SK_TCP_PASSIVE:
|
||||||
fd = socket(BIRD_PF, SOCK_STREAM, IPPROTO_TCP);
|
fd = socket(BIRD_PF, SOCK_STREAM, IPPROTO_TCP);
|
||||||
break;
|
break;
|
||||||
|
@ -625,6 +631,7 @@ sk_open(sock *s)
|
||||||
case SK_MAGIC:
|
case SK_MAGIC:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
sk_alloc_bufs(s);
|
||||||
#ifdef IPV6
|
#ifdef IPV6
|
||||||
#ifdef IPV6_MTU_DISCOVER
|
#ifdef IPV6_MTU_DISCOVER
|
||||||
{
|
{
|
||||||
|
@ -644,7 +651,6 @@ sk_open(sock *s)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
sk_alloc_bufs(s);
|
|
||||||
add_tail(&sock_list, &s->n);
|
add_tail(&sock_list, &s->n);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -686,6 +692,15 @@ bad:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sk_close(sock *s)
|
||||||
|
{
|
||||||
|
if (s->entered)
|
||||||
|
s->type = SK_DELETED;
|
||||||
|
else
|
||||||
|
rfree(s);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
sk_maybe_write(sock *s)
|
sk_maybe_write(sock *s)
|
||||||
{
|
{
|
||||||
|
@ -767,19 +782,6 @@ sk_read(sock *s)
|
||||||
{
|
{
|
||||||
switch (s->type)
|
switch (s->type)
|
||||||
{
|
{
|
||||||
case SK_TCP_ACTIVE:
|
|
||||||
{
|
|
||||||
sockaddr sa;
|
|
||||||
fill_in_sockaddr(&sa, s->daddr, s->dport);
|
|
||||||
if (connect(s->fd, (struct sockaddr *) &sa, sizeof(sa)) >= 0)
|
|
||||||
sk_tcp_connected(s);
|
|
||||||
else if (errno != EINTR && errno != EAGAIN && errno != EINPROGRESS)
|
|
||||||
{
|
|
||||||
log(L_ERR "connect: %m");
|
|
||||||
s->err_hook(s, errno);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
case SK_TCP_PASSIVE:
|
case SK_TCP_PASSIVE:
|
||||||
{
|
{
|
||||||
sockaddr sa;
|
sockaddr sa;
|
||||||
|
@ -816,6 +818,8 @@ sk_read(sock *s)
|
||||||
}
|
}
|
||||||
case SK_MAGIC:
|
case SK_MAGIC:
|
||||||
return s->rx_hook(s, 0);
|
return s->rx_hook(s, 0);
|
||||||
|
case SK_DELETED:
|
||||||
|
return 0;
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
sockaddr sa;
|
sockaddr sa;
|
||||||
|
@ -842,9 +846,28 @@ sk_read(sock *s)
|
||||||
static void
|
static void
|
||||||
sk_write(sock *s)
|
sk_write(sock *s)
|
||||||
{
|
{
|
||||||
|
switch (s->type)
|
||||||
|
{
|
||||||
|
case SK_TCP_ACTIVE:
|
||||||
|
{
|
||||||
|
sockaddr sa;
|
||||||
|
fill_in_sockaddr(&sa, s->daddr, s->dport);
|
||||||
|
if (connect(s->fd, (struct sockaddr *) &sa, sizeof(sa)) >= 0)
|
||||||
|
sk_tcp_connected(s);
|
||||||
|
else if (errno != EINTR && errno != EAGAIN && errno != EINPROGRESS)
|
||||||
|
{
|
||||||
|
log(L_ERR "connect: %m");
|
||||||
|
s->err_hook(s, errno);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SK_DELETED:
|
||||||
|
return;
|
||||||
|
default:
|
||||||
while (s->ttx != s->tbuf && sk_maybe_write(s) > 0)
|
while (s->ttx != s->tbuf && sk_maybe_write(s) > 0)
|
||||||
s->tx_hook(s);
|
s->tx_hook(s);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
sk_dump_all(void)
|
sk_dump_all(void)
|
||||||
|
@ -965,6 +988,7 @@ io_loop(void)
|
||||||
WALK_LIST_DELSAFE(n, p, sock_list)
|
WALK_LIST_DELSAFE(n, p, sock_list)
|
||||||
{
|
{
|
||||||
s = SKIP_BACK(sock, n, n);
|
s = SKIP_BACK(sock, n, n);
|
||||||
|
s->entered = 1;
|
||||||
if (FD_ISSET(s->fd, &rd))
|
if (FD_ISSET(s->fd, &rd))
|
||||||
{
|
{
|
||||||
FD_CLR(s->fd, &rd);
|
FD_CLR(s->fd, &rd);
|
||||||
|
@ -976,6 +1000,7 @@ io_loop(void)
|
||||||
FD_CLR(s->fd, &wr);
|
FD_CLR(s->fd, &wr);
|
||||||
sk_write(s);
|
sk_write(s);
|
||||||
}
|
}
|
||||||
|
s->entered = 0;
|
||||||
if (s->type == SK_DELETED)
|
if (s->type == SK_DELETED)
|
||||||
rfree(s);
|
rfree(s);
|
||||||
}
|
}
|
||||||
|
|
|
@ -236,8 +236,8 @@ cli_err(sock *s, int err)
|
||||||
log(L_INFO "CLI connection dropped: %s", strerror(err));
|
log(L_INFO "CLI connection dropped: %s", strerror(err));
|
||||||
else
|
else
|
||||||
log(L_INFO "CLI connection closed");
|
log(L_INFO "CLI connection closed");
|
||||||
s->type = SK_DELETED;
|
|
||||||
cli_free(s->data);
|
cli_free(s->data);
|
||||||
|
sk_close(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|
Loading…
Reference in a new issue