-/* $Id$
- *
+/*
* Copyright (c) 1987-2009 by the citadel.org team
*
* This program is free software; you can redistribute it and/or modify
ret = CtdlIPCGenericCommand(ipc, "GETU", NULL, 0, NULL, NULL, cret);
if (ret / 100 == 2) {
- uret[0]->USscreenwidth = extract_int(cret, 0);
- uret[0]->USscreenheight = extract_int(cret, 1);
uret[0]->flags = extract_int(cret, 2);
}
return ret;
if (!uret) return -2;
if (!cret) return -2;
- sprintf(aaa, "SETU %d|%d|%d",
- uret->USscreenwidth, uret->USscreenheight,
- uret->flags);
+ sprintf(aaa,
+ "SETU 80|24|%d",
+ uret->flags
+ );
return CtdlIPCGenericCommand(ipc, aaa, NULL, 0, NULL, NULL, cret);
}
break;
case 22: strcpy(ipc->ServInfo.svn_revision, buf);
break;
+ case 24: ipc->ServInfo.guest_logins = atoi(buf);
+ break;
}
}
/* ************************************************************************** */
-/* Stuff below this line is not for public consumption */
+/* Stuff below this line is not for public consumption */
/* ************************************************************************** */
}
-static int connectsock(char *host, char *service, char *protocol, int defaultPort)
+/*
+ * Connect to a Citadel on a remote host using a TCP/IP socket
+ */
+static int tcp_connectsock(char *host, char *service)
{
- struct hostent *phe;
- struct servent *pse;
- struct protoent *ppe;
- struct sockaddr_in sin;
- int s, type;
+ struct in6_addr serveraddr;
+ struct addrinfo hints;
+ struct addrinfo *res = NULL;
+ struct addrinfo *ai = NULL;
+ int rc = (-1);
+ int sock = (-1);
- memset(&sin, 0, sizeof(sin));
- sin.sin_family = AF_INET;
-
- pse = getservbyname(service, protocol);
- if (pse != NULL) {
- sin.sin_port = pse->s_port;
- }
- else if (atoi(service) > 0) {
- sin.sin_port = htons(atoi(service));
+ if ((host == NULL) || IsEmptyStr(host)) {
+ service = DEFAULT_HOST ;
}
- else {
- sin.sin_port = htons(defaultPort);
- }
- phe = gethostbyname(host);
- if (phe) {
- memcpy(&sin.sin_addr, phe->h_addr, phe->h_length);
- } else if ((sin.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE) {
- return -1;
+ if ((service == NULL) || IsEmptyStr(service)) {
+ service = DEFAULT_PORT ;
}
- if ((ppe = getprotobyname(protocol)) == 0) {
- return -1;
+
+ memset(&hints, 0x00, sizeof(hints));
+ hints.ai_flags = AI_NUMERICSERV;
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+
+ /*
+ * Handle numeric IPv4 and IPv6 addresses
+ */
+ rc = inet_pton(AF_INET, host, &serveraddr);
+ if (rc == 1) { /* dotted quad */
+ hints.ai_family = AF_INET;
+ hints.ai_flags |= AI_NUMERICHOST;
}
- if (!strcmp(protocol, "udp")) {
- type = SOCK_DGRAM;
- } else {
- type = SOCK_STREAM;
+ else {
+ rc = inet_pton(AF_INET6, host, &serveraddr);
+ if (rc == 1) { /* IPv6 address */
+ hints.ai_family = AF_INET6;
+ hints.ai_flags |= AI_NUMERICHOST;
+ }
}
- s = socket(PF_INET, type, ppe->p_proto);
- if (s < 0) {
- return -1;
+ /* Begin the connection process */
+
+ rc = getaddrinfo(host, service, &hints, &res);
+ if (rc != 0) {
+ return(-1);
}
- if (connect(s, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
- close(s);
- return -1;
+ /*
+ * Try all available addresses until we connect to one or until we run out.
+ */
+ for (ai = res; ai != NULL; ai = ai->ai_next) {
+ sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+ if (sock < 0) return(-1);
+
+ rc = connect(sock, ai->ai_addr, ai->ai_addrlen);
+ if (rc >= 0) {
+ return(sock); /* Connected! */
+ }
+ else {
+ close(sock); /* Failed. Close the socket to avoid fd leak! */
+ }
}
- return (s);
+ return(-1);
}
+
+
+
+
+/*
+ * Connect to a Citadel on the local host using a unix domain socket
+ */
static int uds_connectsock(int *isLocal, char *sockpath)
{
struct sockaddr_un addr;
/* If we're using a unix domain socket we can do a bunch of stuff */
if (!strcmp(cithost, UDS)) {
if (!strcasecmp(citport, DEFAULT_PORT)) {
- snprintf(sockpath, sizeof sockpath, file_citadel_socket);
+ snprintf(sockpath, sizeof sockpath, "%s", file_citadel_socket);
}
else {
snprintf(sockpath, sizeof sockpath, "%s/%s", citport, "citadel.socket");
}
if (hostbuf != NULL) strcpy(hostbuf, cithost);
if (portbuf != NULL) strcpy(portbuf, sockpath);
+ strcpy(ipc->ip_hostname, "");
+ strcpy(ipc->ip_address, "");
return ipc;
}
- ipc->sock = connectsock(cithost, citport, "tcp", 504);
+ ipc->sock = tcp_connectsock(cithost, citport);
if (ipc->sock == -1) {
ifree(ipc);
return 0;
}
+
+
+ /* Learn the actual network identity of the host to which we are connected */
+
+ struct sockaddr_in6 clientaddr;
+ unsigned int addrlen = sizeof(clientaddr);
+
+ ipc->ip_hostname[0] = 0;
+ ipc->ip_address[0] = 0;
+
+ getpeername(ipc->sock, (struct sockaddr *)&clientaddr, &addrlen);
+ getnameinfo((struct sockaddr *)&clientaddr, addrlen,
+ ipc->ip_hostname, sizeof ipc->ip_hostname, NULL, 0, 0
+ );
+ getnameinfo((struct sockaddr *)&clientaddr, addrlen,
+ ipc->ip_address, sizeof ipc->ip_address, NULL, 0, NI_NUMERICHOST
+ );
+
+ /* stuff other things elsewhere */
+
if (hostbuf != NULL) strcpy(hostbuf, cithost);
if (portbuf != NULL) strcpy(portbuf, citport);
return ipc;