9
0
Fork 0

Convert all code to Linux coding style

After so many years of silence, we don't expect the original author to
return to the project.  To make things a bit simpler for us, we convert
the coding style to what we are used to (Linux style).

The conversion was made using the 'Lindent' script which is part of the
Linux kernel.
This commit is contained in:
Harald Welte 2011-11-02 13:06:18 +01:00
parent ca36f29364
commit bed35df298
27 changed files with 10990 additions and 10338 deletions

File diff suppressed because it is too large Load Diff

View File

@ -12,7 +12,7 @@
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#ifndef CMDLINE_PARSER_PACKAGE
#define CMDLINE_PARSER_PACKAGE PACKAGE
@ -22,105 +22,104 @@ extern "C" {
#define CMDLINE_PARSER_VERSION VERSION
#endif
struct gengetopt_args_info
{
const char *help_help; /* Print help and exit help description. */
const char *version_help; /* Print version and exit help description. */
int fg_flag; /* Run in foreground (default=off). */
const char *fg_help; /* Run in foreground help description. */
int debug_flag; /* Run in debug mode (default=off). */
const char *debug_help; /* Run in debug mode help description. */
char * conf_arg; /* Read configuration file (default='/etc/ggsn.conf'). */
char * conf_orig; /* Read configuration file original value given at command line. */
const char *conf_help; /* Read configuration file help description. */
char * pidfile_arg; /* Filename of process id file (default='/var/run/ggsn.pid'). */
char * pidfile_orig; /* Filename of process id file original value given at command line. */
const char *pidfile_help; /* Filename of process id file help description. */
char * statedir_arg; /* Directory of nonvolatile data (default='/var/lib/ggsn/'). */
char * statedir_orig; /* Directory of nonvolatile data original value given at command line. */
const char *statedir_help; /* Directory of nonvolatile data help description. */
char * listen_arg; /* Local interface. */
char * listen_orig; /* Local interface original value given at command line. */
const char *listen_help; /* Local interface help description. */
char * net_arg; /* Network (default='192.168.0.0/24'). */
char * net_orig; /* Network original value given at command line. */
const char *net_help; /* Network help description. */
char * ipup_arg; /* Script to run after link-up. */
char * ipup_orig; /* Script to run after link-up original value given at command line. */
const char *ipup_help; /* Script to run after link-up help description. */
char * ipdown_arg; /* Script to run after link-down. */
char * ipdown_orig; /* Script to run after link-down original value given at command line. */
const char *ipdown_help; /* Script to run after link-down help description. */
char * dynip_arg; /* Dynamic IP address pool. */
char * dynip_orig; /* Dynamic IP address pool original value given at command line. */
const char *dynip_help; /* Dynamic IP address pool help description. */
char * statip_arg; /* Static IP address pool. */
char * statip_orig; /* Static IP address pool original value given at command line. */
const char *statip_help; /* Static IP address pool help description. */
char * pcodns1_arg; /* PCO DNS Server 1 (default='0.0.0.0'). */
char * pcodns1_orig; /* PCO DNS Server 1 original value given at command line. */
const char *pcodns1_help; /* PCO DNS Server 1 help description. */
char * pcodns2_arg; /* PCO DNS Server 2 (default='0.0.0.0'). */
char * pcodns2_orig; /* PCO DNS Server 2 original value given at command line. */
const char *pcodns2_help; /* PCO DNS Server 2 help description. */
int timelimit_arg; /* Exit after timelimit seconds (default='0'). */
char * timelimit_orig; /* Exit after timelimit seconds original value given at command line. */
const char *timelimit_help; /* Exit after timelimit seconds help description. */
char * apn_arg; /* Access point name (default='internet'). */
char * apn_orig; /* Access point name original value given at command line. */
const char *apn_help; /* Access point name help description. */
int qos_arg; /* Requested quality of service (default='0x0b921f'). */
char * qos_orig; /* Requested quality of service original value given at command line. */
const char *qos_help; /* Requested quality of service help description. */
int help_given ; /* Whether help was given. */
int version_given ; /* Whether version was given. */
int fg_given ; /* Whether fg was given. */
int debug_given ; /* Whether debug was given. */
int conf_given ; /* Whether conf was given. */
int pidfile_given ; /* Whether pidfile was given. */
int statedir_given ; /* Whether statedir was given. */
int listen_given ; /* Whether listen was given. */
int net_given ; /* Whether net was given. */
int ipup_given ; /* Whether ipup was given. */
int ipdown_given ; /* Whether ipdown was given. */
int dynip_given ; /* Whether dynip was given. */
int statip_given ; /* Whether statip was given. */
int pcodns1_given ; /* Whether pcodns1 was given. */
int pcodns2_given ; /* Whether pcodns2 was given. */
int timelimit_given ; /* Whether timelimit was given. */
int apn_given ; /* Whether apn was given. */
int qos_given ; /* Whether qos was given. */
struct gengetopt_args_info {
const char *help_help; /* Print help and exit help description. */
const char *version_help; /* Print version and exit help description. */
int fg_flag; /* Run in foreground (default=off). */
const char *fg_help; /* Run in foreground help description. */
int debug_flag; /* Run in debug mode (default=off). */
const char *debug_help; /* Run in debug mode help description. */
char *conf_arg; /* Read configuration file (default='/etc/ggsn.conf'). */
char *conf_orig; /* Read configuration file original value given at command line. */
const char *conf_help; /* Read configuration file help description. */
char *pidfile_arg; /* Filename of process id file (default='/var/run/ggsn.pid'). */
char *pidfile_orig; /* Filename of process id file original value given at command line. */
const char *pidfile_help; /* Filename of process id file help description. */
char *statedir_arg; /* Directory of nonvolatile data (default='/var/lib/ggsn/'). */
char *statedir_orig; /* Directory of nonvolatile data original value given at command line. */
const char *statedir_help; /* Directory of nonvolatile data help description. */
char *listen_arg; /* Local interface. */
char *listen_orig; /* Local interface original value given at command line. */
const char *listen_help; /* Local interface help description. */
char *net_arg; /* Network (default='192.168.0.0/24'). */
char *net_orig; /* Network original value given at command line. */
const char *net_help; /* Network help description. */
char *ipup_arg; /* Script to run after link-up. */
char *ipup_orig; /* Script to run after link-up original value given at command line. */
const char *ipup_help; /* Script to run after link-up help description. */
char *ipdown_arg; /* Script to run after link-down. */
char *ipdown_orig; /* Script to run after link-down original value given at command line. */
const char *ipdown_help; /* Script to run after link-down help description. */
char *dynip_arg; /* Dynamic IP address pool. */
char *dynip_orig; /* Dynamic IP address pool original value given at command line. */
const char *dynip_help; /* Dynamic IP address pool help description. */
char *statip_arg; /* Static IP address pool. */
char *statip_orig; /* Static IP address pool original value given at command line. */
const char *statip_help; /* Static IP address pool help description. */
char *pcodns1_arg; /* PCO DNS Server 1 (default='0.0.0.0'). */
char *pcodns1_orig; /* PCO DNS Server 1 original value given at command line. */
const char *pcodns1_help; /* PCO DNS Server 1 help description. */
char *pcodns2_arg; /* PCO DNS Server 2 (default='0.0.0.0'). */
char *pcodns2_orig; /* PCO DNS Server 2 original value given at command line. */
const char *pcodns2_help; /* PCO DNS Server 2 help description. */
int timelimit_arg; /* Exit after timelimit seconds (default='0'). */
char *timelimit_orig; /* Exit after timelimit seconds original value given at command line. */
const char *timelimit_help; /* Exit after timelimit seconds help description. */
char *apn_arg; /* Access point name (default='internet'). */
char *apn_orig; /* Access point name original value given at command line. */
const char *apn_help; /* Access point name help description. */
int qos_arg; /* Requested quality of service (default='0x0b921f'). */
char *qos_orig; /* Requested quality of service original value given at command line. */
const char *qos_help; /* Requested quality of service help description. */
} ;
int help_given; /* Whether help was given. */
int version_given; /* Whether version was given. */
int fg_given; /* Whether fg was given. */
int debug_given; /* Whether debug was given. */
int conf_given; /* Whether conf was given. */
int pidfile_given; /* Whether pidfile was given. */
int statedir_given; /* Whether statedir was given. */
int listen_given; /* Whether listen was given. */
int net_given; /* Whether net was given. */
int ipup_given; /* Whether ipup was given. */
int ipdown_given; /* Whether ipdown was given. */
int dynip_given; /* Whether dynip was given. */
int statip_given; /* Whether statip was given. */
int pcodns1_given; /* Whether pcodns1 was given. */
int pcodns2_given; /* Whether pcodns2 was given. */
int timelimit_given; /* Whether timelimit was given. */
int apn_given; /* Whether apn was given. */
int qos_given; /* Whether qos was given. */
extern const char *gengetopt_args_info_purpose;
extern const char *gengetopt_args_info_usage;
extern const char *gengetopt_args_info_help[];
};
int cmdline_parser (int argc, char * const *argv,
struct gengetopt_args_info *args_info);
int cmdline_parser2 (int argc, char * const *argv,
struct gengetopt_args_info *args_info,
int override, int initialize, int check_required);
int cmdline_parser_file_save(const char *filename,
struct gengetopt_args_info *args_info);
extern const char *gengetopt_args_info_purpose;
extern const char *gengetopt_args_info_usage;
extern const char *gengetopt_args_info_help[];
void cmdline_parser_print_help(void);
void cmdline_parser_print_version(void);
int cmdline_parser(int argc, char *const *argv,
struct gengetopt_args_info *args_info);
int cmdline_parser2(int argc, char *const *argv,
struct gengetopt_args_info *args_info,
int override, int initialize, int check_required);
int cmdline_parser_file_save(const char *filename,
struct gengetopt_args_info *args_info);
void cmdline_parser_init (struct gengetopt_args_info *args_info);
void cmdline_parser_free (struct gengetopt_args_info *args_info);
void cmdline_parser_print_help(void);
void cmdline_parser_print_version(void);
int cmdline_parser_configfile (char * const filename,
struct gengetopt_args_info *args_info,
int override, int initialize, int check_required);
void cmdline_parser_init(struct gengetopt_args_info *args_info);
void cmdline_parser_free(struct gengetopt_args_info *args_info);
int cmdline_parser_required (struct gengetopt_args_info *args_info,
const char *prog_name);
int cmdline_parser_configfile(char *const filename,
struct gengetopt_args_info *args_info,
int override, int initialize,
int check_required);
int cmdline_parser_required(struct gengetopt_args_info *args_info,
const char *prog_name);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* CMDLINE_H */
#endif /* __cplusplus */
#endif /* CMDLINE_H */

View File

@ -39,7 +39,7 @@
#include <fcntl.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
@ -55,507 +55,539 @@
#include "cmdline.h"
int end = 0;
int maxfd = 0; /* For select() */
int maxfd = 0; /* For select() */
struct in_addr listen_;
struct in_addr netaddr, destaddr, net, mask; /* Network interface */
struct in_addr dns1, dns2; /* PCO DNS address */
char *ipup, *ipdown; /* Filename of scripts */
int debug; /* Print debug output */
struct in_addr netaddr, destaddr, net, mask; /* Network interface */
struct in_addr dns1, dns2; /* PCO DNS address */
char *ipup, *ipdown; /* Filename of scripts */
int debug; /* Print debug output */
struct ul255_t pco;
struct ul255_t qos;
struct ul255_t apn;
struct gsn_t *gsn; /* GSN instance */
struct tun_t *tun; /* TUN instance */
struct ippool_t *ippool; /* Pool of IP addresses */
struct gsn_t *gsn; /* GSN instance */
struct tun_t *tun; /* TUN instance */
struct ippool_t *ippool; /* Pool of IP addresses */
/* To exit gracefully. Used with GCC compilation flag -pg and gprof */
void signal_handler(int s) {
if (debug) printf("Received signal %d, exiting.\n", s);
end = 1;
void signal_handler(int s)
{
if (debug)
printf("Received signal %d, exiting.\n", s);
end = 1;
}
/* 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) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"Failed to create process ID file: %s!", pidfile);
return;
}
fprintf(file, "%d\n", (int) getpid());
fclose(file);
void log_pid(char *pidfile)
{
FILE *file;
mode_t oldmask;
oldmask = umask(022);
file = fopen(pidfile, "w");
umask(oldmask);
if (!file) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"Failed to create process ID file: %s!", pidfile);
return;
}
fprintf(file, "%d\n", (int)getpid());
fclose(file);
}
#if defined(__sun__)
int daemon(int nochdir, int noclose) {
int fd;
int daemon(int nochdir, int noclose)
{
int fd;
switch (fork()) {
case -1:
return (-1);
case 0:
break;
default:
_exit(0);
}
switch (fork()) {
case -1:
return (-1);
case 0:
break;
default:
_exit(0);
}
if (setsid() == -1)
return (-1);
if (!nochdir) chdir("/");
if (setsid() == -1)
return (-1);
if (!noclose && (fd = open("/dev/null", O_RDWR, 0)) != -1) {
dup2(fd, STDIN_FILENO);
dup2(fd, STDOUT_FILENO);
dup2(fd, STDERR_FILENO);
if (fd > 2) close (fd);
}
return (0);
if (!nochdir)
chdir("/");
if (!noclose && (fd = open("/dev/null", O_RDWR, 0)) != -1) {
dup2(fd, STDIN_FILENO);
dup2(fd, STDOUT_FILENO);
dup2(fd, STDERR_FILENO);
if (fd > 2)
close(fd);
}
return (0);
}
#endif
int encaps_printf(void *p, void *packet, unsigned len)
{
unsigned int i;
if (debug) {
printf("The packet looks like this:\n");
for( i=0; i<len; i++) {
printf("%02x ", (unsigned char)*(char *)(packet+i));
if (!((i+1)%16)) printf("\n");
};
printf("\n");
}
return 0;
unsigned int i;
if (debug) {
printf("The packet looks like this:\n");
for (i = 0; i < len; i++) {
printf("%02x ", (unsigned char)*(char *)(packet + i));
if (!((i + 1) % 16))
printf("\n");
};
printf("\n");
}
return 0;
}
int delete_context(struct pdp_t *pdp) {
if (debug) printf("Deleting PDP context\n");
if (pdp->peer)
ippool_freeip(ippool, (struct ippoolm_t *) pdp->peer);
else
sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Peer not defined!");
return 0;
int delete_context(struct pdp_t *pdp)
{
if (debug)
printf("Deleting PDP context\n");
if (pdp->peer)
ippool_freeip(ippool, (struct ippoolm_t *)pdp->peer);
else
sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Peer not defined!");
return 0;
}
int create_context_ind(struct pdp_t *pdp)
{
struct in_addr addr;
struct ippoolm_t *member;
int create_context_ind(struct pdp_t *pdp) {
struct in_addr addr;
struct ippoolm_t *member;
if (debug)
printf("Received create PDP context request\n");
if (debug) printf("Received create PDP context request\n");
pdp->eua.l = 0; /* TODO: Indicates dynamic IP */
pdp->eua.l=0; /* TODO: Indicates dynamic IP */
/* ulcpy(&pdp->qos_neg, &pdp->qos_req, sizeof(pdp->qos_req.v)); */
memcpy(pdp->qos_neg0, pdp->qos_req0, sizeof(pdp->qos_req0));
memcpy(&pdp->pco_neg, &pco, sizeof(pdp->pco_neg));
/* ulcpy(&pdp->qos_neg, &pdp->qos_req, sizeof(pdp->qos_req.v)); */
memcpy(pdp->qos_neg0, pdp->qos_req0, sizeof(pdp->qos_req0));
memcpy(&pdp->pco_neg, &pco, sizeof(pdp->pco_neg));
memcpy(pdp->qos_neg.v, pdp->qos_req.v, pdp->qos_req.l); /* TODO */
pdp->qos_neg.l = pdp->qos_req.l;
memcpy(pdp->qos_neg.v, pdp->qos_req.v, pdp->qos_req.l); /* TODO */
pdp->qos_neg.l = pdp->qos_req.l;
if (pdp_euaton(&pdp->eua, &addr)) {
addr.s_addr = 0; /* Request dynamic */
}
if (pdp_euaton(&pdp->eua, &addr)) {
addr.s_addr = 0; /* Request dynamic */
}
if (ippool_newip(ippool, &member, &addr, 0)) {
gtp_create_context_resp(gsn, pdp, GTPCAUSE_NO_RESOURCES);
return 0; /* Allready in use, or no more available */
}
if (ippool_newip(ippool, &member, &addr, 0)) {
gtp_create_context_resp(gsn, pdp, GTPCAUSE_NO_RESOURCES);
return 0; /* Allready in use, or no more available */
}
pdp_ntoeua(&member->addr, &pdp->eua);
pdp->peer = member;
pdp->ipif = tun; /* TODO */
member->peer = pdp;
pdp_ntoeua(&member->addr, &pdp->eua);
pdp->peer = member;
pdp->ipif = tun; /* TODO */
member->peer = pdp;
gtp_create_context_resp(gsn, pdp, GTPCAUSE_ACC_REQ);
return 0; /* Success */
gtp_create_context_resp(gsn, pdp, GTPCAUSE_ACC_REQ);
return 0; /* Success */
}
/* Callback for receiving messages from tun */
int cb_tun_ind(struct tun_t *tun, void *pack, unsigned len) {
struct ippoolm_t *ipm;
struct in_addr dst;
struct tun_packet_t *iph = (struct tun_packet_t*) pack;
dst.s_addr = iph->dst;
int cb_tun_ind(struct tun_t *tun, void *pack, unsigned len)
{
struct ippoolm_t *ipm;
struct in_addr dst;
struct tun_packet_t *iph = (struct tun_packet_t *)pack;
if (debug) printf("Received packet from tun!\n");
dst.s_addr = iph->dst;
if (ippool_getip(ippool, &ipm, &dst)) {
if (debug) printf("Received packet with no destination!!!\n");
return 0;
}
if (ipm->peer) /* Check if a peer protocol is defined */
gtp_data_req(gsn, (struct pdp_t*) ipm->peer, pack, len);
return 0;
if (debug)
printf("Received packet from tun!\n");
if (ippool_getip(ippool, &ipm, &dst)) {
if (debug)
printf("Received packet with no destination!!!\n");
return 0;
}
if (ipm->peer) /* Check if a peer protocol is defined */
gtp_data_req(gsn, (struct pdp_t *)ipm->peer, pack, len);
return 0;
}
int encaps_tun(struct pdp_t *pdp, void *pack, unsigned len) {
if (debug) printf("encaps_tun. Packet received: forwarding to tun\n");
return tun_encaps((struct tun_t*) pdp->ipif, pack, len);
int encaps_tun(struct pdp_t *pdp, void *pack, unsigned len)
{
if (debug)
printf("encaps_tun. Packet received: forwarding to tun\n");
return tun_encaps((struct tun_t *)pdp->ipif, pack, len);
}
int main(int argc, char **argv)
{
/* gengeopt declarations */
struct gengetopt_args_info args_info;
/* gengeopt declarations */
struct gengetopt_args_info args_info;
struct hostent *host;
struct hostent *host;
/* Handle keyboard interrupt SIGINT */
struct sigaction s;
s.sa_handler = (void *) signal_handler;
if ((0 != sigemptyset( &s.sa_mask )) && debug)
printf("sigemptyset failed.\n");
s.sa_flags = SA_RESETHAND;
if ((sigaction(SIGINT, &s, NULL) != 0) && debug)
printf("Could not register SIGINT signal handler.\n");
fd_set fds; /* For select() */
struct timeval idleTime; /* How long to select() */
/* Handle keyboard interrupt SIGINT */
struct sigaction s;
s.sa_handler = (void *)signal_handler;
if ((0 != sigemptyset(&s.sa_mask)) && debug)
printf("sigemptyset failed.\n");
s.sa_flags = SA_RESETHAND;
if ((sigaction(SIGINT, &s, NULL) != 0) && debug)
printf("Could not register SIGINT signal handler.\n");
fd_set fds; /* For select() */
struct timeval idleTime; /* How long to select() */
int timelimit; /* Number of seconds to be connected */
int starttime; /* Time program was started */
int timelimit; /* Number of seconds to be connected */
int starttime; /* Time program was started */
/* open a connection to the syslog daemon */
/*openlog(PACKAGE, LOG_PID, LOG_DAEMON);*/
/* open a connection to the syslog daemon */
/*openlog(PACKAGE, LOG_PID, LOG_DAEMON); */
/* TODO: Only use LOG__PERROR for linux */
/* TODO: Only use LOG__PERROR for linux */
#ifdef __linux__
openlog(PACKAGE, (LOG_PID | LOG_PERROR), LOG_DAEMON);
openlog(PACKAGE, (LOG_PID | LOG_PERROR), LOG_DAEMON);
#else
openlog(PACKAGE, (LOG_PID), LOG_DAEMON);
openlog(PACKAGE, (LOG_PID), LOG_DAEMON);
#endif
if (cmdline_parser(argc, argv, &args_info) != 0)
exit(1);
if (args_info.debug_flag) {
printf("listen: %s\n", args_info.listen_arg);
if (args_info.conf_arg)
printf("conf: %s\n", args_info.conf_arg);
printf("fg: %d\n", args_info.fg_flag);
printf("debug: %d\n", args_info.debug_flag);
printf("qos: %#08x\n", args_info.qos_arg);
if (args_info.apn_arg)
printf("apn: %s\n", args_info.apn_arg);
if (args_info.net_arg)
printf("net: %s\n", args_info.net_arg);
if (args_info.dynip_arg)
printf("dynip: %s\n", args_info.dynip_arg);
if (args_info.statip_arg)
printf("statip: %s\n", args_info.statip_arg);
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);
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);
printf("timelimit: %d\n", args_info.timelimit_arg);
}
if (cmdline_parser (argc, argv, &args_info) != 0)
exit(1);
if (args_info.debug_flag) {
printf("listen: %s\n", args_info.listen_arg);
if (args_info.conf_arg) printf("conf: %s\n", args_info.conf_arg);
printf("fg: %d\n", args_info.fg_flag);
printf("debug: %d\n", args_info.debug_flag);
printf("qos: %#08x\n", args_info.qos_arg);
if (args_info.apn_arg) printf("apn: %s\n", args_info.apn_arg);
if (args_info.net_arg) printf("net: %s\n", args_info.net_arg);
if (args_info.dynip_arg) printf("dynip: %s\n", args_info.dynip_arg);
if (args_info.statip_arg) printf("statip: %s\n", args_info.statip_arg);
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);
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);
printf("timelimit: %d\n", args_info.timelimit_arg);
}
/* Try out our new parser */
/* Try out our new parser */
if (cmdline_parser_configfile (args_info.conf_arg, &args_info, 0, 0, 0) != 0)
exit(1);
if (args_info.debug_flag) {
printf("cmdline_parser_configfile\n");
printf("listen: %s\n", args_info.listen_arg);
printf("conf: %s\n", args_info.conf_arg);
printf("fg: %d\n", args_info.fg_flag);
printf("debug: %d\n", args_info.debug_flag);
printf("qos: %#08x\n", args_info.qos_arg);
if (args_info.apn_arg) printf("apn: %s\n", args_info.apn_arg);
if (args_info.net_arg) printf("net: %s\n", args_info.net_arg);
if (args_info.dynip_arg) printf("dynip: %s\n", args_info.dynip_arg);
if (args_info.statip_arg) printf("statip: %s\n", args_info.statip_arg);
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);
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);
printf("timelimit: %d\n", args_info.timelimit_arg);
}
if (cmdline_parser_configfile(args_info.conf_arg, &args_info, 0, 0, 0)
!= 0)
exit(1);
if (args_info.debug_flag) {
printf("cmdline_parser_configfile\n");
printf("listen: %s\n", args_info.listen_arg);
printf("conf: %s\n", args_info.conf_arg);
printf("fg: %d\n", args_info.fg_flag);
printf("debug: %d\n", args_info.debug_flag);
printf("qos: %#08x\n", args_info.qos_arg);
if (args_info.apn_arg)
printf("apn: %s\n", args_info.apn_arg);
if (args_info.net_arg)
printf("net: %s\n", args_info.net_arg);
if (args_info.dynip_arg)
printf("dynip: %s\n", args_info.dynip_arg);
if (args_info.statip_arg)
printf("statip: %s\n", args_info.statip_arg);
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);
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);
printf("timelimit: %d\n", args_info.timelimit_arg);
}
/* Handle each option */
/* Handle each option */
/* debug */
debug = args_info.debug_flag;
/* debug */
debug = args_info.debug_flag;
/* listen */
/* Do hostname lookup to translate hostname to IP address */
/* Any port listening is not possible as a valid address is */
/* required for create_pdp_context_response messages */
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);
exit(1);
}
else {
memcpy(&listen_.s_addr, host->h_addr, host->h_length);
}
}
else {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"Listening address must be specified! "
"Please use command line option --listen or "
"edit %s configuration file\n", args_info.conf_arg);
exit(1);
}
/* listen */
/* Do hostname lookup to translate hostname to IP address */
/* Any port listening is not possible as a valid address is */
/* required for create_pdp_context_response messages */
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);
exit(1);
} else {
memcpy(&listen_.s_addr, host->h_addr, host->h_length);
}
} else {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"Listening address must be specified! "
"Please use command line option --listen or "
"edit %s configuration file\n", args_info.conf_arg);
exit(1);
}
/* net */
/* Store net as in_addr net and mask */
if (args_info.net_arg) {
if(ippool_aton(&net, &mask, args_info.net_arg, 0)) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"Invalid network address: %s!", args_info.net_arg);
exit(1);
}
netaddr.s_addr = htonl(ntohl(net.s_addr) + 1);
destaddr.s_addr = htonl(ntohl(net.s_addr) + 1);
}
else {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"Network address must be specified: %s!", args_info.net_arg);
exit(1);
}
/* net */
/* Store net as in_addr net and mask */
if (args_info.net_arg) {
if (ippool_aton(&net, &mask, args_info.net_arg, 0)) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"Invalid network address: %s!",
args_info.net_arg);
exit(1);
}
netaddr.s_addr = htonl(ntohl(net.s_addr) + 1);
destaddr.s_addr = htonl(ntohl(net.s_addr) + 1);
} else {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"Network address must be specified: %s!",
args_info.net_arg);
exit(1);
}
/* dynip */
if (!args_info.dynip_arg) {
if (ippool_new(&ippool, args_info.net_arg, NULL, 1, 0,
IPPOOL_NONETWORK | IPPOOL_NOGATEWAY | IPPOOL_NOBROADCAST)) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"Failed to allocate IP pool!");
exit(1);
}
}
else {
if (ippool_new(&ippool, args_info.dynip_arg, NULL, 1 ,0,
IPPOOL_NONETWORK | IPPOOL_NOGATEWAY | IPPOOL_NOBROADCAST)) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"Failed to allocate IP pool!");
exit(1);
}
}
/* dynip */
if (!args_info.dynip_arg) {
if (ippool_new(&ippool, args_info.net_arg, NULL, 1, 0,
IPPOOL_NONETWORK | IPPOOL_NOGATEWAY |
IPPOOL_NOBROADCAST)) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"Failed to allocate IP pool!");
exit(1);
}
} else {
if (ippool_new(&ippool, args_info.dynip_arg, NULL, 1, 0,
IPPOOL_NONETWORK | IPPOOL_NOGATEWAY |
IPPOOL_NOBROADCAST)) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"Failed to allocate IP pool!");
exit(1);
}
}
/* DNS1 and DNS2 */
/* DNS1 and DNS2 */
#ifdef HAVE_INET_ATON
dns1.s_addr = 0;
if (args_info.pcodns1_arg) {
if (0 == inet_aton(args_info.pcodns1_arg, &dns1)) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"Failed to convert pcodns1!");
exit(1);
}
}
dns2.s_addr = 0;
if (args_info.pcodns2_arg) {
if (0 == inet_aton(args_info.pcodns2_arg, &dns2)) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"Failed to convert pcodns2!");
exit(1);
}
}
dns1.s_addr = 0;
if (args_info.pcodns1_arg) {
if (0 == inet_aton(args_info.pcodns1_arg, &dns1)) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"Failed to convert pcodns1!");
exit(1);
}
}
dns2.s_addr = 0;
if (args_info.pcodns2_arg) {
if (0 == inet_aton(args_info.pcodns2_arg, &dns2)) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"Failed to convert pcodns2!");
exit(1);
}
}
#else
dns1.s_addr = 0;
if (args_info.pcodns1_arg) {
dns1.s_addr = inet_addr(args_info.pcodns1_arg);
if (dns1.s_addr == -1) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"Failed to convert pcodns1!");
exit(1);
}
}
dns2.s_addr = 0;
if (args_info.pcodns2_arg) {
dns2.s_addr = inet_addr(args_info.pcodns2_arg);
if (dns2.s_addr == -1) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"Failed to convert pcodns2!");
exit(1);
}
}
dns1.s_addr = 0;
if (args_info.pcodns1_arg) {
dns1.s_addr = inet_addr(args_info.pcodns1_arg);
if (dns1.s_addr == -1) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"Failed to convert pcodns1!");
exit(1);
}
}
dns2.s_addr = 0;
if (args_info.pcodns2_arg) {
dns2.s_addr = inet_addr(args_info.pcodns2_arg);
if (dns2.s_addr == -1) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"Failed to convert pcodns2!");
exit(1);
}
}
#endif
pco.l = 20;
pco.v[0] = 0x80; /* x0000yyy x=1, yyy=000: PPP */
pco.v[1] = 0x80; /* IPCP */
pco.v[2] = 0x21;
pco.v[3] = 0x10; /* Length of contents */
pco.v[4] = 0x02; /* ACK */
pco.v[5] = 0x00; /* ID: Need to match request */
pco.v[6] = 0x00; /* Length */
pco.v[7] = 0x10;
pco.v[8] = 0x81; /* DNS 1 */
pco.v[9] = 0x06;
memcpy(&pco.v[10], &dns1, sizeof(dns1));
pco.v[14] = 0x83;
pco.v[15] = 0x06; /* DNS 2 */
memcpy(&pco.v[16], &dns2, sizeof(dns2));
pco.l = 20;
pco.v[0] = 0x80; /* x0000yyy x=1, yyy=000: PPP */
pco.v[1] = 0x80; /* IPCP */
pco.v[2] = 0x21;
pco.v[3] = 0x10; /* Length of contents */
pco.v[4] = 0x02; /* ACK */
pco.v[5] = 0x00; /* ID: Need to match request */
pco.v[6] = 0x00; /* Length */
pco.v[7] = 0x10;
pco.v[8] = 0x81; /* DNS 1 */
pco.v[9] = 0x06;
memcpy(&pco.v[10], &dns1, sizeof(dns1));
pco.v[14] = 0x83;
pco.v[15] = 0x06; /* DNS 2 */
memcpy(&pco.v[16], &dns2, sizeof(dns2));
/* ipup */
ipup = args_info.ipup_arg;
/* ipup */
ipup = args_info.ipup_arg;
/* ipdown */
ipdown = args_info.ipdown_arg;
/* ipdown */
ipdown = args_info.ipdown_arg;
/* Timelimit */
timelimit = args_info.timelimit_arg;
starttime = time(NULL);
/* Timelimit */
timelimit = args_info.timelimit_arg;
starttime = time(NULL);
/* qos */
qos.l = 3;
qos.v[2] = (args_info.qos_arg) & 0xff;
qos.v[1] = ((args_info.qos_arg) >> 8) & 0xff;
qos.v[0] = ((args_info.qos_arg) >> 16) & 0xff;
/* qos */
qos.l = 3;
qos.v[2] = (args_info.qos_arg) & 0xff;
qos.v[1] = ((args_info.qos_arg) >> 8) & 0xff;
qos.v[0] = ((args_info.qos_arg) >> 16) & 0xff;
/* apn */
if (strlen(args_info.apn_arg) > (sizeof(apn.v)-1)) {
printf("Invalid APN\n");
return -1;
}
apn.l = strlen(args_info.apn_arg) + 1;
apn.v[0] = (char) strlen(args_info.apn_arg);
strncpy((char *) &apn.v[1], args_info.apn_arg, sizeof(apn.v)-1);
/* apn */
if (strlen(args_info.apn_arg) > (sizeof(apn.v) - 1)) {
printf("Invalid APN\n");
return -1;
}
apn.l = strlen(args_info.apn_arg) + 1;
apn.v[0] = (char)strlen(args_info.apn_arg);
strncpy((char *)&apn.v[1], args_info.apn_arg, sizeof(apn.v) - 1);
/* foreground */
/* If flag not given run as a daemon */
if (!args_info.fg_flag) {
FILE *f;
int rc;
closelog();
/* Close the standard file descriptors. */
/* Is this really needed ? */
f = freopen("/dev/null", "w", stdout);
if (f == NULL) {
sys_err(LOG_WARNING, __FILE__, __LINE__, 0,
"Could not redirect stdout to /dev/null");
}
f = freopen("/dev/null", "w", stderr);
if (f == NULL) {
sys_err(LOG_WARNING, __FILE__, __LINE__, 0,
"Could not redirect stderr to /dev/null");
}
f = freopen("/dev/null", "r", stdin);
if (f == NULL) {
sys_err(LOG_WARNING, __FILE__, __LINE__, 0,
"Could not redirect stdin to /dev/null");
}
rc = daemon(0, 0);
if (rc != 0) {
sys_err(LOG_ERR, __FILE__, __LINE__, rc,
"Could not daemonize");
exit(1);
}
/* Open log again. This time with new pid */
openlog(PACKAGE, LOG_PID, LOG_DAEMON);
}
/* foreground */
/* If flag not given run as a daemon */
if (!args_info.fg_flag)
{
FILE *f;
int rc;
closelog();
/* Close the standard file descriptors. */
/* Is this really needed ? */
f = freopen("/dev/null", "w", stdout);
if (f == NULL) {
sys_err(LOG_WARNING, __FILE__, __LINE__, 0,
"Could not redirect stdout to /dev/null");
}
f = freopen("/dev/null", "w", stderr);
if (f == NULL) {
sys_err(LOG_WARNING, __FILE__, __LINE__, 0,
"Could not redirect stderr to /dev/null");
}
f = freopen("/dev/null", "r", stdin);
if (f == NULL) {
sys_err(LOG_WARNING, __FILE__, __LINE__, 0,
"Could not redirect stdin to /dev/null");
}
rc = daemon(0, 0);
if (rc != 0) {
sys_err(LOG_ERR, __FILE__, __LINE__, rc, "Could not daemonize");
exit(1);
}
/* Open log again. This time with new pid */
openlog(PACKAGE, LOG_PID, LOG_DAEMON);
}
/* pidfile */
/* This has to be done after we have our final pid */
if (args_info.pidfile_arg) {
log_pid(args_info.pidfile_arg);
}
/* pidfile */
/* This has to be done after we have our final pid */
if (args_info.pidfile_arg) {
log_pid(args_info.pidfile_arg);
}
if (debug)
printf("gtpclient: Initialising GTP tunnel\n");
if (debug) printf("gtpclient: Initialising GTP tunnel\n");
if (gtp_new(&gsn, args_info.statedir_arg, &listen_, GTP_MODE_GGSN)) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"Failed to create gtp");
exit(1);
}
if (gsn->fd0 > maxfd) maxfd = gsn->fd0;
if (gsn->fd1c > maxfd) maxfd = gsn->fd1c;
if (gsn->fd1u > maxfd) maxfd = gsn->fd1u;
if (gtp_new(&gsn, args_info.statedir_arg, &listen_, GTP_MODE_GGSN)) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Failed to create gtp");
exit(1);
}
if (gsn->fd0 > maxfd)
maxfd = gsn->fd0;
if (gsn->fd1c > maxfd)
maxfd = gsn->fd1c;
if (gsn->fd1u > maxfd)
maxfd = gsn->fd1u;
gtp_set_cb_data_ind(gsn, encaps_tun);
gtp_set_cb_delete_context(gsn, delete_context);
gtp_set_cb_create_context_ind(gsn, create_context_ind);
gtp_set_cb_data_ind(gsn, encaps_tun);
gtp_set_cb_delete_context(gsn, delete_context);
gtp_set_cb_create_context_ind(gsn, create_context_ind);
/* Create a tunnel interface */
if (debug)
printf("Creating tun interface\n");
if (tun_new((struct tun_t **)&tun)) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Failed to create tun");
if (debug)
printf("Failed to create tun\n");
exit(1);
}
/* Create a tunnel interface */
if (debug) printf("Creating tun interface\n");
if (tun_new((struct tun_t**) &tun)) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"Failed to create tun");
if (debug) printf("Failed to create tun\n");
exit(1);
}
if (debug)
printf("Setting tun IP address\n");
if (tun_setaddr(tun, &netaddr, &destaddr, &mask)) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"Failed to set tun IP address");
if (debug)
printf("Failed to set tun IP address\n");
exit(1);
}
if (debug) printf("Setting tun IP address\n");
if (tun_setaddr(tun, &netaddr, &destaddr, &mask)) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"Failed to set tun IP address");
if (debug) printf("Failed to set tun IP address\n");
exit(1);
}
tun_set_cb_ind(tun, cb_tun_ind);
if (tun->fd > maxfd)
maxfd = tun->fd;
tun_set_cb_ind(tun, cb_tun_ind);
if (tun->fd > maxfd) maxfd = tun->fd;
if (ipup) tun_runscript(tun, ipup);
if (ipup)
tun_runscript(tun, ipup);
/******************************************************************/
/* Main select loop */
/* Main select loop */
/******************************************************************/
while ((((starttime + timelimit) > time(NULL)) || (0 == timelimit)) && (!end)) {
while ((((starttime + timelimit) > time(NULL)) || (0 == timelimit))
&& (!end)) {
FD_ZERO(&fds);
if (tun) FD_SET(tun->fd, &fds);
FD_SET(gsn->fd0, &fds);
FD_SET(gsn->fd1c, &fds);
FD_SET(gsn->fd1u, &fds);
gtp_retranstimeout(gsn, &idleTime);
switch (select(maxfd + 1, &fds, NULL, NULL, &idleTime)) {
case -1: /* errno == EINTR : unblocked signal */
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"select() returned -1");
/* On error, select returns without modifying fds */
FD_ZERO(&fds);
break;
case 0:
/* printf("Select returned 0\n"); */
gtp_retrans(gsn); /* Only retransmit if nothing else */
break;
default:
break;
}
FD_ZERO(&fds);
if (tun)
FD_SET(tun->fd, &fds);
FD_SET(gsn->fd0, &fds);
FD_SET(gsn->fd1c, &fds);
FD_SET(gsn->fd1u, &fds);
if (tun->fd != -1 && FD_ISSET(tun->fd, &fds) &&
tun_decaps(tun) < 0) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"TUN read failed (fd)=(%d)", tun->fd);
}
if (FD_ISSET(gsn->fd0, &fds))
gtp_decaps0(gsn);
if (FD_ISSET(gsn->fd1c, &fds))
gtp_decaps1c(gsn);
if (FD_ISSET(gsn->fd1u, &fds))
gtp_decaps1u(gsn);
}
gtp_retranstimeout(gsn, &idleTime);
switch (select(maxfd + 1, &fds, NULL, NULL, &idleTime)) {
case -1: /* errno == EINTR : unblocked signal */
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"select() returned -1");
/* On error, select returns without modifying fds */
FD_ZERO(&fds);
break;
case 0:
/* printf("Select returned 0\n"); */
gtp_retrans(gsn); /* Only retransmit if nothing else */
break;
default:
break;
}
if (tun->fd != -1 && FD_ISSET(tun->fd, &fds) &&
tun_decaps(tun) < 0) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"TUN read failed (fd)=(%d)", tun->fd);
}
if (FD_ISSET(gsn->fd0, &fds))
gtp_decaps0(gsn);
if (FD_ISSET(gsn->fd1c, &fds))
gtp_decaps1c(gsn);
if (FD_ISSET(gsn->fd1u, &fds))
gtp_decaps1u(gsn);
}
cmdline_parser_free(&args_info);
ippool_free(ippool);
gtp_free(gsn);
tun_free(tun);
return 1;
cmdline_parser_free(&args_info);
ippool_free(ippool);
gtp_free(gsn);
tun_free(tun);
return 1;
}

