Module: sip-router
Branch: master
Commit: b558d12e5dc1274ef5933bf03e2bdd6b0546eeae
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=b558d12…
Author: Juha Heinanen <jh(a)tutpro.com>
Committer: Juha Heinanen <jh(a)tutpro.com>
Date: Thu Jun 17 13:03:35 2010 +0300
modules/lcr: fixed bsearch argument plus doc improvements
- First bsearch argument must be of type struct gw_info.
- README improvements.
---
modules/lcr/README | 14 ++++++------
modules/lcr/doc/lcr_admin.xml | 5 ++-
modules/lcr/lcr_mod.c | 48 +++++++++++++++++++++++-----------------
3 files changed, 38 insertions(+), 29 deletions(-)
diff --git a/modules/lcr/README b/modules/lcr/README
index 7f3f795..5a4a31a 100644
--- a/modules/lcr/README
+++ b/modules/lcr/README
@@ -850,8 +850,8 @@ if (from_gw("1", "$avp(s:real_source_addr)") {
4.5. from_any_gw([ip_addr])
- Checks if request comes from IP address of any gateway. Only LCR
- instances, where all gateways have IP address, are included in the
+ Checks if request comes from IP address and port of any gateway. Only
+ LCR instances, where all gateways have IP address, are included in the
test. IP address to be checked is either taken from source IP address
of the request or (if present) from ip_addr pseudo variable argument.
@@ -875,11 +875,11 @@ $var(lcr_id) = from_any_gw();
4.6. to_gw(lcr_id [, ip_addr])
- Checks if in-dialog request goes to a gateway in LCR instance specified
- by lcr_id argument. Fails if LCR instance includes one or more gateways
- without IP address. IP address to be checked is either taken from
- Request-URI hostpart or (if present) from ip_addr pseudo variable
- argument.
+ Checks if in-dialog request goes to IP address and port of a gateway in
+ LCR instance specified by lcr_id argument. Fails if LCR instance
+ includes one or more gateways without IP address. IP address to be
+ checked is either taken from Request-URI hostpart or (if present) from
+ ip_addr pseudo variable argument.
Returns 1 on success and -1 on failure and error.
diff --git a/modules/lcr/doc/lcr_admin.xml b/modules/lcr/doc/lcr_admin.xml
index 7d59972..764392f 100644
--- a/modules/lcr/doc/lcr_admin.xml
+++ b/modules/lcr/doc/lcr_admin.xml
@@ -1105,7 +1105,7 @@ if (from_gw("1", "$avp(s:real_source_addr)") {
<function moreinfo="none">from_any_gw([ip_addr])</function>
</title>
<para>
- Checks if request comes from IP address of
+ Checks if request comes from IP address and port of
any gateway. Only LCR instances, where all gateways
have IP address, are included in the test.
IP address to be checked is either
@@ -1145,7 +1145,8 @@ $var(lcr_id) = from_any_gw();
<function moreinfo="none">to_gw(lcr_id [, ip_addr])</function>
</title>
<para>
- Checks if in-dialog request goes to a gateway in LCR
+ Checks if in-dialog request goes to IP address and port
+ of a gateway in LCR
instance specified by lcr_id argument. Fails if LCR
instance includes one or more gateways without IP
address. IP address to be
diff --git a/modules/lcr/lcr_mod.c b/modules/lcr/lcr_mod.c
index 7594c1b..e3603cb 100644
--- a/modules/lcr/lcr_mod.c
+++ b/modules/lcr/lcr_mod.c
@@ -769,7 +769,7 @@ static pcre *reg_ex_comp(const char *pattern)
/*
- * Compare gateways based on their IP address and port
+ * Compare gateways based on their IP address
*/
static int comp_gws(const void *_g1, const void *_g2)
{
@@ -779,9 +779,6 @@ static int comp_gws(const void *_g1, const void *_g2)
if (g1->ip_addr < g2->ip_addr) return -1;
if (g1->ip_addr > g2->ip_addr) return 1;
- if (g1->port < g2->port) return -1;
- if (g1->port > g2->port) return 1;
-
return 0;
}
@@ -2057,12 +2054,12 @@ static int next_gw(struct sip_msg* _m, char* _s1, char* _s2)
/*
- * Checks if request comes from a gateway
+ * Checks if request comes from ip address of a gateway
*/
static int do_from_gw(struct sip_msg* _m, unsigned int lcr_id,
unsigned int src_addr)
{
- struct gw_info *res, *gws;
+ struct gw_info *res, gw, *gws;
int_str val;
gws = gw_pt[lcr_id];
@@ -2073,8 +2070,9 @@ static int do_from_gw(struct sip_msg* _m, unsigned int lcr_id,
return -1;
}
- /* Search for gw address */
- res = (struct gw_info *)bsearch(&src_addr, &(gws[1]), gws[0].ip_addr,
+ /* Search for gw ip address */
+ gw.ip_addr = src_addr;
+ res = (struct gw_info *)bsearch(&gw, &(gws[1]), gws[0].ip_addr,
sizeof(struct gw_info), comp_gws);
/* Store flags and return result */
@@ -2092,7 +2090,8 @@ static int do_from_gw(struct sip_msg* _m, unsigned int lcr_id,
/*
- * Checks if request comes from a gateway taking src_address from reques.
+ * Checks if request comes from ip address of a gateway taking source
+ * address from request.
*/
static int from_gw_1(struct sip_msg* _m, char* _lcr_id, char* _s2)
{
@@ -2118,7 +2117,8 @@ static int from_gw_1(struct sip_msg* _m, char* _lcr_id, char* _s2)
/*
- * Checks if request comes from a gateway taking source address from param.
+ * Checks if request comes from ip address of a gateway taking source
+ * address from param.
*/
static int from_gw_2(struct sip_msg* _m, char* _lcr_id, char* _addr)
{
@@ -2163,7 +2163,8 @@ static int from_gw_2(struct sip_msg* _m, char* _lcr_id, char* _addr)
/*
- * Checks if request comes from any gateway taking source address from request.
+ * Checks if request comes from ip address of any gateway taking source
+ * address from request.
*/
static int from_any_gw_0(struct sip_msg* _m, char* _s1, char* _s2)
{
@@ -2181,7 +2182,8 @@ static int from_any_gw_0(struct sip_msg* _m, char* _s1, char* _s2)
/*
- * Checks if request comes from a gateway taking source address from param.
+ * Checks if request comes from ip address of a a gateway taking source
+ * address from param.
*/
static int from_any_gw_1(struct sip_msg* _m, char* _addr, char* _s2)
{
@@ -2221,12 +2223,12 @@ static int from_any_gw_1(struct sip_msg* _m, char* _addr, char* _s2)
/*
- * Checks if in-dialog request goes to gateway
+ * Checks if in-dialog request goes to ip address of a gateway.
*/
static int do_to_gw(struct sip_msg* _m, unsigned int lcr_id,
unsigned int dst_addr)
{
- struct gw_info *res, *gws;
+ struct gw_info *res, gw, *gws;
gws = gw_pt[lcr_id];
@@ -2236,8 +2238,9 @@ static int do_to_gw(struct sip_msg* _m, unsigned int lcr_id,
return -1;
}
- /* Search for gw address */
- res = (struct gw_info *)bsearch(&dst_addr, &(gws[1]), gws[0].ip_addr,
+ /* Search for gw ip address */
+ gw.ip_addr = dst_addr;
+ res = (struct gw_info *)bsearch(&gw, &(gws[1]), gws[0].ip_addr,
sizeof(struct gw_info), comp_gws);
/* Return result */
@@ -2252,7 +2255,8 @@ static int do_to_gw(struct sip_msg* _m, unsigned int lcr_id,
/*
- * Checks if request goes to a gateway taking destination address from request.
+ * Checks if request goes to ip address of a gateway taking destination
+ * address from Request URI.
*/
static int to_gw_1(struct sip_msg* _m, char* _lcr_id, char* _s2)
{
@@ -2294,7 +2298,8 @@ static int to_gw_1(struct sip_msg* _m, char* _lcr_id, char* _s2)
/*
- * Checks if request goes to a gateway, taking destination address from param.
+ * Checks if request goes to ip address of a gateway taking destination
+ * address from param.
*/
static int to_gw_2(struct sip_msg* _m, char* _lcr_id, char* _addr)
{
@@ -2339,7 +2344,8 @@ static int to_gw_2(struct sip_msg* _m, char* _lcr_id, char* _addr)
/*
- * Checks if request goes to any gateway taking dst_addr from request.
+ * Checks if request goes to ip address of any gateway taking destination
+ * address from Request-URI.
*/
static int to_any_gw_0(struct sip_msg* _m, char* _s1, char* _s2)
{
@@ -2364,6 +2370,7 @@ static int to_any_gw_0(struct sip_msg* _m, char* _s1, char* _s2)
dst_addr = ip->u.addr32[0];
}
+ /* Do test */
for (i = 1; i <= lcr_count_param; i++) {
if (do_to_gw(_m, i, dst_addr) == 1) {
return i;
@@ -2374,7 +2381,8 @@ static int to_any_gw_0(struct sip_msg* _m, char* _s1, char* _s2)
/*
- * Checks if request goes to any gateway taking dst_addr from param.
+ * Checks if request goes to ip address of any gateway taking destination
+ * address from param.
*/
static int to_any_gw_1(struct sip_msg* _m, char* _addr, char* _s2)
{
Module: sip-router
Branch: andrei/tcp_tls_changes
Commit: 9da6fae72b9883ab8dbbb4e681c4d4e96d6549e4
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=9da6fae…
Author: Andrei Pelinescu-Onciul <andrei(a)iptel.org>
Committer: Andrei Pelinescu-Onciul <andrei(a)iptel.org>
Date: Wed Jun 16 21:03:06 2010 +0200
tcp: fix fd passing bug
If connections are opened and closed very quickly when data is
sent on them, it is possible that a connection gets closed
(close() inside tcp_main) while a process waits for its fd, just
before tcp_main attempts to send the fd. In this case the fd
sending will fail (one cannot send a closed fd) and the process
that asked for it will remain waiting forever.
The fix always checks before attempting to send the fd if the fd is
still open and the connection is not in a "bad" state. If not,
a new error response is sent (no fd and connection == NULL).
---
tcp_main.c | 48 +++++++++++++++++++++++++++++++++++++++++-------
1 files changed, 41 insertions(+), 7 deletions(-)
diff --git a/tcp_main.c b/tcp_main.c
index 98827f9..dcdb6fc 100644
--- a/tcp_main.c
+++ b/tcp_main.c
@@ -2102,16 +2102,22 @@ static int tcpconn_send_put(struct tcp_connection* c, char* buf, unsigned len,
do_close_fd=0;
goto release_c;
}
- if (unlikely(c!=tmp)){
- LOG(L_CRIT, "BUG: tcp_send: get_fd: got different connection:"
+ /* handle fd closed or bad connection/error
+ (it's possible that this happened in the time between
+ we found the intial connection and the time when we get
+ the fd)
+ */
+ if (unlikely(c!=tmp || fd==-1 || c->state==S_CONN_BAD)){
+ if (unlikely(c!=tmp && tmp!=0))
+ BUG("tcp_send: get_fd: got different connection:"
" %p (id= %d, refcnt=%d state=%d) != "
" %p (n=%d)\n",
c, c->id, atomic_get(&c->refcnt), c->state,
tmp, n
- );
+ );
n=-1; /* fail */
/* don't cache fd & close it */
- do_close_fd = 1;
+ do_close_fd = (fd==-1)?0:1;
#ifdef TCP_FD_CACHE
use_fd_cache = 0;
#endif /* TCP_FD_CACHE */
@@ -2943,6 +2949,12 @@ inline static void send_fd_queue_run(struct tcp_send_fd_q* q)
struct send_fd_info* t;
for (p=t=&q->data[0]; p<q->crt; p++){
+ if (unlikely(p->tcp_conn->state == S_CONN_BAD ||
+ p->tcp_conn->flags & F_CONN_FD_CLOSED ||
+ p->tcp_conn->s ==-1)) {
+ /* bad and/or already closed connection => remove */
+ goto rm_con;
+ }
if (unlikely(send_fd(p->unix_sock, &(p->tcp_conn),
sizeof(struct tcp_connection*), p->tcp_conn->s)<=0)){
if ( ((errno==EAGAIN)||(errno==EWOULDBLOCK)) &&
@@ -2958,7 +2970,11 @@ inline static void send_fd_queue_run(struct tcp_send_fd_q* q)
p->unix_sock, (long)(p-&q->data[0]), p->retries,
p->tcp_conn, p->tcp_conn->s, errno,
strerror(errno));
+rm_con:
#ifdef TCP_ASYNC
+ /* if a connection is on the send_fd queue it means it's
+ not watched for read anymore => could be watched only for
+ write */
if (p->tcp_conn->flags & F_CONN_WRITE_W){
io_watch_del(&io_h, p->tcp_conn->s, -1, IO_FD_CLOSING);
p->tcp_conn->flags &=~F_CONN_WRITE_W;
@@ -3222,6 +3238,7 @@ error:
inline static int handle_ser_child(struct process_table* p, int fd_i)
{
struct tcp_connection* tcpconn;
+ struct tcp_connection* tmp;
long response[2];
int cmd;
int bytes;
@@ -3317,9 +3334,26 @@ inline static int handle_ser_child(struct process_table* p, int fd_i)
/* send the requested FD */
/* WARNING: take care of setting refcnt properly to
* avoid race conditions */
- if (unlikely(send_fd(p->unix_sock, &tcpconn, sizeof(tcpconn),
- tcpconn->s)<=0)){
- LOG(L_ERR, "ERROR: handle_ser_child: send_fd failed\n");
+ if (unlikely(tcpconn->state == S_CONN_BAD ||
+ (tcpconn->flags & F_CONN_FD_CLOSED) ||
+ tcpconn->s ==-1)) {
+ /* connection is already marked as bad and/or has no
+ fd => don't try to send the fd (trying to send a
+ closed fd _will_ fail) */
+ tmp = 0;
+ if (unlikely(send_all(p->unix_sock, &tmp, sizeof(tmp)) <= 0))
+ BUG("handle_ser_child: CONN_GET_FD: send_all failed\n");
+ /* no need to attempt to destroy the connection, it should
+ be already in the process of being destroyed */
+ } else if (unlikely(send_fd(p->unix_sock, &tcpconn,
+ sizeof(tcpconn), tcpconn->s)<=0)){
+ LOG(L_ERR, "handle_ser_child: CONN_GET_FD:"
+ " send_fd failed\n");
+ /* try sending error (better then not sending anything) */
+ tmp = 0;
+ if (unlikely(send_all(p->unix_sock, &tmp, sizeof(tmp)) <= 0))
+ BUG("handle_ser_child: CONN_GET_FD:"
+ " send_fd send_all fallback failed\n");
}
break;
case CONN_NEW:
Module: sip-router
Branch: andrei/tcp_tls_changes
Commit: dabd96ab1a8aaa6c90bfddcd8ae4dec79964ea2f
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=dabd96a…
Author: Andrei Pelinescu-Onciul <andrei(a)iptel.org>
Committer: Andrei Pelinescu-Onciul <andrei(a)iptel.org>
Date: Wed Jun 16 18:26:51 2010 +0200
tls: config option for sending close notify alerts
Added a new config option for enabling or disabling the sending of
close notify alerts prior to closing the corresponding tcp
connection. Sending the close notify prior to tcp shutdown is
nicer from a TLS point of view, but it has a measurable
performance impact and it's not a must (3-4% when using 50% cpu,
with a debug build and 300cps => 6-8% from the cpu is spent on
close notify alerts).
By default it's off (change from older versions where it was
hardwired-on).
It can be changed via modparam (
e.g. modparam("tls", "send_close_notify", 1) )
or at runtime
(e.g. sercmd cfg.set_now_int tls send_close_notify 1 ).
---
modules/tls/tls_cfg.c | 7 ++++++-
modules/tls/tls_cfg.h | 2 ++
modules/tls/tls_mod.c | 1 +
modules/tls/tls_server.c | 2 +-
4 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/modules/tls/tls_cfg.c b/modules/tls/tls_cfg.c
index b255626..8f1cff9 100644
--- a/modules/tls/tls_cfg.c
+++ b/modules/tls/tls_cfg.c
@@ -61,7 +61,8 @@ struct cfg_group_tls default_tls_cfg = {
-1, /* low_mem_threshold2 */
10*1024*1024, /* ct_wq_max: 10 Mb by default */
64*1024, /* con_ct_wq_max: 64Kb by default */
- 4096 /* ct_wq_blk_size */
+ 4096, /* ct_wq_blk_size */
+ 0 /* send_close_notify (off by default)*/
};
void* tls_cfg = &default_tls_cfg;
@@ -191,6 +192,10 @@ cfg_def_t tls_cfg_def[] = {
{"ct_wq_blk_size", CFG_VAR_INT | CFG_ATOMIC, 1, 65536, 0, 0,
"internal TLS pre-write (clear-text) queue minimum block size"
" (advanced tunning or debugging for now)"},
+ {"send_close_notify", CFG_VAR_INT | CFG_ATOMIC, 0, 1, 0, 0,
+ "enable/disable sending a close notify TLS shutdown alert"
+ " before closing the corresponding TCP connection."
+ "Note that having it enabled has a performance impact."},
{0, 0, 0, 0, 0, 0}
};
diff --git a/modules/tls/tls_cfg.h b/modules/tls/tls_cfg.h
index 41e149c..eea7292 100644
--- a/modules/tls/tls_cfg.h
+++ b/modules/tls/tls_cfg.h
@@ -90,6 +90,8 @@ struct cfg_group_tls {
int ct_wq_max; /* maximum overall tls write clear text queued bytes */
int con_ct_wq_max; /* maximum clear text write queued bytes per con */
int ct_wq_blk_size; /* minimum block size for the clear text write queue */
+ int send_close_notify; /* if set try to be nice and send a shutdown alert
+ before closing the tcp connection */
};
diff --git a/modules/tls/tls_mod.c b/modules/tls/tls_mod.c
index de12b5b..49c4ec3 100644
--- a/modules/tls/tls_mod.c
+++ b/modules/tls/tls_mod.c
@@ -205,6 +205,7 @@ static param_export_t params[] = {
{"ssl_max_send_fragment", PARAM_INT,
&default_tls_cfg.ssl_max_send_fragment},
{"ssl_read_ahead", PARAM_INT, &default_tls_cfg.ssl_read_ahead},
+ {"send_close_notify", PARAM_INT, &default_tls_cfg.send_close_notify},
{"tls_force_run", PARAM_INT, &default_tls_cfg.force_run},
{"low_mem_threshold1", PARAM_INT, &default_tls_cfg.low_mem_threshold1},
{"low_mem_threshold2", PARAM_INT, &default_tls_cfg.low_mem_threshold2},
diff --git a/modules/tls/tls_server.c b/modules/tls/tls_server.c
index c99e6b3..be661de 100644
--- a/modules/tls/tls_server.c
+++ b/modules/tls/tls_server.c
@@ -502,7 +502,7 @@ void tls_h_close(struct tcp_connection *c, int fd)
* still be in a writer, so in this case locking is needed.
*/
DBG("Closing SSL connection %p\n", c->extra_data);
- if (likely(c->extra_data)) {
+ if (unlikely(cfg_get(tls, tls_cfg, send_close_notify) && c->extra_data)) {
lock_get(&c->write_lock);
if (unlikely(c->extra_data == 0)) {
/* changed in the meanwhile */
Module: sip-router
Branch: master
Commit: e68d92a1b05d3df9c1c3a6ac8c1447a4ea2f7932
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=e68d92a…
Author: Miklos Tirpak <miklos(a)iptel.org>
Committer: Miklos Tirpak <miklos(a)iptel.org>
Date: Wed Jun 16 16:09:31 2010 +0200
dns_cache: remove unused err_flags variable
err_flags is deleted from the dns_rr structure.
This flag was checked sometimes, but its value was never
set. Anyway, this flag contained duplicated information
because the parent structure, dns_hash_entry, has a similar
flag (ent_flags & DNS_FLAG_BAD_NAME). And a single hash
entry cannot contain both positive and negative resource
records at the same time.
---
dns_cache.c | 13 +++----------
dns_cache.h | 2 --
2 files changed, 3 insertions(+), 12 deletions(-)
diff --git a/dns_cache.c b/dns_cache.c
index 32b4e21..c7e4b32 100644
--- a/dns_cache.c
+++ b/dns_cache.c
@@ -2081,7 +2081,7 @@ error:
-/* gets the first non-expired, good record starting with record no
+/* gets the first non-expired record starting with record no
* from the dns_hash_entry struct e
* params: e - dns_hash_entry struct
* *no - it must contain the start record number (0 initially);
@@ -2126,9 +2126,6 @@ inline static struct dns_rr* dns_entry_get_rr( struct dns_hash_entry* e,
((s_ticks_t)(now-rr->expire)>=0) /* expired rr */
)
continue;
- if (rr->err_flags){ /* bad rr */
- continue;
- }
/* everything is ok now */
*no=n;
return rr;
@@ -2227,7 +2224,6 @@ retry:
#endif
((e->ent_flags & DNS_FLAG_PERMANENT) == 0) &&
((s_ticks_t)(now-rr->expire)>=0) /* expired entry */) ||
- (rr->err_flags) /* bad rr */ ||
(srv_marked(tried, idx)) ) /* already tried */{
r_sums[idx].r_sum=0; /* 0 sum, to skip over it */
r_sums[idx].rr=0; /* debug: mark it as unused */
@@ -3689,10 +3685,9 @@ void dns_cache_debug_all(rpc_t* rpc, void* ctx)
default:
rpc->add(ctx, "ss", "unknown", "?");
}
- rpc->add(ctx, "dd",
+ rpc->add(ctx, "d",
(int)(s_ticks_t)(rr->expire-now)<0?-1:
- TICKS_TO_S(rr->expire-now),
- (int)rr->err_flags);
+ TICKS_TO_S(rr->expire-now));
}
}
}
@@ -3876,8 +3871,6 @@ void dns_cache_print_entry(rpc_t* rpc, void* ctx, struct dns_hash_entry* e)
rpc->printf(ctx, "%srr expires in (s): %d", SPACE_FORMAT,
(s_ticks_t)(rr->expire-now)<0?-1 :
TICKS_TO_S(rr->expire-now));
- rpc->printf(ctx, "%srr error flags: %d", SPACE_FORMAT,
- rr->err_flags);
}
}
diff --git a/dns_cache.h b/dns_cache.h
index e45d76c..06e00a7 100644
--- a/dns_cache.h
+++ b/dns_cache.h
@@ -135,8 +135,6 @@ struct dns_rr{
struct dns_rr* next;
void* rdata; /**< depends on the type */
ticks_t expire; /**< = ttl + crt_time */
- unsigned char err_flags; /**< if 0 everything is ok */
-
};
Module: sip-router
Branch: master
Commit: 6a0b45abdbc1a7fa2a6cc0ce3f5d9646b7b188fd
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=6a0b45a…
Author: Miklos Tirpak <miklos(a)iptel.org>
Committer: Miklos Tirpak <miklos(a)iptel.org>
Date: Wed Jun 16 16:04:16 2010 +0200
dns_cache: minor fix, goto instead of break
Exit from the main look when no number of entries
has already been processed in dns_cache_clean()
---
dns_cache.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/dns_cache.c b/dns_cache.c
index 1f3206c..32b4e21 100644
--- a/dns_cache.c
+++ b/dns_cache.c
@@ -680,7 +680,7 @@ inline static int dns_cache_clean(unsigned int no, int expired_only)
deleted++;
}
n++;
- if (n>=no) break;
+ if (n>=no) goto skip;
}
}
/* not fair, but faster then random() */
Module: sip-router
Branch: master
Commit: fa09f630c284cb13ad9e3ad34d433bdbdda6750b
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=fa09f63…
Author: Miklos Tirpak <miklos(a)iptel.org>
Committer: Miklos Tirpak <miklos(a)iptel.org>
Date: Tue Jun 15 10:15:46 2010 +0200
dns_cache: dns_cache_delete_single_record() added
The function deletes a single resource record
of an existing DNS entry. If the entry has only one
record then the entire entry is deleted.
The resource record is identified by its name, type,
and value, i.e. ip addres in case of A/AAAA record,
target name in case of SRV record.
Only A, AAAA, and SRV records are supported.
---
dns_cache.c | 151 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
dns_cache.h | 13 +++++-
2 files changed, 163 insertions(+), 1 deletions(-)
diff --git a/dns_cache.c b/dns_cache.c
index 7605ee6..675df80 100644
--- a/dns_cache.c
+++ b/dns_cache.c
@@ -4313,6 +4313,157 @@ static void dns_cache_delete_record(rpc_t* rpc, void* ctx, unsigned short type)
rpc->fault(ctx, 400, "Not found");
}
+/* Delete a single record from the cache,
+ * i.e. the record with the same name and value
+ * (ip address in case of A/AAAA record, name in case of SRV record).
+ *
+ * Currently only A, AAAA, and SRV records are supported.
+ */
+int dns_cache_delete_single_record(unsigned short type,
+ str *name,
+ str *value,
+ int flags)
+{
+ struct dns_hash_entry *old=NULL, *new=NULL;
+ struct dns_rr *rr, **next_p;
+ str rr_name;
+ struct ip_addr *ip_addr;
+ int err, h;
+
+ /* eliminate gcc warnings */
+ rr_name.s = NULL;
+ rr_name.len = 0;
+ ip_addr = 0;
+
+ if (!cfg_get(core, core_cfg, use_dns_cache)){
+ LOG(L_ERR, "ERROR: dns cache support disabled (see use_dns_cache)\n");
+ return -1;
+ }
+
+ if ((type != T_A) && (type != T_AAAA) && (type != T_SRV)) {
+ LOG(L_ERR, "ERROR: rr type %d is not implemented\n",
+ type);
+ return -1;
+ }
+
+ if (!flags) {
+ /* fix-up the values */
+ switch(type) {
+ case T_A:
+ ip_addr = str2ip(value);
+ if (!ip_addr) {
+ LOG(L_ERR, "ERROR: Malformed ip address: %.*s\n",
+ value->len, value->s);
+ return -1;
+ }
+ break;
+ case T_AAAA:
+#ifdef USE_IPV6
+ ip_addr = str2ip6(value);
+ if (!ip_addr) {
+ LOG(L_ERR, "ERROR: Malformed ip address: %.*s\n",
+ value->len, value->s);
+ return -1;
+ }
+ break;
+#else /* USE_IPV6 */
+ LOG(L_ERR, "ERROR: IPv6 support is disabled\n");
+ return -1;
+#endif /* USE_IPV6 */
+ case T_SRV:
+ rr_name = *value;
+ break;
+ }
+ }
+
+ /* check whether there is a matching entry in the cache */
+ if ((old = dns_hash_get(name, type, &h, &err)) == NULL)
+ goto not_found;
+
+ if ((old->type != type) /* may be CNAME */
+ || (old->err_flags != flags)
+ )
+ goto not_found;
+
+ if (flags) /* negative record, there is no value */
+ goto delete;
+
+ /* check whether there is an rr with the same value */
+ for (rr=old->rr_lst, next_p=&old->rr_lst;
+ rr;
+ next_p=&rr->next, rr=rr->next
+ )
+ if ((((type == T_A) || (type == T_AAAA)) &&
+ (memcmp(ip_addr->u.addr, ((struct a_rdata*)rr->rdata)->ip,
+ ip_addr->len)==0))
+ || ((type == T_SRV) &&
+ (((struct srv_rdata*)rr->rdata)->name_len == rr_name.len) &&
+ (memcmp(rr_name.s, ((struct srv_rdata*)rr->rdata)->name,
+ rr_name.len)==0)))
+ break;
+
+ if (!rr)
+ goto not_found;
+
+ if ((rr == old->rr_lst) && (rr->next == NULL)) {
+ /* There is a single rr value, hence the whole
+ * hash entry can be deleted */
+ goto delete;
+ } else {
+ /* we must modify the entry, so better to clone it, modify the new
+ * one, and replace the old with the new entry in the hash table,
+ * because the entry might be in use (even if the dns hash is
+ * locked). The old entry will be removed from the hash and
+ * automatically destroyed when its refcnt will be 0*/
+ new = dns_cache_clone_entry(old, 0, 0, 0);
+ if (!new) {
+ LOG(L_ERR, "ERROR: Failed to clone an existing "
+ "DNS cache entry\n");
+ dns_hash_put(old);
+ return -1;
+ }
+ /* let rr and next_p point to the new structure */
+ rr = (struct dns_rr*)translate_pointer((char*)new,
+ (char*)old,
+ (char*)rr);
+ next_p = (struct dns_rr**)translate_pointer((char*)new,
+ (char*)old,
+ (char*)next_p);
+ /* unlink rr from the list. The memory will be freed
+ * when the whole record is freed */
+ *next_p = rr->next;
+ }
+
+delete:
+ LOCK_DNS_HASH();
+ if (new) {
+ /* delete the old entry only if the new one can be added */
+ if (dns_cache_add_unsafe(new)) {
+ LOG(L_ERR, "ERROR: Failed to add the entry to the cache\n");
+ UNLOCK_DNS_HASH();
+ if (old)
+ dns_hash_put(old);
+ return -1;
+ } else {
+ /* remove the old entry from the list */
+ if (old)
+ _dns_hash_remove(old);
+ }
+ } else if (old) {
+ _dns_hash_remove(old);
+ }
+ UNLOCK_DNS_HASH();
+
+ if (old)
+ dns_hash_put(old);
+ return 0;
+
+not_found:
+ LOG(L_ERR, "ERROR: No matching record found\n");
+ if (old)
+ dns_hash_put(old);
+ return -1;
+}
/* performs a dns lookup over rpc */
void dns_cache_rpc_lookup(rpc_t* rpc, void* ctx)
diff --git a/dns_cache.h b/dns_cache.h
index a8a4bd4..ffacd02 100644
--- a/dns_cache.h
+++ b/dns_cache.h
@@ -350,7 +350,7 @@ void dns_set_server_state(int state);
int dns_get_server_state(void);
#endif /* DNS_WATCHDOG_SUPPORT */
-/* Adds a new record to the cache.
+/** @brief Adds a new record to the cache.
* If there is an existing record with the same name and value
* (ip address in case of A/AAAA record, name in case of SRV record)
* only the remaining fields are updated.
@@ -366,5 +366,16 @@ int dns_cache_add_record(unsigned short type,
int port,
int flags);
+/** @brief Delete a single record from the cache,
+ * i.e. the record with the same name and value
+ * (ip address in case of A/AAAA record, name in case of SRV record).
+ *
+ * Currently only A, AAAA, and SRV records are supported.
+ */
+int dns_cache_delete_single_record(unsigned short type,
+ str *name,
+ str *value,
+ int flags);
+
#endif
Module: sip-router
Branch: master
Commit: ec79c28a238fa8e66823161daa7994a679ef56f2
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=ec79c28…
Author: Miklos Tirpak <miklos(a)iptel.org>
Committer: Miklos Tirpak <miklos(a)iptel.org>
Date: Wed Jun 16 15:49:24 2010 +0200
dns_cache: added support for permanent entries
Permanent entries are intended to be used for management
purposes, i.e. they are useful if there is no DNS server
available for instance. Such entries never expire, and overwrite
any existing entry that was added by the resolver.
They can be added to the cache from modules or over the RPC calls
dns.add_a, dns.add_aaaa and dns.add_srv with the flag value of 2.
(or 3 in case of negative permanent entry)
- err_flags in struct dns_hash_entry is changed to be a general
purpose flag, and renamed to ent_flag.
- DNS_BAD_NAME is renamed to DNS_FLAG_BAD_NAME
- DNS_FLAG_PERMANENT value is added.
- new rpc call to force deleting the permanent entries from the
cache: dns.delete_all_force. (dns.delete_all deletes only
the non-permanent entries.)
---
core_cmd.c | 10 ++++-
dns_cache.c | 143 +++++++++++++++++++++++++++++++++++++++++++----------------
dns_cache.h | 23 +++++++--
3 files changed, 131 insertions(+), 45 deletions(-)
Diff: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commitdiff;h=ec7…
Module: sip-router
Branch: andrei/raw_sock
Commit: 22e7e32e343724a42abc4c0c1b7986e88e50111b
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=22e7e32…
Author: Andrei Pelinescu-Onciul <andrei(a)iptel.org>
Committer: Andrei Pelinescu-Onciul <andrei(a)iptel.org>
Date: Tue Jun 15 16:36:14 2010 +0200
raw sockets: udp send will use now raw sockets if enabled
A raw socket, that will be used for sending, is now initialized on
startup. The operation can succeed only if sr is started as root
or with CAP_NET_RAW.
If the initialization fails and the raw sockets are forced on from
the config (udp4_raw = 1), ser won't start. If the raw socket are
in auto mode (udp4_raw = -1), sr will start, but with the raw
socket send part disabled (normal udp send will be used).
If the raw socket part is not disabled at startup, it can be
turned anytime on/off via the runtime cfg. framework.
Note: the raw socket send is supported only over ipv4 and for now
only on linux.
---
main.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++-------
udp_server.c | 69 ++++++++++++++++++++++++++++++++++++--------------
2 files changed, 119 insertions(+), 29 deletions(-)
diff --git a/main.c b/main.c
index 7d28bcd..a90e855 100644
--- a/main.c
+++ b/main.c
@@ -73,16 +73,15 @@
* 2008-08-08 sctp support (andrei)
* 2008-08-19 -l support for mmultihomed addresses/addresses lists
* (e.g. -l (eth0, 1.2.3.4, foo.bar) ) (andrei)
- * 2010-04-19 added daemon_status_fd pipe to communicate the parent process with
- the main process in daemonize mode, so the parent process can return
- the proper exit status code (ibc)
+ * 2010-04-19 added daemon_status_fd pipe to communicate the parent process
+ * with the main process in daemonize mode, so the parent process
+ * can return the proper exit status code (ibc)
*/
-/*!
- * \file
- * \brief SIP-router core ::
- * \ingroup core
- * Module: \ref core
+/** intializations and startup.
+ * @file main.c
+ * @ingroup core
+ * Module: @ref core
*/
/*! \defgroup core SIP-router core
@@ -148,6 +147,9 @@
#include "nonsip_hooks.h"
#include "ut.h"
#include "signals.h"
+#ifdef USE_RAW_SOCKS
+#include "raw_sock.h"
+#endif /* USE_RAW_SOCKS */
#ifdef USE_TCP
#include "poll_types.h"
#include "tcp_init.h"
@@ -439,6 +441,9 @@ struct socket_info* bind_address=0; /* pointer to the crt. proc.
listening address*/
struct socket_info* sendipv4; /* ipv4 socket to use when msg. comes from ipv6*/
struct socket_info* sendipv6; /* same as above for ipv6 */
+#ifdef USE_RAW_SOCKS
+int raw_udp4_send_sock = -1; /* raw socket used for sending udp4 packets */
+#endif /* USE_RAW_SOCKS */
#ifdef USE_TCP
struct socket_info* sendipv4_tcp;
struct socket_info* sendipv6_tcp;
@@ -1237,9 +1242,35 @@ int main_loop()
/* only one address, we ignore all the others */
if (udp_init(udp_listen)==-1) goto error;
bind_address=udp_listen;
- if (bind_address->address.af==AF_INET)
+ if (bind_address->address.af==AF_INET) {
sendipv4=bind_address;
- else
+#ifdef USE_RAW_SOCKS
+ /* always try to have a raw socket opened if we are using ipv4 */
+ raw_udp4_send_sock = raw_socket(IPPROTO_RAW, 0, 0, 1);
+ if (raw_udp4_send_sock < 0) {
+ if ( default_core_cfg.udp4_raw > 0) {
+ /* force use raw socket failed */
+ ERR("could not initialize raw udp send socket (ipv4):"
+ " %s (%d)\n", strerror(errno), errno);
+ if (errno == EPERM)
+ ERR("could not initialize raw socket on startup"
+ " due to inadequate permissions, please"
+ " restart as root or with CAP_NET_RAW\n");
+ goto error;
+ }
+ default_core_cfg.udp4_raw = 0; /* disabled */
+ } else {
+ register_fds(1);
+ if (default_core_cfg.udp4_raw < 0) {
+ /* auto-detect => use it */
+ default_core_cfg.udp4_raw = 1; /* enabled */
+ DBG("raw socket possible => turning it on\n");
+ }
+ }
+#else
+ default_core.cfg.udp4_raw = 0;
+#endif /* USE_RAW_SOCKS */
+ } else
sendipv6=bind_address;
if (udp_listen->next){
LOG(L_WARN, "WARNING: using only the first listen address"
@@ -1363,6 +1394,34 @@ int main_loop()
/* children_no per each socket */
cfg_register_child(children_no);
}
+#ifdef USE_RAW_SOCKS
+ /* always try to have a raw socket opened if we are using ipv4 */
+ if (sendipv4) {
+ raw_udp4_send_sock = raw_socket(IPPROTO_RAW, 0, 0, 1);
+ if (raw_udp4_send_sock < 0) {
+ if ( default_core_cfg.udp4_raw > 0) {
+ /* force use raw socket failed */
+ ERR("could not initialize raw udp send socket (ipv4):"
+ " %s (%d)\n", strerror(errno), errno);
+ if (errno == EPERM)
+ ERR("could not initialize raw socket on startup"
+ " due to inadequate permissions, please"
+ " restart as root or with CAP_NET_RAW\n");
+ goto error;
+ }
+ default_core_cfg.udp4_raw = 0; /* disabled */
+ } else {
+ register_fds(1);
+ if (default_core_cfg.udp4_raw < 0) {
+ /* auto-detect => use it */
+ default_core_cfg.udp4_raw = 1; /* enabled */
+ DBG("raw socket possible => turning it on\n");
+ }
+ }
+ }
+#else
+ default_core_cfg.udp4_raw = 0;
+#endif /* USE_RAW_SOCKS */
#ifdef USE_SCTP
if (!sctp_disable){
for(si=sctp_listen; si; si=si->next){
diff --git a/udp_server.c b/udp_server.c
index a54a4fe..d4a9d7b 100644
--- a/udp_server.c
+++ b/udp_server.c
@@ -41,14 +41,14 @@
* 2007-08-28 disable/set MTU discover option for the udp sockets
* (in linux it's enabled by default which produces udp packets
* with the DF flag ser) (patch from hscholz)
+ * 2010-06-15 support for using raw sockets for sending (andrei)
*/
-/*!
- * \file
- * \brief SIP-router core ::
- * \ingroup core
- * Module: \ref core
+/** udp send and loop-receive functions.
+ * @file udp_server.c
+ * @ingroup core
+ * Module: @ref core
*/
#include <stdlib.h>
@@ -67,6 +67,7 @@
#include "udp_server.h"
+#include "compiler_opt.h"
#include "globals.h"
#include "config.h"
#include "dprint.h"
@@ -74,6 +75,10 @@
#include "mem/mem.h"
#include "ip_addr.h"
#include "cfg/cfg_struct.h"
+#ifdef USE_RAW_SOCKS
+#include "raw_sock.h"
+#endif /* USE_RAW_SOCKS */
+
#ifdef USE_STUN
#include "ser_stun.h"
@@ -551,6 +556,9 @@ int udp_send(struct dest_info* dst, char *buf, unsigned len)
int n;
int tolen;
struct ip_addr ip; /* used only on error, for debugging */
+#ifdef USE_RAW_SOCKS
+ int mtu;
+#endif /* USE_RAW_SOCKS */
#ifdef DBG_MSG_QA
/* aborts on error, does nothing otherwise */
@@ -559,24 +567,47 @@ int udp_send(struct dest_info* dst, char *buf, unsigned len)
abort();
}
#endif
-
- tolen=sockaddru_len(dst->to);
+#ifdef USE_RAW_SOCKS
+ if (likely( ! (raw_udp4_send_sock >= 0 &&
+ cfg_get(core, core_cfg, udp4_raw) &&
+ dst->send_sock->address.af == AF_INET) )) {
+#endif /* USE_RAW_SOCKS */
+ /* normal send over udp socket */
+ tolen=sockaddru_len(dst->to);
again:
- n=sendto(dst->send_sock->socket, buf, len, 0, &dst->to.s, tolen);
+ n=sendto(dst->send_sock->socket, buf, len, 0, &dst->to.s, tolen);
#ifdef XL_DEBUG
- LOG(L_INFO, "INFO: send status: %d\n", n);
+ LOG(L_INFO, "INFO: send status: %d\n", n);
#endif
- if (n==-1){
- su2ip_addr(&ip, &dst->to);
- LOG(L_ERR, "ERROR: udp_send: sendto(sock,%p,%u,0,%s:%d,%d): %s(%d)\n",
- buf,len, ip_addr2a(&ip), su_getport(&dst->to), tolen,
- strerror(errno),errno);
- if (errno==EINTR) goto again;
- if (errno==EINVAL) {
- LOG(L_CRIT,"CRITICAL: invalid sendtoparameters\n"
- "one possible reason is the server is bound to localhost and\n"
- "attempts to send to the net\n");
+ if (unlikely(n==-1)){
+ su2ip_addr(&ip, &dst->to);
+ LOG(L_ERR, "ERROR: udp_send: sendto(sock,%p,%u,0,%s:%d,%d):"
+ " %s(%d)\n", buf,len, ip_addr2a(&ip),
+ su_getport(&dst->to), tolen, strerror(errno), errno);
+ if (errno==EINTR) goto again;
+ if (errno==EINVAL) {
+ LOG(L_CRIT,"CRITICAL: invalid sendtoparameters\n"
+ "one possible reason is the server is bound to localhost and\n"
+ "attempts to send to the net\n");
+ }
+ }
+#ifdef USE_RAW_SOCKS
+ } else {
+ /* send over a raw socket */
+ mtu = cfg_get(core, core_cfg, udp4_raw_mtu);
+raw_again:
+ n=raw_iphdr_udp4_send(raw_udp4_send_sock, buf, len,
+ &dst->send_sock->su,
+ &dst->to,
+ mtu);
+ if (unlikely(n==-1)){
+ su2ip_addr(&ip, &dst->to);
+ LOG(L_ERR, "ERROR: raw_udp4_send(sock,%p,%u,...,%s:%d,%d):"
+ " %s(%d)\n", buf,len, ip_addr2a(&ip),
+ su_getport(&dst->to), mtu, strerror(errno), errno);
+ if (errno==EINTR) goto raw_again;
}
}
+#endif /* USE_RAW_SOCKS */
return n;
}