int afp_server_reconnect(struct afp_server * s, char * mesg, unsigned int *l, unsigned int max) { int i; struct afp_volume * v; if (afp_server_connect(s,0)) { *l+=snprintf(mesg,max-*l,"Error resuming connection to %s\n", s->server_name_printable); return 1; } dsi_opensession(s); if(afp_server_login(s,mesg,l,max)) return 1; for (i=0;i<s->num_volumes;i++) { v=&s->volumes[i]; if (strlen(v->mountpoint)) { if (afp_connect_volume(v,v->server,mesg,l,max)) *l+=snprintf(mesg,max-*l, "Could not mount %s\n", v->volume_name_printable); } } return 0; }
/* hand off the command. return child connection to the main program */ afp_child_t *dsi_getsession(DSI *dsi, server_child *serv_children, int tickleval) { pid_t pid; unsigned int ipc_fds[2]; afp_child_t *child; if (socketpair(PF_UNIX, SOCK_STREAM, 0, ipc_fds) < 0) { LOG(log_error, logtype_dsi, "dsi_getsess: %s", strerror(errno)); exit( EXITERR_CLNT ); } 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); } 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; case 0: /* child. mostly handled below. */ break; default: /* parent */ /* using SIGQUIT 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)) < 0) { LOG(log_error, logtype_dsi, "dsi_getsess: %s", strerror(errno)); dsi->header.dsi_flags = DSIFL_REPLY; dsi->header.dsi_code = DSIERR_SERVBUSY; dsi_send(dsi); dsi->header.dsi_code = DSIERR_OK; kill(pid, SIGQUIT); } dsi->proto_close(dsi); return child; } /* child: check number of open connections. this is one off the * actual count. */ if ((serv_children->count >= serv_children->nsessions) && (dsi->header.dsi_command == DSIFUNC_OPEN)) { LOG(log_info, logtype_dsi, "dsi_getsess: too many connections"); dsi->header.dsi_flags = DSIFL_REPLY; dsi->header.dsi_code = DSIERR_TOOMANY; dsi_send(dsi); exit(EXITERR_CLNT); } /* get rid of some stuff */ close(dsi->serversock); server_child_free(serv_children); switch (dsi->header.dsi_command) { case DSIFUNC_STAT: /* send off status and return */ { /* OpenTransport 1.1.2 bug workaround: * * OT code doesn't currently handle close sockets well. urk. * the workaround: wait for the client to close its * side. timeouts prevent indefinite resource use. */ static struct timeval timeout = {120, 0}; fd_set readfds; dsi_getstatus(dsi); FD_ZERO(&readfds); FD_SET(dsi->socket, &readfds); free(dsi); select(FD_SETSIZE, &readfds, NULL, NULL, &timeout); exit(0); } break; case DSIFUNC_OPEN: /* setup session */ /* set up the tickle timer */ dsi->timer.it_interval.tv_sec = dsi->timer.it_value.tv_sec = tickleval; 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[1] = ipc_fds[1]; return child; break; default: /* just close */ LOG(log_info, logtype_dsi, "DSIUnknown %d", dsi->header.dsi_command); dsi->proto_close(dsi); exit(EXITERR_CLNT); } }
struct afp_server * afp_server_complete_connection( void * priv, struct afp_server * server, struct sockaddr_in * address, unsigned char * versions, unsigned int uams, char * username, char * password, unsigned int requested_version, unsigned int uam_mask) { char loginmsg[AFP_LOGINMESG_LEN]; int using_uam; #define LOGIN_ERROR_MESG_LEN 1024 char mesg[LOGIN_ERROR_MESG_LEN]; unsigned int len=0; memset(loginmsg,0,AFP_LOGINMESG_LEN); server->requested_version=requested_version; memcpy(server->username,username,sizeof(server->username)); memcpy(server->password,password,sizeof(server->password)); add_fd_and_signal(server->fd); dsi_opensession(server); /* Figure out what version we're using */ if (((server->using_version= pick_version(versions,requested_version))==NULL)) { log_for_client(priv,AFPFSD,LOG_ERR, "Server cannot handle AFP version %d\n", requested_version); goto error; } using_uam=pick_uam(uams,uam_mask); if (using_uam==-1) { log_for_client(priv,AFPFSD,LOG_ERR, "Could not pick a matching UAM.\n"); goto error; } server->using_uam=using_uam; if (afp_server_login(server,mesg,&len,LOGIN_ERROR_MESG_LEN)) { log_for_client(priv,AFPFSD,LOG_ERR, "Login error: %s\n", mesg); goto error; } if (afp_getsrvrparms(server)) { log_for_client(priv,AFPFSD,LOG_ERR, "Could not get server parameters\n"); goto error; } /* If we haven't gotten a proper date back, so set it to the connect time. */ if (server->connect_time==3094168448) { struct timeval tv; gettimeofday(&tv,NULL); server->connect_time = tv.tv_sec; } afp_getsrvrmsg(server,AFPMESG_LOGIN, ((server->using_version->av_number>=30)?1:0), DSI_DEFAULT_TIMEOUT,loginmsg); /* block */ if (strlen(loginmsg)>0) log_for_client(priv,AFPFSD,LOG_NOTICE, "Login message: %s\n", loginmsg); memcpy(server->loginmesg,loginmsg, AFP_LOGINMESG_LEN); return server; error: afp_server_remove(server); return NULL; }