On Fri, Jul 23, 2010 at 09:19:44AM +0900, Keisuke MORI wrote:
> The attached patch is to remove libnet dependency from IPv6addr RA
> by replacing the same functionality using the standard socket API.
> 
> Currently there are following problems with resource-agents package:
> 
>  - IPv6addr RA requires an extra libnet package on the run-time environment.
>   That is pretty inconvenient particularly for RHEL users because
>   it's not included in the standard distribution.
> 
>  - The pre-built RPMs from ClusterLabs does not include IPv6addr RA.
>   This was once reported in the pacemaker list:
>   http://www.gossamer-threads.com/lists/linuxha/pacemaker/64295#64295
> 
> The patch will resolve those issues.
> I believe that none of Pacemaker/Heartbeat related packages would be
> depending on libnet library any more after patched.

Hi Mori-san,

I will add that libnet seems to be more or less unmaintained.

You seem to make using libnet optional, is there a reason
not to just remove it? portability?

> # HG changeset patch
> # User Keisuke MORI <kskm...@intellilink.co.jp>
> # Date 1279802861 -32400
> # Branch ipv6
> # Node ID 40d5dbdca9cc089b6514c7525cd2dbd678299711
> # Parent  b3142fd9cc672f2217e632608bc986b46265b193
> IPv6addr: remove libnet dependency
> 
> diff -r b3142fd9cc67 -r 40d5dbdca9cc configure.in
> --- a/configure.in    Fri Jul 16 09:46:38 2010 +0200
> +++ b/configure.in    Thu Jul 22 21:47:41 2010 +0900
> @@ -607,6 +607,7 @@
>        [new_libnet=yes; AC_DEFINE(HAVE_LIBNET_1_1_API, 1, Libnet 1.1 API)],
>        [new_libnet=no; AC_DEFINE(HAVE_LIBNET_1_0_API, 1, Libnet 1.0 
> API)],$LIBNETLIBS)
>     AC_SUBST(LIBNETLIBS)
> +   AC_DEFINE(HAVE_LIBNET_API, 1, Libnet API)
>  fi
>  
>  if test "$new_libnet" = yes; then
> @@ -634,7 +635,7 @@
>  dnl ************************************************************************
>  dnl * Check for netinet/icmp6.h to enable the IPv6addr resource agent
>  AC_CHECK_HEADERS(netinet/icmp6.h,[],[],[#include <sys/types.h>])
> -AM_CONDITIONAL(USE_IPV6ADDR, test "$ac_cv_header_netinet_icmp6_h" = yes -a 
> "$new_libnet" = yes )
> +AM_CONDITIONAL(USE_IPV6ADDR, test "$ac_cv_header_netinet_icmp6_h" = yes )
>  
>  dnl ========================================================================
>  dnl Compiler flags
> diff -r b3142fd9cc67 -r 40d5dbdca9cc heartbeat/IPv6addr.c
> --- a/heartbeat/IPv6addr.c    Fri Jul 16 09:46:38 2010 +0200
> +++ b/heartbeat/IPv6addr.c    Thu Jul 22 21:47:41 2010 +0900
> @@ -87,13 +87,25 @@
>  
>  #include <config.h>
>  
> +#include <stdio.h>
>  #include <stdlib.h>
> +#include <unistd.h>
>  #include <sys/types.h>
> +#include <sys/socket.h>
>  #include <netinet/icmp6.h>
> +#include <arpa/inet.h> /* for inet_pton */
> +#include <net/if.h> /* for if_nametoindex */
> +#include <sys/ioctl.h>
> +#include <sys/stat.h>
> +#include <fcntl.h>
>  #include <libgen.h>
>  #include <syslog.h>
> +#include <signal.h>
> +#include <errno.h>
>  #include <clplumbing/cl_log.h>
> +#ifdef HAVE_LIBNET_API
>  #include <libnet.h>
> +#endif
>  
>  
>  #define PIDFILE_BASE HA_RSCTMPDIR  "/IPv6addr-"
> @@ -400,8 +412,11 @@
>       return OCF_NOT_RUNNING;
>  }
>  
> +#ifdef HAVE_LIBNET_API
>  /* Send an unsolicited advertisement packet
>   * Please refer to rfc2461
> + *
> + * Libnet based implementation.
>   */
>  int
>  send_ua(struct in6_addr* src_ip, char* if_name)
> @@ -466,6 +481,108 @@
>       libnet_destroy(l);
>       return status;
>  }
> +#else /* HAVE_LIBNET_API */
> +/* Send an unsolicited advertisement packet
> + * Please refer to rfc4861 / rfc3542
> + *
> + * Libnet independent implementation.
> + */
> +int
> +send_ua(struct in6_addr* src_ip, char* if_name)
> +{
> +     int status = -1;
> +     int fd;
> +
> +     int ifindex;
> +     int hop;
> +     struct ifreq ifr;
> +#define HWADDR_LEN 6 /* mac address length */

Personally I'd prefer the define outside of the function.

> +     u_int8_t payload[sizeof(struct nd_neighbor_advert)
> +                      + sizeof(struct nd_opt_hdr) + HWADDR_LEN];
> +     struct nd_neighbor_advert *na;
> +     struct nd_opt_hdr *opt;
> +     struct sockaddr_in6 src_sin6;
> +     struct sockaddr_in6 dst_sin6;
> +
> +     if ((fd = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) == 0) {
> +             cl_log(LOG_ERR, "socket(IPPROTO_ICMPV6) failed: %s",
> +                    strerror(errno));
> +             goto err;
> +     }
> +     /* set the outgoing interface */
> +     ifindex = if_nametoindex(if_name);
> +     if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_IF,
> +                    &ifindex, sizeof(ifindex)) < 0) {
> +             cl_log(LOG_ERR, "setsockopt(IPV6_MULTICAST_IF) failed: %s",
> +                    strerror(errno));
> +             goto err;
> +     }
> +     /* set the hop limit */
> +     hop = 255; /* 255 is required. see rfc4861 7.1.2 */
> +     if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
> +                    &hop, sizeof(hop)) < 0) {
> +             cl_log(LOG_ERR, "setsockopt(IPV6_MULTICAST_HOPS) failed: %s",
> +                    strerror(errno));
> +             goto err;
> +     }
> +     
> +     /* set the source address */
> +     memset(&src_sin6, 0, sizeof(src_sin6));
> +     src_sin6.sin6_family = AF_INET6;
> +     src_sin6.sin6_addr = *src_ip;
> +     src_sin6.sin6_port = 0;
> +     if (bind(fd, (struct sockaddr *)&src_sin6, sizeof(src_sin6)) < 0) {
> +             cl_log(LOG_ERR, "bind() failed: %s", strerror(errno));
> +             goto err;
> +     }
> +
> +
> +     /* get the hardware address */
> +     memset(&ifr, 0, sizeof(ifr));
> +     strncpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name) - 1);
> +     if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) {
> +             cl_log(LOG_ERR, "ioctl(SIOCGIFHWADDR) failed: %s", 
> strerror(errno));
> +             goto err;
> +     }
> +
> +     /* build a neighbor advertisement message */
> +     memset(&payload, 0, sizeof(payload));
> +
> +     na = (struct nd_neighbor_advert *)&payload;
> +     na->nd_na_type = ND_NEIGHBOR_ADVERT;
> +     na->nd_na_code = 0;
> +     na->nd_na_cksum = 0; /* calculated by kernel */
> +     na->nd_na_flags_reserved = ND_NA_FLAG_OVERRIDE;
> +     na->nd_na_target = (*src_ip);

