Repository files navigation

omcproxy - IGMPv3 and MLDv2 proxy

omcproxy is an IGMPv3 and MLDv2 multicast proxy for Linux routers. This is my personal fork of openwrt/omcproxy, which in turn is partly based on Oryon/pimbd.

It runs on my Linux PC router at home to make Hikari-TV work reliably in a dedicated IPTV VLAN.

Background

NTT's Hikari-TV uses IPv6 multicast to deliver IPTV streams efficiently. In theory this is beautiful and how the internet is supposed to work - finally someone going all-in on IPv6 and even the exotic stuff like multicast.

In practice though, no one seems to implement the functionality to handle IPv6 multicast in a home network and internet connection correctly. ;) omcproxy was the only software I could find that actually worked, and with a few patches here and there, the incident reports from my wife about the TV not working eventually stopped.

Multicast Routing

Linux does not route or forward multicast frames across interfaces (such as between the upstream WAN and my local LAN) by default. Even if we "simply" set up a few static routes e.g. via smcroute, it wouldn't work, because NTT's routers only start sending us the multicast traffic after we join the group and regularly refresh the membership.

An MLDv2-aware proxy daemon is thus required to relay MLD Membership Reports from the proprietary set-top box to NTT's multicast routers, and forward the incoming IPv6 multicast payloads downstream.

Why use a separate VLAN?

Once I got the traffic flow working on my router and the TV showing the channels, I hit the next issue: My Mikrotik switches (with SwOS) and my TP-Link Deco APs don't support MLDv2, and even my LANCOM switches had some strange bugs in their implementation. This leads to traffic being dropped, or broadcast to all ports, which is especially fun when it hits and overwhelms the Wi-Fi. The easiest fix was to put the multicast traffic on a separate VLAN and carefully thread it through to only hit the ethernet port on the switch where the STB is connected.

Features

  1. Source-Specific Multicast Querier

    • MLDv2 querier (based on RFC 3810)
    • IGMPv3 querier (based on RFC 3376)
  2. Multicast Proxying (based on RFC 4605)

    • Kernel-space multicast routing
    • Multiple instances support
    • Address-scope specific proxying

Scope

omcproxy forwards multicast data in one direction: from the upstream interface to downstream interfaces with matching subscriptions. Membership signaling from downstream hosts is aggregated and proxied to the upstream network as the RFC 4605 host portion. Multicast data that originates on a downstream interface is not forwarded, neither to the upstream interface nor to sibling downstream interfaces; such flows get an empty kernel route so that they do not generate repeated cache-miss notifications. This is a deliberate limitation: the target use case is receiving multicast services (such as IPTV) from an upstream network, where the upstream provider drops customer-originated multicast anyway.

Changes in this fork

  • Rewritten in modern C23, clang-formatted to Chromium style, zero clang-tidy warnings.
  • No external dependencies anymore: libubox is replaced by a small epoll and timerfd event loop and a vendored intrusive list header.
  • Merged the IGMPv3 and MLDv2 wire codecs into one shared, unit-tested, fuzz-tested implementation.
  • Added a whole bunch of unit tests, network-namespace integration tests, sanitizer builds, a libFuzzer harness for the packet parsers. Enabled strict compiler warnings and fixed all the findings.
  • Many bug fixes and lots of hardening; see the git history for details.

Building

CMake 3.21+ and Ninja are required.

cmake --preset default
cmake --build --preset default

The binary lands in build/omcproxy. Run it as root with one or more proxy specs, first interface is the upstream:

omcproxy [-v] <uplink>,<downlink>[,<downlink>...][,scope=<scope>][,strict]

With strict, a downstream interface only receives forwarded traffic while this proxy is the elected IGMP/MLD querier on it, as RFC 4605 suggests for LANs with more than one proxy. The default is to keep forwarding even after losing the election, which is the safe choice when another device (such as a snooping switch) sends queries but does not forward multicast itself.

The kernel must support PIM on the multicast routing sockets (CONFIG_IP_PIMSM_V1 or CONFIG_IP_PIMSM_V2, and CONFIG_IPV6_PIMSM_V2). Common distribution kernels enable these options. OpenWrt's generic kernel configuration disables IPv4 PIM, so OpenWrt needs a custom kernel configuration that enables the options. omcproxy uses PIM mode to receive wrong-interface upcalls for any arrival interface, which it needs to recover forwarding when a spoofed packet created a multicast route with the wrong parent. Startup fails when the kernel lacks this support.

Testing

ctest --preset default # unit tests
ctest --preset netns # integration tests in network namespaces

The netns tests need unprivileged user namespaces (or root). The asan preset builds with AddressSanitizer and UndefinedBehaviorSanitizer and has matching asan and netns-asan test presets. The fuzz preset builds build-fuzz/test/fuzz_gmp, a libFuzzer target for the packet parsers (requires clang).

About

IGMPv3/MLDv2 Proxy for Linux routers (modernized fork of openwrt/omcproxy)

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

