Git Product home page Git Product logo

pim6sd's Introduction

PIM-SM/SSM IPv6 Multicast Routing for UNIX

pim6sd is an IPv6 Protocol Independent Multicast routing daemon, which supports both Any-Source as well as Source-Specific Multicast, also known as PIM-SM and PIM-SSM.

pim6sd stems from pim6dd, which was originally based on pimd, which in turn was based on mrouted.

Note: pim6sd currently requires a configuration file to start.

Troubleshooting

Having successfully built pim6sd (see below), starting it for the first time might be confusing:

  • What happened?
  • Where to look for status?
  • Why isn't it routing?

First of all, pim6sd is a UNIX daemon. By default it starts in the background and only logs warnings and errors to syslog.

Second, you might want to start it in debug mode, with a reduced .conf file. See the pim6sd.conf.sample and pim6sd.conf(5) man page for help.

cp pim6sd.conf.sample pim6sd.conf
sudo pim6sd -f pim6sd.conf -n -d all

This starts pim6sd with the local pim6sd.conf in the foreground, enabling all debug messages. When running in the foreground the debug messages are shown (unthrottled) in the same terminal. Periodically the state of interfaces and routing tables are shown in this debug log.

To see pim6sd status when running in the background, send SIGUSR1 to the PID, it is saved in /var/run/pim6sd.pid when the daemon has started successfully. The status is found in /var/run/pim6sd.dump. You can also use the pim6stat script, which does all this for you.

The single most common problem when dealing with multicast routing is the TTL of the multicast to be routed. If the TTL is 1 the data will be dropped by the kernel -- this is not a problem of pim6sd.

Another problem, which perhaps is not as common, is systems with lots of interfaces. The kernel multicast routing stack is (usually) limited to MAX 32 "virtual" interfaces. These "VIFs" are enumerated by the daemon at startup based on either the contents of the pim6sd.conf or querying the kernel for available interfaces. Should you run into problems with this, use the following construct in your .conf file to ensure multicast routing is only enabled between your foo and bar interfaces:

default_phyint_status disable;
phyint foo enable;
phyint bar enable;

More helpful tips and information is available in the man pages:

  • pim6sd(8)
  • pim6sd.conf(5)

Build & Install

The configure script and Makefile supports de facto standard options such as --prefix=PATH. E.g., to install pim6sd to /usr instead of the default /usr/local, with /etc for .conf file(s) and /var for PID and status dump files:

./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var
make
sudo make install-strip

Building from GIT

If you want to contribute, or simply just try out the latest but unreleased features, then you need to know a few things about the [GNU build system][buildsystem]:

  • configure.ac and a per-directory Makefile.am are key files
  • configure and Makefile.in are generated from autogen.sh
  • Makefile is generated by configure script

To build from GIT you first need to clone the repository and run the autogen.sh script. This requires automake and autoconf to be installed on your system.

git clone https://github.com/troglobit/pim6sd.git
cd pim6sd/
./autogen.sh
./configure && make
sudo make install-strip

GIT sources are a moving target and are not recommended for production systems, unless you know what you are doing!

Origin & References

This project was forked from mcast-tools to focus on pim6sd only.

pim6sd's People

Contributors

austinpayne avatar lemmi avatar leoplo avatar t-x avatar troglobit avatar yoshfuji avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

pim6sd's Issues

Protocol not available

Runneng with archlinux:

pim6sd: 18:53:33.417 warning - setsockopt(IPV6_ROUTER_ALERT): Protocol not available

Kernel: 5.4.24-rt15-2-rt

Chokes on bridge interface

From what I can tell pim6sd chokes on a bridge interface. Not sure that is the symptom, I can't really tell.

# strace -s 128 ./src/pim6sd -d all -c ../pim6sd.conf
[...]
sendto(4, "<31>Apr 30 04:05:14 pim6sd[11705]: br-lan comes up ,vif #5 now in service", 73, MSG_NOSIGNAL, NULL, 0) = 73
setsockopt(6, SOL_IPV6, IPV6_ADD_MEMBERSHIP, {inet_pton(AF_INET6, "ff02::d", &ipv6mr_multiaddr), ipv6mr_interface=if_nametoindex("br-lan")}, 20) = 0
setsockopt(5, SOL_IPV6, IPV6_ADD_MEMBERSHIP, {inet_pton(AF_INET6, "ff02::2", &ipv6mr_multiaddr), ipv6mr_interface=if_nametoindex("br-lan")}, 20) = 0
--- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=NULL} ---
+++ killed by SIGSEGV +++
Segmentation fault

I'm not sure how to create a debug build, so if you could provide instructions I will be able to collect a more complete backtrace.

Starting program: /usr/src/pim6sd/src/pim6sd -d all -c ../pim6sd.conf
debug level 0xffffffffffffffff (mld_proto,mld_timer,mld_member,switch,trace,timeout,pkt,interfaces,kernel,cache,rsrr,pim_detail,pim_hello,pim_register,pim_join_prune,pim_bootstrap,pim_asserts,pim_cand_rp,pim_routes,pim_timers,pim_rpf)

Program received signal SIGSEGV, Segmentation fault.
0x000055555556062e in make_mld6_msg (dst=0x0, alert=1, datalen=<optimized out>, delay=10000, ifindex=<optimized out>, group=<optimized out>, src=0x5555555da6f8, code=0, type=130)
    at mld6.c:562
562			    cmsgp->cmsg_len = CMSG_LEN(hbhlen);
(gdb) bt full
#0  0x000055555556062e in make_mld6_msg (dst=0x0, alert=1, datalen=<optimized out>, delay=10000, ifindex=<optimized out>, group=<optimized out>, src=0x5555555da6f8, code=0, type=130) at mld6.c:562
        currentlen = <optimized out>
        hbhbuf = <optimized out>
        optp = 0x0
        cmsgp = <optimized out>
        mhp = <optimized out>
        ctllen = 64
        hbhlen = 8
        mhp = <optimized out>
        ctllen = <optimized out>
        hbhlen = <optimized out>
        __a = <optimized out>
        cmsgp = <optimized out>
        pktinfo = <optimized out>
        currentlen = <optimized out>
        hbhbuf = <optimized out>
        optp = <optimized out>
#1  send_mld6 (type=type@entry=130, code=code@entry=0, src=0x5555555da6f8, dst=dst@entry=0x0, group=<optimized out>, index=5, delay=10000, datalen=0, alert=1) at mld6.c:614
        dstp = <optimized out>
#2  0x0000555555560c8e in query_groups (v=v@entry=0x5555555888e0 <uvifs+2240>) at mld6_proto.c:154
        ret = <optimized out>
#3  0x00005555555748a8 in start_vif (vifi=vifi@entry=5) at vif.c:387
        v = 0x5555555888e0 <uvifs+2240>
#4  0x0000555555574988 in start_all_vifs () at vif.c:315
        vifi = 5
        v = 0x5555555888e0 <uvifs+2240>
        action = <optimized out>
#5  0x000055555555673c in main (argc=<optimized out>, argv=<optimized out>) at main.c:445
        dummy = <optimized out>
        dummysigalrm = 32767
        fp = <optimized out>
        tv = {tv_sec = 140737488348116, tv_usec = 140737354129665}
        difftime = <optimized out>
        curtime = {tv_sec = 140733193388032, tv_usec = 140737353953944}
        lasttime = <optimized out>
        timeout = <optimized out>
        rfds = {fds_bits = {140737353953704, 140737353608743, 1700966438, 140737488348480, 26577600, 140737488348320, 140737488348304, 140737488348120, 140737354131288, 1, 0, 0, 1, 1700966438, 140737354132160, 140737488348472}}
        readers = {fds_bits = {140737354131248, 0, 140737488348528, 140737354003295, 0, 140737488348528, 0, 0, 0, 140737354131248, 140737353608743, 0, 140737488348304, 140737488348320, 140737354132160, 0}}
        nfds = 0
        n = <optimized out>
        i = <optimized out>
        secs = <optimized out>
        sa = {__sigaction_handler = {sa_handler = 0x0, sa_sigaction = 0x0}, sa_mask = {__val = {0, 4294967295, 0, 140737353953896, 140737354131248, 0, 0, 0, 0, 0, 0, 0, 5, 140737488348728, 140737488348776, 140737488348528}}, sa_flags = -134225520, sa_restorer = 0x0}
        d = <optimized out>
        c = <optimized out>
        tmpd = <optimized out>

For reference, br-lan looks like this

# ip -d a show dev br-lan
5: br-lan: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 00:0d:b9:49:cc:f9 brd ff:ff:ff:ff:ff:ff promiscuity 0 minmtu 68 maxmtu 65535 
    bridge forward_delay 1500 hello_time 200 max_age 2000 ageing_time 30000 stp_state 0 priority 32768 vlan_filtering 0 vlan_protocol 802.1Q bridge_id 8000.0:d:b9:49:cc:f9 designated_root 8000.0:d:b9:49:cc:f9 root_port 0 root_path_cost 0 topology_change 0 topology_change_detected 0 hello_timer    0.00 tcn_timer    0.00 topology_change_timer    0.00 gc_timer  234.90 vlan_default_pvid 1 vlan_stats_enabled 0 group_fwd_mask 0 group_address 01:80:c2:00:00:00 mcast_snooping 1 mcast_router 1 mcast_query_use_ifaddr 0 mcast_querier 0 mcast_hash_elasticity 4 mcast_hash_max 512 mcast_last_member_count 2 mcast_startup_query_count 2 mcast_last_member_interval 100 mcast_membership_interval 26000 mcast_querier_interval 25500 mcast_query_interval 12500 mcast_query_response_interval 1000 mcast_startup_query_interval 3124 mcast_stats_enabled 0 mcast_igmp_version 2 mcast_mld_version 1 nf_call_iptables 0 nf_call_ip6tables 0 nf_call_arptables 0 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535 
    inet 172.23.42.126/26 brd 172.23.42.127 scope global br-lan
       valid_lft forever preferred_lft forever
    inet6 2003:d4:bf10:402::1/64 scope global dynamic noprefixroute 
       valid_lft 14218sec preferred_lft 1618sec
    inet6 fd42:23:42:100::1/64 scope global 
       valid_lft forever preferred_lft forever
    inet6 fe80::846a:6ff:fec9:1426/64 scope link 
       valid_lft forever preferred_lft forever

segfault after ~5 seconds if an interface has no carrier

