Add default APN for each EUA Type

MS may request an unknown APN. In this case we will use
the APN configured in the vty as default-apn but if
the type support does not match the request we will fail.

The commit adds two more vty commands to configure a default
vpn for v6 and for v4v6

Change-Id: I03fcf8a1532bd9988ea99a6afd3dc325174ce9d6
Fixes: OS#4511
This commit is contained in:
Keith Whyte 2020-04-25 05:39:21 +02:00
parent 04715d284f
commit a6a8cc1442
3 changed files with 77 additions and 29 deletions

View File

@ -446,16 +446,44 @@ int create_context_ind(struct pdp_t *pdp)
LOGPPDP(LOGL_DEBUG, pdp, "Processing create PDP context request for APN '%s'\n",
apn_name ? name_buf : "(NONE)");
/* FIXME: we manually force all context requests to dynamic here! */
if (pdp->eua.l > 2)
pdp->eua.l = 2;
memset(addr, 0, sizeof(addr));
if ((num_addr = in46a_from_eua(&pdp->eua, addr)) < 0) {
LOGPPDP(LOGL_ERROR, pdp, "Cannot decode EUA from MS/SGSN: %s\n",
osmo_hexdump(pdp->eua.v, pdp->eua.l));
gtp_create_context_resp(gsn, pdp, GTPCAUSE_UNKNOWN_PDP);
return 0;
}
/* First find an exact APN name match */
if (apn_name != NULL)
apn = ggsn_find_apn(ggsn, name_buf);
/* ignore if the APN has not been started */
if (apn && !apn->started)
apn = NULL;
/* then try default (if any) */
if (!apn)
apn = ggsn->cfg.default_apn;
if (!apn) {
switch (num_addr) {
case 2:
apn = ggsn->cfg.default_apn_v4v6;
break;
case 1:
if (in46a_is_v4(&addr[0])) {
apn = ggsn->cfg.default_apn_v4;
} else {
apn = ggsn->cfg.default_apn_v6;
}
break;
default:
/* in46a_from_eua() returned other than 1 or 2 ? */
OSMO_ASSERT(0);
break;
}
}
/* ignore if the APN has not been started */
if (apn && !apn->started)
apn = NULL;
@ -467,23 +495,11 @@ int create_context_ind(struct pdp_t *pdp)
return 0;
}
/* FIXME: we manually force all context requests to dynamic here! */
if (pdp->eua.l > 2)
pdp->eua.l = 2;
memcpy(pdp->qos_neg0, pdp->qos_req0, sizeof(pdp->qos_req0));
memcpy(pdp->qos_neg.v, pdp->qos_req.v, pdp->qos_req.l); /* TODO */
pdp->qos_neg.l = pdp->qos_req.l;
memset(addr, 0, sizeof(addr));
if ((num_addr = in46a_from_eua(&pdp->eua, addr)) < 0) {
LOGPPDP(LOGL_ERROR, pdp, "Cannot decode EUA from MS/SGSN: %s\n",
osmo_hexdump(pdp->eua.v, pdp->eua.l));
gtp_create_context_resp(gsn, pdp, GTPCAUSE_UNKNOWN_PDP);
return 0;
}
/* Store the actual APN for logging and the VTY */
rc = osmo_apn_from_str(pdp->apn_use.v, sizeof(pdp->apn_use.v), apn->cfg.name);
if (rc < 0) /* Unlikely this would happen, but anyway... */

View File