omcproxy - IGMPv3 and MLDv2 proxy

omcproxy is an IGMPv3 and MLDv2 multicast proxy for Linux routers. This is my personal fork of openwrt/omcproxy, which in turn is partly based on Oryon/pimbd.

It runs on my Linux PC router at home to make Hikari-TV work reliably in a dedicated IPTV VLAN.

Background

NTT's Hikari-TV uses IPv6 multicast to deliver IPTV streams efficiently. In theory this is beautiful and how the internet is supposed to work - finally someone going all-in on IPv6 and even the exotic stuff like multicast.

In practice though, no one seems to implement the functionality to handle IPv6 multicast in a home network and internet connection correctly. ;) omcproxy was the only software I could find that actually worked, and with a few patches here and there, the incident reports from my wife about the TV not working eventually stopped.

Multicast Routing

Linux does not route or forward multicast frames across interfaces (such as between the upstream WAN and my local LAN) by default. Even if we "simply" set up a few static routes e.g. via smcroute, it wouldn't work, because NTT's routers only start sending us the multicast traffic after we join the group and regularly refresh the membership.

An MLDv2-aware proxy daemon is thus required to relay MLD Membership Reports from the proprietary set-top box to NTT's multicast routers, and forward the incoming IPv6 multicast payloads downstream.

Why use a separate VLAN?

Once I got the traffic flow working on my router and the TV showing the channels, I hit the next issue: My Mikrotik switches (with SwOS) and my TP-Link Deco APs don't support MLDv2, and even my LANCOM switches had some strange bugs in their implementation. This leads to traffic being dropped, or broadcast to all ports, which is especially fun when it hits and overwhelms the Wi-Fi. The easiest fix was to put the multicast traffic on a separate VLAN and carefully thread it through to only hit the ethernet port on the switch where the STB is connected.

Features

  1. Source-Specific Multicast Querier

    • MLDv2 querier (based on RFC 3810)
    • IGMPv3 querier (based on RFC 3376)
  2. Multicast Proxying (based on RFC 4605)

    • Kernel-space multicast routing
    • Multiple instances support
    • Address-scope specific proxying

Scope

omcproxy forwards multicast data in one direction: from the upstream interface to downstream interfaces with matching subscriptions. Membership signaling from downstream hosts is aggregated and proxied to the upstream network as the RFC 4605 host portion. Multicast data that originates on a downstream interface is not forwarded, neither to the upstream interface nor to sibling downstream interfaces; such flows get an empty kernel route so that they do not generate repeated cache-miss notifications. This is a deliberate limitation: the target use case is receiving multicast services (such as IPTV) from an upstream network, where the upstream provider drops customer-originated multicast anyway.

Changes in this fork

  • Rewritten in modern C23, clang-formatted to Chromium style, zero clang-tidy warnings.
  • No external dependencies anymore: libubox is replaced by a small epoll and timerfd event loop and a vendored intrusive list header.
  • Merged the IGMPv3 and MLDv2 wire codecs into one shared, unit-tested, fuzz-tested implementation.
  • Added a whole bunch of unit tests, network-namespace integration tests, sanitizer builds, a libFuzzer harness for the packet parsers. Enabled strict compiler warnings and fixed all the findings.
  • Many bug fixes and lots of hardening; see the git history for details.

Building

CMake 3.21+ and Ninja are required.

cmake --preset default
cmake --build --preset default

The binary lands in build/omcproxy. Run it as root with one or more proxy specs, first interface is the upstream:

omcproxy [-v] <uplink>,<downlink>[,<downlink>...][,scope=<scope>][,strict]

With strict, a downstream interface only receives forwarded traffic while this proxy is the elected IGMP/MLD querier on it, as RFC 4605 suggests for LANs with more than one proxy. The default is to keep forwarding even after losing the election, which is the safe choice when another device (such as a snooping switch) sends queries but does not forward multicast itself.

The kernel must support PIM on the multicast routing sockets (CONFIG_IP_PIMSM_V1 or CONFIG_IP_PIMSM_V2, and CONFIG_IPV6_PIMSM_V2). Common distribution kernels enable these options. OpenWrt's generic kernel configuration disables IPv4 PIM, so OpenWrt needs a custom kernel configuration that enables the options. omcproxy uses PIM mode to receive wrong-interface upcalls for any arrival interface, which it needs to recover forwarding when a spoofed packet created a multicast route with the wrong parent. Startup fails when the kernel lacks this support.

Testing

ctest --preset default # unit tests
ctest --preset netns # integration tests in network namespaces

The netns tests need unprivileged user namespaces (or root). The asan preset builds with AddressSanitizer and UndefinedBehaviorSanitizer and has matching asan and netns-asan test presets. The fuzz preset builds build-fuzz/test/fuzz_gmp, a libFuzzer target for the packet parsers (requires clang).

About

IGMPv3/MLDv2 Proxy for Linux routers (modernized fork of openwrt/omcproxy)

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

