(root)/
strace-6.5/
tests/
ip_mreq.c
       1  /*
       2   * Copyright (c) 2015-2016 Dmitry V. Levin <ldv@strace.io>
       3   * Copyright (c) 2015-2021 The strace developers.
       4   * All rights reserved.
       5   *
       6   * SPDX-License-Identifier: GPL-2.0-or-later
       7   */
       8  
       9  #include "tests.h"
      10  #include <netinet/in.h>
      11  
      12  #if defined IP_ADD_MEMBERSHIP && defined IPV6_ADD_MEMBERSHIP \
      13   && defined IPV6_JOIN_ANYCAST
      14  
      15  # include <limits.h>
      16  # include <stdio.h>
      17  # include <unistd.h>
      18  # include <sys/socket.h>
      19  # include <arpa/inet.h>
      20  # include <net/if.h>
      21  
      22  # define multi4addr	"224.0.0.3"
      23  # define multi6addr	"ff01::c"
      24  # define interface	"127.0.0.1"
      25  
      26  int
      27  main(void)
      28  {
      29  	TAIL_ALLOC_OBJECT_CONST_PTR(struct ip_mreq, m4);
      30  	TAIL_ALLOC_OBJECT_CONST_PTR(struct ipv6_mreq, m6);
      31  	int rc;
      32  
      33  	inet_pton(AF_INET, multi4addr, &m4->imr_multiaddr);
      34  	inet_pton(AF_INET, interface, &m4->imr_interface);
      35  	inet_pton(AF_INET6, multi6addr, &m6->ipv6mr_multiaddr);
      36  
      37  	m6->ipv6mr_interface = ifindex_lo();
      38  	if (!m6->ipv6mr_interface)
      39  		perror_msg_and_skip("lo");
      40  
      41  	(void) close(0);
      42  	if (socket(AF_INET, SOCK_DGRAM, 0))
      43  		perror_msg_and_skip("socket");
      44  
      45  	struct {
      46  		const int level;
      47  		const char *const str_level;
      48  		const int name;
      49  		const char *str_name;
      50  		const void *const val;
      51  		unsigned int size;
      52  		const char *const addr;
      53  	} opts[] = {
      54  		{
      55  			ARG_STR(SOL_IP), ARG_STR(IP_ADD_MEMBERSHIP),
      56  			m4, sizeof(*m4),
      57  			"{imr_multiaddr=inet_addr(\"" multi4addr
      58  			"\"), imr_interface=inet_addr(\"" interface "\")}"
      59  		},
      60  		{
      61  			ARG_STR(SOL_IP), ARG_STR(IP_DROP_MEMBERSHIP),
      62  			m4, sizeof(*m4),
      63  			"{imr_multiaddr=inet_addr(\"" multi4addr
      64  			"\"), imr_interface=inet_addr(\"" interface "\")}"
      65  		},
      66  		{
      67  			ARG_STR(SOL_IPV6), ARG_STR(IPV6_ADD_MEMBERSHIP),
      68  			m6, sizeof(*m6),
      69  			"{inet_pton(AF_INET6, \"" multi6addr
      70  			"\", &ipv6mr_multiaddr)"
      71  			", ipv6mr_interface=" IFINDEX_LO_STR "}"
      72  		},
      73  		{
      74  			ARG_STR(SOL_IPV6), ARG_STR(IPV6_DROP_MEMBERSHIP),
      75  			m6, sizeof(*m6),
      76  			"{inet_pton(AF_INET6, \"" multi6addr
      77  			"\", &ipv6mr_multiaddr)"
      78  			", ipv6mr_interface=" IFINDEX_LO_STR "}"
      79  		},
      80  		{
      81  			ARG_STR(SOL_IPV6), ARG_STR(IPV6_JOIN_ANYCAST),
      82  			m6, sizeof(*m6),
      83  			"{inet_pton(AF_INET6, \"" multi6addr
      84  			"\", &ipv6mr_multiaddr)"
      85  			", ipv6mr_interface=" IFINDEX_LO_STR "}"
      86  		},
      87  		{
      88  			ARG_STR(SOL_IPV6), ARG_STR(IPV6_LEAVE_ANYCAST),
      89  			m6, sizeof(*m6),
      90  			"{inet_pton(AF_INET6, \"" multi6addr
      91  			"\", &ipv6mr_multiaddr)"
      92  			", ipv6mr_interface=" IFINDEX_LO_STR "}"
      93  		}
      94  	};
      95  
      96  	for (unsigned int i = 0; i < ARRAY_SIZE(opts); ++i) {
      97  		/* optlen < 0, EINVAL */
      98  		rc = setsockopt(0, opts[i].level, opts[i].name,
      99  				opts[i].val, -1);
     100  		printf("setsockopt(0, %s, %s, %p, -1) = %s\n",
     101  		       opts[i].str_level, opts[i].str_name,
     102  		       opts[i].val, sprintrc(rc));
     103  
     104  		/* optlen < sizeof(struct), EINVAL */
     105  		rc = setsockopt(0, opts[i].level, opts[i].name,
     106  				opts[i].val, opts[i].size - 1);
     107  		printf("setsockopt(0, %s, %s, %p, %u) = %s\n",
     108  		       opts[i].str_level, opts[i].str_name,
     109  		       opts[i].val, opts[i].size - 1, sprintrc(rc));
     110  
     111  		/* optval EFAULT */
     112  		rc = setsockopt(0, opts[i].level, opts[i].name,
     113  				opts[i].val + 1, opts[i].size);
     114  		printf("setsockopt(0, %s, %s, %p, %u) = %s\n",
     115  		       opts[i].str_level, opts[i].str_name,
     116  		       opts[i].val + 1, opts[i].size, sprintrc(rc));
     117  
     118  		/* classic */
     119  		rc = setsockopt(0, opts[i].level, opts[i].name,
     120  				opts[i].val, opts[i].size);
     121  		printf("setsockopt(0, %s, %s, %s, %u) = %s\n",
     122  		       opts[i].str_level, opts[i].str_name,
     123  		       opts[i].addr, opts[i].size, sprintrc(rc));
     124  
     125  		/* optlen > sizeof(struct), shortened */
     126  		rc = setsockopt(0, opts[i].level, opts[i].name,
     127  				opts[i].val, INT_MAX);
     128  		printf("setsockopt(0, %s, %s, %s, %u) = %s\n",
     129  		       opts[i].str_level, opts[i].str_name,
     130  		       opts[i].addr, INT_MAX, sprintrc(rc));
     131  	}
     132  
     133  	puts("+++ exited with 0 +++");
     134  	return 0;
     135  }
     136  
     137  #else
     138  
     139  SKIP_MAIN_UNDEFINED("IP_ADD_MEMBERSHIP && IPV6_ADD_MEMBERSHIP"
     140  		    " && IPV6_JOIN_ANYCAST")
     141  
     142  #endif