1 /*-*- Mode: C; c-basic-offset: 8 -*-*/
14 #include "socket-util.h"
16 int socket_address_parse(SocketAddress
*a
, const char *s
) {
25 a
->type
= SOCK_STREAM
;
28 /* IPv6 in [x:.....:z]:p notation */
30 if (!(e
= strchr(s
+1, ']')))
33 if (!(n
= strndup(s
+1, e
-s
-1)))
37 if (inet_pton(AF_INET6
, n
, &a
->sockaddr
.in6
.sin6_addr
) <= 0) {
39 return errno
!= 0 ? -errno
: -EINVAL
;
49 if ((r
= safe_atou(e
, &u
)) < 0)
52 if (u
<= 0 || u
> 0xFFFF)
55 a
->sockaddr
.in6
.sin6_family
= AF_INET6
;
56 a
->sockaddr
.in6
.sin6_port
= htons((uint16_t) u
);
57 a
->size
= sizeof(struct sockaddr_in6
);
59 } else if (*s
== '/') {
65 if (l
>= sizeof(a
->sockaddr
.un
.sun_path
))
68 a
->sockaddr
.un
.sun_family
= AF_UNIX
;
69 memcpy(a
->sockaddr
.un
.sun_path
, s
, l
);
70 a
->size
= sizeof(sa_family_t
) + l
+ 1;
72 } else if (*s
== '=') {
73 /* Abstract AF_UNIX socket */
77 if (l
>= sizeof(a
->sockaddr
.un
.sun_path
) - 1)
80 a
->sockaddr
.un
.sun_family
= AF_UNIX
;
81 memcpy(a
->sockaddr
.un
.sun_path
+1, s
+1, l
);
82 a
->size
= sizeof(struct sockaddr_un
);
86 if ((e
= strchr(s
, ':'))) {
89 if ((r
= safe_atou(e
+1, &u
)) < 0)
92 if (u
<= 0 || u
> 0xFFFF)
95 if (!(n
= strndup(s
, e
-s
)))
98 /* IPv4 in w.x.y.z:p notation? */
99 if ((r
= inet_pton(AF_INET
, n
, &a
->sockaddr
.in4
.sin_addr
)) < 0) {
105 /* Gotcha, it's a traditional IPv4 address */
108 a
->sockaddr
.in4
.sin_family
= AF_INET
;
109 a
->sockaddr
.in4
.sin_port
= htons((uint16_t) u
);
110 a
->size
= sizeof(struct sockaddr_in
);
114 if (strlen(n
) > IF_NAMESIZE
-1) {
119 /* Uh, our last resort, an interface name */
120 idx
= if_nametoindex(n
);
126 a
->sockaddr
.in6
.sin6_family
= AF_INET6
;
127 a
->sockaddr
.in6
.sin6_port
= htons((uint16_t) u
);
128 a
->sockaddr
.in6
.sin6_scope_id
= idx
;
129 a
->sockaddr
.in6
.sin6_addr
= in6addr_any
;
130 a
->size
= sizeof(struct sockaddr_in6
);
136 if ((r
= safe_atou(s
, &u
)) < 0)
139 if (u
<= 0 || u
> 0xFFFF)
142 a
->sockaddr
.in6
.sin6_family
= AF_INET6
;
143 a
->sockaddr
.in6
.sin6_port
= htons((uint16_t) u
);
144 a
->sockaddr
.in6
.sin6_addr
= in6addr_any
;
145 a
->size
= sizeof(struct sockaddr_in6
);
152 int socket_address_verify(const SocketAddress
*a
) {
155 switch (socket_address_family(a
)) {
157 if (a
->size
!= sizeof(struct sockaddr_in
))
160 if (a
->sockaddr
.in4
.sin_port
== 0)
166 if (a
->size
!= sizeof(struct sockaddr_in6
))
169 if (a
->sockaddr
.in6
.sin6_port
== 0)
175 if (a
->size
< sizeof(sa_family_t
))
178 if (a
->size
> sizeof(sa_family_t
)) {
180 if (a
->sockaddr
.un
.sun_path
[0] == 0) {
182 if (a
->size
!= sizeof(struct sockaddr_un
))
188 if (!(e
= memchr(a
->sockaddr
.un
.sun_path
, 0, sizeof(a
->sockaddr
.un
.sun_path
))))
191 if (a
->size
!= sizeof(sa_family_t
) + (e
- a
->sockaddr
.un
.sun_path
) + 1)
199 return -EAFNOSUPPORT
;
203 int socket_address_print(const SocketAddress
*a
, char **p
) {
208 if ((r
= socket_address_verify(a
)) < 0)
211 switch (socket_address_family(a
)) {
215 if (!(ret
= new(char, INET_ADDRSTRLEN
+1+5+1)))
218 if (!inet_ntop(AF_INET
, &a
->sockaddr
.in4
.sin_addr
, ret
, INET_ADDRSTRLEN
)) {
223 sprintf(strchr(ret
, 0), ":%u", ntohs(a
->sockaddr
.in4
.sin_port
));
231 if (!(ret
= new(char, 1+INET6_ADDRSTRLEN
+2+5+1)))
235 if (!inet_ntop(AF_INET6
, &a
->sockaddr
.in6
.sin6_addr
, ret
+1, INET6_ADDRSTRLEN
)) {
240 sprintf(strchr(ret
, 0), "]:%u", ntohs(a
->sockaddr
.in6
.sin6_port
));
248 if (a
->size
<= sizeof(sa_family_t
)) {
250 if (!(ret
= strdup("<unamed>")))
253 } else if (a
->sockaddr
.un
.sun_path
[0] == 0) {
256 /* FIXME: We assume we can print the
257 * socket path here and that it hasn't
258 * more than one NUL byte. That is
259 * actually an invalid assumption */
261 if (!(ret
= new(char, sizeof(a
->sockaddr
.un
.sun_path
)+1)))
265 memcpy(ret
+1, a
->sockaddr
.un
.sun_path
+1, sizeof(a
->sockaddr
.un
.sun_path
)-1);
266 ret
[sizeof(a
->sockaddr
.un
.sun_path
)] = 0;
270 if (!(ret
= strdup(a
->sockaddr
.un
.sun_path
)))
283 int socket_address_listen(const SocketAddress
*a
, int backlog
, SocketAddressBindIPv6Only only
, const char *bind_to_device
, int *ret
) {
288 if ((r
= socket_address_verify(a
)) < 0)
291 if ((fd
= socket(socket_address_family(a
), a
->type
| SOCK_NONBLOCK
| SOCK_CLOEXEC
, 0)) < 0)
294 if (socket_address_family(a
) == AF_INET6
&& only
!= SOCKET_ADDRESS_DEFAULT
) {
295 int flag
= only
== SOCKET_ADDRESS_IPV6_ONLY
;
297 if (setsockopt(fd
, IPPROTO_IPV6
, IPV6_V6ONLY
, &flag
, sizeof(flag
)) < 0)
302 if (setsockopt(fd
, SOL_SOCKET
, SO_BINDTODEVICE
, bind_to_device
, strlen(bind_to_device
)+1) < 0)
306 if (setsockopt(fd
, SOL_SOCKET
, SO_REUSEADDR
, &one
, sizeof(one
)) < 0)
309 if (bind(fd
, &a
->sockaddr
.sa
, a
->size
) < 0)
312 if (a
->type
== SOCK_STREAM
)
313 if (listen(fd
, backlog
) < 0)