blob: 0230b55260492e0029525f9806718846063c1580 [file] [log] [blame]
jjako52c24142002-12-16 13:33:51 +00001/*
2 * OpenGGSN - Gateway GPRS Support Node
3 * Copyright (C) 2002 Mondru AB.
4 *
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 *
10 * The initial developer of the original code is
11 * Jens Jakobsen <jj@openggsn.org>
12 *
13 * Contributor(s):
14 *
15 */
16
17/*
18 * sgsnemu.c
19 *
20 */
21
22
23#ifdef __linux__
24#define _GNU_SOURCE 1 /* strdup() prototype, broken arpa/inet.h */
25#endif
26
27
28#include <syslog.h>
29#include <ctype.h>
30#include <netdb.h>
31#include <signal.h>
32#include <stdio.h>
33#include <string.h>
34#include <stdlib.h>
35#include <sys/types.h>
36#include <sys/socket.h>
37#include <netinet/in.h>
38#include <arpa/inet.h>
39#include <sys/wait.h>
40#include <sys/stat.h>
41#include <unistd.h>
42#include <sys/socket.h>
43#include <sys/ioctl.h>
jjako5da68452003-01-28 16:08:47 +000044#include <sys/time.h>
jjako52c24142002-12-16 13:33:51 +000045#include <net/if.h>
46#include <features.h>
47#include <errno.h>
48#include <asm/types.h>
49#include <sys/socket.h>
50#include <linux/netlink.h>
51#include <resolv.h>
52#include <time.h>
53
54#include "tun.h"
55#include "../gtp/pdp.h"
56#include "../gtp/gtp.h"
57#include "cmdline.h"
58
jjako5da68452003-01-28 16:08:47 +000059#define SGSNEMU_BUFSIZE 1024
60
jjako52c24142002-12-16 13:33:51 +000061/* State variable */
62/* 0: Idle */
63/* 1: Wait_connect */
64/* 2: Connected */
65/* 3: Wait_disconnect */
66int state = 0;
67
68int maxfd = 0; /* For select() */
69int tun_fd = -1; /* Network file descriptor */
70struct tun_t *tun; /* TUN instance */
71struct tun_t *tun1, *tun2; /* TUN instance for client */
72int tun_fd1 = -1; /* Network file descriptor */
73int tun_fd2 = -1; /* Network file descriptor */
jjako52c24142002-12-16 13:33:51 +000074
jjako5da68452003-01-28 16:08:47 +000075/* Variables matching program configuration parameters */
jjako52c24142002-12-16 13:33:51 +000076int debug; /* Print debug messages */
jjako5da68452003-01-28 16:08:47 +000077struct in_addr net, mask; /* Network interface */
78int createif; /* Create local network interface */
79char *ipup, *ipdown; /* Filename of scripts */
80int defaultroute; /* Set up default route */
81struct in_addr pinghost; /* Remote ping host */
82int pingrate, pingsize, pingcount, pingquiet;
83struct in_addr listen_, remote;
84struct in_addr dns;
85int contexts; /* Number of contexts to create */
86int timelimit; /* Number of seconds to be connected */
jjako52c24142002-12-16 13:33:51 +000087
jjako5da68452003-01-28 16:08:47 +000088
89/* Definitions to use for PING. Most of the ping code was derived from */
90/* the original ping program by Mike Muuss */
91
92/* IP header and ICMP echo header */
93#define CREATEPING_MAX 2048
94#define CREATEPING_IP 20
95#define CREATEPING_ICMP 8
96
97struct ip_ping {
98 u_int8_t ipver; /* Type and header length*/
99 u_int8_t tos; /* Type of Service */
100 u_int16_t length; /* Total length */
101 u_int16_t fragid; /* Identifier */
102 u_int16_t offset; /* Flags and fragment offset */
103 u_int8_t ttl; /* Time to live */
104 u_int8_t protocol; /* Protocol */
105 u_int16_t ipcheck; /* Header checksum */
106 u_int32_t src; /* Source address */
107 u_int32_t dst; /* Destination */
108 u_int8_t type; /* Type and header length*/
109 u_int8_t code; /* Code */
110 u_int16_t checksum; /* Header checksum */
111 u_int16_t ident; /* Identifier */
112 u_int16_t seq; /* Sequence number */
113 u_int8_t data[CREATEPING_MAX]; /* Data */
114} __attribute__((packed));
115
116/* Statistical values for ping */
117int nreceived = 0;
118int ntreceived = 0;
119int ntransmitted = 0;
120int tmin = 999999999;
121int tmax = 0;
122int tsum = 0;
123
124
125int encaps_printf(struct pdp_t *pdp, void *pack, unsigned len) {
jjako52c24142002-12-16 13:33:51 +0000126 int i;
127 printf("The packet looks like this:\n");
128 for( i=0; i<len; i++) {
jjako5da68452003-01-28 16:08:47 +0000129 printf("%02x ", (unsigned char)*(char *)(pack+i));
jjako52c24142002-12-16 13:33:51 +0000130 if (!((i+1)%16)) printf("\n");
131 };
jjako5da68452003-01-28 16:08:47 +0000132 printf("\n");
133 return 0;
jjako52c24142002-12-16 13:33:51 +0000134}
135
jjako5da68452003-01-28 16:08:47 +0000136char * print_ipprot(int t) {
137 switch (t) {
138 case 1: return "ICMP";
139 case 6: return "TCP";
140 case 17: return "UDP";
141 default: return "Unknown";
142 };
143}
144
145
146char * print_icmptype(int t) {
147 static char *ttab[] = {
148 "Echo Reply",
149 "ICMP 1",
150 "ICMP 2",
151 "Dest Unreachable",
152 "Source Quench",
153 "Redirect",
154 "ICMP 6",
155 "ICMP 7",
156 "Echo",
157 "ICMP 9",
158 "ICMP 10",
159 "Time Exceeded",
160 "Parameter Problem",
161 "Timestamp",
162 "Timestamp Reply",
163 "Info Request",
164 "Info Reply"
165 };
166 if( t < 0 || t > 16 )
167 return("OUT-OF-RANGE");
168 return(ttab[t]);
169}
170
171/* Print out statistics when at the end of ping sequence */
172int ping_finish()
173{
174 printf("\n");
175 printf("\n----%s PING Statistics----\n", inet_ntoa(pinghost));
176 printf("%d packets transmitted, ", ntransmitted );
177 printf("%d packets received, ", nreceived );
178 if (ntransmitted) {
179 if( nreceived > ntransmitted)
180 printf("-- somebody's printing up packets!");
181 else
182 printf("%d%% packet loss",
183 (int) (((ntransmitted-nreceived)*100) /
184 ntransmitted));
185 }
186 printf("\n");
187 if (debug) printf("%d packets received in total\n", ntreceived );
188 if (nreceived && tsum)
189 printf("round-trip (ms) min/avg/max = %.3f/%.3f/%.3f\n\n",
190 tmin/1000.0,
191 tsum/1000.0/nreceived,
192 tmax/1000.0 );
193 ntransmitted = 0;
194 return 0;
195}
196
197/* Handle a received ping packet. Print out line and update statistics. */
198int encaps_ping(struct pdp_t *pdp, void *pack, unsigned len) {
199 struct timezone tz;
200 struct timeval tv;
201 struct timeval *tp;
202 struct ip_ping *pingpack = pack;
203 struct in_addr src;
204 int triptime;
205
206 src.s_addr = pingpack->src;
207
208 gettimeofday(&tv, &tz);
209 if (debug) printf("%d.%6d ", (int) tv.tv_sec, (int) tv.tv_usec);
210
211 if (len < CREATEPING_IP + CREATEPING_ICMP) {
212 printf("packet too short (%d bytes) from %s\n", len,
213 inet_ntoa(src));
214 return 0;
215 }
216
217 ntreceived++;
218 if (pingpack->protocol != 1) {
219 if (!pingquiet) printf("%d bytes from %s: ip_protocol=%d (%s)\n",
220 len, inet_ntoa(src), pingpack->protocol,
221 print_ipprot(pingpack->protocol));
222 return 0;
223 }
224
225 if (pingpack->type != 0) {
226 if (!pingquiet) printf("%d bytes from %s: icmp_type=%d (%s) icmp_code=%d\n",
227 len, inet_ntoa(src), pingpack->type,
228 print_icmptype(pingpack->type), pingpack->code);
229 return 0;
230 }
231
232 nreceived++;
233 if (!pingquiet) printf("%d bytes from %s: icmp_seq=%d", len,
234 inet_ntoa(src), ntohs(pingpack->seq));
235
236 if (len >= sizeof(struct timeval) + CREATEPING_IP + CREATEPING_ICMP) {
237 gettimeofday(&tv, &tz);
238 tp = (struct timeval *) pingpack->data;
239 if( (tv.tv_usec -= tp->tv_usec) < 0 ) {
240 tv.tv_sec--;
241 tv.tv_usec += 1000000;
242 }
243 tv.tv_sec -= tp->tv_sec;
244
245 triptime = tv.tv_sec*1000000+(tv.tv_usec);
246 tsum += triptime;
247 if( triptime < tmin )
248 tmin = triptime;
249 if( triptime > tmax )
250 tmax = triptime;
251
252 if (!pingquiet) printf(" time=%.3f ms\n", triptime/1000.0);
253
254 }
255 else
256 if (!pingquiet) printf("\n");
257 return 0;
258}
259
260/* Create a new ping packet and send it off to peer. */
261int create_ping(void *gsn, struct pdp_t *pdp,
262 struct in_addr *dst, int seq, int datasize) {
263
264 struct ip_ping pack;
265 u_int16_t *p = (u_int16_t *) &pack;
266 u_int8_t *p8 = (u_int8_t *) &pack;
267 struct in_addr src;
268 int n;
269 long int sum = 0;
270 int count = 0;
271
272 struct timezone tz;
273 struct timeval *tp = (struct timeval *) &p8[CREATEPING_IP + CREATEPING_ICMP];
274
275 if (datasize > CREATEPING_MAX) {
276 fprintf(stderr, "%s: Ping size to large: %d!\n",
277 PACKAGE, datasize);
278 syslog(LOG_ERR, "Ping size to large: %d!",
279 datasize);
280 exit(1);
281 }
282
283 memcpy(&src, &(pdp->eua.v[2]), 4); /* Copy a 4 byte address */
284
285 pack.ipver = 0x45;
286 pack.tos = 0x00;
287 pack.length = htons(CREATEPING_IP + CREATEPING_ICMP + datasize);
288 pack.fragid = 0x0000;
289 pack.offset = 0x0040;
290 pack.ttl = 0x40;
291 pack.protocol = 0x01;
292 pack.ipcheck = 0x0000;
293 pack.src = src.s_addr;
294 pack.dst = dst->s_addr;
295 pack.type = 0x08;
296 pack.code = 0x00;
297 pack.checksum = 0x0000;
298 pack.ident = 0x0000;
299 pack.seq = htons(seq);
300
301 /* Generate ICMP payload */
302 p8 = (u_int8_t *) &pack + CREATEPING_IP + CREATEPING_ICMP;
303 for (n=0; n<(datasize); n++) p8[n] = n;
304
305 if (datasize >= sizeof(struct timeval))
306 gettimeofday(tp, &tz);
307
308 /* Calculate IP header checksum */
309 p = (u_int16_t *) &pack;
310 count = CREATEPING_IP;
311 sum = 0;
312 while (count>1) {
313 sum += *p++;
314 count -= 2;
315 }
316 while (sum>>16)
317 sum = (sum & 0xffff) + (sum >> 16);
318 pack.ipcheck = ~sum;
319
320
321 /* Calculate ICMP checksum */
322 count = CREATEPING_ICMP + datasize; /* Length of ICMP message */
323 sum = 0;
324 p = (u_int16_t *) &pack;
325 p += CREATEPING_IP / 2;
326 while (count>1) {
327 sum += *p++;
328 count -= 2;
329 }
330 if (count>0)
331 sum += * (unsigned char *) p;
332 while (sum>>16)
333 sum = (sum & 0xffff) + (sum >> 16);
334 pack.checksum = ~sum;
335
336 ntransmitted++;
337
338 return gtp_gpdu(gsn, pdp, &pack, 28 + datasize);
339}
340
341
jjako52c24142002-12-16 13:33:51 +0000342/* Used to write process ID to file. Assume someone else will delete */
343void log_pid(char *pidfile) {
344 FILE *file;
345 mode_t oldmask;
346
347 oldmask = umask(022);
348 file = fopen(pidfile, "w");
349 umask(oldmask);
350 if(!file)
351 return;
352 fprintf(file, "%d\n", getpid());
353 fclose(file);
354}
355
jjako52c24142002-12-16 13:33:51 +0000356int delete_context(struct pdp_t *pdp) {
jjako5da68452003-01-28 16:08:47 +0000357 char buf[SGSNEMU_BUFSIZE];
358 if ((createif) && (pdp->ipif!=0)) {
jjako52c24142002-12-16 13:33:51 +0000359 tun_freetun((struct tun_t*) pdp->ipif);
360
361 /* Clean up locally */
362 if (pdp->ipif == tun1) {
363 printf("Deleting tun interface\n");
364 tun_fd1=-1;
365 }
366 if (pdp->ipif == tun2) {
367 printf("Deleting tun interface\n");
368 tun_fd2=-1;
369 }
370 }
jjako5da68452003-01-28 16:08:47 +0000371
372 if (ipdown) {
373 /* system("ipdown /dev/tun0 192.168.0.10"); */
374 snprintf(buf, sizeof(buf), "%s %s %hu.%hu.%hu.%hu",
375 ipdown,
376 ((struct tun_t*) pdp->ipif)->devname,
377 pdp->eua.v[2], pdp->eua.v[3], pdp->eua.v[4], pdp->eua.v[5]);
378 if (debug) printf("%s\n", buf);
379 system(buf);
380 }
jjako52c24142002-12-16 13:33:51 +0000381
382 pdp_ipdel(pdp);
383 return 0;
384}
385
386int create_pdp_conf(struct pdp_t *pdp, int cause) {
jjako5da68452003-01-28 16:08:47 +0000387 char buf[SGSNEMU_BUFSIZE];
388 char snet[SGSNEMU_BUFSIZE];
389 char smask[SGSNEMU_BUFSIZE];
jjako52c24142002-12-16 13:33:51 +0000390
391 printf("Received create PDP context response. Cause value: %d\n", cause);
392 if ((cause == 128) && (pdp->eua.l == 6)) {
jjako5da68452003-01-28 16:08:47 +0000393
394 if (!createif) {
jjako52c24142002-12-16 13:33:51 +0000395 pdp->ipif = tun1;
396 }
397 else {
398 printf("Setting up interface and routing\n");
399 if ((tun_fd = tun_newtun((struct tun_t**) &pdp->ipif)) > maxfd)
400 maxfd = tun_fd;
jjako5da68452003-01-28 16:08:47 +0000401
jjako52c24142002-12-16 13:33:51 +0000402 /* HACK: Only support select of up to two tun interfaces */
403 if (NULL == tun1) {
404 tun1 = pdp->ipif;
405 tun_fd1 = tun1->fd;
406 }
407 else {
408 tun2 = pdp->ipif;
409 tun_fd2 = tun2->fd;
410 }
411
jjako49014712003-01-05 17:59:49 +0000412 /*system("/sbin/ifconfig tun0 192.168.0.10");*/
jjako5da68452003-01-28 16:08:47 +0000413 snprintf(buf, sizeof(buf), "/sbin/ifconfig %s %hu.%hu.%hu.%hu",
jjako52c24142002-12-16 13:33:51 +0000414 ((struct tun_t*) pdp->ipif)->devname,
415 pdp->eua.v[2], pdp->eua.v[3], pdp->eua.v[4], pdp->eua.v[5]);
jjako5da68452003-01-28 16:08:47 +0000416 /* if (debug) */ printf("%s\n", buf);
jjako52c24142002-12-16 13:33:51 +0000417 system(buf);
jjako5da68452003-01-28 16:08:47 +0000418
419 /* system("route add -host 192.168.0.10 dev tun0"); */
420 /* It seams as if we do not need to set up a route to a p-t-p interface
421 snprintf(buf, sizeof(buf),
422 "/sbin/route add -host %hu.%hu.%hu.%hu dev %s",
423 pdp->eua.v[2], pdp->eua.v[3], pdp->eua.v[4], pdp->eua.v[5],
424 ((struct tun_t*) pdp->ipif)->devname);
425 if (debug) printf("%s\n", buf);
426 system(buf);*/
427
428 if (defaultroute) {
429 strncpy(snet, inet_ntoa(net), sizeof(snet));
430 strncpy(smask, inet_ntoa(mask), sizeof(smask));
431 /* system("route add -net 0.0.0.0 netmask 0.0.0.0 gw 192.168.0.1"); */
432 snprintf(buf, sizeof(buf),
433 "/sbin/route add -net %s netmask %s gw %hu.%hu.%hu.%hu",
434 snet, smask,
435 pdp->eua.v[2], pdp->eua.v[3], pdp->eua.v[4], pdp->eua.v[5]);
436 /* if (debug) */ printf("%s\n", buf);
437 system(buf);
438 }
439
440 if (ipup) {
441 /* system("ipup /dev/tun0 192.168.0.10"); */
442 snprintf(buf, sizeof(buf), "%s %s %hu.%hu.%hu.%hu",
443 ipup,
444 ((struct tun_t*) pdp->ipif)->devname,
445 pdp->eua.v[2], pdp->eua.v[3], pdp->eua.v[4], pdp->eua.v[5]);
446 if (debug) printf("%s\n", buf);
447 system(buf);
448 }
jjako52c24142002-12-16 13:33:51 +0000449
jjako52c24142002-12-16 13:33:51 +0000450 }
451
452 pdp_ipset(pdp, pdp->ipif, &pdp->eua);
453
454 state = 2; /* Connected */
455 }
456 else {
457 state = 0;
458 }
459
460 printf("\n");
461
462 return 0;
463}
464
jjako52c24142002-12-16 13:33:51 +0000465int delete_pdp_conf(struct pdp_t *pdp, int cause) {
466 printf("Received delete PDP context response. Cause value: %d\n", cause);
jjako5da68452003-01-28 16:08:47 +0000467 state = 0; /* Idle */
jjako52c24142002-12-16 13:33:51 +0000468 return 0;
469}
470
471int echo_conf(struct pdp_t *pdp, int cause) {
jjako5da68452003-01-28 16:08:47 +0000472 if (cause <0)
473 printf("Echo request timed out\n");
474 else
475 printf("Received echo response.\n");
jjako52c24142002-12-16 13:33:51 +0000476 return 0;
477}
478
479int conf(int type, int cause, struct pdp_t* pdp, void *aid) {
480 /* if (cause < 0) return 0; Some error occurred. We don't care */
481 switch (type) {
482 case GTP_ECHO_REQ:
483 return echo_conf(pdp, cause);
484 case GTP_CREATE_PDP_REQ:
485 if (cause !=128) return 0; /* Request not accepted. We don't care */
486 return create_pdp_conf(pdp, cause);
487 case GTP_DELETE_PDP_REQ:
488 if (cause !=128) return 0; /* Request not accepted. We don't care */
489 return delete_pdp_conf(pdp, cause);
490 default:
491 return 0;
492 }
493}
494
495int encaps_gtp_client(void *gsn, struct tun_t *tun, void *pack, unsigned len) {
496 /* Special client version which checks for source address instead */
497 struct pdp_t *pdp;
498 struct in_addr addr;
499 struct ul66_t eua;
500 /*printf("encaps_gtp. Packet received: forwarding to gtp.\n");*/
501 /* First we need to extract the IP destination address */
502 memcpy(&addr.s_addr, pack+12, 4); /* This ought to be dest addr */
503 pdp_ntoeua(&addr, &eua);
504 if (pdp_ipget(&pdp, tun, &eua) == 0) {
505 return gtp_gpdu((struct gsn_t*) gsn, pdp, pack, len);
506 }
507 else {
jjako5da68452003-01-28 16:08:47 +0000508 printf("Received packet without a valid source address!!!\n");
jjako52c24142002-12-16 13:33:51 +0000509 return 0;
510 }
511}
512
513int encaps_tun(struct pdp_t *pdp, void *pack, unsigned len) {
514 /* printf("encaps_tun. Packet received: forwarding to tun\n");*/
515 return tun_encaps((struct tun_t*) pdp->ipif, pack, len);
516}
517
518int main(int argc, char **argv)
519{
520 /* gengeopt declarations */
521 struct gengetopt_args_info args_info;
522
jjako52c24142002-12-16 13:33:51 +0000523
524 struct hostent *host;
jjako52c24142002-12-16 13:33:51 +0000525 int gtpfd = -1; /* Network file descriptor */
526 struct gsn_t *gsn; /* GSN instance */
jjako52c24142002-12-16 13:33:51 +0000527 fd_set fds; /* For select() */
528 struct timeval idleTime; /* How long to select() */
jjako5da68452003-01-28 16:08:47 +0000529 struct pdp_t *pdp[50];
jjako52c24142002-12-16 13:33:51 +0000530 int n; /* For counter */
jjako5da68452003-01-28 16:08:47 +0000531 int starttime; /* Time program was started */
532 int pingseq = 0; /* Ping sequence counter */
jjako52c24142002-12-16 13:33:51 +0000533
jjako5da68452003-01-28 16:08:47 +0000534 /* function-local options */
jjako52c24142002-12-16 13:33:51 +0000535 struct ul_t imsi, qos, apn, msisdn;
536 unsigned char qosh[3], imsih[8], apnh[256], msisdnh[256];
537 struct ul255_t pco;
538 uint64_t imsi3;
539
540 /* open a connection to the syslog daemon */
541 /*openlog(PACKAGE, LOG_PID, LOG_DAEMON);*/
542 openlog(PACKAGE, (LOG_PID | LOG_PERROR), LOG_DAEMON);
543
544 if (cmdline_parser (argc, argv, &args_info) != 0)
545 exit(1);
546 if (args_info.debug_flag) {
547 printf("remote: %s\n", args_info.remote_arg);
548 printf("listen: %s\n", args_info.listen_arg);
549 printf("conf: %s\n", args_info.conf_arg);
550 printf("fg: %d\n", args_info.fg_flag);
551 printf("debug: %d\n", args_info.debug_flag);
552 printf("imsi: %s\n", args_info.imsi_arg);
553 printf("qos: %#08x\n", args_info.qos_arg);
554 printf("apn: %s\n", args_info.apn_arg);
555 printf("msisdn: %s\n", args_info.msisdn_arg);
556 printf("uid: %s\n", args_info.uid_arg);
557 printf("pwd: %s\n", args_info.pwd_arg);
jjako52c24142002-12-16 13:33:51 +0000558 printf("pidfile: %s\n", args_info.pidfile_arg);
559 printf("statedir: %s\n", args_info.statedir_arg);
560 printf("dns: %s\n", args_info.dns_arg);
561 printf("contexts: %d\n", args_info.contexts_arg);
562 printf("timelimit: %d\n", args_info.timelimit_arg);
jjako5da68452003-01-28 16:08:47 +0000563 printf("createif: %d\n", args_info.createif_flag);
564 printf("ipup: %s\n", args_info.ipup_arg);
565 printf("ipdown: %s\n", args_info.ipdown_arg);
566 printf("defaultroute: %d\n", args_info.defaultroute_flag);
567 printf("net: %s\n", args_info.net_arg);
568 printf("mask: %s\n", args_info.mask_arg);
569 printf("pinghost: %s\n", args_info.pinghost_arg);
570 printf("pingrate: %d\n", args_info.pingrate_arg);
571 printf("pingsize: %d\n", args_info.pingsize_arg);
572 printf("pingcount: %d\n", args_info.pingcount_arg);
573 printf("pingquiet: %d\n", args_info.pingquiet_flag);
jjako52c24142002-12-16 13:33:51 +0000574 }
575
576 /* Try out our new parser */
577
578 if (args_info.conf_arg) {
579 if (cmdline_parser_configfile (args_info.conf_arg, &args_info, 0) != 0)
580 exit(1);
581 if (args_info.debug_flag) {
582 printf("cmdline_parser_configfile\n");
583 printf("remote: %s\n", args_info.remote_arg);
584 printf("listen: %s\n", args_info.listen_arg);
585 printf("conf: %s\n", args_info.conf_arg);
586 printf("fg: %d\n", args_info.fg_flag);
587 printf("debug: %d\n", args_info.debug_flag);
588 printf("imsi: %s\n", args_info.imsi_arg);
589 printf("qos: %#08x\n", args_info.qos_arg);
590 printf("apn: %s\n", args_info.apn_arg);
591 printf("msisdn: %s\n", args_info.msisdn_arg);
592 printf("uid: %s\n", args_info.uid_arg);
593 printf("pwd: %s\n", args_info.pwd_arg);
jjako52c24142002-12-16 13:33:51 +0000594 printf("pidfile: %s\n", args_info.pidfile_arg);
595 printf("statedir: %s\n", args_info.statedir_arg);
596 printf("dns: %s\n", args_info.dns_arg);
597 printf("contexts: %d\n", args_info.contexts_arg);
598 printf("timelimit: %d\n", args_info.timelimit_arg);
jjako5da68452003-01-28 16:08:47 +0000599 printf("createif: %d\n", args_info.createif_flag);
600 printf("ipup: %s\n", args_info.ipup_arg);
601 printf("ipdown: %s\n", args_info.ipdown_arg);
602 printf("defaultroute: %d\n", args_info.defaultroute_flag);
603 printf("net: %s\n", args_info.net_arg);
604 printf("mask: %s\n", args_info.mask_arg);
605 printf("pinghost: %s\n", args_info.pinghost_arg);
606 printf("pingrate: %d\n", args_info.pingrate_arg);
607 printf("pingsize: %d\n", args_info.pingsize_arg);
608 printf("pingcount: %d\n", args_info.pingcount_arg);
609 printf("pingquiet: %d\n", args_info.pingquiet_flag);
jjako52c24142002-12-16 13:33:51 +0000610 }
611 }
612
613 /* Handle each option */
614
615 /* foreground */
jjako5da68452003-01-28 16:08:47 +0000616 /* If fg flag not given run as a daemon */
jjako52c24142002-12-16 13:33:51 +0000617 if (!args_info.fg_flag)
618 {
619 closelog();
620 /* Close the standard file descriptors. Why? */
621 freopen("/dev/null", "w", stdout);
622 freopen("/dev/null", "w", stderr);
623 freopen("/dev/null", "r", stdin);
624 daemon(0, 0);
625 /* Open log again. This time with new pid */
626 openlog(PACKAGE, LOG_PID, LOG_DAEMON);
627 }
628
629 /* debug */
630 debug = args_info.debug_flag;
631
632 /* pidfile */
633 /* This has to be done after we have our final pid */
634 if (args_info.pidfile_arg) {
635 log_pid(args_info.pidfile_arg);
636 }
637
638 /* dns */
jjako5da68452003-01-28 16:08:47 +0000639 /* If no dns option is given use system default */
jjako52c24142002-12-16 13:33:51 +0000640 /* Do hostname lookup to translate hostname to IP address */
641 printf("\n");
642 if (args_info.dns_arg) {
643 if (!(host = gethostbyname(args_info.dns_arg))) {
644 fprintf(stderr, "%s: Invalid dns address: %s!\n",
645 PACKAGE, args_info.dns_arg);
646 syslog(LOG_ERR, "Invalid dns address: %s!",
647 args_info.dns_arg);
648 exit(1);
649 }
650 else {
651 memcpy(&dns.s_addr, host->h_addr, host->h_length);
652 _res.nscount = 1;
653 _res.nsaddr_list[0].sin_addr = dns;
654 printf("Using DNS server: %s (%s)\n", args_info.dns_arg, inet_ntoa(dns));
655 }
656 }
657 else {
658 dns.s_addr= 0;
659 printf("Using default DNS server\n");
660 }
661
662 /* listen */
663 /* If no listen option is specified listen to any local port */
664 /* Do hostname lookup to translate hostname to IP address */
665 if (args_info.listen_arg) {
666 if (!(host = gethostbyname(args_info.listen_arg))) {
667 fprintf(stderr, "%s: Invalid listening address: %s!\n",
668 PACKAGE, args_info.listen_arg);
669 syslog(LOG_ERR, "Invalid listening address: %s!",
670 args_info.listen_arg);
671 exit(1);
672 }
673 else {
jjako5da68452003-01-28 16:08:47 +0000674 memcpy(&listen_.s_addr, host->h_addr, host->h_length);
675 printf("Local IP address is: %s (%s)\n", args_info.listen_arg, inet_ntoa(listen_));
jjako52c24142002-12-16 13:33:51 +0000676 }
677 }
678 else {
679 fprintf(stderr, "%s: Listening address must be specified: %s!\n",
680 PACKAGE, args_info.listen_arg);
681 syslog(LOG_ERR, "Listening address must be specified: %s!",
682 args_info.listen_arg);
683 exit(1);
684 }
685
686
687 /* remote */
688 /* If no remote option is specified terminate */
689 /* Do hostname lookup to translate hostname to IP address */
690 if (args_info.remote_arg) {
691 if (!(host = gethostbyname(args_info.remote_arg))) {
692 fprintf(stderr, "%s: Invalid remote address: %s!\n",
693 PACKAGE, args_info.remote_arg);
694 syslog(LOG_ERR, "Invalid remote address: %s!",
695 args_info.remote_arg);
696 exit(1);
697 }
698 else {
699 memcpy(&remote.s_addr, host->h_addr, host->h_length);
700 printf("Remote IP address is: %s (%s)\n", args_info.remote_arg, inet_ntoa(remote));
701 }
702 }
703 else {
704 fprintf(stderr, "%s: No remote address given!\n",
705 PACKAGE);
706 syslog(LOG_ERR, "No remote address given!");
707 exit(1);
708 }
709
710
jjako52c24142002-12-16 13:33:51 +0000711 /* imsi */
712 if (strlen(args_info.imsi_arg)!=15) {
713 printf("Invalid IMSI\n");
714 exit(1);
715 }
716 imsi.l = 8;
717 imsi.v = imsih;
718 imsi.v[0] = args_info.imsi_arg[0]-48 + (args_info.imsi_arg[1]-48)*16;
719 imsi.v[1] = args_info.imsi_arg[2]-48 + (args_info.imsi_arg[3]-48)*16;
720 imsi.v[2] = args_info.imsi_arg[4]-48 + (args_info.imsi_arg[5]-48)*16;
721 imsi.v[3] = args_info.imsi_arg[6]-48 + (args_info.imsi_arg[7]-48)*16;
722 imsi.v[4] = args_info.imsi_arg[8]-48 + (args_info.imsi_arg[9]-48)*16;
723 imsi.v[5] = args_info.imsi_arg[10]-48 + (args_info.imsi_arg[11]-48)*16;
724 imsi.v[6] = args_info.imsi_arg[12]-48 + (args_info.imsi_arg[13]-48)*16;
725 imsi.v[7] = args_info.imsi_arg[14]-48 + 0*16;
726
727 if (imsi.l > sizeof(imsi3)) {
728 printf("Invalid IMSI\n");
729 exit(1);
730 }
731 else {
732 memcpy(&imsi3, imsi.v, imsi.l);
733 printf("IMSI is: %s (%#08llx)\n", args_info.imsi_arg, imsi3);
734 }
735
736 /* qos */
737 qos.l = 3;
738 qos.v = qosh;
739 qos.v[2] = (args_info.qos_arg) & 0xff;
740 qos.v[1] = ((args_info.qos_arg) >> 8) & 0xff;
741 qos.v[0] = ((args_info.qos_arg) >> 16) & 0xff;
742
743 /* contexts */
jjako5da68452003-01-28 16:08:47 +0000744 if (args_info.contexts_arg>16) {
745 printf("Contexts has to be less than 16\n");
746 exit(1);
747 }
jjako52c24142002-12-16 13:33:51 +0000748 contexts = args_info.contexts_arg;
749
750 /* Timelimit */
751 timelimit = args_info.timelimit_arg;
752 starttime = time(NULL);
753
754 /* apn */
755 if (strlen(args_info.apn_arg)>255) {
756 printf("Invalid APN\n");
757 exit(1);
758 }
759 apn.l = strlen(args_info.apn_arg) + 1;
760 apn.v = apnh;
761 apn.v[0] = (char) strlen(args_info.apn_arg);
762 strncpy(&apn.v[1], args_info.apn_arg, 255);
763 printf("Using APN: %s\n", args_info.apn_arg);
764
765 /* msisdn */
766 if (strlen(args_info.msisdn_arg)>255) {
767 printf("Invalid MSISDN\n");
768 exit(1);
769 }
770 msisdn.l = 1;
771 msisdn.v = msisdnh;
772 msisdn.v[0] = 0x91; /* International format */
773 for(n=0; n<strlen(args_info.msisdn_arg); n++) {
774 if ((n%2) == 0) {
775 msisdn.v[((int)n/2)+1] = args_info.msisdn_arg[n] - 48 + 0xf0;
776 msisdn.l += 1;
777 }
778 else {
779 msisdn.v[((int)n/2)+1] = (msisdn.v[((int)n/2)+1] & 0x0f) + (args_info.msisdn_arg[n] - 48) * 16;
780 }
781 }
782 printf("Using MSISDN: %s\n", args_info.msisdn_arg);
783
784 /* UID and PWD */
785 /* Might need to also insert stuff like DNS etc. */
786 if ((strlen(args_info.uid_arg) + strlen(args_info.pwd_arg) + 10)>255) {
787 printf("invalid UID and PWD\n");
788 exit(1);
789 }
790 pco.l = strlen(args_info.uid_arg) + strlen(args_info.pwd_arg) + 10;
791 pco.v[0] = 0x80; /* PPP */
792 pco.v[1] = 0xc0;
793 pco.v[2] = 0x23; /* PAP */
794 pco.v[3] = 0x12;
795 pco.v[4] = 0x01; /* Authenticate request */
796 pco.v[5] = 0x01;
797 pco.v[6] = 0x00; /* MSB of length */
798 pco.v[7] = strlen(args_info.uid_arg) + strlen(args_info.pwd_arg) + 6;
799 pco.v[8] = strlen(args_info.uid_arg);
800 memcpy(&pco.v[9], args_info.uid_arg, strlen(args_info.uid_arg));
801 pco.v[9+strlen(args_info.uid_arg)] = strlen(args_info.pwd_arg);
802 memcpy(&pco.v[10+strlen(args_info.uid_arg)], args_info.pwd_arg, strlen(args_info.pwd_arg));
803
jjako5da68452003-01-28 16:08:47 +0000804 /* createif */
805 createif = args_info.createif_flag;
806
807 /* ipup */
808 ipup = args_info.ipup_arg;
809
810 /* ipdown */
811 ipdown = args_info.ipdown_arg;
812
813 /* defaultroute */
814 defaultroute = args_info.defaultroute_flag;
815
816 /* net */
817 /* Store net as in_addr */
818 if (args_info.net_arg) {
819 if (!inet_aton(args_info.net_arg, &net)) {
820 fprintf(stderr, "%s: Invalid network address: %s!\n",
821 PACKAGE, args_info.net_arg);
822 syslog(LOG_ERR, "Invalid network address: %s!",
823 args_info.net_arg);
824 exit(1);
825 }
826 }
827
828 /* mask */
829 /* Store mask as in_addr */
830 if (args_info.mask_arg) {
831 if (!inet_aton(args_info.mask_arg, &mask)) {
832 fprintf(stderr, "%s: Invalid network mask: %s!\n",
833 PACKAGE, args_info.mask_arg);
834 syslog(LOG_ERR, "Invalid network mask: %s!",
835 args_info.mask_arg);
836 exit(1);
837 }
838 }
839
840 /* pinghost */
841 /* Store ping host as in_addr */
842 if (args_info.pinghost_arg) {
843 if (!inet_aton(args_info.pinghost_arg, &pinghost)) {
844 fprintf(stderr, "%s: Invalid ping host: %s!\n",
845 PACKAGE, args_info.pinghost_arg);
846 syslog(LOG_ERR, "Invalid ping host: %s!",
847 args_info.pinghost_arg);
848 exit(1);
849 }
850 }
851
852 /* Other ping parameters */
853 pingrate = args_info.pingrate_arg;
854 pingsize = args_info.pingsize_arg;
855 pingcount = args_info.pingcount_arg;
856 pingquiet = args_info.pingquiet_flag;
jjako52c24142002-12-16 13:33:51 +0000857
858 printf("\nInitialising GTP library\n");
jjako5da68452003-01-28 16:08:47 +0000859 if ((gtpfd = gtp_new(&gsn, args_info.statedir_arg, &listen_)) > maxfd)
jjako52c24142002-12-16 13:33:51 +0000860 maxfd = gtpfd;
861
862 if ((gtpfd = gtp_fd(gsn)) > maxfd)
863 maxfd = gtpfd;
864
jjako5da68452003-01-28 16:08:47 +0000865 if (createif)
866 gtp_set_cb_gpdu(gsn, encaps_tun);
867 else
868 gtp_set_cb_gpdu(gsn, encaps_ping);
869
jjako52c24142002-12-16 13:33:51 +0000870 gtp_set_cb_delete_context(gsn, delete_context);
871
872 gtp_set_cb_conf(gsn, conf);
873 printf("Done initialising GTP library\n\n");
jjako52c24142002-12-16 13:33:51 +0000874
875 /* See if anybody is there */
876 printf("Sending off echo request\n");
877 if (gtpfd != -1) gtp_echo_req(gsn, &remote); /* See if remote is alive ? */
878
879 for(n=0; n<contexts; n++) {
880 printf("Setting up PDP context #%d\n", n);
881
882 pdp_newpdp(&pdp[n], imsi3, n, NULL); /* Allocated here. Cleaned up in gtp.c: TODO Should be statically allocated! */
883
884 /*
885 if (qos.l > sizeof(pdp[n]->qos_req.v)) {
886 exit(1);
887 }
888 else {
889 pdp[n]->qos_req.l = qos.l;
890 memcpy(pdp[n]->qos_req.v, qos.v, qos.l);
891 }
892 */
893 memcpy(pdp[n]->qos_req0, qos.v, qos.l); /* TODO range check */
894
895 pdp[n]->selmode = 0x01; /* MS provided APN, subscription not verified */
896
897 if (apn.l > sizeof(pdp[n]->apn_use.v)) {
898 exit(1);
899 }
900 else {
901 pdp[n]->apn_use.l = apn.l;
902 memcpy(pdp[n]->apn_use.v, apn.v, apn.l);
903 }
904
905 pdp[n]->gsnlc.l = 4;
jjako5da68452003-01-28 16:08:47 +0000906 memcpy(pdp[n]->gsnlc.v, &listen_, 4);
jjako52c24142002-12-16 13:33:51 +0000907 pdp[n]->gsnlu.l = 4;
jjako5da68452003-01-28 16:08:47 +0000908 memcpy(pdp[n]->gsnlu.v, &listen_, 4);
jjako52c24142002-12-16 13:33:51 +0000909
910 if (msisdn.l > sizeof(pdp[n]->msisdn.v)) {
911 exit(1);
912 }
913 else {
914 pdp[n]->msisdn.l = msisdn.l;
915 memcpy(pdp[n]->msisdn.v, msisdn.v, msisdn.l);
916 }
917
918 ipv42eua(&pdp[n]->eua, NULL); /* Request dynamic IP address */
919
920 if (pco.l > sizeof(pdp[n]->pco_req.v)) {
921 exit(1);
922 }
923 else {
924 pdp[n]->pco_req.l = pco.l;
925 memcpy(pdp[n]->pco_req.v, pco.v, pco.l);
926 }
927
928 /* Create context */
929 /* We send this of once. Retransmissions are handled by gtplib */
930 if (gtpfd != -1) gtp_create_context(gsn, pdp[n], NULL, &remote);
931 }
932
933 state = 1; /* Enter wait_connection state */
934
935 printf("Waiting for response from ggsn........\n\n");
936
jjako5da68452003-01-28 16:08:47 +0000937
jjako52c24142002-12-16 13:33:51 +0000938 /******************************************************************/
939 /* Main select loop */
940 /******************************************************************/
941
jjako5da68452003-01-28 16:08:47 +0000942 while ((((starttime + timelimit + 10) > time(NULL))
943 || (0 == timelimit)) && (state!=0)) {
jjako52c24142002-12-16 13:33:51 +0000944
945 /* Take down client connections at some stage */
946 if (((starttime + timelimit) <= time(NULL)) && (0 != timelimit) && (2 == state)) {
947 state = 3;
948 for(n=0; n<contexts; n++) {
949 /* Delete context */
950 printf("Disconnecting PDP context #%d\n", n);
951 if (gtpfd != -1) gtp_delete_context(gsn, pdp[n], NULL);
jjako5da68452003-01-28 16:08:47 +0000952 if ((pinghost.s_addr !=0) && ntransmitted) ping_finish();
jjako52c24142002-12-16 13:33:51 +0000953 }
jjako5da68452003-01-28 16:08:47 +0000954}
955
956
957 /* Ping */
958 while ((2 == state) && (pinghost.s_addr !=0) &&
959 ((pingseq < pingcount) || (pingcount == 0)) &&
960 (starttime + pingseq/pingrate) <= time(NULL)) {
961 create_ping(gsn, pdp[pingseq % contexts],
962 &pinghost, pingseq++, pingsize);
jjako52c24142002-12-16 13:33:51 +0000963 }
964
jjako5da68452003-01-28 16:08:47 +0000965 if (ntransmitted && pingcount && nreceived >= pingcount)
966 ping_finish();
967
968
jjako52c24142002-12-16 13:33:51 +0000969 FD_ZERO(&fds);
970 if (tun_fd1 != -1) FD_SET(tun_fd1, &fds);
971 if (tun_fd2 != -1) FD_SET(tun_fd2, &fds);
972 if (gtpfd != -1) FD_SET(gtpfd, &fds);
973
974 gtp_retranstimeout(gsn, &idleTime);
975
jjako5da68452003-01-28 16:08:47 +0000976 if ((pinghost.s_addr !=0) &&
977 ((idleTime.tv_sec !=0) || (idleTime.tv_usec !=0))) {
978 idleTime.tv_sec = 0;
979 idleTime.tv_usec = 1000000 / pingrate;
980 }
981
jjako52c24142002-12-16 13:33:51 +0000982 switch (select(maxfd + 1, &fds, NULL, NULL, &idleTime)) {
983 case -1:
984 syslog(LOG_ERR, "sgsnemu: select = -1");
985 break;
986 case 0:
987 gtp_retrans(gsn); /* Only retransmit if nothing else */
988 break;
989 default:
990 break;
991 }
992
993 if (tun_fd1 != -1 &&
994 FD_ISSET(tun_fd1, &fds) &&
995 tun_decaps(tun1, encaps_gtp_client, gsn) < 0) {
996 syslog(LOG_ERR, "TUN read failed (fd)=(%d)", tun_fd1);
997 }
998
999 if (tun_fd2 != -1 &&
1000 FD_ISSET(tun_fd2, &fds) &&
1001 tun_decaps(tun2, encaps_gtp_client, gsn) < 0) {
1002 syslog(LOG_ERR, "TUN read failed (fd)=(%d)", tun_fd2);
1003 }
1004
1005 if (gtpfd != -1 && FD_ISSET(gtpfd, &fds) &&
1006 gtp_decaps(gsn) < 0) {
jjako5da68452003-01-28 16:08:47 +00001007 syslog(LOG_ERR, "GTP read failed (gtpfd)=(%d)", gtpfd);
jjako52c24142002-12-16 13:33:51 +00001008 }
1009
1010
jjako5da68452003-01-28 16:08:47 +00001011 }
jjako52c24142002-12-16 13:33:51 +00001012
1013 gtp_free(gsn); /* Clean up the gsn instance */
1014
jjako5da68452003-01-28 16:08:47 +00001015 return 0;
jjako52c24142002-12-16 13:33:51 +00001016
1017}
1018