From 47bdff2570e40f2a9dad03547e0a907752211eb4 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Tue, 18 Oct 2016 16:11:22 +0200 Subject: [PATCH 001/133] WIP: l2tpd: make it compile again fix all compiler warnings & errors but -Wunsed-function --- siu/l2tp/Makefile | 14 +++++++-- siu/l2tp/l2tpd.c | 66 +++++++++++++++++++++++++------------------ siu/l2tp/l2tpd_data.c | 11 ++++++++ siu/l2tp/l2tpd_data.h | 3 ++ 4 files changed, 63 insertions(+), 31 deletions(-) diff --git a/siu/l2tp/Makefile b/siu/l2tp/Makefile index ec602d1..9b869be 100644 --- a/siu/l2tp/Makefile +++ b/siu/l2tp/Makefile @@ -1,8 +1,16 @@ +PREFIX ?= /usr/local + +CFLAGS := -I $(PREFIX)/include/ -Wno-unused-function -Wall +LDFLAGS := -L $(PREFIX)/lib -lcrypto -losmocore -losmogsm -ltalloc + all: l2tpd -l2tpd: l2tpd.c l2tpd_data.c l2tpd_fsm.c - $(CC) -Wall -lcrypto -losmocore -losmogsm -o $@ $< +l2tpd: l2tpd.o l2tpd_fsm.o l2tpd_data.o + $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) + +%.o: %.c + $(CC) $(CFLAGS) -c $^ -o $@ clean: - rm l2tpd + rm -f l2tpd l2tp*.o diff --git a/siu/l2tp/l2tpd.c b/siu/l2tp/l2tpd.c index 857a29c..a0bbcb2 100644 --- a/siu/l2tp/l2tpd.c +++ b/siu/l2tp/l2tpd.c @@ -12,9 +12,11 @@ #include #include #include +#include #include "l2tp_protocol.h" #include "l2tpd.h" +#include "l2tpd_data.h" #include "l2tpd_fsm.h" /*********************************************************************** @@ -31,6 +33,9 @@ struct avp_parsed { uint8_t *data; }; +struct l2tpd_instance *l2i; +/* FIXME: global static instance */ + /* parse single AVP at msg->data + offset and return the new offset */ static int msgb_avp_parse(struct avp_parsed *ap, struct msgb *msg, int offset) { @@ -72,14 +77,14 @@ static int msgb_avps_parse(struct avps_parsed *avps, struct msgb *msg, int offse memset(avps, 0, sizeof(*avps)); while (msgb_length(msg) - offset > 0) { - struct avp_parsed *avp = avps->avp[avps->num_avps++]; + struct avp_parsed *avp = &avps->avp[avps->num_avp++]; int rc = msgb_avp_parse(avp, msg, offset); if (rc < 0) return rc; else offset = rc; } - return num_avps; + return avps->num_avp; } static struct avp_parsed * @@ -95,7 +100,7 @@ avps_parsed_find(struct avps_parsed *avps, uint16_t vendor_id, uint16_t type) return NULL; } -static uint8_t avpp_val(struct avps_parsed *avps, uint16_t vendor_id, uint16_t type) +static uint8_t *avpp_val(struct avps_parsed *avps, uint16_t vendor_id, uint16_t type) { struct avp_parsed *avp = avps_parsed_find(avps, vendor_id, type); if (!avp) @@ -120,7 +125,7 @@ int avpp_val_u32(struct avps_parsed *avps, uint16_t vendor_id, uint16_t type, if (avp->data_len < sizeof(*u32)) return -EINVAL; - u32 = *(uint32_t *)avp->data; + *u32 = *((uint32_t *)avp->data); return 0; } @@ -133,7 +138,7 @@ int avpp_val_u16(struct avps_parsed *avps, uint16_t vendor_id, uint16_t type, if (avp->data_len < sizeof(*u16)) return -EINVAL; - u16 = *(uint16_t *)avp->data; + *u16 = *((uint16_t *)avp->data); return 0; } @@ -148,7 +153,7 @@ static int msgb_avp_put(struct msgb *msg, uint16_t vendor_id, uint16_t type, return -1; } - msgb_put_u16(msg, (data_len + 6) & 0x3ff | (m_flag ? 0x8000 : 0)); + msgb_put_u16(msg, ((data_len + 6) & 0x3ff) | (m_flag ? 0x8000 : 0)); msgb_put_u16(msg, vendor_id); msgb_put_u16(msg, type); out = msgb_put(msg, data_len); @@ -235,13 +240,14 @@ static int digest_avp_update(struct msgb *msg) if (ntohs(ah->attr_type) != AVP_IETF_MSG_DIGEST || ntohs(ah->vendor_id) != VENDOR_IETF || - ntohs(ah->m_h_length) & 0x3FF != 17) { + (ntohs(ah->m_h_length) & 0x3FF) != 17) { LOGP(DL2TP, LOGL_ERROR, "Missing Digest AVP, cannot update\n"); return -1; } if (len > msgb_l2tplen(msg)) { - LOGP(DL2TP, LOGL_ERROR, ""); + /* FIXME: improve log message */ + LOGP(DL2TP, LOGL_ERROR, "invalid length"); return -1; } @@ -275,6 +281,7 @@ static int l2tp_msgb_tx(struct msgb *msg) /* FIXME: put in the queue for reliable re-transmission */ /* FIXME: actually transmit it */ + return 0; } /*********************************************************************** @@ -383,6 +390,7 @@ static int rx_scc_rq(struct msgb *msg, struct avps_parsed *ap) { struct l2tp_control_hdr *ch = msgb_l2tph(msg); struct l2tpd_connection *l2cc; + char *host_name = NULL; uint16_t pw; /* Abort if Pseudowire capability doesn't include 6(HDLC) */ @@ -404,7 +412,7 @@ static int rx_scc_rq(struct msgb *msg, struct avps_parsed *ap) &router_id)) l2cc->remote.router_id = router_id; /* Host Name AVP */ - host_name = avpp_val(ap, VENDOR_IETF, AVP_IETF_HOST_NAME); + host_name = (char *) avpp_val(ap, VENDOR_IETF, AVP_IETF_HOST_NAME); if (host_name) l2cc->remote.host_name = talloc_strdup(l2cc, host_name); } @@ -418,7 +426,7 @@ static int rx_scc_rq(struct msgb *msg, struct avps_parsed *ap) static int rx_scc_cn(struct msgb *msg, struct avps_parsed *ap) { struct l2tp_control_hdr *ch = msgb_l2tph(msg); - struct l2tpd_connection *l2cc = l2tpd_cc_find_by_l_cc_id(ch->ccid); + struct l2tpd_connection *l2cc = l2tpd_cc_find_by_l_cc_id(l2i, ch->ccid); if (!l2cc) return -1; @@ -432,7 +440,7 @@ static int rx_scc_cn(struct msgb *msg, struct avps_parsed *ap) static int rx_stop_ccn(struct msgb *msg, struct avps_parsed *ap) { struct l2tp_control_hdr *ch = msgb_l2tph(msg); - struct l2tpd_connection *l2cc = l2tpd_cc_find_by_l_cc_id(ch->ccid); + struct l2tpd_connection *l2cc = l2tpd_cc_find_by_l_cc_id(l2i, ch->ccid); if (!l2cc) return -1; @@ -445,10 +453,10 @@ static int rx_stop_ccn(struct msgb *msg, struct avps_parsed *ap) static int rx_ic_rq(struct msgb *msg, struct avps_parsed *ap) { struct l2tp_control_hdr *ch = msgb_l2tph(msg); - struct l2tpd_connection *l2cc = l2tpd_cc_find_by_l_cc_id(ch->ccid); + struct l2tpd_connection *l2cc = l2tpd_cc_find_by_l_cc_id(l2i, ch->ccid); struct l2tpd_session *l2s; - uint32_t r_sess_id = avpp_val_u32(ap, VENDOR_IETF, AVP_IETF_REM_SESS_ID); - uint32_t l_sess_id = avpp_val_u32(ap, VENDOR_IETF, AVP_IETF_LOC_SESS_ID); + uint32_t r_sess_id = 0; + uint32_t l_sess_id = 0; if (!l2cc) return -1; @@ -464,13 +472,13 @@ static int rx_ic_rq(struct msgb *msg, struct avps_parsed *ap) } else { l2s = l2tpd_sess_find_by_l_s_id(l2cc, r_sess_id); if (!l2s) { - LOGP(DL2TPD, LOGL_ERROR, "NoSession %u\n", + LOGP(DL2TP, LOGL_ERROR, "NoSession %u\n", r_sess_id); return -1; } } - osmo_fsm_inst_dispatch(l2ic->fsm, L2IC_E_RX_ICRQ, msg); + osmo_fsm_inst_dispatch(l2cc->fsm, L2IC_E_RX_ICRQ, msg); return 0; } @@ -478,12 +486,12 @@ static int rx_ic_rq(struct msgb *msg, struct avps_parsed *ap) static int rx_ic_cn(struct msgb *msg, struct avps_parsed *ap) { struct l2tp_control_hdr *ch = msgb_l2tph(msg); - struct l2tpd_connection *l2cc = l2tpd_cc_find_by_l_cc_id(ch->ccid); + struct l2tpd_connection *l2cc = l2tpd_cc_find_by_l_cc_id(l2i, ch->ccid); if (!l2cc) return -1; - osmo_fsm_inst_dispatch(l2ic->fsm, L2IC_E_RX_ICCN, msg); + osmo_fsm_inst_dispatch(l2cc->fsm, L2IC_E_RX_ICCN, msg); return 0; } @@ -491,12 +499,12 @@ static int rx_ic_cn(struct msgb *msg, struct avps_parsed *ap) static int rx_cdn(struct msgb *msg, struct avps_parsed *ap) { struct l2tp_control_hdr *ch = msgb_l2tph(msg); - struct l2tpd_connection *l2cc = l2tpd_cc_find_by_l_cc_id(ch->ccid); + struct l2tpd_connection *l2cc = l2tpd_cc_find_by_l_cc_id(l2i, ch->ccid); if (!l2cc) return -1; - osmo_fsm_inst_dispatch(l2ic->fsm, L2IC_E_RX_CDN, msg); + osmo_fsm_inst_dispatch(l2cc->fsm, L2IC_E_RX_CDN, msg); return 0; } @@ -531,7 +539,7 @@ static int l2tp_rcvmsg_control_ietf(struct msgb *msg, struct avps_parsed *ap, static int rx_eri_tcrp(struct msgb *msg, struct avps_parsed *ap) { struct l2tp_control_hdr *ch = msgb_l2tph(msg); - struct l2tpd_connection *l2cc = l2tpd_cc_find_by_l_cc_id(ch->ccid); + struct l2tpd_connection *l2cc = l2tpd_cc_find_by_l_cc_id(l2i, ch->ccid); if (!l2cc) return -1; @@ -541,7 +549,7 @@ static int rx_eri_tcrp(struct msgb *msg, struct avps_parsed *ap) static int rx_eri_altcrp(struct msgb *msg, struct avps_parsed *ap) { struct l2tp_control_hdr *ch = msgb_l2tph(msg); - struct l2tpd_connection *l2cc = l2tpd_cc_find_by_l_cc_id(ch->ccid); + struct l2tpd_connection *l2cc = l2tpd_cc_find_by_l_cc_id(l2i, ch->ccid); if (!l2cc) return -1; @@ -579,7 +587,7 @@ static int l2tp_rcvmsg_control(struct msgb *msg) return -1; } - if (ch->ver & T_BIT|L_BIT|S_BIT != T_BIT|L_BIT|S_BIT) { + if ((ch->ver & (T_BIT|L_BIT|S_BIT)) != (T_BIT|L_BIT|S_BIT)) { LOGP(DL2TP, LOGL_ERROR, "L2TP Bits wrong\n"); return -1; } @@ -620,11 +628,13 @@ static int l2tp_rcvmsg_control(struct msgb *msg) if (first_avp->vendor_id == VENDOR_IETF && first_avp->type == AVP_IETF_CTRL_MSG) - return l2tp_rcvmsg_control_ietf(msg, &ap); + return l2tp_rcvmsg_control_ietf(msg, &ap, msg_type); else if (first_avp->vendor_id == VENDOR_ERICSSON && - firrst_avp->type == AVP_ERIC_CTRL_MSG) - return l2tp_rcvmsg_control_ericsson(msg, &ap); + first_avp->type == AVP_ERIC_CTRL_MSG) + return l2tp_rcvmsg_control_ericsson(msg, &ap, msg_type); + /* FIXME: return value */ + return -1; } static int l2tp_rcvmsg_data(struct msgb *msg, bool ip_transport) @@ -635,8 +645,6 @@ static int l2tp_rcvmsg_data(struct msgb *msg, bool ip_transport) int l2tp_rcvmsg(struct msgb *msg, bool ip_transport) { - struct l2tp_control_hdr *ch; - if (ip_transport) { uint32_t session = osmo_load32be(msgb_l2tph(msg)); if (session == 0) { @@ -649,6 +657,7 @@ int l2tp_rcvmsg(struct msgb *msg, bool ip_transport) } else { LOGP(DL2TP, LOGL_ERROR, "UDP transport not supported (yet?)\n"); /* FIXME */ + return -1; } } @@ -696,6 +705,7 @@ int main(int argc, char **argv) struct l2tpd_instance li; int rc; + l2i = &li; li.cfg.bind_ip = "0.0.0.0"; rc = l2tpd_instance_start(&li); if (rc < 0) diff --git a/siu/l2tp/l2tpd_data.c b/siu/l2tp/l2tpd_data.c index 41555cb..4dbcbe5 100644 --- a/siu/l2tp/l2tpd_data.c +++ b/siu/l2tp/l2tpd_data.c @@ -46,3 +46,14 @@ l2tpd_sess_alloc(struct l2tpd_connection *conn) return l2s; } + +struct l2tpd_session * +l2tpd_sess_find_by_l_s_id(struct l2tpd_connection *conn, uint32_t session_id) +{ + struct l2tpd_session *l2s; + llist_for_each_entry(l2s, &conn->sessions, list) { + if (l2s->l_sess_id == session_id) + return l2s; + } + return NULL; +} diff --git a/siu/l2tp/l2tpd_data.h b/siu/l2tp/l2tpd_data.h index 48199ec..48cb30a 100644 --- a/siu/l2tp/l2tpd_data.h +++ b/siu/l2tp/l2tpd_data.h @@ -10,3 +10,6 @@ l2tpd_cc_alloc(struct l2tpd_instance *inst); struct l2tpd_session * l2tpd_sess_alloc(struct l2tpd_connection *conn); + +struct l2tpd_session * +l2tpd_sess_find_by_l_s_id(struct l2tpd_connection *conn, uint32_t session_id); From e0524720a3e47b8f8f5ac8fad8a0fdf2aa4f4ba7 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Sun, 23 Oct 2016 16:28:52 +0200 Subject: [PATCH 002/133] l2tp_data: add l2tpd_cc_find_by_sockaddr() --- siu/l2tp/l2tpd_data.c | 13 +++++++++++++ siu/l2tp/l2tpd_data.h | 7 +++++++ 2 files changed, 20 insertions(+) diff --git a/siu/l2tp/l2tpd_data.c b/siu/l2tp/l2tpd_data.c index 4dbcbe5..0060a6c 100644 --- a/siu/l2tp/l2tpd_data.c +++ b/siu/l2tp/l2tpd_data.c @@ -4,6 +4,7 @@ #include #include +#include #include "l2tpd.h" #include "l2tpd_data.h" @@ -20,6 +21,18 @@ l2tpd_cc_find_by_l_cc_id(struct l2tpd_instance *inst, uint32_t l_cc_id) return NULL; } + +struct l2tpd_connection * +l2tpd_cc_find_by_sockaddr(struct l2tpd_instance *inst, struct sockaddr *ss); +{ + struct l2tpd_connection *l2c; + llist_for_each_entry(l2c, &inst->connections, list) { + if (sockaddr_equal(ss, &l2c->remote.ss)) + return l2c; + } + return NULL; +} + struct l2tpd_connection * l2tpd_cc_alloc(struct l2tpd_instance *inst) { diff --git a/siu/l2tp/l2tpd_data.h b/siu/l2tp/l2tpd_data.h index 48cb30a..cb38fb1 100644 --- a/siu/l2tp/l2tpd_data.h +++ b/siu/l2tp/l2tpd_data.h @@ -2,12 +2,19 @@ #include "l2tpd.h" +struct sockaddr; + +/* l2tp connection */ +struct l2tpd_connection * +l2tpd_cc_find_by_sockaddr(struct l2tpd_instance *inst, struct sockaddr *ss); + struct l2tpd_connection * l2tpd_cc_find_by_l_cc_id(struct l2tpd_instance *inst, uint32_t l_cc_id); struct l2tpd_connection * l2tpd_cc_alloc(struct l2tpd_instance *inst); +/* l2tp session */ struct l2tpd_session * l2tpd_sess_alloc(struct l2tpd_connection *conn); From 11f28c40a12d3d77c1ab4d0e7fa7b04d179f4374 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Sun, 23 Oct 2016 16:29:56 +0200 Subject: [PATCH 003/133] l2tp_data: give l2tp_recvmsg socketaddr of the incoming packet --- siu/l2tp/l2tpd.c | 11 ++++++----- siu/l2tp/l2tpd.h | 3 +++ 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/siu/l2tp/l2tpd.c b/siu/l2tp/l2tpd.c index a0bbcb2..e0fdb0e 100644 --- a/siu/l2tp/l2tpd.c +++ b/siu/l2tp/l2tpd.c @@ -643,8 +643,9 @@ static int l2tp_rcvmsg_data(struct msgb *msg, bool ip_transport) return 0; } -int l2tp_rcvmsg(struct msgb *msg, bool ip_transport) +int l2tp_rcvmsg(struct sockaddr *ss, struct msgb *msg, bool ip_transport) { + /* search first for the ip */ if (ip_transport) { uint32_t session = osmo_load32be(msgb_l2tph(msg)); if (session == 0) { @@ -664,21 +665,21 @@ int l2tp_rcvmsg(struct msgb *msg, bool ip_transport) static int l2tp_ip_read_cb(struct osmo_fd *ofd, unsigned int what) { struct msgb *msg = l2tp_msgb_alloc(); - struct sockaddr_in sin; - socklen_t sin_len = sizeof(sin); + struct sockaddr ss; + socklen_t ss_len = sizeof(ss); int rc; /* actually read the message from the raw IP socket */ msg->l2h = msg->data; rc = recvfrom(ofd->fd, msgb_l2tph(msg), msgb_l2tplen(msg), 0, - (struct sockaddr *) &sin, &sin_len); + (struct sockaddr *) &ss, &ss_len); if (rc < 0) return rc; msgb_put(msg, rc); /* FIXME: resolve l2tpd_connection somewhere ? */ - return l2tp_rcvmsg(msg, true); + return l2tp_rcvmsg(ss, msg, true); } static int l2tpd_instance_start(struct l2tpd_instance *li) diff --git a/siu/l2tp/l2tpd.h b/siu/l2tp/l2tpd.h index 781d0bc..d84629b 100644 --- a/siu/l2tp/l2tpd.h +++ b/siu/l2tp/l2tpd.h @@ -2,6 +2,8 @@ #include +#include + #include #include #include @@ -19,6 +21,7 @@ static inline unsigned int msgb_l2tplen(const struct msgb *msg) /* identifiers of a peer on a L2TP connection */ struct l2tpd_peer { + struct sockaddr ss; char *host_name; uint32_t router_id; /* Control Connection ID */ From f79af9629bddb4cca7b699db729d23d7811ad391 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Sun, 23 Oct 2016 21:37:28 +0200 Subject: [PATCH 004/133] l2tpd_cc_find_by_sockaddr: add sockaddr length to function signature osmo_sockaddr_equal requires an sockaddr length --- siu/l2tp/l2tpd_data.c | 6 ++---- siu/l2tp/l2tpd_data.h | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/siu/l2tp/l2tpd_data.c b/siu/l2tp/l2tpd_data.c index 0060a6c..8b3971a 100644 --- a/siu/l2tp/l2tpd_data.c +++ b/siu/l2tp/l2tpd_data.c @@ -23,11 +23,11 @@ l2tpd_cc_find_by_l_cc_id(struct l2tpd_instance *inst, uint32_t l_cc_id) struct l2tpd_connection * -l2tpd_cc_find_by_sockaddr(struct l2tpd_instance *inst, struct sockaddr *ss); +l2tpd_cc_find_by_sockaddr(struct l2tpd_instance *inst, struct sockaddr *ss, int ss_len) { struct l2tpd_connection *l2c; llist_for_each_entry(l2c, &inst->connections, list) { - if (sockaddr_equal(ss, &l2c->remote.ss)) + if (osmo_sockaddr_equal(ss, &l2c->remote.ss, ss_len)) return l2c; } return NULL; @@ -46,8 +46,6 @@ l2tpd_cc_alloc(struct l2tpd_instance *inst) return l2c; } - - struct l2tpd_session * l2tpd_sess_alloc(struct l2tpd_connection *conn) { diff --git a/siu/l2tp/l2tpd_data.h b/siu/l2tp/l2tpd_data.h index cb38fb1..c37680f 100644 --- a/siu/l2tp/l2tpd_data.h +++ b/siu/l2tp/l2tpd_data.h @@ -6,7 +6,7 @@ struct sockaddr; /* l2tp connection */ struct l2tpd_connection * -l2tpd_cc_find_by_sockaddr(struct l2tpd_instance *inst, struct sockaddr *ss); +l2tpd_cc_find_by_sockaddr(struct l2tpd_instance *inst, struct sockaddr *ss, int ss_len); struct l2tpd_connection * l2tpd_cc_find_by_l_cc_id(struct l2tpd_instance *inst, uint32_t l_cc_id); From 425cef78245ef1670710f28b50537ebf989b0e8d Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Sun, 23 Oct 2016 21:38:07 +0200 Subject: [PATCH 005/133] l2tpd_data: init l2connetion fsm --- siu/l2tp/l2tpd_data.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/siu/l2tp/l2tpd_data.c b/siu/l2tp/l2tpd_data.c index 8b3971a..2d56fa4 100644 --- a/siu/l2tp/l2tpd_data.c +++ b/siu/l2tp/l2tpd_data.c @@ -5,9 +5,11 @@ #include #include #include +#include #include "l2tpd.h" #include "l2tpd_data.h" +#include "l2tpd_fsm.h" /* Find a connection for given local control connection id */ struct l2tpd_connection * @@ -42,6 +44,7 @@ l2tpd_cc_alloc(struct l2tpd_instance *inst) l2c->local.ccid = inst->next_l_cc_id++; llist_add(&l2c->list, &inst->connections); + l2c->fsm = osmo_fsm_inst_alloc(l2tp_cc_fsm, l2c, NULL, LOGL_DEBUG, NULL); return l2c; } From 0e71714f7f14a6e17c15891d52f566ecde8d4734 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Sun, 23 Oct 2016 21:39:44 +0200 Subject: [PATCH 006/133] generalize l2tp_rcvmsg: dont to any difference between ip and udp this should handle the upper layer --- siu/l2tp/l2tpd.c | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/siu/l2tp/l2tpd.c b/siu/l2tp/l2tpd.c index e0fdb0e..0a48202 100644 --- a/siu/l2tp/l2tpd.c +++ b/siu/l2tp/l2tpd.c @@ -643,28 +643,21 @@ static int l2tp_rcvmsg_data(struct msgb *msg, bool ip_transport) return 0; } -int l2tp_rcvmsg(struct sockaddr *ss, struct msgb *msg, bool ip_transport) +int l2tp_rcvmsg(struct l2tpd_connection *conn, struct msgb *msg) { - /* search first for the ip */ - if (ip_transport) { - uint32_t session = osmo_load32be(msgb_l2tph(msg)); - if (session == 0) { - /* strip session ID and feed to control */ - msgb_pull(msg, sizeof(session)); - return l2tp_rcvmsg_control(msg); - } else { - return l2tp_rcvmsg_data(msg, true); - } - } else { - LOGP(DL2TP, LOGL_ERROR, "UDP transport not supported (yet?)\n"); - /* FIXME */ - return -1; + uint32_t session = osmo_load32be(msgb_l2tph(msg)); + if (session == 0) { + /* strip session ID and feed to control */ + msgb_pull(msg, sizeof(session)); + return l2tp_rcvmsg_control(msg); } + return -1; } static int l2tp_ip_read_cb(struct osmo_fd *ofd, unsigned int what) { struct msgb *msg = l2tp_msgb_alloc(); + struct l2tpd_connection *l2c; struct sockaddr ss; socklen_t ss_len = sizeof(ss); int rc; @@ -679,7 +672,7 @@ static int l2tp_ip_read_cb(struct osmo_fd *ofd, unsigned int what) /* FIXME: resolve l2tpd_connection somewhere ? */ - return l2tp_rcvmsg(ss, msg, true); + return l2tp_rcvmsg(l2c, msg); } static int l2tpd_instance_start(struct l2tpd_instance *li) From 3a566f2b05820d8e8d8b2ac365cd18bcf0b7ba5d Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Sun, 23 Oct 2016 21:40:34 +0200 Subject: [PATCH 007/133] lookup the l2tpd connection using the src ip --- siu/l2tp/l2tpd.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/siu/l2tp/l2tpd.c b/siu/l2tp/l2tpd.c index 0a48202..c3dc0ee 100644 --- a/siu/l2tp/l2tpd.c +++ b/siu/l2tp/l2tpd.c @@ -671,6 +671,13 @@ static int l2tp_ip_read_cb(struct osmo_fd *ofd, unsigned int what) msgb_put(msg, rc); /* FIXME: resolve l2tpd_connection somewhere ? */ + l2c = l2tpd_cc_find_by_sockaddr(l2i, ss, sizeof(*ss)); + if (!l2c) { + /* create a new connection */ + LOGP(DL2TP, LOGL_ERROR, "New l2tp connection: %s\n", ); + l2c = l2tpd_cc_alloc(l2i); + memcpy(l2c->remote.ss, &ss, sizeof(*ss)); + } return l2tp_rcvmsg(l2c, msg); } From 0dfe18c7bd3942b5b0019e3a11d0bb93ca1ea6a1 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Sun, 23 Oct 2016 22:32:50 +0200 Subject: [PATCH 008/133] fixme: use local version until osmo_sockaddr_equal is upstream work around old libosmocore version --- siu/l2tp/l2tpd.c | 2 +- siu/l2tp/l2tpd_data.c | 33 +++++++++++++++++++++++++++++++-- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/siu/l2tp/l2tpd.c b/siu/l2tp/l2tpd.c index c3dc0ee..e0adc2d 100644 --- a/siu/l2tp/l2tpd.c +++ b/siu/l2tp/l2tpd.c @@ -633,7 +633,7 @@ static int l2tp_rcvmsg_control(struct msgb *msg) first_avp->type == AVP_ERIC_CTRL_MSG) return l2tp_rcvmsg_control_ericsson(msg, &ap, msg_type); - /* FIXME: return value */ + LOGP(DL2TP, LOGL_ERROR, "Unknown packet received.\n"); return -1; } diff --git a/siu/l2tp/l2tpd_data.c b/siu/l2tp/l2tpd_data.c index 2d56fa4..3a28814 100644 --- a/siu/l2tp/l2tpd_data.c +++ b/siu/l2tp/l2tpd_data.c @@ -11,6 +11,36 @@ #include "l2tpd_data.h" #include "l2tpd_fsm.h" + +/* FIXME: use libosmocore osmo_sockaddr_equal when its upstream */ +static int sockaddr_equal(const struct sockaddr *a, + const struct sockaddr *b, unsigned int len) +{ + struct sockaddr_in *sin_a, *sin_b; + struct sockaddr_in6 *sin6_a, *sin6_b; + + if (a->sa_family != b->sa_family) + return 0; + + switch (a->sa_family) { + case AF_INET: + sin_a = (struct sockaddr_in *)a; + sin_b = (struct sockaddr_in *)b; + if (!memcmp(&sin_a->sin_addr, &sin_b->sin_addr, + sizeof(struct in_addr))) + return 1; + break; + case AF_INET6: + sin6_a = (struct sockaddr_in6 *)a; + sin6_b = (struct sockaddr_in6 *)b; + if (!memcmp(&sin6_a->sin6_addr, &sin6_b->sin6_addr, + sizeof(struct in6_addr))) + return 1; + break; + } + return 0; +} + /* Find a connection for given local control connection id */ struct l2tpd_connection * l2tpd_cc_find_by_l_cc_id(struct l2tpd_instance *inst, uint32_t l_cc_id) @@ -23,13 +53,12 @@ l2tpd_cc_find_by_l_cc_id(struct l2tpd_instance *inst, uint32_t l_cc_id) return NULL; } - struct l2tpd_connection * l2tpd_cc_find_by_sockaddr(struct l2tpd_instance *inst, struct sockaddr *ss, int ss_len) { struct l2tpd_connection *l2c; llist_for_each_entry(l2c, &inst->connections, list) { - if (osmo_sockaddr_equal(ss, &l2c->remote.ss, ss_len)) + if (sockaddr_equal(ss, &l2c->remote.ss, ss_len)) return l2c; } return NULL; From 07702774ecba7407a2b464a46512b34599d99405 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Sun, 23 Oct 2016 22:42:52 +0200 Subject: [PATCH 009/133] l2tpd: fix compiler errors and misused format string --- siu/l2tp/l2tpd.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/siu/l2tp/l2tpd.c b/siu/l2tp/l2tpd.c index e0adc2d..966f1f1 100644 --- a/siu/l2tp/l2tpd.c +++ b/siu/l2tp/l2tpd.c @@ -671,12 +671,13 @@ static int l2tp_ip_read_cb(struct osmo_fd *ofd, unsigned int what) msgb_put(msg, rc); /* FIXME: resolve l2tpd_connection somewhere ? */ - l2c = l2tpd_cc_find_by_sockaddr(l2i, ss, sizeof(*ss)); + l2c = l2tpd_cc_find_by_sockaddr(l2i, &ss, sizeof(ss)); if (!l2c) { /* create a new connection */ - LOGP(DL2TP, LOGL_ERROR, "New l2tp connection: %s\n", ); + /* FIXME: add l2tp ip address */ + LOGP(DL2TP, LOGL_ERROR, "New l2tp connection.\n"); l2c = l2tpd_cc_alloc(l2i); - memcpy(l2c->remote.ss, &ss, sizeof(*ss)); + memcpy(&l2c->remote.ss, &ss, sizeof(ss)); } return l2tp_rcvmsg(l2c, msg); From d461968d7a46aad863931dba2c41d74ebdaf2c0a Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Sun, 23 Oct 2016 22:43:35 +0200 Subject: [PATCH 010/133] l2tpd_fsm: make fsm itself and states public --- siu/l2tp/l2tpd_data.c | 2 +- siu/l2tp/l2tpd_fsm.c | 25 ++----------------------- siu/l2tp/l2tpd_fsm.h | 19 +++++++++++++++++++ 3 files changed, 22 insertions(+), 24 deletions(-) diff --git a/siu/l2tp/l2tpd_data.c b/siu/l2tp/l2tpd_data.c index 3a28814..90baf79 100644 --- a/siu/l2tp/l2tpd_data.c +++ b/siu/l2tp/l2tpd_data.c @@ -73,7 +73,7 @@ l2tpd_cc_alloc(struct l2tpd_instance *inst) l2c->local.ccid = inst->next_l_cc_id++; llist_add(&l2c->list, &inst->connections); - l2c->fsm = osmo_fsm_inst_alloc(l2tp_cc_fsm, l2c, NULL, LOGL_DEBUG, NULL); + l2c->fsm = osmo_fsm_inst_alloc(&l2tp_cc_fsm, l2c, NULL, LOGL_DEBUG, NULL); return l2c; } diff --git a/siu/l2tp/l2tpd_fsm.c b/siu/l2tp/l2tpd_fsm.c index 2bca8ba..4cfda69 100644 --- a/siu/l2tp/l2tpd_fsm.c +++ b/siu/l2tp/l2tpd_fsm.c @@ -4,24 +4,6 @@ #define S(x) (1 << (x)) -enum l2tpd_ctrl_con_state { - /* Before we receive SCCRQ*/ - L2CC_S_INIT, - /* After we sent SCCRP, waiting for SCCCN */ - L2CC_S_WAIT_CTL_CONN, - /* Control Conncetion is established */ - L2CC_S_ESTABLISHED, -}; - -/* ICRQ recipient */ -enum l2tpd_in_call_state { - /* Waiting for ICRQ */ - L2IC_S_INIT, - /* Waiting for ICCN */ - L2IC_S_WAIT_CONN, - L2IC_S_ESTABLISHED, -}; - static void l2tp_ctrl_s_init(struct osmo_fsm_inst *fi, uint32_t event, void *data) { /* FIXME: Send SCCRP */ @@ -83,7 +65,7 @@ static const struct osmo_fsm_state l2tp_ctrl_states[] = { }, }; -static struct osmo_fsm l2tp_cc_fsm = { +struct osmo_fsm l2tp_cc_fsm = { .name = "L2TP-CC", .states = l2tp_ctrl_states, .num_states = ARRAY_SIZE(l2tp_ctrl_states), @@ -91,9 +73,6 @@ static struct osmo_fsm l2tp_cc_fsm = { .event_names = l2tp_cc_events, }; - - - static void l2tp_ic_s_init(struct osmo_fsm_inst *fi, uint32_t event, void *data) { /* ICRQ was received */ @@ -156,7 +135,7 @@ static const struct osmo_fsm_state l2tp_ic_states[] = { }, }; -static struct osmo_fsm l2tp_ic_fsm = { +struct osmo_fsm l2tp_ic_fsm = { .name = "L2TP-IC", .states = l2tp_ic_states, .num_states = ARRAY_SIZE(l2tp_ic_states), diff --git a/siu/l2tp/l2tpd_fsm.h b/siu/l2tp/l2tpd_fsm.h index 1c3d6d4..5af92f2 100644 --- a/siu/l2tp/l2tpd_fsm.h +++ b/siu/l2tp/l2tpd_fsm.h @@ -35,4 +35,23 @@ enum l2tpd_in_call_event { L2IC_E_LOCAL_CLOSE_REQ, }; +enum l2tpd_ctrl_con_state { + /* Before we receive SCCRQ*/ + L2CC_S_INIT, + /* After we sent SCCRP, waiting for SCCCN */ + L2CC_S_WAIT_CTL_CONN, + /* Control Conncetion is established */ + L2CC_S_ESTABLISHED, +}; +/* ICRQ recipient */ +enum l2tpd_in_call_state { + /* Waiting for ICRQ */ + L2IC_S_INIT, + /* Waiting for ICCN */ + L2IC_S_WAIT_CONN, + L2IC_S_ESTABLISHED, +}; + +extern struct osmo_fsm l2tp_ic_fsm; +extern struct osmo_fsm l2tp_cc_fsm; From 0a6dd1b1f9dbd926406964cfc7921e4e4a61c01d Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Sun, 23 Oct 2016 23:01:23 +0200 Subject: [PATCH 011/133] init logging system --- siu/l2tp/l2tpd.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/siu/l2tp/l2tpd.c b/siu/l2tp/l2tpd.c index 966f1f1..ed2c1fd 100644 --- a/siu/l2tp/l2tpd.c +++ b/siu/l2tp/l2tpd.c @@ -701,6 +701,19 @@ static int l2tpd_instance_start(struct l2tpd_instance *li) return 0; } +/* default categories */ +static struct log_info_cat l2tp_categories[] = { + [DL2TP] = { + .name = "DL2TP", + .description = "L2TP logging messages", + .enabled = 1, .loglevel = LOGL_DEBUG, + }, +}; + +static const struct log_info l2tp_log_info = { + .cat = l2tp_categories, + .num_cat = ARRAY_SIZE(l2tp_categories), +}; int main(int argc, char **argv) { @@ -713,6 +726,8 @@ int main(int argc, char **argv) if (rc < 0) exit(1); + log_init(&l2tp_log_info, NULL); + while (1) { osmo_select_main(0); } From 6cd77eb4490cfd130840e756ecc7c3e3f80788b0 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Sun, 23 Oct 2016 23:16:54 +0200 Subject: [PATCH 012/133] l2tpd: move ofd setup before osmo_sock_init_ofd() --- siu/l2tp/l2tpd.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/siu/l2tp/l2tpd.c b/siu/l2tp/l2tpd.c index ed2c1fd..40182f6 100644 --- a/siu/l2tp/l2tpd.c +++ b/siu/l2tp/l2tpd.c @@ -689,15 +689,15 @@ static int l2tpd_instance_start(struct l2tpd_instance *li) INIT_LLIST_HEAD(&li->connections); + li->l2tp_ofd.when = BSC_FD_READ; + li->l2tp_ofd.cb = l2tp_ip_read_cb; + li->l2tp_ofd.data = li; + rc = osmo_sock_init_ofd(&li->l2tp_ofd, AF_INET, SOCK_RAW, IPPROTO_L2TP, li->cfg.bind_ip, 0, 0); if (rc < 0) return rc; - li->l2tp_ofd.when = BSC_FD_READ; - li->l2tp_ofd.cb = l2tp_ip_read_cb; - li->l2tp_ofd.data = li; - return 0; } From 6339e6a03847b717edb3593ec63cc3bf3bb03af2 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Sun, 23 Oct 2016 23:17:13 +0200 Subject: [PATCH 013/133] l2tpd: init talloc and use it for l2tpd_instance l2i --- siu/l2tp/l2tpd.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/siu/l2tp/l2tpd.c b/siu/l2tp/l2tpd.c index 40182f6..9226faa 100644 --- a/siu/l2tp/l2tpd.c +++ b/siu/l2tp/l2tpd.c @@ -717,12 +717,14 @@ static const struct log_info l2tp_log_info = { int main(int argc, char **argv) { - struct l2tpd_instance li; int rc; - l2i = &li; - li.cfg.bind_ip = "0.0.0.0"; - rc = l2tpd_instance_start(&li); + void *tall_l2tp_ctx = talloc_named_const(NULL, 0, "l2tpd"); + + l2i = talloc_zero(tall_l2tp_ctx, struct l2tpd_instance); + l2i->cfg.bind_ip = "0.0.0.0"; + + rc = l2tpd_instance_start(l2i); if (rc < 0) exit(1); From 290e88eb596fd5a852827bd1cc68c4d6f2d7c56c Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Sun, 23 Oct 2016 23:19:03 +0200 Subject: [PATCH 014/133] l2tpd/Makefile: add EXTRA_CFLAGS --- siu/l2tp/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/siu/l2tp/Makefile b/siu/l2tp/Makefile index 9b869be..7c6a51a 100644 --- a/siu/l2tp/Makefile +++ b/siu/l2tp/Makefile @@ -4,6 +4,8 @@ PREFIX ?= /usr/local CFLAGS := -I $(PREFIX)/include/ -Wno-unused-function -Wall LDFLAGS := -L $(PREFIX)/lib -lcrypto -losmocore -losmogsm -ltalloc +CFLAGS += $(EXTRA_CFLAGS) + all: l2tpd l2tpd: l2tpd.o l2tpd_fsm.o l2tpd_data.o From 43d10dd7ddcfd4c5c9a7a8be65633195945b66c9 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Sun, 23 Oct 2016 23:29:57 +0200 Subject: [PATCH 015/133] l2tpd: add logging to stderr --- siu/l2tp/l2tpd.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/siu/l2tp/l2tpd.c b/siu/l2tp/l2tpd.c index 9226faa..bcd10d7 100644 --- a/siu/l2tp/l2tpd.c +++ b/siu/l2tp/l2tpd.c @@ -718,7 +718,7 @@ static const struct log_info l2tp_log_info = { int main(int argc, char **argv) { int rc; - + struct log_target *stderr_target; void *tall_l2tp_ctx = talloc_named_const(NULL, 0, "l2tpd"); l2i = talloc_zero(tall_l2tp_ctx, struct l2tpd_instance); @@ -729,6 +729,10 @@ int main(int argc, char **argv) exit(1); log_init(&l2tp_log_info, NULL); + stderr_target = log_target_create_stderr(); + log_add_target(stderr_target); + log_set_print_filename(stderr_target, 0); + while (1) { osmo_select_main(0); From 8cb31473ba62c77b04102aab67f48395c3a05c32 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Sun, 23 Oct 2016 23:30:19 +0200 Subject: [PATCH 016/133] l2tpd: register fsms --- siu/l2tp/l2tpd.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/siu/l2tp/l2tpd.c b/siu/l2tp/l2tpd.c index bcd10d7..4086673 100644 --- a/siu/l2tp/l2tpd.c +++ b/siu/l2tp/l2tpd.c @@ -721,6 +721,10 @@ int main(int argc, char **argv) struct log_target *stderr_target; void *tall_l2tp_ctx = talloc_named_const(NULL, 0, "l2tpd"); + /* register fsms */ + osmo_fsm_register(&l2tp_cc_fsm); + osmo_fsm_register(&l2tp_ic_fsm); + l2i = talloc_zero(tall_l2tp_ctx, struct l2tpd_instance); l2i->cfg.bind_ip = "0.0.0.0"; From a349490d0c72d50df9bc2c29bd9c0183e19f4fdf Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Sun, 23 Oct 2016 23:30:55 +0200 Subject: [PATCH 017/133] l2tpd_data: rename variable `l2tpd_instance inst -> l2tp` to conform to the rest of the source --- siu/l2tp/l2tpd_data.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/siu/l2tp/l2tpd_data.c b/siu/l2tp/l2tpd_data.c index 90baf79..fb92cbd 100644 --- a/siu/l2tp/l2tpd_data.c +++ b/siu/l2tp/l2tpd_data.c @@ -65,14 +65,14 @@ l2tpd_cc_find_by_sockaddr(struct l2tpd_instance *inst, struct sockaddr *ss, int } struct l2tpd_connection * -l2tpd_cc_alloc(struct l2tpd_instance *inst) +l2tpd_cc_alloc(struct l2tpd_instance *l2i) { - struct l2tpd_connection *l2c = talloc_zero(inst, struct l2tpd_connection); + struct l2tpd_connection *l2c = talloc_zero(l2i, struct l2tpd_connection); INIT_LLIST_HEAD(&l2c->sessions); - l2c->local.ccid = inst->next_l_cc_id++; + l2c->local.ccid = l2i->next_l_cc_id++; - llist_add(&l2c->list, &inst->connections); + llist_add(&l2c->list, &l2i->connections); l2c->fsm = osmo_fsm_inst_alloc(&l2tp_cc_fsm, l2c, NULL, LOGL_DEBUG, NULL); return l2c; From 76dc1edfe6f526ad4d91a422c14de7aabca92be5 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Mon, 24 Oct 2016 00:20:24 +0200 Subject: [PATCH 018/133] l2tpd: correct value of S_BIT (sequence bit) --- siu/l2tp/l2tp_protocol.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/siu/l2tp/l2tp_protocol.h b/siu/l2tp/l2tp_protocol.h index 98f6261..d0c900a 100644 --- a/siu/l2tp/l2tp_protocol.h +++ b/siu/l2tp/l2tp_protocol.h @@ -14,7 +14,7 @@ struct l2tp_control_hdr { #define T_BIT 0x8000 #define L_BIT 0x4000 -#define S_BIT 0x1000 +#define S_BIT 0x0800 #define Z_BITS 0x37F8 /* Reserved bits: We must drop anything with these there */ From 62bd1d631cfec8355724a02312ccb148dc4d1a5b Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Mon, 24 Oct 2016 00:20:40 +0200 Subject: [PATCH 019/133] l2tpd: increase tailroom to 1500 --- siu/l2tp/l2tpd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/siu/l2tp/l2tpd.c b/siu/l2tp/l2tpd.c index 4086673..4883610 100644 --- a/siu/l2tp/l2tpd.c +++ b/siu/l2tp/l2tpd.c @@ -208,7 +208,7 @@ static void l2tp_hdr_swap(struct l2tp_control_hdr *ch) static struct msgb *l2tp_msgb_alloc(void) { - return msgb_alloc_headroom(1500, 100, "L2TP"); + return msgb_alloc_headroom(1600, 100, "L2TP"); } static int msgb_avp_put_digest(struct msgb *msg) From 73cff03662a961a5bd29138d7763bceb16768bc7 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Mon, 24 Oct 2016 00:47:44 +0200 Subject: [PATCH 020/133] l2tpd: use l2tp_rcvmsg_control() must use msgb_data instead of msgb_l2tph --- siu/l2tp/l2tpd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/siu/l2tp/l2tpd.c b/siu/l2tp/l2tpd.c index 4883610..1e1d5b1 100644 --- a/siu/l2tp/l2tpd.c +++ b/siu/l2tp/l2tpd.c @@ -574,7 +574,7 @@ static int l2tp_rcvmsg_control_ericsson(struct msgb *msg, struct avps_parsed *ap static int l2tp_rcvmsg_control(struct msgb *msg) { - struct l2tp_control_hdr *ch = msgb_l2tph(msg); + struct l2tp_control_hdr *ch = (struct l2tp_control_hdr *) msgb_data(msg); struct avps_parsed ap; struct avp_parsed *first_avp; uint16_t msg_type; From 325c8858fcf461deb4ecf3222d7b60ef86766a81 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Mon, 24 Oct 2016 00:48:32 +0200 Subject: [PATCH 021/133] l2tpd/msgb_avp_parse: fix pointer arithmethic and length checks --- siu/l2tp/l2tpd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/siu/l2tp/l2tpd.c b/siu/l2tp/l2tpd.c index 1e1d5b1..fc6c8b2 100644 --- a/siu/l2tp/l2tpd.c +++ b/siu/l2tp/l2tpd.c @@ -40,7 +40,7 @@ struct l2tpd_instance *l2i; static int msgb_avp_parse(struct avp_parsed *ap, struct msgb *msg, int offset) { uint32_t msgb_left = msgb_length(msg) - offset; - struct l2tp_avp_hdr *ah = (struct l2tp_avp_hdr *) msg->data + offset; + struct l2tp_avp_hdr *ah = (struct l2tp_avp_hdr *) (msgb_data(msg) + offset); uint16_t avp_len; if (sizeof(*ah) > msgb_left) { @@ -52,7 +52,7 @@ static int msgb_avp_parse(struct avp_parsed *ap, struct msgb *msg, int offset) LOGP(DL2TP, LOGL_NOTICE, "AVP Parse: AVP len < 6\n"); return -1; } - if (sizeof(*ah) + avp_len > msgb_left) { + if (avp_len > msgb_left) { LOGP(DL2TP, LOGL_NOTICE, "AVP Data beyond end of msgb\n"); return -1; } From ffca1f240b58886f9f3249254aeb1d25bd3930c7 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Mon, 24 Oct 2016 00:49:29 +0200 Subject: [PATCH 022/133] l2tpd/rx_scc_rq: fix pseudowire cap check by using htons() --- siu/l2tp/l2tpd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/siu/l2tp/l2tpd.c b/siu/l2tp/l2tpd.c index fc6c8b2..090f67a 100644 --- a/siu/l2tp/l2tpd.c +++ b/siu/l2tp/l2tpd.c @@ -395,7 +395,7 @@ static int rx_scc_rq(struct msgb *msg, struct avps_parsed *ap) /* Abort if Pseudowire capability doesn't include 6(HDLC) */ if (avpp_val_u16(ap, VENDOR_IETF, AVP_IETF_PW_CAP_LIST, &pw) < 0 || - pw != 0x0006) { + pw != htons(0x0006)) { LOGP(DL2TP, LOGL_ERROR, "Pseudowire != HDLC\n"); return -1; } From 36f2a7f1dd223db6e985cc5a93529aa9f260fb1e Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Mon, 24 Oct 2016 00:50:09 +0200 Subject: [PATCH 023/133] l2tpd/l2tp_ip_read_cb: use msgb_data for recvfrom and set msgb pointer to l2h=l2tp, l1h=ip --- siu/l2tp/l2tpd.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/siu/l2tp/l2tpd.c b/siu/l2tp/l2tpd.c index 090f67a..9c563eb 100644 --- a/siu/l2tp/l2tpd.c +++ b/siu/l2tp/l2tpd.c @@ -663,12 +663,16 @@ static int l2tp_ip_read_cb(struct osmo_fd *ofd, unsigned int what) int rc; /* actually read the message from the raw IP socket */ - msg->l2h = msg->data; - rc = recvfrom(ofd->fd, msgb_l2tph(msg), msgb_l2tplen(msg), 0, + rc = recvfrom(ofd->fd, msg->data, msg->data_len, 0, (struct sockaddr *) &ss, &ss_len); if (rc < 0) return rc; msgb_put(msg, rc); + msg->l1h = msg->data; /* l1h = ip header */ + + msgb_pull(msg, 20); /* IPv4 header. FIXME: Should depend on the family */ + msg->l2h = msg->data; + /* FIXME: resolve l2tpd_connection somewhere ? */ l2c = l2tpd_cc_find_by_sockaddr(l2i, &ss, sizeof(ss)); From f1d399b7177cb463270ac512939e482f7581bbda Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Mon, 24 Oct 2016 04:08:11 +0200 Subject: [PATCH 024/133] l2tpd: add transmit / sendto function --- siu/l2tp/l2tpd.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/siu/l2tp/l2tpd.c b/siu/l2tp/l2tpd.c index 9c563eb..354c376 100644 --- a/siu/l2tp/l2tpd.c +++ b/siu/l2tp/l2tpd.c @@ -267,6 +267,7 @@ static int l2tp_msgb_tx(struct msgb *msg) { struct l2tpd_connection *l2c = msg->dst; struct l2tp_control_hdr *l2h; + int ret; /* first prepend the L2TP control header */ l2h = (struct l2tp_control_hdr *) msgb_push(msg, sizeof(*l2h)); @@ -280,8 +281,8 @@ static int l2tp_msgb_tx(struct msgb *msg) /* FIXME: put in the queue for reliable re-transmission */ - /* FIXME: actually transmit it */ - return 0; + ret = sendto(l2i->l2tp_ofd.fd, msgb_l2tph(msg), msgb_l2tplen(msg), 0, &l2c->remote.ss, sizeof(l2c->remote.ss)); + return ret; } /*********************************************************************** From 0feedc3623e8ab4fdbc0be55fada92593c291d78 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Mon, 24 Oct 2016 04:08:30 +0200 Subject: [PATCH 025/133] l2tpd_data: add l2c as private data to fsm --- siu/l2tp/l2tpd_data.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/siu/l2tp/l2tpd_data.c b/siu/l2tp/l2tpd_data.c index fb92cbd..5ea39a2 100644 --- a/siu/l2tp/l2tpd_data.c +++ b/siu/l2tp/l2tpd_data.c @@ -73,7 +73,7 @@ l2tpd_cc_alloc(struct l2tpd_instance *l2i) l2c->local.ccid = l2i->next_l_cc_id++; llist_add(&l2c->list, &l2i->connections); - l2c->fsm = osmo_fsm_inst_alloc(&l2tp_cc_fsm, l2c, NULL, LOGL_DEBUG, NULL); + l2c->fsm = osmo_fsm_inst_alloc(&l2tp_cc_fsm, l2c, l2c, LOGL_DEBUG, NULL); return l2c; } From d67d2a6eaf2b5252acd1e07a4182e4db1a041c06 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Mon, 24 Oct 2016 04:10:00 +0200 Subject: [PATCH 026/133] l2tpd/rx_scc_rq: use msgb_data to get the correct data --- siu/l2tp/l2tpd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/siu/l2tp/l2tpd.c b/siu/l2tp/l2tpd.c index 354c376..d711174 100644 --- a/siu/l2tp/l2tpd.c +++ b/siu/l2tp/l2tpd.c @@ -389,7 +389,7 @@ static int tx_hello(struct l2tpd_session *ls) /* Incoming "Start Control-Connection Request" from SIU */ static int rx_scc_rq(struct msgb *msg, struct avps_parsed *ap) { - struct l2tp_control_hdr *ch = msgb_l2tph(msg); + struct l2tp_control_hdr *ch = (struct l2tp_control_hdr *) msgb_data(msg); struct l2tpd_connection *l2cc; char *host_name = NULL; uint16_t pw; From a569b04d5cf3857c145f722bcf3ef3cd4248bc3e Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Mon, 24 Oct 2016 04:14:20 +0200 Subject: [PATCH 027/133] l2tpd: save sockaddr over msg->dst into l2c->remote.ss --- siu/l2tp/l2tpd.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/siu/l2tp/l2tpd.c b/siu/l2tp/l2tpd.c index d711174..3ba9071 100644 --- a/siu/l2tp/l2tpd.c +++ b/siu/l2tp/l2tpd.c @@ -391,6 +391,7 @@ static int rx_scc_rq(struct msgb *msg, struct avps_parsed *ap) { struct l2tp_control_hdr *ch = (struct l2tp_control_hdr *) msgb_data(msg); struct l2tpd_connection *l2cc; + struct sockaddr *sockaddr = msg->dst; char *host_name = NULL; uint16_t pw; @@ -416,8 +417,11 @@ static int rx_scc_rq(struct msgb *msg, struct avps_parsed *ap) host_name = (char *) avpp_val(ap, VENDOR_IETF, AVP_IETF_HOST_NAME); if (host_name) l2cc->remote.host_name = talloc_strdup(l2cc, host_name); + memcpy(&l2cc->remote.ss, sockaddr, sizeof(*sockaddr)); + } else { + LOGP(DL2TP, LOGL_ERROR, "Received a SCCRQ with control id != 0: %d\n", ch->ccid); + return -1; } - /* FIXME: start fsm first! */ osmo_fsm_inst_dispatch(l2cc->fsm, L2CC_E_RX_SCCRQ, msg); return 0; @@ -673,6 +677,7 @@ static int l2tp_ip_read_cb(struct osmo_fd *ofd, unsigned int what) msgb_pull(msg, 20); /* IPv4 header. FIXME: Should depend on the family */ msg->l2h = msg->data; + msg->dst = &ss; /* FIXME: resolve l2tpd_connection somewhere ? */ From 3df97f21116a4332bac98d54231555d9d6cc2458 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Mon, 24 Oct 2016 04:14:51 +0200 Subject: [PATCH 028/133] l2tpd: dont lookup l2tp_rcvmsg over ip --- siu/l2tp/l2tpd.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/siu/l2tp/l2tpd.c b/siu/l2tp/l2tpd.c index 3ba9071..90c799d 100644 --- a/siu/l2tp/l2tpd.c +++ b/siu/l2tp/l2tpd.c @@ -662,7 +662,6 @@ int l2tp_rcvmsg(struct l2tpd_connection *conn, struct msgb *msg) static int l2tp_ip_read_cb(struct osmo_fd *ofd, unsigned int what) { struct msgb *msg = l2tp_msgb_alloc(); - struct l2tpd_connection *l2c; struct sockaddr ss; socklen_t ss_len = sizeof(ss); int rc; @@ -679,18 +678,7 @@ static int l2tp_ip_read_cb(struct osmo_fd *ofd, unsigned int what) msg->l2h = msg->data; msg->dst = &ss; - - /* FIXME: resolve l2tpd_connection somewhere ? */ - l2c = l2tpd_cc_find_by_sockaddr(l2i, &ss, sizeof(ss)); - if (!l2c) { - /* create a new connection */ - /* FIXME: add l2tp ip address */ - LOGP(DL2TP, LOGL_ERROR, "New l2tp connection.\n"); - l2c = l2tpd_cc_alloc(l2i); - memcpy(&l2c->remote.ss, &ss, sizeof(ss)); - } - - return l2tp_rcvmsg(l2c, msg); + return l2tp_rcvmsg(msg); } static int l2tpd_instance_start(struct l2tpd_instance *li) From 0eb0b71530a882f5f4729cf479c461199addb68e Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Mon, 24 Oct 2016 04:14:51 +0200 Subject: [PATCH 029/133] l2tpd: fixup dont lookup l2tp_rcvmsg over ip forgotten function signature --- siu/l2tp/l2tpd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/siu/l2tp/l2tpd.c b/siu/l2tp/l2tpd.c index 90c799d..3c9ef94 100644 --- a/siu/l2tp/l2tpd.c +++ b/siu/l2tp/l2tpd.c @@ -648,7 +648,7 @@ static int l2tp_rcvmsg_data(struct msgb *msg, bool ip_transport) return 0; } -int l2tp_rcvmsg(struct l2tpd_connection *conn, struct msgb *msg) +int l2tp_rcvmsg(struct msgb *msg) { uint32_t session = osmo_load32be(msgb_l2tph(msg)); if (session == 0) { From dd028bfbd3145e0b3a80f23b77f20840d9c4faaf Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Mon, 24 Oct 2016 05:14:56 +0200 Subject: [PATCH 030/133] l2tpd.c: move packet handling out of l2tpd.c into l2tpd_packet.c --- siu/l2tp/Makefile | 2 +- siu/l2tp/l2tpd.c | 638 +------------------------------------- siu/l2tp/l2tpd.h | 2 + siu/l2tp/l2tpd_packet.c | 657 ++++++++++++++++++++++++++++++++++++++++ siu/l2tp/l2tpd_packet.h | 7 + 5 files changed, 668 insertions(+), 638 deletions(-) create mode 100644 siu/l2tp/l2tpd_packet.c create mode 100644 siu/l2tp/l2tpd_packet.h diff --git a/siu/l2tp/Makefile b/siu/l2tp/Makefile index 7c6a51a..d035a62 100644 --- a/siu/l2tp/Makefile +++ b/siu/l2tp/Makefile @@ -8,7 +8,7 @@ CFLAGS += $(EXTRA_CFLAGS) all: l2tpd -l2tpd: l2tpd.o l2tpd_fsm.o l2tpd_data.o +l2tpd: l2tpd.o l2tpd_fsm.o l2tpd_data.o l2tpd_packet.o $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) %.o: %.c diff --git a/siu/l2tp/l2tpd.c b/siu/l2tp/l2tpd.c index 3c9ef94..ba1d42f 100644 --- a/siu/l2tp/l2tpd.c +++ b/siu/l2tp/l2tpd.c @@ -18,647 +18,11 @@ #include "l2tpd.h" #include "l2tpd_data.h" #include "l2tpd_fsm.h" - -/*********************************************************************** - * AVP Parser / Encoder - ***********************************************************************/ - -/* a parsed representation of an L2TP AVP */ -struct avp_parsed { - uint16_t vendor_id; - uint16_t type; - uint16_t data_len; - uint8_t m:1, - h:1; - uint8_t *data; -}; +#include "l2tpd_packet.h" struct l2tpd_instance *l2i; /* FIXME: global static instance */ -/* parse single AVP at msg->data + offset and return the new offset */ -static int msgb_avp_parse(struct avp_parsed *ap, struct msgb *msg, int offset) -{ - uint32_t msgb_left = msgb_length(msg) - offset; - struct l2tp_avp_hdr *ah = (struct l2tp_avp_hdr *) (msgb_data(msg) + offset); - uint16_t avp_len; - - if (sizeof(*ah) > msgb_left) { - LOGP(DL2TP, LOGL_NOTICE, "AVP Hdr beyond end of msgb\n"); - return -1; - } - avp_len = ntohs(ah->m_h_length) & 0x3ff; - if (avp_len < 6) { - LOGP(DL2TP, LOGL_NOTICE, "AVP Parse: AVP len < 6\n"); - return -1; - } - if (avp_len > msgb_left) { - LOGP(DL2TP, LOGL_NOTICE, "AVP Data beyond end of msgb\n"); - return -1; - } - - ap->vendor_id = ntohs(ah->vendor_id); - ap->type = ntohs(ah->attr_type); - ap->data_len = avp_len - sizeof(*ah); - ap->data = ah->value; - ap->m = !!(ah->m_h_length & 0x8000); - ap->h = !!(ah->m_h_length & 0x4000); - - return offset + avp_len; -} - -struct avps_parsed { - unsigned int num_avp; - struct avp_parsed avp[64]; -}; - -static int msgb_avps_parse(struct avps_parsed *avps, struct msgb *msg, int offset) -{ - memset(avps, 0, sizeof(*avps)); - - while (msgb_length(msg) - offset > 0) { - struct avp_parsed *avp = &avps->avp[avps->num_avp++]; - int rc = msgb_avp_parse(avp, msg, offset); - if (rc < 0) - return rc; - else - offset = rc; - } - return avps->num_avp; -} - -static struct avp_parsed * -avps_parsed_find(struct avps_parsed *avps, uint16_t vendor_id, uint16_t type) -{ - unsigned int i; - - for (i = 0; i < avps->num_avp; i++) { - struct avp_parsed *avp = &avps->avp[i]; - if (avp->vendor_id == vendor_id && avp->type == type) - return avp; - } - return NULL; -} - -static uint8_t *avpp_val(struct avps_parsed *avps, uint16_t vendor_id, uint16_t type) -{ - struct avp_parsed *avp = avps_parsed_find(avps, vendor_id, type); - if (!avp) - return NULL; - return avp->data; -} - -static int avpp_len(struct avps_parsed *avps, uint16_t vendor_id, uint16_t type) -{ - struct avp_parsed *avp = avps_parsed_find(avps, vendor_id, type); - if (!avp) - return 0; - return avp->data_len; -} - -int avpp_val_u32(struct avps_parsed *avps, uint16_t vendor_id, uint16_t type, - uint32_t *u32) -{ - struct avp_parsed *avp = avps_parsed_find(avps, vendor_id, type); - if (!avp) - return -ENODEV; - if (avp->data_len < sizeof(*u32)) - return -EINVAL; - - *u32 = *((uint32_t *)avp->data); - return 0; -} - -int avpp_val_u16(struct avps_parsed *avps, uint16_t vendor_id, uint16_t type, - uint16_t *u16) -{ - struct avp_parsed *avp = avps_parsed_find(avps, vendor_id, type); - if (!avp) - return -ENODEV; - if (avp->data_len < sizeof(*u16)) - return -EINVAL; - - *u16 = *((uint16_t *)avp->data); - return 0; -} - -/* store an AVP at the end of the msg */ -static int msgb_avp_put(struct msgb *msg, uint16_t vendor_id, uint16_t type, - const uint8_t *data, uint16_t data_len, bool m_flag) -{ - uint8_t *out; - - if (data_len > 0x3ff - 6) { - LOGP(DL2TP, LOGL_ERROR, "Data too long for AVP\n"); - return -1; - } - - msgb_put_u16(msg, ((data_len + 6) & 0x3ff) | (m_flag ? 0x8000 : 0)); - msgb_put_u16(msg, vendor_id); - msgb_put_u16(msg, type); - out = msgb_put(msg, data_len); - memcpy(out, data, data_len); - - return 6 + data_len; -} - -/* store an uint8_t value AVP */ -static int msgb_avp_put_u8(struct msgb *msg, uint16_t vendor, uint16_t avp_type, - uint8_t val, bool m_flag) -{ - return msgb_avp_put(msg, vendor, avp_type, &val, 1, m_flag); -} - -/* store an uint16_t value AVP */ -static int msgb_avp_put_u16(struct msgb *msg, uint16_t vendor, uint16_t avp_type, - uint16_t val, bool m_flag) -{ - val = htons(val); - return msgb_avp_put(msg, vendor, avp_type, (uint8_t *)&val, 2, m_flag); -} - -/* store an uint32_t value AVP */ -static int msgb_avp_put_u32(struct msgb *msg, uint16_t vendor, uint16_t avp_type, - uint32_t val, bool m_flag) -{ - val = htonl(val); - return msgb_avp_put(msg, vendor, avp_type, (uint8_t *)&val, 4, m_flag); -} - -/* store a 'message type' AVP */ -static int msgb_avp_put_msgt(struct msgb *msg, uint16_t vendor, uint16_t msg_type) -{ - return msgb_avp_put_u16(msg, vendor, AVP_IETF_CTRL_MSG, msg_type, true); -} - - -/*********************************************************************** - * Message utilities - ***********************************************************************/ - -/* swap all fields of the l2tp_control header structure */ -static void l2tp_hdr_swap(struct l2tp_control_hdr *ch) -{ - ch->ver = ntohs(ch->ver); - ch->length = ntohs(ch->length); - ch->ccid = ntohl(ch->ccid); - ch->Ns = ntohs(ch->Ns); - ch->Nr = ntohs(ch->Nr); -} - -static struct msgb *l2tp_msgb_alloc(void) -{ - return msgb_alloc_headroom(1600, 100, "L2TP"); -} - -static int msgb_avp_put_digest(struct msgb *msg) -{ - /* we simply put a zero-initialized AVP for now and update when - * trnasmitting */ - const uint8_t digest_zero[17] = { 0, }; - return msgb_avp_put(msg, VENDOR_IETF, AVP_IETF_MSG_DIGEST, - digest_zero, sizeof(digest_zero), true); -} - -/* E/// L2TP seems to use a static, constant HMAC key */ -static const uint8_t digest_key[] = { - 0x7b, 0x60, 0x85, 0xfb, 0xf4, 0x59, 0x33, 0x67, - 0x0a, 0xbc, 0xb0, 0x7a, 0x27, 0xfc, 0xea, 0x5e -}; - -/* update the message digest inside the AVP of a message */ -static int digest_avp_update(struct msgb *msg) -{ - struct l2tp_control_hdr *l2h = msgb_l2tph(msg); - struct l2tp_avp_hdr *ah = (struct l2tp_avp_hdr *) ((uint8_t *)l2h + sizeof(*l2h)); - uint8_t *hmac_res; - unsigned int len = ntohs(l2h->length); - - /* Digest AVP header is guaranteed to be the second AVP in a - * control message. First AVP is message type AVP with overall - * length of 8 bytes */ - - if (ntohs(ah->attr_type) != AVP_IETF_MSG_DIGEST || - ntohs(ah->vendor_id) != VENDOR_IETF || - (ntohs(ah->m_h_length) & 0x3FF) != 17) { - LOGP(DL2TP, LOGL_ERROR, "Missing Digest AVP, cannot update\n"); - return -1; - } - - if (len > msgb_l2tplen(msg)) { - /* FIXME: improve log message */ - LOGP(DL2TP, LOGL_ERROR, "invalid length"); - return -1; - } - - DEBUGP(DL2TP, "Tx Message before digest: %s\n", msgb_hexdump(msg)); - /* RFC says HMAC_Hash(shared_key, local_nonce + remote_nonce + control_message), - * but ericsson is doning something different without any - * local/remote nonce? */ - hmac_res = HMAC(EVP_md5(), digest_key, sizeof(digest_key), - (const uint8_t *)l2h, len, NULL, NULL); - memcpy(ah->value, hmac_res, 16); - DEBUGP(DL2TP, "Tx Message with digest: %s\n", msgb_hexdump(msg)); - - return 0; -} - -static int l2tp_msgb_tx(struct msgb *msg) -{ - struct l2tpd_connection *l2c = msg->dst; - struct l2tp_control_hdr *l2h; - int ret; - - /* first prepend the L2TP control header */ - l2h = (struct l2tp_control_hdr *) msgb_push(msg, sizeof(*l2h)); - l2h->ver = htons(T_BIT|L_BIT|S_BIT| msgb_l2tplen(msg)); - l2h->ccid = htonl(l2c->remote.ccid); - l2h->Ns = htons(l2c->next_tx_seq_nr++); - l2h->Nr = htons(l2c->next_rx_seq_nr); - - /* then insert/patch the message digest AVP */ - digest_avp_update(msg); - - /* FIXME: put in the queue for reliable re-transmission */ - - ret = sendto(l2i->l2tp_ofd.fd, msgb_l2tph(msg), msgb_l2tplen(msg), 0, &l2c->remote.ss, sizeof(l2c->remote.ss)); - return ret; -} - -/*********************************************************************** - * IETF specified messages - ***********************************************************************/ - -static int tx_scc_rp(struct l2tpd_connection *lc) -{ - struct msgb *msg = l2tp_msgb_alloc(); - const uint8_t eric_ver3_only[12] = { 0,0,0,3, 0,0,0,0, 0,0,0,0 }; - const uint8_t host_name[3] = { 'B', 'S', 'C' }; - const uint32_t router_id = 0x2342; - - msgb_avp_put_msgt(msg, VENDOR_IETF, IETF_CTRLMSG_SCCRP); - msgb_avp_put_digest(msg); - msgb_avp_put_u32(msg, VENDOR_IETF, AVP_IETF_AS_CTRL_CON_ID, - lc->remote.ccid, true); - msgb_avp_put(msg, VENDOR_ERICSSON, AVP_ERIC_PROTO_VER, - eric_ver3_only, sizeof(eric_ver3_only), true); - msgb_avp_put(msg, VENDOR_IETF, AVP_IETF_HOST_NAME, - host_name, sizeof(host_name), false); - msgb_avp_put_u32(msg, VENDOR_IETF, AVP_IETF_ROUTER_ID, - router_id, false); - msgb_avp_put_u16(msg, VENDOR_IETF, AVP_IETF_PW_CAP_LIST, - 0x0006, true); - - return l2tp_msgb_tx(msg); -} - -static int tx_tc_rq(struct l2tpd_session *ls) -{ - struct msgb *msg = l2tp_msgb_alloc(); - const uint8_t tcg[] = { 0x00, 0x19, 0x01, 0x1f, 0x05, - 0, 10, 11, 12, 62, /* SAPIs */ - 10, 251, 134, 1, /* IP */ - 0x00, 0x01, 0x05, 0x05, 0xb9 }; - - msgb_avp_put_msgt(msg, VENDOR_ERICSSON, ERIC_CTRLMSG_TCRQ); - msgb_avp_put_digest(msg); - msgb_avp_put(msg, VENDOR_ERICSSON, AVP_ERIC_TRANSP_CFG, - tcg, sizeof(tcg), true); - - return l2tp_msgb_tx(msg); -} - -static int tx_altc_rq(struct l2tpd_session *ls) -{ - struct msgb *msg = l2tp_msgb_alloc(); - const uint8_t tcsc[] = { 2, - 0, 0, 0, - 62, 62, 0 }; - - msgb_avp_put_msgt(msg, VENDOR_ERICSSON, ERIC_CTRLMSG_ALTCRQ); - msgb_avp_put_digest(msg); - msgb_avp_put(msg, VENDOR_ERICSSON, AVP_ERIC_TEI_TO_SC_MAP, - tcsc, sizeof(tcsc), true); - - return l2tp_msgb_tx(msg); -} - -static int tx_ic_rp(struct l2tpd_session *ls) -{ - struct msgb *msg = l2tp_msgb_alloc(); - - msgb_avp_put_msgt(msg, VENDOR_IETF, IETF_CTRLMSG_ICRP); - msgb_avp_put_digest(msg); - msgb_avp_put_u32(msg, VENDOR_IETF, AVP_IETF_LOC_SESS_ID, - ls->l_sess_id, true); - msgb_avp_put_u32(msg, VENDOR_IETF, AVP_IETF_REM_SESS_ID, - ls->r_sess_id, true); - /* Circuit type: existing; Circuit status: up */ - msgb_avp_put_u16(msg, VENDOR_IETF, AVP_IETF_CIRC_STATUS, - 0x0001, true); - /* Default L2 specific sublayer present */ - msgb_avp_put_u16(msg, VENDOR_IETF, AVP_IETF_L2_SPEC_SUBL, - 0x0001, true); - /* All incoming data packets require sequencing */ - msgb_avp_put_u16(msg, VENDOR_IETF, AVP_IETF_DATA_SEQUENCING, - 0x0002, true); - - return l2tp_msgb_tx(msg); -} - -static int tx_ack(struct l2tpd_session *ls) -{ - struct msgb *msg = l2tp_msgb_alloc(); - - msgb_avp_put_msgt(msg, VENDOR_IETF, IETF_CTRLMSG_ACK); - msgb_avp_put_digest(msg); - - return l2tp_msgb_tx(msg); -} - -static int tx_hello(struct l2tpd_session *ls) -{ - struct msgb *msg = l2tp_msgb_alloc(); - - msgb_avp_put_msgt(msg, VENDOR_IETF, IETF_CTRLMSG_HELLO); - msgb_avp_put_digest(msg); - - return l2tp_msgb_tx(msg); -} - -/* Incoming "Start Control-Connection Request" from SIU */ -static int rx_scc_rq(struct msgb *msg, struct avps_parsed *ap) -{ - struct l2tp_control_hdr *ch = (struct l2tp_control_hdr *) msgb_data(msg); - struct l2tpd_connection *l2cc; - struct sockaddr *sockaddr = msg->dst; - char *host_name = NULL; - uint16_t pw; - - /* Abort if Pseudowire capability doesn't include 6(HDLC) */ - if (avpp_val_u16(ap, VENDOR_IETF, AVP_IETF_PW_CAP_LIST, &pw) < 0 || - pw != htons(0x0006)) { - LOGP(DL2TP, LOGL_ERROR, "Pseudowire != HDLC\n"); - return -1; - } - - if (ch->ccid == 0) { - uint32_t remote_ccid, router_id; - l2cc = l2tpd_cc_alloc(l2i); - /* Get Assigned CCID and store in l2cc->remote.ccid */ - avpp_val_u32(ap, VENDOR_IETF, AVP_IETF_AS_CTRL_CON_ID, - &remote_ccid); - l2cc->remote.ccid = remote_ccid; - /* Router ID AVP */ - if (avpp_val_u32(ap, VENDOR_IETF, AVP_IETF_ROUTER_ID, - &router_id)) - l2cc->remote.router_id = router_id; - /* Host Name AVP */ - host_name = (char *) avpp_val(ap, VENDOR_IETF, AVP_IETF_HOST_NAME); - if (host_name) - l2cc->remote.host_name = talloc_strdup(l2cc, host_name); - memcpy(&l2cc->remote.ss, sockaddr, sizeof(*sockaddr)); - } else { - LOGP(DL2TP, LOGL_ERROR, "Received a SCCRQ with control id != 0: %d\n", ch->ccid); - return -1; - } - - osmo_fsm_inst_dispatch(l2cc->fsm, L2CC_E_RX_SCCRQ, msg); - return 0; -} - -/* Incoming "Start Control-Connection Connected" from SIU */ -static int rx_scc_cn(struct msgb *msg, struct avps_parsed *ap) -{ - struct l2tp_control_hdr *ch = msgb_l2tph(msg); - struct l2tpd_connection *l2cc = l2tpd_cc_find_by_l_cc_id(l2i, ch->ccid); - - if (!l2cc) - return -1; - - osmo_fsm_inst_dispatch(l2cc->fsm, L2CC_E_RX_SCCCN, msg); - /* FIXME: Send TCRQ and ALTCRQ */ - return 0; -} - -/* Incoming "Stop Control-Connection Notificiation" from SIU */ -static int rx_stop_ccn(struct msgb *msg, struct avps_parsed *ap) -{ - struct l2tp_control_hdr *ch = msgb_l2tph(msg); - struct l2tpd_connection *l2cc = l2tpd_cc_find_by_l_cc_id(l2i, ch->ccid); - - if (!l2cc) - return -1; - - osmo_fsm_inst_dispatch(l2cc->fsm, L2CC_E_RX_STOP_CCN, msg); - return 0; -} - -/* Incoming "Incoming Call Request" from SIU */ -static int rx_ic_rq(struct msgb *msg, struct avps_parsed *ap) -{ - struct l2tp_control_hdr *ch = msgb_l2tph(msg); - struct l2tpd_connection *l2cc = l2tpd_cc_find_by_l_cc_id(l2i, ch->ccid); - struct l2tpd_session *l2s; - uint32_t r_sess_id = 0; - uint32_t l_sess_id = 0; - - if (!l2cc) - return -1; - if (avpp_val_u32(ap, VENDOR_IETF, AVP_IETF_REM_SESS_ID, &r_sess_id)) - return -1; - if (avpp_val_u32(ap, VENDOR_IETF, AVP_IETF_LOC_SESS_ID, &l_sess_id)) - return -1; - - if (r_sess_id == 0) { - l2s = l2tpd_sess_alloc(l2cc); - l2s->r_sess_id = l_sess_id; - avpp_val_u16(ap, VENDOR_IETF, AVP_IETF_PW_TYPE, &l2s->pw_type); - } else { - l2s = l2tpd_sess_find_by_l_s_id(l2cc, r_sess_id); - if (!l2s) { - LOGP(DL2TP, LOGL_ERROR, "NoSession %u\n", - r_sess_id); - return -1; - } - } - - osmo_fsm_inst_dispatch(l2cc->fsm, L2IC_E_RX_ICRQ, msg); - return 0; -} - -/* Incoming "Incoming Call Connected" from SIU */ -static int rx_ic_cn(struct msgb *msg, struct avps_parsed *ap) -{ - struct l2tp_control_hdr *ch = msgb_l2tph(msg); - struct l2tpd_connection *l2cc = l2tpd_cc_find_by_l_cc_id(l2i, ch->ccid); - - if (!l2cc) - return -1; - - osmo_fsm_inst_dispatch(l2cc->fsm, L2IC_E_RX_ICCN, msg); - return 0; -} - -/* Incoming "Incoming Call Connected" from SIU */ -static int rx_cdn(struct msgb *msg, struct avps_parsed *ap) -{ - struct l2tp_control_hdr *ch = msgb_l2tph(msg); - struct l2tpd_connection *l2cc = l2tpd_cc_find_by_l_cc_id(l2i, ch->ccid); - - if (!l2cc) - return -1; - - osmo_fsm_inst_dispatch(l2cc->fsm, L2IC_E_RX_CDN, msg); - return 0; -} - -/* Receive an IETF specified control message */ -static int l2tp_rcvmsg_control_ietf(struct msgb *msg, struct avps_parsed *ap, - uint16_t msg_type) -{ - switch (msg_type) { - case IETF_CTRLMSG_SCCRQ: - return rx_scc_rq(msg, ap); - case IETF_CTRLMSG_SCCCN: - return rx_scc_cn(msg, ap); - case IETF_CTRLMSG_STOPCCN: - return rx_stop_ccn(msg, ap); - case IETF_CTRLMSG_ICRQ: - return rx_ic_rq(msg, ap); - case IETF_CTRLMSG_ICCN: - return rx_ic_cn(msg, ap); - case IETF_CTRLMSG_CDN: - return rx_cdn(msg, ap); - default: - LOGP(DL2TP, LOGL_ERROR, "Unknown/Unhandled IETF Control " - "Message Type 0x%04x\n", msg_type); - return -1; - } -} - -/*********************************************************************** - * Ericsson specific messages - ***********************************************************************/ - -static int rx_eri_tcrp(struct msgb *msg, struct avps_parsed *ap) -{ - struct l2tp_control_hdr *ch = msgb_l2tph(msg); - struct l2tpd_connection *l2cc = l2tpd_cc_find_by_l_cc_id(l2i, ch->ccid); - - if (!l2cc) - return -1; - return 0; -} - -static int rx_eri_altcrp(struct msgb *msg, struct avps_parsed *ap) -{ - struct l2tp_control_hdr *ch = msgb_l2tph(msg); - struct l2tpd_connection *l2cc = l2tpd_cc_find_by_l_cc_id(l2i, ch->ccid); - - if (!l2cc) - return -1; - return 0; -} - -/* Receive an Ericsson specific control message */ -static int l2tp_rcvmsg_control_ericsson(struct msgb *msg, struct avps_parsed *ap, - uint16_t msg_type) -{ - switch (msg_type) { - case ERIC_CTRLMSG_TCRP: - return rx_eri_tcrp(msg, ap); - case ERIC_CTRLMSG_ALTCRP: - return rx_eri_altcrp(msg, ap); - default: - LOGP(DL2TP, LOGL_ERROR, "Unknown/Unhandled Ericsson Control " - "Message Type 0x%04x\n", msg_type); - return -1; - } -} - -static int l2tp_rcvmsg_control(struct msgb *msg) -{ - struct l2tp_control_hdr *ch = (struct l2tp_control_hdr *) msgb_data(msg); - struct avps_parsed ap; - struct avp_parsed *first_avp; - uint16_t msg_type; - int rc; - - l2tp_hdr_swap(ch); - - if ((ch->ver & VER_MASK) != 3) { - LOGP(DL2TP, LOGL_ERROR, "L2TP Version != 3\n"); - return -1; - } - - if ((ch->ver & (T_BIT|L_BIT|S_BIT)) != (T_BIT|L_BIT|S_BIT)) { - LOGP(DL2TP, LOGL_ERROR, "L2TP Bits wrong\n"); - return -1; - } - - if (ch->ver & Z_BITS) { - LOGP(DL2TP, LOGL_ERROR, "L2TP Z bit must not be set\n"); - return -1; - } - - if (msgb_l2tplen(msg) < ch->length) { - LOGP(DL2TP, LOGL_ERROR, "L2TP message length beyond msgb\n"); - return -1; - } - - if (ch->ccid != 0) { - LOGP(DL2TP, LOGL_ERROR, "Control Message for CCID != 0\n"); - return -1; - } - - /* Parse the first AVP an see if it is Control Message */ - rc = msgb_avps_parse(&ap, msg, sizeof(*ch)); - if (rc < 0) { - LOGP(DL2TP, LOGL_ERROR, "Error in parsing AVPs\n"); - return rc; - } - if (ap.num_avp <= 0) { - LOGP(DL2TP, LOGL_ERROR, "Not at least one AVP\n"); - return -1; - } - first_avp = &ap.avp[0]; - - if (first_avp->data_len != 2) { - LOGP(DL2TP, LOGL_ERROR, "Control Msg AVP length !=2: %u\n", - first_avp->data_len); - return -1; - } - msg_type = osmo_load16be(first_avp->data); - - if (first_avp->vendor_id == VENDOR_IETF && - first_avp->type == AVP_IETF_CTRL_MSG) - return l2tp_rcvmsg_control_ietf(msg, &ap, msg_type); - else if (first_avp->vendor_id == VENDOR_ERICSSON && - first_avp->type == AVP_ERIC_CTRL_MSG) - return l2tp_rcvmsg_control_ericsson(msg, &ap, msg_type); - - LOGP(DL2TP, LOGL_ERROR, "Unknown packet received.\n"); - return -1; -} - -static int l2tp_rcvmsg_data(struct msgb *msg, bool ip_transport) -{ - DEBUGP(DL2TP, "rx data: %s\n", msgb_hexdump(msg)); - return 0; -} - -int l2tp_rcvmsg(struct msgb *msg) -{ - uint32_t session = osmo_load32be(msgb_l2tph(msg)); - if (session == 0) { - /* strip session ID and feed to control */ - msgb_pull(msg, sizeof(session)); - return l2tp_rcvmsg_control(msg); - } - return -1; -} - static int l2tp_ip_read_cb(struct osmo_fd *ofd, unsigned int what) { struct msgb *msg = l2tp_msgb_alloc(); diff --git a/siu/l2tp/l2tpd.h b/siu/l2tp/l2tpd.h index d84629b..4f46427 100644 --- a/siu/l2tp/l2tpd.h +++ b/siu/l2tp/l2tpd.h @@ -83,3 +83,5 @@ struct l2tpd_instance { enum { DL2TP, }; + +extern struct l2tpd_instance *l2i; diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c new file mode 100644 index 0000000..0fe91c5 --- /dev/null +++ b/siu/l2tp/l2tpd_packet.c @@ -0,0 +1,657 @@ +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "l2tp_protocol.h" +#include "l2tpd.h" +#include "l2tpd_data.h" +#include "l2tpd_fsm.h" + +/*********************************************************************** + * AVP Parser / Encoder + ***********************************************************************/ + +/* a parsed representation of an L2TP AVP */ +struct avp_parsed { + uint16_t vendor_id; + uint16_t type; + uint16_t data_len; + uint8_t m:1, + h:1; + uint8_t *data; +}; + +/* parse single AVP at msg->data + offset and return the new offset */ +static int msgb_avp_parse(struct avp_parsed *ap, struct msgb *msg, int offset) +{ + uint32_t msgb_left = msgb_length(msg) - offset; + struct l2tp_avp_hdr *ah = (struct l2tp_avp_hdr *) (msgb_data(msg) + offset); + uint16_t avp_len; + + if (sizeof(*ah) > msgb_left) { + LOGP(DL2TP, LOGL_NOTICE, "AVP Hdr beyond end of msgb\n"); + return -1; + } + avp_len = ntohs(ah->m_h_length) & 0x3ff; + if (avp_len < 6) { + LOGP(DL2TP, LOGL_NOTICE, "AVP Parse: AVP len < 6\n"); + return -1; + } + if (avp_len > msgb_left) { + LOGP(DL2TP, LOGL_NOTICE, "AVP Data beyond end of msgb\n"); + return -1; + } + + ap->vendor_id = ntohs(ah->vendor_id); + ap->type = ntohs(ah->attr_type); + ap->data_len = avp_len - sizeof(*ah); + ap->data = ah->value; + ap->m = !!(ah->m_h_length & 0x8000); + ap->h = !!(ah->m_h_length & 0x4000); + + return offset + avp_len; +} + +struct avps_parsed { + unsigned int num_avp; + struct avp_parsed avp[64]; +}; + +static int msgb_avps_parse(struct avps_parsed *avps, struct msgb *msg, int offset) +{ + memset(avps, 0, sizeof(*avps)); + + while (msgb_length(msg) - offset > 0) { + struct avp_parsed *avp = &avps->avp[avps->num_avp++]; + int rc = msgb_avp_parse(avp, msg, offset); + if (rc < 0) + return rc; + else + offset = rc; + } + return avps->num_avp; +} + +static struct avp_parsed * +avps_parsed_find(struct avps_parsed *avps, uint16_t vendor_id, uint16_t type) +{ + unsigned int i; + + for (i = 0; i < avps->num_avp; i++) { + struct avp_parsed *avp = &avps->avp[i]; + if (avp->vendor_id == vendor_id && avp->type == type) + return avp; + } + return NULL; +} + +static uint8_t *avpp_val(struct avps_parsed *avps, uint16_t vendor_id, uint16_t type) +{ + struct avp_parsed *avp = avps_parsed_find(avps, vendor_id, type); + if (!avp) + return NULL; + return avp->data; +} + +static int avpp_len(struct avps_parsed *avps, uint16_t vendor_id, uint16_t type) +{ + struct avp_parsed *avp = avps_parsed_find(avps, vendor_id, type); + if (!avp) + return 0; + return avp->data_len; +} + +int avpp_val_u32(struct avps_parsed *avps, uint16_t vendor_id, uint16_t type, + uint32_t *u32) +{ + struct avp_parsed *avp = avps_parsed_find(avps, vendor_id, type); + if (!avp) + return -ENODEV; + if (avp->data_len < sizeof(*u32)) + return -EINVAL; + + *u32 = *((uint32_t *)avp->data); + return 0; +} + +int avpp_val_u16(struct avps_parsed *avps, uint16_t vendor_id, uint16_t type, + uint16_t *u16) +{ + struct avp_parsed *avp = avps_parsed_find(avps, vendor_id, type); + if (!avp) + return -ENODEV; + if (avp->data_len < sizeof(*u16)) + return -EINVAL; + + *u16 = *((uint16_t *)avp->data); + return 0; +} + +/* store an AVP at the end of the msg */ +static int msgb_avp_put(struct msgb *msg, uint16_t vendor_id, uint16_t type, + const uint8_t *data, uint16_t data_len, bool m_flag) +{ + uint8_t *out; + + if (data_len > 0x3ff - 6) { + LOGP(DL2TP, LOGL_ERROR, "Data too long for AVP\n"); + return -1; + } + + msgb_put_u16(msg, ((data_len + 6) & 0x3ff) | (m_flag ? 0x8000 : 0)); + msgb_put_u16(msg, vendor_id); + msgb_put_u16(msg, type); + out = msgb_put(msg, data_len); + memcpy(out, data, data_len); + + return 6 + data_len; +} + +/* store an uint8_t value AVP */ +static int msgb_avp_put_u8(struct msgb *msg, uint16_t vendor, uint16_t avp_type, + uint8_t val, bool m_flag) +{ + return msgb_avp_put(msg, vendor, avp_type, &val, 1, m_flag); +} + +/* store an uint16_t value AVP */ +static int msgb_avp_put_u16(struct msgb *msg, uint16_t vendor, uint16_t avp_type, + uint16_t val, bool m_flag) +{ + val = htons(val); + return msgb_avp_put(msg, vendor, avp_type, (uint8_t *)&val, 2, m_flag); +} + +/* store an uint32_t value AVP */ +static int msgb_avp_put_u32(struct msgb *msg, uint16_t vendor, uint16_t avp_type, + uint32_t val, bool m_flag) +{ + val = htonl(val); + return msgb_avp_put(msg, vendor, avp_type, (uint8_t *)&val, 4, m_flag); +} + +/* store a 'message type' AVP */ +static int msgb_avp_put_msgt(struct msgb *msg, uint16_t vendor, uint16_t msg_type) +{ + return msgb_avp_put_u16(msg, vendor, AVP_IETF_CTRL_MSG, msg_type, true); +} + + +/*********************************************************************** + * Message utilities + ***********************************************************************/ + +/* swap all fields of the l2tp_control header structure */ +static void l2tp_hdr_swap(struct l2tp_control_hdr *ch) +{ + ch->ver = ntohs(ch->ver); + ch->length = ntohs(ch->length); + ch->ccid = ntohl(ch->ccid); + ch->Ns = ntohs(ch->Ns); + ch->Nr = ntohs(ch->Nr); +} + +struct msgb *l2tp_msgb_alloc(void) +{ + return msgb_alloc_headroom(1600, 100, "L2TP"); +} + +static int msgb_avp_put_digest(struct msgb *msg) +{ + /* we simply put a zero-initialized AVP for now and update when + * trnasmitting */ + const uint8_t digest_zero[17] = { 0, }; + return msgb_avp_put(msg, VENDOR_IETF, AVP_IETF_MSG_DIGEST, + digest_zero, sizeof(digest_zero), true); +} + +/* E/// L2TP seems to use a static, constant HMAC key */ +static const uint8_t digest_key[] = { + 0x7b, 0x60, 0x85, 0xfb, 0xf4, 0x59, 0x33, 0x67, + 0x0a, 0xbc, 0xb0, 0x7a, 0x27, 0xfc, 0xea, 0x5e +}; + +/* update the message digest inside the AVP of a message */ +static int digest_avp_update(struct msgb *msg) +{ + struct l2tp_control_hdr *l2h = msgb_l2tph(msg); + struct l2tp_avp_hdr *ah = (struct l2tp_avp_hdr *) ((uint8_t *)l2h + sizeof(*l2h)); + uint8_t *hmac_res; + unsigned int len = ntohs(l2h->length); + + /* Digest AVP header is guaranteed to be the second AVP in a + * control message. First AVP is message type AVP with overall + * length of 8 bytes */ + + if (ntohs(ah->attr_type) != AVP_IETF_MSG_DIGEST || + ntohs(ah->vendor_id) != VENDOR_IETF || + (ntohs(ah->m_h_length) & 0x3FF) != 17) { + LOGP(DL2TP, LOGL_ERROR, "Missing Digest AVP, cannot update\n"); + return -1; + } + + if (len > msgb_l2tplen(msg)) { + /* FIXME: improve log message */ + LOGP(DL2TP, LOGL_ERROR, "invalid length"); + return -1; + } + + DEBUGP(DL2TP, "Tx Message before digest: %s\n", msgb_hexdump(msg)); + /* RFC says HMAC_Hash(shared_key, local_nonce + remote_nonce + control_message), + * but ericsson is doning something different without any + * local/remote nonce? */ + hmac_res = HMAC(EVP_md5(), digest_key, sizeof(digest_key), + (const uint8_t *)l2h, len, NULL, NULL); + memcpy(ah->value, hmac_res, 16); + DEBUGP(DL2TP, "Tx Message with digest: %s\n", msgb_hexdump(msg)); + + return 0; +} + +static int l2tp_msgb_tx(struct msgb *msg) +{ + struct l2tpd_connection *l2c = msg->dst; + struct l2tp_control_hdr *l2h; + int ret; + + /* first prepend the L2TP control header */ + l2h = (struct l2tp_control_hdr *) msgb_push(msg, sizeof(*l2h)); + l2h->ver = htons(T_BIT|L_BIT|S_BIT| msgb_l2tplen(msg)); + l2h->ccid = htonl(l2c->remote.ccid); + l2h->Ns = htons(l2c->next_tx_seq_nr++); + l2h->Nr = htons(l2c->next_rx_seq_nr); + + /* then insert/patch the message digest AVP */ + digest_avp_update(msg); + + /* FIXME: put in the queue for reliable re-transmission */ + + ret = sendto(l2i->l2tp_ofd.fd, msgb_l2tph(msg), msgb_l2tplen(msg), 0, &l2c->remote.ss, sizeof(l2c->remote.ss)); + return ret; +} + +/*********************************************************************** + * IETF specified messages + ***********************************************************************/ + +static int tx_scc_rp(struct l2tpd_connection *lc) +{ + struct msgb *msg = l2tp_msgb_alloc(); + const uint8_t eric_ver3_only[12] = { 0,0,0,3, 0,0,0,0, 0,0,0,0 }; + const uint8_t host_name[3] = { 'B', 'S', 'C' }; + const uint32_t router_id = 0x2342; + + msgb_avp_put_msgt(msg, VENDOR_IETF, IETF_CTRLMSG_SCCRP); + msgb_avp_put_digest(msg); + msgb_avp_put_u32(msg, VENDOR_IETF, AVP_IETF_AS_CTRL_CON_ID, + lc->remote.ccid, true); + msgb_avp_put(msg, VENDOR_ERICSSON, AVP_ERIC_PROTO_VER, + eric_ver3_only, sizeof(eric_ver3_only), true); + msgb_avp_put(msg, VENDOR_IETF, AVP_IETF_HOST_NAME, + host_name, sizeof(host_name), false); + msgb_avp_put_u32(msg, VENDOR_IETF, AVP_IETF_ROUTER_ID, + router_id, false); + msgb_avp_put_u16(msg, VENDOR_IETF, AVP_IETF_PW_CAP_LIST, + 0x0006, true); + + return l2tp_msgb_tx(msg); +} + +static int tx_tc_rq(struct l2tpd_session *ls) +{ + struct msgb *msg = l2tp_msgb_alloc(); + const uint8_t tcg[] = { 0x00, 0x19, 0x01, 0x1f, 0x05, + 0, 10, 11, 12, 62, /* SAPIs */ + 10, 251, 134, 1, /* IP */ + 0x00, 0x01, 0x05, 0x05, 0xb9 }; + + msgb_avp_put_msgt(msg, VENDOR_ERICSSON, ERIC_CTRLMSG_TCRQ); + msgb_avp_put_digest(msg); + msgb_avp_put(msg, VENDOR_ERICSSON, AVP_ERIC_TRANSP_CFG, + tcg, sizeof(tcg), true); + + return l2tp_msgb_tx(msg); +} + +static int tx_altc_rq(struct l2tpd_session *ls) +{ + struct msgb *msg = l2tp_msgb_alloc(); + const uint8_t tcsc[] = { 2, + 0, 0, 0, + 62, 62, 0 }; + + msgb_avp_put_msgt(msg, VENDOR_ERICSSON, ERIC_CTRLMSG_ALTCRQ); + msgb_avp_put_digest(msg); + msgb_avp_put(msg, VENDOR_ERICSSON, AVP_ERIC_TEI_TO_SC_MAP, + tcsc, sizeof(tcsc), true); + + return l2tp_msgb_tx(msg); +} + +static int tx_ic_rp(struct l2tpd_session *ls) +{ + struct msgb *msg = l2tp_msgb_alloc(); + + msgb_avp_put_msgt(msg, VENDOR_IETF, IETF_CTRLMSG_ICRP); + msgb_avp_put_digest(msg); + msgb_avp_put_u32(msg, VENDOR_IETF, AVP_IETF_LOC_SESS_ID, + ls->l_sess_id, true); + msgb_avp_put_u32(msg, VENDOR_IETF, AVP_IETF_REM_SESS_ID, + ls->r_sess_id, true); + /* Circuit type: existing; Circuit status: up */ + msgb_avp_put_u16(msg, VENDOR_IETF, AVP_IETF_CIRC_STATUS, + 0x0001, true); + /* Default L2 specific sublayer present */ + msgb_avp_put_u16(msg, VENDOR_IETF, AVP_IETF_L2_SPEC_SUBL, + 0x0001, true); + /* All incoming data packets require sequencing */ + msgb_avp_put_u16(msg, VENDOR_IETF, AVP_IETF_DATA_SEQUENCING, + 0x0002, true); + + return l2tp_msgb_tx(msg); +} + +static int tx_ack(struct l2tpd_session *ls) +{ + struct msgb *msg = l2tp_msgb_alloc(); + + msgb_avp_put_msgt(msg, VENDOR_IETF, IETF_CTRLMSG_ACK); + msgb_avp_put_digest(msg); + + return l2tp_msgb_tx(msg); +} + +static int tx_hello(struct l2tpd_session *ls) +{ + struct msgb *msg = l2tp_msgb_alloc(); + + msgb_avp_put_msgt(msg, VENDOR_IETF, IETF_CTRLMSG_HELLO); + msgb_avp_put_digest(msg); + + return l2tp_msgb_tx(msg); +} + +/* Incoming "Start Control-Connection Request" from SIU */ +static int rx_scc_rq(struct msgb *msg, struct avps_parsed *ap) +{ + struct l2tp_control_hdr *ch = (struct l2tp_control_hdr *) msgb_data(msg); + struct l2tpd_connection *l2cc; + struct sockaddr *sockaddr = msg->dst; + char *host_name = NULL; + uint16_t pw; + + /* Abort if Pseudowire capability doesn't include 6(HDLC) */ + if (avpp_val_u16(ap, VENDOR_IETF, AVP_IETF_PW_CAP_LIST, &pw) < 0 || + pw != htons(0x0006)) { + LOGP(DL2TP, LOGL_ERROR, "Pseudowire != HDLC\n"); + return -1; + } + + if (ch->ccid == 0) { + uint32_t remote_ccid, router_id; + l2cc = l2tpd_cc_alloc(l2i); + /* Get Assigned CCID and store in l2cc->remote.ccid */ + avpp_val_u32(ap, VENDOR_IETF, AVP_IETF_AS_CTRL_CON_ID, + &remote_ccid); + l2cc->remote.ccid = remote_ccid; + /* Router ID AVP */ + if (avpp_val_u32(ap, VENDOR_IETF, AVP_IETF_ROUTER_ID, + &router_id)) + l2cc->remote.router_id = router_id; + /* Host Name AVP */ + host_name = (char *) avpp_val(ap, VENDOR_IETF, AVP_IETF_HOST_NAME); + if (host_name) + l2cc->remote.host_name = talloc_strdup(l2cc, host_name); + memcpy(&l2cc->remote.ss, sockaddr, sizeof(*sockaddr)); + } else { + LOGP(DL2TP, LOGL_ERROR, "Received a SCCRQ with control id != 0: %d\n", ch->ccid); + return -1; + } + + osmo_fsm_inst_dispatch(l2cc->fsm, L2CC_E_RX_SCCRQ, msg); + return 0; +} + +/* Incoming "Start Control-Connection Connected" from SIU */ +static int rx_scc_cn(struct msgb *msg, struct avps_parsed *ap) +{ + struct l2tp_control_hdr *ch = msgb_l2tph(msg); + struct l2tpd_connection *l2cc = l2tpd_cc_find_by_l_cc_id(l2i, ch->ccid); + + if (!l2cc) + return -1; + + osmo_fsm_inst_dispatch(l2cc->fsm, L2CC_E_RX_SCCCN, msg); + /* FIXME: Send TCRQ and ALTCRQ */ + return 0; +} + +/* Incoming "Stop Control-Connection Notificiation" from SIU */ +static int rx_stop_ccn(struct msgb *msg, struct avps_parsed *ap) +{ + struct l2tp_control_hdr *ch = msgb_l2tph(msg); + struct l2tpd_connection *l2cc = l2tpd_cc_find_by_l_cc_id(l2i, ch->ccid); + + if (!l2cc) + return -1; + + osmo_fsm_inst_dispatch(l2cc->fsm, L2CC_E_RX_STOP_CCN, msg); + return 0; +} + +/* Incoming "Incoming Call Request" from SIU */ +static int rx_ic_rq(struct msgb *msg, struct avps_parsed *ap) +{ + struct l2tp_control_hdr *ch = msgb_l2tph(msg); + struct l2tpd_connection *l2cc = l2tpd_cc_find_by_l_cc_id(l2i, ch->ccid); + struct l2tpd_session *l2s; + uint32_t r_sess_id = 0; + uint32_t l_sess_id = 0; + + if (!l2cc) + return -1; + if (avpp_val_u32(ap, VENDOR_IETF, AVP_IETF_REM_SESS_ID, &r_sess_id)) + return -1; + if (avpp_val_u32(ap, VENDOR_IETF, AVP_IETF_LOC_SESS_ID, &l_sess_id)) + return -1; + + if (r_sess_id == 0) { + l2s = l2tpd_sess_alloc(l2cc); + l2s->r_sess_id = l_sess_id; + avpp_val_u16(ap, VENDOR_IETF, AVP_IETF_PW_TYPE, &l2s->pw_type); + } else { + l2s = l2tpd_sess_find_by_l_s_id(l2cc, r_sess_id); + if (!l2s) { + LOGP(DL2TP, LOGL_ERROR, "NoSession %u\n", + r_sess_id); + return -1; + } + } + + osmo_fsm_inst_dispatch(l2cc->fsm, L2IC_E_RX_ICRQ, msg); + return 0; +} + +/* Incoming "Incoming Call Connected" from SIU */ +static int rx_ic_cn(struct msgb *msg, struct avps_parsed *ap) +{ + struct l2tp_control_hdr *ch = msgb_l2tph(msg); + struct l2tpd_connection *l2cc = l2tpd_cc_find_by_l_cc_id(l2i, ch->ccid); + + if (!l2cc) + return -1; + + osmo_fsm_inst_dispatch(l2cc->fsm, L2IC_E_RX_ICCN, msg); + return 0; +} + +/* Incoming "Incoming Call Connected" from SIU */ +static int rx_cdn(struct msgb *msg, struct avps_parsed *ap) +{ + struct l2tp_control_hdr *ch = msgb_l2tph(msg); + struct l2tpd_connection *l2cc = l2tpd_cc_find_by_l_cc_id(l2i, ch->ccid); + + if (!l2cc) + return -1; + + osmo_fsm_inst_dispatch(l2cc->fsm, L2IC_E_RX_CDN, msg); + return 0; +} + +/* Receive an IETF specified control message */ +static int l2tp_rcvmsg_control_ietf(struct msgb *msg, struct avps_parsed *ap, + uint16_t msg_type) +{ + switch (msg_type) { + case IETF_CTRLMSG_SCCRQ: + return rx_scc_rq(msg, ap); + case IETF_CTRLMSG_SCCCN: + return rx_scc_cn(msg, ap); + case IETF_CTRLMSG_STOPCCN: + return rx_stop_ccn(msg, ap); + case IETF_CTRLMSG_ICRQ: + return rx_ic_rq(msg, ap); + case IETF_CTRLMSG_ICCN: + return rx_ic_cn(msg, ap); + case IETF_CTRLMSG_CDN: + return rx_cdn(msg, ap); + default: + LOGP(DL2TP, LOGL_ERROR, "Unknown/Unhandled IETF Control " + "Message Type 0x%04x\n", msg_type); + return -1; + } +} + +/*********************************************************************** + * Ericsson specific messages + ***********************************************************************/ + +static int rx_eri_tcrp(struct msgb *msg, struct avps_parsed *ap) +{ + struct l2tp_control_hdr *ch = msgb_l2tph(msg); + struct l2tpd_connection *l2cc = l2tpd_cc_find_by_l_cc_id(l2i, ch->ccid); + + if (!l2cc) + return -1; + return 0; +} + +static int rx_eri_altcrp(struct msgb *msg, struct avps_parsed *ap) +{ + struct l2tp_control_hdr *ch = msgb_l2tph(msg); + struct l2tpd_connection *l2cc = l2tpd_cc_find_by_l_cc_id(l2i, ch->ccid); + + if (!l2cc) + return -1; + return 0; +} + +/* Receive an Ericsson specific control message */ +static int l2tp_rcvmsg_control_ericsson(struct msgb *msg, struct avps_parsed *ap, + uint16_t msg_type) +{ + switch (msg_type) { + case ERIC_CTRLMSG_TCRP: + return rx_eri_tcrp(msg, ap); + case ERIC_CTRLMSG_ALTCRP: + return rx_eri_altcrp(msg, ap); + default: + LOGP(DL2TP, LOGL_ERROR, "Unknown/Unhandled Ericsson Control " + "Message Type 0x%04x\n", msg_type); + return -1; + } +} + +static int l2tp_rcvmsg_control(struct msgb *msg) +{ + struct l2tp_control_hdr *ch = (struct l2tp_control_hdr *) msgb_data(msg); + struct avps_parsed ap; + struct avp_parsed *first_avp; + uint16_t msg_type; + int rc; + + l2tp_hdr_swap(ch); + + if ((ch->ver & VER_MASK) != 3) { + LOGP(DL2TP, LOGL_ERROR, "L2TP Version != 3\n"); + return -1; + } + + if ((ch->ver & (T_BIT|L_BIT|S_BIT)) != (T_BIT|L_BIT|S_BIT)) { + LOGP(DL2TP, LOGL_ERROR, "L2TP Bits wrong\n"); + return -1; + } + + if (ch->ver & Z_BITS) { + LOGP(DL2TP, LOGL_ERROR, "L2TP Z bit must not be set\n"); + return -1; + } + + if (msgb_l2tplen(msg) < ch->length) { + LOGP(DL2TP, LOGL_ERROR, "L2TP message length beyond msgb\n"); + return -1; + } + + if (ch->ccid != 0) { + LOGP(DL2TP, LOGL_ERROR, "Control Message for CCID != 0\n"); + return -1; + } + + /* Parse the first AVP an see if it is Control Message */ + rc = msgb_avps_parse(&ap, msg, sizeof(*ch)); + if (rc < 0) { + LOGP(DL2TP, LOGL_ERROR, "Error in parsing AVPs\n"); + return rc; + } + if (ap.num_avp <= 0) { + LOGP(DL2TP, LOGL_ERROR, "Not at least one AVP\n"); + return -1; + } + first_avp = &ap.avp[0]; + + if (first_avp->data_len != 2) { + LOGP(DL2TP, LOGL_ERROR, "Control Msg AVP length !=2: %u\n", + first_avp->data_len); + return -1; + } + msg_type = osmo_load16be(first_avp->data); + + if (first_avp->vendor_id == VENDOR_IETF && + first_avp->type == AVP_IETF_CTRL_MSG) + return l2tp_rcvmsg_control_ietf(msg, &ap, msg_type); + else if (first_avp->vendor_id == VENDOR_ERICSSON && + first_avp->type == AVP_ERIC_CTRL_MSG) + return l2tp_rcvmsg_control_ericsson(msg, &ap, msg_type); + + LOGP(DL2TP, LOGL_ERROR, "Unknown packet received.\n"); + return -1; +} + +static int l2tp_rcvmsg_data(struct msgb *msg, bool ip_transport) +{ + DEBUGP(DL2TP, "rx data: %s\n", msgb_hexdump(msg)); + return 0; +} + +int l2tp_rcvmsg(struct msgb *msg) +{ + uint32_t session = osmo_load32be(msgb_l2tph(msg)); + if (session == 0) { + /* strip session ID and feed to control */ + msgb_pull(msg, sizeof(session)); + return l2tp_rcvmsg_control(msg); + } + return -1; +} diff --git a/siu/l2tp/l2tpd_packet.h b/siu/l2tp/l2tpd_packet.h new file mode 100644 index 0000000..911f28f --- /dev/null +++ b/siu/l2tp/l2tpd_packet.h @@ -0,0 +1,7 @@ +#pragma once + +struct msgb; + +int l2tp_rcvmsg(struct msgb *msg); + +struct msgb *l2tp_msgb_alloc(void); From a768dfca4ecf9cce493f6b5e48093b0d539d02fd Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Mon, 24 Oct 2016 05:15:56 +0200 Subject: [PATCH 031/133] l2tpd_packet: make tx function public will be used by the fsm --- siu/l2tp/l2tpd_packet.c | 12 ++++++------ siu/l2tp/l2tpd_packet.h | 9 +++++++++ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index 0fe91c5..9df11e9 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -286,7 +286,7 @@ static int l2tp_msgb_tx(struct msgb *msg) * IETF specified messages ***********************************************************************/ -static int tx_scc_rp(struct l2tpd_connection *lc) +int l2tp_tx_scc_rp(struct l2tpd_connection *lc) { struct msgb *msg = l2tp_msgb_alloc(); const uint8_t eric_ver3_only[12] = { 0,0,0,3, 0,0,0,0, 0,0,0,0 }; @@ -309,7 +309,7 @@ static int tx_scc_rp(struct l2tpd_connection *lc) return l2tp_msgb_tx(msg); } -static int tx_tc_rq(struct l2tpd_session *ls) +int l2tp_tx_tc_rq(struct l2tpd_session *ls) { struct msgb *msg = l2tp_msgb_alloc(); const uint8_t tcg[] = { 0x00, 0x19, 0x01, 0x1f, 0x05, @@ -325,7 +325,7 @@ static int tx_tc_rq(struct l2tpd_session *ls) return l2tp_msgb_tx(msg); } -static int tx_altc_rq(struct l2tpd_session *ls) +int l2tp_tx_altc_rq(struct l2tpd_session *ls) { struct msgb *msg = l2tp_msgb_alloc(); const uint8_t tcsc[] = { 2, @@ -340,7 +340,7 @@ static int tx_altc_rq(struct l2tpd_session *ls) return l2tp_msgb_tx(msg); } -static int tx_ic_rp(struct l2tpd_session *ls) +int l2tp_tx_ic_rp(struct l2tpd_session *ls) { struct msgb *msg = l2tp_msgb_alloc(); @@ -363,7 +363,7 @@ static int tx_ic_rp(struct l2tpd_session *ls) return l2tp_msgb_tx(msg); } -static int tx_ack(struct l2tpd_session *ls) +int l2tp_tx_ack(struct l2tpd_session *ls) { struct msgb *msg = l2tp_msgb_alloc(); @@ -373,7 +373,7 @@ static int tx_ack(struct l2tpd_session *ls) return l2tp_msgb_tx(msg); } -static int tx_hello(struct l2tpd_session *ls) +int l2tp_tx_hello(struct l2tpd_session *ls) { struct msgb *msg = l2tp_msgb_alloc(); diff --git a/siu/l2tp/l2tpd_packet.h b/siu/l2tp/l2tpd_packet.h index 911f28f..31a0569 100644 --- a/siu/l2tp/l2tpd_packet.h +++ b/siu/l2tp/l2tpd_packet.h @@ -1,6 +1,15 @@ #pragma once struct msgb; +struct l2tpd_connection; +struct l2tpd_session; + +int l2tp_tx_scc_rp(struct l2tpd_connection *lc); +int l2tp_tx_tc_rq(struct l2tpd_session *ls); +int l2tp_tx_altc_rq(struct l2tpd_session *ls); +int l2tp_tx_ic_rp(struct l2tpd_session *ls); +int l2tp_tx_ack(struct l2tpd_session *ls); +int l2tp_tx_hello(struct l2tpd_session *ls); int l2tp_rcvmsg(struct msgb *msg); From 8ff4d0b5debdd444f20f17b27dfd8b96bb250da8 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Mon, 24 Oct 2016 05:21:03 +0200 Subject: [PATCH 032/133] l2tpd_packet: use l2c/l2s instead of ls lc as everywhere else in the tree --- siu/l2tp/l2tpd_packet.c | 18 +++++++++--------- siu/l2tp/l2tpd_packet.h | 12 ++++++------ 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index 9df11e9..52c6238 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -286,7 +286,7 @@ static int l2tp_msgb_tx(struct msgb *msg) * IETF specified messages ***********************************************************************/ -int l2tp_tx_scc_rp(struct l2tpd_connection *lc) +int l2tp_tx_scc_rp(struct l2tpd_connection *l2c) { struct msgb *msg = l2tp_msgb_alloc(); const uint8_t eric_ver3_only[12] = { 0,0,0,3, 0,0,0,0, 0,0,0,0 }; @@ -296,7 +296,7 @@ int l2tp_tx_scc_rp(struct l2tpd_connection *lc) msgb_avp_put_msgt(msg, VENDOR_IETF, IETF_CTRLMSG_SCCRP); msgb_avp_put_digest(msg); msgb_avp_put_u32(msg, VENDOR_IETF, AVP_IETF_AS_CTRL_CON_ID, - lc->remote.ccid, true); + l2c->remote.ccid, true); msgb_avp_put(msg, VENDOR_ERICSSON, AVP_ERIC_PROTO_VER, eric_ver3_only, sizeof(eric_ver3_only), true); msgb_avp_put(msg, VENDOR_IETF, AVP_IETF_HOST_NAME, @@ -309,7 +309,7 @@ int l2tp_tx_scc_rp(struct l2tpd_connection *lc) return l2tp_msgb_tx(msg); } -int l2tp_tx_tc_rq(struct l2tpd_session *ls) +int l2tp_tx_tc_rq(struct l2tpd_session *l2s) { struct msgb *msg = l2tp_msgb_alloc(); const uint8_t tcg[] = { 0x00, 0x19, 0x01, 0x1f, 0x05, @@ -325,7 +325,7 @@ int l2tp_tx_tc_rq(struct l2tpd_session *ls) return l2tp_msgb_tx(msg); } -int l2tp_tx_altc_rq(struct l2tpd_session *ls) +int l2tp_tx_altc_rq(struct l2tpd_session *l2s) { struct msgb *msg = l2tp_msgb_alloc(); const uint8_t tcsc[] = { 2, @@ -340,16 +340,16 @@ int l2tp_tx_altc_rq(struct l2tpd_session *ls) return l2tp_msgb_tx(msg); } -int l2tp_tx_ic_rp(struct l2tpd_session *ls) +int l2tp_tx_ic_rp(struct l2tpd_session *l2s) { struct msgb *msg = l2tp_msgb_alloc(); msgb_avp_put_msgt(msg, VENDOR_IETF, IETF_CTRLMSG_ICRP); msgb_avp_put_digest(msg); msgb_avp_put_u32(msg, VENDOR_IETF, AVP_IETF_LOC_SESS_ID, - ls->l_sess_id, true); + l2s->l_sess_id, true); msgb_avp_put_u32(msg, VENDOR_IETF, AVP_IETF_REM_SESS_ID, - ls->r_sess_id, true); + l2s->r_sess_id, true); /* Circuit type: existing; Circuit status: up */ msgb_avp_put_u16(msg, VENDOR_IETF, AVP_IETF_CIRC_STATUS, 0x0001, true); @@ -363,7 +363,7 @@ int l2tp_tx_ic_rp(struct l2tpd_session *ls) return l2tp_msgb_tx(msg); } -int l2tp_tx_ack(struct l2tpd_session *ls) +int l2tp_tx_ack(struct l2tpd_session *l2s) { struct msgb *msg = l2tp_msgb_alloc(); @@ -373,7 +373,7 @@ int l2tp_tx_ack(struct l2tpd_session *ls) return l2tp_msgb_tx(msg); } -int l2tp_tx_hello(struct l2tpd_session *ls) +int l2tp_tx_hello(struct l2tpd_session *l2s) { struct msgb *msg = l2tp_msgb_alloc(); diff --git a/siu/l2tp/l2tpd_packet.h b/siu/l2tp/l2tpd_packet.h index 31a0569..4ca1bfc 100644 --- a/siu/l2tp/l2tpd_packet.h +++ b/siu/l2tp/l2tpd_packet.h @@ -4,12 +4,12 @@ struct msgb; struct l2tpd_connection; struct l2tpd_session; -int l2tp_tx_scc_rp(struct l2tpd_connection *lc); -int l2tp_tx_tc_rq(struct l2tpd_session *ls); -int l2tp_tx_altc_rq(struct l2tpd_session *ls); -int l2tp_tx_ic_rp(struct l2tpd_session *ls); -int l2tp_tx_ack(struct l2tpd_session *ls); -int l2tp_tx_hello(struct l2tpd_session *ls); +int l2tp_tx_scc_rp(struct l2tpd_connection *l2c); +int l2tp_tx_tc_rq(struct l2tpd_session *l2s); +int l2tp_tx_altc_rq(struct l2tpd_session *l2s); +int l2tp_tx_ic_rp(struct l2tpd_session *l2s); +int l2tp_tx_ack(struct l2tpd_session *l2s); +int l2tp_tx_hello(struct l2tpd_session *l2s); int l2tp_rcvmsg(struct msgb *msg); From 387ab48db223fd63199f70f0a4c719487b3baefd Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Mon, 24 Oct 2016 05:37:11 +0200 Subject: [PATCH 033/133] l2tpd_packet: set msg->dst = l2c when using a session this is an expensive call --- siu/l2tp/l2tpd_packet.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index 52c6238..b70735b 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -306,12 +306,15 @@ int l2tp_tx_scc_rp(struct l2tpd_connection *l2c) msgb_avp_put_u16(msg, VENDOR_IETF, AVP_IETF_PW_CAP_LIST, 0x0006, true); + msg->dst = l2c; return l2tp_msgb_tx(msg); } int l2tp_tx_tc_rq(struct l2tpd_session *l2s) { struct msgb *msg = l2tp_msgb_alloc(); + /* FIXME: use pointer instead of this call */ + struct l2tpd_connection *l2c = l2tpd_cc_find_by_l_cc_id(l2i, l2s->l_sess_id); const uint8_t tcg[] = { 0x00, 0x19, 0x01, 0x1f, 0x05, 0, 10, 11, 12, 62, /* SAPIs */ 10, 251, 134, 1, /* IP */ @@ -322,12 +325,15 @@ int l2tp_tx_tc_rq(struct l2tpd_session *l2s) msgb_avp_put(msg, VENDOR_ERICSSON, AVP_ERIC_TRANSP_CFG, tcg, sizeof(tcg), true); + msg->dst = l2c; return l2tp_msgb_tx(msg); } int l2tp_tx_altc_rq(struct l2tpd_session *l2s) { struct msgb *msg = l2tp_msgb_alloc(); + /* FIXME: use pointer instead of this call */ + struct l2tpd_connection *l2c = l2tpd_cc_find_by_l_cc_id(l2i, l2s->l_sess_id); const uint8_t tcsc[] = { 2, 0, 0, 0, 62, 62, 0 }; @@ -337,12 +343,15 @@ int l2tp_tx_altc_rq(struct l2tpd_session *l2s) msgb_avp_put(msg, VENDOR_ERICSSON, AVP_ERIC_TEI_TO_SC_MAP, tcsc, sizeof(tcsc), true); + msg->dst = l2c; return l2tp_msgb_tx(msg); } int l2tp_tx_ic_rp(struct l2tpd_session *l2s) { struct msgb *msg = l2tp_msgb_alloc(); + /* FIXME: use pointer instead of this call */ + struct l2tpd_connection *l2c = l2tpd_cc_find_by_l_cc_id(l2i, l2s->l_sess_id); msgb_avp_put_msgt(msg, VENDOR_IETF, IETF_CTRLMSG_ICRP); msgb_avp_put_digest(msg); @@ -360,26 +369,33 @@ int l2tp_tx_ic_rp(struct l2tpd_session *l2s) msgb_avp_put_u16(msg, VENDOR_IETF, AVP_IETF_DATA_SEQUENCING, 0x0002, true); + msg->dst = l2c; return l2tp_msgb_tx(msg); } int l2tp_tx_ack(struct l2tpd_session *l2s) { struct msgb *msg = l2tp_msgb_alloc(); + /* FIXME: use pointer instead of this call */ + struct l2tpd_connection *l2c = l2tpd_cc_find_by_l_cc_id(l2i, l2s->l_sess_id); msgb_avp_put_msgt(msg, VENDOR_IETF, IETF_CTRLMSG_ACK); msgb_avp_put_digest(msg); + msg->dst = l2c; return l2tp_msgb_tx(msg); } int l2tp_tx_hello(struct l2tpd_session *l2s) { struct msgb *msg = l2tp_msgb_alloc(); + /* FIXME: use pointer instead of this call */ + struct l2tpd_connection *l2c = l2tpd_cc_find_by_l_cc_id(l2i, l2s->l_sess_id); msgb_avp_put_msgt(msg, VENDOR_IETF, IETF_CTRLMSG_HELLO); msgb_avp_put_digest(msg); + msg->dst = l2c; return l2tp_msgb_tx(msg); } From 8d4c3e0a5299443b2ea0a3cc7e90c406a5e66920 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Mon, 24 Oct 2016 05:37:52 +0200 Subject: [PATCH 034/133] l2tpd_packet: return 0 on success in l2tp_msgb_tx() --- siu/l2tp/l2tpd_packet.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index b70735b..eff8413 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -279,7 +279,9 @@ static int l2tp_msgb_tx(struct msgb *msg) /* FIXME: put in the queue for reliable re-transmission */ ret = sendto(l2i->l2tp_ofd.fd, msgb_l2tph(msg), msgb_l2tplen(msg), 0, &l2c->remote.ss, sizeof(l2c->remote.ss)); - return ret; + if (ret < 0) + return ret; + return 0; } /*********************************************************************** From 4df20bcdcff3c76e12234588d4b1934302a6a2b3 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Mon, 24 Oct 2016 05:38:07 +0200 Subject: [PATCH 035/133] l2tpd_fsm: sent out SCCRP --- siu/l2tp/l2tpd_fsm.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/siu/l2tp/l2tpd_fsm.c b/siu/l2tp/l2tpd_fsm.c index 4cfda69..52e7cc7 100644 --- a/siu/l2tp/l2tpd_fsm.c +++ b/siu/l2tp/l2tpd_fsm.c @@ -1,13 +1,17 @@ #include + +#include "l2tpd_packet.h" #include "l2tpd_fsm.h" #define S(x) (1 << (x)) static void l2tp_ctrl_s_init(struct osmo_fsm_inst *fi, uint32_t event, void *data) { - /* FIXME: Send SCCRP */ - osmo_fsm_inst_state_chg(fi, L2CC_S_WAIT_CTL_CONN, 0, 0); + struct l2tpd_connection *l2c = data; + if (!l2tp_tx_scc_rp(l2c)) { + osmo_fsm_inst_state_chg(fi, L2CC_S_WAIT_CTL_CONN, 0, 0); + } } static void l2tp_ctrl_s_wait_ctl_conn(struct osmo_fsm_inst *fi, uint32_t event, void *data) From 6203509f9def572ba0f87dc0b6ae476ff56d91b5 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Mon, 24 Oct 2016 06:23:07 +0200 Subject: [PATCH 036/133] l2tpd_fsm: use priv instead of data data contains the msgbuffer --- siu/l2tp/l2tpd_fsm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/siu/l2tp/l2tpd_fsm.c b/siu/l2tp/l2tpd_fsm.c index 52e7cc7..e97ebc8 100644 --- a/siu/l2tp/l2tpd_fsm.c +++ b/siu/l2tp/l2tpd_fsm.c @@ -8,7 +8,7 @@ static void l2tp_ctrl_s_init(struct osmo_fsm_inst *fi, uint32_t event, void *data) { - struct l2tpd_connection *l2c = data; + struct l2tpd_connection *l2c = fi->priv; if (!l2tp_tx_scc_rp(l2c)) { osmo_fsm_inst_state_chg(fi, L2CC_S_WAIT_CTL_CONN, 0, 0); } From e1aa3aaa1cdf00252e241d55688ed08b1be3b519 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Mon, 24 Oct 2016 06:23:55 +0200 Subject: [PATCH 037/133] l2tpd: l2tp_msgb_alloc(): sets now l2h -> msg->data --- siu/l2tp/l2tpd_packet.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index eff8413..3b8f9ff 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -205,7 +205,10 @@ static void l2tp_hdr_swap(struct l2tp_control_hdr *ch) struct msgb *l2tp_msgb_alloc(void) { - return msgb_alloc_headroom(1600, 100, "L2TP"); + struct msgb *msg = msgb_alloc_headroom(1600, 100, "L2TP"); + if (msg) + msg->l2h = msg->data; + return msg; } static int msgb_avp_put_digest(struct msgb *msg) From f6a71518ccf841134d4204be6abc7e2c45d18a8a Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Mon, 24 Oct 2016 06:24:51 +0200 Subject: [PATCH 038/133] l2tpd_packet/digest_avp_update: use msgb_data / msgb_lenght --- siu/l2tp/l2tpd_packet.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index 3b8f9ff..800c7d0 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -229,7 +229,7 @@ static const uint8_t digest_key[] = { /* update the message digest inside the AVP of a message */ static int digest_avp_update(struct msgb *msg) { - struct l2tp_control_hdr *l2h = msgb_l2tph(msg); + struct l2tp_control_hdr *l2h = (struct l2tp_control_hdr *) msgb_data(msg); struct l2tp_avp_hdr *ah = (struct l2tp_avp_hdr *) ((uint8_t *)l2h + sizeof(*l2h)); uint8_t *hmac_res; unsigned int len = ntohs(l2h->length); @@ -245,7 +245,7 @@ static int digest_avp_update(struct msgb *msg) return -1; } - if (len > msgb_l2tplen(msg)) { + if (len > msgb_length(msg)) { /* FIXME: improve log message */ LOGP(DL2TP, LOGL_ERROR, "invalid length"); return -1; From b201ef2f021c872f342921d93f6cd10cb783e673 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Mon, 24 Oct 2016 06:25:31 +0200 Subject: [PATCH 039/133] l2tpd_packet/digest_avp_update: fix search AVP digest --- siu/l2tp/l2tpd_packet.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index 800c7d0..162979b 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -237,10 +237,11 @@ static int digest_avp_update(struct msgb *msg) /* Digest AVP header is guaranteed to be the second AVP in a * control message. First AVP is message type AVP with overall * length of 8 bytes */ + ah = (struct l2tp_avp_hdr *) ((uint8_t *) ah + 8); if (ntohs(ah->attr_type) != AVP_IETF_MSG_DIGEST || ntohs(ah->vendor_id) != VENDOR_IETF || - (ntohs(ah->m_h_length) & 0x3FF) != 17) { + (ntohs(ah->m_h_length) & 0x3FF) != 23) { LOGP(DL2TP, LOGL_ERROR, "Missing Digest AVP, cannot update\n"); return -1; } From 75436421a492ab8a466a9d60b65e4c0167a4abd0 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Mon, 24 Oct 2016 06:26:06 +0200 Subject: [PATCH 040/133] l2tpd_packet: complete l2tp control header missing session id and incorrect lenght / version field --- siu/l2tp/l2tpd_packet.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index 162979b..2bddd9b 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -269,10 +269,12 @@ static int l2tp_msgb_tx(struct msgb *msg) struct l2tpd_connection *l2c = msg->dst; struct l2tp_control_hdr *l2h; int ret; + uint32_t *session_id; /* first prepend the L2TP control header */ l2h = (struct l2tp_control_hdr *) msgb_push(msg, sizeof(*l2h)); - l2h->ver = htons(T_BIT|L_BIT|S_BIT| msgb_l2tplen(msg)); + l2h->ver = htons(T_BIT|L_BIT|S_BIT| 0x3); + l2h->length = htons(msgb_length(msg)); l2h->ccid = htonl(l2c->remote.ccid); l2h->Ns = htons(l2c->next_tx_seq_nr++); l2h->Nr = htons(l2c->next_rx_seq_nr); @@ -280,6 +282,10 @@ static int l2tp_msgb_tx(struct msgb *msg) /* then insert/patch the message digest AVP */ digest_avp_update(msg); + /* push session id */ + session_id = (uint32_t *) msgb_push(msg, 4); + *session_id = 0; + /* FIXME: put in the queue for reliable re-transmission */ ret = sendto(l2i->l2tp_ofd.fd, msgb_l2tph(msg), msgb_l2tplen(msg), 0, &l2c->remote.ss, sizeof(l2c->remote.ss)); From e17366d0b0005cfc105c4b8472caa87eace091e5 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Mon, 24 Oct 2016 06:26:27 +0200 Subject: [PATCH 041/133] l2tpd_packet: use msgb_data / msgb_length when transmitting --- siu/l2tp/l2tpd_packet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index 2bddd9b..19e5a5a 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -288,7 +288,7 @@ static int l2tp_msgb_tx(struct msgb *msg) /* FIXME: put in the queue for reliable re-transmission */ - ret = sendto(l2i->l2tp_ofd.fd, msgb_l2tph(msg), msgb_l2tplen(msg), 0, &l2c->remote.ss, sizeof(l2c->remote.ss)); + ret = sendto(l2i->l2tp_ofd.fd, msgb_data(msg), msgb_length(msg), 0, &l2c->remote.ss, sizeof(l2c->remote.ss)); if (ret < 0) return ret; return 0; From 606f60da6c80fae2a69425e2dab73c4ba233a4b7 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Mon, 24 Oct 2016 06:30:23 +0200 Subject: [PATCH 042/133] l2tpd_packet: also do htons/htonl in avpp_val_u16/32 --- siu/l2tp/l2tpd_packet.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index 19e5a5a..58dd74b 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -123,6 +123,7 @@ int avpp_val_u32(struct avps_parsed *avps, uint16_t vendor_id, uint16_t type, return -EINVAL; *u32 = *((uint32_t *)avp->data); + *u32 = htonl(*u32); return 0; } @@ -136,6 +137,7 @@ int avpp_val_u16(struct avps_parsed *avps, uint16_t vendor_id, uint16_t type, return -EINVAL; *u16 = *((uint16_t *)avp->data); + *u16 = htons(*u16); return 0; } @@ -422,7 +424,7 @@ static int rx_scc_rq(struct msgb *msg, struct avps_parsed *ap) /* Abort if Pseudowire capability doesn't include 6(HDLC) */ if (avpp_val_u16(ap, VENDOR_IETF, AVP_IETF_PW_CAP_LIST, &pw) < 0 || - pw != htons(0x0006)) { + pw != 0x0006) { LOGP(DL2TP, LOGL_ERROR, "Pseudowire != HDLC\n"); return -1; } From 4a043b76d5bfdf6f3e891cbdbdfbdd27806bc4b8 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Mon, 24 Oct 2016 06:47:30 +0200 Subject: [PATCH 043/133] l2tpd_packet: add vendor_name = Ericsson to SCCRP --- siu/l2tp/l2tpd_packet.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index 58dd74b..7d2ea48 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -305,6 +305,7 @@ int l2tp_tx_scc_rp(struct l2tpd_connection *l2c) struct msgb *msg = l2tp_msgb_alloc(); const uint8_t eric_ver3_only[12] = { 0,0,0,3, 0,0,0,0, 0,0,0,0 }; const uint8_t host_name[3] = { 'B', 'S', 'C' }; + const uint8_t vendor_name[8] = { 'E', 'r', 'i', 'c', 's', 's', 'o', 'n' }; const uint32_t router_id = 0x2342; msgb_avp_put_msgt(msg, VENDOR_IETF, IETF_CTRLMSG_SCCRP); @@ -315,6 +316,8 @@ int l2tp_tx_scc_rp(struct l2tpd_connection *l2c) eric_ver3_only, sizeof(eric_ver3_only), true); msgb_avp_put(msg, VENDOR_IETF, AVP_IETF_HOST_NAME, host_name, sizeof(host_name), false); + msgb_avp_put(msg, VENDOR_IETF, AVP_IETF_VENDOR_NAME, + vendor_name, sizeof(vendor_name), false); msgb_avp_put_u32(msg, VENDOR_IETF, AVP_IETF_ROUTER_ID, router_id, false); msgb_avp_put_u16(msg, VENDOR_IETF, AVP_IETF_PW_CAP_LIST, From 15ef36a217ea9d96c67ecfe39759a71592e79b11 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Mon, 24 Oct 2016 06:48:03 +0200 Subject: [PATCH 044/133] l2tpd_packet: first packet already count, set the l2c->next_rx_seq_nr = 1 --- siu/l2tp/l2tpd_packet.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index 7d2ea48..4024427 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -448,6 +448,7 @@ static int rx_scc_rq(struct msgb *msg, struct avps_parsed *ap) if (host_name) l2cc->remote.host_name = talloc_strdup(l2cc, host_name); memcpy(&l2cc->remote.ss, sockaddr, sizeof(*sockaddr)); + l2cc->next_rx_seq_nr = 1; } else { LOGP(DL2TP, LOGL_ERROR, "Received a SCCRQ with control id != 0: %d\n", ch->ccid); return -1; @@ -661,6 +662,8 @@ static int l2tp_rcvmsg_control(struct msgb *msg) } msg_type = osmo_load16be(first_avp->data); + /* FIXME: we need to get the l2c here to count the rx */ + if (first_avp->vendor_id == VENDOR_IETF && first_avp->type == AVP_IETF_CTRL_MSG) return l2tp_rcvmsg_control_ietf(msg, &ap, msg_type); From 73b7656636b39e7ea31151f28c5feae3957df080 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Mon, 24 Oct 2016 07:25:47 +0200 Subject: [PATCH 045/133] l2tp_protocol: correct value of AVP_IETF_AS_CTRL_CON_ID --- siu/l2tp/l2tp_protocol.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/siu/l2tp/l2tp_protocol.h b/siu/l2tp/l2tp_protocol.h index d0c900a..1cde319 100644 --- a/siu/l2tp/l2tp_protocol.h +++ b/siu/l2tp/l2tp_protocol.h @@ -49,7 +49,6 @@ enum l2tp_avp_ietf { AVP_IETF_CTRL_MSG = 0, AVP_IETF_RESULT_CODE = 1, AVP_IETF_CTRL_TIE_BRK = 5, - AVP_IETF_AS_CTRL_CON_ID = 6, AVP_IETF_HOST_NAME = 7, AVP_IETF_VENDOR_NAME = 8, AVP_IETF_RX_WIN_SIZE = 10, @@ -58,6 +57,7 @@ enum l2tp_avp_ietf { AVP_IETF_CIRC_ERRORS = 34, AVP_IETF_MSG_DIGEST = 59, AVP_IETF_ROUTER_ID = 60, + AVP_IETF_AS_CTRL_CON_ID = 61, AVP_IETF_PW_CAP_LIST = 62, AVP_IETF_LOC_SESS_ID = 63, AVP_IETF_REM_SESS_ID = 64, From 36294b5878d33bafb5e2e1df0b3dd6c611a7b3ef Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Mon, 24 Oct 2016 07:26:17 +0200 Subject: [PATCH 046/133] l2tp_instance: setsockopt to the same tos value of bsc --- siu/l2tp/l2tpd.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/siu/l2tp/l2tpd.c b/siu/l2tp/l2tpd.c index ba1d42f..d1761fc 100644 --- a/siu/l2tp/l2tpd.c +++ b/siu/l2tp/l2tpd.c @@ -48,6 +48,7 @@ static int l2tp_ip_read_cb(struct osmo_fd *ofd, unsigned int what) static int l2tpd_instance_start(struct l2tpd_instance *li) { int rc; + uint8_t dscp = 0xb8; INIT_LLIST_HEAD(&li->connections); @@ -60,6 +61,9 @@ static int l2tpd_instance_start(struct l2tpd_instance *li) if (rc < 0) return rc; + setsockopt(li->l2tp_ofd.fd, IPPROTO_IP, IP_TOS, + &dscp, sizeof(dscp)); + return 0; } From ec03bf207aa3baf5ec3f177f2f75dda09c823777 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Mon, 24 Oct 2016 07:26:38 +0200 Subject: [PATCH 047/133] l2tpd_packet: set router_id to the same value of trace --- siu/l2tp/l2tpd_packet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index 4024427..4483c49 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -306,7 +306,7 @@ int l2tp_tx_scc_rp(struct l2tpd_connection *l2c) const uint8_t eric_ver3_only[12] = { 0,0,0,3, 0,0,0,0, 0,0,0,0 }; const uint8_t host_name[3] = { 'B', 'S', 'C' }; const uint8_t vendor_name[8] = { 'E', 'r', 'i', 'c', 's', 's', 'o', 'n' }; - const uint32_t router_id = 0x2342; + const uint32_t router_id = 0xac1e2a05; msgb_avp_put_msgt(msg, VENDOR_IETF, IETF_CTRLMSG_SCCRP); msgb_avp_put_digest(msg); From 22bdaae934caa897c25067ead34cf4412681128a Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Mon, 24 Oct 2016 18:58:40 +0200 Subject: [PATCH 048/133] l2tpd_packet: correct digest, the first byte must be zero in the message the first byte is the type of digest (hmac-md5) --- siu/l2tp/l2tpd_packet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index 4483c49..3bd64d8 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -260,7 +260,7 @@ static int digest_avp_update(struct msgb *msg) * local/remote nonce? */ hmac_res = HMAC(EVP_md5(), digest_key, sizeof(digest_key), (const uint8_t *)l2h, len, NULL, NULL); - memcpy(ah->value, hmac_res, 16); + memcpy(ah->value + 1, hmac_res, 16); DEBUGP(DL2TP, "Tx Message with digest: %s\n", msgb_hexdump(msg)); return 0; From 370e69c9bb3688f13ebf90a4454c718189d4bfe4 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Mon, 24 Oct 2016 21:09:43 +0200 Subject: [PATCH 049/133] l2tpd_data: add ccid to fsm id allows to identifiy the fsm instances --- siu/l2tp/l2tpd_data.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/siu/l2tp/l2tpd_data.c b/siu/l2tp/l2tpd_data.c index 5ea39a2..3b069e7 100644 --- a/siu/l2tp/l2tpd_data.c +++ b/siu/l2tp/l2tpd_data.c @@ -68,12 +68,16 @@ struct l2tpd_connection * l2tpd_cc_alloc(struct l2tpd_instance *l2i) { struct l2tpd_connection *l2c = talloc_zero(l2i, struct l2tpd_connection); + char id_str[12] = {0}; + INIT_LLIST_HEAD(&l2c->sessions); l2c->local.ccid = l2i->next_l_cc_id++; + snprintf(id_str, 12, "%d", l2c->local.ccid); + llist_add(&l2c->list, &l2i->connections); - l2c->fsm = osmo_fsm_inst_alloc(&l2tp_cc_fsm, l2c, l2c, LOGL_DEBUG, NULL); + l2c->fsm = osmo_fsm_inst_alloc(&l2tp_cc_fsm, l2c, l2c, LOGL_DEBUG, id_str); return l2c; } From 4863678b85cb572e87c47dcb224afc8f2e803899 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Mon, 24 Oct 2016 21:10:44 +0200 Subject: [PATCH 050/133] l2tpd_packet: add l2tp_connection *l2c into receive functions and lookup the cid --- siu/l2tp/l2tpd_packet.c | 83 ++++++++++++++++++++--------------------- 1 file changed, 40 insertions(+), 43 deletions(-) diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index 3bd64d8..0488ed2 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -417,10 +417,9 @@ int l2tp_tx_hello(struct l2tpd_session *l2s) } /* Incoming "Start Control-Connection Request" from SIU */ -static int rx_scc_rq(struct msgb *msg, struct avps_parsed *ap) +static int rx_scc_rq(struct l2tpd_connection *l2c, struct msgb *msg, struct avps_parsed *ap) { struct l2tp_control_hdr *ch = (struct l2tp_control_hdr *) msgb_data(msg); - struct l2tpd_connection *l2cc; struct sockaddr *sockaddr = msg->dst; char *host_name = NULL; uint16_t pw; @@ -434,36 +433,33 @@ static int rx_scc_rq(struct msgb *msg, struct avps_parsed *ap) if (ch->ccid == 0) { uint32_t remote_ccid, router_id; - l2cc = l2tpd_cc_alloc(l2i); + l2c = l2tpd_cc_alloc(l2i, local_cid); /* Get Assigned CCID and store in l2cc->remote.ccid */ avpp_val_u32(ap, VENDOR_IETF, AVP_IETF_AS_CTRL_CON_ID, &remote_ccid); - l2cc->remote.ccid = remote_ccid; + l2c->remote.ccid = remote_ccid; /* Router ID AVP */ if (avpp_val_u32(ap, VENDOR_IETF, AVP_IETF_ROUTER_ID, &router_id)) - l2cc->remote.router_id = router_id; + l2c->remote.router_id = router_id; /* Host Name AVP */ host_name = (char *) avpp_val(ap, VENDOR_IETF, AVP_IETF_HOST_NAME); if (host_name) - l2cc->remote.host_name = talloc_strdup(l2cc, host_name); - memcpy(&l2cc->remote.ss, sockaddr, sizeof(*sockaddr)); - l2cc->next_rx_seq_nr = 1; + l2c->remote.host_name = talloc_strdup(l2c, host_name); + memcpy(&l2c->remote.ss, sockaddr, sizeof(*sockaddr)); + l2c->next_rx_seq_nr = 1; } else { LOGP(DL2TP, LOGL_ERROR, "Received a SCCRQ with control id != 0: %d\n", ch->ccid); return -1; } - osmo_fsm_inst_dispatch(l2cc->fsm, L2CC_E_RX_SCCRQ, msg); + osmo_fsm_inst_dispatch(l2c->fsm, L2CC_E_RX_SCCRQ, msg); return 0; } /* Incoming "Start Control-Connection Connected" from SIU */ -static int rx_scc_cn(struct msgb *msg, struct avps_parsed *ap) +static int rx_scc_cn(struct l2tpd_connection *l2cc, struct msgb *msg, struct avps_parsed *ap) { - struct l2tp_control_hdr *ch = msgb_l2tph(msg); - struct l2tpd_connection *l2cc = l2tpd_cc_find_by_l_cc_id(l2i, ch->ccid); - if (!l2cc) return -1; @@ -473,11 +469,8 @@ static int rx_scc_cn(struct msgb *msg, struct avps_parsed *ap) } /* Incoming "Stop Control-Connection Notificiation" from SIU */ -static int rx_stop_ccn(struct msgb *msg, struct avps_parsed *ap) +static int rx_stop_ccn(struct l2tpd_connection *l2cc, struct msgb *msg, struct avps_parsed *ap) { - struct l2tp_control_hdr *ch = msgb_l2tph(msg); - struct l2tpd_connection *l2cc = l2tpd_cc_find_by_l_cc_id(l2i, ch->ccid); - if (!l2cc) return -1; @@ -486,10 +479,8 @@ static int rx_stop_ccn(struct msgb *msg, struct avps_parsed *ap) } /* Incoming "Incoming Call Request" from SIU */ -static int rx_ic_rq(struct msgb *msg, struct avps_parsed *ap) +static int rx_ic_rq(struct l2tpd_connection *l2cc, struct msgb *msg, struct avps_parsed *ap) { - struct l2tp_control_hdr *ch = msgb_l2tph(msg); - struct l2tpd_connection *l2cc = l2tpd_cc_find_by_l_cc_id(l2i, ch->ccid); struct l2tpd_session *l2s; uint32_t r_sess_id = 0; uint32_t l_sess_id = 0; @@ -519,11 +510,8 @@ static int rx_ic_rq(struct msgb *msg, struct avps_parsed *ap) } /* Incoming "Incoming Call Connected" from SIU */ -static int rx_ic_cn(struct msgb *msg, struct avps_parsed *ap) +static int rx_ic_cn(struct l2tpd_connection *l2cc, struct msgb *msg, struct avps_parsed *ap) { - struct l2tp_control_hdr *ch = msgb_l2tph(msg); - struct l2tpd_connection *l2cc = l2tpd_cc_find_by_l_cc_id(l2i, ch->ccid); - if (!l2cc) return -1; @@ -532,11 +520,8 @@ static int rx_ic_cn(struct msgb *msg, struct avps_parsed *ap) } /* Incoming "Incoming Call Connected" from SIU */ -static int rx_cdn(struct msgb *msg, struct avps_parsed *ap) +static int rx_cdn(struct l2tpd_connection *l2cc, struct msgb *msg, struct avps_parsed *ap) { - struct l2tp_control_hdr *ch = msgb_l2tph(msg); - struct l2tpd_connection *l2cc = l2tpd_cc_find_by_l_cc_id(l2i, ch->ccid); - if (!l2cc) return -1; @@ -545,22 +530,23 @@ static int rx_cdn(struct msgb *msg, struct avps_parsed *ap) } /* Receive an IETF specified control message */ -static int l2tp_rcvmsg_control_ietf(struct msgb *msg, struct avps_parsed *ap, +static int l2tp_rcvmsg_control_ietf(struct l2tpd_connection *l2c, + struct msgb *msg, struct avps_parsed *ap, uint16_t msg_type) { switch (msg_type) { case IETF_CTRLMSG_SCCRQ: - return rx_scc_rq(msg, ap); + return rx_scc_rq(l2c, msg, ap); case IETF_CTRLMSG_SCCCN: - return rx_scc_cn(msg, ap); + return rx_scc_cn(l2c, msg, ap); case IETF_CTRLMSG_STOPCCN: - return rx_stop_ccn(msg, ap); + return rx_stop_ccn(l2c, msg, ap); case IETF_CTRLMSG_ICRQ: - return rx_ic_rq(msg, ap); + return rx_ic_rq(l2c, msg, ap); case IETF_CTRLMSG_ICCN: - return rx_ic_cn(msg, ap); + return rx_ic_cn(l2c, msg, ap); case IETF_CTRLMSG_CDN: - return rx_cdn(msg, ap); + return rx_cdn(l2c, msg, ap); default: LOGP(DL2TP, LOGL_ERROR, "Unknown/Unhandled IETF Control " "Message Type 0x%04x\n", msg_type); @@ -593,7 +579,8 @@ static int rx_eri_altcrp(struct msgb *msg, struct avps_parsed *ap) } /* Receive an Ericsson specific control message */ -static int l2tp_rcvmsg_control_ericsson(struct msgb *msg, struct avps_parsed *ap, +static int l2tp_rcvmsg_control_ericsson(struct l2tpd_connection *l2c, + struct msgb *msg, struct avps_parsed *ap, uint16_t msg_type) { switch (msg_type) { @@ -611,6 +598,7 @@ static int l2tp_rcvmsg_control_ericsson(struct msgb *msg, struct avps_parsed *ap static int l2tp_rcvmsg_control(struct msgb *msg) { struct l2tp_control_hdr *ch = (struct l2tp_control_hdr *) msgb_data(msg); + struct l2tpd_connection *l2c = NULL; struct avps_parsed ap; struct avp_parsed *first_avp; uint16_t msg_type; @@ -638,11 +626,6 @@ static int l2tp_rcvmsg_control(struct msgb *msg) return -1; } - if (ch->ccid != 0) { - LOGP(DL2TP, LOGL_ERROR, "Control Message for CCID != 0\n"); - return -1; - } - /* Parse the first AVP an see if it is Control Message */ rc = msgb_avps_parse(&ap, msg, sizeof(*ch)); if (rc < 0) { @@ -663,13 +646,27 @@ static int l2tp_rcvmsg_control(struct msgb *msg) msg_type = osmo_load16be(first_avp->data); /* FIXME: we need to get the l2c here to count the rx */ + if (ch->ccid != 0) { + /* lookup control connection */ + l2c = l2tpd_cc_find_by_l_cc_id(l2i, ch->ccid); + if (!l2c) { + LOGP(DL2TP, LOGL_ERROR, "l2tp: can not find a connection for ccid %d\n", ch->ccid); + return -1; + } + + /* FIXME: do real seq numbering. check if already received etc. */ + if (l2c->next_rx_seq_nr < (ch->Ns + 1)) + l2c->next_rx_seq_nr = ch->Ns + 1; + if (l2c->next_tx_seq_nr != ch->Nr) + LOGP(DL2TP, LOGL_ERROR, "l2tp: wrong seq number received. expectd %d != recveived %d.\n", l2c->next_tx_seq_nr, ch->Ns); + } if (first_avp->vendor_id == VENDOR_IETF && first_avp->type == AVP_IETF_CTRL_MSG) - return l2tp_rcvmsg_control_ietf(msg, &ap, msg_type); + return l2tp_rcvmsg_control_ietf(l2c, msg, &ap, msg_type); else if (first_avp->vendor_id == VENDOR_ERICSSON && first_avp->type == AVP_ERIC_CTRL_MSG) - return l2tp_rcvmsg_control_ericsson(msg, &ap, msg_type); + return l2tp_rcvmsg_control_ericsson(l2c, msg, &ap, msg_type); LOGP(DL2TP, LOGL_ERROR, "Unknown packet received.\n"); return -1; From 629e0b770e1be56316b747ef0070b3e3e3bcfced Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Mon, 24 Oct 2016 21:19:54 +0200 Subject: [PATCH 051/133] l2tpd_packet: l2tp_tx_ack change to a control connection message TX Ack is used by control connection, not by session management --- siu/l2tp/l2tpd_packet.c | 3 +-- siu/l2tp/l2tpd_packet.h | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index 0488ed2..59c34a0 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -390,11 +390,10 @@ int l2tp_tx_ic_rp(struct l2tpd_session *l2s) return l2tp_msgb_tx(msg); } -int l2tp_tx_ack(struct l2tpd_session *l2s) +int l2tp_tx_ack(struct l2tpd_connection *l2c) { struct msgb *msg = l2tp_msgb_alloc(); /* FIXME: use pointer instead of this call */ - struct l2tpd_connection *l2c = l2tpd_cc_find_by_l_cc_id(l2i, l2s->l_sess_id); msgb_avp_put_msgt(msg, VENDOR_IETF, IETF_CTRLMSG_ACK); msgb_avp_put_digest(msg); diff --git a/siu/l2tp/l2tpd_packet.h b/siu/l2tp/l2tpd_packet.h index 4ca1bfc..332502e 100644 --- a/siu/l2tp/l2tpd_packet.h +++ b/siu/l2tp/l2tpd_packet.h @@ -8,7 +8,7 @@ int l2tp_tx_scc_rp(struct l2tpd_connection *l2c); int l2tp_tx_tc_rq(struct l2tpd_session *l2s); int l2tp_tx_altc_rq(struct l2tpd_session *l2s); int l2tp_tx_ic_rp(struct l2tpd_session *l2s); -int l2tp_tx_ack(struct l2tpd_session *l2s); +int l2tp_tx_ack(struct l2tpd_connection *l2c); int l2tp_tx_hello(struct l2tpd_session *l2s); int l2tp_rcvmsg(struct msgb *msg); From 10d655150cb5c5db00a13884884373aabe30141b Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Mon, 24 Oct 2016 21:20:25 +0200 Subject: [PATCH 052/133] l2tpd_packet: fix removal of forgotten local_cid in l2tpd_cc_alloc() --- siu/l2tp/l2tpd_packet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index 59c34a0..a8bcc7d 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -432,7 +432,7 @@ static int rx_scc_rq(struct l2tpd_connection *l2c, struct msgb *msg, struct avps if (ch->ccid == 0) { uint32_t remote_ccid, router_id; - l2c = l2tpd_cc_alloc(l2i, local_cid); + l2c = l2tpd_cc_alloc(l2i); /* Get Assigned CCID and store in l2cc->remote.ccid */ avpp_val_u32(ap, VENDOR_IETF, AVP_IETF_AS_CTRL_CON_ID, &remote_ccid); From 10036edca368a4e27863a90f52d7d46ddf54d9ec Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Mon, 24 Oct 2016 21:20:42 +0200 Subject: [PATCH 053/133] l2tpd_fsm: answer to a SCCCN with a ACK --- siu/l2tp/l2tpd_fsm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/siu/l2tp/l2tpd_fsm.c b/siu/l2tp/l2tpd_fsm.c index e97ebc8..613b0f9 100644 --- a/siu/l2tp/l2tpd_fsm.c +++ b/siu/l2tp/l2tpd_fsm.c @@ -16,8 +16,11 @@ static void l2tp_ctrl_s_init(struct osmo_fsm_inst *fi, uint32_t event, void *dat static void l2tp_ctrl_s_wait_ctl_conn(struct osmo_fsm_inst *fi, uint32_t event, void *data) { + struct l2tpd_connection *l2c = fi->priv; + switch (event) { case L2CC_E_RX_SCCCN: + l2tp_tx_ack(l2c); osmo_fsm_inst_state_chg(fi, L2CC_S_ESTABLISHED, 0, 0); break; } From 5ce4fc112c8f8f203988a1d701cc535078c8f09c Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Mon, 24 Oct 2016 21:33:58 +0200 Subject: [PATCH 054/133] l2tpd: set l2i->next_l_ccid to 1 0 is reserved for discovery. so 0 should never assigned to a control connection --- siu/l2tp/l2tpd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/siu/l2tp/l2tpd.c b/siu/l2tp/l2tpd.c index d1761fc..cfea946 100644 --- a/siu/l2tp/l2tpd.c +++ b/siu/l2tp/l2tpd.c @@ -93,6 +93,8 @@ int main(int argc, char **argv) l2i = talloc_zero(tall_l2tp_ctx, struct l2tpd_instance); l2i->cfg.bind_ip = "0.0.0.0"; + /* important must not 0 */ + l2i->next_l_cc_id = 1; rc = l2tpd_instance_start(l2i); if (rc < 0) From f9a4590f2dc6fa06ff95deb297d83581d9dfab28 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Mon, 24 Oct 2016 21:35:02 +0200 Subject: [PATCH 055/133] l2tpd_fsm: answer to a to STOP CCN with an ACK still a TODO to tear down the fsm and struct --- siu/l2tp/l2tpd_fsm.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/siu/l2tp/l2tpd_fsm.c b/siu/l2tp/l2tpd_fsm.c index 613b0f9..0380375 100644 --- a/siu/l2tp/l2tpd_fsm.c +++ b/siu/l2tp/l2tpd_fsm.c @@ -23,17 +23,24 @@ static void l2tp_ctrl_s_wait_ctl_conn(struct osmo_fsm_inst *fi, uint32_t event, l2tp_tx_ack(l2c); osmo_fsm_inst_state_chg(fi, L2CC_S_ESTABLISHED, 0, 0); break; + case L2CC_E_RX_STOP_CCN: + l2tp_tx_ack(l2c); + /* FIXME: tear down whole l2c */ + break; } } static void l2tp_ctrl_s_established(struct osmo_fsm_inst *fi, uint32_t event, void *data) { + struct l2tpd_connection *l2c = fi->priv; + switch (event) { case L2CC_E_LOCAL_CLOSE_REQ: /* FIXME: Send StopCCN */ break; case L2CC_E_RX_STOP_CCN: - /* FIXME */ + l2tp_tx_ack(l2c); + /* FIXME: tear down whole l2c */ break; } } From 39c2f5a3235261f9c33a099fb6226d2b09153057 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Mon, 24 Oct 2016 21:35:21 +0200 Subject: [PATCH 056/133] l2tpd: log allocation of new CC with local + remote id --- siu/l2tp/l2tpd_packet.c | 1 + 1 file changed, 1 insertion(+) diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index a8bcc7d..0c22312 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -447,6 +447,7 @@ static int rx_scc_rq(struct l2tpd_connection *l2c, struct msgb *msg, struct avps l2c->remote.host_name = talloc_strdup(l2c, host_name); memcpy(&l2c->remote.ss, sockaddr, sizeof(*sockaddr)); l2c->next_rx_seq_nr = 1; + LOGP(DL2TP, LOGL_INFO, "Allocated CC: local %d remote %d\n", l2c->local.ccid, l2c->remote.ccid); } else { LOGP(DL2TP, LOGL_ERROR, "Received a SCCRQ with control id != 0: %d\n", ch->ccid); return -1; From 4b4becaa23396cff50987b6a2ab99e33e91d23d8 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Tue, 25 Oct 2016 11:25:40 +0200 Subject: [PATCH 057/133] l2tpd_packet: implement l2tp_tx_stop_ccn --- siu/l2tp/l2tpd_packet.c | 12 ++++++++++++ siu/l2tp/l2tpd_packet.h | 1 + 2 files changed, 13 insertions(+) diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index 0c22312..7cba7dc 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -327,6 +327,18 @@ int l2tp_tx_scc_rp(struct l2tpd_connection *l2c) return l2tp_msgb_tx(msg); } +int l2tp_tx_stop_ccn(struct l2tpd_connection *l2c) +{ + struct msgb *msg = l2tp_msgb_alloc(); + /* FIXME: use pointer instead of this call */ + + msgb_avp_put_msgt(msg, VENDOR_IETF, IETF_CTRLMSG_STOPCCN); + msgb_avp_put_digest(msg); + + msg->dst = l2c; + return l2tp_msgb_tx(msg); +} + int l2tp_tx_tc_rq(struct l2tpd_session *l2s) { struct msgb *msg = l2tp_msgb_alloc(); diff --git a/siu/l2tp/l2tpd_packet.h b/siu/l2tp/l2tpd_packet.h index 332502e..eb0f7b0 100644 --- a/siu/l2tp/l2tpd_packet.h +++ b/siu/l2tp/l2tpd_packet.h @@ -5,6 +5,7 @@ struct l2tpd_connection; struct l2tpd_session; int l2tp_tx_scc_rp(struct l2tpd_connection *l2c); +int l2tp_tx_stop_ccn(struct l2tpd_connection *l2c); int l2tp_tx_tc_rq(struct l2tpd_session *l2s); int l2tp_tx_altc_rq(struct l2tpd_session *l2s); int l2tp_tx_ic_rp(struct l2tpd_session *l2s); From 23a1114d28d2518183d92fb032df21d1eaa2a419 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Tue, 25 Oct 2016 11:27:59 +0200 Subject: [PATCH 058/133] l2tpd_fsm: send stop ccn on local close requests events --- siu/l2tp/l2tpd_fsm.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/siu/l2tp/l2tpd_fsm.c b/siu/l2tp/l2tpd_fsm.c index 0380375..07daaf1 100644 --- a/siu/l2tp/l2tpd_fsm.c +++ b/siu/l2tp/l2tpd_fsm.c @@ -19,6 +19,11 @@ static void l2tp_ctrl_s_wait_ctl_conn(struct osmo_fsm_inst *fi, uint32_t event, struct l2tpd_connection *l2c = fi->priv; switch (event) { + case L2CC_E_LOCAL_CLOSE_REQ: + l2tp_tx_stop_ccn(l2c); + osmo_fsm_inst_state_chg(fi, L2CC_S_INIT, 0, 0); + /* FIXME: teardown */ + break; case L2CC_E_RX_SCCCN: l2tp_tx_ack(l2c); osmo_fsm_inst_state_chg(fi, L2CC_S_ESTABLISHED, 0, 0); @@ -36,7 +41,9 @@ static void l2tp_ctrl_s_established(struct osmo_fsm_inst *fi, uint32_t event, vo switch (event) { case L2CC_E_LOCAL_CLOSE_REQ: - /* FIXME: Send StopCCN */ + l2tp_tx_stop_ccn(l2c); + osmo_fsm_inst_state_chg(fi, L2CC_S_INIT, 0, 0); + /* FIXME: teardown */ break; case L2CC_E_RX_STOP_CCN: l2tp_tx_ack(l2c); From cc942323f0b637455bf9c6e303a5e62c90ea786f Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Tue, 25 Oct 2016 12:11:05 +0200 Subject: [PATCH 059/133] l2tpd: free msgb after handling everything --- siu/l2tp/l2tpd.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/siu/l2tp/l2tpd.c b/siu/l2tp/l2tpd.c index cfea946..f231ad5 100644 --- a/siu/l2tp/l2tpd.c +++ b/siu/l2tp/l2tpd.c @@ -42,7 +42,10 @@ static int l2tp_ip_read_cb(struct osmo_fd *ofd, unsigned int what) msg->l2h = msg->data; msg->dst = &ss; - return l2tp_rcvmsg(msg); + rc = l2tp_rcvmsg(msg); + msgb_free(msg); + + return rc; } static int l2tpd_instance_start(struct l2tpd_instance *li) From 1ec0edc5590e3263bc1a58782fb3250c042e6609 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Tue, 25 Oct 2016 12:11:51 +0200 Subject: [PATCH 060/133] l2tpd_fsm: add control connection states L2CC_S_WAIT_FOR_TCRP, L2CC_S_ESTABLISHED_CONFIGURED L2CC_S_WAIT_FOR_TCRP = after sending a TCRQ L2CC_S_ESTABLISHED_CONFIGURED = when the connection is fully initialized --- siu/l2tp/l2tpd_fsm.c | 52 +++++++++++++++++++++++++++++++++++++++++--- siu/l2tp/l2tpd_fsm.h | 6 +++++ 2 files changed, 55 insertions(+), 3 deletions(-) diff --git a/siu/l2tp/l2tpd_fsm.c b/siu/l2tp/l2tpd_fsm.c index 07daaf1..cf027fe 100644 --- a/siu/l2tp/l2tpd_fsm.c +++ b/siu/l2tp/l2tpd_fsm.c @@ -39,11 +39,41 @@ static void l2tp_ctrl_s_established(struct osmo_fsm_inst *fi, uint32_t event, vo { struct l2tpd_connection *l2c = fi->priv; + if (!l2tp_tx_scc_rp(l2c)) { + osmo_fsm_inst_state_chg(fi, L2CC_S_WAIT_FOR_TCRP, 0, 0); + } +} + +static void l2tp_ctrl_s_wait_for_tcrp(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + struct l2tpd_connection *l2c = fi->priv; + switch (event) { case L2CC_E_LOCAL_CLOSE_REQ: l2tp_tx_stop_ccn(l2c); osmo_fsm_inst_state_chg(fi, L2CC_S_INIT, 0, 0); - /* FIXME: teardown */ + /* FIXME: teardown instead of INIT */ + break; + case L2CC_E_RX_STOP_CCN: + l2tp_tx_ack(l2c); + /* FIXME: tear down whole l2c */ + break; + case L2CC_E_RX_TCRP: + l2tp_tx_ack(l2c); + osmo_fsm_inst_state_chg(fi, L2CC_S_ESTABLISHED_CONFIGURED, 0, 0); + break; + } +} + +static void l2tp_ctrl_s_established_configured(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + struct l2tpd_connection *l2c = fi->priv; + + switch (event) { + case L2CC_E_LOCAL_CLOSE_REQ: + l2tp_tx_stop_ccn(l2c); + osmo_fsm_inst_state_chg(fi, L2CC_S_INIT, 0, 0); + /* FIXME: teardown instead of INIT */ break; case L2CC_E_RX_STOP_CCN: l2tp_tx_ack(l2c); @@ -58,6 +88,7 @@ static const struct value_string l2tp_cc_events[] = { { L2CC_E_RX_SCCRP, "RX-SCCRP" }, { L2CC_E_RX_SCCCN, "RX-SCCCN" }, { L2CC_E_RX_STOP_CCN, "RX-STOPCCN" }, + { L2CC_E_RX_TCRP, "RX-TCRP" }, { 0, NULL } }; @@ -79,11 +110,27 @@ static const struct osmo_fsm_state l2tp_ctrl_states[] = { [L2CC_S_ESTABLISHED] = { .in_event_mask = S(L2CC_E_LOCAL_CLOSE_REQ) | S(L2CC_E_RX_STOP_CCN), - .out_state_mask = S(L2CC_S_ESTABLISHED) | + .out_state_mask = S(L2CC_S_WAIT_FOR_TCRP) | S(L2CC_S_INIT), .name = "ESTABLISHED", .action = l2tp_ctrl_s_established, }, + [L2CC_S_WAIT_FOR_TCRP] = { + .in_event_mask = S(L2CC_E_LOCAL_CLOSE_REQ) | + S(L2CC_E_RX_STOP_CCN) | + S(L2CC_E_RX_TCRP), + .out_state_mask = S(L2CC_S_ESTABLISHED_CONFIGURED) | + S(L2CC_S_INIT), + .name = "WAIT_FOR_TCRP", + .action = l2tp_ctrl_s_wait_for_tcrp, + }, + [L2CC_S_ESTABLISHED_CONFIGURED] = { + .in_event_mask = S(L2CC_E_LOCAL_CLOSE_REQ) | + S(L2CC_E_RX_STOP_CCN), + .out_state_mask = S(L2CC_S_INIT), + .name = "ESTABLISHED_CONFIGURED", + .action = l2tp_ctrl_s_established_configured, + }, }; struct osmo_fsm l2tp_cc_fsm = { @@ -165,4 +212,3 @@ struct osmo_fsm l2tp_ic_fsm = { .allstate_event_mask = S(L2IC_E_RX_CDN) | S(L2IC_E_LOCAL_CLOSE_REQ), .allstate_action = l2tp_ic_allstate, }; - diff --git a/siu/l2tp/l2tpd_fsm.h b/siu/l2tp/l2tpd_fsm.h index 5af92f2..9f8e507 100644 --- a/siu/l2tp/l2tpd_fsm.h +++ b/siu/l2tp/l2tpd_fsm.h @@ -15,6 +15,8 @@ enum l2tpd_ctrl_con_event { L2CC_E_RX_SCCCN, /* Received Stop CCN */ L2CC_E_RX_STOP_CCN, + /* Received Transport configuration Reply */ + L2CC_E_RX_TCRP, }; enum l2tpd_in_call_event { @@ -42,6 +44,10 @@ enum l2tpd_ctrl_con_state { L2CC_S_WAIT_CTL_CONN, /* Control Conncetion is established */ L2CC_S_ESTABLISHED, + /* After we sent a TCRQ, waiting for TCRP */ + L2CC_S_WAIT_FOR_TCRP, + /* We configured the SIU to start sessions */ + L2CC_S_ESTABLISHED_CONFIGURED }; /* ICRQ recipient */ From 8af3b8ebf20d1dce578a13df6a9d43942e4d6a31 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Tue, 25 Oct 2016 14:30:21 +0200 Subject: [PATCH 061/133] l2tpd_fsm: allow to receive L2CC_E_RX_STOP_CCN in L2CC_S_WAIT_CTL_CONN L2CC_E_RX_STOP_CCN can received at any state --- siu/l2tp/l2tpd_fsm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/siu/l2tp/l2tpd_fsm.c b/siu/l2tp/l2tpd_fsm.c index cf027fe..988fea1 100644 --- a/siu/l2tp/l2tpd_fsm.c +++ b/siu/l2tp/l2tpd_fsm.c @@ -101,7 +101,8 @@ static const struct osmo_fsm_state l2tp_ctrl_states[] = { }, [L2CC_S_WAIT_CTL_CONN] = { .in_event_mask = S(L2CC_E_RX_SCCCN) | - S(L2CC_E_LOCAL_CLOSE_REQ), + S(L2CC_E_LOCAL_CLOSE_REQ) | + S(L2CC_E_RX_STOP_CCN), .out_state_mask = S(L2CC_S_ESTABLISHED) | S(L2CC_S_INIT), .name = "WAIT_CTL_CONN", From 4da71e0232972e2687f428e2cf78deda30c1f43a Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Tue, 25 Oct 2016 14:30:43 +0200 Subject: [PATCH 062/133] l2tpd_fsm: sent out a TCRQ after control connection is established --- siu/l2tp/l2tpd_fsm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/siu/l2tp/l2tpd_fsm.c b/siu/l2tp/l2tpd_fsm.c index 988fea1..27ae966 100644 --- a/siu/l2tp/l2tpd_fsm.c +++ b/siu/l2tp/l2tpd_fsm.c @@ -39,7 +39,7 @@ static void l2tp_ctrl_s_established(struct osmo_fsm_inst *fi, uint32_t event, vo { struct l2tpd_connection *l2c = fi->priv; - if (!l2tp_tx_scc_rp(l2c)) { + if (!l2tp_tx_tc_rq(l2c)) { osmo_fsm_inst_state_chg(fi, L2CC_S_WAIT_FOR_TCRP, 0, 0); } } From 2b3566c365096fbf2ea2dff344c25f9925d443a6 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Tue, 25 Oct 2016 14:31:07 +0200 Subject: [PATCH 063/133] l2tpd_packet: add cid to wrong seq number received --- siu/l2tp/l2tpd_packet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index 7cba7dc..b2d46cf 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -670,7 +670,7 @@ static int l2tp_rcvmsg_control(struct msgb *msg) if (l2c->next_rx_seq_nr < (ch->Ns + 1)) l2c->next_rx_seq_nr = ch->Ns + 1; if (l2c->next_tx_seq_nr != ch->Nr) - LOGP(DL2TP, LOGL_ERROR, "l2tp: wrong seq number received. expectd %d != recveived %d.\n", l2c->next_tx_seq_nr, ch->Ns); + LOGP(DL2TP, LOGL_ERROR, "cid %d: wrong seq number received. expectd %d != recveived %d.\n", l2c->local.ccid, l2c->next_tx_seq_nr, ch->Ns); } if (first_avp->vendor_id == VENDOR_IETF && From 32ebeebe755a9fa6854b7ccb1bd7d412b5a996f9 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Tue, 25 Oct 2016 14:35:11 +0200 Subject: [PATCH 064/133] l2tpd_packet: l2tp_tx_stop_ccn_msg(msg) to sent out STOP CCN to unknown control connections --- siu/l2tp/l2tpd_packet.c | 21 +++++++++++++++++++++ siu/l2tp/l2tpd_packet.h | 1 + 2 files changed, 22 insertions(+) diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index b2d46cf..545fd30 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -339,6 +339,27 @@ int l2tp_tx_stop_ccn(struct l2tpd_connection *l2c) return l2tp_msgb_tx(msg); } +int l2tp_tx_stop_ccn_msg(struct msgb *old) +{ + struct msgb *msg = l2tp_msgb_alloc(); + struct l2tpd_connection l2c; + memset(&l2c, 0x0, sizeof(l2c)); + + struct l2tp_control_hdr *ch = (struct l2tp_control_hdr *) msgb_data(old); + + memcpy(&l2c.remote.ss, old->dst, sizeof(struct sockaddr)); + l2c.next_tx_seq_nr = ch->Nr; + l2c.next_rx_seq_nr = ch->Ns + 1; + l2c.remote.ccid = ch->ccid; + /* FIXME: use pointer instead of this call */ + + msgb_avp_put_msgt(msg, VENDOR_IETF, IETF_CTRLMSG_STOPCCN); + msgb_avp_put_digest(msg); + + msg->dst = &l2c; + return l2tp_msgb_tx(msg); +} + int l2tp_tx_tc_rq(struct l2tpd_session *l2s) { struct msgb *msg = l2tp_msgb_alloc(); diff --git a/siu/l2tp/l2tpd_packet.h b/siu/l2tp/l2tpd_packet.h index eb0f7b0..a5e308d 100644 --- a/siu/l2tp/l2tpd_packet.h +++ b/siu/l2tp/l2tpd_packet.h @@ -6,6 +6,7 @@ struct l2tpd_session; int l2tp_tx_scc_rp(struct l2tpd_connection *l2c); int l2tp_tx_stop_ccn(struct l2tpd_connection *l2c); +int l2tp_tx_stop_ccn_msg(struct msgb *old); int l2tp_tx_tc_rq(struct l2tpd_session *l2s); int l2tp_tx_altc_rq(struct l2tpd_session *l2s); int l2tp_tx_ic_rp(struct l2tpd_session *l2s); From 00120312c36de00a1794a79206c6b8ba3523cbb6 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Tue, 25 Oct 2016 14:36:10 +0200 Subject: [PATCH 065/133] l2tpd_packet.h: sort tx functions --- siu/l2tp/l2tpd_packet.h | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/siu/l2tp/l2tpd_packet.h b/siu/l2tp/l2tpd_packet.h index a5e308d..8c50bf6 100644 --- a/siu/l2tp/l2tpd_packet.h +++ b/siu/l2tp/l2tpd_packet.h @@ -4,13 +4,16 @@ struct msgb; struct l2tpd_connection; struct l2tpd_session; +/* control connection management */ int l2tp_tx_scc_rp(struct l2tpd_connection *l2c); int l2tp_tx_stop_ccn(struct l2tpd_connection *l2c); -int l2tp_tx_stop_ccn_msg(struct msgb *old); -int l2tp_tx_tc_rq(struct l2tpd_session *l2s); -int l2tp_tx_altc_rq(struct l2tpd_session *l2s); -int l2tp_tx_ic_rp(struct l2tpd_session *l2s); +int l2tp_tx_stop_ccn_msg(struct msgb *old) +int l2tp_tx_tc_rq(struct l2tpd_connection *l2c); +int l2tp_tx_altc_rq(struct l2tpd_connection *l2c); int l2tp_tx_ack(struct l2tpd_connection *l2c); + +/* session management */ +int l2tp_tx_ic_rp(struct l2tpd_session *l2s); int l2tp_tx_hello(struct l2tpd_session *l2s); int l2tp_rcvmsg(struct msgb *msg); From 5941d7be495c4fb6b5aab8d7930aead9395e66d7 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Tue, 25 Oct 2016 15:06:18 +0200 Subject: [PATCH 066/133] l2tpd_packet: implement l2tp_tx_tc_rq l2tp_tx_altc_rq_superchannel l2tp_tx_altc_rq_timeslot --- siu/l2tp/l2tpd_packet.c | 65 +++++++++++++++++++++++++++++++---------- siu/l2tp/l2tpd_packet.h | 3 +- 2 files changed, 51 insertions(+), 17 deletions(-) diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index 545fd30..e172ed5 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -360,36 +360,69 @@ int l2tp_tx_stop_ccn_msg(struct msgb *old) return l2tp_msgb_tx(msg); } -int l2tp_tx_tc_rq(struct l2tpd_session *l2s) +int l2tp_tx_tc_rq(struct l2tpd_connection *l2c) +{ + struct msgb *msg = l2tp_msgb_alloc(); + const uint8_t tcg[] = { + 0x03, 0xe8, /* overload threashold */ + 0x03, /* number of transport groups */ + + /* first transport group */ + 0x11, /* tc group id */ + 0x02, /* number of sapis */ + 0x00, 0x62, /* SAPIs */ + 172, 23, 42, 3, /* IP */ + 0x2e, 0x01, 0x5, 0x1, 0x2c, /* dscp, crc32, bundling timeout, max packet size */ + + /* second transport group */ + 0x06, /* tc group id */ + 0x02, /* number of sapis */ + 0x0a, 0x0b, /* SAPIs */ + 172, 23, 42, 3, /* IP */ + 0x08, 0x01, 0x5, 0x1, 0x2c, /* dscp, crc32, bundling timeout, max packet size */ + + /* third transport group */ + 0x08, /* tc group id */ + 0x01, /* number of sapis */ + 0x0c, /* SAPIs */ + 172, 23, 42, 3, /* IP */ + 0x22, 0x01, 0x5, 0x1, 0x2c, /* dscp, crc32, bundling timeout, max packet size */ + }; + + msgb_avp_put_msgt(msg, VENDOR_ERICSSON, ERIC_CTRLMSG_TCRQ); + msgb_avp_put_digest(msg); + msgb_avp_put(msg, VENDOR_ERICSSON, AVP_ERIC_TRANSP_CFG, + tcg, sizeof(tcg), true); + + msg->dst = l2c; + return l2tp_msgb_tx(msg); +} + +int l2tp_tx_altc_rq_timeslot(struct l2tpd_connection *l2c) { struct msgb *msg = l2tp_msgb_alloc(); - /* FIXME: use pointer instead of this call */ - struct l2tpd_connection *l2c = l2tpd_cc_find_by_l_cc_id(l2i, l2s->l_sess_id); - const uint8_t tcg[] = { 0x00, 0x19, 0x01, 0x1f, 0x05, - 0, 10, 11, 12, 62, /* SAPIs */ - 10, 251, 134, 1, /* IP */ - 0x00, 0x01, 0x05, 0x05, 0xb9 }; - msgb_avp_put_msgt(msg, VENDOR_ERICSSON, ERIC_CTRLMSG_TCRQ); + msgb_avp_put_msgt(msg, VENDOR_ERICSSON, ERIC_CTRLMSG_ALTCRQ); msgb_avp_put_digest(msg); - msgb_avp_put(msg, VENDOR_ERICSSON, AVP_ERIC_TRANSP_CFG, - tcg, sizeof(tcg), true); + msgb_avp_put_u32(msg, VENDOR_IETF, AVP_ERIC_ABIS_LO_MODE, + 0x0, true); /* SingleTimeslot */ msg->dst = l2c; return l2tp_msgb_tx(msg); } -int l2tp_tx_altc_rq(struct l2tpd_session *l2s) +int l2tp_tx_altc_rq_superchannel(struct l2tpd_connection *l2c) { struct msgb *msg = l2tp_msgb_alloc(); - /* FIXME: use pointer instead of this call */ - struct l2tpd_connection *l2c = l2tpd_cc_find_by_l_cc_id(l2i, l2s->l_sess_id); - const uint8_t tcsc[] = { 2, - 0, 0, 0, - 62, 62, 0 }; + const uint8_t tcsc[] = { + 2, /* number of transport config bundling group */ + 1, 1, 0x0, /* TEI from 1 to 1 to SC 0 */ + 62, 62, 0x0}; /* TEI from 62 to 62 to SC 0 */ msgb_avp_put_msgt(msg, VENDOR_ERICSSON, ERIC_CTRLMSG_ALTCRQ); msgb_avp_put_digest(msg); + msgb_avp_put_u32(msg, VENDOR_IETF, AVP_ERIC_ABIS_LO_MODE, + 0x1, true); /* Superchannel */ msgb_avp_put(msg, VENDOR_ERICSSON, AVP_ERIC_TEI_TO_SC_MAP, tcsc, sizeof(tcsc), true); diff --git a/siu/l2tp/l2tpd_packet.h b/siu/l2tp/l2tpd_packet.h index 8c50bf6..3ebf615 100644 --- a/siu/l2tp/l2tpd_packet.h +++ b/siu/l2tp/l2tpd_packet.h @@ -9,7 +9,8 @@ int l2tp_tx_scc_rp(struct l2tpd_connection *l2c); int l2tp_tx_stop_ccn(struct l2tpd_connection *l2c); int l2tp_tx_stop_ccn_msg(struct msgb *old) int l2tp_tx_tc_rq(struct l2tpd_connection *l2c); -int l2tp_tx_altc_rq(struct l2tpd_connection *l2c); +int l2tp_tx_altc_rq_superchannel(struct l2tpd_connection *l2c); +int l2tp_tx_altc_rq_timeslot(struct l2tpd_connection *l2c); int l2tp_tx_ack(struct l2tpd_connection *l2c); /* session management */ From 1e7e8dedffb30f357098140b586e2831ff2837ce Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Tue, 25 Oct 2016 15:06:42 +0200 Subject: [PATCH 067/133] l2tpd_packet: fix forgotten ; --- siu/l2tp/l2tpd_packet.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/siu/l2tp/l2tpd_packet.h b/siu/l2tp/l2tpd_packet.h index 3ebf615..85c271a 100644 --- a/siu/l2tp/l2tpd_packet.h +++ b/siu/l2tp/l2tpd_packet.h @@ -7,7 +7,7 @@ struct l2tpd_session; /* control connection management */ int l2tp_tx_scc_rp(struct l2tpd_connection *l2c); int l2tp_tx_stop_ccn(struct l2tpd_connection *l2c); -int l2tp_tx_stop_ccn_msg(struct msgb *old) +int l2tp_tx_stop_ccn_msg(struct msgb *old); int l2tp_tx_tc_rq(struct l2tpd_connection *l2c); int l2tp_tx_altc_rq_superchannel(struct l2tpd_connection *l2c); int l2tp_tx_altc_rq_timeslot(struct l2tpd_connection *l2c); From a0d08a8995d70644a5d71e6671f0fcef4ad66d7e Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Tue, 25 Oct 2016 15:14:58 +0200 Subject: [PATCH 068/133] l2tpd_data/l2tpd_sess_alloc: setup fsm for session --- siu/l2tp/l2tpd_data.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/siu/l2tp/l2tpd_data.c b/siu/l2tp/l2tpd_data.c index 3b069e7..49f6797 100644 --- a/siu/l2tp/l2tpd_data.c +++ b/siu/l2tp/l2tpd_data.c @@ -86,10 +86,13 @@ struct l2tpd_session * l2tpd_sess_alloc(struct l2tpd_connection *conn) { struct l2tpd_session *l2s = talloc_zero(conn, struct l2tpd_session); + char id_str[12] = {0}; l2s->l_sess_id = conn->next_l_sess_id++; + snprintf(id_str, 12, "%d", l2s->l_sess_id); llist_add(&l2s->list, &conn->sessions); + l2s->fsm = osmo_fsm_inst_alloc(&l2tp_ic_fsm, l2s, l2s, LOGL_DEBUG, id_str); return l2s; } From 4fa5b2d1a2921f930fb91f144283e0e799f69b66 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Tue, 25 Oct 2016 15:15:13 +0200 Subject: [PATCH 069/133] l2tpd_packet: improve log messages for rx_ic_rq --- siu/l2tp/l2tpd_packet.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index e172ed5..b1f9e44 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -553,16 +553,24 @@ static int rx_ic_rq(struct l2tpd_connection *l2cc, struct msgb *msg, struct avps if (!l2cc) return -1; - if (avpp_val_u32(ap, VENDOR_IETF, AVP_IETF_REM_SESS_ID, &r_sess_id)) + if (avpp_val_u32(ap, VENDOR_IETF, AVP_IETF_REM_SESS_ID, &r_sess_id)) { + LOGP(DL2TP, LOGL_ERROR, "ccid %d: Missing AVP REM_SESS_ID\n", + l2cc->local.ccid); return -1; - if (avpp_val_u32(ap, VENDOR_IETF, AVP_IETF_LOC_SESS_ID, &l_sess_id)) + } + if (avpp_val_u32(ap, VENDOR_IETF, AVP_IETF_LOC_SESS_ID, &l_sess_id)) { + LOGP(DL2TP, LOGL_ERROR, "ccid %d: Missing AVP LOC_SESS_ID\n", + l2cc->local.ccid); return -1; + } if (r_sess_id == 0) { l2s = l2tpd_sess_alloc(l2cc); l2s->r_sess_id = l_sess_id; avpp_val_u16(ap, VENDOR_IETF, AVP_IETF_PW_TYPE, &l2s->pw_type); } else { + LOGP(DL2TP, LOGL_NOTICE, "ccid %d: Received rx_ic_rq for already known session %u\n", + l2cc->local.ccid, r_sess_id); l2s = l2tpd_sess_find_by_l_s_id(l2cc, r_sess_id); if (!l2s) { LOGP(DL2TP, LOGL_ERROR, "NoSession %u\n", From 13cc5e1d0ae9f8bfd017e69c65703bb57570f624 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Tue, 25 Oct 2016 15:58:42 +0200 Subject: [PATCH 070/133] l2tpd_packet: add avpp_val_u8() to complete api for avpp --- siu/l2tp/l2tpd_packet.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index b1f9e44..565270a 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -141,6 +141,19 @@ int avpp_val_u16(struct avps_parsed *avps, uint16_t vendor_id, uint16_t type, return 0; } +int avpp_val_u8(struct avps_parsed *avps, uint16_t vendor_id, uint16_t type, + uint8_t *u8) +{ + struct avp_parsed *avp = avps_parsed_find(avps, vendor_id, type); + if (!avp) + return -ENODEV; + if (avp->data_len < sizeof(*u8)) + return -EINVAL; + + *u8 = *((uint8_t *)avp->data); + return 0; +} + /* store an AVP at the end of the msg */ static int msgb_avp_put(struct msgb *msg, uint16_t vendor_id, uint16_t type, const uint8_t *data, uint16_t data_len, bool m_flag) From 20dc4e196bd2cc8d684b3facc4e7397bf2cb4f57 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Tue, 25 Oct 2016 15:59:35 +0200 Subject: [PATCH 071/133] l2tpd_packet: fix assigned connection id avp in header previous we sent the remote ccid in our assigned ccid avp --- siu/l2tp/l2tpd_packet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index 565270a..f19defe 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -324,7 +324,7 @@ int l2tp_tx_scc_rp(struct l2tpd_connection *l2c) msgb_avp_put_msgt(msg, VENDOR_IETF, IETF_CTRLMSG_SCCRP); msgb_avp_put_digest(msg); msgb_avp_put_u32(msg, VENDOR_IETF, AVP_IETF_AS_CTRL_CON_ID, - l2c->remote.ccid, true); + l2c->local.ccid, true); msgb_avp_put(msg, VENDOR_ERICSSON, AVP_ERIC_PROTO_VER, eric_ver3_only, sizeof(eric_ver3_only), true); msgb_avp_put(msg, VENDOR_IETF, AVP_IETF_HOST_NAME, From 54f5d5f08b88f7592b612096c32787e86708e8eb Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Tue, 25 Oct 2016 16:00:23 +0200 Subject: [PATCH 072/133] l2tpd_packet: use decimal sapis --- siu/l2tp/l2tpd_packet.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index f19defe..63f25f3 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -383,21 +383,21 @@ int l2tp_tx_tc_rq(struct l2tpd_connection *l2c) /* first transport group */ 0x11, /* tc group id */ 0x02, /* number of sapis */ - 0x00, 0x62, /* SAPIs */ + 00, 62, /* SAPIs */ 172, 23, 42, 3, /* IP */ 0x2e, 0x01, 0x5, 0x1, 0x2c, /* dscp, crc32, bundling timeout, max packet size */ /* second transport group */ 0x06, /* tc group id */ 0x02, /* number of sapis */ - 0x0a, 0x0b, /* SAPIs */ + 10, 11, /* SAPIs */ 172, 23, 42, 3, /* IP */ 0x08, 0x01, 0x5, 0x1, 0x2c, /* dscp, crc32, bundling timeout, max packet size */ /* third transport group */ 0x08, /* tc group id */ 0x01, /* number of sapis */ - 0x0c, /* SAPIs */ + 12, /* SAPIs */ 172, 23, 42, 3, /* IP */ 0x22, 0x01, 0x5, 0x1, 0x2c, /* dscp, crc32, bundling timeout, max packet size */ }; From 5a221a0bde42caa0acef370a59829750c4dd6b19 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Tue, 25 Oct 2016 16:01:46 +0200 Subject: [PATCH 073/133] l2tpd_packet: add l2tpd_connection to ericsson receive functions As already done to ietf receive function, we need the context of a l2tpd_connection --- siu/l2tp/l2tpd_packet.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index 63f25f3..51d037e 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -645,7 +645,7 @@ static int l2tp_rcvmsg_control_ietf(struct l2tpd_connection *l2c, * Ericsson specific messages ***********************************************************************/ -static int rx_eri_tcrp(struct msgb *msg, struct avps_parsed *ap) +static int rx_eri_tcrp(struct l2tpd_connection *l2c, struct msgb *msg, struct avps_parsed *ap) { struct l2tp_control_hdr *ch = msgb_l2tph(msg); struct l2tpd_connection *l2cc = l2tpd_cc_find_by_l_cc_id(l2i, ch->ccid); @@ -655,7 +655,7 @@ static int rx_eri_tcrp(struct msgb *msg, struct avps_parsed *ap) return 0; } -static int rx_eri_altcrp(struct msgb *msg, struct avps_parsed *ap) +static int rx_eri_altcrp(struct l2tpd_connection *l2c, struct msgb *msg, struct avps_parsed *ap) { struct l2tp_control_hdr *ch = msgb_l2tph(msg); struct l2tpd_connection *l2cc = l2tpd_cc_find_by_l_cc_id(l2i, ch->ccid); @@ -672,9 +672,9 @@ static int l2tp_rcvmsg_control_ericsson(struct l2tpd_connection *l2c, { switch (msg_type) { case ERIC_CTRLMSG_TCRP: - return rx_eri_tcrp(msg, ap); + return rx_eri_tcrp(l2c, msg, ap); case ERIC_CTRLMSG_ALTCRP: - return rx_eri_altcrp(msg, ap); + return rx_eri_altcrp(l2c, msg, ap); default: LOGP(DL2TP, LOGL_ERROR, "Unknown/Unhandled Ericsson Control " "Message Type 0x%04x\n", msg_type); From 2e48578587af5b1af64f8afd5e9450ae1172d594 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Tue, 25 Oct 2016 16:02:57 +0200 Subject: [PATCH 074/133] l2tpd_packet: save remote_end_id into session the remote end id is used as bundling group id. To connect session with sockets later we need to know what data is tunneled into this session --- siu/l2tp/l2tpd.h | 3 +++ siu/l2tp/l2tpd_packet.c | 1 + 2 files changed, 4 insertions(+) diff --git a/siu/l2tp/l2tpd.h b/siu/l2tp/l2tpd.h index 4f46427..135c004 100644 --- a/siu/l2tp/l2tpd.h +++ b/siu/l2tp/l2tpd.h @@ -62,6 +62,9 @@ struct l2tpd_session { uint32_t next_tx_seq_nr; /* seq nr of expected next Rx frame */ uint32_t next_rx_seq_nr; + /* remote end id. TCRQ & ALTRQ configures the bundling ids to TEI/SAPIs. + * In ICRQ the remote end id is used as bundling id */ + uint8_t remote_end_id; /* finite state machine for call/session */ struct osmo_fsm_inst *fsm; diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index 51d037e..215f869 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -581,6 +581,7 @@ static int rx_ic_rq(struct l2tpd_connection *l2cc, struct msgb *msg, struct avps l2s = l2tpd_sess_alloc(l2cc); l2s->r_sess_id = l_sess_id; avpp_val_u16(ap, VENDOR_IETF, AVP_IETF_PW_TYPE, &l2s->pw_type); + avpp_val_u8(ap, VENDOR_IETF, AVP_IETF_REMOTE_END, &l2s->remote_end_id); } else { LOGP(DL2TP, LOGL_NOTICE, "ccid %d: Received rx_ic_rq for already known session %u\n", l2cc->local.ccid, r_sess_id); From 4b4acb69c3a265cbf75122eb67ebe4a7a2e363ae Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Tue, 25 Oct 2016 16:04:13 +0200 Subject: [PATCH 075/133] l2tpd_fsm: only sent SCC RP when received a SCC RQ --- siu/l2tp/l2tpd_fsm.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/siu/l2tp/l2tpd_fsm.c b/siu/l2tp/l2tpd_fsm.c index 27ae966..18caa39 100644 --- a/siu/l2tp/l2tpd_fsm.c +++ b/siu/l2tp/l2tpd_fsm.c @@ -1,7 +1,9 @@ #include +#include "l2tpd.h" #include "l2tpd_packet.h" +#include "l2tpd_data.h" #include "l2tpd_fsm.h" #define S(x) (1 << (x)) @@ -9,8 +11,13 @@ static void l2tp_ctrl_s_init(struct osmo_fsm_inst *fi, uint32_t event, void *data) { struct l2tpd_connection *l2c = fi->priv; - if (!l2tp_tx_scc_rp(l2c)) { - osmo_fsm_inst_state_chg(fi, L2CC_S_WAIT_CTL_CONN, 0, 0); + + switch (event) { + case L2CC_E_RX_SCCRQ: + if (!l2tp_tx_scc_rp(l2c)) { + osmo_fsm_inst_state_chg(fi, L2CC_S_WAIT_CTL_CONN, 0, 0); + } + break; } } From d670f094ac514a1e2099fd74bd2479c9fceb1784 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Tue, 25 Oct 2016 16:04:42 +0200 Subject: [PATCH 076/133] l2tpd_fsm: jump over L2CC_S_ESTABLISHED L2CC_S_ESTABLISHED will used later a final state. But for know ignore this state and move over to WAIT_FOR_TXRP --- siu/l2tp/l2tpd_fsm.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/siu/l2tp/l2tpd_fsm.c b/siu/l2tp/l2tpd_fsm.c index 18caa39..c6ade65 100644 --- a/siu/l2tp/l2tpd_fsm.c +++ b/siu/l2tp/l2tpd_fsm.c @@ -32,8 +32,8 @@ static void l2tp_ctrl_s_wait_ctl_conn(struct osmo_fsm_inst *fi, uint32_t event, /* FIXME: teardown */ break; case L2CC_E_RX_SCCCN: - l2tp_tx_ack(l2c); - osmo_fsm_inst_state_chg(fi, L2CC_S_ESTABLISHED, 0, 0); + if (!l2tp_tx_tc_rq(l2c)) + osmo_fsm_inst_state_chg(fi, L2CC_S_WAIT_FOR_TCRP, 0, 0); break; case L2CC_E_RX_STOP_CCN: l2tp_tx_ack(l2c); @@ -111,6 +111,7 @@ static const struct osmo_fsm_state l2tp_ctrl_states[] = { S(L2CC_E_LOCAL_CLOSE_REQ) | S(L2CC_E_RX_STOP_CCN), .out_state_mask = S(L2CC_S_ESTABLISHED) | + S(L2CC_S_WAIT_FOR_TCRP) | S(L2CC_S_INIT), .name = "WAIT_CTL_CONN", .action = l2tp_ctrl_s_wait_ctl_conn, From b34d874def0380acf5816a636e67bf636cc548ec Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Tue, 25 Oct 2016 16:12:11 +0200 Subject: [PATCH 077/133] l2tpd_fsm/session: add basic logic into states and sent out packets --- siu/l2tp/l2tpd_fsm.c | 49 ++++++++++++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/siu/l2tp/l2tpd_fsm.c b/siu/l2tp/l2tpd_fsm.c index c6ade65..3c48fc0 100644 --- a/siu/l2tp/l2tpd_fsm.c +++ b/siu/l2tp/l2tpd_fsm.c @@ -150,24 +150,6 @@ struct osmo_fsm l2tp_cc_fsm = { .event_names = l2tp_cc_events, }; -static void l2tp_ic_s_init(struct osmo_fsm_inst *fi, uint32_t event, void *data) -{ - /* ICRQ was received */ - OSMO_ASSERT(event == L2IC_E_RX_ICRQ); - /* FIXME: Send ICRP */ - osmo_fsm_inst_state_chg(fi, L2IC_S_WAIT_CONN, 0, 0); -} - -static void l2tp_ic_s_wait_conn(struct osmo_fsm_inst *fi, uint32_t event, void *data) -{ - /* ICCN wsa received */ - OSMO_ASSERT(event == L2IC_E_RX_ICCN); - osmo_fsm_inst_state_chg(fi, L2IC_S_ESTABLISHED, 0, 0); -} - -static void l2tp_ic_s_established(struct osmo_fsm_inst *fi, uint32_t event, void *data) -{ -} static void l2tp_ic_allstate(struct osmo_fsm_inst *fi, uint32_t event, void *data) { @@ -182,6 +164,37 @@ static void l2tp_ic_allstate(struct osmo_fsm_inst *fi, uint32_t event, void *dat } } +static void l2tp_ic_s_init(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + struct l2tpd_session *l2s = fi->priv; + + switch (event) { + case L2IC_E_RX_ICRQ: + if (!l2tp_tx_ic_rp(l2s)) + osmo_fsm_inst_state_chg(fi, L2IC_S_WAIT_CONN, 0, 0); + break; + } + l2tp_ic_allstate(fi, event, data); +} + +static void l2tp_ic_s_wait_conn(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + struct l2tpd_session *l2s = (struct l2tpd_session *) fi->priv; + struct l2tpd_connection *l2c = l2tpd_cc_find_by_l_cc_id(l2i, l2s->l_sess_id); + + switch (event) { + case L2IC_E_RX_ICCN: + /* ICCN wsa received */ + if (!l2tp_tx_ack(l2c)) + osmo_fsm_inst_state_chg(fi, L2IC_S_ESTABLISHED, 0, 0); + } +} + +static void l2tp_ic_s_established(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ +} + + static const struct value_string l2tp_ic_names[] = { { L2IC_E_RX_ICRQ, "RX-InCall-Req" }, { L2IC_E_RX_ICCN, "RX-InCall-Connect" }, From 52255ec31c1cdcffe1fe0b226ddf76ff74294799 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Tue, 25 Oct 2016 16:16:21 +0200 Subject: [PATCH 078/133] l2tpd_packet: implement rx_eri_tcrp() dispatch an event to the fsm (L2CC_E_RX_TCRP) when result == 0 --- siu/l2tp/l2tpd_packet.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index 215f869..bc1f9a3 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -651,8 +651,23 @@ static int rx_eri_tcrp(struct l2tpd_connection *l2c, struct msgb *msg, struct av struct l2tp_control_hdr *ch = msgb_l2tph(msg); struct l2tpd_connection *l2cc = l2tpd_cc_find_by_l_cc_id(l2i, ch->ccid); + uint16_t avp_result = 0; + if (!l2cc) return -1; + + if (avpp_val_u16(ap, VENDOR_IETF, AVP_IETF_RESULT_CODE, &avp_result)) { + LOGP(DL2TP, LOGL_ERROR, "TXRP doesnt contain a result code. Aborting control connection.\n"); + osmo_fsm_inst_dispatch(l2c->fsm, L2CC_E_LOCAL_CLOSE_REQ, msg); + } + + if (avp_result) { + LOGP(DL2TP, LOGL_ERROR, "TXRP returned result code %d instead of 0. Aborting control connection.\n", + avp_result); + /* FIXME: result message */ + osmo_fsm_inst_dispatch(l2c->fsm, L2CC_E_LOCAL_CLOSE_REQ, msg); + } + osmo_fsm_inst_dispatch(l2cc->fsm, L2CC_E_RX_TCRP, msg); return 0; } From ce52db0a435361cf72b1dd810f7918637674face Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Tue, 25 Oct 2016 16:28:48 +0200 Subject: [PATCH 079/133] l2tpd_packet/rx_eri_tcrp: remove old lookup of l2tp_connection by ccid already given as function argument --- siu/l2tp/l2tpd_packet.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index bc1f9a3..266b21b 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -648,12 +648,9 @@ static int l2tp_rcvmsg_control_ietf(struct l2tpd_connection *l2c, static int rx_eri_tcrp(struct l2tpd_connection *l2c, struct msgb *msg, struct avps_parsed *ap) { - struct l2tp_control_hdr *ch = msgb_l2tph(msg); - struct l2tpd_connection *l2cc = l2tpd_cc_find_by_l_cc_id(l2i, ch->ccid); - uint16_t avp_result = 0; - if (!l2cc) + if (!l2c) return -1; if (avpp_val_u16(ap, VENDOR_IETF, AVP_IETF_RESULT_CODE, &avp_result)) { @@ -667,7 +664,7 @@ static int rx_eri_tcrp(struct l2tpd_connection *l2c, struct msgb *msg, struct av /* FIXME: result message */ osmo_fsm_inst_dispatch(l2c->fsm, L2CC_E_LOCAL_CLOSE_REQ, msg); } - osmo_fsm_inst_dispatch(l2cc->fsm, L2CC_E_RX_TCRP, msg); + osmo_fsm_inst_dispatch(l2c->fsm, L2CC_E_RX_TCRP, msg); return 0; } From 2ec61137ef46b24ea151dcfba775b52b28f243d2 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Tue, 25 Oct 2016 16:47:21 +0200 Subject: [PATCH 080/133] l2tpd_fsm: implement hello receiver --- siu/l2tp/l2tpd_fsm.h | 2 ++ siu/l2tp/l2tpd_packet.c | 13 +++++++++++++ 2 files changed, 15 insertions(+) diff --git a/siu/l2tp/l2tpd_fsm.h b/siu/l2tp/l2tpd_fsm.h index 9f8e507..48d8890 100644 --- a/siu/l2tp/l2tpd_fsm.h +++ b/siu/l2tp/l2tpd_fsm.h @@ -17,6 +17,8 @@ enum l2tpd_ctrl_con_event { L2CC_E_RX_STOP_CCN, /* Received Transport configuration Reply */ L2CC_E_RX_TCRP, + /* Received a HELLO / Keepalive */ + L2CC_E_RX_HELLO, }; enum l2tpd_in_call_event { diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index 266b21b..139db25 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -557,6 +557,17 @@ static int rx_stop_ccn(struct l2tpd_connection *l2cc, struct msgb *msg, struct a return 0; } +/* Incoming Keepalive / Hello from SIU */ +static int rx_hello(struct l2tpd_connection *l2cc, struct msgb *msg, struct avps_parsed *ap) +{ + if (!l2cc) + return -1; + + osmo_fsm_inst_dispatch(l2cc->fsm, L2CC_E_RX_HELLO, msg); + return 0; +} + + /* Incoming "Incoming Call Request" from SIU */ static int rx_ic_rq(struct l2tpd_connection *l2cc, struct msgb *msg, struct avps_parsed *ap) { @@ -635,6 +646,8 @@ static int l2tp_rcvmsg_control_ietf(struct l2tpd_connection *l2c, return rx_ic_cn(l2c, msg, ap); case IETF_CTRLMSG_CDN: return rx_cdn(l2c, msg, ap); + case IETF_CTRLMSG_HELLO: + return rx_hello(l2c, msg, ap); default: LOGP(DL2TP, LOGL_ERROR, "Unknown/Unhandled IETF Control " "Message Type 0x%04x\n", msg_type); From fb52b9a5df3be595f8fe02027edd604a86a2e4fa Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Tue, 25 Oct 2016 16:49:36 +0200 Subject: [PATCH 081/133] l2tpd_fsm: add an allstate_action for HELLO LOCAL_CLOSE_REQ RX_STOP_CCN --- siu/l2tp/l2tpd_fsm.c | 41 +++++++++++++---------------------------- 1 file changed, 13 insertions(+), 28 deletions(-) diff --git a/siu/l2tp/l2tpd_fsm.c b/siu/l2tp/l2tpd_fsm.c index 3c48fc0..e2ab620 100644 --- a/siu/l2tp/l2tpd_fsm.c +++ b/siu/l2tp/l2tpd_fsm.c @@ -26,19 +26,10 @@ static void l2tp_ctrl_s_wait_ctl_conn(struct osmo_fsm_inst *fi, uint32_t event, struct l2tpd_connection *l2c = fi->priv; switch (event) { - case L2CC_E_LOCAL_CLOSE_REQ: - l2tp_tx_stop_ccn(l2c); - osmo_fsm_inst_state_chg(fi, L2CC_S_INIT, 0, 0); - /* FIXME: teardown */ - break; case L2CC_E_RX_SCCCN: if (!l2tp_tx_tc_rq(l2c)) osmo_fsm_inst_state_chg(fi, L2CC_S_WAIT_FOR_TCRP, 0, 0); break; - case L2CC_E_RX_STOP_CCN: - l2tp_tx_ack(l2c); - /* FIXME: tear down whole l2c */ - break; } } @@ -56,15 +47,6 @@ static void l2tp_ctrl_s_wait_for_tcrp(struct osmo_fsm_inst *fi, uint32_t event, struct l2tpd_connection *l2c = fi->priv; switch (event) { - case L2CC_E_LOCAL_CLOSE_REQ: - l2tp_tx_stop_ccn(l2c); - osmo_fsm_inst_state_chg(fi, L2CC_S_INIT, 0, 0); - /* FIXME: teardown instead of INIT */ - break; - case L2CC_E_RX_STOP_CCN: - l2tp_tx_ack(l2c); - /* FIXME: tear down whole l2c */ - break; case L2CC_E_RX_TCRP: l2tp_tx_ack(l2c); osmo_fsm_inst_state_chg(fi, L2CC_S_ESTABLISHED_CONFIGURED, 0, 0); @@ -73,6 +55,10 @@ static void l2tp_ctrl_s_wait_for_tcrp(struct osmo_fsm_inst *fi, uint32_t event, } static void l2tp_ctrl_s_established_configured(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ +} + +static void l2tp_ctrl_allstate(struct osmo_fsm_inst *fi, uint32_t event, void *data) { struct l2tpd_connection *l2c = fi->priv; @@ -86,6 +72,9 @@ static void l2tp_ctrl_s_established_configured(struct osmo_fsm_inst *fi, uint32_ l2tp_tx_ack(l2c); /* FIXME: tear down whole l2c */ break; + case L2CC_E_RX_HELLO: + l2tp_tx_ack(l2c); + break; } } @@ -107,9 +96,7 @@ static const struct osmo_fsm_state l2tp_ctrl_states[] = { .action = l2tp_ctrl_s_init, }, [L2CC_S_WAIT_CTL_CONN] = { - .in_event_mask = S(L2CC_E_RX_SCCCN) | - S(L2CC_E_LOCAL_CLOSE_REQ) | - S(L2CC_E_RX_STOP_CCN), + .in_event_mask = S(L2CC_E_RX_SCCCN), .out_state_mask = S(L2CC_S_ESTABLISHED) | S(L2CC_S_WAIT_FOR_TCRP) | S(L2CC_S_INIT), @@ -117,25 +104,21 @@ static const struct osmo_fsm_state l2tp_ctrl_states[] = { .action = l2tp_ctrl_s_wait_ctl_conn, }, [L2CC_S_ESTABLISHED] = { - .in_event_mask = S(L2CC_E_LOCAL_CLOSE_REQ) | - S(L2CC_E_RX_STOP_CCN), + .in_event_mask = 0, .out_state_mask = S(L2CC_S_WAIT_FOR_TCRP) | S(L2CC_S_INIT), .name = "ESTABLISHED", .action = l2tp_ctrl_s_established, }, [L2CC_S_WAIT_FOR_TCRP] = { - .in_event_mask = S(L2CC_E_LOCAL_CLOSE_REQ) | - S(L2CC_E_RX_STOP_CCN) | - S(L2CC_E_RX_TCRP), + .in_event_mask = S(L2CC_E_RX_TCRP), .out_state_mask = S(L2CC_S_ESTABLISHED_CONFIGURED) | S(L2CC_S_INIT), .name = "WAIT_FOR_TCRP", .action = l2tp_ctrl_s_wait_for_tcrp, }, [L2CC_S_ESTABLISHED_CONFIGURED] = { - .in_event_mask = S(L2CC_E_LOCAL_CLOSE_REQ) | - S(L2CC_E_RX_STOP_CCN), + .in_event_mask = 0, .out_state_mask = S(L2CC_S_INIT), .name = "ESTABLISHED_CONFIGURED", .action = l2tp_ctrl_s_established_configured, @@ -148,6 +131,8 @@ struct osmo_fsm l2tp_cc_fsm = { .num_states = ARRAY_SIZE(l2tp_ctrl_states), .log_subsys = 0, .event_names = l2tp_cc_events, + .allstate_event_mask = S(L2CC_E_RX_HELLO) | S(L2CC_E_LOCAL_CLOSE_REQ) | S(L2CC_E_RX_STOP_CCN), + .allstate_action = l2tp_ctrl_allstate, }; From 79f8080193109663e3014b9325698b08a345a9d5 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Wed, 26 Oct 2016 04:15:37 +0200 Subject: [PATCH 082/133] l2tpd: log error message of recvfrom() --- siu/l2tp/l2tpd.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/siu/l2tp/l2tpd.c b/siu/l2tp/l2tpd.c index f231ad5..e864eeb 100644 --- a/siu/l2tp/l2tpd.c +++ b/siu/l2tp/l2tpd.c @@ -33,8 +33,10 @@ static int l2tp_ip_read_cb(struct osmo_fd *ofd, unsigned int what) /* actually read the message from the raw IP socket */ rc = recvfrom(ofd->fd, msg->data, msg->data_len, 0, (struct sockaddr *) &ss, &ss_len); - if (rc < 0) + if (rc < 0) { + LOGP(DL2TP, LOGL_ERROR, "recvfrom() failed: %s\n", strerror(errno)); return rc; + } msgb_put(msg, rc); msg->l1h = msg->data; /* l1h = ip header */ From 64471b67999ddf12290fb99a788c911550021f73 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Wed, 26 Oct 2016 04:17:19 +0200 Subject: [PATCH 083/133] l2tpd_packet: fix correct hardcoded ip address for receiving SAPIs the ip must exact match the from of the actually connection otherwise the SIU will try to reach the IP via SCCRQ to create a secondary connection --- siu/l2tp/l2tpd_packet.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index 139db25..581b356 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -384,21 +384,21 @@ int l2tp_tx_tc_rq(struct l2tpd_connection *l2c) 0x11, /* tc group id */ 0x02, /* number of sapis */ 00, 62, /* SAPIs */ - 172, 23, 42, 3, /* IP */ + 172, 30, 42, 3, /* IP */ 0x2e, 0x01, 0x5, 0x1, 0x2c, /* dscp, crc32, bundling timeout, max packet size */ /* second transport group */ 0x06, /* tc group id */ 0x02, /* number of sapis */ 10, 11, /* SAPIs */ - 172, 23, 42, 3, /* IP */ + 172, 30, 42, 3, /* IP */ 0x08, 0x01, 0x5, 0x1, 0x2c, /* dscp, crc32, bundling timeout, max packet size */ /* third transport group */ 0x08, /* tc group id */ 0x01, /* number of sapis */ 12, /* SAPIs */ - 172, 23, 42, 3, /* IP */ + 172, 30, 42, 3, /* IP */ 0x22, 0x01, 0x5, 0x1, 0x2c, /* dscp, crc32, bundling timeout, max packet size */ }; From 1f9b1d1a8678f55bf98b3b3e4a7e94da04c736f9 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Thu, 27 Oct 2016 03:53:31 +0200 Subject: [PATCH 084/133] l2tpd: correct sequence number for acks *FIXME* --- siu/l2tp/l2tpd_packet.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index 581b356..73fde2a 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -279,7 +279,7 @@ static int digest_avp_update(struct msgb *msg) return 0; } -static int l2tp_msgb_tx(struct msgb *msg) +static int l2tp_msgb_tx(struct msgb *msg, int not_ack) { struct l2tpd_connection *l2c = msg->dst; struct l2tp_control_hdr *l2h; @@ -291,8 +291,12 @@ static int l2tp_msgb_tx(struct msgb *msg) l2h->ver = htons(T_BIT|L_BIT|S_BIT| 0x3); l2h->length = htons(msgb_length(msg)); l2h->ccid = htonl(l2c->remote.ccid); - l2h->Ns = htons(l2c->next_tx_seq_nr++); l2h->Nr = htons(l2c->next_rx_seq_nr); + /* only acks dont increase seq */ + if (not_ack) + l2h->Ns = htons(l2c->next_tx_seq_nr++); + else + l2h->Ns = htons(l2c->next_tx_seq_nr - 1); /* then insert/patch the message digest AVP */ digest_avp_update(msg); @@ -337,7 +341,7 @@ int l2tp_tx_scc_rp(struct l2tpd_connection *l2c) 0x0006, true); msg->dst = l2c; - return l2tp_msgb_tx(msg); + return l2tp_msgb_tx(msg, 1); } int l2tp_tx_stop_ccn(struct l2tpd_connection *l2c) @@ -349,7 +353,7 @@ int l2tp_tx_stop_ccn(struct l2tpd_connection *l2c) msgb_avp_put_digest(msg); msg->dst = l2c; - return l2tp_msgb_tx(msg); + return l2tp_msgb_tx(msg, 1); } int l2tp_tx_stop_ccn_msg(struct msgb *old) @@ -370,7 +374,7 @@ int l2tp_tx_stop_ccn_msg(struct msgb *old) msgb_avp_put_digest(msg); msg->dst = &l2c; - return l2tp_msgb_tx(msg); + return l2tp_msgb_tx(msg, 1); } int l2tp_tx_tc_rq(struct l2tpd_connection *l2c) @@ -408,7 +412,7 @@ int l2tp_tx_tc_rq(struct l2tpd_connection *l2c) tcg, sizeof(tcg), true); msg->dst = l2c; - return l2tp_msgb_tx(msg); + return l2tp_msgb_tx(msg, 1); } int l2tp_tx_altc_rq_timeslot(struct l2tpd_connection *l2c) @@ -421,7 +425,7 @@ int l2tp_tx_altc_rq_timeslot(struct l2tpd_connection *l2c) 0x0, true); /* SingleTimeslot */ msg->dst = l2c; - return l2tp_msgb_tx(msg); + return l2tp_msgb_tx(msg, 1); } int l2tp_tx_altc_rq_superchannel(struct l2tpd_connection *l2c) @@ -440,7 +444,7 @@ int l2tp_tx_altc_rq_superchannel(struct l2tpd_connection *l2c) tcsc, sizeof(tcsc), true); msg->dst = l2c; - return l2tp_msgb_tx(msg); + return l2tp_msgb_tx(msg, 1); } int l2tp_tx_ic_rp(struct l2tpd_session *l2s) @@ -466,7 +470,7 @@ int l2tp_tx_ic_rp(struct l2tpd_session *l2s) 0x0002, true); msg->dst = l2c; - return l2tp_msgb_tx(msg); + return l2tp_msgb_tx(msg, 1); } int l2tp_tx_ack(struct l2tpd_connection *l2c) @@ -478,7 +482,7 @@ int l2tp_tx_ack(struct l2tpd_connection *l2c) msgb_avp_put_digest(msg); msg->dst = l2c; - return l2tp_msgb_tx(msg); + return l2tp_msgb_tx(msg, 0); } int l2tp_tx_hello(struct l2tpd_session *l2s) @@ -491,7 +495,7 @@ int l2tp_tx_hello(struct l2tpd_session *l2s) msgb_avp_put_digest(msg); msg->dst = l2c; - return l2tp_msgb_tx(msg); + return l2tp_msgb_tx(msg, 1); } /* Incoming "Start Control-Connection Request" from SIU */ From 89c41159b85a3677ea669471579c932c6dbc1a10 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Thu, 27 Oct 2016 03:55:14 +0200 Subject: [PATCH 085/133] l2tpd: correct length of AVP_ERIC_ABIS_LO_MODE --- siu/l2tp/l2tpd_packet.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index 73fde2a..b648b36 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -421,7 +421,7 @@ int l2tp_tx_altc_rq_timeslot(struct l2tpd_connection *l2c) msgb_avp_put_msgt(msg, VENDOR_ERICSSON, ERIC_CTRLMSG_ALTCRQ); msgb_avp_put_digest(msg); - msgb_avp_put_u32(msg, VENDOR_IETF, AVP_ERIC_ABIS_LO_MODE, + msgb_avp_put_u8(msg, VENDOR_ERICSSON, AVP_ERIC_ABIS_LO_MODE, 0x0, true); /* SingleTimeslot */ msg->dst = l2c; @@ -438,7 +438,7 @@ int l2tp_tx_altc_rq_superchannel(struct l2tpd_connection *l2c) msgb_avp_put_msgt(msg, VENDOR_ERICSSON, ERIC_CTRLMSG_ALTCRQ); msgb_avp_put_digest(msg); - msgb_avp_put_u32(msg, VENDOR_IETF, AVP_ERIC_ABIS_LO_MODE, + msgb_avp_put_u8(msg, VENDOR_ERICSSON, AVP_ERIC_ABIS_LO_MODE, 0x1, true); /* Superchannel */ msgb_avp_put(msg, VENDOR_ERICSSON, AVP_ERIC_TEI_TO_SC_MAP, tcsc, sizeof(tcsc), true); From 0ba51d59ff78d341a458966b8657a4f3da08868d Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Thu, 27 Oct 2016 03:57:02 +0200 Subject: [PATCH 086/133] l2tpd_packet: implement router_id based on a ip --- siu/l2tp/l2tpd_packet.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index b648b36..b7c9dcf 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -323,7 +323,8 @@ int l2tp_tx_scc_rp(struct l2tpd_connection *l2c) const uint8_t eric_ver3_only[12] = { 0,0,0,3, 0,0,0,0, 0,0,0,0 }; const uint8_t host_name[3] = { 'B', 'S', 'C' }; const uint8_t vendor_name[8] = { 'E', 'r', 'i', 'c', 's', 's', 'o', 'n' }; - const uint32_t router_id = 0xac1e2a05; + struct in_addr router_id; + inet_aton("172.30.42.3", &router_id); msgb_avp_put_msgt(msg, VENDOR_IETF, IETF_CTRLMSG_SCCRP); msgb_avp_put_digest(msg); @@ -335,8 +336,8 @@ int l2tp_tx_scc_rp(struct l2tpd_connection *l2c) host_name, sizeof(host_name), false); msgb_avp_put(msg, VENDOR_IETF, AVP_IETF_VENDOR_NAME, vendor_name, sizeof(vendor_name), false); - msgb_avp_put_u32(msg, VENDOR_IETF, AVP_IETF_ROUTER_ID, - router_id, false); + msgb_avp_put(msg, VENDOR_IETF, AVP_IETF_ROUTER_ID, + (uint8_t *)&router_id.s_addr, sizeof(router_id.s_addr), false); msgb_avp_put_u16(msg, VENDOR_IETF, AVP_IETF_PW_CAP_LIST, 0x0006, true); From 5bb921435820d1286f2e52c343db02aa2340ed21 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Thu, 27 Oct 2016 03:58:50 +0200 Subject: [PATCH 087/133] l2tpd_packet: implement rx_eri_altcrp() to push fsm --- siu/l2tp/l2tpd_packet.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index b7c9dcf..a8f0eee 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -688,11 +688,23 @@ static int rx_eri_tcrp(struct l2tpd_connection *l2c, struct msgb *msg, struct av static int rx_eri_altcrp(struct l2tpd_connection *l2c, struct msgb *msg, struct avps_parsed *ap) { - struct l2tp_control_hdr *ch = msgb_l2tph(msg); - struct l2tpd_connection *l2cc = l2tpd_cc_find_by_l_cc_id(l2i, ch->ccid); + uint16_t avp_result = 0; - if (!l2cc) + if (!l2c) return -1; + + if (avpp_val_u16(ap, VENDOR_IETF, AVP_IETF_RESULT_CODE, &avp_result)) { + LOGP(DL2TP, LOGL_ERROR, "ALTXRP doesnt contain a result code. Aborting control connection.\n"); + osmo_fsm_inst_dispatch(l2c->fsm, L2CC_E_LOCAL_CLOSE_REQ, msg); + } + + if (avp_result) { + LOGP(DL2TP, LOGL_ERROR, "ALTXRP returned result code %d instead of 0. Aborting control connection.\n", + avp_result); + /* FIXME: result message */ + osmo_fsm_inst_dispatch(l2c->fsm, L2CC_E_LOCAL_CLOSE_REQ, msg); + } + osmo_fsm_inst_dispatch(l2c->fsm, L2CC_E_RX_ALTCRP, msg); return 0; } From a34c2c189c92c1b1742c6de9a022bb09b48f72d3 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Thu, 27 Oct 2016 04:01:21 +0200 Subject: [PATCH 088/133] l2tpd: improve logmessage recvfrom() --- siu/l2tp/l2tpd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/siu/l2tp/l2tpd.c b/siu/l2tp/l2tpd.c index e864eeb..e729e27 100644 --- a/siu/l2tp/l2tpd.c +++ b/siu/l2tp/l2tpd.c @@ -34,7 +34,7 @@ static int l2tp_ip_read_cb(struct osmo_fd *ofd, unsigned int what) rc = recvfrom(ofd->fd, msg->data, msg->data_len, 0, (struct sockaddr *) &ss, &ss_len); if (rc < 0) { - LOGP(DL2TP, LOGL_ERROR, "recvfrom() failed: %s\n", strerror(errno)); + LOGP(DL2TP, LOGL_ERROR, "recievefrom failed %s\n", strerror(errno)); return rc; } msgb_put(msg, rc); From 05d94164b3209a796e71e54c5f465a52e08a0bba Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Thu, 27 Oct 2016 04:05:08 +0200 Subject: [PATCH 089/133] l2tpd: implement ALTCRP as states --- siu/l2tp/l2tpd_fsm.c | 22 +++++++++++++++++++++- siu/l2tp/l2tpd_fsm.h | 4 ++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/siu/l2tp/l2tpd_fsm.c b/siu/l2tp/l2tpd_fsm.c index e2ab620..7f2ac7e 100644 --- a/siu/l2tp/l2tpd_fsm.c +++ b/siu/l2tp/l2tpd_fsm.c @@ -48,6 +48,18 @@ static void l2tp_ctrl_s_wait_for_tcrp(struct osmo_fsm_inst *fi, uint32_t event, switch (event) { case L2CC_E_RX_TCRP: + l2tp_tx_altc_rq_timeslot(l2c); + osmo_fsm_inst_state_chg(fi, L2CC_S_WAIT_FOR_ALTCRP, 0, 0); + break; + } +} + +static void l2tp_ctrl_s_wait_for_altcrp(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + struct l2tpd_connection *l2c = fi->priv; + + switch (event) { + case L2CC_E_RX_ALTCRP: l2tp_tx_ack(l2c); osmo_fsm_inst_state_chg(fi, L2CC_S_ESTABLISHED_CONFIGURED, 0, 0); break; @@ -85,6 +97,7 @@ static const struct value_string l2tp_cc_events[] = { { L2CC_E_RX_SCCCN, "RX-SCCCN" }, { L2CC_E_RX_STOP_CCN, "RX-STOPCCN" }, { L2CC_E_RX_TCRP, "RX-TCRP" }, + { L2CC_E_RX_ALTCRP, "RX-ALTCRP" }, { 0, NULL } }; @@ -112,11 +125,18 @@ static const struct osmo_fsm_state l2tp_ctrl_states[] = { }, [L2CC_S_WAIT_FOR_TCRP] = { .in_event_mask = S(L2CC_E_RX_TCRP), - .out_state_mask = S(L2CC_S_ESTABLISHED_CONFIGURED) | + .out_state_mask = S(L2CC_S_WAIT_FOR_ALTCRP) | S(L2CC_S_INIT), .name = "WAIT_FOR_TCRP", .action = l2tp_ctrl_s_wait_for_tcrp, }, + [L2CC_S_WAIT_FOR_ALTCRP] = { + .in_event_mask = S(L2CC_E_RX_ALTCRP), + .out_state_mask = S(L2CC_S_ESTABLISHED_CONFIGURED) | + S(L2CC_S_INIT), + .name = "WAIT_FOR_ALTCRP", + .action = l2tp_ctrl_s_wait_for_altcrp, + }, [L2CC_S_ESTABLISHED_CONFIGURED] = { .in_event_mask = 0, .out_state_mask = S(L2CC_S_INIT), diff --git a/siu/l2tp/l2tpd_fsm.h b/siu/l2tp/l2tpd_fsm.h index 48d8890..082dffa 100644 --- a/siu/l2tp/l2tpd_fsm.h +++ b/siu/l2tp/l2tpd_fsm.h @@ -17,6 +17,8 @@ enum l2tpd_ctrl_con_event { L2CC_E_RX_STOP_CCN, /* Received Transport configuration Reply */ L2CC_E_RX_TCRP, + /* Received Abis Lower Transport configuration Reply */ + L2CC_E_RX_ALTCRP, /* Received a HELLO / Keepalive */ L2CC_E_RX_HELLO, }; @@ -48,6 +50,8 @@ enum l2tpd_ctrl_con_state { L2CC_S_ESTABLISHED, /* After we sent a TCRQ, waiting for TCRP */ L2CC_S_WAIT_FOR_TCRP, + /* After we sent a ALTTCRQ, waiting for ALTCRP */ + L2CC_S_WAIT_FOR_ALTCRP, /* We configured the SIU to start sessions */ L2CC_S_ESTABLISHED_CONFIGURED }; From 2ef52501925ee5e16bbcd9986da1f771a851acc4 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Thu, 27 Oct 2016 04:05:32 +0200 Subject: [PATCH 090/133] l2tpd_fsm: add RX-HELLO events --- siu/l2tp/l2tpd_fsm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/siu/l2tp/l2tpd_fsm.c b/siu/l2tp/l2tpd_fsm.c index 7f2ac7e..f1b6f00 100644 --- a/siu/l2tp/l2tpd_fsm.c +++ b/siu/l2tp/l2tpd_fsm.c @@ -98,6 +98,7 @@ static const struct value_string l2tp_cc_events[] = { { L2CC_E_RX_STOP_CCN, "RX-STOPCCN" }, { L2CC_E_RX_TCRP, "RX-TCRP" }, { L2CC_E_RX_ALTCRP, "RX-ALTCRP" }, + { L2CC_E_RX_HELLO, "RX-HELLO" }, { 0, NULL } }; From 3b84bcebc4fe4e7bad4e4a2fcd35c9a55640b070 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Thu, 27 Oct 2016 04:06:03 +0200 Subject: [PATCH 091/133] l2tpd_fsm: go to state INIT after L2CC_E_RX_STOP_CCN --- siu/l2tp/l2tpd_fsm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/siu/l2tp/l2tpd_fsm.c b/siu/l2tp/l2tpd_fsm.c index f1b6f00..9c4692e 100644 --- a/siu/l2tp/l2tpd_fsm.c +++ b/siu/l2tp/l2tpd_fsm.c @@ -82,6 +82,7 @@ static void l2tp_ctrl_allstate(struct osmo_fsm_inst *fi, uint32_t event, void *d break; case L2CC_E_RX_STOP_CCN: l2tp_tx_ack(l2c); + osmo_fsm_inst_state_chg(fi, L2CC_S_INIT, 0, 0); /* FIXME: tear down whole l2c */ break; case L2CC_E_RX_HELLO: From cc0456ac4535d77a2b6cff05695c156fba6c6edf Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Thu, 27 Oct 2016 04:07:49 +0200 Subject: [PATCH 092/133] l2tpd_fsm: sent stop ccn for unknown sessions --- siu/l2tp/l2tpd_packet.c | 1 + 1 file changed, 1 insertion(+) diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index a8f0eee..b13eeeb 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -781,6 +781,7 @@ static int l2tp_rcvmsg_control(struct msgb *msg) l2c = l2tpd_cc_find_by_l_cc_id(l2i, ch->ccid); if (!l2c) { LOGP(DL2TP, LOGL_ERROR, "l2tp: can not find a connection for ccid %d\n", ch->ccid); + l2tp_tx_stop_ccn_msg(msg); return -1; } From af5c3e22c4462ab93c1da15a7a875af20bfcc8dc Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Thu, 27 Oct 2016 04:16:46 +0200 Subject: [PATCH 093/133] l2tpd: add debug logs on recieved packets --- siu/l2tp/l2tpd_packet.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index b13eeeb..26ae386 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -713,6 +713,7 @@ static int l2tp_rcvmsg_control_ericsson(struct l2tpd_connection *l2c, struct msgb *msg, struct avps_parsed *ap, uint16_t msg_type) { + LOGP(DL2TP, LOGL_ERROR, "Rx: ericsson msg_type 0x%04x\n", msg_type); switch (msg_type) { case ERIC_CTRLMSG_TCRP: return rx_eri_tcrp(l2c, msg, ap); @@ -792,6 +793,8 @@ static int l2tp_rcvmsg_control(struct msgb *msg) LOGP(DL2TP, LOGL_ERROR, "cid %d: wrong seq number received. expectd %d != recveived %d.\n", l2c->local.ccid, l2c->next_tx_seq_nr, ch->Ns); } + LOGP(DL2TP, LOGL_ERROR, "Rx: l2tp vendor/type 0x%04x/0x%04x 0x%04x\n", first_avp->vendor_id, first_avp->type, msg_type); + if (first_avp->vendor_id == VENDOR_IETF && first_avp->type == AVP_IETF_CTRL_MSG) return l2tp_rcvmsg_control_ietf(l2c, msg, &ap, msg_type); @@ -816,6 +819,8 @@ int l2tp_rcvmsg(struct msgb *msg) /* strip session ID and feed to control */ msgb_pull(msg, sizeof(session)); return l2tp_rcvmsg_control(msg); + } else { + LOGP(DL2TP, LOGL_ERROR, "Received session %d data.\n", session); } return -1; } From 34104f6d52680eb42abdbb58112c400a559abee6 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Sun, 30 Oct 2016 18:03:42 +0100 Subject: [PATCH 094/133] l2tpd_packet: use correct fsm on rx_ic_rq --- siu/l2tp/l2tpd_packet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index 26ae386..4eb9910 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -609,7 +609,7 @@ static int rx_ic_rq(struct l2tpd_connection *l2cc, struct msgb *msg, struct avps } } - osmo_fsm_inst_dispatch(l2cc->fsm, L2IC_E_RX_ICRQ, msg); + osmo_fsm_inst_dispatch(l2s->fsm, L2IC_E_RX_ICRQ, msg); return 0; } From f859aaab166e34fe84111ae6d38026ed519bb6a9 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Sun, 30 Oct 2016 18:04:12 +0100 Subject: [PATCH 095/133] l2tpd_data: start with 1 as session id session with 0 is special and used for discovery --- siu/l2tp/l2tpd_data.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/siu/l2tp/l2tpd_data.c b/siu/l2tp/l2tpd_data.c index 49f6797..8a1c5b3 100644 --- a/siu/l2tp/l2tpd_data.c +++ b/siu/l2tp/l2tpd_data.c @@ -78,6 +78,8 @@ l2tpd_cc_alloc(struct l2tpd_instance *l2i) llist_add(&l2c->list, &l2i->connections); l2c->fsm = osmo_fsm_inst_alloc(&l2tp_cc_fsm, l2c, l2c, LOGL_DEBUG, id_str); + /* session id starts with 1 */ + l2c->next_l_sess_id = 1; return l2c; } From fc1486ed73bf14b9b69a77f996cc9d489137f073 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Sun, 30 Oct 2016 18:05:41 +0100 Subject: [PATCH 096/133] l2tpd_packet: add backref for session I'vnt't found a solution using container_of() to get the connection for a session. add a direct pointer to have a direct reference. Saves a lot lookups using the connection id every time --- siu/l2tp/l2tpd.h | 2 ++ siu/l2tp/l2tpd_data.c | 1 + siu/l2tp/l2tpd_fsm.c | 2 +- siu/l2tp/l2tpd_packet.c | 3 +-- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/siu/l2tp/l2tpd.h b/siu/l2tp/l2tpd.h index 135c004..df985a9 100644 --- a/siu/l2tp/l2tpd.h +++ b/siu/l2tp/l2tpd.h @@ -50,6 +50,8 @@ struct l2tpd_connection { /* A L2TP session within a connection */ struct l2tpd_session { + /* our conncetion */ + struct l2tpd_connection *connection; /* our link into the connection.sessions */ struct llist_head list; /* local session ID */ diff --git a/siu/l2tp/l2tpd_data.c b/siu/l2tp/l2tpd_data.c index 8a1c5b3..16b0f5a 100644 --- a/siu/l2tp/l2tpd_data.c +++ b/siu/l2tp/l2tpd_data.c @@ -95,6 +95,7 @@ l2tpd_sess_alloc(struct l2tpd_connection *conn) llist_add(&l2s->list, &conn->sessions); l2s->fsm = osmo_fsm_inst_alloc(&l2tp_ic_fsm, l2s, l2s, LOGL_DEBUG, id_str); + l2s->connection = conn; return l2s; } diff --git a/siu/l2tp/l2tpd_fsm.c b/siu/l2tp/l2tpd_fsm.c index 9c4692e..4fad959 100644 --- a/siu/l2tp/l2tpd_fsm.c +++ b/siu/l2tp/l2tpd_fsm.c @@ -187,7 +187,7 @@ static void l2tp_ic_s_init(struct osmo_fsm_inst *fi, uint32_t event, void *data) static void l2tp_ic_s_wait_conn(struct osmo_fsm_inst *fi, uint32_t event, void *data) { struct l2tpd_session *l2s = (struct l2tpd_session *) fi->priv; - struct l2tpd_connection *l2c = l2tpd_cc_find_by_l_cc_id(l2i, l2s->l_sess_id); + struct l2tpd_connection *l2c = l2s->connection; switch (event) { case L2IC_E_RX_ICCN: diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index 4eb9910..71750a0 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -451,8 +451,7 @@ int l2tp_tx_altc_rq_superchannel(struct l2tpd_connection *l2c) int l2tp_tx_ic_rp(struct l2tpd_session *l2s) { struct msgb *msg = l2tp_msgb_alloc(); - /* FIXME: use pointer instead of this call */ - struct l2tpd_connection *l2c = l2tpd_cc_find_by_l_cc_id(l2i, l2s->l_sess_id); + struct l2tpd_connection *l2c = l2s->connection; msgb_avp_put_msgt(msg, VENDOR_IETF, IETF_CTRLMSG_ICRP); msgb_avp_put_digest(msg); From d28d4e31f5d8076981b27d8c5f8710d7a85a2b73 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Sun, 30 Oct 2016 18:06:04 +0100 Subject: [PATCH 097/133] l2tpd_fsm: remove l2tp_ic_allstate() call, directly called by fsm code --- siu/l2tp/l2tpd_fsm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/siu/l2tp/l2tpd_fsm.c b/siu/l2tp/l2tpd_fsm.c index 4fad959..f84e598 100644 --- a/siu/l2tp/l2tpd_fsm.c +++ b/siu/l2tp/l2tpd_fsm.c @@ -181,7 +181,6 @@ static void l2tp_ic_s_init(struct osmo_fsm_inst *fi, uint32_t event, void *data) osmo_fsm_inst_state_chg(fi, L2IC_S_WAIT_CONN, 0, 0); break; } - l2tp_ic_allstate(fi, event, data); } static void l2tp_ic_s_wait_conn(struct osmo_fsm_inst *fi, uint32_t event, void *data) From 8bac56c1d44e23ebed4e15294d26a53b2c958c82 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Sun, 30 Oct 2016 18:06:22 +0100 Subject: [PATCH 098/133] l2tpd_packet: improve log message for unknown sessions --- siu/l2tp/l2tpd_packet.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index 71750a0..11343ca 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -602,8 +602,9 @@ static int rx_ic_rq(struct l2tpd_connection *l2cc, struct msgb *msg, struct avps l2cc->local.ccid, r_sess_id); l2s = l2tpd_sess_find_by_l_s_id(l2cc, r_sess_id); if (!l2s) { - LOGP(DL2TP, LOGL_ERROR, "NoSession %u\n", + LOGP(DL2TP, LOGL_ERROR, "NoSession found for %u\n", r_sess_id); + /* FIXME: send error packet */ return -1; } } From f3e113878289b6484eb1af242227583c3d1183fe Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Sun, 30 Oct 2016 19:08:57 +0100 Subject: [PATCH 099/133] l2tpd_fsm: move TC/ALTC logic into own fsm --- siu/l2tp/l2tpd_fsm.c | 158 +++++++++++++++++++++++++++---------------- siu/l2tp/l2tpd_fsm.h | 56 ++++++++++----- 2 files changed, 138 insertions(+), 76 deletions(-) diff --git a/siu/l2tp/l2tpd_fsm.c b/siu/l2tp/l2tpd_fsm.c index f84e598..923c5d4 100644 --- a/siu/l2tp/l2tpd_fsm.c +++ b/siu/l2tp/l2tpd_fsm.c @@ -28,47 +28,15 @@ static void l2tp_ctrl_s_wait_ctl_conn(struct osmo_fsm_inst *fi, uint32_t event, switch (event) { case L2CC_E_RX_SCCCN: if (!l2tp_tx_tc_rq(l2c)) - osmo_fsm_inst_state_chg(fi, L2CC_S_WAIT_FOR_TCRP, 0, 0); + osmo_fsm_inst_state_chg(fi, L2CC_S_ESTABLISHED, 0, 0); break; } } static void l2tp_ctrl_s_established(struct osmo_fsm_inst *fi, uint32_t event, void *data) { - struct l2tpd_connection *l2c = fi->priv; - - if (!l2tp_tx_tc_rq(l2c)) { - osmo_fsm_inst_state_chg(fi, L2CC_S_WAIT_FOR_TCRP, 0, 0); - } } -static void l2tp_ctrl_s_wait_for_tcrp(struct osmo_fsm_inst *fi, uint32_t event, void *data) -{ - struct l2tpd_connection *l2c = fi->priv; - - switch (event) { - case L2CC_E_RX_TCRP: - l2tp_tx_altc_rq_timeslot(l2c); - osmo_fsm_inst_state_chg(fi, L2CC_S_WAIT_FOR_ALTCRP, 0, 0); - break; - } -} - -static void l2tp_ctrl_s_wait_for_altcrp(struct osmo_fsm_inst *fi, uint32_t event, void *data) -{ - struct l2tpd_connection *l2c = fi->priv; - - switch (event) { - case L2CC_E_RX_ALTCRP: - l2tp_tx_ack(l2c); - osmo_fsm_inst_state_chg(fi, L2CC_S_ESTABLISHED_CONFIGURED, 0, 0); - break; - } -} - -static void l2tp_ctrl_s_established_configured(struct osmo_fsm_inst *fi, uint32_t event, void *data) -{ -} static void l2tp_ctrl_allstate(struct osmo_fsm_inst *fi, uint32_t event, void *data) { @@ -97,8 +65,6 @@ static const struct value_string l2tp_cc_events[] = { { L2CC_E_RX_SCCRP, "RX-SCCRP" }, { L2CC_E_RX_SCCCN, "RX-SCCCN" }, { L2CC_E_RX_STOP_CCN, "RX-STOPCCN" }, - { L2CC_E_RX_TCRP, "RX-TCRP" }, - { L2CC_E_RX_ALTCRP, "RX-ALTCRP" }, { L2CC_E_RX_HELLO, "RX-HELLO" }, { 0, NULL } }; @@ -113,38 +79,16 @@ static const struct osmo_fsm_state l2tp_ctrl_states[] = { [L2CC_S_WAIT_CTL_CONN] = { .in_event_mask = S(L2CC_E_RX_SCCCN), .out_state_mask = S(L2CC_S_ESTABLISHED) | - S(L2CC_S_WAIT_FOR_TCRP) | S(L2CC_S_INIT), .name = "WAIT_CTL_CONN", .action = l2tp_ctrl_s_wait_ctl_conn, }, [L2CC_S_ESTABLISHED] = { .in_event_mask = 0, - .out_state_mask = S(L2CC_S_WAIT_FOR_TCRP) | - S(L2CC_S_INIT), + .out_state_mask = S(L2CC_S_INIT), .name = "ESTABLISHED", .action = l2tp_ctrl_s_established, - }, - [L2CC_S_WAIT_FOR_TCRP] = { - .in_event_mask = S(L2CC_E_RX_TCRP), - .out_state_mask = S(L2CC_S_WAIT_FOR_ALTCRP) | - S(L2CC_S_INIT), - .name = "WAIT_FOR_TCRP", - .action = l2tp_ctrl_s_wait_for_tcrp, - }, - [L2CC_S_WAIT_FOR_ALTCRP] = { - .in_event_mask = S(L2CC_E_RX_ALTCRP), - .out_state_mask = S(L2CC_S_ESTABLISHED_CONFIGURED) | - S(L2CC_S_INIT), - .name = "WAIT_FOR_ALTCRP", - .action = l2tp_ctrl_s_wait_for_altcrp, - }, - [L2CC_S_ESTABLISHED_CONFIGURED] = { - .in_event_mask = 0, - .out_state_mask = S(L2CC_S_INIT), - .name = "ESTABLISHED_CONFIGURED", - .action = l2tp_ctrl_s_established_configured, - }, + } }; struct osmo_fsm l2tp_cc_fsm = { @@ -157,7 +101,103 @@ struct osmo_fsm l2tp_cc_fsm = { .allstate_action = l2tp_ctrl_allstate, }; +/* l2tp conf fsm */ +static void l2tp_conf_s_wait_for_tcrp(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + struct l2tpd_connection *l2c = fi->priv; + + switch (event) { + case L2CC_E_RX_TCRP: + l2tp_tx_altc_rq_timeslot(l2c); + osmo_fsm_inst_state_chg(fi, L2CONF_S_WAIT_FOR_ALTCRP, 0, 0); + break; + } +} + +static void l2tp_conf_s_wait_for_altcrp(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + struct l2tpd_connection *l2c = fi->priv; + + switch (event) { + case L2CC_E_RX_ALTCRP: + l2tp_tx_ack(l2c); + osmo_fsm_inst_state_chg(fi, L2CONF_S_ESTABLISHED, 0, 0); + break; + } +} + +static void l2tp_conf_s_established(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ +} + +static void l2tp_conf_allstate(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + switch (event) { + case L2CONF_E_LOCAL_CLOSE_REQ: + osmo_fsm_inst_state_chg(fi, L2CONF_S_INIT, 0, 0); + /* FIXME: teardown instead of INIT */ + break; + } +} + +static const struct value_string l2tp_conf_events[] = { + { L2CONF_E_LOCAL_CLOSE_REQ, "LOCAL-CLOSE" }, + { L2CONF_E_TX_TCRQ, "RX-TCRP" }, + { L2CONF_E_RX_TCRP, "RX-TCRP" }, + { L2CONF_E_RX_ALTCRP, "RX-ALTCRP" }, + { L2IC_E_RX_ICCN, "RX-InCall-Connect" }, + { 0, NULL } +}; + +static const struct osmo_fsm_state l2tp_conf_states[] = { + [L2CONF_S_INIT] = { + .in_event_mask = S(L2CONF_E_RX_TCRP), + .out_state_mask = S(L2CONF_S_WAIT_FOR_ALTCRP) | + S(L2CONF_S_INIT), + .name = "WAIT_FOR_TCRP", + .action = l2tp_conf_s_wait_for_tcrp, + }, + [L2CONF_S_WAIT_FOR_TCRP] = { + .in_event_mask = S(L2CONF_E_RX_TCRP), + .out_state_mask = S(L2CONF_S_WAIT_FOR_ALTCRP) | + S(L2CONF_S_INIT), + .name = "WAIT_FOR_TCRP", + .action = l2tp_conf_s_wait_for_tcrp, + }, + [L2CONF_S_WAIT_FOR_TC_SESSIONS] = { + .in_event_mask = S(L2CONF_E_RX_TCRP), + .out_state_mask = S(L2CONF_S_WAIT_FOR_ALTCRP) | + S(L2CONF_S_INIT), + .name = "WAIT_FOR_TCRP", + .action = l2tp_conf_s_wait_for_tcrp, + }, + [L2CONF_S_WAIT_FOR_ALTCRP] = { + .in_event_mask = S(L2CONF_E_RX_ALTCRP), + .out_state_mask = S(L2CONF_S_ESTABLISHED) | + S(L2CONF_S_INIT), + .name = "WAIT_FOR_ALTCRP", + .action = l2tp_conf_s_wait_for_altcrp, + }, + [L2CONF_S_ESTABLISHED] = { + .in_event_mask = 0, + .out_state_mask = S(L2CONF_S_INIT), + .name = "ESTABLISHED", + .action = l2tp_conf_s_established, + }, +}; + +struct osmo_fsm l2tp_conf_fsm = { + .name = "L2TP-CONF", + .states = l2tp_conf_states, + .num_states = ARRAY_SIZE(l2tp_conf_states), + .log_subsys = 0, + .event_names = l2tp_conf_events, + .allstate_event_mask = S(L2CC_E_LOCAL_CLOSE_REQ), + .allstate_action = l2tp_conf_allstate, +}; + +/* l2tp ic/session fsm */ static void l2tp_ic_allstate(struct osmo_fsm_inst *fi, uint32_t event, void *data) { switch (event) { diff --git a/siu/l2tp/l2tpd_fsm.h b/siu/l2tp/l2tpd_fsm.h index 082dffa..f238c31 100644 --- a/siu/l2tp/l2tpd_fsm.h +++ b/siu/l2tp/l2tpd_fsm.h @@ -23,6 +23,15 @@ enum l2tpd_ctrl_con_event { L2CC_E_RX_HELLO, }; +enum l2tpd_ctrl_con_state { + /* Before we receive SCCRQ*/ + L2CC_S_INIT, + /* After we sent SCCRP, waiting for SCCCN */ + L2CC_S_WAIT_CTL_CONN, + /* Control Conncetion is established */ + L2CC_S_ESTABLISHED, +}; + enum l2tpd_in_call_event { #if 0 L2IC_E_START, @@ -40,21 +49,7 @@ enum l2tpd_in_call_event { /* Local Close Request */ L2IC_E_LOCAL_CLOSE_REQ, }; - -enum l2tpd_ctrl_con_state { - /* Before we receive SCCRQ*/ - L2CC_S_INIT, - /* After we sent SCCRP, waiting for SCCCN */ - L2CC_S_WAIT_CTL_CONN, - /* Control Conncetion is established */ - L2CC_S_ESTABLISHED, - /* After we sent a TCRQ, waiting for TCRP */ - L2CC_S_WAIT_FOR_TCRP, - /* After we sent a ALTTCRQ, waiting for ALTCRP */ - L2CC_S_WAIT_FOR_ALTCRP, - /* We configured the SIU to start sessions */ - L2CC_S_ESTABLISHED_CONFIGURED -}; +extern struct osmo_fsm l2tp_cc_fsm; /* ICRQ recipient */ enum l2tpd_in_call_state { @@ -64,6 +59,33 @@ enum l2tpd_in_call_state { L2IC_S_WAIT_CONN, L2IC_S_ESTABLISHED, }; - extern struct osmo_fsm l2tp_ic_fsm; -extern struct osmo_fsm l2tp_cc_fsm; + +enum l2tpd_configure_event { + /* sent the TC rq within state machine */ + L2CONF_E_TX_TCRQ, + /* received TC RP */ + L2CONF_E_RX_TCRP, + /* l2tp session setted up */ + L2CONF_E_RX_ICCN, + /* received ALTC RP */ + L2CONF_E_RX_ALTCRP, + /* Local Close Request */ + L2CONF_E_LOCAL_CLOSE_REQ, +}; + +enum l2tpd_configure_state { + /* initial state, sent out TCRQ */ + L2CONF_S_INIT, + /* Waiting for TCRP */ + L2CONF_S_WAIT_FOR_TCRP, + /* Wait until all l2tp sessions of tcrp setted up. Afterwards sent out ALTCRQ */ + L2CONF_S_WAIT_FOR_TC_SESSIONS, + /* Waiting for ALTCRP */ + L2CONF_S_WAIT_FOR_ALTCRP, + /* Wait until all l2tp session altcr setted up */ + L2CONF_S_WAIT_FOR_ALTC_SESSIONS, + /* Established */ + L2CONF_S_ESTABLISHED +}; +extern struct osmo_fsm l2tp_conf_fsm; From 1a8498aa0da1de92ec5efa8d4c0fef17fa2aeedb Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Sun, 30 Oct 2016 19:29:42 +0100 Subject: [PATCH 100/133] l2tpd_data: add conf_fsm as into 'struct l2tpd_connection' --- siu/l2tp/l2tpd.h | 2 ++ siu/l2tp/l2tpd_data.c | 1 + 2 files changed, 3 insertions(+) diff --git a/siu/l2tp/l2tpd.h b/siu/l2tp/l2tpd.h index df985a9..d0fa2ff 100644 --- a/siu/l2tp/l2tpd.h +++ b/siu/l2tp/l2tpd.h @@ -46,6 +46,8 @@ struct l2tpd_connection { uint32_t next_l_sess_id; /* finite state machine for connection */ struct osmo_fsm_inst *fsm; + /* finite state machine for traffic channels */ + struct osmo_fsm_inst *conf_fsm; }; /* A L2TP session within a connection */ diff --git a/siu/l2tp/l2tpd_data.c b/siu/l2tp/l2tpd_data.c index 16b0f5a..0f36eb1 100644 --- a/siu/l2tp/l2tpd_data.c +++ b/siu/l2tp/l2tpd_data.c @@ -78,6 +78,7 @@ l2tpd_cc_alloc(struct l2tpd_instance *l2i) llist_add(&l2c->list, &l2i->connections); l2c->fsm = osmo_fsm_inst_alloc(&l2tp_cc_fsm, l2c, l2c, LOGL_DEBUG, id_str); + l2c->conf_fsm = osmo_fsm_inst_alloc(&l2tp_conf_fsm, l2c, l2c, LOGL_DEBUG, id_str); /* session id starts with 1 */ l2c->next_l_sess_id = 1; From aa4b668e5dcea14aadccbb9d05b21ef2c384a166 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Sun, 30 Oct 2016 19:30:10 +0100 Subject: [PATCH 101/133] l2tpd_fsm: include osmocom/core/fsm.h --- siu/l2tp/l2tpd_fsm.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/siu/l2tp/l2tpd_fsm.h b/siu/l2tp/l2tpd_fsm.h index f238c31..85228fd 100644 --- a/siu/l2tp/l2tpd_fsm.h +++ b/siu/l2tp/l2tpd_fsm.h @@ -1,5 +1,7 @@ #pragma once +#include + enum l2tpd_ctrl_con_event { #if 0 /* Local open request (not applicable on server */ From 5ca60d694e2f5e7d330ebc3de94935e5bbc2b222 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Sun, 30 Oct 2016 19:31:18 +0100 Subject: [PATCH 102/133] l2tpd_fsm: migrate state & event into conf_fsm the l2tp_conf_fsm handle traffic channels and wait between allocation, because the siu can not handle to many packets at once --- siu/l2tp/l2tpd_fsm.c | 71 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 65 insertions(+), 6 deletions(-) diff --git a/siu/l2tp/l2tpd_fsm.c b/siu/l2tp/l2tpd_fsm.c index 923c5d4..6e07995 100644 --- a/siu/l2tp/l2tpd_fsm.c +++ b/siu/l2tp/l2tpd_fsm.c @@ -27,8 +27,10 @@ static void l2tp_ctrl_s_wait_ctl_conn(struct osmo_fsm_inst *fi, uint32_t event, switch (event) { case L2CC_E_RX_SCCCN: - if (!l2tp_tx_tc_rq(l2c)) + if (!l2tp_tx_ack(l2c)) { osmo_fsm_inst_state_chg(fi, L2CC_S_ESTABLISHED, 0, 0); + osmo_fsm_inst_dispatch(l2c->conf_fsm, L2CONF_E_TX_TCRQ, data); + } break; } } @@ -103,18 +105,47 @@ struct osmo_fsm l2tp_cc_fsm = { /* l2tp conf fsm */ +static void l2tp_conf_s_init(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + switch (event) { + case L2CONF_E_TX_TCRQ: + break; + } +} + static void l2tp_conf_s_wait_for_tcrp(struct osmo_fsm_inst *fi, uint32_t event, void *data) { struct l2tpd_connection *l2c = fi->priv; switch (event) { - case L2CC_E_RX_TCRP: + case L2CONF_E_RX_TCRP: l2tp_tx_altc_rq_timeslot(l2c); osmo_fsm_inst_state_chg(fi, L2CONF_S_WAIT_FOR_ALTCRP, 0, 0); break; } } +static void l2tp_conf_s_wait_for_tc_sessions(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + struct l2tpd_connection *l2c = fi->priv; + struct l2tpd_session *l2s; + int i = 0; + + switch (event) { + case L2CONF_E_RX_ICCN: + llist_for_each_entry(l2s, &l2c->sessions, list) { + i++; + } + LOGP(DL2TP, LOGL_ERROR, "Found %d sessions\n", i); + if (i >= 3) { + osmo_fsm_inst_state_chg(fi, L2CONF_S_WAIT_FOR_ALTCRP, 0, 0); + l2tp_tx_altc_rq_timeslot(l2c); + } + break; + } +} + + static void l2tp_conf_s_wait_for_altcrp(struct osmo_fsm_inst *fi, uint32_t event, void *data) { struct l2tpd_connection *l2c = fi->priv; @@ -122,11 +153,32 @@ static void l2tp_conf_s_wait_for_altcrp(struct osmo_fsm_inst *fi, uint32_t event switch (event) { case L2CC_E_RX_ALTCRP: l2tp_tx_ack(l2c); - osmo_fsm_inst_state_chg(fi, L2CONF_S_ESTABLISHED, 0, 0); + osmo_fsm_inst_state_chg(fi, L2CONF_S_WAIT_FOR_ALTC_SESSIONS, 0, 0); break; } } +static void l2tp_conf_s_wait_for_altc_sessions(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + struct l2tpd_connection *l2c = fi->priv; + struct l2tpd_session *l2s; + int i = 0; + + switch (event) { + case L2CONF_E_RX_ICCN: + llist_for_each_entry(l2s, &l2c->sessions, list) { + i++; + } + LOGP(DL2TP, LOGL_ERROR, "Found %d sessions\n", i); + + if (i >= 4) { + osmo_fsm_inst_state_chg(fi, L2CONF_S_ESTABLISHED, 0, 0); + } + break; + } +} + + static void l2tp_conf_s_established(struct osmo_fsm_inst *fi, uint32_t event, void *data) { } @@ -156,7 +208,7 @@ static const struct osmo_fsm_state l2tp_conf_states[] = { .out_state_mask = S(L2CONF_S_WAIT_FOR_ALTCRP) | S(L2CONF_S_INIT), .name = "WAIT_FOR_TCRP", - .action = l2tp_conf_s_wait_for_tcrp, + .action = l2tp_conf_s_init, }, [L2CONF_S_WAIT_FOR_TCRP] = { .in_event_mask = S(L2CONF_E_RX_TCRP), @@ -169,8 +221,8 @@ static const struct osmo_fsm_state l2tp_conf_states[] = { .in_event_mask = S(L2CONF_E_RX_TCRP), .out_state_mask = S(L2CONF_S_WAIT_FOR_ALTCRP) | S(L2CONF_S_INIT), - .name = "WAIT_FOR_TCRP", - .action = l2tp_conf_s_wait_for_tcrp, + .name = "WAIT_FOR_TC_SESSIONS", + .action = l2tp_conf_s_wait_for_tc_sessions, }, [L2CONF_S_WAIT_FOR_ALTCRP] = { .in_event_mask = S(L2CONF_E_RX_ALTCRP), @@ -179,6 +231,13 @@ static const struct osmo_fsm_state l2tp_conf_states[] = { .name = "WAIT_FOR_ALTCRP", .action = l2tp_conf_s_wait_for_altcrp, }, + [L2CONF_S_WAIT_FOR_ALTC_SESSIONS] = { + .in_event_mask = S(L2CONF_E_RX_TCRP), + .out_state_mask = S(L2CONF_S_WAIT_FOR_ALTCRP) | + S(L2CONF_S_INIT), + .name = "WAIT_FOR_ALTC_SESSIONS", + .action = l2tp_conf_s_wait_for_altc_sessions, + }, [L2CONF_S_ESTABLISHED] = { .in_event_mask = 0, .out_state_mask = S(L2CONF_S_INIT), From 2f21b23c46653622d52f5ad4bd0a2f7f9f8ebfca Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Sun, 30 Oct 2016 19:52:58 +0100 Subject: [PATCH 103/133] l2tpd: register l2tp_conf_fsm every fsm must registered --- siu/l2tp/l2tpd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/siu/l2tp/l2tpd.c b/siu/l2tp/l2tpd.c index e729e27..2061c4b 100644 --- a/siu/l2tp/l2tpd.c +++ b/siu/l2tp/l2tpd.c @@ -95,6 +95,7 @@ int main(int argc, char **argv) /* register fsms */ osmo_fsm_register(&l2tp_cc_fsm); osmo_fsm_register(&l2tp_ic_fsm); + osmo_fsm_register(&l2tp_conf_fsm); l2i = talloc_zero(tall_l2tp_ctx, struct l2tpd_instance); l2i->cfg.bind_ip = "0.0.0.0"; From 7e0bc9515539925445e65b7f4b658dc012217ef6 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Sun, 30 Oct 2016 19:53:20 +0100 Subject: [PATCH 104/133] l2tpd: allow transistion from INIT -> INIT, when a StopSC received in init --- siu/l2tp/l2tpd_fsm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/siu/l2tp/l2tpd_fsm.c b/siu/l2tp/l2tpd_fsm.c index 6e07995..46e554d 100644 --- a/siu/l2tp/l2tpd_fsm.c +++ b/siu/l2tp/l2tpd_fsm.c @@ -74,7 +74,7 @@ static const struct value_string l2tp_cc_events[] = { static const struct osmo_fsm_state l2tp_ctrl_states[] = { [L2CC_S_INIT] = { .in_event_mask = S(L2CC_E_RX_SCCRQ), - .out_state_mask = S(L2CC_S_WAIT_CTL_CONN), + .out_state_mask = S(L2CC_S_WAIT_CTL_CONN) | S(L2CC_S_INIT), .name = "INIT", .action = l2tp_ctrl_s_init, }, From af2cd0815bed504ea7b98005a63cb09cbc57d3fb Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Sun, 30 Oct 2016 19:53:52 +0100 Subject: [PATCH 105/133] l2tpd: correct event name of L2CONF_E_RX_ALTCRP --- siu/l2tp/l2tpd_fsm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/siu/l2tp/l2tpd_fsm.c b/siu/l2tp/l2tpd_fsm.c index 46e554d..e775636 100644 --- a/siu/l2tp/l2tpd_fsm.c +++ b/siu/l2tp/l2tpd_fsm.c @@ -151,7 +151,7 @@ static void l2tp_conf_s_wait_for_altcrp(struct osmo_fsm_inst *fi, uint32_t event struct l2tpd_connection *l2c = fi->priv; switch (event) { - case L2CC_E_RX_ALTCRP: + case L2CONF_E_RX_ALTCRP: l2tp_tx_ack(l2c); osmo_fsm_inst_state_chg(fi, L2CONF_S_WAIT_FOR_ALTC_SESSIONS, 0, 0); break; From e6502cd8f10ef36fb37571da036c6f838ab1abbd Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Sun, 30 Oct 2016 19:54:10 +0100 Subject: [PATCH 106/133] l2tpd_fsm: correct valuestring of L2CONF_E_TX_TCRQ --- siu/l2tp/l2tpd_fsm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/siu/l2tp/l2tpd_fsm.c b/siu/l2tp/l2tpd_fsm.c index e775636..2cda860 100644 --- a/siu/l2tp/l2tpd_fsm.c +++ b/siu/l2tp/l2tpd_fsm.c @@ -195,7 +195,7 @@ static void l2tp_conf_allstate(struct osmo_fsm_inst *fi, uint32_t event, void *d static const struct value_string l2tp_conf_events[] = { { L2CONF_E_LOCAL_CLOSE_REQ, "LOCAL-CLOSE" }, - { L2CONF_E_TX_TCRQ, "RX-TCRP" }, + { L2CONF_E_TX_TCRQ, "TX-TCRQ" }, { L2CONF_E_RX_TCRP, "RX-TCRP" }, { L2CONF_E_RX_ALTCRP, "RX-ALTCRP" }, { L2IC_E_RX_ICCN, "RX-InCall-Connect" }, From 7e3f5b6cfc668e725665a74723b8807bb63ce9f6 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Sun, 30 Oct 2016 20:12:21 +0100 Subject: [PATCH 107/133] l2tpd_fsm: correct naming of all old L2CC_ enums in L2CONF fsm --- siu/l2tp/l2tpd_fsm.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/siu/l2tp/l2tpd_fsm.c b/siu/l2tp/l2tpd_fsm.c index 2cda860..28b576c 100644 --- a/siu/l2tp/l2tpd_fsm.c +++ b/siu/l2tp/l2tpd_fsm.c @@ -204,15 +204,15 @@ static const struct value_string l2tp_conf_events[] = { static const struct osmo_fsm_state l2tp_conf_states[] = { [L2CONF_S_INIT] = { - .in_event_mask = S(L2CONF_E_RX_TCRP), - .out_state_mask = S(L2CONF_S_WAIT_FOR_ALTCRP) | + .in_event_mask = S(L2CONF_E_TX_TCRQ), + .out_state_mask = S(L2CONF_S_WAIT_FOR_TCRP) | S(L2CONF_S_INIT), - .name = "WAIT_FOR_TCRP", + .name = "INIT", .action = l2tp_conf_s_init, }, [L2CONF_S_WAIT_FOR_TCRP] = { .in_event_mask = S(L2CONF_E_RX_TCRP), - .out_state_mask = S(L2CONF_S_WAIT_FOR_ALTCRP) | + .out_state_mask = S(L2CONF_S_WAIT_FOR_TC_SESSIONS) | S(L2CONF_S_INIT), .name = "WAIT_FOR_TCRP", .action = l2tp_conf_s_wait_for_tcrp, @@ -226,14 +226,14 @@ static const struct osmo_fsm_state l2tp_conf_states[] = { }, [L2CONF_S_WAIT_FOR_ALTCRP] = { .in_event_mask = S(L2CONF_E_RX_ALTCRP), - .out_state_mask = S(L2CONF_S_ESTABLISHED) | + .out_state_mask = S(L2CONF_S_WAIT_FOR_ALTC_SESSIONS) | S(L2CONF_S_INIT), .name = "WAIT_FOR_ALTCRP", .action = l2tp_conf_s_wait_for_altcrp, }, [L2CONF_S_WAIT_FOR_ALTC_SESSIONS] = { .in_event_mask = S(L2CONF_E_RX_TCRP), - .out_state_mask = S(L2CONF_S_WAIT_FOR_ALTCRP) | + .out_state_mask = S(L2CONF_S_ESTABLISHED) | S(L2CONF_S_INIT), .name = "WAIT_FOR_ALTC_SESSIONS", .action = l2tp_conf_s_wait_for_altc_sessions, @@ -252,7 +252,7 @@ struct osmo_fsm l2tp_conf_fsm = { .num_states = ARRAY_SIZE(l2tp_conf_states), .log_subsys = 0, .event_names = l2tp_conf_events, - .allstate_event_mask = S(L2CC_E_LOCAL_CLOSE_REQ), + .allstate_event_mask = S(L2CONF_E_LOCAL_CLOSE_REQ), .allstate_action = l2tp_conf_allstate, }; From 86e5a57ce572e38433994ca8480d83316b58e044 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Sun, 30 Oct 2016 20:12:41 +0100 Subject: [PATCH 108/133] l2tpd_fsm/l2tp_conf: sent TC_RQ on L2CONF_E_TX_TCRQ event --- siu/l2tp/l2tpd_fsm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/siu/l2tp/l2tpd_fsm.c b/siu/l2tp/l2tpd_fsm.c index 28b576c..8cead04 100644 --- a/siu/l2tp/l2tpd_fsm.c +++ b/siu/l2tp/l2tpd_fsm.c @@ -107,8 +107,11 @@ struct osmo_fsm l2tp_cc_fsm = { static void l2tp_conf_s_init(struct osmo_fsm_inst *fi, uint32_t event, void *data) { + struct l2tpd_connection *l2c = fi->priv; + switch (event) { case L2CONF_E_TX_TCRQ: + l2tp_tx_tc_rq(l2c); break; } } From b1601d6996eba268c4553872f83485cd423ffc40 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Sun, 30 Oct 2016 20:12:59 +0100 Subject: [PATCH 109/133] l2tpd_packet: correct sequence number in ACKs --- siu/l2tp/l2tpd_packet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index 11343ca..f31040d 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -296,7 +296,7 @@ static int l2tp_msgb_tx(struct msgb *msg, int not_ack) if (not_ack) l2h->Ns = htons(l2c->next_tx_seq_nr++); else - l2h->Ns = htons(l2c->next_tx_seq_nr - 1); + l2h->Ns = htons(l2c->next_tx_seq_nr); /* then insert/patch the message digest AVP */ digest_avp_update(msg); From f90d51e16aa7188d59edd38735ae789065b888ff Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Sun, 30 Oct 2016 20:13:28 +0100 Subject: [PATCH 110/133] l2tpd_packet: implement rx_ic_cn() to dispatch L2IC_E_RX_ICCN --- siu/l2tp/l2tpd_packet.c | 44 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index f31040d..1c9ae79 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -613,13 +613,55 @@ static int rx_ic_rq(struct l2tpd_connection *l2cc, struct msgb *msg, struct avps return 0; } +static struct l2tpd_session * +get_session_by_msg(struct l2tpd_connection *l2cc, struct msgb *msg, + struct avps_parsed *ap) +{ + struct l2tpd_session *l2s; + uint32_t l_sess_id; + uint32_t r_sess_id; + + if (avpp_val_u32(ap, VENDOR_IETF, AVP_IETF_REM_SESS_ID, &r_sess_id)) { + LOGP(DL2TP, LOGL_ERROR, "ccid %d: Missing AVP REM_SESS_ID\n", + l2cc->local.ccid); + return NULL; + } + if (avpp_val_u32(ap, VENDOR_IETF, AVP_IETF_LOC_SESS_ID, &l_sess_id)) { + LOGP(DL2TP, LOGL_ERROR, "ccid %d: Missing AVP LOC_SESS_ID\n", + l2cc->local.ccid); + return NULL; + } + + l2s = l2tpd_sess_find_by_l_s_id(l2cc, r_sess_id); + if (!l2s) { + LOGP(DL2TP, LOGL_ERROR, "ccid %d: Can not find session %d\n", + l2cc->local.ccid, r_sess_id); + return NULL; + } + + if (l2s->r_sess_id != l_sess_id) { + LOGP(DL2TP, LOGL_ERROR, "ccid %d: Packet remote session id %d differs from known %d\n", + l2cc->local.ccid, l_sess_id, l2s->r_sess_id); + return NULL; + } + + return l2s; +} + /* Incoming "Incoming Call Connected" from SIU */ static int rx_ic_cn(struct l2tpd_connection *l2cc, struct msgb *msg, struct avps_parsed *ap) { + struct l2tpd_session *l2s; + if (!l2cc) return -1; - osmo_fsm_inst_dispatch(l2cc->fsm, L2IC_E_RX_ICCN, msg); + l2s = get_session_by_msg(l2cc, msg, ap); + if (!l2s) { + return -1; + } + + osmo_fsm_inst_dispatch(l2s->fsm, L2IC_E_RX_ICCN, msg); return 0; } From 75e72bd7057a8bf203825a716d6484f227c7222f Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Sun, 30 Oct 2016 20:36:10 +0100 Subject: [PATCH 111/133] l2tpd_fsm: rename L2CONF_E_RX_ICCN -> L2CONF_E_ESTABLISH_SESSION will only triggered when a session change state to established --- siu/l2tp/l2tpd_fsm.c | 4 ++-- siu/l2tp/l2tpd_fsm.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/siu/l2tp/l2tpd_fsm.c b/siu/l2tp/l2tpd_fsm.c index 8cead04..717d8f4 100644 --- a/siu/l2tp/l2tpd_fsm.c +++ b/siu/l2tp/l2tpd_fsm.c @@ -135,7 +135,7 @@ static void l2tp_conf_s_wait_for_tc_sessions(struct osmo_fsm_inst *fi, uint32_t int i = 0; switch (event) { - case L2CONF_E_RX_ICCN: + case L2CONF_E_ESTABLISH_SESSION: llist_for_each_entry(l2s, &l2c->sessions, list) { i++; } @@ -168,7 +168,7 @@ static void l2tp_conf_s_wait_for_altc_sessions(struct osmo_fsm_inst *fi, uint32_ int i = 0; switch (event) { - case L2CONF_E_RX_ICCN: + case L2CONF_E_ESTABLISH_SESSION: llist_for_each_entry(l2s, &l2c->sessions, list) { i++; } diff --git a/siu/l2tp/l2tpd_fsm.h b/siu/l2tp/l2tpd_fsm.h index 85228fd..cb97778 100644 --- a/siu/l2tp/l2tpd_fsm.h +++ b/siu/l2tp/l2tpd_fsm.h @@ -69,7 +69,7 @@ enum l2tpd_configure_event { /* received TC RP */ L2CONF_E_RX_TCRP, /* l2tp session setted up */ - L2CONF_E_RX_ICCN, + L2CONF_E_ESTABLISH_SESSION, /* received ALTC RP */ L2CONF_E_RX_ALTCRP, /* Local Close Request */ From c9b24084f41d333b782c57e54d4f5ca7a4488984 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Sun, 30 Oct 2016 20:36:37 +0100 Subject: [PATCH 112/133] l2tpd_fsm: dispatch L2CONF_E_ESTABLISH_SESSION on L2IC_S_ESTABLISHED --- siu/l2tp/l2tpd_fsm.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/siu/l2tp/l2tpd_fsm.c b/siu/l2tp/l2tpd_fsm.c index 717d8f4..7541e87 100644 --- a/siu/l2tp/l2tpd_fsm.c +++ b/siu/l2tp/l2tpd_fsm.c @@ -292,9 +292,11 @@ static void l2tp_ic_s_wait_conn(struct osmo_fsm_inst *fi, uint32_t event, void * switch (event) { case L2IC_E_RX_ICCN: - /* ICCN wsa received */ - if (!l2tp_tx_ack(l2c)) + /* ICCN received */ + if (!l2tp_tx_ack(l2c)) { osmo_fsm_inst_state_chg(fi, L2IC_S_ESTABLISHED, 0, 0); + osmo_fsm_inst_dispatch(l2c->conf_fsm, L2CONF_E_ESTABLISH_SESSION, data); + } } } From 44749b1dfed364b3404bced01ca512f7e8e8c4ef Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Sun, 30 Oct 2016 21:07:58 +0100 Subject: [PATCH 113/133] l2tpd_packet: add missing AVP ResultError for STOP_CCN --- siu/l2tp/l2tpd_packet.c | 1 + 1 file changed, 1 insertion(+) diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index 1c9ae79..dac0e6a 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -352,6 +352,7 @@ int l2tp_tx_stop_ccn(struct l2tpd_connection *l2c) msgb_avp_put_msgt(msg, VENDOR_IETF, IETF_CTRLMSG_STOPCCN); msgb_avp_put_digest(msg); + msgb_avp_put_u16(msg, VENDOR_IETF, AVP_IETF_RESULT_CODE, 0x1, 1); msg->dst = l2c; return l2tp_msgb_tx(msg, 1); From c0720cbf22ce5199bbeb31796a0487417550ccea Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Sun, 30 Oct 2016 21:08:47 +0100 Subject: [PATCH 114/133] l2tpd_packet/fsm: fix last missing parts for conf_fsm --- siu/l2tp/l2tpd_fsm.c | 11 ++++++----- siu/l2tp/l2tpd_fsm.h | 4 ---- siu/l2tp/l2tpd_packet.c | 4 ++-- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/siu/l2tp/l2tpd_fsm.c b/siu/l2tp/l2tpd_fsm.c index 7541e87..01495a8 100644 --- a/siu/l2tp/l2tpd_fsm.c +++ b/siu/l2tp/l2tpd_fsm.c @@ -112,6 +112,7 @@ static void l2tp_conf_s_init(struct osmo_fsm_inst *fi, uint32_t event, void *dat switch (event) { case L2CONF_E_TX_TCRQ: l2tp_tx_tc_rq(l2c); + osmo_fsm_inst_state_chg(fi, L2CONF_S_WAIT_FOR_TCRP, 0, 0); break; } } @@ -122,8 +123,8 @@ static void l2tp_conf_s_wait_for_tcrp(struct osmo_fsm_inst *fi, uint32_t event, switch (event) { case L2CONF_E_RX_TCRP: - l2tp_tx_altc_rq_timeslot(l2c); - osmo_fsm_inst_state_chg(fi, L2CONF_S_WAIT_FOR_ALTCRP, 0, 0); + l2tp_tx_ack(l2c); + osmo_fsm_inst_state_chg(fi, L2CONF_S_WAIT_FOR_TC_SESSIONS, 0, 0); break; } } @@ -201,7 +202,7 @@ static const struct value_string l2tp_conf_events[] = { { L2CONF_E_TX_TCRQ, "TX-TCRQ" }, { L2CONF_E_RX_TCRP, "RX-TCRP" }, { L2CONF_E_RX_ALTCRP, "RX-ALTCRP" }, - { L2IC_E_RX_ICCN, "RX-InCall-Connect" }, + { L2CONF_E_ESTABLISH_SESSION, "RX-InCall-Connect" }, { 0, NULL } }; @@ -221,7 +222,7 @@ static const struct osmo_fsm_state l2tp_conf_states[] = { .action = l2tp_conf_s_wait_for_tcrp, }, [L2CONF_S_WAIT_FOR_TC_SESSIONS] = { - .in_event_mask = S(L2CONF_E_RX_TCRP), + .in_event_mask = S(L2CONF_E_ESTABLISH_SESSION), .out_state_mask = S(L2CONF_S_WAIT_FOR_ALTCRP) | S(L2CONF_S_INIT), .name = "WAIT_FOR_TC_SESSIONS", @@ -235,7 +236,7 @@ static const struct osmo_fsm_state l2tp_conf_states[] = { .action = l2tp_conf_s_wait_for_altcrp, }, [L2CONF_S_WAIT_FOR_ALTC_SESSIONS] = { - .in_event_mask = S(L2CONF_E_RX_TCRP), + .in_event_mask = S(L2CONF_E_ESTABLISH_SESSION), .out_state_mask = S(L2CONF_S_ESTABLISHED) | S(L2CONF_S_INIT), .name = "WAIT_FOR_ALTC_SESSIONS", diff --git a/siu/l2tp/l2tpd_fsm.h b/siu/l2tp/l2tpd_fsm.h index cb97778..18037b6 100644 --- a/siu/l2tp/l2tpd_fsm.h +++ b/siu/l2tp/l2tpd_fsm.h @@ -17,10 +17,6 @@ enum l2tpd_ctrl_con_event { L2CC_E_RX_SCCCN, /* Received Stop CCN */ L2CC_E_RX_STOP_CCN, - /* Received Transport configuration Reply */ - L2CC_E_RX_TCRP, - /* Received Abis Lower Transport configuration Reply */ - L2CC_E_RX_ALTCRP, /* Received a HELLO / Keepalive */ L2CC_E_RX_HELLO, }; diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index dac0e6a..9542dc3 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -725,7 +725,7 @@ static int rx_eri_tcrp(struct l2tpd_connection *l2c, struct msgb *msg, struct av /* FIXME: result message */ osmo_fsm_inst_dispatch(l2c->fsm, L2CC_E_LOCAL_CLOSE_REQ, msg); } - osmo_fsm_inst_dispatch(l2c->fsm, L2CC_E_RX_TCRP, msg); + osmo_fsm_inst_dispatch(l2c->conf_fsm, L2CONF_E_RX_TCRP, msg); return 0; } @@ -747,7 +747,7 @@ static int rx_eri_altcrp(struct l2tpd_connection *l2c, struct msgb *msg, struct /* FIXME: result message */ osmo_fsm_inst_dispatch(l2c->fsm, L2CC_E_LOCAL_CLOSE_REQ, msg); } - osmo_fsm_inst_dispatch(l2c->fsm, L2CC_E_RX_ALTCRP, msg); + osmo_fsm_inst_dispatch(l2c->conf_fsm, L2CONF_E_RX_ALTCRP, msg); return 0; } From 53c8999df1a5e5e5854b9b1b5e3b896cc0532307 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Mon, 31 Oct 2016 00:41:18 +0100 Subject: [PATCH 115/133] l2tpd: move next_l_sess_id into l2tp_instance the sessions are unique to the daemon. E.g. data packets only contain a session id and no connection id --- siu/l2tp/l2tpd.c | 5 ++++- siu/l2tp/l2tpd.h | 6 ++++-- siu/l2tp/l2tpd_data.c | 6 ++---- siu/l2tp/l2tpd_data.h | 2 +- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/siu/l2tp/l2tpd.c b/siu/l2tp/l2tpd.c index 2061c4b..f37fd31 100644 --- a/siu/l2tp/l2tpd.c +++ b/siu/l2tp/l2tpd.c @@ -99,8 +99,11 @@ int main(int argc, char **argv) l2i = talloc_zero(tall_l2tp_ctx, struct l2tpd_instance); l2i->cfg.bind_ip = "0.0.0.0"; - /* important must not 0 */ + /* connection id starts with 1 */ l2i->next_l_cc_id = 1; + /* session id starts with 1 */ + l2i->next_l_sess_id = 1; + rc = l2tpd_instance_start(l2i); if (rc < 0) diff --git a/siu/l2tp/l2tpd.h b/siu/l2tp/l2tpd.h index d0fa2ff..e646d63 100644 --- a/siu/l2tp/l2tpd.h +++ b/siu/l2tp/l2tpd.h @@ -42,8 +42,6 @@ struct l2tpd_connection { uint16_t next_tx_seq_nr; /* seq nr of expected next Rx frame */ uint16_t next_rx_seq_nr; - /* next local session id */ - uint32_t next_l_sess_id; /* finite state machine for connection */ struct osmo_fsm_inst *fsm; /* finite state machine for traffic channels */ @@ -78,7 +76,11 @@ struct l2tpd_session { struct l2tpd_instance { /* list of l2tpd_connection */ struct llist_head connections; + /* next connection id */ uint32_t next_l_cc_id; + /* next local session id */ + uint32_t next_l_sess_id; + struct osmo_fd l2tp_ofd; diff --git a/siu/l2tp/l2tpd_data.c b/siu/l2tp/l2tpd_data.c index 0f36eb1..b9be352 100644 --- a/siu/l2tp/l2tpd_data.c +++ b/siu/l2tp/l2tpd_data.c @@ -79,19 +79,17 @@ l2tpd_cc_alloc(struct l2tpd_instance *l2i) llist_add(&l2c->list, &l2i->connections); l2c->fsm = osmo_fsm_inst_alloc(&l2tp_cc_fsm, l2c, l2c, LOGL_DEBUG, id_str); l2c->conf_fsm = osmo_fsm_inst_alloc(&l2tp_conf_fsm, l2c, l2c, LOGL_DEBUG, id_str); - /* session id starts with 1 */ - l2c->next_l_sess_id = 1; return l2c; } struct l2tpd_session * -l2tpd_sess_alloc(struct l2tpd_connection *conn) +l2tpd_sess_alloc(struct l2tpd_instance *l2i, struct l2tpd_connection *conn) { struct l2tpd_session *l2s = talloc_zero(conn, struct l2tpd_session); char id_str[12] = {0}; - l2s->l_sess_id = conn->next_l_sess_id++; + l2s->l_sess_id = l2i->next_l_sess_id++; snprintf(id_str, 12, "%d", l2s->l_sess_id); llist_add(&l2s->list, &conn->sessions); diff --git a/siu/l2tp/l2tpd_data.h b/siu/l2tp/l2tpd_data.h index c37680f..d546407 100644 --- a/siu/l2tp/l2tpd_data.h +++ b/siu/l2tp/l2tpd_data.h @@ -16,7 +16,7 @@ l2tpd_cc_alloc(struct l2tpd_instance *inst); /* l2tp session */ struct l2tpd_session * -l2tpd_sess_alloc(struct l2tpd_connection *conn); +l2tpd_sess_alloc(struct l2tpd_instance *inst, struct l2tpd_connection *conn); struct l2tpd_session * l2tpd_sess_find_by_l_s_id(struct l2tpd_connection *conn, uint32_t session_id); From af3181040f299078f6101a1e0b57b6d6a4bd9927 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Mon, 31 Oct 2016 00:45:47 +0100 Subject: [PATCH 116/133] l2tpd_data: search for a specific session_id using all connections because sessions are unique per l2tp_instance we have to search over all connections to find the correct session --- siu/l2tp/l2tpd_data.c | 11 +++++++---- siu/l2tp/l2tpd_data.h | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/siu/l2tp/l2tpd_data.c b/siu/l2tp/l2tpd_data.c index b9be352..881d7b2 100644 --- a/siu/l2tp/l2tpd_data.c +++ b/siu/l2tp/l2tpd_data.c @@ -100,12 +100,15 @@ l2tpd_sess_alloc(struct l2tpd_instance *l2i, struct l2tpd_connection *conn) } struct l2tpd_session * -l2tpd_sess_find_by_l_s_id(struct l2tpd_connection *conn, uint32_t session_id) +l2tpd_sess_find_by_l_s_id(struct l2tpd_instance *l2i, uint32_t session_id) { struct l2tpd_session *l2s; - llist_for_each_entry(l2s, &conn->sessions, list) { - if (l2s->l_sess_id == session_id) - return l2s; + struct l2tpd_connection *l2c; + llist_for_each_entry(l2c, &l2i->connections, list) { + llist_for_each_entry(l2s, &l2c->sessions, list) { + if (l2s->l_sess_id == session_id) + return l2s; + } } return NULL; } diff --git a/siu/l2tp/l2tpd_data.h b/siu/l2tp/l2tpd_data.h index d546407..df85fd6 100644 --- a/siu/l2tp/l2tpd_data.h +++ b/siu/l2tp/l2tpd_data.h @@ -19,4 +19,4 @@ struct l2tpd_session * l2tpd_sess_alloc(struct l2tpd_instance *inst, struct l2tpd_connection *conn); struct l2tpd_session * -l2tpd_sess_find_by_l_s_id(struct l2tpd_connection *conn, uint32_t session_id); +l2tpd_sess_find_by_l_s_id(struct l2tpd_instance *inst, uint32_t session_id); From 3f3191b4f013fbef124145a53c597c4ad644eae9 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Mon, 31 Oct 2016 22:27:17 +0100 Subject: [PATCH 117/133] l2tp_socket: handle unix sockets using wqueue --- siu/l2tp/l2tpd_socket.c | 113 ++++++++++++++++++++++++++++++++++++++++ siu/l2tp/l2tpd_socket.h | 21 ++++++++ 2 files changed, 134 insertions(+) create mode 100644 siu/l2tp/l2tpd_socket.c create mode 100644 siu/l2tp/l2tpd_socket.h diff --git a/siu/l2tp/l2tpd_socket.c b/siu/l2tp/l2tpd_socket.c new file mode 100644 index 0000000..17acc47 --- /dev/null +++ b/siu/l2tp/l2tpd_socket.c @@ -0,0 +1,113 @@ + +#include +#include +#include +#include +#include + + +#include +#include +#include +#include + +#include "l2tpd_socket.h" + +/* accept a new connection */ +static int mncc_sock_accept(struct osmo_fd *bfd, unsigned int flags) +{ + struct l2tp_socket_state *state = container_of(bfd, struct l2tp_socket_state, listen_bfd); + struct osmo_fd *conn_bfd = &state->wqueue.bfd; + struct sockaddr_un un_addr; + socklen_t len; + int rc; + + len = sizeof(un_addr); + rc = accept(bfd->fd, (struct sockaddr *) &un_addr, &len); + if (rc < 0) { + LOGP(state->log_class, LOGL_ERROR, "Failed to accept a new connection\n"); + return -1; + } + + if (conn_bfd->fd >= 0) { + LOGP(state->log_class, LOGL_NOTICE, "There is already one connection to the socket\n"); + osmo_fd_unregister(conn_bfd); + close(conn_bfd->fd); + return 0; + } + + conn_bfd->fd = rc; + conn_bfd->when = BSC_FD_READ | BSC_FD_WRITE; + + if (osmo_fd_register(conn_bfd) != 0) { + LOGP(state->log_class, LOGL_ERROR, "Failed to register new connection fd\n"); + close(conn_bfd->fd); + conn_bfd->fd = -1; + return -1; + } + + LOGP(state->log_class, LOGL_NOTICE, "MNCC Socket has connection with external " + "call control application\n"); + + return 0; +} + +void l2tp_set_read_callback(struct l2tp_socket_state *state, int (*read_cb)(struct osmo_fd *fd)) +{ + state->wqueue.read_cb = read_cb; +} + +void l2tp_set_write_callback(struct l2tp_socket_state *state, int (*write_cb)(struct osmo_fd *fd, struct msgb *msg)) +{ + state->wqueue.write_cb = write_cb; +} + + +/*! + * \brief l2tp_enqueue_data + * \param sock + * \return 0 on success + */ +int l2tp_socket_enqueue(struct l2tp_socket_state *state, struct msgb *msg) +{ + return osmo_wqueue_enqueue(&state->wqueue, msg); +} + +/*! + * \brief l2tp_socket_init + * \param sock + * \param sock_path + * \return 0 on success + */ +int l2tp_socket_init(struct l2tp_socket_state *state, const char *sock_path, int queue_len) +{ + struct osmo_fd *bfd; + int rc; + + osmo_wqueue_init(&state->wqueue, queue_len); + state->wqueue.bfd.fd = -1; + + bfd = &state->listen_bfd; + bfd->fd = osmo_sock_unix_init(SOCK_SEQPACKET, 0, sock_path, + OSMO_SOCK_F_BIND); + if (bfd->fd < 0) { + LOGP(state->log_class, LOGL_ERROR, "Could not create unix socket: %s: %s\n", + sock_path, strerror(errno)); + talloc_free(state); + return -1; + } + + bfd->when = BSC_FD_READ; + bfd->cb = mncc_sock_accept; + + rc = osmo_fd_register(bfd); + if (rc < 0) { + LOGP(state->log_class, LOGL_ERROR, "Could not register listen fd: %d\n", rc); + close(bfd->fd); + talloc_free(state); + return rc; + } + + LOGP(state->log_class, LOGL_NOTICE, "MNCC socket at %s\n", sock_path); + return 0; +} diff --git a/siu/l2tp/l2tpd_socket.h b/siu/l2tp/l2tpd_socket.h new file mode 100644 index 0000000..ce2ccca --- /dev/null +++ b/siu/l2tp/l2tpd_socket.h @@ -0,0 +1,21 @@ +#pragma once + +#include + +/*! + * \brief The socket_state struct represents a unix socket + */ +struct l2tp_socket_state { + /*! write queue of our data socket */ + struct osmo_wqueue wqueue; + /*! \brief listen_bfd listening socket*/ + struct osmo_fd listen_bfd; + + int log_class; +}; + +int l2tp_socket_init(struct l2tp_socket_state *state, const char *sock_path, int queue_len); +int l2tp_socket_enqueue(struct l2tp_socket_state *state, struct msgb *msg); + +void l2tp_set_read_callback(struct l2tp_socket_state *state, int (*read_cb)(struct osmo_fd *fd)); +void l2tp_set_write_callback(struct l2tp_socket_state *state, int (*write_cb)(struct osmo_fd *fd, struct msgb *msg)); From ea53d3999ea7c461b7a9ab54cee864f87dc75b79 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Wed, 2 Nov 2016 20:29:36 +0100 Subject: [PATCH 118/133] l2tp_socket_init: setup log_class in l2tp_socket_init --- siu/l2tp/Makefile | 2 +- siu/l2tp/l2tpd_socket.c | 3 ++- siu/l2tp/l2tpd_socket.h | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/siu/l2tp/Makefile b/siu/l2tp/Makefile index d035a62..ad95bd9 100644 --- a/siu/l2tp/Makefile +++ b/siu/l2tp/Makefile @@ -8,7 +8,7 @@ CFLAGS += $(EXTRA_CFLAGS) all: l2tpd -l2tpd: l2tpd.o l2tpd_fsm.o l2tpd_data.o l2tpd_packet.o +l2tpd: l2tpd.o l2tpd_fsm.o l2tpd_data.o l2tpd_packet.o l2tpd_socket.c $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) %.o: %.c diff --git a/siu/l2tp/l2tpd_socket.c b/siu/l2tp/l2tpd_socket.c index 17acc47..e7c02fa 100644 --- a/siu/l2tp/l2tpd_socket.c +++ b/siu/l2tp/l2tpd_socket.c @@ -79,11 +79,12 @@ int l2tp_socket_enqueue(struct l2tp_socket_state *state, struct msgb *msg) * \param sock_path * \return 0 on success */ -int l2tp_socket_init(struct l2tp_socket_state *state, const char *sock_path, int queue_len) +int l2tp_socket_init(struct l2tp_socket_state *state, const char *sock_path, int queue_len, int log_class) { struct osmo_fd *bfd; int rc; + state->log_class = log_class; osmo_wqueue_init(&state->wqueue, queue_len); state->wqueue.bfd.fd = -1; diff --git a/siu/l2tp/l2tpd_socket.h b/siu/l2tp/l2tpd_socket.h index ce2ccca..74d73a1 100644 --- a/siu/l2tp/l2tpd_socket.h +++ b/siu/l2tp/l2tpd_socket.h @@ -14,7 +14,7 @@ struct l2tp_socket_state { int log_class; }; -int l2tp_socket_init(struct l2tp_socket_state *state, const char *sock_path, int queue_len); +int l2tp_socket_init(struct l2tp_socket_state *state, const char *sock_path, int queue_len, int log_class); int l2tp_socket_enqueue(struct l2tp_socket_state *state, struct msgb *msg); void l2tp_set_read_callback(struct l2tp_socket_state *state, int (*read_cb)(struct osmo_fd *fd)); From 4c11f1bd238ea2926bd17dab85205c9e9b6e0e63 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Wed, 2 Nov 2016 20:46:08 +0100 Subject: [PATCH 119/133] l2tpd_packet: add msgb_free() after sending the message --- siu/l2tp/l2tpd_packet.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index 9542dc3..1df0393 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -308,6 +308,8 @@ static int l2tp_msgb_tx(struct msgb *msg, int not_ack) /* FIXME: put in the queue for reliable re-transmission */ ret = sendto(l2i->l2tp_ofd.fd, msgb_data(msg), msgb_length(msg), 0, &l2c->remote.ss, sizeof(l2c->remote.ss)); + + msgb_free(msg); if (ret < 0) return ret; return 0; From ee24efc5e0812c21a206e3bb4cef2f6147bc7b1f Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Wed, 2 Nov 2016 20:47:54 +0100 Subject: [PATCH 120/133] implement l2tpd_tx_data including crc32 --- siu/l2tp/crc32.c | 105 ++++++++++++++++++++++++++++++++++++++++ siu/l2tp/crc32.h | 3 ++ siu/l2tp/l2tpd_packet.c | 23 +++++++++ siu/l2tp/l2tpd_packet.h | 1 + 4 files changed, 132 insertions(+) create mode 100644 siu/l2tp/crc32.c create mode 100644 siu/l2tp/crc32.h diff --git a/siu/l2tp/crc32.c b/siu/l2tp/crc32.c new file mode 100644 index 0000000..5e181fd --- /dev/null +++ b/siu/l2tp/crc32.c @@ -0,0 +1,105 @@ +/*- + * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or + * code or tables extracted from it, as desired without restriction. + * + * First, the polynomial itself and its table of feedback terms. The + * polynomial is + * X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 + * + * Note that we take it "backwards" and put the highest-order term in + * the lowest-order bit. The X^32 term is "implied"; the LSB is the + * X^31 term, etc. The X^0 term (usually shown as "+1") results in + * the MSB being 1 + * + * Note that the usual hardware shift register implementation, which + * is what we're using (we're merely optimizing it by doing eight-bit + * chunks at a time) shifts bits into the lowest-order term. In our + * implementation, that means shifting towards the right. Why do we + * do it this way? Because the calculated CRC must be transmitted in + * order from highest-order term to lowest-order term. UARTs transmit + * characters in order from LSB to MSB. By storing the CRC this way + * we hand it to the UART in the order low-byte to high-byte; the UART + * sends each low-bit to hight-bit; and the result is transmission bit + * by bit from highest- to lowest-order term without requiring any bit + * shuffling on our part. Reception works similarly + * + * The feedback terms table consists of 256, 32-bit entries. Notes + * + * The table can be generated at runtime if desired; code to do so + * is shown later. It might not be obvious, but the feedback + * terms simply represent the results of eight shift/xor opera + * tions for all combinations of data and CRC register values + * + * The values must be right-shifted by eight bits by the "updcrc + * logic; the shift must be unsigned (bring in zeroes). On some + * hardware you could probably optimize the shift in assembler by + * using byte-swap instructions + * polynomial $edb88320 + * + * + * CRC32 code derived from work by Gary S. Brown. + */ + +#include +#include + +static uint32_t crc32_tab[] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, + 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, + 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, + 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, + 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, + 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, + 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, + 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, + 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, + 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, + 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, + 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, + 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, + 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, + 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, + 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, + 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, + 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d +}; + +uint32_t +crc32(uint32_t crc, const void *buf, size_t size) +{ + const uint8_t *p; + + p = buf; + crc = crc ^ ~0U; + + while (size--) + crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); + + return crc ^ ~0U; +} + diff --git a/siu/l2tp/crc32.h b/siu/l2tp/crc32.h new file mode 100644 index 0000000..ff4a05c --- /dev/null +++ b/siu/l2tp/crc32.h @@ -0,0 +1,3 @@ + +uint32_t +crc32(uint32_t crc, const void *buf, size_t size); diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index 1df0393..748f61d 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -18,6 +18,7 @@ #include "l2tpd.h" #include "l2tpd_data.h" #include "l2tpd_fsm.h" +#include "crc32.h" /*********************************************************************** * AVP Parser / Encoder @@ -315,6 +316,28 @@ static int l2tp_msgb_tx(struct msgb *msg, int not_ack) return 0; } +int l2tp_tx_data(struct msgb *msg) +{ + struct l2tp_data_hdr *hdr; + struct l2tpd_session *l2s = msg->dst; + struct l2tpd_connection *l2c = l2s->connection; + int ret; + uint32_t crc; + + hdr = (struct l2tp_data_hdr *) msgb_push(msg, sizeof(*hdr)); + hdr->session_id = htonl(l2s->r_sess_id); + hdr->sequence_id = htonl(l2s->next_tx_seq_nr++ | L2TP_DATA_SEQ_BIT); + hdr->crc = 0; + + crc = crc32(0x0, msgb_data(msg), (size_t) msgb_length(msg)); + hdr->crc = htonl(crc); + + ret = sendto(l2i->l2tp_ofd.fd, msgb_data(msg), msgb_length(msg), 0, &l2c->remote.ss, sizeof(l2c->remote.ss)); + if (ret < 0) + return ret; + return 0; +} + /*********************************************************************** * IETF specified messages ***********************************************************************/ diff --git a/siu/l2tp/l2tpd_packet.h b/siu/l2tp/l2tpd_packet.h index 85c271a..11a2fe7 100644 --- a/siu/l2tp/l2tpd_packet.h +++ b/siu/l2tp/l2tpd_packet.h @@ -18,5 +18,6 @@ int l2tp_tx_ic_rp(struct l2tpd_session *l2s); int l2tp_tx_hello(struct l2tpd_session *l2s); int l2tp_rcvmsg(struct msgb *msg); +int l2tp_tx_data(struct msgb *msg); struct msgb *l2tp_msgb_alloc(void); From 7c69530eae7830c8017b9ec42d2a9ebb6d0032df Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Wed, 2 Nov 2016 20:51:30 +0100 Subject: [PATCH 121/133] l2tpd_socket: complete unix socket implementation --- siu/l2tp/l2tpd_socket.c | 66 +++++++++++++++++++++++++++++++++-------- siu/l2tp/l2tpd_socket.h | 2 +- 2 files changed, 55 insertions(+), 13 deletions(-) diff --git a/siu/l2tp/l2tpd_socket.c b/siu/l2tp/l2tpd_socket.c index e7c02fa..98c3214 100644 --- a/siu/l2tp/l2tpd_socket.c +++ b/siu/l2tp/l2tpd_socket.c @@ -1,3 +1,24 @@ +/* generic unix socket interface + * + * (C) 2016 by Alexander Couzens + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ #include #include @@ -13,8 +34,33 @@ #include "l2tpd_socket.h" + +static int l2tp_sock_write(struct osmo_fd *bfd, struct msgb *msg) +{ + int rc; + + rc = write(bfd->fd, msg->data, msg->len); + if (rc != msg->len) + LOGP(DLCTRL, LOGL_ERROR, "Failed to write message to the unix connection.\n"); + + return rc; +} + +int l2tp_sock_cleanup(struct osmo_fd *bfd) +{ + int rc; + struct osmo_wqueue *wq = container_of(bfd, struct osmo_wqueue, bfd); + + osmo_wqueue_clear(wq); + rc = close(bfd->fd); + osmo_fd_unregister(bfd); + bfd->fd = -1; + + return rc; +} + /* accept a new connection */ -static int mncc_sock_accept(struct osmo_fd *bfd, unsigned int flags) +static int l2tp_sock_accept(struct osmo_fd *bfd, unsigned int flags) { struct l2tp_socket_state *state = container_of(bfd, struct l2tp_socket_state, listen_bfd); struct osmo_fd *conn_bfd = &state->wqueue.bfd; @@ -31,13 +77,12 @@ static int mncc_sock_accept(struct osmo_fd *bfd, unsigned int flags) if (conn_bfd->fd >= 0) { LOGP(state->log_class, LOGL_NOTICE, "There is already one connection to the socket\n"); - osmo_fd_unregister(conn_bfd); - close(conn_bfd->fd); + l2tp_sock_cleanup(conn_bfd); return 0; } conn_bfd->fd = rc; - conn_bfd->when = BSC_FD_READ | BSC_FD_WRITE; + conn_bfd->when = BSC_FD_READ; if (osmo_fd_register(conn_bfd) != 0) { LOGP(state->log_class, LOGL_ERROR, "Failed to register new connection fd\n"); @@ -46,7 +91,10 @@ static int mncc_sock_accept(struct osmo_fd *bfd, unsigned int flags) return -1; } - LOGP(state->log_class, LOGL_NOTICE, "MNCC Socket has connection with external " + state->wqueue.write_cb = l2tp_sock_write; + state->wqueue.except_cb = l2tp_sock_cleanup; + + LOGP(state->log_class, LOGL_NOTICE, "Unix Socket has connection with external " "call control application\n"); return 0; @@ -57,12 +105,6 @@ void l2tp_set_read_callback(struct l2tp_socket_state *state, int (*read_cb)(stru state->wqueue.read_cb = read_cb; } -void l2tp_set_write_callback(struct l2tp_socket_state *state, int (*write_cb)(struct osmo_fd *fd, struct msgb *msg)) -{ - state->wqueue.write_cb = write_cb; -} - - /*! * \brief l2tp_enqueue_data * \param sock @@ -99,7 +141,7 @@ int l2tp_socket_init(struct l2tp_socket_state *state, const char *sock_path, int } bfd->when = BSC_FD_READ; - bfd->cb = mncc_sock_accept; + bfd->cb = l2tp_sock_accept; rc = osmo_fd_register(bfd); if (rc < 0) { diff --git a/siu/l2tp/l2tpd_socket.h b/siu/l2tp/l2tpd_socket.h index 74d73a1..a629813 100644 --- a/siu/l2tp/l2tpd_socket.h +++ b/siu/l2tp/l2tpd_socket.h @@ -18,4 +18,4 @@ int l2tp_socket_init(struct l2tp_socket_state *state, const char *sock_path, int int l2tp_socket_enqueue(struct l2tp_socket_state *state, struct msgb *msg); void l2tp_set_read_callback(struct l2tp_socket_state *state, int (*read_cb)(struct osmo_fd *fd)); -void l2tp_set_write_callback(struct l2tp_socket_state *state, int (*write_cb)(struct osmo_fd *fd, struct msgb *msg)); +int l2tp_sock_cleanup(struct osmo_fd *bfd); From 146e57ec329051cb2aca4cedc2a51e87e3b3ca9c Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Wed, 2 Nov 2016 20:56:32 +0100 Subject: [PATCH 122/133] fixup! implement l2tpd_tx_data including crc32 --- siu/l2tp/l2tp_protocol.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/siu/l2tp/l2tp_protocol.h b/siu/l2tp/l2tp_protocol.h index 1cde319..3424875 100644 --- a/siu/l2tp/l2tp_protocol.h +++ b/siu/l2tp/l2tp_protocol.h @@ -4,6 +4,15 @@ #define IPPROTO_L2TP 115 #endif +struct l2tp_data_hdr { + uint32_t session_id; /* session and message type */\ + uint32_t sequence_id; /* sequence number */ + uint32_t crc; +}; + +#define L2TP_DATA_SEQ_ID_MASK 0xffffff +#define L2TP_DATA_SEQ_BIT 0x40000000 + struct l2tp_control_hdr { uint16_t ver; /* Version and more */ uint16_t length; /* Length field */ From b2a4c2c85e615992c2121d8e2cc1e81e19b6096b Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Wed, 2 Nov 2016 21:28:16 +0100 Subject: [PATCH 123/133] l2tpd_packet: correct usage of l2tpd_data functions --- siu/l2tp/l2tpd_packet.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index 748f61d..7ac8de8 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -619,14 +619,14 @@ static int rx_ic_rq(struct l2tpd_connection *l2cc, struct msgb *msg, struct avps } if (r_sess_id == 0) { - l2s = l2tpd_sess_alloc(l2cc); + l2s = l2tpd_sess_alloc(l2i, l2cc); l2s->r_sess_id = l_sess_id; avpp_val_u16(ap, VENDOR_IETF, AVP_IETF_PW_TYPE, &l2s->pw_type); avpp_val_u8(ap, VENDOR_IETF, AVP_IETF_REMOTE_END, &l2s->remote_end_id); } else { LOGP(DL2TP, LOGL_NOTICE, "ccid %d: Received rx_ic_rq for already known session %u\n", l2cc->local.ccid, r_sess_id); - l2s = l2tpd_sess_find_by_l_s_id(l2cc, r_sess_id); + l2s = l2tpd_sess_find_by_l_s_id(l2i, r_sess_id); if (!l2s) { LOGP(DL2TP, LOGL_ERROR, "NoSession found for %u\n", r_sess_id); @@ -658,7 +658,7 @@ get_session_by_msg(struct l2tpd_connection *l2cc, struct msgb *msg, return NULL; } - l2s = l2tpd_sess_find_by_l_s_id(l2cc, r_sess_id); + l2s = l2tpd_sess_find_by_l_s_id(l2i, r_sess_id); if (!l2s) { LOGP(DL2TP, LOGL_ERROR, "ccid %d: Can not find session %d\n", l2cc->local.ccid, r_sess_id); From 404cfd772fff564542ca5db7ac04cd2b9019b004 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Wed, 2 Nov 2016 21:30:07 +0100 Subject: [PATCH 124/133] l2tpd_packet/controlconnection: improve sequence checks and log output --- siu/l2tp/l2tpd_packet.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index 7ac8de8..e69dd72 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -855,10 +855,22 @@ static int l2tp_rcvmsg_control(struct msgb *msg) } /* FIXME: do real seq numbering. check if already received etc. */ - if (l2c->next_rx_seq_nr < (ch->Ns + 1)) - l2c->next_rx_seq_nr = ch->Ns + 1; + if (l2c->next_rx_seq_nr == ch->Ns) { + l2c->next_rx_seq_nr++; + /* everything ok */ + } else if (l2c->next_rx_seq_nr < ch->Ns) { + /* old packet, we already received this one, but might not sent a ACK */ + LOGP(DL2TP, LOGL_ERROR, "cid %d: wrong ch->Ns received. expectd %d != received %d.\n", l2c->local.ccid, l2c->next_rx_seq_nr, ch->Ns); + } else { + /* (l2c->next_rx_seq_nr > ch->Ns) + * lost some packets. ignore */ + LOGP(DL2TP, LOGL_ERROR, "cid %d: wrong ch->Ns received. expectd %d != received %d.\n", l2c->local.ccid, l2c->next_rx_seq_nr, ch->Ns); + return -1; + } + if (l2c->next_tx_seq_nr != ch->Nr) - LOGP(DL2TP, LOGL_ERROR, "cid %d: wrong seq number received. expectd %d != recveived %d.\n", l2c->local.ccid, l2c->next_tx_seq_nr, ch->Ns); + LOGP(DL2TP, LOGL_ERROR, "cid %d: wrong Nr received. expectd %d != received %d.\n", l2c->local.ccid, l2c->next_tx_seq_nr, ch->Nr); + } LOGP(DL2TP, LOGL_ERROR, "Rx: l2tp vendor/type 0x%04x/0x%04x 0x%04x\n", first_avp->vendor_id, first_avp->type, msg_type); From 1e1eebddc6d0b7ebaa4128018f4f2c38166ed256 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Wed, 2 Nov 2016 21:31:49 +0100 Subject: [PATCH 125/133] implement lapd decoding/encoding and rx/tx data path --- siu/l2tp/Makefile | 2 +- siu/l2tp/l2tp_protocol.h | 4 + siu/l2tp/l2tpd.c | 13 +- siu/l2tp/l2tpd.h | 16 ++- siu/l2tp/l2tpd_fsm.c | 15 +++ siu/l2tp/l2tpd_lapd.c | 260 +++++++++++++++++++++++++++++++++++++++ siu/l2tp/l2tpd_lapd.h | 7 ++ siu/l2tp/l2tpd_packet.c | 48 +++++++- 8 files changed, 359 insertions(+), 6 deletions(-) create mode 100644 siu/l2tp/l2tpd_lapd.c create mode 100644 siu/l2tp/l2tpd_lapd.h diff --git a/siu/l2tp/Makefile b/siu/l2tp/Makefile index ad95bd9..ba7bde5 100644 --- a/siu/l2tp/Makefile +++ b/siu/l2tp/Makefile @@ -8,7 +8,7 @@ CFLAGS += $(EXTRA_CFLAGS) all: l2tpd -l2tpd: l2tpd.o l2tpd_fsm.o l2tpd_data.o l2tpd_packet.o l2tpd_socket.c +l2tpd: l2tpd.o l2tpd_fsm.o l2tpd_data.o l2tpd_packet.o l2tpd_socket.c l2tpd_lapd.c $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) %.o: %.c diff --git a/siu/l2tp/l2tp_protocol.h b/siu/l2tp/l2tp_protocol.h index 3424875..77bc1c0 100644 --- a/siu/l2tp/l2tp_protocol.h +++ b/siu/l2tp/l2tp_protocol.h @@ -126,3 +126,7 @@ enum l2tp_eric_ctrlmsg { ERIC_CTRLMSG_ALTCRP = 5, ERIC_CTRLMSG_LCCSN = 6, }; + +#define TC_GROUP_TRAU 0x6 +#define TC_GROUP_PGSL 0x8 +#define TC_GROUP_RSL_OML 0x11 diff --git a/siu/l2tp/l2tpd.c b/siu/l2tp/l2tpd.c index f37fd31..16905b3 100644 --- a/siu/l2tp/l2tpd.c +++ b/siu/l2tp/l2tpd.c @@ -19,6 +19,8 @@ #include "l2tpd_data.h" #include "l2tpd_fsm.h" #include "l2tpd_packet.h" +#include "l2tpd_lapd.h" +#include "l2tpd_socket.h" struct l2tpd_instance *l2i; /* FIXME: global static instance */ @@ -99,12 +101,14 @@ int main(int argc, char **argv) l2i = talloc_zero(tall_l2tp_ctx, struct l2tpd_instance); l2i->cfg.bind_ip = "0.0.0.0"; + l2i->cfg.rsl_oml_path = "/tmp/rsl_oml"; + l2i->cfg.pgsl_path = "/tmp/pgsl_oml"; + l2i->cfg.trau_path = "/tmp/trau_oml"; /* connection id starts with 1 */ l2i->next_l_cc_id = 1; /* session id starts with 1 */ l2i->next_l_sess_id = 1; - rc = l2tpd_instance_start(l2i); if (rc < 0) exit(1); @@ -114,6 +118,13 @@ int main(int argc, char **argv) log_add_target(stderr_target); log_set_print_filename(stderr_target, 0); + l2tp_socket_init(&l2i->rsl_oml.state, l2i->cfg.rsl_oml_path, 100, DL2TP); + l2tp_socket_init(&l2i->trau.state, l2i->cfg.trau_path, 100, DL2TP); + l2tp_socket_init(&l2i->pgsl.state, l2i->cfg.pgsl_path, 100, DL2TP); + + l2tp_set_read_callback(&l2i->rsl_oml.state, unix_rsl_oml_cb); + l2tp_set_read_callback(&l2i->pgsl.state, unix_rsl_oml_cb); + l2tp_set_read_callback(&l2i->trau.state, unix_rsl_oml_cb); while (1) { osmo_select_main(0); diff --git a/siu/l2tp/l2tpd.h b/siu/l2tp/l2tpd.h index e646d63..fe50ef5 100644 --- a/siu/l2tp/l2tpd.h +++ b/siu/l2tp/l2tpd.h @@ -9,6 +9,8 @@ #include #include +#include "l2tpd_socket.h" + static inline void *msgb_l2tph(struct msgb *msg) { return msg->l2h; @@ -73,6 +75,11 @@ struct l2tpd_session { /* TODO: sockets for TRAU and PCU */ }; +struct traffic_channel { + struct l2tp_socket_state state; + struct l2tpd_session *session; +}; + struct l2tpd_instance { /* list of l2tpd_connection */ struct llist_head connections; @@ -81,11 +88,18 @@ struct l2tpd_instance { /* next local session id */ uint32_t next_l_sess_id; - struct osmo_fd l2tp_ofd; + /* unix sockets */ + + struct traffic_channel rsl_oml; + struct traffic_channel trau; + struct traffic_channel pgsl; struct { const char *bind_ip; + const char *rsl_oml_path; + const char *pgsl_path; + const char *trau_path; } cfg; }; diff --git a/siu/l2tp/l2tpd_fsm.c b/siu/l2tp/l2tpd_fsm.c index 01495a8..f1e3d3d 100644 --- a/siu/l2tp/l2tpd_fsm.c +++ b/siu/l2tp/l2tpd_fsm.c @@ -1,6 +1,8 @@ #include +#include "l2tp_protocol.h" + #include "l2tpd.h" #include "l2tpd_packet.h" #include "l2tpd_data.h" @@ -297,12 +299,25 @@ static void l2tp_ic_s_wait_conn(struct osmo_fsm_inst *fi, uint32_t event, void * if (!l2tp_tx_ack(l2c)) { osmo_fsm_inst_state_chg(fi, L2IC_S_ESTABLISHED, 0, 0); osmo_fsm_inst_dispatch(l2c->conf_fsm, L2CONF_E_ESTABLISH_SESSION, data); + switch (l2s->remote_end_id) { + /* FIXME: kick out the old session */ + case TC_GROUP_PGSL: + l2i->pgsl.session = l2s; + break; + case TC_GROUP_RSL_OML: + l2i->rsl_oml.session = l2s; + break; + case TC_GROUP_TRAU: + l2i->trau.session = l2s; + break; + } } } } static void l2tp_ic_s_established(struct osmo_fsm_inst *fi, uint32_t event, void *data) { + /* FIXME: remove old session if it got dealloc from l2i->trau.session etc. */ } diff --git a/siu/l2tp/l2tpd_lapd.c b/siu/l2tp/l2tpd_lapd.c new file mode 100644 index 0000000..9b6095a --- /dev/null +++ b/siu/l2tp/l2tpd_lapd.c @@ -0,0 +1,260 @@ + + +#include +#include +#include +#include + +#include "l2tp_protocol.h" + +#include "l2tpd.h" +#include "l2tpd_lapd.h" +#include "l2tpd_packet.h" +#include "l2tpd_socket.h" + +/* lapd and ehdlc differs in the first 16 bit + * lapd saves tei, sapi, c/r bit, ea1, ea2 bit + * ehdlc saves tei, sapi, c/r and length in a compressed way, + * meaining tei & sapi are limited to certain values */ + +#define LAPD_SAPI_SHIFT 10 +#define LAPD_SAPI_MASK 0xfc00 +#define LAPD_TEI_SHIFT 1 +#define LAPD_TEI_MASK 0x00fe +#define LAPD_CR_BIT_MASK 0x0200 +#define LAPD_EA2_BIT_MASK 0x0001 + +#define EHDLC_CSAPI_MASK 0xe000 +#define EHDLC_CSAPI_SHIFT 13 +#define EHDLC_CTEI_MASK 0x1e00 +#define EHDLC_CTEI_SHIFT 9 +#define EHDLC_LENGTH_MASK 0x01ff + +/*! + * \brief csapi_to_sapi + * \param csapi + * \return sapi + */ +static int csapi_to_sapi(int csapi) +{ + switch (csapi) { + case 0: + case 1: + return 0; + case 2: + return 10; + + case 3: + return 11; + case 4: + return 12; + case 5: + case 6: + return 62; + default: + return -1; + } +} + +/*! + * \brief csapi_to_cr + * \param csapi + * \return cr bit + */ +static int csapi_to_cr(int csapi) +{ + switch (csapi) { + case 0: + return 0; + case 1: + return 1; + case 2: + case 3: + case 4: + case 5: + return 0; + case 6: + return 1; + default: + return -1; + } +} + +/*! + * \brief sapi_to_csapi + * \param sapi + * \param cr c/r bit + * \return + */ +static int sapi_to_csapi(int sapi, int cr) +{ + switch (sapi) { + case 0: + return cr ? 1 : 0; + case 10: + return 2; + case 11: + return 3; + case 12: + return 4; + case 62: + return cr ? 6 : 5; + default: + return -1; + } +} + +static int tei_to_ctei(int tei) +{ + if (tei >= 0 && tei <= 11) + return tei; + else if (tei >= 60 && tei <= 63) + return tei - 48; + else /* invalid */ + return -1; +} + +static int ctei_to_tei(int ctei) +{ + if (ctei >= 0 && ctei <= 11) + return ctei; + else if (ctei >= 12 && ctei <= 15) + return ctei + 48; + else /* invalid */ + return -1; +} + +int lapd_lapd_to_ehdlc(struct l2tpd_instance *l2i, struct msgb *msg) +{ + uint16_t lapd_address = osmo_load16be(msgb_data(msg)); + uint16_t ehdlc_compressed = 0; + int sapi = lapd_address >> LAPD_SAPI_SHIFT; + int tei = (lapd_address & LAPD_TEI_MASK) >> LAPD_TEI_SHIFT; + int cr = lapd_address & LAPD_CR_BIT_MASK; + int length = msgb_length(msg); + + ehdlc_compressed |= (sapi_to_csapi(sapi, cr) << EHDLC_CSAPI_SHIFT) & EHDLC_CSAPI_MASK; + ehdlc_compressed |= (tei_to_ctei(tei) << EHDLC_CTEI_SHIFT) & EHDLC_CTEI_MASK; + ehdlc_compressed |= length & EHDLC_LENGTH_MASK; + + osmo_store16be(ehdlc_compressed, msgb_data(msg)); + + return l2tp_tx_data(msg); +} + +/*! + * \brief lapd_ehdlc_to_lapd + * \param l2i + * \param session which received the packets + * \param msg + * \return + */ +int lapd_ehdlc_to_lapd(struct l2tpd_instance *l2i, struct l2tpd_session *l2s, struct msgb *msg) +{ + struct traffic_channel *channel = NULL; + switch (l2s->remote_end_id) { + case TC_GROUP_PGSL: + channel = &l2i->pgsl; + break; + + case TC_GROUP_RSL_OML: + channel = &l2i->rsl_oml; + break; + case TC_GROUP_TRAU: + channel = &l2i->trau; + break; + } + + if (!channel) { + LOGP(DL2TP, LOGL_NOTICE, "Can not find traffic channel for session %d\n", l2s->l_sess_id); + return -1; + } + + /* FIXME: do we have to sent empty packets ? */ + while (msgb_length(msg) > 2) { + struct msgb *send_msg; + uint16_t lapd_address = 0; + uint16_t ehdlc_compressed = osmo_load16be(msgb_data(msg)); + int csapi = (ehdlc_compressed & EHDLC_CSAPI_MASK) >> EHDLC_CSAPI_SHIFT; + int ctei = (ehdlc_compressed & EHDLC_CTEI_MASK) >> EHDLC_CTEI_SHIFT; + int length = (ehdlc_compressed & EHDLC_LENGTH_MASK); + + lapd_address |= (csapi_to_sapi(csapi) << LAPD_SAPI_SHIFT) & LAPD_SAPI_MASK; + lapd_address |= csapi_to_cr(csapi) ? LAPD_CR_BIT_MASK : 0; + lapd_address |= (ctei_to_tei(ctei) << LAPD_TEI_SHIFT) & LAPD_TEI_MASK; + lapd_address |= LAPD_EA2_BIT_MASK; + + osmo_store16be(lapd_address, msgb_data(msg)); + + if (length > msgb_length(msg)) { + LOGP(DL2TP, LOGL_NOTICE, "Can not parse msg as ehdlc because its to short. %d > %d.\n", length, msgb_length(msg)); + return 0; + } + + send_msg = msgb_alloc(length + 128, "lapd frame"); + memcpy(msgb_data(send_msg), msgb_data(msg), length); + msgb_pull(msg, length); + msgb_put(send_msg, length); + + l2tp_socket_enqueue(&channel->state, send_msg); + } + + if (msgb_length(msg) > 0) + LOGP(DL2TP, LOGL_NOTICE, "ehdlc_to_lapd: bytes leftover after parsing %d.\n", msgb_length(msg)); + + return 0; +} + + +/*! + * \brief rsl_oml_cb called when data arrived on the unix socket + * \param fd + * \return 0 on success + */ +int unix_rsl_oml_cb(struct osmo_fd *fd) +{ + struct msgb *msg = l2tp_msgb_alloc(); + int rc; + + struct osmo_wqueue *wqueue = container_of(fd, struct osmo_wqueue, bfd); + struct l2tp_socket_state *state = container_of(wqueue, struct l2tp_socket_state, wqueue); + struct traffic_channel *channel = container_of(state, struct traffic_channel, state); + + rc = read(fd->fd, msg->data, msg->data_len); + if (rc < 0) { + LOGP(DL2TP, LOGL_ERROR, "read failed %s\n", strerror(errno)); + return rc; + } else if (rc == 0) { + LOGP(DL2TP, LOGL_ERROR, "closing socket because read 0 bytes\n"); + l2tp_sock_cleanup(fd); + return 0; + } + if (rc > 3) { + LOGP(DL2TP, LOGL_ERROR, "read %d\n", rc); + } + msgb_put(msg, rc); + msg->dst = channel->session; + + if (!channel->session) { + LOGP(DL2TP, LOGL_NOTICE, "Drop packets.\n"); + msgb_free(msg); + return 1; + } + + rc = lapd_lapd_to_ehdlc(l2i, msg); + if (rc) { + LOGP(DL2TP, LOGL_NOTICE, "lapd_to_ehlc returned != 0: %d.\n", rc); + } + + return 0; +} + +int unix_trau_cb(struct osmo_fd *fd) +{ + return 0; +} + +int unix_pgsl_cb(struct osmo_fd *fd) +{ + return 0; +} diff --git a/siu/l2tp/l2tpd_lapd.h b/siu/l2tp/l2tpd_lapd.h new file mode 100644 index 0000000..ba2c240 --- /dev/null +++ b/siu/l2tp/l2tpd_lapd.h @@ -0,0 +1,7 @@ +#pragma once + +int lapd_lapd_to_ehdlc(struct l2tpd_instance *l2i, struct msgb *msg); +int lapd_ehdlc_to_lapd(struct l2tpd_instance *l2i, struct l2tpd_session *session, struct msgb *msg); +int unix_rsl_oml_cb(struct osmo_fd *fd); +int unix_trau_cb(struct osmo_fd *fd); +int unix_pgsl_cb(struct osmo_fd *fd); diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index e69dd72..3b667df 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -18,6 +18,7 @@ #include "l2tpd.h" #include "l2tpd_data.h" #include "l2tpd_fsm.h" +#include "l2tpd_lapd.h" #include "crc32.h" /*********************************************************************** @@ -886,10 +887,50 @@ static int l2tp_rcvmsg_control(struct msgb *msg) return -1; } -static int l2tp_rcvmsg_data(struct msgb *msg, bool ip_transport) +static int l2tp_rcvmsg_data(struct msgb *msg) { - DEBUGP(DL2TP, "rx data: %s\n", msgb_hexdump(msg)); - return 0; + struct l2tp_data_hdr *hdr; + struct l2tpd_session *l2s; + int len = msgb_length(msg); + uint32_t sequence_id = 0; + + if (len < sizeof(*hdr)) { + LOGP(DL2TP, LOGL_INFO, "Received data packet which is to small %d < %d.\n", len, 12); + return -1; + } + + hdr = (struct l2tp_data_hdr *) msgb_data(msg); + hdr->session_id = htonl(hdr->session_id); + hdr->sequence_id = htonl(hdr->sequence_id); + hdr->crc = htonl(hdr->crc); + sequence_id = hdr->sequence_id & L2TP_DATA_SEQ_ID_MASK; + msgb_pull(msg, sizeof(*hdr)); + + l2s = l2tpd_sess_find_by_l_s_id(l2i, hdr->session_id); + if (!l2s) { + LOGP(DL2TP, LOGL_INFO, "session %u: Received data packet for an unknown session.\n", hdr->session_id); + return -1; + } + + if (!(hdr->sequence_id & L2TP_DATA_SEQ_BIT)) { + LOGP(DL2TP, LOGL_INFO, "session %u: Ignoring packets because of missing seq bit.\n", hdr->session_id); + return -1; + } + + /* check sequence id */ + if (sequence_id < l2s->next_rx_seq_nr) { + LOGP(DL2TP, LOGL_DEBUG, "session %d: Received old data packet %d.\n", l2s->l_sess_id, sequence_id); + return -1; + } else if (sequence_id > l2s->next_rx_seq_nr) { + LOGP(DL2TP, LOGL_DEBUG, "session %d: Received a data packet of the future %d.\n", l2s->l_sess_id, hdr->session_id); + } else { + l2s->next_rx_seq_nr++; + } + + /* ignore crc on rx */ + struct msgb *send_msg = msgb_copy(msg, "data_to_unix"); + + return lapd_ehdlc_to_lapd(l2i, l2s, send_msg); } int l2tp_rcvmsg(struct msgb *msg) @@ -900,6 +941,7 @@ int l2tp_rcvmsg(struct msgb *msg) msgb_pull(msg, sizeof(session)); return l2tp_rcvmsg_control(msg); } else { + l2tp_rcvmsg_data(msg); LOGP(DL2TP, LOGL_ERROR, "Received session %d data.\n", session); } return -1; From 82888d95582dc40183a073f9fb5f96b0c836c00c Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Wed, 2 Nov 2016 21:32:20 +0100 Subject: [PATCH 126/133] fixup! implement l2tpd_tx_data including crc32 --- siu/l2tp/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/siu/l2tp/Makefile b/siu/l2tp/Makefile index ba7bde5..86734c2 100644 --- a/siu/l2tp/Makefile +++ b/siu/l2tp/Makefile @@ -8,7 +8,7 @@ CFLAGS += $(EXTRA_CFLAGS) all: l2tpd -l2tpd: l2tpd.o l2tpd_fsm.o l2tpd_data.o l2tpd_packet.o l2tpd_socket.c l2tpd_lapd.c +l2tpd: l2tpd.o l2tpd_fsm.o l2tpd_data.o l2tpd_packet.o l2tpd_socket.c l2tpd_lapd.c crc32.c $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) %.o: %.c From d601392fa7bfe92dd4612585751a03edc20f5e3b Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Wed, 2 Nov 2016 21:45:55 +0100 Subject: [PATCH 127/133] add simple test_connect example programm --- siu/l2tp/Makefile | 5 +- siu/l2tp/test_connect.c | 102 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 siu/l2tp/test_connect.c diff --git a/siu/l2tp/Makefile b/siu/l2tp/Makefile index 86734c2..aa3b12f 100644 --- a/siu/l2tp/Makefile +++ b/siu/l2tp/Makefile @@ -6,11 +6,14 @@ LDFLAGS := -L $(PREFIX)/lib -lcrypto -losmocore -losmogsm -ltalloc CFLAGS += $(EXTRA_CFLAGS) -all: l2tpd +all: l2tpd test_connect l2tpd: l2tpd.o l2tpd_fsm.o l2tpd_data.o l2tpd_packet.o l2tpd_socket.c l2tpd_lapd.c crc32.c $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) +test_connect: test_connect.o + $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) + %.o: %.c $(CC) $(CFLAGS) -c $^ -o $@ diff --git a/siu/l2tp/test_connect.c b/siu/l2tp/test_connect.c new file mode 100644 index 0000000..be8990e --- /dev/null +++ b/siu/l2tp/test_connect.c @@ -0,0 +1,102 @@ +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +int socket_read(struct osmo_fd *bfd, unsigned int flags) +{ + struct msgb *msg = msgb_alloc(1500, "rx unix data"); + int rc; + + printf("Socket read called\n"); + /* actually read the message from the raw IP socket */ + rc = read(bfd->fd, msg->data, msg->data_len); + if (rc < 0) { + printf("recievefrom failed %s\n", strerror(errno)); + return rc; + } + msgb_put(msg, rc); + printf("Recv data\n"); + printf(msgb_hexdump(msg)); + printf("\n"); + + msgb_free(msg); + return 0; +} + +int connect_bfd(struct osmo_fd *bfd, const char *sock_path) +{ + int rc = 0; + + bfd->when = BSC_FD_READ; + bfd->cb = socket_read; + bfd->fd = osmo_sock_unix_init(SOCK_SEQPACKET, 0, sock_path,OSMO_SOCK_F_CONNECT); + + rc = osmo_fd_register(bfd); + + return rc; +} + +struct osmo_timer_list timer; + +void timer_cb(void *priv) +{ + struct osmo_fd *bfd = priv; + const uint8_t xid_62_62[16] = { + 0xfa, 0x7d, 0xaf, 0x82, 0x80, 0x00, 0x09, 0x07, 0x01, 0x0b, 0x09, 0x01, 0x0e, 0x08, 0x01, 0x03 + }; + const uint8_t xid_0_1[16] = { + 0x02, 0x03, 0xaf, 0x82, 0x80, 0x00, 0x09, 0x07, 0x01, 0x0b, 0x09, 0x01, 0x0e, 0x08, 0x01, 0x03 + }; + + const uint8_t xid_62_1[16] = { + 0xfa, 0x03, 0xaf, 0x82, 0x80, 0x00, 0x09, 0x07, 0x01, 0x0b, 0x09, 0x01, 0x0e, 0x08, 0x01, 0x03 + }; + + const uint8_t xid_sabm[3] = { + 0xfa, 0x03, 0x7f, + }; + + printf("Timer called\n"); + write(bfd->fd, xid_62_62, sizeof(xid_62_62)); +// write(bfd->fd, xid_0_1, sizeof(xid_0_1)); +// write(bfd->fd, xid_62_1, sizeof(xid_62_1)); +// write(bfd->fd, xid_sabm, sizeof(xid_sabm)); + + /* 300 ms */ + osmo_timer_schedule(&timer, 0, 300000); +} + +int main(int argc, const char *argv[]) +{ + struct osmo_fd bfd; + + void *tall_test_ctx = talloc_named_const(NULL, 1, "l2tp test context"); + if (!tall_test_ctx) + abort(); + + msgb_talloc_ctx_init(tall_test_ctx, 0); + if (connect_bfd(&bfd, "/tmp/rsl_oml")) { + printf("Can not connect"); + exit(1); + } + + timer.cb = timer_cb; + timer.data = &bfd; + + osmo_timer_schedule(&timer, 3, 0); + + for (;;) + osmo_select_main(0); + + return EXIT_SUCCESS; +} From 394608d082e535c9d6682ea4c4be84db506f32aa Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Fri, 4 Nov 2016 12:34:49 +0100 Subject: [PATCH 128/133] l2tpd socket naming: there's no oml associated with p-gsl or trau --- siu/l2tp/l2tpd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/siu/l2tp/l2tpd.c b/siu/l2tp/l2tpd.c index 16905b3..84f593d 100644 --- a/siu/l2tp/l2tpd.c +++ b/siu/l2tp/l2tpd.c @@ -102,8 +102,8 @@ int main(int argc, char **argv) l2i = talloc_zero(tall_l2tp_ctx, struct l2tpd_instance); l2i->cfg.bind_ip = "0.0.0.0"; l2i->cfg.rsl_oml_path = "/tmp/rsl_oml"; - l2i->cfg.pgsl_path = "/tmp/pgsl_oml"; - l2i->cfg.trau_path = "/tmp/trau_oml"; + l2i->cfg.pgsl_path = "/tmp/pgsl"; + l2i->cfg.trau_path = "/tmp/trau"; /* connection id starts with 1 */ l2i->next_l_cc_id = 1; /* session id starts with 1 */ From 283c2c3257fddc1a2ea9a54cd5f31468c46b52ff Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Tue, 8 Nov 2016 11:38:18 +0100 Subject: [PATCH 129/133] lapd: free message in unix_rsl_oml_cb() --- siu/l2tp/l2tpd_lapd.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/siu/l2tp/l2tpd_lapd.c b/siu/l2tp/l2tpd_lapd.c index 9b6095a..d83cd31 100644 --- a/siu/l2tp/l2tpd_lapd.c +++ b/siu/l2tp/l2tpd_lapd.c @@ -223,9 +223,11 @@ int unix_rsl_oml_cb(struct osmo_fd *fd) rc = read(fd->fd, msg->data, msg->data_len); if (rc < 0) { LOGP(DL2TP, LOGL_ERROR, "read failed %s\n", strerror(errno)); + msgb_free(msg); return rc; } else if (rc == 0) { LOGP(DL2TP, LOGL_ERROR, "closing socket because read 0 bytes\n"); + msgb_free(msg); l2tp_sock_cleanup(fd); return 0; } @@ -246,6 +248,7 @@ int unix_rsl_oml_cb(struct osmo_fd *fd) LOGP(DL2TP, LOGL_NOTICE, "lapd_to_ehlc returned != 0: %d.\n", rc); } + msgb_free(msg); return 0; } From 388a33ca9c0ef012bd5410ac667d9a873e2e81aa Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Tue, 8 Nov 2016 11:38:47 +0100 Subject: [PATCH 130/133] lapd: use l2tp_msgb_alloc() instead of msgb_alloc() --- siu/l2tp/l2tpd_lapd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/siu/l2tp/l2tpd_lapd.c b/siu/l2tp/l2tpd_lapd.c index d83cd31..f540b09 100644 --- a/siu/l2tp/l2tpd_lapd.c +++ b/siu/l2tp/l2tpd_lapd.c @@ -191,7 +191,7 @@ int lapd_ehdlc_to_lapd(struct l2tpd_instance *l2i, struct l2tpd_session *l2s, st return 0; } - send_msg = msgb_alloc(length + 128, "lapd frame"); + send_msg = l2tp_msgb_alloc(); memcpy(msgb_data(send_msg), msgb_data(msg), length); msgb_pull(msg, length); msgb_put(send_msg, length); From 95f8ae04bd6ece0989c754e16019dcce397aacbe Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Fri, 11 Nov 2016 16:17:54 +0100 Subject: [PATCH 131/133] lapd_switch_altc: allow to switch between timeslot and superchannel a special crafted packet can switch between the modes. The packet look like 0x23004200 as magic and 1byte as value (0 = timeslot, 1 = superchannel) --- siu/l2tp/l2tpd_lapd.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/siu/l2tp/l2tpd_lapd.c b/siu/l2tp/l2tpd_lapd.c index f540b09..1078018 100644 --- a/siu/l2tp/l2tpd_lapd.c +++ b/siu/l2tp/l2tpd_lapd.c @@ -205,6 +205,38 @@ int lapd_ehdlc_to_lapd(struct l2tpd_instance *l2i, struct l2tpd_session *l2s, st return 0; } +/*! + * \brief lapd_switch_altc try to parse the msg, if valid it change the ALTC type to the requested + * \param l2i + * \param msg + * \return 1 if valid and parsed, 0 if should passthrough to the siu + */ +int lapd_switch_altc(struct l2tpd_instance *l2i, struct msgb *msg) +{ + struct l2tpd_session *l2s = msg->dst; + + /* magic 0x23004200 (4 byte) + value (1 byte) */ + if (msgb_length(msg) != (4 + 1)) + return 0; + + /* skip lapd header */ + if (osmo_load32be(msgb_data(msg)) != 0x23004200) + return 0; + + /* pull data pointer to next object */ + msgb_pull(msg, 4); + + if (msgb_pull_u8(msg)) { + LOGP(DL2TP, LOGL_INFO, "ALTCRQ -> SuperChannel requested\n"); + l2tp_tx_altc_rq_superchannel(l2s->connection); + } else { + LOGP(DL2TP, LOGL_INFO, "ALTCRQ -> TimeSlot requested\n"); + l2tp_tx_altc_rq_timeslot(l2s->connection); + } + + return 1; +} + /*! * \brief rsl_oml_cb called when data arrived on the unix socket @@ -243,6 +275,12 @@ int unix_rsl_oml_cb(struct osmo_fd *fd) return 1; } + /* check if this packet is for us */ + if (lapd_switch_altc(l2i, msg)) { + msgb_free(msg); + return 0; + } + rc = lapd_lapd_to_ehdlc(l2i, msg); if (rc) { LOGP(DL2TP, LOGL_NOTICE, "lapd_to_ehlc returned != 0: %d.\n", rc); From 9143daf21eab777fd644741533e530b81282fc87 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Fri, 11 Nov 2016 16:18:24 +0100 Subject: [PATCH 132/133] l2tp_packet: remove logoutput on every data packet --- siu/l2tp/l2tpd_lapd.c | 4 +--- siu/l2tp/l2tpd_packet.c | 1 - 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/siu/l2tp/l2tpd_lapd.c b/siu/l2tp/l2tpd_lapd.c index 1078018..eeea628 100644 --- a/siu/l2tp/l2tpd_lapd.c +++ b/siu/l2tp/l2tpd_lapd.c @@ -263,9 +263,7 @@ int unix_rsl_oml_cb(struct osmo_fd *fd) l2tp_sock_cleanup(fd); return 0; } - if (rc > 3) { - LOGP(DL2TP, LOGL_ERROR, "read %d\n", rc); - } + msgb_put(msg, rc); msg->dst = channel->session; diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index 3b667df..1dcfb1b 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -942,7 +942,6 @@ int l2tp_rcvmsg(struct msgb *msg) return l2tp_rcvmsg_control(msg); } else { l2tp_rcvmsg_data(msg); - LOGP(DL2TP, LOGL_ERROR, "Received session %d data.\n", session); } return -1; } From eb07d89ffcc31100df55a7ad7f8ea985a36c0a49 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Fri, 11 Nov 2016 16:19:19 +0100 Subject: [PATCH 133/133] l2tp_packet: dont answer an ACK with a StopCCN if connection is unknown as long we don't do real ack handling, just ignore ACK without connection, because on a StopCCN an ACK is sent out --- siu/l2tp/l2tpd_packet.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/siu/l2tp/l2tpd_packet.c b/siu/l2tp/l2tpd_packet.c index 1dcfb1b..4f0fb77 100644 --- a/siu/l2tp/l2tpd_packet.c +++ b/siu/l2tp/l2tpd_packet.c @@ -851,7 +851,13 @@ static int l2tp_rcvmsg_control(struct msgb *msg) l2c = l2tpd_cc_find_by_l_cc_id(l2i, ch->ccid); if (!l2c) { LOGP(DL2TP, LOGL_ERROR, "l2tp: can not find a connection for ccid %d\n", ch->ccid); - l2tp_tx_stop_ccn_msg(msg); + /* ignore acks */ + if (first_avp->vendor_id != VENDOR_IETF || + first_avp->type != AVP_IETF_CTRL_MSG || + msg_type != IETF_CTRLMSG_ACK) { + l2tp_tx_stop_ccn_msg(msg); + } + return -1; }