aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSUZUKI, Shinsuke <suz@kame.net>2007-02-27 14:21:41 +0000
committerBjørn Mork <bjorn@mork.no>2010-08-06 15:37:36 +0200
commitfe2c74572f875332b461ba2a17a594a7ee4eb2d3 (patch)
tree84ca26e3f0168158823d7c741479e37ba069a862
parentfcdc0798bb2be5fa00427240afda6bdfd3d0a392 (diff)
supported compilation on Solaris (contributed by James Carlson)
-rw-r--r--CHANGES6
-rw-r--r--Makefile.in13
-rw-r--r--auth.h8
-rw-r--r--common.c190
-rwxr-xr-xconfigure338
-rw-r--r--configure.in23
-rw-r--r--control.h11
-rw-r--r--dhcp6.h22
-rw-r--r--dhcp6c.c2
-rw-r--r--dhcp6relay.c4
-rw-r--r--dhcp6s.c4
-rw-r--r--missing/arc4random.h5
-rw-r--r--missing/daemon.c50
-rw-r--r--missing/err.h34
-rw-r--r--missing/getifaddrs.c217
-rw-r--r--missing/ifaddrs.h44
-rw-r--r--missing/sys/queue.h137
-rw-r--r--missing/warnx.c59
18 files changed, 1130 insertions, 37 deletions
diff --git a/CHANGES b/CHANGES
index 4fdd666..9f11c07 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,9 @@
+2007-02-27 SUZUKI, Shinsuke <suz@kame.net>
+ * Makefile.in, configure.in, configure, auth.h, common.c, control.h, dhcp6.h,
+ dhcp6s.c, missing/{arc4random.h, daemon.c, err.h, getifaddrs.c, ifaddrs.h,
+ sys/queue.h, warnx.c}
+ supported compilation on Solaris (contributed by James Carlson)
+
2007-02-12 SUZUKI, Shinsuke <suz@kame.net>
* cftoken.l: accepts interface names, such as eth0.100(Linux VLAN interface)
or foobar (named by "ifconfig name" command). (Bug-ID 1644637)
diff --git a/Makefile.in b/Makefile.in
index 4398b31..3e6f606 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -25,7 +25,7 @@
# SUCH DAMAGE.
#
-# $Id: Makefile.in,v 1.14 2007-02-12 08:32:36 suzsuz Exp $
+# $Id: Makefile.in,v 1.15 2007-02-27 14:21:40 suzsuz Exp $
# $KAME: Makefile.in,v 1.45 2005/10/16 16:25:38 suz Exp $
#
@@ -90,6 +90,12 @@ strlcat.o: $(srcdir)/missing/strlcat.c
strlcpy.o: $(srcdir)/missing/strlcpy.c
$(CC) -c $(srcdir)/missing/$*.c
arc4random.o: $(srcdir)/missing/arc4random.c
+ $(CC) $(CFLAGS) -c $(srcdir)/missing/$*.c
+getifaddrs.o: $(srcdir)/missing/getifaddrs.c
+ $(CC) -c $(srcdir)/missing/$*.c
+daemon.o: $(srcdir)/missing/daemon.c
+ $(CC) -c $(srcdir)/missing/$*.c
+warnx.o: $(srcdir)/missing/warnx.c
$(CC) -c $(srcdir)/missing/$*.c
$(srcdir)/ianaopts.h: gentab.pl bootp-dhcp-parameters
@@ -122,4 +128,7 @@ package:
$(srcdir)/configure $(srcdir)/configure.in \
$(srcdir)/install-sh $(srcdir)/*.sample \
$(srcdir)/missing/arc4random.? $(srcdir)/missing/strlcat.c \
- $(srcdir)/missing/strlcpy.c
+ $(srcdir)/missing/strlcpy.c $(srcdir)/missing/daemon.c \
+ $(srcdir)/missing/err.h $(srcdir)/missing/warnx.c \
+ $(srcdir)/missing/ifaddrs.h $(srcdir)/missing/getifaddrs.c \
+ $(srcdir)/missing/sys/queue.h
diff --git a/auth.h b/auth.h
index 8413658..84564d9 100644
--- a/auth.h
+++ b/auth.h
@@ -29,6 +29,14 @@
* SUCH DAMAGE.
*/
+#ifdef __sun__
+#define __P(x) x
+#ifndef U_INT32_T_DEFINED
+#define U_INT32_T_DEFINED
+typedef uint32_t u_int32_t;
+#endif
+#endif
+
#define MD5_DIGESTLENGTH 16
/* secret key information for delayed authentication */
diff --git a/common.c b/common.c
index 698c716..7b1ba4f 100644
--- a/common.c
+++ b/common.c
@@ -55,6 +55,13 @@
#include <linux/if_packet.h>
#endif
#include <net/if_arp.h>
+#ifdef __sun__
+#include <sys/sockio.h>
+#include <sys/dlpi.h>
+#include <stropts.h>
+#include <fcntl.h>
+#include <libdevinfo.h>
+#endif
#ifdef __KAME__
#include <netinet6/in6_var.h>
@@ -71,13 +78,7 @@
#include <string.h>
#include <err.h>
#include <netdb.h>
-
-#ifdef HAVE_GETIFADDRS
-# ifdef HAVE_IFADDRS_H
-# define USE_GETIFADDRS
-# include <ifaddrs.h>
-# endif
-#endif
+#include <ifaddrs.h>
#include <dhcp6.h>
#include <config.h>
@@ -1081,6 +1082,137 @@ get_duid(idfile, duid)
return (-1);
}
+#ifdef __sun__
+struct hwparms {
+ char *buf;
+ u_int16_t *hwtypep;
+ ssize_t retval;
+};
+
+static ssize_t
+getifhwaddr(const char *ifname, char *buf, u_int16_t *hwtypep, int ppa)
+{
+ int fd, flags;
+ char fname[MAXPATHLEN], *cp;
+ struct strbuf putctl;
+ struct strbuf getctl;
+ long getbuf[1024];
+ dl_info_req_t dlir;
+ dl_phys_addr_req_t dlpar;
+ dl_phys_addr_ack_t *dlpaa;
+
+ dprintf(LOG_DEBUG, FNAME, "trying %s ppa %d", ifname, ppa);
+
+ if (ifname[0] == '\0')
+ return (-1);
+ if (ppa >= 0 && !isdigit(ifname[strlen(ifname) - 1]))
+ (void) snprintf(fname, sizeof (fname), "/dev/%s%d", ifname,
+ ppa);
+ else
+ (void) snprintf(fname, sizeof (fname), "/dev/%s", ifname);
+ getctl.maxlen = sizeof (getbuf);
+ getctl.buf = (char *)getbuf;
+ if ((fd = open(fname, O_RDWR)) == -1) {
+ dl_attach_req_t dlar;
+
+ cp = fname + strlen(fname) - 1;
+ if (!isdigit(*cp))
+ return (-1);
+ while (cp > fname) {
+ if (!isdigit(*cp))
+ break;
+ cp--;
+ }
+ if (cp == fname)
+ return (-1);
+ cp++;
+ dlar.dl_ppa = atoi(cp);
+ *cp = '\0';
+ if ((fd = open(fname, O_RDWR)) == -1)
+ return (-1);
+ dlar.dl_primitive = DL_ATTACH_REQ;
+ putctl.len = sizeof (dlar);
+ putctl.buf = (char *)&dlar;
+ if (putmsg(fd, &putctl, NULL, 0) == -1) {
+ (void) close(fd);
+ return (-1);
+ }
+ flags = 0;
+ if (getmsg(fd, &getctl, NULL, &flags) == -1) {
+ (void) close(fd);
+ return (-1);
+ }
+ if (getbuf[0] != DL_OK_ACK) {
+ (void) close(fd);
+ return (-1);
+ }
+ }
+ dlir.dl_primitive = DL_INFO_REQ;
+ putctl.len = sizeof (dlir);
+ putctl.buf = (char *)&dlir;
+ if (putmsg(fd, &putctl, NULL, 0) == -1) {
+ (void) close(fd);
+ return (-1);
+ }
+ flags = 0;
+ if (getmsg(fd, &getctl, NULL, &flags) == -1) {
+ (void) close(fd);
+ return (-1);
+ }
+ if (getbuf[0] != DL_INFO_ACK) {
+ (void) close(fd);
+ return (-1);
+ }
+ switch (((dl_info_ack_t *)getbuf)->dl_mac_type) {
+ case DL_CSMACD:
+ case DL_ETHER:
+ case DL_100VG:
+ case DL_ETH_CSMA:
+ case DL_100BT:
+ *hwtypep = ARPHRD_ETHER;
+ break;
+ default:
+ (void) close(fd);
+ return (-1);
+ }
+ dlpar.dl_primitive = DL_PHYS_ADDR_REQ;
+ dlpar.dl_addr_type = DL_CURR_PHYS_ADDR;
+ putctl.len = sizeof (dlpar);
+ putctl.buf = (char *)&dlpar;
+ if (putmsg(fd, &putctl, NULL, 0) == -1) {
+ (void) close(fd);
+ return (-1);
+ }
+ flags = 0;
+ if (getmsg(fd, &getctl, NULL, &flags) == -1) {
+ (void) close(fd);
+ return (-1);
+ }
+ if (getbuf[0] != DL_PHYS_ADDR_ACK) {
+ (void) close(fd);
+ return (-1);
+ }
+ dlpaa = (dl_phys_addr_ack_t *)getbuf;
+ if (dlpaa->dl_addr_length != 6) {
+ (void) close(fd);
+ return (-1);
+ }
+ (void) memcpy(buf, (char *)getbuf + dlpaa->dl_addr_offset,
+ dlpaa->dl_addr_length);
+ return (dlpaa->dl_addr_length);
+}
+
+static int
+devfs_handler(di_node_t node, di_minor_t minor, void *arg)
+{
+ struct hwparms *parms = arg;
+
+ parms->retval = getifhwaddr(di_minor_name(minor), parms->buf,
+ parms->hwtypep, di_instance(node));
+ return (parms->retval == -1 ? DI_WALK_CONTINUE : DI_WALK_TERMINATE);
+}
+#endif
+
static ssize_t
gethwid(buf, len, ifname, hwtypep)
char *buf;
@@ -1097,6 +1229,28 @@ gethwid(buf, len, ifname, hwtypep)
#endif
ssize_t l;
+#ifdef __sun__
+ if (ifname == NULL) {
+ di_node_t root;
+ struct hwparms parms;
+
+ if ((root = di_init("/", DINFOSUBTREE | DINFOMINOR |
+ DINFOPROP)) == DI_NODE_NIL) {
+ dprintf(LOG_INFO, FNAME, "di_init failed");
+ return (-1);
+ }
+ parms.buf = buf;
+ parms.hwtypep = hwtypep;
+ parms.retval = -1;
+ (void) di_walk_minor(root, DDI_NT_NET, DI_CHECK_ALIAS, &parms,
+ devfs_handler);
+ di_fini(root);
+ return (parms.retval);
+ } else {
+ return (getifhwaddr(ifname, buf, hwtypep, -1));
+ }
+#endif
+
if (getifaddrs(&ifap) < 0)
return (-1);
@@ -3094,6 +3248,9 @@ ifaddrconf(cmd, ifname, addr, plen, pltime, vltime)
struct in6_ifreq req;
struct ifreq ifr;
#endif
+#ifdef __sun__
+ struct lifreq req;
+#endif
unsigned long ioctl_cmd;
char *cmdstr;
int s; /* XXX overhead */
@@ -3107,6 +3264,9 @@ ifaddrconf(cmd, ifname, addr, plen, pltime, vltime)
#ifdef __linux__
ioctl_cmd = SIOCSIFADDR;
#endif
+#ifdef __sun__
+ ioctl_cmd = SIOCLIFADDIF;
+#endif
break;
case IFADDRCONF_REMOVE:
cmdstr = "remove";
@@ -3116,6 +3276,9 @@ ifaddrconf(cmd, ifname, addr, plen, pltime, vltime)
#ifdef __linux__
ioctl_cmd = SIOCDIFADDR;
#endif
+#ifdef __sun__
+ ioctl_cmd = SIOCLIFREMOVEIF;
+#endif
break;
default:
return (-1);
@@ -3149,6 +3312,9 @@ ifaddrconf(cmd, ifname, addr, plen, pltime, vltime)
req.ifr6_prefixlen = plen;
req.ifr6_ifindex = ifr.ifr_ifindex;
#endif
+#ifdef __sun__
+ strncpy(req.lifr_name, ifname, sizeof (req.lifr_name));
+#endif
if (ioctl(s, ioctl_cmd, &req)) {
dprintf(LOG_NOTICE, FNAME, "failed to %s an address on %s: %s",
@@ -3157,6 +3323,16 @@ ifaddrconf(cmd, ifname, addr, plen, pltime, vltime)
return (-1);
}
+#ifdef __sun__
+ memcpy(&req.lifr_addr, addr, sizeof (*addr));
+ if (ioctl(s, SIOCSLIFADDR, &req) == -1) {
+ dprintf(LOG_NOTICE, FNAME, "failed to %s new address on %s: %s",
+ cmdstr, ifname, strerror(errno));
+ close(s);
+ return (-1);
+ }
+#endif
+
dprintf(LOG_DEBUG, FNAME, "%s an address %s/%d on %s", cmdstr,
addr2str((struct sockaddr *)addr), plen, ifname);
diff --git a/configure b/configure
index 7ba6697..5eef856 100755
--- a/configure
+++ b/configure
@@ -2915,8 +2915,62 @@ fi
CFLAGS="$CFLAGS -I\$(srcdir)"
-echo "$as_me:$LINENO: checking for getaddrinfo/getnameinfo library" >&5
-echo $ECHO_N "checking for getaddrinfo/getnameinfo library... $ECHO_C" >&6
+if test -x /usr/bin/sun && /usr/bin/sun; then
+ CFLAGS="$CFLAGS -D_XOPEN_SOURCE=500 -D__EXTENSIONS__"
+ LDFLAGS="-lxnet -ldevinfo -lnsl -lsocket -lrt"
+fi
+
+echo "$as_me:$LINENO: checking for sys/queue.h" >&5
+echo $ECHO_N "checking for sys/queue.h... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/queue.h>
+int
+main ()
+{
+TAILQ_HEAD(test, none);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+ CFLAGS="$CFLAGS -I\$(srcdir)/missing"
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
echo "$as_me:$LINENO: checking for egrep" >&5
echo $ECHO_N "checking for egrep... $ECHO_C" >&6
@@ -2947,9 +3001,13 @@ _ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
$EGREP "yes" >/dev/null 2>&1; then
result=kame
+else
+ result=regular
fi
rm -f conftest*
+echo "$as_me:$LINENO: checking for getaddrinfo/getnameinfo library" >&5
+echo $ECHO_N "checking for getaddrinfo/getnameinfo library... $ECHO_C" >&6
echo "$as_me:$LINENO: result: $result" >&5
echo "${ECHO_T}$result" >&6
case $result in
@@ -3263,9 +3321,13 @@ fi
done
-echo "$as_me:$LINENO: checking for getifaddrs" >&5
-echo $ECHO_N "checking for getifaddrs... $ECHO_C" >&6
-if test "${ac_cv_func_getifaddrs+set}" = set; then
+
+for ac_func in getifaddrs
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
cat >conftest.$ac_ext <<_ACEOF
@@ -3274,12 +3336,12 @@ _ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
-/* Define getifaddrs to an innocuous variant, in case <limits.h> declares getifaddrs.
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define getifaddrs innocuous_getifaddrs
+#define $ac_func innocuous_$ac_func
/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char getifaddrs (); below.
+ which can conflict with char $ac_func (); below.
Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
<limits.h> exists even on freestanding compilers. */
@@ -3289,7 +3351,7 @@ cat >>conftest.$ac_ext <<_ACEOF
# include <assert.h>
#endif
-#undef getifaddrs
+#undef $ac_func
/* Override any gcc2 internal prototype to avoid an error. */
#ifdef __cplusplus
@@ -3298,14 +3360,14 @@ extern "C"
#endif
/* We use char because int might match the return type of a gcc2
builtin and then its argument prototype would still apply. */
-char getifaddrs ();
+char $ac_func ();
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
-#if defined (__stub_getifaddrs) || defined (__stub___getifaddrs)
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
choke me
#else
-char (*f) () = getifaddrs;
+char (*f) () = $ac_func;
#endif
#ifdef __cplusplus
}
@@ -3314,7 +3376,7 @@ char (*f) () = getifaddrs;
int
main ()
{
-return f != getifaddrs;
+return f != $ac_func;
;
return 0;
}
@@ -3341,27 +3403,35 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
- ac_cv_func_getifaddrs=yes
+ eval "$as_ac_var=yes"
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
-ac_cv_func_getifaddrs=no
+eval "$as_ac_var=no"
fi
rm -f conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
fi
-echo "$as_me:$LINENO: result: $ac_cv_func_getifaddrs" >&5
-echo "${ECHO_T}$ac_cv_func_getifaddrs" >&6
-if test $ac_cv_func_getifaddrs = yes; then
- cat >>confdefs.h <<\_ACEOF
-#define HAVE_GETIFADDRS 1
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF
else
- echo FATAL: getifaddrs is required
- exit 1
+ case $LIBOBJS in
+ "$ac_func.$ac_objext" | \
+ *" $ac_func.$ac_objext" | \
+ "$ac_func.$ac_objext "* | \
+ *" $ac_func.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS $ac_func.$ac_objext" ;;
+esac
+
fi
+done
+
for ac_func in if_nametoindex
@@ -3579,6 +3649,230 @@ done
+for ac_func in daemon
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_var=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+else
+ case $LIBOBJS in
+ "$ac_func.$ac_objext" | \
+ *" $ac_func.$ac_objext" | \
+ "$ac_func.$ac_objext "* | \
+ *" $ac_func.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS $ac_func.$ac_objext" ;;
+esac
+
+fi
+done
+
+
+
+for ac_func in warnx
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_var=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+else
+ case $LIBOBJS in
+ "$ac_func.$ac_objext" | \
+ *" $ac_func.$ac_objext" | \
+ "$ac_func.$ac_objext "* | \
+ *" $ac_func.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS $ac_func.$ac_objext" ;;
+esac
+
+fi
+done
+
+
+
echo "$as_me:$LINENO: checking for ANSI C header files" >&5
echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6
if test "${ac_cv_header_stdc+set}" = set; then
diff --git a/configure.in b/configure.in
index 825dade..461949a 100644
--- a/configure.in
+++ b/configure.in
@@ -50,12 +50,25 @@ dnl exit 1])
CFLAGS="$CFLAGS -I\$(srcdir)"
-AC_MSG_CHECKING(for getaddrinfo/getnameinfo library)
+dnl On Sun systems, we need to use the standards-compliant 3XNET functions
+if test -x /usr/bin/sun && /usr/bin/sun; then
+ CFLAGS="$CFLAGS -D_XOPEN_SOURCE=500 -D__EXTENSIONS__"
+ LDFLAGS="-lxnet -ldevinfo -lnsl -lsocket -lrt"
+fi
+
+AC_MSG_CHECKING(for sys/queue.h)
+AC_TRY_COMPILE([#include <sys/queue.h>],
+ [TAILQ_HEAD(test, none);],
+ [AC_MSG_RESULT(yes)],
+ [AC_MSG_RESULT(no)
+ CFLAGS="$CFLAGS -I\$(srcdir)/missing"])
+
AC_EGREP_CPP(yes,
[#include <netinet/in.h>
#ifdef __KAME__
yes
-#endif], [result=kame])
+#endif], [result=kame], [result=regular])
+AC_MSG_CHECKING(for getaddrinfo/getnameinfo library)
AC_MSG_RESULT($result)
case $result in
kame) AC_DEFINE(INET6)
@@ -68,11 +81,11 @@ esac
AC_REPLACE_FUNCS(getaddrinfo)
AC_REPLACE_FUNCS(getnameinfo)
-AC_CHECK_FUNC(getifaddrs, AC_DEFINE(HAVE_GETIFADDRS), [dnl
- echo FATAL: getifaddrs is required
- exit 1])
+AC_REPLACE_FUNCS(getifaddrs)
AC_CHECK_FUNCS(if_nametoindex)
AC_REPLACE_FUNCS(strlcpy strlcat)
+AC_REPLACE_FUNCS(daemon)
+AC_REPLACE_FUNCS(warnx)
dnl Checks for header files.
AC_HEADER_STDC
diff --git a/control.h b/control.h
index bf0beb9..de1214b 100644
--- a/control.h
+++ b/control.h
@@ -29,6 +29,17 @@
* SUCH DAMAGE.
*/
+#ifdef __sun__
+#ifndef U_INT16_T_DEFINED
+#define U_INT16_T_DEFINED
+typedef uint16_t u_int16_t;
+#endif
+#ifndef U_INT32_T_DEFINED
+#define U_INT32_T_DEFINED
+typedef uint32_t u_int32_t;
+#endif
+#endif
+
#define DEFAULT_SERVER_CONTROL_ADDR "::1" /* default IPv6 address for server
* control socket */
#define DEFAULT_SERVER_CONTROL_PORT "5547" /* default TCP port for server
diff --git a/dhcp6.h b/dhcp6.h
index f2b82f8..6afb517 100644
--- a/dhcp6.h
+++ b/dhcp6.h
@@ -31,6 +31,28 @@
#ifndef __DHCP6_H_DEFINED
#define __DHCP6_H_DEFINED
+#ifdef __sun__
+#define __P(x) x
+typedef uint8_t u_int8_t;
+#ifndef U_INT16_T_DEFINED
+#define U_INT16_T_DEFINED
+typedef uint16_t u_int16_t;
+#endif
+#ifndef U_INT32_T_DEFINED
+#define U_INT32_T_DEFINED
+typedef uint32_t u_int32_t;
+#endif
+typedef uint64_t u_int64_t;
+#ifndef CMSG_SPACE
+#define CMSG_SPACE(l) \
+ ((unsigned int)_CMSG_HDR_ALIGN(sizeof (struct cmsghdr) + (l)))
+#endif
+#ifndef CMSG_LEN
+#define CMSG_LEN(l) \
+ ((unsigned int)_CMSG_DATA_ALIGN(sizeof (struct cmsghdr)) + (l))
+#endif
+#endif
+
/* Error Values */
#define DH6ERR_FAILURE 16
#define DH6ERR_AUTHFAIL 17
diff --git a/dhcp6c.c b/dhcp6c.c
index 2c98e96..df4643f 100644
--- a/dhcp6c.c
+++ b/dhcp6c.c
@@ -317,12 +317,14 @@ client6_init()
strerror(errno));
exit(1);
}
+#ifdef IPV6_V6ONLY
if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
&on, sizeof(on)) < 0) {
dprintf(LOG_ERR, FNAME, "setsockopt(IPV6_V6ONLY): %s",
strerror(errno));
exit(1);
}
+#endif
/*
* According RFC3315 2.2, only the incoming port should be bound to UDP
diff --git a/dhcp6relay.c b/dhcp6relay.c
index e05a47c..78d18df 100644
--- a/dhcp6relay.c
+++ b/dhcp6relay.c
@@ -360,12 +360,14 @@ relay6_init(int ifnum, char *iflist[])
strerror(errno));
goto failexit;
}
+#ifdef IPV6_V6ONLY
if (setsockopt(csock, IPPROTO_IPV6, IPV6_V6ONLY,
&on, sizeof (on)) < 0) {
dprintf(LOG_ERR, FNAME, "setsockopt(csock, IPV6_V6ONLY): %s",
strerror(errno));
goto failexit;
}
+#endif
if (bind(csock, res->ai_addr, res->ai_addrlen) < 0) {
dprintf(LOG_ERR, FNAME, "bind(csock): %s", strerror(errno));
goto failexit;
@@ -470,12 +472,14 @@ relay6_init(int ifnum, char *iflist[])
goto failexit;
}
on = 1;
+#ifdef IPV6_V6ONLY
if (setsockopt(ssock, IPPROTO_IPV6, IPV6_V6ONLY,
&on, sizeof (on)) < 0) {
dprintf(LOG_ERR, FNAME, "setsockopt(ssock, IPV6_V6ONLY): %s",
strerror(errno));
goto failexit;
}
+#endif
if (bind(ssock, res->ai_addr, res->ai_addrlen) < 0) {
dprintf(LOG_ERR, FNAME, "bind(ssock): %s", strerror(errno));
goto failexit;
diff --git a/dhcp6s.c b/dhcp6s.c
index 0016438..4c5f3b7 100644
--- a/dhcp6s.c
+++ b/dhcp6s.c
@@ -441,12 +441,14 @@ server6_init()
exit(1);
}
#endif
+#ifdef IPV6_V6ONLY
if (setsockopt(insock, IPPROTO_IPV6, IPV6_V6ONLY,
&on, sizeof(on)) < 0) {
dprintf(LOG_ERR, FNAME,
"setsockopt(inbound, IPV6_V6ONLY): %s", strerror(errno));
exit(1);
}
+#endif
if (bind(insock, res->ai_addr, res->ai_addrlen) < 0) {
dprintf(LOG_ERR, FNAME, "bind(insock): %s", strerror(errno));
exit(1);
@@ -517,7 +519,7 @@ server6_init()
strerror(errno));
exit(1);
}
-#ifndef __linux__
+#if !defined(__linux__) && !defined(__sun__)
/* make the socket write-only */
if (shutdown(outsock, 0)) {
dprintf(LOG_ERR, FNAME, "shutdown(outbound, 0): %s",
diff --git a/missing/arc4random.h b/missing/arc4random.h
index 7487efa..074c100 100644
--- a/missing/arc4random.h
+++ b/missing/arc4random.h
@@ -29,4 +29,9 @@
* SUCH DAMAGE.
*/
+#ifdef __sun__
+#define __P(x) x
+typedef uint32_t u_int32_t;
+#endif
+
extern u_int32_t arc4random __P((void));
diff --git a/missing/daemon.c b/missing/daemon.c
new file mode 100644
index 0000000..9bf6416
--- /dev/null
+++ b/missing/daemon.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2006 WIDE Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+int
+daemon(int nochdir, int noclose)
+{
+ if (fork() != 0)
+ _exit(0);
+ if (nochdir == 0)
+ (void) chdir("/");
+ if (noclose == 0) {
+ (void) close(0);
+ (void) open("/dev/null", O_RDWR);
+ (void) dup2(0, 1);
+ (void) dup2(0, 2);
+ }
+ (void) setsid();
+ if (fork() != 0)
+ _exit(0);
+ return (0);
+}
diff --git a/missing/err.h b/missing/err.h
new file mode 100644
index 0000000..dfc41d5
--- /dev/null
+++ b/missing/err.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2006 WIDE Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+extern void err(int, const char *);
+/* PRINTFLIKE2 */
+extern void errx(int, const char *, ...);
+/* PRINTFLIKE1 */
+extern void warnx(const char *, ...);
+#define warn warnx
diff --git a/missing/getifaddrs.c b/missing/getifaddrs.c
new file mode 100644
index 0000000..4320c43
--- /dev/null
+++ b/missing/getifaddrs.c
@@ -0,0 +1,217 @@
+/*
+ * Copyright (c) 2006 WIDE Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/sockio.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#include "ifaddrs.h"
+
+static int
+get_lifreq(int fd, struct lifreq **ifr_ret)
+{
+ struct lifnum lifn;
+ struct lifconf lifc;
+ struct lifreq *lifrp;
+
+ lifn.lifn_family = AF_UNSPEC;
+ lifn.lifn_flags = 0;
+ if (ioctl(fd, SIOCGLIFNUM, &lifn) == -1)
+ lifn.lifn_count = 16;
+ else
+ lifn.lifn_count += 16;
+
+ for (;;) {
+ lifc.lifc_len = lifn.lifn_count * sizeof (*lifrp);
+ lifrp = malloc(lifc.lifc_len);
+ if (lifrp == NULL)
+ return (-1);
+
+ lifc.lifc_family = AF_UNSPEC;
+ lifc.lifc_flags = 0;
+ lifc.lifc_buf = (char *)lifrp;
+ if (ioctl(fd, SIOCGLIFCONF, &lifc) == -1) {
+ free(lifrp);
+ if (errno == EINVAL) {
+ lifn.lifn_count <<= 1;
+ continue;
+ }
+ (void) close(fd);
+ return (-1);
+ }
+ if (lifc.lifc_len < (lifn.lifn_count - 1) * sizeof (*lifrp))
+ break;
+ free(lifrp);
+ lifn.lifn_count <<= 1;
+ }
+ (void) close(fd);
+
+ *ifr_ret = lifrp;
+
+ return (lifc.lifc_len / sizeof (*lifrp));
+}
+
+static size_t
+nbytes(const struct lifreq *lifrp, int nlif, size_t socklen)
+{
+ size_t len = 0;
+ size_t slen;
+
+ while (nlif > 0) {
+ slen = strlen(lifrp->lifr_name) + 1;
+ len += sizeof (struct ifaddrs) + ((slen + 3) & ~3);
+ len += 3 * socklen;
+ lifrp++;
+ nlif--;
+ }
+ return (len);
+}
+
+static struct sockaddr *
+addrcpy(struct sockaddr_storage *addr, char **bufp)
+{
+ char *buf = *bufp;
+ size_t len;
+
+ len = addr->ss_family == AF_INET ? sizeof (struct sockaddr_in) :
+ sizeof (struct sockaddr_in6);
+ (void) memcpy(buf, addr, len);
+ *bufp = buf + len;
+ return ((struct sockaddr *)buf);
+}
+
+static int
+populate(struct ifaddrs *ifa, int fd, struct lifreq *lifrp, int nlif, int af,
+ char **bufp)
+{
+ char *buf = *bufp;
+ size_t slen;
+
+ while (nlif > 0) {
+ ifa->ifa_next = (nlif > 1) ? ifa + 1 : NULL;
+ (void) strcpy(ifa->ifa_name = buf, lifrp->lifr_name);
+ slen = strlen(lifrp->lifr_name) + 1;
+ buf += (slen + 3) & ~3;
+ if (ioctl(fd, SIOCGLIFFLAGS, lifrp) == -1)
+ ifa->ifa_flags = 0;
+ else
+ ifa->ifa_flags = lifrp->lifr_flags;
+ if (ioctl(fd, SIOCGLIFADDR, lifrp) == -1)
+ ifa->ifa_addr = NULL;
+ else
+ ifa->ifa_addr = addrcpy(&lifrp->lifr_addr, &buf);
+ if (ioctl(fd, SIOCGLIFNETMASK, lifrp) == -1)
+ ifa->ifa_netmask = NULL;
+ else
+ ifa->ifa_netmask = addrcpy(&lifrp->lifr_addr, &buf);
+ if (ifa->ifa_flags & IFF_POINTOPOINT) {
+ if (ioctl(fd, SIOCGLIFDSTADDR, lifrp) == -1)
+ ifa->ifa_dstaddr = NULL;
+ else
+ ifa->ifa_dstaddr =
+ addrcpy(&lifrp->lifr_dstaddr, &buf);
+ } else if (ifa->ifa_flags & IFF_BROADCAST) {
+ if (ioctl(fd, SIOCGLIFBRDADDR, lifrp) == -1)
+ ifa->ifa_broadaddr = NULL;
+ else
+ ifa->ifa_broadaddr =
+ addrcpy(&lifrp->lifr_broadaddr, &buf);
+ } else {
+ ifa->ifa_dstaddr = NULL;
+ }
+
+ ifa++;
+ nlif--;
+ lifrp++;
+ }
+ *bufp = buf;
+ return (0);
+}
+
+int
+getifaddrs(struct ifaddrs **ifap)
+{
+ int fd4, fd6;
+ int nif4, nif6 = 0;
+ struct lifreq *ifr4 = NULL;
+ struct lifreq *ifr6 = NULL;
+ struct ifaddrs *ifa = NULL;
+ char *buf;
+
+ if ((fd4 = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
+ return (-1);
+ if ((fd6 = socket(AF_INET6, SOCK_DGRAM, 0)) == -1 &&
+ errno != EAFNOSUPPORT) {
+ (void) close(fd4);
+ return (-1);
+ }
+
+ if ((nif4 = get_lifreq(fd4, &ifr4)) == -1 ||
+ (fd6 != -1 && (nif6 = get_lifreq(fd6, &ifr6)) == -1))
+ goto failure;
+
+ if (nif4 == 0 && nif6 == 0) {
+ *ifap = NULL;
+ return (0);
+ }
+
+ ifa = malloc(nbytes(ifr4, nif4, sizeof (struct sockaddr_in)) +
+ nbytes(ifr6, nif6, sizeof (struct sockaddr_in6)));
+ if (ifa == NULL)
+ goto failure;
+
+ buf = (char *)(ifa + nif4 + nif6);
+
+ if (populate(ifa, fd4, ifr4, nif4, AF_INET, &buf) == -1)
+ goto failure;
+ if (nif4 > 0 && nif6 > 0)
+ ifa[nif4 - 1].ifa_next = ifa + nif4;
+ if (populate(ifa + nif4, fd6, ifr6, nif6, AF_INET6, &buf) == -1)
+ goto failure;
+
+ return (0);
+
+failure:
+ free(ifa);
+ (void) close(fd4);
+ if (fd6 != -1)
+ (void) close(fd6);
+ free(ifr4);
+ free(ifr6);
+ return (-1);
+}
+
+void
+freeifaddrs(struct ifaddrs *ifa)
+{
+ free(ifa);
+}
diff --git a/missing/ifaddrs.h b/missing/ifaddrs.h
new file mode 100644
index 0000000..0bf5f92
--- /dev/null
+++ b/missing/ifaddrs.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2006 WIDE Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+
+#undef ifa_broadaddr
+#undef ifa_dstaddr
+struct ifaddrs {
+ struct ifaddrs *ifa_next; /* Pointer to next struct */
+ char *ifa_name; /* Interface name */
+ uint64_t ifa_flags; /* Interface flags */
+ struct sockaddr *ifa_addr; /* Interface address */
+ struct sockaddr *ifa_netmask; /* Interface netmask */
+ struct sockaddr *ifa_dstaddr; /* P2P interface destination */
+};
+#define ifa_broadaddr ifa_dstaddr
+
+extern int getifaddrs(struct ifaddrs **);
+extern void freeifaddrs(struct ifaddrs *);
diff --git a/missing/sys/queue.h b/missing/sys/queue.h
new file mode 100644
index 0000000..027f495
--- /dev/null
+++ b/missing/sys/queue.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Adapted from FreeBSD sys/queue.h by James Carlson <james.d.carlson@sun.com>
+ *
+ * @(#)queue.h 8.5 (Berkeley) 8/20/94
+ * $FreeBSD: src/sys/sys/queue.h,v 1.32.2.6 2001/12/18 10:09:02 ru Exp $
+ */
+
+/*
+ * Tail queue declarations.
+ */
+#define TAILQ_HEAD(name, type) \
+struct name { \
+ struct type *tqh_first; /* first element */ \
+ struct type **tqh_last; /* addr of last next element */ \
+}
+
+#define TAILQ_ENTRY(type) \
+struct { \
+ struct type *tqe_next; /* next element */ \
+ struct type **tqe_prev; /* address of previous next element */ \
+}
+
+/*
+ * Tail queue functions.
+ */
+#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
+
+#define TAILQ_FIRST(head) ((head)->tqh_first)
+
+#define TAILQ_INIT(head) do { \
+ TAILQ_FIRST((head)) = NULL; \
+ (head)->tqh_last = &TAILQ_FIRST((head)); \
+} while (0)
+
+#define TAILQ_INSERT_HEAD(head, elm, field) do { \
+ if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \
+ TAILQ_FIRST((head))->field.tqe_prev = \
+ &TAILQ_NEXT((elm), field); \
+ else \
+ (head)->tqh_last = &TAILQ_NEXT((elm), field); \
+ TAILQ_FIRST((head)) = (elm); \
+ (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \
+} while (0)
+
+#define TAILQ_INSERT_TAIL(head, elm, field) do { \
+ TAILQ_NEXT((elm), field) = NULL; \
+ (elm)->field.tqe_prev = (head)->tqh_last; \
+ *(head)->tqh_last = (elm); \
+ (head)->tqh_last = &TAILQ_NEXT((elm), field); \
+} while (0)
+
+#define TAILQ_LAST(head, headname) \
+ (*(((struct headname *)((head)->tqh_last))->tqh_last))
+
+#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
+
+#define TAILQ_REMOVE(head, elm, field) do { \
+ if ((TAILQ_NEXT((elm), field)) != NULL) \
+ TAILQ_NEXT((elm), field)->field.tqe_prev = \
+ (elm)->field.tqe_prev; \
+ else \
+ (head)->tqh_last = (elm)->field.tqe_prev; \
+ *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \
+} while (0)
+
+/*
+ * List declarations.
+ */
+#define LIST_HEAD(name, type) \
+struct name { \
+ struct type *lh_first; /* first element */ \
+}
+
+#define LIST_ENTRY(type) \
+struct { \
+ struct type *le_next; /* next element */ \
+ struct type **le_prev; /* address of previous next element */ \
+}
+
+/*
+ * List functions.
+ */
+
+#define LIST_EMPTY(head) ((head)->lh_first == NULL)
+
+#define LIST_FIRST(head) ((head)->lh_first)
+
+#define LIST_INIT(head) do { \
+ LIST_FIRST((head)) = NULL; \
+} while (0)
+
+#define LIST_INSERT_HEAD(head, elm, field) do { \
+ if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \
+ LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
+ LIST_FIRST((head)) = (elm); \
+ (elm)->field.le_prev = &LIST_FIRST((head)); \
+} while (0)
+
+#define LIST_NEXT(elm, field) ((elm)->field.le_next)
+
+#define LIST_REMOVE(elm, field) do { \
+ if (LIST_NEXT((elm), field) != NULL) \
+ LIST_NEXT((elm), field)->field.le_prev = \
+ (elm)->field.le_prev; \
+ *(elm)->field.le_prev = LIST_NEXT((elm), field); \
+} while (0)
diff --git a/missing/warnx.c b/missing/warnx.c
new file mode 100644
index 0000000..75e1a96
--- /dev/null
+++ b/missing/warnx.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2006 WIDE Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+void
+err(int retv, const char *str)
+{
+ (void) fprintf(stderr, "%s\n", str);
+ exit(retv);
+}
+
+void
+errx(int retv, const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ (void) vfprintf(stderr, fmt, args);
+ va_end(args);
+ exit(retv);
+}
+
+void
+warnx(const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ (void) vfprintf(stderr, fmt, args);
+ va_end(args);
+}