Exemple #1
0
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;
}
Exemple #2
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);
  }
}
Exemple #3
0
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;

}