- avformat/udp: set ttl upper bound to 255
- avformat/udp: properly check for valid ttl in url
- avformat/udp: use one setsockopt for ipv4/ipv6
- avformat/udp: Fix IP_MULTICAST_TTL for BSD compatibility
- avformat/udp: remove IPPROTO_IPV6 macro

Index: libavformat/udp.c
--- libavformat/udp.c.orig
+++ libavformat/udp.c
@@ -134,7 +134,7 @@ static const AVOption options[] = {
     { "reuse",          "explicitly allow reusing UDP sockets",            OFFSET(reuse_socket),   AV_OPT_TYPE_BOOL,   { .i64 = -1 },    -1, 1,       D|E },
     { "reuse_socket",   "explicitly allow reusing UDP sockets",            OFFSET(reuse_socket),   AV_OPT_TYPE_BOOL,   { .i64 = -1 },    -1, 1,       .flags = D|E },
     { "broadcast", "explicitly allow or disallow broadcast destination",   OFFSET(is_broadcast),   AV_OPT_TYPE_BOOL,   { .i64 = 0  },     0, 1,       E },
-    { "ttl",            "Time to live (multicast only)",                   OFFSET(ttl),            AV_OPT_TYPE_INT,    { .i64 = 16 },     0, INT_MAX, E },
+    { "ttl",            "Time to live (multicast only)",                   OFFSET(ttl),            AV_OPT_TYPE_INT,    { .i64 = 16 },     0, 255,     E },
     { "connect",        "set if connect() should be called on socket",     OFFSET(is_connected),   AV_OPT_TYPE_BOOL,   { .i64 =  0 },     0, 1,       .flags = D|E },
     { "fifo_size",      "set the UDP receiving circular buffer size, expressed as a number of packets with size of 188 bytes", OFFSET(circular_buffer_size), AV_OPT_TYPE_INT, {.i64 = 7*4096}, 0, INT_MAX, D },
     { "overrun_nonfatal", "survive in case of UDP receiving circular buffer overrun", OFFSET(overrun_nonfatal), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1,    D },
@@ -161,22 +161,40 @@ static const AVClass udplite_context_class = {
 static int udp_set_multicast_ttl(int sockfd, int mcastTTL,
                                  struct sockaddr *addr)
 {
+    int protocol, cmd;
+
+    /* There is some confusion in the world whether IP_MULTICAST_TTL
+     * takes a byte or an int as an argument.
+     * BSD seems to indicate byte so we are going with that and use
+     * int and fall back to byte to be safe */
+    switch (addr->sa_family) {
 #ifdef IP_MULTICAST_TTL
-    if (addr->sa_family == AF_INET) {
-        if (setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_TTL, &mcastTTL, sizeof(mcastTTL)) < 0) {
-            ff_log_net_error(NULL, AV_LOG_ERROR, "setsockopt(IP_MULTICAST_TTL)");
-            return ff_neterrno();
-        }
-    }
+        case AF_INET:
+            protocol = IPPROTO_IP;
+            cmd      = IP_MULTICAST_TTL;
+            break;
 #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) {
-            ff_log_net_error(NULL, AV_LOG_ERROR, "setsockopt(IPV6_MULTICAST_HOPS)");
+#ifdef IPV6_MULTICAST_HOPS
+        case AF_INET6:
+            protocol = IPPROTO_IPV6;
+            cmd      = IPV6_MULTICAST_HOPS;
+            break;
+#endif
+        default:
+            return 0;
+    }
+
+    if (setsockopt(sockfd, protocol, cmd, &mcastTTL, sizeof(mcastTTL)) < 0) {
+        /* BSD compatibility */
+        unsigned char ttl = (unsigned char) mcastTTL;
+
+        ff_log_net_error(NULL, AV_LOG_DEBUG, "setsockopt(IPV4/IPV6 MULTICAST TTL)");
+        if (setsockopt(sockfd, protocol, cmd, &ttl, sizeof(ttl)) < 0) {
+            ff_log_net_error(NULL, AV_LOG_ERROR, "setsockopt(IPV4/IPV6 MULTICAST TTL)");
             return ff_neterrno();
         }
     }
-#endif
+
     return 0;
 }
 
@@ -673,6 +691,11 @@ static int udp_open(URLContext *h, const char *uri, in
         }
         if (av_find_info_tag(buf, sizeof(buf), "ttl", p)) {
             s->ttl = strtol(buf, NULL, 10);
+            if (s->ttl < 0 || s->ttl > 255) {
+                av_log(h, AV_LOG_ERROR, "ttl(%d) should be in range [0,255]\n", s->ttl);
+                ret = AVERROR(EINVAL);
+                goto fail;
+            }
         }
         if (av_find_info_tag(buf, sizeof(buf), "udplite_coverage", p)) {
             s->udplite_coverage = strtol(buf, NULL, 10);
