Merge branch 'master' into s1ap-brchiu

This commit is contained in:
Sukchan Lee
2018-03-09 21:02:17 +09:00
18 changed files with 350 additions and 58 deletions

View File

@@ -8,7 +8,7 @@ dnl This program is distributed in the hope that it will be useful, but
dnl WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
dnl implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
AC_INIT([NextEPC], [0.3.4], [acetcom@gmail.com])
AC_INIT([NextEPC], [0.3.5], [acetcom@gmail.com])
AC_SUBST(LIBVERSION)
LIBVERSION=1:0:0

12
debian/changelog vendored
View File

@@ -1,3 +1,15 @@
nextepc (0.3.5~xenial) xenial; urgency=medium
* Bug Fixed
-- Sukchan Lee <acetcom@gmail.com> Tue, 06 Mar 2018 12:41:53 +0000
nextepc (0.3.5~artful) artful; urgency=medium
* Bug Fixed
-- Sukchan Lee <acetcom@gmail.com> Tue, 06 Mar 2018 12:40:07 +0000
nextepc (0.3.4-1~xenial) xenial; urgency=medium
* Bug Fixed

View File

@@ -252,20 +252,40 @@ status_t emm_build_security_mode_command(
nas_key_set_identifier->tsc = 0;
nas_key_set_identifier->nas_key_set_identifier = 0;
replayed_ue_security_capabilities->length =
sizeof(replayed_ue_security_capabilities->eea) +
sizeof(replayed_ue_security_capabilities->eia) +
sizeof(replayed_ue_security_capabilities->uea) +
sizeof(replayed_ue_security_capabilities->uia) +
sizeof(replayed_ue_security_capabilities->gea);
replayed_ue_security_capabilities->eea = mme_ue->ue_network_capability.eea;
replayed_ue_security_capabilities->eia = mme_ue->ue_network_capability.eia;
replayed_ue_security_capabilities->uea = mme_ue->ue_network_capability.uea;
replayed_ue_security_capabilities->uia = mme_ue->ue_network_capability.uia;
replayed_ue_security_capabilities->uia =
mme_ue->ue_network_capability.uia & 0x7f;
replayed_ue_security_capabilities->gea =
(mme_ue->ms_network_capability.gea1 << 6) |
mme_ue->ms_network_capability.extended_gea;
replayed_ue_security_capabilities->length =
sizeof(replayed_ue_security_capabilities->eea) +
sizeof(replayed_ue_security_capabilities->eia);
if (replayed_ue_security_capabilities->uea ||
replayed_ue_security_capabilities->uia)
replayed_ue_security_capabilities->length =
sizeof(replayed_ue_security_capabilities->eea) +
sizeof(replayed_ue_security_capabilities->eia) +
sizeof(replayed_ue_security_capabilities->uea) +
sizeof(replayed_ue_security_capabilities->uia);
if (replayed_ue_security_capabilities->gea)
replayed_ue_security_capabilities->length =
sizeof(replayed_ue_security_capabilities->eea) +
sizeof(replayed_ue_security_capabilities->eia) +
sizeof(replayed_ue_security_capabilities->uea) +
sizeof(replayed_ue_security_capabilities->uia) +
sizeof(replayed_ue_security_capabilities->gea);
d_trace(5, " SEC[LEN:%d EEA:0x%x EIA:0x%x UEA:0x%x UIA:0x%x GEA:0x%x]\n",
replayed_ue_security_capabilities->length,
replayed_ue_security_capabilities->eea,
replayed_ue_security_capabilities->eia,
replayed_ue_security_capabilities->uea,
replayed_ue_security_capabilities->uia,
replayed_ue_security_capabilities->gea);
mme_kdf_nas(MME_KDF_NAS_INT_ALG, mme_ue->selected_int_algorithm,
mme_ue->kasme, mme_ue->knas_int);
mme_kdf_nas(MME_KDF_NAS_ENC_ALG, mme_ue->selected_enc_algorithm,

View File

@@ -112,9 +112,14 @@ status_t emm_handle_attach_request(
memcpy(&mme_ue->ue_network_capability,
&attach_request->ue_network_capability,
sizeof(attach_request->ue_network_capability));
memcpy(&mme_ue->ms_network_capability,
&attach_request->ms_network_capability,
sizeof(attach_request->ms_network_capability));
if (attach_request->presencemask &
NAS_ATTACH_REQUEST_MS_NETWORK_CAPABILITY_PRESENT)
{
memcpy(&mme_ue->ms_network_capability,
&attach_request->ms_network_capability,
sizeof(attach_request->ms_network_capability));
}
switch(eps_mobile_identity->imsi.type)
{
@@ -195,7 +200,8 @@ status_t emm_handle_attach_complete(
NAS_EMM_INFORMATION_UNIVERSAL_TIME_AND_LOCAL_TIME_ZONE_PRESENT;
universal_time_and_local_time_zone->year =
NAS_TIME_TO_BCD(time_exp.tm_year % 100);
universal_time_and_local_time_zone->mon = NAS_TIME_TO_BCD(time_exp.tm_mon);
universal_time_and_local_time_zone->mon =
NAS_TIME_TO_BCD(time_exp.tm_mon+1);
universal_time_and_local_time_zone->mday =
NAS_TIME_TO_BCD(time_exp.tm_mday);
universal_time_and_local_time_zone->hour =
@@ -214,6 +220,22 @@ status_t emm_handle_attach_complete(
NAS_EMM_INFORMATION_NETWORK_DAYLIGHT_SAVING_TIME_PRESENT;
network_daylight_saving_time->length = 1;
if(mme_self()->full_name.length)
{
emm_information->presencemask |=
NAS_EMM_INFORMATION_FULL_NAME_FOR_NETWORK_PRESENT;
memcpy(&emm_information->full_name_for_network,
&mme_self()->full_name, sizeof(nas_network_name_t));
}
if(mme_self()->short_name.length)
{
emm_information->presencemask |=
NAS_EMM_INFORMATION_SHORT_NAME_FOR_NETWORK_PRESENT;
memcpy(&emm_information->short_name_for_network,
&mme_self()->short_name, sizeof(nas_network_name_t));
}
rv = nas_security_encode(&emmbuf, mme_ue, &message);
d_assert(rv == CORE_OK && emmbuf, return CORE_ERROR, "emm build error");
d_assert(nas_send_to_downlink_nas_transport(mme_ue, emmbuf) == CORE_OK,,);

View File

@@ -1211,6 +1211,57 @@ status_t mme_context_parse_config()
}
}
}
else if(!strcmp(mme_key, "network_name"))
{
yaml_iter_t network_name_iter;
yaml_iter_recurse(&mme_iter, &network_name_iter);
while(yaml_iter_next(&network_name_iter))
{
const char *network_name_key =
yaml_iter_key(&network_name_iter);
d_assert(network_name_key,
return CORE_ERROR,);
if (!strcmp(network_name_key, "full"))
{
nas_network_name_t *network_full_name =
&self.full_name;
const char *c_network_name =
yaml_iter_value(&network_name_iter);
c_uint8_t size = strlen(c_network_name);
c_uint8_t i;
for(i = 0;i<size;i++)
{
/* Workaround to convert the ASCII to USC-2 */
network_full_name->name[i*2] = 0;
network_full_name->name[(i*2)+1] =
c_network_name[i];
}
network_full_name->length = size*2+1;
network_full_name->coding_scheme = 1;
}
else if (!strcmp(network_name_key, "short"))
{
nas_network_name_t *network_short_name =
&self.short_name;
const char *c_network_name =
yaml_iter_value(&network_name_iter);
c_uint8_t size = strlen(c_network_name);
c_uint8_t i;
for(i = 0;i<size;i++)
{
/* Workaround to convert the ASCII to USC-2 */
network_short_name->name[i*2] = 0;
network_short_name->name[(i*2)+1] =
c_network_name[i];
}
network_short_name->length = size*2+1;
network_short_name->coding_scheme = 1;
}
}
}
else
d_warn("unknown key `%s`", mme_key);
}
@@ -2180,6 +2231,54 @@ status_t mme_ue_set_imsi(mme_ue_t *mme_ue, c_int8_t *imsi_bcd)
return CORE_OK;
}
int mme_ue_have_indirect_tunnel(mme_ue_t *mme_ue)
{
mme_sess_t *sess = NULL;
sess = mme_sess_first(mme_ue);
while(sess)
{
mme_bearer_t *bearer = mme_bearer_first(sess);
while(bearer)
{
if (MME_HAVE_ENB_DL_INDIRECT_TUNNEL(bearer) ||
MME_HAVE_ENB_UL_INDIRECT_TUNNEL(bearer) ||
MME_HAVE_SGW_DL_INDIRECT_TUNNEL(bearer) ||
MME_HAVE_SGW_UL_INDIRECT_TUNNEL(bearer))
{
return 1;
}
bearer = mme_bearer_next(bearer);
}
sess = mme_sess_next(sess);
}
return 0;
}
status_t mme_ue_clear_indirect_tunnel(mme_ue_t *mme_ue)
{
mme_sess_t *sess = NULL;
d_assert(mme_ue, return CORE_ERROR,);
sess = mme_sess_first(mme_ue);
while(sess)
{
mme_bearer_t *bearer = mme_bearer_first(sess);
while(bearer)
{
CLEAR_INDIRECT_TUNNEL(bearer);
bearer = mme_bearer_next(bearer);
}
sess = mme_sess_next(sess);
}
return CORE_OK;
}
status_t mme_ue_associate_enb_ue(mme_ue_t *mme_ue, enb_ue_t *enb_ue)
{
d_assert(mme_ue, return CORE_ERROR, "Null param");

View File

@@ -132,6 +132,11 @@ typedef struct _mme_context_t {
/* System */
msgq_id queue_id; /* Queue for processing MME control plane */
tm_service_t tm_service; /* Timer Service */
/* Network Name */
nas_network_name_t short_name; /* Network short name */
nas_network_name_t full_name; /* Network Full Name */
} mme_context_t;
typedef struct _mme_enb_t {
@@ -543,6 +548,9 @@ CORE_DECLARE(mme_ue_t*) mme_ue_find_by_message(nas_message_t *message);
CORE_DECLARE(status_t) mme_ue_set_imsi(
mme_ue_t *mme_ue, c_int8_t *imsi_bcd);
CORE_DECLARE(int) mme_ue_have_indirect_tunnel(mme_ue_t *mme_ue);
CORE_DECLARE(status_t) mme_ue_clear_indirect_tunnel(mme_ue_t *mme_ue);
/*
* o RECV Initial UE-Message : S-TMSI
* o RECV Attach Request : IMSI, GUTI

View File

@@ -643,9 +643,6 @@ void mme_s11_handle_delete_indirect_data_forwarding_tunnel_response(
{
status_t rv;
mme_sess_t *sess = NULL;
mme_bearer_t *bearer = NULL;
d_assert(xact, return, "Null param");
d_assert(mme_ue, return, "Null param");
d_assert(rsp, return, "Null param");
@@ -660,18 +657,8 @@ void mme_s11_handle_delete_indirect_data_forwarding_tunnel_response(
mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid);
rv = gtp_xact_commit(xact);
d_assert(rv == CORE_OK, return, "xact_commit error");
d_assert(rv == CORE_OK,, "xact_commit error");
sess = mme_sess_first(mme_ue);
while(sess)
{
bearer = mme_bearer_first(sess);
while(bearer)
{
CLEAR_INDIRECT_TUNNEL(bearer);
bearer = mme_bearer_next(bearer);
}
sess = mme_sess_next(sess);
}
rv = mme_ue_clear_indirect_tunnel(mme_ue);
d_assert(rv == CORE_OK,, "mme_ue_clear_indirect_tunnel() failed");
}

View File

@@ -717,7 +717,7 @@ void s1ap_handle_ue_context_release_complete(
d_assert(rv == CORE_OK,, "enb_ue_removeI() failed");
d_assert(mme_ue,,);
if (SESSION_CONTEXT_IS_AVAILABLE(mme_ue))
if (mme_ue_have_indirect_tunnel(mme_ue))
{
rv = mme_gtp_send_delete_indirect_data_forwarding_tunnel_request(mme_ue);
d_assert(rv == CORE_OK,, "mme_gtp_send_delete_indirect_data_"
@@ -725,22 +725,12 @@ void s1ap_handle_ue_context_release_complete(
}
else
{
mme_sess_t *sess = NULL;
mme_bearer_t *bearer = NULL;
d_warn("GTP-C(S11) has already been deleted");
sess = mme_sess_first(mme_ue);
while(sess)
{
bearer = mme_bearer_first(sess);
while(bearer)
{
CLEAR_INDIRECT_TUNNEL(bearer);
bearer = mme_bearer_next(bearer);
}
sess = mme_sess_next(sess);
}
d_warn("Check your eNodeB");
d_warn(" There is no INDIRECT TUNNEL");
d_warn(" Packet could be dropped during S1-Handover");
rv = mme_ue_clear_indirect_tunnel(mme_ue);
d_assert(rv == CORE_OK,,
"mme_ue_clear_indirect_tunnel() failed");
}
break;
}
@@ -1085,7 +1075,7 @@ void s1ap_handle_handover_request_ack(mme_enb_t *enb, s1ap_message_t *message)
S1AP_STORE_DATA(
&mme_ue->container, &ies->target_ToSource_TransparentContainer);
if (i > 0)
if (mme_ue_have_indirect_tunnel(mme_ue) == 1)
{
rv = mme_gtp_send_create_indirect_data_forwarding_tunnel_request(
mme_ue);
@@ -1230,6 +1220,68 @@ void s1ap_handle_enb_status_transfer(mme_enb_t *enb, s1ap_message_t *message)
d_assert(rv == CORE_OK,,);
}
void s1ap_handle_enb_configuration_transfer(
mme_enb_t *enb, s1ap_message_t *message, pkbuf_t *pkbuf)
{
status_t rv;
char buf[CORE_ADDRSTRLEN];
S1ap_ENBConfigurationTransferIEs_t *ies = NULL;
d_assert(enb, return,);
ies = &message->s1ap_ENBConfigurationTransferIEs;
d_assert(ies, return,);
d_trace(3, "[MME] ENB configuration transfer\n");
d_trace(5, " IP[%s] ENB_ID[%d]\n",
CORE_ADDR(enb->addr, buf), enb->enb_id);
if (ies->presenceMask &
S1AP_ENBCONFIGURATIONTRANSFERIES_SONCONFIGURATIONTRANSFERECT_PRESENT)
{
S1ap_SONConfigurationTransfer_t *transfer =
&ies->sonConfigurationTransferECT;
mme_enb_t *target_enb = NULL;
c_uint32_t source_enb_id, target_enb_id;
c_uint16_t source_tac, target_tac;
s1ap_ENB_ID_to_uint32(
&transfer->sourceeNB_ID.global_S1ap_ENB_ID.eNB_ID,
&source_enb_id);
s1ap_ENB_ID_to_uint32(
&transfer->targeteNB_ID.global_S1ap_ENB_ID.eNB_ID,
&target_enb_id);
memcpy(&source_tac, transfer->sourceeNB_ID.selected_S1ap_TAI.tAC.buf,
sizeof(source_tac));
source_tac = ntohs(source_tac);
memcpy(&target_tac, transfer->targeteNB_ID.selected_S1ap_TAI.tAC.buf,
sizeof(target_tac));
target_tac = ntohs(target_tac);
d_trace(5, " Source : ENB_ID[%s:%d], TAC[%d]\n",
transfer->sourceeNB_ID.global_S1ap_ENB_ID.eNB_ID.present ==
S1ap_ENB_ID_PR_homeENB_ID ? "Home" :
transfer->sourceeNB_ID.global_S1ap_ENB_ID.eNB_ID.present ==
S1ap_ENB_ID_PR_macroENB_ID ? "Macro" : "Others",
source_enb_id, source_tac);
d_trace(5, " Target : ENB_ID[%s:%d], TAC[%d]\n",
transfer->targeteNB_ID.global_S1ap_ENB_ID.eNB_ID.present ==
S1ap_ENB_ID_PR_homeENB_ID ? "Home" :
transfer->targeteNB_ID.global_S1ap_ENB_ID.eNB_ID.present ==
S1ap_ENB_ID_PR_macroENB_ID ? "Macro" : "Others",
target_enb_id, target_tac);
target_enb = mme_enb_find_by_enb_id(target_enb_id);
d_assert(target_enb, return,
"Cannot find target eNB = %d", target_enb_id);
rv = s1ap_send_mme_configuration_transfer(target_enb, pkbuf);
d_assert(rv == CORE_OK,,);
}
}
void s1ap_handle_handover_notification(mme_enb_t *enb, s1ap_message_t *message)
{
status_t rv;

View File

@@ -45,6 +45,8 @@ CORE_DECLARE(void) s1ap_handle_handover_cancel(
CORE_DECLARE(void) s1ap_handle_enb_status_transfer(
mme_enb_t *enb, s1ap_message_t *message);
CORE_DECLARE(void) s1ap_handle_enb_configuration_transfer(
mme_enb_t *enb, s1ap_message_t *message, pkbuf_t *pkbuf);
CORE_DECLARE(void) s1ap_handle_handover_notification(
mme_enb_t *enb, s1ap_message_t *message);

View File

@@ -459,6 +459,28 @@ status_t s1ap_send_mme_status_transfer(
return rv;
}
status_t s1ap_send_mme_configuration_transfer(
mme_enb_t *target_enb, pkbuf_t *recvbuf)
{
status_t rv;
char *payload;
pkbuf_t *sendbuf = NULL;
d_assert(target_enb, return CORE_ERROR,);
d_assert(recvbuf, return CORE_ERROR,);
sendbuf = pkbuf_copy(recvbuf);
d_assert(sendbuf, return CORE_ERROR,);
payload = sendbuf->payload;
payload[1] = S1AP_ProcedureCode_id_MMEConfigurationTransfer;
payload[8] = S1AP_ProtocolIE_ID_id_SONConfigurationTransferMCT;
rv = s1ap_send_to_enb(target_enb, sendbuf);
d_assert(rv == CORE_OK,, "s1ap send error");
return CORE_OK;
}
status_t s1ap_send_error_indication(
mme_enb_t *enb, c_uint16_t presenceMask,
c_uint32_t enb_ue_s1ap_id, c_uint32_t mme_ue_s1ap_id,

View File

@@ -29,6 +29,8 @@ mme:
security:
integrity_order : [ EIA1, EIA2, EIA0 ]
ciphering_order : [ EEA0, EEA1, EEA2 ]
network_name:
full: NextEPC
sgw:
gtpc:

View File

@@ -143,6 +143,16 @@ mme:
integrity_order : [ EIA1, EIA2, EIA0 ]
ciphering_order : [ EEA0, EEA1, EEA2 ]
#
# <Network Name>
# network_name:
# full: NextEPC
# short: Next
#
network_name:
full: NextEPC
hss:
freeDiameter: hss.conf

View File

@@ -48,8 +48,8 @@ static void attach_test1(abts_case *tc, void *data)
"0002010000000153 12172c5949640125 006b000518000c00 00004900203311c6"
"03c6a6d67f695e5a c02bb75b381b693c 3893a6d932fd9182 3544e3e79b";
char *_emm_information =
"000b402a00000300 000005c00100009d 000800020001001a 001413279fcc7266"
"0307614771304112 527563490100";
"000b403b00000300 000005c00100009d 000800020001001a 002524271f9b491e"
"030761430f10004e 0065007800740045 0050004347812072 11240563490100";
mongoc_collection_t *collection = NULL;
bson_t *doc = NULL;
@@ -244,7 +244,7 @@ static void attach_test1(abts_case *tc, void *data)
ABTS_INT_EQUAL(tc, CORE_OK, rv);
CORE_HEX(_emm_information, strlen(_emm_information), tmp);
ABTS_TRUE(tc, memcmp(recvbuf->payload, tmp, 28) == 0);
ABTS_TRUE(tc, memcmp(recvbuf->payload+43, tmp+43, 3) == 0);
ABTS_TRUE(tc, memcmp(recvbuf->payload+32, tmp+32, 20) == 0);
pkbuf_free(recvbuf);
core_sleep(time_from_msec(300));
@@ -863,9 +863,8 @@ static void attach_test3(abts_case *tc, void *data)
"403b000003000000 05c0020000c80008 00020002001a0025 2407520042200639"
"1c0021554d444928 4a1a062e10e543cb 257f1f800021f4f9 2d522a5b87";
char *_security_mode_command =
"000b"
"4027000003000000 05c0020000c80008 00020002001a0011 103744bcbbd20007"
"5d010005f0f00000 00";
"000b402400000300 000005c0020000c8 000800020002001a 000e0d37a3761a13"
"00075d010002f0f0";
char *_esm_information_request =
"000b"
@@ -882,9 +881,8 @@ static void attach_test3(abts_case *tc, void *data)
"05ff9c6791b8503a 032c6effa7";
char *_emm_information =
"000b"
"402a000003000000 05c0020000c80008 00020002001a0014 1327dc833e850307"
"6147717042911120 8a490100";
"000b403b00000300 000005c0020000c8 000800020002001a 002524276782702a"
"030761430f10004e 0065007800740045 0050004347812072 11941563490100";
char *_ue_context_release_command =
"0017"
@@ -1070,7 +1068,7 @@ static void attach_test3(abts_case *tc, void *data)
ABTS_INT_EQUAL(tc, CORE_OK, rv);
CORE_HEX(_emm_information, strlen(_emm_information), tmp);
ABTS_TRUE(tc, memcmp(recvbuf->payload, tmp, 28) == 0);
ABTS_TRUE(tc, memcmp(recvbuf->payload+43, tmp+43, 3) == 0);
ABTS_TRUE(tc, memcmp(recvbuf->payload+32, tmp+32, 20) == 0);
pkbuf_free(recvbuf);
/* Retreive M-TMSI */

View File

@@ -613,6 +613,18 @@ static void handover_test2(abts_case *tc, void *data)
core_sleep(time_from_msec(300));
/* Send ENB configuration transfer */
rv = tests1ap_build_enb_configuration_transfer(&sendbuf, 0);
ABTS_INT_EQUAL(tc, CORE_OK, rv);
rv = tests1ap_enb_send(sock1, sendbuf);
ABTS_INT_EQUAL(tc, CORE_OK, rv);
/* Receive Handover Request */
recvbuf = pkbuf_alloc(0, MAX_SDU_LEN);
rv = tests1ap_enb_read(sock2, recvbuf);
ABTS_INT_EQUAL(tc, CORE_OK, rv);
pkbuf_free(recvbuf);
/* Send Handover Required */
rv = tests1ap_build_handover_required(&sendbuf, 0);
ABTS_INT_EQUAL(tc, CORE_OK, rv);

View File

@@ -1948,6 +1948,50 @@ status_t tests1ap_build_enb_status_transfer(
return CORE_OK;
}
status_t tests1ap_build_enb_configuration_transfer(
pkbuf_t **pkbuf, int i)
{
char *payload[TESTS1AP_MAX_MESSAGE] = {
"0028"
"403c000001008140 354000f110000004 3000f1105ba00000 f11040830bb87000"
"f1105ba000000000 98401341f0c0a864 6800000099400702 00f8c0a86468",
"",
"",
"",
"",
"",
"",
"",
"",
};
c_uint16_t len[TESTS1AP_MAX_MESSAGE] = {
64,
0,
0,
0,
0,
0,
0,
0,
0,
};
char hexbuf[MAX_SDU_LEN];
*pkbuf = pkbuf_alloc(0, MAX_SDU_LEN);
if (!(*pkbuf)) return CORE_ERROR;
(*pkbuf)->len = len[i];
memcpy((*pkbuf)->payload, CORE_HEX(payload[i], strlen(payload[i]), hexbuf),
(*pkbuf)->len);
return CORE_OK;
}
status_t tests1ap_build_handover_notify(pkbuf_t **pkbuf, int i)
{
char *payload[TESTS1AP_MAX_MESSAGE] = {

View File

@@ -82,6 +82,8 @@ CORE_DECLARE(status_t) tests1ap_build_handover_request_ack_static(
pkbuf_t **pkbuf, int i);
CORE_DECLARE(status_t) tests1ap_build_enb_status_transfer(
pkbuf_t **pkbuf, int i);
CORE_DECLARE(status_t) tests1ap_build_enb_configuration_transfer(
pkbuf_t **pkbuf, int i);
CORE_DECLARE(status_t) tests1ap_build_handover_notify(pkbuf_t **pkbuf, int i);
CORE_DECLARE(status_t) tests1ap_build_handover_cancel(pkbuf_t **pkbuf, int i);

View File

@@ -1,6 +1,6 @@
{
"name": "nextepc",
"version": "0.3.4",
"version": "0.3.5",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View File

@@ -1,6 +1,6 @@
{
"name": "nextepc",
"version": "0.3.4",
"version": "0.3.5",
"description": "NextEPC",
"main": "index.js",
"repository": "https://github.com/acetcom/nextepc",