MT#9561 upstream fixes from 4.1 branch

Change-Id: I2d21fbd2d1ab0f272439cd227e472da0baa98af7
vseva/6243_fix_clean
Victor Seva 11 years ago
parent cf7aa848cf
commit 3421de34c4

@ -12,6 +12,17 @@ upstream/0005-textops-Refresh-README.patch
#
upstream/core-new-internal-msg-flag-added-FL_RR_ADDED.patch
upstream/rr-use-internal-msg-flags-to-mark-a-request-with-rec.patch
# 4.1 upstream fixes
upstream/0001-exec-safety-check-against-bash-vulnerability-CVE-201.patch
upstream/0002-exec-add-parameter-to-control-the-option-for-bash-ex.patch
upstream/0003-dialog-check-if-the-transaction-is-created-for-BYE-c.patch
upstream/0004-dialog-set-again-the-dialog-ids-in-context-for-BYE-p.patch
upstream/0005-dialog-fixed-typo-copy-paste-oversight-to-dlg-pointe.patch
upstream/0006-core-helper-functions-to-get-addr-and-port-to-be-use.patch
upstream/0007-tm-use-advertised-addr-port-if-set-for-socket-in-rm-.patch
upstream/0008-mohqueue-fixed-db_qtable-parameter-name.patch
upstream/0009-rr-Fix-memory-leak-when-using-outbound.patch
upstream/0010-core-xavp-Fix-xavp_insert-to-prevent-corrupted-linke.patch
#
no_lib64_on_64_bits.patch
no_INSTALL_file.patch

@ -0,0 +1,44 @@
From aebd010ee1ebff8a70877164fb7b508c1ca5503d Mon Sep 17 00:00:00 2001
From: Seudin Kasumovic <seudin.kasumovic@gmail.com>
Date: Thu, 25 Sep 2014 16:56:28 +0200
Subject: [PATCH] exec: safety check against bash vulnerability CVE-2014-6271
(cherry picked from commit d5d57c0df931c9d60432def919c837cc76e4ce42)
---
modules/exec/exec_hf.c | 18 ++++++++++++++----
1 file changed, 14 insertions(+), 4 deletions(-)
diff --git a/modules/exec/exec_hf.c b/modules/exec/exec_hf.c
index 3bc761b..d336070 100644
--- a/modules/exec/exec_hf.c
+++ b/modules/exec/exec_hf.c
@@ -256,12 +256,22 @@ static int print_hf_var(struct hf_wrapper *w, int offset)
memcpy(envvar, w->prefix, w->prefix_len); c=envvar+w->prefix_len;
memcpy(c, hname, hlen ); c+=hlen;
*c=EV_ASSIGN;c++;
- memcpy(c, w->u.hf->body.s+offset, w->u.hf->body.len );
- c+=w->u.hf->body.len;
+ if (!strncmp(w->u.hf->body.s,"() {",MIN(w->u.hf->body.len,4))) {
+ memcpy(c, w->u.hf->body.s+offset+2, w->u.hf->body.len-2 );
+ c+=(w->u.hf->body.len-2);
+ } else {
+ memcpy(c, w->u.hf->body.s+offset, w->u.hf->body.len );
+ c+=w->u.hf->body.len;
+ }
for (wi=w->next_same; wi; wi=wi->next_same) {
*c=HF_SEPARATOR;c++;
- memcpy(c, wi->u.hf->body.s+offset, wi->u.hf->body.len );
- c+=wi->u.hf->body.len;
+ if (!strncmp(w->u.hf->body.s,"() {",MIN(w->u.hf->body.len,4))) {
+ memcpy(c, w->u.hf->body.s+offset+2, w->u.hf->body.len-2 );
+ c+=(w->u.hf->body.len-2);
+ } else {
+ memcpy(c, w->u.hf->body.s+offset, w->u.hf->body.len );
+ c+=w->u.hf->body.len;
+ }
}
*c=0; /* zero termination */
LM_DBG("%s\n", envvar );
--
2.1.1

