mirror of
				https://gitea.osmocom.org/cellular-infrastructure/osmo-ggsn.git
				synced 2025-11-04 06:03:23 +00:00 
			
		
		
		
	Compare commits
	
		
			1 Commits
		
	
	
		
			1.3.0
			...
			pespin/dis
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					31e9f03dbf | 
							
								
								
									
										14
									
								
								configure.ac
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								configure.ac
									
									
									
									
									
								
							@@ -64,13 +64,20 @@ dnl GTP Linux kernel dependencies
 | 
				
			|||||||
AC_ARG_ENABLE([gtp-linux],
 | 
					AC_ARG_ENABLE([gtp-linux],
 | 
				
			||||||
	AS_HELP_STRING([--enable-gtp-linux], [Build GTP tunneling Linux kernel]),
 | 
						AS_HELP_STRING([--enable-gtp-linux], [Build GTP tunneling Linux kernel]),
 | 
				
			||||||
	[enable_gtp_linux="$enableval"], [enable_gtp_linux="no"])
 | 
						[enable_gtp_linux="$enableval"], [enable_gtp_linux="no"])
 | 
				
			||||||
 | 
					 | 
				
			||||||
AS_IF([test "x$enable_gtp_linux" = "xyes"], [
 | 
					AS_IF([test "x$enable_gtp_linux" = "xyes"], [
 | 
				
			||||||
	PKG_CHECK_MODULES([LIBGTPNL], [libgtpnl >= 1.0.0])
 | 
						PKG_CHECK_MODULES([LIBGTPNL], [libgtpnl >= 1.0.0])
 | 
				
			||||||
])
 | 
					])
 | 
				
			||||||
 | 
					 | 
				
			||||||
