/* -*- c-file-style: "linux"; -*- Copyright (C) 2002 by Brad Hards 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_num_modules(); 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; }