1/*	$NetBSD: getifaddrs_w32.c,v 1.2 2017/01/28 21:31:50 christos Exp $	*/
2
3/***********************************************************************
4 * Copyright (c) 2009, Secure Endpoints Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * - Redistributions of source code must retain the above copyright
12 *   notice, this list of conditions and the following disclaimer.
13 *
14 * - Redistributions in binary form must reproduce the above copyright
15 *   notice, this list of conditions and the following disclaimer in
16 *   the documentation and/or other materials provided with the
17 *   distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
24 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
30 * OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 **********************************************************************/
33
34#include<config.h>
35
36#include <krb5/roken.h>
37
38#include <ifaddrs.h>
39
40#ifndef _WIN32
41#error This is a Windows specific implementation.
42#endif
43
44static struct sockaddr *
45dupaddr(const sockaddr_gen * src)
46{
47    sockaddr_gen * d = malloc(sizeof(*d));
48
49    if (d) {
50	memcpy(d, src, sizeof(*d));
51    }
52
53    return (struct sockaddr *) d;
54}
55
56int ROKEN_LIB_FUNCTION
57rk_getifaddrs(struct ifaddrs **ifpp)
58{
59    SOCKET s = INVALID_SOCKET;
60    size_t il_len = 8192;
61    int ret = -1;
62    INTERFACE_INFO *il = NULL;
63
64    *ifpp = NULL;
65
66    s = socket(AF_INET, SOCK_DGRAM, 0);
67    if (s == INVALID_SOCKET)
68	return -1;
69
70    for (;;) {
71	DWORD cbret = 0;
72
73	il = malloc(il_len);
74	if (!il)
75	    break;
76
77	ZeroMemory(il, il_len);
78
79	if (WSAIoctl(s, SIO_GET_INTERFACE_LIST, NULL, 0,
80		     (LPVOID) il, (DWORD) il_len, &cbret,
81		     NULL, NULL) == 0) {
82	    il_len = cbret;
83	    break;
84	}
85
86	free (il);
87	il = NULL;
88
89	if (WSAGetLastError() == WSAEFAULT && cbret > il_len) {
90	    il_len = cbret;
91	} else {
92	    break;
93	}
94    }
95
96    if (!il)
97	goto _exit;
98
99    /* il is an array of INTERFACE_INFO structures.  il_len has the
100       actual size of the buffer.  The number of elements is
101       il_len/sizeof(INTERFACE_INFO) */
102
103    {
104	size_t n = il_len / sizeof(INTERFACE_INFO);
105	size_t i;
106
107	for (i = 0; i < n; i++ ) {
108	    struct ifaddrs *ifp;
109
110	    ifp = malloc(sizeof(*ifp));
111	    if (ifp == NULL)
112		break;
113
114	    ZeroMemory(ifp, sizeof(*ifp));
115
116	    ifp->ifa_next = NULL;
117	    ifp->ifa_name = NULL;
118	    ifp->ifa_flags = il[i].iiFlags;
119	    ifp->ifa_addr = dupaddr(&il[i].iiAddress);
120	    ifp->ifa_netmask = dupaddr(&il[i].iiNetmask);
121	    ifp->ifa_broadaddr = dupaddr(&il[i].iiBroadcastAddress);
122	    ifp->ifa_data = NULL;
123
124	    *ifpp = ifp;
125	    ifpp = &ifp->ifa_next;
126	}
127
128	if (i == n)
129	    ret = 0;
130    }
131
132 _exit:
133
134    if (s != INVALID_SOCKET)
135	closesocket(s);
136
137    if (il)
138	free (il);
139
140    return ret;
141}
142
143void ROKEN_LIB_FUNCTION
144rk_freeifaddrs(struct ifaddrs *ifp)
145{
146    struct ifaddrs *p, *q;
147
148    for(p = ifp; p; ) {
149	if (p->ifa_name)
150	    free(p->ifa_name);
151	if(p->ifa_addr)
152	    free(p->ifa_addr);
153	if(p->ifa_dstaddr)
154	    free(p->ifa_dstaddr);
155	if(p->ifa_netmask)
156	    free(p->ifa_netmask);
157	if(p->ifa_data)
158	    free(p->ifa_data);
159	q = p;
160	p = p->ifa_next;
161	free(q);
162    }
163}
164