-
Notifications
You must be signed in to change notification settings - Fork 3k
/
Copy pathinet_drv.c
15602 lines (13864 loc) · 455 KB
/
inet_drv.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
* %CopyrightBegin%
*
* Copyright Ericsson AB 1997-2024. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* %CopyrightEnd%
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
/* If we HAVE_SCTP_H and Solaris, we need to define the following in
* order to get SCTP working:
*/
#if (defined(HAVE_SCTP_H) && defined(__sun) && defined(__SVR4))
#define SOLARIS10 1
/* WARNING: This is not quite correct, it may also be Solaris 11! */
#define _XPG4_2
#define __EXTENSIONS__
#endif
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <ctype.h>
#include <sys/types.h>
#include <errno.h>
#include <stdint.h>
#define IDENTITY(c) c
#define STRINGIFY_1(b) IDENTITY(#b)
#define STRINGIFY(a) STRINGIFY_1(a)
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_SYS_UIO_H
#include <sys/uio.h>
#endif
#ifdef HAVE_NET_IF_DL_H
#include <net/if_dl.h>
#endif
#ifdef HAVE_IFADDRS_H
#include <ifaddrs.h>
#endif
#ifdef HAVE_NETPACKET_PACKET_H
#include <netpacket/packet.h>
#endif
#ifdef HAVE_SYS_UN_H
#include <sys/un.h>
#endif
#ifdef HAVE_SENDFILE
#if defined(__linux__) || (defined(__sun) && defined(__SVR4))
#include <sys/sendfile.h>
#elif defined(__FreeBSD__) || defined(__DragonFly__)
/* Need to define __BSD_VISIBLE in order to expose prototype of sendfile */
#define __BSD_VISIBLE 1
#include <sys/socket.h>
#endif
#endif
#if defined(__APPLE__) && defined(__MACH__) && !defined(__DARWIN__)
#define __DARWIN__ 1
#endif
/* All platforms fail on malloc errors. */
#define FATAL_MALLOC
/* The linux kernel sctp include files have an alignment bug
that causes warnings of this type to appear:
drivers/common/inet_drv.c:3196:47: error: taking address of packed member of 'struct sctp_paddr_change' may result in an unaligned pointer value [-Werror=address-of-packed-member]
3196 | i = load_inet_get_address(spec, i, desc, &sptr->spc_aaddr);
So we need to suppress those, without disabling all warning
diagnostics of that type.
See https://lore.kernel.org/patchwork/patch/1108122/ for the
patch that fixes this bug. In a few years we should be able to
remove this suppression. */
#ifdef HAVE_GCC_DIAG_IGNORE_WADDRESS_OF_PACKED_MEMBER
#define PUSH_SUPPRESS_ADDRESS_OF_PACKED_MEMBER() \
_Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Waddress-of-packed-member\"") \
do { } while(0)
#define POP_SUPPRESS_ADDRESS_OF_PACKED_MEMBER() \
_Pragma("GCC diagnostic pop") \
do { } while(0)
#else
#define PUSH_SUPPRESS_ADDRESS_OF_PACKED_MEMBER() \
do { } while(0)
#define POP_SUPPRESS_ADDRESS_OF_PACKED_MEMBER() \
do { } while(0)
#endif
#include "erl_driver.h"
#if !defined(TRUE)
#define TRUE 1
#endif
#if !defined(FALSE)
#define FALSE 0
#endif
/* Descriptor debug */
/* #define INET_DRV_DEBUG 1 */
#ifdef INET_DRV_DEBUG
#define DDBG_DEFAULT TRUE
#else
#define DDBG_DEFAULT FALSE
#endif
#define DDBG(__D__, __ARG__) \
do if ( (__D__)->debug ) { erts_printf __ARG__ ; } while (0)
#define B2S(__B__) ((__B__) ? "true" : "false")
#define SH2S(__H__) (((__H__) == TCP_SHUT_WR) ? "write" : \
(((__H__) == TCP_SHUT_RD) ? "read" : \
(((__H__) == TCP_SHUT_RDWR) ? "read-write" : \
"undefined")))
#define A2S(__A__) (((__A__) == INET_PASSIVE) ? "passive" : \
(((__A__) == INET_ACTIVE) ? "active" : \
(((__A__) == INET_ONCE) ? "once" : \
(((__A__) == INET_MULTI) ? "multi" : \
"undefined"))))
#define M2S(__M__) (((__M__) == INET_MODE_LIST) ? "list" : \
(((__M__) == INET_MODE_BINARY) ? "binary" : \
"undefined"))
#define D2S(__D__) (((__D__) == INET_DELIVER_PORT) ? "port" : \
(((__D__) == INET_DELIVER_TERM) ? "term" : \
"undefined"))
#define DOM2S(__D__) (((__D__) == INET_AF_INET) ? "inet" : \
(((__D__) == INET_AF_INET6) ? "inet6" : \
(((__D__) == INET_AF_LOCAL) ? "local" : \
"undefined")))
#if defined(AF_LINK)
#define FAM2S(__F__) (((__F__) == AF_INET) ? "inet" : \
(((__F__) == AF_INET6) ? "inet6" : \
(((__F__) == AF_LINK) ? "link" : \
"undefined")))
#elif defined(AF_PACKET)
#define FAM2S(__F__) (((__F__) == AF_INET) ? "inet" : \
(((__F__) == AF_INET6) ? "inet6" : \
(((__F__) == AF_PACKET) ? "packet" : \
"undefined")))
#else
#define FAM2S(__F__) (((__F__) == AF_INET) ? "inet" : \
(((__F__) == AF_INET6) ? "inet6" : \
"undefined"))
#endif
#if defined(__WIN32__) && defined(ARCH_64)
#define SOCKET_FSTR "%lld"
#else
#define SOCKET_FSTR "%d"
#endif
/* The IS_SOCKET_ERROR macro below is used for portability reasons. While
POSIX specifies that errors from socket-related system calls should be
indicated with a -1 return value, some users have experienced non-Windows
OS kernels that return negative values other than -1. While one can argue
that such kernels are technically broken, comparing against values less
than 0 covers their out-of-spec return values without imposing incorrect
semantics on systems that manage to correctly return -1 for errors, thus
increasing Erlang's portability.
*/
#ifdef __WIN32__
#define IS_SOCKET_ERROR(val) ((val) == SOCKET_ERROR)
#else
#define IS_SOCKET_ERROR(val) ((val) < 0)
#endif
#ifdef __WIN32__
#define LLU "%I64u"
#else
#define LLU "%llu"
#endif
typedef unsigned long long llu_t;
#ifndef INT16_MIN
#define INT16_MIN (-32768)
#endif
#ifndef INT16_MAX
#define INT16_MAX (32767)
#endif
#ifdef __WIN32__
#define STRNCASECMP strncasecmp
#define INCL_WINSOCK_API_TYPEDEFS 1
#ifndef WINDOWS_H_INCLUDES_WINSOCK2_H
#include <winsock2.h>
#endif
#include <windows.h>
#include <Ws2tcpip.h> /* NEED VC 6.0 or higher */
/* Visual studio 2008+: NTDDI_VERSION needs to be set for iphlpapi.h
to define the right structures. It needs to be set to WINXP (or LONGHORN)
for IPV6 to work and it's set lower by default, so we need to change it. */
#ifdef HAVE_SDKDDKVER_H
# include <sdkddkver.h>
# ifdef NTDDI_VERSION
# undef NTDDI_VERSION
# endif
# define NTDDI_VERSION NTDDI_WINXP
#endif
#include <iphlpapi.h>
#undef WANT_NONBLOCKING
#include "sys.h"
#undef EWOULDBLOCK
#undef ETIMEDOUT
#ifdef EINPROGRESS
#undef EINPROGRESS
#endif
#ifdef EALREADY
#undef EALREADY
#endif
#ifdef ENOTSOCK
#undef ENOTSOCK
#endif
#ifdef EDESTADDRREQ
#undef EDESTADDRREQ
#endif
#ifdef EMSGSIZE
#undef EMSGSIZE
#endif
#ifdef EPROTOTYPE
#undef EPROTOTYPE
#endif
#ifdef ENOPROTOOPT
#undef ENOPROTOOPT
#endif
#ifdef EPROTONOSUPPORT
#undef EPROTONOSUPPORT
#endif
#ifdef EOPNOTSUPP
#undef EOPNOTSUPP
#endif
#ifdef EAFNOSUPPORT
#undef EAFNOSUPPORT
#endif
#ifdef EADDRINUSE
#undef EADDRINUSE
#endif
#ifdef EADDRNOTAVAIL
#undef EADDRNOTAVAIL
#endif
#ifdef ENETDOWN
#undef ENETDOWN
#endif
#ifdef ENETUNREACH
#undef ENETUNREACH
#endif
#ifdef ENETRESET
#undef ENETRESET
#endif
#ifdef ECONNABORTED
#undef ECONNABORTED
#endif
#ifdef ECONNRESET
#undef ECONNRESET
#endif
#ifdef ENOBUFS
#undef ENOBUFS
#endif
#ifdef EISCONN
#undef EISCONN
#endif
#ifdef ENOTCONN
#undef ENOTCONN
#endif
#ifdef ECONNREFUSED
#undef ECONNREFUSED
#endif
#ifdef ELOOP
#undef ELOOP
#endif
#ifdef EHOSTUNREACH
#undef EHOSTUNREACH
#endif
#define HAVE_MULTICAST_SUPPORT
#define HAVE_UDP
#define ERRNO_BLOCK WSAEWOULDBLOCK
#define EWOULDBLOCK WSAEWOULDBLOCK
#define EINPROGRESS WSAEINPROGRESS
#define EALREADY WSAEALREADY
#define ENOTSOCK WSAENOTSOCK
#define EDESTADDRREQ WSAEDESTADDRREQ
#define EMSGSIZE WSAEMSGSIZE
#define EPROTOTYPE WSAEPROTOTYPE
#define ENOPROTOOPT WSAENOPROTOOPT
#define EPROTONOSUPPORT WSAEPROTONOSUPPORT
#define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT
#define EOPNOTSUPP WSAEOPNOTSUPP
#define EPFNOSUPPORT WSAEPFNOSUPPORT
#define EAFNOSUPPORT WSAEAFNOSUPPORT
#define EADDRINUSE WSAEADDRINUSE
#define EADDRNOTAVAIL WSAEADDRNOTAVAIL
#define ENETDOWN WSAENETDOWN
#define ENETUNREACH WSAENETUNREACH
#define ENETRESET WSAENETRESET
#define ECONNABORTED WSAECONNABORTED
#define ECONNRESET WSAECONNRESET
#define ENOBUFS WSAENOBUFS
#define EISCONN WSAEISCONN
#define ENOTCONN WSAENOTCONN
#define ESHUTDOWN WSAESHUTDOWN
#define ETOOMANYREFS WSAETOOMANYREFS
#define ETIMEDOUT WSAETIMEDOUT
#define ECONNREFUSED WSAECONNREFUSED
#define ELOOP WSAELOOP
#undef ENAMETOOLONG
#define ENAMETOOLONG WSAENAMETOOLONG
#define EHOSTDOWN WSAEHOSTDOWN
#define EHOSTUNREACH WSAEHOSTUNREACH
#undef ENOTEMPTY
#define ENOTEMPTY WSAENOTEMPTY
#define EPROCLIM WSAEPROCLIM
#define EUSERS WSAEUSERS
#define EDQUOT WSAEDQUOT
#define ESTALE WSAESTALE
#define EREMOTE WSAEREMOTE
#define INVALID_EVENT WSA_INVALID_EVENT
static BOOL (WINAPI *fpSetHandleInformation)(HANDLE,DWORD,DWORD);
#define sock_open(af, type, proto) \
make_noninheritable_handle(socket((af), (type), (proto)))
#define sock_close(s) closesocket((s))
#define sock_shutdown(s, how) shutdown((s), (how))
#define sock_accept(s, addr, len) \
make_noninheritable_handle(accept((s), (addr), (len)))
#define sock_connect(s, addr, len) connect((s), (addr), (len))
#define sock_listen(s, b) listen((s), (b))
#define sock_bind(s, addr, len) bind((s), (addr), (len))
#define sock_getopt(s,t,n,v,l) getsockopt((s),(t),(n),(v),(l))
#define sock_setopt(s,t,n,v,l) setsockopt((s),(t),(n),(v),(l))
#define sock_name(s, addr, len) getsockname((s), (addr), (len))
#define sock_peer(s, addr, len) getpeername((s), (addr), (len))
#define sock_ntohs(x) ntohs((x))
#define sock_ntohl(x) ntohl((x))
#define sock_htons(x) htons((x))
#define sock_htonl(x) htonl((x))
#define sock_send(s,buf,len,flag) send((s),(buf),(len),(flag))
#define sock_sendv(s, vec, size, np, flag) \
WSASend((s),(WSABUF*)(vec),(size),(np),(flag),NULL,NULL)
#define sock_recv(s,buf,len,flag) recv((s),(buf),(len),(flag))
#define sock_recvfrom(s,buf,blen,flag,addr,alen) \
recvfrom((s),(buf),(blen),(flag),(addr),(alen))
#define sock_sendto(s,buf,blen,flag,addr,alen) \
sendto((s),(buf),(blen),(flag),(addr),(alen))
#define sock_hostname(buf, len) gethostname((buf), (len))
#define sock_getservbyname(name,proto) getservbyname((name),(proto))
#define sock_getservbyport(port,proto) getservbyport((port),(proto))
#define sock_errno() WSAGetLastError()
#define sock_create_event(d) WSACreateEvent()
#define sock_close_event(e) WSACloseEvent(e)
#define sock_select(D, Flags, OnOff) winsock_event_select(D, Flags, OnOff)
#define SET_BLOCKING(s) ioctlsocket(s, FIONBIO, &zero_value)
#define SET_NONBLOCKING(s) ioctlsocket(s, FIONBIO, &one_value)
static unsigned long zero_value = 0;
static unsigned long one_value = 1;
#define TCP_SHUT_WR SD_SEND
#define TCP_SHUT_RD SD_RECEIVE
#define TCP_SHUT_RDWR SD_BOTH
#else /* !__WIN32__ */
#include <sys/time.h>
#ifdef NETDB_H_NEEDS_IN_H
#include <netinet/in.h>
#endif
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#ifdef DEF_INADDR_LOOPBACK_IN_RPC_TYPES_H
#include <rpc/types.h>
#endif
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <sys/param.h>
#ifdef HAVE_ARPA_NAMESER_H
#include <arpa/nameser.h>
#endif
#ifdef HAVE_SYS_SOCKIO_H
#include <sys/sockio.h>
#endif
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
#include <net/if.h>
#ifdef HAVE_SCHED_H
#include <sched.h>
#endif
#ifdef HAVE_SETNS_H
#include <setns.h>
#endif
#define HAVE_UDP
/* SCTP support -- currently for UNIX platforms only: */
#undef HAVE_SCTP
#if defined(HAVE_SCTP_H)
#include <netinet/sctp.h>
/* SCTP Socket API Draft from version 11 on specifies that netinet/sctp.h must
explicitly define HAVE_SCTP in case when SCTP is supported, but Solaris 10
still apparently uses Draft 10, and does not define that symbol, so we have
to define it explicitly:
*/
#ifndef HAVE_SCTP
# define HAVE_SCTP
#endif
/* These changed in draft 11, so SOLARIS10 uses the old MSG_* */
#if ! HAVE_DECL_SCTP_UNORDERED
# define SCTP_UNORDERED MSG_UNORDERED
#endif
#if ! HAVE_DECL_SCTP_ADDR_OVER
# define SCTP_ADDR_OVER MSG_ADDR_OVER
#endif
#if ! HAVE_DECL_SCTP_ABORT
# define SCTP_ABORT MSG_ABORT
#endif
#if ! HAVE_DECL_SCTP_EOF
# define SCTP_EOF MSG_EOF
#endif
/* More Solaris 10 fixes: */
#if ! HAVE_DECL_SCTP_CLOSED && HAVE_DECL_SCTPS_IDLE
# define SCTP_CLOSED SCTPS_IDLE
# undef HAVE_DECL_SCTP_CLOSED
# define HAVE_DECL_SCTP_CLOSED 1
#endif
#if ! HAVE_DECL_SCTP_BOUND && HAVE_DECL_SCTPS_BOUND
# define SCTP_BOUND SCTPS_BOUND
# undef HAVE_DECL_SCTP_BOUND
# define HAVE_DECL_SCTP_BOUND 1
#endif
#if ! HAVE_DECL_SCTP_LISTEN && HAVE_DECL_SCTPS_LISTEN
# define SCTP_LISTEN SCTPS_LISTEN
# undef HAVE_DECL_SCTP_LISTEN
# define HAVE_DECL_SCTP_LISTEN 1
#endif
#if ! HAVE_DECL_SCTP_COOKIE_WAIT && HAVE_DECL_SCTPS_COOKIE_WAIT
# define SCTP_COOKIE_WAIT SCTPS_COOKIE_WAIT
# undef HAVE_DECL_SCTP_COOKIE_WAIT
# define HAVE_DECL_SCTP_COOKIE_WAIT 1
#endif
#if ! HAVE_DECL_SCTP_COOKIE_ECHOED && HAVE_DECL_SCTPS_COOKIE_ECHOED
# define SCTP_COOKIE_ECHOED SCTPS_COOKIE_ECHOED
# undef HAVE_DECL_SCTP_COOKIE_ECHOED
# define HAVE_DECL_SCTP_COOKIE_ECHOED 1
#endif
#if ! HAVE_DECL_SCTP_ESTABLISHED && HAVE_DECL_SCTPS_ESTABLISHED
# define SCTP_ESTABLISHED SCTPS_ESTABLISHED
# undef HAVE_DECL_SCTP_ESTABLISHED
# define HAVE_DECL_SCTP_ESTABLISHED 1
#endif
#if ! HAVE_DECL_SCTP_SHUTDOWN_PENDING && HAVE_DECL_SCTPS_SHUTDOWN_PENDING
# define SCTP_SHUTDOWN_PENDING SCTPS_SHUTDOWN_PENDING
# undef HAVE_DECL_SCTP_SHUTDOWN_PENDING
# define HAVE_DECL_SCTP_SHUTDOWN_PENDING 1
#endif
#if ! HAVE_DECL_SCTP_SHUTDOWN_SENT && HAVE_DECL_SCTPS_SHUTDOWN_SENT
# define SCTP_SHUTDOWN_SENT SCTPS_SHUTDOWN_SENT
# undef HAVE_DECL_SCTP_SHUTDOWN_SENT
# define HAVE_DECL_SCTP_SHUTDOWN_SENT 1
#endif
#if ! HAVE_DECL_SCTP_SHUTDOWN_RECEIVED && HAVE_DECL_SCTPS_SHUTDOWN_RECEIVED
# define SCTP_SHUTDOWN_RECEIVED SCTPS_SHUTDOWN_RECEIVED
# undef HAVE_DECL_SCTP_SHUTDOWN_RECEIVED
# define HAVE_DECL_SCTP_SHUTDOWN_RECEIVED 1
#endif
#if ! HAVE_DECL_SCTP_SHUTDOWN_ACK_SENT && HAVE_DECL_SCTPS_SHUTDOWN_ACK_SENT
# define SCTP_SHUTDOWN_ACK_SENT SCTPS_SHUTDOWN_ACK_SENT
# undef HAVE_DECL_SCTP_SHUTDOWN_ACK_SENT
# define HAVE_DECL_SCTP_SHUTDOWN_ACK_SENT 1
#endif
/* New spelling in lksctp 2.6.22 or maybe even earlier:
* adaption -> adaptation
*/
#if !defined(SCTP_ADAPTATION_LAYER) && defined (SCTP_ADAPTION_LAYER)
# define SCTP_ADAPTATION_LAYER SCTP_ADAPTION_LAYER
# define SCTP_ADAPTATION_INDICATION SCTP_ADAPTION_INDICATION
# define sctp_adaptation_event sctp_adaption_event
# define sctp_setadaptation sctp_setadaption
# define sn_adaptation_event sn_adaption_event
# define sai_adaptation_ind sai_adaption_ind
# define ssb_adaptation_ind ssb_adaption_ind
# define sctp_adaptation_layer_event sctp_adaption_layer_event
#endif
#if defined(__GNUC__) && defined(HAVE_SCTP_BINDX)
static typeof(sctp_bindx) *p_sctp_bindx = NULL;
#else
static int (*p_sctp_bindx)
(int sd, struct sockaddr *addrs, int addrcnt, int flags) = NULL;
#endif
#if defined(__GNUC__) && defined(HAVE_SCTP_PEELOFF)
static typeof(sctp_peeloff) *p_sctp_peeloff = NULL;
#else
static int (*p_sctp_peeloff)
(int sd, sctp_assoc_t assoc_id) = NULL;
#endif
#if defined(__GNUC__) && defined(HAVE_SCTP_GETLADDRS)
static typeof(sctp_getladdrs) *p_sctp_getladdrs = NULL;
#else
static int (*p_sctp_getladdrs)
(int sd, sctp_assoc_t assoc_id, struct sockaddr **ss) = NULL;
#endif
#if defined(__GNUC__) && defined(HAVE_SCTP_FREELADDRS)
static typeof(sctp_freeladdrs) *p_sctp_freeladdrs = NULL;
#else
static void (*p_sctp_freeladdrs)(struct sockaddr *addrs) = NULL;
#endif
#if defined(__GNUC__) && defined(HAVE_SCTP_GETPADDRS)
static typeof(sctp_getpaddrs) *p_sctp_getpaddrs = NULL;
#else
static int (*p_sctp_getpaddrs)
(int sd, sctp_assoc_t assoc_id, struct sockaddr **ss) = NULL;
#endif
#if defined(__GNUC__) && defined(HAVE_SCTP_FREEPADDRS)
static typeof(sctp_freepaddrs) *p_sctp_freepaddrs = NULL;
#else
static void (*p_sctp_freepaddrs)(struct sockaddr *addrs) = NULL;
#endif
#if defined(__GNUC__) && defined(HAVE_SCTP_CONNECTX)
static typeof(sctp_connectx) *p_sctp_connectx = NULL;
#else
static int (*p_sctp_connectx)
(int sd, struct sockaddr * addrs, int addrcnt, sctp_assoc_t * assoc_id) = NULL;
#endif
#endif /* #if defined(HAVE_SCTP_H) */
#ifndef WANT_NONBLOCKING
#define WANT_NONBLOCKING
#endif
#include "sys.h"
#ifdef INET_DRV_DEBUG
#define DEBUG 1
#undef DEBUGF
#define DEBUGF(__X__) erts_printf __X__
#endif
#if !defined(HAVE_STRNCASECMP)
#define STRNCASECMP my_strncasecmp
static int my_strncasecmp(const char *s1, const char *s2, size_t n)
{
int i;
for (i=0;i<n-1 && s1[i] && s2[i] && toupper(s1[i]) == toupper(s2[i]);++i)
;
return (toupper(s1[i]) - toupper(s2[i]));
}
#else
#define STRNCASECMP strncasecmp
#endif
#define INVALID_SOCKET -1
#define INVALID_EVENT -1
#define SOCKET_ERROR -1
#define SOCKET int
#define HANDLE long int
#define FD_READ ERL_DRV_READ
#define FD_WRITE ERL_DRV_WRITE
#define FD_CLOSE 0
#define FD_CONNECT ERL_DRV_WRITE
#define FD_ACCEPT ERL_DRV_READ
#define sock_connect(s, addr, len) connect((s), (addr), (len))
#define sock_listen(s, b) listen((s), (b))
#define sock_bind(s, addr, len) bind((s), (addr), (len))
#define sock_getopt(s,t,n,v,l) getsockopt((s),(t),(n),(v),(l))
#define sock_setopt(s,t,n,v,l) setsockopt((s),(t),(n),(v),(l))
#define sock_name(s, addr, len) getsockname((s), (addr), (len))
#define sock_peer(s, addr, len) getpeername((s), (addr), (len))
#define sock_ntohs(x) ntohs((x))
#define sock_ntohl(x) ntohl((x))
#define sock_htons(x) htons((x))
#define sock_htonl(x) htonl((x))
#define sock_accept(s, addr, len) accept((s), (addr), (len))
#define sock_send(s,buf,len,flag) send((s),(buf),(len),(flag))
#define sock_sendto(s,buf,blen,flag,addr,alen) \
sendto((s),(buf),(blen),(flag),(addr),(alen))
#define sock_sendv(s, vec, size, np, flag) \
(*(np) = writev((s), (struct iovec*)(vec), (size)))
#define sock_sendmsg(s,msghdr,flag) sendmsg((s),(msghdr),(flag))
#define sock_open(af, type, proto) socket((af), (type), (proto))
#define sock_close(s) close((s))
#define sock_shutdown(s, how) shutdown((s), (how))
#define sock_hostname(buf, len) gethostname((buf), (len))
#define sock_getservbyname(name,proto) getservbyname((name), (proto))
#define sock_getservbyport(port,proto) getservbyport((port), (proto))
#define sock_recv(s,buf,len,flag) recv((s),(buf),(len),(flag))
#define sock_recvfrom(s,buf,blen,flag,addr,alen) \
recvfrom((s),(buf),(blen),(flag),(addr),(alen))
#define sock_recvmsg(s,msghdr,flag) recvmsg((s),(msghdr),(flag))
#define sock_errno() errno
#define sock_create_event(d) ((d)->s) /* return file descriptor */
#define sock_close_event(e) /* do nothing */
#define inet_driver_select(port, e, mode, on) \
driver_select(port, e, mode | (on?ERL_DRV_USE:0), on)
#define sock_select(d, flags, onoff) do { \
ASSERT(!INET_IGNORED(d)); \
(d)->event_mask = (onoff) ? \
((d)->event_mask | (flags)) : \
((d)->event_mask & ~(flags)); \
DEBUGF(("(%s / %d) sock_select(%p): flags=%02X, onoff=%d, event_mask=%02lX\r\n", \
__FILE__, __LINE__, (d)->port, (flags), (onoff), (unsigned long) (d)->event_mask)); \
inet_driver_select((d)->port, (ErlDrvEvent)(long)(d)->event, (flags), (onoff)); \
} while(0)
#define TCP_SHUT_WR SHUT_WR
#define TCP_SHUT_RD SHUT_RD
#define TCP_SHUT_RDWR SHUT_RDWR
#endif /* !__WIN32__ */
#ifdef HAVE_SOCKLEN_T
# define SOCKLEN_T socklen_t
#elif defined(__WIN32__)
# define SOCKLEN_T int
#else
# warning "Non-Windows OS without type 'socklen_t'"
# define SOCKLEN_T size_t
#endif
#include "packet_parser.h"
#if defined(HAVE_SYS_UN_H) || defined(SO_BINDTODEVICE)
/* strnlen doesn't exist everywhere */
static size_t my_strnlen(const char *s, size_t maxlen)
{
size_t i = 0;
while (i < maxlen && s[i] != '\0')
i++;
return i;
}
#endif
#ifdef VALGRIND
# include <valgrind/memcheck.h>
#else
# define VALGRIND_MAKE_MEM_DEFINED(ptr,size)
#endif
#ifndef __WIN32__
/* Calculate CMSG_NXTHDR without having a struct msghdr*.
* CMSG_LEN only caters for alignment for start of data.
* To get how much to advance we need to use CMSG_SPACE
* on the payload length. To get the payload length we
* take the calculated cmsg->cmsg_len and subtract the
* header length. To get the header length we use
* the pointer difference from the cmsg start pointer
* to the CMSG_DATA(cmsg) pointer.
*
* Some platforms (seen on ppc Linux 2.6.29-3.ydl61.3)
* may return 0 as the cmsg_len if the cmsg is to be ignored.
*/
#define LEN_CMSG_DATA(cmsg) \
((cmsg)->cmsg_len < sizeof (struct cmsghdr) ? 0 : \
(cmsg)->cmsg_len - ((char*)CMSG_DATA(cmsg) - (char*)(cmsg)))
#define NXT_CMSG_HDR(cmsg) \
((struct cmsghdr*)(((char*)(cmsg)) + CMSG_SPACE(LEN_CMSG_DATA(cmsg))))
#endif
#if !defined(IPV6_PKTOPTIONS) && defined(IPV6_2292PKTOPTIONS)
#define IPV6_PKTOPTIONS IPV6_2292PKTOPTIONS
#endif
/*
Magic errno value used locally for return of {error, system_limit}
- the emulator definition of SYSTEM_LIMIT is not available here.
*/
#define INET_ERRNO_SYSTEM_LIMIT (15 << 8)
/*----------------------------------------------------------------------------
** Interface constants.
**
** This section must be "identical" to the corresponding inet_int.hrl
*/
/* general address encode/decode tag */
#define INET_AF_UNSPEC 0
#define INET_AF_INET 1
#define INET_AF_INET6 2
#define INET_AF_ANY 3 /* INADDR_ANY or IN6ADDR_ANY_INIT */
#define INET_AF_LOOPBACK 4 /* INADDR_LOOPBACK or IN6ADDR_LOOPBACK_INIT */
#define INET_AF_LOCAL 5
#define INET_AF_UNDEFINED 6 /* Unknown */
#define INET_AF_LIST 7 /* List of addresses for sctp connectx */
/* open and INET_REQ_GETTYPE enumeration */
#define INET_TYPE_STREAM 1
#define INET_TYPE_DGRAM 2
#define INET_TYPE_SEQPACKET 3
/* INET_LOPT_MODE options */
#define INET_MODE_LIST 0
#define INET_MODE_BINARY 1
/* INET_LOPT_DELIVER options */
#define INET_DELIVER_PORT 0
#define INET_DELIVER_TERM 1
/* INET_LOPT_ACTIVE options */
#define INET_PASSIVE 0 /* false */
#define INET_ACTIVE 1 /* true */
#define INET_ONCE 2 /* true; active once then passive */
#define INET_MULTI 3 /* true; active N then passive */
/* INET_REQ_GETSTATUS enumeration */
#define INET_F_OPEN 0x0001
/* INET_F_BOUND removed - renumber when there comes a bigger rewrite */
#define INET_F_ACTIVE 0x0004
#define INET_F_LISTEN 0x0008
#define INET_F_CON 0x0010
#define INET_F_ACC 0x0020
#define INET_F_LST 0x0040
#define INET_F_BUSY 0x0080
#define INET_F_MULTI_CLIENT 0x0100 /* Multiple clients for one descriptor, i.e. multi-accept */
/* One numberspace for *_REQ_* so if an e.g UDP request is issued
** for a TCP socket, the driver can protest.
*/
#define INET_REQ_OPEN 1
#define INET_REQ_CLOSE 2
#define INET_REQ_CONNECT 3
#define INET_REQ_PEER 4
#define INET_REQ_NAME 5
#define INET_REQ_BIND 6
#define INET_REQ_SETOPTS 7
#define INET_REQ_GETOPTS 8
/* #define INET_REQ_GETIX 9 NOT USED ANY MORE */
/* #define INET_REQ_GETIF 10 REPLACE BY NEW STUFF */
#define INET_REQ_GETSTAT 11
#define INET_REQ_GETHOSTNAME 12
#define INET_REQ_FDOPEN 13
#define INET_REQ_GETFD 14
#define INET_REQ_GETTYPE 15
#define INET_REQ_GETSTATUS 16
#define INET_REQ_GETSERVBYNAME 17
#define INET_REQ_GETSERVBYPORT 18
#define INET_REQ_SETNAME 19
#define INET_REQ_SETPEER 20
#define INET_REQ_GETIFLIST 21
#define INET_REQ_IFGET 22
#define INET_REQ_IFSET 23
#define INET_REQ_SUBSCRIBE 24
#define INET_REQ_GETIFADDRS 25
#define INET_REQ_ACCEPT 26
#define INET_REQ_LISTEN 27
#define INET_REQ_IGNOREFD 28
#define INET_REQ_GETLADDRS 29
#define INET_REQ_GETPADDRS 30
/* TCP requests */
/* #define TCP_REQ_ACCEPT 40 MOVED */
/* #define TCP_REQ_LISTEN 41 MERGED */
#define TCP_REQ_RECV 42
#define TCP_REQ_UNRECV 43
#define TCP_REQ_SHUTDOWN 44
#define TCP_REQ_SENDFILE 45
/* UDP and SCTP requests */
#define PACKET_REQ_RECV 60 /* Common for UDP and SCTP */
/* #define SCTP_REQ_LISTEN 61 MERGED Different from TCP; not for UDP */
#define SCTP_REQ_BINDX 62 /* Multi-home SCTP bind */
#define SCTP_REQ_PEELOFF 63
/* INET_REQ_SUBSCRIBE sub-requests */
#define INET_SUBS_EMPTY_OUT_Q 1
/* TCP additional flags */
#define TCP_ADDF_DELAY_SEND 1
#define TCP_ADDF_CLOSE_SENT 2 /* Close sent (active mode only) */
#define TCP_ADDF_DELAYED_CLOSE_RECV 4 /* If receive fails, report {error,closed} (passive mode) */
#define TCP_ADDF_DELAYED_CLOSE_SEND 8 /* If send fails, report {error,closed} (passive mode) */
#define TCP_ADDF_PENDING_SHUT_WR 16 /* Call shutdown(sock, SHUT_WR) when queue empties */
#define TCP_ADDF_PENDING_SHUT_RDWR 32 /* Call shutdown(sock, SHUT_RDWR) when queue empties */
#define TCP_ADDF_PENDING_SHUTDOWN \
(TCP_ADDF_PENDING_SHUT_WR | TCP_ADDF_PENDING_SHUT_RDWR)
#define TCP_ADDF_SHOW_ECONNRESET 64 /* Tell user about incoming RST */
#define TCP_ADDF_DELAYED_ECONNRESET 128 /* An ECONNRESET error occurred on send or shutdown */
#define TCP_ADDF_SHUTDOWN_WR_DONE 256 /* A shutdown(sock, SHUT_WR) or SHUT_RDWR was made */
#define TCP_ADDF_LINGER_ZERO 512 /* Discard driver queue on port close */
#define TCP_ADDF_SENDFILE 1024 /* Send from an fd instead of the driver queue */
#define TCP_ADDF_NO_READ_AHEAD 2048 /* Don't read ahead in packet modes */
/* *_REQ_* replies */
#define INET_REP_ERROR 0
#define INET_REP_OK 1
#define INET_REP 2
/* INET_REQ_SETOPTS and INET_REQ_GETOPTS options */
#define INET_OPT_REUSEADDR 0 /* enable/disable local address reuse */
#define INET_OPT_KEEPALIVE 1 /* enable/disable keep connections alive */
#define INET_OPT_DONTROUTE 2 /* enable/disable routing for messages */
#define INET_OPT_LINGER 3 /* linger on close if data is present */
#define INET_OPT_BROADCAST 4 /* enable/disable transmission of broadcast */
#define INET_OPT_OOBINLINE 5 /* enable/disable out-of-band data in band */
#define INET_OPT_SNDBUF 6 /* set send buffer size */
#define INET_OPT_RCVBUF 7 /* set receive buffer size */
#define INET_OPT_PRIORITY 8 /* set priority */
#define INET_OPT_TOS 9 /* Set type of service */
#define TCP_OPT_NODELAY 10 /* don't delay send to coalesce packets */
#define UDP_OPT_MULTICAST_IF 11 /* set/get IP multicast interface */
#define UDP_OPT_MULTICAST_TTL 12 /* set/get IP multicast timetolive */
#define UDP_OPT_MULTICAST_LOOP 13 /* set/get IP multicast loopback */
#define UDP_OPT_ADD_MEMBERSHIP 14 /* add an IP group membership */
#define UDP_OPT_DROP_MEMBERSHIP 15 /* drop an IP group membership */
#define INET_OPT_IPV6_V6ONLY 16 /* IPv6 only socket, no mapped v4 addrs */
#define INET_OPT_REUSEPORT 17 /* enable/disable local port reuse */
#define INET_OPT_REUSEPORT_LB 18 /* enable/disable local port reuse */
#define INET_OPT_EXCLUSIVEADDRUSE 19 /* windows specific exclusive addr */
/* LOPT is local options */
#define INET_LOPT_BUFFER 20 /* min buffer size hint */
#define INET_LOPT_HEADER 21 /* list header size */
#define INET_LOPT_ACTIVE 22 /* enable/disable active receive */
#define INET_LOPT_PACKET 23 /* packet header type (TCP) */
#define INET_LOPT_MODE 24 /* list or binary mode */
#define INET_LOPT_DELIVER 25 /* port or term delivery */
#define INET_LOPT_EXITONCLOSE 26 /* exit port on active close or not ! */
#define INET_LOPT_TCP_HIWTRMRK 27 /* set local high watermark */
#define INET_LOPT_TCP_LOWTRMRK 28 /* set local low watermark */
/* 29 unused */
#define INET_LOPT_TCP_SEND_TIMEOUT 30 /* set send timeout */
#define INET_LOPT_TCP_DELAY_SEND 31 /* Delay sends until next poll */
#define INET_LOPT_PACKET_SIZE 32 /* Max packet size */
#define INET_LOPT_UDP_READ_PACKETS 33 /* Number of packets to read */
#define INET_OPT_RAW 34 /* Raw socket options */
#define INET_LOPT_TCP_SEND_TIMEOUT_CLOSE 35 /* auto-close on send timeout or not */
#define INET_LOPT_MSGQ_HIWTRMRK 36 /* set local msgq high watermark */
#define INET_LOPT_MSGQ_LOWTRMRK 37 /* set local msgq low watermark */
#define INET_LOPT_NETNS 38 /* Network namespace pathname */
#define INET_LOPT_TCP_SHOW_ECONNRESET 39 /* tell user about incoming RST */
#define INET_LOPT_LINE_DELIM 40 /* Line delimiting char */
#define INET_OPT_TCLASS 41 /* IPv6 transport class */
#define INET_OPT_BIND_TO_DEVICE 42 /* get/set network device the socket is bound to */
#define INET_OPT_RECVTOS 43 /* IP_RECVTOS ancillary data */
#define INET_OPT_RECVTCLASS 44 /* IPV6_RECVTCLASS ancillary data */
#define INET_OPT_PKTOPTIONS 45 /* IP(V6)_PKTOPTIONS get ancillary data */
#define INET_OPT_TTL 46 /* IP_TTL */
#define INET_OPT_RECVTTL 47 /* IP_RECVTTL ancillary data */
#define TCP_OPT_NOPUSH 48 /* super-Nagle, aka TCP_CORK */
#define INET_LOPT_TCP_READ_AHEAD 49 /* Read ahead of packet data */
#define INET_LOPT_NON_BLOCK_SEND 50 /* Non-blocking send, only SCTP */
#define INET_LOPT_DEBUG 99 /* Enable/disable DEBUG for a socket */
/* SCTP options: a separate range, from 100: */
#define SCTP_OPT_RTOINFO 100
#define SCTP_OPT_ASSOCINFO 101
#define SCTP_OPT_INITMSG 102
#define SCTP_OPT_AUTOCLOSE 103
#define SCTP_OPT_NODELAY 104
#define SCTP_OPT_DISABLE_FRAGMENTS 105
#define SCTP_OPT_I_WANT_MAPPED_V4_ADDR 106
#define SCTP_OPT_MAXSEG 107
#define SCTP_OPT_SET_PEER_PRIMARY_ADDR 108
#define SCTP_OPT_PRIMARY_ADDR 109
#define SCTP_OPT_ADAPTATION_LAYER 110
#define SCTP_OPT_PEER_ADDR_PARAMS 111
#define SCTP_OPT_DEFAULT_SEND_PARAM 112
#define SCTP_OPT_EVENTS 113
#define SCTP_OPT_DELAYED_ACK_TIME 114
#define SCTP_OPT_STATUS 115
#define SCTP_OPT_GET_PEER_ADDR_INFO 116
/* INET_REQ_IFGET and INET_REQ_IFSET options */
#define INET_IFOPT_ADDR 1
#define INET_IFOPT_BROADADDR 2
#define INET_IFOPT_DSTADDR 3
#define INET_IFOPT_MTU 4
#define INET_IFOPT_NETMASK 5
#define INET_IFOPT_FLAGS 6
#define INET_IFOPT_HWADDR 7
/* INET_REQ_GETSTAT enumeration */
#define INET_STAT_RECV_CNT 1
#define INET_STAT_RECV_MAX 2
#define INET_STAT_RECV_AVG 3
#define INET_STAT_RECV_DVI 4
#define INET_STAT_SEND_CNT 5
#define INET_STAT_SEND_MAX 6
#define INET_STAT_SEND_AVG 7
#define INET_STAT_SEND_PND 8
#define INET_STAT_RECV_OCT 9 /* received octets */
#define INET_STAT_SEND_OCT 10 /* sent octets */
/* INET_IFOPT_FLAGS enumeration */
#define INET_IFF_UP 0x0001
#define INET_IFF_BROADCAST 0x0002
#define INET_IFF_LOOPBACK 0x0004
#define INET_IFF_POINTTOPOINT 0x0008
#define INET_IFF_RUNNING 0x0010
#define INET_IFF_MULTICAST 0x0020
/* Complement flags for turning them off */
#define INET_IFF_DOWN 0x0100
#define INET_IFF_NBROADCAST 0x0200
/* #define INET_IFF_NLOOPBACK 0x0400 */
#define INET_IFF_NPOINTTOPOINT 0x0800
/* #define INET_IFF_NRUNNING 0x1000 */
/* #define INET_IFF_NMULTICAST 0x2000 */
/* Flags for "sctp_sndrcvinfo". Used in a bitmask -- must be powers of 2:
** INET_REQ_SETOPTS:SCTP_OPT_DEFAULT_SEND_PARAM
*/
#define SCTP_FLAG_UNORDERED (1 /* am_unordered */)
#define SCTP_FLAG_ADDR_OVER (2 /* am_addr_over */)
#define SCTP_FLAG_ABORT (4 /* am_abort */)
#define SCTP_FLAG_EOF (8 /* am_eof */)
#define SCTP_FLAG_SNDALL (16 /* am_sndall, NOT YET IMPLEMENTED */)
/* Flags for "sctp_set_opts" (actually for SCTP_OPT_PEER_ADDR_PARAMS).
** These flags are also used in a bitmask, so they must be powers of 2:
*/
#define SCTP_FLAG_HB_ENABLE (1 /* am_hb_enable */)
#define SCTP_FLAG_HB_DISABLE (2 /* am_hb_disable */)
#define SCTP_FLAG_HB_DEMAND (4 /* am_hb_demand */)
#define SCTP_FLAG_PMTUD_ENABLE (8 /* am_pmtud_enable */)
#define SCTP_FLAG_PMTUD_DISABLE (16 /* am_pmtud_disable */)
#define SCTP_FLAG_SACDELAY_ENABLE (32 /* am_sackdelay_enable */)
#define SCTP_FLAG_SACDELAY_DISABLE (64 /* am_sackdelay_disable */)
/* Flags for recv_cmsgflags */
#define INET_CMSG_RECVTOS (1 << 0) /* am_recvtos, am_tos */
#define INET_CMSG_RECVTCLASS (1 << 1) /* am_recvtclass, am_tclass */
#define INET_CMSG_RECVTTL (1 << 2) /* am_recvttl, am_ttl */
/* Inet flags */
#define INET_FLG_BUFFER_SET (1 << 0) /* am_buffer has been set by user */