From 3832c4f908e6d9d821b18bbccab017b2d3d6c79c Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 7 Jul 2011 17:47:26 +0200 Subject: e1_input: add new refcounting scheme to avoid leaking E1 lines This patch 's/e1inp_line_get/e1inp_line_find/g' since we need this function name for the new refcounting scheme. Basically, I have added a new function to clone lines that is used by the ipaccess driver: struct e1inp_line *e1inp_line_clone(void *ctx, struct e1inp_line *line); And two functions to bump and decrement the refcount: void e1inp_line_get(struct e1inp_line *line); void e1inp_line_put(struct e1inp_line *line); This is useful to avoid leaking virtual E1 lines in the ipaccess case, since we have two sockets for OML and RSL respectively, we have to release the line *once* both sockets have been closed. Without this patch, there are cases in which we don't know if it's time to release the virtual E1 line. This patch also includes a fix to avoid crashing if we open a connection with OML/RSL port without sending any ID_RESP message (in that case, we have no chance to set the signal link). I tested these situations with netcat. --- src/e1_input.c | 42 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 6 deletions(-) (limited to 'src/e1_input.c') diff --git a/src/e1_input.c b/src/e1_input.c index 419ec8c..6873f21 100644 --- a/src/e1_input.c +++ b/src/e1_input.c @@ -269,7 +269,7 @@ int e1inp_ts_config_sign(struct e1inp_ts *ts, struct e1inp_line *line) return 0; } -struct e1inp_line *e1inp_line_get(uint8_t e1_nr) +struct e1inp_line *e1inp_line_find(uint8_t e1_nr) { struct e1inp_line *e1i_line; @@ -288,7 +288,7 @@ e1inp_line_create(uint8_t e1_nr, const char *driver_name) struct e1inp_line *line; int i; - line = e1inp_line_get(e1_nr); + line = e1inp_line_find(e1_nr); if (line) { LOGP(DINP, LOGL_ERROR, "E1 Line %u already exists\n", e1_nr); @@ -313,11 +313,39 @@ e1inp_line_create(uint8_t e1_nr, const char *driver_name) line->ts[i].num = i+1; line->ts[i].line = line; } + line->refcnt++; llist_add_tail(&line->list, &e1inp_line_list); return line; } +struct e1inp_line * +e1inp_line_clone(void *ctx, struct e1inp_line *line) +{ + struct e1inp_line *clone; + + /* clone virtual E1 line for this new OML link. */ + clone = talloc_zero(ctx, struct e1inp_line); + if (clone == NULL) + return NULL; + + memcpy(clone, line, sizeof(struct e1inp_line)); + clone->refcnt = 1; + return clone; +} + +void e1inp_line_get(struct e1inp_line *line) +{ + line->refcnt++; +} + +void e1inp_line_put(struct e1inp_line *line) +{ + line->refcnt--; + if (line->refcnt == 0) + talloc_free(line); +} + void e1inp_line_bind_ops(struct e1inp_line *line, const struct e1inp_line_ops *ops) { @@ -325,12 +353,12 @@ e1inp_line_bind_ops(struct e1inp_line *line, const struct e1inp_line_ops *ops) } #if 0 -struct e1inp_line *e1inp_line_get_create(uint8_t e1_nr) +struct e1inp_line *e1inp_line_find_create(uint8_t e1_nr) { struct e1inp_line *line; int i; - line = e1inp_line_get(e1_nr); + line = e1inp_line_find(e1_nr); if (line) return line; @@ -353,7 +381,7 @@ static struct e1inp_ts *e1inp_ts_get(uint8_t e1_nr, uint8_t ts_nr) { struct e1inp_line *e1i_line; - e1i_line = e1inp_line_get(e1_nr); + e1i_line = e1inp_line_find(e1_nr); if (!e1i_line) return NULL; @@ -549,8 +577,10 @@ int e1inp_line_update(struct e1inp_line *line) struct input_signal_data isd; int rc; + e1inp_line_get(line); + /* This line has been already initialized, skip this. */ - if (++line->refcnt > 1) + if (line->refcnt > 2) return 0; if (line->driver && line->ops && line->driver->line_update) { -- cgit v1.2.3-55-g7522