omcproxy - IGMPv3 and MLDv2 proxy

omcproxy is an IGMPv3 and MLDv2 multicast proxy for Linux routers. This is my personal fork of openwrt/omcproxy, which in turn is partly based on Oryon/pimbd.

It runs on my Linux PC router at home to make Hikari-TV work reliably in a dedicated IPTV VLAN.

Background

NTT's Hikari-TV uses IPv6 multicast to deliver IPTV streams efficiently. In theory this is beautiful and how the internet is supposed to work - finally someone going all-in on IPv6 and even the exotic stuff like multicast.

In practice though, no one seems to implement the functionality to handle IPv6 multicast in a home network and internet connection correctly. ;) omcproxy was the only software I could find that actually worked, and with a few patches here and there, the incident reports from my wife about the TV not working eventually stopped.

Multicast Routing

Linux does not route or forward multicast frames across interfaces (such as between the upstream WAN and my local LAN) by default. Even if we "simply" set up a few static routes e.g. via smcroute, it wouldn't work, because NTT's routers only start sending us the multicast traffic after we join the group and regularly refresh the membership.

An MLDv2-aware proxy daemon is thus required to relay MLD Membership Reports from the proprietary set-top box to NTT's multicast routers, and forward the incoming IPv6 multicast payloads downstream.

Why use a separate VLAN?

Once I got the traffic flow working on my router and the TV showing the channels, I hit the next issue: My Mikrotik switches (with SwOS) and my TP-Link Deco APs don't support MLDv2, and even my LANCOM switches had some strange bugs in their implementation. This leads to traffic being dropped, or broadcast to all ports, which is especially fun when it hits and overwhelms the Wi-Fi. The easiest fix was to put the multicast traffic on a separate VLAN and carefully thread it through to only hit the ethernet port on the switch where the STB is connected.

Features

  1. Source-Specific Multicast Querier

    • MLDv2 querier (based on RFC 3810)
    • IGMPv3 querier (based on RFC 3376)
  2. Multicast Proxying (based on RFC 4605)

    • Kernel-space multicast routing
    • Multiple instances support
    • Address-scope specific proxying

Scope

omcproxy forwards multicast data in one direction: from the upstream interface to downstream interfaces with matching subscriptions. Membership signaling from downstream hosts is aggregated and proxied to the upstream network as the RFC 4605 host portion. Multicast data that originates on a downstream interface is not forwarded, neither to the upstream interface nor to sibling downstream interfaces; such flows get an empty kernel route so that they do not generate repeated cache-miss notifications. This is a deliberate limitation: the target use case is receiving multicast services (such as IPTV) from an upstream network, where the upstream provider drops customer-originated multicast anyway.

Changes in this fork

  • Rewritten in modern C23, clang-formatted to Chromium style, zero clang-tidy warnings.
  • No external dependencies anymore: libubox is replaced by a small epoll and timerfd event loop and a vendored intrusive list header.
  • Merged the IGMPv3 and MLDv2 wire codecs into one shared, unit-tested, fuzz-tested implementation.
  • Added a whole bunch of unit tests, network-namespace integration tests, sanitizer builds, a libFuzzer harness for the packet parsers. Enabled strict compiler warnings and fixed all the findings.
  • Many bug fixes and lots of hardening; see the git history for details.

Building

CMake 3.21+ and Ninja are required.

cmake --preset default
cmake --build --preset default

The binary lands in build/omcproxy. Run it as root with one or more proxy specs, first interface is the upstream:

omcproxy [-v] <uplink>,<downlink>[,<downlink>...][,scope=<scope>][,strict]

With strict, a downstream interface only receives forwarded traffic while this proxy is the elected IGMP/MLD querier on it, as RFC 4605 suggests for LANs with more than one proxy. The default is to keep forwarding even after losing the election, which is the safe choice when another device (such as a snooping switch) sends queries but does not forward multicast itself.

The kernel must support PIM on the multicast routing sockets (CONFIG_IP_PIMSM_V1 or CONFIG_IP_PIMSM_V2, and CONFIG_IPV6_PIMSM_V2). Common distribution kernels enable these options. OpenWrt's generic kernel configuration disables IPv4 PIM, so OpenWrt needs a custom kernel configuration that enables the options. omcproxy uses PIM mode to receive wrong-interface upcalls for any arrival interface, which it needs to recover forwarding when a spoofed packet created a multicast route with the wrong parent. Startup fails when the kernel lacks this support.

Testing

ctest --preset default # unit tests
ctest --preset netns # integration tests in network namespaces

The netns tests need unprivileged user namespaces (or root). The asan preset builds with AddressSanitizer and UndefinedBehaviorSanitizer and has matching asan and netns-asan test presets. The fuzz preset builds build-fuzz/test/fuzz_gmp, a libFuzzer target for the packet parsers (requires clang).

About

IGMPv3/MLDv2 Proxy for Linux routers (modernized fork of openwrt/omcproxy)

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

