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> 2016-05-10 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Hannes Jochriem: Submitted by Hannes Jochriem:

View file

@ -505,12 +505,19 @@ network connection to (TCP)
on on
.Ar host .Ar host
is established. 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 The remote endpoint is assumed to be a terminal or console server
that connects the network stream to a local serial port where the that connects the network stream to a local serial port where the
actual programmer has been attached to. actual programmer has been attached to.
The port is assumed to be properly configured, for example using a The port is assumed to be properly configured, for example using a
transparent 8-bit data connection without parity at 115200 Baud transparent 8-bit data connection without parity at 115200 Baud
for a STK500. for a STK500.
.Pp
Note: The ability to handle IPv6 hostnames and addresses is limited to
Posix systems (by now).
.It Fl q .It Fl q
Disable (or quell) output of the progress bar while reading or writing Disable (or quell) output of the progress bar while reading or writing
to the device. Specify it a second time for even quieter operation. 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]) AC_CHECK_LIB([ws2_32], [puts])
# Checks for library functions. # 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]) AC_MSG_CHECKING([for a Win32 HID libray])
SAVED_LIBS="${LIBS}" 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 In this case, instead of trying to open a local device, a TCP
network connection to (TCP) @var{port} on @var{host} network connection to (TCP) @var{port} on @var{host}
is established. 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 The remote endpoint is assumed to be a terminal or console server
that connects the network stream to a local serial port where the that connects the network stream to a local serial port where the
actual programmer has been attached to. 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 transparent 8-bit data connection without parity at 115200 Baud
for a STK500. for a STK500.
Note: The ability to handle IPv6 hostnames and addresses is limited to
Posix systems (by now).
@item -q @item -q
Disable (or quell) output of the progress bar while reading or writing 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; return 0;
} }
#include "ac_cfg.h"
// Timeout read & write variants // Timeout read & write variants
// Additionally to the regular -1 on I/O error, they return -2 on timeout // 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 static int
net_open(const char *port, union filedescriptor *fdp) net_open(const char *port, union filedescriptor *fdp)
{ {
char *hstr, *pstr, *end; #ifdef HAVE_GETADDRINFO
unsigned int pnum; char *hp, *hstr, *pstr;
int fd; int s, fd, ret = -1;
struct sockaddr_in sockaddr; struct addrinfo hints;
struct hostent *hp; 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", avrdude_message(MSG_INFO, "%s: net_open(): Out of memory!\n",
progname); progname);
return -1; 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", avrdude_message(MSG_INFO, "%s: net_open(): Mangled host:port string \"%s\"\n",
progname, hstr); progname, hstr);
free(hstr); goto error;
return -1; }
/*
* 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'; *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)) { if (s != 0) {
avrdude_message(MSG_INFO, "%s: net_open(): Bad port number \"%s\"\n", avrdude_message(MSG_INFO,
progname, pstr); "%s: net_open(): Cannot resolve "
free(hstr); "host=\"%s\", port=\"%s\": %s\n",
return -1; progname, hstr, pstr, gai_strerror(s));
goto error;
} }
for (rp = result; rp != NULL; rp = rp->ai_next) {
if ((hp = gethostbyname(hstr)) == NULL) { fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
avrdude_message(MSG_INFO, "%s: net_open(): unknown host \"%s\"\n", if (fd == -1) {
progname, hstr); /* This one failed, loop over */
free(hstr); continue;
return -1; }
if (connect(fd, rp->ai_addr, rp->ai_addrlen) != -1) {
/* Success, we are connected */
break;
}
close(fd);
} }
if (rp == NULL) {
free(hstr); avrdude_message(MSG_INFO, "%s: net_open(): Cannot connect: %s\n",
progname, strerror(errno));
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;
} }
else {
memset(&sockaddr, 0, sizeof(struct sockaddr_in)); fdp->ifd = fd;
sockaddr.sin_family = AF_INET; ret = 0;
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;
} }
freeaddrinfo(result);
fdp->ifd = fd; error:
return 0; 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 */
} }