Added IP address alias capability for FreeBSD
diff --git a/ggsn/ggsn.c b/ggsn/ggsn.c
index b75b01d..c0592c9 100644
--- a/ggsn/ggsn.c
+++ b/ggsn/ggsn.c
@@ -90,7 +90,7 @@
   fclose(file);
 }
 
-#ifdef __sun__
+#if defined(_sun__)
 int daemon(int nochdir, int noclose) {
   int fd;
 
diff --git a/ggsn/tun.c b/ggsn/tun.c
index 208cca6..b406fdb 100644
--- a/ggsn/tun.c
+++ b/ggsn/tun.c
@@ -343,22 +343,28 @@
 
   /* TODO: Is this needed on FreeBSD? */
   if (!this->addrs) /* Use ioctl for first addr to make ping work */
-    return tun_setaddr(this, addr, dstaddr, netmask);
+    return tun_setaddr(this, addr, dstaddr, netmask); /* TODO dstaddr */
 
   memset(&areq, 0, sizeof(areq));
 
   /* Set up interface name */
   strncpy(areq.ifra_name, this->devname, IFNAMSIZ);
-  ifr.ifr_name[IFNAMSIZ-1] = 0; /* Make sure to terminate */
+  areq.ifra_name[IFNAMSIZ-1] = 0; /* Make sure to terminate */
 
-  ((struct sockaddr_in) areq.ifra_addr).sin_family = AF_INET;
-  ((struct sockaddr_in) areq.ifra_addr).sin_len = sizeof(areq.ifra_addr);
-  ((struct sockaddr_in) areq.ifra_addr).sin_addr.s_addr = addr->s_addr;
+  ((struct sockaddr_in*) &areq.ifra_addr)->sin_family = AF_INET;
+  ((struct sockaddr_in*) &areq.ifra_addr)->sin_len = sizeof(areq.ifra_addr);
+  ((struct sockaddr_in*) &areq.ifra_addr)->sin_addr.s_addr = addr->s_addr;
 
-  ((struct sockaddr_in) areq.ifra_mask).sin_family = AF_INET;
-  ((struct sockaddr_in) areq.ifra_mask).sin_len    = sizeof(areq.ifra_mask);
-  ((struct sockaddr_in) areq.ifra_mask).sin_addr.s_addr = netmask->s_addr;
+  ((struct sockaddr_in*) &areq.ifra_mask)->sin_family = AF_INET;
+  ((struct sockaddr_in*) &areq.ifra_mask)->sin_len    = sizeof(areq.ifra_mask);
+  ((struct sockaddr_in*) &areq.ifra_mask)->sin_addr.s_addr = netmask->s_addr;
 
+  /* For some reason FreeBSD uses ifra_broadcast for specifying dstaddr */
+  ((struct sockaddr_in*) &areq.ifra_broadaddr)->sin_family = AF_INET;
+  ((struct sockaddr_in*) &areq.ifra_broadaddr)->sin_len = 
+    sizeof(areq.ifra_broadaddr);
+  ((struct sockaddr_in*) &areq.ifra_broadaddr)->sin_addr.s_addr = 
+    dstaddr->s_addr;
 
   /* Create a channel to the NET kernel. */
   if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
@@ -607,6 +613,8 @@
 #elif defined(__FreeBSD__)
   char devname[IFNAMSIZ+5]; /* "/dev/" + ifname */
   int devnum;
+  struct ifaliasreq areq;
+  int fd;
 
 #elif defined(__sun__)
   int if_fd, ppa = -1;
@@ -663,6 +671,27 @@
 
   snprintf((*tun)->devname, sizeof((*tun)->devname), "tun%d", devnum);
   (*tun)->devname[sizeof((*tun)->devname)] = 0;
+
+  /* The tun device we found might have "old" IP addresses allocated */
+  /* We need to delete those. This problem is not present on Linux */
+
+  memset(&areq, 0, sizeof(areq));
+
+  /* Set up interface name */
+  strncpy(areq.ifra_name, (*tun)->devname, IFNAMSIZ);
+  areq.ifra_name[IFNAMSIZ-1] = 0; /* Make sure to terminate */
+
+  /* Create a channel to the NET kernel. */
+  if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+    sys_err(LOG_ERR, __FILE__, __LINE__, errno,
+	    "socket() failed");
+    return -1;
+  }
+  
+  /* Delete any IP addresses until SIOCDIFADDR fails */
+  while (ioctl(fd, SIOCDIFADDR, (void *) &areq) != -1);
+
+  close(fd);
   return 0;
 
 #elif defined(__sun__)
diff --git a/gtp/gtp.c b/gtp/gtp.c
index af4bdba..d4e5d74 100644
--- a/gtp/gtp.c
+++ b/gtp/gtp.c
@@ -407,7 +407,7 @@
   memset(&addr, 0, sizeof(addr));
   addr.sin_family = AF_INET;
   addr.sin_addr = *inetaddr;
-#ifdef __FreeBSD__
+#if defined(__FreeBSD__)
   addr.sin_len = sizeof(addr);
 #endif
 
@@ -766,7 +766,7 @@
   addr.sin_family = AF_INET;
   addr.sin_addr = *listen;  /* Same IP for user traffic and signalling*/
   addr.sin_port = htons(GTP0_PORT);
-#ifdef __FreeBSD__
+#if defined(__FreeBSD__)
   addr.sin_len = sizeof(addr);
 #endif
   
@@ -787,7 +787,7 @@
   addr.sin_family = AF_INET;
   addr.sin_addr = *listen;  /* Same IP for user traffic and signalling*/
   addr.sin_port = htons(GTP1C_PORT);
-#ifdef __FreeBSD__
+#if defined(__FreeBSD__)
   addr.sin_len = sizeof(addr);
 #endif
   
@@ -808,7 +808,7 @@
   addr.sin_family = AF_INET;
   addr.sin_addr = *listen;  /* Same IP for user traffic and signalling*/
   addr.sin_port = htons(GTP1U_PORT);
-#ifdef __FreeBSD__
+#if defined(__FreeBSD__)
   addr.sin_len = sizeof(addr);
 #endif
   
@@ -2944,7 +2944,7 @@
 
   memset(&addr, 0, sizeof(addr));
   addr.sin_family = AF_INET;
-#ifdef __FreeBSD__
+#if defined(__FreeBSD__)
   addr.sin_len = sizeof(addr);
 #endif
 
@@ -2965,7 +2965,8 @@
     if (len > sizeof (union gtp_packet) - sizeof(struct gtp0_header)) {
       gsn->err_memcpy++;
       gtp_err(LOG_ERR, __FILE__, __LINE__, 
-	      "Memcpy failed");
+	      "Memcpy failed: %d > %d", len,
+	      sizeof (union gtp_packet) - sizeof(struct gtp0_header));
       return EOF;
     }
     memcpy(packet.gtp0.p, pack, len); /* TODO Should be avoided! */
@@ -2985,7 +2986,8 @@
     if (len > sizeof (union gtp_packet) - sizeof(struct gtp1_header_long)) {
       gsn->err_memcpy++;
       gtp_err(LOG_ERR, __FILE__, __LINE__, 
-	      "Memcpy failed");
+	      "Memcpy failed: %d > %d", len,
+	      sizeof (union gtp_packet) - sizeof(struct gtp0_header));
       return EOF;
     }
     memcpy(packet.gtp1l.p, pack, len); /* TODO Should be avoided! */
diff --git a/sgsnemu/tun.c b/sgsnemu/tun.c
index 208cca6..b406fdb 100644
--- a/sgsnemu/tun.c
+++ b/sgsnemu/tun.c
@@ -343,22 +343,28 @@
 
   /* TODO: Is this needed on FreeBSD? */
   if (!this->addrs) /* Use ioctl for first addr to make ping work */
-    return tun_setaddr(this, addr, dstaddr, netmask);
+    return tun_setaddr(this, addr, dstaddr, netmask); /* TODO dstaddr */
 
   memset(&areq, 0, sizeof(areq));
 
   /* Set up interface name */
   strncpy(areq.ifra_name, this->devname, IFNAMSIZ);
-  ifr.ifr_name[IFNAMSIZ-1] = 0; /* Make sure to terminate */
+  areq.ifra_name[IFNAMSIZ-1] = 0; /* Make sure to terminate */
 
-  ((struct sockaddr_in) areq.ifra_addr).sin_family = AF_INET;
-  ((struct sockaddr_in) areq.ifra_addr).sin_len = sizeof(areq.ifra_addr);
-  ((struct sockaddr_in) areq.ifra_addr).sin_addr.s_addr = addr->s_addr;
+  ((struct sockaddr_in*) &areq.ifra_addr)->sin_family = AF_INET;
+  ((struct sockaddr_in*) &areq.ifra_addr)->sin_len = sizeof(areq.ifra_addr);
+  ((struct sockaddr_in*) &areq.ifra_addr)->sin_addr.s_addr = addr->s_addr;
 
-  ((struct sockaddr_in) areq.ifra_mask).sin_family = AF_INET;
-  ((struct sockaddr_in) areq.ifra_mask).sin_len    = sizeof(areq.ifra_mask);
-  ((struct sockaddr_in) areq.ifra_mask).sin_addr.s_addr = netmask->s_addr;
+  ((struct sockaddr_in*) &areq.ifra_mask)->sin_family = AF_INET;
+  ((struct sockaddr_in*) &areq.ifra_mask)->sin_len    = sizeof(areq.ifra_mask);
+  ((struct sockaddr_in*) &areq.ifra_mask)->sin_addr.s_addr = netmask->s_addr;
 
+  /* For some reason FreeBSD uses ifra_broadcast for specifying dstaddr */
+  ((struct sockaddr_in*) &areq.ifra_broadaddr)->sin_family = AF_INET;
+  ((struct sockaddr_in*) &areq.ifra_broadaddr)->sin_len = 
+    sizeof(areq.ifra_broadaddr);
+  ((struct sockaddr_in*) &areq.ifra_broadaddr)->sin_addr.s_addr = 
+    dstaddr->s_addr;
 
   /* Create a channel to the NET kernel. */
   if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
@@ -607,6 +613,8 @@
 #elif defined(__FreeBSD__)
   char devname[IFNAMSIZ+5]; /* "/dev/" + ifname */
   int devnum;
+  struct ifaliasreq areq;
+  int fd;
 
 #elif defined(__sun__)
   int if_fd, ppa = -1;
@@ -663,6 +671,27 @@
 
   snprintf((*tun)->devname, sizeof((*tun)->devname), "tun%d", devnum);
   (*tun)->devname[sizeof((*tun)->devname)] = 0;
+
+  /* The tun device we found might have "old" IP addresses allocated */
+  /* We need to delete those. This problem is not present on Linux */
+
+  memset(&areq, 0, sizeof(areq));
+
+  /* Set up interface name */
+  strncpy(areq.ifra_name, (*tun)->devname, IFNAMSIZ);
+  areq.ifra_name[IFNAMSIZ-1] = 0; /* Make sure to terminate */
+
+  /* Create a channel to the NET kernel. */
+  if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+    sys_err(LOG_ERR, __FILE__, __LINE__, errno,
+	    "socket() failed");
+    return -1;
+  }
+  
+  /* Delete any IP addresses until SIOCDIFADDR fails */
+  while (ioctl(fd, SIOCDIFADDR, (void *) &areq) != -1);
+
+  close(fd);
   return 0;
 
 #elif defined(__sun__)