ggsn: Send proper errors in create_context_ind()
When we receive PDP context requests for unknown PDP types or if we run out of dynamic addresses, we need to inform the SGSN that PDP context creation failed. Change-Id: Ibf199c1726130d27c8f80230b30ee51101c93b06
This commit is contained in:
parent
a0d281db1c
commit
d1bf1e11ba
14
ggsn/ggsn.c
14
ggsn/ggsn.c
|
@ -178,6 +178,7 @@ int create_context_ind(struct pdp_t *pdp)
|
|||
{
|
||||
struct in46_addr addr;
|
||||
struct ippoolm_t *member;
|
||||
int rc;
|
||||
|
||||
DEBUGP(DGGSN, "Received create PDP context request\n");
|
||||
|
||||
|
@ -192,11 +193,16 @@ int create_context_ind(struct pdp_t *pdp)
|
|||
pdp->qos_neg.l = pdp->qos_req.l;
|
||||
|
||||
if (in46a_from_eua(&pdp->eua, &addr)) {
|
||||
addr.v4.s_addr = 0; /* Request dynamic */
|
||||
SYS_ERR(DGGSN, LOGL_ERROR, 0, "Cannot decode EUA from MS/SGSN: %s",
|
||||
osmo_hexdump(pdp->eua.v, pdp->eua.l));
|
||||
gtp_create_context_resp(gsn, pdp, GTPCAUSE_UNKNOWN_PDP);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ippool_newip(ippool, &member, &addr, 0)) {
|
||||
gtp_create_context_resp(gsn, pdp, GTPCAUSE_NO_RESOURCES);
|
||||
rc = ippool_newip(ippool, &member, &addr, 0);
|
||||
if (rc < 0) {
|
||||
SYS_ERR(DGGSN, LOGL_ERROR, 0, "Cannot allocate IP address in pool\n");
|
||||
gtp_create_context_resp(gsn, pdp, -rc);
|
||||
return 0; /* Allready in use, or no more available */
|
||||
}
|
||||
|
||||
|
@ -208,6 +214,8 @@ int create_context_ind(struct pdp_t *pdp)
|
|||
if (gtp_kernel_tunnel_add(pdp) < 0) {
|
||||
SYS_ERR(DGGSN, LOGL_ERROR, 0,
|
||||
"Cannot add tunnel to kernel: %s\n", strerror(errno));
|
||||
gtp_create_context_resp(gsn, pdp, GTPCAUSE_SYS_FAIL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!send_trap(gsn, pdp, member, "imsi-ass-ip")) { /* TRAP with IP assignment */
|
||||
|
|
16
lib/ippool.c
16
lib/ippool.c
|
@ -402,7 +402,7 @@ int ippool_newip(struct ippool_t *this, struct ippoolm_t **member,
|
|||
if (!this->allowstat) {
|
||||
SYS_ERR(DIP, LOGL_ERROR, 0,
|
||||
"Static IP address not allowed");
|
||||
return -1;
|
||||
return -GTPCAUSE_NOT_SUPPORTED;
|
||||
}
|
||||
if (!in46a_within_mask(addr, &this->stataddr, this->stataddrprefixlen)) {
|
||||
SYS_ERR(DIP, LOGL_ERROR, 0, "Static out of range");
|
||||
|
@ -412,7 +412,7 @@ int ippool_newip(struct ippool_t *this, struct ippoolm_t **member,
|
|||
if (!this->allowdyn) {
|
||||
SYS_ERR(DIP, LOGL_ERROR, 0,
|
||||
"Dynamic IP address not allowed");
|
||||
return -1;
|
||||
return -GTPCAUSE_NOT_SUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -438,7 +438,7 @@ int ippool_newip(struct ippool_t *this, struct ippoolm_t **member,
|
|||
if (!this->firstdyn) {
|
||||
SYS_ERR(DIP, LOGL_ERROR, 0,
|
||||
"No more IP addresses available");
|
||||
return -1;
|
||||
return -GTPCAUSE_ADDR_OCCUPIED;
|
||||
} else
|
||||
p2 = this->firstdyn;
|
||||
}
|
||||
|
@ -447,12 +447,12 @@ int ippool_newip(struct ippool_t *this, struct ippoolm_t **member,
|
|||
if (p2->inuse) {
|
||||
SYS_ERR(DIP, LOGL_ERROR, 0,
|
||||
"IP address allready in use");
|
||||
return -1; /* Allready in use / Should not happen */
|
||||
return -GTPCAUSE_SYS_FAIL; /* Allready in use / Should not happen */
|
||||
}
|
||||
|
||||
if (p2->addr.len != addr->len) {
|
||||
SYS_ERR(DIP, LOGL_ERROR, 0, "MS requested unsupported PDP context type");
|
||||
return -1;
|
||||
return -GTPCAUSE_UNKNOWN_PDP;
|
||||
}
|
||||
|
||||
/* Remove from linked list of free dynamic addresses */
|
||||
|
@ -481,13 +481,13 @@ int ippool_newip(struct ippool_t *this, struct ippoolm_t **member,
|
|||
if (!this->firststat) {
|
||||
SYS_ERR(DIP, LOGL_ERROR, 0,
|
||||
"No more IP addresses available");
|
||||
return -1; /* No more available */
|
||||
return -GTPCAUSE_ADDR_OCCUPIED; /* No more available */
|
||||
} else
|
||||
p2 = this->firststat;
|
||||
|
||||
if (p2->addr.len != addr->len) {
|
||||
SYS_ERR(DIP, LOGL_ERROR, 0, "MS requested unsupported PDP context type");
|
||||
return -1;
|
||||
return -GTPCAUSE_UNKNOWN_PDP;
|
||||
}
|
||||
|
||||
/* Remove from linked list of free static addresses */
|
||||
|
@ -512,7 +512,7 @@ int ippool_newip(struct ippool_t *this, struct ippoolm_t **member,
|
|||
|
||||
SYS_ERR(DIP, LOGL_ERROR, 0,
|
||||
"Could not allocate IP address");
|
||||
return -1; /* Should never get here. TODO: Bad code */
|
||||
return -GTPCAUSE_SYS_FAIL; /* Should never get here. TODO: Bad code */
|
||||
}
|
||||
|
||||
int ippool_freeip(struct ippool_t *this, struct ippoolm_t *member)
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#define _IPPOOL_H
|
||||
|
||||
#include "../lib/in46_addr.h"
|
||||
#include "../gtp/gtp.h"
|
||||
|
||||
/* Assuming that the address space is fragmented we need a hash table
|
||||
in order to return the addresses.
|
||||
|
|
Reference in New Issue