mirror of
https://gitea.osmocom.org/cellular-infrastructure/osmo-ggsn.git
synced 2025-11-03 13:43:25 +00:00
Compare commits
7 Commits
1.4.0
...
neels/refa
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dce814f71c | ||
|
|
9684894586 | ||
|
|
9036950dea | ||
|
|
065476d192 | ||
|
|
af9ba522f5 | ||
|
|
ea600c9c02 | ||
|
|
878e188be7 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -2,6 +2,7 @@ Makefile
|
||||
Makefile.in
|
||||
aclocal.m4
|
||||
autom4te.cache
|
||||
compile
|
||||
config.guess
|
||||
config.h.in*
|
||||
config.h
|
||||
|
||||
57
gtp/gtp.c
57
gtp/gtp.c
@@ -305,19 +305,19 @@ static uint32_t get_tei(void *pack)
|
||||
* requires the receiving GSN to send a response, with the same information
|
||||
* as in the original response. For most messages this happens automatically:
|
||||
*
|
||||
* Echo: Automatically dublicates the original response
|
||||
* Echo: Automatically duplicates the original response
|
||||
* Create pdp context: The SGSN may send create context request even if
|
||||
* a context allready exist (imsi+nsapi?). This means that the reply will
|
||||
automatically dublicate the original response. It might however have
|
||||
* a context already exist (imsi+nsapi?). This means that the reply will
|
||||
* automatically duplicate the original response. It might however have
|
||||
* side effects in the application which is asked twice to validate
|
||||
* the login.
|
||||
* Update pdp context: Automatically dublicates the original response???
|
||||
* Update pdp context: Automatically duplicates the original response???
|
||||
* Delete pdp context. Automatically in gtp0, but in gtp1 will generate
|
||||
* a nonexist reply message.
|
||||
*
|
||||
* The correct solution will be to make a queue containing response messages.
|
||||
* This queue should be checked whenever a request is received. If the
|
||||
* response is allready in the queue that response should be transmitted.
|
||||
* response is already in the queue that response should be transmitted.
|
||||
* It should be possible to find messages in this queue on the basis of
|
||||
* the sequence number and peer GSN IP address (The sequense number is unique
|
||||
* within each path). This need to be implemented by a hash table. Furthermore
|
||||
@@ -614,7 +614,16 @@ int gtp_notification(struct gsn_t *gsn, int version,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gtp_dublicate(struct gsn_t *gsn, int version,
|
||||
/* Look for a message in the response queue for the given peer and sequence
|
||||
* number seq. If found, (re-)send the response message and return 0. Otherwise
|
||||
* return nonzero. This allows catching duplicate messages.
|
||||
* A response message stays in the response queue until it times out.
|
||||
* So, for any number of identical requests within that timeout period, the
|
||||
* same packet can be resent.
|
||||
* TODO this only checks the peer and sequence number, and does not verify that
|
||||
* the GTP request is identical to the previous one for this peer and sequence
|
||||
* nr: a mere peer or seq glitch can cause leaks of previous responses. */
|
||||
int gtp_duplicate(struct gsn_t *gsn, int version,
|
||||
struct sockaddr_in *peer, uint16_t seq)
|
||||
{
|
||||
struct qmsg_t *qmsg;
|
||||
@@ -636,6 +645,8 @@ int gtp_dublicate(struct gsn_t *gsn, int version,
|
||||
qmsg->fd, (unsigned long)&qmsg->p, qmsg->l,
|
||||
strerror(errno));
|
||||
}
|
||||
|
||||
/* TODO: qmsg->retrans++ ? */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -873,8 +884,8 @@ int gtp_echo_ind(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
|
||||
int fd, void *pack, unsigned len)
|
||||
{
|
||||
|
||||
/* Check if it was a dublicate request */
|
||||
if (!gtp_dublicate(gsn, 0, peer, get_seq(pack)))
|
||||
/* Repeat previous response in case of duplicate request */
|
||||
if (!gtp_duplicate(gsn, 0, peer, get_seq(pack)))
|
||||
return 0;
|
||||
|
||||
/* Send off reply to request */
|
||||
@@ -1258,13 +1269,15 @@ int gtp_create_pdp_ind(struct gsn_t *gsn, int version,
|
||||
uint8_t linked_nsapi = 0;
|
||||
struct pdp_t *linked_pdp = NULL;
|
||||
|
||||
if (!gtp_dublicate(gsn, version, peer, seq))
|
||||
/* Repeat previous response in case of duplicate request */
|
||||
if (!gtp_duplicate(gsn, version, peer, seq))
|
||||
return 0;
|
||||
|
||||
pdp = &pdp_buf;
|
||||
memset(pdp, 0, sizeof(struct pdp_t));
|
||||
|
||||
if (version == 0) {
|
||||
/* TODO code dup: get_tid() */
|
||||
uint64_t tid = be64toh(((union gtp_packet *)pack)->gtp0.h.tid);
|
||||
|
||||
pdp_set_imsi_nsapi(pdp, tid);
|
||||
@@ -1511,7 +1524,7 @@ int gtp_create_pdp_ind(struct gsn_t *gsn, int version,
|
||||
if (!pdp_getimsi(&pdp_old, pdp->imsi, pdp->nsapi)) {
|
||||
/* Found old pdp with same tid. Now the voodoo begins! */
|
||||
/* 09.60 / 29.060 allows create on existing context to "steal" */
|
||||
/* the context which was allready established */
|
||||
/* the context which was already established */
|
||||
/* We check that the APN, selection mode and MSISDN is the same */
|
||||
DEBUGP(DLGTP, "gtp_create_pdp_ind: Old context found\n");
|
||||
if ((pdp->apn_req.l == pdp_old->apn_req.l)
|
||||
@@ -1953,10 +1966,9 @@ int gtp_update_pdp_ind(struct gsn_t *gsn, int version,
|
||||
uint64_t imsi;
|
||||
uint8_t nsapi;
|
||||
|
||||
/* Is this a dublicate ? */
|
||||
if (!gtp_dublicate(gsn, version, peer, seq)) {
|
||||
return 0; /* We allready send of response once */
|
||||
}
|
||||
/* Repeat previous response in case of duplicate request */
|
||||
if (!gtp_duplicate(gsn, version, peer, seq))
|
||||
return 0;
|
||||
|
||||
/* Decode information elements */
|
||||
if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
|
||||
@@ -2085,7 +2097,7 @@ int gtp_update_pdp_ind(struct gsn_t *gsn, int version,
|
||||
}
|
||||
|
||||
/* TEIC (conditional) */
|
||||
/* If TEIC is not included it means that we have allready received it */
|
||||
/* If TEIC is not included it means that we have already received it */
|
||||
/* TODO: From 29.060 it is not clear if TEI_C MUST be included for */
|
||||
/* all updated contexts, or only for one of the linked contexts */
|
||||
gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn);
|
||||
@@ -2179,6 +2191,9 @@ int gtp_update_pdp_conf(struct gsn_t *gsn, int version,
|
||||
if (gtp_conf(gsn, 0, peer, pack, len, &type, &cbp))
|
||||
return EOF;
|
||||
|
||||
/* TODO This function is called from gtp_decaps1c() (for GTP v1) but
|
||||
* uses gtp0.h.flow (GTP v0 data element)
|
||||
*/
|
||||
/* Find the context in question */
|
||||
if (pdp_getgtp0(&pdp, ntoh16(((union gtp_packet *)pack)->gtp0.h.flow))) {
|
||||
gsn->err_unknownpdp++;
|
||||
@@ -2192,6 +2207,9 @@ int gtp_update_pdp_conf(struct gsn_t *gsn, int version,
|
||||
/* Register that we have received a valid teic from GGSN */
|
||||
pdp->teic_confirmed = 1;
|
||||
|
||||
/* TODO This function is called from gtp_decaps1c() (for GTP v1) but
|
||||
* explicitly passes version 0 and GTP0_HEADER_SIZE to gtpie_decaps()
|
||||
*/
|
||||
/* Decode information elements */
|
||||
if (gtpie_decaps
|
||||
(ie, 0, pack + GTP0_HEADER_SIZE, len - GTP0_HEADER_SIZE)) {
|
||||
@@ -2424,10 +2442,9 @@ int gtp_delete_pdp_ind(struct gsn_t *gsn, int version,
|
||||
int n;
|
||||
int count = 0;
|
||||
|
||||
/* Is this a dublicate ? */
|
||||
if (!gtp_dublicate(gsn, version, peer, seq)) {
|
||||
return 0; /* We allready send off response once */
|
||||
}
|
||||
/* Repeat previous response in case of duplicate request */
|
||||
if (!gtp_duplicate(gsn, version, peer, seq))
|
||||
return 0;
|
||||
|
||||
/* Find the linked context in question */
|
||||
if (pdp_getgtp1(&linked_pdp, get_tei(pack))) {
|
||||
@@ -2638,7 +2655,7 @@ int gtp_gpdu_ind(struct gsn_t *gsn, int version,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Receives GTP packet and sends off for further processing
|
||||
/* Receives GTP packet and sends off for further processing.
|
||||
* Function will check the validity of the header. If the header
|
||||
* is not valid the packet is either dropped or a version not
|
||||
* supported is returned to the peer.
|
||||
|
||||
@@ -147,7 +147,7 @@ struct ul16_t;
|
||||
|
||||
struct gtp0_header { /* Descriptions from 3GPP 09.60 */
|
||||
uint8_t flags; /* 01 bitfield, with typical values */
|
||||
/* 000..... Version: 1 (0) */
|
||||
/* 000..... Version: 0 */
|
||||
/* ...1111. Spare (7) */
|
||||
/* .......0 SNDCP N-PDU Number flag (0) */
|
||||
uint8_t type; /* 02 Message type. T-PDU = 0xff */
|
||||
@@ -223,7 +223,7 @@ union gtp_packet {
|
||||
* application this struct is provided in order to store all
|
||||
* relevant information related to the gsn.
|
||||
*
|
||||
* Note that this does not include information storage for '
|
||||
* Note that this does not include information storage for
|
||||
* each pdp context. This is stored in another struct.
|
||||
*************************************************************/
|
||||
|
||||
|
||||
20
gtp/gtpie.c
20
gtp/gtpie.c
@@ -135,13 +135,14 @@ int gtpie_gettlv(union gtpie_member *ie[], int type, int instance,
|
||||
{
|
||||
int ien;
|
||||
ien = gtpie_getie(ie, type, instance);
|
||||
if (ien >= 0) {
|
||||
*length = ntoh16(ie[ien]->tlv.l);
|
||||
if (*length <= size)
|
||||
memcpy(dst, ie[ien]->tlv.v, *length);
|
||||
else
|
||||
return EOF;
|
||||
}
|
||||
if (ien < 0)
|
||||
return EOF;
|
||||
|
||||
*length = ntoh16(ie[ien]->tlv.l);
|
||||
if (*length > size)
|
||||
return EOF;
|
||||
|
||||
memcpy(dst, ie[ien]->tlv.v, *length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -150,10 +151,9 @@ int gtpie_gettv0(union gtpie_member *ie[], int type, int instance,
|
||||
{
|
||||
int ien;
|
||||
ien = gtpie_getie(ie, type, instance);
|
||||
if (ien >= 0)
|
||||
memcpy(dst, ie[ien]->tv0.v, size);
|
||||
else
|
||||
if (ien < 0)
|
||||
return EOF;
|
||||
memcpy(dst, ie[ien]->tv0.v, size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1267,7 +1267,8 @@ int cb_tun_ind(struct tun_t *tun, void *pack, unsigned len)
|
||||
src.s_addr = iph->src;
|
||||
|
||||
if (ipget(&ipm, &src)) {
|
||||
printf("Received packet without a valid source address!!!\n");
|
||||
printf("Dropping packet from invalid source address: %s\n",
|
||||
inet_ntoa(src));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1569,7 +1570,7 @@ int main(int argc, char **argv)
|
||||
512 = Flat rate, 256 = Hot billing */
|
||||
|
||||
/* Create context */
|
||||
/* We send this of once. Retransmissions are handled by gtplib */
|
||||
/* We send this off once. Retransmissions are handled by gtplib */
|
||||
gtp_create_context_req(gsn, pdp, &iparr[n]);
|
||||
}
|
||||
|
||||
@@ -1577,9 +1578,9 @@ int main(int argc, char **argv)
|
||||
|
||||
printf("Waiting for response from ggsn........\n\n");
|
||||
|
||||
/******************************************************************/
|
||||
/******************************************************************/
|
||||
/* Main select loop */
|
||||
/******************************************************************/
|
||||
/******************************************************************/
|
||||
|
||||
while ((0 != state) && (5 != state)) {
|
||||
|
||||
@@ -1613,7 +1614,7 @@ int main(int argc, char **argv)
|
||||
state = 3;
|
||||
}
|
||||
|
||||
/* Send off disconnect */
|
||||
/* Send disconnect */
|
||||
if (3 == state) {
|
||||
state = 4;
|
||||
stoptime = time(NULL) + 5; /* Extra seconds to allow disconnect */
|
||||
@@ -1628,11 +1629,11 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
/* Send of ping packets */
|
||||
/* Send ping packets */
|
||||
diff = 0;
|
||||
while ((diff <= 0) &&
|
||||
/* Send off an ICMP ping packet */
|
||||
/*if ( */ (options.pinghost.s_addr) && (2 == state) &&
|
||||
/*if */ (options.pinghost.s_addr) && (2 == state) &&
|
||||
((pingseq < options.pingcount)
|
||||
|| (options.pingcount == 0))) {
|
||||
if (!pingseq)
|
||||
|
||||
Reference in New Issue
Block a user