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