• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Socket module header file */
2 
3 /* Includes needed for the sockaddr_* symbols below */
4 #ifndef MS_WINDOWS
5 #ifdef __VMS
6 #   include <socket.h>
7 # else
8 #   include <sys/socket.h>
9 # endif
10 # include <netinet/in.h>
11 # if !defined(__CYGWIN__)
12 #  include <netinet/tcp.h>
13 # endif
14 
15 #else /* MS_WINDOWS */
16 # include <winsock2.h>
17 /* Windows 'supports' CMSG_LEN, but does not follow the POSIX standard
18  * interface at all, so there is no point including the code that
19  * attempts to use it.
20  */
21 # ifdef PySocket_BUILDING_SOCKET
22 #  undef CMSG_LEN
23 # endif
24 # include <ws2tcpip.h>
25 /* VC6 is shipped with old platform headers, and does not have MSTcpIP.h
26  * Separate SDKs have all the functions we want, but older ones don't have
27  * any version information.
28  * I use SIO_GET_MULTICAST_FILTER to detect a decent SDK.
29  */
30 # ifdef SIO_GET_MULTICAST_FILTER
31 #  include <mstcpip.h> /* for SIO_RCVALL */
32 #  define HAVE_ADDRINFO
33 #  define HAVE_SOCKADDR_STORAGE
34 #  define HAVE_GETADDRINFO
35 #  define HAVE_GETNAMEINFO
36 #  define ENABLE_IPV6
37 # else
38 typedef int socklen_t;
39 # endif /* IPPROTO_IPV6 */
40 #endif /* MS_WINDOWS */
41 
42 #ifdef HAVE_SYS_UN_H
43 # include <sys/un.h>
44 #else
45 # undef AF_UNIX
46 #endif
47 
48 #ifdef HAVE_LINUX_NETLINK_H
49 # ifdef HAVE_ASM_TYPES_H
50 #  include <asm/types.h>
51 # endif
52 # include <linux/netlink.h>
53 #else
54 #  undef AF_NETLINK
55 #endif
56 
57 #ifdef HAVE_BLUETOOTH_BLUETOOTH_H
58 #include <bluetooth/bluetooth.h>
59 #include <bluetooth/rfcomm.h>
60 #include <bluetooth/l2cap.h>
61 #include <bluetooth/sco.h>
62 #include <bluetooth/hci.h>
63 #endif
64 
65 #ifdef HAVE_BLUETOOTH_H
66 #include <bluetooth.h>
67 #endif
68 
69 #ifdef HAVE_NET_IF_H
70 # include <net/if.h>
71 #endif
72 
73 #ifdef HAVE_NETPACKET_PACKET_H
74 # include <sys/ioctl.h>
75 # include <netpacket/packet.h>
76 #endif
77 
78 #ifdef HAVE_LINUX_TIPC_H
79 # include <linux/tipc.h>
80 #endif
81 
82 #ifdef HAVE_LINUX_CAN_H
83 # include <linux/can.h>
84 #else
85 # undef AF_CAN
86 # undef PF_CAN
87 #endif
88 
89 #ifdef HAVE_LINUX_CAN_RAW_H
90 #include <linux/can/raw.h>
91 #endif
92 
93 #ifdef HAVE_LINUX_CAN_BCM_H
94 #include <linux/can/bcm.h>
95 #endif
96 
97 #ifdef HAVE_SYS_SYS_DOMAIN_H
98 #include <sys/sys_domain.h>
99 #endif
100 #ifdef HAVE_SYS_KERN_CONTROL_H
101 #include <sys/kern_control.h>
102 #endif
103 
104 #ifdef HAVE_LINUX_VM_SOCKETS_H
105 # include <linux/vm_sockets.h>
106 #else
107 # undef AF_VSOCK
108 #endif
109 
110 #ifdef HAVE_SOCKADDR_ALG
111 
112 # include <linux/if_alg.h>
113 # ifndef AF_ALG
114 #  define AF_ALG 38
115 # endif
116 # ifndef SOL_ALG
117 #  define SOL_ALG 279
118 # endif
119 
120 /* Linux 3.19 */
121 # ifndef ALG_SET_AEAD_ASSOCLEN
122 #  define ALG_SET_AEAD_ASSOCLEN           4
123 # endif
124 # ifndef ALG_SET_AEAD_AUTHSIZE
125 #  define ALG_SET_AEAD_AUTHSIZE           5
126 # endif
127 /* Linux 4.8 */
128 # ifndef ALG_SET_PUBKEY
129 #  define ALG_SET_PUBKEY                  6
130 # endif
131 
132 # ifndef ALG_OP_SIGN
133 #  define ALG_OP_SIGN                     2
134 # endif
135 # ifndef ALG_OP_VERIFY
136 #  define ALG_OP_VERIFY                   3
137 # endif
138 
139 #endif /* HAVE_SOCKADDR_ALG */
140 
141 
142 #ifndef Py__SOCKET_H
143 #define Py__SOCKET_H
144 #ifdef __cplusplus
145 extern "C" {
146 #endif
147 
148 /* Python module and C API name */
149 #define PySocket_MODULE_NAME    "_socket"
150 #define PySocket_CAPI_NAME      "CAPI"
151 #define PySocket_CAPSULE_NAME   PySocket_MODULE_NAME "." PySocket_CAPI_NAME
152 
153 /* Abstract the socket file descriptor type */
154 #ifdef MS_WINDOWS
155 typedef SOCKET SOCKET_T;
156 #       ifdef MS_WIN64
157 #               define SIZEOF_SOCKET_T 8
158 #       else
159 #               define SIZEOF_SOCKET_T 4
160 #       endif
161 #else
162 typedef int SOCKET_T;
163 #       define SIZEOF_SOCKET_T SIZEOF_INT
164 #endif
165 
166 #if SIZEOF_SOCKET_T <= SIZEOF_LONG
167 #define PyLong_FromSocket_t(fd) PyLong_FromLong((SOCKET_T)(fd))
168 #define PyLong_AsSocket_t(fd) (SOCKET_T)PyLong_AsLong(fd)
169 #else
170 #define PyLong_FromSocket_t(fd) PyLong_FromLongLong((SOCKET_T)(fd))
171 #define PyLong_AsSocket_t(fd) (SOCKET_T)PyLong_AsLongLong(fd)
172 #endif
173 
174 /* Socket address */
175 typedef union sock_addr {
176     struct sockaddr_in in;
177     struct sockaddr sa;
178 #ifdef AF_UNIX
179     struct sockaddr_un un;
180 #endif
181 #ifdef AF_NETLINK
182     struct sockaddr_nl nl;
183 #endif
184 #ifdef ENABLE_IPV6
185     struct sockaddr_in6 in6;
186     struct sockaddr_storage storage;
187 #endif
188 #ifdef HAVE_BLUETOOTH_BLUETOOTH_H
189     struct sockaddr_l2 bt_l2;
190     struct sockaddr_rc bt_rc;
191     struct sockaddr_sco bt_sco;
192     struct sockaddr_hci bt_hci;
193 #endif
194 #ifdef HAVE_NETPACKET_PACKET_H
195     struct sockaddr_ll ll;
196 #endif
197 #ifdef HAVE_LINUX_CAN_H
198     struct sockaddr_can can;
199 #endif
200 #ifdef HAVE_SYS_KERN_CONTROL_H
201     struct sockaddr_ctl ctl;
202 #endif
203 #ifdef HAVE_SOCKADDR_ALG
204     struct sockaddr_alg alg;
205 #endif
206 #ifdef AF_VSOCK
207     struct sockaddr_vm vm;
208 #endif
209 } sock_addr_t;
210 
211 /* The object holding a socket.  It holds some extra information,
212    like the address family, which is used to decode socket address
213    arguments properly. */
214 
215 typedef struct {
216     PyObject_HEAD
217     SOCKET_T sock_fd;           /* Socket file descriptor */
218     int sock_family;            /* Address family, e.g., AF_INET */
219     int sock_type;              /* Socket type, e.g., SOCK_STREAM */
220     int sock_proto;             /* Protocol type, usually 0 */
221     PyObject *(*errorhandler)(void); /* Error handler; checks
222                                         errno, returns NULL and
223                                         sets a Python exception */
224     _PyTime_t sock_timeout;     /* Operation timeout in seconds;
225                                         0.0 means non-blocking */
226 } PySocketSockObject;
227 
228 /* --- C API ----------------------------------------------------*/
229 
230 /* Short explanation of what this C API export mechanism does
231    and how it works:
232 
233     The _ssl module needs access to the type object defined in
234     the _socket module. Since cross-DLL linking introduces a lot of
235     problems on many platforms, the "trick" is to wrap the
236     C API of a module in a struct which then gets exported to
237     other modules via a PyCapsule.
238 
239     The code in socketmodule.c defines this struct (which currently
240     only contains the type object reference, but could very
241     well also include other C APIs needed by other modules)
242     and exports it as PyCapsule via the module dictionary
243     under the name "CAPI".
244 
245     Other modules can now include the socketmodule.h file
246     which defines the needed C APIs to import and set up
247     a static copy of this struct in the importing module.
248 
249     After initialization, the importing module can then
250     access the C APIs from the _socket module by simply
251     referring to the static struct, e.g.
252 
253     Load _socket module and its C API; this sets up the global
254     PySocketModule:
255 
256     if (PySocketModule_ImportModuleAndAPI())
257         return;
258 
259 
260     Now use the C API as if it were defined in the using
261     module:
262 
263     if (!PyArg_ParseTuple(args, "O!|zz:ssl",
264 
265                           PySocketModule.Sock_Type,
266 
267                           (PyObject*)&Sock,
268                           &key_file, &cert_file))
269         return NULL;
270 
271     Support could easily be extended to export more C APIs/symbols
272     this way. Currently, only the type object is exported,
273     other candidates would be socket constructors and socket
274     access functions.
275 
276 */
277 
278 /* C API for usage by other Python modules */
279 typedef struct {
280     PyTypeObject *Sock_Type;
281     PyObject *error;
282     PyObject *timeout_error;
283 } PySocketModule_APIObject;
284 
285 #define PySocketModule_ImportModuleAndAPI() PyCapsule_Import(PySocket_CAPSULE_NAME, 1)
286 
287 #ifdef __cplusplus
288 }
289 #endif
290 #endif /* !Py__SOCKET_H */
291