/* * connect.c * * Copyright (C) 2007 Alex deVries * */ #include #include #include #include #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; }