@ -0,0 +1,70 @@
From cc40de5865b1758681f97b7d92c1fed533ed7c7f Mon Sep 17 00:00:00 2001
From: Daniel-Constantin Mierla <miconda@gmail.com>
Date: Thu, 25 Sep 2014 16:59:34 +0200
Subject: [PATCH] exec: add parameter to control the option for bash exec
safety check of CVE-2014-6271
- parameter: bash_safety - default is 1 (enabled), set to 0 to disable
- just in case someone needs that kind of header and knows what
he/she does
(cherry picked from commit 21eb073c25b66b110193f1607b93f256f7d9fdfa)
---
modules/exec/exec_hf.c | 6 ++++--
modules/exec/exec_mod.c | 2 ++
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/modules/exec/exec_hf.c b/modules/exec/exec_hf.c
index d336070..4fc248d 100644
--- a/modules/exec/exec_hf.c
+++ b/modules/exec/exec_hf.c
@@ -52,6 +52,8 @@
#include "../../char_msg_val.h"
#include "exec_hf.h"
+extern int exec_bash_safety;
+
/* should be environment variables set by header fields ? */
unsigned int setvars=1;
@@ -256,7 +258,7 @@ static int print_hf_var(struct hf_wrapper *w, int offset)
memcpy(envvar, w->prefix, w->prefix_len); c=envvar+w->prefix_len;
memcpy(c, hname, hlen ); c+=hlen;
*c=EV_ASSIGN;c++;
- if (!strncmp(w->u.hf->body.s,"() {",MIN(w->u.hf->body.len,4))) {
+ if (exec_bash_safety && !strncmp(w->u.hf->body.s,"() {",MIN(w->u.hf->body.len,4))) {
memcpy(c, w->u.hf->body.s+offset+2, w->u.hf->body.len-2 );
c+=(w->u.hf->body.len-2);
} else {
@@ -265,7 +267,7 @@ static int print_hf_var(struct hf_wrapper *w, int offset)
}
for (wi=w->next_same; wi; wi=wi->next_same) {
*c=HF_SEPARATOR;c++;
- if (!strncmp(w->u.hf->body.s,"() {",MIN(w->u.hf->body.len,4))) {
+ if (exec_bash_safety && !strncmp(w->u.hf->body.s,"() {",MIN(w->u.hf->body.len,4))) {
memcpy(c, w->u.hf->body.s+offset+2, w->u.hf->body.len-2 );
c+=(w->u.hf->body.len-2);
} else {
diff --git a/modules/exec/exec_mod.c b/modules/exec/exec_mod.c
index 86947c0..547fffb 100644
--- a/modules/exec/exec_mod.c
+++ b/modules/exec/exec_mod.c
@@ -44,6 +44,7 @@
MODULE_VERSION
unsigned int time_to_kill=0;
+int exec_bash_safety=1;
static int mod_init( void );
@@ -77,6 +78,7 @@ static cmd_export_t cmds[] = {
static param_export_t params[] = {
{"time_to_kill", INT_PARAM, &time_to_kill},
{"setvars", INT_PARAM, &setvars },
+ {"bash_safety", INT_PARAM, &exec_bash_safety },
{0, 0, 0}
};
--
2.1.1

@ -0,0 +1,28 @@
From 6f9519b001a608af20787e0cfaf4a3a0d2dfc1fb Mon Sep 17 00:00:00 2001
From: Daniel-Constantin Mierla <miconda@gmail.com>
Date: Wed, 24 Sep 2014 23:46:00 +0200
Subject: [PATCH] dialog: set again the dialog ids in context for BYE
processing
- they can be reset by event route execution
(cherry picked from commit 5b733fa361afced0418947c965b256dbe7ae3a68)
---
modules/dialog/dlg_handlers.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/modules/dialog/dlg_handlers.c b/modules/dialog/dlg_handlers.c
index 45292b3..9ccdfe8 100644
--- a/modules/dialog/dlg_handlers.c
+++ b/modules/dialog/dlg_handlers.c
@@ -1280,6 +1280,7 @@ void dlg_onroute(struct sip_msg* req, str *route_params, void *param)
_dlg_ctx.cpid = my_pid();
_dlg_ctx.expect_t = 1;
+ dlg_set_ctx_iuid(dlg);
if_update_stat( dlg_enable_stats, active_dlgs, -1);
goto done;
--
2.1.1

@ -0,0 +1,36 @@
From a8427ce51f8b4a31fa122844db8ceec9c728a1ac Mon Sep 17 00:00:00 2001
From: Daniel-Constantin Mierla <miconda@gmail.com>
Date: Fri, 26 Sep 2014 09:16:39 +0200
Subject: [PATCH] dialog: fixed typo/copy&paste oversight to dlg pointer name
in clean routine
- credits to Alex Balshov for report, troubleshooting and spotting the
fix
(cherry picked from commit 8e6c83182677ec234c5f44c5dfcb40e421a21bcb)
---
modules/dialog/dlg_hash.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/modules/dialog/dlg_hash.c b/modules/dialog/dlg_hash.c
index 8b94b01..4284801 100644
--- a/modules/dialog/dlg_hash.c
+++ b/modules/dialog/dlg_hash.c
@@ -250,11 +250,11 @@ int dlg_clean_run(ticks_t ti)
destroy_dlg(tdlg);
}
if(tdlg->state==DLG_STATE_CONFIRMED_NA && tdlg->start_ts<tm-60) {
- if(update_dlg_timer(&dlg->tl, 10)<0) {
+ if(update_dlg_timer(&tdlg->tl, 10)<0) {
LM_ERR("failed to update dialog lifetime in long non-ack state\n");
}
- dlg->lifetime = 10;
- dlg->dflags |= DLG_FLAG_CHANGED;
+ tdlg->lifetime = 10;
+ tdlg->dflags |= DLG_FLAG_CHANGED;
}
}
lock_set_release(d_table->locks, d_table->entries[i].lock_idx);
--
2.1.1

@ -0,0 +1,55 @@
From a52c0024723a59d90c3c3966d5deadaf8b0d4440 Mon Sep 17 00:00:00 2001
From: Daniel-Constantin Mierla <miconda@gmail.com>
Date: Sun, 28 Sep 2014 12:48:53 +0200
Subject: [PATCH] core: helper functions to get addr and port to be used in
signaling from socket info (cherry picked from commit
c725f1dec14863e069bfd1e5c26857a1005528d5)
---
ip_addr.c | 21 +++++++++++++++++++++
ip_addr.h | 2 ++
2 files changed, 23 insertions(+)
diff --git a/ip_addr.c b/ip_addr.c
index 5f8881e..7175bd0 100644
--- a/ip_addr.c
+++ b/ip_addr.c
@@ -404,3 +404,24 @@ int ip_addr_match_net(ip_addr_t *iaddr, ip_addr_t *naddr,
return 0;
return -1;
}
+
+int si_get_signaling_data(struct socket_info *si, str **addr, str **port)
+{
+ if(si==NULL)
+ return -1;
+ if(addr) {
+ if(si->useinfo.name.len>0) {
+ *addr = &si->useinfo.name;
+ } else {
+ *addr = &si->address_str;
+ }
+ }
+ if(port) {
+ if(si->useinfo.port_no>0) {
+ *port = &si->useinfo.port_no_str;
+ } else {
+ *port = &si->port_no_str;
+ }
+ }
+ return 0;
+}
diff --git a/ip_addr.h b/ip_addr.h
index 20b3ec2..5806122 100644
--- a/ip_addr.h
+++ b/ip_addr.h
@@ -807,4 +807,6 @@ inline static void init_dst_from_rcv(struct dest_info* dst,
*/
int ip_addr_match_net(ip_addr_t *iaddr, ip_addr_t *naddr, int mask);
+int si_get_signaling_data(struct socket_info *si, str **addr, str **port);
+
#endif
--
2.1.1

@ -0,0 +1,45 @@
From 88031fe50236f9eb1fc28309fd466e86d8c6b81b Mon Sep 17 00:00:00 2001
From: Daniel-Constantin Mierla <miconda@gmail.com>
Date: Sun, 28 Sep 2014 12:49:27 +0200
Subject: [PATCH] tm: use advertised addr/port if set for socket in rm rpc uac
commands
- reported by Juha Heinanen
(cherry picked from commit 131139883c03f3851ad99e96c59dfe3c349ec011)
---
modules/tm/rpc_uac.c | 11 ++++-------
1 file changed, 4 insertions(+), 7 deletions(-)
diff --git a/modules/tm/rpc_uac.c b/modules/tm/rpc_uac.c
index a305b63..507f4ae 100644
--- a/modules/tm/rpc_uac.c
+++ b/modules/tm/rpc_uac.c
@@ -156,12 +156,10 @@ static char *get_hfblock(str *uri, struct hdr_field *hf, int proto,
total_len = 0;
last = &sl;
last->next = 0;
+ sock_name = 0;
+ portname = 0;
if (ssock){
- sock_name = &ssock->address_str;
- portname = &ssock->port_no_str;
- }else{
- sock_name = 0;
- portname = 0;
+ si_get_signaling_data(ssock, &sock_name, &portname);
}
for (; hf; hf = hf->next) {
@@ -197,8 +195,7 @@ static char *get_hfblock(str *uri, struct hdr_field *hf, int proto,
" failed\n");
goto error;
}
- sock_name = &di.send_sock->address_str;
- portname = &di.send_sock->port_no_str;
+ si_get_signaling_data(di.send_sock, &sock_name, &portname);
}
if (!append_str_list(sock_name->s, sock_name->len, &last,
&total_len))
--
2.1.1

@ -0,0 +1,38 @@
From f3820f1a9837451b9209aa40ca5ab750e59fec19 Mon Sep 17 00:00:00 2001
From: Daniel-Constantin Mierla <miconda@gmail.com>
Date: Thu, 2 Oct 2014 10:18:11 +0200
Subject: [PATCH] mohqueue: fixed db_qtable parameter name
- reported by Marino Mileti
(cherry picked from commit 321575dcd18e42fe6c62942ef417dd8acf7f466d)
Conflicts:
modules/mohqueue/mohq.c
---
modules/mohqueue/mohq.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/modules/mohqueue/mohq.c b/modules/mohqueue/mohq.c
index 0c0d118..20a9ace 100644
--- a/modules/mohqueue/mohq.c
+++ b/modules/mohqueue/mohq.c
@@ -70,7 +70,7 @@ int moh_maxcalls = 50;
static param_export_t mod_parms [] = {
{ "db_url", STR_PARAM, &db_url },
{ "db_ctable", STR_PARAM, &db_ctable },
- { "db_ctable", STR_PARAM, &db_qtable },
+ { "db_qtable", STR_PARAM, &db_qtable },
{ "mohdir", STR_PARAM, &mohdir },
{ "moh_maxcalls", INT_PARAM, &moh_maxcalls },
{ NULL, 0, NULL },
@@ -439,4 +439,4 @@ if (pmod_data->pcall_lock->plock)
shm_free (pmod_data);
pmod_data = NULL;
return -1;
-}
\ No newline at end of file
+}
--
2.1.1

@ -0,0 +1,233 @@
From 2d49bc59bb8084bfb8f4e1c89210d9e8c35781a8 Mon Sep 17 00:00:00 2001
From: Hugh Waite <hugh.waite@acision.com>
Date: Thu, 2 Oct 2014 18:37:00 +0100
Subject: [PATCH] rr: Fix memory leak when using outbound
- Flow token memory is freed after building the rr header
---
modules/rr/record.c | 78 ++++++++++++++++++++++++++++++++++++++---------------
1 file changed, 56 insertions(+), 22 deletions(-)
diff --git a/modules/rr/record.c b/modules/rr/record.c
index 3ccd452..00fa024 100644
--- a/modules/rr/record.c
+++ b/modules/rr/record.c
@@ -375,11 +375,12 @@ static int copy_flow_token(str *token, struct sip_msg *_m)
int record_route(struct sip_msg* _m, str *params)
{
struct lump* l, *l2;
- str user;
+ str user = {NULL, 0};
struct to_body* from = NULL;
str* tag;
int use_ob = rr_obb.use_outbound ? rr_obb.use_outbound(_m) : 0;
int sips;
+ int ret = 0;
user.len = 0;
@@ -406,7 +407,8 @@ int record_route(struct sip_msg* _m, str *params)
if (append_fromtag) {
if (parse_from_header(_m) < 0) {
LM_ERR("From parsing failed\n");
- return -2;
+ ret = -2;
+ goto error;
}
from = (struct to_body*)_m->from->parsed;
tag = &from->tag_value;
@@ -426,17 +428,20 @@ int record_route(struct sip_msg* _m, str *params)
l2 = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, 0);
if (!l || !l2) {
LM_ERR("failed to create an anchor\n");
- return -5;
+ ret = -5;
+ goto error;
}
l = insert_cond_lump_after(l, COND_IF_DIFF_REALMS, 0);
l2 = insert_cond_lump_before(l2, COND_IF_DIFF_REALMS, 0);
if (!l || !l2) {
LM_ERR("failed to insert conditional lump\n");
- return -6;
+ ret = -6;
+ goto error;
}
if (build_rr(l, l2, &user, tag, params, OUTBOUND, sips) < 0) {
LM_ERR("failed to insert outbound Record-Route\n");
- return -7;
+ ret = -7;
+ goto error;
}
}
@@ -444,17 +449,24 @@ int record_route(struct sip_msg* _m, str *params)
l2 = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, 0);
if (!l || !l2) {
LM_ERR("failed to create an anchor\n");
- return -3;
+ ret = -3;
+ goto error;
}
if (build_rr(l, l2, &user, tag, params, INBOUND, sips) < 0) {
LM_ERR("failed to insert inbound Record-Route\n");
- return -4;
+ ret = -4;
+ goto error;
}
/* reset the rr_param buffer */
rr_param_buf.len = 0;
- return 0;
+ ret = 0;
+error:
+ if ((use_ob == 1) || (use_ob == 2))
+ if (user.s != NULL)
+ pkg_free(user.s);
+ return ret;
}
@@ -470,7 +482,7 @@ int record_route(struct sip_msg* _m, str *params)
*/
int record_route_preset(struct sip_msg* _m, str* _data)
{
- str user;
+ str user = {NULL, 0};
struct to_body* from;
struct lump* l;
char* hdr, *p;
@@ -479,6 +491,7 @@ int record_route_preset(struct sip_msg* _m, str* _data)
char *rr_prefix;
int rr_prefix_len;
int sips;
+ int ret = 0;
sips = rr_is_sips(_m);
if(sips==0) {
@@ -513,7 +526,8 @@ int record_route_preset(struct sip_msg* _m, str* _data)
if (append_fromtag) {
if (parse_from_header(_m) < 0) {
LM_ERR("From parsing failed\n");
- return -2;
+ ret = -2;
+ goto error;
}
from = (struct to_body*)_m->from->parsed;
}
@@ -521,7 +535,8 @@ int record_route_preset(struct sip_msg* _m, str* _data)
l = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, HDR_RECORDROUTE_T);
if (!l) {
LM_ERR("failed to create lump anchor\n");
- return -3;
+ ret = -3;
+ goto error;
}
hdr_len = rr_prefix_len;
@@ -544,7 +559,8 @@ int record_route_preset(struct sip_msg* _m, str* _data)
hdr = pkg_malloc(hdr_len);
if (!hdr) {
LM_ERR("no pkg memory left\n");
- return -4;
+ ret = -4;
+ goto error;
}
p = hdr;
@@ -581,9 +597,15 @@ int record_route_preset(struct sip_msg* _m, str* _data)
if (!insert_new_lump_after(l, hdr, hdr_len, 0)) {
LM_ERR("failed to insert new lump\n");
pkg_free(hdr);
- return -5;
+ ret = -5;
+ goto error;
}
- return 1;
+ ret = 1;
+error:
+ if ((use_ob == 1) || (use_ob == 2))
+ if (user.s != NULL)
+ pkg_free(user.s);
+ return ret;
}
/*!
@@ -723,12 +745,13 @@ lump_err:
int record_route_advertised_address(struct sip_msg* _m, str* _data)
{
- str user;
+ str user = {NULL, 0};
str *tag = NULL;
struct lump* l;
struct lump* l2;
int use_ob = rr_obb.use_outbound ? rr_obb.use_outbound(_m) : 0;
int sips;
+ int ret = 0;
user.len = 0;
user.s = 0;
@@ -753,7 +776,8 @@ int record_route_advertised_address(struct sip_msg* _m, str* _data)
if (append_fromtag) {
if (parse_from_header(_m) < 0) {
LM_ERR("From parsing failed\n");
- return -2;
+ ret = -2;
+ goto error;
}
tag = &((struct to_body*)_m->from->parsed)->tag_value;
}
@@ -765,18 +789,21 @@ int record_route_advertised_address(struct sip_msg* _m, str* _data)
l2 = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, 0);
if (!l || !l2) {
LM_ERR("failed to create an anchor\n");
- return -3;
+ ret = -3;
+ goto error;
}
l = insert_cond_lump_after(l, COND_IF_DIFF_PROTO, 0);
l2 = insert_cond_lump_before(l2, COND_IF_DIFF_PROTO, 0);
if (!l || !l2) {
LM_ERR("failed to insert conditional lump\n");
- return -4;
+ ret = -4;
+ goto error;
}
if (build_advertised_rr(l, l2, _data, &user, tag, OUTBOUND,
sips) < 0) {
LM_ERR("failed to insert outbound Record-Route\n");
- return -5;
+ ret = -5;
+ goto error;
}
}
@@ -784,14 +811,21 @@ int record_route_advertised_address(struct sip_msg* _m, str* _data)
l2 = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, 0);
if (!l || !l2) {
LM_ERR("failed to create an anchor\n");
- return -6;
+ ret = -6;
+ goto error;
}
if (build_advertised_rr(l, l2, _data, &user, tag, INBOUND, sips) < 0) {
LM_ERR("failed to insert outbound Record-Route\n");
- return -7;
+ ret = -7;
+ goto error;
}
- return 1;
+ ret = 1;
+error:
+ if ((use_ob == 1) || (use_ob == 2))
+ if (user.s != NULL)
+ pkg_free(user.s);
+ return ret;
}
--
2.1.1

@ -0,0 +1,83 @@
From 58746ce4966b254cb465045cb517f652a24a5317 Mon Sep 17 00:00:00 2001
From: Hugh Waite <hugh.waite@acision.com>
Date: Wed, 8 Oct 2014 19:01:20 +0100
Subject: [PATCH] core: xavp: Fix xavp_insert to prevent corrupted linked lists
- Inserting data at a given index will pad the xavp with XTYPE_NULL entries
- Inserting data will replace a NULL entry if present
(cherry picked from commit 1828c8ab644243878fc6db9ff0f2592e656dc09a)
---
xavp.c | 34 +++++++++++++++++++---------------
1 file changed, 19 insertions(+), 15 deletions(-)
diff --git a/xavp.c b/xavp.c
index 5f51731..0d73fd3 100644
--- a/xavp.c
+++ b/xavp.c
@@ -694,44 +694,48 @@ sr_xavp_t *xavp_clone_level_nodata(sr_xavp_t *xold)
int xavp_insert(sr_xavp_t *xavp, int idx, sr_xavp_t **list)
{
sr_xavp_t *crt = 0;
- sr_xavp_t *fst = 0;
sr_xavp_t *lst = 0;
sr_xval_t val;
int n = 0;
int i = 0;
- if(idx==0)
+ crt = xavp_get_internal(&xavp->name, list, 0, NULL);
+
+ if (idx == 0 && (!crt || crt->val.type != SR_XTYPE_NULL))
return xavp_add(xavp, list);
- crt = xavp_get_internal(&xavp->name, list, 0, 0);
while(crt!=NULL && n<idx) {
lst = crt;
n++;
crt = xavp_get_next(lst);
}
+
+ if (crt && crt->val.type == SR_XTYPE_NULL) {
+ xavp->next = crt->next;
+ crt->next = xavp;
+
+ xavp_rm(crt, list);
+ return 0;
+ }
+
memset(&val, 0, sizeof(sr_xval_t));
val.type = SR_XTYPE_NULL;
for(i=0; i<idx-n; i++) {
- crt = xavp_add_value(&xavp->name, &val, list);
+ crt = xavp_new_value(&xavp->name, &val);
if(crt==NULL)
return -1;
- if(fst==NULL)
- fst = crt;
- if(lst==NULL) {
- if(xavp_add(crt, list)<0)
- return -1;
+ if (lst == NULL) {
+ crt->next = *list;
+ *list = crt;
} else {
crt->next = lst->next;
lst->next = crt;
}
+ lst = crt;
}
- if(fst==NULL) {
- return xavp_add(xavp, list);
- } else {
- xavp->next = fst->next;
- fst->next = xavp;
- }
+ xavp->next = lst->next;
+ lst->next = xavp;
return 0;
}
--
2.1.1
Loading…
Cancel
Save