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:
parent
656569b0e9
commit
927ad5776c
@ -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:
|
||||
|
@ -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.
|
||||
|
@ -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}"
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user