[PATCH] Decode setsockopt() multicast arguments

Dmitry V. Levin ldv at altlinux.org
Wed Mar 19 01:19:38 UTC 2014


On Mon, Mar 17, 2014 at 07:24:00PM +0100, Ben Noordhuis wrote:
> * net.c (sys_setsockopt): decode IP_ADD_MEMBERSHIP, IP_DROP_MEMBERSHIP,
>   IPV6_ADD_MEMBERSHIP and IPV6_DROP_MEMBERSHIP arguments.

Thanks.

> --- a/net.c
> +++ b/net.c
> @@ -2301,6 +2301,49 @@ static void printicmpfilter(struct tcb *tcp, long addr)
>  }
>  #endif /* ICMP_FILTER */
>  
> +#if defined(IP_ADD_MEMBERSHIP) || defined(IP_DROP_MEMBERSHIP)

Is it really possible to have only one of these constants defined?

> +static void printmreq(struct tcb *tcp, long addr, int len)
> +{
> +	struct ip_mreq mreq;

We usually add an empty line here.

> +	if (len == sizeof(mreq) && umove(tcp, addr, &mreq) == 0) {
> +		tprintf("{imr_multiaddr=inet_addr(\"%s\"),",
> +			inet_ntoa(mreq.imr_multiaddr));
> +		tprintf(" imr_interface=inet_addr(\"%s\")}",
> +			inet_ntoa(mreq.imr_interface));
> +	}
> +	else {
> +		printstr(tcp, addr, len);
> +	}
> +}
> +#endif /* defined(IP_ADD_MEMBERSHIP) || defined(IP_DROP_MEMBERSHIP) */
> +
> +#if defined(IPV6_ADD_MEMBERSHIP) || defined(IPV6_DROP_MEMBERSHIP)
> +static void printmreq6(struct tcb *tcp, long addr, int len)
> +{
> +#if HAVE_INET_NTOP
> +	struct ipv6_mreq mreq;
> +	const struct in6_addr *in6;
> +	char text[INET6_ADDRSTRLEN];
> +
> +	if (len != sizeof(mreq))
> +		goto fail;
> +
> +	if (umove(tcp, addr, &mreq) < 0)
> +		goto fail;
> +
> +	in6 = &mreq.ipv6mr_multiaddr;
> +	if (inet_ntop(AF_INET6, in6, text, sizeof(text)) != text)
> +		goto fail;
> +
> +	tprintf("{ipv6mr_multiaddr=inet_ntop(\"%s\"), ipv6mr_interface=%d}",
> +		text, mreq.ipv6mr_interface);
> +	return;
> +fail:

The same code written without "goto" would be more readable:

	if (len == sizeof(mreq) &&
	    umove(tcp, addr, &mreq) == 0 &&
	    inet_ntop(AF_INET6, &mreq.ipv6mr_multiaddr, text, sizeof(text))) {
		tprintf(...);
		return;
	}

> +#endif /* HAVE_INET_NTOP */
> +	printstr(tcp, addr, len);
> +}
> +#endif /* defined(IPV6_ADD_MEMBERSHIP) || defined(IPV6_DROP_MEMBERSHIP) */
> +
>  static int
>  printsockopt(struct tcb *tcp, int level, int name, long addr, int len)
>  {
> @@ -2327,7 +2370,34 @@ printsockopt(struct tcb *tcp, int level, int name, long addr, int len)
>  		break;
>  #ifdef SOL_IP
>  	case SOL_IP:
> -		printxval(sockipoptions, name, "IP_???");
> +		switch (name) {
> +#ifdef IP_ADD_MEMBERSHIP
> +			case IP_ADD_MEMBERSHIP:
> +				tprints("IP_ADD_MEMBERSHIP, ");
> +				printmreq(tcp, addr, len);
> +				return 0;
> +#endif
> +#ifdef IP_DROP_MEMBERSHIP
> +			case IP_DROP_MEMBERSHIP:
> +				tprints("IP_DROP_MEMBERSHIP, ");
> +				printmreq(tcp, addr, len);
> +				return 0;
> +#endif
> +#ifdef IPV6_ADD_MEMBERSHIP
> +			case IPV6_ADD_MEMBERSHIP:
> +				tprints("IPV6_ADD_MEMBERSHIP, ");
> +				printmreq6(tcp, addr, len);
> +				return 0;
> +#endif
> +#ifdef IPV6_DROP_MEMBERSHIP
> +			case IPV6_DROP_MEMBERSHIP:
> +				tprints("IPV6_DROP_MEMBERSHIP, ");
> +				printmreq6(tcp, addr, len);
> +				return 0;
> +#endif
> +			default:
> +				printxval(sockipoptions, name, "IP_???");
> +		}

Could it be coded in a more compact way? e.g. if ADD_MEMBERSHIP and
DROP_MEMBERSHIP constants are either defined or undefined altogether:

	printxval(sockipoptions, name, "IP_???");
	switch (name) {
#ifdef IP_ADD_MEMBERSHIP
		case IP_ADD_MEMBERSHIP:
		case IP_DROP_MEMBERSHIP:
			tprints(", ");
			printmreq(tcp, addr, len);
			return 0;
#endif
#ifdef IPV6_ADD_MEMBERSHIP
		case IPV6_ADD_MEMBERSHIP:
		case IPV6_DROP_MEMBERSHIP:
			tprints(", ");
			printmreq6(tcp, addr, len);
			return 0;
#endif
		default: break;
	}

>  		break;
>  #endif
>  #ifdef SOL_IPV6

-- 
ldv
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: not available
URL: <http://lists.strace.io/pipermail/strace-devel/attachments/20140319/aebfc463/attachment.bin>


More information about the Strace-devel mailing list