aboutsummaryrefslogtreecommitdiffstats
path: root/gtp/gtp.c
diff options
context:
space:
mode:
authorjjako <jjako>2003-07-06 20:53:57 +0000
committerjjako <jjako>2003-07-06 20:53:57 +0000
commit1db1c81302902cdaa34fbc9953abd08cfb70f0f0 (patch)
treeed49bf4faffd7ede3ff5ba27f2e7aed0da6a2d18 /gtp/gtp.c
parent88c2216e8eec9be3a3aa08f1020d045a31d291e1 (diff)
Improved GTP error handling
Diffstat (limited to 'gtp/gtp.c')
-rw-r--r--gtp/gtp.c184
1 files changed, 140 insertions, 44 deletions
diff --git a/gtp/gtp.c b/gtp/gtp.c
index fb98be1..fa87364 100644
--- a/gtp/gtp.c
+++ b/gtp/gtp.c
@@ -54,6 +54,55 @@
#include "gtpie.h"
#include "queue.h"
+
+/* Error reporting functions */
+
+void gtp_err(int priority, char *filename, int linenum, char *fmt, ...) {
+ va_list args;
+ char buf[ERRMSG_SIZE];
+
+ va_start(args, fmt);
+ vsnprintf(buf, ERRMSG_SIZE, fmt, args);
+ va_end(args);
+ buf[ERRMSG_SIZE-1] = 0;
+ syslog(priority, "%s: %d: %s", filename, linenum, buf);
+}
+
+void gtp_errpack(int pri, char *fn, int ln, struct sockaddr_in *peer,
+ void *pack, unsigned len, char *fmt, ...) {
+
+ va_list args;
+ char buf[ERRMSG_SIZE];
+ char buf2[ERRMSG_SIZE];
+ int n;
+ int pos;
+
+ va_start(args, fmt);
+ vsnprintf(buf, ERRMSG_SIZE, fmt, args);
+ va_end(args);
+ buf[ERRMSG_SIZE-1] = 0;
+
+ snprintf(buf2, ERRMSG_SIZE, "Packet from %s:%u, length: %d, content:",
+ inet_ntoa(peer->sin_addr),
+ ntohs(peer->sin_port),
+ len);
+ buf2[ERRMSG_SIZE-1] = 0;
+ pos = strlen(buf2);
+ for(n=0; n<len; n++) {
+ if ((pos+4)<ERRMSG_SIZE) {
+ sprintf((buf2+pos), " %02hhx", ((unsigned char*)pack)[n]);
+ pos += 3;
+ }
+ }
+ buf2[pos] = 0;
+
+ syslog(pri, "%s: %d: %s. %s", fn, ln, buf, buf2);
+
+}
+
+
+
+
/* API Functions */
const char* gtp_version()
@@ -80,6 +129,65 @@ int gtp_create_context(struct gsn_t *gsn, struct pdp_t *pdp, void *aid,
return gtp_create_pdp_req(gsn, version, aid, inetaddr, pdp);
}
+int gtp_create_context2(struct gsn_t *gsn, void *aid,
+ struct in_addr* inetaddr,
+ int selmode, uint64_t imsi, int nsapi,
+ uint8_t *qos, int qoslen,
+ char *apn, int apnlen,
+ char *msisdn, int msisdnlen,
+ uint8_t *pco, int pcolen) {
+ int version = 0;
+
+ struct pdp_t *pdp;
+
+ if (qoslen > sizeof(pdp->qos_req0)) {
+ gtp_err(LOG_ERR, __FILE__, __LINE__, 0, "QoS length too big");
+ return -1;
+ }
+
+ if (apnlen > sizeof(pdp->apn_use.v)) {
+ gtp_err(LOG_ERR, __FILE__, __LINE__, 0, "APN length too big");
+ return -1;
+ }
+
+ if (msisdnlen > sizeof(pdp->msisdn.v)) {
+ gtp_err(LOG_ERR, __FILE__, __LINE__, 0, "MSISDN length too big");
+ return -1;
+ }
+
+ if (pcolen > sizeof(pdp->pco_req.v)) {
+ gtp_err(LOG_ERR, __FILE__, __LINE__, 0, "PCO length too big");
+ return -1;
+ }
+
+ /* New pdp allocated here:*/
+ pdp_newpdp(&pdp, imsi, nsapi, NULL);
+
+ pdp->peer = aid;
+ pdp->ipif = NULL;
+
+ pdp->selmode = selmode;
+
+ memcpy(pdp->qos_req0, qos, qoslen); /* Length checked above */
+ pdp->apn_use.l = apnlen;
+ memcpy(pdp->apn_use.v, apn, apnlen); /* Length checked above */
+
+ pdp->gsnlc.l = sizeof(gsn->gsnc);
+ memcpy(pdp->gsnlc.v, &gsn->gsnc, sizeof(gsn->gsnc));
+ pdp->gsnlu.l = sizeof(gsn->gsnc);
+ memcpy(pdp->gsnlu.v, &gsn->gsnc, sizeof(gsn->gsnc));
+
+ pdp->msisdn.l = msisdnlen;
+ memcpy(pdp->msisdn.v, msisdn, msisdnlen);
+
+ ipv42eua(&pdp->eua, NULL); /* Request dynamic IP address */
+
+ pdp->pco_req.l = pcolen;
+ memcpy(pdp->pco_req.v, pco, pcolen);
+
+ return gtp_create_pdp_req(gsn, version, aid, inetaddr, pdp);
+}
+
int gtp_update_context(struct gsn_t *gsn, struct pdp_t *pdp, void *aid,
struct in_addr* inetaddr) {
int version = 0;
@@ -213,49 +321,6 @@ char* snprint_packet(struct gsn_t *gsn, struct sockaddr_in *peer,
return buf;
}
-void gtp_err(int priority, char *filename, int linenum, char *fmt, ...) {
- va_list args;
- char buf[ERRMSG_SIZE];
-
- va_start(args, fmt);
- vsnprintf(buf, ERRMSG_SIZE, fmt, args);
- va_end(args);
- buf[ERRMSG_SIZE-1] = 0;
- syslog(priority, "%s: %d: %s", filename, linenum, buf);
-}
-
-void gtp_errpack(int pri, char *fn, int ln, struct sockaddr_in *peer,
- void *pack, unsigned len, char *fmt, ...) {
-
- va_list args;
- char buf[ERRMSG_SIZE];
- char buf2[ERRMSG_SIZE];
- int n;
- int pos;
-
- va_start(args, fmt);
- vsnprintf(buf, ERRMSG_SIZE, fmt, args);
- va_end(args);
- buf[ERRMSG_SIZE-1] = 0;
-
- snprintf(buf2, ERRMSG_SIZE, "Packet from %s:%u, length: %d, content:",
- inet_ntoa(peer->sin_addr),
- ntohs(peer->sin_port),
- len);
- buf2[ERRMSG_SIZE-1] = 0;
- pos = strlen(buf2);
- for(n=0; n<len; n++) {
- if ((pos+4)<ERRMSG_SIZE) {
- sprintf((buf2+pos), " %02hhx", ((unsigned char*)pack)[n]);
- pos += 3;
- }
- }
- buf2[pos] = 0;
-
- syslog(pri, "%s: %d: %s. %s", fn, ln, buf, buf2);
-
-}
-
/* ***********************************************************
* Reliable delivery of signalling messages
@@ -560,7 +625,8 @@ static void log_restart(struct gsn_t *gsn) {
-int gtp_new(struct gsn_t **gsn, char *statedir, struct in_addr *listen)
+int gtp_new(struct gsn_t **gsn, char *statedir, struct in_addr *listen,
+ int mode)
{
struct sockaddr_in addr;
int gtp_fd;
@@ -1720,6 +1786,14 @@ int gtp_gpdu_ind(struct gsn_t *gsn, int version,
return gtp_error_ind_resp(gsn, version, peer, pack, len);
}
+
+ /* If the GPDU was not from the peer GSN tell him to delete context */
+ if (memcmp(&peer->sin_addr, pdp->gsnru.v, pdp->gsnru.l)) { /* TODO Range? */
+ gsn->err_unknownpdp++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
+ "Unknown PDP context");
+ return gtp_error_ind_resp(gsn, version, peer, pack, len);
+ }
/* Callback function */
if (gsn->cb_gpdu !=0)
@@ -1801,6 +1875,28 @@ int gtp_decaps(struct gsn_t *gsn)
"GTP0 packet too short");
continue; /* Silently discard 29.60: 11.1.2 */
}
+
+ if ((gsn->mode == GTP_MODE_GGSN) &&
+ ((pheader->type == GTP_CREATE_PDP_RSP) ||
+ (pheader->type == GTP_UPDATE_PDP_RSP) ||
+ (pheader->type == GTP_DELETE_PDP_RSP))) {
+ gsn->unexpect++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
+ "Unexpected GTP Signalling Message");
+ continue; /* Silently discard 29.60: 11.1.4 */
+ }
+
+ if ((gsn->mode == GTP_MODE_SGSN) &&
+ ((pheader->type == GTP_CREATE_PDP_REQ) ||
+ (pheader->type == GTP_UPDATE_PDP_REQ) ||
+ (pheader->type == GTP_DELETE_PDP_REQ))) {
+ gsn->unexpect++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
+ "Unexpected GTP Signalling Message");
+ continue; /* Silently discard 29.60: 11.1.4 */
+ }
+
+
switch (pheader->type) {
case GTP_ECHO_REQ: