[Pacemaker] [PATCH] pingd: set ICMP6 filter
Kazunori INOUE
inouekazu at intellilink.co.jp
Thu Oct 15 06:19:43 EDT 2009
Hi Andrew,
Andrew Beekhof wrote:
> 2009/10/9 Kazunori INOUE <inouekazu at intellilink.co.jp>:
>> Hi all,
>>
>> I'm posting patch for pignd in Pacemaker 1.0 (changeset:6cf252e61e25).
>> This patch sets the filter of ICMP6 and fixed some bugs.
>
> Could you be a little more specific about what those bugs were? :-)
>
I'm sorry, I'd like to explain 3 fixed bugs.
1. Under a specific situation, in spite of dead node, it is detected as
alive.
* Steps to reproduce:
# /usr/lib64/heartbeat/pingd -N 'dead node'
# ping 'alive node' -i.3 (ping is executed at another terminal.)
-> pingd may detect that the node is alive.
* ha-debug:
# /usr/lib64/heartbeat/pingd -V -N 192.168.16.196
# ping 192.168.16.195 -i.3
:
# cat /var/log/ha-debug
Oct 15 13:04:32 x3650a pingd: [21347]: info: Invoked: /usr/lib64/heartbeat/pingd -V -N 192.168.16.196
Oct 15 13:04:32 x3650a pingd: [21347]: info: main: Starting pingd
Oct 15 13:04:33 x3650a pingd: [21347]: debug: stand_alone_ping: Node 192.168.16.196 is alive
Oct 15 13:04:33 x3650a pingd: [21347]: info: attrd_lazy_update: Connecting to cluster... 5 retries remaining
Oct 15 13:04:33 x3650a pingd: [21347]: debug: init_client_ipc_comms_nodispatch: Attempting to talk on: /var/run/crm/attrd
Oct 15 13:04:33 x3650a pingd: [21347]: debug: attrd_update: Sent update: pingd=1 for localhost
Oct 15 13:04:34 x3650a pingd: [21347]: debug: process_icmp_error: No error message: -1: Resource temporarily unavailable (11)
Oct 15 13:04:34 x3650a pingd: [21347]: info: stand_alone_ping: Node 192.168.16.196 is unreachable (read)
Oct 15 13:04:35 x3650a pingd: [21347]: debug: process_icmp_error: No error message: -1: Resource temporarily unavailable (11)
Oct 15 13:04:35 x3650a pingd: [21347]: info: stand_alone_ping: Node 192.168.16.196 is unreachable (read)
Oct 15 13:04:36 x3650a pingd: [21347]: debug: attrd_update: Sent update: pingd=0 for localhost
Oct 15 13:04:36 x3650a pingd: [21347]: debug: process_icmp_error: No error message: -1: Resource temporarily unavailable (11)
Oct 15 13:04:36 x3650a pingd: [21347]: info: stand_alone_ping: Node 192.168.16.196 is unreachable (read)
Oct 15 13:04:37 x3650a pingd: [21347]: debug: process_icmp_error: No error message: -1: Resource temporarily unavailable (11)
Oct 15 13:04:37 x3650a pingd: [21347]: info: stand_alone_ping: Node 192.168.16.196 is unreachable (read)
Oct 15 13:04:38 x3650a pingd: [21347]: debug: attrd_update: Sent update: pingd=0 for localhost
Oct 15 13:04:38 x3650a pingd: [21347]: debug: process_icmp_error: No error message: -1: Resource temporarily unavailable (11)
Oct 15 13:04:38 x3650a pingd: [21347]: info: stand_alone_ping: Node 192.168.16.196 is unreachable (read)
Oct 15 13:04:39 x3650a pingd: [21347]: debug: ping_read: Read failed: No route to host (113)
Oct 15 13:04:39 x3650a pingd: [21347]: info: stand_alone_ping: Node 192.168.16.196 is unreachable (read)
Oct 15 13:04:40 x3650a pingd: [21347]: debug: attrd_update: Sent update: pingd=0 for localhost
# grep pingd= /var/log/ha-debug
Oct 15 13:04:33 x3650a pingd: [21347]: debug: attrd_update: Sent update: pingd=1 for localhost
Oct 15 13:04:36 x3650a pingd: [21347]: debug: attrd_update: Sent update: pingd=0 for localhost
Oct 15 13:04:38 x3650a pingd: [21347]: debug: attrd_update: Sent update: pingd=0 for localhost
Oct 15 13:04:40 x3650a pingd: [21347]: debug: attrd_update: Sent update: pingd=0 for localhost
* The part of a corresponding patch:
513 @@ -507,19 +739,21 @@
514 }
515 icp = (struct icmp6_hdr *)buf;
516
517 - if (icp->icmp6_type == ICMP6_ECHO_REPLY
518 - && node->iseq == ntohs(icp->icmp6_seq)) {
519 - rc = 1; /* Alive */
520 + if (icp->icmp6_type == ICMP6_ECHO_REPLY) {
521 + if (ident == ntohs(icp->icmp6_id)
522 + && node->iseq == ntohs(icp->icmp6_seq)) {
523 + rc = 1; /* Alive */
524 + }
525
541 @@ -558,12 +792,14 @@
542 /* Check the IP header */
543 icp = (struct icmp*)(buf + iplen);
544
545 - if (icp->icmp_type == ICMP_ECHOREPLY
546 - && node->iseq == ntohs(icp->icmp_seq)) {
547 - rc = 1; /* Alive */
548 + if (icp->icmp_type == ICMP_ECHOREPLY) {
549 + if (ident == ntohs(icp->icmp_id)
550 + && node->iseq == ntohs(icp->icmp_seq)) {
551 + rc = 1; /* Alive */
552 + }
553
610 @@ -622,6 +874,13 @@
611 rc = dump_v4_echo(node, packet, bytes, &m);
612 }
613
614 + gettimeofday(&recv_time, NULL);
615 + if ((recv_start_time.tv_sec + ping_timeout) < recv_time.tv_sec) {
616 + crm_warn("failed to receive for timeout.");
617 + crm_free(packet);
618 + return FALSE;
619 + }
620 +
2. a small bug
* The part of a corresponding patch:
633 @@ -1024,7 +1285,7 @@
634 crm_err("non-option ARGV-elements: ");
635 printf("non-option ARGV-elements: ");
636 while (optind < argc) {
637 - crm_err("%s ", argv[optind++]);
638 + crm_err("%s ", argv[optind]);
639 printf("%s ", argv[optind++]);
640 }
641 printf("\n");
3. Since the ICMP filter of IPv6 is not set up, ERROR and WARN log are
outputted.
* ha-debug:
# cat /var/log/ha-debug
Oct 15 13:40:11 x3650a pingd.ORG: [21422]: info: Invoked: /usr/lib64/heartbeat/pingd.ORG -N 2001:db8:91:0:91::182 -V
Oct 15 13:40:11 x3650a pingd.ORG: [21422]: info: main: Starting pingd.ORG
Oct 15 13:40:11 x3650a pingd.ORG: [21422]: WARN: ping_open: setsockopt failed: Cannot install ICMP filters for 2001:db8:91:0:91::182: Protocol not available (92)
Oct 15 13:40:11 x3650a pingd.ORG: [21422]: ERROR: ping_desc: Unknown type: 128
Oct 15 13:40:11 x3650a pingd.ORG: [21422]: debug: dump_v6_echo: Echo from 2001:db8:91:0:91::182 (exp=1, seq=1, id=21422, dest=2001:db8:91:0:91::182, data=pingd-v6): Unknown type
Oct 15 13:40:11 x3650a pingd.ORG: [21422]: info: ping_read: Retrying...
Oct 15 13:40:11 x3650a pingd.ORG: [21422]: ERROR: ping_desc: Unknown type: 129
Oct 15 13:40:11 x3650a pingd.ORG: [21422]: debug: dump_v6_echo: Echo from 2001:db8:91:0:91::182 (exp=1, seq=1, id=21422, dest=2001:db8:91:0:91::182, data=pingd-v6): Unknown type
Oct 15 13:40:11 x3650a pingd.ORG: [21422]: debug: stand_alone_ping: Node 2001:db8:91:0:91::182 is alive
Oct 15 13:40:11 x3650a pingd.ORG: [21422]: info: attrd_lazy_update: Connecting to cluster... 5 retries remaining
Oct 15 13:40:11 x3650a pingd.ORG: [21422]: debug: init_client_ipc_comms_nodispatch: Attempting to talk on: /var/run/crm/attrd
Oct 15 13:40:11 x3650a pingd.ORG: [21422]: debug: attrd_update: Sent update: pingd=1 for localhost
Oct 15 13:40:12 x3650a pingd.ORG: [21422]: WARN: ping_open: setsockopt failed: Cannot install ICMP filters for 2001:db8:91:0:91::182: Protocol not available (92)
Oct 15 13:40:12 x3650a pingd.ORG: [21422]: ERROR: ping_desc: Unknown type: 128
Oct 15 13:40:12 x3650a pingd.ORG: [21422]: debug: dump_v6_echo: Echo from 2001:db8:91:0:91::182 (exp=2, seq=2, id=21422, dest=2001:db8:91:0:91::182, data=pingd-v6): Unknown type
Oct 15 13:40:12 x3650a pingd.ORG: [21422]: info: ping_read: Retrying...
Oct 15 13:40:12 x3650a pingd.ORG: [21422]: ERROR: ping_desc: Unknown type: 129
Oct 15 13:40:12 x3650a pingd.ORG: [21422]: debug: dump_v6_echo: Echo from 2001:db8:91:0:91::182 (exp=2, seq=2, id=21422, dest=2001:db8:91:0:91::182, data=pingd-v6): Unknown type
Oct 15 13:40:12 x3650a pingd.ORG: [21422]: debug: stand_alone_ping: Node 2001:db8:91:0:91::182 is alive
Oct 15 13:40:12 x3650a pingd.ORG: [21422]: debug: attrd_update: Sent update: pingd=1 for localhost
Therefore, the ICMP filter of IPV6 is set up.
- add process_icmp6_error() , and
process_icmp_error() is renamed to process_icmp4_error().
- modified ping_desc().
I hope they are helpful to you.
Regards,
Kazunori INOUE
>> I hope they are helpful to you.
>>
>> Regards,
>> Kazunori INOUE
>>
>> diff -urN stable-1.0.org/tools/pingd.c stable-1.0.mod/tools/pingd.c
>> --- stable-1.0.org/tools/pingd.c 2009-10-09 14:05:07.000000000 +0900
>> +++ stable-1.0.mod/tools/pingd.c 2009-10-09 13:57:21.000000000 +0900
>> @@ -40,6 +40,9 @@
>> #include <sys/un.h>
>> #include <sys/socket.h>
>> #include <sys/uio.h>
>> +#include <sys/time.h>
>> +#include <net/if.h>
>> +#include <sys/ioctl.h>
>>
>> #include <arpa/inet.h>
>> #include <netinet/ip.h>
>> @@ -89,6 +92,9 @@
>>
>> int ident; /* our pid */
>>
>> +unsigned char cmsgbuf[4096];
>> +int cmsglen = 0;
>> +
>> typedef struct ping_node_s {
>> int fd; /* ping socket */
>> uint16_t iseq; /* sequence number */
>> @@ -109,7 +115,8 @@
>> const char *node, const char *link, const char *status,
>> void *private_data);
>> void send_update(int active);
>> -int process_icmp_error(ping_node *node, struct sockaddr_in *whereto);
>> +int process_icmp6_error(ping_node *node, struct sockaddr_in6 *whereto);
>> +int process_icmp4_error(ping_node *node, struct sockaddr_in *whereto);
>>
>> /*
>> * in_cksum --
>> @@ -148,102 +155,248 @@
>> return answer;
>> }
>>
>> -static const char *ping_desc(uint8_t type, uint8_t code)
>> +static const char *ping_desc(gboolean family, uint8_t type, uint8_t code)
>> {
>> - switch(type) {
>> - case ICMP_ECHOREPLY:
>> - return "Echo Reply";
>> - case ICMP_ECHO:
>> - return "Echo Request";
>> - case ICMP_PARAMPROB:
>> - return "Bad Parameter";
>> - case ICMP_SOURCEQUENCH:
>> - return "Packet lost, slow down";
>> - case ICMP_TSTAMP:
>> - return "Timestamp Request";
>> - case ICMP_TSTAMPREPLY:
>> - return "Timestamp Reply";
>> - case ICMP_IREQ:
>> - return "Information Request";
>> - case ICMP_IREQREPLY:
>> - return "Information Reply";
>> -
>> - case ICMP_UNREACH:
>> - switch(code) {
>> - case ICMP_UNREACH_NET:
>> - return "Unreachable Network";
>> - case ICMP_UNREACH_HOST:
>> - return "Unreachable Host";
>> - case ICMP_UNREACH_PROTOCOL:
>> - return "Unreachable Protocol";
>> - case ICMP_UNREACH_PORT:
>> - return "Unreachable Port";
>> - case ICMP_UNREACH_NEEDFRAG:
>> - return "Unreachable: Fragmentation needed";
>> - case ICMP_UNREACH_SRCFAIL:
>> - return "Unreachable Source Route";
>> - case ICMP_UNREACH_NET_UNKNOWN:
>> - return "Unknown Network";
>> - case ICMP_UNREACH_HOST_UNKNOWN:
>> - return "Unknown Host";
>> - case ICMP_UNREACH_ISOLATED:
>> - return "Unreachable: Isolated";
>> - case ICMP_UNREACH_NET_PROHIB:
>> - return "Prohibited network";
>> - case ICMP_UNREACH_HOST_PROHIB:
>> - return "Prohibited host";
>> - case ICMP_UNREACH_FILTER_PROHIB:
>> - return "Unreachable: Prohibited filter";
>> - case ICMP_UNREACH_TOSNET:
>> - return "Unreachable: Type of Service and Network";
>> - case ICMP_UNREACH_TOSHOST:
>> - return "Unreachable: Type of Service and Host";
>> - case ICMP_UNREACH_HOST_PRECEDENCE:
>> - return "Unreachable: Prec vio";
>> - case ICMP_UNREACH_PRECEDENCE_CUTOFF:
>> - return "Unreachable: Prec cutoff";
>> + if(family == AF_INET6) {
>> + switch(type) {
>> + case ICMP6_DST_UNREACH:
>> + switch(code) {
>> + case ICMP6_DST_UNREACH_NOROUTE:
>> + return "No Route to Destination";
>> + case ICMP6_DST_UNREACH_ADMIN:
>> + return "Destination Administratively Unreachable";
>> + case ICMP6_DST_UNREACH_BEYONDSCOPE:
>> + return "Destination Unreachable Beyond Scope";
>> + case ICMP6_DST_UNREACH_ADDR:
>> + return "Destination Address Unreachable";
>> + case ICMP6_DST_UNREACH_NOPORT:
>> + return "Destination Port Unreachable";
>> + default:
>> + crm_err("Unreachable: Unkown subtype: %d", code);
>> + return "Unreachable: Unkown Subtype";
>> + }
>> + case ICMP6_PACKET_TOO_BIG:
>> + return "Packet too big";
>> + case ICMP6_TIME_EXCEEDED:
>> + switch(code) {
>> + case ICMP6_TIME_EXCEED_TRANSIT:
>> + return "Time to live exceeded";
>> + case ICMP6_TIME_EXCEED_REASSEMBLY:
>> + return "Frag reassembly time exceeded";
>> + default:
>> + crm_err("Timeout: Unkown subtype: %d", code);
>> + return "Timeout: Unkown Subtype";
>> + }
>> + case ICMP6_PARAM_PROB:
>> + switch(code) {
>> + case ICMP6_PARAMPROB_HEADER:
>> + return "Parameter problem: Erroneous Header";
>> + case ICMP6_PARAMPROB_NEXTHEADER:
>> + return "Parameter problem: Unknown Nextheader";
>> + case ICMP6_PARAMPROB_OPTION:
>> + return "Parameter problem: Unrecognized Option";
>> + default:
>> + crm_err("Invalid header: Unkown subtype: %d", code);
>> + return "Invalid header: Unkown Subtype";
>> + }
>> + case ICMP6_ECHO_REQUEST:
>> + return "Echo Request";
>> + case ICMP6_ECHO_REPLY:
>> + return "Echo Reply";
>> + case MLD_LISTENER_QUERY:
>> + return "Multicast Listener Query";
>> + case MLD_LISTENER_REPORT:
>> + return "Multicast Listener Report";
>> + case MLD_LISTENER_REDUCTION:
>> + return "Multicast Listener Done";
>> + case ND_ROUTER_SOLICIT:
>> + return "Router Solicitation";
>> + case ND_ROUTER_ADVERT:
>> + return "Router Advertisement";
>> + case ND_NEIGHBOR_SOLICIT:
>> + return "Neighbor Solicitation";
>> + case ND_NEIGHBOR_ADVERT:
>> + return "Neighbor Advertisement";
>> + case ND_REDIRECT:
>> + return "Redirect";
>> + case ICMP6_ROUTER_RENUMBERING:
>> + return "Router renumbering";
>> default:
>> - crm_err("Unreachable: Unknown subtype: %d", code);
>> - return "Unreachable: Unknown Subtype";
>> - }
>> - break;
>> + crm_err("Unknown type: %d", type);
>> + return "Unknown type";
>> + }
>> + } else {
>> + switch(type) {
>> + case ICMP_ECHOREPLY:
>> + return "Echo Reply";
>> + case ICMP_ECHO:
>> + return "Echo Request";
>> + case ICMP_PARAMPROB:
>> + return "Bad Parameter";
>> + case ICMP_SOURCEQUENCH:
>> + return "Packet lost, slow down";
>> + case ICMP_TSTAMP:
>> + return "Timestamp Request";
>> + case ICMP_TSTAMPREPLY:
>> + return "Timestamp Reply";
>> + case ICMP_IREQ:
>> + return "Information Request";
>> + case ICMP_IREQREPLY:
>> + return "Information Reply";
>> +
>> + case ICMP_UNREACH:
>> + switch(code) {
>> + case ICMP_UNREACH_NET:
>> + return "Unreachable Network";
>> + case ICMP_UNREACH_HOST:
>> + return "Unreachable Host";
>> + case ICMP_UNREACH_PROTOCOL:
>> + return "Unreachable Protocol";
>> + case ICMP_UNREACH_PORT:
>> + return "Unreachable Port";
>> + case ICMP_UNREACH_NEEDFRAG:
>> + return "Unreachable: Fragmentation needed";
>> + case ICMP_UNREACH_SRCFAIL:
>> + return "Unreachable Source Route";
>> + case ICMP_UNREACH_NET_UNKNOWN:
>> + return "Unknown Network";
>> + case ICMP_UNREACH_HOST_UNKNOWN:
>> + return "Unknown Host";
>> + case ICMP_UNREACH_ISOLATED:
>> + return "Unreachable: Isolated";
>> + case ICMP_UNREACH_NET_PROHIB:
>> + return "Prohibited network";
>> + case ICMP_UNREACH_HOST_PROHIB:
>> + return "Prohibited host";
>> + case ICMP_UNREACH_FILTER_PROHIB:
>> + return "Unreachable: Prohibited filter";
>> + case ICMP_UNREACH_TOSNET:
>> + return "Unreachable: Type of Service and Network";
>> + case ICMP_UNREACH_TOSHOST:
>> + return "Unreachable: Type of Service and Host";
>> + case ICMP_UNREACH_HOST_PRECEDENCE:
>> + return "Unreachable: Prec vio";
>> + case ICMP_UNREACH_PRECEDENCE_CUTOFF:
>> + return "Unreachable: Prec cutoff";
>> + default:
>> + crm_err("Unreachable: Unknown subtype: %d", code);
>> + return "Unreachable: Unknown Subtype";
>> + }
>> + break;
>>
>> - case ICMP_REDIRECT:
>> - switch(code) {
>> - case ICMP_REDIRECT_NET:
>> - return "Redirect: Network";
>> - case ICMP_REDIRECT_HOST:
>> - return "Redirect: Host";
>> - case ICMP_REDIRECT_TOSNET:
>> - return "Redirect: Type of Service and Network";
>> - case ICMP_REDIRECT_TOSHOST:
>> - return "Redirect: Type of Service and Host";
>> - default:
>> - crm_err("Redirect: Unknown subtype: %d", code);
>> - return "Redirect: Unknown Subtype";
>> - }
>> + case ICMP_REDIRECT:
>> + switch(code) {
>> + case ICMP_REDIRECT_NET:
>> + return "Redirect: Network";
>> + case ICMP_REDIRECT_HOST:
>> + return "Redirect: Host";
>> + case ICMP_REDIRECT_TOSNET:
>> + return "Redirect: Type of Service and Network";
>> + case ICMP_REDIRECT_TOSHOST:
>> + return "Redirect: Type of Service and Host";
>> + default:
>> + crm_err("Redirect: Unknown subtype: %d", code);
>> + return "Redirect: Unknown Subtype";
>> + }
>> +
>> + case ICMP_TIMXCEED:
>> + switch(code) {
>> + case ICMP_TIMXCEED_INTRANS:
>> + return "Timeout: TTL";
>> + case ICMP_TIMXCEED_REASS:
>> + return "Timeout: Fragmentation reassembly";
>> + default:
>> + crm_err("Timeout: Unkown subtype: %d", code);
>> + return "Timeout: Unkown Subtype";
>> + }
>> + break;
>>
>> - case ICMP_TIMXCEED:
>> - switch(code) {
>> - case ICMP_TIMXCEED_INTRANS:
>> - return "Timeout: TTL";
>> - case ICMP_TIMXCEED_REASS:
>> - return "Timeout: Fragmentation reassembly";
>> default:
>> - crm_err("Timeout: Unkown subtype: %d", code);
>> - return "Timeout: Unkown Subtype";
>> + crm_err("Unknown type: %d", type);
>> + return "Unknown type";
>> }
>> - break;
>> -
>> - default:
>> - crm_err("Unknown type: %d", type);
>> - return "Unknown type";
>> - }
>> + }
>> }
>>
>> #ifdef ON_LINUX
>> # define MAX_HOST 1024
>> -int process_icmp_error(ping_node *node, struct sockaddr_in *whereto)
>> +int process_icmp6_error(ping_node *node, struct sockaddr_in6 *whereto)
>> +{
>> + int rc = 0;
>> + char buf[512];
>> + struct iovec iov;
>> + struct msghdr msg;
>> + struct icmp6_hdr icmph;
>> + struct sockaddr_in6 target;
>> + struct cmsghdr *cmsg = NULL;
>> + struct sock_extended_err *s_err = NULL;
>> +
>> + iov.iov_base = &icmph;
>> + iov.iov_len = sizeof(icmph);
>> + msg.msg_name = (void*)⌖
>> + msg.msg_namelen = sizeof(target);
>> + msg.msg_iov = &iov;
>> + msg.msg_iovlen = 1;
>> + msg.msg_flags = 0;
>> + msg.msg_control = buf;
>> + msg.msg_controllen = sizeof(buf);
>> +
>> + rc = recvmsg(node->fd, &msg, MSG_ERRQUEUE|MSG_DONTWAIT);
>> + if (rc < 0 || rc < sizeof(icmph)) {
>> + crm_perror(LOG_DEBUG, "No error message: %d", rc);
>> + return 0;
>> + }
>> +
>> + for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
>> + if (cmsg->cmsg_level == SOL_IPV6 && cmsg->cmsg_type == IPV6_RECVERR) {
>> + s_err = (struct sock_extended_err *)CMSG_DATA(cmsg);
>> + }
>> + }
>> +
>> + CRM_ASSERT(s_err != NULL);
>> +
>> + if (s_err->ee_origin == SO_EE_ORIGIN_LOCAL) {
>> + if (s_err->ee_errno == EMSGSIZE) {
>> + crm_info("local error: Message too long, mtu=%u", s_err->ee_info);
>> + } else {
>> + crm_info("local error: %s", strerror(s_err->ee_errno));
>> + }
>> + return 0;
>> +
>> + } else if (s_err->ee_origin == SO_EE_ORIGIN_ICMP6) {
>> + struct sockaddr_in6 *sin = (struct sockaddr_in6*)(s_err+1);
>> + const char *ping_result = ping_desc(node->type, s_err->ee_type, s_err->ee_code);
>> + static char target_s[64], whereto_s[64], ping_host_s[64];
>> + inet_ntop(AF_INET6, (struct in6_addr *)&(target.sin6_addr), target_s, sizeof(target_s));
>> + inet_ntop(AF_INET6, (struct in6_addr *)&(whereto->sin6_addr), whereto_s, sizeof(whereto_s));
>> +
>> + if (ntohs(icmph.icmp6_id) != ident) {
>> + /* Result was not for us */
>> + crm_debug("Not our error (ident): %d %d", ntohs(icmph.icmp6_id), ident);
>> + return -1;
>> +
>> + } else if (memcmp(&target.sin6_addr, &whereto->sin6_addr, 16)) {
>> + /* Result was not for us */
>> + crm_debug("Not our error (addr): %s %s", target_s, whereto_s);
>> + return -1;
>> +
>> + } else if (icmph.icmp6_type != ICMP6_ECHO_REQUEST) {
>> + /* Not an error */
>> + crm_info("Not an error: %d", icmph.icmp6_type);
>> + return -1;
>> + }
>> +
>> + inet_ntop(AF_INET6, (struct in6_addr *)&(sin->sin6_addr), ping_host_s, sizeof(ping_host_s));
>> + crm_debug("From %s icmp_seq=%u %s", ping_host_s, ntohs(icmph.icmp6_seq), ping_result);
>> +
>> + } else {
>> + crm_debug("else: %d", s_err->ee_origin);
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +int process_icmp4_error(ping_node *node, struct sockaddr_in *whereto)
>> {
>> int rc = 0;
>> char buf[512];
>> @@ -289,7 +442,7 @@
>> } else if (s_err->ee_origin == SO_EE_ORIGIN_ICMP) {
>> char ping_host[MAX_HOST];
>> struct sockaddr_in *sin = (struct sockaddr_in*)(s_err+1);
>> - const char *ping_result = ping_desc(s_err->ee_type, s_err->ee_code);
>> + const char *ping_result = ping_desc(node->type, s_err->ee_type, s_err->ee_code);
>> char *target_s = inet_ntoa(*(struct in_addr *)&(target.sin_addr.s_addr));
>> char *whereto_s = inet_ntoa(*(struct in_addr *)&(whereto->sin_addr.s_addr));
>>
>> @@ -335,7 +488,13 @@
>> return 0;
>> }
>> #else
>> -int process_icmp_error(ping_node *node, struct sockaddr_in *whereto)
>> +int process_icmp6_error(ping_node *node, struct sockaddr_in6 *whereto)
>> +{
>> + /* dummy function */
>> + return 0;
>> +}
>> +
>> +int process_icmp4_error(ping_node *node, struct sockaddr_in *whereto)
>> {
>> /* dummy function */
>> return 0;
>> @@ -365,6 +524,8 @@
>> char *hostname = NULL;
>> struct addrinfo *res = NULL;
>> struct addrinfo hints;
>> + char *addr = NULL;
>> + char *cp = NULL;
>>
>> /* getaddrinfo */
>> bzero(&hints, sizeof(struct addrinfo));
>> @@ -378,7 +539,13 @@
>> hints.ai_protocol = IPPROTO_ICMP;
>> }
>>
>> - ret_ga = getaddrinfo(node->host, NULL, &hints, &res);
>> + addr = crm_strdup(node->host);
>> + if ((cp = strchr(addr, '%'))) {
>> + *cp = 0;
>> + }
>> + crm_debug("node->host[%s], addr[%s]", node->host, addr);
>> + ret_ga = getaddrinfo(addr, NULL, &hints, &res);
>> + crm_free(addr);
>> if (ret_ga) {
>> crm_warn("getaddrinfo: %s", gai_strerror(ret_ga));
>> goto bail;
>> @@ -431,19 +598,84 @@
>> #ifdef ON_LINUX
>> {
>> int dummy = 1;
>> - struct icmp_filter filt;
>> - filt.data = ~((1<<ICMP_SOURCE_QUENCH)|
>> - (1<<ICMP_DEST_UNREACH)|
>> - (1<<ICMP_TIME_EXCEEDED)|
>> - (1<<ICMP_PARAMETERPROB)|
>> - (1<<ICMP_REDIRECT)|
>> - (1<<ICMP_ECHOREPLY));
>>
>> - if (setsockopt(node->fd, SOL_RAW, ICMP_FILTER, (char*)&filt, sizeof(filt)) == -1) {
>> - crm_perror(LOG_WARNING, "setsockopt failed: Cannot install ICMP filters for %s", node->dest);
>> - }
>> + memset(&cmsgbuf, 0, sizeof(cmsgbuf));
>> + cmsglen = 0;
>>
>> - setsockopt(node->fd, SOL_IP, IP_RECVERR, (char *)&dummy, sizeof(dummy));
>> + if(node->type == AF_INET6) {
>> + struct icmp6_filter filt;
>> +
>> + ICMP6_FILTER_SETBLOCKALL(&filt);
>> + ICMP6_FILTER_SETPASS(ICMP6_ECHO_REPLY, &filt);
>> +
>> + if (setsockopt(node->fd, IPPROTO_ICMPV6, ICMP6_FILTER, (char*)&filt, sizeof(filt)) == -1) {
>> + crm_perror(LOG_WARNING, "setsockopt failed: Cannot install ICMP6 filters for %s", node->dest);
>> + }
>> + setsockopt(node->fd, SOL_IPV6, IPV6_RECVERR, (char *)&dummy, sizeof(dummy));
>> +
>> + if ((cp = strchr(node->host, '%'))) {
>> + struct ifreq ifr;
>> + struct cmsghdr *cmsg;
>> + struct in6_pktinfo *ipi;
>> +
>> + memset(&ifr, 0, sizeof(ifr));
>> + cp++;
>> + crm_debug("set interface: [%s]", cp);
>> + strncpy(ifr.ifr_name, cp, IFNAMSIZ-1);
>> +
>> + if (ioctl(node->fd, SIOCGIFINDEX, &ifr) >= 0) {
>> + cmsg = (struct cmsghdr*)cmsgbuf;
>> + cmsglen = CMSG_SPACE(sizeof(*ipi));
>> + cmsg->cmsg_len = CMSG_LEN(sizeof(*ipi));
>> + cmsg->cmsg_level = SOL_IPV6;
>> + cmsg->cmsg_type = IPV6_PKTINFO;
>> +
>> + ipi = (struct in6_pktinfo*)CMSG_DATA(cmsg);
>> + memset(ipi, 0, sizeof(*ipi));
>> + ipi->ipi6_ifindex = ifr.ifr_ifindex;
>> + } else {
>> + crm_warn("unknown interface %s specified", cp);
>> + }
>> + }
>> + } else {
>> + struct icmp_filter filt;
>> + filt.data = ~((1<<ICMP_SOURCE_QUENCH)|
>> + (1<<ICMP_DEST_UNREACH)|
>> + (1<<ICMP_TIME_EXCEEDED)|
>> + (1<<ICMP_PARAMETERPROB)|
>> + (1<<ICMP_REDIRECT)|
>> + (1<<ICMP_ECHOREPLY));
>> +
>> + if (setsockopt(node->fd, SOL_RAW, ICMP_FILTER, (char*)&filt, sizeof(filt)) == -1) {
>> + crm_perror(LOG_WARNING, "setsockopt failed: Cannot install ICMP filters for %s", node->dest);
>> + }
>> + setsockopt(node->fd, SOL_IP, IP_RECVERR, (char *)&dummy, sizeof(dummy));
>> +
>> + if ((cp = strchr(node->host, '%'))) {
>> + struct ifreq ifr;
>> + struct cmsghdr *cmsg;
>> + struct in_pktinfo *ipi;
>> +
>> + memset(&ifr, 0, sizeof(ifr));
>> + cp++;
>> + crm_debug("set interface: [%s]", cp);
>> + strncpy(ifr.ifr_name, cp, IFNAMSIZ-1);
>> +
>> + if (ioctl(node->fd, SIOCGIFINDEX, &ifr) >= 0) {
>> + cmsg = (struct cmsghdr*)cmsgbuf;
>> + cmsglen = CMSG_SPACE(sizeof(*ipi));
>> + cmsg->cmsg_len = CMSG_LEN(sizeof(*ipi));
>> + cmsg->cmsg_level = SOL_IP;
>> + cmsg->cmsg_type = IP_PKTINFO;
>> +
>> + ipi = (struct in_pktinfo*)CMSG_DATA(cmsg);
>> + memset(ipi, 0, sizeof(*ipi));
>> + ipi->ipi_ifindex = ifr.ifr_ifindex;
>> + } else {
>> + crm_warn("unknown interface %s specified", cp);
>> + }
>> + }
>> + }
>> }
>> #endif
>>
>> @@ -507,19 +739,21 @@
>> }
>> icp = (struct icmp6_hdr *)buf;
>>
>> - if (icp->icmp6_type == ICMP6_ECHO_REPLY
>> - && node->iseq == ntohs(icp->icmp6_seq)) {
>> - rc = 1; /* Alive */
>> + if (icp->icmp6_type == ICMP6_ECHO_REPLY) {
>> + if (ident == ntohs(icp->icmp6_id)
>> + && node->iseq == ntohs(icp->icmp6_seq)) {
>> + rc = 1; /* Alive */
>> + }
>>
>> } else if(icp->icmp6_type != ICMP6_ECHO_REQUEST) {
>> - rc = 0; /* Error */
>> + rc = process_icmp6_error(node, (struct sockaddr_in6*)&(node->addr));
>> }
>>
>> - do_crm_log(rc==0?LOG_WARNING:LOG_DEBUG,
>> + do_crm_log(LOG_DEBUG_2,
>> "Echo from %s (exp=%d, seq=%d, id=%d, dest=%s, data=%s): %s",
>> from_host, node->iseq, ntohs(icp->icmp6_seq),
>> ntohs(icp->icmp6_id), node->dest, (char*)(buf + ICMP6ECHOLEN),
>> - ping_desc(icp->icmp6_type, icp->icmp6_code));
>> + ping_desc(node->type, icp->icmp6_type, icp->icmp6_code));
>>
>> return rc;
>> }
>> @@ -558,12 +792,14 @@
>> /* Check the IP header */
>> icp = (struct icmp*)(buf + iplen);
>>
>> - if (icp->icmp_type == ICMP_ECHOREPLY
>> - && node->iseq == ntohs(icp->icmp_seq)) {
>> - rc = 1; /* Alive */
>> + if (icp->icmp_type == ICMP_ECHOREPLY) {
>> + if (ident == ntohs(icp->icmp_id)
>> + && node->iseq == ntohs(icp->icmp_seq)) {
>> + rc = 1; /* Alive */
>> + }
>>
>> } else if(icp->icmp_type != ICMP_ECHO) {
>> - rc = process_icmp_error(node, (struct sockaddr_in*)from);
>> + rc = process_icmp4_error(node, (struct sockaddr_in*)from);
>> }
>>
>> /* TODO: Stop logging icmp_id once we're sure everything works */
>> @@ -571,7 +807,7 @@
>> "Echo from %s (exp=%d, seq=%d, id=%d, dest=%s, data=%s): %s",
>> from_host, node->iseq, ntohs(icp->icmp_seq),
>> ntohs(icp->icmp_id), node->dest, icp->icmp_data,
>> - ping_desc(icp->icmp_type, icp->icmp_code));
>> + ping_desc(node->type, icp->icmp_type, icp->icmp_code));
>>
>> return rc;
>> }
>> @@ -585,9 +821,14 @@
>> struct cmsghdr *cm;
>> u_char buf[1024];
>> struct iovec iov[2];
>> + int saved_errno = 0;
>>
>> + struct timeval recv_start_time;
>> + struct timeval recv_time;
>> int packlen;
>> u_char *packet;
>> +
>> + gettimeofday(&recv_start_time, NULL);
>> packlen = DEFDATALEN + IP6LEN + ICMP6ECHOLEN + EXTRA;
>>
>> crm_malloc0(packet, packlen);
>> @@ -606,12 +847,23 @@
>>
>>
>> bytes = recvmsg(node->fd, &m, 0);
>> + saved_errno = errno;
>> crm_debug_2("Got %d bytes", bytes);
>>
>> if(bytes < 0) {
>> crm_perror(LOG_DEBUG, "Read failed");
>> - if (errno != EAGAIN && errno != EINTR) {
>> - process_icmp_error(node, (struct sockaddr_in*)&fromaddr);
>> + if (saved_errno != EAGAIN && saved_errno != EINTR) {
>> + int rc = 0;
>> + if(node->type == AF_INET6) {
>> + rc = process_icmp6_error(node, (struct sockaddr_in6*)&(node->addr));
>> + } else {
>> + rc = process_icmp4_error(node, (struct sockaddr_in*)&fromaddr);
>> + }
>> +
>> + if(rc < 0) {
>> + crm_info("Retrying...");
>> + goto retry;
>> + }
>> }
>>
>> } else if (bytes > 0) {
>> @@ -622,6 +874,13 @@
>> rc = dump_v4_echo(node, packet, bytes, &m);
>> }
>>
>> + gettimeofday(&recv_time, NULL);
>> + if ((recv_start_time.tv_sec + ping_timeout) < recv_time.tv_sec) {
>> + crm_warn("failed to receive for timeout.");
>> + crm_free(packet);
>> + return FALSE;
>> + }
>> +
>> if(rc < 0) {
>> crm_info("Retrying...");
>> goto retry;
>> @@ -704,6 +963,8 @@
>> iov.iov_len = bytes;
>> smsghdr.msg_iov = &iov;
>> smsghdr.msg_iovlen = 1;
>> + smsghdr.msg_control = cmsgbuf;
>> + smsghdr.msg_controllen = cmsglen;
>>
>> rc = sendmsg(node->fd, &smsghdr, 0);
>>
>> @@ -1024,7 +1285,7 @@
>> crm_err("non-option ARGV-elements: ");
>> printf("non-option ARGV-elements: ");
>> while (optind < argc) {
>> - crm_err("%s ", argv[optind++]);
>> + crm_err("%s ", argv[optind]);
>> printf("%s ", argv[optind++]);
>> }
>> printf("\n");
>>
>> _______________________________________________
>> Pacemaker mailing list
>> Pacemaker at oss.clusterlabs.org
>> http://oss.clusterlabs.org/mailman/listinfo/pacemaker
>>
>>
>
> _______________________________________________
> Pacemaker mailing list
> Pacemaker at oss.clusterlabs.org
> http://oss.clusterlabs.org/mailman/listinfo/pacemaker
More information about the Pacemaker
mailing list