5035
gtp/gtp.c

File diff suppressed because it is too large Load Diff

441
gtp/gtp.h
View File

@ -12,7 +12,7 @@
#ifndef _GTP_H
#define _GTP_H
#define GTP_DEBUG 0 /* Print debug information */
#define GTP_DEBUG 0 /* Print debug information */
#define GTP_MODE_GGSN 1
#define GTP_MODE_SGSN 2
@ -22,7 +22,7 @@
#define GTP1U_PORT 2152
#define PACKET_MAX 8196
#define GTP_MAX 0xffff /* TODO: Choose right number */
#define GTP_MAX 0xffff /* TODO: Choose right number */
#define GTP0_HEADER_SIZE 20
#define GTP1_HEADER_SIZE_SHORT 8
#define GTP1_HEADER_SIZE_LONG 12
@ -34,107 +34,104 @@
#define NAMESIZE 1024
/* GTP version 1 extension header type definitions. */
#define GTP_EXT_PDCP_PDU 0xC0 /* PDCP PDU Number */
#define GTP_EXT_PDCP_PDU 0xC0 /* PDCP PDU Number */
/* GTP version 1 message type definitions. Also covers version 0 except *
* for anonymous PDP context which was superceded in version 1 */
/* 0 For future use. */
#define GTP_ECHO_REQ 1 /* Echo Request */
#define GTP_ECHO_RSP 2 /* Echo Response */
#define GTP_NOT_SUPPORTED 3 /* Version Not Supported */
#define GTP_ALIVE_REQ 4 /* Node Alive Request */
#define GTP_ALIVE_RSP 5 /* Node Alive Response */
#define GTP_REDIR_REQ 6 /* Redirection Request */
#define GTP_REDIR_RSP 7 /* Redirection Response */
#define GTP_ECHO_REQ 1 /* Echo Request */
#define GTP_ECHO_RSP 2 /* Echo Response */
#define GTP_NOT_SUPPORTED 3 /* Version Not Supported */
#define GTP_ALIVE_REQ 4 /* Node Alive Request */
#define GTP_ALIVE_RSP 5 /* Node Alive Response */
#define GTP_REDIR_REQ 6 /* Redirection Request */
#define GTP_REDIR_RSP 7 /* Redirection Response */
/* 8-15 For future use. */
#define GTP_CREATE_PDP_REQ 16 /* Create PDP Context Request */
#define GTP_CREATE_PDP_RSP 17 /* Create PDP Context Response */
#define GTP_UPDATE_PDP_REQ 18 /* Update PDP Context Request */
#define GTP_UPDATE_PDP_RSP 19 /* Update PDP Context Response */
#define GTP_DELETE_PDP_REQ 20 /* Delete PDP Context Request */
#define GTP_DELETE_PDP_RSP 21 /* Delete PDP Context Response */
/* 22-25 For future use. */ /* In version GTP 1 anonomous PDP context */
#define GTP_ERROR 26 /* Error Indication */
#define GTP_PDU_NOT_REQ 27 /* PDU Notification Request */
#define GTP_PDU_NOT_RSP 28 /* PDU Notification Response */
#define GTP_PDU_NOT_REJ_REQ 29 /* PDU Notification Reject Request */
#define GTP_PDU_NOT_REJ_RSP 30 /* PDU Notification Reject Response */
#define GTP_SUPP_EXT_HEADER 31 /* Supported Extension Headers Notification */
#define GTP_SND_ROUTE_REQ 32 /* Send Routeing Information for GPRS Request */
#define GTP_SND_ROUTE_RSP 33 /* Send Routeing Information for GPRS Response */
#define GTP_FAILURE_REQ 34 /* Failure Report Request */
#define GTP_FAILURE_RSP 35 /* Failure Report Response */
#define GTP_MS_PRESENT_REQ 36 /* Note MS GPRS Present Request */
#define GTP_MS_PRESENT_RSP 37 /* Note MS GPRS Present Response */
/* 38-47 For future use. */
#define GTP_IDEN_REQ 48 /* Identification Request */
#define GTP_IDEN_RSP 49 /* Identification Response */
#define GTP_SGSN_CONTEXT_REQ 50 /* SGSN Context Request */
#define GTP_SGSN_CONTEXT_RSP 51 /* SGSN Context Response */
#define GTP_SGSN_CONTEXT_ACK 52 /* SGSN Context Acknowledge */
#define GTP_FWD_RELOC_REQ 53 /* Forward Relocation Request */
#define GTP_FWD_RELOC_RSP 54 /* Forward Relocation Response */
#define GTP_FWD_RELOC_COMPL 55 /* Forward Relocation Complete */
#define GTP_RELOC_CANCEL_REQ 56 /* Relocation Cancel Request */
#define GTP_RELOC_CANCEL_RSP 57 /* Relocation Cancel Response */
#define GTP_FWD_SRNS 58 /* Forward SRNS Context */
#define GTP_FWD_RELOC_ACK 59 /* Forward Relocation Complete Acknowledge */
#define GTP_FWD_SRNS_ACK 60 /* Forward SRNS Context Acknowledge */
#define GTP_CREATE_PDP_REQ 16 /* Create PDP Context Request */
#define GTP_CREATE_PDP_RSP 17 /* Create PDP Context Response */
#define GTP_UPDATE_PDP_REQ 18 /* Update PDP Context Request */
#define GTP_UPDATE_PDP_RSP 19 /* Update PDP Context Response */
#define GTP_DELETE_PDP_REQ 20 /* Delete PDP Context Request */
#define GTP_DELETE_PDP_RSP 21 /* Delete PDP Context Response */
/* 22-25 For future use. *//* In version GTP 1 anonomous PDP context */
#define GTP_ERROR 26 /* Error Indication */
#define GTP_PDU_NOT_REQ 27 /* PDU Notification Request */
#define GTP_PDU_NOT_RSP 28 /* PDU Notification Response */
#define GTP_PDU_NOT_REJ_REQ 29 /* PDU Notification Reject Request */
#define GTP_PDU_NOT_REJ_RSP 30 /* PDU Notification Reject Response */
#define GTP_SUPP_EXT_HEADER 31 /* Supported Extension Headers Notification */
#define GTP_SND_ROUTE_REQ 32 /* Send Routeing Information for GPRS Request */
#define GTP_SND_ROUTE_RSP 33 /* Send Routeing Information for GPRS Response */
#define GTP_FAILURE_REQ 34 /* Failure Report Request */
#define GTP_FAILURE_RSP 35 /* Failure Report Response */
#define GTP_MS_PRESENT_REQ 36 /* Note MS GPRS Present Request */
#define GTP_MS_PRESENT_RSP 37 /* Note MS GPRS Present Response */
/* 38-47 For future use. */
#define GTP_IDEN_REQ 48 /* Identification Request */
#define GTP_IDEN_RSP 49 /* Identification Response */
#define GTP_SGSN_CONTEXT_REQ 50 /* SGSN Context Request */
#define GTP_SGSN_CONTEXT_RSP 51 /* SGSN Context Response */
#define GTP_SGSN_CONTEXT_ACK 52 /* SGSN Context Acknowledge */
#define GTP_FWD_RELOC_REQ 53 /* Forward Relocation Request */
#define GTP_FWD_RELOC_RSP 54 /* Forward Relocation Response */
#define GTP_FWD_RELOC_COMPL 55 /* Forward Relocation Complete */
#define GTP_RELOC_CANCEL_REQ 56 /* Relocation Cancel Request */
#define GTP_RELOC_CANCEL_RSP 57 /* Relocation Cancel Response */
#define GTP_FWD_SRNS 58 /* Forward SRNS Context */
#define GTP_FWD_RELOC_ACK 59 /* Forward Relocation Complete Acknowledge */
#define GTP_FWD_SRNS_ACK 60 /* Forward SRNS Context Acknowledge */
/* 61-239 For future use. */
#define GTP_DATA_TRAN_REQ 240 /* Data Record Transfer Request */
#define GTP_DATA_TRAN_RSP 241 /* Data Record Transfer Response */
#define GTP_DATA_TRAN_REQ 240 /* Data Record Transfer Request */
#define GTP_DATA_TRAN_RSP 241 /* Data Record Transfer Response */
/* 242-254 For future use. */
#define GTP_GPDU 255 /* G-PDU */
#define GTP_GPDU 255 /* G-PDU */
/* GTP information element cause codes from 29.060 v3.9.0 7.7 */
/* */
#define GTPCAUSE_REQ_IMSI 0 /* Request IMSI */
#define GTPCAUSE_REQ_IMEI 1 /* Request IMEI */
#define GTPCAUSE_REQ_IMSI_IMEI 2 /* Request IMSI and IMEI */
#define GTPCAUSE_NO_ID_NEEDED 3 /* No identity needed */
#define GTPCAUSE_MS_REFUSES_X 4 /* MS refuses */
#define GTPCAUSE_MS_NOT_RESP_X 5 /* MS is not GPRS responding */
#define GTPCAUSE_006 6 /* For future use 6-48 */
#define GTPCAUSE_049 49 /* Cause values reserved for GPRS charging protocol use (See GTP' in GSM 12.15) 49-63 */
#define GTPCAUSE_064 64 /* For future use 64-127 */
#define GTPCAUSE_ACC_REQ 128 /* Request accepted */
#define GTPCAUSE_129 129 /* For future use 129-176 */
#define GTPCAUSE_177 177 /* Cause values reserved for GPRS charging protocol use (See GTP' In GSM 12.15) 177-191 */
#define GTPCAUSE_NON_EXIST 192 /* Non-existent */
#define GTPCAUSE_INVALID_MESSAGE 193 /* Invalid message format */
#define GTPCAUSE_IMSI_NOT_KNOWN 194 /* IMSI not known */
#define GTPCAUSE_MS_DETACHED 195 /* MS is GPRS detached */
#define GTPCAUSE_MS_NOT_RESP 196 /* MS is not GPRS responding */
#define GTPCAUSE_MS_REFUSES 197 /* MS refuses */
#define GTPCAUSE_198 198 /* For future use */
#define GTPCAUSE_NO_RESOURCES 199 /* No resources available */
#define GTPCAUSE_NOT_SUPPORTED 200 /* Service not supported */
#define GTPCAUSE_MAN_IE_INCORRECT 201 /* Mandatory IE incorrect */
#define GTPCAUSE_MAN_IE_MISSING 202 /* Mandatory IE missing */
#define GTPCAUSE_OPT_IE_INCORRECT 203 /* Optional IE incorrect */
#define GTPCAUSE_SYS_FAIL 204 /* System failure */
#define GTPCAUSE_ROAMING_REST 205 /* Roaming Restriction */
#define GTPCAUSE_PTIMSI_MISMATCH 206 /* P-TMSI signature mismatch */
#define GTPCAUSE_CONN_SUSP 207 /* GPRS connection suspended */
#define GTPCAUSE_AUTH_FAIL 208 /* Authentication failure */
#define GTPCAUSE_USER_AUTH_FAIL 209 /* User authentication failed */
#define GTPCAUSE_CONTEXT_NOT_FOUND 210 /* Context not found */
#define GTPCAUSE_ADDR_OCCUPIED 211 /* All dynamic PDP addresses are occupied */
#define GTPCAUSE_NO_MEMORY 212 /* No memory is available */
#define GTPCAUSE_RELOC_FAIL 213 /* Relocation failure */
#define GTPCAUSE_UNKNOWN_MAN_EXTHEADER 214 /* Unknown mandatory extension header */
#define GTPCAUSE_SEM_ERR_TFT 215 /* Semantic error in the TFT operation */
#define GTPCAUSE_SYN_ERR_TFT 216 /* Syntactic error in the TFT operation */
#define GTPCAUSE_SEM_ERR_FILTER 217 /* Semantic errors in packet filter(s) */
#define GTPCAUSE_SYN_ERR_FILTER 218 /* Syntactic errors in packet filter(s) */
#define GTPCAUSE_MISSING_APN 219 /* Missing or unknown APN*/
#define GTPCAUSE_UNKNOWN_PDP 220 /* Unknown PDP address or PDP type */
#define GTPCAUSE_221 221 /* For Future Use 221-240 */
#define GTPCAUSE_241 241 /* Cause Values Reserved For Gprs Charging Protocol Use (See Gtp' In Gsm 12.15) 241-255 */
#define GTPCAUSE_REQ_IMSI 0 /* Request IMSI */
#define GTPCAUSE_REQ_IMEI 1 /* Request IMEI */
#define GTPCAUSE_REQ_IMSI_IMEI 2 /* Request IMSI and IMEI */
#define GTPCAUSE_NO_ID_NEEDED 3 /* No identity needed */
#define GTPCAUSE_MS_REFUSES_X 4 /* MS refuses */
#define GTPCAUSE_MS_NOT_RESP_X 5 /* MS is not GPRS responding */
#define GTPCAUSE_006 6 /* For future use 6-48 */
#define GTPCAUSE_049 49 /* Cause values reserved for GPRS charging protocol use (See GTP' in GSM 12.15) 49-63 */
#define GTPCAUSE_064 64 /* For future use 64-127 */
#define GTPCAUSE_ACC_REQ 128 /* Request accepted */
#define GTPCAUSE_129 129 /* For future use 129-176 */
#define GTPCAUSE_177 177 /* Cause values reserved for GPRS charging protocol use (See GTP' In GSM 12.15) 177-191 */
#define GTPCAUSE_NON_EXIST 192 /* Non-existent */
#define GTPCAUSE_INVALID_MESSAGE 193 /* Invalid message format */
#define GTPCAUSE_IMSI_NOT_KNOWN 194 /* IMSI not known */
#define GTPCAUSE_MS_DETACHED 195 /* MS is GPRS detached */
#define GTPCAUSE_MS_NOT_RESP 196 /* MS is not GPRS responding */
#define GTPCAUSE_MS_REFUSES 197 /* MS refuses */
#define GTPCAUSE_198 198 /* For future use */
#define GTPCAUSE_NO_RESOURCES 199 /* No resources available */
#define GTPCAUSE_NOT_SUPPORTED 200 /* Service not supported */
#define GTPCAUSE_MAN_IE_INCORRECT 201 /* Mandatory IE incorrect */
#define GTPCAUSE_MAN_IE_MISSING 202 /* Mandatory IE missing */
#define GTPCAUSE_OPT_IE_INCORRECT 203 /* Optional IE incorrect */
#define GTPCAUSE_SYS_FAIL 204 /* System failure */
#define GTPCAUSE_ROAMING_REST 205 /* Roaming Restriction */
#define GTPCAUSE_PTIMSI_MISMATCH 206 /* P-TMSI signature mismatch */
#define GTPCAUSE_CONN_SUSP 207 /* GPRS connection suspended */
#define GTPCAUSE_AUTH_FAIL 208 /* Authentication failure */
#define GTPCAUSE_USER_AUTH_FAIL 209 /* User authentication failed */
#define GTPCAUSE_CONTEXT_NOT_FOUND 210 /* Context not found */
#define GTPCAUSE_ADDR_OCCUPIED 211 /* All dynamic PDP addresses are occupied */
#define GTPCAUSE_NO_MEMORY 212 /* No memory is available */
#define GTPCAUSE_RELOC_FAIL 213 /* Relocation failure */
#define GTPCAUSE_UNKNOWN_MAN_EXTHEADER 214 /* Unknown mandatory extension header */
#define GTPCAUSE_SEM_ERR_TFT 215 /* Semantic error in the TFT operation */
#define GTPCAUSE_SYN_ERR_TFT 216 /* Syntactic error in the TFT operation */
#define GTPCAUSE_SEM_ERR_FILTER 217 /* Semantic errors in packet filter(s) */
#define GTPCAUSE_SYN_ERR_FILTER 218 /* Syntactic errors in packet filter(s) */
#define GTPCAUSE_MISSING_APN 219 /* Missing or unknown APN */
#define GTPCAUSE_UNKNOWN_PDP 220 /* Unknown PDP address or PDP type */
#define GTPCAUSE_221 221 /* For Future Use 221-240 */
#define GTPCAUSE_241 241 /* Cause Values Reserved For Gprs Charging Protocol Use (See Gtp' In Gsm 12.15) 241-255 */
/* GTP 0 header.
* Explanation to some of the fields:
@ -147,75 +144,72 @@
* Tunnel ID is IMSI+NSAPI. Unique identifier of PDP context. Is somewhat
* redundant because the header also includes flow. */
struct gtp0_header { /* Descriptions from 3GPP 09.60 */
uint8_t flags; /* 01 bitfield, with typical values */
/* 000..... Version: 1 (0) */
/* ...1111. Spare (7) */
/* .......0 SNDCP N-PDU Number flag (0) */
uint8_t type; /* 02 Message type. T-PDU = 0xff */
uint16_t length; /* 03 Length (of G-PDU excluding header) */
uint16_t seq; /* 05 Sequence Number */
uint16_t flow; /* 07 Flow Label ( = 0 for signalling) */
uint8_t number; /* 09 SNDCP N-PDU LCC Number ( 0 = 0xff) */
uint8_t spare1; /* 10 Spare */
uint8_t spare2; /* 11 Spare */
uint8_t spare3; /* 12 Spare */
uint64_t tid; /* 13 Tunnel ID */
}; /* 20 */
struct gtp0_header { /* Descriptions from 3GPP 09.60 */
uint8_t flags; /* 01 bitfield, with typical values */
/* 000..... Version: 1 (0) */
/* ...1111. Spare (7) */
/* .......0 SNDCP N-PDU Number flag (0) */
uint8_t type; /* 02 Message type. T-PDU = 0xff */
uint16_t length; /* 03 Length (of G-PDU excluding header) */
uint16_t seq; /* 05 Sequence Number */
uint16_t flow; /* 07 Flow Label ( = 0 for signalling) */
uint8_t number; /* 09 SNDCP N-PDU LCC Number ( 0 = 0xff) */
uint8_t spare1; /* 10 Spare */
uint8_t spare2; /* 11 Spare */
uint8_t spare3; /* 12 Spare */
uint64_t tid; /* 13 Tunnel ID */
}; /* 20 */
struct gtp1_header_short { /* Descriptions from 3GPP 29060 */
uint8_t flags; /* 01 bitfield, with typical values */
/* 001..... Version: 1 */
/* ...1.... Protocol Type: GTP=1, GTP'=0 */
/* ....0... Spare = 0 */
/* .....0.. Extension header flag: 0 */
/* ......0. Sequence number flag: 0 */
/* .......0 PN: N-PDU Number flag */
uint8_t type; /* 02 Message type. T-PDU = 0xff */
uint16_t length; /* 03 Length (of IP packet or signalling) */
uint32_t tei; /* 05 - 08 Tunnel Endpoint ID */
struct gtp1_header_short { /* Descriptions from 3GPP 29060 */
uint8_t flags; /* 01 bitfield, with typical values */
/* 001..... Version: 1 */
/* ...1.... Protocol Type: GTP=1, GTP'=0 */
/* ....0... Spare = 0 */
/* .....0.. Extension header flag: 0 */
/* ......0. Sequence number flag: 0 */
/* .......0 PN: N-PDU Number flag */
uint8_t type; /* 02 Message type. T-PDU = 0xff */
uint16_t length; /* 03 Length (of IP packet or signalling) */
uint32_t tei; /* 05 - 08 Tunnel Endpoint ID */
};
struct gtp1_header_long { /* Descriptions from 3GPP 29060 */
uint8_t flags; /* 01 bitfield, with typical values */
/* 001..... Version: 1 */
/* ...1.... Protocol Type: GTP=1, GTP'=0 */
/* ....0... Spare = 0 */
/* .....0.. Extension header flag: 0 */
/* ......1. Sequence number flag: 1 */
/* .......0 PN: N-PDU Number flag */
uint8_t type; /* 02 Message type. T-PDU = 0xff */
uint16_t length; /* 03 Length (of IP packet or signalling) */
uint32_t tei; /* 05 Tunnel Endpoint ID */
uint16_t seq; /* 10 Sequence Number */
uint8_t npdu; /* 11 N-PDU Number */
uint8_t next; /* 12 Next extension header type. Empty = 0 */
struct gtp1_header_long { /* Descriptions from 3GPP 29060 */
uint8_t flags; /* 01 bitfield, with typical values */
/* 001..... Version: 1 */
/* ...1.... Protocol Type: GTP=1, GTP'=0 */
/* ....0... Spare = 0 */
/* .....0.. Extension header flag: 0 */
/* ......1. Sequence number flag: 1 */
/* .......0 PN: N-PDU Number flag */
uint8_t type; /* 02 Message type. T-PDU = 0xff */
uint16_t length; /* 03 Length (of IP packet or signalling) */
uint32_t tei; /* 05 Tunnel Endpoint ID */
uint16_t seq; /* 10 Sequence Number */
uint8_t npdu; /* 11 N-PDU Number */
uint8_t next; /* 12 Next extension header type. Empty = 0 */
};
struct gtp0_packet {
struct gtp0_header h;
uint8_t p[GTP_MAX];
} __attribute__((packed));
struct gtp0_header h;
uint8_t p[GTP_MAX];
} __attribute__ ((packed));
struct gtp1_packet_short {
struct gtp1_header_short h;
uint8_t p[GTP_MAX];
} __attribute__((packed));
struct gtp1_header_short h;
uint8_t p[GTP_MAX];
} __attribute__ ((packed));
struct gtp1_packet_long {
struct gtp1_header_long h;
uint8_t p[GTP_MAX];
} __attribute__((packed));
struct gtp1_header_long h;
uint8_t p[GTP_MAX];
} __attribute__ ((packed));
union gtp_packet {
uint8_t flags;
struct gtp0_packet gtp0;
struct gtp1_packet_short gtp1s;
struct gtp1_packet_long gtp1l;
} __attribute__((packed));
uint8_t flags;
struct gtp0_packet gtp0;
struct gtp1_packet_short gtp1s;
struct gtp1_packet_long gtp1l;
} __attribute__ ((packed));
/* ***********************************************************
* Information storage for each gsn instance
@ -233,64 +227,63 @@ union gtp_packet {
*************************************************************/
struct gsn_t {
/* Parameters related to the network interface */
/* Parameters related to the network interface */
int fd0; /* GTP0 file descriptor */
int fd1c; /* GTP1 control plane file descriptor */
int fd1u; /* GTP0 user plane file descriptor */
int mode; /* Mode of operation: GGSN or SGSN */
struct in_addr gsnc; /* IP address of this gsn for signalling */
struct in_addr gsnu; /* IP address of this gsn for user traffic */
int fd0; /* GTP0 file descriptor */
int fd1c; /* GTP1 control plane file descriptor */
int fd1u; /* GTP0 user plane file descriptor */
int mode; /* Mode of operation: GGSN or SGSN */
struct in_addr gsnc; /* IP address of this gsn for signalling */
struct in_addr gsnu; /* IP address of this gsn for user traffic */
/* Parameters related to signalling messages */
uint16_t seq_next; /* Next sequence number to use */
int seq_first; /* First packet in queue (oldest timeout) */
int seq_last; /* Last packet in queue (youngest timeout) */
/* Parameters related to signalling messages */
uint16_t seq_next; /* Next sequence number to use */
int seq_first; /* First packet in queue (oldest timeout) */
int seq_last; /* Last packet in queue (youngest timeout) */
unsigned char restart_counter; /* Increment on restart. Stored on disk */
char *statedir; /* Disk location for permanent storage */
unsigned char restart_counter; /* Increment on restart. Stored on disk */
char *statedir; /* Disk location for permanent storage */
struct queue_t *queue_req; /* Request queue */
struct queue_t *queue_resp; /* Response queue */
struct queue_t *queue_req; /* Request queue */
struct queue_t *queue_resp; /* Response queue */
/* Call back functions */
int (*cb_delete_context) (struct pdp_t*);
int (*cb_create_context_ind) (struct pdp_t*);
int (*cb_unsup_ind) (struct sockaddr_in *peer);
int (*cb_extheader_ind) (struct sockaddr_in *peer);
int (*cb_conf) (int type, int cause, struct pdp_t *pdp, void* cbp);
int (*cb_data_ind) (struct pdp_t* pdp, void* pack, unsigned len);
int (*cb_recovery) (struct sockaddr_in *peer, uint8_t recovery);
/* Call back functions */
int (*cb_delete_context) (struct pdp_t *);
int (*cb_create_context_ind) (struct pdp_t *);
int (*cb_unsup_ind) (struct sockaddr_in * peer);
int (*cb_extheader_ind) (struct sockaddr_in * peer);
int (*cb_conf) (int type, int cause, struct pdp_t * pdp, void *cbp);
int (*cb_data_ind) (struct pdp_t * pdp, void *pack, unsigned len);
int (*cb_recovery) (struct sockaddr_in * peer, uint8_t recovery);
/* Counters */
uint64_t err_socket; /* Number of socket errors */
uint64_t err_readfrom; /* Number of readfrom errors */
uint64_t err_sendto; /* Number of sendto errors */
uint64_t err_memcpy; /* Number of memcpy */
uint64_t err_queuefull; /* Number of times queue was full */
uint64_t err_seq; /* Number of seq out of range */
uint64_t err_address; /* GSN address conversion failed */
uint64_t err_unknownpdp; /* GSN address conversion failed */
uint64_t err_unknowntid; /* Application supplied unknown imsi+nsapi */
uint64_t err_cause; /* Unexpected cause value received */
uint64_t err_outofpdp; /* Out of storage for PDP contexts */
/* Counters */
uint64_t empty; /* Number of empty packets */
uint64_t unsup; /* Number of unsupported version 29.60 11.1.1 */
uint64_t tooshort; /* Number of too short headers 29.60 11.1.2 */
uint64_t unknown; /* Number of unknown messages 29.60 11.1.3 */
uint64_t unexpect; /* Number of unexpected messages 29.60 11.1.4 */
uint64_t dublicate; /* Number of dublicate or unsolicited replies */
uint64_t missing; /* Number of missing information field messages */
uint64_t incorrect; /* Number of incorrect information field messages */
uint64_t invalid; /* Number of invalid message format messages */
uint64_t err_socket; /* Number of socket errors */
uint64_t err_readfrom; /* Number of readfrom errors */
uint64_t err_sendto; /* Number of sendto errors */
uint64_t err_memcpy; /* Number of memcpy */
uint64_t err_queuefull; /* Number of times queue was full */
uint64_t err_seq; /* Number of seq out of range */
uint64_t err_address; /* GSN address conversion failed */
uint64_t err_unknownpdp; /* GSN address conversion failed */
uint64_t err_unknowntid; /* Application supplied unknown imsi+nsapi */
uint64_t err_cause; /* Unexpected cause value received */
uint64_t err_outofpdp; /* Out of storage for PDP contexts */
uint64_t empty; /* Number of empty packets */
uint64_t unsup; /* Number of unsupported version 29.60 11.1.1 */
uint64_t tooshort; /* Number of too short headers 29.60 11.1.2 */
uint64_t unknown; /* Number of unknown messages 29.60 11.1.3 */
uint64_t unexpect; /* Number of unexpected messages 29.60 11.1.4 */
uint64_t dublicate; /* Number of dublicate or unsolicited replies */
uint64_t missing; /* Number of missing information field messages */
uint64_t incorrect; /* Number of incorrect information field messages */
uint64_t invalid; /* Number of invalid message format messages */
};
/* External API functions */
extern const char* gtp_version();
extern const char *gtp_version();
extern int gtp_new(struct gsn_t **gsn, char *statedir, struct in_addr *listen,
int mode);
@ -300,27 +293,29 @@ extern int gtp_newpdp(struct gsn_t *gsn, struct pdp_t **pdp,
uint64_t imsi, uint8_t nsapi);
extern int gtp_freepdp(struct gsn_t *gsn, struct pdp_t *pdp);
extern int gtp_create_context_req(struct gsn_t *gsn, struct pdp_t *pdp,
extern int gtp_create_context_req(struct gsn_t *gsn, struct pdp_t *pdp,
void *cbp);
extern int gtp_set_cb_create_context_ind(struct gsn_t *gsn,
int (*cb_create_context_ind) (struct pdp_t* pdp));
int (*cb_create_context_ind) (struct
pdp_t *
pdp));
extern int gtp_create_context_resp(struct gsn_t *gsn, struct pdp_t *pdp,
extern int gtp_create_context_resp(struct gsn_t *gsn, struct pdp_t *pdp,
int cause);
extern int gtp_update_context(struct gsn_t *gsn, struct pdp_t *pdp,
void *cbp, struct in_addr* inetaddr);
extern int gtp_update_context(struct gsn_t *gsn, struct pdp_t *pdp,
void *cbp, struct in_addr *inetaddr);
extern int gtp_delete_context_req(struct gsn_t *gsn, struct pdp_t *pdp,
extern int gtp_delete_context_req(struct gsn_t *gsn, struct pdp_t *pdp,
void *cbp, int teardown);
extern int gtp_data_req(struct gsn_t *gsn, struct pdp_t *pdp,
void *pack, unsigned len);
extern int gtp_set_cb_data_ind(struct gsn_t *gsn,
int (*cb_data_ind) (struct pdp_t* pdp, void* pack, unsigned len));
int (*cb_data_ind) (struct pdp_t * pdp,
void *pack, unsigned len));
extern int gtp_fd(struct gsn_t *gsn);
extern int gtp_decaps0(struct gsn_t *gsn);
@ -329,45 +324,46 @@ extern int gtp_decaps1u(struct gsn_t *gsn);
extern int gtp_retrans(struct gsn_t *gsn);
extern int gtp_retranstimeout(struct gsn_t *gsn, struct timeval *timeout);
extern int gtp_set_cb_delete_context(struct gsn_t *gsn,
int (*cb_delete_context) (struct pdp_t* pdp));
extern int gtp_set_cb_delete_context(struct gsn_t *gsn,
int (*cb_delete_context) (struct pdp_t *
pdp));
/*extern int gtp_set_cb_create_context(struct gsn_t *gsn,
int (*cb_create_context) (struct pdp_t* pdp)); */
extern int gtp_set_cb_unsup_ind(struct gsn_t *gsn,
int (*cb) (struct sockaddr_in *peer));
int (*cb) (struct sockaddr_in * peer));
extern int gtp_set_cb_extheader_ind(struct gsn_t *gsn,
int (*cb) (struct sockaddr_in *peer));
int (*cb) (struct sockaddr_in * peer));
extern int gtp_set_cb_conf(struct gsn_t *gsn,
int (*cb) (int type, int cause, struct pdp_t* pdp, void *cbp));
int (*cb) (int type, int cause, struct pdp_t * pdp,
void *cbp));
int gtp_set_cb_recovery(struct gsn_t *gsn,
int (*cb) (struct sockaddr_in *peer, uint8_t recovery));
int (*cb) (struct sockaddr_in * peer,
uint8_t recovery));
/* Internal functions (not part of the API */
extern int gtp_echo_req(struct gsn_t *gsn, int version, void *cbp,
struct in_addr *inetaddrs);
extern int gtp_echo_resp(struct gsn_t *gsn, int version,
extern int gtp_echo_resp(struct gsn_t *gsn, int version,
struct sockaddr_in *peer, int fd,
void *pack, unsigned len);
extern int gtp_echo_ind(struct gsn_t *gsn, int version,
struct sockaddr_in *peer, int fd,
extern int gtp_echo_ind(struct gsn_t *gsn, int version,
struct sockaddr_in *peer, int fd,
void *pack, unsigned len);
extern int gtp_echo_conf(struct gsn_t *gsn, int version,
struct sockaddr_in *peer,
void *pack, unsigned len);
extern int gtp_echo_conf(struct gsn_t *gsn, int version,
struct sockaddr_in *peer, void *pack, unsigned len);
extern int gtp_unsup_req(struct gsn_t *gsn, int version,
extern int gtp_unsup_req(struct gsn_t *gsn, int version,
struct sockaddr_in *peer,
int fd, void *pack, unsigned len);
extern int gtp_unsup_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
void *pack, unsigned len);
extern int gtp_create_pdp_resp(struct gsn_t *gsn, int version,
extern int gtp_create_pdp_resp(struct gsn_t *gsn, int version,
struct pdp_t *pdp, uint8_t cause);
extern int gtp_create_pdp_ind(struct gsn_t *gsn, int version,
@ -379,14 +375,14 @@ extern int gtp_create_pdp_conf(struct gsn_t *gsn, int version,
void *pack, unsigned len);
extern int gtp_update_pdp_req(struct gsn_t *gsn, int version, void *cbp,
struct in_addr* inetaddr, struct pdp_t *pdp);
struct in_addr *inetaddr, struct pdp_t *pdp);
extern int gtp_delete_pdp_req(struct gsn_t *gsn, int version, void *cbp,
struct pdp_t *pdp);
extern int gtp_delete_pdp_resp(struct gsn_t *gsn, int version,
struct sockaddr_in *peer, int fd,
void *pack, unsigned len,
void *pack, unsigned len,
struct pdp_t *pdp, struct pdp_t *linked_pdp,
uint8_t cause, int teardown);
@ -398,10 +394,9 @@ extern int gtp_delete_pdp_conf(struct gsn_t *gsn, int version,
struct sockaddr_in *peer,
void *pack, unsigned len);
extern int ipv42eua(struct ul66_t *eua, struct in_addr *src);
extern int eua2ipv4(struct in_addr *dst, struct ul66_t *eua);
extern int gsna2in_addr(struct in_addr *dst, struct ul16_t *gsna);
extern int in_addr2gsna(struct ul16_t *gsna, struct in_addr *src);
#endif /* !_GTP_H */
#endif /* !_GTP_H */

File diff suppressed because it is too large Load Diff

View File

@ -21,14 +21,13 @@
#define ntoh32(x) ntohl(x)
#if BYTE_ORDER == LITTLE_ENDIAN
static __inline uint64_t
hton64(uint64_t q)
static __inline uint64_t hton64(uint64_t q)
{
register uint32_t u, l;
u = q >> 32;
l = (uint32_t) q;
register uint32_t u, l;
u = q >> 32;
l = (uint32_t) q;
return htonl(u) | ((uint64_t)htonl(l) << 32);
return htonl(u) | ((uint64_t) htonl(l) << 32);
}
#define ntoh64(_x) hton64(_x)
@ -42,127 +41,124 @@ hton64(uint64_t q)
#error "Please fix <machine/endian.h>"
#endif
#define GTPIE_SIZE 256 /* Max number of information elements */
#define GTPIE_MAX 0xffff /* Max length of information elements */
#define GTPIE_MAX_TV 28 /* Max length of type value pair */
#define GTPIE_MAX_TLV 0xffff-3 /* Max length of TLV (GTP length is 16 bit) */
#define GTPIE_SIZE 256 /* Max number of information elements */
#define GTPIE_MAX 0xffff /* Max length of information elements */
#define GTPIE_MAX_TV 28 /* Max length of type value pair */
#define GTPIE_MAX_TLV 0xffff-3 /* Max length of TLV (GTP length is 16 bit) */
#define GTPIE_DEBUG 0 /* Print debug information */
#define GTPIE_DEBUG 0 /* Print debug information */
/* GTP Information elements from 29.060 v3.9.0 7.7 Information Elements */
/* Also covers version 0. Note that version 0 6: QOS Profile was superceded *
* by 135: QOS Profile in version 1 */
#define GTPIE_CAUSE 1 /* Cause 1 */
#define GTPIE_IMSI 2 /* International Mobile Subscriber Identity 8 */
#define GTPIE_RAI 3 /* Routing Area Identity (RAI) 8 */
#define GTPIE_TLLI 4 /* Temporary Logical Link Identity (TLLI) 4 */
#define GTPIE_P_TMSI 5 /* Packet TMSI (P-TMSI) 4 */
#define GTPIE_QOS_PROFILE0 6 /* Quality of Service Profile GTP version 0 3*/
/* 6-7 SPARE */ /* 6 is QoS Profile vers 0 */
#define GTPIE_REORDER 8 /* Reordering Required 1 */
#define GTPIE_AUTH_TRIPLET 9 /* Authentication Triplet 28 */
/* 10 SPARE */
#define GTPIE_MAP_CAUSE 11 /* MAP Cause 1 */
#define GTPIE_P_TMSI_S 12 /* P-TMSI Signature 3 */
#define GTPIE_MS_VALIDATED 13 /* MS Validated 1 */
#define GTPIE_RECOVERY 14 /* Recovery 1 */
#define GTPIE_SELECTION_MODE 15 /* Selection Mode 1 */
#define GTPIE_FL_DI 16 /* Flow Label Data I 2 */
#define GTPIE_TEI_DI 16 /* Tunnel Endpoint Identifier Data I 4 */
#define GTPIE_TEI_C 17 /* Tunnel Endpoint Identifier Control Plane 4 */
#define GTPIE_FL_C 17 /* Flow Label Signalling 2 */
#define GTPIE_TEI_DII 18 /* Tunnel Endpoint Identifier Data II 5 */
#define GTPIE_TEARDOWN 19 /* Teardown Ind 1 */
#define GTPIE_NSAPI 20 /* NSAPI 1 */
#define GTPIE_RANAP_CAUSE 21 /* RANAP Cause 1 */
#define GTPIE_RAB_CONTEXT 22 /* RAB Context 7 */
#define GTPIE_RP_SMS 23 /* Radio Priority SMS 1 */
#define GTPIE_RP 24 /* Radio Priority 1 */
#define GTPIE_PFI 25 /* Packet Flow Id 2 */
#define GTPIE_CHARGING_C 26 /* Charging Characteristics 2 */
#define GTPIE_TRACE_REF 27 /* Trace Reference 2 */
#define GTPIE_TRACE_TYPE 28 /* Trace Type 2 */
#define GTPIE_MS_NOT_REACH 29 /* MS Not Reachable Reason 1 */
/* 30-116 UNUSED */
#define GTPIE_CAUSE 1 /* Cause 1 */
#define GTPIE_IMSI 2 /* International Mobile Subscriber Identity 8 */
#define GTPIE_RAI 3 /* Routing Area Identity (RAI) 8 */
#define GTPIE_TLLI 4 /* Temporary Logical Link Identity (TLLI) 4 */
#define GTPIE_P_TMSI 5 /* Packet TMSI (P-TMSI) 4 */
#define GTPIE_QOS_PROFILE0 6 /* Quality of Service Profile GTP version 0 3 */
/* 6-7 SPARE *//* 6 is QoS Profile vers 0 */
#define GTPIE_REORDER 8 /* Reordering Required 1 */
#define GTPIE_AUTH_TRIPLET 9 /* Authentication Triplet 28 */
/* 10 SPARE */
#define GTPIE_MAP_CAUSE 11 /* MAP Cause 1 */
#define GTPIE_P_TMSI_S 12 /* P-TMSI Signature 3 */
#define GTPIE_MS_VALIDATED 13 /* MS Validated 1 */
#define GTPIE_RECOVERY 14 /* Recovery 1 */
#define GTPIE_SELECTION_MODE 15 /* Selection Mode 1 */
#define GTPIE_FL_DI 16 /* Flow Label Data I 2 */
#define GTPIE_TEI_DI 16 /* Tunnel Endpoint Identifier Data I 4 */
#define GTPIE_TEI_C 17 /* Tunnel Endpoint Identifier Control Plane 4 */
#define GTPIE_FL_C 17 /* Flow Label Signalling 2 */
#define GTPIE_TEI_DII 18 /* Tunnel Endpoint Identifier Data II 5 */
#define GTPIE_TEARDOWN 19 /* Teardown Ind 1 */
#define GTPIE_NSAPI 20 /* NSAPI 1 */
#define GTPIE_RANAP_CAUSE 21 /* RANAP Cause 1 */
#define GTPIE_RAB_CONTEXT 22 /* RAB Context 7 */
#define GTPIE_RP_SMS 23 /* Radio Priority SMS 1 */
#define GTPIE_RP 24 /* Radio Priority 1 */
#define GTPIE_PFI 25 /* Packet Flow Id 2 */
#define GTPIE_CHARGING_C 26 /* Charging Characteristics 2 */
#define GTPIE_TRACE_REF 27 /* Trace Reference 2 */
#define GTPIE_TRACE_TYPE 28 /* Trace Type 2 */
#define GTPIE_MS_NOT_REACH 29 /* MS Not Reachable Reason 1 */
/* 30-116 UNUSED */
/* 117-126 Reserved for the GPRS charging protocol (see GTP' in GSM 12.15) */
#define GTPIE_CHARGING_ID 127 /* Charging ID 4 */
#define GTPIE_EUA 128 /* End User Address */
#define GTPIE_MM_CONTEXT 129 /* MM Context */
#define GTPIE_PDP_CONTEXT 130 /* PDP Context */
#define GTPIE_APN 131 /* Access Point Name */
#define GTPIE_PCO 132 /* Protocol Configuration Options */
#define GTPIE_GSN_ADDR 133 /* GSN Address */
#define GTPIE_MSISDN 134 /* MS International PSTN/ISDN Number */
#define GTPIE_QOS_PROFILE 135 /* Quality of Service Profile */
#define GTPIE_AUTH_QUINTUP 136 /* Authentication Quintuplet */
#define GTPIE_TFT 137 /* Traffic Flow Template */
#define GTPIE_TARGET_INF 138 /* Target Identification */
#define GTPIE_UTRAN_TRANS 139 /* UTRAN Transparent Container */
#define GTPIE_RAB_SETUP 140 /* RAB Setup Information */
#define GTPIE_EXT_HEADER_T 141 /* Extension Header Type List */
#define GTPIE_TRIGGER_ID 142 /* Trigger Id */
#define GTPIE_OMC_ID 143 /* OMC Identity */
#define GTPIE_RAT_TYPE 151 /* Radio Access Technology Type */
#define GTPIE_USER_LOC 152 /* User Location Information */
#define GTPIE_MS_TZ 153 /* MS Time Zone */
#define GTPIE_IMEI_SV 154 /* IMEI Software Version */
#define GTPIE_CHARGING_ID 127 /* Charging ID 4 */
#define GTPIE_EUA 128 /* End User Address */
#define GTPIE_MM_CONTEXT 129 /* MM Context */
#define GTPIE_PDP_CONTEXT 130 /* PDP Context */
#define GTPIE_APN 131 /* Access Point Name */
#define GTPIE_PCO 132 /* Protocol Configuration Options */
#define GTPIE_GSN_ADDR 133 /* GSN Address */
#define GTPIE_MSISDN 134 /* MS International PSTN/ISDN Number */
#define GTPIE_QOS_PROFILE 135 /* Quality of Service Profile */
#define GTPIE_AUTH_QUINTUP 136 /* Authentication Quintuplet */
#define GTPIE_TFT 137 /* Traffic Flow Template */
#define GTPIE_TARGET_INF 138 /* Target Identification */
#define GTPIE_UTRAN_TRANS 139 /* UTRAN Transparent Container */
#define GTPIE_RAB_SETUP 140 /* RAB Setup Information */
#define GTPIE_EXT_HEADER_T 141 /* Extension Header Type List */
#define GTPIE_TRIGGER_ID 142 /* Trigger Id */
#define GTPIE_OMC_ID 143 /* OMC Identity */
#define GTPIE_RAT_TYPE 151 /* Radio Access Technology Type */
#define GTPIE_USER_LOC 152 /* User Location Information */
#define GTPIE_MS_TZ 153 /* MS Time Zone */
#define GTPIE_IMEI_SV 154 /* IMEI Software Version */
/* 239-250 Reserved for the GPRS charging protocol (see GTP' in GSM 12.15) */
#define GTPIE_CHARGING_ADDR 251 /* Charging Gateway Address */
#define GTPIE_CHARGING_ADDR 251 /* Charging Gateway Address */
/* 252-254 Reserved for the GPRS charging protocol (see GTP' in GSM 12.15) */
#define GTPIE_PRIVATE 255 /* Private Extension */
#define GTPIE_PRIVATE 255 /* Private Extension */
/* GTP information element structs in network order */
struct gtpie_ext { /* Extension header */
uint8_t t; /* Type */
uint8_t l; /* Length */
uint8_t *p; /* Value */
} __attribute__((packed));
struct gtpie_ext { /* Extension header */
uint8_t t; /* Type */
uint8_t l; /* Length */
uint8_t *p; /* Value */
} __attribute__ ((packed));
struct gtpie_tlv { /* Type length value pair */
uint8_t t; /* Type */
uint16_t l; /* Length */
uint8_t v[GTPIE_MAX_TLV]; /* Value */
} __attribute__((packed));
struct gtpie_tlv { /* Type length value pair */
uint8_t t; /* Type */
uint16_t l; /* Length */
uint8_t v[GTPIE_MAX_TLV]; /* Value */
} __attribute__ ((packed));
struct gtpie_tv0 { /* 1 byte type value pair */
uint8_t t; /* Type */
uint8_t v[GTPIE_MAX_TV]; /* Pointer to value */
}__attribute__((packed));
struct gtpie_tv0 { /* 1 byte type value pair */
uint8_t t; /* Type */
uint8_t v[GTPIE_MAX_TV]; /* Pointer to value */
} __attribute__ ((packed));
struct gtpie_tv1 { /* 1 byte type value pair */
uint8_t t; /* Type */
uint8_t v; /* Value */
}__attribute__((packed));
struct gtpie_tv1 { /* 1 byte type value pair */
uint8_t t; /* Type */
uint8_t v; /* Value */
} __attribute__ ((packed));
struct gtpie_tv2 { /* 2 byte type value pair */
uint8_t t; /* Type */
uint16_t v; /* Value */
}__attribute__((packed));
struct gtpie_tv2 { /* 2 byte type value pair */
uint8_t t; /* Type */
uint16_t v; /* Value */
} __attribute__ ((packed));
struct gtpie_tv4 { /* 4 byte type value pair */
uint8_t t; /* Type */
uint32_t v; /* Value */
}__attribute__((packed));
struct gtpie_tv8 { /* 8 byte type value pair */
uint8_t t; /* Type */
uint64_t v; /* Value */
}__attribute__((packed));
struct gtpie_tv4 { /* 4 byte type value pair */
uint8_t t; /* Type */
uint32_t v; /* Value */
} __attribute__ ((packed));
struct gtpie_tv8 { /* 8 byte type value pair */
uint8_t t; /* Type */
uint64_t v; /* Value */
} __attribute__ ((packed));
union gtpie_member {
uint8_t t;
struct gtpie_ext ext;
struct gtpie_tlv tlv;
struct gtpie_tv0 tv0;
struct gtpie_tv1 tv1;
struct gtpie_tv2 tv2;
struct gtpie_tv4 tv4;
struct gtpie_tv8 tv8;
}__attribute__((packed));
uint8_t t;
struct gtpie_ext ext;
struct gtpie_tlv tlv;
struct gtpie_tv0 tv0;
struct gtpie_tv1 tv1;
struct gtpie_tv2 tv2;
struct gtpie_tv4 tv4;
struct gtpie_tv8 tv8;
} __attribute__ ((packed));
/*
cause
@ -214,45 +210,46 @@ private
*/
struct tlv1 {
uint8_t type;
uint8_t length;
}__attribute__((packed));
uint8_t type;
uint8_t length;
} __attribute__ ((packed));
struct tlv2 {
uint8_t type;
uint16_t length;
}__attribute__((packed));
uint8_t type;
uint16_t length;
} __attribute__ ((packed));
extern int gtpie_tlv(void *p, unsigned int *length, unsigned int size,
uint8_t t, int l, void *v);
extern int gtpie_tv0(void *p, unsigned int *length, unsigned int size,
uint8_t t, int l, uint8_t *v);
extern int gtpie_tv1(void *p, unsigned int *length, unsigned int size, uint8_t t, uint8_t v);
extern int gtpie_tv2(void *p, unsigned int *length, unsigned int size, uint8_t t, uint16_t v);
extern int gtpie_tv4(void *p, unsigned int *length, unsigned int size, uint8_t t, uint32_t v);
extern int gtpie_tv8(void *p, unsigned int *length, unsigned int size, uint8_t t, uint64_t v);
extern int gtpie_getie(union gtpie_member* ie[], int type, int instance);
extern int gtpie_exist(union gtpie_member* ie[], int type, int instance);
extern int gtpie_gettlv(union gtpie_member* ie[], int type, int instance,
extern int gtpie_tv0(void *p, unsigned int *length, unsigned int size,
uint8_t t, int l, uint8_t * v);
extern int gtpie_tv1(void *p, unsigned int *length, unsigned int size,
uint8_t t, uint8_t v);
extern int gtpie_tv2(void *p, unsigned int *length, unsigned int size,
uint8_t t, uint16_t v);
extern int gtpie_tv4(void *p, unsigned int *length, unsigned int size,
uint8_t t, uint32_t v);
extern int gtpie_tv8(void *p, unsigned int *length, unsigned int size,
uint8_t t, uint64_t v);
extern int gtpie_getie(union gtpie_member *ie[], int type, int instance);
extern int gtpie_exist(union gtpie_member *ie[], int type, int instance);
extern int gtpie_gettlv(union gtpie_member *ie[], int type, int instance,
unsigned int *length, void *dst, unsigned int size);
extern int gtpie_gettv0(union gtpie_member* ie[], int type, int instance,
extern int gtpie_gettv0(union gtpie_member *ie[], int type, int instance,
void *dst, unsigned int size);
extern int gtpie_gettv1(union gtpie_member* ie[], int type, int instance,
uint8_t *dst);
extern int gtpie_gettv2(union gtpie_member* ie[], int type, int instance,
uint16_t *dst);
extern int gtpie_gettv4(union gtpie_member* ie[], int type, int instance,
uint32_t *dst);
extern int gtpie_gettv8(union gtpie_member* ie[], int type, int instance,
uint64_t *dst);
extern int gtpie_gettv1(union gtpie_member *ie[], int type, int instance,
uint8_t * dst);
extern int gtpie_gettv2(union gtpie_member *ie[], int type, int instance,
uint16_t * dst);
extern int gtpie_gettv4(union gtpie_member *ie[], int type, int instance,
uint32_t * dst);
extern int gtpie_gettv8(union gtpie_member *ie[], int type, int instance,
uint64_t * dst);
extern int gtpie_decaps(union gtpie_member* ie[], int version,
extern int gtpie_decaps(union gtpie_member *ie[], int version,
void *pack, unsigned len);
extern int gtpie_encaps(union gtpie_member* ie[], void *pack, unsigned *len);
extern int gtpie_encaps(union gtpie_member *ie[], void *pack, unsigned *len);
extern int gtpie_encaps2(union gtpie_member ie[], unsigned int size,
void *pack, unsigned *len);
#endif /* !_GTPIE_H */
void *pack, unsigned *len);
#endif /* !_GTPIE_H */

View File

@ -81,52 +81,64 @@ acceptable. Do NOT use for cryptographic purposes.
--------------------------------------------------------------------
*/
ub4 lookup( k, length, level)
register ub1 *k; /* the key */
register ub4 length; /* the length of the key */
register ub4 level; /* the previous hash, or an arbitrary value */
ub4 lookup(k, length, level)
register ub1 *k; /* the key */
register ub4 length; /* the length of the key */
register ub4 level; /* the previous hash, or an arbitrary value */
{
register ub4 a,b,c,len;
register ub4 a, b, c, len;
/* Set up the internal state */
len = length;
a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
c = level; /* the previous hash value */
/* Set up the internal state */
len = length;
a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
c = level; /* the previous hash value */
/*---------------------------------------- handle most of the key */
while (len >= 12)
{
a += (k[0] +((ub4)k[1]<<8) +((ub4)k[2]<<16) +((ub4)k[3]<<24));
b += (k[4] +((ub4)k[5]<<8) +((ub4)k[6]<<16) +((ub4)k[7]<<24));
c += (k[8] +((ub4)k[9]<<8) +((ub4)k[10]<<16)+((ub4)k[11]<<24));
mix(a,b,c);
k += 12; len -= 12;
}
while (len >= 12) {
a += (k[0] + ((ub4) k[1] << 8) + ((ub4) k[2] << 16) +
((ub4) k[3] << 24));
b += (k[4] + ((ub4) k[5] << 8) + ((ub4) k[6] << 16) +
((ub4) k[7] << 24));
c += (k[8] + ((ub4) k[9] << 8) + ((ub4) k[10] << 16) +
((ub4) k[11] << 24));
mix(a, b, c);
k += 12;
len -= 12;
}
/*------------------------------------- handle the last 11 bytes */
c += length;
switch(len) /* all the case statements fall through */
{
case 11: c+=((ub4)k[10]<<24);
case 10: c+=((ub4)k[9]<<16);
case 9 : c+=((ub4)k[8]<<8);
/* the first byte of c is reserved for the length */
case 8 : b+=((ub4)k[7]<<24);
case 7 : b+=((ub4)k[6]<<16);
case 6 : b+=((ub4)k[5]<<8);
case 5 : b+=k[4];
case 4 : a+=((ub4)k[3]<<24);
case 3 : a+=((ub4)k[2]<<16);
case 2 : a+=((ub4)k[1]<<8);
case 1 : a+=k[0];
/* case 0: nothing left to add */
}
mix(a,b,c);
c += length;
switch (len) { /* all the case statements fall through */
case 11:
c += ((ub4) k[10] << 24);
case 10:
c += ((ub4) k[9] << 16);
case 9:
c += ((ub4) k[8] << 8);
/* the first byte of c is reserved for the length */
case 8:
b += ((ub4) k[7] << 24);
case 7:
b += ((ub4) k[6] << 16);
case 6:
b += ((ub4) k[5] << 8);
case 5:
b += k[4];
case 4:
a += ((ub4) k[3] << 24);
case 3:
a += ((ub4) k[2] << 16);
case 2:
a += ((ub4) k[1] << 8);
case 1:
a += k[0];
/* case 0: nothing left to add */
}
mix(a, b, c);
/*-------------------------------------------- report the result */
return c;
return c;
}
/*
--------------------------------------------------------------------
mixc -- mixc 8 4-bit values as quickly and thoroughly as possible.
@ -169,78 +181,120 @@ Use to detect changes between revisions of documents, assuming nobody
is trying to cause collisions. Do NOT use for cryptography.
--------------------------------------------------------------------
*/
void checksum( k, len, state)
void checksum(k, len, state)
register ub1 *k;
register ub4 len;
register ub4 len;
register ub4 *state;
{
register ub4 a,b,c,d,e,f,g,h,length;
register ub4 a, b, c, d, e, f, g, h, length;
/* Use the length and level; add in the golden ratio. */
length = len;
a=state[0]; b=state[1]; c=state[2]; d=state[3];
e=state[4]; f=state[5]; g=state[6]; h=state[7];
/* Use the length and level; add in the golden ratio. */
length = len;
a = state[0];
b = state[1];
c = state[2];
d = state[3];
e = state[4];
f = state[5];
g = state[6];
h = state[7];
/*---------------------------------------- handle most of the key */
while (len >= 32)
{
a += (k[0] +(k[1]<<8) +(k[2]<<16) +(k[3]<<24));
b += (k[4] +(k[5]<<8) +(k[6]<<16) +(k[7]<<24));
c += (k[8] +(k[9]<<8) +(k[10]<<16)+(k[11]<<24));
d += (k[12]+(k[13]<<8)+(k[14]<<16)+(k[15]<<24));
e += (k[16]+(k[17]<<8)+(k[18]<<16)+(k[19]<<24));
f += (k[20]+(k[21]<<8)+(k[22]<<16)+(k[23]<<24));
g += (k[24]+(k[25]<<8)+(k[26]<<16)+(k[27]<<24));
h += (k[28]+(k[29]<<8)+(k[30]<<16)+(k[31]<<24));
mixc(a,b,c,d,e,f,g,h);
mixc(a,b,c,d,e,f,g,h);
mixc(a,b,c,d,e,f,g,h);
mixc(a,b,c,d,e,f,g,h);
k += 32; len -= 32;
}
while (len >= 32) {
a += (k[0] + (k[1] << 8) + (k[2] << 16) + (k[3] << 24));
b += (k[4] + (k[5] << 8) + (k[6] << 16) + (k[7] << 24));
c += (k[8] + (k[9] << 8) + (k[10] << 16) + (k[11] << 24));
d += (k[12] + (k[13] << 8) + (k[14] << 16) + (k[15] << 24));
e += (k[16] + (k[17] << 8) + (k[18] << 16) + (k[19] << 24));
f += (k[20] + (k[21] << 8) + (k[22] << 16) + (k[23] << 24));
g += (k[24] + (k[25] << 8) + (k[26] << 16) + (k[27] << 24));
h += (k[28] + (k[29] << 8) + (k[30] << 16) + (k[31] << 24));
mixc(a, b, c, d, e, f, g, h);
mixc(a, b, c, d, e, f, g, h);
mixc(a, b, c, d, e, f, g, h);
mixc(a, b, c, d, e, f, g, h);
k += 32;
len -= 32;
}
/*------------------------------------- handle the last 31 bytes */
h += length;
switch(len)
{
case 31: h+=(k[30]<<24);
case 30: h+=(k[29]<<16);
case 29: h+=(k[28]<<8);
case 28: g+=(k[27]<<24);
case 27: g+=(k[26]<<16);
case 26: g+=(k[25]<<8);
case 25: g+=k[24];
case 24: f+=(k[23]<<24);
case 23: f+=(k[22]<<16);
case 22: f+=(k[21]<<8);
case 21: f+=k[20];
case 20: e+=(k[19]<<24);
case 19: e+=(k[18]<<16);
case 18: e+=(k[17]<<8);
case 17: e+=k[16];
case 16: d+=(k[15]<<24);
case 15: d+=(k[14]<<16);
case 14: d+=(k[13]<<8);
case 13: d+=k[12];
case 12: c+=(k[11]<<24);
case 11: c+=(k[10]<<16);
case 10: c+=(k[9]<<8);
case 9 : c+=k[8];
case 8 : b+=(k[7]<<24);
case 7 : b+=(k[6]<<16);
case 6 : b+=(k[5]<<8);
case 5 : b+=k[4];
case 4 : a+=(k[3]<<24);
case 3 : a+=(k[2]<<16);
case 2 : a+=(k[1]<<8);
case 1 : a+=k[0];
}
mixc(a,b,c,d,e,f,g,h);
mixc(a,b,c,d,e,f,g,h);
mixc(a,b,c,d,e,f,g,h);
mixc(a,b,c,d,e,f,g,h);
h += length;
switch (len) {
case 31:
h += (k[30] << 24);
case 30:
h += (k[29] << 16);
case 29:
h += (k[28] << 8);
case 28:
g += (k[27] << 24);
case 27:
g += (k[26] << 16);
case 26:
g += (k[25] << 8);
case 25:
g += k[24];
case 24:
f += (k[23] << 24);
case 23:
f += (k[22] << 16);
case 22:
f += (k[21] << 8);
case 21:
f += k[20];
case 20:
e += (k[19] << 24);
case 19:
e += (k[18] << 16);
case 18:
e += (k[17] << 8);
case 17:
e += k[16];
case 16:
d += (k[15] << 24);
case 15:
d += (k[14] << 16);
case 14:
d += (k[13] << 8);
case 13:
d += k[12];
case 12:
c += (k[11] << 24);
case 11:
c += (k[10] << 16);
case 10:
c += (k[9] << 8);
case 9:
c += k[8];
case 8:
b += (k[7] << 24);
case 7:
b += (k[6] << 16);
case 6:
b += (k[5] << 8);
case 5:
b += k[4];
case 4:
a += (k[3] << 24);
case 3:
a += (k[2] << 16);
case 2:
a += (k[1] << 8);
case 1:
a += k[0];
}
mixc(a, b, c, d, e, f, g, h);
mixc(a, b, c, d, e, f, g, h);
mixc(a, b, c, d, e, f, g, h);
mixc(a, b, c, d, e, f, g, h);
/*-------------------------------------------- report the result */
state[0]=a; state[1]=b; state[2]=c; state[3]=d;
state[4]=e; state[5]=f; state[6]=g; state[7]=h;
state[0] = a;
state[1] = b;
state[2] = c;
state[3] = d;
state[4] = e;
state[5] = f;
state[6] = g;
state[7] = h;
}

View File

@ -16,14 +16,14 @@ Source is http://burtleburtle.net/bob/c/lookupa.h
#ifndef LOOKUPA
#define LOOKUPA
typedef unsigned long int ub4; /* unsigned 4-byte quantities */
typedef unsigned char ub1;
typedef unsigned long int ub4; /* unsigned 4-byte quantities */
typedef unsigned char ub1;
#define CHECKSTATE 8
#define hashsize(n) ((ub4)1<<(n))
#define hashmask(n) (hashsize(n)-1)
ub4 lookup(/*_ ub1 *k, ub4 length, ub4 level _*/);
void checksum(/*_ ub1 *k, ub4 length, ub4 *state _*/);
ub4 lookup( /*_ ub1 *k, ub4 length, ub4 level _*/ );
void checksum( /*_ ub1 *k, ub4 length, ub4 *state _*/ );
#endif /* LOOKUPA */

309
gtp/pdp.c
View File

@ -31,8 +31,8 @@
* Global variables TODO: most should be moved to gsn_t
*************************************************************/
struct pdp_t pdpa[PDP_MAX]; /* PDP storage */
struct pdp_t* hashtid[PDP_MAX];/* Hash table for IMSI + NSAPI */
struct pdp_t pdpa[PDP_MAX]; /* PDP storage */
struct pdp_t *hashtid[PDP_MAX]; /* Hash table for IMSI + NSAPI */
/* struct pdp_t* haship[PDP_MAX]; Hash table for IP and network interface */
/* ***********************************************************
@ -107,144 +107,171 @@ struct pdp_t* hashtid[PDP_MAX];/* Hash table for IMSI + NSAPI */
*
*************************************************************/
int pdp_init() {
memset(&pdpa, 0, sizeof(pdpa));
memset(&hashtid, 0, sizeof(hashtid));
/* memset(&haship, 0, sizeof(haship)); */
int pdp_init()
{
memset(&pdpa, 0, sizeof(pdpa));
memset(&hashtid, 0, sizeof(hashtid));
/* memset(&haship, 0, sizeof(haship)); */
return 0;
return 0;
}
int pdp_newpdp(struct pdp_t **pdp, uint64_t imsi, uint8_t nsapi,
struct pdp_t *pdp_old){
int n;
for (n=0; n<PDP_MAX; n++) { /* TODO: Need to do better than linear search */
if (pdpa[n].inuse == 0) {
*pdp = &pdpa[n];
if (NULL != pdp_old) memcpy(*pdp, pdp_old, sizeof(struct pdp_t));
else memset(*pdp, 0, sizeof(struct pdp_t));
(*pdp)->inuse = 1;
(*pdp)->imsi = imsi;
(*pdp)->nsapi = nsapi;
(*pdp)->fllc = (uint16_t) n + 1;
(*pdp)->fllu = (uint16_t) n + 1;
(*pdp)->teid_own = (uint32_t) n + 1;
if (!(*pdp)->secondary) (*pdp)->teic_own = (uint32_t) n + 1;
pdp_tidset(*pdp, pdp_gettid(imsi, nsapi));
/* Insert reference in primary context */
if (((*pdp)->teic_own > 0 ) && ((*pdp)->teic_own <= PDP_MAX)) {
pdpa[(*pdp)->teic_own-1].secondary_tei[(*pdp)->nsapi & 0x0f] =
(*pdp)->teid_own;
}
return 0;
}
}
return EOF; /* No more available */
int pdp_newpdp(struct pdp_t **pdp, uint64_t imsi, uint8_t nsapi,
struct pdp_t *pdp_old)
{
int n;
for (n = 0; n < PDP_MAX; n++) { /* TODO: Need to do better than linear search */
if (pdpa[n].inuse == 0) {
*pdp = &pdpa[n];
if (NULL != pdp_old)
memcpy(*pdp, pdp_old, sizeof(struct pdp_t));
else
memset(*pdp, 0, sizeof(struct pdp_t));
(*pdp)->inuse = 1;
(*pdp)->imsi = imsi;
(*pdp)->nsapi = nsapi;
(*pdp)->fllc = (uint16_t) n + 1;
(*pdp)->fllu = (uint16_t) n + 1;
(*pdp)->teid_own = (uint32_t) n + 1;
if (!(*pdp)->secondary)
(*pdp)->teic_own = (uint32_t) n + 1;
pdp_tidset(*pdp, pdp_gettid(imsi, nsapi));
/* Insert reference in primary context */
if (((*pdp)->teic_own > 0)
&& ((*pdp)->teic_own <= PDP_MAX)) {
pdpa[(*pdp)->teic_own -
1].secondary_tei[(*pdp)->nsapi & 0x0f] =
(*pdp)->teid_own;
}
return 0;
}
}
return EOF; /* No more available */
}
int pdp_freepdp(struct pdp_t *pdp){
pdp_tiddel(pdp);
int pdp_freepdp(struct pdp_t *pdp)
{
pdp_tiddel(pdp);
/* Remove any references in primary context */
if ((pdp->secondary) && (pdp->teic_own > 0 ) && (pdp->teic_own <= PDP_MAX)) {
pdpa[pdp->teic_own-1].secondary_tei[pdp->nsapi & 0x0f] = 0;
}
/* Remove any references in primary context */
if ((pdp->secondary) && (pdp->teic_own > 0)
&& (pdp->teic_own <= PDP_MAX)) {
pdpa[pdp->teic_own - 1].secondary_tei[pdp->nsapi & 0x0f] = 0;
}
memset(pdp, 0, sizeof(struct pdp_t));
return 0;
memset(pdp, 0, sizeof(struct pdp_t));
return 0;
}
int pdp_getpdp(struct pdp_t **pdp){
*pdp = &pdpa[0];
return 0;
int pdp_getpdp(struct pdp_t **pdp)
{
*pdp = &pdpa[0];
return 0;
}
int pdp_getgtp0(struct pdp_t **pdp, uint16_t fl){
if ((fl>PDP_MAX) || (fl<1)) {
return EOF; /* Not found */
}
else {
*pdp = &pdpa[fl-1];
if ((*pdp)->inuse) return 0;
else return EOF;
/* Context exists. We do no further validity checking. */
}
int pdp_getgtp0(struct pdp_t **pdp, uint16_t fl)
{
if ((fl > PDP_MAX) || (fl < 1)) {
return EOF; /* Not found */
} else {
*pdp = &pdpa[fl - 1];
if ((*pdp)->inuse)
return 0;
else
return EOF;
/* Context exists. We do no further validity checking. */
}
}
int pdp_getgtp1(struct pdp_t **pdp, uint32_t tei){
if ((tei>PDP_MAX) || (tei<1)) {
return EOF; /* Not found */
}
else {
*pdp = &pdpa[tei-1];
if ((*pdp)->inuse) return 0;
else return EOF;
/* Context exists. We do no further validity checking. */
}
int pdp_getgtp1(struct pdp_t **pdp, uint32_t tei)
{
if ((tei > PDP_MAX) || (tei < 1)) {
return EOF; /* Not found */
} else {
*pdp = &pdpa[tei - 1];
if ((*pdp)->inuse)
return 0;
else
return EOF;
/* Context exists. We do no further validity checking. */
}
}
int pdp_tidhash(uint64_t tid) {
return (lookup(&tid, sizeof(tid), 0) % PDP_MAX);
int pdp_tidhash(uint64_t tid)
{
return (lookup(&tid, sizeof(tid), 0) % PDP_MAX);
}
int pdp_tidset(struct pdp_t *pdp, uint64_t tid) {
int hash = pdp_tidhash(tid);
struct pdp_t *pdp2;
struct pdp_t *pdp_prev = NULL;
if (PDP_DEBUG) printf("Begin pdp_tidset tid = %llx\n", tid);
pdp->tidnext = NULL;
pdp->tid = tid;
for (pdp2 = hashtid[hash]; pdp2; pdp2 = pdp2->tidnext)
pdp_prev = pdp2;
if (!pdp_prev)
hashtid[hash] = pdp;
else
pdp_prev->tidnext = pdp;
if (PDP_DEBUG) printf("End pdp_tidset\n");
return 0;
int pdp_tidset(struct pdp_t *pdp, uint64_t tid)
{
int hash = pdp_tidhash(tid);
struct pdp_t *pdp2;
struct pdp_t *pdp_prev = NULL;
if (PDP_DEBUG)
printf("Begin pdp_tidset tid = %llx\n", tid);
pdp->tidnext = NULL;
pdp->tid = tid;
for (pdp2 = hashtid[hash]; pdp2; pdp2 = pdp2->tidnext)
pdp_prev = pdp2;
if (!pdp_prev)
hashtid[hash] = pdp;
else
pdp_prev->tidnext = pdp;
if (PDP_DEBUG)
printf("End pdp_tidset\n");
return 0;
}
int pdp_tiddel(struct pdp_t *pdp) {
int hash = pdp_tidhash(pdp->tid);
struct pdp_t *pdp2;
struct pdp_t *pdp_prev = NULL;
if (PDP_DEBUG) printf("Begin pdp_tiddel tid = %llx\n", pdp->tid);
for (pdp2 = hashtid[hash]; pdp2; pdp2 = pdp2->tidnext) {
if (pdp2 == pdp) {
if (!pdp_prev)
hashtid[hash] = pdp2->tidnext;
else
pdp_prev->tidnext = pdp2->tidnext;
if (PDP_DEBUG) printf("End pdp_tiddel: PDP found\n");
return 0;
}
pdp_prev = pdp2;
}
if (PDP_DEBUG) printf("End pdp_tiddel: PDP not found\n");
return EOF; /* End of linked list and not found */
int pdp_tiddel(struct pdp_t *pdp)
{
int hash = pdp_tidhash(pdp->tid);
struct pdp_t *pdp2;
struct pdp_t *pdp_prev = NULL;
if (PDP_DEBUG)
printf("Begin pdp_tiddel tid = %llx\n", pdp->tid);
for (pdp2 = hashtid[hash]; pdp2; pdp2 = pdp2->tidnext) {
if (pdp2 == pdp) {
if (!pdp_prev)
hashtid[hash] = pdp2->tidnext;
else
pdp_prev->tidnext = pdp2->tidnext;
if (PDP_DEBUG)
printf("End pdp_tiddel: PDP found\n");
return 0;
}
pdp_prev = pdp2;
}
if (PDP_DEBUG)
printf("End pdp_tiddel: PDP not found\n");
return EOF; /* End of linked list and not found */
}
int pdp_tidget(struct pdp_t **pdp, uint64_t tid) {
int hash = pdp_tidhash(tid);
struct pdp_t *pdp2;
if (PDP_DEBUG) printf("Begin pdp_tidget tid = %llx\n", tid);
for (pdp2 = hashtid[hash]; pdp2; pdp2 = pdp2->tidnext) {
if (pdp2->tid == tid) {
*pdp = pdp2;
if (PDP_DEBUG) printf("Begin pdp_tidget. Found\n");
return 0;
}
}
if (PDP_DEBUG) printf("Begin pdp_tidget. Not found\n");
return EOF; /* End of linked list and not found */
int pdp_tidget(struct pdp_t **pdp, uint64_t tid)
{
int hash = pdp_tidhash(tid);
struct pdp_t *pdp2;
if (PDP_DEBUG)
printf("Begin pdp_tidget tid = %llx\n", tid);
for (pdp2 = hashtid[hash]; pdp2; pdp2 = pdp2->tidnext) {
if (pdp2->tid == tid) {
*pdp = pdp2;
if (PDP_DEBUG)
printf("Begin pdp_tidget. Found\n");
return 0;
}
}
if (PDP_DEBUG)
printf("Begin pdp_tidget. Not found\n");
return EOF; /* End of linked list and not found */
}
int pdp_getimsi(struct pdp_t **pdp, uint64_t imsi, uint8_t nsapi) {
return pdp_tidget(pdp,
(imsi & 0x0fffffffffffffffull) + ((uint64_t)nsapi << 60));
int pdp_getimsi(struct pdp_t **pdp, uint64_t imsi, uint8_t nsapi)
{
return pdp_tidget(pdp,
(imsi & 0x0fffffffffffffffull) +
((uint64_t) nsapi << 60));
}
/*
@ -320,32 +347,36 @@ int pdp_ipget(struct pdp_t **pdp, void* ipif, struct ul66_t *eua) {
*/
/* Various conversion functions */
int pdp_ntoeua(struct in_addr *src, struct ul66_t *eua) {
eua->l=6;
eua->v[0]=0xf1; /* IETF */
eua->v[1]=0x21; /* IPv4 */
memcpy(&eua->v[2], src, 4); /* Copy a 4 byte address */
return 0;
int pdp_ntoeua(struct in_addr *src, struct ul66_t *eua)
{
eua->l = 6;
eua->v[0] = 0xf1; /* IETF */
eua->v[1] = 0x21; /* IPv4 */
memcpy(&eua->v[2], src, 4); /* Copy a 4 byte address */
return 0;
}
int pdp_euaton(struct ul66_t *eua, struct in_addr *dst) {
if((eua->l!=6) || (eua->v[0]!=0xf1) || (eua->v[1]!=0x21)) {
return EOF;
}
memcpy(dst, &eua->v[2], 4); /* Copy a 4 byte address */
return 0;
int pdp_euaton(struct ul66_t *eua, struct in_addr *dst)
{
if ((eua->l != 6) || (eua->v[0] != 0xf1) || (eua->v[1] != 0x21)) {
return EOF;
}
memcpy(dst, &eua->v[2], 4); /* Copy a 4 byte address */
return 0;
}
uint64_t pdp_gettid(uint64_t imsi, uint8_t nsapi) {
return (imsi & 0x0fffffffffffffffull) + ((uint64_t)nsapi << 60);
uint64_t pdp_gettid(uint64_t imsi, uint8_t nsapi)
{
return (imsi & 0x0fffffffffffffffull) + ((uint64_t) nsapi << 60);
}
int ulcpy(void* dst, void* src, size_t size) {
if (((struct ul255_t*)src)->l <= size) {
((struct ul255_t*)dst)->l = ((struct ul255_t*)src)->l;
memcpy(((struct ul255_t*)dst)->v, ((struct ul255_t*)src)->v,
((struct ul255_t*)dst)->l);
return 0;
}
else return EOF;
int ulcpy(void *dst, void *src, size_t size)
{
if (((struct ul255_t *)src)->l <= size) {
((struct ul255_t *)dst)->l = ((struct ul255_t *)src)->l;
memcpy(((struct ul255_t *)dst)->v, ((struct ul255_t *)src)->v,
((struct ul255_t *)dst)->l);
return 0;
} else
return EOF;
}

236
gtp/pdp.h
View File

@ -12,42 +12,40 @@
#ifndef _PDP_H
#define _PDP_H
#define PDP_MAX 1024 /* Max number of PDP contexts */
#define PDP_MAXNSAPI 16 /* Max number of NSAPI */
#define PDP_MAX 1024 /* Max number of PDP contexts */
#define PDP_MAXNSAPI 16 /* Max number of NSAPI */
#define PDP_DEBUG 0 /* Print debug information */
#define PDP_DEBUG 0 /* Print debug information */
/* GTP Information elements from 29.060 v3.9.0 7.7 Information Elements */
/* Also covers version 0. Note that version 0 6: QOS Profile was superceded *
* by 135: QOS Profile in version 1 */
struct sl_t {
unsigned int l;
char *v;
unsigned int l;
char *v;
};
struct ul_t {
unsigned int l;
unsigned char *v;
unsigned int l;
unsigned char *v;
};
struct ul16_t {
unsigned int l;
unsigned char v[16];
unsigned int l;
unsigned char v[16];
};
struct ul66_t {
unsigned int l;
unsigned char v[66];
unsigned int l;
unsigned char v[66];
};
struct ul255_t {
unsigned int l;
unsigned char v[255];
unsigned int l;
unsigned char v[255];
};
/* *****************************************************************
* Information storage for each PDP context
*
@ -103,131 +101,130 @@ unsigned char v[255];
*****************************************************************/
struct pdp_t {
/* Parameter determining if this PDP is in use. */
uint8_t inuse; /* 0=free. 1=used by somebody */
/* Parameter determining if this PDP is in use. */
uint8_t inuse; /* 0=free. 1=used by somebody */
/* Pointers related to hash tables */
struct pdp_t *tidnext;
struct pdp_t *ipnext;
/* Pointers related to hash tables */
struct pdp_t *tidnext;
struct pdp_t *ipnext;
/* Parameters shared by all PDP context belonging to the same MS */
/* Parameters shared by all PDP context belonging to the same MS */
void *ipif; /* IP network interface */
void *peer; /* Pointer to peer protocol */
void *asap; /* Application specific service access point */
void *ipif; /* IP network interface */
void *peer; /* Pointer to peer protocol */
void *asap; /* Application specific service access point */
uint64_t imsi; /* International Mobile Subscriber Identity.*/
struct ul16_t msisdn; /* The basic MSISDN of the MS. */
uint8_t mnrg; /* Indicates whether the MS is marked as not reachable for PS at the HLR. (1 bit, not transmitted) */
uint8_t cch_sub; /* The charging characteristics for the MS, e.g. normal, prepaid, flat-rate, and/or hot billing subscription. (not transmitted) */
uint16_t traceref; /* Identifies a record or a collection of records for a particular trace. */
uint16_t tracetype;/* Indicates the type of trace. */
struct ul_t triggerid;/* Identifies the entity that initiated the trace. */
struct ul_t omcid; /* Identifies the OMC that shall receive the trace record(s). */
uint8_t rec_hlr; /* Indicates if HLR or VLR is performing database recovery. (1 bit, not transmitted) */
uint64_t imsi; /* International Mobile Subscriber Identity. */
struct ul16_t msisdn; /* The basic MSISDN of the MS. */
uint8_t mnrg; /* Indicates whether the MS is marked as not reachable for PS at the HLR. (1 bit, not transmitted) */
uint8_t cch_sub; /* The charging characteristics for the MS, e.g. normal, prepaid, flat-rate, and/or hot billing subscription. (not transmitted) */
uint16_t traceref; /* Identifies a record or a collection of records for a particular trace. */
uint16_t tracetype; /* Indicates the type of trace. */
struct ul_t triggerid; /* Identifies the entity that initiated the trace. */
struct ul_t omcid; /* Identifies the OMC that shall receive the trace record(s). */
uint8_t rec_hlr; /* Indicates if HLR or VLR is performing database recovery. (1 bit, not transmitted) */
/* Parameters specific to each individual PDP context */
/* Parameters specific to each individual PDP context */
uint8_t pdp_id; /* Index of the PDP context. (PDP context identifier) */
uint8_t pdp_state;/* PDP State Packet data protocol state, INACTIVE or ACTIVE. (1 bit, not transmitted) */
/* struct ul_t pdp_type; * PDP type; e.g. PPP or IP. */
/* struct ul_t pdp_addr; * PDP address; e.g. an IP address. */
struct ul66_t eua; /* End user address. PDP type and address combined */
uint8_t pdp_dyn; /* Indicates whether PDP Address is static or dynamic. (1 bit, not transmitted) */
struct ul255_t apn_req;/* The APN requested. */
struct ul255_t apn_sub;/* The APN received from the HLR. */
struct ul255_t apn_use;/* The APN Network Identifier currently used. */
uint8_t nsapi; /* Network layer Service Access Point Identifier. (4 bit) */
uint16_t ti; /* Transaction Identifier. (4 or 12 bit) */
uint8_t pdp_id; /* Index of the PDP context. (PDP context identifier) */
uint8_t pdp_state; /* PDP State Packet data protocol state, INACTIVE or ACTIVE. (1 bit, not transmitted) */
/* struct ul_t pdp_type; * PDP type; e.g. PPP or IP. */
/* struct ul_t pdp_addr; * PDP address; e.g. an IP address. */
struct ul66_t eua; /* End user address. PDP type and address combined */
uint8_t pdp_dyn; /* Indicates whether PDP Address is static or dynamic. (1 bit, not transmitted) */
struct ul255_t apn_req; /* The APN requested. */
struct ul255_t apn_sub; /* The APN received from the HLR. */
struct ul255_t apn_use; /* The APN Network Identifier currently used. */
uint8_t nsapi; /* Network layer Service Access Point Identifier. (4 bit) */
uint16_t ti; /* Transaction Identifier. (4 or 12 bit) */
uint32_t teic_own; /* (Own Tunnel Endpoint Identifier Control) */
uint32_t teid_own; /* (Own Tunnel Endpoint Identifier Data I) */
uint32_t teic_gn; /* Tunnel Endpoint Identifier for the Gn and Gp interfaces. (Control plane) */
uint32_t teid_gn; /* Tunnel Endpoint Identifier for the Gn and Gp interfaces. (Data I) */
uint32_t tei_iu; /* Tunnel Endpoint Identifier for the Iu interface. */
uint32_t teic_own; /* (Own Tunnel Endpoint Identifier Control) */
uint32_t teid_own; /* (Own Tunnel Endpoint Identifier Data I) */
uint32_t teic_gn; /* Tunnel Endpoint Identifier for the Gn and Gp interfaces. (Control plane) */
uint32_t teid_gn; /* Tunnel Endpoint Identifier for the Gn and Gp interfaces. (Data I) */
uint32_t tei_iu; /* Tunnel Endpoint Identifier for the Iu interface. */
uint16_t fllc; /* (Local Flow Label Control, gtp0) */
uint16_t fllu; /* (Local Flow Label Data I, gtp0) */
uint16_t flrc; /* (Remote gn/gp Flow Label Control, gtp0) */
uint16_t flru; /* (Remote gn/gp Flow Label Data I, gtp0) */
uint16_t fllc; /* (Local Flow Label Control, gtp0) */
uint16_t fllu; /* (Local Flow Label Data I, gtp0) */
uint16_t flrc; /* (Remote gn/gp Flow Label Control, gtp0) */
uint16_t flru; /* (Remote gn/gp Flow Label Data I, gtp0) */
struct ul255_t tft; /* Traffic flow template. */
/*struct ul16_t sgsnc; * The IP address of the SGSN currently serving this MS. (Control plane) */
/*struct ul16_t sgsnu; * The IP address of the SGSN currently serving this MS. (User plane) */
/*struct ul16_t ggsnc; * The IP address of the GGSN currently used. (Control plane) */
/*struct ul16_t ggsnu; * The IP address of the GGSN currently used. (User plane) */
struct ul255_t tft; /* Traffic flow template. */
/*struct ul16_t sgsnc; * The IP address of the SGSN currently serving this MS. (Control plane) */
/*struct ul16_t sgsnu; * The IP address of the SGSN currently serving this MS. (User plane) */
/*struct ul16_t ggsnc; * The IP address of the GGSN currently used. (Control plane) */
/*struct ul16_t ggsnu; * The IP address of the GGSN currently used. (User plane) */
struct ul16_t gsnlc; /* The IP address of the local GSN. (Control plane) */
struct ul16_t gsnlu; /* The IP address of the local GSN. (User plane) */
struct ul16_t gsnrc; /* The IP address of the remote GSN. (Control plane) */
struct ul16_t gsnru; /* The IP address of the remote GSN. (User plane) */
struct ul16_t gsnlc; /* The IP address of the local GSN. (Control plane) */
struct ul16_t gsnlu; /* The IP address of the local GSN. (User plane) */
struct ul16_t gsnrc; /* The IP address of the remote GSN. (Control plane) */
struct ul16_t gsnru; /* The IP address of the remote GSN. (User plane) */
uint8_t vplmn_allow; /* Specifies whether the MS is allowed to use the APN in the domain of the HPLMN only, or additionally the APN in the domain of the VPLMN. (1 bit) */
uint8_t qos_sub0[3]; /* The quality of service profile subscribed. */
uint8_t qos_req0[3]; /* The quality of service profile requested. */
uint8_t qos_neg0[3]; /* The quality of service profile negotiated. */
struct ul255_t qos_sub; /* The quality of service profile subscribed. */
struct ul255_t qos_req; /* The quality of service profile requested. */
struct ul255_t qos_neg; /* The quality of service profile negotiated. */
uint8_t radio_pri;/* The RLC/MAC radio priority level for uplink user data transmission. (4 bit) */
uint16_t flow_id; /* Packet flow identifier. */
/* struct ul_t bssqos_neg; * The aggregate BSS quality of service profile negotiated for the packet flow that this PDP context belongs to. (NOT GTP)*/
uint8_t sndcpd; /* SNDCP sequence number of the next downlink N-PDU to be sent to the MS. */
uint8_t sndcpu; /* SNDCP sequence number of the next uplink N-PDU expected from the MS. */
uint8_t rec_sgsn; /* Indicates if the SGSN is performing database recovery. (1 bit, not transmitted) */
uint8_t vplmn_allow; /* Specifies whether the MS is allowed to use the APN in the domain of the HPLMN only, or additionally the APN in the domain of the VPLMN. (1 bit) */
uint8_t qos_sub0[3]; /* The quality of service profile subscribed. */
uint8_t qos_req0[3]; /* The quality of service profile requested. */
uint8_t qos_neg0[3]; /* The quality of service profile negotiated. */
struct ul255_t qos_sub; /* The quality of service profile subscribed. */
struct ul255_t qos_req; /* The quality of service profile requested. */
struct ul255_t qos_neg; /* The quality of service profile negotiated. */
uint8_t radio_pri; /* The RLC/MAC radio priority level for uplink user data transmission. (4 bit) */
uint16_t flow_id; /* Packet flow identifier. */
/* struct ul_t bssqos_neg; * The aggregate BSS quality of service profile negotiated for the packet flow that this PDP context belongs to. (NOT GTP) */
uint8_t sndcpd; /* SNDCP sequence number of the next downlink N-PDU to be sent to the MS. */
uint8_t sndcpu; /* SNDCP sequence number of the next uplink N-PDU expected from the MS. */
uint8_t rec_sgsn; /* Indicates if the SGSN is performing database recovery. (1 bit, not transmitted) */
/* uint16_t gtpsnd; GTP-U sequence number of the next downlink N-PDU to be sent to the SGSN / received from the GGSN. */
/* uint16_t gtpsnu; GTP-U sequence number of the next uplink N-PDU to be received from the SGSN / sent to the GGSN */
uint16_t gtpsntx; /* GTP-U sequence number of the next downlink N-PDU to be sent (09.60 section 8.1.1.1) */
uint16_t gtpsnrx; /* GTP-U sequence number of the next uplink N-PDU to be received (09.60 section 8.1.1.1) */
uint8_t pdcpsndd; /* Sequence number of the next downlink in-sequence PDCP-PDU to be sent to the MS. */
uint8_t pdcpsndu; /* Sequence number of the next uplink in-sequence PDCP-PDU expected from the MS. */
uint32_t cid; /* Charging identifier, identifies charging records generated by SGSN and GGSN. */
uint16_t cch_pdp; /* The charging characteristics for this PDP context, e.g. normal, prepaid, flat-rate, and/or hot billing. */
struct ul16_t rnc_addr;/* The IP address of the RNC currently used. */
uint8_t reorder; /* Specifies whether the GGSN shall reorder N-PDUs received from the SGSN / Specifies whether the SGSN shall reorder N-PDUs before delivering the N-PSUs to the MS. (1 bit) */
struct ul255_t pco_req; /* Requested packet control options. */
struct ul255_t pco_neg; /* Negotiated packet control options. */
uint32_t selmode; /* Selection mode. */
struct ul255_t rattype; /* Radio Access Technology Type */
int rattype_given; /* Radio Access Technology Type given*/
struct ul255_t userloc; /* User Location Information */
int userloc_given; /* User Location Information given*/
struct ul255_t rai; /* Routing Area Information */
int rai_given; /* Routing Area Information given*/
struct ul255_t mstz; /* MS Time Zone */
int mstz_given; /* MS Time Zone given*/
struct ul255_t imeisv; /* IMEI Software Version */
int imeisv_given; /* IMEI Software Version given*/
int norecovery_given; /* norecovery given*/
uint16_t gtpsntx; /* GTP-U sequence number of the next downlink N-PDU to be sent (09.60 section 8.1.1.1) */
uint16_t gtpsnrx; /* GTP-U sequence number of the next uplink N-PDU to be received (09.60 section 8.1.1.1) */
uint8_t pdcpsndd; /* Sequence number of the next downlink in-sequence PDCP-PDU to be sent to the MS. */
uint8_t pdcpsndu; /* Sequence number of the next uplink in-sequence PDCP-PDU expected from the MS. */
uint32_t cid; /* Charging identifier, identifies charging records generated by SGSN and GGSN. */
uint16_t cch_pdp; /* The charging characteristics for this PDP context, e.g. normal, prepaid, flat-rate, and/or hot billing. */
struct ul16_t rnc_addr; /* The IP address of the RNC currently used. */
uint8_t reorder; /* Specifies whether the GGSN shall reorder N-PDUs received from the SGSN / Specifies whether the SGSN shall reorder N-PDUs before delivering the N-PSUs to the MS. (1 bit) */
struct ul255_t pco_req; /* Requested packet control options. */
struct ul255_t pco_neg; /* Negotiated packet control options. */
uint32_t selmode; /* Selection mode. */
struct ul255_t rattype; /* Radio Access Technology Type */
int rattype_given; /* Radio Access Technology Type given */
struct ul255_t userloc; /* User Location Information */
int userloc_given; /* User Location Information given */
struct ul255_t rai; /* Routing Area Information */
int rai_given; /* Routing Area Information given */
struct ul255_t mstz; /* MS Time Zone */
int mstz_given; /* MS Time Zone given */
struct ul255_t imeisv; /* IMEI Software Version */
int imeisv_given; /* IMEI Software Version given */
int norecovery_given; /* norecovery given */
/* Additional parameters used by library */
/* Additional parameters used by library */
int version; /* Protocol version currently in use. 0 or 1 */
int version; /* Protocol version currently in use. 0 or 1 */
uint64_t tid; /* Combination of imsi and nsapi */
uint16_t seq; /* Sequence number of last request */
struct sockaddr_in sa_peer; /* Address of last request */
int fd; /* File descriptor request was received on */
uint64_t tid; /* Combination of imsi and nsapi */
uint16_t seq; /* Sequence number of last request */
struct sockaddr_in sa_peer; /* Address of last request */
int fd; /* File descriptor request was received on */
uint8_t teic_confirmed; /* 0: Not confirmed. 1: Confirmed */
uint8_t teic_confirmed; /* 0: Not confirmed. 1: Confirmed */
/* Parameters used for secondary activation procedure (tei data) */
/* If (secondary == 1) then teic_own indicates linked PDP context */
uint8_t secondary; /* 0: Primary (control). 1: Secondary (data only) */
uint8_t nodata; /* 0: User plane PDP context. 1: No user plane */
/* Parameters used for secondary activation procedure (tei data) */
/* If (secondary == 1) then teic_own indicates linked PDP context */
uint8_t secondary; /* 0: Primary (control). 1: Secondary (data only) */
uint8_t nodata; /* 0: User plane PDP context. 1: No user plane */
/* Secondary contexts of this primary context */
uint32_t secondary_tei[PDP_MAXNSAPI];
/* Secondary contexts of this primary context */
uint32_t secondary_tei[PDP_MAXNSAPI];
/* IP address used for Create and Update PDP Context Requests */
struct in_addr hisaddr0; /* Server address */
struct in_addr hisaddr1; /* Server address */
/* IP address used for Create and Update PDP Context Requests */
struct in_addr hisaddr0; /* Server address */
struct in_addr hisaddr1; /* Server address */
/* to be used by libgtp callers/users (to attach their own private state) */
void *priv;
/* to be used by libgtp callers/users (to attach their own private state) */
void *priv;
};
/* functions related to pdp_t management */
int pdp_init();
int pdp_newpdp(struct pdp_t **pdp, uint64_t imsi, uint8_t nsapi,
@ -245,7 +242,6 @@ int pdp_tidset(struct pdp_t *pdp, uint64_t tid);
int pdp_tiddel(struct pdp_t *pdp);
int pdp_tidget(struct pdp_t **pdp, uint64_t tid);
/*
int pdp_iphash(void* ipif, struct ul66_t *eua);
int pdp_ipset(struct pdp_t *pdp, void* ipif, struct ul66_t *eua);
@ -256,6 +252,6 @@ int pdp_ipget(struct pdp_t **pdp, void* ipif, struct ul66_t *eua);
int pdp_ntoeua(struct in_addr *src, struct ul66_t *eua);
int pdp_euaton(struct ul66_t *eua, struct in_addr *dst);
uint64_t pdp_gettid(uint64_t imsi, uint8_t nsapi);
int ulcpy(void* dst, void* src, size_t size);
int ulcpy(void *dst, void *src, size_t size);
#endif /* !_PDP_H */
#endif /* !_PDP_H */

View File

@ -29,224 +29,260 @@
#include "gtp.h"
#include "queue.h"
int queue_print(struct queue_t *queue) {
int n;
printf("Queue: %x Next: %d First: %d Last: %d\n", (int) queue, queue->next, queue->first, queue->last);
printf("# State seq next prev timeout retrans\n");
for (n=0; n<QUEUE_SIZE; n++) {
printf("%d %d %d %d %d %d %d\n",
n,
queue->qmsga[n].state,
queue->qmsga[n].seq,
queue->qmsga[n].next,
queue->qmsga[n].prev,
(int) queue->qmsga[n].timeout,
queue->qmsga[n].retrans);
}
return 0;
int queue_print(struct queue_t *queue)
{
int n;
printf("Queue: %x Next: %d First: %d Last: %d\n", (int)queue,
queue->next, queue->first, queue->last);
printf("# State seq next prev timeout retrans\n");
for (n = 0; n < QUEUE_SIZE; n++) {
printf("%d %d %d %d %d %d %d\n",
n,
queue->qmsga[n].state,
queue->qmsga[n].seq,
queue->qmsga[n].next,
queue->qmsga[n].prev,
(int)queue->qmsga[n].timeout, queue->qmsga[n].retrans);
}
return 0;
}
int queue_seqhash(struct sockaddr_in *peer, uint16_t seq) {
/* With QUEUE_HASH_SIZE = 2^16 this describes all possible
seq values. Thus we have perfect hash for the request queue.
For the response queue we might have collisions, but not very
often.
For performance optimisation we should remove the modulus
operator, but this is only valid for QUEUE_HASH_SIZE = 2^16 */
return seq % QUEUE_HASH_SIZE;
int queue_seqhash(struct sockaddr_in *peer, uint16_t seq)
{
/* With QUEUE_HASH_SIZE = 2^16 this describes all possible
seq values. Thus we have perfect hash for the request queue.
For the response queue we might have collisions, but not very
often.
For performance optimisation we should remove the modulus
operator, but this is only valid for QUEUE_HASH_SIZE = 2^16 */
return seq % QUEUE_HASH_SIZE;
}
int queue_seqset(struct queue_t *queue, struct qmsg_t *qmsg,
struct sockaddr_in *peer, uint16_t seq) {
int hash = queue_seqhash(peer, seq);
struct qmsg_t *qmsg2;
struct qmsg_t *qmsg_prev = NULL;
struct sockaddr_in *peer, uint16_t seq)
{
int hash = queue_seqhash(peer, seq);
struct qmsg_t *qmsg2;
struct qmsg_t *qmsg_prev = NULL;
if (QUEUE_DEBUG) printf("Begin queue_seqset seq = %d\n", (int) seq);
if (QUEUE_DEBUG) printf("SIZEOF PEER %d, *PEER %d\n", sizeof(peer), sizeof(*peer));
if (QUEUE_DEBUG)
printf("Begin queue_seqset seq = %d\n", (int)seq);
if (QUEUE_DEBUG)
printf("SIZEOF PEER %d, *PEER %d\n", sizeof(peer),
sizeof(*peer));
qmsg->seq = seq;
memcpy(&qmsg->peer, peer, sizeof(*peer));
qmsg->seq = seq;
memcpy(&qmsg->peer, peer, sizeof(*peer));
for (qmsg2 = queue->hashseq[hash]; qmsg2; qmsg2 = qmsg2->seqnext)
qmsg_prev = qmsg2;
if (!qmsg_prev)
queue->hashseq[hash] = qmsg;
else
qmsg_prev->seqnext = qmsg;
if (QUEUE_DEBUG) printf("End queue_seqset\n");
return 0;
for (qmsg2 = queue->hashseq[hash]; qmsg2; qmsg2 = qmsg2->seqnext)
qmsg_prev = qmsg2;
if (!qmsg_prev)
queue->hashseq[hash] = qmsg;
else
qmsg_prev->seqnext = qmsg;
if (QUEUE_DEBUG)
printf("End queue_seqset\n");
return 0;
}
int queue_seqdel(struct queue_t *queue, struct qmsg_t *qmsg)
{
int hash = queue_seqhash(&qmsg->peer, qmsg->seq);
struct qmsg_t *qmsg2;
struct qmsg_t *qmsg_prev = NULL;
if (QUEUE_DEBUG)
printf("Begin queue_seqdel seq = %d\n", (int)qmsg->seq);
int queue_seqdel(struct queue_t *queue, struct qmsg_t *qmsg) {
int hash = queue_seqhash(&qmsg->peer, qmsg->seq);
struct qmsg_t *qmsg2;
struct qmsg_t *qmsg_prev = NULL;
if (QUEUE_DEBUG) printf("Begin queue_seqdel seq = %d\n", (int) qmsg->seq);
for (qmsg2 = queue->hashseq[hash]; qmsg2; qmsg2 = qmsg2->seqnext) {
if (qmsg == qmsg) {
if (!qmsg_prev)
queue->hashseq[hash] = qmsg2->seqnext;
else
qmsg_prev->seqnext = qmsg2->seqnext;
if (QUEUE_DEBUG) printf("End queue_seqset: SEQ found\n");
return 0;
}
qmsg_prev = qmsg2;
}
printf("End queue_seqset: SEQ not found\n");
return EOF; /* End of linked list and not found */
for (qmsg2 = queue->hashseq[hash]; qmsg2; qmsg2 = qmsg2->seqnext) {
if (qmsg == qmsg) {
if (!qmsg_prev)
queue->hashseq[hash] = qmsg2->seqnext;
else
qmsg_prev->seqnext = qmsg2->seqnext;
if (QUEUE_DEBUG)
printf("End queue_seqset: SEQ found\n");
return 0;
}
qmsg_prev = qmsg2;
}
printf("End queue_seqset: SEQ not found\n");
return EOF; /* End of linked list and not found */
}
/* Allocates and initialises new queue structure */
int queue_new(struct queue_t **queue) {
if (QUEUE_DEBUG) printf("queue_new\n");
*queue = calloc(1, sizeof(struct queue_t));
(*queue)->next = 0;
(*queue)->first = -1;
(*queue)->last = -1;
int queue_new(struct queue_t **queue)
{
if (QUEUE_DEBUG)
printf("queue_new\n");
*queue = calloc(1, sizeof(struct queue_t));
(*queue)->next = 0;
(*queue)->first = -1;
(*queue)->last = -1;
if (QUEUE_DEBUG) queue_print(*queue);
if (*queue) return 0;
else return EOF;
if (QUEUE_DEBUG)
queue_print(*queue);
if (*queue)
return 0;
else
return EOF;
}
/* Deallocates queue structure */
int queue_free(struct queue_t *queue) {
if (QUEUE_DEBUG) printf("queue_free\n");
if (QUEUE_DEBUG) queue_print(queue);
free(queue);
return 0;
int queue_free(struct queue_t *queue)
{
if (QUEUE_DEBUG)
printf("queue_free\n");
if (QUEUE_DEBUG)
queue_print(queue);
free(queue);
return 0;
}
int queue_newmsg(struct queue_t *queue, struct qmsg_t **qmsg,
struct sockaddr_in *peer, uint16_t seq) {
if (QUEUE_DEBUG) printf("queue_newmsg %d\n", (int) seq);
if (queue->qmsga[queue->next].state == 1) {
return EOF; /* Queue is full */
}
else {
*qmsg = &queue->qmsga[queue->next];
queue_seqset(queue, *qmsg, peer, seq);
(*qmsg)->state = 1; /* Space taken */
(*qmsg)->this = queue->next;
(*qmsg)->next=-1; /* End of the queue */
(*qmsg)->prev=queue->last; /* Link to the previous */
if (queue->last != -1)
queue->qmsga[queue->last].next=queue->next; /* Link previous to us */
queue->last = queue->next; /* End of queue */
if (queue->first == -1) queue->first = queue->next;
queue->next = (queue->next+1) % QUEUE_SIZE; /* Increment */
if (QUEUE_DEBUG) queue_print(queue);
return 0;
}
struct sockaddr_in *peer, uint16_t seq)
{
if (QUEUE_DEBUG)
printf("queue_newmsg %d\n", (int)seq);
if (queue->qmsga[queue->next].state == 1) {
return EOF; /* Queue is full */
} else {
*qmsg = &queue->qmsga[queue->next];
queue_seqset(queue, *qmsg, peer, seq);
(*qmsg)->state = 1; /* Space taken */
(*qmsg)->this = queue->next;
(*qmsg)->next = -1; /* End of the queue */
(*qmsg)->prev = queue->last; /* Link to the previous */
if (queue->last != -1)
queue->qmsga[queue->last].next = queue->next; /* Link previous to us */
queue->last = queue->next; /* End of queue */
if (queue->first == -1)
queue->first = queue->next;
queue->next = (queue->next + 1) % QUEUE_SIZE; /* Increment */
if (QUEUE_DEBUG)
queue_print(queue);
return 0;
}
}
int queue_freemsg(struct queue_t *queue, struct qmsg_t *qmsg) {
if (QUEUE_DEBUG) printf("queue_freemsg\n");
if (qmsg->state != 1) {
return EOF; /* Not in queue */
}
int queue_freemsg(struct queue_t *queue, struct qmsg_t *qmsg)
{
if (QUEUE_DEBUG)
printf("queue_freemsg\n");
if (qmsg->state != 1) {
return EOF; /* Not in queue */
}
queue_seqdel(queue, qmsg);
queue_seqdel(queue, qmsg);
if (qmsg->next == -1) /* Are we the last in queue? */
queue->last = qmsg->prev;
else
queue->qmsga[qmsg->next].prev = qmsg->prev;
if (qmsg->prev == -1) /* Are we the first in queue? */
queue->first = qmsg->next;
else
queue->qmsga[qmsg->prev].next = qmsg->next;
if (qmsg->next == -1) /* Are we the last in queue? */
queue->last = qmsg->prev;
else
queue->qmsga[qmsg->next].prev = qmsg->prev;
memset(qmsg, 0, sizeof(struct qmsg_t)); /* Just to be safe */
if (qmsg->prev == -1) /* Are we the first in queue? */
queue->first = qmsg->next;
else
queue->qmsga[qmsg->prev].next = qmsg->next;
if (QUEUE_DEBUG) queue_print(queue);
memset(qmsg, 0, sizeof(struct qmsg_t)); /* Just to be safe */
return 0;
if (QUEUE_DEBUG)
queue_print(queue);
return 0;
}
int queue_back(struct queue_t *queue, struct qmsg_t *qmsg) {
if (QUEUE_DEBUG) printf("queue_back\n");
if (qmsg->state != 1) {
return EOF; /* Not in queue */
}
int queue_back(struct queue_t *queue, struct qmsg_t *qmsg)
{
if (QUEUE_DEBUG)
printf("queue_back\n");
if (qmsg->state != 1) {
return EOF; /* Not in queue */
}
/* Insert stuff to maintain hash table */
/* Insert stuff to maintain hash table */
if (qmsg->next != -1) {/* Only swop if there are others */
queue->qmsga[qmsg->next].prev = qmsg->prev;
queue->first = qmsg->next;
qmsg->next = -1;
qmsg->prev = queue->last;
if (queue->last != -1) queue->qmsga[queue->last].next = qmsg->this;
queue->last = qmsg->this;
}
if (QUEUE_DEBUG) queue_print(queue);
return 0;
if (qmsg->next != -1) { /* Only swop if there are others */
queue->qmsga[qmsg->next].prev = qmsg->prev;
queue->first = qmsg->next;
qmsg->next = -1;
qmsg->prev = queue->last;
if (queue->last != -1)
queue->qmsga[queue->last].next = qmsg->this;
queue->last = qmsg->this;
}
if (QUEUE_DEBUG)
queue_print(queue);
return 0;
}
/* Get the element with a particular sequence number */
int queue_getfirst(struct queue_t *queue, struct qmsg_t **qmsg) {
/*printf("queue_getfirst\n");*/
if (queue->first == -1) {
*qmsg = NULL;
return EOF; /* End of queue = queue is empty. */
}
*qmsg = &queue->qmsga[queue->first];
if (QUEUE_DEBUG) queue_print(queue);
return 0;
int queue_getfirst(struct queue_t *queue, struct qmsg_t **qmsg)
{
/*printf("queue_getfirst\n"); */
if (queue->first == -1) {
*qmsg = NULL;
return EOF; /* End of queue = queue is empty. */
}
*qmsg = &queue->qmsga[queue->first];
if (QUEUE_DEBUG)
queue_print(queue);
return 0;
}
int queue_getseqx(struct queue_t *queue, struct qmsg_t **qmsg,
struct sockaddr_in *peer, uint16_t seq) {
int n;
if (QUEUE_DEBUG) printf("queue_getseq, %d\n", (int) seq);
if (QUEUE_DEBUG) queue_print(queue);
for (n=0; n<QUEUE_SIZE; n++) {
if ((queue->qmsga[n].seq == seq) &&
(!memcmp(&queue->qmsga[n].peer, peer, sizeof(*peer)))) {
*qmsg = &queue->qmsga[n];
return 0;
}
}
return EOF; /* Not found */
struct sockaddr_in *peer, uint16_t seq)
{
int n;
if (QUEUE_DEBUG)
printf("queue_getseq, %d\n", (int)seq);
if (QUEUE_DEBUG)
queue_print(queue);
for (n = 0; n < QUEUE_SIZE; n++) {
if ((queue->qmsga[n].seq == seq) &&
(!memcmp(&queue->qmsga[n].peer, peer, sizeof(*peer)))) {
*qmsg = &queue->qmsga[n];
return 0;
}
}
return EOF; /* Not found */
}
int queue_seqget(struct queue_t *queue, struct qmsg_t **qmsg,
struct sockaddr_in *peer, uint16_t seq) {
int hash = queue_seqhash(peer, seq);
struct qmsg_t *qmsg2;
if (QUEUE_DEBUG) printf("Begin queue_seqget seq = %d\n", (int) seq);
for (qmsg2 = queue->hashseq[hash]; qmsg2; qmsg2 = qmsg2->seqnext) {
if ((qmsg2->seq == seq) &&
(!memcmp(&qmsg2->peer, peer, sizeof(*peer)))) {
*qmsg = qmsg2;
if (QUEUE_DEBUG) printf("End queue_seqget. Found\n");
return 0;
}
}
if (QUEUE_DEBUG) printf("End queue_seqget. Not found\n");
return EOF; /* End of linked list and not found */
struct sockaddr_in *peer, uint16_t seq)
{
int hash = queue_seqhash(peer, seq);
struct qmsg_t *qmsg2;
if (QUEUE_DEBUG)
printf("Begin queue_seqget seq = %d\n", (int)seq);
for (qmsg2 = queue->hashseq[hash]; qmsg2; qmsg2 = qmsg2->seqnext) {
if ((qmsg2->seq == seq) &&
(!memcmp(&qmsg2->peer, peer, sizeof(*peer)))) {
*qmsg = qmsg2;
if (QUEUE_DEBUG)
printf("End queue_seqget. Found\n");
return 0;
}
}
if (QUEUE_DEBUG)
printf("End queue_seqget. Not found\n");
return EOF; /* End of linked list and not found */
}
int queue_freemsg_seq(struct queue_t *queue, struct sockaddr_in *peer,
uint16_t seq, uint8_t *type, void **cbp) {
struct qmsg_t *qmsg;
if (queue_seqget(queue, &qmsg, peer, seq)) {
*cbp = NULL;
*type = 0;
return EOF;
}
*cbp = qmsg->cbp;
*type = qmsg->type;
if (queue_freemsg(queue, qmsg)) {
return EOF;
}
return 0;
int queue_freemsg_seq(struct queue_t *queue, struct sockaddr_in *peer,
uint16_t seq, uint8_t * type, void **cbp)
{
struct qmsg_t *qmsg;
if (queue_seqget(queue, &qmsg, peer, seq)) {
*cbp = NULL;
*type = 0;
return EOF;
}
*cbp = qmsg->cbp;
*type = qmsg->type;
if (queue_freemsg(queue, qmsg)) {
return EOF;
}
return 0;
}

View File

@ -17,37 +17,36 @@
#ifndef _QUEUE_H
#define _QUEUE_H
#define QUEUE_DEBUG 0 /* Print debug information */
#define QUEUE_DEBUG 0 /* Print debug information */
#define QUEUE_SIZE 1024 /* Size of retransmission queue */
#define QUEUE_HASH_SIZE 65536 /* Size of hash table (2^16) */
#define QUEUE_SIZE 1024 /* Size of retransmission queue */
#define QUEUE_HASH_SIZE 65536 /* Size of hash table (2^16) */
struct qmsg_t { /* Holder for queued packets */
int state; /* 0=empty, 1=full */
uint16_t seq; /* The sequence number */
uint8_t type; /* The type of packet */
void *cbp; /* Application specific pointer */
union gtp_packet p; /* The packet stored */
int l; /* Length of the packet */
int fd; /* Socket packet was sent to / received from */
struct sockaddr_in peer;/* Address packet was sent to / received from */
struct qmsg_t *seqnext; /* Pointer to next in sequence hash list */
int next; /* Pointer to the next in queue. -1: Last */
int prev; /* Pointer to the previous in queue. -1: First */
int this; /* Pointer to myself */
time_t timeout; /* When do we retransmit this packet? */
int retrans; /* How many times did we retransmit this? */
struct qmsg_t { /* Holder for queued packets */
int state; /* 0=empty, 1=full */
uint16_t seq; /* The sequence number */
uint8_t type; /* The type of packet */
void *cbp; /* Application specific pointer */
union gtp_packet p; /* The packet stored */
int l; /* Length of the packet */
int fd; /* Socket packet was sent to / received from */
struct sockaddr_in peer; /* Address packet was sent to / received from */
struct qmsg_t *seqnext; /* Pointer to next in sequence hash list */
int next; /* Pointer to the next in queue. -1: Last */
int prev; /* Pointer to the previous in queue. -1: First */
int this; /* Pointer to myself */
time_t timeout; /* When do we retransmit this packet? */
int retrans; /* How many times did we retransmit this? */
};
struct queue_t {
struct qmsg_t qmsga[QUEUE_SIZE]; /* Array holding signalling messages */
void *hashseq[QUEUE_HASH_SIZE]; /* Hash array */
int next; /* Next location in queue to use */
int first; /* First packet in queue (oldest timeout) */
int last; /* Last packet in queue (youngest timeout) */
struct qmsg_t qmsga[QUEUE_SIZE]; /* Array holding signalling messages */
void *hashseq[QUEUE_HASH_SIZE]; /* Hash array */
int next; /* Next location in queue to use */
int first; /* First packet in queue (oldest timeout) */
int last; /* Last packet in queue (youngest timeout) */
};
/* Allocates and initialises new queue structure */
int queue_new(struct queue_t **queue);
/* Deallocates queue structure */
@ -63,11 +62,9 @@ int queue_back(struct queue_t *queue, struct qmsg_t *qmsg);
int queue_getfirst(struct queue_t *queue, struct qmsg_t **qmsg);
/* Get the element with a particular sequence number */
int queue_seqget(struct queue_t *queue, struct qmsg_t **qmsg,
struct sockaddr_in *peer, uint16_t seq);
struct sockaddr_in *peer, uint16_t seq);
/* Free message based on sequence number */
int queue_freemsg_seq(struct queue_t *queue, struct sockaddr_in *peer,
uint16_t seq, uint8_t *type, void **cbp);
#endif /* !_QUEUE_H */
uint16_t seq, uint8_t * type, void **cbp);
#endif /* !_QUEUE_H */

File diff suppressed because it is too large Load Diff

View File

@ -52,7 +52,6 @@
#ifndef ELIDE_CODE
/* This needs to come after some library #include
to get __GNU_LIBRARY__ defined. */
#ifdef __GNU_LIBRARY__
@ -63,15 +62,15 @@
#define NULL 0
#endif
int
getopt_long (argc, argv, options, long_options, opt_index)
int argc;
char *const *argv;
const char *options;
const struct option *long_options;
int *opt_index;
int getopt_long(argc, argv, options, long_options, opt_index)
int argc;
char *const *argv;
const char *options;
const struct option *long_options;
int *opt_index;
{
return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
return _getopt_internal(argc, argv, options, long_options, opt_index,
0);
}
/* Like getopt_long, but '-' as well as '--' can indicate a long option.
@ -79,110 +78,106 @@ getopt_long (argc, argv, options, long_options, opt_index)
but does match a short option, it is parsed as a short option
instead. */
int
getopt_long_only (argc, argv, options, long_options, opt_index)
int argc;
char *const *argv;
const char *options;
const struct option *long_options;
int *opt_index;
int getopt_long_only(argc, argv, options, long_options, opt_index)
int argc;
char *const *argv;
const char *options;
const struct option *long_options;
int *opt_index;
{
return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
return _getopt_internal(argc, argv, options, long_options, opt_index,
1);
}
#endif /* Not ELIDE_CODE. */
#endif /* Not ELIDE_CODE. */
#ifdef TEST
#include <stdio.h>
int
main (argc, argv)
int argc;
char **argv;
int main(argc, argv)
int argc;
char **argv;
{
int c;
int digit_optind = 0;
int c;
int digit_optind = 0;
while (1)
{
int this_option_optind = optind ? optind : 1;
int option_index = 0;
static struct option long_options[] =
{
{"add", 1, 0, 0},
{"append", 0, 0, 0},
{"delete", 1, 0, 0},
{"verbose", 0, 0, 0},
{"create", 0, 0, 0},
{"file", 1, 0, 0},
{0, 0, 0, 0}
};
while (1) {
int this_option_optind = optind ? optind : 1;
int option_index = 0;
static struct option long_options[] = {
{"add", 1, 0, 0},
{"append", 0, 0, 0},
{"delete", 1, 0, 0},
{"verbose", 0, 0, 0},
{"create", 0, 0, 0},
{"file", 1, 0, 0},
{0, 0, 0, 0}
};
c = getopt_long (argc, argv, "abc:d:0123456789",
long_options, &option_index);
if (c == -1)
break;
c = getopt_long(argc, argv, "abc:d:0123456789",
long_options, &option_index);
if (c == -1)
break;
switch (c)
{
case 0:
printf ("option %s", long_options[option_index].name);
if (optarg)
printf (" with arg %s", optarg);
printf ("\n");
break;
switch (c) {
case 0:
printf("option %s", long_options[option_index].name);
if (optarg)
printf(" with arg %s", optarg);
printf("\n");
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (digit_optind != 0 && digit_optind != this_option_optind)
printf ("digits occur in two different argv-elements.\n");
digit_optind = this_option_optind;
printf ("option %c\n", c);
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (digit_optind != 0
&& digit_optind != this_option_optind)
printf
("digits occur in two different argv-elements.\n");
digit_optind = this_option_optind;
printf("option %c\n", c);
break;
case 'a':
printf ("option a\n");
break;
case 'a':
printf("option a\n");
break;
case 'b':
printf ("option b\n");
break;
case 'b':
printf("option b\n");
break;
case 'c':
printf ("option c with value `%s'\n", optarg);
break;
case 'c':
printf("option c with value `%s'\n", optarg);
break;
case 'd':
printf ("option d with value `%s'\n", optarg);
break;
case 'd':
printf("option d with value `%s'\n", optarg);
break;
case '?':
break;
case '?':
break;
default:
printf ("?? getopt returned character code 0%o ??\n", c);
default:
printf("?? getopt returned character code 0%o ??\n", c);
}
}
}
if (optind < argc)
{
printf ("non-option ARGV-elements: ");
while (optind < argc)
printf ("%s ", argv[optind++]);
printf ("\n");
}
if (optind < argc) {
printf("non-option ARGV-elements: ");
while (optind < argc)
printf("%s ", argv[optind++]);
printf("\n");
}
exit (0);
exit(0);
}
#endif /* TEST */

View File

@ -20,7 +20,7 @@
#ifndef _GETOPT_H
#ifndef __need_getopt
# define _GETOPT_H 1
#define _GETOPT_H 1
#endif
/* If __GNU_LIBRARY__ is not already defined, either we are being used
@ -31,7 +31,7 @@
if it's from glibc. (Why ctype.h? It's guaranteed to exist and it
doesn't flood the namespace with stuff the way some other headers do.) */
#if !defined __GNU_LIBRARY__
# include <ctype.h>
#include <ctype.h>
#endif
#ifdef __cplusplus
@ -44,7 +44,7 @@ extern "C" {
Also, when `ordering' is RETURN_IN_ORDER,
each non-option ARGV-element is returned here. */
extern char *optarg;
extern char *optarg;
/* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller
@ -58,16 +58,16 @@ extern char *optarg;
Otherwise, `optind' communicates from one call to the next
how much of ARGV has been scanned so far. */
extern int optind;
extern int optind;
/* Callers store zero here to inhibit the error message `getopt' prints
for unrecognized options. */
extern int opterr;
extern int opterr;
/* Set to an option character which was unrecognized. */
extern int optopt;
extern int optopt;
#ifndef __need_getopt
/* Describe the long-named options requested by the application.
@ -91,27 +91,25 @@ extern int optopt;
one). For long options that have a zero `flag' field, `getopt'
returns the contents of the `val' field. */
struct option
{
# if (defined __STDC__ && __STDC__) || defined __cplusplus
const char *name;
# else
char *name;
# endif
/* has_arg can't be an enum because some compilers complain about
type mismatches in all the code that assumes it is an int. */
int has_arg;
int *flag;
int val;
};
struct option {
#if (defined __STDC__ && __STDC__) || defined __cplusplus
const char *name;
#else
char *name;
#endif
/* has_arg can't be an enum because some compilers complain about
type mismatches in all the code that assumes it is an int. */
int has_arg;
int *flag;
int val;
};
/* Names for the values of the `has_arg' field of `struct option'. */
# define no_argument 0
# define required_argument 1
# define optional_argument 2
#endif /* need getopt */
#define no_argument 0
#define required_argument 1
#define optional_argument 2
#endif /* need getopt */
/* Get definitions and prototypes for functions to process the
arguments in ARGV (ARGC of them, minus the program name) for
@ -138,43 +136,44 @@ struct option
`getopt'. */
#if (defined __STDC__ && __STDC__) || defined __cplusplus
# ifdef __GNU_LIBRARY__
#ifdef __GNU_LIBRARY__
/* Many other libraries have conflicting prototypes for getopt, with
differences in the consts, in stdlib.h. To avoid compilation
errors, only prototype getopt for the GNU C library. */
extern int getopt (int __argc, char *const *__argv, const char *__shortopts);
# else /* not __GNU_LIBRARY__ */
extern int getopt ();
# endif /* __GNU_LIBRARY__ */
extern int getopt(int __argc, char *const *__argv,
const char *__shortopts);
#else /* not __GNU_LIBRARY__ */
extern int getopt();
#endif /* __GNU_LIBRARY__ */
# ifndef __need_getopt
extern int getopt_long (int __argc, char *const *__argv, const char *__shortopts,
const struct option *__longopts, int *__longind);
extern int getopt_long_only (int __argc, char *const *__argv,
const char *__shortopts,
const struct option *__longopts, int *__longind);
#ifndef __need_getopt
extern int getopt_long(int __argc, char *const *__argv,
const char *__shortopts,
const struct option *__longopts, int *__longind);
extern int getopt_long_only(int __argc, char *const *__argv,
const char *__shortopts,
const struct option *__longopts,
int *__longind);
/* Internal only. Users should not call this directly. */
extern int _getopt_internal (int __argc, char *const *__argv,
const char *__shortopts,
const struct option *__longopts, int *__longind,
int __long_only);
# endif
#else /* not __STDC__ */
extern int getopt ();
# ifndef __need_getopt
extern int getopt_long ();
extern int getopt_long_only ();
extern int _getopt_internal(int __argc, char *const *__argv,
const char *__shortopts,
const struct option *__longopts,
int *__longind, int __long_only);
#endif
#else /* not __STDC__ */
extern int getopt();
#ifndef __need_getopt
extern int getopt_long();
extern int getopt_long_only();
extern int _getopt_internal ();
# endif
#endif /* __STDC__ */
extern int _getopt_internal();
#endif
#endif /* __STDC__ */
#ifdef __cplusplus
}
#endif
/* Make sure we later can get all the definitions and declarations. */
#undef __need_getopt
#endif /* getopt.h */
#endif /* getopt.h */

View File

@ -10,9 +10,9 @@
*/
#include <sys/types.h>
#include <netinet/in.h> /* in_addr */
#include <stdlib.h> /* calloc */
#include <stdio.h> /* sscanf */
#include <netinet/in.h> /* in_addr */
#include <stdlib.h> /* calloc */
#include <stdio.h> /* sscanf */
#include <syslog.h>
#include <string.h>
#include <sys/socket.h>
@ -21,312 +21,320 @@
#include "ippool.h"
#include "lookup.h"
int ippool_printaddr(struct ippool_t *this)
{
unsigned int n;
printf("ippool_printaddr\n");
printf("Firstdyn %d\n", this->firstdyn - this->member);
printf("Lastdyn %d\n", this->lastdyn - this->member);
printf("Firststat %d\n", this->firststat - this->member);
printf("Laststat %d\n", this->laststat - this->member);
printf("Listsize %d\n", this->listsize);
int ippool_printaddr(struct ippool_t *this) {
unsigned int n;
printf("ippool_printaddr\n");
printf("Firstdyn %d\n", this->firstdyn - this->member);
printf("Lastdyn %d\n", this->lastdyn - this->member);
printf("Firststat %d\n", this->firststat - this->member);
printf("Laststat %d\n", this->laststat - this->member);
printf("Listsize %d\n", this->listsize);
for (n=0; n<this->listsize; n++) {
printf("Unit %d inuse %d prev %d next %d addr %s %x\n",
n,
this->member[n].inuse,
this->member[n].prev - this->member,
this->member[n].next - this->member,
inet_ntoa(this->member[n].addr),
this->member[n].addr.s_addr
);
}
return 0;
for (n = 0; n < this->listsize; n++) {
printf("Unit %d inuse %d prev %d next %d addr %s %x\n",
n,
this->member[n].inuse,
this->member[n].prev - this->member,
this->member[n].next - this->member,
inet_ntoa(this->member[n].addr),
this->member[n].addr.s_addr);
}
return 0;
}
int ippool_hashadd(struct ippool_t *this, struct ippoolm_t *member) {
uint32_t hash;
struct ippoolm_t *p;
struct ippoolm_t *p_prev = NULL;
int ippool_hashadd(struct ippool_t *this, struct ippoolm_t *member)
{
uint32_t hash;
struct ippoolm_t *p;
struct ippoolm_t *p_prev = NULL;
/* Insert into hash table */
hash = ippool_hash4(&member->addr) & this->hashmask;
for (p = this->hash[hash]; p; p = p->nexthash)
p_prev = p;
if (!p_prev)
this->hash[hash] = member;
else
p_prev->nexthash = member;
return 0; /* Always OK to insert */
/* Insert into hash table */
hash = ippool_hash4(&member->addr) & this->hashmask;
for (p = this->hash[hash]; p; p = p->nexthash)
p_prev = p;
if (!p_prev)
this->hash[hash] = member;
else
p_prev->nexthash = member;
return 0; /* Always OK to insert */
}
int ippool_hashdel(struct ippool_t *this, struct ippoolm_t *member) {
uint32_t hash;
struct ippoolm_t *p;
struct ippoolm_t *p_prev = NULL;
int ippool_hashdel(struct ippool_t *this, struct ippoolm_t *member)
{
uint32_t hash;
struct ippoolm_t *p;
struct ippoolm_t *p_prev = NULL;
/* Find in hash table */
hash = ippool_hash4(&member->addr) & this->hashmask;
for (p = this->hash[hash]; p; p = p->nexthash) {
if (p == member) {
break;
}
p_prev = p;
}
/* Find in hash table */
hash = ippool_hash4(&member->addr) & this->hashmask;
for (p = this->hash[hash]; p; p = p->nexthash) {
if (p == member) {
break;
}
p_prev = p;
}
if (p!= member) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"ippool_hashdel: Tried to delete member not in hash table");
return -1;
}
if (p != member) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"ippool_hashdel: Tried to delete member not in hash table");
return -1;
}
if (!p_prev)
this->hash[hash] = p->nexthash;
else
p_prev->nexthash = p->nexthash;
if (!p_prev)
this->hash[hash] = p->nexthash;
else
p_prev->nexthash = p->nexthash;
return 0;
return 0;
}
unsigned long int ippool_hash4(struct in_addr *addr) {
return lookup((unsigned char*) &addr->s_addr, sizeof(addr->s_addr), 0);
unsigned long int ippool_hash4(struct in_addr *addr)
{
return lookup((unsigned char *)&addr->s_addr, sizeof(addr->s_addr), 0);
}
#ifndef IPPOOL_NOIP6
unsigned long int ippool_hash6(struct in6_addr *addr) {
return lookup((unsigned char*) addr->u6_addr8, sizeof(addr->u6_addr8), 0);
unsigned long int ippool_hash6(struct in6_addr *addr)
{
return lookup((unsigned char *)addr->u6_addr8, sizeof(addr->u6_addr8),
0);
}
#endif
/* Get IP address and mask */
int ippool_aton(struct in_addr *addr, struct in_addr *mask,
char *pool, int number) {
char *pool, int number)
{
/* Parse only first instance of network for now */
/* Eventually "number" will indicate the token which we want to parse */
/* Parse only first instance of network for now */
/* Eventually "number" will indicate the token which we want to parse */
unsigned int a1, a2, a3, a4;
unsigned int m1, m2, m3, m4;
int c;
int m;
int masklog;
unsigned int a1, a2, a3, a4;
unsigned int m1, m2, m3, m4;
int c;
int m;
int masklog;
c = sscanf(pool, "%u.%u.%u.%u/%u.%u.%u.%u",
&a1, &a2, &a3, &a4,
&m1, &m2, &m3, &m4);
switch (c) {
case 4:
mask->s_addr = 0xffffffff;
break;
case 5:
if (m1 > 32) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Invalid mask");
return -1; /* Invalid mask */
}
mask->s_addr = htonl(0xffffffff << (32 - m1));
break;
case 8:
if (m1 >= 256 || m2 >= 256 || m3 >= 256 || m4 >= 256) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Invalid mask");
return -1; /* Wrong mask format */
}
m = m1 * 0x1000000 + m2 * 0x10000 + m3 * 0x100 + m4;
for (masklog = 0; ((1 << masklog) < ((~m)+1)); masklog++);
if (((~m)+1) != (1 << masklog)) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Invalid mask");
return -1; /* Wrong mask format (not all ones followed by all zeros)*/
}
mask->s_addr = htonl(m);
break;
default:
sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Invalid mask");
return -1; /* Invalid mask */
}
c = sscanf(pool, "%u.%u.%u.%u/%u.%u.%u.%u",
&a1, &a2, &a3, &a4, &m1, &m2, &m3, &m4);
switch (c) {
case 4:
mask->s_addr = 0xffffffff;
break;
case 5:
if (m1 > 32) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Invalid mask");
return -1; /* Invalid mask */
}
mask->s_addr = htonl(0xffffffff << (32 - m1));
break;
case 8:
if (m1 >= 256 || m2 >= 256 || m3 >= 256 || m4 >= 256) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Invalid mask");
return -1; /* Wrong mask format */
}
m = m1 * 0x1000000 + m2 * 0x10000 + m3 * 0x100 + m4;
for (masklog = 0; ((1 << masklog) < ((~m) + 1)); masklog++) ;
if (((~m) + 1) != (1 << masklog)) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Invalid mask");
return -1; /* Wrong mask format (not all ones followed by all zeros) */
}
mask->s_addr = htonl(m);
break;
default:
sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Invalid mask");
return -1; /* Invalid mask */
}
if (a1 >= 256 || a2 >= 256 || a3 >= 256 || a4 >= 256) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Wrong IP address format");
return -1;
}
else
addr->s_addr = htonl(a1 * 0x1000000 + a2 * 0x10000 + a3 * 0x100 + a4);
if (a1 >= 256 || a2 >= 256 || a3 >= 256 || a4 >= 256) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"Wrong IP address format");
return -1;
} else
addr->s_addr =
htonl(a1 * 0x1000000 + a2 * 0x10000 + a3 * 0x100 + a4);
return 0;
return 0;
}
/* Create new address pool */
int ippool_new(struct ippool_t **this, char *dyn, char *stat,
int allowdyn, int allowstat, int flags) {
int ippool_new(struct ippool_t **this, char *dyn, char *stat,
int allowdyn, int allowstat, int flags)
{
/* Parse only first instance of pool for now */
/* Parse only first instance of pool for now */
int i;
struct in_addr addr;
struct in_addr mask;
struct in_addr stataddr;
struct in_addr statmask;
unsigned int m;
int listsize;
int dynsize;
unsigned int statsize;
int i;
struct in_addr addr;
struct in_addr mask;
struct in_addr stataddr;
struct in_addr statmask;
unsigned int m;
int listsize;
int dynsize;
unsigned int statsize;
if (!allowdyn) {
dynsize = 0;
}
else {
if (ippool_aton(&addr, &mask, dyn, 0)) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"Failed to parse dynamic pool");
return -1;
}
if (!allowdyn) {
dynsize = 0;
} else {
if (ippool_aton(&addr, &mask, dyn, 0)) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"Failed to parse dynamic pool");
return -1;
}
/* Set IPPOOL_NONETWORK if IPPOOL_NOGATEWAY is set */
if (flags & IPPOOL_NOGATEWAY) {
flags |= IPPOOL_NONETWORK;
}
m = ntohl(mask.s_addr);
dynsize = ((~m)+1);
if (flags & IPPOOL_NONETWORK) /* Exclude network address from pool */
dynsize--;
if (flags & IPPOOL_NOGATEWAY) /* Exclude gateway address from pool */
dynsize--;
if (flags & IPPOOL_NOBROADCAST) /* Exclude broadcast address from pool */
dynsize--;
}
/* Set IPPOOL_NONETWORK if IPPOOL_NOGATEWAY is set */
if (flags & IPPOOL_NOGATEWAY) {
flags |= IPPOOL_NONETWORK;
}
if (!allowstat) {
statsize = 0;
stataddr.s_addr = 0;
statmask.s_addr = 0;
}
else {
if (ippool_aton(&stataddr, &statmask, stat, 0)) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"Failed to parse static range");
return -1;
}
m = ntohl(mask.s_addr);
dynsize = ((~m) + 1);
if (flags & IPPOOL_NONETWORK) /* Exclude network address from pool */
dynsize--;
if (flags & IPPOOL_NOGATEWAY) /* Exclude gateway address from pool */
dynsize--;
if (flags & IPPOOL_NOBROADCAST) /* Exclude broadcast address from pool */
dynsize--;
}
m = ntohl(statmask.s_addr);
statsize = ((~m)+1);
if (statsize > IPPOOL_STATSIZE) statsize = IPPOOL_STATSIZE;
}
if (!allowstat) {
statsize = 0;
stataddr.s_addr = 0;
statmask.s_addr = 0;
} else {
if (ippool_aton(&stataddr, &statmask, stat, 0)) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"Failed to parse static range");
return -1;
}
listsize = dynsize + statsize; /* Allocate space for static IP addresses */
m = ntohl(statmask.s_addr);
statsize = ((~m) + 1);
if (statsize > IPPOOL_STATSIZE)
statsize = IPPOOL_STATSIZE;
}
if (!(*this = calloc(sizeof(struct ippool_t), 1))) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"Failed to allocate memory for ippool");
return -1;
}
(*this)->allowdyn = allowdyn;
(*this)->allowstat = allowstat;
(*this)->stataddr = stataddr;
(*this)->statmask = statmask;
listsize = dynsize + statsize; /* Allocate space for static IP addresses */
(*this)->listsize += listsize;
if (!((*this)->member = calloc(sizeof(struct ippoolm_t), listsize))){
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"Failed to allocate memory for members in ippool");
return -1;
}
for ((*this)->hashlog = 0;
((1 << (*this)->hashlog) < listsize);
(*this)->hashlog++);
if (!(*this = calloc(sizeof(struct ippool_t), 1))) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"Failed to allocate memory for ippool");
return -1;
}
/* printf ("Hashlog %d %d %d\n", (*this)->hashlog, listsize, (1 << (*this)->hashlog)); */
(*this)->allowdyn = allowdyn;
(*this)->allowstat = allowstat;
(*this)->stataddr = stataddr;
(*this)->statmask = statmask;
/* Determine hashsize */
(*this)->hashsize = 1 << (*this)->hashlog; /* Fails if mask=0: All Internet*/
(*this)->hashmask = (*this)->hashsize -1;
/* Allocate hash table */
if (!((*this)->hash = calloc(sizeof(struct ippoolm_t), (*this)->hashsize))){
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"Failed to allocate memory for hash members in ippool");
return -1;
}
(*this)->firstdyn = NULL;
(*this)->lastdyn = NULL;
for (i = 0; i<dynsize; i++) {
(*this)->listsize += listsize;
if (!((*this)->member = calloc(sizeof(struct ippoolm_t), listsize))) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"Failed to allocate memory for members in ippool");
return -1;
}
if (flags & IPPOOL_NOGATEWAY)
(*this)->member[i].addr.s_addr = htonl(ntohl(addr.s_addr) + i + 2);
else if (flags & IPPOOL_NONETWORK)
(*this)->member[i].addr.s_addr = htonl(ntohl(addr.s_addr) + i + 1);
else
(*this)->member[i].addr.s_addr = htonl(ntohl(addr.s_addr) + i);
(*this)->member[i].inuse = 0;
for ((*this)->hashlog = 0;
((1 << (*this)->hashlog) < listsize); (*this)->hashlog++) ;
/* Insert into list of unused */
(*this)->member[i].prev = (*this)->lastdyn;
if ((*this)->lastdyn) {
(*this)->lastdyn->next = &((*this)->member[i]);
}
else {
(*this)->firstdyn = &((*this)->member[i]);
}
(*this)->lastdyn = &((*this)->member[i]);
(*this)->member[i].next = NULL; /* Redundant */
/* printf ("Hashlog %d %d %d\n", (*this)->hashlog, listsize, (1 << (*this)->hashlog)); */
( void)ippool_hashadd(*this, &(*this)->member[i]);
}
/* Determine hashsize */
(*this)->hashsize = 1 << (*this)->hashlog; /* Fails if mask=0: All Internet */
(*this)->hashmask = (*this)->hashsize - 1;
(*this)->firststat = NULL;
(*this)->laststat = NULL;
for (i = dynsize; i<listsize; i++) {
/* Allocate hash table */
if (!
((*this)->hash =
calloc(sizeof(struct ippoolm_t), (*this)->hashsize))) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"Failed to allocate memory for hash members in ippool");
return -1;
}
(*this)->member[i].addr.s_addr = 0;
(*this)->member[i].inuse = 0;
(*this)->firstdyn = NULL;
(*this)->lastdyn = NULL;
for (i = 0; i < dynsize; i++) {
/* Insert into list of unused */
(*this)->member[i].prev = (*this)->laststat;
if ((*this)->laststat) {
(*this)->laststat->next = &((*this)->member[i]);
}
else {
(*this)->firststat = &((*this)->member[i]);
}
(*this)->laststat = &((*this)->member[i]);
(*this)->member[i].next = NULL; /* Redundant */
}
if (flags & IPPOOL_NOGATEWAY)
(*this)->member[i].addr.s_addr =
htonl(ntohl(addr.s_addr) + i + 2);
else if (flags & IPPOOL_NONETWORK)
(*this)->member[i].addr.s_addr =
htonl(ntohl(addr.s_addr) + i + 1);
else
(*this)->member[i].addr.s_addr =
htonl(ntohl(addr.s_addr) + i);
if (0) (void)ippool_printaddr(*this);
return 0;
(*this)->member[i].inuse = 0;
/* Insert into list of unused */
(*this)->member[i].prev = (*this)->lastdyn;
if ((*this)->lastdyn) {
(*this)->lastdyn->next = &((*this)->member[i]);
} else {
(*this)->firstdyn = &((*this)->member[i]);
}
(*this)->lastdyn = &((*this)->member[i]);
(*this)->member[i].next = NULL; /* Redundant */
(void)ippool_hashadd(*this, &(*this)->member[i]);
}
(*this)->firststat = NULL;
(*this)->laststat = NULL;
for (i = dynsize; i < listsize; i++) {
(*this)->member[i].addr.s_addr = 0;
(*this)->member[i].inuse = 0;
/* Insert into list of unused */
(*this)->member[i].prev = (*this)->laststat;
if ((*this)->laststat) {
(*this)->laststat->next = &((*this)->member[i]);
} else {
(*this)->firststat = &((*this)->member[i]);
}
(*this)->laststat = &((*this)->member[i]);
(*this)->member[i].next = NULL; /* Redundant */
}
if (0)
(void)ippool_printaddr(*this);
return 0;
}
/* Delete existing address pool */
int ippool_free(struct ippool_t *this) {
free(this->hash);
free(this->member);
free(this);
return 0; /* Always OK */
int ippool_free(struct ippool_t *this)
{
free(this->hash);
free(this->member);
free(this);
return 0; /* Always OK */
}
/* Find an IP address in the pool */
int ippool_getip(struct ippool_t *this, struct ippoolm_t **member,
struct in_addr *addr) {
struct ippoolm_t *p;
uint32_t hash;
struct in_addr *addr)
{
struct ippoolm_t *p;
uint32_t hash;
/* Find in hash table */
hash = ippool_hash4(addr) & this->hashmask;
for (p = this->hash[hash]; p; p = p->nexthash) {
if ((p->addr.s_addr == addr->s_addr) && (p->inuse)) {
if (member) *member = p;
return 0;
}
}
if (member) *member = NULL;
/*sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Address could not be found");*/
return -1;
/* Find in hash table */
hash = ippool_hash4(addr) & this->hashmask;
for (p = this->hash[hash]; p; p = p->nexthash) {
if ((p->addr.s_addr == addr->s_addr) && (p->inuse)) {
if (member)
*member = p;
return 0;
}
}
if (member)
*member = NULL;
/*sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Address could not be found"); */
return -1;
}
/**
@ -337,188 +345,193 @@ int ippool_getip(struct ippool_t *this, struct ippoolm_t **member,
* address space.
**/
int ippool_newip(struct ippool_t *this, struct ippoolm_t **member,
struct in_addr *addr, int statip) {
struct ippoolm_t *p;
struct ippoolm_t *p2 = NULL;
uint32_t hash;
struct in_addr *addr, int statip)
{
struct ippoolm_t *p;
struct ippoolm_t *p2 = NULL;
uint32_t hash;
/* If static:
* Look in dynaddr.
* If found remove from firstdyn/lastdyn linked list.
* Else allocate from stataddr.
* Remove from firststat/laststat linked list.
* Insert into hash table.
*
* If dynamic
* Remove from firstdyn/lastdyn linked list.
*
*/
/* If static:
* Look in dynaddr.
* If found remove from firstdyn/lastdyn linked list.
* Else allocate from stataddr.
* Remove from firststat/laststat linked list.
* Insert into hash table.
*
* If dynamic
* Remove from firstdyn/lastdyn linked list.
*
*/
if (0) (void)ippool_printaddr(this);
if (0)
(void)ippool_printaddr(this);
/* First check to see if this type of address is allowed */
if ((addr) && (addr->s_addr) && statip) { /* IP address given */
if (!this->allowstat) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Static IP address not allowed");
return -1;
}
if ((addr->s_addr & this->statmask.s_addr) != this->stataddr.s_addr) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Static out of range");
return -1;
}
}
else {
if (!this->allowdyn) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"Dynamic IP address not allowed");
return -1;
}
}
/* First check to see if this type of address is allowed */
if ((addr) && (addr->s_addr) && statip) { /* IP address given */
if (!this->allowstat) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"Static IP address not allowed");
return -1;
}
if ((addr->s_addr & this->statmask.s_addr) !=
this->stataddr.s_addr) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"Static out of range");
return -1;
}
} else {
if (!this->allowdyn) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"Dynamic IP address not allowed");
return -1;
}
}
/* If IP address given try to find it in dynamic address pool */
if ((addr) && (addr->s_addr)) { /* IP address given */
/* Find in hash table */
hash = ippool_hash4(addr) & this->hashmask;
for (p = this->hash[hash]; p; p = p->nexthash) {
if ((p->addr.s_addr == addr->s_addr)) {
p2 = p;
break;
}
}
}
/* If IP address given try to find it in dynamic address pool */
if ((addr) && (addr->s_addr)) { /* IP address given */
/* Find in hash table */
hash = ippool_hash4(addr) & this->hashmask;
for (p = this->hash[hash]; p; p = p->nexthash) {
if ((p->addr.s_addr == addr->s_addr)) {
p2 = p;
break;
}
}
}
/* If IP was already allocated we can not use it */
if ((!statip) && (p2) && (p2->inuse)) {
p2 = NULL;
}
/* If IP was already allocated we can not use it */
if ((!statip) && (p2) && (p2->inuse)) {
p2 = NULL;
}
/* If not found yet and dynamic IP then allocate dynamic IP */
if ((!p2) && (!statip)) {
if (!this ->firstdyn) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"No more IP addresses available");
return -1;
}
else
p2 = this ->firstdyn;
}
if (p2) { /* Was allocated from dynamic address pool */
if (p2->inuse) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"IP address allready in use");
return -1; /* Allready in use / Should not happen */
}
/* If not found yet and dynamic IP then allocate dynamic IP */
if ((!p2) && (!statip)) {
if (!this->firstdyn) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"No more IP addresses available");
return -1;
} else
p2 = this->firstdyn;
}
/* Remove from linked list of free dynamic addresses */
if (p2->prev)
p2->prev->next = p2->next;
else
this->firstdyn = p2->next;
if (p2->next)
p2->next->prev = p2->prev;
else
this->lastdyn = p2->prev;
p2->next = NULL;
p2->prev = NULL;
p2->inuse = 1; /* Dynamic address in use */
*member = p2;
if (0) (void)ippool_printaddr(this);
return 0; /* Success */
}
if (p2) { /* Was allocated from dynamic address pool */
if (p2->inuse) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"IP address allready in use");
return -1; /* Allready in use / Should not happen */
}
/* It was not possible to allocate from dynamic address pool */
/* Try to allocate from static address space */
/* Remove from linked list of free dynamic addresses */
if (p2->prev)
p2->prev->next = p2->next;
else
this->firstdyn = p2->next;
if (p2->next)
p2->next->prev = p2->prev;
else
this->lastdyn = p2->prev;
p2->next = NULL;
p2->prev = NULL;
p2->inuse = 1; /* Dynamic address in use */
if ((addr) && (addr->s_addr) && (statip)) { /* IP address given */
if (!this->firststat) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"No more IP addresses available");
return -1; /* No more available */
}
else
p2 = this ->firststat;
*member = p2;
if (0)
(void)ippool_printaddr(this);
return 0; /* Success */
}
/* Remove from linked list of free static addresses */
if (p2->prev)
p2->prev->next = p2->next;
else
this->firststat = p2->next;
if (p2->next)
p2->next->prev = p2->prev;
else
this->laststat = p2->prev;
p2->next = NULL;
p2->prev = NULL;
p2->inuse = 2; /* Static address in use */
memcpy(&p2->addr, addr, sizeof(addr));
*member = p2;
(void)ippool_hashadd(this, *member);
if (0) (void)ippool_printaddr(this);
return 0; /* Success */
}
/* It was not possible to allocate from dynamic address pool */
/* Try to allocate from static address space */
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"Could not allocate IP address");
return -1; /* Should never get here. TODO: Bad code */
if ((addr) && (addr->s_addr) && (statip)) { /* IP address given */
if (!this->firststat) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"No more IP addresses available");
return -1; /* No more available */
} else
p2 = this->firststat;
/* Remove from linked list of free static addresses */
if (p2->prev)
p2->prev->next = p2->next;
else
this->firststat = p2->next;
if (p2->next)
p2->next->prev = p2->prev;
else
this->laststat = p2->prev;
p2->next = NULL;
p2->prev = NULL;
p2->inuse = 2; /* Static address in use */
memcpy(&p2->addr, addr, sizeof(addr));
*member = p2;
(void)ippool_hashadd(this, *member);
if (0)
(void)ippool_printaddr(this);
return 0; /* Success */
}
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"Could not allocate IP address");
return -1; /* Should never get here. TODO: Bad code */
}
int ippool_freeip(struct ippool_t *this, struct ippoolm_t *member)
{
int ippool_freeip(struct ippool_t *this, struct ippoolm_t *member) {
if (0) (void)ippool_printaddr(this);
if (0)
(void)ippool_printaddr(this);
if (!member->inuse) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Address not in use");
return -1; /* Not in use: Should not happen */
}
if (!member->inuse) {
sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Address not in use");
return -1; /* Not in use: Should not happen */
}
switch (member->inuse) {
case 0: /* Not in use: Should not happen */
sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Address not in use");
return -1;
case 1: /* Allocated from dynamic address space */
/* Insert into list of unused */
member->prev = this->lastdyn;
if (this->lastdyn) {
this->lastdyn->next = member;
}
else {
this->firstdyn = member;
}
this->lastdyn = member;
member->inuse = 0;
member->peer = NULL;
if (0) (void)ippool_printaddr(this);
return 0;
case 2: /* Allocated from static address space */
if (ippool_hashdel(this, member))
return -1;
/* Insert into list of unused */
member->prev = this->laststat;
if (this->laststat) {
this->laststat->next = member;
}
else {
this->firststat = member;
}
this->laststat = member;
member->inuse = 0;
member->addr.s_addr = 0;
member->peer = NULL;
member->nexthash = NULL;
if (0) (void)ippool_printaddr(this);
return 0;
default: /* Should not happen */
sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Could not free IP address");
return -1;
}
switch (member->inuse) {
case 0: /* Not in use: Should not happen */
sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Address not in use");
return -1;
case 1: /* Allocated from dynamic address space */
/* Insert into list of unused */
member->prev = this->lastdyn;
if (this->lastdyn) {
this->lastdyn->next = member;
} else {
this->firstdyn = member;
}
this->lastdyn = member;
member->inuse = 0;
member->peer = NULL;
if (0)
(void)ippool_printaddr(this);
return 0;
case 2: /* Allocated from static address space */
if (ippool_hashdel(this, member))
return -1;
/* Insert into list of unused */
member->prev = this->laststat;
if (this->laststat) {
this->laststat->next = member;
} else {
this->firststat = member;
}
this->laststat = member;
member->inuse = 0;
member->addr.s_addr = 0;
member->peer = NULL;
member->nexthash = NULL;
if (0)
(void)ippool_printaddr(this);
return 0;
default: /* Should not happen */
sys_err(LOG_ERR, __FILE__, __LINE__, 0,
"Could not free IP address");
return -1;
}
}
#ifndef IPPOOL_NOIP6
extern unsigned long int ippool_hash6(struct in6_addr *addr);
extern int ippool_getip6(struct ippool_t *this, struct in6_addr *addr);