There is no need to enclose *src_ip in brackets.

> +
> +     /* options field; set the target link-layer address */
> +     opt = (struct nd_opt_hdr *)&payload[sizeof(struct nd_neighbor_advert)];
> +     opt->nd_opt_type = ND_OPT_TARGET_LINKADDR;
> +     opt->nd_opt_len = 1; /* The length of the option in units of 8 octets */
> +     memcpy(&payload[sizeof(struct nd_neighbor_advert)
> +                     + sizeof(struct nd_opt_hdr)],
> +            &ifr.ifr_hwaddr.sa_data, HWADDR_LEN);
> +
> +     /* sending an unsolicited neighbor advertisement to all */
> +     memset(&dst_sin6, 0, sizeof(dst_sin6));
> +     dst_sin6.sin6_family = AF_INET6;
> +     inet_pton(AF_INET6, BCAST_ADDR, &dst_sin6.sin6_addr); /* should not 
> fail */
> +
> +     if (sendto(fd, &payload, sizeof(payload), 0,
> +                (struct sockaddr *)&dst_sin6, sizeof(dst_sin6))
> +         != sizeof(payload)) {
> +             cl_log(LOG_ERR, "sendto(%s) failed: %s",
> +                    if_name, strerror(errno));
> +             goto err;
> +     }

Is it valid to assume that there will never be a partial write?

> +     status = 0;
> +
> +err:
> +     close(fd);
> +     return status;
> +}
> +#endif /* HAVE_LIBNET_API */
>  
>  /* find the network interface associated with an address */
>  char*
> @@ -643,7 +760,7 @@
>  is_addr6_available(struct in6_addr* addr6)
>  {
>       struct sockaddr_in6             addr;
> -     struct libnet_icmpv6_hdr        icmph;
> +     struct icmp6_hdr                icmph;
>       u_char                          outpack[MINPACKSIZE];
>       int                             icmp_sock;
>       int                             ret;
> @@ -653,11 +770,11 @@
>  
>       icmp_sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
>       memset(&icmph, 0, sizeof(icmph));
> -     icmph.icmp_type = ICMP6_ECHO;
> -     icmph.icmp_code = 0;
> -     icmph.icmp_sum = 0;
> -     icmph.seq = htons(0);
> -     icmph.id = 0;
> +     icmph.icmp6_type = ICMP6_ECHO_REQUEST;
> +     icmph.icmp6_code = 0;
> +     icmph.icmp6_cksum = 0;
> +     icmph.icmp6_seq = htons(0);
> +     icmph.icmp6_id = 0;
>  
>       memset(&outpack, 0, sizeof(outpack));
>       memcpy(&outpack, &icmph, sizeof(icmph));

> _______________________________________________________
> Linux-HA-Dev: Linux-HA-Dev@lists.linux-ha.org
> http://lists.linux-ha.org/mailman/listinfo/linux-ha-dev
> Home Page: http://linux-ha.org/

_______________________________________________________
Linux-HA-Dev: Linux-HA-Dev@lists.linux-ha.org
http://lists.linux-ha.org/mailman/listinfo/linux-ha-dev
Home Page: http://linux-ha.org/

Reply via email to