corosync  2.4.3
totemudp.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2005 MontaVista Software, Inc.
3  * Copyright (c) 2006-2012 Red Hat, Inc.
4  *
5  * All rights reserved.
6  *
7  * Author: Steven Dake (sdake@redhat.com)
8 
9  * This software licensed under BSD license, the text of which follows:
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions are met:
13  *
14  * - Redistributions of source code must retain the above copyright notice,
15  * this list of conditions and the following disclaimer.
16  * - Redistributions in binary form must reproduce the above copyright notice,
17  * this list of conditions and the following disclaimer in the documentation
18  * and/or other materials provided with the distribution.
19  * - Neither the name of the MontaVista Software, Inc. nor the names of its
20  * contributors may be used to endorse or promote products derived from this
21  * software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
27  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
33  * THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 #include <config.h>
37 
38 #include <assert.h>
39 #include <pthread.h>
40 #include <sys/mman.h>
41 #include <sys/types.h>
42 #include <sys/stat.h>
43 #include <sys/socket.h>
44 #include <netdb.h>
45 #include <sys/un.h>
46 #include <sys/ioctl.h>
47 #include <sys/param.h>
48 #include <netinet/in.h>
49 #include <arpa/inet.h>
50 #include <unistd.h>
51 #include <fcntl.h>
52 #include <stdlib.h>
53 #include <stdio.h>
54 #include <errno.h>
55 #include <sched.h>
56 #include <time.h>
57 #include <sys/time.h>
58 #include <sys/poll.h>
59 #include <sys/uio.h>
60 #include <limits.h>
61 
62 #include <corosync/sq.h>
63 #include <corosync/swab.h>
64 #include <corosync/list.h>
65 #include <qb/qbdefs.h>
66 #include <qb/qbloop.h>
67 #define LOGSYS_UTILS_ONLY 1
68 #include <corosync/logsys.h>
69 #include "totemudp.h"
70 
71 #include "util.h"
72 #include "totemcrypto.h"
73 
74 #include <nss.h>
75 #include <pk11pub.h>
76 #include <pkcs11.h>
77 #include <prerror.h>
78 
79 #ifndef MSG_NOSIGNAL
80 #define MSG_NOSIGNAL 0
81 #endif
82 
83 #define MCAST_SOCKET_BUFFER_SIZE (TRANSMITS_ALLOWED * FRAME_SIZE_MAX)
84 #define NETIF_STATE_REPORT_UP 1
85 #define NETIF_STATE_REPORT_DOWN 2
86 
87 #define BIND_STATE_UNBOUND 0
88 #define BIND_STATE_REGULAR 1
89 #define BIND_STATE_LOOPBACK 2
90 
94  int token;
95  /*
96  * Socket used for local multicast delivery. We don't rely on multicast
97  * loop and rather this UNIX DGRAM socket is used. Socket is created by
98  * socketpair call and they are used in same way as pipe (so [0] is read
99  * end and [1] is write end)
100  */
102 };
103 
106 
108 
110 
112 
114 
115  void *context;
116 
117  void (*totemudp_deliver_fn) (
118  void *context,
119  const void *msg,
120  unsigned int msg_len);
121 
122  void (*totemudp_iface_change_fn) (
123  void *context,
124  const struct totem_ip_address *iface_address);
125 
126  void (*totemudp_target_set_completed) (void *context);
127 
128  /*
129  * Function and data used to log messages
130  */
132 
134 
136 
138 
140 
142 
143  void (*totemudp_log_printf) (
144  int level,
145  int subsys,
146  const char *function,
147  const char *file,
148  int line,
149  const char *format,
150  ...)__attribute__((format(printf, 6, 7)));
151 
152  void *udp_context;
153 
154  char iov_buffer[FRAME_SIZE_MAX];
155 
156  char iov_buffer_flush[FRAME_SIZE_MAX];
157 
158  struct iovec totemudp_iov_recv;
159 
160  struct iovec totemudp_iov_recv_flush;
161 
162  struct totemudp_socket totemudp_sockets;
163 
164  struct totem_ip_address mcast_address;
165 
167 
169 
171 
173 
175 
176  struct timeval stats_tv_start;
177 
178  struct totem_ip_address my_id;
179 
180  int firstrun;
181 
182  qb_loop_timer_handle timer_netif_check_timeout;
183 
184  unsigned int my_memb_entries;
185 
186  int flushing;
187 
189 
191 
192  struct totem_ip_address token_target;
193 };
194 
195 struct work_item {
196  const void *msg;
197  unsigned int msg_len;
199 };
200 
201 static int totemudp_build_sockets (
202  struct totemudp_instance *instance,
203  struct totem_ip_address *bindnet_address,
204  struct totem_ip_address *mcastaddress,
205  struct totemudp_socket *sockets,
206  struct totem_ip_address *bound_to);
207 
208 static struct totem_ip_address localhost;
209 
210 static void totemudp_instance_initialize (struct totemudp_instance *instance)
211 {
212  memset (instance, 0, sizeof (struct totemudp_instance));
213 
215 
216  instance->totemudp_iov_recv.iov_base = instance->iov_buffer;
217 
218  instance->totemudp_iov_recv.iov_len = FRAME_SIZE_MAX; //sizeof (instance->iov_buffer);
219  instance->totemudp_iov_recv_flush.iov_base = instance->iov_buffer_flush;
220 
221  instance->totemudp_iov_recv_flush.iov_len = FRAME_SIZE_MAX; //sizeof (instance->iov_buffer);
222 
223  /*
224  * There is always atleast 1 processor
225  */
226  instance->my_memb_entries = 1;
227 }
228 
229 #define log_printf(level, format, args...) \
230 do { \
231  instance->totemudp_log_printf ( \
232  level, instance->totemudp_subsys_id, \
233  __FUNCTION__, __FILE__, __LINE__, \
234  (const char *)format, ##args); \
235 } while (0);
236 
237 #define LOGSYS_PERROR(err_num, level, fmt, args...) \
238 do { \
239  char _error_str[LOGSYS_MAX_PERROR_MSG_LEN]; \
240  const char *_error_ptr = qb_strerror_r(err_num, _error_str, sizeof(_error_str)); \
241  instance->totemudp_log_printf ( \
242  level, instance->totemudp_subsys_id, \
243  __FUNCTION__, __FILE__, __LINE__, \
244  fmt ": %s (%d)\n", ##args, _error_ptr, err_num); \
245  } while(0)
246 
248  void *udp_context,
249  const char *cipher_type,
250  const char *hash_type)
251 {
252 
253  return (0);
254 }
255 
256 
257 static inline void ucast_sendmsg (
258  struct totemudp_instance *instance,
259  struct totem_ip_address *system_to,
260  const void *msg,
261  unsigned int msg_len)
262 {
263  struct msghdr msg_ucast;
264  int res = 0;
265  size_t buf_out_len;
266  unsigned char buf_out[FRAME_SIZE_MAX];
267  struct sockaddr_storage sockaddr;
268  struct iovec iovec;
269  int addrlen;
270 
271  /*
272  * Encrypt and digest the message
273  */
275  instance->crypto_inst,
276  (const unsigned char *)msg,
277  msg_len,
278  buf_out,
279  &buf_out_len) != 0) {
280  log_printf(LOGSYS_LEVEL_CRIT, "Error encrypting/signing packet (non-critical)");
281  return;
282  }
283 
284  iovec.iov_base = (void *)buf_out;
285  iovec.iov_len = buf_out_len;
286 
287  /*
288  * Build unicast message
289  */
290  memset(&msg_ucast, 0, sizeof(msg_ucast));
292  instance->totem_interface->ip_port, &sockaddr, &addrlen);
293  msg_ucast.msg_name = &sockaddr;
294  msg_ucast.msg_namelen = addrlen;
295  msg_ucast.msg_iov = (void *)&iovec;
296  msg_ucast.msg_iovlen = 1;
297 #ifdef HAVE_MSGHDR_CONTROL
298  msg_ucast.msg_control = 0;
299 #endif
300 #ifdef HAVE_MSGHDR_CONTROLLEN
301  msg_ucast.msg_controllen = 0;
302 #endif
303 #ifdef HAVE_MSGHDR_FLAGS
304  msg_ucast.msg_flags = 0;
305 #endif
306 #ifdef HAVE_MSGHDR_ACCRIGHTS
307  msg_ucast.msg_accrights = NULL;
308 #endif
309 #ifdef HAVE_MSGHDR_ACCRIGHTSLEN
310  msg_ucast.msg_accrightslen = 0;
311 #endif
312 
313 
314  /*
315  * Transmit unicast message
316  * An error here is recovered by totemsrp
317  */
318  res = sendmsg (instance->totemudp_sockets.mcast_send, &msg_ucast,
319  MSG_NOSIGNAL);
320  if (res < 0) {
321  LOGSYS_PERROR (errno, instance->totemudp_log_level_debug,
322  "sendmsg(ucast) failed (non-critical)");
323  }
324 }
325 
326 static inline void mcast_sendmsg (
327  struct totemudp_instance *instance,
328  const void *msg,
329  unsigned int msg_len)
330 {
331  struct msghdr msg_mcast;
332  int res = 0;
333  size_t buf_out_len;
334  unsigned char buf_out[FRAME_SIZE_MAX];
335  struct iovec iovec;
336  struct sockaddr_storage sockaddr;
337  int addrlen;
338 
339  /*
340  * Encrypt and digest the message
341  */
343  instance->crypto_inst,
344  (const unsigned char *)msg,
345  msg_len,
346  buf_out,
347  &buf_out_len) != 0) {
348  log_printf(LOGSYS_LEVEL_CRIT, "Error encrypting/signing packet (non-critical)");
349  return;
350  }
351 
352  iovec.iov_base = (void *)&buf_out;
353  iovec.iov_len = buf_out_len;
354 
355  /*
356  * Build multicast message
357  */
359  instance->totem_interface->ip_port, &sockaddr, &addrlen);
360  memset(&msg_mcast, 0, sizeof(msg_mcast));
361  msg_mcast.msg_name = &sockaddr;
362  msg_mcast.msg_namelen = addrlen;
363  msg_mcast.msg_iov = (void *)&iovec;
364  msg_mcast.msg_iovlen = 1;
365 #ifdef HAVE_MSGHDR_CONTROL
366  msg_mcast.msg_control = 0;
367 #endif
368 #ifdef HAVE_MSGHDR_CONTROLLEN
369  msg_mcast.msg_controllen = 0;
370 #endif
371 #ifdef HAVE_MSGHDR_FLAGS
372  msg_mcast.msg_flags = 0;
373 #endif
374 #ifdef HAVE_MSGHDR_ACCRIGHTS
375  msg_mcast.msg_accrights = NULL;
376 #endif
377 #ifdef HAVE_MSGHDR_ACCRIGHTSLEN
378  msg_mcast.msg_accrightslen = 0;
379 #endif
380 
381  /*
382  * Transmit multicast message
383  * An error here is recovered by totemsrp
384  */
385  res = sendmsg (instance->totemudp_sockets.mcast_send, &msg_mcast,
386  MSG_NOSIGNAL);
387  if (res < 0) {
388  LOGSYS_PERROR (errno, instance->totemudp_log_level_debug,
389  "sendmsg(mcast) failed (non-critical)");
390  instance->stats->continuous_sendmsg_failures++;
391  } else {
392  instance->stats->continuous_sendmsg_failures = 0;
393  }
394 
395  /*
396  * Transmit multicast message to local unix mcast loop
397  * An error here is recovered by totemsrp
398  */
399  msg_mcast.msg_name = NULL;
400  msg_mcast.msg_namelen = 0;
401 
402  res = sendmsg (instance->totemudp_sockets.local_mcast_loop[1], &msg_mcast,
403  MSG_NOSIGNAL);
404  if (res < 0) {
405  LOGSYS_PERROR (errno, instance->totemudp_log_level_debug,
406  "sendmsg(local mcast loop) failed (non-critical)");
407  }
408 }
409 
410 
412  void *udp_context)
413 {
414  struct totemudp_instance *instance = (struct totemudp_instance *)udp_context;
415  int res = 0;
416 
417  if (instance->totemudp_sockets.mcast_recv > 0) {
418  qb_loop_poll_del (instance->totemudp_poll_handle,
419  instance->totemudp_sockets.mcast_recv);
420  close (instance->totemudp_sockets.mcast_recv);
421  }
422  if (instance->totemudp_sockets.mcast_send > 0) {
423  close (instance->totemudp_sockets.mcast_send);
424  }
425  if (instance->totemudp_sockets.local_mcast_loop[0] > 0) {
426  qb_loop_poll_del (instance->totemudp_poll_handle,
427  instance->totemudp_sockets.local_mcast_loop[0]);
428  close (instance->totemudp_sockets.local_mcast_loop[0]);
429  close (instance->totemudp_sockets.local_mcast_loop[1]);
430  }
431  if (instance->totemudp_sockets.token > 0) {
432  qb_loop_poll_del (instance->totemudp_poll_handle,
433  instance->totemudp_sockets.token);
434  close (instance->totemudp_sockets.token);
435  }
436 
437  return (res);
438 }
439 
440 /*
441  * Only designed to work with a message with one iov
442  */
443 
444 static int net_deliver_fn (
445  int fd,
446  int revents,
447  void *data)
448 {
449  struct totemudp_instance *instance = (struct totemudp_instance *)data;
450  struct msghdr msg_recv;
451  struct iovec *iovec;
452  struct sockaddr_storage system_from;
453  int bytes_received;
454  int res = 0;
455 
456  if (instance->flushing == 1) {
457  iovec = &instance->totemudp_iov_recv_flush;
458  } else {
459  iovec = &instance->totemudp_iov_recv;
460  }
461 
462  /*
463  * Receive datagram
464  */
465  msg_recv.msg_name = &system_from;
466  msg_recv.msg_namelen = sizeof (struct sockaddr_storage);
467  msg_recv.msg_iov = iovec;
468  msg_recv.msg_iovlen = 1;
469 #ifdef HAVE_MSGHDR_CONTROL
470  msg_recv.msg_control = 0;
471 #endif
472 #ifdef HAVE_MSGHDR_CONTROLLEN
473  msg_recv.msg_controllen = 0;
474 #endif
475 #ifdef HAVE_MSGHDR_FLAGS
476  msg_recv.msg_flags = 0;
477 #endif
478 #ifdef HAVE_MSGHDR_ACCRIGHTS
479  msg_recv.msg_accrights = NULL;
480 #endif
481 #ifdef HAVE_MSGHDR_ACCRIGHTSLEN
482  msg_recv.msg_accrightslen = 0;
483 #endif
484 
485  bytes_received = recvmsg (fd, &msg_recv, MSG_NOSIGNAL | MSG_DONTWAIT);
486  if (bytes_received == -1) {
487  return (0);
488  } else {
489  instance->stats_recv += bytes_received;
490  }
491 
492  /*
493  * Authenticate and if authenticated, decrypt datagram
494  */
495  res = crypto_authenticate_and_decrypt (instance->crypto_inst, iovec->iov_base, &bytes_received);
496  if (res == -1) {
497  log_printf (instance->totemudp_log_level_security, "Received message has invalid digest... ignoring.");
499  "Invalid packet data");
500  iovec->iov_len = FRAME_SIZE_MAX;
501  return 0;
502  }
503  iovec->iov_len = bytes_received;
504 
505  /*
506  * Handle incoming message
507  */
508  instance->totemudp_deliver_fn (
509  instance->context,
510  iovec->iov_base,
511  iovec->iov_len);
512 
513  iovec->iov_len = FRAME_SIZE_MAX;
514  return (0);
515 }
516 
517 static int netif_determine (
518  struct totemudp_instance *instance,
519  struct totem_ip_address *bindnet,
520  struct totem_ip_address *bound_to,
521  int *interface_up,
522  int *interface_num)
523 {
524  int res;
525 
526  res = totemip_iface_check (bindnet, bound_to,
527  interface_up, interface_num,
528  instance->totem_config->clear_node_high_bit);
529 
530 
531  return (res);
532 }
533 
534 
535 /*
536  * If the interface is up, the sockets for totem are built. If the interface is down
537  * this function is requeued in the timer list to retry building the sockets later.
538  */
539 static void timer_function_netif_check_timeout (
540  void *data)
541 {
542  struct totemudp_instance *instance = (struct totemudp_instance *)data;
543  int interface_up;
544  int interface_num;
545  struct totem_ip_address *bind_address;
546 
547  /*
548  * Build sockets for every interface
549  */
550  netif_determine (instance,
551  &instance->totem_interface->bindnet,
552  &instance->totem_interface->boundto,
553  &interface_up, &interface_num);
554  /*
555  * If the network interface isn't back up and we are already
556  * in loopback mode, add timer to check again and return
557  */
558  if ((instance->netif_bind_state == BIND_STATE_LOOPBACK &&
559  interface_up == 0) ||
560 
561  (instance->my_memb_entries == 1 &&
562  instance->netif_bind_state == BIND_STATE_REGULAR &&
563  interface_up == 1)) {
564 
565  qb_loop_timer_add (instance->totemudp_poll_handle,
566  QB_LOOP_MED,
567  instance->totem_config->downcheck_timeout*QB_TIME_NS_IN_MSEC,
568  (void *)instance,
569  timer_function_netif_check_timeout,
570  &instance->timer_netif_check_timeout);
571 
572  /*
573  * Add a timer to check for a downed regular interface
574  */
575  return;
576  }
577 
578  if (instance->totemudp_sockets.mcast_recv > 0) {
579  qb_loop_poll_del (instance->totemudp_poll_handle,
580  instance->totemudp_sockets.mcast_recv);
581  close (instance->totemudp_sockets.mcast_recv);
582  }
583  if (instance->totemudp_sockets.mcast_send > 0) {
584  close (instance->totemudp_sockets.mcast_send);
585  }
586  if (instance->totemudp_sockets.local_mcast_loop[0] > 0) {
587  qb_loop_poll_del (instance->totemudp_poll_handle,
588  instance->totemudp_sockets.local_mcast_loop[0]);
589  close (instance->totemudp_sockets.local_mcast_loop[0]);
590  close (instance->totemudp_sockets.local_mcast_loop[1]);
591  }
592  if (instance->totemudp_sockets.token > 0) {
593  qb_loop_poll_del (instance->totemudp_poll_handle,
594  instance->totemudp_sockets.token);
595  close (instance->totemudp_sockets.token);
596  }
597 
598  if (interface_up == 0) {
599  /*
600  * Interface is not up
601  */
603  bind_address = &localhost;
604 
605  /*
606  * Add a timer to retry building interfaces and request memb_gather_enter
607  */
608  qb_loop_timer_add (instance->totemudp_poll_handle,
609  QB_LOOP_MED,
610  instance->totem_config->downcheck_timeout*QB_TIME_NS_IN_MSEC,
611  (void *)instance,
612  timer_function_netif_check_timeout,
613  &instance->timer_netif_check_timeout);
614  } else {
615  /*
616  * Interface is up
617  */
619  bind_address = &instance->totem_interface->bindnet;
620  }
621  /*
622  * Create and bind the multicast and unicast sockets
623  */
624  (void)totemudp_build_sockets (instance,
625  &instance->mcast_address,
626  bind_address,
627  &instance->totemudp_sockets,
628  &instance->totem_interface->boundto);
629 
630  qb_loop_poll_add (
631  instance->totemudp_poll_handle,
632  QB_LOOP_MED,
633  instance->totemudp_sockets.mcast_recv,
634  POLLIN, instance, net_deliver_fn);
635 
636  qb_loop_poll_add (
637  instance->totemudp_poll_handle,
638  QB_LOOP_MED,
639  instance->totemudp_sockets.local_mcast_loop[0],
640  POLLIN, instance, net_deliver_fn);
641 
642  qb_loop_poll_add (
643  instance->totemudp_poll_handle,
644  QB_LOOP_MED,
645  instance->totemudp_sockets.token,
646  POLLIN, instance, net_deliver_fn);
647 
648  totemip_copy (&instance->my_id, &instance->totem_interface->boundto);
649 
650  /*
651  * This reports changes in the interface to the user and totemsrp
652  */
653  if (instance->netif_bind_state == BIND_STATE_REGULAR) {
654  if (instance->netif_state_report & NETIF_STATE_REPORT_UP) {
656  "The network interface [%s] is now up.",
657  totemip_print (&instance->totem_interface->boundto));
659  instance->totemudp_iface_change_fn (instance->context, &instance->my_id);
660  }
661  /*
662  * Add a timer to check for interface going down in single membership
663  */
664  if (instance->my_memb_entries == 1) {
665  qb_loop_timer_add (instance->totemudp_poll_handle,
666  QB_LOOP_MED,
667  instance->totem_config->downcheck_timeout*QB_TIME_NS_IN_MSEC,
668  (void *)instance,
669  timer_function_netif_check_timeout,
670  &instance->timer_netif_check_timeout);
671  }
672 
673  } else {
676  "The network interface is down.");
677  instance->totemudp_iface_change_fn (instance->context, &instance->my_id);
678  }
680 
681  }
682 }
683 
684 /* Set the socket priority to INTERACTIVE to ensure
685  that our messages don't get queued behind anything else */
686 static void totemudp_traffic_control_set(struct totemudp_instance *instance, int sock)
687 {
688 #ifdef SO_PRIORITY
689  int prio = 6; /* TC_PRIO_INTERACTIVE */
690 
691  if (setsockopt(sock, SOL_SOCKET, SO_PRIORITY, &prio, sizeof(int))) {
692  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning, "Could not set traffic priority");
693  }
694 #endif
695 }
696 
697 static int totemudp_build_sockets_ip (
698  struct totemudp_instance *instance,
699  struct totem_ip_address *mcast_address,
700  struct totem_ip_address *bindnet_address,
701  struct totemudp_socket *sockets,
702  struct totem_ip_address *bound_to,
703  int interface_num)
704 {
705  struct sockaddr_storage sockaddr;
706  struct ipv6_mreq mreq6;
707  struct ip_mreq mreq;
708  struct sockaddr_storage mcast_ss, boundto_ss;
709  struct sockaddr_in6 *mcast_sin6 = (struct sockaddr_in6 *)&mcast_ss;
710  struct sockaddr_in *mcast_sin = (struct sockaddr_in *)&mcast_ss;
711  struct sockaddr_in *boundto_sin = (struct sockaddr_in *)&boundto_ss;
712  unsigned int sendbuf_size;
713  unsigned int recvbuf_size;
714  unsigned int optlen = sizeof (sendbuf_size);
715  unsigned int retries;
716  int addrlen;
717  int res;
718  int flag;
719  uint8_t sflag;
720  int i;
721 
722  /*
723  * Create multicast recv socket
724  */
725  sockets->mcast_recv = socket (bindnet_address->family, SOCK_DGRAM, 0);
726  if (sockets->mcast_recv == -1) {
727  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
728  "socket() failed");
729  return (-1);
730  }
731 
732  totemip_nosigpipe (sockets->mcast_recv);
733  res = fcntl (sockets->mcast_recv, F_SETFL, O_NONBLOCK);
734  if (res == -1) {
735  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
736  "Could not set non-blocking operation on multicast socket");
737  return (-1);
738  }
739 
740  /*
741  * Force reuse
742  */
743  flag = 1;
744  if ( setsockopt(sockets->mcast_recv, SOL_SOCKET, SO_REUSEADDR, (char *)&flag, sizeof (flag)) < 0) {
745  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
746  "setsockopt(SO_REUSEADDR) failed");
747  return (-1);
748  }
749 
750  /*
751  * Create local multicast loop socket
752  */
753  if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sockets->local_mcast_loop) == -1) {
754  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
755  "socket() failed");
756  return (-1);
757  }
758 
759  for (i = 0; i < 2; i++) {
760  totemip_nosigpipe (sockets->local_mcast_loop[i]);
761  res = fcntl (sockets->local_mcast_loop[i], F_SETFL, O_NONBLOCK);
762  if (res == -1) {
763  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
764  "Could not set non-blocking operation on multicast socket");
765  return (-1);
766  }
767  }
768 
769 
770 
771  /*
772  * Setup mcast send socket
773  */
774  sockets->mcast_send = socket (bindnet_address->family, SOCK_DGRAM, 0);
775  if (sockets->mcast_send == -1) {
776  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
777  "socket() failed");
778  return (-1);
779  }
780 
781  totemip_nosigpipe (sockets->mcast_send);
782  res = fcntl (sockets->mcast_send, F_SETFL, O_NONBLOCK);
783  if (res == -1) {
784  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
785  "Could not set non-blocking operation on multicast socket");
786  return (-1);
787  }
788 
789  /*
790  * Force reuse
791  */
792  flag = 1;
793  if ( setsockopt(sockets->mcast_send, SOL_SOCKET, SO_REUSEADDR, (char *)&flag, sizeof (flag)) < 0) {
794  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
795  "setsockopt(SO_REUSEADDR) failed");
796  return (-1);
797  }
798 
800  &sockaddr, &addrlen);
801 
802  retries = 0;
803  while (1) {
804  res = bind (sockets->mcast_send, (struct sockaddr *)&sockaddr, addrlen);
805  if (res == 0) {
806  break;
807  }
808  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
809  "Unable to bind the socket to send multicast packets");
810  if (++retries > BIND_MAX_RETRIES) {
811  break;
812  }
813 
814  /*
815  * Wait for a while
816  */
817  (void)poll(NULL, 0, BIND_RETRIES_INTERVAL * retries);
818  }
819  if (res == -1) {
820  return (-1);
821  }
822 
823  /*
824  * Setup unicast socket
825  */
826  sockets->token = socket (bindnet_address->family, SOCK_DGRAM, 0);
827  if (sockets->token == -1) {
828  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
829  "socket() failed");
830  return (-1);
831  }
832 
833  totemip_nosigpipe (sockets->token);
834  res = fcntl (sockets->token, F_SETFL, O_NONBLOCK);
835  if (res == -1) {
836  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
837  "Could not set non-blocking operation on token socket");
838  return (-1);
839  }
840 
841  /*
842  * Force reuse
843  */
844  flag = 1;
845  if ( setsockopt(sockets->token, SOL_SOCKET, SO_REUSEADDR, (char *)&flag, sizeof (flag)) < 0) {
846  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
847  "setsockopt(SO_REUSEADDR) failed");
848  return (-1);
849  }
850 
851  /*
852  * Bind to unicast socket used for token send/receives
853  * This has the side effect of binding to the correct interface
854  */
855  totemip_totemip_to_sockaddr_convert(bound_to, instance->totem_interface->ip_port, &sockaddr, &addrlen);
856 
857  retries = 0;
858  while (1) {
859  res = bind (sockets->token, (struct sockaddr *)&sockaddr, addrlen);
860  if (res == 0) {
861  break;
862  }
863  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
864  "Unable to bind UDP unicast socket");
865  if (++retries > BIND_MAX_RETRIES) {
866  break;
867  }
868 
869  /*
870  * Wait for a while
871  */
872  (void)poll(NULL, 0, BIND_RETRIES_INTERVAL * retries);
873  }
874  if (res == -1) {
875  return (-1);
876  }
877 
878  recvbuf_size = MCAST_SOCKET_BUFFER_SIZE;
879  sendbuf_size = MCAST_SOCKET_BUFFER_SIZE;
880  /*
881  * Set buffer sizes to avoid overruns
882  */
883  res = setsockopt (sockets->mcast_recv, SOL_SOCKET, SO_RCVBUF, &recvbuf_size, optlen);
884  if (res == -1) {
885  LOGSYS_PERROR (errno, instance->totemudp_log_level_debug,
886  "Unable to set SO_RCVBUF size on UDP mcast socket");
887  return (-1);
888  }
889  res = setsockopt (sockets->mcast_send, SOL_SOCKET, SO_SNDBUF, &sendbuf_size, optlen);
890  if (res == -1) {
891  LOGSYS_PERROR (errno, instance->totemudp_log_level_debug,
892  "Unable to set SO_SNDBUF size on UDP mcast socket");
893  return (-1);
894  }
895  res = setsockopt (sockets->local_mcast_loop[0], SOL_SOCKET, SO_RCVBUF, &recvbuf_size, optlen);
896  if (res == -1) {
897  LOGSYS_PERROR (errno, instance->totemudp_log_level_debug,
898  "Unable to set SO_RCVBUF size on UDP local mcast loop socket");
899  return (-1);
900  }
901  res = setsockopt (sockets->local_mcast_loop[1], SOL_SOCKET, SO_SNDBUF, &sendbuf_size, optlen);
902  if (res == -1) {
903  LOGSYS_PERROR (errno, instance->totemudp_log_level_debug,
904  "Unable to set SO_SNDBUF size on UDP local mcast loop socket");
905  return (-1);
906  }
907 
908  res = getsockopt (sockets->mcast_recv, SOL_SOCKET, SO_RCVBUF, &recvbuf_size, &optlen);
909  if (res == 0) {
911  "Receive multicast socket recv buffer size (%d bytes).", recvbuf_size);
912  }
913 
914  res = getsockopt (sockets->mcast_send, SOL_SOCKET, SO_SNDBUF, &sendbuf_size, &optlen);
915  if (res == 0) {
917  "Transmit multicast socket send buffer size (%d bytes).", sendbuf_size);
918  }
919 
920  res = getsockopt (sockets->local_mcast_loop[0], SOL_SOCKET, SO_RCVBUF, &recvbuf_size, &optlen);
921  if (res == 0) {
923  "Local receive multicast loop socket recv buffer size (%d bytes).", recvbuf_size);
924  }
925 
926  res = getsockopt (sockets->local_mcast_loop[1], SOL_SOCKET, SO_SNDBUF, &sendbuf_size, &optlen);
927  if (res == 0) {
929  "Local transmit multicast loop socket send buffer size (%d bytes).", sendbuf_size);
930  }
931 
932 
933  /*
934  * Join group membership on socket
935  */
936  totemip_totemip_to_sockaddr_convert(mcast_address, instance->totem_interface->ip_port, &mcast_ss, &addrlen);
937  totemip_totemip_to_sockaddr_convert(bound_to, instance->totem_interface->ip_port, &boundto_ss, &addrlen);
938 
939  if (instance->totem_config->broadcast_use == 1) {
940  unsigned int broadcast = 1;
941 
942  if ((setsockopt(sockets->mcast_recv, SOL_SOCKET,
943  SO_BROADCAST, &broadcast, sizeof (broadcast))) == -1) {
944  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
945  "setting broadcast option failed");
946  return (-1);
947  }
948  if ((setsockopt(sockets->mcast_send, SOL_SOCKET,
949  SO_BROADCAST, &broadcast, sizeof (broadcast))) == -1) {
950  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
951  "setting broadcast option failed");
952  return (-1);
953  }
954  } else {
955  switch (bindnet_address->family) {
956  case AF_INET:
957  memset(&mreq, 0, sizeof(mreq));
958  mreq.imr_multiaddr.s_addr = mcast_sin->sin_addr.s_addr;
959  mreq.imr_interface.s_addr = boundto_sin->sin_addr.s_addr;
960  res = setsockopt (sockets->mcast_recv, IPPROTO_IP, IP_ADD_MEMBERSHIP,
961  &mreq, sizeof (mreq));
962  if (res == -1) {
963  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
964  "join ipv4 multicast group failed");
965  return (-1);
966  }
967  break;
968  case AF_INET6:
969  memset(&mreq6, 0, sizeof(mreq6));
970  memcpy(&mreq6.ipv6mr_multiaddr, &mcast_sin6->sin6_addr, sizeof(struct in6_addr));
971  mreq6.ipv6mr_interface = interface_num;
972 
973  res = setsockopt (sockets->mcast_recv, IPPROTO_IPV6, IPV6_JOIN_GROUP,
974  &mreq6, sizeof (mreq6));
975  if (res == -1) {
976  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
977  "join ipv6 multicast group failed");
978  return (-1);
979  }
980  break;
981  }
982  }
983 
984  /*
985  * Turn off multicast loopback
986  */
987 
988  flag = 0;
989  switch ( bindnet_address->family ) {
990  case AF_INET:
991  sflag = 0;
992  res = setsockopt (sockets->mcast_send, IPPROTO_IP, IP_MULTICAST_LOOP,
993  &sflag, sizeof (sflag));
994  break;
995  case AF_INET6:
996  res = setsockopt (sockets->mcast_send, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
997  &flag, sizeof (flag));
998  }
999  if (res == -1) {
1000  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
1001  "Unable to turn off multicast loopback");
1002  return (-1);
1003  }
1004 
1005  /*
1006  * Set multicast packets TTL
1007  */
1008  flag = instance->totem_interface->ttl;
1009  if (bindnet_address->family == AF_INET6) {
1010  res = setsockopt (sockets->mcast_send, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
1011  &flag, sizeof (flag));
1012  if (res == -1) {
1013  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
1014  "set mcast v6 TTL failed");
1015  return (-1);
1016  }
1017  } else {
1018  sflag = flag;
1019  res = setsockopt(sockets->mcast_send, IPPROTO_IP, IP_MULTICAST_TTL,
1020  &sflag, sizeof(sflag));
1021  if (res == -1) {
1022  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
1023  "set mcast v4 TTL failed");
1024  return (-1);
1025  }
1026  }
1027 
1028  /*
1029  * Bind to a specific interface for multicast send and receive
1030  */
1031  switch ( bindnet_address->family ) {
1032  case AF_INET:
1033  if (setsockopt (sockets->mcast_send, IPPROTO_IP, IP_MULTICAST_IF,
1034  &boundto_sin->sin_addr, sizeof (boundto_sin->sin_addr)) < 0) {
1035  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
1036  "cannot select interface for multicast packets (send)");
1037  return (-1);
1038  }
1039  if (setsockopt (sockets->mcast_recv, IPPROTO_IP, IP_MULTICAST_IF,
1040  &boundto_sin->sin_addr, sizeof (boundto_sin->sin_addr)) < 0) {
1041  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
1042  "cannot select interface for multicast packets (recv)");
1043  return (-1);
1044  }
1045  break;
1046  case AF_INET6:
1047  if (setsockopt (sockets->mcast_send, IPPROTO_IPV6, IPV6_MULTICAST_IF,
1048  &interface_num, sizeof (interface_num)) < 0) {
1049  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
1050  "cannot select interface for multicast packets (send v6)");
1051  return (-1);
1052  }
1053  if (setsockopt (sockets->mcast_recv, IPPROTO_IPV6, IPV6_MULTICAST_IF,
1054  &interface_num, sizeof (interface_num)) < 0) {
1055  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
1056  "cannot select interface for multicast packets (recv v6)");
1057  return (-1);
1058  }
1059  break;
1060  }
1061 
1062  /*
1063  * Bind to multicast socket used for multicast receives
1064  * This needs to happen after all of the multicast setsockopt() calls
1065  * as the kernel seems to only put them into effect (for IPV6) when bind()
1066  * is called.
1067  */
1069  instance->totem_interface->ip_port, &sockaddr, &addrlen);
1070 
1071  retries = 0;
1072  while (1) {
1073  res = bind (sockets->mcast_recv, (struct sockaddr *)&sockaddr, addrlen);
1074  if (res == 0) {
1075  break;
1076  }
1077  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
1078  "Unable to bind the socket to receive multicast packets");
1079  if (++retries > BIND_MAX_RETRIES) {
1080  break;
1081  }
1082 
1083  /*
1084  * Wait for a while
1085  */
1086  (void)poll(NULL, 0, BIND_RETRIES_INTERVAL * retries);
1087  }
1088 
1089  if (res == -1) {
1090  return (-1);
1091  }
1092  return 0;
1093 }
1094 
1095 static int totemudp_build_sockets (
1096  struct totemudp_instance *instance,
1097  struct totem_ip_address *mcast_address,
1098  struct totem_ip_address *bindnet_address,
1099  struct totemudp_socket *sockets,
1100  struct totem_ip_address *bound_to)
1101 {
1102  int interface_num;
1103  int interface_up;
1104  int res;
1105 
1106  /*
1107  * Determine the ip address bound to and the interface name
1108  */
1109  res = netif_determine (instance,
1110  bindnet_address,
1111  bound_to,
1112  &interface_up,
1113  &interface_num);
1114 
1115  if (res == -1) {
1116  return (-1);
1117  }
1118 
1119  totemip_copy(&instance->my_id, bound_to);
1120 
1121  res = totemudp_build_sockets_ip (instance, mcast_address,
1122  bindnet_address, sockets, bound_to, interface_num);
1123 
1124  if (res == -1) {
1125  /* if we get here, corosync won't work anyway, so better leaving than faking to work */
1126  LOGSYS_PERROR (errno, instance->totemudp_log_level_error,
1127  "Unable to create sockets, exiting");
1128  exit(EXIT_FAILURE);
1129  }
1130 
1131  /* We only send out of the token socket */
1132  totemudp_traffic_control_set(instance, sockets->token);
1133  return res;
1134 }
1135 
1136 /*
1137  * Totem Network interface - also does encryption/decryption
1138  * depends on poll abstraction, POSIX, IPV4
1139  */
1140 
1141 /*
1142  * Create an instance
1143  */
1145  qb_loop_t *poll_handle,
1146  void **udp_context,
1147  struct totem_config *totem_config,
1148  totemsrp_stats_t *stats,
1149  int interface_no,
1150  void *context,
1151 
1152  void (*deliver_fn) (
1153  void *context,
1154  const void *msg,
1155  unsigned int msg_len),
1156 
1157  void (*iface_change_fn) (
1158  void *context,
1159  const struct totem_ip_address *iface_address),
1160 
1161  void (*target_set_completed) (
1162  void *context))
1163 {
1164  struct totemudp_instance *instance;
1165 
1166  instance = malloc (sizeof (struct totemudp_instance));
1167  if (instance == NULL) {
1168  return (-1);
1169  }
1170 
1171  totemudp_instance_initialize (instance);
1172 
1173  instance->totem_config = totem_config;
1174  instance->stats = stats;
1175 
1176  /*
1177  * Configure logging
1178  */
1179  instance->totemudp_log_level_security = 1; //totem_config->totem_logging_configuration.log_level_security;
1186 
1187  /*
1188  * Initialize random number generator for later use to generate salt
1189  */
1190  instance->crypto_inst = crypto_init (totem_config->private_key,
1191  totem_config->private_key_len,
1192  totem_config->crypto_cipher_type,
1193  totem_config->crypto_hash_type,
1194  instance->totemudp_log_printf,
1195  instance->totemudp_log_level_security,
1196  instance->totemudp_log_level_notice,
1197  instance->totemudp_log_level_error,
1198  instance->totemudp_subsys_id);
1199  if (instance->crypto_inst == NULL) {
1200  free(instance);
1201  return (-1);
1202  }
1203  /*
1204  * Initialize local variables for totemudp
1205  */
1206  instance->totem_interface = &totem_config->interfaces[interface_no];
1207  totemip_copy (&instance->mcast_address, &instance->totem_interface->mcast_addr);
1208  memset (instance->iov_buffer, 0, FRAME_SIZE_MAX);
1209 
1210  instance->totemudp_poll_handle = poll_handle;
1211 
1212  instance->totem_interface->bindnet.nodeid = instance->totem_config->node_id;
1213 
1214  instance->context = context;
1215  instance->totemudp_deliver_fn = deliver_fn;
1216 
1217  instance->totemudp_iface_change_fn = iface_change_fn;
1218 
1219  instance->totemudp_target_set_completed = target_set_completed;
1220 
1221  totemip_localhost (instance->mcast_address.family, &localhost);
1222  localhost.nodeid = instance->totem_config->node_id;
1223 
1224  /*
1225  * RRP layer isn't ready to receive message because it hasn't
1226  * initialized yet. Add short timer to check the interfaces.
1227  */
1228  qb_loop_timer_add (instance->totemudp_poll_handle,
1229  QB_LOOP_MED,
1230  100*QB_TIME_NS_IN_MSEC,
1231  (void *)instance,
1232  timer_function_netif_check_timeout,
1233  &instance->timer_netif_check_timeout);
1234 
1235  *udp_context = instance;
1236  return (0);
1237 }
1238 
1240 {
1241  return malloc (FRAME_SIZE_MAX);
1242 }
1243 
1244 void totemudp_buffer_release (void *ptr)
1245 {
1246  return free (ptr);
1247 }
1248 
1250  void *udp_context,
1251  int processor_count)
1252 {
1253  struct totemudp_instance *instance = (struct totemudp_instance *)udp_context;
1254  int res = 0;
1255 
1256  instance->my_memb_entries = processor_count;
1257  qb_loop_timer_del (instance->totemudp_poll_handle,
1258  instance->timer_netif_check_timeout);
1259  if (processor_count == 1) {
1260  qb_loop_timer_add (instance->totemudp_poll_handle,
1261  QB_LOOP_MED,
1262  instance->totem_config->downcheck_timeout*QB_TIME_NS_IN_MSEC,
1263  (void *)instance,
1264  timer_function_netif_check_timeout,
1265  &instance->timer_netif_check_timeout);
1266  }
1267 
1268  return (res);
1269 }
1270 
1271 int totemudp_recv_flush (void *udp_context)
1272 {
1273  struct totemudp_instance *instance = (struct totemudp_instance *)udp_context;
1274  struct pollfd ufd;
1275  int nfds;
1276  int res = 0;
1277  int i;
1278  int sock;
1279 
1280  instance->flushing = 1;
1281 
1282  for (i = 0; i < 2; i++) {
1283  sock = -1;
1284  if (i == 0) {
1285  sock = instance->totemudp_sockets.mcast_recv;
1286  }
1287  if (i == 1) {
1288  sock = instance->totemudp_sockets.local_mcast_loop[0];
1289  }
1290  assert(sock != -1);
1291 
1292  do {
1293  ufd.fd = sock;
1294  ufd.events = POLLIN;
1295  nfds = poll (&ufd, 1, 0);
1296  if (nfds == 1 && ufd.revents & POLLIN) {
1297  net_deliver_fn (sock, ufd.revents, instance);
1298  }
1299  } while (nfds == 1);
1300  }
1301 
1302  instance->flushing = 0;
1303 
1304  return (res);
1305 }
1306 
1307 int totemudp_send_flush (void *udp_context)
1308 {
1309  return 0;
1310 }
1311 
1313  void *udp_context,
1314  const void *msg,
1315  unsigned int msg_len)
1316 {
1317  struct totemudp_instance *instance = (struct totemudp_instance *)udp_context;
1318  int res = 0;
1319 
1320  ucast_sendmsg (instance, &instance->token_target, msg, msg_len);
1321 
1322  return (res);
1323 }
1325  void *udp_context,
1326  const void *msg,
1327  unsigned int msg_len)
1328 {
1329  struct totemudp_instance *instance = (struct totemudp_instance *)udp_context;
1330  int res = 0;
1331 
1332  mcast_sendmsg (instance, msg, msg_len);
1333 
1334  return (res);
1335 }
1336 
1338  void *udp_context,
1339  const void *msg,
1340  unsigned int msg_len)
1341 {
1342  struct totemudp_instance *instance = (struct totemudp_instance *)udp_context;
1343  int res = 0;
1344 
1345  mcast_sendmsg (instance, msg, msg_len);
1346 
1347  return (res);
1348 }
1349 
1350 extern int totemudp_iface_check (void *udp_context)
1351 {
1352  struct totemudp_instance *instance = (struct totemudp_instance *)udp_context;
1353  int res = 0;
1354 
1355  timer_function_netif_check_timeout (instance);
1356 
1357  return (res);
1358 }
1359 
1360 extern void totemudp_net_mtu_adjust (void *udp_context, struct totem_config *totem_config)
1361 {
1362 
1363  assert(totem_config->interface_count > 0);
1364 
1365  totem_config->net_mtu -= crypto_sec_header_size(totem_config->crypto_cipher_type,
1366  totem_config->crypto_hash_type) +
1368 }
1369 
1370 const char *totemudp_iface_print (void *udp_context) {
1371  struct totemudp_instance *instance = (struct totemudp_instance *)udp_context;
1372  const char *ret_char;
1373 
1374  ret_char = totemip_print (&instance->my_id);
1375 
1376  return (ret_char);
1377 }
1378 
1380  void *udp_context,
1381  struct totem_ip_address *addr)
1382 {
1383  struct totemudp_instance *instance = (struct totemudp_instance *)udp_context;
1384  int res = 0;
1385 
1386  memcpy (addr, &instance->my_id, sizeof (struct totem_ip_address));
1387 
1388  return (res);
1389 }
1390 
1392  void *udp_context,
1393  const struct totem_ip_address *token_target)
1394 {
1395  struct totemudp_instance *instance = (struct totemudp_instance *)udp_context;
1396  int res = 0;
1397 
1398  memcpy (&instance->token_target, token_target,
1399  sizeof (struct totem_ip_address));
1400 
1401  instance->totemudp_target_set_completed (instance->context);
1402 
1403  return (res);
1404 }
1405 
1407  void *udp_context)
1408 {
1409  struct totemudp_instance *instance = (struct totemudp_instance *)udp_context;
1410  unsigned int res;
1411  struct sockaddr_storage system_from;
1412  struct msghdr msg_recv;
1413  struct pollfd ufd;
1414  int nfds;
1415  int msg_processed = 0;
1416  int i;
1417  int sock;
1418 
1419  /*
1420  * Receive datagram
1421  */
1422  msg_recv.msg_name = &system_from;
1423  msg_recv.msg_namelen = sizeof (struct sockaddr_storage);
1424  msg_recv.msg_iov = &instance->totemudp_iov_recv_flush;
1425  msg_recv.msg_iovlen = 1;
1426 #ifdef HAVE_MSGHDR_CONTROL
1427  msg_recv.msg_control = 0;
1428 #endif
1429 #ifdef HAVE_MSGHDR_CONTROLLEN
1430  msg_recv.msg_controllen = 0;
1431 #endif
1432 #ifdef HAVE_MSGHDR_FLAGS
1433  msg_recv.msg_flags = 0;
1434 #endif
1435 #ifdef HAVE_MSGHDR_ACCRIGHTS
1436  msg_recv.msg_accrights = NULL;
1437 #endif
1438 #ifdef HAVE_MSGHDR_ACCRIGHTSLEN
1439  msg_recv.msg_accrightslen = 0;
1440 #endif
1441 
1442  for (i = 0; i < 2; i++) {
1443  sock = -1;
1444  if (i == 0) {
1445  sock = instance->totemudp_sockets.mcast_recv;
1446  }
1447  if (i == 1) {
1448  sock = instance->totemudp_sockets.local_mcast_loop[0];
1449  }
1450  assert(sock != -1);
1451 
1452  do {
1453  ufd.fd = sock;
1454  ufd.events = POLLIN;
1455  nfds = poll (&ufd, 1, 0);
1456  if (nfds == 1 && ufd.revents & POLLIN) {
1457  res = recvmsg (sock, &msg_recv, MSG_NOSIGNAL | MSG_DONTWAIT);
1458  if (res != -1) {
1459  msg_processed = 1;
1460  } else {
1461  msg_processed = -1;
1462  }
1463  }
1464  } while (nfds == 1);
1465  }
1466 
1467  return (msg_processed);
1468 }
1469 
unsigned int clear_node_high_bit
Definition: totem.h:120
unsigned short family
Definition: coroapi.h:113
int totemudp_crypto_set(void *udp_context, const char *cipher_type, const char *hash_type)
Definition: totemudp.c:247
int totemudp_processor_count_set(void *udp_context, int processor_count)
Definition: totemudp.c:1249
int totemip_localhost(int family, struct totem_ip_address *localhost)
Definition: totemip.c:182
#define BIND_MAX_RETRIES
Definition: totem.h:55
int totemudp_subsys_id
Definition: totemudp.c:141
struct iovec totemudp_iov_recv_flush
Definition: totemudp.c:160
struct totem_interface * interfaces
Definition: totem.h:117
unsigned int interface_count
Definition: totem.h:118
totemsrp_stats_t * stats
Definition: totemudp.c:190
struct totemudp_instance * instance
Definition: totemudp.c:198
struct crypto_instance * crypto_inst
Definition: totemudp.c:105
size_t crypto_sec_header_size(const char *crypto_cipher_type, const char *crypto_hash_type)
Definition: totemcrypto.c:771
The totem_ip_address struct.
Definition: coroapi.h:111
const char * totemip_print(const struct totem_ip_address *addr)
Definition: totemip.c:214
void(* totemudp_iface_change_fn)(void *context, const struct totem_ip_address *iface_address)
Definition: totemudp.c:122
void(* totemudp_deliver_fn)(void *context, const void *msg, unsigned int msg_len)
Definition: totemudp.c:117
void totemudp_net_mtu_adjust(void *udp_context, struct totem_config *totem_config)
Definition: totemudp.c:1360
void * totemudp_buffer_alloc(void)
Definition: totemudp.c:1239
int totemudp_mcast_flush_send(void *udp_context, const void *msg, unsigned int msg_len)
Definition: totemudp.c:1324
int totemudp_token_target_set(void *udp_context, const struct totem_ip_address *token_target)
Definition: totemudp.c:1391
unsigned char private_key[TOTEM_PRIVATE_KEY_LEN]
Definition: totem.h:125
char iov_buffer[FRAME_SIZE_MAX]
Definition: totemudp.c:154
#define MSG_NOSIGNAL
Definition: totemudp.c:80
struct totemudp_socket totemudp_sockets
Definition: totemudp.c:162
unsigned char addr[TOTEMIP_ADDRLEN]
Definition: coroapi.h:77
struct crypto_instance * crypto_init(const unsigned char *private_key, unsigned int private_key_len, const char *crypto_cipher_type, const char *crypto_hash_type, void(*log_printf_func)(int level, int subsys, const char *function, const char *file, int line, const char *format,...) __attribute__((format(printf, 6, 7))), int log_level_security, int log_level_notice, int log_level_error, int log_subsys_id)
Definition: totemcrypto.c:895
void totemip_copy(struct totem_ip_address *addr1, const struct totem_ip_address *addr2)
Definition: totemip.c:95
struct totem_ip_address mcast_address
Definition: totemudp.c:164
unsigned int downcheck_timeout
Definition: totem.h:148
int totemudp_mcast_noflush_send(void *udp_context, const void *msg, unsigned int msg_len)
Definition: totemudp.c:1337
unsigned int private_key_len
Definition: totem.h:127
int totemudp_log_level_security
Definition: totemudp.c:131
#define BIND_STATE_REGULAR
Definition: totemudp.c:88
struct totem_config * totem_config
Definition: totemudp.c:188
#define NETIF_STATE_REPORT_DOWN
Definition: totemudp.c:85
#define totemip_nosigpipe(s)
Definition: totemip.h:56
int totemudp_log_level_error
Definition: totemudp.c:133
int totemudp_send_flush(void *udp_context)
Definition: totemudp.c:1307
uint16_t ttl
Definition: totem.h:72
int totemudp_recv_flush(void *udp_context)
Definition: totemudp.c:1271
unsigned int node_id
Definition: totem.h:119
struct iovec totemudp_iov_recv
Definition: totemudp.c:158
int totemip_iface_check(struct totem_ip_address *bindnet, struct totem_ip_address *boundto, int *interface_up, int *interface_num, int mask_high_bit)
Definition: totemip.c:405
int crypto_encrypt_and_sign(struct crypto_instance *instance, const unsigned char *buf_in, const size_t buf_in_len, unsigned char *buf_out, size_t *buf_out_len)
Definition: totemcrypto.c:820
int totemudp_token_send(void *udp_context, const void *msg, unsigned int msg_len)
Definition: totemudp.c:1312
struct totem_interface * totem_interface
Definition: totemudp.c:109
int totemudp_initialize(qb_loop_t *poll_handle, void **udp_context, struct totem_config *totem_config, totemsrp_stats_t *stats, int interface_no, void *context, void(*deliver_fn)(void *context, const void *msg, unsigned int msg_len), void(*iface_change_fn)(void *context, const struct totem_ip_address *iface_address), void(*target_set_completed)(void *context))
Create an instance.
Definition: totemudp.c:1144
unsigned int nodeid
Definition: coroapi.h:112
qb_loop_t * totemudp_poll_handle
Definition: totemudp.c:107
char * crypto_hash_type
Definition: totem.h:186
int netif_state_report
Definition: totemudp.c:111
unsigned int my_memb_entries
Definition: totemudp.c:184
struct totem_ip_address mcast_addr
Definition: totem.h:70
Linked list API.
#define BIND_RETRIES_INTERVAL
Definition: totem.h:56
void(* totemudp_log_printf)(int level, int subsys, const char *function, const char *file, int line, const char *format,...) __attribute__((format(printf
Definition: totemudp.c:143
int totemudp_finalize(void *udp_context)
Definition: totemudp.c:411
struct totem_ip_address boundto
Definition: totem.h:69
#define BIND_STATE_LOOPBACK
Definition: totemudp.c:89
typedef __attribute__
size_t totemip_udpip_header_size(int family)
Definition: totemip.c:496
const char * totemudp_iface_print(void *udp_context)
Definition: totemudp.c:1370
#define NETIF_STATE_REPORT_UP
Definition: totemudp.c:84
void(* log_printf)(int level, int subsys, const char *function_name, const char *file_name, int file_line, const char *format,...) __attribute__((format(printf
Definition: totem.h:78
uint16_t ip_port
Definition: totem.h:71
#define MCAST_SOCKET_BUFFER_SIZE
Definition: totemudp.c:83
void(*) void udp_context)
Definition: totemudp.c:150
unsigned int net_mtu
Definition: totem.h:168
char iov_buffer_flush[FRAME_SIZE_MAX]
Definition: totemudp.c:156
int totemudp_log_level_debug
Definition: totemudp.c:139
int crypto_authenticate_and_decrypt(struct crypto_instance *instance, unsigned char *buf, int *buf_len)
Definition: totemcrypto.c:842
int totemudp_log_level_notice
Definition: totemudp.c:137
unsigned int broadcast_use
Definition: totem.h:182
int totemudp_iface_get(void *udp_context, struct totem_ip_address *addr)
Definition: totemudp.c:1379
#define FRAME_SIZE_MAX
Definition: totem.h:50
#define LOGSYS_LEVEL_CRIT
Definition: logsys.h:69
void(* totemudp_target_set_completed)(void *context)
Definition: totemudp.c:126
const void * msg
Definition: totemudp.c:196
int totemip_totemip_to_sockaddr_convert(struct totem_ip_address *ip_addr, uint16_t port, struct sockaddr_storage *saddr, int *addrlen)
Definition: totemip.c:222
struct totem_logging_configuration totem_logging_configuration
Definition: totem.h:166
#define LOGSYS_PERROR(err_num, level, fmt, args...)
Definition: totemudp.c:237
struct srp_addr system_from
Definition: totemsrp.c:61
#define log_printf(level, format, args...)
Definition: totemudp.c:229
char * crypto_cipher_type
Definition: totem.h:184
struct totem_ip_address my_id
Definition: totemudp.c:178
int totemudp_recv_mcast_empty(void *udp_context)
Definition: totemudp.c:1406
int totemudp_iface_check(void *udp_context)
Definition: totemudp.c:1350
struct totem_ip_address bindnet
Definition: totem.h:68
uint32_t continuous_sendmsg_failures
Definition: totem.h:272
unsigned int msg_len
Definition: totemudp.c:197
int local_mcast_loop[2]
Definition: totemudp.c:101
struct totem_ip_address token_target
Definition: totemudp.c:192
qb_loop_timer_handle timer_netif_check_timeout
Definition: totemudp.c:182
void totemudp_buffer_release(void *ptr)
Definition: totemudp.c:1244
int totemudp_log_level_warning
Definition: totemudp.c:135