From: Frank Lahm Date: Sat, 5 May 2012 06:20:14 +0000 (+0200) Subject: Merge 2-2 X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a83e8197c7b8af45f8d56acf158920c03698bfc6;hp=-c;p=netatalk.git Merge 2-2 --- a83e8197c7b8af45f8d56acf158920c03698bfc6 diff --combined etc/afpd/afp_config.c index ed806704,29b552d3..a61fe102 --- a/etc/afpd/afp_config.c +++ b/etc/afpd/afp_config.c @@@ -18,132 -18,576 +18,129 @@@ #include #include -#ifdef USE_SRVLOC -#include -#endif /* USE_SRVLOC */ - #include #include #include -#include -#include -#include #include #include #include +#include +#include +#include +#include #ifdef HAVE_LDAP #include #endif -#include #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 ... */ -void configfree(AFPConfig *configs, const AFPConfig *config) +/*! + * Free and cleanup all linked DSI objects from config + * + * Preserve object pointed to by "dsi". + * "dsi" can be NULL in which case all DSI objects _and_ the options object are freed + */ +void configfree(AFPObj *obj, DSI *dsi) { - AFPConfig *p, *q; + DSI *p, *q; - for (p = configs; p; p = q) { + /* the master loaded the volumes for zeroconf, get rid of that */ + unload_volumes(obj); + + for (p = obj->dsi; p; p = q) { q = p->next; - if (p == config) + if (p == dsi) continue; - - /* do a little reference counting */ - if (--(*p->optcount) < 1) { - afp_options_free(&p->obj.options, p->defoptions); - free(p->optcount); - } - - switch (p->obj.proto) { -#ifndef NO_DDP - case AFPPROTO_ASP: - free(p->obj.Obj); - free(p->obj.Type); - free(p->obj.Zone); - atp_close(((ASP) p->obj.handle)->asp_atp); - free(p->obj.handle); - break; -#endif /* no afp/asp */ - case AFPPROTO_DSI: - close(p->fd); - free(p->obj.handle); - break; - } + close(p->socket); free(p); } + - /* the master loaded the volumes for zeroconf, get rid of that */ - 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; -#ifndef NO_DDP - char *Obj, *Type = "", *Zone = ""; -#endif - - /* 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'; - -#ifndef NO_DDP - /* Add ZONE, */ - if (nbp_name(options->server, &Obj, &Type, &Zone )) { - LOG(log_error, logtype_afpd, "srvloc_encode: can't parse %s", options->server ); - } - else { - snprintf( buf+i, sizeof(buf)-i-1 ,"&ZONE=%s", Zone); - } -#endif - 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 */ -} - -#ifndef NO_DDP -static void asp_cleanup(const AFPConfig *config) -{ - /* we need to stop tickle handler */ - asp_stop_tickle(); - nbp_unrgstr(config->obj.Obj, config->obj.Type, config->obj.Zone, - &config->obj.options.ddpaddr); -} - -/* these two are almost identical. it should be possible to collapse them - * into one with minimal junk. */ -static int asp_start(AFPConfig *config, AFPConfig *configs, - server_child *server_children) -{ - ASP asp; - - if (!(asp = asp_getsession(config->obj.handle, server_children, - config->obj.options.tickleval))) { - LOG(log_error, logtype_afpd, "main: asp_getsession: %s", strerror(errno) ); - exit( EXITERR_CLNT ); - } - - if (asp->child) { - configfree(configs, config); /* free a bunch of stuff */ - afp_over_asp(&config->obj); - exit (0); - } - - return 0; -} -#endif /* no afp/asp */ - -static afp_child_t *dsi_start(AFPConfig *config, AFPConfig *configs, - server_child *server_children) -{ - DSI *dsi = config->obj.handle; - afp_child_t *child = NULL; - - if (!(child = dsi_getsession(dsi, - server_children, - config->obj.options.tickleval))) { - /* we've forked. */ - configfree(configs, config); - afp_over_dsi(&config->obj); /* start a session */ - exit (0); - } - - return child; -} - -#ifndef NO_DDP -static AFPConfig *ASPConfigInit(const struct afp_options *options, - unsigned char *refcount) -{ - AFPConfig *config; - ATP atp; - ASP asp; - char *Obj, *Type = "AFPServer", *Zone = "*"; - char *convname = NULL; - - if ((config = (AFPConfig *) calloc(1, sizeof(AFPConfig))) == NULL) - return NULL; - - if ((atp = atp_open(ATADDR_ANYPORT, &options->ddpaddr)) == NULL) { - LOG(log_error, logtype_afpd, "main: atp_open: %s", strerror(errno) ); - free(config); - return NULL; - } - - if ((asp = asp_init( atp )) == NULL) { - LOG(log_error, logtype_afpd, "main: asp_init: %s", strerror(errno) ); - atp_close(atp); - free(config); - return NULL; - } - - /* register asp server */ - Obj = (char *) options->hostname; - if (options->server && (size_t)-1 ==(convert_string_allocate( options->unixcharset, options->maccharset, - options->server, strlen(options->server), &convname)) ) { - if ((convname = strdup(options->server)) == NULL ) { - LOG(log_error, logtype_afpd, "malloc: %s", strerror(errno) ); - goto serv_free_return; - } - } - - if (nbp_name(convname, &Obj, &Type, &Zone )) { - LOG(log_error, logtype_afpd, "main: can't parse %s", options->server ); - goto serv_free_return; - } - if (convname) - free (convname); - - /* dup Obj, Type and Zone as they get assigned to a single internal - * buffer by nbp_name */ - if ((config->obj.Obj = strdup(Obj)) == NULL) - goto serv_free_return; - - if ((config->obj.Type = strdup(Type)) == NULL) { - free(config->obj.Obj); - goto serv_free_return; - } - - if ((config->obj.Zone = strdup(Zone)) == NULL) { - free(config->obj.Obj); - free(config->obj.Type); - goto serv_free_return; - } - - /* make sure we're not registered */ - nbp_unrgstr(Obj, Type, Zone, &options->ddpaddr); - if (nbp_rgstr( atp_sockaddr( atp ), Obj, Type, Zone ) < 0 ) { - LOG(log_error, logtype_afpd, "Can't register %s:%s@%s", Obj, Type, Zone ); - free(config->obj.Obj); - free(config->obj.Type); - free(config->obj.Zone); - goto serv_free_return; - } - - LOG(log_info, logtype_afpd, "%s:%s@%s started on %u.%u:%u (%s)", Obj, Type, Zone, - ntohs( atp_sockaddr( atp )->sat_addr.s_net ), - atp_sockaddr( atp )->sat_addr.s_node, - atp_sockaddr( atp )->sat_port, VERSION ); - - config->fd = atp_fileno(atp); - config->obj.handle = asp; - config->obj.config = config; - config->obj.proto = AFPPROTO_ASP; - - memcpy(&config->obj.options, options, sizeof(struct afp_options)); - config->optcount = refcount; - (*refcount)++; - - config->server_start = asp_start; - config->server_cleanup = asp_cleanup; - - return config; - -serv_free_return: - asp_close(asp); - free(config); - return NULL; -} -#endif /* no afp/asp */ - - -static AFPConfig *DSIConfigInit(const struct afp_options *options, - unsigned char *refcount, - const dsi_proto protocol) -{ - AFPConfig *config; - DSI *dsi; - char *p, *q; - - if ((config = (AFPConfig *) calloc(1, sizeof(AFPConfig))) == NULL) { - LOG(log_error, logtype_afpd, "DSIConfigInit: malloc(config): %s", strerror(errno) ); - return NULL; - } - - LOG(log_debug, logtype_afpd, "DSIConfigInit: hostname: %s, ip/port: %s/%s, ", - options->hostname, - options->ipaddr ? options->ipaddr : "default", - options->port ? options->port : "548"); - - if ((dsi = dsi_init(protocol, "afpd", options->hostname, - options->ipaddr, options->port, - options->flags & OPTION_PROXY, - 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); + if (dsi) { + dsi->next = NULL; + obj->dsi = dsi; } 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); + afp_options_free(&obj->options); } - -#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; - dsi->AFPobj = &config->obj; - config->obj.config = config; - config->obj.proto = AFPPROTO_DSI; - - memcpy(&config->obj.options, options, sizeof(struct afp_options)); - /* get rid of any appletalk info. we use the fact that the DSI - * stuff is done after the ASP stuff. */ - p = config->obj.options.server; - if (p && (q = strchr(p, ':'))) - *q = '\0'; - - config->optcount = refcount; - (*refcount)++; -- - config->server_start = dsi_start; - return config; } -/* allocate server configurations. this should really store the last - * entry in config->last or something like that. that would make - * supporting multiple dsi transports easier. */ -static AFPConfig *AFPConfigInit(struct afp_options *options, - const struct afp_options *defoptions) +/*! + * Get everything running + */ +int configinit(AFPObj *obj) { - AFPConfig *config = NULL, *next = NULL; - unsigned char *refcount; - - if ((refcount = (unsigned char *) - calloc(1, sizeof(unsigned char))) == NULL) { - LOG(log_error, logtype_afpd, "AFPConfigInit: calloc(refcount): %s", strerror(errno) ); - return NULL; - } - -#ifndef NO_DDP - /* handle asp transports */ - if ((options->transports & AFPTRANS_DDP) && - (config = ASPConfigInit(options, refcount))) - config->defoptions = defoptions; -#endif /* NO_DDP */ - - - /* set signature */ - set_signature(options); + EC_INIT; + DSI *dsi, **next = &obj->dsi; + char *p = NULL, *q = NULL, *savep; + const char *r; - /* handle dsi transports and dsi proxies. we only proxy - * for DSI connections. */ + auth_load(obj->options.uampath, obj->options.uamlist); + set_signature(&obj->options); - /* 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) || - ((options->flags & OPTION_PROXY) && config)) - && (next = DSIConfigInit(options, refcount, DSI_TCPIP))) - next->defoptions = defoptions; + LOG(log_debug, logtype_afpd, "DSIConfigInit: hostname: %s, listen: %s, port: %s", + obj->options.hostname, + obj->options.listen ? obj->options.listen : "(default: hostname)", + obj->options.port); - /* 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); + /* obj->options->listen is of the from "IP[:port][,IP:[PORT], ...]" */ + /* obj->options->port is the default port to listen (548) */ - /* this should be able to accept multiple dsi transports. i think - * the only thing that gets affected is the net addresses. */ - status_init(config, next, options); - - /* attach dsi config to tail of asp config */ - if (config) { - config->next = next; - return config; + if (obj->options.listen) { + EC_NULL( q = p = strdup(obj->options.listen) ); + EC_NULL( p = strtok_r(p, ", ", &savep) ); } - return next; -} - -/* fill in the appropriate bits for each interface */ -AFPConfig *configinit(struct afp_options *cmdline) -{ - 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); - } - - /* 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; + while (1) { + if ((dsi = dsi_init(obj, obj->options.hostname, p, obj->options.port)) == NULL) + break; - have_option = 1; + status_init(obj, dsi); + *next = dsi; + next = &dsi->next; ++ dsi->AFPobj = obj; - memcpy(&options, cmdline, sizeof(options)); - if (!afp_options_parseline(p, &options)) - continue; + LOG(log_note, logtype_afpd, "Netatalk AFP/TCP listening on %s:%d", + getip_string((struct sockaddr *)&dsi->server), + getip_port((struct sockaddr *)&dsi->server)); - /* 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; - } + if (p) + /* p is NULL if ! obj->options.listen */ + p = strtok_r(NULL, ", ", &savep); + if (!p) + break; } - if (obj->dsi == NULL) - EC_FAIL; - #ifdef HAVE_LDAP - /* Parse afp_ldap.conf */ - acl_ldap_readconfig(_PATH_ACL_LDAPCONF); + /* Parse afp.conf */ + acl_ldap_readconfig(obj->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 && !(first->obj.options.flags & OPTION_NOZEROCONF)) { - load_volumes(&first->obj); - zeroconf_register(first); + if (! (obj->options.flags & OPTION_NOZEROCONF)) { + load_volumes(obj, NULL); + zeroconf_register(obj); + } + + if ((r = iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, "fce listener", NULL))) { + LOG(log_note, logtype_afpd, "Adding FCE listener: %s", r); + fce_add_udp_socket(r); + } + if ((r = iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, "fce coalesce", NULL))) { + LOG(log_note, logtype_afpd, "Fce coalesce: %s", r); + fce_set_coalesce(r); + } + if ((r = iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, "fce events", NULL))) { + LOG(log_note, logtype_afpd, "Fce events: %s", r); + fce_set_events(r); } - - return first; +EC_CLEANUP: + if (q) + free(q); + EC_EXIT; } diff --combined etc/afpd/afp_dsi.c index f1e37167,bf454e15..58c37009 --- a/etc/afpd/afp_dsi.c +++ b/etc/afpd/afp_dsi.c @@@ -37,14 -37,18 +37,14 @@@ #include #include #include - #include +#include + #include "switch.h" #include "auth.h" #include "fork.h" #include "dircache.h" -#ifdef FORCE_UIDGID -#warning UIDGID -#include "uid.h" -#endif /* FORCE_UIDGID */ - #ifndef SOL_TCP #define SOL_TCP IPPROTO_TCP #endif @@@ -75,7 -79,7 +75,7 @@@ static rc_elem_t replaycache[REPLAYCACH 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; @@@ -92,7 -96,7 +92,7 @@@ } } - close_all_vol(); + close_all_vol(obj); if (obj->logout) (*obj->logout)(); @@@ -109,7 -113,7 +109,7 @@@ */ 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 */ @@@ -122,7 -126,7 +122,7 @@@ 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)*/ @@@ -138,7 -142,7 +138,7 @@@ /* 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"); @@@ -159,7 -163,7 +159,7 @@@ static void afp_dsi_transfer_session(in { 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"); @@@ -210,13 -214,13 +210,13 @@@ static void afp_dsi_timedown(int sig _U { 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; } @@@ -273,17 -277,17 +273,17 @@@ static void afp_dsi_debug(int sig _U_ /* ---------------------- */ 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); @@@ -337,7 -341,7 +337,7 @@@ 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"); @@@ -361,14 -365,14 +361,14 @@@ static void pending_request(DSI *dsi 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)); } } @@@ -378,14 -382,13 +378,13 @@@ */ void afp_over_dsi(AFPObj *obj) { - DSI *dsi = (DSI *) obj->handle; + DSI *dsi = (DSI *) obj->dsi; int rc_idx; - u_int32_t err, cmd; - u_int8_t function; + uint32_t err, cmd; + uint8_t function; struct sigaction action; AFPobj = obj; - dsi->AFPobj = obj; obj->exit = afp_dsi_die; obj->reply = (int (*)()) dsi_cmdreply; obj->attention = (int (*)(void *, AFPUserBytes)) dsi_attention; @@@ -538,7 -541,7 +537,7 @@@ if (reload_request) { reload_request = 0; - load_volumes(AFPobj); + load_volumes(AFPobj, closevol); } /* The first SIGINT enables debugging, the next restores the config */ @@@ -551,15 -554,15 +550,15 @@@ if (debugging) { if (obj->options.logconfig) - setuplog(obj->options.logconfig); + setuplog(obj->options.logconfig, obj->options.logfile); else - setuplog("default log_note"); + setuplog("default:note", NULL); debugging = 0; } else { char logstr[50]; debugging = 1; - sprintf(logstr, "default log_maxdebug /tmp/afpd.%u.XXXXXX", getpid()); - setuplog(logstr); + sprintf(logstr, "/tmp/afpd.%u.XXXXXX", getpid()); + setuplog("default:maxdebug", logstr); } } @@@ -623,6 -626,11 +622,6 @@@ dir_free_invalid_q(); -#ifdef FORCE_UIDGID - /* bring everything back to old euid, egid */ - if (obj->force_uid) - restore_uidgid ( &obj->uidgid ); -#endif /* FORCE_UIDGID */ dsi->flags &= ~DSI_RUNNING; /* Add result to the AFP replay cache */ @@@ -663,6 -671,11 +662,6 @@@ AfpNum2name(function), AfpErr2name(err)); dsi->flags &= ~DSI_RUNNING; -#ifdef FORCE_UIDGID - /* bring everything back to old euid, egid */ - if (obj->force_uid) - restore_uidgid ( &obj->uidgid ); -#endif /* FORCE_UIDGID */ } else { LOG(log_error, logtype_afpd, "(write) bad function %x", function); dsi->datalen = 0; diff --combined etc/afpd/main.c index 5b79c08d,e23d5570..e89d0a2e --- a/etc/afpd/main.c +++ b/etc/afpd/main.c @@@ -11,8 -11,10 +11,8 @@@ #include #include #include - #include #include -#include #include #include #include @@@ -20,18 -22,19 +20,18 @@@ #include #include +#include #include - -#include #include #include -#include -#include #include #include #include #include #include +#include #include +#include #include "afp_config.h" #include "status.h" @@@ -39,12 -42,21 +39,12 @@@ #include "uam_auth.h" #include "afp_zeroconf.h" -#ifdef TRU64 -#include -#include -#include - -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; -static AFPConfig *configs; +unsigned char nologin = 0; + +static AFPObj obj; static server_child *server_children; static sig_atomic_t reloadconfig = 0; static sig_atomic_t gotsigchld = 0; @@@ -56,34 -68,45 +56,34 @@@ static int fdset_size; /* curr 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 */ +static afp_child_t *dsi_start(AFPObj *obj, DSI *dsi, server_child *server_children); -/* This is registered with atexit() */ -static void afp_exit(void) +static void afp_exit(int ret) { - if (parent_or_child == 0) - /* Only do this in the parent */ - server_unlock(default_options.pidfile); + exit(ret); } /* ------------------ 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; + 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, @@@ -93,21 -116,29 +93,21 @@@ 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; - -#ifndef NO_DDP - asp_kill(sig); -#endif /* ! NO_DDP */ - switch( sig ) { case SIGTERM: @@@ -117,7 -148,7 +117,7 @@@ LOG(log_note, logtype_afpd, "AFP Server shutting down on SIGTERM"); break; case SIGQUIT: - if (default_options.flags & OPTION_KEEPSESSIONS) { + if (obj.options.flags & OPTION_KEEPSESSIONS) { LOG(log_note, logtype_afpd, "AFP Server shutting down on SIGQUIT, NOT disconnecting clients"); } else { LOG(log_note, logtype_afpd, "AFP Server shutting down on SIGQUIT"); @@@ -128,7 -159,11 +128,7 @@@ 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); - exit(0); + _exit(0); break; case SIGUSR1 : @@@ -210,37 -245,53 +210,37 @@@ static int setlimits(void 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 */ - /* Parse argv args and initialize default options */ - afp_options_init(&default_options); - if (!afp_options_parse(ac, av, &default_options)) - exit(EXITERR_CONF); - - if (check_lockfile("afpd", default_options.pidfile) != 0) - exit(EXITERR_SYS); - - if (!(default_options.flags & OPTION_DEBUG) && (daemonize(0, 0) != 0)) - exit(EXITERR_SYS); + afp_options_parse_cmdline(&obj, ac, av); - if (create_lockfile("afpd", default_options.pidfile) != 0) + if (!(obj.cmdlineflags & OPTION_DEBUG) && (daemonize(0, 0) != 0)) exit(EXITERR_SYS); /* Log SIGBUS/SIGSEGV SBT */ fault_setup(NULL); - /* Default log setup: log to syslog */ - set_processname("afpd"); - setuplog("default log_note"); + if (afp_config_parse(&obj, "afpd") != 0) + afp_exit(EXITERR_CONF); /* Save the user's current umask */ - default_options.save_mask = umask( default_options.umask ); - - atexit(afp_exit); + obj.options.save_mask = umask(obj.options.umask); /* install child handler for asp and dsi. we do this before afp_goaway * as afp_goaway references stuff from here. * XXX: this should really be setup after the initial connections. */ - if (!(server_children = server_child_alloc(default_options.connections, - CHILD_NFORKS))) { + if (!(server_children = server_child_alloc(obj.options.connections, CHILD_NFORKS))) { LOG(log_error, logtype_afpd, "main: server_child alloc: %s", strerror(errno) ); - exit(EXITERR_SYS); + afp_exit(EXITERR_SYS); } + + sigemptyset(&sigs); + pthread_sigmask(SIG_SETMASK, &sigs, NULL); memset(&sv, 0, sizeof(sv)); /* linux at least up to 2.4.22 send a SIGXFZ for vfat fs, @@@ -250,7 -301,7 +250,7 @@@ sigemptyset( &sv.sa_mask ); if (sigaction(SIGXFSZ, &sv, NULL ) < 0 ) { LOG(log_error, logtype_afpd, "main: sigaction: %s", strerror(errno) ); - exit(EXITERR_SYS); + afp_exit(EXITERR_SYS); } #endif @@@ -265,7 -316,7 +265,7 @@@ sv.sa_flags = SA_RESTART; if ( sigaction( SIGCHLD, &sv, NULL ) < 0 ) { LOG(log_error, logtype_afpd, "main: sigaction: %s", strerror(errno) ); - exit(EXITERR_SYS); + afp_exit(EXITERR_SYS); } sigemptyset( &sv.sa_mask ); @@@ -277,7 -328,7 +277,7 @@@ sv.sa_flags = SA_RESTART; if ( sigaction( SIGUSR1, &sv, NULL ) < 0 ) { LOG(log_error, logtype_afpd, "main: sigaction: %s", strerror(errno) ); - exit(EXITERR_SYS); + afp_exit(EXITERR_SYS); } sigemptyset( &sv.sa_mask ); @@@ -289,9 -340,10 +289,9 @@@ sv.sa_flags = SA_RESTART; if ( sigaction( SIGHUP, &sv, NULL ) < 0 ) { LOG(log_error, logtype_afpd, "main: sigaction: %s", strerror(errno) ); - exit(EXITERR_SYS); + afp_exit(EXITERR_SYS); } - sigemptyset( &sv.sa_mask ); sigaddset(&sv.sa_mask, SIGALRM); sigaddset(&sv.sa_mask, SIGHUP); @@@ -301,7 -353,7 +301,7 @@@ sv.sa_flags = SA_RESTART; if ( sigaction( SIGTERM, &sv, NULL ) < 0 ) { LOG(log_error, logtype_afpd, "main: sigaction: %s", strerror(errno) ); - exit(EXITERR_SYS); + afp_exit(EXITERR_SYS); } sigemptyset( &sv.sa_mask ); @@@ -313,10 -365,10 +313,10 @@@ sv.sa_flags = SA_RESTART; if (sigaction(SIGQUIT, &sv, NULL ) < 0 ) { LOG(log_error, logtype_afpd, "main: sigaction: %s", strerror(errno) ); - exit(EXITERR_SYS); + afp_exit(EXITERR_SYS); } - /* afpd.conf: not in config file: lockfile, connections, configfile + /* afp.conf: not in config file: lockfile, configfile * preference: command-line provides defaults. * config file over-writes defaults. * @@@ -335,29 -387,29 +335,29 @@@ sigaddset(&sigs, SIGCHLD); pthread_sigmask(SIG_BLOCK, &sigs, NULL); - if (!(configs = configinit(&default_options))) { + if (configinit(&obj) != 0) { LOG(log_error, logtype_afpd, "main: no servers configured"); - exit(EXITERR_CONF); + afp_exit(EXITERR_CONF); } pthread_sigmask(SIG_UNBLOCK, &sigs, NULL); - /* Register CNID */ + /* Initialize */ cnid_init(); - + /* watch atp, dsi sockets and ipc parent/child file descriptor. */ - if (default_options.flags & OPTION_KEEPSESSIONS) { + if (obj.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(&obj); /* set limits */ (void)setlimits(); afp_child_t *child; - int fd[2]; /* we only use one, but server_child_add expects [2] */ + int recon_ipc_fd; pid_t pid; int saveerrno; @@@ -383,17 -435,22 +383,17 @@@ if (reloadconfig) { nologin++; auth_unload(); - fd_reset_listening_sockets(); + fd_reset_listening_sockets(&obj); LOG(log_info, logtype_afpd, "re-reading configuration file"); - for (config = configs; config; config = config->next) - if (config->server_cleanup) - config->server_cleanup(config); - - /* configfree close atp socket used for DDP tickle, there's an issue - * with atp tid. */ - configfree(configs, NULL); - if (!(configs = configinit(&default_options))) { + + configfree(&obj, NULL); + if (configinit(&obj) != 0) { LOG(log_error, logtype_afpd, "config re-read: no servers configured"); - exit(EXITERR_CONF); + afp_exit(EXITERR_CONF); } - fd_set_listening_sockets(); + fd_set_listening_sockets(&obj); nologin = 0; reloadconfig = 0; @@@ -412,18 -469,20 +412,18 @@@ } for (int i = 0; i < fdset_used; i++) { - if (fdset[i].revents & (POLLIN | POLLERR | POLLHUP)) { + if (fdset[i].revents & (POLLIN | POLLERR | POLLHUP | POLLNVAL)) { 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(&obj, (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(obj.options.connections + AFP_LISTENERS + FDSET_SAFETY, &fdset, &polldata, &fdset_used, &fdset_size, - child->ipc_fds[0], + child->ipc_fd, IPC_FD, child); } @@@ -433,11 -492,11 +433,11 @@@ child = (afp_child_t *)polldata[i].data; LOG(log_debug, logtype_afpd, "main: IPC request from child[%u]", child->pid); - if (ipc_server_read(server_children, child->ipc_fds[0]) != 0) { - fdset_del_fd(&fdset, &polldata, &fdset_used, &fdset_size, child->ipc_fds[0]); - close(child->ipc_fds[0]); - child->ipc_fds[0] = -1; + if (ipc_server_read(server_children, child->ipc_fd) != 0) { + fdset_del_fd(&fdset, &polldata, &fdset_used, &fdset_size, child->ipc_fd); + close(child->ipc_fd); + child->ipc_fd = -1; - if ((default_options.flags & OPTION_KEEPSESSIONS) && child->disasociated) { + if ((obj.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); } @@@ -446,28 -505,29 +446,29 @@@ case DISASOCIATED_IPC_FD: LOG(log_debug, logtype_afpd, "main: IPC reconnect request"); - if ((fd[0] = accept(disasociated_ipc_fd, NULL, NULL)) == -1) { + if ((recon_ipc_fd = accept(disasociated_ipc_fd, NULL, NULL)) == -1) { LOG(log_error, logtype_afpd, "main: accept: %s", strerror(errno)); break; } - if (readt(fd[0], &pid, sizeof(pid_t), 0, 1) != sizeof(pid_t)) { + if (readt(recon_ipc_fd, &pid, sizeof(pid_t), 0, 1) != sizeof(pid_t)) { LOG(log_error, logtype_afpd, "main: readt: %s", strerror(errno)); - close(fd[0]); + close(recon_ipc_fd); break; } LOG(log_note, logtype_afpd, "main: IPC reconnect from pid [%u]", pid); - if ((child = server_child_add(server_children, CHILD_DSIFORK, pid, fd)) == NULL) { + + if ((child = server_child_add(server_children, CHILD_DSIFORK, pid, recon_ipc_fd)) == NULL) { LOG(log_error, logtype_afpd, "main: server_child_add"); - close(fd[0]); + close(recon_ipc_fd); break; } child->disasociated = 1; - fdset_add_fd(default_options.connections + AFP_LISTENERS + FDSET_SAFETY, + fdset_add_fd(obj.options.connections + AFP_LISTENERS + FDSET_SAFETY, &fdset, &polldata, &fdset_used, &fdset_size, - fd[0], + recon_ipc_fd, IPC_FD, child); break; @@@ -482,26 -542,3 +483,22 @@@ return 0; } + +static afp_child_t *dsi_start(AFPObj *obj, DSI *dsi, server_child *server_children) +{ + afp_child_t *child = NULL; + - if (!(child = dsi_getsession(dsi, - server_children, - obj->options.tickleval))) { ++ if (dsi_getsession(dsi, server_children, obj->options.tickleval, &child) != 0) { + LOG(log_error, logtype_afpd, "dsi_start: session error: %s", strerror(errno)); + return NULL; + } + + /* we've forked. */ - if (child->ipc_fds[0] == -1) { ++ if (child == NULL) { + configfree(obj, dsi); - obj->ipc_fd = child->ipc_fds[1]; - free(child); + afp_over_dsi(obj); /* start a session */ + exit (0); + } + + return child; +} diff --combined include/atalk/dsi.h index 60afc186,eded2b8f..bd8cc8b4 --- a/include/atalk/dsi.h +++ b/include/atalk/dsi.h @@@ -3,101 -3,107 +3,101 @@@ * All rights reserved. */ -#ifndef _ATALK_DSI_H +#ifndef _ATALK_DSI_H #define _ATALK_DSI_H -#include #include #include -#include #include +#include +#include #include #include #include #include -#include - /* 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 . +/* these need to be kept in sync w/ AFPTRANS_* in . * 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 { - u_int8_t dsi_flags; /* packet type: request or reply */ - u_int8_t dsi_command; /* command */ - u_int16_t dsi_requestID; /* request ID */ - u_int32_t dsi_code; /* error code or data offset */ - u_int32_t dsi_len; /* total data length */ - u_int32_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 */ - - u_int32_t attn_quantum, datasize, server_quantum; - u_int16_t serverID, clientID; - char *status; - u_int8_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 + struct DSI *next; /* multiple listening addresses */ + AFPObj *AFPobj; + int statuslen; + char status[1400]; + char *signature; + 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; + uint8_t commands[DSI_CMDSIZ], data[DSI_DATASIZ]; + size_t datalen, cmdlen; + off_t read_count, write_count; + uint32_t flags; /* DSI flags like DSI_SLEEPING, DSI_DISCONNECTED */ + 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 @@@ -119,17 -125,17 +119,17 @@@ #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 */ @@@ -156,12 -162,15 +156,12 @@@ #endif /* 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 u_int32_t /* server quantum */); +extern DSI *dsi_init(AFPObj *obj, const char *hostname, const char *address, const char *port); extern void dsi_setstatus (DSI *, char *, const size_t); +extern int dsi_tcp_init(DSI *dsi, const char *hostname, const char *address, const char *port); /* in dsi_getsess.c */ --extern afp_child_t *dsi_getsession (DSI *, server_child *, const int); ++extern int dsi_getsession (DSI *, server_child *, const int, afp_child_t **); extern void dsi_kill (int); @@@ -174,8 -183,6 +174,8 @@@ extern void dsi_getstatus (DSI *) extern void dsi_close (DSI *); #define DSI_NOWAIT 1 +#define DSI_MSG_MORE 2 + /* low-level stream commands -- in dsi_stream.c */ extern ssize_t dsi_stream_write (DSI *, void *, const size_t, const int mode); extern size_t dsi_stream_read (DSI *, void *, const size_t); @@@ -184,7 -191,7 +184,7 @@@ extern int dsi_stream_receive (DSI *) extern int dsi_disconnect(DSI *dsi); #ifdef WITH_SENDFILE -extern ssize_t dsi_stream_read_file(DSI *, int, off_t off, const size_t len); +extern ssize_t dsi_stream_read_file(DSI *, int, off_t off, const size_t len, const int err); #endif /* client writes -- dsi_write.c */ @@@ -195,15 -202,15 +195,15 @@@ extern void dsi_writeflush (DSI *) /* 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 */ diff --combined include/atalk/server_child.h index 262ee201,5ee8314f..ad41bcec --- a/include/atalk/server_child.h +++ b/include/atalk/server_child.h @@@ -6,8 -6,9 +6,8 @@@ #ifndef _ATALK_SERVER_CHILD_H #define _ATALK_SERVER_CHILD_H 1 -#include #include -#include +#include /* useful stuff for child processes. most of this is hidden in * server_child.c to ease changes in implementation */ @@@ -31,19 -32,21 +31,19 @@@ typedef struct server_child_data uint32_t time; /* client boot time (from the mac client) */ uint32_t idlen; /* clientid len (from the Mac client) */ char *clientid; /* clientid (from the Mac client) */ - int ipc_fds[2]; /* socketpair for IPC bw */ + int ipc_fd; /* socket for IPC bw afpd parent and childs */ struct server_child_data **prevp, *next; } afp_child_t; -extern int parent_or_child; - /* server_child.c */ extern server_child *server_child_alloc (const int, const int); - extern afp_child_t *server_child_add (server_child *, int, pid_t, uint ipc_fds[2]); + extern afp_child_t *server_child_add (server_child *, int, pid_t, int ipc_fd); extern int server_child_remove (server_child *, const int, const pid_t); extern void server_child_free (server_child *); extern void server_child_kill (server_child *, const int, const int); extern void server_child_kill_one_by_id (server_child *children, const int forkid, const pid_t pid, const uid_t, - const u_int32_t len, char *id, u_int32_t boottime); + const uint32_t len, char *id, uint32_t boottime); extern int server_child_transfer_session(server_child *children, int forkid, pid_t, uid_t, int, uint16_t); extern void server_child_setup (server_child *, const int, void (*)(const pid_t)); extern void server_child_handler (server_child *); diff --combined libatalk/dsi/dsi_getsess.c index 8d6e544c,bcc32da2..001279cd --- a/libatalk/dsi/dsi_getsess.c +++ b/libatalk/dsi/dsi_getsess.c @@@ -18,8 -18,18 +18,8 @@@ #include #include -/* POSIX.1 sys/wait.h check */ #include -#ifdef HAVE_SYS_WAIT_H #include -#endif /* HAVE_SYS_WAIT_H */ -#ifndef WEXITSTATUS -#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) -#endif /* ! WEXITSTATUS */ -#ifndef WIFEXITED -#define WIFEXITED(stat_val) (((stat_val) & 255) == 0) -#endif /* ! WIFEXITED */ - #include #include #include @@@ -27,8 -37,8 +27,13 @@@ #include #include --/* hand off the command. return child connection to the main program */ --afp_child_t *dsi_getsession(DSI *dsi, server_child *serv_children, int tickleval) ++/*! ++ * Start a DSI session, fork an afpd process ++ * ++ * @param childp (w) after fork: parent return pointer to child, child returns NULL ++ * @returns 0 on sucess, any other value denotes failure ++ */ ++int dsi_getsession(DSI *dsi, server_child *serv_children, int tickleval, afp_child_t **childp) { pid_t pid; unsigned int ipc_fds[2]; @@@ -36,37 -46,38 +41,39 @@@ if (socketpair(PF_UNIX, SOCK_STREAM, 0, ipc_fds) < 0) { LOG(log_error, logtype_dsi, "dsi_getsess: %s", strerror(errno)); -- exit( EXITERR_CLNT ); ++ return -1; } if (setnonblock(ipc_fds[0], 1) != 0 || setnonblock(ipc_fds[1], 1) != 0) { LOG(log_error, logtype_dsi, "dsi_getsess: setnonblock: %s", strerror(errno)); -- exit(EXITERR_CLNT); ++ return -1; } switch (pid = dsi->proto_open(dsi)) { /* in libatalk/dsi/dsi_tcp.c */ case -1: /* if we fail, just return. it might work later */ LOG(log_error, logtype_dsi, "dsi_getsess: %s", strerror(errno)); -- return NULL; ++ return -1; case 0: /* child. mostly handled below. */ break; default: /* parent */ - /* using SIGQUIT is hokey, but the child might not have + /* using SIGKILL is hokey, but the child might not have * re-established its signal handler for SIGTERM yet. */ - if ((child = server_child_add(serv_children, CHILD_DSIFORK, pid, ipc_fds)) == NULL) { + close(ipc_fds[1]); + if ((child = server_child_add(serv_children, CHILD_DSIFORK, pid, ipc_fds[0])) == NULL) { LOG(log_error, logtype_dsi, "dsi_getsess: %s", strerror(errno)); + close(ipc_fds[0]); dsi->header.dsi_flags = DSIFL_REPLY; dsi->header.dsi_code = DSIERR_SERVBUSY; dsi_send(dsi); dsi->header.dsi_code = DSIERR_OK; - kill(pid, SIGQUIT); + kill(pid, SIGKILL); } - close(ipc_fds[1]); dsi->proto_close(dsi); -- return child; ++ *childp = child; ++ return 0; } /* child: check number of open connections. this is one off the @@@ -81,9 -92,9 +88,10 @@@ } /* get rid of some stuff */ + dsi->AFPobj->ipc_fd = ipc_fds[1]; close(ipc_fds[0]); close(dsi->serversock); + dsi->serversock = -1; server_child_free(serv_children); switch (dsi->header.dsi_command) { @@@ -115,13 -126,7 +123,8 @@@ dsi->timer.it_interval.tv_usec = dsi->timer.it_value.tv_usec = 0; signal(SIGPIPE, SIG_IGN); /* we catch these ourselves */ dsi_opensession(dsi); - if ((child = calloc(1, sizeof(afp_child_t))) == NULL) - exit(EXITERR_SYS); - - child->ipc_fds[0] = -1; - child->ipc_fds[1] = ipc_fds[1]; - close(ipc_fds[0]); - return child; - return NULL; ++ *childp = NULL; ++ return 0; default: /* just close */ LOG(log_info, logtype_dsi, "DSIUnknown %d", dsi->header.dsi_command); diff --combined libatalk/util/server_child.c index c87417d5,86f05a09..ada3e610 --- a/libatalk/util/server_child.c +++ b/libatalk/util/server_child.c @@@ -18,11 -18,17 +18,11 @@@ #include #include -#ifdef HAVE_UNISTD_H #include -#endif /* HAVE_UNISTD_H */ #include #include - -/* POSIX.1 sys/wait.h check */ #include -#ifdef HAVE_SYS_WAIT_H #include -#endif /* HAVE_SYS_WAIT_H */ #include #include @@@ -55,6 -61,8 +55,6 @@@ typedef struct server_child_fork void (*cleanup)(const pid_t); } server_child_fork; -int parent_or_child; /* 0: parent, 1: child */ - static inline void hash_child(struct server_child_data **htable, struct server_child_data *child) { @@@ -113,7 -121,7 +113,7 @@@ server_child *server_child_alloc(const * add a child * @return pointer to struct server_child_data on success, NULL on error */ - afp_child_t *server_child_add(server_child *children, int forkid, pid_t pid, uint ipc_fds[2]) + afp_child_t *server_child_add(server_child *children, int forkid, pid_t pid, int ipc_fd) { server_child_fork *fork; afp_child_t *child = NULL; @@@ -144,8 -152,7 +144,7 @@@ child->pid = pid; child->valid = 0; child->killed = 0; - child->ipc_fds[0] = ipc_fds[0]; - child->ipc_fds[1] = ipc_fds[1]; + child->ipc_fd = ipc_fd; hash_child(fork->table, child); children->count++; @@@ -173,15 -180,9 +172,9 @@@ int server_child_remove(server_child *c } /* In main:child_handler() we need the fd in order to remove it from the pollfd set */ - fd = child->ipc_fds[0]; - if (child->ipc_fds[0] != -1) { - close(child->ipc_fds[0]); - child->ipc_fds[0] = -1; - } - if (child->ipc_fds[1] != -1) { - close(child->ipc_fds[1]); - child->ipc_fds[1] = -1; - } + fd = child->ipc_fd; + if (fd != -1) + close(fd); free(child); children->count--; @@@ -206,9 -207,7 +199,7 @@@ void server_child_free(server_child *ch child = fork->table[j]; /* start at the beginning */ while (child) { tmp = child->next; - - if (child->ipc_fds[0] != -1) - close(child->ipc_fds[0]); + close(child->ipc_fd); if (child->clientid) { free(child->clientid); } @@@ -300,12 -299,12 +291,12 @@@ int server_child_transfer_session(serve LOG(log_note, logtype_default, "Reconnect: transfering session to child[%u]", pid); - if (writet(child->ipc_fds[0], &DSI_requestID, 2, 0, 2) != 2) { + if (writet(child->ipc_fd, &DSI_requestID, 2, 0, 2) != 2) { LOG(log_error, logtype_default, "Reconnect: error sending DSI id to child[%u]", pid); EC_STATUS(-1); goto EC_CLEANUP; } - EC_ZERO_LOG(send_fd(child->ipc_fds[0], afp_socket)); + EC_ZERO_LOG(send_fd(child->ipc_fd, afp_socket)); EC_ZERO_LOG(kill(pid, SIGURG)); EC_STATUS(1);