View File

@ -34,35 +34,35 @@
#define IPPOOL_STATSIZE 0x10000
struct ippoolm_t; /* Forward declaration */
struct ippoolm_t; /* Forward declaration */
struct ippool_t {
unsigned int listsize; /* Total number of addresses */
int allowdyn; /* Allow dynamic IP address allocation */
int allowstat; /* Allow static IP address allocation */
struct in_addr stataddr; /* Static address range network address */
struct in_addr statmask; /* Static address range network mask */
struct ippoolm_t *member; /* Listsize array of members */
unsigned int hashsize; /* Size of hash table */
int hashlog; /* Log2 size of hash table */
int hashmask; /* Bitmask for calculating hash */
struct ippoolm_t **hash; /* Hashsize array of pointer to member */
struct ippoolm_t *firstdyn; /* Pointer to first free dynamic member */
struct ippoolm_t *lastdyn; /* Pointer to last free dynamic member */
struct ippoolm_t *firststat; /* Pointer to first free static member */
struct ippoolm_t *laststat; /* Pointer to last free static member */
unsigned int listsize; /* Total number of addresses */
int allowdyn; /* Allow dynamic IP address allocation */
int allowstat; /* Allow static IP address allocation */
struct in_addr stataddr; /* Static address range network address */
struct in_addr statmask; /* Static address range network mask */
struct ippoolm_t *member; /* Listsize array of members */
unsigned int hashsize; /* Size of hash table */
int hashlog; /* Log2 size of hash table */
int hashmask; /* Bitmask for calculating hash */
struct ippoolm_t **hash; /* Hashsize array of pointer to member */
struct ippoolm_t *firstdyn; /* Pointer to first free dynamic member */
struct ippoolm_t *lastdyn; /* Pointer to last free dynamic member */
struct ippoolm_t *firststat; /* Pointer to first free static member */
struct ippoolm_t *laststat; /* Pointer to last free static member */
};
struct ippoolm_t {
#ifndef IPPOOL_NOIP6
struct in6_addr addr; /* IP address of this member */
struct in6_addr addr; /* IP address of this member */
#else
struct in_addr addr; /* IP address of this member */
struct in_addr addr; /* IP address of this member */
#endif
int inuse; /* 0=available; 1= dynamic; 2 = static */
struct ippoolm_t *nexthash; /* Linked list part of hash table */
struct ippoolm_t *prev, *next; /* Linked list of free dynamic or static */
void *peer; /* Pointer to peer protocol handler */
int inuse; /* 0=available; 1= dynamic; 2 = static */
struct ippoolm_t *nexthash; /* Linked list part of hash table */
struct ippoolm_t *prev, *next; /* Linked list of free dynamic or static */
void *peer; /* Pointer to peer protocol handler */
};
/* The above structures require approximately 20+4 = 24 bytes for
@ -73,7 +73,7 @@ struct ippoolm_t {
extern unsigned long int ippool_hash4(struct in_addr *addr);
/* Create new address pool */
extern int ippool_new(struct ippool_t **this, char *dyn, char *stat,
extern int ippool_new(struct ippool_t **this, char *dyn, char *stat,
int allowdyn, int allowstat, int flags);
/* Delete existing address pool */
@ -81,7 +81,7 @@ extern int ippool_free(struct ippool_t *this);
/* Find an IP address in the pool */
extern int ippool_getip(struct ippool_t *this, struct ippoolm_t **member,
struct in_addr *addr);
struct in_addr *addr);
/* Get an IP address. If addr = 0.0.0.0 get a dynamic IP address. Otherwise
check to see if the given address is available */
@ -95,11 +95,10 @@ extern int ippool_freeip(struct ippool_t *this, struct ippoolm_t *member);
extern int ippool_aton(struct in_addr *addr, struct in_addr *mask,
char *pool, int number);
#ifndef IPPOOL_NOIP6
extern unsigned long int ippool_hash6(struct in6_addr *addr);
extern int ippool_getip6(struct ippool_t *this, struct in6_addr *addr);
extern int ippool_returnip6(struct ippool_t *this, struct in6_addr *addr);
#endif
#endif /* !_IPPOOL_H */
#endif /* !_IPPOOL_H */

