Updated patches to work with the current trunk.
[rsync/rsync-patches.git] / slp.diff
CommitLineData
9978080e
WD
1This adds Service Location Protocol support.
2
03019e41 3To use this patch, run these commands for a successful build:
9978080e 4
03019e41 5 patch -p1 <patches/slp.diff
27e96866 6 ./prepare-source
9978080e 7 ./configure --enable-slp
9978080e
WD
8 make
9
6bc8e4ec
WD
10TODO: the configure changes should abort if the user requests --enable-slp
11and we can't honor that request.
12
cc3e685d 13diff --git a/Makefile.in b/Makefile.in
fc557362 14index feacb90..09e1547 100644
cc3e685d
WD
15--- a/Makefile.in
16+++ b/Makefile.in
03019e41 17@@ -13,6 +13,8 @@ CFLAGS=@CFLAGS@
9978080e
WD
18 CPPFLAGS=@CPPFLAGS@
19 EXEEXT=@EXEEXT@
20 LDFLAGS=@LDFLAGS@
21+LIBSLP=@LIBSLP@
22+SLPOBJ=@SLPOBJ@
23
24 INSTALLCMD=@INSTALL@
25 INSTALLMAN=@INSTALL@
fc557362 26@@ -38,7 +40,7 @@ OBJS1=flist.o rsync.o generator.o receiver.o cleanup.o sender.o exclude.o \
790ba11a 27 OBJS2=options.o io.o compat.o hlink.o token.o uidlist.o socket.o hashtable.o \
5795bf59 28 fileio.o batch.o clientname.o chmod.o acls.o xattrs.o
9978080e
WD
29 OBJS3=progress.o pipe.o
30-DAEMON_OBJ = params.o loadparm.o clientserver.o access.o connection.o authenticate.o
31+DAEMON_OBJ = params.o loadparm.o clientserver.o access.o connection.o authenticate.o $(SLPOBJ)
32 popt_OBJS=popt/findme.o popt/popt.o popt/poptconfig.o \
33 popt/popthelp.o popt/poptparse.o
34 OBJS=$(OBJS1) $(OBJS2) $(OBJS3) $(DAEMON_OBJ) $(LIBOBJ) $(ZLIBOBJ) @BUILD_POPT@
fc557362 35@@ -74,7 +76,7 @@ install-strip:
9978080e
WD
36 $(MAKE) INSTALL_STRIP='-s' install
37
38 rsync$(EXEEXT): $(OBJS)
39- $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
40+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) $(LIBSLP)
41
42 $(OBJS): $(HEADERS)
f2863bc0 43 $(CHECK_OBJS): $(HEADERS)
cc3e685d 44diff --git a/clientserver.c b/clientserver.c
fc557362 45index b6afe00..a242809 100644
cc3e685d
WD
46--- a/clientserver.c
47+++ b/clientserver.c
fc557362 48@@ -1153,6 +1153,13 @@ int daemon_main(void)
9978080e
WD
49 * address too. In fact, why not just do inet_ntop on the
50 * local address??? */
51
52+#ifdef HAVE_LIBSLP
53+ if (register_services()) {
54+ rprintf(FINFO,
55+ "Couldn't register with service discovery protocol, continuing anyway\n");
56+ }
57+#endif
58+
9f085fa3
WD
59 start_accept_loop(rsync_port, start_daemon);
60 return -1;
61 }
cc3e685d 62diff --git a/configure.in b/configure.in
fc557362 63index bc7d4a7..f8dc177 100644
cc3e685d
WD
64--- a/configure.in
65+++ b/configure.in
fc557362 66@@ -647,6 +647,29 @@ if test $rsync_cv_can_hardlink_special = yes; then
1898c899 67 AC_DEFINE(CAN_HARDLINK_SPECIAL, 1, [Define to 1 if link() can hard-link special files.])
9978080e
WD
68 fi
69
70+AC_ARG_ENABLE(slp, [ --disable-slp turn off SLP support, defaults to on])
71+AC_ARG_WITH(openslp-libs, [ --with-openslp-libs set directory for OpenSLP library],
72+ LDFLAGS="-L$withval $LDFLAGS"
73+ DSOFLAGS="-L$withval $DSOFLAGS",)
74+AC_ARG_WITH(openslp-includes, [ --with-openslp-includes set directory for OpenSLP includes],
75+ CFLAGS="-I$withval $CFLAGS"
76+ CXXFLAGS="-I$withval $CXXFLAGS"
77+ CPPFLAGS="-I$withval $CPPFLAGS",)
78+
79+LIBSLP=""
80+SLPOBJ=""
81+
82+if test x$enable_slp != xno; then
83+ AC_CHECK_HEADER(slp.h,
84+ AC_CHECK_LIB(slp, SLPOpen,
85+ AC_DEFINE(HAVE_LIBSLP, 1, [Define to 1 for SLP support])
86+ SLPOBJ="srvreg.o srvloc.o"
87+ LIBSLP="-lslp"))
88+fi
89+
90+AC_SUBST(LIBSLP)
91+AC_SUBST(SLPOBJ)
92+
93 AC_CACHE_CHECK([for working socketpair],rsync_cv_HAVE_SOCKETPAIR,[
94 AC_TRY_RUN([
95 #include <sys/types.h>
cc3e685d 96diff --git a/loadparm.c b/loadparm.c
fc557362 97index 8e48e6d..a833006 100644
cc3e685d
WD
98--- a/loadparm.c
99+++ b/loadparm.c
fc557362 100@@ -97,6 +97,9 @@ typedef struct {
9978080e
WD
101 char *socket_options;
102
103 int rsync_port;
6bc8e4ec 104+#ifdef HAVE_LIBSLP
9978080e 105+ int slp_refresh;
6bc8e4ec 106+#endif
fc557362 107 } global_vars;
9978080e 108
fc557362
WD
109 /* This structure describes a single section. Their order must match the
110@@ -311,6 +314,9 @@ static struct parm_struct parm_table[] =
111 {"motd file", P_STRING, P_GLOBAL,&Vars.g.motd_file, NULL,0},
112 {"pid file", P_STRING, P_GLOBAL,&Vars.g.pid_file, NULL,0},
113 {"port", P_INTEGER,P_GLOBAL,&Vars.g.rsync_port, NULL,0},
6bc8e4ec 114+#ifdef HAVE_LIBSLP
fc557362 115+ {"slp refresh", P_INTEGER,P_GLOBAL,&Vars.g.slp_refresh, NULL,0},
6bc8e4ec 116+#endif
fc557362 117 {"socket options", P_STRING, P_GLOBAL,&Vars.g.socket_options, NULL,0},
9978080e 118
fc557362
WD
119 {"auth users", P_STRING, P_LOCAL, &Vars.l.auth_users, NULL,0},
120@@ -392,6 +398,9 @@ FN_GLOBAL_STRING(lp_pid_file, &Vars.g.pid_file)
121 FN_GLOBAL_STRING(lp_socket_options, &Vars.g.socket_options)
9978080e 122
fc557362 123 FN_GLOBAL_INTEGER(lp_rsync_port, &Vars.g.rsync_port)
6bc8e4ec 124+#ifdef HAVE_LIBSLP
fc557362 125+FN_GLOBAL_INTEGER(lp_slp_refresh, &Vars.g.slp_refresh)
6bc8e4ec 126+#endif
9978080e
WD
127
128 FN_LOCAL_STRING(lp_auth_users, auth_users)
85096e5e 129 FN_LOCAL_STRING(lp_charset, charset)
cc3e685d 130diff --git a/main.c b/main.c
fc557362 131index 2ef2f47..3535264 100644
cc3e685d
WD
132--- a/main.c
133+++ b/main.c
fc557362 134@@ -1195,6 +1195,18 @@ static int start_client(int argc, char *argv[])
3731f97b 135
9978080e 136 if (!read_batch) { /* for read_batch, NO source is specified */
790ba11a 137 char *path = check_for_hostspec(argv[0], &shell_machine, &rsync_port);
9978080e
WD
138+
139+ if (shell_machine && !shell_machine[0]) {
140+#ifdef HAVE_LIBSLP
141+ /* User entered just rsync:// URI */
142+ print_service_list();
143+ exit_cleanup(0);
144+#else /* No SLP, die here */
145+ rprintf(FINFO, "No SLP support, cannot browse\n");
146+ exit_cleanup(RERR_SYNTAX);
147+#endif
148+ }
149+
790ba11a 150 if (path) { /* source is remote */
9f085fa3
WD
151 char *dummy_host;
152 int dummy_port = 0;
cc3e685d 153diff --git a/options.c b/options.c
fc557362 154index e7c6c61..dae5716 100644
cc3e685d
WD
155--- a/options.c
156+++ b/options.c
fc557362 157@@ -566,6 +566,7 @@ static void print_rsync_version(enum logcode f)
9978080e 158 char const *links = "no ";
58b399b9 159 char const *iconv = "no ";
9978080e
WD
160 char const *ipv6 = "no ";
161+ char const *slp = "no ";
162 STRUCT_STAT *dumstat;
163
ac2da598 164 #if SUBPROTOCOL_VERSION != 0
fc557362 165@@ -599,6 +600,9 @@ static void print_rsync_version(enum logcode f)
85096e5e
WD
166 #if defined HAVE_LUTIMES && defined HAVE_UTIMES
167 symtimes = "";
9978080e 168 #endif
9978080e
WD
169+#if HAVE_LIBSLP
170+ slp = "";
171+#endif
ac2da598
WD
172
173 rprintf(f, "%s version %s protocol version %d%s\n",
174 RSYNC_NAME, RSYNC_VERSION, PROTOCOL_VERSION, subprotocol);
fc557362 175@@ -612,8 +616,8 @@ static void print_rsync_version(enum logcode f)
5e3c6c93
WD
176 (int)(sizeof (int64) * 8));
177 rprintf(f, " %ssocketpairs, %shardlinks, %ssymlinks, %sIPv6, batchfiles, %sinplace,\n",
178 got_socketpair, hardlinks, links, ipv6, have_inplace);
85096e5e
WD
179- rprintf(f, " %sappend, %sACLs, %sxattrs, %siconv, %ssymtimes\n",
180- have_inplace, acls, xattrs, iconv, symtimes);
181+ rprintf(f, " %sappend, %sACLs, %sxattrs, %siconv, %ssymtimes, %sSLP\n",
182+ have_inplace, acls, xattrs, iconv, symtimes, slp);
5e3c6c93 183
9978080e 184 #ifdef MAINTAINER_MODE
5e3c6c93 185 rprintf(f, "Panic Action: \"%s\"\n", get_panic_action());
cc3e685d 186diff --git a/rsync.h b/rsync.h
fc557362 187index be7cf8a..8353124 100644
cc3e685d
WD
188--- a/rsync.h
189+++ b/rsync.h
fc557362 190@@ -194,6 +194,10 @@
9978080e
WD
191 #define SIGNIFICANT_ITEM_FLAGS (~(\
192 ITEM_BASIS_TYPE_FOLLOWS | ITEM_XNAME_FOLLOWS | ITEM_LOCAL_CHANGE))
193
194+/* this is the minimum we'll use, irrespective of config setting */
195+/* definately don't set to less than about 30 seconds */
196+#define SLP_MIN_TIMEOUT 120
76c553f7 197+
c0c7984e 198 #define CFN_KEEP_DOT_DIRS (1<<0)
76c553f7
WD
199 #define CFN_KEEP_TRAILING_SLASH (1<<1)
200 #define CFN_DROP_TRAILING_DOT_DIR (1<<2)
cc3e685d 201diff --git a/rsync.yo b/rsync.yo
fc557362 202index 941f7a5..1518b3f 100644
cc3e685d
WD
203--- a/rsync.yo
204+++ b/rsync.yo
abd3adb8 205@@ -148,7 +148,12 @@ particular rsync daemon by leaving off the module name:
9978080e
WD
206
207 quote(tt(rsync somehost.mydomain.com::))
208
209-See the following section for more details.
210+And, if Service Location Protocol is available, the following will list the
211+available rsync servers:
212+
213+quote(tt(rsync rsync://))
214+
215+See the following section for even more usage details.
216
217 manpagesection(ADVANCED USAGE)
218
cc3e685d
WD
219diff --git a/rsyncd.conf b/rsyncd.conf
220new file mode 100644
fc557362 221index 0000000..971723f
cc3e685d
WD
222--- /dev/null
223+++ b/rsyncd.conf
9978080e
WD
224@@ -0,0 +1,3 @@
225+
226+slp refresh = 300
227+
cc3e685d 228diff --git a/rsyncd.conf.yo b/rsyncd.conf.yo
fc557362 229index d4978cd..318f0ec 100644
cc3e685d
WD
230--- a/rsyncd.conf.yo
231+++ b/rsyncd.conf.yo
fc557362 232@@ -108,6 +108,15 @@ details on some of the options you may be able to set. By default no
ae306a29
WD
233 special socket options are set. These settings can also be specified
234 via the bf(--sockopts) command-line option.
9978080e 235
e66d6d51 236+dit(bf(slp refresh)) This parameter is used to determine how long service
9978080e 237+advertisements are valid (measured in seconds), and is only applicable if
e66d6d51 238+you have Service Location Protocol support compiled in. If this is
9978080e
WD
239+not set or is set to zero, then service advertisements never time out. If
240+this is set to less than 120 seconds, then 120 seconds is used. If it is
241+set to more than 65535, then 65535 is used (which is a limitation of SLP).
242+Using 3600 (one hour) is a good number if you tend to change your
243+configuration.
244+
245 enddit()
246
ae306a29 247 manpagesection(MODULE PARAMETERS)
fc557362 248@@ -739,6 +748,7 @@ use chroot = yes
9978080e
WD
249 max connections = 4
250 syslog facility = local5
251 pid file = /var/run/rsyncd.pid
252+slp refresh = 3600
253
254 [ftp]
85096e5e 255 path = /var/ftp/./pub
cc3e685d 256diff --git a/socket.c b/socket.c
fc557362 257index 5df3a50..a4a2b0a 100644
cc3e685d
WD
258--- a/socket.c
259+++ b/socket.c
e66d6d51 260@@ -530,6 +530,16 @@ void start_accept_loop(int port, int (*fn)(int, int))
9978080e
WD
261 {
262 fd_set deffds;
263 int *sp, maxfd, i;
6bc8e4ec 264+#ifdef HAVE_LIBSLP
9978080e
WD
265+ time_t next_slp_refresh;
266+ short slp_timeout = lp_slp_refresh();
267+ if (slp_timeout) {
268+ if (slp_timeout < SLP_MIN_TIMEOUT)
269+ slp_timeout = SLP_MIN_TIMEOUT;
270+ /* re-register before slp times out */
271+ slp_timeout -= 15;
272+ }
6bc8e4ec 273+#endif
9978080e 274
27e96866 275 #ifdef HAVE_SIGACTION
9978080e 276 sigact.sa_flags = SA_NOCLDSTOP;
e66d6d51 277@@ -558,14 +568,25 @@ void start_accept_loop(int port, int (*fn)(int, int))
9978080e
WD
278 maxfd = sp[i];
279 }
280
6bc8e4ec 281+#ifdef HAVE_LIBSLP
9978080e 282+ next_slp_refresh = time(NULL) + slp_timeout;
6bc8e4ec 283+#endif
9978080e
WD
284+
285 /* now accept incoming connections - forking a new process
286 * for each incoming connection */
287 while (1) {
288 fd_set fds;
289 pid_t pid;
290 int fd;
291+ int sel_ret;
9978080e
WD
292 struct sockaddr_storage addr;
293 socklen_t addrlen = sizeof addr;
6bc8e4ec
WD
294+#ifdef HAVE_LIBSLP
295+ struct timeval slp_tv;
296+
9978080e
WD
297+ slp_tv.tv_sec = 10;
298+ slp_tv.tv_usec = 0;
6bc8e4ec 299+#endif
9978080e
WD
300
301 /* close log file before the potentially very long select so
302 * file can be trimmed by another process instead of growing
fc557362 303@@ -578,7 +599,18 @@ void start_accept_loop(int port, int (*fn)(int, int))
9978080e
WD
304 fds = deffds;
305 #endif
fc557362
WD
306
307- if (select(maxfd + 1, &fds, NULL, NULL, NULL) < 1)
6bc8e4ec
WD
308+#ifdef HAVE_LIBSLP
309+ sel_ret = select(maxfd + 1, &fds, NULL, NULL,
310+ slp_timeout ? &slp_tv : NULL);
9978080e 311+ if (sel_ret == 0 && slp_timeout && time(NULL) > next_slp_refresh) {
fc557362
WD
312+ rprintf(FINFO, "Service registration expired, refreshing it\n");
313+ register_services();
314+ next_slp_refresh = time(NULL) + slp_timeout;
9978080e 315+ }
6bc8e4ec
WD
316+#else
317+ sel_ret = select(maxfd + 1, &fds, NULL, NULL, NULL);
318+#endif
fc557362 319+ if (sel_ret < 1)
9978080e
WD
320 continue;
321
322 for (i = 0, fd = -1; sp[i] >= 0; i++) {
cc3e685d
WD
323diff --git a/srvloc.c b/srvloc.c
324new file mode 100644
fc557362 325index 0000000..99eea16
cc3e685d
WD
326--- /dev/null
327+++ b/srvloc.c
6bc8e4ec 328@@ -0,0 +1,103 @@
9978080e
WD
329+/* -*- c-file-style: "linux"; -*-
330+
331+ Copyright (C) 2002 by Brad Hards <bradh@frogmouth.net>
332+
333+ This program is free software; you can redistribute it and/or modify
334+ it under the terms of the GNU General Public License as published by
335+ the Free Software Foundation; either version 2 of the License, or
336+ (at your option) any later version.
337+
338+ This program is distributed in the hope that it will be useful,
339+ but WITHOUT ANY WARRANTY; without even the implied warranty of
340+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
341+ GNU General Public License for more details.
342+
343+ You should have received a copy of the GNU General Public License
344+ along with this program; if not, write to the Free Software
345+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
346+*/
347+
348+/* This file implements the service location functionality */
349+/* Basically, it uses normal Service Location Protocol API */
350+
351+/* It is really a cheap hack - just to show how it might work
352+ in a real application.
353+*/
354+
355+#include "rsync.h"
356+
357+#include <slp.h>
358+#include <stdio.h>
359+#include <string.h>
360+
361+/* This one just prints out the attributes */
362+static SLPBoolean getAttrCallback(UNUSED(SLPHandle hslp), const char *attrlist,
363+ SLPError errcode, UNUSED(void *cookie))
364+{
365+ char *cleanstr;
366+
367+ if (errcode == SLP_OK) {
6bc8e4ec 368+ if (!strcmp(attrlist, "(comment=)"))
9978080e 369+ rprintf(FINFO, "\t(No description)\n");
6bc8e4ec 370+ else {
9978080e
WD
371+ cleanstr = strrchr(attrlist, ')') ;
372+ *cleanstr = ' '; /* remove last ')' */
373+ rprintf(FINFO, "\t%s\n", strchr(attrlist, '=') + 1);
374+ }
375+ }
376+ return SLP_FALSE;
377+}
378+
6bc8e4ec
WD
379+static SLPBoolean getSLPSrvURLCallback(UNUSED(SLPHandle hslp),
380+ const char *srvurl, UNUSED(unsigned short lifetime),
381+ SLPError errcode, void *cookie)
9978080e
WD
382+{
383+ SLPError result;
384+ SLPHandle attrhslp;
385+
386+ if (errcode == SLP_OK) {
387+ /* chop service: off the front */
388+ rprintf(FINFO, " %s ", (strchr(srvurl, ':') + 1));
389+ /* check for any attributes */
390+ if (SLPOpen("en", SLP_FALSE,&attrhslp) == SLP_OK) {
391+ result = SLPFindAttrs(attrhslp, srvurl,
392+ "", /* return all attributes */
393+ "", /* use configured scopes */
394+ getAttrCallback, NULL);
395+ if (result != SLP_OK) {
396+ rprintf(FERROR, "errorcode: %i\n",result);
397+ }
398+ SLPClose(attrhslp);
399+ }
400+ *(SLPError*)cookie = SLP_OK;
6bc8e4ec 401+ } else
9978080e 402+ *(SLPError*)cookie = errcode;
9978080e
WD
403+
404+ /* Return SLP_TRUE because we want to be called again
405+ * if more services were found. */
406+
407+ return SLP_TRUE;
408+}
409+
410+int print_service_list(void)
411+{
412+ SLPError err;
413+ SLPError callbackerr;
414+ SLPHandle hslp;
415+
416+ err = SLPOpen("en",SLP_FALSE,&hslp);
417+ if (err != SLP_OK) {
418+ rprintf(FERROR, "Error opening slp handle %i\n", err);
419+ return err;
420+ }
421+
422+ SLPFindSrvs(hslp, "rsync",
423+ 0, /* use configured scopes */
424+ 0, /* no attr filter */
425+ getSLPSrvURLCallback, &callbackerr);
426+
427+ /* Now that we're done using slp, close the slp handle */
428+ SLPClose(hslp);
429+
430+ return 0;
431+}
cc3e685d
WD
432diff --git a/srvreg.c b/srvreg.c
433new file mode 100644
fc557362 434index 0000000..04afe60
cc3e685d
WD
435--- /dev/null
436+++ b/srvreg.c
9978080e
WD
437@@ -0,0 +1,128 @@
438+/* -*- c-file-style: "linux"; -*-
439+
440+ Copyright (C) 2002 by Brad Hards <bradh@frogmouth.net>
441+
442+ This program is free software; you can redistribute it and/or modify
443+ it under the terms of the GNU General Public License as published by
444+ the Free Software Foundation; either version 2 of the License, or
445+ (at your option) any later version.
446+
447+ This program is distributed in the hope that it will be useful,
448+ but WITHOUT ANY WARRANTY; without even the implied warranty of
449+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
450+ GNU General Public License for more details.
451+
452+ You should have received a copy of the GNU General Public License
453+ along with this program; if not, write to the Free Software
454+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
455+*/
456+
457+/* This file implements the service registration functionality */
458+
459+/* Basically, it uses normal Service Location Protocol API */
460+
461+#include "rsync.h"
462+#include "slp.h"
463+#include "netdb.h"
464+
465+extern int rsync_port;
466+
467+static void slp_callback(UNUSED(SLPHandle hslp), SLPError errcode, void *cookie)
468+{
469+ /* return the error code in the cookie */
470+ *(SLPError*)cookie = errcode;
471+
472+ /* You could do something else here like print out
473+ * the errcode, etc. Remember, as a general rule,
474+ * do not try to do too much in a callback because
475+ * it is being executed by the same thread that is
476+ * reading slp packets from the wire. */
477+}
478+
479+int register_services(void)
480+{
481+ SLPError err, callbackerr;
482+ SLPHandle hslp;
483+ int n;
484+ int i;
485+ char srv[120];
486+ char attr[120];
487+ char localhost[256];
488+ extern char *config_file;
489+ short timeout;
490+ struct addrinfo aih, *ai = 0;
491+
492+ if (!lp_load(config_file, 0)) {
493+ exit_cleanup(RERR_SYNTAX);
494+ }
495+
496+ n = lp_numservices();
497+
498+ if (0 == lp_slp_refresh())
499+ timeout = SLP_LIFETIME_MAXIMUM; /* don't expire, ever */
500+ else if (SLP_MIN_TIMEOUT > lp_slp_refresh())
501+ timeout = SLP_MIN_TIMEOUT; /* use a reasonable minimum */
502+ else if (SLP_LIFETIME_MAXIMUM <= lp_slp_refresh())
503+ timeout = (SLP_LIFETIME_MAXIMUM - 1); /* as long as possible */
504+ else
505+ timeout = lp_slp_refresh();
506+
507+ rprintf(FINFO, "rsyncd registering %d service%s with slpd for %d seconds:\n", n, ((n==1)? "":"s"), timeout);
508+ err = SLPOpen("en",SLP_FALSE,&hslp);
509+ if (err != SLP_OK) {
510+ rprintf(FINFO, "Error opening slp handle %i\n",err);
511+ return err;
512+ }
513+ if (gethostname(localhost, sizeof localhost)) {
514+ rprintf(FINFO, "Could not get hostname: %s\n", strerror(errno));
515+ return err;
516+ }
517+ memset(&aih, 0, sizeof aih);
518+ aih.ai_family = PF_UNSPEC;
519+ aih.ai_flags = AI_CANONNAME;
520+ if (0 != (err = getaddrinfo(localhost, 0, &aih, &ai)) || !ai) {
521+ rprintf(FINFO, "Could not resolve hostname: %s\n", gai_strerror(err));
522+ return err;
523+ }
524+ /* Register each service with SLP */
525+ for (i = 0; i < n; i++) {
526+ if (!lp_list(i))
527+ continue;
528+
529+ snprintf(srv, sizeof srv, "service:rsync://%s:%d/%s",
530+ ai->ai_canonname,
531+ rsync_port,
532+ lp_name(i));
533+ rprintf(FINFO, " %s\n", srv);
534+ if (lp_comment(i)) {
535+ snprintf(attr, sizeof attr, "(comment=%s)",
536+ lp_comment(i));
537+ }
538+ err = SLPReg(hslp,
539+ srv, /* service to register */
540+ timeout,
541+ 0, /* this is ignored */
542+ attr, /* attributes */
543+ SLP_TRUE, /* new registration - don't change this */
544+ slp_callback, /* callback */
545+ &callbackerr);
546+
547+ /* err may contain an error code that occurred as the slp library
548+ * _prepared_ to make the call. */
549+ if (err != SLP_OK || callbackerr != SLP_OK)
550+ rprintf(FINFO, "Error registering service with slp %i\n", err);
551+
552+ /* callbackerr may contain an error code (that was assigned through
553+ * the callback cookie) that occurred as slp packets were sent on
554+ * the wire. */
555+ if (callbackerr != SLP_OK)
556+ rprintf(FINFO, "Error registering service with slp %i\n",callbackerr);
557+ }
558+
559+ /* Now that we're done using slp, close the slp handle */
560+ freeaddrinfo(ai);
561+ SLPClose(hslp);
562+
563+ /* refresh is done in main select loop */
564+ return 0;
565+}