-/* $Id$
- *
+/*
* Copyright (c) 1987-2009 by the citadel.org team
*
* This program is free software; you can redistribute it and/or modify
break;
case 22: strcpy(ipc->ServInfo.svn_revision, buf);
break;
+ case 24: ipc->ServInfo.guest_logins = atoi(buf);
+ break;
}
}
int CtdlIPCSetLastRead(CtdlIPC *ipc, long msgnum, char *cret)
{
register int ret;
- char aaa[16];
+ char aaa[64];
if (!cret) return -2;
/* DELE */
int CtdlIPCDeleteMessage(CtdlIPC *ipc, long msgnum, char *cret)
{
- char aaa[16];
+ char aaa[64];
if (!cret) return -2;
if (!msgnum) return -2;
/* KILL */
int CtdlIPCDeleteRoom(CtdlIPC *ipc, int for_real, char *cret)
{
- char aaa[16];
+ char aaa[64];
if (!cret) return -2;
if (!cret) return -2;
if (!username) return -2;
- if (axlevel < 0 || axlevel > 7) return -2;
+ if (axlevel < AxDeleted || axlevel > AxAideU) return -2;
aaa = (char *)malloc(strlen(username) + 17);
if (!aaa) return -1;
/* EINF */
int CtdlIPCSetRoomInfo(CtdlIPC *ipc, int for_real, const char *info, char *cret)
{
- char aaa[16];
+ char aaa[64];
if (!cret) return -1;
if (!info) return -1;
/* mode is 0 = enable, 1 = disable, 2 = status */
int CtdlIPCEnableInstantMessageReceipt(CtdlIPC *ipc, int mode, char *cret)
{
- char aaa[16];
+ char aaa[64];
if (!cret) return -2;
/* STEL */
int CtdlIPCStealthMode(CtdlIPC *ipc, int mode, char *cret)
{
- char aaa[16];
+ char aaa[64];
if (!cret) return -1;
/* TERM */
int CtdlIPCTerminateSession(CtdlIPC *ipc, int sid, char *cret)
{
- char aaa[16];
+ char aaa[64];
if (!cret) return -1;
/* GPEX */
/* which is 0 = room, 1 = floor, 2 = site, 3 = default for mailboxes */
/* caller must free the struct ExpirePolicy */
-int CtdlIPCGetMessageExpirationPolicy(CtdlIPC *ipc, int which,
+int CtdlIPCGetMessageExpirationPolicy(CtdlIPC *ipc, GPEXWhichPolicy which,
struct ExpirePolicy **policy, char *cret)
{
- static char *proto[] = {"room", "floor", "site", "mailboxes" };
+ static char *proto[] = {
+ strof(roompolicy),
+ strof(floorpolicy),
+ strof(sitepolicy),
+ strof(mailboxespolicy)
+ };
char cmd[256];
register int ret;
/* REQT */
int CtdlIPCRequestClientLogout(CtdlIPC *ipc, int session, char *cret)
{
- char aaa[16];
+ char aaa[64];
if (!cret) return -2;
if (session < 0) return -2;
}
/* Pointless flag waving */
#if SSLEAY_VERSION_NUMBER >= 0x0922
- SSL_set_session_id_context(temp_ssl, "Citadel SID", 14);
+ SSL_set_session_id_context(temp_ssl, (const unsigned char*) "Citadel SID", 14);
#endif
if (!access(EGD_POOL, F_OK))
}
ipc->ssl = temp_ssl;
- BIO_set_close(ipc->ssl->rbio, BIO_NOCLOSE);
+ if (BIO_set_close(ipc->ssl->rbio, BIO_NOCLOSE))
{
int bits, alg_bits;
/* ************************************************************************** */
-/* Stuff below this line is not for public consumption */
+/* Stuff below this line is not for public consumption */
/* ************************************************************************** */
-INLINE void CtdlIPC_lock(CtdlIPC *ipc)
-{
- if (ipc->network_status_cb) ipc->network_status_cb(1);
-#ifdef THREADED_CLIENT
- pthread_mutex_lock(&(ipc->mutex));
-#endif
-}
-
-
-INLINE void CtdlIPC_unlock(CtdlIPC *ipc)
-{
-#ifdef THREADED_CLIENT
- pthread_mutex_unlock(&(ipc->mutex));
-#endif
- if (ipc->network_status_cb) ipc->network_status_cb(0);
-}
-
-
/* Read a listing from the server up to 000. Append to dest if it exists */
char *CtdlIPCReadListing(CtdlIPC *ipc, char *dest)
{
}
-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;
-
- memset(&sin, 0, sizeof(sin));
- sin.sin_family = AF_INET;
+ struct in6_addr serveraddr;
+ struct addrinfo hints;
+ struct addrinfo *res = NULL;
+ struct addrinfo *ai = NULL;
+ int rc = (-1);
+ int sock = (-1);
- pse = getservbyname(service, protocol);
- if (pse != NULL) {
- sin.sin_port = pse->s_port;
- }
- else if (atoi(service) > 0) {
- sin.sin_port = htons(atoi(service));
- }
- else {
- sin.sin_port = htons(defaultPort);
+ if ((host == NULL) || IsEmptyStr(host)) {
+ service = DEFAULT_HOST ;
}
- 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 (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;