View File

@ -17,10 +17,10 @@
* statistical properties and speed. It is NOT recommended for cryptographic
* purposes.
**/
unsigned long int lookup( k, length, level)
register unsigned char *k; /* the key */
register unsigned long int length; /* the length of the key */
register unsigned long int level; /* the previous hash, or an arbitrary value*/
unsigned long int lookup(k, length, level)
register unsigned char *k; /* the key */
register unsigned long int length; /* the length of the key */
register unsigned long int level; /* the previous hash, or an arbitrary value */
{
#define mix(a,b,c) \
@ -36,45 +36,57 @@ register unsigned long int level; /* the previous hash, or an arbitrary value*/
c -= a; c -= b; c ^= (b>>15); \
}
typedef unsigned long int ub4; /* unsigned 4-byte quantities */
typedef unsigned char ub1; /* unsigned 1-byte quantities */
register unsigned long int a,b,c,len;
/* Set up the internal state */
len = length;
a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
c = level; /* the previous hash value */
/*---------------------------------------- handle most of the key */
while (len >= 12)
{
a += (k[0] +((ub4)k[1]<<8) +((ub4)k[2]<<16) +((ub4)k[3]<<24));
b += (k[4] +((ub4)k[5]<<8) +((ub4)k[6]<<16) +((ub4)k[7]<<24));
c += (k[8] +((ub4)k[9]<<8) +((ub4)k[10]<<16)+((ub4)k[11]<<24));
mix(a,b,c);
k += 12; len -= 12;
}
/*------------------------------------- handle the last 11 bytes */
c += length;
switch(len) /* all the case statements fall through */
{
case 11: c+=((ub4)k[10]<<24);
case 10: c+=((ub4)k[9]<<16);
case 9 : c+=((ub4)k[8]<<8);
/* the first byte of c is reserved for the length */
case 8 : b+=((ub4)k[7]<<24);
case 7 : b+=((ub4)k[6]<<16);
case 6 : b+=((ub4)k[5]<<8);
case 5 : b+=k[4];
case 4 : a+=((ub4)k[3]<<24);
case 3 : a+=((ub4)k[2]<<16);
case 2 : a+=((ub4)k[1]<<8);
case 1 : a+=k[0];
/* case 0: nothing left to add */
}
mix(a,b,c);
/*-------------------------------------------- report the result */
return c;
}
typedef unsigned long int ub4; /* unsigned 4-byte quantities */
typedef unsigned char ub1; /* unsigned 1-byte quantities */
register unsigned long int a, b, c, len;
/* Set up the internal state */
len = length;
a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
c = level; /* the previous hash value */
/*---------------------------------------- handle most of the key */
while (len >= 12) {
a += (k[0] + ((ub4) k[1] << 8) + ((ub4) k[2] << 16) +
((ub4) k[3] << 24));
b += (k[4] + ((ub4) k[5] << 8) + ((ub4) k[6] << 16) +
((ub4) k[7] << 24));
c += (k[8] + ((ub4) k[9] << 8) + ((ub4) k[10] << 16) +
((ub4) k[11] << 24));
mix(a, b, c);
k += 12;
len -= 12;
}
/*------------------------------------- handle the last 11 bytes */
c += length;
switch (len) { /* all the case statements fall through */
case 11:
c += ((ub4) k[10] << 24);
case 10:
c += ((ub4) k[9] << 16);
case 9:
c += ((ub4) k[8] << 8);
/* the first byte of c is reserved for the length */
case 8:
b += ((ub4) k[7] << 24);
case 7:
b += ((ub4) k[6] << 16);
case 6:
b += ((ub4) k[5] << 8);
case 5:
b += k[4];
case 4:
a += ((ub4) k[3] << 24);
case 3:
a += ((ub4) k[2] << 16);
case 2:
a += ((ub4) k[1] << 8);
case 1:
a += k[0];
/* case 0: nothing left to add */
}
mix(a, b, c);
/*-------------------------------------------- report the result */
return c;
}