With current master (c3e2cab) I get a segfault after about 5 seconds if one of the two interfaces I have enabled in the pim6.conf has no carrier.

My pim6sd.conf looks like this:

default_phyint_status disable;
phyint ip6gre1 enable;
phyint pim-veth0 enable;

And "ip address *" like this:

$ ip a show dev ip6gre1
134: ip6gre1@NONE: (POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP) mtu 1448 qdisc noqueue state UNKNOWN group default qlen 1000
    link/gre6 2001:67c:2d50:0:7e76:35ff:fe14:e6d7 peer 2001:67c:2ed8:0:217:f2ff:fe93:66c9
    inet6 fd5c:725:2841::2/64 scope global
       valid_lft forever preferred_lft forever
    inet6 fe80::2c72:92ff:fe13:7098/64 scope link
       valid_lft forever preferred_lft forever
$ ip a show dev pim-veth0
128: pim-veth0@if127: (NO-CARRIER,BROADCAST,MULTICAST,UP) mtu 1500 qdisc noqueue state LOWERLAYERDOWN group default qlen 1000
    link/ether 32:dc:c7:8a:ac:2d brd ff:ff:ff:ff:ff:ff link-netns pim6test0

(< and > replaced with "()")

pim-veth0 has NO-CARRIER because I haven't set the interface pim-veth1, which sits in a different network namespace, up yet.

gdb output:

$ gdb --args ./src/pim6sd -n -f pim6sd.conf
GNU gdb (Debian 8.2.1-2) 8.2.1
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
.
Find the GDB manual and other documentation resources online at:
    .

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./src/pim6sd...done.
(gdb) run
Starting program: /home/linus/dev-priv/pim6sd/src/pim6sd -n -f pim6sd.conf
pim6sd: 16:40:37.907 warning - setsockopt(IPV6_ROUTER_ALERT): Protocol not available
pim6sd: 16:40:37.908 warning - Not registering detected interface lo: Operation not permitted
pim6sd: 16:40:37.908 warning - Not registering detected interface wwp0s20f0u6: Operation not permitted
pim6sd: 16:40:37.908 warning - Not registering detected interface wlp61s0: Operation not permitted
pim6sd: 16:40:37.908 warning - Not registering detected interface wlp61s0: Operation not permitted
pim6sd: 16:40:37.908 warning - Not registering detected interface wlp61s0: Operation not permitted
pim6sd: 16:40:37.908 warning - Not registering detected interface br0: Operation not permitted
pim6sd: 16:40:37.908 warning - Not registering detected interface vmtap0: Operation not permitted
pim6sd: 16:40:37.908 warning - Not registering detected interface vmtap1: Operation not permitted
pim6sd: 16:40:37.908 warning - Not registering detected interface vmtap25: Operation not permitted
pim6sd: 16:40:37.908 warning - Not registering detected interface vmtap5: Operation not permitted
pim6sd: 16:40:37.908 warning - Not registering detected interface vmtap2: Operation not permitted
pim6sd: 16:40:37.908 warning - Not registering detected interface vmtap15: Operation not permitted
pim6sd: 16:40:37.908 warning - Not registering detected interface vmtap3: Operation not permitted
pim6sd: 16:40:37.908 warning - Not registering detected interface vmtap4: Operation not permitted
pim6sd: 16:40:37.908 warning - Not registering detected interface vmtap10: Operation not permitted
pim6sd: 16:40:37.908 warning - Not registering detected interface vmtap20: Operation not permitted
pim6sd: 16:40:37.908 warning - Not registering detected interface vmtap16: Operation not permitted
pim6sd: 16:40:37.908 warning - Not registering detected interface vmtap17: Operation not permitted
pim6sd: 16:40:37.908 warning - Not registering detected interface vmtap26: Operation not permitted
pim6sd: 16:40:37.908 warning - Not registering detected interface vmtap18: Operation not permitted
pim6sd: 16:40:37.908 warning - Not registering detected interface vmtap27: Operation not permitted
pim6sd: 16:40:37.908 warning - Not registering detected interface vmtap19: Operation not permitted
pim6sd: 16:40:37.908 warning - Not registering detected interface vmtap28: Operation not permitted
pim6sd: 16:40:37.908 warning - Not registering detected interface vmtap29: Operation not permitted
pim6sd: 16:40:37.909 warning - Not registering detected interface vmtap6: Operation not permitted
pim6sd: 16:40:37.909 warning - Not registering detected interface vmtap7: Operation not permitted
pim6sd: 16:40:37.909 warning - Not registering detected interface vmtap8: Operation not permitted
pim6sd: 16:40:37.909 warning - Not registering detected interface vmtap9: Operation not permitted
pim6sd: 16:40:37.909 warning - Not registering detected interface vmtap11: Operation not permitted
pim6sd: 16:40:37.909 warning - Not registering detected interface vmtap12: Operation not permitted
pim6sd: 16:40:37.909 warning - Not registering detected interface vmtap13: Operation not permitted
pim6sd: 16:40:37.909 warning - Not registering detected interface vmtap14: Operation not permitted
pim6sd: 16:40:37.909 warning - Not registering detected interface vmtap21: Operation not permitted
pim6sd: 16:40:37.909 warning - Not registering detected interface vmtap22: Operation not permitted
pim6sd: 16:40:37.909 warning - Not registering detected interface vmtap23: Operation not permitted
pim6sd: 16:40:37.909 warning - Not registering detected interface vmtap24: Operation not permitted
pim6sd: 16:40:37.909 warning - Not registering detected interface vmbr0: Operation not permitted
pim6sd: 16:40:37.909 warning - Not registering detected interface vmbr1: Operation not permitted

Program received signal SIGSEGV, Segmentation fault.
0x0000555555575840 in start_vif (vifi=vifi@entry=1) at vif.c:370
370                     v->uv_querier->al_addr = v->uv_linklocal->pa_addr;
(gdb) bt
#0  0x0000555555575840 in start_vif (vifi=vifi@entry=1) at vif.c:370
#1  0x00005555555765e0 in check_vif_state () at vif.c:679
#2  0x0000555555572ab3 in age_vifs () at timer.c:224
#3  0x0000555555560a19 in timer (i=) at main.c:695
#4  0x00005555555571da in age_callout_queue (elapsed_time=) at callout.c:130
#5  0x0000555555556cad in main (argc=, argv=) at main.c:642
(gdb) bt full
#0  0x0000555555575840 in start_vif (vifi=vifi@entry=1) at vif.c:370
        v = 0x555555589200 
#1  0x00005555555765e0 in check_vif_state () at vif.c:679
        checking_vifs = 1
        v = 0x555555589200 
        ifr = {ifr_ifrn = {ifrn_name = "pim-veth0\000\000\000\000\000\000"}, ifr_ifru = {ifru_addr = {sa_family = 4099, sa_data = "\000\000\000\000\000\000\064gWUUU\000"}, ifru_dstaddr = {sa_family = 4099,
              sa_data = "\000\000\000\000\000\000\064gWUUU\000"}, ifru_broadaddr = {sa_family = 4099, sa_data = "\000\000\000\000\000\000\064gWUUU\000"}, ifru_netmask = {sa_family = 4099,
              sa_data = "\000\000\000\000\000\000\064gWUUU\000"}, ifru_hwaddr = {sa_family = 4099, sa_data = "\000\000\000\000\000\000\064gWUUU\000"}, ifru_flags = 4099, ifru_ivalue = 4099, ifru_mtu = 4099,
            ifru_map = {mem_start = 4099, mem_end = 93824992372532, base_addr = 3432, irq = 0 '\000', dma = 0 '\000', port = 0 '\000'}, ifru_slave = "\003\020\000\000\000\000\000\000\064gWUUU\000",
            ifru_newname = "\003\020\000\000\000\000\000\000\064gWUUU\000", ifru_data = 0x1003 }}
        vifi = 1
#2  0x0000555555572ab3 in age_vifs () at timer.c:224
        vifi = 
        v = 
        next_nbr = 
        curr_nbr = 
#3  0x0000555555560a19 in timer (i=) at main.c:695
No locals.
#4  0x00005555555571da in age_callout_queue (elapsed_time=) at callout.c:130
        ptr = 0x55555558fe40
        expQ = 0x55555558fe40
#5  0x0000555555556cad in main (argc=, argv=) at main.c:642
        dummy = 0
        dummysigalrm = 14
        fp = 
        tv = {tv_sec = 0, tv_usec = 487896}
        difftime = {tv_sec = 1, tv_usec = 178997}
        curtime = {tv_sec = 1556980843, tv_usec = 88486}
        lasttime = {tv_sec = 1556980843, tv_usec = 88486}
        timeout = 
        rfds = {fds_bits = {16, 0 }}
        readers = {fds_bits = {48, 0 }}
        nfds = 6
        n = 
        i = 
        secs = 
        sa = {__sigaction_handler = {sa_handler = 0x555555560a50 , sa_sigaction = 0x555555560a50 }, sa_mask = {__val = {0 }}, sa_flags = 0, sa_restorer = 0x0}
        d = 
        c = 
        tmpd = 
(gdb)

RP-Set not refreshing / vanishing PIM bootstrap

When I initially start pim6sd and receive a PIM bootstrap message (or via a PIM Hello option?), the RP-Set is populated just fine:

01:55:06.111 no group_prefix was specified
01:55:06.111 Local BSR address: fd5c:725:2841::2
01:55:06.111 Local BSR priority : 0
01:55:06.111 Local BSR period is : 0 sec.
01:55:06.112 Local BSR hash mask length: 0
01:55:06.162 skip the existing address
---------------------------RP-Set----------------------------
Current BSR address: fd5c:725:2841::1 Prio: 0 Timeout: 155
RP-address(Upstream)/Group prefix             Prio Hold Age
fd5c:725:2841::1(fe80::1%ip6gre1)
     ff00::/8                                 0    150  145

However when receiving the next bootstrap message, pim6sd reports some issues:

01:56:00.468 NETLINK: ask path to fd5c:725:2841::1
01:56:00.468 warning - NETLINK: ifindex=4, but no vif
01:56:00.468 receive_pim6_bootstrap: can't find a route to the BSR(fd5c:725:2841::1)

Trying to ping this IPv6 Unique Local Address works just fine though:

