📄 sgsnemu.c
字号:
/*
* OpenGGSN - Gateway GPRS Support Node
* Copyright (C) 2002, 2003, 2004 Mondru AB.
*
* The contents of this file may be used under the terms of the GNU
* General Public License Version 2, provided that the above copyright
* notice and this permission notice is included in all copies or
* substantial portions of the software.
*
*/
/*
* sgsnemu.c
*
*/
#ifdef __linux__
#define _GNU_SOURCE 1 /* strdup() prototype, broken arpa/inet.h */
#endif
#include <syslog.h>
#include <ctype.h>
#include <netdb.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <net/if.h>
#include <errno.h>
#include <sys/socket.h>
#include <resolv.h>
#include <time.h>
#include "config.h"
#include "tun.h"
#include "ippool.h"
#include "syserr.h"
#include "../gtp/pdp.h"
#include "../gtp/gtp.h"
#include "cmdline.h"
#define IPADDRLEN 256 /* Character length of addresses */
#define MAXCONTEXTS 1024 /* Max number of allowed contexts */
/* HASH tables for IP address allocation */
struct iphash_t {
uint8_t inuse; /* 0=free. 1=used by somebody */
struct iphash_t *ipnext;
struct pdp_t *pdp;
struct in_addr addr;
};
struct iphash_t iparr[MAXCONTEXTS];
struct iphash_t *iphash[MAXCONTEXTS];
/* State variable used for ping */
/* 0: Idle */
/* 1: Wait_connect */
/* 2: Connected */
/* 3: Done */
/* 4: Wait_disconnect */
/* 5: Disconnected */
int state = 0;
struct gsn_t *gsn = NULL; /* GSN instance */
struct tun_t *tun = NULL; /* TUN instance */
int maxfd = 0; /* For select() */
int echoversion = 1; /* First try this version */
/* Struct with local versions of gengetopt options */
struct {
int debug; /* Print debug messages */
int createif; /* Create local network interface */
struct in_addr netaddr, destaddr, net, mask; /* Network interface */
char *ipup, *ipdown; /* Filename of scripts */
int defaultroute; /* Set up default route */
struct in_addr pinghost; /* Remote ping host */
int pingrate;
int pingsize;
int pingcount;
int pingquiet;
struct in_addr listen;
struct in_addr remote;
struct in_addr dns;
int contexts; /* Number of contexts to create */
int timelimit; /* Number of seconds to be connected */
char *statedir;
uint64_t imsi;
uint8_t nsapi;
int gtpversion;
struct ul255_t pco;
struct ul255_t qos;
uint16_t cch;
struct ul255_t apn;
uint8_t selmode;
struct ul16_t msisdn;
} options;
/* Definitions to use for PING. Most of the ping code was derived from */
/* the original ping program by Mike Muuss */
/* IP header and ICMP echo header */
#define CREATEPING_MAX 2048
#define CREATEPING_IP 20
#define CREATEPING_ICMP 8
struct ip_ping {
uint8_t ipver; /* Type and header length*/
uint8_t tos; /* Type of Service */
uint16_t length; /* Total length */
uint16_t fragid; /* Identifier */
uint16_t offset; /* Flags and fragment offset */
uint8_t ttl; /* Time to live */
uint8_t protocol; /* Protocol */
uint16_t ipcheck; /* Header checksum */
uint32_t src; /* Source address */
uint32_t dst; /* Destination */
uint8_t type; /* Type and header length*/
uint8_t code; /* Code */
uint16_t checksum; /* Header checksum */
uint16_t ident; /* Identifier */
uint16_t seq; /* Sequence number */
uint8_t data[CREATEPING_MAX]; /* Data */
} __attribute__((packed));
/* Statistical values for ping */
int nreceived = 0;
int ntreceived = 0;
int ntransmitted = 0;
int tmin = 999999999;
int tmax = 0;
int tsum = 0;
int pingseq = 0; /* Ping sequence counter */
struct timeval firstping;
int ipset(struct iphash_t *ipaddr, struct in_addr *addr) {
int hash = ippool_hash4(addr) % MAXCONTEXTS;
struct iphash_t *h;
struct iphash_t *prev = NULL;
ipaddr->ipnext = NULL;
ipaddr->addr.s_addr = addr->s_addr;
for (h = iphash[hash]; h; h = h->ipnext)
prev = h;
if (!prev)
iphash[hash] = ipaddr;
else
prev->ipnext = ipaddr;
return 0;
}
int ipdel(struct iphash_t *ipaddr) {
int hash = ippool_hash4(&ipaddr->addr) % MAXCONTEXTS;
struct iphash_t *h;
struct iphash_t *prev = NULL;
for (h = iphash[hash]; h; h = h->ipnext) {
if (h == ipaddr) {
if (!prev)
iphash[hash] = h->ipnext;
else
prev->ipnext = h->ipnext;
return 0;
}
prev = h;
}
return EOF; /* End of linked list and not found */
}
int ipget(struct iphash_t **ipaddr, struct in_addr *addr) {
int hash = ippool_hash4(addr) % MAXCONTEXTS;
struct iphash_t *h;
for (h = iphash[hash]; h; h = h->ipnext) {
if ((h->addr.s_addr == addr->s_addr)) {
*ipaddr = h;
return 0;
}
}
return EOF; /* End of linked list and not found */
}
/* Used to write process ID to file. Assume someone else will delete */
void log_pid(char *pidfile) {
FILE *file;
mode_t oldmask;
oldmask = umask(022);
file = fopen(pidfile, "w");
umask(oldmask);
if(!file)
return;
fprintf(file, "%d\n", (int) getpid());
fclose(file);
}
int process_options(int argc, char **argv) {
/* gengeopt declarations */
struct gengetopt_args_info args_info;
struct hostent *host;
int n;
if (cmdline_parser (argc, argv, &args_info) != 0)
return -1;
if (args_info.debug_flag) {
if (args_info.remote_arg) printf("remote: %s\n", args_info.remote_arg);
if (args_info.listen_arg) printf("listen: %s\n", args_info.listen_arg);
if (args_info.conf_arg) printf("conf: %s\n", args_info.conf_arg);
printf("debug: %d\n", args_info.debug_flag);
if (args_info.imsi_arg) printf("imsi: %s\n", args_info.imsi_arg);
printf("qos: %#08x\n", args_info.qos_arg);
printf("charging: %#04x\n", args_info.charging_arg);
if (args_info.apn_arg) printf("apn: %s\n", args_info.apn_arg);
if (args_info.msisdn_arg) printf("msisdn: %s\n", args_info.msisdn_arg);
if (args_info.uid_arg) printf("uid: %s\n", args_info.uid_arg);
if (args_info.pwd_arg) printf("pwd: %s\n", args_info.pwd_arg);
if (args_info.pidfile_arg) printf("pidfile: %s\n", args_info.pidfile_arg);
if (args_info.statedir_arg) printf("statedir: %s\n", args_info.statedir_arg);
if (args_info.dns_arg) printf("dns: %s\n", args_info.dns_arg);
printf("contexts: %d\n", args_info.contexts_arg);
printf("timelimit: %d\n", args_info.timelimit_arg);
printf("createif: %d\n", args_info.createif_flag);
if (args_info.ipup_arg) printf("ipup: %s\n", args_info.ipup_arg);
if (args_info.ipdown_arg) printf("ipdown: %s\n", args_info.ipdown_arg);
printf("defaultroute: %d\n", args_info.defaultroute_flag);
if (args_info.pinghost_arg) printf("pinghost: %s\n", args_info.pinghost_arg);
printf("pingrate: %d\n", args_info.pingrate_arg);
printf("pingsize: %d\n", args_info.pingsize_arg);
printf("pingcount: %d\n", args_info.pingcount_arg);
printf("pingquiet: %d\n", args_info.pingquiet_flag);
}
/* Try out our new parser */
if (args_info.conf_arg) {
if (cmdline_parser_configfile (args_info.conf_arg, &args_info, 0) != 0)
return -1;
if (args_info.debug_flag) {
printf("cmdline_parser_configfile\n");
if (args_info.remote_arg) printf("remote: %s\n", args_info.remote_arg);
if (args_info.listen_arg) printf("listen: %s\n", args_info.listen_arg);
if (args_info.conf_arg) printf("conf: %s\n", args_info.conf_arg);
printf("debug: %d\n", args_info.debug_flag);
if (args_info.imsi_arg) printf("imsi: %s\n", args_info.imsi_arg);
printf("qos: %#08x\n", args_info.qos_arg);
printf("charging: %#04x\n", args_info.charging_arg);
if (args_info.apn_arg) printf("apn: %s\n", args_info.apn_arg);
if (args_info.msisdn_arg) printf("msisdn: %s\n", args_info.msisdn_arg);
if (args_info.uid_arg) printf("uid: %s\n", args_info.uid_arg);
if (args_info.pwd_arg) printf("pwd: %s\n", args_info.pwd_arg);
if (args_info.pidfile_arg) printf("pidfile: %s\n", args_info.pidfile_arg);
if (args_info.statedir_arg) printf("statedir: %s\n", args_info.statedir_arg);
if (args_info.dns_arg) printf("dns: %s\n", args_info.dns_arg);
printf("contexts: %d\n", args_info.contexts_arg);
printf("timelimit: %d\n", args_info.timelimit_arg);
printf("createif: %d\n", args_info.createif_flag);
if (args_info.ipup_arg) printf("ipup: %s\n", args_info.ipup_arg);
if (args_info.ipdown_arg) printf("ipdown: %s\n", args_info.ipdown_arg);
printf("defaultroute: %d\n", args_info.defaultroute_flag);
if (args_info.pinghost_arg) printf("pinghost: %s\n", args_info.pinghost_arg);
printf("pingrate: %d\n", args_info.pingrate_arg);
printf("pingsize: %d\n", args_info.pingsize_arg);
printf("pingcount: %d\n", args_info.pingcount_arg);
printf("pingquiet: %d\n", args_info.pingquiet_flag);
}
}
/* Handle each option */
/* foreground */
/* If fg flag not given run as a daemon */
/* Do not allow sgsnemu to run as deamon
if (!args_info.fg_flag)
{
closelog();
freopen("/dev/null", "w", stdout);
freopen("/dev/null", "w", stderr);
freopen("/dev/null", "r", stdin);
daemon(0, 0);
openlog(PACKAGE, LOG_PID, LOG_DAEMON);
} */
/* debug */
options.debug = args_info.debug_flag;
/* pidfile */
/* This has to be done after we have our final pid */
if (args_info.pidfile_arg) {
log_pid(args_info.pidfile_arg);
}
/* dns */
/* If no dns option is given use system default */
/* Do hostname lookup to translate hostname to IP address */
printf("\n");
if (args_info.dns_arg) {
if (!(host = gethostbyname(args_info.dns_arg))) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"Invalid DNS address: %s!", args_info.dns_arg);
return -1;
}
else {
memcpy(&options.dns.s_addr, host->h_addr, host->h_length);
_res.nscount = 1;
_res.nsaddr_list[0].sin_addr = options.dns;
printf("Using DNS server: %s (%s)\n",
args_info.dns_arg, inet_ntoa(options.dns));
}
}
else {
options.dns.s_addr= 0;
printf("Using default DNS server\n");
}
/* listen */
/* If no listen option is specified listen to any local port */
/* Do hostname lookup to translate hostname to IP address */
if (args_info.listen_arg) {
if (!(host = gethostbyname(args_info.listen_arg))) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"Invalid listening address: %s!", args_info.listen_arg);
return -1;
}
else {
memcpy(&options.listen.s_addr, host->h_addr, host->h_length);
printf("Local IP address is: %s (%s)\n",
args_info.listen_arg, inet_ntoa(options.listen));
}
}
else {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"Listening address must be specified: %s!", args_info.listen_arg);
return -1;
}
/* remote */
/* If no remote option is specified terminate */
/* Do hostname lookup to translate hostname to IP address */
if (args_info.remote_arg) {
if (!(host = gethostbyname(args_info.remote_arg))) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"Invalid remote address: %s!", args_info.remote_arg);
return -1;
}
else {
memcpy(&options.remote.s_addr, host->h_addr, host->h_length);
printf("Remote IP address is: %s (%s)\n",
args_info.remote_arg, inet_ntoa(options.remote));
}
}
else {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"No remote address given!");
return -1;
}
/* imsi */
if (strlen(args_info.imsi_arg)!=15) {
printf("Invalid IMSI\n");
return -1;
}
options.imsi = 0xf000000000000000ull;
options.imsi |= ((uint64_t) (args_info.imsi_arg[ 0]-48));
options.imsi |= ((uint64_t) (args_info.imsi_arg[ 1]-48)) << 4;
options.imsi |= ((uint64_t) (args_info.imsi_arg[ 2]-48)) << 8;
options.imsi |= ((uint64_t) (args_info.imsi_arg[ 3]-48)) << 12;
options.imsi |= ((uint64_t) (args_info.imsi_arg[ 4]-48)) << 16;
options.imsi |= ((uint64_t) (args_info.imsi_arg[ 5]-48)) << 20;
options.imsi |= ((uint64_t) (args_info.imsi_arg[ 6]-48)) << 24;
options.imsi |= ((uint64_t) (args_info.imsi_arg[ 7]-48)) << 28;
options.imsi |= ((uint64_t) (args_info.imsi_arg[ 8]-48)) << 32;
options.imsi |= ((uint64_t) (args_info.imsi_arg[ 9]-48)) << 36;
options.imsi |= ((uint64_t) (args_info.imsi_arg[10]-48)) << 40;
options.imsi |= ((uint64_t) (args_info.imsi_arg[11]-48)) << 44;
options.imsi |= ((uint64_t) (args_info.imsi_arg[12]-48)) << 48;
options.imsi |= ((uint64_t) (args_info.imsi_arg[13]-48)) << 52;
options.imsi |= ((uint64_t) (args_info.imsi_arg[14]-48)) << 56;
printf("IMSI is: %s (%#08llx)\n",
args_info.imsi_arg, options.imsi);
/* nsapi */
if ((args_info.nsapi_arg > 15) ||
(args_info.nsapi_arg < 0)) {
printf("Invalid NSAPI\n");
return -1;
}
options.nsapi = args_info.nsapi_arg;
printf("Using NSAPI: %d\n", args_info.nsapi_arg);
/* qos */
options.qos.l = 3;
options.qos.v[2] = (args_info.qos_arg) & 0xff;
options.qos.v[1] = ((args_info.qos_arg) >> 8) & 0xff;
options.qos.v[0] = ((args_info.qos_arg) >> 16) & 0xff;
/* charging */
options.cch = args_info.charging_arg;
/* contexts */
if (args_info.contexts_arg > MAXCONTEXTS) {
printf("Contexts has to be less than %d\n", MAXCONTEXTS);
return -1;
}
options.contexts = args_info.contexts_arg;
/* Timelimit */
options.timelimit = args_info.timelimit_arg;
/* gtpversion */
if ((args_info.gtpversion_arg > 1) ||
(args_info.gtpversion_arg < 0)) {
printf("Invalid GTP version\n");
return -1;
}
options.gtpversion = args_info.gtpversion_arg;
printf("Using GTP version: %d\n", args_info.gtpversion_arg);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -