IPv4v6 PDP context type in sgsnemu

Change-Id: If6eb2f1a5d0fb71da80e289112a67dd2faa30b4b
diff --git a/lib/tun.c b/lib/tun.c
index 1aeed55..b6a9652 100644
--- a/lib/tun.c
+++ b/lib/tun.c
@@ -364,3 +364,35 @@
 {
 	return netdev_ip_local_get(tun->devname, prefix_list, prefix_size, flags);
 }
+
+#if defined(__linux__)
+
+int tun_settoken(struct tun_t *tun, struct in46_addr *addr)
+{
+	struct in46_addr token;
+	char buf[2048];
+	int rc;
+
+	rc = system("/sbin/ip token list");
+
+	token = *addr;
+	memset(token.v6.s6_addr, 0, 8);
+
+	printf("TUN Interface Addr: %s\n", in46a_ntoa(addr));
+	printf("TUN Interface token: %s\n", in46a_ntoa(&token));
+
+	/* system("ip token set ::1/64 dev tun0"); */
+	snprintf(buf, sizeof(buf), "/sbin/ip token set %s/64 dev %s",
+		 in46a_ntoa(&token), tun->devname);
+	buf[sizeof(buf) - 1] = 0;
+	printf("Exec TUN CMD: %s\n", buf);
+	rc = system(buf);
+	if (rc == -1) {
+		SYS_ERR(DTUN, LOGL_ERROR, errno,
+			"Error executing command %s", buf);
+		return -1;
+	}
+	return 0;
+}
+
+#endif
diff --git a/lib/tun.h b/lib/tun.h
index 07ca04a..397c7f2 100644
--- a/lib/tun.h
+++ b/lib/tun.h
@@ -59,4 +59,8 @@
 int tun_ip_local_get(const struct tun_t *tun, struct in46_prefix *prefix_list,
 		     size_t prefix_size, int flags);
 
+#if defined(__linux__)
+extern int tun_settoken(struct tun_t *tun, struct in46_addr *addr);
+#endif
+
 #endif /* !_TUN_H */
diff --git a/sgsnemu/cmdline.c b/sgsnemu/cmdline.c
index 13d0295..21ac665 100644
--- a/sgsnemu/cmdline.c
+++ b/sgsnemu/cmdline.c
@@ -80,7 +80,7 @@
 	"      --pingcount=INT           Number of ping req to send  (default=`0')",
 	"      --pingquiet               Do not print ping packet info  (default=off)",
 	"      --no-tx-gpdu-seq          Don't transmit G-PDU sequence nums\n                                  (default=off)",
-	"  -t, --pdp-type=(v4|v6)        PDP Type  (default=`v4')",
+	"  -t, --pdp-type=(v4|v6|v4v6)   PDP Type  (default=`v4')",
 	0
 };
 
diff --git a/sgsnemu/cmdline.ggo b/sgsnemu/cmdline.ggo
index 0d074aa..3394e76 100644
--- a/sgsnemu/cmdline.ggo
+++ b/sgsnemu/cmdline.ggo
@@ -68,4 +68,4 @@
 modeoption   "pingquiet"    - "Do not print ping packet info"  flag dependon="pinghost" off             mode="pinghost"
 
 option  "no-tx-gpdu-seq" - "Don't transmit G-PDU sequence nums"   flag    off
-option  "pdp-type"     t "PDP Type"                       string default="v4" no typestr="(v4|v6)"
+option  "pdp-type"     t "PDP Type"                       string default="v4" no typestr="(v4|v6|v4v6)"
diff --git a/sgsnemu/sgsnemu.c b/sgsnemu/sgsnemu.c
index fce5059..5af6b62 100644
--- a/sgsnemu/sgsnemu.c
+++ b/sgsnemu/sgsnemu.c
@@ -949,13 +949,16 @@
 		options.pdp_type = PDP_EUA_TYPE_v6;
 	else if (!strcmp(args_info.pdp_type_arg, "v4"))
 		options.pdp_type = PDP_EUA_TYPE_v4;
+	else if (!strcmp(args_info.pdp_type_arg, "v4v6"))
+		options.pdp_type = PDP_EUA_TYPE_v4v6;
 	else {
 		SYS_ERR(DSGSN, LOGL_ERROR, 0, "Unsupported/unknown PDP Type '%s'\n",
 			args_info.pdp_type_arg);
 		return -1;
 	}
 
-	if (options.pingcount && options.pdp_type != PDP_EUA_TYPE_v4) {
+	if (options.pingcount && (options.pdp_type != PDP_EUA_TYPE_v4 &&
+				  options.pdp_type != PDP_EUA_TYPE_v4v6)) {
 		SYS_ERR(DSGSN, LOGL_ERROR, 0, "built-in ping only works with IPv4, use tun-device");
 		return -1;
 	}
@@ -1483,6 +1486,12 @@
 			prefixlen = 64;
 		/* printf("Setting up interface and routing\n"); */
 		tun_addaddr(tun, &addr, &addr, prefixlen);
+
+#if defined(__linux__)
+		if (addr.len == 16)
+			tun_settoken(tun, &addr);
+#endif
+
 		if (options.defaultroute) {
 			struct in_addr rm;
 			rm.s_addr = 0;
@@ -1494,7 +1503,8 @@
 
 	/* now that ip-up has been executed, check if we are configured to
 	 * accept router advertisements */
-	if (options.createif && options.pdp_type == PDP_EUA_TYPE_v6) {
+	if (options.createif && (options.pdp_type == PDP_EUA_TYPE_v6 ||
+				 options.pdp_type == PDP_EUA_TYPE_v4v6)) {
 		char *accept_ra, *forwarding;
 
 		accept_ra = proc_ipv6_conf_read(tun->devname, "accept_ra");