From c04302c05029683aa68275a82a56f50a6f064fe9 Mon Sep 17 00:00:00 2001 From: archang Date: Fri, 26 Sep 2014 18:12:12 +0800 Subject: [PATCH 1/7] Add ipv6 support for api listen --- api.c | 164 +++++++++++++++++++++++++++++++++--------------------- cgminer.c | 4 ++ miner.h | 3 + 3 files changed, 109 insertions(+), 62 deletions(-) diff --git a/api.c b/api.c index 73e1b4cad8..2f4b1a33a1 100644 --- a/api.c +++ b/api.c @@ -613,9 +613,9 @@ static bool do_a_restart; static time_t when = 0; // when the request occurred -struct IP4ACCESS { - in_addr_t ip; - in_addr_t mask; +struct IPACCESS { + struct in6_addr ip; + struct in6_addr mask; char group; }; @@ -633,7 +633,7 @@ struct APIGROUPS { char *commands; } apigroups['Z' - 'A' + 1]; // only A=0 to Z=25 (R: noprivs, W: allprivs) -static struct IP4ACCESS *ipaccess = NULL; +static struct IPACCESS *ipaccess = NULL; static int ips = 0; struct io_data { @@ -4419,17 +4419,20 @@ static void setup_groups() /* * Interpret [W:]IP[/Prefix][,[R|W:]IP2[/Prefix2][,...]] --api-allow option + * ipv6 address should be enclosed with a pair of square brackets and the prefix left outside * special case of 0/0 allows /0 (means all IP addresses) */ -#define ALLIP4 "0/0" +#define ALLIP "0/0" /* * N.B. IP4 addresses are by Definition 32bit big endian on all platforms */ static void setup_ipaccess() { - char *buf, *ptr, *comma, *slash, *dot; - int ipcount, mask, octet, i; + char *buf, *ptr, *comma, *slash, *end; + int ipcount, mask, octet, i, shift; char group; + bool ipv6; + char tmp[30]; buf = malloc(strlen(opt_api_allow) + 1); if (unlikely(!buf)) @@ -4444,7 +4447,7 @@ static void setup_ipaccess() ipcount++; // possibly more than needed, but never less - ipaccess = calloc(ipcount, sizeof(struct IP4ACCESS)); + ipaccess = calloc(ipcount, sizeof(struct IPACCESS)); if (unlikely(!ipaccess)) quit(1, "Failed to calloc ipaccess"); @@ -4474,41 +4477,58 @@ static void setup_ipaccess() ipaccess[ips].group = group; - if (strcmp(ptr, ALLIP4) == 0) - ipaccess[ips].ip = ipaccess[ips].mask = 0; + if (strcmp(ptr, ALLIP) == 0){ + for (i = 0; i < 16; i++){ + ipaccess[ips].ip.s6_addr[i] = 0; + ipaccess[ips].mask.s6_addr[i] = 0; + } + } else { - slash = strchr(ptr, '/'); + ipv6 = false; + end = strchr(ptr, '/'); + slash = end--; + if (*ptr == '[' && *end == ']'){ + *(ptr++) = '\0'; + *(end--) = '\0'; + ipv6 = true; + } if (!slash) - ipaccess[ips].mask = 0xffffffff; + for (i = 0; i < 16; i++) + ipaccess[ips].mask.s6_addr[i] = 0xff; else { *(slash++) = '\0'; mask = atoi(slash); - if (mask < 1 || mask > 32) + if (mask < 1 || (mask += ipv6 ? 0 : 96) > 128 ) goto popipo; // skip invalid/zero - ipaccess[ips].mask = 0; - while (mask-- >= 0) { - octet = 1 << (mask % 8); - ipaccess[ips].mask |= (octet << (24 - (8 * (mask >> 3)))); + for (i = 0; i < 16; i++) + ipaccess[ips].mask.s6_addr[i] = 0; + + i = 0; + shift = 7; + while (mask-- > 0) { + ipaccess[ips].mask.s6_addr[i] |= 1 << shift; + if (shift-- == 0){ + i++; + shift = 7; + } } } - ipaccess[ips].ip = 0; // missing default to '.0' - for (i = 0; ptr && (i < 4); i++) { - dot = strchr(ptr, '.'); - if (dot) - *(dot++) = '\0'; - - octet = atoi(ptr); - if (octet < 0 || octet > 0xff) - goto popipo; // skip invalid - - ipaccess[ips].ip |= (octet << (24 - (i * 8))); - - ptr = dot; + for (i = 0; i < 16; i++) + ipaccess[ips].ip.s6_addr[i] = 0; // missing default to '[::]' + if (ipv6){ + if (inet_pton(AF_INET6, ptr, &(ipaccess[ips].ip)) != 1) + goto popipo; } - - ipaccess[ips].ip &= ipaccess[ips].mask; + else { + // v4 mapped v6 address, such as "::ffff:255.255.255.255" + sprintf(tmp, "::ffff:%s", ptr); + if (inet_pton(AF_INET6, tmp, &(ipaccess[ips].ip)) != 1) + goto popipo; + } + for (i = 0; i < 16; i++) + ipaccess[ips].ip.s6_addr[i] &= ipaccess[ips].mask.s6_addr[i]; } ips++; @@ -4547,18 +4567,37 @@ static void *restart_thread(__maybe_unused void *userdata) return NULL; } -static bool check_connect(struct sockaddr_in *cli, char **connectaddr, char *group) +static bool check_connect(struct sockaddr_storage *cli, char **connectaddr, char *group) { bool addrok = false; - int i; + int i, j; + bool match; + char ip[50], tmp[50]; + struct in6_addr client_ip; + + getnameinfo((struct sockaddr *)cli, sizeof(*cli), + ip, sizeof(ip), NULL, 0, NI_NUMERICHOST); + *connectaddr = ip; - *connectaddr = inet_ntoa(cli->sin_addr); + // v4 mapped v6 address, such as "::ffff:255.255.255.255" + if (cli->ss_family == AF_INET){ + sprintf(tmp, "::ffff:%s", ip); + inet_pton(AF_INET6, tmp, &client_ip); + } + else + inet_pton(AF_INET6, *connectaddr, &client_ip); *group = NOPRIVGROUP; if (opt_api_allow) { - int client_ip = htonl(cli->sin_addr.s_addr); - for (i = 0; i < ips; i++) { - if ((client_ip & ipaccess[i].mask) == ipaccess[i].ip) { + for (i = 0; i < ips; i++){ + match = true; + for (j = 0; j < 16; j++) + if ((client_ip.s6_addr[j] & ipaccess[i].mask.s6_addr[j]) + != ipaccess[i].ip.s6_addr[j]) { + match = false; + break; + } + if (match){ addrok = true; *group = ipaccess[i].group; break; @@ -4568,7 +4607,8 @@ static bool check_connect(struct sockaddr_in *cli, char **connectaddr, char *gro if (opt_api_network) addrok = true; else - addrok = (strcmp(*connectaddr, localaddr) == 0); + addrok = (strcmp(*connectaddr, localaddr) == 0) + || IN6_IS_ADDR_LOOPBACK(&client_ip); } return addrok; @@ -4660,7 +4700,7 @@ static void mcast() continue; } - addrok = check_connect(&came_from, &connectaddr, &group); + addrok = check_connect((struct sockaddr_storage *)&came_from, &connectaddr, &group); applog(LOG_DEBUG, "API mcast from %s - %s", connectaddr, addrok ? "Accepted" : "Ignored"); if (!addrok) @@ -4753,8 +4793,8 @@ void api(int api_thr_id) char *binderror; time_t bindstart; short int port = opt_api_port; - struct sockaddr_in serv; - struct sockaddr_in cli; + char port_s[10]; + struct sockaddr_storage cli; socklen_t clisiz; char cmdbuf[100]; char *cmd = NULL; @@ -4767,6 +4807,7 @@ void api(int api_thr_id) bool isjson; bool did, isjoin = false, firstjoin; int i; + struct addrinfo hints, *res; SOCKETTYPE *apisock; @@ -4802,27 +4843,26 @@ void api(int api_thr_id) * to ensure curl has already called WSAStartup() in windows */ cgsleep_ms(opt_log_interval*1000); - *apisock = socket(AF_INET, SOCK_STREAM, 0); - if (*apisock == INVSOCK) { - applog(LOG_ERR, "API1 initialisation failed (%s)%s", SOCKERRMSG, UNAVAILABLE); + sprintf(port_s, "%d", port); + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_PASSIVE; + hints.ai_family = AF_UNSPEC; + if (getaddrinfo(opt_api_host, port_s, &hints, &res) != 0){ + applog(LOG_ERR, "API failed to resolve %s", opt_api_host); free(apisock); return; } - - memset(&serv, 0, sizeof(serv)); - - serv.sin_family = AF_INET; - - if (!opt_api_allow && !opt_api_network) { - serv.sin_addr.s_addr = inet_addr(localaddr); - if (serv.sin_addr.s_addr == (in_addr_t)INVINETADDR) { - applog(LOG_ERR, "API2 initialisation failed (%s)%s", SOCKERRMSG, UNAVAILABLE); - free(apisock); - return; - } + while (res != NULL){ + *apisock = socket(res->ai_family, SOCK_STREAM, 0); + if (*apisock > 0) + break; + res = res -> ai_next; + } + if (*apisock == INVSOCK) { + applog(LOG_ERR, "API initialisation failed (%s)%s", SOCKERRMSG, UNAVAILABLE); + free(apisock); + return; } - - serv.sin_port = htons(port); #ifndef WIN32 // On linux with SO_REUSEADDR, bind will get the port if the previous @@ -4842,7 +4882,7 @@ void api(int api_thr_id) bound = 0; bindstart = time(NULL); while (bound == 0) { - if (SOCKETFAIL(bind(*apisock, (struct sockaddr *)(&serv), sizeof(serv)))) { + if (SOCKETFAIL(bind(*apisock, res->ai_addr, res->ai_addrlen))) { binderror = SOCKERRMSG; if ((time(NULL) - bindstart) > 61) break; @@ -4888,7 +4928,7 @@ void api(int api_thr_id) goto die; } - addrok = check_connect(&cli, &connectaddr, &group); + addrok = check_connect((struct sockaddr_storage *)&cli, &connectaddr, &group); applog(LOG_DEBUG, "API: connection from %s - %s", connectaddr, addrok ? "Accepted" : "Ignored"); @@ -5052,7 +5092,7 @@ void api(int api_thr_id) pthread_cleanup_pop(true); free(apisock); - + if (opt_debug) applog(LOG_DEBUG, "API: terminating due to: %s", do_a_quit ? "QUIT" : (do_a_restart ? "RESTART" : (bye ? "BYE" : "UNKNOWN!"))); diff --git a/cgminer.c b/cgminer.c index 519dc0d9e0..30ad2ef93d 100644 --- a/cgminer.c +++ b/cgminer.c @@ -198,6 +198,7 @@ char *opt_api_allow = NULL; char *opt_api_groups; char *opt_api_description = PACKAGE_STRING; int opt_api_port = 4028; +char *opt_api_host = API_LISTEN_ADDR; bool opt_api_listen; bool opt_api_mcast; char *opt_api_mcast_addr = API_MCAST_ADDR; @@ -1116,6 +1117,9 @@ static struct opt_table opt_config_table[] = { OPT_WITH_ARG("--api-port", set_int_1_to_65535, opt_show_intval, &opt_api_port, "Port number of miner API"), + OPT_WITH_ARG("--api-host", + opt_set_charp, NULL, &opt_api_host, + "Specify API listen address, default: 0.0.0.0"), #ifdef USE_AVALON OPT_WITHOUT_ARG("--avalon-auto", opt_set_bool, &opt_avalon_auto, diff --git a/miner.h b/miner.h index ba49e46c8f..875390e932 100644 --- a/miner.h +++ b/miner.h @@ -956,6 +956,7 @@ static inline void _cg_wunlock(cglock_t *lock, const char *file, const char *fun struct pool; +#define API_LISTEN_ADDR "0.0.0.0" #define API_MCAST_CODE "FTW" #define API_MCAST_ADDR "224.0.0.75" @@ -979,9 +980,11 @@ extern int opt_api_mcast_port; extern char *opt_api_groups; extern char *opt_api_description; extern int opt_api_port; +extern char *opt_api_host; extern bool opt_api_listen; extern bool opt_api_network; extern bool opt_delaynet; +extern bool opt_stratum_ignore; extern time_t last_getwork; extern bool opt_restart; #ifdef USE_ICARUS From a0fb48b0be0776b425fad4ee43794b2c5ebd9d56 Mon Sep 17 00:00:00 2001 From: archang Date: Fri, 26 Sep 2014 18:25:25 +0800 Subject: [PATCH 2/7] Remove the brackets when using v6 pool address --- util.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/util.c b/util.c index 4e150aabb8..b9513763bd 100644 --- a/util.c +++ b/util.c @@ -1476,7 +1476,13 @@ bool extract_sockaddr(char *url, char **sockaddr_url, char **sockaddr_port) if (url_len < 1) return false; - + + /* Get rid of the [] */ + if (ipv6_begin && ipv6_end && ipv6_end > ipv6_begin){ + url_len -= 2; + url_begin++; + } + snprintf(url_address, 254, "%.*s", url_len, url_begin); if (port_len) { From c045884e5c64638ecf65460f9d6c86b2c801d648 Mon Sep 17 00:00:00 2001 From: archang Date: Sun, 28 Sep 2014 13:54:52 +0800 Subject: [PATCH 3/7] Free addrinfo garbage --- api.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/api.c b/api.c index 2f4b1a33a1..bb83c468e3 100644 --- a/api.c +++ b/api.c @@ -4807,7 +4807,7 @@ void api(int api_thr_id) bool isjson; bool did, isjoin = false, firstjoin; int i; - struct addrinfo hints, *res; + struct addrinfo hints, *res, *host; SOCKETTYPE *apisock; @@ -4852,14 +4852,16 @@ void api(int api_thr_id) free(apisock); return; } - while (res != NULL){ + host = res; + while (host != NULL){ *apisock = socket(res->ai_family, SOCK_STREAM, 0); if (*apisock > 0) break; - res = res -> ai_next; + host = host->ai_next; } if (*apisock == INVSOCK) { applog(LOG_ERR, "API initialisation failed (%s)%s", SOCKERRMSG, UNAVAILABLE); + freeaddrinfo(res); free(apisock); return; } @@ -4882,7 +4884,7 @@ void api(int api_thr_id) bound = 0; bindstart = time(NULL); while (bound == 0) { - if (SOCKETFAIL(bind(*apisock, res->ai_addr, res->ai_addrlen))) { + if (SOCKETFAIL(bind(*apisock, host->ai_addr, host->ai_addrlen))) { binderror = SOCKERRMSG; if ((time(NULL) - bindstart) > 61) break; @@ -4893,6 +4895,7 @@ void api(int api_thr_id) } else bound = 1; } + freeaddrinfo(res); if (bound == 0) { applog(LOG_ERR, "API bind to port %d failed (%s)%s", port, binderror, UNAVAILABLE); From 6ad44906ac01b3ba40703462984bc7f12b4bcc7d Mon Sep 17 00:00:00 2001 From: archang Date: Tue, 30 Sep 2014 11:54:31 +0800 Subject: [PATCH 4/7] Fix client ip address output --- api.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/api.c b/api.c index bb83c468e3..8ce53147ac 100644 --- a/api.c +++ b/api.c @@ -4572,16 +4572,16 @@ static bool check_connect(struct sockaddr_storage *cli, char **connectaddr, char bool addrok = false; int i, j; bool match; - char ip[50], tmp[50]; + char tmp[30]; struct in6_addr client_ip; + *connectaddr = (char *)malloc(INET6_ADDRSTRLEN); getnameinfo((struct sockaddr *)cli, sizeof(*cli), - ip, sizeof(ip), NULL, 0, NI_NUMERICHOST); - *connectaddr = ip; + *connectaddr, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST); // v4 mapped v6 address, such as "::ffff:255.255.255.255" if (cli->ss_family == AF_INET){ - sprintf(tmp, "::ffff:%s", ip); + sprintf(tmp, "::ffff:%s", *connectaddr); inet_pton(AF_INET6, tmp, &client_ip); } else From 7c4473955a2b44830754e704514ad4ea1a78c2a5 Mon Sep 17 00:00:00 2001 From: archang Date: Wed, 8 Oct 2014 09:34:48 +0800 Subject: [PATCH 5/7] Support ipv6 multicast --- api.c | 129 +++++++++++++++++++++++++++++++++++++++------------------ util.c | 2 +- 2 files changed, 89 insertions(+), 42 deletions(-) diff --git a/api.c b/api.c index 8ce53147ac..995df8ff86 100644 --- a/api.c +++ b/api.c @@ -4477,8 +4477,8 @@ static void setup_ipaccess() ipaccess[ips].group = group; - if (strcmp(ptr, ALLIP) == 0){ - for (i = 0; i < 16; i++){ + if (strcmp(ptr, ALLIP) == 0) { + for (i = 0; i < 16; i++) { ipaccess[ips].ip.s6_addr[i] = 0; ipaccess[ips].mask.s6_addr[i] = 0; } @@ -4487,7 +4487,7 @@ static void setup_ipaccess() ipv6 = false; end = strchr(ptr, '/'); slash = end--; - if (*ptr == '[' && *end == ']'){ + if (*ptr == '[' && *end == ']') { *(ptr++) = '\0'; *(end--) = '\0'; ipv6 = true; @@ -4508,7 +4508,7 @@ static void setup_ipaccess() shift = 7; while (mask-- > 0) { ipaccess[ips].mask.s6_addr[i] |= 1 << shift; - if (shift-- == 0){ + if (shift-- == 0) { i++; shift = 7; } @@ -4517,7 +4517,7 @@ static void setup_ipaccess() for (i = 0; i < 16; i++) ipaccess[ips].ip.s6_addr[i] = 0; // missing default to '[::]' - if (ipv6){ + if (ipv6) { if (inet_pton(AF_INET6, ptr, &(ipaccess[ips].ip)) != 1) goto popipo; } @@ -4580,7 +4580,7 @@ static bool check_connect(struct sockaddr_storage *cli, char **connectaddr, char *connectaddr, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST); // v4 mapped v6 address, such as "::ffff:255.255.255.255" - if (cli->ss_family == AF_INET){ + if (cli->ss_family == AF_INET) { sprintf(tmp, "::ffff:%s", *connectaddr); inet_pton(AF_INET6, tmp, &client_ip); } @@ -4589,7 +4589,7 @@ static bool check_connect(struct sockaddr_storage *cli, char **connectaddr, char *group = NOPRIVGROUP; if (opt_api_allow) { - for (i = 0; i < ips; i++){ + for (i = 0; i < ips; i++) { match = true; for (j = 0; j < 16; j++) if ((client_ip.s6_addr[j] & ipaccess[i].mask.s6_addr[j]) @@ -4597,7 +4597,7 @@ static bool check_connect(struct sockaddr_storage *cli, char **connectaddr, char match = false; break; } - if (match){ + if (match) { addrok = true; *group = ipaccess[i].group; break; @@ -4616,13 +4616,11 @@ static bool check_connect(struct sockaddr_storage *cli, char **connectaddr, char static void mcast() { - struct sockaddr_in listen; - struct ip_mreq grp; - struct sockaddr_in came_from; + struct sockaddr_storage came_from; time_t bindstart; char *binderror; - SOCKETTYPE mcast_sock; - SOCKETTYPE reply_sock; + SOCKETTYPE mcast_sock = INVSOCK; + SOCKETTYPE reply_sock = INVSOCK; socklen_t came_from_siz; char *connectaddr; ssize_t rep; @@ -4632,19 +4630,31 @@ static void mcast() bool addrok; char group; + char port_s[10], came_from_port[10]; + struct addrinfo hints, *res, *host, *client; + char expect[] = "cgminer-"; // first 8 bytes constant char *expect_code; size_t expect_code_len; char buf[1024]; char replybuf[1024]; - memset(&grp, 0, sizeof(grp)); - grp.imr_multiaddr.s_addr = inet_addr(opt_api_mcast_addr); - if (grp.imr_multiaddr.s_addr == INADDR_NONE) - quit(1, "Invalid Multicast Address"); - grp.imr_interface.s_addr = INADDR_ANY; - - mcast_sock = socket(AF_INET, SOCK_DGRAM, 0); + sprintf(port_s, "%d", opt_api_mcast_port); + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + if (getaddrinfo(opt_api_mcast_addr, port_s, &hints, &res) != 0) + quit(1, "Invalid API Multicast Address"); + host = res; + while (host != NULL) { + mcast_sock = socket(res->ai_family, SOCK_DGRAM, 0); + if (mcast_sock > 0) + break; + host = host->ai_next; + } + if (mcast_sock == INVSOCK) { + freeaddrinfo(res); + quit(1, "API mcast could not open socket"); + } int optval = 1; if (SOCKETFAIL(setsockopt(mcast_sock, SOL_SOCKET, SO_REUSEADDR, (void *)(&optval), sizeof(optval)))) { @@ -4652,16 +4662,11 @@ static void mcast() goto die; } - memset(&listen, 0, sizeof(listen)); - listen.sin_family = AF_INET; - listen.sin_addr.s_addr = INADDR_ANY; - listen.sin_port = htons(opt_api_mcast_port); - // try for more than 1 minute ... in case the old one hasn't completely gone yet bound = 0; bindstart = time(NULL); while (bound == 0) { - if (SOCKETFAIL(bind(mcast_sock, (struct sockaddr *)(&listen), sizeof(listen)))) { + if (SOCKETFAIL(bind(mcast_sock, host->ai_addr, host->ai_addrlen))) { binderror = SOCKERRMSG; if ((time(NULL) - bindstart) > 61) break; @@ -4672,14 +4677,41 @@ static void mcast() } if (bound == 0) { - applog(LOG_ERR, "API mcast bind to port %d failed (%s)%s", opt_api_port, binderror, MUNAVAILABLE); + applog(LOG_ERR, "API mcast bind to port %d failed (%s)%s", opt_api_mcast_port, binderror, MUNAVAILABLE); goto die; } - if (SOCKETFAIL(setsockopt(mcast_sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *)(&grp), sizeof(grp)))) { - applog(LOG_ERR, "API mcast join failed (%s)%s", SOCKERRMSG, MUNAVAILABLE); - goto die; + switch (host->ai_family) { + case AF_INET: { + struct ip_mreq grp; + memset(&grp, 0, sizeof(grp)); + grp.imr_multiaddr.s_addr = ((struct sockaddr_in *)(host->ai_addr))->sin_addr.s_addr; + grp.imr_interface.s_addr = INADDR_ANY; + + if (SOCKETFAIL(setsockopt(mcast_sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, + (void *)(&grp), sizeof(grp)))) { + applog(LOG_ERR, "API mcast join failed (%s)%s", SOCKERRMSG, MUNAVAILABLE); + goto die; + } + break; + } + case AF_INET6: { + struct ipv6_mreq grp; + memcpy(&grp.ipv6mr_multiaddr, &(((struct sockaddr_in6 *)(host->ai_addr))->sin6_addr), + sizeof(struct in6_addr)); + grp.ipv6mr_interface= 0; + + if (SOCKETFAIL(setsockopt(mcast_sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, + (void *)(&grp), sizeof(grp)))) { + applog(LOG_ERR, "API mcast join failed (%s)%s", SOCKERRMSG, MUNAVAILABLE); + goto die; + } + break; + } + default: + break; } + freeaddrinfo(res); expect_code_len = sizeof(expect) + strlen(opt_api_mcast_code); expect_code = malloc(expect_code_len+1); @@ -4700,7 +4732,7 @@ static void mcast() continue; } - addrok = check_connect((struct sockaddr_storage *)&came_from, &connectaddr, &group); + addrok = check_connect(&came_from, &connectaddr, &group); applog(LOG_DEBUG, "API mcast from %s - %s", connectaddr, addrok ? "Accepted" : "Ignored"); if (!addrok) @@ -4710,10 +4742,11 @@ static void mcast() if (rep > 0 && buf[rep-1] == '\n') buf[--rep] = '\0'; - applog(LOG_DEBUG, "API mcast request rep=%d (%s) from %s:%d", - (int)rep, buf, - inet_ntoa(came_from.sin_addr), - ntohs(came_from.sin_port)); + getnameinfo((struct sockaddr *)(&came_from), came_from_siz, + NULL, 0, came_from_port, sizeof(came_from_port), NI_NUMERICHOST); + + applog(LOG_DEBUG, "API mcast request rep=%d (%s) from [%s]:%s", + (int)rep, buf, connectaddr, came_from_port); if ((size_t)rep > expect_code_len && memcmp(buf, expect_code, expect_code_len) == 0) { reply_port = atoi(&buf[expect_code_len]); @@ -4724,16 +4757,30 @@ static void mcast() applog(LOG_DEBUG, "API mcast request OK port %s=%d", &buf[expect_code_len], reply_port); - came_from.sin_port = htons(reply_port); - reply_sock = socket(AF_INET, SOCK_DGRAM, 0); + if (getaddrinfo(connectaddr, &buf[expect_code_len], &hints, &res) != 0) { + applog(LOG_ERR, "Invalid client address %s", connectaddr); + continue; + } + client = res; + while (client) { + reply_sock = socket(res->ai_family, SOCK_DGRAM, 0); + if (mcast_sock > 0) + break; + client = client->ai_next; + } + if (reply_sock == INVSOCK) { + freeaddrinfo(res); + applog(LOG_ERR, "API mcast could not open socket to client %s", connectaddr); + continue; + } snprintf(replybuf, sizeof(replybuf), "cgm-" API_MCAST_CODE "-%d-%s", opt_api_port, opt_api_mcast_des); rep = sendto(reply_sock, replybuf, strlen(replybuf)+1, - 0, (struct sockaddr *)(&came_from), - sizeof(came_from)); + 0, client->ai_addr, client->ai_addrlen); + freeaddrinfo(res); if (SOCKETFAIL(rep)) { applog(LOG_DEBUG, "API mcast send reply failed (%s) (%d)", SOCKERRMSG, (int)reply_sock); @@ -4847,13 +4894,13 @@ void api(int api_thr_id) memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_PASSIVE; hints.ai_family = AF_UNSPEC; - if (getaddrinfo(opt_api_host, port_s, &hints, &res) != 0){ + if (getaddrinfo(opt_api_host, port_s, &hints, &res) != 0) { applog(LOG_ERR, "API failed to resolve %s", opt_api_host); free(apisock); return; } host = res; - while (host != NULL){ + while (host) { *apisock = socket(res->ai_family, SOCK_STREAM, 0); if (*apisock > 0) break; diff --git a/util.c b/util.c index b9513763bd..5e0e0861ef 100644 --- a/util.c +++ b/util.c @@ -1478,7 +1478,7 @@ bool extract_sockaddr(char *url, char **sockaddr_url, char **sockaddr_port) return false; /* Get rid of the [] */ - if (ipv6_begin && ipv6_end && ipv6_end > ipv6_begin){ + if (ipv6_begin && ipv6_end && ipv6_end > ipv6_begin) { url_len -= 2; url_begin++; } From ac1a48dc79c2cf68108ebd956641f4d857c8d19f Mon Sep 17 00:00:00 2001 From: archang Date: Wed, 8 Oct 2014 10:36:01 +0800 Subject: [PATCH 6/7] Fix error when using v6 without mask in api-allow --- api.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/api.c b/api.c index 995df8ff86..43ca129f6a 100644 --- a/api.c +++ b/api.c @@ -4484,18 +4484,18 @@ static void setup_ipaccess() } } else { - ipv6 = false; end = strchr(ptr, '/'); - slash = end--; - if (*ptr == '[' && *end == ']') { - *(ptr++) = '\0'; - *(end--) = '\0'; - ipv6 = true; - } - if (!slash) + if (!end) for (i = 0; i < 16; i++) ipaccess[ips].mask.s6_addr[i] = 0xff; else { + slash = end--; + ipv6 = false; + if (*ptr == '[' && *end == ']') { + *(ptr++) = '\0'; + *(end--) = '\0'; + ipv6 = true; + } *(slash++) = '\0'; mask = atoi(slash); if (mask < 1 || (mask += ipv6 ? 0 : 96) > 128 ) From b0967df98a2903c579764528acc52000513c177d Mon Sep 17 00:00:00 2001 From: archang Date: Wed, 8 Oct 2014 10:44:04 +0800 Subject: [PATCH 7/7] Clean --- miner.h | 1 - 1 file changed, 1 deletion(-) diff --git a/miner.h b/miner.h index 875390e932..dd82bfdfb1 100644 --- a/miner.h +++ b/miner.h @@ -984,7 +984,6 @@ extern char *opt_api_host; extern bool opt_api_listen; extern bool opt_api_network; extern bool opt_delaynet; -extern bool opt_stratum_ignore; extern time_t last_getwork; extern bool opt_restart; #ifdef USE_ICARUS