-Changes in ?.?.?
+Changes in 2.2.3
================
+* NEW: afpd: support for mdnsresponder
+* NEW: afpd: new LDAP config option ldap_uuid_string
* UPD: based on Unicode 6.1.0
* UPD: experimental systemd service files: always run both afpd and cnid_metad
+* UPD: afpd: Ensure our umask is not altered by eg pam_umask
+* UPD: afpd: Use GSS_C_NO_NAME as server principal when Kerberos options -fqdn
+ and -krb5service are not set, from Jamie Gilbertson
+* FIX: afpd: sendfile() on FreeBSD was broken, courtesy of Denis Ahrens
+* FIX: afpd: Dont use searchdb when doing partial name search
+* FIX: afpd: Fix a possible bug handling disconnected sessions, NetAFP Bug ID #16
Changes in 2.2.2
================
-2.2.2
\ No newline at end of file
+2.2.3dev
\ No newline at end of file
+# Netatalk 2.x afp volume cofiguration
# This file looks empty when viewed with "vi". In fact, there is one
# '~', so users with no AppleVolumes file in their home directory get
# their home directory by default.
-# ($Id)
+# Netatalk 2.x afp volume configuration
###
### Delete a '#' character at the head of line if you need.
### If clients are Mac OS X only, it is not especially necessary.
+# Netatalk 2.x LDAP configuration
+
# ldap_server = localhost
# ldap_auth_method = simple
# ldap_auth_dn = cn=admin,dc=domain,dc=org
#
-# CONFIGURATION FOR AFPD
+# CONFIGURATION FOR AFPD (Netatalk 2.x)
#
# Each single line defines a virtual server that should be available.
# Though, using "\" character, newline escaping is supported.
-# Netatalk configuration
+# Netatalk 2.x configuration
#########################################################################
# Global configuration
afp_avahi.c \
afp_config.c \
afp_dsi.c \
+ afp_mdns.c \
afp_options.c \
afp_util.c \
afp_zeroconf.c \
noinst_HEADERS = auth.h afp_config.h desktop.h directory.h fce_api_internal.h file.h \
filedir.h fork.h icon.h mangle.h misc.h status.h switch.h \
uam_auth.h uid.h unix.h volume.h hash.h acls.h acl_mappings.h extattrs.h \
- dircache.h afp_zeroconf.h afp_avahi.h
+ dircache.h afp_zeroconf.h afp_avahi.h afp_mdns.h
hash_SOURCES = hash.c
hash_CFLAGS = -DKAZLIB_TEST_MAIN -I$(top_srcdir)/include
#include <atalk/dsi.h>
#include <atalk/unicode.h>
+#include "afp_zeroconf.h"
#include "afp_avahi.h"
#include "afp_config.h"
#include "volume.h"
#include "afp_config.h"
-#define AFP_DNS_SERVICE_TYPE "_afpovertcp._tcp"
-#define ADISK_SERVICE_TYPE "_adisk._tcp"
-#define DEV_INFO_SERVICE_TYPE "_device-info._tcp"
-
-#define MAXINSTANCENAMELEN 63
-
struct context {
/* Avahi stuff */
int thread_running;
--- /dev/null
+/*
+ * Author: Lee Essen <lee.essen@nowonline.co.uk>
+ * Based on: avahi support from Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ * Purpose: mdns based Zeroconf support
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_MDNS
+
+#include <unistd.h>
+#include <time.h>
+#include <pthread.h>
+#include <poll.h>
+
+#include <atalk/logger.h>
+#include <atalk/util.h>
+#include <atalk/dsi.h>
+#include <atalk/unicode.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
+ * deallocate them later
+ */
+static DNSServiceRef *svc_refs = NULL;
+static int svc_ref_count = 0;
+static pthread_t poller;
+
+/*
+ * 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); \
+ }
+#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); \
+ }
+
+
+/*
+ * This is the thread that polls the filehandles
+ */
+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));
+ assert(fds);
+
+ for(int i=0; i < svc_ref_count; i++) {
+ int fd = DNSServiceRefSockFD(svc_refs[i]);
+ fds[i].fd = fd;
+ fds[i].events = POLLIN;
+ }
+
+ // Now we can poll and process the results...
+ while(poll(fds, svc_ref_count, -1) > 0) {
+ for(int i=0; i < svc_ref_count; i++) {
+ if(fds[i].revents & POLLIN) {
+ error = DNSServiceProcessResult(svc_refs[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) {
+ 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);
+ if(svc_refs) {
+ for(int i=0; i < svc_ref_count; i++) {
+ DNSServiceRefDeallocate(svc_refs[i]);
+ }
+ free(svc_refs);
+ svc_refs = NULL;
+ svc_ref_count = 0;
+ }
+}
+
+/*
+ * This function tries to register the AFP DNS
+ * SRV service type.
+ */
+static void register_stuff(const AFPConfig *configs) {
+ uint port;
+ const AFPConfig *config;
+ const struct vol *volume;
+ DSI *dsi;
+ char name[MAXINSTANCENAMELEN+1];
+ DNSServiceErrorType error;
+ TXTRecordRef txt_adisk;
+ TXTRecordRef txt_devinfo;
+ char tmpname[256];
+
+ // If we had already registered, then we will unregister and re-register
+ if(svc_refs) unregister_stuff();
+
+ /* Register our service, prepare the TXT record */
+ TXTRecordCreate(&txt_adisk, 0, NULL);
+ TXTRecordPrintf(&txt_adisk, "sys", "waMa=0,adVF=0x100");
+
+ /* Build AFP volumes list */
+ int i = 0;
+
+ for (volume = getvolumes(); volume; volume = volume->v_next) {
+
+ if (convert_string(CH_UCS2, CH_UTF8_MAC, volume->v_name, -1, tmpname, 255) <= 0) {
+ LOG ( log_error, logtype_afpd, "Could not set Zeroconf volume name for TimeMachine");
+ goto fail;
+ }
+
+ if (volume->v_flags & AFPVOL_TM) {
+ 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);
+ } 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);
+ }
+ }
+ }
+
+ // Now we can count the configs so we know how many service
+ // records to allocate
+ for (config = configs; config; config = config->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
+ }
+
+ // Allocate the memory to store our service refs
+ svc_refs = calloc(svc_ref_count, sizeof(DNSServiceRef));
+ assert(svc_ref);
+ svc_ref_count = 0;
+
+ /* AFP server */
+ for (config = configs; config; config = config->next) {
+
+ dsi = (DSI *)config->obj.handle;
+ port = getip_port((struct sockaddr *)&dsi->server);
+
+ if (convert_string(config->obj.options.unixcharset,
+ CH_UTF8,
+ config->obj.options.server ?
+ config->obj.options.server :
+ config->obj.options.hostname,
+ -1,
+ name,
+ MAXINSTANCENAMELEN) <= 0) {
+ LOG(log_error, logtype_afpd, "Could not set Zeroconf instance name");
+ goto fail;
+ }
+ if ((dsi->bonjourname = strdup(name)) == NULL) {
+ LOG(log_error, logtype_afpd, "Could not set Zeroconf instance name");
+ goto fail;
+
+ }
+ LOG(log_info, logtype_afpd, "Registering server '%s' with Bonjour",
+ dsi->bonjourname);
+
+ error = DNSServiceRegister(&svc_refs[svc_ref_count++],
+ 0, // no flags
+ 0, // all network interfaces
+ dsi->bonjourname,
+ AFP_DNS_SERVICE_TYPE,
+ "", // default domains
+ NULL, // default host name
+ htons(port),
+ 0, // length of TXT
+ NULL, // no TXT
+ RegisterReply, // callback
+ NULL); // no context
+ if(error != kDNSServiceErr_NoError) {
+ LOG(log_error, logtype_afpd, "Failed to add service: %s, error=%d",
+ AFP_DNS_SERVICE_TYPE, error);
+ goto fail;
+ }
+
+ if(i) {
+ error = DNSServiceRegister(&svc_refs[svc_ref_count++],
+ 0, // no flags
+ 0, // all network interfaces
+ dsi->bonjourname,
+ ADISK_SERVICE_TYPE,
+ "", // default domains
+ NULL, // default host name
+ htons(port),
+ TXTRecordGetLength(&txt_adisk),
+ TXTRecordGetBytesPtr(&txt_adisk),
+ RegisterReply, // callback
+ NULL); // no context
+ if(error != kDNSServiceErr_NoError) {
+ LOG(log_error, logtype_afpd, "Failed to add service: %s, error=%d",
+ ADISK_SERVICE_TYPE, error);
+ goto fail;
+ }
+ }
+
+ if (config->obj.options.mimicmodel) {
+ TXTRecordCreate(&txt_devinfo, 0, NULL);
+ TXTRecordPrintf(&txt_devinfo, "model", config->obj.options.mimicmodel);
+ error = DNSServiceRegister(&svc_refs[svc_ref_count++],
+ 0, // no flags
+ 0, // all network interfaces
+ dsi->bonjourname,
+ DEV_INFO_SERVICE_TYPE,
+ "", // default domains
+ NULL, // default host name
+ htons(port),
+ TXTRecordGetLength(&txt_devinfo),
+ TXTRecordGetBytesPtr(&txt_devinfo),
+ RegisterReply, // callback
+ NULL); // no context
+ TXTRecordDeallocate(&txt_devinfo);
+ if(error != kDNSServiceErr_NoError) {
+ LOG(log_error, logtype_afpd, "Failed to add service: %s, error=%d",
+ DEV_INFO_SERVICE_TYPE, error);
+ goto fail;
+ }
+ } /* if (config->obj.options.mimicmodel) */
+ } /* for config*/
+
+ /*
+ * Now we can create the thread that will poll for the results
+ * and handle the calling of the callbacks
+ */
+ if(pthread_create(&poller, NULL, polling_thread, NULL) != 0) {
+ LOG(log_error, logtype_afpd, "Unable to start mDNS polling thread");
+ goto fail;
+ }
+
+fail:
+ TXTRecordDeallocate(&txt_adisk);
+ return;
+}
+
+/************************************************************************
+ * Public funcions
+ ************************************************************************/
+
+/*
+ * Tries to setup the Zeroconf thread and any
+ * neccessary config setting.
+ */
+void md_zeroconf_register(const AFPConfig *configs) {
+ int error;
+
+ register_stuff(configs);
+ return;
+}
+
+/*
+ * Tries to shutdown this loop impl.
+ * Call this function from inside this thread.
+ */
+int md_zeroconf_unregister() {
+ unregister_stuff();
+ return 0;
+}
+
+#endif /* USE_MDNS */
+
--- /dev/null
+/*
+ * Author: Lee Essen <lee.essen@nowonline.co.uk>
+ * Based on: avahi support from Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ * Purpose: mdns based Zeroconf support
+ */
+
+#ifndef AFPD_MDNS_H
+#define AFPD_MDNS_H
+
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+#include <dns_sd.h>
+
+#include <atalk/logger.h>
+
+#include "afp_config.h"
+
+/* prototype definitions */
+void md_zeroconf_register(const AFPConfig *configs);
+int md_zeroconf_unregister(void);
+
+#endif /* AFPD_MDNS_H */
#endif
printf( " Zeroconf support:\t" );
-#ifdef USE_ZEROCONF
- puts( "Yes" );
+#if defined (HAVE_MDNS)
+ puts( "mDNSResponder" );
+#elif defined (HAVE_AVAHI)
+ puts( "Avahi" );
#else
puts( "No" );
#endif
#include "afp_zeroconf.h"
#include "afp_config.h"
-#ifdef HAVE_AVAHI
+#ifdef HAVE_MDNS
+#include "afp_mdns.h"
+#elif defined (HAVE_AVAHI)
#include "afp_avahi.h"
#endif
*/
void zeroconf_register(const AFPConfig *configs)
{
-#if defined (HAVE_AVAHI)
+#if defined (HAVE_MDNS)
+ LOG(log_debug, logtype_afpd, "Attempting to register with mDNS using mDNSResponder");
+
+ md_zeroconf_register(configs);
+#elif defined (HAVE_AVAHI)
LOG(log_debug, logtype_afpd, "Attempting to register with mDNS using Avahi");
av_zeroconf_register(configs);
void zeroconf_deregister(void)
{
-#if defined (HAVE_AVAHI)
+#if defined (HAVE_MDNS)
+ LOG(log_debug, logtype_afpd, "Attempting to de-register mDNS using mDNSResponder");
+ md_zeroconf_unregister();
+#elif defined (HAVE_AVAHI)
LOG(log_debug, logtype_afpd, "Attempting to de-register mDNS using Avahi");
av_zeroconf_unregister();
#endif
#include "afp_config.h"
+#define AFP_DNS_SERVICE_TYPE "_afpovertcp._tcp"
+#define ADISK_SERVICE_TYPE "_adisk._tcp"
+#define DEV_INFO_SERVICE_TYPE "_device-info._tcp"
+
+#define MAXINSTANCENAMELEN 63
+
/*
* Prototype Definitions
*/
#include "misc.h"
#include "unix.h"
-int afs_getvolspace( vol, bfree, btotal, bsize )
-struct vol *vol;
-VolSpace *bfree, *btotal;
-u_int32_t *bsize;
+int afs_getvolspace(struct vol *vol, VolSpace *bfree, VolSpace *btotal, u_int32_t *bsize)
{
struct ViceIoctl vi;
struct VolumeStatus *vs;
#undef accessmode
#endif
-void afsmode( vol, path, ma, dir, st )
-const struct volume *vol;
-char *path;
-struct maccess *ma;
-struct dir *dir;
-struct stat *st;
+void afsmode(const struct volume *vol, char *path, struct maccess *ma, struct dir *dir, struct stat *st)
{
struct ViceIoctl vi;
char buf[ 1024 ];
mpath = obj->newtmp;
mp = makemacpath( vol, mpath, AFPOBJ_TMPSIZ, curdir, path->m_name );
if (!mp) {
+ close(tfd);
return AFPERR_PARAM ;
}
save_uidgid ( &obj->uidgid );
#endif
+ /* pam_umask or similar might have changed our umask */
+ (void)umask(obj->options.umask);
+
return( AFP_OK );
}
#define DS_BSIZE 128
static int save_cidx = -1; /* Saved index of currently scanned directory. */
-
static struct dsitem *dstack = NULL; /* Directory stack data... */
static int dssize = 0; /* Directory stack (allocated) size... */
static int dsidx = 0; /* First free item index... */
-
static struct scrit c1, c2; /* search criteria */
+/* Clears directory stack. */
+static void clearstack(void)
+{
+ save_cidx = -1;
+ while (dsidx > 0) {
+ dsidx--;
+ free(dstack[dsidx].path);
+ }
+}
+
/* Puts new item onto directory stack. */
static int addstack(char *uname, struct dir *dir, int pidx)
{
struct dsitem *ds;
size_t l, u;
+ struct dsitem *tmpds = NULL;
/* check if we have some space on stack... */
if (dsidx >= dssize) {
dssize += DS_BSIZE;
- dstack = realloc(dstack, dssize * sizeof(struct dsitem));
- if (dstack == NULL)
+ tmpds = realloc(dstack, dssize * sizeof(struct dsitem));
+ if (tmpds == NULL) {
+ clearstack();
+ free(dstack);
return -1;
+ }
+ dstack = tmpds;
}
/* Put new element. Allocate and copy lname and path. */
return -1;
}
-/* Clears directory stack. */
-static void clearstack(void)
-{
- save_cidx = -1;
- while (dsidx > 0) {
- dsidx--;
- free(dstack[dsidx].path);
- }
-}
-
/* Looks up for an opened adouble structure, opens resource fork of selected file.
* FIXME What about noadouble?
*/
/* Call search */
*rbuflen = 24;
if ((c1.rbitmap & (1 << FILPBIT_PDINFO))
+ && !(c1.rbitmap & (1<<CATPBIT_PARTIAL))
&& (strcmp(vol->v_cnidscheme, "dbd") == 0)
&& (vol->v_flags & AFPVOL_SEARCHDB))
/* we've got a name and it's a dbd volume, so search CNID database */
err = vol->vfs->vfs_deletecurdir(vol);
if (err) {
LOG(log_error, logtype_afpd, "deletecurdir: error deleting .AppleDouble in \"%s\"",
- curdir->d_fullpath);
+ cfrombstr(curdir->d_fullpath));
return err;
}
static uint maxvol;
#define MAXSPAWN 3 /* Max times respawned in.. */
-#define TESTTIME 42 /* this much seconds apfd client tries to *
+#define TESTTIME 10 /* this much seconds apfd client tries to *
* to reconnect every 5 secondes, catch it */
#define MAXVOLS 4096
#define DEFAULTHOST "localhost"
struct volinfo *volinfo;
pid_t pid;
time_t tm; /* When respawned last */
- int count; /* Times respawned in the last TESTTIME secondes */
+ unsigned int count; /* Times respawned in the last TESTTIME secondes */
int control_fd; /* file descriptor to child cnid_dbd process */
};
return -1;
}
} else {
- /* we have a slot but no process, check for respawn too fast */
- if ( (t < (up->tm + TESTTIME)) /* We're in the respawn time window */
- &&
- (up->count > MAXSPAWN) ) { /* ...and already tried to fork too often */
- LOG(log_maxdebug, logtype_cnid, "maybe_start_dbd: respawn too fast just exiting");
- return -1; /* just exit, dont sleep, because we might have work to do for another client */
- }
- if ( t >= (up->tm + TESTTIME) ) { /* out of respawn too fast windows reset the count */
- LOG(log_maxdebug, logtype_cnid, "maybe_start_dbd: respawn window ended");
- up->tm = t;
- up->count = 0;
+ /* we have a slot but no process */
+ if (up->count > 0) {
+ /* check for respawn too fast */
+ if (t < (up->tm + TESTTIME)) {
+ /* We're in the respawn time window */
+ if (up->count > MAXSPAWN) {
+ /* ...and already tried to fork too often */
+ LOG(log_maxdebug, logtype_cnid, "maybe_start_dbd: respawning too fast");
+ return -1; /* just exit, dont sleep, because we might have work to do for another client */
+ }
+ } else {
+ /* out of respawn too fast windows reset the count */
+ LOG(log_info, logtype_cnid, "maybe_start_dbd: respawn window ended");
+ up->count = 0;
+ }
}
up->count++;
- LOG(log_maxdebug, logtype_cnid, "maybe_start_dbd: respawn count now is: %u", up->count);
+ up->tm = t;
+ LOG(log_maxdebug, logtype_cnid, "maybe_start_dbd: respawn count: %u", up->count);
if (up->count > MAXSPAWN) {
/* We spawned too fast. From now until the first time we tried + TESTTIME seconds
we will just return -1 above */
- LOG(log_maxdebug, logtype_cnid, "maybe_start_dbd: reached MAXSPAWN threshhold");
- }
+ LOG(log_info, logtype_cnid, "maybe_start_dbd: reached MAXSPAWN threshhold");
+ }
}
/*
}
}
if (WIFEXITED(status)) {
- LOG(log_info, logtype_cnid, "cnid_dbd pid %i exited with exit code %i",
+ LOG(log_info, logtype_cnid, "cnid_dbd[%i] exited with exit code %i",
pid, WEXITSTATUS(status));
+ } else {
+ /* cnid_dbd did a clean exit probably on idle timeout, reset bookkeeping */
+ srv[i].tm = 0;
+ srv[i].count = 0;
}
- else if (WIFSIGNALED(status)) {
- LOG(log_info, logtype_cnid, "cnid_dbd pid %i exited with signal %i",
+ if (WIFSIGNALED(status)) {
+ LOG(log_info, logtype_cnid, "cnid_dbd[%i] received signal %i",
pid, WTERMSIG(status));
}
sigchild = 0;
exit(1);
}
if (!getuid()) {
- LOG(log_info, logtype_cnid, "Setting uid/gid to %i/%i", st.st_uid, st.st_gid);
+ LOG(log_debug, logtype_cnid, "Setting uid/gid to %i/%i", st.st_uid, st.st_gid);
if (setgid(st.st_gid) < 0 || setuid(st.st_uid) < 0) {
LOG(log_error, logtype_cnid, "uid/gid: %s", strerror(errno));
exit(1);
static void log_principal(gss_name_t server_name)
{
#if 0
+ if (server_name == GSS_C_NO_NAME)
+ return;
/* FIXME: must call gss_canonicalize_name before gss_export_name */
OM_uint32 major_status = 0, minor_status = 0;
gss_buffer_desc exported_name;
size_t principal_length;
gss_buffer_desc s_princ_buffer;
- /* get all the required information from afpd */
+ /* get information from afpd */
if (uam_afpserver_option(obj, UAM_OPTION_FQDN, (void*) &fqdn, &fqdnlen) < 0)
return 1;
LOG(log_debug, logtype_uams, "get_afpd_principal: fqdn: %s", fqdn);
return 1;
LOG(log_debug, logtype_uams, "get_afpd_principal: service: %s", service);
- /* we need all the info, log error and return if one's missing */
+ /* if we don't have all the info, log that and return GSS_C_NO_NAME */
if (!service || !servicelen || !fqdn || !fqdnlen) {
- LOG(log_error, logtype_uams,
- "get_afpd_principal: could not retrieve required information from afpd.");
- return 1;
+ LOG(log_note, logtype_uams,
+ "get_afpd_principal: could not retrieve information from afpd, using default service principal(s)");
+
+ *server_name = GSS_C_NO_NAME;
+ return 0;
}
/* allocate memory to hold the temporary principal string */
gss_release_cred( &status, &server_creds );
cleanup_vars:
- gss_release_name( &status, &server_name );
+ if (server_name != GSS_C_NO_NAME)
+ gss_release_name( &status, &server_name );
return ret;
}
extern char *ldap_userbase;
extern char *ldap_groupbase;
extern char *ldap_uuid_attr;
+extern char *ldap_uuid_string;
extern char *ldap_name_attr;
extern char *ldap_group_attr;
extern char *ldap_uid_attr;
#define AFP_UUID_H
#define UUID_BINSIZE 16
-#define UUID_STRINGSIZE 36
typedef unsigned char *uuidp_t;
typedef unsigned char atalk_uuid_t[UUID_BINSIZE];
#define UUIDTYPESTR_MASK 3
extern char *uuidtype[];
-/* afp_options.c needs these. defined in libatalk/ldap.c */
-extern char *ldap_host;
-extern int ldap_auth_method;
-extern char *ldap_auth_dn;
-extern char *ldap_auth_pw;
-extern char *ldap_userbase;
-extern char *ldap_groupbase;
-extern char *ldap_uuid_attr;
-extern char *ldap_name_attr;
-extern char *ldap_group_attr;
-extern char *ldap_uid_attr;
-
/********************************************************
* Interface
********************************************************/
char *ldap_groupbase;
int ldap_groupscope;
char *ldap_uuid_attr;
+char *ldap_uuid_string;
char *ldap_name_attr;
char *ldap_group_attr;
char *ldap_uid_attr;
{&ldap_groupbase, "ldap_groupbase", 0, 0, -1},
{&ldap_groupscope, "ldap_groupscope", 1 ,1, -1},
{&ldap_uuid_attr, "ldap_uuid_attr", 0, 0, -1},
+ {&ldap_uuid_string,"ldap_uuid_string", 0, 0, 0},
{&ldap_name_attr, "ldap_name_attr", 0, 0, -1},
{&ldap_group_attr, "ldap_group_attr", 0, 0, -1},
{&ldap_uid_attr, "ldap_uid_attr", 0, 0, 0},
val++;
if ((val = strtok(val, " \n")) == NULL)
return -1;
- if ((val = strdup(val)) == NULL)
- return -1;
if ((pref = strtok(p, " =")) == NULL)
return -1;
+ if ((val = strdup(val)) == NULL)
+ return -1;
*R_pref = pref;
*R_val = val;
#include <atalk/logger.h>
#include <atalk/afp.h>
#include <atalk/uuid.h>
+#include <atalk/ldapconfig.h>
#include <atalk/util.h>
#include "aclldap.h"
int nibble = 1;
int i = 0;
unsigned char c, val = 0;
-
- while (*uuidstring) {
+
+ while (*uuidstring && i < UUID_BINSIZE) {
c = *uuidstring;
if (c == '-') {
uuidstring++;
/*!
* Convert 16 byte binary uuid to neat ascii represantation including dashes.
- *
+ * Use defined or default ascii mask for dash placement
* Returns pointer to static buffer.
*/
const char *uuid_bin2string(unsigned char *uuid) {
- static char uuidstring[UUID_STRINGSIZE + 1];
-
+ static char uuidstring[64];
+ const char *uuidmask;
int i = 0;
unsigned char c;
- while (i < UUID_STRINGSIZE) {
+#ifdef HAVE_LDAP
+ if (ldap_uuid_string)
+ uuidmask = ldap_uuid_string;
+ else
+#endif
+ uuidmask = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
+
+ LOG(log_debug, logtype_afpd, "uuid_bin2string{uuid}: mask: %s", uuidmask);
+
+ while (i < strlen(uuidmask)) {
c = *uuid;
uuid++;
sprintf(uuidstring + i, "%02X", c);
i += 2;
- if (i==8 || i==13 || i==18 || i==23)
+ if (uuidmask[i] == '-')
uuidstring[i++] = '-';
}
uuidstring[i] = 0;
#include <sys/uio.h>
ssize_t sys_sendfile(int tofd, int fromfd, off_t *offset, size_t count)
{
- return sendfile(fromfd, tofd, *offset, count, NULL, offset, 0);
+ off_t len;
+ int ret;
+
+ ret = sendfile(fromfd, tofd, *offset, count, NULL, &len, 0);
+
+ *offset += len;
+
+ if (ret != 0)
+ return -1;
+ return len;
}
#else
maxfd = dsi->socket + 1;
while (1) {
+ if (dsi->socket == -1)
+ /* eg dsi_disconnect() might have disconnected us */
+ return -1;
FD_ZERO(&readfds);
FD_ZERO(&writefds);
lock.l_type = F_WRLCK;
if (fcntl(fd, F_SETLK, &lock) < 0) {
+ close(fd);
if (errno == EACCES || errno == EAGAIN) {
/* ignore, other process already writing the file */
return 0;
AC_MSG_RESULT([ LIBS = $CUPS_LIBS])
AC_MSG_RESULT([ CFLAGS = $CUPS_CFLAGS])
fi
+ if test x"$netatalk_cv_zeroconf" = x"yes"; then
+ AC_MSG_RESULT([ ZEROCONF:])
+ AC_MSG_RESULT([ LIBS = $ZEROCONF_LIBS])
+ AC_MSG_RESULT([ CFLAGS = $ZEROCONF_CFLAGS])
+ fi
])
zeroconf_dir="$zeroconf"
fi
- # mDNS support using Avahi
- AC_CHECK_HEADER(
- avahi-client/client.h,
- AC_CHECK_LIB(
- avahi-client,
- avahi_client_new,
- AC_DEFINE(USE_ZEROCONF, 1, [Use DNS-SD registration]))
- )
+ # mDNS support using mDNSResponder
+ AC_CHECK_HEADER(
+ dns_sd.h,
+ AC_CHECK_LIB(
+ dns_sd,
+ DNSServiceRegister,
+ AC_DEFINE(USE_ZEROCONF, 1, [Use DNS-SD registration]))
+ )
- case "$ac_cv_lib_avahi_client_avahi_client_new" in
- yes)
- PKG_CHECK_MODULES(AVAHI, [ avahi-client >= 0.6 ])
- PKG_CHECK_MODULES(AVAHI_TPOLL, [ avahi-client >= 0.6.4 ],
- [AC_DEFINE(HAVE_AVAHI_THREADED_POLL, 1, [Uses Avahis threaded poll implementation])],
- [AC_MSG_WARN(This Avahi implementation is not supporting threaded poll objects. Maybe this is not what you want.)])
- ZEROCONF_LIBS="$AVAHI_LIBS"
- ZEROCONF_CFLAGS="$AVAHI_CFLAGS"
- AC_DEFINE(HAVE_AVAHI, 1, [Use Avahi/DNS-SD registration])
- found_zeroconf=yes
- ;;
- esac
+ if test "$ac_cv_lib_dns_sd_DNSServiceRegister" = yes; then
+ ZEROCONF_LIBS="-ldns_sd"
+ AC_DEFINE(HAVE_MDNS, 1, [Use mDNSRespnder/DNS-SD registration])
+ found_zeroconf=yes
+ fi
- CPPFLAGS="$savedcppflags"
- LDFLAGS="$savedldflags"
+ # mDNS support using Avahi
+ if test x"$found_zeroconf" != x"yes" ; then
+ AC_CHECK_HEADER(
+ avahi-client/client.h,
+ AC_CHECK_LIB(
+ avahi-client,
+ avahi_client_new,
+ AC_DEFINE(USE_ZEROCONF, 1, [Use DNS-SD registration]))
+ )
+
+ case "$ac_cv_lib_avahi_client_avahi_client_new" in
+ yes)
+ PKG_CHECK_MODULES(AVAHI, [ avahi-client >= 0.6 ])
+ PKG_CHECK_MODULES(AVAHI_TPOLL, [ avahi-client >= 0.6.4 ],
+ [AC_DEFINE(HAVE_AVAHI_THREADED_POLL, 1, [Uses Avahis threaded poll implementation])],
+ [AC_MSG_WARN(This Avahi implementation is not supporting threaded poll objects. Maybe this is not what you want.)])
+ ZEROCONF_LIBS="$AVAHI_LIBS"
+ ZEROCONF_CFLAGS="$AVAHI_CFLAGS"
+ AC_DEFINE(HAVE_AVAHI, 1, [Use Avahi/DNS-SD registration])
+ found_zeroconf=yes
+ ;;
+ esac
+ CPPFLAGS="$savedcppflags"
+ LDFLAGS="$savedldflags"
+ fi
fi
-
+
netatalk_cv_zeroconf=no
AC_MSG_CHECKING([whether to enable Zerconf support])
if test "x$found_zeroconf" = "xyes"; then