@ -115,8 +115,10 @@ struct ggsn_ctx {
char *name;
/* Description string */
char *description;
/* an APN that shall be used as default for any non-matching APN */
struct apn_ctx *default_apn;
/* APNs that shall be used as default for any non-matching APN */
struct apn_ctx *default_apn_v4;
struct apn_ctx *default_apn_v6;
struct apn_ctx *default_apn_v4v6;
/* ADdress to which we listen for GTP */
struct in46_addr listen_addr;
/* Local GTP-C address advertised in GTP */

View File

@ -269,30 +269,55 @@ DEFUN(cfg_ggsn_no_apn, cfg_ggsn_no_apn_cmd,
return CMD_SUCCESS;
}
DEFUN(cfg_ggsn_default_apn, cfg_ggsn_default_apn_cmd,
"default-apn NAME",
DEFUN(cfg_ggsn_default_apn_v4, cfg_ggsn_default_apn_v4_cmd,
"default-apn (v4|v6|v4v6) NAME",
"Set a default-APN to be used if no other APN matches\n"
"Set a default-APN to be used if no other APN v4 matches\n"
"Set a default-APN to be used if no other APN v6 matches\n"
"Set a default-APN to be used if no other APN v4v6 matches\n"
"APN Name\n")
{
struct ggsn_ctx *ggsn = (struct ggsn_ctx *) vty->index;
struct apn_ctx *apn;
apn = ggsn_find_apn(ggsn, argv[0]);
/* backwards compatibility with 'default-apn NAME'. */
const char *apn_name = (argc > 1) ? argv[1] : argv[0];
const char *apn_type = (argc > 1) ? argv[0] : "v4";
apn = ggsn_find_apn(ggsn, apn_name);
if (!apn) {
vty_out(vty, "%% No APN of name '%s' found%s", argv[0], VTY_NEWLINE);
vty_out(vty, "%% No APN of name '%s' found%s", apn_name, VTY_NEWLINE);
return CMD_WARNING;
}
ggsn->cfg.default_apn = apn;
if (!strcmp(apn_type, "v4"))
ggsn->cfg.default_apn_v4 = apn;
if (!strcmp(apn_type, "v6"))
ggsn->cfg.default_apn_v6 = apn;
if (!strcmp(apn_type, "v4v6"))
ggsn->cfg.default_apn_v4v6 = apn;
return CMD_SUCCESS;
}
DEFUN(cfg_ggsn_no_default_apn, cfg_ggsn_no_default_apn_cmd,
"no default-apn",
NO_STR "Remove default-APN to be used if no other APN matches\n")
ALIAS_DEPRECATED(cfg_ggsn_default_apn_v4, cfg_ggsn_default_apn_cmd,
"default-apn NAME",
"Set a default-APN to be used if no other APN matches\n"
"APN Name\n")
DEFUN(cfg_ggsn_no_default_apn_v4, cfg_ggsn_no_default_apn_v4_cmd,
"no default-apn (v4|v6|v4v6)",
NO_STR "Remove default-APN to be used if no other APN v4 matches\n"
"Remove default-APN to be used if no other APN v4 matches\n"
"Remove default-APN to be used if no other APN v6 matches\n"
"Remove default-APN to be used if no other APN v4v6 matches\n")
{
struct ggsn_ctx *ggsn = (struct ggsn_ctx *) vty->index;
ggsn->cfg.default_apn = NULL;
if (!strcmp(argv[0], "v4"))
ggsn->cfg.default_apn_v4 = NULL;
if (!strcmp(argv[0], "v6"))
ggsn->cfg.default_apn_v6 = NULL;
if (!strcmp(argv[0], "v4v6"))
ggsn->cfg.default_apn_v4v6 = NULL;
return CMD_SUCCESS;
}
@ -790,8 +815,12 @@ static int config_write_ggsn(struct vty *vty)
vty_out(vty, " gtp user-ip %s%s", in46a_ntoa(&ggsn->cfg.gtpu_addr), VTY_NEWLINE);
llist_for_each_entry(apn, &ggsn->apn_list, list)
config_write_apn(vty, apn);
if (ggsn->cfg.default_apn)
vty_out(vty, " default-apn %s%s", ggsn->cfg.default_apn->cfg.name, VTY_NEWLINE);
if (ggsn->cfg.default_apn_v4)
vty_out(vty, " default-apn v4 %s%s", ggsn->cfg.default_apn_v4->cfg.name, VTY_NEWLINE);
if (ggsn->cfg.default_apn_v6)
vty_out(vty, " default-apn v6 %s%s", ggsn->cfg.default_apn_v6->cfg.name, VTY_NEWLINE);
if (ggsn->cfg.default_apn_v4v6)
vty_out(vty, " default-apn v4v6 %s%s", ggsn->cfg.default_apn_v4v6->cfg.name, VTY_NEWLINE);
if (ggsn->cfg.echo_interval)
vty_out(vty, " echo-interval %u%s", ggsn->cfg.echo_interval, VTY_NEWLINE);
/* must be last */
@ -1096,7 +1125,8 @@ int ggsn_vty_init(void)
install_element(GGSN_NODE, &cfg_ggsn_apn_cmd);
install_element(GGSN_NODE, &cfg_ggsn_no_apn_cmd);
install_element(GGSN_NODE, &cfg_ggsn_default_apn_cmd);
install_element(GGSN_NODE, &cfg_ggsn_no_default_apn_cmd);
install_element(GGSN_NODE, &cfg_ggsn_default_apn_v4_cmd);
install_element(GGSN_NODE, &cfg_ggsn_no_default_apn_v4_cmd);
install_element(GGSN_NODE, &cfg_ggsn_show_sgsn_cmd);
install_element(GGSN_NODE, &cfg_ggsn_echo_interval_cmd);
install_element(GGSN_NODE, &cfg_ggsn_no_echo_interval_cmd);