X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=citadel%2Futillib%2Fcitadel_ipc.c;h=69a73116f376f683c1f0b787c3442a39c853a691;hb=6106c1da54f0923550c7bdceb45246fb88e9ea19;hp=0428937ad1ad469e5480e898fac6f3e9c005cc5e;hpb=5f64f2053612a1c695a94c7c7008182fc7058182;p=citadel.git diff --git a/citadel/utillib/citadel_ipc.c b/citadel/utillib/citadel_ipc.c index 0428937ad..69a73116f 100644 --- a/citadel/utillib/citadel_ipc.c +++ b/citadel/utillib/citadel_ipc.c @@ -1,5 +1,4 @@ -/* $Id$ - * +/* * Copyright (c) 1987-2009 by the citadel.org team * * This program is free software; you can redistribute it and/or modify @@ -756,6 +755,8 @@ int CtdlIPCServerInfo(CtdlIPC *ipc, char *cret) break; case 22: strcpy(ipc->ServInfo.svn_revision, buf); break; + case 24: ipc->ServInfo.guest_logins = atoi(buf); + break; } } @@ -786,7 +787,7 @@ int CtdlIPCReadDirectory(CtdlIPC *ipc, char **listing, char *cret) int CtdlIPCSetLastRead(CtdlIPC *ipc, long msgnum, char *cret) { register int ret; - char aaa[16]; + char aaa[64]; if (!cret) return -2; @@ -964,7 +965,7 @@ int CtdlIPCRoomInfo(CtdlIPC *ipc, char **iret, char *cret) /* DELE */ int CtdlIPCDeleteMessage(CtdlIPC *ipc, long msgnum, char *cret) { - char aaa[16]; + char aaa[64]; if (!cret) return -2; if (!msgnum) return -2; @@ -997,7 +998,7 @@ int CtdlIPCMoveMessage(CtdlIPC *ipc, int copy, long msgnum, const char *destroom /* KILL */ int CtdlIPCDeleteRoom(CtdlIPC *ipc, int for_real, char *cret) { - char aaa[16]; + char aaa[64]; if (!cret) return -2; @@ -1108,7 +1109,7 @@ int CtdlIPCValidateUser(CtdlIPC *ipc, const char *username, int axlevel, char *c 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; @@ -1123,7 +1124,7 @@ int CtdlIPCValidateUser(CtdlIPC *ipc, const char *username, int axlevel, char *c /* 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; @@ -1610,7 +1611,7 @@ int CtdlIPCGetInstantMessage(CtdlIPC *ipc, char **listing, char *cret) /* 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; @@ -1668,7 +1669,7 @@ int CtdlIPCListUsersWithBios(CtdlIPC *ipc, char **listing, char *cret) /* STEL */ int CtdlIPCStealthMode(CtdlIPC *ipc, int mode, char *cret) { - char aaa[16]; + char aaa[64]; if (!cret) return -1; @@ -1680,7 +1681,7 @@ int CtdlIPCStealthMode(CtdlIPC *ipc, int mode, char *cret) /* TERM */ int CtdlIPCTerminateSession(CtdlIPC *ipc, int sid, char *cret) { - char aaa[16]; + char aaa[64]; if (!cret) return -1; @@ -1860,10 +1861,15 @@ int CtdlIPCAideSetUserParameters(CtdlIPC *ipc, const struct ctdluser *uret, char /* 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; @@ -2001,7 +2007,7 @@ int CtdlIPCSetRoomNetworkConfig(CtdlIPC *ipc, const char *listing, char *cret) /* REQT */ int CtdlIPCRequestClientLogout(CtdlIPC *ipc, int session, char *cret) { - char aaa[16]; + char aaa[64]; if (!cret) return -2; if (session < 0) return -2; @@ -2090,7 +2096,7 @@ int CtdlIPCStartEncryption(CtdlIPC *ipc, char *cret) } 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; @@ -2179,28 +2185,10 @@ int CtdlIPCMessageBaseCheck(CtdlIPC *ipc, char **mret, char *cret) /* ************************************************************************** */ -/* 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) { @@ -2626,55 +2614,79 @@ int CtdlIPCGenericCommand(CtdlIPC *ipc, } -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; @@ -3252,14 +3264,36 @@ CtdlIPC* CtdlIPC_new(int argc, char **argv, char *hostbuf, char *portbuf) } 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;