forked from acouzens/open5gs
Adding support for static IP assignment in HSS (#306)
This commit is contained in:
parent
cdbbbc500b
commit
b994a8efbf
|
@ -261,7 +261,7 @@ int ogs_dict_s6a_entry(char *conffile)
|
|||
struct local_rules_definition rules[] =
|
||||
{
|
||||
{ { .avp_vendor = 10415, .avp_name = "Context-Identifier" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Served-Party-IP-Address" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Served-Party-IP-Address" }, RULE_OPTIONAL, -1, 2 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "PDN-Type" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Service-Selection" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "EPS-Subscribed-QoS-Profile" }, RULE_OPTIONAL, -1, 1 },
|
||||
|
|
|
@ -60,6 +60,7 @@ struct dict_object *ogs_diam_s6a_apn_configuration = NULL;
|
|||
struct dict_object *ogs_diam_s6a_max_bandwidth_ul = NULL;
|
||||
struct dict_object *ogs_diam_s6a_max_bandwidth_dl = NULL;
|
||||
struct dict_object *ogs_diam_s6a_pdn_type = NULL;
|
||||
struct dict_object *ogs_diam_s6a_served_party_ip_address = NULL;
|
||||
struct dict_object *ogs_diam_s6a_eps_subscribed_qos_profile = NULL;
|
||||
struct dict_object *ogs_diam_s6a_qos_class_identifier = NULL;
|
||||
struct dict_object *ogs_diam_s6a_allocation_retention_priority = NULL;
|
||||
|
@ -119,6 +120,7 @@ int ogs_diam_s6a_init(void)
|
|||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "APN-Configuration", &ogs_diam_s6a_apn_configuration);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Service-Selection", &ogs_diam_s6a_service_selection);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "PDN-Type", &ogs_diam_s6a_pdn_type);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Served-Party-IP-Address", &ogs_diam_s6a_served_party_ip_address);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Subscription-Data", &ogs_diam_s6a_subscription_data);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Subscriber-Status", &ogs_diam_s6a_subscriber_status);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Network-Access-Mode", &ogs_diam_s6a_network_access_mode);
|
||||
|
|
|
@ -36,6 +36,7 @@ extern "C" {
|
|||
#define OGS_DIAM_S6A_AVP_CODE_ALL_APN_CONFIG_INC_IND (1428)
|
||||
#define OGS_DIAM_S6A_AVP_CODE_APN_CONFIGURATION (1430)
|
||||
#define OGS_DIAM_S6A_AVP_CODE_MIP_HOME_AGENT_ADDRESS (334)
|
||||
#define OGS_DIAM_S6A_AVP_CODE_SERVED_PARTY_IP_ADDRESS (848)
|
||||
|
||||
#define OGS_DIAM_S6A_RAT_TYPE_WLAN 0
|
||||
#define OGS_DIAM_S6A_RAT_TYPE_VIRTUAL 1
|
||||
|
@ -99,6 +100,7 @@ extern struct dict_object *ogs_diam_s6a_apn_configuration;
|
|||
extern struct dict_object *ogs_diam_s6a_max_bandwidth_ul;
|
||||
extern struct dict_object *ogs_diam_s6a_max_bandwidth_dl;
|
||||
extern struct dict_object *ogs_diam_s6a_pdn_type;
|
||||
extern struct dict_object *ogs_diam_s6a_served_party_ip_address;
|
||||
extern struct dict_object *ogs_diam_s6a_eps_subscribed_qos_profile;
|
||||
extern struct dict_object *ogs_diam_s6a_qos_class_identifier;
|
||||
extern struct dict_object *ogs_diam_s6a_allocation_retention_priority;
|
||||
|
|
|
@ -8,6 +8,9 @@ display_help() {
|
|||
echo " add {imsi key opc}: adds a user to the database with default values"
|
||||
echo " remove {imsi}: removes a user from the database"
|
||||
echo " reset: WIPES OUT the database and restores it to an empty default"
|
||||
echo " static_ip {imsi ip4}: adds a static IP assignment to an already-existing user"
|
||||
echo " static_ip6 {imsi ip6}: adds a static IPv6 assignment to an already-existing user"
|
||||
echo " type {imsi type}: changes the PDN-Type of the first PDN: 0 = IPv4, 1 = IPv6, 2 = IPv4v6, 3 = v4 OR v6"
|
||||
echo " help: displays this message and exits"
|
||||
echo " default values are as follows: APN \"internet\", dl_bw/ul_bw 1 Gbps, PGW address is 127.0.0.3, IPv4 only"
|
||||
}
|
||||
|
@ -24,16 +27,27 @@ if [ "$1" = "help" ]; then
|
|||
fi
|
||||
|
||||
if [ "$1" = "add" ]; then
|
||||
if [ "$#" -ne 4 ]; then
|
||||
echo "dbconf.sh: incorrect number of args, format is \"dbconf.sh add imsi key opc\""
|
||||
exit 1
|
||||
fi
|
||||
IMSI=$2
|
||||
KI=$3
|
||||
OPC=$4
|
||||
if [ "$#" -eq 4 ]; then
|
||||
IMSI=$2
|
||||
KI=$3
|
||||
OPC=$4
|
||||
|
||||
mongo --eval "db.subscribers.update({\"imsi\" : \"$IMSI\"}, { \$setOnInsert: { \"imsi\" : \"$IMSI\", \"pdn\" : [ { \"apn\" : \"internet\", \"_id\" : new ObjectId(), \"pcc_rule\" : [ ], \"pgw\" : { \"addr\" : \"127.0.0.3\" }, \"ambr\" : { \"downlink\" : NumberLong(1024000), \"uplink\" : NumberLong(1024000) }, \"qos\" : { \"qci\" : NumberInt(9), \"arp\" : { \"priority_level\" : NumberInt(8), \"pre_emption_vulnerability\" : NumberInt(1), \"pre_emption_capability\" : NumberInt(0) } }, \"type\" : NumberInt(0) } ], \"ambr\" : { \"downlink\" : NumberLong(1024000), \"uplink\" : NumberLong(1024000) }, \"subscribed_rau_tau_timer\" : NumberInt(12), \"network_access_mode\" : NumberInt(2), \"subscriber_status\" : NumberInt(0), \"access_restriction_data\" : NumberInt(32), \"security\" : { \"k\" : \"$KI\", \"amf\" : \"8000\", \"op\" : null, \"opc\" : \"$OPC\" }, \"__v\" : 0 } }, upsert=true);" open5gs
|
||||
exit 0
|
||||
mongo --eval "db.subscribers.update({\"imsi\" : \"$IMSI\"}, { \$setOnInsert: { \"imsi\" : \"$IMSI\", \"pdn\" : [ { \"apn\" : \"internet\", \"_id\" : new ObjectId(), \"pcc_rule\" : [ ], \"pgw\" : { \"addr\" : \"127.0.0.3\" }, \"ambr\" : { \"downlink\" : NumberLong(1024000), \"uplink\" : NumberLong(1024000) }, \"qos\" : { \"qci\" : NumberInt(9), \"arp\" : { \"priority_level\" : NumberInt(8), \"pre_emption_vulnerability\" : NumberInt(1), \"pre_emption_capability\" : NumberInt(0) } }, \"type\" : NumberInt(0) } ], \"ambr\" : { \"downlink\" : NumberLong(1024000), \"uplink\" : NumberLong(1024000) }, \"subscribed_rau_tau_timer\" : NumberInt(12), \"network_access_mode\" : NumberInt(2), \"subscriber_status\" : NumberInt(0), \"access_restriction_data\" : NumberInt(32), \"security\" : { \"k\" : \"$KI\", \"amf\" : \"8000\", \"op\" : null, \"opc\" : \"$OPC\" }, \"__v\" : 0 } }, upsert=true);" open5gs
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$#" -eq 5 ]; then
|
||||
IMSI=$2
|
||||
IP=$3
|
||||
KI=$4
|
||||
OPC=$5
|
||||
|
||||
mongo --eval "db.subscribers.update({\"imsi\" : \"$IMSI\"}, { \$setOnInsert: { \"imsi\" : \"$IMSI\", \"pdn\" : [ { \"apn\" : \"internet\", \"_id\" : new ObjectId(), \"pcc_rule\" : [ ], \"pgw\" : { \"addr\" : \"127.0.0.3\" }, \"ambr\" : { \"downlink\" : NumberLong(1024000), \"uplink\" : NumberLong(1024000) }, \"qos\" : { \"qci\" : NumberInt(9), \"arp\" : { \"priority_level\" : NumberInt(8), \"pre_emption_vulnerability\" : NumberInt(1), \"pre_emption_capability\" : NumberInt(0) } }, \"type\" : NumberInt(0), \"addr\" : \"$IP\" } ], \"ambr\" : { \"downlink\" : NumberLong(1024000), \"uplink\" : NumberLong(1024000) }, \"subscribed_rau_tau_timer\" : NumberInt(12), \"network_access_mode\" : NumberInt(2), \"subscriber_status\" : NumberInt(0), \"access_restriction_data\" : NumberInt(32), \"security\" : { \"k\" : \"$KI\", \"amf\" : \"8000\", \"op\" : null, \"opc\" : \"$OPC\" }, \"__v\" : 0 } }, upsert=true);" open5gs
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "dbconf.sh: incorrect number of args, format is \"dbconf.sh add imsi key opc\""
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$1" = "remove" ]; then
|
||||
|
@ -57,4 +71,40 @@ if [ "$1" = "reset" ]; then
|
|||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$1" = "static_ip" ]; then
|
||||
if [ "$#" -ne 3 ]; then
|
||||
echo "dbconf.sh: incorrect number of args, format is \"dbconf.sh static_ip imsi ip\""
|
||||
exit 1
|
||||
fi
|
||||
IMSI=$2
|
||||
IP=$3
|
||||
|
||||
mongo --eval "db.subscribers.update({\"imsi\": \"$IMSI\"},{\$set: { \"pdn.0.addr\": \"$IP\" }});" open5gs
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$1" = "static_ip6" ]; then
|
||||
if [ "$#" -ne 3 ]; then
|
||||
echo "dbconf.sh: incorrect number of args, format is \"dbconf.sh static_ip6 imsi ip\""
|
||||
exit 1
|
||||
fi
|
||||
IMSI=$2
|
||||
IP=$3
|
||||
|
||||
mongo --eval "db.subscribers.update({\"imsi\": \"$IMSI\"},{\$set: { \"pdn.0.addr6\": \"$IP\" }});" open5gs
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$1" = "type" ]; then
|
||||
if [ "$#" -ne 3 ]; then
|
||||
echo "dbconf.sh: incorrect number of args, format is \"dbconf.sh type imsi type\""
|
||||
exit 1
|
||||
fi
|
||||
IMSI=$2
|
||||
TYPE=$3
|
||||
|
||||
mongo --eval "db.subscribers.update({\"imsi\": \"$IMSI\"},{\$set: { \"pdn.0.type\": NumberInt($TYPE) }});" open5gs
|
||||
exit 0
|
||||
fi
|
||||
|
||||
display_help
|
||||
|
|
|
@ -630,6 +630,30 @@ int hss_db_subscription_data(
|
|||
}
|
||||
}
|
||||
}
|
||||
} else if (!strcmp(child2_key, "addr") && BSON_ITER_HOLDS_UTF8(&child2_iter)) {
|
||||
ogs_ipsubnet_t ipsub;
|
||||
const char *v = bson_iter_utf8(&child2_iter, &length);
|
||||
rv = ogs_ipsubnet(&ipsub, v, NULL);
|
||||
if (rv == OGS_OK) {
|
||||
if (pdn->paa.pdn_type == OGS_HSS_PDN_TYPE_IPV6) {
|
||||
pdn->paa.pdn_type = OGS_HSS_PDN_TYPE_IPV4V6;
|
||||
} else {
|
||||
pdn->paa.pdn_type = OGS_HSS_PDN_TYPE_IPV4;
|
||||
}
|
||||
pdn->paa.both.addr = ipsub.sub[0];
|
||||
}
|
||||
} else if (!strcmp(child2_key, "addr6") && BSON_ITER_HOLDS_UTF8(&child2_iter)) {
|
||||
ogs_ipsubnet_t ipsub;
|
||||
const char *v = bson_iter_utf8(&child2_iter, &length);
|
||||
rv = ogs_ipsubnet(&ipsub, v, NULL);
|
||||
if (rv == OGS_OK) {
|
||||
if (pdn->paa.pdn_type == OGS_HSS_PDN_TYPE_IPV4) {
|
||||
pdn->paa.pdn_type = OGS_HSS_PDN_TYPE_IPV4V6;
|
||||
} else {
|
||||
pdn->paa.pdn_type = OGS_HSS_PDN_TYPE_IPV6;
|
||||
}
|
||||
memcpy(&(pdn->paa.both.addr6), ipsub.sub, OGS_IPV6_LEN);
|
||||
}
|
||||
}
|
||||
}
|
||||
pdn_index++;
|
||||
|
|
|
@ -446,7 +446,7 @@ static int hss_ogs_diam_s6a_ulr_cb( struct msg **msg, struct avp *avp,
|
|||
for (i = 0; i < subscription_data.num_of_pdn; i++) {
|
||||
/* Set the APN Configuration */
|
||||
struct avp *apn_configuration, *context_identifier;
|
||||
struct avp *pdn_type, *service_selection;
|
||||
struct avp *pdn_type, *served_party_ip_address, *service_selection;
|
||||
struct avp *eps_subscribed_qos_profile, *qos_class_identifier;
|
||||
struct avp *allocation_retention_priority, *priority_level;
|
||||
struct avp *pre_emption_capability, *pre_emption_vulnerability;
|
||||
|
@ -481,6 +481,31 @@ static int hss_ogs_diam_s6a_ulr_cb( struct msg **msg, struct avp *avp,
|
|||
MSG_BRW_LAST_CHILD, pdn_type);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set Served-Party-IP-Address */
|
||||
if ((pdn->pdn_type == OGS_HSS_PDN_TYPE_IPV4 || pdn->pdn_type == OGS_HSS_PDN_TYPE_IPV4V6) &&
|
||||
(pdn->paa.pdn_type == OGS_HSS_PDN_TYPE_IPV4 || pdn->paa.pdn_type == OGS_HSS_PDN_TYPE_IPV4V6)) {
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_served_party_ip_address, 0, &served_party_ip_address);
|
||||
ogs_assert(ret == 0);
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_addr.s_addr = pdn->paa.both.addr;
|
||||
ret = fd_msg_avp_value_encode (&sin, served_party_ip_address);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(apn_configuration, MSG_BRW_LAST_CHILD, served_party_ip_address);
|
||||
ogs_assert(ret == 0);
|
||||
}
|
||||
|
||||
if ((pdn->pdn_type == OGS_HSS_PDN_TYPE_IPV6 || pdn->pdn_type == OGS_HSS_PDN_TYPE_IPV4V6) &&
|
||||
(pdn->paa.pdn_type == OGS_HSS_PDN_TYPE_IPV6 || pdn->paa.pdn_type == OGS_HSS_PDN_TYPE_IPV4V6)) {
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_served_party_ip_address, 0, &served_party_ip_address);
|
||||
ogs_assert(ret == 0);
|
||||
sin6.sin6_family = AF_INET6;
|
||||
memcpy(sin6.sin6_addr.s6_addr, pdn->paa.both.addr6, OGS_IPV6_LEN);
|
||||
ret = fd_msg_avp_value_encode (&sin6, served_party_ip_address);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(apn_configuration, MSG_BRW_LAST_CHILD, served_party_ip_address);
|
||||
ogs_assert(ret == 0);
|
||||
}
|
||||
|
||||
/* Set Service-Selection */
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_service_selection, 0,
|
||||
&service_selection);
|
||||
|
|
|
@ -567,6 +567,7 @@ static void mme_s6a_ula_cb(void *data, struct msg **msg)
|
|||
unsigned long dur;
|
||||
int error = 0;
|
||||
int new;
|
||||
ogs_sockaddr_t addr;
|
||||
|
||||
mme_event_t *e = NULL;
|
||||
mme_ue_t *mme_ue = NULL;
|
||||
|
@ -767,11 +768,47 @@ static void mme_s6a_ula_cb(void *data, struct msg **msg)
|
|||
if (avpch3) {
|
||||
ret = fd_msg_avp_hdr(avpch3, &hdr);
|
||||
pdn->pdn_type = hdr->avp_value->i32;
|
||||
pdn->paa.pdn_type = pdn->pdn_type;
|
||||
} else {
|
||||
ogs_error("no_PDN-Type");
|
||||
error++;
|
||||
}
|
||||
|
||||
/* Served-Party-IP-Address parsing for any static IPs */
|
||||
ret = fd_msg_browse(avpch2, MSG_BRW_FIRST_CHILD, &avpch3, NULL);
|
||||
ogs_assert(ret == 0);
|
||||
while (avpch3) {
|
||||
ret = fd_msg_avp_hdr(avpch3, &hdr);
|
||||
ogs_assert(ret == 0);
|
||||
switch(hdr->avp_code) {
|
||||
case OGS_DIAM_S6A_AVP_CODE_SERVED_PARTY_IP_ADDRESS:
|
||||
ret = fd_msg_avp_value_interpret(avpch3, &addr.sa);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
if (addr.ogs_sa_family == AF_INET) {
|
||||
if (pdn->paa.pdn_type == OGS_HSS_PDN_TYPE_IPV4) {
|
||||
pdn->paa.addr = addr.sin.sin_addr.s_addr;
|
||||
} else if (pdn->paa.pdn_type == OGS_HSS_PDN_TYPE_IPV4V6) {
|
||||
pdn->paa.both.addr = addr.sin.sin_addr.s_addr;
|
||||
} else {
|
||||
ogs_error("Warning: Received a static IPv4 address but PDN-Type does not include IPv4. Ignoring...");
|
||||
}
|
||||
} else if (addr.ogs_sa_family == AF_INET6) {
|
||||
if (pdn->paa.pdn_type == OGS_HSS_PDN_TYPE_IPV6) {
|
||||
memcpy(pdn->paa.addr6, addr.sin6.sin6_addr.s6_addr, OGS_IPV6_LEN);
|
||||
} else if (pdn->paa.pdn_type == OGS_HSS_PDN_TYPE_IPV4V6) {
|
||||
memcpy(pdn->paa.both.addr6, addr.sin6.sin6_addr.s6_addr, OGS_IPV6_LEN);
|
||||
} else {
|
||||
ogs_error("Warning: Received a static IPv6 address but PDN-Type does not include IPv6. Ignoring...");
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
fd_msg_browse(avpch3, MSG_BRW_NEXT, &avpch3, NULL);
|
||||
}
|
||||
|
||||
ret = fd_avp_search_avp(avpch2,
|
||||
ogs_diam_s6a_eps_subscribed_qos_profile, &avpch3);
|
||||
ogs_assert(ret == 0);
|
||||
|
|
|
@ -164,6 +164,21 @@ int mme_s11_build_create_session_request(
|
|||
}
|
||||
req->pdn_type.presence = 1;
|
||||
|
||||
/* If we started with both addrs (IPV4V6) but the above code
|
||||
* (pdn_type & sess->request_type) truncates us down to just one,
|
||||
* we need to change position of addresses in struct. */
|
||||
if (req->pdn_type.u8 == OGS_GTP_PDN_TYPE_IPV4 &&
|
||||
pdn->paa.pdn_type == OGS_HSS_PDN_TYPE_IPV4V6) {
|
||||
uint32_t addr = pdn->paa.both.addr;
|
||||
pdn->paa.addr = addr;
|
||||
}
|
||||
if (req->pdn_type.u8 == OGS_GTP_PDN_TYPE_IPV6 &&
|
||||
pdn->paa.pdn_type == OGS_HSS_PDN_TYPE_IPV4V6) {
|
||||
uint8_t addr[16];
|
||||
memcpy(&addr, pdn->paa.both.addr6, OGS_IPV6_LEN);
|
||||
memcpy(pdn->paa.addr6, &addr, OGS_IPV6_LEN);
|
||||
}
|
||||
|
||||
pdn->paa.pdn_type = req->pdn_type.u8;
|
||||
req->pdn_address_allocation.data = &pdn->paa;
|
||||
if (req->pdn_type.u8 == OGS_GTP_PDN_TYPE_IPV4)
|
||||
|
|
|
@ -573,6 +573,7 @@ int pgw_context_parse_config(void)
|
|||
const char *mask_or_numbits = NULL;
|
||||
const char *apn = NULL;
|
||||
const char *dev = self.tun_ifname;
|
||||
bool static_pool = false;
|
||||
|
||||
if (ogs_yaml_iter_type(&ue_pool_array) ==
|
||||
YAML_MAPPING_NODE) {
|
||||
|
@ -607,13 +608,17 @@ int pgw_context_parse_config(void)
|
|||
apn = ogs_yaml_iter_value(&ue_pool_iter);
|
||||
} else if (!strcmp(ue_pool_key, "dev")) {
|
||||
dev = ogs_yaml_iter_value(&ue_pool_iter);
|
||||
} else if (!strcmp(ue_pool_key, "static")) {
|
||||
char *str = (char *)ogs_yaml_iter_value(&ue_pool_iter);
|
||||
if (!strcmp(str, "true")) {
|
||||
static_pool = true;
|
||||
}
|
||||
} else
|
||||
ogs_warn("unknown key `%s`", ue_pool_key);
|
||||
}
|
||||
|
||||
if (ipstr && mask_or_numbits) {
|
||||
subnet = pgw_subnet_add(
|
||||
ipstr, mask_or_numbits, apn, dev);
|
||||
subnet = pgw_subnet_add(ipstr, mask_or_numbits, apn, dev, static_pool);
|
||||
ogs_assert(subnet);
|
||||
} else {
|
||||
ogs_warn("Ignore : addr(%s/%s), apn(%s)",
|
||||
|
@ -724,7 +729,7 @@ static void *sess_hash_keygen(uint8_t *out, int *out_len,
|
|||
|
||||
pgw_sess_t *pgw_sess_add(
|
||||
uint8_t *imsi, int imsi_len, char *apn,
|
||||
uint8_t pdn_type, uint8_t ebi)
|
||||
uint8_t pdn_type, uint8_t ebi, ogs_paa_t *paa)
|
||||
{
|
||||
char buf1[OGS_ADDRSTRLEN];
|
||||
char buf2[OGS_ADDRSTRLEN];
|
||||
|
@ -760,12 +765,14 @@ pgw_sess_t *pgw_sess_add(
|
|||
bearer->ebi = ebi;
|
||||
|
||||
sess->pdn.paa.pdn_type = pdn_type;
|
||||
ogs_assert(pdn_type == paa->pdn_type);
|
||||
|
||||
if (pdn_type == OGS_GTP_PDN_TYPE_IPV4) {
|
||||
sess->ipv4 = pgw_ue_ip_alloc(AF_INET, apn);
|
||||
sess->ipv4 = pgw_ue_ip_alloc(AF_INET, apn, (uint8_t *)&(paa->addr));
|
||||
ogs_assert(sess->ipv4);
|
||||
sess->pdn.paa.addr = sess->ipv4->addr[0];
|
||||
} else if (pdn_type == OGS_GTP_PDN_TYPE_IPV6) {
|
||||
sess->ipv6 = pgw_ue_ip_alloc(AF_INET6, apn);
|
||||
sess->ipv6 = pgw_ue_ip_alloc(AF_INET6, apn, (paa->addr6));
|
||||
ogs_assert(sess->ipv6);
|
||||
|
||||
subnet6 = sess->ipv6->subnet;
|
||||
|
@ -774,9 +781,9 @@ pgw_sess_t *pgw_sess_add(
|
|||
sess->pdn.paa.len = subnet6->prefixlen;
|
||||
memcpy(sess->pdn.paa.addr6, sess->ipv6->addr, OGS_IPV6_LEN);
|
||||
} else if (pdn_type == OGS_GTP_PDN_TYPE_IPV4V6) {
|
||||
sess->ipv4 = pgw_ue_ip_alloc(AF_INET, apn);
|
||||
sess->ipv4 = pgw_ue_ip_alloc(AF_INET, apn, (uint8_t *)&(paa->both.addr));
|
||||
ogs_assert(sess->ipv4);
|
||||
sess->ipv6 = pgw_ue_ip_alloc(AF_INET6, apn);
|
||||
sess->ipv6 = pgw_ue_ip_alloc(AF_INET6, apn, (paa->both.addr6));
|
||||
ogs_assert(sess->ipv6);
|
||||
|
||||
subnet6 = sess->ipv6->subnet;
|
||||
|
@ -887,6 +894,11 @@ pgw_sess_t *pgw_sess_add_by_message(ogs_gtp_message_t *message)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (req->pdn_address_allocation.presence == 0) {
|
||||
ogs_error("No PAA Type");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ogs_fqdn_parse(apn,
|
||||
req->access_point_name.data, req->access_point_name.len);
|
||||
|
||||
|
@ -894,6 +906,8 @@ pgw_sess_t *pgw_sess_add_by_message(ogs_gtp_message_t *message)
|
|||
apn, req->pdn_type.u8,
|
||||
req->bearer_contexts_to_be_created.eps_bearer_id.u8);
|
||||
|
||||
ogs_paa_t *paa = (ogs_paa_t *)req->pdn_address_allocation.data;
|
||||
|
||||
/*
|
||||
* 7.2.1 in 3GPP TS 29.274 Release 15
|
||||
*
|
||||
|
@ -920,7 +934,7 @@ pgw_sess_t *pgw_sess_add_by_message(ogs_gtp_message_t *message)
|
|||
}
|
||||
sess = pgw_sess_add(req->imsi.data, req->imsi.len, apn,
|
||||
req->pdn_type.u8,
|
||||
req->bearer_contexts_to_be_created.eps_bearer_id.u8);
|
||||
req->bearer_contexts_to_be_created.eps_bearer_id.u8, paa);
|
||||
ogs_assert(sess);
|
||||
|
||||
return sess;
|
||||
|
@ -1253,19 +1267,57 @@ static pgw_subnet_t *find_subnet(int family, const char *apn)
|
|||
return subnet;
|
||||
}
|
||||
|
||||
pgw_ue_ip_t *pgw_ue_ip_alloc(int family, const char *apn)
|
||||
pgw_ue_ip_t *pgw_ue_ip_alloc(int family, const char *apn, uint8_t *addr)
|
||||
{
|
||||
pgw_subnet_t *subnet = NULL;
|
||||
pgw_ue_ip_t *ue_ip = NULL;
|
||||
|
||||
ogs_assert(apn);
|
||||
|
||||
subnet = find_subnet(family, apn);
|
||||
ogs_assert(subnet);
|
||||
|
||||
ogs_pool_alloc(&subnet->pool, &ue_ip);
|
||||
ogs_assert(ue_ip);
|
||||
bool static_ip = 0;
|
||||
int address_size = 0;
|
||||
|
||||
if (family == AF_INET) {
|
||||
address_size = 4;
|
||||
} else if (family == AF_INET6) {
|
||||
address_size = 16;
|
||||
} else {
|
||||
ogs_error("unknown address family!");
|
||||
ogs_assert(0);
|
||||
}
|
||||
|
||||
// if address is all zeros, we are allocating dynamically
|
||||
int i = 0;
|
||||
for(i = 0; i < address_size; i++) {
|
||||
if (addr[i] != 0) {
|
||||
static_ip = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// mismatch error cases
|
||||
if (!subnet->static_pool && static_ip) {
|
||||
ogs_warn("HSS assigning static IP but PGW subnet is dynamic (default). Ignoring HSS-assigned IP and proceeding with dynamic allocation...");
|
||||
}
|
||||
|
||||
if (subnet->static_pool && !static_ip) {
|
||||
ogs_error("PGW subnet is static but HSS did not assign the UE an IP. Cannot proceed with assignment.");
|
||||
ogs_assert(ue_ip);
|
||||
return ue_ip;
|
||||
}
|
||||
|
||||
// if assigning a static IP, do so. If not, assign dynamically!
|
||||
if (subnet->static_pool) {
|
||||
ue_ip = calloc(1, sizeof(pgw_ue_ip_t));
|
||||
ue_ip->subnet = subnet;
|
||||
memcpy(ue_ip->addr, addr, address_size);
|
||||
} else {
|
||||
ogs_pool_alloc(&subnet->pool, &ue_ip);
|
||||
}
|
||||
|
||||
ogs_assert(ue_ip);
|
||||
return ue_ip;
|
||||
}
|
||||
|
||||
|
@ -1277,7 +1329,12 @@ int pgw_ue_ip_free(pgw_ue_ip_t *ue_ip)
|
|||
subnet = ue_ip->subnet;
|
||||
|
||||
ogs_assert(subnet);
|
||||
ogs_pool_free(&subnet->pool, ue_ip);
|
||||
|
||||
if (subnet->static_pool) {
|
||||
free(ue_ip);
|
||||
} else {
|
||||
ogs_pool_free(&subnet->pool, ue_ip);
|
||||
}
|
||||
|
||||
return OGS_OK;
|
||||
}
|
||||
|
@ -1350,7 +1407,7 @@ pgw_dev_t *pgw_dev_next(pgw_dev_t *dev)
|
|||
|
||||
pgw_subnet_t *pgw_subnet_add(
|
||||
const char *ipstr, const char *mask_or_numbits,
|
||||
const char *apn, const char *ifname)
|
||||
const char *apn, const char *ifname, bool static_pool)
|
||||
{
|
||||
int rv;
|
||||
pgw_dev_t *dev = NULL;
|
||||
|
@ -1385,6 +1442,8 @@ pgw_subnet_t *pgw_subnet_add(
|
|||
|
||||
ogs_pool_init(&subnet->pool, ogs_config()->pool.sess);
|
||||
|
||||
subnet->static_pool = static_pool;
|
||||
|
||||
ogs_list_add(&self.subnet_list, subnet);
|
||||
|
||||
return subnet;
|
||||
|
|
|
@ -117,6 +117,7 @@ typedef struct pgw_subnet_s {
|
|||
ogs_ipsubnet_t gw; /* Gateway : cafe::1 */
|
||||
char apn[OGS_MAX_APN_LEN]; /* APN : "internet", "volte", .. */
|
||||
|
||||
bool static_pool; /* Does the pool assign addresses dynamically or statically via HSS */
|
||||
int family; /* AF_INET or AF_INET6 */
|
||||
uint8_t prefixlen; /* prefixlen */
|
||||
OGS_POOL(pool, pgw_ue_ip_t);
|
||||
|
@ -228,7 +229,8 @@ pgw_sess_t *pgw_sess_add_by_message(ogs_gtp_message_t *message);
|
|||
|
||||
pgw_sess_t *pgw_sess_add(
|
||||
uint8_t *imsi, int imsi_len, char *apn,
|
||||
uint8_t pdn_type, uint8_t ebi);
|
||||
uint8_t pdn_type, uint8_t ebi, ogs_paa_t *addr);
|
||||
|
||||
int pgw_sess_remove(pgw_sess_t *sess);
|
||||
void pgw_sess_remove_all(void);
|
||||
pgw_sess_t *pgw_sess_find(uint32_t index);
|
||||
|
@ -259,7 +261,7 @@ pgw_pf_t *pgw_pf_first(pgw_bearer_t *bearer);
|
|||
pgw_pf_t *pgw_pf_next(pgw_pf_t *pf);
|
||||
|
||||
int pgw_ue_pool_generate(void);
|
||||
pgw_ue_ip_t *pgw_ue_ip_alloc(int family, const char *apn);
|
||||
pgw_ue_ip_t *pgw_ue_ip_alloc(int family, const char *apn, uint8_t *addr);
|
||||
int pgw_ue_ip_free(pgw_ue_ip_t *ip);
|
||||
|
||||
pgw_dev_t *pgw_dev_add(const char *ifname);
|
||||
|
@ -271,7 +273,7 @@ pgw_dev_t *pgw_dev_next(pgw_dev_t *dev);
|
|||
|
||||
pgw_subnet_t *pgw_subnet_add(
|
||||
const char *ipstr, const char *mask_or_numbits,
|
||||
const char *apn, const char *ifname);
|
||||
const char *apn, const char *ifname, bool static_pool);
|
||||
pgw_subnet_t *pgw_subnet_next(pgw_subnet_t *subnet);
|
||||
int pgw_subnet_remove(pgw_subnet_t *subnet);
|
||||
void pgw_subnet_remove_all(void);
|
||||
|
|
|
@ -185,7 +185,7 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
|
|||
|
||||
if (!subnet) {
|
||||
ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data, pkbuf->len);
|
||||
ogs_trace("[DROP] Cannot find subnet V:%d, IPv4:%p, IPv6:%p",
|
||||
ogs_error("[DROP] Cannot find subnet V:%d, IPv4:%p, IPv6:%p",
|
||||
ip_h->ip_v, sess->ipv4, sess->ipv6);
|
||||
goto cleanup;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue