diff --git a/src/mme/Makefile.am b/src/mme/Makefile.am index b53d718da..fafb52d5a 100644 --- a/src/mme/Makefile.am +++ b/src/mme/Makefile.am @@ -5,8 +5,9 @@ noinst_LTLIBRARIES = libmme.la libmme_la_SOURCES = \ mme-kdf.h kasumi.h snow-3g.h zuc.h \ mme-event.h mme-context.h \ - s1ap-build.h s1ap-handler.h s1ap-conv.h s1ap-path.h \ ogs-sctp.h \ + s1ap-build.h s1ap-handler.h s1ap-conv.h s1ap-path.h \ + sgsap-path.h \ mme-fd-path.h mme-s6a-handler.h \ nas-conv.h nas-security.h nas-path.h \ emm-handler.h emm-build.h \ @@ -15,8 +16,9 @@ libmme_la_SOURCES = \ mme-sm.h mme-path.h \ mme-kdf.c kasumi.c snow-3g.c zuc.c \ mme-init.c mme-event.c mme-context.c \ - s1ap-sm.c s1ap-build.c s1ap-handler.c s1ap-conv.c s1ap-path.c \ ogs-sctp.c \ + s1ap-sm.c s1ap-build.c s1ap-handler.c s1ap-conv.c s1ap-path.c \ + sgsap-sm.c sgsap-path.c \ mme-fd-path.c mme-s6a-handler.c \ nas-conv.c nas-security.c nas-path.c \ emm-sm.c emm-handler.c emm-build.c \ @@ -27,7 +29,7 @@ libmme_la_SOURCES = \ $(NULL) if WITH_USRSCTP -libmme_la_SOURCES += ogs-usrsctp.c s1ap-usrpath.c +libmme_la_SOURCES += ogs-usrsctp.c s1ap-usrpath.c sgsap-usrpath.c else libmme_la_SOURCES += ogs-lksctp.c s1ap-lkpath.c endif diff --git a/src/mme/mme-context.c b/src/mme/mme-context.c index 1bd785afe..a605ef572 100644 --- a/src/mme/mme-context.c +++ b/src/mme/mme-context.c @@ -1174,9 +1174,10 @@ int mme_context_parse_config() plmn_id_build(&plmn_id, atoi(mcc), atoi(mnc), strlen(mnc)); - nas_from_plmn_id(&vlr->nas_plmn_id, &plmn_id); - vlr->tac = atoi(tac); - vlr->lac = atoi(lac); + nas_from_plmn_id(&vlr->tai.plmn_id, &plmn_id); + vlr->tai.tac = atoi(tac); + nas_from_plmn_id(&vlr->lai.plmn_id, &plmn_id); + vlr->lai.lac = atoi(lac); } while (ogs_yaml_iter_type(&sgsap_array) == YAML_SEQUENCE_NODE); } else @@ -1552,6 +1553,32 @@ void mme_vlr_remove_all() mme_vlr_remove(vlr); } +mme_vlr_t *mme_vlr_find_by_tai(nas_tai_t *tai) +{ + mme_vlr_t *vlr = NULL; + ogs_assert(tai); + + ogs_list_for_each(&self.vlr_list, vlr) { + if (memcmp(&vlr->tai, tai, sizeof *tai) == 0) + return vlr; + } + + return NULL; +} + +mme_vlr_t *mme_vlr_find_by_lai(nas_lai_t *lai) +{ + mme_vlr_t *vlr = NULL; + ogs_assert(lai); + + ogs_list_for_each(&self.vlr_list, vlr) { + if (memcmp(&vlr->lai, lai, sizeof *lai) == 0) + return vlr; + } + + return NULL; +} + mme_enb_t *mme_enb_add(ogs_sock_t *sock, ogs_sockaddr_t *addr) { mme_enb_t *enb = NULL; diff --git a/src/mme/mme-context.h b/src/mme/mme-context.h index e7c60e190..b3aab3f5d 100644 --- a/src/mme/mme-context.h +++ b/src/mme/mme-context.h @@ -169,9 +169,8 @@ typedef struct mme_pgw_s { typedef struct mme_vlr_s { ogs_lnode_t lnode; - nas_plmn_id_t nas_plmn_id; - uint16_t tac; - uint16_t lac; + nas_tai_t tai; + nas_lai_t lai; ogs_socknode_t *node; } mme_vlr_t; @@ -546,6 +545,8 @@ ogs_sockaddr_t *mme_pgw_addr_find_by_apn( mme_vlr_t *mme_vlr_add(ogs_sockaddr_t *addr); void mme_vlr_remove(mme_vlr_t *vlr); void mme_vlr_remove_all(); +mme_vlr_t *mme_vlr_find_by_tai(nas_tai_t *tai); +mme_vlr_t *mme_vlr_find_by_lai(nas_lai_t *lai); mme_enb_t *mme_enb_add(ogs_sock_t *sock, ogs_sockaddr_t *addr); int mme_enb_remove(mme_enb_t *enb); diff --git a/src/mme/mme-event.c b/src/mme/mme-event.c index 723dae74b..1e3015d33 100644 --- a/src/mme/mme-event.c +++ b/src/mme/mme-event.c @@ -1,3 +1,22 @@ +/* + * Copyright (C) 2019 by Sukchan Lee + * + * This file is part of Open5GS. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 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, see . + */ + #include "mme-event.h" #include "mme-context.h" @@ -72,38 +91,41 @@ const char *mme_event_get_name(mme_event_t *e) if (e == NULL) return OGS_FSM_NAME_INIT_SIG; - switch (e->id) - { - case OGS_FSM_ENTRY_SIG: - return OGS_FSM_NAME_ENTRY_SIG; - case OGS_FSM_EXIT_SIG: - return OGS_FSM_NAME_EXIT_SIG; + switch (e->id) { + case OGS_FSM_ENTRY_SIG: + return OGS_FSM_NAME_ENTRY_SIG; + case OGS_FSM_EXIT_SIG: + return OGS_FSM_NAME_EXIT_SIG; - case MME_EVT_S1AP_MESSAGE: - return "MME_EVT_S1AP_MESSAGE"; - case MME_EVT_S1AP_DELAYED_SEND: - return "MME_EVT_S1AP_DELAYED_SEND"; - case MME_EVT_S1AP_LO_ACCEPT: - return "MME_EVT_S1AP_LO_ACCEPT"; - case MME_EVT_S1AP_LO_SCTP_COMM_UP: - return "MME_EVT_S1AP_LO_SCTP_COMM_UP"; - case MME_EVT_S1AP_LO_CONNREFUSED: - return "MME_EVT_S1AP_LO_CONNREFUSED"; + case MME_EVT_S1AP_MESSAGE: + return "MME_EVT_S1AP_MESSAGE"; + case MME_EVT_S1AP_DELAYED_SEND: + return "MME_EVT_S1AP_DELAYED_SEND"; + case MME_EVT_S1AP_LO_ACCEPT: + return "MME_EVT_S1AP_LO_ACCEPT"; + case MME_EVT_S1AP_LO_SCTP_COMM_UP: + return "MME_EVT_S1AP_LO_SCTP_COMM_UP"; + case MME_EVT_S1AP_LO_CONNREFUSED: + return "MME_EVT_S1AP_LO_CONNREFUSED"; - case MME_EVT_EMM_MESSAGE: - return "MME_EVT_EMM_MESSAGE"; + case MME_EVT_EMM_MESSAGE: + return "MME_EVT_EMM_MESSAGE"; + case MME_EVT_ESM_MESSAGE: + return "MME_EVT_ESM_MESSAGE"; + case MME_EVT_S11_MESSAGE: + return "MME_EVT_S11_MESSAGE"; + case MME_EVT_S6A_MESSAGE: + return "MME_EVT_S6A_MESSAGE"; - case MME_EVT_ESM_MESSAGE: - return "MME_EVT_ESM_MESSAGE"; + case MME_EVT_SGSAP_MESSAGE: + return "MME_EVT_SGSAP_MESSAGE"; + case MME_EVT_SGSAP_LO_WILL_CONNECT: + return "MME_EVT_SGSAP_LO_WILL_CONNECT"; + case MME_EVT_SGSAP_LO_CONNECTED: + return "MME_EVT_SGSAP_LO_CONNECTED"; - case MME_EVT_S11_MESSAGE: - return "MME_EVT_S11_MESSAGE"; - - case MME_EVT_S6A_MESSAGE: - return "MME_EVT_S6A_MESSAGE"; - - default: - break; + default: + break; } return "UNKNOWN_EVENT"; diff --git a/src/mme/mme-event.h b/src/mme/mme-event.h index 8888cf2cd..10d5dda26 100644 --- a/src/mme/mme-event.h +++ b/src/mme/mme-event.h @@ -1,11 +1,30 @@ -#ifndef __MME_EVENT_H__ -#define __MME_EVENT_H__ +/* + * Copyright (C) 2019 by Sukchan Lee + * + * This file is part of Open5GS. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 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, see . + */ + +#ifndef MME_EVENT_H +#define MME_EVENT_H #include "ogs-core.h" #ifdef __cplusplus extern "C" { -#endif /* __cplusplus */ +#endif /* forward declaration */ typedef enum { @@ -22,6 +41,10 @@ typedef enum { MME_EVT_S11_MESSAGE, MME_EVT_S6A_MESSAGE, + MME_EVT_SGSAP_MESSAGE, + MME_EVT_SGSAP_LO_WILL_CONNECT, + MME_EVT_SGSAP_LO_CONNECTED, + MME_EVT_TOP, } mme_event_e; @@ -72,6 +95,6 @@ const char *mme_event_get_name(mme_event_t *e); #ifdef __cplusplus } -#endif /* __cplusplus */ +#endif -#endif /* __MME_EVENT_H__ */ +#endif /* MME_EVENT_H */ diff --git a/src/mme/mme-sm.h b/src/mme/mme-sm.h index faccdbcab..0b817ca7b 100644 --- a/src/mme/mme-sm.h +++ b/src/mme/mme-sm.h @@ -54,6 +54,12 @@ void esm_state_pdn_did_disconnect(ogs_fsm_t *s, mme_event_t *e); void esm_state_bearer_deactivated(ogs_fsm_t *s, mme_event_t *e); void esm_state_exception(ogs_fsm_t *s, mme_event_t *e); +void sgsap_state_initial(ogs_fsm_t *s, mme_event_t *e); +void sgsap_state_final(ogs_fsm_t *s, mme_event_t *e); +void sgsap_state_will_connect(ogs_fsm_t *s, mme_event_t *e); +void sgsap_state_connected(ogs_fsm_t *s, mme_event_t *e); +void sgsap_state_exception(ogs_fsm_t *s, mme_event_t *e); + #define mme_sm_debug(__pe) \ ogs_debug("%s(): %s\n", __func__, mme_event_get_name(__pe)) diff --git a/src/mme/sgsap-path.c b/src/mme/sgsap-path.c new file mode 100644 index 000000000..9b1085c84 --- /dev/null +++ b/src/mme/sgsap-path.c @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2019 by Sukchan Lee + * + * This file is part of Open5GS. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 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, see . + */ + +#include "ogs-sctp.h" + +#include "sgsap-path.h" + +int sgsap_open() +{ + return OGS_OK; +} + +void sgsap_close() +{ +} + +int sgsap_send(ogs_sock_t *sock, ogs_pkbuf_t *pkbuf, + ogs_sockaddr_t *addr, uint16_t stream_no) +{ + int sent; + + ogs_assert(sock); + ogs_assert(pkbuf); + + sent = ogs_sctp_sendmsg(sock, pkbuf->data, pkbuf->len, + addr, SCTP_SGSAP_PPID, stream_no); + if (sent < 0 || sent != pkbuf->len) { + ogs_error("ogs_sctp_sendmsg error (%d:%s)", errno, strerror(errno)); + return OGS_ERROR; + } + ogs_pkbuf_free(pkbuf); + + return OGS_OK; +} + +int sgsap_recv(ogs_sock_t *sock, ogs_pkbuf_t *pkbuf) +{ + int size; + + ogs_assert(sock); + ogs_assert(pkbuf); + + size = ogs_sctp_recvdata(sock, pkbuf->data, MAX_SDU_LEN, NULL, NULL); + if (size <= 0) { + ogs_error("sgsap_recv() failed"); + return OGS_ERROR; + } + + ogs_pkbuf_trim(pkbuf, size); + return OGS_OK;; +} + +int sgsap_send_to_vlr(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf, uint16_t stream_no) +{ + char buf[OGS_ADDRSTRLEN]; + ogs_socknode_t *node = NULL;; + ogs_sock_t *sock = NULL;; + int rv; + + ogs_assert(vlr); + ogs_assert(pkbuf); + node = vlr->node; + ogs_assert(node); + sock = node->sock; + ogs_assert(sock); + + ogs_debug(" IP[%s] TAI[MCC:%d%d%d,MNC:%d%d%d,TAC:%d]", + OGS_ADDR(node->addr, buf), + vlr->tai.plmn_id.mcc1, vlr->tai.plmn_id.mcc2, vlr->tai.plmn_id.mcc3, + vlr->tai.plmn_id.mnc1, vlr->tai.plmn_id.mnc2, vlr->tai.plmn_id.mnc3, + vlr->tai.tac); + ogs_debug(" LAI[MCC:%d%d%d,MNC:%d%d%d,TAC:%d]", + vlr->lai.plmn_id.mcc1, vlr->lai.plmn_id.mcc2, vlr->lai.plmn_id.mcc3, + vlr->lai.plmn_id.mnc1, vlr->lai.plmn_id.mnc2, vlr->lai.plmn_id.mnc3, + vlr->lai.lac); + + rv = sgsap_send(sock, pkbuf, NULL, stream_no); + if (rv != OGS_OK) { + ogs_error("sgsap_send() failed"); + ogs_pkbuf_free(pkbuf); + } + + return OGS_OK;; +} + diff --git a/src/mme/sgsap-path.h b/src/mme/sgsap-path.h new file mode 100644 index 000000000..4da89b7d0 --- /dev/null +++ b/src/mme/sgsap-path.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2019 by Sukchan Lee + * + * This file is part of Open5GS. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 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, see . + */ + +#ifndef SGSAP_PATH_H +#define SGSAP_PATH_H + +#include "mme-context.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int sgsap_open(void); +void sgsap_close(void); + +ogs_sock_t *sgsap_client(ogs_socknode_t *node); +void sgsap_recv_handler(short when, ogs_socket_t fd, void *data); + +int sgsap_send(ogs_sock_t *sock, + ogs_pkbuf_t *pkbuf, ogs_sockaddr_t *addr, uint16_t stream_no); +int sgsap_recv(ogs_sock_t *sock, ogs_pkbuf_t *pkbuf); + +int sgsap_send_to_vlr(mme_vlr_t *vlr, ogs_pkbuf_t *pkb, uint16_t stream_no); + +#ifdef __cplusplus +} +#endif + +#endif /* SGSAP_PATH_H */ diff --git a/src/mme/sgsap-sm.c b/src/mme/sgsap-sm.c new file mode 100644 index 000000000..4f4fa430e --- /dev/null +++ b/src/mme/sgsap-sm.c @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2019 by Sukchan Lee + * + * This file is part of Open5GS. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 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, see . + */ + +#include "mme-event.h" +#include "mme-sm.h" + +void sgsap_state_initial(ogs_fsm_t *s, mme_event_t *e) +{ + ogs_assert(s); + + mme_sm_debug(e); + + OGS_FSM_TRAN(s, &sgsap_state_will_connect); +} + +void sgsap_state_final(ogs_fsm_t *s, mme_event_t *e) +{ + ogs_assert(s); + + mme_sm_debug(e); +} + +void sgsap_state_will_connect(ogs_fsm_t *s, mme_event_t *e) +{ + ogs_assert(s); + ogs_assert(e); + + mme_sm_debug(e); + + switch (e->id) { + case OGS_FSM_ENTRY_SIG: + break; + case OGS_FSM_EXIT_SIG: + break; + case MME_EVT_SGSAP_MESSAGE: + break; + default: + ogs_error("Unknown event %s", mme_event_get_name(e)); + break; + } +} + +void sgsap_state_connected(ogs_fsm_t *s, mme_event_t *e) +{ + ogs_assert(s); + ogs_assert(e); + + mme_sm_debug(e); + + switch (e->id) { + case OGS_FSM_ENTRY_SIG: + break; + case OGS_FSM_EXIT_SIG: + break; + case MME_EVT_SGSAP_MESSAGE: + break; + default: + ogs_error("Unknown event %s", mme_event_get_name(e)); + break; + } +} + +void sgsap_state_exception(ogs_fsm_t *s, mme_event_t *e) +{ + ogs_assert(s); + ogs_assert(e); + + mme_sm_debug(e); + + switch (e->id) { + case OGS_FSM_ENTRY_SIG: + break; + case OGS_FSM_EXIT_SIG: + break; + default: + ogs_error("Unknown event %s", mme_event_get_name(e)); + break; + } +} + diff --git a/src/mme/sgsap-usrpath.c b/src/mme/sgsap-usrpath.c new file mode 100644 index 000000000..ee60010e2 --- /dev/null +++ b/src/mme/sgsap-usrpath.c @@ -0,0 +1,243 @@ +/* + * Copyright (C) 2019 by Sukchan Lee + * + * This file is part of Open5GS. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 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, see . + */ + +#include "ogs-sctp.h" + +#include "app/context.h" +#include "sgsap-path.h" + +int sgsap_usrsctp_recv_handler(struct socket *sock, + union sctp_sockstore addr, void *data, size_t datalen, + struct sctp_rcvinfo rcv, int flags, void *ulp_info); + +#if 0 +static ogs_sockaddr_t *usrsctp_remote_addr(union sctp_sockstore *store); +#endif + +ogs_sock_t *sgsap_client(ogs_socknode_t *node) +{ + char buf[OGS_ADDRSTRLEN]; + ogs_sock_t *sock = NULL; + + ogs_assert(node); + + ogs_socknode_sctp_option(node, &context_self()->config.sockopt); + ogs_socknode_set_poll(node, mme_self()->pollset, + OGS_POLLIN, sgsap_usrsctp_recv_handler, node); + + sock = ogs_sctp_client(SOCK_STREAM, node); + ogs_assert(sock); + + ogs_info("sgsap_client() [%s]:%d", + OGS_ADDR(node->addr, buf), OGS_PORT(node->addr)); + + return sock; +} + +void sgsap_recv_handler(short when, ogs_socket_t fd, void *data) +{ + /* At this point, nextepc does not use SOCK_STREAM in libusrsctp */ + ogs_assert_if_reached(); +} + +int sgsap_usrsctp_recv_handler(struct socket *sock, + union sctp_sockstore store, void *data, size_t datalen, + struct sctp_rcvinfo rcv, int flags, void *ulp_info) +{ + if (data) { +#if 0 + int rv; + mme_event_t *e = NULL; + + if (flags & MSG_NOTIFICATION) { + union sctp_notification *not = (union sctp_notification *)data; + if (not->sn_header.sn_length == (uint32_t)datalen) { + switch(not->sn_header.sn_type) { + case SCTP_ASSOC_CHANGE : + { + ogs_debug("SCTP_ASSOC_CHANGE:" + "[T:%d, F:0x%x, S:%d, I/O:%d/%d]", + not->sn_assoc_change.sac_type, + not->sn_assoc_change.sac_flags, + not->sn_assoc_change.sac_state, + not->sn_assoc_change.sac_inbound_streams, + not->sn_assoc_change.sac_outbound_streams); + + if (not->sn_assoc_change.sac_state == + SCTP_SHUTDOWN_COMP || + not->sn_assoc_change.sac_state == + SCTP_COMM_LOST) { + ogs_sockaddr_t *addr = + usrsctp_remote_addr(&store); + ogs_assert(addr); + + if (not->sn_assoc_change.sac_state == + SCTP_SHUTDOWN_COMP) + ogs_debug("SCTP_SHUTDOWN_COMP"); + if (not->sn_assoc_change.sac_state == + SCTP_COMM_LOST) + ogs_debug("SCTP_COMM_LOST"); + + e = mme_event_new(MME_EVT_S1AP_LO_CONNREFUSED); + ogs_assert(e); + e->enb_sock = (ogs_sock_t *)sock; + e->enb_addr = addr; + rv = ogs_queue_push(mme_self()->queue, e); + if (rv != OGS_OK) { + ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_free(e->enb_addr); + mme_event_free(e); + } else { + ogs_pollset_notify(mme_self()->pollset); + } + } else if (not->sn_assoc_change.sac_state == SCTP_COMM_UP) { + ogs_sockaddr_t *addr = + usrsctp_remote_addr(&store); + ogs_assert(addr); + + ogs_debug("SCTP_COMM_UP"); + + e = mme_event_new(MME_EVT_S1AP_LO_SCTP_COMM_UP); + ogs_assert(e); + e->enb_sock = (ogs_sock_t *)sock; + e->enb_addr = addr; + e->inbound_streams = + not->sn_assoc_change.sac_inbound_streams; + e->outbound_streams = + not->sn_assoc_change.sac_outbound_streams; + rv = ogs_queue_push(mme_self()->queue, e); + if (rv != OGS_OK) { + ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_free(e->enb_addr); + mme_event_free(e); + } else { + ogs_pollset_notify(mme_self()->pollset); + } + } + break; + } + case SCTP_SHUTDOWN_EVENT : + { + ogs_sockaddr_t *addr = usrsctp_remote_addr(&store); + ogs_assert(addr); + + ogs_debug("SCTP_SHUTDOWN_EVENT:" + "[T:0x%x, F:0x%x, L:0x%x]", + not->sn_shutdown_event.sse_type, + not->sn_shutdown_event.sse_flags, + not->sn_shutdown_event.sse_length); + + e = mme_event_new(MME_EVT_S1AP_LO_CONNREFUSED); + ogs_assert(e); + e->enb_sock = (ogs_sock_t *)sock; + e->enb_addr = addr; + rv = ogs_queue_push(mme_self()->queue, e); + if (rv != OGS_OK) { + ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_free(e->enb_addr); + mme_event_free(e); + } else { + ogs_pollset_notify(mme_self()->pollset); + } + break; + } + case SCTP_PEER_ADDR_CHANGE: + ogs_warn("SCTP_PEER_ADDR_CHANGE:" + "[T:%d, F:0x%x, S:%d]", + not->sn_paddr_change.spc_type, + not->sn_paddr_change.spc_flags, + not->sn_paddr_change.spc_error); + break; + case SCTP_REMOTE_ERROR: + ogs_warn("SCTP_REMOTE_ERROR:[T:%d, F:0x%x, S:%d]", + not->sn_remote_error.sre_type, + not->sn_remote_error.sre_flags, + not->sn_remote_error.sre_error); + break; + case SCTP_SEND_FAILED : + ogs_error("SCTP_SEND_FAILED:[T:%d, F:0x%x, S:%d]", + not->sn_send_failed_event.ssfe_type, + not->sn_send_failed_event.ssfe_flags, + not->sn_send_failed_event.ssfe_error); + break; + default : + ogs_error("Discarding event with " + "unknown flags:0x%x type:0x%x", + flags, not->sn_header.sn_type); + break; + } + } + } else if (flags & MSG_EOR) { + ogs_pkbuf_t *pkbuf; + ogs_sockaddr_t *addr = NULL; + + pkbuf = ogs_pkbuf_alloc(NULL, MAX_SDU_LEN); + ogs_pkbuf_put_data(pkbuf, data, datalen); + + addr = usrsctp_remote_addr(&store); + ogs_assert(addr); + + e = mme_event_new(MME_EVT_S1AP_MESSAGE); + ogs_assert(e); + e->enb_sock = (ogs_sock_t *)sock; + e->enb_addr = addr; + e->pkbuf = pkbuf; + rv = ogs_queue_push(mme_self()->queue, e); + if (rv != OGS_OK) { + ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_free(e->enb_addr); + ogs_pkbuf_free(e->pkbuf); + mme_event_free(e); + } else { + ogs_pollset_notify(mme_self()->pollset); + } + } else { + ogs_error("Not engough buffer. Need more recv : 0x%x", flags); + } +#endif + free(data); + } + return (1); +} + +#if 0 +static ogs_sockaddr_t *usrsctp_remote_addr(union sctp_sockstore *store) +{ + ogs_sockaddr_t *addr = NULL; + + ogs_assert(store); + + addr = ogs_calloc(1, sizeof(ogs_sockaddr_t)); + ogs_assert(addr); + + addr->ogs_sa_family = store->sin.sin_family; + switch(addr->ogs_sa_family) { + case AF_INET: + memcpy(&addr->sin, &store->sin, sizeof(struct sockaddr_in)); + break; + case AF_INET6: + memcpy(&addr->sin6, &store->sin6, sizeof(struct sockaddr_in6)); + break; + default: + ogs_assert_if_reached(); + } + + return addr; +} +#endif