omcproxy - IGMPv3 and MLDv2 proxy

omcproxy is an IGMPv3 and MLDv2 multicast proxy for Linux routers. This is my personal fork of openwrt/omcproxy, which in turn is partly based on Oryon/pimbd.

It runs on my Linux PC router at home to make Hikari-TV work reliably in a dedicated IPTV VLAN.

Background

NTT's Hikari-TV uses IPv6 multicast to deliver IPTV streams efficiently. In theory this is beautiful and how the internet is supposed to work - finally someone going all-in on IPv6 and even the exotic stuff like multicast.

In practice though, no one seems to implement the functionality to handle IPv6 multicast in a home network and internet connection correctly. ;) omcproxy was the only software I could find that actually worked, and with a few patches here and there, the incident reports from my wife about the TV not working eventually stopped.

Multicast Routing

Linux does not route or forward multicast frames across interfaces (such as between the upstream WAN and my local LAN) by default. Even if we "simply" set up a few static routes e.g. via smcroute, it wouldn't work, because NTT's routers only start sending us the multicast traffic after we join the group and regularly refresh the membership.

An MLDv2-aware proxy daemon is thus required to relay MLD Membership Reports from the proprietary set-top box to NTT's multicast routers, and forward the incoming IPv6 multicast payloads downstream.

Why use a separate VLAN?

Once I got the traffic flow working on my router and the TV showing the channels, I hit the next issue: My Mikrotik switches (with SwOS) and my TP-Link Deco APs don't support MLDv2, and even my LANCOM switches had some strange bugs in their implementation. This leads to traffic being dropped, or broadcast to all ports, which is especially fun when it hits and overwhelms the Wi-Fi. The easiest fix was to put the multicast traffic on a separate VLAN and carefully thread it through to only hit the ethernet port on the switch where the STB is connected.

Features

  1. Source-Specific Multicast Querier

    • MLDv2 querier (based on RFC 3810)
    • IGMPv3 querier (based on RFC 3376)
  2. Multicast Proxying (based on RFC 4605)

    • Kernel-space multicast routing
    • Multiple instances support
    • Address-scope specific proxying

Scope

omcproxy forwards multicast data in one direction: from the upstream interface to downstream interfaces with matching subscriptions. Membership signaling from downstream hosts is aggregated and proxied to the upstream network as the RFC 4605 host portion. Multicast data that originates on a downstream interface is not forwarded, neither to the upstream interface nor to sibling downstream interfaces; such flows get an empty kernel route so that they do not generate repeated cache-miss notifications. This is a deliberate limitation: the target use case is receiving multicast services (such as IPTV) from an upstream network, where the upstream provider drops customer-originated multicast anyway.

Changes in this fork

  • Rewritten in modern C23, clang-formatted to Chromium style, zero clang-tidy warnings.
  • No external dependencies anymore: libubox is replaced by a small epoll and timerfd event loop and a vendored intrusive list header.
  • Merged the IGMPv3 and MLDv2 wire codecs into one shared, unit-tested, fuzz-tested implementation.
  • Added a whole bunch of unit tests, network-namespace integration tests, sanitizer builds, a libFuzzer harness for the packet parsers. Enabled strict compiler warnings and fixed all the findings.
  • Many bug fixes and lots of hardening; see the git history for details.

Building

CMake 3.21+ and Ninja are required.

cmake --preset default
cmake --build --preset default

The binary lands in build/omcproxy. Run it as root with one or more proxy specs, first interface is the upstream:

omcproxy [-v] <uplink>,<downlink>[,<downlink>...][,scope=<scope>][,strict]

With strict, a downstream interface only receives forwarded traffic while this proxy is the elected IGMP/MLD querier on it, as RFC 4605 suggests for LANs with more than one proxy. The default is to keep forwarding even after losing the election, which is the safe choice when another device (such as a snooping switch) sends queries but does not forward multicast itself.

The kernel must support PIM on the multicast routing sockets (CONFIG_IP_PIMSM_V1 or CONFIG_IP_PIMSM_V2, and CONFIG_IPV6_PIMSM_V2). Common distribution kernels enable these options. OpenWrt's generic kernel configuration disables IPv4 PIM, so OpenWrt needs a custom kernel configuration that enables the options. omcproxy uses PIM mode to receive wrong-interface upcalls for any arrival interface, which it needs to recover forwarding when a spoofed packet created a multicast route with the wrong parent. Startup fails when the kernel lacks this support.

Testing

ctest --preset default # unit tests
ctest --preset netns # integration tests in network namespaces

The netns tests need unprivileged user namespaces (or root). The asan preset builds with AddressSanitizer and UndefinedBehaviorSanitizer and has matching asan and netns-asan test presets. The fuzz preset builds build-fuzz/test/fuzz_gmp, a libFuzzer target for the packet parsers (requires clang).

About

IGMPv3/MLDv2 Proxy for Linux routers (modernized fork of openwrt/omcproxy)

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

