avrdude: Cherry-pick rev 1421 from upstream:

Submitted by Reinhard Max patch #8311: Add IPv6 support to the
-Pnet:host:port option * ser_posix.c (net_open):
Rewrite to use getaddrinfo() rather than gethostbyname()

Fix #2918
This commit is contained in:
Vojtech Kral 2019-09-20 17:14:28 +02:00
parent 656569b0e9
commit 927ad5776c
5 changed files with 81 additions and 41 deletions

View File

@ -1,3 +1,12 @@
2018-01-17 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
(cherry-picked)
Submitted by Reinhard Max
patch #8311: Add IPv6 support to the -Pnet:host:port option
* ser_posix.c (net_open): Rewrite to use getaddrinfo()
rather than gethostbyname()
* avrdude.1: Document IPv6 feature
* doc/avrdude.texi: (Dito)
2016-05-10 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Hannes Jochriem:

View File

@ -505,12 +505,19 @@ network connection to (TCP)
on
.Ar host
is established.
Square brackets may be placed around
.Ar host
to improve readability, for numeric IPv6 addresses (e.g.
.Li net:[2001:db8::42]:1337 ) .
The remote endpoint is assumed to be a terminal or console server
that connects the network stream to a local serial port where the
actual programmer has been attached to.
The port is assumed to be properly configured, for example using a
transparent 8-bit data connection without parity at 115200 Baud
for a STK500.
.Pp
Note: The ability to handle IPv6 hostnames and addresses is limited to
Posix systems (by now).
.It Fl q
Disable (or quell) output of the progress bar while reading or writing
to the device. Specify it a second time for even quieter operation.

View File

@ -214,7 +214,7 @@ AC_HEADER_TIME
AC_CHECK_LIB([ws2_32], [puts])
# Checks for library functions.
AC_CHECK_FUNCS([memset select strcasecmp strdup strerror strncasecmp strtol strtoul gettimeofday usleep])
AC_CHECK_FUNCS([memset select strcasecmp strdup strerror strncasecmp strtol strtoul gettimeofday usleep getaddrinfo])
AC_MSG_CHECKING([for a Win32 HID libray])
SAVED_LIBS="${LIBS}"

View File

@ -557,6 +557,9 @@ higher level protocol (as opposed to bit-bang style programmers),
In this case, instead of trying to open a local device, a TCP
network connection to (TCP) @var{port} on @var{host}
is established.
Square brackets may be placed around @var{host} to improve
readability for numeric IPv6 addresses (e.g.
@code{net:[2001:db8::42]:1337}).
The remote endpoint is assumed to be a terminal or console server
that connects the network stream to a local serial port where the
actual programmer has been attached to.
@ -564,6 +567,8 @@ The port is assumed to be properly configured, for example using a
transparent 8-bit data connection without parity at 115200 Baud
for a STK500.
Note: The ability to handle IPv6 hostnames and addresses is limited to
Posix systems (by now).
@item -q
Disable (or quell) output of the progress bar while reading or writing

View File

@ -150,6 +150,7 @@ static int ser_setspeed(union filedescriptor *fd, long baud)
return 0;
}
#include "ac_cfg.h"
// Timeout read & write variants
// Additionally to the regular -1 on I/O error, they return -2 on timeout
@ -221,23 +222,35 @@ ssize_t write_timeout(int fd, const void *buf, size_t count, long timeout)
static int
net_open(const char *port, union filedescriptor *fdp)
{
char *hstr, *pstr, *end;
unsigned int pnum;
int fd;
struct sockaddr_in sockaddr;
struct hostent *hp;
#ifdef HAVE_GETADDRINFO
char *hp, *hstr, *pstr;
int s, fd, ret = -1;
struct addrinfo hints;
struct addrinfo *result, *rp;
if ((hstr = strdup(port)) == NULL) {
if ((hstr = hp = strdup(port)) == NULL) {
avrdude_message(MSG_INFO, "%s: net_open(): Out of memory!\n",
progname);
return -1;
}
if (((pstr = strchr(hstr, ':')) == NULL) || (pstr == hstr)) {
/*
* As numeric IPv6 addresses use colons as separators, we need to
* look for the last colon here, which separates the port number or
* service name from the host or IP address.
*/
if (((pstr = strrchr(hstr, ':')) == NULL) || (pstr == hstr)) {
avrdude_message(MSG_INFO, "%s: net_open(): Mangled host:port string \"%s\"\n",
progname, hstr);
free(hstr);
return -1;
goto error;
}
/*
* Remove brackets from the host part, if present.
*/
if (*hstr == '[' && *(pstr-1) == ']') {
hstr++;
*(pstr-1) = '\0';
}
/*
@ -245,43 +258,49 @@ net_open(const char *port, union filedescriptor *fdp)
*/
*pstr++ = '\0';
pnum = strtoul(pstr, &end, 10);
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
s = getaddrinfo(hstr, pstr, &hints, &result);
if ((*pstr == '\0') || (*end != '\0') || (pnum == 0) || (pnum > 65535)) {
avrdude_message(MSG_INFO, "%s: net_open(): Bad port number \"%s\"\n",
progname, pstr);
free(hstr);
return -1;
if (s != 0) {
avrdude_message(MSG_INFO,
"%s: net_open(): Cannot resolve "
"host=\"%s\", port=\"%s\": %s\n",
progname, hstr, pstr, gai_strerror(s));
goto error;
}
if ((hp = gethostbyname(hstr)) == NULL) {
avrdude_message(MSG_INFO, "%s: net_open(): unknown host \"%s\"\n",
progname, hstr);
free(hstr);
return -1;
for (rp = result; rp != NULL; rp = rp->ai_next) {
fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if (fd == -1) {
/* This one failed, loop over */
continue;
}
if (connect(fd, rp->ai_addr, rp->ai_addrlen) != -1) {
/* Success, we are connected */
break;
}
close(fd);
}
free(hstr);
if ((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
avrdude_message(MSG_INFO, "%s: net_open(): Cannot open socket: %s\n",
progname, strerror(errno));
return -1;
if (rp == NULL) {
avrdude_message(MSG_INFO, "%s: net_open(): Cannot connect: %s\n",
progname, strerror(errno));
}
memset(&sockaddr, 0, sizeof(struct sockaddr_in));
sockaddr.sin_family = AF_INET;
sockaddr.sin_port = htons(pnum);
memcpy(&(sockaddr.sin_addr.s_addr), hp->h_addr, sizeof(struct in_addr));
if (connect(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr))) {
avrdude_message(MSG_INFO, "%s: net_open(): Connect failed: %s\n",
progname, strerror(errno));
return -1;
else {
fdp->ifd = fd;
ret = 0;
}
freeaddrinfo(result);
fdp->ifd = fd;
return 0;
error:
free(hp);
return ret;
#else
avrdude_message(MSG_INFO,
"%s: Networking is not supported on your platform.\n"
"If you need it, please open a bug report.\n", progname);
return -1;
#endif /* HAVE_GETADDRINFO */
}