dnl Check for quota support
AC_NETATALK_CHECK_QUOTA
-dnl Check for optional server location protocol support (used by MacOS X)
-AC_NETATALK_SRVLOC
-
dnl Check for optional Zeroconf support
AC_NETATALK_ZEROCONF
@SLP_CFLAGS@ @ZEROCONF_CFLAGS@ \
-DAPPLCNAME \
-DSERVERTEXT=\"$(SERVERTEXT)/\" \
- -D_PATH_AFPDDEFVOL=\"$(pkgconfdir)/AppleVolumes.default\" \
- -D_PATH_AFPDSYSVOL=\"$(pkgconfdir)/AppleVolumes.system\" \
-D_PATH_AFPDPWFILE=\"$(pkgconfdir)/afppasswd\" \
-D_PATH_AFPDCONF=\"$(pkgconfdir)/afpd.conf\" \
-D_PATH_AFPDSIGCONF=\"$(pkgconfdir)/afp_signature.conf\" \
-D_PATH_AFPDUAMPATH=\"$(UAMS_PATH)/\" \
- -D_PATH_ACL_LDAPCONF=\"$(pkgconfdir)/afp_ldap.conf\" \
-D_PATH_AFPDUUIDCONF=\"$(pkgconfdir)/afp_voluuid.conf\" \
-D_PATH_CONFDIR=\"$(pkgconfdir)\"
/* AFP server */
for (config = ctx->configs; config; config = config->next) {
- dsi = (DSI *)config->obj.handle;
+ dsi = (DSI *)config->obj.dsi;
port = getip_port((struct sockaddr *)&dsi->server);
if (convert_string(config->obj.options.unixcharset,
#include <netinet/in.h>
#include <arpa/inet.h>
-#ifdef USE_SRVLOC
-#include <slp.h>
-#endif /* USE_SRVLOC */
-
#include <atalk/logger.h>
#include <atalk/util.h>
#include <atalk/dsi.h>
#include <atalk/afp.h>
#include <atalk/compat.h>
#include <atalk/server_child.h>
+#include <atalk/globals.h>
#ifdef HAVE_LDAP
#include <atalk/ldapconfig.h>
#endif
-#include <atalk/globals.h>
#include "afp_config.h"
#include "uam_auth.h"
#include "status.h"
#include "volume.h"
#include "afp_zeroconf.h"
-#define LINESIZE 1024
-
/* get rid of unneeded configurations. i use reference counts to deal
* w/ multiple configs sharing the same afp_options. oh, to dream of
* garbage collection ... */
if (p == config)
continue;
- /* do a little reference counting */
- if (--(*p->optcount) < 1) {
- afp_options_free(&p->obj.options, p->defoptions);
- free(p->optcount);
- }
+ afp_options_free(&p->obj.options, p->defoptions);
switch (p->obj.proto) {
case AFPPROTO_DSI:
close(p->fd);
- free(p->obj.handle);
+ free(p->obj.dsi);
break;
}
free(p);
unload_volumes_and_extmap();
}
-#ifdef USE_SRVLOC
-static void SRVLOC_callback(SLPHandle hslp _U_, SLPError errcode, void *cookie) {
- *(SLPError*)cookie = errcode;
-}
-
-static char hex[17] = "0123456789abcdef";
-
-static char * srvloc_encode(const struct afp_options *options, const char *name)
-{
- static char buf[512];
- char *conv_name;
- unsigned char *p;
- unsigned int i = 0;
-
- /* Convert name to maccharset */
- if ((size_t)-1 ==(convert_string_allocate( options->unixcharset, options->maccharset,
- name, -1, &conv_name)) )
- return (char*)name;
-
- /* Escape characters */
- p = conv_name;
- while (*p && i<(sizeof(buf)-4)) {
- if (*p == '@')
- break;
- else if (isspace(*p)) {
- buf[i++] = '%';
- buf[i++] = '2';
- buf[i++] = '0';
- p++;
- }
- else if ((!isascii(*p)) || *p <= 0x2f || *p == 0x3f ) {
- buf[i++] = '%';
- buf[i++] = hex[*p >> 4];
- buf[i++] = hex[*p++ & 15];
- }
- else {
- buf[i++] = *p++;
- }
- }
- buf[i] = '\0';
-
- free (conv_name);
-
- return buf;
-}
-#endif /* USE_SRVLOC */
static void dsi_cleanup(const AFPConfig *config)
{
-#ifdef USE_SRVLOC
- SLPError err;
- SLPError callbackerr;
- SLPHandle hslp;
- DSI *dsi = (DSI *)config->obj.handle;
-
- /* Do nothing if we didn't register. */
- if (!dsi || dsi->srvloc_url[0] == '\0')
- return;
-
- err = SLPOpen("en", SLP_FALSE, &hslp);
- if (err != SLP_OK) {
- LOG(log_error, logtype_afpd, "dsi_cleanup: Error opening SRVLOC handle");
- goto srvloc_dereg_err;
- }
-
- err = SLPDereg(hslp,
- dsi->srvloc_url,
- SRVLOC_callback,
- &callbackerr);
- if (err != SLP_OK) {
- LOG(log_error, logtype_afpd, "dsi_cleanup: Error unregistering %s from SRVLOC", dsi->srvloc_url);
- goto srvloc_dereg_err;
- }
-
- if (callbackerr != SLP_OK) {
- LOG(log_error, logtype_afpd, "dsi_cleanup: Error in callback while trying to unregister %s from SRVLOC (%d)", dsi->srvloc_url, callbackerr);
- goto srvloc_dereg_err;
- }
-
-srvloc_dereg_err:
- dsi->srvloc_url[0] = '\0';
- SLPClose(hslp);
-#endif /* USE_SRVLOC */
+ return;
}
static afp_child_t *dsi_start(AFPConfig *config, AFPConfig *configs,
server_child *server_children)
{
- DSI *dsi = config->obj.handle;
+ DSI *dsi = config->obj.dsi;
afp_child_t *child = NULL;
if (!(child = dsi_getsession(dsi,
if ((dsi = dsi_init(protocol, "afpd", options->hostname,
options->ipaddr, options->port,
- options->flags & OPTION_PROXY,
- options->server_quantum)) == NULL) {
+ 0, options->server_quantum)) == NULL) {
LOG(log_error, logtype_afpd, "main: dsi_init: %s", strerror(errno) );
free(config);
return NULL;
}
dsi->dsireadbuf = options->dsireadbuf;
- if (options->flags & OPTION_PROXY) {
- LOG(log_note, logtype_afpd, "AFP/TCP proxy initialized for %s:%d (%s)",
- getip_string((struct sockaddr *)&dsi->server), getip_port((struct sockaddr *)&dsi->server), VERSION);
- } else {
- LOG(log_note, logtype_afpd, "AFP/TCP started, advertising %s:%d (%s)",
- getip_string((struct sockaddr *)&dsi->server), getip_port((struct sockaddr *)&dsi->server), VERSION);
- }
+ LOG(log_note, logtype_afpd, "AFP/TCP started, advertising %s:%d (%s)",
+ getip_string((struct sockaddr *)&dsi->server), getip_port((struct sockaddr *)&dsi->server), VERSION);
-#ifdef USE_SRVLOC
- dsi->srvloc_url[0] = '\0'; /* Mark that we haven't registered. */
- if (!(options->flags & OPTION_NOSLP)) {
- SLPError err;
- SLPError callbackerr;
- SLPHandle hslp;
- unsigned int afp_port;
- int l;
- char *srvloc_hostname;
- const char *hostname;
-
- err = SLPOpen("en", SLP_FALSE, &hslp);
- if (err != SLP_OK) {
- LOG(log_error, logtype_afpd, "DSIConfigInit: Error opening SRVLOC handle");
- goto srvloc_reg_err;
- }
-
- /* XXX We don't want to tack on the port number if we don't have to.
- * Why?
- * Well, this seems to break MacOS < 10. If the user _really_ wants to
- * use a non-default port, they can, but be aware, this server might
- * not show up int the Network Browser.
- */
- afp_port = getip_port((struct sockaddr *)&dsi->server);
- /* If specified use the FQDN to register with srvloc, otherwise use IP. */
- p = NULL;
- if (options->fqdn) {
- hostname = options->fqdn;
- p = strchr(hostname, ':');
- }
- else
- hostname = getip_string((struct sockaddr *)&dsi->server);
-
- srvloc_hostname = srvloc_encode(options, (options->server ? options->server : options->hostname));
-
- if ((p) || afp_port == 548) {
- l = snprintf(dsi->srvloc_url, sizeof(dsi->srvloc_url), "afp://%s/?NAME=%s", hostname, srvloc_hostname);
- }
- else {
- l = snprintf(dsi->srvloc_url, sizeof(dsi->srvloc_url), "afp://%s:%d/?NAME=%s", hostname, afp_port, srvloc_hostname);
- }
-
- if (l == -1 || l >= (int)sizeof(dsi->srvloc_url)) {
- LOG(log_error, logtype_afpd, "DSIConfigInit: Hostname is too long for SRVLOC");
- dsi->srvloc_url[0] = '\0';
- goto srvloc_reg_err;
- }
-
- err = SLPReg(hslp,
- dsi->srvloc_url,
- SLP_LIFETIME_MAXIMUM,
- "afp",
- "",
- SLP_TRUE,
- SRVLOC_callback,
- &callbackerr);
- if (err != SLP_OK) {
- LOG(log_error, logtype_afpd, "DSIConfigInit: Error registering %s with SRVLOC", dsi->srvloc_url);
- dsi->srvloc_url[0] = '\0';
- goto srvloc_reg_err;
- }
-
- if (callbackerr != SLP_OK) {
- LOG(log_error, logtype_afpd, "DSIConfigInit: Error in callback trying to register %s with SRVLOC", dsi->srvloc_url);
- dsi->srvloc_url[0] = '\0';
- goto srvloc_reg_err;
- }
-
- LOG(log_info, logtype_afpd, "Sucessfully registered %s with SRVLOC", dsi->srvloc_url);
- config->server_cleanup = dsi_cleanup;
-
-srvloc_reg_err:
- SLPClose(hslp);
- }
-#endif /* USE_SRVLOC */
-
- config->fd = dsi->serversock;
- config->obj.handle = dsi;
- config->obj.config = config;
- config->obj.proto = AFPPROTO_DSI;
+ config->dsi = dsi;
memcpy(&config->obj.options, options, sizeof(struct afp_options));
/* get rid of any appletalk info. we use the fact that the DSI
if (p && (q = strchr(p, ':')))
*q = '\0';
- config->optcount = refcount;
- (*refcount)++;
-
- config->server_start = dsi_start;
return config;
}
/* set signature */
set_signature(options);
- /* handle dsi transports and dsi proxies. we only proxy
- * for DSI connections. */
-
- /* this should have something like the following:
- * for (i=mindsi; i < maxdsi; i++)
- * if (options->transports & (1 << i) &&
- * (next = DSIConfigInit(options, refcount, i)))
- * next->defoptions = defoptions;
- */
- if ( (options->transports & AFPTRANS_TCP)
- &&
- ((options->flags & OPTION_PROXY) == 0)
- &&
- (next = DSIConfigInit(options, refcount, DSI_TCPIP)))
- next->defoptions = defoptions;
-
- /* load in all the authentication modules. we can load the same
- things multiple times if necessary. however, loading different
- things with the same names will cause complaints. by not loading
- in any uams with proxies, we prevent ddp connections from succeeding.
- */
- auth_load(options->uampath, options->uamlist);
+ if ((next = DSIConfigInit(options, refcount, DSI_TCPIP)))
+ /* load in all the authentication modules. we can load the same
+ things multiple times if necessary. however, loading different
+ things with the same names will cause complaints. by not loading
+ in any uams with proxies, we prevent ddp connections from succeeding.
+ */
+ auth_load(options->uampath, options->uamlist);
/* this should be able to accept multiple dsi transports. i think
* the only thing that gets affected is the net addresses. */
return next;
}
-/* fill in the appropriate bits for each interface */
-AFPConfig *configinit(struct afp_options *cmdline)
+/*!
+ * Parse configfile and build AFPObj
+ */
+int configinit(AFPObj *AFPObj, const struct afp_options *defoptions)
{
- FILE *fp;
- char buf[LINESIZE + 1], *p, have_option = 0;
- size_t len;
- struct afp_options options;
- AFPConfig *config=NULL, *first = NULL;
-
- /* if config file doesn't exist, load defaults */
- if ((fp = fopen(cmdline->configfile, "r")) == NULL)
- {
- LOG(log_debug, logtype_afpd, "ConfigFile %s not found, assuming defaults",
- cmdline->configfile);
- return AFPConfigInit(cmdline, cmdline);
- }
+ int have_option = 0;
- /* scan in the configuration file */
- len = 0;
- while (!feof(fp)) {
- if (!fgets(&buf[len], LINESIZE - len, fp) || buf[len] == '#')
- continue;
- len = strlen(buf);
- if ( len >= 2 && buf[len-2] == '\\' ) {
- len -= 2;
- continue;
- } else
- len = 0;
-
- /* a little pre-processing to get rid of spaces and end-of-lines */
- p = buf;
- while (p && isspace(*p))
- p++;
- if (!p || (*p == '\0'))
- continue;
+ afp_options_duplicate(&AFPObj->options, defoptions);
- have_option = 1;
+ if ((AFPObj->iniconfig = iniparser_load(AFPObj->options.configfile)) == NULL)
+ /* if config file doesn't exist, load defaults */
+ return AFPConfigInit(AFPObj);
- memcpy(&options, cmdline, sizeof(options));
- if (!afp_options_parseline(p, &options))
- continue;
+ if (afp_options_parse(AFPObj) != 0)
+ return -1;
- /* AFPConfigInit can return two linked configs due to DSI and ASP */
- if (!first) {
- if ((first = AFPConfigInit(&options, cmdline)))
- config = first->next ? first->next : first;
- } else if ((config->next = AFPConfigInit(&options, cmdline))) {
- config = config->next->next ? config->next->next : config->next;
- }
- }
+ AFPConfigInit(AFPObj);
#ifdef HAVE_LDAP
/* Parse afp_ldap.conf */
- acl_ldap_readconfig(_PATH_ACL_LDAPCONF);
+ acl_ldap_readconfig(AFPObj->iniconfig);
#endif /* HAVE_LDAP */
LOG(log_debug, logtype_afpd, "Finished parsing Config File");
- fclose(fp);
-
- if (!have_option)
- first = AFPConfigInit(cmdline, cmdline);
/* Now register with zeroconf, we also need the volumes for that */
- if (! (first->obj.options.flags & OPTION_NOZEROCONF)) {
- load_volumes(&first->obj);
- zeroconf_register(first);
+ if (! (AFPObj->options.flags & OPTION_NOZEROCONF)) {
+ load_volumes(AFPObj);
+ zeroconf_register(AFPObj);
}
return first;
#include <atalk/server_child.h>
#include <atalk/globals.h>
-typedef struct AFPConfig {
- AFPObj obj;
- int fd, statuslen;
- unsigned char *optcount;
- char status[1400];
- const void *defoptions, *signature;
- afp_child_t *(*server_start) (struct AFPConfig *, struct AFPConfig *,
- server_child *);
- void (*server_cleanup) (const struct AFPConfig *);
- struct AFPConfig *next;
-} AFPConfig;
-
extern AFPConfig *configinit (struct afp_options *);
extern void configfree (AFPConfig *, const AFPConfig *);
static sigjmp_buf recon_jmp;
static void afp_dsi_close(AFPObj *obj)
{
- DSI *dsi = obj->handle;
+ DSI *dsi = obj->dsi;
close(obj->ipc_fd);
obj->ipc_fd = -1;
*/
static void afp_dsi_die(int sig)
{
- DSI *dsi = (DSI *)AFPobj->handle;
+ DSI *dsi = (DSI *)AFPobj->dsi;
if (dsi->flags & DSI_RECONINPROG) {
/* Primary reconnect succeeded, got SIGTERM from afpd parent */
exit(0);
}
- dsi_attention(AFPobj->handle, AFPATTN_SHUTDOWN);
+ dsi_attention(AFPobj->dsi, AFPATTN_SHUTDOWN);
afp_dsi_close(AFPobj);
if (sig) /* if no signal, assume dieing because logins are disabled &
don't log it (maintenance mode)*/
/* SIGQUIT handler */
static void ipc_reconnect_handler(int sig _U_)
{
- DSI *dsi = (DSI *)AFPobj->handle;
+ DSI *dsi = (DSI *)AFPobj->dsi;
if (reconnect_ipc(AFPobj) != 0) {
LOG(log_error, logtype_afpd, "ipc_reconnect_handler: failed IPC reconnect");
{
uint16_t dsiID;
int socket;
- DSI *dsi = (DSI *)AFPobj->handle;
+ DSI *dsi = (DSI *)AFPobj->dsi;
LOG(log_debug, logtype_afpd, "afp_dsi_transfer_session: got SIGURG, trying to receive session");
{
struct sigaction sv;
struct itimerval it;
- DSI *dsi = (DSI *)AFPobj->handle;
+ DSI *dsi = (DSI *)AFPobj->dsi;
dsi->flags |= DSI_DIE;
/* shutdown and don't reconnect. server going down in 5 minutes. */
setmessage("The server is going down for maintenance.");
- if (dsi_attention(AFPobj->handle, AFPATTN_SHUTDOWN | AFPATTN_NORECONNECT |
+ if (dsi_attention(AFPobj->dsi, AFPATTN_SHUTDOWN | AFPATTN_NORECONNECT |
AFPATTN_MESG | AFPATTN_TIME(5)) < 0) {
- DSI *dsi = (DSI *)AFPobj->handle;
+ DSI *dsi = (DSI *)AFPobj->dsi;
dsi->down_request = 1;
}
/* ---------------------- */
static void afp_dsi_getmesg (int sig _U_)
{
- DSI *dsi = (DSI *)AFPobj->handle;
+ DSI *dsi = (DSI *)AFPobj->dsi;
dsi->msg_request = 1;
- if (dsi_attention(AFPobj->handle, AFPATTN_MESG | AFPATTN_TIME(5)) < 0)
+ if (dsi_attention(AFPobj->dsi, AFPATTN_MESG | AFPATTN_TIME(5)) < 0)
dsi->msg_request = 2;
}
static void alarm_handler(int sig _U_)
{
int err;
- DSI *dsi = (DSI *)AFPobj->handle;
+ DSI *dsi = (DSI *)AFPobj->dsi;
/* we have to restart the timer because some libraries may use alarm() */
setitimer(ITIMER_REAL, &dsi->timer, NULL);
if ((err = pollvoltime(AFPobj)) == 0)
LOG(log_debug, logtype_afpd, "afp_alarm: sending DSI tickle");
- err = dsi_tickle(AFPobj->handle);
+ err = dsi_tickle(AFPobj->dsi);
if (err <= 0) {
if (geteuid() == 0) {
LOG(log_note, logtype_afpd, "afp_alarm: unauthenticated user, connection problem");
if (dsi->msg_request) {
if (dsi->msg_request == 2) {
/* didn't send it in signal handler */
- dsi_attention(AFPobj->handle, AFPATTN_MESG | AFPATTN_TIME(5));
+ dsi_attention(AFPobj->dsi, AFPATTN_MESG | AFPATTN_TIME(5));
}
dsi->msg_request = 0;
readmessage(AFPobj);
}
if (dsi->down_request) {
dsi->down_request = 0;
- dsi_attention(AFPobj->handle, AFPATTN_SHUTDOWN | AFPATTN_NORECONNECT |
+ dsi_attention(AFPobj->dsi, AFPATTN_SHUTDOWN | AFPATTN_NORECONNECT |
AFPATTN_MESG | AFPATTN_TIME(5));
}
}
*/
void afp_over_dsi(AFPObj *obj)
{
- DSI *dsi = (DSI *) obj->handle;
+ DSI *dsi = (DSI *) obj->dsi;
int rc_idx;
uint32_t err, cmd;
uint8_t function;
#include "auth.h"
#include "dircache.h"
-#ifndef MIN
-#define MIN(a, b) ((a) < (b) ? (a) : (b))
-#endif /* MIN */
-
-/* FIXME CNID */
-const char *Cnid_srv = "localhost";
-const char *Cnid_port = "4700";
-
-#define OPTIONS "dn:f:s:uc:g:P:ptDS:TL:F:U:hIvVm:"
+#define OPTIONS "dn:uc:g:P:ptS:L:F:U:hIvVm:"
#define LENGTH 512
-/* return an option. this uses an internal array, so it's necessary
- * to duplicate it if you want to hold it for long. this is probably
- * non-optimal. */
-static char *getoption(char *buf, const char *option)
+/* initialize options */
+void afp_options_init(struct afp_options *options)
{
- static char string[LENGTH + 1];
- char *end;
- int len;
-
- if (option && (buf = strstr(buf, option)))
- buf = strpbrk(buf, " \t");
-
- while (buf && isspace(*buf))
- buf++;
-
- if (!buf)
- return NULL;
-
- /* search for any quoted stuff */
- if (*buf == '"' && (end = strchr(buf + 1, '"'))) {
- buf++;
- len = MIN(end - buf, LENGTH);
- } else if ((end = strpbrk(buf, " \t\n"))) /* option or eoln */
- len = MIN(end - buf, LENGTH);
- else
- len = MIN(strlen(buf), LENGTH);
-
- strncpy(string, buf, len);
- string[len] = '\0';
- return string;
+ memset(options, 0, sizeof(struct afp_options));
+
+ options->pidfile = _PATH_AFPDLOCK;
+ options->configfile = D_PATH_CONFDIR "afp.conf";
+ options->sigconffile = _PATH_AFPDSIGCONF;
+ options->uuidconf = _PATH_AFPDUUIDCONF;
+ options->server_notif = 1;
+ options->dsireadbuf = 12;
}
/* get rid of any allocated afp_option buffers. */
-void afp_options_free(struct afp_options *opt,
- const struct afp_options *save)
+void afp_options_free(struct afp_options *opt)
{
- if (opt->defaultvol.name && (opt->defaultvol.name != save->defaultvol.name))
- free(opt->defaultvol.name);
- if (opt->defaultvol.full_name && (opt->defaultvol.full_name != save->defaultvol.full_name))
- free(opt->defaultvol.full_name);
-
- if (opt->systemvol.name && (opt->systemvol.name != save->systemvol.name))
- free(opt->systemvol.name);
- if (opt->systemvol.full_name && (opt->systemvol.full_name != save->systemvol.full_name))
- free(opt->systemvol.full_name);
-
- if (opt->uservol.name && (opt->uservol.name != save->uservol.name))
- free(opt->uservol.name);
- if (opt->uservol.full_name && (opt->uservol.full_name != save->uservol.full_name))
- free(opt->uservol.full_name);
-
- if (opt->loginmesg && (opt->loginmesg != save->loginmesg))
- free(opt->loginmesg);
- if (opt->guest && (opt->guest != save->guest))
+ if (opt->adminauthuser)
+ free(opt->adminauthuser);
+ if (opt->configfile)
+ free(opt->configfile);
+ if (opt->fqdn)
+ free(opt->fqdn);
+ if (opt->guest)
free(opt->guest);
- if (opt->server && (opt->server != save->server))
- free(opt->server);
- if (opt->ipaddr && (opt->ipaddr != save->ipaddr))
+ if (opt->ipaddr)
free(opt->ipaddr);
- if (opt->port && (opt->port != save->port))
+ if (opt->k5realm)
+ free(opt->k5realm);
+ if (opt->k5keytab)
+ free(opt->k5keytab);
+ if (opt->k5service)
+ free(opt->k5service);
+ if (opt->logconfig)
+ free(opt->logconfig);
+ if (opt->loginmesg)
+ free(opt->loginmesg);
+ if (opt->maccodepage)
+ free(opt->maccodepage);
+ if (opt->mimicmodel)
+ free(opt->mimicmodel);
+ if (opt->ntdomain)
+ free(opt->ntdomain);
+ if (opt->ntseparator)
+ free(opt->ntseparator);
+ if (opt->passwdfile)
+ free(opt->passwdfile);
+ if (opt->port)
free(opt->port);
- if (opt->fqdn && (opt->fqdn != save->fqdn))
- free(opt->fqdn);
- if (opt->uampath && (opt->uampath != save->uampath))
- free(opt->uampath);
- if (opt->uamlist && (opt->uamlist != save->uamlist))
+ if (opt->server)
+ free(opt->server);
+ if (opt->signatureopt)
+ free(opt->signatureopt);
+ if (opt->uamlist)
free(opt->uamlist);
- if (opt->passwdfile && (opt->passwdfile != save->passwdfile))
- free(opt->passwdfile);
- if (opt->signatureopt && (opt->signatureopt != save->signatureopt))
- free(opt->signatureopt);
- if (opt->k5service && (opt->k5service != save->k5service))
- free(opt->k5service);
- if (opt->k5realm && (opt->k5realm != save->k5realm))
- free(opt->k5realm);
- if (opt->k5keytab && (opt->k5keytab != save->k5keytab))
- free(opt->k5keytab);
- if (opt->unixcodepage && (opt->unixcodepage != save->unixcodepage))
- free(opt->unixcodepage);
- if (opt->maccodepage && (opt->maccodepage != save->maccodepage))
- free(opt->maccodepage);
-
- if (opt->ntdomain && (opt->ntdomain != save->ntdomain))
- free(opt->ntdomain);
- if (opt->ntseparator && (opt->ntseparator != save->ntseparator))
- free(opt->ntseparator);
- if (opt->logconfig && (opt->logconfig != save->logconfig))
- free(opt->logconfig);
- if (opt->mimicmodel && (opt->mimicmodel != save->mimicmodel))
- free(opt->mimicmodel);
- if (opt->adminauthuser && (opt->adminauthuser != save->adminauthuser))
- free(opt->adminauthuser);
+ if (opt->uampath)
+ free(opt->uampath);
+ if (opt->unixcodepage)
+ free(opt->unixcodepage);
}
-/* initialize options */
-void afp_options_init(struct afp_options *options)
+void afp_options_duplicate(struct afp_options *options, const struct afp_options *soptions)
{
- memset(options, 0, sizeof(struct afp_options));
- options->connections = 20;
- options->pidfile = _PATH_AFPDLOCK;
- options->defaultvol.name = _PATH_AFPDDEFVOL;
- options->systemvol.name = _PATH_AFPDSYSVOL;
- options->configfile = _PATH_AFPDCONF;
- options->sigconffile = _PATH_AFPDSIGCONF;
- options->uuidconf = _PATH_AFPDUUIDCONF;
- options->uampath = _PATH_AFPDUAMPATH;
- options->uamlist = "uams_dhx.so,uams_dhx2.so";
- options->guest = "nobody";
- options->loginmesg = "";
- options->transports = AFPTRANS_TCP; /* TCP only */
- options->passwdfile = _PATH_AFPDPWFILE;
- options->tickleval = 30;
- options->timeout = 4; /* 4 tickles = 2 minutes */
- options->sleep = 10 * 60 * 2; /* 10 h in 30 seconds tick */
- options->disconnected = 10 * 60 * 2; /* 10 h in 30 seconds tick */
- options->server_notif = 1;
- options->authprintdir = NULL;
- options->signatureopt = "auto";
- options->umask = 0;
-#ifdef ADMIN_GRP
- options->admingid = 0;
-#endif /* ADMIN_GRP */
- options->k5service = NULL;
- options->k5realm = NULL;
- options->k5keytab = NULL;
- options->unixcharset = CH_UNIX;
- options->unixcodepage = "LOCALE";
- options->maccharset = CH_MAC;
- options->maccodepage = "MAC_ROMAN";
- options->volnamelen = 80; /* spec: 255, 10.1: 73, 10.4/10.5: 80 */
- options->ntdomain = NULL;
- options->ntseparator = NULL;
-#ifdef USE_SRVLOC
- /* don't advertize slp by default */
- options->flags |= OPTION_NOSLP;
-#endif
- options->dircachesize = DEFAULT_MAX_DIRCACHE_SIZE;
- options->flags |= OPTION_ACL2MACCESS;
- options->flags |= OPTION_UUID;
- options->tcp_sndbuf = 0; /* 0 means don't change OS default */
- options->tcp_rcvbuf = 0; /* 0 means don't change OS default */
- options->dsireadbuf = 12;
- options->mimicmodel = NULL;
- options->fce_fmodwait = 60; /* put fmod events 60 seconds on hold */
- options->adminauthuser = NULL;
+ memcpy(options, soptions, sizeof(struct afp_options));
+
+ options->pidfile = NULL;
+ options->uuidconf = NULL;
+
+ options->configfile = strdup(options->configfile);
+ options->guest = strdup(options->guest);
+ options->loginmesg = strdup(options->loginmesg);
+ options->maccodepage = strdup(options->maccodepage);
+ options->passwdfile = strdup(options->passwdfile);
+ options->sigconffile = strdup(options->sigconffile);
+ options->signatureopt = strdup(options->signatureopt);
+ options->uamlist = strdup(options->uamlist);
+ options->uampath = strdup(options->uampath);
+ options->unixcodepage = strdup(options->unixcodepage);
}
-/* parse an afpd.conf line. i'm doing it this way because it's
- * easy. it is, however, massively hokey. sample afpd.conf:
- * server:AFPServer@zone -loginmesg "blah blah blah" -nodsi
- * "private machine"@zone2 -noguest -port 11012
- * server2 -nocleartxt -nodsi
- *
- * NOTE: this ignores unknown options
- */
-int afp_options_parseline(char *buf, struct afp_options *options)
+#define MAXVAL
+int afp_options_parse(AFPObj *AFPObj)
{
- char *c, *opt;
-
- /* handle server */
- if (*buf != '-' && (c = getoption(buf, NULL)) && (opt = strdup(c)))
- options->server = opt;
-
- /* parse toggles */
- if (strstr(buf, " -nodebug"))
- options->flags &= ~OPTION_DEBUG;
-#ifdef USE_SRVLOC
- if (strstr(buf, " -slp"))
- options->flags &= ~OPTION_NOSLP;
-#endif
-#ifdef USE_ZEROCONF
- if (strstr(buf, " -nozeroconf"))
+ dictionary *config = AFPObj->iniconfig;
+ struct afp_options *options = &AFPObj->options;
+ int i;
+ const char *p, *tmp;
+ char val[MAXVAL];
+
+ /* [Global] */
+
+ options->logconfig = iniparser_getstring(config, INISEC_GLOBAL, "loglevel", "default:note");
+ options->logfile = iniparser_getstring(config, INISEC_GLOBAL, "logfile", NULL);
+ setuplog(logconfig, logfile);
+
+ /* [AFP] "options" options wo values */
+ options->flags |= OPTION_ACL2MACCESS | OPTION_UUID;
+
+ p = iniparser_getstring(config, INISEC_AFP, "options", "");
+ strcpy(val, " ");
+ strlcat(val, p, MAXVAL);
+
+ if (strstr(val, " nozeroconf"))
options->flags |= OPTION_NOZEROCONF;
-#endif
- if (strstr(buf, " -nouservolfirst"))
- options->flags &= ~OPTION_USERVOLFIRST;
- if (strstr(buf, " -uservolfirst"))
- options->flags |= OPTION_USERVOLFIRST;
- if (strstr(buf, " -nouservol"))
- options->flags |= OPTION_NOUSERVOL;
- if (strstr(buf, " -uservol"))
- options->flags &= ~OPTION_NOUSERVOL;
- if (strstr(buf, " -proxy"))
- options->flags |= OPTION_PROXY;
- if (strstr(buf, " -noicon"))
- options->flags &= ~OPTION_CUSTOMICON;
- if (strstr(buf, " -icon"))
+ if (strstr(val, " icon"))
options->flags |= OPTION_CUSTOMICON;
- if (strstr(buf, " -advertise_ssh"))
+ if (strstr(val, " noicon"))
+ options->flags &= ~OPTION_CUSTOMICON;
+ if (strstr(val, " advertise_ssh"))
options->flags |= OPTION_ANNOUNCESSH;
- if (strstr(buf, " -noacl2maccess"))
+ if (strstr(val, " noacl2maccess"))
options->flags &= ~OPTION_ACL2MACCESS;
- if (strstr(buf, " -keepsessions")) {
- default_options.flags |= OPTION_KEEPSESSIONS;
+ if (strstr(val, " keepsessions"))
options->flags |= OPTION_KEEPSESSIONS;
- }
-
- /* passwd bits */
- if (strstr(buf, " -nosavepassword"))
+ if (strstr(val, " keepsessions"))
+ options->flags |= OPTION_CLOSEVOL;
+ if (strstr(val, " nosavepassword"))
options->passwdbits |= PASSWD_NOSAVE;
- if (strstr(buf, " -savepassword"))
+ if (strstr(val, " savepassword"))
options->passwdbits &= ~PASSWD_NOSAVE;
- if (strstr(buf, " -nosetpassword"))
+ if (strstr(val, " nosetpassword"))
options->passwdbits &= ~PASSWD_SET;
- if (strstr(buf, " -setpassword"))
+ if (strstr(val, " setpassword"))
options->passwdbits |= PASSWD_SET;
-
- /* transports */
- if (strstr(buf, " -transall"))
- options->transports = AFPTRANS_ALL;
- if (strstr(buf, " -notransall"))
- options->transports = AFPTRANS_NONE;
- if (strstr(buf, " -tcp"))
- options->transports |= AFPTRANS_TCP;
- if (strstr(buf, " -notcp"))
- options->transports &= ~AFPTRANS_TCP;
- if (strstr(buf, " -ddp"))
- options->transports |= AFPTRANS_DDP;
- if (strstr(buf, " -noddp"))
- options->transports &= ~AFPTRANS_DDP;
- if (strstr(buf, "-client_polling"))
+ if (strstr(val, " client_polling"))
options->server_notif = 0;
- /* figure out options w/ values. currently, this will ignore the setting
- * if memory is lacking. */
-
- if ((c = getoption(buf, "-hostname"))) {
- int len = strlen (c);
- if (len <= MAXHOSTNAMELEN) {
- memcpy(options->hostname, c, len);
- options->hostname[len] = 0;
- }
- else
- LOG(log_info, logtype_afpd, "WARNING: hostname %s is too long (%d)",c,len);
- }
-
- if ((c = getoption(buf, "-defaultvol")) && (opt = strdup(c)))
- options->defaultvol.name = opt;
- if ((c = getoption(buf, "-systemvol")) && (opt = strdup(c)))
- options->systemvol.name = opt;
- if ((c = getoption(buf, "-loginmesg")) && (opt = strdup(c))) {
- int i = 0, j = 0;
- while (c[i]) {
- if (c[i] != '\\') {
- opt[j++] = c[i];
- } else {
- i++;
- if (c[i] == 'n')
- opt[j++] = '\n';
- }
- i++;
- }
- opt[j] = 0;
- options->loginmesg = opt;
-
- }
- if ((c = getoption(buf, "-guestname")) && (opt = strdup(c)))
- options->guest = opt;
- if ((c = getoption(buf, "-passwdfile")) && (opt = strdup(c)))
- options->passwdfile = opt;
- if ((c = getoption(buf, "-passwdminlen")))
- options->passwdminlen = MIN(1, atoi(c));
- if ((c = getoption(buf, "-loginmaxfail")))
- options->loginmaxfail = atoi(c);
- if ((c = getoption(buf, "-tickleval"))) {
- options->tickleval = atoi(c);
- if (options->tickleval <= 0) {
- options->tickleval = 30;
- }
- }
- if ((c = getoption(buf, "-timeout"))) {
- options->timeout = atoi(c);
- if (options->timeout <= 0) {
- options->timeout = 4;
- }
- }
-
- if ((c = getoption(buf, "-sleep"))) {
- options->disconnected = options->sleep = atoi(c) * 120;
- if (options->sleep <= 4) {
- options->disconnected = options->sleep = 4;
- }
- }
-
- if ((c = getoption(buf, "-dsireadbuf"))) {
- options->dsireadbuf = atoi(c);
- if (options->dsireadbuf < 6)
- options->dsireadbuf = 6;
- }
-
- if ((c = getoption(buf, "-server_quantum")))
- options->server_quantum = strtoul(c, NULL, 0);
-
- if ((c = getoption(buf, "-volnamelen"))) {
- options->volnamelen = atoi(c);
- if (options->volnamelen < 8) {
- options->volnamelen = 8; /* max mangled volname "???#FFFF" */
- }
- if (options->volnamelen > 255) {
- options->volnamelen = 255; /* AFP3 spec */
- }
- }
-
- /* -[no]setuplog <logtype> <loglevel> [<filename>]*/
- c = buf;
- /* Now THIS is hokey! Multiple occurrences are not supported by our current code, */
- /* so I have to loop myself. */
- while (NULL != (c = strstr(c, "-setuplog"))) {
- char *optstr;
- if ((optstr = getoption(c, "-setuplog"))) {
- /* hokey2: options->logconfig must be converted to store an array of logstrings */
- if (options->logconfig)
- free(options->logconfig);
- options->logconfig = strdup(optstr);
- setuplog(optstr);
- c += sizeof("-setuplog");
- }
+ /* figure out options w values */
+
+ options->loginmesg = iniparser_getstring(config, INISEC_AFP, "loginmesg", "");
+ options->guest = iniparser_getstring(config, INISEC_AFP, "guestname", "nobody");
+ options->passwdfile = iniparser_getstring(config, INISEC_AFP, "passwdfile", _PATH_AFPDPWFILE);
+ options->uampath = iniparser_getstring(config, INISEC_AFP, "uampath", _PATH_AFPDUAMPATH);
+ options->uamlist = iniparser_getstring(config, INISEC_AFP, "uamlist", "uams_dhx.so,uams_dhx2.so");
+ options->port = iniparser_getstring(config, INISEC_AFP, "port", "548");
+ options->signatureopt = iniparser_getstring(config, INISEC_AFP, "signature", "auto");
+
+ options->connections = iniparser_getint (config, INISEC_AFP, "maxcon", 200);
+ options->passwdminlen = iniparser_getint (config, INISEC_AFP, "passwdminlen", 0);
+ options->tickleval = iniparser_getint (config, INISEC_AFP, "tickleval", 30);
+ options->timeout = iniparser_getint (config, INISEC_AFP, "timeout", 4);
+ options->dsireadbuf = iniparser_getint (config, INISEC_AFP, "dsireadbuf", 12);
+ options->server_quantum = iniparser_getint (config, INISEC_AFP, "server_quantum", DSI_SERVQUANT_DEF);
+ options->volnamelen = iniparser_getint (config, INISEC_AFP, "volnamelen", 80);
+ options->dircachesize = iniparser_getint (config, INISEC_AFP, "dircachesize", DEFAULT_MAX_DIRCACHE_SIZE);
+ options->tcp_sndbuf = iniparser_getint (config, INISEC_AFP, "tcpsndbuf", 0);
+ options->tcp_rcvbuf = iniparser_getint (config, INISEC_AFP, "tcprcvbuf", 0);
+ options->fce_fmodwait = iniparser_getint (config, INISEC_AFP, "fceholdfmod", 60);
+ options->sleep = iniparser_getint (config, INISEC_AFP, "sleep", 10) * 60 * 2;
+ options->disconnect = iniparser_getint (config, INISEC_AFP, "disconnect" 24) * 60 * 2;
+
+ options->k5service = iniparser_getstringdup(config, INISEC_AFP, "k5service", NULL);
+ options->k5realm = iniparser_getstringdup(config, INISEC_AFP, "k5realm", NULL);
+ options->authprintdir = iniparser_getstringdup(config, INISEC_AFP, "authprintdir", NULL);
+ options->ipaddr = iniparser_getstringdup(config, INISEC_AFP, "ipaddr", NULL);
+ options->hostname = iniparser_getstringdup(config, INISEC_AFP, "hostname", NULL);
+ options->ntdomain = iniparser_getstringdup(config, INISEC_AFP, "ntdomain", NULL);
+ options->ntseparator = iniparser_getstringdup(config, INISEC_AFP, "ntseparator", NULL);
+ options->mimicmodel = iniparser_getstringdup(config, INISEC_AFP, "mimicmodel", NULL);
+ options->adminauthuser = iniparser_getstringdup(config, INISEC_AFP, "adminauthuser", NULL);
+
+ if ((p = iniparser_getstring(config, INISEC_AFP, "k5keytab", NULL))) {
+ EC_NULL_LOG( options->k5keytab = malloc(strlen(p) + 14) );
+ snprintf(options->k5keytab, strlen(p) + 14, "KRB5_KTNAME=%s", p);
+ putenv(options->k5keytab);
}
- if ((c = getoption(buf, "-unsetuplog")))
- unsetuplog(c);
-
#ifdef ADMIN_GRP
- if ((c = getoption(buf, "-admingroup"))) {
- struct group *gr = getgrnam(c);
- if (gr != NULL) {
- options->admingid = gr->gr_gid;
- }
+ if ((p = iniparser_getstring(config, INISEC_AFP, "admingroup", NULL))) {
+ struct group *gr = getgrnam(p);
+ if (gr != NULL)
+ options->admingid = gr->gr_gid;
}
#endif /* ADMIN_GRP */
- if ((c = getoption(buf, "-k5service")) && (opt = strdup(c)))
- options->k5service = opt;
- if ((c = getoption(buf, "-k5realm")) && (opt = strdup(c)))
- options->k5realm = opt;
- if ((c = getoption(buf, "-k5keytab"))) {
- if ( NULL == (options->k5keytab = (char *) malloc(sizeof(char)*(strlen(c)+14)) )) {
- LOG(log_error, logtype_afpd, "malloc failed");
- exit(-1);
- }
- snprintf(options->k5keytab, strlen(c)+14, "KRB5_KTNAME=%s", c);
- putenv(options->k5keytab);
- /* setenv( "KRB5_KTNAME", c, 1 ); */
- }
- if ((c = getoption(buf, "-authprintdir")) && (opt = strdup(c)))
- options->authprintdir = opt;
- if ((c = getoption(buf, "-uampath")) && (opt = strdup(c)))
- options->uampath = opt;
- if ((c = getoption(buf, "-uamlist")) && (opt = strdup(c)))
- options->uamlist = opt;
-
- if ((c = getoption(buf, "-ipaddr"))) {
-#if 0
- struct in_addr inaddr;
- if (inet_aton(c, &inaddr) && (opt = strdup(c))) {
- if (!gethostbyaddr((const char *) &inaddr, sizeof(inaddr), AF_INET))
- LOG(log_info, logtype_afpd, "WARNING: can't find %s", opt);
- options->ipaddr = opt;
- }
- else {
- LOG(log_error, logtype_afpd, "Error parsing -ipaddr, is %s in numbers-and-dots notation?", c);
+ p = iniparser_getstring(config, INISEC_AFP, "cnidserver", "localhost:4700");
+ tmp = strrchr(p, ':');
+ if (tmp)
+ *t = 0;
+ options->Cnid_srv = strdup(p);
+ if (tmp)
+ options->Cnid_port = strdup(tmp + 1);
+ LOG(log_debug, logtype_afpd, "CNID Server: %s:%s", options->Cnid_srv, options->Cnid_port);
+
+
+ if ((p = iniparser_getstring(config, INISEC_AFP, "fqdn", NULL))) {
+ /* do a little checking for the domain name. */
+ tmp = strchr(c, ':');
+ if (tmp)
+ *tmp = '\0';
+ if (gethostbyname(p)) {
+ if (tmp)
+ *tmp = ':';
+ if ((opt = strdup(p)))
+ options->fqdn = opt;
+ } else {
+ LOG(log_error, logtype_afpd, "error parsing -fqdn, gethostbyname failed for: %s", c);
}
-#endif
- options->ipaddr = strdup(c);
}
- /* FIXME CNID Cnid_srv is a server attribute */
- if ((c = getoption(buf, "-cnidserver"))) {
- char *p = strrchr(c, ':');
- if (p)
- *p = 0;
- Cnid_srv = strdup(c);
- if (p)
- Cnid_port = strdup(p + 1);
- LOG(log_debug, logtype_afpd, "CNID Server: %s:%s", Cnid_srv, Cnid_port);
+ p = iniparser_getstring(config, INISEC_AFP, "unixcodepage", "LOCALE");
+ if ((options->unixcharset = add_charset(p)) == (charset_t)-1) {
+ options->unixcharset = CH_UNIX;
+ LOG(log_warning, logtype_afpd, "Setting Unix codepage to '%s' failed", p);
+ } else {
+ options->unixcodepage = strdup(p);
}
-
- if ((c = getoption(buf, "-port")))
- options->port = strdup(c);
- if ((c = getoption(buf, "-signature")) && (opt = strdup(c)))
- options->signatureopt = opt;
-
- /* do a little checking for the domain name. */
- if ((c = getoption(buf, "-fqdn"))) {
- char *p = strchr(c, ':');
- if (p)
- *p = '\0';
- if (gethostbyname(c)) {
- if (p)
- *p = ':';
- if ((opt = strdup(c)))
- options->fqdn = opt;
- }
- else {
- LOG(log_error, logtype_afpd, "error parsing -fqdn, gethostbyname failed for: %s", c);
- }
+
+ p = iniparser_getstring(config, INISEC_AFP, "maccodepage", "MAC_ROMAN");
+ if ((options->maccharset = add_charset(p)) == (charset_t)-1) {
+ options->maccharset = CH_MAC;
+ LOG(log_warning, logtype_afpd, "Setting Unix codepage to '%s' failed", p);
+ } else {
+ options->maccharset = strdup(p);
}
- if ((c = getoption(buf, "-unixcodepage"))) {
- if ((charset_t)-1 == ( options->unixcharset = add_charset(c)) ) {
- options->unixcharset = CH_UNIX;
- LOG(log_warning, logtype_afpd, "setting Unix codepage to '%s' failed", c);
- }
- else {
- if ((opt = strdup(c)))
- options->unixcodepage = opt;
- }
+ if ((p = iniparser_getstring(config, INISEC_AFP, "fcelistener", NULL))) {
+ LOG(log_note, logtype_afpd, "Adding FCE listener: %s", p);
+ fce_add_udp_socket(p);
}
-
- if ((c = getoption(buf, "-maccodepage"))) {
- if ((charset_t)-1 == ( options->maccharset = add_charset(c)) ) {
- options->maccharset = CH_MAC;
- LOG(log_warning, logtype_afpd, "setting Mac codepage to '%s' failed", c);
- }
- else {
- if ((opt = strdup(c)))
- options->maccodepage = opt;
- }
+ if ((p = iniparser_getstring(config, INISEC_AFP, "fcecoalesce", NULL))) {
+ LOG(log_note, logtype_afpd, "Fce coalesce: %s", p);
+ fce_set_coalesce(p);
}
-
- if ((c = strstr(buf, "-closevol"))) {
- options->closevol= 1;
+ if ((p = iniparser_getstring(config, INISEC_AFP, "fceevents", NULL))) {
+ LOG(log_note, logtype_afpd, "Fce events: %s", p);
+ fce_set_events(p);
}
- if ((c = getoption(buf, "-ntdomain")) && (opt = strdup(c)))
- options->ntdomain = opt;
-
- if ((c = getoption(buf, "-ntseparator")) && (opt = strdup(c)))
- options->ntseparator = opt;
-
- if ((c = getoption(buf, "-dircachesize")))
- options->dircachesize = atoi(c);
-
- if ((c = getoption(buf, "-tcpsndbuf")))
- options->tcp_sndbuf = atoi(c);
-
- if ((c = getoption(buf, "-tcprcvbuf")))
- options->tcp_rcvbuf = atoi(c);
-
- if ((c = getoption(buf, "-fcelistener"))) {
- LOG(log_note, logtype_afpd, "Adding fce listener \"%s\"", c);
- fce_add_udp_socket(c);
- }
- if ((c = getoption(buf, "-fcecoalesce"))) {
- LOG(log_note, logtype_afpd, "Fce coalesce: %s", c);
- fce_set_coalesce(c);
- }
- if ((c = getoption(buf, "-fceevents"))) {
- LOG(log_note, logtype_afpd, "Fce events: %s", c);
- fce_set_events(c);
- }
-
- if ((c = getoption(buf, "-fceholdfmod")))
- options->fce_fmodwait = atoi(c);
-
- if ((c = getoption(buf, "-mimicmodel")) && (opt = strdup(c)))
- options->mimicmodel = opt;
-
- if ((c = getoption(buf, "-adminauthuser")) && (opt = strdup(c)))
- options->adminauthuser = opt;
+ /* Check for sane values */
+ if (options->tickleval <= 0)
+ options->tickleval = 30;
+ if (options->timeout <= 0)
+ options->timeout = 4;
+ if (options->sleep <= 4)
+ options->disconnected = options->sleep = 4;
+ if (options->dsireadbuf < 6)
+ options->dsireadbuf = 6;
+ if (options->volnamelen < 8)
+ options->volnamelen = 8; /* max mangled volname "???#FFFF" */
+ if (options->volnamelen > 255)
+ options->volnamelen = 255; /* AFP3 spec */
return 1;
}
{
show_version( );
- printf( " SLP support:\t" );
-#ifdef USE_SRVLOC
- puts( "Yes" );
-#else
- puts( "No" );
-#endif
-
printf( " Zeroconf support:\t" );
#ifdef USE_ZEROCONF
puts( "Yes" );
*/
static void show_usage( char *name )
{
- fprintf( stderr, "Usage:\t%s [-duptDTI] [-f defaultvolumes] [-s systemvolumes] [-n nbpname]\n", name );
+ fprintf( stderr, "Usage:\t%s [-duptDTI] [-n nbpname]\n", name );
fprintf( stderr, "\t [-c maxconnections] [-g guest] [-P pidfile] [-S port] [-L message]\n" );
fprintf( stderr, "\t [-F configfile] [-U uams] [-m umask]\n" );
fprintf( stderr, "\t%s -h|-v|-V\n", name );
}
-int afp_options_parse(int ac, char **av, struct afp_options *options)
+int afp_options_parse_cmdline(int ac, char **av, struct afp_options *options)
{
extern char *optarg;
extern int optind;
char *p;
char *tmp; /* Used for error checking the result of strtol */
int c, err = 0;
+ char buf[1024];
- if (gethostname(options->hostname, sizeof(options->hostname )) < 0 ) {
+ if (gethostname(buf, sizeof(buf)) < 0 ) {
perror( "gethostname" );
return 0;
}
- if (NULL != ( p = strchr(options->hostname, '.' )) ) {
+ if (NULL != (p = strchr(buf, '.')))
*p = '\0';
- }
-
-#ifdef ultrix
- if (NULL == ( p = strrchr( av[ 0 ], '/' )) ) {
- p = av[ 0 ];
- } else {
- p++;
- }
- openlog( p, LOG_PID ); /* ultrix only */
-#endif /* ultrix */
+ options->hostname = strdup(buf);
while (EOF != ( c = getopt( ac, av, OPTIONS )) ) {
switch ( c ) {
case 'd' :
options->flags |= OPTION_DEBUG;
break;
- case 'n' :
- options->server = optarg;
- break;
- case 'f' :
- options->defaultvol.name = optarg;
- break;
- case 's' :
- options->systemvol.name = optarg;
- break;
- case 'u' :
- options->flags |= OPTION_USERVOLFIRST;
- break;
- case 'c' :
- options->connections = atoi( optarg );
- break;
- case 'g' :
- options->guest = optarg;
- break;
-
- case 'P' :
- options->pidfile = optarg;
- break;
-
- case 'p':
- options->passwdbits |= PASSWD_NOSAVE;
- break;
- case 't':
- options->passwdbits |= PASSWD_SET;
- break;
-
- case 'D':
- options->transports &= ~AFPTRANS_DDP;
- break;
- case 'S':
- options->port = optarg;
- break;
- case 'T':
- options->transports &= ~AFPTRANS_TCP;
- break;
- case 'L':
- options->loginmesg = optarg;
- break;
case 'F':
options->configfile = optarg;
break;
- case 'U':
- options->uamlist = optarg;
- break;
case 'v': /* version */
show_version( ); puts( "" );
- show_paths( ); puts( "" );
+ show_paths( ); puts( "" );
exit( 0 );
break;
case 'V': /* extended version */
show_version_extended( ); puts( "" );
- show_paths( ); puts( "" );
+ show_paths( ); puts( "" );
exit( 0 );
break;
case 'h': /* usage */
show_usage( p );
exit( 0 );
break;
- case 'I':
- options->flags |= OPTION_CUSTOMICON;
- break;
- case 'm':
- options->umask = strtoul(optarg, &tmp, 8);
- if ((options->umask > 0777)) {
- fprintf(stderr, "%s: out of range umask setting provided\n", p);
- err++;
- }
- if (tmp[0] != '\0') {
- fprintf(stderr, "%s: invalid characters in umask setting provided\n", p);
- err++;
- }
- break;
default :
err++;
}
if ((err == AFP_OK) || (err == AFPERR_AUTHCONT))
return err;
- obj->reply(obj->handle, err);
+ obj->reply(obj->dsi, err);
obj->exit(0);
return AFP_OK;
int afp_zzz(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)
{
uint32_t data;
- DSI *dsi = (DSI *)AFPobj->handle;
+ DSI *dsi = (DSI *)AFPobj->dsi;
*rbuflen = 0;
ibuf += 2;
/* ---------------------- */
int afp_disconnect(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
{
- DSI *dsi = (DSI *)obj->handle;
+ DSI *dsi = (DSI *)obj->dsi;
uint16_t type;
uint32_t tklen;
pid_t token;
int afp_logout(AFPObj *obj, char *ibuf _U_, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
{
- DSI *dsi = (DSI *)(obj->handle);
+ DSI *dsi = (DSI *)(obj->dsi);
LOG(log_note, logtype_afpd, "AFP logout by %s", obj->username);
of_close_all_forks();
addicon_err:
if ( cc < 0 ) {
if (obj->proto == AFPPROTO_DSI) {
- dsi_writeinit(obj->handle, rbuf, buflen);
- dsi_writeflush(obj->handle);
+ dsi_writeinit(obj->dsi, rbuf, buflen);
+ dsi_writeflush(obj->dsi);
}
return cc;
}
switch (obj->proto) {
case AFPPROTO_DSI:
{
- DSI *dsi = obj->handle;
+ DSI *dsi = obj->dsi;
iovcnt = dsi_writeinit(dsi, rbuf, buflen);
rc = min( bsize, rsize );
if ((obj->proto == AFPPROTO_DSI) && (buflen < rc)) {
- DSI *dsi = obj->handle;
+ DSI *dsi = obj->dsi;
struct stat st;
off_t size;
/* dsi can stream requests. we can only do this if we're not checking
* for an end-of-line character. oh well. */
if ((obj->proto == AFPPROTO_DSI) && (*rbuflen < reqcount) && !nlmask) {
- DSI *dsi = obj->handle;
+ DSI *dsi = obj->dsi;
off_t size;
/* reqcount isn't always truthful. we need to deal with that. */
switch (obj->proto) {
case AFPPROTO_DSI:
{
- DSI *dsi = obj->handle;
+ DSI *dsi = obj->dsi;
/* find out what we have already and write it out. */
cc = dsi_writeinit(dsi, rbuf, *rbuflen);
afp_write_err:
if (obj->proto == AFPPROTO_DSI) {
- dsi_writeinit(obj->handle, rbuf, *rbuflen);
- dsi_writeflush(obj->handle);
+ dsi_writeinit(obj->dsi, rbuf, *rbuflen);
+ dsi_writeflush(obj->dsi);
}
if (err != AFP_OK) {
*rbuflen = 0;
#include "uam_auth.h"
#include "afp_zeroconf.h"
-#ifdef TRU64
-#include <sys/security.h>
-#include <prot.h>
-#include <sia.h>
-
-static int argc = 0;
-static char **argv = NULL;
-#endif /* TRU64 */
-
#define AFP_LISTENERS 32
#define FDSET_SAFETY 5
-unsigned char nologin = 0;
-struct afp_options default_options;
+unsigned char nologin = 0;
-static AFPConfig *configs;
+static AFPObj AFPObj;
static server_child *server_children;
static sig_atomic_t reloadconfig = 0;
static sig_atomic_t gotsigchld = 0;
static int fdset_used; /* number of used elements */
static int disasociated_ipc_fd; /* disasociated sessions uses this fd for IPC */
-#ifdef TRU64
-void afp_get_cmdline( int *ac, char ***av)
-{
- *ac = argc;
- *av = argv;
-}
-#endif /* TRU64 */
-
/* This is registered with atexit() */
static void afp_exit(void)
{
/* ------------------
initialize fd set we are waiting for.
*/
-static void fd_set_listening_sockets(void)
+static void fd_set_listening_sockets(const AFPObj *config)
{
- AFPConfig *config;
+ const DSI *dsi;
- for (config = configs; config; config = config->next) {
- if (config->fd < 0) /* for proxies */
- continue;
- fdset_add_fd(default_options.connections + AFP_LISTENERS + FDSET_SAFETY,
+ for (dsi = config->dsi; dsi; dsi = dsi->next) {
+ fdset_add_fd(config->options.connections + AFP_LISTENERS + FDSET_SAFETY,
&fdset,
&polldata,
&fdset_used,
&fdset_size,
- config->fd,
+ dsi->serversock,
LISTEN_FD,
- config);
+ dsi);
}
- if (default_options.flags & OPTION_KEEPSESSIONS)
- fdset_add_fd(default_options.connections + AFP_LISTENERS + FDSET_SAFETY,
+ if (config->options.flags & OPTION_KEEPSESSIONS)
+ fdset_add_fd(config->options.connections + AFP_LISTENERS + FDSET_SAFETY,
&fdset,
&polldata,
&fdset_used,
NULL);
}
-static void fd_reset_listening_sockets(void)
+static void fd_reset_listening_sockets(const AFPObj *config)
{
- AFPConfig *config;
+ const DSI *dsi;
- for (config = configs; config; config = config->next) {
- if (config->fd < 0) /* for proxies */
- continue;
- fdset_del_fd(&fdset, &polldata, &fdset_used, &fdset_size, config->fd);
+ for (dsi = config->dsi; dsi; dsi = dsi->next) {
+ fdset_del_fd(&fdset, &polldata, &fdset_used, &fdset_size, dsi->serversock);
}
- if (default_options.flags & OPTION_KEEPSESSIONS)
+ if (config->options.flags & OPTION_KEEPSESSIONS)
fdset_del_fd(&fdset, &polldata, &fdset_used, &fdset_size, disasociated_ipc_fd);
}
/* ------------------ */
static void afp_goaway(int sig)
{
- AFPConfig *config;
-
switch( sig ) {
case SIGTERM:
if (server_children)
server_child_kill(server_children, CHILD_DSIFORK, sig);
- for (config = configs; config; config = config->next)
- if (config->server_cleanup)
- config->server_cleanup(config);
- server_unlock(default_options.pidfile);
+ dsi_cleanup(AFPObj);
+ server_unlock(AFPObj->options.pidfile);
exit(0);
break;
int main(int ac, char **av)
{
- AFPConfig *config;
fd_set rfds;
void *ipc;
struct sigaction sv;
sigset_t sigs;
int ret;
-
-#ifdef TRU64
- argc = ac;
- argv = av;
- set_auth_parameters( ac, av );
-#endif /* TRU64 */
+ struct afp_options default_options = {0};
/* Parse argv args and initialize default options */
afp_options_init(&default_options);
- if (!afp_options_parse(ac, av, &default_options))
+ if (!afp_options_parse_cmdline(ac, av, &default_options))
exit(EXITERR_CONF);
if (check_lockfile("afpd", default_options.pidfile) != 0)
sigaddset(&sigs, SIGCHLD);
pthread_sigmask(SIG_BLOCK, &sigs, NULL);
- if (!(configs = configinit(&default_options))) {
+ if (!(AFPObj = configinit(&default_options))) {
LOG(log_error, logtype_afpd, "main: no servers configured");
exit(EXITERR_CONF);
}
/* watch atp, dsi sockets and ipc parent/child file descriptor. */
- if (default_options.flags & OPTION_KEEPSESSIONS) {
+ if (AFPObj.options.flags & OPTION_KEEPSESSIONS) {
LOG(log_note, logtype_afpd, "Activating continous service");
disasociated_ipc_fd = ipc_server_uds(_PATH_AFP_IPC);
}
- fd_set_listening_sockets();
+ fd_set_listening_sockets(&AFPObj);
/* set limits */
(void)setlimits();
if (reloadconfig) {
nologin++;
auth_unload();
- fd_reset_listening_sockets();
+ fd_reset_listening_sockets(&AFPObj);
LOG(log_info, logtype_afpd, "re-reading configuration file");
- for (config = configs; config; config = config->next)
- if (config->server_cleanup)
- config->server_cleanup(config);
+ dsi_cleanup(&AFPObj);
/* configfree close atp socket used for DDP tickle, there's an issue
* with atp tid. */
- configfree(configs, NULL);
- if (!(configs = configinit(&default_options))) {
+ configfree(&AFPObj);
+ if (!(AFPObj = configinit(&default_options))) {
LOG(log_error, logtype_afpd, "config re-read: no servers configured");
exit(EXITERR_CONF);
}
- fd_set_listening_sockets();
+ fd_set_listening_sockets(&AFPObj);
nologin = 0;
reloadconfig = 0;
switch (polldata[i].fdtype) {
case LISTEN_FD:
- config = (AFPConfig *)polldata[i].data;
- /* config->server_start is afp_config.c:dsi_start() for DSI */
- if (child = config->server_start(config, configs, server_children)) {
+ if (child = dsi_start(AFPObj, (DSI *)polldata[i].data, server_children)) {
/* Add IPC fd to select fd set */
- fdset_add_fd(default_options.connections + AFP_LISTENERS + FDSET_SAFETY,
+ fdset_add_fd(AFPObj.options.connections + AFP_LISTENERS + FDSET_SAFETY,
&fdset,
&polldata,
&fdset_used,
fdset_del_fd(&fdset, &polldata, &fdset_used, &fdset_size, child->ipc_fds[0]);
close(child->ipc_fds[0]);
child->ipc_fds[0] = -1;
- if ((default_options.flags & OPTION_KEEPSESSIONS) && child->disasociated) {
+ if ((AFPObj.options.flags & OPTION_KEEPSESSIONS) && child->disasociated) {
LOG(log_note, logtype_afpd, "main: removing reattached child[%u]", child->pid);
server_child_remove(server_children, CHILD_DSIFORK, child->pid);
}
break;
}
child->disasociated = 1;
- fdset_add_fd(default_options.connections + AFP_LISTENERS + FDSET_SAFETY,
+ fdset_add_fd(AFPObj.options.connections + AFP_LISTENERS + FDSET_SAFETY,
&fdset,
&polldata,
&fdset_used,
uid_t euid;
uint32_t maxmsgsize;
- maxmsgsize = (obj->proto == AFPPROTO_DSI)?MIN(MAX(((DSI*)obj->handle)->attn_quantum, MAXMESGSIZE),MAXPATHLEN):MAXMESGSIZE;
+ maxmsgsize = (obj->proto == AFPPROTO_DSI)?MIN(MAX(((DSI*)obj->dsi)->attn_quantum, MAXMESGSIZE),MAXPATHLEN):MAXMESGSIZE;
i=0;
/* Construct file name SERVERTEXT/message.[pid] */
*rbuflen = 0;
- msgsize = (obj->proto == AFPPROTO_DSI)?MAX(((DSI*)obj->handle)->attn_quantum, MAXMESGSIZE):MAXMESGSIZE;
+ msgsize = (obj->proto == AFPPROTO_DSI)?MAX(((DSI*)obj->dsi)->attn_quantum, MAXMESGSIZE):MAXMESGSIZE;
memcpy(&type, ibuf + 2, sizeof(type));
memcpy(&bitmap, ibuf + 4, sizeof(bitmap));
if (dsiconfig) {
status = dsiconfig->status;
maxstatuslen=sizeof(dsiconfig->status);
- dsi = dsiconfig->obj.handle;
+ dsi = dsiconfig->obj.dsi;
if (dsi->server.ss_family == AF_INET) { /* IPv4 */
const struct sockaddr_in *sa4 = (struct sockaddr_in *)&dsi->server;
ipok = sa4->sin_addr.s_addr ? 1 : 0;
if (gettimeofday(&tv, &tz) < 0)
return -1;
- srandom(tv.tv_sec + (unsigned long) obj + (unsigned long) obj->handle);
+ srandom(tv.tv_sec + (unsigned long) obj + (unsigned long) obj->dsi);
for (i = 0; i < len; i += sizeof(result)) {
result = random();
memcpy(buf + i, &result, sizeof(result));
*len = sizeof(obj->options.passwdminlen);
break;
- case UAM_PASSWD_MAXFAIL:
- *((int *) option) = obj->options.loginmaxfail;
- *len = sizeof(obj->options.loginmaxfail);
- break;
-
case UAM_PASSWD_EXPIRETIME: /* not implemented */
default:
return -1;
case UAM_OPTION_CLIENTNAME:
{
- struct DSI *dsi = obj->handle;
+ struct DSI *dsi = obj->dsi;
const struct sockaddr *sa;
static char hbuf[NI_MAXHOST];
if (!obj)
return AFPERR_PARAM;
- len = dsi_writeinit(obj->handle, buf, *buflen);
+ len = dsi_writeinit(obj->dsi, buf, *buflen);
if (!len || ((len = action(handle, buf, len)) < 0)) {
- dsi_writeflush(obj->handle);
+ dsi_writeflush(obj->dsi);
goto uam_afp_read_err;
}
- while ((len = (dsi_write(obj->handle, buf, *buflen)))) {
+ while ((len = (dsi_write(obj->dsi, buf, *buflen)))) {
if ((len = action(handle, buf, len)) < 0) {
- dsi_writeflush(obj->handle);
+ dsi_writeflush(obj->dsi);
goto uam_afp_read_err;
}
}
} else if (is_var(p, "$c")) {
if (afpmaster && xlatevolname)
return NULL;
- DSI *dsi = obj->handle;
+ DSI *dsi = obj->dsi;
len = sprintf(dest, "%s:%u",
getip_string((struct sockaddr *)&dsi->client),
getip_port((struct sockaddr *)&dsi->client));
} else if (is_var(p, "$i")) {
if (afpmaster && xlatevolname)
return NULL;
- DSI *dsi = obj->handle;
+ DSI *dsi = obj->dsi;
q = getip_string((struct sockaddr *)&dsi->client);
} else if (is_var(p, "$s")) {
if (obj->Obj)
{
int mask_int;
char buf[MAXPATHLEN + 1], *p, *b;
- DSI *dsi = obj->handle;
+ DSI *dsi = obj->dsi;
struct sockaddr_storage client;
if (!args)
if ( (vol->v_flags & AFPVOL_OPEN) && vol->v_mtime + 30 < tv.tv_sec) {
if ( !stat( vol->v_path, &st ) && vol->v_mtime != st.st_mtime ) {
vol->v_mtime = st.st_mtime;
- if (!obj->attention(obj->handle, AFPATTN_NOTIFY | AFPATTN_VOLCHANGED))
+ if (!obj->attention(obj->dsi, AFPATTN_NOTIFY | AFPATTN_VOLCHANGED))
return -1;
return 1;
}
* AFP 3.2 and above clients seem to be ok without so many notification
*/
if (afp_version < 32 && obj->options.server_notif) {
- obj->attention(obj->handle, AFPATTN_NOTIFY | AFPATTN_VOLCHANGED);
+ obj->attention(obj->dsi, AFPATTN_NOTIFY | AFPATTN_VOLCHANGED);
}
}
}
#define AFPPROTO_ASP 1
#define AFPPROTO_DSI 2
-/* actual transports. the DSI ones (tcp right now) need to be
- * kept in sync w/ <atalk/dsi.h>.
- * convention: AFPTRANS_* = (1 << DSI_*)
- */
-#define AFPTRANS_NONE 0
-#define AFPTRANS_DDP (1 << 0)
-#define AFPTRANS_TCP (1 << 1)
-#define AFPTRANS_ALL (AFPTRANS_DDP | AFPTRANS_TCP)
-
/* server flags */
#define AFPSRVRINFO_COPY (1<<0) /* supports copyfile */
#define AFPSRVRINFO_PASSWD (1<<1) /* supports change password */
Function prototypes
---------------------------------------------------------------------------*/
-/*-------------------------------------------------------------------------*/
-/**
- @brief Compute the hash key for a string.
- @param key Character string to use for key.
- @return 1 unsigned int on at least 32 bits.
-
- This hash function has been taken from an Article in Dr Dobbs Journal.
- This is normally a collision-free function, distributing keys evenly.
- The key is stored anyway in the struct so that collision can be avoided
- by comparing the key itself in last resort.
- */
-/*--------------------------------------------------------------------------*/
-unsigned dictionary_hash(char * key);
-
-/*-------------------------------------------------------------------------*/
-/**
- @brief Create a new dictionary object.
- @param size Optional initial size of the dictionary.
- @return 1 newly allocated dictionary objet.
-
- This function allocates a new dictionary object of given size and returns
- it. If you do not know in advance (roughly) the number of entries in the
- dictionary, give size=0.
- */
-/*--------------------------------------------------------------------------*/
-dictionary * dictionary_new(int size);
-
-/*-------------------------------------------------------------------------*/
-/**
- @brief Delete a dictionary object
- @param d dictionary object to deallocate.
- @return void
-
- Deallocate a dictionary object and all memory associated to it.
- */
-/*--------------------------------------------------------------------------*/
-void dictionary_del(dictionary * vd);
-
-/*-------------------------------------------------------------------------*/
-/**
- @brief Get a value from a dictionary.
- @param d dictionary object to search.
- @param key Key to look for in the dictionary.
- @param def Default value to return if key not found.
- @return 1 pointer to internally allocated character string.
-
- This function locates a key in a dictionary and returns a pointer to its
- value, or the passed 'def' pointer if no such key can be found in
- dictionary. The returned character pointer points to data internal to the
- dictionary object, you should not try to free it or modify it.
- */
-/*--------------------------------------------------------------------------*/
-char * dictionary_get(dictionary * d, char * key, char * def);
-
-
-/*-------------------------------------------------------------------------*/
-/**
- @brief Set a value in a dictionary.
- @param d dictionary object to modify.
- @param key Key to modify or add.
- @param val Value to add.
- @return int 0 if Ok, anything else otherwise
-
- If the given key is found in the dictionary, the associated value is
- replaced by the provided one. If the key cannot be found in the
- dictionary, it is added to it.
-
- It is Ok to provide a NULL value for val, but NULL values for the dictionary
- or the key are considered as errors: the function will return immediately
- in such a case.
-
- Notice that if you dictionary_set a variable to NULL, a call to
- dictionary_get will return a NULL value: the variable will be found, and
- its value (NULL) is returned. In other words, setting the variable
- content to NULL is equivalent to deleting the variable from the
- dictionary. It is not possible (in this implementation) to have a key in
- the dictionary without value.
-
- This function returns non-zero in case of failure.
- */
-/*--------------------------------------------------------------------------*/
-int dictionary_set(dictionary * vd, char * key, char * val);
-
-/*-------------------------------------------------------------------------*/
-/**
- @brief Delete a key in a dictionary
- @param d dictionary object to modify.
- @param key Key to remove.
- @return void
-
- This function deletes a key in a dictionary. Nothing is done if the
- key cannot be found.
- */
-/*--------------------------------------------------------------------------*/
-void dictionary_unset(dictionary * d, char * key);
-
-
-/*-------------------------------------------------------------------------*/
-/**
- @brief Dump a dictionary to an opened file pointer.
- @param d Dictionary to dump
- @param f Opened file pointer.
- @return void
-
- Dumps a dictionary onto an opened file pointer. Key pairs are printed out
- as @c [Key]=[Value], one per line. It is Ok to provide stdout or stderr as
- output file pointers.
- */
-/*--------------------------------------------------------------------------*/
-void dictionary_dump(dictionary * d, FILE * out);
+unsigned dictionary_hash (char * key);
+dictionary *dictionary_new (int size);
+void dictionary_del (dictionary * vd);
+char *dictionary_get (dictionary * d, char *section, char * key, char * def);
+int dictionary_set (dictionary * vd, char *section, char * key, char * val);
+void dictionary_unset (dictionary * d, char *section, char * key);
+void dictionary_dump (dictionary * d, FILE * out);
#endif
* All rights reserved.
*/
-#ifndef _ATALK_DSI_H
+#ifndef _ATALK_DSI_H
#define _ATALK_DSI_H
#include <sys/types.h>
#include <atalk/globals.h>
/* What a DSI packet looks like:
- 0 32
- |-------------------------------|
- |flags |command| requestID |
- |-------------------------------|
- |error code/enclosed data offset|
- |-------------------------------|
- |total data length |
- |-------------------------------|
- |reserved field |
- |-------------------------------|
-
- CONVENTION: anything with a dsi_ prefix is kept in network byte order.
+ 0 32
+ |-------------------------------|
+ |flags |command| requestID |
+ |-------------------------------|
+ |error code/enclosed data offset|
+ |-------------------------------|
+ |total data length |
+ |-------------------------------|
+ |reserved field |
+ |-------------------------------|
+
+ CONVENTION: anything with a dsi_ prefix is kept in network byte order.
*/
-/* these need to be kept in sync w/ AFPTRANS_* in <atalk/afp.h>.
+/* these need to be kept in sync w/ AFPTRANS_* in <atalk/afp.h>.
* convention: AFPTRANS_* = (1 << DSI_*) */
typedef enum {
- DSI_MIN = 1,
- DSI_TCPIP = 1,
- DSI_MAX = 1
+ DSI_MIN = 1,
+ DSI_TCPIP = 1,
+ DSI_MAX = 1
} dsi_proto;
#define DSI_BLOCKSIZ 16
struct dsi_block {
- uint8_t dsi_flags; /* packet type: request or reply */
- uint8_t dsi_command; /* command */
- uint16_t dsi_requestID; /* request ID */
- uint32_t dsi_code; /* error code or data offset */
- uint32_t dsi_len; /* total data length */
- uint32_t dsi_reserved; /* reserved field */
+ uint8_t dsi_flags; /* packet type: request or reply */
+ uint8_t dsi_command; /* command */
+ uint16_t dsi_requestID; /* request ID */
+ uint32_t dsi_code; /* error code or data offset */
+ uint32_t dsi_len; /* total data length */
+ uint32_t dsi_reserved; /* reserved field */
};
-#define DSI_CMDSIZ 8192
+#define DSI_CMDSIZ 8192
#define DSI_DATASIZ 8192
/* child and parent processes might interpret a couple of these
* differently. */
typedef struct DSI {
- AFPObj *AFPobj;
- dsi_proto protocol;
- struct dsi_block header;
- struct sockaddr_storage server, client;
- struct itimerval timer;
- int tickle; /* tickle count */
- int in_write; /* in the middle of writing multiple packets,
- signal handlers can't write to the socket */
- int msg_request; /* pending message to the client */
- int down_request; /* pending SIGUSR1 down in 5 mn */
-
- uint32_t attn_quantum, datasize, server_quantum;
- uint16_t serverID, clientID;
- char *status;
- uint8_t commands[DSI_CMDSIZ], data[DSI_DATASIZ];
- size_t statuslen;
- size_t datalen, cmdlen;
- off_t read_count, write_count;
- uint32_t flags; /* DSI flags like DSI_SLEEPING, DSI_DISCONNECTED */
- const char *program;
- int socket, serversock;
-
- /* protocol specific open/close, send/receive
- * send/receive fill in the header and use dsi->commands.
- * write/read just write/read data */
- pid_t (*proto_open)(struct DSI *);
- void (*proto_close)(struct DSI *);
-
- /* url registered with slpd */
-#ifdef USE_SRVLOC
- char srvloc_url[512];
-#endif
+ DSI *next; /* multiple listening addresses */
+ AFPObj *AFPobj;
+ struct dsi_block header;
+ struct sockaddr_storage server, client;
+ struct itimerval timer;
+ int tickle; /* tickle count */
+ int in_write; /* in the middle of writing multiple packets,
+ signal handlers can't write to the socket */
+ int msg_request; /* pending message to the client */
+ int down_request; /* pending SIGUSR1 down in 5 mn */
+
+ uint32_t attn_quantum, datasize, server_quantum;
+ uint16_t serverID, clientID;
+ char *status;
+ uint8_t commands[DSI_CMDSIZ], data[DSI_DATASIZ];
+ size_t statuslen;
+ size_t datalen, cmdlen;
+ off_t read_count, write_count;
+ uint32_t flags; /* DSI flags like DSI_SLEEPING, DSI_DISCONNECTED */
+ const char *program;
+ int socket; /* AFP session socket */
+ int serversock; /* listening socket */
+
+ /* DSI readahead buffer used for buffered reads in dsi_peek */
+ size_t dsireadbuf; /* size of the DSI readahead buffer used in dsi_peek() */
+ char *buffer; /* buffer start */
+ char *start; /* current buffer head */
+ char *eof; /* end of currently used buffer */
+ char *end;
#ifdef USE_ZEROCONF
- char *bonjourname; /* server name as UTF8 maxlen MAXINSTANCENAMELEN */
- int zeroconf_registered;
+ char *bonjourname; /* server name as UTF8 maxlen MAXINSTANCENAMELEN */
+ int zeroconf_registered;
#endif
- /* DSI readahead buffer used for buffered reads in dsi_peek */
- size_t dsireadbuf; /* size of the DSI readahead buffer used in dsi_peek() */
- char *buffer;
- char *start;
- char *eof;
- char *end;
+ /* protocol specific open/close, send/receive
+ * send/receive fill in the header and use dsi->commands.
+ * write/read just write/read data */
+ pid_t (*proto_open)(struct DSI *);
+ void (*proto_close)(struct DSI *);
} DSI;
-
+
/* DSI flags */
#define DSIFL_REQUEST 0x00
#define DSIFL_REPLY 0x01
#define DSIFUNC_MAX 8 /* largest command */
/* DSI Error codes: most of these aren't used. */
-#define DSIERR_OK 0x0000
-#define DSIERR_BADVERS 0xfbd6
-#define DSIERR_BUFSMALL 0xfbd5
-#define DSIERR_NOSESS 0xfbd4
-#define DSIERR_NOSERV 0xfbd3
-#define DSIERR_PARM 0xfbd2
-#define DSIERR_SERVBUSY 0xfbd1
-#define DSIERR_SESSCLOS 0xfbd0
-#define DSIERR_SIZERR 0xfbcf
-#define DSIERR_TOOMANY 0xfbce
-#define DSIERR_NOACK 0xfbcd
+#define DSIERR_OK 0x0000
+#define DSIERR_BADVERS 0xfbd6
+#define DSIERR_BUFSMALL 0xfbd5
+#define DSIERR_NOSESS 0xfbd4
+#define DSIERR_NOSERV 0xfbd3
+#define DSIERR_PARM 0xfbd2
+#define DSIERR_SERVBUSY 0xfbd1
+#define DSIERR_SESSCLOS 0xfbd0
+#define DSIERR_SIZERR 0xfbcf
+#define DSIERR_TOOMANY 0xfbce
+#define DSIERR_NOACK 0xfbcd
/* server and client quanta */
#define DSI_DEFQUANT 2 /* default attention quantum size */
/* basic initialization: dsi_init.c */
extern DSI *dsi_init (const dsi_proto /*protocol*/,
- const char * /*program*/,
- const char * /*host*/, const char * /*address*/,
- const char * /*port*/, const int /*proxy*/,
- const uint32_t /* server quantum */);
+ const char * /*program*/,
+ const char * /*host*/, const char * /*address*/,
+ const char * /*port*/, const int /*proxy*/,
+ const uint32_t /* server quantum */);
extern void dsi_setstatus (DSI *, char *, const size_t);
/* in dsi_getsess.c */
/* client reads -- dsi_read.c */
extern ssize_t dsi_readinit (DSI *, void *, const size_t, const size_t,
- const int);
+ const int);
extern ssize_t dsi_read (DSI *, void *, const size_t);
extern void dsi_readdone (DSI *);
/* some useful macros */
#define dsi_serverID(x) ((x)->serverID++)
-#define dsi_send(x) do { \
- (x)->header.dsi_len = htonl((x)->cmdlen); \
- dsi_stream_send((x), (x)->commands, (x)->cmdlen); \
-} while (0)
+#define dsi_send(x) do { \
+ (x)->header.dsi_len = htonl((x)->cmdlen); \
+ dsi_stream_send((x), (x)->commands, (x)->cmdlen); \
+ } while (0)
#endif /* atalk/dsi.h */
#include <netdb.h> /* this isn't header-protected under ultrix */
#endif /* HAVE_NETDB_H */
-#include <netatalk/at.h>
#include <atalk/afp.h>
#include <atalk/compat.h>
#include <atalk/unicode.h>
#include <atalk/uam.h>
+#include <atalk/iniparser.h>
/* #define DOSFILELEN 12 */ /* Type1, DOS-compat*/
#define MACFILELEN 31 /* Type2, HFS-compat */
#define MAXUSERLEN 256
#define OPTION_DEBUG (1 << 0)
-#define OPTION_USERVOLFIRST (1 << 1)
-#define OPTION_NOUSERVOL (1 << 2)
-#define OPTION_PROXY (1 << 3)
+#define OPTION_CLOSEVOL (1 << 1)
#define OPTION_CUSTOMICON (1 << 4)
-#define OPTION_NOSLP (1 << 5)
#define OPTION_ANNOUNCESSH (1 << 6)
#define OPTION_UUID (1 << 7)
#define OPTION_ACL2MACCESS (1 << 8)
#define OPTION_NOZEROCONF (1 << 9)
#define OPTION_KEEPSESSIONS (1 << 10) /* preserve sessions across master afpd restart with SIGQUIT */
+/**********************************************************************************************
+ * Ini config sections
+ **********************************************************************************************/
+
+#define INISEC_GLOBAL "General"
+#define INISEC_AFP "AFP"
+
+struct DSI;
+#define AFPOBJ_TMPSIZ (MAXPATHLEN)
+
/* a couple of these options could get stuck in unions to save
* space. */
struct afp_volume_name {
};
struct afp_options {
- int connections, transports, tickleval, timeout, server_notif, flags, dircachesize;
+ int connections; /* Maximum number of possible AFP connections */
+ int tickleval;
+ int timeout;
+ int server_notif;
+ int flags;
+ int dircachesize;
int sleep; /* Maximum time allowed to sleep (in tickles) */
int disconnected; /* Maximum time in disconnected state (in tickles) */
int fce_fmodwait; /* number of seconds FCE file mod events are put on hold */
unsigned int tcp_sndbuf, tcp_rcvbuf;
- unsigned char passwdbits, passwdminlen, loginmaxfail;
+ unsigned char passwdbits, passwdminlen;
uint32_t server_quantum;
int dsireadbuf; /* scale factor for sizefof(dsi->buffer) = server_quantum * dsireadbuf */
- char hostname[MAXHOSTNAMELEN + 1], *server, *ipaddr, *port, *configfile;
+ char *hostname;
+ char *ipaddr, *port;
+ char *Cnid_srv, *Cnid_port;
+ char *configfile;
char *uampath, *fqdn;
char *pidfile;
char *sigconffile;
char *uuidconf;
- struct afp_volume_name defaultvol, systemvol, uservol;
- int closevol;
-
char *guest, *loginmesg, *keyfile, *passwdfile;
char *uamlist;
char *authprintdir;
gid_t admingid;
#endif /* ADMIN_GRP */
int volnamelen;
-
/* default value for winbind authentication */
char *ntdomain, *ntseparator;
char *logconfig;
-
+ char *logfile;
char *mimicmodel;
char *adminauthuser;
};
-#define AFPOBJ_TMPSIZ (MAXPATHLEN)
-typedef struct _AFPObj {
- int proto;
- unsigned long servernum;
- void *handle; /* either (DSI *) or (ASP *) */
- void *config;
+typedef struct AFPObj {
+ int statuslen;
+ char status[1400];
+ const void *signature;
+ struct DSI *dsi;
struct afp_options options;
- char *Obj, *Type, *Zone;
+ const dictionary *iniconfig;
char username[MAXUSERLEN];
- void (*logout)(void), (*exit)(int);
- int (*reply)(void *, int);
- int (*attention)(void *, AFPUserBytes);
/* to prevent confusion, only use these in afp_* calls */
char oldtmp[AFPOBJ_TMPSIZ + 1], newtmp[AFPOBJ_TMPSIZ + 1];
void *uam_cookie; /* cookie for uams */
struct session_info sinfo;
uid_t uid; /* client running user id */
int ipc_fd; /* anonymous PF_UNIX socket for IPC with afpd parent */
+ /* Functions */
+ void (*logout)(void);
+ void (*exit)(int);
+ int (*reply)(void *, int);
+ int (*attention)(void *, AFPUserBytes);
} AFPObj;
/* typedef for AFP functions handlers */
extern int get_afp_errno (const int param);
extern void afp_options_init (struct afp_options *);
-extern int afp_options_parse (int, char **, struct afp_options *);
-extern int afp_options_parseline (char *, struct afp_options *);
+extern int afp_options_parse_cmdline (int, char **, struct afp_options *);
+extern int afp_options_parseline (char *, struct afp_options *);
extern void afp_options_free (struct afp_options *,
const struct afp_options *);
extern void setmessage (const char *);
#include "dictionary.h"
-/*-------------------------------------------------------------------------*/
-/**
- @brief Get number of sections in a dictionary
- @param d Dictionary to examine
- @return int Number of sections found in dictionary
-
- This function returns the number of sections found in a dictionary.
- The test to recognize sections is done on the string stored in the
- dictionary: a section name is given as "section" whereas a key is
- stored as "section:key", thus the test looks for entries that do not
- contain a colon.
-
- This clearly fails in the case a section name contains a colon, but
- this should simply be avoided.
-
- This function returns -1 in case of error.
- */
-/*--------------------------------------------------------------------------*/
-
-int iniparser_getnsec(dictionary * d);
-
-
-/*-------------------------------------------------------------------------*/
-/**
- @brief Get name for section n in a dictionary.
- @param d Dictionary to examine
- @param n Section number (from 0 to nsec-1).
- @return Pointer to char string
-
- This function locates the n-th section in a dictionary and returns
- its name as a pointer to a string statically allocated inside the
- dictionary. Do not free or modify the returned string!
-
- This function returns NULL in case of error.
- */
-/*--------------------------------------------------------------------------*/
-
-char * iniparser_getsecname(dictionary * d, int n);
-
-
-/*-------------------------------------------------------------------------*/
-/**
- @brief Save a dictionary to a loadable ini file
- @param d Dictionary to dump
- @param f Opened file pointer to dump to
- @return void
-
- This function dumps a given dictionary into a loadable ini file.
- It is Ok to specify @c stderr or @c stdout as output files.
- */
-/*--------------------------------------------------------------------------*/
-
-void iniparser_dump_ini(dictionary * d, FILE * f);
-
-/*-------------------------------------------------------------------------*/
-/**
- @brief Dump a dictionary to an opened file pointer.
- @param d Dictionary to dump.
- @param f Opened file pointer to dump to.
- @return void
-
- This function prints out the contents of a dictionary, one element by
- line, onto the provided file pointer. It is OK to specify @c stderr
- or @c stdout as output files. This function is meant for debugging
- purposes mostly.
- */
-/*--------------------------------------------------------------------------*/
-void iniparser_dump(dictionary * d, FILE * f);
-
-/*-------------------------------------------------------------------------*/
-/**
- @brief Get the string associated to a key
- @param d Dictionary to search
- @param key Key string to look for
- @param def Default value to return if key not found.
- @return pointer to statically allocated character string
-
- This function queries a dictionary for a key. A key as read from an
- ini file is given as "section:key". If the key cannot be found,
- the pointer passed as 'def' is returned.
- The returned char pointer is pointing to a string allocated in
- the dictionary, do not free or modify it.
- */
-/*--------------------------------------------------------------------------*/
-char * iniparser_getstring(dictionary * d, char * key, char * def);
-
-/*-------------------------------------------------------------------------*/
-/**
- @brief Get the string associated to a key, convert to an int
- @param d Dictionary to search
- @param key Key string to look for
- @param notfound Value to return in case of error
- @return integer
-
- This function queries a dictionary for a key. A key as read from an
- ini file is given as "section:key". If the key cannot be found,
- the notfound value is returned.
-
- Supported values for integers include the usual C notation
- so decimal, octal (starting with 0) and hexadecimal (starting with 0x)
- are supported. Examples:
-
- - "42" -> 42
- - "042" -> 34 (octal -> decimal)
- - "0x42" -> 66 (hexa -> decimal)
-
- Warning: the conversion may overflow in various ways. Conversion is
- totally outsourced to strtol(), see the associated man page for overflow
- handling.
-
- Credits: Thanks to A. Becker for suggesting strtol()
- */
-/*--------------------------------------------------------------------------*/
-int iniparser_getint(dictionary * d, char * key, int notfound);
-
-/*-------------------------------------------------------------------------*/
-/**
- @brief Get the string associated to a key, convert to a double
- @param d Dictionary to search
- @param key Key string to look for
- @param notfound Value to return in case of error
- @return double
-
- This function queries a dictionary for a key. A key as read from an
- ini file is given as "section:key". If the key cannot be found,
- the notfound value is returned.
- */
-/*--------------------------------------------------------------------------*/
-double iniparser_getdouble(dictionary * d, char * key, double notfound);
-
-/*-------------------------------------------------------------------------*/
-/**
- @brief Get the string associated to a key, convert to a boolean
- @param d Dictionary to search
- @param key Key string to look for
- @param notfound Value to return in case of error
- @return integer
-
- This function queries a dictionary for a key. A key as read from an
- ini file is given as "section:key". If the key cannot be found,
- the notfound value is returned.
-
- A true boolean is found if one of the following is matched:
-
- - A string starting with 'y'
- - A string starting with 'Y'
- - A string starting with 't'
- - A string starting with 'T'
- - A string starting with '1'
-
- A false boolean is found if one of the following is matched:
-
- - A string starting with 'n'
- - A string starting with 'N'
- - A string starting with 'f'
- - A string starting with 'F'
- - A string starting with '0'
-
- The notfound value returned if no boolean is identified, does not
- necessarily have to be 0 or 1.
- */
-/*--------------------------------------------------------------------------*/
-int iniparser_getboolean(dictionary * d, char * key, int notfound);
-
-
-/*-------------------------------------------------------------------------*/
-/**
- @brief Set an entry in a dictionary.
- @param ini Dictionary to modify.
- @param entry Entry to modify (entry name)
- @param val New value to associate to the entry.
- @return int 0 if Ok, -1 otherwise.
-
- If the given entry can be found in the dictionary, it is modified to
- contain the provided value. If it cannot be found, -1 is returned.
- It is Ok to set val to NULL.
- */
-/*--------------------------------------------------------------------------*/
-int iniparser_set(dictionary * ini, char * entry, char * val);
-
-
-/*-------------------------------------------------------------------------*/
-/**
- @brief Delete an entry in a dictionary
- @param ini Dictionary to modify
- @param entry Entry to delete (entry name)
- @return void
-
- If the given entry can be found, it is deleted from the dictionary.
- */
-/*--------------------------------------------------------------------------*/
-void iniparser_unset(dictionary * ini, char * entry);
-
-/*-------------------------------------------------------------------------*/
-/**
- @brief Finds out if a given entry exists in a dictionary
- @param ini Dictionary to search
- @param entry Name of the entry to look for
- @return integer 1 if entry exists, 0 otherwise
-
- Finds out if a given entry exists in the dictionary. Since sections
- are stored as keys with NULL associated values, this is the only way
- of querying for the presence of sections in a dictionary.
- */
-/*--------------------------------------------------------------------------*/
-int iniparser_find_entry(dictionary * ini, char * entry) ;
-
-/*-------------------------------------------------------------------------*/
-/**
- @brief Parse an ini file and return an allocated dictionary object
- @param ininame Name of the ini file to read.
- @return Pointer to newly allocated dictionary
-
- This is the parser for ini files. This function is called, providing
- the name of the file to be read. It returns a dictionary object that
- should not be accessed directly, but through accessor functions
- instead.
-
- The returned dictionary must be freed using iniparser_freedict().
- */
-/*--------------------------------------------------------------------------*/
-dictionary * iniparser_load(char * ininame);
-
-/*-------------------------------------------------------------------------*/
-/**
- @brief Free all memory associated to an ini dictionary
- @param d Dictionary to free
- @return void
-
- Free all memory associated to an ini dictionary.
- It is mandatory to call this function before the dictionary object
- gets out of the current context.
- */
-/*--------------------------------------------------------------------------*/
-void iniparser_freedict(dictionary * d);
+int iniparser_getnsec(dictionary * d);
+char *iniparser_getsecname(dictionary * d, int n);
+void iniparser_dump_ini(dictionary * d, FILE * f);
+void iniparser_dump(dictionary * d, FILE * f);
+char *iniparser_getstring(dictionary * d, char *section, char * key, char * def);
+char *iniparser_getstringdup(dictionary * d, char *section, char * key, char * def);
+int iniparser_getint(dictionary * d, char *section, char * key, int notfound);
+double iniparser_getdouble(dictionary * d, char *section, char * key, double notfound);
+int iniparser_getboolean(dictionary * d, char *section, char * key, int notfound);
+int iniparser_set(dictionary * ini, char *section, char * key, char * val);
+void iniparser_unset(dictionary * ini, char *section, char * key);
+int iniparser_find_entry(dictionary * ini, char * entry) ;
+dictionary *iniparser_load(char * ininame);
+void iniparser_freedict(dictionary * d);
#endif
#ifndef LDAPCONFIG_H
#define LDAPCONFIG_H
+#include <atalk/iniparser.h>
+
/* One function does the whole job */
-extern int acl_ldap_readconfig(char *name);
+extern int acl_ldap_readconfig(dictionary *iniconfig);
/* These are the prefvalues */
extern char *ldap_server;
Global function decarations
========================================================================= */
-/* */
-void log_init(void);
-
-/* Setup the level and type of log that will be logged for file loggging */
-void log_setup(const char *filename, enum loglevels loglevel, enum logtypes logtype);
-
-/* Setup the level and type of log that will be logged to syslog. */
-void syslog_setup(int loglevel, enum logtypes logtype,
- int display_options, int facility);
-
-/* This gets called e.g. from afpd.conf parsing code with a string like: */
-/* "default log_maxdebug /var/log/afpd.log" */
-void setuplog(const char *logstr);
-
-/* This gets called e.g. from afpd.conf parsing code with a string like: */
-/* "default dummyname" */
-void unsetuplog(const char *logstr);
-
-/* finish up and close the logs */
-void log_close(void);
-
-/* This function sets up the ProcessName */
+void setuplog(const char *loglevel, const char *logfile);
void set_processname(const char *processname);
/* LOG macro func no.1: log the message to file */
* We choose the verbose form in favor of the obfuscated ones, its easier
* to parse for human beings and facilitates expanding the macro for
* inline checks for debug levels.
- *
- * How to properly enclose multistatement macros:
- * http://en.wikipedia.org/wiki/C_macro#Multiple_statements
*/
#define LOG_MAX log_info
* get back the corresponding option. not all of these are implemented. */
#define UAM_PASSWD_FILENAME (1 << 0)
#define UAM_PASSWD_MINLENGTH (1 << 1)
-#define UAM_PASSWD_MAXFAIL (1 << 2) /* not implemented yet. */
#define UAM_PASSWD_EXPIRETIME (1 << 3) /* not implemented yet. */
/* max lenght of username */
#include <atalk/ldapconfig.h>
#include <atalk/logger.h>
+#include <atalk/iniparser.h>
-#define LINESIZE 1024
-
-/* Parse one line. Return result in pref and val */
-static int getpref(char *buf, char **R_pref, char **R_val)
-{
- char *p, *pref, *val;
-
- /* a little pre-processing to get rid of spaces and end-of-lines */
- p = buf;
- while (p && isspace(*p))
- p++;
- if (!p || (*p == '\0'))
- return -1;
-
- if ((val = strchr(p, '=')) == NULL)
- return -1;
- while ((*val == '=') || (*val == ' '))
- val++;
- if ((val = strtok(val, " \n")) == NULL)
- return -1;
- if ((val = strdup(val)) == NULL)
- return -1;
- if ((pref = strtok(p, " =")) == NULL)
- return -1;
-
- *R_pref = pref;
- *R_val = val;
- return 0;
-}
-
-/* Parse the afp_ldap.conf file */
-int acl_ldap_readconfig(char *name)
+int acl_ldap_readconfig(dictionary *iniconfig)
{
int i, j;
- FILE *f;
- char buf[LINESIZE];
- char *pref, *val;
+ char *val;
- f = fopen(name,"r");
- if (!f) {
- perror("fopen");
- return -1;
+ i = 0;
+ /* now see if its a correct pref */
+ for (i = 0; ldap_prefs[i].name != NULL; i++) {
+ if ((val = iniparser_getstring(ldap_prefs[i].name)) != NULL) {
+ /* ok, found a valid pref */
+
+ /* check if we have pre-defined values */
+ if (ldap_prefs[i].intfromarray == 0) {
+ /* no, its just a string */
+ ldap_prefs[i].valid = 0;
+ if (ldap_prefs[i].strorint)
+ /* store as int */
+ *((int *)(ldap_prefs[i].pref)) = atoi(val);
+ else
+ /* store string as string */
+ *((char **)(ldap_prefs[i].pref)) = val;
+ } else {
+ /* ok, we have string to int mapping for this pref
+ eg. "none", "simple", "sasl" map to 0, 128, 129 */
+ for (j = 0; prefs_array[j].pref != NULL; j++) {
+ if ((strcmp(prefs_array[j].pref, ldap_prefs[i].name) == 0)
+ && (strcmp(prefs_array[j].valuestring, val) == 0)) {
+ ldap_prefs[i].valid = 0;
+ *((int *)(ldap_prefs[i].pref)) = prefs_array[j].value;
+ break;
+ }
+ }
+ }
+ }
}
- while (!feof(f)) {
- /* read a line from file */
- if (!fgets(buf, LINESIZE, f) || buf[0] == '#')
- continue;
-
- /* parse and return pref and value */
- if ((getpref(buf, &pref, &val)) != 0)
- continue;
-
- i = 0;
- /* now see if its a correct pref */
- while(ldap_prefs[i].pref != NULL) {
- if ((strcmp(ldap_prefs[i].name, pref)) == 0) {
- /* ok, found a valid pref */
-
- /* check if we have pre-defined values */
- if (0 == ldap_prefs[i].intfromarray) {
- /* no, its just a string */
- ldap_prefs[i].valid = 0;
- if (0 == ldap_prefs[i].strorint)
- /* store string as string */
- *((char **)(ldap_prefs[i].pref)) = val;
- else
- /* store as int */
- *((int *)(ldap_prefs[i].pref)) = atoi(val);
- } else {
- /* ok, we have string to int mapping for this pref
- eg. "none", "simple", "sasl" map to 0, 128, 129 */
- j = 0;
- while(prefs_array[j].pref != NULL) {
- if (((strcmp(prefs_array[j].pref, pref)) == 0) &&
- ((strcmp(prefs_array[j].valuestring, val)) == 0)) {
- ldap_prefs[i].valid = 0;
- *((int *)(ldap_prefs[i].pref)) = prefs_array[j].value;
- }
- j++;
- } /* while j*/
- } /* if else 0 == ldap_prefs*/
- break;
- } /* if strcmp */
- i++;
- } /* while i */
- if (ldap_prefs[i].pref == NULL)
- LOG(log_error, logtype_afpd,"afp_ldap.conf: Unknown option: \"%s\"", pref);
- } /* EOF */
-
/* check if the config is sane and complete */
i = 0;
ldap_config_valid = 1;
static void dsi_init_buffer(DSI *dsi)
{
- size_t quantum = dsi->server_quantum ? dsi->server_quantum : DSI_SERVQUANT_DEF;
-
/* default is 12 * 300k = 3,6 MB (Apr 2011) */
- if ((dsi->buffer = malloc(dsi->dsireadbuf * quantum)) == NULL) {
+ if ((dsi->buffer = malloc(dsi->dsireadbuf * dsi->server_quantum)) == NULL) {
LOG(log_error, logtype_dsi, "dsi_init_buffer: OOM");
AFP_PANIC("OOM in dsi_init_buffer");
}
dsi->start = dsi->buffer;
dsi->eof = dsi->buffer;
- dsi->end = dsi->buffer + (dsi->dsireadbuf * quantum);
+ dsi->end = dsi->buffer + (dsi->dsireadbuf * dsi->server_quantum);
}
/* OpenSession. set up the connection */
/*---------------------------------------------------------------------------
Includes
---------------------------------------------------------------------------*/
-#include "dictionary.h"
+#include <atalk/dictionary.h>
+#include <atalk/compat.h>
#include <stdio.h>
#include <stdlib.h>
Private functions
---------------------------------------------------------------------------*/
+#define MAXKEYSIZE 1024
+static char *makekey(const char *section, const char *entry)
+{
+ static char buf[MAXKEYSIZE];
+
+ strlcpy(buf, section, MAXKEYSIZE);
+ if (entry) {
+ strlcat(buf, ":", MAXKEYSIZE);
+ strlcat(buf, entry, MAXKEYSIZE);
+ }
+
+ return buf;
+}
+
/* Doubles the allocated size associated to a pointer */
/* 'size' is the current allocated size. */
static void * mem_double(void * ptr, int size)
dictionary object, you should not try to free it or modify it.
*/
/*--------------------------------------------------------------------------*/
-char * dictionary_get(dictionary * d, char * key, char * def)
+char * dictionary_get(dictionary * d, char *section, char * key, char * def)
{
unsigned hash ;
int i ;
- hash = dictionary_hash(key);
+ hash = dictionary_hash(makekey(section, key));
for (i=0 ; i<d->size ; i++) {
if (d->key[i]==NULL)
continue ;
/* Compare hash */
if (hash==d->hash[i]) {
/* Compare string, to avoid hash collisions */
- if (!strcmp(key, d->key[i])) {
+ if (!strcmp(makekey(section, key), d->key[i])) {
return d->val[i] ;
}
}
This function returns non-zero in case of failure.
*/
/*--------------------------------------------------------------------------*/
-int dictionary_set(dictionary * d, char * key, char * val)
+int dictionary_set(dictionary * d, char *section, char * key, char * val)
{
int i ;
unsigned hash ;
if (d==NULL || key==NULL) return -1 ;
/* Compute hash for this key */
- hash = dictionary_hash(key) ;
+ hash = dictionary_hash(makekey(section, key));
/* Find if value is already in dictionary */
if (d->n>0) {
for (i=0 ; i<d->size ; i++) {
if (d->key[i]==NULL)
continue ;
if (hash==d->hash[i]) { /* Same hash value */
- if (!strcmp(key, d->key[i])) { /* Same key */
+ if (!strcmp(makekey(section, key), d->key[i])) { /* Same key */
/* Found a value: modify and return */
if (d->val[i]!=NULL)
free(d->val[i]);
}
}
/* Copy key */
- d->key[i] = xstrdup(key);
+ d->key[i] = xstrdup(makekey(section, key));
d->val[i] = val ? xstrdup(val) : NULL ;
d->hash[i] = hash;
d->n ++ ;
key cannot be found.
*/
/*--------------------------------------------------------------------------*/
-void dictionary_unset(dictionary * d, char * key)
+void dictionary_unset(dictionary * d, char *section, char * key)
{
unsigned hash ;
int i ;
return;
}
- hash = dictionary_hash(key);
+ hash = dictionary_hash(makekey(section, key));
for (i=0 ; i<d->size ; i++) {
if (d->key[i]==NULL)
continue ;
/* Compare hash */
if (hash==d->hash[i]) {
/* Compare string, to avoid hash collisions */
- if (!strcmp(key, d->key[i])) {
+ if (!strcmp(makekey(section, key), d->key[i])) {
/* Found key */
break ;
}
}
return ;
}
-
-
-/* Test code */
-#ifdef TESTDIC
-#define NVALS 20000
-int main(int argc, char *argv[])
-{
- dictionary * d ;
- char * val ;
- int i ;
- char cval[90] ;
-
- /* Allocate dictionary */
- printf("allocating...\n");
- d = dictionary_new(0);
-
- /* Set values in dictionary */
- printf("setting %d values...\n", NVALS);
- for (i=0 ; i<NVALS ; i++) {
- sprintf(cval, "%04d", i);
- dictionary_set(d, cval, "salut");
- }
- printf("getting %d values...\n", NVALS);
- for (i=0 ; i<NVALS ; i++) {
- sprintf(cval, "%04d", i);
- val = dictionary_get(d, cval, DICT_INVALID_KEY);
- if (val==DICT_INVALID_KEY) {
- printf("cannot get value for key [%s]\n", cval);
- }
- }
- printf("unsetting %d values...\n", NVALS);
- for (i=0 ; i<NVALS ; i++) {
- sprintf(cval, "%04d", i);
- dictionary_unset(d, cval);
- }
- if (d->n != 0) {
- printf("error deleting values\n");
- }
- printf("deallocating...\n");
- dictionary_del(d);
- return 0 ;
-}
-#endif
-/* vim: set ts=4 et sw=4 tw=75 */
LINE_VALUE
} line_status ;
-/*-------------------------------------------------------------------------*/
-/**
- @brief Convert a string to lowercase.
- @param s String to convert.
- @return ptr to statically allocated string.
-
- This function returns a pointer to a statically allocated string
- containing a lowercased version of the input string. Do not free
- or modify the returned string! Since the returned string is statically
- allocated, it will be modified at each function call (not re-entrant).
- */
-/*--------------------------------------------------------------------------*/
-static char * strlwc(char * s)
-{
- return s;
-
- static char l[ASCIILINESZ+1];
- int i ;
-
- if (s==NULL) return NULL ;
- memset(l, 0, ASCIILINESZ+1);
- i=0 ;
- while (s[i] && i<ASCIILINESZ) {
- l[i] = (char)tolower((int)s[i]);
- i++ ;
- }
- l[ASCIILINESZ]=(char)0;
- return l ;
-}
-
/*-------------------------------------------------------------------------*/
/**
@brief Remove blanks at the beginning and the end of a string.
/**
@brief Get the string associated to a key
@param d Dictionary to search
+ @param section Section to search
@param key Key string to look for
@param def Default value to return if key not found.
@return pointer to statically allocated character string
the dictionary, do not free or modify it.
*/
/*--------------------------------------------------------------------------*/
-char * iniparser_getstring(dictionary * d, char * key, char * def)
+char * iniparser_getstring(dictionary * d, char *section, char * key, char * def)
{
- char * lc_key ;
char * sval ;
if (d==NULL || key==NULL)
return def ;
- lc_key = strlwc(key);
- sval = dictionary_get(d, lc_key, def);
+ sval = dictionary_get(d, section, key, def);
return sval ;
}
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Get the string associated to a key
+ @param d Dictionary to search
+ @param section Section to search
+ @param key Key string to look for
+ @param def Default value to return if key not found.
+ @return pointer to statically allocated character string
+
+ This function queries a dictionary for a key. A key as read from an
+ ini file is given as "section:key". If the key cannot be found,
+ the pointer passed as 'def' is returned.
+ The returned char pointer a strdup'ed allocated string, so the caller must free it.
+ */
+/*--------------------------------------------------------------------------*/
+char * iniparser_getstringdup(dictionary * d, char *section, char * key, char * def)
+{
+ char * sval ;
+
+ if (d==NULL || key==NULL)
+ return def ;
+
+ if ((sval = dictionary_get(d, section, key, def)))
+ return strdup(sval);
+ return NULL;
+}
+
/*-------------------------------------------------------------------------*/
/**
@brief Get the string associated to a key, convert to an int
- @param d Dictionary to search
- @param key Key string to look for
+ @param d Dictionary to search
+ @param section Section to search
+ @param key Key string to look for
@param notfound Value to return in case of error
@return integer
Credits: Thanks to A. Becker for suggesting strtol()
*/
/*--------------------------------------------------------------------------*/
-int iniparser_getint(dictionary * d, char * key, int notfound)
+int iniparser_getint(dictionary * d, char *section, char * key, int notfound)
{
char * str ;
- str = iniparser_getstring(d, key, INI_INVALID_KEY);
+ str = iniparser_getstring(d, section, key, INI_INVALID_KEY);
if (str==INI_INVALID_KEY) return notfound ;
return (int)strtol(str, NULL, 0);
}
/*-------------------------------------------------------------------------*/
/**
@brief Get the string associated to a key, convert to a double
- @param d Dictionary to search
- @param key Key string to look for
+ @param d Dictionary to search
+ @param section Section to search
+ @param key Key string to look for
@param notfound Value to return in case of error
@return double
the notfound value is returned.
*/
/*--------------------------------------------------------------------------*/
-double iniparser_getdouble(dictionary * d, char * key, double notfound)
+double iniparser_getdouble(dictionary * d, char *section, char * key, double notfound)
{
char * str ;
- str = iniparser_getstring(d, key, INI_INVALID_KEY);
+ str = iniparser_getstring(d, section, key, INI_INVALID_KEY);
if (str==INI_INVALID_KEY) return notfound ;
return atof(str);
}
/*-------------------------------------------------------------------------*/
/**
@brief Get the string associated to a key, convert to a boolean
- @param d Dictionary to search
- @param key Key string to look for
+ @param d Dictionary to search
+ @param section Section to search
+ @param key Key string to look for
@param notfound Value to return in case of error
@return integer
necessarily have to be 0 or 1.
*/
/*--------------------------------------------------------------------------*/
-int iniparser_getboolean(dictionary * d, char * key, int notfound)
+int iniparser_getboolean(dictionary * d, char *section, char * key, int notfound)
{
char * c ;
int ret ;
- c = iniparser_getstring(d, key, INI_INVALID_KEY);
+ c = iniparser_getstring(d, section, key, INI_INVALID_KEY);
if (c==INI_INVALID_KEY) return notfound ;
if (c[0]=='y' || c[0]=='Y' || c[0]=='1' || c[0]=='t' || c[0]=='T') {
ret = 1 ;
of querying for the presence of sections in a dictionary.
*/
/*--------------------------------------------------------------------------*/
-int iniparser_find_entry(
- dictionary * ini,
- char * entry
-)
+int iniparser_find_entry(dictionary *ini, char *entry)
{
int found=0 ;
- if (iniparser_getstring(ini, entry, INI_INVALID_KEY)!=INI_INVALID_KEY) {
+ if (iniparser_getstring(ini, entry, NULL, INI_INVALID_KEY)!=INI_INVALID_KEY) {
found = 1 ;
}
return found ;
/**
@brief Set an entry in a dictionary.
@param ini Dictionary to modify.
- @param entry Entry to modify (entry name)
+ @param section Entry to modify (entry section)
+ @param key Entry to modify (entry key)
@param val New value to associate to the entry.
@return int 0 if Ok, -1 otherwise.
It is Ok to set val to NULL.
*/
/*--------------------------------------------------------------------------*/
-int iniparser_set(dictionary * ini, char * entry, char * val)
+int iniparser_set(dictionary * ini, char *section, char * key, char * val)
{
- return dictionary_set(ini, strlwc(entry), val) ;
+ return dictionary_set(ini, section, key, val) ;
}
/*-------------------------------------------------------------------------*/
/**
@brief Delete an entry in a dictionary
@param ini Dictionary to modify
- @param entry Entry to delete (entry name)
+ @param section Entry to delete (entry section)
+ @param key Entry to delete (entry key)
@return void
If the given entry can be found, it is deleted from the dictionary.
*/
/*--------------------------------------------------------------------------*/
-void iniparser_unset(dictionary * ini, char * entry)
+void iniparser_unset(dictionary * ini, char *section, char * key)
{
- dictionary_unset(ini, strlwc(entry));
+ dictionary_unset(ini, section, key);
}
/*-------------------------------------------------------------------------*/
/* Section name */
sscanf(line, "[%[^]]", section);
strcpy(section, strstrip(section));
- strcpy(section, strlwc(section));
+ strcpy(section, section);
sta = LINE_SECTION ;
} else if (sscanf (line, "%[^=] = \"%[^\"]\"", key, value) == 2
|| sscanf (line, "%[^=] = '%[^\']'", key, value) == 2
|| sscanf (line, "%[^=] = %[^;#]", key, value) == 2) {
/* Usual key=value, with or without comments */
strcpy(key, strstrip(key));
- strcpy(key, strlwc(key));
+ strcpy(key, key);
strcpy(value, strstrip(value));
/*
* sscanf cannot handle '' or "" as empty values
* key=#
*/
strcpy(key, strstrip(key));
- strcpy(key, strlwc(key));
+ strcpy(key, key);
value[0]=0 ;
sta = LINE_VALUE ;
} else {
break ;
case LINE_SECTION:
- errs = dictionary_set(dict, section, NULL);
+ errs = dictionary_set(dict, section, NULL, NULL);
break ;
case LINE_VALUE:
- sprintf(tmp, "%s:%s", section, key);
- errs = dictionary_set(dict, tmp, val) ;
+ errs = dictionary_set(dict, section, key, val) ;
break ;
case LINE_ERROR:
dictionary_del(d);
}
-/* vim: set ts=4 et sw=4 tw=75 */
return hash;
}
-/*
- * If filename == NULL its for syslog logging, otherwise its for file-logging.
- * "unsetuplog" calls with loglevel == NULL.
- * loglevel == NULL means:
- * if logtype == default
- * disable logging
- * else
- * set to default logging
- */
-static void setuplog_internal(const char *loglevel, const char *logtype, const char *filename)
-{
- unsigned int typenum, levelnum;
-
- /* Parse logtype */
- for( typenum=0; typenum < num_logtype_strings; typenum++) {
- if (strcasecmp(logtype, arr_logtype_strings[typenum]) == 0)
- break;
- }
- if (typenum >= num_logtype_strings) {
- return;
- }
-
- /* Parse loglevel */
- if (loglevel == NULL) {
- levelnum = 0;
- } else {
- for(levelnum=1; levelnum < num_loglevel_strings; levelnum++) {
- if (strcasecmp(loglevel, arr_loglevel_strings[levelnum]) == 0)
- break;
- }
- if (levelnum >= num_loglevel_strings) {
- return;
- }
- }
-
- /* is this a syslog setup or a filelog setup ? */
- if (filename == NULL) {
- /* must be syslog */
- syslog_setup(levelnum,
- typenum,
- logoption_ndelay | logoption_pid,
- logfacility_daemon);
- } else {
- /* this must be a filelog */
- log_setup(filename, levelnum, typenum);
- }
-
- return;
-}
-
static void generate_message_details(char *message_details_buffer,
int message_details_buffer_length,
int display_options,
}
}
-/* =========================================================================
- Global function definitions
- ========================================================================= */
+/* Called by the LOG macro for syslog messages */
+static void make_syslog_entry(enum loglevels loglevel, enum logtypes logtype _U_, char *message)
+{
+ if ( !log_config.syslog_opened ) {
+ openlog(log_config.processname,
+ log_config.syslog_display_options,
+ log_config.syslog_facility);
+ log_config.syslog_opened = true;
+ }
+
+ syslog(get_syslog_equivalent(loglevel), "%s", message);
+}
-void log_init(void)
+static void log_init(void)
{
syslog_setup(log_info,
logtype_default,
logfacility_daemon);
}
-void log_setup(const char *filename, enum loglevels loglevel, enum logtypes logtype)
+static void log_setup(const char *filename, enum loglevels loglevel, enum logtypes logtype)
{
uid_t process_uid;
}
/* Setup syslog logging */
-void syslog_setup(int loglevel, enum logtypes logtype, int display_options, int facility)
+static void syslog_setup(int loglevel, enum logtypes logtype, int display_options, int facility)
{
/*
* FIXME:
arr_loglevel_strings[loglevel]);
}
-void log_close(void)
+/*
+ * If filename == NULL its for syslog logging, otherwise its for file-logging.
+ * "unsetuplog" calls with loglevel == NULL.
+ * loglevel == NULL means:
+ * if logtype == default
+ * disable logging
+ * else
+ * set to default logging
+ */
+static void setuplog_internal(const char *loglevel, const char *logtype, const char *filename)
{
+ unsigned int typenum, levelnum;
+
+ /* Parse logtype */
+ for( typenum=0; typenum < num_logtype_strings; typenum++) {
+ if (strcasecmp(logtype, arr_logtype_strings[typenum]) == 0)
+ break;
+ }
+ if (typenum >= num_logtype_strings) {
+ return;
+ }
+
+ /* Parse loglevel */
+ if (loglevel == NULL) {
+ levelnum = 0;
+ } else {
+ for(levelnum=1; levelnum < num_loglevel_strings; levelnum++) {
+ if (strcasecmp(loglevel, arr_loglevel_strings[levelnum]) == 0)
+ break;
+ }
+ if (levelnum >= num_loglevel_strings) {
+ return;
+ }
+ }
+
+ /* is this a syslog setup or a filelog setup ? */
+ if (filename == NULL) {
+ /* must be syslog */
+ syslog_setup(levelnum,
+ typenum,
+ logoption_ndelay | logoption_pid,
+ logfacility_daemon);
+ } else {
+ /* this must be a filelog */
+ log_setup(filename, levelnum, typenum);
+ }
+
+ return;
}
+/* =========================================================================
+ Global function definitions
+ ========================================================================= */
+
/* This function sets up the processname */
void set_processname(const char *processname)
{
log_config.processname[15] = 0;
}
-/* Called by the LOG macro for syslog messages */
-static void make_syslog_entry(enum loglevels loglevel, enum logtypes logtype _U_, char *message)
-{
- if ( !log_config.syslog_opened ) {
- openlog(log_config.processname,
- log_config.syslog_display_options,
- log_config.syslog_facility);
- log_config.syslog_opened = true;
- }
-
- syslog(get_syslog_equivalent(loglevel), "%s", message);
-}
-
/* -------------------------------------------------------------------------
make_log_entry has 1 main flaws:
The message in its entirity, must fit into the tempbuffer.
inlog = 0;
}
-
-void setuplog(const char *logstr)
+void setuplog(const char *logstr, const char *logfile)
{
- char *ptr, *ptrbak, *logtype, *loglevel = NULL, *filename = NULL;
- ptr = strdup(logstr);
- ptrbak = ptr;
+ char *ptr, *save;
+ char *logtype, *loglevel;
+ char c;
- /* logtype */
- logtype = ptr;
+ save = ptr = strdup(logstr);
- /* get loglevel */
- ptr = strpbrk(ptr, " \t");
- if (ptr) {
- *ptr++ = 0;
+ while (*ptr) {
while (*ptr && isspace(*ptr))
ptr++;
- loglevel = ptr;
- /* get filename */
- ptr = strpbrk(ptr, " \t");
- if (ptr) {
- *ptr++ = 0;
- while (*ptr && isspace(*ptr))
- ptr++;
- }
- filename = ptr;
- if (filename && *filename == 0)
- filename = NULL;
- }
+ logtype = ptr;
+ ptr = strpbrk(ptr, ":");
+ if (!ptr)
+ break;
+ *ptr = 0;
- /* finally call setuplog, filename can be NULL */
- setuplog_internal(loglevel, logtype, filename);
+ ptr++;
+ loglevel = ptr;
+ while (*ptr && !isspace(*ptr))
+ ptr++;
+ c = *ptr;
+ *ptr = 0;
+ setuplog_internal(loglevel, logtype, filename);
+ *ptr = c;
+ }
- free(ptrbak);
+ free(save);
}
-void unsetuplog(const char *logstr)
-{
- char *str, *logtype, *filename;
-
- str = strdup(logstr);
-
- /* logtype */
- logtype = str;
-
- /* get filename, can be NULL */
- strtok(str, " \t");
- filename = strtok(NULL, " \t");
-
- /* finally call setuplog, filename can be NULL */
- setuplog_internal(NULL, str, filename);
-
- free(str);
-}
+++ /dev/null
-dnl Check for optional server location protocol support (used by MacOS X)
-
-AC_DEFUN([AC_NETATALK_SRVLOC], [
-
- SLP_LIBS=""
- SLP_CFLAGS=""
- found_slp=no
- srvlocdir=""
-
- AC_ARG_ENABLE(srvloc,
- [ --enable-srvloc[[=DIR]] enable Server Location Protocol (SLP) support],
- [srvloc=$enableval],
- [srvloc=no]
- )
-
- dnl make sure atalk_libname is defined beforehand
- [[ -n "$atalk_libname" ]] || AC_MSG_ERROR([internal error, atalk_libname undefined])
-
- if test "x$srvloc" != "xno"; then
-
- savedcppflags="$CPPFLAGS"
- savedldflags="$LDFLAGS"
- if test "x$srvloc" = "xyes" ; then
- srvlocdir="/usr"
- else
- srvlocdir="$srvloc"
- fi
- CPPFLAGS="$CPPFLAGS -I$srvlocdir/include"
- LDFLAGS="$LDFLAGS -L$srvlocdir/$atalk_libname"
-
- AC_MSG_CHECKING([for slp.h])
- AC_TRY_CPP([#include <slp.h>],
- [
- AC_MSG_RESULT([yes])
- found_slp=yes
- ],
- [
- AC_MSG_RESULT([no])
- ]
- )
-
- if test "x$found_slp" = "xyes"; then
- AC_CHECK_LIB(slp, SLPOpen, [
- SLP_LIBS="-L$srvlocdir/$atalk_libname -lslp"
- SLP_CFLAGS="-I$srvlocdir/include"
- ],[
- AC_MSG_RESULT([no])
- found_slp=no
- ])
- fi
-
- CPPFLAGS="$savedcppflags"
- LDFLAGS="$savedldflags"
- fi
-
- netatalk_cv_srvloc=no
- AC_MSG_CHECKING([whether to enable srvloc (SLP) support])
- if test "x$found_slp" = "xyes"; then
- AC_MSG_RESULT([yes])
- AC_DEFINE(USE_SRVLOC, 1, [Define to enable SLP support])
- netatalk_cv_srvloc=yes
- else
- AC_MSG_RESULT([no])
- if test "x$srvloc" != "xno" -a "x$srvloc" != "xyes"; then
- AC_MSG_ERROR([SLP installation not found])
- fi
- fi
-
-
-
- LIB_REMOVE_USR_LIB(SLP_LIBS)
- CFLAGS_REMOVE_USR_INCLUDE(SLP_CFLAGS)
- AC_SUBST(SLP_LIBS)
- AC_SUBST(SLP_CFLAGS)
-])