omcproxy - IGMPv3 and MLDv2 proxy

omcproxy is an IGMPv3 and MLDv2 multicast proxy for Linux routers. This is my personal fork of openwrt/omcproxy, which in turn is partly based on Oryon/pimbd.

It runs on my Linux PC router at home to make Hikari-TV work reliably in a dedicated IPTV VLAN.

Background

NTT's Hikari-TV uses IPv6 multicast to deliver IPTV streams efficiently. In theory this is beautiful and how the internet is supposed to work - finally someone going all-in on IPv6 and even the exotic stuff like multicast.

In practice though, no one seems to implement the functionality to handle IPv6 multicast in a home network and internet connection correctly. ;) omcproxy was the only software I could find that actually worked, and with a few patches here and there, the incident reports from my wife about the TV not working eventually stopped.

Multicast Routing

Linux does not route or forward multicast frames across interfaces (such as between the upstream WAN and my local LAN) by default. Even if we "simply" set up a few static routes e.g. via smcroute, it wouldn't work, because NTT's routers only start sending us the multicast traffic after we join the group and regularly refresh the membership.

An MLDv2-aware proxy daemon is thus required to relay MLD Membership Reports from the proprietary set-top box to NTT's multicast routers, and forward the incoming IPv6 multicast payloads downstream.

Why use a separate VLAN?

Once I got the traffic flow working on my router and the TV showing the channels, I hit the next issue: My Mikrotik switches (with SwOS) and my TP-Link Deco APs don't support MLDv2, and even my LANCOM switches had some strange bugs in their implementation. This leads to traffic being dropped, or broadcast to all ports, which is especially fun when it hits and overwhelms the Wi-Fi. The easiest fix was to put the multicast traffic on a separate VLAN and carefully thread it through to only hit the ethernet port on the switch where the STB is connected.

Features

  1. Source-Specific Multicast Querier

    • MLDv2 querier (based on RFC 3810)
    • IGMPv3 querier (based on RFC 3376)
  2. Multicast Proxying (based on RFC 4605)

    • Kernel-space multicast routing
    • Multiple instances support
    • Address-scope specific proxying

Scope

omcproxy forwards multicast data in one direction: from the upstream interface to downstream interfaces with matching subscriptions. Membership signaling from downstream hosts is aggregated and proxied to the upstream network as the RFC 4605 host portion. Multicast data that originates on a downstream interface is not forwarded, neither to the upstream interface nor to sibling downstream interfaces; such flows get an empty kernel route so that they do not generate repeated cache-miss notifications. This is a deliberate limitation: the target use case is receiving multicast services (such as IPTV) from an upstream network, where the upstream provider drops customer-originated multicast anyway.

Changes in this fork

  • Rewritten in modern C23, clang-formatted to Chromium style, zero clang-tidy warnings.
  • No external dependencies anymore: libubox is replaced by a small epoll and timerfd event loop and a vendored intrusive list header.
  • Merged the IGMPv3 and MLDv2 wire codecs into one shared, unit-tested, fuzz-tested implementation.
  • Added a whole bunch of unit tests, network-namespace integration tests, sanitizer builds, a libFuzzer harness for the packet parsers. Enabled strict compiler warnings and fixed all the findings.
  • Many bug fixes and lots of hardening; see the git history for details.

Building

CMake 3.21+ and Ninja are required.

cmake --preset default
cmake --build --preset default

The binary lands in build/omcproxy. Run it as root with one or more proxy specs, first interface is the upstream:

omcproxy [-v] <uplink>,<downlink>[,<downlink>...][,scope=<scope>][,strict]

With strict, a downstream interface only receives forwarded traffic while this proxy is the elected IGMP/MLD querier on it, as RFC 4605 suggests for LANs with more than one proxy. The default is to keep forwarding even after losing the election, which is the safe choice when another device (such as a snooping switch) sends queries but does not forward multicast itself.

The kernel must support PIM on the multicast routing sockets (CONFIG_IP_PIMSM_V1 or CONFIG_IP_PIMSM_V2, and CONFIG_IPV6_PIMSM_V2). Common distribution kernels enable these options. OpenWrt's generic kernel configuration disables IPv4 PIM, so OpenWrt needs a custom kernel configuration that enables the options. omcproxy uses PIM mode to receive wrong-interface upcalls for any arrival interface, which it needs to recover forwarding when a spoofed packet created a multicast route with the wrong parent. Startup fails when the kernel lacks this support.

Testing

ctest --preset default # unit tests
ctest --preset netns # integration tests in network namespaces

The netns tests need unprivileged user namespaces (or root). The asan preset builds with AddressSanitizer and UndefinedBehaviorSanitizer and has matching asan and netns-asan test presets. The fuzz preset builds build-fuzz/test/fuzz_gmp, a libFuzzer target for the packet parsers (requires clang).

About

IGMPv3/MLDv2 Proxy for Linux routers (modernized fork of openwrt/omcproxy)

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

