public inbox for b.a.t.m.a.n@lists.open-mesh.org
 help / color / mirror / Atom feed
From: Jonathan Haws <Jonathan.Haws@sdl.usu.edu>
To: "b.a.t.m.a.n@lists.open-mesh.org" <b.a.t.m.a.n@lists.open-mesh.org>
Subject: Re: [B.A.T.M.A.N.] [PATCH] IPv4 multicast distribution support.
Date: Mon, 16 Jan 2017 19:52:41 +0000	[thread overview]
Message-ID: <1484596361.15751.2.camel@sdl.usu.edu> (raw)
In-Reply-To: <1484596174-16341-1-git-send-email-jhaws@sdl.usu.edu>

I realize that the code in this patch is not formatted properly, but I
was unable to get checkpatch.pl to scan this right - it needs a full
kernel tree.  Is there another formatting script I can run?

I wanted to submit this anyway (even with the formatting problems) to
get people looking at it.  I had need of this because I'm running
batman-adv and alfred in a setting where certain devices do not (and
will not) support IPv6.  What I've got here seems like a clean method
of providing IPv4 support; however IPv6 and IPv4 cannot be mixed.

What are everyone's thoughts?  Is this a good approach or would you
prefer it changed?

Thanks!

-- 
Jonathan R. Haws
Embedded Engineer
Space Dynamics Laboratory
jhaws@sdl.usu.edu



