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  if (msg_len + crypto_get_current_sec_header_size(instance->crypto_inst) > sizeof(buf_out)) {
272  log_printf(LOGSYS_LEVEL_CRIT, "UDP message for ucast is too big. Ignoring message");
273 
274  return ;
275  }
276 
277  /*
278  * Encrypt and digest the message
279  */
281  instance->crypto_inst,
282  (const unsigned char *)msg,
283  msg_len,
284  buf_out,
285  &buf_out_len) != 0) {
286  log_printf(LOGSYS_LEVEL_CRIT, "Error encrypting/signing packet (non-critical)");
287  return;
288  }
289 
290  iovec.iov_base = (void *)buf_out;
291  iovec.iov_len = buf_out_len;
292 
293  /*
294  * Build unicast message
295  */
296  memset(&msg_ucast, 0, sizeof(msg_ucast));
298  instance->totem_interface->ip_port, &sockaddr, &addrlen);
299  msg_ucast.msg_name = &sockaddr;
300  msg_ucast.msg_namelen = addrlen;
301  msg_ucast.msg_iov = (void *)&iovec;
302  msg_ucast.msg_iovlen = 1;
303 #ifdef HAVE_MSGHDR_CONTROL
304  msg_ucast.msg_control = 0;
305 #endif
306 #ifdef HAVE_MSGHDR_CONTROLLEN
307  msg_ucast.msg_controllen = 0;
308 #endif
309 #ifdef HAVE_MSGHDR_FLAGS
310  msg_ucast.msg_flags = 0;
311 #endif
312 #ifdef HAVE_MSGHDR_ACCRIGHTS
313  msg_ucast.msg_accrights = NULL;
314 #endif
315 #ifdef HAVE_MSGHDR_ACCRIGHTSLEN
316  msg_ucast.msg_accrightslen = 0;
317 #endif
318 
319 
320  /*
321  * Transmit unicast message
322  * An error here is recovered by totemsrp
323  */
324  res = sendmsg (instance->totemudp_sockets.mcast_send, &msg_ucast,
325  MSG_NOSIGNAL);
326  if (res < 0) {
327  LOGSYS_PERROR (errno, instance->totemudp_log_level_debug,
328  "sendmsg(ucast) failed (non-critical)");
329  }
330 }
331 
332 static inline void mcast_sendmsg (
333  struct totemudp_instance *instance,
334  const void *msg,
335  unsigned int msg_len)
336 {
337  struct msghdr msg_mcast;
338  int res = 0;
339  size_t buf_out_len;
340  unsigned char buf_out[FRAME_SIZE_MAX];
341  struct iovec iovec;
342  struct sockaddr_storage sockaddr;
343  int addrlen;
344 
345  if (msg_len + crypto_get_current_sec_header_size(instance->crypto_inst) > sizeof(buf_out)) {
346  log_printf(LOGSYS_LEVEL_CRIT, "UDP message for mcast is too big. Ignoring message");
347 
348  return ;
349  }
350 
351  /*
352  * Encrypt and digest the message
353  */
355  instance->crypto_inst,
356  (const unsigned char *)msg,
357  msg_len,
358  buf_out,
359  &buf_out_len) != 0) {
360  log_printf(LOGSYS_LEVEL_CRIT, "Error encrypting/signing packet (non-critical)");
361  return;
362  }
363 
364  iovec.iov_base = (void *)&buf_out;
365  iovec.iov_len = buf_out_len;
366 
367  /*
368  * Build multicast message
369  */
371  instance->totem_interface->ip_port, &sockaddr, &addrlen);
372  memset(&msg_mcast, 0, sizeof(msg_mcast));
373  msg_mcast.msg_name = &sockaddr;
374  msg_mcast.msg_namelen = addrlen;
375  msg_mcast.msg_iov = (void *)&iovec;
376  msg_mcast.msg_iovlen = 1;
377 #ifdef HAVE_MSGHDR_CONTROL
378  msg_mcast.msg_control = 0;
379 #endif
380 #ifdef HAVE_MSGHDR_CONTROLLEN
381  msg_mcast.msg_controllen = 0;
382 #endif
383 #ifdef HAVE_MSGHDR_FLAGS
384  msg_mcast.msg_flags = 0;
385 #endif
386 #ifdef HAVE_MSGHDR_ACCRIGHTS
387  msg_mcast.msg_accrights = NULL;
388 #endif
389 #ifdef HAVE_MSGHDR_ACCRIGHTSLEN
390  msg_mcast.msg_accrightslen = 0;
391 #endif
392 
393  /*
394  * Transmit multicast message
395  * An error here is recovered by totemsrp
396  */
397  res = sendmsg (instance->totemudp_sockets.mcast_send, &msg_mcast,
398  MSG_NOSIGNAL);
399  if (res < 0) {
400  LOGSYS_PERROR (errno, instance->totemudp_log_level_debug,
401  "sendmsg(mcast) failed (non-critical)");
402  instance->stats->continuous_sendmsg_failures++;
403  } else {
404  instance->stats->continuous_sendmsg_failures = 0;
405  }
406 
407  /*
408  * Transmit multicast message to local unix mcast loop
409  * An error here is recovered by totemsrp
410  */
411  msg_mcast.msg_name = NULL;
412  msg_mcast.msg_namelen = 0;
413 
414  res = sendmsg (instance->totemudp_sockets.local_mcast_loop[1], &msg_mcast,
415  MSG_NOSIGNAL);
416  if (res < 0) {
417  LOGSYS_PERROR (errno, instance->totemudp_log_level_debug,
418  "sendmsg(local mcast loop) failed (non-critical)");
419  }
420 }
421 
422 
424  void *udp_context)
425 {
426  struct totemudp_instance *instance = (struct totemudp_instance *)udp_context;
427  int res = 0;
428 
429  if (instance->totemudp_sockets.mcast_recv > 0) {
430  qb_loop_poll_del (instance->totemudp_poll_handle,
431  instance->totemudp_sockets.mcast_recv);
432  close (instance->totemudp_sockets.mcast_recv);
433  }
434  if (instance->totemudp_sockets.mcast_send > 0) {
435  close (instance->totemudp_sockets.mcast_send);
436  }
437  if (instance->totemudp_sockets.local_mcast_loop[0] > 0) {
438  qb_loop_poll_del (instance->totemudp_poll_handle,
439  instance->totemudp_sockets.local_mcast_loop[0]);
440  close (instance->totemudp_sockets.local_mcast_loop[0]);
441  close (instance->totemudp_sockets.local_mcast_loop[1]);
442  }
443  if (instance->totemudp_sockets.token > 0) {
444  qb_loop_poll_del (instance->totemudp_poll_handle,
445  instance->totemudp_sockets.token);
446  close (instance->totemudp_sockets.token);
447  }
448 
449  return (res);
450 }
451 
452 /*
453  * Only designed to work with a message with one iov
454  */
455 
456 static int net_deliver_fn (
457  int fd,
458  int revents,
459  void *data)
460 {
461  struct totemudp_instance *instance = (struct totemudp_instance *)data;
462  struct msghdr msg_recv;
463  struct iovec *iovec;
464  struct sockaddr_storage system_from;
465  int bytes_received;
466  int res = 0;
467 
468  if (instance->flushing == 1) {
469  iovec = &instance->totemudp_iov_recv_flush;
470  } else {
471  iovec = &instance->totemudp_iov_recv;
472  }
473 
474  /*
475  * Receive datagram
476  */
477  msg_recv.msg_name = &system_from;
478  msg_recv.msg_namelen = sizeof (struct sockaddr_storage);
479  msg_recv.msg_iov = iovec;
480  msg_recv.msg_iovlen = 1;
481 #ifdef HAVE_MSGHDR_CONTROL
482  msg_recv.msg_control = 0;
483 #endif
484 #ifdef HAVE_MSGHDR_CONTROLLEN
485  msg_recv.msg_controllen = 0;
486 #endif
487 #ifdef HAVE_MSGHDR_FLAGS
488  msg_recv.msg_flags = 0;
489 #endif
490 #ifdef HAVE_MSGHDR_ACCRIGHTS
491  msg_recv.msg_accrights = NULL;
492 #endif
493 #ifdef HAVE_MSGHDR_ACCRIGHTSLEN
494  msg_recv.msg_accrightslen = 0;
495 #endif
496 
497  bytes_received = recvmsg (fd, &msg_recv, MSG_NOSIGNAL | MSG_DONTWAIT);
498  if (bytes_received == -1) {
499  return (0);
500  } else {
501  instance->stats_recv += bytes_received;
502  }
503 
504  /*
505  * Authenticate and if authenticated, decrypt datagram
506  */
507  res = crypto_authenticate_and_decrypt (instance->crypto_inst, iovec->iov_base, &bytes_received);
508  if (res == -1) {
509  log_printf (instance->totemudp_log_level_security, "Received message has invalid digest... ignoring.");
511  "Invalid packet data");
512  iovec->iov_len = FRAME_SIZE_MAX;
513  return 0;
514  }
515  iovec->iov_len = bytes_received;
516 
517  /*
518  * Handle incoming message
519  */
520  instance->totemudp_deliver_fn (
521  instance->context,
522  iovec->iov_base,
523  iovec->iov_len);
524 
525  iovec->iov_len = FRAME_SIZE_MAX;
526  return (0);
527 }
528 
529 static int netif_determine (
530  struct totemudp_instance *instance,
531  struct totem_ip_address *bindnet,
532  struct totem_ip_address *bound_to,
533  int *interface_up,
534  int *interface_num)
535 {
536  int res;
537 
538  res = totemip_iface_check (bindnet, bound_to,
539  interface_up, interface_num,
540  instance->totem_config->clear_node_high_bit);
541 
542 
543  return (res);
544 }
545 
546 
547 /*
548  * If the interface is up, the sockets for totem are built. If the interface is down
549  * this function is requeued in the timer list to retry building the sockets later.
550  */
551 static void timer_function_netif_check_timeout (
552  void *data)
553 {
554  struct totemudp_instance *instance = (struct totemudp_instance *)data;
555  int interface_up;
556  int interface_num;
557  struct totem_ip_address *bind_address;
558 
559  /*
560  * Build sockets for every interface
561  */
562  netif_determine (instance,
563  &instance->totem_interface->bindnet,
564  &instance->totem_interface->boundto,
565  &interface_up, &interface_num);
566  /*
567  * If the network interface isn't back up and we are already
568  * in loopback mode, add timer to check again and return
569  */
570  if ((instance->netif_bind_state == BIND_STATE_LOOPBACK &&
571  interface_up == 0) ||
572 
573  (instance->my_memb_entries == 1 &&
574  instance->netif_bind_state == BIND_STATE_REGULAR &&
575  interface_up == 1)) {
576 
577  qb_loop_timer_add (instance->totemudp_poll_handle,
578  QB_LOOP_MED,
579  instance->totem_config->downcheck_timeout*QB_TIME_NS_IN_MSEC,
580  (void *)instance,
581  timer_function_netif_check_timeout,
582  &instance->timer_netif_check_timeout);
583 
584  /*
585  * Add a timer to check for a downed regular interface
586  */
587  return;
588  }
589 
590  if (instance->totemudp_sockets.mcast_recv > 0) {
591  qb_loop_poll_del (instance->totemudp_poll_handle,
592  instance->totemudp_sockets.mcast_recv);
593  close (instance->totemudp_sockets.mcast_recv);
594  }
595  if (instance->totemudp_sockets.mcast_send > 0) {
596  close (instance->totemudp_sockets.mcast_send);
597  }
598  if (instance->totemudp_sockets.local_mcast_loop[0] > 0) {
599  qb_loop_poll_del (instance->totemudp_poll_handle,
600  instance->totemudp_sockets.local_mcast_loop[0]);
601  close (instance->totemudp_sockets.local_mcast_loop[0]);
602  close (instance->totemudp_sockets.local_mcast_loop[1]);
603  }
604  if (instance->totemudp_sockets.token > 0) {
605  qb_loop_poll_del (instance->totemudp_poll_handle,
606  instance->totemudp_sockets.token);
607  close (instance->totemudp_sockets.token);
608  }
609 
610  if (interface_up == 0) {
611  /*
612  * Interface is not up
613  */
615  bind_address = &localhost;
616 
617  /*
618  * Add a timer to retry building interfaces and request memb_gather_enter
619  */
620  qb_loop_timer_add (instance->totemudp_poll_handle,
621  QB_LOOP_MED,
622  instance->totem_config->downcheck_timeout*QB_TIME_NS_IN_MSEC,
623  (void *)instance,
624  timer_function_netif_check_timeout,
625  &instance->timer_netif_check_timeout);
626  } else {
627  /*
628  * Interface is up
629  */
631  bind_address = &instance->totem_interface->bindnet;
632  }
633  /*
634  * Create and bind the multicast and unicast sockets
635  */
636  (void)totemudp_build_sockets (instance,
637  &instance->mcast_address,
638  bind_address,
639  &instance->totemudp_sockets,
640  &instance->totem_interface->boundto);
641 
642  qb_loop_poll_add (
643  instance->totemudp_poll_handle,
644  QB_LOOP_MED,
645  instance->totemudp_sockets.mcast_recv,
646  POLLIN, instance, net_deliver_fn);
647 
648  qb_loop_poll_add (
649  instance->totemudp_poll_handle,
650  QB_LOOP_MED,
651  instance->totemudp_sockets.local_mcast_loop[0],
652  POLLIN, instance, net_deliver_fn);
653 
654  qb_loop_poll_add (
655  instance->totemudp_poll_handle,
656  QB_LOOP_MED,
657  instance->totemudp_sockets.token,
658  POLLIN, instance, net_deliver_fn);
659 
660  totemip_copy (&instance->my_id, &instance->totem_interface->boundto);
661 
662  /*
663  * This reports changes in the interface to the user and totemsrp
664  */
665  if (instance->netif_bind_state == BIND_STATE_REGULAR) {
666  if (instance->netif_state_report & NETIF_STATE_REPORT_UP) {
668  "The network interface [%s] is now up.",
669  totemip_print (&instance->totem_interface->boundto));
671  instance->totemudp_iface_change_fn (instance->context, &instance->my_id);
672  }
673  /*
674  * Add a timer to check for interface going down in single membership
675  */
676  if (instance->my_memb_entries == 1) {
677  qb_loop_timer_add (instance->totemudp_poll_handle,
678  QB_LOOP_MED,
679  instance->totem_config->downcheck_timeout*QB_TIME_NS_IN_MSEC,
680  (void *)instance,
681  timer_function_netif_check_timeout,
682  &instance->timer_netif_check_timeout);
683  }
684 
685  } else {
688  "The network interface is down.");
689  instance->totemudp_iface_change_fn (instance->context, &instance->my_id);
690  }
692 
693  }
694 }
695 
696 /* Set the socket priority to INTERACTIVE to ensure
697  that our messages don't get queued behind anything else */
698 static void totemudp_traffic_control_set(struct totemudp_instance *instance, int sock)
699 {
700 #ifdef SO_PRIORITY
701  int prio = 6; /* TC_PRIO_INTERACTIVE */
702 
703  if (setsockopt(sock, SOL_SOCKET, SO_PRIORITY, &prio, sizeof(int))) {
704  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning, "Could not set traffic priority");
705  }
706 #endif
707 }
708 
709 static int totemudp_build_sockets_ip (
710  struct totemudp_instance *instance,
711  struct totem_ip_address *mcast_address,
712  struct totem_ip_address *bindnet_address,
713  struct totemudp_socket *sockets,
714  struct totem_ip_address *bound_to,
715  int interface_num)
716 {
717  struct sockaddr_storage sockaddr;
718  struct ipv6_mreq mreq6;
719  struct ip_mreq mreq;
720  struct sockaddr_storage mcast_ss, boundto_ss;
721  struct sockaddr_in6 *mcast_sin6 = (struct sockaddr_in6 *)&mcast_ss;
722  struct sockaddr_in *mcast_sin = (struct sockaddr_in *)&mcast_ss;
723  struct sockaddr_in *boundto_sin = (struct sockaddr_in *)&boundto_ss;
724  unsigned int sendbuf_size;
725  unsigned int recvbuf_size;
726  unsigned int optlen = sizeof (sendbuf_size);
727  unsigned int retries;
728  int addrlen;
729  int res;
730  int flag;
731  uint8_t sflag;
732  int i;
733 
734  /*
735  * Create multicast recv socket
736  */
737  sockets->mcast_recv = socket (bindnet_address->family, SOCK_DGRAM, 0);
738  if (sockets->mcast_recv == -1) {
739  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
740  "socket() failed");
741  return (-1);
742  }
743 
744  totemip_nosigpipe (sockets->mcast_recv);
745  res = fcntl (sockets->mcast_recv, F_SETFL, O_NONBLOCK);
746  if (res == -1) {
747  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
748  "Could not set non-blocking operation on multicast socket");
749  return (-1);
750  }
751 
752  /*
753  * Force reuse
754  */
755  flag = 1;
756  if ( setsockopt(sockets->mcast_recv, SOL_SOCKET, SO_REUSEADDR, (char *)&flag, sizeof (flag)) < 0) {
757  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
758  "setsockopt(SO_REUSEADDR) failed");
759  return (-1);
760  }
761 
762  /*
763  * Create local multicast loop socket
764  */
765  if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sockets->local_mcast_loop) == -1) {
766  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
767  "socket() failed");
768  return (-1);
769  }
770 
771  for (i = 0; i < 2; i++) {
772  totemip_nosigpipe (sockets->local_mcast_loop[i]);
773  res = fcntl (sockets->local_mcast_loop[i], F_SETFL, O_NONBLOCK);
774  if (res == -1) {
775  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
776  "Could not set non-blocking operation on multicast socket");
777  return (-1);
778  }
779  }
780 
781 
782 
783  /*
784  * Setup mcast send socket
785  */
786  sockets->mcast_send = socket (bindnet_address->family, SOCK_DGRAM, 0);
787  if (sockets->mcast_send == -1) {
788  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
789  "socket() failed");
790  return (-1);
791  }
792 
793  totemip_nosigpipe (sockets->mcast_send);
794  res = fcntl (sockets->mcast_send, F_SETFL, O_NONBLOCK);
795  if (res == -1) {
796  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
797  "Could not set non-blocking operation on multicast socket");
798  return (-1);
799  }
800 
801  /*
802  * Force reuse
803  */
804  flag = 1;
805  if ( setsockopt(sockets->mcast_send, SOL_SOCKET, SO_REUSEADDR, (char *)&flag, sizeof (flag)) < 0) {
806  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
807  "setsockopt(SO_REUSEADDR) failed");
808  return (-1);
809  }
810 
812  &sockaddr, &addrlen);
813 
814  retries = 0;
815  while (1) {
816  res = bind (sockets->mcast_send, (struct sockaddr *)&sockaddr, addrlen);
817  if (res == 0) {
818  break;
819  }
820  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
821  "Unable to bind the socket to send multicast packets");
822  if (++retries > BIND_MAX_RETRIES) {
823  break;
824  }
825 
826  /*
827  * Wait for a while
828  */
829  (void)poll(NULL, 0, BIND_RETRIES_INTERVAL * retries);
830  }
831  if (res == -1) {
832  return (-1);
833  }
834 
835  /*
836  * Setup unicast socket
837  */
838  sockets->token = socket (bindnet_address->family, SOCK_DGRAM, 0);
839  if (sockets->token == -1) {
840  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
841  "socket() failed");
842  return (-1);
843  }
844 
845  totemip_nosigpipe (sockets->token);
846  res = fcntl (sockets->token, F_SETFL, O_NONBLOCK);
847  if (res == -1) {
848  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
849  "Could not set non-blocking operation on token socket");
850  return (-1);
851  }
852 
853  /*
854  * Force reuse
855  */
856  flag = 1;
857  if ( setsockopt(sockets->token, SOL_SOCKET, SO_REUSEADDR, (char *)&flag, sizeof (flag)) < 0) {
858  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
859  "setsockopt(SO_REUSEADDR) failed");
860  return (-1);
861  }
862 
863  /*
864  * Bind to unicast socket used for token send/receives
865  * This has the side effect of binding to the correct interface
866  */
867  totemip_totemip_to_sockaddr_convert(bound_to, instance->totem_interface->ip_port, &sockaddr, &addrlen);
868 
869  retries = 0;
870  while (1) {
871  res = bind (sockets->token, (struct sockaddr *)&sockaddr, addrlen);
872  if (res == 0) {
873  break;
874  }
875  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
876  "Unable to bind UDP unicast socket");
877  if (++retries > BIND_MAX_RETRIES) {
878  break;
879  }
880 
881  /*
882  * Wait for a while
883  */
884  (void)poll(NULL, 0, BIND_RETRIES_INTERVAL * retries);
885  }
886  if (res == -1) {
887  return (-1);
888  }
889 
890  recvbuf_size = MCAST_SOCKET_BUFFER_SIZE;
891  sendbuf_size = MCAST_SOCKET_BUFFER_SIZE;
892  /*
893  * Set buffer sizes to avoid overruns
894  */
895  res = setsockopt (sockets->mcast_recv, 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 mcast socket");
899  return (-1);
900  }
901  res = setsockopt (sockets->mcast_send, 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 mcast socket");
905  return (-1);
906  }
907  res = setsockopt (sockets->local_mcast_loop[0], SOL_SOCKET, SO_RCVBUF, &recvbuf_size, optlen);
908  if (res == -1) {
909  LOGSYS_PERROR (errno, instance->totemudp_log_level_debug,
910  "Unable to set SO_RCVBUF size on UDP local mcast loop socket");
911  return (-1);
912  }
913  res = setsockopt (sockets->local_mcast_loop[1], SOL_SOCKET, SO_SNDBUF, &sendbuf_size, optlen);
914  if (res == -1) {
915  LOGSYS_PERROR (errno, instance->totemudp_log_level_debug,
916  "Unable to set SO_SNDBUF size on UDP local mcast loop socket");
917  return (-1);
918  }
919 
920  res = getsockopt (sockets->mcast_recv, SOL_SOCKET, SO_RCVBUF, &recvbuf_size, &optlen);
921  if (res == 0) {
923  "Receive multicast socket recv buffer size (%d bytes).", recvbuf_size);
924  }
925 
926  res = getsockopt (sockets->mcast_send, SOL_SOCKET, SO_SNDBUF, &sendbuf_size, &optlen);
927  if (res == 0) {
929  "Transmit multicast socket send buffer size (%d bytes).", sendbuf_size);
930  }
931 
932  res = getsockopt (sockets->local_mcast_loop[0], SOL_SOCKET, SO_RCVBUF, &recvbuf_size, &optlen);
933  if (res == 0) {
935  "Local receive multicast loop socket recv buffer size (%d bytes).", recvbuf_size);
936  }
937 
938  res = getsockopt (sockets->local_mcast_loop[1], SOL_SOCKET, SO_SNDBUF, &sendbuf_size, &optlen);
939  if (res == 0) {
941  "Local transmit multicast loop socket send buffer size (%d bytes).", sendbuf_size);
942  }
943 
944 
945  /*
946  * Join group membership on socket
947  */
948  totemip_totemip_to_sockaddr_convert(mcast_address, instance->totem_interface->ip_port, &mcast_ss, &addrlen);
949  totemip_totemip_to_sockaddr_convert(bound_to, instance->totem_interface->ip_port, &boundto_ss, &addrlen);
950 
951  if (instance->totem_config->broadcast_use == 1) {
952  unsigned int broadcast = 1;
953 
954  if ((setsockopt(sockets->mcast_recv, SOL_SOCKET,
955  SO_BROADCAST, &broadcast, sizeof (broadcast))) == -1) {
956  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
957  "setting broadcast option failed");
958  return (-1);
959  }
960  if ((setsockopt(sockets->mcast_send, SOL_SOCKET,
961  SO_BROADCAST, &broadcast, sizeof (broadcast))) == -1) {
962  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
963  "setting broadcast option failed");
964  return (-1);
965  }
966  } else {
967  switch (bindnet_address->family) {
968  case AF_INET:
969  memset(&mreq, 0, sizeof(mreq));
970  mreq.imr_multiaddr.s_addr = mcast_sin->sin_addr.s_addr;
971  mreq.imr_interface.s_addr = boundto_sin->sin_addr.s_addr;
972  res = setsockopt (sockets->mcast_recv, IPPROTO_IP, IP_ADD_MEMBERSHIP,
973  &mreq, sizeof (mreq));
974  if (res == -1) {
975  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
976  "join ipv4 multicast group failed");
977  return (-1);
978  }
979  break;
980  case AF_INET6:
981  memset(&mreq6, 0, sizeof(mreq6));
982  memcpy(&mreq6.ipv6mr_multiaddr, &mcast_sin6->sin6_addr, sizeof(struct in6_addr));
983  mreq6.ipv6mr_interface = interface_num;
984 
985  res = setsockopt (sockets->mcast_recv, IPPROTO_IPV6, IPV6_JOIN_GROUP,
986  &mreq6, sizeof (mreq6));
987  if (res == -1) {
988  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
989  "join ipv6 multicast group failed");
990  return (-1);
991  }
992  break;
993  }
994  }
995 
996  /*
997  * Turn off multicast loopback
998  */
999 
1000  flag = 0;
1001  switch ( bindnet_address->family ) {
1002  case AF_INET:
1003  sflag = 0;
1004  res = setsockopt (sockets->mcast_send, IPPROTO_IP, IP_MULTICAST_LOOP,
1005  &sflag, sizeof (sflag));
1006  break;
1007  case AF_INET6:
1008  res = setsockopt (sockets->mcast_send, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
1009  &flag, sizeof (flag));
1010  }
1011  if (res == -1) {
1012  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
1013  "Unable to turn off multicast loopback");
1014  return (-1);
1015  }
1016 
1017  /*
1018  * Set multicast packets TTL
1019  */
1020  flag = instance->totem_interface->ttl;
1021  if (bindnet_address->family == AF_INET6) {
1022  res = setsockopt (sockets->mcast_send, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
1023  &flag, sizeof (flag));
1024  if (res == -1) {
1025  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
1026  "set mcast v6 TTL failed");
1027  return (-1);
1028  }
1029  } else {
1030  sflag = flag;
1031  res = setsockopt(sockets->mcast_send, IPPROTO_IP, IP_MULTICAST_TTL,
1032  &sflag, sizeof(sflag));
1033  if (res == -1) {
1034  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
1035  "set mcast v4 TTL failed");
1036  return (-1);
1037  }
1038  }
1039 
1040  /*
1041  * Bind to a specific interface for multicast send and receive
1042  */
1043  switch ( bindnet_address->family ) {
1044  case AF_INET:
1045  if (setsockopt (sockets->mcast_send, IPPROTO_IP, IP_MULTICAST_IF,
1046  &boundto_sin->sin_addr, sizeof (boundto_sin->sin_addr)) < 0) {
1047  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
1048  "cannot select interface for multicast packets (send)");
1049  return (-1);
1050  }
1051  if (setsockopt (sockets->mcast_recv, IPPROTO_IP, IP_MULTICAST_IF,
1052  &boundto_sin->sin_addr, sizeof (boundto_sin->sin_addr)) < 0) {
1053  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
1054  "cannot select interface for multicast packets (recv)");
1055  return (-1);
1056  }
1057  break;
1058  case AF_INET6:
1059  if (setsockopt (sockets->mcast_send, IPPROTO_IPV6, IPV6_MULTICAST_IF,
1060  &interface_num, sizeof (interface_num)) < 0) {
1061  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
1062  "cannot select interface for multicast packets (send v6)");
1063  return (-1);
1064  }
1065  if (setsockopt (sockets->mcast_recv, IPPROTO_IPV6, IPV6_MULTICAST_IF,
1066  &interface_num, sizeof (interface_num)) < 0) {
1067  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
1068  "cannot select interface for multicast packets (recv v6)");
1069  return (-1);
1070  }
1071  break;
1072  }
1073 
1074  /*
1075  * Bind to multicast socket used for multicast receives
1076  * This needs to happen after all of the multicast setsockopt() calls
1077  * as the kernel seems to only put them into effect (for IPV6) when bind()
1078  * is called.
1079  */
1081  instance->totem_interface->ip_port, &sockaddr, &addrlen);
1082 
1083  retries = 0;
1084  while (1) {
1085  res = bind (sockets->mcast_recv, (struct sockaddr *)&sockaddr, addrlen);
1086  if (res == 0) {
1087  break;
1088  }
1089  LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
1090  "Unable to bind the socket to receive multicast packets");
1091  if (++retries > BIND_MAX_RETRIES) {
1092  break;
1093  }
1094 
1095  /*
1096  * Wait for a while
1097  */
1098  (void)poll(NULL, 0, BIND_RETRIES_INTERVAL * retries);
1099  }
1100 
1101  if (res == -1) {
1102  return (-1);
1103  }
1104  return 0;
1105 }
1106 
1107 static int totemudp_build_sockets (
1108  struct totemudp_instance *instance,
1109  struct totem_ip_address *mcast_address,
1110  struct totem_ip_address *bindnet_address,
1111  struct totemudp_socket *sockets,
1112  struct totem_ip_address *bound_to)
1113 {
1114  int interface_num;
1115  int interface_up;
1116  int res;
1117 
1118  /*
1119  * Determine the ip address bound to and the interface name
1120  */
1121  res = netif_determine (instance,
1122  bindnet_address,
1123  bound_to,
1124  &interface_up,
1125  &interface_num);
1126 
1127  if (res == -1) {
1128  return (-1);
1129  }
1130 
1131  totemip_copy(&instance->my_id, bound_to);
1132 
1133  res = totemudp_build_sockets_ip (instance, mcast_address,
1134  bindnet_address, sockets, bound_to, interface_num);
1135 
1136  if (res == -1) {
1137  /* if we get here, corosync won't work anyway, so better leaving than faking to work */
1138  LOGSYS_PERROR (errno, instance->totemudp_log_level_error,
1139  "Unable to create sockets, exiting");
1140  exit(EXIT_FAILURE);
1141  }
1142 
1143  /* We only send out of the token socket */
1144  totemudp_traffic_control_set(instance, sockets->token);
1145  return res;
1146 }
1147 
1148 /*
1149  * Totem Network interface - also does encryption/decryption
1150  * depends on poll abstraction, POSIX, IPV4
1151  */
1152 
1153 /*
1154  * Create an instance
1155  */
1157  qb_loop_t *poll_handle,
1158  void **udp_context,
1159  struct totem_config *totem_config,
1160  totemsrp_stats_t *stats,
1161  int interface_no,
1162  void *context,
1163 
1164  void (*deliver_fn) (
1165  void *context,
1166  const void *msg,
1167  unsigned int msg_len),
1168 
1169  void (*iface_change_fn) (
1170  void *context,
1171  const struct totem_ip_address *iface_address),
1172 
1173  void (*target_set_completed) (
1174  void *context))
1175 {
1176  struct totemudp_instance *instance;
1177 
1178  instance = malloc (sizeof (struct totemudp_instance));
1179  if (instance == NULL) {
1180  return (-1);
1181  }
1182 
1183  totemudp_instance_initialize (instance);
1184 
1185  instance->totem_config = totem_config;
1186  instance->stats = stats;
1187 
1188  /*
1189  * Configure logging
1190  */
1191  instance->totemudp_log_level_security = 1; //totem_config->totem_logging_configuration.log_level_security;
1198 
1199  /*
1200  * Initialize random number generator for later use to generate salt
1201  */
1202  instance->crypto_inst = crypto_init (totem_config->private_key,
1203  totem_config->private_key_len,
1204  totem_config->crypto_cipher_type,
1205  totem_config->crypto_hash_type,
1206  instance->totemudp_log_printf,
1207  instance->totemudp_log_level_security,
1208  instance->totemudp_log_level_notice,
1209  instance->totemudp_log_level_error,
1210  instance->totemudp_subsys_id);
1211  if (instance->crypto_inst == NULL) {
1212  free(instance);
1213  return (-1);
1214  }
1215  /*
1216  * Initialize local variables for totemudp
1217  */
1218  instance->totem_interface = &totem_config->interfaces[interface_no];
1219  totemip_copy (&instance->mcast_address, &instance->totem_interface->mcast_addr);
1220  memset (instance->iov_buffer, 0, FRAME_SIZE_MAX);
1221 
1222  instance->totemudp_poll_handle = poll_handle;
1223 
1224  instance->totem_interface->bindnet.nodeid = instance->totem_config->node_id;
1225 
1226  instance->context = context;
1227  instance->totemudp_deliver_fn = deliver_fn;
1228 
1229  instance->totemudp_iface_change_fn = iface_change_fn;
1230 
1231  instance->totemudp_target_set_completed = target_set_completed;
1232 
1233  totemip_localhost (instance->mcast_address.family, &localhost);
1234  localhost.nodeid = instance->totem_config->node_id;
1235 
1236  /*
1237  * RRP layer isn't ready to receive message because it hasn't
1238  * initialized yet. Add short timer to check the interfaces.
1239  */
1240  qb_loop_timer_add (instance->totemudp_poll_handle,
1241  QB_LOOP_MED,
1242  100*QB_TIME_NS_IN_MSEC,
1243  (void *)instance,
1244  timer_function_netif_check_timeout,
1245  &instance->timer_netif_check_timeout);
1246 
1247  *udp_context = instance;
1248  return (0);
1249 }
1250 
1252 {
1253  return malloc (FRAME_SIZE_MAX);
1254 }
1255 
1256 void totemudp_buffer_release (void *ptr)
1257 {
1258  return free (ptr);
1259 }
1260 
1262  void *udp_context,
1263  int processor_count)
1264 {
1265  struct totemudp_instance *instance = (struct totemudp_instance *)udp_context;
1266  int res = 0;
1267 
1268  instance->my_memb_entries = processor_count;
1269  qb_loop_timer_del (instance->totemudp_poll_handle,
1270  instance->timer_netif_check_timeout);
1271  if (processor_count == 1) {
1272  qb_loop_timer_add (instance->totemudp_poll_handle,
1273  QB_LOOP_MED,
1274  instance->totem_config->downcheck_timeout*QB_TIME_NS_IN_MSEC,
1275  (void *)instance,
1276  timer_function_netif_check_timeout,
1277  &instance->timer_netif_check_timeout);
1278  }
1279 
1280  return (res);
1281 }
1282 
1283 int totemudp_recv_flush (void *udp_context)
1284 {
1285  struct totemudp_instance *instance = (struct totemudp_instance *)udp_context;
1286  struct pollfd ufd;
1287  int nfds;
1288  int res = 0;
1289  int i;
1290  int sock;
1291 
1292  instance->flushing = 1;
1293 
1294  for (i = 0; i < 2; i++) {
1295  sock = -1;
1296  if (i == 0) {
1297  sock = instance->totemudp_sockets.mcast_recv;
1298  }
1299  if (i == 1) {
1300  sock = instance->totemudp_sockets.local_mcast_loop[0];
1301  }
1302  assert(sock != -1);
1303 
1304  do {
1305  ufd.fd = sock;
1306  ufd.events = POLLIN;
1307  nfds = poll (&ufd, 1, 0);
1308  if (nfds == 1 && ufd.revents & POLLIN) {
1309  net_deliver_fn (sock, ufd.revents, instance);
1310  }
1311  } while (nfds == 1);
1312  }
1313 
1314  instance->flushing = 0;
1315 
1316  return (res);
1317 }
1318 
1319 int totemudp_send_flush (void *udp_context)
1320 {
1321  return 0;
1322 }
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  ucast_sendmsg (instance, &instance->token_target, msg, msg_len);
1333 
1334  return (res);
1335 }
1337  void *udp_context,
1338  const void *msg,
1339  unsigned int msg_len)
1340 {
1341  struct totemudp_instance *instance = (struct totemudp_instance *)udp_context;
1342  int res = 0;
1343 
1344  mcast_sendmsg (instance, msg, msg_len);
1345 
1346  return (res);
1347 }
1348 
1350  void *udp_context,
1351  const void *msg,
1352  unsigned int msg_len)
1353 {
1354  struct totemudp_instance *instance = (struct totemudp_instance *)udp_context;
1355  int res = 0;
1356 
1357  mcast_sendmsg (instance, msg, msg_len);
1358 
1359  return (res);
1360 }
1361 
1362 extern int totemudp_iface_check (void *udp_context)
1363 {
1364  struct totemudp_instance *instance = (struct totemudp_instance *)udp_context;
1365  int res = 0;
1366 
1367  timer_function_netif_check_timeout (instance);
1368 
1369  return (res);
1370 }
1371 
1372 extern void totemudp_net_mtu_adjust (void *udp_context, struct totem_config *totem_config)
1373 {
1374 
1375  assert(totem_config->interface_count > 0);
1376 
1377  totem_config->net_mtu -= crypto_sec_header_size(totem_config->crypto_cipher_type,
1378  totem_config->crypto_hash_type) +
1380 }
1381 
1382 const char *totemudp_iface_print (void *udp_context) {
1383  struct totemudp_instance *instance = (struct totemudp_instance *)udp_context;
1384  const char *ret_char;
1385 
1386  ret_char = totemip_print (&instance->my_id);
1387 
1388  return (ret_char);
1389 }
1390 
1392  void *udp_context,
1393  struct totem_ip_address *addr)
1394 {
1395  struct totemudp_instance *instance = (struct totemudp_instance *)udp_context;
1396  int res = 0;
1397 
1398  memcpy (addr, &instance->my_id, sizeof (struct totem_ip_address));
1399 
1400  return (res);
1401 }
1402 
1404  void *udp_context,
1405  const struct totem_ip_address *token_target)
1406 {
1407  struct totemudp_instance *instance = (struct totemudp_instance *)udp_context;
1408  int res = 0;
1409 
1410  memcpy (&instance->token_target, token_target,
1411  sizeof (struct totem_ip_address));
1412 
1413  instance->totemudp_target_set_completed (instance->context);
1414 
1415  return (res);
1416 }
1417 
1419  void *udp_context)
1420 {
1421  struct totemudp_instance *instance = (struct totemudp_instance *)udp_context;
1422  unsigned int res;
1423  struct sockaddr_storage system_from;
1424  struct msghdr msg_recv;
1425  struct pollfd ufd;
1426  int nfds;
1427  int msg_processed = 0;
1428  int i;
1429  int sock;
1430 
1431  /*
1432  * Receive datagram
1433  */
1434  msg_recv.msg_name = &system_from;
1435  msg_recv.msg_namelen = sizeof (struct sockaddr_storage);
1436  msg_recv.msg_iov = &instance->totemudp_iov_recv_flush;
1437  msg_recv.msg_iovlen = 1;
1438 #ifdef HAVE_MSGHDR_CONTROL
1439  msg_recv.msg_control = 0;
1440 #endif
1441 #ifdef HAVE_MSGHDR_CONTROLLEN
1442  msg_recv.msg_controllen = 0;
1443 #endif
1444 #ifdef HAVE_MSGHDR_FLAGS
1445  msg_recv.msg_flags = 0;
1446 #endif
1447 #ifdef HAVE_MSGHDR_ACCRIGHTS
1448  msg_recv.msg_accrights = NULL;
1449 #endif
1450 #ifdef HAVE_MSGHDR_ACCRIGHTSLEN
1451  msg_recv.msg_accrightslen = 0;
1452 #endif
1453 
1454  for (i = 0; i < 2; i++) {
1455  sock = -1;
1456  if (i == 0) {
1457  sock = instance->totemudp_sockets.mcast_recv;
1458  }
1459  if (i == 1) {
1460  sock = instance->totemudp_sockets.local_mcast_loop[0];
1461  }
1462  assert(sock != -1);
1463 
1464  do {
1465  ufd.fd = sock;
1466  ufd.events = POLLIN;
1467  nfds = poll (&ufd, 1, 0);
1468  if (nfds == 1 && ufd.revents & POLLIN) {
1469  res = recvmsg (sock, &msg_recv, MSG_NOSIGNAL | MSG_DONTWAIT);
1470  if (res != -1) {
1471  msg_processed = 1;
1472  } else {
1473  msg_processed = -1;
1474  }
1475  }
1476  } while (nfds == 1);
1477  }
1478 
1479  return (msg_processed);
1480 }
1481 
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:1261
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:776
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
size_t crypto_get_current_sec_header_size(const struct crypto_instance *instance)
Definition: totemcrypto.c:811
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:1372
void * totemudp_buffer_alloc(void)
Definition: totemudp.c:1251
int totemudp_mcast_flush_send(void *udp_context, const void *msg, unsigned int msg_len)
Definition: totemudp.c:1336
int totemudp_token_target_set(void *udp_context, const struct totem_ip_address *token_target)
Definition: totemudp.c:1403
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:912
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:1349
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:1319
uint16_t ttl
Definition: totem.h:72
int totemudp_recv_flush(void *udp_context)
Definition: totemudp.c:1283
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:832
int totemudp_token_send(void *udp_context, const void *msg, unsigned int msg_len)
Definition: totemudp.c:1324
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:1156
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:423
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:1382
#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:854
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:1391
#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:1418
int totemudp_iface_check(void *udp_context)
Definition: totemudp.c:1362
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:1256
int totemudp_log_level_warning
Definition: totemudp.c:135