File nullmailer-1.10-ipv6.patch of Package nullmailer
diff -rU3 nullmailer-1.05/lib/connect.h nullmailer-1.05-ipv6/lib/connect.h
--- nullmailer-1.05/lib/connect.h 2007-10-08 00:48:27.000000000 +0200
+++ nullmailer-1.05-ipv6/lib/connect.h 2010-12-10 13:55:53.000000000 +0100
@@ -3,6 +3,8 @@
#include "mystring/mystring.h"
-extern int tcpconnect(const mystring& hostname, int port);
+typedef enum { v4_or_v6, v4_only, v6_only } tcpconn_addresstype_t;
+
+extern int tcpconnect(const mystring& hostname, const char* service, const tcpconn_addresstype_t addresstype);
#endif // NULLMAILER_CONNECT__H__
diff -rU3 nullmailer-1.05/lib/tcpconnect.cc nullmailer-1.05-ipv6/lib/tcpconnect.cc
--- nullmailer-1.05/lib/tcpconnect.cc 2007-10-10 07:02:13.000000000 +0200
+++ nullmailer-1.05-ipv6/lib/tcpconnect.cc 2010-12-10 14:07:56.000000000 +0100
@@ -26,43 +26,53 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
+#include <unistd.h>
#include "errcodes.h"
#include "connect.h"
-static int sethostbyname(const mystring& hostname, struct sockaddr_in& sa)
+int tcpconnect(const mystring& hostname, const char* service, const tcpconn_addresstype_t addresstype)
{
- struct hostent *he = gethostbyname(hostname.c_str());
- if(!he) {
- switch(h_errno) {
- case HOST_NOT_FOUND: return -ERR_HOST_NOT_FOUND;
- case NO_ADDRESS: return -ERR_NO_ADDRESS;
- case NO_RECOVERY: return -ERR_GHBN_FATAL;
- case TRY_AGAIN: return -ERR_GHBN_TEMP;
+ int family;
+ switch (addresstype) {
+ case v4_only: family = AF_INET; break;
+ case v6_only: family = AF_INET6; break;
+ default: family = AF_INET | AF_INET6;
+ }
+
+ struct addrinfo *ai = NULL,
+ hints = {AI_V4MAPPED | AI_ADDRCONFIG | AI_ALL, family, SOCK_STREAM, 0, 0, NULL, NULL, NULL};
+ if (addresstype == v6_only) { hints.ai_flags &= ~AI_ALL; }
+ int res = getaddrinfo(hostname.c_str(), service, &hints, &ai);
+ if(res != 0) {
+ switch(res) {
+ case EAI_NONAME: return -ERR_HOST_NOT_FOUND;
+ case EAI_FAIL: return -ERR_GHBN_FATAL;
+ case EAI_AGAIN: return -ERR_GHBN_TEMP;
default: return -ERR_GHBN_TEMP;
}
}
- memcpy(&sa.sin_addr, he->h_addr, he->h_length);
- return 0;
-}
-int tcpconnect(const mystring& hostname, int port)
-{
- struct sockaddr_in sa;
- memset(&sa, 0, sizeof(sa));
- int e = sethostbyname(hostname, sa);
- if(e) return e;
- sa.sin_family = AF_INET;
- sa.sin_port = htons(port);
- int s = socket(PF_INET, SOCK_STREAM, 0);
- if(s == -1)
- return -ERR_SOCKET;
- if(connect(s, (sockaddr*)&sa, sizeof(sa)) != 0) {
+ struct addrinfo *trythis = ai;
+ int result = -ERR_HOST_NOT_FOUND;
+ while (trythis) {
+ int s = socket(trythis->ai_addr->sa_family, SOCK_STREAM, 0);
+ if(s == -1) {
+ result = -ERR_SOCKET;
+ break;
+ }
+ if(connect(s, trythis->ai_addr, trythis->ai_addrlen) == 0) {
+ result = s;
+ break;
+ }
switch(errno) {
- case ECONNREFUSED: return -ERR_CONN_REFUSED;
- case ETIMEDOUT: return -ERR_CONN_TIMEDOUT;
- case ENETUNREACH: return -ERR_CONN_UNREACHABLE;
- default: return -ERR_CONN_FAILED;
+ case ECONNREFUSED: result = -ERR_CONN_REFUSED; break;
+ case ETIMEDOUT: result = -ERR_CONN_TIMEDOUT; break;
+ case ENETUNREACH: result = -ERR_CONN_UNREACHABLE; break;
+ default: result = -ERR_CONN_FAILED; break;
}
+ close(s);
+ trythis = trythis->ai_next;
}
- return s;
+ freeaddrinfo(ai);
+ return result;
}
--- nullmailer-1.10/protocols/protocol.cc.orig 2012-04-20 01:10:16.000000000 +0200
+++ nullmailer-1.10/protocols/protocol.cc 2012-04-30 12:23:32.000000000 +0200
@@ -29,16 +29,18 @@
const char* user = 0;
const char* pass = 0;
-int port = 0;
+const char* port = 0;
int auth_method = AUTH_DETECT;
int use_ssl = 0;
int use_starttls = 0;
+int ipv4_only = 0;
+int ipv6_only = 0;
const char* cli_help_suffix = "";
const char* cli_args_usage = "remote-address < mail-file";
const int cli_args_min = 1;
const int cli_args_max = 1;
cli_option cli_options[] = {
- { 'p', "port", cli_option::integer, 0, &port,
+ { 'p', "port", cli_option::string, 0, &port,
"Set the port number on the remote host to connect to", 0 },
{ 0, "user", cli_option::string, 0, &user,
"Set the user name for authentication", 0 },
@@ -46,6 +48,10 @@
"Set the password for authentication", 0 },
{ 0, "auth-login", cli_option::flag, AUTH_LOGIN, &auth_method,
"Use AUTH LOGIN instead of auto-detecting in SMTP", 0 },
+ { '4', "ipv4", cli_option::flag, 1, &ipv4_only,
+ "Try connecting with IPv4 only", 0 },
+ { '6', "ipv6", cli_option::flag, 1, &ipv6_only,
+ "Try connecting with IPv6 only", 0 },
#ifdef HAVE_TLS
{ 0, "ssl", cli_option::flag, 1, &use_ssl,
"Connect using SSL (on an alternate port by default)", 0 },
@@ -92,6 +98,9 @@
int cli_main(int, char* argv[])
{
const char* remote = argv[0];
+ tcpconn_addresstype_t addresstype = v4_or_v6;
+ if (ipv4_only && !ipv6_only) { addresstype = v4_only; }
+ if (!ipv4_only && ipv6_only) { addresstype = v6_only; }
if (port == 0)
port = use_ssl ? default_ssl_port : default_port;
if (port < 0)
@@ -100,7 +109,7 @@
tls_init(remote);
fdibuf in(0, true);
protocol_prep(in);
- int fd = tcpconnect(remote, port);
+ int fd = tcpconnect(remote, port, addresstype);
if(fd < 0)
protocol_fail(-fd, "Connect failed");
if (use_ssl)
--- nullmailer-1.10/protocols/protocol.h.orig 2012-04-20 01:10:16.000000000 +0200
+++ nullmailer-1.10/protocols/protocol.h 2012-04-30 12:25:13.000000000 +0200
@@ -5,8 +5,8 @@
#define DEFAULT_CA_FILE "/etc/ssl/certs/ca-certificates.crt"
-extern const int default_port;
-extern const int default_ssl_port;
+extern const char* default_port;
+extern const char* default_ssl_port;
extern void protocol_fail(int e, const char* msg);
extern void protocol_succ(const char* msg);
@@ -16,7 +16,9 @@
extern const char* user;
extern const char* pass;
extern int auth_method;
-extern int port;
+extern int ipv4_only;
+extern int ipv6_only;
+extern const char* port;
extern int use_ssl;
extern int use_starttls;
extern int tls_insecure;
--- nullmailer-1.10/protocols/qmqp.cc.orig 2012-04-20 01:10:16.000000000 +0200
+++ nullmailer-1.10/protocols/qmqp.cc 2012-04-30 12:25:38.000000000 +0200
@@ -30,8 +30,8 @@
#include "netstring.h"
#include "protocol.h"
-const int default_port = 628;
-const int default_ssl_port = -1; // No standard for QMQP over SSL exists
+const char* default_port = "628";
+const char* default_ssl_port = "-1"; // No standard for QMQP over SSL exists
const char* cli_program = "qmqp";
const char* cli_help_prefix = "Send an emal message via QMQP\n";
--- nullmailer-1.10/protocols/smtp.cc.orig 2012-04-20 01:10:16.000000000 +0200
+++ nullmailer-1.10/protocols/smtp.cc 2012-04-30 12:26:03.000000000 +0200
@@ -30,8 +30,8 @@
#include "mystring/mystring.h"
#include "protocol.h"
-const int default_port = 25;
-const int default_ssl_port = 465;
+const char* default_port = "25";
+const char* default_ssl_port = "465";
const char* cli_program = "smtp";
const char* cli_help_prefix = "Send an email message via SMTP\n";