View File

@ -20,6 +20,7 @@
#ifndef _LOOKUP_H
#define _LOOKUP_H
unsigned long int lookup( unsigned char *k, unsigned long int length, unsigned long int level);
unsigned long int lookup(unsigned char *k, unsigned long int length,
unsigned long int level);
#endif /* !_LOOKUP_H */
#endif /* !_LOOKUP_H */

View File

@ -20,52 +20,55 @@
#include "syserr.h"
void sys_err(int pri, char *fn, int ln, int en, char *fmt, ...)
{
va_list args;
char buf[SYSERR_MSGSIZE];
void sys_err(int pri, char *fn, int ln, int en, char *fmt, ...) {
va_list args;
char buf[SYSERR_MSGSIZE];
va_start(args, fmt);
vsnprintf(buf, SYSERR_MSGSIZE, fmt, args);
va_end(args);
buf[SYSERR_MSGSIZE-1] = 0; /* Make sure it is null terminated */
if (en)
syslog(pri, "%s: %d: %d (%s) %s", fn, ln, en, strerror(en), buf);
else
syslog(pri, "%s: %d: %s", fn, ln, buf);
va_start(args, fmt);
vsnprintf(buf, SYSERR_MSGSIZE, fmt, args);
va_end(args);
buf[SYSERR_MSGSIZE - 1] = 0; /* Make sure it is null terminated */
if (en)
syslog(pri, "%s: %d: %d (%s) %s", fn, ln, en, strerror(en),
buf);
else
syslog(pri, "%s: %d: %s", fn, ln, buf);
}
void sys_errpack(int pri, char *fn, int ln, int en, struct sockaddr_in *peer,
void *pack, unsigned len, char *fmt, ...) {
va_list args;
char buf[SYSERR_MSGSIZE];
char buf2[SYSERR_MSGSIZE];
unsigned int n;
int pos;
va_start(args, fmt);
vsnprintf(buf, SYSERR_MSGSIZE, fmt, args);
va_end(args);
buf[SYSERR_MSGSIZE-1] = 0;
void *pack, unsigned len, char *fmt, ...)
{
snprintf(buf2, SYSERR_MSGSIZE, "Packet from %s:%u, length: %d, content:",
inet_ntoa(peer->sin_addr),
ntohs(peer->sin_port),
len);
buf2[SYSERR_MSGSIZE-1] = 0;
pos = strlen(buf2);
for(n=0; n<len; n++) {
if ((pos+4)<SYSERR_MSGSIZE) {
sprintf((buf2+pos), " %02hhx", ((unsigned char*)pack)[n]);
pos += 3;
}
}
buf2[pos] = 0;
if (en)
syslog(pri, "%s: %d: %d (%s) %s. %s", fn, ln, en, strerror(en), buf, buf2);
else
syslog(pri, "%s: %d: %s. %s", fn, ln, buf, buf2);
va_list args;
char buf[SYSERR_MSGSIZE];
char buf2[SYSERR_MSGSIZE];
unsigned int n;
int pos;
va_start(args, fmt);
vsnprintf(buf, SYSERR_MSGSIZE, fmt, args);
va_end(args);
buf[SYSERR_MSGSIZE - 1] = 0;
snprintf(buf2, SYSERR_MSGSIZE,
"Packet from %s:%u, length: %d, content:",
inet_ntoa(peer->sin_addr), ntohs(peer->sin_port), len);
buf2[SYSERR_MSGSIZE - 1] = 0;
pos = strlen(buf2);
for (n = 0; n < len; n++) {
if ((pos + 4) < SYSERR_MSGSIZE) {
sprintf((buf2 + pos), " %02hhx",
((unsigned char *)pack)[n]);
pos += 3;
}
}
buf2[pos] = 0;
if (en)
syslog(pri, "%s: %d: %d (%s) %s. %s", fn, ln, en, strerror(en),
buf, buf2);
else
syslog(pri, "%s: %d: %s. %s", fn, ln, buf, buf2);
}

View File

@ -18,4 +18,4 @@ void sys_err(int pri, char *filename, int en, int line, char *fmt, ...);
void sys_errpack(int pri, char *fn, int ln, int en, struct sockaddr_in *peer,
void *pack, unsigned len, char *fmt, ...);
#endif /* !_SYSERR_H */
#endif /* !_SYSERR_H */

1100
lib/tun.c

File diff suppressed because it is too large Load Diff

View File

@ -12,44 +12,42 @@
#ifndef _TUN_H
#define _TUN_H
#define PACKET_MAX 8196 /* Maximum packet size we receive */
#define PACKET_MAX 8196 /* Maximum packet size we receive */
#define TUN_SCRIPTSIZE 256
#define TUN_ADDRSIZE 128
#define TUN_NLBUFSIZE 1024
struct tun_packet_t {
unsigned int ver:4;
unsigned int ihl:4;
unsigned int dscp:6;
unsigned int ecn:2;
unsigned int length:16;
unsigned int id:16;
unsigned int flags:3;
unsigned int fragment:13;
unsigned int ttl:8;
unsigned int protocol:8;
unsigned int check:16;
unsigned int src:32;
unsigned int dst:32;
unsigned int ver:4;
unsigned int ihl:4;
unsigned int dscp:6;
unsigned int ecn:2;
unsigned int length:16;
unsigned int id:16;
unsigned int flags:3;
unsigned int fragment:13;
unsigned int ttl:8;
unsigned int protocol:8;
unsigned int check:16;
unsigned int src:32;
unsigned int dst:32;
};
/* ***********************************************************
* Information storage for each tun instance
*************************************************************/
struct tun_t {
int fd; /* File descriptor to tun interface */
struct in_addr addr;
struct in_addr dstaddr;
struct in_addr netmask;
int addrs; /* Number of allocated IP addresses */
int routes; /* One if we allocated an automatic route */
char devname[IFNAMSIZ];/* Name of the tun device */
int (*cb_ind) (struct tun_t *tun, void *pack, unsigned len);
int fd; /* File descriptor to tun interface */
struct in_addr addr;
struct in_addr dstaddr;
struct in_addr netmask;
int addrs; /* Number of allocated IP addresses */
int routes; /* One if we allocated an automatic route */
char devname[IFNAMSIZ]; /* Name of the tun device */
int (*cb_ind) (struct tun_t * tun, void *pack, unsigned len);
};
extern int tun_new(struct tun_t **tun);
extern int tun_free(struct tun_t *tun);
extern int tun_decaps(struct tun_t *this);
@ -58,17 +56,16 @@ extern int tun_encaps(struct tun_t *tun, void *pack, unsigned len);
extern int tun_addaddr(struct tun_t *this, struct in_addr *addr,
struct in_addr *dstaddr, struct in_addr *netmask);
extern int tun_setaddr(struct tun_t *this, struct in_addr *our_adr,
extern int tun_setaddr(struct tun_t *this, struct in_addr *our_adr,
struct in_addr *his_adr, struct in_addr *net_mask);
int tun_addroute(struct tun_t *this, struct in_addr *dst,
int tun_addroute(struct tun_t *this, struct in_addr *dst,
struct in_addr *gateway, struct in_addr *mask);
extern int tun_set_cb_ind(struct tun_t *this,
int (*cb_ind) (struct tun_t *tun, void *pack, unsigned len));
extern int tun_set_cb_ind(struct tun_t *this,
int (*cb_ind) (struct tun_t * tun, void *pack,
unsigned len));
extern int tun_runscript(struct tun_t *tun, char *script);
extern int tun_runscript(struct tun_t *tun, char* script);
#endif /* !_TUN_H */
#endif /* !_TUN_H */

File diff suppressed because it is too large Load Diff

View File

@ -12,7 +12,7 @@
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#ifndef CMDLINE_PARSER_PACKAGE
#define CMDLINE_PARSER_PACKAGE PACKAGE
@ -22,190 +22,189 @@ extern "C" {
#define CMDLINE_PARSER_VERSION VERSION
#endif
struct gengetopt_args_info
{
const char *help_help; /* Print help and exit help description. */
const char *version_help; /* Print version and exit help description. */
int debug_flag; /* Run in debug mode (default=off). */
const char *debug_help; /* Run in debug mode help description. */
char * conf_arg; /* Read configuration file. */
char * conf_orig; /* Read configuration file original value given at command line. */
const char *conf_help; /* Read configuration file help description. */
char * pidfile_arg; /* Filename of process id file (default='./sgsnemu.pid'). */
char * pidfile_orig; /* Filename of process id file original value given at command line. */
const char *pidfile_help; /* Filename of process id file help description. */
char * statedir_arg; /* Directory of nonvolatile data (default='./'). */
char * statedir_orig; /* Directory of nonvolatile data original value given at command line. */
const char *statedir_help; /* Directory of nonvolatile data help description. */
char * dns_arg; /* DNS Server to use. */
char * dns_orig; /* DNS Server to use original value given at command line. */
const char *dns_help; /* DNS Server to use help description. */
char * listen_arg; /* Local interface. */
char * listen_orig; /* Local interface original value given at command line. */
const char *listen_help; /* Local interface help description. */
char * remote_arg; /* Remote host. */
char * remote_orig; /* Remote host original value given at command line. */
const char *remote_help; /* Remote host help description. */
int contexts_arg; /* Number of contexts (default='1'). */
char * contexts_orig; /* Number of contexts original value given at command line. */
const char *contexts_help; /* Number of contexts help description. */
int timelimit_arg; /* Exit after timelimit seconds (default='0'). */
char * timelimit_orig; /* Exit after timelimit seconds original value given at command line. */
const char *timelimit_help; /* Exit after timelimit seconds help description. */
int gtpversion_arg; /* GTP version to use (default='1'). */
char * gtpversion_orig; /* GTP version to use original value given at command line. */
const char *gtpversion_help; /* GTP version to use help description. */
char * apn_arg; /* Access point name (default='internet'). */
char * apn_orig; /* Access point name original value given at command line. */
const char *apn_help; /* Access point name help description. */
int selmode_arg; /* Selection mode (default='0x01'). */
char * selmode_orig; /* Selection mode original value given at command line. */
const char *selmode_help; /* Selection mode help description. */
char * rattype_arg; /* Radio Access Technology Type (optional). */
char * rattype_orig;
char * rattype_help;
char * userloc_arg; /* User Location Information (optional). */
char * userloc_orig;
char * userloc_help;
char * rai_arg; /* Routing Area Information (optional). */
char * rai_orig;
char * rai_help;
char * mstz_arg; /* MS Time Zone (optional). */
char * mstz_orig;
char * mstz_help;
char * imeisv_arg; /* IMEI(SV) (optional). */
char * imeisv_orig;
char * imeisv_help;
char * imsi_arg; /* IMSI (default='240010123456789'). */
char * imsi_orig; /* IMSI original value given at command line. */
const char *imsi_help; /* IMSI help description. */
int nsapi_arg; /* NSAPI (default='0'). */
char * nsapi_orig; /* NSAPI original value given at command line. */
const char *nsapi_help; /* NSAPI help description. */
char * msisdn_arg; /* Mobile Station ISDN number (default='46702123456'). */
char * msisdn_orig; /* Mobile Station ISDN number original value given at command line. */
const char *msisdn_help; /* Mobile Station ISDN number help description. */
int qos_arg; /* Requested quality of service (default='0x0b921f'). */
char * qos_orig; /* Requested quality of service original value given at command line. */
const char *qos_help; /* Requested quality of service help description. */
unsigned long long int qose1_arg; /* Requested quality of service Extension 1 */
char * qose1_orig; /* Requested quality of service Extension 1 original value given at command line. */
int qose2_arg; /* Requested quality of service Extension 2 */
char * qose2_orig; /* Requested quality of service Extension 2 original value given at command line. */
int qose3_arg; /* Requested quality of service Extension 3 */
char * qose3_orig; /* Requested quality of service Extension 3 original value given at command line. */
int qose4_arg; /* Requested quality of service Extension 4 */
char * qose4_orig; /* Requested quality of service Extension 4 original value given at command line. */
int charging_arg; /* Charging characteristics (default='0x0800'). */
char * charging_orig; /* Charging characteristics original value given at command line. */
const char *charging_help; /* Charging characteristics help description. */
char * uid_arg; /* Login user ID (default='mig'). */
char * uid_orig; /* Login user ID original value given at command line. */
const char *uid_help; /* Login user ID help description. */
char * pwd_arg; /* Login password (default='hemmelig'). */
char * pwd_orig; /* Login password original value given at command line. */
const char *pwd_help; /* Login password help description. */
int createif_flag; /* Create local network interface (default=off). */
const char *createif_help; /* Create local network interface help description. */
char * net_arg; /* Network address for local interface. */
char * net_orig; /* Network address for local interface original value given at command line. */
const char *net_help; /* Network address for local interface help description. */
int defaultroute_flag; /* Create default route (default=off). */
const char *defaultroute_help; /* Create default route help description. */
char * ipup_arg; /* Script to run after link-up. */
char * ipup_orig; /* Script to run after link-up original value given at command line. */
const char *ipup_help; /* Script to run after link-up help description. */
char * ipdown_arg; /* Script to run after link-down. */
char * ipdown_orig; /* Script to run after link-down original value given at command line. */
const char *ipdown_help; /* Script to run after link-down help description. */
char * pinghost_arg; /* Ping remote host. */
char * pinghost_orig; /* Ping remote host original value given at command line. */
const char *pinghost_help; /* Ping remote host help description. */
int pingrate_arg; /* Number of ping req per second (default='1'). */
char * pingrate_orig; /* Number of ping req per second original value given at command line. */
const char *pingrate_help; /* Number of ping req per second help description. */
int pingsize_arg; /* Number of ping data bytes (default='56'). */
char * pingsize_orig; /* Number of ping data bytes original value given at command line. */
const char *pingsize_help; /* Number of ping data bytes help description. */
int pingcount_arg; /* Number of ping req to send (default='0'). */
char * pingcount_orig; /* Number of ping req to send original value given at command line. */
const char *pingcount_help; /* Number of ping req to send help description. */
int pingquiet_flag; /* Do not print ping packet info (default=off). */
const char *pingquiet_help; /* Do not print ping packet info help description. */
int norecovery_flag; /* Do not print ping packet info (default=off). */
const char *norecovery_help; /* Do not print ping packet info help description. */
int help_given ; /* Whether help was given. */
int version_given ; /* Whether version was given. */
int debug_given ; /* Whether debug was given. */
int conf_given ; /* Whether conf was given. */
int pidfile_given ; /* Whether pidfile was given. */
int statedir_given ; /* Whether statedir was given. */
int dns_given ; /* Whether dns was given. */
int listen_given ; /* Whether listen was given. */
int remote_given ; /* Whether remote was given. */
int contexts_given ; /* Whether contexts was given. */
int timelimit_given ; /* Whether timelimit was given. */
int gtpversion_given ; /* Whether gtpversion was given. */
int apn_given ; /* Whether apn was given. */
int selmode_given ; /* Whether selmode was given. */
int rattype_given ; /* Whether rattype was given. */
int userloc_given ; /* Whether userloc was given. */
int rai_given ; /* Whether RAI was given. */
int mstz_given ; /* Whether mstz was given. */
int imeisv_given ; /* Whether imeisv was given. */
int imsi_given ; /* Whether imsi was given. */
int nsapi_given ; /* Whether nsapi was given. */
int msisdn_given ; /* Whether msisdn was given. */
int qos_given ; /* Whether qos was given. */
int qose1_given ; /* Whether qos Extension 1 was given. */
int qose2_given ; /* Whether qos Extension 2 was given. */
int qose3_given ; /* Whether qos Extension 3 was given. */
int qose4_given ; /* Whether qos Extension 4 was given. */
int charging_given ; /* Whether charging was given. */
int uid_given ; /* Whether uid was given. */
int pwd_given ; /* Whether pwd was given. */
int createif_given ; /* Whether createif was given. */
int net_given ; /* Whether net was given. */
int defaultroute_given ; /* Whether defaultroute was given. */
int ipup_given ; /* Whether ipup was given. */
int ipdown_given ; /* Whether ipdown was given. */
int pinghost_given ; /* Whether pinghost was given. */
int pingrate_given ; /* Whether pingrate was given. */
int pingsize_given ; /* Whether pingsize was given. */
int pingcount_given ; /* Whether pingcount was given. */
int pingquiet_given ; /* Whether pingquiet was given. */
int norecovery_given ; /* Whether norecovery was given. */
struct gengetopt_args_info {
const char *help_help; /* Print help and exit help description. */
const char *version_help; /* Print version and exit help description. */
int debug_flag; /* Run in debug mode (default=off). */
const char *debug_help; /* Run in debug mode help description. */
char *conf_arg; /* Read configuration file. */
char *conf_orig; /* Read configuration file original value given at command line. */
const char *conf_help; /* Read configuration file help description. */
char *pidfile_arg; /* Filename of process id file (default='./sgsnemu.pid'). */
char *pidfile_orig; /* Filename of process id file original value given at command line. */
const char *pidfile_help; /* Filename of process id file help description. */
char *statedir_arg; /* Directory of nonvolatile data (default='./'). */
char *statedir_orig; /* Directory of nonvolatile data original value given at command line. */
const char *statedir_help; /* Directory of nonvolatile data help description. */
char *dns_arg; /* DNS Server to use. */
char *dns_orig; /* DNS Server to use original value given at command line. */
const char *dns_help; /* DNS Server to use help description. */
char *listen_arg; /* Local interface. */
char *listen_orig; /* Local interface original value given at command line. */
const char *listen_help; /* Local interface help description. */
char *remote_arg; /* Remote host. */
char *remote_orig; /* Remote host original value given at command line. */
const char *remote_help; /* Remote host help description. */
int contexts_arg; /* Number of contexts (default='1'). */
char *contexts_orig; /* Number of contexts original value given at command line. */
const char *contexts_help; /* Number of contexts help description. */
int timelimit_arg; /* Exit after timelimit seconds (default='0'). */
char *timelimit_orig; /* Exit after timelimit seconds original value given at command line. */
const char *timelimit_help; /* Exit after timelimit seconds help description. */
int gtpversion_arg; /* GTP version to use (default='1'). */
char *gtpversion_orig; /* GTP version to use original value given at command line. */
const char *gtpversion_help; /* GTP version to use help description. */
char *apn_arg; /* Access point name (default='internet'). */
char *apn_orig; /* Access point name original value given at command line. */
const char *apn_help; /* Access point name help description. */
int selmode_arg; /* Selection mode (default='0x01'). */
char *selmode_orig; /* Selection mode original value given at command line. */
const char *selmode_help; /* Selection mode help description. */
char *rattype_arg; /* Radio Access Technology Type (optional). */
char *rattype_orig;
char *rattype_help;
char *userloc_arg; /* User Location Information (optional). */
char *userloc_orig;
char *userloc_help;
char *rai_arg; /* Routing Area Information (optional). */
char *rai_orig;
char *rai_help;
char *mstz_arg; /* MS Time Zone (optional). */
char *mstz_orig;
char *mstz_help;
char *imeisv_arg; /* IMEI(SV) (optional). */
char *imeisv_orig;
char *imeisv_help;
char *imsi_arg; /* IMSI (default='240010123456789'). */
char *imsi_orig; /* IMSI original value given at command line. */
const char *imsi_help; /* IMSI help description. */
int nsapi_arg; /* NSAPI (default='0'). */
char *nsapi_orig; /* NSAPI original value given at command line. */
const char *nsapi_help; /* NSAPI help description. */
char *msisdn_arg; /* Mobile Station ISDN number (default='46702123456'). */
char *msisdn_orig; /* Mobile Station ISDN number original value given at command line. */
const char *msisdn_help; /* Mobile Station ISDN number help description. */
int qos_arg; /* Requested quality of service (default='0x0b921f'). */
char *qos_orig; /* Requested quality of service original value given at command line. */
const char *qos_help; /* Requested quality of service help description. */
unsigned long long int qose1_arg; /* Requested quality of service Extension 1 */
char *qose1_orig; /* Requested quality of service Extension 1 original value given at command line. */
int qose2_arg; /* Requested quality of service Extension 2 */
char *qose2_orig; /* Requested quality of service Extension 2 original value given at command line. */
int qose3_arg; /* Requested quality of service Extension 3 */
char *qose3_orig; /* Requested quality of service Extension 3 original value given at command line. */
int qose4_arg; /* Requested quality of service Extension 4 */
char *qose4_orig; /* Requested quality of service Extension 4 original value given at command line. */
int charging_arg; /* Charging characteristics (default='0x0800'). */
char *charging_orig; /* Charging characteristics original value given at command line. */
const char *charging_help; /* Charging characteristics help description. */
char *uid_arg; /* Login user ID (default='mig'). */
char *uid_orig; /* Login user ID original value given at command line. */
const char *uid_help; /* Login user ID help description. */
char *pwd_arg; /* Login password (default='hemmelig'). */
char *pwd_orig; /* Login password original value given at command line. */
const char *pwd_help; /* Login password help description. */
int createif_flag; /* Create local network interface (default=off). */
const char *createif_help; /* Create local network interface help description. */
char *net_arg; /* Network address for local interface. */
char *net_orig; /* Network address for local interface original value given at command line. */
const char *net_help; /* Network address for local interface help description. */
int defaultroute_flag; /* Create default route (default=off). */
const char *defaultroute_help; /* Create default route help description. */
char *ipup_arg; /* Script to run after link-up. */
char *ipup_orig; /* Script to run after link-up original value given at command line. */
const char *ipup_help; /* Script to run after link-up help description. */
char *ipdown_arg; /* Script to run after link-down. */
char *ipdown_orig; /* Script to run after link-down original value given at command line. */
const char *ipdown_help; /* Script to run after link-down help description. */
char *pinghost_arg; /* Ping remote host. */
char *pinghost_orig; /* Ping remote host original value given at command line. */
const char *pinghost_help; /* Ping remote host help description. */
int pingrate_arg; /* Number of ping req per second (default='1'). */
char *pingrate_orig; /* Number of ping req per second original value given at command line. */
const char *pingrate_help; /* Number of ping req per second help description. */
int pingsize_arg; /* Number of ping data bytes (default='56'). */
char *pingsize_orig; /* Number of ping data bytes original value given at command line. */
const char *pingsize_help; /* Number of ping data bytes help description. */
int pingcount_arg; /* Number of ping req to send (default='0'). */
char *pingcount_orig; /* Number of ping req to send original value given at command line. */
const char *pingcount_help; /* Number of ping req to send help description. */
int pingquiet_flag; /* Do not print ping packet info (default=off). */
const char *pingquiet_help; /* Do not print ping packet info help description. */
int norecovery_flag; /* Do not print ping packet info (default=off). */
const char *norecovery_help; /* Do not print ping packet info help description. */
} ;
int help_given; /* Whether help was given. */
int version_given; /* Whether version was given. */
int debug_given; /* Whether debug was given. */
int conf_given; /* Whether conf was given. */
int pidfile_given; /* Whether pidfile was given. */
int statedir_given; /* Whether statedir was given. */
int dns_given; /* Whether dns was given. */
int listen_given; /* Whether listen was given. */
int remote_given; /* Whether remote was given. */
int contexts_given; /* Whether contexts was given. */
int timelimit_given; /* Whether timelimit was given. */
int gtpversion_given; /* Whether gtpversion was given. */
int apn_given; /* Whether apn was given. */
int selmode_given; /* Whether selmode was given. */
int rattype_given; /* Whether rattype was given. */
int userloc_given; /* Whether userloc was given. */
int rai_given; /* Whether RAI was given. */
int mstz_given; /* Whether mstz was given. */
int imeisv_given; /* Whether imeisv was given. */
int imsi_given; /* Whether imsi was given. */
int nsapi_given; /* Whether nsapi was given. */
int msisdn_given; /* Whether msisdn was given. */
int qos_given; /* Whether qos was given. */
int qose1_given; /* Whether qos Extension 1 was given. */
int qose2_given; /* Whether qos Extension 2 was given. */
int qose3_given; /* Whether qos Extension 3 was given. */
int qose4_given; /* Whether qos Extension 4 was given. */
int charging_given; /* Whether charging was given. */
int uid_given; /* Whether uid was given. */
int pwd_given; /* Whether pwd was given. */
int createif_given; /* Whether createif was given. */
int net_given; /* Whether net was given. */
int defaultroute_given; /* Whether defaultroute was given. */
int ipup_given; /* Whether ipup was given. */
int ipdown_given; /* Whether ipdown was given. */
int pinghost_given; /* Whether pinghost was given. */
int pingrate_given; /* Whether pingrate was given. */
int pingsize_given; /* Whether pingsize was given. */
int pingcount_given; /* Whether pingcount was given. */
int pingquiet_given; /* Whether pingquiet was given. */
int norecovery_given; /* Whether norecovery was given. */
extern const char *gengetopt_args_info_purpose;
extern const char *gengetopt_args_info_usage;
extern const char *gengetopt_args_info_help[];
};
int cmdline_parser (int argc, char * const *argv,
struct gengetopt_args_info *args_info);
int cmdline_parser2 (int argc, char * const *argv,
struct gengetopt_args_info *args_info,
int override, int initialize, int check_required);
int cmdline_parser_file_save(const char *filename,
struct gengetopt_args_info *args_info);
extern const char *gengetopt_args_info_purpose;
extern const char *gengetopt_args_info_usage;
extern const char *gengetopt_args_info_help[];
void cmdline_parser_print_help(void);
void cmdline_parser_print_version(void);
int cmdline_parser(int argc, char *const *argv,
struct gengetopt_args_info *args_info);
int cmdline_parser2(int argc, char *const *argv,
struct gengetopt_args_info *args_info,
int override, int initialize, int check_required);
int cmdline_parser_file_save(const char *filename,
struct gengetopt_args_info *args_info);
void cmdline_parser_init (struct gengetopt_args_info *args_info);
void cmdline_parser_free (struct gengetopt_args_info *args_info);
void cmdline_parser_print_help(void);
void cmdline_parser_print_version(void);
int cmdline_parser_configfile (char * const filename,
struct gengetopt_args_info *args_info,
int override, int initialize, int check_required);
void cmdline_parser_init(struct gengetopt_args_info *args_info);
void cmdline_parser_free(struct gengetopt_args_info *args_info);
int cmdline_parser_required (struct gengetopt_args_info *args_info,
const char *prog_name);
int cmdline_parser_configfile(char *const filename,
struct gengetopt_args_info *args_info,
int override, int initialize,
int check_required);
int cmdline_parser_required(struct gengetopt_args_info *args_info,
const char *prog_name);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* CMDLINE_H */
#endif /* __cplusplus */
#endif /* CMDLINE_H */

File diff suppressed because it is too large Load Diff