omcproxy - IGMPv3 and MLDv2 proxy

omcproxy is an IGMPv3 and MLDv2 multicast proxy for Linux routers. This is my personal fork of openwrt/omcproxy, which in turn is partly based on Oryon/pimbd.

It runs on my Linux PC router at home to make Hikari-TV work reliably in a dedicated IPTV VLAN.

Background

NTT's Hikari-TV uses IPv6 multicast to deliver IPTV streams efficiently. In theory this is beautiful and how the internet is supposed to work - finally someone going all-in on IPv6 and even the exotic stuff like multicast.

In practice though, no one seems to implement the functionality to handle IPv6 multicast in a home network and internet connection correctly. ;) omcproxy was the only software I could find that actually worked, and with a few patches here and there, the incident reports from my wife about the TV not working eventually stopped.

Multicast Routing

Linux does not route or forward multicast frames across interfaces (such as between the upstream WAN and my local LAN) by default. Even if we "simply" set up a few static routes e.g. via smcroute, it wouldn't work, because NTT's routers only start sending us the multicast traffic after we join the group and regularly refresh the membership.

An MLDv2-aware proxy daemon is thus required to relay MLD Membership Reports from the proprietary set-top box to NTT's multicast routers, and forward the incoming IPv6 multicast payloads downstream.

Why use a separate VLAN?

Once I got the traffic flow working on my router and the TV showing the channels, I hit the next issue: My Mikrotik switches (with SwOS) and my TP-Link Deco APs don't support MLDv2, and even my LANCOM switches had some strange bugs in their implementation. This leads to traffic being dropped, or broadcast to all ports, which is especially fun when it hits and overwhelms the Wi-Fi. The easiest fix was to put the multicast traffic on a separate VLAN and carefully thread it through to only hit the ethernet port on the switch where the STB is connected.

Features

  1. Source-Specific Multicast Querier

    • MLDv2 querier (based on RFC 3810)
    • IGMPv3 querier (based on RFC 3376)
  2. Multicast Proxying (based on RFC 4605)

    • Kernel-space multicast routing
    • Multiple instances support
    • Address-scope specific proxying

Scope

omcproxy forwards multicast data in one direction: from the upstream interface to downstream interfaces with matching subscriptions. Membership signaling from downstream hosts is aggregated and proxied to the upstream network as the RFC 4605 host portion. Multicast data that originates on a downstream interface is not forwarded, neither to the upstream interface nor to sibling downstream interfaces; such flows get an empty kernel route so that they do not generate repeated cache-miss notifications. This is a deliberate limitation: the target use case is receiving multicast services (such as IPTV) from an upstream network, where the upstream provider drops customer-originated multicast anyway.

Changes in this fork

  • Rewritten in modern C23, clang-formatted to Chromium style, zero clang-tidy warnings.
  • No external dependencies anymore: libubox is replaced by a small epoll and timerfd event loop and a vendored intrusive list header.
  • Merged the IGMPv3 and MLDv2 wire codecs into one shared, unit-tested, fuzz-tested implementation.
  • Added a whole bunch of unit tests, network-namespace integration tests, sanitizer builds, a libFuzzer harness for the packet parsers. Enabled strict compiler warnings and fixed all the findings.
  • Many bug fixes and lots of hardening; see the git history for details.

Building

CMake 3.21+ and Ninja are required.

cmake --preset default
cmake --build --preset default

The binary lands in build/omcproxy. Run it as root with one or more proxy specs, first interface is the upstream:

omcproxy [-v] <uplink>,<downlink>[,<downlink>...][,scope=<scope>][,strict]

With strict, a downstream interface only receives forwarded traffic while this proxy is the elected IGMP/MLD querier on it, as RFC 4605 suggests for LANs with more than one proxy. The default is to keep forwarding even after losing the election, which is the safe choice when another device (such as a snooping switch) sends queries but does not forward multicast itself.

The kernel must support PIM on the multicast routing sockets (CONFIG_IP_PIMSM_V1 or CONFIG_IP_PIMSM_V2, and CONFIG_IPV6_PIMSM_V2). Common distribution kernels enable these options. OpenWrt's generic kernel configuration disables IPv4 PIM, so OpenWrt needs a custom kernel configuration that enables the options. omcproxy uses PIM mode to receive wrong-interface upcalls for any arrival interface, which it needs to recover forwarding when a spoofed packet created a multicast route with the wrong parent. Startup fails when the kernel lacks this support.

Testing

ctest --preset default # unit tests
ctest --preset netns # integration tests in network namespaces

The netns tests need unprivileged user namespaces (or root). The asan preset builds with AddressSanitizer and UndefinedBehaviorSanitizer and has matching asan and netns-asan test presets. The fuzz preset builds build-fuzz/test/fuzz_gmp, a libFuzzer target for the packet parsers (requires clang).

About

IGMPv3/MLDv2 Proxy for Linux routers (modernized fork of openwrt/omcproxy)

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

