8c7c5f74914b786f77432eef750e8133dce22c81
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 also listen to IPv4 addresses */
82 ret
= setsockopt(server_fd
, IPPROTO_IPV6
, IPV6_V6ONLY
,
83 (char *) &v6only
, sizeof(v6only
));
88 socklen
= sizeof(*sin6ptr
);
89 ret
= bind(server_fd
, (struct sockaddr
*)sin6ptr
, socklen
);
94 ret
= getsockname(server_fd
, (struct sockaddr
*)sin6ptr
, &socklen
);
98 *port
= ntohs(sin6ptr
->sin6_port
);
100 struct sockaddr_in
*sinptr
= (struct sockaddr_in
*)&saddr
;
102 /* Initialize sockaddr for bind */
103 sinptr
->sin_family
= family
;
104 sinptr
->sin_addr
.s_addr
= INADDR_ANY
;
105 sinptr
->sin_port
= htons(*port
);
107 socklen
= sizeof(*sinptr
);
108 ret
= bind(server_fd
, (struct sockaddr
*)sinptr
, socklen
);
113 ret
= getsockname(server_fd
, (struct sockaddr
*)sinptr
, &socklen
);
117 *port
= ntohs(sinptr
->sin_port
);
122 ret
= SOCKET_GET_ERROR();
123 if (server_fd
!= -1) {
124 closesocket(server_fd
);
126 SOCKET_SET_ERROR(ret
);
131 netutils_get_address(void *sockaddr
, int *length
)
133 unsigned char ipv4_prefix
[] = { 0,0,0,0,0,0,0,0,0,0,255,255 };
134 struct sockaddr
*address
= sockaddr
;
139 if (address
->sa_family
== AF_INET
) {
140 struct sockaddr_in
*sin
;
142 sin
= (struct sockaddr_in
*)address
;
143 *length
= sizeof(sin
->sin_addr
.s_addr
);
144 return (unsigned char *)&sin
->sin_addr
.s_addr
;
145 } else if (address
->sa_family
== AF_INET6
) {
146 struct sockaddr_in6
*sin6
;
148 sin6
= (struct sockaddr_in6
*)address
;
149 if (!memcmp(sin6
->sin6_addr
.s6_addr
, ipv4_prefix
, 12)) {
150 /* Actually an embedded IPv4 address */
151 *length
= sizeof(sin6
->sin6_addr
.s6_addr
)-12;
152 return (sin6
->sin6_addr
.s6_addr
+12);
154 *length
= sizeof(sin6
->sin6_addr
.s6_addr
);
155 return sin6
->sin6_addr
.s6_addr
;
163 netutils_parse_address(int family
, const char *src
, void *dst
, int dstlen
)
165 struct addrinfo
*result
;
166 struct addrinfo
*ptr
;
167 struct addrinfo hints
;
171 if (family
!= AF_INET
&& family
!= AF_INET6
) {
178 memset(&hints
, 0, sizeof(hints
));
179 hints
.ai_family
= family
;
180 hints
.ai_flags
= AI_PASSIVE
| AI_NUMERICHOST
;
182 ret
= getaddrinfo(src
, NULL
, &hints
, &result
);
188 for (ptr
=result
; ptr
!=NULL
; ptr
=ptr
->ai_next
) {
189 if (family
== ptr
->ai_family
&& (unsigned int)dstlen
>= ptr
->ai_addrlen
) {
190 memcpy(dst
, ptr
->ai_addr
, ptr
->ai_addrlen
);
191 length
= ptr
->ai_addrlen
;
195 freeaddrinfo(result
);