├── AUTHORS ├── COPYING ├── MRD6shQuickRef.txt ├── Makefile ├── README ├── README.translator ├── Troubleshooter ├── config └── base.pl ├── debian ├── changelog ├── compat ├── control ├── copyright ├── dirs ├── docs ├── examples ├── manpages ├── mrd6.init ├── rules └── watch ├── docs ├── mrd6.8 └── mrd6sh.1 ├── include ├── mrd │ ├── address.h │ ├── address_set.h │ ├── group.h │ ├── icmp.h │ ├── interface.h │ ├── log.h │ ├── mfa.h │ ├── mrd.h │ ├── mrib.h │ ├── node.h │ ├── packet_buffer.h │ ├── parser.h │ ├── rib.h │ ├── router.h │ ├── source_discovery.h │ ├── support │ │ ├── lists.h │ │ ├── objpool.h │ │ ├── ptree.h │ │ ├── refcount.h │ │ └── uint_n.h │ └── timers.h └── mrdpriv │ ├── bgp │ └── def.h │ ├── bsd │ └── rib.h │ ├── console │ └── console.h │ ├── dummy │ ├── mfa.h │ └── rib.h │ ├── icmp_inet6.h │ ├── ks_mfa.h │ ├── linux │ ├── icmp_raw.h │ ├── raw_socket.h │ ├── translator.h │ ├── unicast_route.h │ └── us_mfa.h │ ├── mld │ ├── def.h │ └── router.h │ └── pim │ ├── def.h │ ├── group.h │ ├── interface.h │ ├── neighbour.h │ └── router.h ├── ipkg ├── README ├── S50mrd6 ├── control ├── mrd6.base.conf ├── mrd6.m6bone.conf ├── postinst ├── preinst └── rules ├── rpm └── mrd6.spec ├── src ├── Makefile ├── address.cpp ├── address_set.cpp ├── bgp │ ├── bgp.cpp │ └── bgp_def.cpp ├── bsd │ ├── bsd_rib.cpp │ └── mrd_components.cpp ├── confs │ ├── mrd.conf │ ├── mrd.m6bone-bgp.conf │ ├── mrd.m6bone.conf │ └── mrd.translator.conf ├── console │ ├── Module.options │ ├── console.cpp │ ├── telnet_console.cpp │ └── unix_console.cpp ├── dummy │ ├── dummy.cpp │ └── mrd_components.cpp ├── extra │ ├── coredumper.cpp │ └── mld_ext.cpp ├── group.cpp ├── icmp.cpp ├── icmp_inet6.cpp ├── interface.cpp ├── ks_mfa.cpp ├── linux │ ├── Module.options │ ├── linux_icmp_raw.cpp │ ├── linux_unicast_route.cpp │ ├── mrd_components.cpp │ ├── translator.cpp │ └── us_mfa.cpp ├── log.cpp ├── main.cpp ├── mfa.cpp ├── mld │ ├── mld_conf.cpp │ ├── mld_def.cpp │ ├── mld_module.cpp │ └── mld_router.cpp ├── mrd.cpp ├── mrdisc │ ├── mrdisc_def.h │ └── mrdisc_module.cpp ├── mrib.cpp ├── msnip │ ├── msnip_def.h │ └── msnip_module.cpp ├── no-modules.cpp ├── node.cpp ├── parser.cpp ├── pim │ ├── Module.options │ ├── pim_bsr.cpp │ ├── pim_conf.cpp │ ├── pim_def.cpp │ ├── pim_group.cpp │ ├── pim_interface.cpp │ ├── pim_module.cpp │ ├── pim_neighbour.cpp │ ├── pim_oif.cpp │ ├── pim_router.cpp │ ├── pim_source.cpp │ └── test-cases │ │ └── hashmask.c ├── rib.cpp ├── ripng │ ├── EXPERIMENTAL │ └── ripng.cpp ├── router.cpp ├── scripts │ └── generate-modules-cpp.pl ├── support │ ├── Module.options │ ├── objpool.cpp │ └── ptree.cpp ├── test_dl_inclusion_in_libc.cpp ├── tests │ ├── address_unittest.cpp │ ├── mrib-1.sh │ ├── mrib_unittest.cpp │ ├── ptree_unittest.cpp │ ├── run-all.sh │ └── stress-mrib.cpp ├── timers.cpp └── zebra │ └── zebra.cpp └── tools ├── c ├── Makefile └── mrd6sh.c └── mrd6sh /AUTHORS: -------------------------------------------------------------------------------- 1 | Hugo Santos 2 | 3 | -------------------------------------------------------------------------------- /MRD6shQuickRef.txt: -------------------------------------------------------------------------------- 1 | mrd6sh is a tool that along with builtin telnet support allow one to 2 | interactively configure and obtain information from MRD6. The 3 | following consists of a brief list of the most important commands. 4 | Please note that most commands may be called by the least common 5 | command prefix, for instance, 'sho gr' may be used instead of 'show 6 | group'. 7 | 8 | $ mrd6sh show group [] 9 | 10 | Display all group information, including possible MLD and PIM 11 | information related to a particular group. A group address may be 12 | supplied to obtain information about a single group only. 13 | 14 | $ mrd6sh show group detail 15 | 16 | Outputs extra information related to group interfaces, in MLD's case 17 | it outputs the full Multicast Filter, Source timers and particular 18 | listener interest. 19 | 20 | $ mrd6sh show mfa counters 21 | 22 | Displays per-group and per-source state 60 second average forwarding 23 | statistics. 24 | 25 | $ mrd6sh show interface [ [extended]] 26 | 27 | Displays all interface information, including PIM info such as known 28 | neighbours and MLD information (Querier, etc). An interface name may 29 | be supplied to obtain information about that interface only. If the 30 | parameter 'extended' is used for a particular interface, also outputs 31 | extra PIM information such as neighbour upstream Join/Prune info. 32 | 33 | $ mrd6sh show mrib 34 | 35 | Outputs the current contents of the Multicast Routing Information 36 | base. 37 | 38 | $ mrd6sh show rpf
39 | 40 | Matches MRIB prefix information (possibly including output interface 41 | and nexthop address) for the supplied address. This command can be 42 | used to check what information is MRD6 using to route towards a 43 | particular source. 44 | 45 | $ mrd6sh log attach default \"mrd.log\" all 46 | 47 | Changes mrd.log's log level to All. Use this whenever you find odd 48 | behaviour as it triggers the logging of all signaling information, 49 | state changes, etc. You should use your log file name instead of 50 | mrd.log if you use a different one. 51 | 52 | $ mrd6sh show version 53 | 54 | Important information that should be supplied while reporting bugs :-) 55 | 56 | -- 57 | 58 | In case you are using the BGP module, the following command is also of 59 | interest. 60 | 61 | $ mrd6sh show bgp 62 | 63 | Outputs current BGP neighbour state, including filter match 64 | statistics, current BGP state machine state, uptime, etc. 65 | 66 | $ mrd6sh show translator 67 | 68 | Displays the current state and configuration of the IPv4 to IPv6 multicast 69 | translator module. 70 | 71 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | @$(MAKE) -C src 3 | 4 | install: 5 | @$(MAKE) -C src install 6 | 7 | clean: 8 | @$(MAKE) -C src clean 9 | 10 | config: 11 | @config/base.pl 12 | 13 | .PHONY: all config install clean 14 | 15 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | [note from the author, 2013: mrd6 is unsupported software. Since 2 | 2005 native multicast forwarding support has been added to Linux 3 | and pim6sd can be used to manage it. mrd6's codebase is kept 4 | around for historical reasons, it should still work in current 5 | kernels and still allows you to do funky things with routing. 6 | Feel free to fork. -hugo] 7 | 8 | This is mrd6, a ipv6 multicast routing daemon for Linux (and BSD). 9 | 10 | It supports MLDv2 (and MLDv1 compatibility), PIM-SM (including SSM 11 | support, BSR and Embedded-RP), partial MBGP support (IPv6 multicast 12 | SAFI to populate the local mrib, when used in an edge), native and 13 | virtual interfaces (ipv6-ipv4, ipv6-ipv6 and tun/tap tunnels have 14 | all been tested extensively) as well as remote configuration (via CLI). 15 | Automatic translation of IPv4 multicast traffic to IPv6 is also 16 | supported (contributed by Teemu Kiviniemi). 17 | 18 | You may use mrd6 with any Linux 2.6 based system as no kernel support 19 | for ipv6 multicast forwarding is required, that feature is implemented 20 | by mrd6 itself. 21 | 22 | Build requirements: a GNU build system, including G++ and Make. 23 | 24 | To build the default configuration, just run 'make', a 'mrd6' binary 25 | will be compiled in src/. You can then install it (including 26 | default configuration files and man pages) into your system using 27 | 'make install'. 28 | 29 | For a custom build, run 'make config', where support for individual 30 | features may be enabled or disabled. 31 | 32 | For more information refer to http://fivebits.net/proj/mrd6/ 33 | 34 | mrd6 started being developed in 2004 and thus it's showing it's age. 35 | However it is still a useful tool in certain scenarios, including 36 | quick network prototyping, testing new network features and even to 37 | run in embedded systems. 38 | 39 | - Hugo Santos 40 | -------------------------------------------------------------------------------- /README.translator: -------------------------------------------------------------------------------- 1 | IPv4 to IPv6 multicast translator 2 | --------------------------------- 3 | 4 | MRD6 contains an IPv4 to IPv6 multicast translator implementation. 5 | 6 | The implementation follows the architectural ideas and address 7 | translation presented in draft-venaas-behave-mcast46 8 | Internet-Draft. IPv4 to IPv6 protocol translation is done using an 9 | adapted version of the SIIT algorithm (RFC 2765). 10 | 11 | The translator can be used as an MLD to IGMP proxy, or to make IPv4 12 | groups available for a large IPv6 network using PIM-SM. The 13 | translator performs only IPv4 to IPv6 translation. IPv6 to IPv4 14 | translation is not supported. The translator supports both ASM 15 | (any-source multicast) and SSM (source-specific multicast). 16 | 17 | The translator is supported only on Linux. 18 | 19 | 20 | 21 | Address translation 22 | ------------------- 23 | 24 | An IPv4 source address is translated to an IPv6 address by 25 | prepending the IPv4 address with the IPv6 unicast prefix configured 26 | to the translator (unicast-prefix configuration option). In other 27 | words, the original IPv4 source address is stored in the last 32 28 | bits of the IPv6 address. The IPv6 unicast prefix must be routed 29 | towards the translator on the IPv6 network. 30 | 31 | In similar fashion, IPv4 ASM or SSM addresses are translated to 32 | IPv6 ASM and SSM addresses, by prepending the original IPv4 33 | addresses with the IPv6 ASM or SSM prefix configured to the 34 | translator (asm-prefix and ssm-prefix configuration options). 35 | 36 | The translator must be configured as the rendezvous point (RP) for 37 | the IPv6 ASM prefix. A good way to accomplish this is to use an 38 | Embedded-RP ASM prefix (RFC 3956). 39 | 40 | 41 | 42 | Joining and leaving IPv4 groups 43 | ------------------------------- 44 | 45 | The translator receives IPv6 multicast joins with the protocols 46 | supported by MRD6 (MLDv2, PIM-SM). 47 | 48 | (*,G) joins: 49 | If the the IPv6 group address matches the configured ASM prefix, 50 | the translator joins the IPv4 ASM group embedded in the IPv6 51 | address. The embedded IPv4 address must be also a valid IPv4 ASM 52 | group address. 53 | 54 | (S,G) joins: 55 | If the IPv6 source address matches the configured unicast prefix, 56 | and the IPv6 group address matches the SSM prefix, the translator 57 | joins the IPv4 SSM channel embedded in the IPv6 addresses. The 58 | embedded IPv4 group address must be also a valid IPv4 SSM group 59 | address. 60 | 61 | When the last IPv6 receiver leaves a translated group, the 62 | translator leaves the original IPv4 group. The translator joins and 63 | leaves IPv4 groups with IGMPv3 (RFC 3376) through the IPv4 64 | interface configured to the translator (ipv4-interface 65 | configuration option). 66 | 67 | 68 | 69 | Protocol translation 70 | -------------------- 71 | 72 | The implementation translates received IPv4 multicast packets to 73 | IPv6 with a modified SIIT (RFC 2765) algorithm. 74 | 75 | All transport layer protocols are translated. However, transport 76 | layer checksums are updated only for UDP packets. Thus, other 77 | transport layer protocols may be translated with invalid checksums. 78 | 79 | IPv4 fragments are translated to identical IPv6 80 | fragments. Additionally, if the size of a translated packet exceeds 81 | the currently known IPv6 path MTU, the translator handles 82 | fragmentation on behalf of the IPv4 multicast senders. 83 | 84 | 85 | 86 | Example configuration 87 | --------------------- 88 | 89 | /* IPv4 to IPv6 multicast translator configuration. */ 90 | translator { 91 | 92 | /* IPv4 interface and address of the translator */ 93 | ipv4-interface = eth0; 94 | ipv4-address = 192.0.2.75; 95 | 96 | /* Unicast prefix prepended to IPv4 source addresses. 97 | * The prefix must be routed towards the translator on 98 | * the IPv6 network. */ 99 | unicast-prefix = 2001:db8:ab:cd:ef::/96; 100 | 101 | /* Multicast prefix prepended to IPv4 ASM and SSM group addresses */ 102 | asm-prefix = ff7e:140:2001:db8:ab:cd::/96; 103 | ssm-prefix = ff3e::/96; 104 | } 105 | 106 | 107 | 108 | Useful mrd6sh commands 109 | ---------------------- 110 | 111 | show translator 112 | 113 | Displays the current state and configuration of the IPv4 to 114 | IPv6 multicast translator module. 115 | 116 | show group 117 | 118 | Displays information about all translated groups. 119 | 120 | show counters 121 | 122 | Displays forwarding statistics. 123 | 124 | 125 | 126 | Author and contact information 127 | ------------------------------ 128 | 129 | The multicast translator was implemented by Teemu Kiviniemi as part 130 | of his master's thesis. The thesis describes the translator 131 | implementation in detail. 132 | 133 | The thesis is available at: 134 | http://iki.fi/teemuki/translator/ 135 | 136 | E-mail: 137 | Teemu Kiviniemi 138 | 139 | 140 | 141 | Thanks to 142 | --------- 143 | 144 | Pekka Savola for comments and suggestions. 145 | 146 | CSC - It Center for Science Ltd. and Funet for the possibility to 147 | use a modern, high performance network for developing and testing 148 | the multicast translator. 149 | 150 | -------------------------------------------------------------------------------- /Troubleshooter: -------------------------------------------------------------------------------- 1 | MRD6 Troubleshooter 2 | ------------------- 3 | 4 | Common problems: 5 | 6 | (1) P: The router doesn't create the group and source state for a 7 | directly attached sender. 8 | 9 | A: mrd6 will only create implicit states (i.e. from receiving data 10 | packets) if the source of those packets is local. The router will 11 | only assume the source is local _if and only if_ the incoming 12 | interface has an address with the same prefix as the source. 13 | 14 | (2) P: I'm testing a small setup using PIM-SM and the Any Source 15 | Multicast (ASM) model. The Designated Router for the source 16 | has created a source state for the sender and the downstream 17 | router has also created the (*,G) state for the localy joined 18 | group but no packets reach the receiver. 19 | 20 | A: No RP address is configured by default in mrd6, and PIM-SM 21 | requires one for ASM to work. You may configure an RP address on 22 | both routers using the following configuration: 23 | 24 | groups { 25 | ff00::/8 { 26 | pim rp = 2001::1; 27 | } 28 | } 29 | 30 | Where ff00::/8 is the group mask which is being configured and 31 | 2001::1 is the RP address. Please note that the configured RP 32 | must be a PIM-SM router as well (one of your deployed routers 33 | would work fine). You may also configure the RP address online 34 | via: 35 | 36 | # mrd6sh groups ff00::/8 pim rp = 2001::1 37 | 38 | If your problem doesn't match any of the previous described situations 39 | procede with the following. 40 | 41 | Generic troubleshooter 42 | ---------------------- 43 | 44 | Increase the logging level to 'all' by for instance either by adding 45 | to or changing your configuration: 46 | 47 | log { 48 | attach default "mrd.log" all; 49 | } 50 | 51 | You may also attach a live log watcher or change your log level while 52 | mrd6 is running: 53 | 54 | # mrd6sh attach default \"mrd.log\" all 55 | 56 | to change the log level for the logfile to 'all' or: 57 | 58 | # mrd6sh console attach-log all 59 | 60 | to watch the log messages live. 61 | 62 | After doing so repeat any operations which failed previously and check 63 | for any error messages in the logs. These messages should express the 64 | possible problems clearly, and if they don't, or you believe the error 65 | is wrong or even if you get no related output at all, please contact 66 | the developers. 67 | 68 | -------------------------------------------------------------------------------- /debian/changelog: -------------------------------------------------------------------------------- 1 | mrd6 (0.9.6-2) unstable; urgency=low 2 | 3 | * Now really fix S390 building issues (Closes: #455280) 4 | 5 | -- Hugo Santos Fri, 4 Jul 2008 14:59:21 +0200 6 | 7 | mrd6 (0.9.6-1) unstable; urgency=low 8 | 9 | * New upstream release. 10 | 11 | -- Hugo Santos Fri, 4 Jul 2008 14:59:21 +0200 12 | 13 | mrd6 (0.9.5-rev3.dfsg-0.2) unstable; urgency=low 14 | 15 | * Non-maintainer upload. 16 | * Repackage upstream tarball to remove non-free IETF RFC/I-D (Closes: #423063) 17 | * Really fix FTBFS with GCC 4.3 (Closes: #417436) 18 | * Clean up debian/rules and create debian/{examples,manpages} 19 | 20 | -- Lior Kaplan Sat, 09 Jun 2007 00:57:01 +0300 21 | 22 | mrd6 (0.9.5-rev3-0.1) unstable; urgency=low 23 | 24 | * Non-maintainer upload. (Closes: #418074) 25 | * New maintainer. (Closes: #418084) 26 | - Adopt this package by its upstream, which works on it very tightly with 27 | Debian. Thank you Hugo for covering for an MIA maintainer. 28 | * New upstream release 29 | - Fix segfault when unloading module (Closes: #394590) 30 | - Fix FTBFS with GCC 4.3 (Closes: #417436) 31 | - New upstream address (Closes: #411805) 32 | - Change the package's version number inside debian, so it will be more 33 | accurate and easy to maintain with future (debian & upstream) versions. 34 | * debian/control: 35 | - Bump standards version to 3.7.2.2 (no changes needed) 36 | - Remove extra build depends, as they are covered by build-essential. 37 | - Update package description according to the README file. 38 | - Change maintainer to Hugo Santos. 39 | * Add watch file. 40 | 41 | -- Lior Kaplan Mon, 09 Apr 2007 20:28:32 +0300 42 | 43 | mrd6 (0.9.5-release-1) unstable; urgency=low 44 | 45 | * New upstream release 46 | * Hack the version number so we can upgrade properly 47 | * New features: 48 | - update to draft 06 49 | - implements MSNIP and MRDISC 50 | - improved user-space forwarding on Linux 51 | 52 | -- Anand Kumria Sun, 8 Jan 2006 12:28:48 +1100 53 | 54 | mrd6 (0.9.5-pre2-1) unstable; urgency=low 55 | 56 | * New upstream (pre)release 57 | 58 | -- Anand Kumria Mon, 28 Nov 2005 15:41:11 +1100 59 | 60 | mrd6 (0.9.5-pre1-1) unstable; urgency=low 61 | 62 | * Initial upload to Debian 63 | 64 | -- Anand Kumria Tue, 15 Nov 2005 11:05:57 +1100 65 | 66 | mrd6 (0.9.4-beta2-1) unstable; urgency=low 67 | 68 | * beta2 69 | 70 | -- Hugo Santos Mon, 17 Oct 2005 22:57:45 +0100 71 | 72 | mrd6 (0.9.4-beta1-1) unstable; urgency=low 73 | 74 | * Bumped to 0.9.4-beta1 75 | 76 | -- Hugo Santos Wed, 28 Sep 2005 01:11:03 +0100 77 | 78 | mrd6 (0.9.2-beta3-1) unstable; urgency=low 79 | 80 | * beta3 81 | 82 | -- Hugo Santos Tue, 23 Aug 2005 23:36:40 +0100 83 | 84 | mrd6 (0.9.2-beta2-1) unstable; urgency=low 85 | 86 | * beta2 87 | 88 | -- Hugo Santos Thu, 18 Aug 2005 00:09:07 +0100 89 | 90 | mrd6 (0.9.2-beta1-1) unstable; urgency=low 91 | 92 | * Bumped to 0.9.2. 93 | 94 | -- Hugo Santos Fri, 12 Aug 2005 00:30:29 +0100 95 | 96 | mrd6 (0.9.1-beta2-1) unstable; urgency=low 97 | 98 | * Version bump 99 | 100 | -- Hugo Santos Mon, 25 Jul 2005 00:32:34 +0100 101 | 102 | mrd6 (0.9.1-beta1-1) unstable; urgency=low 103 | 104 | * Version bump 105 | 106 | -- Hugo Santos Thu, 7 Jul 2005 02:34:26 +0100 107 | 108 | mrd6 (0.9-beta2) unstable; urgency=low 109 | 110 | * Beta 2 111 | 112 | -- Hugo Santos Thu, 30 Jun 2005 06:19:51 +0100 113 | 114 | mrd6 (0.9-beta1) unstable; urgency=low 115 | 116 | * Bump to 0.9 117 | 118 | -- Hugo Santos Sat, 25 Jun 2005 20:07:24 +0100 119 | 120 | mrd6 (0.8.5-beta1-1) unstable; urgency=low 121 | 122 | * Bumped to 0.8.5 123 | 124 | -- Hugo Santos Sat, 30 Apr 2005 21:55:09 +0100 125 | 126 | mrd6 (0.8-beta2-1) unstable; urgency=low 127 | 128 | * Yet another bump. 0.8-beta2 129 | 130 | -- Hugo Santos Sat, 23 Apr 2005 03:06:53 +0100 131 | 132 | mrd6 (0.8-beta1-1) unstable; urgency=low 133 | 134 | * Bumped version to 0.8-beta1 135 | 136 | -- Hugo Santos Tue, 19 Apr 2005 23:34:04 +0100 137 | 138 | mrd6 (0.7-beta3-1) unstable; urgency=low 139 | 140 | * Bumped version to 0.7-beta3 141 | 142 | -- Hugo Santos Tue, 5 Apr 2005 02:08:32 +0100 143 | 144 | mrd6 (0.7-beta2-1) unstable; urgency=low 145 | 146 | * Bumped version to 0.7-beta2 147 | 148 | -- Hugo Santos Thu, 26 Mar 2005 03:46:26 +0000 149 | 150 | mrd6 (0.7-beta1-1) unstable; urgency=low 151 | 152 | * Bumped version to 0.7-beta1 153 | 154 | -- Hugo Santos Thu, 24 Mar 2005 14:52:00 +0000 155 | 156 | mrd6 (0.6-beta6-1) unstable; urgency=low 157 | 158 | * Bumped version to beta6 159 | 160 | -- Hugo Santos Sun, 7 Mar 2005 23:13:08 +0000 161 | 162 | mrd6 (0.6-beta5-1) unstable; urgency=low 163 | 164 | * Initial Release. 165 | 166 | -- Hugo Santos Sun, 27 Feb 2005 03:08:08 +0000 167 | 168 | -------------------------------------------------------------------------------- /debian/compat: -------------------------------------------------------------------------------- 1 | 5 2 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Source: mrd6 2 | Section: net 3 | Priority: optional 4 | Maintainer: Hugo Santos 5 | Build-Depends: debhelper (>= 5.0.0), perl 6 | Standards-Version: 3.7.3 7 | Homepage: http://fivebits.net/proj/mrd6/ 8 | 9 | Package: mrd6 10 | Architecture: any 11 | Depends: ${shlibs:Depends}, lsb-base 12 | Description: IPv6 Multicast Routing Daemon 13 | mrd6 is a modular IPv6 Multicast Routing Daemon which implements: 14 | * MLDv1 and MLDv2 support 15 | - MLD proxying 16 | * PIM-SM (ASM and SSM) 17 | - Bootstrap (BSR) Mechanism support 18 | - Static RP configuration 19 | - Embedded-RP support (RFC 3956) 20 | * partial MBGP support 21 | - Implements basic BGP4 mechanisms (IPv6 Multicast SAFI) 22 | to update local MRIB from MBGP info 23 | - Uses IPv6 Multicast SAFI prefixes announced by 24 | peers to update local MRIB 25 | - Is able to announce local prefixes 26 | - Filter support 27 | * Supports both native and virtual (tunnel) interfaces 28 | (tested IPv6-IPv4, IPv6-IPv6 and TUN/TAP tunnels) 29 | * Abstract Forwarding Interface (MFA) with user-space module 30 | * Remote configuration and online administration 31 | . 32 | Homepage: http://fivebits.net/proj/mrd6/ 33 | -------------------------------------------------------------------------------- /debian/copyright: -------------------------------------------------------------------------------- 1 | It was downloaded from http://fivebits.net/proj/mrd6/ 2 | 3 | Copyright Holder: 4 | 5 | 2006, 2007 - Hugo Santos 6 | 2004, 2005, 2006 - Universidade de Aveiro, IT Aveiro 7 | 8 | Contact: 9 | 10 | Hugo Santos 11 | 12 | License: 13 | 14 | This program is free software; you can redistribute it and/or modify 15 | it under the terms of the GNU General Public License as published by 16 | the Free Software Foundation; either version 2 of the License, or 17 | (at your option) any later version. 18 | 19 | This program is distributed in the hope that it will be useful, 20 | but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | GNU General Public License for more details. 23 | 24 | You should have received a copy of the GNU General Public License 25 | along with this program; if not, write to the Free Software 26 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 27 | 28 | A full copy of the GNU General Public Licence can be found 29 | at /usr/share/common-licenses/GPL-2 30 | -------------------------------------------------------------------------------- /debian/dirs: -------------------------------------------------------------------------------- 1 | usr/lib/mrd6 2 | -------------------------------------------------------------------------------- /debian/docs: -------------------------------------------------------------------------------- 1 | MRD6shQuickRef.txt 2 | Troubleshooter 3 | README 4 | README.translator 5 | -------------------------------------------------------------------------------- /debian/examples: -------------------------------------------------------------------------------- 1 | src/confs/* 2 | -------------------------------------------------------------------------------- /debian/manpages: -------------------------------------------------------------------------------- 1 | docs/mrd6.8 2 | docs/mrd6sh.1 3 | -------------------------------------------------------------------------------- /debian/mrd6.init: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ### BEGIN INIT INFO 3 | # Provides: mrd6 4 | # Default-Start: 2 3 4 5 5 | # Default-Stop: 0 1 6 6 | # Required-Start: $network 7 | # Required-Stop: $network 8 | # Short-Description: IPv6 Multicast Routing Daemon 9 | # Description: mrd6 is a IPv6 IPv6 Multicast Routing Daemon which 10 | # implements: MLDv1, MLDv2, PIM-SM, partial MBGP support, 11 | # Native and virtual (tunnel) interfaces support and CLI 12 | # support. 13 | ### END INIT INFO 14 | 15 | # Author: Hugo Santos 16 | 17 | PATH=/usr/sbin:/usr/bin:/sbin:/bin 18 | DAEMON=/usr/sbin/mrd6 19 | NAME=mrd6 20 | DESC="Multicast routing daemon" 21 | CONF=/etc/mrd6.conf 22 | 23 | test -x $DAEMON || exit 0 24 | 25 | test -r $CONF || exit 0 26 | 27 | . /lib/lsb/init-functions 28 | 29 | case "$1" in 30 | start) 31 | log_begin_msg "Starting $DESC: $NAME" 32 | start-stop-daemon --start --quiet -m --pidfile /var/run/mrd6.pid --exec $DAEMON -- -D 33 | log_end_msg $? 34 | ;; 35 | stop) 36 | log_begin_msg "Stopping $DESC: $NAME" 37 | start-stop-daemon --stop --quiet --oknodo --exec $DAEMON 38 | rm -f /var/run/mrd6.pid 39 | log_end_msg $? 40 | ;; 41 | restart|force-reload) 42 | /etc/init.d/$NAME stop 43 | /etc/init.d/$NAME start 44 | ;; 45 | *) 46 | N=/etc/init.d/$NAME 47 | echo "Usage: $N {start|stop|restart|force-reload}" >&2 48 | exit 1 49 | ;; 50 | esac 51 | 52 | exit 0 53 | 54 | -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | 3 | # export DH_VERBOSE=1 4 | 5 | TARGET = mrd6 6 | DESTDIR = $(CURDIR)/debian/mrd6 7 | 8 | export TARGET DESTDIR 9 | 10 | configure: configure-stamp 11 | 12 | configure-stamp: 13 | dh_testdir 14 | 15 | config/base.pl \ 16 | --prefix /usr \ 17 | --static mld \ 18 | --static pim \ 19 | --static console \ 20 | --external bgp \ 21 | --external msnip \ 22 | --external mrdisc \ 23 | 24 | touch configure-stamp 25 | 26 | build: build-stamp 27 | 28 | build-stamp: configure 29 | dh_testdir 30 | 31 | $(MAKE) 32 | 33 | touch build-stamp 34 | 35 | clean: 36 | dh_testdir 37 | dh_testroot 38 | 39 | [ ! -f Makefile ] || $(MAKE) clean 40 | rm -rf src/build/ 41 | rm -f src/Makefile.options 42 | rm -f build-stamp configure-stamp 43 | 44 | dh_clean 45 | 46 | install: build 47 | dh_testdir 48 | dh_testroot 49 | dh_clean -k 50 | dh_installdirs 51 | 52 | $(MAKE) install 53 | 54 | # Build architecture-independent files here. 55 | binary-indep: build install 56 | # We have nothing to do by default. 57 | 58 | # Build architecture-dependent files here. 59 | binary-arch: build install 60 | dh_testdir 61 | dh_testroot 62 | dh_installchangelogs 63 | dh_installdocs 64 | dh_installexamples 65 | # dh_install 66 | dh_installinit 67 | dh_installman 68 | dh_link 69 | dh_strip 70 | dh_compress 71 | dh_fixperms 72 | dh_installdeb 73 | dh_shlibdeps 74 | dh_gencontrol 75 | dh_md5sums 76 | dh_builddeb 77 | 78 | binary: binary-indep binary-arch 79 | .PHONY: build clean binary-indep binary-arch binary install 80 | -------------------------------------------------------------------------------- /debian/watch: -------------------------------------------------------------------------------- 1 | version=3 2 | # Using example fron the uscan man page: 3 | # This is a variant HTTP format which allows direct specification of 4 | # the homepage: 5 | # Homepage Pattern [Version [Action]] 6 | http://fivebits.net/proj/mrd6 /files/mrd6/mrd6-([\d\.-]*).tar.gz 7 | -------------------------------------------------------------------------------- /docs/mrd6.8: -------------------------------------------------------------------------------- 1 | .TH MRD6 8 "IPv6 Multicast routing daemon" 2 | .SH NAME 3 | mrd6 \- an IPv6 Multicast routing daemon and framework 4 | .SH SYNOPSIS 5 | .B mrd6 6 | [ 7 | .B \-D 8 | ] [ 9 | .B \-f 10 | .I config-file 11 | ] [ 12 | .B \-A 13 | ] 14 | .SH DESCRIPTION 15 | .B mrd6 16 | is a multicast routing daemon that supports PIM-SM, MLDv2, MBGP, and others. 17 | .SH OPTIONS 18 | Options available for the 19 | .B mrd6 20 | command: 21 | .TP 22 | \fB\-D\fR 23 | Forks into the background after init. 24 | .TP 25 | \fB\-f\fR 26 | Specifies the configuration file to be used. If this option is not specified 27 | .B mrd6 28 | will try to load \fB\fI/etc/mrd6.conf\fR. 29 | .TP 30 | \fB\-A\fR 31 | Don't auto-load 32 | .B mrd6 33 | modules that were built statically. 34 | .SH FILES 35 | .TP 36 | .BI /etc/mrd6.conf 37 | The default location of the 38 | .B mrd6 39 | config file. 40 | .SH DIAGNOSTICS 41 | .B mrd6 42 | will log to the stderr file descriptor, to a log file or through syslog 43 | to the system logs. For more information on how to configure \fBmrd6\fR 44 | check the included documentation. 45 | .SH BUGS 46 | Report any bugs to 47 | .BI http://fivebits.net/proj/mrd6/ 48 | 49 | -------------------------------------------------------------------------------- /docs/mrd6sh.1: -------------------------------------------------------------------------------- 1 | .TH MRD6SH 1 "IPv6 Multicast routing daemon" 2 | .SH NAME 3 | mrd6 \- an IPv6 Multicast routing daemon and framework 4 | .SH SYNOPSIS 5 | .B mrd6sh 6 | .I command 7 | .SH DESCRIPTION 8 | .B mrd6sh 9 | allows you both to either obtain current state information from 10 | .B mrd6 11 | as well as to dynamically configure it. 12 | .SH OPTIONS 13 | Options available for the 14 | .B mrd6 15 | command: 16 | .TP 17 | .I command 18 | The full command that will be sent to \fBmrd6\fR. 19 | For a list of common useful commands check the included MRD6shQuickRef.txt 20 | .SH FILES 21 | .TP 22 | .BI /usr/share/doc/mrd6/MRD6shQuickRef.txt 23 | A quick reference to useful \fBmrd6\fR commands. 24 | .SH BUGS 25 | Report any bugs to 26 | .BI http://fivebits.net/proj/mrd6/ 27 | 28 | -------------------------------------------------------------------------------- /include/mrd/address.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Multicast Routing Daemon (MRD) 3 | * address.h 4 | * 5 | * Copyright (C) 2006, 2007 - Hugo Santos 6 | * Copyright (C) 2004..2006 - Universidade de Aveiro, IT Aveiro 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * Author: Hugo Santos 23 | */ 24 | 25 | #ifndef _mrd_address_h_ 26 | #define _mrd_address_h_ 27 | 28 | #include 29 | #include 30 | 31 | #include 32 | 33 | #include 34 | #include 35 | #include 36 | 37 | class base_stream; 38 | 39 | static inline bool operator < (const in6_addr &a1, const in6_addr &a2) { 40 | return memcmp(a1.s6_addr, a2.s6_addr, 16) < 0; 41 | } 42 | 43 | static inline bool operator == (const in6_addr &a1, const in6_addr &a2) { 44 | return IN6_ARE_ADDR_EQUAL(&a1, &a2); 45 | } 46 | 47 | static inline int pnode_prefix_length(const in6_addr &p) { 48 | return sizeof(in6_addr) * 8; 49 | } 50 | 51 | static inline bool pnode_symbol_at(const in6_addr &p, int n) { 52 | return p.s6_addr[n / 8] & (0x80 >> (n & 0x07)); 53 | } 54 | 55 | /*! 56 | * \class inet6_addr mrd/address.h 57 | * \brief provides an in6_addr + prefixlen abstraction and container. 58 | */ 59 | struct inet6_addr { 60 | inet6_addr(); 61 | inet6_addr(const in6_addr &); 62 | inet6_addr(const in6_addr &, uint8_t prefixlen); 63 | inet6_addr(const inet6_addr &); 64 | explicit inet6_addr(const std::string &); 65 | explicit inet6_addr(const std::vector &); 66 | 67 | static inet6_addr any() { 68 | return inet6_addr(); 69 | } 70 | 71 | bool is_any() const { 72 | return IN6_IS_ADDR_UNSPECIFIED(&addr); 73 | } 74 | 75 | bool is_linklocal() const { 76 | return IN6_IS_ADDR_LINKLOCAL(&addr); 77 | } 78 | 79 | enum { 80 | multicast = 2, 81 | network = 4 82 | }; 83 | 84 | unsigned type() const; 85 | 86 | inet6_addr prefix() const; 87 | 88 | bool operator < (const inet6_addr &) const; 89 | bool operator > (const inet6_addr &) const; 90 | bool operator == (const inet6_addr &) const; 91 | 92 | bool operator == (const in6_addr &rho) const { 93 | return IN6_ARE_ADDR_EQUAL(&addr, &rho); 94 | } 95 | 96 | inet6_addr &operator = (const inet6_addr &base) { 97 | set(base.address(), base.prefixlen); 98 | return *this; 99 | } 100 | 101 | inet6_addr &operator = (const in6_addr &base) { 102 | return (*this) = inet6_addr(base); 103 | } 104 | 105 | bool partial_match(const in6_addr &ma, uint8_t malen) const { 106 | uint8_t plen = prefixlen; 107 | const uint32_t *ap = (const uint32_t *)&addr; 108 | const uint32_t *bp = (const uint32_t *)&ma; 109 | while (plen >= 32) { 110 | if (*ap != *bp) 111 | return false; 112 | ap ++; bp ++; 113 | plen -= 32; 114 | } 115 | if (plen > 0) { 116 | uint32_t mask = 0xffffffff << (32 - plen); 117 | if ((ntohl(*ap) & mask) != (ntohl(*bp) & mask)) 118 | return false; 119 | } 120 | return true; 121 | } 122 | 123 | bool matches(const in6_addr &ma, uint8_t malen = 128) const { 124 | if (prefixlen == 0) { 125 | return true; 126 | } else if (prefixlen == 128) { 127 | return IN6_ARE_ADDR_EQUAL(&addr, &ma); 128 | } else if (malen < prefixlen) { 129 | return false; 130 | } 131 | 132 | return partial_match(ma, malen); 133 | } 134 | 135 | bool matches(const inet6_addr &address) const { 136 | return matches(address.address(), address.prefixlen); 137 | } 138 | 139 | const in6_addr &address() const { return addr; } 140 | const in6_addr *address_p() const { return &addr; } 141 | 142 | std::string as_string() const; 143 | sockaddr_in6 as_sockaddr() const; 144 | 145 | char *print_string(char *, int) const; 146 | 147 | operator std::string () const { return as_string(); } 148 | operator in6_addr () const { return addr; } 149 | 150 | void set(const in6_addr &, uint8_t); 151 | 152 | bool set(const std::string &); 153 | 154 | static bool from_string(const std::string &, inet6_addr &); 155 | static void to_string(const inet6_addr &, std::string &); 156 | 157 | void apply_prefixlen(); 158 | 159 | /* ptree-key implementing methods */ 160 | friend int pnode_prefix_length(const inet6_addr &p) { 161 | return p.prefixlen; 162 | } 163 | 164 | friend bool pnode_symbol_at(const inet6_addr &p, int n) { 165 | return pnode_symbol_at(p.addr, n); 166 | } 167 | 168 | in6_addr addr; 169 | uint8_t prefixlen; 170 | }; 171 | 172 | static inline const char *stream_type_format_parameter(const in6_addr &) { 173 | return "{addr}"; 174 | } 175 | 176 | static inline const char *stream_type_format_parameter(const inet6_addr &) { 177 | return "{Addr}"; 178 | } 179 | 180 | void stream_push_formated_type(base_stream &os, const in6_addr &); 181 | void stream_push_formated_type(base_stream &os, const inet6_addr &); 182 | 183 | #endif 184 | 185 | -------------------------------------------------------------------------------- /include/mrd/address_set.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Multicast Routing Daemon (MRD) 3 | * address_set.h 4 | * 5 | * Copyright (C) 2006, 2007 - Hugo Santos 6 | * Copyright (C) 2004..2006 - Universidade de Aveiro, IT Aveiro 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * Author: Hugo Santos 23 | */ 24 | 25 | #ifndef _mrd_address_set_h_ 26 | #define _mrd_address_set_h_ 27 | 28 | #include 29 | 30 | #include 31 | #include 32 | #include 33 | 34 | class base_stream; 35 | 36 | /*! 37 | * \class address_set mrd/address_set.h 38 | * \brief implements an address list. 39 | */ 40 | class address_set : public std::set { 41 | public: 42 | address_set(); 43 | address_set(const in6_addr &); 44 | address_set(const inet6_addr &); 45 | address_set(const address_set &); 46 | 47 | address_set &union_with(const address_set &); 48 | address_set &union_with(const address_set &, address_set &diff); 49 | address_set &diff_with(const address_set &); 50 | address_set &diff_with(const address_set &, address_set &diff); 51 | address_set &intersect_with(const address_set &); 52 | address_set &intersect_with(const address_set &, address_set &diff); 53 | 54 | address_set &assign_with(const address_set &, address_set &added, address_set &remove); 55 | 56 | bool has_addr(const in6_addr &) const; 57 | 58 | bool remove(const in6_addr &); 59 | 60 | address_set &operator += (const in6_addr &); 61 | 62 | address_set operator + (const address_set &addrs) const { 63 | return address_set(*this).union_with(addrs); 64 | } 65 | 66 | address_set operator - (const address_set &addrs) const { 67 | return address_set(*this).diff_with(addrs); 68 | } 69 | 70 | address_set operator * (const address_set &addrs) const { 71 | return address_set(*this).intersect_with(addrs); 72 | } 73 | 74 | base_stream &print_to(base_stream &) const; 75 | }; 76 | 77 | // inlines 78 | 79 | inline address_set::address_set() { } 80 | inline address_set::address_set(const in6_addr &addr) 81 | { insert(end(), addr); } 82 | inline address_set::address_set(const inet6_addr &addr) 83 | { insert(end(), addr.address()); } 84 | inline address_set::address_set(const address_set &orig) 85 | : std::set(orig) { } 86 | 87 | inline bool address_set::has_addr(const in6_addr &addr) const { 88 | return find(addr) != end(); 89 | } 90 | 91 | inline address_set &address_set::operator += (const in6_addr &addr) { 92 | insert(end(), addr); 93 | return *this; 94 | } 95 | 96 | static inline const char *stream_type_format_parameter(const address_set &) { 97 | return "{addrset}"; 98 | } 99 | 100 | static inline void stream_push_formated_type(base_stream &os, const address_set &val) { 101 | val.print_to(os); 102 | } 103 | 104 | #endif 105 | 106 | -------------------------------------------------------------------------------- /include/mrd/icmp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Multicast Routing Daemon (MRD) 3 | * mrd/icmp.h 4 | * 5 | * Copyright (C) 2006, 2007 - Hugo Santos 6 | * Copyright (C) 2004..2006 - Universidade de Aveiro, IT Aveiro 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * Author: Hugo Santos 23 | */ 24 | 25 | #ifndef _mrd_icmp_h_ 26 | #define _mrd_icmp_h_ 27 | 28 | #include 29 | #include 30 | 31 | #include 32 | 33 | class interface; 34 | 35 | class icmp_handler { 36 | public: 37 | virtual ~icmp_handler() {} 38 | 39 | virtual void icmp_message_available(interface *, const in6_addr &, 40 | const in6_addr &, icmp6_hdr *, 41 | int) = 0; 42 | }; 43 | 44 | class icmp_base { 45 | public: 46 | virtual ~icmp_base() {} 47 | 48 | virtual bool check_startup() = 0; 49 | virtual void shutdown() = 0; 50 | 51 | bool send_icmp(const in6_addr &dst, icmp6_hdr *, uint16_t) const; 52 | bool send_icmp(const interface *intf, const in6_addr &dst, 53 | icmp6_hdr *, uint16_t) const; 54 | bool send_icmp(const interface *intf, const in6_addr &dst, 55 | int rta, icmp6_hdr *, uint16_t) const; 56 | bool send_icmp(const interface *, const in6_addr &, 57 | const in6_addr &, icmp6_hdr *, uint16_t) const; 58 | 59 | virtual bool send_icmp(const interface *, const in6_addr &, 60 | const in6_addr &, int, icmp6_hdr *, 61 | uint16_t) const = 0; 62 | 63 | bool register_handler(int type, icmp_handler *); 64 | 65 | void require_mgroup(const in6_addr &, bool); 66 | 67 | virtual void added_interface(interface *) = 0; 68 | virtual void removed_interface(interface *) = 0; 69 | 70 | protected: 71 | void icmp_message_available(interface *, const in6_addr &, 72 | const in6_addr &, icmp6_hdr *, int); 73 | 74 | virtual void registration_changed(); 75 | virtual void internal_require_mgroup(const in6_addr &, bool) = 0; 76 | 77 | typedef std::map handlers; 78 | handlers m_handlers; 79 | 80 | typedef std::map mgroups; 81 | mgroups m_mgroups; 82 | }; 83 | 84 | #endif 85 | 86 | -------------------------------------------------------------------------------- /include/mrd/interface.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Multicast Routing Daemon (MRD) 3 | * interface.h 4 | * 5 | * Copyright (C) 2006, 2007 - Hugo Santos 6 | * Copyright (C) 2004..2006 - Universidade de Aveiro, IT Aveiro 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * Author: Hugo Santos 23 | */ 24 | 25 | #ifndef _mrd_interface_h_ 26 | #define _mrd_interface_h_ 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include 34 | #include 35 | 36 | class mrd; 37 | class router; 38 | class intfconf; 39 | class interface; 40 | class base_stream; 41 | class intfconf_node; 42 | 43 | class intfconf : public conf_node { 44 | public: 45 | typedef conf_node base; 46 | 47 | intfconf(const char *); 48 | ~intfconf(); 49 | 50 | const char *description() const { return "Interface configuration"; } 51 | 52 | bool check_startup(); 53 | 54 | void fill_defaults(); 55 | 56 | void property_changed(node *, const char *); 57 | node *create_child(const char *); 58 | bool call_method(int, base_stream &, 59 | const std::vector &); 60 | 61 | virtual node *next_similar_node() const; 62 | 63 | bool is_enabled() const; 64 | 65 | bool is_router_enabled(const char *) const; 66 | 67 | void update_interface_configuration(interface *); 68 | 69 | private: 70 | bool disable_router(const std::vector &); 71 | void remove_child_node(node *); 72 | 73 | std::set disabled_routers; 74 | }; 75 | 76 | class intfconf_node : public conf_node { 77 | public: 78 | intfconf_node(intfconf *, const char *); 79 | 80 | virtual bool fill_defaults() { return true; } 81 | virtual node *next_similar_node() const; 82 | }; 83 | 84 | class interface_node : public node { 85 | public: 86 | interface_node(router *rt); 87 | virtual ~interface_node(); 88 | 89 | virtual void attached(interface *owner); 90 | virtual void dettached(); 91 | 92 | interface *owner() const { return n_owner; } 93 | router *owner_router() const { return n_owner_router; } 94 | 95 | virtual void address_added_or_removed(bool, const inet6_addr &) {} 96 | 97 | /* logging */ 98 | bool should_log(int) const; 99 | base_stream &log() const; 100 | 101 | protected: 102 | interface *n_owner; 103 | router *n_owner_router; 104 | }; 105 | 106 | /*! 107 | * \class interface mrd/interface.h 108 | * \brief Represents a system network interface. 109 | */ 110 | class interface : public node { 111 | public: 112 | interface(intfconf *, int indx, const char *name, int type, int mtu, int flags); 113 | ~interface(); 114 | 115 | void shutdown(); 116 | 117 | int index() const { return mif_index; } 118 | const char *name() const { return mif_name.c_str(); } 119 | 120 | const char *description() const { return "Network interface"; } 121 | 122 | enum { 123 | None = 0, 124 | Loopback, 125 | Ethernet, 126 | PPP, 127 | Tunnel, 128 | TUN, 129 | IEEE1394, 130 | IEEE802_11, 131 | IEEE802_1Q, 132 | IPv4_Translator, 133 | }; 134 | 135 | enum kernel_state { 136 | Down, 137 | NoLink, 138 | Up, 139 | }; 140 | 141 | int type() const { return mif_type; } 142 | const char *type_str() const; 143 | int mtu() const { return mif_mtu; } 144 | 145 | kernel_state state() const { return mif_state; } 146 | 147 | bool up(bool ignoremrd = false) const; 148 | 149 | void change_state(kernel_state); 150 | 151 | /* Is the interface a virtual interface? */ 152 | bool is_virtual(); 153 | 154 | /* returns true if this interface is attached 155 | * to a multi-access LAN */ 156 | bool is_multiaccess() const; 157 | 158 | bool attach_node(interface_node *); 159 | void dettach_node(interface_node *); 160 | interface_node *node_owned_by(const router *) const; 161 | 162 | const in6_addr *linklocal() const { return mif_linklocal.address_p(); } 163 | 164 | const std::set &linklocals() const { return mif_linklocals; } 165 | const std::set &globals() const { return mif_globals; } 166 | 167 | const inet6_addr &primary_addr() const; 168 | 169 | const sockaddr_in6 *localaddr() const { return &mif_localaddr; } 170 | 171 | bool has_global(const in6_addr &addr) const; 172 | 173 | bool in_same_subnet(const in6_addr &) const; 174 | 175 | intfconf *conf() const { return mif_conf; } 176 | 177 | void address_added_or_removed(bool isnew, const inet6_addr &); 178 | 179 | bool output_info(base_stream &, const std::vector &) const; 180 | base_stream &log() const; 181 | 182 | private: 183 | friend class mrd; 184 | friend class intfconf; 185 | 186 | int mif_index; 187 | std::string mif_name; 188 | int mif_type; 189 | int mif_mtu; 190 | int mif_flags; 191 | 192 | kernel_state mif_state; 193 | bool mif_enabled; 194 | 195 | sockaddr_in6 mif_localaddr; 196 | inet6_addr mif_linklocal; 197 | 198 | std::set mif_linklocals; 199 | std::set mif_globals; 200 | 201 | intfconf *mif_conf; 202 | 203 | tval mif_creationtime; 204 | 205 | void add_remove_address(bool isnew, const inet6_addr &); 206 | void broadcast_change_state(bool wasdown); 207 | void set_enabled(bool newstate, bool newiface=false); 208 | }; 209 | 210 | uint16_t ipv6_checksum(uint8_t protocol, const in6_addr &src, const in6_addr &dst, const void *data, uint16_t len); 211 | 212 | #endif 213 | 214 | -------------------------------------------------------------------------------- /include/mrd/mfa.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Multicast Routing Daemon (MRD) 3 | * mfa.h 4 | * 5 | * Copyright (C) 2006, 2007 - Hugo Santos 6 | * Copyright (C) 2004..2006 - Universidade de Aveiro, IT Aveiro 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * Author: Hugo Santos 23 | */ 24 | 25 | #ifndef _mrd_mfa_h_ 26 | #define _mrd_mfa_h_ 27 | 28 | #include 29 | 30 | #include 31 | #include 32 | 33 | class router; 34 | class interface; 35 | 36 | struct ip6_hdr; 37 | 38 | class mfa_group_source { 39 | public: 40 | mfa_group_source(); 41 | virtual ~mfa_group_source(); 42 | 43 | enum { 44 | any_incoming = 0, 45 | wrong_iif, 46 | event_count 47 | }; 48 | 49 | enum { 50 | f_any_incoming = 1, 51 | f_wrong_iif = 2, 52 | }; 53 | 54 | enum action { 55 | no_action = 0, 56 | notify_no_copy, 57 | copy_metadata, 58 | copy_full_packet 59 | }; 60 | 61 | virtual void change_flags(uint32_t, action) = 0; 62 | 63 | virtual void set_iif(interface *) = 0; 64 | virtual void release_iif(interface *) = 0; 65 | 66 | virtual void add_oif(interface *) = 0; 67 | virtual void release_oif(interface *) = 0; 68 | 69 | virtual void get_input_counter(uint64_t &bytes) const = 0; 70 | virtual void get_forwarding_counter(uint64_t &bytes) const = 0; 71 | 72 | void *instowner; 73 | }; 74 | 75 | class mfa_group { 76 | public: 77 | mfa_group(router *owner); 78 | virtual ~mfa_group() {} 79 | 80 | router *owner() const { return m_owner; } 81 | 82 | virtual void activate(bool) = 0; 83 | 84 | virtual mfa_group_source *create_source_state(const in6_addr &, void * = 0) = 0; 85 | virtual void release_source_state(mfa_group_source *) = 0; 86 | 87 | virtual void change_default_flags(uint32_t, mfa_group_source::action) = 0; 88 | 89 | void *instowner; 90 | 91 | private: 92 | router *m_owner; 93 | }; 94 | 95 | /*! 96 | * \brief implements the core interface with the current 97 | * MFA (Multicast forwarding agent). 98 | */ 99 | class mfa_core : public node { 100 | public: 101 | virtual ~mfa_core() {} 102 | 103 | virtual bool pre_startup(); 104 | virtual bool check_startup() = 0; 105 | virtual void shutdown() = 0; 106 | 107 | virtual void added_interface(interface *) {} 108 | virtual void removed_interface(interface *) {} 109 | 110 | virtual mfa_group *create_group(router *, const inet6_addr &, void * = 0) = 0; 111 | virtual void release_group(mfa_group *) = 0; 112 | 113 | virtual void change_group_default_flags(uint32_t, mfa_group_source::action) {} 114 | 115 | virtual void forward(interface *, ip6_hdr *, uint16_t) const = 0; 116 | 117 | static mfa_core *mfa(); 118 | 119 | protected: 120 | mfa_core(); 121 | }; 122 | 123 | #endif 124 | 125 | -------------------------------------------------------------------------------- /include/mrd/packet_buffer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Multicast Routing Daemon (MRD) 3 | * packet_buffer.h 4 | * 5 | * Copyright (C) 2006, 2007 - Hugo Santos 6 | * Copyright (C) 2004..2006 - Universidade de Aveiro, IT Aveiro 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * Author: Hugo Santos 23 | */ 24 | 25 | #ifndef _mrd_packet_buffer_h_ 26 | #define _mrd_packet_buffer_h_ 27 | 28 | #include 29 | #include 30 | 31 | #include 32 | #include 33 | 34 | struct ip6_hdr; 35 | 36 | class interface; 37 | class socket_base; 38 | 39 | /*! 40 | * \class std_packet_buffer mrd/packet_buffer.h 41 | * \brief Implements a packet buffer with pre-reserve head-space for 42 | * fast encapsulation. 43 | */ 44 | template 45 | class std_packet_buffer { 46 | public: 47 | std_packet_buffer() 48 | : source(0), rlength(-1), read_offset(0), send_offset(0) { 49 | memset(pb_buf, 0, sizeof(pb_buf)); 50 | } 51 | 52 | template T *header(int offset = 0) { return (T *)(pb_buf + EBS + offset); } 53 | void *pheader(int offset = 0) { return pb_buf + EBS + offset; } 54 | 55 | ip6_hdr *ip6_header() { return (ip6_hdr *)(pb_buf + EBS + read_offset); } 56 | 57 | int recvfrom(int sock, sockaddr *sa, socklen_t *salen) { 58 | rlength = ::recvfrom(sock, pb_buf + EBS, BS - EBS, 0, sa, salen); 59 | read_offset = 0; 60 | return rlength; 61 | } 62 | 63 | int sendto(int sock, const sockaddr *sa, socklen_t salen) { 64 | int res = ::sendto(sock, pb_buf + EBS + send_offset, rlength, 0, sa, salen); 65 | send_offset = 0; 66 | return res; 67 | } 68 | 69 | void full_resize(int length) { 70 | rlength = length; 71 | } 72 | 73 | void set_send_offset(int length) { 74 | send_offset -= length; 75 | rlength += length; 76 | } 77 | 78 | uint8_t *buffer() { return pb_buf + EBS; } 79 | const uint8_t *buffer() const { return pb_buf + EBS; } 80 | 81 | uint32_t bufferlen() const { return BS - EBS; } 82 | 83 | interface *source; 84 | 85 | int rlength; 86 | 87 | int read_offset, send_offset; 88 | 89 | int auxhdr_off, auxhdr_len; 90 | 91 | private: 92 | uint8_t pb_buf[BS]; 93 | }; 94 | 95 | typedef std_packet_buffer<4096, 256> packet_buffer; 96 | 97 | class encoding_buffer { 98 | public: 99 | encoding_buffer(int); 100 | ~encoding_buffer(); 101 | 102 | bool check_startup(); 103 | 104 | bool require(int len) const { return (m_head + len) <= m_tail; } 105 | bool tail_require(int len) const { return (m_tail + len) <= m_end; } 106 | 107 | void *eat(int); 108 | void *put(int); 109 | 110 | uint8_t *head() const { return m_head; } 111 | uint8_t *tail() const { return m_tail; } 112 | 113 | uint32_t data_length() const { return m_tail - m_head; } 114 | uint32_t available_length() const { return m_end - m_tail; } 115 | 116 | void advance_head(int); 117 | void advance_tail(int); 118 | void compact(); 119 | void clear(); 120 | 121 | bool empty() const { return m_head == m_tail; } 122 | 123 | /* Helpers */ 124 | template T &eat() { return *((T *)eat(sizeof(T))); } 125 | template T &put() { return *((T *)put(sizeof(T))); } 126 | 127 | int neatl() { return ntohl(eat()); } 128 | uint32_t neatu32() { return ntohl(eat()); } 129 | uint8_t neatu8() { return eat(); } 130 | uint16_t neatu16() { return ntohs(eat()); } 131 | 132 | int consume(socket_base &, bool blocking = false); 133 | int flush_to(socket_base &, bool wantsread, bool blocking = false); 134 | 135 | private: 136 | uint8_t *m_buffer, *m_end; 137 | uint8_t *m_head, *m_tail; 138 | }; 139 | 140 | #endif 141 | 142 | -------------------------------------------------------------------------------- /include/mrd/parser.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Multicast Routing Daemon (MRD) 3 | * parser.h 4 | * 5 | * Copyright (C) 2006, 2007 - Hugo Santos 6 | * Copyright (C) 2004..2006 - Universidade de Aveiro, IT Aveiro 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * Author: Hugo Santos 23 | */ 24 | 25 | #ifndef _mrd_parser_h_ 26 | #define _mrd_parser_h_ 27 | 28 | #include 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | class parser_context { 36 | public: 37 | parser_context(); 38 | parser_context(const char *input, bool partial = false); 39 | parser_context(const parser_context &); 40 | 41 | parser_context &operator = (const parser_context &); 42 | 43 | enum token_type { 44 | NONE, 45 | LCURLY, RCURLY, 46 | LPARENT, RPARENT, 47 | TERM, 48 | EQUAL, 49 | PLUSEQUAL, 50 | DOT, COMMA, 51 | 52 | /* identifier, integer, address, etc. */ 53 | TOKEN, 54 | /* TOKEN directly followed by a '?' */ 55 | PARTIAL_TOKEN, 56 | /* quoted string */ 57 | STRING, 58 | }; 59 | 60 | static const char *token_name(token_type); 61 | 62 | struct symbol { 63 | symbol(); 64 | symbol(int, token_type, const std::string &); 65 | symbol(const symbol &); 66 | 67 | int line; 68 | token_type sym; 69 | std::string value; 70 | }; 71 | 72 | int current_line_number() const { return m_current_line; } 73 | std::string current_line() const; 74 | const char *current_input() const { return m_input_pointer; } 75 | int current_column() const { return m_input_pointer - m_input_line_start; } 76 | 77 | // -1 parsing error 78 | // 0 no more symbols 79 | // 1 parsed with success 80 | int read(); 81 | int eat(); 82 | int eat(token_type); 83 | int eat(int, ...); 84 | 85 | const symbol &head() const { return m_current; } 86 | 87 | private: 88 | int read_token(bool, int *, const char ** = 0, bool = true); 89 | 90 | int parse_one(const char *input, int state, int *sym, int *readnum) const; 91 | 92 | symbol m_current; 93 | int m_current_line; 94 | 95 | std::list m_symq; 96 | 97 | const char *m_input; 98 | const char *m_input_pointer; 99 | const char *m_input_line_start; 100 | 101 | bool m_partial; 102 | }; 103 | 104 | #endif 105 | 106 | -------------------------------------------------------------------------------- /include/mrd/rib.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Multicast Routing Daemon (MRD) 3 | * rib.h 4 | * 5 | * Copyright (C) 2006, 2007 - Hugo Santos 6 | * Copyright (C) 2004..2006 - Universidade de Aveiro, IT Aveiro 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * Author: Hugo Santos 23 | */ 24 | 25 | #ifndef _mrd_unicast_route_h_ 26 | #define _mrd_unicast_route_h_ 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | 34 | class interface; 35 | 36 | /*! 37 | * callback based unicast route watcher 38 | */ 39 | struct rib_watcher_base { 40 | rib_watcher_base(); 41 | virtual ~rib_watcher_base(); 42 | 43 | void set_destination(const inet6_addr &); 44 | void release(); 45 | 46 | void update(); 47 | 48 | enum { 49 | HAS_ROUTE = 1, 50 | GATEWAY = 2, 51 | PREFSRC = 4, 52 | DEV = 8, 53 | PROTOCOL = 16, 54 | METRIC = 32 55 | }; 56 | 57 | virtual void route_changed(uint32_t) = 0; 58 | 59 | template 60 | T *oif(R *r) const { return r->get_interface(dev); } 61 | 62 | bool valid; 63 | int dev; 64 | in6_addr dst, gateway, prefsrc; 65 | uint32_t protocol, metric; 66 | }; 67 | 68 | /*! 69 | * template based unicast route watcher 70 | */ 71 | template 72 | struct rib_watcher : rib_watcher_base { 73 | typedef std::mem_fun1_t callback_def; 74 | 75 | rib_watcher(Holder *, callback_def c); 76 | 77 | void route_changed(uint32_t); 78 | 79 | private: 80 | Holder *_h; 81 | callback_def _cb; 82 | }; 83 | 84 | template inline rib_watcher::rib_watcher(H *h, 85 | rib_watcher::callback_def c) 86 | : rib_watcher_base(), _h(h), _cb(c) {} 87 | 88 | template inline void rib_watcher::route_changed(uint32_t flags) { 89 | _cb(_h, flags); 90 | } 91 | 92 | /*! 93 | * provides an interface to get resolve unicast routes from 94 | * the operating system's RIB 95 | */ 96 | class rib_def : public node, public mrib_origin { 97 | public: 98 | rib_def(); 99 | 100 | virtual bool check_startup(); 101 | virtual void shutdown(); 102 | 103 | virtual void check_initial_interfaces(); 104 | 105 | bool call_method(int, base_stream &, const std::vector &); 106 | 107 | const char *description() const; 108 | void return_prefix(mrib_def::prefix *); 109 | 110 | virtual bool dump_info(base_stream &) const; 111 | 112 | virtual void register_route(rib_watcher_base *, const inet6_addr &); 113 | virtual void unregister_route(rib_watcher_base *); 114 | virtual void update_route(rib_watcher_base *); 115 | 116 | interface *path_towards(const inet6_addr &) const; 117 | interface *path_towards(const inet6_addr &, inet6_addr &) const; 118 | interface *path_towards(const inet6_addr &, inet6_addr &, inet6_addr &) const; 119 | interface *path_towards(const inet6_addr &addr, inet6_addr &prefsrc, 120 | inet6_addr &nexthop, inet6_addr &record) const; 121 | 122 | void transfer_watchers(rib_def *); 123 | 124 | protected: 125 | typedef std::multimap notify_list; 126 | 127 | notify_list rt_notify_list; 128 | 129 | struct lookup_result { 130 | int dev; 131 | inet6_addr dst; 132 | in6_addr nexthop, source; 133 | uint32_t protocol, metric; 134 | }; 135 | 136 | virtual bool lookup_prefix(const in6_addr &, lookup_result &) const = 0; 137 | 138 | void update_all(); 139 | void prefix_changed(bool, const lookup_result &); 140 | 141 | property_def *populate_mrib; 142 | property_def *base_distance; 143 | }; 144 | 145 | #endif 146 | 147 | -------------------------------------------------------------------------------- /include/mrd/router.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Multicast Routing Daemon (MRD) 3 | * router.h 4 | * 5 | * Copyright (C) 2006, 2007 - Hugo Santos 6 | * Copyright (C) 2004..2006 - Universidade de Aveiro, IT Aveiro 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * Author: Hugo Santos 23 | */ 24 | 25 | #ifndef _mrd_router_h_ 26 | #define _mrd_router_h_ 27 | 28 | #include 29 | #include 30 | 31 | #include 32 | #include 33 | #include 34 | 35 | class mrd; 36 | class group; 37 | class router; 38 | class interface; 39 | 40 | class intfconf; 41 | class intfconf_node; 42 | class groupconf; 43 | class groupconf_node; 44 | 45 | class mfa_group; 46 | 47 | /*! 48 | * Each routing protocol (PIM, etc) in `mrd' derives from this 49 | * router class which provides an interface with the core router 50 | * for event notification, mfa interaction, etc. This class also 51 | * follows the configuration protocol through the `node' class. 52 | */ 53 | class router : public node, public source_discovery_sink { 54 | public: 55 | router(const char *); 56 | virtual ~router(); 57 | 58 | virtual void attach(mrd *); 59 | virtual bool check_startup(); 60 | virtual void shutdown(); 61 | 62 | /* logging */ 63 | base_stream &log() const; 64 | virtual base_stream &log_router_desc(base_stream &) const; 65 | 66 | /*! 67 | * router implementations should use this method instead of 68 | * mrd::get_interface_by_index in order to comply with configured 69 | * parameters, including the disabling of this router instance 70 | */ 71 | interface *get_interface_by_index(int) const; 72 | 73 | /*! 74 | * Event triggered whenever a new group instance is created. 75 | * router implementations should attach their own group_node 76 | * instances at this point if they wish to react to group 77 | * filter changes 78 | */ 79 | virtual void created_group(group *); 80 | virtual void released_group(group *); 81 | 82 | /*! 83 | * This method is called whenever a new interface is added to 84 | * the system. If for some reason the router instance wishes 85 | * to prevent the interface's inclusion, it should return false, 86 | * effectively vetoing the new interface 87 | */ 88 | virtual void add_interface(interface *); 89 | virtual void remove_interface(interface *); 90 | 91 | virtual intfconf_node *create_interface_configuration(intfconf *); 92 | virtual groupconf_node *create_group_configuration(groupconf *); 93 | 94 | virtual void mfa_notify(mfa_group_source *, const in6_addr &, const in6_addr &, 95 | uint32_t flags, mfa_group_source::action, interface *iif, 96 | ip6_hdr *, uint16_t alen, uint16_t len); 97 | 98 | void event(int, void *); 99 | }; 100 | 101 | #endif 102 | 103 | -------------------------------------------------------------------------------- /include/mrd/source_discovery.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Multicast Routing Daemon (MRD) 3 | * source_discovery.h 4 | * 5 | * Copyright (C) 2006, 2007 - Hugo Santos 6 | * Copyright (C) 2004..2006 - Universidade de Aveiro, IT Aveiro 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * Author: Hugo Santos 23 | */ 24 | 25 | #ifndef _mrd_source_discovery_h_ 26 | #define _mrd_source_discovery_h_ 27 | 28 | #include 29 | #include 30 | 31 | #include 32 | #include 33 | 34 | class group; 35 | class group_node; 36 | class groupconf; 37 | 38 | /*! 39 | * Source discovery base interface. Source discovery origin's supply 40 | * new sources to mrd's core which are then distributed to source sinks 41 | * and group nodes, triggering the creation of source states. 42 | */ 43 | class source_discovery_origin { 44 | public: 45 | virtual ~source_discovery_origin(); 46 | 47 | /*! 48 | * Returns the origin unique textual description. i.e. `static`, 49 | * `data-plane`, etc. 50 | */ 51 | virtual const char *origin_description() const = 0; 52 | 53 | /*! 54 | * may be called by source_discovery implementations in order to 55 | * advertise a new source to all active groups that match the supplied 56 | * group mask 57 | */ 58 | virtual void discovered_source(int ifindex, const inet6_addr &grpmask, 59 | const inet6_addr &source); 60 | /*! 61 | * may be called by source_discovery implementations in order to 62 | * advertise that the supplied source was lost to all active groups 63 | * that match the supplied group mask 64 | */ 65 | virtual void lost_source(const inet6_addr &groupmask, 66 | const inet6_addr &source); 67 | 68 | /*! 69 | * called by mrd whenever the interest of an active group on this 70 | * source discovery origin changes. if include=true, the current 71 | * known sources should be advertised via discovered_source 72 | */ 73 | virtual void group_interest_changed(group_node *, bool include); 74 | 75 | /*! 76 | * called by mrd whenever this source discovery origin instance 77 | * is attached to a group conf object. any childs and/or methods 78 | * and properties should be instantiated here 79 | */ 80 | virtual void groupconf_registered(groupconf *, bool include); 81 | }; 82 | 83 | class aggr_source_discovery : public source_discovery_origin { 84 | public: 85 | bool check_startup(); 86 | 87 | void discovered_source(int ifindex, const inet6_addr &groupmask, 88 | const inet6_addr &source); 89 | void lost_source(const inet6_addr &groupmask, 90 | const inet6_addr &source); 91 | 92 | void group_interest_changed(group_node *n, bool include); 93 | 94 | void dump_cache(base_stream &) const; 95 | 96 | protected: 97 | aggr_source_discovery(int keepalive); 98 | 99 | virtual void gc(); 100 | 101 | typedef std::pair sg_pair; 102 | typedef std::map cache; 103 | 104 | int add_to_cache(cache &, int, const inet6_addr &, const inet6_addr &); 105 | void run_gc(cache &); 106 | 107 | void dump_cache(base_stream &, const cache &) const; 108 | 109 | int m_keepalive; 110 | cache m_cache; 111 | 112 | timer m_gc_timer; 113 | }; 114 | 115 | /*! 116 | * Data plane based source discovery implementation. Operating system 117 | * modules should instantiate a `data-plane` origin and call discovered_source() 118 | * for each non-existant state with active flows 119 | */ 120 | class data_plane_source_discovery : public aggr_source_discovery { 121 | public: 122 | data_plane_source_discovery(); 123 | 124 | const char *origin_description() const { return "data-plane"; } 125 | }; 126 | 127 | /*! 128 | * Implements a static source origin. The sources to be advertised are populated 129 | * statically via configuration. 130 | */ 131 | class static_source_discovery : public source_discovery_origin { 132 | public: 133 | const char *origin_description() const { return "static"; } 134 | 135 | void group_interest_changed(group_node *n, bool include); 136 | 137 | void groupconf_registered(groupconf *, bool include); 138 | }; 139 | 140 | /*! 141 | * Registered source discovery sinks in mrd receive discovered_source events 142 | */ 143 | class source_discovery_sink { 144 | public: 145 | virtual ~source_discovery_sink(); 146 | 147 | /*! 148 | * the default implementation checks if the group exists, and if 149 | * so calls discovered_source with the group instance 150 | */ 151 | virtual void discovered_source(interface *, const inet6_addr &grpaddr, 152 | const inet6_addr &sourceaddr, 153 | source_discovery_origin *); 154 | 155 | virtual void discovered_source(interface *, group *, 156 | const inet6_addr &source, 157 | source_discovery_origin *); 158 | }; 159 | 160 | #endif 161 | 162 | -------------------------------------------------------------------------------- /include/mrd/support/lists.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Multicast Routing Daemon (MRD) 3 | * lists.h 4 | * 5 | * Copyright (C) 2006, 2007 - Hugo Santos 6 | * Copyright (C) 2004..2006 - Universidade de Aveiro, IT Aveiro 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * Author: Hugo Santos 23 | */ 24 | 25 | #ifndef _support_lists_h_ 26 | #define _support_lists_h_ 27 | 28 | struct list_node { 29 | struct list_node *next; 30 | }; 31 | 32 | struct dlist_node { 33 | struct dlist_node *prev, *next; 34 | }; 35 | 36 | #define container_of(ptr, type, member) \ 37 | ((type *)(((char *)ptr) - offsetof(type, member))) 38 | 39 | template 40 | static inline void list_push_front(T * &lst, T *node) { 41 | node->next = lst; 42 | lst = node; 43 | } 44 | 45 | template 46 | static inline T *list_pop_front(T * &lst) { 47 | if (!lst) 48 | return 0; 49 | T *head = lst; 50 | lst = lst->next; 51 | return head; 52 | } 53 | 54 | template 55 | static inline void list_insert_after(T * &lst, T *prev, T *node) { 56 | if (prev) { 57 | node->next = prev->next; 58 | prev->next = node; 59 | } else { 60 | node->next = lst; 61 | lst = node; 62 | } 63 | } 64 | 65 | template 66 | static inline bool list_search_remove(T * &lst, T *node) { 67 | T *prev = 0; 68 | 69 | for (T *curr = lst; curr; curr = curr->next) { 70 | if (curr == node) { 71 | /* unlink the node from the list */ 72 | if (prev) 73 | prev->next = curr->next; 74 | else 75 | lst = curr->next; 76 | return true; 77 | } 78 | 79 | prev = curr; 80 | } 81 | 82 | return false; 83 | } 84 | 85 | template 86 | static inline void dlist_push_front(T * &lst, T *node) { 87 | node->prev = 0; 88 | if (lst) 89 | lst->prev = node; 90 | node->next = lst; 91 | lst = node; 92 | } 93 | 94 | template 95 | static inline T *dlist_pop_front(T * &lst) { 96 | if (!lst) 97 | return 0; 98 | 99 | T *head = lst; 100 | 101 | lst = lst->next; 102 | if (lst) 103 | lst->prev = 0; 104 | 105 | return head; 106 | } 107 | 108 | template 109 | static inline void list_remove(T * &node) { 110 | list_pop_front(node); 111 | } 112 | 113 | template 114 | static inline void dlist_remove(T * &lst, T *node) { 115 | if (!node->prev) { 116 | if (node->next) { 117 | node->next->prev = 0; 118 | lst = node->next; 119 | } else { 120 | lst = 0; 121 | } 122 | } else { 123 | node->prev->next = node->next; 124 | if (node->prev->next) 125 | node->prev->next->prev = node->prev; 126 | } 127 | } 128 | 129 | #endif 130 | 131 | -------------------------------------------------------------------------------- /include/mrd/support/objpool.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Multicast Routing Daemon (MRD) 3 | * objpool.h 4 | * 5 | * Copyright (C) 2006, 2007 - Hugo Santos 6 | * Copyright (C) 2004..2006 - Universidade de Aveiro, IT Aveiro 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * Author: Hugo Santos 23 | */ 24 | 25 | #ifndef _objpool_h_ 26 | #define _objpool_h_ 27 | 28 | #include 29 | #include 30 | 31 | #include /* for placement new */ 32 | 33 | #ifndef SUPPORT_NO_POOLING 34 | class base_objpool { 35 | public: 36 | base_objpool(uint32_t _count, uint32_t _single); 37 | base_objpool(const base_objpool &pool); 38 | 39 | void *generic_request_obj(); 40 | 41 | protected: 42 | struct _memchunk; 43 | 44 | struct _objhead { 45 | /* 2 * sizeof(void *) per object */ 46 | _memchunk *parent; 47 | _objhead *next; 48 | uint8_t _obj[0]; 49 | } __attribute((packed)); 50 | 51 | struct _memchunk { 52 | uint8_t *chunk, *endchunk; 53 | uint32_t count, free; 54 | _memchunk *prev, *next; 55 | _objhead *head; 56 | } __attribute((packed)); 57 | 58 | void base_return_obj(void *obj, _memchunk * &m); 59 | 60 | _memchunk *_alloc_chunk(uint32_t count); 61 | void _free_chunk(_memchunk *m); 62 | _memchunk *_find_chunk(_objhead *h); 63 | void _clear_memchunks(_memchunk *); 64 | void _clear_memchunks(); 65 | 66 | uint32_t granularity, single; 67 | 68 | _memchunk *light, *heavy; 69 | }; 70 | 71 | template 72 | class objpool : public base_objpool { 73 | public: 74 | objpool(uint32_t _count) 75 | : base_objpool(_count, sizeof(objtype)) {} 76 | 77 | objpool(const objpool &pool) 78 | : base_objpool(pool) {} 79 | 80 | ~objpool() { 81 | clear(); 82 | } 83 | 84 | void clear() { 85 | clear(heavy); 86 | clear(light); 87 | 88 | _clear_memchunks(); 89 | } 90 | 91 | objtype *request_obj() { 92 | void *p = generic_request_obj(); 93 | if (!p) 94 | return 0; 95 | 96 | /* XXX handle exceptions in constructor */ 97 | 98 | return new (p) objtype(); 99 | } 100 | 101 | /* One of each helper method below for the number of arguments */ 102 | 103 | template 104 | objtype *request_obj(const Arg &arg) { 105 | void *p = generic_request_obj(); 106 | if (!p) 107 | return 0; 108 | 109 | /* XXX handle exceptions in constructor */ 110 | 111 | return new (p) objtype(arg); 112 | } 113 | 114 | template 115 | objtype *request_obj(const Arg1 &arg1, const Arg2 &arg2) { 116 | void *p = generic_request_obj(); 117 | if (!p) 118 | return 0; 119 | 120 | /* XXX handle exceptions in constructor */ 121 | 122 | return new (p) objtype(arg1, arg2); 123 | } 124 | 125 | void return_obj(objtype *obj) { 126 | _memchunk *m; 127 | 128 | base_return_obj(obj, m); 129 | 130 | obj->~objtype(); 131 | 132 | if (m->free == m->count) { 133 | if (!m->prev) 134 | light = m->next; 135 | else 136 | m->prev->next = m->next; 137 | 138 | _free_chunk(m); 139 | } 140 | } 141 | 142 | private: 143 | void clear(_memchunk *head) { 144 | uint32_t one_size = sizeof(_objhead) + sizeof(objtype); 145 | 146 | for (; head; head = head->next) { 147 | for (uint8_t *p = head->chunk; p < head->endchunk; 148 | p += one_size) { 149 | _objhead *h = (_objhead *)p; 150 | 151 | if (h->next == 0) 152 | ((objtype *)&h->_obj)->~objtype(); 153 | } 154 | } 155 | } 156 | }; 157 | 158 | #else 159 | 160 | template 161 | class objpool { 162 | public: 163 | objpool(uint32_t _count) { 164 | } 165 | 166 | objpool(const objpool &pool) { 167 | } 168 | 169 | ~objpool() { 170 | } 171 | 172 | void clear() { 173 | /* empty */ 174 | } 175 | 176 | objtype *request_obj() { 177 | return new objtype(); 178 | } 179 | 180 | template 181 | objtype *request_obj(const Arg &arg) { 182 | return new objtype(arg); 183 | } 184 | 185 | template 186 | objtype *request_obj(const Arg1 &arg1, const Arg2 &arg2) { 187 | return new objtype(arg1, arg2); 188 | } 189 | 190 | void return_obj(objtype *obj) { 191 | delete obj; 192 | } 193 | }; 194 | #endif 195 | 196 | #endif 197 | 198 | -------------------------------------------------------------------------------- /include/mrd/support/refcount.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Multicast Routing Daemon (MRD) 3 | * refcount.h 4 | * 5 | * Copyright (C) 2006, 2007 - Hugo Santos 6 | * Copyright (C) 2004..2006 - Universidade de Aveiro, IT Aveiro 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * Author: Hugo Santos 23 | */ 24 | 25 | #ifndef _support_refcount_h_ 26 | #define _support_refcount_h_ 27 | 28 | class refcountable { 29 | public: 30 | refcountable(); 31 | virtual ~refcountable(); 32 | 33 | void grab(); 34 | void release(); 35 | 36 | int get_refcount() const; 37 | 38 | protected: 39 | virtual void destructor(); 40 | 41 | private: 42 | int _refcount; 43 | }; 44 | 45 | class auto_grab { 46 | public: 47 | auto_grab(refcountable *_t) : t(_t) { 48 | t->grab(); 49 | } 50 | 51 | ~auto_grab() { 52 | if (t) 53 | t->release(); 54 | } 55 | 56 | private: 57 | refcountable *t; 58 | }; 59 | 60 | inline refcountable::refcountable() : _refcount(0) {} 61 | inline refcountable::~refcountable() { /* assert(_refcount == 0); */ } 62 | 63 | inline void refcountable::grab() { 64 | _refcount ++; 65 | } 66 | 67 | inline void refcountable::release() { 68 | _refcount --; 69 | if (_refcount == 0) 70 | destructor(); 71 | } 72 | 73 | inline int refcountable::get_refcount() const { 74 | return _refcount; 75 | } 76 | 77 | inline void refcountable::destructor() { 78 | delete this; 79 | } 80 | 81 | #endif 82 | 83 | -------------------------------------------------------------------------------- /include/mrd/support/uint_n.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Multicast Routing Daemon (MRD) 3 | * uint_n.h 4 | * 5 | * Copyright (C) 2007 Hugo Santos 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | * 21 | * Author: Hugo Santos 22 | */ 23 | 24 | #ifndef __uint_n__h 25 | #define __uint_n__h 26 | 27 | #include 28 | 29 | namespace priv { 30 | /* these are used just to use c++ type-matching 31 | * capabilities through overriding */ 32 | static inline uint16_t __host_to_net(uint16_t v) { return htons(v); } 33 | static inline uint32_t __host_to_net(uint32_t v) { return htonl(v); } 34 | 35 | static inline uint16_t __net_to_host(uint16_t v) { return ntohs(v); } 36 | static inline uint32_t __net_to_host(uint32_t v) { return ntohl(v); } 37 | 38 | template 39 | struct uint_n { 40 | _Base __value; 41 | 42 | uint_n() : __value(0) {} 43 | 44 | _Base host() const { return __net_to_host(__value); } 45 | 46 | static uint_n<_Base> net(_Base v) { 47 | uint_n<_Base> u; 48 | u.__value = __host_to_net(v); 49 | return u; 50 | } 51 | } __attribute__ ((packed)); 52 | } 53 | 54 | typedef priv::uint_n uint16n_t; 55 | typedef priv::uint_n uint32n_t; 56 | 57 | static inline uint16n_t hton(uint16_t value) { return uint16n_t::net(value); } 58 | static inline uint32n_t hton(uint32_t value) { return uint32n_t::net(value); } 59 | 60 | static inline uint16_t ntoh(uint16n_t value) { return value.host(); } 61 | static inline uint32_t ntoh(uint32n_t value) { return value.host(); } 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /include/mrdpriv/bgp/def.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Multicast Routing Daemon (MRD) 3 | * bgp/def.h 4 | * 5 | * Copyright (C) 2006, 2007 - Hugo Santos 6 | * Copyright (C) 2004..2006 - Universidade de Aveiro, IT Aveiro 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * Author: Hugo Santos 23 | */ 24 | 25 | #ifndef _mrd_bgp_def_h_ 26 | #define _mrd_bgp_def_h_ 27 | 28 | #include 29 | 30 | #include 31 | #include 32 | 33 | #include 34 | 35 | class bgp_message { 36 | public: 37 | bgp_message(); 38 | bgp_message(uint8_t); 39 | bgp_message(const bgp_message &); 40 | virtual ~bgp_message(); 41 | 42 | virtual bool decode(encoding_buffer &); 43 | virtual bool encode(encoding_buffer &) const; 44 | 45 | virtual uint16_t length() const { return len; } 46 | 47 | const char *type_name() const; 48 | 49 | uint16_t len; 50 | uint8_t type; 51 | }; 52 | 53 | class bgp_open_message : public bgp_message { 54 | public: 55 | bgp_open_message(); 56 | bgp_open_message(const bgp_message &); 57 | 58 | virtual uint16_t length() const; 59 | 60 | bool decode(encoding_buffer &); 61 | bool encode(encoding_buffer &) const; 62 | 63 | uint8_t version; 64 | uint16_t as; 65 | uint16_t holdtime; 66 | uint32_t bgpid; 67 | 68 | enum { 69 | IPV6 = 2 70 | }; 71 | 72 | enum { 73 | UNICAST = 1, 74 | MULTICAST, 75 | UNICAST_MULTICAST 76 | }; 77 | 78 | typedef std::pair capability; 79 | std::vector capabilities; 80 | }; 81 | 82 | class bgp_as_path : public std::vector { 83 | public: 84 | bgp_as_path &prepend(uint16_t value) { insert(begin(), value); return *this; } 85 | }; 86 | 87 | typedef std::pair bgp_community; 88 | typedef std::vector bgp_communities; 89 | 90 | class bgp_update_message : public bgp_message { 91 | public: 92 | bgp_update_message(); 93 | bgp_update_message(const bgp_message &); 94 | 95 | virtual uint16_t length() const; 96 | 97 | bool decode(encoding_buffer &); 98 | bool encode(encoding_buffer &) const; 99 | 100 | enum { 101 | IGP = 0, 102 | INCOMPLETE = 2 103 | }; 104 | 105 | uint8_t origin; 106 | uint32_t localpref, med; 107 | 108 | bgp_as_path as_path; 109 | 110 | bgp_communities communities; 111 | 112 | std::vector nexthops; 113 | std::vector prefixes; 114 | std::vector unreach_prefixes; 115 | }; 116 | 117 | class bgp_notification_message : public bgp_message { 118 | public: 119 | bgp_notification_message(); 120 | bgp_notification_message(const bgp_message &); 121 | 122 | virtual uint16_t length() const; 123 | 124 | bool decode(encoding_buffer &); 125 | bool encode(encoding_buffer &) const; 126 | 127 | uint8_t errorcode; 128 | uint8_t suberrorcode; 129 | }; 130 | 131 | #endif 132 | 133 | -------------------------------------------------------------------------------- /include/mrdpriv/bsd/rib.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Multicast Routing Daemon (MRD) 3 | * bsd/rib.h 4 | * 5 | * Copyright (C) 2006, 2007 - Hugo Santos 6 | * Copyright (C) 2004..2006 - Universidade de Aveiro, IT Aveiro 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * Author: Hugo Santos 23 | */ 24 | 25 | #ifndef _mrd_bsd_rib_h_ 26 | #define _mrd_bsd_rib_h_ 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | struct rt_msghdr; 35 | struct if_msghdr; 36 | struct ifa_msghdr; 37 | struct rt_addrinfo; 38 | 39 | class bsd_rib : public rib_def { 40 | public: 41 | bsd_rib(); 42 | 43 | bool check_startup(); 44 | void shutdown(); 45 | 46 | void check_initial_interfaces(); 47 | 48 | bool lookup_prefix(const in6_addr &, lookup_result &) const; 49 | 50 | void process_messages(rt_msghdr *, int len); 51 | void process_if_msg(if_msghdr *); 52 | void process_ifa_msg(int, ifa_msghdr *, bool); 53 | void process_addrinfo(int, rt_addrinfo *, bool); 54 | 55 | bool fill_lookup_result(lookup_result &, rt_msghdr *) const; 56 | 57 | void data_pending(uint32_t); 58 | void event_pending(rt_msghdr *); 59 | 60 | rt_msghdr *read_until(unsigned) const; 61 | 62 | int rtsock; 63 | socket0 evsock; 64 | mutable uint32_t rtseq; 65 | }; 66 | 67 | #endif 68 | 69 | -------------------------------------------------------------------------------- /include/mrdpriv/console/console.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Multicast Routing Daemon (MRD) 3 | * console.h 4 | * 5 | * Copyright (C) 2006, 2007 - Hugo Santos 6 | * Copyright (C) 2004..2006 - Universidade de Aveiro, IT Aveiro 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * Author: Hugo Santos 23 | */ 24 | 25 | #ifndef _mrd_console_h_ 26 | #define _mrd_console_h_ 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | class mrd; 44 | 45 | class console_connection; 46 | 47 | class console_module : public mrd_module, public node { 48 | public: 49 | console_module(mrd *m, void *dlh); 50 | ~console_module(); 51 | 52 | const char *description() const; 53 | 54 | bool check_startup(); 55 | void shutdown(); 56 | 57 | bool call_method(int id, base_stream &, 58 | const std::vector &); 59 | bool negate_method(int id, base_stream &, 60 | const std::vector &); 61 | bool output_info(base_stream &ctx, const std::vector &) const; 62 | 63 | #ifndef CONSOLE_NO_TELNET 64 | void new_client(uint32_t); 65 | #endif 66 | void new_unix_client(uint32_t); 67 | 68 | void release_connection(console_connection *); 69 | 70 | bool password_for(const inet6_addr &, const char *, std::string &) const; 71 | 72 | #ifndef CONSOLE_NO_TELNET 73 | socket0 srvsock; 74 | #endif 75 | socket0 unix_srvsock; 76 | 77 | std::list connections; 78 | 79 | struct auth_desc { 80 | std::string username; 81 | std::string password; 82 | }; 83 | 84 | typedef std::map, 86 | std::greater > allow_local_def; 87 | 88 | allow_local_def acl; 89 | 90 | bool allow_addr(const std::vector &); 91 | bool deny_addr(const std::vector &); 92 | bool allow_local(const std::vector &); 93 | bool attach_log(base_stream &, const std::vector &); 94 | 95 | bool show_history(base_stream &); 96 | 97 | console_connection *calling_connection(base_stream &) const; 98 | }; 99 | 100 | extern console_module *console; 101 | 102 | class console_log_node : public tb_log_node { 103 | public: 104 | console_log_node(console_connection *); 105 | 106 | void rename(const char *); 107 | 108 | void log(int, int, const char *, bool newline); 109 | 110 | console_connection *_conn; 111 | std::string _buf; 112 | }; 113 | 114 | class console_connection : public stream_flusher { 115 | public: 116 | console_connection(mrd *core, int); 117 | virtual ~console_connection() {} 118 | 119 | virtual bool check_startup(); 120 | void shutdown(); 121 | void doom(); 122 | 123 | virtual void release(); 124 | 125 | void data_available(uint32_t); 126 | virtual void process_input(int) = 0; 127 | 128 | virtual bool process_line(const char *); 129 | 130 | void process_deep_line(parser_context *); 131 | 132 | enum { 133 | CONSISTENCY_ERROR = -3, 134 | INPUT_ERROR = -2, 135 | END_LINE = -1, 136 | OK = 0 137 | }; 138 | 139 | int transform(parser_context *, node *, node::content_type, 140 | node * &) const; 141 | int transform(parser_context *, node *, node::content_type, 142 | node * &, std::string &) const; 143 | 144 | void writeclient(const char *); 145 | 146 | virtual void flushed(const char *, bool) = 0; 147 | 148 | virtual void dump_history(base_stream &) const; 149 | 150 | virtual void log(bool end); 151 | 152 | mrd *m_mrd; 153 | 154 | bool is_doomed; 155 | 156 | socket0 sock; 157 | 158 | mutable base_stream _output; 159 | 160 | unsigned char buffer[1024]; 161 | 162 | std::string bufbuffer; 163 | 164 | int advance_one(parser_context *, node *); 165 | int check_termination(parser_context *, node *); 166 | void dump_partial(const char *); 167 | void dump_partial(node *, parser_context *, bool); 168 | 169 | bool autoclose; 170 | console_log_node *clog; 171 | }; 172 | 173 | class telnet_console_connection : public console_connection { 174 | public: 175 | telnet_console_connection(mrd *core, int, const inet6_addr &, uint32_t); 176 | ~telnet_console_connection(); 177 | 178 | bool check_startup(); 179 | void release(); 180 | 181 | const inet6_addr &peeraddr() const { return c_peeraddr; } 182 | 183 | bool authenticate(const char *); 184 | 185 | void process_input(int); 186 | 187 | void flushed(const char *, bool); 188 | 189 | bool process_line(const char *); 190 | 191 | void dump_history(base_stream &) const; 192 | void log(bool end); 193 | private: 194 | enum { 195 | NoState, 196 | WaitingPassword, 197 | GotAllData, 198 | }; 199 | 200 | bool process_cmd(); 201 | 202 | bool tabcomplete(); 203 | 204 | void show_prompt(); 205 | void set_prompt(const char *); 206 | 207 | void clearline(); 208 | void redisplay_input(); 209 | 210 | void cmd(char c, char opt); 211 | 212 | void release_connection(); 213 | 214 | void history_up(); 215 | void history_down(); 216 | 217 | timer conn_timer; 218 | 219 | std::deque ctlbuf; 220 | 221 | int pmode; 222 | 223 | bool will_echo; 224 | bool should_echo; 225 | bool input_is_updated; 226 | 227 | std::string inputbuf; 228 | std::string tmp_inputbuf; 229 | 230 | std::vector history; 231 | int history_pos; 232 | 233 | int authenticate_state; 234 | std::string username; 235 | 236 | std::string prompt; 237 | 238 | inet6_addr c_peeraddr; 239 | }; 240 | 241 | class unix_console_connection : public console_connection { 242 | public: 243 | unix_console_connection(mrd *core, int); 244 | 245 | void process_input(int); 246 | 247 | void release(); 248 | 249 | void flushed(const char *, bool); 250 | }; 251 | 252 | #endif 253 | 254 | -------------------------------------------------------------------------------- /include/mrdpriv/dummy/mfa.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Multicast Routing Daemon (MRD) 3 | * dummy/mfa.h 4 | * 5 | * Copyright (C) 2006, 2007 - Hugo Santos 6 | * Copyright (C) 2004..2006 - Universidade de Aveiro, IT Aveiro 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * Author: Hugo Santos 23 | */ 24 | 25 | #ifndef _mrd_dummy_mfa_h_ 26 | #define _mrd_dummy_mfa_h_ 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #include 35 | 36 | #include 37 | #include 38 | 39 | class interface; 40 | class router; 41 | 42 | struct ip6_hdr; 43 | 44 | class dummy_mfa_group_source; 45 | class dummy_mfa_group; 46 | class dummy_mfa_instance; 47 | class dummy_mfa; 48 | 49 | class dummy_mfa_group_source : public mfa_group_source { 50 | public: 51 | dummy_mfa_group_source(dummy_mfa_group *, const in6_addr &, uint32_t, action *); 52 | 53 | void change_flags(uint32_t, action); 54 | 55 | void set_iif(interface *); 56 | void release_iif(interface *); 57 | 58 | void add_oif(interface *); 59 | void release_oif(interface *); 60 | 61 | void forward(ip6_hdr *, uint16_t) const; 62 | }; 63 | 64 | class dummy_mfa_group : public mfa_group { 65 | public: 66 | dummy_mfa_group(dummy_mfa_instance *, const inet6_addr &); 67 | 68 | void activate(bool); 69 | 70 | mfa_group_source *create_source_state(const in6_addr &, void *); 71 | void release_source_state(mfa_group_source *); 72 | 73 | void change_default_flags(uint32_t, mfa_group_source::action); 74 | }; 75 | 76 | class dummy_mfa_instance : public mfa_instance { 77 | public: 78 | dummy_mfa_instance(dummy_mfa *, router *); 79 | 80 | mfa_group *create_group(const inet6_addr &, void *); 81 | void release_group(mfa_group *); 82 | 83 | void change_group_default_flags(uint32_t, mfa_group_source::action); 84 | }; 85 | 86 | class dummy_mfa : public mfa_core { 87 | public: 88 | dummy_mfa(); 89 | 90 | bool check_startup(); 91 | void shutdown(); 92 | 93 | mfa_instance *alloc_instance(router *); 94 | 95 | void added_interface(interface *); 96 | void removed_interface(interface *); 97 | }; 98 | 99 | #endif 100 | 101 | -------------------------------------------------------------------------------- /include/mrdpriv/dummy/rib.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Multicast Routing Daemon (MRD) 3 | * dummy/rib.h 4 | * 5 | * Copyright (C) 2006, 2007 - Hugo Santos 6 | * Copyright (C) 2004..2006 - Universidade de Aveiro, IT Aveiro 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * Author: Hugo Santos 23 | */ 24 | 25 | #ifndef _mrd_dummy_rib_h_ 26 | #define _mrd_dummy_rib_h_ 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | #include 34 | 35 | class dummy_rib : public rib_def { 36 | public: 37 | dummy_rib(); 38 | 39 | bool check_startup(); 40 | void shutdown(); 41 | 42 | void register_route(rib_watcher_base *, const inet6_addr &); 43 | void unregister_route(rib_watcher_base *); 44 | void update_route(rib_watcher_base *); 45 | 46 | interface *path_towards(const inet6_addr &, inet6_addr &, inet6_addr &, inet6_addr &) const; 47 | }; 48 | 49 | #endif 50 | 51 | -------------------------------------------------------------------------------- /include/mrdpriv/icmp_inet6.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Multicast Routing Daemon (MRD) 3 | * mrdpriv/icmp_inet6.h 4 | * 5 | * Copyright (C) 2006, 2007 - Hugo Santos 6 | * Copyright (C) 2004..2006 - Universidade de Aveiro, IT Aveiro 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * Author: Hugo Santos 23 | */ 24 | 25 | #ifndef _mrd_icmp_inet6_h_ 26 | #define _mrd_icmp_inet6_h_ 27 | 28 | #include 29 | #include 30 | 31 | class icmp_inet6 : public icmp_base { 32 | public: 33 | icmp_inet6(); 34 | 35 | bool check_startup(); 36 | void shutdown(); 37 | 38 | bool send_icmp(const interface *, const in6_addr &, 39 | const in6_addr &, int, icmp6_hdr *, uint16_t) const; 40 | 41 | void added_interface(interface *); 42 | void removed_interface(interface *); 43 | 44 | void data_available(uint32_t); 45 | 46 | bool apply_icmp_filter(); 47 | 48 | void registration_changed(); 49 | void internal_require_mgroup(const in6_addr &, bool); 50 | 51 | mutable socket6 m_icmpsock; 52 | }; 53 | 54 | #endif 55 | 56 | -------------------------------------------------------------------------------- /include/mrdpriv/ks_mfa.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Multicast Routing Daemon (MRD) 3 | * ks_mfa.h 4 | * 5 | * Copyright (C) 2006, 2007 - Hugo Santos 6 | * Copyright (C) 2004..2006 - Universidade de Aveiro, IT Aveiro 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * Author: Hugo Santos 23 | */ 24 | 25 | #ifndef _mrd_ks_mfa_h_ 26 | #define _mrd_ks_mfa_h_ 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | #ifdef OS_LINUX 40 | #include 41 | #else 42 | #include 43 | #endif 44 | 45 | class interface; 46 | class router; 47 | 48 | struct ip6_hdr; 49 | 50 | class ks_mfa_group_source; 51 | class ks_mfa_group; 52 | class ks_mfa; 53 | 54 | class ks_mfa_group_source : public mfa_group_source { 55 | public: 56 | ks_mfa_group_source(ks_mfa_group *, const in6_addr &, uint32_t, action *); 57 | virtual ~ks_mfa_group_source(); 58 | 59 | const in6_addr &address() const { return m_addr.address(); } 60 | 61 | bool is_iif(interface *intf) const { return intf == m_iif; } 62 | bool has_oif(interface *) const; 63 | 64 | void change_flags(uint32_t, action); 65 | 66 | void set_iif(interface *); 67 | void release_iif(interface *); 68 | 69 | void add_oif(interface *); 70 | void release_oif(interface *); 71 | 72 | void get_input_counter(uint64_t &) const; 73 | void get_forwarding_counter(uint64_t &) const; 74 | 75 | void output_info(base_stream &) const; 76 | 77 | private: 78 | typedef std::vector oifs; 79 | 80 | ks_mfa_group *m_owner; 81 | inet6_addr m_addr; 82 | 83 | interface *m_iif; 84 | oifs m_oifs; 85 | 86 | mf6cctl m_ks_state; 87 | 88 | uint32_t m_flags; 89 | uint32_t m_interest_flags; 90 | 91 | friend class ks_mfa; 92 | }; 93 | 94 | class ks_mfa_group : public mfa_group { 95 | public: 96 | ks_mfa_group(router *, const inet6_addr &); 97 | 98 | const inet6_addr &addr() const { return m_addr; } 99 | 100 | void activate(bool); 101 | 102 | mfa_group_source *create_source_state(const in6_addr &, void *); 103 | mfa_group_source *get_source_state(const in6_addr &) const; 104 | void release_source_state(mfa_group_source *); 105 | 106 | void change_default_flags(uint32_t, mfa_group_source::action); 107 | 108 | void output_info(base_stream &) const; 109 | 110 | private: 111 | ks_mfa_group_source *match_source(const in6_addr &addr) const; 112 | 113 | typedef std::map sources; 114 | 115 | sources m_sources; 116 | 117 | enum state { 118 | running, 119 | pending, 120 | denied 121 | }; 122 | 123 | state m_state; 124 | 125 | inet6_addr m_addr; 126 | 127 | uint32_t m_flags; 128 | mfa_group_source::action m_actions[mfa_group_source::event_count]; 129 | }; 130 | 131 | inline ks_mfa_group_source *ks_mfa_group::match_source(const in6_addr &addr) const { 132 | sources::const_iterator k = m_sources.find(addr); 133 | if (k != m_sources.end()) { 134 | return k->second; 135 | } 136 | 137 | return 0; 138 | } 139 | 140 | class ks_mfa : public mfa_core { 141 | public: 142 | ks_mfa(); 143 | 144 | bool pre_startup(); 145 | bool check_startup(); 146 | void shutdown(); 147 | 148 | bool supports_stats() const { return true; } 149 | 150 | void added_interface(interface *); 151 | void removed_interface(interface *); 152 | 153 | bool output_info(base_stream &, const std::vector &) const; 154 | 155 | void data_available(interface *, int); 156 | 157 | int vif(interface *iif) const; 158 | void commit(mf6cctl *, bool = false); 159 | 160 | void discovered_source(int, const inet6_addr &, const inet6_addr &); 161 | 162 | mfa_group *create_group(router *, const inet6_addr &, void *); 163 | mfa_group *get_group(const inet6_addr &) const; 164 | void release_group(mfa_group *); 165 | 166 | void change_group_default_flags(uint32_t, mfa_group_source::action); 167 | 168 | void forward(interface *, ip6_hdr *, uint16_t) const; 169 | 170 | uint32_t m_grpflags; 171 | mfa_group_source::action m_grpactions[mfa_group_source::event_count]; 172 | 173 | void get_input_counter(const ks_mfa_group_source *, uint64_t &); 174 | void get_forwarding_counter(const ks_mfa_group_source *, uint64_t &); 175 | 176 | void get_source_counters(const ks_mfa_group_source *, sioc_sg_req6 *); 177 | 178 | private: 179 | int m_icmpsock; 180 | 181 | void kernel_data_pending(uint32_t); 182 | 183 | socket0 m_sock; 184 | 185 | std::map vifs; 186 | std::map rev_vifs; 187 | 188 | data_plane_source_discovery data_plane_sourcedisc; 189 | 190 | ks_mfa_group *match_group(const in6_addr &) const; 191 | 192 | typedef std::map groups; 193 | 194 | groups m_groups; 195 | }; 196 | 197 | inline ks_mfa_group *ks_mfa::match_group(const in6_addr &addr) const { 198 | for (groups::const_iterator k = m_groups.begin(); 199 | k != m_groups.end(); ++k) { 200 | if (k->first.matches(addr)) { 201 | return k->second; 202 | } 203 | } 204 | 205 | return 0; 206 | } 207 | 208 | inline bool ks_mfa_group_source::has_oif(interface *oif) const { 209 | return std::find(m_oifs.begin(), m_oifs.end(), oif) != m_oifs.end(); 210 | } 211 | 212 | #endif 213 | 214 | -------------------------------------------------------------------------------- /include/mrdpriv/linux/icmp_raw.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Multicast Routing Daemon (MRD) 3 | * mrdpriv/linux/icmp_raw.h 4 | * 5 | * Copyright (C) 2010 - CSC - IT Center for Science Ltd. 6 | * Copyright (C) 2006, 2007 - Hugo Santos 7 | * Copyright (C) 2004..2006 - Universidade de Aveiro, IT Aveiro 8 | * 9 | * This program is free software; you can redistribute it and/or modify 10 | * it under the terms of the GNU General Public License as published by 11 | * the Free Software Foundation; either version 2 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License 20 | * along with this program; if not, write to the Free Software 21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | * 23 | * Author: Hugo Santos 24 | */ 25 | 26 | #ifndef _mrd_linux_icmp_raw_h_ 27 | #define _mrd_linux_icmp_raw_h_ 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | class linux_icmp_raw : public icmp_inet6 { 34 | public: 35 | linux_icmp_raw(); 36 | 37 | bool check_startup(); 38 | void shutdown(); 39 | 40 | void added_interface(interface *); 41 | void removed_interface(interface *); 42 | 43 | typedef linux_raw_socket raw_socket; 44 | 45 | void data_available(raw_socket *); 46 | 47 | void registration_changed(); 48 | void internal_require_mgroup(const in6_addr &, bool); 49 | 50 | private: 51 | int create_socket(interface *); 52 | 53 | typedef std::map ifid_socket_map; 54 | ifid_socket_map m_ifid_socket; 55 | }; 56 | 57 | #endif 58 | 59 | -------------------------------------------------------------------------------- /include/mrdpriv/linux/raw_socket.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Multicast Routing Daemon (MRD) 3 | * mrdpriv/linux/raw_socket.h 4 | * 5 | * Copyright (C) 2010 - CSC - IT Center for Science Ltd. 6 | * Copyright (C) 2006, 2007 - Hugo Santos 7 | * Copyright (C) 2004..2006 - Universidade de Aveiro, IT Aveiro 8 | * 9 | * This program is free software; you can redistribute it and/or modify 10 | * it under the terms of the GNU General Public License as published by 11 | * the Free Software Foundation; either version 2 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License 20 | * along with this program; if not, write to the Free Software 21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | * 23 | * Author: Teemu Kiviniemi 24 | */ 25 | 26 | #ifndef _mrd_linux_raw_socket_h_ 27 | #define _mrd_linux_raw_socket_h_ 28 | 29 | #include 30 | 31 | template 32 | class linux_raw_socket : public socket_base { 33 | public: 34 | linux_raw_socket(const char *name, Holder *holder); 35 | 36 | void callback(uint32_t); 37 | 38 | #ifndef LINUX_NO_MMAP 39 | void *m_mmapped; 40 | uint32_t m_framesize; 41 | uint32_t m_mmappedlen; 42 | uint8_t *m_mmapbuf; 43 | #endif 44 | private: 45 | Holder *m_holder; 46 | }; 47 | 48 | template 49 | linux_raw_socket::linux_raw_socket(const char *name, Holder *holder) 50 | : socket_base(name), 51 | #ifndef LINUX_NO_MMAP 52 | m_mmapped(NULL), 53 | m_framesize(2048), 54 | m_mmappedlen(1024*1024), 55 | m_mmapbuf(NULL), 56 | #endif 57 | m_holder(holder) { 58 | } 59 | 60 | template 61 | void linux_raw_socket::callback(uint32_t) { 62 | m_holder->data_available(this); 63 | } 64 | 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /include/mrdpriv/linux/translator.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Multicast Routing Daemon (MRD) 3 | * translator.h - IPv4 to IPv6 multicast translator 4 | * 5 | * Copyright (C) 2009..2011 - Teemu Kiviniemi 6 | * Copyright (C) 2009 - CSC - IT Center for Science Ltd. 7 | * Copyright (C) 2006, 2007 - Hugo Santos 8 | * Copyright (C) 2004..2006 - Universidade de Aveiro, IT Aveiro 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 | * 24 | * Author: Teemu Kiviniemi 25 | */ 26 | 27 | #ifndef _mrd_translator_h_ 28 | #define _mrd_translator_h_ 29 | 30 | #include 31 | #include 32 | #include 33 | 34 | #include 35 | #include 36 | 37 | #include 38 | 39 | class interface; 40 | class us_mfa; 41 | 42 | /*! 43 | * IPv4 to IPv6 multicast translator 44 | */ 45 | class translator : public node, public icmp_handler, public mrib_origin { 46 | public: 47 | 48 | translator(us_mfa *); 49 | ~translator(); 50 | 51 | /* Pre-initialization */ 52 | bool pre_startup(); 53 | 54 | /* Initialization */ 55 | bool check_startup(); 56 | 57 | /* De-initialization */ 58 | void shutdown(); 59 | 60 | /* Return node description */ 61 | const char *description() const; 62 | 63 | /* Dump node information */ 64 | bool output_info(base_stream &, const std::vector &) const; 65 | 66 | /* Join/leave a group */ 67 | void change_group_state(const in6_addr &, bool); 68 | 69 | /* Join/leave an SSM channel */ 70 | void change_source_state(const in6_addr &, const in6_addr &, bool); 71 | 72 | /* Handle incoming ICMPv6 messages. */ 73 | void icmp_message_available(interface *, const in6_addr &, const in6_addr &, 74 | icmp6_hdr *, int); 75 | 76 | /* MRD event handler */ 77 | void event(int, void *); 78 | 79 | /* Set new MTU for a destination. */ 80 | void set_mtu(const in6_addr &, uint32_t); 81 | 82 | /* Handle a new prefix in MRIB. */ 83 | void prefix_added(const inet6_addr &src, mrib_def::metric_def metric, 84 | const mrib_def::prefix &prefix); 85 | 86 | /* Required by mrib_origin, not used here. */ 87 | void return_prefix(mrib_def::prefix *); 88 | 89 | private: 90 | 91 | /* Receive incoming IPv4 packets */ 92 | void data_available(uint32_t); 93 | 94 | /* Handle and translate an incoming IPv4 packet */ 95 | void handle_ipv4(const int, uint8_t *, const uint16_t); 96 | 97 | /* Send an IPv6 packet in fragments. buf must contain an IPv6 packet with a fragment header */ 98 | void send_fragmented_ipv6(const int, uint8_t *, uint16_t, uint16_t); 99 | 100 | /* Return true if a group is an IPv4 ASM group */ 101 | bool is_asm_group(const in6_addr &) const; 102 | 103 | /* Return true if a group is an IPv4 SSM group */ 104 | bool is_ssm_group(const in6_addr &) const; 105 | 106 | /* Return true if a group is an IPv4 ASM group */ 107 | bool is_asm_group(const in_addr) const; 108 | 109 | /* Return true if a group is an IPv4 SSM group */ 110 | bool is_ssm_group(const in_addr) const; 111 | 112 | /* Return true if a group is an IPv4 link-local multicast group */ 113 | bool is_ll_group(const in_addr) const; 114 | 115 | /* Return true if an IPv4 source address is valid for multicast. */ 116 | bool is_valid_source(const in6_addr &) const; 117 | 118 | /* Return true if an IPv4 source address is valid for multicast. */ 119 | bool is_valid_source(const in_addr) const; 120 | 121 | /* Return the embedded IPv4 address (last 32 bits) from an IPv6 address. */ 122 | in_addr get_embedded_address(const in6_addr &) const; 123 | 124 | /* Set the embedded IPv4 address (last 32 bits) of an IPv6 address. */ 125 | void set_embedded_address(in6_addr &, const in_addr) const; 126 | 127 | /* Get MTU for a destination. */ 128 | uint16_t get_mtu(const in_addr) const; 129 | 130 | /* Erase previously set MTU. */ 131 | void erase_mtu(const in6_addr &); 132 | 133 | /* Calculate IPv4 checksum (RFC 1071) */ 134 | uint16_t ipv4_checksum(const uint8_t *, uint16_t) const; 135 | 136 | property_def *m_p_ipv4_interface; 137 | property_def *m_p_ipv4_address; 138 | property_def *m_p_unicast_prefix; 139 | property_def *m_p_asm_prefix; 140 | property_def *m_p_ssm_prefix; 141 | int m_igmp_fd; 142 | bool m_enabled; 143 | uint32_t m_fragment_id; 144 | interface *m_interface; 145 | interface *m_virtual_interface; 146 | socket0 m_rawsock; 147 | ip6_hdr m_asm_hdr; 148 | ip6_hdr m_ssm_hdr; 149 | us_mfa *m_mfa; 150 | 151 | typedef std::map group_mtu_map; 152 | group_mtu_map m_group_mtu; 153 | }; 154 | 155 | #endif 156 | -------------------------------------------------------------------------------- /include/mrdpriv/linux/unicast_route.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Multicast Routing Daemon (MRD) 3 | * unicast_route.h 4 | * 5 | * Copyright (C) 2006, 2007 - Hugo Santos 6 | * Copyright (C) 2004..2006 - Universidade de Aveiro, IT Aveiro 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * Author: Hugo Santos 23 | */ 24 | 25 | #ifndef _mrd_linux_unicast_route_h_ 26 | #define _mrd_linux_unicast_route_h_ 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | #ifdef __STRICT_ANSI__ 33 | #undef __STRICT_ANSI__ 34 | #include 35 | #include 36 | #include 37 | #define __STRICT_ANSI__ 38 | #else 39 | #include 40 | #include 41 | #include 42 | #endif 43 | 44 | #include 45 | #include 46 | #include 47 | 48 | struct netlink_msg; 49 | 50 | /*! 51 | * \brief Implements the `unicast_router' interface in Linux. 52 | */ 53 | class linux_unicast_router : public rib_def { 54 | public: 55 | linux_unicast_router(); 56 | ~linux_unicast_router(); 57 | 58 | bool check_startup(); 59 | void shutdown(); 60 | 61 | void check_initial_interfaces(); 62 | 63 | bool set_property(const char *, const char *); 64 | 65 | void do_dump(int); 66 | 67 | private: 68 | bool send_nlmsg(const netlink_msg *, netlink_msg *) const; 69 | bool lookup_prefix(const in6_addr &, lookup_result &) const; 70 | 71 | void notify_changes(); 72 | void data_available(uint32_t); 73 | int process_message(); 74 | 75 | void dump_request(int); 76 | 77 | void handle_route_event(bool isnew, nlmsghdr *); 78 | void handle_intf_event(bool isnew, nlmsghdr *); 79 | void handle_addr_event(bool isnew, nlmsghdr *); 80 | 81 | void parse_prefix_rec(rtattr *tb[], int, int, lookup_result &) const; 82 | 83 | bool call_method(int, base_stream &, const std::vector &); 84 | bool filter_routes(base_stream &, const std::vector &); 85 | bool show_filter_routes(base_stream &, const std::vector &); 86 | 87 | std::map parse_rt_protos() const; 88 | 89 | uint8_t *buffer; 90 | property_def *bufferlen; 91 | 92 | int rt_sock; 93 | socket0 rt_bcast_sock; 94 | bool rt_dumping; 95 | 96 | uint32_t rt_nlseq; 97 | 98 | std::set filter_protos; 99 | }; 100 | 101 | #endif 102 | 103 | -------------------------------------------------------------------------------- /include/mrdpriv/mld/def.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Multicast Routing Daemon (MRD) 3 | * mld/def.h 4 | * 5 | * Copyright (C) 2006, 2007 - Hugo Santos 6 | * Copyright (C) 2004..2006 - Universidade de Aveiro, IT Aveiro 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * Author: Hugo Santos 23 | */ 24 | 25 | #ifndef _mrd_mdl_def_h_ 26 | #define _mrd_mdl_def_h_ 27 | 28 | #include 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | class node; 36 | class mld_intfconf_node; 37 | 38 | #ifndef MLD_LISTENER_QUERY 39 | #define MLD_LISTENER_QUERY 130 40 | #endif 41 | 42 | #ifndef MLD_LISTENER_REPORT 43 | #define MLD_LISTENER_REPORT 131 44 | #endif 45 | 46 | #ifndef MLD_LISTENER_REDUCTION 47 | #define MLD_LISTENER_REDUCTION 132 48 | #endif 49 | 50 | #ifndef MLDv2_LISTENER_REPORT 51 | #define MLDv2_LISTENER_REPORT 143 52 | #endif 53 | 54 | #ifndef MLDv2_LISTENER_REPORT_OLD 55 | #define MLDv2_LISTENER_REPORT_OLD 206 56 | #endif 57 | 58 | extern in6_addr in6addr_linkscope_allnodes; 59 | 60 | #define MLD_SSM_MODE_INCLUDE 1 61 | #define MLD_SSM_MODE_EXCLUDE 2 62 | #define MLD_SSM_CHANGE_TO_INCLUDE 3 63 | #define MLD_SSM_CHANGE_TO_EXCLUDE 4 64 | #define MLD_SSM_ALLOW_SOURCES 5 65 | #define MLD_SSM_BLOCK_SOURCES 6 66 | 67 | class interface; 68 | 69 | /*! 70 | * \brief MLD base header. 71 | */ 72 | struct mld_base { 73 | uint8_t type; 74 | uint8_t code; 75 | uint16_t checksum; 76 | 77 | uint16n_t maxdelay; 78 | uint16n_t data; 79 | } __attribute__ ((packed)); 80 | 81 | struct mldv1 : mld_base { 82 | in6_addr mcaddr; 83 | 84 | int length() const { return sizeof(mldv1); } 85 | 86 | void construct(const in6_addr &, int type, mld_intfconf_node *); 87 | } __attribute__ ((packed)); 88 | 89 | struct mldv1_query : mldv1 { 90 | void construct(const in6_addr &, mld_intfconf_node *); 91 | } __attribute__ ((packed)); 92 | 93 | /*! 94 | * \brief MLDv2 Query header. derives from MLD header. 95 | */ 96 | struct mldv2_query : mldv1 { 97 | #if BYTE_ORDER == LITTLE_ENDIAN 98 | uint8_t qrv : 3, suppress : 1, resv2 : 4; 99 | #elif BYTE_ORDER == BIG_ENDIAN 100 | uint8_t resv2 : 4, suppress : 1, qrv : 3; 101 | #else 102 | # error "your system endianness isn't supported yet" 103 | #endif 104 | uint8_t qqic; 105 | uint16n_t nsrcs; 106 | in6_addr srcs[0]; 107 | 108 | int length() const { return sizeof(mldv1) + 4 + ntoh(nsrcs) * sizeof(in6_addr); } 109 | 110 | void construct(const in6_addr &, int type, mld_intfconf_node *); 111 | void construct_query(const in6_addr &mca, mld_intfconf_node *conf) { 112 | construct(mca, MLD_LISTENER_QUERY, conf); 113 | } 114 | 115 | } __attribute__ ((packed)); 116 | 117 | /*! 118 | * \brief A MLDv2 Multicast record. Contained in MLDv2 Report messages. 119 | */ 120 | struct mldv2_mrec { 121 | uint8_t type; 122 | uint8_t auxdatalen; 123 | uint16n_t nsrcs; 124 | in6_addr mca; 125 | 126 | in6_addr *sources() { 127 | return (in6_addr *)(((uint8_t *)this) + sizeof(*this)); 128 | } 129 | 130 | mldv2_mrec *next() { 131 | return (mldv2_mrec *) 132 | (((uint8_t *)this) + sizeof(*this) + 133 | ntoh(nsrcs) * sizeof(in6_addr) + auxdatalen); 134 | } 135 | } __attribute__ ((packed)); 136 | 137 | /*! 138 | * \brief A MLDv2 Report header. Derives from MLD base header. 139 | */ 140 | struct mldv2_report : mld_base { 141 | const uint16n_t &nmrecs() const { return data; } 142 | 143 | mldv2_mrec *mrecs() { 144 | return (mldv2_mrec *)(((uint8_t *)this) + sizeof(*this)); 145 | } 146 | } __attribute__ ((packed)); 147 | 148 | #endif 149 | 150 | -------------------------------------------------------------------------------- /include/mrdpriv/pim/interface.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Multicast Routing Daemon (MRD) 3 | * pim/interface.h 4 | * 5 | * Copyright (C) 2006, 2007 - Hugo Santos 6 | * Copyright (C) 2004..2006 - Universidade de Aveiro, IT Aveiro 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * Author: Hugo Santos 23 | */ 24 | 25 | #ifndef _mrd_pim_interface_h_ 26 | #define _mrd_pim_interface_h_ 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #include 35 | 36 | #include 37 | 38 | #include 39 | 40 | class interface; 41 | class group; 42 | 43 | class pim_group_node; 44 | class pim_neighbour; 45 | 46 | class pim_intfconf_node; 47 | 48 | class pim_interface : public interface_node { 49 | public: 50 | pim_interface(); 51 | ~pim_interface(); 52 | 53 | const char *description() const { return "PIM interface information"; } 54 | 55 | bool check_startup(); 56 | bool start_timers(); 57 | void shutdown(); 58 | 59 | void attached(interface *); 60 | 61 | bool am_dr() const { return !elected_dr; } 62 | 63 | uint32_t effective_propagation_delay() const; 64 | uint32_t effective_override_interval() const; 65 | bool lan_delay_enabled() const; 66 | 67 | bool send_local(sockaddr_in6 *dst, pim_message *msg, uint16_t len) const; 68 | bool send_all_routers(pim_message *msg, uint16_t len) const; 69 | 70 | bool send_join_prune(pim_joinprune_message *) const; 71 | bool send_assert(pim_assert_message *) const; 72 | 73 | void data_available(const sockaddr_in6 *src, const sockaddr_in6 *dst); 74 | 75 | bool call_method(int id, base_stream &, 76 | const std::vector &); 77 | 78 | pim_neighbour *get_neighbour(const in6_addr &) const; 79 | pim_neighbour *allocate_neighbour(const in6_addr &); 80 | 81 | enum state { 82 | NOT_READY = 0, 83 | LOCAL_READY, 84 | READY 85 | }; 86 | 87 | state get_state() const { return intf_state; } 88 | 89 | const std::list &get_neighbours() const { return neighbours; } 90 | 91 | bool output_info(base_stream &, const std::vector &) const; 92 | bool output_info(base_stream &, bool extended) const; 93 | 94 | pim_intfconf_node *conf() const; 95 | 96 | bool suppression_enabled() const; 97 | uint32_t suppressed_value() const; 98 | 99 | private: 100 | void found_new_neighbour(pim_neighbour *); 101 | 102 | void event(int, void *); 103 | 104 | void handle_hello(const sockaddr_in6 *, 105 | pim_hello_message *, uint16_t len); 106 | void handle_joinprune(const sockaddr_in6 *, 107 | pim_joinprune_message *, uint16_t len); 108 | void handle_external_joinprune(const sockaddr_in6 *, 109 | pim_joinprune_message *, uint16_t len); 110 | 111 | void handle_join_wc_rpt(const inet6_addr &, const inet6_addr &, 112 | const address_set &, uint16_t, bool); 113 | void handle_join_wc_rpt(group *, const inet6_addr &, 114 | const address_set &, uint32_t, bool); 115 | 116 | void handle_join_source(const inet6_addr &, const inet6_addr &, 117 | uint32_t, bool); 118 | void handle_join_source(group *, const inet6_addr &, uint32_t, bool); 119 | 120 | void handle_join(const inet6_addr &, const inet6_addr &, uint32_t, bool); 121 | void handle_join(pim_group_node *, const inet6_addr &, uint32_t, bool); 122 | 123 | void handle_assert(const sockaddr_in6 *, 124 | pim_assert_message *msg, uint16_t len); 125 | void handle_bootstrap(const sockaddr_in6 *, const sockaddr_in6 *, 126 | pim_bootstrap_message *, uint16_t len); 127 | 128 | void handle_register(const sockaddr_in6 *, const sockaddr_in6 *); 129 | void handle_register_stop(const sockaddr_in6 *); 130 | void handle_candidate_rp_adv(const sockaddr_in6 *, 131 | pim_candidate_rp_adv_message *, uint16_t len); 132 | 133 | void send_hello(); 134 | void send_hellox(uint16_t); 135 | 136 | bool flap_neighbour(base_stream &, const std::vector &, 137 | bool remove); 138 | 139 | void property_changed(node *n, const char *); 140 | 141 | /* Triggered whenever a Neighbour timer expires. */ 142 | void neighbour_timed_out(pim_neighbour * &); 143 | /* Removes a Neighbour from this interface, notifying of the 144 | * Neighbour loss. If elect is true, after removal the DR 145 | * election mechanism is triggered. */ 146 | void remove_neighbour(pim_neighbour *, bool elect); 147 | 148 | /* Implements the Lan-Prune-Delay mechanism. */ 149 | void check_lan_delay(); 150 | /* Implements the DR election mechanism. */ 151 | void elect_subnet_dr(); 152 | 153 | void update_hello_interval(uint32_t); 154 | 155 | typedef std::list neighbours_def; 156 | 157 | message_stats_node m_stats; 158 | 159 | uint32_t gen_id; 160 | timer hello_timer_id; 161 | 162 | pim_neighbour *elected_dr; 163 | uint32_t m_propagation_delay, m_override_interval; 164 | bool m_landelay_enabled; 165 | 166 | neighbours_def neighbours; 167 | 168 | state intf_state; 169 | 170 | void address_added_or_removed(bool, const inet6_addr &); 171 | 172 | friend class pim_neighbour; 173 | }; 174 | 175 | inline pim_intfconf_node *pim_interface::conf() const { 176 | return owner() ? (pim_intfconf_node *)owner()->conf()->get_child("pim") : 0; 177 | } 178 | 179 | #endif 180 | 181 | -------------------------------------------------------------------------------- /ipkg/README: -------------------------------------------------------------------------------- 1 | ---------------- 2 | MRD6 for OpenWrt 3 | ---------------- 4 | 5 | This will generate a 1151K large mrd6 binary for mips. 6 | 7 | More information on OpenWrt on http://www.openwrt.org/ 8 | 9 | 10 | How to build mrd6 for OpenWRT 11 | ----------------------------- 12 | 13 | # Get OpenWrt-SDK (http://openwrt.org/BuildingPackages) 14 | wget http://downloads.openwrt.org/nbd/gcc34/OpenWrt-SDK-Linux-i686-1.tar.bz2 15 | tar xjvf OpenWrt-SDK-Linux-i686-1.tar.bz2 16 | 17 | cd OpenWrt-SDK-Linux-i686-1/package/ 18 | 19 | # untar mrd6 source code here 20 | 21 | # The directory tree will loks like: 22 | # .../OpenWrt-SDK-Linux-i686-1/package/mrd6/src/... 23 | 24 | # Modify OPENWRTBR in mrd6/ipkg/rules according to your OpenWrt-SDK directory path 25 | 26 | # From mrd6 directory start: 27 | fakeroot ipkg-buildpackage -c 28 | 29 | the ipk package will be generated in ../ 30 | 31 | Thanks to 32 | --------- 33 | 34 | Hugo Santos for all porting, sizing down work and of course for writing mrd6. 35 | 36 | Bernhard Schmidt for some network conectivity. 37 | 38 | -- 39 | Sebastien Chaumontet (snip) 40 | July 2005 41 | -------------------------------------------------------------------------------- /ipkg/S50mrd6: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | DNAME=mrd6 4 | 5 | case $1 in 6 | start) 7 | /sbin/lsmod | grep ipv6 > /dev/null 8 | if [ "$?" != "0" ] 9 | then 10 | echo -n "IPv6 stack required by mrd6. Loading ipv6 module: " 11 | /sbin/insmod ipv6 12 | echo "Done." 13 | fi 14 | echo -n "Starting IPv6 multicast router (mrd6): " 15 | /usr/sbin/$DNAME -f /etc/mrd6.conf -D 16 | echo "Done." 17 | ;; 18 | stop) 19 | echo -n "Stopping IPv6 multicast router (mrd6): " 20 | killall $DNAME 21 | echo "Done." 22 | ;; 23 | restart) 24 | $0 stop 25 | $0 start 26 | ;; 27 | *) 28 | echo "Usage: $0 {start | stop | restart}" 29 | ;; 30 | esac 31 | exit 0 32 | -------------------------------------------------------------------------------- /ipkg/control: -------------------------------------------------------------------------------- 1 | Package: mrd6 2 | Version: 0.9.5-pre2-1 3 | Architecture: mipsel 4 | Maintainer: Sebastien Chaumontet 5 | Source: http://fivebits.net/mrd6/ 6 | Section: net 7 | Priority: optional 8 | Depends: kmod-ipv6 9 | Description: IPv6 multicast routing daemon 10 | -------------------------------------------------------------------------------- /ipkg/mrd6.base.conf: -------------------------------------------------------------------------------- 1 | log { 2 | attach stderr normal; 3 | attach default "/var/log/mrd6.log" message_err; 4 | } 5 | 6 | interfaces disable br0; // Should be vlan0 + eth1 but Linux bridge seems broken for multicast 7 | interfaces disable eth0; // Interface to internal bridge 8 | handle-proper-bridge = true; // use ETH_P_ALL to see all packets on wrt54g 9 | 10 | -------------------------------------------------------------------------------- /ipkg/mrd6.m6bone.conf: -------------------------------------------------------------------------------- 1 | log { 2 | attach stderr normal; 3 | attach default "/var/log/mrd6.log" message_err; 4 | } 5 | 6 | interfaces disable br0; // Should be vlan0 + eth1 but Linux bridge seems broken for multicast 7 | interfaces disable eth0; // Interface to internal bridge 8 | handle-proper-bridge = true; // use ETH_P_ALL to see all packets on wrt54g 9 | 10 | // The default configured RP is m6bone's Renater RP. 11 | // Change this according to your setup 12 | 13 | groups ff00::/8 pim rp = 2001:660:3007:300:1::; 14 | 15 | -------------------------------------------------------------------------------- /ipkg/postinst: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | /etc/init.d/S50mrd6 start 3 | -------------------------------------------------------------------------------- /ipkg/preinst: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | if [ -x /etc/init.d/S50mrd6 ] 3 | then 4 | /etc/init.d/S50mrd6 stop 5 | fi 6 | -------------------------------------------------------------------------------- /ipkg/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | 3 | # Path to OpenWrt-SDK 4 | OPENWRTBR ?= /opt/openwrt-sdk 5 | ARCH = mipsel 6 | 7 | TARGET = mrd6 8 | DESTDIR = /tmp/mrd6 9 | 10 | # use -static for ipkg 11 | FULL_STATIC = yes 12 | 13 | # compiled modules 14 | MODULES = mld pim console 15 | # used options 16 | OPTIONS = NO_INET6_OPTION 17 | MODULE_OPTIONS = 18 | 19 | -include ipkg/rules.local 20 | 21 | # ---------- Cross compilation env 22 | OPTIMIZE_FOR_CPU=$(ARCH) 23 | STAGING_DIR=$(OPENWRTBR)/staging_dir_$(ARCH)$(ARCH_FPU_SUFFIX) 24 | # TARGET_CROSS=$(STAGING_DIR)/bin/$(OPTIMIZE_FOR_CPU)-linux- 25 | TARGET_CROSS=$(STAGING_DIR)/bin/$(OPTIMIZE_FOR_CPU)-linux-uclibc- 26 | CC = $(TARGET_CROSS)gcc 27 | CXX = $(TARGET_CROSS)g++ 28 | STRIP = $(TARGET_CROSS)strip 29 | 30 | export TARGET DESTDIR FULL_STATIC CC CXX STRIP 31 | 32 | CONF_MODULES = $(addprefix --static ,$(MODULES)) 33 | CONF_OPTIONS = $(addprefix --option ,$(OPTIONS)) 34 | CONF_MODULE_OPTIONS = $(addprefix --module-option ,$(MODULE_OPTIONS)) 35 | 36 | all: build 37 | 38 | configure: configure-stamp 39 | 40 | configure-stamp: 41 | config/base.pl \ 42 | --prefix /usr \ 43 | --optimizations space \ 44 | --support-modules no \ 45 | $(CONF_OPTIONS) $(CONF_MODULE_OPTIONS) $(CONF_MODULES) 46 | touch configure-stamp 47 | 48 | build: configure 49 | $(MAKE) -C src 50 | $(MAKE) -C tools/c 51 | 52 | clean: 53 | rm configure-stamp 54 | $(MAKE) -C src clean 55 | 56 | install: build 57 | $(MAKE) -C src install 58 | $(MAKE) -C tools/c install 59 | 60 | for f in `find $(DESTDIR) -type f`; do (if file $$f | grep "not stripped" > /dev/null; then ( $(STRIP) --strip-unneeded $$f); fi); done 61 | 62 | mkdir -p $(DESTDIR)/etc/init.d/ 63 | cp -p ipkg/S50mrd6 $(DESTDIR)/etc/init.d/ 64 | -------------------------------------------------------------------------------- /rpm/mrd6.spec: -------------------------------------------------------------------------------- 1 | Summary: Multicast Routing Daemon for IPv6 2 | Name: mrd6 3 | Version: 0.9.5 4 | Release: 1 5 | URL: http://fivebits.net/mrd6/ 6 | License: GPL 7 | Source0: http://fivebits.net/mrd6/download/mrd6-0.9.5.tar.gz 8 | Group: Networking 9 | Packager: Hugo Santos 10 | BuildRoot: %{_builddir}/%{name}-%{version}-root 11 | 12 | %description 13 | MRD6 is a modular IPv6 Multicast Routing Daemon which implements: 14 | * MLDv1 and MLDv2 with forwarding capabilities 15 | - MLD proxying 16 | * PIM-SM (ASM and SSM) 17 | - Bootstrap (BSR) Mechanism support 18 | - Static RP configuration 19 | - Embedded-RP support 20 | * partial MBGP support 21 | - Uses IPv6 Multicast SAFI prefixes announced by 22 | peers to update local MRIB 23 | - Is able to announce local prefixes 24 | - Filter support 25 | * Native and virtual (tunnel) interfaces support 26 | * CLI support (remote configuration and management) via 27 | telnet or local access 28 | 29 | %prep 30 | %setup -q -n mrd6-0.9.5 31 | 32 | %build 33 | make 34 | 35 | %install 36 | [ %{buildroot} != "/" ] && rm -rf %{buildroot} 37 | PREFIX=%{_prefix} DESTDIR=%{buildroot} make install 38 | 39 | %clean 40 | [ %{buildroot} != "/" ] && rm -rf %{buildroot} 41 | 42 | %files 43 | %defattr(-, root, root) 44 | %doc README README.translator MRD6shQuickRef.txt src/confs/mrd.conf 45 | %{_prefix}/sbin/mrd6 46 | %{_prefix}/lib/mrd6/* 47 | %{_prefix}/bin/mrd6sh 48 | 49 | %changelog 50 | * Sun Jan 8 2006 Hugo Santos 0.9.5 51 | - 0.9.5 52 | -------------------------------------------------------------------------------- /src/address.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Multicast Routing Daemon (MRD) 3 | * address.cpp 4 | * 5 | * Copyright (C) 2009, 2011 - Teemu Kiviniemi 6 | * Copyright (C) 2009 - CSC - IT Center for Science Ltd. 7 | * Copyright (C) 2006, 2007 - Hugo Santos 8 | * Copyright (C) 2004..2006 - Universidade de Aveiro, IT Aveiro 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 | * 24 | * Author: Hugo Santos 25 | */ 26 | 27 | #include 28 | #include 29 | 30 | #include 31 | #include 32 | 33 | #include 34 | #include 35 | 36 | base_stream &operator << (base_stream &os, const inet6_addr &addr) { 37 | return os.xprintf("%{Addr}", addr); 38 | } 39 | 40 | base_stream &operator << (base_stream &os, const in6_addr &addr) { 41 | return os.xprintf("%{addr}", addr); 42 | } 43 | 44 | void stream_push_formated_type(base_stream &os, const in6_addr &addr) { 45 | char *p = os.req_buffer(64); 46 | inet_ntop(AF_INET6, &addr, p, 64); 47 | os.commit_change(strlen(p)); 48 | } 49 | 50 | void stream_push_formated_type(base_stream &os, const inet6_addr &addr) { 51 | char *p = addr.print_string(os.req_buffer(64), 64); 52 | os.commit_change(strlen(p)); 53 | } 54 | 55 | inet6_addr::inet6_addr() 56 | : addr(in6addr_any), prefixlen(0) { 57 | } 58 | 59 | inet6_addr::inet6_addr(const in6_addr &addr) 60 | : addr(addr), prefixlen(128) { 61 | } 62 | 63 | inet6_addr::inet6_addr(const in6_addr &address, uint8_t plen) 64 | : addr(address), prefixlen(plen) { 65 | } 66 | 67 | inet6_addr::inet6_addr(const inet6_addr &addr) 68 | : addr(addr.addr), prefixlen(addr.prefixlen) { 69 | } 70 | 71 | inet6_addr::inet6_addr(const std::string &addr) { 72 | set(addr); 73 | } 74 | 75 | inet6_addr::inet6_addr(const std::vector &_addr) { 76 | if (_addr.size() == 16) { 77 | in6_addr addr; 78 | for (int i = 0; i < 16; i++) 79 | addr.s6_addr[i] = _addr[i]; 80 | set(addr, 128); 81 | } else { 82 | set(in6addr_any, 0); 83 | } 84 | } 85 | 86 | unsigned inet6_addr::type() const { 87 | unsigned val = 0; 88 | 89 | if (IN6_IS_ADDR_MULTICAST(&addr)) 90 | val |= multicast; 91 | 92 | if (prefixlen < 128) { 93 | int octet = prefixlen / 8; 94 | const int bit = prefixlen % 8; 95 | if (bit != 0) { 96 | if ((addr.s6_addr[octet] & (0xff >> bit)) != 0) 97 | return val; 98 | octet++; 99 | } 100 | for (int i = 15; i >= octet; i--) { 101 | if (addr.s6_addr[i] != 0) 102 | return val; 103 | } 104 | 105 | /* All bits outside the prefix are zero. */ 106 | val |= network; 107 | } 108 | 109 | return val; 110 | } 111 | 112 | bool inet6_addr::operator < (const inet6_addr &address) const { 113 | if (prefixlen < address.prefixlen) 114 | return true; 115 | else if (prefixlen > address.prefixlen) 116 | return false; 117 | return memcmp(addr.s6_addr, address.addr.s6_addr, sizeof(in6_addr)) < 0; 118 | } 119 | 120 | bool inet6_addr::operator > (const inet6_addr &address) const { 121 | if (prefixlen > address.prefixlen) 122 | return true; 123 | else if (prefixlen < address.prefixlen) 124 | return false; 125 | return memcmp(addr.s6_addr, address.addr.s6_addr, sizeof(in6_addr)) > 0; 126 | } 127 | 128 | bool inet6_addr::operator == (const inet6_addr &address) const { 129 | if (prefixlen != address.prefixlen) 130 | return false; 131 | return IN6_ARE_ADDR_EQUAL(&addr, &address.addr); 132 | } 133 | 134 | std::string inet6_addr::as_string() const { 135 | char buf[64]; 136 | 137 | return std::string(print_string(buf, sizeof(buf))); 138 | } 139 | 140 | char *inet6_addr::print_string(char *buf, int len) const { 141 | if (!inet_ntop(AF_INET6, &addr, buf, len)) { 142 | return 0; 143 | } else { 144 | int l = strlen(buf); 145 | if (prefixlen < 128) { 146 | len -= l; 147 | if (len > 4) { 148 | buf[l] = '/'; 149 | sprintf(buf + l + 1, "%i", prefixlen); 150 | } 151 | } 152 | 153 | return buf; 154 | } 155 | } 156 | 157 | sockaddr_in6 inet6_addr::as_sockaddr() const { 158 | sockaddr_in6 saddr; 159 | 160 | memset(&saddr, 0, sizeof(saddr)); 161 | 162 | saddr.sin6_family = AF_INET6; 163 | saddr.sin6_addr = addr; 164 | 165 | return saddr; 166 | } 167 | 168 | void inet6_addr::set(const in6_addr &address, uint8_t plen) { 169 | addr = address; 170 | prefixlen = plen; 171 | } 172 | 173 | bool inet6_addr::set(const std::string &str) { 174 | if (str == "any") { 175 | addr = in6addr_any; 176 | prefixlen = 0; 177 | return true; 178 | } 179 | 180 | size_t k = str.find('/'); 181 | if (k < str.size()) { 182 | std::string tmp = str; 183 | std::string prefix = str.c_str() + k + 1; 184 | tmp.resize(k); 185 | 186 | if (!inet_pton(AF_INET6, tmp.c_str(), &addr)) 187 | return false; 188 | 189 | char *end; 190 | int pl = strtol(prefix.c_str(), &end, 10); 191 | if (*end || pl < 0 || pl > 128) 192 | return false; 193 | prefixlen = pl; 194 | } else { 195 | if (!inet_pton(AF_INET6, str.c_str(), &addr)) 196 | return false; 197 | prefixlen = 128; 198 | } 199 | return true; 200 | } 201 | 202 | bool inet6_addr::from_string(const std::string &value, inet6_addr &res) { 203 | return res.set(value); 204 | } 205 | 206 | void inet6_addr::to_string(const inet6_addr &value, std::string &res) { 207 | res = value.as_string(); 208 | } 209 | 210 | inet6_addr inet6_addr::prefix() const { 211 | inet6_addr copy = *this; 212 | copy.apply_prefixlen(); 213 | return copy; 214 | } 215 | 216 | void inet6_addr::apply_prefixlen() { 217 | uint8_t *ptr = addr.s6_addr; 218 | 219 | int start = prefixlen / 8; 220 | int mask = (0xff << (8 - (prefixlen % 8))) & 0xff; 221 | 222 | if (start < 15) 223 | memset(ptr + start + 1, 0, (16 - start - 1)); 224 | 225 | ptr[start] &= mask; 226 | } 227 | 228 | -------------------------------------------------------------------------------- /src/address_set.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Multicast Routing Daemon (MRD) 3 | * address_set.cpp 4 | * 5 | * Copyright (C) 2006, 2007 - Hugo Santos 6 | * Copyright (C) 2004..2006 - Universidade de Aveiro, IT Aveiro 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * Author: Hugo Santos 23 | */ 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | address_set &address_set::union_with(const address_set &b, address_set &diff) { 30 | for (const_iterator i = b.begin(); i != b.end(); ++i) { 31 | if (insert(*i).second) 32 | diff.insert(*i); 33 | } 34 | return *this; 35 | } 36 | 37 | address_set &address_set::union_with(const address_set &b) { 38 | for (const_iterator i = b.begin(); i != b.end(); ++i) { 39 | insert(*i); 40 | } 41 | return *this; 42 | } 43 | 44 | address_set &address_set::diff_with(const address_set &b, address_set &diff) { 45 | if (!empty() && !b.empty()) { 46 | for (iterator i = b.begin(); i != b.end(); ++i) { 47 | iterator j = find(*i); 48 | if (j != end()) { 49 | diff.insert(*j); 50 | erase(j); 51 | } 52 | } 53 | } 54 | return *this; 55 | } 56 | 57 | address_set &address_set::diff_with(const address_set &b) { 58 | if (!empty() && !b.empty()) { 59 | for (iterator i = b.begin(); i != b.end(); ++i) { 60 | iterator j = find(*i); 61 | if (j != end()) { 62 | erase(j); 63 | } 64 | } 65 | } 66 | return *this; 67 | } 68 | 69 | address_set &address_set::intersect_with(const address_set &b) { 70 | if (b.empty()) { 71 | clear(); 72 | } else { 73 | for (iterator i = begin(); i != end(); ++i) { 74 | if (!b.has_addr(*i)) { 75 | erase(i); 76 | } 77 | } 78 | for (const_iterator j = b.begin(); j != b.end(); ++j) { 79 | insert(*j); 80 | } 81 | } 82 | return *this; 83 | } 84 | 85 | address_set &address_set::intersect_with(const address_set &b, address_set &diff) { 86 | if (b.empty()) { 87 | diff = *this; 88 | clear(); 89 | } else { 90 | for (iterator i = begin(); i != end(); ++i) { 91 | if (!b.has_addr(*i)) { 92 | diff.insert(*i); 93 | erase(i); 94 | } 95 | } 96 | for (const_iterator j = b.begin(); j != b.end(); ++j) { 97 | insert(*j); 98 | } 99 | } 100 | return *this; 101 | } 102 | 103 | address_set &address_set::assign_with(const address_set &b, address_set &added, address_set &removed) { 104 | if (b.empty()) { 105 | removed = *this; 106 | clear(); 107 | } else { 108 | for (const_iterator i = b.begin(); i != b.end(); ++i) { 109 | if (!has_addr(*i)) 110 | added.insert(*i); 111 | } 112 | for (const_iterator i = begin(); i != end(); ++i) { 113 | if (!b.has_addr(*i)) 114 | removed.insert(*i); 115 | } 116 | *this = b; 117 | } 118 | 119 | return *this; 120 | } 121 | 122 | bool address_set::remove(const in6_addr &addr) { 123 | iterator i = find(addr); 124 | if (i == end()) 125 | return false; 126 | erase(i); 127 | return true; 128 | } 129 | 130 | base_stream &address_set::print_to(base_stream &os) const { 131 | if (empty()) { 132 | os.write("{}"); 133 | } else { 134 | os.write("{"); 135 | 136 | for (address_set::const_iterator i = begin(); i != end(); ++i) { 137 | if (i != begin()) 138 | os.write(", "); 139 | stream_push_formated_type(os, *i); 140 | } 141 | 142 | os.write("}"); 143 | } 144 | 145 | return os; 146 | } 147 | 148 | base_stream &operator << (base_stream &os, const address_set &addrs) { 149 | return addrs.print_to(os); 150 | } 151 | 152 | -------------------------------------------------------------------------------- /src/bsd/mrd_components.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Multicast Routing Daemon (MRD) 3 | * mrd_components.cpp 4 | * 5 | * Copyright (C) 2006, 2007 - Hugo Santos 6 | * Copyright (C) 2004..2006 - Universidade de Aveiro, IT Aveiro 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * Author: Hugo Santos 23 | */ 24 | 25 | #include 26 | 27 | #include 28 | #include 29 | 30 | bool mrd::prepare_os_components() { 31 | m_mfa = new ks_mfa(); 32 | 33 | return true; 34 | } 35 | 36 | void mrd::prepare_second_components() { 37 | if (!m_rib_handler) 38 | m_rib_handler = new bsd_rib(); 39 | } 40 | 41 | const char *mrd::loopback_interface_name() const { 42 | return "lo0"; 43 | } 44 | 45 | void mrd::output_backtrace(base_stream &out) const { 46 | out.writeline("Backtraces aren't available in this system."); 47 | } 48 | 49 | char *mrd::obtain_frame_description(void *ptr) const { 50 | return 0; 51 | } 52 | 53 | void *mrd::posix_uctx::get_current_frame() const { 54 | return 0; 55 | } 56 | 57 | -------------------------------------------------------------------------------- /src/confs/mrd.conf: -------------------------------------------------------------------------------- 1 | /* MRD example configuration file */ 2 | 3 | log { 4 | /* Logs are controlled via the 'attach' method */ 5 | /* syntax (one of): 6 | 7 | attach syslog [level] 8 | attach stderr [level] 9 | attach name filename [level] 10 | 11 | where level is one of: 12 | quiet, normal, verbose, debug or extradebug 13 | */ 14 | attach stderr normal; 15 | attach default "mrd.log" debug; 16 | } 17 | 18 | load-module console; 19 | load-module mld; 20 | load-module pim; 21 | 22 | console { 23 | /* Allow access from any host with admin/admin */ 24 | /* allow-access admin admin any; */ 25 | 26 | /* Command format: */ 27 | /* allow-access [username [password [address mask]]]; */ 28 | } 29 | 30 | /* Global pim variable configuration */ 31 | pim { 32 | /* we want to be a BSR candidate */ 33 | enable bsr-candidate; 34 | /* we want to be a RP candidate */ 35 | enable rp-candidate; 36 | } 37 | 38 | /* Groups configuration */ 39 | groups { 40 | /* group mask */ 41 | ff0e::/16 { 42 | pim { 43 | /* include this group mask in our RP adv */ 44 | enable rp_adv; 45 | } 46 | } 47 | } 48 | 49 | -------------------------------------------------------------------------------- /src/confs/mrd.m6bone-bgp.conf: -------------------------------------------------------------------------------- 1 | /* MRD example configuration file */ 2 | 3 | log { 4 | /* Logs are controlled via the 'attach' method */ 5 | /* syntax (one of): 6 | 7 | attach syslog [level] 8 | attach stderr [level] 9 | attach name filename [level] 10 | 11 | where level is one of: 12 | quiet, normal, verbose, debug or extradebug 13 | 14 | loglevels may be checked via console, e.g.: 15 | ../tools/mrd6sh show log \* 16 | */ 17 | attach stderr normal; 18 | attach default "mrd.log" debug; 19 | } 20 | 21 | /* Enable the console, MLD, PIM and BGP modules */ 22 | load-module console; 23 | load-module mld; 24 | load-module pim; 25 | load-module bgp; 26 | 27 | console { 28 | /* Allow access from any host with admin/admin */ 29 | /* allow-access admin admin any; */ 30 | 31 | /* Command format: */ 32 | /* allow-access [username [password [address mask]]]; */ 33 | } 34 | 35 | bgp { 36 | /* local AS number */ 37 | router-as 65000; 38 | 39 | /* neighbours are added using the following format 40 | neighbor { 41 | address { 42 | peer-as neigh_AS; 43 | 44 | [filter [num] (in|out) ;] 45 | } 46 | } 47 | 48 | where a filter is defined in the following way 49 | 50 | access-list in1 { 51 | /* accept any prefix that matches 2000::/3 with 52 | * prefixlen >= 24 and <= 64. */ 53 | prefix permit 2000::/3 ge 24 le 64; 54 | 55 | /* command format */ 56 | /* prefix (permit|deny) address [seq num] [ge val] [le val]; */ 57 | 58 | /* "ge val" (greater-or-equal) or "le val" (less-or-equal) */ 59 | } 60 | 61 | /* a access filter must explicitly permit, as it denies by default */ 62 | access-list out1 { 63 | /* accept any prefix except 2001:2002::/64 */ 64 | prefix deny 2001:2002::/64; 65 | prefix permit any; 66 | } 67 | 68 | e.g. 69 | access-list one { 70 | prefix permit 2000::/3 ge 24 le 64; 71 | } 72 | 73 | access-list two { 74 | prefix permit 2001:cafe::/32; 75 | } 76 | 77 | neighbor { 78 | 2001:cafe::1 { 79 | peer-as 65122; 80 | 81 | filter in one; 82 | filter out two; 83 | } 84 | 2001:beef::2 { 85 | peer-as 65123; 86 | 87 | /* no filters? accept by default */ 88 | } 89 | } 90 | */ 91 | } 92 | 93 | /* Group configuration */ 94 | groups { 95 | /* For ff0e::/16, ff1e::/16 and ff3e:30:2001:700::/64 the configuration is static */ 96 | ff0e::/16 { 97 | pim { 98 | rp 2001:660:3007:300:1::; 99 | } 100 | } 101 | ff1e::/16 { 102 | pim { 103 | rp 2001:660:3007:300:1::; 104 | } 105 | } 106 | ff3e:30:2001:700::/64 { 107 | pim { 108 | rp 2001:700:e000:501::2; 109 | } 110 | } 111 | } 112 | 113 | -------------------------------------------------------------------------------- /src/confs/mrd.m6bone.conf: -------------------------------------------------------------------------------- 1 | /* MRD example configuration file */ 2 | 3 | log { 4 | /* Logs are controlled via the 'attach' method */ 5 | /* syntax (one of): 6 | 7 | attach syslog [level] 8 | attach stderr [level] 9 | attach name filename [level] 10 | 11 | where level is one of: 12 | quiet, normal, verbose, debug or extradebug 13 | 14 | loglevels may be checked via console, e.g.: 15 | ../tools/mrd6sh show log \* 16 | */ 17 | attach stderr normal; 18 | attach default "mrd.log" debug; 19 | } 20 | 21 | /* Enable the console, MLD and PIM modules */ 22 | load-module console; 23 | load-module mld; 24 | load-module pim; 25 | 26 | console { 27 | /* Allow access from any host with admin/admin */ 28 | /* allow-access admin admin any; */ 29 | 30 | /* Command format: */ 31 | /* allow-access [password [address mask]]; */ 32 | } 33 | 34 | /* Static MRIB configuration */ 35 | mrib { 36 | /* Available commands: 37 | local ; 38 | prefix via [dev ] [metric ] [export]; 39 | e.g. 40 | local 2001:2002:2003::/48; 41 | prefix 2000::/3 via 2001:2002::1; 42 | */ 43 | } 44 | 45 | /* Group configuration */ 46 | groups { 47 | /* For ff0e::/16, ff1e::/16 and ff3e:30:2001:700::/64 the configuration is static */ 48 | ff0e::/16 { 49 | pim rp 2001:660:3007:300:1::; 50 | } 51 | ff1e::/16 { 52 | pim rp 2001:660:3007:300:1::; 53 | } 54 | ff3e:30:2001:700::/64 { 55 | pim rp 2001:700:e000:501::2; 56 | } 57 | } 58 | 59 | -------------------------------------------------------------------------------- /src/confs/mrd.translator.conf: -------------------------------------------------------------------------------- 1 | /* MRD example configuration file */ 2 | 3 | log { 4 | /* Logs are controlled via the 'attach' method */ 5 | /* syntax (one of): 6 | 7 | attach syslog [level] 8 | attach stderr [level] 9 | attach name filename [level] 10 | 11 | where level is one of: 12 | quiet, normal, verbose, debug or extradebug 13 | */ 14 | attach stderr normal; 15 | attach default "mrd.log" debug; 16 | } 17 | 18 | load-module console; 19 | load-module mld; 20 | load-module pim; 21 | 22 | console { 23 | /* Allow access from any host with admin/admin */ 24 | /* allow-access admin admin any; */ 25 | 26 | /* Command format: */ 27 | /* allow-access [username [password [address mask]]]; */ 28 | } 29 | 30 | /* Global pim variable configuration */ 31 | pim { 32 | /* we want to be a BSR candidate */ 33 | enable bsr-candidate; 34 | /* we want to be a RP candidate */ 35 | enable rp-candidate; 36 | } 37 | 38 | /* Groups configuration */ 39 | groups { 40 | /* group mask */ 41 | ff0e::/16 { 42 | pim { 43 | /* include this group mask in our RP adv */ 44 | enable rp_adv; 45 | } 46 | } 47 | } 48 | 49 | /* IPv4 to IPv6 multicast translator configuration. 50 | * See README.translator for details. */ 51 | translator { 52 | 53 | /* IPv4 interface and address of the translator 54 | * Uncomment to enable the translator. */ 55 | // ipv4-interface = eth0; 56 | ipv4-address = 192.0.2.75; 57 | 58 | /* Unicast prefix prepended to IPv4 source addresses. 59 | * The prefix must be routed towards the translator on 60 | * the IPv6 network. */ 61 | unicast-prefix = 2001:db8:ab:cd:ef::/96; 62 | 63 | /* Multicast prefix prepended to IPv4 ASM and SSM group addresses */ 64 | asm-prefix = ff7e:140:2001:db8:ab:cd::/96; 65 | ssm-prefix = ff3e::/96; 66 | } 67 | -------------------------------------------------------------------------------- /src/console/Module.options: -------------------------------------------------------------------------------- 1 | boolean TELNET default on description "Enable console's Telnet support" 2 | -------------------------------------------------------------------------------- /src/console/unix_console.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Multicast Routing Daemon (MRD) 3 | * unix_console.cpp 4 | * 5 | * Copyright (C) 2006, 2007 - Hugo Santos 6 | * Copyright (C) 2004..2006 - Universidade de Aveiro, IT Aveiro 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * Author: Hugo Santos 23 | */ 24 | 25 | #include 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #include 36 | 37 | extern const char *socketPath; 38 | 39 | extern console_module *console; 40 | 41 | bool __console_allow_local(const std::vector &args) { 42 | if (args.empty()) 43 | return false; 44 | 45 | group *grp = getgrnam(args[0].c_str()); 46 | if (!grp) 47 | return false; 48 | 49 | if (chown(socketPath, 0, grp->gr_gid) != 0) 50 | return false; 51 | 52 | return chmod(socketPath, 0660) == 0; 53 | } 54 | 55 | unix_console_connection::unix_console_connection(mrd *core, int fd) 56 | : console_connection(core, fd) { 57 | autoclose = true; 58 | } 59 | 60 | void unix_console_connection::flushed(const char *str, bool newline) { 61 | writeclient(str); 62 | if (newline) 63 | writeclient("\n"); 64 | } 65 | 66 | void unix_console_connection::process_input(int len) { 67 | int st = 0; 68 | 69 | while (st < len) { 70 | int i; 71 | 72 | for (i = st; i < len; i++) { 73 | if (buffer[i] == '\n' || buffer[i] == ';' || buffer[i] == '?') { 74 | break; 75 | } 76 | } 77 | 78 | if (buffer[i] == '?') { 79 | //std::string in((const char *)buffer + st, i - st); 80 | std::string in((const char *)buffer + st, (i + 1) - st); 81 | 82 | dump_partial(in.c_str()); 83 | } else if ((i - st) > 0) { 84 | if (buffer[i] == '\n') 85 | i--; 86 | std::string in((const char *)buffer + st, i - st); 87 | process_line(in.c_str()); 88 | } 89 | 90 | st = i + 1; 91 | } 92 | 93 | if (autoclose) { 94 | if (bufbuffer.empty()) 95 | console->release_connection(this); 96 | else 97 | doom(); 98 | } 99 | } 100 | 101 | void unix_console_connection::release() { 102 | delete this; 103 | } 104 | 105 | -------------------------------------------------------------------------------- /src/dummy/dummy.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Multicast Routing Daemon (MRD) 3 | * dummy.cpp 4 | * 5 | * Copyright (C) 2006, 2007 - Hugo Santos 6 | * Copyright (C) 2004..2006 - Universidade de Aveiro, IT Aveiro 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * Author: Hugo Santos 23 | */ 24 | 25 | #include 26 | #include 27 | 28 | dummy_mfa_group_source::dummy_mfa_group_source(dummy_mfa_group *, const in6_addr &, uint32_t, action *) {} 29 | 30 | void dummy_mfa_group_source::change_flags(uint32_t, action) {} 31 | 32 | void dummy_mfa_group_source::set_iif(interface *) {} 33 | void dummy_mfa_group_source::release_iif(interface *) {} 34 | 35 | void dummy_mfa_group_source::add_oif(interface *) {} 36 | void dummy_mfa_group_source::release_oif(interface *) {} 37 | 38 | void dummy_mfa_group_source::forward(ip6_hdr *, uint16_t) const {} 39 | 40 | dummy_mfa_group::dummy_mfa_group(dummy_mfa_instance *, const inet6_addr &) {} 41 | 42 | void dummy_mfa_group::activate(bool) {} 43 | 44 | mfa_group_source *dummy_mfa_group::create_source_state(const in6_addr &addr, void *) { 45 | return new dummy_mfa_group_source(this, addr, 0, 0); 46 | } 47 | 48 | void dummy_mfa_group::release_source_state(mfa_group_source *src) { 49 | delete src; 50 | } 51 | 52 | void dummy_mfa_group::change_default_flags(uint32_t, mfa_group_source::action) {} 53 | 54 | dummy_mfa_instance::dummy_mfa_instance(dummy_mfa *, router *) {} 55 | 56 | mfa_group *dummy_mfa_instance::create_group(const inet6_addr &addr, void *) { 57 | return new dummy_mfa_group(this, addr); 58 | } 59 | 60 | void dummy_mfa_instance::release_group(mfa_group *grp) { 61 | delete grp; 62 | } 63 | 64 | void dummy_mfa_instance::change_group_default_flags(uint32_t, mfa_group_source::action) {} 65 | 66 | dummy_mfa::dummy_mfa() {} 67 | 68 | bool dummy_mfa::check_startup() { 69 | return node::check_startup(); 70 | } 71 | 72 | void dummy_mfa::shutdown() {} 73 | 74 | mfa_instance *dummy_mfa::alloc_instance(router *r) { 75 | return new dummy_mfa_instance(this, r); 76 | } 77 | 78 | void dummy_mfa::added_interface(interface *intf) {} 79 | void dummy_mfa::removed_interface(interface *intf) {} 80 | 81 | dummy_rib::dummy_rib() {} 82 | 83 | bool dummy_rib::check_startup() { 84 | return true; 85 | } 86 | void dummy_rib::shutdown() {} 87 | 88 | void dummy_rib::register_route(rib_watcher_base *, const inet6_addr &) {} 89 | void dummy_rib::unregister_route(rib_watcher_base *) {} 90 | void dummy_rib::update_route(rib_watcher_base *) {} 91 | 92 | interface *dummy_rib::path_towards(const inet6_addr &, inet6_addr &, inet6_addr &, inet6_addr &) const { 93 | return 0; 94 | } 95 | 96 | -------------------------------------------------------------------------------- /src/dummy/mrd_components.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Multicast Routing Daemon (MRD) 3 | * mrd_components.cpp 4 | * 5 | * Copyright (C) 2006, 2007 - Hugo Santos 6 | * Copyright (C) 2004..2006 - Universidade de Aveiro, IT Aveiro 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * Author: Hugo Santos 23 | */ 24 | 25 | #include 26 | 27 | #include 28 | #include 29 | 30 | void mrd::start_os_components() { 31 | m_mfa = new dummy_mfa(); 32 | g_unirouter = new dummy_rib(); 33 | } 34 | 35 | -------------------------------------------------------------------------------- /src/extra/coredumper.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Multicast Routing Daemon (MRD) 3 | * coredumper.cpp 4 | * 5 | * Copyright (C) 2006, 2007 - Hugo Santos 6 | * Copyright (C) 2004..2006 - Universidade de Aveiro, IT Aveiro 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * Author: Hugo Santos 23 | */ 24 | 25 | #include 26 | #include 27 | 28 | #include 29 | 30 | static const method_info coredumper_methods[] = { 31 | { "dump", 0, 1000, false, 0 }, 32 | { 0 } 33 | }; 34 | 35 | class coredumper_module : public mrd_module, public node { 36 | public: 37 | coredumper_module(mrd *m, void *); 38 | ~coredumper_module(); 39 | 40 | bool check_startup(); 41 | void shutdown(); 42 | 43 | bool call_method(int id, base_stream &, 44 | const std::vector &); 45 | 46 | bool dump(base_stream &); 47 | }; 48 | 49 | module_entry(coredumper, coredumper_module); 50 | 51 | coredumper_module::coredumper_module(mrd *m, void *dlh) 52 | : mrd_module(m, dlh), node(m, "coredumper") {} 53 | 54 | coredumper_module::~coredumper_module() { 55 | } 56 | 57 | bool coredumper_module::check_startup() { 58 | if (!node::check_startup()) 59 | return false; 60 | import_methods(coredumper_methods); 61 | return m_mrd->add_child("coredumper", this) != 0; 62 | } 63 | 64 | void coredumper_module::shutdown() { 65 | m_mrd->remove_child("coredumper"); 66 | } 67 | 68 | bool coredumper_module::call_method(int id, base_stream &out, 69 | const std::vector &args) { 70 | if (id == 1000) 71 | return dump(out); 72 | return node::call_method(id, out, args); 73 | } 74 | 75 | bool coredumper_module::dump(base_stream &out) { 76 | char filename[256]; 77 | 78 | sprintf(filename, "coredump-%u", (uint32_t)time(0)); 79 | 80 | if (WriteCoreDump(filename) < 0) { 81 | out << "Failed to write coredump." << endl; 82 | } else { 83 | out << "Core dumped to " << filename << endl; 84 | } 85 | 86 | return true; 87 | } 88 | 89 | -------------------------------------------------------------------------------- /src/icmp.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Multicast Routing Daemon (MRD) 3 | * icmp.cpp 4 | * 5 | * Copyright (C) 2006, 2007 - Hugo Santos 6 | * Copyright (C) 2004..2006 - Universidade de Aveiro, IT Aveiro 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * Author: Hugo Santos 23 | */ 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | bool icmp_base::register_handler(int type, icmp_handler *h) { 30 | handlers::iterator i = m_handlers.find(type); 31 | 32 | if (!h) { 33 | if (i != m_handlers.end()) 34 | m_handlers.erase(i); 35 | else 36 | return false; 37 | } else { 38 | if (i != m_handlers.end()) 39 | return false; 40 | 41 | m_handlers[type] = h; 42 | } 43 | 44 | registration_changed(); 45 | 46 | return true; 47 | } 48 | 49 | void icmp_base::registration_changed() { 50 | } 51 | 52 | bool icmp_base::send_icmp(const in6_addr &dst, icmp6_hdr *hdr, uint16_t len) const { 53 | interface *intf = g_mrd->rib().path_towards(dst); 54 | 55 | if (!intf) 56 | return false; 57 | 58 | return send_icmp(intf, dst, hdr, len); 59 | } 60 | 61 | bool icmp_base::send_icmp(const interface *intf, const in6_addr &dst, 62 | icmp6_hdr *hdr, uint16_t len) const { 63 | return send_icmp(intf, dst, -1, hdr, len); 64 | } 65 | 66 | bool icmp_base::send_icmp(const interface *intf, const in6_addr &dst, 67 | int rta, icmp6_hdr *hdr, uint16_t len) const { 68 | if (IN6_IS_ADDR_LINKLOCAL(&dst) || IN6_IS_ADDR_MC_LINKLOCAL(&dst)) 69 | return send_icmp(intf, *intf->linklocal(), dst, rta, hdr, len); 70 | else { 71 | if (intf->globals().empty()) { 72 | if (g_mrd->should_log(DEBUG)) { 73 | g_mrd->log().xprintf( 74 | "[ICMPv6] Failed to send message to " 75 | "%{addr}, no global address.\n", dst); 76 | } 77 | return false; 78 | } 79 | 80 | return send_icmp(intf, *intf->globals().begin(), dst, rta, hdr, len); 81 | } 82 | } 83 | 84 | bool icmp_base::send_icmp(const interface *intf, const in6_addr &src, 85 | const in6_addr &to, icmp6_hdr *hdr, 86 | uint16_t len) const { 87 | return send_icmp(intf, src, to, -1, hdr, len); 88 | } 89 | 90 | void icmp_base::icmp_message_available(interface *intf, const in6_addr &src, 91 | const in6_addr &dst, icmp6_hdr *hdr, 92 | int len) { 93 | handlers::iterator i = m_handlers.find((int)hdr->icmp6_type); 94 | if (i != m_handlers.end()) { 95 | i->second->icmp_message_available(intf, src, dst, hdr, len); 96 | } else { 97 | if (g_mrd->should_log(MESSAGE_CONTENT)) { 98 | g_mrd->log().xprintf("[ICMPv6] No handler for type " 99 | "%i.\n", (int)hdr->icmp6_type); 100 | } 101 | } 102 | } 103 | 104 | void icmp_base::require_mgroup(const in6_addr &mgroup, bool include) { 105 | mgroups::iterator i = m_mgroups.find(mgroup); 106 | 107 | if (include) { 108 | if (i == m_mgroups.end()) { 109 | m_mgroups[mgroup] = 1; 110 | internal_require_mgroup(mgroup, true); 111 | } else { 112 | i->second ++; 113 | } 114 | } else { 115 | if (i != m_mgroups.end()) { 116 | i->second --; 117 | if (i->second == 0) { 118 | m_mgroups.erase(i); 119 | internal_require_mgroup(mgroup, false); 120 | } 121 | } 122 | } 123 | } 124 | 125 | -------------------------------------------------------------------------------- /src/icmp_inet6.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Multicast Routing Daemon (MRD) 3 | * icmp_inet6.cpp 4 | * 5 | * Copyright (C) 2006, 2007 - Hugo Santos 6 | * Copyright (C) 2004..2006 - Universidade de Aveiro, IT Aveiro 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * Author: Hugo Santos 23 | */ 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include 31 | 32 | #include 33 | #include 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | 44 | /* this should be in */ 45 | #ifndef IP6OPT_ROUTER_ALERT 46 | #define IP6OPT_ROUTER_ALERT 5 47 | #endif 48 | 49 | icmp_inet6::icmp_inet6() 50 | : m_icmpsock("icmpv6", this, std::mem_fun(&icmp_inet6::data_available)) { 51 | } 52 | 53 | static uint8_t buffer[8192]; 54 | 55 | bool icmp_inet6::check_startup() { 56 | int sock = socket(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6); 57 | if (sock < 0) { 58 | if (g_mrd->should_log(WARNING)) 59 | g_mrd->log().perror("ICMPv6: Failed to create ICMPv6 socket"); 60 | return false; 61 | } 62 | 63 | if (!m_icmpsock.register_fd(sock)) { 64 | close(sock); 65 | return false; 66 | } 67 | 68 | if (!m_icmpsock.enable_mc_loop(false)) 69 | return false; 70 | 71 | return true; 72 | } 73 | 74 | void icmp_inet6::shutdown() { 75 | m_icmpsock.unregister(); 76 | } 77 | 78 | bool icmp_inet6::apply_icmp_filter() { 79 | #ifdef ICMP6_FILTER 80 | icmp6_filter filter; 81 | ICMP6_FILTER_SETBLOCKALL(&filter); 82 | 83 | for (handlers::const_iterator i = 84 | m_handlers.begin(); i != m_handlers.end(); ++i) { 85 | ICMP6_FILTER_SETPASS(i->first, &filter); 86 | } 87 | 88 | if (setsockopt(m_icmpsock.fd(), IPPROTO_ICMPV6, ICMP6_FILTER, 89 | &filter, sizeof(filter)) < 0) { 90 | if (g_mrd->should_log(VERBOSE)) 91 | g_mrd->log().writeline("[ICMPv6] failed to install " 92 | "ICMP filter in socket."); 93 | 94 | return false; 95 | } 96 | #endif 97 | 98 | return true; 99 | } 100 | 101 | void icmp_inet6::registration_changed() { 102 | apply_icmp_filter(); 103 | } 104 | 105 | void icmp_inet6::data_available(uint32_t) { 106 | int recvlen = m_icmpsock.recvfrom(buffer, sizeof(buffer)); 107 | 108 | if (recvlen < 0) 109 | return; 110 | 111 | sockaddr_in6 dst; 112 | int index; 113 | 114 | if (!m_icmpsock.destination_address(dst, index)) 115 | return; 116 | 117 | if (index == 0) 118 | return; 119 | 120 | const sockaddr_in6 &from = m_icmpsock.source_address(); 121 | 122 | if (g_mrd->should_log(MESSAGE_SIG)) 123 | g_mrd->log().xprintf("[ICMPv6] Message from %{addr} to %{addr}" 124 | " dev %i.\n", from.sin6_addr, 125 | dst.sin6_addr, index); 126 | 127 | interface *intf = g_mrd->get_interface_by_index(index); 128 | if (!intf) 129 | return; 130 | 131 | icmp_message_available(intf, from.sin6_addr, dst.sin6_addr, 132 | (icmp6_hdr *)buffer, recvlen); 133 | } 134 | 135 | static int _add_rta(const socket6_base &b, uint16_t value) { 136 | /* Hop-by-hop Option header with RTA 137 | * [ 00 00 05 02 00 00 01 00 ] */ 138 | const int opt_rta_len = 8; 139 | 140 | cmsghdr *cmsg = b.next_cmsghdr(opt_rta_len); 141 | if (cmsg == NULL) 142 | return -1; 143 | 144 | cmsg->cmsg_len = CMSG_SPACE(opt_rta_len); 145 | cmsg->cmsg_level = IPPROTO_IPV6; 146 | cmsg->cmsg_type = IPV6_HOPOPTS; 147 | 148 | uint8_t *extbuf = (uint8_t *)CMSG_DATA(cmsg); 149 | 150 | extbuf[0] = 0x00; /* next header */ 151 | extbuf[1] = 0x00; /* length (8 bytes) */ 152 | extbuf[2] = IP6OPT_ROUTER_ALERT; 153 | extbuf[3] = 0x02; /* RTA length (2 bytes) */ 154 | *(uint16_t *)(extbuf + 4) = htons(value); 155 | extbuf[6] = IP6OPT_PADN; 156 | extbuf[7] = 0x00; 157 | 158 | return CMSG_SPACE(opt_rta_len); 159 | } 160 | 161 | bool icmp_inet6::send_icmp(const interface *intf, const in6_addr &src, 162 | const in6_addr &to, int rtaval, icmp6_hdr *hdr, 163 | uint16_t len) const { 164 | sockaddr_in6 dst, from; 165 | 166 | memset(&dst, 0, sizeof(sockaddr_in6)); 167 | memset(&from, 0, sizeof(sockaddr_in6)); 168 | 169 | dst.sin6_family = AF_INET6; 170 | dst.sin6_addr = to; 171 | 172 | from.sin6_family = AF_INET6; 173 | from.sin6_addr = src; 174 | 175 | if (IN6_IS_ADDR_LINKLOCAL(&src)) 176 | from.sin6_scope_id = intf->index(); 177 | 178 | int optspace = 0; 179 | 180 | if (rtaval >= 0) { 181 | optspace = _add_rta(m_icmpsock, rtaval); 182 | if (optspace < 0) { 183 | if (g_mrd->should_log(EXTRADEBUG)) 184 | g_mrd->log().writeline( 185 | "Failed to send ICMPv6 message: wasn't" 186 | "able to construct message."); 187 | return false; 188 | } 189 | } 190 | 191 | if (m_icmpsock.sendto(hdr, len, &dst, &from, optspace) < 0) { 192 | if (g_mrd->should_log(EXTRADEBUG)) 193 | g_mrd->log().xprintf("Failed to send ICMPv6 message from" 194 | " %{addr} to %{addr}: %s.\n", src, 195 | to, strerror(errno)); 196 | return false; 197 | } 198 | 199 | if (g_mrd->should_log(MESSAGE_SIG)) 200 | g_mrd->log().xprintf("Sent ICMPv6 message from %{addr} to " 201 | "%{addr} in %s.\n", src, to, 202 | intf->name()); 203 | 204 | return true; 205 | } 206 | 207 | void icmp_inet6::internal_require_mgroup(const in6_addr &mgroup, bool include) { 208 | mrd::interface_list::const_iterator i = g_mrd->intflist().begin(); 209 | 210 | for (; i != g_mrd->intflist().end(); ++i) { 211 | if (!i->second->up()) 212 | continue; 213 | 214 | if (include) 215 | m_icmpsock.join_mc(i->second, mgroup); 216 | else 217 | m_icmpsock.leave_mc(i->second, mgroup); 218 | } 219 | } 220 | 221 | void icmp_inet6::added_interface(interface *intf) { 222 | for (mgroups::const_iterator i = 223 | m_mgroups.begin(); i != m_mgroups.end(); ++i) { 224 | m_icmpsock.join_mc(intf, i->first); 225 | } 226 | } 227 | 228 | void icmp_inet6::removed_interface(interface *intf) { 229 | for (mgroups::const_iterator i = 230 | m_mgroups.begin(); i != m_mgroups.end(); ++i) { 231 | m_icmpsock.leave_mc(intf, i->first); 232 | } 233 | } 234 | 235 | -------------------------------------------------------------------------------- /src/linux/Module.options: -------------------------------------------------------------------------------- 1 | boolean MMAP default on description "Enable Packet Socket MMAP support" 2 | boolean ICMPRAW default on description "Use PF_PACKET ICMP backend on Linux. Supports MLDv1" 3 | boolean TRANSLATOR default on description "Enable the IPv4 to IPv6 multicast translator" 4 | -------------------------------------------------------------------------------- /src/linux/mrd_components.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Multicast Routing Daemon (MRD) 3 | * mrd_components.cpp 4 | * 5 | * Copyright (C) 2006, 2007 - Hugo Santos 6 | * Copyright (C) 2004..2006 - Universidade de Aveiro, IT Aveiro 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * Author: Hugo Santos 23 | */ 24 | 25 | #include 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | 34 | #if defined(__GLIBC__) && !defined(__UCLIBC__) 35 | #include 36 | #endif 37 | 38 | static bool ks_mfa_available() { 39 | int icmpsock = socket(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6); 40 | if (icmpsock < 0) { 41 | return false; 42 | } 43 | 44 | int vers = 1; 45 | 46 | if (setsockopt(icmpsock, IPPROTO_IPV6, MRT6_INIT, &vers, sizeof(vers)) < 0) { 47 | close(icmpsock); 48 | return false; 49 | } else { 50 | setsockopt(icmpsock, IPPROTO_IPV6, MRT6_DONE, 0, 0); 51 | close(icmpsock); 52 | return true; 53 | } 54 | } 55 | 56 | bool mrd::prepare_os_components() { 57 | if (ks_mfa_available()) { 58 | if (should_log(NORMAL)) 59 | log().writeline("Using kernel-space multicast forwarding"); 60 | 61 | m_mfa = new ks_mfa(); 62 | } else { 63 | if (should_log(NORMAL)) 64 | log().writeline("Kernel-space multicast forwarding not available; falling back to user-space forwarding"); 65 | 66 | m_mfa = new us_mfa(); 67 | } 68 | 69 | if (!instantiate_property_b("handle-proper-bridge", false)) 70 | return false; 71 | 72 | #ifndef LINUX_NO_ICMPRAW 73 | m_icmp = new linux_icmp_raw(); 74 | #endif 75 | 76 | return true; 77 | } 78 | 79 | void mrd::prepare_second_components() { 80 | if (!m_rib_handler) 81 | m_rib_handler = new linux_unicast_router(); 82 | } 83 | 84 | const char *mrd::loopback_interface_name() const { 85 | return "lo"; 86 | } 87 | 88 | #define MAX_DEEP_BACKTRACE 32 89 | 90 | void mrd::output_backtrace(base_stream &out) const { 91 | #if defined(__GLIBC__) && !defined(__UCLIBC__) 92 | void *bt[MAX_DEEP_BACKTRACE]; 93 | 94 | int count = backtrace(bt, MAX_DEEP_BACKTRACE); 95 | 96 | char **btnames = backtrace_symbols(bt, count); 97 | 98 | for (int i = 0; i < count; i++) { 99 | out.xprintf("#%i %s\n", i+1, btnames[i]); 100 | } 101 | 102 | free(btnames); 103 | #else 104 | out.writeline("Backtraces aren't available in this system."); 105 | #endif 106 | } 107 | 108 | char *mrd::obtain_frame_description(void *ptr) const { 109 | #if defined(__GLIBC__) && !defined(__UCLIBC__) 110 | void *p[1] = { ptr }; 111 | 112 | char **names = backtrace_symbols(p, 1); 113 | char *ret = strdup(names[0]); 114 | free(names); 115 | 116 | return ret; 117 | #else 118 | return 0; 119 | #endif 120 | } 121 | 122 | void *mrd::posix_uctx::get_current_frame() const { 123 | #if defined(__GLIBC__) 124 | #if defined(__i386__) 125 | return (void *)base->uc_mcontext.gregs[REG_EIP]; 126 | #endif 127 | #endif 128 | return 0; 129 | } 130 | 131 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Multicast Routing Daemon (MRD) 3 | * main.cpp 4 | * 5 | * Copyright (C) 2006, 2007 - Hugo Santos 6 | * Copyright (C) 2004..2006 - Universidade de Aveiro, IT Aveiro 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * Author: Hugo Santos 23 | */ 24 | 25 | #include 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include 34 | 35 | void usage() { 36 | printf("Usage: mrd [OPTIONS...]\n\n"); 37 | printf(" -D run in the background\n"); 38 | printf(" -A don't auto-load static modules\n"); 39 | printf(" -f configuration file to use. mrd.conf is used by default\n"); 40 | printf(" -h this screen\n"); 41 | } 42 | 43 | int main(int argc, char **argv) { 44 | mrd m; 45 | 46 | static option longopts[] = { 47 | { "help", 0, 0, 'h' }, 48 | { 0, 0, 0, 0 } 49 | }; 50 | 51 | int c, optint; 52 | bool forkself = false; 53 | bool autoload = true; 54 | const char *conffile = 0; 55 | 56 | while ((c = getopt_long(argc, argv, "DAhf:m:", longopts, &optint)) != -1) { 57 | switch (c) { 58 | case 'D': 59 | forkself = true; 60 | break; 61 | case 'A': 62 | autoload = false; 63 | break; 64 | case 'h': 65 | usage(); 66 | return 1; 67 | case 'f': 68 | conffile = optarg; 69 | break; 70 | case 'm': 71 | m.load_early_module(optarg); 72 | break; 73 | } 74 | } 75 | 76 | if (forkself) { 77 | if (daemon(1, 0) != 0) { 78 | fprintf(stderr, "(MRD) failed to daemonize."); 79 | return -1; 80 | } 81 | } 82 | 83 | if (!m.check_startup(conffile, autoload)) { 84 | return -1; 85 | } 86 | 87 | m.start(); 88 | 89 | return 0; 90 | } 91 | 92 | -------------------------------------------------------------------------------- /src/mfa.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Multicast Routing Daemon (MRD) 3 | * mfa.cpp 4 | * 5 | * Copyright (C) 2006, 2007 - Hugo Santos 6 | * Copyright (C) 2004..2006 - Universidade de Aveiro, IT Aveiro 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * Author: Hugo Santos 23 | */ 24 | 25 | #include 26 | #include 27 | 28 | mfa_group_source::mfa_group_source() { 29 | } 30 | 31 | mfa_group_source::~mfa_group_source() { 32 | } 33 | 34 | mfa_group::mfa_group(router *owner) 35 | : m_owner(owner) { 36 | } 37 | 38 | mfa_core::mfa_core() 39 | : node(g_mrd, "mfa") { 40 | 41 | change_group_default_flags(mfa_group_source::f_wrong_iif, 42 | mfa_group_source::copy_metadata); 43 | 44 | } 45 | 46 | bool mfa_core::pre_startup() { 47 | if (!node::check_startup()) 48 | return false; 49 | 50 | g_mrd->add_child(this); 51 | 52 | return true; 53 | } 54 | 55 | mfa_core *mfa_core::mfa() { 56 | return g_mrd->m_mfa; 57 | } 58 | 59 | -------------------------------------------------------------------------------- /src/mld/mld_conf.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Multicast Routing Daemon (MRD) 3 | * mld_conf.cpp 4 | * 5 | * Copyright (C) 2006, 2007 - Hugo Santos 6 | * Copyright (C) 2004..2006 - Universidade de Aveiro, IT Aveiro 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * Author: Hugo Santos 23 | */ 24 | 25 | #include 26 | #include 27 | 28 | #include 29 | 30 | enum { 31 | mld_intfconf_method_signaling_filter = 3000, 32 | }; 33 | 34 | static const method_info mld_intfconf_node_methods[] = { 35 | { "signaling-filter", 0, mld_intfconf_method_signaling_filter, false, 0 }, 36 | { 0 } 37 | }; 38 | 39 | mld_intfconf_node::mld_intfconf_node(intfconf *conf) 40 | : intfconf_node(conf, "mld") { 41 | } 42 | 43 | bool mld_intfconf_node::check_startup() { 44 | if (!intfconf_node::check_startup()) 45 | return false; 46 | 47 | import_methods(mld_intfconf_node_methods); 48 | 49 | return true; 50 | } 51 | 52 | bool mld_intfconf_node::fill_defaults() { 53 | instantiate_property_u("robustness", 2); 54 | instantiate_property_u("query_interval", 125000); 55 | instantiate_property_u("query_response_interval", 10000); 56 | instantiate_property_u("startup_query_interval", 125000 / 4); 57 | instantiate_property_u("startup_query_count", 2); 58 | instantiate_property_u("last_listener_query_interval", 1000); 59 | instantiate_property_u("last_listener_query_count", 2); 60 | instantiate_property_u("unsolicited_report_interval", 1000); 61 | instantiate_property_u("version", 2); 62 | 63 | instantiate_property_b("querier", true); 64 | 65 | instantiate_property("proxy_to", property_def::VAL_STRING); 66 | 67 | return m_properties.size() == 11; 68 | } 69 | 70 | bool mld_intfconf_node::call_method(int id, base_stream &out, 71 | const std::vector &args) { 72 | if (id == mld_intfconf_method_signaling_filter) { 73 | std::set filter; 74 | 75 | for (std::vector::const_iterator i = 76 | args.begin(); i != args.end(); ++i) { 77 | inet6_addr addr; 78 | if (!addr.set(i->c_str())) 79 | return false; 80 | filter.insert(filter.end(), addr); 81 | } 82 | 83 | m_signaling_filter = filter; 84 | 85 | return true; 86 | } 87 | 88 | return intfconf_node::call_method(id, out, args); 89 | } 90 | 91 | bool mld_intfconf_node::set_property(const char *key, const char *value) { 92 | if (!next_similar_node()->has_property(key)) 93 | return false; 94 | 95 | return set_property_inst(key, property_def::VAL_UNSIGNED, value); 96 | } 97 | 98 | uint32_t mld_intfconf_node::robustness() const { 99 | return get_property_unsigned("robustness"); 100 | } 101 | 102 | uint32_t mld_intfconf_node::query_interval() const { 103 | return get_property_unsigned("query_interval"); 104 | } 105 | 106 | uint32_t mld_intfconf_node::query_response_interval() const { 107 | return get_property_unsigned("query_response_interval"); 108 | } 109 | 110 | uint32_t mld_intfconf_node::mali() const { 111 | return robustness() * query_interval() + query_response_interval(); 112 | } 113 | 114 | uint32_t mld_intfconf_node::other_querier_present_timeout() const { 115 | return robustness() * query_interval() + query_response_interval() / 2; 116 | } 117 | 118 | uint32_t mld_intfconf_node::startup_query_interval() const { 119 | return get_property_unsigned("startup_query_interval"); 120 | } 121 | 122 | uint32_t mld_intfconf_node::startup_query_count() const { 123 | return get_property_unsigned("startup_query_count"); 124 | } 125 | 126 | uint32_t mld_intfconf_node::last_listener_query_interval() const { 127 | return get_property_unsigned("last_listener_query_interval"); 128 | } 129 | 130 | uint32_t mld_intfconf_node::last_listener_query_count() const { 131 | return get_property_unsigned("last_listener_query_count"); 132 | } 133 | 134 | uint32_t mld_intfconf_node::last_listener_query_time() const { 135 | return last_listener_query_interval() * last_listener_query_count(); 136 | } 137 | 138 | uint32_t mld_intfconf_node::unsolicited_report_interval() const { 139 | return get_property_unsigned("unsolicited_report_interval"); 140 | } 141 | 142 | uint32_t mld_intfconf_node::older_version_querier_present_timeout() const { 143 | /* XXX query_interval should be the last query_interval received */ 144 | return robustness() * query_interval() + query_response_interval(); 145 | } 146 | 147 | uint32_t mld_intfconf_node::version() const { 148 | return get_property_unsigned("version"); 149 | } 150 | 151 | bool mld_intfconf_node::querier() const { 152 | return get_property_bool("querier"); 153 | } 154 | 155 | const std::set &mld_intfconf_node::signaling_filter() const { 156 | return m_signaling_filter; 157 | } 158 | 159 | mld_groupconf_node::mld_groupconf_node(groupconf *parent) 160 | : groupconf_node(parent, "mld") { 161 | } 162 | 163 | bool mld_groupconf_node::fill_defaults() { 164 | if (!instantiate_property_b("forward", false)) 165 | return false; 166 | return true; 167 | } 168 | 169 | bool mld_groupconf_node::set_property(const char *key, const char *value) { 170 | return !strcmp(key, "forward") && set_property_inst(key, property_def::VAL_BOOL, value); 171 | } 172 | 173 | -------------------------------------------------------------------------------- /src/mld/mld_def.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Multicast Routing Daemon (MRD) 3 | * mld_def.cpp 4 | * 5 | * Copyright (C) 2006, 2007 - Hugo Santos 6 | * Copyright (C) 2004..2006 - Universidade de Aveiro, IT Aveiro 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * Author: Hugo Santos 23 | */ 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | void mldv1::construct(const in6_addr &addr, int _type, mld_intfconf_node *n) { 31 | type = _type; 32 | code = 0; 33 | checksum = 0; 34 | 35 | /* General Query 36 | * max_response_delay = [Query Response Interval] 37 | * Multicast-Address-Specific Query 38 | * max_response_delay = [Last Listener Query Interval] */ 39 | 40 | if (IN6_IS_ADDR_UNSPECIFIED(&addr)) 41 | maxdelay = hton((uint16_t)n->query_response_interval()); 42 | else 43 | maxdelay = hton((uint16_t)n->last_listener_query_interval()); 44 | 45 | data = hton((uint16_t)0); 46 | 47 | mcaddr = addr; 48 | } 49 | 50 | void mldv1_query::construct(const in6_addr &mcaddr, mld_intfconf_node *node) { 51 | mldv1::construct(mcaddr, MLD_LISTENER_QUERY, node); 52 | } 53 | 54 | void mldv2_query::construct(const in6_addr &addr, int type, mld_intfconf_node *n) { 55 | mldv1::construct(addr, type, n); 56 | 57 | qrv = n->robustness(); 58 | suppress = 0; 59 | resv2 = 0; 60 | 61 | uint32_t qis = n->query_interval() / 1000; 62 | 63 | if (qis < 128) 64 | qqic = qis; 65 | else { 66 | int exp = 0; 67 | 68 | while ((qis >> (exp+3)) > 0x1f) 69 | exp++; 70 | 71 | qis >>= exp+3; 72 | qis -= 0x10; 73 | 74 | qqic = 0x80 | (exp << 4) | qis; 75 | } 76 | 77 | nsrcs = hton((uint16_t)0); 78 | } 79 | 80 | -------------------------------------------------------------------------------- /src/mld/mld_module.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Multicast Routing Daemon (MRD) 3 | * mld_module.cpp 4 | * 5 | * Copyright (C) 2006, 2007 - Hugo Santos 6 | * Copyright (C) 2004..2006 - Universidade de Aveiro, IT Aveiro 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * Author: Hugo Santos 23 | */ 24 | 25 | #include 26 | #include 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | extern mld_router *mld; 34 | 35 | class mld_module : public mrd_module { 36 | public: 37 | mld_module(mrd *m, void *dlh); 38 | 39 | bool check_startup(); 40 | void shutdown(); 41 | 42 | void module_loaded(const char *, mrd_module *); 43 | }; 44 | 45 | module_entry(mld, mld_module); 46 | 47 | mld_module::mld_module(mrd *m, void *dlh) : mrd_module(m, dlh) { 48 | } 49 | 50 | bool mld_module::check_startup() { 51 | mld = new mld_router(); 52 | if (!mld) 53 | return false; 54 | if (!g_mrd->register_router(mld)) { 55 | delete mld; 56 | mld = 0; 57 | return false; 58 | } 59 | return true; 60 | } 61 | 62 | void mld_module::shutdown() { 63 | g_mrd->unregister_router(mld); 64 | mld->shutdown(); 65 | delete mld; 66 | mld = 0; 67 | } 68 | 69 | void mld_module::module_loaded(const char *name, mrd_module *) { 70 | } 71 | 72 | -------------------------------------------------------------------------------- /src/mrdisc/mrdisc_def.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Multicast Routing Daemon (MRD) 3 | * mrdisc_def.h 4 | * 5 | * Copyright (C) 2006, 2007 - Hugo Santos 6 | * Copyright (C) 2004..2006 - Universidade de Aveiro, IT Aveiro 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * Author: Hugo Santos 23 | */ 24 | 25 | #ifndef _mrd_mrdisc_def_h_ 26 | #define _mrd_mrdisc_def_h_ 27 | 28 | #include 29 | #include 30 | 31 | #define MRDISC_ROUTER_ADVERTISEMENT 151 32 | #define MRDISC_ROUTER_SOLICITATION 152 33 | #define MRDISC_ROUTER_TERMINATION 153 34 | 35 | #endif 36 | 37 | -------------------------------------------------------------------------------- /src/msnip/msnip_def.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Multicast Routing Daemon (MRD) 3 | * msnip_def.h 4 | * 5 | * Copyright (C) 2006, 2007 - Hugo Santos 6 | * Copyright (C) 2004..2006 - Universidade de Aveiro, IT Aveiro 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * Author: Hugo Santos 23 | */ 24 | 25 | #ifndef _mrd_msnip_def_h_ 26 | #define _mrd_msnip_def_h_ 27 | 28 | #include 29 | #include 30 | 31 | #define MSNIP_HIS_REPORT 202 32 | #define MSNIP_MRM_REPORT 203 33 | 34 | enum { 35 | MSNIP_TRANSMIT = 1, 36 | MSNIP_HOLD = 2 37 | }; 38 | 39 | struct msnip_his : icmp6_hdr { 40 | }; 41 | 42 | struct msnip_mrm : icmp6_hdr { 43 | struct { 44 | uint8_t rectype; 45 | uint8_t resv[3]; 46 | in6_addr address; 47 | } __attribute((packed)) records[0]; 48 | }; 49 | 50 | #endif 51 | 52 | -------------------------------------------------------------------------------- /src/no-modules.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Multicast Routing Daemon (MRD) 3 | * modules.cpp 4 | * 5 | * Copyright (C) 2007 - Hugo Santos 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | * 21 | * Author: Hugo Santos 22 | */ 23 | 24 | #include 25 | 26 | void mrd::add_static_modules() { 27 | } 28 | 29 | -------------------------------------------------------------------------------- /src/pim/Module.options: -------------------------------------------------------------------------------- 1 | boolean BSR default on description "Enable PIM Bootstrap Router support" 2 | -------------------------------------------------------------------------------- /src/pim/pim_module.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Multicast Routing Daemon (MRD) 3 | * pim_module.cpp 4 | * 5 | * Copyright (C) 2006, 2007 - Hugo Santos 6 | * Copyright (C) 2004..2006 - Universidade de Aveiro, IT Aveiro 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * Author: Hugo Santos 23 | */ 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include 32 | #include 33 | 34 | extern pim_router *pim; 35 | 36 | class pim_module : public mrd_module { 37 | public: 38 | pim_module(mrd *, void *dlh); 39 | 40 | bool check_startup(); 41 | void shutdown(); 42 | }; 43 | 44 | module_entry(pim, pim_module); 45 | 46 | pim_module::pim_module(mrd *m, void *dlh) : mrd_module(m, dlh) { 47 | } 48 | 49 | bool pim_module::check_startup() { 50 | pim = new pim_router(); 51 | if (!pim) 52 | return false; 53 | if (!g_mrd->register_router(pim)) { 54 | delete pim; 55 | pim = 0; 56 | return false; 57 | } 58 | return true; 59 | } 60 | 61 | void pim_module::shutdown() { 62 | g_mrd->unregister_router(pim); 63 | 64 | pim->shutdown(); 65 | delete pim; 66 | pim = 0; 67 | } 68 | 69 | -------------------------------------------------------------------------------- /src/pim/test-cases/hashmask.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main(int argc, char **argv) 7 | { 8 | struct in6_addr in; 9 | char buf[64]; 10 | int mask, i; 11 | 12 | inet_pton(AF_INET6, argv[1], &in); 13 | mask = atoi(argv[2]); 14 | 15 | if (mask < 128) { 16 | in.s6_addr[mask / 8] &= 0xff << (8 - mask % 8); 17 | for (i = (mask + 7) / 8; i < 16; i++) 18 | in.s6_addr[i] = 0; 19 | } 20 | 21 | printf("result: %s\n", inet_ntop(AF_INET6, &in, buf, sizeof(buf))); 22 | 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /src/ripng/EXPERIMENTAL: -------------------------------------------------------------------------------- 1 | This code is experimental and shouldn't be considered. 2 | -------------------------------------------------------------------------------- /src/router.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Multicast Routing Daemon (MRD) 3 | * router.cpp 4 | * 5 | * Copyright (C) 2006, 2007 - Hugo Santos 6 | * Copyright (C) 2004..2006 - Universidade de Aveiro, IT Aveiro 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * Author: Hugo Santos 23 | */ 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | router::router(const char *name) 31 | : node(0, name) {} 32 | 33 | router::~router() { 34 | } 35 | 36 | void router::attach(mrd *m) { 37 | m_parent = m; 38 | } 39 | 40 | bool router::check_startup() { 41 | if (!node::check_startup()) 42 | return false; 43 | 44 | return true; 45 | } 46 | 47 | void router::shutdown() { 48 | } 49 | 50 | base_stream &router::log() const { 51 | return log_router_desc(node::log()); 52 | } 53 | 54 | base_stream &router::log_router_desc(base_stream &os) const { 55 | return os; 56 | } 57 | 58 | interface *router::get_interface_by_index(int index) const { 59 | interface *intf = g_mrd->get_interface_by_index(index); 60 | if (intf->conf()->is_router_enabled(name())) 61 | return intf; 62 | return 0; 63 | } 64 | 65 | void router::created_group(group *) { 66 | /* empty */ 67 | } 68 | 69 | void router::released_group(group *) { 70 | /* empty */ 71 | } 72 | 73 | void router::add_interface(interface *) { 74 | /* empty */ 75 | } 76 | 77 | void router::remove_interface(interface *) { 78 | /* empty */ 79 | } 80 | 81 | intfconf_node *router::create_interface_configuration(intfconf *) { 82 | return 0; 83 | } 84 | 85 | groupconf_node *router::create_group_configuration(groupconf *) { 86 | return 0; 87 | } 88 | 89 | void router::mfa_notify(mfa_group_source *, const in6_addr &, const in6_addr &, 90 | uint32_t flags, mfa_group_source::action, interface *iif, 91 | ip6_hdr *, uint16_t alen, uint16_t len) { 92 | } 93 | 94 | void router::event(int id, void *param) { 95 | switch (id) { 96 | case mrd::InterfaceStateChanged: 97 | { 98 | interface *intf = (interface *)param; 99 | 100 | if (intf->up()) { 101 | if (intf->conf()->is_router_enabled(name())) 102 | add_interface(intf); 103 | } else { 104 | remove_interface(intf); 105 | } 106 | } 107 | break; 108 | case mrd::NewGroup: 109 | created_group((group *)param); 110 | break; 111 | case mrd::ReleasedGroup: 112 | released_group((group *)param); 113 | break; 114 | default: 115 | node::event(id, param); 116 | } 117 | } 118 | 119 | -------------------------------------------------------------------------------- /src/scripts/generate-modules-cpp.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | 3 | use strict; 4 | 5 | my $i; 6 | my $m; 7 | 8 | print "/* This file was automatically generated */\n"; 9 | print "#include \n"; 10 | 11 | for ($i = 0; $i <= $#ARGV; $i++) { 12 | $m = lc $ARGV[$i]; 13 | print "extern \"C\" mrd_module *mrd_module_init_$m(void *, mrd *);\n"; 14 | } 15 | 16 | print "void mrd::add_static_modules() {\n"; 17 | for ($i = 0; $i <= $#ARGV; $i++) { 18 | $m = lc $ARGV[$i]; 19 | print "\tm_static_modules[\"$m\"] = &mrd_module_init_$m;\n"; 20 | } 21 | print "}\n"; 22 | -------------------------------------------------------------------------------- /src/support/Module.options: -------------------------------------------------------------------------------- 1 | boolean POOLING default on description "Enable MRD6's memory pools" 2 | -------------------------------------------------------------------------------- /src/support/objpool.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Multicast Routing Daemon (MRD) 3 | * objpool.cpp 4 | * 5 | * Copyright (C) 2006, 2007 - Hugo Santos 6 | * Copyright (C) 2004..2006 - Universidade de Aveiro, IT Aveiro 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * Author: Hugo Santos 23 | */ 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | #ifndef SUPPORT_NO_POOLING 30 | 31 | base_objpool::base_objpool(uint32_t _count, uint32_t _single) 32 | : granularity(_count), single(_single), light(0), heavy(0) { 33 | assert(granularity > 0); 34 | } 35 | 36 | base_objpool::base_objpool(const base_objpool &pool) 37 | : granularity(pool.granularity), single(pool.single), light(0), heavy(0) { 38 | } 39 | 40 | void *base_objpool::generic_request_obj() { 41 | if (!light) { 42 | /* There are no mem chunks with free objects */ 43 | light = _alloc_chunk(granularity); 44 | if (!light) 45 | return 0; 46 | } 47 | 48 | /* assert(head->head) */ 49 | 50 | _objhead *h = light->head; 51 | light->head = h->next; 52 | 53 | /* Every node with next=0 is allocated */ 54 | h->next = 0; 55 | 56 | light->free --; 57 | 58 | if (light->free == 0) { 59 | /* move this light mem chunk to heavy mem chunks */ 60 | _memchunk *m = dlist_pop_front(light); 61 | dlist_push_front(heavy, m); 62 | } 63 | 64 | return &h->_obj; 65 | } 66 | 67 | void base_objpool::base_return_obj(void *obj, _memchunk * &m) { 68 | _objhead *h = (_objhead *)(((uint8_t *)obj) - sizeof(_objhead)); 69 | 70 | assert(h->next == 0); 71 | assert(h->parent); 72 | 73 | m = _find_chunk(h); 74 | 75 | /* assert(m = _find_chunk(h, prev)); */ 76 | 77 | h->next = m->head; 78 | m->head = h; 79 | 80 | m->free ++; 81 | 82 | if (m->free == 1) { 83 | /* mem chunk is light again */ 84 | dlist_remove(heavy, m); 85 | dlist_push_front(light, m); 86 | } 87 | } 88 | 89 | base_objpool::_memchunk *base_objpool::_alloc_chunk(uint32_t count) { 90 | uint32_t one_size = sizeof(_objhead) + single; 91 | uint32_t size = sizeof(_memchunk) + count * one_size; 92 | 93 | uint8_t *mb = new uint8_t[size]; 94 | _memchunk *m = (_memchunk *)mb; 95 | 96 | if (m) { 97 | m->chunk = mb + sizeof(_memchunk); 98 | m->endchunk = mb + size; 99 | m->prev = m->next = 0; 100 | m->head = (_objhead *)m->chunk; 101 | m->count = count; 102 | m->free = count; 103 | 104 | uint8_t *p = m->chunk; 105 | while (p < m->endchunk) { 106 | _objhead *h = (_objhead *)p; 107 | p += one_size; 108 | h->parent = m; 109 | h->next = (_objhead *)p; 110 | } 111 | } 112 | 113 | return m; 114 | } 115 | 116 | void base_objpool::_free_chunk(_memchunk *m) { 117 | uint8_t *mb = (uint8_t *)m; 118 | 119 | delete [] mb; 120 | } 121 | 122 | base_objpool::_memchunk *base_objpool::_find_chunk(_objhead *h) { 123 | return h->parent; 124 | } 125 | 126 | void base_objpool::_clear_memchunks() { 127 | _clear_memchunks(heavy); 128 | _clear_memchunks(light); 129 | } 130 | 131 | void base_objpool::_clear_memchunks(_memchunk *m) { 132 | while (m) { 133 | _memchunk *h = m; 134 | m = m->next; 135 | 136 | _free_chunk(h); 137 | } 138 | } 139 | 140 | #endif 141 | 142 | -------------------------------------------------------------------------------- /src/test_dl_inclusion_in_libc.cpp: -------------------------------------------------------------------------------- 1 | int main(void) 2 | { 3 | void *(*dlopen_fct)(const char *filename, int flag); 4 | char *(*dlerror_fct)(void); 5 | void *(*dlsym_fct)(void *handle, const char *symbol); 6 | int (*dlclose_fct)(void *handle); 7 | 8 | dlopen_fct = dlopen; 9 | dlerror_fct = dlerror; 10 | dlsym_fct = dlsym; 11 | dlclose_fct = dlclose; 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /src/tests/address_unittest.cpp: -------------------------------------------------------------------------------- 1 | #define BOOST_AUTO_TEST_MAIN 2 | #include 3 | 4 | #include 5 | 6 | BOOST_AUTO_UNIT_TEST(address_test1) { 7 | inet6_addr a0(std::string("::/0")); 8 | inet6_addr a1(std::string("::")); 9 | inet6_addr a2(std::string("2000::/3")); 10 | inet6_addr a3(std::string("2001:123:456::/3")); 11 | inet6_addr a4(std::string("2001::1")); 12 | inet6_addr a5(std::string("2002::/16")); 13 | 14 | BOOST_CHECK(a0 == inet6_addr::any()); 15 | BOOST_CHECK(a1.addr == in6addr_any); 16 | BOOST_CHECK(a1.prefixlen == 128); 17 | BOOST_CHECK(a2.addr.s6_addr[0] == 0x20); 18 | BOOST_CHECK(a2.prefixlen == 3); 19 | 20 | a3.apply_prefixlen(); 21 | 22 | BOOST_CHECK(a2 == a3); 23 | BOOST_CHECK(a0.matches(a4)); 24 | BOOST_CHECK(a2.matches(a4)); 25 | BOOST_CHECK(!a5.matches(a4)); 26 | } 27 | 28 | -------------------------------------------------------------------------------- /src/tests/mrib-1.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | for i in `seq 1 9999`; do 4 | $1 mrib prefix 2001:$i::/32 via 2001:$i::1 metric $i 5 | done 6 | 7 | -------------------------------------------------------------------------------- /src/tests/mrib_unittest.cpp: -------------------------------------------------------------------------------- 1 | #define BOOST_AUTO_TEST_MAIN 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | class test_origin : public mrib_origin { 10 | const char *description() const { return "test"; } 11 | 12 | void return_prefix(mrib_def::prefix *p) { 13 | delete p; 14 | } 15 | }; 16 | 17 | static inet6_addr ADDR(const char *str) { 18 | return inet6_addr(string(str)); 19 | } 20 | 21 | static inet6_addr ANY() { 22 | return inet6_addr::any(); 23 | } 24 | 25 | static mrib_def::prefix *new_prefix(mrib_origin *o) { 26 | mrib_def::prefix *p = new mrib_def::prefix(o); 27 | p->nexthop = inet6_addr::any(); 28 | p->distance = 0; 29 | p->metric = 0; 30 | p->flags = 0; 31 | p->intf = NULL; 32 | return p; 33 | } 34 | 35 | static void test1(mrib_def &m, test_origin &o, 36 | const inet6_addr &pfx1, mrib_def::prefix *p1, 37 | const inet6_addr &pfx2, mrib_def::prefix *p2) { 38 | BOOST_CHECK(m.get_prefix(pfx1, NULL) == p1); 39 | BOOST_CHECK(m.get_prefix(pfx1, &o) == p1); 40 | 41 | BOOST_CHECK(m.get_prefix(pfx2, NULL) == p2); 42 | BOOST_CHECK(m.get_prefix(pfx2, &o) == p2); 43 | 44 | BOOST_CHECK(m.prefix_lookup(ADDR("2001:124::1"), ANY()) == p1); 45 | BOOST_CHECK(m.prefix_lookup(ADDR("2001:123::1"), ANY()) == p2); 46 | BOOST_CHECK(m.prefix_lookup(ADDR("7000::"), ANY()) == NULL); 47 | } 48 | 49 | BOOST_AUTO_UNIT_TEST(mrib_test1) { 50 | mrib_def m(NULL); 51 | test_origin o; 52 | 53 | BOOST_REQUIRE(m.check_startup()); 54 | 55 | mrib_def::prefix *p1 = new_prefix(&o); 56 | mrib_def::prefix *p2 = new_prefix(&o); 57 | 58 | inet6_addr pfx1(ADDR("2000::/3")); 59 | inet6_addr pfx2(ADDR("2001:123::/32")); 60 | 61 | BOOST_REQUIRE(m.install_prefix(pfx1, p1)); 62 | BOOST_REQUIRE(m.install_prefix(pfx2, p2)); 63 | 64 | test1(m, o, pfx1, p1, pfx2, p2); 65 | 66 | m.shutdown(); 67 | } 68 | 69 | BOOST_AUTO_UNIT_TEST(mrib_test1_rev) { 70 | mrib_def m(NULL); 71 | test_origin o; 72 | 73 | BOOST_REQUIRE(m.check_startup()); 74 | 75 | mrib_def::prefix *p1 = new_prefix(&o); 76 | mrib_def::prefix *p2 = new_prefix(&o); 77 | 78 | inet6_addr pfx1(ADDR("2000::/3")); 79 | inet6_addr pfx2(ADDR("2001:123::/32")); 80 | 81 | BOOST_REQUIRE(m.install_prefix(pfx2, p2)); 82 | BOOST_REQUIRE(m.install_prefix(pfx1, p1)); 83 | 84 | test1(m, o, pfx1, p1, pfx2, p2); 85 | 86 | m.shutdown(); 87 | } 88 | -------------------------------------------------------------------------------- /src/tests/ptree_unittest.cpp: -------------------------------------------------------------------------------- 1 | #define BOOST_AUTO_TEST_MAIN 2 | #include 3 | 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | typedef pair test_prefix; 9 | 10 | int pnode_prefix_length(const test_prefix &p) { 11 | return p.second; 12 | } 13 | 14 | bool pnode_symbol_at(const test_prefix &p, int n) { 15 | return (p.first >> (31 - n)) & 0x1; 16 | } 17 | 18 | #include 19 | 20 | void stream_push_formated_type(base_stream &os, const test_prefix &p) { 21 | char tmp[32]; 22 | snprintf(tmp, sizeof(tmp), "%x", p.first); 23 | os.xprintf("[%s / %i]", tmp, p.second); 24 | } 25 | 26 | ostream & operator << (ostream &os, const test_prefix &p) { 27 | return os << "[" << hex << p.first << " / " << dec << p.second << "]"; 28 | } 29 | 30 | #include 31 | 32 | bool operator == (const test_prefix &p1, const test_prefix &p2) { 33 | return p1.first == p2.first && p1.second == p2.second; 34 | } 35 | 36 | struct test_node : ptree_node { 37 | test_node(const test_prefix &pfx) : prefix(pfx) {} 38 | test_node(const test_node &n) : prefix(n.prefix) {} 39 | 40 | test_prefix prefix; 41 | 42 | friend bool operator == (const test_node &n1, const test_node &n2) { 43 | return n1.prefix == n2.prefix; 44 | } 45 | }; 46 | 47 | static void fill_nodes(vector &nodes) { 48 | nodes.push_back(test_node(test_prefix(0xffff0000, 16))); 49 | nodes.push_back(test_node(test_prefix(0x7fff0000, 16))); 50 | nodes.push_back(test_node(test_prefix(0x7fff1230, 30))); 51 | nodes.push_back(test_node(test_prefix(0x7fff1231, 32))); 52 | } 53 | 54 | BOOST_AUTO_UNIT_TEST(ptree_test1) { 55 | ptree p; 56 | BOOST_REQUIRE(p.size() == 0); 57 | 58 | vector nodes; 59 | fill_nodes(nodes); 60 | 61 | size_t count = 0; 62 | for (vector::iterator i = nodes.begin(); i != nodes.end(); ++i) { 63 | test_node *node = &(*i); 64 | BOOST_CHECK(p.insert(node) == node); 65 | ++count; 66 | BOOST_CHECK(p.size() == count); 67 | } 68 | 69 | for (vector::iterator i = nodes.begin(); i != nodes.end(); ++i) { 70 | test_node *node = &(*i); 71 | BOOST_CHECK(p.search(node->prefix) == node); 72 | } 73 | 74 | log_base log(NULL); 75 | BOOST_REQUIRE(log.check_startup()); 76 | log.attach_node(new file_log_node(&log, "stderr", EVERYTHING, stderr)); 77 | 78 | p.dump_internal_tree(log.current_context()); 79 | 80 | p.clear(); 81 | BOOST_REQUIRE(p.size() == 0); 82 | } 83 | 84 | BOOST_AUTO_UNIT_TEST(ptree_test2) { 85 | ptree p; 86 | BOOST_REQUIRE(p.size() == 0); 87 | 88 | vector nodes; 89 | fill_nodes(nodes); 90 | 91 | for (vector::iterator i = nodes.begin(); i != nodes.end(); ++i) 92 | BOOST_REQUIRE(p.insert(&(*i)) != NULL); 93 | 94 | BOOST_CHECK(p.longest_match(test_prefix(0x00000000, 32)) == NULL); 95 | BOOST_CHECK(p.longest_match(test_prefix(0xfffe0000, 32)) == NULL); 96 | BOOST_CHECK(p.longest_match(test_prefix(0xffff0000, 32)) == &nodes[0]); 97 | BOOST_CHECK(p.longest_match(test_prefix(0xffff8000, 32)) == &nodes[0]); 98 | BOOST_CHECK(p.longest_match(test_prefix(0xffff1234, 32)) == &nodes[0]); 99 | BOOST_CHECK(p.longest_match(test_prefix(0x7fff1200, 32)) == &nodes[1]); 100 | BOOST_CHECK(p.longest_match(test_prefix(0x7fff1230, 32)) == &nodes[2]); 101 | BOOST_CHECK(p.longest_match(test_prefix(0x7fff1232, 32)) == &nodes[2]); 102 | BOOST_CHECK(p.longest_match(test_prefix(0x7fff1231, 32)) == &nodes[3]); 103 | 104 | p.clear(); 105 | BOOST_REQUIRE(p.size() == 0); 106 | } 107 | -------------------------------------------------------------------------------- /src/tests/run-all.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | for t in tests/*_unittest; do 3 | if [ -x $t ]; then 4 | N=`basename $t` 5 | echo " --- Running $N ---" 6 | $t 7 | fi 8 | done 9 | -------------------------------------------------------------------------------- /src/tests/stress-mrib.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Multicast Routing Daemon (MRD) 3 | * stress-mrib.cpp 4 | * 5 | * Copyright (C) 2006, 2007 - Hugo Santos 6 | * Copyright (C) 2004..2006 - Universidade de Aveiro, IT Aveiro 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * Author: Hugo Santos 23 | */ 24 | 25 | /* 26 | * stress_mrib - a simple module that when loaded will flood the 27 | * MRIB with lots of prefixes. good to test responsiveness 28 | * during install as well as memory usage. 29 | */ 30 | 31 | #include 32 | #include 33 | 34 | #include 35 | 36 | struct stress_prefix : mrib_def::prefix { 37 | stress_prefix(mrib_origin *owner) 38 | : mrib_def::prefix(owner) {} 39 | 40 | /* possible private data */ 41 | uint8_t _space[16 + 8]; 42 | }; 43 | 44 | static objpool _stress_prefixes(256); 45 | 46 | /* besides being a module, we also are a MRIB origin and an event sink */ 47 | class stress_mrib_module : public mrd_module, public mrib_origin, public event_sink { 48 | public: 49 | stress_mrib_module(mrd *, void *); 50 | ~stress_mrib_module(); 51 | 52 | const char *description() const { return "stress-mrib"; } 53 | 54 | void return_prefix(mrib_def::prefix *p) { 55 | _stress_prefixes.return_obj((stress_prefix *)p); 56 | } 57 | 58 | bool check_startup(); 59 | void shutdown(); 60 | 61 | void event(int, void *); 62 | 63 | inet6_addr nh; 64 | int count; 65 | timeval start; 66 | double accum; 67 | }; 68 | 69 | module_entry(stress_mrib, stress_mrib_module); 70 | 71 | stress_mrib_module::stress_mrib_module(mrd *m, void *p) 72 | : mrd_module(m, p) { 73 | count = 0; 74 | accum = 0; 75 | } 76 | 77 | stress_mrib_module::~stress_mrib_module() { 78 | } 79 | 80 | bool stress_mrib_module::check_startup() { 81 | /* bogus nexthop, we dont care */ 82 | if (!nh.set("2001:2002::3")) 83 | return false; 84 | 85 | gettimeofday(&start, 0); 86 | 87 | /* as soon as we are loaded, start the hammering */ 88 | g_mrd->register_task(this, 0); 89 | 90 | return true; 91 | } 92 | 93 | void stress_mrib_module::shutdown() { 94 | /* on shutdown, clear all how MRIB damage */ 95 | g_mrd->mrib().origin_lost(this); 96 | } 97 | 98 | void stress_mrib_module::event(int, void *) { 99 | /* dont install more than 500000 prefixes */ 100 | if (count >= 500000) { 101 | timeval end; 102 | gettimeofday(&end, 0); 103 | 104 | uint32_t diff = (end.tv_sec - start.tv_sec) * 1000000; 105 | if (end.tv_usec > start.tv_usec) 106 | diff += end.tv_usec - start.tv_usec; 107 | else 108 | diff += 1000000 + end.tv_usec - start.tv_usec; 109 | 110 | g_mrd->log().info(QUIET) << "[STRESS] Took " << accum << "us to install " << count << " (real " << diff << "us)" 111 | << " prefixes, " << (accum / (double)count) << "us per prefix in average" << endl; 112 | return; 113 | } 114 | 115 | count++; 116 | 117 | /* generate a random prefix */ 118 | inet6_addr p; 119 | 120 | for (int i = 0; i < 4; i++) 121 | p.addr.s6_addr32[i] = rand(); 122 | 123 | /* with a random prefix len 10-96 */ 124 | p.prefixlen = 10 + rand() % 87; 125 | 126 | p.apply_prefixlen(); 127 | 128 | stress_prefix *pr = _stress_prefixes.request_obj(this); 129 | if (pr) { 130 | pr->distance = rand() % 100; 131 | pr->metric = rand() % 10000; 132 | pr->nexthop = nh; 133 | pr->intf = 0; 134 | 135 | timeval ts, te; 136 | 137 | gettimeofday(&ts, 0); 138 | 139 | /* install the prefix with random metric */ 140 | g_mrd->mrib().install_prefix(p, pr); 141 | 142 | gettimeofday(&te, 0); 143 | 144 | uint32_t diff = (te.tv_sec - ts.tv_sec) * 1000000; 145 | if (te.tv_usec > ts.tv_usec) 146 | diff += te.tv_usec - ts.tv_usec; 147 | else 148 | diff += (1000000 + te.tv_usec - ts.tv_usec); 149 | 150 | accum += diff; 151 | } else { 152 | _stress_prefixes.return_obj(pr); 153 | g_mrd->log().info(QUIET) << "[STRESS] failed to add prefix " << p << endl; 154 | } 155 | 156 | /* keep hammering */ 157 | g_mrd->register_task(this, 0); 158 | } 159 | 160 | -------------------------------------------------------------------------------- /tools/c/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS ?= -g -O2 2 | CFLAGS += -Wall -ansi 3 | 4 | PREFIX ?= /usr/local 5 | 6 | -include ../../src/Makefile.options 7 | 8 | all: mrd6sh 9 | 10 | install: mrd6sh 11 | install -D mrd6sh $(DESTDIR)$(PREFIX)/bin/mrd6sh 12 | 13 | clean: 14 | rm -f mrd6sh 15 | 16 | -------------------------------------------------------------------------------- /tools/c/mrd6sh.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define MRD_SOCKET "/var/run/mrd6" 8 | 9 | int main(int argc, char *argv[]) { 10 | int i, sock; 11 | struct sockaddr_un addr; 12 | char buf[256]; 13 | int ptr; 14 | 15 | if (argc < 2) { 16 | printf("No command specified.\n"); 17 | return -1; 18 | } 19 | 20 | strcpy(buf, argv[1]); 21 | ptr = strlen(buf); 22 | 23 | for (i = 2; i < argc; i++) { 24 | if ((ptr + strlen(argv[i])) >= sizeof(buf)) { 25 | printf("Command is too long.\n"); 26 | return -1; 27 | } 28 | sprintf(buf + ptr, " %s", argv[i]); 29 | ptr += 1 + strlen(argv[i]); 30 | } 31 | 32 | buf[ptr] = 0; 33 | 34 | sock = socket(AF_UNIX, SOCK_STREAM, 0); 35 | if (sock < 0) { 36 | perror("socket()"); 37 | return -1; 38 | } 39 | 40 | memset(&addr, 0, sizeof(addr)); 41 | 42 | addr.sun_family = AF_UNIX; 43 | strcpy(addr.sun_path, MRD_SOCKET); 44 | 45 | if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { 46 | perror("connect()"); 47 | return -1; 48 | } 49 | 50 | if (send(sock, buf, ptr + 1, 0) < 0) { 51 | perror("send()"); 52 | return -1; 53 | } 54 | 55 | while ((i = recv(sock, buf, sizeof(buf), 0)) > 0) { 56 | buf[i] = 0; 57 | printf(buf); 58 | } 59 | 60 | return 0; 61 | } 62 | 63 | -------------------------------------------------------------------------------- /tools/mrd6sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | 3 | # by Marco d'Itri 4 | 5 | use strict; 6 | use IO::Socket::UNIX; 7 | 8 | my $MRD_SOCKET = '/var/run/mrd6'; 9 | 10 | if (@ARGV == 0) { 11 | print "No command specified.\n"; 12 | exit 1; 13 | } 14 | 15 | my $command = join(' ', @ARGV) . "\r\n"; 16 | 17 | my $sock = new IO::Socket::UNIX( 18 | Type => SOCK_STREAM, 19 | Peer => $MRD_SOCKET, 20 | ); 21 | 22 | if (not defined $sock) { 23 | print "Failed to connect to MRD6, is the router daemon running?\n"; 24 | exit 1; 25 | } 26 | 27 | print $sock $command or die "write: $!"; 28 | 29 | while (<$sock>) { 30 | print $_; 31 | } 32 | 33 | exit 0; 34 | --------------------------------------------------------------------------------