2 * Copyright (C) 2011-2012 Juho Vähä-Herttua
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
25 WORD wVersionRequested
;
29 wVersionRequested
= MAKEWORD(2, 2);
30 ret
= WSAStartup(wVersionRequested
, &wsaData
);
35 if (LOBYTE(wsaData
.wVersion
) != 2 ||
36 HIBYTE(wsaData
.wVersion
) != 2) {
37 /* Version mismatch, requested version not found */
53 netutils_init_socket(unsigned short *port
, int use_ipv6
, int use_udp
)
55 int family
= use_ipv6
? AF_INET6
: AF_INET
;
56 int type
= use_udp
? SOCK_DGRAM
: SOCK_STREAM
;
57 int proto
= use_udp
? IPPROTO_UDP
: IPPROTO_TCP
;
59 struct sockaddr_storage saddr
;
66 server_fd
= socket(family
, type
, proto
);
67 if (server_fd
== -1) {
71 memset(&saddr
, 0, sizeof(saddr
));
73 struct sockaddr_in6
*sin6ptr
= (struct sockaddr_in6
*)&saddr
;
76 /* Initialize sockaddr for bind */
77 sin6ptr
->sin6_family
= family
;
78 sin6ptr
->sin6_addr
= in6addr_any
;
79 sin6ptr
->sin6_port
= htons(*port
);
81 /* Make sure we only listen to IPv6 addresses */
82 setsockopt(server_fd
, IPPROTO_IPV6
, IPV6_V6ONLY
,
83 (char *) &v6only
, sizeof(v6only
));
85 socklen
= sizeof(*sin6ptr
);
86 ret
= bind(server_fd
, (struct sockaddr
*)sin6ptr
, socklen
);
91 ret
= getsockname(server_fd
, (struct sockaddr
*)sin6ptr
, &socklen
);
95 *port
= ntohs(sin6ptr
->sin6_port
);
97 struct sockaddr_in
*sinptr
= (struct sockaddr_in
*)&saddr
;
99 /* Initialize sockaddr for bind */
100 sinptr
->sin_family
= family
;
101 sinptr
->sin_addr
.s_addr
= INADDR_ANY
;
102 sinptr
->sin_port
= htons(*port
);
104 socklen
= sizeof(*sinptr
);
105 ret
= bind(server_fd
, (struct sockaddr
*)sinptr
, socklen
);
110 ret
= getsockname(server_fd
, (struct sockaddr
*)sinptr
, &socklen
);
114 *port
= ntohs(sinptr
->sin_port
);
119 ret
= SOCKET_GET_ERROR();
120 if (server_fd
!= -1) {
121 closesocket(server_fd
);
123 SOCKET_SET_ERROR(ret
);
128 netutils_get_address(void *sockaddr
, int *length
)
130 unsigned char ipv4_prefix
[] = { 0,0,0,0,0,0,0,0,0,0,255,255 };
131 struct sockaddr
*address
= sockaddr
;
136 if (address
->sa_family
== AF_INET
) {
137 struct sockaddr_in
*sin
;
139 sin
= (struct sockaddr_in
*)address
;
140 *length
= sizeof(sin
->sin_addr
.s_addr
);
141 return (unsigned char *)&sin
->sin_addr
.s_addr
;
142 } else if (address
->sa_family
== AF_INET6
) {
143 struct sockaddr_in6
*sin6
;
145 sin6
= (struct sockaddr_in6
*)address
;
146 if (!memcmp(sin6
->sin6_addr
.s6_addr
, ipv4_prefix
, 12)) {
147 /* Actually an embedded IPv4 address */
148 *length
= sizeof(sin6
->sin6_addr
.s6_addr
)-12;
149 return (sin6
->sin6_addr
.s6_addr
+12);
151 *length
= sizeof(sin6
->sin6_addr
.s6_addr
);
152 return sin6
->sin6_addr
.s6_addr
;
160 netutils_parse_address(int family
, const char *src
, void *dst
, int dstlen
)
162 struct addrinfo
*result
;
163 struct addrinfo
*ptr
;
164 struct addrinfo hints
;
168 if (family
!= AF_INET
&& family
!= AF_INET6
) {
175 memset(&hints
, 0, sizeof(hints
));
176 hints
.ai_family
= family
;
177 hints
.ai_flags
= AI_PASSIVE
| AI_NUMERICHOST
;
179 ret
= getaddrinfo(src
, NULL
, &hints
, &result
);
185 for (ptr
=result
; ptr
!=NULL
; ptr
=ptr
->ai_next
) {
186 if (family
== ptr
->ai_family
&& (unsigned int)dstlen
>= ptr
->ai_addrlen
) {
187 memcpy(dst
, ptr
->ai_addr
, ptr
->ai_addrlen
);
188 length
= ptr
->ai_addrlen
;
192 freeaddrinfo(result
);