From a6a8cc1442e266d8d53266c3a24f3cbbb4784768 Mon Sep 17 00:00:00 2001 From: Keith Date: Sat, 25 Apr 2020 05:39:21 +0200 Subject: 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 --- ggsn/ggsn.c | 46 +++++++++++++++++++++++++++++++--------------- ggsn/ggsn.h | 6 ++++-- ggsn/ggsn_vty.c | 54 ++++++++++++++++++++++++++++++++++++++++++------------ 3 files changed, 77 insertions(+), 29 deletions(-) diff --git a/ggsn/ggsn.c b/ggsn/ggsn.c index 159362f..81d8509 100644 --- a/ggsn/ggsn.c +++ b/ggsn/ggsn.c @@ -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... */ diff --git a/ggsn/ggsn.h b/ggsn/ggsn.h index 82984a0..51f4ec1 100644 --- a/ggsn/ggsn.h +++ b/ggsn/ggsn.h @@ -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 */ diff --git a/ggsn/ggsn_vty.c b/ggsn/ggsn_vty.c index cb92a8a..740ac08 100644 --- a/ggsn/ggsn_vty.c +++ b/ggsn/ggsn_vty.c @@ -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); -- cgit v1.2.3