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
;
75 /* Initialize sockaddr for bind */
76 sin6ptr
->sin6_family
= family
;
77 sin6ptr
->sin6_addr
= in6addr_any
;
78 sin6ptr
->sin6_port
= htons(*port
);
80 socklen
= sizeof(*sin6ptr
);
81 ret
= bind(server_fd
, (struct sockaddr
*)sin6ptr
, socklen
);
86 ret
= getsockname(server_fd
, (struct sockaddr
*)sin6ptr
, &socklen
);
90 *port
= ntohs(sin6ptr
->sin6_port
);
92 struct sockaddr_in
*sinptr
= (struct sockaddr_in
*)&saddr
;
94 /* Initialize sockaddr for bind */
95 sinptr
->sin_family
= family
;
96 sinptr
->sin_addr
.s_addr
= INADDR_ANY
;
97 sinptr
->sin_port
= htons(*port
);
99 socklen
= sizeof(*sinptr
);
100 ret
= bind(server_fd
, (struct sockaddr
*)sinptr
, socklen
);
105 ret
= getsockname(server_fd
, (struct sockaddr
*)sinptr
, &socklen
);
109 *port
= ntohs(sinptr
->sin_port
);
114 ret
= SOCKET_GET_ERROR();
115 if (server_fd
!= -1) {
116 closesocket(server_fd
);
118 SOCKET_SET_ERROR(ret
);
123 netutils_get_address(void *sockaddr
, int *length
)
125 unsigned char ipv4_prefix
[] = { 0,0,0,0,0,0,0,0,0,0,255,255 };
126 struct sockaddr
*address
= sockaddr
;
131 if (address
->sa_family
== AF_INET
) {
132 struct sockaddr_in
*sin
;
134 sin
= (struct sockaddr_in
*)address
;
135 *length
= sizeof(sin
->sin_addr
.s_addr
);
136 return (unsigned char *)&sin
->sin_addr
.s_addr
;
137 } else if (address
->sa_family
== AF_INET6
) {
138 struct sockaddr_in6
*sin6
;
140 sin6
= (struct sockaddr_in6
*)address
;
141 if (!memcmp(sin6
->sin6_addr
.s6_addr
, ipv4_prefix
, 12)) {
142 /* Actually an embedded IPv4 address */
143 *length
= sizeof(sin6
->sin6_addr
.s6_addr
)-12;
144 return (sin6
->sin6_addr
.s6_addr
+12);
146 *length
= sizeof(sin6
->sin6_addr
.s6_addr
);
147 return sin6
->sin6_addr
.s6_addr
;
155 netutils_parse_address(int family
, const char *src
, void *dst
, int dstlen
)
157 struct addrinfo
*result
;
158 struct addrinfo
*ptr
;
159 struct addrinfo hints
;
163 if (family
!= AF_INET
&& family
!= AF_INET6
) {
170 memset(&hints
, 0, sizeof(hints
));
171 hints
.ai_family
= family
;
172 hints
.ai_flags
= AI_PASSIVE
| AI_NUMERICHOST
;
174 ret
= getaddrinfo(src
, NULL
, &hints
, &result
);
180 for (ptr
=result
; ptr
!=NULL
; ptr
=ptr
->ai_next
) {
181 if (family
== ptr
->ai_family
&& dstlen
>= ptr
->ai_addrlen
) {
182 memcpy(dst
, ptr
->ai_addr
, ptr
->ai_addrlen
);
183 length
= ptr
->ai_addrlen
;
187 freeaddrinfo(result
);