/
sockaddr-util.h
225 lines (207 loc) · 6.5 KB
/
sockaddr-util.h
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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
/*
* Copyright (c) 2007-2012 Zmanda, Inc. All Rights Reserved.
* Copyright (c) 2013-2016 Carbonite, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Contact information: Carbonite Inc., 756 N Pastoria Ave
* Sunnyvale, CA 94086, USA, or: http://www.zmanda.com
*
* Author: Dustin J. Mitchell <dustin@zmanda.com>
*/
/*
* Utility routines for handling sockaddrs
*/
#ifndef SOCKADDR_UTIL_H
#define SOCKADDR_UTIL_H
#include <arpa/inet.h>
/* Unfortunately, the system-level sockaddr_storage definition can lead to
* C aliasing errors (where the optimizer doesn't notice that two operations
* affect the same datum). We define our own similar type as a union.
*/
typedef union sockaddr_union {
struct sockaddr sa;
struct sockaddr_in sin;
#ifdef WORKING_IPV6
struct sockaddr_in6 sin6;
#endif
#ifdef HAVE_SOCKADDR_STORAGE
struct sockaddr_storage ss; /* not used; just here to make the union full-size */
#endif
} sockaddr_union;
typedef struct amsbind_s {
sockaddr_union addr;
socklen_t_equiv socklen;
} ambind_t;
/* Dump a sockaddr_union using dbprintf
*
* @param sa: the sockaddr to dump
*/
void dump_sockaddr(sockaddr_union * sa);
/* Convert a sockaddr_union to a string.
*
* NOTE: this function is not threadsafe!
*
* @param sa: the sockaddr_union to dump
* @returns: pointer to statically allocated string
*/
char * str_sockaddr(sockaddr_union *sa);
char * str_sockaddr_no_port(sockaddr_union *sa);
/* same but threadsafe, the string is put in strsockaddr
*/
char * str_sockaddr_r(sockaddr_union *sa, char *strsockaddr, socklen_t size);
char * str_sockaddr_no_port_r(sockaddr_union *sa, char *strsockaddr,
socklen_t size);
/* Compare two sockaddr_union objects, optionally comparing
* only the address (and thus ignoring port, flow info, etc.).
*
* @param su1: one sockaddr_union to compare
* @param su2: the other sockaddr_union to compare
* @param addr_only: if true, ignore port, flow info, etc.
* @returns: -1, 0, or 1 for <, ==, >, respectively
*/
int cmp_sockaddr(sockaddr_union *su1,
sockaddr_union *su2,
int addr_only);
/* Parse a string into a sockaddr. This will try all available address
* families.
*
* @param src: the string representation of the address
* @param dst: the sockaddr_union in which to store the result
* @returns: 1 on success, -1 on error, or 0 if unparseable
*/
int str_to_sockaddr(
const char *src,
sockaddr_union *dst);
/* Copy a sockaddr object.
*
* @param dest: destination
* @param src: source
*/
#define copy_sockaddr(dest, src) memcpy((dest), (src), SS_LEN((src)))
/* The "best" address family we support.
*/
/* AF_NATIVE */
#ifdef WORKING_IPV6
#define AF_NATIVE AF_INET6
#else
#define AF_NATIVE AF_INET
#endif
/* Get the family for a sockaddr_union.
*
* @param su: the sockaddr_union to examine
*/
#define SU_GET_FAMILY(su) ((su)->sa.sa_family)
/* Calculate the length of the data in a sockaddr_union.
*
* @param su: the sockaddr_union to examine
* @returns: length of the data in the object
*/
/* SS_LEN(su) */
#ifdef WORKING_IPV6
# define SS_LEN(su) (SU_GET_FAMILY(su)==AF_INET6? sizeof(struct sockaddr_in6):sizeof(struct sockaddr_in))
#else
# define SS_LEN(su) (sizeof(struct sockaddr_in))
#endif
/* Initialize a sockaddr_union to all zeroes (as directed by RFC),
* and set its address family as specified
*
* @param su: sockaddr_union object to initialize
* @param family: an AF_* constant
*/
/* SU_INIT(su, family) */
#define SU_INIT(su, family) do { \
memset((su), 0, sizeof(*(su))); \
(su)->sa.sa_family = (family); \
} while (0);
/* set a sockaddr_union to the family-appropriate equivalent of
* INADDR_ANY -- a wildcard address and port. Call SU_INIT(su)
* first to initialize the object and set the family.
*
* @param su: the sockaddr_union to set
*/
/* SU_SET_INADDR_ANY(su) */
#ifdef WORKING_IPV6
#define SU_SET_INADDR_ANY(su) do { \
switch (SU_GET_FAMILY(su)) { \
case AF_INET6: \
(su)->sin6.sin6_flowinfo = 0; \
(su)->sin6.sin6_addr = in6addr_any; \
break; \
case AF_INET: \
(su)->sin.sin_addr.s_addr = INADDR_ANY; \
break; \
} \
} while (0);
#else
#define SU_SET_INADDR_ANY(su) do { \
(su)->sin.sin_addr.s_addr = INADDR_ANY; \
} while (0);
#endif
/* Set the IP in a sockaddr_union that already has an family
*
* @param su: the sockaddr_union to manipulate
* @param ip: the IP to insert
*/
/* SU_SET_INADDR(su, ip) */
#ifdef WORKING_IPV6
#define SU_SET_INADDR(su, ip) do { \
switch (SU_GET_FAMILY(su)) { \
case AF_INET6: \
(su)->sin6.sin6_flowinfo = 0; \
inet_pton(SU_GET_FAMILY(su), ip, &((su)->sin6.sin6_addr)); \
break; \
case AF_INET: \
inet_pton(SU_GET_FAMILY(su), ip, &((su)->sin.sin_addr)); \
break; \
} \
} while (0);
#else
#define SU_SET_INADDR(su, ip) \
inet_pton(SU_GET_FAMILY(su), ip, &((su)->sin.sin_addr));
#endif
/* Set the port in a sockaddr_union that already has an family
*
* @param su: the sockaddr_union to manipulate
* @param port: the port to insert (in host byte order)
*/
/* SU_SET_PORT(su, port) */
#ifdef WORKING_IPV6
#define SU_SET_PORT(su, port) \
switch (SU_GET_FAMILY(su)) { \
case AF_INET: \
(su)->sin.sin_port = (in_port_t)htons((port)); \
break; \
case AF_INET6: \
(su)->sin6.sin6_port = (in_port_t)htons((port)); \
break; \
default: assert(0); \
}
#else
#define SU_SET_PORT(su, port) \
(su)->sin.sin_port = (in_port_t)htons((port));
#endif
/* Get the port in a sockaddr_union object
*
* @param su: the sockaddr_union to manipulate
* @return: the port, in host byte horder
*/
/* SU_GET_PORT(su) */
#ifdef WORKING_IPV6
#define SU_GET_PORT(su) (ntohs(SU_GET_FAMILY(su) == AF_INET6? (su)->sin6.sin6_port:(su)->sin.sin_port))
#else
#define SU_GET_PORT(su) (ntohs((su)->sin.sin_port))
#endif
#endif /* SOCKADDR_UTIL_H */