$ ping6 fd5c:725:2841::1
PING fd5c:725:2841::1(fd5c:725:2841::1) 56 data bytes
64 bytes from fd5c:725:2841::1: icmp_seq=1 ttl=64 time=165 ms
64 bytes from fd5c:725:2841::1: icmp_seq=2 ttl=64 time=184 ms
^C
--- fd5c:725:2841::1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 3ms
rtt min/avg/max/mdev = 164.666/174.281/183.896/9.615 ms

Eventually the RP-Set entries time out and the "Current BSR address" is replaced by the zero/unspecified IPv6 address and stays that way even when the next PIM bootstrap message is received:

---------------------------RP-Set----------------------------
Current BSR address: fd5c:725:2841::1 Prio: 0 Timeout: 5
RP-address(Upstream)/Group prefix             Prio Hold Age

01:57:45.419 nothing to do with general-query on router-side, except for querier-election
---------------------------RP-Set----------------------------
Current BSR address: :: Prio: 0 Timeout: 160
RP-address(Upstream)/Group prefix             Prio Hold Age

---------------------------RP-Set----------------------------
Current BSR address: :: Prio: 0 Timeout: 155
RP-address(Upstream)/Group prefix             Prio Hold Age

---------------------------RP-Set----------------------------
Current BSR address: :: Prio: 0 Timeout: 150
RP-address(Upstream)/Group prefix             Prio Hold Age

01:58:00.213 NETLINK: ask path to fd5c:725:2841::1
01:58:00.213 warning - NETLINK: ifindex=4, but no vif
01:58:00.213 receive_pim6_bootstrap: can't find a route to the BSR(fd5c:725:2841::1)
---------------------------RP-Set----------------------------
Current BSR address: :: Prio: 0 Timeout: 145
RP-address(Upstream)/Group prefix             Prio Hold Age

01:58:05.742 skip the existing address

The two interfaces configured in pim6sd.conf look like this:

134: ip6gre1@NONE: (POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP) mtu 1448 qdisc noqueue state UNKNOWN group default qlen 1000
    link/gre6 2001:67c:2d50:0:7e76:35ff:fe14:e6d7 peer 2001:67c:2ed8:0:217:f2ff:fe93:66c9
    inet6 fd5c:725:2841::2/64 scope global 
       valid_lft forever preferred_lft forever
    inet6 fe80::2/64 scope link 
       valid_lft forever preferred_lft forever
142: pim-veth0@if141: (BROADCAST,MULTICAST,UP,LOWER_UP) mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether ae:0d:96:7b:5f:b1 brd ff:ff:ff:ff:ff:ff link-netns pim6test0
    inet6 fe80::ac0d:96ff:fe7b:5fb1/64 scope link 
       valid_lft forever preferred_lft forever

And the bootstrap router (fd5c:725:2841::1) is behind ip6gre1.

The "ifindex=4" in the NETLINK warning looks a bit suspicious. That is the ifindex of my main/wireless interface "wlp61s0". Which has the default routes and provides internet connectivity etc.

phyint management

pim6sd, as pimd and probably other tools, tries to listen on all interfaces it sees by default. I would kindly ask you to revisit that default and only listen to configured interfaces, so I can safely and explicitly decide where to support multicast. This is a default I greatly appreciate in other routing daemons, like bird or babeld.

From my POV It makes little sense to listen on interfaces that are neither access links to client devices nor backbone links where multicast is being forwarded in between.

I currently need to phyint [...] disable 15 interfaces because they're one of

  • lacp hardlinks
  • bridge ports (interfaces enslaved to a bridge)
  • 802.1q trunks
  • management networks
  • loopback interfaces

The way it is now If another interface popped up it would be inadvertently used by pim6sd, whether I liked that or not.

Thanks for your work!

Make ; at end of line in .conf file optional

Currently the pim6sd .conf file parser requires a ; even though most settings end with a newline. To make editing the .conf a bit more "Made Easy" it would be preferable if the parser could also accept newline as a separator for configuration directives. Similar to mrouted, pimd, and smcroute. At least mrouted uses the same type of Yacc/Bison based parser (with the same ancestry).

This may seem like a complicated issue to start with, but the build system takes care of a lot of the problems with running yacc/bison and lex/flex. Most of the work is figuring out how the mrouted parser does it and porting that to pim6sd.

PIM Decapsulation

We noticed last night that some packets were transported within PIM register encapsulation. They are transported successfully to the respective DR but decapsulation and forwarding into the local LAN segment does not seem to be working.

 04:52:58.145133 IP6 (flowlabel 0x0541e, hlim 64, next-header PIM (103) payload length: 112) fd42:23:42:ff01::1 > fd42:23:42:b300::1: PIMv2, length 112
  Register, cksum 0x313c (correct), Flags [ none ]
  IP6 (flowlabel 0x09faf, hlim 16, next-header ICMPv6 (58) payload length: 64) fd42:23:42:b800::1 > ff3e:30:fd42:23:42::1: [icmp6 sum ok] ICMP6, echo request, seq 75
 04:52:58.198919 IP6 (flowlabel 0x61d79, hlim 62, next-header ICMPv6 (58) payload length: 64) fdd5:69d5:c530:1::2 > fd42:23:42:b800::1: [icmp6 sum ok] ICMP6, echo reply, seq 75

@T-X As always, I rely on your input and confirmation of this issue.

No global addresses available

Pim6sd complains about having no global addresses available, the log shows two (on br-lan and br-wifi).

