aboutsummaryrefslogtreecommitdiffstats
path: root/sgsnemu/sgsnemu.c
diff options
context:
space:
mode:
authorjjako <jjako>2003-11-10 12:31:41 +0000
committerjjako <jjako>2003-11-10 12:31:41 +0000
commit193e8b1b01ed3e4065d4a300fddbf51a2980844b (patch)
treef1cb9920ca8e0845b5e949c49ad950db40ddff33 /sgsnemu/sgsnemu.c
parent0b076a331e1e7f955580313a5da416c170b3b4ce (diff)
Added --net, --nsapi, --gtpversion options
Diffstat (limited to 'sgsnemu/sgsnemu.c')
-rw-r--r--sgsnemu/sgsnemu.c152
1 files changed, 141 insertions, 11 deletions
diff --git a/sgsnemu/sgsnemu.c b/sgsnemu/sgsnemu.c
index e636f1b..c63f634 100644
--- a/sgsnemu/sgsnemu.c
+++ b/sgsnemu/sgsnemu.c
@@ -59,7 +59,7 @@
#include "cmdline.h"
#define IPADDRLEN 256 /* Character length of addresses */
-#define MAXCONTEXTS 16 /* Max number of allowed contexts */
+#define MAXCONTEXTS 1024 /* Max number of allowed contexts */
/* HASH tables for IP address allocation */
struct iphash_t {
@@ -89,6 +89,7 @@ int echoversion = 1; /* First try this version */
struct {
int debug; /* Print debug messages */
int createif; /* Create local network interface */
+ struct in_addr net, mask; /* Network interface */
char *ipup, *ipdown; /* Filename of scripts */
int defaultroute; /* Set up default route */
struct in_addr pinghost; /* Remote ping host */
@@ -103,6 +104,8 @@ struct {
int timelimit; /* Number of seconds to be connected */
char *statedir;
uint64_t imsi;
+ uint8_t nsapi;
+ int gtpversion;
struct ul255_t pco;
struct ul255_t qos;
struct ul255_t apn;
@@ -389,8 +392,18 @@ int process_options(int argc, char **argv) {
options.imsi |= ((uint64_t) (args_info.imsi_arg[13]-48)) << 52;
options.imsi |= ((uint64_t) (args_info.imsi_arg[14]-48)) << 56;
- printf("IMSI is: %s (%#08llx)\n",
- args_info.imsi_arg, options.imsi);
+ printf("IMSI is: %s (%#08llx)\n",
+ args_info.imsi_arg, options.imsi);
+
+
+ /* nsapi */
+ if ((args_info.nsapi_arg > 15) ||
+ (args_info.nsapi_arg < 0)) {
+ printf("Invalid NSAPI\n");
+ return -1;
+ }
+ options.nsapi = args_info.nsapi_arg;
+ printf("Using NSAPI: %d\n", args_info.nsapi_arg);
/* qos */
@@ -409,6 +422,16 @@ int process_options(int argc, char **argv) {
/* Timelimit */
options.timelimit = args_info.timelimit_arg;
+ /* gtpversion */
+ if ((args_info.gtpversion_arg > 1) ||
+ (args_info.gtpversion_arg < 0)) {
+ printf("Invalid GTP version\n");
+ return -1;
+ }
+ options.gtpversion = args_info.gtpversion_arg;
+ printf("Using GTP version: %d\n", args_info.gtpversion_arg);
+
+
/* apn */
if (strlen(args_info.apn_arg) > (sizeof(options.apn.v)-1)) {
printf("Invalid APN\n");
@@ -464,6 +487,20 @@ int process_options(int argc, char **argv) {
/* createif */
options.createif = args_info.createif_flag;
+ /* net */
+ /* Store net as in_addr net and mask */
+ if (args_info.net_arg) {
+ if(ippool_aton(&options.net, &options.mask, args_info.net_arg, 0)) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0,
+ "Invalid network address: %s!", args_info.net_arg);
+ exit(1);
+ }
+ }
+ else {
+ options.net.s_addr = 0;
+ options.mask.s_addr = 0;
+ }
+
/* ipup */
options.ipup = args_info.ipup_arg;
@@ -544,6 +581,81 @@ char * print_icmptype(int t) {
return(ttab[t]);
}
+int msisdn_add(struct ul16_t *src, struct ul16_t *dst, int add) {
+ int n;
+ uint64_t i64 = 0;
+ uint8_t msa[sizeof(i64) * 3]; /* Allocate 3 digits per octet (0..255) */
+ int msalen = 0;
+
+ /* Convert to uint64_t from ul16_t format (most significant digit first) */
+ /* ul16_t format always starts with 0x91 to indicate international format */
+ /* In ul16_t format 0x0f/0xf0 indicates that digit is not used */
+ for (n=0; n< src->l; n++) {
+ if ((src->v[n] & 0x0f) != 0x0f) {
+ i64 *= 10;
+ i64 += src->v[n] & 0x0f;
+ }
+ if ((src->v[n] & 0xf0) != 0xf0) {
+ i64 *= 10;
+ i64 += (src->v[n] & 0xf0) >> 4;
+ }
+ }
+
+ i64 += add;
+
+ /* Generate array with least significant digit in first octet */
+ while (i64) {
+ msa[msalen++] = i64 % 10;
+ i64 = i64 / 10;
+ }
+
+ /* Convert back to ul16_t format */
+ for(n=0; n<msalen; n++) {
+ if ((n%2) == 0) {
+ dst->v[((int)n/2)] = msa[msalen-n-1] + 0xf0;
+ dst->l += 1;
+ }
+ else {
+ dst->v[((int)n/2)] = (dst->v[((int)n/2)] & 0x0f) +
+ msa[msalen-n-1] * 16;
+ }
+ }
+
+ return 0;
+
+}
+
+int imsi_add(uint64_t src, uint64_t *dst, int add) {
+ /* TODO: big endian / small endian ??? */
+ uint64_t i64 = 0;
+
+ /* Convert from uint64_t bcd to uint64_t integer format */
+ /* The resulting integer format is multiplied by 10 */
+ while (src) {
+ if ((src & 0x0f) != 0x0f) {
+ i64 *= 10;
+ i64 += (src & 0x0f);
+ }
+ if ((src & 0xf0) != 0xf0) {
+ i64 *= 10;
+ i64 += (src & 0xf0) >> 4;
+ }
+ src = src >> 8;
+ }
+
+ i64 += add * 10;
+
+ *dst = 0;
+ while (i64) {
+ *dst = *dst << 4;
+ *dst += (i64 % 10);
+ i64 = i64 / 10;
+ }
+
+ return 0;
+
+}
+
/* Calculate time left until we have to send off next ping packet */
int ping_timeout(struct timeval *tp) {
struct timezone tz;
@@ -786,7 +898,7 @@ int create_pdp_conf(struct pdp_t *pdp, void *cbp, int cause) {
if (iph->pdp->version == 1) {
printf("Retrying with version 0\n");
iph->pdp->version = 0;
- gtp_create_context_req(gsn, iph->pdp, iph, &options.remote);
+ gtp_create_context_req(gsn, iph->pdp, iph);
return 0;
}
else {
@@ -816,7 +928,7 @@ int create_pdp_conf(struct pdp_t *pdp, void *cbp, int cause) {
printf("Received create PDP context response. IP address: %s\n",
inet_ntoa(addr));
- if (options.createif) {
+ if ((options.createif) && (!options.net.s_addr)) {
struct in_addr m;
inet_aton("255.255.255.255", &m);
/* printf("Setting up interface and routing\n");*/
@@ -935,6 +1047,18 @@ int main(int argc, char **argv)
if (tun->fd > maxfd) maxfd = tun->fd;
}
+ if ((options.createif) && (options.net.s_addr)) {
+ /* printf("Setting up interface and routing\n");*/
+ tun_addaddr(tun, &options.net, &options.net, &options.mask);
+ if (options.defaultroute) {
+ struct in_addr rm;
+ rm.s_addr = 0;
+ tun_addroute(tun, &rm, &options.net, &rm);
+ }
+ if (options.ipup) tun_runscript(tun, options.ipup);
+ }
+
+
/* Initialise hash tables */
memset(&iphash, 0, sizeof(iphash));
memset(&iparr, 0, sizeof(iparr));
@@ -943,16 +1067,20 @@ int main(int argc, char **argv)
/* See if anybody is there */
printf("Sending off echo request\n");
+ echoversion = options.gtpversion;
gtp_echo_req(gsn, echoversion, NULL, &options.remote); /* Is remote alive? */
for(n=0; n<options.contexts; n++) {
+ uint64_t myimsi;
printf("Setting up PDP context #%d\n", n);
iparr[n].inuse = 1; /* TODO */
+ imsi_add(options.imsi, &myimsi, n);
+
/* Allocated here. */
/* If create context failes we have to deallocate ourselves. */
- /* Otherwise it is deallocated gy gtplib */
- pdp_newpdp(&pdp, options.imsi, n, NULL);
+ /* Otherwise it is deallocated by gtplib */
+ pdp_newpdp(&pdp, myimsi, options.nsapi, NULL);
pdp->peer = &iparr[n];
pdp->ipif = tun; /* TODO */
@@ -992,8 +1120,7 @@ int main(int argc, char **argv)
exit(1);
}
else {
- pdp->msisdn.l = options.msisdn.l;
- memcpy(pdp->msisdn.v, options.msisdn.v, options.msisdn.l);
+ msisdn_add(&options.msisdn, &pdp->msisdn, n);
}
ipv42eua(&pdp->eua, NULL); /* Request dynamic IP address */
@@ -1007,11 +1134,14 @@ int main(int argc, char **argv)
memcpy(pdp->pco_req.v, options.pco.v, options.pco.l);
}
- pdp->version = 1; /* First try with version 1 */
+ pdp->version = options.gtpversion;
+
+ pdp->hisaddr0 = options.remote;
+ pdp->hisaddr1 = options.remote;
/* Create context */
/* We send this of once. Retransmissions are handled by gtplib */
- gtp_create_context_req(gsn, pdp, &iparr[n], &options.remote);
+ gtp_create_context_req(gsn, pdp, &iparr[n]);
}
state = 1; /* Enter wait_connection state */