summaryrefslogtreecommitdiffstats
path: root/src/e1_input.c
diff options
context:
space:
mode:
authorPablo Neira Ayuso2011-07-07 17:47:26 +0200
committerPablo Neira Ayuso2011-07-07 19:33:24 +0200
commit3832c4f908e6d9d821b18bbccab017b2d3d6c79c (patch)
tree0fb3bc3956cde0c85db98671146cb503c86a138b /src/e1_input.c
parentipaccess: close connection if we receive bad messages from BTS (diff)
downloadlibosmo-abis-3832c4f908e6d9d821b18bbccab017b2d3d6c79c.tar.gz
libosmo-abis-3832c4f908e6d9d821b18bbccab017b2d3d6c79c.tar.xz
libosmo-abis-3832c4f908e6d9d821b18bbccab017b2d3d6c79c.zip
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.
Diffstat (limited to 'src/e1_input.c')
-rw-r--r--src/e1_input.c42
1 files changed, 36 insertions, 6 deletions
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) {