# /usr/src/pim6sd/src/pim6sd -n -f /etc/pim6sd.conf -d all
debug level 0xffffffffffffffff (mld_proto,mld_timer,mld_member,switch,trace,timeout,pkt,interfaces,kernel,cache,rsrr,pim_detail,pim_hello,pim_register,pim_join_prune,pim_bootstrap,pim_asserts,pim_cand_rp,pim_routes,pim_timers,pim_rpf)
15:57:26.173 pim6sd version 2.1.0-alpha23 starting
15:57:26.173 65536 octets allocated for the emit/recept buffer mld6
15:57:26.173 Buffer reception size for socket 4 : 262144 in 0 iterations
15:57:26.174 warning - setsockopt(IPV6_ROUTER_ALERT): Protocol not available
15:57:26.174 65536 octets allocated for the emit/recept buffer pim6
15:57:26.174 Buffer reception size for socket 5 : 262144 in 0 iterations
15:57:26.174 Interfaces world initialized...
15:57:26.174 Getting vifs from /etc/pim6sd.conf
<3>comment [#The timer granularity.] (23)
<3>comment [#More this value is small,more pim6sd will be accurate ] (55)
<3>comment [#default if not specified : 5] (29)
<3>comment [#BE SURE to have to same granularity on ALL routers,] (52)
<3>comment [#otherwise....] (14)
<3>comment [#granularity 5;] (15)
<3>comment [#syntax : phyint <interface> <disable> <metric> [metric] <preference> [preference]] (82)
<3>comment [#metric and pref are for the asserts messages] (45)
<3>comment [#samples :] (10)
<3>default_phyint_status
<3>disable
<3>end cnf [;] (1)
<3>begin phyint [phyint] (6)
<7>br-lan
<9>end phyint [;] (1)
<3>begin phyint [phyint] (6)
<7>br-wifi
<9>end phyint [;] (1)
<3>begin phyint [phyint] (6)
<7>wg-ganymede
<9>end phyint [;] (1)
<3>begin phyint [phyint] (6)
<7>wg-juno
<9>end phyint [;] (1)
<3>comment [#phyint ed1 disable;] (20)
<3>comment [#phyint de0 disable;] (20)
<3>comment [#phyint ed0 disable;] (20)
<3>comment [#phyint gif0 disable;] (21)
<3>comment [#---------------Protocol timer specifications---------------------------#] (73)
<3>comment [#Notes : theses value are the default spec value!] (49)
<3>comment [#do not touch it if you don't know what you do!!] (48)
<3>comment [#you MUST change theses values according to the granularity value!] (66)
<3>comment [#syntax :  'hello_period <number> <coef>'.] (42)
<3>comment [# number is the period in second between 2 hello messages] (57)
<3>comment [# and coef is the coef to determine the hello holdtime=hello_period*coef] (72)
<3>comment [# default if not specified: 30 3.5] (34)
<3>comment [#hello_period 30 3.5;] (21)
<3>comment [#syntax :  'join_prune_period <number> <coef>'.] (47)
<3>comment [# number is the period in second between 2 join/prune messages] (62)
<3>comment [# and coef is the coef to determine the join/prune holdtime=join_prune_period*coef] (82)
<3>comment [# default if not specified : 60 3.5] (35)
<3>comment [#join_prune_period 60 3.5;] (26)
<3>comment [#syntax :  'data_timeout <number>'.] (35)
<3>comment [# number is the time after which (S,G) state for a silent source will be deleted] (80)
<3>comment [# default if not specified  : 210 ] (34)
<3>comment [#data_timeout 210;] (18)
<3>comment [#syntax :  'register_suppression_timeout <number>'.] (51)
<3>comment [# This is the mean interval between receiving a Register-Stop and allowing] (74)
<3>comment [#Register to be send again.] (27)
<3>comment [# default if not specified  : 60] (32)
<3>comment [#register_suppression_timeout 60;] (33)
<3>comment [#syntax :  'probe_time <number>'.] (33)
<3>comment [#This is the time between sending a null Register and the Register-Suppression-Timer] (84)
<3>comment [#expiring unless it is restarted by receiving a Register-Stop.] (62)
<3>comment [#default if not specified : 5] (29)
<3>comment [#probe_time 5;] (14)
<3>comment [#syntax :  'assert_timeout <number>'.] (37)
<3>comment [#this is the interval between the last time an Assert is received and the time at which the ] (92)
<3>comment [#assert is timeout] (18)
<3>comment [#default if not specified : 180] (31)
<3>comment [#assert_timeout 180;] (20)
<3>comment [#syntax : <cand_rp> <interface> <time> [time] <priority> [priority]] (67)
<3>comment [#and time can't be <  10 ] (25)
<3>comment [#you can just type cand_rp, ] (28)
<3>comment [#samples :] (10)
<3>comment [#cand_rp;] (9)
<3>comment [#cand_rp de0;] (13)
<3>comment [#cand_rp ed0 priority 0 time 6;] (31)
<3>comment [#syntax : <group_prefix> <multicast address>/<prefix length>] (60)
<3>comment [#group_prefix ff06::15 ] (23)
<3>comment [#default if not specified : ff00::/8] (36)
<3>comment [#samples:] (9)
<3>comment [#group_prefix ff1e::15/128;] (27)
<3>comment [#group_prefix ff2e::/16;] (24)
<3>comment [#syntax : <cand_bootstrap_router> <interface> <priority> [priority] <time> [time]] (81)
<3>comment [#Typically, you can simply set cand_bootstrap_router for a candidate bootstrap] (78)
<3>comment [#router. All other parameters are optional.] (43)
<3>comment [#the bootstrap period is configurable, BUT the holdtime of a bootstrap] (70)
<3>comment [#router is not in the fields of a bootstrap message : it is hard-coded] (70)
<3>comment [#in the pim6sd include file!] (28)
<3>comment [#So be sure to have a time < PIM_BOOTSTRAP_TIMEOUT (file pimd.h )] (65)
<3>comment [#cand_bootstrap_router de0 priority 15 time 5;] (46)
<3>comment [#syntax : <switch_register_threshold> <rate> [number] <interval> [number]] (73)
<3>comment [#default rate = 50000 interval = 20s] (36)
<3>comment [#samples :] (10)
<3>comment [#TODO : not tested] (18)
<3>comment [#switch_register_threshold rate 54389 interval 45;] (50)
<3>comment [#switch_register_threshold;] (27)
<3>comment [#syntax : <switch_data_threshold> <rate> [number] <interval> [number]] (69)
<3>comment [#default rate = 50000 interval = 20s] (36)
<3>comment [#TODO : not tested] (18)
<3>comment [#samples:] (9)
<3>comment [#switch_data_threshold interval 100 rate 1000;] (46)
<3>comment [#syntax : <default_source_metric> [number]] (42)
<3>comment [#default_source_metric 1243;] (28)
<3>comment [#syntax : <default_source_preference> [number]] (46)
<3>comment [#default_source_preference 123 ;] (32)
parse successed.
15:57:26.177 pim_hello_period set to: 30
15:57:26.177 pim_hello_holdtime set to: 105
15:57:26.177 pim_join_prune_period set to: 60
15:57:26.178 pim_join_prune_holdtime set to: 210
15:57:26.178 timer interval set to: 5
15:57:26.178 PIM data timeout set to: 210
15:57:26.178 PIM register suppression timeout set to: 60
15:57:26.178 PIM register probe time set to: 5
15:57:26.178 PIM assert timeout set to: 180
15:57:26.178 reg_rate_limit set to 100000 (bits/s)
15:57:26.178 reg_rate_interval set to  20 s.
15:57:26.178 data_rate_limit set to 100000 (bits/s)
15:57:26.178 data_rate_interval set to 20 s.
15:57:26.178 Getting vifs from kernel
15:57:26.181 warning - Not registering detected interface lo: Operation not permitted
15:57:26.181 warning - Not registering detected interface lo: Operation not permitted
15:57:26.181 warning - Not registering detected interface enp1s0: Operation not permitted
15:57:26.181 warning - Not registering detected interface enp2s0: Operation not permitted
15:57:26.182 Installing br-lan (2003:d4:bf07:7c02::1 on subnet ::/64) ,as vif #4 - rate = 0
15:57:26.182 Installing br-lan (fd42:23:42:100::1 on subnet ::/64) ,as vif #4 - rate = 0
15:57:26.182 Installing br-lan (fe80::846a:6ff:fec9:1426 on subnet ::/64) ,as vif #4 - rate = 0
15:57:26.182 warning - Not registering detected interface wlp4s0: Operation not permitted
15:57:26.182 Installing br-wifi (2003:d4:bf07:7c03::1 on subnet ::/64) ,as vif #4 - rate = 0
15:57:26.182 Installing br-wifi (fd42:23:42:110::1 on subnet ::/64) ,as vif #4 - rate = 0
15:57:26.182 Installing br-wifi (fe80::dc70:c7ff:fe97:4611 on subnet ::/64) ,as vif #4 - rate = 0
15:57:26.183 warning - Not registering detected interface br-iot: Operation not permitted
15:57:26.183 warning - Not registering detected interface br-mgmt: Operation not permitted
15:57:26.183 warning - Not registering detected interface br-mesh: Operation not permitted
15:57:26.183 warning - Not registering detected interface enp2s0.42: Operation not permitted
15:57:26.183 warning - Not registering detected interface enp2s0.100: Operation not permitted
15:57:26.183 warning - Not registering detected interface enp2s0.120: Operation not permitted
15:57:26.184 warning - Not registering detected interface enp2s0.200: Operation not permitted
15:57:26.184 Installing wg-ganymede (fd42:23:42:ff00::1 on subnet ::/64) ,as vif #4 - rate = 0
15:57:26.184 Installing wg-ganymede (fe80::1 on subnet ::/64) ,as vif #4 - rate = 0
15:57:26.184 Installing wg-juno (fd42:23:42:ff01::1 on subnet ::/64) ,as vif #4 - rate = 0
15:57:26.184 Installing wg-juno (fe80::1 on subnet ::/64) ,as vif #4 - rate = 0
15:57:26.184 warning - Not registering detected interface vnet0: Operation not permitted
15:57:26.185 warning - Not registering detected interface vnet1: Operation not permitted
15:57:26.185 warning - Not registering detected interface ppp0: Operation not permitted
15:57:26.185 warning - Not registering detected interface ppp0: Operation not permitted
15:57:26.185 There's no global address available

segfaults when system has >32 interfaces

On startup I get the following segfault:

$ sudo gdb --args ./src/pim6sd -f ./pim6sd.conf                                                                                                                                     <โ”€(Fri,May03)โ”€โ”˜
GNU gdb (Debian 8.2.1-1) 8.2.1
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
.
Find the GDB manual and other documentation resources online at:
    .

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./src/pim6sd...done.
(gdb) run
Starting program: /home/linus/dev-priv/pim6sd/src/pim6sd -f ./pim6sd.conf
BFD: /usr/lib/debug/.build-id/75/5312dcb2382eb2fde78494879bb2104028ae80.debug: unable to initialize decompress status for section .debug_aranges
BFD: /usr/lib/debug/.build-id/75/5312dcb2382eb2fde78494879bb2104028ae80.debug: unable to initialize decompress status for section .debug_aranges
warning: File "/usr/lib/debug/.build-id/75/5312dcb2382eb2fde78494879bb2104028ae80.debug" has no build-id, file skipped
BFD: /usr/lib/debug/.build-id/55/e7de84df6813c82c5b12822219c17d19c9c4b0.debug: unable to initialize decompress status for section .debug_aranges
BFD: /usr/lib/debug/.build-id/55/e7de84df6813c82c5b12822219c17d19c9c4b0.debug: unable to initialize decompress status for section .debug_aranges
warning: File "/usr/lib/debug/.build-id/55/e7de84df6813c82c5b12822219c17d19c9c4b0.debug" has no build-id, file skipped
pim6sd: 00:44:23.767 warning - setsockopt(IPV6_ROUTER_ALERT): Protocol not available
pim6sd: 00:44:23.768 warning - add_phaddr: found more than one link-local address on ip6gre1
pim6sd: 00:44:23.768 warning - add_phaddr: found more than one link-local address on vmtap20
pim6sd: 00:44:23.768 warning - add_phaddr: found more than one link-local address on vmtap22

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7e6b6e6 in malloc () from /lib/x86_64-linux-gnu/libc.so.6
(gdb) bt
#0  0x00007ffff7e6b6e6 in malloc () from /lib/x86_64-linux-gnu/libc.so.6
#1  0x00007ffff7e5f2fa in open_memstream () from /lib/x86_64-linux-gnu/libc.so.6
#2  0x00007ffff7edab30 in __vsyslog_chk () from /lib/x86_64-linux-gnu/libc.so.6
#3  0x00007ffff7edb09c in syslog () from /lib/x86_64-linux-gnu/libc.so.6
#4  0x000055555555e23e in log_msg (severity=severity@entry=4, syserr=syserr@entry=0, format=format@entry=0x55555557aed8 "add_phaddr: found more than one link-local address on %s") at debug.c:755
#5  0x000055555555cf70 in add_phaddr (v=v@entry=0x55555558d2c0, addr=addr@entry=0x7fffffffe200, mask=mask@entry=0x7fffffffe1f0, rmt=rmt@entry=0x0) at config.c:311
#6  0x000055555555d1be in config_vifs_from_kernel () at config.c:246
#7  0x0000555555576139 in init_vifs () at vif.c:173
#8  0x0000555555556776 in main (argc=, argv=) at main.c:448
(gdb) bt full
#0  0x00007ffff7e6b6e6 in malloc () from /lib/x86_64-linux-gnu/libc.so.6
No symbol table info available.
#1  0x00007ffff7e5f2fa in open_memstream () from /lib/x86_64-linux-gnu/libc.so.6
No symbol table info available.
#2  0x00007ffff7edab30 in __vsyslog_chk () from /lib/x86_64-linux-gnu/libc.so.6
No symbol table info available.
#3  0x00007ffff7edb09c in syslog () from /lib/x86_64-linux-gnu/libc.so.6
No symbol table info available.
#4  0x000055555555e23e in log_msg (severity=severity@entry=4, syserr=syserr@entry=0, format=format@entry=0x55555557aed8 "add_phaddr: found more than one link-local address on %s") at debug.c:755
        ap = {{gp_offset = 32, fp_offset = 48, overflow_arg_area = 0x7fffffffe1a0, reg_save_area = 0x7fffffffe0c0}}
        fmt = "warning - add_phaddr: found more than one link-local address on vmtap22", '\000' 
        msg = 
        now = {tv_sec = 1556837063, tv_usec = 768495}
        thyme = 
#5  0x000055555555cf70 in add_phaddr (v=v@entry=0x55555558d2c0, addr=addr@entry=0x7fffffffe200, mask=mask@entry=0x7fffffffe1f0, rmt=rmt@entry=0x0) at config.c:311
        pa = 0x55555558dc80
        i = 
#6  0x000055555555d1be in config_vifs_from_kernel () at config.c:246
        v = 0x55555558d2c0
        i = 
        addr = {sin6_family = 10, sin6_port = 0, sin6_flowinfo = 0, sin6_addr = {__in6_u = {__u6_addr8 = "\376\200\000\000\000\000\000\000<\t\272\377\376\222\060\\", __u6_addr16 = {33022, 0, 0, 0, 2364, 65466, 
                37630, 23600}, __u6_addr32 = {33022, 0, 4290382140, 1546687230}}}, sin6_scope_id = 1324}
        rmt_addr = {sin6_family = 0, sin6_port = 0, sin6_flowinfo = 0, sin6_addr = {__in6_u = {__u6_addr8 = '\000' , __u6_addr16 = {0, 0, 0, 0, 0, 0, 0, 0}, __u6_addr32 = {0, 0, 0, 0}}}, 
          sin6_scope_id = 0}
        rmt = 
        mask = {__in6_u = {__u6_addr8 = "\377\377\377\377\377\377\377\377\000\000\000\000\000\000\000", __u6_addr16 = {65535, 65535, 65535, 65535, 0, 0, 0, 0}, __u6_addr32 = {4294967295, 4294967295, 0, 0}}}
        flags = 4163
        ifap = 0x5555555e7b40
        ifa = 0x5555555eb350
        __a = 
#7  0x0000555555576139 in init_vifs () at vif.c:173
        vifi = 
        v = 
        enabled_vifs = 0
#8  0x0000555555556776 in main (argc=, argv=) at main.c:448
        dummy = 
        dummysigalrm = 32767
        fp = 
        tv = {tv_sec = 140737488348020, tv_usec = 140737354129665}
        difftime = 
        curtime = {tv_sec = 140733193388032, tv_usec = 140737353953944}
        lasttime = 
        timeout = 
        rfds = {fds_bits = {140737353953704, 140737353514535, 1700966438, 140737488348384, 26577600, 140737488348224, 140737488348208, 140737488348024, 140737354131288, 1, 0, 0, 1, 1700966438, 140737354132160, 
            140737488348376}}
        readers = {fds_bits = {140737354131248, 0, 140737488348432, 140737354003295, 0, 140737488348432, 0, 0, 0, 140737354131248, 140737353514535, 896, 140737488348208, 140737488348224, 140737354132160, 0}}
        nfds = 0
        n = 
        i = 
        secs = 
        sa = {__sigaction_handler = {sa_handler = 0x38000000380, sa_sigaction = 0x38000000380}, sa_mask = {__val = {3848290698112, 4294967295, 3848290698112, 140737353953896, 140737354131248, 0, 0, 0, 0, 0, 0, 
              0, 15775231, 194, 140737488348358, 1}}, sa_flags = -135750363, sa_restorer = 0x0}
        d = 
        c = 
        tmpd = 
(gdb)

Cannot run at the same time as pimd

It looks not possible to run this concurrently with pimd to support a dual-stack multicast routing?

If I try I get an error message and a stop:

cannot enable multicast routing in kernel: Address already in use

Exits after returned mld_type == 0, triggered by received UDP multicast packets

In MLDv2 mode I'm somehow hitting the "if (mld6_recvlen < 0)" check in mld6_read(). Which then results in pim6sd shutting down.

Debugging output when this happens shows:

  • rcvmh.msg_name: fe80::ba:7aff:fedf:406
  • mld_recvlen: 80

The 80 bytes from recvmsg() look like this, where the first one is indeed 0x00:

00 01 01 00 00 00 00 00 fe 80 00 00 00 00 00 00
00 ba 7a ff fe df 04 06 ff 05 00 00 00 00 00 00
00 00 00 00 00 02 10 01 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

With some ebtables blocking I could narrow it down to the following IPv6 UDP packet:

$ tcpdump -x -i eth0 "ip6 src fe80::ba:7aff:fedf:406 and inbound"
01:47:30.028003 IP6 fe80::ba:7aff:fedf:406.56078 > ff05::2:1001.1001: UDP, length 34
        0x0000:  600c 55af 002a 1101 fe80 0000 0000 0000
        0x0010:  00ba 7aff fedf 0406 ff05 0000 0000 0000
        0x0020:  0000 0000 0002 1001 db0e 03e9 002a db12
        0x0030:  4745 5420 6e6f 6465 696e 666f 2073 7461
        0x0040:  7469 7374 6963 7320 6e65 6967 6862 6f75
        0x0050:  7273

udp-mcast2.cap.txt

However this does not seem fully match the previous buffer received from recvmsg()?

So far this somehow looks a bit like a Linux kernel bug to me, as we explicitly set the socket as SOCK_RAW for IPPROTO_ICMPV6, which should exclude UDP.

I'm also wondering if there might be a way to check for ICMPv6 explicitly from what recvmsg() returns to exclude the UDP packet responses. But so far the returned buffer looks like (mostly) garbage?

root@ffhl-pim6-router:~# uname -a
Linux ffhl-pim6-router 6.5.11-8-pve #1 SMP PREEMPT_DYNAMIC PMX 6.5.11-8 (2024-01-30T12:27Z) x86_64 GNU/Linux

Missing pim-join-prune in 3 router setup

Advancing to more interesting setups now, here is an issue for a three router setup, with a client subnet attached to each of them:

pim6sd-3-router

Setup:

In this setup router0, router1 and router2 are running pim6sd. router1 is configured as the bootstrap router and router2 as a rendez-vous point for ff13:23:42:ffff::/64. There is then a multicast listener for ff13:23:42:ffff::123 on client0 and client1. And client2 continuously sends ICMPv6 messages to ff13:23:42:ffff::123.

Issue:

While router1 sends pim-join-prune messages to router2, our RP, just fine router0 does not.

router0 receives seemingly correct bootstrap messages with the RP information:

router0$ tcpdump -i wan0 -n -v -l
tcpdump: listening on wan0, link-type EN10MB (Ethernet), capture size 262144 bytes
18:09:32.921513 IP6 (flowlabel 0x5b502, hlim 1, next-header PIM (103) payload length: 72) fe80::11:22ff:fe00:2 > ff02::d: PIMv2, length 72
        Bootstrap, cksum 0x0f2a (correct) tag=cea5 hashmlen=126 BSRprio=0 BSR=fd5c:725:2841::2 (group0: ff13:23:42:ffff::/64 RPcnt=1 FRPcnt=1 RP0=fd5c:725:2841:1::3,holdtime=2m30s,prio=0)

But does not seem to be able to set the "upstream" in its RP-Set:

router0$ pim6stat
[...]
---------------------------RP-Set----------------------------
Current BSR address: fd5c:725:2841::2 Prio: 0 Timeout: 140
RP-address(Upstream)/Group prefix             Prio Hold Age
fd5c:725:2841:1::3(none)
     ff13:23:42:ffff::/64                     0    150  130

router0 is able to ping both the bootstrap and RP listed just fine (so does not seem to be an issue with unicast routes):

router0$ ping6 -c3 fd5c:725:2841::2 
PING fd5c:725:2841::2(fd5c:725:2841::2) 56 data bytes
64 bytes from fd5c:725:2841::2: icmp_seq=1 ttl=64 time=0.078 ms
64 bytes from fd5c:725:2841::2: icmp_seq=2 ttl=64 time=0.099 ms
64 bytes from fd5c:725:2841::2: icmp_seq=3 ttl=64 time=0.030 ms

--- fd5c:725:2841::2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 48ms
rtt min/avg/max/mdev = 0.030/0.069/0.099/0.028 ms
router0$ ping6 -c3 fd5c:725:2841:1::3
PING fd5c:725:2841:1::3(fd5c:725:2841:1::3) 56 data bytes
64 bytes from fd5c:725:2841:1::3: icmp_seq=1 ttl=63 time=0.149 ms
64 bytes from fd5c:725:2841:1::3: icmp_seq=2 ttl=63 time=0.050 ms
64 bytes from fd5c:725:2841:1::3: icmp_seq=3 ttl=63 time=0.137 ms

--- fd5c:725:2841:1::3 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 54ms
rtt min/avg/max/mdev = 0.050/0.112/0.149/0.044 ms

Reproducer and pim6stat:

https://gist.github.com/T-X/b585768892bda7d652406c71365a2b27

undefined reference to `yywrap'

I've tried building pim6sd on another debian buster machine and it will not link, I'm not sure why. It works, when I try building it in a fresh debian:buster docker container.

  CCLD     pim6sd
/usr/bin/ld: pim6sd-cftoken.o: in function `yylex':
/usr/src/pim6sd/src/cftoken.c:2390: undefined reference to `yywrap'
collect2: error: ld returned 1 exit status

I have installed

  • build-essential
  • autoreconf
  • flex
  • bison
autogen.sh
# ./autogen.sh
autoreconf: Entering directory `.'
autoreconf: configure.ac: not using Gettext
autoreconf: running: aclocal --force --warnings=portability 
autoreconf: configure.ac: tracing
autoreconf: configure.ac: not using Libtool
autoreconf: running: /usr/bin/autoconf --force --warnings=portability
autoreconf: running: /usr/bin/autoheader --force --warnings=portability
autoreconf: running: automake --add-missing --force-missing --warnings=portability
configure.ac:14: installing './compile'
configure.ac:4: installing './install-sh'
configure.ac:4: installing './missing'
src/Makefile.am: installing './depcomp'
configure.ac: installing './ylwrap'
autoreconf: no config.status: cannot re-make
autoreconf: Leaving directory `.'
configure
# ./configure
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /bin/mkdir -p
checking for gawk... no
checking for mawk... mawk
checking whether make sets $(MAKE)... yes
checking whether make supports nested variables... yes
checking whether make supports nested variables... (cached) yes
checking for gcc... gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables... 
checking whether we are cross compiling... no
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
checking whether gcc understands -c and -o together... yes
checking whether make supports the include directive... yes (GNU style)
checking dependency style of gcc... gcc3
checking for bison... bison -y
checking for flex... flex
checking lex output file root... lex.yy
checking lex library... none needed
checking whether yytext is a pointer... no
checking for main in -lfl... no
checking for main in -ll... no
checking for main in -ly... yes
checking how to run the C preprocessor... gcc -E
checking for grep that handles long lines and -e... /bin/grep
checking for egrep... /bin/grep -E
checking for ANSI C header files... yes
checking for sys/types.h... yes
checking for sys/stat.h... yes
checking for stdlib.h... yes
checking for string.h... yes
checking for memory.h... yes
checking for strings.h... yes
checking for inttypes.h... yes
checking for stdint.h... yes
checking for unistd.h... yes
checking arpa/inet.h usability... yes
checking arpa/inet.h presence... yes
checking for arpa/inet.h... yes
checking fcntl.h usability... yes
checking fcntl.h presence... yes
checking for fcntl.h... yes
checking netdb.h usability... yes
checking netdb.h presence... yes
checking for netdb.h... yes
checking netinet/in.h usability... yes
checking netinet/in.h presence... yes
checking for netinet/in.h... yes
checking paths.h usability... yes
checking paths.h presence... yes
checking for paths.h... yes
checking stddef.h usability... yes
checking stddef.h presence... yes
checking for stddef.h... yes
checking for stdlib.h... (cached) yes
checking for string.h... (cached) yes
checking for strings.h... (cached) yes
checking sys/file.h usability... yes
checking sys/file.h presence... yes
checking for sys/file.h... yes
checking sys/ioctl.h usability... yes
checking sys/ioctl.h presence... yes
checking for sys/ioctl.h... yes
checking sys/param.h usability... yes
checking sys/param.h presence... yes
checking for sys/param.h... yes
checking sys/socket.h usability... yes
checking sys/socket.h presence... yes
checking for sys/socket.h... yes
checking sys/time.h usability... yes
checking sys/time.h presence... yes
checking for sys/time.h... yes
checking syslog.h usability... yes
checking syslog.h presence... yes
checking for syslog.h... yes
checking for unistd.h... (cached) yes
checking for sys/types.h... (cached) yes
checking for sys/queue.h... yes
checking for netinet/in.h... (cached) yes
checking for net/if.h... yes
checking for net/if_var.h... no
checking for netinet6/in6_var.h... no
checking for sys/types.h... (cached) yes
checking for netinet6/pim6.h... no
checking for stdbool.h that conforms to C99... yes
checking for _Bool... yes
checking for ANSI C header files... (cached) yes
checking for an ANSI C-conforming const... yes
checking for pid_t... yes
checking return type of signal handlers... void
checking for size_t... yes
checking whether time.h and sys/time.h may both be included... yes
checking whether struct tm is in sys/time.h or time.h... time.h
checking for ANSI C header files... (cached) yes
checking for fcntl.h... (cached) yes
checking for paths.h... (cached) yes
checking stdarg.h usability... yes
checking stdarg.h presence... yes
checking for stdarg.h... yes
checking for sys/file.h... (cached) yes
checking for sys/ioctl.h... (cached) yes
checking for sys/time.h... (cached) yes
checking for syslog.h... (cached) yes
checking for unistd.h... (cached) yes
checking if you have struct mld_hdr in your system... yes
checking for bzero... yes
checking for dup2... yes
checking for gettimeofday... yes
checking for isascii... yes
checking for memset... yes
checking for select... yes
checking for socket... yes
checking for strchr... yes
checking for strdup... yes
checking for strerror... yes
checking for strrchr... yes
checking for strncpy... yes
checking for strlcpy... no
checking for strlcat... no
checking if you have a length field in struct sockaddr*... no
checking if you enabled router-side mldv2... yes
checking if you enabled host-side mldv2... no
checking userland-kernel interface for routing information... netlink
checking for inet6_opt_init in -lc... yes
checking that generated files are newer than configure... done
configure: creating ./config.status
config.status: creating Makefile
config.status: creating man/Makefile
config.status: creating include/Makefile
config.status: creating src/Makefile
config.status: creating include/config.h
config.status: executing depfiles commands

------------------ Summary ------------------
 pim6sd version 2.1.0-beta1
  Prefix................: /usr/local
  Sysconfdir............: /usr/local/etc
  Localstatedir.........: /usr/local/var
  C Compiler............: gcc -g -O2   -ly 

Optional features:
  Router-side MLDv2.....: yes
  Host-side MLDv2.......: no

------------- Compiler version --------------
gcc (Debian 8.3.0-6) 8.3.0
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
---------------------------------------------

Check the above options and compile with:
 make
make
# make -j4
Making all in include
make[1]: Entering directory '/usr/src/pim6sd/include'
make  all-am
make[2]: Entering directory '/usr/src/pim6sd/include'
make[2]: Leaving directory '/usr/src/pim6sd/include'
make[1]: Leaving directory '/usr/src/pim6sd/include'
Making all in src
make[1]: Entering directory '/usr/src/pim6sd/src'
  YACC     cfparse.c
updating cfparse.h
make  all-am
make[2]: Entering directory '/usr/src/pim6sd/src'
  CC       pim6sd-callout.o
  LEX      cftoken.c
  CC       pim6sd-cfparse.o
  CC       pim6sd-config.o
  CC       pim6sd-crc.o
  CC       pim6sd-debug.o
  CC       pim6sd-inet6.o
  CC       pim6sd-kern.o
  CC       pim6sd-main.o
  CC       pim6sd-mld6.o
  CC       pim6sd-mld6_proto.o
  CC       pim6sd-mld6v2.o
  CC       pim6sd-mld6v2_proto.o
  CC       pim6sd-mrt.o
  CC       pim6sd-netlink.o
  CC       pim6sd-routesock.o
  CC       pim6sd-pim6.o
  CC       pim6sd-pim6_proto.o
  CC       pim6sd-route.o
  CC       pim6sd-rp.o
  CC       pim6sd-timer.o
  CC       pim6sd-trace.o
  CC       pim6sd-vif.o
  CC       pim6sd-cftoken.o
  CC       ../lib/strlcpy.o
  CC       ../lib/strlcat.o
  CCLD     pim6sd
/usr/bin/ld: pim6sd-cftoken.o: in function `yylex':
/usr/src/pim6sd/src/cftoken.c:2390: undefined reference to `yywrap'
collect2: error: ld returned 1 exit status
make[2]: *** [Makefile:456: pim6sd] Error 1
make[2]: Leaving directory '/usr/src/pim6sd/src'
make[1]: *** [Makefile:370: all] Error 2
make[1]: Leaving directory '/usr/src/pim6sd/src'
make: *** [Makefile:397: all-recursive] Error 1

Syntax error for interface names with dashes

Hi,

I've just started exploring pim6sd and I noticed that as soon as I add the following line the config parser reports a syntax error:

phyint wg-io disable;

even though the interface exists that way:

613: wg-io: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1412 qdisc noqueue state UNKNOWN group default qlen 1000
    link/none 
    inet 172.23.42.225/31 scope global wg-io
       valid_lft forever preferred_lft forever
    inet6 fd42:23:42:ff00::2/64 scope global 
       valid_lft forever preferred_lft forever
    inet6 fe80::2/64 scope link 
       valid_lft forever preferred_lft forever

This is apparently related to the dash in the interface name, underlines do work.

crash in make_mld6v2_msg with mld6v2

It seems we aren't allocating enough space for the in6_pktinfo structure plus the IP6OPT_ROUTER_ALERT, causing cmsgp to be NULL here, causing a NULL pointer dereference and crash here. This fixes the problem for me:

diff --git a/src/mld6v2.c b/src/mld6v2.c
index 8cd5a4d..6a69593 100644
--- a/src/mld6v2.c
+++ b/src/mld6v2.c
@@ -252,7 +252,7 @@ make_mld6v2_msg(int type, int code, struct sockaddr_in6 *src,
            log_msg(LOG_ERR, 0, "inet6_opt_append(0) failed");
        if ((hbhlen = inet6_opt_finish(NULL, 0, hbhlen)) == -1)
            log_msg(LOG_ERR, 0, "inet6_opt_finish(0) failed");
-       ctllen += CMSG_SPACE(hbhlen);
+       ctllen += CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(hbhlen);
 #else                          /* old advanced API */
        hbhlen = inet6_option_space(sizeof(raopt));
        ctllen += hbhlen;

ssm.conf.sample syntax error

I tried to run pim6sd in SSM mode like this:

root@me:/home/pim6sd# src/pim6sd -f ssm.conf.sample -n -d all
debug level 0xffffffff: mld_proto, mld_timer, mld_member, mld, switch, trace, mtrace, traceroute, timeout, callout, pkt, packets, interfaces, vif, kernel, cache, mfc, k_c
ache, k_mfc, rsrr, pim_detail, pim_hello, pim_neighbors, pim_register, registers, pim_join_prune, pim_j_p, pim_jp, pim_bootstrap, pim_bsr, bsr, bootstrap, pim_asserts, pi
m_cand_rp, pim_c_rp, pim_rp, rp, pim_routes, pim_routing, pim_mrt, pim_timers, pim_rpf, rpf, pim, routes, routing, mrt, routers, mrouters, neighbors, timers, asserts, all
, 3                                                 
15:20:37.382 pim6sd version 2.1.0-beta1 starting                        
15:20:37.385 65536 octets allocated for the emit/recept buffer mld6                                                                                                       
15:20:37.385 Buffer reception size for socket 4 : 262144 in 0 iterations                                                                                                  
15:20:37.386 65536 octets allocated for the emit/recept buffer pim6                                                                                                       
15:20:37.386 Buffer reception size for socket 5 : 262144 in 0 iterations
15:20:37.387 Interfaces world initialized...    
15:20:37.387 Getting vifs from ssm.conf.sample                     
<3>comment [## SSM configuration example] (28)                          
<3>comment [## syntax : phyint <interface> <disable> <metric> [metric] <preference> ] (72)                                                                               
<3>comment [##         [preference] [version <version>]] (43)           
<3>comment [##   metric and pref are for the asserts messages] (49)
<3>comment [#phyint ed1 enable version 1;       # speaks only MLDv1] (49)
<3>comment [#phyint de0 enable version 2;       # speaks only MLDv2] (49)
<3>begin phyint [phyint] (6)                                                              
<7>fxp0                                                      
<9>enable                                                          
<9>version                                                               
ssm.conf.sample 7: syntax error                                          
ssm.conf.sample 7: fatal parse failure: exiting (1 errors)                                
15:20:37.388 fatal error in parsing the config file

I did not modify ssm.conf.sample file. Parsing pim6sd.conf.sample works for me.

Timer accuracy is way off

The accuracy with which timers run is way off. There are times when the seconds pass quite normally and then the timers are stuck for minutes at a time.

This leads to missing MLD queries and therefore missing group joins.

This happens with a granularity of 5. Setting a granularity of 1 leads to much more reasonable timer behaviour.

The hardware this happens on is x86_64 (APU2c4) with Linux 4.19.37.

segfault in age_routes()

While playing with embedded-RP multicast addresses (RFC3956) I stumbled over segmentation fault in age_routes() / timer.c:

$ gdb --core ./core src/pim6sd
GNU gdb (Debian 8.2.1-2) 8.2.1
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
.
Find the GDB manual and other documentation resources online at:
    .

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from src/pim6sd...done.
[New LWP 16228]
Core was generated by `/home/linus/dev-priv/pim6sd/src/pim6sd -d pim_bootstrap pim_join_prune -n -f /t'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  age_routes () at timer.c:680
680                     grpentry_ptr_next = grpentry_ptr->rpnext;
(gdb) bt
#0  age_routes () at timer.c:680
#1  0x000055c687dd792e in timer (i=) at main.c:577
#2  0x000055c687dcdf0a in age_callout_queue (elapsed_time=) at callout.c:130
#3  0x000055c687dcda56 in main (argc=, argv=) at main.c:523
(gdb) l
675
676                 for (grpentry_ptr = rp_grp_entry_ptr->grplink;
677                      grpentry_ptr != (grpentry_t *) NULL;
678                      grpentry_ptr = grpentry_ptr_next)
679                 {
680                     grpentry_ptr_next = grpentry_ptr->rpnext;
681                     mrtentry_grp = grpentry_ptr->grp_route;
682                     mrtentry_srcs = grpentry_ptr->mrtlink;
683
684                     grp_action = PIM_ACTION_NOTHING;
(gdb) bt full
#0  age_routes () at timer.c:680
        cand_rp_ptr = 0x55c68898a380
        grpentry_ptr = 0x2070696b73203a5d
        grpentry_ptr_next = 
        mrtentry_grp = 
        mrtentry_rp = 
        mrtentry_wide = 
        mrtentry_srcs = 
        mrtentry_srcs_next = 
        v = 
        vifi = 
        pim_nbr_ptr = 
        change_flag = 
        rp_action = 0
        grp_action = 
        src_action = 0
        src_action_rp = 0
        dont_calc_action = 
        did_switch_flag = 
        rp_grp_entry_ptr = 0x55c6889d0480
        kernel_cache_ptr = 
        kernel_cache_next = 
        curr_bytecnt = 
        rpentry_ptr = 0x55c688989a80
        update_rp_iif = 0
        update_src_iif = 
        new_pruned_oifs = {ifs_bits = {812540268, 1953853184, 1764586085, 100, 2291994691, 21958, 2279604384, 21958}}
        g = 
        g_next = 
#1  0x000055c687dd792e in timer (i=) at main.c:577
No locals.
#2  0x000055c687dcdf0a in age_callout_queue (elapsed_time=) at callout.c:130
        ptr = 0x55c688989a50
        expQ = 0x55c688989a50
#3  0x000055c687dcda56 in main (argc=, argv=) at main.c:523
        dummy = 0
        dummysigalrm = 14
        fp = 
        tv = {tv_sec = 0, tv_usec = 789179}
        difftime = {tv_sec = 1, tv_usec = 21892}
        curtime = {tv_sec = 1558205981, tv_usec = 133769}
        lasttime = {tv_sec = 1558205981, tv_usec = 133769}
        timeout = 
        rfds = {fds_bits = {32, 0 }}
        readers = {fds_bits = {48, 0 }}
        nfds = 6
        n = 
        i = 
        secs = 1
        sa = {__sigaction_handler = {sa_handler = 0x55c687dd7960 , sa_sigaction = 0x55c687dd7960 }, sa_mask = {__val = {0 }}, sa_flags = 0, sa_restorer = 0x0}
        d = 
        c = 
        ch = -1
(gdb) quit

The core dump file was generated in a setup with three multicast routers. The RP was on the last one which had the pim6sd that crashed.

The crash would happen about 5 seconds after pim6sd was started with the following script to reproduce:

https://gist.github.com/T-X/91a3aa37e5056adac051d767cdf4e2c2

If I try to start pim6sd a second time after the crash it works without issues. So my current guess is that the RP crashes because of receiving a PIM Join/Prune before a PIM Hello from a neighbor or something like that.

I'll dig deeper into what might be causing this.

Code cleanup, test on musl libc using Alpine or Void Linux

@lemmi reports on IRC there are several old anachronisms in the code base (c.f. pimd which already has all this cleaned up).

Here's a build sample from Void Linux

Making all in include
make[1]: Entering directory '/builddir/pim6sd-master/include'
make  all-am
make[2]: Entering directory '/builddir/pim6sd-master/include'
make[2]: Nothing to be done for 'all-am'.
make[2]: Leaving directory '/builddir/pim6sd-master/include'
make[1]: Leaving directory '/builddir/pim6sd-master/include'
Making all in src
make[1]: Entering directory '/builddir/pim6sd-master/src'
make  all-am
make[2]: Entering directory '/builddir/pim6sd-master/src'
  CCLD     pim6sd
/usr/bin/ld: pim6sd-mld6.o: in function `send_mld6':
mld6.c:(.text+0xba4): undefined reference to `inet6_option_init'
/usr/bin/ld: mld6.c:(.text+0xbc6): undefined reference to `inet6_option_append'
/usr/bin/ld: mld6.c:(.text+0xca0): undefined reference to `inet6_option_space'
/usr/bin/ld: pim6sd-mld6v2.o: in function `send_mld6v2':
mld6v2.c:(.text+0x618): undefined reference to `inet6_option_space'
/usr/bin/ld: mld6v2.c:(.text+0x6d3): undefined reference to `inet6_option_init'
/usr/bin/ld: mld6v2.c:(.text+0x6f5): undefined reference to `inet6_option_append'
collect2: error: ld returned 1 exit status
make[2]: *** [Makefile:455: pim6sd] Error 1
make[2]: Leaving directory '/builddir/pim6sd-master/src'
make[1]: *** [Makefile:369: all] Error 2
make[1]: Leaving directory '/builddir/pim6sd-master/src'
make: *** [Makefile:396: all-recursive] Error 1
=> ERROR: pim6sd-2.1.0_1: do_build: '${make_cmd} ${makejobs} ${make_build_args} ${make_build_target}' exited with 2
=> ERROR:   in do_build() at common/build-style/gnu-configure.sh:13

Seg fault when interface is missing link-local address

I'm running into a seg fault on a Raspberry Pi4 when one configured interface is missing a link-local address. It appears to be because the age_vif timer is trying to send out a hello on the interface and then crashing because of bad memory where the address should be.

I've fixed it in a separate branch but I'm not entirely sure if this is right fix (seems like maybe this VIF shouldn't even be getting this far?). If it is, I'm happy to open a PR just let me know.

Host info

pi@r0:pim6sd [fix/eth-no-ipv6-lla] $ uname -a
Linux r0.local 5.4.51-v8+ #1333 SMP PREEMPT Mon Aug 10 16:58:35 BST 2020 aarch64 GNU/Linux
pi@r0:pim6sd [fix/eth-no-ipv6-lla] $ cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 10 (buster)"
NAME="Debian GNU/Linux"
VERSION_ID="10"
VERSION="10 (buster)"
VERSION_CODENAME=buster
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"

GDB output

pi@r0:pim6sd [fix/eth-no-ipv6-lla] $ cat pim6sd.conf
default_phyint_status disable;
phyint eth0 enable;
phyint eth1 enable;
pi@r0:build [fix/eth-no-ipv6-lla] $ sudo gdb --args ./src/pim6sd -f ../pim6sd.conf -n -d all
GNU gdb (Debian 8.2.1-2+b3) 8.2.1
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "aarch64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./src/pim6sd...done.
(gdb) r
Starting program: /home/pi/pim6sd/build/src/pim6sd -f ../pim6sd.conf -n -d all
debug level 0xffffffffffffffff: mld_proto, mld_timer, mld_member, mld, switch, trace, mtrace, traceroute, timeout, callout, pkt, packets, interfaces, vif, kernel, cache, mfc, k_cache, k_mfc, rsrr, pim_detail, pim_hello, pim_neighbors, pim_register, registers, pim_join_prune, pim_j_p, pim_jp, pim_bootstrap, pim_bsr, bsr, bootstrap, pim_asserts, pim_cand_rp, pim_c_rp, pim_rp, rp, pim_routes, pim_routing, pim_mrt, pim_timers, pim_rpf, rpf, pim, routes, routing, mrt, routers, mrouters, neighbors, timers, asserts, all, 3
18:21:55.315 pim6sd version 2.1.0-beta1 starting
18:21:55.315 65536 octets allocated for the emit/recept buffer mld6
18:21:55.315 Buffer reception size for socket 4 : 262144 in 0 iterations
18:21:55.315 65536 octets allocated for the emit/recept buffer pim6
18:21:55.315 Buffer reception size for socket 5 : 262144 in 0 iterations
18:21:55.315 Interfaces world initialized...
18:21:55.315 Getting vifs from ../pim6sd.conf
<3>default_phyint_status
<3>disable
<3>end cnf [;] (1)
<3>begin phyint [phyint] (6)
<7>eth0
<9>enable
<9>end phyint [;] (1)
<3>begin phyint [phyint] (6)
<7>eth1
<9>enable
<9>end phyint [;] (1)
parse successed.
18:21:55.316 pim_hello_period set to: 30
18:21:55.316 pim_hello_holdtime set to: 105
18:21:55.316 pim_join_prune_period set to: 60
18:21:55.316 pim_join_prune_holdtime set to: 210
18:21:55.316 timer interval set to: 5
18:21:55.316 PIM data timeout set to: 210
18:21:55.316 PIM register suppression timeout set to: 60
18:21:55.316 PIM register probe time set to: 5
18:21:55.316 PIM assert timeout set to: 180
18:21:55.316 reg_rate_limit set to 100000 (bits/s)
18:21:55.316 reg_rate_interval set to  20 s.
18:21:55.316 data_rate_limit set to 100000 (bits/s)
18:21:55.316 data_rate_interval set to 20 s.
18:21:55.316 Getting vifs from kernel
18:21:55.316 warning - Not registering detected interface lo: Operation not permitted
18:21:55.316 warning - Not registering detected interface lo: Operation not permitted
18:21:55.316 Installing eth0 (fd42:de00:c832:9fc:1b3e:bf07:72ee:d0c8 on subnet ::/64) ,as vif #2 - rate = 0
18:21:55.317 Installing eth0 (fe80::1f0:10f3:e995:5829 on subnet ::/64) ,as vif #2 - rate = 0
18:21:55.317 PIM kernel initialization done
18:21:55.317 Interface register_mif0 (subnet ::/0), installed on vif #2 - rate = 0
18:21:55.317 eth0 comes up ,vif #0 now in service
18:21:55.317 SENT Multicast Listener Query     from fe80::1f0:10f3:e995:5829 to ff02::1
18:21:55.317 eth1 is DOWN; vif #1 out of service
18:21:55.317 register vifi : 2 , register pifi : 2
18:21:55.318 register_mif0 comes up ,vif #2 now in service
18:21:55.318 Local Cand-RP address is : fd42:de00:c832:9fc:1b3e:bf07:72ee:d0c8
18:21:55.318 Local Cand-RP priority is : 0
18:21:55.319 Local Cand-RP advertisement period is : 0 sec.
18:21:55.319 no group_prefix was specified
18:21:55.319 Local BSR address: fd42:de00:c832:9fc:1b3e:bf07:72ee:d0c8
18:21:55.319 Local BSR priority : 0
18:21:55.319 Local BSR period is : 0 sec.
18:21:55.319 Local BSR hash mask length: 0

Multicast Interface Table
 Mif   PhyIF Local-Address/Prefixlen                     Scope GenID    Flags
  0     eth0 fe80::1f0:10f3:e995:5829/64                 2     729ed2e  QRY NO-NBR DR
             fd42:de00:c832:9fc:1b3e:bf07:72ee:d0c8/64   0
             Timers: PIM hello = 0:30, MLD query = 0:30
             possible MLD version = 1
             Timers: PIM hello = 0:00, MLD query = 0:00
             possible MLD version = 1
  2   regist fe80::1f0:10f3:e995:5829/64                 2     0        REGISTER
             Timers: PIM hello = 0:00, MLD query = 0:00
             possible MLD version = 1

Multicast Routing Table
 Source          Group           RP-addr         Flags
--------------------------(*,*,RP)--------------------------
Number of Groups: 0
Number of Cache MIRRORs: 0

18:21:55.319 Receiving PIM v2 Hello              from fe80::1f0:10f3:e995:5829
18:21:56.681 accept_listener_report: group(ff02::1:ffee:d0c8) has the link-local scope. discard
18:22:00.233 accept_listener_report: group(ff02::d) has the link-local scope. discard
18:22:01.234 eth1 comes up ,vif #1 now in service
18:22:01.234 warning - Interface eth1 has no link-local address, cannot send MLD query.

Multicast Interface Table
 Mif   PhyIF Local-Address/Prefixlen                     Scope GenID    Flags
  0     eth0 fe80::1f0:10f3:e995:5829/64                 2     729ed2e  QRY NO-NBR DR
             fd42:de00:c832:9fc:1b3e:bf07:72ee:d0c8/64   0
             Timers: PIM hello = 0:25, MLD query = 0:25
             possible MLD version = 1
             Timers: PIM hello = 0:04, MLD query = 2:05
             possible MLD version = 1
  2   regist fe80::1f0:10f3:e995:5829/64                 2     0        REGISTER
             Timers: PIM hello = 0:00, MLD query = 0:00
             possible MLD version = 1

Multicast Routing Table
 Source          Group           RP-addr         Flags
--------------------------(*,*,RP)--------------------------
Number of Groups: 0
Number of Cache MIRRORs: 0

---------------------------RP-Set----------------------------
Current BSR address: :: Prio: 0 Timeout: 155
RP-address(Upstream)/Group prefix             Prio Hold Age

18:22:01.245 RECV UNKNOWN ICMPv6 message: type = 0x8f, code = 0x00  from a non link local address: ::
18:22:01.385 RECV UNKNOWN ICMPv6 message: type = 0x8f, code = 0x00  from a non link local address: ::
18:22:01.513 accept_listener_report: group(ff02::1:ff00:0) has the link-local scope. discard
18:22:03.305 accept_listener_report: group(ff02::fb) has the link-local scope. discard
18:22:03.561 accept_listener_report: group(ff02::2) has the link-local scope. discard
18:22:03.821 accepting multicast listener report: src fe80::1f0:10f3:e995:5829,dst ff05::2, grp ff05::2
18:22:03.822 The group doesn't exist, trying to add it
18:22:03.822 create group entry, group ff05::2
18:22:05.097 accept_listener_report: group(ff02::1:ff95:5829) has the link-local scope. discard

Program received signal SIGSEGV, Segmentation fault.
0x000000555556900c in pim6_cksum (len=<optimized out>, dst=0x5555598b60 <allpim6routers_group+8>, src=0x10, addr=0x55555cf390) at ../../src/pim6.c:505
505	    u_int16_t answer = 0;
(gdb) bt
#0  0x000000555556900c in pim6_cksum (len=<optimized out>, dst=0x5555598b60 <allpim6routers_group+8>, src=0x10, addr=0x55555cf390) at ../../src/pim6.c:505
#1  send_pim6 (buf=0x55555cf390 " ", src=0x8, dst=0x5555598b58 <allpim6routers_group>, type=type@entry=0, datalen=datalen@entry=22) at ../../src/pim6.c:426
#2  0x0000005555569ddc in send_pim6_hello (v=v@entry=0x5555599048 <uvifs+448>, holdtime=<optimized out>) at ../../src/pim6_proto.c:827
#3  0x000000555557362c in age_vifs () at ../../src/timer.c:297
#4  0x0000005555561dc4 in timer (i=<optimized out>) at ../../src/main.c:464
#5  0x0000005555558720 in age_callout_queue (elapsed_time=<optimized out>) at ../../src/callout.c:129
#6  0x00000055555581e8 in timeout (n=-1) at ../../src/main.c:539
#7  main (argc=<optimized out>, argv=<optimized out>) at ../../src/main.c:408

Not forwarding multicast (Linux kernel (config) issue?)

Setup:

Same as in #13.

Issue:

router2 receives PIM Join/Prune from router1 and receives ICMPv6 multicast messages from client2 but does not forward these to router1.

Details:

Ignoring the issues discovered for router0 in #13 for now, router2 should still forward to router1 as at least router1 sends correct pim-join-prune messages to router2 due to the listener on client2. However:

Packets are received on lan0 of router2 from client2 fine:

router2$ timeout 15 tcpdump -c3 -i lan0 -n -v -l icmp6
tcpdump: listening on lan0, link-type EN10MB (Ethernet), capture size 262144 bytes
18:44:28.336339 IP6 (flowlabel 0x65e89, hlim 1, next-header ICMPv6 (58) payload length: 64) fd5c:725:2841:103::2 > ff13:23:42:ffff::123: [icmp6 sum ok] ICMP6, echo request, seq 245
18:44:29.360333 IP6 (flowlabel 0x65e89, hlim 1, next-header ICMPv6 (58) payload length: 64) fd5c:725:2841:103::2 > ff13:23:42:ffff::123: [icmp6 sum ok] ICMP6, echo request, seq 246
18:44:30.388044 IP6 (flowlabel 0x65e89, hlim 1, next-header ICMPv6 (58) payload length: 64) fd5c:725:2841:103::2 > ff13:23:42:ffff::123: [icmp6 sum ok] ICMP6, echo request, seq 247
3 packets captured
3 packets received by filter
0 packets dropped by kernel

However they are not forwarded to router1 on wan0:

router2$ timeout 15 tcpdump -c3 -i wan0 -n -v -l icmp6
tcpdump: listening on wan0, link-type EN10MB (Ethernet), capture size 262144 bytes

0 packets captured
0 packets received by filter
0 packets dropped by kernel

The pim6sd internal routing table on router2 looks like this:

Multicast Routing Table
 Source          Group           RP-addr         Flags
---------------------------(*,G)----------------------------
 IN6ADDR_ANY     ff13:23:42:ffff::123 fd5c:725:2841:1::3 WC RP
Joined   oifs: j..                 
Pruned   oifs: ...                 
Leaves   oifs: ...                 
Asserted oifs: ...                 
Outgoing oifs: o..                 
Incoming     : ..I                 
Upstream nbr: NONE

TIMERS: Entry=185 JP=40 RS=0 Assert=0
  MIF   0   1   2   3   4   5   6   7   8   9
    0 185   0   0
---------------------------(S,G)----------------------------
 fd5c:725:2841:103::2 ff13:23:42:ffff::123 fd5c:725:2841:1::3 SPT CACHE SG
Joined   oifs: ...                 
Pruned   oifs: ...                 
Leaves   oifs: ...                 
Asserted oifs: ...                 
Outgoing oifs: o..                 
Incoming     : .I.                 
Upstream nbr: NONE

TIMERS: Entry=195 JP=40 RS=0 Assert=0
  MIF   0   1   2   3   4   5   6   7   8   9
    0   0   0   0

And there is an entry in "ip -6 mroute show":

router2$ ip -6 mroute show
(fd5c:725:2841:103::2,ff13:23:42:ffff::123) Iif: lan0       Oifs: wan0  State: resolved

Also, multicast forwarding seems to be correctly enabled in the kernel:

router2$ cat /proc/sys/net/ipv6/conf/wan0/mc_forwarding 
1
router2$ cat /proc/sys/net/ipv6/conf/lan0/mc_forwarding 
1
router2$ cat /proc/sys/net/ipv6/conf/all/mc_forwarding 
1

So I'm a bit confused why the ICMPv6 multicast packets are not forwarded from router2 to router1. The Linux kernel in use is a 4.19.28 kernel as provided by Debian Sid. (I'm probably missing something obvious?)

Potentially broken PIM checksum

We've seen PIM messages in Wireshark with a broken checksum.

My ones from fe80::2 were fine while @mweinelt was sending bogus ones from fe80::1. One difference was that I had deleted the auto-generated link-local address on my ip6gre1 interface while @mweinelt hadn't. After he deleted that one, too, the checksum was fine again.

My guess is that pim6sd had chosen to the auto-generated IPv6 link-local address for its checksum computation. But the packets were then send with the fe80::1/64 he had manually assigned.

One key difference with PIM in IPv6 compared to IPv4 I think is that that the checksum is calculated over this "IPv6 pseudo header" which includes the IPv6 source and destination address.

Convert configuration directives from underscore to dashes

The pimd and mrouted .conf parsers have converted to use dashes for settings instead of underscore, yet keeping compat aliases for their old counterparts.

This is an entry level issue since most of the work can be inferred from how the same functionality was implemented in mrouted previously.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.