blob: 9a15d3211f2334d7929d659d45bb420bb3e65e64 [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);
jjako7e051d32004-05-27 20:06:36 +0000249 printf("charging: %#04x\n", args_info.charging_arg);
jjakoc6762cf2004-04-28 14:52:58 +0000250 if (args_info.apn_arg) printf("apn: %s\n", args_info.apn_arg);
251 if (args_info.msisdn_arg) printf("msisdn: %s\n", args_info.msisdn_arg);
252 if (args_info.uid_arg) printf("uid: %s\n", args_info.uid_arg);
253 if (args_info.pwd_arg) printf("pwd: %s\n", args_info.pwd_arg);
254 if (args_info.pidfile_arg) printf("pidfile: %s\n", args_info.pidfile_arg);
255 if (args_info.statedir_arg) printf("statedir: %s\n", args_info.statedir_arg);
256 if (args_info.dns_arg) printf("dns: %s\n", args_info.dns_arg);
jjakoa7cd2492003-04-11 09:40:12 +0000257 printf("contexts: %d\n", args_info.contexts_arg);
258 printf("timelimit: %d\n", args_info.timelimit_arg);
259 printf("createif: %d\n", args_info.createif_flag);
jjakoc6762cf2004-04-28 14:52:58 +0000260 if (args_info.ipup_arg) printf("ipup: %s\n", args_info.ipup_arg);
261 if (args_info.ipdown_arg) printf("ipdown: %s\n", args_info.ipdown_arg);
jjakoa7cd2492003-04-11 09:40:12 +0000262 printf("defaultroute: %d\n", args_info.defaultroute_flag);
jjakoc6762cf2004-04-28 14:52:58 +0000263 if (args_info.pinghost_arg) printf("pinghost: %s\n", args_info.pinghost_arg);
jjakoa7cd2492003-04-11 09:40:12 +0000264 printf("pingrate: %d\n", args_info.pingrate_arg);
265 printf("pingsize: %d\n", args_info.pingsize_arg);
266 printf("pingcount: %d\n", args_info.pingcount_arg);
267 printf("pingquiet: %d\n", args_info.pingquiet_flag);
268 }
269
270 /* Try out our new parser */
271
272 if (args_info.conf_arg) {
Harald Welte1b3e5772010-05-04 11:13:56 +0200273 if (cmdline_parser_configfile (args_info.conf_arg, &args_info, 0, 0, 0) != 0)
jjakoa7cd2492003-04-11 09:40:12 +0000274 return -1;
275 if (args_info.debug_flag) {
276 printf("cmdline_parser_configfile\n");
jjakoc6762cf2004-04-28 14:52:58 +0000277 if (args_info.remote_arg) printf("remote: %s\n", args_info.remote_arg);
278 if (args_info.listen_arg) printf("listen: %s\n", args_info.listen_arg);
279 if (args_info.conf_arg) printf("conf: %s\n", args_info.conf_arg);
jjakoa7cd2492003-04-11 09:40:12 +0000280 printf("debug: %d\n", args_info.debug_flag);
jjakoc6762cf2004-04-28 14:52:58 +0000281 if (args_info.imsi_arg) printf("imsi: %s\n", args_info.imsi_arg);
jjakoa7cd2492003-04-11 09:40:12 +0000282 printf("qos: %#08x\n", args_info.qos_arg);
jjako7e051d32004-05-27 20:06:36 +0000283 printf("charging: %#04x\n", args_info.charging_arg);
jjakoc6762cf2004-04-28 14:52:58 +0000284 if (args_info.apn_arg) printf("apn: %s\n", args_info.apn_arg);
285 if (args_info.msisdn_arg) printf("msisdn: %s\n", args_info.msisdn_arg);
286 if (args_info.uid_arg) printf("uid: %s\n", args_info.uid_arg);
287 if (args_info.pwd_arg) printf("pwd: %s\n", args_info.pwd_arg);
288 if (args_info.pidfile_arg) printf("pidfile: %s\n", args_info.pidfile_arg);
289 if (args_info.statedir_arg) printf("statedir: %s\n", args_info.statedir_arg);
290 if (args_info.dns_arg) printf("dns: %s\n", args_info.dns_arg);
jjakoa7cd2492003-04-11 09:40:12 +0000291 printf("contexts: %d\n", args_info.contexts_arg);
292 printf("timelimit: %d\n", args_info.timelimit_arg);
293 printf("createif: %d\n", args_info.createif_flag);
jjakoc6762cf2004-04-28 14:52:58 +0000294 if (args_info.ipup_arg) printf("ipup: %s\n", args_info.ipup_arg);
295 if (args_info.ipdown_arg) printf("ipdown: %s\n", args_info.ipdown_arg);
jjakoa7cd2492003-04-11 09:40:12 +0000296 printf("defaultroute: %d\n", args_info.defaultroute_flag);
jjakoc6762cf2004-04-28 14:52:58 +0000297 if (args_info.pinghost_arg) printf("pinghost: %s\n", args_info.pinghost_arg);
jjakoa7cd2492003-04-11 09:40:12 +0000298 printf("pingrate: %d\n", args_info.pingrate_arg);
299 printf("pingsize: %d\n", args_info.pingsize_arg);
300 printf("pingcount: %d\n", args_info.pingcount_arg);
301 printf("pingquiet: %d\n", args_info.pingquiet_flag);
302 }
303 }
304
305 /* Handle each option */
306
307 /* foreground */
jjakoe607f742003-07-06 21:21:30 +0000308 /* If fg flag not given run as a daemon */
309 /* Do not allow sgsnemu to run as deamon
jjakoa7cd2492003-04-11 09:40:12 +0000310 if (!args_info.fg_flag)
311 {
312 closelog();
jjakoa7cd2492003-04-11 09:40:12 +0000313 freopen("/dev/null", "w", stdout);
314 freopen("/dev/null", "w", stderr);
315 freopen("/dev/null", "r", stdin);
316 daemon(0, 0);
jjakoa7cd2492003-04-11 09:40:12 +0000317 openlog(PACKAGE, LOG_PID, LOG_DAEMON);
jjakoe607f742003-07-06 21:21:30 +0000318 } */
jjakoa7cd2492003-04-11 09:40:12 +0000319
320 /* debug */
321 options.debug = args_info.debug_flag;
322
323 /* pidfile */
324 /* This has to be done after we have our final pid */
325 if (args_info.pidfile_arg) {
326 log_pid(args_info.pidfile_arg);
327 }
328
329 /* dns */
330 /* If no dns option is given use system default */
331 /* Do hostname lookup to translate hostname to IP address */
332 printf("\n");
333 if (args_info.dns_arg) {
334 if (!(host = gethostbyname(args_info.dns_arg))) {
335 sys_err(LOG_ERR, __FILE__, __LINE__, 0,
336 "Invalid DNS address: %s!", args_info.dns_arg);
337 return -1;
338 }
339 else {
340 memcpy(&options.dns.s_addr, host->h_addr, host->h_length);
341 _res.nscount = 1;
342 _res.nsaddr_list[0].sin_addr = options.dns;
343 printf("Using DNS server: %s (%s)\n",
344 args_info.dns_arg, inet_ntoa(options.dns));
345 }
346 }
347 else {
348 options.dns.s_addr= 0;
349 printf("Using default DNS server\n");
350 }
351
352 /* listen */
353 /* If no listen option is specified listen to any local port */
354 /* Do hostname lookup to translate hostname to IP address */
355 if (args_info.listen_arg) {
356 if (!(host = gethostbyname(args_info.listen_arg))) {
357 sys_err(LOG_ERR, __FILE__, __LINE__, 0,
358 "Invalid listening address: %s!", args_info.listen_arg);
359 return -1;
360 }
361 else {
362 memcpy(&options.listen.s_addr, host->h_addr, host->h_length);
363 printf("Local IP address is: %s (%s)\n",
364 args_info.listen_arg, inet_ntoa(options.listen));
365 }
366 }
367 else {
368 sys_err(LOG_ERR, __FILE__, __LINE__, 0,
369 "Listening address must be specified: %s!", args_info.listen_arg);
370 return -1;
371 }
372
373
374 /* remote */
375 /* If no remote option is specified terminate */
376 /* Do hostname lookup to translate hostname to IP address */
377 if (args_info.remote_arg) {
378 if (!(host = gethostbyname(args_info.remote_arg))) {
379 sys_err(LOG_ERR, __FILE__, __LINE__, 0,
380 "Invalid remote address: %s!", args_info.remote_arg);
381 return -1;
382 }
383 else {
384 memcpy(&options.remote.s_addr, host->h_addr, host->h_length);
385 printf("Remote IP address is: %s (%s)\n",
386 args_info.remote_arg, inet_ntoa(options.remote));
387 }
388 }
389 else {
390 sys_err(LOG_ERR, __FILE__, __LINE__, 0,
391 "No remote address given!");
392 return -1;
393 }
394
395
396 /* imsi */
397 if (strlen(args_info.imsi_arg)!=15) {
398 printf("Invalid IMSI\n");
399 return -1;
400 }
jjako06e9f122004-01-19 18:37:58 +0000401
jjakod48c5ff2004-01-26 22:25:40 +0000402 options.imsi = 0xf000000000000000ull;
jjako06e9f122004-01-19 18:37:58 +0000403 options.imsi |= ((uint64_t) (args_info.imsi_arg[ 0]-48));
jjakoa7cd2492003-04-11 09:40:12 +0000404 options.imsi |= ((uint64_t) (args_info.imsi_arg[ 1]-48)) << 4;
405 options.imsi |= ((uint64_t) (args_info.imsi_arg[ 2]-48)) << 8;
406 options.imsi |= ((uint64_t) (args_info.imsi_arg[ 3]-48)) << 12;
407 options.imsi |= ((uint64_t) (args_info.imsi_arg[ 4]-48)) << 16;
408 options.imsi |= ((uint64_t) (args_info.imsi_arg[ 5]-48)) << 20;
409 options.imsi |= ((uint64_t) (args_info.imsi_arg[ 6]-48)) << 24;
410 options.imsi |= ((uint64_t) (args_info.imsi_arg[ 7]-48)) << 28;
411 options.imsi |= ((uint64_t) (args_info.imsi_arg[ 8]-48)) << 32;
412 options.imsi |= ((uint64_t) (args_info.imsi_arg[ 9]-48)) << 36;
413 options.imsi |= ((uint64_t) (args_info.imsi_arg[10]-48)) << 40;
414 options.imsi |= ((uint64_t) (args_info.imsi_arg[11]-48)) << 44;
415 options.imsi |= ((uint64_t) (args_info.imsi_arg[12]-48)) << 48;
416 options.imsi |= ((uint64_t) (args_info.imsi_arg[13]-48)) << 52;
417 options.imsi |= ((uint64_t) (args_info.imsi_arg[14]-48)) << 56;
418
jjako193e8b12003-11-10 12:31:41 +0000419 printf("IMSI is: %s (%#08llx)\n",
420 args_info.imsi_arg, options.imsi);
421
422
423 /* nsapi */
424 if ((args_info.nsapi_arg > 15) ||
425 (args_info.nsapi_arg < 0)) {
426 printf("Invalid NSAPI\n");
427 return -1;
428 }
429 options.nsapi = args_info.nsapi_arg;
430 printf("Using NSAPI: %d\n", args_info.nsapi_arg);
jjakoa7cd2492003-04-11 09:40:12 +0000431
432
433 /* qos */
434 options.qos.l = 3;
435 options.qos.v[2] = (args_info.qos_arg) & 0xff;
436 options.qos.v[1] = ((args_info.qos_arg) >> 8) & 0xff;
437 options.qos.v[0] = ((args_info.qos_arg) >> 16) & 0xff;
jjako7e051d32004-05-27 20:06:36 +0000438
439 /* charging */
440 options.cch = args_info.charging_arg;
jjakoa7cd2492003-04-11 09:40:12 +0000441
442 /* contexts */
443 if (args_info.contexts_arg > MAXCONTEXTS) {
444 printf("Contexts has to be less than %d\n", MAXCONTEXTS);
445 return -1;
446 }
447 options.contexts = args_info.contexts_arg;
448
449 /* Timelimit */
450 options.timelimit = args_info.timelimit_arg;
451
jjako193e8b12003-11-10 12:31:41 +0000452 /* gtpversion */
453 if ((args_info.gtpversion_arg > 1) ||
454 (args_info.gtpversion_arg < 0)) {
455 printf("Invalid GTP version\n");
456 return -1;
457 }
458 options.gtpversion = args_info.gtpversion_arg;
459 printf("Using GTP version: %d\n", args_info.gtpversion_arg);
460
461
jjakoa7cd2492003-04-11 09:40:12 +0000462 /* apn */
463 if (strlen(args_info.apn_arg) > (sizeof(options.apn.v)-1)) {
464 printf("Invalid APN\n");
465 return -1;
466 }
jjako9f26b952005-03-14 22:03:05 +0000467 options.apn.l = strlen(args_info.apn_arg);
Emmanuel Bretelle2a7cad52010-09-07 15:56:02 +0200468 strncpy((char *)options.apn.v, args_info.apn_arg, sizeof(options.apn.v));
jjako9f26b952005-03-14 22:03:05 +0000469 options.apn.v[sizeof(options.apn.v)-1] = 0;
jjakoa7cd2492003-04-11 09:40:12 +0000470 printf("Using APN: %s\n", args_info.apn_arg);
jjako1a51df72004-07-20 08:30:21 +0000471
472
473 /* selmode */
474 options.selmode = args_info.selmode_arg;
475 printf("Using selection mode: %d\n", args_info.selmode_arg);
476
Yann BONNAMY944dce32010-10-29 17:07:44 +0200477 /* rattype */
478 if (args_info.rattype_given == 1 ) {
479 options.rattype_given = 1 ;
480 options.rattype.l = strlen(args_info.rattype_arg) ;
481 options.rattype.v[0] = atoi(args_info.rattype_arg) ;
482 printf("Using RAT Type: %s\n", args_info.rattype_arg);
483 }
484
485 /* userloc */
486 if (args_info.userloc_given == 1 ) {
487 printf("Using User Location Information: %s\n", args_info.userloc_arg);
488 tmp = args_info.userloc_arg ;
489 n=0;
490 pch = strtok (tmp,".");
491 while (pch != NULL) {
492 userloc_el[n] = pch ;
493 pch = strtok (NULL, ".");
494 n++;
495 }
496
497 options.userloc_given = 1 ;
498 options.userloc.l = 8 ;
499
500 /* 3GPP Geographic Location Type t0 / t1 / t2 */
501 type = userloc_el[0];
502 printf("->type : %c\n", type[0]);
503 if ( (strlen(type)!=1) || (!isdigit(type[0])) ) {
504 printf("Invalid type \n");
505 return -1;
506 }
507 /* options.userloc.v[0] = 0x00 */
508 options.userloc.v[0] = type[0] - 48;
509
510 /* MCC */
511 mcc = userloc_el[1] ;
512 printf("->mcc : %s\n", mcc);
513 if (strlen(mcc)!=3) {
514 printf("Invalid MCC lenght\n");
515 return -1;
516 }
517
518 /* MNC */
519 mnc = userloc_el[2] ;
520 printf("->mnc : %s\n", mnc);
521
522 /* octet 5 - MCC Digit 2 - MCC Digit 1 */
523 /* options.userloc.v[1] = 0x52 */
524 a = (uint8_t) (mcc[0] - 48);
525 b = (uint8_t) (mcc[1] - 48);
526 options.userloc.v[1] = 16*b+a ;
527
528 /* octet 6 - MNC Digit 3 - MCC Digit 3 */
529 /* options.userloc.v[2] = 0xf0 */
530 a = (uint8_t) (mcc[2] - 48);
531
532 if ( (strlen(mnc) > 3) || (strlen(mnc) < 2)) {
533 printf("Invalid MNC lenght\n");
534 return -1;
535 }
536 if (strlen(mnc)==2) {
537 b = 15 ;
538 }
539 if (strlen(mnc)==3) {
540 b = (uint8_t) (mnc[2] - 48);
541 }
542 options.userloc.v[2] = 16*b+a ;
543
544 /* octet 7 - MNC Digit 2 - MNC Digit 1 */
545 /* options.userloc.v[3] = 0x99*/
546 a = (uint8_t) (mnc[0]- 48);
547 b = (uint8_t) (mnc[1]- 48);
548 options.userloc.v[3] = 16*b+a ;
549
550 /* LAC */
551 lac = userloc_el[3] ;
552 /*options.userloc.v[4] = 0x12 ; */
553 /*options.userloc.v[5] = 0x10 ; */
554 printf("->LAC: %s\n", lac);
555 lac_d = atoi(lac);
556 if (lac_d>65535 || lac_d<1) {
557 printf("Invalid LAC\n");
558 return -1;
559 }
560 i = lac_d >> 8 ;
561 options.userloc.v[4] = i; /* octet 8 - LAC */
562 options.userloc.v[5] = lac_d; /* octet 9 - LAC */
563
564 /* CI/SAC/RAC */
565 rest = userloc_el[4] ;
566 printf("->CI/SAC/RAC : %s\n", rest);
567 lac_d = atoi(rest);
568 if (lac_d>65535 || lac_d<1) {
569 printf("Invalid CI/SAC/RAC\n");
570 return -1;
571 }
572 /*options.userloc.v[6] = 0x04 ; */
573 /*options.userloc.v[7] = 0xb7 ; */
574 i = lac_d >> 8 ;
575 options.userloc.v[6] = i; /* octet 10 - t0,CI / t1,SAC / t2,RAC */
576 options.userloc.v[7] = lac_d; /* octet 11 - t0,CI / t1,SAC / t2,RAC */
577 }
578 /* mstz */
579 if (args_info.mstz_given == 1 ) {
580 options.mstz_given = 1 ;
581 options.mstz.l = 2 ;
582
583 printf("Using MS Time Zone: %s\n", args_info.mstz_arg);
584 tmp = args_info.mstz_arg ;
585 n=0;
586 pch = strtok (tmp,".");
587 while (pch != NULL) {
588 mstz_el[n] = pch ;
589 pch = strtok (NULL, ".");
590 n++;
591 }
592
593 /* sign */
594 sign = atoi(mstz_el[0]) ;
595 printf("->Sign (0=+ / 1=-): %d\n", sign);
596 if ( sign!=0 && sign!=1 ) {
597 printf("Invalid Sign \n");
598 return -1;
599 }
600 /* nbquarters */
601 nbquarters = atoi(mstz_el[1]) ;
602 printf("->Number of Quarters of an Hour : %d\n", nbquarters);
603 if ( nbquarters<0 || nbquarters>79 ) {
604 printf("Invalid Number of Quarters \n");
605 return -1;
606 }
607 /* DST */
608 DST = atoi(mstz_el[2]) ;
609 printf("->Daylight Saving Time Adjustment : %d\n", DST);
610 if ( DST<0 || DST>3 ) {
611 printf("Invalid DST Adjustment \n");
612 return -1;
613 }
614 /* 12345678
615 bits 123 = unit of # of quarters of an hour
616 bits 678 = # of quarters of an hour / 10
617 bit 5 = sign
618 */
619 i= nbquarters % 10 ;
620 i = i << 4 ;
621 i = i + nbquarters / 10 + 8 * sign;
622 /* options.mstz.v[0] = 0x69 ; */
623 /* options.mstz.v[1] = 0x01 ; */
624 options.mstz.v[0] = i ;
625 options.mstz.v[1] = DST ;
626 n = (i & 0x08) ? '-' : '+';
627 printf("->Human Readable MS Time Zone : GMT %c %d hours %d minutes\n", n , nbquarters / 4, nbquarters % 4 * 15);
628 }
629
630 /* imeisv */
631 if (args_info.imeisv_given == 1 ) {
632 options.imeisv_given = 1 ;
633 if (strlen(args_info.imeisv_arg)!=16) {
634 printf("Invalid IMEI(SV)\n");
635 return -1;
636 }
637 options.imeisv.l = 8 ;
638 for(n=0; n<8; n++) {
639 a = (uint8_t) (args_info.imeisv_arg [2*n] - 48) ;
640 b = (uint8_t) (args_info.imeisv_arg [2*n + 1] - 48) ;
641 options.imeisv.v[n] = 16*b+a ;
642 }
643 printf("Using IMEI(SV): %s\n", args_info.imeisv_arg);
644 }
jjakoa7cd2492003-04-11 09:40:12 +0000645
646 /* msisdn */
647 if (strlen(args_info.msisdn_arg)>(sizeof(options.msisdn.v)-1)) {
648 printf("Invalid MSISDN\n");
649 return -1;
650 }
651 options.msisdn.l = 1;
652 options.msisdn.v[0] = 0x91; /* International format */
653 for(n=0; n<strlen(args_info.msisdn_arg); n++) {
654 if ((n%2) == 0) {
655 options.msisdn.v[((int)n/2)+1] = args_info.msisdn_arg[n] - 48 + 0xf0;
656 options.msisdn.l += 1;
657 }
658 else {
659 options.msisdn.v[((int)n/2)+1] =
660 (options.msisdn.v[((int)n/2)+1] & 0x0f) +
661 (args_info.msisdn_arg[n] - 48) * 16;
662 }
663 }
664 printf("Using MSISDN: %s\n", args_info.msisdn_arg);
665
666 /* UID and PWD */
667 /* Might need to also insert stuff like DNS etc. */
668 if ((strlen(args_info.uid_arg) + strlen(args_info.pwd_arg) + 10)>
669 (sizeof(options.pco.v)-1)) {
670 printf("invalid UID and PWD\n");
671 return -1;
672 }
673 options.pco.l = strlen(args_info.uid_arg) + strlen(args_info.pwd_arg) + 10;
674 options.pco.v[0] = 0x80; /* PPP */
675 options.pco.v[1] = 0xc0; /* PAP */
676 options.pco.v[2] = 0x23;
jjakob62c3dd2004-05-27 18:51:55 +0000677 options.pco.v[3] = strlen(args_info.uid_arg) + strlen(args_info.pwd_arg) + 6;
jjakoa7cd2492003-04-11 09:40:12 +0000678 options.pco.v[4] = 0x01; /* Authenticate request */
679 options.pco.v[5] = 0x01;
680 options.pco.v[6] = 0x00; /* MSB of length */
681 options.pco.v[7] = strlen(args_info.uid_arg) + strlen(args_info.pwd_arg) + 6;
682 options.pco.v[8] = strlen(args_info.uid_arg);
683 memcpy(&options.pco.v[9], args_info.uid_arg, strlen(args_info.uid_arg));
684 options.pco.v[9+strlen(args_info.uid_arg)] = strlen(args_info.pwd_arg);
685 memcpy(&options.pco.v[10+strlen(args_info.uid_arg)],
686 args_info.pwd_arg, strlen(args_info.pwd_arg));
687
688 /* createif */
689 options.createif = args_info.createif_flag;
690
jjako193e8b12003-11-10 12:31:41 +0000691 /* net */
692 /* Store net as in_addr net and mask */
693 if (args_info.net_arg) {
694 if(ippool_aton(&options.net, &options.mask, args_info.net_arg, 0)) {
695 sys_err(LOG_ERR, __FILE__, __LINE__, 0,
696 "Invalid network address: %s!", args_info.net_arg);
697 exit(1);
698 }
jjakoc6762cf2004-04-28 14:52:58 +0000699
700#if defined (__sun__)
701 options.netaddr.s_addr = htonl(ntohl(options.net.s_addr) + 1);
702 options.destaddr.s_addr = htonl(ntohl(options.net.s_addr) + 1);
703#else
704 options.netaddr.s_addr = options.net.s_addr;
705 options.destaddr.s_addr = options.net.s_addr;
706#endif
707
jjako193e8b12003-11-10 12:31:41 +0000708 }
709 else {
710 options.net.s_addr = 0;
711 options.mask.s_addr = 0;
jjakoc6762cf2004-04-28 14:52:58 +0000712 options.netaddr.s_addr = 0;
713 options.destaddr.s_addr = 0;
jjako193e8b12003-11-10 12:31:41 +0000714 }
715
jjakoa7cd2492003-04-11 09:40:12 +0000716 /* ipup */
717 options.ipup = args_info.ipup_arg;
718
719 /* ipdown */
720 options.ipdown = args_info.ipdown_arg;
721
722 /* statedir */
723 options.statedir = args_info.statedir_arg;
724
725 /* defaultroute */
726 options.defaultroute = args_info.defaultroute_flag;
727
728
jjako76032b92004-01-14 06:22:08 +0000729 /* pinghost */
jjakoa7cd2492003-04-11 09:40:12 +0000730 /* Store ping host as in_addr */
731 if (args_info.pinghost_arg) {
jjako76032b92004-01-14 06:22:08 +0000732 if (!(host = gethostbyname(args_info.pinghost_arg))) {
jjakoa7cd2492003-04-11 09:40:12 +0000733 sys_err(LOG_ERR, __FILE__, __LINE__, 0,
734 "Invalid ping host: %s!", args_info.pinghost_arg);
735 return -1;
736 }
jjako76032b92004-01-14 06:22:08 +0000737 else {
738 memcpy(&options.pinghost.s_addr, host->h_addr, host->h_length);
739 printf("Using ping host: %s (%s)\n",
740 args_info.pinghost_arg, inet_ntoa(options.pinghost));
741 }
jjakoa7cd2492003-04-11 09:40:12 +0000742 }
743
744 /* Other ping parameters */
745 options.pingrate = args_info.pingrate_arg;
746 options.pingsize = args_info.pingsize_arg;
747 options.pingcount = args_info.pingcount_arg;
748 options.pingquiet = args_info.pingquiet_flag;
749
750 return 0;
751
752}
753
jjako5da68452003-01-28 16:08:47 +0000754
755int encaps_printf(struct pdp_t *pdp, void *pack, unsigned len) {
Harald Weltef54a1f42010-05-04 11:08:38 +0200756 unsigned int i;
jjako52c24142002-12-16 13:33:51 +0000757 printf("The packet looks like this:\n");
758 for( i=0; i<len; i++) {
jjako5da68452003-01-28 16:08:47 +0000759 printf("%02x ", (unsigned char)*(char *)(pack+i));
jjako52c24142002-12-16 13:33:51 +0000760 if (!((i+1)%16)) printf("\n");
761 };
jjako5da68452003-01-28 16:08:47 +0000762 printf("\n");
763 return 0;
jjako52c24142002-12-16 13:33:51 +0000764}
765
jjako5da68452003-01-28 16:08:47 +0000766char * print_ipprot(int t) {
767 switch (t) {
768 case 1: return "ICMP";
769 case 6: return "TCP";
770 case 17: return "UDP";
771 default: return "Unknown";
772 };
773}
774
775
776char * print_icmptype(int t) {
777 static char *ttab[] = {
778 "Echo Reply",
779 "ICMP 1",
780 "ICMP 2",
781 "Dest Unreachable",
782 "Source Quench",
783 "Redirect",
784 "ICMP 6",
785 "ICMP 7",
786 "Echo",
787 "ICMP 9",
788 "ICMP 10",
789 "Time Exceeded",
790 "Parameter Problem",
791 "Timestamp",
792 "Timestamp Reply",
793 "Info Request",
794 "Info Reply"
795 };
796 if( t < 0 || t > 16 )
797 return("OUT-OF-RANGE");
798 return(ttab[t]);
799}
800
jjako193e8b12003-11-10 12:31:41 +0000801int msisdn_add(struct ul16_t *src, struct ul16_t *dst, int add) {
Harald Weltef54a1f42010-05-04 11:08:38 +0200802 unsigned int n;
jjako193e8b12003-11-10 12:31:41 +0000803 uint64_t i64 = 0;
804 uint8_t msa[sizeof(i64) * 3]; /* Allocate 3 digits per octet (0..255) */
Harald Weltef54a1f42010-05-04 11:08:38 +0200805 unsigned int msalen = 0;
jjako193e8b12003-11-10 12:31:41 +0000806
807 /* Convert to uint64_t from ul16_t format (most significant digit first) */
808 /* ul16_t format always starts with 0x91 to indicate international format */
809 /* In ul16_t format 0x0f/0xf0 indicates that digit is not used */
810 for (n=0; n< src->l; n++) {
811 if ((src->v[n] & 0x0f) != 0x0f) {
812 i64 *= 10;
813 i64 += src->v[n] & 0x0f;
814 }
815 if ((src->v[n] & 0xf0) != 0xf0) {
816 i64 *= 10;
817 i64 += (src->v[n] & 0xf0) >> 4;
818 }
819 }
820
821 i64 += add;
822
823 /* Generate array with least significant digit in first octet */
824 while (i64) {
825 msa[msalen++] = i64 % 10;
826 i64 = i64 / 10;
827 }
828
829 /* Convert back to ul16_t format */
830 for(n=0; n<msalen; n++) {
831 if ((n%2) == 0) {
832 dst->v[((int)n/2)] = msa[msalen-n-1] + 0xf0;
833 dst->l += 1;
834 }
835 else {
836 dst->v[((int)n/2)] = (dst->v[((int)n/2)] & 0x0f) +
837 msa[msalen-n-1] * 16;
838 }
839 }
840
841 return 0;
842
843}
844
845int imsi_add(uint64_t src, uint64_t *dst, int add) {
846 /* TODO: big endian / small endian ??? */
847 uint64_t i64 = 0;
848
849 /* Convert from uint64_t bcd to uint64_t integer format */
850 /* The resulting integer format is multiplied by 10 */
851 while (src) {
852 if ((src & 0x0f) != 0x0f) {
853 i64 *= 10;
854 i64 += (src & 0x0f);
855 }
856 if ((src & 0xf0) != 0xf0) {
857 i64 *= 10;
858 i64 += (src & 0xf0) >> 4;
859 }
860 src = src >> 8;
861 }
862
863 i64 += add * 10;
864
865 *dst = 0;
866 while (i64) {
867 *dst = *dst << 4;
868 *dst += (i64 % 10);
869 i64 = i64 / 10;
870 }
871
jjakod48c5ff2004-01-26 22:25:40 +0000872 *dst |= 0xf000000000000000ull;
jjako06e9f122004-01-19 18:37:58 +0000873
jjako193e8b12003-11-10 12:31:41 +0000874 return 0;
875
876}
877
jjakoafb2a972003-01-29 21:04:13 +0000878/* Calculate time left until we have to send off next ping packet */
879int ping_timeout(struct timeval *tp) {
880 struct timezone tz;
881 struct timeval tv;
882 int diff;
jjakoa7cd2492003-04-11 09:40:12 +0000883 if ((options.pinghost.s_addr) && (2 == state) &&
884 ((pingseq < options.pingcount) || (options.pingcount == 0))) {
jjakoafb2a972003-01-29 21:04:13 +0000885 gettimeofday(&tv, &tz);
jjakoa7cd2492003-04-11 09:40:12 +0000886 diff = 1000000 / options.pingrate * pingseq -
jjakoafb2a972003-01-29 21:04:13 +0000887 1000000 * (tv.tv_sec - firstping.tv_sec) -
888 (tv.tv_usec - firstping.tv_usec); /* Microseconds safe up to 500 sec */
889 tp->tv_sec = 0;
890 if (diff > 0)
891 tp->tv_usec = diff;
jjakoa7cd2492003-04-11 09:40:12 +0000892 else {
jjakoafb2a972003-01-29 21:04:13 +0000893 /* For some reason we get packet loss if set to zero */
jjakoa7cd2492003-04-11 09:40:12 +0000894 tp->tv_usec = 100000 / options.pingrate; /* 10 times pingrate */
895 tp->tv_usec = 0;
896 }
jjakoafb2a972003-01-29 21:04:13 +0000897 }
898 return 0;
899}
900
jjako5da68452003-01-28 16:08:47 +0000901/* Print out statistics when at the end of ping sequence */
902int ping_finish()
903{
jjakoafb2a972003-01-29 21:04:13 +0000904 struct timezone tz;
905 struct timeval tv;
906 int elapsed;
907 gettimeofday(&tv, &tz);
908 elapsed = 1000000 * (tv.tv_sec - firstping.tv_sec) +
909 (tv.tv_usec - firstping.tv_usec); /* Microseconds */
jjako5da68452003-01-28 16:08:47 +0000910 printf("\n");
jjakoa7cd2492003-04-11 09:40:12 +0000911 printf("\n----%s PING Statistics----\n", inet_ntoa(options.pinghost));
jjakoafb2a972003-01-29 21:04:13 +0000912 printf("%d packets transmitted in %.3f seconds, ", ntransmitted,
913 elapsed / 1000000.0);
jjako5da68452003-01-28 16:08:47 +0000914 printf("%d packets received, ", nreceived );
915 if (ntransmitted) {
916 if( nreceived > ntransmitted)
917 printf("-- somebody's printing up packets!");
918 else
919 printf("%d%% packet loss",
920 (int) (((ntransmitted-nreceived)*100) /
921 ntransmitted));
922 }
923 printf("\n");
jjakoa7cd2492003-04-11 09:40:12 +0000924 if (options.debug) printf("%d packets received in total\n", ntreceived );
jjako5da68452003-01-28 16:08:47 +0000925 if (nreceived && tsum)
926 printf("round-trip (ms) min/avg/max = %.3f/%.3f/%.3f\n\n",
927 tmin/1000.0,
928 tsum/1000.0/nreceived,
929 tmax/1000.0 );
jjakoafb2a972003-01-29 21:04:13 +0000930 printf("%d packets transmitted \n", ntreceived );
931
jjako5da68452003-01-28 16:08:47 +0000932 ntransmitted = 0;
933 return 0;
934}
935
936/* Handle a received ping packet. Print out line and update statistics. */
937int encaps_ping(struct pdp_t *pdp, void *pack, unsigned len) {
938 struct timezone tz;
939 struct timeval tv;
940 struct timeval *tp;
941 struct ip_ping *pingpack = pack;
942 struct in_addr src;
943 int triptime;
944
945 src.s_addr = pingpack->src;
946
947 gettimeofday(&tv, &tz);
jjakoa7cd2492003-04-11 09:40:12 +0000948 if (options.debug) printf("%d.%6d ", (int) tv.tv_sec, (int) tv.tv_usec);
jjako5da68452003-01-28 16:08:47 +0000949
950 if (len < CREATEPING_IP + CREATEPING_ICMP) {
951 printf("packet too short (%d bytes) from %s\n", len,
952 inet_ntoa(src));
953 return 0;
954 }
955
956 ntreceived++;
957 if (pingpack->protocol != 1) {
jjakoa7cd2492003-04-11 09:40:12 +0000958 if (!options.pingquiet) printf("%d bytes from %s: ip_protocol=%d (%s)\n",
jjako5da68452003-01-28 16:08:47 +0000959 len, inet_ntoa(src), pingpack->protocol,
960 print_ipprot(pingpack->protocol));
961 return 0;
962 }
963
964 if (pingpack->type != 0) {
jjakoa7cd2492003-04-11 09:40:12 +0000965 if (!options.pingquiet) printf("%d bytes from %s: icmp_type=%d (%s) icmp_code=%d\n",
jjako5da68452003-01-28 16:08:47 +0000966 len, inet_ntoa(src), pingpack->type,
967 print_icmptype(pingpack->type), pingpack->code);
968 return 0;
969 }
970
971 nreceived++;
jjakoa7cd2492003-04-11 09:40:12 +0000972 if (!options.pingquiet) printf("%d bytes from %s: icmp_seq=%d", len,
jjako5da68452003-01-28 16:08:47 +0000973 inet_ntoa(src), ntohs(pingpack->seq));
974
975 if (len >= sizeof(struct timeval) + CREATEPING_IP + CREATEPING_ICMP) {
976 gettimeofday(&tv, &tz);
977 tp = (struct timeval *) pingpack->data;
978 if( (tv.tv_usec -= tp->tv_usec) < 0 ) {
979 tv.tv_sec--;
980 tv.tv_usec += 1000000;
981 }
982 tv.tv_sec -= tp->tv_sec;
983
984 triptime = tv.tv_sec*1000000+(tv.tv_usec);
985 tsum += triptime;
986 if( triptime < tmin )
987 tmin = triptime;
988 if( triptime > tmax )
989 tmax = triptime;
990
jjakoa7cd2492003-04-11 09:40:12 +0000991 if (!options.pingquiet) printf(" time=%.3f ms\n", triptime/1000.0);
jjako5da68452003-01-28 16:08:47 +0000992
993 }
994 else
jjakoa7cd2492003-04-11 09:40:12 +0000995 if (!options.pingquiet) printf("\n");
jjako5da68452003-01-28 16:08:47 +0000996 return 0;
997}
998
999/* Create a new ping packet and send it off to peer. */
1000int create_ping(void *gsn, struct pdp_t *pdp,
Harald Weltef54a1f42010-05-04 11:08:38 +02001001 struct in_addr *dst, int seq, unsigned int datasize) {
jjako5da68452003-01-28 16:08:47 +00001002
1003 struct ip_ping pack;
jjako0141d202004-01-09 15:19:20 +00001004 uint16_t *p = (uint16_t *) &pack;
1005 uint8_t *p8 = (uint8_t *) &pack;
jjako5da68452003-01-28 16:08:47 +00001006 struct in_addr src;
Harald Weltef54a1f42010-05-04 11:08:38 +02001007 unsigned int n;
jjako5da68452003-01-28 16:08:47 +00001008 long int sum = 0;
1009 int count = 0;
1010
1011 struct timezone tz;
1012 struct timeval *tp = (struct timeval *) &p8[CREATEPING_IP + CREATEPING_ICMP];
1013
1014 if (datasize > CREATEPING_MAX) {
jjakoa7cd2492003-04-11 09:40:12 +00001015 sys_err(LOG_ERR, __FILE__, __LINE__, 0,
1016 "Ping size to large: %d!", datasize);
1017 return -1;
jjako5da68452003-01-28 16:08:47 +00001018 }
1019
1020 memcpy(&src, &(pdp->eua.v[2]), 4); /* Copy a 4 byte address */
1021
1022 pack.ipver = 0x45;
1023 pack.tos = 0x00;
1024 pack.length = htons(CREATEPING_IP + CREATEPING_ICMP + datasize);
1025 pack.fragid = 0x0000;
1026 pack.offset = 0x0040;
1027 pack.ttl = 0x40;
1028 pack.protocol = 0x01;
1029 pack.ipcheck = 0x0000;
1030 pack.src = src.s_addr;
1031 pack.dst = dst->s_addr;
1032 pack.type = 0x08;
1033 pack.code = 0x00;
1034 pack.checksum = 0x0000;
1035 pack.ident = 0x0000;
1036 pack.seq = htons(seq);
1037
1038 /* Generate ICMP payload */
jjako0141d202004-01-09 15:19:20 +00001039 p8 = (uint8_t *) &pack + CREATEPING_IP + CREATEPING_ICMP;
jjako5da68452003-01-28 16:08:47 +00001040 for (n=0; n<(datasize); n++) p8[n] = n;
1041
1042 if (datasize >= sizeof(struct timeval))
1043 gettimeofday(tp, &tz);
1044
1045 /* Calculate IP header checksum */
jjako0141d202004-01-09 15:19:20 +00001046 p = (uint16_t *) &pack;
jjako5da68452003-01-28 16:08:47 +00001047 count = CREATEPING_IP;
1048 sum = 0;
1049 while (count>1) {
1050 sum += *p++;
1051 count -= 2;
1052 }
1053 while (sum>>16)
1054 sum = (sum & 0xffff) + (sum >> 16);
1055 pack.ipcheck = ~sum;
1056
1057
1058 /* Calculate ICMP checksum */
1059 count = CREATEPING_ICMP + datasize; /* Length of ICMP message */
1060 sum = 0;
jjako0141d202004-01-09 15:19:20 +00001061 p = (uint16_t *) &pack;
jjako5da68452003-01-28 16:08:47 +00001062 p += CREATEPING_IP / 2;
1063 while (count>1) {
1064 sum += *p++;
1065 count -= 2;
1066 }
1067 if (count>0)
1068 sum += * (unsigned char *) p;
1069 while (sum>>16)
1070 sum = (sum & 0xffff) + (sum >> 16);
1071 pack.checksum = ~sum;
1072
1073 ntransmitted++;
jjako08d331d2003-10-13 20:33:30 +00001074 return gtp_data_req(gsn, pdp, &pack, 28 + datasize);
jjako5da68452003-01-28 16:08:47 +00001075}
1076
1077
jjakoa7cd2492003-04-11 09:40:12 +00001078int delete_context(struct pdp_t *pdp) {
1079
1080 if (tun && options.ipdown) tun_runscript(tun, options.ipdown);
1081
1082 ipdel((struct iphash_t*) pdp->peer);
1083 memset(pdp->peer, 0, sizeof(struct iphash_t)); /* To be sure */
jjako7b8fad42003-07-07 14:37:42 +00001084
1085 if (1 == options.contexts)
1086 state = 5; /* Disconnected */
1087
jjakoa7cd2492003-04-11 09:40:12 +00001088 return 0;
jjako52c24142002-12-16 13:33:51 +00001089}
1090
jjakoa7cd2492003-04-11 09:40:12 +00001091
1092/* Callback for receiving messages from tun */
1093int cb_tun_ind(struct tun_t *tun, void *pack, unsigned len) {
1094 struct iphash_t *ipm;
1095 struct in_addr src;
1096 struct tun_packet_t *iph = (struct tun_packet_t*) pack;
1097
1098 src.s_addr = iph->src;
1099
1100 if (ipget(&ipm, &src)) {
1101 printf("Received packet without a valid source address!!!\n");
1102 return 0;
jjako52c24142002-12-16 13:33:51 +00001103 }
jjako5da68452003-01-28 16:08:47 +00001104
jjakoa7cd2492003-04-11 09:40:12 +00001105 if (ipm->pdp) /* Check if a peer protocol is defined */
jjako08d331d2003-10-13 20:33:30 +00001106 gtp_data_req(gsn, ipm->pdp, pack, len);
jjako52c24142002-12-16 13:33:51 +00001107 return 0;
1108}
1109
jjako2c381332003-10-21 19:09:53 +00001110int create_pdp_conf(struct pdp_t *pdp, void *cbp, int cause) {
jjakoa7cd2492003-04-11 09:40:12 +00001111 struct in_addr addr;
jjako52c24142002-12-16 13:33:51 +00001112
jjako2c381332003-10-21 19:09:53 +00001113 struct iphash_t *iph = (struct iphash_t*) cbp;
1114
1115 if (cause < 0) {
1116 printf("Create PDP Context Request timed out\n");
1117 if (iph->pdp->version == 1) {
1118 printf("Retrying with version 0\n");
1119 iph->pdp->version = 0;
jjako193e8b12003-11-10 12:31:41 +00001120 gtp_create_context_req(gsn, iph->pdp, iph);
jjako2c381332003-10-21 19:09:53 +00001121 return 0;
1122 }
1123 else {
1124 state = 0;
jjako0b076a32003-10-25 15:59:31 +00001125 pdp_freepdp(iph->pdp);
1126 iph->pdp = NULL;
jjako2c381332003-10-21 19:09:53 +00001127 return EOF;
1128 }
1129 }
1130
jjakoa7cd2492003-04-11 09:40:12 +00001131 if (cause != 128) {
1132 printf("Received create PDP context response. Cause value: %d\n", cause);
jjako52c24142002-12-16 13:33:51 +00001133 state = 0;
jjako0b076a32003-10-25 15:59:31 +00001134 pdp_freepdp(iph->pdp);
1135 iph->pdp = NULL;
jjakoa7cd2492003-04-11 09:40:12 +00001136 return EOF; /* Not what we expected */
jjako52c24142002-12-16 13:33:51 +00001137 }
1138
jjakoa7cd2492003-04-11 09:40:12 +00001139 if (pdp_euaton(&pdp->eua, &addr)) {
1140 printf("Received create PDP context response. Cause value: %d\n", cause);
jjako0b076a32003-10-25 15:59:31 +00001141 pdp_freepdp(iph->pdp);
1142 iph->pdp = NULL;
jjakoa7cd2492003-04-11 09:40:12 +00001143 state = 0;
1144 return EOF; /* Not a valid IP address */
1145 }
1146
1147 printf("Received create PDP context response. IP address: %s\n",
1148 inet_ntoa(addr));
1149
jjako193e8b12003-11-10 12:31:41 +00001150 if ((options.createif) && (!options.net.s_addr)) {
jjakoa7cd2492003-04-11 09:40:12 +00001151 struct in_addr m;
jjakoff9985c2004-01-16 11:05:22 +00001152#ifdef HAVE_INET_ATON
jjako1d3db972004-01-16 09:56:56 +00001153 inet_aton("255.255.255.255", &m);
1154#else
jjakob73f23a2004-01-16 19:46:41 +00001155 m.s_addr = -1;
jjako1d3db972004-01-16 09:56:56 +00001156#endif
jjakoa7cd2492003-04-11 09:40:12 +00001157 /* printf("Setting up interface and routing\n");*/
1158 tun_addaddr(tun, &addr, &addr, &m);
1159 if (options.defaultroute) {
1160 struct in_addr rm;
1161 rm.s_addr = 0;
1162 tun_addroute(tun, &rm, &addr, &rm);
1163 }
1164 if (options.ipup) tun_runscript(tun, options.ipup);
1165 }
1166
1167 ipset((struct iphash_t*) pdp->peer, &addr);
1168
1169 state = 2; /* Connected */
jjako52c24142002-12-16 13:33:51 +00001170
1171 return 0;
1172}
1173
jjako52c24142002-12-16 13:33:51 +00001174int delete_pdp_conf(struct pdp_t *pdp, int cause) {
1175 printf("Received delete PDP context response. Cause value: %d\n", cause);
1176 return 0;
1177}
1178
jjako08d331d2003-10-13 20:33:30 +00001179int echo_conf(int recovery) {
jjako91aaf222003-10-22 10:09:32 +00001180
1181 if (recovery < 0) {
1182 printf("Echo Request timed out\n");
1183 if (echoversion == 1) {
1184 printf("Retrying with version 0\n");
1185 echoversion = 0;
1186 gtp_echo_req(gsn, echoversion, NULL, &options.remote);
jjako91aaf222003-10-22 10:09:32 +00001187 return 0;
1188 }
1189 else {
1190 state = 0;
1191 return EOF;
1192 }
jjako7b8fad42003-07-07 14:37:42 +00001193 }
jjako581c9f02003-10-22 11:28:20 +00001194 else {
jjako08d331d2003-10-13 20:33:30 +00001195 printf("Received echo response\n");
jjako581c9f02003-10-22 11:28:20 +00001196 if (!options.contexts) state = 5;
1197 }
jjako52c24142002-12-16 13:33:51 +00001198 return 0;
1199}
1200
jjako2c381332003-10-21 19:09:53 +00001201int conf(int type, int cause, struct pdp_t* pdp, void *cbp) {
jjako52c24142002-12-16 13:33:51 +00001202 /* if (cause < 0) return 0; Some error occurred. We don't care */
1203 switch (type) {
1204 case GTP_ECHO_REQ:
jjako08d331d2003-10-13 20:33:30 +00001205 return echo_conf(cause);
jjako52c24142002-12-16 13:33:51 +00001206 case GTP_CREATE_PDP_REQ:
jjako2c381332003-10-21 19:09:53 +00001207 return create_pdp_conf(pdp, cbp, cause);
jjako52c24142002-12-16 13:33:51 +00001208 case GTP_DELETE_PDP_REQ:
1209 if (cause !=128) return 0; /* Request not accepted. We don't care */
1210 return delete_pdp_conf(pdp, cause);
1211 default:
1212 return 0;
1213 }
1214}
1215
jjako52c24142002-12-16 13:33:51 +00001216
1217int encaps_tun(struct pdp_t *pdp, void *pack, unsigned len) {
1218 /* printf("encaps_tun. Packet received: forwarding to tun\n");*/
1219 return tun_encaps((struct tun_t*) pdp->ipif, pack, len);
1220}
1221
1222int main(int argc, char **argv)
1223{
jjako52c24142002-12-16 13:33:51 +00001224 fd_set fds; /* For select() */
1225 struct timeval idleTime; /* How long to select() */
jjakoa7cd2492003-04-11 09:40:12 +00001226 struct pdp_t *pdp;
1227 int n;
1228 int starttime = time(NULL); /* Time program was started */
jjako7b8fad42003-07-07 14:37:42 +00001229 int stoptime = 0; /* Time to exit */
1230 int pingtimeout = 0; /* Time to print ping statistics */
jjakoafb2a972003-01-29 21:04:13 +00001231
1232 struct timezone tz; /* Used for calculating ping times */
1233 struct timeval tv;
1234 int diff;
jjako52c24142002-12-16 13:33:51 +00001235
jjako52c24142002-12-16 13:33:51 +00001236 /* open a connection to the syslog daemon */
1237 /*openlog(PACKAGE, LOG_PID, LOG_DAEMON);*/
jjako0141d202004-01-09 15:19:20 +00001238 /* TODO: Only use LOG__PERROR for linux */
1239
1240#ifdef __linux__
jjako52c24142002-12-16 13:33:51 +00001241 openlog(PACKAGE, (LOG_PID | LOG_PERROR), LOG_DAEMON);
jjako0141d202004-01-09 15:19:20 +00001242#else
1243 openlog(PACKAGE, (LOG_PID), LOG_DAEMON);
1244#endif
1245
jjako52c24142002-12-16 13:33:51 +00001246
jjakoa7cd2492003-04-11 09:40:12 +00001247 /* Process options given in configuration file and command line */
1248 if (process_options(argc, argv))
jjako52c24142002-12-16 13:33:51 +00001249 exit(1);
jjako52c24142002-12-16 13:33:51 +00001250
1251 printf("\nInitialising GTP library\n");
jjakoe607f742003-07-06 21:21:30 +00001252 if (gtp_new(&gsn, options.statedir, &options.listen, GTP_MODE_SGSN)) {
jjakoa7cd2492003-04-11 09:40:12 +00001253 sys_err(LOG_ERR, __FILE__, __LINE__, 0,
1254 "Failed to create gtp");
1255 exit(1);
1256 }
jjako08d331d2003-10-13 20:33:30 +00001257 if (gsn->fd0 > maxfd) maxfd = gsn->fd0;
1258 if (gsn->fd1c > maxfd) maxfd = gsn->fd1c;
1259 if (gsn->fd1u > maxfd) maxfd = gsn->fd1u;
jjako52c24142002-12-16 13:33:51 +00001260
jjakoa7cd2492003-04-11 09:40:12 +00001261 gtp_set_cb_delete_context(gsn, delete_context);
1262 gtp_set_cb_conf(gsn, conf);
1263 if (options.createif)
jjako08d331d2003-10-13 20:33:30 +00001264 gtp_set_cb_data_ind(gsn, encaps_tun);
jjako5da68452003-01-28 16:08:47 +00001265 else
jjako08d331d2003-10-13 20:33:30 +00001266 gtp_set_cb_data_ind(gsn, encaps_ping);
jjakoa7cd2492003-04-11 09:40:12 +00001267
1268 if (options.createif) {
1269 printf("Setting up interface\n");
1270 /* Create a tunnel interface */
1271 if (tun_new((struct tun_t**) &tun)) {
1272 sys_err(LOG_ERR, __FILE__, __LINE__, 0,
1273 "Failed to create tun");
1274 exit(1);
1275 }
1276 tun_set_cb_ind(tun, cb_tun_ind);
1277 if (tun->fd > maxfd) maxfd = tun->fd;
1278 }
1279
jjako193e8b12003-11-10 12:31:41 +00001280 if ((options.createif) && (options.net.s_addr)) {
1281 /* printf("Setting up interface and routing\n");*/
jjakoc6762cf2004-04-28 14:52:58 +00001282 tun_addaddr(tun, &options.netaddr, &options.destaddr, &options.mask);
jjako193e8b12003-11-10 12:31:41 +00001283 if (options.defaultroute) {
1284 struct in_addr rm;
1285 rm.s_addr = 0;
jjakoc6762cf2004-04-28 14:52:58 +00001286 tun_addroute(tun, &rm, &options.destaddr, &rm);
jjako193e8b12003-11-10 12:31:41 +00001287 }
1288 if (options.ipup) tun_runscript(tun, options.ipup);
1289 }
1290
1291
jjakoa7cd2492003-04-11 09:40:12 +00001292 /* Initialise hash tables */
1293 memset(&iphash, 0, sizeof(iphash));
1294 memset(&iparr, 0, sizeof(iparr));
1295
jjako52c24142002-12-16 13:33:51 +00001296 printf("Done initialising GTP library\n\n");
jjako52c24142002-12-16 13:33:51 +00001297
1298 /* See if anybody is there */
1299 printf("Sending off echo request\n");
jjako193e8b12003-11-10 12:31:41 +00001300 echoversion = options.gtpversion;
jjako91aaf222003-10-22 10:09:32 +00001301 gtp_echo_req(gsn, echoversion, NULL, &options.remote); /* Is remote alive? */
jjako52c24142002-12-16 13:33:51 +00001302
jjakoa7cd2492003-04-11 09:40:12 +00001303 for(n=0; n<options.contexts; n++) {
jjako193e8b12003-11-10 12:31:41 +00001304 uint64_t myimsi;
jjako52c24142002-12-16 13:33:51 +00001305 printf("Setting up PDP context #%d\n", n);
jjakoa7cd2492003-04-11 09:40:12 +00001306 iparr[n].inuse = 1; /* TODO */
jjako52c24142002-12-16 13:33:51 +00001307
jjako193e8b12003-11-10 12:31:41 +00001308 imsi_add(options.imsi, &myimsi, n);
1309
jjako0b076a32003-10-25 15:59:31 +00001310 /* Allocated here. */
1311 /* If create context failes we have to deallocate ourselves. */
jjako193e8b12003-11-10 12:31:41 +00001312 /* Otherwise it is deallocated by gtplib */
1313 pdp_newpdp(&pdp, myimsi, options.nsapi, NULL);
jjakoa7cd2492003-04-11 09:40:12 +00001314
1315 pdp->peer = &iparr[n];
1316 pdp->ipif = tun; /* TODO */
1317 iparr[n].pdp = pdp;
1318
1319 if (options.qos.l > sizeof(pdp->qos_req0)) {
1320 sys_err(LOG_ERR, __FILE__, __LINE__, 0, "QoS length too big");
jjako52c24142002-12-16 13:33:51 +00001321 exit(1);
1322 }
1323 else {
jjakoa7cd2492003-04-11 09:40:12 +00001324 memcpy(pdp->qos_req0, options.qos.v, options.qos.l);
jjako52c24142002-12-16 13:33:51 +00001325 }
jjako08d331d2003-10-13 20:33:30 +00001326
1327 /* TODO */
1328 pdp->qos_req.l = 4;
1329 pdp->qos_req.v[0] = 0x00;
1330 memcpy(pdp->qos_req.v+1, options.qos.v, options.qos.l);
jjako52c24142002-12-16 13:33:51 +00001331
jjako1a51df72004-07-20 08:30:21 +00001332 pdp->selmode = options.selmode;
jjako52c24142002-12-16 13:33:51 +00001333
Yann BONNAMY944dce32010-10-29 17:07:44 +02001334 pdp->rattype.l = options.rattype.l;
1335 memcpy(pdp->rattype.v, options.rattype.v, options.rattype.l);
1336 pdp->rattype_given = options.rattype_given;
1337
1338 pdp->userloc.l = options.userloc.l;
1339 memcpy(pdp->userloc.v, options.userloc.v, options.userloc.l);
1340 pdp->userloc_given = options.userloc_given;
1341
1342 pdp->mstz.l = options.mstz.l;
1343 memcpy(pdp->mstz.v, options.mstz.v, options.mstz.l);
1344 pdp->mstz_given = options.mstz_given;
1345
1346 pdp->imeisv.l = options.imeisv.l;
1347 memcpy(pdp->imeisv.v, options.imeisv.v, options.imeisv.l);
1348 pdp->imeisv_given = options.imeisv_given;
1349
jjakoa7cd2492003-04-11 09:40:12 +00001350 if (options.apn.l > sizeof(pdp->apn_use.v)) {
1351 sys_err(LOG_ERR, __FILE__, __LINE__, 0, "APN length too big");
jjako52c24142002-12-16 13:33:51 +00001352 exit(1);
1353 }
1354 else {
jjakoa7cd2492003-04-11 09:40:12 +00001355 pdp->apn_use.l = options.apn.l;
1356 memcpy(pdp->apn_use.v, options.apn.v, options.apn.l);
jjako52c24142002-12-16 13:33:51 +00001357 }
1358
jjakoa7cd2492003-04-11 09:40:12 +00001359 pdp->gsnlc.l = sizeof(options.listen);
1360 memcpy(pdp->gsnlc.v, &options.listen, sizeof(options.listen));
1361 pdp->gsnlu.l = sizeof(options.listen);
1362 memcpy(pdp->gsnlu.v, &options.listen, sizeof(options.listen));
jjako52c24142002-12-16 13:33:51 +00001363
jjakoa7cd2492003-04-11 09:40:12 +00001364 if (options.msisdn.l > sizeof(pdp->msisdn.v)) {
1365 sys_err(LOG_ERR, __FILE__, __LINE__, 0, "MSISDN length too big");
jjako52c24142002-12-16 13:33:51 +00001366 exit(1);
1367 }
1368 else {
jjako193e8b12003-11-10 12:31:41 +00001369 msisdn_add(&options.msisdn, &pdp->msisdn, n);
jjakoa7cd2492003-04-11 09:40:12 +00001370 }
1371
1372 ipv42eua(&pdp->eua, NULL); /* Request dynamic IP address */
1373
1374 if (options.pco.l > sizeof(pdp->pco_req.v)) {
1375 sys_err(LOG_ERR, __FILE__, __LINE__, 0, "PCO length too big");
1376 exit(1);
1377 }
1378 else {
1379 pdp->pco_req.l = options.pco.l;
1380 memcpy(pdp->pco_req.v, options.pco.v, options.pco.l);
jjako52c24142002-12-16 13:33:51 +00001381 }
1382
jjako193e8b12003-11-10 12:31:41 +00001383 pdp->version = options.gtpversion;
1384
1385 pdp->hisaddr0 = options.remote;
1386 pdp->hisaddr1 = options.remote;
jjako08d331d2003-10-13 20:33:30 +00001387
jjako7e051d32004-05-27 20:06:36 +00001388 pdp->cch_pdp = options.cch; /* 2048 = Normal, 1024 = Prepaid,
1389 512 = Flat rate, 256 = Hot billing */
jjakob62c3dd2004-05-27 18:51:55 +00001390
jjako52c24142002-12-16 13:33:51 +00001391 /* Create context */
1392 /* We send this of once. Retransmissions are handled by gtplib */
jjako193e8b12003-11-10 12:31:41 +00001393 gtp_create_context_req(gsn, pdp, &iparr[n]);
jjako52c24142002-12-16 13:33:51 +00001394 }
1395
1396 state = 1; /* Enter wait_connection state */
1397
1398 printf("Waiting for response from ggsn........\n\n");
1399
jjako5da68452003-01-28 16:08:47 +00001400
jjako52c24142002-12-16 13:33:51 +00001401 /******************************************************************/
1402 /* Main select loop */
1403 /******************************************************************/
1404
jjako7b8fad42003-07-07 14:37:42 +00001405 while ((0 != state) && (5 != state)) {
jjako52c24142002-12-16 13:33:51 +00001406
jjako7b8fad42003-07-07 14:37:42 +00001407 /* Take down client after timeout after disconnect */
1408 if ((4 == state) && ((stoptime) <= time(NULL))) {
1409 state = 5;
1410 }
1411
1412 /* Take down client after timelimit timeout */
1413 if ((2 == state) && (options.timelimit) &&
1414 ((starttime + options.timelimit) <= time(NULL))) {
jjako52c24142002-12-16 13:33:51 +00001415 state = 3;
jjako7b8fad42003-07-07 14:37:42 +00001416 }
1417
1418 /* Take down client after ping timeout */
1419 if ((2 == state) && (pingtimeout) && (pingtimeout <= time(NULL))) {
1420 state = 3;
1421 }
1422
1423 /* Set pingtimeout for later disconnection */
1424 if (options.pingcount && ntransmitted >= options.pingcount) {
1425 pingtimeout = time(NULL) + 5; /* Extra seconds */
1426 }
1427
1428 /* Print statistics if no more ping packets are missing */
1429 if (ntransmitted && options.pingcount && nreceived >= options.pingcount) {
1430 ping_finish();
1431 if (!options.createif)
1432 state = 3;
1433 }
1434
jjako2c381332003-10-21 19:09:53 +00001435 /* Send off disconnect */
jjako7b8fad42003-07-07 14:37:42 +00001436 if (3 == state) {
1437 state = 4;
1438 stoptime = time(NULL) + 5; /* Extra seconds to allow disconnect */
jjakoa7cd2492003-04-11 09:40:12 +00001439 for(n=0; n<options.contexts; n++) {
jjako52c24142002-12-16 13:33:51 +00001440 /* Delete context */
1441 printf("Disconnecting PDP context #%d\n", n);
jjako2c381332003-10-21 19:09:53 +00001442 gtp_delete_context_req(gsn, iparr[n].pdp, NULL, 1);
jjakoa7cd2492003-04-11 09:40:12 +00001443 if ((options.pinghost.s_addr !=0) && ntransmitted) ping_finish();
jjako52c24142002-12-16 13:33:51 +00001444 }
jjakoafb2a972003-01-29 21:04:13 +00001445 }
jjako7b8fad42003-07-07 14:37:42 +00001446
1447 /* Send of ping packets */
jjakoa7cd2492003-04-11 09:40:12 +00001448 diff = 0;
1449 while (( diff<=0 ) &&
jjako7b8fad42003-07-07 14:37:42 +00001450 /* Send off an ICMP ping packet */
jjakoa7cd2492003-04-11 09:40:12 +00001451 /*if (*/(options.pinghost.s_addr) && (2 == state) &&
jjako7b8fad42003-07-07 14:37:42 +00001452 ((pingseq < options.pingcount) || (options.pingcount == 0))) {
jjakoafb2a972003-01-29 21:04:13 +00001453 if (!pingseq) gettimeofday(&firstping, &tz); /* Set time of first ping */
1454 gettimeofday(&tv, &tz);
jjakoa7cd2492003-04-11 09:40:12 +00001455 diff = 1000000 / options.pingrate * pingseq -
jjakoafb2a972003-01-29 21:04:13 +00001456 1000000 * (tv.tv_sec - firstping.tv_sec) -
1457 (tv.tv_usec - firstping.tv_usec); /* Microseconds safe up to 500 sec */
1458 if (diff <=0) {
jjakoa7cd2492003-04-11 09:40:12 +00001459 if (options.debug) printf("Create_ping %d\n", diff);
1460 create_ping(gsn, iparr[pingseq % options.contexts].pdp,
1461 &options.pinghost, pingseq, options.pingsize);
jjakoafb2a972003-01-29 21:04:13 +00001462 pingseq++;
1463 }
jjako52c24142002-12-16 13:33:51 +00001464 }
jjako5da68452003-01-28 16:08:47 +00001465
jjako52c24142002-12-16 13:33:51 +00001466 FD_ZERO(&fds);
jjakoa7cd2492003-04-11 09:40:12 +00001467 if (tun) FD_SET(tun->fd, &fds);
jjako08d331d2003-10-13 20:33:30 +00001468 FD_SET(gsn->fd0, &fds);
1469 FD_SET(gsn->fd1c, &fds);
1470 FD_SET(gsn->fd1u, &fds);
jjako52c24142002-12-16 13:33:51 +00001471
1472 gtp_retranstimeout(gsn, &idleTime);
jjakoafb2a972003-01-29 21:04:13 +00001473 ping_timeout(&idleTime);
jjakoa7cd2492003-04-11 09:40:12 +00001474
1475 if (options.debug) printf("idletime.tv_sec %d, idleTime.tv_usec %d\n",
1476 (int) idleTime.tv_sec, (int) idleTime.tv_usec);
1477
jjako52c24142002-12-16 13:33:51 +00001478 switch (select(maxfd + 1, &fds, NULL, NULL, &idleTime)) {
1479 case -1:
jjakoa7cd2492003-04-11 09:40:12 +00001480 sys_err(LOG_ERR, __FILE__, __LINE__, 0,
1481 "Select returned -1");
jjako52c24142002-12-16 13:33:51 +00001482 break;
1483 case 0:
1484 gtp_retrans(gsn); /* Only retransmit if nothing else */
1485 break;
1486 default:
1487 break;
1488 }
jjakoa7cd2492003-04-11 09:40:12 +00001489
1490 if ((tun) && FD_ISSET(tun->fd, &fds) && tun_decaps(tun) < 0) {
1491 sys_err(LOG_ERR, __FILE__, __LINE__, 0,
1492 "TUN decaps failed");
jjako52c24142002-12-16 13:33:51 +00001493 }
1494
jjako08d331d2003-10-13 20:33:30 +00001495 if (FD_ISSET(gsn->fd0, &fds))
1496 gtp_decaps0(gsn);
1497
1498 if (FD_ISSET(gsn->fd1c, &fds))
1499 gtp_decaps1c(gsn);
1500
1501 if (FD_ISSET(gsn->fd1u, &fds))
1502 gtp_decaps1u(gsn);
jjako5da68452003-01-28 16:08:47 +00001503 }
jjakoa7cd2492003-04-11 09:40:12 +00001504
jjako52c24142002-12-16 13:33:51 +00001505 gtp_free(gsn); /* Clean up the gsn instance */
1506
jjakoa7cd2492003-04-11 09:40:12 +00001507 if (options.createif)
1508 tun_free(tun);
jjako7b8fad42003-07-07 14:37:42 +00001509
1510 if (0 == state)
1511 exit(1); /* Indicate error */
jjako52c24142002-12-16 13:33:51 +00001512
jjakoa7cd2492003-04-11 09:40:12 +00001513 return 0;
jjako52c24142002-12-16 13:33:51 +00001514}
1515