omcproxy - IGMPv3 and MLDv2 proxy

omcproxy is an IGMPv3 and MLDv2 multicast proxy for Linux routers. This is my personal fork of openwrt/omcproxy, which in turn is partly based on Oryon/pimbd.

It runs on my Linux PC router at home to make Hikari-TV work reliably in a dedicated IPTV VLAN.

Background

NTT's Hikari-TV uses IPv6 multicast to deliver IPTV streams efficiently. In theory this is beautiful and how the internet is supposed to work - finally someone going all-in on IPv6 and even the exotic stuff like multicast.

In practice though, no one seems to implement the functionality to handle IPv6 multicast in a home network and internet connection correctly. ;) omcproxy was the only software I could find that actually worked, and with a few patches here and there, the incident reports from my wife about the TV not working eventually stopped.

Multicast Routing

Linux does not route or forward multicast frames across interfaces (such as between the upstream WAN and my local LAN) by default. Even if we "simply" set up a few static routes e.g. via smcroute, it wouldn't work, because NTT's routers only start sending us the multicast traffic after we join the group and regularly refresh the membership.

An MLDv2-aware proxy daemon is thus required to relay MLD Membership Reports from the proprietary set-top box to NTT's multicast routers, and forward the incoming IPv6 multicast payloads downstream.

Why use a separate VLAN?

Once I got the traffic flow working on my router and the TV showing the channels, I hit the next issue: My Mikrotik switches (with SwOS) and my TP-Link Deco APs don't support MLDv2, and even my LANCOM switches had some strange bugs in their implementation. This leads to traffic being dropped, or broadcast to all ports, which is especially fun when it hits and overwhelms the Wi-Fi. The easiest fix was to put the multicast traffic on a separate VLAN and carefully thread it through to only hit the ethernet port on the switch where the STB is connected.

Features

  1. Source-Specific Multicast Querier

    • MLDv2 querier (based on RFC 3810)
    • IGMPv3 querier (based on RFC 3376)
  2. Multicast Proxying (based on RFC 4605)

    • Kernel-space multicast routing
    • Multiple instances support
    • Address-scope specific proxying

Scope

omcproxy forwards multicast data in one direction: from the upstream interface to downstream interfaces with matching subscriptions. Membership signaling from downstream hosts is aggregated and proxied to the upstream network as the RFC 4605 host portion. Multicast data that originates on a downstream interface is not forwarded, neither to the upstream interface nor to sibling downstream interfaces; such flows get an empty kernel route so that they do not generate repeated cache-miss notifications. This is a deliberate limitation: the target use case is receiving multicast services (such as IPTV) from an upstream network, where the upstream provider drops customer-originated multicast anyway.

Changes in this fork

  • Rewritten in modern C23, clang-formatted to Chromium style, zero clang-tidy warnings.
  • No external dependencies anymore: libubox is replaced by a small epoll and timerfd event loop and a vendored intrusive list header.
  • Merged the IGMPv3 and MLDv2 wire codecs into one shared, unit-tested, fuzz-tested implementation.
  • Added a whole bunch of unit tests, network-namespace integration tests, sanitizer builds, a libFuzzer harness for the packet parsers. Enabled strict compiler warnings and fixed all the findings.
  • Many bug fixes and lots of hardening; see the git history for details.

Building

CMake 3.21+ and Ninja are required.

cmake --preset default
cmake --build --preset default

The binary lands in build/omcproxy. Run it as root with one or more proxy specs, first interface is the upstream:

omcproxy [-v] <uplink>,<downlink>[,<downlink>...][,scope=<scope>][,strict]

With strict, a downstream interface only receives forwarded traffic while this proxy is the elected IGMP/MLD querier on it, as RFC 4605 suggests for LANs with more than one proxy. The default is to keep forwarding even after losing the election, which is the safe choice when another device (such as a snooping switch) sends queries but does not forward multicast itself.

The kernel must support PIM on the multicast routing sockets (CONFIG_IP_PIMSM_V1 or CONFIG_IP_PIMSM_V2, and CONFIG_IPV6_PIMSM_V2). Common distribution kernels enable these options. OpenWrt's generic kernel configuration disables IPv4 PIM, so OpenWrt needs a custom kernel configuration that enables the options. omcproxy uses PIM mode to receive wrong-interface upcalls for any arrival interface, which it needs to recover forwarding when a spoofed packet created a multicast route with the wrong parent. Startup fails when the kernel lacks this support.

Testing

ctest --preset default # unit tests
ctest --preset netns # integration tests in network namespaces

The netns tests need unprivileged user namespaces (or root). The asan preset builds with AddressSanitizer and UndefinedBehaviorSanitizer and has matching asan and netns-asan test presets. The fuzz preset builds build-fuzz/test/fuzz_gmp, a libFuzzer target for the packet parsers (requires clang).

About

IGMPv3/MLDv2 Proxy for Linux routers (modernized fork of openwrt/omcproxy)

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

