Created
March 13, 2012 02:11
-
-
Save anonymous/2026167 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This adds Service Location Protocol support. | |
To use this patch, run these commands for a successful build: | |
patch -p1 <patches/slp.diff | |
./prepare-source | |
./configure --enable-slp | |
make | |
TODO: the configure changes should abort if the user requests --enable-slp | |
and we can't honor that request. | |
based-on: 40afd365cc8ca968fd16e161d24df5b8a8a520cc | |
diff --git a/Makefile.in b/Makefile.in | |
--- a/Makefile.in | |
+++ b/Makefile.in | |
@@ -13,6 +13,8 @@ CFLAGS=@CFLAGS@ | |
CPPFLAGS=@CPPFLAGS@ | |
EXEEXT=@EXEEXT@ | |
LDFLAGS=@LDFLAGS@ | |
+LIBSLP=@LIBSLP@ | |
+SLPOBJ=@SLPOBJ@ | |
INSTALLCMD=@INSTALL@ | |
INSTALLMAN=@INSTALL@ | |
@@ -37,7 +39,7 @@ OBJS1=flist.o rsync.o generator.o receiver.o cleanup.o sender.o exclude.o \ | |
OBJS2=options.o io.o compat.o hlink.o token.o uidlist.o socket.o hashtable.o \ | |
fileio.o batch.o clientname.o chmod.o acls.o xattrs.o | |
OBJS3=progress.o pipe.o | |
-DAEMON_OBJ = params.o loadparm.o clientserver.o access.o connection.o authenticate.o | |
+DAEMON_OBJ = params.o loadparm.o clientserver.o access.o connection.o authenticate.o $(SLPOBJ) | |
popt_OBJS=popt/findme.o popt/popt.o popt/poptconfig.o \ | |
popt/popthelp.o popt/poptparse.o | |
OBJS=$(OBJS1) $(OBJS2) $(OBJS3) $(DAEMON_OBJ) $(LIBOBJ) $(ZLIBOBJ) @BUILD_POPT@ | |
@@ -73,7 +75,7 @@ install-strip: | |
$(MAKE) INSTALL_STRIP='-s' install | |
rsync$(EXEEXT): $(OBJS) | |
- $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) | |
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) $(LIBSLP) | |
$(OBJS): $(HEADERS) | |
$(CHECK_OBJS): $(HEADERS) | |
diff --git a/clientserver.c b/clientserver.c | |
--- a/clientserver.c | |
+++ b/clientserver.c | |
@@ -1074,6 +1074,13 @@ int daemon_main(void) | |
* address too. In fact, why not just do getnameinfo on the | |
* local address??? */ | |
+#ifdef HAVE_LIBSLP | |
+ if (lp_use_slp() && register_services() != 0) { | |
+ rprintf(FINFO, | |
+ "Couldn't register with service discovery protocol, continuing anyway\n"); | |
+ } | |
+#endif | |
+ | |
start_accept_loop(rsync_port, start_daemon); | |
return -1; | |
} | |
diff --git a/configure.ac b/configure.ac | |
--- a/configure.ac | |
+++ b/configure.ac | |
@@ -668,6 +668,29 @@ if test $rsync_cv_can_hardlink_special = yes; then | |
AC_DEFINE(CAN_HARDLINK_SPECIAL, 1, [Define to 1 if link() can hard-link special files.]) | |
fi | |
+AC_ARG_ENABLE(slp, [ --disable-slp turn off SLP support, defaults to on]) | |
+AC_ARG_WITH(openslp-libs, [ --with-openslp-libs set directory for OpenSLP library], | |
+ LDFLAGS="-L$withval $LDFLAGS" | |
+ DSOFLAGS="-L$withval $DSOFLAGS",) | |
+AC_ARG_WITH(openslp-includes, [ --with-openslp-includes set directory for OpenSLP includes], | |
+ CFLAGS="-I$withval $CFLAGS" | |
+ CXXFLAGS="-I$withval $CXXFLAGS" | |
+ CPPFLAGS="-I$withval $CPPFLAGS",) | |
+ | |
+LIBSLP="" | |
+SLPOBJ="" | |
+ | |
+if test x$enable_slp != xno; then | |
+ AC_CHECK_HEADER(slp.h, | |
+ AC_CHECK_LIB(slp, SLPOpen, | |
+ AC_DEFINE(HAVE_LIBSLP, 1, [Define to 1 for SLP support]) | |
+ SLPOBJ="srvreg.o srvloc.o" | |
+ LIBSLP="-lslp")) | |
+fi | |
+ | |
+AC_SUBST(LIBSLP) | |
+AC_SUBST(SLPOBJ) | |
+ | |
AC_CACHE_CHECK([for working socketpair],rsync_cv_HAVE_SOCKETPAIR,[ | |
AC_TRY_RUN([ | |
#include <sys/types.h> | |
diff --git a/loadparm.c b/loadparm.c | |
--- a/loadparm.c | |
+++ b/loadparm.c | |
@@ -109,6 +109,13 @@ typedef struct | |
char *socket_options; | |
int rsync_port; | |
+#ifdef HAVE_LIBSLP | |
+ int slp_refresh; | |
+#endif | |
+ | |
+#ifdef HAVE_LIBSLP | |
+ BOOL use_slp; | |
+#endif | |
} global; | |
static global Globals; | |
@@ -300,7 +307,13 @@ static struct parm_struct parm_table[] = | |
{"motd file", P_STRING, P_GLOBAL,&Globals.motd_file, NULL,0}, | |
{"pid file", P_STRING, P_GLOBAL,&Globals.pid_file, NULL,0}, | |
{"port", P_INTEGER,P_GLOBAL,&Globals.rsync_port, NULL,0}, | |
+#ifdef HAVE_LIBSLP | |
+ {"slp refresh", P_INTEGER,P_GLOBAL,&Globals.slp_refresh, NULL,0}, | |
+#endif | |
{"socket options", P_STRING, P_GLOBAL,&Globals.socket_options, NULL,0}, | |
+#ifdef HAVE_LIBSLP | |
+ {"use slp", P_BOOL, P_GLOBAL,&Globals.use_slp, NULL,0}, | |
+#endif | |
{"auth users", P_STRING, P_LOCAL, &sDefault.auth_users, NULL,0}, | |
{"charset", P_STRING, P_LOCAL, &sDefault.charset, NULL,0}, | |
@@ -354,6 +367,9 @@ static struct parm_struct parm_table[] = | |
static void init_globals(void) | |
{ | |
memset(&Globals, 0, sizeof Globals); | |
+#ifdef HAVE_LIBSLP | |
+ Globals.use_slp = True; | |
+#endif | |
} | |
/*************************************************************************** | |
@@ -394,6 +410,13 @@ FN_GLOBAL_STRING(lp_pid_file, &Globals.pid_file) | |
FN_GLOBAL_STRING(lp_socket_options, &Globals.socket_options) | |
FN_GLOBAL_INTEGER(lp_rsync_port, &Globals.rsync_port) | |
+#ifdef HAVE_LIBSLP | |
+FN_GLOBAL_INTEGER(lp_slp_refresh, &Globals.slp_refresh) | |
+#endif | |
+ | |
+#ifdef HAVE_LIBSLP | |
+FN_GLOBAL_BOOL(lp_use_slp, &Globals.use_slp) | |
+#endif | |
FN_LOCAL_STRING(lp_auth_users, auth_users) | |
FN_LOCAL_STRING(lp_charset, charset) | |
diff --git a/main.c b/main.c | |
--- a/main.c | |
+++ b/main.c | |
@@ -1133,6 +1133,18 @@ static int start_client(int argc, char *argv[]) | |
if (!read_batch) { /* for read_batch, NO source is specified */ | |
char *path = check_for_hostspec(argv[0], &shell_machine, &rsync_port); | |
+ | |
+ if (shell_machine && !shell_machine[0]) { | |
+#ifdef HAVE_LIBSLP | |
+ /* User entered just rsync:// URI */ | |
+ print_service_list(); | |
+ exit_cleanup(0); | |
+#else /* No SLP, die here */ | |
+ rprintf(FINFO, "No SLP support, cannot browse\n"); | |
+ exit_cleanup(RERR_SYNTAX); | |
+#endif | |
+ } | |
+ | |
if (path) { /* source is remote */ | |
char *dummy_host; | |
int dummy_port = 0; | |
diff --git a/options.c b/options.c | |
--- a/options.c | |
+++ b/options.c | |
@@ -223,6 +223,7 @@ static void print_rsync_version(enum logcode f) | |
char const *links = "no "; | |
char const *iconv = "no "; | |
char const *ipv6 = "no "; | |
+ char const *slp = "no "; | |
STRUCT_STAT *dumstat; | |
#if SUBPROTOCOL_VERSION != 0 | |
@@ -256,6 +257,9 @@ static void print_rsync_version(enum logcode f) | |
#ifdef CAN_SET_SYMLINK_TIMES | |
symtimes = ""; | |
#endif | |
+#if HAVE_LIBSLP | |
+ slp = ""; | |
+#endif | |
rprintf(f, "%s version %s protocol version %d%s\n", | |
RSYNC_NAME, RSYNC_VERSION, PROTOCOL_VERSION, subprotocol); | |
@@ -269,8 +273,8 @@ static void print_rsync_version(enum logcode f) | |
(int)(sizeof (int64) * 8)); | |
rprintf(f, " %ssocketpairs, %shardlinks, %ssymlinks, %sIPv6, batchfiles, %sinplace,\n", | |
got_socketpair, hardlinks, links, ipv6, have_inplace); | |
- rprintf(f, " %sappend, %sACLs, %sxattrs, %siconv, %ssymtimes\n", | |
- have_inplace, acls, xattrs, iconv, symtimes); | |
+ rprintf(f, " %sappend, %sACLs, %sxattrs, %siconv, %ssymtimes, %sSLP\n", | |
+ have_inplace, acls, xattrs, iconv, symtimes, slp); | |
#ifdef MAINTAINER_MODE | |
rprintf(f, "Panic Action: \"%s\"\n", get_panic_action()); | |
diff --git a/rsync.h b/rsync.h | |
--- a/rsync.h | |
+++ b/rsync.h | |
@@ -199,6 +199,10 @@ | |
#define SIGNIFICANT_ITEM_FLAGS (~(\ | |
ITEM_BASIS_TYPE_FOLLOWS | ITEM_XNAME_FOLLOWS | ITEM_LOCAL_CHANGE)) | |
+/* this is the minimum we'll use, irrespective of config setting */ | |
+/* definately don't set to less than about 30 seconds */ | |
+#define SLP_MIN_TIMEOUT 120 | |
+ | |
#define CFN_KEEP_DOT_DIRS (1<<0) | |
#define CFN_KEEP_TRAILING_SLASH (1<<1) | |
#define CFN_DROP_TRAILING_DOT_DIR (1<<2) | |
diff --git a/rsync.yo b/rsync.yo | |
--- a/rsync.yo | |
+++ b/rsync.yo | |
@@ -148,7 +148,12 @@ particular rsync daemon by leaving off the module name: | |
quote(tt(rsync somehost.mydomain.com::)) | |
-See the following section for more details. | |
+And, if Service Location Protocol is available, the following will list the | |
+available rsync servers: | |
+ | |
+quote(tt(rsync rsync://)) | |
+ | |
+See the following section for even more usage details. | |
manpagesection(ADVANCED USAGE) | |
diff --git a/rsyncd.conf b/rsyncd.conf | |
new file mode 100644 | |
--- /dev/null | |
+++ b/rsyncd.conf | |
@@ -0,0 +1,3 @@ | |
+ | |
+slp refresh = 300 | |
+ | |
diff --git a/rsyncd.conf.yo b/rsyncd.conf.yo | |
--- a/rsyncd.conf.yo | |
+++ b/rsyncd.conf.yo | |
@@ -104,6 +104,19 @@ details on some of the options you may be able to set. By default no | |
special socket options are set. These settings can also be specified | |
via the bf(--sockopts) command-line option. | |
+dit(bf(use slp)) This parameter is used to determine if the module names are | |
+advertised via slp. The default is for this to be enabled, which will | |
+advertise your public modules. | |
+ | |
+dit(bf(slp refresh)) This parameter is used to determine how long service | |
+advertisements are valid (measured in seconds), and is only applicable if | |
+you have Service Location Protocol support compiled in. If this is | |
+not set or is set to zero, then service advertisements never timeout. If | |
+this is set to less than 120 seconds, then 120 seconds is used. If it is | |
+set to more than 65535, then 65535 is used (which is a limitation of SLP). | |
+Using 3600 (one hour) is a good number if you tend to change your | |
+configuration. | |
+ | |
enddit() | |
manpagesection(MODULE PARAMETERS) | |
@@ -658,6 +671,7 @@ use chroot = yes | |
max connections = 4 | |
syslog facility = local5 | |
pid file = /var/run/rsyncd.pid | |
+slp refresh = 3600 | |
[ftp] | |
path = /var/ftp/./pub | |
diff --git a/socket.c b/socket.c | |
--- a/socket.c | |
+++ b/socket.c | |
@@ -544,6 +544,16 @@ void start_accept_loop(int port, int (*fn)(int, int)) | |
{ | |
fd_set deffds; | |
int *sp, maxfd, i; | |
+#ifdef HAVE_LIBSLP | |
+ time_t next_slp_refresh; | |
+ short slp_timeout = lp_use_slp() ? lp_slp_refresh() : 0; | |
+ if (slp_timeout) { | |
+ if (slp_timeout < SLP_MIN_TIMEOUT) | |
+ slp_timeout = SLP_MIN_TIMEOUT; | |
+ /* re-register before slp times out */ | |
+ slp_timeout -= 15; | |
+ } | |
+#endif | |
#ifdef HAVE_SIGACTION | |
sigact.sa_flags = SA_NOCLDSTOP; | |
@@ -572,14 +582,25 @@ void start_accept_loop(int port, int (*fn)(int, int)) | |
maxfd = sp[i]; | |
} | |
+#ifdef HAVE_LIBSLP | |
+ next_slp_refresh = time(NULL) + slp_timeout; | |
+#endif | |
+ | |
/* now accept incoming connections - forking a new process | |
* for each incoming connection */ | |
while (1) { | |
fd_set fds; | |
pid_t pid; | |
int fd; | |
+ int sel_ret; | |
struct sockaddr_storage addr; | |
socklen_t addrlen = sizeof addr; | |
+#ifdef HAVE_LIBSLP | |
+ struct timeval slp_tv; | |
+ | |
+ slp_tv.tv_sec = 10; | |
+ slp_tv.tv_usec = 0; | |
+#endif | |
/* close log file before the potentially very long select so | |
* file can be trimmed by another process instead of growing | |
@@ -592,7 +613,18 @@ void start_accept_loop(int port, int (*fn)(int, int)) | |
fds = deffds; | |
#endif | |
- if (select(maxfd + 1, &fds, NULL, NULL, NULL) < 1) | |
+#ifdef HAVE_LIBSLP | |
+ sel_ret = select(maxfd + 1, &fds, NULL, NULL, | |
+ slp_timeout ? &slp_tv : NULL); | |
+ if (sel_ret == 0 && slp_timeout && time(NULL) > next_slp_refresh) { | |
+ rprintf(FINFO, "Service registration expired, refreshing it\n"); | |
+ register_services(); | |
+ next_slp_refresh = time(NULL) + slp_timeout; | |
+ } | |
+#else | |
+ sel_ret = select(maxfd + 1, &fds, NULL, NULL, NULL); | |
+#endif | |
+ if (sel_ret < 1) | |
continue; | |
for (i = 0, fd = -1; sp[i] >= 0; i++) { | |
diff --git a/srvloc.c b/srvloc.c | |
new file mode 100644 | |
--- /dev/null | |
+++ b/srvloc.c | |
@@ -0,0 +1,103 @@ | |
+/* -*- c-file-style: "linux"; -*- | |
+ | |
+ Copyright (C) 2002 by Brad Hards <bradh@frogmouth.net> | |
+ | |
+ This program is free software; you can redistribute it and/or modify | |
+ it under the terms of the GNU General Public License as published by | |
+ the Free Software Foundation; either version 2 of the License, or | |
+ (at your option) any later version. | |
+ | |
+ This program is distributed in the hope that it will be useful, | |
+ but WITHOUT ANY WARRANTY; without even the implied warranty of | |
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
+ GNU General Public License for more details. | |
+ | |
+ You should have received a copy of the GNU General Public License | |
+ along with this program; if not, write to the Free Software | |
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
+*/ | |
+ | |
+/* This file implements the service location functionality */ | |
+/* Basically, it uses normal Service Location Protocol API */ | |
+ | |
+/* It is really a cheap hack - just to show how it might work | |
+ in a real application. | |
+*/ | |
+ | |
+#include "rsync.h" | |
+ | |
+#include <slp.h> | |
+#include <stdio.h> | |
+#include <string.h> | |
+ | |
+/* This one just prints out the attributes */ | |
+static SLPBoolean getAttrCallback(UNUSED(SLPHandle hslp), const char *attrlist, | |
+ SLPError errcode, UNUSED(void *cookie)) | |
+{ | |
+ char *cleanstr; | |
+ | |
+ if (errcode == SLP_OK) { | |
+ if (!strcmp(attrlist, "(comment=)")) | |
+ rprintf(FINFO, "\t(No description)\n"); | |
+ else { | |
+ cleanstr = strrchr(attrlist, ')') ; | |
+ *cleanstr = ' '; /* remove last ')' */ | |
+ rprintf(FINFO, "\t%s\n", strchr(attrlist, '=') + 1); | |
+ } | |
+ } | |
+ return SLP_FALSE; | |
+} | |
+ | |
+static SLPBoolean getSLPSrvURLCallback(UNUSED(SLPHandle hslp), | |
+ const char *srvurl, UNUSED(unsigned short lifetime), | |
+ SLPError errcode, void *cookie) | |
+{ | |
+ SLPError result; | |
+ SLPHandle attrhslp; | |
+ | |
+ if (errcode == SLP_OK) { | |
+ /* chop service: off the front */ | |
+ rprintf(FINFO, " %s ", (strchr(srvurl, ':') + 1)); | |
+ /* check for any attributes */ | |
+ if (SLPOpen("en", SLP_FALSE,&attrhslp) == SLP_OK) { | |
+ result = SLPFindAttrs(attrhslp, srvurl, | |
+ "", /* return all attributes */ | |
+ "", /* use configured scopes */ | |
+ getAttrCallback, NULL); | |
+ if (result != SLP_OK) { | |
+ rprintf(FERROR, "errorcode: %i\n",result); | |
+ } | |
+ SLPClose(attrhslp); | |
+ } | |
+ *(SLPError*)cookie = SLP_OK; | |
+ } else | |
+ *(SLPError*)cookie = errcode; | |
+ | |
+ /* Return SLP_TRUE because we want to be called again | |
+ * if more services were found. */ | |
+ | |
+ return SLP_TRUE; | |
+} | |
+ | |
+int print_service_list(void) | |
+{ | |
+ SLPError err; | |
+ SLPError callbackerr; | |
+ SLPHandle hslp; | |
+ | |
+ err = SLPOpen("en",SLP_FALSE,&hslp); | |
+ if (err != SLP_OK) { | |
+ rprintf(FERROR, "Error opening slp handle %i\n", err); | |
+ return err; | |
+ } | |
+ | |
+ SLPFindSrvs(hslp, "rsync", | |
+ 0, /* use configured scopes */ | |
+ 0, /* no attr filter */ | |
+ getSLPSrvURLCallback, &callbackerr); | |
+ | |
+ /* Now that we're done using slp, close the slp handle */ | |
+ SLPClose(hslp); | |
+ | |
+ return 0; | |
+} | |
diff --git a/srvreg.c b/srvreg.c | |
new file mode 100644 | |
--- /dev/null | |
+++ b/srvreg.c | |
@@ -0,0 +1,128 @@ | |
+/* -*- c-file-style: "linux"; -*- | |
+ | |
+ Copyright (C) 2002 by Brad Hards <bradh@frogmouth.net> | |
+ | |
+ This program is free software; you can redistribute it and/or modify | |
+ it under the terms of the GNU General Public License as published by | |
+ the Free Software Foundation; either version 2 of the License, or | |
+ (at your option) any later version. | |
+ | |
+ This program is distributed in the hope that it will be useful, | |
+ but WITHOUT ANY WARRANTY; without even the implied warranty of | |
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
+ GNU General Public License for more details. | |
+ | |
+ You should have received a copy of the GNU General Public License | |
+ along with this program; if not, write to the Free Software | |
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
+*/ | |
+ | |
+/* This file implements the service registration functionality */ | |
+ | |
+/* Basically, it uses normal Service Location Protocol API */ | |
+ | |
+#include "rsync.h" | |
+#include "slp.h" | |
+#include "netdb.h" | |
+ | |
+extern int rsync_port; | |
+ | |
+static void slp_callback(UNUSED(SLPHandle hslp), SLPError errcode, void *cookie) | |
+{ | |
+ /* return the error code in the cookie */ | |
+ *(SLPError*)cookie = errcode; | |
+ | |
+ /* You could do something else here like print out | |
+ * the errcode, etc. Remember, as a general rule, | |
+ * do not try to do too much in a callback because | |
+ * it is being executed by the same thread that is | |
+ * reading slp packets from the wire. */ | |
+} | |
+ | |
+int register_services(void) | |
+{ | |
+ SLPError err, callbackerr; | |
+ SLPHandle hslp; | |
+ int n; | |
+ int i; | |
+ char srv[120]; | |
+ char attr[120]; | |
+ char localhost[256]; | |
+ extern char *config_file; | |
+ short timeout; | |
+ struct addrinfo aih, *ai = 0; | |
+ | |
+ if (!lp_load(config_file, 0)) { | |
+ exit_cleanup(RERR_SYNTAX); | |
+ } | |
+ | |
+ n = lp_numservices(); | |
+ | |
+ if (0 == lp_slp_refresh()) | |
+ timeout = SLP_LIFETIME_MAXIMUM; /* don't expire, ever */ | |
+ else if (SLP_MIN_TIMEOUT > lp_slp_refresh()) | |
+ timeout = SLP_MIN_TIMEOUT; /* use a reasonable minimum */ | |
+ else if (SLP_LIFETIME_MAXIMUM <= lp_slp_refresh()) | |
+ timeout = (SLP_LIFETIME_MAXIMUM - 1); /* as long as possible */ | |
+ else | |
+ timeout = lp_slp_refresh(); | |
+ | |
+ rprintf(FINFO, "rsyncd registering %d service%s with slpd for %d seconds:\n", n, ((n==1)? "":"s"), timeout); | |
+ err = SLPOpen("en",SLP_FALSE,&hslp); | |
+ if (err != SLP_OK) { | |
+ rprintf(FINFO, "Error opening slp handle %i\n",err); | |
+ return err; | |
+ } | |
+ if (gethostname(localhost, sizeof localhost)) { | |
+ rprintf(FINFO, "Could not get hostname: %s\n", strerror(errno)); | |
+ return err; | |
+ } | |
+ memset(&aih, 0, sizeof aih); | |
+ aih.ai_family = PF_UNSPEC; | |
+ aih.ai_flags = AI_CANONNAME; | |
+ if (0 != (err = getaddrinfo(localhost, 0, &aih, &ai)) || !ai) { | |
+ rprintf(FINFO, "Could not resolve hostname: %s\n", gai_strerror(err)); | |
+ return err; | |
+ } | |
+ /* Register each service with SLP */ | |
+ for (i = 0; i < n; i++) { | |
+ if (!lp_list(i)) | |
+ continue; | |
+ | |
+ snprintf(srv, sizeof srv, "service:rsync://%s:%d/%s", | |
+ ai->ai_canonname, | |
+ rsync_port, | |
+ lp_name(i)); | |
+ rprintf(FINFO, " %s\n", srv); | |
+ if (lp_comment(i)) { | |
+ snprintf(attr, sizeof attr, "(comment=%s)", | |
+ lp_comment(i)); | |
+ } | |
+ err = SLPReg(hslp, | |
+ srv, /* service to register */ | |
+ timeout, | |
+ 0, /* this is ignored */ | |
+ attr, /* attributes */ | |
+ SLP_TRUE, /* new registration - don't change this */ | |
+ slp_callback, /* callback */ | |
+ &callbackerr); | |
+ | |
+ /* err may contain an error code that occurred as the slp library | |
+ * _prepared_ to make the call. */ | |
+ if (err != SLP_OK || callbackerr != SLP_OK) | |
+ rprintf(FINFO, "Error registering service with slp %i\n", err); | |
+ | |
+ /* callbackerr may contain an error code (that was assigned through | |
+ * the callback cookie) that occurred as slp packets were sent on | |
+ * the wire. */ | |
+ if (callbackerr != SLP_OK) | |
+ rprintf(FINFO, "Error registering service with slp %i\n",callbackerr); | |
+ } | |
+ | |
+ /* Now that we're done using slp, close the slp handle */ | |
+ freeaddrinfo(ai); | |
+ SLPClose(hslp); | |
+ | |
+ /* refresh is done in main select loop */ | |
+ return 0; | |
+} | |
diff -up a/config.h.in b/config.h.in | |
--- a/config.h.in | |
+++ b/config.h.in | |
@@ -197,6 +197,9 @@ | |
/* Define to 1 if you have the `sec' library (-lsec). */ | |
#undef HAVE_LIBSEC | |
+/* Define to 1 for SLP support */ | |
+#undef HAVE_LIBSLP | |
+ | |
/* Define to 1 if you have the `socket' library (-lsocket). */ | |
#undef HAVE_LIBSOCKET | |
diff -up a/configure.sh b/configure.sh | |
--- a/configure.sh | |
+++ b/configure.sh | |
@@ -606,6 +606,8 @@ BUILD_POPT | |
CC_SHOBJ_FLAG | |
OBJ_RESTORE | |
OBJ_SAVE | |
+SLPOBJ | |
+LIBSLP | |
ALLOCA | |
LIBOBJS | |
HAVE_YODL2MAN | |
@@ -686,6 +688,9 @@ enable_ipv6 | |
enable_locale | |
enable_iconv_open | |
enable_iconv | |
+enable_slp | |
+with_openslp_libs | |
+with_openslp_includes | |
enable_acl_support | |
enable_xattr_support | |
' | |
@@ -1320,6 +1325,7 @@ Optional Features: | |
--disable-locale disable locale features | |
--disable-iconv-open disable all use of iconv_open() function | |
--disable-iconv disable rsync's --iconv option | |
+ --disable-slp turn off SLP support, defaults to on | |
--disable-acl-support disable ACL support | |
--disable-xattr-support disable extended attributes | |
@@ -1334,6 +1340,8 @@ Optional Packages: | |
--with-nobody-group=GROUP | |
set the default unprivileged group (default nobody | |
or nogroup) | |
+ --with-openslp-libs set directory for OpenSLP library | |
+ --with-openslp-includes set directory for OpenSLP includes | |
Some influential environment variables: | |
CC C compiler command | |
@@ -7685,6 +7693,85 @@ $as_echo "#define CAN_HARDLINK_SPECIAL 1 | |
fi | |
+# Check whether --enable-slp was given. | |
+if test "${enable_slp+set}" = set; then : | |
+ enableval=$enable_slp; | |
+fi | |
+ | |
+ | |
+# Check whether --with-openslp-libs was given. | |
+if test "${with_openslp_libs+set}" = set; then : | |
+ withval=$with_openslp_libs; LDFLAGS="-L$withval $LDFLAGS" | |
+ DSOFLAGS="-L$withval $DSOFLAGS" | |
+fi | |
+ | |
+ | |
+# Check whether --with-openslp-includes was given. | |
+if test "${with_openslp_includes+set}" = set; then : | |
+ withval=$with_openslp_includes; CFLAGS="-I$withval $CFLAGS" | |
+ CXXFLAGS="-I$withval $CXXFLAGS" | |
+ CPPFLAGS="-I$withval $CPPFLAGS" | |
+fi | |
+ | |
+ | |
+LIBSLP="" | |
+SLPOBJ="" | |
+ | |
+if test x$enable_slp != xno; then | |
+ ac_fn_c_check_header_mongrel "$LINENO" "slp.h" "ac_cv_header_slp_h" "$ac_includes_default" | |
+if test "x$ac_cv_header_slp_h" = xyes; then : | |
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SLPOpen in -lslp" >&5 | |
+$as_echo_n "checking for SLPOpen in -lslp... " >&6; } | |
+if ${ac_cv_lib_slp_SLPOpen+:} false; then : | |
+ $as_echo_n "(cached) " >&6 | |
+else | |
+ ac_check_lib_save_LIBS=$LIBS | |
+LIBS="-lslp $LIBS" | |
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext | |
+/* end confdefs.h. */ | |
+ | |
+/* Override any GCC internal prototype to avoid an error. | |
+ Use char because int might match the return type of a GCC | |
+ builtin and then its argument prototype would still apply. */ | |
+#ifdef __cplusplus | |
+extern "C" | |
+#endif | |
+char SLPOpen (); | |
+int | |
+main () | |
+{ | |
+return SLPOpen (); | |
+ ; | |
+ return 0; | |
+} | |
+_ACEOF | |
+if ac_fn_c_try_link "$LINENO"; then : | |
+ ac_cv_lib_slp_SLPOpen=yes | |
+else | |
+ ac_cv_lib_slp_SLPOpen=no | |
+fi | |
+rm -f core conftest.err conftest.$ac_objext \ | |
+ conftest$ac_exeext conftest.$ac_ext | |
+LIBS=$ac_check_lib_save_LIBS | |
+fi | |
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_slp_SLPOpen" >&5 | |
+$as_echo "$ac_cv_lib_slp_SLPOpen" >&6; } | |
+if test "x$ac_cv_lib_slp_SLPOpen" = xyes; then : | |
+ | |
+$as_echo "#define HAVE_LIBSLP 1" >>confdefs.h | |
+ | |
+ SLPOBJ="srvreg.o srvloc.o" | |
+ LIBSLP="-lslp" | |
+fi | |
+ | |
+fi | |
+ | |
+ | |
+fi | |
+ | |
+ | |
+ | |
+ | |
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working socketpair" >&5 | |
$as_echo_n "checking for working socketpair... " >&6; } | |
if ${rsync_cv_HAVE_SOCKETPAIR+:} false; then : | |
diff -up a/proto.h b/proto.h | |
--- a/proto.h | |
+++ b/proto.h | |
@@ -183,6 +183,8 @@ char *lp_motd_file(void); | |
char *lp_pid_file(void); | |
char *lp_socket_options(void); | |
int lp_rsync_port(void); | |
+int lp_slp_refresh(void); | |
+BOOL lp_use_slp(void); | |
char *lp_auth_users(int module_id); | |
char *lp_charset(int module_id); | |
char *lp_comment(int module_id); | |
@@ -294,6 +296,8 @@ int open_socket_out_wrapped(char *host, | |
int is_a_socket(int fd); | |
void start_accept_loop(int port, int (*fn)(int, int)); | |
void set_socket_options(int fd, char *options); | |
+int print_service_list(void); | |
+int register_services(void); | |
int do_unlink(const char *fname); | |
int do_symlink(const char *fname1, const char *fname2); | |
int do_link(const char *fname1, const char *fname2); | |
diff -up a/rsync.1 b/rsync.1 | |
--- a/rsync.1 | |
+++ b/rsync.1 | |
@@ -180,7 +180,15 @@ particular rsync daemon by leaving off t | |
.RE | |
.PP | |
-See the following section for more details. | |
+And, if Service Location Protocol is available, the following will list the | |
+available rsync servers: | |
+.PP | |
+.RS | |
+\f(CWrsync rsync://\fP | |
+.RE | |
+ | |
+.PP | |
+See the following section for even more usage details. | |
.PP | |
.SH "ADVANCED USAGE" | |
diff -up a/rsyncd.conf.5 b/rsyncd.conf.5 | |
--- a/rsyncd.conf.5 | |
+++ b/rsyncd.conf.5 | |
@@ -121,6 +121,21 @@ details on some of the options you may b | |
special socket options are set. These settings can also be specified | |
via the \fB\-\-sockopts\fP command\-line option. | |
.IP | |
+.IP "\fBuse slp\fP" | |
+This parameter is used to determine if the module names are | |
+advertised via slp. The default is for this to be enabled, which will | |
+advertise your public modules. | |
+.IP | |
+.IP "\fBslp refresh\fP" | |
+This parameter is used to determine how long service | |
+advertisements are valid (measured in seconds), and is only applicable if | |
+you have Service Location Protocol support compiled in. If this is | |
+not set or is set to zero, then service advertisements never timeout. If | |
+this is set to less than 120 seconds, then 120 seconds is used. If it is | |
+set to more than 65535, then 65535 is used (which is a limitation of SLP). | |
+Using 3600 (one hour) is a good number if you tend to change your | |
+configuration. | |
+.IP | |
.SH "MODULE PARAMETERS" | |
.PP | |
@@ -770,6 +785,7 @@ use chroot = yes | |
max connections = 4 | |
syslog facility = local5 | |
pid file = /var/run/rsyncd.pid | |
+slp refresh = 3600 | |
[ftp] | |
path = /var/ftp/./pub |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment