Browse Source

Add libcap and mdnsresponder

Steven Barth 10 years ago
parent
commit
4132123ce5

+ 56
- 0
libs/libcap/Makefile View File

@@ -0,0 +1,56 @@
1
+#
2
+# Copyright (C) 2011 OpenWrt.org
3
+#
4
+# This is free software, licensed under the GNU General Public License v2.
5
+# See /LICENSE for more information.
6
+#
7
+
8
+include $(TOPDIR)/rules.mk
9
+
10
+PKG_NAME:=libcap
11
+PKG_VERSION:=2.24
12
+PKG_RELEASE:=1
13
+
14
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
15
+PKG_SOURCE_URL:=http://www.kernel.org/pub/linux/libs/security/linux-privs/libcap2/
16
+PKG_MD5SUM:=d43ab9f680435a7fff35b4ace8d45b80
17
+PKG_MAINTAINER:=Steven Barth <cyrus@openwrt.org>
18
+
19
+PKG_INSTALL:=1
20
+
21
+include $(INCLUDE_DIR)/package.mk
22
+include $(INCLUDE_DIR)/kernel.mk
23
+
24
+define Package/libcap
25
+  TITLE:=Linux capabilities library
26
+  SECTION:=libs
27
+  CATEGORY:=Libraries
28
+  URL:=http://www.kernel.org/pub/linux/libs/security/linux-privs/libcap2/
29
+endef
30
+
31
+MAKE_FLAGS += \
32
+    CFLAGS="$(TARGET_CFLAGS)" \
33
+    BUILD_CC="$(CC)" \
34
+    BUILD_CFLAGS="$(FPIC) -I$(PKG_BUILD_DIR)/libcap/include" \
35
+    CFLAGS="$(TARGET_CFLAGS)" \
36
+    LD="$(TARGET_CC)" \
37
+    LDFLAGS="$(TARGET_LDFLAGS) -shared" \
38
+    INDENT="| true" \
39
+    PAM_CAP="no" \
40
+    LIBATTR="no" \
41
+    DYNAMIC="yes" \
42
+    lib="lib"
43
+
44
+define Build/InstallDev
45
+	$(INSTALL_DIR) $(1)/usr/include/sys
46
+	$(CP) $(PKG_INSTALL_DIR)/usr/include/* $(1)/usr/include/
47
+	$(INSTALL_DIR) $(1)/usr/lib/
48
+	$(CP) $(PKG_INSTALL_DIR)/lib/* $(1)/usr/lib/
49
+endef
50
+
51
+define Package/libcap/install
52
+	$(INSTALL_DIR) $(1)/usr/lib
53
+	$(CP) $(PKG_INSTALL_DIR)/lib/libcap.so* $(1)/usr/lib/
54
+endef
55
+
56
+$(eval $(call BuildPackage,libcap))

+ 166
- 0
net/mdnsresponder/Makefile View File

@@ -0,0 +1,166 @@
1
+#
2
+# Copyright (C) 2009-2014 OpenWrt.org
3
+#
4
+# This is free software, licensed under the GNU General Public License v2.
5
+# See /LICENSE for more information.
6
+#
7
+
8
+include $(TOPDIR)/rules.mk
9
+
10
+PKG_NAME:=mDNSResponder
11
+PKG_VERSION:=544
12
+PKG_RELEASE:=4
13
+
14
+PKG_SOURCE:=mDNSResponder-$(PKG_VERSION).tar.gz
15
+PKG_SOURCE_URL:=http://opensource.apple.com/tarballs/mDNSResponder/
16
+PKG_MD5SUM:=39142ab70bd82a096801ce346f86cbab
17
+PKG_MAINTAINER:=Steven Barth <cyrus@openwrt.org>
18
+
19
+PKG_BUILD_DIR:=$(BUILD_DIR)/mDNSResponder-$(PKG_VERSION)
20
+
21
+PKG_BUILD_PARALLEL:=0
22
+PKG_INSTALL:=1
23
+
24
+include $(INCLUDE_DIR)/package.mk
25
+
26
+# sys/capability.h is not part of *libc*
27
+PKG_BUILD_DEPENDS:=libcap
28
+
29
+define Package/mDNSResponder/Default
30
+  SECTION:=net
31
+  CATEGORY:=Network
32
+  SUBMENU:=IP Addresses and Names
33
+  TITLE:=mDNS
34
+  URL:=http://developer.apple.com/networking/bonjour/
35
+endef
36
+
37
+define Package/mDNSResponder/Default/description
38
+  Bonjour, also known as zero-configuration networking, enables
39
+  automatic discovery of computers, devices, and services on
40
+  IP networks.
41
+endef
42
+
43
+define Package/mdns-utils
44
+$(call Package/mDNSResponder/Default)
45
+  TITLE+= client utilities
46
+  DEPENDS+= +mdnsd
47
+endef
48
+
49
+define Package/mdns-utils/description
50
+$(call Package/mDNSResponder/Default/description)
51
+ .
52
+ This package contains mDNS client utilities:
53
+ - dns-sd
54
+ - mDNSClient
55
+ - mDNSIdentify
56
+ - mDNSNetMonitor
57
+ - mDNSProxyResponder
58
+ - mDNSResponder
59
+endef
60
+
61
+define Package/mdnsd
62
+$(call Package/mDNSResponder/Default)
63
+  TITLE+= server daemon
64
+endef
65
+
66
+define Package/mdnsd/description
67
+$(call Package/mDNSResponder/Default/description)
68
+ .
69
+ This package contains the mDNS server daemon.
70
+endef
71
+
72
+define Package/mdnsresponder
73
+$(call Package/mDNSResponder/Default)
74
+  TITLE+= suite (meta)
75
+  DEPENDS+= +mdns-utils +mdnsd
76
+endef
77
+
78
+define Package/mdnsresponder/description
79
+$(call Package/mDNSResponder/Default/description)
80
+ .
81
+ This meta package contains only dependencies on other packages.
82
+endef
83
+
84
+# I have no idea why -lc is required, but without it, C library symbols are
85
+# not found:
86
+MAKE_FLAGS += \
87
+	CFLAGS_DEBUG="$(TARGET_CFLAGS)" \
88
+	LINKOPTS=-lc \
89
+	LDCONFIG= \
90
+	ETCBASE="$(PKG_INSTALL_DIR)/etc" \
91
+	INSTBASE="$(PKG_INSTALL_DIR)/usr" \
92
+	NSSINSTPATH="$(PKG_INSTALL_DIR)/lib" \
93
+	MANPATH="$(PKG_INSTALL_DIR)/usr/man" \
94
+	STARTUPSCRIPTDIR="$(PKG_INSTALL_DIR)/etc/init.d" \
95
+	RUNLEVELSCRIPTSDIR="$(PKG_INSTALL_DIR)/etc/rc.d" \
96
+	os=linux-uclibc
97
+MAKE_PATH = mDNSPosix
98
+
99
+define Build/Compile
100
+	$(call Build/Compile/Default)
101
+	# XXX: mDNSResponder's "make install" does not seem to create:
102
+	mkdir -p $(PKG_INSTALL_DIR)/lib/
103
+	mkdir -p $(PKG_INSTALL_DIR)/usr/bin/
104
+	mkdir -p $(PKG_INSTALL_DIR)/usr/sbin/
105
+	mkdir -p $(PKG_INSTALL_DIR)/usr/lib/
106
+	mkdir -p $(PKG_INSTALL_DIR)/usr/man/man5/
107
+	mkdir -p $(PKG_INSTALL_DIR)/usr/man/man8/
108
+	mkdir -p $(PKG_INSTALL_DIR)/usr/include/
109
+	mkdir -p $(PKG_INSTALL_DIR)/etc/
110
+	mkdir -p $(PKG_INSTALL_DIR)/etc/init.d/
111
+	mkdir -p $(PKG_INSTALL_DIR)/etc/rc.d/
112
+	mkdir -p $(PKG_INSTALL_DIR)/etc/rc.d/rc2.d/
113
+	mkdir -p $(PKG_INSTALL_DIR)/etc/rc.d/rc3.d/
114
+	mkdir -p $(PKG_INSTALL_DIR)/etc/rc.d/rc4.d/
115
+	mkdir -p $(PKG_INSTALL_DIR)/etc/rc.d/rc5.d/
116
+	mkdir -p $(PKG_INSTALL_DIR)/etc/rc.d/rc0.d/
117
+	mkdir -p $(PKG_INSTALL_DIR)/etc/rc.d/rc6.d/
118
+endef
119
+
120
+define Build/InstallDev
121
+	$(INSTALL_DIR) $(1)/usr/include
122
+	$(CP) $(PKG_BUILD_DIR)/mDNSShared/dns_sd.h $(1)/usr/include/
123
+	$(INSTALL_DIR) $(1)/usr/lib
124
+	$(CP) $(PKG_BUILD_DIR)/mDNSPosix/build/prod/*.so* $(1)/usr/lib/
125
+endef
126
+
127
+define Package/mdns-utils/conffile
128
+  /etc/init.d/mDNSResponder
129
+endef
130
+
131
+define Package/mdns-utils/install
132
+	$(INSTALL_DIR) $(1)/usr/bin/
133
+	$(CP) $(PKG_INSTALL_DIR)/usr/bin/dns-sd $(1)/usr/bin/
134
+	$(CP) $(PKG_BUILD_DIR)/mDNSPosix/build/prod/mDNSClientPosix $(1)/usr/bin/mDNSClient
135
+	$(CP) $(PKG_BUILD_DIR)/mDNSPosix/build/prod/mDNSIdentify $(1)/usr/bin/mDNSIdentify
136
+	$(CP) $(PKG_BUILD_DIR)/mDNSPosix/build/prod/mDNSNetMonitor $(1)/usr/bin/mDNSNetMonitor
137
+	$(CP) $(PKG_BUILD_DIR)/mDNSPosix/build/prod/mDNSProxyResponderPosix $(1)/usr/bin/mDNSProxyResponder
138
+	$(CP) $(PKG_BUILD_DIR)/mDNSPosix/build/prod/mDNSResponderPosix $(1)/usr/bin/mDNSResponder
139
+	$(INSTALL_DIR) $(1)/etc
140
+	$(INSTALL_DATA) ./files/mDNSResponder.conf $(1)/etc/
141
+	$(INSTALL_DIR) $(1)/etc/init.d
142
+	$(INSTALL_BIN) ./files/mDNSResponder.init $(1)/etc/init.d/mDNSResponder
143
+endef
144
+
145
+define Package/mdns-utils/conffiles
146
+/etc/mDNSResponder.conf
147
+endef
148
+
149
+define Package/mdnsd/install
150
+	$(INSTALL_DIR) $(1)/usr/sbin/
151
+	$(CP) $(PKG_INSTALL_DIR)/usr/sbin/mdnsd $(1)/usr/sbin/
152
+	$(INSTALL_DIR) $(1)/etc/hotplug.d/iface
153
+	$(INSTALL_DIR) $(1)/etc/init.d
154
+	$(INSTALL_BIN) ./files/mdnsd.init $(1)/etc/init.d/mdnsd
155
+	$(INSTALL_DIR) $(1)/usr/lib/
156
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/libdns_sd.so.1 $(1)/usr/lib/
157
+	$(LN) -s libdns_sd.so.1 $(1)/usr/lib/libdns_sd.so
158
+endef
159
+
160
+define Package/mdnsresponder/install
161
+	:
162
+endef
163
+
164
+$(eval $(call BuildPackage,mdns-utils))
165
+$(eval $(call BuildPackage,mdnsd))
166
+$(eval $(call BuildPackage,mdnsresponder))

+ 4
- 0
net/mdnsresponder/files/mDNSResponder.conf View File

@@ -0,0 +1,4 @@
1
+"OpenWrt SSH"
2
+_ssh._tcp. local
3
+22
4
+OpenWrt SSH server

+ 14
- 0
net/mdnsresponder/files/mDNSResponder.init View File

@@ -0,0 +1,14 @@
1
+#!/bin/sh /etc/rc.common
2
+# Copyright (C) 2009-2011 OpenWrt.org
3
+
4
+START=61
5
+
6
+SERVICE_USE_PID=1
7
+
8
+start() {
9
+	service_start /usr/bin/mDNSResponder -b -f /etc/mDNSResponder.conf
10
+}
11
+
12
+stop() {
13
+	service_stop /usr/bin/mDNSResponder
14
+}

+ 14
- 0
net/mdnsresponder/files/mdnsd.init View File

@@ -0,0 +1,14 @@
1
+#!/bin/sh /etc/rc.common
2
+# Copyright (C) 2009-2014 OpenWrt.org
3
+
4
+START=60
5
+STOP=10
6
+USE_PROCD=1
7
+
8
+start_service() {
9
+    procd_open_instance
10
+    procd_set_param command /usr/sbin/mdnsd -debug
11
+    procd_set_param respawn
12
+    procd_close_instance
13
+}
14
+

+ 123
- 0
net/mdnsresponder/patches/001-cross_compile.patch View File

@@ -0,0 +1,123 @@
1
+--- a/Clients/Makefile
2
++++ b/Clients/Makefile
3
+@@ -23,6 +23,8 @@
4
+ 
5
+ #############################################################################
6
+ 
7
++CC = @cc
8
++
9
+ # On OS X the dns_sd library functions are included in libSystem, which is implicitly linked with every executable
10
+ # If /usr/lib/libSystem.dylib exists, then we're on OS X, so we don't need also to link the "dns_sd" shared library
11
+ ifneq "$(wildcard /usr/lib/libSystem.dylib)" ""
12
+@@ -42,10 +44,10 @@ build:
13
+ 	mkdir build
14
+ 
15
+ build/dns-sd: build dns-sd.c ClientCommon.c
16
+-	cc $(filter %.c %.o, $+) $(LIBS) -I../mDNSShared -Wall -o $@
17
++	$(CC) $(CFLAGS) $(filter %.c %.o, $+) $(LIBS) -I../mDNSShared -Wall -o $@
18
+ 
19
+ build/dns-sd64: build dns-sd.c ClientCommon.c
20
+-	cc $(filter %.c %.o, $+) $(LIBS) -I../mDNSShared -Wall -o $@ -m64
21
++	$(CC) $(CFLAGS) $(filter %.c %.o, $+) $(LIBS) -I../mDNSShared -Wall -o $@ -m64
22
+ 
23
+ # Note, we can make a 'fat' version of dns-sd using 'lipo', as shown below, but we
24
+ # don't, because we don't want or need a 'fat' version of dns-sd, because it will
25
+--- a/mDNSPosix/Makefile
26
++++ b/mDNSPosix/Makefile
27
+@@ -54,10 +54,11 @@ COREDIR = ../mDNSCore
28
+ SHAREDDIR ?= ../mDNSShared
29
+ JDK = /usr/jdk
30
+ 
31
+-CC = @cc
32
++CC = @gcc
33
+ BISON = @bison
34
+ FLEX = @flex
35
+-LD = ld -shared
36
++LD = @ld
37
++SOOPTS = -shared
38
+ CP = cp
39
+ RM = rm
40
+ LN = ln -s -f
41
+@@ -82,7 +83,7 @@ else
42
+ CFLAGS_DEBUG = -Os -DMDNS_DEBUGMSGS=0 
43
+ OBJDIR ?= objects/prod
44
+ BUILDDIR ?= build/prod
45
+-STRIP = strip -S 
46
++STRIP = @strip -S
47
+ endif
48
+ 
49
+ # Configure per-OS peculiarities
50
+@@ -91,7 +92,7 @@ CFLAGS_DEBUG = -O0 -DMDNS_DEBUGMSGS=0
51
+ CFLAGS_OS = -DNOT_HAVE_DAEMON -DNOT_HAVE_SA_LEN -DNOT_HAVE_SOCKLEN_T -DNOT_HAVE_IF_NAMETOINDEX \
52
+ 	 -DLOG_PERROR=0 -D_XPG4_2 -D__EXTENSIONS__ -DHAVE_BROKEN_RECVIF_NAME -DTARGET_OS_SOLARIS
53
+ CC = gcc
54
+-LD = gcc -shared
55
++LD = gcc
56
+ LINKOPTS = -lsocket -lnsl -lresolv
57
+ JAVACFLAGS_OS += -I$(JDK)/include/solaris
58
+ ifneq ($(DEBUG),1)
59
+@@ -147,7 +148,8 @@ CFLAGS_OS = -DHAVE_IPV6 -no-cpp-precomp 
60
+ 	-D__MAC_OS_X_VERSION_MIN_REQUIRED=__MAC_OS_X_VERSION_10_4 \
61
+ 	-D__APPLE_USE_RFC_2292 #-Wunreachable-code
62
+ CC = gcc
63
+-LD = $(CC) -dynamiclib
64
++LD = $(CC)
65
++SOOPTS= -dynamiclib
66
+ LINKOPTS = -lSystem
67
+ LDSUFFIX = dylib
68
+ JDK = /System/Library/Frameworks/JavaVM.framework/Home
69
+@@ -169,8 +171,9 @@ NSSLIBFILE  := $(NSSLIBNAME)-$(NSSVERSIO
70
+ NSSLINKNAME := $(NSSLIBNAME).so.2
71
+ NSSINSTPATH := /lib
72
+ 
73
+-# If not otherwise defined, we install into /usr/lib and /usr/include
74
++# If not otherwise defined, we install into /usr/lib, /usr/include and /etc
75
+ # and our startup script is called mdns (e.g. /etc/init.d/mdns)
76
++ETCBASE?=/etc
77
+ INSTBASE?=/usr
78
+ STARTUPSCRIPTNAME?=mdns
79
+ 
80
+@@ -256,7 +259,7 @@ libdns_sd: setup $(BUILDDIR)/libdns_sd.$
81
+ CLIENTLIBOBJS = $(OBJDIR)/dnssd_clientlib.c.so.o $(OBJDIR)/dnssd_clientstub.c.so.o $(OBJDIR)/dnssd_ipc.c.so.o
82
+ 
83
+ $(BUILDDIR)/libdns_sd.$(LDSUFFIX): $(CLIENTLIBOBJS)
84
+-	@$(LD) $(LINKOPTS) -o $@ $+
85
++	@$(LD) $(SOOPTS) $(LINKOPTS) -o $@ $+
86
+ 	@$(STRIP) $@
87
+ 
88
+ Clients: setup libdns_sd ../Clients/build/dns-sd
89
+@@ -291,7 +294,7 @@ InstalledManPages: $(MANPATH)/man8/mdnsd
90
+ InstalledClients: $(INSTBASE)/bin/dns-sd
91
+ 	@echo $+ " installed"
92
+ 
93
+-InstalledNSS: $(NSSINSTPATH)/$(NSSLINKNAME) /etc/nss_mdns.conf $(MANPATH)/man5/nss_mdns.conf.5 $(MANPATH)/man8/libnss_mdns.8
94
++InstalledNSS: $(NSSINSTPATH)/$(NSSLINKNAME) $(ETCBASE)/nss_mdns.conf $(MANPATH)/man5/nss_mdns.conf.5 $(MANPATH)/man8/libnss_mdns.8
95
+ 	@echo $+ " installed"
96
+ 
97
+ # Note: If daemon already installed, we make sure it's stopped before overwriting it
98
+@@ -346,19 +349,21 @@ $(INSTBASE)/bin/dns-sd: ../Clients/build
99
+ 
100
+ $(NSSINSTPATH)/$(NSSLINKNAME): $(NSSINSTPATH)/$(NSSLIBFILE)
101
+ 	$(LN) $< $@
102
+-	ldconfig
103
++ifdef LDCONFIG
104
++	$(LDCONFIG)
105
++endif
106
+ 
107
+ $(NSSINSTPATH)/$(NSSLIBFILE): $(BUILDDIR)/$(NSSLIBFILE)
108
+ 	$(CP) $< $@
109
+ 	chmod 444 $@
110
+ 
111
+-/etc/nss_mdns.conf: nss_mdns.conf
112
++$(ETCBASE)/nss_mdns.conf: nss_mdns.conf
113
+ 	$(CP) $< $@
114
+ 	chmod 444 $@
115
+ 	# Check the nsswitch.conf file.
116
+ 	# If 'mdns' does not already appear on the "hosts:" line, then add it right before 'dns'
117
+-	cp -f /etc/nsswitch.conf /etc/nsswitch.conf.pre-mdns
118
+-	sed -e '/mdns/!s/^\(hosts:.*\)dns\(.*\)/\1mdns dns\2/' /etc/nsswitch.conf.pre-mdns > /etc/nsswitch.conf
119
++	-[ -f $(ETCBASE)/nsswitch.conf ] && cp -f $(ETCBASE)/nsswitch.conf $(ETCBASE)/nsswitch.conf.pre-mdns
120
++	-[ -f $(ETCBASE)/nsswitch.conf ] && sed -e '/mdns/!s/^\(hosts:.*\)dns\(.*\)/\1mdns dns\2/' $(ETCBASE)/nsswitch.conf.pre-mdns > $(ETCBASE)/nsswitch.conf
121
+ 
122
+ #############################################################################
123
+ 

+ 562
- 0
net/mdnsresponder/patches/100-linux_fixes.patch View File

@@ -0,0 +1,562 @@
1
+diff --git a/.gitignore b/.gitignore
2
+new file mode 100644
3
+index 0000000..920cdfc
4
+--- /dev/null
5
++++ b/.gitignore
6
+@@ -0,0 +1,4 @@
7
++Clients/build
8
++mDNSPosix/build
9
++mDNSPosix/objects
10
++
11
+diff --git a/mDNSPosix/PosixDaemon.c b/mDNSPosix/PosixDaemon.c
12
+index 88b3292..e86a6c7 100644
13
+--- a/mDNSPosix/PosixDaemon.c
14
++++ b/mDNSPosix/PosixDaemon.c
15
+@@ -37,6 +37,11 @@
16
+ #include <fcntl.h>
17
+ #include <pwd.h>
18
+ #include <sys/types.h>
19
++#ifdef __linux__
20
++#include <sys/capability.h> /* !!! We require libcap-dev for this. Oh well. */
21
++/* prctl is required to enable inheriting of capabilities across setuid */
22
++#include <sys/prctl.h>
23
++#endif /* __linux__ */
24
+ 
25
+ #if __APPLE__
26
+ #undef daemon
27
+@@ -184,16 +189,50 @@ int main(int argc, char **argv)
28
+ 
29
+     Reconfigure(&mDNSStorage);
30
+ 
31
++#ifdef __linux__
32
++    /*
33
++     * SO_BINDTODEVICE is privileged operation; however, we can get
34
++     * around it using capabilities instead of remaining root.
35
++     */
36
++    if (mStatus_NoError == err)
37
++      {
38
++        if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) < 0)
39
++          perror("prctl PR_SET_KEEPCAPS");
40
++      }
41
++#endif /* __linux__ */
42
++
43
+     // Now that we're finished with anything privileged, switch over to running as "nobody"
44
+     if (mStatus_NoError == err)
45
+     {
46
+         const struct passwd *pw = getpwnam("nobody");
47
+         if (pw != NULL)
48
++          {
49
+             setuid(pw->pw_uid);
50
++#ifdef __linux__
51
++            struct __user_cap_header_struct ch;
52
++            struct __user_cap_data_struct cd[_LINUX_CAPABILITY_U32S_3];
53
++
54
++            memset(&ch, 0, sizeof(ch));
55
++            ch.version = _LINUX_CAPABILITY_VERSION_3;
56
++            ch.pid = getpid();
57
++            memset(&cd[0], 0, sizeof(cd));
58
++            /* CAP_NET_RAW is required to use SO_BINDTODEVICE */
59
++            int caps = CAP_TO_MASK(CAP_NET_RAW);
60
++            cd[0].permitted = caps;
61
++            cd[0].effective = caps;
62
++            if (capset(&ch, &cd[0]) < 0)
63
++              perror("capset");
64
++#endif /* __linux__ */
65
++          }
66
+         else
67
+             LogMsg("WARNING: mdnsd continuing as root because user \"nobody\" does not exist");
68
+     }
69
+ 
70
++#ifdef __linux__
71
++    if (mStatus_NoError == err)
72
++      err = mDNSPlatformPosixRefreshInterfaceList(&mDNSStorage);
73
++#endif /* __linux__ */
74
++
75
+     if (mStatus_NoError == err)
76
+         err = MainLoop(&mDNSStorage);
77
+ 
78
+diff --git a/mDNSPosix/Responder.c b/mDNSPosix/Responder.c
79
+index 3996b7b..e58d8eb 100755
80
+--- a/mDNSPosix/Responder.c
81
++++ b/mDNSPosix/Responder.c
82
+@@ -603,7 +603,8 @@ static mStatus RegisterServicesInFile(const char *filePath)
83
+         status = mStatus_UnknownErr;
84
+     }
85
+ 
86
+-    assert(0 == fclose(fp));
87
++    int rv = fclose(fp);
88
++    assert(0 == rv);
89
+ 
90
+     return status;
91
+ }
92
+diff --git a/mDNSPosix/mDNSPosix.c b/mDNSPosix/mDNSPosix.c
93
+index 953bf64..4e481ea 100755
94
+--- a/mDNSPosix/mDNSPosix.c
95
++++ b/mDNSPosix/mDNSPosix.c
96
+@@ -136,7 +136,7 @@ mDNSlocal void SockAddrTomDNSAddr(const struct sockaddr *const sa, mDNSAddr *ipA
97
+ 
98
+ // mDNS core calls this routine when it needs to send a packet.
99
+ mDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const void *const msg, const mDNSu8 *const end,
100
+-                                       mDNSInterfaceID InterfaceID, UDPSocket *src, const mDNSAddr *dst, 
101
++                                       mDNSInterfaceID InterfaceID, UDPSocket *src, const mDNSAddr *dst,
102
+                                        mDNSIPPort dstPort, mDNSBool useBackgroundTrafficClass)
103
+ {
104
+     int err = 0;
105
+@@ -574,9 +574,17 @@ mDNSlocal void FreePosixNetworkInterface(PosixNetworkInterface *intf)
106
+ {
107
+     assert(intf != NULL);
108
+     if (intf->intfName != NULL) free((void *)intf->intfName);
109
+-    if (intf->multicastSocket4 != -1) assert(close(intf->multicastSocket4) == 0);
110
++    if (intf->multicastSocket4 != -1)
111
++      {
112
++        int rv = close(intf->multicastSocket4);
113
++        assert(rv == 0);
114
++      }
115
+ #if HAVE_IPV6
116
+-    if (intf->multicastSocket6 != -1) assert(close(intf->multicastSocket6) == 0);
117
++    if (intf->multicastSocket6 != -1)
118
++      {
119
++        int rv = close(intf->multicastSocket6);
120
++        assert(rv == 0);
121
++      }
122
+ #endif
123
+     free(intf);
124
+ }
125
+@@ -703,6 +711,29 @@ mDNSlocal int SetupSocket(struct sockaddr *intfAddr, mDNSIPPort port, int interf
126
+             if (err < 0) { err = errno; perror("setsockopt - IP_MULTICAST_TTL"); }
127
+         }
128
+ 
129
++#ifdef __linux__
130
++#ifdef SO_BINDTODEVICE
131
++        if (err == 0 && interfaceIndex)
132
++        {
133
++            char ifname[IFNAMSIZ];
134
++            if (if_indextoname(interfaceIndex, ifname))
135
++              {
136
++                err = setsockopt(*sktPtr, SOL_SOCKET, SO_BINDTODEVICE, ifname, strlen(ifname));
137
++                if (err < 0)
138
++                  {
139
++                    err = errno;
140
++                    perror("setsockopt - SO_BINDTODEVICE");
141
++                  }
142
++              }
143
++            else
144
++              {
145
++                err = errno;
146
++                perror("if_indextoname");
147
++              }
148
++        }
149
++#endif /* SO_BINDTODEVICE */
150
++#endif /* __linux__ */
151
++
152
+         // And start listening for packets
153
+         if (err == 0)
154
+         {
155
+@@ -784,6 +815,29 @@ mDNSlocal int SetupSocket(struct sockaddr *intfAddr, mDNSIPPort port, int interf
156
+             if (err < 0) { err = errno; perror("setsockopt - IPV6_MULTICAST_HOPS"); }
157
+         }
158
+ 
159
++#ifdef __linux__
160
++#ifdef SO_BINDTODEVICE
161
++        if (err == 0 && interfaceIndex)
162
++        {
163
++            char ifname[IFNAMSIZ];
164
++            if (if_indextoname(interfaceIndex, ifname))
165
++              {
166
++                err = setsockopt(*sktPtr, SOL_SOCKET, SO_BINDTODEVICE, ifname, strlen(ifname));
167
++                if (err < 0)
168
++                  {
169
++                    err = errno;
170
++                    perror("setsockopt - SO_BINDTODEVICE");
171
++                  }
172
++              }
173
++            else
174
++              {
175
++                err = errno;
176
++                perror("if_indextoname");
177
++              }
178
++        }
179
++#endif /* SO_BINDTODEVICE */
180
++#endif /* __linux__ */
181
++
182
+         // And start listening for packets
183
+         if (err == 0)
184
+         {
185
+@@ -815,7 +869,12 @@ mDNSlocal int SetupSocket(struct sockaddr *intfAddr, mDNSIPPort port, int interf
186
+     }
187
+ 
188
+     // Clean up
189
+-    if (err != 0 && *sktPtr != -1) { assert(close(*sktPtr) == 0); *sktPtr = -1; }
190
++    if (err != 0 && *sktPtr != -1)
191
++      {
192
++        int rv = close(*sktPtr);
193
++        assert(rv == 0);
194
++        *sktPtr = -1;
195
++      }
196
+     assert((err == 0) == (*sktPtr != -1));
197
+     return err;
198
+ }
199
+@@ -994,7 +1053,7 @@ mDNSlocal mStatus OpenIfNotifySocket(int *pFD)
200
+     /* Subscribe the socket to Link & IP addr notifications. */
201
+     mDNSPlatformMemZero(&snl, sizeof snl);
202
+     snl.nl_family = AF_NETLINK;
203
+-    snl.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR;
204
++    snl.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR;
205
+     ret = bind(sock, (struct sockaddr *) &snl, sizeof snl);
206
+     if (0 == ret)
207
+         *pFD = sock;
208
+@@ -1072,11 +1131,18 @@ mDNSlocal mDNSu32       ProcessRoutingNotification(int sd)
209
+         PrintNetLinkMsg(pNLMsg);
210
+ #endif
211
+ 
212
++        // this result isn't used anywhere as a number, just as
213
++        // non-zero - however, I have seen devices with more than 32
214
++        // interfaces at some point..
215
++        // (on Linux, every tunnel increases index for example)
216
++
217
+         // Process the NetLink message
218
+         if (pNLMsg->nlmsg_type == RTM_GETLINK || pNLMsg->nlmsg_type == RTM_NEWLINK)
219
+-            result |= 1 << ((struct ifinfomsg*) NLMSG_DATA(pNLMsg))->ifi_index;
220
++          result |= 1;
221
++        // << ((struct ifinfomsg*) NLMSG_DATA(pNLMsg))->ifi_index;
222
+         else if (pNLMsg->nlmsg_type == RTM_DELADDR || pNLMsg->nlmsg_type == RTM_NEWADDR)
223
+-            result |= 1 << ((struct ifaddrmsg*) NLMSG_DATA(pNLMsg))->ifa_index;
224
++          result |= 1;
225
++        // << ((struct ifaddrmsg*) NLMSG_DATA(pNLMsg))->ifa_index;
226
+ 
227
+         // Advance pNLMsg to the next message in the buffer
228
+         if ((pNLMsg->nlmsg_flags & NLM_F_MULTI) != 0 && pNLMsg->nlmsg_type != NLMSG_DONE)
229
+@@ -1247,8 +1313,12 @@ mDNSexport mStatus mDNSPlatformInit(mDNS *const m)
230
+     if (err == mStatus_NoError) err = SetupSocket(&sa, zeroIPPort, 0, &m->p->unicastSocket6);
231
+ #endif
232
+ 
233
++    // In Linux case, we can't set up sockets with different owner -
234
++    // it blows up SO_REUSEPORT. So we do this step bit later.
235
++#ifndef __linux__
236
+     // Tell mDNS core about the network interfaces on this machine.
237
+     if (err == mStatus_NoError) err = SetupInterfaceList(m);
238
++#endif /* !__linux__ */
239
+ 
240
+     // Tell mDNS core about DNS Servers
241
+     mDNS_Lock(m);
242
+@@ -1281,9 +1351,17 @@ mDNSexport void mDNSPlatformClose(mDNS *const m)
243
+ {
244
+     assert(m != NULL);
245
+     ClearInterfaceList(m);
246
+-    if (m->p->unicastSocket4 != -1) assert(close(m->p->unicastSocket4) == 0);
247
++    if (m->p->unicastSocket4 != -1)
248
++      {
249
++        int rv = close(m->p->unicastSocket4);
250
++        assert(rv == 0);
251
++      }
252
+ #if HAVE_IPV6
253
+-    if (m->p->unicastSocket6 != -1) assert(close(m->p->unicastSocket6) == 0);
254
++    if (m->p->unicastSocket6 != -1)
255
++      {
256
++        int rv = close(m->p->unicastSocket6);
257
++        assert(rv == 0);
258
++      }
259
+ #endif
260
+ }
261
+ 
262
+@@ -1533,14 +1611,14 @@ mDNSexport mStatus    mDNSPlatformClearSPSMACAddr(void)
263
+ mDNSexport mDNSu16 mDNSPlatformGetUDPPort(UDPSocket *sock)
264
+ {
265
+     (void) sock; // unused
266
+- 
267
++
268
+     return (mDNSu16)-1;
269
+ }
270
+ 
271
+ mDNSexport mDNSBool mDNSPlatformInterfaceIsD2D(mDNSInterfaceID InterfaceID)
272
+ {
273
+     (void) InterfaceID; // unused
274
+-    
275
++
276
+     return mDNSfalse;
277
+ }
278
+ 
279
+diff --git a/mDNSPosix/mDNSUNP.c b/mDNSPosix/mDNSUNP.c
280
+index b392fc7..9f85e0e 100755
281
+--- a/mDNSPosix/mDNSUNP.c
282
++++ b/mDNSPosix/mDNSUNP.c
283
+@@ -61,154 +61,86 @@
284
+ #endif
285
+ 
286
+ #if defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX
287
+-#include <netdb.h>
288
+-#include <arpa/inet.h>
289
+-
290
+-/* Converts a prefix length to IPv6 network mask */
291
+-void plen_to_mask(int plen, char *addr) {
292
+-    int i;
293
+-    int colons=7; /* Number of colons in IPv6 address */
294
+-    int bits_in_block=16; /* Bits per IPv6 block */
295
+-    for(i=0; i<=colons; i++) {
296
+-        int block, ones=0xffff, ones_in_block;
297
+-        if (plen>bits_in_block) ones_in_block=bits_in_block;
298
+-        else ones_in_block=plen;
299
+-        block = ones & (ones << (bits_in_block-ones_in_block));
300
+-        i==0 ? sprintf(addr, "%x", block) : sprintf(addr, "%s:%x", addr, block);
301
+-        plen -= ones_in_block;
302
+-    }
303
+-}
304
++#include <sys/types.h>
305
++#include <ifaddrs.h>
306
++
307
+ 
308
+-/* Gets IPv6 interface information from the /proc filesystem in linux*/
309
+-struct ifi_info *get_ifi_info_linuxv6(int family, int doaliases)
310
++/* Correct way to deal with this is just to use getifaddrs (glibc
311
++ * 2.3.3+ and various BSDs, but BSDs are 'slightly different' just to
312
++ * make life interesting). We assume Linux getifaddrs is available,
313
++ * and if not, please upgrade. */
314
++struct ifi_info *get_ifi_info_linuxv6(int doaliases)
315
+ {
316
+-    struct ifi_info *ifi, *ifihead, **ifipnext, *ifipold, **ifiptr;
317
+-    FILE *fp;
318
+-    char addr[8][5];
319
+-    int flags, myflags, index, plen, scope;
320
+-    char ifname[9], lastname[IFNAMSIZ];
321
+-    char addr6[32+7+1]; /* don't forget the seven ':' */
322
+-    struct addrinfo hints, *res0;
323
+-    struct sockaddr_in6 *sin6;
324
+-    struct in6_addr *addrptr;
325
+-    int err;
326
+-    int sockfd = -1;
327
+-    struct ifreq ifr;
328
+-
329
+-    res0=NULL;
330
+-    ifihead = NULL;
331
+-    ifipnext = &ifihead;
332
+-    lastname[0] = 0;
333
++  struct ifaddrs *ifap, *ifa;
334
++  struct ifi_info *ifi = NULL, *head = NULL;
335
+ 
336
+-    if ((fp = fopen(PROC_IFINET6_PATH, "r")) != NULL) {
337
+-        sockfd = socket(AF_INET6, SOCK_DGRAM, 0);
338
+-        if (sockfd < 0) {
339
+-            goto gotError;
340
++  /* doaliases seems always true in the calls in current code */
341
++  assert(doaliases);
342
++
343
++  if (getifaddrs(&ifap) < 0)
344
++    {
345
++      return NULL;
346
++    }
347
++  for (ifa = ifap ; ifa ; ifa = ifa->ifa_next)
348
++    {
349
++      /* Care only about IPv6 addresses on non-point-to-point links. */
350
++      if (!ifa->ifa_addr
351
++          || ifa->ifa_addr->sa_family != AF_INET6)
352
++        continue;
353
++      ifi = calloc(1, sizeof(*ifi));
354
++      if (!ifi)
355
++        break;
356
++      strncpy(ifi->ifi_name, ifa->ifa_name, IFI_NAME);
357
++      /* We ignore ifi_{haddr,hlen}, everyone else does too */
358
++      ifi->ifi_flags = ifa->ifa_flags;
359
++      /* We ignore ifi_myflags; IFI_ALIAS isn't used anywhere */
360
++      ifi->ifi_index = if_nametoindex(ifa->ifa_name);
361
++      if (!(ifi->ifi_addr = malloc(sizeof(struct sockaddr_in6))))
362
++        break;
363
++      memcpy(ifi->ifi_addr, ifa->ifa_addr, sizeof(struct sockaddr_in6));
364
++
365
++      if (ifa->ifa_netmask)
366
++        {
367
++          if (!(ifi->ifi_netmask = malloc(sizeof(struct sockaddr_in6))))
368
++            break;
369
++          memcpy(ifi->ifi_netmask, ifa->ifa_netmask,
370
++                 sizeof(struct sockaddr_in6));
371
+         }
372
+-        while (fscanf(fp,
373
+-                      "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %8s\n",
374
+-                      addr[0],addr[1],addr[2],addr[3],
375
+-                      addr[4],addr[5],addr[6],addr[7],
376
+-                      &index, &plen, &scope, &flags, ifname) != EOF) {
377
+-
378
+-            myflags = 0;
379
+-            if (strncmp(lastname, ifname, IFNAMSIZ) == 0) {
380
+-                if (doaliases == 0)
381
+-                    continue;   /* already processed this interface */
382
+-                myflags = IFI_ALIAS;
383
+-            }
384
+-            memcpy(lastname, ifname, IFNAMSIZ);
385
+-            ifi = (struct ifi_info*)calloc(1, sizeof(struct ifi_info));
386
+-            if (ifi == NULL) {
387
+-                goto gotError;
388
+-            }
389
+ 
390
+-            ifipold   = *ifipnext;       /* need this later */
391
+-            ifiptr    = ifipnext;
392
+-            *ifipnext = ifi;            /* prev points to this new one */
393
+-            ifipnext = &ifi->ifi_next;  /* pointer to next one goes here */
394
+-
395
+-            sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
396
+-                    addr[0],addr[1],addr[2],addr[3],
397
+-                    addr[4],addr[5],addr[6],addr[7]);
398
+-
399
+-            /* Add address of the interface */
400
+-            memset(&hints, 0, sizeof(hints));
401
+-            hints.ai_family = AF_INET6;
402
+-            hints.ai_flags = AI_NUMERICHOST;
403
+-            err = getaddrinfo(addr6, NULL, &hints, &res0);
404
+-            if (err) {
405
+-                goto gotError;
406
+-            }
407
+-            ifi->ifi_addr = calloc(1, sizeof(struct sockaddr_in6));
408
+-            if (ifi->ifi_addr == NULL) {
409
+-                goto gotError;
410
+-            }
411
+-            memcpy(ifi->ifi_addr, res0->ai_addr, sizeof(struct sockaddr_in6));
412
++      if (!(ifi->ifi_addr = malloc(sizeof(struct sockaddr_in6))))
413
++        break;
414
++      memcpy(ifi->ifi_addr, ifa->ifa_addr, sizeof(struct sockaddr_in6));
415
+ 
416
+-            /* Add netmask of the interface */
417
+-            char ipv6addr[INET6_ADDRSTRLEN];
418
+-            plen_to_mask(plen, ipv6addr);
419
+-            ifi->ifi_netmask = calloc(1, sizeof(struct sockaddr_in6));
420
+-            if (ifi->ifi_addr == NULL) {
421
+-                goto gotError;
422
+-            }
423
+-            sin6=calloc(1, sizeof(struct sockaddr_in6));
424
+-            addrptr=calloc(1, sizeof(struct in6_addr));
425
+-            inet_pton(family, ipv6addr, addrptr);
426
+-            sin6->sin6_family=family;
427
+-            sin6->sin6_addr=*addrptr;
428
+-            sin6->sin6_scope_id=scope;
429
+-            memcpy(ifi->ifi_netmask, sin6, sizeof(struct sockaddr_in6));
430
+-            free(sin6);
431
+-
432
+-
433
+-            /* Add interface name */
434
+-            memcpy(ifi->ifi_name, ifname, IFI_NAME);
435
+-
436
+-            /* Add interface index */
437
+-            ifi->ifi_index = index;
438
+-
439
+-            /* Add interface flags*/
440
+-            memcpy(ifr.ifr_name, ifname, IFNAMSIZ);
441
+-            if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) {
442
+-                if (errno == EADDRNOTAVAIL) {
443
+-                    /*
444
+-                     * If the main interface is configured with no IP address but
445
+-                     * an alias interface exists with an IP address, you get
446
+-                     * EADDRNOTAVAIL for the main interface
447
+-                     */
448
+-                    free(ifi->ifi_addr);
449
+-                    free(ifi);
450
+-                    ifipnext  = ifiptr;
451
+-                    *ifipnext = ifipold;
452
+-                    continue;
453
+-                } else {
454
+-                    goto gotError;
455
+-                }
456
+-            }
457
+-            ifi->ifi_flags = ifr.ifr_flags;
458
+-            freeaddrinfo(res0);
459
+-            res0=NULL;
460
+-        }
461
+-    }
462
+-    goto done;
463
+ 
464
+-gotError:
465
+-    if (ifihead != NULL) {
466
+-        free_ifi_info(ifihead);
467
+-        ifihead = NULL;
468
+-    }
469
+-    if (res0 != NULL) {
470
+-        freeaddrinfo(res0);
471
+-        res0=NULL;
472
+-    }
473
+-done:
474
+-    if (sockfd != -1) {
475
+-        assert(close(sockfd) == 0);
476
++      if (ifa->ifa_flags & IFF_POINTOPOINT && ifa->ifa_dstaddr)
477
++        {
478
++          if (!(ifi->ifi_dstaddr = malloc(sizeof(struct sockaddr_in6))))
479
++            break;
480
++          memcpy(ifi->ifi_dstaddr, ifa->ifa_dstaddr,
481
++                 sizeof(struct sockaddr_in6));
482
++        }
483
++      else if (ifa->ifa_broadaddr)
484
++        {
485
++          if (!(ifi->ifi_brdaddr = malloc(sizeof(struct sockaddr_in6))))
486
++            break;
487
++          memcpy(ifi->ifi_brdaddr, ifa->ifa_broadaddr,
488
++                 sizeof(struct sockaddr_in6));
489
++        }
490
++      ifi->ifi_next = head;
491
++      head = ifi;
492
++      ifi = NULL;
493
++    };
494
++  if (ifi)
495
++    {
496
++      /* An error occurred. Let's bail out. */
497
++      ifi->ifi_next = head;
498
++      free_ifi_info(head);
499
++      return NULL;
500
+     }
501
+-    return(ifihead);    /* pointer to first structure in linked list */
502
++  freeifaddrs(ifap);
503
++  return head;
504
+ }
505
++
506
+ #endif // defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX
507
+ 
508
+ struct ifi_info *get_ifi_info(int family, int doaliases)
509
+@@ -229,7 +161,7 @@ struct ifi_info *get_ifi_info(int family, int doaliases)
510
+ #endif
511
+ 
512
+ #if defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX
513
+-    if (family == AF_INET6) return get_ifi_info_linuxv6(family, doaliases);
514
++    if (family == AF_INET6) return get_ifi_info_linuxv6(doaliases);
515
+ #endif
516
+ 
517
+     sockfd = -1;
518
+diff --git a/mDNSPosix/mDNSUNP.h b/mDNSPosix/mDNSUNP.h
519
+index cc81b7d..e710087 100755
520
+--- a/mDNSPosix/mDNSUNP.h
521
++++ b/mDNSPosix/mDNSUNP.h
522
+@@ -97,8 +97,7 @@ struct ifi_info {
523
+ };
524
+ 
525
+ #if defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX
526
+-#define PROC_IFINET6_PATH "/proc/net/if_inet6"
527
+-extern struct ifi_info  *get_ifi_info_linuxv6(int family, int doaliases);
528
++extern struct ifi_info  *get_ifi_info_linuxv6(int doaliases);
529
+ #endif
530
+ 
531
+ #if defined(AF_INET6) && HAVE_IPV6
532
+diff --git a/mDNSShared/dnsextd_parser.y b/mDNSShared/dnsextd_parser.y
533
+index 18c5990..d4b63ce 100644
534
+--- a/mDNSShared/dnsextd_parser.y
535
++++ b/mDNSShared/dnsextd_parser.y
536
+@@ -15,6 +15,8 @@
537
+  * limitations under the License.
538
+  */
539
+ 
540
++%parse-param { void *context }
541
++
542
+ %{
543
+ #include <stdio.h>
544
+ #include <stdlib.h>
545
+@@ -23,7 +25,7 @@
546
+ #include "DebugServices.h"
547
+ #include "dnsextd.h"
548
+ 
549
+-void yyerror( const char* error );
550
++void yyerror( void *context, const char* error );
551
+ int  yylex(void);
552
+ 
553
+ 
554
+@@ -378,7 +380,7 @@ int yywrap(void);
555
+ 
556
+ extern int yylineno;
557
+ 
558
+-void yyerror( const char *str )
559
++void yyerror( void *context, const char *str )
560
+ {
561
+         fprintf( stderr,"%s:%d: error: %s\n", g_filename, yylineno, str );
562
+ }