omcproxy - IGMPv3 and MLDv2 proxy

omcproxy is an IGMPv3 and MLDv2 multicast proxy for Linux routers. This is my personal fork of openwrt/omcproxy, which in turn is partly based on Oryon/pimbd.

It runs on my Linux PC router at home to make Hikari-TV work reliably in a dedicated IPTV VLAN.

Background

NTT's Hikari-TV uses IPv6 multicast to deliver IPTV streams efficiently. In theory this is beautiful and how the internet is supposed to work - finally someone going all-in on IPv6 and even the exotic stuff like multicast.

In practice though, no one seems to implement the functionality to handle IPv6 multicast in a home network and internet connection correctly. ;) omcproxy was the only software I could find that actually worked, and with a few patches here and there, the incident reports from my wife about the TV not working eventually stopped.

Multicast Routing

Linux does not route or forward multicast frames across interfaces (such as between the upstream WAN and my local LAN) by default. Even if we "simply" set up a few static routes e.g. via smcroute, it wouldn't work, because NTT's routers only start sending us the multicast traffic after we join the group and regularly refresh the membership.

An MLDv2-aware proxy daemon is thus required to relay MLD Membership Reports from the proprietary set-top box to NTT's multicast routers, and forward the incoming IPv6 multicast payloads downstream.

Why use a separate VLAN?

Once I got the traffic flow working on my router and the TV showing the channels, I hit the next issue: My Mikrotik switches (with SwOS) and my TP-Link Deco APs don't support MLDv2, and even my LANCOM switches had some strange bugs in their implementation. This leads to traffic being dropped, or broadcast to all ports, which is especially fun when it hits and overwhelms the Wi-Fi. The easiest fix was to put the multicast traffic on a separate VLAN and carefully thread it through to only hit the ethernet port on the switch where the STB is connected.

Features

  1. Source-Specific Multicast Querier

    • MLDv2 querier (based on RFC 3810)
    • IGMPv3 querier (based on RFC 3376)
  2. Multicast Proxying (based on RFC 4605)

    • Kernel-space multicast routing
    • Multiple instances support
    • Address-scope specific proxying

Scope

omcproxy forwards multicast data in one direction: from the upstream interface to downstream interfaces with matching subscriptions. Membership signaling from downstream hosts is aggregated and proxied to the upstream network as the RFC 4605 host portion. Multicast data that originates on a downstream interface is not forwarded, neither to the upstream interface nor to sibling downstream interfaces; such flows get an empty kernel route so that they do not generate repeated cache-miss notifications. This is a deliberate limitation: the target use case is receiving multicast services (such as IPTV) from an upstream network, where the upstream provider drops customer-originated multicast anyway.

Changes in this fork

  • Rewritten in modern C23, clang-formatted to Chromium style, zero clang-tidy warnings.
  • No external dependencies anymore: libubox is replaced by a small epoll and timerfd event loop and a vendored intrusive list header.
  • Merged the IGMPv3 and MLDv2 wire codecs into one shared, unit-tested, fuzz-tested implementation.
  • Added a whole bunch of unit tests, network-namespace integration tests, sanitizer builds, a libFuzzer harness for the packet parsers. Enabled strict compiler warnings and fixed all the findings.
  • Many bug fixes and lots of hardening; see the git history for details.

Building

CMake 3.21+ and Ninja are required.

cmake --preset default
cmake --build --preset default

The binary lands in build/omcproxy. Run it as root with one or more proxy specs, first interface is the upstream:

omcproxy [-v] <uplink>,<downlink>[,<downlink>...][,scope=<scope>][,strict]

With strict, a downstream interface only receives forwarded traffic while this proxy is the elected IGMP/MLD querier on it, as RFC 4605 suggests for LANs with more than one proxy. The default is to keep forwarding even after losing the election, which is the safe choice when another device (such as a snooping switch) sends queries but does not forward multicast itself.

The kernel must support PIM on the multicast routing sockets (CONFIG_IP_PIMSM_V1 or CONFIG_IP_PIMSM_V2, and CONFIG_IPV6_PIMSM_V2). Common distribution kernels enable these options. OpenWrt's generic kernel configuration disables IPv4 PIM, so OpenWrt needs a custom kernel configuration that enables the options. omcproxy uses PIM mode to receive wrong-interface upcalls for any arrival interface, which it needs to recover forwarding when a spoofed packet created a multicast route with the wrong parent. Startup fails when the kernel lacks this support.

Testing

ctest --preset default # unit tests
ctest --preset netns # integration tests in network namespaces

The netns tests need unprivileged user namespaces (or root). The asan preset builds with AddressSanitizer and UndefinedBehaviorSanitizer and has matching asan and netns-asan test presets. The fuzz preset builds build-fuzz/test/fuzz_gmp, a libFuzzer target for the packet parsers (requires clang).

About

IGMPv3/MLDv2 Proxy for Linux routers (modernized fork of openwrt/omcproxy)

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages