Solaris tun interface
diff --git a/sgsnemu/ippool.c b/sgsnemu/ippool.c
index e3b72a5..ca31677 100644
--- a/sgsnemu/ippool.c
+++ b/sgsnemu/ippool.c
@@ -238,6 +238,11 @@
     if (ippool_aton(&addr, &mask, dyn, 0))
       return -1; /* Failed to parse dynamic pool */
 
+    /* Set IPPOOL_NOGATEWAY if IPPOOL_NODESTADDR is set */
+    if (flags & IPPOOL_NODESTADDR) {
+      flags |= IPPOOL_NOGATEWAY;
+    }
+
     /* Set IPPOOL_NONETWORK if IPPOOL_NOGATEWAY is set */
     if (flags & IPPOOL_NOGATEWAY) {   
       flags |= IPPOOL_NONETWORK;
@@ -249,6 +254,8 @@
       dynsize--;
     if (flags & IPPOOL_NOGATEWAY)   /* Exclude gateway address from pool */
       dynsize--;
+    if (flags & IPPOOL_NODESTADDR)  /* Exclude destination address from pool */
+      dynsize--;
     if (flags & IPPOOL_NOBROADCAST) /* Exclude broadcast address from pool */
       dynsize--;
   }
@@ -305,7 +312,9 @@
   (*this)->lastdyn = NULL;
   for (i = 0; i<dynsize; i++) {
 
-    if (flags & IPPOOL_NOGATEWAY)
+    if (flags & IPPOOL_NODESTADDR)
+      (*this)->member[i].addr.s_addr = htonl(ntohl(addr.s_addr) + i + 3);
+    else if (flags & IPPOOL_NOGATEWAY)
       (*this)->member[i].addr.s_addr = htonl(ntohl(addr.s_addr) + i + 2);
     else if (flags & IPPOOL_NONETWORK)
       (*this)->member[i].addr.s_addr = htonl(ntohl(addr.s_addr) + i + 1);
diff --git a/sgsnemu/ippool.h b/sgsnemu/ippool.h
index 67a6f3e..46ba447 100644
--- a/sgsnemu/ippool.h
+++ b/sgsnemu/ippool.h
@@ -36,6 +36,7 @@
 #define IPPOOL_NONETWORK   0x01
 #define IPPOOL_NOBROADCAST 0x02
 #define IPPOOL_NOGATEWAY   0x04
+#define IPPOOL_NODESTADDR  0x08
 
 #define IPPOOL_STATSIZE 0x10000
 
diff --git a/sgsnemu/sgsnemu.c b/sgsnemu/sgsnemu.c
index 4915fcd..9bc576e 100644
--- a/sgsnemu/sgsnemu.c
+++ b/sgsnemu/sgsnemu.c
@@ -87,7 +87,7 @@
 struct {
   int debug;                      /* Print debug messages */
   int createif;                   /* Create local network interface */
-  struct in_addr net, mask;       /* Network interface       */
+  struct in_addr netaddr, destaddr, net, mask;   /* Network interface  */
   char *ipup, *ipdown;            /* Filename of scripts */
   int defaultroute;               /* Set up default route */
   struct in_addr pinghost;        /* Remote ping host    */
@@ -218,26 +218,26 @@
   if (cmdline_parser (argc, argv, &args_info) != 0)
     return -1;
   if (args_info.debug_flag) {
-    printf("remote: %s\n", args_info.remote_arg);
-    printf("listen: %s\n", args_info.listen_arg);
-    printf("conf: %s\n", args_info.conf_arg);
+    if (args_info.remote_arg) printf("remote: %s\n", args_info.remote_arg);
+    if (args_info.listen_arg) printf("listen: %s\n", args_info.listen_arg);
+    if (args_info.conf_arg) printf("conf: %s\n", args_info.conf_arg);
     printf("debug: %d\n", args_info.debug_flag);
-    printf("imsi: %s\n", args_info.imsi_arg);
+    if (args_info.imsi_arg) printf("imsi: %s\n", args_info.imsi_arg);
     printf("qos: %#08x\n", args_info.qos_arg);
-    printf("apn: %s\n", args_info.apn_arg);
-    printf("msisdn: %s\n", args_info.msisdn_arg);
-    printf("uid: %s\n", args_info.uid_arg);
-    printf("pwd: %s\n", args_info.pwd_arg);
-    printf("pidfile: %s\n", args_info.pidfile_arg);
-    printf("statedir: %s\n", args_info.statedir_arg);
-    printf("dns: %s\n", args_info.dns_arg);
+    if (args_info.apn_arg) printf("apn: %s\n", args_info.apn_arg);
+    if (args_info.msisdn_arg) printf("msisdn: %s\n", args_info.msisdn_arg);
+    if (args_info.uid_arg) printf("uid: %s\n", args_info.uid_arg);
+    if (args_info.pwd_arg) printf("pwd: %s\n", args_info.pwd_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);
+    if (args_info.dns_arg) printf("dns: %s\n", args_info.dns_arg);
     printf("contexts: %d\n", args_info.contexts_arg);
     printf("timelimit: %d\n", args_info.timelimit_arg);
     printf("createif: %d\n", args_info.createif_flag);
-    printf("ipup: %s\n", args_info.ipup_arg);
-    printf("ipdown: %s\n", args_info.ipdown_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);
     printf("defaultroute: %d\n", args_info.defaultroute_flag);
-    printf("pinghost: %s\n", args_info.pinghost_arg);
+    if (args_info.pinghost_arg) printf("pinghost: %s\n", args_info.pinghost_arg);
     printf("pingrate: %d\n", args_info.pingrate_arg);
     printf("pingsize: %d\n", args_info.pingsize_arg);
     printf("pingcount: %d\n", args_info.pingcount_arg);
@@ -251,26 +251,26 @@
       return -1;
     if (args_info.debug_flag) {
       printf("cmdline_parser_configfile\n");
-      printf("remote: %s\n", args_info.remote_arg);
-      printf("listen: %s\n", args_info.listen_arg);
-      printf("conf: %s\n", args_info.conf_arg);
+      if (args_info.remote_arg) printf("remote: %s\n", args_info.remote_arg);
+      if (args_info.listen_arg) printf("listen: %s\n", args_info.listen_arg);
+      if (args_info.conf_arg) printf("conf: %s\n", args_info.conf_arg);
       printf("debug: %d\n", args_info.debug_flag);
-      printf("imsi: %s\n", args_info.imsi_arg);
+      if (args_info.imsi_arg) printf("imsi: %s\n", args_info.imsi_arg);
       printf("qos: %#08x\n", args_info.qos_arg);
-      printf("apn: %s\n", args_info.apn_arg);
-      printf("msisdn: %s\n", args_info.msisdn_arg);
-      printf("uid: %s\n", args_info.uid_arg);
-      printf("pwd: %s\n", args_info.pwd_arg);
-      printf("pidfile: %s\n", args_info.pidfile_arg);
-      printf("statedir: %s\n", args_info.statedir_arg);
-      printf("dns: %s\n", args_info.dns_arg);
+      if (args_info.apn_arg) printf("apn: %s\n", args_info.apn_arg);
+      if (args_info.msisdn_arg) printf("msisdn: %s\n", args_info.msisdn_arg);
+      if (args_info.uid_arg) printf("uid: %s\n", args_info.uid_arg);
+      if (args_info.pwd_arg) printf("pwd: %s\n", args_info.pwd_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);
+      if (args_info.dns_arg) printf("dns: %s\n", args_info.dns_arg);
       printf("contexts: %d\n", args_info.contexts_arg);
       printf("timelimit: %d\n", args_info.timelimit_arg);
       printf("createif: %d\n", args_info.createif_flag);
-      printf("ipup: %s\n", args_info.ipup_arg);
-      printf("ipdown: %s\n", args_info.ipdown_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);
       printf("defaultroute: %d\n", args_info.defaultroute_flag);
-      printf("pinghost: %s\n", args_info.pinghost_arg);
+      if (args_info.pinghost_arg) printf("pinghost: %s\n", args_info.pinghost_arg);
       printf("pingrate: %d\n", args_info.pingrate_arg);
       printf("pingsize: %d\n", args_info.pingsize_arg);
       printf("pingcount: %d\n", args_info.pingcount_arg);
@@ -495,10 +495,21 @@
 	      "Invalid network address: %s!", args_info.net_arg);
       exit(1);
     }
+
+#if defined (__sun__)
+    options.netaddr.s_addr = htonl(ntohl(options.net.s_addr) + 1);
+    options.destaddr.s_addr = htonl(ntohl(options.net.s_addr) + 1);
+#else
+    options.netaddr.s_addr = options.net.s_addr;
+    options.destaddr.s_addr = options.net.s_addr;
+#endif
+
   }
   else {
     options.net.s_addr = 0;
     options.mask.s_addr = 0;
+    options.netaddr.s_addr = 0;
+    options.destaddr.s_addr = 0;
   }
 
   /* ipup */
@@ -1067,11 +1078,11 @@
 
   if ((options.createif) && (options.net.s_addr)) {
     /* printf("Setting up interface and routing\n");*/
-    tun_addaddr(tun, &options.net,  &options.net, &options.mask);
+    tun_addaddr(tun, &options.netaddr,  &options.destaddr, &options.mask);
     if (options.defaultroute) {
       struct in_addr rm;
       rm.s_addr = 0;
-      tun_addroute(tun, &rm,  &options.net, &rm);
+      tun_addroute(tun, &rm, &options.destaddr, &rm);
     }
     if (options.ipup) tun_runscript(tun, options.ipup);
   }
diff --git a/sgsnemu/tun.c b/sgsnemu/tun.c
index b406fdb..3436972 100644
--- a/sgsnemu/tun.c
+++ b/sgsnemu/tun.c
@@ -619,6 +619,8 @@
 #elif defined(__sun__)
   int if_fd, ppa = -1;
   static int ip_fd = 0;
+  int muxid;
+  struct ifreq ifr;
 
 #else
 #error  "Unknown platform!"
@@ -696,8 +698,8 @@
 
 #elif defined(__sun__)
 
-  if( (ip_fd = open("/dev/ip", O_RDWR, 0)) < 0){
-    sys_err(LOG_ERR, __FILE__, __LINE__, errno, "Can't open /dev/ip");
+  if( (ip_fd = open("/dev/udp", O_RDWR, 0)) < 0){
+    sys_err(LOG_ERR, __FILE__, __LINE__, errno, "Can't open /dev/udp");
     return -1;
   }
   
@@ -708,28 +710,28 @@
   
   /* Assign a new PPA and get its unit number. */
   if( (ppa = ioctl((*tun)->fd, TUNNEWPPA, -1)) < 0){
-    syslog(LOG_ERR, "Can't assign new interface");
+    sys_err(LOG_ERR, __FILE__, __LINE__, errno, "Can't assign new interface");
     return -1;
   }
   
   if( (if_fd = open("/dev/tun", O_RDWR, 0)) < 0){
-    syslog(LOG_ERR, "Can't open /dev/tun (2)");
+    sys_err(LOG_ERR, __FILE__, __LINE__, errno, "Can't open /dev/tun (2)");
     return -1;
   }
   if(ioctl(if_fd, I_PUSH, "ip") < 0){
-    syslog(LOG_ERR, "Can't push IP module");
+    sys_err(LOG_ERR, __FILE__, __LINE__, errno, "Can't push IP module");
     return -1;
   }
   
   /* Assign ppa according to the unit number returned by tun device */
   if(ioctl(if_fd, IF_UNITSEL, (char *)&ppa) < 0){
-    syslog(LOG_ERR, "Can't set PPA %d", ppa);
+    sys_err(LOG_ERR, __FILE__, __LINE__, errno, "Can't set PPA %d", ppa);
     return -1;
   }
 
   /* Link the two streams */
-  if(ioctl(ip_fd, I_LINK, if_fd) < 0){
-    syslog(LOG_ERR, "Can't link TUN device to IP");
+  if ((muxid = ioctl(ip_fd, I_LINK, if_fd)) < 0) {
+    sys_err(LOG_ERR, __FILE__, __LINE__, errno, "Can't link TUN device to IP");
     return -1;
   }
 
@@ -737,6 +739,20 @@
   
   snprintf((*tun)->devname, sizeof((*tun)->devname), "tun%d", ppa);
   (*tun)->devname[sizeof((*tun)->devname)] = 0;
+
+  memset(&ifr, 0, sizeof(ifr));
+  strcpy(ifr.ifr_name, (*tun)->devname);
+  ifr.ifr_ip_muxid = muxid;
+  
+  if (ioctl(ip_fd, SIOCSIFMUXID, &ifr) < 0) {
+    ioctl(ip_fd, I_PUNLINK, muxid);
+    sys_err(LOG_ERR, __FILE__, __LINE__, errno, "Can't set multiplexor id");
+    return -1;
+  }
+  
+  /*  if (fcntl (fd, F_SETFL, O_NONBLOCK) < 0)
+      msg (M_ERR, "Set file descriptor to non-blocking failed"); */
+
   return 0;
 
 #else
@@ -767,6 +783,9 @@
 
 int tun_decaps(struct tun_t *this)
 {
+
+#if defined(__linux__) || defined (__FreeBSD__)
+
   unsigned char buffer[PACKET_MAX];
   int status;
   
@@ -779,11 +798,45 @@
     return this->cb_ind(this, buffer, status);
 
   return 0;
+
+#elif defined (__sun__)
+
+  unsigned char buffer[PACKET_MAX];
+  struct strbuf sbuf;
+  int f = 0;
+  
+  sbuf.maxlen = PACKET_MAX;      
+  sbuf.buf = buffer;
+  if (getmsg(this->fd, NULL, &sbuf, &f) < 0) {
+    sys_err(LOG_ERR, __FILE__, __LINE__, errno, "getmsg() failed");
+    return -1;
+  }
+
+  if (this->cb_ind)
+    return this->cb_ind(this, buffer, sbuf.len);
+
+  return 0;
+  
+#endif
+
 }
 
+
 int tun_encaps(struct tun_t *tun, void *pack, unsigned len)
 {
+
+#if defined(__linux__) || defined (__FreeBSD__)
+
   return write(tun->fd, pack, len);
+
+#elif defined (__sun__)
+
+  struct strbuf sbuf;
+  sbuf.len = len;      
+  sbuf.buf = pack;
+  return putmsg(tun->fd, NULL, &sbuf, 0);
+
+#endif
 }
 
 int tun_runscript(struct tun_t *tun, char* script) {