diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d1f80ba5..6043e3440 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,9 +3,10 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Added IPv6 support (@wh201906) - Fixed `lf hid clone --bin` - now correctly handles sentinel bits (@iceman1001) - Experimental UDP support in linux (@iceman1001, @wh201906) - - Changed CI scripts to speed up the builds (@wh201906) + - Changed CI scripts to speed up the builds (@wh201906) - Changed the timeout of local TCP connections (@wh201906) - Finalized implementation of configcard generation for keyroll when cardhelper is not present (@Antiklesys) - Added documentation for compiling on iOS (@The-SamminAter) diff --git a/client/src/comms.c b/client/src/comms.c index 6fd2ff9b0..4d65fd5f9 100644 --- a/client/src/comms.c +++ b/client/src/comms.c @@ -682,7 +682,9 @@ int TestProxmark(pm3_device_t *dev) { int res; if (is_tcp_conn || is_udp_conn) { if ((strstr(g_conn.serial_port_name, "localhost") != NULL) || - (strstr(g_conn.serial_port_name, "127.0.0.1") != NULL)) { + (strstr(g_conn.serial_port_name, "127.0.0.1") != NULL) || + (strstr(g_conn.serial_port_name, "[::1]") != NULL) || + (strstr(g_conn.serial_port_name, "p:::1") != NULL)) { res = uart_reconfigure_timeouts(UART_TCP_CLIENT_LOCAL_RX_TIMEOUT_MS); } else { res = uart_reconfigure_timeouts(UART_TCP_CLIENT_RX_TIMEOUT_MS); diff --git a/client/src/uart/uart_posix.c b/client/src/uart/uart_posix.c index ff2a6cde3..5480e98b7 100644 --- a/client/src/uart/uart_posix.c +++ b/client/src/uart/uart_posix.c @@ -108,8 +108,10 @@ serial_port uart_open(const char *pcPortName, uint32_t speed) { struct addrinfo *addr = NULL, *rp; - char *addrstr = strdup(pcPortName + 4); - if (addrstr == NULL) { + char *addrPortStr = strdup(pcPortName + 4); + char *addrstr = addrPortStr; + const char *portstr; + if (addrPortStr == NULL) { PrintAndLogEx(ERR, "error: string duplication"); free(sp); return INVALID_SERIAL_PORT; @@ -117,26 +119,59 @@ serial_port uart_open(const char *pcPortName, uint32_t speed) { timeout.tv_usec = UART_TCP_CLIENT_RX_TIMEOUT_MS * 1000; - char *colon = strrchr(addrstr, ':'); - const char *portstr; - if (colon) { - portstr = colon + 1; - *colon = '\0'; - } else { + // find the start of the address + char *endBracket = strrchr(addrPortStr, ']'); + if (addrPortStr[0] == '[') { + addrstr += 1; + if (endBracket == NULL) { + PrintAndLogEx(ERR, "error: wrong address: [] unmatched"); + free(addrPortStr); + free(sp); + return INVALID_SERIAL_PORT; + } + } + + // find the port + char *lColon = strchr(addrPortStr, ':'); + char *rColon = strrchr(addrPortStr, ':'); + if (rColon == NULL) { + // no colon + // "tcp:", "tcp:[]" portstr = "18888"; + } else if (lColon == rColon) { + // only one colon + // "tcp::", "tcp:[]:" + portstr = rColon + 1; + } else { + // two or more colon, IPv6 address + // tcp:[]: + // "tcp:", "tcp:[]" + if (endBracket != NULL && rColon == endBracket + 1) { + portstr = rColon + 1; + } else { + portstr = "18888"; + } + } + + // handle the end of the address + if (endBracket != NULL) { + *endBracket = '\0'; + } else if (rColon != NULL && lColon == rColon) { + *rColon = '\0'; } struct addrinfo info; memset(&info, 0, sizeof(info)); + info.ai_family = PF_UNSPEC; info.ai_socktype = SOCK_STREAM; int s = getaddrinfo(addrstr, portstr, &info, &addr); if (s != 0) { PrintAndLogEx(ERR, "error: getaddrinfo: %s", gai_strerror(s)); freeaddrinfo(addr); - free(addrstr); + free(addrPortStr); free(sp); return INVALID_SERIAL_PORT; } @@ -155,7 +190,7 @@ serial_port uart_open(const char *pcPortName, uint32_t speed) { } freeaddrinfo(addr); - free(addrstr); + free(addrPortStr); if (rp == NULL) { /* No address succeeded */ PrintAndLogEx(ERR, "error: Could not connect"); @@ -184,8 +219,10 @@ serial_port uart_open(const char *pcPortName, uint32_t speed) { struct addrinfo *addr = NULL, *rp; - char *addrstr = strdup(pcPortName + 4); - if (addrstr == NULL) { + char *addrPortStr = strdup(pcPortName + 4); + char *addrstr = addrPortStr; + const char *portstr; + if (addrPortStr == NULL) { PrintAndLogEx(ERR, "error: string duplication"); free(sp); return INVALID_SERIAL_PORT; @@ -193,20 +230,52 @@ serial_port uart_open(const char *pcPortName, uint32_t speed) { timeout.tv_usec = UART_TCP_CLIENT_RX_TIMEOUT_MS * 1000; - char *colon = strrchr(addrstr, ':'); - const char *portstr; - if (colon) { - portstr = colon + 1; - *colon = '\0'; - } else { + // find the start of the address + char *endBracket = strrchr(addrPortStr, ']'); + if (addrPortStr[0] == '[') { + addrstr += 1; + if (endBracket == NULL) { + PrintAndLogEx(ERR, "error: wrong address: [] unmatched"); + free(addrPortStr); + free(sp); + return INVALID_SERIAL_PORT; + } + } + + // find the port + char *lColon = strchr(addrPortStr, ':'); + char *rColon = strrchr(addrPortStr, ':'); + if (rColon == NULL) { + // no colon + // "tcp:", "tcp:[]" portstr = "18888"; + } else if (lColon == rColon) { + // only one colon + // "tcp::", "tcp:[]:" + portstr = rColon + 1; + } else { + // two or more colon, IPv6 address + // tcp:[]: + // "tcp:", "tcp:[]" + if (endBracket != NULL && rColon == endBracket + 1) { + portstr = rColon + 1; + } else { + portstr = "18888"; + } + } + + // handle the end of the address + if (endBracket != NULL) { + *endBracket = '\0'; + } else if (rColon != NULL && lColon == rColon) { + *rColon = '\0'; } struct addrinfo info; memset(&info, 0, sizeof(info)); - info.ai_family = AF_INET; + info.ai_family = PF_UNSPEC; info.ai_socktype = SOCK_DGRAM; // info.ai_protocol = SOL_UDP; @@ -214,7 +283,7 @@ serial_port uart_open(const char *pcPortName, uint32_t speed) { if (s != 0) { PrintAndLogEx(ERR, "error: getaddrinfo: %s", gai_strerror(s)); freeaddrinfo(addr); - free(addrstr); + free(addrPortStr); free(sp); return INVALID_SERIAL_PORT; } @@ -233,7 +302,7 @@ serial_port uart_open(const char *pcPortName, uint32_t speed) { } freeaddrinfo(addr); - free(addrstr); + free(addrPortStr); if (rp == NULL) { /* No address succeeded */ PrintAndLogEx(ERR, "error: Could not connect"); diff --git a/client/src/uart/uart_win32.c b/client/src/uart/uart_win32.c index 541804a24..983127015 100644 --- a/client/src/uart/uart_win32.c +++ b/client/src/uart/uart_win32.c @@ -109,8 +109,10 @@ serial_port uart_open(const char *pcPortName, uint32_t speed) { struct addrinfo *addr = NULL, *rp; - char *addrstr = strdup(pcPortName + 4); - if (addrstr == NULL) { + char *addrPortStr = strdup(pcPortName + 4); + char *addrstr = addrPortStr; + const char *portstr; + if (addrPortStr == NULL) { PrintAndLogEx(ERR, "error: string duplication"); free(sp); return INVALID_SERIAL_PORT; @@ -118,13 +120,45 @@ serial_port uart_open(const char *pcPortName, uint32_t speed) { timeout.tv_usec = UART_TCP_CLIENT_RX_TIMEOUT_MS * 1000; - char *colon = strrchr(addrstr, ':'); - const char *portstr; - if (colon) { - portstr = colon + 1; - *colon = '\0'; - } else { + // find the start of the address + char *endBracket = strrchr(addrPortStr, ']'); + if (addrPortStr[0] == '[') { + addrstr += 1; + if (endBracket == NULL) { + PrintAndLogEx(ERR, "error: wrong address: [] unmatched"); + free(addrPortStr); + free(sp); + return INVALID_SERIAL_PORT; + } + } + + // find the port + char *lColon = strchr(addrPortStr, ':'); + char *rColon = strrchr(addrPortStr, ':'); + if (rColon == NULL) { + // no colon + // "tcp:", "tcp:[]" portstr = "18888"; + } else if (lColon == rColon) { + // only one colon + // "tcp::", "tcp:[]:" + portstr = rColon + 1; + } else { + // two or more colon, IPv6 address + // tcp:[]: + // "tcp:", "tcp:[]" + if (endBracket != NULL && rColon == endBracket + 1) { + portstr = rColon + 1; + } else { + portstr = "18888"; + } + } + + // handle the end of the address + if (endBracket != NULL) { + *endBracket = '\0'; + } else if (rColon != NULL && lColon == rColon) { + *rColon = '\0'; } WSADATA wsaData; @@ -134,19 +168,21 @@ serial_port uart_open(const char *pcPortName, uint32_t speed) { iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); if (iResult != 0) { PrintAndLogEx(ERR, "error: WSAStartup failed with error: %d", iResult); + free(addrPortStr); free(sp); return INVALID_SERIAL_PORT; } memset(&info, 0, sizeof(info)); + info.ai_family = AF_UNSPEC; info.ai_socktype = SOCK_STREAM; info.ai_protocol = IPPROTO_TCP; int s = getaddrinfo(addrstr, portstr, &info, &addr); if (s != 0) { - PrintAndLogEx(ERR, "error: getaddrinfo: %s", gai_strerror(s)); + PrintAndLogEx(ERR, "error: getaddrinfo: %d: %s", s, gai_strerror(s)); freeaddrinfo(addr); - free(addrstr); + free(addrPortStr); free(sp); WSACleanup(); return INVALID_SERIAL_PORT; @@ -167,7 +203,7 @@ serial_port uart_open(const char *pcPortName, uint32_t speed) { } freeaddrinfo(addr); - free(addrstr); + free(addrPortStr); if (rp == NULL) { /* No address succeeded */ PrintAndLogEx(ERR, "error: Could not connect");