1 /***************************************************************************
2  * nsock_internal.h -- PRIVATE interface definitions for the guts of the   *
3  * nsock parallel socket event library. Applications calling this library  *
4  * should NOT include this. even LOOK at these :).                         *
5  *                                                                         *
6  ***********************IMPORTANT NSOCK LICENSE TERMS***********************
7  *                                                                         *
8  * The nsock parallel socket event library is (C) 1999-2017 Insecure.Com   *
9  * LLC This library is free software; you may redistribute and/or          *
10  * modify it under the terms of the GNU General Public License as          *
11  * published by the Free Software Foundation; Version 2.  This guarantees  *
12  * your right to use, modify, and redistribute this software under certain *
13  * conditions.  If this license is unacceptable to you, Insecure.Com LLC   *
14  * may be willing to sell alternative licenses (contact                    *
15  * sales@insecure.com ).                                                   *
16  *                                                                         *
17  * As a special exception to the GPL terms, Insecure.Com LLC grants        *
18  * permission to link the code of this program with any version of the     *
19  * OpenSSL library which is distributed under a license identical to that  *
20  * listed in the included docs/licenses/OpenSSL.txt file, and distribute   *
21  * linked combinations including the two. You must obey the GNU GPL in all *
22  * respects for all of the code used other than OpenSSL.  If you modify    *
23  * this file, you may extend this exception to your version of the file,   *
24  * but you are not obligated to do so.                                     *
25  *                                                                         *
26  * If you received these files with a written license agreement stating    *
27  * terms other than the (GPL) terms above, then that alternative license   *
28  * agreement takes precedence over this comment.                           *
29  *                                                                         *
30  * Source is provided to this software because we believe users have a     *
31  * right to know exactly what a program is going to do before they run it. *
32  * This also allows you to audit the software for security holes.          *
33  *                                                                         *
34  * Source code also allows you to port Nmap to new platforms, fix bugs,    *
35  * and add new features.  You are highly encouraged to send your changes   *
36  * to the dev@nmap.org mailing list for possible incorporation into the    *
37  * main distribution.  By sending these changes to Fyodor or one of the    *
38  * Insecure.Org development mailing lists, or checking them into the Nmap  *
39  * source code repository, it is understood (unless you specify otherwise) *
40  * that you are offering the Nmap Project (Insecure.Com LLC) the           *
41  * unlimited, non-exclusive right to reuse, modify, and relicense the      *
42  * code.  Nmap will always be available Open Source, but this is important *
43  * because the inability to relicense code has caused devastating problems *
44  * for other Free Software projects (such as KDE and NASM).  We also       *
45  * occasionally relicense the code to third parties as discussed above.    *
46  * If you wish to specify special license conditions of your               *
47  * contributions, just say so when you send them.                          *
48  *                                                                         *
49  * This program is distributed in the hope that it will be useful, but     *
50  * WITHOUT ANY WARRANTY; without even the implied warranty of              *
51  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU       *
52  * General Public License v2.0 for more details                            *
53  * (http://www.gnu.org/licenses/gpl-2.0.html).                             *
54  *                                                                         *
55  ***************************************************************************/
56 
57 /* $Id$ */
58 
59 #ifndef NSOCK_INTERNAL_H
60 #define NSOCK_INTERNAL_H
61 
62 #include <nbase.h>
63 
64 #ifdef HAVE_CONFIG_H
65 #include "nsock_config.h"
66 #include "nbase_config.h"
67 #endif
68 
69 #ifdef WIN32
70 #include "nbase_winconfig.h"
71 #include <Winsock2.h>
72 #endif
73 
74 #include "gh_list.h"
75 #include "gh_heap.h"
76 #include "filespace.h"
77 #include "nsock.h" /* The public interface -- I need it for some enum defs */
78 #include "nsock_ssl.h"
79 #include "nsock_proxy.h"
80 
81 #if HAVE_SYS_TIME_H
82 #include <sys/time.h>
83 #endif
84 #if HAVE_UNISTD_H
85 #include <unistd.h>
86 #endif
87 #if HAVE_SYS_SOCKET_H
88 #include <sys/socket.h>
89 #endif
90 #if HAVE_NETINET_IN_H
91 #include <netinet/in.h>
92 #endif
93 #if HAVE_ARPA_INET_H
94 #include <arpa/inet.h>
95 #endif
96 #if HAVE_STRING_H
97 #include <string.h>
98 #endif
99 #if HAVE_STRINGS_H
100 #include <strings.h>
101 #endif
102 #if HAVE_SYS_UN_H
103 #include <sys/un.h>
104 #endif
105 
106 #ifndef IPPROTO_SCTP
107 #define IPPROTO_SCTP 132
108 #endif
109 
110 
111 /* ------------------- CONSTANTS ------------------- */
112 #define READ_BUFFER_SZ 8192
113 
114 enum nsock_read_types {
115   NSOCK_READLINES,
116   NSOCK_READBYTES,
117   NSOCK_READ
118 };
119 
120 enum iod_state {
121   NSIOD_STATE_DELETED,
122   NSIOD_STATE_INITIAL,
123 
124   /* sd was provided to us in nsock_iod_new2 (see nsock_iod.c) */
125   NSIOD_STATE_UNKNOWN,
126 
127   NSIOD_STATE_CONNECTED_TCP,
128   NSIOD_STATE_CONNECTED_UDP
129 };
130 
131 /* XXX: ensure that these values can be OR'ed when adding new ones */
132 #define EV_NONE   0x00
133 #define EV_READ   0x01
134 #define EV_WRITE  0x02
135 #define EV_EXCEPT 0x04
136 
137 
138 /* ------------------- STRUCTURES ------------------- */
139 
140 struct readinfo {
141   enum nsock_read_types read_type;
142   /* num lines; num bytes; whatever (depends on read_type) */
143   int num;
144 };
145 
146 struct writeinfo {
147   struct sockaddr_storage dest;
148   size_t destlen;
149   /* Number of bytes successfully written */
150   int written_so_far;
151 };
152 
153 /* Remember that callers of this library should NOT be accessing these
154  * fields directly */
155 struct npool {
156   /* User data, NULL if unset */
157   void *userdata;
158 
159   /* IO Engine vtable */
160   struct io_engine *engine;
161   /* IO Engine internal data */
162   void *engine_data;
163 
164   /* Active network events */
165   gh_list_t connect_events;
166   gh_list_t read_events;
167   gh_list_t write_events;
168 #if HAVE_PCAP
169   gh_list_t pcap_read_events;
170 #endif
171   gh_heap_t expirables;
172 
173   /* Active iods and related lists of events */
174   gh_list_t active_iods;
175 
176   /* struct niod structures that have been freed for reuse */
177   gh_list_t free_iods;
178   /* When an event is deleted, we stick it here for later reuse */
179   gh_list_t free_events;
180 
181   /* Number of events pending (total) on all lists */
182   int events_pending;
183 
184   /* Serial # of next event (used to create next nsock_event_id */
185   unsigned long next_event_serial;
186   /* Serial # of next iod to be created */
187   unsigned long next_iod_serial;
188 
189   /* If nsock_loop() returns NSOCK_LOOP_ERROR, this is where we describe the
190    * error (errnum fashion) */
191   int errnum;
192 
193   /* If true, new sockets will have SO_BROADCAST set */
194   int broadcast;
195 
196   /* Interface to bind to; only supported on Linux with SO_BINDTODEVICE sockopt. */
197   const char *device;
198 
199   /* If true, exit the next iteration of nsock_loop with a status of
200    * NSOCK_LOOP_QUIT. */
201   int quit;
202 
203 #if HAVE_OPENSSL
204   /* The SSL Context (options and such) */
205   SSL_CTX *sslctx;
206 #endif
207 
208   /* Optional proxy chain (NULL is not set). Can only be set once per NSP (using
209    * nsock_proxychain_new() or nsock_pool_set_proxychain(). */
210   struct proxy_chain *px_chain;
211 
212 };
213 
214 
215 /* nsock_iod is like a "file descriptor" for the nsock library.  You use it to
216  * request events. */
217 struct niod {
218   /* The socket descriptor related to the event */
219   int sd;
220 
221   /* Number of pending events on this iod */
222   int events_pending;
223 
224   /* Pending events */
225   gh_lnode_t *first_connect;
226   gh_lnode_t *first_read;
227   gh_lnode_t *first_write;
228 #if HAVE_PCAP
229   gh_lnode_t *first_pcap_read;
230 #endif
231 
232   int readsd_count;
233   int writesd_count;
234 #if HAVE_PCAP
235   int readpcapsd_count;
236 #endif
237 
238   int watched_events;
239 
240   /* The struct npool used to create the iod (used for deletion) */
241   struct npool *nsp;
242 
243   enum iod_state state;
244 
245   /* The host and port we are connected to using sd (saves a call to getpeername) */
246   struct sockaddr_storage peer;
247   /* The host and port to bind to with sd */
248   struct sockaddr_storage local;
249 
250   /* The length of peer/local actually used (sizeof(sockaddr_in) or
251    * sizeof(sockaddr_in6), SUN_LEN(sockaddr_un), or 0 if peer/local
252    * has not been filled in */
253   size_t locallen;
254   size_t peerlen;
255 
256   /* -1 if none yet, otherwise IPPROTO_TCP, etc. */
257   int lastproto;
258 
259   /* The struct npool keeps track of NIODs that have been allocated so that it
260    * can destroy them if the msp is deleted.  This pointer makes it easy to
261    * remove this struct niod from the allocated list when necessary */
262   gh_lnode_t nodeq;
263 
264 #define IOD_REGISTERED  0x01
265 #define IOD_PROCESSED   0x02    /* internally used by engine_kqueue.c */
266 
267 #define IOD_PROPSET(iod, flag)  ((iod)->_flags |= (flag))
268 #define IOD_PROPCLR(iod, flag)  ((iod)->_flags &= ~(flag))
269 #define IOD_PROPGET(iod, flag)  (((iod)->_flags & (flag)) != 0)
270   char _flags;
271 
272   /* Used for SSL Server Name Indication. */
273   char *hostname;
274 
275 #if HAVE_OPENSSL
276   /* An SSL connection (or NULL if none) */
277   SSL *ssl;
278   /* SSL SESSION ID (or NULL if none) */
279   SSL_SESSION *ssl_session;
280 #else
281   /* Because there are many if (nsi->ssl) cases in the code */
282   char *ssl;
283 #endif
284   /* Every iod has an id which is always unique for the same nspool (unless you
285    * create billions of them) */
286   unsigned long id;
287 
288   /* No. of bytes read from the sd*/
289   unsigned long read_count;
290   /* No. of bytes written to the sd */
291   unsigned long write_count;
292 
293   void *userdata;
294 
295   /* IP options to set on socket before connect() */
296   void *ipopts;
297   int ipoptslen;
298 
299   /* Pointer to mspcap struct (used only if pcap support is included) */
300   void *pcap;
301 
302   struct proxy_chain_context *px_ctx;
303 
304 };
305 
306 
307 /* nsock_event_t handles a single event.  Its ID is generally returned when the
308  * event is created, and the event is included in callbacks */
309 struct nevent {
310   /* Every event has an ID which is unique for a given nsock unless you blow
311    * through more than 500,000,000 events */
312   nsock_event_id id;
313 
314   enum nse_type type;
315   enum nse_status status;
316 
317   /* For write events, this is the data to be written, for read events, this is
318    * what we will read into */
319   struct filespace iobuf;
320 
321   /* The timeout of the event -- absolute time
322    * except that tv_sec == 0 means no timeout */
323   struct timeval timeout;
324 
325   /* Info pertaining to READ requests */
326   struct readinfo readinfo;
327   /* Info pertaining to WRITE requests */
328   struct writeinfo writeinfo;
329 
330 #if HAVE_OPENSSL
331   struct sslinfo sslinfo;
332 #endif
333 
334   /* If we return a status of NSE_STATUS_ERROR, this must be set */
335   int errnum;
336 
337   /* The nsock I/O descriptor related to event (if applicable) */
338   struct niod *iod;
339 
340   /* The handler to call when event is complete */
341   nsock_ev_handler handler;
342 
343   /* slot in the expirable binheap */
344   gh_hnode_t expire;
345 
346   /* For some reasons (see nsock_pcap.c) we register pcap events as both read
347    * and pcap_read events when in PCAP_BSD_SELECT_HACK mode. We then need two
348    * gh_lnode_t handles. To make code simpler, we _always_ use _nodeq_pcap for
349    * pcap_read events and _nodeq_io for the other ones.
350    * When not in PCAP_BSD_SELECT_HACK mode we define both handles as members
351    * of an union to optimize memory footprint. */
352   gh_lnode_t nodeq_io;
353   gh_lnode_t nodeq_pcap;
354 
355   /* Optional (NULL if unset) pointer to pass to the handler */
356   void *userdata;
357 
358   /* If this event is all filled out and ready for immediate delivery,
359    * event_done is nonzero.  Used when event is finished at unexpected time and
360    * we want to dispatch it later to avoid duplicating stat update code and all
361    * that other crap */
362   unsigned int event_done: 1;
363   unsigned int eof: 1;
364 
365 #if HAVE_IOCP
366   struct extended_overlapped *eov;
367 #endif
368 };
369 
370 struct io_operations {
371   int(*iod_connect)(struct npool *nsp, int sockfd, const struct sockaddr *addr, socklen_t addrlen);
372 
373   int(*iod_read)(struct npool *nsp, int sockfd, void *buf, size_t len, int flags,
374     struct sockaddr *src_addr, socklen_t *addrlen);
375 
376   int(*iod_write)(struct npool *nsp, int sockfd, const void *buf, size_t len, int flags,
377     const struct sockaddr *dest_addr, socklen_t addrlen);
378 };
379 
380 struct io_engine {
381   /* Human readable identifier for this engine. */
382   const char *name;
383 
384   /* Engine constructor */
385   int (*init)(struct npool *nsp);
386 
387   /* Engine destructor */
388   void (*destroy)(struct npool *nsp);
389 
390   /* Register a new IOD to the engine */
391   int(*iod_register)(struct npool *nsp, struct niod *iod, struct nevent *nse, int ev);
392 
393   /* Remove a registered IOD */
394   int(*iod_unregister)(struct npool *nsp, struct niod *iod);
395 
396   /* Modify events for a registered IOD.
397    *  - ev_set represent the events to add
398    *  - ev_clr represent the events to delete (if set) */
399   int (*iod_modify)(struct npool *nsp, struct niod *iod, struct nevent *nse, int ev_set, int ev_clr);
400 
401   /* Main engine loop */
402   int (*loop)(struct npool *nsp, int msec_timeout);
403 
404   /* I/O operations */
405   struct io_operations *io_operations;
406 };
407 
408 /* ----------- NSOCK I/O ENGINE CONVENIENCE WRAPPERS ------------ */
nsock_engine_init(struct npool * nsp)409 static inline int nsock_engine_init(struct npool *nsp) {
410   return nsp->engine->init(nsp);
411 }
412 
nsock_engine_destroy(struct npool * nsp)413 static inline void nsock_engine_destroy(struct npool *nsp) {
414   nsp->engine->destroy(nsp);
415   return;
416 }
417 
nsock_engine_iod_register(struct npool * nsp,struct niod * iod,struct nevent * nse,int ev)418 static inline int nsock_engine_iod_register(struct npool *nsp, struct niod *iod, struct nevent *nse, int ev) {
419   return nsp->engine->iod_register(nsp, iod, nse, ev);
420 }
421 
nsock_engine_iod_unregister(struct npool * nsp,struct niod * iod)422 static inline int nsock_engine_iod_unregister(struct npool *nsp, struct niod *iod) {
423   return nsp->engine->iod_unregister(nsp, iod);
424 }
425 
nsock_engine_iod_modify(struct npool * nsp,struct niod * iod,struct nevent * nse,int ev_set,int ev_clr)426 static inline int nsock_engine_iod_modify(struct npool *nsp, struct niod *iod, struct nevent *nse, int ev_set, int ev_clr) {
427   return nsp->engine->iod_modify(nsp, iod, nse, ev_set, ev_clr);
428 }
429 
nsock_engine_loop(struct npool * nsp,int msec_timeout)430 static inline int nsock_engine_loop(struct npool *nsp, int msec_timeout) {
431   return nsp->engine->loop(nsp, msec_timeout);
432 }
433 
434 /* ------------------- PROTOTYPES ------------------- */
435 
436 int event_timedout(struct nevent *nse);
437 
438 /* Get a new nsock_event_id, given a type */
439 nsock_event_id get_new_event_id(struct npool *nsp, enum nse_type type);
440 
441 /* Take an event ID and return the type (NSE_TYPE_CONNECT, etc */
442 enum nse_type get_event_id_type(nsock_event_id event_id);
443 
444 /* Create a new event structure -- must be deleted later with event_delete,
445  * unless it returns NULL (failure).  NULL can be passed in for the struct niod and
446  * the userdata if not available. */
447 struct nevent *event_new(struct npool *nsp, enum nse_type type, struct niod *iod,
448                            int timeout_msecs, nsock_ev_handler handler, void *userdata);
449 
450 /* An internal function for cancelling an event when you already have a pointer
451  * to the struct nevent (use nsock_event_cancel if you just have an ID).  The
452  * event_list passed in should correspond to the type of the event.  For
453  * example, with NSE_TYPE_READ, you would pass in &iod->read_events;.  elem
454  * is the list element in event_list which holds the event.  Pass a nonzero for
455  * notify if you want the program owning the event to be notified that it has
456  * been cancelled */
457 int nevent_delete(struct npool *nsp, struct nevent *nse, gh_list_t *event_list, gh_lnode_t *elem, int notify);
458 
459 /* Adjust various statistics, dispatches the event handler (if notify is
460  * nonzero) and then deletes the event.  This function does NOT delete the event
461  * from any lists it might be on (eg nsp->read_list etc.) nse->event_done
462  * MUST be true when you call this */
463 void event_dispatch_and_delete(struct npool *nsp, struct nevent *nse, int notify);
464 
465 /* Free an struct nevent which was allocated with event_new, including all internal
466  * resources.  Note -- we assume that nse->iod->events_pending (if it exists)
467  * has ALREADY been decremented (done during event_dispatch_and_delete) -- so
468  * remember to do this if you call event_delete() directly */
469 void event_delete(struct npool *nsp, struct nevent *nse);
470 
471 /* Add an event to the appropriate nsp event list, handles housekeeping such as
472  * adjusting the descriptor select/poll lists, registering the timeout value,
473  * etc. */
474 void nsock_pool_add_event(struct npool *nsp, struct nevent *nse);
475 
476 void nsock_connect_internal(struct npool *ms, struct nevent *nse, int type, int proto, struct sockaddr_storage *ss, size_t sslen, unsigned short port);
477 
478 /* Comments on using the following handle_*_result functions are available in nsock_core.c */
479 
480 /* handle_connect_results assumes that select or poll have already shown the
481  * descriptor to be active */
482 void handle_connect_result(struct npool *ms, struct nevent *nse, enum nse_status status);
483 
484 void handle_read_result(struct npool *ms, struct nevent *nse, enum nse_status status);
485 
486 void handle_write_result(struct npool *ms, struct nevent *nse, enum nse_status status);
487 
488 void handle_timer_result(struct npool *ms, struct nevent *nse, enum nse_status status);
489 
490 #if HAVE_PCAP
491 void handle_pcap_read_result(struct npool *ms, struct nevent *nse, enum nse_status status);
492 #endif
493 
494 /* An event has been completed and the handler is about to be called.  This
495  * function writes out tracing data about the event if necessary */
496 void nsock_trace_handler_callback(struct npool *ms, struct nevent *nse);
497 
498 #if HAVE_OPENSSL
499 /* Sets the ssl session of an nsock_iod, increments usage count.  The session
500  * should not have been set yet (as no freeing is done) */
501 void nsi_set_ssl_session(struct niod *iod, SSL_SESSION *sessid);
502 #endif
503 
next_expirable_event(struct npool * nsp)504 static inline struct nevent *next_expirable_event(struct npool *nsp) {
505   gh_hnode_t *hnode;
506 
507   hnode = gh_heap_min(&nsp->expirables);
508   if (!hnode)
509     return NULL;
510 
511   return container_of(hnode, struct nevent, expire);
512 }
513 
lnode_nevent(gh_lnode_t * lnode)514 static inline struct nevent *lnode_nevent(gh_lnode_t *lnode) {
515   return container_of(lnode, struct nevent, nodeq_io);
516 }
517 
lnode_nevent2(gh_lnode_t * lnode)518 static inline struct nevent *lnode_nevent2(gh_lnode_t *lnode) {
519   return container_of(lnode, struct nevent, nodeq_pcap);
520 }
521 
522 #endif /* NSOCK_INTERNAL_H */
523 
524