]> git.saurik.com Git - apple/network_cmds.git/blob - unbound/contrib/unbound_unixsock.diff
09d05d39203fd4523204bcb53bcdaca01b473c75
[apple/network_cmds.git] / unbound / contrib / unbound_unixsock.diff
1 diff --git a/daemon/remote.c b/daemon/remote.c
2 index a2b2204..b6990f3 100644
3 --- a/daemon/remote.c
4 +++ b/daemon/remote.c
5 @@ -81,6 +81,11 @@
6 #ifdef HAVE_NETDB_H
7 #include <netdb.h>
8 #endif
9 +#ifdef HAVE_PWD_H
10 +#include <pwd.h>
11 +#include <sys/stat.h>
12 +#include <fcntl.h>
13 +#endif
14
15 /* just for portability */
16 #ifdef SQ
17 @@ -235,7 +240,8 @@ void daemon_remote_delete(struct daemon_remote* rc)
18 * @return false on failure.
19 */
20 static int
21 -add_open(const char* ip, int nr, struct listen_port** list, int noproto_is_err)
22 +add_open(const char* ip, int nr, struct listen_port** list, int noproto_is_err,
23 + struct config_file* cfg)
24 {
25 struct addrinfo hints;
26 struct addrinfo* res;
27 @@ -246,29 +252,74 @@ add_open(const char* ip, int nr, struct listen_port** list, int noproto_is_err)
28 snprintf(port, sizeof(port), "%d", nr);
29 port[sizeof(port)-1]=0;
30 memset(&hints, 0, sizeof(hints));
31 - hints.ai_socktype = SOCK_STREAM;
32 - hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
33 - if((r = getaddrinfo(ip, port, &hints, &res)) != 0 || !res) {
34 -#ifdef USE_WINSOCK
35 - if(!noproto_is_err && r == EAI_NONAME) {
36 - /* tried to lookup the address as name */
37 - return 1; /* return success, but do nothing */
38 +
39 + if(ip[0] == '/') {
40 + /* This looks like UNIX socket! */
41 + fd = create_domain_accept_sock(ip);
42 +/*
43 + * When unbound starts, it first creates a socket and then
44 + * drops privs, so the socket is created as root user.
45 + * This is fine, but we would like to set _unbound user group
46 + * for this socket, and permissions should be 0660 so only
47 + * root and _unbound group members can invoke unbound-control.
48 + * The username used here is the same as username that unbound
49 + * uses for its worker processes.
50 + */
51 +
52 +/*
53 + * Note: this code is an exact copy of code from daemon.c
54 + * Normally this should be either wrapped into a function,
55 + * or gui/gid values should be retrieved at config parsing time
56 + * and then stored in configfile structure.
57 + * This requires action from unbound developers!
58 +*/
59 +#ifdef HAVE_GETPWNAM
60 + struct passwd *pwd = NULL;
61 + uid_t uid;
62 + gid_t gid;
63 + /* initialize, but not to 0 (root) */
64 + memset(&uid, 112, sizeof(uid));
65 + memset(&gid, 112, sizeof(gid));
66 + log_assert(cfg);
67 +
68 + if(cfg->username && cfg->username[0]) {
69 + if((pwd = getpwnam(cfg->username)) == NULL)
70 + fatal_exit("user '%s' does not exist.",
71 + cfg->username);
72 + uid = pwd->pw_uid;
73 + gid = pwd->pw_gid;
74 + endpwent();
75 }
76 +
77 + chown(ip, 0, gid);
78 + chmod(ip, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
79 +#endif
80 + } else {
81 + hints.ai_socktype = SOCK_STREAM;
82 + hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
83 + if((r = getaddrinfo(ip, port, &hints, &res)) != 0 || !res) {
84 +#ifdef USE_WINSOCK
85 + if(!noproto_is_err && r == EAI_NONAME) {
86 + /* tried to lookup the address as name */
87 + return 1; /* return success, but do nothing */
88 + }
89 #endif /* USE_WINSOCK */
90 - log_err("control interface %s:%s getaddrinfo: %s %s",
91 - ip?ip:"default", port, gai_strerror(r),
92 + log_err("control interface %s:%s getaddrinfo: %s %s",
93 + ip?ip:"default", port, gai_strerror(r),
94 #ifdef EAI_SYSTEM
95 r==EAI_SYSTEM?(char*)strerror(errno):""
96 #else
97 ""
98 #endif
99 );
100 - return 0;
101 + return 0;
102 + }
103 +
104 + /* open fd */
105 + fd = create_tcp_accept_sock(res, 1, &noproto);
106 + freeaddrinfo(res);
107 }
108
109 - /* open fd */
110 - fd = create_tcp_accept_sock(res, 1, &noproto);
111 - freeaddrinfo(res);
112 if(fd == -1 && noproto) {
113 if(!noproto_is_err)
114 return 1; /* return success, but do nothing */
115 @@ -305,7 +356,7 @@ struct listen_port* daemon_remote_open_ports(struct config_file* cfg)
116 if(cfg->control_ifs) {
117 struct config_strlist* p;
118 for(p = cfg->control_ifs; p; p = p->next) {
119 - if(!add_open(p->str, cfg->control_port, &l, 1)) {
120 + if(!add_open(p->str, cfg->control_port, &l, 1, cfg)) {
121 listening_ports_free(l);
122 return NULL;
123 }
124 @@ -313,12 +364,12 @@ struct listen_port* daemon_remote_open_ports(struct config_file* cfg)
125 } else {
126 /* defaults */
127 if(cfg->do_ip6 &&
128 - !add_open("::1", cfg->control_port, &l, 0)) {
129 + !add_open("::1", cfg->control_port, &l, 0, cfg)) {
130 listening_ports_free(l);
131 return NULL;
132 }
133 if(cfg->do_ip4 &&
134 - !add_open("127.0.0.1", cfg->control_port, &l, 1)) {
135 + !add_open("127.0.0.1", cfg->control_port, &l, 1, cfg)) {
136 listening_ports_free(l);
137 return NULL;
138 }
139 diff --git a/services/listen_dnsport.c b/services/listen_dnsport.c
140 index ea7ec3a..4cb04e2 100644
141 --- a/services/listen_dnsport.c
142 +++ b/services/listen_dnsport.c
143 @@ -55,6 +55,10 @@
144 #endif
145 #include <fcntl.h>
146
147 +#ifndef USE_WINSOCK
148 +#include <sys/un.h>
149 +#endif
150 +
151 /** number of queued TCP connections for listen() */
152 #define TCP_BACKLOG 5
153
154 @@ -376,6 +380,53 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
155 }
156
157 int
158 +create_domain_accept_sock(char *path) {
159 + int s;
160 + struct sockaddr_un unixaddr;
161 +
162 +#ifndef USE_WINSOCK
163 + unixaddr.sun_len = sizeof(unixaddr);
164 + unixaddr.sun_family = AF_UNIX;
165 + strlcpy(unixaddr.sun_path, path, 104);
166 +
167 + if((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
168 + log_err("Cannot create UNIX socket %s (%s)",
169 + path, strerror(errno));
170 + return -1;
171 + }
172 +
173 + if(unlink(path) && errno != ENOENT) {
174 + /* The socket already exists and cannot be removed */
175 + log_err("Cannot remove old UNIX socket %s (%s)",
176 + path, strerror(errno));
177 + return -1;
178 + }
179 +
180 + if(bind(s, (struct sockaddr *) &unixaddr,
181 + sizeof(struct sockaddr_un)) == -1) {
182 + log_err("Cannot bind UNIX socket %s (%s)",
183 + path, strerror(errno));
184 + return -1;
185 + }
186 +
187 + if(!fd_set_nonblock(s)) {
188 + log_err("Cannot set non-blocking mode");
189 + return -1;
190 + }
191 +
192 + if(listen(s, TCP_BACKLOG) == -1) {
193 + log_err("can't listen: %s", strerror(errno));
194 + return -1;
195 + }
196 +
197 + return s;
198 +#else
199 + log_err("UNIX sockets are not supported");
200 + return -1;
201 +#endif
202 +}
203 +
204 +int
205 create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto)
206 {
207 int s;
208 diff --git a/smallapp/unbound-control.c b/smallapp/unbound-control.c
209 index a872f92..10631fd 100644
210 --- a/smallapp/unbound-control.c
211 +++ b/smallapp/unbound-control.c
212 @@ -59,6 +59,8 @@
213 #include "util/locks.h"
214 #include "util/net_help.h"
215
216 +#include <sys/un.h>
217 +
218 /** Give unbound-control usage, and exit (1). */
219 static void
220 usage()
221 @@ -158,6 +160,7 @@ contact_server(const char* svr, struct config_file* cfg, int statuscmd)
222 {
223 struct sockaddr_storage addr;
224 socklen_t addrlen;
225 + int addrfamily = 0;
226 int fd;
227 /* use svr or the first config entry */
228 if(!svr) {
229 @@ -176,12 +179,21 @@ contact_server(const char* svr, struct config_file* cfg, int statuscmd)
230 if(strchr(svr, '@')) {
231 if(!extstrtoaddr(svr, &addr, &addrlen))
232 fatal_exit("could not parse IP@port: %s", svr);
233 + } else if(svr[0] == '/') {
234 + struct sockaddr_un* unixsock = (struct sockaddr_un *) &addr;
235 + unixsock->sun_family = AF_UNIX;
236 + unixsock->sun_len = sizeof(unixsock);
237 + strlcpy(unixsock->sun_path, svr, 104);
238 + addrlen = sizeof(struct sockaddr_un);
239 + addrfamily = AF_UNIX;
240 } else {
241 if(!ipstrtoaddr(svr, cfg->control_port, &addr, &addrlen))
242 fatal_exit("could not parse IP: %s", svr);
243 }
244 - fd = socket(addr_is_ip6(&addr, addrlen)?AF_INET6:AF_INET,
245 - SOCK_STREAM, 0);
246 +
247 + if(addrfamily != AF_UNIX)
248 + addrfamily = addr_is_ip6(&addr, addrlen)?AF_INET6:AF_INET;
249 + fd = socket(addrfamily, SOCK_STREAM, 0);
250 if(fd == -1) {
251 #ifndef USE_WINSOCK
252 fatal_exit("socket: %s", strerror(errno));
253 diff --git a/util/net_help.c b/util/net_help.c
254 index b3136a3..5b5b4a3 100644
255 --- a/util/net_help.c
256 +++ b/util/net_help.c
257 @@ -45,6 +45,7 @@
258 #include "util/module.h"
259 #include "util/regional.h"
260 #include <fcntl.h>
261 +#include <sys/un.h>
262 #include <openssl/ssl.h>
263 #include <openssl/err.h>
264
265 @@ -135,7 +136,7 @@ log_addr(enum verbosity_value v, const char* str,
266 {
267 uint16_t port;
268 const char* family = "unknown";
269 - char dest[100];
270 + char dest[108];
271 int af = (int)((struct sockaddr_in*)addr)->sin_family;
272 void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr;
273 if(verbosity < v)
274 @@ -148,15 +149,23 @@ log_addr(enum verbosity_value v, const char* str,
275 case AF_UNIX: family="unix"; break;
276 default: break;
277 }
278 - if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) {
279 - strncpy(dest, "(inet_ntop error)", sizeof(dest));
280 +
281 + if(af != AF_UNIX) {
282 + if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) {
283 + strncpy(dest, "(inet_ntop error)", sizeof(dest));
284 + }
285 + dest[sizeof(dest)-1] = 0;
286 + port = ntohs(((struct sockaddr_in*)addr)->sin_port);
287 + if(verbosity >= 4)
288 + verbose(v, "%s %s %s port %d (len %d)", str, family,
289 + dest, (int)port, (int)addrlen);
290 + else verbose(v, "%s %s port %d", str, dest, (int)port);
291 + } else {
292 + struct sockaddr_un* unixsock;
293 + unixsock = (struct sockaddr_un *) addr;
294 + strlcpy(dest, unixsock->sun_path, sizeof(dest));
295 + verbose(v, "%s %s %s", str, family, dest);
296 }
297 - dest[sizeof(dest)-1] = 0;
298 - port = ntohs(((struct sockaddr_in*)addr)->sin_port);
299 - if(verbosity >= 4)
300 - verbose(v, "%s %s %s port %d (len %d)", str, family, dest,
301 - (int)port, (int)addrlen);
302 - else verbose(v, "%s %s port %d", str, dest, (int)port);
303 }
304
305 int