AM_CONDITIONAL([ENABLE_GTP_KERNEL], [test "$enable_gtp_linux" = "yes"])
 | 
					AM_CONDITIONAL([ENABLE_GTP_KERNEL], [test "$enable_gtp_linux" = "yes"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Enable/disable IPv6 support
 | 
				
			||||||
 | 
					AC_ARG_ENABLE([ipv6], [AS_HELP_STRING([--enable-ipv6], [Build IPv6 support])],
 | 
				
			||||||
 | 
					    [enable_ipv6="$enableval"],[enable_ipv6="yes"])
 | 
				
			||||||
 | 
					if test "x$enable_ipv6" = "xyes" ; then
 | 
				
			||||||
 | 
					    AC_DEFINE(BUILD_IPv6, 1, [Define if we want to build IPv6 support])
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					AM_CONDITIONAL(BUILD_IPv6, test "x$enable_ipv6" = "xyes")
 | 
				
			||||||
 | 
					#AC_SUBST(enable_ipv6)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Checks for header files.
 | 
					# Checks for header files.
 | 
				
			||||||
AC_HEADER_STDC
 | 
					AC_HEADER_STDC
 | 
				
			||||||
AC_HEADER_SYS_WAIT
 | 
					AC_HEADER_SYS_WAIT
 | 
				
			||||||
@@ -170,4 +177,5 @@ AC_OUTPUT
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
echo "
 | 
					echo "
 | 
				
			||||||
osmo-ggsn Configuration:
 | 
					osmo-ggsn Configuration:
 | 
				
			||||||
  GTP Linux kernel support:			${enable_gtp_linux}"
 | 
					  GTP Linux kernel support:			${enable_gtp_linux}
 | 
				
			||||||
 | 
					  IPv6 support:		                       	${enable_ipv6}"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,7 +12,10 @@ osmo_ggsn_LDADD += -lgtpnl
 | 
				
			|||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
osmo_ggsn_DEPENDENCIES = ../gtp/libgtp.la ../lib/libmisc.a
 | 
					osmo_ggsn_DEPENDENCIES = ../gtp/libgtp.la ../lib/libmisc.a
 | 
				
			||||||
osmo_ggsn_SOURCES = ggsn_vty.c ggsn.c ggsn.h gtp-kernel.h icmpv6.c icmpv6.h checksum.c checksum.h
 | 
					osmo_ggsn_SOURCES = ggsn_vty.c ggsn.c ggsn.h gtp-kernel.h checksum.c checksum.h
 | 
				
			||||||
 | 
					if BUILD_IPv6
 | 
				
			||||||
 | 
					osmo_ggsn_SOURCES += icmpv6.c icmpv6.h
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if ENABLE_GTP_KERNEL
 | 
					if ENABLE_GTP_KERNEL
 | 
				
			||||||
osmo_ggsn_SOURCES += gtp-kernel.c
 | 
					osmo_ggsn_SOURCES += gtp-kernel.c
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										38
									
								
								ggsn/ggsn.c
									
									
									
									
									
								
							
							
						
						
									
										38
									
								
								ggsn/ggsn.c
									
									
									
									
									
								
							@@ -65,7 +65,9 @@
 | 
				
			|||||||
#include "../gtp/pdp.h"
 | 
					#include "../gtp/pdp.h"
 | 
				
			||||||
#include "../gtp/gtp.h"
 | 
					#include "../gtp/gtp.h"
 | 
				
			||||||
#include "gtp-kernel.h"
 | 
					#include "gtp-kernel.h"
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
#include "icmpv6.h"
 | 
					#include "icmpv6.h"
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
#include "ggsn.h"
 | 
					#include "ggsn.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void *tall_ggsn_ctx;
 | 
					void *tall_ggsn_ctx;
 | 
				
			||||||
@@ -115,7 +117,9 @@ int apn_stop(struct apn_ctx *apn, bool force)
 | 
				
			|||||||
	LOGPAPN(LOGL_NOTICE, apn, "%sStopping\n", force ? "FORCED " : "");
 | 
						LOGPAPN(LOGL_NOTICE, apn, "%sStopping\n", force ? "FORCED " : "");
 | 
				
			||||||
	/* check if pools have any active PDP contexts and bail out */
 | 
						/* check if pools have any active PDP contexts and bail out */
 | 
				
			||||||
	pool_close_all_pdp(apn->v4.pool);
 | 
						pool_close_all_pdp(apn->v4.pool);
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
	pool_close_all_pdp(apn->v6.pool);
 | 
						pool_close_all_pdp(apn->v6.pool);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* shutdown whatever old state might be left */
 | 
						/* shutdown whatever old state might be left */
 | 
				
			||||||
	if (apn->tun.tun) {
 | 
						if (apn->tun.tun) {
 | 
				
			||||||
@@ -137,12 +141,13 @@ int apn_stop(struct apn_ctx *apn, bool force)
 | 
				
			|||||||
		ippool_free(apn->v4.pool);
 | 
							ippool_free(apn->v4.pool);
 | 
				
			||||||
		apn->v4.pool = NULL;
 | 
							apn->v4.pool = NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
	if (apn->v6.pool) {
 | 
						if (apn->v6.pool) {
 | 
				
			||||||
		LOGPAPN(LOGL_INFO, apn, "Releasing IPv6 pool\n");
 | 
							LOGPAPN(LOGL_INFO, apn, "Releasing IPv6 pool\n");
 | 
				
			||||||
		ippool_free(apn->v6.pool);
 | 
							ippool_free(apn->v6.pool);
 | 
				
			||||||
		apn->v6.pool = NULL;
 | 
							apn->v6.pool = NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
	apn->started = false;
 | 
						apn->started = false;
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -155,9 +160,11 @@ static int alloc_ippool_blacklist(struct apn_ctx *apn, struct in46_prefix **blac
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	*blacklist = NULL;
 | 
						*blacklist = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
	if (ipv6)
 | 
						if (ipv6)
 | 
				
			||||||
		flags = IP_TYPE_IPv6_NONLINK;
 | 
							flags = IP_TYPE_IPv6_NONLINK;
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
		flags = IP_TYPE_IPv4;
 | 
							flags = IP_TYPE_IPv4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	while (1) {
 | 
						while (1) {
 | 
				
			||||||
@@ -191,7 +198,9 @@ static int alloc_ippool_blacklist(struct apn_ctx *apn, struct in46_prefix **blac
 | 
				
			|||||||
int apn_start(struct apn_ctx *apn)
 | 
					int apn_start(struct apn_ctx *apn)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int ippool_flags = IPPOOL_NONETWORK | IPPOOL_NOBROADCAST;
 | 
						int ippool_flags = IPPOOL_NONETWORK | IPPOOL_NOBROADCAST;
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
	struct in46_prefix ipv6_tun_linklocal_ip;
 | 
						struct in46_prefix ipv6_tun_linklocal_ip;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
	struct in46_prefix *blacklist;
 | 
						struct in46_prefix *blacklist;
 | 
				
			||||||
	int blacklist_size;
 | 
						int blacklist_size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -226,7 +235,7 @@ int apn_start(struct apn_ctx *apn)
 | 
				
			|||||||
				return -1;
 | 
									return -1;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
		if (apn->v6.cfg.ifconfig_prefix.addr.len) {
 | 
							if (apn->v6.cfg.ifconfig_prefix.addr.len) {
 | 
				
			||||||
			LOGPAPN(LOGL_INFO, apn, "Setting tun IPv6 address %s\n",
 | 
								LOGPAPN(LOGL_INFO, apn, "Setting tun IPv6 address %s\n",
 | 
				
			||||||
				in46p_ntoa(&apn->v6.cfg.ifconfig_prefix));
 | 
									in46p_ntoa(&apn->v6.cfg.ifconfig_prefix));
 | 
				
			||||||
@@ -239,13 +248,13 @@ int apn_start(struct apn_ctx *apn)
 | 
				
			|||||||
				return -1;
 | 
									return -1;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
		if (apn->tun.cfg.ipup_script) {
 | 
							if (apn->tun.cfg.ipup_script) {
 | 
				
			||||||
			LOGPAPN(LOGL_INFO, apn, "Running ip-up script %s\n",
 | 
								LOGPAPN(LOGL_INFO, apn, "Running ip-up script %s\n",
 | 
				
			||||||
				apn->tun.cfg.ipup_script);
 | 
									apn->tun.cfg.ipup_script);
 | 
				
			||||||
			tun_runscript(apn->tun.tun, apn->tun.cfg.ipup_script);
 | 
								tun_runscript(apn->tun.tun, apn->tun.cfg.ipup_script);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
		if (apn->cfg.apn_type_mask & (APN_TYPE_IPv6|APN_TYPE_IPv4v6)) {
 | 
							if (apn->cfg.apn_type_mask & (APN_TYPE_IPv6|APN_TYPE_IPv4v6)) {
 | 
				
			||||||
			if (tun_ip_local_get(apn->tun.tun, &ipv6_tun_linklocal_ip, 1, IP_TYPE_IPv6_LINK) < 1) {
 | 
								if (tun_ip_local_get(apn->tun.tun, &ipv6_tun_linklocal_ip, 1, IP_TYPE_IPv6_LINK) < 1) {
 | 
				
			||||||
				LOGPAPN(LOGL_ERROR, apn, "Cannot obtain IPv6 link-local address of "
 | 
									LOGPAPN(LOGL_ERROR, apn, "Cannot obtain IPv6 link-local address of "
 | 
				
			||||||
@@ -255,17 +264,20 @@ int apn_start(struct apn_ctx *apn)
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			apn->v6_lladdr = ipv6_tun_linklocal_ip.addr.v6;
 | 
								apn->v6_lladdr = ipv6_tun_linklocal_ip.addr.v6;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* set back-pointer from TUN device to APN */
 | 
							/* set back-pointer from TUN device to APN */
 | 
				
			||||||
		apn->tun.tun->priv = apn;
 | 
							apn->tun.tun->priv = apn;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case APN_GTPU_MODE_KERNEL_GTP:
 | 
						case APN_GTPU_MODE_KERNEL_GTP:
 | 
				
			||||||
		LOGPAPN(LOGL_INFO, apn, "Opening Kernel GTP device %s\n", apn->tun.cfg.dev_name);
 | 
							LOGPAPN(LOGL_INFO, apn, "Opening Kernel GTP device %s\n", apn->tun.cfg.dev_name);
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
		if (apn->cfg.apn_type_mask & (APN_TYPE_IPv6|APN_TYPE_IPv4v6)) {
 | 
							if (apn->cfg.apn_type_mask & (APN_TYPE_IPv6|APN_TYPE_IPv4v6)) {
 | 
				
			||||||
			LOGPAPN(LOGL_ERROR, apn, "Kernel GTP currently supports only IPv4\n");
 | 
								LOGPAPN(LOGL_ERROR, apn, "Kernel GTP currently supports only IPv4\n");
 | 
				
			||||||
			apn_stop(apn, false);
 | 
								apn_stop(apn, false);
 | 
				
			||||||
			return -1;
 | 
								return -1;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
		/* use GTP kernel module for data packet encapsulation */
 | 
							/* use GTP kernel module for data packet encapsulation */
 | 
				
			||||||
		if (gtp_kernel_init(apn->ggsn->gsn, apn->tun.cfg.dev_name,
 | 
							if (gtp_kernel_init(apn->ggsn->gsn, apn->tun.cfg.dev_name,
 | 
				
			||||||
				    &apn->v4.cfg.ifconfig_prefix, apn->tun.cfg.ipup_script) < 0) {
 | 
									    &apn->v4.cfg.ifconfig_prefix, apn->tun.cfg.ipup_script) < 0) {
 | 
				
			||||||
@@ -294,6 +306,7 @@ int apn_start(struct apn_ctx *apn)
 | 
				
			|||||||
		talloc_free(blacklist);
 | 
							talloc_free(blacklist);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
	/* Create IPv6 pool */
 | 
						/* Create IPv6 pool */
 | 
				
			||||||
	if (apn->v6.cfg.dynamic_prefix.addr.len) {
 | 
						if (apn->v6.cfg.dynamic_prefix.addr.len) {
 | 
				
			||||||
		LOGPAPN(LOGL_INFO, apn, "Creating IPv6 pool %s\n",
 | 
							LOGPAPN(LOGL_INFO, apn, "Creating IPv6 pool %s\n",
 | 
				
			||||||
@@ -310,6 +323,7 @@ int apn_start(struct apn_ctx *apn)
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		talloc_free(blacklist);
 | 
							talloc_free(blacklist);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	LOGPAPN(LOGL_NOTICE, apn, "Successfully started\n");
 | 
						LOGPAPN(LOGL_NOTICE, apn, "Successfully started\n");
 | 
				
			||||||
	apn->started = true;
 | 
						apn->started = true;
 | 
				
			||||||
@@ -468,6 +482,7 @@ static void process_pco(struct apn_ctx *apn, struct pdp_t *pdp)
 | 
				
			|||||||
		build_ipcp_pco(msg, 0, &apn->v4.cfg.dns[0], &apn->v4.cfg.dns[1]);
 | 
							build_ipcp_pco(msg, 0, &apn->v4.cfg.dns[0], &apn->v4.cfg.dns[1]);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
	if (pco_contains_proto(&pdp->pco_req, PCO_P_DNS_IPv6_ADDR)) {
 | 
						if (pco_contains_proto(&pdp->pco_req, PCO_P_DNS_IPv6_ADDR)) {
 | 
				
			||||||
		for (i = 0; i < ARRAY_SIZE(apn->v6.cfg.dns); i++) {
 | 
							for (i = 0; i < ARRAY_SIZE(apn->v6.cfg.dns); i++) {
 | 
				
			||||||
			struct in46_addr *i46a = &apn->v6.cfg.dns[i];
 | 
								struct in46_addr *i46a = &apn->v6.cfg.dns[i];
 | 
				
			||||||
@@ -476,6 +491,7 @@ static void process_pco(struct apn_ctx *apn, struct pdp_t *pdp)
 | 
				
			|||||||
			msgb_t16lv_put(msg, PCO_P_DNS_IPv6_ADDR, i46a->len, i46a->v6.s6_addr);
 | 
								msgb_t16lv_put(msg, PCO_P_DNS_IPv6_ADDR, i46a->len, i46a->v6.s6_addr);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (pco_contains_proto(&pdp->pco_req, PCO_P_DNS_IPv4_ADDR)) {
 | 
						if (pco_contains_proto(&pdp->pco_req, PCO_P_DNS_IPv4_ADDR)) {
 | 
				
			||||||
		for (i = 0; i < ARRAY_SIZE(apn->v4.cfg.dns); i++) {
 | 
							for (i = 0; i < ARRAY_SIZE(apn->v4.cfg.dns); i++) {
 | 
				
			||||||
@@ -502,12 +518,14 @@ static bool apn_supports_ipv4(const struct apn_ctx *apn)
 | 
				
			|||||||
	return false;
 | 
						return false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
static bool apn_supports_ipv6(const struct apn_ctx *apn)
 | 
					static bool apn_supports_ipv6(const struct apn_ctx *apn)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (apn->v6.cfg.static_prefix.addr.len  || apn->v6.cfg.dynamic_prefix.addr.len)
 | 
						if (apn->v6.cfg.static_prefix.addr.len  || apn->v6.cfg.dynamic_prefix.addr.len)
 | 
				
			||||||
		return true;
 | 
							return true;
 | 
				
			||||||
	return false;
 | 
						return false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int create_context_ind(struct pdp_t *pdp)
 | 
					int create_context_ind(struct pdp_t *pdp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -575,6 +593,7 @@ int create_context_ind(struct pdp_t *pdp)
 | 
				
			|||||||
			gtp_create_context_resp(gsn, pdp, GTPCAUSE_SYS_FAIL);
 | 
								gtp_create_context_resp(gsn, pdp, GTPCAUSE_SYS_FAIL);
 | 
				
			||||||
			return 0;
 | 
								return 0;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
	} else if (addr.len == sizeof(struct in6_addr)) {
 | 
						} else if (addr.len == sizeof(struct in6_addr)) {
 | 
				
			||||||
		struct in46_addr tmp;
 | 
							struct in46_addr tmp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -594,6 +613,7 @@ int create_context_ind(struct pdp_t *pdp)
 | 
				
			|||||||
		/* use allocated 64bit prefix as lower 64bit, used as link id by MS */
 | 
							/* use allocated 64bit prefix as lower 64bit, used as link id by MS */
 | 
				
			||||||
		memcpy(tmp.v6.s6_addr+8, &member->addr.v6, 8);
 | 
							memcpy(tmp.v6.s6_addr+8, &member->addr.v6, 8);
 | 
				
			||||||
		in46a_to_eua(&tmp, &pdp->eua);
 | 
							in46a_to_eua(&tmp, &pdp->eua);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
	} else
 | 
						} else
 | 
				
			||||||
		OSMO_ASSERT(0);
 | 
							OSMO_ASSERT(0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -635,7 +655,9 @@ static int cb_tun_ind(struct tun_t *tun, void *pack, unsigned len)
 | 
				
			|||||||
	struct ippoolm_t *ipm;
 | 
						struct ippoolm_t *ipm;
 | 
				
			||||||
	struct in46_addr dst;
 | 
						struct in46_addr dst;
 | 
				
			||||||
	struct iphdr *iph = (struct iphdr *)pack;
 | 
						struct iphdr *iph = (struct iphdr *)pack;
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
	struct ip6_hdr *ip6h = (struct ip6_hdr *)pack;
 | 
						struct ip6_hdr *ip6h = (struct ip6_hdr *)pack;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
	struct ippool_t *pool;
 | 
						struct ippool_t *pool;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (iph->version == 4) {
 | 
						if (iph->version == 4) {
 | 
				
			||||||
@@ -644,6 +666,7 @@ static int cb_tun_ind(struct tun_t *tun, void *pack, unsigned len)
 | 
				
			|||||||
		dst.len = 4;
 | 
							dst.len = 4;
 | 
				
			||||||
		dst.v4.s_addr = iph->daddr;
 | 
							dst.v4.s_addr = iph->daddr;
 | 
				
			||||||
		pool = apn->v4.pool;
 | 
							pool = apn->v4.pool;
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
	} else if (iph->version == 6) {
 | 
						} else if (iph->version == 6) {
 | 
				
			||||||
		/* Due to the fact that 3GPP requires an allocation of a
 | 
							/* Due to the fact that 3GPP requires an allocation of a
 | 
				
			||||||
		 * /64 prefix to each MS, we must instruct
 | 
							 * /64 prefix to each MS, we must instruct
 | 
				
			||||||
@@ -652,6 +675,7 @@ static int cb_tun_ind(struct tun_t *tun, void *pack, unsigned len)
 | 
				
			|||||||
		dst.len = 8;
 | 
							dst.len = 8;
 | 
				
			||||||
		dst.v6 = ip6h->ip6_dst;
 | 
							dst.v6 = ip6h->ip6_dst;
 | 
				
			||||||
		pool = apn->v6.pool;
 | 
							pool = apn->v6.pool;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		LOGP(DTUN, LOGL_NOTICE, "non-IPv packet received from tun\n");
 | 
							LOGP(DTUN, LOGL_NOTICE, "non-IPv packet received from tun\n");
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
@@ -673,16 +697,20 @@ static int cb_tun_ind(struct tun_t *tun, void *pack, unsigned len)
 | 
				
			|||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
/* RFC3307 link-local scope multicast address */
 | 
					/* RFC3307 link-local scope multicast address */
 | 
				
			||||||
static const struct in6_addr all_router_mcast_addr = {
 | 
					static const struct in6_addr all_router_mcast_addr = {
 | 
				
			||||||
	.s6_addr = { 0xff,0x02,0,0,  0,0,0,0, 0,0,0,0,  0,0,0,2 }
 | 
						.s6_addr = { 0xff,0x02,0,0,  0,0,0,0, 0,0,0,0,  0,0,0,2 }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* MS-originated GTP1-U packet, needs to be sent via TUN device */
 | 
					/* MS-originated GTP1-U packet, needs to be sent via TUN device */
 | 
				
			||||||
static int encaps_tun(struct pdp_t *pdp, void *pack, unsigned len)
 | 
					static int encaps_tun(struct pdp_t *pdp, void *pack, unsigned len)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct iphdr *iph = (struct iphdr *)pack;
 | 
						struct iphdr *iph = (struct iphdr *)pack;
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
	struct ip6_hdr *ip6h = (struct ip6_hdr *)pack;
 | 
						struct ip6_hdr *ip6h = (struct ip6_hdr *)pack;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
	struct tun_t *tun = (struct tun_t *)pdp->ipif;
 | 
						struct tun_t *tun = (struct tun_t *)pdp->ipif;
 | 
				
			||||||
	struct apn_ctx *apn = tun->priv;
 | 
						struct apn_ctx *apn = tun->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -692,11 +720,13 @@ static int encaps_tun(struct pdp_t *pdp, void *pack, unsigned len)
 | 
				
			|||||||
	LOGPPDP(LOGL_DEBUG, pdp, "Packet received: forwarding to tun\n");
 | 
						LOGPPDP(LOGL_DEBUG, pdp, "Packet received: forwarding to tun\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch (iph->version) {
 | 
						switch (iph->version) {
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
	case 6:
 | 
						case 6:
 | 
				
			||||||
		/* daddr: all-routers multicast addr */
 | 
							/* daddr: all-routers multicast addr */
 | 
				
			||||||
		if (IN6_ARE_ADDR_EQUAL(&ip6h->ip6_dst, &all_router_mcast_addr))
 | 
							if (IN6_ARE_ADDR_EQUAL(&ip6h->ip6_dst, &all_router_mcast_addr))
 | 
				
			||||||
			return handle_router_mcast(pdp->gsn, pdp, &apn->v6_lladdr, pack, len);
 | 
								return handle_router_mcast(pdp->gsn, pdp, &apn->v6_lladdr, pack, len);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
	case 4:
 | 
						case 4:
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -334,8 +334,10 @@ static struct cmd_node apn_node = {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static const struct value_string pdp_type_names[] = {
 | 
					static const struct value_string pdp_type_names[] = {
 | 
				
			||||||
	{ APN_TYPE_IPv4, "v4" },
 | 
						{ APN_TYPE_IPv4, "v4" },
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
	{ APN_TYPE_IPv6, "v6" },
 | 
						{ APN_TYPE_IPv6, "v6" },
 | 
				
			||||||
	{ APN_TYPE_IPv4v6, "v4v6" },
 | 
						{ APN_TYPE_IPv4v6, "v4v6" },
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
	{ 0, NULL }
 | 
						{ 0, NULL }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -345,13 +347,17 @@ static const struct value_string apn_gtpu_mode_names[] = {
 | 
				
			|||||||
	{ 0, NULL }
 | 
						{ 0, NULL }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
 | 
					#define V4V6V46_ARGS	"(v4|v6|v4v6)"
 | 
				
			||||||
#define V4V6V46_STRING	"IPv4(-only) PDP Type\n"	\
 | 
					#define V4V6V46_STRING	"IPv4(-only) PDP Type\n"	\
 | 
				
			||||||
			"IPv6(-only) PDP Type\n"	\
 | 
								"IPv6(-only) PDP Type\n"	\
 | 
				
			||||||
			"IPv4v6 (dual-stack) PDP Type\n"
 | 
								"IPv4v6 (dual-stack) PDP Type\n"
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#define V4V6V46_ARGS	"(v4)"
 | 
				
			||||||
 | 
					#define V4V6V46_STRING	"IPv4(-only) PDP Type\n"
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
DEFUN(cfg_apn_type_support, cfg_apn_type_support_cmd,
 | 
					DEFUN(cfg_apn_type_support, cfg_apn_type_support_cmd,
 | 
				
			||||||
	"type-support (v4|v6|v4v6)",
 | 
						"type-support " V4V6V46_ARGS,
 | 
				
			||||||
	"Enable support for PDP Type\n"
 | 
						"Enable support for PDP Type\n"
 | 
				
			||||||
	V4V6V46_STRING)
 | 
						V4V6V46_STRING)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -363,7 +369,7 @@ DEFUN(cfg_apn_type_support, cfg_apn_type_support_cmd,
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DEFUN(cfg_apn_no_type_support, cfg_apn_no_type_support_cmd,
 | 
					DEFUN(cfg_apn_no_type_support, cfg_apn_no_type_support_cmd,
 | 
				
			||||||
	"no type-support (v4|v6|v4v6)",
 | 
						"no type-support " V4V6V46_ARGS,
 | 
				
			||||||
	NO_STR "Disable support for PDP Type\n"
 | 
						NO_STR "Disable support for PDP Type\n"
 | 
				
			||||||
	V4V6V46_STRING)
 | 
						V4V6V46_STRING)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -480,6 +486,7 @@ DEFUN(cfg_apn_no_ip_ifconfig, cfg_apn_no_ip_ifconfig_cmd,
 | 
				
			|||||||
	return CMD_SUCCESS;
 | 
						return CMD_SUCCESS;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
DEFUN(cfg_apn_ipv6_prefix, cfg_apn_ipv6_prefix_cmd,
 | 
					DEFUN(cfg_apn_ipv6_prefix, cfg_apn_ipv6_prefix_cmd,
 | 
				
			||||||
	"ipv6 prefix (static|dynamic) X:X::X:X/M",
 | 
						"ipv6 prefix (static|dynamic) X:X::X:X/M",
 | 
				
			||||||
	IP6_STR PREFIX_STR "IPv6 Address/Prefix-Length\n")
 | 
						IP6_STR PREFIX_STR "IPv6 Address/Prefix-Length\n")
 | 
				
			||||||
@@ -512,6 +519,7 @@ DEFUN(cfg_apn_no_ipv6_ifconfig, cfg_apn_no_ipv6_ifconfig_cmd,
 | 
				
			|||||||
	memset(&apn->v6.cfg.ifconfig_prefix, 0, sizeof(apn->v6.cfg.ifconfig_prefix));
 | 
						memset(&apn->v6.cfg.ifconfig_prefix, 0, sizeof(apn->v6.cfg.ifconfig_prefix));
 | 
				
			||||||
	return CMD_SUCCESS;
 | 
						return CMD_SUCCESS;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define DNS_STRINGS "Configure DNS Server\n" "primary/secondary DNS\n" "IP address of DNS Sever\n"
 | 
					#define DNS_STRINGS "Configure DNS Server\n" "primary/secondary DNS\n" "IP address of DNS Sever\n"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -528,6 +536,7 @@ DEFUN(cfg_apn_ip_dns, cfg_apn_ip_dns_cmd,
 | 
				
			|||||||
	return CMD_SUCCESS;
 | 
						return CMD_SUCCESS;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
DEFUN(cfg_apn_ipv6_dns, cfg_apn_ipv6_dns_cmd,
 | 
					DEFUN(cfg_apn_ipv6_dns, cfg_apn_ipv6_dns_cmd,
 | 
				
			||||||
	"ipv6 dns <0-1> X:X::X:X",
 | 
						"ipv6 dns <0-1> X:X::X:X",
 | 
				
			||||||
	IP6_STR DNS_STRINGS)
 | 
						IP6_STR DNS_STRINGS)
 | 
				
			||||||
@@ -540,20 +549,27 @@ DEFUN(cfg_apn_ipv6_dns, cfg_apn_ipv6_dns_cmd,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	return CMD_SUCCESS;
 | 
						return CMD_SUCCESS;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
 | 
					#define IPV46_ARGS "(ip|ipv6)"
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#define IPV46_ARGS "(ip)"
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
DEFUN(cfg_apn_no_dns, cfg_apn_no_dns_cmd,
 | 
					DEFUN(cfg_apn_no_dns, cfg_apn_no_dns_cmd,
 | 
				
			||||||
	"no (ip|ipv6) dns <0-1>",
 | 
						"no " IPV46_ARGS " dns <0-1>",
 | 
				
			||||||
	NO_STR IP_STR IP6_STR "Disable DNS Server\n" "primary/secondary DNS\n")
 | 
						NO_STR IP_STR IP6_STR "Disable DNS Server\n" "primary/secondary DNS\n")
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct apn_ctx *apn = (struct apn_ctx *) vty->index;
 | 
						struct apn_ctx *apn = (struct apn_ctx *) vty->index;
 | 
				
			||||||
	struct in46_addr *a;
 | 
						struct in46_addr *a = NULL;
 | 
				
			||||||
	int idx = atoi(argv[1]);
 | 
						int idx = atoi(argv[1]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!strcmp(argv[0], "ip"))
 | 
						if (!strcmp(argv[0], "ip"))
 | 
				
			||||||
		a = &apn->v4.cfg.dns[idx];
 | 
							a = &apn->v4.cfg.dns[idx];
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		a = &apn->v6.cfg.dns[idx];
 | 
							a = &apn->v6.cfg.dns[idx];
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
	memset(a, 0, sizeof(*a));
 | 
						memset(a, 0, sizeof(*a));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return CMD_SUCCESS;
 | 
						return CMD_SUCCESS;
 | 
				
			||||||
@@ -656,6 +672,7 @@ static void config_write_apn(struct vty *vty, struct apn_ctx *apn)
 | 
				
			|||||||
	if (apn->v4.cfg.ifconfig_prefix.addr.len)
 | 
						if (apn->v4.cfg.ifconfig_prefix.addr.len)
 | 
				
			||||||
		vty_dump_prefix(vty, "  ip ifconfig", &apn->v4.cfg.ifconfig_prefix);
 | 
							vty_dump_prefix(vty, "  ip ifconfig", &apn->v4.cfg.ifconfig_prefix);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
	/* IPv6 prefixes + DNS */
 | 
						/* IPv6 prefixes + DNS */
 | 
				
			||||||
	if (apn->v6.cfg.static_prefix.addr.len)
 | 
						if (apn->v6.cfg.static_prefix.addr.len)
 | 
				
			||||||
		vty_dump_prefix(vty, "  ipv6 prefix static", &apn->v6.cfg.static_prefix);
 | 
							vty_dump_prefix(vty, "  ipv6 prefix static", &apn->v6.cfg.static_prefix);
 | 
				
			||||||
@@ -668,7 +685,7 @@ static void config_write_apn(struct vty *vty, struct apn_ctx *apn)
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	if (apn->v6.cfg.ifconfig_prefix.addr.len)
 | 
						if (apn->v6.cfg.ifconfig_prefix.addr.len)
 | 
				
			||||||
		vty_dump_prefix(vty, "  ipv6 ifconfig", &apn->v6.cfg.ifconfig_prefix);
 | 
							vty_dump_prefix(vty, "  ipv6 ifconfig", &apn->v6.cfg.ifconfig_prefix);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
	/* must be last */
 | 
						/* must be last */
 | 
				
			||||||
	vty_out(vty, "  %sshutdown%s", apn->cfg.shutdown ? "" : "no ", VTY_NEWLINE);
 | 
						vty_out(vty, "  %sshutdown%s", apn->cfg.shutdown ? "" : "no ", VTY_NEWLINE);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -704,8 +721,12 @@ static const char *print_gsnaddr(const struct ul16_t *in)
 | 
				
			|||||||
	struct in46_addr in46;
 | 
						struct in46_addr in46;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	in46.len = in->l;
 | 
						in46.len = in->l;
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
	OSMO_ASSERT(in->l <= sizeof(in46.v6));
 | 
						OSMO_ASSERT(in->l <= sizeof(in46.v6));
 | 
				
			||||||
	memcpy(&in46.v6, in->v, in->l);
 | 
					#else
 | 
				
			||||||
 | 
						OSMO_ASSERT(in->l <= sizeof(in46.v4));
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
						memcpy(&in46.v4, in->v, in->l);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return in46a_ntoa(&in46);
 | 
						return in46a_ntoa(&in46);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -781,7 +802,9 @@ static void ippool_show_pdp_contexts(struct vty *vty, struct ippool_t *pool)
 | 
				
			|||||||
static void apn_show_pdp_contexts(struct vty *vty, struct apn_ctx *apn)
 | 
					static void apn_show_pdp_contexts(struct vty *vty, struct apn_ctx *apn)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	ippool_show_pdp_contexts(vty, apn->v4.pool);
 | 
						ippool_show_pdp_contexts(vty, apn->v4.pool);
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
	ippool_show_pdp_contexts(vty, apn->v6.pool);
 | 
						ippool_show_pdp_contexts(vty, apn->v6.pool);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DEFUN(show_pdpctx, show_pdpctx_cmd,
 | 
					DEFUN(show_pdpctx, show_pdpctx_cmd,
 | 
				
			||||||
@@ -885,14 +908,16 @@ int ggsn_vty_init(void)
 | 
				
			|||||||
	install_element(APN_NODE, &cfg_apn_ipdown_script_cmd);
 | 
						install_element(APN_NODE, &cfg_apn_ipdown_script_cmd);
 | 
				
			||||||
	install_element(APN_NODE, &cfg_apn_no_ipdown_script_cmd);
 | 
						install_element(APN_NODE, &cfg_apn_no_ipdown_script_cmd);
 | 
				
			||||||
	install_element(APN_NODE, &cfg_apn_ip_prefix_cmd);
 | 
						install_element(APN_NODE, &cfg_apn_ip_prefix_cmd);
 | 
				
			||||||
	install_element(APN_NODE, &cfg_apn_ipv6_prefix_cmd);
 | 
					 | 
				
			||||||
	install_element(APN_NODE, &cfg_apn_ip_dns_cmd);
 | 
						install_element(APN_NODE, &cfg_apn_ip_dns_cmd);
 | 
				
			||||||
	install_element(APN_NODE, &cfg_apn_ipv6_dns_cmd);
 | 
					 | 
				
			||||||
	install_element(APN_NODE, &cfg_apn_no_dns_cmd);
 | 
						install_element(APN_NODE, &cfg_apn_no_dns_cmd);
 | 
				
			||||||
	install_element(APN_NODE, &cfg_apn_ip_ifconfig_cmd);
 | 
						install_element(APN_NODE, &cfg_apn_ip_ifconfig_cmd);
 | 
				
			||||||
	install_element(APN_NODE, &cfg_apn_no_ip_ifconfig_cmd);
 | 
						install_element(APN_NODE, &cfg_apn_no_ip_ifconfig_cmd);
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
 | 
						install_element(APN_NODE, &cfg_apn_ipv6_prefix_cmd);
 | 
				
			||||||
 | 
						install_element(APN_NODE, &cfg_apn_ipv6_dns_cmd);
 | 
				
			||||||
	install_element(APN_NODE, &cfg_apn_ipv6_ifconfig_cmd);
 | 
						install_element(APN_NODE, &cfg_apn_ipv6_ifconfig_cmd);
 | 
				
			||||||
	install_element(APN_NODE, &cfg_apn_no_ipv6_ifconfig_cmd);
 | 
						install_element(APN_NODE, &cfg_apn_no_ipv6_ifconfig_cmd);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
	install_element(APN_NODE, &cfg_apn_gpdu_seq_cmd);
 | 
						install_element(APN_NODE, &cfg_apn_gpdu_seq_cmd);
 | 
				
			||||||
	install_element(APN_NODE, &cfg_apn_no_gpdu_seq_cmd);
 | 
						install_element(APN_NODE, &cfg_apn_no_gpdu_seq_cmd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,9 +28,11 @@ int in46a_to_af(const struct in46_addr *in)
 | 
				
			|||||||
	switch (in->len) {
 | 
						switch (in->len) {
 | 
				
			||||||
	case 4:
 | 
						case 4:
 | 
				
			||||||
		return AF_INET;
 | 
							return AF_INET;
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
	case 8:
 | 
						case 8:
 | 
				
			||||||
	case 16:
 | 
						case 16:
 | 
				
			||||||
		return AF_INET6;
 | 
							return AF_INET6;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		OSMO_ASSERT(0);
 | 
							OSMO_ASSERT(0);
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
@@ -41,17 +43,21 @@ int in46a_to_af(const struct in46_addr *in)
 | 
				
			|||||||
int in46a_to_sas(struct sockaddr_storage *out, const struct in46_addr *in)
 | 
					int in46a_to_sas(struct sockaddr_storage *out, const struct in46_addr *in)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct sockaddr_in *sin = (struct sockaddr_in *)out;
 | 
						struct sockaddr_in *sin = (struct sockaddr_in *)out;
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)out;
 | 
						struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)out;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch (in->len) {
 | 
						switch (in->len) {
 | 
				
			||||||
	case 4:
 | 
						case 4:
 | 
				
			||||||
		sin->sin_family = AF_INET;
 | 
							sin->sin_family = AF_INET;
 | 
				
			||||||
		sin->sin_addr = in->v4;
 | 
							sin->sin_addr = in->v4;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
	case 16:
 | 
						case 16:
 | 
				
			||||||
		sin6->sin6_family = AF_INET6;
 | 
							sin6->sin6_family = AF_INET6;
 | 
				
			||||||
		sin6->sin6_addr = in->v6;
 | 
							sin6->sin6_addr = in->v6;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		OSMO_ASSERT(0);
 | 
							OSMO_ASSERT(0);
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
@@ -98,7 +104,7 @@ const char *in46p_ntoa(const struct in46_prefix *in46p)
 | 
				
			|||||||
 *  \returns 1 in case they are equal; 0 otherwise */
 | 
					 *  \returns 1 in case they are equal; 0 otherwise */
 | 
				
			||||||
int in46a_equal(const struct in46_addr *a, const struct in46_addr *b)
 | 
					int in46a_equal(const struct in46_addr *a, const struct in46_addr *b)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (a->len == b->len && !memcmp(&a->v6, &b->v6, a->len))
 | 
						if (a->len == b->len && !memcmp(&a->v4, &b->v4, a->len))
 | 
				
			||||||
		return 1;
 | 
							return 1;
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
@@ -115,12 +121,13 @@ int in46a_prefix_equal(const struct in46_addr *a, const struct in46_addr *b)
 | 
				
			|||||||
	else
 | 
						else
 | 
				
			||||||
		len = a->len;
 | 
							len = a->len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!memcmp(&a->v6, &b->v6, len))
 | 
						if (!memcmp(&a->v4, &b->v4, len))
 | 
				
			||||||
		return 1;
 | 
							return 1;
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
/*! Match if IPv6 addr1 + addr2 are within same \a mask */
 | 
					/*! Match if IPv6 addr1 + addr2 are within same \a mask */
 | 
				
			||||||
static int ipv6_within_mask(const struct in6_addr *addr1, const struct in6_addr *addr2,
 | 
					static int ipv6_within_mask(const struct in6_addr *addr1, const struct in6_addr *addr2,
 | 
				
			||||||
			    const struct in6_addr *mask)
 | 
								    const struct in6_addr *mask)
 | 
				
			||||||
@@ -167,6 +174,7 @@ static void create_ipv6_netmask(struct in6_addr *netmask, int prefixlen)
 | 
				
			|||||||
		*p_netmask = htonl(0xFFFFFFFF << (32 - prefixlen));
 | 
							*p_netmask = htonl(0xFFFFFFFF << (32 - prefixlen));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*! Determine if given \a addr is within given \a net + \a prefixlen
 | 
					/*! Determine if given \a addr is within given \a net + \a prefixlen
 | 
				
			||||||
 *  Builds the netmask from \a net + \a prefixlen and matches it to \a addr
 | 
					 *  Builds the netmask from \a net + \a prefixlen and matches it to \a addr
 | 
				
			||||||
@@ -174,7 +182,9 @@ static void create_ipv6_netmask(struct in6_addr *netmask, int prefixlen)
 | 
				
			|||||||
int in46a_within_mask(const struct in46_addr *addr, const struct in46_addr *net, size_t prefixlen)
 | 
					int in46a_within_mask(const struct in46_addr *addr, const struct in46_addr *net, size_t prefixlen)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct in_addr netmask;
 | 
						struct in_addr netmask;
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
	struct in6_addr netmask6;
 | 
						struct in6_addr netmask6;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (addr->len != net->len)
 | 
						if (addr->len != net->len)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
@@ -186,9 +196,11 @@ int in46a_within_mask(const struct in46_addr *addr, const struct in46_addr *net,
 | 
				
			|||||||
			return 1;
 | 
								return 1;
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
			return 0;
 | 
								return 0;
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
	case 16:
 | 
						case 16:
 | 
				
			||||||
		create_ipv6_netmask(&netmask6, prefixlen);
 | 
							create_ipv6_netmask(&netmask6, prefixlen);
 | 
				
			||||||
		return ipv6_within_mask(&addr->v6, &net->v6, &netmask6);
 | 
							return ipv6_within_mask(&addr->v6, &net->v6, &netmask6);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		OSMO_ASSERT(0);
 | 
							OSMO_ASSERT(0);
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
@@ -210,6 +222,7 @@ static unsigned int ipv4_netmasklen(const struct in_addr *netmask)
 | 
				
			|||||||
	return prefix;
 | 
						return prefix;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
static unsigned int ipv6_netmasklen(const struct in6_addr *netmask)
 | 
					static unsigned int ipv6_netmasklen(const struct in6_addr *netmask)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	#if defined(__linux__)
 | 
						#if defined(__linux__)
 | 
				
			||||||
@@ -235,6 +248,7 @@ static unsigned int ipv6_netmasklen(const struct in6_addr *netmask)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	return prefix;
 | 
						return prefix;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*! Convert netmask to prefix length representation
 | 
					/*! Convert netmask to prefix length representation
 | 
				
			||||||
 *  \param[in] netmask in46_addr containing a netmask (consecutive list of 1-bit followed by consecutive list of 0-bit)
 | 
					 *  \param[in] netmask in46_addr containing a netmask (consecutive list of 1-bit followed by consecutive list of 0-bit)
 | 
				
			||||||
@@ -245,8 +259,10 @@ unsigned int in46a_netmasklen(const struct in46_addr *netmask)
 | 
				
			|||||||
	switch (netmask->len) {
 | 
						switch (netmask->len) {
 | 
				
			||||||
	case 4:
 | 
						case 4:
 | 
				
			||||||
		return ipv4_netmasklen(&netmask->v4);
 | 
							return ipv4_netmasklen(&netmask->v4);
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
	case 16:
 | 
						case 16:
 | 
				
			||||||
		return ipv6_netmasklen(&netmask->v6);
 | 
							return ipv6_netmasklen(&netmask->v6);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		OSMO_ASSERT(0);
 | 
							OSMO_ASSERT(0);
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
@@ -264,6 +280,7 @@ int in46a_to_eua(const struct in46_addr *src, struct ul66_t *eua)
 | 
				
			|||||||
		eua->v[1] = PDP_EUA_TYPE_v4;
 | 
							eua->v[1] = PDP_EUA_TYPE_v4;
 | 
				
			||||||
		memcpy(&eua->v[2], &src->v4, 4);	/* Copy a 4 byte address */
 | 
							memcpy(&eua->v[2], &src->v4, 4);	/* Copy a 4 byte address */
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
	case 8:
 | 
						case 8:
 | 
				
			||||||
	case 16:
 | 
						case 16:
 | 
				
			||||||
		eua->l = 18;
 | 
							eua->l = 18;
 | 
				
			||||||
@@ -271,6 +288,7 @@ int in46a_to_eua(const struct in46_addr *src, struct ul66_t *eua)
 | 
				
			|||||||
		eua->v[1] = PDP_EUA_TYPE_v6;
 | 
							eua->v[1] = PDP_EUA_TYPE_v6;
 | 
				
			||||||
		memcpy(&eua->v[2], &src->v6, 16);	/* Copy a 16 byte address */
 | 
							memcpy(&eua->v[2], &src->v6, 16);	/* Copy a 16 byte address */
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		OSMO_ASSERT(0);
 | 
							OSMO_ASSERT(0);
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
@@ -296,6 +314,7 @@ int in46a_from_eua(const struct ul66_t *eua, struct in46_addr *dst)
 | 
				
			|||||||
		else
 | 
							else
 | 
				
			||||||
			dst->v4.s_addr = 0;
 | 
								dst->v4.s_addr = 0;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
	case PDP_EUA_TYPE_v6:
 | 
						case PDP_EUA_TYPE_v6:
 | 
				
			||||||
		dst->len = 16;
 | 
							dst->len = 16;
 | 
				
			||||||
		if (eua->l >= 18)
 | 
							if (eua->l >= 18)
 | 
				
			||||||
@@ -303,6 +322,7 @@ int in46a_from_eua(const struct ul66_t *eua, struct in46_addr *dst)
 | 
				
			|||||||
		else
 | 
							else
 | 
				
			||||||
			memset(&dst->v6, 0, 16);
 | 
								memset(&dst->v6, 0, 16);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,13 +4,17 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "../gtp/pdp.h"
 | 
					#include "../gtp/pdp.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "config.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* a simple wrapper around an in6_addr to also contain the length of the address,
 | 
					/* a simple wrapper around an in6_addr to also contain the length of the address,
 | 
				
			||||||
 * thereby implicitly indicating the address family of the address */
 | 
					 * thereby implicitly indicating the address family of the address */
 | 
				
			||||||
struct in46_addr {
 | 
					struct in46_addr {
 | 
				
			||||||
	uint8_t len;
 | 
						uint8_t len;
 | 
				
			||||||
	union {
 | 
						union {
 | 
				
			||||||
		struct in_addr v4;
 | 
							struct in_addr v4;
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
		struct in6_addr v6;
 | 
							struct in6_addr v6;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										20
									
								
								lib/ippool.c
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								lib/ippool.c
									
									
									
									
									
								
							@@ -22,6 +22,8 @@
 | 
				
			|||||||
#include "ippool.h"
 | 
					#include "ippool.h"
 | 
				
			||||||
#include "lookup.h"
 | 
					#include "lookup.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "config.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int ippool_printaddr(struct ippool_t *this)
 | 
					int ippool_printaddr(struct ippool_t *this)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	unsigned int n;
 | 
						unsigned int n;
 | 
				
			||||||
@@ -96,18 +98,24 @@ static unsigned long int ippool_hash4(struct in_addr *addr)
 | 
				
			|||||||
	return lookup((unsigned char *)&addr->s_addr, sizeof(addr->s_addr), 0);
 | 
						return lookup((unsigned char *)&addr->s_addr, sizeof(addr->s_addr), 0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
static unsigned long int ippool_hash6(struct in6_addr *addr, unsigned int len)
 | 
					static unsigned long int ippool_hash6(struct in6_addr *addr, unsigned int len)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	/* TODO: Review hash spread for IPv6 */
 | 
						/* TODO: Review hash spread for IPv6 */
 | 
				
			||||||
	return lookup((unsigned char *)addr->s6_addr, len, 0);
 | 
						return lookup((unsigned char *)addr->s6_addr, len, 0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
unsigned long int ippool_hash(struct in46_addr *addr)
 | 
					unsigned long int ippool_hash(struct in46_addr *addr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
	if (addr->len == 4)
 | 
						if (addr->len == 4)
 | 
				
			||||||
		return ippool_hash4(&addr->v4);
 | 
							return ippool_hash4(&addr->v4);
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		return ippool_hash6(&addr->v6, addr->len);
 | 
							return ippool_hash6(&addr->v6, addr->len);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
						return ippool_hash4(&addr->v4);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Get IP address and mask */
 | 
					/* Get IP address and mask */
 | 
				
			||||||
@@ -148,11 +156,14 @@ int ippool_aton(struct in46_addr *addr, size_t *prefixlen, const char *pool_in,
 | 
				
			|||||||
		*prefixlen = 32;
 | 
							*prefixlen = 32;
 | 
				
			||||||
		addr->len = sizeof(struct in_addr);
 | 
							addr->len = sizeof(struct in_addr);
 | 
				
			||||||
		addr->v4 = ((struct sockaddr_in*)ai->ai_addr)->sin_addr;
 | 
							addr->v4 = ((struct sockaddr_in*)ai->ai_addr)->sin_addr;
 | 
				
			||||||
	} else {
 | 
						}
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
		*prefixlen = 128;
 | 
							*prefixlen = 128;
 | 
				
			||||||
		addr->len = sizeof(struct in6_addr);
 | 
							addr->len = sizeof(struct in6_addr);
 | 
				
			||||||
		addr->v6 = ((struct sockaddr_in6*)ai->ai_addr)->sin6_addr;
 | 
							addr->v6 = ((struct sockaddr_in6*)ai->ai_addr)->sin6_addr;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
	freeaddrinfo(ai);
 | 
						freeaddrinfo(ai);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* parse prefixlen */
 | 
						/* parse prefixlen */
 | 
				
			||||||
@@ -177,7 +188,7 @@ int ippool_aton(struct in46_addr *addr, size_t *prefixlen, const char *pool_in,
 | 
				
			|||||||
void in46a_inc(struct in46_addr *addr)
 | 
					void in46a_inc(struct in46_addr *addr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	size_t addrlen;
 | 
						size_t addrlen;
 | 
				
			||||||
	uint8_t *a = (uint8_t *)&addr->v6;
 | 
						uint8_t *a = (uint8_t *)&addr->v4;
 | 
				
			||||||
	for (addrlen = addr->len; addrlen > 0; addrlen--) {
 | 
						for (addrlen = addr->len; addrlen > 0; addrlen--) {
 | 
				
			||||||
		if (++a[addrlen-1])
 | 
							if (++a[addrlen-1])
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
@@ -215,11 +226,12 @@ int ippool_new(struct ippool_t **this, const struct in46_prefix *dyn, const stru
 | 
				
			|||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		addr = dyn->addr;
 | 
							addr = dyn->addr;
 | 
				
			||||||
		addrprefixlen = dyn->prefixlen;
 | 
							addrprefixlen = dyn->prefixlen;
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
		/* we want to work with /64 prefixes, i.e. allocate /64 prefixes rather
 | 
							/* we want to work with /64 prefixes, i.e. allocate /64 prefixes rather
 | 
				
			||||||
		 * than /128 (single IPv6 addresses) */
 | 
							 * than /128 (single IPv6 addresses) */
 | 
				
			||||||
		if (addr.len == sizeof(struct in6_addr))
 | 
							if (addr.len == sizeof(struct in6_addr))
 | 
				
			||||||
			addr.len = 64/8;
 | 
								addr.len = 64/8;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
		dynsize = (1 << (addr.len*8 - addrprefixlen));
 | 
							dynsize = (1 << (addr.len*8 - addrprefixlen));
 | 
				
			||||||
		if (flags & IPPOOL_NONETWORK)	/* Exclude network address from pool */
 | 
							if (flags & IPPOOL_NONETWORK)	/* Exclude network address from pool */
 | 
				
			||||||
			dynsize--;
 | 
								dynsize--;
 | 
				
			||||||
@@ -404,8 +416,10 @@ int ippool_newip(struct ippool_t *this, struct ippoolm_t **member,
 | 
				
			|||||||
	if (addr) {
 | 
						if (addr) {
 | 
				
			||||||
		if (addr->len == 4 && addr->v4.s_addr)
 | 
							if (addr->len == 4 && addr->v4.s_addr)
 | 
				
			||||||
			specified = 1;
 | 
								specified = 1;
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
		if (addr->len == 16 && !IN6_IS_ADDR_UNSPECIFIED(&addr->v6))
 | 
							if (addr->len == 16 && !IN6_IS_ADDR_UNSPECIFIED(&addr->v6))
 | 
				
			||||||
			specified = 1;
 | 
								specified = 1;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* First check to see if this type of address is allowed */
 | 
						/* First check to see if this type of address is allowed */
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										13
									
								
								lib/tun.c
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								lib/tun.c
									
									
									
									
									
								
							@@ -62,7 +62,9 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#if defined(__linux__)
 | 
					#if defined(__linux__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
#include <linux/ipv6.h>
 | 
					#include <linux/ipv6.h>
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int tun_nlattr(struct nlmsghdr *n, int nsize, int type, void *d, int dlen)
 | 
					static int tun_nlattr(struct nlmsghdr *n, int nsize, int type, void *d, int dlen)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -197,6 +199,7 @@ static int tun_setaddr4(struct tun_t *this, struct in_addr *addr,
 | 
				
			|||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
static int tun_setaddr6(struct tun_t *this, struct in6_addr *addr, struct in6_addr *dstaddr,
 | 
					static int tun_setaddr6(struct tun_t *this, struct in6_addr *addr, struct in6_addr *dstaddr,
 | 
				
			||||||
			size_t prefixlen)
 | 
								size_t prefixlen)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -280,6 +283,7 @@ static int tun_setaddr6(struct tun_t *this, struct in6_addr *addr, struct in6_ad
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					#endif /* BUILD_IPv6 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int tun_setaddr(struct tun_t *this, struct in46_addr *addr, struct in46_addr *dstaddr, size_t prefixlen)
 | 
					int tun_setaddr(struct tun_t *this, struct in46_addr *addr, struct in46_addr *dstaddr, size_t prefixlen)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -288,8 +292,10 @@ int tun_setaddr(struct tun_t *this, struct in46_addr *addr, struct in46_addr *ds
 | 
				
			|||||||
	case 4:
 | 
						case 4:
 | 
				
			||||||
		netmask.s_addr = htonl(0xffffffff << (32 - prefixlen));
 | 
							netmask.s_addr = htonl(0xffffffff << (32 - prefixlen));
 | 
				
			||||||
		return tun_setaddr4(this, &addr->v4, dstaddr ? &dstaddr->v4 : NULL, &netmask);
 | 
							return tun_setaddr4(this, &addr->v4, dstaddr ? &dstaddr->v4 : NULL, &netmask);
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
	case 16:
 | 
						case 16:
 | 
				
			||||||
		return tun_setaddr6(this, &addr->v6, dstaddr ? &dstaddr->v6 : NULL, prefixlen);
 | 
							return tun_setaddr6(this, &addr->v6, dstaddr ? &dstaddr->v6 : NULL, prefixlen);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -762,11 +768,13 @@ int tun_runscript(struct tun_t *tun, char *script)
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
int netdev_ip_local_get(const char *devname, struct in46_prefix *prefix_list, size_t prefix_size, int flags)
 | 
					int netdev_ip_local_get(const char *devname, struct in46_prefix *prefix_list, size_t prefix_size, int flags)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
	static const uint8_t ll_prefix[] = { 0xfe,0x80, 0,0, 0,0, 0,0 };
 | 
						static const uint8_t ll_prefix[] = { 0xfe,0x80, 0,0, 0,0, 0,0 };
 | 
				
			||||||
 | 
						bool is_ipv6_ll;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
	struct ifaddrs *ifaddr, *ifa;
 | 
						struct ifaddrs *ifaddr, *ifa;
 | 
				
			||||||
	struct in46_addr netmask;
 | 
						struct in46_addr netmask;
 | 
				
			||||||
	size_t count = 0;
 | 
						size_t count = 0;
 | 
				
			||||||
	bool is_ipv6_ll;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (getifaddrs(&ifaddr) == -1) {
 | 
						if (getifaddrs(&ifaddr) == -1) {
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
@@ -792,7 +800,7 @@ int netdev_ip_local_get(const char *devname, struct in46_prefix *prefix_list, si
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			count++;
 | 
								count++;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
		if (ifa->ifa_addr->sa_family == AF_INET6 && (flags & IP_TYPE_IPv6)) {
 | 
							if (ifa->ifa_addr->sa_family == AF_INET6 && (flags & IP_TYPE_IPv6)) {
 | 
				
			||||||
			struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) ifa->ifa_addr;
 | 
								struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) ifa->ifa_addr;
 | 
				
			||||||
			struct sockaddr_in6 *netmask6 = (struct sockaddr_in6 *) ifa->ifa_netmask;
 | 
								struct sockaddr_in6 *netmask6 = (struct sockaddr_in6 *) ifa->ifa_netmask;
 | 
				
			||||||
@@ -812,6 +820,7 @@ int netdev_ip_local_get(const char *devname, struct in46_prefix *prefix_list, si
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			count++;
 | 
								count++;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	freeifaddrs(ifaddr);
 | 
						freeifaddrs(ifaddr);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -936,10 +936,12 @@ static int process_options(int argc, char **argv)
 | 
				
			|||||||
		options.tx_gpdu_seq = 1;
 | 
							options.tx_gpdu_seq = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* PDP Type */
 | 
						/* PDP Type */
 | 
				
			||||||
	if (!strcmp(args_info.pdp_type_arg, "v6"))
 | 
						if (!strcmp(args_info.pdp_type_arg, "v4"))
 | 
				
			||||||
		options.pdp_type = PDP_EUA_TYPE_v6;
 | 
					 | 
				
			||||||
	else if (!strcmp(args_info.pdp_type_arg, "v4"))
 | 
					 | 
				
			||||||
		options.pdp_type = PDP_EUA_TYPE_v4;
 | 
							options.pdp_type = PDP_EUA_TYPE_v4;
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
 | 
						else if if (!strcmp(args_info.pdp_type_arg, "v6"))
 | 
				
			||||||
 | 
							options.pdp_type = PDP_EUA_TYPE_v6;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
	else {
 | 
						else {
 | 
				
			||||||
		SYS_ERR(DSGSN, LOGL_ERROR, 0, "Unsupported/unknown PDP Type '%s'\n",
 | 
							SYS_ERR(DSGSN, LOGL_ERROR, 0, "Unsupported/unknown PDP Type '%s'\n",
 | 
				
			||||||
			args_info.pdp_type_arg);
 | 
								args_info.pdp_type_arg);
 | 
				
			||||||
@@ -955,6 +957,7 @@ static int process_options(int argc, char **argv)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
/* read a single value from a /procc file, up to 255 bytes, callee-allocated */
 | 
					/* read a single value from a /procc file, up to 255 bytes, callee-allocated */
 | 
				
			||||||
static char *proc_read(const char *path)
 | 
					static char *proc_read(const char *path)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -989,6 +992,7 @@ static char *proc_ipv6_conf_read(const char *dev, const char *file)
 | 
				
			|||||||
	snprintf(path, sizeof(path), fmt, dev, file);
 | 
						snprintf(path, sizeof(path), fmt, dev, file);
 | 
				
			||||||
	return proc_read(path);
 | 
						return proc_read(path);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static char *print_ipprot(int t)
 | 
					static char *print_ipprot(int t)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -1323,8 +1327,10 @@ static int delete_context(struct pdp_t *pdp)
 | 
				
			|||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
/* Link-Local address  prefix fe80::/64 */
 | 
					/* Link-Local address  prefix fe80::/64 */
 | 
				
			||||||
static const uint8_t ll_prefix[] = { 0xfe,0x80, 0,0, 0,0, 0,0 };
 | 
					static const uint8_t ll_prefix[] = { 0xfe,0x80, 0,0, 0,0, 0,0 };
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Callback for receiving messages from tun */
 | 
					/* Callback for receiving messages from tun */
 | 
				
			||||||
static int cb_tun_ind(struct tun_t *tun, void *pack, unsigned len)
 | 
					static int cb_tun_ind(struct tun_t *tun, void *pack, unsigned len)
 | 
				
			||||||
@@ -1332,7 +1338,9 @@ static int cb_tun_ind(struct tun_t *tun, void *pack, unsigned len)
 | 
				
			|||||||
	struct iphash_t *ipm;
 | 
						struct iphash_t *ipm;
 | 
				
			||||||
	struct in46_addr src;
 | 
						struct in46_addr src;
 | 
				
			||||||
	struct iphdr *iph = (struct iphdr *)pack;
 | 
						struct iphdr *iph = (struct iphdr *)pack;
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
	struct ip6_hdr *ip6h = (struct ip6_hdr *)pack;
 | 
						struct ip6_hdr *ip6h = (struct ip6_hdr *)pack;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (iph->version == 4) {
 | 
						if (iph->version == 4) {
 | 
				
			||||||
		if (len < sizeof(*iph) || len < 4*iph->ihl) {
 | 
							if (len < sizeof(*iph) || len < 4*iph->ihl) {
 | 
				
			||||||
@@ -1341,6 +1349,7 @@ static int cb_tun_ind(struct tun_t *tun, void *pack, unsigned len)
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		src.len = 4;
 | 
							src.len = 4;
 | 
				
			||||||
		src.v4.s_addr = iph->saddr;
 | 
							src.v4.s_addr = iph->saddr;
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
	} else if (iph->version == 6) {
 | 
						} else if (iph->version == 6) {
 | 
				
			||||||
		/* We only have a single entry in the hash table, and it consists of the link-local
 | 
							/* We only have a single entry in the hash table, and it consists of the link-local
 | 
				
			||||||
		 * address "fe80::prefix".  So we need to make sure to convert non-link-local source
 | 
							 * address "fe80::prefix".  So we need to make sure to convert non-link-local source
 | 
				
			||||||
@@ -1355,6 +1364,7 @@ static int cb_tun_ind(struct tun_t *tun, void *pack, unsigned len)
 | 
				
			|||||||
			memcpy(&src.v6.s6_addr[0], ll_prefix, sizeof(ll_prefix));
 | 
								memcpy(&src.v6.s6_addr[0], ll_prefix, sizeof(ll_prefix));
 | 
				
			||||||
			memcpy(&src.v6.s6_addr[sizeof(ll_prefix)], ip6h->ip6_src.s6_addr, 16-sizeof(ll_prefix));
 | 
								memcpy(&src.v6.s6_addr[sizeof(ll_prefix)], ip6h->ip6_src.s6_addr, 16-sizeof(ll_prefix));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		printf("Dropping packet with invalid IP version %u\n", iph->version);
 | 
							printf("Dropping packet with invalid IP version %u\n", iph->version);
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
@@ -1416,6 +1426,7 @@ static int create_pdp_conf(struct pdp_t *pdp, void *cbp, int cause)
 | 
				
			|||||||
	       in46a_ntoa(&addr));
 | 
						       in46a_ntoa(&addr));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch (addr.len) {
 | 
						switch (addr.len) {
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
	case 16: /* IPv6 */
 | 
						case 16: /* IPv6 */
 | 
				
			||||||
		/* we have to enable the kernel to perform stateless autoconfiguration,
 | 
							/* we have to enable the kernel to perform stateless autoconfiguration,
 | 
				
			||||||
		 * i.e. send a router solicitation using the lover 64bits of the allocated
 | 
							 * i.e. send a router solicitation using the lover 64bits of the allocated
 | 
				
			||||||
@@ -1423,6 +1434,7 @@ static int create_pdp_conf(struct pdp_t *pdp, void *cbp, int cause)
 | 
				
			|||||||
		memcpy(addr.v6.s6_addr, ll_prefix, sizeof(ll_prefix));
 | 
							memcpy(addr.v6.s6_addr, ll_prefix, sizeof(ll_prefix));
 | 
				
			||||||
		printf("Derived IPv6 link-local address: %s\n", in46a_ntoa(&addr));
 | 
							printf("Derived IPv6 link-local address: %s\n", in46a_ntoa(&addr));
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
	case 4: /* IPv4 */
 | 
						case 4: /* IPv4 */
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -1443,6 +1455,7 @@ static int create_pdp_conf(struct pdp_t *pdp, void *cbp, int cause)
 | 
				
			|||||||
			tun_runscript(tun, options.ipup);
 | 
								tun_runscript(tun, options.ipup);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
	/* now that ip-up has been executed, check if we are configured to
 | 
						/* now that ip-up has been executed, check if we are configured to
 | 
				
			||||||
	 * accept router advertisements */
 | 
						 * accept router advertisements */
 | 
				
			||||||
	if (options.createif && options.pdp_type == PDP_EUA_TYPE_v6) {
 | 
						if (options.createif && options.pdp_type == PDP_EUA_TYPE_v6) {
 | 
				
			||||||
@@ -1463,6 +1476,7 @@ static int create_pdp_conf(struct pdp_t *pdp, void *cbp, int cause)
 | 
				
			|||||||
		free(accept_ra);
 | 
							free(accept_ra);
 | 
				
			||||||
		free(forwarding);
 | 
							free(forwarding);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ipset((struct iphash_t *)pdp->peer, &addr);
 | 
						ipset((struct iphash_t *)pdp->peer, &addr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,29 +20,37 @@ static const struct in46_addr g_ia4 = {
 | 
				
			|||||||
	.v4.s_addr = 0x0d0c0b0a,
 | 
						.v4.s_addr = 0x0d0c0b0a,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
static const struct in46_addr g_ia6 = {
 | 
					static const struct in46_addr g_ia6 = {
 | 
				
			||||||
	.len = 16,
 | 
						.len = 16,
 | 
				
			||||||
	.v6.s6_addr = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 },
 | 
						.v6.s6_addr = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 },
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void test_in46a_to_af(void)
 | 
					static void test_in46a_to_af(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
	struct in46_addr ia;
 | 
						struct in46_addr ia;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	printf("Testing in46a_to_af()\n");
 | 
						printf("Testing in46a_to_af()\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	OSMO_ASSERT(in46a_to_af(&g_ia4) == AF_INET);
 | 
						OSMO_ASSERT(in46a_to_af(&g_ia4) == AF_INET);
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
	OSMO_ASSERT(in46a_to_af(&g_ia6) == AF_INET6);
 | 
						OSMO_ASSERT(in46a_to_af(&g_ia6) == AF_INET6);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ia.len = 8;
 | 
						ia.len = 8;
 | 
				
			||||||
	OSMO_ASSERT(in46a_to_af(&ia) == AF_INET6);
 | 
						OSMO_ASSERT(in46a_to_af(&ia) == AF_INET6);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void test_in46a_to_sas(void)
 | 
					static void test_in46a_to_sas(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct sockaddr_storage ss;
 | 
						struct sockaddr_storage ss;
 | 
				
			||||||
	struct sockaddr_in *sin = (struct sockaddr_in *) &ss;
 | 
						struct sockaddr_in *sin = (struct sockaddr_in *) &ss;
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) &ss;
 | 
						struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) &ss;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	printf("Testing in46a_to_sas()\n");
 | 
						printf("Testing in46a_to_sas()\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -51,10 +59,12 @@ static void test_in46a_to_sas(void)
 | 
				
			|||||||
	OSMO_ASSERT(sin->sin_family == AF_INET);
 | 
						OSMO_ASSERT(sin->sin_family == AF_INET);
 | 
				
			||||||
	OSMO_ASSERT(sin->sin_addr.s_addr == g_ia4.v4.s_addr);
 | 
						OSMO_ASSERT(sin->sin_addr.s_addr == g_ia4.v4.s_addr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
	memset(&ss, 0, sizeof(ss));
 | 
						memset(&ss, 0, sizeof(ss));
 | 
				
			||||||
	OSMO_ASSERT(in46a_to_sas(&ss, &g_ia6) == 0);
 | 
						OSMO_ASSERT(in46a_to_sas(&ss, &g_ia6) == 0);
 | 
				
			||||||
	OSMO_ASSERT(sin6->sin6_family == AF_INET6);
 | 
						OSMO_ASSERT(sin6->sin6_family == AF_INET6);
 | 
				
			||||||
	OSMO_ASSERT(!memcmp(&sin6->sin6_addr, &g_ia6.v6, sizeof(sin6->sin6_addr)));
 | 
						OSMO_ASSERT(!memcmp(&sin6->sin6_addr, &g_ia6.v6, sizeof(sin6->sin6_addr)));
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void test_in46a_ntop(void)
 | 
					static void test_in46a_ntop(void)
 | 
				
			||||||
@@ -79,10 +89,11 @@ static void test_in46a_ntop(void)
 | 
				
			|||||||
	res = in46a_ntop(&ia, buf, sizeof(buf));
 | 
						res = in46a_ntop(&ia, buf, sizeof(buf));
 | 
				
			||||||
	OSMO_ASSERT(res && !strcmp(res, "1.2.3.4"));
 | 
						OSMO_ASSERT(res && !strcmp(res, "1.2.3.4"));
 | 
				
			||||||
	printf("res = %s\n", res);
 | 
						printf("res = %s\n", res);
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
	res = in46a_ntop(&g_ia6, buf, sizeof(buf));
 | 
						res = in46a_ntop(&g_ia6, buf, sizeof(buf));
 | 
				
			||||||
	OSMO_ASSERT(res && !strcmp(res, "102:304:506:708:90a:b0c:d0e:f10"));
 | 
						OSMO_ASSERT(res && !strcmp(res, "102:304:506:708:90a:b0c:d0e:f10"));
 | 
				
			||||||
	printf("res = %s\n", res);
 | 
						printf("res = %s\n", res);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void test_in46p_ntoa(void)
 | 
					static void test_in46p_ntoa(void)
 | 
				
			||||||
@@ -108,11 +119,12 @@ static void test_in46a_equal(void)
 | 
				
			|||||||
	b.v4.s_addr = g_ia4.v4.s_addr;
 | 
						b.v4.s_addr = g_ia4.v4.s_addr;
 | 
				
			||||||
	OSMO_ASSERT(in46a_equal(&g_ia4, &b));
 | 
						OSMO_ASSERT(in46a_equal(&g_ia4, &b));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
	memset(&b, 0xff, sizeof(b));
 | 
						memset(&b, 0xff, sizeof(b));
 | 
				
			||||||
	b.len = g_ia6.len;
 | 
						b.len = g_ia6.len;
 | 
				
			||||||
	b.v6 = g_ia6.v6;
 | 
						b.v6 = g_ia6.v6;
 | 
				
			||||||
	OSMO_ASSERT(in46a_equal(&g_ia6, &b));
 | 
						OSMO_ASSERT(in46a_equal(&g_ia6, &b));
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -155,10 +167,12 @@ static void test_in46a_within_mask(void)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static void test_in46a_to_eua(void)
 | 
					static void test_in46a_to_eua(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
	const struct in46_addr ia_v6_8 = {
 | 
						const struct in46_addr ia_v6_8 = {
 | 
				
			||||||
		.len = 8,
 | 
							.len = 8,
 | 
				
			||||||
		.v6.s6_addr = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 },
 | 
							.v6.s6_addr = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 },
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
	struct ul66_t eua;
 | 
						struct ul66_t eua;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	printf("testing in46a_to_eua()\n");
 | 
						printf("testing in46a_to_eua()\n");
 | 
				
			||||||
@@ -174,6 +188,7 @@ static void test_in46a_to_eua(void)
 | 
				
			|||||||
	OSMO_ASSERT(eua.v[1] == PDP_EUA_TYPE_v4);
 | 
						OSMO_ASSERT(eua.v[1] == PDP_EUA_TYPE_v4);
 | 
				
			||||||
	OSMO_ASSERT(osmo_load32le(&eua.v[2]) == g_ia4.v4.s_addr);
 | 
						OSMO_ASSERT(osmo_load32le(&eua.v[2]) == g_ia4.v4.s_addr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
	/* IPv6 address */
 | 
						/* IPv6 address */
 | 
				
			||||||
	OSMO_ASSERT(in46a_to_eua(&g_ia6, &eua) == 0);
 | 
						OSMO_ASSERT(in46a_to_eua(&g_ia6, &eua) == 0);
 | 
				
			||||||
	OSMO_ASSERT(eua.v[0] == PDP_EUA_ORG_IETF);
 | 
						OSMO_ASSERT(eua.v[0] == PDP_EUA_ORG_IETF);
 | 
				
			||||||
@@ -185,6 +200,7 @@ static void test_in46a_to_eua(void)
 | 
				
			|||||||
	OSMO_ASSERT(eua.v[0] == PDP_EUA_ORG_IETF);
 | 
						OSMO_ASSERT(eua.v[0] == PDP_EUA_ORG_IETF);
 | 
				
			||||||
	OSMO_ASSERT(eua.v[1] == PDP_EUA_TYPE_v6);
 | 
						OSMO_ASSERT(eua.v[1] == PDP_EUA_TYPE_v6);
 | 
				
			||||||
	OSMO_ASSERT(!memcmp(&eua.v[2], &ia_v6_8.v6, 16));
 | 
						OSMO_ASSERT(!memcmp(&eua.v[2], &ia_v6_8.v6, 16));
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void test_in46a_from_eua(void)
 | 
					static void test_in46a_from_eua(void)
 | 
				
			||||||
@@ -193,10 +209,11 @@ static void test_in46a_from_eua(void)
 | 
				
			|||||||
	struct ul66_t eua;
 | 
						struct ul66_t eua;
 | 
				
			||||||
	const uint8_t v4_unspec[] = { PDP_EUA_ORG_IETF, PDP_EUA_TYPE_v4 };
 | 
						const uint8_t v4_unspec[] = { PDP_EUA_ORG_IETF, PDP_EUA_TYPE_v4 };
 | 
				
			||||||
	const uint8_t v4_spec[] = { PDP_EUA_ORG_IETF, PDP_EUA_TYPE_v4, 1,2,3,4 };
 | 
						const uint8_t v4_spec[] = { PDP_EUA_ORG_IETF, PDP_EUA_TYPE_v4, 1,2,3,4 };
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
	const uint8_t v6_unspec[] = { PDP_EUA_ORG_IETF, PDP_EUA_TYPE_v6 };
 | 
						const uint8_t v6_unspec[] = { PDP_EUA_ORG_IETF, PDP_EUA_TYPE_v6 };
 | 
				
			||||||
	const uint8_t v6_spec[] = { PDP_EUA_ORG_IETF, PDP_EUA_TYPE_v6,
 | 
						const uint8_t v6_spec[] = { PDP_EUA_ORG_IETF, PDP_EUA_TYPE_v6,
 | 
				
			||||||
				    1,2,3,4,5,6,7,8,9,0xa,0xb,0xc,0xd,0xe,0xf,0x10 };
 | 
									    1,2,3,4,5,6,7,8,9,0xa,0xb,0xc,0xd,0xe,0xf,0x10 };
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
	memset(&eua, 0, sizeof(eua));
 | 
						memset(&eua, 0, sizeof(eua));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	printf("Testing in46a_from_eua()\n");
 | 
						printf("Testing in46a_from_eua()\n");
 | 
				
			||||||
@@ -232,6 +249,7 @@ static void test_in46a_from_eua(void)
 | 
				
			|||||||
	OSMO_ASSERT(ia.len == 4);
 | 
						OSMO_ASSERT(ia.len == 4);
 | 
				
			||||||
	OSMO_ASSERT(ia.v4.s_addr == htonl(0x01020304));
 | 
						OSMO_ASSERT(ia.v4.s_addr == htonl(0x01020304));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
	/* unspecified V6 */
 | 
						/* unspecified V6 */
 | 
				
			||||||
	memcpy(eua.v, v6_unspec, sizeof(v6_unspec));
 | 
						memcpy(eua.v, v6_unspec, sizeof(v6_unspec));
 | 
				
			||||||
	eua.l = sizeof(v6_unspec);
 | 
						eua.l = sizeof(v6_unspec);
 | 
				
			||||||
@@ -245,6 +263,7 @@ static void test_in46a_from_eua(void)
 | 
				
			|||||||
	OSMO_ASSERT(in46a_from_eua(&eua, &ia) == 0);
 | 
						OSMO_ASSERT(in46a_from_eua(&eua, &ia) == 0);
 | 
				
			||||||
	OSMO_ASSERT(ia.len == 16);
 | 
						OSMO_ASSERT(ia.len == 16);
 | 
				
			||||||
	OSMO_ASSERT(!memcmp(&ia.v6, v6_spec+2, ia.len));
 | 
						OSMO_ASSERT(!memcmp(&ia.v6, v6_spec+2, ia.len));
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void test_in46a_netmasklen(void)
 | 
					static void test_in46a_netmasklen(void)
 | 
				
			||||||
@@ -275,6 +294,7 @@ static void test_in46a_netmasklen(void)
 | 
				
			|||||||
	len = in46a_netmasklen(&netmask);
 | 
						len = in46a_netmasklen(&netmask);
 | 
				
			||||||
	OSMO_ASSERT(len == 0);
 | 
						OSMO_ASSERT(len == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(BUILD_IPv6)
 | 
				
			||||||
	printf("Testing in46a_netmasklen() with IPv6 addresses\n");
 | 
						printf("Testing in46a_netmasklen() with IPv6 addresses\n");
 | 
				
			||||||
	const struct in46_addr netmaskA = {
 | 
						const struct in46_addr netmaskA = {
 | 
				
			||||||
		.len = 16,
 | 
							.len = 16,
 | 
				
			||||||
@@ -303,6 +323,7 @@ static void test_in46a_netmasklen(void)
 | 
				
			|||||||
	};
 | 
						};
 | 
				
			||||||
	len = in46a_netmasklen(&netmaskD);
 | 
						len = in46a_netmasklen(&netmaskD);
 | 
				
			||||||
	OSMO_ASSERT(len == 0);
 | 
						OSMO_ASSERT(len == 0);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int main(int argc, char **argv)
 | 
					int main(int argc, char **argv)
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user