On Mon, 2017-01-16 at 12:49 -0700, Jonathan Haws wrote:
> Enabled via -4 expert option where multicast group address is
> specified.
> This option will disable IPv6 communication and is intended for use
> in networks
> which do not support IPv6 addressing.
> 
> When this option is enabled, all IPv6 communication is disabled.
> Combining
> IPv4 and IPv6 alfred nodes is unsupported.
> 
> Signed-off-by: Jonathan Haws <jhaws@sdl.usu.edu>
> ---
>  README         |   4 +-
>  alfred.h       |  21 +++++---
>  batadv_query.c |  53 ++++++++++++-------
>  batadv_query.h |   5 +-
>  client.c       |   2 +-
>  main.c         |  10 +++-
>  man/alfred.8   |   5 ++
>  netsock.c      | 160
> +++++++++++++++++++++++++++++++++++++++++++++++++++++----
>  recv.c         |  67 +++++++++++++++++-------
>  send.c         |  51 ++++++++++++------
>  server.c       |   8 +--
>  unix_sock.c    |   2 +-
>  12 files changed, 308 insertions(+), 80 deletions(-)
> 
> diff --git a/README b/README
> index bc1c3bc..28f3dc9 100644
> --- a/README
> +++ b/README
> @@ -20,7 +20,9 @@ programs to communicate with alfred (done via unix
> sockets). alfred then takes
>  care of distributing the local information to other alfred servers
> on other
>  nodes. This is done via IPv6 link-local multicast, and does not
> require any
>  configuration. A user can request data from alfred, and will receive
> the
> -information available from all alfred servers in the network.
> +information available from all alfred servers in the network.
> Alternatively,
> +alfred can be configured to distribute the local information via
> IPv4 multicast.
> +This is configured by setting the IPv4 multicast group address in
> the -4 option.
>  
>  Compilation
>  -----------
> diff --git a/alfred.h b/alfred.h
> index 2e8db1e..5237594 100644
> --- a/alfred.h
> +++ b/alfred.h
> @@ -48,6 +48,12 @@ enum data_source {
>  	SOURCE_SYNCED = 2,
>  };
>  
> +typedef union
> +{
> +  struct in_addr ipv4;
> +  struct in6_addr ipv6;
> +} alfred_addr;
> +
>  struct dataset {
>  	struct alfred_data data;
>  	unsigned char *buf;
> @@ -80,7 +86,7 @@ struct transaction_head {
>  
>  struct server {
>  	struct ether_addr hwaddr;
> -	struct in6_addr address;
> +	alfred_addr address;
>  	struct timespec last_seen;
>  	uint8_t tq;
>  };
> @@ -100,7 +106,7 @@ enum clientmode {
>  
>  struct interface {
>  	struct ether_addr hwaddr;
> -	struct in6_addr address;
> +	alfred_addr address;
>  	uint32_t scope_id;
>  	char *interface;
>  	int netsock;
> @@ -122,6 +128,7 @@ struct globals {
>  	int clientmode_arg;
>  	int clientmode_version;
>  	int verbose;
> +	int ipv4mode;
>  
>  	int unix_sock;
>  	const char *unix_path;
> @@ -142,7 +149,7 @@ struct globals {
>  
>  #define MAX_PAYLOAD ((1 << 16) - 1 - sizeof(struct udphdr))
>  
> -extern const struct in6_addr in6addr_localmcast;
> +extern alfred_addr alfred_mcast;
>  
>  /* server.c */
>  int alfred_server(struct globals *globals);
> @@ -169,13 +176,13 @@ static inline bool transaction_finished(struct
> transaction_head *head)
>  
>  /* send.c */
>  int push_data(struct globals *globals, struct interface *interface,
> -	      struct in6_addr *destination, enum data_source
> max_source_level,
> +	      alfred_addr *destination, enum data_source
> max_source_level,
>  	      int type_filter, uint16_t tx_id);
>  int announce_master(struct globals *globals);
>  int push_local_data(struct globals *globals);
>  int sync_data(struct globals *globals);
> -ssize_t send_alfred_packet(struct interface *interface,
> -			   const struct in6_addr *dest, void *buf,
> int length);
> +ssize_t send_alfred_packet(struct globals *globals, struct interface
> *interface,
> +			   const alfred_addr *dest, void *buf, int
> length);
>  /* unix_sock.c */
>  int unix_sock_read(struct globals *globals);
>  int unix_sock_open_daemon(struct globals *globals);
> @@ -195,7 +202,7 @@ int netsock_prepare_select(struct globals
> *globals, fd_set *fds, int maxsock);
>  void netsock_check_error(struct globals *globals, fd_set *errfds);
>  int netsock_receive_packet(struct globals *globals, fd_set *fds);
>  int netsock_own_address(const struct globals *globals,
> -			const struct in6_addr *address);
> +			const alfred_addr *address);
>  /* util.c */
>  int time_diff(struct timespec *tv1, struct timespec *tv2,
>  	      struct timespec *tvdiff);
> diff --git a/batadv_query.c b/batadv_query.c
> index ac45b9b..ae91d2e 100644
> --- a/batadv_query.c
> +++ b/batadv_query.c
> @@ -80,22 +80,22 @@ out:
>  	return ret;
>  }
>  
> -int mac_to_ipv6(const struct ether_addr *mac, struct in6_addr *addr)
> +int mac_to_ipv6(const struct ether_addr *mac, alfred_addr *addr)
>  {
>  	memset(addr, 0, sizeof(*addr));
> -	addr->s6_addr[0] = 0xfe;
> -	addr->s6_addr[1] = 0x80;
> +	addr->ipv6.s6_addr[0] = 0xfe;
> +	addr->ipv6.s6_addr[1] = 0x80;
>  
> -	addr->s6_addr[8] = mac->ether_addr_octet[0] ^ 0x02;
> -	addr->s6_addr[9] = mac->ether_addr_octet[1];
> -	addr->s6_addr[10] = mac->ether_addr_octet[2];
> +	addr->ipv6.s6_addr[8] = mac->ether_addr_octet[0] ^ 0x02;
> +	addr->ipv6.s6_addr[9] = mac->ether_addr_octet[1];
> +	addr->ipv6.s6_addr[10] = mac->ether_addr_octet[2];
>  
> -	addr->s6_addr[11] = 0xff;
> -	addr->s6_addr[12] = 0xfe;
> +	addr->ipv6.s6_addr[11] = 0xff;
> +	addr->ipv6.s6_addr[12] = 0xfe;
>  
> -	addr->s6_addr[13] = mac->ether_addr_octet[3];
> -	addr->s6_addr[14] = mac->ether_addr_octet[4];
> -	addr->s6_addr[15] = mac->ether_addr_octet[5];
> +	addr->ipv6.s6_addr[13] = mac->ether_addr_octet[3];
> +	addr->ipv6.s6_addr[14] = mac->ether_addr_octet[4];
> +	addr->ipv6.s6_addr[15] = mac->ether_addr_octet[5];
>  
>  	return 0;
>  }
> @@ -118,17 +118,17 @@ int is_ipv6_eui64(const struct in6_addr *addr)
>  	return 1;
>  }
>  
> -int ipv6_to_mac(const struct in6_addr *addr, struct ether_addr *mac)
> +int ipv6_to_mac(const alfred_addr *addr, struct ether_addr *mac)
>  {
> -	if (!is_ipv6_eui64(addr))
> +	if (!is_ipv6_eui64(&addr->ipv6))
>  		return -EINVAL;
>  
> -	mac->ether_addr_octet[0] = addr->s6_addr[8] ^ 0x02;
> -	mac->ether_addr_octet[1] = addr->s6_addr[9];
> -	mac->ether_addr_octet[2] = addr->s6_addr[10];
> -	mac->ether_addr_octet[3] = addr->s6_addr[13];
> -	mac->ether_addr_octet[4] = addr->s6_addr[14];
> -	mac->ether_addr_octet[5] = addr->s6_addr[15];
> +	mac->ether_addr_octet[0] = addr->ipv6.s6_addr[8] ^ 0x02;
> +	mac->ether_addr_octet[1] = addr->ipv6.s6_addr[9];
> +	mac->ether_addr_octet[2] = addr->ipv6.s6_addr[10];
> +	mac->ether_addr_octet[3] = addr->ipv6.s6_addr[13];
> +	mac->ether_addr_octet[4] = addr->ipv6.s6_addr[14];
> +	mac->ether_addr_octet[5] = addr->ipv6.s6_addr[15];
>  
>  	if (!is_valid_ether_addr(mac->ether_addr_octet))
>  		return -EINVAL;
> @@ -136,6 +136,21 @@ int ipv6_to_mac(const struct in6_addr *addr,
> struct ether_addr *mac)
>  	return 0;
>  }
>  
> +int ipv4_to_mac(const alfred_addr *addr, struct ether_addr *mac)
> +{
> +  mac->ether_addr_octet[0] = 0;
> +  mac->ether_addr_octet[1] = 0;
> +  mac->ether_addr_octet[2] = (addr->ipv4.s_addr >> 24) & 0xFF;
> +  mac->ether_addr_octet[3] = (addr->ipv4.s_addr >> 16) & 0xFF;
> +  mac->ether_addr_octet[4] = (addr->ipv4.s_addr >>  8) & 0xFF;
> +  mac->ether_addr_octet[5] = (addr->ipv4.s_addr >>  0) & 0xFF;
> +
> +  if (!is_valid_ether_addr(mac->ether_addr_octet))
> +    return -EINVAL;
> +
> +  return 0;
> +}
> +
>  static int batadv_interface_check_debugfs(const char *mesh_iface)
>  {
>  	char full_path[MAX_PATH + 1];
> diff --git a/batadv_query.h b/batadv_query.h
> index 0df8a35..ec69290 100644
> --- a/batadv_query.h
> +++ b/batadv_query.h
> @@ -28,8 +28,9 @@ struct ether_addr *translate_mac(const char
> *mesh_iface,
>  				 const struct ether_addr *mac);
>  uint8_t get_tq(const char *mesh_iface, struct ether_addr *mac);
>  int batadv_interface_check(const char *mesh_iface);
> -int mac_to_ipv6(const struct ether_addr *mac, struct in6_addr
> *addr);
> -int ipv6_to_mac(const struct in6_addr *addr, struct ether_addr
> *mac);
> +int mac_to_ipv6(const struct ether_addr *mac, alfred_addr *addr);
> +int ipv6_to_mac(const alfred_addr *addr, struct ether_addr *mac);
> +int ipv4_to_mac(const alfred_addr *addr, struct ether_addr *mac);
>  int is_ipv6_eui64(const struct in6_addr *addr);
>  
>  #endif
> diff --git a/client.c b/client.c
> index 357fdb9..4102046 100644
> --- a/client.c
> +++ b/client.c
> @@ -239,7 +239,7 @@ static int check_interface(const char *iface)
>  		return -1;
>  	}
>  
> -	sock = socket(PF_INET6, SOCK_DGRAM, 0);
> +	sock = socket(PF_INET, SOCK_DGRAM, 0);
>  	if (sock < 0) {
>  		perror("can't open socket");
>  		return -1;
> diff --git a/main.c b/main.c
> index 0d30ea4..c222f91 100644
> --- a/main.c
> +++ b/main.c
> @@ -19,6 +19,7 @@
>   *
>   */
>  
> +#include <arpa/inet.h>
>  #include <getopt.h>
>  #include <signal.h>
>  #include <stdio.h>
> @@ -61,6 +62,7 @@ static void alfred_usage(void)
>  	printf("                                      other
> masters\n");
>  	printf("  -p, --sync-period [period]          set
> synchronization period, in seconds\n");
>  	printf("                                      fractional
> seconds are supported (i.e. 0.2 = 5 Hz)\n");
> +	printf("  -4                                  specify IPv4
> multicast address and operate in IPv4 mode");
>  	printf("\n");
>  	printf("  -u, --unix-path [path]              path to unix
> socket used for client-server\n");
>  	printf("                                      communication
> (default: \""ALFRED_SOCK_PATH_DEFAULT"\")\n");
> @@ -196,6 +198,7 @@ static struct globals *alfred_init(int argc, char
> *argv[])
>  	globals->mesh_iface = "bat0";
>  	globals->unix_path = ALFRED_SOCK_PATH_DEFAULT;
>  	globals->verbose = 0;
> +  globals->ipv4mode = 0;
>  	globals->update_command = NULL;
>  	globals->sync_period.tv_sec = ALFRED_INTERVAL;
>  	globals->sync_period.tv_nsec = 0;
> @@ -204,7 +207,7 @@ static struct globals *alfred_init(int argc, char
> *argv[])
>  
>  	time_random_seed();
>  
> -	while ((opt = getopt_long(argc, argv,
> "ms:r:hi:b:vV:M:I:u:dc:p:", long_options,
> +	while ((opt = getopt_long(argc, argv,
> "ms:r:hi:b:vV:M:I:u:dc:p:4:", long_options,
>  				  &opt_ind)) != -1) {
>  		switch (opt) {
>  		case 'r':
> @@ -277,6 +280,11 @@ static struct globals *alfred_init(int argc,
> char *argv[])
>  			globals->sync_period.tv_nsec = (double)
> (sync_period - (int) sync_period) * 1e9;
>  			printf(" ** Setting sync interval to: %.9f
> seconds (%ld.%09ld)\n", sync_period, globals->sync_period.tv_sec,
> globals->sync_period.tv_nsec);
>  			break;
> +		case '4':
> +		  globals->ipv4mode = 1;
> +		  inet_pton(AF_INET, optarg, &alfred_mcast.ipv4);
> +		  printf(" ** IPv4 Multicast Mode: %x\n",
> alfred_mcast.ipv4.s_addr);
> +		  break;
>  		case 'h':
>  		default:
>  			alfred_usage();
> diff --git a/man/alfred.8 b/man/alfred.8
> index 5936e64..c4f0b96 100644
> --- a/man/alfred.8
> +++ b/man/alfred.8
> @@ -123,6 +123,11 @@ as arguments.
>  Specify alfred synchronization period, in seconds. If not specified,
> the default
>  ALFRED_INTERVAL setting of 10 seconds will be used. Fractional
> seconds are
>  supported.
> +.TP
> +\fB\-4\fP
> +Specify the IPv4 multicast group address and enable IPv4 data-
> sharing (disabling
> +IPv6 communication). This option is required on systems that do not
> support IPv6
> +addressing.
>  .
>  .SH EXAMPLES
>  Start an alfred server listening on bridge br0 (assuming that this
> bridge
> diff --git a/netsock.c b/netsock.c
> index 86db8a6..2e2d041 100644
> --- a/netsock.c
> +++ b/netsock.c
> @@ -43,10 +43,12 @@
>  #include "list.h"
>  #include "hash.h"
>  
> -const struct in6_addr in6addr_localmcast = {{{ 0xff, 0x02, 0x00,
> 0x00,
> -					       0x00, 0x00, 0x00,
> 0x00,
> -					       0x00, 0x00, 0x00,
> 0x00,
> -					       0x00, 0x00, 0x00,
> 0x01 } } };
> +alfred_addr alfred_mcast = {
> +    .ipv6={{{ 0xff, 0x02, 0x00, 0x00,
> +              0x00, 0x00, 0x00, 0x00,
> +              0x00, 0x00, 0x00, 0x00,
> +              0x00, 0x00, 0x00, 0x01 } } }
> +};
>  
>  static int server_compare(void *d1, void *d2)
>  {
> @@ -262,7 +264,7 @@ static int netsock_open(struct interface
> *interface)
>  	memset(&sin6_mc, 0, sizeof(sin6_mc));
>  	sin6_mc.sin6_port = htons(ALFRED_PORT);
>  	sin6_mc.sin6_family = AF_INET6;
> -	memcpy(&sin6_mc.sin6_addr, &in6addr_localmcast,
> +	memcpy(&sin6_mc.sin6_addr, &alfred_mcast,
>  	       sizeof(sin6_mc.sin6_addr));
>  	sin6_mc.sin6_scope_id = interface->scope_id;
>  
> @@ -291,7 +293,7 @@ static int netsock_open(struct interface
> *interface)
>  		goto err;
>  	}
>  
> -	memcpy(&mreq.ipv6mr_multiaddr, &in6addr_localmcast,
> +	memcpy(&mreq.ipv6mr_multiaddr, &alfred_mcast,
>  	       sizeof(mreq.ipv6mr_multiaddr));
>  	mreq.ipv6mr_interface = interface->scope_id;
>  
> @@ -335,6 +337,137 @@ err:
>  	return -1;
>  }
>  
> +static int netsock_open4(struct interface *interface)
> +{
> +  int sock;
> +  int sock_mc;
> +  struct sockaddr_in sin4, sin_mc;
> +  struct ip_mreq mreq;
> +  struct ifreq ifr;
> +  int ret;
> +
> +  interface->netsock = -1;
> +  interface->netsock_mcast = -1;
> +
> +  sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
> +  if (sock  < 0) {
> +    perror("ipv4: can't open socket");
> +    return -1;
> +  }
> +
> +  sock_mc = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
> +  if (sock_mc  < 0) {
> +    perror("ipv4: can't open mc socket");
> +    return -1;
> +  }
> +
> +  memset(&ifr, 0, sizeof(ifr));
> +  strncpy(ifr.ifr_name, interface->interface, IFNAMSIZ);
> +  ifr.ifr_name[IFNAMSIZ - 1] = '\0';
> +  if (ioctl(sock_mc, SIOCGIFHWADDR, &ifr) == -1) {
> +    perror("ipv4: can't get MAC address");
> +    goto err;
> +  }
> +  memcpy(&interface->hwaddr, &ifr.ifr_hwaddr.sa_data, 6);
> +
> +  memset(&sin4, 0, sizeof(sin4));
> +  sin4.sin_port = htons(ALFRED_PORT);
> +  sin4.sin_family = AF_INET;
> +  sin4.sin_addr.s_addr = INADDR_ANY;
> +
> +  memset(&sin_mc, 0, sizeof(sin_mc));
> +  sin_mc.sin_port = htons(ALFRED_PORT);
> +  sin_mc.sin_family = AF_INET;
> +  memcpy(&sin_mc.sin_addr, &alfred_mcast, sizeof(sin_mc.sin_addr));
> +
> +  enable_raw_bind_capability(1);
> +  if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, interface-
> >interface,
> +           strlen(interface->interface) + 1)) {
> +    perror("ipv4: can't bind to device");
> +    goto err;
> +  }
> +
> +  if (setsockopt(sock_mc, SOL_SOCKET, SO_BINDTODEVICE,
> +           interface->interface,
> +           strlen(interface->interface) + 1)) {
> +    perror("ipv4: can't bind to device");
> +    goto err;
> +  }
> +  enable_raw_bind_capability(0);
> +
> +  ret = 1;
> +  if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &ret, sizeof(ret))
> < 0)
> +  {
> +    perror("ipv4: can't set reuse flag");
> +    goto err;
> +  }
> +  if (setsockopt(sock_mc, SOL_SOCKET, SO_REUSEADDR, &ret,
> sizeof(ret)) < 0)
> +  {
> +    perror("ipv4: can't set mc reuse flag");
> +    goto err;
> +  }
> +
> +  if (bind(sock, (struct sockaddr *)&sin4, sizeof(sin4)) < 0) {
> +    perror("ipv4: can't bind");
> +    goto err;
> +  }
> +
> +  if (bind(sock_mc, (struct sockaddr *)&sin_mc, sizeof(sin_mc)) < 0)
> {
> +    perror("ipv4: can't bind mc");
> +    goto err;
> +  }
> +
> +  memcpy(&mreq.imr_multiaddr, &alfred_mcast.ipv4,
> sizeof(mreq.imr_multiaddr));
> +
> +  if (ioctl(sock_mc, SIOCGIFADDR, &ifr) < 0)
> +  {
> +    perror("ipv4: can't get IP address");
> +    goto err;
> +  }
> +  mreq.imr_interface = ((struct sockaddr_in *) &ifr.ifr_addr)-
> >sin_addr;
> +  memcpy(&interface->address.ipv4,
> +      &((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr,
> +      sizeof(struct in_addr));
> +
> +  if (setsockopt(sock_mc, IPPROTO_IP, IP_ADD_MEMBERSHIP,
> +           &mreq, sizeof(mreq))) {
> +    perror("ipv4: can't add multicast membership");
> +    goto err;
> +  }
> +
> +  ret = fcntl(sock, F_GETFL, 0);
> +  if (ret < 0) {
> +    perror("failed to get file status flags");
> +    goto err;
> +  }
> +
> +  ret = fcntl(sock, F_SETFL, ret | O_NONBLOCK);
> +  if (ret < 0) {
> +    perror("failed to set file status flags");
> +    goto err;
> +  }
> +
> +  ret = fcntl(sock_mc, F_GETFL, 0);
> +  if (ret < 0) {
> +    perror("ipv4: failed to get file status flags");
> +    goto err;
> +  }
> +
> +  ret = fcntl(sock_mc, F_SETFL, ret | O_NONBLOCK);
> +  if (ret < 0) {
> +    perror("ipv4: failed to set file status flags");
> +    goto err;
> +  }
> +
> +  interface->netsock = sock;
> +  interface->netsock_mcast = sock_mc;
> +
> +  return 0;
> +err:
> +  close(sock_mc);
> +  return -1;
> +}
> +
>  int netsock_open_all(struct globals *globals)
>  {
>  	int num_socks = 0;
> @@ -342,7 +475,11 @@ int netsock_open_all(struct globals *globals)
>  	struct interface *interface;
>  
>  	list_for_each_entry(interface, &globals->interfaces, list) {
> -		ret = netsock_open(interface);
> +	  if (globals->ipv4mode)
> +	    ret = netsock_open4(interface);
> +	  else
> +	    ret = netsock_open(interface);
> +
>  		if (ret >= 0)
>  			num_socks++;
>  	}
> @@ -356,7 +493,12 @@ void netsock_reopen(struct globals *globals)
>  
>  	list_for_each_entry(interface, &globals->interfaces, list) {
>  		if (interface->netsock < 0)
> -			netsock_open(interface);
> +		{
> +	    if (globals->ipv4mode)
> +	      netsock_open4(interface);
> +	    else
> +	      netsock_open(interface);
> +		}
>  	}
>  }
>  
> @@ -430,7 +572,7 @@ int netsock_receive_packet(struct globals
> *globals, fd_set *fds)
>  }
>  
>  int netsock_own_address(const struct globals *globals,
> -			const struct in6_addr *address)
> +			const alfred_addr *address)
>  {
>  	struct interface *interface;
>  
> diff --git a/recv.c b/recv.c
> index bb8cc05..cc1ef5b 100644
> --- a/recv.c
> +++ b/recv.c
> @@ -190,7 +190,7 @@ static int finish_alfred_transaction(struct
> globals *globals,
>  }
>  
>  static int process_alfred_push_data(struct globals *globals,
> -				    struct in6_addr *source,
> +				    alfred_addr *source,
>  				    struct alfred_push_data_v0
> *push)
>  {
>  	int len;
> @@ -200,7 +200,10 @@ static int process_alfred_push_data(struct
> globals *globals,
>  	struct transaction_packet *transaction_packet;
>  	int found;
>  
> -	ret = ipv6_to_mac(source, &mac);
> +  if (globals->ipv4mode)
> +    ret = ipv4_to_mac(source, &mac);
> +  else
> +    ret = ipv6_to_mac(source, &mac);
>  	if (ret < 0)
>  		goto err;
>  
> @@ -260,7 +263,7 @@ err:
>  static int
>  process_alfred_announce_master(struct globals *globals,
>  			       struct interface *interface,
> -			       struct in6_addr *source,
> +			       alfred_addr *source,
>  			       struct alfred_announce_master_v0
> *announce)
>  {
>  	struct server *server;
> @@ -271,7 +274,10 @@ process_alfred_announce_master(struct globals
> *globals,
>  
>  	len = ntohs(announce->header.length);
>  
> -	ret = ipv6_to_mac(source, &mac);
> +	if (globals->ipv4mode)
> +	  ret = ipv4_to_mac(source, &mac);
> +	else
> +	  ret = ipv6_to_mac(source, &mac);
>  	if (ret < 0)
>  		return -1;
>  
> @@ -316,7 +322,7 @@ process_alfred_announce_master(struct globals
> *globals,
>  
>  static int process_alfred_request(struct globals *globals,
>  				  struct interface *interface,
> -				  struct in6_addr *source,
> +				  alfred_addr *source,
>  				  struct alfred_request_v0 *request)
>  {
>  	int len;
> @@ -336,7 +342,7 @@ static int process_alfred_request(struct globals
> *globals,
>  }
>  
>  static int process_alfred_status_txend(struct globals *globals,
> -				       struct in6_addr *source,
> +				       alfred_addr *source,
>  				       struct alfred_status_v0
> *request)
>  {
>  	struct transaction_head search, *head;
> @@ -351,7 +357,10 @@ static int process_alfred_status_txend(struct
> globals *globals,
>  	if (len != (sizeof(*request) - sizeof(request->header)))
>  		return -1;
>  
> -	ret = ipv6_to_mac(source, &mac);
> +  if (globals->ipv4mode)
> +    ret = ipv4_to_mac(source, &mac);
> +  else
> +    ret = ipv6_to_mac(source, &mac);
>  	if (ret < 0)
>  		return -1;
>  
> @@ -389,15 +398,28 @@ int recv_alfred_packet(struct globals *globals,
> struct interface *interface,
>  	uint8_t buf[MAX_PAYLOAD];
>  	ssize_t length;
>  	struct alfred_tlv *packet;
> -	struct sockaddr_in6 source;
> +	struct sockaddr_in *source;
> +	struct sockaddr_in source4;
> +	struct sockaddr_in6 source6;
>  	socklen_t sourcelen;
> +	alfred_addr alfred_source;
>  
>  	if (interface->netsock < 0)
>  		return -1;
>  
> -	sourcelen = sizeof(source);
> +	if (globals->ipv4mode)
> +	{
> +    source = (struct sockaddr_in *) &source4;
> +    sourcelen = sizeof(source4);
> +	}
> +	else
> +	{
> +    source = (struct sockaddr_in *) &source6;
> +    sourcelen = sizeof(source6);
> +	}
> +
>  	length = recvfrom(recv_sock, buf, sizeof(buf), 0,
> -			  (struct sockaddr *)&source, &sourcelen);
> +			  (struct sockaddr *) source, &sourcelen);
>  	if (length <= 0) {
>  		perror("read from network socket failed");
>  		return -1;
> @@ -405,12 +427,21 @@ int recv_alfred_packet(struct globals *globals,
> struct interface *interface,
>  
>  	packet = (struct alfred_tlv *)buf;
>  
> -	/* drop packets not sent over link-local ipv6 */
> -	if (!is_ipv6_eui64(&source.sin6_addr))
> -		return -1;
> +  if (globals->ipv4mode)
> +  {
> +    memcpy(&alfred_source, &source4.sin_addr,
> sizeof(source4.sin_addr));
> +  }
> +  else
> +  {
> +    memcpy(&alfred_source, &source6.sin6_addr,
> sizeof(source6.sin6_addr));
> +
> +    /* drop packets not sent over link-local ipv6 */
> +    if (!is_ipv6_eui64(&alfred_source.ipv6))
> +      return -1;
> +  }
>  
>  	/* drop packets from ourselves */
> -	if (netsock_own_address(globals, &source.sin6_addr))
> +	if (netsock_own_address(globals, &alfred_source))
>  		return -1;
>  
>  	/* drop truncated packets */
> @@ -424,20 +455,20 @@ int recv_alfred_packet(struct globals *globals,
> struct interface *interface,
>  
>  	switch (packet->type) {
>  	case ALFRED_PUSH_DATA:
> -		process_alfred_push_data(globals, &source.sin6_addr,
> +		process_alfred_push_data(globals, &alfred_source,
>  					 (struct alfred_push_data_v0
> *)packet);
>  		break;
>  	case ALFRED_ANNOUNCE_MASTER:
>  		process_alfred_announce_master(globals, interface,
> -					       &source.sin6_addr,
> +					       &alfred_source,
>  					       (struct
> alfred_announce_master_v0 *)packet);
>  		break;
>  	case ALFRED_REQUEST:
> -		process_alfred_request(globals, interface,
> &source.sin6_addr,
> +		process_alfred_request(globals, interface,
> &alfred_source,
>  				       (struct alfred_request_v0
> *)packet);
>  		break;
>  	case ALFRED_STATUS_TXEND:
> -		process_alfred_status_txend(globals,
> &source.sin6_addr,
> +		process_alfred_status_txend(globals, &alfred_source,
>  					    (struct alfred_status_v0
> *)packet);
>  		break;
>  	default:
> diff --git a/send.c b/send.c
> index c7a2af2..81ff060 100644
> --- a/send.c
> +++ b/send.c
> @@ -42,7 +42,7 @@ int announce_master(struct globals *globals)
>  		announcement.header.version = ALFRED_VERSION;
>  		announcement.header.length = htons(0);
>  
> -		send_alfred_packet(interface, &in6addr_localmcast,
> +		send_alfred_packet(globals, interface,
> &alfred_mcast,
>  				   &announcement,
> sizeof(announcement));
>  	}
>  
> @@ -50,7 +50,7 @@ int announce_master(struct globals *globals)
>  }
>  
>  int push_data(struct globals *globals, struct interface *interface,
> -	      struct in6_addr *destination, enum data_source
> max_source_level,
> +	      alfred_addr *destination, enum data_source
> max_source_level,
>  	      int type_filter, uint16_t tx_id)
>  {
>  	struct hash_it_t *hashit = NULL;
> @@ -90,7 +90,7 @@ int push_data(struct globals *globals, struct
> interface *interface,
>  			tlv_length += sizeof(*push) - sizeof(push-
> >header);
>  			push->header.length = htons(tlv_length);
>  			push->tx.seqno = htons(seqno++);
> -			send_alfred_packet(interface, destination,
> push,
> +			send_alfred_packet(globals, interface,
> destination, push,
>  					   sizeof(*push) +
> total_length);
>  			total_length = 0;
>  		}
> @@ -114,7 +114,7 @@ int push_data(struct globals *globals, struct
> interface *interface,
>  		tlv_length += sizeof(*push) - sizeof(push->header);
>  		push->header.length = htons(tlv_length);
>  		push->tx.seqno = htons(seqno++);
> -		send_alfred_packet(interface, destination, push,
> +		send_alfred_packet(globals, interface, destination,
> push,
>  				   sizeof(*push) + total_length);
>  	}
>  
> @@ -128,7 +128,7 @@ int push_data(struct globals *globals, struct
> interface *interface,
>  		status_end.tx.id = tx_id;
>  		status_end.tx.seqno = htons(seqno);
>  
> -		send_alfred_packet(interface, destination,
> &status_end,
> +		send_alfred_packet(globals, interface, destination,
> &status_end,
>  				   sizeof(status_end));
>  	}
>  
> @@ -170,24 +170,41 @@ int push_local_data(struct globals *globals)
>  	return 0;
>  }
>  
> -ssize_t send_alfred_packet(struct interface *interface,
> -			   const struct in6_addr *dest, void *buf,
> int length)
> +ssize_t send_alfred_packet(struct globals *globals, struct interface
> *interface,
> +			   const alfred_addr *dest, void *buf, int
> length)
>  {
>  	ssize_t ret;
> -	struct sockaddr_in6 dest_addr;
> -
> -	memset(&dest_addr, 0, sizeof(dest_addr));
> -	dest_addr.sin6_family = AF_INET6;
> -	dest_addr.sin6_port = htons(ALFRED_PORT);
> -	dest_addr.sin6_scope_id = interface->scope_id;
> -	memcpy(&dest_addr.sin6_addr, dest, sizeof(*dest));
> +	struct sockaddr *dest_addr;
> +	struct sockaddr_in6 dest_addr6;
> +	struct sockaddr_in dest_addr4;
> +	socklen_t slen;
> +
> +	if (globals->ipv4mode)
> +	{
> +    memset(&dest_addr4, 0, sizeof(dest_addr4));
> +    dest_addr4.sin_family = AF_INET;
> +    dest_addr4.sin_port = htons(ALFRED_PORT);
> +    memcpy(&dest_addr4.sin_addr, &dest->ipv4, sizeof(dest->ipv4));
> +
> +    slen = sizeof(struct sockaddr_in);
> +    dest_addr = (struct sockaddr *) &dest_addr4;
> +	}
> +  else
> +  {
> +    memset(&dest_addr6, 0, sizeof(dest_addr6));
> +    dest_addr6.sin6_family = AF_INET6;
> +    dest_addr6.sin6_port = htons(ALFRED_PORT);
> +    dest_addr6.sin6_scope_id = interface->scope_id;
> +    memcpy(&dest_addr6.sin6_addr, &dest->ipv6, sizeof(dest->ipv6));
> +
> +    slen = sizeof(struct sockaddr_in6);
> +    dest_addr = (struct sockaddr *) &dest_addr6;
> +  }
>  
>  	if (interface->netsock < 0)
>  		return 0;
>  
> -	ret = sendto(interface->netsock, buf, length, 0,
> -		     (struct sockaddr *)&dest_addr,
> -		     sizeof(struct sockaddr_in6));
> +	ret = sendto(interface->netsock, buf, length, 0, dest_addr,
> slen);
>  	if (ret == -EPERM) {
>  		perror("Error during sent");
>  		close(interface->netsock);
> diff --git a/server.c b/server.c
> index f6e0c8a..337423a 100644
> --- a/server.c
> +++ b/server.c
> @@ -218,7 +218,7 @@ static int purge_data(struct globals *globals)
>  	return 0;
>  }
>  
> -static void check_if_socket(struct interface *interface)
> +static void check_if_socket(struct interface *interface, struct
> globals *globals)
>  {
>  	int sock;
>  	struct ifreq ifr;
> @@ -226,7 +226,7 @@ static void check_if_socket(struct interface
> *interface)
>  	if (interface->netsock < 0)
>  		return;
>  
> -	sock = socket(PF_INET6, SOCK_DGRAM, 0);
> +	sock = socket(PF_INET, SOCK_DGRAM, 0);
>  	if (sock < 0) {
>  		perror("can't open socket");
>  		return;
> @@ -240,7 +240,7 @@ static void check_if_socket(struct interface
> *interface)
>  		goto close;
>  	}
>  
> -	if (interface->scope_id != (uint32_t)ifr.ifr_ifindex) {
> +	if ((0 == globals->ipv4mode) && (interface->scope_id !=
> (uint32_t)ifr.ifr_ifindex)) {
>  		fprintf(stderr,
>  			"iface index changed from %"PRIu32" to %d,
> closing netsock\n",
>  			interface->scope_id, ifr.ifr_ifindex);
> @@ -282,7 +282,7 @@ static void check_if_sockets(struct globals
> *globals)
>  	globals->if_check = now;
>  
>  	list_for_each_entry(interface, &globals->interfaces, list)
> -		check_if_socket(interface);
> +		check_if_socket(interface, globals);
>  }
>  
>  static void execute_update_command(struct globals *globals)
> diff --git a/unix_sock.c b/unix_sock.c
> index 0a819a2..4a8c6e0 100644
> --- a/unix_sock.c
> +++ b/unix_sock.c
> @@ -258,7 +258,7 @@ static int unix_sock_req_data(struct globals
> *globals,
>  	head->client_socket = client_sock;
>  	head->requested_type = request->requested_type;
>  
> -	send_alfred_packet(interface, &globals->best_server-
> >address,
> +	send_alfred_packet(globals, interface, &globals-
> >best_server->address,
>  			   request, sizeof(*request));
>  
>  	return 0;

  reply	other threads:[~2017-01-16 19:52 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-01-16 19:49 [B.A.T.M.A.N.] [PATCH] IPv4 multicast distribution support Jonathan Haws
2017-01-16 19:52 ` Jonathan Haws [this message]
2017-01-17  7:44 ` Sven Eckelmann
2017-01-17 15:39   ` Jonathan Haws
2017-01-17 16:54     ` Sven Eckelmann
2017-01-17 19:11       ` Linus Lüssing
2017-01-18  5:12       ` Jonathan Haws
2017-01-18  8:11         ` Sven Eckelmann
2017-01-17 19:30 ` Linus Lüssing
2017-01-18  5:06   ` Jonathan Haws

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1484596361.15751.2.camel@sdl.usu.edu \
    --to=jonathan.haws@sdl.usu.edu \
    --cc=b.a.t.m.a.n@lists.open-mesh.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox