⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sgsnemu.c

📁 NGN-3G核心部件SGSN的代码实现
💻 C
📖 第 1 页 / 共 3 页
字号:
/* 
 *  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 + -