blob: edee09ec1d40f7720cabdec605dccc63eb42a0dc [file] [log] [blame]
jjako52c24142002-12-16 13:33:51 +00001/*
2 * OpenGGSN - Gateway GPRS Support Node
jjako0fe0df02004-09-17 11:30:40 +00003 * Copyright (C) 2002, 2003, 2004 Mondru AB.
jjako52c24142002-12-16 13:33:51 +00004 *
5 * The contents of this file may be used under the terms of the GNU
6 * General Public License Version 2, provided that the above copyright
7 * notice and this permission notice is included in all copies or
8 * substantial portions of the software.
9 *
jjako52c24142002-12-16 13:33:51 +000010 */
11
12/*
13 * sgsnemu.c
14 *
15 */
16
17
18#ifdef __linux__
jjakoa7cd2492003-04-11 09:40:12 +000019#define _GNU_SOURCE 1 /* strdup() prototype, broken arpa/inet.h */
jjako52c24142002-12-16 13:33:51 +000020#endif
21
22
23#include <syslog.h>
24#include <ctype.h>
25#include <netdb.h>
26#include <signal.h>
27#include <stdio.h>
28#include <string.h>
29#include <stdlib.h>
30#include <sys/types.h>
31#include <sys/socket.h>
32#include <netinet/in.h>
33#include <arpa/inet.h>
34#include <sys/wait.h>
35#include <sys/stat.h>
36#include <unistd.h>
37#include <sys/socket.h>
38#include <sys/ioctl.h>
jjako5da68452003-01-28 16:08:47 +000039#include <sys/time.h>
jjako52c24142002-12-16 13:33:51 +000040#include <net/if.h>
jjako52c24142002-12-16 13:33:51 +000041#include <errno.h>
jjako52c24142002-12-16 13:33:51 +000042#include <sys/socket.h>
jjako52c24142002-12-16 13:33:51 +000043#include <resolv.h>
44#include <time.h>
45
jjakoff9985c2004-01-16 11:05:22 +000046#include "config.h"
Emmanuel Bretelle2a103682010-09-07 17:01:20 +020047#include "../lib/tun.h"
48#include "../lib/ippool.h"
49#include "../lib/syserr.h"
jjako52c24142002-12-16 13:33:51 +000050#include "../gtp/pdp.h"
51#include "../gtp/gtp.h"
52#include "cmdline.h"
53
jjakoa7cd2492003-04-11 09:40:12 +000054#define IPADDRLEN 256 /* Character length of addresses */
jjako193e8b12003-11-10 12:31:41 +000055#define MAXCONTEXTS 1024 /* Max number of allowed contexts */
jjako5da68452003-01-28 16:08:47 +000056
jjakoa7cd2492003-04-11 09:40:12 +000057/* HASH tables for IP address allocation */
58struct iphash_t {
59 uint8_t inuse; /* 0=free. 1=used by somebody */
60 struct iphash_t *ipnext;
61 struct pdp_t *pdp;
62 struct in_addr addr;
63};
64struct iphash_t iparr[MAXCONTEXTS];
65struct iphash_t *iphash[MAXCONTEXTS];
66
67/* State variable used for ping */
68/* 0: Idle */
69/* 1: Wait_connect */
70/* 2: Connected */
jjako7b8fad42003-07-07 14:37:42 +000071/* 3: Done */
72/* 4: Wait_disconnect */
73/* 5: Disconnected */
jjako581c9f02003-10-22 11:28:20 +000074int state = 0;
jjako52c24142002-12-16 13:33:51 +000075
jjakoa7cd2492003-04-11 09:40:12 +000076struct gsn_t *gsn = NULL; /* GSN instance */
77struct tun_t *tun = NULL; /* TUN instance */
jjako52c24142002-12-16 13:33:51 +000078int maxfd = 0; /* For select() */
jjako91aaf222003-10-22 10:09:32 +000079int echoversion = 1; /* First try this version */
jjako52c24142002-12-16 13:33:51 +000080
jjakoa7cd2492003-04-11 09:40:12 +000081/* Struct with local versions of gengetopt options */
82struct {
83 int debug; /* Print debug messages */
84 int createif; /* Create local network interface */
jjakoc6762cf2004-04-28 14:52:58 +000085 struct in_addr netaddr, destaddr, net, mask; /* Network interface */
jjakoa7cd2492003-04-11 09:40:12 +000086 char *ipup, *ipdown; /* Filename of scripts */
87 int defaultroute; /* Set up default route */
88 struct in_addr pinghost; /* Remote ping host */
89 int pingrate;
90 int pingsize;
91 int pingcount;
92 int pingquiet;
93 struct in_addr listen;
94 struct in_addr remote;
95 struct in_addr dns;
96 int contexts; /* Number of contexts to create */
97 int timelimit; /* Number of seconds to be connected */
98 char *statedir;
99 uint64_t imsi;
jjako193e8b12003-11-10 12:31:41 +0000100 uint8_t nsapi;
101 int gtpversion;
jjakoa7cd2492003-04-11 09:40:12 +0000102 struct ul255_t pco;
103 struct ul255_t qos;
jjako7e051d32004-05-27 20:06:36 +0000104 uint16_t cch;
jjakoa7cd2492003-04-11 09:40:12 +0000105 struct ul255_t apn;
jjako1a51df72004-07-20 08:30:21 +0000106 uint8_t selmode;
Yann BONNAMY944dce32010-10-29 17:07:44 +0200107 struct ul255_t rattype;
108 int rattype_given;
109 struct ul255_t userloc;
110 int userloc_given;
111 struct ul255_t mstz;
112 int mstz_given;
113 struct ul255_t imeisv;
114 int imeisv_given;
jjakoa7cd2492003-04-11 09:40:12 +0000115 struct ul16_t msisdn;
116} options;
jjako52c24142002-12-16 13:33:51 +0000117
jjako5da68452003-01-28 16:08:47 +0000118
119/* Definitions to use for PING. Most of the ping code was derived from */
120/* the original ping program by Mike Muuss */
121
122/* IP header and ICMP echo header */
123#define CREATEPING_MAX 2048
124#define CREATEPING_IP 20
125#define CREATEPING_ICMP 8
126
127struct ip_ping {
jjako0141d202004-01-09 15:19:20 +0000128 uint8_t ipver; /* Type and header length*/
129 uint8_t tos; /* Type of Service */
130 uint16_t length; /* Total length */
131 uint16_t fragid; /* Identifier */
132 uint16_t offset; /* Flags and fragment offset */
133 uint8_t ttl; /* Time to live */
134 uint8_t protocol; /* Protocol */
135 uint16_t ipcheck; /* Header checksum */
136 uint32_t src; /* Source address */
137 uint32_t dst; /* Destination */
138 uint8_t type; /* Type and header length*/
139 uint8_t code; /* Code */
140 uint16_t checksum; /* Header checksum */
141 uint16_t ident; /* Identifier */
142 uint16_t seq; /* Sequence number */
143 uint8_t data[CREATEPING_MAX]; /* Data */
jjako5da68452003-01-28 16:08:47 +0000144} __attribute__((packed));
145
146/* Statistical values for ping */
147int nreceived = 0;
148int ntreceived = 0;
149int ntransmitted = 0;
150int tmin = 999999999;
151int tmax = 0;
152int tsum = 0;
jjakoafb2a972003-01-29 21:04:13 +0000153int pingseq = 0; /* Ping sequence counter */
154struct timeval firstping;
jjako5da68452003-01-28 16:08:47 +0000155
jjakoa7cd2492003-04-11 09:40:12 +0000156int ipset(struct iphash_t *ipaddr, struct in_addr *addr) {
157 int hash = ippool_hash4(addr) % MAXCONTEXTS;
158 struct iphash_t *h;
159 struct iphash_t *prev = NULL;
160 ipaddr->ipnext = NULL;
161 ipaddr->addr.s_addr = addr->s_addr;
162 for (h = iphash[hash]; h; h = h->ipnext)
163 prev = h;
164 if (!prev)
165 iphash[hash] = ipaddr;
166 else
167 prev->ipnext = ipaddr;
168 return 0;
169}
170
171int ipdel(struct iphash_t *ipaddr) {
172 int hash = ippool_hash4(&ipaddr->addr) % MAXCONTEXTS;
173 struct iphash_t *h;
174 struct iphash_t *prev = NULL;
175 for (h = iphash[hash]; h; h = h->ipnext) {
176 if (h == ipaddr) {
177 if (!prev)
178 iphash[hash] = h->ipnext;
179 else
180 prev->ipnext = h->ipnext;
181 return 0;
182 }
183 prev = h;
184 }
185 return EOF; /* End of linked list and not found */
186}
187
188int ipget(struct iphash_t **ipaddr, struct in_addr *addr) {
189 int hash = ippool_hash4(addr) % MAXCONTEXTS;
190 struct iphash_t *h;
191 for (h = iphash[hash]; h; h = h->ipnext) {
192 if ((h->addr.s_addr == addr->s_addr)) {
193 *ipaddr = h;
194 return 0;
195 }
196 }
197 return EOF; /* End of linked list and not found */
198}
199
200
201/* Used to write process ID to file. Assume someone else will delete */
202void log_pid(char *pidfile) {
203 FILE *file;
204 mode_t oldmask;
205
206 oldmask = umask(022);
207 file = fopen(pidfile, "w");
208 umask(oldmask);
209 if(!file)
210 return;
jjako0141d202004-01-09 15:19:20 +0000211 fprintf(file, "%d\n", (int) getpid());
jjakoa7cd2492003-04-11 09:40:12 +0000212 fclose(file);
213}
214
215
216int process_options(int argc, char **argv) {
217 /* gengeopt declarations */
218 struct gengetopt_args_info args_info;
219
220 struct hostent *host;
Harald Weltef54a1f42010-05-04 11:08:38 +0200221 unsigned int n;
Yann BONNAMY944dce32010-10-29 17:07:44 +0200222 uint16_t i;
223 uint8_t a;
224 uint8_t b;
225 char * tmp;
226 char * pch;
227 char * type;
228 char * mcc;
229 char * mnc;
230 char * lac;
231 int lac_d;
232 char * rest;
233 char *userloc_el[] = {"TYPE","MCC","MNC","LAC","REST"};
234 char *mstz_el[] = {"SIGN","QUARTERS","DST"};
235 int sign ;
236 int nbquarters ;
237 int DST ;
238
jjakoa7cd2492003-04-11 09:40:12 +0000239
240 if (cmdline_parser (argc, argv, &args_info) != 0)
241 return -1;
242 if (args_info.debug_flag) {
jjakoc6762cf2004-04-28 14:52:58 +0000243 if (args_info.remote_arg) printf("remote: %s\n", args_info.remote_arg);
244 if (args_info.listen_arg) printf("listen: %s\n", args_info.listen_arg);
245 if (args_info.conf_arg) printf("conf: %s\n", args_info.conf_arg);
jjakoa7cd2492003-04-11 09:40:12 +0000246 printf("debug: %d\n", args_info.debug_flag);
jjakoc6762cf2004-04-28 14:52:58 +0000247 if (args_info.imsi_arg) printf("imsi: %s\n", args_info.imsi_arg);
jjakoa7cd2492003-04-11 09:40:12 +0000248 printf("qos: %#08x\n", args_info.qos_arg);
Yann BONNAMY11a398f2010-11-18 10:01:21 +0100249 printf("qose1: %#0.16llx\n", args_info.qose1_arg);
250 printf("qose2: %#04x\n", args_info.qose2_arg);
251 printf("qose3: %#06x\n", args_info.qose3_arg);
252 printf("qose4: %#06x\n", args_info.qose4_arg);
jjako7e051d32004-05-27 20:06:36 +0000253 printf("charging: %#04x\n", args_info.charging_arg);
jjakoc6762cf2004-04-28 14:52:58 +0000254 if (args_info.apn_arg) printf("apn: %s\n", args_info.apn_arg);
255 if (args_info.msisdn_arg) printf("msisdn: %s\n", args_info.msisdn_arg);
256 if (args_info.uid_arg) printf("uid: %s\n", args_info.uid_arg);
257 if (args_info.pwd_arg) printf("pwd: %s\n", args_info.pwd_arg);
258 if (args_info.pidfile_arg) printf("pidfile: %s\n", args_info.pidfile_arg);
259 if (args_info.statedir_arg) printf("statedir: %s\n", args_info.statedir_arg);
260 if (args_info.dns_arg) printf("dns: %s\n", args_info.dns_arg);
jjakoa7cd2492003-04-11 09:40:12 +0000261 printf("contexts: %d\n", args_info.contexts_arg);
262 printf("timelimit: %d\n", args_info.timelimit_arg);
263 printf("createif: %d\n", args_info.createif_flag);
jjakoc6762cf2004-04-28 14:52:58 +0000264 if (args_info.ipup_arg) printf("ipup: %s\n", args_info.ipup_arg);
265 if (args_info.ipdown_arg) printf("ipdown: %s\n", args_info.ipdown_arg);
jjakoa7cd2492003-04-11 09:40:12 +0000266 printf("defaultroute: %d\n", args_info.defaultroute_flag);
jjakoc6762cf2004-04-28 14:52:58 +0000267 if (args_info.pinghost_arg) printf("pinghost: %s\n", args_info.pinghost_arg);
jjakoa7cd2492003-04-11 09:40:12 +0000268 printf("pingrate: %d\n", args_info.pingrate_arg);
269 printf("pingsize: %d\n", args_info.pingsize_arg);
270 printf("pingcount: %d\n", args_info.pingcount_arg);
271 printf("pingquiet: %d\n", args_info.pingquiet_flag);
272 }
273
274 /* Try out our new parser */
275
276 if (args_info.conf_arg) {
Harald Welte1b3e5772010-05-04 11:13:56 +0200277 if (cmdline_parser_configfile (args_info.conf_arg, &args_info, 0, 0, 0) != 0)
jjakoa7cd2492003-04-11 09:40:12 +0000278 return -1;
279 if (args_info.debug_flag) {
280 printf("cmdline_parser_configfile\n");
jjakoc6762cf2004-04-28 14:52:58 +0000281 if (args_info.remote_arg) printf("remote: %s\n", args_info.remote_arg);
282 if (args_info.listen_arg) printf("listen: %s\n", args_info.listen_arg);
283 if (args_info.conf_arg) printf("conf: %s\n", args_info.conf_arg);
jjakoa7cd2492003-04-11 09:40:12 +0000284 printf("debug: %d\n", args_info.debug_flag);
jjakoc6762cf2004-04-28 14:52:58 +0000285 if (args_info.imsi_arg) printf("imsi: %s\n", args_info.imsi_arg);
jjakoa7cd2492003-04-11 09:40:12 +0000286 printf("qos: %#08x\n", args_info.qos_arg);
Yann BONNAMY11a398f2010-11-18 10:01:21 +0100287 printf("qose1: %#0.16llx\n", args_info.qose1_arg);
288 printf("qose2: %#04x\n", args_info.qose2_arg);
289 printf("qose3: %#06x\n", args_info.qose3_arg);
290 printf("qose4: %#06x\n", args_info.qose4_arg);
jjako7e051d32004-05-27 20:06:36 +0000291 printf("charging: %#04x\n", args_info.charging_arg);
jjakoc6762cf2004-04-28 14:52:58 +0000292 if (args_info.apn_arg) printf("apn: %s\n", args_info.apn_arg);
293 if (args_info.msisdn_arg) printf("msisdn: %s\n", args_info.msisdn_arg);
294 if (args_info.uid_arg) printf("uid: %s\n", args_info.uid_arg);
295 if (args_info.pwd_arg) printf("pwd: %s\n", args_info.pwd_arg);
296 if (args_info.pidfile_arg) printf("pidfile: %s\n", args_info.pidfile_arg);
297 if (args_info.statedir_arg) printf("statedir: %s\n", args_info.statedir_arg);
298 if (args_info.dns_arg) printf("dns: %s\n", args_info.dns_arg);
jjakoa7cd2492003-04-11 09:40:12 +0000299 printf("contexts: %d\n", args_info.contexts_arg);
300 printf("timelimit: %d\n", args_info.timelimit_arg);
301 printf("createif: %d\n", args_info.createif_flag);
jjakoc6762cf2004-04-28 14:52:58 +0000302 if (args_info.ipup_arg) printf("ipup: %s\n", args_info.ipup_arg);
303 if (args_info.ipdown_arg) printf("ipdown: %s\n", args_info.ipdown_arg);
jjakoa7cd2492003-04-11 09:40:12 +0000304 printf("defaultroute: %d\n", args_info.defaultroute_flag);
jjakoc6762cf2004-04-28 14:52:58 +0000305 if (args_info.pinghost_arg) printf("pinghost: %s\n", args_info.pinghost_arg);
jjakoa7cd2492003-04-11 09:40:12 +0000306 printf("pingrate: %d\n", args_info.pingrate_arg);
307 printf("pingsize: %d\n", args_info.pingsize_arg);
308 printf("pingcount: %d\n", args_info.pingcount_arg);
309 printf("pingquiet: %d\n", args_info.pingquiet_flag);
310 }
311 }
312
313 /* Handle each option */
314
315 /* foreground */
jjakoe607f742003-07-06 21:21:30 +0000316 /* If fg flag not given run as a daemon */
317 /* Do not allow sgsnemu to run as deamon
jjakoa7cd2492003-04-11 09:40:12 +0000318 if (!args_info.fg_flag)
319 {
320 closelog();
jjakoa7cd2492003-04-11 09:40:12 +0000321 freopen("/dev/null", "w", stdout);
322 freopen("/dev/null", "w", stderr);
323 freopen("/dev/null", "r", stdin);
324 daemon(0, 0);
jjakoa7cd2492003-04-11 09:40:12 +0000325 openlog(PACKAGE, LOG_PID, LOG_DAEMON);
jjakoe607f742003-07-06 21:21:30 +0000326 } */
jjakoa7cd2492003-04-11 09:40:12 +0000327
328 /* debug */
329 options.debug = args_info.debug_flag;
330
331 /* pidfile */
332 /* This has to be done after we have our final pid */
333 if (args_info.pidfile_arg) {
334 log_pid(args_info.pidfile_arg);
335 }
336
337 /* dns */
338 /* If no dns option is given use system default */
339 /* Do hostname lookup to translate hostname to IP address */
340 printf("\n");
341 if (args_info.dns_arg) {
342 if (!(host = gethostbyname(args_info.dns_arg))) {
343 sys_err(LOG_ERR, __FILE__, __LINE__, 0,
344 "Invalid DNS address: %s!", args_info.dns_arg);
345 return -1;
346 }
347 else {
348 memcpy(&options.dns.s_addr, host->h_addr, host->h_length);
349 _res.nscount = 1;
350 _res.nsaddr_list[0].sin_addr = options.dns;
351 printf("Using DNS server: %s (%s)\n",
352 args_info.dns_arg, inet_ntoa(options.dns));
353 }
354 }
355 else {
356 options.dns.s_addr= 0;
357 printf("Using default DNS server\n");
358 }
359
360 /* listen */
361 /* If no listen option is specified listen to any local port */
362 /* Do hostname lookup to translate hostname to IP address */
363 if (args_info.listen_arg) {
364 if (!(host = gethostbyname(args_info.listen_arg))) {
365 sys_err(LOG_ERR, __FILE__, __LINE__, 0,
366 "Invalid listening address: %s!", args_info.listen_arg);
367 return -1;
368 }
369 else {
370 memcpy(&options.listen.s_addr, host->h_addr, host->h_length);
371 printf("Local IP address is: %s (%s)\n",
372 args_info.listen_arg, inet_ntoa(options.listen));
373 }
374 }
375 else {
376 sys_err(LOG_ERR, __FILE__, __LINE__, 0,
377 "Listening address must be specified: %s!", args_info.listen_arg);
378 return -1;
379 }
380
381
382 /* remote */
383 /* If no remote option is specified terminate */
384 /* Do hostname lookup to translate hostname to IP address */
385 if (args_info.remote_arg) {
386 if (!(host = gethostbyname(args_info.remote_arg))) {
387 sys_err(LOG_ERR, __FILE__, __LINE__, 0,
388 "Invalid remote address: %s!", args_info.remote_arg);
389 return -1;
390 }
391 else {
392 memcpy(&options.remote.s_addr, host->h_addr, host->h_length);
393 printf("Remote IP address is: %s (%s)\n",
394 args_info.remote_arg, inet_ntoa(options.remote));
395 }
396 }
397 else {
398 sys_err(LOG_ERR, __FILE__, __LINE__, 0,
399 "No remote address given!");
400 return -1;
401 }
402
403
404 /* imsi */
405 if (strlen(args_info.imsi_arg)!=15) {
406 printf("Invalid IMSI\n");
407 return -1;
408 }
jjako06e9f122004-01-19 18:37:58 +0000409
jjakod48c5ff2004-01-26 22:25:40 +0000410 options.imsi = 0xf000000000000000ull;
jjako06e9f122004-01-19 18:37:58 +0000411 options.imsi |= ((uint64_t) (args_info.imsi_arg[ 0]-48));
jjakoa7cd2492003-04-11 09:40:12 +0000412 options.imsi |= ((uint64_t) (args_info.imsi_arg[ 1]-48)) << 4;
413 options.imsi |= ((uint64_t) (args_info.imsi_arg[ 2]-48)) << 8;
414 options.imsi |= ((uint64_t) (args_info.imsi_arg[ 3]-48)) << 12;
415 options.imsi |= ((uint64_t) (args_info.imsi_arg[ 4]-48)) << 16;
416 options.imsi |= ((uint64_t) (args_info.imsi_arg[ 5]-48)) << 20;
417 options.imsi |= ((uint64_t) (args_info.imsi_arg[ 6]-48)) << 24;
418 options.imsi |= ((uint64_t) (args_info.imsi_arg[ 7]-48)) << 28;
419 options.imsi |= ((uint64_t) (args_info.imsi_arg[ 8]-48)) << 32;
420 options.imsi |= ((uint64_t) (args_info.imsi_arg[ 9]-48)) << 36;
421 options.imsi |= ((uint64_t) (args_info.imsi_arg[10]-48)) << 40;
422 options.imsi |= ((uint64_t) (args_info.imsi_arg[11]-48)) << 44;
423 options.imsi |= ((uint64_t) (args_info.imsi_arg[12]-48)) << 48;
424 options.imsi |= ((uint64_t) (args_info.imsi_arg[13]-48)) << 52;
425 options.imsi |= ((uint64_t) (args_info.imsi_arg[14]-48)) << 56;
426
jjako193e8b12003-11-10 12:31:41 +0000427 printf("IMSI is: %s (%#08llx)\n",
428 args_info.imsi_arg, options.imsi);
429
430
431 /* nsapi */
432 if ((args_info.nsapi_arg > 15) ||
433 (args_info.nsapi_arg < 0)) {
434 printf("Invalid NSAPI\n");
435 return -1;
436 }
437 options.nsapi = args_info.nsapi_arg;
438 printf("Using NSAPI: %d\n", args_info.nsapi_arg);
jjakoa7cd2492003-04-11 09:40:12 +0000439
440
441 /* qos */
Yann BONNAMY11a398f2010-11-18 10:01:21 +0100442 options.qos.l = 4;
443 options.qos.v[3] = (args_info.qos_arg) & 0xff;
444 options.qos.v[2] = ((args_info.qos_arg) >> 8)& 0xff;
445 options.qos.v[1] = ((args_info.qos_arg) >> 16) & 0xff;
446 options.qos.v[0] = ((args_info.qos_arg) >> 24) & 0xff;
447 /* Extensions according to 3GPP TS 24.008 */
448 if (args_info.qose1_given == 1 ) {
449 options.qos.l = 12;
450 options.qos.v[11] = (args_info.qose1_arg) & 0xff;
451 options.qos.v[10] = ((args_info.qose1_arg) >> 8)& 0xff;
452 options.qos.v[9] = ((args_info.qose1_arg) >> 16)& 0xff;
453 options.qos.v[8] = ((args_info.qose1_arg) >> 24)& 0xff;
454 options.qos.v[7] = ((args_info.qose1_arg) >> 32)& 0xff;
455 options.qos.v[6] = ((args_info.qose1_arg) >> 40) & 0xff;
456 options.qos.v[5] = ((args_info.qose1_arg) >> 48) & 0xff;
457 options.qos.v[4] = ((args_info.qose1_arg) >> 56) & 0xff;
458 if (args_info.qose2_given == 1 ) {
459 options.qos.l = 13;
460 options.qos.v[12] = (args_info.qose2_arg) & 0xff;
461 if (args_info.qose3_given == 1 ) {
462 options.qos.l = 15;
463 options.qos.v[14] = (args_info.qose3_arg) & 0xff;
464 options.qos.v[13] = ((args_info.qose3_arg) >> 8)& 0xff;
465 if (args_info.qose4_given == 1 ) {
466 options.qos.l = 17;
467 options.qos.v[16] = (args_info.qose4_arg) & 0xff;
468 options.qos.v[15] = ((args_info.qose4_arg) >> 8)& 0xff;
469 }
470 }
471 }
472 }
473
jjako7e051d32004-05-27 20:06:36 +0000474 /* charging */
475 options.cch = args_info.charging_arg;
jjakoa7cd2492003-04-11 09:40:12 +0000476
477 /* contexts */
478 if (args_info.contexts_arg > MAXCONTEXTS) {
479 printf("Contexts has to be less than %d\n", MAXCONTEXTS);
480 return -1;
481 }
482 options.contexts = args_info.contexts_arg;
483
484 /* Timelimit */
485 options.timelimit = args_info.timelimit_arg;
486
jjako193e8b12003-11-10 12:31:41 +0000487 /* gtpversion */
488 if ((args_info.gtpversion_arg > 1) ||
489 (args_info.gtpversion_arg < 0)) {
490 printf("Invalid GTP version\n");
491 return -1;
492 }
493 options.gtpversion = args_info.gtpversion_arg;
494 printf("Using GTP version: %d\n", args_info.gtpversion_arg);
495
496
jjakoa7cd2492003-04-11 09:40:12 +0000497 /* apn */
498 if (strlen(args_info.apn_arg) > (sizeof(options.apn.v)-1)) {
499 printf("Invalid APN\n");
500 return -1;
501 }
jjako9f26b952005-03-14 22:03:05 +0000502 options.apn.l = strlen(args_info.apn_arg);
Emmanuel Bretelle2a7cad52010-09-07 15:56:02 +0200503 strncpy((char *)options.apn.v, args_info.apn_arg, sizeof(options.apn.v));
jjako9f26b952005-03-14 22:03:05 +0000504 options.apn.v[sizeof(options.apn.v)-1] = 0;
jjakoa7cd2492003-04-11 09:40:12 +0000505 printf("Using APN: %s\n", args_info.apn_arg);
jjako1a51df72004-07-20 08:30:21 +0000506
507
508 /* selmode */
509 options.selmode = args_info.selmode_arg;
510 printf("Using selection mode: %d\n", args_info.selmode_arg);
511
Yann BONNAMY944dce32010-10-29 17:07:44 +0200512 /* rattype */
513 if (args_info.rattype_given == 1 ) {
514 options.rattype_given = 1 ;
515 options.rattype.l = strlen(args_info.rattype_arg) ;
516 options.rattype.v[0] = atoi(args_info.rattype_arg) ;
517 printf("Using RAT Type: %s\n", args_info.rattype_arg);
518 }
519
520 /* userloc */
521 if (args_info.userloc_given == 1 ) {
522 printf("Using User Location Information: %s\n", args_info.userloc_arg);
523 tmp = args_info.userloc_arg ;
524 n=0;
525 pch = strtok (tmp,".");
526 while (pch != NULL) {
527 userloc_el[n] = pch ;
528 pch = strtok (NULL, ".");
529 n++;
530 }
531
532 options.userloc_given = 1 ;
533 options.userloc.l = 8 ;
534
535 /* 3GPP Geographic Location Type t0 / t1 / t2 */
536 type = userloc_el[0];
537 printf("->type : %c\n", type[0]);
538 if ( (strlen(type)!=1) || (!isdigit(type[0])) ) {
539 printf("Invalid type \n");
540 return -1;
541 }
542 /* options.userloc.v[0] = 0x00 */
543 options.userloc.v[0] = type[0] - 48;
544
545 /* MCC */
546 mcc = userloc_el[1] ;
547 printf("->mcc : %s\n", mcc);
548 if (strlen(mcc)!=3) {
549 printf("Invalid MCC lenght\n");
550 return -1;
551 }
552
553 /* MNC */
554 mnc = userloc_el[2] ;
555 printf("->mnc : %s\n", mnc);
556
557 /* octet 5 - MCC Digit 2 - MCC Digit 1 */
558 /* options.userloc.v[1] = 0x52 */
559 a = (uint8_t) (mcc[0] - 48);
560 b = (uint8_t) (mcc[1] - 48);
561 options.userloc.v[1] = 16*b+a ;
562
563 /* octet 6 - MNC Digit 3 - MCC Digit 3 */
564 /* options.userloc.v[2] = 0xf0 */
565 a = (uint8_t) (mcc[2] - 48);
566
567 if ( (strlen(mnc) > 3) || (strlen(mnc) < 2)) {
568 printf("Invalid MNC lenght\n");
569 return -1;
570 }
571 if (strlen(mnc)==2) {
572 b = 15 ;
573 }
574 if (strlen(mnc)==3) {
575 b = (uint8_t) (mnc[2] - 48);
576 }
577 options.userloc.v[2] = 16*b+a ;
578
579 /* octet 7 - MNC Digit 2 - MNC Digit 1 */
580 /* options.userloc.v[3] = 0x99*/
581 a = (uint8_t) (mnc[0]- 48);
582 b = (uint8_t) (mnc[1]- 48);
583 options.userloc.v[3] = 16*b+a ;
584
585 /* LAC */
586 lac = userloc_el[3] ;
587 /*options.userloc.v[4] = 0x12 ; */
588 /*options.userloc.v[5] = 0x10 ; */
589 printf("->LAC: %s\n", lac);
590 lac_d = atoi(lac);
591 if (lac_d>65535 || lac_d<1) {
592 printf("Invalid LAC\n");
593 return -1;
594 }
595 i = lac_d >> 8 ;
596 options.userloc.v[4] = i; /* octet 8 - LAC */
597 options.userloc.v[5] = lac_d; /* octet 9 - LAC */
598
599 /* CI/SAC/RAC */
600 rest = userloc_el[4] ;
601 printf("->CI/SAC/RAC : %s\n", rest);
602 lac_d = atoi(rest);
603 if (lac_d>65535 || lac_d<1) {
604 printf("Invalid CI/SAC/RAC\n");
605 return -1;
606 }
607 /*options.userloc.v[6] = 0x04 ; */
608 /*options.userloc.v[7] = 0xb7 ; */
609 i = lac_d >> 8 ;
610 options.userloc.v[6] = i; /* octet 10 - t0,CI / t1,SAC / t2,RAC */
611 options.userloc.v[7] = lac_d; /* octet 11 - t0,CI / t1,SAC / t2,RAC */
612 }
613 /* mstz */
614 if (args_info.mstz_given == 1 ) {
615 options.mstz_given = 1 ;
616 options.mstz.l = 2 ;
617
618 printf("Using MS Time Zone: %s\n", args_info.mstz_arg);
619 tmp = args_info.mstz_arg ;
620 n=0;
621 pch = strtok (tmp,".");
622 while (pch != NULL) {
623 mstz_el[n] = pch ;
624 pch = strtok (NULL, ".");
625 n++;
626 }
627
628 /* sign */
629 sign = atoi(mstz_el[0]) ;
630 printf("->Sign (0=+ / 1=-): %d\n", sign);
631 if ( sign!=0 && sign!=1 ) {
632 printf("Invalid Sign \n");
633 return -1;
634 }
635 /* nbquarters */
636 nbquarters = atoi(mstz_el[1]) ;
637 printf("->Number of Quarters of an Hour : %d\n", nbquarters);
638 if ( nbquarters<0 || nbquarters>79 ) {
639 printf("Invalid Number of Quarters \n");
640 return -1;
641 }
642 /* DST */
643 DST = atoi(mstz_el[2]) ;
644 printf("->Daylight Saving Time Adjustment : %d\n", DST);
645 if ( DST<0 || DST>3 ) {
646 printf("Invalid DST Adjustment \n");
647 return -1;
648 }
649 /* 12345678
650 bits 123 = unit of # of quarters of an hour
651 bits 678 = # of quarters of an hour / 10
652 bit 5 = sign
653 */
654 i= nbquarters % 10 ;
655 i = i << 4 ;
656 i = i + nbquarters / 10 + 8 * sign;
657 /* options.mstz.v[0] = 0x69 ; */
658 /* options.mstz.v[1] = 0x01 ; */
659 options.mstz.v[0] = i ;
660 options.mstz.v[1] = DST ;
661 n = (i & 0x08) ? '-' : '+';
662 printf("->Human Readable MS Time Zone : GMT %c %d hours %d minutes\n", n , nbquarters / 4, nbquarters % 4 * 15);
663 }
664
665 /* imeisv */
666 if (args_info.imeisv_given == 1 ) {
667 options.imeisv_given = 1 ;
668 if (strlen(args_info.imeisv_arg)!=16) {
669 printf("Invalid IMEI(SV)\n");
670 return -1;
671 }
672 options.imeisv.l = 8 ;
673 for(n=0; n<8; n++) {
674 a = (uint8_t) (args_info.imeisv_arg [2*n] - 48) ;
675 b = (uint8_t) (args_info.imeisv_arg [2*n + 1] - 48) ;
676 options.imeisv.v[n] = 16*b+a ;
677 }
678 printf("Using IMEI(SV): %s\n", args_info.imeisv_arg);
679 }
jjakoa7cd2492003-04-11 09:40:12 +0000680
681 /* msisdn */
682 if (strlen(args_info.msisdn_arg)>(sizeof(options.msisdn.v)-1)) {
683 printf("Invalid MSISDN\n");
684 return -1;
685 }
686 options.msisdn.l = 1;
687 options.msisdn.v[0] = 0x91; /* International format */
688 for(n=0; n<strlen(args_info.msisdn_arg); n++) {
689 if ((n%2) == 0) {
690 options.msisdn.v[((int)n/2)+1] = args_info.msisdn_arg[n] - 48 + 0xf0;
691 options.msisdn.l += 1;
692 }
693 else {
694 options.msisdn.v[((int)n/2)+1] =
695 (options.msisdn.v[((int)n/2)+1] & 0x0f) +
696 (args_info.msisdn_arg[n] - 48) * 16;
697 }
698 }
699 printf("Using MSISDN: %s\n", args_info.msisdn_arg);
700
701 /* UID and PWD */
702 /* Might need to also insert stuff like DNS etc. */
703 if ((strlen(args_info.uid_arg) + strlen(args_info.pwd_arg) + 10)>
704 (sizeof(options.pco.v)-1)) {
705 printf("invalid UID and PWD\n");
706 return -1;
707 }
708 options.pco.l = strlen(args_info.uid_arg) + strlen(args_info.pwd_arg) + 10;
709 options.pco.v[0] = 0x80; /* PPP */
710 options.pco.v[1] = 0xc0; /* PAP */
711 options.pco.v[2] = 0x23;
jjakob62c3dd2004-05-27 18:51:55 +0000712 options.pco.v[3] = strlen(args_info.uid_arg) + strlen(args_info.pwd_arg) + 6;
jjakoa7cd2492003-04-11 09:40:12 +0000713 options.pco.v[4] = 0x01; /* Authenticate request */
714 options.pco.v[5] = 0x01;
715 options.pco.v[6] = 0x00; /* MSB of length */
716 options.pco.v[7] = strlen(args_info.uid_arg) + strlen(args_info.pwd_arg) + 6;
717 options.pco.v[8] = strlen(args_info.uid_arg);
718 memcpy(&options.pco.v[9], args_info.uid_arg, strlen(args_info.uid_arg));
719 options.pco.v[9+strlen(args_info.uid_arg)] = strlen(args_info.pwd_arg);
720 memcpy(&options.pco.v[10+strlen(args_info.uid_arg)],
721 args_info.pwd_arg, strlen(args_info.pwd_arg));
722
723 /* createif */
724 options.createif = args_info.createif_flag;
725
jjako193e8b12003-11-10 12:31:41 +0000726 /* net */
727 /* Store net as in_addr net and mask */
728 if (args_info.net_arg) {
729 if(ippool_aton(&options.net, &options.mask, args_info.net_arg, 0)) {
730 sys_err(LOG_ERR, __FILE__, __LINE__, 0,
731 "Invalid network address: %s!", args_info.net_arg);
732 exit(1);
733 }
jjakoc6762cf2004-04-28 14:52:58 +0000734
735#if defined (__sun__)
736 options.netaddr.s_addr = htonl(ntohl(options.net.s_addr) + 1);
737 options.destaddr.s_addr = htonl(ntohl(options.net.s_addr) + 1);
738#else
739 options.netaddr.s_addr = options.net.s_addr;
740 options.destaddr.s_addr = options.net.s_addr;
741#endif
742
jjako193e8b12003-11-10 12:31:41 +0000743 }
744 else {
745 options.net.s_addr = 0;
746 options.mask.s_addr = 0;
jjakoc6762cf2004-04-28 14:52:58 +0000747 options.netaddr.s_addr = 0;
748 options.destaddr.s_addr = 0;
jjako193e8b12003-11-10 12:31:41 +0000749 }
750
jjakoa7cd2492003-04-11 09:40:12 +0000751 /* ipup */
752 options.ipup = args_info.ipup_arg;
753
754 /* ipdown */
755 options.ipdown = args_info.ipdown_arg;
756
757 /* statedir */
758 options.statedir = args_info.statedir_arg;
759
760 /* defaultroute */
761 options.defaultroute = args_info.defaultroute_flag;
762
763
jjako76032b92004-01-14 06:22:08 +0000764 /* pinghost */
jjakoa7cd2492003-04-11 09:40:12 +0000765 /* Store ping host as in_addr */
766 if (args_info.pinghost_arg) {
jjako76032b92004-01-14 06:22:08 +0000767 if (!(host = gethostbyname(args_info.pinghost_arg))) {
jjakoa7cd2492003-04-11 09:40:12 +0000768 sys_err(LOG_ERR, __FILE__, __LINE__, 0,
769 "Invalid ping host: %s!", args_info.pinghost_arg);
770 return -1;
771 }
jjako76032b92004-01-14 06:22:08 +0000772 else {
773 memcpy(&options.pinghost.s_addr, host->h_addr, host->h_length);
774 printf("Using ping host: %s (%s)\n",
775 args_info.pinghost_arg, inet_ntoa(options.pinghost));
776 }
jjakoa7cd2492003-04-11 09:40:12 +0000777 }
778
779 /* Other ping parameters */
780 options.pingrate = args_info.pingrate_arg;
781 options.pingsize = args_info.pingsize_arg;
782 options.pingcount = args_info.pingcount_arg;
783 options.pingquiet = args_info.pingquiet_flag;
784
785 return 0;
786
787}
788
jjako5da68452003-01-28 16:08:47 +0000789
790int encaps_printf(struct pdp_t *pdp, void *pack, unsigned len) {
Harald Weltef54a1f42010-05-04 11:08:38 +0200791 unsigned int i;
jjako52c24142002-12-16 13:33:51 +0000792 printf("The packet looks like this:\n");
793 for( i=0; i<len; i++) {
jjako5da68452003-01-28 16:08:47 +0000794 printf("%02x ", (unsigned char)*(char *)(pack+i));
jjako52c24142002-12-16 13:33:51 +0000795 if (!((i+1)%16)) printf("\n");
796 };
jjako5da68452003-01-28 16:08:47 +0000797 printf("\n");
798 return 0;
jjako52c24142002-12-16 13:33:51 +0000799}
800
jjako5da68452003-01-28 16:08:47 +0000801char * print_ipprot(int t) {
802 switch (t) {
803 case 1: return "ICMP";
804 case 6: return "TCP";
805 case 17: return "UDP";
806 default: return "Unknown";
807 };
808}
809
810
811char * print_icmptype(int t) {
812 static char *ttab[] = {
813 "Echo Reply",
814 "ICMP 1",
815 "ICMP 2",
816 "Dest Unreachable",
817 "Source Quench",
818 "Redirect",
819 "ICMP 6",
820 "ICMP 7",
821 "Echo",
822 "ICMP 9",
823 "ICMP 10",
824 "Time Exceeded",
825 "Parameter Problem",
826 "Timestamp",
827 "Timestamp Reply",
828 "Info Request",
829 "Info Reply"
830 };
831 if( t < 0 || t > 16 )
832 return("OUT-OF-RANGE");
833 return(ttab[t]);
834}
835
jjako193e8b12003-11-10 12:31:41 +0000836int msisdn_add(struct ul16_t *src, struct ul16_t *dst, int add) {
Harald Weltef54a1f42010-05-04 11:08:38 +0200837 unsigned int n;
jjako193e8b12003-11-10 12:31:41 +0000838 uint64_t i64 = 0;
839 uint8_t msa[sizeof(i64) * 3]; /* Allocate 3 digits per octet (0..255) */
Harald Weltef54a1f42010-05-04 11:08:38 +0200840 unsigned int msalen = 0;
jjako193e8b12003-11-10 12:31:41 +0000841
842 /* Convert to uint64_t from ul16_t format (most significant digit first) */
843 /* ul16_t format always starts with 0x91 to indicate international format */
844 /* In ul16_t format 0x0f/0xf0 indicates that digit is not used */
845 for (n=0; n< src->l; n++) {
846 if ((src->v[n] & 0x0f) != 0x0f) {
847 i64 *= 10;
848 i64 += src->v[n] & 0x0f;
849 }
850 if ((src->v[n] & 0xf0) != 0xf0) {
851 i64 *= 10;
852 i64 += (src->v[n] & 0xf0) >> 4;
853 }
854 }
855
856 i64 += add;
857
858 /* Generate array with least significant digit in first octet */
859 while (i64) {
860 msa[msalen++] = i64 % 10;
861 i64 = i64 / 10;
862 }
863
864 /* Convert back to ul16_t format */
865 for(n=0; n<msalen; n++) {
866 if ((n%2) == 0) {
867 dst->v[((int)n/2)] = msa[msalen-n-1] + 0xf0;
868 dst->l += 1;
869 }
870 else {
871 dst->v[((int)n/2)] = (dst->v[((int)n/2)] & 0x0f) +
872 msa[msalen-n-1] * 16;
873 }
874 }
875
876 return 0;
877
878}
879
880int imsi_add(uint64_t src, uint64_t *dst, int add) {
881 /* TODO: big endian / small endian ??? */
882 uint64_t i64 = 0;
883
884 /* Convert from uint64_t bcd to uint64_t integer format */
885 /* The resulting integer format is multiplied by 10 */
886 while (src) {
887 if ((src & 0x0f) != 0x0f) {
888 i64 *= 10;
889 i64 += (src & 0x0f);
890 }
891 if ((src & 0xf0) != 0xf0) {
892 i64 *= 10;
893 i64 += (src & 0xf0) >> 4;
894 }
895 src = src >> 8;
896 }
897
898 i64 += add * 10;
899
900 *dst = 0;
901 while (i64) {
902 *dst = *dst << 4;
903 *dst += (i64 % 10);
904 i64 = i64 / 10;
905 }
906
jjakod48c5ff2004-01-26 22:25:40 +0000907 *dst |= 0xf000000000000000ull;
jjako06e9f122004-01-19 18:37:58 +0000908
jjako193e8b12003-11-10 12:31:41 +0000909 return 0;
910
911}
912
jjakoafb2a972003-01-29 21:04:13 +0000913/* Calculate time left until we have to send off next ping packet */
914int ping_timeout(struct timeval *tp) {
915 struct timezone tz;
916 struct timeval tv;
917 int diff;
jjakoa7cd2492003-04-11 09:40:12 +0000918 if ((options.pinghost.s_addr) && (2 == state) &&
919 ((pingseq < options.pingcount) || (options.pingcount == 0))) {
jjakoafb2a972003-01-29 21:04:13 +0000920 gettimeofday(&tv, &tz);
jjakoa7cd2492003-04-11 09:40:12 +0000921 diff = 1000000 / options.pingrate * pingseq -
jjakoafb2a972003-01-29 21:04:13 +0000922 1000000 * (tv.tv_sec - firstping.tv_sec) -
923 (tv.tv_usec - firstping.tv_usec); /* Microseconds safe up to 500 sec */
924 tp->tv_sec = 0;
925 if (diff > 0)
926 tp->tv_usec = diff;
jjakoa7cd2492003-04-11 09:40:12 +0000927 else {
jjakoafb2a972003-01-29 21:04:13 +0000928 /* For some reason we get packet loss if set to zero */
jjakoa7cd2492003-04-11 09:40:12 +0000929 tp->tv_usec = 100000 / options.pingrate; /* 10 times pingrate */
930 tp->tv_usec = 0;
931 }
jjakoafb2a972003-01-29 21:04:13 +0000932 }
933 return 0;
934}
935
jjako5da68452003-01-28 16:08:47 +0000936/* Print out statistics when at the end of ping sequence */
937int ping_finish()
938{
jjakoafb2a972003-01-29 21:04:13 +0000939 struct timezone tz;
940 struct timeval tv;
941 int elapsed;
942 gettimeofday(&tv, &tz);
943 elapsed = 1000000 * (tv.tv_sec - firstping.tv_sec) +
944 (tv.tv_usec - firstping.tv_usec); /* Microseconds */
jjako5da68452003-01-28 16:08:47 +0000945 printf("\n");
jjakoa7cd2492003-04-11 09:40:12 +0000946 printf("\n----%s PING Statistics----\n", inet_ntoa(options.pinghost));
jjakoafb2a972003-01-29 21:04:13 +0000947 printf("%d packets transmitted in %.3f seconds, ", ntransmitted,
948 elapsed / 1000000.0);
jjako5da68452003-01-28 16:08:47 +0000949 printf("%d packets received, ", nreceived );
950 if (ntransmitted) {
951 if( nreceived > ntransmitted)
952 printf("-- somebody's printing up packets!");
953 else
954 printf("%d%% packet loss",
955 (int) (((ntransmitted-nreceived)*100) /
956 ntransmitted));
957 }
958 printf("\n");
jjakoa7cd2492003-04-11 09:40:12 +0000959 if (options.debug) printf("%d packets received in total\n", ntreceived );
jjako5da68452003-01-28 16:08:47 +0000960 if (nreceived && tsum)
961 printf("round-trip (ms) min/avg/max = %.3f/%.3f/%.3f\n\n",
962 tmin/1000.0,
963 tsum/1000.0/nreceived,
964 tmax/1000.0 );
jjakoafb2a972003-01-29 21:04:13 +0000965 printf("%d packets transmitted \n", ntreceived );
966
jjako5da68452003-01-28 16:08:47 +0000967 ntransmitted = 0;
968 return 0;
969}
970
971/* Handle a received ping packet. Print out line and update statistics. */
972int encaps_ping(struct pdp_t *pdp, void *pack, unsigned len) {
973 struct timezone tz;
974 struct timeval tv;
975 struct timeval *tp;
976 struct ip_ping *pingpack = pack;
977 struct in_addr src;
978 int triptime;
979
980 src.s_addr = pingpack->src;
981
982 gettimeofday(&tv, &tz);
jjakoa7cd2492003-04-11 09:40:12 +0000983 if (options.debug) printf("%d.%6d ", (int) tv.tv_sec, (int) tv.tv_usec);
jjako5da68452003-01-28 16:08:47 +0000984
985 if (len < CREATEPING_IP + CREATEPING_ICMP) {
986 printf("packet too short (%d bytes) from %s\n", len,
987 inet_ntoa(src));
988 return 0;
989 }
990
991 ntreceived++;
992 if (pingpack->protocol != 1) {
jjakoa7cd2492003-04-11 09:40:12 +0000993 if (!options.pingquiet) printf("%d bytes from %s: ip_protocol=%d (%s)\n",
jjako5da68452003-01-28 16:08:47 +0000994 len, inet_ntoa(src), pingpack->protocol,
995 print_ipprot(pingpack->protocol));
996 return 0;
997 }
998
999 if (pingpack->type != 0) {
jjakoa7cd2492003-04-11 09:40:12 +00001000 if (!options.pingquiet) printf("%d bytes from %s: icmp_type=%d (%s) icmp_code=%d\n",
jjako5da68452003-01-28 16:08:47 +00001001 len, inet_ntoa(src), pingpack->type,
1002 print_icmptype(pingpack->type), pingpack->code);
1003 return 0;
1004 }
1005
1006 nreceived++;
jjakoa7cd2492003-04-11 09:40:12 +00001007 if (!options.pingquiet) printf("%d bytes from %s: icmp_seq=%d", len,
jjako5da68452003-01-28 16:08:47 +00001008 inet_ntoa(src), ntohs(pingpack->seq));
1009
1010 if (len >= sizeof(struct timeval) + CREATEPING_IP + CREATEPING_ICMP) {
1011 gettimeofday(&tv, &tz);
1012 tp = (struct timeval *) pingpack->data;
1013 if( (tv.tv_usec -= tp->tv_usec) < 0 ) {
1014 tv.tv_sec--;
1015 tv.tv_usec += 1000000;
1016 }
1017 tv.tv_sec -= tp->tv_sec;
1018
1019 triptime = tv.tv_sec*1000000+(tv.tv_usec);
1020 tsum += triptime;
1021 if( triptime < tmin )
1022 tmin = triptime;
1023 if( triptime > tmax )
1024 tmax = triptime;
1025
jjakoa7cd2492003-04-11 09:40:12 +00001026 if (!options.pingquiet) printf(" time=%.3f ms\n", triptime/1000.0);
jjako5da68452003-01-28 16:08:47 +00001027
1028 }
1029 else
jjakoa7cd2492003-04-11 09:40:12 +00001030 if (!options.pingquiet) printf("\n");
jjako5da68452003-01-28 16:08:47 +00001031 return 0;
1032}
1033
1034/* Create a new ping packet and send it off to peer. */
1035int create_ping(void *gsn, struct pdp_t *pdp,
Harald Weltef54a1f42010-05-04 11:08:38 +02001036 struct in_addr *dst, int seq, unsigned int datasize) {
jjako5da68452003-01-28 16:08:47 +00001037
1038 struct ip_ping pack;
jjako0141d202004-01-09 15:19:20 +00001039 uint16_t *p = (uint16_t *) &pack;
1040 uint8_t *p8 = (uint8_t *) &pack;
jjako5da68452003-01-28 16:08:47 +00001041 struct in_addr src;
Harald Weltef54a1f42010-05-04 11:08:38 +02001042 unsigned int n;
jjako5da68452003-01-28 16:08:47 +00001043 long int sum = 0;
1044 int count = 0;
1045
1046 struct timezone tz;
1047 struct timeval *tp = (struct timeval *) &p8[CREATEPING_IP + CREATEPING_ICMP];
1048
1049 if (datasize > CREATEPING_MAX) {
jjakoa7cd2492003-04-11 09:40:12 +00001050 sys_err(LOG_ERR, __FILE__, __LINE__, 0,
1051 "Ping size to large: %d!", datasize);
1052 return -1;
jjako5da68452003-01-28 16:08:47 +00001053 }
1054
1055 memcpy(&src, &(pdp->eua.v[2]), 4); /* Copy a 4 byte address */
1056
1057 pack.ipver = 0x45;
1058 pack.tos = 0x00;
1059 pack.length = htons(CREATEPING_IP + CREATEPING_ICMP + datasize);
1060 pack.fragid = 0x0000;
1061 pack.offset = 0x0040;
1062 pack.ttl = 0x40;
1063 pack.protocol = 0x01;
1064 pack.ipcheck = 0x0000;
1065 pack.src = src.s_addr;
1066 pack.dst = dst->s_addr;
1067 pack.type = 0x08;
1068 pack.code = 0x00;
1069 pack.checksum = 0x0000;
1070 pack.ident = 0x0000;
1071 pack.seq = htons(seq);
1072
1073 /* Generate ICMP payload */
jjako0141d202004-01-09 15:19:20 +00001074 p8 = (uint8_t *) &pack + CREATEPING_IP + CREATEPING_ICMP;
jjako5da68452003-01-28 16:08:47 +00001075 for (n=0; n<(datasize); n++) p8[n] = n;
1076
1077 if (datasize >= sizeof(struct timeval))
1078 gettimeofday(tp, &tz);
1079
1080 /* Calculate IP header checksum */
jjako0141d202004-01-09 15:19:20 +00001081 p = (uint16_t *) &pack;
jjako5da68452003-01-28 16:08:47 +00001082 count = CREATEPING_IP;
1083 sum = 0;
1084 while (count>1) {
1085 sum += *p++;
1086 count -= 2;
1087 }
1088 while (sum>>16)
1089 sum = (sum & 0xffff) + (sum >> 16);
1090 pack.ipcheck = ~sum;
1091
1092
1093 /* Calculate ICMP checksum */
1094 count = CREATEPING_ICMP + datasize; /* Length of ICMP message */
1095 sum = 0;
jjako0141d202004-01-09 15:19:20 +00001096 p = (uint16_t *) &pack;
jjako5da68452003-01-28 16:08:47 +00001097 p += CREATEPING_IP / 2;
1098 while (count>1) {
1099 sum += *p++;
1100 count -= 2;
1101 }
1102 if (count>0)
1103 sum += * (unsigned char *) p;
1104 while (sum>>16)
1105 sum = (sum & 0xffff) + (sum >> 16);
1106 pack.checksum = ~sum;
1107
1108 ntransmitted++;
jjako08d331d2003-10-13 20:33:30 +00001109 return gtp_data_req(gsn, pdp, &pack, 28 + datasize);
jjako5da68452003-01-28 16:08:47 +00001110}
1111
1112
jjakoa7cd2492003-04-11 09:40:12 +00001113int delete_context(struct pdp_t *pdp) {
1114
1115 if (tun && options.ipdown) tun_runscript(tun, options.ipdown);
1116
1117 ipdel((struct iphash_t*) pdp->peer);
1118 memset(pdp->peer, 0, sizeof(struct iphash_t)); /* To be sure */
jjako7b8fad42003-07-07 14:37:42 +00001119
1120 if (1 == options.contexts)
1121 state = 5; /* Disconnected */
1122
jjakoa7cd2492003-04-11 09:40:12 +00001123 return 0;
jjako52c24142002-12-16 13:33:51 +00001124}
1125
jjakoa7cd2492003-04-11 09:40:12 +00001126
1127/* Callback for receiving messages from tun */
1128int cb_tun_ind(struct tun_t *tun, void *pack, unsigned len) {
1129 struct iphash_t *ipm;
1130 struct in_addr src;
1131 struct tun_packet_t *iph = (struct tun_packet_t*) pack;
1132
1133 src.s_addr = iph->src;
1134
1135 if (ipget(&ipm, &src)) {
1136 printf("Received packet without a valid source address!!!\n");
1137 return 0;
jjako52c24142002-12-16 13:33:51 +00001138 }
jjako5da68452003-01-28 16:08:47 +00001139
jjakoa7cd2492003-04-11 09:40:12 +00001140 if (ipm->pdp) /* Check if a peer protocol is defined */
jjako08d331d2003-10-13 20:33:30 +00001141 gtp_data_req(gsn, ipm->pdp, pack, len);
jjako52c24142002-12-16 13:33:51 +00001142 return 0;
1143}
1144
jjako2c381332003-10-21 19:09:53 +00001145int create_pdp_conf(struct pdp_t *pdp, void *cbp, int cause) {
jjakoa7cd2492003-04-11 09:40:12 +00001146 struct in_addr addr;
jjako52c24142002-12-16 13:33:51 +00001147
jjako2c381332003-10-21 19:09:53 +00001148 struct iphash_t *iph = (struct iphash_t*) cbp;
1149
1150 if (cause < 0) {
1151 printf("Create PDP Context Request timed out\n");
1152 if (iph->pdp->version == 1) {
1153 printf("Retrying with version 0\n");
1154 iph->pdp->version = 0;
jjako193e8b12003-11-10 12:31:41 +00001155 gtp_create_context_req(gsn, iph->pdp, iph);
jjako2c381332003-10-21 19:09:53 +00001156 return 0;
1157 }
1158 else {
1159 state = 0;
jjako0b076a32003-10-25 15:59:31 +00001160 pdp_freepdp(iph->pdp);
1161 iph->pdp = NULL;
jjako2c381332003-10-21 19:09:53 +00001162 return EOF;
1163 }
1164 }
1165
jjakoa7cd2492003-04-11 09:40:12 +00001166 if (cause != 128) {
1167 printf("Received create PDP context response. Cause value: %d\n", cause);
jjako52c24142002-12-16 13:33:51 +00001168 state = 0;
jjako0b076a32003-10-25 15:59:31 +00001169 pdp_freepdp(iph->pdp);
1170 iph->pdp = NULL;
jjakoa7cd2492003-04-11 09:40:12 +00001171 return EOF; /* Not what we expected */
jjako52c24142002-12-16 13:33:51 +00001172 }
1173
jjakoa7cd2492003-04-11 09:40:12 +00001174 if (pdp_euaton(&pdp->eua, &addr)) {
1175 printf("Received create PDP context response. Cause value: %d\n", cause);
jjako0b076a32003-10-25 15:59:31 +00001176 pdp_freepdp(iph->pdp);
1177 iph->pdp = NULL;
jjakoa7cd2492003-04-11 09:40:12 +00001178 state = 0;
1179 return EOF; /* Not a valid IP address */
1180 }
1181
1182 printf("Received create PDP context response. IP address: %s\n",
1183 inet_ntoa(addr));
1184
jjako193e8b12003-11-10 12:31:41 +00001185 if ((options.createif) && (!options.net.s_addr)) {
jjakoa7cd2492003-04-11 09:40:12 +00001186 struct in_addr m;
jjakoff9985c2004-01-16 11:05:22 +00001187#ifdef HAVE_INET_ATON
jjako1d3db972004-01-16 09:56:56 +00001188 inet_aton("255.255.255.255", &m);
1189#else
jjakob73f23a2004-01-16 19:46:41 +00001190 m.s_addr = -1;
jjako1d3db972004-01-16 09:56:56 +00001191#endif
jjakoa7cd2492003-04-11 09:40:12 +00001192 /* printf("Setting up interface and routing\n");*/
1193 tun_addaddr(tun, &addr, &addr, &m);
1194 if (options.defaultroute) {
1195 struct in_addr rm;
1196 rm.s_addr = 0;
1197 tun_addroute(tun, &rm, &addr, &rm);
1198 }
1199 if (options.ipup) tun_runscript(tun, options.ipup);
1200 }
1201
1202 ipset((struct iphash_t*) pdp->peer, &addr);
1203
1204 state = 2; /* Connected */
jjako52c24142002-12-16 13:33:51 +00001205
1206 return 0;
1207}
1208
jjako52c24142002-12-16 13:33:51 +00001209int delete_pdp_conf(struct pdp_t *pdp, int cause) {
1210 printf("Received delete PDP context response. Cause value: %d\n", cause);
1211 return 0;
1212}
1213
jjako08d331d2003-10-13 20:33:30 +00001214int echo_conf(int recovery) {
jjako91aaf222003-10-22 10:09:32 +00001215
1216 if (recovery < 0) {
1217 printf("Echo Request timed out\n");
1218 if (echoversion == 1) {
1219 printf("Retrying with version 0\n");
1220 echoversion = 0;
1221 gtp_echo_req(gsn, echoversion, NULL, &options.remote);
jjako91aaf222003-10-22 10:09:32 +00001222 return 0;
1223 }
1224 else {
1225 state = 0;
1226 return EOF;
1227 }
jjako7b8fad42003-07-07 14:37:42 +00001228 }
jjako581c9f02003-10-22 11:28:20 +00001229 else {
jjako08d331d2003-10-13 20:33:30 +00001230 printf("Received echo response\n");
jjako581c9f02003-10-22 11:28:20 +00001231 if (!options.contexts) state = 5;
1232 }
jjako52c24142002-12-16 13:33:51 +00001233 return 0;
1234}
1235
jjako2c381332003-10-21 19:09:53 +00001236int conf(int type, int cause, struct pdp_t* pdp, void *cbp) {
jjako52c24142002-12-16 13:33:51 +00001237 /* if (cause < 0) return 0; Some error occurred. We don't care */
1238 switch (type) {
1239 case GTP_ECHO_REQ:
jjako08d331d2003-10-13 20:33:30 +00001240 return echo_conf(cause);
jjako52c24142002-12-16 13:33:51 +00001241 case GTP_CREATE_PDP_REQ:
jjako2c381332003-10-21 19:09:53 +00001242 return create_pdp_conf(pdp, cbp, cause);
jjako52c24142002-12-16 13:33:51 +00001243 case GTP_DELETE_PDP_REQ:
1244 if (cause !=128) return 0; /* Request not accepted. We don't care */
1245 return delete_pdp_conf(pdp, cause);
1246 default:
1247 return 0;
1248 }
1249}
1250
jjako52c24142002-12-16 13:33:51 +00001251
1252int encaps_tun(struct pdp_t *pdp, void *pack, unsigned len) {
1253 /* printf("encaps_tun. Packet received: forwarding to tun\n");*/
1254 return tun_encaps((struct tun_t*) pdp->ipif, pack, len);
1255}
1256
1257int main(int argc, char **argv)
1258{
jjako52c24142002-12-16 13:33:51 +00001259 fd_set fds; /* For select() */
1260 struct timeval idleTime; /* How long to select() */
jjakoa7cd2492003-04-11 09:40:12 +00001261 struct pdp_t *pdp;
1262 int n;
1263 int starttime = time(NULL); /* Time program was started */
jjako7b8fad42003-07-07 14:37:42 +00001264 int stoptime = 0; /* Time to exit */
1265 int pingtimeout = 0; /* Time to print ping statistics */
jjakoafb2a972003-01-29 21:04:13 +00001266
1267 struct timezone tz; /* Used for calculating ping times */
1268 struct timeval tv;
1269 int diff;
jjako52c24142002-12-16 13:33:51 +00001270
jjako52c24142002-12-16 13:33:51 +00001271 /* open a connection to the syslog daemon */
1272 /*openlog(PACKAGE, LOG_PID, LOG_DAEMON);*/
jjako0141d202004-01-09 15:19:20 +00001273 /* TODO: Only use LOG__PERROR for linux */
1274
1275#ifdef __linux__
jjako52c24142002-12-16 13:33:51 +00001276 openlog(PACKAGE, (LOG_PID | LOG_PERROR), LOG_DAEMON);
jjako0141d202004-01-09 15:19:20 +00001277#else
1278 openlog(PACKAGE, (LOG_PID), LOG_DAEMON);
1279#endif
1280
jjako52c24142002-12-16 13:33:51 +00001281
jjakoa7cd2492003-04-11 09:40:12 +00001282 /* Process options given in configuration file and command line */
1283 if (process_options(argc, argv))
jjako52c24142002-12-16 13:33:51 +00001284 exit(1);
jjako52c24142002-12-16 13:33:51 +00001285
1286 printf("\nInitialising GTP library\n");
jjakoe607f742003-07-06 21:21:30 +00001287 if (gtp_new(&gsn, options.statedir, &options.listen, GTP_MODE_SGSN)) {
jjakoa7cd2492003-04-11 09:40:12 +00001288 sys_err(LOG_ERR, __FILE__, __LINE__, 0,
1289 "Failed to create gtp");
1290 exit(1);
1291 }
jjako08d331d2003-10-13 20:33:30 +00001292 if (gsn->fd0 > maxfd) maxfd = gsn->fd0;
1293 if (gsn->fd1c > maxfd) maxfd = gsn->fd1c;
1294 if (gsn->fd1u > maxfd) maxfd = gsn->fd1u;
jjako52c24142002-12-16 13:33:51 +00001295
jjakoa7cd2492003-04-11 09:40:12 +00001296 gtp_set_cb_delete_context(gsn, delete_context);
1297 gtp_set_cb_conf(gsn, conf);
1298 if (options.createif)
jjako08d331d2003-10-13 20:33:30 +00001299 gtp_set_cb_data_ind(gsn, encaps_tun);
jjako5da68452003-01-28 16:08:47 +00001300 else
jjako08d331d2003-10-13 20:33:30 +00001301 gtp_set_cb_data_ind(gsn, encaps_ping);
jjakoa7cd2492003-04-11 09:40:12 +00001302
1303 if (options.createif) {
1304 printf("Setting up interface\n");
1305 /* Create a tunnel interface */
1306 if (tun_new((struct tun_t**) &tun)) {
1307 sys_err(LOG_ERR, __FILE__, __LINE__, 0,
1308 "Failed to create tun");
1309 exit(1);
1310 }
1311 tun_set_cb_ind(tun, cb_tun_ind);
1312 if (tun->fd > maxfd) maxfd = tun->fd;
1313 }
1314
jjako193e8b12003-11-10 12:31:41 +00001315 if ((options.createif) && (options.net.s_addr)) {
1316 /* printf("Setting up interface and routing\n");*/
jjakoc6762cf2004-04-28 14:52:58 +00001317 tun_addaddr(tun, &options.netaddr, &options.destaddr, &options.mask);
jjako193e8b12003-11-10 12:31:41 +00001318 if (options.defaultroute) {
1319 struct in_addr rm;
1320 rm.s_addr = 0;
jjakoc6762cf2004-04-28 14:52:58 +00001321 tun_addroute(tun, &rm, &options.destaddr, &rm);
jjako193e8b12003-11-10 12:31:41 +00001322 }
1323 if (options.ipup) tun_runscript(tun, options.ipup);
1324 }
1325
1326
jjakoa7cd2492003-04-11 09:40:12 +00001327 /* Initialise hash tables */
1328 memset(&iphash, 0, sizeof(iphash));
1329 memset(&iparr, 0, sizeof(iparr));
1330
jjako52c24142002-12-16 13:33:51 +00001331 printf("Done initialising GTP library\n\n");
jjako52c24142002-12-16 13:33:51 +00001332
1333 /* See if anybody is there */
1334 printf("Sending off echo request\n");
jjako193e8b12003-11-10 12:31:41 +00001335 echoversion = options.gtpversion;
jjako91aaf222003-10-22 10:09:32 +00001336 gtp_echo_req(gsn, echoversion, NULL, &options.remote); /* Is remote alive? */
jjako52c24142002-12-16 13:33:51 +00001337
jjakoa7cd2492003-04-11 09:40:12 +00001338 for(n=0; n<options.contexts; n++) {
jjako193e8b12003-11-10 12:31:41 +00001339 uint64_t myimsi;
jjako52c24142002-12-16 13:33:51 +00001340 printf("Setting up PDP context #%d\n", n);
jjakoa7cd2492003-04-11 09:40:12 +00001341 iparr[n].inuse = 1; /* TODO */
jjako52c24142002-12-16 13:33:51 +00001342
jjako193e8b12003-11-10 12:31:41 +00001343 imsi_add(options.imsi, &myimsi, n);
1344
jjako0b076a32003-10-25 15:59:31 +00001345 /* Allocated here. */
1346 /* If create context failes we have to deallocate ourselves. */
jjako193e8b12003-11-10 12:31:41 +00001347 /* Otherwise it is deallocated by gtplib */
1348 pdp_newpdp(&pdp, myimsi, options.nsapi, NULL);
jjakoa7cd2492003-04-11 09:40:12 +00001349
1350 pdp->peer = &iparr[n];
1351 pdp->ipif = tun; /* TODO */
1352 iparr[n].pdp = pdp;
1353
Yann BONNAMY11a398f2010-11-18 10:01:21 +01001354 if (options.gtpversion == 0) {
1355 if (options.qos.l - 1 > sizeof(pdp->qos_req0)) {
1356 sys_err(LOG_ERR, __FILE__, __LINE__, 0, "QoS length too big");
1357 exit(1);
1358 }
1359 else {
1360 memcpy(pdp->qos_req0, options.qos.v, options.qos.l);
1361 }
jjako52c24142002-12-16 13:33:51 +00001362 }
jjako08d331d2003-10-13 20:33:30 +00001363
Yann BONNAMY11a398f2010-11-18 10:01:21 +01001364 pdp->qos_req.l = options.qos.l ;
1365 memcpy(pdp->qos_req.v, options.qos.v, options.qos.l);
jjako52c24142002-12-16 13:33:51 +00001366
jjako1a51df72004-07-20 08:30:21 +00001367 pdp->selmode = options.selmode;
jjako52c24142002-12-16 13:33:51 +00001368
Yann BONNAMY944dce32010-10-29 17:07:44 +02001369 pdp->rattype.l = options.rattype.l;
1370 memcpy(pdp->rattype.v, options.rattype.v, options.rattype.l);
1371 pdp->rattype_given = options.rattype_given;
1372
1373 pdp->userloc.l = options.userloc.l;
1374 memcpy(pdp->userloc.v, options.userloc.v, options.userloc.l);
1375 pdp->userloc_given = options.userloc_given;
1376
1377 pdp->mstz.l = options.mstz.l;
1378 memcpy(pdp->mstz.v, options.mstz.v, options.mstz.l);
1379 pdp->mstz_given = options.mstz_given;
1380
1381 pdp->imeisv.l = options.imeisv.l;
1382 memcpy(pdp->imeisv.v, options.imeisv.v, options.imeisv.l);
1383 pdp->imeisv_given = options.imeisv_given;
1384
jjakoa7cd2492003-04-11 09:40:12 +00001385 if (options.apn.l > sizeof(pdp->apn_use.v)) {
1386 sys_err(LOG_ERR, __FILE__, __LINE__, 0, "APN length too big");
jjako52c24142002-12-16 13:33:51 +00001387 exit(1);
1388 }
1389 else {
jjakoa7cd2492003-04-11 09:40:12 +00001390 pdp->apn_use.l = options.apn.l;
1391 memcpy(pdp->apn_use.v, options.apn.v, options.apn.l);
jjako52c24142002-12-16 13:33:51 +00001392 }
1393
jjakoa7cd2492003-04-11 09:40:12 +00001394 pdp->gsnlc.l = sizeof(options.listen);
1395 memcpy(pdp->gsnlc.v, &options.listen, sizeof(options.listen));
1396 pdp->gsnlu.l = sizeof(options.listen);
1397 memcpy(pdp->gsnlu.v, &options.listen, sizeof(options.listen));
jjako52c24142002-12-16 13:33:51 +00001398
jjakoa7cd2492003-04-11 09:40:12 +00001399 if (options.msisdn.l > sizeof(pdp->msisdn.v)) {
1400 sys_err(LOG_ERR, __FILE__, __LINE__, 0, "MSISDN length too big");
jjako52c24142002-12-16 13:33:51 +00001401 exit(1);
1402 }
1403 else {
jjako193e8b12003-11-10 12:31:41 +00001404 msisdn_add(&options.msisdn, &pdp->msisdn, n);
jjakoa7cd2492003-04-11 09:40:12 +00001405 }
1406
1407 ipv42eua(&pdp->eua, NULL); /* Request dynamic IP address */
1408
1409 if (options.pco.l > sizeof(pdp->pco_req.v)) {
1410 sys_err(LOG_ERR, __FILE__, __LINE__, 0, "PCO length too big");
1411 exit(1);
1412 }
1413 else {
1414 pdp->pco_req.l = options.pco.l;
1415 memcpy(pdp->pco_req.v, options.pco.v, options.pco.l);
jjako52c24142002-12-16 13:33:51 +00001416 }
1417
jjako193e8b12003-11-10 12:31:41 +00001418 pdp->version = options.gtpversion;
1419
1420 pdp->hisaddr0 = options.remote;
1421 pdp->hisaddr1 = options.remote;
jjako08d331d2003-10-13 20:33:30 +00001422
jjako7e051d32004-05-27 20:06:36 +00001423 pdp->cch_pdp = options.cch; /* 2048 = Normal, 1024 = Prepaid,
1424 512 = Flat rate, 256 = Hot billing */
jjakob62c3dd2004-05-27 18:51:55 +00001425
jjako52c24142002-12-16 13:33:51 +00001426 /* Create context */
1427 /* We send this of once. Retransmissions are handled by gtplib */
jjako193e8b12003-11-10 12:31:41 +00001428 gtp_create_context_req(gsn, pdp, &iparr[n]);
jjako52c24142002-12-16 13:33:51 +00001429 }
1430
1431 state = 1; /* Enter wait_connection state */
1432
1433 printf("Waiting for response from ggsn........\n\n");
1434
jjako5da68452003-01-28 16:08:47 +00001435
jjako52c24142002-12-16 13:33:51 +00001436 /******************************************************************/
1437 /* Main select loop */
1438 /******************************************************************/
1439
jjako7b8fad42003-07-07 14:37:42 +00001440 while ((0 != state) && (5 != state)) {
jjako52c24142002-12-16 13:33:51 +00001441
jjako7b8fad42003-07-07 14:37:42 +00001442 /* Take down client after timeout after disconnect */
1443 if ((4 == state) && ((stoptime) <= time(NULL))) {
1444 state = 5;
1445 }
1446
1447 /* Take down client after timelimit timeout */
1448 if ((2 == state) && (options.timelimit) &&
1449 ((starttime + options.timelimit) <= time(NULL))) {
jjako52c24142002-12-16 13:33:51 +00001450 state = 3;
jjako7b8fad42003-07-07 14:37:42 +00001451 }
1452
1453 /* Take down client after ping timeout */
1454 if ((2 == state) && (pingtimeout) && (pingtimeout <= time(NULL))) {
1455 state = 3;
1456 }
1457
1458 /* Set pingtimeout for later disconnection */
1459 if (options.pingcount && ntransmitted >= options.pingcount) {
1460 pingtimeout = time(NULL) + 5; /* Extra seconds */
1461 }
1462
1463 /* Print statistics if no more ping packets are missing */
1464 if (ntransmitted && options.pingcount && nreceived >= options.pingcount) {
1465 ping_finish();
1466 if (!options.createif)
1467 state = 3;
1468 }
1469
jjako2c381332003-10-21 19:09:53 +00001470 /* Send off disconnect */
jjako7b8fad42003-07-07 14:37:42 +00001471 if (3 == state) {
1472 state = 4;
1473 stoptime = time(NULL) + 5; /* Extra seconds to allow disconnect */
jjakoa7cd2492003-04-11 09:40:12 +00001474 for(n=0; n<options.contexts; n++) {
jjako52c24142002-12-16 13:33:51 +00001475 /* Delete context */
1476 printf("Disconnecting PDP context #%d\n", n);
jjako2c381332003-10-21 19:09:53 +00001477 gtp_delete_context_req(gsn, iparr[n].pdp, NULL, 1);
jjakoa7cd2492003-04-11 09:40:12 +00001478 if ((options.pinghost.s_addr !=0) && ntransmitted) ping_finish();
jjako52c24142002-12-16 13:33:51 +00001479 }
jjakoafb2a972003-01-29 21:04:13 +00001480 }
jjako7b8fad42003-07-07 14:37:42 +00001481
1482 /* Send of ping packets */
jjakoa7cd2492003-04-11 09:40:12 +00001483 diff = 0;
1484 while (( diff<=0 ) &&
jjako7b8fad42003-07-07 14:37:42 +00001485 /* Send off an ICMP ping packet */
jjakoa7cd2492003-04-11 09:40:12 +00001486 /*if (*/(options.pinghost.s_addr) && (2 == state) &&
jjako7b8fad42003-07-07 14:37:42 +00001487 ((pingseq < options.pingcount) || (options.pingcount == 0))) {
jjakoafb2a972003-01-29 21:04:13 +00001488 if (!pingseq) gettimeofday(&firstping, &tz); /* Set time of first ping */
1489 gettimeofday(&tv, &tz);
jjakoa7cd2492003-04-11 09:40:12 +00001490 diff = 1000000 / options.pingrate * pingseq -
jjakoafb2a972003-01-29 21:04:13 +00001491 1000000 * (tv.tv_sec - firstping.tv_sec) -
1492 (tv.tv_usec - firstping.tv_usec); /* Microseconds safe up to 500 sec */
1493 if (diff <=0) {
jjakoa7cd2492003-04-11 09:40:12 +00001494 if (options.debug) printf("Create_ping %d\n", diff);
1495 create_ping(gsn, iparr[pingseq % options.contexts].pdp,
1496 &options.pinghost, pingseq, options.pingsize);
jjakoafb2a972003-01-29 21:04:13 +00001497 pingseq++;
1498 }
jjako52c24142002-12-16 13:33:51 +00001499 }
jjako5da68452003-01-28 16:08:47 +00001500
jjako52c24142002-12-16 13:33:51 +00001501 FD_ZERO(&fds);
jjakoa7cd2492003-04-11 09:40:12 +00001502 if (tun) FD_SET(tun->fd, &fds);
jjako08d331d2003-10-13 20:33:30 +00001503 FD_SET(gsn->fd0, &fds);
1504 FD_SET(gsn->fd1c, &fds);
1505 FD_SET(gsn->fd1u, &fds);
jjako52c24142002-12-16 13:33:51 +00001506
1507 gtp_retranstimeout(gsn, &idleTime);
jjakoafb2a972003-01-29 21:04:13 +00001508 ping_timeout(&idleTime);
jjakoa7cd2492003-04-11 09:40:12 +00001509
1510 if (options.debug) printf("idletime.tv_sec %d, idleTime.tv_usec %d\n",
1511 (int) idleTime.tv_sec, (int) idleTime.tv_usec);
1512
jjako52c24142002-12-16 13:33:51 +00001513 switch (select(maxfd + 1, &fds, NULL, NULL, &idleTime)) {
1514 case -1:
jjakoa7cd2492003-04-11 09:40:12 +00001515 sys_err(LOG_ERR, __FILE__, __LINE__, 0,
1516 "Select returned -1");
jjako52c24142002-12-16 13:33:51 +00001517 break;
1518 case 0:
1519 gtp_retrans(gsn); /* Only retransmit if nothing else */
1520 break;
1521 default:
1522 break;
1523 }
jjakoa7cd2492003-04-11 09:40:12 +00001524
1525 if ((tun) && FD_ISSET(tun->fd, &fds) && tun_decaps(tun) < 0) {
1526 sys_err(LOG_ERR, __FILE__, __LINE__, 0,
1527 "TUN decaps failed");
jjako52c24142002-12-16 13:33:51 +00001528 }
1529
jjako08d331d2003-10-13 20:33:30 +00001530 if (FD_ISSET(gsn->fd0, &fds))
1531 gtp_decaps0(gsn);
1532
1533 if (FD_ISSET(gsn->fd1c, &fds))
1534 gtp_decaps1c(gsn);
1535
1536 if (FD_ISSET(gsn->fd1u, &fds))
1537 gtp_decaps1u(gsn);
jjako5da68452003-01-28 16:08:47 +00001538 }
jjakoa7cd2492003-04-11 09:40:12 +00001539
jjako52c24142002-12-16 13:33:51 +00001540 gtp_free(gsn); /* Clean up the gsn instance */
1541
jjakoa7cd2492003-04-11 09:40:12 +00001542 if (options.createif)
1543 tun_free(tun);
jjako7b8fad42003-07-07 14:37:42 +00001544
1545 if (0 == state)
1546 exit(1); /* Indicate error */
jjako52c24142002-12-16 13:33:51 +00001547
jjakoa7cd2492003-04-11 09:40:12 +00001548 return 0;
jjako52c24142002-12-16 13:33:51 +00001549}
1550