blob: 1c2116059cb7ad784b99c9e1cba04f4ddb289d80 [file] [log] [blame]
James Kuszmaul4cb043c2021-01-17 11:25:51 -08001/*-
2 * Copyright (c) 2011-2012 Irene Ruengeler
3 * Copyright (c) 2011-2012 Michael Tuexen
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 */
28
29
30#ifdef _WIN32
31#include <netinet/sctp_pcb.h>
32#include <sys/timeb.h>
33#include <iphlpapi.h>
34#pragma comment(lib, "IPHLPAPI.lib")
35#endif
36#include <netinet/sctp_os_userspace.h>
37#if defined(__Userspace_os_FreeBSD)
38#include <pthread_np.h>
39#endif
40
41#if defined(__Userspace_os_Linux)
42#include <sys/prctl.h>
43#endif
44
45#if defined(__Userspace_os_Windows)
46/* Adapter to translate Unix thread start routines to Windows thread start
47 * routines.
48 */
49static DWORD WINAPI
50sctp_create_thread_adapter(void *arg) {
51 start_routine_t start_routine = (start_routine_t)arg;
52 return start_routine(NULL) == NULL;
53}
54
55int
56sctp_userspace_thread_create(userland_thread_t *thread, start_routine_t start_routine)
57{
58 *thread = CreateThread(NULL, 0, sctp_create_thread_adapter,
59 (void *)start_routine, 0, NULL);
60 if (*thread == NULL)
61 return GetLastError();
62 return 0;
63}
64#else
65int
66sctp_userspace_thread_create(userland_thread_t *thread, start_routine_t start_routine)
67{
68 return pthread_create(thread, NULL, start_routine, NULL);
69}
70#endif
71
72void
73sctp_userspace_set_threadname(const char *name)
74{
75#if defined(__Userspace_os_Darwin)
76 pthread_setname_np(name);
77#endif
78#if defined(__Userspace_os_Linux)
79 prctl(PR_SET_NAME, name);
80#endif
81#if defined(__Userspace_os_FreeBSD)
82 pthread_set_name_np(pthread_self(), name);
83#endif
84}
85
86#if !defined(_WIN32) && !defined(__Userspace_os_NaCl)
87int
88sctp_userspace_get_mtu_from_ifn(uint32_t if_index, int af)
89{
90 struct ifreq ifr;
91 int fd;
92
93 memset(&ifr, 0, sizeof(struct ifreq));
94 if_indextoname(if_index, ifr.ifr_name);
95 /* TODO can I use the raw socket here and not have to open a new one with each query? */
96 if ((fd = socket(af, SOCK_DGRAM, 0)) < 0)
97 return (0);
98 if (ioctl(fd, SIOCGIFMTU, &ifr) < 0) {
99 close(fd);
100 return (0);
101 }
102 close(fd);
103 return ifr.ifr_mtu;
104}
105#endif
106
107#if defined(__Userspace_os_NaCl)
108int
109sctp_userspace_get_mtu_from_ifn(uint32_t if_index, int af)
110{
111 return 1280;
112}
113#endif
114
115#ifdef _WIN32
116int
117sctp_userspace_get_mtu_from_ifn(uint32_t if_index, int af)
118{
119 PIP_ADAPTER_ADDRESSES pAdapterAddrs, pAdapt;
120 DWORD AdapterAddrsSize, Err;
121 int ret;
122
123 ret = 0;
124 AdapterAddrsSize = 0;
125 pAdapterAddrs = NULL;
126 if ((Err = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, NULL, &AdapterAddrsSize)) != 0) {
127 if ((Err != ERROR_BUFFER_OVERFLOW) && (Err != ERROR_INSUFFICIENT_BUFFER)) {
128 SCTPDBG(SCTP_DEBUG_USR, "GetAdaptersAddresses() sizing failed with error code %d, AdapterAddrsSize = %d\n", Err, AdapterAddrsSize);
129 ret = -1;
130 goto cleanup;
131 }
132 }
133 if ((pAdapterAddrs = (PIP_ADAPTER_ADDRESSES) GlobalAlloc(GPTR, AdapterAddrsSize)) == NULL) {
134 SCTPDBG(SCTP_DEBUG_USR, "Memory allocation error!\n");
135 ret = -1;
136 goto cleanup;
137 }
138 if ((Err = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, pAdapterAddrs, &AdapterAddrsSize)) != ERROR_SUCCESS) {
139 SCTPDBG(SCTP_DEBUG_USR, "GetAdaptersAddresses() failed with error code %d\n", Err);
140 ret = -1;
141 goto cleanup;
142 }
143 for (pAdapt = pAdapterAddrs; pAdapt; pAdapt = pAdapt->Next) {
144 if (pAdapt->IfIndex == if_index)
145 ret = pAdapt->Mtu;
146 break;
147 }
148cleanup:
149 if (pAdapterAddrs != NULL) {
150 GlobalFree(pAdapterAddrs);
151 }
152 return (ret);
153}
154
155void
156getwintimeofday(struct timeval *tv)
157{
158 struct timeb tb;
159
160 ftime(&tb);
161 tv->tv_sec = (long)tb.time;
162 tv->tv_usec = (long)(tb.millitm) * 1000L;
163}
164
165int
166Win_getifaddrs(struct ifaddrs** interfaces)
167{
168 int ret;
169#if defined(INET) || defined(INET6)
170 DWORD Err, AdapterAddrsSize;
171 int count;
172 PIP_ADAPTER_ADDRESSES pAdapterAddrs, pAdapt;
173 struct ifaddrs *ifa;
174#endif
175#if defined(INET)
176 struct sockaddr_in *addr;
177#endif
178#if defined(INET6)
179 struct sockaddr_in6 *addr6;
180#endif
181#if defined(INET) || defined(INET6)
182 count = 0;
183#endif
184 ret = 0;
185#if defined(INET)
186 AdapterAddrsSize = 0;
187 pAdapterAddrs = NULL;
188 if ((Err = GetAdaptersAddresses(AF_INET, 0, NULL, NULL, &AdapterAddrsSize)) != 0) {
189 if ((Err != ERROR_BUFFER_OVERFLOW) && (Err != ERROR_INSUFFICIENT_BUFFER)) {
190 SCTPDBG(SCTP_DEBUG_USR, "GetAdaptersV4Addresses() sizing failed with error code %d and AdapterAddrsSize = %d\n", Err, AdapterAddrsSize);
191 ret = -1;
192 goto cleanup;
193 }
194 }
195 /* Allocate memory from sizing information */
196 if ((pAdapterAddrs = (PIP_ADAPTER_ADDRESSES) GlobalAlloc(GPTR, AdapterAddrsSize)) == NULL) {
197 SCTPDBG(SCTP_DEBUG_USR, "Memory allocation error!\n");
198 ret = -1;
199 goto cleanup;
200 }
201 /* Get actual adapter information */
202 if ((Err = GetAdaptersAddresses(AF_INET, 0, NULL, pAdapterAddrs, &AdapterAddrsSize)) != ERROR_SUCCESS) {
203 SCTPDBG(SCTP_DEBUG_USR, "GetAdaptersV4Addresses() failed with error code %d\n", Err);
204 ret = -1;
205 goto cleanup;
206 }
207 /* Enumerate through each returned adapter and save its information */
208 for (pAdapt = pAdapterAddrs, count; pAdapt; pAdapt = pAdapt->Next, count++) {
209 addr = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in));
210 ifa = (struct ifaddrs *)malloc(sizeof(struct ifaddrs));
211 if ((addr == NULL) || (ifa == NULL)) {
212 SCTPDBG(SCTP_DEBUG_USR, "Can't allocate memory\n");
213 ret = -1;
214 goto cleanup;
215 }
216 ifa->ifa_name = _strdup(pAdapt->AdapterName);
217 ifa->ifa_flags = pAdapt->Flags;
218 ifa->ifa_addr = (struct sockaddr *)addr;
219 memcpy(addr, &pAdapt->FirstUnicastAddress->Address.lpSockaddr, sizeof(struct sockaddr_in));
220 interfaces[count] = ifa;
221 }
222 GlobalFree(pAdapterAddrs);
223#endif
224#if defined(INET6)
225 AdapterAddrsSize = 0;
226 pAdapterAddrs = NULL;
227 if ((Err = GetAdaptersAddresses(AF_INET6, 0, NULL, NULL, &AdapterAddrsSize)) != 0) {
228 if ((Err != ERROR_BUFFER_OVERFLOW) && (Err != ERROR_INSUFFICIENT_BUFFER)) {
229 SCTPDBG(SCTP_DEBUG_USR, "GetAdaptersV6Addresses() sizing failed with error code %d AdapterAddrsSize = %d\n", Err, AdapterAddrsSize);
230 ret = -1;
231 goto cleanup;
232 }
233 }
234 /* Allocate memory from sizing information */
235 if ((pAdapterAddrs = (PIP_ADAPTER_ADDRESSES) GlobalAlloc(GPTR, AdapterAddrsSize)) == NULL) {
236 SCTPDBG(SCTP_DEBUG_USR, "Memory allocation error!\n");
237 ret = -1;
238 goto cleanup;
239 }
240 /* Get actual adapter information */
241 if ((Err = GetAdaptersAddresses(AF_INET6, 0, NULL, pAdapterAddrs, &AdapterAddrsSize)) != ERROR_SUCCESS) {
242 SCTPDBG(SCTP_DEBUG_USR, "GetAdaptersV6Addresses() failed with error code %d\n", Err);
243 ret = -1;
244 goto cleanup;
245 }
246 /* Enumerate through each returned adapter and save its information */
247 for (pAdapt = pAdapterAddrs, count; pAdapt; pAdapt = pAdapt->Next, count++) {
248 addr6 = (struct sockaddr_in6 *)malloc(sizeof(struct sockaddr_in6));
249 ifa = (struct ifaddrs *)malloc(sizeof(struct ifaddrs));
250 if ((addr6 == NULL) || (ifa == NULL)) {
251 SCTPDBG(SCTP_DEBUG_USR, "Can't allocate memory\n");
252 ret = -1;
253 goto cleanup;
254 }
255 ifa->ifa_name = _strdup(pAdapt->AdapterName);
256 ifa->ifa_flags = pAdapt->Flags;
257 ifa->ifa_addr = (struct sockaddr *)addr6;
258 memcpy(addr6, &pAdapt->FirstUnicastAddress->Address.lpSockaddr, sizeof(struct sockaddr_in6));
259 interfaces[count] = ifa;
260 }
261#endif
262#if defined(INET) || defined(INET6)
263cleanup:
264 if (pAdapterAddrs != NULL) {
265 GlobalFree(pAdapterAddrs);
266 }
267#endif
268 return (ret);
269}
270
271int
272win_if_nametoindex(const char *ifname)
273{
274 IP_ADAPTER_ADDRESSES *addresses, *addr;
275 ULONG status, size;
276 int index = 0;
277
278 if (!ifname) {
279 return 0;
280 }
281
282 size = 0;
283 status = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, NULL, &size);
284 if (status != ERROR_BUFFER_OVERFLOW) {
285 return 0;
286 }
287 addresses = malloc(size);
288 status = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, addresses, &size);
289 if (status == ERROR_SUCCESS) {
290 for (addr = addresses; addr; addr = addr->Next) {
291 if (addr->AdapterName && !strcmp(ifname, addr->AdapterName)) {
292 index = addr->IfIndex;
293 break;
294 }
295 }
296 }
297
298 free(addresses);
299 return index;
300}
301
302#if WINVER < 0x0600
303/* These functions are written based on the code at
304 * http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
305 * Therefore, for the rest of the file the following applies:
306 *
307 *
308 * Copyright and Licensing Information for ACE(TM), TAO(TM), CIAO(TM),
309 * DAnCE(TM), and CoSMIC(TM)
310 *
311 * [1]ACE(TM), [2]TAO(TM), [3]CIAO(TM), DAnCE(TM), and [4]CoSMIC(TM)
312 * (henceforth referred to as "DOC software") are copyrighted by
313 * [5]Douglas C. Schmidt and his [6]research group at [7]Washington
314 * University, [8]University of California, Irvine, and [9]Vanderbilt
315 * University, Copyright (c) 1993-2012, all rights reserved. Since DOC
316 * software is open-source, freely available software, you are free to
317 * use, modify, copy, and distribute--perpetually and irrevocably--the
318 * DOC software source code and object code produced from the source, as
319 * well as copy and distribute modified versions of this software. You
320 * must, however, include this copyright statement along with any code
321 * built using DOC software that you release. No copyright statement
322 * needs to be provided if you just ship binary executables of your
323 * software products.
324 *
325 * You can use DOC software in commercial and/or binary software releases
326 * and are under no obligation to redistribute any of your source code
327 * that is built using DOC software. Note, however, that you may not
328 * misappropriate the DOC software code, such as copyrighting it yourself
329 * or claiming authorship of the DOC software code, in a way that will
330 * prevent DOC software from being distributed freely using an
331 * open-source development model. You needn't inform anyone that you're
332 * using DOC software in your software, though we encourage you to let
333 * [10]us know so we can promote your project in the [11]DOC software
334 * success stories.
335 *
336 * The [12]ACE, [13]TAO, [14]CIAO, [15]DAnCE, and [16]CoSMIC web sites
337 * are maintained by the [17]DOC Group at the [18]Institute for Software
338 * Integrated Systems (ISIS) and the [19]Center for Distributed Object
339 * Computing of Washington University, St. Louis for the development of
340 * open-source software as part of the open-source software community.
341 * Submissions are provided by the submitter ``as is'' with no warranties
342 * whatsoever, including any warranty of merchantability, noninfringement
343 * of third party intellectual property, or fitness for any particular
344 * purpose. In no event shall the submitter be liable for any direct,
345 * indirect, special, exemplary, punitive, or consequential damages,
346 * including without limitation, lost profits, even if advised of the
347 * possibility of such damages. Likewise, DOC software is provided as is
348 * with no warranties of any kind, including the warranties of design,
349 * merchantability, and fitness for a particular purpose,
350 * noninfringement, or arising from a course of dealing, usage or trade
351 * practice. Washington University, UC Irvine, Vanderbilt University,
352 * their employees, and students shall have no liability with respect to
353 * the infringement of copyrights, trade secrets or any patents by DOC
354 * software or any part thereof. Moreover, in no event will Washington
355 * University, UC Irvine, or Vanderbilt University, their employees, or
356 * students be liable for any lost revenue or profits or other special,
357 * indirect and consequential damages.
358 *
359 * DOC software is provided with no support and without any obligation on
360 * the part of Washington University, UC Irvine, Vanderbilt University,
361 * their employees, or students to assist in its use, correction,
362 * modification, or enhancement. A [20]number of companies around the
363 * world provide commercial support for DOC software, however. DOC
364 * software is Y2K-compliant, as long as the underlying OS platform is
365 * Y2K-compliant. Likewise, DOC software is compliant with the new US
366 * daylight savings rule passed by Congress as "The Energy Policy Act of
367 * 2005," which established new daylight savings times (DST) rules for
368 * the United States that expand DST as of March 2007. Since DOC software
369 * obtains time/date and calendaring information from operating systems
370 * users will not be affected by the new DST rules as long as they
371 * upgrade their operating systems accordingly.
372 *
373 * The names ACE(TM), TAO(TM), CIAO(TM), DAnCE(TM), CoSMIC(TM),
374 * Washington University, UC Irvine, and Vanderbilt University, may not
375 * be used to endorse or promote products or services derived from this
376 * source without express written permission from Washington University,
377 * UC Irvine, or Vanderbilt University. This license grants no permission
378 * to call products or services derived from this source ACE(TM),
379 * TAO(TM), CIAO(TM), DAnCE(TM), or CoSMIC(TM), nor does it grant
380 * permission for the name Washington University, UC Irvine, or
381 * Vanderbilt University to appear in their names.
382 *
383 * If you have any suggestions, additions, comments, or questions, please
384 * let [21]me know.
385 *
386 * [22]Douglas C. Schmidt
387 *
388 * References
389 *
390 * 1. http://www.cs.wustl.edu/~schmidt/ACE.html
391 * 2. http://www.cs.wustl.edu/~schmidt/TAO.html
392 * 3. http://www.dre.vanderbilt.edu/CIAO/
393 * 4. http://www.dre.vanderbilt.edu/cosmic/
394 * 5. http://www.dre.vanderbilt.edu/~schmidt/
395 * 6. http://www.cs.wustl.edu/~schmidt/ACE-members.html
396 * 7. http://www.wustl.edu/
397 * 8. http://www.uci.edu/
398 * 9. http://www.vanderbilt.edu/
399 * 10. mailto:doc_group@cs.wustl.edu
400 * 11. http://www.cs.wustl.edu/~schmidt/ACE-users.html
401 * 12. http://www.cs.wustl.edu/~schmidt/ACE.html
402 * 13. http://www.cs.wustl.edu/~schmidt/TAO.html
403 * 14. http://www.dre.vanderbilt.edu/CIAO/
404 * 15. http://www.dre.vanderbilt.edu/~schmidt/DOC_ROOT/DAnCE/
405 * 16. http://www.dre.vanderbilt.edu/cosmic/
406 * 17. http://www.dre.vanderbilt.edu/
407 * 18. http://www.isis.vanderbilt.edu/
408 * 19. http://www.cs.wustl.edu/~schmidt/doc-center.html
409 * 20. http://www.cs.wustl.edu/~schmidt/commercial-support.html
410 * 21. mailto:d.schmidt@vanderbilt.edu
411 * 22. http://www.dre.vanderbilt.edu/~schmidt/
412 * 23. http://www.cs.wustl.edu/ACE.html
413 */
414
415void
416InitializeXPConditionVariable(userland_cond_t *cv)
417{
418 cv->waiters_count = 0;
419 InitializeCriticalSection(&(cv->waiters_count_lock));
420 cv->events_[C_SIGNAL] = CreateEvent (NULL, FALSE, FALSE, NULL);
421 cv->events_[C_BROADCAST] = CreateEvent (NULL, TRUE, FALSE, NULL);
422}
423
424void
425DeleteXPConditionVariable(userland_cond_t *cv)
426{
427 CloseHandle(cv->events_[C_BROADCAST]);
428 CloseHandle(cv->events_[C_SIGNAL]);
429 DeleteCriticalSection(&(cv->waiters_count_lock));
430}
431
432int
433SleepXPConditionVariable(userland_cond_t *cv, userland_mutex_t *mtx)
434{
435 int result, last_waiter;
436
437 EnterCriticalSection(&cv->waiters_count_lock);
438 cv->waiters_count++;
439 LeaveCriticalSection(&cv->waiters_count_lock);
440 LeaveCriticalSection (mtx);
441 result = WaitForMultipleObjects(2, cv->events_, FALSE, INFINITE);
442 if (result==-1) {
443 result = GetLastError();
444 }
445 EnterCriticalSection(&cv->waiters_count_lock);
446 cv->waiters_count--;
447 last_waiter = result == (C_SIGNAL + C_BROADCAST && (cv->waiters_count == 0));
448 LeaveCriticalSection(&cv->waiters_count_lock);
449 if (last_waiter)
450 ResetEvent(cv->events_[C_BROADCAST]);
451 EnterCriticalSection (mtx);
452 return result;
453}
454
455void
456WakeAllXPConditionVariable(userland_cond_t *cv)
457{
458 int have_waiters;
459 EnterCriticalSection(&cv->waiters_count_lock);
460 have_waiters = cv->waiters_count > 0;
461 LeaveCriticalSection(&cv->waiters_count_lock);
462 if (have_waiters)
463 SetEvent (cv->events_[C_BROADCAST]);
464}
465#endif
466#endif