-
Notifications
You must be signed in to change notification settings - Fork 30
/
netutils.c
140 lines (112 loc) · 2.77 KB
/
netutils.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/*
* Copyright (C) 2010-2021 Red Hat, Inc. All rights reserved.
*
* Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
* Federico Simoncelli <fsimon@kronosnet.org>
*
* This software licensed under LGPL-2.0+
*/
#include "config.h"
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <errno.h>
#include <string.h>
#include "internals.h"
#include "netutils.h"
int cmpaddr(const struct sockaddr_storage *ss1, const struct sockaddr_storage *ss2)
{
struct sockaddr_in6 *ss1_addr6 = (struct sockaddr_in6 *)ss1;
struct sockaddr_in6 *ss2_addr6 = (struct sockaddr_in6 *)ss2;
struct sockaddr_in *ss1_addr = (struct sockaddr_in *)ss1;
struct sockaddr_in *ss2_addr = (struct sockaddr_in *)ss2;
if (ss1->ss_family != ss2->ss_family) {
return -1;
}
if (ss1->ss_family == AF_INET6) {
return memcmp(&ss1_addr6->sin6_addr.s6_addr32, &ss2_addr6->sin6_addr.s6_addr32, sizeof(struct in6_addr));
}
return memcmp(&ss1_addr->sin_addr.s_addr, &ss2_addr->sin_addr.s_addr, sizeof(struct in_addr));
}
socklen_t sockaddr_len(const struct sockaddr_storage *ss)
{
if (ss->ss_family == AF_INET) {
return sizeof(struct sockaddr_in);
} else {
return sizeof(struct sockaddr_in6);
}
}
/* Only copy the valid parts of a sockaddr* */
void copy_sockaddr(struct sockaddr_storage *sout, const struct sockaddr_storage *sin)
{
memset(sout, 0, sizeof(struct sockaddr_storage));
memmove(sout, sin, sockaddr_len(sin));
}
/*
* exported APIs
*/
int knet_strtoaddr(const char *host, const char *port, struct sockaddr_storage *ss, socklen_t sslen)
{
int err;
struct addrinfo hints;
struct addrinfo *result = NULL;
if (!host) {
errno = EINVAL;
return -1;
}
if (!port) {
errno = EINVAL;
return -1;
}
if (!ss) {
errno = EINVAL;
return -1;
}
if (!sslen) {
errno = EINVAL;
return -1;
}
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
err = getaddrinfo(host, port, &hints, &result);
if (!err) {
memmove(ss, result->ai_addr,
(sslen < result->ai_addrlen) ? sslen : result->ai_addrlen);
freeaddrinfo(result);
}
if (!err)
errno = 0;
return err;
}
int knet_addrtostr(const struct sockaddr_storage *ss, socklen_t sslen,
char *addr_buf, size_t addr_buf_size,
char *port_buf, size_t port_buf_size)
{
int err;
if (!ss) {
errno = EINVAL;
return -1;
}
if (!sslen) {
errno = EINVAL;
return -1;
}
if (!addr_buf) {
errno = EINVAL;
return -1;
}
if (!port_buf) {
errno = EINVAL;
return -1;
}
err = getnameinfo((struct sockaddr *)ss, sockaddr_len(ss),
addr_buf, addr_buf_size,
port_buf, port_buf_size,
NI_NUMERICHOST | NI_NUMERICSERV);
if (!err)
errno = 0;
return err;
}