aboutsummaryrefslogtreecommitdiffstats
path: root/ggsn/ggsn.c
diff options
context:
space:
mode:
Diffstat (limited to 'ggsn/ggsn.c')
-rw-r--r--ggsn/ggsn.c924
1 files changed, 478 insertions, 446 deletions
diff --git a/ggsn/ggsn.c b/ggsn/ggsn.c
index 9e0b597..1152519 100644
--- a/ggsn/ggsn.c
+++ b/ggsn/ggsn.c
@@ -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;
-
- switch (fork()) {
- case -1:
- return (-1);
- case 0:
- break;
- default:
- _exit(0);
- }
-
- if (setsid() == -1)
- return (-1);
-
- 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);
+int daemon(int nochdir, int noclose)
+{
+ int fd;
+
+ switch (fork()) {
+ case -1:
+ return (-1);
+ case 0:
+ break;
+ default:
+ _exit(0);
+ }
+
+ if (setsid() == -1)
+ return (-1);
+
+ 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;
-
- 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 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;
-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);
+ dst.s_addr = iph->dst;
+
+ 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 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);
- }
-
- /* 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);
- }
-
- /* Handle each option */
-
- /* 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);
- }
-
-
- /* 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);
- }
- }
-
- /* DNS1 and DNS2 */
+ 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 */
+
+ 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 */
+
+ /* 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);
+ }
+
+ /* 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);
+ }
+ }
+
+ /* 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));
-
- /* ipup */
- ipup = args_info.ipup_arg;
-
- /* ipdown */
- ipdown = args_info.ipdown_arg;
-
- /* 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;
-
- /* 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);
- }
-
- /* 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 (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);
-
-
- /* 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);
- }
-
-
- tun_set_cb_ind(tun, cb_tun_ind);
- if (tun->fd > maxfd) maxfd = tun->fd;
-
- if (ipup) tun_runscript(tun, ipup);
+ 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;
+
+ /* ipdown */
+ ipdown = args_info.ipdown_arg;
+
+ /* 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;
+
+ /* 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);
+ }
+
+ /* 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 (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);
+
+ /* 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);
+ }
+
+ tun_set_cb_ind(tun, cb_tun_ind);
+ if (tun->fd > maxfd)
+ maxfd = tun->fd;
+
+ if (ipup)
+ tun_runscript(tun, ipup);
/******************************************************************/
- /* Main select loop */
+ /* Main select loop */
/******************************************************************/
- 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;
- }
-
- 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;
-
-}
+ 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;
+ }
+
+ 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;
+}