Commit | Line | Data |
---|---|---|
9978080e WD |
1 | This adds Service Location Protocol support. |
2 | ||
03019e41 | 3 | To 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 |
10 | TODO: the configure changes should abort if the user requests --enable-slp |
11 | and we can't honor that request. | |
12 | ||
cc3e685d | 13 | diff --git a/Makefile.in b/Makefile.in |
fc557362 | 14 | index 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 | 44 | diff --git a/clientserver.c b/clientserver.c |
fc557362 | 45 | index 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 | 62 | diff --git a/configure.in b/configure.in |
fc557362 | 63 | index 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 | 96 | diff --git a/loadparm.c b/loadparm.c |
fc557362 | 97 | index 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 | 130 | diff --git a/main.c b/main.c |
fc557362 | 131 | index 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 | 153 | diff --git a/options.c b/options.c |
fc557362 | 154 | index 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 | 186 | diff --git a/rsync.h b/rsync.h |
fc557362 | 187 | index 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 | 201 | diff --git a/rsync.yo b/rsync.yo |
fc557362 | 202 | index 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 |
219 | diff --git a/rsyncd.conf b/rsyncd.conf |
220 | new file mode 100644 | |
fc557362 | 221 | index 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 | 228 | diff --git a/rsyncd.conf.yo b/rsyncd.conf.yo |
fc557362 | 229 | index 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 | 256 | diff --git a/socket.c b/socket.c |
fc557362 | 257 | index 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 |
323 | diff --git a/srvloc.c b/srvloc.c |
324 | new file mode 100644 | |
fc557362 | 325 | index 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 |
432 | diff --git a/srvreg.c b/srvreg.c |
433 | new file mode 100644 | |
fc557362 | 434 | index 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 | +} |