[Pacemaker] [PATCH] pingd: set ICMP6 filter

Andrew Beekhof andrew at beekhof.net
Wed Oct 28 16:56:23 EDT 2009


Applied:
  http://hg.clusterlabs.org/pacemaker/stable-1.0/rev/afccc27a7249

Sorry for the delay!

On Thu, Oct 15, 2009 at 12:19 PM, Kazunori INOUE
<inouekazu at intellilink.co.jp> wrote:
> 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
>
> _______________________________________________
> Pacemaker mailing list
> Pacemaker at oss.clusterlabs.org
> http://oss.clusterlabs.org/mailman/listinfo/pacemaker
>




More information about the Pacemaker mailing list