afpfs-ng-mac/lib/connect.c

156 lines
4.3 KiB
C

/*
* connect.c
*
* Copyright (C) 2007 Alex deVries
*
*/
#include <signal.h>
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include "afpfs-ng/afp.h"
#include "afpfs-ng/dsi.h"
#include "afpfs-ng/utils.h"
#include "afpfs-ng/uams_def.h"
#include "afpfs-ng/codepage.h"
#include "users.h"
#include "afpfs-ng/libafpclient.h"
#include "server.h"
struct addrinfo * afp_get_address(void * priv, const char * hostname, unsigned int port)
{
char port_string[6];
struct addrinfo hints;
struct addrinfo * addresses;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
snprintf(port_string, sizeof(port_string), "%u", port);
int res = getaddrinfo(hostname, port_string, &hints, &addresses);
if (res != 0 ) {
log_for_client(priv,AFPFSD,LOG_ERR,
"Could not resolve %s.\n",hostname);
return NULL;
}
return addresses;
}
struct afp_server * afp_server_full_connect (void * priv, struct afp_connection_request *req)
{
int ret;
struct addrinfo * address;
struct afp_server * s=NULL;
struct afp_server * tmpserver;
char signature[AFP_SIGNATURE_LEN];
unsigned char versions[SERVER_MAX_VERSIONS];
unsigned int uams;
char machine_type[AFP_MACHINETYPE_LEN];
char server_name[AFP_SERVER_NAME_LEN];
char server_name_utf8[AFP_SERVER_NAME_UTF8_LEN];
char server_name_printable[AFP_SERVER_NAME_UTF8_LEN];
unsigned int rx_quantum;
char icon[AFP_SERVER_ICON_LEN];
if ((address = afp_get_address(priv,req->url.servername, req->url.port)) == NULL)
goto error;
if ((s=find_server_by_address(address))) goto have_server;
if ((tmpserver=afp_server_init(address))==NULL) goto error;
if ((ret=afp_server_connect(tmpserver,1))<0) {
if (ret==-ETIMEDOUT) {
log_for_client(priv,AFPFSD,LOG_ERR,
"Could not connect, never got a response to getstatus, %s\n",strerror(-ret));
} else {
log_for_client(priv,AFPFSD,LOG_ERR,
"Could not connect, %s\n",strerror(-ret));
}
afp_server_remove(tmpserver);
goto error;
}
loop_disconnect(tmpserver);
memcpy(icon,&tmpserver->icon,AFP_SERVER_ICON_LEN);
memcpy(&versions,&tmpserver->versions,SERVER_MAX_VERSIONS);
uams=tmpserver->supported_uams;
memcpy(signature,&tmpserver->signature,AFP_SIGNATURE_LEN);
memcpy(machine_type,&tmpserver->machine_type,AFP_MACHINETYPE_LEN);
memcpy(server_name,&tmpserver->server_name,AFP_SERVER_NAME_LEN);
memcpy(server_name_utf8,&tmpserver->server_name_utf8,
AFP_SERVER_NAME_UTF8_LEN);
memcpy(server_name_printable,&tmpserver->server_name_printable,
AFP_SERVER_NAME_UTF8_LEN);
rx_quantum=tmpserver->rx_quantum;
afp_server_remove(tmpserver);
s=find_server_by_signature(signature);
if (!s) {
s = afp_server_init(address);
if (afp_server_connect(s,0) !=0) {
log_for_client(priv,AFPFSD,LOG_ERR,
"Could not connect to server error: %s\n",
strerror(errno));
goto error;
}
//if our user and password strings are both empty and if
//the server supports anonymous logins, pretend we only support
//that as auth will never succeed with such credentials
if(*req->url.username == '\0' && *req->url.password == '\0'
&& (uams & UAM_NOUSERAUTHENT)) {
req->uam_mask = UAM_NOUSERAUTHENT;
}
if ((afp_server_complete_connection(priv,
s,address,(unsigned char *) &versions,uams,
req->url.username, req->url.password,
req->url.requested_version, req->uam_mask))==NULL) {
goto error;
}
s->supported_uams=uams;
memcpy(s->signature,signature,AFP_SIGNATURE_LEN);
memcpy(s->server_name,server_name,AFP_SERVER_NAME_LEN);
memcpy(s->server_name_utf8,server_name_utf8,
AFP_SERVER_NAME_UTF8_LEN);
memcpy(s->server_name_printable,server_name_printable,
AFP_SERVER_NAME_UTF8_LEN);
memcpy(s->machine_type,machine_type,AFP_MACHINETYPE_LEN);
memcpy(s->icon,icon,AFP_SERVER_ICON_LEN);
s->rx_quantum=rx_quantum;
}
have_server:
/* Figure out if we're using netatalk */
if (strcmp(s->machine_type,"Netatalk")==0)
s->server_type=AFPFS_SERVER_TYPE_NETATALK;
else if (strcmp(s->machine_type,"Airport")==0)
s->server_type=AFPFS_SERVER_TYPE_AIRPORT;
else if (strcmp(s->machine_type,"Macintosh")==0)
s->server_type=AFPFS_SERVER_TYPE_MACINTOSH;
else
s->server_type=AFPFS_SERVER_TYPE_UNKNOWN;
return s;
error:
if ((s) && (!something_is_mounted(s))) { /* FIXME */
afp_server_remove(s);
}
return NULL;
}