1    	/*
2    	 * Copyright (C) 2010-2025 Red Hat, Inc.  All rights reserved.
3    	 *
4    	 * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
5    	 *          Federico Simoncelli <fsimon@kronosnet.org>
6    	 *
7    	 * This software licensed under LGPL-2.0+
8    	 */
9    	
10   	#include "config.h"
11   	
12   	#include <stdlib.h>
13   	#include <string.h>
14   	#include <unistd.h>
15   	#include <errno.h>
16   	#include <pthread.h>
17   	#include <math.h>
18   	#include <sys/time.h>
19   	#include <sys/resource.h>
20   	
21   	#include "internals.h"
22   	#include "crypto.h"
23   	#include "links.h"
24   	#include "compress.h"
25   	#include "compat.h"
26   	#include "common.h"
27   	#include "threads_common.h"
28   	#include "threads_heartbeat.h"
29   	#include "threads_pmtud.h"
30   	#include "threads_dsthandler.h"
31   	#include "threads_rx.h"
32   	#include "threads_tx.h"
33   	#include "transports.h"
34   	#include "transport_common.h"
35   	#include "logging.h"
36   	
37   	static int _init_locks(knet_handle_t knet_h)
38   	{
39   		int savederrno = 0;
40   	
41   		savederrno = pthread_rwlock_init(&knet_h->global_rwlock, NULL);
42   		if (savederrno) {
43   			log_err(knet_h, KNET_SUB_HANDLE, "Unable to initialize list rwlock: %s",
44   				strerror(savederrno));
45   			goto exit_fail;
46   		}
47   	
48   		savederrno = pthread_mutex_init(&knet_h->handle_stats_mutex, NULL);
49   		if (savederrno) {
50   			log_err(knet_h, KNET_SUB_HANDLE, "Unable to initialize handle stats mutex: %s",
51   				strerror(savederrno));
52   			goto exit_fail;
53   		}
54   	
55   		savederrno = pthread_mutex_init(&knet_h->threads_status_mutex, NULL);
56   		if (savederrno) {
57   			log_err(knet_h, KNET_SUB_HANDLE, "Unable to initialize threads status mutex: %s",
58   				strerror(savederrno));
59   			goto exit_fail;
60   		}
61   	
62   		savederrno = pthread_mutex_init(&knet_h->pmtud_mutex, NULL);
63   		if (savederrno) {
64   			log_err(knet_h, KNET_SUB_HANDLE, "Unable to initialize pmtud mutex: %s",
65   				strerror(savederrno));
66   			goto exit_fail;
67   		}
68   	
69   		savederrno = pthread_mutex_init(&knet_h->kmtu_mutex, NULL);
70   		if (savederrno) {
71   			log_err(knet_h, KNET_SUB_HANDLE, "Unable to initialize kernel_mtu mutex: %s",
72   				strerror(savederrno));
73   			goto exit_fail;
74   		}
75   	
76   		savederrno = pthread_cond_init(&knet_h->pmtud_cond, NULL);
77   		if (savederrno) {
78   			log_err(knet_h, KNET_SUB_HANDLE, "Unable to initialize pmtud conditional mutex: %s",
79   				strerror(savederrno));
80   			goto exit_fail;
81   		}
82   	
83   		savederrno = pthread_mutex_init(&knet_h->hb_mutex, NULL);
84   		if (savederrno) {
85   			log_err(knet_h, KNET_SUB_HANDLE, "Unable to initialize hb_thread mutex: %s",
86   				strerror(savederrno));
87   			goto exit_fail;
88   		}
89   	
90   		savederrno = pthread_mutex_init(&knet_h->tx_mutex, NULL);
91   		if (savederrno) {
92   			log_err(knet_h, KNET_SUB_HANDLE, "Unable to initialize tx_thread mutex: %s",
93   				strerror(savederrno));
94   			goto exit_fail;
95   		}
96   	
97   		savederrno = pthread_mutex_init(&knet_h->backoff_mutex, NULL);
98   		if (savederrno) {
99   			log_err(knet_h, KNET_SUB_HANDLE, "Unable to initialize pong timeout backoff mutex: %s",
100  				strerror(savederrno));
101  			goto exit_fail;
102  		}
103  	
104  		savederrno = pthread_mutex_init(&knet_h->tx_seq_num_mutex, NULL);
105  		if (savederrno) {
106  			log_err(knet_h, KNET_SUB_HANDLE, "Unable to initialize tx_seq_num_mutex mutex: %s",
107  				strerror(savederrno));
108  			goto exit_fail;
109  		}
110  	
111  		return 0;
112  	
113  	exit_fail:
114  		errno = savederrno;
115  		return -1;
116  	}
117  	
118  	static void _destroy_locks(knet_handle_t knet_h)
119  	{
120  		pthread_rwlock_destroy(&knet_h->global_rwlock);
121  		pthread_mutex_destroy(&knet_h->pmtud_mutex);
122  		pthread_mutex_destroy(&knet_h->kmtu_mutex);
123  		pthread_cond_destroy(&knet_h->pmtud_cond);
124  		pthread_mutex_destroy(&knet_h->hb_mutex);
125  		pthread_mutex_destroy(&knet_h->tx_mutex);
126  		pthread_mutex_destroy(&knet_h->backoff_mutex);
127  		pthread_mutex_destroy(&knet_h->tx_seq_num_mutex);
128  		pthread_mutex_destroy(&knet_h->threads_status_mutex);
129  		pthread_mutex_destroy(&knet_h->handle_stats_mutex);
130  	}
131  	
132  	static int _init_socks(knet_handle_t knet_h)
133  	{
134  		int savederrno = 0;
135  	
136  		if (_init_socketpair(knet_h, knet_h->dstsockfd)) {
137  			savederrno = errno;
138  			log_err(knet_h, KNET_SUB_HANDLE, "Unable to initialize internal dstsockpair: %s",
139  				strerror(savederrno));
140  			goto exit_fail;
141  		}
142  	
143  		return 0;
144  	
145  	exit_fail:
146  		errno = savederrno;
147  		return -1;
148  	}
149  	
150  	static void _close_socks(knet_handle_t knet_h)
151  	{
152  		_close_socketpair(knet_h, knet_h->dstsockfd);
153  	}
154  	
155  	static int _init_buffers(knet_handle_t knet_h)
156  	{
157  		int savederrno = 0;
158  		unsigned int i;
159  		size_t bufsize;
160  	
161  		for (i = 0; i < PCKT_FRAG_MAX; i++) {
162  			bufsize = ceil((float)KNET_MAX_PACKET_SIZE / (i + 1)) + KNET_HEADER_ALL_SIZE;
163  			knet_h->send_to_links_buf[i] = malloc(bufsize);
164  			if (!knet_h->send_to_links_buf[i]) {
165  				savederrno = errno;
166  				log_err(knet_h, KNET_SUB_HANDLE, "Unable to allocate memory datafd to link buffer: %s",
167  					strerror(savederrno));
168  				goto exit_fail;
169  			}
170  			memset(knet_h->send_to_links_buf[i], 0, bufsize);
171  		}
172  	
173  		for (i = 0; i < PCKT_RX_BUFS; i++) {
174  			knet_h->recv_from_links_buf[i] = malloc(KNET_DATABUFSIZE);
175  			if (!knet_h->recv_from_links_buf[i]) {
176  				savederrno = errno;
177  				log_err(knet_h, KNET_SUB_HANDLE, "Unable to allocate memory for link to datafd buffer: %s",
178  					strerror(savederrno));
179  				goto exit_fail;
180  			}
181  			memset(knet_h->recv_from_links_buf[i], 0, KNET_DATABUFSIZE);
182  		}
183  	
184  		knet_h->recv_from_sock_buf = malloc(KNET_DATABUFSIZE);
185  		if (!knet_h->recv_from_sock_buf) {
186  			savederrno = errno;
187  			log_err(knet_h, KNET_SUB_HANDLE, "Unable to allocate memory for app to datafd buffer: %s",
188  					strerror(savederrno));
189  			goto exit_fail;
190  		}
191  		memset(knet_h->recv_from_sock_buf, 0, KNET_DATABUFSIZE);
192  	
193  		knet_h->pingbuf = malloc(KNET_HEADER_PING_SIZE);
194  		if (!knet_h->pingbuf) {
195  			savederrno = errno;
196  			log_err(knet_h, KNET_SUB_HANDLE, "Unable to allocate memory for hearbeat buffer: %s",
197  				strerror(savederrno));
198  			goto exit_fail;
199  		}
200  		memset(knet_h->pingbuf, 0, KNET_HEADER_PING_SIZE);
201  	
202  		knet_h->pmtudbuf = malloc(KNET_PMTUD_SIZE_V6 + KNET_HEADER_ALL_SIZE);
203  		if (!knet_h->pmtudbuf) {
204  			savederrno = errno;
205  			log_err(knet_h, KNET_SUB_HANDLE, "Unable to allocate memory for pmtud buffer: %s",
206  				strerror(savederrno));
207  			goto exit_fail;
208  		}
209  		memset(knet_h->pmtudbuf, 0, KNET_PMTUD_SIZE_V6 + KNET_HEADER_ALL_SIZE);
210  	
211  		for (i = 0; i < PCKT_FRAG_MAX; i++) {
212  			bufsize = ceil((float)KNET_MAX_PACKET_SIZE / (i + 1)) + KNET_HEADER_ALL_SIZE + KNET_DATABUFSIZE_CRYPT_PAD;
213  			knet_h->send_to_links_buf_crypt[i] = malloc(bufsize);
214  			if (!knet_h->send_to_links_buf_crypt[i]) {
215  				savederrno = errno;
216  				log_err(knet_h, KNET_SUB_HANDLE, "Unable to allocate memory for crypto datafd to link buffer: %s",
217  					strerror(savederrno));
218  				goto exit_fail;
219  			}
220  			memset(knet_h->send_to_links_buf_crypt[i], 0, bufsize);
221  		}
222  	
223  		knet_h->recv_from_links_buf_decrypt = malloc(KNET_DATABUFSIZE_CRYPT);
224  		if (!knet_h->recv_from_links_buf_decrypt) {
225  			savederrno = errno;
226  			log_err(knet_h, KNET_SUB_CRYPTO, "Unable to allocate memory for crypto link to datafd buffer: %s",
227  				strerror(savederrno));
228  			goto exit_fail;
229  		}
230  		memset(knet_h->recv_from_links_buf_decrypt, 0, KNET_DATABUFSIZE_CRYPT);
231  	
232  		knet_h->recv_from_links_buf_crypt = malloc(KNET_DATABUFSIZE_CRYPT);
233  		if (!knet_h->recv_from_links_buf_crypt) {
234  			savederrno = errno;
235  			log_err(knet_h, KNET_SUB_CRYPTO, "Unable to allocate memory for crypto link to datafd buffer: %s",
236  				strerror(savederrno));
237  			goto exit_fail;
238  		}
239  		memset(knet_h->recv_from_links_buf_crypt, 0, KNET_DATABUFSIZE_CRYPT);
240  	
241  		knet_h->pingbuf_crypt = malloc(KNET_DATABUFSIZE_CRYPT);
242  		if (!knet_h->pingbuf_crypt) {
243  			savederrno = errno; 
244  			log_err(knet_h, KNET_SUB_CRYPTO, "Unable to allocate memory for crypto hearbeat buffer: %s",
245  				strerror(savederrno));
246  			goto exit_fail;
247  		}
248  		memset(knet_h->pingbuf_crypt, 0, KNET_DATABUFSIZE_CRYPT);
249  	
250  		knet_h->pmtudbuf_crypt = malloc(KNET_DATABUFSIZE_CRYPT);
251  		if (!knet_h->pmtudbuf_crypt) {
252  			savederrno = errno;
253  			log_err(knet_h, KNET_SUB_HANDLE, "Unable to allocate memory for crypto pmtud buffer: %s",
254  				strerror(savederrno));
255  			goto exit_fail;
256  		}
257  		memset(knet_h->pmtudbuf_crypt, 0, KNET_DATABUFSIZE_CRYPT);
258  	
259  		knet_h->recv_from_links_buf_decompress = malloc(KNET_DATABUFSIZE_COMPRESS);
260  		if (!knet_h->recv_from_links_buf_decompress) {
261  			savederrno = errno;
262  			log_err(knet_h, KNET_SUB_HANDLE, "Unable to allocate memory for decompress buffer: %s",
263  				strerror(savederrno));
264  			goto exit_fail;
265  		}
266  		memset(knet_h->recv_from_links_buf_decompress, 0, KNET_DATABUFSIZE_COMPRESS);
267  	
268  		knet_h->send_to_links_buf_compress = malloc(KNET_DATABUFSIZE_COMPRESS);
269  		if (!knet_h->send_to_links_buf_compress) {
270  			savederrno = errno;
271  			log_err(knet_h, KNET_SUB_HANDLE, "Unable to allocate memory for compress buffer: %s",
272  				strerror(savederrno));
273  			goto exit_fail;
274  		}
275  		memset(knet_h->send_to_links_buf_compress, 0, KNET_DATABUFSIZE_COMPRESS);
276  	
277  		memset(knet_h->knet_transport_fd_tracker, 0, sizeof(knet_h->knet_transport_fd_tracker));
278  		for (i = 0; i < KNET_MAX_FDS; i++) {
279  			knet_h->knet_transport_fd_tracker[i].transport = KNET_MAX_TRANSPORTS;
280  		}
281  	
282  		return 0;
283  	
284  	exit_fail:
285  		errno = savederrno;
286  		return -1;
287  	}
288  	
289  	static void _destroy_buffers(knet_handle_t knet_h)
290  	{
291  		unsigned int i;
292  	
293  		for (i = 0; i < PCKT_FRAG_MAX; i++) {
294  			free(knet_h->send_to_links_buf[i]);
295  			free(knet_h->send_to_links_buf_crypt[i]);
296  		}
297  	
298  		for (i = 0; i < PCKT_RX_BUFS; i++) {
299  			free(knet_h->recv_from_links_buf[i]);
300  		}
301  	
302  		free(knet_h->recv_from_links_buf_decompress);
303  		free(knet_h->send_to_links_buf_compress);
304  		free(knet_h->recv_from_sock_buf);
305  		free(knet_h->recv_from_links_buf_decrypt);
306  		free(knet_h->recv_from_links_buf_crypt);
307  		free(knet_h->pingbuf);
308  		free(knet_h->pingbuf_crypt);
309  		free(knet_h->pmtudbuf);
310  		free(knet_h->pmtudbuf_crypt);
311  	}
312  	
313  	static int _init_epolls(knet_handle_t knet_h)
314  	{
315  		struct epoll_event ev;
316  		int savederrno = 0;
317  	
318  		/*
319  		 * even if the kernel does dynamic allocation with epoll_ctl
320  		 * we need to reserve one extra for host to host communication
321  		 */
322  		knet_h->send_to_links_epollfd = epoll_create(KNET_EPOLL_MAX_EVENTS + 1);
323  		if (knet_h->send_to_links_epollfd < 0) {
324  			savederrno = errno;
325  			log_err(knet_h, KNET_SUB_HANDLE, "Unable to create epoll datafd to link fd: %s",
326  				strerror(savederrno));
327  			goto exit_fail;
328  		}
329  	
330  		knet_h->recv_from_links_epollfd = epoll_create(KNET_EPOLL_MAX_EVENTS);
331  		if (knet_h->recv_from_links_epollfd < 0) {
332  			savederrno = errno;
333  			log_err(knet_h, KNET_SUB_HANDLE, "Unable to create epoll link to datafd fd: %s",
334  				strerror(savederrno));
335  			goto exit_fail;
336  		}
337  	
338  		knet_h->dst_link_handler_epollfd = epoll_create(KNET_EPOLL_MAX_EVENTS);
339  		if (knet_h->dst_link_handler_epollfd < 0) {
340  			savederrno = errno;
341  			log_err(knet_h, KNET_SUB_HANDLE, "Unable to create epoll dst cache fd: %s",
342  				strerror(savederrno));
343  			goto exit_fail;
344  		}
345  	
346  		if (_fdset_cloexec(knet_h->send_to_links_epollfd)) {
347  			savederrno = errno;
348  			log_err(knet_h, KNET_SUB_HANDLE, "Unable to set CLOEXEC on datafd to link epoll fd: %s",
349  				strerror(savederrno)); 
350  			goto exit_fail;
351  		}
352  	
353  		if (_fdset_cloexec(knet_h->recv_from_links_epollfd)) {
354  			savederrno = errno;
355  			log_err(knet_h, KNET_SUB_HANDLE, "Unable to set CLOEXEC on link to datafd epoll fd: %s",
356  				strerror(savederrno)); 
357  			goto exit_fail;
358  		}
359  	
360  		if (_fdset_cloexec(knet_h->dst_link_handler_epollfd)) {
361  			savederrno = errno;
362  			log_err(knet_h, KNET_SUB_HANDLE, "Unable to set CLOEXEC on dst cache epoll fd: %s",
363  				strerror(savederrno)); 
364  			goto exit_fail;
365  		}
366  	
367  		memset(&ev, 0, sizeof(struct epoll_event));
368  		ev.events = EPOLLIN;
369  		ev.data.fd = knet_h->dstsockfd[0];
370  	
371  		if (epoll_ctl(knet_h->dst_link_handler_epollfd,
372  			      EPOLL_CTL_ADD, knet_h->dstsockfd[0], &ev)) {
373  			savederrno = errno;
374  			log_err(knet_h, KNET_SUB_HANDLE, "Unable to add dstsockfd[0] to epoll pool: %s",
375  				strerror(savederrno));
376  			goto exit_fail;
377  		}
378  	
379  		return 0;
380  	
381  	exit_fail:
382  		errno = savederrno;
383  		return -1;
384  	}
385  	
386  	static void _close_epolls(knet_handle_t knet_h)
387  	{
388  		struct epoll_event ev;
389  		int i;
390  	
391  		memset(&ev, 0, sizeof(struct epoll_event));
392  	
393  		for (i = 0; i < KNET_DATAFD_MAX; i++) {
394  			if (knet_h->sockfd[i].in_use) {
395  				epoll_ctl(knet_h->send_to_links_epollfd, EPOLL_CTL_DEL, knet_h->sockfd[i].sockfd[knet_h->sockfd[i].is_created], &ev);
396  				if  (knet_h->sockfd[i].sockfd[knet_h->sockfd[i].is_created]) {
397  					 _close_socketpair(knet_h, knet_h->sockfd[i].sockfd);
398  				}
399  			}
400  		}
401  	
402  		epoll_ctl(knet_h->dst_link_handler_epollfd, EPOLL_CTL_DEL, knet_h->dstsockfd[0], &ev);
403  		close(knet_h->send_to_links_epollfd);
404  		close(knet_h->recv_from_links_epollfd);
405  		close(knet_h->dst_link_handler_epollfd);
406  	}
407  	
408  	static int _start_threads(knet_handle_t knet_h)
409  	{
410  		int savederrno = 0;
411  		pthread_attr_t attr;
412  	
413  		set_thread_status(knet_h, KNET_THREAD_PMTUD, KNET_THREAD_REGISTERED);
414  	
415  		savederrno = pthread_attr_init(&attr);
416  		if (savederrno) {
417  			log_err(knet_h, KNET_SUB_HANDLE, "Unable to init pthread attributes: %s",
418  				strerror(savederrno));
419  			goto exit_fail;
420  		}
421  		savederrno = pthread_attr_setstacksize(&attr, KNET_THREAD_STACK_SIZE);
422  		if (savederrno) {
423  			log_err(knet_h, KNET_SUB_HANDLE, "Unable to set stack size attribute: %s",
424  				strerror(savederrno));
425  			goto exit_fail;
426  		}
427  	
428  		savederrno = pthread_create(&knet_h->pmtud_link_handler_thread, &attr,
429  					    _handle_pmtud_link_thread, (void *) knet_h);
430  		if (savederrno) {
431  			log_err(knet_h, KNET_SUB_HANDLE, "Unable to start pmtud link thread: %s",
432  				strerror(savederrno));
433  			goto exit_fail;
434  		}
435  	
436  		set_thread_status(knet_h, KNET_THREAD_DST_LINK, KNET_THREAD_REGISTERED);
437  		savederrno = pthread_create(&knet_h->dst_link_handler_thread, &attr,
438  					    _handle_dst_link_handler_thread, (void *) knet_h);
439  		if (savederrno) {
440  			log_err(knet_h, KNET_SUB_HANDLE, "Unable to start dst cache thread: %s",
441  				strerror(savederrno));
442  			goto exit_fail;
443  		}
444  	
445  		set_thread_status(knet_h, KNET_THREAD_TX, KNET_THREAD_REGISTERED);
446  		savederrno = pthread_create(&knet_h->send_to_links_thread, &attr,
447  					    _handle_send_to_links_thread, (void *) knet_h);
448  		if (savederrno) {
449  			log_err(knet_h, KNET_SUB_HANDLE, "Unable to start datafd to link thread: %s",
450  				strerror(savederrno));
451  			goto exit_fail;
452  		}
453  	
454  		set_thread_status(knet_h, KNET_THREAD_RX, KNET_THREAD_REGISTERED);
455  		savederrno = pthread_create(&knet_h->recv_from_links_thread, &attr,
456  					    _handle_recv_from_links_thread, (void *) knet_h);
457  		if (savederrno) {
458  			log_err(knet_h, KNET_SUB_HANDLE, "Unable to start link to datafd thread: %s",
459  				strerror(savederrno));
460  			goto exit_fail;
461  		}
462  	
463  		set_thread_status(knet_h, KNET_THREAD_HB, KNET_THREAD_REGISTERED);
464  		savederrno = pthread_create(&knet_h->heartbt_thread, &attr,
465  					    _handle_heartbt_thread, (void *) knet_h);
466  		if (savederrno) {
467  			log_err(knet_h, KNET_SUB_HANDLE, "Unable to start heartbeat thread: %s",
468  				strerror(savederrno));
469  			goto exit_fail;
470  		}
471  	
472  		savederrno = pthread_attr_destroy(&attr);
473  		if (savederrno) {
474  			log_err(knet_h, KNET_SUB_HANDLE, "Unable to destroy pthread attributes: %s",
475  				strerror(savederrno));
476  			/*
477  			 * Do not return error code. Error is not critical.
478  			 */
479  		}
480  	
481  		return 0;
482  	
483  	exit_fail:
484  		errno = savederrno;
485  		return -1;
486  	}
487  	
488  	static void _stop_threads(knet_handle_t knet_h)
489  	{
490  		void *retval;
491  	
492  		wait_all_threads_status(knet_h, KNET_THREAD_STOPPED);
493  	
494  		if (knet_h->heartbt_thread) {
495  			pthread_cancel(knet_h->heartbt_thread);
496  			pthread_join(knet_h->heartbt_thread, &retval);
497  		}
498  	
499  		if (knet_h->send_to_links_thread) {
500  			pthread_cancel(knet_h->send_to_links_thread);
501  			pthread_join(knet_h->send_to_links_thread, &retval);
502  		}
503  	
504  		if (knet_h->recv_from_links_thread) {
505  			pthread_cancel(knet_h->recv_from_links_thread);
506  			pthread_join(knet_h->recv_from_links_thread, &retval);
507  		}
508  	
509  		if (knet_h->dst_link_handler_thread) {
510  			pthread_cancel(knet_h->dst_link_handler_thread);
511  			pthread_join(knet_h->dst_link_handler_thread, &retval);
512  		}
513  	
514  		if (knet_h->pmtud_link_handler_thread) {
515  			pthread_cancel(knet_h->pmtud_link_handler_thread);
516  			pthread_join(knet_h->pmtud_link_handler_thread, &retval);
517  		}
518  	}
519  	
520  	knet_handle_t knet_handle_new_ex(knet_node_id_t host_id,
521  					 int            log_fd,
522  					 uint8_t        default_log_level,
523  					 uint64_t       flags)
524  	{
525  		knet_handle_t knet_h;
526  		int savederrno = 0;
527  		struct rlimit cur;
528  	
529  		if (getrlimit(RLIMIT_NOFILE, &cur) < 0) {
530  			return NULL;
531  		}
532  	
533  		if ((log_fd < 0) || ((unsigned int)log_fd >= cur.rlim_max)) {
534  			errno = EINVAL;
535  			return NULL;
536  		}
537  	
538  		/*
539  		 * validate incoming request
540  		 */
541  	
542  		if ((log_fd) && (default_log_level > KNET_LOG_DEBUG)) {
543  			errno = EINVAL;
544  			return NULL;
545  		}
546  	
547  		if (flags > KNET_HANDLE_FLAG_PRIVILEGED * 2 - 1) {
548  			errno = EINVAL;
549  			return NULL;
550  		}
551  	
552  		/*
553  		 * allocate handle
554  		 */
555  	
556  		knet_h = malloc(sizeof(struct knet_handle));
557  		if (!knet_h) {
558  			errno = ENOMEM;
559  			return NULL;
560  		}
561  		memset(knet_h, 0, sizeof(struct knet_handle));
562  	
563  		/*
564  		 * setting up some handle data so that we can use logging
565  		 * also when initializing the library global locks
566  		 * and trackers
567  		 */
568  	
569  		knet_h->flags = flags;
570  	
571  		/*
572  		 * copy config in place
573  		 */
574  	
575  		knet_h->host_id = host_id;
576  		knet_h->logfd = log_fd;
577  		if (knet_h->logfd > 0) {
578  			memset(&knet_h->log_levels, default_log_level, KNET_MAX_SUBSYSTEMS);
579  		}
580  	
581  		/*
582  		 * set pmtud default timers
583  		 */
584  		knet_h->pmtud_interval = KNET_PMTUD_DEFAULT_INTERVAL;
585  	
586  		/*
587  		 * set transports reconnect default timers
588  		 */
589  		knet_h->reconnect_int = KNET_TRANSPORT_DEFAULT_RECONNECT_INTERVAL;
590  	
591  		/*
592  		 * Set the default path for plugins
593  		 */
594  		knet_h->plugin_path = PLUGINPATH;
595  	
596  		/*
597  		 * Set 'min' stats to the maximum value so the
598  		 * first value we get is always less
599  		 */
600  		knet_h->stats.tx_compress_time_min = UINT64_MAX;
601  		knet_h->stats.rx_compress_time_min = UINT64_MAX;
602  		knet_h->stats.tx_crypt_time_min = UINT64_MAX;
603  		knet_h->stats.rx_crypt_time_min = UINT64_MAX;
604  	
605  		/*
606  		 * init global shared bits
607  		 */
608  		savederrno = pthread_mutex_lock(&handle_config_mutex);
609  		if (savederrno) {
610  			log_err(knet_h, KNET_SUB_HANDLE, "Unable to get handle mutex lock: %s",
611  				strerror(savederrno));
612  			free(knet_h);
613  			knet_h = NULL;
614  			errno = savederrno;
615  			return NULL;
616  		}
617  	
618  		if (!handle_list_init) {
619  			qb_list_init(&handle_list.head);
620  			handle_list_init = 1;
621  		}
622  	
623  		qb_list_add(&knet_h->list, &handle_list.head);
624  	
625  		/*
626  		 * init global shlib tracker
627  		 */
628  		if (_init_shlib_tracker(knet_h) < 0) {
629  			savederrno = errno;
630  			log_err(knet_h, KNET_SUB_HANDLE, "Unable to init handle tracker: %s",
631  				strerror(savederrno));
632  			errno = savederrno;
633  			pthread_mutex_unlock(&handle_config_mutex);
634  			goto exit_fail;
635  		}
636  	
637  		pthread_mutex_unlock(&handle_config_mutex);
638  	
639  		/*
640  		 * init main locking structures
641  		 */
642  	
643  		if (_init_locks(knet_h)) {
644  			savederrno = errno;
645  			goto exit_fail;
646  		}
647  	
648  		/*
649  		 * init sockets
650  		 */
651  	
652  		if (_init_socks(knet_h)) {
653  			savederrno = errno;
654  			goto exit_fail;
655  		}
656  	
657  		/*
658  		 * allocate packet buffers
659  		 */
660  	
661  		if (_init_buffers(knet_h)) {
662  			savederrno = errno;
663  			goto exit_fail;
664  		}
665  	
666  		if (compress_init(knet_h)) {
667  			savederrno = errno;
668  			goto exit_fail;
669  		}
670  	
671  		/*
672  		 * create epoll fds
673  		 */
674  	
675  		if (_init_epolls(knet_h)) {
676  			savederrno = errno;
677  			goto exit_fail;
678  		}
679  	
680  		/*
681  		 * start transports
682  		 */
683  	
684  		if (start_all_transports(knet_h)) {
685  			savederrno = errno;
686  			goto exit_fail;
687  		}
688  	
689  		/*
690  		 * start internal threads
691  		 */
692  	
693  		if (_start_threads(knet_h)) {
694  			savederrno = errno;
695  			goto exit_fail;
696  		}
697  	
698  		wait_all_threads_status(knet_h, KNET_THREAD_STARTED);
699  	
700  		errno = 0;
701  		return knet_h;
702  	
703  	exit_fail:
704  		knet_handle_free(knet_h);
705  		errno = savederrno;
706  		return NULL;
707  	}
708  	
709  	knet_handle_t knet_handle_new(knet_node_id_t host_id,
710  				      int            log_fd,
711  				      uint8_t        default_log_level)
712  	{
713  		return knet_handle_new_ex(host_id, log_fd, default_log_level, KNET_HANDLE_FLAG_PRIVILEGED);
714  	}
715  	
716  	int knet_handle_free(knet_handle_t knet_h)
717  	{
718  		int savederrno = 0;
719  	
720  		if (!_is_valid_handle(knet_h)) {
721  			return -1;
722  		}
723  	
724  		savederrno = get_global_wrlock(knet_h);
725  		if (savederrno) {
726  			log_err(knet_h, KNET_SUB_HANDLE, "Unable to get write lock: %s",
727  				strerror(savederrno));
728  			errno = savederrno;
729  			return -1;
730  		}
731  	
(21) Event example_checked: Example 1: "knet_h->host_head" has its value checked in "knet_h->host_head != NULL".
Also see events: [null_field][example_checked][example_checked][example_checked][example_checked][alias_transfer][dereference]
732  		if (knet_h->host_head != NULL) {
733  			savederrno = EBUSY;
734  			log_err(knet_h, KNET_SUB_HANDLE,
735  				"Unable to free handle: host(s) or listener(s) are still active: %s",
736  				strerror(savederrno));
737  			pthread_rwlock_unlock(&knet_h->global_rwlock);
738  			errno = savederrno;
739  			return -1;
740  		}
741  	
742  		knet_h->fini_in_progress = 1;
743  	
744  		pthread_rwlock_unlock(&knet_h->global_rwlock);
745  	
746  		_stop_threads(knet_h);
747  		stop_all_transports(knet_h);
748  		_close_epolls(knet_h);
749  		_destroy_buffers(knet_h);
750  		_close_socks(knet_h);
751  		crypto_fini(knet_h, KNET_MAX_CRYPTO_INSTANCES + 1); /* values above MAX_CRYPTO will release all crypto resources */
752  		compress_fini(knet_h, 1);
753  		_destroy_locks(knet_h);
754  	
755  		(void)pthread_mutex_lock(&handle_config_mutex);
756  		qb_list_del(&knet_h->list);
757  		_fini_shlib_tracker();
758  		pthread_mutex_unlock(&handle_config_mutex);
759  	
760  		free(knet_h);
761  		knet_h = NULL;
762  	
763  		errno = 0;
764  		return 0;
765  	}
766