#include <atalk/util.h>
#include <atalk/dsi.h>
#include <atalk/unicode.h>
+#include <atalk/netatalk_conf.h>
#include "afp_zeroconf.h"
#include "afp_mdns.h"
-#include "afp_config.h"
-#include "volume.h"
/*
* We'll store all the DNSServiceRef's here so that we can
/*
* Its easier to use asprintf to set the TXT record values
*/
-#define TXTRecordPrintf(rec, key, args...) { \
- char *str; \
- asprintf(&str, args); \
- TXTRecordSetValue(rec, key, strlen(str), str); \
- free(str); \
+
+int TXTRecordPrintf(TXTRecordRef * rec, const char * key, const char * fmt, ... )
+{
+ int ret = 0;
+ char *str;
+ va_list ap;
+ va_start( ap, fmt );
+
+ if( 0 > vasprintf(&str, fmt, ap ) ) {
+ va_end(ap);
+ return -1;
+ }
+ va_end(ap);
+
+ if( kDNSServiceErr_NoError != TXTRecordSetValue(rec, key, strlen(str), str) ) {
+ ret = -1;
+ }
+
+ free(str);
+ return ret;
+}
+
+int TXTRecordKeyPrintf(TXTRecordRef * rec, const char * key_fmt, int key_var, const char * fmt, ...)
+{
+ int ret = 0;
+ char *key = NULL, *str = NULL;
+ va_list ap;
+
+ if( 0 > asprintf(&key, key_fmt, key_var))
+ return -1;
+
+ va_start( ap, fmt );
+ if( 0 > vasprintf(&str, fmt, ap )) {
+ va_end(ap);
+ ret = -1;
+ goto exit;
}
-#define TXTRecordKeyPrintf(rec, k, var, args...) { \
- char *key, *str; \
- asprintf(&key, k, var); \
- asprintf(&str, args); \
- TXTRecordSetValue(rec, key, strlen(str), str); \
- free(str); free(key); \
+ va_end(ap);
+
+ if( kDNSServiceErr_NoError != TXTRecordSetValue(rec, key, strlen(str), str) ) {
+ ret = -1;
+ goto exit;
}
+exit:
+ if (str)
+ free(str);
+ if (key)
+ free(key);
+ return ret;
+}
+
+static struct pollfd *fds;
/*
* This is the thread that polls the filehandles
*/
-void *polling_thread(void *arg) {
+static void *polling_thread(void *arg) {
// First we loop through getting the filehandles and adding them to our poll, we
// need to allocate our pollfd's
DNSServiceErrorType error;
- struct pollfd *fds = calloc(svc_ref_count, sizeof(struct pollfd));
+ fds = calloc(svc_ref_count, sizeof(struct pollfd));
assert(fds);
for(int i=0; i < svc_ref_count; i++) {
return(NULL);
}
-
/*
* This is the callback for the service register function ... actually there isn't a lot
* we can do if we get problems, so we don't really need to do anything other than report
* the issue.
*/
-void RegisterReply(DNSServiceRef sdRef, DNSServiceFlags flags, DNSServiceErrorType errorCode,
- const char *name, const char *regtype, const char *domain, void *context) {
-
- if(errorCode != kDNSServiceErr_NoError) {
+static void RegisterReply(DNSServiceRef sdRef, DNSServiceFlags flags, DNSServiceErrorType errorCode,
+ const char *name, const char *regtype, const char *domain, void *context)
+{
+ if (errorCode != kDNSServiceErr_NoError) {
LOG(log_error, logtype_afpd, "Failed to register mDNS service: %s%s%s: code=%d",
name, regtype, domain, errorCode);
}
}
-
/*
* This function unregisters anything we have already
* registered and frees associated memory
*/
static void unregister_stuff() {
- pthread_kill(poller, SIGKILL);
+ pthread_cancel(poller);
+
+ for (int i = 0; i < svc_ref_count; i++)
+ close(fds[i].fd);
+ free(fds);
+ fds = NULL;
+
if(svc_refs) {
for(int i=0; i < svc_ref_count; i++) {
DNSServiceRefDeallocate(svc_refs[i]);
* This function tries to register the AFP DNS
* SRV service type.
*/
-static void register_stuff(const AFPConfig *configs) {
+static void register_stuff(const AFPObj *obj) {
uint port;
- const AFPConfig *config;
const struct vol *volume;
DSI *dsi;
char name[MAXINSTANCENAMELEN+1];
/* Register our service, prepare the TXT record */
TXTRecordCreate(&txt_adisk, 0, NULL);
- TXTRecordPrintf(&txt_adisk, "sys", "waMa=0,adVF=0x100");
+ if( 0 > TXTRecordPrintf(&txt_adisk, "sys", "waMa=0,adVF=0x100") ) {
+ LOG ( log_error, logtype_afpd, "Could not create Zeroconf TXTRecord for sys");
+ goto fail;
+ }
/* Build AFP volumes list */
int i = 0;
if (volume->v_uuid) {
LOG(log_info, logtype_afpd, "Registering volume '%s' with UUID: '%s' for TimeMachine",
volume->v_localname, volume->v_uuid);
- TXTRecordKeyPrintf(&txt_adisk, "dk%u", i++, "adVN=%s,adVF=0xa1,adVU=%s",
- tmpname, volume->v_uuid);
+ if( 0 > TXTRecordKeyPrintf(&txt_adisk, "dk%u", i++, "adVN=%s,adVF=0xa1,adVU=%s",
+ tmpname, volume->v_uuid) ) {
+ LOG ( log_error, logtype_afpd, "Could not set Zeroconf TXTRecord for dk%u", i);
+ goto fail;
+ }
} else {
LOG(log_warning, logtype_afpd, "Registering volume '%s' for TimeMachine. But UUID is invalid.",
volume->v_localname);
- TXTRecordKeyPrintf(&txt_adisk, "dk%u", i++, "adVN=%s,adVF=0xa1", tmpname);
+ if( 0 > TXTRecordKeyPrintf(&txt_adisk, "dk%u", i++, "adVN=%s,adVF=0xa1", tmpname) ) {
+ LOG ( log_error, logtype_afpd, "Could not set Zeroconf TXTRecord for dk%u", i);
+ goto fail;
+ }
}
}
}
// Now we can count the configs so we know how many service
// records to allocate
- for (config = configs; config; config = config->next) {
+ for (dsi = obj->dsi; dsi; dsi = dsi->next) {
svc_ref_count++; // AFP_DNS_SERVICE_TYPE
- if(i) svc_ref_count++; // ADISK_SERVICE_TYPE
- if (config->obj.options.mimicmodel) svc_ref_count++; // DEV_INFO_SERVICE_TYPE
+ if (i) svc_ref_count++; // ADISK_SERVICE_TYPE
+ if (obj->options.mimicmodel) svc_ref_count++; // DEV_INFO_SERVICE_TYPE
}
// Allocate the memory to store our service refs
svc_refs = calloc(svc_ref_count, sizeof(DNSServiceRef));
- assert(svc_ref);
+ assert(svc_refs);
svc_ref_count = 0;
/* AFP server */
- for (config = configs; config; config = config->next) {
+ for (dsi = obj->dsi; dsi; dsi = dsi->next) {
- dsi = (DSI *)config->obj.handle;
port = getip_port((struct sockaddr *)&dsi->server);
- if (convert_string(config->obj.options.unixcharset,
+ if (convert_string(obj->options.unixcharset,
CH_UTF8,
- config->obj.options.server ?
- config->obj.options.server :
- config->obj.options.hostname,
+ obj->options.hostname,
-1,
name,
MAXINSTANCENAMELEN) <= 0) {
}
}
- if (config->obj.options.mimicmodel) {
+ if (obj->options.mimicmodel) {
+ LOG(log_info, logtype_afpd, "Registering server '%s' with model '%s'",
+ dsi->bonjourname, obj->options.mimicmodel);
TXTRecordCreate(&txt_devinfo, 0, NULL);
- TXTRecordPrintf(&txt_devinfo, "model", config->obj.options.mimicmodel);
+ if( 0 > TXTRecordPrintf(&txt_devinfo, "model", obj->options.mimicmodel) ) {
+ LOG ( log_error, logtype_afpd, "Could not create Zeroconf TXTRecord for model");
+ goto fail;
+ }
+
error = DNSServiceRegister(&svc_refs[svc_ref_count++],
0, // no flags
0, // all network interfaces
DEV_INFO_SERVICE_TYPE,
"", // default domains
NULL, // default host name
- htons(port),
+ /*
+ * We would probably use port 0 zero, but we can't, from man DNSServiceRegister:
+ * "A value of 0 for a port is passed to register placeholder services.
+ * Place holder services are not found when browsing, but other
+ * clients cannot register with the same name as the placeholder service."
+ * We therefor use port 9 which is used by the adisk service type.
+ */
+ htons(9),
TXTRecordGetLength(&txt_devinfo),
TXTRecordGetBytesPtr(&txt_devinfo),
RegisterReply, // callback
* Tries to setup the Zeroconf thread and any
* neccessary config setting.
*/
-void md_zeroconf_register(const AFPConfig *configs) {
+void md_zeroconf_register(const AFPObj *obj) {
int error;
- register_stuff(configs);
+ register_stuff(obj);
return;
}