howl patch for better BSD support
Andrea Campi
andrea+freebsd_net at webcom.it
Fri Jan 7 08:57:13 PST 2005
Hi,
as promised, I've been working on improving howl. I've been in touch
with the authors, so in fact this is also resulting in cross-platform
fixes.
You can find the results of my work so far either attached to this
email (provided they get through mailing list filters) or at this URL:
http://www.webcom.it/ports/howl/files/patch-BSD ; you can just drop in
the ports/net/howl/files directory.
The current status is that autoipd and nifd are working (for people not
familiar with howl, these deal with address negotiation and interface
status monitoring respectively). I haven't done anything with
mDNSResponder apart from checking it still compiles.
There's a lot of stuff to cleanup. Style sucks beyond telling, but that's
because at this stage I'm striving to keep the sources diffable to their
Linux counterpart. This will change at a later stage.
Could some kind folk familiar look at the diff and maybe try it? Apart
from feedback of the "it works/doesn't" kind, I'm also looking for
guidance on the preferred way to do things.
On this note: I'm still using SIOCAIFADDR, as mentioned before, to add
a new IP address. I'm still not sure on how to do it best.
The way things currently work is:
- when autoipd starts, it figures out a random IP, using the MAC
address as a seed. It starts probing for someone else already using it,
and if nobody is, it start announcing it;
- autoipd then starts monitoring for conflicts, and when it detects
one it either tries to defend or picks a different one;
- nifd is charged with monitoring link state changes; if it detects
one, or it notices that an interface changed IP address, it signals
autoipd to go through all the process again.
Now all this all nice, except it doesn't work! If I manually change
the interface address, to simulate what for instance dhclient would do,
nifd notices and signals autoipd, who then goes, picks a new IP address
and sets it!
This happens because nothing is checking whether the IP is valid before
letting autoipd loose. The problem is that this is too hard to do in the
general case; however, I think we can reasonably deal with the common
DHCP+zeroconf case by using dhclient-script(8). Basically, I'd start
autoipd on EXPIRE or FAIL and kill it on BOUND.
I will go this way, at least for a beginning, unless someone with more
experience is willing to guide me. I do plan on creating a sample script
that could be provided in the port to give a complete solution.
Thought?
Bye,
Andrea
--
Intel: where Quality is job number 0.9998782345!
-------------- next part --------------
Index: configure
===================================================================
RCS file: /home/CVS/howl/work/howl-0.9.7/configure,v
retrieving revision 1.1.1.1
retrieving revision 1.3
diff -u -r1.1.1.1 -r1.3
--- configure 12 Dec 2004 08:24:26 -0000 1.1.1.1
+++ configure 12 Dec 2004 09:16:29 -0000 1.3
@@ -8516,6 +8516,17 @@
PLATFORM_LIBS="-framework CoreFoundation"
HOWL_MAN_PAGES=
;;
+ *-*-freebsd*)
+ SRC_SUBDIRS="lib mDNSResponder autoipd nifd"
+ LIB_SUBDIRS="howl mDNSResponder"
+ HOWL_LIB_SUBDIRS="Posix NotOSX"
+ HOWL_LIB_OBJECTS='posix_salt.lo posix_socket.lo posix_time.lo posix_signal.lo posix_interface.lo notosx_mdns_stub.lo'
+ MDNSRESPONDER_LIB_SUBDIRS="Posix"
+ MDNSRESPONDER_LIB_OBJECTS='posix_mdns.lo'
+ AUTOIPD_EXTRA_OBJECTS='freebsd_autoip.lo posix_main.lo'
+ PLATFORM_LIBS=-lpthread
+ HOWL_MAN_PAGES='mDNSResponder.8 autoipd.8 nifd.8'
+ ;;
*-*-linux*)
SRC_SUBDIRS="lib mDNSResponder autoipd nifd"
LIB_SUBDIRS="howl mDNSResponder"
@@ -8562,7 +8573,7 @@
- ac_config_files="$ac_config_files Makefile include/Makefile include/salt/Makefile include/corby/Makefile include/discovery/Makefile include/rendezvous/Makefile src/Makefile src/lib/Makefile src/lib/howl/Makefile src/lib/howl/MacOSX/Makefile src/lib/howl/Posix/Makefile src/lib/howl/Win32/Makefile src/lib/howl/NotOSX/Makefile src/lib/mDNSResponder/Makefile src/lib/mDNSResponder/Posix/Makefile src/lib/mDNSResponder/Win32/Makefile src/mDNSResponder/Makefile src/mDNSResponder/Posix/Makefile src/mDNSResponder/Win32/Makefile src/autoipd/Makefile src/autoipd/Posix/Makefile src/autoipd/Linux/Makefile src/nifd/Makefile test/Makefile test/step/Makefile samples/Makefile samples/console/Makefile samples/console/publish/Makefile samples/console/browse/Makefile samples/console/resolve/Makefile samples/console/query/Makefile samples/Win32/Makefile samples/Win32/IEBar/Makefile docs/Makefile etc/Makefile howl.pc"
+ ac_config_files="$ac_config_files Makefile include/Makefile include/salt/Makefile include/corby/Makefile include/discovery/Makefile include/rendezvous/Makefile src/Makefile src/lib/Makefile src/lib/howl/Makefile src/lib/howl/MacOSX/Makefile src/lib/howl/Posix/Makefile src/lib/howl/Win32/Makefile src/lib/howl/NotOSX/Makefile src/lib/mDNSResponder/Makefile src/lib/mDNSResponder/Posix/Makefile src/lib/mDNSResponder/Win32/Makefile src/mDNSResponder/Makefile src/mDNSResponder/Posix/Makefile src/mDNSResponder/Win32/Makefile src/autoipd/Makefile src/autoipd/Posix/Makefile src/autoipd/BSD/Makefile src/autoipd/Linux/Makefile src/nifd/Makefile test/Makefile test/step/Makefile samples/Makefile samples/console/Makefile samples/console/publish/Makefile samples/console/browse/Makefile samples/console/resolve/Makefile samples/console/query/Makefile samples/Win32/Makefile samples/Win32/IEBar/Makefile docs/Makefile etc/Makefile howl.pc"
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
# tests run on this system so they can be shared between configure
@@ -9125,6 +9136,7 @@
"src/mDNSResponder/Win32/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/mDNSResponder/Win32/Makefile" ;;
"src/autoipd/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/autoipd/Makefile" ;;
"src/autoipd/Posix/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/autoipd/Posix/Makefile" ;;
+ "src/autoipd/BSD/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/autoipd/BSD/Makefile" ;;
"src/autoipd/Linux/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/autoipd/Linux/Makefile" ;;
"src/nifd/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/nifd/Makefile" ;;
"test/Makefile" ) CONFIG_FILES="$CONFIG_FILES test/Makefile" ;;
Index: src/autoipd/Makefile.in
===================================================================
RCS file: /home/CVS/howl/work/howl-0.9.7/src/autoipd/Makefile.in,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- src/autoipd/Makefile.in 12 Dec 2004 08:24:39 -0000 1.1.1.1
+++ src/autoipd/Makefile.in 12 Dec 2004 09:16:29 -0000 1.2
@@ -96,13 +96,13 @@
am__include = @am__include@
am__quote = @am__quote@
install_sh = @install_sh@
-SUBDIRS = Posix Linux
+SUBDIRS = Posix BSD Linux
INCLUDES = -I$(top_srcdir)/include/
LDADD = $(AUTOIPD_EXTRA_OBJECTS) $(top_srcdir)/src/lib/howl/libhowl.la $(PLATFORM_LIBS)
AM_LDFLAGS = -static
bin_PROGRAMS = autoipd
autoipd_SOURCES = autoip.c autoip.h
-EXTRA_autoipd_SOURCES = Linux/linux_autoip.c Posix/posix_main.c
+EXTRA_autoipd_SOURCES = BSD/freebsd_autoip.c Linux/linux_autoip.c Posix/posix_main.c
autoipd_DEPENDENCIES = $(AUTOIPD_EXTRA_OBJECTS)
subdir = src/autoipd
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
@@ -124,6 +124,7 @@
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@AMDEP_TRUE at DEP_FILES = ./$(DEPDIR)/autoip.Po \
+ at AMDEP_TRUE@ ./$(DEPDIR)/freebsd_autoip.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/linux_autoip.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/posix_main.Po
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
@@ -182,6 +183,7 @@
echo " rm -f $$p $$f"; \
rm -f $$p $$f ; \
done
+freebsd_autoip.$(OBJEXT): BSD/freebsd_autoip.c
linux_autoip.$(OBJEXT): Linux/linux_autoip.c
posix_main.$(OBJEXT): Posix/posix_main.c
autoipd$(EXEEXT): $(autoipd_OBJECTS) $(autoipd_DEPENDENCIES)
@@ -195,6 +197,7 @@
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/autoip.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/freebsd_autoip.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/linux_autoip.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/posix_main.Po at am__quote@
@@ -219,6 +222,24 @@
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(LTCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<
+freebsd_autoip.o: BSD/freebsd_autoip.c
+ at AMDEP_TRUE@ source='BSD/freebsd_autoip.c' object='freebsd_autoip.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@ depfile='$(DEPDIR)/freebsd_autoip.Po' tmpdepfile='$(DEPDIR)/freebsd_autoip.TPo' @AMDEPBACKSLASH@
+ at AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o freebsd_autoip.o `test -f 'BSD/freebsd_autoip.c' || echo '$(srcdir)/'`BSD/freebsd_autoip.c
+
+freebsd_autoip.obj: BSD/freebsd_autoip.c
+ at AMDEP_TRUE@ source='BSD/freebsd_autoip.c' object='freebsd_autoip.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@ depfile='$(DEPDIR)/freebsd_autoip.Po' tmpdepfile='$(DEPDIR)/freebsd_autoip.TPo' @AMDEPBACKSLASH@
+ at AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o freebsd_autoip.obj `cygpath -w BSD/freebsd_autoip.c`
+
+freebsd_autoip.lo: BSD/freebsd_autoip.c
+ at AMDEP_TRUE@ source='BSD/freebsd_autoip.c' object='freebsd_autoip.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@ depfile='$(DEPDIR)/freebsd_autoip.Plo' tmpdepfile='$(DEPDIR)/freebsd_autoip.TPlo' @AMDEPBACKSLASH@
+ at AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o freebsd_autoip.lo `test -f 'BSD/freebsd_autoip.c' || echo '$(srcdir)/'`BSD/freebsd_autoip.c
+
linux_autoip.o: Linux/linux_autoip.c
@AMDEP_TRUE@ source='Linux/linux_autoip.c' object='linux_autoip.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/linux_autoip.Po' tmpdepfile='$(DEPDIR)/linux_autoip.TPo' @AMDEPBACKSLASH@
Index: src/autoipd/autoip.c
===================================================================
RCS file: /home/CVS/howl/work/howl-0.9.7/src/autoipd/autoip.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- src/autoipd/autoip.c 12 Dec 2004 08:24:39 -0000 1.1.1.1
+++ src/autoipd/autoip.c 12 Dec 2004 09:09:50 -0000 1.2
@@ -212,6 +212,12 @@
sw_debug(SW_LOG_VERBOSE, "IDLE\n");
/*
+ * initialize the MAC address
+ */
+ err = sw_network_interface_mac_address(self->m_nif, &self->m_mac_addr);
+ sw_check_okay(err, exit);
+
+ /*
* initialize the ip address
*/
err = sw_autoip_network_interface_make_initial_ip_address(self);
Index: src/lib/howl/Posix/posix_interface.c
===================================================================
RCS file: /home/CVS/howl/work/howl-0.9.7/src/lib/howl/Posix/posix_interface.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 posix_interface.c
--- src/lib/howl/Posix/posix_interface.c 12 Dec 2004 08:24:31 -0000 1.1.1.1
+++ src/lib/howl/Posix/posix_interface.c 7 Jan 2005 15:39:58 -0000
@@ -45,6 +45,14 @@
# include <linux/ethtool.h>
#endif
+#if defined(__FreeBSD__)
+#include <sys/sysctl.h>
+#include <net/ethernet.h>
+#include <net/if_types.h>
+#include <net/if_media.h>
+#include <net/route.h>
+#endif
+
#ifndef SIOCGIFCONF
# include <sys/sockio.h>
#endif
@@ -231,13 +240,16 @@
sw_network_interface self,
sw_bool * islinked)
{
-#if defined(__linux__)
int fd;
- struct ifreq ifr;
int r;
- struct ethtool_value edata;
+ struct ifreq ifr;
int res;
sw_result err = SW_OKAY;
+#if defined(__linux__)
+ struct ethtool_value edata;
+#elif defined(__FreeBSD__)
+ struct ifmediareq ifmr;
+#endif
sw_assert(self != NULL); /* must be initialized */
sw_assert(islinked != NULL); /* must be allocated */
@@ -251,6 +263,19 @@
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, self->m_name, sizeof(ifr.ifr_name) - 1);
+ /* get the interface flags */
+ res = ioctl(fd, SIOCGIFFLAGS, &ifr);
+ err = sw_translate_error(res == 0, errno);
+ sw_check_okay_log(err, exit);
+
+ /* if it's down, we can't have a link */
+ if ((ifr.ifr_flags & IFF_UP) != IFF_UP)
+ {
+ *islinked = SW_FALSE;
+ goto exit;
+ }
+
+#if defined(__linux__)
edata.cmd = ETHTOOL_GLINK;
ifr.ifr_data = (caddr_t) &edata;
@@ -259,15 +284,25 @@
sw_check_okay_log(err, exit);
*islinked = edata.data ? SW_TRUE : SW_FALSE;
+#elif defined(__FreeBSD__)
+ memset(&ifmr, 0, sizeof(ifmr));
+ strncpy(ifmr.ifm_name, self->m_name, sizeof(ifmr.ifm_name) - 1);
+
+ res = ioctl(fd, SIOCGIFMEDIA, (caddr_t)&ifmr);
+ err = sw_translate_error(res == 0, errno);
+ sw_check_okay_log(err, exit);
+
+ if (!ifmr.ifm_status & IFM_AVALID)
+ goto exit;
+
+ *islinked = (ifmr.ifm_status & IFM_ACTIVE)? SW_TRUE : SW_FALSE;
+#endif
exit:
close(fd);
return err;
-#else
- return SW_OKAY;
-#endif
}
@@ -280,6 +315,77 @@
}
+#if defined(__FreeBSD__)
+static int
+get_interface_lladdr_by_index(unsigned int ifindex, sw_mac_address *m_mac_addr) {
+
+ int mib[6];
+ struct if_msghdr *ifm;
+ struct sockaddr_dl *sdl;
+
+ int needed, count = 0;
+ int res;
+ sw_result err = SW_OKAY;
+
+retry:
+ mib[0] = CTL_NET;
+ mib[1] = PF_ROUTE;
+ mib[2] = 0;
+ mib[3] = 0; /* address family */
+ mib[4] = NET_RT_IFLIST;
+ mib[5] = ifindex; /* interface index */
+
+ /* determine how much memory is needed */
+ res = sysctl(mib, 6, NULL, &needed, NULL, 0);
+ err = sw_translate_error(res == 0, errno);
+ sw_check_okay_log(err, exit);
+
+ ifm = (struct if_msghdr *)malloc(needed);
+ err = sw_translate_error(ifm != NULL, SW_E_MEM);
+ sw_check_okay_log(err, exit);
+
+ /* retrieve information */
+ res = sysctl(mib, 6, ifm, &needed, NULL, 0);
+ if (res < 0) {
+ if (errno == ENOMEM && count++ < 10) {
+ sw_debug(SW_LOG_WARNING,
+ "Routing table grew, retrying");
+ free(ifm);
+ sleep(1);
+ goto retry;
+ }
+
+ err = sw_translate_error(res == 0, errno);
+ sw_check_okay_log(err, exit);
+ }
+
+ sw_debug(SW_LOG_ERROR, "ifm->ifm_type %d=%d\n",
+ ifm->ifm_type, RTM_IFINFO);
+ if (ifm->ifm_type != RTM_IFINFO)
+ return 0;
+
+ if (ifm->ifm_data.ifi_datalen == 0)
+ ifm->ifm_data.ifi_datalen = sizeof(struct if_data);
+
+ sdl = (struct sockaddr_dl *)((char *)ifm + sizeof(struct if_msghdr) -
+ sizeof(struct if_data) + ifm->ifm_data.ifi_datalen);
+
+ sw_debug(SW_LOG_ERROR, "sdl->sdl_alen %d\n", sdl->sdl_alen);
+ if (sdl->sdl_alen > 1) {
+ if (sdl->sdl_type == IFT_ETHER &&
+ sdl->sdl_alen == ETHER_ADDR_LEN) {
+ sw_memcpy(m_mac_addr->m_id,
+ (struct ether_addr *)LLADDR(sdl),
+ sizeof(struct ether_addr));
+ return 1;
+ }
+ }
+
+exit:
+ return 0;
+}
+#endif
+
static sw_result
sw_posix_network_interface_init_from_name(
sw_posix_network_interface nif,
@@ -332,6 +438,7 @@
sw_debug(SW_LOG_VERBOSE, "got ip address: %s\n", tmpname);
/* mac address */
+#if !defined(__FreeBSD__)
#if defined(SIOCGIFHWADDR)
res = ioctl(sock, SIOCGIFHWADDR, &ifr);
err = sw_translate_error(res == 0, errno);
@@ -343,10 +450,17 @@
sw_check_okay_log(err, exit);
sw_memcpy(nif->m_super.m_mac_address.m_id, (sw_uint8*)(ifr.ifr_ifru.ifru_enaddr), sizeof(sw_mac_address));
#endif
+#endif
/* index */
nif->m_super.m_index = if_nametoindex(ifr.ifr_name);
+#if defined(__FreeBSD__)
+ res = get_interface_lladdr_by_index(nif->m_super.m_index, &nif->m_super.m_mac_address);
+ err = sw_translate_error(res == 1, SW_E_UNKNOWN);
+ sw_check_okay_log(err, exit);
+#endif
+
/* initialize link status field */
sw_network_interface_link_status(&nif->m_super, &(nif->m_super.m_linked));
@@ -387,6 +501,12 @@
/* ip address */
sw_ipv4_address_init_from_saddr(&(nif->m_super.m_ipv4_address), ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr);
+#if defined(__FreeBSD__)
+ res = get_interface_lladdr_by_index(nif->m_super.m_index, &nif->m_super.m_mac_address);
+ sw_debug(SW_LOG_ERROR, "%d %s res %d\n", nif->m_super.m_index, ifr->ifr_name, res);
+ err = sw_translate_error(res == 1, SW_E_UNKNOWN);
+ sw_check_okay_log(err, exit);
+#else
/* get a socket for ioctling */
err = sw_posix_inet_socket(&sock);
sw_check_okay(err, exit);
@@ -403,6 +523,7 @@
sw_check_okay_log(err, exit);
sw_memcpy(nif->m_super.m_mac_address.m_id, (sw_uint8*)(ifr->ifr_ifru.ifru_enaddr), sizeof(sw_mac_address));
#endif
+#endif
/* initialize link status field */
sw_network_interface_link_status(&nif->m_super, &(nif->m_super.m_linked));
@@ -515,6 +636,7 @@
sw_uint32 * nifc,
sw_network_interface ** nifv)
{
+#if defined(__linux__)
FILE * fh;
char buf[512];
int procnetdev_vsn;
@@ -585,6 +707,132 @@
}
return err;
+#elif defined(__FreeBSD__)
+ int mib[6];
+ struct if_msghdr *ifm, *nextifm;
+ struct ifa_msghdr *ifam;
+ int addrcount;
+ struct sockaddr_dl *sdl;
+ char name[IFNAMSIZ];
+ sw_posix_network_interface nif;
+ sw_ipv4_address ipaddr;
+
+ int needed, count = 0;
+ char *buf, *lim, *next;
+ int res;
+ sw_result err = SW_OKAY;
+
+ /* TODO hard code 10 for now */
+ /* allocate nifv */
+ *nifv = (sw_network_interface*) sw_malloc(10 * sizeof(sw_network_interface));
+ err = sw_translate_error(*nifv, SW_E_MEM);
+ sw_check_okay_log(err, exit);
+
+ *nifc = 0;
+
+retry:
+ mib[0] = CTL_NET;
+ mib[1] = PF_ROUTE;
+ mib[2] = 0;
+ mib[3] = 0;
+ mib[4] = NET_RT_IFLIST;
+ mib[5] = 0;
+
+ /* determine how much memory is needed */
+ res = sysctl(mib, 6, NULL, &needed, NULL, 0);
+ err = sw_translate_error(res == 0, errno);
+ sw_check_okay_log(err, exit);
+
+ buf = malloc(needed);
+ err = sw_translate_error(buf != NULL, SW_E_MEM);
+ sw_check_okay_log(err, exit);
+
+ /* retrieve information */
+ res = sysctl(mib, 6, buf, &needed, NULL, 0);
+ if (res < 0) {
+ if (errno == ENOMEM && count++ < 10) {
+ warnx("Routing table grew, retrying");
+ free(ifm);
+ sleep(1);
+ goto retry;
+ }
+
+ err = sw_translate_error(res == 0, errno);
+ sw_check_okay_log(err, exit);
+ }
+
+ lim = buf + needed;
+ next = buf;
+ while (next < lim) {
+ ifm = (struct if_msghdr *)next;
+
+ if (ifm->ifm_type == RTM_IFINFO) {
+ if (ifm->ifm_data.ifi_datalen == 0)
+ ifm->ifm_data.ifi_datalen = sizeof(struct if_data);
+
+ sdl = (struct sockaddr_dl *)((char *)ifm +
+ sizeof(struct if_msghdr) -
+ sizeof(struct if_data) +
+ ifm->ifm_data.ifi_datalen);
+ } else {
+ sw_debug(SW_LOG_ERROR,
+ "out of sync parsing NET_RT_IFLIST\n");
+ err = SW_E_INIT;
+ goto exit;
+ }
+
+ next += ifm->ifm_msglen;
+ ifam = NULL;
+ addrcount = 0;
+ while (next < lim) {
+ nextifm = (struct if_msghdr *)next;
+ if (nextifm->ifm_type != RTM_NEWADDR)
+ break;
+
+ if (ifam == NULL)
+ ifam = (struct ifa_msghdr *)nextifm;
+
+ next += nextifm->ifm_msglen;
+ }
+
+ memcpy(name, sdl->sdl_data,
+ sizeof(name) < sdl->sdl_nlen ?
+ sizeof(name)-1 : sdl->sdl_nlen);
+ name[sizeof(name) < sdl->sdl_nlen ?
+ sizeof(name)-1 : sdl->sdl_nlen] = '\0';
+
+ sw_debug(SW_LOG_ERROR, "name=%s", name);
+
+ if ((ifm->ifm_flags & IFF_BROADCAST) == 0)
+ {
+ continue;
+ }
+
+ /* create a new netif */
+ err = sw_network_interface_init((sw_network_interface*)&nif);
+ sw_check_okay(err, exit);
+
+ /* initialize fields */
+ err = sw_posix_network_interface_init_from_name(nif, name);
+ sw_check_okay(err, exit);
+
+ err = sw_network_interface_ipv4_address((sw_network_interface)nif, &ipaddr);
+ sw_check_okay(err, exit);
+
+ (*nifv)[(*nifc)++] = (sw_network_interface)nif;
+ }
+
+ err = SW_OKAY;
+
+exit:
+
+ if (err && *nifv)
+ {
+ sw_network_interfaces_fina(*nifc, *nifv);
+ }
+
+ return err;
+#endif
}
sw_result
diff -urN empty/Makefile src/autoipd/BSD/Makefile
--- src/autoipd/BSD/Makefile Thu Jan 1 01:00:00 1970
+++ src/autoipd/BSD/Makefile Sun Dec 12 10:36:27 2004
@@ -0,0 +1,232 @@
+# Makefile.in generated by automake 1.6.3 from Makefile.am.
+# src/autoipd/BSD/Makefile. Generated from Makefile.in by configure.
+
+# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
+# Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = /bin/sh
+
+srcdir = .
+top_srcdir = ../../..
+
+prefix = /usr/local
+exec_prefix = ${prefix}
+
+bindir = ${exec_prefix}/bin
+sbindir = ${exec_prefix}/sbin
+libexecdir = ${exec_prefix}/libexec
+datadir = ${prefix}/share
+sysconfdir = ${prefix}/etc
+sharedstatedir = ${prefix}/com
+localstatedir = ${prefix}/var
+libdir = ${exec_prefix}/lib
+infodir = ${prefix}/info
+mandir = ${prefix}/man
+includedir = ${prefix}/include
+oldincludedir = /usr/include
+pkgdatadir = $(datadir)/howl
+pkglibdir = $(libdir)/howl
+pkgincludedir = $(includedir)/howl
+top_builddir = ../../..
+
+ACLOCAL = ${SHELL} /usr/ports/net/howl/work/howl-0.9.7/missing --run aclocal-1.6
+AUTOCONF = ${SHELL} /usr/ports/net/howl/work/howl-0.9.7/missing --run autoconf
+AUTOMAKE = ${SHELL} /usr/ports/net/howl/work/howl-0.9.7/missing --run automake-1.6
+AUTOHEADER = ${SHELL} /usr/ports/net/howl/work/howl-0.9.7/missing --run autoheader
+
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = /usr/bin/install -c
+INSTALL_PROGRAM = install -s -m 555
+INSTALL_DATA = install -m 444
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_SCRIPT = install -m 555
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = s,x,x,
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_alias =
+host_triplet = i386-portbld-freebsd5.3
+
+EXEEXT =
+OBJEXT = o
+PATH_SEPARATOR = :
+AMTAR = ${SHELL} /usr/ports/net/howl/work/howl-0.9.7/missing --run tar
+AS = @AS@
+AUTOIPD_EXTRA_OBJECTS = freebsd_autoip.lo posix_main.lo
+AWK = nawk
+CC = cc
+CXX = c++
+DEPDIR = .deps
+DLLTOOL = @DLLTOOL@
+ECHO = echo
+HOWL_LIBRARY_VERSION = 1:0:0
+HOWL_LIB_OBJECTS = posix_salt.lo posix_socket.lo posix_time.lo posix_signal.lo posix_interface.lo notosx_mdns_stub.lo
+HOWL_LIB_SUBDIRS = Posix NotOSX
+HOWL_MAN_PAGES = mDNSResponder.8 autoipd.8 nifd.8
+HOWL_RELEASE =
+INSTALL_STRIP_PROGRAM = ${SHELL} $(install_sh) -c -s
+LIBTOOL = $(SHELL) /usr/local/bin/libtool15
+LIB_SUBDIRS = howl mDNSResponder
+LN_S = ln -s
+MDNSRESPONDER_LIBRARY_VERSION = 0:0:0
+MDNSRESPONDER_LIB_OBJECTS = posix_mdns.lo
+MDNSRESPONDER_LIB_SUBDIRS = Posix
+OBJDUMP = @OBJDUMP@
+PACKAGE = howl
+PLATFORM_LIBS = -lpthread
+RANLIB = ranlib
+SRC_SUBDIRS = lib mDNSResponder autoipd nifd
+STRIP = strip
+VERSION = 0.9.7
+am__include = include
+am__quote =
+install_sh = /usr/ports/net/howl/work/howl-0.9.7/install-sh
+sources_h = freebsd_autoip.h
+sources_c = freebsd_autoip.c
+DIST_SOURCES = $(sources_h) $(sources_c) Makefile.am
+INCLUDES = -I$(top_srcdir)/include/
+subdir = src/autoipd/BSD
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/include/howl_config.h
+CONFIG_CLEAN_FILES =
+DIST_COMMON = Makefile.am Makefile.in
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4)
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/autoipd/BSD/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+ -rm -f libtool
+uninstall-info-am:
+tags: TAGS
+TAGS:
+
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+
+top_distdir = ../../..
+distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
+
+distdir: $(DISTFILES)
+ @list='$(DISTFILES)'; for file in $$list; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+ dir="/$$dir"; \
+ $(mkinstalldirs) "$(distdir)$$dir"; \
+ else \
+ dir=''; \
+ fi; \
+ if test -d $$d/$$file; then \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile
+
+installdirs:
+
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -rm -f Makefile $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+
+distclean-am: clean-am distclean-generic distclean-libtool
+
+dvi: dvi-am
+
+dvi-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+uninstall-am: uninstall-info-am
+
+.PHONY: all all-am check check-am clean clean-generic clean-libtool \
+ distclean distclean-generic distclean-libtool distdir dvi \
+ dvi-am info info-am install install-am install-data \
+ install-data-am install-exec install-exec-am install-info \
+ install-info-am install-man install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-generic \
+ mostlyclean-libtool uninstall uninstall-am uninstall-info-am
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff -urN empty/Makefile.in src/autoipd/BSD/Makefile.in
--- src/autoipd/BSD/Makefile.in Thu Jan 1 01:00:00 1970
+++ src/autoipd/BSD/Makefile.in Sun Dec 12 10:35:09 2004
@@ -0,0 +1,232 @@
+# Makefile.in generated by automake 1.6.3 from Makefile.am.
+# @configure_input@
+
+# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
+# Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+ at SET_MAKE@
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ../../..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = @program_transform_name@
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_alias = @host_alias@
+host_triplet = @host@
+
+EXEEXT = @EXEEXT@
+OBJEXT = @OBJEXT@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+AMTAR = @AMTAR@
+AS = @AS@
+AUTOIPD_EXTRA_OBJECTS = @AUTOIPD_EXTRA_OBJECTS@
+AWK = @AWK@
+CC = @CC@
+CXX = @CXX@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+ECHO = @ECHO@
+HOWL_LIBRARY_VERSION = @HOWL_LIBRARY_VERSION@
+HOWL_LIB_OBJECTS = @HOWL_LIB_OBJECTS@
+HOWL_LIB_SUBDIRS = @HOWL_LIB_SUBDIRS@
+HOWL_MAN_PAGES = @HOWL_MAN_PAGES@
+HOWL_RELEASE = @HOWL_RELEASE@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LIBTOOL = @LIBTOOL@
+LIB_SUBDIRS = @LIB_SUBDIRS@
+LN_S = @LN_S@
+MDNSRESPONDER_LIBRARY_VERSION = @MDNSRESPONDER_LIBRARY_VERSION@
+MDNSRESPONDER_LIB_OBJECTS = @MDNSRESPONDER_LIB_OBJECTS@
+MDNSRESPONDER_LIB_SUBDIRS = @MDNSRESPONDER_LIB_SUBDIRS@
+OBJDUMP = @OBJDUMP@
+PACKAGE = @PACKAGE@
+PLATFORM_LIBS = @PLATFORM_LIBS@
+RANLIB = @RANLIB@
+SRC_SUBDIRS = @SRC_SUBDIRS@
+STRIP = @STRIP@
+VERSION = @VERSION@
+am__include = @am__include@
+am__quote = @am__quote@
+install_sh = @install_sh@
+sources_h = freebsd_autoip.h
+sources_c = freebsd_autoip.c
+DIST_SOURCES = $(sources_h) $(sources_c) Makefile.am
+INCLUDES = -I$(top_srcdir)/include/
+subdir = src/autoipd/BSD
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/include/howl_config.h
+CONFIG_CLEAN_FILES =
+DIST_COMMON = Makefile.am Makefile.in
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4)
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/autoipd/BSD/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+ -rm -f libtool
+uninstall-info-am:
+tags: TAGS
+TAGS:
+
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+
+top_distdir = ../../..
+distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
+
+distdir: $(DISTFILES)
+ @list='$(DISTFILES)'; for file in $$list; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+ dir="/$$dir"; \
+ $(mkinstalldirs) "$(distdir)$$dir"; \
+ else \
+ dir=''; \
+ fi; \
+ if test -d $$d/$$file; then \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile
+
+installdirs:
+
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -rm -f Makefile $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+
+distclean-am: clean-am distclean-generic distclean-libtool
+
+dvi: dvi-am
+
+dvi-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+uninstall-am: uninstall-info-am
+
+.PHONY: all all-am check check-am clean clean-generic clean-libtool \
+ distclean distclean-generic distclean-libtool distdir dvi \
+ dvi-am info info-am install install-am install-data \
+ install-data-am install-exec install-exec-am install-info \
+ install-info-am install-man install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-generic \
+ mostlyclean-libtool uninstall uninstall-am uninstall-info-am
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff -urN empty/freebsd_autoip.c src/autoipd/BSD/freebsd_autoip.c
--- src/autoipd/BSD/freebsd_autoip.c Thu Jan 1 01:00:00 1970
+++ src/autoipd/BSD/freebsd_autoip.c Fri Jan 7 16:07:11 2005
@@ -0,0 +1,511 @@
+/*
+ * Copyright 2003, 2004 Porchdog Software. All rights reserved.
+ * Copyright 2004, 2005 Andrea Campi <andrea PLUS freebsd AT webcom DOT it>
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY PORCHDOG SOFTWARE ``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 HOWL 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.
+ *
+ * The views and conclusions contained in the software and documentation are those
+ * of the authors and should not be interpreted as representing official policies,
+ * either expressed or implied, of Porchdog Software.
+ */
+
+#include "freebsd_autoip.h"
+#include <sys/sysctl.h>
+#include <netinet/in.h>
+#include <net/bpf.h>
+#include <net/ethernet.h>
+#include <net/if_dl.h>
+#include <net/route.h>
+#include <salt/socket.h>
+#include <salt/address.h>
+#include <salt/debug.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+
+
+static sw_result
+sw_freebsd_autoip_network_interface_socket_event_handler(
+ sw_socket_handler handler,
+ sw_salt salt,
+ sw_socket socket,
+ sw_socket_event events,
+ sw_opaque extra);
+
+
+static struct bpf_insn arp_bpf_filter [] = {
+ /* Make sure this is an IP packet... */
+ BPF_STMT (BPF_LD + BPF_H + BPF_ABS, 12),
+ BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_ARP, 0, 1),
+
+ /* If we passed all the tests, ask for the whole packet. */
+ BPF_STMT(BPF_RET+BPF_K, 96),
+
+ /* Otherwise, drop it. */
+ BPF_STMT(BPF_RET+BPF_K, 0),
+};
+
+int arp_bpf_filter_len = (sizeof arp_bpf_filter / sizeof (struct bpf_insn));
+
+
+sw_string
+sw_platform_autoip_network_interface_default_interface_name()
+{
+ sw_string ret = NULL;
+ int mib[6];
+ struct if_msghdr *ifm, *nextifm;
+ struct ifa_msghdr *ifam;
+ struct sockaddr_dl *sdl;
+ char name[IFNAMSIZ];
+
+ int needed, count = 0;
+ char *buf, *lim, *next;
+ int res;
+ sw_result err = SW_OKAY;
+
+retry:
+ mib[0] = CTL_NET;
+ mib[1] = PF_ROUTE;
+ mib[2] = 0;
+ mib[3] = 0;
+ mib[4] = NET_RT_IFLIST;
+ mib[5] = 0;
+
+ /* determine how much memory is needed */
+ res = sysctl(mib, 6, NULL, &needed, NULL, 0);
+ err = sw_translate_error(res == 0, errno);
+ sw_check_okay_log(err, exit);
+
+ buf = malloc(needed);
+ err = sw_translate_error(buf != NULL, SW_E_MEM);
+ sw_check_okay_log(err, exit);
+
+ /* retrieve information */
+ res = sysctl(mib, 6, buf, &needed, NULL, 0);
+ if (res < 0) {
+ if (errno == ENOMEM && count++ < 10) {
+ warnx("Routing table grew, retrying");
+ free(ifm);
+ sleep(1);
+ goto retry;
+ }
+
+ err = sw_translate_error(res == 0, errno);
+ sw_check_okay_log(err, exit);
+ }
+
+ lim = buf + needed;
+ next = buf;
+ while (next < lim) {
+ ifm = (struct if_msghdr *)next;
+
+ if (ifm->ifm_type == RTM_IFINFO) {
+ if (ifm->ifm_data.ifi_datalen == 0)
+ ifm->ifm_data.ifi_datalen = sizeof(struct if_data);
+
+ sdl = (struct sockaddr_dl *)((char *)ifm +
+ sizeof(struct if_msghdr) -
+ sizeof(struct if_data) +
+ ifm->ifm_data.ifi_datalen);
+ } else {
+ sw_debug(SW_LOG_ERROR,
+ "out of sync parsing NET_RT_IFLIST\n");
+ err = SW_E_INIT;
+ goto exit;
+ }
+
+ next += ifm->ifm_msglen;
+ ifam = NULL;
+ while (next < lim) {
+ nextifm = (struct if_msghdr *)next;
+ if (nextifm->ifm_type != RTM_NEWADDR)
+ break;
+
+ if (ifam == NULL)
+ ifam = (struct ifa_msghdr *)nextifm;
+
+ next += nextifm->ifm_msglen;
+ }
+
+ if ((ifm->ifm_flags & IFF_BROADCAST) == 0)
+ {
+ continue;
+ }
+
+ memcpy(name, sdl->sdl_data,
+ sizeof(name) < sdl->sdl_nlen ?
+ sizeof(name)-1 : sdl->sdl_nlen);
+ name[sizeof(name) < sdl->sdl_nlen ?
+ sizeof(name)-1 : sdl->sdl_nlen] = '\0';
+
+ ret = strdup(name);
+ break;
+ }
+
+ err = SW_OKAY;
+
+exit:
+
+ return ret;
+}
+
+
+sw_result
+sw_platform_autoip_network_interface_new(
+ sw_autoip_network_interface * anif,
+ sw_salt salt,
+ sw_network_interface nif)
+{
+ sw_freebsd_autoip_network_interface self;
+ int res;
+ int macsock;
+ struct ifreq ifr;
+ char tname[IFNAMSIZ];
+ sw_result err = SW_OKAY;
+ int fd;
+ char name[IFNAMSIZ];
+ struct bpf_version v;
+ struct bpf_program p;
+ int flag, n;
+
+ self = (sw_freebsd_autoip_network_interface) sw_malloc(sizeof(struct _sw_freebsd_autoip_network_interface));
+ sw_check(self, exit, err = SW_E_MEM);
+
+ err = sw_autoip_network_interface_init(&self->m_super, salt, nif);
+ sw_check_okay(err, exit);
+
+ /*
+ * create out socket
+ */
+ n = 0;
+ do {
+ sprintf(tname, "/dev/bpf%d", n++);
+ fd = open(tname, O_RDWR);
+ } while (fd < 0 && errno == EBUSY && n < 1000);
+ err = sw_translate_error(fd != -1, errno);
+ sw_check_okay_log(err, exit);
+
+ self->m_osock = fd;
+ self->m_isock = fd;
+
+ /* Make sure the BPF version is in range... */
+ res = ioctl(fd, BIOCVERSION, &v);
+ err = sw_translate_error(res != -1, errno);
+ sw_check_okay_log(err, exit);
+
+ if (v.bv_major != BPF_MAJOR_VERSION || v.bv_minor < BPF_MINOR_VERSION) {
+ fprintf(stderr, "BPF version mismatch\n");
+ err = sw_translate_error(0, SW_E_UNKNOWN);
+ sw_check_okay_log(err, exit);
+ }
+
+ /*
+ * initialize the device name
+ */
+ sw_memset(&ifr, 0, sizeof(ifr));
+ sw_network_interface_name(self->m_super.m_nif, name, IFNAMSIZ);
+ strncpy(ifr.ifr_name, name, IFNAMSIZ - 1);
+
+ /*
+ * bind to the interface
+ */
+ res = ioctl(fd, BIOCSETIF, &ifr);
+ err = sw_translate_error(res != -1, errno);
+ sw_check_okay_log(err, exit);
+
+ /* Set immediate mode so that reads return as soon as a packet
+ * comes in, rather than waiting for the input buffer to fill with
+ * packets. */
+ flag = 1;
+ res = ioctl(fd, BIOCIMMEDIATE, &flag);
+ err = sw_translate_error(res != -1, errno);
+ sw_check_okay_log(err, exit);
+
+ /* */
+ flag = 0;
+ res = ioctl(fd, BIOCSSEESENT, &flag);
+ err = sw_translate_error(res != -1, errno);
+ sw_check_okay_log(err, exit);
+
+ /* */
+ flag = 1;
+ res = ioctl(fd, BIOCSHDRCMPLT, &flag);
+ err = sw_translate_error(res != -1, errno);
+ sw_check_okay_log(err, exit);
+
+ /* Get the required BPF buffer length from the kernel. */
+ res = ioctl(fd, BIOCGBLEN, &self->m_blen);
+ err = sw_translate_error(res != -1, errno);
+ sw_check_okay_log(err, exit);
+
+ self->m_buf = malloc(self->m_blen);
+ err = sw_translate_error(self->m_buf != NULL, errno);
+ sw_check_okay_log(err, exit);
+
+ /*
+ * set BPF filter
+ */
+ p.bf_len = arp_bpf_filter_len;
+ p.bf_insns = arp_bpf_filter;
+ res = ioctl(fd, BIOCSETF, &p);
+ err = sw_translate_error(res != -1, errno);
+ sw_check_okay_log(err, exit);
+
+ /*
+ * set non-blocking socket
+ */
+ res = fcntl(self->m_isock, F_GETFL);
+ err = sw_translate_error(res != -1, errno);
+ sw_check_okay_log(err, exit);
+
+ res = fcntl(self->m_isock, F_SETFL, res | O_NONBLOCK);
+ err = sw_translate_error(res != -1, errno);
+ sw_check_okay_log(err, exit);
+
+ err = sw_tcp_socket_init_with_desc(&self->m_socket, self->m_isock);
+ sw_check_okay(err, exit);
+
+ err = sw_autoip_network_interface_handle_wakeup(&self->m_super);
+ sw_check_okay(err, exit);
+
+ *anif = &self->m_super;
+
+exit:
+
+ if (err && self)
+ {
+ sw_platform_autoip_network_interface_delete(&self->m_super);
+ *anif = NULL;
+ }
+
+ return err;
+}
+
+
+sw_result
+sw_platform_autoip_network_interface_delete(
+ sw_autoip_network_interface anif)
+{
+ sw_freebsd_autoip_network_interface self = (sw_freebsd_autoip_network_interface) anif;
+
+ sw_autoip_network_interface_fina(&self->m_super);
+
+ sw_platform_autoip_network_interface_stop_monitoring(anif);
+
+ /*
+ * free
+ */
+ close(self->m_isock);
+ close(self->m_osock);
+
+ /*
+ * and we're good
+ */
+ sw_free(self);
+
+ return SW_OKAY;
+}
+
+
+sw_result
+sw_platform_autoip_network_interface_set_mac_address(
+ const char * s)
+{
+ return SW_E_INIT;
+}
+
+
+sw_result
+sw_platform_autoip_network_interface_start_monitoring(
+ sw_autoip_network_interface anif)
+{
+ sw_freebsd_autoip_network_interface self = (sw_freebsd_autoip_network_interface) anif;
+ sw_result err;
+
+ err = sw_salt_register_socket(self->m_super.m_salt, self->m_socket, SW_SOCKET_READ, (sw_socket_handler) self, sw_freebsd_autoip_network_interface_socket_event_handler, (sw_opaque) NULL);
+ sw_check_okay(err, exit);
+
+exit:
+
+ return err;
+}
+
+
+sw_result
+sw_platform_autoip_network_interface_stop_monitoring(
+ sw_autoip_network_interface anif)
+{
+ sw_freebsd_autoip_network_interface self = (sw_freebsd_autoip_network_interface) anif;
+ sw_result err;
+
+ err = sw_salt_unregister_socket(self->m_super.m_salt, self->m_socket);
+ sw_check_okay(err, exit);
+
+exit:
+
+ return err;
+}
+
+
+
+sw_result
+sw_platform_autoip_network_interface_send_arp_packet(
+ sw_autoip_network_interface anif,
+ sw_arp_packet * packet)
+{
+ sw_freebsd_autoip_network_interface self = (sw_freebsd_autoip_network_interface) anif;
+ struct sockaddr sndarp;
+ char name[IFNAMSIZ];
+ sw_mac_address mymac;
+ int res;
+ sw_result err = SW_OKAY;
+
+ /*
+ * get interface name
+ */
+ sw_network_interface_name(self->m_super.m_nif, name, IFNAMSIZ);
+ strcpy(sndarp.sa_data, name);
+
+ /*
+ * send packet
+ */
+ res = write(self->m_osock, packet, sizeof(struct _sw_arp_packet));
+ err = sw_translate_error(res >= 0, errno);
+ sw_check_okay_log(err, exit);
+
+exit:
+
+ return err;
+}
+
+
+sw_result
+sw_platform_autoip_network_interface_set_ip_address(
+ sw_autoip_network_interface anif)
+{
+ sw_freebsd_autoip_network_interface self = (sw_freebsd_autoip_network_interface) anif;
+ int r;
+ int sock_fd;
+ struct ifreq ifr;
+ struct in_addr saddr;
+ char name[IFNAMSIZ];
+ int res;
+ sw_result err = SW_OKAY;
+ struct ifaliasreq ifra;
+ struct sockaddr_in addr;
+
+ /*
+ * socket for ioctl
+ */
+ sock_fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
+ err = sw_translate_error(sock_fd != -1, errno);
+ sw_check_okay_log(err, exit);
+
+ /*
+ * initialize the device name
+ */
+ sw_memset(&ifra, 0, sizeof(ifra));
+ sw_network_interface_name(self->m_super.m_nif, name, IFNAMSIZ);
+ strncpy(ifra.ifra_name, name, IFNAMSIZ - 1);
+
+ /*
+ * initialize the ip address
+ */
+ addr.sin_addr.s_addr = sw_ipv4_address_saddr(self->m_super.m_ip_addr);
+ addr.sin_family = AF_INET;
+ addr.sin_len = sizeof(struct sockaddr_in);
+ memcpy(&ifra.ifra_addr, &addr, sizeof(struct sockaddr_in));
+
+ addr.sin_addr.s_addr |= ntohl(0x0000ffff);
+ memcpy(&ifra.ifra_broadaddr, &addr, sizeof(struct sockaddr_in));
+
+ addr.sin_addr.s_addr = ntohl(0xffff0000);
+ memcpy(&ifra.ifra_mask, &addr, sizeof(struct sockaddr_in));
+
+ res = ioctl(sock_fd, SIOCAIFADDR, &ifra);
+ err = sw_translate_error(res == 0, errno);
+ sw_check_okay_log(err, exit);
+
+ err = sw_network_interface_set_ipv4_address(self->m_super.m_nif, self->m_super.m_ip_addr);
+ sw_check_okay(err, exit);
+
+exit:
+
+ if (sock_fd != -1)
+ {
+ close(sock_fd);
+ }
+}
+
+
+static sw_result
+sw_freebsd_autoip_network_interface_socket_event_handler(
+ sw_socket_handler handler,
+ sw_salt salt,
+ sw_socket socket,
+ sw_socket_event events,
+ sw_opaque extra)
+{
+ static sw_mac_address ProbeSenderMAC = { 0, 0, 0, 0, 0, 0 };
+
+ sw_freebsd_autoip_network_interface self = (sw_freebsd_autoip_network_interface) handler;
+ char *ptr, *limit;
+ struct bpf_hdr *hdr;
+ sw_arp_packet *packet;
+ char smyip[18], spacketip[18];
+ char smymac[18], spacketmac[18];
+ int bytes;
+ sw_result err = SW_OKAY;
+
+ sw_assert(self != NULL);
+
+ /*
+ * ignore invocations if not our socket
+ */
+ sw_check(self->m_isock == sw_socket_desc(socket), exit, err = SW_OKAY);
+
+ bytes = read(self->m_isock, self->m_buf, self->m_blen);
+ err = sw_translate_error(bytes >= 0, errno);
+ sw_check_okay_log(err, exit);
+
+
+ for (ptr = (char *)self->m_buf, limit = ptr + bytes;
+ ptr < limit;
+ ptr += BPF_WORDALIGN(hdr->bh_hdrlen + hdr->bh_caplen)) {
+ hdr = (struct bpf_hdr *)ptr;
+ packet = (sw_arp_packet *)(ptr + hdr->bh_hdrlen);
+
+ if (hdr->bh_caplen >= (sizeof(struct _sw_ethernet_header) + sizeof(struct _sw_arp_header)))
+ {
+ if (((ntohs(packet->m_arp_header.m_op)) == SW_AUTOIP_ARP_REQUEST) ||
+ ((ntohs(packet->m_arp_header.m_op)) == SW_AUTOIP_ARP_REPLY))
+ {
+ err = sw_autoip_network_interface_read_arp_packet(&self->m_super, packet);
+ sw_check_okay(err, exit);
+ }
+ }
+ }
+
+exit:
+
+ return err;
+}
diff -urN empty/freebsd_autoip.h src/autoipd/BSD/freebsd_autoip.h
--- src/autoipd/BSD/freebsd_autoip.h Thu Jan 1 01:00:00 1970
+++ src/autoipd/BSD/freebsd_autoip.h Thu Dec 9 17:49:04 2004
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2003, 2004 Porchdog Software. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY PORCHDOG SOFTWARE ``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 HOWL 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.
+ *
+ * The views and conclusions contained in the software and documentation are those
+ * of the authors and should not be interpreted as representing official policies,
+ * either expressed or implied, of Porchdog Software.
+ */
+
+#ifndef _freebsd_autoip_h
+#define _freebsd_autoip_h
+
+
+#include "../autoip.h"
+#include <salt/address.h>
+#include <salt/socket.h>
+#include <salt/interface.h>
+#include <net/if.h>
+
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+
+
+struct _sw_freebsd_autoip_network_interface;
+typedef struct _sw_freebsd_autoip_network_interface * sw_freebsd_autoip_network_interface;
+
+
+struct _sw_freebsd_autoip_network_interface
+{
+ struct _sw_autoip_network_interface m_super;
+ sw_socket m_socket;
+ sw_sockdesc_t m_osock;
+ sw_sockdesc_t m_isock;
+
+ u_int m_blen;
+ unsigned char *m_buf;
+};
+
+
+#if defined(__cplusplus)
+}
+#endif
+
+
+#endif
Index: src/autoipd/BSD/Makefile.am
===================================================================
RCS file: src/autoipd/BSD/Makefile.am
diff -N src/autoipd/BSD/Makefile.am
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/autoipd/BSD/Makefile.am 12 Dec 2004 09:36:10 -0000 1.1
@@ -0,0 +1,4 @@
+sources_h = freebsd_autoip.h
+sources_c = freebsd_autoip.c
+DIST_SOURCES = $(sources_h) $(sources_c) Makefile.am
+INCLUDES = -I$(top_srcdir)/include/
More information about the freebsd-net
mailing list