util: move and improve sockaddr-specific functions

Move the functions to socket.c and improve them to require and check the
sockaddr length.
This commit is contained in:
Miroslav Lichvar 2019-07-18 09:42:11 +02:00
parent 91da65a782
commit 47e4cb31b2
6 changed files with 113 additions and 103 deletions

View file

@ -34,6 +34,7 @@
#include <resolv.h>
#include "nameserv.h"
#include "socket.h"
#include "util.h"
/* ================================================== */
@ -156,10 +157,14 @@ DNS_IPAddress2Name(IPAddr *ip_addr, char *name, int len)
#ifdef FEAT_IPV6
struct sockaddr_in6 in6;
IPSockAddr ip_saddr;
socklen_t slen;
char hbuf[NI_MAXHOST];
slen = UTI_IPAndPortToSockaddr(ip_addr, 0, (struct sockaddr *)&in6);
ip_saddr.ip_addr = *ip_addr;
ip_saddr.port = 0;
slen = SCK_IPSockAddrToSockaddr(&ip_saddr, (struct sockaddr *)&in6, sizeof (in6));
if (!getnameinfo((struct sockaddr *)&in6, slen, hbuf, sizeof (hbuf), NULL, 0, 0))
result = hbuf;
#else

View file

@ -33,6 +33,7 @@
#include "nameserv.h"
#include "logging.h"
#include "privops.h"
#include "socket.h"
#include "util.h"
#define OP_ADJUSTTIME 1024
@ -257,8 +258,7 @@ do_set_time(const ReqSetTime *req, PrvResponse *res)
static void
do_bind_socket(ReqBindSocket *req, PrvResponse *res)
{
unsigned short port;
IPAddr ip;
IPSockAddr ip_saddr;
int sock_fd;
struct sockaddr *sa;
socklen_t sa_len;
@ -267,10 +267,11 @@ do_bind_socket(ReqBindSocket *req, PrvResponse *res)
sa_len = req->sa_len;
sock_fd = req->sock;
UTI_SockaddrToIPAndPort(sa, &ip, &port);
if (port && port != CNF_GetNTPPort() && port != CNF_GetAcquisitionPort()) {
SCK_SockaddrToIPSockAddr(sa, sa_len, &ip_saddr);
if (ip_saddr.port != 0 && ip_saddr.port != CNF_GetNTPPort() &&
ip_saddr.port != CNF_GetAcquisitionPort()) {
close(sock_fd);
res_fatal(res, "Invalid port %d", port);
res_fatal(res, "Invalid port %d", ip_saddr.port);
return;
}
@ -573,13 +574,13 @@ PRV_SetTime(const struct timeval *tp, const struct timezone *tzp)
int
PRV_BindSocket(int sock, struct sockaddr *address, socklen_t address_len)
{
IPSockAddr ip_saddr;
PrvRequest req;
PrvResponse res;
IPAddr ip;
unsigned short port;
UTI_SockaddrToIPAndPort(address, &ip, &port);
if (port && port != CNF_GetNTPPort() && port != CNF_GetAcquisitionPort())
SCK_SockaddrToIPSockAddr(address, address_len, &ip_saddr);
if (ip_saddr.port != 0 && ip_saddr.port != CNF_GetNTPPort() &&
ip_saddr.port != CNF_GetAcquisitionPort())
assert(0);
if (!have_helper())

102
socket.c
View file

@ -119,10 +119,23 @@ prepare_buffers(unsigned int n)
/* ================================================== */
static int
ipsockaddr_to_sockaddr(IPSockAddr *addr, union sockaddr_all *saddr)
static const char *
domain_to_string(int domain)
{
return UTI_IPAndPortToSockaddr(&addr->ip_addr, addr->port, &saddr->sa);
switch (domain) {
case AF_INET:
return "IPv4";
#ifdef AF_INET6
case AF_INET6:
return "IPv6";
#endif
case AF_UNIX:
return "Unix";
case AF_UNSPEC:
return "UNSPEC";
default:
return "?";
}
}
/* ================================================== */
@ -136,7 +149,7 @@ open_socket(int domain, int type, int flags)
if (sock_fd < 0) {
DEBUG_LOG("Could not open %s socket : %s",
UTI_SockaddrFamilyToString(domain), strerror(errno));
domain_to_string(domain), strerror(errno));
return INVALID_SOCK_FD;
}
@ -228,7 +241,7 @@ bind_ip_address(int sock_fd, IPSockAddr *addr, int flags)
;
#endif
saddr_len = ipsockaddr_to_sockaddr(addr, &saddr);
saddr_len = SCK_IPSockAddrToSockaddr(addr, (struct sockaddr *)&saddr, sizeof (saddr));
if (saddr_len == 0)
return 0;
@ -254,7 +267,7 @@ connect_ip_address(int sock_fd, IPSockAddr *addr)
union sockaddr_all saddr;
socklen_t saddr_len;
saddr_len = ipsockaddr_to_sockaddr(addr, &saddr);
saddr_len = SCK_IPSockAddrToSockaddr(addr, (struct sockaddr *)&saddr, sizeof (saddr));
if (saddr_len == 0)
return 0;
@ -584,8 +597,7 @@ process_header(struct msghdr *msg, unsigned int msg_length, int sock_fd, SCK_Mes
case AF_INET6:
#endif
init_message_addresses(message, SCK_ADDR_IP);
UTI_SockaddrToIPAndPort(msg->msg_name, &message->remote_addr.ip.ip_addr,
&message->remote_addr.ip.port);
SCK_SockaddrToIPSockAddr(msg->msg_name, msg->msg_namelen, &message->remote_addr.ip);
break;
case AF_UNIX:
init_message_addresses(message, SCK_ADDR_UNIX);
@ -812,7 +824,8 @@ send_message(int sock_fd, SCK_Message *message, int flags)
saddr_len = 0;
break;
case SCK_ADDR_IP:
saddr_len = ipsockaddr_to_sockaddr(&message->remote_addr.ip, &saddr);
saddr_len = SCK_IPSockAddrToSockaddr(&message->remote_addr.ip,
(struct sockaddr *)&saddr, sizeof (saddr));
break;
case SCK_ADDR_UNIX:
memset(&saddr, 0, sizeof (saddr));
@ -1160,3 +1173,74 @@ SCK_CloseSocket(int sock_fd)
{
close(sock_fd);
}
/* ================================================== */
void
SCK_SockaddrToIPSockAddr(struct sockaddr *sa, int sa_length, IPSockAddr *ip_sa)
{
ip_sa->ip_addr.family = IPADDR_UNSPEC;
ip_sa->port = 0;
switch (sa->sa_family) {
case AF_INET:
if (sa_length < sizeof (struct sockaddr_in))
return;
ip_sa->ip_addr.family = IPADDR_INET4;
ip_sa->ip_addr.addr.in4 = ntohl(((struct sockaddr_in *)sa)->sin_addr.s_addr);
ip_sa->port = ntohs(((struct sockaddr_in *)sa)->sin_port);
break;
#ifdef FEAT_IPV6
case AF_INET6:
if (sa_length < sizeof (struct sockaddr_in6))
return;
ip_sa->ip_addr.family = IPADDR_INET6;
memcpy(&ip_sa->ip_addr.addr.in6, ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr,
sizeof (ip_sa->ip_addr.addr.in6));
ip_sa->port = ntohs(((struct sockaddr_in6 *)sa)->sin6_port);
break;
#endif
default:
break;
}
}
/* ================================================== */
int
SCK_IPSockAddrToSockaddr(IPSockAddr *ip_sa, struct sockaddr *sa, int sa_length)
{
switch (ip_sa->ip_addr.family) {
case IPADDR_INET4:
if (sa_length < sizeof (struct sockaddr_in))
return 0;
memset(sa, 0, sizeof (struct sockaddr_in));
sa->sa_family = AF_INET;
((struct sockaddr_in *)sa)->sin_addr.s_addr = htonl(ip_sa->ip_addr.addr.in4);
((struct sockaddr_in *)sa)->sin_port = htons(ip_sa->port);
#ifdef SIN6_LEN
((struct sockaddr_in *)sa)->sin_len = sizeof (struct sockaddr_in);
#endif
return sizeof (struct sockaddr_in);
#ifdef FEAT_IPV6
case IPADDR_INET6:
if (sa_length < sizeof (struct sockaddr_in6))
return 0;
memset(sa, 0, sizeof (struct sockaddr_in6));
sa->sa_family = AF_INET6;
memcpy(&((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr, ip_sa->ip_addr.addr.in6,
sizeof (((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr));
((struct sockaddr_in6 *)sa)->sin6_port = htons(ip_sa->port);
#ifdef SIN6_LEN
((struct sockaddr_in6 *)sa)->sin6_len = sizeof (struct sockaddr_in6);
#endif
return sizeof (struct sockaddr_in6);
#endif
default:
if (sa_length < sizeof (struct sockaddr))
return 0;
memset(sa, 0, sizeof (struct sockaddr));
sa->sa_family = AF_UNSPEC;
return 0;
}
}

View file

@ -124,4 +124,8 @@ extern int SCK_RemoveSocket(int sock_fd);
/* Close the socket */
extern void SCK_CloseSocket(int sock_fd);
/* Convert between IPSockAddr and sockaddr_in/in6 */
extern void SCK_SockaddrToIPSockAddr(struct sockaddr *sa, int sa_length, IPSockAddr *ip_sa);
extern int SCK_IPSockAddrToSockaddr(IPSockAddr *ip_sa, struct sockaddr *sa, int sa_length);
#endif

80
util.c
View file

@ -492,86 +492,6 @@ UTI_CompareIPs(IPAddr *a, IPAddr *b, IPAddr *mask)
/* ================================================== */
void
UTI_SockaddrToIPAndPort(struct sockaddr *sa, IPAddr *ip, unsigned short *port)
{
switch (sa->sa_family) {
case AF_INET:
ip->family = IPADDR_INET4;
ip->addr.in4 = ntohl(((struct sockaddr_in *)sa)->sin_addr.s_addr);
*port = ntohs(((struct sockaddr_in *)sa)->sin_port);
break;
#ifdef FEAT_IPV6
case AF_INET6:
ip->family = IPADDR_INET6;
memcpy(ip->addr.in6, ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr,
sizeof (ip->addr.in6));
*port = ntohs(((struct sockaddr_in6 *)sa)->sin6_port);
break;
#endif
default:
ip->family = IPADDR_UNSPEC;
*port = 0;
}
}
/* ================================================== */
int
UTI_IPAndPortToSockaddr(IPAddr *ip, unsigned short port, struct sockaddr *sa)
{
switch (ip->family) {
case IPADDR_INET4:
memset(sa, 0, sizeof (struct sockaddr_in));
sa->sa_family = AF_INET;
((struct sockaddr_in *)sa)->sin_addr.s_addr = htonl(ip->addr.in4);
((struct sockaddr_in *)sa)->sin_port = htons(port);
#ifdef SIN6_LEN
((struct sockaddr_in *)sa)->sin_len = sizeof (struct sockaddr_in);
#endif
return sizeof (struct sockaddr_in);
#ifdef FEAT_IPV6
case IPADDR_INET6:
memset(sa, 0, sizeof (struct sockaddr_in6));
sa->sa_family = AF_INET6;
memcpy(((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr, ip->addr.in6,
sizeof (ip->addr.in6));
((struct sockaddr_in6 *)sa)->sin6_port = htons(port);
#ifdef SIN6_LEN
((struct sockaddr_in6 *)sa)->sin6_len = sizeof (struct sockaddr_in6);
#endif
return sizeof (struct sockaddr_in6);
#endif
default:
memset(sa, 0, sizeof (struct sockaddr));
sa->sa_family = AF_UNSPEC;
return 0;
}
}
/* ================================================== */
const char *
UTI_SockaddrFamilyToString(int family)
{
switch (family) {
case AF_INET:
return "IPv4";
#ifdef AF_INET6
case AF_INET6:
return "IPv6";
#endif
case AF_UNIX:
return "Unix";
case AF_UNSPEC:
return "UNSPEC";
default:
return "?";
}
}
/* ================================================== */
char *
UTI_IPSockAddrToString(IPSockAddr *sa)
{

4
util.h
View file

@ -110,10 +110,6 @@ extern void UTI_IPHostToNetwork(IPAddr *src, IPAddr *dest);
extern void UTI_IPNetworkToHost(IPAddr *src, IPAddr *dest);
extern int UTI_CompareIPs(IPAddr *a, IPAddr *b, IPAddr *mask);
extern void UTI_SockaddrToIPAndPort(struct sockaddr *sa, IPAddr *ip, unsigned short *port);
extern int UTI_IPAndPortToSockaddr(IPAddr *ip, unsigned short port, struct sockaddr *sa);
extern const char *UTI_SockaddrFamilyToString(int family);
extern char *UTI_IPSockAddrToString(IPSockAddr *sa);
extern char *UTI_TimeToLogForm(time_t t);