Skip to content

Commit 72fbc58

Browse files
authored
Merge pull request networkupstools#2916 from jimklimov/common-inet_ntopX
Move `inet_ntopXX()` methods to `common.{c,h}`
2 parents 931674f + d84cd61 commit 72fbc58

File tree

6 files changed

+117
-58
lines changed

6 files changed

+117
-58
lines changed

NEWS.adoc

+9
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,15 @@ https://github.com/networkupstools/nut/milestone/9
5252
* Common code hardening: added sanity-checking for dynamically constructed
5353
or selected formatting strings with variable-argument list methods
5454
(typically used with log printing, `dstate` setting, etc.) [#2450]
55+
* Refactored repetitive implementations of `inet_ntopSS()` (nee
56+
`inet_ntopW()` in `upsd.c`) and `inet_ntopAI()` methods into `common.c`,
57+
so now they can be re-used or expanded more easily. [#2916]
58+
59+
- `upsd` updates:
60+
* Fixed two bugs about printing the "further (ignored) addresses resolved
61+
for this name": the way to extract IP address string was not portable
62+
and misfired on some platforms, and the way to print had a theoretical
63+
potential for buffer overflow. [#2915]
5564

5665

5766
Release notes for NUT 2.8.3 - what's new since 2.8.2

clients/upsclient.c

+4-27
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2121
*/
2222

23+
#define NUT_WANT_INET_NTOP_XX 1
24+
2325
#include "config.h" /* safe because it doesn't contain prototypes */
2426
#include "nut_platform.h"
2527

@@ -1162,34 +1164,9 @@ int upscli_tryconnect(UPSCONN_t *ups, const char *host, uint16_t port, int flags
11621164
ups->upserror == UPSCLI_ERR_CONNFAILURE &&
11631165
ups->syserrno == ETIMEDOUT
11641166
) {
1165-
/* https://stackoverflow.com/a/29147085/4715872
1166-
* obviously INET6_ADDRSTRLEN is expected to be larger
1167-
* than INET_ADDRSTRLEN, but this may be required in case
1168-
* if for some unexpected reason IPv6 is not supported, and
1169-
* INET6_ADDRSTRLEN is defined as 0
1170-
* but this is not very likely and I am aware of no cases of
1171-
* this in practice (editor)
1172-
*/
1173-
char addrstr[(INET6_ADDRSTRLEN > INET_ADDRSTRLEN ? INET6_ADDRSTRLEN : INET_ADDRSTRLEN) + 1];
1174-
addrstr[0] = '\0';
1175-
switch (ai->ai_family) {
1176-
case AF_INET: {
1177-
struct sockaddr_in addr_in;
1178-
memcpy(&addr_in, ai->ai_addr, sizeof(addr_in));
1179-
inet_ntop(AF_INET, &(addr_in.sin_addr), addrstr, INET_ADDRSTRLEN);
1180-
break;
1181-
}
1182-
case AF_INET6: {
1183-
struct sockaddr_in6 addr_in6;
1184-
memcpy(&addr_in6, ai->ai_addr, sizeof(addr_in6));
1185-
inet_ntop(AF_INET6, &(addr_in6.sin6_addr), addrstr, INET6_ADDRSTRLEN);
1186-
break;
1187-
}
1188-
default:
1189-
break;
1190-
}
1167+
const char *addrstr = inet_ntopAI(ai);
11911168
upslogx(LOG_WARNING, "%s: Connection to host timed out: '%s'",
1192-
__func__, *addrstr ? addrstr : NUT_STRARG(host));
1169+
__func__, (addrstr && *addrstr) ? addrstr : NUT_STRARG(host));
11931170
break;
11941171
}
11951172
continue;

common/common.c

+66
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1919
*/
2020

21+
#define NUT_WANT_INET_NTOP_XX 1
22+
2123
#include "common.h"
2224
#include "timehead.h"
2325

@@ -4713,3 +4715,67 @@ int match_regex_hex(const regex_t *preg, const int n)
47134715
return match_regex(preg, buf);
47144716
}
47154717
#endif /* HAVE_LIBREGEX */
4718+
4719+
/* NOT THREAD SAFE!
4720+
* Helpers to convert one IP address to string from different structure types
4721+
* Return pointer to internal buffer, or NULL and errno upon errors */
4722+
const char *inet_ntopSS(struct sockaddr_storage *s)
4723+
{
4724+
static char str[40];
4725+
4726+
if (!s) {
4727+
errno = EINVAL;
4728+
return NULL;
4729+
}
4730+
4731+
switch (s->ss_family)
4732+
{
4733+
case AF_INET:
4734+
return inet_ntop (AF_INET, &(((struct sockaddr_in *)s)->sin_addr), str, 16);
4735+
case AF_INET6:
4736+
return inet_ntop (AF_INET6, &(((struct sockaddr_in6 *)s)->sin6_addr), str, 40);
4737+
default:
4738+
errno = EAFNOSUPPORT;
4739+
return NULL;
4740+
}
4741+
}
4742+
4743+
const char *inet_ntopAI(struct addrinfo *ai)
4744+
{
4745+
/* Note: below we manipulate copies of ai - cannot cast into
4746+
* specific structure type pointers right away because:
4747+
* error: cast from 'struct sockaddr *' to 'struct sockaddr_storage *'
4748+
* increases required alignment from 2 to 8
4749+
*/
4750+
/* https://stackoverflow.com/a/29147085/4715872
4751+
* obviously INET6_ADDRSTRLEN is expected to be larger
4752+
* than INET_ADDRSTRLEN, but this may be required in case
4753+
* if for some unexpected reason IPv6 is not supported, and
4754+
* INET6_ADDRSTRLEN is defined as 0
4755+
* but this is not very likely and I am aware of no cases of
4756+
* this in practice (editor)
4757+
*/
4758+
static char addrstr[(INET6_ADDRSTRLEN > INET_ADDRSTRLEN ? INET6_ADDRSTRLEN : INET_ADDRSTRLEN) + 1];
4759+
4760+
if (!ai || !ai->ai_addr) {
4761+
errno = EINVAL;
4762+
return NULL;
4763+
}
4764+
4765+
addrstr[0] = '\0';
4766+
switch (ai->ai_family) {
4767+
case AF_INET: {
4768+
struct sockaddr_in addr_in;
4769+
memcpy(&addr_in, ai->ai_addr, sizeof(addr_in));
4770+
return inet_ntop(AF_INET, &(addr_in.sin_addr), addrstr, INET_ADDRSTRLEN);
4771+
}
4772+
case AF_INET6: {
4773+
struct sockaddr_in6 addr_in6;
4774+
memcpy(&addr_in6, ai->ai_addr, sizeof(addr_in6));
4775+
return inet_ntop(AF_INET6, &(addr_in6.sin6_addr), addrstr, INET6_ADDRSTRLEN);
4776+
}
4777+
default:
4778+
errno = EAFNOSUPPORT;
4779+
return NULL;
4780+
}
4781+
}

docs/nut.dict

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
personal_ws-1.1 en 3463 utf-8
1+
personal_ws-1.1 en 3467 utf-8
22
AAC
33
AAS
44
ABI
@@ -2206,6 +2206,7 @@ ina
22062206
includePath
22072207
includedir
22082208
inductor
2209+
inet
22092210
infos
22102211
infoval
22112212
inh
@@ -2624,6 +2625,9 @@ nowarn
26242625
np
26252626
nspr
26262627
nss
2628+
ntopAI
2629+
ntopSS
2630+
ntopW
26272631
nuget
26282632
num
26292633
numOfBytesFromUPS

include/common.h

+25-4
Original file line numberDiff line numberDiff line change
@@ -66,13 +66,26 @@
6666
#endif
6767

6868
#ifndef WIN32
69-
#include <syslog.h>
69+
# include <syslog.h>
7070
#else /* WIN32 */
71-
#include <winsock2.h>
72-
#include <windows.h>
73-
#include <ws2tcpip.h>
71+
# include <winsock2.h>
72+
# include <windows.h>
73+
# include <ws2tcpip.h>
7474
#endif /* WIN32 */
7575

76+
#ifdef NUT_WANT_INET_NTOP_XX
77+
/* We currently have a few consumers who should define this macro before
78+
* including common.h, while we do not want to encumber preprocessing the
79+
* majority of codebase with these headers and our (thread-unsafe) methods.
80+
*/
81+
# ifndef WIN32
82+
# include <netdb.h>
83+
# include <sys/socket.h>
84+
# include <arpa/inet.h>
85+
# include <netinet/in.h>
86+
# endif /* WIN32 */
87+
#endif /* NUT_WANT_INET_NTOP_XX */
88+
7689
#include <unistd.h> /* useconds_t */
7790
#ifndef HAVE_USECONDS_T
7891
# define useconds_t unsigned long int
@@ -403,6 +416,14 @@ const char * rootpidpath(void);
403416
/* Die with a standard message if socket filename is too long */
404417
void check_unix_socket_filename(const char *fn);
405418

419+
#ifdef NUT_WANT_INET_NTOP_XX
420+
/* NOT THREAD SAFE!
421+
* Helpers to convert one IP address to string from different structure types
422+
* Return pointer to internal buffer, or NULL and errno upon errors */
423+
const char *inet_ntopSS(struct sockaddr_storage *s);
424+
const char *inet_ntopAI(struct addrinfo *ai);
425+
#endif /* NUT_WANT_INET_NTOP_XX */
426+
406427
/* Provide integration for systemd inhibitor interface (where available,
407428
* dummy code otherwise) implementing the pseudo-code example from
408429
* https://systemd.io/INHIBITOR_LOCKS/

server/upsd.c

+8-26
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
2008 Arjen de Korte <[email protected]>
66
2011 - 2012 Arnaud Quette <arnaud.quette.free.fr>
77
2019 Eaton (author: Arnaud Quette <[email protected]>)
8-
2020 - 2024 Jim Klimov <[email protected]>
8+
2020 - 2025 Jim Klimov <[email protected]>
99
1010
This program is free software; you can redistribute it and/or modify
1111
it under the terms of the GNU General Public License as published by
@@ -22,6 +22,8 @@
2222
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2323
*/
2424

25+
#define NUT_WANT_INET_NTOP_XX 1
26+
2527
#include "config.h" /* must be the first header */
2628

2729
#include "upsd.h"
@@ -170,22 +172,6 @@ static int reload_flag = 0, exit_flag = 0;
170172
# define SERVICE_UNIT_NAME "nut-server.service"
171173
#endif
172174

173-
static const char *inet_ntopW (struct sockaddr_storage *s)
174-
{
175-
static char str[40];
176-
177-
switch (s->ss_family)
178-
{
179-
case AF_INET:
180-
return inet_ntop (AF_INET, &(((struct sockaddr_in *)s)->sin_addr), str, 16);
181-
case AF_INET6:
182-
return inet_ntop (AF_INET6, &(((struct sockaddr_in6 *)s)->sin6_addr), str, 40);
183-
default:
184-
errno = EAFNOSUPPORT;
185-
return NULL;
186-
}
187-
}
188-
189175
/* return a pointer to the named ups if possible */
190176
upstype_t *get_ups_ptr(const char *name)
191177
{
@@ -507,17 +493,13 @@ static void setuptcp(stype_t *server)
507493
}
508494

509495
if (ai->ai_next) {
510-
char ipaddrbuf[SMALLBUF];
511-
const char *ipaddr;
512-
snprintf(ipaddrbuf, sizeof(ipaddrbuf), " as ");
513-
ipaddr = inet_ntop(ai->ai_family, ai->ai_addr,
514-
ipaddrbuf + strlen(ipaddrbuf),
515-
sizeof(ipaddrbuf));
496+
const char *ipaddr = inet_ntopAI(ai);
516497
upslogx(LOG_WARNING,
517-
"setuptcp: bound to %s%s but there seem to be "
498+
"setuptcp: bound to %s%s%s but there seem to be "
518499
"further (ignored) addresses resolved for this name",
519500
server->addr,
520-
ipaddr == NULL ? "" : ipaddrbuf);
501+
ipaddr == NULL ? "" : " as ",
502+
ipaddr == NULL ? "" : ipaddr);
521503
}
522504

523505
server->sock_fd = sock_fd;
@@ -812,7 +794,7 @@ static void client_connect(stype_t *server)
812794

813795
time(&client->last_heard);
814796

815-
client->addr = xstrdup(inet_ntopW(&csock));
797+
client->addr = xstrdup(inet_ntopSS(&csock));
816798

817799
client->tracking = 0;
818800

0 commit comments

Comments
 (0)