Monday, October 04, 2021

ffmpeg - fix multicast

$OpenBSD$

Index: libavformat/udp.c
--- libavformat/udp.c.orig
+++ libavformat/udp.c
@@ -161,9 +161,10 @@ static const AVClass udplite_context_class = {
static int udp_set_multicast_ttl(int sockfd, int mcastTTL,
struct sockaddr *addr)
{
+ unsigned char mcastTTLc = mcastTTL;
#ifdef IP_MULTICAST_TTL
if (addr->sa_family == AF_INET) {
- if (setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_TTL, &mcastTTL, sizeof(mcastTTL)) < 0) {
+ if (setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_TTL, &mcastTTLc, sizeof(mcastTTLc)) < 0) {
ff_log_net_error(NULL, AV_LOG_ERROR, "setsockopt(IP_MULTICAST_TTL)");
return ff_neterrno();
}
@@ -171,7 +172,7 @@ static int udp_set_multicast_ttl(int sockfd, int mcast
#endif
#if defined(IPPROTO_IPV6) && defined(IPV6_MULTICAST_HOPS)
if (addr->sa_family == AF_INET6) {
- if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &mcastTTL, sizeof(mcastTTL)) < 0) {
+ if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &mcastTTLc, sizeof(mcastTTLc)) < 0) {
ff_log_net_error(NULL, AV_LOG_ERROR, "setsockopt(IPV6_MULTICAST_HOPS)");
return ff_neterrno();
}
Hi

The TTL for a multicast data packet has to be an unsigned char, but
ffmpeg uses int:

$ ffmpeg -i https://ftp.openbsd.org/pub/OpenBSD/songs/song69.ogg \
> "udp://239.255.0.1:9000?ttl=10"
(...)
setsockopt(IP_MULTICAST_TTL): Invalid argument
udp://239.255.0.1:9000?ttl=10: Invalid argument

The attached patch fixes this by simply casting the int into a unsigned
char. Note that I'm not at all a proficient C programmer, nor a porter,
so please take this as a proof of concept of sorts. There probably is a
more elegant and/or correct solution for this, but hey "it works for
me".

My solution has the obvious issue of int's range being much larger than
u_char's. ffmpeg blindly accepts values greater than 255 without
throwing an error or a warning, and leaves it to the OS to handle it as
it sees fit (I have no other OS readily available to see what happens
there). With this patch, and from my limited testing, the value just
gets truncated and wraps around.

I'd argue that if you are trying to multicast with a TTL larger than
255, you are shooting yourself in the foot and probably should get a
better understanding of what you are doing. Ideally the value would be
checked for correctness, but I think thats a job for someone upstream.

Anyway, here's the patch. Like I said, I have no experience as a
(proper) porter, nor as a C developer, so I decided not to submit the
whole port, just the patch.

Cheers


--

No comments:

Post a Comment