From b533ef8233e7db0ea7f4aac6d45e630d68e6a201 Mon Sep 17 00:00:00 2001 From: Michiel Broek Date: Sat, 29 Jan 2011 13:03:22 +0100 Subject: [PATCH] 0.95.12 develop 1, a lot of systems calls changed to universal IPv4/IPv6 functions --- ChangeLog | 17 ++++++ TODO | 4 +- configure | 2 +- configure.ac | 2 +- lib/nntp.c | 97 ++++++++++++++++--------------- lib/pop3.c | 124 +++++++++++++++++++-------------------- lib/smtp.c | 147 ++++++++++++++++++++++++----------------------- lib/virscan.c | 47 +++++++++------ mbcico/binkp.c | 7 +-- mbcico/opentcp.c | 125 ++++++++++++++++++++++++++-------------- mbcico/session.c | 60 +++++++++++++------ mbnntp/mbnntp.c | 55 +++++++++++++----- mbtask/mbtask.c | 11 ++-- mbtask/ping.c | 5 +- unix/mblogin.c | 34 ++--------- 15 files changed, 419 insertions(+), 318 deletions(-) diff --git a/ChangeLog b/ChangeLog index ffc499b4..f0fa83ed 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ + mbselib: + The virus stream scanner can now uses IPv4 and/or IPv6 to + connect to the clamav server and can use server clusters too. + Connect smtp, pop3 and nntp upgraded to IPv4 and IPv6 use. + + mbcico: + Can accept both IPv6 and IPv4 calls. + Can call IPv4 and IPv6 nodes. + + mbtask: + Upgraded the ping function to newer system calls. Note that + for now I leave the interbbs chat IPv4 only. + + mblogin: + Don't use gethostbyname function. + + v0.95.11 14-Jan-2011 (patches by Scott Street). mbselib: diff --git a/TODO b/TODO index 63e43627..0f583356 100644 --- a/TODO +++ b/TODO @@ -1,6 +1,6 @@ - MBSE BBS V0.95.6 TODO list. - --------------------------- + MBSE BBS V0.95.12 TODO list. + ---------------------------- These are a list of things that must be implemented one way or another. Some things are urgent and necessary to operate the bbs diff --git a/configure b/configure index 2b0d47aa..fe49a55a 100755 --- a/configure +++ b/configure @@ -2274,7 +2274,7 @@ SUBDIRS="lib mbcico mbfido mbmon mbsebbs mbutils mbnntp mbtask mbsetup unix lang PACKAGE="mbsebbs" MAJOR="0" MINOR="95" -REVISION="11" +REVISION="12d1" VERSION="$MAJOR.$MINOR.$REVISION" COPYRIGHT="Copyright (C) 1997-2011 Michiel Broek, All Rights Reserved" SHORTRIGHT="Copyright (C) 1997-2011 M. Broek" diff --git a/configure.ac b/configure.ac index 4243215d..fa83e0ef 100644 --- a/configure.ac +++ b/configure.ac @@ -12,7 +12,7 @@ AC_SUBST(SUBDIRS) PACKAGE="mbsebbs" MAJOR="0" MINOR="95" -REVISION="11" +REVISION="12d1" VERSION="$MAJOR.$MINOR.$REVISION" COPYRIGHT="Copyright (C) 1997-2011 Michiel Broek, All Rights Reserved" SHORTRIGHT="Copyright (C) 1997-2011 M. Broek" diff --git a/lib/nntp.c b/lib/nntp.c index 0557429f..beea92c2 100644 --- a/lib/nntp.c +++ b/lib/nntp.c @@ -32,19 +32,15 @@ #include "mbinet.h" -static int nntpsock = -1; /* TCP/IP socket */ -struct hostent *nhp; /* Host info remote */ -struct servent *nsp; /* Service information */ -struct sockaddr_in nntp_loc; /* For local socket address */ -struct sockaddr_in nntp_rem; /* For remote socket address */ - +static int nntpsock = -1; /* TCP/IP socket */ int nntp_connect(void) { - socklen_t addrlen; - char *p; + char *q, *ipver = NULL, ipstr[INET6_ADDRSTRLEN], servport[10]; + struct addrinfo hints, *res = NULL, *p; + int rc; if (nntpsock != -1) return nntpsock; @@ -54,46 +50,57 @@ int nntp_connect(void) return -1; } - Syslog('+', "NNTP: connecting host: %s:%d", CFG.nntpnode, CFG.nntpport); - memset(&nntp_loc, 0, sizeof(struct sockaddr_in)); - memset(&nntp_rem, 0, sizeof(struct sockaddr_in)); + snprintf(servport, 9, "%d", CFG.nntpport); + Syslog('+', "NNTP: connecting host: %s port %s", CFG.nntpnode, servport); + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; - nntp_rem.sin_family = AF_INET; - - if ((nhp = gethostbyname(CFG.nntpnode)) == NULL) { - WriteError("NNTP: can't find host %s", CFG.nntpnode); - return -1; + if ((rc = getaddrinfo(CFG.popnode, servport, &hints, &res)) != 0) { + WriteError("getaddrinfo %s:%s %s\n", CFG.popnode, servport, gai_strerror(rc)); + return -1; } - nntp_rem.sin_addr.s_addr = ((struct in_addr *)(nhp->h_addr))->s_addr; - nntp_rem.sin_port = htons(CFG.nntpport); + for (p = res; p != NULL; p = p->ai_next) { + void *addr; - if ((nntpsock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { - WriteError("$NNTP: unable to create tcp socket"); - return -1; + if (p->ai_family == AF_INET) { + struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr; + addr = &(ipv4->sin_addr); + ipver = (char *)"IPv4"; + } else { + struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr; + addr = &(ipv6->sin6_addr); + ipver = (char *)"IPv6"; + } + inet_ntop(p->ai_family, addr, ipstr, sizeof ipstr); + Syslog('+', "Trying %s %s port %s", ipver, ipstr, servport); + + if ((nntpsock = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) { + WriteError("$socket()"); + return -1; + } else { + if (connect(nntpsock, p->ai_addr, p->ai_addrlen) == -1) { + WriteError("$connect %s port %s", ipstr, servport); + close(nntpsock); + } else { + break; + } + } + } + if (p == NULL) { + return -1; /* Not connected */ } - if (connect(nntpsock, (struct sockaddr *)&nntp_rem, sizeof(struct sockaddr_in)) == -1) { - WriteError("$NNTP: cannot connect tcp socket"); - return -1; - } - - addrlen = sizeof(struct sockaddr_in); - - if (getsockname(nntpsock, (struct sockaddr *)&nntp_loc, &addrlen) == -1) { - WriteError("$NNTP: unable to read socket address"); - return -1; - } - - p = nntp_receive(); - if (strlen(p) == 0) { + q = nntp_receive(); + if (strlen(q) == 0) { WriteError("NNTP: no response"); nntp_close(); return -1; } - Syslog('+', "NNTP: %s", p); + Syslog('+', "NNTP: %s", q); - if ((strncmp(p, "480", 3) == 0) || CFG.nntpforceauth) { + if ((strncmp(q, "480", 3) == 0) || CFG.nntpforceauth) { /* * Must login with username and password */ @@ -102,8 +109,8 @@ int nntp_connect(void) nntp_close(); return -1; } - } else if (strncmp(p, "200", 3)) { - WriteError("NNTP: bad response: %s", p); + } else if (strncmp(q, "200", 3)) { + WriteError("NNTP: bad response: %s", q); // nntp_close(); FIXME: Don't close, the other end might have done that already // If we do also, this program hangs. Must be fixed! return -1; @@ -112,20 +119,20 @@ int nntp_connect(void) if (CFG.modereader) { Syslog('+', "NNTP: setting mode reader"); nntp_send((char *)"MODE READER\r\n"); - p = nntp_receive(); - Syslog('+', "NNTP: %s", p); - if (strncmp(p, "480", 3) == 0) { + q = nntp_receive(); + Syslog('+', "NNTP: %s", q); + if (strncmp(q, "480", 3) == 0) { /* * Must login with username and password */ - Syslog('+', "NNTP: %s", p); + Syslog('+', "NNTP: %s", q); if (nntp_auth() == FALSE) { WriteError("NNTP: authorisation failure"); nntp_close(); return -1; } - } else if (strncmp(p, "200", 3)) { - WriteError("NNTP: bad response: %s", p); + } else if (strncmp(q, "200", 3)) { + WriteError("NNTP: bad response: %s", q); nntp_close(); return -1; } diff --git a/lib/pop3.c b/lib/pop3.c index 8aca40c9..094e92d3 100644 --- a/lib/pop3.c +++ b/lib/pop3.c @@ -1,10 +1,9 @@ /***************************************************************************** * - * $Id: pop3.c,v 1.8 2007/08/25 15:29:14 mbse Exp $ * Purpose ...............: MBSE BBS Internet Library * ***************************************************************************** - * Copyright (C) 1997-2004 + * Copyright (C) 1997-2011 * * Michiel Broek FIDO: 2:280/2802 * Beekmansbos 10 @@ -33,81 +32,78 @@ #include "mbinet.h" -static int pop3sock = -1; /* TCP/IP socket */ -struct hostent *php; /* Host info remote */ -struct servent *psp; /* Service information */ -struct sockaddr_in pop3_loc; /* For local socket address */ -struct sockaddr_in pop3_rem; /* For remote socket address */ +static int pop3sock = -1; /* TCP/IP socket */ int pop3_connect(void) { - socklen_t addrlen; - char *p; + char *q, *ipver = NULL, ipstr[INET6_ADDRSTRLEN]; + struct addrinfo hints, *res = NULL, *p; + int rc; - if (!strlen(CFG.popnode)) { - WriteError("POP3: host not configured"); - return -1; + if (!strlen(CFG.popnode)) { + WriteError("POP3: host not configured"); + return -1; + } + + Syslog('+', "POP3: connecting host: %s", CFG.popnode); + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + + if ((rc = getaddrinfo(CFG.popnode, "pop3", &hints, &res)) != 0) { + WriteError("getaddrinfo %s: %s\n", CFG.popnode, gai_strerror(rc)); + return -1; + } + + for (p = res; p != NULL; p = p->ai_next) { + void *addr; + + if (p->ai_family == AF_INET) { + struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr; + addr = &(ipv4->sin_addr); + ipver = (char *)"IPv4"; + } else { + struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr; + addr = &(ipv6->sin6_addr); + ipver = (char *)"IPv6"; } + inet_ntop(p->ai_family, addr, ipstr, sizeof ipstr); + Syslog('+', "Trying %s %s port pop3", ipver, ipstr); - Syslog('+', "POP3: connecting host: %s", CFG.popnode); - memset(&pop3_loc, 0, sizeof(struct sockaddr_in)); - memset(&pop3_rem, 0, sizeof(struct sockaddr_in)); - - pop3_rem.sin_family = AF_INET; - - if ((php = gethostbyname(CFG.popnode)) == NULL) { - WriteError("POP3: can't find host %s", CFG.popnode); - return -1; + if ((pop3sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) { + WriteError("$socket()"); + return -1; + } else { + if (connect(pop3sock, p->ai_addr, p->ai_addrlen) == -1) { + WriteError("$connect %s port pop3", ipstr); + close(pop3sock); + } else { + break; + } } + } + if (p == NULL) { + return -1; /* Not connected */ + } - pop3_rem.sin_addr.s_addr = ((struct in_addr *)(php->h_addr))->s_addr; + q = pop3_receive(); + if (strlen(q) == 0) { + WriteError("POP3: no response from server"); + pop3_close(); + return -1; + } - if ((psp = getservbyname("pop3", "tcp")) == NULL) { - /* - * RedHat doesn't follow IANA specs and uses pop-3 in /etc/services - */ - if ((psp = getservbyname("pop-3", "tcp")) == NULL) { - WriteError("POP3: can't find service port for pop3/tcp"); - return -1; - } - } - pop3_rem.sin_port = psp->s_port; + if (strncmp(q, "+OK", 3)) { + WriteError("POP3: bad response: %s", q); + pop3_close(); + return -1; + } - if ((pop3sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { - WriteError("$POP3: unable to create tcp socket"); - return -1; - } + Syslog('+', "POP3: %s", q); - if (connect(pop3sock, (struct sockaddr *)&pop3_rem, sizeof(struct sockaddr_in)) == -1) { - WriteError("$POP3: cannot connect tcp socket"); - return -1; - } - - addrlen = sizeof(struct sockaddr_in); - - if (getsockname(pop3sock, (struct sockaddr *)&pop3_loc, &addrlen) == -1) { - WriteError("$POP3: unable to read socket address"); - return -1; - } - - p = pop3_receive(); - if (strlen(p) == 0) { - WriteError("POP3: no response from server"); - pop3_close(); - return -1; - } - - if (strncmp(p, "+OK", 3)) { - WriteError("POP3: bad response: %s", p); - pop3_close(); - return -1; - } - - Syslog('+', "POP3: %s", p); - - return pop3sock; + return pop3sock; } diff --git a/lib/smtp.c b/lib/smtp.c index aab6bc04..d9626703 100644 --- a/lib/smtp.c +++ b/lib/smtp.c @@ -1,10 +1,9 @@ /***************************************************************************** * - * $Id: smtp.c,v 1.10 2007/08/25 15:29:14 mbse Exp $ * Purpose ...............: MBSE BBS Internet Library * ***************************************************************************** - * Copyright (C) 1997-2005 + * Copyright (C) 1997-2011 * * Michiel Broek FIDO: 2:280/2802 * Beekmansbos 10 @@ -34,84 +33,86 @@ static int smtpsock = -1; /* TCP/IP socket */ -struct hostent *shp; /* Host info remote */ -struct servent *ssp; /* Service information */ -struct sockaddr_in smtp_loc; /* For local socket address */ -struct sockaddr_in smtp_rem; /* For remote socket address */ int smtp_connect(void) { - socklen_t addrlen; - char *p, temp[40]; - - if (smtpsock != -1) - return smtpsock; - - if (!strlen(CFG.smtpnode)) { - WriteError("SMTP: host not configured"); - return -1; - } - - Syslog('+', "SMTP: connecting host: %s", CFG.smtpnode); - memset(&smtp_loc, 0, sizeof(struct sockaddr_in)); - memset(&smtp_rem, 0, sizeof(struct sockaddr_in)); - - smtp_rem.sin_family = AF_INET; - - if ((shp = gethostbyname(CFG.smtpnode)) == NULL) { - WriteError("SMTP: can't find host %s", CFG.smtpnode); - return -1; - } - - smtp_rem.sin_addr.s_addr = ((struct in_addr *)(shp->h_addr))->s_addr; - - if ((ssp = getservbyname("smtp", "tcp")) == NULL) { - WriteError("SMTP: can't find service port for smtp/tcp"); - return -1; - } - smtp_rem.sin_port = ssp->s_port; - - if ((smtpsock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { - WriteError("$SMTP: unable to create tcp socket"); - return -1; - } - - if (connect(smtpsock, (struct sockaddr *)&smtp_rem, sizeof(struct sockaddr_in)) == -1) { - WriteError("$SMTP: can't connect tcp socket"); - return -1; - } - - addrlen = sizeof(struct sockaddr_in); - - if (getsockname(smtpsock, (struct sockaddr *)&smtp_loc, &addrlen) == -1) { - WriteError("$SMTP: unable to read socket address"); - return -1; - } - - p = smtp_receive(); - if (strlen(p) == 0) { - WriteError("SMTP: no response"); - smtp_close(); - return -1; - } - - if (strncmp(p, "220", 3)) { - WriteError("SMTP: bad response: %s", p); - smtp_close(); - return -1; - } - - Syslog('+', "SMTP: %s", p); - - snprintf(temp, 40, "HELO %s\r\n", CFG.sysdomain); - if (smtp_cmd(temp, 250)) { - smtp_close(); - return -1; - } + char *q, *ipver = NULL, ipstr[INET6_ADDRSTRLEN], temp[41]; + struct addrinfo hints, *res = NULL, *p; + int rc; + if (smtpsock != -1) return smtpsock; + + if (!strlen(CFG.smtpnode)) { + WriteError("SMTP: host not configured"); + return -1; + } + + Syslog('+', "SMTP: connecting host: %s", CFG.smtpnode); + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + + if ((rc = getaddrinfo(CFG.popnode, "smtp", &hints, &res)) != 0) { + WriteError("getaddrinfo %s: %s\n", CFG.popnode, gai_strerror(rc)); + return -1; + } + + for (p = res; p != NULL; p = p->ai_next) { + void *addr; + + if (p->ai_family == AF_INET) { + struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr; + addr = &(ipv4->sin_addr); + ipver = (char *)"IPv4"; + } else { + struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr; + addr = &(ipv6->sin6_addr); + ipver = (char *)"IPv6"; + } + inet_ntop(p->ai_family, addr, ipstr, sizeof ipstr); + Syslog('+', "Trying %s %s port pop3", ipver, ipstr); + + if ((smtpsock = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) { + WriteError("$socket()"); + return -1; + } else { + if (connect(smtpsock, p->ai_addr, p->ai_addrlen) == -1) { + WriteError("$connect %s port pop3", ipstr); + close(smtpsock); + } else { + break; + } + } + } + if (p == NULL) { + return -1; /* Not connected */ + } + + q = smtp_receive(); + if (strlen(q) == 0) { + WriteError("SMTP: no response"); + smtp_close(); + return -1; + } + + if (strncmp(q, "220", 3)) { + WriteError("SMTP: bad response: %s", q); + smtp_close(); + return -1; + } + + Syslog('+', "SMTP: %s", q); + + snprintf(temp, 40, "HELO %s\r\n", CFG.sysdomain); + if (smtp_cmd(temp, 250)) { + smtp_close(); + return -1; + } + + return smtpsock; } diff --git a/lib/virscan.c b/lib/virscan.c index 62ee9cda..d5d6703d 100644 --- a/lib/virscan.c +++ b/lib/virscan.c @@ -1,10 +1,9 @@ /***************************************************************************** * - * $Id: virscan.c,v 1.3 2008/02/25 12:11:42 mbse Exp $ * Purpose ...............: Scan a file for virusses * ***************************************************************************** - * Copyright (C) 1997-2008 + * Copyright (C) 1997-2011 * * Michiel Broek FIDO: 2:280/2802 * Beekmansbos 10 @@ -43,43 +42,55 @@ extern pid_t mypid; * 1 = Virus found. * 2 = Internal error. */ -int clam_stream_check(char *server, char *port, char *filename) +int clam_stream_check(char *servname, char *servport, char *filename) { struct sockaddr_in sa_in; - struct addrinfo hints, *res; + struct addrinfo hints, *res = NULL, *p; int s, ss, buf_len = 0, err; - char buf[1024], *buf_c, *port_s; + char buf[1024], *buf_c, *port_s, *ipver = NULL, ipstr[INET6_ADDRSTRLEN]; FILE *fp; - Syslog('f', "clam_stream_check(%s, %s, %s)", server, port, filename); + Syslog('f', "clam_stream_check(%s, %s, %s)", servname, servport, filename); memset(&hints, 0, sizeof(hints)); - hints.ai_family = PF_INET; + hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; - if ((err = getaddrinfo(server, port, &hints, &res)) != 0) { - WriteError("getaddrinfo(%s:%s): %s\n", server, port, gai_strerror(err)); + if ((err = getaddrinfo(servname, servport, &hints, &res)) != 0) { + WriteError("getaddrinfo(%s:%s): %s\n", servname, servport, gai_strerror(err)); return 2; } - while (res) { - s = socket(PF_INET, SOCK_STREAM, 0); - if (s == -1) { + for (p = res; p != NULL; p = p->ai_next) { + void *addr; + + if (p->ai_family == AF_INET) { + struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr; + addr = &(ipv4->sin_addr); + ipver = (char *)"IPv4"; + } else { + struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr; + addr = &(ipv6->sin6_addr); + ipver = (char *)"IPv6"; + } + inet_ntop(p->ai_family, addr, ipstr, sizeof ipstr); + Syslog('+', "Trying %s %s port %s", ipver, ipstr, servport); + + if ((s = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) { WriteError("$socket()"); return 2; } - if (connect(s, res->ai_addr, sizeof(struct sockaddr)) == -1) { - struct sockaddr_in *sa = (struct sockaddr_in *)res->ai_addr; - WriteError("$connect(%s:%d)", inet_ntoa(sa->sin_addr), (int)ntohs(sa->sin_port)); - res = res->ai_next; + if (connect(s, p->ai_addr, p->ai_addrlen) == -1) { + WriteError("$connect %s port %s", ipstr, servport); + p = p->ai_next; close(s); } else { break; } } - if (res == NULL) { - WriteError("unable to connect to %s", server); + if (p == NULL) { + WriteError("unable to connect to %s", servname); return 2; } diff --git a/mbcico/binkp.c b/mbcico/binkp.c index 373dd333..b7eb123f 100644 --- a/mbcico/binkp.c +++ b/mbcico/binkp.c @@ -1,11 +1,10 @@ /***************************************************************************** * - * $Id: binkp.c,v 1.135 2007/08/26 14:02:28 mbse Exp $ * Purpose .................: Fidonet binkp protocol * Binkp protocol copyright : Dima Maloff. * ***************************************************************************** - * Copyright (C) 1997-2007 + * Copyright (C) 1997-2011 * * Michiel Broek FIDO: 2:280/2802 * Beekmansbos 10 @@ -72,7 +71,7 @@ extern char *tempinbound; extern char *ttystat[]; extern int Loaded; extern pid_t mypid; -extern struct sockaddr_in peeraddr; +extern struct sockaddr_in peeraddr4; extern int most_debug; extern int laststat; extern int crashme; @@ -693,7 +692,7 @@ SM_STATE(WaitConn) SM_ERROR; } - if (!CFG.NoMD5 && ((bp.MD_Challenge = MD_getChallenge(NULL, &peeraddr)) != NULL)) { + if (!CFG.NoMD5 && ((bp.MD_Challenge = MD_getChallenge(NULL, &peeraddr4)) != NULL)) { /* * Answering site MUST send CRAM message as very first M_NUL */ diff --git a/mbcico/opentcp.c b/mbcico/opentcp.c index 13e8b8e8..caca4c8f 100644 --- a/mbcico/opentcp.c +++ b/mbcico/opentcp.c @@ -1,10 +1,9 @@ /***************************************************************************** * - * $Id: opentcp.c,v 1.27 2006/07/17 18:54:16 mbse Exp $ * Purpose ...............: Fidonet mailer * ***************************************************************************** - * Copyright (C) 1997-2005 + * Copyright (C) 1997-2011 * * Michiel Broek FIDO: 2:280/2802 * Beekmansbos 10 @@ -59,26 +58,32 @@ static int tcp_is_open = FALSE; -/* opentcp() was rewritten by Martin Junius */ - -int opentcp(char *name) +/* + * Parameter may be: + * host.example.com + * host.example.com:portnumber + * host.example.com:portname + */ +int opentcp(char *servname) { struct servent *se; - struct hostent *he; struct sockaddr_in server; - int a1, a2, a3, a4, GotPort = FALSE; - char *errmsg, *portname; - short portnum; + int rc, GotPort = FALSE; + char *portname, *ipver = NULL, servport[20], ipstr[INET6_ADDRSTRLEN]; + u_int16_t portnum; + struct addrinfo hints, *res=NULL, *p; - Syslog('+', "Open TCP connection to \"%s\"", MBSE_SS(name)); + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + Syslog('+', "Open TCP connection to \"%s\"", MBSE_SS(servname)); tcp_is_open = FALSE; - server.sin_family = AF_INET; /* * Get port number from name argument if there is a : part */ - if ((portname = strchr(name,':'))) { + if ((portname = strchr(servname,':'))) { *portname++='\0'; if ((portnum = atoi(portname))) { server.sin_port=htons(portnum); @@ -112,23 +117,16 @@ int opentcp(char *name) default: server.sin_port = htons(FIDOPORT); } } + snprintf(servport, 19, "%d", ntohs(server.sin_port)); /* - * Get IP address for the hostname + * Lookup hostname and return list of IPv4 and or IPv6 addresses. */ - if (sscanf(name,"%d.%d.%d.%d",&a1,&a2,&a3,&a4) == 4) - server.sin_addr.s_addr = inet_addr(name); - else if ((he = gethostbyname(name))) - memcpy(&server.sin_addr,he->h_addr,he->h_length); - else { - switch (h_errno) { - case HOST_NOT_FOUND: errmsg = (char *)"Authoritative: Host not found"; break; - case TRY_AGAIN: errmsg = (char *)"Non-Authoritive: Host not found"; break; - case NO_RECOVERY: errmsg = (char *)"Non recoverable errors"; break; - case NO_ADDRESS: errmsg = (char *)"Host has no IP address"; break; - default: errmsg = (char *)"Unknown error"; break; - } - Syslog('+', "No IP address for %s: %s\n", name, errmsg); + if ((rc = getaddrinfo(servname, servport, &hints, &res))) { + if (rc == EAI_SYSTEM) + WriteError("opentcp: getaddrinfo() failed"); + else + Syslog('+', "Host not found --> %s\n", gai_strerror(rc)); return -1; } @@ -142,29 +140,68 @@ int opentcp(char *name) close(0); close(1); - if ((fd = socket(AF_INET,SOCK_STREAM,0)) != 0) { - WriteError("$Cannot create socket (got %d, expected 0)", fd); - open("/dev/null",O_RDONLY); - open("/dev/null",O_WRONLY); - return -1; + /* + * In case a node has a A and AAAA dns entry, we now have a list of + * possible connections to make, we try them until we succeed. + * Most likely, the first one is ok. + * Nice that this also works for clustered hosts, not that we will + * find any in fidonet, but ..... + */ + for (p = res; p != NULL; p = p->ai_next) { + void *addr; + + rc = 0; + if (p->ai_family == AF_INET) { + struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr; + addr = &(ipv4->sin_addr); + ipver = (char *)"IPv4"; + } else { + struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr; + addr = &(ipv6->sin6_addr); + ipver = (char *)"IPv6"; + } + inet_ntop(p->ai_family, addr, ipstr, sizeof ipstr); + Syslog('+', "Trying %s %s port %s", ipver, ipstr, servport); + + if ((fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) != 0) { + if (fd > 0) + WriteError("Cannot create socket (got %d, expected 0)", fd); + else + WriteError("$Cannot create socket"); + rc = -1; + } else { + if (dup(fd) != 1) { + WriteError("$Cannot dup socket"); + rc = -1; + } else { + clearerr(stdin); + clearerr(stdout); + if (connect(fd, p->ai_addr, p->ai_addrlen) == -1) { + Syslog('+', "$Cannot connect %s port %s", ipstr, servport); + close(fd+1); /* close duped socket */ + close(fd); /* close this socket */ + rc = -1; + } else { + /* + * Connected, leave this loop + */ + break; + } + } + } } - if (dup(fd) != 1) { - WriteError("$Cannot dup socket"); - open("/dev/null",O_WRONLY); - return -1; - } - clearerr(stdin); - clearerr(stdout); - if (connect(fd,(struct sockaddr *)&server,sizeof(server)) == -1) { - Syslog('+', "$Cannot connect %s",inet_ntoa(server.sin_addr)); + if (rc == -1) { + open("/dev/null", O_RDONLY); + open("/dev/null", O_WRONLY); + freeaddrinfo(res); return -1; } f_flags=0; - - Syslog('+', "Established %s/TCP connection with %s, port %d", + Syslog('+', "Established %s/TCP %s connection with %s, port %s", (tcp_mode == TCPMODE_IFC) ? "IFC":(tcp_mode == TCPMODE_ITN) ?"ITN":(tcp_mode == TCPMODE_IBN) ? "IBN":"Unknown", - inet_ntoa(server.sin_addr), (int)ntohs(server.sin_port)); + ipver, ipstr, servport); + freeaddrinfo(res); c_start = time(NULL); carrier = TRUE; tcp_is_open = TRUE; @@ -181,7 +218,7 @@ void closetcp(void) if (!tcp_is_open) return; - shutdown(fd, 2); + shutdown(fd, SHUT_RDWR); signal(SIGHUP, SIG_IGN); signal(SIGPIPE, SIG_IGN); diff --git a/mbcico/session.c b/mbcico/session.c index fa68e866..59dd68f0 100644 --- a/mbcico/session.c +++ b/mbcico/session.c @@ -1,10 +1,9 @@ /***************************************************************************** * - * $Id: session.c,v 1.37 2007/10/14 13:15:34 mbse Exp $ * Purpose ...............: Fidonet mailer * ***************************************************************************** - * Copyright (C) 1997-2007 + * Copyright (C) 1997-2011 * * Michiel Broek FIDO: 2:280/2802 * Beekmansbos 10 @@ -63,7 +62,8 @@ int session_state = STATE_BAD; static char *data=NULL; -struct sockaddr_in peeraddr; +struct sockaddr_in peeraddr4; +struct sockaddr_in6 peeraddr6; char *typestr(int); @@ -103,6 +103,17 @@ void geoiplookup(GeoIP* gi, char *hostname, int i) Syslog('+', "GeoIP location: %s, %s %s\n", country_name, country_code, country_continent); } } + if (GEOIP_COUNTRY_EDITION_V6 == i) { + country_id = GeoIP_id_by_name_v6(gi, hostname); + country_code = GeoIP_country_code[country_id]; + country_name = GeoIP_country_name[country_id]; + country_continent = GeoIP_country_continent[country_id]; + if (country_code == NULL) { + Syslog('+', "%s: IP Address not found\n", GeoIPDBDescription[i]); + } else { + Syslog('+', "GeoIP location: %s, %s %s\n", country_name, country_code, country_continent); + } + } } #endif @@ -111,12 +122,12 @@ void geoiplookup(GeoIP* gi, char *hostname, int i) int session(faddr *a, node *nl, int role, int tp, char *dt) { int rc = MBERR_OK; - socklen_t addrlen = sizeof(struct sockaddr_in); + socklen_t addrlen = sizeof(struct sockaddr_in6); fa_list *tmpl; int Fdo = -1, input_pipe[2], output_pipe[2]; pid_t ipid, opid; + char str[INET6_ADDRSTRLEN]; #ifdef HAVE_GEOIP_H - char *hostname; GeoIP *gi; #endif @@ -124,18 +135,26 @@ int session(faddr *a, node *nl, int role, int tp, char *dt) session_type = tp; nlent = nl; - if (getpeername(0,(struct sockaddr*)&peeraddr,&addrlen) == 0) { - Syslog('s', "TCP connection: len=%d, family=%hd, port=%hu, addr=%s", - addrlen,peeraddr.sin_family, peeraddr.sin_port, inet_ntoa(peeraddr.sin_addr)); + if (getpeername(0,(struct sockaddr *)&peeraddr6, &addrlen) == 0) { + /* + * Copy IPv4 part into the IPv6 structure. There has to be a better way + * to deal with mixed incoming sockets ??? + */ + memcpy(&peeraddr4, &peeraddr6, sizeof(struct sockaddr_in)); + if ((peeraddr6.sin6_family == AF_INET6) && (inet_ntop(AF_INET6, &peeraddr6.sin6_addr, str, sizeof(str)))) { + Syslog('s', "IPv6 TCP connection: len=%d, port=%hu, addr=%s", addrlen, ntohs(peeraddr6.sin6_port), str); + } else if ((peeraddr4.sin_family == AF_INET) && (inet_ntop(AF_INET, &peeraddr4.sin_addr, str, sizeof(str)))) { + Syslog('s', "IPv4 TCP connection: len=%d, port=%hu, addr=%s", addrlen, ntohs(peeraddr4.sin_port), str); + } if (role == 0) { if (tcp_mode == TCPMODE_IBN) { - Syslog('+', "Incoming IBN/TCP connection from %s", inet_ntoa(peeraddr.sin_addr)); + Syslog('+', "Incoming IBN/TCP connection from %s", str); IsDoing("Incoming IBN/TCP"); } else if (tcp_mode == TCPMODE_IFC) { - Syslog('+', "Incoming IFC/TCP connection from %s", inet_ntoa(peeraddr.sin_addr)); + Syslog('+', "Incoming IFC/TCP connection from %s", str); IsDoing("Incoming IFC/TCP"); } else if (tcp_mode == TCPMODE_ITN) { - Syslog('+', "Incoming ITN/TCP connection from %s", inet_ntoa(peeraddr.sin_addr)); + Syslog('+', "Incoming ITN/TCP connection from %s", str); IsDoing("Incoming ITN/TCP"); } else if (tcp_mode == TCPMODE_NONE) { WriteError("Unknown TCP connection, parameter missing"); @@ -145,13 +164,21 @@ int session(faddr *a, node *nl, int role, int tp, char *dt) session_flags |= SESSION_TCP; #ifdef HAVE_GEOIP_H - hostname = inet_ntoa(peeraddr.sin_addr); _GeoIP_setup_dbfilename(); - if (GeoIP_db_avail(GEOIP_COUNTRY_EDITION)) { - if ((gi = GeoIP_open_type(GEOIP_COUNTRY_EDITION, GEOIP_STANDARD)) != NULL) { - geoiplookup(gi, hostname, GEOIP_COUNTRY_EDITION); + if (peeraddr6.sin6_family == AF_INET6) { + if (GeoIP_db_avail(GEOIP_COUNTRY_EDITION_V6)) { + if ((gi = GeoIP_open_type(GEOIP_COUNTRY_EDITION_V6, GEOIP_STANDARD)) != NULL) { + geoiplookup(gi, str, GEOIP_COUNTRY_EDITION_V6); + } + GeoIP_delete(gi); + } + } else if (peeraddr6.sin6_family == AF_INET) { + if (GeoIP_db_avail(GEOIP_COUNTRY_EDITION)) { + if ((gi = GeoIP_open_type(GEOIP_COUNTRY_EDITION, GEOIP_STANDARD)) != NULL) { + geoiplookup(gi, str, GEOIP_COUNTRY_EDITION); + } + GeoIP_delete(gi); } - GeoIP_delete(gi); } #endif @@ -163,7 +190,6 @@ int session(faddr *a, node *nl, int role, int tp, char *dt) * since it's now on stadin and stdout. */ Fdo = dup(0); - Syslog('s', "session: new socket %d", Fdo); /* * Close stdin and stdout so that when we create the pipes to diff --git a/mbnntp/mbnntp.c b/mbnntp/mbnntp.c index eeac5d4f..5848b4ba 100644 --- a/mbnntp/mbnntp.c +++ b/mbnntp/mbnntp.c @@ -1,10 +1,9 @@ /***************************************************************************** * - * $Id: mbnntp.c,v 1.24 2007/10/14 15:29:58 mbse Exp $ * Purpose ...............: MBSE NNTP Server * ***************************************************************************** - * Copyright (C) 1997-2007 + * Copyright (C) 1997-2011 * * Michiel Broek FIDO: 2:280/2802 * Beekmansbos 10 @@ -42,7 +41,8 @@ time_t t_start; time_t t_end; char *envptr = NULL; -struct sockaddr_in peeraddr; +struct sockaddr_in peeraddr4; +struct sockaddr_in6 peeraddr6; pid_t mypid; unsigned int rcvdbytes = 0L; unsigned int sentbytes = 0L; @@ -124,6 +124,17 @@ void geoiplookup(GeoIP* gi, char *hostname, int i) Syslog('+', "GeoIP location: %s, %s %s\n", country_name, country_code, country_continent); } } + if (GEOIP_COUNTRY_EDITION_V6 == i) { + country_id = GeoIP_id_by_name_v6(gi, hostname); + country_code = GeoIP_country_code[country_id]; + country_name = GeoIP_country_name[country_id]; + country_continent = GeoIP_country_continent[country_id]; + if (country_code == NULL) { + Syslog('+', "%s: IP Address not found\n", GeoIPDBDescription[i]); + } else { + Syslog('+', "GeoIP location: %s, %s %s\n", country_name, country_code, country_continent); + } + } } #endif @@ -133,9 +144,9 @@ int main(int argc, char *argv[]) { struct passwd *pw; int i, rc; - socklen_t addrlen = sizeof(struct sockaddr_in); + socklen_t addrlen = sizeof(struct sockaddr_in6); + char str[INET6_ADDRSTRLEN]; #ifdef HAVE_GEOIP_H - char *hostname; GeoIP *gi; #endif @@ -190,18 +201,34 @@ int main(int argc, char *argv[]) if ((rc = rawport()) != 0) WriteError("Unable to set raw mode"); else { - if (getpeername(0,(struct sockaddr*)&peeraddr,&addrlen) == 0) { - Syslog('s', "TCP connection: len=%d, family=%hd, port=%hu, addr=%s", - addrlen,peeraddr.sin_family, peeraddr.sin_port, inet_ntoa(peeraddr.sin_addr)); - Syslog('+', "Incoming connection from %s", inet_ntoa(peeraddr.sin_addr)); + if (getpeername(0,(struct sockaddr*)&peeraddr6,&addrlen) == 0) { + /* + * Copy IPv4 part into the IPv6 structure. There has to be a better way + * to deal with mixed incoming sockets ??? + */ + memcpy(&peeraddr4, &peeraddr6, sizeof(struct sockaddr_in)); + if ((peeraddr6.sin6_family == AF_INET6) && (inet_ntop(AF_INET6, &peeraddr6.sin6_addr, str, sizeof(str)))) { + Syslog('+', "Incoming IPv6 connection from %s", str); + } else if ((peeraddr4.sin_family == AF_INET) && (inet_ntop(AF_INET, &peeraddr4.sin_addr, str, sizeof(str)))) { + Syslog('+', "Incoming IPv4 connection from %s", str); + } + #ifdef HAVE_GEOIP_H - hostname = inet_ntoa(peeraddr.sin_addr); _GeoIP_setup_dbfilename(); - if (GeoIP_db_avail(GEOIP_COUNTRY_EDITION)) { - if ((gi = GeoIP_open_type(GEOIP_COUNTRY_EDITION, GEOIP_STANDARD)) != NULL) { - geoiplookup(gi, hostname, GEOIP_COUNTRY_EDITION); + if (peeraddr6.sin6_family == AF_INET6) { + if (GeoIP_db_avail(GEOIP_COUNTRY_EDITION_V6)) { + if ((gi = GeoIP_open_type(GEOIP_COUNTRY_EDITION_V6, GEOIP_STANDARD)) != NULL) { + geoiplookup(gi, str, GEOIP_COUNTRY_EDITION_V6); + } + GeoIP_delete(gi); + } + } else if (peeraddr6.sin6_family == AF_INET) { + if (GeoIP_db_avail(GEOIP_COUNTRY_EDITION)) { + if ((gi = GeoIP_open_type(GEOIP_COUNTRY_EDITION, GEOIP_STANDARD)) != NULL) { + geoiplookup(gi, str, GEOIP_COUNTRY_EDITION); + } + GeoIP_delete(gi); } - GeoIP_delete(gi); } #endif #ifdef USE_NEWSGATE diff --git a/mbtask/mbtask.c b/mbtask/mbtask.c index d25723d1..da2d8933 100644 --- a/mbtask/mbtask.c +++ b/mbtask/mbtask.c @@ -1,10 +1,9 @@ /***************************************************************************** * - * $Id: mbtask.c,v 1.136 2008/03/09 12:21:26 mbse Exp $ * Purpose ...............: MBSE BBS Task Manager * ***************************************************************************** - * Copyright (C) 1997-2008 + * Copyright (C) 1997-2011 * * Michiel Broek FIDO: 2:280/2802 * Beekmansbos 10 @@ -987,7 +986,7 @@ void check_sema(void) void start_scheduler(int port) { struct passwd *pw; - char *cmd = NULL; + char *cmd = NULL, ipstr[INET6_ADDRSTRLEN]; if (nodaemon) printf("init fidonet\n"); @@ -1037,10 +1036,14 @@ void start_scheduler(int port) * Setup IBC socket */ if (Run_IBC) { + void *addr; + myaddr_in.sin_family = AF_INET; myaddr_in.sin_addr.s_addr = INADDR_ANY; myaddr_in.sin_port = port; - Syslog('+', "IBC: listen on %s, port %d", inet_ntoa(myaddr_in.sin_addr), ntohs(myaddr_in.sin_port)); + addr = &(myaddr_in.sin_addr); + inet_ntop(AF_INET, addr, ipstr, sizeof ipstr); + Syslog('+', "IBC: listen on %s, port %d", ipstr, ntohs(myaddr_in.sin_port)); ibcsock = socket(AF_INET, SOCK_DGRAM, 0); if (ibcsock == -1) { diff --git a/mbtask/ping.c b/mbtask/ping.c index 995028db..b79f1061 100644 --- a/mbtask/ping.c +++ b/mbtask/ping.c @@ -1,10 +1,9 @@ /***************************************************************************** * - * $Id: ping.c,v 1.41 2006/05/22 12:09:15 mbse Exp $ * Purpose ...............: mbtask - ping functions * ***************************************************************************** - * Copyright (C) 1997-2006 + * Copyright (C) 1997-2011 * * Michiel Broek FIDO: 2:280/2802 * Beekmansbos 10 @@ -349,7 +348,7 @@ void check_ping(void) ping_next = (time_t)(now + 20); - if (inet_aton(pingaddress, &paddr)) { + if (inet_pton(AF_INET, pingaddress, &paddr)) { pingresult[pingnr - 1] = FALSE; rc = ping_send(paddr); if (rc) { diff --git a/unix/mblogin.c b/unix/mblogin.c index 06f9c6d1..0c64cbaf 100644 --- a/unix/mblogin.c +++ b/unix/mblogin.c @@ -448,34 +448,12 @@ int main(int argc, char **argv) STRFCPY(tty, utent.ut_line); if (hflg) { -#ifdef UT_ADDR - struct hostent *he; - - /* - * Fill in the ut_addr field (remote login IP address). - * XXX - login from util-linux does it, but this is not - * the right place to do it. The program that starts - * login (telnetd, rlogind) knows the IP address, so it - * should create the utmp entry and fill in ut_addr. - * gethostbyname() is not 100% reliable (the remote host - * may be unknown, etc.). --marekm - */ - - if ((he = gethostbyname(hostname))) { - utent.ut_addr = *((int32_t *)(he->h_addr_list[0])); -#endif -#ifdef UT_HOST - strncpy(utent.ut_host, hostname, sizeof(utent.ut_host)); -#endif -#if HAVE_UTMPX_H - strncpy(utxent.ut_host, hostname, sizeof(utxent.ut_host)); -#endif - /* - * Add remote hostname to the environment. I think - * (not sure) I saw it once on Irix. --marekm - */ - addenv("REMOTEHOST", hostname); - } + /* + * Add remote hostname to the environment. I think + * (not sure) I saw it once on Irix. --marekm + */ + addenv("REMOTEHOST", hostname); + } #ifdef __linux__ /* workaround for init/getty leaving junk in ut_host at least in some