oor-1.2.0/000077500000000000000000000000001313612200500123025ustar00rootroot00000000000000oor-1.2.0/.gitignore000066400000000000000000000001101313612200500142620ustar00rootroot00000000000000android/bin android/gen android/obj Debug Release .cproject .project *o oor-1.2.0/AUTHORS000066400000000000000000000014521313612200500133540ustar00rootroot00000000000000We thank the following people for their contributions to the project. David Meyer Preethi Natarajan Vina Ermagan Chris White Albert Cabellos Lorand Jakab Albert Lopez Marc Portolés Pranathi Mamidi Alberto Rodriguez-Natal Vasileios Lakafosis Florin Coras Konrad Gawda Matthieu Coudron Rene Bartsch Michiel Blokzijl François Cachereul Lluís García Torres José Miguel Guzmán oor-1.2.0/FAQ.md000066400000000000000000000116511313612200500132370ustar00rootroot00000000000000Q: How can I be updated with the latest news from Open Overlay Router? A: Subscribe to annopunce@openoverlayrouter.org mailing list at http://mail.openoverlayrouter.org/mailman/listinfo Q: How can I contact Open Overlay Router team? A: You can send your question regarding general usage of Open Overlay Router to users@openoverlayrouter.org. For development question or suggestions you can use devel@openoverlayrouter.org. Those lists are open and anyone can subscribe at http://mail.openoverlayrouter.org/mailman/listinfoo. When possible use those mailing lists instead of sending mails directly to us. Q: What is LISP Beta-Network? How can I join? A: You will find all the information here: http://www.lisp4.net You can request joining the Beta-Network using the form on http://www.lisp4.net/beta-network/get-involved/. Q: I am using the Beta-Network, how can I check if I registered correctly? A: The real-time state of the Beta-Network can be check by anyone, look for your EID prefix here: http://www.lisp4.net/lisp-site/ Q: How can I enable different debug levels? A: Launch oor with the -d N option, being N the debug level you want. There are three debug levels, from 1 the less verbose to 3 the most. Level 1 or 2 should be enough for common debug. You can also use the configuration file to set the default debug level. Q: How can I check the incoming/outcoming packets on my system? A: Use a tool like Wireshark. You can listen on the physical interface(s) you are using to see encapsulated packets or listen on the oor TUN interface (oorTun0) to see packets before/after being encapsulated. TUN interface will only appear when Open Overlay Router is running. To look for LISP control or LISP data packets use 'lisp' and 'lisp-data' filters. Q: How can I send ad-hoc LISP Map-Request to the LISP Mapping-System? A: Use the 'lig' tool: https://github.com/LISPmob/lig Note that lig can not be used while Open Overlay Router is running. Q: I obtain no reply to any LISP packets. I see no reply to them in any interface. A: Check that there is no firewall blocking LISP packets. LISP uses UDP port 4341 for data and 4342 for control. Both ports must be open in any firewall on the path. Q: I obtain no reply to my traffic, however I can see how reply traffic is reaching the external physical interface A: Check that Reverse Path filtering is disabled. Add the following lines to /etc/sysctl.conf and reboot the system net.ipv4.conf.default.rp_filter=0 net.ipv4.conf.all.rp_filter=0 Q: My packets are not beeing forwarded A: Check that IP forwarding is enabled on your system. Add the following lines to /etc/sysctl.conf and reboot the system net.ipv4.ip_forward=1 net.ipv6.conf.all.forwarding=1 Q: The debug output shows this message, "forward_native: No output interface found". A: This doesn't mean that Open Overlay Router is not working properly. It just means that it has tried to send a packet natively and it has not found a suitable interface. This can happen, for instance, if you are using IPv4 EIDs with IPv4 only interfaces and your system is generating IPv6 packets Q: The debug output shows this message, "The entry X.X.X.X is not found in the data base" or this one, "X.X.X.X is not a local EID" A: This message appears only when an EID is not found on the local database (the one that stores the EIDs assigned to OOR xTR/MN). Before encapsulating a packet, Open Overlay Router checks if the source address is a local EID (looking into the local database and hence printing this debug message). This is done to avoid encapsulating packets which are not meant to. Like packets originated in the xTR itself and not in the EID subnet, or packets addressed to a host on the same subnet on MN operation. Q: The debug output shows this message, "CRIT: No default output interface. Exiting ..." A: Check that the interface name defined in the "database-mapping" in your config file matches the one you want to use as RLOC interface Q: I want to use multihoming in my OpenWRT router A: Most of OpenWRT routers doesn't have more than one wan interface. To enable multihoming support in your OpenWRT router, you should create a virtual interface to be used as a second WAN. You have to assign a different VLAN to each port you want to use as WAN. Check OpenWRT documentation to see how to configure VLANs in your router. Note that not all routers have support for VLANs, and the ports used in network configuration not always match physical ports. Check the OpenWRT wiki to find documentation on your specific router. Q: I am testing multihoming on OpenWRT using a virtual WAN interface and I see strange behaviour when I force up/down on the virtual interface. A: There is a known issue with virtual WAN interfaces on OpenWRT and Open Overlay Router. On normal operation you should not expect any issue, but if you force up/down on the interface Opne Overlay Router will not behave as it would do with a physical interface. We are looking into how to solve this. oor-1.2.0/LICENSE000066400000000000000000000261361313612200500133170ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.oor-1.2.0/Makefile000066400000000000000000000007351313612200500137470ustar00rootroot00000000000000DIRS = oor BUILDDIRS = $(DIRS:%=build-%) INSTALLDIRS = $(DIRS:%=install-%) CLEANDIRS = $(DIRS:%=clean-%) all: $(BUILDDIRS) $(DIRS): $(BUILDDIRS) $(BUILDDIRS): $(MAKE) -C $(@:build-%=%) install: $(INSTALLDIRS) all $(INSTALLDIRS): $(MAKE) -C $(@:install-%=%) install clean: $(CLEANDIRS) $(CLEANDIRS): $(MAKE) -C $(@:clean-%=%) clean .PHONY: subdirs $(DIRS) .PHONY: subdirs $(BUILDDIRS) .PHONY: subdirs $(INSTALLDIRS) .PHONY: subdirs $(CLEANDIRS) .PHONY: all install clean oor-1.2.0/README.android.md000066400000000000000000000060751313612200500152100ustar00rootroot00000000000000Android -------- Open Overlay Router includes support for Android devices operating as LISP mobile nodes (LISP-MN). There are two implementations of Open Overlay Router merged in a single application, for rooted devices and for non-rooted devices. The application automatically selects the implementation to run according to the features of the device. It is expected that in the future the version executed in rooted devices will provide features beyond those available on the non-root devices, however on the current version there is just one root-only feature, support for IPv6 RLOCs. In both editions, there is a limit of one single EID (IPv4 or IPv6) mapped to one or more RLOC interfaces. Even though several interfaces can be managed by Open Overlay Router at the same time, they can only be used in an active-backup fashion (no more than one interface used at once). Installation ------------ OOR requires a device with Android 4.0 or higher. Please note that due to a bug on Android 4.4.0 and onwards, OOR will not work properly in no rooted devices with Android 4.4.0, 4.4.1, 4.4.2 or 4.4.3. The bug was fixed on Android 4.4.4. To ease the installation process we strongly recommend installing OOR through Google Play (search for “open overlay router”), however you can also download a precompiled APK package file from the Open Overlay Router website or compile the app from sources yourself. In any case, if you choose to install OOR without using Google Play, the device must be configured to allow the installation of packages from "unknown sources" (System Settings -> Security -> Device Administration) To build Open Overlay Router for Android from source code we recomend you to use Android Studio with the Native Development Kit * Android Studio: [https://developer.android.com/studio/index.html] To get the latest version of the OOR source from Github: git clone git://github.com/OpenOverlayRouter/oor.git Import the android folder to Android Studio and select Build APK from the Build menu. To install the application, connect your device to the pc, select Run in the Run menu and select the device you want to install and run the application. Running Open Overlay Router --------------------------- Open Overlay Router Android application allows you to start and stop the oor daemon and edit the most important parameters of the configuration file. To access the full list of configurable parameters you have to edit manually the configuration file located in /sdcard/oor.conf. Manually edited parameters not present in the graphical configuration interface will be overwritten when using the graphical configuration editor. ** Once OOR is running, the source address of the generated traffic is your EID. It is possible that the DNS server used by your device doesn't reply to unknow addresses like your new EID. We are working to try to fix this problem in a new release.** Due to the large amount of data generated by the oor daemon, it is recommended to set "log level" to 0 when not debugging. oor-1.2.0/README.md000066400000000000000000000404471313612200500135720ustar00rootroot00000000000000Overview -------- The OpenOverlayRouter (OOR) project aims to deliver a flexible and modular open-source implementation to deploy programmable overlay networks. It leverages on encapsulating overlay-specific packets into underlay-compatible packets at the edges of the instantiated overlay and route them over the physical underlying infrastructure. In order to do so, it maps overlay identifiers to underlay locators and keeps those mappings updated over time. In the current version, OOR uses the LISP protocol for the control-plane (e.g. mapping retrieval and updating, etc), NETCONF/YANG for the management-plane (e.g. overlay identifiers provisioning, etc) and can use both LISP and VXLAN-GPE headers for encapsulation. Most of the OOR architecture revolves around the LISP protocol and its components, that we introduce briefly here. The Locator/ID Separation Protocol (LISP) is an IETF protocol (RFC6830) that decouples the semantics of identity and location on current IP addresses. It uses the concept of Endpoint IDentifiers (EIDs) to name hosts in edge networks, and Routing LOCators (RLOCs) for nodes in transit networks. EIDs and RLOCs are syntactically indistinguishable from current IPv4 and IPv6 addresses, enabling backwards compatibility with the existing Internet architecture. A distributed database, the Mapping System, is responsible for maintaining the associations between EIDs and RLOCs. LISP Mobile Node (LISP-MN) is a specification to enable fast host mobility using LISP. For convenience, OOR uses terminology borrowed from the LISP protocol and thus uses the term EID for the overlay identifiers and the term RLOC for the underlay locators. Regarding the LISP devices that OOR implements, currently it can operate as an xTR, MS/MR, RTR or LISP-MN. Nowadays, OOR runs on desktop Linux, OpenWRT home routers and Android devices. The current reference platform for OOR development is Ubuntu Server 14.04.5 LTS (Trusty Tahr), OpenWRT 15.05 (Chaos Calmer) and Android 4.3 (Jelly Bean). OOR can work together with the Vector Packet Processing (VPP) technology to obtain an xTR capable to reach bandwith close to the 10 GBps. To use VPP as the OOR dataplane, refears to the README.vpp.md. OpenOverlayRouter is a rename of the LISPmob.org project. Network Prerequisites --------------------- Running a Open Overlay Router device on the public Internet requires the following: xTR - MN * an EID from a Mapping Service Provider (MSP), * the RLOC of the Map-Server that will accept the registration of this EID, * an authentication token to register the EID with the Map-Server, * the RLOC of a Map-Resolver, * the RLOC of a Proxy-ETR, * a publicly routable RLOC for the device running OOR, which is neither firewalled, nor behind NAT (see however "NAT traversal" section for details on this). RTR * the RLOC of a Map-Resolver, * a publicly routable RLOC for the device running OOR, which is neither firewalled, nor behind NAT. MS/MR * a publicly routable RLOC for the device running OOR, which is neither firewalled, nor behind NAT. The above information is used for configuring 'oor' via the configuration file 'oor.conf'. See section "OpenWRT" for OpenWRT configuration details and "Android" for Android configuration details. Visit http://www.lisp4.net/ for more info on the deployment status of the LISP beta-network and how you can join the testbed. Software Prerequisites ---------------------- To build Open Overlay Router for a standard Linux, you will need: * a Linux hosts * a C compiler (tested with `gcc`) * GNU make * git, unless you use a tarball * libConfuse * gengetopt * libcap v2+ * libzmq v3 * libxml2 On Debian-derived Linux distributions (including Ubuntu), installing the following packages will provide all necessary dependencies: * 'build-essential' * 'git-core' * 'libconfuse-dev' * 'gengetopt' * 'libcap2-bin' * 'libzmq3-dev' * 'libxml2-dev' The latest version of the Open Overlay Router source code can be obtained from Github: git clone git://github.com/OpenOverlayRouter/oor.git Installation ------------ To build the code for Linux operating run the following in the top-level directory: make To install it in `/usr/local/sbin`, run sudo make install To build the code for OpenWRT you will need the OpenWRT official SDK. However, for your convenience, we encourage you to install the precompiled .ipk, from our website. Check section "OpenWRT" for details. Running Open Overlay Router --------------------------- Once the code is successfully installed on the device, `oor.conf.example` should be copied to `/etc/oor.conf` and edited with the proper values. Again, see section 'OpenWRT' for OpenWRT details about this. Additionally the device's interface used for physical network connectivity (such as 'eth0', 'wlan0' or 'ppp0') must also be specified in the configuration file. Prior to execute Open Overlay Router, make sure that each external interface (such as 'wan0') has defined a default route with different 'metric' in the routing table (there is a 'default' entry for each outgoing interface). In most cases, this is auto-configured by the operating system during start-up. Check that sysctl options configuration is correct. Make sure that rp_filter kernel network parameter is disabled. It is disabled by default in OpenWRT, but, for instance, it is enabled by default in Ubuntu. Make sure too that IP forwarding is enabled. It should be enabled by default in OpenWRT. You can instruct your system to auto-configure these values during system boot-up if you add the following lines to `/etc/sysctl.conf`. Remember to reboot your system after adding these lines. net.ipv4.conf.default.rp_filter=0 net.ipv4.conf.all.rp_filter=0 net.ipv4.ip_forward=1 net.ipv6.conf.all.forwarding=1 The user space daemon can be started by a non privileged user with the appropriate permissions (particularly CAP_NET_ADMIN and CAP_NET_RAW). Such user can run the daemon with: oor -f /etc/oor.conf It will set up networking and register to the mapping system, after which you can enjoy all the benefits of LISP. Features -------- This is the list of supported features at this moment * xTR / MN - Register to the Mapping System - Request mappings - Reply to mapping requests - Encapsulate data packets (LISP and VXLAN-GPE) - Decapsulate data packets (LISP and VXLAN-GPE) - RLOC Probing (user configurable) - IPv6 full support (EIDs and RLOCs) - Interface management - Multihoming - Experimental NAT traversal - Explicit Locator Path (ELPs) - Instance ID / VNI support - NETCONF/YANG configurable - VPP support (only for IPv4 RLOCs) * RTR - Request mappings - Reply to mapping requests - Reencapsulate data packets (LISP and VXLAN-GPE) - RLOC Probing (user configurable) - IPv6 full support (EIDs and RLOCs) - Interface management - Multihoming - Explicit Locator Path (ELPs) - Instance ID / VNI support * MS / MR - Process registration requests - Notify correct registration - Accept more specific entries - Reply to mapping requests when Proxy Relpy activated - Forward requests to xTRs - IPv6 full support (EIDs and RLOCs) - Interface management - Explicit Locator Path (ELPs) - Instance ID support Note: OOR doesn't support overlapping local prefixes with different IIDs when operating as a XTR or MN. Mobile Node mode (MN) --------------------- When 'oor' is running in MN mode, the EID obtained configured is associated to the 'lispTun0' virtual interface. Two /1 routes covering the full IP addresses space should appear in the routing table. These routes should be pointing to 'lispTun0' device. The following lines show an example of how 'ip addr' and 'ip route' will look like with IPv4, expect a similar output with IPv6: $ ip addr 1: lo: mtu 16436 qdisc noqueue state UNKNOWN link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever 2: eth0: mtu 1500 qdisc pfifo_fast state UP qlen 1000 link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff inet brd scope global eth0 valid_lft forever preferred_lft forever 3: lispTun0: mtu 1450 qdisc pfifo_fast state UNKNOWN qlen 500 link/none inet scope host lispTun0 $ ip route dev eth0 proto kernel scope link src 169.254.0.0/16 dev eth0 scope link metric 1000 0.0.0.0/1 dev lispTun0 128.0.0.0/1 dev lispTun0 default via dev eth0 metric 100 xTR mode -------- To configure Open Overlay Router to use it on xTR mode take into account the following considerations. An EID /30 (at least) prefix is required for IPv4 EIDs. For IPv6 you should have a /126 (at least). This prefix should be used as the network prefix for the subnet where the hosts on the EID space connected to the router are allocated. Assign the EID to an interface on the router and configure it as you would do for a normal network prefix (static configuration, DHCP, etc...). No EID is used for the 'lispTun0' interface in router mode (a local address is automatically used by OOR instead). The following lines show an example of how 'ip addr' and 'ip route' will look like with IPv4, expect a similar output with IPv6: $ ip addr 1: lo: mtu 16436 qdisc noqueue state UNKNOWN link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever 2: eth0: mtu 1500 qdisc pfifo_fast state UP qlen 1000 link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff inet brd scope global eth0 valid_lft forever preferred_lft forever 3: eth1: mtu 1500 qdisc pfifo_fast state UP qlen 1000 link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff inet brd scope global eth0 valid_lft forever preferred_lft forever 4: eth2: mtu 1500 qdisc pfifo_fast state UP qlen 1000 link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff inet brd scope global eth0 valid_lft forever preferred_lft forever 5: lispTun0: mtu 1440 qdisc pfifo_fast state UNKNOWN qlen 500 link/none $ ip route dev eth0 proto kernel scope link src dev eth1 proto kernel scope link src dev eth2 proto kernel scope link src default via dev eth0 metric 100 $ ip rule 0: from all lookup local x: from lookup x 99: from all to lookup main 99: from all to lookup main 100: from lookup 100 100: from lookup 100 32766: from all lookup main 32767: from all lookup default This output is only valid when OOR is not compiled to work with VPP. RTR mode -------- When running in RTR mode, Open Overlay Router serves as a Re-encapsulating Tunnel Router that decapsulates the received traffic to reencapsulate it again towards the next hop. To configure an RTR, select the corresponding operating-mode and fill the parameters of the RTR section and Tunnel Router general configuration of the configuration file The following lines show an example of how 'ip addr' and 'ip route' will look like with IPv4, expect a similar output with IPv6: $ ip addr 1: lo: mtu 16436 qdisc noqueue state UNKNOWN link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever 2: eth0: mtu 1500 qdisc pfifo_fast state UP qlen 1000 link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff inet brd scope global eth0 valid_lft forever preferred_lft forever 3: eth1: mtu 1500 qdisc pfifo_fast state UP qlen 1000 link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff inet brd scope global eth0 valid_lft forever preferred_lft forever 4: lispTun0: mtu 1440 qdisc pfifo_fast state UNKNOWN qlen 500 link/none $ ip route dev eth0 proto kernel scope link src dev eth1 proto kernel scope link src default via dev eth0 metric 100 default via dev eth1 metric 110 $ ip rule 0: from all lookup local x: from lookup x y: from lookup y 32766: from all lookup main 32767: from all lookup default MS/MR mode ---------- Open Overlay Router can be configured as a basic MS/MR where configured EID prefixes can be registered by xTRs. OOR will also reply to MapRequests addressed to those prefixes. To configure Open Overlay Router as a MS/MR, select the corresponding operating-mode and fill the parameters of the MS section of the configuration file. OpenWRT ------- To enable OpenWRT configuration mode and the specific routing operations, the code should have been compiled with the `platform=openwrt` option during OpenWRT package creation. Please note that the best way to get Open Overlay Router on OpenWRT is get a precompiled binary (either the full system or just the Open Overlay Router package) from the github website (https://github.com/OpenOverlayRouter/oor/wiki/Downloads). In OpenWRT, the configuration is performed through the OpenWRT standard configuration tool UCI, instead of using 'oor.conf' file. Configure the UCI file manually in '/etc/config/oor' (by default), use the UCI CLI application, or use the web interface (if available). The configuration fields are analogue to those in the 'oor.conf' file. Android ------- Open Overlay Router includes support for Android devices operating as LISP-MN. Please see the README.android.md file to get details on Open Overlay Router for Android installation, compilation and usage. VPP --- Open Overlay Router has adopted VPP as a new data plane that can be used to encapsulate and decapsulate LISP traffic in a high performance rate. Please see the README.vpp.md file to get details on how to configure OOR and VPP to work together. NAT traversal ------------- Since version 1.1, Open Overlay Router includes experimental NAT traversal capabilities for the modalities of xTR and MN (see LISP NAT traversal draft). In order to use NAT traversal with Open Overlay Router you will need a MS and an RTR (Re-encapsulating Tunnel Router) that are NAT traversal capable. If you are using the beta-network, please take into account that, at the time of this writing (release 1.1), not all devices on the beta-network have been updated to support NAT traversal yet. If NAT traversal feature is enabled, Open Overlay Router is configured to send all data traffic through RTRs even if the interface has a public address. On its current form, NAT traversal support on Open Overlay Router ignores IPv6 addresses on RLOC interfaces, besides, the current NAT traversal implementation in the beta-network only supports the registration of a single EID prefix per device. Contact ------- Should you have questions regarding the use of the Open Overlay Router distribution, please subscribe to the users@openoverlayrouter.org mailing list and ask there (http://mail.openoverlayrouter.org/mailman/listinfo/users). If you wish to participate in the development of Open Overlay Router, use the dedicated mailing list, devel@openoverlayrouter.org (http://mail.openoverlayrouter.org/mailman/listinfo/devel). Additionally, important announcements are sent to the low volume mailing list announce@openoverlayrouter.org (http://mail.openoverlayrouter.org/mailman/listinfo/announce). More interactive help can sometimes be obtained on the '#openoverlayrouter' IRC channel on FreeNode. Bugs you encounter should be filed at the [repository's issue tracker on Github](https://github.com/OpenOverlayRouter/oor/issues). oor-1.2.0/README.vpp.md000066400000000000000000000057111313612200500143710ustar00rootroot00000000000000VPP --- VPP is the open source version of Cisco's Vector Packet Processing (VPP) technology: a high performance, packet-processing stack that can run on commodity CPUs. Open Overlay Router has adopted VPP as an alternative data plane to kernel networking stack that can be used to encapsulate and decapsulate LISP traffic in a high performance rate close to 10 Gbps. The current integration of OOR with VPP is only supported for linux devices with network cards with DPDK support. It is limited to OOR configured as an xTR using only IPv4 RLOCs and a single default route. Installation ------------ To take advantage of VPP you will have to compile and configure it previously. If you already have installed VPP, notice that we apply a patch to the src code of VPP and more exactly to a specific commit of VPP. Without applying this patch, the integration between VPP and OOR will not work. Download the VPP code: git clone https://gerrit.fd.io/r/vpp --branch stable/1704 cd vpp git reset --hard e3b7ad7adebf25af1651a217da8534ada89c369b Patch the code before compiling: cp /VPP/vpp.patch . git apply vpp.patch Install dependecies: sudo make install-dep sudo apt-get install python-cffi python-ply python-pycparser Finally, we compile and install VPP: cd build-root ./bootstrap.sh make V=0 PLATFORM=vpp TAG=vpp install-deb sudo dpkg -i *.deb OOR compilation. Read previously the README.md file cd /oor/ make platform=vpp sudo make install Add the OOR VPP plugins: cd /VPP/oor_ctrl-plugin autoreconf -fis ./configure && make && sudo make install cd /VPP/oor_pkt_miss-plugin autoreconf -fis ./configure && make && sudo make install Configuration ------------- Here we provide you some basic instructions to configure VPP. If you want more details about VPP or how to configure it, check the wiki page of the project To assign an interface to VPP, check it is not up/configured by the Linux Kernel. If it is then shut it down: For e.g. If you want to use eth1 in vpp then: sudo ifconfig eth1 down sudo ip addr flush dev eth1 == Notice that the current version of VPP is only a traffic forwarder. Don't assign to VPP the management interface of the PC. == Start VPP: sudo service vpp start List the interfaces assigned to VPP: vppctl show interface Configure VPP interfaces: Assign an address to the interface: sudo vppctl set int ip address [del] Set status of the interface to up: sudo vppctl set int state up|down Show the interfaces addresses: vppctl show int addr If you want to use IID different to 0 (only works with local networks), you will have to do a previous step before configuring the interface associated with the EIDs: sudo vppctl set interface ip|ip6 table Once you have configured vpp you can start to use OOR. oor-1.2.0/VPP/000077500000000000000000000000001313612200500127475ustar00rootroot00000000000000oor-1.2.0/VPP/oor_ctrl-plugin/000077500000000000000000000000001313612200500160665ustar00rootroot00000000000000oor-1.2.0/VPP/oor_ctrl-plugin/Makefile.am000066400000000000000000000033671313612200500201330ustar00rootroot00000000000000# Copyright (c) 2015 Cisco and/or its affiliates. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. AUTOMAKE_OPTIONS = foreign subdir-objects AM_CFLAGS = -Wall -I${top_srcdir} -I${top_builddir} -lzmq AM_LDFLAGS = -module -shared -avoid-version AM_LIBTOOLFLAGS = --quiet SUFFIXES = .api.h .api .api.json API_FILES = BUILT_SOURCES = vppplugins_LTLIBRARIES = vppapitestplugins_LTLIBRARIES = noinst_HEADERS = nobase_apiinclude_HEADERS = ACLOCAL_AMFLAGS = -I m4 vppapitestpluginsdir = ${libdir}/vpp_api_test_plugins vpppluginsdir = ${libdir}/vpp_plugins include oor_ctrl.am %.api.h: %.api mkdir -p `dirname $@` ; \ $(CC) $(CPPFLAGS) -E -P -C -x c $^ \ | vppapigen --input - --output $@ --show-name $@ %.api.json: %.api @echo " JSON APIGEN " $@ ; \ mkdir -p `dirname $@` ; \ $(CC) $(CPPFLAGS) -E -P -C -x c $^ \ | vppapigen --input - --json $@ apidir = $(prefix)/api/plugins apiincludedir = ${includedir}/vpp_plugins api_DATA = \ $(patsubst %.api,%.api.json,$(API_FILES)) BUILT_SOURCES += \ $(patsubst %.api,%.api.h,$(API_FILES)) # Remove *.la files install-data-hook: @(cd $(vpppluginsdir) && $(RM) $(vppplugins_LTLIBRARIES)) @(cd $(vppapitestpluginsdir) && $(RM) $(vppapitestplugins_LTLIBRARIES)) CLEANFILES = $(BUILT_SOURCES) oor-1.2.0/VPP/oor_ctrl-plugin/configure.ac000066400000000000000000000002461313612200500203560ustar00rootroot00000000000000AC_INIT(oor_ctrl_plugin, 1.0) LT_INIT AM_INIT_AUTOMAKE AM_SILENT_RULES([yes]) AC_PREFIX_DEFAULT([/usr]) AC_PROG_CC AC_OUTPUT([Makefile]) AC_CONFIG_MACRO_DIR([m4]) oor-1.2.0/VPP/oor_ctrl-plugin/oor_ctrl.am000066400000000000000000000022011313612200500202230ustar00rootroot00000000000000# Copyright (c) 2016 Cisco and/or its affiliates. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. vppapitestplugins_LTLIBRARIES += oor_ctrl_test_plugin.la vppplugins_LTLIBRARIES += oor_ctrl_plugin.la oor_ctrl_plugin_la_SOURCES = \ oor_ctrl/oor_ctrl.c \ oor_ctrl/node.c \ oor_ctrl/oor_ctrl_plugin.api.h API_FILES += oor_ctrl/oor_ctrl.api nobase_apiinclude_HEADERS += \ oor_ctrl/oor_ctrl_all_api_h.h \ oor_ctrl/oor_ctrl_msg_enum.h \ oor_ctrl/oor_ctrl.api.h oor_ctrl_test_plugin_la_SOURCES = oor_ctrl/oor_ctrl_test.c oor_ctrl/oor_ctrl_plugin.api.h # vi:syntax=automakeoor-1.2.0/VPP/oor_ctrl-plugin/oor_ctrl/000077500000000000000000000000001313612200500177115ustar00rootroot00000000000000oor-1.2.0/VPP/oor_ctrl-plugin/oor_ctrl/node.c000066400000000000000000000125671313612200500210150ustar00rootroot00000000000000 /* * node.c - skeleton vpp engine plug-in dual-loop node skeleton * * Copyright (c) * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include typedef struct { u32 next_index; u32 sw_if_index; } oor_ctrl_trace_t; /* packet trace format function */ static u8 * format_oor_ctrl_trace (u8 * s, va_list * args) { CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); oor_ctrl_trace_t * t = va_arg (*args, oor_ctrl_trace_t *); s = format (s, "OOR_CTRL: sw_if_index %d, next index %d", t->sw_if_index, t->next_index); return s; } vlib_node_registration_t oor_ctrl_ipv4_node; vlib_node_registration_t oor_ctrl_ipv6_node; #define foreach_oor_ctrl_error \ _(LISPD, "LISP control packets processed") typedef enum { #define _(sym,str) OOR_CTRL_ERROR_##sym, foreach_oor_ctrl_error #undef _ OOR_CTRL_N_ERROR, } oor_ctrl_error_t; static char * oor_ctrl_error_strings[] = { #define _(sym,string) string, foreach_oor_ctrl_error #undef _ }; typedef enum { OOR_CTRL_NEXT_INTERFACE_OUTPUT, OOR_CTRL_N_NEXT, } oor_ctrl_next_t; static uword oor_ctrl_ipv4_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) { u32 n_left_from, * from, * to_next; u32 pkts_swapped = 0; oor_ctrl_main_t *sm = &oor_ctrl_main; from = vlib_frame_vector_args (frame); n_left_from = frame->n_vectors; while (n_left_from > 0) { u32 n_left_to_next_drop; vlib_get_next_frame (vm, node, OOR_CTRL_NEXT_INTERFACE_OUTPUT, to_next, n_left_to_next_drop); while (n_left_from > 0 && n_left_to_next_drop > 0) { u32 bi0; vlib_buffer_t * b0; bi0 = from[0]; from += 1; n_left_from -= 1; to_next[0] = bi0; to_next += 1; n_left_to_next_drop -= 1; b0 = vlib_get_buffer (vm, bi0); vlib_buffer_advance (b0, -(word) (sizeof(udp_header_t)+ sizeof(ip4_header_t) + sizeof(ethernet_header_t))); vnet_buffer(b0)->sw_if_index[VLIB_TX] = sm->sw_if_index; if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) { } } vlib_put_next_frame (vm, node, OOR_CTRL_NEXT_INTERFACE_OUTPUT, n_left_to_next_drop); } vlib_node_increment_counter (vm, oor_ctrl_ipv4_node.index, OOR_CTRL_ERROR_LISPD, pkts_swapped); return frame->n_vectors; } VLIB_REGISTER_NODE (oor_ctrl_ipv4_node) = { .function = oor_ctrl_ipv4_node_fn, .name = "oor_ctrl_ipv4_node", .vector_size = sizeof (u32), .format_trace = format_oor_ctrl_trace, .type = VLIB_NODE_TYPE_INTERNAL, .n_errors = ARRAY_LEN(oor_ctrl_error_strings), .error_strings = oor_ctrl_error_strings, .n_next_nodes = OOR_CTRL_N_NEXT, /* edit / add dispositions here */ .next_nodes = { [OOR_CTRL_NEXT_INTERFACE_OUTPUT] = "interface-output", }, }; static uword oor_ctrl_ipv6_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) { u32 n_left_from, * from, * to_next; u32 pkts_swapped = 0; oor_ctrl_main_t *sm = &oor_ctrl_main; from = vlib_frame_vector_args (frame); n_left_from = frame->n_vectors; while (n_left_from > 0) { u32 n_left_to_next_drop; vlib_get_next_frame (vm, node, OOR_CTRL_NEXT_INTERFACE_OUTPUT, to_next, n_left_to_next_drop); while (n_left_from > 0 && n_left_to_next_drop > 0) { u32 bi0; vlib_buffer_t * b0; bi0 = from[0]; from += 1; n_left_from -= 1; to_next[0] = bi0; to_next += 1; n_left_to_next_drop -= 1; b0 = vlib_get_buffer (vm, bi0); vlib_buffer_advance (b0, -(word) (sizeof(udp_header_t)+ sizeof(ip6_header_t) + sizeof(ethernet_header_t))); vnet_buffer(b0)->sw_if_index[VLIB_TX] = sm->sw_if_index; if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) { } } vlib_put_next_frame (vm, node, OOR_CTRL_NEXT_INTERFACE_OUTPUT, n_left_to_next_drop); } vlib_node_increment_counter (vm, oor_ctrl_ipv6_node.index, OOR_CTRL_ERROR_LISPD, pkts_swapped); return frame->n_vectors; } VLIB_REGISTER_NODE (oor_ctrl_ipv6_node) = { .function = oor_ctrl_ipv6_node_fn, .name = "oor_ctrl_ipv6_node", .vector_size = sizeof (u32), .format_trace = format_oor_ctrl_trace, .type = VLIB_NODE_TYPE_INTERNAL, .n_errors = ARRAY_LEN(oor_ctrl_error_strings), .error_strings = oor_ctrl_error_strings, .n_next_nodes = OOR_CTRL_N_NEXT, /* edit / add dispositions here */ .next_nodes = { [OOR_CTRL_NEXT_INTERFACE_OUTPUT] = "interface-output", }, }; oor-1.2.0/VPP/oor_ctrl-plugin/oor_ctrl/oor_ctrl.api000066400000000000000000000010341313612200500222250ustar00rootroot00000000000000 /* Define a simple enable-disable binary API to control the feature */ define oor_ctrl_enable_disable { /* Client identifier, set from api_main.my_client_index */ u32 client_index; /* Arbitrary context, so client can match reply to request */ u32 context; /* Enable / disable the feature */ u8 enable_disable; /* Interface handle */ u8 host_if_name[64]; }; define oor_ctrl_enable_disable_reply { /* From the request */ u32 context; /* Return value, zero means all OK */ i32 retval; }; oor-1.2.0/VPP/oor_ctrl-plugin/oor_ctrl/oor_ctrl.c000066400000000000000000000336611313612200500217110ustar00rootroot00000000000000 /* * oor_ctrl.c - skeleton vpp engine plug-in * * Copyright (c) * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include #include #include #include #include #include /* define message IDs */ #include /* define message structures */ #define vl_typedefs #include #undef vl_typedefs /* define generated endian-swappers */ #define vl_endianfun #include #undef vl_endianfun /* instantiate all the print functions we know about */ #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__) #define vl_printfun #include #undef vl_printfun /* Get the API version number */ #define vl_api_version(n,v) static u32 api_version=(v); #include #undef vl_api_version #define REPLY_MSG_ID_BASE sm->msg_id_base #include static clib_error_t * oor_link_up_down_function (vnet_main_t * vm, u32 hw_if_index, u32 flags); static clib_error_t * oor_admin_up_down_function (vnet_main_t * vm, u32 sw_if_index, u32 flags); void oor_ip4_add_del_interface_address (ip4_main_t * im, uword opaque, u32 sw_if_index, ip4_address_t * address, u32 address_length, u32 if_address_index, u32 is_delete); void oor_ip6_add_del_interface_address (ip6_main_t * im, uword opaque, u32 sw_if_index, ip6_address_t * address, u32 address_length, u32 if_address_index, u32 is_delete); /* List of message types that this plugin understands */ #define foreach_oor_ctrl_plugin_api_msg \ _(OOR_CTRL_ENABLE_DISABLE, oor_ctrl_enable_disable) /* *INDENT-OFF* */ VLIB_PLUGIN_REGISTER () = { .version = OOR_CTRL_PLUGIN_BUILD_VER, .description = "OOR Ctrl plugin", }; /* *INDENT-ON* */ /* Action function shared between message handler and debug CLI */ int oor_ctrl_enable_disable (oor_ctrl_main_t * sm, u8 * host_if_name, int enable_disable) { u8 hwaddr[6] = {0,0,0,0,0,0}; vnet_sw_interface_t *si; u32 sw_if_index = ~0; u16 flags; int rv; clib_warning("OOR_CTRL: %s node", enable_disable ? "enable" : "disale"); if (enable_disable){ /* Create host-interface */ rv = af_packet_create_if (sm->vlib_main, host_if_name, hwaddr, &sw_if_index); if (rv != 0 && rv != VNET_API_ERROR_SUBIF_ALREADY_EXISTS){ return (VNET_API_ERROR_INVALID_INTERFACE); } /* Set interface status to UP */ flags = VNET_SW_INTERFACE_FLAG_ADMIN_UP; vnet_sw_interface_set_flags (sm->vnet_main, sw_if_index, flags); /* Set interface to unnumbered */ si = vnet_get_sw_interface (sm->vnet_main, sw_if_index); si->flags |= VNET_SW_INTERFACE_FLAG_UNNUMBERED; si->unnumbered_sw_if_index = sw_if_index; ip4_sw_interface_enable_disable (sw_if_index, 1); ip6_sw_interface_enable_disable (sw_if_index, 1); /* Indicate plagin where to write received packets */ sm->sw_if_index = sw_if_index; // LISP GPE is enabled in the pkt miss plugin }else { /* Remove unnumbered interface*/ si = vnet_get_sw_interface (sm->vnet_main, sm->sw_if_index); si->flags &= ~(VNET_SW_INTERFACE_FLAG_UNNUMBERED); si->unnumbered_sw_if_index = (u32) ~ 0; ip4_sw_interface_enable_disable (sm->sw_if_index, 0); ip6_sw_interface_enable_disable (sm->sw_if_index, 0); /* Disable host-interface to send control packets to oor */ sm->sw_if_index = ~0; /* Remove host interfaces */ af_packet_delete_if (sm->vlib_main, host_if_name); } return 0; } static clib_error_t * oor_ctrl_enable_disable_command_fn (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) { oor_ctrl_main_t * sm = &oor_ctrl_main; u8 *host_if_name = NULL; int enable_disable = 1; int rv; while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { if (unformat (input, "disable")){ enable_disable = 0; }else if (unformat (input, "%s", &host_if_name)){ ; }else{ break; } } if (host_if_name == NULL){ return clib_error_return (0, "Please specify an interface..."); } rv = oor_ctrl_enable_disable (sm, host_if_name, enable_disable); switch(rv) { case 0: break; case VNET_API_ERROR_INVALID_SW_IF_INDEX: return clib_error_return (0, "Invalid interface, only works on physical ports"); break; case VNET_API_ERROR_UNIMPLEMENTED: return clib_error_return (0, "Device driver doesn't support redirection"); break; default: return clib_error_return (0, "oor_ctrl_enable_disable returned %d", rv); } return 0; } VLIB_CLI_COMMAND (oor_ctrl_enable_disable_command, static) = { .path = "oor_ctrl enable-disable", .short_help ="oor_ctrl enable-disable [disable]", .function = oor_ctrl_enable_disable_command_fn, }; /* API message handler */ static void vl_api_oor_ctrl_enable_disable_t_handler (vl_api_oor_ctrl_enable_disable_t * mp) { vl_api_oor_ctrl_enable_disable_reply_t * rmp; oor_ctrl_main_t * sm = &oor_ctrl_main; u8 *host_if_name = NULL; int rv; host_if_name = format (0, "%s", mp->host_if_name); vec_add1 (host_if_name, 0); rv = oor_ctrl_enable_disable (sm, host_if_name,(int) (mp->enable_disable)); vec_free (host_if_name); REPLY_MACRO(VL_API_OOR_CTRL_ENABLE_DISABLE_REPLY); } /* Set up the API message handling tables */ static clib_error_t * oor_ctrl_plugin_api_hookup (vlib_main_t *vm) { oor_ctrl_main_t * sm = &oor_ctrl_main; #define _(N,n) \ vl_msg_api_set_handlers((VL_API_##N + sm->msg_id_base), \ #n, \ vl_api_##n##_t_handler, \ vl_noop_handler, \ vl_api_##n##_t_endian, \ vl_api_##n##_t_print, \ sizeof(vl_api_##n##_t), 1); foreach_oor_ctrl_plugin_api_msg; #undef _ return 0; } #define vl_msg_name_crc_list #include #undef vl_msg_name_crc_list static void setup_message_id_table (oor_ctrl_main_t * sm, api_main_t *am) { #define _(id,n,crc) \ vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id + sm->msg_id_base); foreach_vl_msg_name_crc_oor_ctrl; #undef _ } static clib_error_t * oor_ctrl_init (vlib_main_t * vm) { oor_ctrl_main_t * sm = &oor_ctrl_main; clib_error_t * error = 0; ip4_add_del_interface_address_callback_t cb4; ip6_add_del_interface_address_callback_t cb6; ip4_main_t * im4 = &ip4_main; ip6_main_t * im6 = &ip6_main; u8 * name; sm->vnet_main = vnet_get_main (); sm->sw_if_index = ~0; name = format (0, "oor_ctrl_%08x%c", api_version, 0); /* Ask for a correctly-sized block of API message decode slots */ sm->msg_id_base = vl_msg_api_get_msg_ids ((char *) name, VL_MSG_FIRST_AVAILABLE); error = oor_ctrl_plugin_api_hookup (vm); /* Add our API messages to the global name_crc hash table */ setup_message_id_table (sm, &api_main); vec_free(name); udp_register_dst_port (vm, UDP_DST_PORT_lisp_cp, oor_ctrl_ipv4_node.index, 1 /* is_ip4 */); udp_register_dst_port (vm, UDP_DST_PORT_lisp_cp, oor_ctrl_ipv6_node.index, 0 /* is_ip4 */); /* Register call back function of change of address */ cb4.function = oor_ip4_add_del_interface_address; cb4.function_opaque = 0; vec_add1 (im4->add_del_interface_address_callbacks, cb4); cb6.function = oor_ip6_add_del_interface_address; cb6.function_opaque = 0; vec_add1 (im6->add_del_interface_address_callbacks, cb6); return error; } VLIB_INIT_FUNCTION (oor_ctrl_init); /**** NETLINK notification functions ****/ VNET_HW_INTERFACE_LINK_UP_DOWN_FUNCTION (oor_link_up_down_function); static clib_error_t * oor_link_up_down_function (vnet_main_t * vm, u32 hw_if_index, u32 flags) { // vpe_api_main_t *vam = &vpe_api_main; // vnet_hw_interface_t *hi = vnet_get_hw_interface (vm, hw_if_index); // // if (vam->link_state_process_up) // vlib_process_signal_event (vam->vlib_main, // link_state_process_node.index, // API_LINK_STATE_EVENT, hi->sw_if_index); clib_warning("=> oor_link_up_down_function: Link %s", (flags == 1 ? "up" : "down")); return 0; } VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION (oor_admin_up_down_function); static clib_error_t * oor_admin_up_down_function (vnet_main_t * vm, u32 sw_if_index, u32 flags) { u8 sndbuf[1024]; vpp_nl_msg *vpp_msg_h; vpp_nl_link_info *vpp_link_info; int nbytes, error; clib_warning("=> oor_admin_up_down_function: Link %s", (flags == 1 ? "up" : "down")); if (oor_ctrl_main.sw_if_index != ~0){ void *zmq_context = zmq_ctx_new(); void *zmq_sock = zmq_socket(zmq_context, ZMQ_PUSH); error = zmq_connect(zmq_sock, OOR_IPC_FILE); if (error != 0){ clib_warning("oor_admin_up_down_function: Coudn't create ZMQ socket: %s",zmq_strerror (error)); return (0); } memset(sndbuf, 0, 1024); vpp_msg_h = (vpp_nl_msg *)sndbuf; vpp_link_info = (vpp_nl_link_info *)(sndbuf + sizeof(vpp_nl_msg)); if (flags == 1){ vpp_msg_h->type = VPP_NEWLINK; }else{ vpp_msg_h->type = VPP_DELLINK; } vpp_msg_h->len = sizeof(vpp_nl_msg) + sizeof(vpp_nl_link_info); vpp_link_info->ifi_index = sw_if_index; nbytes = zmq_send(zmq_sock,(void *)&sndbuf,vpp_msg_h->len,0); if (nbytes == -1){ clib_warning("oor_admin_up_down_function: Error while ZMQ sending: %s",zmq_strerror (error)); } zmq_close (zmq_sock); zmq_ctx_destroy (zmq_context); } return 0; } void oor_ip4_add_del_interface_address (ip4_main_t * im, uword opaque, u32 sw_if_index, ip4_address_t * address, u32 address_length, u32 if_address_index, u32 is_delete) { u8 sndbuf[1024]; vpp_nl_msg *vpp_msg_h; vpp_nl_addr_info *vpp_addr_info; int nbytes, error; clib_warning("============>>>>> NEW ADDRESS"); if (oor_ctrl_main.sw_if_index != ~0){ void *zmq_context = zmq_ctx_new(); void *zmq_sock = zmq_socket(zmq_context, ZMQ_PUSH); error = zmq_connect(zmq_sock, OOR_IPC_FILE); if (error != 0){ clib_warning("oor_ip4_add_del_interface_address: Coudn't create ZMQ socket: %s",zmq_strerror (error)); return; } memset(sndbuf, 0, 1024); vpp_msg_h = (vpp_nl_msg *)sndbuf; vpp_addr_info = (vpp_nl_addr_info *)(sndbuf + sizeof(vpp_nl_msg)); if (is_delete == 1){ vpp_msg_h->type = VPP_DELADDR; }else{ vpp_msg_h->type = VPP_NEWADDR; } vpp_msg_h->len = sizeof(vpp_nl_msg) + sizeof(vpp_nl_addr_info) + sizeof (ip4_address_t); vpp_addr_info->ifa_family = AF_INET; vpp_addr_info->ifa_prefixlen = address_length; vpp_addr_info->ifa_index = sw_if_index; memcpy(sndbuf + sizeof(vpp_nl_msg) + sizeof(vpp_nl_addr_info), (u8 *)address, sizeof (ip4_address_t)); nbytes = zmq_send(zmq_sock,(void *)&sndbuf,vpp_msg_h->len,0); if (nbytes == -1){ clib_warning("oor_ip4_add_del_interface_address: Error while ZMQ sending: %s",zmq_strerror (error)); } zmq_close (zmq_sock); zmq_ctx_destroy (zmq_context); } return; } void oor_ip6_add_del_interface_address (ip6_main_t * im, uword opaque, u32 sw_if_index, ip6_address_t * address, u32 address_length, u32 if_address_index, u32 is_delete) { u8 sndbuf[1024]; vpp_nl_msg *vpp_msg_h; vpp_nl_addr_info *vpp_addr_info; int nbytes, error; if (oor_ctrl_main.sw_if_index != ~0){ void *zmq_context = zmq_ctx_new(); void *zmq_sock = zmq_socket(zmq_context, ZMQ_PUSH); error = zmq_connect(zmq_sock, OOR_IPC_FILE); if (error != 0){ clib_warning("oor_ip4_add_del_interface_address: Coudn't create ZMQ socket: %s",zmq_strerror (error)); return; } memset(sndbuf, 0, 1024); vpp_msg_h = (vpp_nl_msg *)sndbuf; vpp_addr_info = (vpp_nl_addr_info *)(sndbuf + sizeof(vpp_nl_msg)); if (is_delete == 1){ vpp_msg_h->type = VPP_DELADDR; }else{ vpp_msg_h->type = VPP_NEWADDR; } vpp_msg_h->len = sizeof(vpp_nl_msg) + sizeof(vpp_nl_addr_info) + sizeof (ip6_address_t); vpp_addr_info->ifa_family = AF_INET6; vpp_addr_info->ifa_prefixlen = address_length; vpp_addr_info->ifa_index = sw_if_index; memcpy(sndbuf + sizeof(vpp_nl_msg) + sizeof(vpp_nl_addr_info), (u8 *)address, sizeof (ip6_address_t)); nbytes = zmq_send(zmq_sock,(void *)&sndbuf,vpp_msg_h->len,0); if (nbytes == -1){ clib_warning("oor_ip4_add_del_interface_address: Error while ZMQ sending: %s",zmq_strerror (error)); } zmq_close (zmq_sock); zmq_ctx_destroy (zmq_context); } return; } oor-1.2.0/VPP/oor_ctrl-plugin/oor_ctrl/oor_ctrl.h000066400000000000000000000033451313612200500217120ustar00rootroot00000000000000 /* * oor_ctrl.h - skeleton vpp engine plug-in header file * * Copyright (c) * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __included_oor_ctrl_h__ #define __included_oor_ctrl_h__ #include #include #include #include #include #define OOR_IPC_FILE "ipc:///tmp/oor-vpp-ipc" typedef enum netlink_msg_type_ { VPP_NEWADDR, VPP_DELADDR, VPP_NEWLINK, VPP_DELLINK, VPP_NEWROUTE, VPP_DELROUTE } netlink_msg_type_e; typedef struct { /* API message ID base */ u16 msg_id_base; u32 sw_if_index; /* convenience */ vlib_main_t * vlib_main; vnet_main_t * vnet_main; ethernet_main_t * ethernet_main; } oor_ctrl_main_t; typedef struct vpp_nl_msg_{ netlink_msg_type_e type; u32 len; }vpp_nl_msg; typedef struct{ u32 ifi_index; }vpp_nl_link_info; typedef struct{ u8 ifa_family; u8 ifa_prefixlen; u32 ifa_index; }vpp_nl_addr_info; oor_ctrl_main_t oor_ctrl_main; extern vlib_node_registration_t oor_ctrl_ipv4_node; extern vlib_node_registration_t oor_ctrl_ipv6_node; #define OOR_CTRL_PLUGIN_BUILD_VER "1.0" #endif /* __included_oor_ctrl_h__ */ oor-1.2.0/VPP/oor_ctrl-plugin/oor_ctrl/oor_ctrl_all_api_h.h000066400000000000000000000014311313612200500236740ustar00rootroot00000000000000 /* * oor_ctrl_all_api_h.h - skeleton vpp engine plug-in api #include file * * Copyright (c) * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* Include the generated file, see BUILT_SOURCES in Makefile.am */ #include oor-1.2.0/VPP/oor_ctrl-plugin/oor_ctrl/oor_ctrl_msg_enum.h000066400000000000000000000020301313612200500235720ustar00rootroot00000000000000 /* * oor_ctrl_msg_enum.h - skeleton vpp engine plug-in message enumeration * * Copyright (c) * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef included_oor_ctrl_msg_enum_h #define included_oor_ctrl_msg_enum_h #include #define vl_msg_id(n,h) n, typedef enum { #include /* We'll want to know how many messages IDs we need... */ VL_MSG_FIRST_AVAILABLE, } vl_msg_id_t; #undef vl_msg_id #endif /* included_oor_ctrl_msg_enum_h */ oor-1.2.0/VPP/oor_ctrl-plugin/oor_ctrl/oor_ctrl_test.c000066400000000000000000000125541313612200500227460ustar00rootroot00000000000000 /* * oor_ctrl.c - skeleton vpp-api-test plug-in * * Copyright (c) * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #define __plugin_msg_base oor_ctrl_test_main.msg_id_base #include //uword unformat_sw_if_index (unformat_input_t * input, va_list * args); /* Declare message IDs */ #include /* define message structures */ #define vl_typedefs #include #undef vl_typedefs /* declare message handlers for each api */ #define vl_endianfun /* define message structures */ #include #undef vl_endianfun /* instantiate all the print functions we know about */ #define vl_print(handle, ...) #define vl_printfun #include #undef vl_printfun /* Get the API version number. */ #define vl_api_version(n,v) static u32 api_version=(v); #include #undef vl_api_version typedef struct { /* API message ID base */ u16 msg_id_base; vat_main_t *vat_main; } oor_ctrl_test_main_t; oor_ctrl_test_main_t oor_ctrl_test_main; #define foreach_standard_reply_retval_handler \ _(oor_ctrl_enable_disable_reply) #define _(n) \ static void vl_api_##n##_t_handler \ (vl_api_##n##_t * mp) \ { \ vat_main_t * vam = oor_ctrl_test_main.vat_main; \ i32 retval = ntohl(mp->retval); \ if (vam->async_mode) { \ vam->async_errors += (retval < 0); \ } else { \ vam->retval = retval; \ vam->result_ready = 1; \ } \ } foreach_standard_reply_retval_handler; #undef _ /* * Table of message reply handlers, must include boilerplate handlers * we just generated */ #define foreach_vpe_api_reply_msg \ _(OOR_CTRL_ENABLE_DISABLE_REPLY, oor_ctrl_enable_disable_reply) static int api_oor_ctrl_enable_disable (vat_main_t * vam) { unformat_input_t * input = vam->input; int enable_disable = 1; u32 sw_if_index = ~0; u8 *host_if_name = NULL; vl_api_oor_ctrl_enable_disable_t * mp; int ret; /* Parse args required to build the message */ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { if (unformat (input, "disable")) enable_disable = 0; else if (unformat (input, "%s", &host_if_name)) ; else break; } if (sw_if_index == ~0) { errmsg ("missing interface name / explicit sw_if_index number \n"); return -99; } /* Construct the API message */ M(OOR_CTRL_ENABLE_DISABLE, mp); memcpy(mp->host_if_name,host_if_name,strlen((char *)host_if_name)); mp->enable_disable = enable_disable; /* send it... */ S(mp); /* Wait for a reply... */ W(ret); return (ret); } /* * List of messages that the api test plugin sends, * and that the data plane plugin processes */ #define foreach_vpe_api_msg \ _(oor_ctrl_enable_disable, " [disable]") void oor_ctrl_vat_api_hookup (vat_main_t *vam) { oor_ctrl_test_main_t * sm __attribute__((unused)) = &oor_ctrl_test_main; /* Hook up handlers for replies from the data plane plug-in */ #define _(N,n) \ vl_msg_api_set_handlers((VL_API_##N + sm->msg_id_base), \ #n, \ vl_api_##n##_t_handler, \ vl_noop_handler, \ vl_api_##n##_t_endian, \ vl_api_##n##_t_print, \ sizeof(vl_api_##n##_t), 1); foreach_vpe_api_reply_msg; #undef _ /* API messages we can send */ #define _(n,h) hash_set_mem (vam->function_by_name, #n, api_##n); foreach_vpe_api_msg; #undef _ /* Help strings */ #define _(n,h) hash_set_mem (vam->help_by_name, #n, h); foreach_vpe_api_msg; #undef _ } clib_error_t * vat_plugin_register (vat_main_t *vam) { oor_ctrl_test_main_t * sm = &oor_ctrl_test_main; u8 * name; sm->vat_main = vam; /* Ask the vpp engine for the first assigned message-id */ name = format (0, "oor_ctrl_%08x%c", api_version, 0); sm->msg_id_base = vl_client_get_first_plugin_msg_id ((char *) name); if (sm->msg_id_base != (u16) ~0) oor_ctrl_vat_api_hookup (vam); vec_free(name); return 0; } oor-1.2.0/VPP/oor_pkt_miss-plugin/000077500000000000000000000000001313612200500167535ustar00rootroot00000000000000oor-1.2.0/VPP/oor_pkt_miss-plugin/Makefile.am000066400000000000000000000033651313612200500210160ustar00rootroot00000000000000# Copyright (c) 2015 Cisco and/or its affiliates. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. AUTOMAKE_OPTIONS = foreign subdir-objects AM_CFLAGS = -Wall -I${top_srcdir} -I${top_builddir} AM_LDFLAGS = -module -shared -avoid-version AM_LIBTOOLFLAGS = --quiet SUFFIXES = .api.h .api .api.json API_FILES = BUILT_SOURCES = vppplugins_LTLIBRARIES = vppapitestplugins_LTLIBRARIES = noinst_HEADERS = nobase_apiinclude_HEADERS = ACLOCAL_AMFLAGS = -I m4 vppapitestpluginsdir = ${libdir}/vpp_api_test_plugins vpppluginsdir = ${libdir}/vpp_plugins include oor_pkt_miss.am %.api.h: %.api mkdir -p `dirname $@` ; \ $(CC) $(CPPFLAGS) -E -P -C -x c $^ \ | vppapigen --input - --output $@ --show-name $@ %.api.json: %.api @echo " JSON APIGEN " $@ ; \ mkdir -p `dirname $@` ; \ $(CC) $(CPPFLAGS) -E -P -C -x c $^ \ | vppapigen --input - --json $@ apidir = $(prefix)/api/plugins apiincludedir = ${includedir}/vpp_plugins api_DATA = \ $(patsubst %.api,%.api.json,$(API_FILES)) BUILT_SOURCES += \ $(patsubst %.api,%.api.h,$(API_FILES)) # Remove *.la files install-data-hook: @(cd $(vpppluginsdir) && $(RM) $(vppplugins_LTLIBRARIES)) @(cd $(vppapitestpluginsdir) && $(RM) $(vppapitestplugins_LTLIBRARIES)) CLEANFILES = $(BUILT_SOURCES) oor-1.2.0/VPP/oor_pkt_miss-plugin/configure.ac000066400000000000000000000002521313612200500212400ustar00rootroot00000000000000AC_INIT(oor_pkt_miss_plugin, 1.0) LT_INIT AM_INIT_AUTOMAKE AM_SILENT_RULES([yes]) AC_PREFIX_DEFAULT([/usr]) AC_PROG_CC AC_OUTPUT([Makefile]) AC_CONFIG_MACRO_DIR([m4]) oor-1.2.0/VPP/oor_pkt_miss-plugin/oor_pkt_miss.am000066400000000000000000000023251313612200500220040ustar00rootroot00000000000000# Copyright (c) 2016 Cisco and/or its affiliates. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. vppapitestplugins_LTLIBRARIES += oor_pkt_miss_test_plugin.la vppplugins_LTLIBRARIES += oor_pkt_miss_plugin.la oor_pkt_miss_plugin_la_SOURCES = \ oor_pkt_miss/oor_pkt_miss.c \ oor_pkt_miss/node.c \ oor_pkt_miss/oor_pkt_miss_plugin.api.h API_FILES += oor_pkt_miss/oor_pkt_miss.api nobase_apiinclude_HEADERS += \ oor_pkt_miss/oor_pkt_miss_all_api_h.h \ oor_pkt_miss/oor_pkt_miss_msg_enum.h \ oor_pkt_miss/oor_pkt_miss.api.h oor_pkt_miss_test_plugin_la_SOURCES = oor_pkt_miss/oor_pkt_miss_test.c oor_pkt_miss/oor_pkt_miss_plugin.api.h # vi:syntax=automakeoor-1.2.0/VPP/oor_pkt_miss-plugin/oor_pkt_miss/000077500000000000000000000000001313612200500214635ustar00rootroot00000000000000oor-1.2.0/VPP/oor_pkt_miss-plugin/oor_pkt_miss/node.c000066400000000000000000000067341313612200500225660ustar00rootroot00000000000000 /* * node.c - skeleton vpp engine plug-in dual-loop node skeleton * * Copyright (c) * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include typedef struct { u32 next_index; u32 sw_if_index; } oor_pkt_miss_trace_t; /* packet trace format function */ static u8 * format_oor_pkt_miss_trace (u8 * s, va_list * args) { CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); oor_pkt_miss_trace_t * t = va_arg (*args, oor_pkt_miss_trace_t *); s = format (s, "OOR_PKT_MISS: sw_if_index %d, next index %d", t->sw_if_index, t->next_index); return s; } vlib_node_registration_t oor_pkt_miss_node; #define foreach_oor_pkt_miss_error \ _(SWAPPED, "Mac swap packets processed") typedef enum { #define _(sym,str) OOR_PKT_MISS_ERROR_##sym, foreach_oor_pkt_miss_error #undef _ OOR_PKT_MISS_N_ERROR, } oor_pkt_miss_error_t; static char * oor_pkt_miss_error_strings[] = { #define _(sym,string) string, foreach_oor_pkt_miss_error #undef _ }; typedef enum { OOR_PKT_MISS_NEXT_INTERFACE_OUTPUT, OOR_PKT_MISS_N_NEXT, } oor_pkt_miss_next_t; static uword oor_pkt_miss_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) { u32 n_left_from, * from, * to_next; u32 pkts_swapped = 0; oor_pkt_miss_main_t *sm = &oor_pkt_miss_main; from = vlib_frame_vector_args (frame); n_left_from = frame->n_vectors; while (n_left_from > 0) { u32 n_left_to_next_drop; vlib_get_next_frame (vm, node, OOR_PKT_MISS_NEXT_INTERFACE_OUTPUT, to_next, n_left_to_next_drop); while (n_left_from > 0 && n_left_to_next_drop > 0) { u32 bi0; vlib_buffer_t * b0; bi0 = from[0]; from += 1; n_left_from -= 1; to_next[0] = bi0; to_next += 1; n_left_to_next_drop -= 1; b0 = vlib_get_buffer (vm, bi0); vnet_buffer(b0)->sw_if_index[VLIB_TX] = sm->sw_if_index; if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) { } } vlib_put_next_frame (vm, node, OOR_PKT_MISS_NEXT_INTERFACE_OUTPUT, n_left_to_next_drop); } vlib_node_increment_counter (vm, oor_pkt_miss_node.index, OOR_PKT_MISS_ERROR_SWAPPED, pkts_swapped); return frame->n_vectors; } VLIB_REGISTER_NODE (oor_pkt_miss_node) = { .function = oor_pkt_miss_node_fn, .name = "oor_pkt_miss", .vector_size = sizeof (u32), .format_trace = format_oor_pkt_miss_trace, .type = VLIB_NODE_TYPE_INTERNAL, .n_errors = ARRAY_LEN(oor_pkt_miss_error_strings), .error_strings = oor_pkt_miss_error_strings, .n_next_nodes = OOR_PKT_MISS_N_NEXT, /* edit / add dispositions here */ .next_nodes = { [OOR_PKT_MISS_NEXT_INTERFACE_OUTPUT] = "interface-output", }, }; oor-1.2.0/VPP/oor_pkt_miss-plugin/oor_pkt_miss/oor_pkt_miss.api000066400000000000000000000044131313612200500246700ustar00rootroot00000000000000 /* Define a simple enable-disable binary API to control the feature */ define oor_pkt_miss_enable_disable { /* Client identifier, set from api_main.my_client_index */ u32 client_index; /* Arbitrary context, so client can match reply to request */ u32 context; /* Enable / disable the feature */ u8 enable_disable; u8 host_if_name[64]; }; define oor_pkt_miss_enable_disable_reply { /* From the request */ u32 context; /* Return value, zero means all OK */ i32 retval; }; define oor_pkt_miss_native_route { /* Client identifier, set from api_main.my_client_index */ u32 client_index; /* Arbitrary context, so client can match reply to request */ u32 context; /* Enable / disable the feature */ u8 is_add; /* 1 for IPv6 prefix */ u8 is_ipv6; /* ip4 or ip6 network address */ u8 address[16]; /* prefix len */ u8 mask_len; }; define oor_pkt_miss_native_route_reply { /* From the request */ u32 context; /* Return value, zero means all OK */ i32 retval; }; define oor_pkt_miss_drop_route { /* Client identifier, set from api_main.my_client_index */ u32 client_index; /* Arbitrary context, so client can match reply to request */ u32 context; /* Enable / disable the feature */ u8 is_add; /* 1 for IPv6 prefix */ u8 is_ipv6; /* ip4 or ip6 network address */ u8 address[16]; /* prefix len */ u8 mask_len; /* table where to add or remove route */ u32 table_id; }; define oor_pkt_miss_drop_route_reply { /* From the request */ u32 context; /* Return value, zero means all OK */ i32 retval; }; define oor_pkt_miss_get_default_route { /* Client identifier, set from api_main.my_client_index */ u32 client_index; /* Arbitrary context, so client can match reply to request */ u32 context; /* Request ipv6 gateway */ u8 is_ipv6; }; define oor_pkt_miss_get_default_route_reply { /* From the request */ u32 context; /* Return value, zero means all OK */ i32 retval; /* Request ipv6 gateway */ u8 is_ipv6; /* Address contain gateway address */ u8 has_gateway; /* ip4 or ip6 gateway address */ u8 address[16]; };oor-1.2.0/VPP/oor_pkt_miss-plugin/oor_pkt_miss/oor_pkt_miss.c000066400000000000000000000666271313612200500243600ustar00rootroot00000000000000 /* * oor_pkt_miss.c - skeleton vpp engine plug-in * * Copyright (c) * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include #include #include #include #include /* define message IDs */ #include /* define message structures */ #define vl_typedefs #include #undef vl_typedefs /* define generated endian-swappers */ #define vl_endianfun #include #undef vl_endianfun /* instantiate all the print functions we know about */ #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__) #define vl_printfun #include #undef vl_printfun /* Get the API version number */ #define vl_api_version(n,v) static u32 api_version=(v); #include #undef vl_api_version #define REPLY_MSG_ID_BASE sm->msg_id_base #include int oor_pkt_miss_drop_route (int is_add, fib_prefix_t *prefix, u32 table_id); int oor_pkt_miss_defaults_management_init(oor_pkt_miss_main_t * sm); void oor_pkt_miss_enable_disable_src_route_check(int is_enable); int oor_pkt_miss_defaults_management_uninit(oor_pkt_miss_main_t * sm); int oor_pkt_miss_get_ipv4_gateway(ip46_address_t *gateway); int oor_pkt_miss_get_ipv6_gateway(ip46_address_t *gateway); /* List of message types that this plugin understands */ #define foreach_oor_pkt_miss_plugin_api_msg \ _(OOR_PKT_MISS_ENABLE_DISABLE, oor_pkt_miss_enable_disable) \ _(OOR_PKT_MISS_NATIVE_ROUTE, oor_pkt_miss_native_route) \ _(OOR_PKT_MISS_DROP_ROUTE, oor_pkt_miss_drop_route) \ _(OOR_PKT_MISS_GET_DEFAULT_ROUTE, oor_pkt_miss_get_default_route) /* *INDENT-OFF* */ VLIB_PLUGIN_REGISTER () = { .version = OOR_PKT_MISS_PLUGIN_BUILD_VER, .description = "OOR paket miss plugin", }; /* Action function shared between message handler and debug CLI */ int oor_pkt_miss_enable_disable (oor_pkt_miss_main_t * sm, u8 * host_if_name, int enable_disable) { u8 hwaddr[6] = {0,0,0,0,0,0}; u32 sw_if_index = ~0; vnet_sw_interface_t *si; vnet_lisp_gpe_enable_disable_args_t lisp_gpe_args; char vpp_if_name[100]; u16 flags; int rv; clib_warning("OOR_PKT_MISS: %s node", enable_disable ? "enable" : "disale"); if (enable_disable){ //oor_pkt_miss_enable_disable_src_route_check(0); /* Configure default gateway of the router for native forward entries */ oor_pkt_miss_defaults_management_init(sm); /* Create host-interface */ rv = af_packet_create_if (sm->vlib_main, host_if_name, hwaddr, &sw_if_index); if (rv != 0 && rv != VNET_API_ERROR_SUBIF_ALREADY_EXISTS){ return (VNET_API_ERROR_INVALID_INTERFACE); } /* Set interface status to UP */ flags = VNET_SW_INTERFACE_FLAG_ADMIN_UP; vnet_sw_interface_set_flags (sm->vnet_main, sw_if_index, flags); /* Set interface to unnumbered */ si = vnet_get_sw_interface (sm->vnet_main, sw_if_index); si->flags |= VNET_SW_INTERFACE_FLAG_UNNUMBERED; si->unnumbered_sw_if_index = sw_if_index; ip4_sw_interface_enable_disable (sw_if_index, 1); ip6_sw_interface_enable_disable (sw_if_index, 1); /* Enable lisp data plane */ lisp_gpe_args.is_en = 1; vnet_lisp_gpe_enable_disable (&lisp_gpe_args); /* Enable host-interface to send traffic to oor */ sm->sw_if_index = sw_if_index; }else{ /* Remove unnumbered interface*/ si = vnet_get_sw_interface (sm->vnet_main, sm->sw_if_index); si->flags &= ~(VNET_SW_INTERFACE_FLAG_UNNUMBERED); si->unnumbered_sw_if_index = (u32) ~ 0; ip4_sw_interface_enable_disable (sm->sw_if_index, 0); ip6_sw_interface_enable_disable (sm->sw_if_index, 0); /* Disable host-interface to send traffic to oor */ af_packet_delete_if (sm->vlib_main, host_if_name); sm->sw_if_index = ~0; /* Disable lisp data plane */ lisp_gpe_tenant_l3_iface_unlock (0); lisp_gpe_args.is_en = 0; vnet_lisp_gpe_enable_disable (&lisp_gpe_args); /* Remove host interfaces */ snprintf(vpp_if_name, sizeof (vpp_if_name), "%s%s", "host-",(char *)host_if_name); af_packet_delete_if (sm->vlib_main, (u8 *)vpp_if_name); /* Reinsert the default gateways */ oor_pkt_miss_defaults_management_uninit(sm); // oor_pkt_miss_enable_disable_src_route_check(1); } return 0; } static clib_error_t * oor_pkt_miss_enable_disable_command_fn (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) { oor_pkt_miss_main_t * sm = &oor_pkt_miss_main; u8 *host_if_name = NULL; int enable_disable = 1; int rv; while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { if (unformat (input, "disable")){ enable_disable = 0; }else if (unformat (input, "%s", &host_if_name)){ ; }else{ break; } } if (host_if_name == NULL){ return clib_error_return (0, "Please specify an interface..."); } rv = oor_pkt_miss_enable_disable (sm, host_if_name, enable_disable); switch(rv) { case 0: break; case VNET_API_ERROR_INVALID_SW_IF_INDEX: return clib_error_return (0, "Invalid interface, only works on physical ports"); break; case VNET_API_ERROR_UNIMPLEMENTED: return clib_error_return (0, "Device driver doesn't support redirection"); break; default: return clib_error_return (0, "oor_pkt_miss_enable_disable returned %d", rv); } return 0; } VLIB_CLI_COMMAND (oor_pkt_miss_enable_disable_command, static) = { .path = "oor_pkt_miss enable-disable", .short_help = "oor_pkt_miss enable-disable [disable]", .function = oor_pkt_miss_enable_disable_command_fn, }; /* Action function shared between message handler and debug CLI */ int oor_pkt_miss_native_route (oor_pkt_miss_main_t * sm, int is_add, fib_prefix_t *prefix) { fib_route_path_t *rpaths = NULL, rpath; ip46_address_t *gateway; fib_protocol_t proto; u32 fib_index; if (prefix->fp_proto == FIB_PROTOCOL_IP4){ proto = FIB_PROTOCOL_IP4; fib_index = ip4_fib_index_from_table_id(0); if (!sm->has_ipv4_gateway){ clib_warning("OOR_PKT_MISS: Can not %s prefix via gateway. No IPv4 gateway detected", is_add == 1 ? "add" : "remove"); goto no_gateway; } gateway = &sm->ipv4_gateway; clib_warning("OOR_PKT_MISS: %s route to %s/%d via gateway", (is_add == 1 ? "Add":"Remove"), format (0, "%U", format_ip4_address, &(prefix[0].fp_addr.ip4)), prefix->fp_len); }else{ proto = FIB_PROTOCOL_IP6; fib_index = ip6_fib_index_from_table_id(0); if (!sm->has_ipv6_gateway){ clib_warning("OOR_PKT_MISS: Can not %s prefix via gateway. No IPv6 gateway detected", is_add == 1 ? "add" : "remove"); goto no_gateway; } gateway = &sm->ipv6_gateway; clib_warning("OOR_PKT_MISS: %s route to %s/%d via gateway", (is_add == 1 ? "Add":"Remove"), format (0, "%U", format_ip6_address, &(prefix[0].fp_addr.ip6)), prefix->fp_len); } memset (&rpath, 0, sizeof (rpath)); rpath.frp_fib_index = 0; rpath.frp_weight = 1; rpath.frp_sw_if_index = ~0; // XXX to check rpath.frp_proto = proto; memcpy(&rpath.frp_addr,gateway, sizeof(ip46_address_t)); vec_add1 (rpaths, rpath); if (is_add == 1){ fib_table_entry_path_add2 (fib_index, &prefix[0], FIB_SOURCE_CLI, FIB_ENTRY_FLAG_NONE, &rpaths[0]); // Check if we could send directly rpath }else{ fib_table_entry_delete (fib_index, &prefix[0], FIB_SOURCE_CLI); } return 0; no_gateway: oor_pkt_miss_drop_route (is_add,prefix,0); return 0; } static clib_error_t * oor_pkt_miss_native_route_command_fn (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) { oor_pkt_miss_main_t * sm = &oor_pkt_miss_main; fib_prefix_t *prefixs = NULL, prefix; clib_error_t *error = 0; int is_add = 1; if (sm->sw_if_index == ~0){ return clib_error_return (0, "OOR paket miss plugin is not enabled."); } memset(&prefix,0,sizeof(fib_prefix_t)); while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { if (unformat (input, "del")){ is_add = 0; }else if (unformat (input, "add")){ is_add = 1; }else if (unformat (input, "%U/%d",unformat_ip4_address, &prefix.fp_addr.ip4, &prefix.fp_len)){ prefix.fp_proto = FIB_PROTOCOL_IP4; vec_add1 (prefixs, prefix); }else if (unformat (input, "%U/%d",unformat_ip6_address, &prefix.fp_addr.ip6, &prefix.fp_len)){ prefix.fp_proto = FIB_PROTOCOL_IP6; vec_add1 (prefixs, prefix); }else{ break; } } if (vec_len (prefixs) == 0){ vec_free (prefixs); return clib_error_return (0, "expected ip4/ip6 destination address/length."); } oor_pkt_miss_native_route (sm, is_add, &prefixs[0]); return error; } VLIB_CLI_COMMAND (oor_pkt_miss_native_route_command, static) = { .path = "oor_pkt_miss native-route", .short_help = "oor_pkt_miss native-route [add|del] /", .function = oor_pkt_miss_native_route_command_fn, }; int oor_pkt_miss_drop_route (int is_add, fib_prefix_t *prefix, u32 table_id) { //fib_table_t *fib_table; u32 fib_index; const dpo_id_t *drop_dpo; if (prefix->fp_proto == FIB_PROTOCOL_IP4){ fib_index = ip4_fib_index_from_table_id(table_id); }else{ fib_index = ip6_fib_index_from_table_id(table_id); } if (is_add){ drop_dpo = drop_dpo_get(fib_proto_to_dpo(prefix->fp_proto)); fib_table_entry_special_dpo_add (fib_index,prefix,FIB_SOURCE_CLI,FIB_ENTRY_FLAG_EXCLUSIVE, drop_dpo); }else{ fib_table_entry_delete (fib_index, &prefix[0], FIB_SOURCE_CLI); } return 0; } static clib_error_t * oor_pkt_miss_drop_route_command_fn (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) { oor_pkt_miss_main_t * sm = &oor_pkt_miss_main; fib_prefix_t *prefixs = NULL, prefix; clib_error_t *error = 0; int is_add = 1; u32 table_id = 0; if (sm->sw_if_index == ~0){ return clib_error_return (0, "OOR paket miss plugin is not enabled."); } while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { if (unformat (input, "del")){ is_add = 0; }else if (unformat (input, "add")){ is_add = 1; }else if (unformat (input, "%U/%d",unformat_ip4_address, &prefix.fp_addr.ip4, &prefix.fp_len)){ prefix.fp_proto = FIB_PROTOCOL_IP4; vec_add1 (prefixs, prefix); }else if (unformat (input, "%U/%d",unformat_ip6_address, &prefix.fp_addr.ip6, &prefix.fp_len)){ prefix.fp_proto = FIB_PROTOCOL_IP6; vec_add1 (prefixs, prefix); }else if (unformat (input,"table-id %d",&table_id)){ }else{ break; } } if (vec_len (prefixs) == 0){ vec_free (prefixs); return clib_error_return (0, "expected ip4/ip6 destination address/length."); } oor_pkt_miss_drop_route (is_add, &prefixs[0], table_id); return error; } VLIB_CLI_COMMAND (oor_pkt_miss_drop_route_command, static) = { .path = "oor_pkt_miss drop-route", .short_help = "oor_pkt_miss drop-route [add|del] / [table-id ]", .function = oor_pkt_miss_drop_route_command_fn, }; static clib_error_t * oor_pkt_miss_get_default_route_command_fn (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) { oor_pkt_miss_main_t * sm = &oor_pkt_miss_main; ip46_address_t gateway; clib_error_t *error = 0; int is_ipv6 = 0; u8 *msg = 0; while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { if (unformat (input, "ipv6")){ is_ipv6 = 1; }else if (unformat (input, "ipv4")){ is_ipv6 = 0; }else{ break; } } if (sm->sw_if_index == ~0){ if (is_ipv6){ if (oor_pkt_miss_get_ipv6_gateway(&gateway) == 0){ msg = format (msg, "IPv6 default gw: %U\n",format_ip6_address, &gateway.ip6); vlib_cli_output (vm, "%v", msg); }else{ msg = format (msg, "IPv6 default gw: --\n"); vlib_cli_output (vm, "%v", msg); } }else{ if (oor_pkt_miss_get_ipv4_gateway(&gateway) == 0){ msg = format (msg, "IPv4 default gw: %U\n",format_ip4_address, &gateway.ip4); vlib_cli_output (vm, "%v", msg); }else{ msg = format (msg, "IPv4 default gw: --\n"); vlib_cli_output (vm, "%v", msg); } } }else{ if (is_ipv6){ if (sm->has_ipv6_gateway){ msg = format (msg, "IPv6 default gw: %U\n",format_ip6_address, &sm->ipv6_gateway.ip6); vlib_cli_output (vm, "%v", msg); }else{ msg = format (msg, "IPv6 default gw: --\n"); vlib_cli_output (vm, "%v", msg); } }else{ if (sm->has_ipv4_gateway){ msg = format (msg, "IPv4 default gw: %U\n",format_ip4_address, &sm->ipv4_gateway.ip4); vlib_cli_output (vm, "%v", msg); }else{ msg = format (msg, "IPv4 default gw: --\n"); vlib_cli_output (vm, "%v", msg); } } } return error; } VLIB_CLI_COMMAND (oor_pkt_miss_get_default_route_command, static) = { .path = "oor_pkt_miss get-default-route", .short_help = "oor_pkt_miss get-default-route [ipv4|ipv6]", .function = oor_pkt_miss_get_default_route_command_fn, }; /* API message handler */ static void vl_api_oor_pkt_miss_enable_disable_t_handler (vl_api_oor_pkt_miss_enable_disable_t * mp) { vl_api_oor_pkt_miss_enable_disable_reply_t * rmp; oor_pkt_miss_main_t * sm = &oor_pkt_miss_main; u8 *host_if_name = NULL; int rv; host_if_name = format (0, "%s", mp->host_if_name); vec_add1 (host_if_name, 0); rv = oor_pkt_miss_enable_disable (sm, host_if_name,(int) (mp->enable_disable)); vec_free (host_if_name); REPLY_MACRO(VL_API_OOR_PKT_MISS_ENABLE_DISABLE_REPLY); } static void vl_api_oor_pkt_miss_native_route_t_handler (vl_api_oor_pkt_miss_native_route_t * mp) { vl_api_oor_pkt_miss_native_route_reply_t * rmp; oor_pkt_miss_main_t * sm = &oor_pkt_miss_main; fib_prefix_t prefix; memset(&prefix,0,sizeof(fib_prefix_t)); int rv; prefix.fp_proto = (mp->is_ipv6 == 1) ? FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4; prefix.fp_len = mp->mask_len; if (mp->is_ipv6 == 0){ memcpy(&prefix.fp_addr.ip4,mp->address,4); }else{ memcpy(&prefix.fp_addr.ip6,mp->address,16); } oor_pkt_miss_native_route (sm,mp->is_add,&prefix); REPLY_MACRO(VL_API_OOR_PKT_MISS_NATIVE_ROUTE_REPLY); } static void vl_api_oor_pkt_miss_drop_route_t_handler (vl_api_oor_pkt_miss_drop_route_t * mp) { vl_api_oor_pkt_miss_drop_route_reply_t * rmp; oor_pkt_miss_main_t * sm = &oor_pkt_miss_main; fib_prefix_t prefix; int rv; prefix.fp_proto = (mp->is_ipv6 == 1) ? FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4; prefix.fp_len = mp->mask_len; if (mp->is_ipv6 == 0){ memcpy(&prefix.fp_addr.ip4,mp->address,4); }else{ memcpy(&prefix.fp_addr.ip6,mp->address,16); } clib_warning("=====>>> Drop api"); oor_pkt_miss_drop_route (mp->is_add,&prefix,mp->table_id); REPLY_MACRO(VL_API_OOR_PKT_MISS_DROP_ROUTE_REPLY); } static void vl_api_oor_pkt_miss_get_default_route_t_handler (vl_api_oor_pkt_miss_get_default_route_t * mp) { vl_api_oor_pkt_miss_get_default_route_reply_t * rmp; oor_pkt_miss_main_t * sm = &oor_pkt_miss_main; ip46_address_t gateway; int rv = 0; unix_shared_memory_queue_t *q = vl_api_client_index_to_input_queue (mp->client_index); if (!q){ return; } rmp = vl_msg_api_alloc (sizeof (*rmp)); rmp->_vl_msg_id = ntohs((VL_API_OOR_PKT_MISS_GET_DEFAULT_ROUTE_REPLY)+sm->msg_id_base); rmp->context = mp->context; if (sm->sw_if_index == ~0){ if (mp->is_ipv6){ rmp->is_ipv6 = 1; if (oor_pkt_miss_get_ipv6_gateway(&gateway) == 0){ memcpy(rmp->address,&gateway.ip6,16); rmp->has_gateway = 1; }else{ rmp->has_gateway = 0; } }else{ rmp->is_ipv6 = 0; if (oor_pkt_miss_get_ipv4_gateway(&gateway) == 0){ memcpy(rmp->address,&gateway.ip4,4); rmp->has_gateway = 1; }else{ rmp->has_gateway = 0; } } }else{ if (mp->is_ipv6){ rmp->is_ipv6 = 1; if (sm->has_ipv6_gateway){ memcpy(rmp->address,&sm->ipv6_gateway.ip6,16); rmp->has_gateway = 1; }else{ rmp->has_gateway = 0; } }else{ rmp->is_ipv6 = 0; if (sm->has_ipv4_gateway){ memcpy(rmp->address,&sm->ipv4_gateway.ip4,4); rmp->has_gateway = 1; }else{ rmp->has_gateway = 0; } } } rmp->retval = ntohl(rv); vl_msg_api_send_shmem (q, (u8 *)&rmp); } /* Set up the API message handling tables */ static clib_error_t * oor_pkt_miss_plugin_api_hookup (vlib_main_t *vm) { oor_pkt_miss_main_t * sm = &oor_pkt_miss_main; #define _(N,n) \ vl_msg_api_set_handlers((VL_API_##N + sm->msg_id_base), \ #n, \ vl_api_##n##_t_handler, \ vl_noop_handler, \ vl_api_##n##_t_endian, \ vl_api_##n##_t_print, \ sizeof(vl_api_##n##_t), 1); foreach_oor_pkt_miss_plugin_api_msg; #undef _ return 0; } /******** DEAFAULTS MANAGEMENT **********/ int oor_pkt_miss_get_ipv4_gateway(ip46_address_t *gateway) { ip4_address_t address; u32 mask_len = 0, fib_index; ip4_fib_t *fib; fib_node_index_t index = ~0; adj_index_t adj_inxex; ip_adjacency_t *adj; load_balance_t *lb_m, *lb_b; const dpo_id_t *dpo0, *dpo1, *dpo_fwd; int i=0, j=0, have_gw=0; fib_index = ip4_fib_index_from_table_id(0); if (fib_index == ~0){ clib_warning("OOR_PKT_MISS: No default fib found"); return (-1); } fib = ip4_fib_get(fib_index); memset(&address,0,sizeof(ip4_address_t)); index = ip4_fib_table_lookup(fib, &address, mask_len); if (index == FIB_NODE_INDEX_INVALID){ clib_warning("OOR_PKT_MISS: No default IPv4 gateway found"); return (-2); } dpo_fwd = fib_entry_contribute_ip_forwarding(index); lb_m = load_balance_get (dpo_fwd->dpoi_index); for (i = 0; i < lb_m->lb_n_buckets; i++){ dpo0 = load_balance_get_bucket_i (lb_m, i); if (dpo0->dpoi_type == DPO_LOAD_BALANCE){ lb_b = load_balance_get (dpo0->dpoi_index); for (j = 0; j < lb_b->lb_n_buckets; j++){ dpo1 = load_balance_get_bucket_i (lb_b, j); if (dpo1->dpoi_type == DPO_ADJACENCY || dpo1->dpoi_type == DPO_ADJACENCY_INCOMPLETE){ adj_inxex = dpo1->dpoi_index; if (ADJ_INDEX_INVALID == adj_inxex){ continue; } adj = ip_get_adjacency (&(ip4_main.lookup_main), adj_inxex); memcpy (gateway,&(adj->sub_type.nbr.next_hop),sizeof(ip46_address_t)); clib_warning("OOR_PKT_MISS: IPv4 gateway: %s", format (0, "%U", format_ip4_address, &(adj->sub_type.nbr.next_hop.ip4))); have_gw=1; break; } } if (have_gw == 1){ break; } } } if (have_gw == 0){ clib_warning("OOR_PKT_MISS: No IPv4 gateway found"); return (-4); } return (0); } int oor_pkt_miss_ipv4_defaults_management_init(oor_pkt_miss_main_t * sm) { /* Obtain default gateway */ u32 fib_index; int ret; fib_prefix_t prefix; fib_index = ip4_fib_index_from_table_id(0); ret = oor_pkt_miss_get_ipv4_gateway(&sm->ipv4_gateway); if (ret == 0){ sm->has_ipv4_gateway = 1; }else{ return (ret); } /* Remove the gateway */ memset(&prefix,0,sizeof(fib_prefix_t)); prefix.fp_proto = FIB_PROTOCOL_IP4; /* Remove gateway */ fib_table_entry_delete (fib_index, &prefix, FIB_SOURCE_CLI); return (0); } int oor_pkt_miss_get_ipv6_gateway(ip46_address_t *gateway) { /* Obtain default gateway */ u32 fib_index; ip6_fib_t *fib; fib_node_index_t index = ~0; adj_index_t adj_inxex; ip_adjacency_t *adj; load_balance_t *lb_m, *lb_b; const dpo_id_t *dpo0, *dpo1 , *dpo_fwd; int i=0, j=0, have_gw=0; fib_index = ip6_fib_index_from_table_id(0); if (fib_index == ~0){ clib_warning("OOR_PKT_MISS: No default fib found"); return (-1); } fib = ip6_fib_get(fib_index); fib_prefix_t pfx_0_0 = { .fp_len = 128, .fp_proto = FIB_PROTOCOL_IP6, .fp_addr = { .ip6 = { .as_u64 = { [0] = 0, [1] = 0, }, }, } }; index = fib_table_lookup(fib->index, &pfx_0_0); dpo_fwd = fib_entry_contribute_ip_forwarding(index); lb_m = load_balance_get (dpo_fwd->dpoi_index); for (i = 0; i < lb_m->lb_n_buckets; i++){ dpo0 = load_balance_get_bucket_i (lb_m, i); if (dpo0->dpoi_type == DPO_LOAD_BALANCE){ lb_b = load_balance_get (dpo0->dpoi_index); for (j = 0; j < lb_b->lb_n_buckets; j++){ dpo1 = load_balance_get_bucket_i (lb_b, j); if (dpo1->dpoi_type == DPO_ADJACENCY || dpo1->dpoi_type == DPO_ADJACENCY_INCOMPLETE){ adj_inxex = dpo1->dpoi_index; if (ADJ_INDEX_INVALID == adj_inxex){ continue; } adj = ip_get_adjacency (&(ip6_main.lookup_main), adj_inxex); memcpy (gateway,&(adj->sub_type.nbr.next_hop),sizeof(ip46_address_t)); clib_warning("OOR_PKT_MISS: IPv6 gateway: %s", format (0, "%U", format_ip6_address, &(adj->sub_type.nbr.next_hop.ip6))); have_gw=1; break; } } if (have_gw == 1){ break; } } } if (have_gw == 0){ clib_warning("OOR_PKT_MISS: No IPv6 gateway found"); return (-4); } return (0); } int oor_pkt_miss_ipv6_defaults_management_init(oor_pkt_miss_main_t * sm) { /* Obtain default gateway */ int ret; fib_prefix_t prefix; u32 fib_index; fib_index = ip6_fib_index_from_table_id(0); ret = oor_pkt_miss_get_ipv6_gateway(&sm->ipv6_gateway); if (ret == 0){ sm->has_ipv6_gateway = 1; }else{ return (ret); } /* Remove the gateway */ memset(&prefix,0,sizeof(fib_prefix_t)); prefix.fp_proto = FIB_PROTOCOL_IP6; /* Remove gateway */ fib_table_entry_delete (fib_index, &prefix, FIB_SOURCE_CLI); return (0); } int oor_pkt_miss_defaults_management_init(oor_pkt_miss_main_t * sm) { oor_pkt_miss_ipv4_defaults_management_init(sm); oor_pkt_miss_ipv6_defaults_management_init(sm); return (0); } int oor_pkt_miss_defaults_management_uninit(oor_pkt_miss_main_t * sm) { fib_prefix_t prefix; if (sm->has_ipv4_gateway){ memset(&prefix,0,sizeof(fib_prefix_t)); prefix.fp_proto = FIB_PROTOCOL_IP4; oor_pkt_miss_native_route (sm, 1, &prefix); memset (&sm->ipv4_gateway,0,sizeof(ip46_address_t)); sm->has_ipv4_gateway = 0; } if (sm->has_ipv6_gateway){ memset(&prefix,0,sizeof(fib_prefix_t)); prefix.fp_proto = FIB_PROTOCOL_IP6; oor_pkt_miss_native_route (sm, 1, &prefix); memset (&sm->ipv6_gateway,0,sizeof(ip46_address_t)); sm->has_ipv6_gateway = 0; } return (0); } /* Enable or disable the source path check */ // XXX It doesn't work for IPv6 in VPP 17.01. To be tested in new versions void oor_pkt_miss_enable_disable_src_route_check(int is_enable) { u32 fib_index4, fib_index6; fib_prefix_t pfx4, pfx6; memset (&pfx4,0,sizeof(fib_prefix_t)); pfx4.fp_proto = FIB_PROTOCOL_IP4; memset (&pfx6,0,sizeof(fib_prefix_t)); pfx6.fp_proto = FIB_PROTOCOL_IP6; fib_index4 = ip4_fib_index_from_table_id(0); fib_index6 = ip6_fib_index_from_table_id(0); if (!is_enable){ fib_table_entry_special_add (fib_index4, &pfx4, FIB_SOURCE_URPF_EXEMPT, FIB_ENTRY_FLAG_DROP); fib_table_entry_special_add (fib_index6, &pfx6, FIB_SOURCE_URPF_EXEMPT, FIB_ENTRY_FLAG_DROP); } else{ fib_table_entry_special_remove (fib_index4, &pfx4, FIB_SOURCE_URPF_EXEMPT); fib_table_entry_special_remove (fib_index6, &pfx6, FIB_SOURCE_URPF_EXEMPT); } } #define vl_msg_name_crc_list #include #undef vl_msg_name_crc_list static void setup_message_id_table (oor_pkt_miss_main_t * sm, api_main_t *am) { #define _(id,n,crc) \ vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id + sm->msg_id_base); foreach_vl_msg_name_crc_oor_pkt_miss; #undef _ } static clib_error_t * oor_pkt_miss_init (vlib_main_t * vm) { oor_pkt_miss_main_t * sm = &oor_pkt_miss_main; clib_error_t * error = 0; u8 * name; sm->vnet_main = vnet_get_main (); name = format (0, "oor_pkt_miss_%08x%c", api_version, 0); sm->sw_if_index = ~0; /* Ask for a correctly-sized block of API message decode slots */ sm->msg_id_base = vl_msg_api_get_msg_ids ((char *) name, VL_MSG_FIRST_AVAILABLE); error = oor_pkt_miss_plugin_api_hookup (vm); /* Add our API messages to the global name_crc hash table */ setup_message_id_table (sm, &api_main); vec_free(name); return error; } VLIB_INIT_FUNCTION (oor_pkt_miss_init); oor-1.2.0/VPP/oor_pkt_miss-plugin/oor_pkt_miss/oor_pkt_miss.h000066400000000000000000000026031313612200500243450ustar00rootroot00000000000000 /* * oor_pkt_miss.h - skeleton vpp engine plug-in header file * * Copyright (c) * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __included_oor_pkt_miss_h__ #define __included_oor_pkt_miss_h__ #include #include #include #include #include typedef struct { /* API message ID base */ u16 msg_id_base; u32 sw_if_index; ip46_address_t ipv4_gateway; u8 has_ipv4_gateway; ip46_address_t ipv6_gateway; u8 has_ipv6_gateway; /* convenience */ vlib_main_t * vlib_main; vnet_main_t * vnet_main; ethernet_main_t * ethernet_main; } oor_pkt_miss_main_t; oor_pkt_miss_main_t oor_pkt_miss_main; vlib_node_registration_t oor_pkt_miss_node; #define OOR_PKT_MISS_PLUGIN_BUILD_VER "1.0" #endif /* __included_oor_pkt_miss_h__ */ oor-1.2.0/VPP/oor_pkt_miss-plugin/oor_pkt_miss/oor_pkt_miss_all_api_h.h000066400000000000000000000014451313612200500263400ustar00rootroot00000000000000 /* * oor_pkt_miss_all_api_h.h - skeleton vpp engine plug-in api #include file * * Copyright (c) * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* Include the generated file, see BUILT_SOURCES in Makefile.am */ #include oor-1.2.0/VPP/oor_pkt_miss-plugin/oor_pkt_miss/oor_pkt_miss_msg_enum.h000066400000000000000000000020601313612200500262340ustar00rootroot00000000000000 /* * oor_pkt_miss_msg_enum.h - skeleton vpp engine plug-in message enumeration * * Copyright (c) * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef included_oor_pkt_miss_msg_enum_h #define included_oor_pkt_miss_msg_enum_h #include #define vl_msg_id(n,h) n, typedef enum { #include /* We'll want to know how many messages IDs we need... */ VL_MSG_FIRST_AVAILABLE, } vl_msg_id_t; #undef vl_msg_id #endif /* included_oor_pkt_miss_msg_enum_h */ oor-1.2.0/VPP/oor_pkt_miss-plugin/oor_pkt_miss/oor_pkt_miss_test.c000066400000000000000000000247671313612200500254160ustar00rootroot00000000000000 /* * oor_pkt_miss.c - skeleton vpp-api-test plug-in * * Copyright (c) * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include #include #define __plugin_msg_base oor_pkt_miss_test_main.msg_id_base #include uword unformat_sw_if_index (unformat_input_t * input, va_list * args); /* Declare message IDs */ #include /* define message structures */ #define vl_typedefs #include #undef vl_typedefs /* declare message handlers for each api */ #define vl_endianfun /* define message structures */ #include #undef vl_endianfun /* instantiate all the print functions we know about */ #define vl_print(handle, ...) #define vl_printfun #include #undef vl_printfun /* Get the API version number. */ #define vl_api_version(n,v) static u32 api_version=(v); #include #undef vl_api_version typedef struct { /* API message ID base */ u16 msg_id_base; vat_main_t *vat_main; } oor_pkt_miss_test_main_t; oor_pkt_miss_test_main_t oor_pkt_miss_test_main; #define foreach_standard_reply_retval_handler \ _(oor_pkt_miss_enable_disable_reply) \ _(oor_pkt_miss_native_route_reply) \ _(oor_pkt_miss_drop_route_reply) \ #define _(n) \ static void vl_api_##n##_t_handler \ (vl_api_##n##_t * mp) \ { \ vat_main_t * vam = oor_pkt_miss_test_main.vat_main; \ i32 retval = ntohl(mp->retval); \ if (vam->async_mode) { \ vam->async_errors += (retval < 0); \ } else { \ vam->retval = retval; \ vam->result_ready = 1; \ } \ } foreach_standard_reply_retval_handler; #undef _ /********************** API REPLY HANDLER ***********************************/ static void vl_api_oor_pkt_miss_get_default_route_reply_t_handler(vl_api_oor_pkt_miss_get_default_route_reply_t * mp) { vat_main_t * vam = oor_pkt_miss_test_main.vat_main; i32 retval = ntohl (mp->retval); char ip_addr[INET6_ADDRSTRLEN]; if (0 <= retval) { if (mp->is_ipv6){ if (mp->has_gateway){ inet_ntop(AF_INET6,&(mp->address),ip_addr,INET6_ADDRSTRLEN); fformat (vam->ofp, "IPv6 default gw: %s\n", ip_addr ); }else{ fformat (vam->ofp, "IPv6 default gw: --\n"); } }else{ if (mp->has_gateway){ fformat (vam->ofp, "IPv4 default gw: %U\n",format_ip4_address, &(mp->address)); }else{ fformat (vam->ofp, "IPv4 default gw: --\n"); } } } vam->retval = retval; vam->result_ready = 1; } /* * Table of message reply handlers, must include boilerplate handlers * we just generated */ #define foreach_vpe_api_reply_msg \ _(OOR_PKT_MISS_ENABLE_DISABLE_REPLY, oor_pkt_miss_enable_disable_reply) \ _(OOR_PKT_MISS_NATIVE_ROUTE_REPLY, oor_pkt_miss_native_route_reply) \ _(OOR_PKT_MISS_DROP_ROUTE_REPLY, oor_pkt_miss_drop_route_reply) \ _(OOR_PKT_MISS_GET_DEFAULT_ROUTE_REPLY, oor_pkt_miss_get_default_route_reply) static int api_oor_pkt_miss_enable_disable (vat_main_t * vam) { unformat_input_t * input = vam->input; int enable_disable = 1; u8 *host_if_name = NULL; vl_api_oor_pkt_miss_enable_disable_t * mp; int ret; while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { if (unformat (input, "disable")) enable_disable = 0; else if (unformat (input, "%s", &host_if_name)) ; else break; } unformat_free (input); if (host_if_name == NULL){ errmsg ("missing interface name\n"); return -99; } /* Construct the API message */ M(OOR_PKT_MISS_ENABLE_DISABLE, mp); memcpy(mp->host_if_name,host_if_name,strlen((char *)host_if_name)); mp->enable_disable = enable_disable; /* send it... */ S(mp); /* Wait for a reply... */ W(ret); return (ret); } static int api_oor_pkt_miss_native_route (vat_main_t * vam) { vl_api_oor_pkt_miss_native_route_t * mp; unformat_input_t * input = vam->input; int is_add = 1; ip4_address_t ip4_addr; ip6_address_t ip6_addr; u32 pref_len; u8 ipv4_set = 0; u8 ipv6_set = 0; int ret; /* Parse args required to build the message */ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { if (unformat (input, "del")){ is_add = 0; }else if (unformat (input, "add")){ is_add = 1; }else if (unformat (input, "%U/%d",unformat_ip4_address, &ip4_addr, &pref_len)){ ipv4_set = 1; }else if (unformat (input, "%U/%d",unformat_ip6_address, &ip6_addr, &pref_len)){ ipv6_set = 1; }else{ break; } } if (!ipv4_set && !ipv6_set){ clib_error_return (0, "expected ip4/ip6 destination address/length."); return -99; } /* Construct the API message */ M(OOR_PKT_MISS_NATIVE_ROUTE, mp); mp->is_add = is_add; mp->is_ipv6 = ipv6_set; mp->mask_len = pref_len; if (mp->is_ipv6 != 1){ clib_memcpy (mp->address, &ip4_addr, sizeof(ip4_addr)); }else{ clib_memcpy (mp->address, &ip6_addr, sizeof(ip6_addr)); } /* send it... */ S(mp); /* Wait for a reply... */ W(ret); return(ret); } static int api_oor_pkt_miss_drop_route (vat_main_t * vam) { vl_api_oor_pkt_miss_drop_route_t * mp; unformat_input_t * input = vam->input; int is_add = 1; ip4_address_t ip4_addr; ip6_address_t ip6_addr; u32 pref_len; u8 ipv4_set = 0; u8 ipv6_set = 0; u32 table_id = 0; int ret; /* Parse args required to build the message */ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { if (unformat (input, "del")){ is_add = 0; }else if (unformat (input, "add")){ is_add = 1; }else if (unformat (input, "%U/%d",unformat_ip4_address, &ip4_addr, &pref_len)){ ipv4_set = 1; }else if (unformat (input, "%U/%d",unformat_ip6_address, &ip6_addr, &pref_len)){ ipv6_set = 1; }else if (unformat (input, "table-id %d", &table_id)){ table_id = 1; }else{ break; } } if (!ipv4_set && !ipv6_set){ clib_error_return (0, "expected ip4/ip6 destination address/length."); return -99; } /* Construct the API message */ M(OOR_PKT_MISS_DROP_ROUTE, mp); mp->is_add = is_add; mp->is_ipv6 = ipv6_set; mp->mask_len = pref_len; if (mp->is_ipv6 != 1){ clib_memcpy (mp->address, &ip4_addr, sizeof(ip4_addr)); }else{ clib_memcpy (mp->address, &ip6_addr, sizeof(ip6_addr)); } mp->table_id = table_id; /* send it... */ S(mp); /* Wait for a reply... */ W(ret); return (ret); } static int api_oor_pkt_miss_get_default_route (vat_main_t * vam) { vl_api_oor_pkt_miss_get_default_route_t * mp; unformat_input_t * input = vam->input; int is_ipv6 = 0; int ret; /* Parse args required to build the message */ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { if (unformat (input, "ipv6")){ is_ipv6 = 1; }else if (unformat (input, "ipv4")){ is_ipv6 = 0; }else{ break; } } /* Construct the API message */ M(OOR_PKT_MISS_GET_DEFAULT_ROUTE, mp); mp->is_ipv6 = is_ipv6; /* send it... */ S(mp); /* Wait for a reply... */ W(ret); return (ret); } /* * List of messages that the api test plugin sends, * and that the data plane plugin processes */ #define foreach_vpe_api_msg \ _(oor_pkt_miss_enable_disable, " [disable]") \ _(oor_pkt_miss_native_route, "[add|del] /") \ _(oor_pkt_miss_drop_route, "[add|del] /") \ _(oor_pkt_miss_get_default_route, "[ipv4|ipv6]") static void oor_pkt_miss_vat_api_hookup (vat_main_t *vam) { oor_pkt_miss_test_main_t * sm __attribute__((unused)) = &oor_pkt_miss_test_main; /* Hook up handlers for replies from the data plane plug-in */ #define _(N,n) \ vl_msg_api_set_handlers((VL_API_##N + sm->msg_id_base), \ #n, \ vl_api_##n##_t_handler, \ vl_noop_handler, \ vl_api_##n##_t_endian, \ vl_api_##n##_t_print, \ sizeof(vl_api_##n##_t), 1); foreach_vpe_api_reply_msg; #undef _ /* API messages we can send */ #define _(n,h) hash_set_mem (vam->function_by_name, #n, api_##n); foreach_vpe_api_msg; #undef _ /* Help strings */ #define _(n,h) hash_set_mem (vam->help_by_name, #n, h); foreach_vpe_api_msg; #undef _ } clib_error_t * vat_plugin_register (vat_main_t *vam) { oor_pkt_miss_test_main_t * sm = &oor_pkt_miss_test_main; u8 * name; sm->vat_main = vam; /* Ask the vpp engine for the first assigned message-id */ name = format (0, "oor_pkt_miss_%08x%c", api_version, 0); sm->msg_id_base = vl_client_get_first_plugin_msg_id ((char *) name); if (sm->msg_id_base != (u16) ~0) oor_pkt_miss_vat_api_hookup (vam); vec_free(name); return 0; } oor-1.2.0/VPP/vpp.patch000066400000000000000000000132231313612200500145760ustar00rootroot00000000000000diff --git a/src/vnet/ip/ip4_forward.c b/src/vnet/ip/ip4_forward.c index 7352c2e..a0b8f2f 100644 --- a/src/vnet/ip/ip4_forward.c +++ b/src/vnet/ip/ip4_forward.c @@ -1688,17 +1688,17 @@ ip4_local_inline (vlib_main_t * vm, error0 = ((error0 == IP4_ERROR_UNKNOWN_PROTOCOL && dpo0->dpoi_type == DPO_RECEIVE) ? IP4_ERROR_SPOOFED_LOCAL_PACKETS : error0); - error0 = ((error0 == IP4_ERROR_UNKNOWN_PROTOCOL && - !fib_urpf_check_size (lb0->lb_urpf) && - ip0->dst_address.as_u32 != 0xFFFFFFFF) - ? IP4_ERROR_SRC_LOOKUP_MISS : error0); +// error0 = ((error0 == IP4_ERROR_UNKNOWN_PROTOCOL && +// !fib_urpf_check_size (lb0->lb_urpf) && +// ip0->dst_address.as_u32 != 0xFFFFFFFF) +// ? IP4_ERROR_SRC_LOOKUP_MISS : error0); error1 = ((error1 == IP4_ERROR_UNKNOWN_PROTOCOL && dpo1->dpoi_type == DPO_RECEIVE) ? IP4_ERROR_SPOOFED_LOCAL_PACKETS : error1); - error1 = ((error1 == IP4_ERROR_UNKNOWN_PROTOCOL && - !fib_urpf_check_size (lb1->lb_urpf) && - ip1->dst_address.as_u32 != 0xFFFFFFFF) - ? IP4_ERROR_SRC_LOOKUP_MISS : error1); +// error1 = ((error1 == IP4_ERROR_UNKNOWN_PROTOCOL && +// !fib_urpf_check_size (lb1->lb_urpf) && +// ip1->dst_address.as_u32 != 0xFFFFFFFF) +// ? IP4_ERROR_SRC_LOOKUP_MISS : error1); skip_checks: @@ -1846,10 +1846,10 @@ ip4_local_inline (vlib_main_t * vm, error0 = ((error0 == IP4_ERROR_UNKNOWN_PROTOCOL && dpo0->dpoi_type == DPO_RECEIVE) ? IP4_ERROR_SPOOFED_LOCAL_PACKETS : error0); - error0 = ((error0 == IP4_ERROR_UNKNOWN_PROTOCOL && - !fib_urpf_check_size (lb0->lb_urpf) && - ip0->dst_address.as_u32 != 0xFFFFFFFF) - ? IP4_ERROR_SRC_LOOKUP_MISS : error0); +// error0 = ((error0 == IP4_ERROR_UNKNOWN_PROTOCOL && +// !fib_urpf_check_size (lb0->lb_urpf) && +// ip0->dst_address.as_u32 != 0xFFFFFFFF) +// ? IP4_ERROR_SRC_LOOKUP_MISS : error0); skip_check: @@ -2461,7 +2461,6 @@ ip4_rewrite_inline (vlib_main_t * vm, } /* Verify checksum. */ - ASSERT (ip0->checksum == ip4_header_checksum (ip0)); ASSERT (ip1->checksum == ip4_header_checksum (ip1)); } else diff --git a/src/vnet/ip/ip6_forward.c b/src/vnet/ip/ip6_forward.c index 15970da..0bcb23a 100644 --- a/src/vnet/ip/ip6_forward.c +++ b/src/vnet/ip/ip6_forward.c @@ -1389,20 +1389,20 @@ ip6_local (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) /* Drop packets from unroutable hosts. */ /* If this is a neighbor solicitation (ICMP), skip source RPF check */ - if (error0 == IP6_ERROR_UNKNOWN_PROTOCOL && - type0 != IP_BUILTIN_PROTOCOL_ICMP && - !ip6_address_is_link_local_unicast (&ip0->src_address)) - { - error0 = (!ip6_urpf_loose_check (im, p0, ip0) - ? IP6_ERROR_SRC_LOOKUP_MISS : error0); - } - if (error1 == IP6_ERROR_UNKNOWN_PROTOCOL && - type1 != IP_BUILTIN_PROTOCOL_ICMP && - !ip6_address_is_link_local_unicast (&ip1->src_address)) - { - error1 = (!ip6_urpf_loose_check (im, p1, ip1) - ? IP6_ERROR_SRC_LOOKUP_MISS : error1); - } +// if (error0 == IP6_ERROR_UNKNOWN_PROTOCOL && +// type0 != IP_BUILTIN_PROTOCOL_ICMP && +// !ip6_address_is_link_local_unicast (&ip0->src_address)) +// { +// error0 = (!ip6_urpf_loose_check (im, p0, ip0) +// ? IP6_ERROR_SRC_LOOKUP_MISS : error0); +// } +// if (error1 == IP6_ERROR_UNKNOWN_PROTOCOL && +// type1 != IP_BUILTIN_PROTOCOL_ICMP && +// !ip6_address_is_link_local_unicast (&ip1->src_address)) +// { +// error1 = (!ip6_urpf_loose_check (im, p1, ip1) +// ? IP6_ERROR_SRC_LOOKUP_MISS : error1); +// } next0 = error0 != IP6_ERROR_UNKNOWN_PROTOCOL ? IP_LOCAL_NEXT_DROP : next0; @@ -1485,13 +1485,13 @@ ip6_local (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) (!good_l4_checksum0 ? IP6_ERROR_UDP_CHECKSUM + type0 : error0); /* If this is a neighbor solicitation (ICMP), skip source RPF check */ - if (error0 == IP6_ERROR_UNKNOWN_PROTOCOL && - type0 != IP_BUILTIN_PROTOCOL_ICMP && - !ip6_address_is_link_local_unicast (&ip0->src_address)) - { - error0 = (!ip6_urpf_loose_check (im, p0, ip0) - ? IP6_ERROR_SRC_LOOKUP_MISS : error0); - } +// if (error0 == IP6_ERROR_UNKNOWN_PROTOCOL && +// type0 != IP_BUILTIN_PROTOCOL_ICMP && +// !ip6_address_is_link_local_unicast (&ip0->src_address)) +// { +// error0 = (!ip6_urpf_loose_check (im, p0, ip0) +// ? IP6_ERROR_SRC_LOOKUP_MISS : error0); +// } next0 = error0 != IP6_ERROR_UNKNOWN_PROTOCOL ? IP_LOCAL_NEXT_DROP : next0; diff --git a/src/vnet/lisp-cp/control.c b/src/vnet/lisp-cp/control.c index ebbd1be..a9f7ee3 100644 --- a/src/vnet/lisp-cp/control.c +++ b/src/vnet/lisp-cp/control.c @@ -3601,9 +3601,9 @@ lisp_cp_init (vlib_main_t * vm) hash_set (lcm->table_id_by_vni, 0, 0); hash_set (lcm->vni_by_table_id, 0, 0); - udp_register_dst_port (vm, UDP_DST_PORT_lisp_cp, + udp_register_dst_port (vm, 4343, lisp_cp_input_node.index, 1 /* is_ip4 */ ); - udp_register_dst_port (vm, UDP_DST_PORT_lisp_cp6, + udp_register_dst_port (vm, 4343, lisp_cp_input_node.index, 0 /* is_ip4 */ ); u64 now = clib_cpu_time_now (); diff --git a/src/vnet/lisp-cp/lisp_cp_dpo.c b/src/vnet/lisp-cp/lisp_cp_dpo.c index 848f621..615d3ff 100644 --- a/src/vnet/lisp-cp/lisp_cp_dpo.c +++ b/src/vnet/lisp-cp/lisp_cp_dpo.c @@ -65,12 +65,12 @@ const static dpo_vft_t lisp_cp_vft = { * parent object in the DPO-graph. */ const static char *const lisp_cp_ip4_nodes[] = { - "lisp-cp-lookup-ip4", + "oor_pkt_miss", NULL, }; const static char *const lisp_cp_ip6_nodes[] = { - "lisp-cp-lookup-ip6", + "oor_pkt_miss", NULL, }; oor-1.2.0/netconf/000077500000000000000000000000001313612200500137365ustar00rootroot00000000000000oor-1.2.0/netconf/README000066400000000000000000000042001313612200500146120ustar00rootroot00000000000000LIBNETCONF & NETOPEER INSTALLATION ================================== #Install dependences sudo apt-get install libxslt1-dev libssh2-1-dev libcurl4-gnutls-dev xsltproc libdbus-1-dev libreadline-dev #Install PYANG git clone https://github.com/mbj4668/pyang.git cd pyang/ sudo python setup.py install #Install libnetconf 0.9.x git clone https://github.com/CESNET/libnetconf.git -b 0.9.x cd libnetconf/ ./configure && make && sudo make install #Install netopeer-server for libnetconf 0.9.x git clone https://github.com/CESNET/netopeer.git -b libnetconf-0.9.x cd netopeer/server ./configure && make && sudo make install # Install netopeer-cli if you want to use netooper client cd ../cli/ ./configure && make && sudo make install #Use netopeer-configurator to configure allowed users and permissions OOR MODULE INSTALLATION ======================= #Full instructions at https://github.com/CESNET/libnetconf/blob/master/doc/doxygen/html/d9/d25/transapi.html #Before installing the module, netopeer-server should have been started at least one time to create the database #Move to 'netconf' folder cd ./neteconf #Remove any previous instances sudo netopeer-manager rm --name lispsimple #Create skeleton files lnctool --model ./lispsimple.yang transapi --paths ./lispsimple.paths #Configure autoreconf && ./configure #Replace skeleton files cp oor_lispsimple.c lispsimple.c && cp oor_Makefile Makefile #Compile and install make clean && make && sudo make install && ./libtool --finish /usr/local/lib #Add the module to the server sudo netopeer-manager add --name lispsimple --model ./lispsimple.yin --transapi /usr/local/lib/lispsimple.so --datastore ./datastore.xml #Import the dependences sudo netopeer-manager add --name lispsimple --import ./iana-afn-safi.yin CONFIGURE OOR USING NETCONF =========================== #Start oor. The minimum configuration required by OOR is the operating-mode. It should be xTR or MN. sudo oor #Run the server sudo netopeer-server #Use any netconf client to configure OOR. The easiest one to test the system is netopeer-cli. #To check the possible parameters to be configured, have a look at the file netconf.conf.example oor-1.2.0/netconf/datastore.xml000077500000000000000000000002731313612200500164530ustar00rootroot00000000000000 oor-1.2.0/netconf/iana-afn-safi.yang000077500000000000000000000336511313612200500172230ustar00rootroot00000000000000module iana-afn-safi { namespace "urn:ietf:params:xml:ns:yang:iana-afn-safi"; prefix "ianaaf"; organization "IANA"; contact " Internet Assigned Numbers Authority Postal: ICANN 4676 Admiralty Way, Suite 330 Marina del Rey, CA 90292 Tel: +1 310 823 9358 E-Mail: iana&iana.org"; description "This YANG module provides two typedefs containing YANG definitions for the following IANA-registered enumerations: - Address Family Numbers (AFN) - Subsequent Address Family Identifiers (SAFI) The latest revision of this YANG module can be obtained from the IANA web site. Copyright (c) 2012 IETF Trust and the persons identified as authors of the code. All rights reserved. Redistribution and use in source and binary forms, with or without modification, is permitted pursuant to, and subject to the license terms contained in, the Simplified BSD License set forth in Section 4.c of the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info). This version of this YANG module is part of RFC XXXX; see the RFC itself for full legal notices."; // RFC Ed.: replace XXXX with actual RFC number and remove this // note. // RFC Ed.: update the date below with the date of RFC publication // and remove this note. revision 2013-07-04 { description "Initial revision."; reference "RFC XXXX: IANA Address Family Numbers and Subsequent Address Family Identifiers YANG Module"; } typedef address-family { type enumeration { // value 0 is reserved by IANA enum ipV4 { value "1"; description "IP version 4"; } enum ipV6 { value "2"; description "IP version 6"; } enum nsap { value "3"; description "NSAP"; } enum hdlc { value "4"; description "HDLC (8-bit multidrop)"; } enum bbn1822 { value "5"; description "BBN 1822"; } enum all802 { value "6"; description "802 (includes all 802 media plus Ethernet 'canonical format')"; } enum e163 { value "7"; description "E.163"; } enum e164 { value "8"; description "E.164 (SMDS, FrameRelay, ATM)"; } enum f69 { value "9"; description "F.69 (Telex)"; } enum x121 { value "10"; description "X.121 (X.25, Frame Relay)"; } enum ipx { value "11"; description "IPX (Internetwork Packet Exchange)"; } enum appletalk { value "12"; description "Appletalk"; } enum decnetIV { value "13"; description "DECnet IV"; } enum banyanVines { value "14"; description "Banyan Vines"; } enum e164withNsap { value "15"; description "E.164 with NSAP format subaddress"; reference "ATM Forum UNI 3.1"; } enum dns { value "16"; description "DNS (Domain Name System)"; } enum distinguishedName { value "17"; description "Distinguished Name (per X.500)"; } enum asNumber { value "18"; description "Autonomous System Number"; } enum xtpOverIpv4 { value "19"; description "XTP over IP version 4"; } enum xtpOverIpv6 { value "20"; description "XTP over IP version 6"; } enum xtpNativeModeXTP { value "21"; description "XTP native mode XTP"; } enum fibreChannelWWPN { value "22"; description "Fibre Channel World-Wide Port Name"; } enum fibreChannelWWNN { value "23"; description "Fibre Channel World-Wide Node Name"; } enum gwid { value "24"; description "Gateway Identifier"; } // FIXME: This one is actually called "afi" in the MIB, but // that must be a mistake. enum l2vpn { value "25"; description "AFI for L2VPN information"; reference "RFC 4761: Virtual Private LAN Service (VPLS): Using BGP for Auto-Discovery and Signaling RFC 6074: Provisioning, Auto-Discovery, and Signaling in Layer 2 Virtual Private Networks (L2VPNs)"; } enum mplsTpSectionEndpointIdentifier { value "26"; description "MPLS-TP Section Endpoint Identifier"; reference "draft-ietf-mpls-gach-adv"; } enum mplsTpLspEndpointIdentifier { value "27"; description "MPLS-TP LSP Endpoint Identifier"; reference "draft-ietf-mpls-gach-adv"; } enum mplsTpPseudowireEndpointIdentifier { value "28"; description "MPLS-TP Pseudowire Endpoint Identifier"; reference "draft-ietf-mpls-gach-adv"; } enum eigrpCommonServiceFamily { value "16384"; description "EIGRP Common Service Family"; } enum eigrpIpv4ServiceFamily { value "16385"; description "EIGRP IPv4 Service Family"; } enum eigrpIpv6ServiceFamily { value "16386"; description "EIGRP IPv6 Service Family"; } enum lispCanonicalAddressFormat { value "16387"; description "LISP Canonical Address Format (LCAF)"; } enum bgpLs { value "16388"; description "BGP-LS"; reference "draft-ietf-idr-ls-distribution"; } enum 48BitMac { value "16389"; description "48-bit MAC"; reference "draft-eastlake-rfc5342bis"; } enum 64BitMac { value "16390"; description "64-bit MAC"; reference "draft-eastlake-rfc5342bis"; } // value 65535 is reserved by IANA } description "This typedef is a YANG enumeration of IANA-registered address family numbers (AFN)."; reference "IANA Address Family Numbers registry. "; } typedef subsequent-address-family { type enumeration { // value 0 is reserved by IANA enum nlriUnicast { value "1"; description "Network Layer Reachability Information used for unicast forwarding"; reference "RFC 4760: Multiprotocol Extensions for BGP-4"; } enum nlriMulticast { value "2"; description "Network Layer Reachability Information used for multicast forwarding"; reference "RFC 4760: Multiprotocol Extensions for BGP-4"; } // value 3 is reserved by IANA enum nlriMpls { value "4"; description "Network Layer Reachability Information (NLRI) with MPLS Labels"; reference "RFC 3107: Carrying Label Information in BGP-4"; } enum mcastVpn { value "5"; description "MCAST-VPN"; reference "RFC 6514: BGP Encodings and Procedures for Multicast in MPLS/BGP IP VPNs"; } enum nlriDynamicMsPw { value "6"; status "obsolete"; description "Network Layer Reachability Information used for Dynamic Placement of Multi-Segment Pseudowires (TEMPORARY - Expires 2008-08-23)"; reference "draft-ietf-pwe3-dynamic-ms-pw: Dynamic Placement of Multi Segment Pseudowires"; } enum encapsulation { value "7"; description "Encapsulation SAFI"; reference "RFC 5512: The BGP Encapsulation Subsequent Address Family Identifier (SAFI) and the BGP Tunnel Encapsulation Attribute"; } enum tunnel { value "64"; status "obsolete"; description "Tunnel SAFI"; reference "draft-nalawade-kapoor-tunnel-safi: BGP Tunnel SAFI"; } enum vpls { value "65"; description "Virtual Private LAN Service (VPLS)"; reference "RFC 4761: Virtual Private LAN Service (VPLS): Using BGP for Auto-Discovery and Signaling RFC 6074: Provisioning, Auto-Discovery, and Signaling in Layer 2 Virtual Private Networks (L2VPNs)"; } enum bgpMdt { value "66"; description "BGP MDT SAFI"; reference "RFC 6037: Cisco Systems' Solution for Multicast in BGP/MPLS IP VPNs"; } enum bgp4over6 { value "67"; description "BGP 4over6 SAFI"; reference "RFC 5747: 4over6 Transit Solution Using IP Encapsulation and MP-BGP Extensions"; } enum bgp6over4 { value "68"; description "BGP 6over4 SAFI"; } enum l1VpnAutoDiscovery { value "69"; description "Layer-1 VPN auto-discovery information"; reference "RFC 5195: BGP-Based Auto-Discovery for Layer-1 VPNs"; } enum mplsVpn { value "128"; description "MPLS-labeled VPN address"; reference "RFC 4364: BGP/MPLS IP Virtual Private Networks (VPNs)"; } enum multicastBgpMplsVpn { value "129"; description "Multicast for BGP/MPLS IP Virtual Private Networks (VPNs)"; reference "RFC 6513: Multicast in MPLS/BGP IP VPNs RFC 6514: BGP Encodings and Procedures for Multicast in MPLS/BGP IP VPNs"; } // values 130-131 are reserved by IANA enum routeTargetConstraints { value "132"; description "Route Target constraints"; reference "RFC 4684: Constrained Route Distribution for Border Gateway Protocol/MultiProtocol Label Switching (BGP/MPLS) Internet Protocol (IP) Virtual Private Networks (VPNs)"; } enum ipv4DissFlow { value "133"; description "IPv4 dissemination of flow specification rules"; reference "RFC 5575: Dissemination of Flow Specification Rules"; } enum vpnv4DissFlow { value "134"; description "VPNv4 dissemination of flow specification rules"; reference "RFC 5575: Dissemination of Flow Specification Rules"; } // values 135-139 are reserved by IANA enum vpnAutoDiscovery { value "140"; status "obsolete"; description "VPN auto-discovery"; reference "draft-ietf-l3vpn-bgpvpn-auto: Using BGP as an Auto-Discovery Mechanism for VR-based Layer-3 VPNs"; } // values 141-240 are reserved by IANA enum private241 { value "241"; description "Reserved for Private Use"; reference "RFC 4760: Multiprotocol Extensions for BGP-4"; } enum private242 { value "242"; description "Reserved for Private Use"; reference "RFC 4760: Multiprotocol Extensions for BGP-4"; } enum private243 { value "243"; description "Reserved for Private Use"; reference "RFC 4760: Multiprotocol Extensions for BGP-4"; } enum private244 { value "244"; description "Reserved for Private Use"; reference "RFC 4760: Multiprotocol Extensions for BGP-4"; } enum private245 { value "245"; description "Reserved for Private Use"; reference "RFC 4760: Multiprotocol Extensions for BGP-4"; } enum private246 { value "246"; description "Reserved for Private Use"; reference "RFC 4760: Multiprotocol Extensions for BGP-4"; } enum private247 { value "247"; description "Reserved for Private Use"; reference "RFC 4760: Multiprotocol Extensions for BGP-4"; } enum private248 { value "248"; description "Reserved for Private Use"; reference "RFC 4760: Multiprotocol Extensions for BGP-4"; } enum private249 { value "249"; description "Reserved for Private Use"; reference "RFC 4760: Multiprotocol Extensions for BGP-4"; } enum private250 { value "250"; description "Reserved for Private Use"; reference "RFC 4760: Multiprotocol Extensions for BGP-4"; } enum private251 { value "251"; description "Reserved for Private Use"; reference "RFC 4760: Multiprotocol Extensions for BGP-4"; } enum private252 { value "252"; description "Reserved for Private Use"; reference "RFC 4760: Multiprotocol Extensions for BGP-4"; } enum private253 { value "253"; description "Reserved for Private Use"; reference "RFC 4760: Multiprotocol Extensions for BGP-4"; } enum private254 { value "254"; description "Reserved for Private Use"; reference "RFC 4760: Multiprotocol Extensions for BGP-4"; } // value 255 is reserved by IANA } description "This typedef is a YANG enumeration of IANA-registered subsequent address family identifiers (SAFI)."; reference "IANA SAFI Values registry. "; } } oor-1.2.0/netconf/iana-afn-safi.yin000077500000000000000000000446411313612200500170650ustar00rootroot00000000000000 IANA Internet Assigned Numbers Authority Postal: ICANN 4676 Admiralty Way, Suite 330 Marina del Rey, CA 90292 Tel: +1 310 823 9358 E-Mail: iana&iana.org This YANG module provides two typedefs containing YANG definitions for the following IANA-registered enumerations: - Address Family Numbers (AFN) - Subsequent Address Family Identifiers (SAFI) The latest revision of this YANG module can be obtained from the IANA web site. Copyright (c) 2012 IETF Trust and the persons identified as authors of the code. All rights reserved. Redistribution and use in source and binary forms, with or without modification, is permitted pursuant to, and subject to the license terms contained in, the Simplified BSD License set forth in Section 4.c of the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info). This version of this YANG module is part of RFC XXXX; see the RFC itself for full legal notices. Initial revision. RFC XXXX: IANA Address Family Numbers and Subsequent Address Family Identifiers YANG Module IP version 4 IP version 6 NSAP HDLC (8-bit multidrop) BBN 1822 802 (includes all 802 media plus Ethernet 'canonical format') E.163 E.164 (SMDS, FrameRelay, ATM) F.69 (Telex) X.121 (X.25, Frame Relay) IPX (Internetwork Packet Exchange) Appletalk DECnet IV Banyan Vines E.164 with NSAP format subaddress ATM Forum UNI 3.1 DNS (Domain Name System) Distinguished Name (per X.500) Autonomous System Number XTP over IP version 4 XTP over IP version 6 XTP native mode XTP Fibre Channel World-Wide Port Name Fibre Channel World-Wide Node Name Gateway Identifier AFI for L2VPN information RFC 4761: Virtual Private LAN Service (VPLS): Using BGP for Auto-Discovery and Signaling RFC 6074: Provisioning, Auto-Discovery, and Signaling in Layer 2 Virtual Private Networks (L2VPNs) MPLS-TP Section Endpoint Identifier draft-ietf-mpls-gach-adv MPLS-TP LSP Endpoint Identifier draft-ietf-mpls-gach-adv MPLS-TP Pseudowire Endpoint Identifier draft-ietf-mpls-gach-adv EIGRP Common Service Family EIGRP IPv4 Service Family EIGRP IPv6 Service Family LISP Canonical Address Format (LCAF) BGP-LS draft-ietf-idr-ls-distribution 48-bit MAC draft-eastlake-rfc5342bis 64-bit MAC draft-eastlake-rfc5342bis This typedef is a YANG enumeration of IANA-registered address family numbers (AFN). IANA Address Family Numbers registry. <http://www.iana.org/assignments/address-family-numbers> Network Layer Reachability Information used for unicast forwarding RFC 4760: Multiprotocol Extensions for BGP-4 Network Layer Reachability Information used for multicast forwarding RFC 4760: Multiprotocol Extensions for BGP-4 Network Layer Reachability Information (NLRI) with MPLS Labels RFC 3107: Carrying Label Information in BGP-4 MCAST-VPN RFC 6514: BGP Encodings and Procedures for Multicast in MPLS/BGP IP VPNs Network Layer Reachability Information used for Dynamic Placement of Multi-Segment Pseudowires (TEMPORARY - Expires 2008-08-23) draft-ietf-pwe3-dynamic-ms-pw: Dynamic Placement of Multi Segment Pseudowires Encapsulation SAFI RFC 5512: The BGP Encapsulation Subsequent Address Family Identifier (SAFI) and the BGP Tunnel Encapsulation Attribute Tunnel SAFI draft-nalawade-kapoor-tunnel-safi: BGP Tunnel SAFI Virtual Private LAN Service (VPLS) RFC 4761: Virtual Private LAN Service (VPLS): Using BGP for Auto-Discovery and Signaling RFC 6074: Provisioning, Auto-Discovery, and Signaling in Layer 2 Virtual Private Networks (L2VPNs) BGP MDT SAFI RFC 6037: Cisco Systems' Solution for Multicast in BGP/MPLS IP VPNs BGP 4over6 SAFI RFC 5747: 4over6 Transit Solution Using IP Encapsulation and MP-BGP Extensions BGP 6over4 SAFI Layer-1 VPN auto-discovery information RFC 5195: BGP-Based Auto-Discovery for Layer-1 VPNs MPLS-labeled VPN address RFC 4364: BGP/MPLS IP Virtual Private Networks (VPNs) Multicast for BGP/MPLS IP Virtual Private Networks (VPNs) RFC 6513: Multicast in MPLS/BGP IP VPNs RFC 6514: BGP Encodings and Procedures for Multicast in MPLS/BGP IP VPNs Route Target constraints RFC 4684: Constrained Route Distribution for Border Gateway Protocol/MultiProtocol Label Switching (BGP/MPLS) Internet Protocol (IP) Virtual Private Networks (VPNs) IPv4 dissemination of flow specification rules RFC 5575: Dissemination of Flow Specification Rules VPNv4 dissemination of flow specification rules RFC 5575: Dissemination of Flow Specification Rules VPN auto-discovery draft-ietf-l3vpn-bgpvpn-auto: Using BGP as an Auto-Discovery Mechanism for VR-based Layer-3 VPNs Reserved for Private Use RFC 4760: Multiprotocol Extensions for BGP-4 Reserved for Private Use RFC 4760: Multiprotocol Extensions for BGP-4 Reserved for Private Use RFC 4760: Multiprotocol Extensions for BGP-4 Reserved for Private Use RFC 4760: Multiprotocol Extensions for BGP-4 Reserved for Private Use RFC 4760: Multiprotocol Extensions for BGP-4 Reserved for Private Use RFC 4760: Multiprotocol Extensions for BGP-4 Reserved for Private Use RFC 4760: Multiprotocol Extensions for BGP-4 Reserved for Private Use RFC 4760: Multiprotocol Extensions for BGP-4 Reserved for Private Use RFC 4760: Multiprotocol Extensions for BGP-4 Reserved for Private Use RFC 4760: Multiprotocol Extensions for BGP-4 Reserved for Private Use RFC 4760: Multiprotocol Extensions for BGP-4 Reserved for Private Use RFC 4760: Multiprotocol Extensions for BGP-4 Reserved for Private Use RFC 4760: Multiprotocol Extensions for BGP-4 Reserved for Private Use RFC 4760: Multiprotocol Extensions for BGP-4 This typedef is a YANG enumeration of IANA-registered subsequent address family identifiers (SAFI). IANA SAFI Values registry. <http://www.iana.org/assignments/safi-namespace> oor-1.2.0/netconf/ietf-inet-types.yang000066400000000000000000000370741313612200500176570ustar00rootroot00000000000000module ietf-inet-types { namespace "urn:ietf:params:xml:ns:yang:ietf-inet-types"; prefix "inet"; organization "IETF NETMOD (NETCONF Data Modeling Language) Working Group"; contact "WG Web: WG List: WG Chair: David Partain WG Chair: David Kessens Editor: Juergen Schoenwaelder "; description "This module contains a collection of generally useful derived YANG data types for Internet addresses and related things. Copyright (c) 2010 IETF Trust and the persons identified as authors of the code. All rights reserved. Redistribution and use in source and binary forms, with or without modification, is permitted pursuant to, and subject to the license terms contained in, the Simplified BSD License set forth in Section 4.c of the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info). This version of this YANG module is part of RFC 6021; see the RFC itself for full legal notices."; revision 2010-09-24 { description "Initial revision."; reference "RFC 6021: Common YANG Data Types"; } /*** collection of protocol field related types ***/ typedef ip-version { type enumeration { enum unknown { value "0"; description "An unknown or unspecified version of the Internet protocol."; } enum ipv4 { value "1"; description "The IPv4 protocol as defined in RFC 791."; } enum ipv6 { value "2"; description "The IPv6 protocol as defined in RFC 2460."; } } description "This value represents the version of the IP protocol. In the value set and its semantics, this type is equivalent to the InetVersion textual convention of the SMIv2."; reference "RFC 791: Internet Protocol RFC 2460: Internet Protocol, Version 6 (IPv6) Specification RFC 4001: Textual Conventions for Internet Network Addresses"; } typedef dscp { type uint8 { range "0..63"; } description "The dscp type represents a Differentiated Services Code-Point that may be used for marking packets in a traffic stream. In the value set and its semantics, this type is equivalent to the Dscp textual convention of the SMIv2."; reference "RFC 3289: Management Information Base for the Differentiated Services Architecture RFC 2474: Definition of the Differentiated Services Field (DS Field) in the IPv4 and IPv6 Headers RFC 2780: IANA Allocation Guidelines For Values In the Internet Protocol and Related Headers"; } typedef ipv6-flow-label { type uint32 { range "0..1048575"; } description "The flow-label type represents flow identifier or Flow Label in an IPv6 packet header that may be used to discriminate traffic flows. In the value set and its semantics, this type is equivalent to the IPv6FlowLabel textual convention of the SMIv2."; reference "RFC 3595: Textual Conventions for IPv6 Flow Label RFC 2460: Internet Protocol, Version 6 (IPv6) Specification"; } typedef port-number { type uint16 { range "0..65535"; } description "The port-number type represents a 16-bit port number of an Internet transport layer protocol such as UDP, TCP, DCCP, or SCTP. Port numbers are assigned by IANA. A current list of all assignments is available from . Note that the port number value zero is reserved by IANA. In situations where the value zero does not make sense, it can be excluded by subtyping the port-number type. In the value set and its semantics, this type is equivalent to the InetPortNumber textual convention of the SMIv2."; reference "RFC 768: User Datagram Protocol RFC 793: Transmission Control Protocol RFC 4960: Stream Control Transmission Protocol RFC 4340: Datagram Congestion Control Protocol (DCCP) RFC 4001: Textual Conventions for Internet Network Addresses"; } /*** collection of autonomous system related types ***/ typedef as-number { type uint32; description "The as-number type represents autonomous system numbers which identify an Autonomous System (AS). An AS is a set of routers under a single technical administration, using an interior gateway protocol and common metrics to route packets within the AS, and using an exterior gateway protocol to route packets to other ASs'. IANA maintains the AS number space and has delegated large parts to the regional registries. Autonomous system numbers were originally limited to 16 bits. BGP extensions have enlarged the autonomous system number space to 32 bits. This type therefore uses an uint32 base type without a range restriction in order to support a larger autonomous system number space. In the value set and its semantics, this type is equivalent to the InetAutonomousSystemNumber textual convention of the SMIv2."; reference "RFC 1930: Guidelines for creation, selection, and registration of an Autonomous System (AS) RFC 4271: A Border Gateway Protocol 4 (BGP-4) RFC 4893: BGP Support for Four-octet AS Number Space RFC 4001: Textual Conventions for Internet Network Addresses"; } /*** collection of IP address and hostname related types ***/ typedef ip-address { type union { type inet:ipv4-address; type inet:ipv6-address; } description "The ip-address type represents an IP address and is IP version neutral. The format of the textual representations implies the IP version."; } typedef ipv4-address { type string { pattern '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}' + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])' + '(%[\p{N}\p{L}]+)?'; } description "The ipv4-address type represents an IPv4 address in dotted-quad notation. The IPv4 address may include a zone index, separated by a % sign. The zone index is used to disambiguate identical address values. For link-local addresses, the zone index will typically be the interface index number or the name of an interface. If the zone index is not present, the default zone of the device will be used. The canonical format for the zone index is the numerical format"; } typedef ipv6-address { type string { pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}' + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|' + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}' + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))' + '(%[\p{N}\p{L}]+)?'; pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|' + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)' + '(%.+)?'; } description "The ipv6-address type represents an IPv6 address in full, mixed, shortened, and shortened-mixed notation. The IPv6 address may include a zone index, separated by a % sign. The zone index is used to disambiguate identical address values. For link-local addresses, the zone index will typically be the interface index number or the name of an interface. If the zone index is not present, the default zone of the device will be used. The canonical format of IPv6 addresses uses the compressed format described in RFC 4291, Section 2.2, item 2 with the following additional rules: the :: substitution must be applied to the longest sequence of all-zero 16-bit chunks in an IPv6 address. If there is a tie, the first sequence of all-zero 16-bit chunks is replaced by ::. Single all-zero 16-bit chunks are not compressed. The canonical format uses lowercase characters and leading zeros are not allowed. The canonical format for the zone index is the numerical format as described in RFC 4007, Section 11.2."; reference "RFC 4291: IP Version 6 Addressing Architecture RFC 4007: IPv6 Scoped Address Architecture RFC 5952: A Recommendation for IPv6 Address Text Representation"; } typedef ip-prefix { type union { type inet:ipv4-prefix; type inet:ipv6-prefix; } description "The ip-prefix type represents an IP prefix and is IP version neutral. The format of the textual representations implies the IP version."; } typedef ipv4-prefix { type string { pattern '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}' + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])' + '/(([0-9])|([1-2][0-9])|(3[0-2]))'; } description "The ipv4-prefix type represents an IPv4 address prefix. The prefix length is given by the number following the slash character and must be less than or equal to 32. A prefix length value of n corresponds to an IP address mask that has n contiguous 1-bits from the most significant bit (MSB) and all other bits set to 0. The canonical format of an IPv4 prefix has all bits of the IPv4 address set to zero that are not part of the IPv4 prefix."; } typedef ipv6-prefix { type string { pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}' + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|' + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}' + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))' + '(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))'; pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|' + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)' + '(/.+)'; } description "The ipv6-prefix type represents an IPv6 address prefix. The prefix length is given by the number following the slash character and must be less than or equal 128. A prefix length value of n corresponds to an IP address mask that has n contiguous 1-bits from the most significant bit (MSB) and all other bits set to 0. The IPv6 address should have all bits that do not belong to the prefix set to zero. The canonical format of an IPv6 prefix has all bits of the IPv6 address set to zero that are not part of the IPv6 prefix. Furthermore, IPv6 address is represented in the compressed format described in RFC 4291, Section 2.2, item 2 with the following additional rules: the :: substitution must be applied to the longest sequence of all-zero 16-bit chunks in an IPv6 address. If there is a tie, the first sequence of all-zero 16-bit chunks is replaced by ::. Single all-zero 16-bit chunks are not compressed. The canonical format uses lowercase characters and leading zeros are not allowed."; reference "RFC 4291: IP Version 6 Addressing Architecture"; } /*** collection of domain name and URI types ***/ typedef domain-name { type string { pattern '((([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.)*' + '([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.?)' + '|\.'; length "1..253"; } description "The domain-name type represents a DNS domain name. The name SHOULD be fully qualified whenever possible. Internet domain names are only loosely specified. Section 3.5 of RFC 1034 recommends a syntax (modified in Section 2.1 of RFC 1123). The pattern above is intended to allow for current practice in domain name use, and some possible future expansion. It is designed to hold various types of domain names, including names used for A or AAAA records (host names) and other records, such as SRV records. Note that Internet host names have a stricter syntax (described in RFC 952) than the DNS recommendations in RFCs 1034 and 1123, and that systems that want to store host names in schema nodes using the domain-name type are recommended to adhere to this stricter standard to ensure interoperability. The encoding of DNS names in the DNS protocol is limited to 255 characters. Since the encoding consists of labels prefixed by a length bytes and there is a trailing NULL byte, only 253 characters can appear in the textual dotted notation. The description clause of schema nodes using the domain-name type MUST describe when and how these names are resolved to IP addresses. Note that the resolution of a domain-name value may require to query multiple DNS records (e.g., A for IPv4 and AAAA for IPv6). The order of the resolution process and which DNS record takes precedence can either be defined explicitely or it may depend on the configuration of the resolver. Domain-name values use the US-ASCII encoding. Their canonical format uses lowercase US-ASCII characters. Internationalized domain names MUST be encoded in punycode as described in RFC 3492"; reference "RFC 952: DoD Internet Host Table Specification RFC 1034: Domain Names - Concepts and Facilities RFC 1123: Requirements for Internet Hosts -- Application and Support RFC 2782: A DNS RR for specifying the location of services (DNS SRV) RFC 3492: Punycode: A Bootstring encoding of Unicode for Internationalized Domain Names in Applications (IDNA) RFC 5891: Internationalizing Domain Names in Applications (IDNA): Protocol"; } typedef host { type union { type inet:ip-address; type inet:domain-name; } description "The host type represents either an IP address or a DNS domain name."; } typedef uri { type string; description "The uri type represents a Uniform Resource Identifier (URI) as defined by STD 66. Objects using the uri type MUST be in US-ASCII encoding, and MUST be normalized as described by RFC 3986 Sections 6.2.1, 6.2.2.1, and 6.2.2.2. All unnecessary percent-encoding is removed, and all case-insensitive characters are set to lowercase except for hexadecimal digits, which are normalized to uppercase as described in Section 6.2.2.1. The purpose of this normalization is to help provide unique URIs. Note that this normalization is not sufficient to provide uniqueness. Two URIs that are textually distinct after this normalization may still be equivalent. Objects using the uri type may restrict the schemes that they permit. For example, 'data:' and 'urn:' schemes might not be appropriate. A zero-length URI is not a valid URI. This can be used to express 'URI absent' where required. In the value set and its semantics, this type is equivalent to the Uri SMIv2 textual convention defined in RFC 5017."; reference "RFC 3986: Uniform Resource Identifier (URI): Generic Syntax RFC 3305: Report from the Joint W3C/IETF URI Planning Interest Group: Uniform Resource Identifiers (URIs), URLs, and Uniform Resource Names (URNs): Clarifications and Recommendations RFC 5017: MIB Textual Conventions for Uniform Resource Identifiers (URIs)"; } } oor-1.2.0/netconf/ietf-yang-types.yang000066400000000000000000000430231313612200500176450ustar00rootroot00000000000000module ietf-yang-types { namespace "urn:ietf:params:xml:ns:yang:ietf-yang-types"; prefix "yang"; organization "IETF NETMOD (NETCONF Data Modeling Language) Working Group"; contact "WG Web: WG List: WG Chair: David Kessens WG Chair: Juergen Schoenwaelder Editor: Juergen Schoenwaelder "; description "This module contains a collection of generally useful derived YANG data types. Copyright (c) 2013 IETF Trust and the persons identified as authors of the code. All rights reserved. Redistribution and use in source and binary forms, with or without modification, is permitted pursuant to, and subject to the license terms contained in, the Simplified BSD License set forth in Section 4.c of the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info). This version of this YANG module is part of RFC 6991; see the RFC itself for full legal notices."; revision 2013-07-15 { description "This revision adds the following new data types: - yang-identifier - hex-string - uuid - dotted-quad"; reference "RFC 6991: Common YANG Data Types"; } revision 2010-09-24 { description "Initial revision."; reference "RFC 6021: Common YANG Data Types"; } /*** collection of counter and gauge types ***/ typedef counter32 { type uint32; description "The counter32 type represents a non-negative integer that monotonically increases until it reaches a maximum value of 2^32-1 (4294967295 decimal), when it wraps around and starts increasing again from zero. Counters have no defined 'initial' value, and thus, a single value of a counter has (in general) no information content. Discontinuities in the monotonically increasing value normally occur at re-initialization of the management system, and at other times as specified in the description of a schema node using this type. If such other times can occur, for example, the creation of a schema node of type counter32 at times other than re-initialization, then a corresponding schema node should be defined, with an appropriate type, to indicate the last discontinuity. The counter32 type should not be used for configuration schema nodes. A default statement SHOULD NOT be used in combination with the type counter32. In the value set and its semantics, this type is equivalent to the Counter32 type of the SMIv2."; reference "RFC 2578: Structure of Management Information Version 2 (SMIv2)"; } typedef zero-based-counter32 { type yang:counter32; default "0"; description "The zero-based-counter32 type represents a counter32 that has the defined 'initial' value zero. A schema node of this type will be set to zero (0) on creation and will thereafter increase monotonically until it reaches a maximum value of 2^32-1 (4294967295 decimal), when it wraps around and starts increasing again from zero. Provided that an application discovers a new schema node of this type within the minimum time to wrap, it can use the 'initial' value as a delta. It is important for a management station to be aware of this minimum time and the actual time between polls, and to discard data if the actual time is too long or there is no defined minimum time. In the value set and its semantics, this type is equivalent to the ZeroBasedCounter32 textual convention of the SMIv2."; reference "RFC 4502: Remote Network Monitoring Management Information Base Version 2"; } typedef counter64 { type uint64; description "The counter64 type represents a non-negative integer that monotonically increases until it reaches a maximum value of 2^64-1 (18446744073709551615 decimal), when it wraps around and starts increasing again from zero. Counters have no defined 'initial' value, and thus, a single value of a counter has (in general) no information content. Discontinuities in the monotonically increasing value normally occur at re-initialization of the management system, and at other times as specified in the description of a schema node using this type. If such other times can occur, for example, the creation of a schema node of type counter64 at times other than re-initialization, then a corresponding schema node should be defined, with an appropriate type, to indicate the last discontinuity. The counter64 type should not be used for configuration schema nodes. A default statement SHOULD NOT be used in combination with the type counter64. In the value set and its semantics, this type is equivalent to the Counter64 type of the SMIv2."; reference "RFC 2578: Structure of Management Information Version 2 (SMIv2)"; } typedef zero-based-counter64 { type yang:counter64; default "0"; description "The zero-based-counter64 type represents a counter64 that has the defined 'initial' value zero. A schema node of this type will be set to zero (0) on creation and will thereafter increase monotonically until it reaches a maximum value of 2^64-1 (18446744073709551615 decimal), when it wraps around and starts increasing again from zero. Provided that an application discovers a new schema node of this type within the minimum time to wrap, it can use the 'initial' value as a delta. It is important for a management station to be aware of this minimum time and the actual time between polls, and to discard data if the actual time is too long or there is no defined minimum time. In the value set and its semantics, this type is equivalent to the ZeroBasedCounter64 textual convention of the SMIv2."; reference "RFC 2856: Textual Conventions for Additional High Capacity Data Types"; } typedef gauge32 { type uint32; description "The gauge32 type represents a non-negative integer, which may increase or decrease, but shall never exceed a maximum value, nor fall below a minimum value. The maximum value cannot be greater than 2^32-1 (4294967295 decimal), and the minimum value cannot be smaller than 0. The value of a gauge32 has its maximum value whenever the information being modeled is greater than or equal to its maximum value, and has its minimum value whenever the information being modeled is smaller than or equal to its minimum value. If the information being modeled subsequently decreases below (increases above) the maximum (minimum) value, the gauge32 also decreases (increases). In the value set and its semantics, this type is equivalent to the Gauge32 type of the SMIv2."; reference "RFC 2578: Structure of Management Information Version 2 (SMIv2)"; } typedef gauge64 { type uint64; description "The gauge64 type represents a non-negative integer, which may increase or decrease, but shall never exceed a maximum value, nor fall below a minimum value. The maximum value cannot be greater than 2^64-1 (18446744073709551615), and the minimum value cannot be smaller than 0. The value of a gauge64 has its maximum value whenever the information being modeled is greater than or equal to its maximum value, and has its minimum value whenever the information being modeled is smaller than or equal to its minimum value. If the information being modeled subsequently decreases below (increases above) the maximum (minimum) value, the gauge64 also decreases (increases). In the value set and its semantics, this type is equivalent to the CounterBasedGauge64 SMIv2 textual convention defined in RFC 2856"; reference "RFC 2856: Textual Conventions for Additional High Capacity Data Types"; } /*** collection of identifier-related types ***/ typedef object-identifier { type string { pattern '(([0-1](\.[1-3]?[0-9]))|(2\.(0|([1-9]\d*))))' + '(\.(0|([1-9]\d*)))*'; } description "The object-identifier type represents administratively assigned names in a registration-hierarchical-name tree. Values of this type are denoted as a sequence of numerical non-negative sub-identifier values. Each sub-identifier value MUST NOT exceed 2^32-1 (4294967295). Sub-identifiers are separated by single dots and without any intermediate whitespace. The ASN.1 standard restricts the value space of the first sub-identifier to 0, 1, or 2. Furthermore, the value space of the second sub-identifier is restricted to the range 0 to 39 if the first sub-identifier is 0 or 1. Finally, the ASN.1 standard requires that an object identifier has always at least two sub-identifiers. The pattern captures these restrictions. Although the number of sub-identifiers is not limited, module designers should realize that there may be implementations that stick with the SMIv2 limit of 128 sub-identifiers. This type is a superset of the SMIv2 OBJECT IDENTIFIER type since it is not restricted to 128 sub-identifiers. Hence, this type SHOULD NOT be used to represent the SMIv2 OBJECT IDENTIFIER type; the object-identifier-128 type SHOULD be used instead."; reference "ISO9834-1: Information technology -- Open Systems Interconnection -- Procedures for the operation of OSI Registration Authorities: General procedures and top arcs of the ASN.1 Object Identifier tree"; } typedef object-identifier-128 { type object-identifier { pattern '\d*(\.\d*){1,127}'; } description "This type represents object-identifiers restricted to 128 sub-identifiers. In the value set and its semantics, this type is equivalent to the OBJECT IDENTIFIER type of the SMIv2."; reference "RFC 2578: Structure of Management Information Version 2 (SMIv2)"; } typedef yang-identifier { type string { length "1..max"; pattern '[a-zA-Z_][a-zA-Z0-9\-_.]*'; pattern '.|..|[^xX].*|.[^mM].*|..[^lL].*'; } description "A YANG identifier string as defined by the 'identifier' rule in Section 12 of RFC 6020. An identifier must start with an alphabetic character or an underscore followed by an arbitrary sequence of alphabetic or numeric characters, underscores, hyphens, or dots. A YANG identifier MUST NOT start with any possible combination of the lowercase or uppercase character sequence 'xml'."; reference "RFC 6020: YANG - A Data Modeling Language for the Network Configuration Protocol (NETCONF)"; } /*** collection of types related to date and time***/ typedef date-and-time { type string { pattern '\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?' + '(Z|[\+\-]\d{2}:\d{2})'; } description "The date-and-time type is a profile of the ISO 8601 standard for representation of dates and times using the Gregorian calendar. The profile is defined by the date-time production in Section 5.6 of RFC 3339. The date-and-time type is compatible with the dateTime XML schema type with the following notable exceptions: (a) The date-and-time type does not allow negative years. (b) The date-and-time time-offset -00:00 indicates an unknown time zone (see RFC 3339) while -00:00 and +00:00 and Z all represent the same time zone in dateTime. (c) The canonical format (see below) of data-and-time values differs from the canonical format used by the dateTime XML schema type, which requires all times to be in UTC using the time-offset 'Z'. This type is not equivalent to the DateAndTime textual convention of the SMIv2 since RFC 3339 uses a different separator between full-date and full-time and provides higher resolution of time-secfrac. The canonical format for date-and-time values with a known time zone uses a numeric time zone offset that is calculated using the device's configured known offset to UTC time. A change of the device's offset to UTC time will cause date-and-time values to change accordingly. Such changes might happen periodically in case a server follows automatically daylight saving time (DST) time zone offset changes. The canonical format for date-and-time values with an unknown time zone (usually referring to the notion of local time) uses the time-offset -00:00."; reference "RFC 3339: Date and Time on the Internet: Timestamps RFC 2579: Textual Conventions for SMIv2 XSD-TYPES: XML Schema Part 2: Datatypes Second Edition"; } typedef timeticks { type uint32; description "The timeticks type represents a non-negative integer that represents the time, modulo 2^32 (4294967296 decimal), in hundredths of a second between two epochs. When a schema node is defined that uses this type, the description of the schema node identifies both of the reference epochs. In the value set and its semantics, this type is equivalent to the TimeTicks type of the SMIv2."; reference "RFC 2578: Structure of Management Information Version 2 (SMIv2)"; } typedef timestamp { type yang:timeticks; description "The timestamp type represents the value of an associated timeticks schema node at which a specific occurrence happened. The specific occurrence must be defined in the description of any schema node defined using this type. When the specific occurrence occurred prior to the last time the associated timeticks attribute was zero, then the timestamp value is zero. Note that this requires all timestamp values to be reset to zero when the value of the associated timeticks attribute reaches 497+ days and wraps around to zero. The associated timeticks schema node must be specified in the description of any schema node using this type. In the value set and its semantics, this type is equivalent to the TimeStamp textual convention of the SMIv2."; reference "RFC 2579: Textual Conventions for SMIv2"; } /*** collection of generic address types ***/ typedef phys-address { type string { pattern '([0-9a-fA-F]{2}(:[0-9a-fA-F]{2})*)?'; } description "Represents media- or physical-level addresses represented as a sequence octets, each octet represented by two hexadecimal numbers. Octets are separated by colons. The canonical representation uses lowercase characters. In the value set and its semantics, this type is equivalent to the PhysAddress textual convention of the SMIv2."; reference "RFC 2579: Textual Conventions for SMIv2"; } typedef mac-address { type string { pattern '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'; } description "The mac-address type represents an IEEE 802 MAC address. The canonical representation uses lowercase characters. In the value set and its semantics, this type is equivalent to the MacAddress textual convention of the SMIv2."; reference "IEEE 802: IEEE Standard for Local and Metropolitan Area Networks: Overview and Architecture RFC 2579: Textual Conventions for SMIv2"; } /*** collection of XML-specific types ***/ typedef xpath1.0 { type string; description "This type represents an XPATH 1.0 expression. When a schema node is defined that uses this type, the description of the schema node MUST specify the XPath context in which the XPath expression is evaluated."; reference "XPATH: XML Path Language (XPath) Version 1.0"; } /*** collection of string types ***/ typedef hex-string { type string { pattern '([0-9a-fA-F]{2}(:[0-9a-fA-F]{2})*)?'; } description "A hexadecimal string with octets represented as hex digits separated by colons. The canonical representation uses lowercase characters."; } typedef uuid { type string { pattern '[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-' + '[0-9a-fA-F]{4}-[0-9a-fA-F]{12}'; } description "A Universally Unique IDentifier in the string representation defined in RFC 4122. The canonical representation uses lowercase characters. The following is an example of a UUID in string representation: f81d4fae-7dec-11d0-a765-00a0c91e6bf6 "; reference "RFC 4122: A Universally Unique IDentifier (UUID) URN Namespace"; } typedef dotted-quad { type string { pattern '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}' + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'; } description "An unsigned 32-bit number expressed in the dotted-quad notation, i.e., four octets written as decimal numbers and separated with the '.' (full stop) character."; } } oor-1.2.0/netconf/lispsimple.paths000077500000000000000000000004141313612200500171620ustar00rootroot00000000000000lispsimple=urn:ietf:params:xml:ns:yang:lispsimple /lispsimple:itr-cfg/lispsimple:map-resolvers /lispsimple:itr-cfg/lispsimple:proxy-etrs /lispsimple:etr-cfg/lispsimple:local-eids /lispsimple:etr-cfg/lispsimple:map-servers /lispsimple:rtr-cfg/lispsimple:map-resolvers oor-1.2.0/netconf/lispsimple.yang000077500000000000000000000165001313612200500170040ustar00rootroot00000000000000module lispsimple { namespace "urn:ietf:params:xml:ns:yang:lispsimple"; prefix lispsimple; import ietf-inet-types { prefix inet; } organization "IETF LISP (Locator/ID Separation Protocol) Working Group"; contact "lisp@ietf.org"; description "This YANG module defines the generic configuration data for LISP. The module can be extended by vendors to define vendor-specific LISP configuration parameters and policies. Copyright (c) 2015 IETF Trust and the persons identified as authors of the code. All rights reserved. Redistribution and use in source and binary forms, with or without modification, is permitted pursuant to, and subject to the license terms contained in, the Simplified BSD License set forth in Section 4.c of the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info). This version of this YANG module is part of RFC 6338; see the RFC itself for full legal notices. "; revision 2015-07-02 { description "LISPmob revision."; } typedef eid-id { type string; } typedef simple-address { type union { type inet:ip-address; } } grouping lcaf-address { leaf lcaf-type { type enumeration { enum "null"; enum "afi-list"; enum "instance-id"; enum "as-number"; enum "application-data"; enum "geo-coordinates"; enum "opaque-key"; enum "nat-ttraversal"; enum "nonce-locator"; enum "multicast-info"; enum "explicit-locator-path"; enum "security-key"; enum "source-dest-key"; enum "replication-list"; enum "json-data-model"; enum "key-value-address"; enum "encapsulation-format"; } } choice address { container explicit-locator-path { when "lcaf-type = explicit-locator-path"; list hop { key "address"; leaf address { type simple-address; } leaf lrs-bits { type bits { bit lookup; bit rloc-probe; bit strict; } } } } } } grouping lisp-address { leaf afi { type enumeration { enum "ipv4" { value 1; } enum "ipv6" { value 2; } enum "lcaf" { value 16387; } } } leaf instance-id { type instance-id-type; } choice address { case ipv4 { when "afi = ipv4"; leaf ipv4 { type inet:ipv4-address; } } case ipv6 { when "afi = ipv6"; leaf ipv6 { type inet:ipv6-address; } } case lcaf { when "afi = lcaf"; container lcaf { uses lcaf-address; } } } leaf mask { type uint8; } } typedef interface-name { description "Name of a device interface"; type string; } typedef map-reply-action { description "Defines the lisp map-cache ACT type"; type enumeration { enum "no-action" { value 0; } enum "natively-forward" { value 1; } enum "send-map-request" { value 2; } enum "drop" { value 3; } } } typedef instance-id-type { type uint32 { range "0..16777214"; } } typedef auth-key-type { type enumeration { enum "none" { value 0; } enum "hmac-sha-1-96" { value 1; } enum "hmac-sha-256-128" { value 2; } } } grouping locators { list rloc { key "name"; leaf name { type string; } choice address-type { case interface-address { leaf interface { type interface-name; } } case lisp-address { container locator-address { uses lisp-address; } } } leaf priority { type uint8; } leaf weight { type uint8; } leaf multicast-priority { type uint8; } leaf multicast-weight { type uint8; } } } grouping mappings { list mapping { key "id"; leaf id { type eid-id; } container eid { uses lisp-address; } leaf ttl { type uint32; } choice locator-list { case negative-mapping { leaf map-reply-action { type map-reply-action; } } case positive-mapping { container rlocs { uses locators; } } default "positive-mapping"; } } } container itr-cfg { container rloc-probing { presence "RLOC probing active"; leaf interval { type uint16; units "seconds"; description "Interval in seconds"; } leaf retries { type uint8; description "Number of retries"; } leaf retries-interval { type uint16; units "seconds"; description "Interval in seconds between retries"; } } container itr-rlocs { description "List of RLOCs of the ITR included in Map-Requests"; list itr-rloc { key "id"; leaf id { type string; } container address { uses lisp-address; } } } container map-resolvers { list map-resolver { key "id"; leaf id { type eid-id; } leaf-list map-resolver-address { type inet:ip-address; } } } container proxy-etrs { list proxy-etr { key "id"; leaf id { type eid-id; } container eid-address { uses lisp-address; } leaf-list proxy-etr-address { type inet:ip-address; } } } container map-cache { uses mappings { augment "mapping" { leaf static { description "A configured mapping is a static mapping. If the mapping is learned, it is operational data and static is false."; type boolean; default "true"; } } } } } container etr-cfg { container map-servers { list map-server { key "address"; leaf address { type inet:ip-address; } leaf auth-key { type string; } leaf auth-key-type { type auth-key-type; } } leaf proxy-reply { type boolean; } } container local-eids { list local-eid { key "id"; leaf id { type eid-id; } container eid-address { uses lisp-address; } container rlocs { uses locators; } leaf record-ttl { type uint32; } } } } container rtr-cfg { container map-resolvers { list map-resolver { key "id"; leaf id { type eid-id; } leaf-list map-resolver-address { type inet:ip-address; } } } } } oor-1.2.0/netconf/netconf.conf.example000066400000000000000000000033571313612200500177030ustar00rootroot00000000000000 replace
x.x.x.x
password hmac-sha-1-96
true
eid1 ipv4/ipv6 0 x.x.x.x x rloc1 eth0 1 100 255 0 10 eid2 ipv4 0 y.y.y.y 24 rloc2 ipv4 z.z.z.z 1 100 255 0 10
MR-ODL x.x.x.x
oor-1.2.0/netconf/oor_Makefile000077500000000000000000000032251313612200500162620ustar00rootroot00000000000000PKGNAME = lispsimple TARGET = lispsimple.la # Various configurable paths (remember to edit Makefile.in, not Makefile) prefix = /usr/local exec_prefix = ${prefix} datarootdir = ${prefix}/share datadir = ${datarootdir} bindir = ${exec_prefix}/bin includedir = ${prefix}/include libdir = ${exec_prefix}/lib mandir = ${datarootdir}/man libtool = ./libtool CC = gcc INSTALL = /usr/bin/install -c INSTALL_PROGRAM = ${INSTALL} INSTALL_DATA = ${INSTALL} -m 644 LIBS = -lxml2 -lnetconf -lzmq CFLAGS = -g -I/usr/include/libxml2 -O3 CPPFLAGS = LIBTOOL = $(libtool) --tag=CC --quiet SRCS = lispsimple.c oor_api_netconf.c \ ../oor/lib/oor_log.c \ ../oor/lib/util.c \ ../oor/lib/mem_util.c \ ../oor/lib/generic_list.c \ ../oor/liblisp/lisp_address.c \ ../oor/liblisp/lisp_ip.c \ ../oor/liblisp/lisp_lcaf.c \ ../oor/config/oor_api.c OBJDIR = .obj LOBJS = $(SRCS:%.c=$(OBJDIR)/%.lo) all: $(TARGET) $(TARGET): $(LOBJS) $(OBJS) $(LIBTOOL) --mode=link $(CC) $(CFLAGS) $(CPPFLAGS) $(LIBS) -avoid-version -module -shared -export-dynamic --mode=link -o $@ $^ -rpath $(libdir) $(OBJDIR)/%.lo: %.c @[ -d $$(dirname $@) ] || \ (mkdir -p $$(dirname $@)) $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) $(CPPFLAGS) -fPIC -shared -c $< -o $@ .PHONY: install install: $(TARGET) $(INSTALL) -m 775 -d $(DESTDIR)/$(libdir) $(LIBTOOL) --mode=install cp $(TARGET) $(DESTDIR)/$(libdir)/; .PHONY: clean clean: $(LIBTOOL) --mode clean rm -f $(LOBJS) $(LIBTOOL) --mode clean rm -f $(TARGET) rm -rf $(TARGET) $(OBJDIR) oor-1.2.0/netconf/oor_api_netconf.c000077500000000000000000000334021313612200500172530ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include #include #include #include #include #include "oor_api_netconf.h" #include "../oor/lib/util.h" #include "../oor/lib/oor_log.h" #include "../oor/liblisp/liblisp.h" /******** TO REMOVE ********/ /* config paramaters */ char *config_file = NULL; int debug_level = LDBG_3; int default_rloc_afi = AF_UNSPEC; int daemonize = FALSE; uint32_t iseed = 0; /* initial random number generator */ /* various globals */ pid_t pid = 0; /* child pid */ pid_t sid = 0; /* sockets (fds) */ int ipv4_data_input_fd = 0; int ipv6_data_input_fd = 0; sockmstr_t *smaster = NULL; oor_ctrl_dev_t *ctrl_dev; oor_ctrl_t *lctrl; xmlNodePtr get_inner_xmlNodePtr(xmlNodePtr parent, char *name) { xmlNodePtr node = NULL; xmlChar * xmlName = xmlCharStrdup(name); node = xmlFirstElementChild(parent); while (node != NULL){ if(xmlStrEqual(node->name,xmlName)){ break; } node = xmlNextElementSibling(node); } free(xmlName); return node; } int oor_api_nc_xtr_mr_add(oor_api_connection_t *conn, xmlNodePtr mrs_parent, struct nc_err** error) { uint8_t *data = NULL; int size = 0; char *str_err = NULL; int result = 0; xmlDocPtr doc = NULL; xmlNodePtr root_node = NULL; printf("OOR_API: Add new Map Resolvers list\n"); doc = xmlNewDoc((xmlChar *)"1.0"); root_node = xmlNewNode(NULL, (xmlChar *)"root"); xmlDocSetRootElement(doc, root_node); xmlAddChild(root_node,xmlCopyNode(mrs_parent,1)); xmlDocDumpMemoryEnc(doc, (xmlChar **)&data, &size,"UTF-8"); xmlFreeDoc(doc); if ((size + sizeof(oor_api_msg_hdr_t)) > MAX_API_PKT_LEN){ str_err= strdup("Trying to send too many Map Resolvers"); goto err; } result = oor_api_apply_config(conn, OOR_API_DEV_XTR, OOR_API_TRGT_MRLIST, OOR_API_OPR_CREATE, data, size); free(data); if (result != OOR_API_RES_OK){ str_err= strdup("Config couldn't be applied (new Map Resolvers list)"); goto err; } return EXIT_SUCCESS; err: if (str_err == NULL){ str_err = strdup("Error while trying to add Map Resolver(s)"); } *error = nc_err_new(NC_ERR_OP_FAILED); nc_err_set(*error, NC_ERR_PARAM_MSG,str_err); free(str_err); return EXIT_FAILURE; } int oor_api_nc_xtr_mr_rem(oor_api_connection_t *conn, xmlNodePtr node, struct nc_err** error) { int result; result = oor_api_apply_config(conn, OOR_API_DEV_XTR, OOR_API_TRGT_MRLIST, OOR_API_OPR_DELETE, NULL, 0); printf("OOR_API: Remove Map Resolvers list\n"); if (result != OOR_API_RES_OK){ *error = nc_err_new(NC_ERR_OP_FAILED); nc_err_set(*error, NC_ERR_PARAM_MSG, "Map Resolvers couldn't be removed."); return EXIT_FAILURE; } return EXIT_SUCCESS; } int oor_api_nc_xtr_petrs_add(oor_api_connection_t *conn, xmlNodePtr mrs_parent, struct nc_err** error) { uint8_t *data = NULL; int size = 0; char *str_err = NULL; int result = 0; xmlDocPtr doc = NULL; xmlNodePtr root_node = NULL; printf("OOR_API: Add new Proxy ETRs list\n"); doc = xmlNewDoc((xmlChar *)"1.0"); root_node = xmlNewNode(NULL, (xmlChar *)"root"); xmlDocSetRootElement(doc, root_node); xmlAddChild(root_node,xmlCopyNode(mrs_parent,1)); xmlDocDumpMemoryEnc(doc, (xmlChar **)&data, &size,"UTF-8"); xmlFreeDoc(doc); if ((size + sizeof(oor_api_msg_hdr_t)) > MAX_API_PKT_LEN){ str_err= strdup("Trying to send too many Proxy ETRs"); goto err; } result = oor_api_apply_config(conn, OOR_API_DEV_XTR, OOR_API_TRGT_PETRLIST, OOR_API_OPR_CREATE, data, size); free(data); if (result != OOR_API_RES_OK){ str_err= strdup("Config couldn't be applied (new Map Resolvers list)"); goto err; } return EXIT_SUCCESS; err: if (str_err == NULL){ str_err = strdup("Error while trying to add Proxy ETR(s)"); } *error = nc_err_new(NC_ERR_OP_FAILED); nc_err_set(*error, NC_ERR_PARAM_MSG,str_err); free(str_err); return EXIT_FAILURE; } int oor_api_nc_xtr_petrs_rem(oor_api_connection_t *conn, xmlNodePtr node, struct nc_err** error) { int result; result = oor_api_apply_config(conn, OOR_API_DEV_XTR, OOR_API_TRGT_PETRLIST, OOR_API_OPR_DELETE, NULL, 0); printf("OOR_API: Remove Map Resolvers list\n"); if (result != OOR_API_RES_OK){ *error = nc_err_new(NC_ERR_OP_FAILED); nc_err_set(*error, NC_ERR_PARAM_MSG, "Proxy ETRs couldn't be removed."); return EXIT_FAILURE; } return EXIT_SUCCESS; } int oor_api_nc_xtr_ms_add(oor_api_connection_t *conn, xmlNodePtr map_servers_parent, struct nc_err** error) { uint8_t *data = NULL; int size = 0; char *str_err = NULL; int result = 0; xmlDocPtr doc = NULL; xmlNodePtr root_node = NULL; printf("OOR_API: Add new Map Servers list\n"); doc = xmlNewDoc((xmlChar *)"1.0"); root_node = xmlNewNode(NULL, (xmlChar *)"root"); xmlDocSetRootElement(doc, root_node); xmlAddChild(root_node,xmlCopyNode(map_servers_parent,1)); xmlDocDumpMemoryEnc(doc, (xmlChar **)&data, &size,"UTF-8"); xmlFreeDoc(doc); if ((size + sizeof(oor_api_msg_hdr_t)) > MAX_API_PKT_LEN){ str_err= strdup("Trying to send too many Map Resolvers"); goto err; } result = oor_api_apply_config(conn, OOR_API_DEV_XTR, OOR_API_TRGT_MSLIST, OOR_API_OPR_CREATE, data, size); free(data); if (result != OOR_API_RES_OK){ str_err= strdup("Config couldn't be applied (new Map Servers list)"); goto err; } return EXIT_SUCCESS; err: if (str_err == NULL){ str_err = strdup("Error while trying to add Map Server(s)"); } *error = nc_err_new(NC_ERR_OP_FAILED); nc_err_set(*error, NC_ERR_PARAM_MSG,str_err); free(str_err); return EXIT_FAILURE; } int oor_api_nc_xtr_ms_rem(oor_api_connection_t *conn, xmlNodePtr node, struct nc_err** error) { int result; printf("OOR_API: Remove Map Servers list\n"); result = oor_api_apply_config(conn, OOR_API_DEV_XTR, OOR_API_TRGT_MSLIST, OOR_API_OPR_DELETE, NULL, 0); if (result != OOR_API_RES_OK){ *error = nc_err_new(NC_ERR_OP_FAILED); nc_err_set(*error, NC_ERR_PARAM_MSG, "Map Servers couldn't be removed."); return EXIT_FAILURE; } return EXIT_SUCCESS; } int oor_api_nc_xtr_mapdb_rem(oor_api_connection_t *conn, xmlNodePtr node, struct nc_err** error) { int result; printf("OOR_API: Remove local map database\n"); result = oor_api_apply_config(conn, OOR_API_DEV_XTR, OOR_API_TRGT_MAPDB, OOR_API_OPR_DELETE, NULL, 0); if (result != OOR_API_RES_OK){ *error = nc_err_new(NC_ERR_OP_FAILED); nc_err_set(*error, NC_ERR_PARAM_MSG, "Local Map database couldn't be removed."); return EXIT_FAILURE; } return EXIT_SUCCESS; } int oor_api_nc_xtr_mapdb_add(oor_api_connection_t *conn, xmlNodePtr xml_local_eid_database, struct nc_err** error) { int result; char *str_err = NULL; uint8_t *data = NULL; int size = 0; xmlDocPtr doc = NULL; xmlNodePtr root_node = NULL; printf("OOR_API: Add new local map database\n"); doc = xmlNewDoc((xmlChar *)"1.0"); root_node = xmlNewNode(NULL, (xmlChar *)"root"); xmlDocSetRootElement(doc, root_node); xmlAddChild(root_node,xmlCopyNode(xml_local_eid_database,1)); xmlDocDumpMemoryEnc(doc, (xmlChar **)&data, &size,"UTF-8"); xmlFreeDoc(doc); if ((size + sizeof(oor_api_msg_hdr_t)) > MAX_API_PKT_LEN){ str_err= strdup("oor_api_nc_xtr_mapdb_add: Trying to send too many local EIDs"); goto err; } result = oor_api_apply_config(conn, OOR_API_DEV_XTR, OOR_API_TRGT_MAPDB, OOR_API_OPR_CREATE, data, size); free(data); printf("config applied\n"); if (result != OOR_API_RES_OK){ str_err= strdup("Config couldn't be applied (new local EIDs list)"); goto err; } return EXIT_SUCCESS; err: OOR_LOG(LDBG_1,"OOR_API: Error adding local data base mapping"); *error = nc_err_new(NC_ERR_OP_FAILED); nc_err_set(*error, NC_ERR_PARAM_MSG, "Error while processing config modification request."); return EXIT_FAILURE; } int oor_api_nc_rtr_mr_add(oor_api_connection_t *conn, xmlNodePtr mrs_parent, struct nc_err** error) { uint8_t *data = NULL; int size = 0; char *str_err = NULL; int result = 0; xmlDocPtr doc = NULL; xmlNodePtr root_node = NULL; printf("OOR_API: Add new Map Resolvers list to RTR\n"); doc = xmlNewDoc((xmlChar *)"1.0"); root_node = xmlNewNode(NULL, (xmlChar *)"root"); xmlDocSetRootElement(doc, root_node); xmlAddChild(root_node,xmlCopyNode(mrs_parent,1)); xmlDocDumpMemoryEnc(doc, (xmlChar **)&data, &size,"UTF-8"); xmlFreeDoc(doc); if ((size + sizeof(oor_api_msg_hdr_t)) > MAX_API_PKT_LEN){ str_err= strdup("Trying to send too many Map Resolvers"); goto err; } result = oor_api_apply_config(conn, OOR_API_DEV_RTR, OOR_API_TRGT_MRLIST, OOR_API_OPR_CREATE, data, size); free(data); if (result != OOR_API_RES_OK){ str_err= strdup("Config couldn't be applied (new Map Resolvers list)"); goto err; } return EXIT_SUCCESS; err: if (str_err == NULL){ str_err = strdup("Error while trying to add Map Resolver(s) to RTR"); } *error = nc_err_new(NC_ERR_OP_FAILED); nc_err_set(*error, NC_ERR_PARAM_MSG,str_err); free(str_err); return EXIT_FAILURE; } int oor_api_nc_rtr_mr_rem(oor_api_connection_t *conn, xmlNodePtr node, struct nc_err** error) { int result; result = oor_api_apply_config(conn, OOR_API_DEV_RTR, OOR_API_TRGT_MRLIST, OOR_API_OPR_DELETE, NULL, 0); printf("OOR_API: Remove Map Resolvers list\n"); if (result != OOR_API_RES_OK){ *error = nc_err_new(NC_ERR_OP_FAILED); nc_err_set(*error, NC_ERR_PARAM_MSG, "Map Resolvers couldn't be removed from RTR."); return EXIT_FAILURE; } return EXIT_SUCCESS; } int oor_api_nc_node_accessed(oor_api_connection_t *conn, int dev, int trgt, XMLDIFF_OP op, xmlNodePtr node, struct nc_err** error) { if (op <= 0 || op > (XMLDIFF_MOD | XMLDIFF_CHAIN | XMLDIFF_ADD | XMLDIFF_REM) || ((op & XMLDIFF_ADD) && (op & XMLDIFF_REM))) { goto err; } switch (dev){ case OOR_API_DEV_XTR: switch (trgt){ case OOR_API_TRGT_MRLIST: if ((op & XMLDIFF_ADD) || (op & XMLDIFF_MOD) || (op & XMLDIFF_CHAIN)){ return (oor_api_nc_xtr_mr_add(conn, node, error)); }else if (op & XMLDIFF_REM){ return (oor_api_nc_xtr_mr_rem(conn, node, error)); } goto err; case OOR_API_TRGT_MSLIST: if ((op & XMLDIFF_ADD) || (op & XMLDIFF_MOD) || (op & XMLDIFF_CHAIN)){ return (oor_api_nc_xtr_ms_add(conn, node, error)); }else if (op & XMLDIFF_REM){ return (oor_api_nc_xtr_ms_rem(conn, node, error)); } goto err; case OOR_API_TRGT_MAPDB: if ((op & XMLDIFF_ADD) || (op & XMLDIFF_MOD) || (op & XMLDIFF_CHAIN)){ return (oor_api_nc_xtr_mapdb_add(conn, node, error)); }else if (op & XMLDIFF_REM){ return (oor_api_nc_xtr_mapdb_rem(conn, node, error)); } goto err; case OOR_API_TRGT_PETRLIST: if ((op & XMLDIFF_ADD) || (op & XMLDIFF_MOD) || (op & XMLDIFF_CHAIN)){ return (oor_api_nc_xtr_petrs_add(conn, node, error)); }else if (op & XMLDIFF_REM){ return (oor_api_nc_xtr_petrs_rem(conn, node, error)); } goto err; default: goto err; } break; case OOR_API_DEV_RTR: switch (trgt){ case OOR_API_TRGT_MRLIST: if ((op & XMLDIFF_ADD) || (op & XMLDIFF_MOD) || (op & XMLDIFF_CHAIN)){ return (oor_api_nc_rtr_mr_add(conn, node, error)); }else if (op & XMLDIFF_REM){ return (oor_api_nc_rtr_mr_rem(conn, node, error)); } goto err; default: goto err; } break; default: goto err; } /* We should not reach here */ err: *error = nc_err_new(NC_ERR_OP_FAILED); nc_err_set(*error, NC_ERR_PARAM_MSG, "oor module: operation not supported"); return (EXIT_FAILURE); } oor-1.2.0/netconf/oor_api_netconf.h000077500000000000000000000017311313612200500172600ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef OOR_API_NETCONF_H_ #define OOR_API_NETCONF_H_ #include "../oor/defs.h" #include "../oor/config/oor_api.h" int oor_api_nc_node_accessed(oor_api_connection_t *conn, int dev, int trgt, XMLDIFF_OP op, xmlNodePtr node, struct nc_err** error); #endif /*OOR_API_NETCONF_H_*/ oor-1.2.0/netconf/oor_lispsimple.c000077500000000000000000000247731313612200500171620ustar00rootroot00000000000000/* * This is automatically generated callbacks file * It contains 3 parts: Configuration callbacks, RPC callbacks and state data callbacks. * Do NOT alter function signatures or any structures unless you know exactly what you are doing. */ #include #include #include #include #include "oor_api_netconf.h" /* Structure to store the API connection data */ oor_api_connection_t connection; /* transAPI version which must be compatible with libnetconf */ int transapi_version = 5; /* Signal to libnetconf that configuration data were modified by any callback. * 0 - data not modified * 1 - data have been modified */ int config_modified = 0; /* * Determines the callbacks order. * Set this variable before compilation and DO NOT modify it in runtime. * TRANSAPI_CLBCKS_LEAF_TO_ROOT (default) * TRANSAPI_CLBCKS_ROOT_TO_LEAF */ const TRANSAPI_CLBCKS_ORDER_TYPE callbacks_order = TRANSAPI_CLBCKS_ORDER_DEFAULT; /* Do not modify or set! This variable is set by libnetconf to announce edit-config's error-option Feel free to use it to distinguish module behavior for different error-option values. * Possible values: * NC_EDIT_ERROPT_STOP - Following callback after failure are not executed, all successful callbacks executed till failure point must be applied to the device. * NC_EDIT_ERROPT_CONT - Failed callbacks are skipped, but all callbacks needed to apply configuration changes are executed * NC_EDIT_ERROPT_ROLLBACK - After failure, following callbacks are not executed, but previous successful callbacks are executed again with previous configuration data to roll it back. */ NC_EDIT_ERROPT_TYPE erropt = NC_EDIT_ERROPT_NOTSET; /** * @brief Initialize plugin after loaded and before any other functions are called. * This function should not apply any configuration data to the controlled device. If no * running is returned (it stays *NULL), complete startup configuration is consequently * applied via module callbacks. When a running configuration is returned, libnetconf * then applies (via module's callbacks) only the startup configuration data that * differ from the returned running configuration data. * Please note, that copying startup data to the running is performed only after the * libnetconf's system-wide close - see nc_close() function documentation for more * information. * @param[out] running Current configuration of managed device. * @return EXIT_SUCCESS or EXIT_FAILURE */ int transapi_init(xmlDocPtr *running) { printf("LISP-NC: Starting client-side API... \n"); if (oor_api_init_client(&connection) != GOOD){ printf("LISP-NC: Error while starting client-side API \n"); return EXIT_FAILURE; } printf("LISP-NC: Started client-side API \n"); return EXIT_SUCCESS; } /** * @brief Free all resources allocated on plugin runtime and prepare plugin for removal. */ void transapi_close(void) { printf("\nUnloading oor module...\n"); oor_api_end(&connection); printf("Unload done \n"); return; } /** * @brief Retrieve state data from device and return them as XML document * * @param model Device data model. libxml2 xmlDocPtr. * @param running Running datastore content. libxml2 xmlDocPtr. * @param[out] err Double pointer to error structure. Fill error when some occurs. * @return State data as libxml2 xmlDocPtr or NULL in case of error. */ xmlDocPtr get_state_data(xmlDocPtr model, xmlDocPtr running, struct nc_err **err) { return(NULL); } /* * Mapping prefixes with namespaces. * Do NOT modify this structure! */ struct ns_pair namespace_mapping[] = {{"lispsimple", "urn:ietf:params:xml:ns:yang:lispsimple"}, {NULL, NULL}}; /* * CONFIGURATION callbacks * Here follows set of callback functions run every time some change in associated part of running datastore occurs. * You can safely modify the bodies of all function as well as add new functions for better lucidity of code. */ /** * @brief This callback will be run when node in path /lispsimple:itr-cfg/lispsimple:map-resolvers changes * * @param[in] data Double pointer to void. Its passed to every callback. You can share data using it. * @param[in] op Observed change in path. XMLDIFF_OP type. * @param[in] node Modified node. if op == XMLDIFF_REM its copy of node removed. * @param[out] error If callback fails, it can return libnetconf error structure with a failure description. * * @return EXIT_SUCCESS or EXIT_FAILURE */ /* !DO NOT ALTER FUNCTION SIGNATURE! */ int callback_lispsimple_itr_cfg_lispsimple_map_resolvers(void **data, XMLDIFF_OP op, xmlNodePtr node, struct nc_err **error) { printf("Node accessed %s\n",node->name); return (oor_api_nc_node_accessed(&connection,OOR_API_DEV_XTR,OOR_API_TRGT_MRLIST,op,node,error)); } /** * @brief This callback will be run when node in path /lispsimple:itr-cfg/lispsimple:proxy-etrs changes * * @param[in] data Double pointer to void. Its passed to every callback. You can share data using it. * @param[in] op Observed change in path. XMLDIFF_OP type. * @param[in] node Modified node. if op == XMLDIFF_REM its copy of node removed. * @param[out] error If callback fails, it can return libnetconf error structure with a failure description. * * @return EXIT_SUCCESS or EXIT_FAILURE */ /* !DO NOT ALTER FUNCTION SIGNATURE! */ int callback_lispsimple_itr_cfg_lispsimple_proxy_etrs(void **data, XMLDIFF_OP op, xmlNodePtr node, struct nc_err **error) { printf("Node accessed %s\n",node->name); return (oor_api_nc_node_accessed(&connection,OOR_API_DEV_XTR,OOR_API_TRGT_PETRLIST,op,node,error)); } /** * @brief This callback will be run when node in path /lispsimple:etr-cfg/lispsimple:local-eids changes * * @param[in] data Double pointer to void. Its passed to every callback. You can share data using it. * @param[in] op Observed change in path. XMLDIFF_OP type. * @param[in] node Modified node. if op == XMLDIFF_REM its copy of node removed. * @param[out] error If callback fails, it can return libnetconf error structure with a failure description. * * @return EXIT_SUCCESS or EXIT_FAILURE */ /* !DO NOT ALTER FUNCTION SIGNATURE! */ int callback_lispsimple_etr_cfg_lispsimple_local_eids(void **data, XMLDIFF_OP op, xmlNodePtr node, struct nc_err **error) { printf("Node accessed %s\n",node->name); return (oor_api_nc_node_accessed(&connection,OOR_API_DEV_XTR,OOR_API_TRGT_MAPDB,op,node,error)); } /** * @brief This callback will be run when node in path /lispsimple:etr-cfg/lispsimple:map-servers changes * * @param[in] data Double pointer to void. Its passed to every callback. You can share data using it. * @param[in] op Observed change in path. XMLDIFF_OP type. * @param[in] node Modified node. if op == XMLDIFF_REM its copy of node removed. * @param[out] error If callback fails, it can return libnetconf error structure with a failure description. * * @return EXIT_SUCCESS or EXIT_FAILURE */ /* !DO NOT ALTER FUNCTION SIGNATURE! */ int callback_lispsimple_etr_cfg_lispsimple_map_servers(void **data, XMLDIFF_OP op, xmlNodePtr node, struct nc_err **error) { printf("Node accessed %s\n",node->name); return (oor_api_nc_node_accessed(&connection,OOR_API_DEV_XTR,OOR_API_TRGT_MSLIST,op,node,error)); } /** * @brief This callback will be run when node in path /lispsimple:rtr-cfg/lispsimple:map-resolvers changes * * @param[in] data Double pointer to void. Its passed to every callback. You can share data using it. * @param[in] op Observed change in path. XMLDIFF_OP type. * @param[in] node Modified node. if op == XMLDIFF_REM its copy of node removed. * @param[out] error If callback fails, it can return libnetconf error structure with a failure description. * * @return EXIT_SUCCESS or EXIT_FAILURE */ /* !DO NOT ALTER FUNCTION SIGNATURE! */ int callback_lispsimple_rtr_cfg_lispsimple_map_resolvers(void **data, XMLDIFF_OP op, xmlNodePtr node, struct nc_err **error) { printf("Node accessed %s\n",node->name); return (oor_api_nc_node_accessed(&connection,OOR_API_DEV_RTR,OOR_API_TRGT_MRLIST,op,node,error)); } /* * Structure transapi_config_callbacks provide mapping between callback and path in configuration datastore. * It is used by libnetconf library to decide which callbacks will be run. * DO NOT alter this structure */ struct transapi_data_callbacks clbks = { .callbacks_count = 5, .data = NULL, .callbacks = { {.path = "/lispsimple:itr-cfg/lispsimple:map-resolvers", .func = callback_lispsimple_itr_cfg_lispsimple_map_resolvers}, {.path = "/lispsimple:itr-cfg/lispsimple:proxy-etrs", .func = callback_lispsimple_itr_cfg_lispsimple_proxy_etrs}, {.path = "/lispsimple:etr-cfg/lispsimple:local-eids", .func = callback_lispsimple_etr_cfg_lispsimple_local_eids}, {.path = "/lispsimple:etr-cfg/lispsimple:map-servers", .func = callback_lispsimple_etr_cfg_lispsimple_map_servers}, {.path = "/lispsimple:rtr-cfg/lispsimple:map-resolvers", .func = callback_lispsimple_rtr_cfg_lispsimple_map_resolvers} } }; /* * RPC callbacks * Here follows set of callback functions run every time RPC specific for this device arrives. * You can safely modify the bodies of all function as well as add new functions for better lucidity of code. * Every function takes array of inputs as an argument. On few first lines they are assigned to named variables. Avoid accessing the array directly. * If input was not set in RPC message argument in set to NULL. */ /* * Structure transapi_rpc_callbacks provides mapping between callbacks and RPC messages. * It is used by libnetconf library to decide which callbacks will be run when RPC arrives. * DO NOT alter this structure */ struct transapi_rpc_callbacks rpc_clbks = { .callbacks_count = 0, .callbacks = { } }; /* * Structure transapi_file_callbacks provides mapping between specific files * (e.g. configuration file in /etc/) and the callback function executed when * the file is modified. * The structure is empty by default. Add items, as in example, as you need. * * Example: * int example_callback(const char *filepath, xmlDocPtr *edit_config, int *exec) { * // do the job with changed file content * // if needed, set edit_config parameter to the edit-config data to be applied * // if needed, set exec to 1 to perform consequent transapi callbacks * return 0; * } * * struct transapi_file_callbacks file_clbks = { * .callbacks_count = 1, * .callbacks = { * {.path = "/etc/my_cfg_file", .func = example_callback} * } * } */ struct transapi_file_callbacks file_clbks = { .callbacks_count = 0, .callbacks = {{NULL}} }; oor-1.2.0/oor/000077500000000000000000000000001313612200500131015ustar00rootroot00000000000000oor-1.2.0/oor/.gitignore000066400000000000000000000002541313612200500150720ustar00rootroot00000000000000# Object files *.o # Vi(m) swap files .*.swp # CScope file cscope.out # Compiled executable oor # Local configuration file oor.conf #temp kate files *~ #kdev *.kdev4 oor-1.2.0/oor/CodingStyle.md000066400000000000000000000131061313612200500156500ustar00rootroot00000000000000# Coding style for lispd The purpose of a common coding style for a software project is first and foremost readability and maintainability, and consistent formatting rules go a long way in achieving that. A lot of the following document is inspired from the Linux kernel Documentation/CodingStyle file, with most of the Spaces section copied literally. A notable exception is the indentation style, which is in contradiction with the original document. Thanks to the original authors for their work! Since LISPmob is the implementation of an IETF protocol, this document uses the key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", and "MAY", which are to be interpreted as described in RFC 2119. ## Indentation The code SHOULD be indented at 4 spaces, and 8 spaces (two indentation levels) SHOULD NOT be replaced by TAB characters. The only place for TABs is in Makefiles. Really. Hard drive space is really cheap these days and the amount of space saved by compacting 8 spaces into a TAB character is not worth the potential rendering errors it may cause on different systems with different settings. If you use Vim or Emacs to edit existing files, the editors will be automatically configured for the correct intendation style by the modelines at the bottom. Please place the contents of the modeline template file called `modelines` from this directory at the bottom of any new source file you may create. The `case` labels within a `switch` statement SHOULD be aligned on the same column: switch (condition) { case 'a': statement; break; case 'b': default: statement; break; } Whitespace SHOULD NOT be left at the end of lines, nor on empty lines. ## Linebreaks Lines are RECOMMENDED to be less than 80 character long and MUST NOT be longer than 132 characters. When breaking long lines into several shorter ones, syslog messages SHOULD NOT be broken, to facilitate the ability to grep for them. ## Braces Braces SHOULD be placed K&R style: opening brace last on the line, closing brace first for non-function statement blocks (if, for, do, while, switch): if (condition) { statements; } Function statement blocks have the opening brace first on the next line: int function(int x) { function body } The closing brace is alone on its own line, _except_ in the cases where it is followed by a continuation of the same statement, like: do { loop body } while (condition); and if (condition1) { statements; } else if (condition2) { statements; } else { statements; } Do not unnecessarily use braces where a single statement will do. if (condition) statement; and if (condition) statement; else statement; This does not apply if only one branch of a conditional statement is a single statement; in the latter case use braces in both branches: if (condition) { statement; statement; } else { statement; } ## Spaces The use of spaces depends (mostly) on function-versus-keyword usage. Use a space after (most) keywords. The notable exceptions are `sizeof`, `typeof`, `alignof`, and `__attribute__`, which look somewhat like functions (and are usually used with parentheses in Linux, although they are not required in the language, as in: `sizeof info` after `struct fileinfo info;` is declared). So use a space after these keywords: if, switch, case, for, do, while but not with `sizeof`, `typeof`, `alignof`, or `__attribute__`. E.g., s = sizeof(struct file); Do not add spaces around (inside) parenthesized expressions. This example is _bad_: s = sizeof( struct file ); When declaring pointer data or a function that returns a pointer type, the preferred use of `*` is adjacent to the data name or function name and not adjacent to the type name. Examples: char *linux_banner; unsigned long long memparse(char *ptr, char **retptr); char *match_strdup(substring_t *s); Use one space around (on each side of) most binary and ternary operators, such as any of these: = + - < > * / % | & ^ <= >= == != ? : but no space after unary operators: & * + - ~ ! sizeof typeof alignof __attribute__ defined no space before the postfix increment & decrement unary operators: ++ -- no space after the prefix increment & decrement unary operators: ++ -- and no space around the `.` and `->` structure member operators. Do not leave trailing whitespace at the ends of lines. Some editors with "smart" indentation will insert whitespace at the beginning of new lines as appropriate, so you can start typing the next line of code right away. However, some such editors do not remove the whitespace if you end up not putting a line of code there, such as if you leave a blank line. As a result, you end up with lines containing trailing whitespace. Git will warn you about patches that introduce trailing whitespace, and can optionally strip the trailing whitespace for you; however, if applying a series of patches, this may make later patches in the series fail by changing their context lines. ## Commenting The C89 `/* ... */` style SHOULD be used for comments, and the C99-style `//...` SHOULD NOT. The preferred style for long (multi-line) comments is: /* * This is the preferred style for multi-line * comments in the LISPmob source code. * Please use it consistently. * * Description: A column of asterisks on the left side, * with beginning and ending almost-blank lines. */ oor-1.2.0/oor/Makefile000066400000000000000000000147211313612200500145460ustar00rootroot00000000000000# # # Copyright (C) 2011, 2015 Cisco Systems, Inc. # Copyright (C) 2015 CBA research group, Technical University of Catalonia. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # ifndef CC CC = gcc endif GENGETOPT = gengetopt ERROR = false ifeq "$(platform)" "" CFLAGS += -Wall -std=gnu89 -g -I/usr/include/libxml2 -D_GNU_SOURCE LIBS = -lconfuse -lrt -lm -lzmq -lxml2 else ifeq "$(platform)" "openwrt" CFLAGS += -Wall -std=gnu89 -g -I/usr/include/libxml2 -DOPENWRT -D_GNU_SOURCE LIBS = -lrt -lm -luci else ifeq "$(platform)" "vpp" CFLAGS += -Wall -std=gnu89 -g -I/usr/include/libxml2 -I/usr/include/vpp_plugins -DVPP -D_GNU_SOURCE LIBS = -lconfuse -lrt -lm -lzmq -lxml2 -lvlibmemoryclient -lvlibapi -lsvm -lvppinfra -lpthread -ldl else ERROR = true endif endif endif vpp_api_test_DEPENDENCIES = \ libvlib.la \ libvatplugin.la \ libvlibmemory.la libvnet.la INC = defs.h MAKEFILE = Makefile OBJS = cmdline.o \ config/oor_config_functions.o \ control/oor_control.o \ control/oor_ctrl_device.o \ control/oor_local_db.o \ control/oor_map_cache.o \ control/lisp_xtr.o \ control/lisp_ms.o \ control/control-data-plane/control-data-plane.o \ control/control-data-plane/tun/cdp_tun.o \ data-plane/encapsulations/vxlan-gpe.o \ data-plane/data-plane.o \ data-plane/ttable.o \ data-plane/tun/tun_input.o \ data-plane/tun/tun_output.o \ data-plane/tun/tun.o \ elibs/mbedtls/md.o \ elibs/mbedtls/sha1.o \ elibs/mbedtls/sha256.o \ elibs/mbedtls/md_wrap.o \ elibs/patricia/patricia.o \ fwd_policies/balancing_locators.o \ fwd_policies/fwd_addr_func.o \ fwd_policies/fwd_policy.o \ fwd_policies/fwd_utils.o \ fwd_policies/flow_balancing/flow_balancing.o \ fwd_policies/flow_balancing/fwd_entry_tuple.o \ liblisp/liblisp.o \ liblisp/lisp_address.o \ liblisp/lisp_data.o \ liblisp/lisp_ip.o \ liblisp/lisp_lcaf.o \ liblisp/lisp_locator.o \ liblisp/lisp_mapping.o \ liblisp/lisp_messages.o \ liblisp/lisp_message_fields.o \ lib/cksum.o \ lib/generic_list.o \ lib/hmac.o \ lib/iface_locators.o \ lib/int_table.o \ lib/interfaces_lib.o \ lib/lbuf.o \ lib/lisp_site.o \ lib/oor_log.o \ lib/mapping_db.o \ lib/map_cache_entry.o \ lib/map_local_entry.o \ lib/mem_util.o \ lib/nonces_table.o \ lib/packets.o \ lib/pointers_table.o \ lib/prefixes.o \ lib/routing_tables_lib.o \ lib/sockets.o \ lib/sockets-util.o \ lib/shash.o \ lib/timers.o \ lib/timers_utils.o \ lib/util.o \ net_mgr/net_mgr.o \ net_mgr/net_mgr_proc_fc.o \ net_mgr/kernel/netm_kernel.o \ net_mgr/kernel/iface_mgmt.o \ iface_list.o \ oor.o ifeq "$(platform)" "openwrt" OBJS := $(OBJS) \ config/oor_config_uci.o else OBJS := $(OBJS) \ config/oor_api.o \ config/oor_api_internals.o \ config/oor_config_confuse.o endif ifeq "$(platform)" "vpp" OBJS := $(OBJS) \ control/control-data-plane/vpp/cdp_vpp.o \ data-plane/vpp/vpp.o \ fwd_policies/vpp_balancing/fwd_entry_vpp.o \ fwd_policies/vpp_balancing/vpp_balancing.o \ lib/vpp_api/vpp_api.o \ lib/vpp_api/vpp_api_reply.o \ lib/vpp_api/vpp_api_requests.o \ lib/vpp_api/ctrl_vpp_plugin.o \ lib/vpp_api/pkt_miss_vpp_plugin.o \ net_mgr/vpp/netm_vpp.o endif EXE = oor PREFIX = /usr/local/sbin INCLUDE = -I. -Iliblisp -Ielibs -Ilib -Icontrol -Idata-tun -Ifwd_balancing -Ifwd_policies/flow_balancing \ -Inet_mgr -Inet_mgr/kernel -Inet_mgr/vpp $(EXE): $(OBJS) $(CC) -o $@ $^ $(CFLAGS) $(LDFLAGS) $(LIBS) # # gengetops generates this... # cmdline.c: oor.ggo $(GENGETOPT) -i $< %.o: %.c $(DEPS) $(INC) $(MAKEFILE) ifeq "$(ERROR)" "true" $(error Invalid value of platform parameter) endif $(CC) $(CFLAGS) $(INCLUDE) -c -o $@ $< clean: rm -f *.o $(EXE) \ elibs/patricia/*o \ elibs/bob/*o \ elibs/libcfu/*o \ elibs/mbedtls/*o \ liblisp/*o liblisp/hmac/*o \ lib/*o lib/vpp_api/*o \ net_mgr/*o net_mgr/kernel/*o net_mgr/vpp/*o \ config/*o control/*o control/control-data-plane/*o \ control/control-data-plane/tun/*o control/control-data-plane/vpnapi/*o \ control/control-data-plane/vpp/*o \ data-plane/encapsulations/*o \ data-plane/*o data-plane/tun/*o data-plane/vpnapi/*o data-plane/vpp/*o \ fwd_policies/*o fwd_policies/flow_balancing/*o fwd_policies/vpp_balancing/*o distclean: clean rm -f cmdline.[ch] cscope.out install: $(EXE) mkdir -p $(DESTDIR)$(PREFIX) && cp $(EXE) $(DESTDIR)$(PREFIX) setcap cap_net_raw,cap_net_admin+ep $(DESTDIR)$(PREFIX)/$(EXE) tags: cscope -R -boor-1.2.0/oor/cmdline.c000066400000000000000000000421161313612200500146640ustar00rootroot00000000000000/* File autogenerated by gengetopt version 2.22.6 generated with the following command: gengetopt -i oor.ggo The developers of gengetopt consider the fixed text that goes in all gengetopt output files to be in the public domain: we make no copyright claims on it. */ /* If we use autoconf. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #ifndef FIX_UNUSED #define FIX_UNUSED(X) (void) (X) /* avoid warnings for unused params */ #endif #include #include "cmdline.h" const char *gengetopt_args_info_purpose = ""; const char *gengetopt_args_info_usage = "Usage: oor [OPTIONS]..."; const char *gengetopt_args_info_versiontext = ""; const char *gengetopt_args_info_description = ""; const char *gengetopt_args_info_help[] = { " -h, --help Print help and exit", " -V, --version Print version and exit", "\n Mode: oorconfig", " -d, --debug=ENUM Debugging output [0..3] (possible\n values=\"0\", \"1\", \"2\", \"3\")", " -a, --afi=ENUM Default RLOCs afi [4,6] (possible\n values=\"4\", \"6\")", " -D, --daemonize Daemonize oor", " -f, --config-file=config-file Alternate config file", 0 }; typedef enum {ARG_NO , ARG_STRING , ARG_ENUM } cmdline_parser_arg_type; static void clear_given (struct gengetopt_args_info *args_info); static void clear_args (struct gengetopt_args_info *args_info); static int cmdline_parser_internal (int argc, char **argv, struct gengetopt_args_info *args_info, struct cmdline_parser_params *params, const char *additional_error); const char *cmdline_parser_debug_values[] = {"0", "1", "2", "3", 0}; /*< Possible values for debug. */ const char *cmdline_parser_afi_values[] = {"4", "6", 0}; /*< Possible values for afi. */ static char * gengetopt_strdup (const char *s); static void clear_given (struct gengetopt_args_info *args_info) { args_info->help_given = 0 ; args_info->version_given = 0 ; args_info->debug_given = 0 ; args_info->afi_given = 0 ; args_info->daemonize_given = 0 ; args_info->config_file_given = 0 ; args_info->oorconfig_mode_counter = 0 ; } static void clear_args (struct gengetopt_args_info *args_info) { FIX_UNUSED (args_info); args_info->debug_arg = debug__NULL; args_info->debug_orig = NULL; args_info->afi_arg = afi__NULL; args_info->afi_orig = NULL; args_info->config_file_arg = NULL; args_info->config_file_orig = NULL; } static void init_args_info(struct gengetopt_args_info *args_info) { args_info->help_help = gengetopt_args_info_help[0] ; args_info->version_help = gengetopt_args_info_help[1] ; args_info->debug_help = gengetopt_args_info_help[3] ; args_info->afi_help = gengetopt_args_info_help[4] ; args_info->daemonize_help = gengetopt_args_info_help[5] ; args_info->config_file_help = gengetopt_args_info_help[6] ; } void cmdline_parser_print_version (void) { printf ("%s %s\n", (strlen(CMDLINE_PARSER_PACKAGE_NAME) ? CMDLINE_PARSER_PACKAGE_NAME : CMDLINE_PARSER_PACKAGE), CMDLINE_PARSER_VERSION); if (strlen(gengetopt_args_info_versiontext) > 0) printf("\n%s\n", gengetopt_args_info_versiontext); } static void print_help_common(void) { cmdline_parser_print_version (); if (strlen(gengetopt_args_info_purpose) > 0) printf("\n%s\n", gengetopt_args_info_purpose); if (strlen(gengetopt_args_info_usage) > 0) printf("\n%s\n", gengetopt_args_info_usage); printf("\n"); if (strlen(gengetopt_args_info_description) > 0) printf("%s\n\n", gengetopt_args_info_description); } void cmdline_parser_print_help (void) { int i = 0; print_help_common(); while (gengetopt_args_info_help[i]) printf("%s\n", gengetopt_args_info_help[i++]); } void cmdline_parser_init (struct gengetopt_args_info *args_info) { clear_given (args_info); clear_args (args_info); init_args_info (args_info); } void cmdline_parser_params_init(struct cmdline_parser_params *params) { if (params) { params->override = 0; params->initialize = 1; params->check_required = 1; params->check_ambiguity = 0; params->print_errors = 1; } } struct cmdline_parser_params * cmdline_parser_params_create(void) { struct cmdline_parser_params *params = (struct cmdline_parser_params *)malloc(sizeof(struct cmdline_parser_params)); cmdline_parser_params_init(params); return params; } static void free_string_field (char **s) { if (*s) { free (*s); *s = 0; } } static void cmdline_parser_release (struct gengetopt_args_info *args_info) { free_string_field (&(args_info->debug_orig)); free_string_field (&(args_info->afi_orig)); free_string_field (&(args_info->config_file_arg)); free_string_field (&(args_info->config_file_orig)); clear_given (args_info); } /** * @param val the value to check * @param values the possible values * @return the index of the matched value: * -1 if no value matched, * -2 if more than one value has matched */ static int check_possible_values(const char *val, const char *values[]) { int i, found, last; size_t len; if (!val) /* otherwise strlen() crashes below */ return -1; /* -1 means no argument for the option */ found = last = 0; for (i = 0, len = strlen(val); values[i]; ++i) { if (strncmp(val, values[i], len) == 0) { ++found; last = i; if (strlen(values[i]) == len) return i; /* exact macth no need to check more */ } } if (found == 1) /* one match: OK */ return last; return (found ? -2 : -1); /* return many values or none matched */ } static void write_into_file(FILE *outfile, const char *opt, const char *arg, const char *values[]) { int found = -1; if (arg) { if (values) { found = check_possible_values(arg, values); } if (found >= 0) fprintf(outfile, "%s=\"%s\" # %s\n", opt, arg, values[found]); else fprintf(outfile, "%s=\"%s\"\n", opt, arg); } else { fprintf(outfile, "%s\n", opt); } } int cmdline_parser_dump(FILE *outfile, struct gengetopt_args_info *args_info) { int i = 0; if (!outfile) { fprintf (stderr, "%s: cannot dump options to stream\n", CMDLINE_PARSER_PACKAGE); return EXIT_FAILURE; } if (args_info->help_given) write_into_file(outfile, "help", 0, 0 ); if (args_info->version_given) write_into_file(outfile, "version", 0, 0 ); if (args_info->debug_given) write_into_file(outfile, "debug", args_info->debug_orig, cmdline_parser_debug_values); if (args_info->afi_given) write_into_file(outfile, "afi", args_info->afi_orig, cmdline_parser_afi_values); if (args_info->daemonize_given) write_into_file(outfile, "daemonize", 0, 0 ); if (args_info->config_file_given) write_into_file(outfile, "config-file", args_info->config_file_orig, 0); i = EXIT_SUCCESS; return i; } int cmdline_parser_file_save(const char *filename, struct gengetopt_args_info *args_info) { FILE *outfile; int i = 0; outfile = fopen(filename, "w"); if (!outfile) { fprintf (stderr, "%s: cannot open file for writing: %s\n", CMDLINE_PARSER_PACKAGE, filename); return EXIT_FAILURE; } i = cmdline_parser_dump(outfile, args_info); fclose (outfile); return i; } void cmdline_parser_free (struct gengetopt_args_info *args_info) { cmdline_parser_release (args_info); } /** @brief replacement of strdup, which is not standard */ char * gengetopt_strdup (const char *s) { char *result = 0; if (!s) return result; result = (char*)malloc(strlen(s) + 1); if (result == (char*)0) return (char*)0; strcpy(result, s); return result; } int cmdline_parser (int argc, char **argv, struct gengetopt_args_info *args_info) { return cmdline_parser2 (argc, argv, args_info, 0, 1, 1); } int cmdline_parser_ext (int argc, char **argv, struct gengetopt_args_info *args_info, struct cmdline_parser_params *params) { int result; result = cmdline_parser_internal (argc, argv, args_info, params, 0); if (result == EXIT_FAILURE) { cmdline_parser_free (args_info); exit (EXIT_FAILURE); } return result; } int cmdline_parser2 (int argc, char **argv, struct gengetopt_args_info *args_info, int override, int initialize, int check_required) { int result; struct cmdline_parser_params params; params.override = override; params.initialize = initialize; params.check_required = check_required; params.check_ambiguity = 0; params.print_errors = 1; result = cmdline_parser_internal (argc, argv, args_info, ¶ms, 0); if (result == EXIT_FAILURE) { cmdline_parser_free (args_info); exit (EXIT_FAILURE); } return result; } int cmdline_parser_required (struct gengetopt_args_info *args_info, const char *prog_name) { FIX_UNUSED (args_info); FIX_UNUSED (prog_name); return EXIT_SUCCESS; } static char *package_name = 0; /** * @brief updates an option * @param field the generic pointer to the field to update * @param orig_field the pointer to the orig field * @param field_given the pointer to the number of occurrence of this option * @param prev_given the pointer to the number of occurrence already seen * @param value the argument for this option (if null no arg was specified) * @param possible_values the possible values for this option (if specified) * @param default_value the default value (in case the option only accepts fixed values) * @param arg_type the type of this option * @param check_ambiguity @see cmdline_parser_params.check_ambiguity * @param override @see cmdline_parser_params.override * @param no_free whether to free a possible previous value * @param multiple_option whether this is a multiple option * @param long_opt the corresponding long option * @param short_opt the corresponding short option (or '-' if none) * @param additional_error possible further error specification */ static int update_arg(void *field, char **orig_field, unsigned int *field_given, unsigned int *prev_given, char *value, const char *possible_values[], const char *default_value, cmdline_parser_arg_type arg_type, int check_ambiguity, int override, int no_free, int multiple_option, const char *long_opt, char short_opt, const char *additional_error) { char *stop_char = 0; const char *val = value; int found; char **string_field; FIX_UNUSED (field); stop_char = 0; found = 0; if (!multiple_option && prev_given && (*prev_given || (check_ambiguity && *field_given))) { if (short_opt != '-') fprintf (stderr, "%s: `--%s' (`-%c') option given more than once%s\n", package_name, long_opt, short_opt, (additional_error ? additional_error : "")); else fprintf (stderr, "%s: `--%s' option given more than once%s\n", package_name, long_opt, (additional_error ? additional_error : "")); return 1; /* failure */ } if (possible_values && (found = check_possible_values((value ? value : default_value), possible_values)) < 0) { if (short_opt != '-') fprintf (stderr, "%s: %s argument, \"%s\", for option `--%s' (`-%c')%s\n", package_name, (found == -2) ? "ambiguous" : "invalid", value, long_opt, short_opt, (additional_error ? additional_error : "")); else fprintf (stderr, "%s: %s argument, \"%s\", for option `--%s'%s\n", package_name, (found == -2) ? "ambiguous" : "invalid", value, long_opt, (additional_error ? additional_error : "")); return 1; /* failure */ } if (field_given && *field_given && ! override) return 0; if (prev_given) (*prev_given)++; if (field_given) (*field_given)++; if (possible_values) val = possible_values[found]; switch(arg_type) { case ARG_ENUM: if (val) *((int *)field) = found; break; case ARG_STRING: if (val) { string_field = (char **)field; if (!no_free && *string_field) free (*string_field); /* free previous string */ *string_field = gengetopt_strdup (val); } break; default: break; }; /* store the original value */ switch(arg_type) { case ARG_NO: break; default: if (value && orig_field) { if (no_free) { *orig_field = value; } else { if (*orig_field) free (*orig_field); /* free previous string */ *orig_field = gengetopt_strdup (value); } } }; return 0; /* OK */ } static int check_modes( int given1[], const char *options1[], int given2[], const char *options2[]) { int i = 0, j = 0, errors = 0; while (given1[i] >= 0) { if (given1[i]) { while (given2[j] >= 0) { if (given2[j]) { ++errors; fprintf(stderr, "%s: option %s conflicts with option %s\n", package_name, options1[i], options2[j]); } ++j; } } ++i; } return errors; } int cmdline_parser_internal ( int argc, char **argv, struct gengetopt_args_info *args_info, struct cmdline_parser_params *params, const char *additional_error) { int c; /* Character of the parsed option. */ int error_occurred = 0; struct gengetopt_args_info local_args_info; int override; int initialize; int check_required; int check_ambiguity; package_name = argv[0]; override = params->override; initialize = params->initialize; check_required = params->check_required; check_ambiguity = params->check_ambiguity; if (initialize) cmdline_parser_init (args_info); cmdline_parser_init (&local_args_info); optarg = 0; optind = 0; opterr = params->print_errors; optopt = '?'; while (1) { int option_index = 0; static struct option long_options[] = { { "help", 0, NULL, 'h' }, { "version", 0, NULL, 'V' }, { "debug", 1, NULL, 'd' }, { "afi", 1, NULL, 'a' }, { "daemonize", 0, NULL, 'D' }, { "config-file", 1, NULL, 'f' }, { 0, 0, 0, 0 } }; c = getopt_long (argc, argv, "hVd:a:Df:", long_options, &option_index); if (c == -1) break; /* Exit from `while (1)' loop. */ switch (c) { case 'h': /* Print help and exit. */ cmdline_parser_print_help (); cmdline_parser_free (&local_args_info); exit (EXIT_SUCCESS); case 'V': /* Print version and exit. */ cmdline_parser_print_version (); cmdline_parser_free (&local_args_info); exit (EXIT_SUCCESS); case 'd': /* Debugging output [0..3]. */ args_info->oorconfig_mode_counter += 1; if (update_arg( (void *)&(args_info->debug_arg), &(args_info->debug_orig), &(args_info->debug_given), &(local_args_info.debug_given), optarg, cmdline_parser_debug_values, 0, ARG_ENUM, check_ambiguity, override, 0, 0, "debug", 'd', additional_error)) goto failure; break; case 'a': /* Default RLOCs afi [4,6]. */ args_info->oorconfig_mode_counter += 1; if (update_arg( (void *)&(args_info->afi_arg), &(args_info->afi_orig), &(args_info->afi_given), &(local_args_info.afi_given), optarg, cmdline_parser_afi_values, 0, ARG_ENUM, check_ambiguity, override, 0, 0, "afi", 'a', additional_error)) goto failure; break; case 'D': /* Daemonize oor. */ args_info->oorconfig_mode_counter += 1; if (update_arg( 0 , 0 , &(args_info->daemonize_given), &(local_args_info.daemonize_given), optarg, 0, 0, ARG_NO, check_ambiguity, override, 0, 0, "daemonize", 'D', additional_error)) goto failure; break; case 'f': /* Alternate config file. */ args_info->oorconfig_mode_counter += 1; if (update_arg( (void *)&(args_info->config_file_arg), &(args_info->config_file_orig), &(args_info->config_file_given), &(local_args_info.config_file_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "config-file", 'f', additional_error)) goto failure; break; case 0: /* Long option with no short option */ case '?': /* Invalid option. */ /* `getopt_long' already printed an error message. */ goto failure; default: /* bug: option not considered. */ fprintf (stderr, "%s: option unknown: %c%s\n", CMDLINE_PARSER_PACKAGE, c, (additional_error ? additional_error : "")); abort (); } /* switch */ } /* while */ cmdline_parser_release (&local_args_info); if ( error_occurred ) return (EXIT_FAILURE); return 0; failure: cmdline_parser_release (&local_args_info); return (EXIT_FAILURE); } oor-1.2.0/oor/cmdline.h000066400000000000000000000167561313612200500147040ustar00rootroot00000000000000/** @file cmdline.h * @brief The header file for the command line option parser * generated by GNU Gengetopt version 2.22.6 * http://www.gnu.org/software/gengetopt. * DO NOT modify this file, since it can be overwritten * @author GNU Gengetopt by Lorenzo Bettini */ #ifndef CMDLINE_H #define CMDLINE_H /* If we use autoconf. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include /* for FILE */ #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ #ifndef CMDLINE_PARSER_PACKAGE /** @brief the program name (used for printing errors) */ #define CMDLINE_PARSER_PACKAGE "oor" #endif #ifndef CMDLINE_PARSER_PACKAGE_NAME /** @brief the complete program name (used for help and version) */ #define CMDLINE_PARSER_PACKAGE_NAME "oor" #endif #ifndef CMDLINE_PARSER_VERSION /** @brief the program version */ #define CMDLINE_PARSER_VERSION "1.2.0" #endif enum enum_debug { debug__NULL = -1, debug_arg_0 = 0, debug_arg_1, debug_arg_2, debug_arg_3 }; enum enum_afi { afi__NULL = -1, afi_arg_4 = 0, afi_arg_6 }; /** @brief Where the command line options are stored */ struct gengetopt_args_info { const char *help_help; /**< @brief Print help and exit help description. */ const char *version_help; /**< @brief Print version and exit help description. */ enum enum_debug debug_arg; /**< @brief Debugging output [0..3]. */ char * debug_orig; /**< @brief Debugging output [0..3] original value given at command line. */ const char *debug_help; /**< @brief Debugging output [0..3] help description. */ enum enum_afi afi_arg; /**< @brief Default RLOCs afi [4,6]. */ char * afi_orig; /**< @brief Default RLOCs afi [4,6] original value given at command line. */ const char *afi_help; /**< @brief Default RLOCs afi [4,6] help description. */ const char *daemonize_help; /**< @brief Daemonize oor help description. */ char * config_file_arg; /**< @brief Alternate config file. */ char * config_file_orig; /**< @brief Alternate config file original value given at command line. */ const char *config_file_help; /**< @brief Alternate config file help description. */ unsigned int help_given ; /**< @brief Whether help was given. */ unsigned int version_given ; /**< @brief Whether version was given. */ unsigned int debug_given ; /**< @brief Whether debug was given. */ unsigned int afi_given ; /**< @brief Whether afi was given. */ unsigned int daemonize_given ; /**< @brief Whether daemonize was given. */ unsigned int config_file_given ; /**< @brief Whether config-file was given. */ int oorconfig_mode_counter; /**< @brief Counter for mode oorconfig */ } ; /** @brief The additional parameters to pass to parser functions */ struct cmdline_parser_params { int override; /**< @brief whether to override possibly already present options (default 0) */ int initialize; /**< @brief whether to initialize the option structure gengetopt_args_info (default 1) */ int check_required; /**< @brief whether to check that all required options were provided (default 1) */ int check_ambiguity; /**< @brief whether to check for options already specified in the option structure gengetopt_args_info (default 0) */ int print_errors; /**< @brief whether getopt_long should print an error message for a bad option (default 1) */ } ; /** @brief the purpose string of the program */ extern const char *gengetopt_args_info_purpose; /** @brief the usage string of the program */ extern const char *gengetopt_args_info_usage; /** @brief the description string of the program */ extern const char *gengetopt_args_info_description; /** @brief all the lines making the help output */ extern const char *gengetopt_args_info_help[]; /** * The command line parser * @param argc the number of command line options * @param argv the command line options * @param args_info the structure where option information will be stored * @return 0 if everything went fine, NON 0 if an error took place */ int cmdline_parser (int argc, char **argv, struct gengetopt_args_info *args_info); /** * The command line parser (version with additional parameters - deprecated) * @param argc the number of command line options * @param argv the command line options * @param args_info the structure where option information will be stored * @param override whether to override possibly already present options * @param initialize whether to initialize the option structure my_args_info * @param check_required whether to check that all required options were provided * @return 0 if everything went fine, NON 0 if an error took place * @deprecated use cmdline_parser_ext() instead */ int cmdline_parser2 (int argc, char **argv, struct gengetopt_args_info *args_info, int override, int initialize, int check_required); /** * The command line parser (version with additional parameters) * @param argc the number of command line options * @param argv the command line options * @param args_info the structure where option information will be stored * @param params additional parameters for the parser * @return 0 if everything went fine, NON 0 if an error took place */ int cmdline_parser_ext (int argc, char **argv, struct gengetopt_args_info *args_info, struct cmdline_parser_params *params); /** * Save the contents of the option struct into an already open FILE stream. * @param outfile the stream where to dump options * @param args_info the option struct to dump * @return 0 if everything went fine, NON 0 if an error took place */ int cmdline_parser_dump(FILE *outfile, struct gengetopt_args_info *args_info); /** * Save the contents of the option struct into a (text) file. * This file can be read by the config file parser (if generated by gengetopt) * @param filename the file where to save * @param args_info the option struct to save * @return 0 if everything went fine, NON 0 if an error took place */ int cmdline_parser_file_save(const char *filename, struct gengetopt_args_info *args_info); /** * Print the help */ void cmdline_parser_print_help(void); /** * Print the version */ void cmdline_parser_print_version(void); /** * Initializes all the fields a cmdline_parser_params structure * to their default values * @param params the structure to initialize */ void cmdline_parser_params_init(struct cmdline_parser_params *params); /** * Allocates dynamically a cmdline_parser_params structure and initializes * all its fields to their default values * @return the created and initialized cmdline_parser_params structure */ struct cmdline_parser_params *cmdline_parser_params_create(void); /** * Initializes the passed gengetopt_args_info structure's fields * (also set default values for options that have a default) * @param args_info the structure to initialize */ void cmdline_parser_init (struct gengetopt_args_info *args_info); /** * Deallocates the string fields of the gengetopt_args_info structure * (but does not deallocate the structure itself) * @param args_info the structure to deallocate */ void cmdline_parser_free (struct gengetopt_args_info *args_info); /** * Checks that all the required options were specified * @param args_info the structure to check * @param prog_name the name of the program that will be used to print * possible errors * @return */ int cmdline_parser_required (struct gengetopt_args_info *args_info, const char *prog_name); extern const char *cmdline_parser_debug_values[]; /**< @brief Possible values for debug. */ extern const char *cmdline_parser_afi_values[]; /**< @brief Possible values for afi. */ #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* CMDLINE_H */ oor-1.2.0/oor/config/000077500000000000000000000000001313612200500143465ustar00rootroot00000000000000oor-1.2.0/oor/config/oor_api.c000066400000000000000000000124541313612200500161500ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include #include #include #include #include #include "oor_api.h" #include "../lib/oor_log.h" #include "../lib/mem_util.h" #include "../liblisp/liblisp.h" int oor_api_init_client(oor_api_connection_t *conn) { int error; conn->context = zmq_ctx_new(); //Request-Reply communication pattern (Client side) conn->socket = zmq_socket(conn->context, ZMQ_REQ); //Attachment point for other processes error = zmq_connect(conn->socket, IPC_FILE); if (error != 0){ OOR_LOG(LDBG_2,"LMAPI: Error while ZMQ binding on client: %s\n",zmq_strerror (error)); goto err; } OOR_LOG(LDBG_2,"LMAPI: API client initiated using ZMQ\n"); return (GOOD); err: OOR_LOG(LERR,"LMAPI: The API client couldn't be initialized.\n"); return (BAD); } void oor_api_end(oor_api_connection_t *conn) { OOR_LOG(LDBG_2,"LMAPI: Closing ZMQ-based API\n"); zmq_close (conn->socket); zmq_ctx_destroy (conn->context); OOR_LOG(LDBG_2,"LMAPI: Closed ZMQ-based API\n"); } uint8_t * oor_api_hdr_push(uint8_t *buf, oor_api_msg_hdr_t * hdr) { uint8_t *ptr; memcpy(buf,hdr,sizeof(oor_api_msg_hdr_t)); ptr = CO(buf,sizeof(oor_api_msg_hdr_t)); return (ptr); } void oor_api_fill_hdr(oor_api_msg_hdr_t *hdr, oor_api_msg_device_e dev, oor_api_msg_target_e trgt, oor_api_msg_opr_e opr, oor_api_msg_type_e type, int dlen) { hdr->device = (uint8_t) dev; hdr->target = (uint8_t) trgt; hdr->operation = (uint8_t) opr; hdr->type = (uint8_t) type; hdr->datalen = (uint32_t) dlen; } int oor_api_result_msg_new(uint8_t **buf,oor_api_msg_device_e dev, oor_api_msg_target_e trgt, oor_api_msg_opr_e opr, oor_api_msg_result_e res) { oor_api_msg_hdr_t hdr; uint8_t *ptr; oor_api_fill_hdr(&hdr,dev,trgt,opr,OOR_API_TYPE_RESULT,sizeof(oor_api_msg_result_e)); *buf = xzalloc(sizeof(oor_api_msg_hdr_t)+sizeof(oor_api_msg_result_e)); ptr = oor_api_hdr_push(*buf,&hdr); memcpy(ptr, &res,sizeof(oor_api_msg_result_e)); return (sizeof(oor_api_msg_hdr_t)+sizeof(oor_api_msg_result_e)); } int oor_api_recv(oor_api_connection_t *conn, void *buffer, int flags) { int nbytes; int zmq_flags = 0; zmq_pollitem_t items [1]; int poll_timeout; int poll_rc; if (flags == OOR_API_DONTWAIT){ zmq_flags = ZMQ_DONTWAIT; poll_timeout = 0; //Return immediately }else{ poll_timeout = -1; //Wait indefinitely } items[0].socket = conn->socket; items[0].events = ZMQ_POLLIN; //Check for incoming packets on socket // Poll for packets on socket for poll_timeout time poll_rc = zmq_poll (items, 1, poll_timeout); if (poll_rc == 0) { //There is nothing to read on the socket return (OOR_API_NOTHINGTOREAD); } OOR_LOG(LDBG_3,"LMAPI: Data available in API socket\n"); nbytes = zmq_recv(conn->socket, buffer, MAX_API_PKT_LEN, zmq_flags); OOR_LOG(LDBG_3,"LMAPI: Bytes read from API socket: %d. ",nbytes); if (nbytes == -1){ OOR_LOG(LERR,"LMAPI: Error while ZMQ receiving: %s\n",zmq_strerror (errno)); return (OOR_API_ERROR); } return (nbytes); } int oor_api_send(oor_api_connection_t *conn, void *msg, int len, int flags) { int nbytes; OOR_LOG(LDBG_3,"LMAPI: Ready to send %d bytes through API socket\n",len); nbytes = zmq_send(conn->socket,msg,len,0); OOR_LOG(LDBG_3,"LMAPI: Bytes transmitted over API socket: %d. ",nbytes); if (nbytes == -1){ OOR_LOG(LERR,"LMAPI: Error while ZMQ sending: %s\n",zmq_strerror (errno)); } return (GOOD); } int oor_api_apply_config(oor_api_connection_t *conn, int dev, int trgt, int opr, uint8_t *data, int dlen) { oor_api_msg_hdr_t *hdr; uint8_t *buffer; uint8_t *dta_ptr; uint8_t *res_ptr; int len; buffer = xzalloc(MAX_API_PKT_LEN); hdr = (oor_api_msg_hdr_t *) buffer; dta_ptr = CO(buffer,sizeof(oor_api_msg_hdr_t)); oor_api_fill_hdr(hdr,dev,trgt,opr,OOR_API_TYPE_REQUEST,dlen); memcpy(dta_ptr,data,dlen); len = dlen + sizeof(oor_api_msg_hdr_t); oor_api_send(conn,buffer,len,OOR_API_NOFLAGS); free(buffer); buffer = xzalloc(MAX_API_PKT_LEN); //Blocks until reply len = oor_api_recv(conn,buffer,OOR_API_NOFLAGS); hdr = (oor_api_msg_hdr_t *) buffer; //We expect an OK/ERR result if ((hdr->type != OOR_API_TYPE_RESULT) || (hdr->datalen != sizeof(oor_api_msg_result_e))){ goto err; } res_ptr = CO(buffer,sizeof(oor_api_msg_hdr_t)); if (*res_ptr != OOR_API_RES_OK){ //TODO support fine-grain errors goto err; } // All good free (buffer); return (OOR_API_RES_OK); err: free (buffer); return (OOR_API_RES_ERR); } oor-1.2.0/oor/config/oor_api.h000066400000000000000000000075031313612200500161540ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef OOR_API_H_ #define OOR_API_H_ #include #define IPC_FILE "ipc:///tmp/oor-ipc" #define MAX_API_PKT_LEN 4096 //MAX_IP_PKT_LEN enum { OOR_API_NOFLAGS, OOR_API_DONTWAIT, OOR_API_ERROR = -1, OOR_API_NOTHINGTOREAD = -2 }; typedef enum oor_api_msg_device_e_ { OOR_API_DEV_XTR, OOR_API_DEV_MS, OOR_API_DEV_MR, OOR_API_DEV_RTR } oor_api_msg_device_e; //Device of the operation typedef enum oor_api_msg_opr_e_ { OOR_API_OPR_CREATE, OOR_API_OPR_READ, OOR_API_OPR_UPDATE, OOR_API_OPR_DELETE } oor_api_msg_opr_e; //Type of operation typedef enum oor_api_msg_target_e_ { OOR_API_TRGT_MRLIST, OOR_API_TRGT_MSLIST, OOR_API_TRGT_PETRLIST, OOR_API_TRGT_MAPCACHE, OOR_API_TRGT_MAPDB } oor_api_msg_target_e; //Target of the operation typedef enum lmapi_msg_type_e_ { OOR_API_TYPE_REQUEST, OOR_API_TYPE_RESULT } oor_api_msg_type_e; //Type typedef enum lmapi_msg_result_e_ { OOR_API_RES_OK, OOR_API_RES_ERR } oor_api_msg_result_e; //Results typedef struct oor_api_msg_hdr_t_ { uint8_t device; uint8_t target; uint8_t operation; uint8_t type; uint32_t datalen; } oor_api_msg_hdr_t; /* * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Address AFI | MS Address ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |P| Reserved | Key ID | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Key Length | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Key ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ typedef struct oor_api_msg_ms_t_{ #ifdef LITTLE_ENDIANS uint8_t reserved:7; uint8_t proxy_bit:1; #else uint8_t proxy_bit:1; uint8_t reserved:7; #endif uint8_t reserved2; uint16_t key_id; uint32_t key_len; }oor_api_msg_ms_t; typedef struct oor_api_connection_t_ { void *context; void *socket; } oor_api_connection_t; /* Initialize API system (client) */ int oor_api_init_client(oor_api_connection_t *conn); /* Shutdown API system */ void oor_api_end(oor_api_connection_t *conn); uint8_t *oor_api_hdr_push(uint8_t *buf, oor_api_msg_hdr_t * hdr); int oor_api_send(oor_api_connection_t *conn, void *msg, int len, int flags); int oor_api_recv(oor_api_connection_t *conn, void *buffer, int flags); void oor_api_fill_hdr(oor_api_msg_hdr_t *hdr, oor_api_msg_device_e dev, oor_api_msg_target_e trgt, oor_api_msg_opr_e opr, oor_api_msg_type_e type, int dlen); int oor_api_result_msg_new(uint8_t **buf,oor_api_msg_device_e dev, oor_api_msg_target_e trgt, oor_api_msg_opr_e opr, oor_api_msg_result_e res); int oor_api_apply_config(oor_api_connection_t *conn, int dev, int trgt, int opr, uint8_t *data, int dlen); #endif /*OOR_API_H_*/ oor-1.2.0/oor/config/oor_api_internals.c000066400000000000000000001200631313612200500202230ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "oor_api_internals.h" #include "oor_config_functions.h" #include "../lib/oor_log.h" #include "../liblisp/liblisp.h" #include "../lib/mem_util.h" #include #include #include #include #include #include #include lisp_addr_t * lxml_lcaf_get_lisp_addr (xmlNodePtr xml_lcaf); xmlNodePtr get_inner_xmlNodePtr(xmlNodePtr parent, char *name) { xmlNodePtr node; xmlChar *xmlName = xmlCharStrdup(name); node = xmlFirstElementChild(parent); while (node != NULL){ if(xmlStrEqual(node->name,xmlName)){ break; } node = xmlNextElementSibling(node); } free(xmlName); return (node); } inline xmlNodePtr lxml_get_next_node(xmlNodePtr node) { char * name = (char *)node->name; do { node = xmlNextElementSibling(node); }while(node != NULL && strcmp((char *)node->name,name) != 0); return (node); } lisp_addr_t * lxml_get_lisp_addr(xmlNodePtr xml_address) { lisp_addr_t *addr = NULL; char *str_afi; uint8_t mask; str_afi = (char*)xmlNodeGetContent(get_inner_xmlNodePtr(xml_address,"afi")); if (strcmp(str_afi,"ipv4")==0){ addr = lisp_addr_new(); lisp_addr_ip_from_char((char*)xmlNodeGetContent(get_inner_xmlNodePtr(xml_address,"ipv4")),addr); }else if (strcmp(str_afi,"ipv6") == 0){ addr = lisp_addr_new(); lisp_addr_ip_from_char((char*)xmlNodeGetContent(get_inner_xmlNodePtr(xml_address,"ipv6")),addr); }else if (strcmp(str_afi,"lcaf") == 0){ }else{ OOR_LOG(LDBG_2,"OOR_API->lxml_get_lisp_addr: Afi not supported: %s",str_afi); return NULL; } if (get_inner_xmlNodePtr(xml_address,"mask") != NULL){ mask = atoi((char*)xmlNodeGetContent(get_inner_xmlNodePtr(xml_address,"mask"))); lisp_addr_ip_to_ippref(addr); ip_prefix_set_plen(lisp_addr_get_ippref(addr),mask); } return (addr); } char * lxml_get_char_lisp_addr(xmlNodePtr xml_address, char *name, shash_t *lcaf_ht) { char *lisp_address_str; char *addr; char *mask; char *str_afi; xmlNodePtr xml_lcaf; lisp_addr_t *laddr; str_afi = (char*)xmlNodeGetContent(get_inner_xmlNodePtr(xml_address,"afi")); if (strcmp(str_afi,"ipv4")==0){ addr = (char*)xmlNodeGetContent(get_inner_xmlNodePtr(xml_address,"ipv4")); }else if (strcmp(str_afi,"ipv6") == 0){ addr = (char*)xmlNodeGetContent(get_inner_xmlNodePtr(xml_address,"ipv6")); }else if (strcmp(str_afi,"lcaf") == 0){ free(str_afi); /* Process lcaf address */ xml_lcaf = get_inner_xmlNodePtr(xml_address,"lcaf"); laddr = lxml_lcaf_get_lisp_addr(xml_lcaf); if (laddr == NULL){ OOR_LOG(LDBG_2,"OOR_API->lxml_get_char_lisp_addr: Error processing lcaf address"); return (NULL); } shash_insert(lcaf_ht,strdup(name),laddr); return (strdup(name)); }else{ OOR_LOG(LDBG_2,"OOR_API->lxml_get_char_lisp_addr: Afi not supported: %s",str_afi); free(str_afi); return (NULL); } free(str_afi); /* Process a prefix */ if (get_inner_xmlNodePtr(xml_address,"mask") != NULL){ mask = (char*)xmlNodeGetContent(get_inner_xmlNodePtr(xml_address,"mask")); lisp_address_str = xmalloc(strlen(addr)+strlen(mask)+1+1); sprintf(lisp_address_str,"%s/%s",addr,mask); free(addr); free(mask); }else{ lisp_address_str = addr; } return lisp_address_str; } int lxml_get_iid_lisp_addr(xmlNodePtr xml_address) { int iid; if (get_inner_xmlNodePtr(xml_address,"instance-id") != NULL){ iid = atoi((char*)xmlNodeGetContent(get_inner_xmlNodePtr(xml_address,"instance-id"))); return(iid); } return (0); } lisp_addr_t * lxml_lcaf_get_lisp_addr (xmlNodePtr xml_lcaf) { lisp_addr_t *lcaf_addr; lisp_addr_t *addr; char *str_addr; char *lcaf_type; char *elp_bits; uint8_t lookup_bit = FALSE; uint8_t rloc_probe_bit = FALSE; uint8_t strict_bit = FALSE; xmlNodePtr xml_elp; xmlNodePtr xml_elp_node; elp_t *elp; elp_node_t *enode; lcaf_type = (char*)xmlNodeGetContent(get_inner_xmlNodePtr(xml_lcaf,"lcaf-type")); if (strcmp (lcaf_type,"explicit-locator-path") == 0){ lcaf_addr = lisp_addr_elp_new(); elp = (elp_t *)lisp_addr_lcaf_addr(lcaf_addr); xml_elp = get_inner_xmlNodePtr(xml_lcaf,"explicit-locator-path"); xml_elp_node = get_inner_xmlNodePtr(xml_elp,"hop"); while (xml_elp_node != NULL){ /* Process address */ str_addr = (char*)xmlNodeGetContent(get_inner_xmlNodePtr(xml_elp_node,"address")); addr = lisp_addr_new(); lisp_addr_ip_from_char(str_addr,addr); free(str_addr); /* Process bits */ elp_bits = (char*)xmlNodeGetContent(get_inner_xmlNodePtr(xml_elp_node,"lrs-bits")); if (strstr(elp_bits,"lookup") != NULL){ lookup_bit = TRUE; } if (strstr(elp_bits,"rloc-probe") != NULL){ rloc_probe_bit = TRUE; } if (strstr(elp_bits,"strict") != NULL){ strict_bit = TRUE; } free (elp_bits); enode = elp_node_new_init(addr, lookup_bit, rloc_probe_bit, strict_bit); if (enode != NULL){ elp_add_node(elp, enode); } lisp_addr_del(addr); xml_elp_node = lxml_get_next_node(xml_elp_node); } }else { OOR_LOG(LDBG_2,"OOR_API->lxml_lcaf_get_lisp_addr: LCAF type not supported: %s",lcaf_type); return (NULL); } free(lcaf_type); return (lcaf_addr); } conf_mapping_t * lxml_get_conf_mapping (xmlNodePtr xml_local_eid, shash_t * lcaf_ht) { conf_mapping_t *conf_mapping; conf_loc_t *conf_loct; conf_loc_iface_t *conf_loct_iface; xmlNodePtr xml_rlocs; xmlNodePtr xml_rloc; xmlNodePtr xml_ifce_rloc; xmlNodePtr xml_addr_rloc; char *eid; char *rloc; char *eid_name; char *rloc_name; int ttl = 0; int prty = 255; int wght = 0; int mprty = 255; int mwght = 0; eid_name = (char*)xmlNodeGetContent(get_inner_xmlNodePtr(xml_local_eid,"id")); eid = lxml_get_char_lisp_addr(get_inner_xmlNodePtr(xml_local_eid,"eid-address"),eid_name,lcaf_ht); free(eid_name); if (eid == NULL){ OOR_LOG(LDBG_1,"OOR_API->oor_api_nc_xtr_mapdb_add: Error processing EID"); return NULL; } conf_mapping = conf_mapping_new(); if (conf_mapping == NULL){ free (eid); return NULL; } conf_mapping->eid_prefix = eid; conf_mapping->iid = lxml_get_iid_lisp_addr(get_inner_xmlNodePtr(xml_local_eid,"eid-address")); if (get_inner_xmlNodePtr(xml_local_eid,"record-ttl") != NULL){ ttl = atoi((char*)xmlNodeGetContent(get_inner_xmlNodePtr(xml_local_eid,"record-ttl"))); conf_mapping->ttl = ttl; } /* Process locators */ xml_rlocs = get_inner_xmlNodePtr(xml_local_eid,"rlocs"); xml_rloc = get_inner_xmlNodePtr(xml_rlocs,"rloc"); while (xml_rloc != NULL){ if (get_inner_xmlNodePtr(xml_rloc,"priority") != NULL){ prty = atoi((char*)xmlNodeGetContent(get_inner_xmlNodePtr(xml_rloc,"priority"))); } if (get_inner_xmlNodePtr(xml_rloc,"weight") != NULL){ wght = atoi((char*)xmlNodeGetContent(get_inner_xmlNodePtr(xml_rloc,"weight"))); } if (get_inner_xmlNodePtr(xml_rloc,"mpriority") != NULL){ mprty = atoi((char*)xmlNodeGetContent(get_inner_xmlNodePtr(xml_rloc,"multicast-priority"))); } if (get_inner_xmlNodePtr(xml_rloc,"mweight") != NULL){ mwght = atoi((char*)xmlNodeGetContent(get_inner_xmlNodePtr(xml_rloc,"multicast-weight"))); } if (get_inner_xmlNodePtr(xml_rloc,"interface")!=NULL){ xml_ifce_rloc = get_inner_xmlNodePtr(xml_rloc,"interface"); conf_loct_iface = conf_loc_iface_new_init((char*)xmlNodeGetContent(xml_ifce_rloc),AF_INET,prty,wght,mprty,mwght); if (conf_loct_iface == NULL){ conf_mapping_destroy(conf_mapping); return NULL; } glist_add(conf_loct_iface,conf_mapping->conf_loc_iface_list); conf_loct_iface = conf_loc_iface_new_init((char*)xmlNodeGetContent(xml_ifce_rloc),AF_INET6,prty,wght,mprty,mwght); if (conf_loct_iface == NULL){ conf_mapping_destroy(conf_mapping); return NULL; } glist_add(conf_loct_iface,conf_mapping->conf_loc_iface_list); }else if (get_inner_xmlNodePtr(xml_rloc,"locator-address")!=NULL){ rloc_name = (char*)xmlNodeGetContent(get_inner_xmlNodePtr(xml_rloc,"name")); xml_addr_rloc = get_inner_xmlNodePtr(xml_rloc,"locator-address"); rloc = lxml_get_char_lisp_addr(xml_addr_rloc, rloc_name, lcaf_ht); free(rloc_name); if (rloc == NULL){ conf_mapping_destroy(conf_mapping); return NULL; } conf_loct = conf_loc_new_init(rloc,prty,wght,mprty,mwght); free(rloc); if (conf_loct == NULL){ conf_mapping_destroy(conf_mapping); return NULL; } glist_add(conf_loct,conf_mapping->conf_loc_list); }else{ conf_mapping_destroy(conf_mapping); OOR_LOG(LDBG_1,"OOR_API->oor_api_nc_xtr_mapdb_add: Error processing locator"); return NULL; } xml_rloc = lxml_get_next_node(xml_rloc); } return (conf_mapping); } int lxml_update_map_server_list(xmlNodePtr xml_map_servers, uint8_t proxy_reply, glist_t *map_servers_list) { xmlNodePtr xml_map_sever; xmlNodePtr xml_address; xmlNodePtr xml_key_type; xmlNodePtr xml_key; map_server_elt *ms; char *str_addr; char *key_type_aux; int key_type; char *key; lisp_addr_t *ms_addr; glist_entry_t *ms_it; xml_map_sever = get_inner_xmlNodePtr(xml_map_servers,"map-server"); while (xml_map_sever != NULL){ /* Check parameters */ xml_address = get_inner_xmlNodePtr(xml_map_sever,"address"); if ((xml_address) == NULL){ OOR_LOG (LWRN,"lxml_update_map_server_list: No map server address configured"); return (BAD); } if ((xml_key_type = get_inner_xmlNodePtr(xml_map_sever,"auth-key-type")) == NULL){ OOR_LOG (LWRN,"lxml_update_map_server_list: No authentication key type specified"); return (BAD); } if ((xml_key = get_inner_xmlNodePtr(xml_map_sever,"auth-key")) == NULL){ OOR_LOG (LWRN,"lxml_update_map_server_list: No authentication key specified"); return (BAD); } str_addr = (char*)xmlNodeGetContent(xml_address); key = (char*)xmlNodeGetContent(xml_key); key_type_aux = (char*)xmlNodeGetContent(xml_key_type); if (strcmp(key_type_aux,"none")==0){ key_type = NO_KEY; }else if (strcmp(key_type_aux,"hmac-sha-1-96")==0){ key_type = HMAC_SHA_1_96; }else if (strcmp(key_type_aux,"hmac-sha-256-128")==0){ key_type = HMAC_SHA_256_128; } free(key_type_aux); if (key_type != HMAC_SHA_1_96){ OOR_LOG(LERR, "Configuration file: Only SHA-1 (1) authentication is supported"); free(str_addr); free(key); return (BAD); } ms_addr = lisp_addr_new(); if (ms_addr == NULL){ OOR_LOG(LWRN,"lxml_update_map_server_list: Couldn't allocate memory for a lisp_addr_t structure"); free(str_addr); free(key); return (BAD); } if (lisp_addr_ip_from_char(str_addr,ms_addr) != GOOD){ OOR_LOG(LWRN,"lxml_update_map_server_list: Error processing address: %s",str_addr); free(str_addr); free(key); return (BAD); } free(str_addr); /* Check if the Map Server is already in the list */ glist_for_each_entry(ms_it, map_servers_list) { ms = (map_server_elt *)glist_entry_data(ms_it); if (lisp_addr_cmp(ms->address,ms_addr) == 0){ lisp_addr_del(ms_addr); free(key); OOR_LOG(LDBG_2,"lxml_update_map_server_list: Map server %s already exist. Skipping it ...", lisp_addr_to_char(ms_addr)); xml_map_sever = lxml_get_next_node(xml_map_sever); continue; } } /* Check default afi */ if (default_rloc_afi != AF_UNSPEC && default_rloc_afi != lisp_addr_ip_afi(ms_addr)){ OOR_LOG(LWRN, "The map server %s will not be added due to the selected " "default rloc afi (-a option)", str_addr); lisp_addr_del(ms_addr); free(key); xml_map_sever = lxml_get_next_node(xml_map_sever); continue; } /* Create map server structure and add to the list */ ms = map_server_elt_new_init(ms_addr,key_type,key,proxy_reply); free(key); lisp_addr_del(ms_addr); if (ms == NULL){ return (BAD); } glist_add(ms,map_servers_list); xml_map_sever = lxml_get_next_node(xml_map_sever); } return(GOOD); } int oor_api_init_server(oor_api_connection_t *conn) { int error; conn->context = zmq_ctx_new(); OOR_LOG(LDBG_3,"OOR_API: zmq_ctx_new errno: %s\n",zmq_strerror (errno)); //Request-Reply communication pattern (Server side) conn->socket = zmq_socket(conn->context, ZMQ_REP); OOR_LOG(LDBG_3,"OOR_API: zmq_socket: %s\n",zmq_strerror (errno)); //Attachment point for other processes error = zmq_bind(conn->socket, IPC_FILE); if (error != 0){ OOR_LOG(LDBG_2,"OOR_API: Error while ZMQ binding on server: %s\n",zmq_strerror (error)); goto err; } OOR_LOG(LDBG_2,"OOR_API: API server initiated using ZMQ\n"); return (GOOD); err: OOR_LOG(LERR,"OOR_API: The API server couldn't be initialized.\n"); return (BAD); } int oor_api_xtr_mr_create(oor_api_connection_t *conn, oor_api_msg_hdr_t *hdr, uint8_t *data) { lisp_xtr_t *xtr; uint8_t *result_msg; int result_msg_len; glist_t *list; xmlDocPtr doc; xmlNodePtr root_element; xmlNodePtr mr_list_xml; xmlNodePtr mr_addr_xml; lisp_addr_t *mr_addr; OOR_LOG(LDBG_1, "OOR_API: Creating new list of Map Resolvers"); xtr = CONTAINER_OF(ctrl_dev, lisp_xtr_t, super); list = glist_new_managed((glist_del_fct)lisp_addr_del); doc = xmlReadMemory ((const char *)data, hdr->datalen, NULL, "UTF-8", XML_PARSE_NOBLANKS|XML_PARSE_NSCLEAN|XML_PARSE_NOERROR|XML_PARSE_NOWARNING); root_element = xmlDocGetRootElement(doc); mr_list_xml = get_inner_xmlNodePtr(root_element,"map-resolvers"); mr_list_xml = get_inner_xmlNodePtr(mr_list_xml,"map-resolver"); while (mr_list_xml != NULL){ mr_addr_xml = get_inner_xmlNodePtr(mr_list_xml,"map-resolver-address"); while (mr_addr_xml != NULL){; mr_addr = lisp_addr_new(); if (lisp_addr_ip_from_char((char*)xmlNodeGetContent(mr_addr_xml),mr_addr) != GOOD){ OOR_LOG(LDBG_1,"oor_api_xtr_mr_create: Could not parse Map Resolver: %s", (char*)xmlNodeGetContent(mr_addr_xml)); goto err; } if (default_rloc_afi != AF_UNSPEC && default_rloc_afi != lisp_addr_ip_afi(mr_addr)){ OOR_LOG(LWRN, "oor_api_xtr_mr_create: The Map Resolver %s will not be added due to the selected " "default rloc afi (-a option)", lisp_addr_to_char(mr_addr)); goto err; } if (glist_contain_using_cmp_fct(mr_addr, list, (glist_cmp_fct)lisp_addr_cmp)){ OOR_LOG(LWRN, "oor_api_xtr_mr_create: The Map Resolver %s is duplicated. Descarding all the list.", lisp_addr_to_char(mr_addr)); goto err; } glist_add_tail(lisp_addr_clone(mr_addr), list); mr_addr_xml = lxml_get_next_node(mr_addr_xml); } mr_list_xml = lxml_get_next_node(mr_list_xml); } xmlFreeDoc(doc); doc = NULL; //Everything fine. We replace the old list with the new one glist_destroy(xtr->map_resolvers); xtr->map_resolvers = list; OOR_LOG(LDBG_1, "OOR_API: List of Map Resolvers successfully created"); OOR_LOG(LDBG_2, "************* %13s ***************", "Map Resolvers"); glist_dump(xtr->map_resolvers, (glist_to_char_fct)lisp_addr_to_char, LDBG_1); result_msg_len = oor_api_result_msg_new(&result_msg,hdr->device,hdr->target,hdr->operation,OOR_API_RES_OK); oor_api_send(conn,result_msg,result_msg_len,OOR_API_NOFLAGS); return (GOOD); err: OOR_LOG(LERR, "OOR_API: Error while creating Map Resolver list"); glist_destroy(list); if (doc != NULL){ xmlFreeDoc(doc); } result_msg_len = oor_api_result_msg_new(&result_msg,hdr->device,hdr->target,hdr->operation,OOR_API_RES_ERR); oor_api_send(conn,result_msg,result_msg_len,OOR_API_NOFLAGS); return (BAD); } int oor_api_xtr_mr_delete(oor_api_connection_t *conn, oor_api_msg_hdr_t *hdr, uint8_t *data) { lisp_xtr_t *xtr; uint8_t *result_msg; int result_msg_len; OOR_LOG(LDBG_2, "OOR_API: Deleting Map Resolver list"); xtr = CONTAINER_OF(ctrl_dev, lisp_xtr_t, super); if (glist_size(xtr->map_resolvers) == 0){ result_msg_len = oor_api_result_msg_new(&result_msg,hdr->device,hdr->target,hdr->operation,OOR_API_RES_ERR); oor_api_send(conn,result_msg,result_msg_len,OOR_API_NOFLAGS); OOR_LOG(LWRN, "OOR_API: Trying to remove Map Resolver list, but list was already empty"); return BAD; } glist_remove_all(xtr->map_resolvers); result_msg_len = oor_api_result_msg_new(&result_msg,hdr->device,hdr->target,hdr->operation,OOR_API_RES_OK); oor_api_send(conn,result_msg,result_msg_len,OOR_API_NOFLAGS); OOR_LOG(LDBG_1, "OOR_API: Map Resolver list deleted"); return (GOOD); } int oor_api_xtr_ms_create(oor_api_connection_t *conn, oor_api_msg_hdr_t *hdr, uint8_t *data) { lisp_xtr_t *xtr; xmlDocPtr doc; xmlNodePtr root_element; xmlNodePtr xml_map_servers; xmlNodePtr xml_ms_proxy_reply; int result_msg_len; uint8_t *result_msg; glist_t * map_servers_list; char * str_proxy_reply; uint8_t proxy_reply = FALSE; OOR_LOG(LDBG_1, "OOR_API: Creating new map servers list"); xtr = CONTAINER_OF(ctrl_dev, lisp_xtr_t, super); doc = xmlReadMemory ((const char *)data, hdr->datalen, NULL, "UTF-8", XML_PARSE_NOBLANKS|XML_PARSE_NSCLEAN|XML_PARSE_NOERROR|XML_PARSE_NOWARNING); root_element = xmlDocGetRootElement(doc); xml_map_servers = xmlFirstElementChild(root_element); xml_ms_proxy_reply = get_inner_xmlNodePtr(xml_map_servers,"proxy-reply"); if (xml_ms_proxy_reply != NULL){ str_proxy_reply = (char *)xmlNodeGetContent(xml_ms_proxy_reply); if (strcmp(str_proxy_reply,"true") == 0){ proxy_reply = TRUE; } } map_servers_list = glist_new_managed((glist_del_fct)map_server_elt_del); if (lxml_update_map_server_list(xml_map_servers,proxy_reply, map_servers_list)!=GOOD){ OOR_LOG(LDBG_1,"oor_api_xtr_ms_create: Error adding map servers"); goto err; } xmlFreeDoc(doc); doc = NULL; /* Everything fine. We replace the old list with the new one */ glist_destroy(xtr->map_servers); xtr->map_servers = map_servers_list; /* Reprogram Map Register for local EIDs */ program_map_register(xtr); OOR_LOG(LDBG_1, "OOR_API: List of Map Servers successfully created"); map_servers_dump(xtr, LDBG_1); result_msg_len = oor_api_result_msg_new(&result_msg,hdr->device,hdr->target,hdr->operation,OOR_API_RES_OK); oor_api_send(conn,result_msg,result_msg_len,OOR_API_NOFLAGS); return (GOOD); err: glist_destroy(map_servers_list); if (doc != NULL){ xmlFreeDoc(doc); } result_msg_len = oor_api_result_msg_new(&result_msg,hdr->device,hdr->target,hdr->operation,OOR_API_RES_ERR); oor_api_send(conn,result_msg,result_msg_len,OOR_API_NOFLAGS); OOR_LOG(LWRN, "OOR_API: Error while setting new Map Servers list"); return (BAD); } int oor_api_xtr_ms_delete(oor_api_connection_t *conn, oor_api_msg_hdr_t *hdr, uint8_t *data) { lisp_xtr_t *xtr; uint8_t *result_msg; int result_msg_len; OOR_LOG(LDBG_2, "OOR_API: Deleting Map Servers list"); xtr = CONTAINER_OF(ctrl_dev, lisp_xtr_t, super); if (glist_size(xtr->map_servers) == 0){ //ERROR: Already NULL result_msg_len = oor_api_result_msg_new(&result_msg,hdr->device,hdr->target,hdr->operation,OOR_API_RES_ERR); oor_api_send(conn,result_msg,result_msg_len,OOR_API_NOFLAGS); OOR_LOG(LWRN, "OOR_API: Trying to remove Map Resolver list, but list was already empty"); return (BAD); } glist_remove_all(xtr->map_servers); result_msg_len = oor_api_result_msg_new(&result_msg,hdr->device,hdr->target,hdr->operation,OOR_API_RES_OK); oor_api_send(conn,result_msg,result_msg_len,OOR_API_NOFLAGS); OOR_LOG(LDBG_1, "OOR_API: Map Servers list deleted"); return (GOOD); } int oor_api_xtr_mapdb_create(oor_api_connection_t *conn, oor_api_msg_hdr_t *hdr, uint8_t *data) { lisp_xtr_t *xtr; mapping_t *processed_mapping; map_local_entry_t *map_loc_e, *db_map_loc_e; shash_t *lcaf_ht; void *it; xmlDocPtr doc; xmlNodePtr root_element; xmlNodePtr xml_local_eids; xmlNodePtr xml_local_eid; conf_mapping_t *conf_mapping; glist_t *conf_mapping_list; glist_t *smr_lcl_map_e_list; glist_t *lcl_map_e_list; glist_entry_t *conf_map_it; glist_entry_t *local_map_entry_it; int result_msg_len; uint8_t *result_msg; int ipv4_mapings = 0; int ipv6_mapings = 0; int eid_ip_afi; OOR_LOG(LDBG_1, "OOR_API: Creating new local data base"); lcaf_ht = shash_new_managed((free_value_fn_t)lisp_addr_del); conf_mapping_list = glist_new_managed((glist_del_fct)conf_mapping_destroy); smr_lcl_map_e_list = glist_new(); lcl_map_e_list = glist_new(); xtr = CONTAINER_OF(ctrl_dev, lisp_xtr_t, super); doc = xmlReadMemory ((const char *)data, hdr->datalen, NULL, "UTF-8", XML_PARSE_NOBLANKS|XML_PARSE_NSCLEAN|XML_PARSE_NOERROR|XML_PARSE_NOWARNING); root_element = xmlDocGetRootElement(doc); xml_local_eids = xmlFirstElementChild(root_element); xml_local_eid = xmlFirstElementChild(xml_local_eids); while (xml_local_eid != NULL){ conf_mapping = lxml_get_conf_mapping (xml_local_eid, lcaf_ht); if (conf_mapping == NULL){ goto err; } glist_add(conf_mapping,conf_mapping_list); xml_local_eid = lxml_get_next_node(xml_local_eid); } xmlFreeDoc(doc); doc = NULL; /* We leverage on the OOR configuration subsystem to introduce * and process the configuration mappings into the system */ glist_for_each_entry(conf_map_it, conf_mapping_list){ conf_mapping = (conf_mapping_t *) glist_entry_data(conf_map_it); //XXX Beware the NULL in lcaf_ht. No LCAF support yet processed_mapping = process_mapping_config(&(xtr->super),lcaf_ht,conf_mapping, TRUE); if (processed_mapping == NULL){ OOR_LOG(LDBG_2, "OOR_API: Couldn't process mapping %s",conf_mapping->eid_prefix); goto err; } /* If dev is a mobile node, we can only have one IPv4 and one IPv6 mapping */ if (ctrl_dev_mode(ctrl_dev) == MN_MODE){ eid_ip_afi = lisp_addr_ip_afi((lisp_addr_get_ip_pref_addr(mapping_eid(processed_mapping))));; if (eid_ip_afi == AF_INET){ ipv4_mapings ++; }else if (eid_ip_afi == AF_INET6){ ipv6_mapings ++; } if (ipv4_mapings >1 || ipv6_mapings >1){ OOR_LOG(LWRN, "OOR_API: LISP Mobile Node only supports one IPv4 and one IPv6 EID prefix"); break; } } mapping_set_auth(processed_mapping, 1); map_loc_e = map_local_entry_new_init(processed_mapping); if (map_loc_e == NULL){ OOR_LOG(LDBG_2, "OOR_API: Couldn't allocate map_local_entry_t %s",conf_mapping->eid_prefix); goto err; } if (xtr->fwd_policy->init_map_loc_policy_inf( xtr->fwd_policy_dev_parm, map_loc_e, NULL) != GOOD){ OOR_LOG(LDBG_2, "OOR_API: Couldn't initiate forward information for mapping with EID: %s",conf_mapping->eid_prefix); goto err; } /* Classify entries that are already configured in the data base */ if ((db_map_loc_e = local_map_db_lookup_eid_exact(xtr->local_mdb, mapping_eid(processed_mapping))) != NULL){ /* If the mapping already exist but has been modified add to the list of mappings to SMR */ if (mapping_cmp(map_local_entry_mapping(db_map_loc_e), processed_mapping) != 0){ glist_add(map_loc_e,smr_lcl_map_e_list); } } glist_add(map_loc_e,lcl_map_e_list); } /* * Empty previous local database */ /* Remove routing configuration for the eids */ local_map_db_foreach_entry(xtr->local_mdb, it) { map_loc_e = (map_local_entry_t *)it; ctrl_unregister_mapping_dp(ctrl_dev, map_local_entry_mapping(map_loc_e)); } local_map_db_foreach_end; /* Empty local database */ local_map_db_del(xtr->local_mdb); xtr->local_mdb = local_map_db_new(); /* Add the local map entries to the data base */ glist_for_each_entry(local_map_entry_it, lcl_map_e_list){ map_loc_e = (map_local_entry_t *)glist_entry_data(local_map_entry_it); if (add_local_db_map_local_entry(map_loc_e,xtr) != GOOD){ OOR_LOG(LDBG_2, "OOR_API: Couldn't add mapping %s to local database", lisp_addr_to_char(map_local_entry_eid(map_loc_e))); goto err; } OOR_LOG(LDBG_1, "OOR_API: Updating data-plane for EID prefix %s", lisp_addr_to_char(map_local_entry_eid(map_loc_e))); /* Update the routing rules for the new EID */ if (ctrl_register_mapping_dp(ctrl_dev,map_local_entry_mapping(map_loc_e))!=GOOD){ OOR_LOG(LERR, "OOR_API: Unable to update data-plane for mapping %s", lisp_addr_to_char(map_local_entry_eid(map_loc_e))); goto err; } } /* Update control with new added interfaces */ ctrl_update_iface_info(ctrl_dev->ctrl); OOR_LOG(LDBG_1, "OOR_API: New local data base created"); OOR_LOG(LDBG_2, "************* %20s ***************", "Local EID Database"); local_map_db_dump(xtr->local_mdb, LDBG_1); /* Reprogram Map Register for local EIDs */ program_map_register(xtr); /* SMR of the modified entries */ glist_for_each_entry(local_map_entry_it, smr_lcl_map_e_list){ map_loc_e = (map_local_entry_t *)glist_entry_data(local_map_entry_it); send_smr_and_mreg_for_locl_mapping(xtr, map_loc_e); } result_msg_len = oor_api_result_msg_new(&result_msg,hdr->device,hdr->target,hdr->operation,OOR_API_RES_OK); oor_api_send(conn,result_msg,result_msg_len,OOR_API_NOFLAGS); glist_destroy(conf_mapping_list); glist_destroy(smr_lcl_map_e_list); glist_destroy(lcl_map_e_list); shash_destroy(lcaf_ht); return (GOOD); err: //XXX if error, destroy mappings added to local mapdb? deattach locators from ifaces? glist_destroy(conf_mapping_list); glist_destroy(smr_lcl_map_e_list); glist_destroy(lcl_map_e_list); shash_destroy(lcaf_ht); if (doc != NULL){ xmlFreeDoc(doc); } result_msg_len = oor_api_result_msg_new(&result_msg,hdr->device,hdr->target,hdr->operation,OOR_API_RES_ERR); oor_api_send(conn,result_msg,result_msg_len,OOR_API_NOFLAGS); OOR_LOG(LWRN, "OOR_API: Error while setting new Mapping Database content"); return (BAD); } int oor_api_xtr_mapdb_delete(oor_api_connection_t *conn, oor_api_msg_hdr_t *hdr, uint8_t *data) { lisp_xtr_t *xtr; map_local_entry_t *map_loc_e; void *it; uint8_t *result_msg; int result_msg_len; OOR_LOG(LDBG_2, "OOR_API: Deleting local Mapping Database list"); xtr = CONTAINER_OF(ctrl_dev, lisp_xtr_t, super); /* Remove routing configuration for the eids */ local_map_db_foreach_entry(xtr->local_mdb, it) { map_loc_e = (map_local_entry_t *)it; ctrl_unregister_mapping_dp(ctrl_dev, map_local_entry_mapping(map_loc_e)); } local_map_db_foreach_end; /* Empty local database */ local_map_db_del(xtr->local_mdb); xtr->local_mdb = local_map_db_new(); /* Send confirmation message to the API server */ result_msg_len = oor_api_result_msg_new(&result_msg,hdr->device,hdr->target,hdr->operation,OOR_API_RES_OK); oor_api_send(conn,result_msg,result_msg_len,OOR_API_NOFLAGS); OOR_LOG(LDBG_1, "OOR_API: Local Mapping Database deleted"); return (GOOD); } int oor_api_xtr_petrs_create(oor_api_connection_t *conn, oor_api_msg_hdr_t *hdr, uint8_t *data) { lisp_xtr_t *xtr; uint8_t *result_msg; int result_msg_len; glist_t *str_addr_list; char *str_addr; xmlDocPtr doc; xmlNodePtr root_element; xmlNodePtr petr_list_xml; xmlNodePtr petr_addr_xml; lisp_addr_t *petr_addr; glist_entry_t *addr_it; OOR_LOG(LDBG_1, "OOR_API: Creating new list of Proxy ETRs"); xtr = CONTAINER_OF(ctrl_dev, lisp_xtr_t, super); str_addr_list = glist_new_managed(free); doc = xmlReadMemory ((const char *)data, hdr->datalen, NULL, "UTF-8", XML_PARSE_NOBLANKS|XML_PARSE_NSCLEAN|XML_PARSE_NOERROR|XML_PARSE_NOWARNING); root_element = xmlDocGetRootElement(doc); petr_list_xml = get_inner_xmlNodePtr(root_element,"proxy-etrs"); petr_list_xml = get_inner_xmlNodePtr(petr_list_xml,"proxy-etr"); while (petr_list_xml != NULL){ petr_addr_xml = get_inner_xmlNodePtr(petr_list_xml,"proxy-etr-address"); while (petr_addr_xml != NULL){ str_addr = (char*)xmlNodeGetContent(petr_addr_xml); /* We do some checks before adding the address to the aux list */ petr_addr = lisp_addr_new(); if (lisp_addr_ip_from_char(str_addr,petr_addr) != GOOD){ OOR_LOG(LDBG_1,"oor_api_xtr_mr_create: Could not parse Proxy ETR address: %s", str_addr); goto err; } if (default_rloc_afi != AF_UNSPEC && default_rloc_afi != lisp_addr_ip_afi(petr_addr)){ OOR_LOG(LWRN, "oor_api_xtr_mr_create: The Proxy ETR %s will not be added due to the selected " "default rloc afi (-a option)", str_addr); goto err; } if (glist_contain_using_cmp_fct(str_addr, str_addr_list, (glist_cmp_fct)strcmp)){ OOR_LOG(LWRN, "oor_api_xtr_petr_create: The Proxy ETR %s is duplicated. Descarding all the list.", str_addr); goto err; } glist_add_tail(str_addr, str_addr_list); lisp_addr_del(petr_addr); petr_addr_xml = lxml_get_next_node(petr_addr_xml); } petr_list_xml = lxml_get_next_node(petr_list_xml); } xmlFreeDoc(doc); doc = NULL; //Everything fine. We replace the old list with the new one glist_remove_all(mapping_locators_lists(mcache_entry_mapping(xtr->petrs_ipv4))); glist_remove_all(mapping_locators_lists(mcache_entry_mapping(xtr->petrs_ipv6))); glist_for_each_entry(addr_it,str_addr_list){ str_addr = (char *)glist_entry_data(addr_it); add_proxy_etr_entry(xtr->petrs_ipv4,str_addr,1,100); add_proxy_etr_entry(xtr->petrs_ipv6,str_addr,1,100); } xtr->fwd_policy->updated_map_cache_inf(xtr->fwd_policy_dev_parm,xtr->petrs_ipv4); notify_datap_rm_fwd_from_entry(&(xtr->super),mcache_entry_eid(xtr->petrs_ipv4),FALSE); xtr->fwd_policy->updated_map_cache_inf(xtr->fwd_policy_dev_parm,xtr->petrs_ipv6); notify_datap_rm_fwd_from_entry(&(xtr->super),mcache_entry_eid(xtr->petrs_ipv6),FALSE); OOR_LOG(LDBG_1, "OOR_API: List of Proxy ETRs successfully created"); OOR_LOG(LDBG_1, "************************* Proxy ETRs List ****************************"); mapping_to_char(mcache_entry_mapping(xtr->petrs_ipv4)); mapping_to_char(mcache_entry_mapping(xtr->petrs_ipv6)); result_msg_len = oor_api_result_msg_new(&result_msg,hdr->device,hdr->target,hdr->operation,OOR_API_RES_OK); oor_api_send(conn,result_msg,result_msg_len,OOR_API_NOFLAGS); return (GOOD); err: lisp_addr_del(petr_addr); free(str_addr); xmlFreeDoc(doc); OOR_LOG(LERR, "OOR_API: Error while creating Map Resolver list"); glist_destroy(str_addr_list); result_msg_len = oor_api_result_msg_new(&result_msg,hdr->device,hdr->target,hdr->operation,OOR_API_RES_ERR); oor_api_send(conn,result_msg,result_msg_len,OOR_API_NOFLAGS); return (BAD); } int oor_api_xtr_petrs_delete(oor_api_connection_t *conn, oor_api_msg_hdr_t *hdr, uint8_t *data) { lisp_xtr_t *xtr; uint8_t *result_msg; int result_msg_len; OOR_LOG(LDBG_2, "OOR_API: Deleting Proxy ETRs list"); xtr = CONTAINER_OF(ctrl_dev, lisp_xtr_t, super); glist_remove_all(mapping_locators_lists(mcache_entry_mapping(xtr->petrs_ipv4))); glist_remove_all(mapping_locators_lists(mcache_entry_mapping(xtr->petrs_ipv6))); result_msg_len = oor_api_result_msg_new(&result_msg,hdr->device,hdr->target,hdr->operation,OOR_API_RES_OK); oor_api_send(conn,result_msg,result_msg_len,OOR_API_NOFLAGS); return (GOOD); } int (*oor_api_get_proc_func(oor_api_msg_hdr_t* hdr))(oor_api_connection_t *, oor_api_msg_hdr_t *, uint8_t *) { int (*process_func)(oor_api_connection_t *, oor_api_msg_hdr_t *, uint8_t *) = NULL; oor_dev_type_e device = hdr->device; oor_api_msg_target_e target = hdr->target; oor_api_msg_opr_e operation = hdr->operation; switch (device){ case OOR_API_DEV_XTR: if (ctrl_dev_mode(ctrl_dev) != xTR_MODE && ctrl_dev_mode(ctrl_dev) != MN_MODE){ OOR_LOG(LDBG_1, "OOR_API call = Call API from wrong device"); break; } switch (target){ case OOR_API_TRGT_MRLIST: switch (operation){ case OOR_API_OPR_CREATE: OOR_LOG(LDBG_2, "OOR_API call = (Device: xTR | Target: MR list | Operation: Create)"); process_func = oor_api_xtr_mr_create; break; case OOR_API_OPR_DELETE: OOR_LOG(LDBG_2, "OOR_API call = (Device: xTR | Target: MR list | Operation: Delete)"); process_func = oor_api_xtr_mr_delete; break; default: OOR_LOG(LWRN, "OOR_API call = (Device: xTR | Target: MR list | Operation: Unsupported)"); break; } break; case OOR_API_TRGT_MSLIST: switch (operation){ case OOR_API_OPR_CREATE: OOR_LOG(LDBG_2, "OOR_API call = (Device: xTR | Target: MS list | Operation: Create)"); process_func = oor_api_xtr_ms_create; break; case OOR_API_OPR_DELETE: OOR_LOG(LDBG_2, "OOR_API call = (Device: xTR | Target: MS list | Operation: Delete)"); process_func = oor_api_xtr_ms_delete; break; default: OOR_LOG(LWRN, "OOR_API call = (Device: xTR | Target: MS list | Operation: Unsupported)"); break; } break; case OOR_API_TRGT_MAPDB: switch (operation){ case OOR_API_OPR_CREATE: OOR_LOG(LDBG_2, "OOR_API call = (Device: xTR | Target: Mapping DB | Operation: Create)"); process_func = oor_api_xtr_mapdb_create; break; case OOR_API_OPR_DELETE: OOR_LOG(LDBG_2, "OOR_API call = (Device: xTR | Target: Mapping DB | Operation: Delete)"); process_func = oor_api_xtr_mapdb_delete; break; default: OOR_LOG(LWRN, "OOR_API call = (Device: xTR | Target: Mapping DB | Operation: Unsupported)"); break; } break; case OOR_API_TRGT_PETRLIST: switch (operation){ case OOR_API_OPR_CREATE: OOR_LOG(LDBG_2, "OOR_API call = (Device: xTR | Target: Proxy ETRs | Operation: Create)"); process_func = oor_api_xtr_petrs_create; break; case OOR_API_OPR_DELETE: OOR_LOG(LDBG_2, "OOR_API call = (Device: xTR | Target: Proxy ETRs | Operation: Delete)"); process_func = oor_api_xtr_petrs_delete; break; default: OOR_LOG(LWRN, "OOR_API call = (Device: xTR | Target: Mapping DB | Operation: Unsupported)"); break; } break; default: OOR_LOG(LWRN, "OOR_API call = (Device: xTR | Target: Unsupported)"); break; } break; case OOR_API_DEV_RTR: if (ctrl_dev_mode(ctrl_dev) != RTR_MODE){ OOR_LOG(LDBG_1, "OOR_API call = Call API from wrong device"); break; } switch (target){ case OOR_API_TRGT_MRLIST: switch (operation){ case OOR_API_OPR_CREATE: OOR_LOG(LDBG_2, "OOR_API call = (Device: RTR | Target: MR list | Operation: Create)"); process_func = oor_api_xtr_mr_create; break; case OOR_API_OPR_DELETE: OOR_LOG(LDBG_2, "OOR_API call = (Device: RTR | Target: MR list | Operation: Delete)"); process_func = oor_api_xtr_mr_delete; break; default: OOR_LOG(LWRN, "OOR_API call = (Device: RTR | Target: MR list | Operation: Unsupported)"); break; } break; default: OOR_LOG(LWRN, "OOR_API call = (Device: RTR | Target: Unsupported)"); break; } break; default: OOR_LOG(LWRN, "OOR_API call = (Device: Unsupported)"); break; } return (process_func); } void oor_api_loop(oor_api_connection_t *conn) { uint8_t *buffer; uint8_t *data; int nbytes; int datalen; oor_api_msg_hdr_t *header; int (*process_func)(oor_api_connection_t *, oor_api_msg_hdr_t *, uint8_t *) = NULL; uint8_t *result_msg; int result_msg_len; buffer = xzalloc(MAX_API_PKT_LEN); nbytes = oor_api_recv(conn,buffer,OOR_API_DONTWAIT); if (nbytes == OOR_API_NOTHINGTOREAD){ goto end; } if (nbytes == OOR_API_ERROR){ OOR_LOG(LERR, "oor_api_loop: Error while trying to retrieve API packet\n"); goto end; } header = (oor_api_msg_hdr_t *)buffer; data = CO(buffer,sizeof(oor_api_msg_hdr_t)); datalen = nbytes - sizeof(oor_api_msg_hdr_t); if (header->datalen < datalen){ OOR_LOG(LWRN, "oor_api_loop: API packet longer than expected\n"); } else if (header->datalen > datalen){ OOR_LOG(LERR, "oor_api_loop: API packet shorter than expected\n"); goto end; } process_func = oor_api_get_proc_func(header); if (process_func != NULL){ (*process_func)(conn,header,data); }else { result_msg_len = oor_api_result_msg_new(&result_msg,header->device,header->target,header->operation,OOR_API_RES_ERR); oor_api_send(conn,result_msg,result_msg_len,OOR_API_NOFLAGS); } end: free(buffer); return; } oor-1.2.0/oor/config/oor_api_internals.h000066400000000000000000000017121313612200500202270ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef OOR_API_INTERNALS_H_ #define OOR_API_INTERNALS_H_ #include "oor_api.h" /* API main loop */ void oor_api_loop(oor_api_connection_t *conn); /* Initialize API system (server) */ int oor_api_init_server(oor_api_connection_t *conn); #endif /*OOR_API_INTERNALS_H_*/ oor-1.2.0/oor/config/oor_config_confuse.c000066400000000000000000001027701313612200500203670ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include #ifdef ANDROID #include "../android/jni/confuse_android/src/confuse.h" #else #include #endif #include "oor_config_confuse.h" #include "oor_config_functions.h" #include "../cmdline.h" #include "../iface_list.h" #include "../oor_external.h" #include "../control/oor_control.h" #include "../control/oor_ctrl_device.h" #include "../control/lisp_ms.h" #include "../control/lisp_xtr.h" #include "../data-plane/data-plane.h" #include "../lib/oor_log.h" #include "../lib/shash.h" static void parse_elp_list(cfg_t *cfg, shash_t *ht) { elp_node_t *enode; elp_t *elp; lisp_addr_t *laddr; char *name; int i, j; uint8_t good_elp; for(i = 0; i < cfg_size(cfg, "explicit-locator-path"); i++) { cfg_t *selp = cfg_getnsec(cfg, "explicit-locator-path", i); name = cfg_getstr(selp, "elp-name"); if (name == NULL){ OOR_LOG(LWRN, "Configuration file: explicit-locator-path requires an elp-name. Discarding ELP"); continue; } if (cfg_size(selp, "elp-node") == 0){ OOR_LOG(LWRN, "Configuration file: explicit-locator-path needs at least one elp node. Discarding ELP"); continue; } elp = elp_type_new(); good_elp = TRUE; for (j = 0; j < cfg_size(selp, "elp-node");j++) { cfg_t *senode = cfg_getnsec(selp, "elp-node", j); if (cfg_getstr(senode, "address") == NULL){ good_elp = FALSE; OOR_LOG(LWRN, "Configuration file: elp-node needs at least the address field. Discarding ELP"); break; } enode = xzalloc(sizeof(elp_node_t)); enode->addr = lisp_addr_new(); if (lisp_addr_ip_from_char(cfg_getstr(senode, "address"), enode->addr) != GOOD) { elp_node_del(enode); OOR_LOG(LWRN, "Configuration file: Couldn't parse ELP node %s", cfg_getstr(senode, "address")); continue; } enode->L = cfg_getbool(senode, "lookup") ? 1 : 0; enode->P = cfg_getbool(senode, "probe") ? 1 : 0; enode->S = cfg_getbool(senode, "strict") ? 1: 0; glist_add_tail(enode, elp->nodes); } if (good_elp == FALSE){ elp_type_del(elp); continue; } laddr = lisp_addr_new_lafi(LM_AFI_LCAF); lisp_addr_lcaf_set_type(laddr, LCAF_EXPL_LOC_PATH); lisp_addr_lcaf_set_addr(laddr, elp); OOR_LOG(LDBG_1, "Configuration file: parsed explicit-locator-path: %s", lisp_addr_to_char(laddr)); shash_insert(ht, strdup(name), laddr); } } static void parse_rle_list(cfg_t *cfg, shash_t *ht) { rle_node_t *rnode; rle_t *rle; lisp_addr_t *laddr; char *name; int i, j; for (i = 0; i < cfg_size(cfg, "replication-list"); i++) { cfg_t *selp = cfg_getnsec(cfg, "replication-list", i); name = cfg_getstr(selp, "rle-name"); laddr = lisp_addr_new_lafi(LM_AFI_LCAF); lisp_addr_lcaf_set_type(laddr, LCAF_RLE); rle = rle_type_new(); for (j = 0; j < cfg_size(selp, "rle-node"); j++) { cfg_t *rlenode = cfg_getnsec(selp, "rle-node", j); rnode = rle_node_new(); if (lisp_addr_ip_from_char(cfg_getstr(rlenode, "address"), rnode->addr) != GOOD) { rle_node_del(rnode); OOR_LOG(LDBG_1, "parse_rle_list: Couldn't parse RLE node %s", cfg_getstr(rlenode, "address")); } rnode->level = cfg_getint(rlenode, "level"); glist_add_tail(rnode, rle->nodes); } lisp_addr_lcaf_set_addr(laddr, (void *)rle); OOR_LOG(LDBG_1, "Configuration file: parsed replication-list: %s", lisp_addr_to_char(laddr)); shash_insert(ht, strdup(name), laddr); } } static void parse_mcinfo_list(cfg_t *cfg, shash_t *ht) { mc_t *mc; lisp_addr_t *laddr; char *name; int i, count; count = 0; for (i = 0; i < cfg_size(cfg, "multicast-info"); i++) { cfg_t *mcnode = cfg_getnsec(cfg, "multicast-info", i); name = cfg_getstr(mcnode, "mc-info-name"); laddr = lisp_addr_new_lafi(LM_AFI_LCAF); lisp_addr_lcaf_set_type(laddr, LCAF_MCAST_INFO); mc = mc_type_new(); lisp_addr_ip_from_char(cfg_getstr(mcnode, "source"), mc->src); mc->src_plen = cfg_getint(mcnode, "source-mask-length"); lisp_addr_ip_from_char(cfg_getstr(mcnode, "group"), mc->grp); mc->src_plen = cfg_getint(mcnode, "group-mask-length"); mc->iid = cfg_getint(mcnode, "iid"); lisp_addr_lcaf_set_addr(laddr, mc); OOR_LOG(LDBG_1, "Configuration file: parsed multicast-info: %s", lisp_addr_to_char(laddr)); shash_insert(ht, strdup(name), laddr); count ++; } if (count != 0) { OOR_LOG(LINF, "Parsed configured multicast addresses"); } } static shash_t * parse_lcafs(cfg_t *cfg) { shash_t *lcaf_ht; /* create lcaf hash table */ lcaf_ht = shash_new_managed((free_value_fn_t)lisp_addr_del); parse_elp_list(cfg, lcaf_ht); parse_rle_list(cfg, lcaf_ht); parse_mcinfo_list(cfg, lcaf_ht); return(lcaf_ht); } int parse_mapping_cfg_params(cfg_t *map, conf_mapping_t *conf_mapping, uint8_t is_local) { int ctr; cfg_t *rl; conf_loc_t *conf_loc; conf_loc_iface_t *conf_loc_iface; int afi; if (cfg_getstr(map, "eid-prefix") == NULL){ return (BAD); } strcpy(conf_mapping->eid_prefix,cfg_getstr(map, "eid-prefix")); conf_mapping->iid = cfg_getint(map, "iid"); for (ctr = 0; ctr < cfg_size(map, "rloc-address"); ctr++){ rl = cfg_getnsec(map, "rloc-address", ctr); if (cfg_getstr(rl, "address") == NULL){ OOR_LOG(LWRN, "Configuration file: Mapping %s with no RLOC address selected",conf_mapping->eid_prefix); return (BAD); } conf_loc = conf_loc_new_init( cfg_getstr(rl, "address"), cfg_getint(rl, "priority"), cfg_getint(rl, "weight"), 255,0); glist_add_tail(conf_loc,conf_mapping->conf_loc_list); } if (is_local){ for (ctr = 0; ctr < cfg_size(map, "rloc-iface"); ctr++){ rl = cfg_getnsec(map, "rloc-iface", ctr); afi = cfg_getint(rl, "ip_version"); if (afi == 4){ afi = AF_INET; }else if (afi == 6){ afi = AF_INET6; }else{ OOR_LOG(LERR,"Configuration file: The conf_loc_iface->ip_version of the locator should be 4 (IPv4) or 6 (IPv6)"); return (BAD); } if (cfg_getstr(rl, "interface") == NULL){ OOR_LOG(LWRN, "Configuration file: Mapping %s with no RLOC interface selected",conf_mapping->eid_prefix); return (BAD); } conf_loc_iface = conf_loc_iface_new_init( cfg_getstr(rl, "interface"), afi, cfg_getint(rl, "priority"), cfg_getint(rl, "weight"), 255,0); glist_add_tail(conf_loc_iface,conf_mapping->conf_loc_iface_list); } } return (GOOD); } mapping_t * parse_mapping(cfg_t *map, oor_ctrl_dev_t *dev, shash_t * lcaf_ht, uint8_t is_local) { mapping_t *mapping; conf_mapping_t *conf_mapping; conf_mapping = conf_mapping_new(); if (parse_mapping_cfg_params(map, conf_mapping, is_local) != GOOD){ return (NULL); } mapping = process_mapping_config(dev, lcaf_ht, conf_mapping, is_local); conf_mapping_destroy(conf_mapping); return (mapping); } int parse_map_servers(cfg_t *cfg, lisp_xtr_t *xtr) { int n,i; /* MAP-SERVER CONFIG */ n = cfg_size(cfg, "map-server"); for (i = 0; i < n; i++) { cfg_t *ms = cfg_getnsec(cfg, "map-server", i); if (add_map_server(xtr->map_servers, cfg_getstr(ms, "address"), cfg_getint(ms, "key-type"), cfg_getstr(ms, "key"), (cfg_getbool(ms, "proxy-reply") ? 1 : 0)) == GOOD) { OOR_LOG(LDBG_1, "Added %s to map-server list", cfg_getstr(ms, "address")); } else { OOR_LOG(LWRN, "Can't add %s Map Server.", cfg_getstr(ms, "address")); } } return (GOOD); } int parse_proxy_etrs(cfg_t *cfg, lisp_xtr_t *xtr) { int n,i; /* PROXY-ETR CONFIG */ n = cfg_size(cfg, "proxy-etr-ipv4"); for(i = 0; i < n; i++) { cfg_t *petr = cfg_getnsec(cfg, "proxy-etr-ipv4", i); if(cfg_getstr(petr, "address") == NULL){ OOR_LOG(LERR,"Configuration file: proxy-etr-ipv4 needs at least the address field"); return (BAD); } if (add_proxy_etr_entry(xtr->petrs_ipv4, cfg_getstr(petr, "address"), cfg_getint(petr, "priority"), cfg_getint(petr, "weight")) == GOOD) { OOR_LOG(LDBG_1, "Added %s to proxy-etr list for IPv4 EIDs", cfg_getstr(petr, "address")); } else{ OOR_LOG(LERR, "Can't add proxy-etr %s", cfg_getstr(petr, "address")); } } n = cfg_size(cfg, "proxy-etr-ipv6"); for(i = 0; i < n; i++) { cfg_t *petr = cfg_getnsec(cfg, "proxy-etr-ipv6", i); if(cfg_getstr(petr, "address") == NULL){ OOR_LOG(LERR,"Configuration file: proxy-etr-ipv6 needs at least the address field"); return (BAD); } if (add_proxy_etr_entry(xtr->petrs_ipv6, cfg_getstr(petr, "address"), cfg_getint(petr, "priority"), cfg_getint(petr, "weight")) == GOOD) { OOR_LOG(LDBG_1, "Added %s to proxy-etr list for IPv6 EIDs", cfg_getstr(petr, "address")); } else{ OOR_LOG(LERR, "Can't add proxy-etr %s", cfg_getstr(petr, "address")); } } /* Calculate forwarding info for petrs */ if (xtr->fwd_policy->init_map_cache_policy_inf(xtr->fwd_policy_dev_parm,xtr->petrs_ipv4) != GOOD){ OOR_LOG(LDBG_1, "parse_proxy_etrs: Couldn't initiate routing info for PeTRs!."); mcache_entry_del(xtr->petrs_ipv4); return(BAD); } if (xtr->fwd_policy->init_map_cache_policy_inf(xtr->fwd_policy_dev_parm,xtr->petrs_ipv6) != GOOD){ OOR_LOG(LDBG_1, "parse_proxy_etrs: Couldn't initiate routing info for PeTRs!."); mcache_entry_del(xtr->petrs_ipv6); return(BAD); } return (GOOD); } int parse_proxy_itrs(cfg_t *cfg, lisp_xtr_t *xtr) { int n,i; char *proxy_itr; n = cfg_size(cfg, "proxy-itrs"); for(i = 0; i < n; i++) { if ((proxy_itr = cfg_getnstr(cfg, "proxy-itrs", i)) != NULL) { if (add_server(proxy_itr, xtr->pitrs)==GOOD){ OOR_LOG(LDBG_1, "Added %s to proxy-itr list", proxy_itr); }else { OOR_LOG(LERR, "Can't add %s to proxy-itr list. Discarded ...", proxy_itr); } } } return (GOOD); } int parse_database_mapping(cfg_t *cfg, lisp_xtr_t *xtr, shash_t *lcaf_ht) { int n,i; mapping_t *mapping; map_local_entry_t *map_loc_e; n = cfg_size(cfg, "database-mapping"); for (i = 0; i < n; i++) { mapping = parse_mapping(cfg_getnsec(cfg, "database-mapping", i),&(xtr->super),lcaf_ht,TRUE); if (mapping == NULL){ return (BAD); } map_loc_e = map_local_entry_new_init(mapping); if (map_loc_e == NULL){ mapping_del(mapping); continue; } if (xtr->fwd_policy->init_map_loc_policy_inf( xtr->fwd_policy_dev_parm,map_loc_e,NULL)!= GOOD){ OOR_LOG(LERR, "Couldn't inititate forward information for mapping with EID: %s. Discarding it...", lisp_addr_to_char(mapping_eid(mapping))); map_local_entry_del(map_loc_e); continue; } if (add_local_db_map_local_entry(map_loc_e,xtr) != GOOD){ map_local_entry_del(map_loc_e); continue; } } return (GOOD); } int configure_tunnel_router(cfg_t *cfg, lisp_xtr_t *xtr, shash_t *lcaf_ht) { int i,n,ret; char *map_resolver; char *encap; mapping_t *mapping; /* FWD POLICY STRUCTURES */ #ifdef VPP xtr->fwd_policy = fwd_policy_class_find("vpp_balancing"); #else xtr->fwd_policy = fwd_policy_class_find("flow_balancing"); #endif xtr->fwd_policy_dev_parm = xtr->fwd_policy->new_dev_policy_inf(ctrl_dev,NULL); if ((encap = cfg_getstr(cfg, "encapsulation")) != NULL) { if (strcmp(encap, "LISP") == 0) { xtr->encap_type = ENCP_LISP; }else if (strcmp(encap, "VXLAN-GPE") == 0){ xtr->encap_type = ENCP_VXLAN_GPE; }else{ OOR_LOG(LERR, "Unknown encapsulation type: %s",encap); return (BAD); } } /* RETRIES */ ret = cfg_getint(cfg, "map-request-retries"); xtr->map_request_retries = (ret != 0) ? ret : DEFAULT_MAP_REQUEST_RETRIES; /* RLOC PROBING CONFIG */ cfg_t *dm = cfg_getnsec(cfg, "rloc-probing", 0); if (dm != NULL) { xtr->probe_interval = cfg_getint(dm, "rloc-probe-interval"); xtr->probe_retries = cfg_getint(dm, "rloc-probe-retries"); xtr->probe_retries_interval = cfg_getint(dm, "rloc-probe-retries-interval"); validate_rloc_probing_parameters(&xtr->probe_interval, &xtr->probe_retries, &xtr->probe_retries_interval); } else { OOR_LOG(LDBG_1, "Configuration file: RLOC probing not defined. " "Setting default values: RLOC Probing Interval: %d sec.", RLOC_PROBING_INTERVAL); xtr->probe_interval = RLOC_PROBING_INTERVAL; xtr->probe_retries = DEFAULT_RLOC_PROBING_RETRIES; xtr->probe_retries_interval = DEFAULT_RLOC_PROBING_RETRIES_INTERVAL; } /* MAP-RESOLVER CONFIG */ n = cfg_size(cfg, "map-resolver"); for(i = 0; i < n; i++) { if ((map_resolver = cfg_getnstr(cfg, "map-resolver", i)) != NULL) { if (add_server(map_resolver, xtr->map_resolvers) == GOOD){ OOR_LOG(LDBG_1, "Added %s to map-resolver list", map_resolver); }else{ OOR_LOG(LCRIT,"Can't add %s Map Resolver.",map_resolver); } } } /* STATIC MAP-CACHE CONFIG */ n = cfg_size(cfg, "static-map-cache"); for (i = 0; i < n; i++) { cfg_t *smc = cfg_getnsec(cfg, "static-map-cache", i); mapping = parse_mapping(smc,&(xtr->super),lcaf_ht,FALSE); if (mapping == NULL){ OOR_LOG(LERR, "Can't add static Map Cache entry with EID prefix %s. Discarded ...", cfg_getstr(smc, "eid-prefix")); return(BAD); } if (mcache_lookup_exact(xtr->map_cache, mapping_eid(mapping)) == NULL){ if (tr_mcache_add_static_mapping(xtr, mapping) == GOOD){ OOR_LOG(LDBG_1, "Added static Map Cache entry with EID prefix %s in the database.", lisp_addr_to_char(mapping_eid(mapping))); }else{ OOR_LOG(LERR, "Can't add static Map Cache entry with EID prefix %s. Discarded ...", mapping_eid(mapping)); mapping_del(mapping); } }else{ OOR_LOG(LERR, "Configuration file: Duplicated static Map Cache entry with EID prefix %s." "Discarded ...",cfg_getstr(smc, "eid-prefix")); mapping_del(mapping); continue; } continue; } return (GOOD); } int configure_rtr(cfg_t *cfg) { lisp_xtr_t *xtr; shash_t *lcaf_ht; map_local_entry_t *map_loc_e; mapping_t *mapping; int n,i; /* CREATE AND CONFIGURE RTR (xTR in fact) */ if (ctrl_dev_create(RTR_MODE, &ctrl_dev) != GOOD) { OOR_LOG(LCRIT, "Failed to create RTR. Aborting!"); return (BAD); } lcaf_ht = parse_lcafs(cfg); xtr = CONTAINER_OF(ctrl_dev, lisp_xtr_t, super); if (configure_tunnel_router(cfg, xtr, lcaf_ht)!=GOOD){ return (BAD); } /* INTERFACES CONFIG */ n = cfg_size(cfg, "rtr-ifaces"); if (n) { cfg_t *rifs = cfg_getsec(cfg, "rtr-ifaces"); int nr = cfg_size(rifs, "rtr-iface"); if (nr == 0){ OOR_LOG(LERR, "Configuration file: RTR needs at least one data iface"); } for(i = 0; i < nr; i++) { cfg_t *ri = cfg_getnsec(rifs, "rtr-iface", i); if (cfg_getstr(ri, "iface") == NULL){ OOR_LOG(LERR, "Configuration file: rtr-iface needs at least the iface name"); return (BAD); } if (add_rtr_iface(xtr, cfg_getstr(ri, "iface"), cfg_getint(ri, "ip_version"), cfg_getint(ri, "priority"), cfg_getint(ri, "weight")) == GOOD) { OOR_LOG(LDBG_1, "Configured interface %s for RTR", cfg_getstr(ri, "iface")); } else{ OOR_LOG(LERR, "Can't configure iface %s for RTR", cfg_getstr(ri, "iface")); } } } /* RTR DATABASE MAPPINGS (like for instance replication lists) */ n = cfg_size(cfg, "rtr-database-mapping"); for (i = 0; i < n; i++) { mapping = parse_mapping(cfg_getnsec(cfg, "rtr-database-mapping",i),&(xtr->super),lcaf_ht,TRUE); if (mapping == NULL){ return (BAD); } map_loc_e = map_local_entry_new_init(mapping); if (map_loc_e == NULL){ mapping_del(mapping); continue; } if (xtr->fwd_policy->init_map_loc_policy_inf( xtr->fwd_policy_dev_parm,map_loc_e,NULL) != GOOD){ OOR_LOG(LERR, "Couldn't initiate forward information for rtr database mapping with EID: %s. Discarding it...", lisp_addr_to_char(mapping_eid(mapping))); map_local_entry_del(map_loc_e); continue; } if (add_local_db_map_local_entry(map_loc_e,xtr) != GOOD){ map_local_entry_del(map_loc_e); continue; } if (add_local_db_map_local_entry(map_loc_e,xtr) != GOOD){ map_local_entry_del(map_loc_e); } } /* Deallocate PiTRs and PeTRs elements */ glist_destroy(xtr->pitrs); xtr->pitrs = NULL; shash_destroy(lcaf_ht); return(GOOD); } int configure_xtr(cfg_t *cfg) { lisp_xtr_t *xtr; shash_t *lcaf_ht; /* CREATE AND CONFIGURE XTR */ if (ctrl_dev_create(xTR_MODE, &ctrl_dev) != GOOD) { OOR_LOG(LCRIT, "Failed to create xTR. Aborting!"); exit_cleanup(); } lcaf_ht = parse_lcafs(cfg); xtr = CONTAINER_OF(ctrl_dev, lisp_xtr_t, super); xtr->nat_aware = cfg_getbool(cfg, "nat_traversal_support") ? TRUE:FALSE; if(xtr->nat_aware){ if (nat_set_xTR_ID(xtr) != GOOD){ return (BAD); } nat_set_site_ID(xtr, 0); default_rloc_afi = AF_INET; OOR_LOG(LDBG_1, "NAT support enabled. Set defaul RLOC to IPv4 family"); } if (configure_tunnel_router(cfg, xtr, lcaf_ht)!=GOOD){ return (BAD); } if (parse_map_servers(cfg, xtr) != GOOD){ return (BAD); } if (parse_proxy_etrs(cfg, xtr) != GOOD){ return (BAD); } if (parse_proxy_itrs(cfg, xtr) != GOOD){ return (BAD); } if (parse_database_mapping(cfg, xtr, lcaf_ht) != GOOD){ return (BAD); } /* destroy the hash table */ shash_destroy(lcaf_ht); return (GOOD); } int configure_mn(cfg_t *cfg) { lisp_xtr_t *xtr; shash_t *lcaf_ht; /* CREATE AND CONFIGURE MN */ if (ctrl_dev_create(MN_MODE, &ctrl_dev) != GOOD) { OOR_LOG(LCRIT, "Failed to create mobile node. Aborting!"); exit_cleanup(); } lcaf_ht = parse_lcafs(cfg); xtr = CONTAINER_OF(ctrl_dev, lisp_xtr_t, super); xtr->nat_aware = cfg_getbool(cfg, "nat_traversal_support") ? TRUE:FALSE; if(xtr->nat_aware){ if (nat_set_xTR_ID(xtr) != GOOD){ printf("aaaaaaaaaaaaa\n"); return (BAD); } nat_set_site_ID(xtr, 0); default_rloc_afi = AF_INET; OOR_LOG(LDBG_1, "NAT support enabled. Set defaul RLOC to IPv4 family"); } if (configure_tunnel_router(cfg, xtr, lcaf_ht)!=GOOD){ return (BAD); } if (parse_map_servers(cfg, xtr) != GOOD){ return (BAD); } if (parse_proxy_etrs(cfg, xtr) != GOOD){ return (BAD); } if (parse_proxy_itrs(cfg, xtr) != GOOD){ return (BAD); } if (parse_database_mapping(cfg, xtr, lcaf_ht) != GOOD){ return (BAD); } /* destroy the hash table */ shash_destroy(lcaf_ht); return (GOOD); } int configure_ms(cfg_t *cfg) { char *iface_name; iface_t *iface=NULL; lisp_site_prefix_t *site; shash_t *lcaf_ht; int i; lisp_ms_t *ms; mapping_t *mapping; /* create and configure xtr */ if (ctrl_dev_create(MS_MODE, &ctrl_dev) != GOOD) { OOR_LOG(LCRIT, "Failed to create MS. Aborting!"); exit_cleanup(); } ms = CONTAINER_OF(ctrl_dev, lisp_ms_t, super); /* create lcaf hash table */ lcaf_ht = parse_lcafs(cfg); /* CONTROL INTERFACE */ /* TODO: should work with all interfaces in the future */ iface_name = cfg_getstr(cfg, "control-iface"); if (iface_name) { iface = add_interface(iface_name); if (iface == NULL) { OOR_LOG(LERR, "Configuration file: Couldn't add the control iface of the Map Server"); return(BAD); } }else{ /* we have no iface_name, so also iface is missing */ OOR_LOG(LERR, "Configuration file: Specify the control iface of the Map Server"); return(BAD); } iface_configure (iface, AF_INET); iface_configure (iface, AF_INET6); /* LISP-SITE CONFIG */ for (i = 0; i < cfg_size(cfg, "lisp-site"); i++) { cfg_t *ls = cfg_getnsec(cfg, "lisp-site", i); if (cfg_getstr(ls, "eid-prefix") == NULL || cfg_getstr(ls, "key") == NULL){ OOR_LOG(LERR, "Configuration file: MS LISP site requires at least an eid-prefix and a key"); return (BAD); } site = build_lisp_site_prefix(ms, cfg_getstr(ls, "eid-prefix"), cfg_getint(ls, "iid"), cfg_getint(ls, "key-type"), cfg_getstr(ls, "key"), cfg_getbool(ls, "accept-more-specifics") ? 1:0, cfg_getbool(ls, "proxy-reply") ? 1:0, cfg_getbool(ls, "merge") ? 1 : 0, lcaf_ht); if (site != NULL) { if (mdb_lookup_entry(ms->lisp_sites_db, site->eid_prefix) != NULL){ OOR_LOG(LDBG_1, "Configuration file: Duplicated lisp-site: %s . Discarding...", lisp_addr_to_char(site->eid_prefix)); lisp_site_prefix_del(site); continue; } OOR_LOG(LDBG_1, "Adding lisp site prefix %s to the lisp-sites " "database", lisp_addr_to_char(site->eid_prefix)); ms_add_lisp_site_prefix(ms, site); }else{ OOR_LOG(LERR, "Can't add lisp-site prefix %s. Discarded ...", cfg_getstr(ls, "eid-prefix")); } } /* LISP REGISTERED SITES CONFIG */ for (i = 0; i< cfg_size(cfg, "ms-static-registered-site"); i++ ) { cfg_t *mss = cfg_getnsec(cfg, "ms-static-registered-site", i); mapping = parse_mapping(mss,&(ms->super),lcaf_ht,FALSE); if (mapping == NULL){ OOR_LOG(LERR, "Can't create static register site for %s", cfg_getstr(mss, "eid-prefix")); return (BAD); } /* If the mapping doesn't exist, add it the the database */ if (mdb_lookup_entry_exact(ms->reg_sites_db, mapping_eid(mapping)) == NULL){ if (ms_add_registered_site_prefix(ms, mapping) == GOOD){ OOR_LOG(LDBG_1, "Added static registered site for %s to the registered sites list!", lisp_addr_to_char(mapping_eid(mapping))); }else{ OOR_LOG(LERR, "Failed to add static registered site for %s to the registered sites list!", lisp_addr_to_char(mapping_eid(mapping))); mapping_del(mapping); } }else{ OOR_LOG(LERR, "Configuration file: Duplicated static registered site for %s. Discarded ...", cfg_getstr(mss, "eid-prefix")); mapping_del(mapping); continue; } } /* destroy the hash table */ shash_destroy(lcaf_ht); return(GOOD); } int handle_config_file() { int ret; cfg_t *cfg; char *mode; char *log_file; /* xTR specific */ static cfg_opt_t map_server_opts[] = { CFG_STR("address", 0, CFGF_NONE), CFG_INT("key-type", 1, CFGF_NONE), CFG_STR("key", 0, CFGF_NONE), CFG_BOOL("proxy-reply", cfg_false, CFGF_NONE), CFG_END() }; static cfg_opt_t rloc_address_opts[] = { CFG_STR("address", 0, CFGF_NONE), CFG_INT("priority", 1, CFGF_NONE), CFG_INT("weight", 100, CFGF_NONE), CFG_END() }; static cfg_opt_t rloc_iface_opts[] = { CFG_STR("interface", 0, CFGF_NONE), CFG_INT("ip_version", 4, CFGF_NONE), CFG_INT("priority", 1, CFGF_NONE), CFG_INT("weight", 100, CFGF_NONE), CFG_END() }; static cfg_opt_t db_mapping_opts[] = { CFG_STR("eid-prefix", 0, CFGF_NONE), CFG_INT("iid", 0, CFGF_NONE), CFG_SEC("rloc-address", rloc_address_opts, CFGF_MULTI), CFG_SEC("rloc-iface", rloc_iface_opts, CFGF_MULTI), CFG_END() }; static cfg_opt_t map_cache_mapping_opts[] = { CFG_STR("eid-prefix", 0, CFGF_NONE), CFG_INT("iid", 0, CFGF_NONE), CFG_SEC("rloc-address", rloc_address_opts, CFGF_MULTI), CFG_END() }; static cfg_opt_t petr_mapping_opts[] = { CFG_STR("address", 0, CFGF_NONE), CFG_INT("priority", 1, CFGF_NONE), CFG_INT("weight", 100, CFGF_NONE), CFG_END() }; static cfg_opt_t rtr_iface_opts[] = { CFG_STR("iface", 0, CFGF_NONE), CFG_INT("ip_version", 4, CFGF_NONE), CFG_INT("priority", 1, CFGF_NONE), CFG_INT("weight", 100, CFGF_NONE), CFG_END() }; static cfg_opt_t rtr_ifaces_opts[] = { CFG_SEC("rtr-iface", rtr_iface_opts, CFGF_MULTI), CFG_END() }; static cfg_opt_t rloc_probing_opts[] = { CFG_INT("rloc-probe-interval", 0, CFGF_NONE), CFG_INT("rloc-probe-retries", 3, CFGF_NONE), CFG_INT("rloc-probe-retries-interval", 10, CFGF_NONE), CFG_END() }; static cfg_opt_t elp_node_opts[] = { CFG_STR("address", 0, CFGF_NONE), CFG_BOOL("strict", cfg_false, CFGF_NONE), CFG_BOOL("probe", cfg_false, CFGF_NONE), CFG_BOOL("lookup", cfg_false, CFGF_NONE), CFG_END() }; static cfg_opt_t elp_opts[] = { CFG_STR("elp-name", 0, CFGF_NONE), CFG_SEC("elp-node", elp_node_opts, CFGF_MULTI), CFG_END() }; static cfg_opt_t rle_node_opts[] = { CFG_STR("address", 0, CFGF_NONE), CFG_INT("level", 0, CFGF_NONE), CFG_END() }; static cfg_opt_t rle_opts[] = { CFG_STR("rle-name", 0, CFGF_NONE), CFG_SEC("rle-node", rle_node_opts, CFGF_MULTI), CFG_END() }; static cfg_opt_t mc_info_opts[] = { CFG_STR("mc-info-name", 0, CFGF_NONE), CFG_STR("source", 0, CFGF_NONE), CFG_INT("source-mask-length", 0, CFGF_NONE), CFG_STR("group", 0, CFGF_NONE), CFG_INT("group-mask-length", 0, CFGF_NONE), CFG_INT("iid", 0, CFGF_NONE), CFG_END() }; /* Map-Server specific */ static cfg_opt_t lisp_site_opts[] = { CFG_STR("eid-prefix", 0, CFGF_NONE), CFG_INT("iid", 0, CFGF_NONE), CFG_INT("key-type", 1, CFGF_NONE), CFG_STR("key", 0, CFGF_NONE), CFG_BOOL("accept-more-specifics", cfg_false, CFGF_NONE), CFG_BOOL("proxy-reply", cfg_false, CFGF_NONE), CFG_BOOL("merge", cfg_false, CFGF_NONE), CFG_END() }; cfg_opt_t opts[] = { CFG_SEC("database-mapping", db_mapping_opts, CFGF_MULTI), CFG_SEC("ms-static-registered-site", db_mapping_opts, CFGF_MULTI), CFG_SEC("rtr-database-mapping", db_mapping_opts, CFGF_MULTI), CFG_SEC("static-map-cache", map_cache_mapping_opts, CFGF_MULTI), CFG_SEC("map-server", map_server_opts, CFGF_MULTI), CFG_SEC("rtr-ifaces", rtr_ifaces_opts, CFGF_MULTI), CFG_SEC("proxy-etr-ipv4", petr_mapping_opts, CFGF_MULTI), CFG_SEC("proxy-etr-ipv6", petr_mapping_opts, CFGF_MULTI), CFG_STR("encapsulation", "LISP", CFGF_NONE), CFG_SEC("rloc-probing", rloc_probing_opts, CFGF_MULTI), CFG_INT("map-request-retries", 0, CFGF_NONE), CFG_INT("control-port", 0, CFGF_NONE), CFG_INT("debug", 0, CFGF_NONE), CFG_STR("log-file", 0, CFGF_NONE), CFG_INT("rloc-probing-interval",0, CFGF_NONE), CFG_STR_LIST("map-resolver", 0, CFGF_NONE), CFG_STR_LIST("proxy-itrs", 0, CFGF_NONE), #ifdef ANDROID CFG_BOOL("override-dns", cfg_false, CFGF_NONE), CFG_STR("override-dns-primary", 0, CFGF_NONE), CFG_STR("override-dns-secondary", 0, CFGF_NONE), #endif CFG_STR("operating-mode", 0, CFGF_NONE), CFG_BOOL("nat_traversal_support", cfg_false, CFGF_NONE), CFG_STR("control-iface", 0, CFGF_NONE), CFG_STR("rtr-data-iface", 0, CFGF_NONE), CFG_SEC("lisp-site", lisp_site_opts, CFGF_MULTI), CFG_SEC("explicit-locator-path", elp_opts, CFGF_MULTI), CFG_SEC("replication-list", rle_opts, CFGF_MULTI), CFG_SEC("multicast-info", mc_info_opts, CFGF_MULTI), CFG_END() }; if (config_file == NULL){ config_file = strdup("/etc/oor.conf"); } /* * parse config_file */ cfg = cfg_init(opts, CFGF_NOCASE); ret = cfg_parse(cfg, config_file); if (ret == CFG_FILE_ERROR) { OOR_LOG(LCRIT, "Couldn't find config file %s. If you are useing OOR in daemon mode, please indicate a full path file.", config_file); cfg_free(cfg); return (BAD); } else if(ret == CFG_PARSE_ERROR) { OOR_LOG(LCRIT, "Parse error in file %s, exiting. Check conf file (see oor.conf.example)", config_file); cfg_free(cfg); return(BAD); } /* * oor config options */ /* Debug level */ if (debug_level == -1){ ret = cfg_getint(cfg, "debug"); if (ret > 0) debug_level = ret; else debug_level = 0; if (debug_level > 3) debug_level = 3; } if (debug_level == 1){ OOR_LOG (LINF, "Log level: Low debug"); }else if (debug_level == 2){ OOR_LOG (LINF, "Log level: Medium debug"); }else if (debug_level == 3){ OOR_LOG (LINF, "Log level: High Debug"); } /* * Log file */ log_file = cfg_getstr(cfg, "log-file"); if (daemonize == TRUE){ open_log_file(log_file); } mode = cfg_getstr(cfg, "operating-mode"); if (mode) { if (strcmp(mode, "xTR") == 0) { ret=configure_xtr(cfg); } else if (strcmp(mode, "MS") == 0) { ret=configure_ms(cfg); } else if (strcmp(mode, "RTR") == 0) { ret=configure_rtr(cfg); }else if (strcmp(mode, "MN") == 0) { ret=configure_mn(cfg); }else{ OOR_LOG (LCRIT, "Configuration file: Unknown operating mode: %s",mode); cfg_free(cfg); return (BAD); } } cfg_free(cfg); return(ret); } /* * Editor modelines * * vi: set shiftwidth=4 tabstop=4 expandtab: * :indentSize=4:tabSize=4:noTabs=true: */ oor-1.2.0/oor/config/oor_config_confuse.h000066400000000000000000000015601313612200500203670ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef OOR_CONFIG_CONFUSE_H_ #define OOR_CONFIG_CONFUSE_H_ /* * Parse config file and set up whatever is needed */ int handle_config_file(); #endif /*OOR_CONFIG_CONFUSE_H_*/ oor-1.2.0/oor/config/oor_config_functions.c000066400000000000000000001156541313612200500207420ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include #include #include #include "oor_config_functions.h" #include "../data-plane/data-plane.h" #include "../net_mgr/net_mgr.h" #include "../lib/oor_log.h" #include "../lib/prefixes.h" #include "../lib/util.h" /***************************** FUNCTIONS DECLARATION *************************/ glist_t *fqdn_to_addresses( char *addr_str, const int preferred_afi); /********************************** FUNCTIONS ********************************/ inline conf_mapping_t * conf_mapping_new() { conf_mapping_t * conf_map = (conf_mapping_t *)xzalloc(sizeof(conf_mapping_t)); if (conf_map == NULL){ OOR_LOG(LWRN,"conf_mapping_new: Couldn't allocate memory for a conf_mapping_t structure"); return (NULL); } conf_map->eid_prefix = (char *)xzalloc(MAX_CFG_STRING); conf_map->conf_loc_list = glist_new_managed((glist_del_fct) conf_loc_destroy); conf_map->conf_loc_iface_list = glist_new_managed((glist_del_fct) conf_loc_iface_destroy); conf_map->ttl = DEFAULT_DATA_CACHE_TTL; return (conf_map); } inline void conf_mapping_destroy(conf_mapping_t * conf_map) { glist_destroy(conf_map->conf_loc_list); glist_destroy(conf_map->conf_loc_iface_list); free(conf_map->eid_prefix); free(conf_map); } inline void conf_mapping_dump(conf_mapping_t * conf_map, int log_level) { char buf[2000]; conf_loc_t *conf_loct; conf_loc_iface_t *conf_loct_iface; glist_entry_t *it_loct_addr; glist_entry_t *it_loct_iface; size_t buf_size = sizeof(buf); if (is_loggable(log_level) == FALSE){ return; } snprintf(buf,buf_size,"EID: %s, ttl: %d\n", conf_map->eid_prefix, conf_map->ttl); glist_for_each_entry(it_loct_addr,conf_map->conf_loc_list){ conf_loct = (conf_loc_t *)glist_entry_data(it_loct_addr); snprintf(buf+strlen(buf), buf_size - strlen(buf),"\n %s",conf_loc_to_char(conf_loct)); } glist_for_each_entry(it_loct_iface,conf_map->conf_loc_iface_list){ conf_loct_iface = (conf_loc_iface_t *)glist_entry_data(it_loct_iface); snprintf(buf+strlen(buf), buf_size - strlen(buf),"\n %s",conf_loc_iface_to_char(conf_loct_iface)); } OOR_LOG(log_level,"%s\n",buf); } inline conf_loc_t * conf_loc_new_init(char *addr, uint8_t priority, uint8_t weight, uint8_t mpriority, uint8_t mweight) { conf_loc_t * conf_loc; conf_loc = (conf_loc_t *)xzalloc(sizeof(conf_loc_t)); if (conf_loc == NULL){ OOR_LOG(LWRN,"conf_loc_new_init: Couldn't allocate memory for a conf_loc_t structure"); return (NULL); } conf_loc->address = strdup(addr); conf_loc->priority = priority; conf_loc->weight = weight; conf_loc->mpriority = mpriority; conf_loc->mweight = mweight; return (conf_loc); } char * conf_loc_to_char(conf_loc_t * loc) { static char buf[100]; *buf = '\0'; snprintf(buf,sizeof(buf),"Locator address: %s, Priority: %d, Weight: %d", loc->address,loc->priority,loc->weight); return (buf); } inline conf_loc_iface_t * conf_loc_iface_new_init(char *iface_name, int afi, uint8_t priority, uint8_t weight, uint8_t mpriority, uint8_t mweight) { conf_loc_iface_t * conf_loc_iface; conf_loc_iface = (conf_loc_iface_t *)xzalloc(sizeof(conf_loc_iface_t)); if (conf_loc_iface == NULL){ OOR_LOG(LWRN,"conf_loc_iface_new_init: Couldn't allocate memory for a conf_loc_iface_t structure"); return (NULL); } conf_loc_iface->interface = strdup(iface_name); conf_loc_iface->afi = afi; conf_loc_iface->priority = priority; conf_loc_iface->weight = weight; conf_loc_iface->mpriority = mpriority; conf_loc_iface->mweight = mweight; return (conf_loc_iface); } char * conf_loc_iface_to_char(conf_loc_iface_t * loc_iface) { static char buf[100]; *buf = '\0'; snprintf(buf,sizeof(buf),"Locator interface: %s, AFI: %d, Priority: %d, Weight: %d", loc_iface->interface,loc_iface->afi,loc_iface->priority,loc_iface->weight); return (buf); } no_addr_loct * no_addr_loct_new_init(locator_t * loct, char *iface, int afi) { no_addr_loct * nloct; nloct = (no_addr_loct *)xzalloc(sizeof(no_addr_loct)); if (nloct == NULL){ return (NULL); } nloct->locator = loct; nloct->iface_name = strdup(iface); nloct->afi = afi; return (nloct); } void no_addr_loct_del(no_addr_loct * nloct) { free(nloct->iface_name); free(nloct); } no_addr_loct * get_no_addr_loct_from_list(glist_t *list, locator_t *locator) { glist_entry_t *it; no_addr_loct *nloct; glist_for_each_entry(it,list){ nloct = (no_addr_loct *)glist_entry_data(it); /* Comparing memory position */ if (nloct->locator == locator){ return (nloct); } } return (NULL); } void validate_rloc_probing_parameters(int *interval,int *retries,int *retries_int) { if (*interval < 0) { *interval = 0; } if (*interval > 0) { OOR_LOG(LDBG_1, "RLOC Probing Interval: %d", *interval); } else { OOR_LOG(LDBG_1, "RLOC Probing disabled"); } if (*interval != 0) { if (*retries > OOR_MAX_RETRANSMITS) { *retries = OOR_MAX_RETRANSMITS; OOR_LOG(LWRN, "RLOC Probing retries should be between 0 and %d. " "Using %d retries", OOR_MAX_RETRANSMITS, OOR_MAX_RETRANSMITS); } else if (*retries < 0) { *retries = 0; OOR_LOG(LWRN, "RLOC Probing retries should be between 0 and %d. " "Using 0 retries", OOR_MAX_RETRANSMITS); } if (*retries > 0) { if (*retries_int < OOR_MIN_RETRANSMIT_INTERVAL) { *retries_int = OOR_MIN_RETRANSMIT_INTERVAL; OOR_LOG(LWRN, "RLOC Probing interval retries should be between " "%d and RLOC Probing interval. Using %d seconds", OOR_MIN_RETRANSMIT_INTERVAL, OOR_MIN_RETRANSMIT_INTERVAL); } else if (*retries_int > *interval) { *retries_int = *interval; OOR_LOG(LWRN, "RLOC Probing interval retries should be between " "%d and RLOC Probing interval. Using %d seconds", OOR_MIN_RETRANSMIT_INTERVAL, *interval); } } } } int validate_priority_weight(int p, int w) { /* Check the parameters */ if (p < (MAX_PRIORITY - 1)|| p > UNUSED_RLOC_PRIORITY) { OOR_LOG(LERR, "Configuration file: Priority %d out of range [%d..%d]", p, MAX_PRIORITY, MIN_PRIORITY); return (BAD); } if (w > MAX_WEIGHT || w < MIN_WEIGHT) { OOR_LOG(LERR, "Configuration file: Weight %d out of range [%d..%d]", p, MIN_WEIGHT, MAX_WEIGHT); return (BAD); } return (GOOD); } /* * add a map-resolver to the list */ int add_server(char *str_addr, glist_t *list) { lisp_addr_t * addr; glist_t * addr_list; glist_entry_t * it; addr_list = parse_ip_addr(str_addr); if (addr_list == NULL){ OOR_LOG(LERR, "Error parsing address. Ignoring server with address %s", str_addr); return (BAD); } glist_for_each_entry(it, addr_list) { addr = (lisp_addr_t *)glist_entry_data(it); /* Check that the afi of the map server matches with the default rloc afi * (if it's defined). */ if (default_rloc_afi != AF_UNSPEC && default_rloc_afi != lisp_addr_ip_afi(addr)){ OOR_LOG(LWRN, "The server %s will not be added due to the selected " "default rloc afi (-a option)", str_addr); continue; } glist_add_tail(lisp_addr_clone(addr), list); OOR_LOG(LDBG_3,"The server %s has been added to the list",lisp_addr_to_char(addr)); } glist_destroy(addr_list); return(GOOD); } int add_map_server(glist_t *ms_list, char *str_addr, int key_type, char *key, uint8_t proxy_reply) { lisp_addr_t *addr; map_server_elt *ms; glist_t *addr_list; glist_entry_t *it; if (str_addr == NULL || key_type == 0 || key == NULL){ OOR_LOG(LERR, "Configuration file: Wrong Map Server configuration. " "Check configuration file"); exit_cleanup(); } if (key_type != HMAC_SHA_1_96){ OOR_LOG(LERR, "Configuration file: Only SHA-1 (1) authentication is supported"); exit_cleanup(); } addr_list = parse_ip_addr(str_addr); if (addr_list == NULL){ OOR_LOG(LERR, "Error parsing address. Ignoring Map Server %s", str_addr); return (BAD); } glist_for_each_entry(it, addr_list) { addr = (lisp_addr_t *)glist_entry_data(it); /* Check that the afi of the map server matches with the default rloc afi * (if it's defined). */ if (default_rloc_afi != AF_UNSPEC && default_rloc_afi != lisp_addr_ip_afi(addr)){ OOR_LOG(LWRN, "The map server %s will not be added due to the selected " "default rloc afi (-a option)", str_addr); continue; } ms = map_server_elt_new_init(addr,key_type,key,proxy_reply); if (ms == NULL){ continue; } glist_add(ms, ms_list); } glist_destroy(addr_list); return(GOOD); } int add_proxy_etr_entry(mcache_entry_t *petrs, char *str_addr, int priority, int weight) { glist_t *addr_list; glist_entry_t *it; lisp_addr_t *addr; locator_t *locator; if (str_addr == NULL){ OOR_LOG(LERR, "Configuration file: No interface specified for PETR. " "Discarding!"); return (BAD); } if (validate_priority_weight(priority, weight) != GOOD) { return(BAD); } addr_list = parse_ip_addr(str_addr); if (addr_list == NULL){ OOR_LOG(LERR, "Error parsing RLOC address. Ignoring proxy-ETR %s", str_addr); return (BAD); } glist_for_each_entry(it, addr_list) { addr = glist_entry_data(it); if (default_rloc_afi != AF_UNSPEC && default_rloc_afi != lisp_addr_ip_afi(addr)) { OOR_LOG(LWRN, "The PETR %s will not be added due to the selected " "default rloc afi (-a)", str_addr); continue; } /* Create locator representing the proxy-etr and add it to the mapping */ locator = locator_new_init(addr, UP, 0, 1, priority, weight, 255, 0); if (locator != NULL) { if (mapping_add_locator(mcache_entry_mapping(petrs), locator)!= GOOD){ locator_del(locator); continue; } } } glist_destroy(addr_list); return(GOOD); } /* * Create the locators associated with the address of the iface and assign them * to the mapping_t and the iface_locators * @param iface Interface containing the rlocs associated to the mapping * @param if_loct Structure that associate iface with locators * @param map_loc_e Local mapping where to add the new locators * @param afi Afi of the address of the interface to be used * @param priority priority of the IPv4 RLOC. 1..255 -1 the IPv4 address is not used * @param weight weight of the IPv4 RLOC * @return GOOD if finish correctly or an error code otherwise */ int link_iface_and_mapping(iface_t *iface, iface_locators *if_loct, map_local_entry_t *map_loc_e, int afi, int priority, int weight) { mapping_t *mapping; locator_t *locator; mapping = map_local_entry_mapping(map_loc_e); /* Add mapping to the list of mappings associated to the interface */ if (glist_contain(map_loc_e, if_loct->map_loc_entries) == FALSE){ glist_add(map_loc_e,if_loct->map_loc_entries); } /* Create locator and assign to the mapping and to iface_loct*/ if (priority >= 0){ if (afi == AF_INET){ locator = locator_new_init(iface->ipv4_address, iface->status,1,1, priority, weight, 255, 0); if (locator == NULL){ return (BAD); } if (mapping_add_locator(mapping, locator) != GOOD) { locator_del(locator); return(BAD); } glist_add(locator,if_loct->ipv4_locators); }else{ locator = locator_new_init(iface->ipv6_address, iface->status,1,1, priority, weight, 255, 0); if (locator == NULL){ return (BAD); } if (mapping_add_locator(mapping, locator) != GOOD) { locator_del(locator); return(BAD); } glist_add(locator,if_loct->ipv6_locators); } } return(GOOD); } int add_rtr_iface(lisp_xtr_t *xtr, char *iface_name,int afi, int priority, int weight) { iface_t *iface; iface_locators *if_loct; mapping_t *mapping; lisp_addr_t aux_address; if (iface_name == NULL){ OOR_LOG(LERR, "Configuration file: No interface specified for RTR. " "Discarding!"); return (BAD); } if (validate_priority_weight(priority, weight) != GOOD) { return(BAD); } if (priority < 0){ OOR_LOG(LERR, "Configuration file: Discarding the interface %s of the RTR with afi %d due to the assigned priority", iface_name, afi); return (GOOD); } if (afi != 4 && afi !=6){ OOR_LOG(LERR, "Configuration file: The rtr-iface->afi of the locator should be \"4\" (IPv4)" " or \"6\" (IPv6)"); return (BAD); } afi = (afi == 4) ? AF_INET : AF_INET6; /* Check if the interface already exists. If not, add it*/ if ((iface = get_interface(iface_name)) == NULL) { iface = add_interface(iface_name); if (!iface) { OOR_LOG(LWRN, "add_rtr_iface: Can't create interface %s", iface_name); return(BAD); } } if (iface_configure (iface, afi)!= GOOD){ OOR_LOG(LWRN, "add_rtr_iface: Can't configure addresses of interface %s", iface_name); return(BAD); } if_loct = (iface_locators *)shash_lookup(xtr->iface_locators_table,iface_name); if (if_loct == NULL){ if_loct = iface_locators_new(iface_name); shash_insert(xtr->iface_locators_table, strdup(iface_name), if_loct); } if (!xtr->all_locs_map) { lisp_addr_set_lafi(&aux_address,LM_AFI_NO_ADDR); mapping = mapping_new(); mapping_set_eid(mapping,&aux_address); if (mapping == NULL){ OOR_LOG(LDBG_1, "add_rtr_iface: Can't allocate mapping!"); return (BAD); } xtr->all_locs_map = map_local_entry_new_init(mapping); if(xtr->all_locs_map == NULL){ OOR_LOG(LDBG_1, "add_rtr_iface: Can't allocate map_local_entry_t!"); return (BAD); } if (xtr->fwd_policy->init_map_loc_policy_inf( xtr->fwd_policy_dev_parm,xtr->all_locs_map,NULL) != GOOD){ OOR_LOG(LERR, "Couldn't initiate forward information for rtr localtors.", lisp_addr_to_char(mapping_eid(mapping))); map_local_entry_del(xtr->all_locs_map); return (BAD); } } if (link_iface_and_mapping(iface, if_loct, xtr->all_locs_map, afi, priority, weight) != GOOD) { return(BAD); } /* Updated forwarding info */ xtr->fwd_policy->updated_map_loc_inf(xtr->fwd_policy_dev_parm, xtr->all_locs_map); return(GOOD); } lisp_site_prefix_t * build_lisp_site_prefix(lisp_ms_t *ms, char *eidstr, uint32_t iid, int key_type, char *key, uint8_t more_specifics, uint8_t proxy_reply, uint8_t merge, shash_t *lcaf_ht) { lisp_addr_t *eid_prefix; lisp_addr_t *ht_prefix; lisp_site_prefix_t *site; if (iid > MAX_IID) { OOR_LOG(LERR, "Configuration file: Instance ID %d out of range [0..%d], " "disabling...", iid, MAX_IID); iid = 0; } /* DON'T DELETE eid_prefix */ eid_prefix = lisp_addr_new(); if (lisp_addr_ippref_from_char(eidstr, eid_prefix) != GOOD) { lisp_addr_del(eid_prefix); /* if not found, try in the hash table */ ht_prefix = shash_lookup(lcaf_ht, eidstr); if (!ht_prefix) { OOR_LOG(LERR, "Configuration file: Error parsing EID prefix %s", eidstr); return (NULL); } eid_prefix = lisp_addr_clone(ht_prefix); } pref_conv_to_netw_pref(eid_prefix); site = lisp_site_prefix_init(eid_prefix, iid, key_type, key, more_specifics, proxy_reply, merge); lisp_addr_del(eid_prefix); return(site); } /* Parses an EID/RLOC (IP or LCAF) and returns a list of 'lisp_addr_t'. * Caller must free the returned value */ glist_t * parse_lisp_addr(char *addr_str, shash_t *lcaf_ht) { glist_t *addr_list; lisp_addr_t *addr; lisp_addr_t *lcaf; int res; addr = lisp_addr_new(); if (strstr(addr_str,"/") == NULL){ // Address may be an IP res = lisp_addr_ip_from_char(addr_str, addr); }else{ // Address may be a prefix res = lisp_addr_ippref_from_char(addr_str, addr); } if (res != GOOD){ lisp_addr_del(addr); addr = NULL; /* if not found, try in the hash table */ lcaf = shash_lookup(lcaf_ht, addr_str); if (lcaf != NULL) { addr = lisp_addr_clone(lcaf); } } if (addr != NULL){ addr_list = glist_new_managed((glist_del_fct)lisp_addr_del); if (addr_list != NULL){ glist_add (addr,addr_list); } }else{ addr_list = fqdn_to_addresses(addr_str,default_rloc_afi); } if (addr_list == NULL || glist_size(addr_list) == 0){ OOR_LOG(LERR, "Configuration file: Error parsing address %s",addr_str); } return(addr_list); } /* Parses a char (IP or FQDN) into a list of 'lisp_addr_t'. * Caller must free the returned value */ glist_t * parse_ip_addr(char *addr_str) { glist_t *addr_list; lisp_addr_t *addr; int res; addr = lisp_addr_new(); res = lisp_addr_ip_from_char(addr_str, addr); if (res == GOOD){ addr_list = glist_new_managed((glist_del_fct)lisp_addr_del); if (addr_list != NULL){ glist_add (addr,addr_list); } }else{ lisp_addr_del(addr); addr_list = fqdn_to_addresses(addr_str,default_rloc_afi); } if (addr_list == NULL || glist_size(addr_list) == 0){ OOR_LOG(LERR, "Configuration file: Error parsing the address %s",addr_str); } return(addr_list); } locator_t* clone_customize_locator(oor_ctrl_dev_t *dev, locator_t * locator, glist_t * no_addr_loct_l, uint8_t is_local) { char *iface_name; locator_t *new_locator; iface_t *iface; lisp_addr_t *rloc; lisp_addr_t *aux_rloc; int rloc_ip_afi; no_addr_loct *nloct; lisp_xtr_t *xtr; shash_t *iface_lctrs; iface_locators *if_loct; rloc = locator_addr(locator); /* LOCAL locator */ if (is_local) { /* Decide IP address to be used to lookup the interface */ if (lisp_addr_is_lcaf(rloc) == TRUE) { aux_rloc = lisp_addr_get_ip_addr(rloc); if (aux_rloc == NULL) { OOR_LOG(LERR, "Configuration file: Can't determine RLOC's IP " "address %s", lisp_addr_to_char(rloc)); lisp_addr_del(rloc); return(NULL); } if (!(iface_name = get_interface_name_from_address(aux_rloc))) { OOR_LOG(LERR, "Configuration file: Can't find interface for RLOC %s", lisp_addr_to_char(rloc)); return(NULL); } rloc_ip_afi = lisp_addr_ip_afi(aux_rloc); } else if (lisp_addr_is_no_addr(rloc)){ aux_rloc = rloc; nloct = get_no_addr_loct_from_list(no_addr_loct_l,locator); if (nloct == NULL){ return (NULL); } iface_name = nloct->iface_name; rloc_ip_afi = nloct->afi; } else{ /* Find the interface name associated to the RLOC */ if (!(iface_name = get_interface_name_from_address(rloc))) { OOR_LOG(LERR, "Configuration file: Can't find interface for RLOC %s", lisp_addr_to_char(rloc)); return(NULL); } rloc_ip_afi = lisp_addr_ip_afi(rloc); } /* Find the interface */ iface = get_interface(iface_name); if (iface == NULL){ iface = add_interface(iface_name); if (iface == NULL){ OOR_LOG(LERR, "Configuration file: Can't add interface with name %s", iface_name); return(NULL); } } /* Configure address of the interface */ if (iface_configure (iface, rloc_ip_afi)!= GOOD){ OOR_LOG(LWRN, "Configuration file: Can't configure addresses of interface %s", iface_name); } new_locator = locator_new_init(rloc, iface->status,1, 1, locator_priority(locator), locator_weight(locator),255, 0); /* Associate locator with iface */ if (dev->mode == xTR_MODE || dev->mode == MN_MODE){ xtr = CONTAINER_OF(ctrl_dev, lisp_xtr_t, super); iface_lctrs = xtr->iface_locators_table; if_loct = (iface_locators *)shash_lookup(iface_lctrs, iface_name); if (if_loct == NULL){ if_loct = iface_locators_new(iface_name); shash_insert(xtr->iface_locators_table, strdup(iface_name), if_loct); } if (rloc_ip_afi == AF_INET){ glist_add(new_locator,if_loct->ipv4_locators); }else{ glist_add(new_locator,if_loct->ipv6_locators); } } /* REMOTE locator */ } else { new_locator = locator_new_init(rloc, UP,0 ,1 , locator_priority(locator), locator_weight(locator), 255, 0); } return(new_locator); } /* * Converts the hostname into IPs which are added to a list of lisp_addr_t * @param addr_str String conating fqdn address or de IP address * @param preferred_afi Indicates the afi of the IPs to be added in the list * @return List of addresses (glist_t *) */ glist_t *fqdn_to_addresses(char *addr_str, const int preferred_afi) { glist_t *addr_list; lisp_addr_t *addr; struct addrinfo hints; struct addrinfo *servinfo = NULL; struct addrinfo *p; struct sockaddr *s_addr; int err; addr_list = glist_new_managed((glist_del_fct)lisp_addr_del); memset(&hints, 0, sizeof hints); hints.ai_family = preferred_afi; hints.ai_flags = AI_PASSIVE; hints.ai_protocol = IPPROTO_UDP; /* we are interested in UDP only */ if ((err = getaddrinfo( addr_str, 0, &hints, &servinfo)) != 0) { OOR_LOG( LWRN, "fqdn_to_addresses: %s", gai_strerror(err)); return( NULL ); } /* iterate over addresses */ for (p = servinfo; p != NULL; p = p->ai_next) { if ((addr = lisp_addr_new_lafi(LM_AFI_IP))== NULL){ OOR_LOG( LWRN, "fqdn_to_addresses: Unable to allocate memory for lisp_addr_t"); continue; } s_addr = p->ai_addr; switch(s_addr->sa_family){ case AF_INET: ip_addr_init(lisp_addr_ip(addr),&(((struct sockaddr_in *)s_addr)->sin_addr),s_addr->sa_family); break; case AF_INET6: ip_addr_init(lisp_addr_ip(addr),&(((struct sockaddr_in6 *)s_addr)->sin6_addr),s_addr->sa_family); break; default: break; } OOR_LOG(LDBG_1, "converted addr_str [%s] to address [%s]", addr_str, lisp_addr_to_char(addr)); /* depending on callback return, we continue or not */ glist_add(addr,addr_list); } freeaddrinfo(servinfo); /* free the linked list */ return (addr_list); } static glist_t * process_rloc_address(conf_loc_t *conf_loc, oor_ctrl_dev_t *dev, shash_t *lcaf_ht, uint8_t is_local) { glist_t *loct_list; locator_t *locator; glist_t *addr_list; glist_entry_t *it; lisp_addr_t *address; lisp_addr_t *ip_addr; iface_t *iface; char *iface_name; int ip_afi; lisp_xtr_t *xtr; shash_t *iface_lctrs; iface_locators *if_loct; if (validate_priority_weight(conf_loc->priority, conf_loc->weight) != GOOD) { return (NULL); } addr_list = parse_lisp_addr(conf_loc->address, lcaf_ht); if (addr_list == NULL || glist_size(addr_list) == 0){ return (NULL); } loct_list = glist_new(); if (loct_list == NULL){ return (NULL); } glist_for_each_entry(it,addr_list){ address = (lisp_addr_t *)glist_entry_data(it); /* Remove locators not compatibles with default RLOC */ if (default_rloc_afi != AF_UNSPEC && lisp_addr_ip_afi(lisp_addr_get_ip_addr(address)) != default_rloc_afi){ OOR_LOG(LDBG_1, "Configuration file: RLOC address %s can not be added due to " "the selected default rloc afi (-a option)", lisp_addr_to_char(address)); continue; } if (lisp_addr_lafi(address) == LM_AFI_IPPREF){ OOR_LOG(LERR, "Configuration file: RLOC address can not be a prefix: %s ", lisp_addr_to_char(address)); continue; } if (is_local){ /* Decide IP address to be used to lookup the interface */ if (lisp_addr_is_lcaf(address) == TRUE) { ip_addr = lisp_addr_get_ip_addr(address); if (ip_addr == NULL) { OOR_LOG(LERR, "Configuration file: Can't determine RLOC's IP " "address %s", lisp_addr_to_char(address)); return(NULL); } } else { ip_addr = address; } /* Find the interface name associated to the RLOC */ if (!(iface_name = get_interface_name_from_address(ip_addr))) { OOR_LOG(LERR, "Configuration file: Can't find interface for RLOC %s", lisp_addr_to_char(ip_addr)); continue; } /* Find the interface */ iface = get_interface(iface_name); if (iface == NULL){ iface = add_interface(iface_name); if (iface == NULL){ OOR_LOG(LERR, "Configuration file: Can't add interface with name %s", iface_name); continue; } } ip_afi = lisp_addr_ip_afi(ip_addr); iface_configure (iface, ip_afi); if (lisp_addr_cmp(ip_addr, iface_address(iface, ip_afi))!=0){ OOR_LOG(LERR, "Configuration file: Can't add address %s. The interface don't have " " a gateway associated or the address is not default src address used to reach " " the gateway of the interface", iface_name); continue; } locator = locator_new_init(address, iface->status,1,1,conf_loc->priority, conf_loc->weight, conf_loc->mpriority, conf_loc->mweight); /* If the locator is for a local mapping, associate the locator with the interface */ if (locator != NULL && (dev->mode == xTR_MODE || dev->mode == MN_MODE)){ xtr = CONTAINER_OF(ctrl_dev, lisp_xtr_t, super); iface_lctrs = xtr->iface_locators_table; if_loct = (iface_locators *)shash_lookup(iface_lctrs, iface_name); if (if_loct == NULL){ if_loct = iface_locators_new(iface_name); shash_insert(xtr->iface_locators_table, strdup(iface_name), if_loct); } if (lisp_addr_ip_afi(ip_addr) == AF_INET){ glist_add(locator,if_loct->ipv4_locators); }else{ glist_add(locator,if_loct->ipv6_locators); } } } else { locator = locator_new_init(address, UP, 1, 1, conf_loc->priority, conf_loc->weight, 255, 0); } if (locator != NULL){ glist_add(locator,loct_list); OOR_LOG(LDBG_2,"parse_rloc_address: Locator structure created: \n %s", locator_to_char(locator)); } } glist_destroy(addr_list); return (loct_list); } static locator_t * process_rloc_interface(conf_loc_iface_t * conf_loc_iface, oor_ctrl_dev_t * dev) { locator_t *locator; lisp_addr_t *address; iface_t *iface; lisp_xtr_t *xtr; shash_t *iface_lctrs; iface_locators *if_loct; if (conf_loc_iface == NULL){ return (NULL); } /* Remove locators not compatibles with default RLOC */ if (default_rloc_afi != AF_UNSPEC && conf_loc_iface->afi != default_rloc_afi){ OOR_LOG(LDBG_1, "Configuration file: RLOC of the interface %s can not be added due to " "the selected default rloc afi (-a option)", conf_loc_iface->interface); return (NULL); } if (validate_priority_weight(conf_loc_iface->priority, conf_loc_iface->weight) != GOOD) { return (NULL); } /* Find the interface */ if (!(iface = get_interface(conf_loc_iface->interface))) { if (!(iface = add_interface(conf_loc_iface->interface))) { OOR_LOG(LDBG_1, "Configuration file: Couldn't add interface %s",conf_loc_iface->interface); return (BAD); } } iface_configure (iface, conf_loc_iface->afi); if (conf_loc_iface->afi == AF_INET){ address = iface->ipv4_address; }else{ address = iface->ipv6_address; } locator = locator_new_init(address, iface->status,1,1,conf_loc_iface->priority, conf_loc_iface->weight,conf_loc_iface->mpriority, conf_loc_iface->mweight); OOR_LOG(LDBG_2,"parse_rloc_address: Locator structure created: \n %s", locator_to_char(locator)); /* If the locator is for a local mapping, associate the locator with the interface */ if (locator != NULL && (dev->mode == xTR_MODE || dev->mode == MN_MODE)){ xtr = CONTAINER_OF(ctrl_dev, lisp_xtr_t, super); iface_lctrs = xtr->iface_locators_table; if_loct = (iface_locators *)shash_lookup(iface_lctrs, conf_loc_iface->interface); if (if_loct == NULL){ if_loct = iface_locators_new(conf_loc_iface->interface); shash_insert(xtr->iface_locators_table, strdup(conf_loc_iface->interface), if_loct); } if (conf_loc_iface->afi == AF_INET){ glist_add(locator,if_loct->ipv4_locators); }else{ glist_add(locator,if_loct->ipv6_locators); } } return (locator); } mapping_t * process_mapping_config(oor_ctrl_dev_t * dev, shash_t * lcaf_ht, conf_mapping_t * conf_mapping, uint8_t is_local) { mapping_t *mapping; glist_t *loct_list; glist_entry_t *it; locator_t *locator; glist_t *addr_list; lisp_addr_t *eid_prefix, *ip_eid_prefix; lisp_xtr_t *xtr=NULL; conf_loc_t *conf_loc; conf_loc_iface_t *conf_loc_iface; glist_entry_t *conf_it; int iidmlen; switch (dev->mode){ case xTR_MODE: case MN_MODE: xtr = CONTAINER_OF(ctrl_dev, lisp_xtr_t, super); break; default: break; } addr_list = parse_lisp_addr(conf_mapping->eid_prefix, lcaf_ht); if (addr_list == NULL || glist_size(addr_list) != 1){ return NULL; } ip_eid_prefix = (lisp_addr_t *)glist_first_data(addr_list); pref_conv_to_netw_pref(ip_eid_prefix); if (conf_mapping->iid > MAX_IID || conf_mapping->iid < 0) { OOR_LOG(LERR, "Configuration file: Instance ID %d out of range [0..%d], " "disabling...", conf_mapping->iid, MAX_IID); conf_mapping->iid = 0; } if (conf_mapping->iid > 0){ iidmlen = (lisp_addr_ip_afi(ip_eid_prefix) == AF_INET) ? 32: 128; eid_prefix = lisp_addr_new_init_iid(conf_mapping->iid, ip_eid_prefix, iidmlen); }else{ eid_prefix = lisp_addr_clone(ip_eid_prefix); } /* Create mapping */ mapping = mapping_new_init(eid_prefix); if (mapping == NULL){ return(NULL); } mapping_set_ttl(mapping, conf_mapping->ttl); if (is_local){ mapping_set_auth(mapping, 1); } /* no need for the prefix */ lisp_addr_del(eid_prefix); glist_destroy(addr_list); /* Create and add locators */ glist_for_each_entry(conf_it,conf_mapping->conf_loc_list){ conf_loc = (conf_loc_t *)glist_entry_data(conf_it); loct_list = process_rloc_address(conf_loc, dev, lcaf_ht, is_local); if (loct_list == NULL){ continue; } glist_for_each_entry(it,loct_list){ locator = (locator_t *)glist_entry_data(it); if (locator == NULL){ continue; } /* Check that the locator is not already added */ if (mapping_get_loct_with_addr(mapping, locator_addr(locator)) != NULL){ OOR_LOG(LERR,"Configuration file: Duplicated RLOC with address %s " "for EID prefix %s. Discarded ...", lisp_addr_to_char(locator_addr(locator)), lisp_addr_to_char(mapping_eid(mapping))); if (xtr != NULL && is_local){ iface_locators_unattach_locator(xtr->iface_locators_table,locator); } locator_del(locator); continue; } if (mapping_add_locator(mapping, locator) != GOOD){ OOR_LOG(LDBG_1,"parse_mapping: Couldn't add RLOC with address %s " "to the mapping with EID prefix %s. Discarded ...", lisp_addr_to_char(locator_addr(locator)), lisp_addr_to_char(mapping_eid(mapping))); if (xtr != NULL && is_local){ iface_locators_unattach_locator(xtr->iface_locators_table,locator); } locator_del(locator); continue; } } glist_destroy(loct_list); } if (is_local){ glist_for_each_entry(conf_it,conf_mapping->conf_loc_iface_list){ conf_loc_iface = (conf_loc_iface_t *)glist_entry_data(conf_it); locator = process_rloc_interface(conf_loc_iface, dev); if (locator == NULL){ continue; } /* Check that the locator is not already added */ if (mapping_get_loct_with_addr(mapping, locator_addr(locator)) != NULL){ OOR_LOG(LERR,"Configuration file: Duplicated RLOC with address %s " "for EID prefix %s. Discarded ...", lisp_addr_to_char(locator_addr(locator)), lisp_addr_to_char(mapping_eid(mapping))); if (xtr != NULL){ iface_locators_unattach_locator(xtr->iface_locators_table,locator); } locator_del(locator); continue; } if (mapping_add_locator(mapping, locator) != GOOD){ OOR_LOG(LDBG_1,"parse_mapping: Couldn't add RLOC with address %s " "to the mapping with EID prefix %s. Discarded ...", lisp_addr_to_char(locator_addr(locator)), lisp_addr_to_char(mapping_eid(mapping))); if (xtr != NULL){ iface_locators_unattach_locator(xtr->iface_locators_table,locator); } locator_del(locator); continue; } } } return (mapping); } int add_local_db_map_local_entry(map_local_entry_t *map_loca_entry, lisp_xtr_t *xtr) { lisp_addr_t *eid = map_local_entry_eid(map_loca_entry); if (map_loca_entry == NULL){ OOR_LOG(LERR, "Can't add mapping (NULL)"); return (BAD); } if (local_map_db_lookup_eid_exact(xtr->local_mdb, eid) == NULL){ if (local_map_db_add_entry(xtr->local_mdb, map_loca_entry) == GOOD){ OOR_LOG(LDBG_1, "Added EID prefix %s in the database.", lisp_addr_to_char(eid)); iface_locators_attach_map_local_entry(xtr->iface_locators_table,map_loca_entry); }else{ OOR_LOG(LERR, "Can't add EID prefix %s. Discarded ...", lisp_addr_to_char(eid)); goto err; } }else{ OOR_LOG(LERR, "Configuration file: Duplicated EID prefix %s. Discarded ...", lisp_addr_to_char(eid)); goto err; } return(GOOD); err: iface_locators_unattach_mapping_and_loct( xtr->iface_locators_table, map_loca_entry); return(BAD); } void nat_set_site_ID(lisp_xtr_t *xtr, uint64_t site_id) { xtr->site_id = site_id; } int nat_set_xTR_ID(lisp_xtr_t *xtr) { FILE *xtr_id_file; lisp_xtr_id *xtr_id = &(xtr->xtr_id); int ctr = 0; char *path; char file[200]; char line[80]; char part_xtr_id_str[3]; path = dirname(strdup(config_file)); if (snprintf(file,sizeof(file),"%s/%s",path, DEVICE_ID_FILE) >= sizeof(file)){ OOR_LOG(LERR,"File name path too long"); return (BAD); } xtr_id_file = fopen(file, "r"); if (! xtr_id_file) { xtr_id_file = fopen(file, "w"); if (!xtr_id_file){ OOR_LOG(LERR,"Could not generate device id file \"%s\": %s",file , strerror(errno)); return (BAD); } for (ctr=0; ctr<16; ctr++){ xtr_id->byte[ctr] = (uint8_t)random(); } fprintf(xtr_id_file,"%s", get_char_from_xTR_ID(xtr_id)); }else{ if (fgets(line, sizeof(line),xtr_id_file) == NULL || strlen(line) != 32){ fclose(xtr_id_file); xtr_id_file = fopen(file, "w"); if (!xtr_id_file){ OOR_LOG(LERR,"%s file has wrong format and could not be regenerated: %s",file , strerror(errno)); return (BAD); } for (ctr=0; ctr<16; ctr++){ xtr_id->byte[ctr] = (uint8_t)random(); } fprintf(xtr_id_file,"%s", get_char_from_xTR_ID(xtr_id)); }else{ part_xtr_id_str[2] = '\0'; for (ctr=0; ctr<16; ctr++){ part_xtr_id_str[0] = line[0+ctr*2]; part_xtr_id_str[1] = line[1+ctr*2]; xtr_id->byte[ctr] = (uint8_t)strtol(part_xtr_id_str, NULL, 16); } } } fclose(xtr_id_file); OOR_LOG(LDBG_2,"nat_set_xTR_ID: xTR_ID initialiazed with value: %s", get_char_from_xTR_ID(xtr_id)); return(GOOD); } oor-1.2.0/oor/config/oor_config_functions.h000066400000000000000000000121431313612200500207340ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef OOR_CONFIG_FUNCTIONS_H_ #define OOR_CONFIG_FUNCTIONS_H_ #include "../control/lisp_ms.h" #include "../control/lisp_xtr.h" #include "../lib/iface_locators.h" #include "../lib/lisp_site.h" #include "../lib/map_local_entry.h" #include "../lib/shash.h" #define MAX_CFG_STRING 100 typedef struct no_addr_loct_ { locator_t * locator; char * iface_name; int afi; }no_addr_loct; typedef struct conf_loc_ { char * address; int priority; int weight; int mpriority; int mweight; }conf_loc_t; typedef struct conf_loc_iface_ { char * interface; int afi; int priority; int weight; int mpriority; int mweight; }conf_loc_iface_t; typedef struct conf_mapping_ { char *eid_prefix; int ttl; int iid; glist_t *conf_loc_list; glist_t *conf_loc_iface_list; }conf_mapping_t; static inline conf_loc_t * conf_loc_new(){ return ((conf_loc_t *)xzalloc(sizeof(conf_loc_t))); } conf_loc_t * conf_loc_new_init(char *addr, uint8_t priority, uint8_t weight, uint8_t mpriority, uint8_t mweight); static inline void conf_loc_destroy(conf_loc_t *conf_loc){ if (conf_loc == NULL) return; free(conf_loc->address); free(conf_loc); } char *conf_loc_to_char(conf_loc_t * loc); static inline conf_loc_iface_t * conf_loc_iface_new(){ return ((conf_loc_iface_t *)xzalloc(sizeof(conf_loc_iface_t))); } conf_loc_iface_t * conf_loc_iface_new_init(char *iface_name, int afi, uint8_t priority, uint8_t weight, uint8_t mpriority, uint8_t mweight); static inline void conf_loc_iface_destroy(conf_loc_iface_t *conf_loc_iface){ if (conf_loc_iface == NULL) return; free(conf_loc_iface->interface); free(conf_loc_iface); } char *conf_loc_iface_to_char(conf_loc_iface_t * loc_iface); conf_mapping_t *conf_mapping_new(); void conf_mapping_destroy(conf_mapping_t * conf_map); void conf_mapping_dump(conf_mapping_t * conf_map, int log_level); no_addr_loct * no_addr_loct_new_init(locator_t * loct, char *iface, int afi); void no_addr_loct_del(no_addr_loct * nloct); no_addr_loct * get_no_addr_loct_from_list(glist_t *list, locator_t *locator); void validate_rloc_probing_parameters(int *interval,int *retries,int *retries_int); int validate_priority_weight(int p, int w); int add_server(char *str_addr, glist_t *list); int add_map_server(glist_t *ms_list, char *str_addr, int key_type, char *key, uint8_t proxy_reply); int add_proxy_etr_entry(mcache_entry_t *petrs, char *str_addr, int priority, int weight); /* * Create the locators associated with the address of the iface and assign them * to the mapping_t and the iface_locators * @param iface Interface containing the rlocs associated to the mapping * @param if_loct Structure that associate iface with locators * @param mapping Mapping where to add the new locators * @param priority4 priority of the IPv4 RLOC. 1..255 -1 the IPv4 address is not used * @param weight4 weight of the IPv4 RLOC * @param priority6 priority of the IPv6 RLOC. 1..255 -1 the IPv6 address is not used * @param weight6 weight of the IPv6 RLOC * @return GOOD if finish correctly or an error code otherwise */ int link_iface_and_mapping(iface_t *iface, iface_locators *if_loct, map_local_entry_t *map_loc_e, int afi, int priority, int weight); int add_rtr_iface(lisp_xtr_t *xtr, char *iface_name,int afi, int priority, int weight); lisp_site_prefix_t * build_lisp_site_prefix(lisp_ms_t *ms, char *eidstr, uint32_t iid, int key_type, char *key, uint8_t more_specifics, uint8_t proxy_reply, uint8_t merge, shash_t *lcaf_ht); char * get_interface_name_from_address(lisp_addr_t *addr); /* Parses an EID/RLOC (IP or LCAF) and returns a list of 'lisp_addr_t'. * Caller must free the returned value */ glist_t * parse_lisp_addr(char *address, shash_t *lcaf_ht); /* Parses a char (IP or FQDN) into a list of 'lisp_addr_t'. * Caller must free the returned value */ glist_t * parse_ip_addr(char *addr_str); locator_t* clone_customize_locator(oor_ctrl_dev_t *dev, locator_t * locator, glist_t * no_addr_loct_l, uint8_t is_local); mapping_t * process_mapping_config(oor_ctrl_dev_t * dev, shash_t * lcaf_ht, conf_mapping_t * conf_mapping, uint8_t is_local); int add_local_db_map_local_entry(map_local_entry_t *map_loca_entry, lisp_xtr_t *xtr); void nat_set_site_ID(lisp_xtr_t *xtr, uint64_t site_id); int nat_set_xTR_ID(lisp_xtr_t *xtr); #endif /* OOR_CONFIG_FUNCTIONS_H_ */ oor-1.2.0/oor/config/oor_config_uci.c000066400000000000000000001755541313612200500175170ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "cmdline.h" #include "oor_config_functions.h" #include "oor_config_uci.h" #include "../oor_external.h" #include "../iface_list.h" #include "../control/oor_ctrl_device.h" #include "../control/lisp_xtr.h" #include "../control/lisp_ms.h" #include "../control/oor_control.h" #include "../data-plane/data-plane.h" #include "../lib/shash.h" #include "../lib/oor_log.h" #include "../lib/prefixes.h" #include #include #include /***************************** FUNCTIONS DECLARATION *************************/ int configure_xtr( struct uci_context *ctx, struct uci_package *pck); int configure_mn( struct uci_context *ctx, struct uci_package *pck); int configure_rtr( struct uci_context *ctx, struct uci_package *pck); int configure_ms( struct uci_context *ctx, struct uci_package *pck); static mapping_t* parse_mapping( struct uci_context *ctx, struct uci_section *sect, oor_ctrl_dev_t *dev, shash_t *rloc_set_ht, shash_t *lcaf_ht, glist_t *no_addr_loct_l, uint8_t is_local); static shash_t * parse_rlocs( struct uci_context *ctx, struct uci_package *pck, shash_t *lcaf_ht, glist_t *no_addr_loct_list); static shash_t * parse_rloc_sets( struct uci_context *ctx, struct uci_package *pck, shash_t *rlocs_ht, shash_t *lcaf_ht); static shash_t * parse_lcafs( struct uci_context *ctx, struct uci_package *pck); static int parse_elp_node( struct uci_context *ctx, struct uci_section *section, shash_t *ht); /********************************** FUNCTIONS ********************************/ int handle_config_file() { char *uci_conf_dir; char *uci_conf_file; struct uci_context *ctx; struct uci_package *pck = NULL; struct uci_section *sect; struct uci_element *element; int uci_debug; char *uci_log_file; char *uci_op_mode; int res = BAD; if (config_file == NULL){ config_file = strdup("/etc/config/oor"); } ctx = uci_alloc_context(); if (ctx == NULL) { OOR_LOG(LCRIT, "Could not create UCI context. Exiting ..."); return (BAD); } uci_conf_dir = dirname(strdup(config_file)); uci_conf_file = basename(strdup(config_file)); uci_set_confdir(ctx, uci_conf_dir); OOR_LOG(LDBG_1,"Conf dir: %s\n",ctx->confdir); uci_load(ctx,uci_conf_file,&pck); if (pck == NULL) { OOR_LOG(LCRIT, "Could not load conf file: %s. Exiting ...",uci_conf_file); uci_perror(ctx,"Error while loading file "); uci_free_context(ctx); return (BAD); } OOR_LOG(LDBG_3,"package uci: %s\n",pck->ctx->confdir); uci_foreach_element(&pck->sections, element) { sect = uci_to_section(element); if (strcmp(sect->type, "daemon") == 0){ uci_debug = strtol(uci_lookup_option_string(ctx, sect, "debug"),NULL,10); if (debug_level == -1){//Used to not overwrite debug level passed by console if (uci_debug > 0) debug_level = uci_debug; else debug_level = 0; if (debug_level > 3) debug_level = 3; } uci_log_file = (char *)uci_lookup_option_string(ctx, sect, "log_file"); if (daemonize == TRUE){ open_log_file(uci_log_file); } uci_op_mode = (char *)uci_lookup_option_string(ctx, sect, "operating_mode"); if (uci_op_mode != NULL) { if (strcmp(uci_op_mode, "xTR") == 0) { res = configure_xtr(ctx, pck); } else if (strcmp(uci_op_mode, "MS") == 0) { res = configure_ms(ctx, pck); } else if (strcmp(uci_op_mode, "RTR") == 0) { res = configure_rtr(ctx, pck); }else if (strcmp(uci_op_mode, "MN") == 0) { res = configure_mn(ctx, pck); }else { OOR_LOG(LCRIT, "Configuration file: Unknown operating mode: %s",uci_op_mode); return (BAD); } } continue; } } return (res); } int configure_xtr(struct uci_context *ctx, struct uci_package *pck) { struct uci_section *sect; struct uci_element *element; struct uci_element *elem_addr; struct uci_option *opt; int uci_retries; char *uci_address; char *uci_nat_aware; int uci_key_type; char *uci_key; int uci_proxy_reply; int uci_priority; int uci_weigth; shash_t *lcaf_ht; shash_t *rlocs_ht; shash_t *rloc_set_ht; lisp_xtr_t *xtr; map_local_entry_t *map_loc_e; mapping_t *mapping; glist_t *no_addr_loct_list; /* CREATE AND CONFIGURE XTR */ if (ctrl_dev_create(xTR_MODE, &ctrl_dev) != GOOD) { OOR_LOG(LCRIT, "Failed to create xTR. Aborting!"); return (BAD); } xtr = CONTAINER_OF(ctrl_dev, lisp_xtr_t, super); /* FWD POLICY STRUCTURES */ xtr->fwd_policy = fwd_policy_class_find("flow_balancing"); xtr->fwd_policy_dev_parm = xtr->fwd_policy->new_dev_policy_inf(ctrl_dev,NULL); /* CREATE LCAFS HTABLE */ /* get a hash table of all the elps. If any are configured, * their names could appear in the rloc field of database mappings * or static map cache entries */ lcaf_ht = parse_lcafs(ctx,pck); if (!lcaf_ht){ return (BAD); } /* CREATE RLOCs sets HTABLE */ no_addr_loct_list = glist_new_managed((glist_del_fct)no_addr_loct_del); rlocs_ht = parse_rlocs(ctx,pck,lcaf_ht,no_addr_loct_list); if (!rlocs_ht){ glist_destroy(no_addr_loct_list); return (BAD); } rloc_set_ht = parse_rloc_sets(ctx,pck,rlocs_ht,lcaf_ht); if (!rloc_set_ht){ glist_destroy(no_addr_loct_list); shash_destroy(rloc_set_ht); return (BAD); } uci_foreach_element(&pck->sections, element) { sect = uci_to_section(element); /* NAT Traversal options */ if (strcmp(sect->type, "nat-traversal") == 0){ uci_nat_aware = uci_lookup_option_string(ctx, sect, "nat_traversal_support"); if (uci_nat_aware && strcmp(uci_nat_aware, "on") == 0){ xtr->nat_aware = TRUE; nat_set_xTR_ID(xtr); nat_set_site_ID(xtr, 0); default_rloc_afi = AF_INET; OOR_LOG(LDBG_1, "NAT support enabled. Set defaul RLOC to IPv4 family"); }else{ xtr->nat_aware = FALSE; } break; } } uci_foreach_element(&pck->sections, element) { sect = uci_to_section(element); if (strcmp(sect->type, "daemon") == 0){ /* RETRIES */ if (uci_lookup_option_string(ctx, sect, "map_request_retries") != NULL){ uci_retries = strtol(uci_lookup_option_string(ctx, sect, "map_request_retries"),NULL,10); if (uci_retries >= 0 && uci_retries <= OOR_MAX_RETRANSMITS){ xtr->map_request_retries = uci_retries; }else if (uci_retries > OOR_MAX_RETRANSMITS){ xtr->map_request_retries = OOR_MAX_RETRANSMITS; OOR_LOG(LWRN, "Map-Request retries should be between 0 and %d. " "Using default value: %d",OOR_MAX_RETRANSMITS, OOR_MAX_RETRANSMITS); } }else{ OOR_LOG(LWRN,"Configuration file: Map Request Retries not specified." " Setting default value: %d sec.",DEFAULT_MAP_REQUEST_RETRIES); xtr->map_request_retries = DEFAULT_MAP_REQUEST_RETRIES; continue; } } /* RLOC PROBING CONFIG */ if (strcmp(sect->type, "rloc-probing") == 0){ if (uci_lookup_option_string(ctx, sect, "rloc_probe_interval") != NULL){ xtr->probe_interval = strtol(uci_lookup_option_string(ctx, sect, "rloc_probe_interval"),NULL,10); }else{ OOR_LOG(LWRN,"Configuration file: RLOC probe interval not specified." " Disabling RLOC Probing"); xtr->probe_interval = 0; continue; } if (uci_lookup_option_string(ctx, sect, "rloc_probe_retries") != NULL){ xtr->probe_retries = strtol(uci_lookup_option_string(ctx, sect, "rloc_probe_retries"),NULL,10); }else{ OOR_LOG(LWRN,"Configuration file: RLOC Probe Retries not specified." " Setting default value: %d sec.",DEFAULT_RLOC_PROBING_RETRIES); xtr->probe_retries = DEFAULT_RLOC_PROBING_RETRIES; } if (uci_lookup_option_string(ctx, sect, "rloc_probe_retries_interval") != NULL){ xtr->probe_retries_interval = strtol(uci_lookup_option_string(ctx, sect, "rloc_probe_retries_interval"),NULL,10); }else{ OOR_LOG(LWRN,"Configuration file: RLOC Probe Retries Intervals not specified." " Setting default value: %d sec.",DEFAULT_RLOC_PROBING_RETRIES_INTERVAL); xtr->probe_retries_interval = DEFAULT_RLOC_PROBING_RETRIES_INTERVAL; } validate_rloc_probing_parameters(&xtr->probe_interval, &xtr->probe_retries, &xtr->probe_retries_interval); continue; } /* MAP-RESOLVER CONFIG */ if (strcmp(sect->type, "map-resolver") == 0){ opt = uci_lookup_option(ctx, sect, "address"); if (opt != NULL){ uci_foreach_element(&(opt->v.list), elem_addr){ if (add_server(elem_addr->name, xtr->map_resolvers) != GOOD){ OOR_LOG(LCRIT,"Can't add %s Map Resolver.",elem_addr->name); }else{ OOR_LOG(LDBG_1, "Added %s to map-resolver list", elem_addr->name); } } } continue; } /* MAP-SERVER CONFIG */ if (strcmp(sect->type, "map-server") == 0){ uci_address = (char *)uci_lookup_option_string(ctx, sect, "address"); if (uci_lookup_option_string(ctx, sect, "key_type") != NULL){ uci_key_type = strtol(uci_lookup_option_string(ctx, sect, "key_type"),NULL,10); }else{ OOR_LOG(LWRN,"Configuration file: No ket type assigned to the map server \"%s\"." " Set default value: HMAC_SHA_1_96",uci_address); uci_key_type = HMAC_SHA_1_96; } uci_key = (char *)uci_lookup_option_string(ctx, sect, "key"); if (strcmp(uci_lookup_option_string(ctx, sect, "proxy_reply"), "on") == 0){ uci_proxy_reply = TRUE; }else{ uci_proxy_reply = FALSE; } if (add_map_server(xtr->map_servers,uci_address, uci_key_type, uci_key, uci_proxy_reply) != GOOD ){ OOR_LOG(LCRIT, "Can't add %s Map Server.", uci_address); }else{ OOR_LOG(LDBG_1, "Added %s to map-server list", uci_address); } continue; } /* PROXY-ETR CONFIG */ if (strcmp(sect->type, "proxy-etr-ipv4") == 0){ uci_address = (char *)uci_lookup_option_string(ctx, sect, "address"); if (uci_lookup_option_string(ctx, sect, "priority") != NULL){ uci_priority = strtol(uci_lookup_option_string(ctx, sect, "priority"),NULL,10); }else{ OOR_LOG(LWRN,"Configuration file: No priority assigned to the proxy-etr \"%s\"." " Set default value: 10",uci_address); uci_priority = 10; } if (uci_lookup_option_string(ctx, sect, "weight") != NULL){ uci_weigth = strtol(uci_lookup_option_string(ctx, sect, "weight"),NULL,10); }else{ OOR_LOG(LWRN,"Configuration file: No weight assigned to the proxy-etr \"%s\"." " Set default value: 100",uci_address); uci_weigth = 100; } if (add_proxy_etr_entry(xtr->petrs_ipv4,uci_address,uci_priority,uci_weigth) != GOOD ){ OOR_LOG(LERR, "Can't add proxy-etr %s", uci_address); }else{ OOR_LOG(LDBG_1, "Added %s to proxy-etr list", uci_address); } continue; } /* PROXY-ETR CONFIG */ if (strcmp(sect->type, "proxy-etr-ipv6") == 0){ uci_address = (char *)uci_lookup_option_string(ctx, sect, "address"); if (uci_lookup_option_string(ctx, sect, "priority") != NULL){ uci_priority = strtol(uci_lookup_option_string(ctx, sect, "priority"),NULL,10); }else{ OOR_LOG(LWRN,"Configuration file: No priority assigned to the proxy-etr \"%s\"." " Set default value: 10",uci_address); uci_priority = 10; } if (uci_lookup_option_string(ctx, sect, "weight") != NULL){ uci_weigth = strtol(uci_lookup_option_string(ctx, sect, "weight"),NULL,10); }else{ OOR_LOG(LWRN,"Configuration file: No weight assigned to the proxy-etr \"%s\"." " Set default value: 100",uci_address); uci_weigth = 100; } if (add_proxy_etr_entry(xtr->petrs_ipv6,uci_address,uci_priority,uci_weigth) != GOOD ){ OOR_LOG(LERR, "Can't add proxy-etr %s", uci_address); }else{ OOR_LOG(LDBG_1, "Added %s to proxy-etr list", uci_address); } continue; } /* PROXY-ITR CONFIG */ if (strcmp(sect->type, "proxy-itr") == 0){ opt = uci_lookup_option(ctx, sect, "address"); if (opt != NULL){ uci_foreach_element(&(opt->v.list), elem_addr){ if (add_server(elem_addr->name, xtr->pitrs) != GOOD){ OOR_LOG(LERR, "Can't add %s to proxy-itr list. Discarded ...", elem_addr->name); }else{ OOR_LOG(LDBG_1, "Added %s to proxy-itr list", elem_addr->name); } } } continue; } if (strcmp(sect->type, "database-mapping") == 0){ mapping = parse_mapping(ctx,sect,&(xtr->super),rloc_set_ht,lcaf_ht,no_addr_loct_list,TRUE); if (mapping == NULL){ OOR_LOG(LERR, "Can't add EID prefix %s. Discarded ...", uci_lookup_option_string(ctx, sect, "eid_prefix")); return (BAD); } map_loc_e = map_local_entry_new_init(mapping); if (map_loc_e == NULL){ mapping_del(mapping); continue; } if (xtr->fwd_policy->init_map_loc_policy_inf( xtr->fwd_policy_dev_parm,map_loc_e,NULL) != GOOD){ OOR_LOG(LERR, "Couldn't initiate forward information for mapping with EID: %s. Discarding it...", lisp_addr_to_char(mapping_eid(mapping))); map_local_entry_del(map_loc_e); continue; } if (add_local_db_map_local_entry(map_loc_e,xtr) != GOOD){ map_local_entry_del(map_loc_e); continue; } continue; } /* STATIC MAP-CACHE CONFIG */ if (strcmp(sect->type, "static-map-cache") == 0){ mapping = parse_mapping(ctx,sect,&(xtr->super),rloc_set_ht,lcaf_ht,no_addr_loct_list,FALSE); if (mapping == NULL){ OOR_LOG(LERR, "Can't add static Map Cache entry with EID prefix %s. Discarded ...", uci_lookup_option_string(ctx, sect, "eid_prefix")); return (BAD); } if (mcache_lookup_exact(xtr->map_cache, mapping_eid(mapping)) == NULL){ if (tr_mcache_add_static_mapping(xtr, mapping) == GOOD){ OOR_LOG(LDBG_1, "Added static Map Cache entry with EID prefix %s in the database.", lisp_addr_to_char(mapping_eid(mapping))); }else{ OOR_LOG(LERR, "Can't add static Map Cache entry with EID prefix %s. Discarded ...", mapping_eid(mapping)); mapping_del(mapping); } }else{ OOR_LOG(LERR, "Configuration file: Duplicated static Map Cache entry with EID prefix %s." "Discarded ...",uci_lookup_option_string(ctx, sect, "eid_prefix")); mapping_del(mapping); continue; } continue; } } /* Calculate forwarding info por proxy-etrs */ if (xtr->fwd_policy->init_map_cache_policy_inf(xtr->fwd_policy_dev_parm,xtr->petrs_ipv4) != GOOD){ OOR_LOG(LDBG_1, "Couldn't initiate routing info for PeTRs for IPv4 EIDs!."); mcache_entry_del(xtr->petrs_ipv4); return(BAD); } /* Calculate forwarding info por proxy-etrs */ if (xtr->fwd_policy->init_map_cache_policy_inf(xtr->fwd_policy_dev_parm,xtr->petrs_ipv6) != GOOD){ OOR_LOG(LDBG_1, "Couldn't initiate routing info for PeTRs for IPv6 EIDs!."); mcache_entry_del(xtr->petrs_ipv6); return(BAD); } /* destroy the hash table */ shash_destroy(lcaf_ht); shash_destroy(rlocs_ht); shash_destroy(rloc_set_ht); glist_destroy(no_addr_loct_list); return(GOOD); } int configure_mn(struct uci_context *ctx, struct uci_package *pck) { struct uci_section *sect; struct uci_element *element; struct uci_element *elem_addr; struct uci_option *opt; int uci_retries; char *uci_address; int uci_key_type; char *uci_key; char *uci_nat_aware; int uci_proxy_reply; int uci_priority; int uci_weigth; shash_t *lcaf_ht; shash_t *rlocs_ht; shash_t *rloc_set_ht; lisp_xtr_t *xtr; map_local_entry_t *map_loc_e; mapping_t *mapping; glist_t *no_addr_loct_list; /* CREATE AND CONFIGURE XTR */ if (ctrl_dev_create(MN_MODE, &ctrl_dev) != GOOD) { OOR_LOG(LCRIT, "Failed to create Mobile Node device. Aborting!"); return (BAD); } xtr = CONTAINER_OF(ctrl_dev, lisp_xtr_t, super); /* FWD POLICY STRUCTURES */ xtr->fwd_policy = fwd_policy_class_find("flow_balancing"); xtr->fwd_policy_dev_parm = xtr->fwd_policy->new_dev_policy_inf(ctrl_dev,NULL); /* CREATE LCAFS HTABLE */ /* get a hash table of all the elps. If any are configured, * their names could appear in the rloc field of database mappings * or static map cache entries */ lcaf_ht = parse_lcafs(ctx,pck); if (!lcaf_ht){ return (BAD); } /* CREATE RLOCs sets HTABLE */ no_addr_loct_list = glist_new_managed((glist_del_fct)no_addr_loct_del); rlocs_ht = parse_rlocs(ctx,pck,lcaf_ht,no_addr_loct_list); if (!rlocs_ht){ glist_destroy(no_addr_loct_list); return (BAD); } rloc_set_ht = parse_rloc_sets(ctx,pck,rlocs_ht,lcaf_ht); if (!rloc_set_ht){ glist_destroy(no_addr_loct_list); shash_destroy(rloc_set_ht); return (BAD); } uci_foreach_element(&pck->sections, element) { sect = uci_to_section(element); /* NAT Traversal options */ /* NAT Traversal options */ if (strcmp(sect->type, "nat-traversal") == 0){ uci_nat_aware = uci_lookup_option_string(ctx, sect, "nat_traversal_support"); if (uci_nat_aware && strcmp(uci_nat_aware, "on") == 0){ xtr->nat_aware = TRUE; nat_set_xTR_ID(xtr); nat_set_site_ID(xtr, 0); default_rloc_afi = AF_INET; OOR_LOG(LDBG_1, "NAT support enabled. Set defaul RLOC to IPv4 family"); }else{ xtr->nat_aware = FALSE; } break; } } uci_foreach_element(&pck->sections, element) { sect = uci_to_section(element); if (strcmp(sect->type, "daemon") == 0){ /* RETRIES */ if (uci_lookup_option_string(ctx, sect, "map_request_retries") != NULL){ uci_retries = strtol(uci_lookup_option_string(ctx, sect, "map_request_retries"),NULL,10); if (uci_retries >= 0 && uci_retries <= OOR_MAX_RETRANSMITS){ xtr->map_request_retries = uci_retries; }else if (uci_retries > OOR_MAX_RETRANSMITS){ xtr->map_request_retries = OOR_MAX_RETRANSMITS; OOR_LOG(LWRN, "Map-Request retries should be between 0 and %d. " "Using default value: %d",OOR_MAX_RETRANSMITS, OOR_MAX_RETRANSMITS); } }else{ OOR_LOG(LWRN,"Configuration file: Map Request Retries not specified." " Setting default value: %d sec.",DEFAULT_MAP_REQUEST_RETRIES); xtr->map_request_retries = DEFAULT_MAP_REQUEST_RETRIES; continue; } } /* RLOC PROBING CONFIG */ if (strcmp(sect->type, "rloc-probing") == 0){ if (uci_lookup_option_string(ctx, sect, "rloc_probe_interval") != NULL){ xtr->probe_interval = strtol(uci_lookup_option_string(ctx, sect, "rloc_probe_interval"),NULL,10); }else{ OOR_LOG(LWRN,"Configuration file: RLOC probe interval not specified." " Disabling RLOC Probing"); xtr->probe_interval = 0; continue; } if (uci_lookup_option_string(ctx, sect, "rloc_probe_retries") != NULL){ xtr->probe_retries = strtol(uci_lookup_option_string(ctx, sect, "rloc_probe_retries"),NULL,10); }else{ OOR_LOG(LWRN,"Configuration file: RLOC Probe Retries not specified." " Setting default value: %d sec.",DEFAULT_RLOC_PROBING_RETRIES); xtr->probe_retries = DEFAULT_RLOC_PROBING_RETRIES; } if (uci_lookup_option_string(ctx, sect, "rloc_probe_retries_interval") != NULL){ xtr->probe_retries_interval = strtol(uci_lookup_option_string(ctx, sect, "rloc_probe_retries_interval"),NULL,10); }else{ OOR_LOG(LWRN,"Configuration file: RLOC Probe Retries Intervals not specified." " Setting default value: %d sec.",DEFAULT_RLOC_PROBING_RETRIES_INTERVAL); xtr->probe_retries_interval = DEFAULT_RLOC_PROBING_RETRIES_INTERVAL; } validate_rloc_probing_parameters(&xtr->probe_interval, &xtr->probe_retries, &xtr->probe_retries_interval); continue; } /* MAP-RESOLVER CONFIG */ if (strcmp(sect->type, "map-resolver") == 0){ opt = uci_lookup_option(ctx, sect, "address"); if (opt != NULL){ uci_foreach_element(&(opt->v.list), elem_addr){ if (add_server(elem_addr->name, xtr->map_resolvers) != GOOD){ OOR_LOG(LCRIT,"Can't add %s Map Resolver.",elem_addr->name); }else{ OOR_LOG(LDBG_1, "Added %s to map-resolver list", elem_addr->name); } } } continue; } /* MAP-SERVER CONFIG */ if (strcmp(sect->type, "map-server") == 0){ uci_address = (char *)uci_lookup_option_string(ctx, sect, "address"); if (uci_lookup_option_string(ctx, sect, "key_type") != NULL){ uci_key_type = strtol(uci_lookup_option_string(ctx, sect, "key_type"),NULL,10); }else{ OOR_LOG(LWRN,"Configuration file: No ket type assigned to the map server \"%s\"." " Set default value: HMAC_SHA_1_96",uci_address); uci_key_type = HMAC_SHA_1_96; } uci_key = (char *)uci_lookup_option_string(ctx, sect, "key"); if (strcmp(uci_lookup_option_string(ctx, sect, "proxy_reply"), "on") == 0){ uci_proxy_reply = TRUE; }else{ uci_proxy_reply = FALSE; } if (add_map_server(xtr->map_servers,uci_address, uci_key_type, uci_key, uci_proxy_reply) != GOOD ){ OOR_LOG(LCRIT, "Can't add %s Map Server.", uci_address); }else{ OOR_LOG(LDBG_1, "Added %s to map-server list", uci_address); } continue; } /* PROXY-ETR CONFIG */ if (strcmp(sect->type, "proxy-etr-ipv4") == 0){ uci_address = (char *)uci_lookup_option_string(ctx, sect, "address"); if (uci_lookup_option_string(ctx, sect, "priority") != NULL){ uci_priority = strtol(uci_lookup_option_string(ctx, sect, "priority"),NULL,10); }else{ OOR_LOG(LWRN,"Configuration file: No priority assigned to the proxy-etr \"%s\"." " Set default value: 10",uci_address); uci_priority = 10; } if (uci_lookup_option_string(ctx, sect, "weight") != NULL){ uci_weigth = strtol(uci_lookup_option_string(ctx, sect, "weight"),NULL,10); }else{ OOR_LOG(LWRN,"Configuration file: No weight assigned to the proxy-etr \"%s\"." " Set default value: 100",uci_address); uci_weigth = 100; } if (add_proxy_etr_entry(xtr->petrs_ipv4,uci_address,uci_priority,uci_weigth) != GOOD ){ OOR_LOG(LERR, "Can't add proxy-etr %s", uci_address); }else{ OOR_LOG(LDBG_1, "Added %s to proxy-etr list", uci_address); } continue; } if (strcmp(sect->type, "proxy-etr-ipv6") == 0){ uci_address = (char *)uci_lookup_option_string(ctx, sect, "address"); if (uci_lookup_option_string(ctx, sect, "priority") != NULL){ uci_priority = strtol(uci_lookup_option_string(ctx, sect, "priority"),NULL,10); }else{ OOR_LOG(LWRN,"Configuration file: No priority assigned to the proxy-etr \"%s\"." " Set default value: 10",uci_address); uci_priority = 10; } if (uci_lookup_option_string(ctx, sect, "weight") != NULL){ uci_weigth = strtol(uci_lookup_option_string(ctx, sect, "weight"),NULL,10); }else{ OOR_LOG(LWRN,"Configuration file: No weight assigned to the proxy-etr \"%s\"." " Set default value: 100",uci_address); uci_weigth = 100; } if (add_proxy_etr_entry(xtr->petrs_ipv6,uci_address,uci_priority,uci_weigth) != GOOD ){ OOR_LOG(LERR, "Can't add proxy-etr %s", uci_address); }else{ OOR_LOG(LDBG_1, "Added %s to proxy-etr list", uci_address); } continue; } /* PROXY-ITR CONFIG */ if (strcmp(sect->type, "proxy-itr") == 0){ opt = uci_lookup_option(ctx, sect, "address"); if (opt != NULL){ uci_foreach_element(&(opt->v.list), elem_addr){ if (add_server(elem_addr->name, xtr->pitrs) != GOOD){ OOR_LOG(LERR, "Can't add %s to proxy-itr list. Discarded ...", elem_addr->name); }else{ OOR_LOG(LDBG_1, "Added %s to proxy-itr list", elem_addr->name); } } } continue; } if (strcmp(sect->type, "database-mapping") == 0){ mapping = parse_mapping(ctx,sect,&(xtr->super),rloc_set_ht,lcaf_ht,no_addr_loct_list,TRUE); if (mapping == NULL){ OOR_LOG(LERR, "Can't add EID prefix %s. Discarded ...", uci_lookup_option_string(ctx, sect, "eid_prefix")); return (BAD); } map_loc_e = map_local_entry_new_init(mapping); if (map_loc_e == NULL){ mapping_del(mapping); continue; } if ( xtr->fwd_policy->init_map_loc_policy_inf( xtr->fwd_policy_dev_parm,map_loc_e,NULL) != GOOD){ OOR_LOG(LERR, "Couldn't initiate forward information for mapping with EID: %s. Discarding it...", lisp_addr_to_char(mapping_eid(mapping))); map_local_entry_del(map_loc_e); continue; } if (add_local_db_map_local_entry(map_loc_e,xtr) != GOOD){ map_local_entry_del(map_loc_e); continue; } continue; } /* STATIC MAP-CACHE CONFIG */ if (strcmp(sect->type, "static-map-cache") == 0){ mapping = parse_mapping(ctx,sect,&(xtr->super),rloc_set_ht,lcaf_ht,no_addr_loct_list,FALSE); if (mapping == NULL){ OOR_LOG(LERR, "Can't add static Map Cache entry with EID prefix %s. Discarded ...", uci_lookup_option_string(ctx, sect, "eid_prefix")); return (BAD); } if (mcache_lookup_exact(xtr->map_cache, mapping_eid(mapping)) == NULL){ if (tr_mcache_add_static_mapping(xtr, mapping) == GOOD){ OOR_LOG(LDBG_1, "Added static Map Cache entry with EID prefix %s in the database.", lisp_addr_to_char(mapping_eid(mapping))); }else{ OOR_LOG(LERR, "Can't add static Map Cache entry with EID prefix %s. Discarded ...", mapping_eid(mapping)); mapping_del(mapping); } }else{ OOR_LOG(LERR, "Configuration file: Duplicated static Map Cache entry with EID prefix %s." "Discarded ...",uci_lookup_option_string(ctx, sect, "eid_prefix")); mapping_del(mapping); continue; } continue; } } /* Calculate forwarding info por proxy-etrs */ if (xtr->fwd_policy->init_map_cache_policy_inf(xtr->fwd_policy_dev_parm,xtr->petrs_ipv4) != GOOD){ OOR_LOG(LDBG_1, "Couldn't initiate routing info for PeTRs for IPv4 EIDs!."); mcache_entry_del(xtr->petrs_ipv4); return(BAD); } if (xtr->fwd_policy->init_map_cache_policy_inf(xtr->fwd_policy_dev_parm,xtr->petrs_ipv6) != GOOD){ OOR_LOG(LDBG_1, "Couldn't initiate routing info for PeTRs for IPv6 EIDs!."); mcache_entry_del(xtr->petrs_ipv6); return(BAD); } /* destroy the hash table */ shash_destroy(lcaf_ht); shash_destroy(rlocs_ht); shash_destroy(rloc_set_ht); glist_destroy(no_addr_loct_list); return(GOOD); } int configure_rtr(struct uci_context *ctx, struct uci_package *pck) { lisp_xtr_t *xtr; struct uci_section *sect; struct uci_element *element; struct uci_element *elem_addr; struct uci_option *opt; shash_t *lcaf_ht; shash_t *rlocs_ht; shash_t *rloc_set_ht; int uci_retries; char *uci_address; int uci_key_type; char *uci_key; int uci_proxy_reply; char *uci_iface; mapping_t *mapping; int uci_afi; int uci_priority; int uci_weigth; glist_t *no_addr_loct_list; /* CREATE AND CONFIGURE RTR (xTR in fact) */ if (ctrl_dev_create(RTR_MODE, &ctrl_dev) != GOOD) { OOR_LOG(LCRIT, "Failed to create RTR. Aborting!"); return (BAD); } xtr = CONTAINER_OF(ctrl_dev, lisp_xtr_t, super); /* FWD POLICY STRUCTURES */ xtr->fwd_policy = fwd_policy_class_find("flow_balancing"); xtr->fwd_policy_dev_parm = xtr->fwd_policy->new_dev_policy_inf(ctrl_dev,NULL); /* CREATE LCAFS HTABLE */ /* get a hash table of all the elps. If any are configured, * their names could appear in the rloc field of database mappings * or static map cache entries */ lcaf_ht = parse_lcafs(ctx,pck); if (!lcaf_ht){ return (BAD); } /* CREATE RLOCs sets HTABLE */ no_addr_loct_list = glist_new_managed((glist_del_fct)no_addr_loct_del); rlocs_ht = parse_rlocs(ctx,pck,lcaf_ht,no_addr_loct_list); if (!rlocs_ht){ glist_destroy(no_addr_loct_list); return (BAD); } rloc_set_ht = parse_rloc_sets(ctx,pck,rlocs_ht,lcaf_ht); if (!rloc_set_ht){ glist_destroy(no_addr_loct_list); shash_destroy(rloc_set_ht); return (BAD); } uci_foreach_element(&pck->sections, element) { sect = uci_to_section(element); if (strcmp(sect->type, "daemon") == 0){ /* RETRIES */ if (uci_lookup_option_string(ctx, sect, "map_request_retries") != NULL){ uci_retries = strtol(uci_lookup_option_string(ctx, sect, "map_request_retries"),NULL,10); if (uci_retries >= 0 && uci_retries <= OOR_MAX_RETRANSMITS){ xtr->map_request_retries = uci_retries; }else if (uci_retries > OOR_MAX_RETRANSMITS){ xtr->map_request_retries = OOR_MAX_RETRANSMITS; OOR_LOG(LWRN, "Map-Request retries should be between 0 and %d. " "Using default value: %d",OOR_MAX_RETRANSMITS, OOR_MAX_RETRANSMITS); } }else{ OOR_LOG(LWRN,"Configuration file: Map Request Retries not specified." " Setting default value: %d sec.",DEFAULT_MAP_REQUEST_RETRIES); xtr->map_request_retries = DEFAULT_MAP_REQUEST_RETRIES; continue; } } /* RLOC PROBING CONFIG */ if (strcmp(sect->type, "rloc-probing") == 0){ if (uci_lookup_option_string(ctx, sect, "rloc_probe_interval") != NULL){ xtr->probe_interval = strtol(uci_lookup_option_string(ctx, sect, "rloc_probe_interval"),NULL,10); }else{ OOR_LOG(LWRN,"Configuration file: RLOC probe interval not specified." " Disabling RLOC Probing"); xtr->probe_interval = 0; continue; } if (uci_lookup_option_string(ctx, sect, "rloc_probe_retries") != NULL){ xtr->probe_retries = strtol(uci_lookup_option_string(ctx, sect, "rloc_probe_retries"),NULL,10); }else{ OOR_LOG(LWRN,"Configuration file: RLOC Probe Retries not specified." " Setting default value: %d sec.",DEFAULT_RLOC_PROBING_RETRIES); xtr->probe_retries = DEFAULT_RLOC_PROBING_RETRIES; } if (uci_lookup_option_string(ctx, sect, "rloc_probe_retries_interval") != NULL){ xtr->probe_retries_interval = strtol(uci_lookup_option_string(ctx, sect, "rloc_probe_retries_interval"),NULL,10); }else{ OOR_LOG(LWRN,"Configuration file: RLOC Probe Retries Intervals not specified." " Setting default value: %d sec.",DEFAULT_RLOC_PROBING_RETRIES_INTERVAL); xtr->probe_retries_interval = DEFAULT_RLOC_PROBING_RETRIES_INTERVAL; } validate_rloc_probing_parameters(&xtr->probe_interval, &xtr->probe_retries, &xtr->probe_retries_interval); continue; } /* MAP-RESOLVER CONFIG */ if (strcmp(sect->type, "map-resolver") == 0){ opt = uci_lookup_option(ctx, sect, "address"); if (opt != NULL){ uci_foreach_element(&(opt->v.list), elem_addr){ if (add_server(elem_addr->name, xtr->map_resolvers) != GOOD){ OOR_LOG(LCRIT,"Can't add %s Map Resolver.",elem_addr->name); }else{ OOR_LOG(LDBG_1, "Added %s to map-resolver list", elem_addr->name); } } } continue; } /* MAP-SERVER CONFIG */ if (strcmp(sect->type, "map-server") == 0){ uci_address = (char *)uci_lookup_option_string(ctx, sect, "address"); if (uci_lookup_option_string(ctx, sect, "key_type") != NULL){ uci_key_type = strtol(uci_lookup_option_string(ctx, sect, "key_type"),NULL,10); }else{ OOR_LOG(LWRN,"Configuration file: No ket type assigned to the map server \"%s\"." " Set default value: HMAC_SHA_1_96",uci_address); uci_key_type = HMAC_SHA_1_96; } uci_key = (char *)uci_lookup_option_string(ctx, sect, "key"); if (strcmp(uci_lookup_option_string(ctx, sect, "proxy_reply"), "on") == 0){ uci_proxy_reply = TRUE; }else{ uci_proxy_reply = FALSE; } if (add_map_server(xtr->map_servers,uci_address, uci_key_type, uci_key, uci_proxy_reply) != GOOD ){ OOR_LOG(LCRIT, "Can't add %s Map Server.", uci_address); }else{ OOR_LOG(LDBG_1, "Added %s to map-server list", uci_address); } continue; } /* STATIC MAP-CACHE CONFIG */ if (strcmp(sect->type, "static-map-cache") == 0){ mapping = parse_mapping(ctx,sect,&(xtr->super),rloc_set_ht,lcaf_ht,no_addr_loct_list,FALSE); if (mapping == NULL){ OOR_LOG(LERR, "Can't add static Map Cache entry with EID prefix %s. Discarded ...", uci_lookup_option_string(ctx, sect, "eid_prefix")); return (BAD); } if (mcache_lookup_exact(xtr->map_cache, mapping_eid(mapping)) == NULL){ if (tr_mcache_add_static_mapping(xtr, mapping) == GOOD){ OOR_LOG(LDBG_1, "Added static Map Cache entry with EID prefix %s in the database.", lisp_addr_to_char(mapping_eid(mapping))); }else{ OOR_LOG(LERR, "Can't add static Map Cache entry with EID prefix %s. Discarded ...", mapping_eid(mapping)); mapping_del(mapping); } }else{ OOR_LOG(LERR, "Configuration file: Duplicated static Map Cache entry with EID prefix %s." "Discarded ...",uci_lookup_option_string(ctx, sect, "eid_prefix")); mapping_del(mapping); continue; } continue; } /* INTERFACES CONFIG */ if (strcmp(sect->type, "rtr-iface") == 0){ uci_iface = (char *)uci_lookup_option_string(ctx, sect, "iface"); if (uci_lookup_option_string(ctx, sect, "ip_version") != NULL){ uci_afi = strtol(uci_lookup_option_string(ctx, sect, "ip_version"),NULL,10); }else{ OOR_LOG(LWRN,"Configuration file: No IP version selected for the rtr-iface \"%s\"." ,uci_iface); return (BAD); } if (uci_lookup_option_string(ctx, sect, "priority") != NULL){ uci_priority = strtol(uci_lookup_option_string(ctx, sect, "priority"),NULL,10); }else{ OOR_LOG(LWRN,"Configuration file: No priority assigned to the rtr-iface \"%s\"." " Set default value: 10",uci_iface); uci_priority = 10; } if (uci_lookup_option_string(ctx, sect, "weight") != NULL){ uci_weigth = strtol(uci_lookup_option_string(ctx, sect, "weight"),NULL,10); }else{ OOR_LOG(LWRN,"Configuration file: No weight assigned to the rtr-iface \"%s\"." " Set default value: 100",uci_iface); uci_weigth = 100; } if (add_rtr_iface(xtr, uci_iface, uci_afi, uci_priority, uci_weigth) == GOOD) { OOR_LOG(LDBG_1, "Configured interface %s for RTR",uci_iface); } else{ OOR_LOG(LERR, "Can't configure iface %s for RTR",uci_iface); } } } /* destroy the hash table */ shash_destroy(lcaf_ht); shash_destroy(rlocs_ht); shash_destroy(rloc_set_ht); glist_destroy(no_addr_loct_list); return(GOOD); } int configure_ms(struct uci_context *ctx,struct uci_package *pck) { lisp_ms_t *ms; struct uci_section *sect; struct uci_element *element; char *uci_iface; char *uci_eid_prefix; int uci_iid = 0; int uci_key_type; char *uci_key; uint8_t uci_more_specifics; uint8_t uci_proxy_reply; uint8_t uci_merge; mapping_t *mapping; lisp_site_prefix_t *site; shash_t *lcaf_ht; shash_t *rlocs_ht; shash_t *rloc_set_ht; glist_t *no_addr_loct_list; iface_t *iface; /* create and configure xtr */ if (ctrl_dev_create(MS_MODE, &ctrl_dev) != GOOD) { OOR_LOG(LCRIT, "Failed to create MS. Aborting!"); return (BAD); } ms = CONTAINER_OF(ctrl_dev, lisp_ms_t, super); /* create lcaf hash table */ lcaf_ht = parse_lcafs(ctx,pck); if (!lcaf_ht){ return (BAD); } /* CREATE RLOCs sets HTABLE */ no_addr_loct_list = glist_new_managed((glist_del_fct)no_addr_loct_del); rlocs_ht = parse_rlocs(ctx,pck,lcaf_ht,no_addr_loct_list); if (!rlocs_ht){ glist_destroy(no_addr_loct_list); return (BAD); } rloc_set_ht = parse_rloc_sets(ctx,pck,rlocs_ht,lcaf_ht); if (!rloc_set_ht){ glist_destroy(no_addr_loct_list); shash_destroy(rloc_set_ht); return (BAD); } uci_foreach_element(&pck->sections, element) { sect = uci_to_section(element); /* CONTROL INTERFACE */ /* TODO: should work with all interfaces in the future */ if (strcmp(sect->type, "ms_basic") == 0){ uci_iface = (char *)uci_lookup_option_string(ctx, sect, "control_iface"); if (uci_iface == NULL){ OOR_LOG(LERR,"Configuration file: No control iface assigned"); return(BAD); } if ((iface = add_interface(uci_iface))==NULL) { return(BAD); } iface_configure (iface, AF_INET); iface_configure (iface, AF_INET6); } /* LISP-SITE CONFIG */ if (strcmp(sect->type, "lisp-site") == 0){ uci_eid_prefix = (char *)uci_lookup_option_string(ctx, sect, "eid_prefix"); if (!uci_eid_prefix){ OOR_LOG(LERR,"Configuration file: No eid_prefix assigned"); return (BAD); } if (uci_lookup_option_string(ctx, sect, "key_type") != NULL){ uci_key_type = strtol(uci_lookup_option_string(ctx, sect, "key_type"),NULL,10); }else { OOR_LOG(LERR,"Configuration file: No key-type specified"); return (BAD); } uci_key = (char *)uci_lookup_option_string(ctx, sect, "key"); if (!uci_key){ OOR_LOG(LERR,"Configuration file: Key could not be null"); return (BAD); } if (uci_lookup_option_string(ctx, sect, "accept_more_specifics") != NULL && strcmp(uci_lookup_option_string(ctx, sect, "accept_more_specifics"), "on") == 0){ uci_more_specifics = TRUE; }else{ uci_more_specifics = FALSE; } if (uci_lookup_option_string(ctx, sect, "proxy_reply") != NULL && strcmp(uci_lookup_option_string(ctx, sect, "proxy_reply"), "on") == 0){ uci_proxy_reply = TRUE; }else{ uci_proxy_reply = FALSE; } if (uci_lookup_option_string(ctx, sect, "merge") != NULL && strcmp(uci_lookup_option_string(ctx, sect, "merge"), "on") == 0){ uci_merge = TRUE; }else{ uci_merge = FALSE; } if (uci_lookup_option_string(ctx, sect, "iid") == NULL){ uci_iid = 0; }else{ uci_iid = strtol(uci_lookup_option_string(ctx, sect, "iid"),NULL,10); } site = build_lisp_site_prefix(ms, uci_eid_prefix, uci_iid, uci_key_type, uci_key, uci_more_specifics, uci_proxy_reply, uci_merge, lcaf_ht); if (site) { OOR_LOG(LDBG_1, "Adding lisp site prefix %s to the lisp-sites " "database", lisp_addr_to_char(site->eid_prefix)); ms_add_lisp_site_prefix(ms, site); }else{ OOR_LOG(LERR, "Can't add lisp-site prefix %s. Discarded ...", uci_eid_prefix); } } /* LISP REGISTERED SITES CONFIG */ if (strcmp(sect->type, "ms-static-registered-site") == 0){ mapping = parse_mapping(ctx,sect,&(ms->super),rloc_set_ht,lcaf_ht,no_addr_loct_list,FALSE); if (mapping == NULL){ OOR_LOG(LERR, "Can't create static register site for %s", uci_lookup_option_string(ctx, sect, "eid_prefix")); return (BAD); } if (mdb_lookup_entry_exact(ms->reg_sites_db, mapping_eid(mapping)) == NULL){ if (ms_add_registered_site_prefix(ms, mapping) == GOOD){ OOR_LOG(LDBG_1, "Added static registered site for %s to the registered sites list!", lisp_addr_to_char(mapping_eid(mapping))); }else{ OOR_LOG(LERR, "Failed to add static registered site for %s to the registered sites list!", lisp_addr_to_char(mapping_eid(mapping))); mapping_del(mapping); } }else{ OOR_LOG(LERR, "Configuration file: Duplicated static registered site for %s. Discarded ...", uci_lookup_option_string(ctx, sect, "eid_prefix")); mapping_del(mapping); continue; } continue; } } /* destroy the hash table */ shash_destroy(lcaf_ht); shash_destroy(rlocs_ht); shash_destroy(rloc_set_ht); glist_destroy(no_addr_loct_list); return(GOOD); } static mapping_t* parse_mapping(struct uci_context *ctx, struct uci_section *sect, oor_ctrl_dev_t *dev, shash_t *rloc_set_ht, shash_t *lcaf_ht, glist_t *no_addr_loct_l, uint8_t is_local) { mapping_t *map; locator_t *loct; locator_t *aux_loct; glist_t *addr_list; lisp_addr_t *eid_prefix, *ip_eid_prefix; char *uci_eid; char *uci_rloc_set; int uci_iid,iidmlen; glist_t *rloc_list; glist_entry_t *it; lisp_xtr_t *xtr = NULL; switch (dev->mode){ case xTR_MODE: case MN_MODE: xtr = CONTAINER_OF(ctrl_dev, lisp_xtr_t, super); break; default: break; } uci_eid = (char *)uci_lookup_option_string(ctx, sect, "eid_prefix"); uci_rloc_set = (char *)uci_lookup_option_string(ctx, sect, "rloc_set"); if (uci_eid == NULL || uci_rloc_set == NULL){ return (NULL); } /* Check if the rloc-set exists */ rloc_list = (glist_t *)shash_lookup(rloc_set_ht,uci_rloc_set); if (rloc_list == NULL){ OOR_LOG(LWRN,"Configuration file: The rloc set %s doesn't exist", uci_rloc_set); return (NULL); } /* Get EID prefix */ addr_list = parse_lisp_addr(uci_eid, lcaf_ht); if (addr_list == NULL || glist_size(addr_list) != 1){ return (NULL); } ip_eid_prefix = (lisp_addr_t *)glist_first_data(addr_list); pref_conv_to_netw_pref(ip_eid_prefix); if (uci_lookup_option_string(ctx, sect, "iid") == NULL){ uci_iid = 0; }else{ uci_iid = strtol(uci_lookup_option_string(ctx, sect, "iid"),NULL,10); } if (uci_iid > MAX_IID || uci_iid < 0) { OOR_LOG(LERR, "Configuration file: Instance ID %d out of range [0..%d], " "disabling...",uci_iid, MAX_IID); uci_iid = 0; } if (uci_iid > 0){ iidmlen = (lisp_addr_ip_afi(ip_eid_prefix) == AF_INET) ? 32: 128; eid_prefix = lisp_addr_new_init_iid(uci_iid, ip_eid_prefix, iidmlen); }else{ eid_prefix = lisp_addr_clone(ip_eid_prefix); } /* Create mapping */ if ( is_local){ map = mapping_new_init(eid_prefix); if (map != NULL){ mapping_set_ttl(map, DEFAULT_DATA_CACHE_TTL); mapping_set_auth(map, 1); } }else{ map = mapping_new_init(eid_prefix); } /* no need for the prefix */ lisp_addr_del(eid_prefix); glist_destroy(addr_list); if (map == NULL){ return (NULL); } /* Add the locators of the rloc-set to the mapping */ glist_for_each_entry(it,rloc_list){ aux_loct = (locator_t*)glist_entry_data(it); loct = clone_customize_locator(dev,aux_loct,no_addr_loct_l,is_local); if (loct == NULL){ continue; } if (mapping_add_locator(map, loct) != GOOD){ if (xtr != NULL && is_local){ iface_locators_unattach_locator(xtr->iface_locators_table,loct); } locator_del(loct); continue; } } return(map); } static shash_t * parse_rlocs(struct uci_context *ctx, struct uci_package *pck, shash_t *lcaf_ht, glist_t *no_addr_loct_l) { struct uci_section *section; struct uci_element *element; shash_t *rlocs_ht; locator_t *locator; glist_t *addr_list; lisp_addr_t *address; iface_t *iface; char *uci_rloc_name; char *uci_address; char *uci_iface_name; int uci_afi; int uci_priority; int uci_weight; int afi; no_addr_loct *nloct; /* create lcaf hash table */ rlocs_ht = shash_new_managed((free_value_fn_t)locator_del); uci_foreach_element(&pck->sections, element) { section = uci_to_section(element); if (strcmp(section->type, "rloc-address") == 0){ uci_rloc_name = (char *)uci_lookup_option_string(ctx, section, "name"); if (uci_rloc_name == NULL){ OOR_LOG(LERR,"Configuration file: An rloc-address should have a name"); goto error; } uci_address = (char *)uci_lookup_option_string(ctx, section, "address"); if (uci_address == NULL){ OOR_LOG(LERR,"Configuration file: No address assigned to the rloc \"%s\"",uci_rloc_name); goto error; } if (uci_lookup_option_string(ctx, section, "priority") == NULL){ OOR_LOG(LERR,"Configuration file: No priority assigned to the rloc \"%s\"",uci_rloc_name); goto error; } uci_priority = strtol(uci_lookup_option_string(ctx, section, "priority"),NULL,10); if (uci_lookup_option_string(ctx, section, "weight") == NULL){ OOR_LOG(LERR,"Configuration file: No weight assigned to the rloc \"%s\"",uci_rloc_name); goto error; } uci_weight = strtol(uci_lookup_option_string(ctx, section, "weight"),NULL,10); if (validate_priority_weight(uci_priority, uci_weight) != GOOD) { goto error; } if (shash_lookup(rlocs_ht,uci_rloc_name) != NULL){ OOR_LOG(LDBG_1,"Configuration file: The RLOC %s is duplicated.", uci_rloc_name); goto error; } addr_list = parse_lisp_addr(uci_address, lcaf_ht); if (addr_list == NULL || glist_size(addr_list) == 0){ continue; } if (glist_size(addr_list) > 1){ OOR_LOG(LDBG_1,"Configuration file: With OpenWrt, RLOCs configured with FQDN address " "only use the first IP of the DNS resolution."); } address = (lisp_addr_t *)glist_first_data(addr_list); if (lisp_addr_lafi(address) == LM_AFI_IPPREF){ OOR_LOG(LERR, "Configuration file: RLOC address can not be a prefix: %s ", lisp_addr_to_char(address)); goto error; } /* Create a basic locator. Locaor or remote information will be added later according * who is using the locator*/ locator = locator_new_init(address,UP,1,1,uci_priority,uci_weight,255,0); if (locator != NULL){ shash_insert(rlocs_ht, strdup(uci_rloc_name), locator); } lisp_addr_del(address); } if (strcmp(section->type, "rloc-iface") == 0){ uci_rloc_name = (char *)uci_lookup_option_string(ctx, section, "name"); if (uci_rloc_name == NULL){ OOR_LOG(LERR,"Configuration file: An rloc-iface should have a name"); goto error; } uci_iface_name = (char *)uci_lookup_option_string(ctx, section, "interface"); if (uci_iface_name == NULL){ OOR_LOG(LERR,"Configuration file: An rloc-iface should have an interface selected"); goto error; } if (uci_lookup_option_string(ctx, section, "ip_version") == NULL){ OOR_LOG(LERR,"Configuration file: No afi assigned to the rloc \"%s\"",uci_rloc_name); goto error; } uci_afi = strtol(uci_lookup_option_string(ctx, section, "ip_version"),NULL,10); if (uci_lookup_option_string(ctx, section, "priority") == NULL){ OOR_LOG(LERR,"Configuration file: No priority assigned to the rloc \"%s\"",uci_rloc_name); goto error; } uci_priority = strtol(uci_lookup_option_string(ctx, section, "priority"),NULL,10); if (uci_lookup_option_string(ctx, section, "weight") == NULL){ OOR_LOG(LERR,"Configuration file: No weight assigned to the rloc \"%s\"",uci_rloc_name); goto error; } uci_weight = strtol(uci_lookup_option_string(ctx, section, "weight"),NULL,10); if (validate_priority_weight(uci_priority, uci_weight) != GOOD) { goto error; } if (uci_afi != 4 && uci_afi !=6){ OOR_LOG(LERR, "Configuration file: The afi of the locator should be \"4\" (IPv4)" " or \"6\" (IPv6)"); goto error; } if (shash_lookup(rlocs_ht,uci_rloc_name) != NULL){ OOR_LOG(LDBG_1,"Configuration file: The RLOC %s is duplicated.", uci_rloc_name); goto error; } /* Find the interface */ if (!(iface = get_interface(uci_iface_name))) { if (!(iface = add_interface(uci_iface_name))) { goto error; } } if (uci_afi == 4){ iface_configure (iface, AF_INET); address = iface->ipv4_address; afi = AF_INET; }else{ iface_configure (iface, AF_INET6); address = iface->ipv6_address; afi = AF_INET6; } /* Create a basic locator. Locaor or remote information will be added later according * who is using the locator*/ locator = locator_new_init(address,UP,1,1,uci_priority,uci_weight,255,0); if (locator != NULL){ shash_insert(rlocs_ht, strdup(uci_rloc_name), locator); } /* If iface is not initialized, modify addres of the aux locator indicating the IP afi. * This information will be used during the process of association of the cloned locator * with the iface */ if (lisp_addr_is_no_addr(address)){ nloct = no_addr_loct_new_init(locator, uci_iface_name, afi); glist_add(nloct,no_addr_loct_l); } } } return (rlocs_ht); error: shash_destroy(rlocs_ht); return (NULL); } static shash_t * parse_rloc_sets(struct uci_context *ctx, struct uci_package *pck, shash_t *rlocs_ht, shash_t *lcaf_ht) { struct uci_section *section; struct uci_element *element; struct uci_element *element_loct; struct uci_option *opt; char *uci_rloc_set_name; shash_t *rloc_sets_ht; glist_t *rloc_list; locator_t *loct; /* create lcaf hash table */ rloc_sets_ht = shash_new_managed((free_value_fn_t)glist_destroy); uci_foreach_element(&pck->sections, element) { section = uci_to_section(element); if (strcmp(section->type, "rloc-set") == 0){ uci_rloc_set_name = (char *)uci_lookup_option_string(ctx, section, "name"); if (uci_rloc_set_name == NULL){ OOR_LOG(LERR,"Configuration file: An rloc-set should have a name"); goto error; } rloc_list = (glist_t*)shash_lookup(rloc_sets_ht,uci_rloc_set_name); if (rloc_list == NULL){ rloc_list = glist_new(); if (rloc_list != NULL){ shash_insert(rloc_sets_ht, strdup(uci_rloc_set_name), rloc_list); }else{ OOR_LOG(LWRN, "parse_rloc_sets: Error creating rloc list"); continue; } }else{ OOR_LOG(LERR, "Configuration file: The RLOC set %s is duplicated.", uci_rloc_set_name); goto error; } opt = uci_lookup_option(ctx, section, "rloc_name"); if (opt != NULL){ uci_foreach_element(&(opt->v.list), element_loct){ loct = shash_lookup(rlocs_ht, element_loct->name); if (loct == NULL){ OOR_LOG(LWRN,"Configuration file: The RLOC name %s of the RLOC set %s doesn't exist", element_loct->name, uci_rloc_set_name); goto error; } if (glist_add_tail(loct,rloc_list)!=GOOD){ OOR_LOG(LDBG_1,"parse_rloc_sets: Error adding locator to the rloc-set"); } } }else{ OOR_LOG(LWRN, "Configuration file: The RLOC set %s has no rlocs " "associated.",uci_rloc_set_name); goto error; } } } return (rloc_sets_ht); error: shash_destroy(rloc_sets_ht); return (NULL); } static shash_t * parse_lcafs(struct uci_context *ctx, struct uci_package *pck) { struct uci_section *section; struct uci_element *element; shash_t *lcaf_ht; /* create lcaf hash table */ lcaf_ht = shash_new_managed((free_value_fn_t)lisp_addr_del); uci_foreach_element(&pck->sections, element) { section = uci_to_section(element); if (strcmp(section->type, "elp-node") == 0){ if (parse_elp_node(ctx,section,lcaf_ht)!=GOOD){ shash_destroy(lcaf_ht); return (NULL); } } } //parse_rle_list(cfg, lcaf_ht); //parse_mcinfo_list(cfg, lcaf_ht); return(lcaf_ht); } static int parse_elp_node(struct uci_context *ctx, struct uci_section *section, shash_t *ht) { char *uci_elp_name; char *uci_address; lisp_addr_t *laddr; elp_node_t *elp_node; uci_elp_name = (char *)uci_lookup_option_string(ctx, section, "elp_name"); if (uci_elp_name == NULL){ OOR_LOG(LERR,"Configuration file: An ELP should have a name"); return (BAD); } laddr = (lisp_addr_t *)shash_lookup(ht, uci_elp_name); if (laddr == NULL){ laddr = lisp_addr_elp_new(); if (laddr == NULL){ OOR_LOG(LWRN,"parse_elp_node: Couldn't create ELP address"); return (BAD); } shash_insert(ht, strdup(uci_elp_name), laddr); OOR_LOG(LDBG_3,"parse_elp_node: Added ELP %s to the hash table of LCAF addresses",uci_elp_name); }else { if (lisp_addr_is_elp(laddr) == FALSE){ OOR_LOG(LWRN,"Configuration file: Address %s composed of LCAF addresses of different type", uci_elp_name); return (BAD); } } elp_node = xzalloc(sizeof(elp_node_t)); elp_node->addr = lisp_addr_new(); uci_address = (char *)uci_lookup_option_string(ctx, section, "address"); if (uci_address == NULL){ OOR_LOG(LERR,"Configuration file: An ELP node should have an address assigned"); return (BAD); } if (lisp_addr_ip_from_char(uci_address, elp_node->addr) != GOOD) { elp_node_del(elp_node); OOR_LOG(LERR, "Configuration file: Couldn't parse ELP node %s", uci_address); return (BAD); } if (strcmp(uci_lookup_option_string(ctx, section, "strict"), "on") == 0){ elp_node->S = TRUE; }else{ elp_node->S = FALSE; } if (strcmp(uci_lookup_option_string(ctx, section, "probe"), "on") == 0){ elp_node->P = TRUE; }else{ elp_node->P = FALSE; } if (strcmp(uci_lookup_option_string(ctx, section, "lookup"), "on") == 0){ elp_node->L = TRUE; }else{ elp_node->L = FALSE; } elp_add_node(lcaf_elp_get_elp(lisp_addr_get_lcaf(laddr)),elp_node); OOR_LOG(LDBG_3,"parse_elp_node: Added %s to the ELP %s",uci_address,uci_elp_name); return (GOOD); } oor-1.2.0/oor/config/oor_config_uci.h000066400000000000000000000014511313612200500175040ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef OOR_CONFIG_UCI_H_ #define OOR_CONFIG_UCI_H_ int handle_config_file(); #endif /* OOR_CONFIG_UCI_H_ */ oor-1.2.0/oor/control/000077500000000000000000000000001313612200500145615ustar00rootroot00000000000000oor-1.2.0/oor/control/control-data-plane/000077500000000000000000000000001313612200500202455ustar00rootroot00000000000000oor-1.2.0/oor/control/control-data-plane/control-data-plane.c000066400000000000000000000016121313612200500240750ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "control-data-plane.h" control_dplane_struct_t * control_dp_select() { #ifdef VPNAPI return &control_dp_vpnapi; #elif VPP return &control_dp_vpp; #else return &control_dp_tun; #endif } oor-1.2.0/oor/control/control-data-plane/control-data-plane.h000066400000000000000000000040661313612200500241100ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef CONTROL_DATA_PLANE_H_ #define CONTROL_DATA_PLANE_H_ #include "../../liblisp/liblisp.h" typedef struct iface iface_t; typedef struct uconn uconn_t; typedef struct sock sock_t; /* functions to manipulate routing */ typedef struct control_dplane_struct { int (*control_dp_init)(oor_ctrl_t *ctrl, ...); void (*control_dp_uninit)(oor_ctrl_t *ctrl); int (*control_dp_add_iface_addr)(oor_ctrl_t *ctrl, iface_t *iface, int afi); int (*control_dp_add_iface_gw)(oor_ctrl_t *ctrl, iface_t *iface, int afi); int (*control_dp_recv_msg)(sock_t *sl); int (*control_dp_send_msg)(oor_ctrl_t *ctrl, lbuf_t *buf, uconn_t *udp_conn); lisp_addr_t *(*control_dp_get_default_addr)(oor_ctrl_t *ctrl, int afi); int (*control_dp_updated_route)(oor_ctrl_t *ctrl, int command, iface_t *iface, lisp_addr_t *src_pref, lisp_addr_t *dst_pref, lisp_addr_t *gw); int (*control_dp_updated_addr)(oor_ctrl_t *ctrl, iface_t *iface,lisp_addr_t *old_addr,lisp_addr_t *new_addr); int (*control_dp_update_link)(oor_ctrl_t *ctrl, iface_t *iface, int old_iface_index, int new_iface_index, int status); void *control_dp_data; } control_dplane_struct_t; control_dplane_struct_t * control_dp_select(); extern control_dplane_struct_t control_dp_tun; extern control_dplane_struct_t control_dp_vpnapi; extern control_dplane_struct_t control_dp_vpp; #endif /* CONTROL_DATA_PLANE_H_ */ oor-1.2.0/oor/control/control-data-plane/tun/000077500000000000000000000000001313612200500210535ustar00rootroot00000000000000oor-1.2.0/oor/control/control-data-plane/tun/cdp_tun.c000066400000000000000000000334251313612200500226620ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "cdp_tun.h" #include "../control-data-plane.h" #include "../../oor_control.h" #include "../../oor_ctrl_device.h" #include "../../../iface_list.h" #include "../../../lib/oor_log.h" /***************************** FUNCTIONS DECLARATION *************************/ int tun_control_dp_init(oor_ctrl_t *ctrl, ...); void tun_control_dp_uninit (oor_ctrl_t *ctrl); int tun_control_dp_add_iface_addr(oor_ctrl_t *ctrl,iface_t *iface, int afi); int tun_control_dp_recv_msg(sock_t *sl); int tun_control_dp_send_msg(oor_ctrl_t *ctrl, lbuf_t *buff, uconn_t *udp_conn); lisp_addr_t * tun_control_dp_get_default_addr(oor_ctrl_t *ctrl, int afi); int tun_control_dp_add_iface_gw(oor_ctrl_t *ctrl,iface_t *iface, int afi); int tun_control_dp_updated_route(oor_ctrl_t *ctrl, int command, iface_t *iface, lisp_addr_t *src_pref, lisp_addr_t *dst_pref, lisp_addr_t *gw); int tun_control_dp_updated_addr(oor_ctrl_t *ctrl, iface_t *iface,lisp_addr_t *old_addr, lisp_addr_t *new_addr); int tun_control_dp_update_link(oor_ctrl_t *ctrl, iface_t *iface, int old_iface_index, int new_iface_index, int status); void tun_control_dp_set_default_ctrl_ifaces(tun_ctr_dplane_data_t * data); iface_t * tun_control_dp_get_default_ctrl_iface(tun_ctr_dplane_data_t * data, int afi); lisp_addr_t * tun_control_dp_get_default_ctrl_address(tun_ctr_dplane_data_t * data, int afi); int tun_control_dp_get_default_ctrl_socket(tun_ctr_dplane_data_t * data,int afi); int tun_control_dp_get_output_ctrl_sock(tun_ctr_dplane_data_t * data, uconn_t *udp_conn); control_dplane_struct_t control_dp_tun = { .control_dp_init = tun_control_dp_init, .control_dp_uninit = tun_control_dp_uninit, .control_dp_add_iface_addr = tun_control_dp_add_iface_addr, .control_dp_add_iface_gw = tun_control_dp_add_iface_gw, .control_dp_recv_msg = tun_control_dp_recv_msg, .control_dp_send_msg = tun_control_dp_send_msg, .control_dp_get_default_addr = tun_control_dp_get_default_addr, .control_dp_updated_route = tun_control_dp_updated_route, .control_dp_updated_addr = tun_control_dp_updated_addr, .control_dp_update_link = tun_control_dp_update_link, .control_dp_data = NULL }; /********************************** FUNCTIONS ********************************/ int tun_control_dp_init(oor_ctrl_t *ctrl, ...) { int socket; tun_ctr_dplane_data_t * data; /* Generate receive sockets for control port (4342)*/ if (default_rloc_afi != AF_INET6) { socket = open_control_input_socket(AF_INET); sockmstr_register_read_listener(smaster, tun_control_dp_recv_msg, ctrl,socket); } if (default_rloc_afi != AF_INET) { socket = open_control_input_socket(AF_INET6); sockmstr_register_read_listener(smaster, tun_control_dp_recv_msg, ctrl,socket); } data = (tun_ctr_dplane_data_t *)xmalloc(sizeof(tun_ctr_dplane_data_t)); ctrl->control_data_plane->control_dp_data = (void *)data; tun_control_dp_set_default_ctrl_ifaces(data); return (GOOD); } void tun_control_dp_uninit (oor_ctrl_t *ctrl) { tun_ctr_dplane_data_t * data; data = (tun_ctr_dplane_data_t *)ctrl->control_data_plane->control_dp_data; free(data); } int tun_control_dp_add_iface_addr(oor_ctrl_t *ctrl,iface_t *iface, int afi) { tun_ctr_dplane_data_t * cdp_data = control_dp_tun.control_dp_data; switch (afi){ case AF_INET: if (cdp_data && !cdp_data->default_ctrl_iface_v4){ // It will only enter here when adding interfaces after init process tun_control_dp_set_default_ctrl_ifaces(cdp_data); } break; case AF_INET6: if (cdp_data && !cdp_data->default_ctrl_iface_v6){ // It will only enter here when adding interfaces after init process tun_control_dp_set_default_ctrl_ifaces(cdp_data); } break; default: break; } return (GOOD); } int tun_control_dp_add_iface_gw(oor_ctrl_t *ctrl,iface_t *iface, int afi){ return (GOOD); } /* Process a LISP protocol message sitting on * socket s with address family afi */ int tun_control_dp_recv_msg(sock_t *sl) { uconn_t uc; lbuf_t *b; oor_ctrl_t *ctrl; oor_ctrl_dev_t *dev; ctrl = sl->arg; /* Only one device supported for now */ dev = glist_first_data(ctrl->devices); uc.lp = LISP_CONTROL_PORT; b = lisp_msg_create_buf(); if (sock_ctrl_recv(sl->fd, b, &uc) != GOOD) { OOR_LOG(LDBG_1, "Couldn't retrieve socket information" "for control message! Discarding packet!"); lbuf_del(b); return (BAD); } if (lbuf_size(b) < 4){ OOR_LOG(LDBG_3, "Received a non LISP message in the " "control port! Discarding packet!"); return (BAD); } lbuf_reset_lisp(b); OOR_LOG(LDBG_1, "Received %s, IP: %s -> %s, UDP: %d -> %d", lisp_msg_hdr_to_char(b), lisp_addr_to_char(&uc.ra), lisp_addr_to_char(&uc.la), uc.rp, uc.lp); /* direct call of ctrl device * TODO: check type to decide where to send msg*/ ctrl_dev_recv(dev, b, &uc); lbuf_del(b); return (GOOD); } int tun_control_dp_send_msg(oor_ctrl_t *ctrl, lbuf_t *buff, uconn_t *udp_conn) { int ret, sock, dst_afi; ip_addr_t *src_addr, *dst_addr; lisp_addr_t *ctrl_addr; if (lisp_addr_lafi(&udp_conn->ra) != LM_AFI_IP) { OOR_LOG(LDBG_2, "tun_control_dp_send_msg: Destination address %s of UDP connection is not a IP. " "Discarding!", lisp_addr_to_char(&udp_conn->ra)); return(BAD); } if (lisp_addr_lafi(&udp_conn->la) != LM_AFI_IP) { dst_afi = lisp_addr_ip_afi(&udp_conn->ra); ctrl_addr = tun_control_dp_get_default_ctrl_address(control_dp_tun.control_dp_data, dst_afi); if (!ctrl_addr) { OOR_LOG(LERR, "tun_control_dp_send_msg: No %s control address found, send aborted!", (dst_afi == AF_INET) ? "IPv4" : "IPv6"); return(ERR_SOCKET); } /* Use as local address the default control address */ lisp_addr_copy(&udp_conn->la, ctrl_addr); } sock = tun_control_dp_get_output_ctrl_sock( (tun_ctr_dplane_data_t *)ctrl->control_data_plane->control_dp_data, udp_conn); if (sock == ERR_SOCKET){ return (BAD); } src_addr = lisp_addr_ip(&udp_conn->la); dst_addr = lisp_addr_ip(&udp_conn->ra); if (ip_addr_afi(src_addr) != ip_addr_afi(dst_addr)) { OOR_LOG(LDBG_2, "tun_control_dp_send_msg: src %s and dst %s of UDP connection have " "different IP AFI. Discarding!", ip_addr_to_char(src_addr), ip_addr_to_char(dst_addr)); return(BAD); } pkt_push_udp_and_ip(buff, udp_conn->lp, udp_conn->rp, src_addr, dst_addr); ret = send_raw_packet(sock, lbuf_data(buff), lbuf_size(buff), dst_addr); if (ret != GOOD) { OOR_LOG(LDBG_1, "Failed to send contrl message from RLOC: %s -> %s", lisp_addr_to_char(&udp_conn->la), lisp_addr_to_char(&udp_conn->ra)); return(BAD); } else { OOR_LOG(LDBG_1, "Sent control message IP: %s -> %s UDP: %d -> %d", lisp_addr_to_char(&udp_conn->la), lisp_addr_to_char(&udp_conn->ra), udp_conn->lp, udp_conn->rp); return(GOOD); } } lisp_addr_t * tun_control_dp_get_default_addr(oor_ctrl_t *ctrl, int afi) { tun_ctr_dplane_data_t * data; data = (tun_ctr_dplane_data_t *)ctrl->control_data_plane->control_dp_data; return (tun_control_dp_get_default_ctrl_address(data,afi)); } int tun_control_dp_updated_route(oor_ctrl_t *ctrl, int command, iface_t *iface, lisp_addr_t *src_pref, lisp_addr_t *dst_pref, lisp_addr_t *gw) { return (GOOD); } int tun_control_dp_updated_addr(oor_ctrl_t *ctrl, iface_t *iface,lisp_addr_t *old_addr, lisp_addr_t *new_addr) { int addr_afi; tun_ctr_dplane_data_t * data; data = (tun_ctr_dplane_data_t *)ctrl->control_data_plane->control_dp_data; /* If no default control, recalculate it */ if (iface->status == UP && !lisp_addr_is_no_addr(new_addr)) { addr_afi = lisp_addr_ip_afi(new_addr); if ((data->default_ctrl_iface_v4 == NULL && addr_afi == AF_INET) || (data->default_ctrl_iface_v6 == NULL && addr_afi == AF_INET6)) { OOR_LOG(LDBG_2, "No default control interface. Recalculate new " "control interface"); tun_control_dp_set_default_ctrl_ifaces(data); } } return (GOOD); } int tun_control_dp_update_link(oor_ctrl_t *ctrl, iface_t *iface, int old_iface_index, int new_iface_index, int status) { tun_ctr_dplane_data_t * data; data = (tun_ctr_dplane_data_t *)ctrl->control_data_plane->control_dp_data; /* If the affected interface is the default control or output iface, * recalculate it */ if (data->default_ctrl_iface_v4 == iface || data->default_ctrl_iface_v6 == iface || data->default_ctrl_iface_v4 == NULL || data->default_ctrl_iface_v6 == NULL){ OOR_LOG(LDBG_2,"Default control interface down. Recalculate new control" " interface"); tun_control_dp_set_default_ctrl_ifaces(data); } return (GOOD); } void tun_control_dp_set_default_ctrl_ifaces(tun_ctr_dplane_data_t * data) { data->default_ctrl_iface_v4 = get_any_output_iface(AF_INET); if (data->default_ctrl_iface_v4 != NULL) { OOR_LOG(LDBG_2,"Default IPv4 control iface %s: %s\n", data->default_ctrl_iface_v4->iface_name, lisp_addr_to_char(data->default_ctrl_iface_v4->ipv4_address)); } data->default_ctrl_iface_v6 = get_any_output_iface(AF_INET6); if (data->default_ctrl_iface_v6 != NULL) { OOR_LOG(LDBG_2,"Default IPv6 control iface %s: %s\n", data->default_ctrl_iface_v6->iface_name, lisp_addr_to_char(data->default_ctrl_iface_v6->ipv6_address)); } if (!data->default_ctrl_iface_v4 && !data->default_ctrl_iface_v6) { OOR_LOG(LERR, "NO CONTROL IFACE: all the locators are down"); } } iface_t * tun_control_dp_get_default_ctrl_iface(tun_ctr_dplane_data_t * data, int afi) { iface_t *iface = NULL; switch (afi){ case AF_INET: iface = data->default_ctrl_iface_v4; break; case AF_INET6: iface = data->default_ctrl_iface_v6; break; default: //arnatal TODO: syslog iface = NULL; break; } return (iface); } inline lisp_addr_t * tun_control_dp_get_default_ctrl_address(tun_ctr_dplane_data_t * data, int afi) { lisp_addr_t *address = NULL; switch (afi){ case AF_INET: if (data->default_ctrl_iface_v4 != NULL){ address = data->default_ctrl_iface_v4->ipv4_address; } break; case AF_INET6: if (data->default_ctrl_iface_v6 != NULL){ address = data->default_ctrl_iface_v6->ipv6_address; } break; default: OOR_LOG(LDBG_2,"tun_control_dp_get_default_ctrl_address: Unsupported afi: %d",afi); break; } return (address); } int tun_control_dp_get_default_ctrl_socket(tun_ctr_dplane_data_t * data, int afi) { int socket = ERR_SOCKET; switch (afi){ case AF_INET: if (data->default_ctrl_iface_v4 != NULL){ socket = data->default_ctrl_iface_v4->out_socket_v4; } break; case AF_INET6: if (data->default_ctrl_iface_v6 != NULL){ socket = data->default_ctrl_iface_v6->out_socket_v6; } break; default: socket = ERR_SRC_ADDR; break; } return (socket); } int tun_control_dp_get_output_ctrl_sock(tun_ctr_dplane_data_t * data, uconn_t *udp_conn) { int sock, dst_afi; lisp_addr_t *ctrl_addr; iface_t *iface; dst_afi = lisp_addr_ip_afi(&udp_conn->ra); /* If no local address specified, use the default one */ if (lisp_addr_is_no_addr(&udp_conn->la)) { ctrl_addr = tun_control_dp_get_default_ctrl_address(data, dst_afi); if (!ctrl_addr) { OOR_LOG(LERR, "tun_control_dp_get_output_ctrl_sock: No %s control address found, send aborted!", (dst_afi == AF_INET) ? "IPv4" : "IPv6"); return(ERR_SOCKET); } /* Use as local address the default control address */ lisp_addr_copy(&udp_conn->la, ctrl_addr); } iface = get_interface_with_address(&udp_conn->la); if (iface != NULL) { sock = iface_socket(iface, dst_afi); } else { OOR_LOG(LDBG_2, "tun_control_dp_get_output_ctrl_sock: No interface found with local address %s. Using default one!", lisp_addr_to_char(&udp_conn->la)); ctrl_addr = tun_control_dp_get_default_ctrl_address(data, dst_afi); if (!ctrl_addr) { OOR_LOG(LERR, "tun_control_dp_get_output_ctrl_sock: No control address found, send aborted!"); return(ERR_SOCKET); } /* Use as local address the default control address */ lisp_addr_copy(&udp_conn->la, ctrl_addr); sock = tun_control_dp_get_default_ctrl_socket(data,dst_afi); } if (sock < 0) { OOR_LOG(LERR, "No output socket found, send aborted!"); return(ERR_SOCKET); } return (sock); } oor-1.2.0/oor/control/control-data-plane/tun/cdp_tun.h000066400000000000000000000016421313612200500226630ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef CDP_TUN_H_ #define CDP_TUN_H_ #include "../../../iface_list.h" typedef struct tun_ctr_dplane_data_{ iface_t *default_ctrl_iface_v4; iface_t *default_ctrl_iface_v6; }tun_ctr_dplane_data_t; #endif /* CDP_TUN_H_ */ oor-1.2.0/oor/control/control-data-plane/vpnapi/000077500000000000000000000000001313612200500215425ustar00rootroot00000000000000oor-1.2.0/oor/control/control-data-plane/vpnapi/cdp_vpnapi.c000066400000000000000000000273351313612200500240430ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "cdp_vpnapi.h" #include "../control-data-plane.h" #include "../../oor_control.h" #include "../../oor_ctrl_device.h" #include "../../../iface_list.h" #include "../../../oor_jni.h" #include "../../../lib/oor_log.h" /***************************** FUNCTIONS DECLARATION *************************/ int vpnapi_control_dp_init(oor_ctrl_t *ctrl,...); void vpnapi_control_dp_uninit (oor_ctrl_t *ctrl); int vpnapi_control_dp_add_iface_addr(oor_ctrl_t *ctrl,iface_t *iface, int afi); int vpnapi_control_dp_add_iface_gw(oor_ctrl_t *ctrl,iface_t *iface, int afi); int vpnapi_control_dp_recv_msg(sock_t *sl); int vpnapi_control_dp_send_msg(oor_ctrl_t *ctrl, lbuf_t *buff, uconn_t *udp_conn); lisp_addr_t * vpnapi_control_dp_get_default_addr(oor_ctrl_t *ctrl, int afi); int vpnapi_control_dp_updated_route(oor_ctrl_t *ctrl, int command, iface_t *iface, lisp_addr_t *src_pref,lisp_addr_t *dst_pref, lisp_addr_t *gw); void vpnapi_control_dp_process_new_gateway(oor_ctrl_t *ctrl, iface_t *iface, lisp_addr_t *gateway); int vpnapi_control_dp_updated_addr(oor_ctrl_t *ctrl, iface_t *iface, lisp_addr_t *old_addr,lisp_addr_t *new_addr); int vpnapi_control_dp_update_link(oor_ctrl_t *ctrl, iface_t *iface, int old_iface_index, int new_iface_index, int status); int vpnapi_control_dp_reset_socket(vpnapi_ctr_dplane_data_t * data, int fd, int afi); control_dplane_struct_t control_dp_vpnapi = { .control_dp_init = vpnapi_control_dp_init, .control_dp_uninit = vpnapi_control_dp_uninit, .control_dp_add_iface_addr = vpnapi_control_dp_add_iface_addr, .control_dp_add_iface_gw = vpnapi_control_dp_add_iface_gw, .control_dp_recv_msg = vpnapi_control_dp_recv_msg, .control_dp_send_msg = vpnapi_control_dp_send_msg, .control_dp_get_default_addr = vpnapi_control_dp_get_default_addr, .control_dp_updated_route = vpnapi_control_dp_updated_route, .control_dp_updated_addr = vpnapi_control_dp_updated_addr, .control_dp_update_link = vpnapi_control_dp_update_link, .control_dp_data = NULL }; /********************************** FUNCTIONS ********************************/ int vpnapi_control_dp_init(oor_ctrl_t *ctrl, ...) { vpnapi_ctr_dplane_data_t *data; sock_t *sock; data = xmalloc(sizeof(vpnapi_ctr_dplane_data_t)); ctrl->control_data_plane->control_dp_data = (void *)data; /* Generate receive sockets for control port (4342)*/ if (default_rloc_afi != AF_INET6) { data->ipv4_ctrl_socket = open_control_input_socket(AF_INET); sockmstr_register_read_listener(smaster, vpnapi_control_dp_recv_msg, ctrl,data->ipv4_ctrl_socket); oor_jni_protect_socket(data->ipv4_ctrl_socket); sock = sockmstr_register_get_by_bind_port (smaster, AF_INET, LISP_DATA_PORT); if (sock != NULL){ data->ipv4_data_socket = sock_fd(sock); } }else { data->ipv4_ctrl_socket = ERR_SOCKET; } if (default_rloc_afi != AF_INET) { data->ipv6_ctrl_socket = open_control_input_socket(AF_INET6); sockmstr_register_read_listener(smaster, vpnapi_control_dp_recv_msg, ctrl,data->ipv6_ctrl_socket); oor_jni_protect_socket(data->ipv6_ctrl_socket); }else { data->ipv6_ctrl_socket = ERR_SOCKET; } return (GOOD); } void vpnapi_control_dp_uninit (oor_ctrl_t *ctrl) { vpnapi_ctr_dplane_data_t * data; data = (vpnapi_ctr_dplane_data_t *)ctrl->control_data_plane->control_dp_data; free(data); } int vpnapi_control_dp_add_iface_addr(oor_ctrl_t *ctrl,iface_t *iface, int afi) { return (GOOD); } int vpnapi_control_dp_add_iface_gw(oor_ctrl_t *ctrl,iface_t *iface, int afi) { return (GOOD); } /* Process a LISP protocol message sitting on * socket s with address family afi */ int vpnapi_control_dp_recv_msg(sock_t *sl) { uconn_t uc; lbuf_t *b; oor_ctrl_t *ctrl; oor_ctrl_dev_t *dev; ctrl = sl->arg; /* Only one device supported for now */ dev = glist_first_data(ctrl->devices); uc.lp = LISP_CONTROL_PORT; b = lisp_msg_create_buf(); if (sock_ctrl_recv(sl->fd, b, &uc) != GOOD) { OOR_LOG(LDBG_1, "Couldn't retrieve socket information" "for control message! Discarding packet!"); lbuf_del(b); return (BAD); } if (lbuf_size(b) < 4){ OOR_LOG(LDBG_3, "Received a non LISP message in the " "control port! Discarding packet!"); return (BAD); } lbuf_reset_lisp(b); OOR_LOG(LDBG_1, "Received %s, IP: %s -> %s, UDP: %d -> %d", lisp_msg_hdr_to_char(b), lisp_addr_to_char(&uc.ra), lisp_addr_to_char(&uc.la), uc.rp, uc.lp); /* direct call of ctrl device * TODO: check type to decide where to send msg*/ ctrl_dev_recv(dev, b, &uc); lbuf_del(b); return (GOOD); } int vpnapi_control_dp_send_msg(oor_ctrl_t *ctrl, lbuf_t *buff, uconn_t *udp_conn) { int ret; int sock; ip_addr_t *src_addr, *dst_addr; vpnapi_ctr_dplane_data_t * data; data = (vpnapi_ctr_dplane_data_t *)ctrl->control_data_plane->control_dp_data; if (lisp_addr_lafi(&udp_conn->ra) != LM_AFI_IP) { OOR_LOG(LDBG_2, "vpnapi_control_dp_send_msg: Destination address %s of UDP connection is not a IP. " "Discarding!", lisp_addr_to_char(&udp_conn->ra)); return(BAD); } src_addr = lisp_addr_ip(&udp_conn->la); dst_addr = lisp_addr_ip(&udp_conn->ra); if (!lisp_addr_is_no_addr(&udp_conn->la) && (ip_addr_afi(src_addr) != ip_addr_afi(dst_addr))) { OOR_LOG(LDBG_2, "vpnapi_control_dp_send_msg: src %s and dst %s of UDP connection have " "different IP AFI. Discarding!", ip_addr_to_char(src_addr), ip_addr_to_char(dst_addr)); return(BAD); } switch (ip_addr_afi(dst_addr)){ case AF_INET: if (udp_conn->lp == LISP_CONTROL_PORT){ sock = data->ipv4_ctrl_socket; }else{ sock = data->ipv4_data_socket; } break; case AF_INET6: sock = data->ipv6_ctrl_socket; break; default: return (BAD); } ret = send_datagram_packet (sock, lbuf_data(buff), lbuf_size(buff), &udp_conn->ra, udp_conn->rp); if (ret != GOOD) { OOR_LOG(LDBG_1, "Failed to send contrl message from RLOC: %s -> %s", lisp_addr_to_char(&udp_conn->la), lisp_addr_to_char(&udp_conn->ra)); return(BAD); } else { OOR_LOG(LDBG_1, "Sent control message IP: %s -> %s UDP: %d -> %d", lisp_addr_to_char(&udp_conn->la), lisp_addr_to_char(&udp_conn->ra), udp_conn->lp, udp_conn->rp); return(GOOD); } } lisp_addr_t * vpnapi_control_dp_get_default_addr(oor_ctrl_t *ctrl, int afi) { iface_t *iface; lisp_addr_t *addr = NULL; iface = get_any_output_iface(afi); if (iface != NULL){ addr = iface_address(iface, afi); } return (addr); } int vpnapi_control_dp_updated_route(oor_ctrl_t *ctrl, int command, iface_t *iface, lisp_addr_t *src_pref, lisp_addr_t *dst_pref, lisp_addr_t *gateway) { if (lisp_addr_ip_afi(gateway) != LM_AFI_NO_ADDR && lisp_addr_ip_afi(dst_pref) == LM_AFI_NO_ADDR) { /* Check if the addres is a global address*/ if (ip_addr_is_link_local(lisp_addr_ip(gateway)) == TRUE) { OOR_LOG(LDBG_3,"vpnapi_updated_route: the extractet address " "from the netlink messages is a local link address: %s " "discarded", lisp_addr_to_char(gateway)); return (GOOD); } vpnapi_control_dp_process_new_gateway(ctrl,iface,gateway); } return (GOOD); } void vpnapi_control_dp_process_new_gateway(oor_ctrl_t *ctrl, iface_t *iface, lisp_addr_t *gateway) { int afi; vpnapi_ctr_dplane_data_t * data; afi = lisp_addr_ip_afi(gateway); data = (vpnapi_ctr_dplane_data_t *)ctrl->control_data_plane->control_dp_data; /* Recreate sockets */ switch(afi){ case AF_INET: vpnapi_control_dp_reset_socket(data, data->ipv4_ctrl_socket,AF_INET); break; case AF_INET6: vpnapi_control_dp_reset_socket(data, data->ipv6_ctrl_socket,AF_INET6); break; default: return; } } int vpnapi_control_dp_updated_addr(oor_ctrl_t *ctrl, iface_t *iface, lisp_addr_t *old_addr,lisp_addr_t *new_addr) { int addr_afi; vpnapi_ctr_dplane_data_t * data; data = (vpnapi_ctr_dplane_data_t *)ctrl->control_data_plane->control_dp_data; if (lisp_addr_is_no_addr(new_addr)){ return(GOOD); } addr_afi = lisp_addr_ip_afi(new_addr); /* Check if the detected change of address is the same. */ if (lisp_addr_cmp(old_addr, new_addr) == 0) { OOR_LOG(LDBG_2, "vpnapi_control_dp_updated_addr: The change of address detected " "for interface %s doesn't affect", iface->iface_name); return (GOOD); }; switch (addr_afi){ case AF_INET: vpnapi_control_dp_reset_socket(data, data->ipv4_ctrl_socket, AF_INET); break; case AF_INET6: vpnapi_control_dp_reset_socket(data, data->ipv6_ctrl_socket, AF_INET6); break; default: return (BAD); } return (GOOD); } int vpnapi_control_dp_update_link(oor_ctrl_t *ctrl, iface_t *iface, int old_iface_index, int new_iface_index, int status) { vpnapi_ctr_dplane_data_t * data; data = (vpnapi_ctr_dplane_data_t *)ctrl->control_data_plane->control_dp_data; if (default_rloc_afi != AF_INET6){ vpnapi_control_dp_reset_socket(data, data->ipv4_ctrl_socket, AF_INET); } if (default_rloc_afi != AF_INET){ vpnapi_control_dp_reset_socket(data, data->ipv6_ctrl_socket, AF_INET6); } return (GOOD); } int vpnapi_control_dp_reset_socket(vpnapi_ctr_dplane_data_t * data, int fd, int afi) { sock_t *old_sock, *data_sock; int new_fd; old_sock = sockmstr_register_get_by_fd(smaster,fd); switch (afi){ case AF_INET: OOR_LOG(LDBG_2,"reset_socket: Reset IPv4 control socket\n"); new_fd = open_control_input_socket(AF_INET); if (new_fd == ERR_SOCKET){ OOR_LOG(LDBG_2,"vpnapi_reset_socket: Error recreating the socket"); return (BAD); } data->ipv4_ctrl_socket = new_fd; /* The data socket has probably changed too. Refresh it */ data_sock = sockmstr_register_get_by_bind_port (smaster, AF_INET, LISP_DATA_PORT); if (data_sock != NULL){ data->ipv4_data_socket = sock_fd(data_sock); } break; case AF_INET6: OOR_LOG(LDBG_2,"reset_socket: Reset IPv6 control socket\n"); new_fd = open_control_input_socket(AF_INET6); if (new_fd == ERR_SOCKET){ OOR_LOG(LDBG_2,"vpnapi_reset_socket: Error recreating the socket"); return (BAD); } data->ipv6_ctrl_socket = new_fd; break; default: return (BAD); } sockmstr_register_read_listener(smaster,old_sock->recv_cb,old_sock->arg,new_fd); sockmstr_unregister_read_listenedr(smaster,old_sock); /* Protect the socket from loops in the system*/ oor_jni_protect_socket(new_fd); return (GOOD); } oor-1.2.0/oor/control/control-data-plane/vpnapi/cdp_vpnapi.h000066400000000000000000000016651313612200500240460ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef CDP_VPNAPI_H_ #define CDP_VPNAPI_H_ typedef struct vpnapi_ctr_dplane_data_{ int ipv4_ctrl_socket; int ipv6_ctrl_socket; int ipv4_data_socket; /* To send Encap Map Register */ }vpnapi_ctr_dplane_data_t; #endif /* CDP_VPNAPI_H_ */ oor-1.2.0/oor/control/control-data-plane/vpp/000077500000000000000000000000001313612200500210525ustar00rootroot00000000000000oor-1.2.0/oor/control/control-data-plane/vpp/cdp_vpp.c000066400000000000000000000273521313612200500226620ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include #include #include #include #include #include "cdp_vpp.h" #include "../../../lib/vpp_api/vpp_api_requests.h" #include "../control-data-plane.h" #include "../../lib/interfaces_lib.h" #include "../../lib/oor_log.h" #include "../../oor_control.h" #include "../../oor_ctrl_device.h" int vpp_control_dp_init(oor_ctrl_t *ctrl,...); void vpp_control_dp_uninit (oor_ctrl_t *ctrl); int vpp_control_dp_add_iface_addr(oor_ctrl_t *ctrl,iface_t *iface, int afi); int vpp_control_dp_add_iface_gw(oor_ctrl_t *ctrl,iface_t *iface, int afi); int vpp_control_dp_recv_msg(sock_t *sl); int vpp_control_dp_send_msg(oor_ctrl_t *ctrl, lbuf_t *buff, uconn_t *udp_conn); lisp_addr_t * vpp_control_dp_get_default_addr(oor_ctrl_t *ctrl, int afi); inline lisp_addr_t * vpp_control_dp_get_default_ctrl_address(vpp_ctr_dplane_data_t * data, int afi); int vpp_control_dp_updated_route(oor_ctrl_t *ctrl, int command, iface_t *iface, lisp_addr_t *src_pref,lisp_addr_t *dst_pref, lisp_addr_t *gw); void vpp_control_dp_process_new_gateway(oor_ctrl_t *ctrl, iface_t *iface, lisp_addr_t *gateway); int vpp_control_dp_updated_addr(oor_ctrl_t *ctrl, iface_t *iface, lisp_addr_t *old_addr,lisp_addr_t *new_addr); int vpp_control_dp_update_link(oor_ctrl_t *ctrl, iface_t *iface, int old_iface_index, int new_iface_index, int status); void vpp_control_dp_set_default_ctrl_ifaces(vpp_ctr_dplane_data_t * data); /* Process a received control message */ int vpp_control_dp_recv_msg(sock_t *sl); control_dplane_struct_t control_dp_vpp = { .control_dp_init = vpp_control_dp_init, .control_dp_uninit = vpp_control_dp_uninit, .control_dp_add_iface_addr = vpp_control_dp_add_iface_addr, .control_dp_add_iface_gw = vpp_control_dp_add_iface_gw, .control_dp_recv_msg = vpp_control_dp_recv_msg, .control_dp_send_msg = vpp_control_dp_send_msg, .control_dp_get_default_addr = vpp_control_dp_get_default_addr, .control_dp_updated_route = vpp_control_dp_updated_route, .control_dp_updated_addr = vpp_control_dp_updated_addr, .control_dp_update_link = vpp_control_dp_update_link, .control_dp_data = NULL }; int tap_fd = 0; uint8_t mac[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; int vpp_control_dp_init(oor_ctrl_t *ctrl,...) { vpp_ctr_dplane_data_t *data; /* Configure data plane */ if ((tap_fd = create_tun_tap(TAP,TAP_CTRL_IFACE_NAME,TAP_MTU_CTRL_VPP)) == BAD){ return (BAD); } /* Enable oor control node in VPP */ if (vpp_oor_ctrl_enable_disable(TAP_CTRL_IFACE_NAME, TRUE)!= GOOD){ OOR_LOG(LERR,"VPP: Could not initiate oor ctrl plugin."); return (BAD); } OOR_LOG(LDBG_1,"VPP: Enabled OOR Ctrl plugin"); /* Register socket */ sockmstr_register_read_listener(smaster, vpp_control_dp_recv_msg, ctrl,tap_fd); data = (vpp_ctr_dplane_data_t *)xmalloc(sizeof(vpp_ctr_dplane_data_t)); if (!data){ return (BAD); } control_dp_vpp.control_dp_data = (void *)data; vpp_control_dp_set_default_ctrl_ifaces(data); return (GOOD); } void vpp_control_dp_uninit (oor_ctrl_t *ctrl) { vpp_ctr_dplane_data_t *data = (vpp_ctr_dplane_data_t *)control_dp_vpp.control_dp_data; if (data){ if (vpp_oor_ctrl_enable_disable(TAP_CTRL_IFACE_NAME, FALSE)!= GOOD){ OOR_LOG(LERR,"VPP: Could not disable oor ctrl plugin."); }else{ OOR_LOG(LDBG_1,"VPP: Disable OOR Ctrl plugin"); } free(data); } } int vpp_control_dp_add_iface_addr(oor_ctrl_t *ctrl,iface_t *iface, int afi) { vpp_ctr_dplane_data_t * cdp_data = control_dp_vpp.control_dp_data; switch (afi){ case AF_INET: if (cdp_data && !cdp_data->default_ctrl_iface_v4){ // It will only enter here when adding interfaces after init process vpp_control_dp_set_default_ctrl_ifaces(cdp_data); } break; case AF_INET6: if (cdp_data && !cdp_data->default_ctrl_iface_v6){ // It will only enter here when adding interfaces after init process vpp_control_dp_set_default_ctrl_ifaces(cdp_data); } break; default: break; } return (GOOD); } int vpp_control_dp_add_iface_gw(oor_ctrl_t *ctrl,iface_t *iface, int afi) { return (GOOD); } /* Process a received control message */ int vpp_control_dp_recv_msg(sock_t *sl) { uconn_t uc; lbuf_t *b; oor_ctrl_t *ctrl; oor_ctrl_dev_t *dev; packet_tuple_t tpl; ctrl = sl->arg; /* Only one device supported for now */ dev = glist_first_data(ctrl->devices); b = lisp_msg_create_buf(); if (sock_recv(sl->fd, b) != GOOD) { OOR_LOG(LDBG_1, "Couldn't read socket. Discarding packet!"); lbuf_del(b); return (BAD); } /* Remove ethernet header (TAP interface) */ pkt_pull_eth(b); lbuf_reset_ip(b); if (pkt_parse_5_tuple(b, &tpl) != GOOD) { return (BAD); } if (tpl.protocol != IPPROTO_UDP || tpl.dst_port != LISP_CONTROL_PORT){ return(BAD); } uconn_from_5_tuple(&tpl, &uc, 1); /* Remove IP and UDP header */ pkt_pull_ip(b); pkt_pull_udp(b); lbuf_reset_lisp(b); OOR_LOG(LDBG_1, "Received %s, IP: %s -> %s, UDP: %d -> %d", lisp_msg_hdr_to_char(b), lisp_addr_to_char(&uc.ra), lisp_addr_to_char(&uc.la), uc.rp, uc.lp); /* direct call of ctrl device * TODO: check type to decide where to send msg*/ ctrl_dev_recv(dev, b, &uc); lbuf_del(b); return (GOOD); } int vpp_control_dp_send_msg(oor_ctrl_t *ctrl, lbuf_t *buff, uconn_t *udp_conn) { int ret,dst_afi; ip_addr_t *src_addr, *dst_addr; lisp_addr_t *ctrl_addr; if (lisp_addr_lafi(&udp_conn->ra) != LM_AFI_IP) { OOR_LOG(LDBG_2, "vpp_control_dp_send_msg: Destination address %s of UDP connection is not a IP. " "Discarding!", lisp_addr_to_char(&udp_conn->ra)); return(BAD); } if (lisp_addr_lafi(&udp_conn->la) != LM_AFI_IP) { dst_afi = lisp_addr_ip_afi(&udp_conn->ra); ctrl_addr = vpp_control_dp_get_default_ctrl_address(control_dp_vpp.control_dp_data, dst_afi); if (!ctrl_addr) { OOR_LOG(LERR, "vpp_control_dp_send_msg: No %s control address found, send aborted!", (dst_afi == AF_INET) ? "IPv4" : "IPv6"); return(ERR_SOCKET); } /* Use as local address the default control address */ lisp_addr_copy(&udp_conn->la, ctrl_addr); } src_addr = lisp_addr_ip(&udp_conn->la); dst_addr = lisp_addr_ip(&udp_conn->ra); if (ip_addr_afi(src_addr) != ip_addr_afi(dst_addr)) { OOR_LOG(LDBG_2, "vpp_control_dp_send_msg: src %s and dst %s of UDP connection have " "different IP AFI. Discarding!", ip_addr_to_char(src_addr), ip_addr_to_char(dst_addr)); return(BAD); } pkt_push_udp_and_ip(buff, udp_conn->lp, udp_conn->rp, src_addr, dst_addr); if (lisp_addr_ip_afi(&udp_conn->la) == AF_INET){ pkt_push_eth(buff, mac, mac, ETH_P_IP); }else{ pkt_push_eth(buff, mac, mac, ETH_P_IPV6); } lbuf_reset_eth(buff); ret = write(tap_fd, lbuf_data(buff), lbuf_size(buff)); if (ret < 0) { OOR_LOG(LDBG_1, "Failed to send contrl message from RLOC: %s -> %s", lisp_addr_to_char(&udp_conn->la), lisp_addr_to_char(&udp_conn->ra)); return(BAD); } else { OOR_LOG(LDBG_1, "Sent control message IP: %s -> %s UDP: %d -> %d", lisp_addr_to_char(&udp_conn->la), lisp_addr_to_char(&udp_conn->ra), udp_conn->lp, udp_conn->rp); return(GOOD); } return (GOOD); } lisp_addr_t * vpp_control_dp_get_default_addr(oor_ctrl_t *ctrl, int afi) { vpp_ctr_dplane_data_t * data; data = (vpp_ctr_dplane_data_t *)control_dp_vpp.control_dp_data; return (vpp_control_dp_get_default_ctrl_address(data,afi)); } inline lisp_addr_t * vpp_control_dp_get_default_ctrl_address(vpp_ctr_dplane_data_t * data, int afi) { lisp_addr_t *address = NULL; switch (afi){ case AF_INET: if (data->default_ctrl_iface_v4 != NULL){ address = data->default_ctrl_iface_v4->ipv4_address; } break; case AF_INET6: if (data->default_ctrl_iface_v6 != NULL){ address = data->default_ctrl_iface_v6->ipv6_address; } break; default: OOR_LOG(LDBG_2,"vpp_control_dp_get_default_ctrl_address: Unsupported afi: %d",afi); break; } return (address); } int vpp_control_dp_updated_route(oor_ctrl_t *ctrl, int command, iface_t *iface, lisp_addr_t *src_pref,lisp_addr_t *dst_pref, lisp_addr_t *gw) { return (GOOD); } void vpp_control_dp_process_new_gateway(oor_ctrl_t *ctrl, iface_t *iface, lisp_addr_t *gateway) { } int vpp_control_dp_updated_addr(oor_ctrl_t *ctrl, iface_t *iface, lisp_addr_t *old_addr,lisp_addr_t *new_addr) { int addr_afi; vpp_ctr_dplane_data_t * data; data = (vpp_ctr_dplane_data_t *)ctrl->control_data_plane->control_dp_data; /* If no default control, recalculate it */ if (iface->status == UP) { addr_afi = lisp_addr_ip_afi(new_addr); if ((data->default_ctrl_iface_v4 == NULL && addr_afi == AF_INET) || (data->default_ctrl_iface_v6 == NULL && addr_afi == AF_INET6)) { OOR_LOG(LDBG_2, "No default control interface. Recalculate new " "control interface"); vpp_control_dp_set_default_ctrl_ifaces(data); } } return (GOOD); } int vpp_control_dp_update_link(oor_ctrl_t *ctrl, iface_t *iface, int old_iface_index, int new_iface_index, int status) { vpp_ctr_dplane_data_t * data; data = (vpp_ctr_dplane_data_t *)ctrl->control_data_plane->control_dp_data; /* If the affected interface is the default control or output iface, * recalculate it */ if (data->default_ctrl_iface_v4 == iface || data->default_ctrl_iface_v6 == iface || data->default_ctrl_iface_v4 == NULL || data->default_ctrl_iface_v6 == NULL){ OOR_LOG(LDBG_2,"Default control interface down. Recalculate new control" " interface"); vpp_control_dp_set_default_ctrl_ifaces(data); } return (GOOD); } void vpp_control_dp_set_default_ctrl_ifaces(vpp_ctr_dplane_data_t * data) { data->default_ctrl_iface_v4 = get_any_output_iface(AF_INET); if (data->default_ctrl_iface_v4 != NULL) { OOR_LOG(LDBG_2,"Default IPv4 control iface %s: %s\n", data->default_ctrl_iface_v4->iface_name, lisp_addr_to_char(data->default_ctrl_iface_v4->ipv4_address)); } data->default_ctrl_iface_v6 = get_any_output_iface(AF_INET6); if (data->default_ctrl_iface_v6 != NULL) { OOR_LOG(LDBG_2,"Default IPv6 control iface %s: %s\n", data->default_ctrl_iface_v6->iface_name, lisp_addr_to_char(data->default_ctrl_iface_v6->ipv6_address)); } if (!data->default_ctrl_iface_v4 && !data->default_ctrl_iface_v6) { OOR_LOG(LERR, "NO CONTROL IFACE: all the locators are down"); } } oor-1.2.0/oor/control/control-data-plane/vpp/cdp_vpp.h000066400000000000000000000017741313612200500226670ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef CDP_VPP_H_ #define CDP_VPP_H_ #include "../../../iface_list.h" #define TAP_CTRL_IFACE_NAME "oorCtap0" #define TAP_MTU_CTRL_VPP 1500 typedef struct vpp_ctr_dplane_data_{ iface_t *default_ctrl_iface_v4; iface_t *default_ctrl_iface_v6; }vpp_ctr_dplane_data_t; #endif /* CDP_VPP_H_ */ oor-1.2.0/oor/control/lisp_ms.c000066400000000000000000000512001313612200500163710ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "lisp_ms.h" #include "../defs.h" #include "../lib/cksum.h" #include "../lib/oor_log.h" #include "../lib/pointers_table.h" #include "../lib/prefixes.h" static int ms_recv_map_request(lisp_ms_t *, lbuf_t *, uconn_t *); static int ms_recv_map_register(lisp_ms_t *, lbuf_t *, uconn_t *); static int ms_recv_msg(oor_ctrl_dev_t *, lbuf_t *, uconn_t *); static inline lisp_ms_t *lisp_ms_cast(oor_ctrl_dev_t *dev); static locator_t * get_locator_with_afi(mapping_t *m, int afi) { glist_t *loct_list = NULL; glist_entry_t *it_list = NULL; glist_entry_t *it_loct = NULL; locator_t *loct = NULL; lisp_addr_t *addr = NULL; int lafi = 0; int afi_type = 0; glist_for_each_entry(it_list,mapping_locators_lists(m)){ loct_list = (glist_t *)glist_entry_data(it_list); locator_list_lafi_type(loct_list,&lafi,&afi_type); if (lafi == LM_AFI_NO_ADDR || (lafi == LM_AFI_IP && afi_type != afi)){ continue; } glist_for_each_entry(it_loct,loct_list){ loct = (locator_t *)glist_entry_data(it_loct); if (locator_state(loct) == DOWN){ continue; } addr = locator_addr(loct); addr = lisp_addr_get_ip_addr(addr); if (lisp_addr_ip_afi (addr) == afi){ return (loct); } } } return(NULL); } static int get_etr_from_lcaf(lisp_addr_t *laddr, lisp_addr_t **dst) { lcaf_addr_t *lcaf = NULL; elp_node_t *enode; lcaf = lisp_addr_get_lcaf(laddr); switch (lcaf_addr_get_type(lcaf)) { case LCAF_EXPL_LOC_PATH: /* we're looking for the ETR, so the destination is the last elp hop */ enode = glist_last_data(lcaf_elp_node_list(lcaf)); *dst = enode->addr; break; default: *dst = NULL; OOR_LOG(LDBG_1, "get_locator_from_lcaf: Type % not supported!, ", lcaf_addr_get_type(lcaf)); return (BAD); } return (GOOD); } /* forward encapsulated Map-Request to ETR */ static int forward_mreq(lisp_ms_t *ms, lbuf_t *b, mapping_t *m) { oor_ctrl_t *ctrl = NULL; lisp_addr_t *drloc = NULL; locator_t *loct = NULL; uconn_t fwd_uc; ctrl = ctrl_dev_get_ctrl_t(&(ms->super)); if ((ctrl_supported_afis(ctrl) & IPv4_SUPPORT) != 0){ loct = get_locator_with_afi(m, AF_INET); } if (loct == NULL && (ctrl_supported_afis(ctrl) & IPv6_SUPPORT) != 0){ loct = get_locator_with_afi(m, AF_INET6); } if (loct == NULL){ OOR_LOG(LDBG_1, "Can't find valid RLOC to forward Map-Request to " "ETR. Discarding!"); return(BAD); } drloc = lisp_addr_get_ip_addr(locator_addr(loct)); if (lisp_addr_lafi(drloc) == LM_AFI_LCAF) { get_etr_from_lcaf(drloc, &drloc); } OOR_LOG(LDBG_3, "Found xTR with locator %s to forward Encap Map-Request", lisp_addr_to_char(drloc)); /* Set buffer to forward the encapsulated message*/ lbuf_point_to_lisp_hdr(b); uconn_init(&fwd_uc, LISP_CONTROL_PORT, LISP_CONTROL_PORT, NULL, drloc); return(send_msg(&ms->super, b, &fwd_uc)); } /* Called when the timer associated with a registered lisp site expires. */ static int lsite_entry_expiration_timer_cb(oor_timer_t *t) { lisp_reg_site_t *rsite = NULL; lisp_addr_t *addr = NULL; lisp_ms_t *ms = t->owner; rsite = oor_timer_cb_argument(t); addr = mapping_eid(rsite->site_map); OOR_LOG(LDBG_1,"Registration of site with EID %s timed out", lisp_addr_to_char(addr)); mdb_remove_entry(ms->reg_sites_db, addr); lisp_reg_site_del(rsite); ms_dump_registered_sites(ms, LDBG_3); return(GOOD); } static void lsite_entry_start_expiration_timer(lisp_ms_t *ms, lisp_reg_site_t *rsite) { oor_timer_t *timer; timer = oor_timer_create(REG_SITE_EXPRY_TIMER); oor_timer_init(timer, ms, lsite_entry_expiration_timer_cb, rsite, NULL, NULL); htable_ptrs_timers_add(ptrs_to_timers_ht,rsite, timer); /* Give a 2s margin before purging the registered site */ oor_timer_start(timer, MS_SITE_EXPIRATION + 2); OOR_LOG(LDBG_2,"The map cache entry of EID %s will expire in %ld seconds.", lisp_addr_to_char(mapping_eid(rsite->site_map)), MS_SITE_EXPIRATION); } static void lsite_entry_update_expiration_timer(lisp_ms_t *ms, lisp_reg_site_t *rsite) { oor_timer_t *timer; glist_t *timer_lst; timer_lst = htable_ptrs_timers_get_timers_of_type_from_obj(ptrs_to_timers_ht,rsite, REG_SITE_EXPRY_TIMER); if (glist_size(timer_lst) != 1){ OOR_LOG(LDBG_1,"lsite_entry_start_expiration_timer: %d timers for same site." "It should never happen", glist_size(timer_lst)); glist_destroy(timer_lst); return; } timer = (oor_timer_t *)glist_first_data(timer_lst); glist_destroy(timer_lst); /* Give a 2s margin before purging the registered site */ oor_timer_start(timer, MS_SITE_EXPIRATION + 2); OOR_LOG(LDBG_2,"The map cache entry of EID %s will expire in %ld seconds.", lisp_addr_to_char(mapping_eid(rsite->site_map)), MS_SITE_EXPIRATION); } static int ms_recv_map_request(lisp_ms_t *ms, lbuf_t *buf, uconn_t *uc) { lisp_addr_t * seid = NULL; lisp_addr_t * deid = NULL; mapping_t * map = NULL; glist_t * itr_rlocs = NULL; void * mreq_hdr = NULL; void * mrep_hdr = NULL; mapping_record_hdr_t * rec = NULL; int i = 0; lbuf_t * mrep = NULL; lbuf_t b; lisp_site_prefix_t * site = NULL; lisp_reg_site_t * rsite = NULL; uint8_t act_flag; /* local copy of the buf that can be modified */ b = *buf; seid = lisp_addr_new(); mreq_hdr = lisp_msg_pull_hdr(&b); if (lisp_msg_parse_addr(&b, seid) != GOOD) { goto err; } OOR_LOG(LDBG_1, " src-eid: %s", lisp_addr_to_char(seid)); if (MREQ_RLOC_PROBE(mreq_hdr)) { OOR_LOG(LDBG_2, "Probe bit set. Discarding!"); return(BAD); } if (MREQ_SMR(mreq_hdr)) { OOR_LOG(LDBG_2, "SMR bit set. Discarding!"); return(BAD); } /* PROCESS ITR RLOCs */ itr_rlocs = laddr_list_new(); lisp_msg_parse_itr_rlocs(&b, itr_rlocs); for (i = 0; i < MREQ_REC_COUNT(mreq_hdr); i++) { deid = lisp_addr_new(); /* PROCESS EID REC */ if (lisp_msg_parse_eid_rec(&b, deid) != GOOD) { goto err; } /* CHECK IF WE NEED TO PROXY REPLY */ site = mdb_lookup_entry(ms->lisp_sites_db, deid); rsite = mdb_lookup_entry(ms->reg_sites_db, deid); /* Static entries will have null site and not null rsite */ if (!site && !rsite) { /* send negative map-reply with TTL 15 min */ if (lisp_addr_is_iid(deid)){ act_flag = ACT_NO_ACTION; }else{ act_flag = ACT_NATIVE_FWD; } mrep = lisp_msg_neg_mrep_create(deid, 15, act_flag,A_AUTHORITATIVE, MREQ_NONCE(mreq_hdr)); OOR_LOG(LDBG_1,"The requested EID %s doesn't belong to this Map Server", lisp_addr_to_char(deid)); OOR_LOG(LDBG_2, "%s, EID: %s, NEGATIVE", lisp_msg_hdr_to_char(mrep), lisp_addr_to_char(deid)); send_msg(&ms->super, mrep, uc); lisp_msg_destroy(mrep); lisp_addr_del(deid); continue; } /* Find if the site actually registered */ if (!rsite) { /* send negative map-reply with TTL 1 min */ mrep = lisp_msg_neg_mrep_create(deid, 1, ACT_NATIVE_FWD,A_AUTHORITATIVE, MREQ_NONCE(mreq_hdr)); OOR_LOG(LDBG_1,"The requested EID %s is not registered", lisp_addr_to_char(deid)); OOR_LOG(LDBG_2, "%s, EID: %s, NEGATIVE", lisp_msg_hdr_to_char(mrep), lisp_addr_to_char(deid)); send_msg(&ms->super, mrep, uc); lisp_msg_destroy(mrep); lisp_addr_del(deid); continue; } map = rsite->site_map; /* If site is null, the request is for a static entry */ /* IF *NOT* PROXY REPLY: forward the message to an xTR */ if (site != NULL && site->proxy_reply == FALSE) { /* FIXME: once locs become one object, send that instead of mapping */ forward_mreq(ms, buf, map); lisp_msg_destroy(mrep); lisp_addr_del(deid); continue; } OOR_LOG(LDBG_1,"The requested EID %s belongs to the registered prefix %s. Send Map Reply", lisp_addr_to_char(deid), lisp_addr_to_char(mapping_eid(map))); /* IF PROXY REPLY: build Map-Reply */ mrep = lisp_msg_create(LISP_MAP_REPLY); rec = lisp_msg_put_mapping(mrep, map, NULL); /* Set the authoritative bit of the record to false*/ MAP_REC_AUTH(rec) = A_NO_AUTHORITATIVE; mrep_hdr = lisp_msg_hdr(mrep); MREP_RLOC_PROBE(mrep_hdr) = 0; MREP_NONCE(mrep_hdr) = MREQ_NONCE(mreq_hdr); /* SEND MAP-REPLY */ laddr_list_get_addr(itr_rlocs, lisp_addr_ip_afi(&uc->la), &uc->ra); if (send_msg(&ms->super, mrep, uc) != GOOD) { OOR_LOG(LDBG_1, "Couldn't send Map-Reply!"); } lisp_msg_destroy(mrep); lisp_addr_del(deid); } glist_destroy(itr_rlocs); lisp_addr_del(seid); return(GOOD); err: glist_destroy(itr_rlocs); lisp_msg_destroy(mrep); lisp_addr_del(deid); lisp_addr_del(seid); return(BAD); } static int ms_recv_map_register(lisp_ms_t *ms, lbuf_t *buf, uconn_t *uc) { lisp_reg_site_t *rsite = NULL, *new_rsite = NULL; lisp_site_prefix_t *reg_pref = NULL; char *key = NULL; lisp_addr_t *eid; lbuf_t b; void *hdr = NULL, *mntf_hdr = NULL; int i = 0; mapping_t *m = NULL; locator_t *probed = NULL; lbuf_t *mntf = NULL; lisp_key_type_e keyid = HMAC_SHA_1_96; /* TODO configurable */ int valid_records = FALSE; b = *buf; hdr = lisp_msg_pull_hdr(&b); if (MREG_WANT_MAP_NOTIFY(hdr)) { mntf = lisp_msg_create(LISP_MAP_NOTIFY); lisp_msg_put_empty_auth_record(mntf, keyid); } lisp_msg_pull_auth_field(&b); for (i = 0; i < MREG_REC_COUNT(hdr); i++) { m = mapping_new(); if (lisp_msg_parse_mapping_record(&b, m, &probed) != GOOD) { goto err; } if (mapping_auth(m) == 0){ OOR_LOG(LWRN,"ms_recv_map_register: Received a none authoritative record in a Map Register: %s", lisp_addr_to_char(mapping_eid(m))); } /* To be sure that we store the network address and not a IP-> 10.0.0.0/24 instead of 10.0.0.1/24 */ eid = mapping_eid(m); pref_conv_to_netw_pref(eid); /* find configured prefix */ reg_pref = mdb_lookup_entry(ms->lisp_sites_db, eid); if (!reg_pref) { OOR_LOG(LDBG_1, "EID %s not in configured lisp-sites DB " "Discarding mapping", lisp_addr_to_char(eid)); mapping_del(m); continue; } /* CHECK AUTH */ /* if first record, lookup the key */ if (!key) { if (lisp_msg_check_auth_field(buf, reg_pref->key) != GOOD) { OOR_LOG(LDBG_1, "Message validation failed for EID %s with key " "%s. Stopping processing!", lisp_addr_to_char(eid), reg_pref->key); goto bad; } OOR_LOG(LDBG_2, "Message validated with key associated to EID %s", lisp_addr_to_char(eid)); key = reg_pref->key; } else if (strncmp(key, reg_pref->key, strlen(key)) !=0 ) { OOR_LOG(LDBG_1, "EID %s part of multi EID Map-Register has different " "key! Discarding!", lisp_addr_to_char(eid)); continue; } /* check more specific */ if (reg_pref->accept_more_specifics == TRUE){ if (!pref_is_prefix_b_part_of_a( lisp_addr_get_ip_pref_addr(reg_pref->eid_prefix), lisp_addr_get_ip_pref_addr(mapping_eid(m)))){ OOR_LOG(LDBG_1, "EID %s not in configured lisp-sites DB! " "Discarding mapping!", lisp_addr_to_char(eid)); mapping_del(m); continue; } }else if(lisp_addr_cmp(reg_pref->eid_prefix, eid) !=0) { OOR_LOG(LDBG_1, "EID %s is a more specific of %s. However more " "specifics not configured! Discarding", lisp_addr_to_char(eid), lisp_addr_to_char(reg_pref->eid_prefix)); lisp_addr_del(eid); continue; } rsite = mdb_lookup_entry_exact(ms->reg_sites_db, eid); if (rsite) { if (mapping_cmp(rsite->site_map, m) != 0) { if (!reg_pref->merge) { OOR_LOG(LDBG_3, "Prefix %s already registered, updating " "locators", lisp_addr_to_char(eid)); mapping_update_locators(rsite->site_map,mapping_locators_lists(m)); } else { /* TREAT MERGE SEMANTICS */ OOR_LOG(LWRN, "Prefix %s has merge semantics", lisp_addr_to_char(eid)); } ms_dump_registered_sites(ms, LDBG_3); } reg_pref->proxy_reply = MREG_PROXY_REPLY(hdr); /* update registration timer */ lsite_entry_update_expiration_timer(ms, rsite); } else { /* save prefix to the registered sites db */ new_rsite = xzalloc(sizeof(lisp_reg_site_t)); new_rsite->site_map = m; mdb_add_entry(ms->reg_sites_db, mapping_eid(m), new_rsite); lsite_entry_start_expiration_timer(ms, new_rsite); reg_pref->proxy_reply = MREG_PROXY_REPLY(hdr); ms_dump_registered_sites(ms, LDBG_3); } if (MREG_WANT_MAP_NOTIFY(hdr)) { lisp_msg_put_mapping(mntf, m, NULL); valid_records = TRUE; } /* if site previously registered, just remove the parsed mapping */ if (rsite) { mapping_del(m); } } /* check if key is initialized, otherwise registration failed */ if (mntf && key && valid_records) { mntf_hdr = lisp_msg_hdr(mntf); MNTF_NONCE(mntf_hdr) = MREG_NONCE(hdr); lisp_msg_fill_auth_data(mntf, keyid, key); OOR_LOG(LDBG_1, "%s, IP: %s -> %s, UDP: %d -> %d", lisp_msg_hdr_to_char(mntf), lisp_addr_to_char(&uc->la), lisp_addr_to_char(&uc->ra), uc->lp, uc->rp); send_msg(&ms->super, mntf, uc); } lisp_msg_destroy(mntf); return(GOOD); err: return(BAD); mapping_del(m); lisp_msg_destroy(mntf); bad: /* could return different error */ mapping_del(m); lisp_msg_destroy(mntf); return(BAD); } int ms_add_lisp_site_prefix(lisp_ms_t *ms, lisp_site_prefix_t *sp) { if (!sp) return(BAD); if(!mdb_add_entry(ms->lisp_sites_db, lsite_prefix(sp), sp)) return(BAD); return(GOOD); } int ms_add_registered_site_prefix(lisp_ms_t *ms, mapping_t *sp) { if (!sp) { return(BAD); } lisp_reg_site_t *rs = xzalloc(sizeof(lisp_reg_site_t)); rs->site_map = sp; if (!mdb_add_entry(ms->reg_sites_db, mapping_eid(sp), rs)) return(BAD); return(GOOD); } void ms_dump_configured_sites(lisp_ms_t *ms, int log_level) { if (is_loggable(log_level) == FALSE){ return; } void *it = NULL; lisp_site_prefix_t *site = NULL; OOR_LOG(log_level,"****************** MS configured prefixes **************\n"); mdb_foreach_entry(ms->lisp_sites_db, it) { site = it; OOR_LOG(log_level, "Prefix: %s, accept specifics: %s merge: %s, proxy: %s", lisp_addr_to_char(site->eid_prefix), (site->accept_more_specifics) ? "on" : "off", (site->merge) ? "on" : "off", (site->proxy_reply) ? "on" : "off"); } mdb_foreach_entry_end; OOR_LOG(log_level,"*******************************************************\n"); } void ms_dump_registered_sites(lisp_ms_t *ms, int log_level) { if (is_loggable(log_level) == FALSE){ return; } void *it = NULL; lisp_reg_site_t *rsite = NULL; OOR_LOG(log_level,"**************** MS registered sites ******************\n"); mdb_foreach_entry(ms->reg_sites_db, it) { rsite = it; OOR_LOG(log_level, "%s", mapping_to_char(rsite->site_map)); } mdb_foreach_entry_end; OOR_LOG(log_level,"*******************************************************\n"); } static inline lisp_ms_t * lisp_ms_cast(oor_ctrl_dev_t *dev) { /* make sure */ lm_assert(dev->ctrl_class == &ms_ctrl_class); return(CONTAINER_OF(dev, lisp_ms_t, super)); } static int ms_recv_msg(oor_ctrl_dev_t *dev, lbuf_t *msg, uconn_t *uc) { int ret = BAD; lisp_msg_type_e type; lisp_ms_t *ms; ms = lisp_ms_cast(dev); type = lisp_msg_type(msg); if (type == LISP_ENCAP_CONTROL_TYPE) { if (lisp_msg_ecm_decap(msg, &uc->rp) != GOOD) return (BAD); type = lisp_msg_type(msg); } switch(type) { case LISP_MAP_REQUEST: ret = ms_recv_map_request(ms, msg, uc); break; case LISP_MAP_REGISTER: ret = ms_recv_map_register(ms, msg, uc); break; case LISP_MAP_REPLY: case LISP_MAP_NOTIFY: case LISP_INFO_NAT: OOR_LOG(LDBG_3, "Map-Server: Received control message with type %d." " Discarding!", type); break; default: OOR_LOG(LDBG_3, "Map-Server: Received unidentified type (%d) control " "message", type); ret = BAD; break; } if (ret != GOOD) { OOR_LOG(LDBG_1, "Map-Server: Failed to process control message"); return(BAD); } else { OOR_LOG(LDBG_3, "Map-Server: Completed processing of control message"); return(ret); } } int ms_if_link_update(oor_ctrl_dev_t *dev, char *iface_name, uint8_t state) { return (GOOD); } int ms_if_addr_update(oor_ctrl_dev_t *dev, char *iface_name, lisp_addr_t *old_addr, lisp_addr_t *new_addr, uint8_t status) { return (GOOD); } int ms_route_update(oor_ctrl_dev_t *dev, int command, char *iface_name ,lisp_addr_t *src_pref, lisp_addr_t *dst_pref, lisp_addr_t *gateway) { return (GOOD); } fwd_info_t * ms_get_fwd_entry(oor_ctrl_dev_t *dev, packet_tuple_t *tuple) { return (NULL); } static oor_ctrl_dev_t * ms_ctrl_alloc() { lisp_ms_t *ms; ms = xzalloc(sizeof(lisp_ms_t)); return(&ms->super); } static int ms_ctrl_construct(oor_ctrl_dev_t *dev) { lisp_ms_t *ms = lisp_ms_cast(dev); ms->reg_sites_db = mdb_new(); ms->lisp_sites_db = mdb_new(); if (!ms->reg_sites_db || !ms->lisp_sites_db) { return(BAD); } OOR_LOG(LDBG_1, "Finished Constructing Map-Server"); return(GOOD); } static void ms_ctrl_destruct(oor_ctrl_dev_t *dev) { lisp_ms_t *ms = lisp_ms_cast(dev); mdb_del(ms->lisp_sites_db, (mdb_del_fct)lisp_site_prefix_del); mdb_del(ms->reg_sites_db, (mdb_del_fct)lisp_reg_site_del); } void ms_ctrl_dealloc(oor_ctrl_dev_t *dev) { lisp_ms_t *ms = lisp_ms_cast(dev); OOR_LOG(LDBG_1, "Freeing Map-Server ..."); free(ms); } void ms_ctrl_run(oor_ctrl_dev_t *dev) { lisp_ms_t *ms = lisp_ms_cast(dev); OOR_LOG (LDBG_1, "****** Summary of the configuration ******"); ms_dump_configured_sites(ms, LDBG_1); ms_dump_registered_sites(ms, LDBG_1); OOR_LOG(LDBG_1, "Starting Map-Server ..."); } ctrl_dev_class_t ms_ctrl_class = { .alloc = ms_ctrl_alloc, .construct = ms_ctrl_construct, .dealloc = ms_ctrl_dealloc, .destruct = ms_ctrl_destruct, .run = ms_ctrl_run, .recv_msg = ms_recv_msg, .if_link_update = ms_if_link_update, .if_addr_update = ms_if_addr_update, .route_update = ms_route_update, .get_fwd_entry = ms_get_fwd_entry }; oor-1.2.0/oor/control/lisp_ms.h000066400000000000000000000023571313612200500164070ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef LISP_MS_H_ #define LISP_MS_H_ #include "oor_ctrl_device.h" #include "../lib/lisp_site.h" typedef struct _lisp_ms { oor_ctrl_dev_t super; /* base "class" */ /* ms members */ mdb_t *lisp_sites_db; mdb_t *reg_sites_db; } lisp_ms_t; /* ms interface */ int ms_add_lisp_site_prefix(lisp_ms_t *ms, lisp_site_prefix_t *site); int ms_add_registered_site_prefix(lisp_ms_t *dev, mapping_t *sp); void ms_dump_configured_sites(lisp_ms_t *dev, int log_level); void ms_dump_registered_sites(lisp_ms_t *dev, int log_level); #endif /* LISP_MS_H_ */ oor-1.2.0/oor/control/lisp_xtr.c000066400000000000000000003074671313612200500166120ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include #include "../lib/iface_locators.h" #include "../lib/sockets.h" #include "../lib/mem_util.h" #include "../lib/oor_log.h" #include "../lib/timers_utils.h" #include "../lib/util.h" #include "lisp_xtr.h" static int mc_entry_expiration_timer_cb(oor_timer_t *t); static void mc_entry_start_expiration_timer(lisp_xtr_t *, mcache_entry_t *); static void mc_entry_start_expiration_timer2(lisp_xtr_t *xtr, mcache_entry_t *mce, int time); static int handle_locator_probe_reply(lisp_xtr_t *, mcache_entry_t *, lisp_addr_t *); static int update_mcache_entry(lisp_xtr_t *, mapping_t *); static int tr_recv_map_reply(lisp_xtr_t *, lbuf_t *, uconn_t *); static int tr_reply_to_smr(lisp_xtr_t *xtr, lisp_addr_t *src_eid, lisp_addr_t *req_eid); static int tr_recv_map_request(lisp_xtr_t *, lbuf_t *, uconn_t *); static int tr_recv_map_notify(lisp_xtr_t *, lbuf_t *); static int tr_recv_info_nat(lisp_xtr_t *xtr, lbuf_t *buf, uconn_t *uc); int tr_update_nat_info(lisp_xtr_t *xtr, map_local_entry_t *mle, locator_t *loct, glist_t *rtr_list); void tr_update_fwd_info_rtrs(lisp_xtr_t *xtr); glist_t *nat_select_rtrs(glist_t * rtr_list); static glist_t *build_rloc_list(mapping_t *m); static int build_and_send_smr_mreq(lisp_xtr_t *, mapping_t *, lisp_addr_t *, lisp_addr_t *); static int build_and_send_smr_mreq_to_map(lisp_xtr_t *, mapping_t *, mapping_t *); static int send_all_smr_cb(oor_timer_t *); static void send_all_smr_and_mreg(lisp_xtr_t *); static int smr_invoked_map_request_cb(oor_timer_t *timer); static int send_smr_invoked_map_request(lisp_xtr_t *xtr, lisp_addr_t *src_eid, mcache_entry_t *mce, uint64_t nonce); static int program_smr(lisp_xtr_t *, int time); static int send_map_request_retry_cb(oor_timer_t *timer); static int build_and_send_encap_map_request(lisp_xtr_t *xtr, lisp_addr_t *src_eid, mcache_entry_t *mce, uint64_t nonce); static int build_and_send_map_reg(lisp_xtr_t *, mapping_t *, map_server_elt *, uint64_t); int program_map_register_for_mapping(lisp_xtr_t *xtr, map_local_entry_t *mle); static int encap_map_register_cb(oor_timer_t *timer); int program_encap_map_reg_of_loct_for_map(lisp_xtr_t *xtr, map_local_entry_t *mle, locator_t *src_loct); static int rloc_probing(lisp_xtr_t *, mapping_t *, locator_t *loc, uint64_t nonce); static void program_rloc_probing(lisp_xtr_t *, mcache_entry_t *, locator_t *, int); static void program_mce_rloc_probing(lisp_xtr_t *, mcache_entry_t *); static inline lisp_xtr_t *lisp_xtr_cast(oor_ctrl_dev_t *); int map_reply_fill_uconn(lisp_xtr_t *xtr, glist_t *itr_rlocs, uconn_t *uc); static void proxy_etrs_dump(lisp_xtr_t *, int log_level); static fwd_info_t *tr_get_forwarding_entry(oor_ctrl_dev_t *, packet_tuple_t *); glist_t *get_local_locators_with_address(local_map_db_t *local_db, lisp_addr_t *addr); map_local_entry_t *get_map_loc_ent_containing_loct_ptr(local_map_db_t *local_db, locator_t *locator); glist_t *get_map_local_entry_to_smr(lisp_xtr_t *xtr); static lisp_addr_t * get_map_resolver(lisp_xtr_t *xtr); mcache_entry_t *get_proxy_etrs_for_afi(lisp_xtr_t *xtr, int afi); static int mapping_has_elp_with_l_bit(mapping_t *map); /* Funtions related to timer_rloc_probe_argument */ timer_rloc_probe_argument *timer_rloc_probe_argument_new_init(mcache_entry_t *mce, locator_t *locator); int xtr_if_link_update(oor_ctrl_dev_t *dev, char *iface_name, uint8_t status); int xtr_if_addr_update(oor_ctrl_dev_t *dev, char *iface_name, lisp_addr_t *old_addr, lisp_addr_t *new_addr, uint8_t status); int xtr_route_update(oor_ctrl_dev_t *dev, int command, char *iface_name , lisp_addr_t *src_pref, lisp_addr_t *dst_pref, lisp_addr_t *gateway); int xtr_iface_event_signaling(lisp_xtr_t * xtr, iface_locators * if_loct); void timer_rloc_probe_argument_free(timer_rloc_probe_argument *timer_arg); /* Funtions related to timer_map_req_argument */ timer_map_req_argument *timer_map_req_arg_new_init(mcache_entry_t *mce, lisp_addr_t *src_eid); void timer_map_req_arg_free(timer_map_req_argument * timer_arg); /* Funtions related to timer_map_reg_argument */ timer_map_reg_argument * timer_map_reg_argument_new_init(map_local_entry_t *mle, map_server_elt *ms); void timer_map_reg_arg_free(timer_map_reg_argument * timer_arg); timer_encap_map_reg_argument *timer_encap_map_reg_argument_new_init(map_local_entry_t *mle, map_server_elt *ms, locator_t *src_loct, lisp_addr_t *rtr_addr); void timer_encap_map_reg_arg_free(timer_encap_map_reg_argument * timer_arg); void timer_encap_map_reg_stop_using_locator(map_local_entry_t *mle, locator_t *loct); timer_inf_req_argument * timer_inf_req_argument_new_init(map_local_entry_t *mle, locator_t *loct, map_server_elt *ms); void timer_inf_req_arg_free(timer_inf_req_argument * timer_arg); void timer_inf_req_stop_using_locator(map_local_entry_t *mle, locator_t *loct); inline oor_encap_t tr_get_encap_type(lisp_xtr_t *tr) { return (tr->encap_type); } /* Called when the timer associated with an EID entry expires. */ static int mc_entry_expiration_timer_cb(oor_timer_t *timer) { mcache_entry_t *mce = oor_timer_cb_argument(timer); mapping_t *map = mcache_entry_mapping(mce); lisp_addr_t *addr = mapping_eid(map); lisp_xtr_t *xtr = oor_timer_owner(timer); OOR_LOG(LDBG_1,"Got expiration for EID %s", lisp_addr_to_char(addr)); tr_mcache_remove_entry(xtr, mce); return(GOOD); } static void mc_entry_start_expiration_timer(lisp_xtr_t *xtr, mcache_entry_t *mce) { int time = mapping_ttl(mcache_entry_mapping(mce))*60; mc_entry_start_expiration_timer2(xtr, mce, time); } static void mc_entry_start_expiration_timer2(lisp_xtr_t *xtr, mcache_entry_t *mce, int time) { /* Expiration cache timer */ oor_timer_t *timer; timer = oor_timer_create(EXPIRE_MAP_CACHE_TIMER); oor_timer_init(timer,xtr,mc_entry_expiration_timer_cb,mce,NULL,NULL); htable_ptrs_timers_add(ptrs_to_timers_ht, mce, timer); oor_timer_start(timer, time); if (time > 60){ OOR_LOG(LDBG_1,"The map cache entry of EID %s will expire in %d minutes.", lisp_addr_to_char(mapping_eid(mcache_entry_mapping(mce))),time/60); }else{ OOR_LOG(LDBG_1,"The map cache entry of EID %s will expire in %d seconds.", lisp_addr_to_char(mapping_eid(mcache_entry_mapping(mce))),time); } } /* Process a record from map-reply probe message */ static int handle_locator_probe_reply(lisp_xtr_t *xtr, mcache_entry_t *mce, lisp_addr_t *probed_addr) { locator_t * loct = NULL; mapping_t * map = NULL; map = mcache_entry_mapping(mce); loct = mapping_get_loct_with_addr(map, probed_addr); if (!loct){ OOR_LOG(LDBG_2,"Probed locator %s not part of the the mapping %s", lisp_addr_to_char(probed_addr), lisp_addr_to_char(mapping_eid(map))); return (ERR_NO_EXIST); } OOR_LOG(LDBG_1," Successfully probed RLOC %s of cache entry with EID %s", lisp_addr_to_char(locator_addr(loct)), lisp_addr_to_char(mapping_eid(map))); if (loct->state == DOWN) { loct->state = UP; OOR_LOG(LDBG_1," Locator %s state changed to UP", lisp_addr_to_char(locator_addr(loct))); /* [re]Calculate forwarding info if status changed*/ xtr->fwd_policy->updated_map_cache_inf(xtr->fwd_policy_dev_parm,mce); notify_datap_rm_fwd_from_entry(&(xtr->super),mapping_eid(map),FALSE); } /* Reprogramming timers of rloc probing */ program_rloc_probing(xtr, mce, loct, xtr->probe_interval); return (GOOD); } static int update_mcache_entry(lisp_xtr_t *xtr, mapping_t *recv_map) { mcache_entry_t *mce = NULL; mapping_t *map = NULL; lisp_addr_t *eid = NULL; eid = mapping_eid(recv_map); /* Serch map cache entry exist*/ mce = mcache_lookup_exact(xtr->map_cache, eid); if (!mce){ OOR_LOG(LDBG_2,"No map cache entry for %s", lisp_addr_to_char(eid)); return (BAD); } OOR_LOG(LDBG_2, "Mapping with EID %s already exists, replacing!", lisp_addr_to_char(eid)); map = mcache_entry_mapping(mce); /* DISCARD all locator state */ mapping_update_locators(map, mapping_locators_lists(recv_map)); /* Update forwarding info */ xtr->fwd_policy->updated_map_cache_inf(xtr->fwd_policy_dev_parm,mce); notify_datap_rm_fwd_from_entry(&(xtr->super),eid,FALSE); /* Reprogramming timers */ mc_entry_start_expiration_timer(xtr, mce); /* RLOC probing timer */ program_mce_rloc_probing(xtr, mce); return (GOOD); } static int tr_recv_map_reply(lisp_xtr_t *xtr, lbuf_t *buf, uconn_t *udp_con) { void *mrep_hdr; locator_t *probed; lisp_addr_t *probed_addr; mapping_t *m, *aux_m; lbuf_t b; mcache_entry_t *mce; nonces_list_t *nonces_lst; oor_timer_t *timer; timer_map_req_argument *t_mr_arg; int records,active_entry,i; /* local copy */ b = *buf; mrep_hdr = lisp_msg_pull_hdr(&b); /* Check NONCE */ nonces_lst = htable_nonces_lookup(nonces_ht, MREP_NONCE(mrep_hdr)); if (!nonces_lst){ OOR_LOG(LDBG_2, " Nonce %"PRIx64" doesn't match any Map-Request nonce. " "Discarding message!", MREP_NONCE(mrep_hdr)); return(BAD); } timer = nonces_list_timer(nonces_lst); /* If it is not a Map Reply Probe */ if (!MREP_RLOC_PROBE(mrep_hdr)){ t_mr_arg = (timer_map_req_argument *)oor_timer_cb_argument(timer); /* We only accept one record except when the nonce is generated by a not active entry */ mce = t_mr_arg->mce; active_entry = mcache_entry_active(mce); if (!active_entry){ records = MREP_REC_COUNT(mrep_hdr); /* delete placeholder/dummy mapping inorder to install the new one */ tr_mcache_remove_entry(xtr, mce); /* Timers are removed during the process of deleting the mce*/ timer = NULL; }else{ if (MREP_REC_COUNT(mrep_hdr) >1){ OOR_LOG(LINF,"Received Map Reply with multiple records. Only first one will be processed"); } records = 1; } for (i = 0; i < records; i++) { m = mapping_new(); if (lisp_msg_parse_mapping_record(&b, m, &probed) != GOOD) { goto err; } if (mapping_has_elp_with_l_bit(m)){ OOR_LOG(LDBG_1,"Received a Map Reply with an ELP with the L bit set. " "Not supported -> Discrding map reply"); goto err; } /* Mapping is NOT ACTIVE */ if (!active_entry) { /* DO NOT free mapping in this case */ tr_mcache_add_mapping(xtr, m); /* Mapping is ACTIVE */ } else { /* the reply might be for an active mapping (SMR)*/ update_mcache_entry(xtr, m); mapping_del(m); } mcache_dump_db(xtr->map_cache, LDBG_3); } }else{ if (MREP_REC_COUNT(mrep_hdr) >1){ OOR_LOG(LDBG_1,"Received Map Reply Probe with multiple records. Only first one will be processed"); } records = 1; for (i = 0; i < records; i++) { m = mapping_new(); if (lisp_msg_parse_mapping_record(&b, m, &probed) != GOOD) { goto err; } if (mapping_has_elp_with_l_bit(m)){ OOR_LOG(LDBG_1,"Received a Map Reply with an ELP with the L bit set. " "Not supported -> Discrding map reply"); goto err; } if (probed != NULL){ probed_addr = locator_addr(probed); }else{ probed_addr = &(udp_con->ra); } mce = mcache_lookup_exact(xtr->map_cache, mapping_eid(m)); if (!mce){ /* Check if the map reply probe is from a proxy */ mce = get_proxy_etrs_for_afi(xtr, lisp_addr_ip_afi(mapping_eid(m))); if (mce) { aux_m = mcache_entry_mapping(mce); if (lisp_addr_cmp(mapping_eid(m),mapping_eid(aux_m)) != 0){ OOR_LOG(LDBG_2,"Received a non requested Map Reply probe"); return (BAD); } }else{ OOR_LOG(LDBG_2,"Received a non requested Map Reply probe"); return (BAD); } } handle_locator_probe_reply(xtr, mce, probed_addr); /* No need to free 'probed' since it's a pointer to a locator in * of m's */ mapping_del(m); } } if (timer != NULL){ /* Remove nonces_lst and associated timer*/ stop_timer_from_obj(mce,timer,ptrs_to_timers_ht,nonces_ht); } return(GOOD); err: locator_del(probed); mapping_del(m); return(BAD); } static int tr_reply_to_smr(lisp_xtr_t *xtr, lisp_addr_t *src_eid, lisp_addr_t *req_eid) { mcache_entry_t *mce; oor_timer_t *timer; timer_map_req_argument *timer_arg; /* Lookup the map cache entry that match with the requested EID prefix */ if (!(mce = mcache_lookup(xtr->map_cache, req_eid))) { OOR_LOG(LDBG_2,"tr_reply_to_smr: Received a solicited SMR from %s but it " "doesn't exist in cache", lisp_addr_to_char(req_eid)); return(BAD); } /* Creat timer responsible of retries */ timer_arg = timer_map_req_arg_new_init(mce,src_eid); timer = oor_timer_with_nonce_new(SMR_INV_RETRY_TIMER, xtr, smr_invoked_map_request_cb, timer_arg,(oor_timer_del_cb_arg_fn)timer_map_req_arg_free); htable_ptrs_timers_add(ptrs_to_timers_ht, mce, timer); smr_invoked_map_request_cb(timer); return(GOOD); } static int tr_recv_map_request(lisp_xtr_t *xtr, lbuf_t *buf, uconn_t *uc) { lisp_addr_t *seid = NULL; lisp_addr_t *deid = NULL; map_local_entry_t *map_loc_e = NULL; mapping_t *map = NULL; glist_t *itr_rlocs = NULL; void *mreq_hdr = NULL; void *mrep_hdr = NULL; int i = 0; lbuf_t *mrep = NULL; lbuf_t b; /* local copy of the buf that can be modified */ b = *buf; seid = lisp_addr_new(); deid = lisp_addr_new(); mreq_hdr = lisp_msg_pull_hdr(&b); if (lisp_msg_parse_addr(&b, seid) != GOOD) { goto err; } if (MREQ_RLOC_PROBE(mreq_hdr) && MREQ_REC_COUNT(mreq_hdr) > 1) { OOR_LOG(LDBG_1, "More than one EID record in RLOC probe. Discarding!"); goto err; } if (MREQ_SMR(mreq_hdr) && MREQ_REC_COUNT(mreq_hdr) > 1) { OOR_LOG(LDBG_1, "More than one EID record in SMR request. Discarding!"); goto err; } /* Process additional ITR RLOCs */ itr_rlocs = laddr_list_new(); lisp_msg_parse_itr_rlocs(&b, itr_rlocs); /* Process records and build Map-Reply */ mrep = lisp_msg_create(LISP_MAP_REPLY); for (i = 0; i < MREQ_REC_COUNT(mreq_hdr); i++) { if (lisp_msg_parse_eid_rec(&b, deid) != GOOD) { goto err; } OOR_LOG(LDBG_1, " dst-eid: %s", lisp_addr_to_char(deid)); if (xtr->super.mode == xTR_MODE || xtr->super.mode == MN_MODE) { /* Check the existence of the requested EID */ map_loc_e = local_map_db_lookup_eid(xtr->local_mdb, deid, TRUE); if (!map_loc_e) { OOR_LOG(LDBG_1,"EID %s not locally configured!", lisp_addr_to_char(deid)); goto err; } map = map_local_entry_mapping(map_loc_e); lisp_msg_put_mapping(mrep, map, MREQ_RLOC_PROBE(mreq_hdr) ? &uc->la: NULL); }else if (xtr->super.mode == RTR_MODE && (MREQ_SMR(mreq_hdr) || MREQ_RLOC_PROBE(mreq_hdr))){ lisp_msg_put_neg_mapping(mrep, deid, 0, ACT_NO_ACTION, A_NO_AUTHORITATIVE); } /* If packet is a Solicit Map Request, process it */ if (lisp_addr_lafi(seid) != LM_AFI_NO_ADDR && MREQ_SMR(mreq_hdr)) { if(tr_reply_to_smr(xtr,deid,seid) != GOOD) { goto err; } /* Return if RLOC probe bit is not set */ if (!MREQ_RLOC_PROBE(mreq_hdr)) { goto done; }; } } mrep_hdr = lisp_msg_hdr(mrep); MREP_RLOC_PROBE(mrep_hdr) = MREQ_RLOC_PROBE(mreq_hdr); MREP_NONCE(mrep_hdr) = MREQ_NONCE(mreq_hdr); /* SEND MAP-REPLY */ if (map_reply_fill_uconn(xtr, itr_rlocs, uc) != GOOD){ OOR_LOG(LDBG_1, "Couldn't send Map Reply, no itr_rlocs reachable"); goto err; } OOR_LOG(LDBG_1, "Sending %s", lisp_msg_hdr_to_char(mrep)); send_msg(&xtr->super, mrep, uc); done: glist_destroy(itr_rlocs); lisp_msg_destroy(mrep); lisp_addr_del(seid); lisp_addr_del(deid); return(GOOD); err: glist_destroy(itr_rlocs); lisp_msg_destroy(mrep); lisp_addr_del(seid); lisp_addr_del(deid); return(BAD); } static int tr_recv_info_nat(lisp_xtr_t *xtr, lbuf_t *buf, uconn_t *uc) { lisp_addr_t *inf_reply_eid, *inf_req_eid, *nat_lcaf_addr; void *info_nat_hdr, *info_nat_hdr_2; lbuf_t b; nonces_list_t *nonces_lst; timer_inf_req_argument *timer_arg; int len, ttl; glist_t *rtr_lst; map_local_entry_t *mle; /* local copy of the buf that can be modified */ b = *buf; info_nat_hdr = lisp_msg_pull_hdr(&b); if (INF_REQ_R_bit(info_nat_hdr) == INFO_REQUEST){ OOR_LOG(LDBG_1, "XTR received an Info Request. Discarting message"); return(BAD); } /* Check NONCE */ nonces_lst = htable_nonces_lookup(nonces_ht, INF_REQ_NONCE(info_nat_hdr)); if (!nonces_lst){ OOR_LOG(LDBG_2, " Nonce %"PRIx64" doesn't match any Info Request nonce. " "Discarding message!", INF_REQ_NONCE(info_nat_hdr)); return(BAD); } timer_arg = oor_timer_cb_argument(nonces_list_timer(nonces_lst)); mle = timer_arg->mle; lisp_msg_pull_auth_field(&b); info_nat_hdr_2 = lbuf_pull(&b, sizeof(info_nat_hdr_2_t)); /* Get EID prefix for the info reply and compare with the one of the info request*/ inf_reply_eid = lisp_addr_new(); len = lisp_addr_parse(lbuf_data(&b), inf_reply_eid); if (len <= 0) { lisp_addr_del(inf_reply_eid); return(BAD); } lbuf_pull(&b, len); lisp_addr_set_plen(inf_reply_eid, INF_REQ_2_EID_MASK(info_nat_hdr_2)); inf_req_eid = map_local_entry_eid(mle); if (lisp_addr_cmp(inf_reply_eid,inf_req_eid)!=0){ OOR_LOG(LDBG_2, "EID from info request and info reply are different (%s - %s)", lisp_addr_to_char(inf_req_eid),lisp_addr_to_char(inf_reply_eid)); lisp_addr_del(inf_reply_eid); return (BAD); } lisp_addr_del(inf_reply_eid); /* We obtain the key to use in the authentication process from the argument of the timer */ if (lisp_msg_check_auth_field(buf, timer_arg->ms->key) != GOOD) { OOR_LOG(LDBG_1, "Info Reply Message validation failed for EID %s with key " "%s. Stopping processing!", lisp_addr_to_char(inf_req_eid), timer_arg->ms->key); return (BAD); } nat_lcaf_addr = lisp_addr_new(); len = lisp_addr_parse(lbuf_data(&b), nat_lcaf_addr); if (len <= 0) { lisp_addr_del(nat_lcaf_addr); OOR_LOG(LDBG_2, "tr_recv_info_nat: Can not parse nat lcaf address"); return(BAD); } rtr_lst = nat_type_get_rtr_addr_lst(lcaf_addr_get_nat(lisp_addr_get_lcaf(nat_lcaf_addr))); if (tr_update_nat_info(xtr,mle,timer_arg->loct,rtr_lst) == GOOD){ /* Configure Encap Map Register */ program_encap_map_reg_of_loct_for_map(xtr, mle,timer_arg->loct); /* Reprogram time for next Info Request interval */ htable_nonces_reset_nonces_lst(nonces_ht,nonces_lst); ttl = ntohl(INF_REQ_2_TTL(info_nat_hdr_2)); oor_timer_start(nonces_lst->timer, ttl*60); OOR_LOG(LDBG_1,"Info Request of %s to %s from locator %s programmed in %d minutes.", lisp_addr_to_char(map_local_entry_eid(mle)), lisp_addr_to_char(timer_arg->ms->address), lisp_addr_to_char(locator_addr(timer_arg->loct)), ttl); } lisp_addr_del(nat_lcaf_addr); return (GOOD); } int tr_update_nat_info(lisp_xtr_t *xtr, map_local_entry_t *mle, locator_t *loct, glist_t *rtr_list) { glist_t *final_rtr_list; final_rtr_list = nat_select_rtrs(rtr_list); if (glist_size(final_rtr_list) == 0){ OOR_LOG(LDBG_1, "Info Reply Message doesn't have any compatible RTR"); glist_destroy(final_rtr_list); return (BAD); } mle_nat_info_update(mle, loct, final_rtr_list); /* Update forwarding info of the local entry*/ xtr->fwd_policy->updated_map_cache_inf(xtr->fwd_policy_dev_parm,xtr->rtrs); notify_datap_rm_fwd_from_entry(&(xtr->super),mcache_entry_eid(xtr->rtrs),FALSE); xtr->fwd_policy->updated_map_loc_inf(xtr->fwd_policy_dev_parm,mle); notify_datap_rm_fwd_from_entry(&(xtr->super),map_local_entry_eid(mle),TRUE); /* Update forwarding info of rtrs */ tr_update_fwd_info_rtrs(xtr); glist_destroy(final_rtr_list); return (GOOD); } void tr_update_fwd_info_rtrs(lisp_xtr_t *xtr) { lisp_addr_t addr, *rtr_addr; map_local_entry_t *mle; mapping_t *map; locator_t *rtr_loct; glist_t *rtr_addr_list; glist_entry_t *addr_it; map = mcache_entry_mapping(xtr->rtrs); /* Remove the list of rtr locators */ mapping_remove_locators(map); /* Regenerate rtr list using the information of local map entries */ local_map_db_foreach_entry(xtr->local_mdb,mle){ rtr_addr_list = mle_rtr_addr_list(mle); glist_for_each_entry(addr_it, rtr_addr_list){ rtr_addr = (lisp_addr_t *)glist_entry_data(addr_it); rtr_loct = locator_new_init(rtr_addr,UP,0,1,1,100,255,0); mapping_add_locator(map,rtr_loct); } glist_destroy(rtr_addr_list); }local_map_db_foreach_end; /* Update forwarding info of rtrs */ xtr->fwd_policy->updated_map_cache_inf(xtr->fwd_policy_dev_parm,xtr->rtrs); lisp_addr_ippref_from_char(FULL_IPv4_ADDRESS_SPACE,&addr); notify_datap_rm_fwd_from_entry(&(xtr->super),&addr,FALSE); } glist_t * nat_select_rtrs(glist_t * rtr_list) { glist_t *final_rtr_list = glist_new_managed((glist_del_fct)lisp_addr_del); lisp_addr_t *rtr_addr; addr_list_rm_not_compatible_addr(rtr_list, IPv4_SUPPORT); //TODO Select RTR process rtr_addr = (lisp_addr_t *)glist_first_data(rtr_list); if (rtr_addr){ glist_add(lisp_addr_clone(rtr_addr), final_rtr_list); } return (final_rtr_list); } int map_reply_fill_uconn(lisp_xtr_t *xtr, glist_t *itr_rlocs, uconn_t *uc) { lisp_addr_t *src_loc; int afi; if (laddr_list_get_addr(itr_rlocs, lisp_addr_ip_afi(&uc->la), &uc->ra) == GOOD){ return (GOOD); } if (lisp_addr_ip_afi(&uc->la) == AF_INET){ afi = AF_INET6; }else{ afi = AF_INET; } src_loc = ctrl_default_rloc(xtr->super.ctrl, afi); if (src_loc == NULL){ return (BAD); } if (laddr_list_get_addr(itr_rlocs, afi, &uc->ra) != GOOD){ return (BAD); } lisp_addr_copy(&uc->la, src_loc); return (GOOD); } static int handle_merge_semantics(lisp_xtr_t *xtr, mapping_t *rec_map) { lisp_addr_t *eid = NULL; mcache_entry_t *mce = NULL; mapping_t *map = NULL; eid = mapping_eid(rec_map); OOR_LOG(LDBG_1, "Merge-Semantics on, moving returned mapping to " "map-cache"); /* XXX, TODO: done thinking of lisp-re, MUST change to be more general */ /* Save the mapping returned by the map-notify in the mapping * cache */ mce = mcache_lookup(xtr->map_cache,eid); if(mce == NULL){ /* FIRST registration */ if (tr_mcache_add_mapping(xtr, rec_map) != GOOD) { mapping_del(rec_map); return(BAD); } /* for MC initialize the JIB */ /* if (lisp_addr_is_mc(eid) && !mapping_get_re_data(mcache_entry_mapping(mce))) { mapping_init_re_data(mcache_entry_mapping(mce)); } */ return (GOOD); } map = mcache_entry_mapping(mce); if (mapping_cmp(map, rec_map) != 0) { /* UPDATED rlocs */ OOR_LOG(LDBG_3, "Prefix %s already registered, updating locators", lisp_addr_to_char(eid)); mapping_update_locators(map,mapping_locators_lists(rec_map)); /* Update forward info*/ xtr->fwd_policy->updated_map_cache_inf(xtr->fwd_policy_dev_parm,mce); notify_datap_rm_fwd_from_entry(&(xtr->super),mcache_entry_eid(mce),FALSE); program_mce_rloc_probing(xtr, mce); } return(GOOD); } static int tr_recv_map_notify(lisp_xtr_t *xtr, lbuf_t *buf) { lisp_addr_t *eid; map_local_entry_t *map_loc_e; mapping_t *m, *local_map; void *hdr; locator_t *probed ; map_server_elt *ms; nonces_list_t *nonces_lst; oor_timer_t *timer; timer_map_reg_argument *timer_arg_mn; timer_encap_map_reg_argument *timer_arg_emn; int i, res = BAD; lbuf_t b; /* local copy */ b = *buf; hdr = lisp_msg_pull_hdr(&b); /* Check NONCE */ nonces_lst = htable_nonces_lookup(nonces_ht, MNTF_NONCE(hdr)); if (!nonces_lst){ OOR_LOG(LDBG_1, "No Map Register sent with nonce: %"PRIx64 " Discarding message!", MNTF_NONCE(hdr)); return(BAD); } timer = nonces_list_timer(nonces_lst); if (MNTF_I_BIT(hdr)==1){ OOR_LOG(LDBG_1,"Received Data Map Notify"); timer_arg_emn = (timer_encap_map_reg_argument *)oor_timer_cb_argument(timer); ms = timer_arg_emn->ms; if (MNTF_R_BIT(hdr)==1){ /* We subtract the RTR authentication field. Is not used in the authentication * calculation of the map notify.*/ // XXX Speculate that this field is removed by RTR so length is 0 lbuf_set_size(buf, lbuf_size(buf) - sizeof(auth_record_hdr_t)); } }else{ timer_arg_mn = (timer_map_reg_argument *)oor_timer_cb_argument(timer); ms = timer_arg_mn->ms; } res = lisp_msg_check_auth_field(buf, ms->key); if (res != GOOD){ OOR_LOG(LDBG_1, "Map-Notify message is invalid"); return(BAD); } lisp_msg_pull_auth_field(&b); for (i = 0; i < MNTF_REC_COUNT(hdr); i++) { m = mapping_new(); if (lisp_msg_parse_mapping_record(&b, m, &probed) != GOOD) { mapping_del(m); return(BAD); } eid = mapping_eid(m); map_loc_e = local_map_db_lookup_eid_exact(xtr->local_mdb, eid); if (!map_loc_e) { OOR_LOG(LDBG_1, "Map-Notify confirms registration of UNKNOWN EID %s." " Dropping!", lisp_addr_to_char(eid)); continue; } local_map = map_local_entry_mapping(map_loc_e); OOR_LOG(LDBG_1, "Map-Notify message confirms correct registration of %s." "Programing next Map-Register in %d seconds",lisp_addr_to_char(eid), MAP_REGISTER_INTERVAL); /* MULTICAST MERGE SEMANTICS */ if (lisp_addr_is_mc(eid) && mapping_cmp(local_map, m) != 0) { handle_merge_semantics(xtr, m); } mapping_del(m); htable_nonces_reset_nonces_lst(nonces_ht,nonces_lst); oor_timer_start(timer,MAP_REGISTER_INTERVAL); } return(GOOD); } int handle_map_cache_miss(lisp_xtr_t *xtr, lisp_addr_t *requested_eid, lisp_addr_t *src_eid) { mcache_entry_t *mce = mcache_entry_new(); mapping_t *m = NULL; oor_timer_t *timer; timer_map_req_argument *timer_arg; int ret; /* Install temporary, NOT active, mapping in map_cache */ m = mapping_new_init(requested_eid); mapping_set_action(m, ACT_NATIVE_FWD); mcache_entry_init(mce, m); /* Precalculate routing information */ if (xtr->fwd_policy->init_map_cache_policy_inf(xtr->fwd_policy_dev_parm,mce) != GOOD){ OOR_LOG(LWRN, "handle_map_cache_miss: Couldn't initiate routing info for map cache entry %s!. Discarding it.", lisp_addr_to_char(requested_eid)); mcache_entry_del(mce); return(BAD); } if (mcache_add_entry(xtr->map_cache, requested_eid, mce) != GOOD) { OOR_LOG(LWRN, "Couln't install temporary map cache entry for %s!", lisp_addr_to_char(requested_eid)); mcache_entry_del(mce); return(BAD); } timer_arg = timer_map_req_arg_new_init(mce,src_eid); timer = oor_timer_with_nonce_new(MAP_REQUEST_RETRY_TIMER,xtr,send_map_request_retry_cb, timer_arg,(oor_timer_del_cb_arg_fn)timer_map_req_arg_free); htable_ptrs_timers_add(ptrs_to_timers_ht,mce,timer); ret = send_map_request_retry_cb(timer); if (ret == BAD){ // We mantain the entry in the cache with a small expiration time // During this expiration time the data plane will not interrupt the control plane mc_entry_start_expiration_timer2(xtr, mce, 10); } return(ret); } static glist_t * build_rloc_list(mapping_t *mapping) { glist_t *rlocs = glist_new(); locator_t *locator = NULL; lisp_addr_t *loc_addr = NULL; if (glist_size(mapping_locators_lists(mapping)) == 0){ return (rlocs); } mapping_foreach_active_locator(mapping, locator){ loc_addr = locator_addr(locator); glist_add_tail(loc_addr,rlocs); }mapping_foreach_active_locator_end; return(rlocs); } static int build_and_send_smr_mreq(lisp_xtr_t *xtr, mapping_t *smap, lisp_addr_t *deid, lisp_addr_t *drloc) { uconn_t uc; lbuf_t * b = NULL; lisp_addr_t *seid = NULL; lisp_addr_t *srloc = NULL; void *hdr = NULL; glist_t *itr_rlocs = NULL; int res = GOOD; seid = mapping_eid(smap); itr_rlocs = build_rloc_list(smap); /* build Map-Request */ b = lisp_msg_mreq_create(seid, itr_rlocs, deid); if (b == NULL){ lisp_msg_destroy(b); return (BAD); } hdr = lisp_msg_hdr(b); MREQ_SMR(hdr) = 1; OOR_LOG(LDBG_1, "%s, itr-rlocs: %s, src-eid: %s, req-eid: %s ", lisp_msg_hdr_to_char(b), laddr_list_to_char(itr_rlocs), lisp_addr_to_char(seid), lisp_addr_to_char(deid)); glist_destroy(itr_rlocs); srloc = ctrl_default_rloc(xtr->super.ctrl, lisp_addr_ip_afi(drloc)); if (!srloc) { OOR_LOG(LDBG_2, "No compatible RLOC was found to send SMR Map-Request " "for local EID %s", lisp_addr_to_char(seid)); lisp_msg_destroy(b); return(BAD); } uconn_init(&uc, LISP_CONTROL_PORT, LISP_CONTROL_PORT, srloc, drloc); res = send_msg(&xtr->super, b, &uc); lisp_msg_destroy(b); return(res); } /* solicit SMRs for 'src_map' to all locators of 'dst_map'*/ static int build_and_send_smr_mreq_to_map(lisp_xtr_t *xtr, mapping_t *src_map, mapping_t *dst_map) { lisp_addr_t *deid = NULL, *drloc = NULL; locator_t *loct = NULL; deid = mapping_eid(dst_map); mapping_foreach_active_locator(dst_map, loct){ if (loct->state == UP){ drloc = locator_addr(loct); build_and_send_smr_mreq(xtr, src_map, deid, drloc); } }mapping_foreach_active_locator_end; return(GOOD); } static int send_all_smr_cb(oor_timer_t *timer) { send_all_smr_and_mreg((lisp_xtr_t *)oor_timer_cb_argument(timer)); return(GOOD); } /* Send a solicit map request for each rloc of all eids in the map cache * database */ static void send_all_smr_and_mreg(lisp_xtr_t *xtr) { map_local_entry_t * map_loc_e = NULL; glist_t * map_loc_e_list = NULL; // glist_entry_t * it = NULL; OOR_LOG(LDBG_1,"\n**** Re-Register and send SMRs for mappings with updated " "RLOCs ****"); /* Get a list of mappings that require smrs */ map_loc_e_list = get_map_local_entry_to_smr(xtr); /* Send map register and SMR request for each mapping */ //glist_dump(map_loc_e_list,(glist_to_char_fct)map_local_entry_to_char,LDBG_1); glist_for_each_entry(it, map_loc_e_list) { map_loc_e = (map_local_entry_t *)glist_entry_data(it); send_smr_and_mreg_for_locl_mapping(xtr, map_loc_e); } glist_destroy(map_loc_e_list); OOR_LOG(LDBG_2,"*** Finished sending notifications ***\n"); } void send_smr_and_mreg_for_locl_mapping(lisp_xtr_t *xtr, map_local_entry_t *map_loc_e) { mcache_entry_t * mce; mapping_t * mcache_map; mapping_t * map; glist_entry_t * it_pitr; lisp_addr_t * pitr_addr; lisp_addr_t * eid; assert(map_loc_e); map = map_local_entry_mapping(map_loc_e); eid = mapping_eid(map); program_map_register_for_mapping(xtr, map_loc_e); OOR_LOG(LDBG_1, "Start SMR for local EID %s", lisp_addr_to_char(eid)); /* TODO: spec says SMRs should be sent only to peer ITRs that sent us * traffic in the last minute. Should change this in the future*/ /* XXX: works ONLY with IP */ mcache_foreach_active_entry_in_ip_eid_db(xtr->map_cache, eid, mce) { mcache_map = mcache_entry_mapping(mce); build_and_send_smr_mreq_to_map(xtr, map, mcache_map); } mcache_foreach_active_entry_in_ip_eid_db_end; /* SMR proxy-itr */ OOR_LOG(LDBG_1, "Sending SMRs to PITRs"); glist_for_each_entry(it_pitr, xtr->pitrs){ pitr_addr = (lisp_addr_t *)glist_entry_data(it_pitr); build_and_send_smr_mreq(xtr, map, eid, pitr_addr); } } static int smr_invoked_map_request_cb(oor_timer_t *timer) { timer_map_req_argument *timer_arg = (timer_map_req_argument *)oor_timer_cb_argument(timer); nonces_list_t *nonces_list = oor_timer_nonces(timer); lisp_xtr_t *xtr = oor_timer_owner(timer); uint64_t nonce; lisp_addr_t *deid; if (nonces_list_size(nonces_list) - 1 < OOR_MAX_SMR_RETRANSMIT) { nonce = nonce_new(); if (send_smr_invoked_map_request(xtr, timer_arg->src_eid, timer_arg->mce, nonce) != GOOD){ return (BAD); } htable_nonces_insert(nonces_ht, nonce, nonces_list); oor_timer_start(timer, OOR_INITIAL_SMR_TIMEOUT); return (GOOD); } else { deid = mapping_eid(mcache_entry_mapping(timer_arg->mce)); OOR_LOG(LDBG_1,"SMR: No Map Reply for EID %s. Removing entry ...", lisp_addr_to_char(deid)); tr_mcache_remove_entry(xtr,timer_arg->mce); return (BAD); } } static int send_smr_invoked_map_request(lisp_xtr_t *xtr, lisp_addr_t *src_eid, mcache_entry_t *mce, uint64_t nonce) { uconn_t uc; lisp_addr_t *drloc, *srloc; struct lbuf *b = NULL; void *hdr = NULL; mapping_t *m = NULL; lisp_addr_t *deid = NULL, *s_in_addr = NULL, *d_in_addr = NULL; glist_t *rlocs = NULL; int afi, ret ; m = mcache_entry_mapping(mce); deid = mapping_eid(m); afi = lisp_addr_ip_afi(deid); OOR_LOG(LDBG_1,"SMR: Map-Request for EID: %s",lisp_addr_to_char(deid)); /* BUILD Map-Request */ /* no source EID and mapping, so put default control rlocs */ rlocs = ctrl_default_rlocs(xtr->super.ctrl); b = lisp_msg_mreq_create(src_eid, rlocs, mapping_eid(m)); if (b == NULL){ OOR_LOG(LWRN, "send_smr_invoked_map_request: Couldn't create map request message"); glist_destroy(rlocs); return (BAD); } hdr = lisp_msg_hdr(b); MREQ_SMR_INVOKED(hdr) = 1; MREQ_NONCE(hdr) = nonce; /* we could put anything here. Still, better put something that * makes a bit of sense .. */ s_in_addr = local_map_db_get_main_eid(xtr->local_mdb, afi); d_in_addr = deid; /* If we don't have a source EID as an RTR, we use an RLOC. May be, RTR could have a loopback EID address */ if (s_in_addr == NULL){ s_in_addr = ctrl_default_rloc(ctrl_dev_get_ctrl_t(&(xtr->super)),afi); if (s_in_addr == NULL){ OOR_LOG(LDBG_1,"SMR: Couldn't generate Map-Request for EID: %s. No source inner ip address available)", lisp_addr_to_char(deid)); return (BAD); } } /* SEND */ OOR_LOG(LDBG_1, "%s, itr-rlocs:%s src-eid: %s, req-eid: %s", lisp_msg_hdr_to_char(b), laddr_list_to_char(rlocs), lisp_addr_to_char(src_eid), lisp_addr_to_char(deid)); /* Encapsulate messgae and send it to the map resolver */ lisp_msg_encap(b, LISP_CONTROL_PORT, LISP_CONTROL_PORT, s_in_addr, d_in_addr); srloc = NULL; drloc = get_map_resolver(xtr); if (!drloc){ glist_destroy(rlocs); lisp_msg_destroy(b); return (BAD); } uconn_init(&uc, LISP_CONTROL_PORT, LISP_CONTROL_PORT, srloc, drloc); ret = send_msg(&xtr->super, b, &uc); glist_destroy(rlocs); lisp_msg_destroy(b); return (ret); } static int program_smr(lisp_xtr_t *xtr, int time) { OOR_LOG(LDBG_1,"Reprograming SMR in %d seconds",time); if (!xtr->smr_timer) { xtr->smr_timer = oor_timer_create(SMR_TIMER); oor_timer_init(xtr->smr_timer, xtr, send_all_smr_cb, xtr, NULL,NULL); } oor_timer_start(xtr->smr_timer, time); return(GOOD); } static int send_map_request_retry_cb(oor_timer_t *timer) { timer_map_req_argument *timer_arg = (timer_map_req_argument *)oor_timer_cb_argument(timer); nonces_list_t *nonces_list = oor_timer_nonces(timer); lisp_xtr_t *xtr = oor_timer_owner(timer); uint64_t nonce; lisp_addr_t *deid; int retries = nonces_list_size(nonces_list); deid = mapping_eid (mcache_entry_mapping(timer_arg->mce)); if (retries - 1 < xtr->map_request_retries) { if (retries > 0) { OOR_LOG(LDBG_1, "Retransmitting Map Request for EID: %s (%d retries)", lisp_addr_to_char(deid), retries); } nonce = nonce_new(); if (build_and_send_encap_map_request(xtr, timer_arg->src_eid, timer_arg->mce, nonce) != GOOD){ return (BAD); } htable_nonces_insert(nonces_ht, nonce, nonces_list); oor_timer_start(timer, OOR_INITIAL_MRQ_TIMEOUT); return (GOOD); } else { OOR_LOG(LDBG_1, "No Map-Reply for EID %s after %d retries. Aborting!", lisp_addr_to_char(deid), retries -1 ); /* When removing mce, all timers associated to it are canceled */ tr_mcache_remove_entry(xtr,timer_arg->mce); return (ERR_NO_REPLY); } } /* Sends Encap Map-Request for EID in 'mce' and sets-up a retry timer */ static int build_and_send_encap_map_request(lisp_xtr_t *xtr, lisp_addr_t *seid, mcache_entry_t *mce, uint64_t nonce) { uconn_t uc; mapping_t *m = NULL; lisp_addr_t *deid = NULL; lisp_addr_t *drloc, *srloc; glist_t *rlocs = NULL; lbuf_t *b = NULL; void *mr_hdr = NULL; if (glist_size(xtr->map_resolvers) == 0){ OOR_LOG(LDBG_1, "Couldn't send encap map request: No map resolver configured"); return (BAD); } m = mcache_entry_mapping(mce); deid = mapping_eid(m); /* BUILD Map-Request */ // Rlocs to be used as ITR of the map req. rlocs = ctrl_default_rlocs(xtr->super.ctrl); OOR_LOG(LDBG_1, "locators for req: %s", laddr_list_to_char(rlocs)); b = lisp_msg_mreq_create(seid, rlocs, deid); if (b == NULL) { OOR_LOG(LDBG_1, "build_and_send_encap_map_request: Couldn't create map request message"); glist_destroy(rlocs); return(BAD); } mr_hdr = lisp_msg_hdr(b); MREQ_NONCE(mr_hdr) = nonce; OOR_LOG(LDBG_1, "%s, itr-rlocs:%s, src-eid: %s, req-eid: %s", lisp_msg_hdr_to_char(b), laddr_list_to_char(rlocs), lisp_addr_to_char(seid), lisp_addr_to_char(deid)); glist_destroy(rlocs); /* Encapsulate message and send it to the map resolver */ lisp_msg_encap(b, LISP_CONTROL_PORT, LISP_CONTROL_PORT, seid, deid); srloc = NULL; drloc = get_map_resolver(xtr); if (!drloc){ lisp_msg_destroy(b); return (BAD); } uconn_init(&uc, LISP_CONTROL_PORT, LISP_CONTROL_PORT, srloc, drloc); send_msg(&xtr->super, b, &uc); lisp_msg_destroy(b); return(GOOD); } /* build and send generic map-register with one record * for each map server */ static int build_and_send_info_req(lisp_xtr_t * xtr, mapping_t * m, locator_t *loct, map_server_elt *ms, uint64_t nonce) { lbuf_t * b = NULL; void *hdr; lisp_addr_t *srloc, *drloc; uconn_t uc; b = lisp_msg_inf_req_create(m, ms->key_type); if (!b) { return(BAD); } hdr = lisp_msg_hdr(b); INF_REQ_NONCE(hdr) = nonce; if (lisp_msg_fill_auth_data(b, ms->key_type, ms->key) != GOOD) { return(BAD); } srloc = locator_addr(loct); drloc = ms->address; OOR_LOG(LDBG_1, "%s, EID: %s, MS: %s", lisp_msg_hdr_to_char(b), lisp_addr_to_char(mapping_eid(m)), lisp_addr_to_char(drloc)); uconn_init(&uc, LISP_CONTROL_PORT, LISP_CONTROL_PORT, srloc, drloc); send_msg(&xtr->super, b, &uc); lisp_msg_destroy(b); return(GOOD); } /* build and send generic map-register with one record * for each map server */ static int build_and_send_map_reg(lisp_xtr_t * xtr, mapping_t * m, map_server_elt *ms, uint64_t nonce) { lbuf_t * b = NULL; void * hdr = NULL; lisp_addr_t * drloc = NULL; uconn_t uc; b = lisp_msg_mreg_create(m, ms->key_type); if (!b) { return(BAD); } hdr = lisp_msg_hdr(b); MREG_PROXY_REPLY(hdr) = ms->proxy_reply; MREG_NONCE(hdr) = nonce; if (lisp_msg_fill_auth_data(b, ms->key_type, ms->key) != GOOD) { return(BAD); } drloc = ms->address; OOR_LOG(LDBG_1, "%s, EID: %s, MS: %s", lisp_msg_hdr_to_char(b), lisp_addr_to_char(mapping_eid(m)), lisp_addr_to_char(drloc)); uconn_init(&uc, LISP_CONTROL_PORT, LISP_CONTROL_PORT, NULL, drloc); send_msg(&xtr->super, b, &uc); lisp_msg_destroy(b); return(GOOD); } static int build_and_send_encap_map_reg(lisp_xtr_t * xtr, mapping_t * m, map_server_elt *ms, lisp_addr_t *etr_addr, lisp_addr_t *rtr_addr, uint64_t nonce) { lbuf_t * b; void * hdr; uconn_t uc; b = lisp_msg_nat_mreg_create(m, xtr->site_id, &xtr->xtr_id, ms->key_type); hdr = lisp_msg_hdr(b); MREG_NONCE(hdr) = nonce; MREG_PROXY_REPLY(hdr) = 1; MREG_IBIT(hdr) = 1; MREG_RBIT(hdr) = 1; if (lisp_addr_ip_afi(ms->address) != lisp_addr_ip_afi(etr_addr)){ OOR_LOG(LDBG_1, "build_and_send_ecm_map_reg: Map Server afi not compatible with selected" " local rloc (%s)", lisp_addr_to_char(etr_addr)); lisp_msg_destroy(b); return (BAD); } if (lisp_msg_fill_auth_data(b, ms->key_type, ms->key) != GOOD) { OOR_LOG(LDBG_2, "build_and_send_ecm_map_reg: Error filling the authentication data"); return(BAD); } lisp_msg_encap(b, LISP_CONTROL_PORT, LISP_CONTROL_PORT, etr_addr,ms->address); hdr = lisp_msg_ecm_hdr(b); /* TODO To use when implementing draft version 4 or higher */ //ECM_RTR_PROCESS_BIT(hdr) = 1; OOR_LOG(LDBG_1, "%s, Inner IP: %s -> %s, EID: %s, RTR: %s", lisp_msg_hdr_to_char(b), lisp_addr_to_char(etr_addr), lisp_addr_to_char(ms->address), lisp_addr_to_char(mapping_eid(m)), lisp_addr_to_char(rtr_addr)); uconn_init(&uc, LISP_DATA_PORT, LISP_CONTROL_PORT, etr_addr, rtr_addr); send_msg(&xtr->super, b, &uc); lisp_msg_destroy(b); return(GOOD); } static int map_register_cb(oor_timer_t *timer) { timer_map_reg_argument *timer_arg = oor_timer_cb_argument(timer); nonces_list_t *nonces_lst = oor_timer_nonces(timer); lisp_xtr_t *xtr = oor_timer_owner(timer); mapping_t *map = map_local_entry_mapping(timer_arg->mle); map_server_elt *ms = timer_arg->ms; uint64_t nonce; if ((nonces_list_size(nonces_lst) -1) < 10000){// xtr->probe_retries){ nonce = nonce_new(); if (build_and_send_map_reg(xtr, map, ms, nonce) != GOOD){ return (BAD); } if (nonces_list_size(nonces_lst) > 0) { OOR_LOG(LDBG_1,"Sent Retry Map-Register for mapping %s to %s " "(%d retries)", lisp_addr_to_char(mapping_eid(map)), lisp_addr_to_char(ms->address), nonces_list_size(nonces_lst)); } else { OOR_LOG(LDBG_1,"Sent Map-Register for mapping %s to %s " , lisp_addr_to_char(mapping_eid(map)), lisp_addr_to_char(ms->address)); } htable_nonces_insert(nonces_ht, nonce,nonces_lst); oor_timer_start(timer, OOR_INITIAL_MREG_TIMEOUT); return (GOOD); }else{ /* If we have reached maximum number of retransmissions, change remote * locator status */ /* Reprogram time for next Map Register interval */ htable_nonces_reset_nonces_lst(nonces_ht,nonces_lst); oor_timer_start(timer, MAP_REGISTER_INTERVAL); OOR_LOG(LWRN,"Map Register of %s to %s not received reply. Retry in %d seconds", lisp_addr_to_char(mapping_eid(map)), lisp_addr_to_char(ms->address), MAP_REGISTER_INTERVAL); return (BAD); } } int program_map_register(lisp_xtr_t *xtr) { void *map_local_entry_it; map_local_entry_t *mle; oor_timer_t *timer; timer_map_reg_argument *timer_arg; map_server_elt *ms; glist_entry_t *ms_it; if (glist_size(xtr->map_servers) == 0){ return (BAD); } local_map_db_foreach_entry(xtr->local_mdb, map_local_entry_it) { mle = (map_local_entry_t *)map_local_entry_it; /* Cancel timers associated to the map register of the local map entry */ stop_timers_of_type_from_obj(mle,MAP_REGISTER_TIMER,ptrs_to_timers_ht, nonces_ht); /* Configure map register for each map server */ glist_for_each_entry(ms_it,xtr->map_servers){ ms = (map_server_elt *)glist_entry_data(ms_it); timer_arg = timer_map_reg_argument_new_init(mle,ms); timer = oor_timer_with_nonce_new(MAP_REGISTER_TIMER, xtr, map_register_cb, timer_arg,(oor_timer_del_cb_arg_fn)timer_map_reg_arg_free); htable_ptrs_timers_add(ptrs_to_timers_ht, mle, timer); map_register_cb(timer); } } local_map_db_foreach_end; return(GOOD); } int program_map_register_for_mapping(lisp_xtr_t *xtr, map_local_entry_t *mle) { oor_timer_t *timer; timer_map_reg_argument *timer_arg; map_server_elt *ms; glist_entry_t *ms_it; if (glist_size(xtr->map_servers) == 0){ return (BAD); } /* Cancel timers associated to the map register of the local map entry */ stop_timers_of_type_from_obj(mle,MAP_REGISTER_TIMER,ptrs_to_timers_ht, nonces_ht); /* Configure map register for each map server */ glist_for_each_entry(ms_it,xtr->map_servers){ ms = (map_server_elt *)glist_entry_data(ms_it); timer_arg = timer_map_reg_argument_new_init(mle,ms); timer = oor_timer_with_nonce_new(MAP_REGISTER_TIMER, xtr, map_register_cb, timer_arg,(oor_timer_del_cb_arg_fn)timer_map_reg_arg_free); htable_ptrs_timers_add(ptrs_to_timers_ht, mle, timer); map_register_cb(timer); } return(GOOD); } static int encap_map_register_cb(oor_timer_t *timer) { timer_encap_map_reg_argument *timer_arg = oor_timer_cb_argument(timer); nonces_list_t *nonces_lst = oor_timer_nonces(timer); lisp_xtr_t *xtr = oor_timer_owner(timer); mapping_t *map = map_local_entry_mapping(timer_arg->mle); map_server_elt *ms = timer_arg->ms; lisp_addr_t *etr_addr = locator_addr(timer_arg->src_loct); lisp_addr_t *rtr_addr = timer_arg->rtr_rloc; uint64_t nonce; if ((nonces_list_size(nonces_lst) -1) < xtr->probe_retries){ nonce = nonce_new(); if (build_and_send_encap_map_reg(xtr, map, ms, etr_addr, rtr_addr, nonce) != GOOD){ return (BAD); } if (nonces_list_size(nonces_lst) > 0) { OOR_LOG(LDBG_1,"Sent Retry Encap Map-Register for mapping %s to MS %s from RLOC %s through RTR %s" "(%d retries)", lisp_addr_to_char(mapping_eid(map)), lisp_addr_to_char(ms->address), lisp_addr_to_char(etr_addr),lisp_addr_to_char(rtr_addr),nonces_list_size(nonces_lst)); } else { OOR_LOG(LDBG_1,"Sent Encap Map-Register for mapping %s to MS %s from RLOC %s through RTR %s" , lisp_addr_to_char(mapping_eid(map)),lisp_addr_to_char(ms->address), lisp_addr_to_char(etr_addr),lisp_addr_to_char(rtr_addr)); } htable_nonces_insert(nonces_ht, nonce,nonces_lst); oor_timer_start(timer, OOR_INITIAL_MREG_TIMEOUT); return (GOOD); }else{ /* If we have reached maximum number of retransmissions, change remote * locator status */ /* Reprogram time for next Map Register interval */ htable_nonces_reset_nonces_lst(nonces_ht,nonces_lst); oor_timer_start(timer, MAP_REGISTER_INTERVAL); OOR_LOG(LDBG_1,"Encap Map-Register for mapping %s to MS %s from RLOC %s through RTR %s not received reply." " Retry in %d seconds", lisp_addr_to_char(mapping_eid(map)),lisp_addr_to_char(ms->address), lisp_addr_to_char(etr_addr),lisp_addr_to_char(rtr_addr), MAP_REGISTER_INTERVAL); return (BAD); } } int program_encap_map_reg_of_loct_for_map(lisp_xtr_t *xtr, map_local_entry_t *mle, locator_t *src_loct) { oor_timer_t *timer; timer_encap_map_reg_argument *timer_arg; map_server_elt *ms; glist_t *timers_lst, *rtr_addr_lst; glist_entry_t *ms_it, *timers_it, *rtr_it; lisp_addr_t *rtr_addr; if (glist_size(xtr->map_servers) == 0){ return (BAD); } /* * We configure the timers using the map_local_entry_t pointer instead of locator * as we want to isolate locatars form timers */ /* Cancel timers associated to encap map register associated to the locator */ timers_lst = htable_ptrs_timers_get_timers_of_type_from_obj(ptrs_to_timers_ht, mle, ENCAP_MAP_REGISTER_TIMER); glist_for_each_entry(timers_it,timers_lst){ timer = (oor_timer_t *)glist_entry_data(timers_it); timer_arg = oor_timer_cb_argument(timer); if(src_loct == timer_arg->src_loct){ stop_timer_from_obj(mle,timer,ptrs_to_timers_ht, nonces_ht); // Continue processing as it could be more than one map server, RTR } } glist_destroy(timers_lst); /* Configure encap map register for each RTR and MS*/ rtr_addr_lst = mle_rtr_addr_list(mle); glist_for_each_entry(rtr_it,rtr_addr_lst){ rtr_addr = (lisp_addr_t *)glist_entry_data(rtr_it); glist_for_each_entry(ms_it,xtr->map_servers){ ms = (map_server_elt *)glist_entry_data(ms_it); timer_arg = timer_encap_map_reg_argument_new_init(mle,ms,src_loct,rtr_addr); timer = oor_timer_with_nonce_new(ENCAP_MAP_REGISTER_TIMER, xtr, encap_map_register_cb, timer_arg,(oor_timer_del_cb_arg_fn)timer_encap_map_reg_arg_free); htable_ptrs_timers_add(ptrs_to_timers_ht, mle, timer); encap_map_register_cb(timer); } } glist_destroy(rtr_addr_lst); return(GOOD); } static int info_request_cb(oor_timer_t *timer) { timer_inf_req_argument *timer_arg = oor_timer_cb_argument(timer); nonces_list_t *nonces_lst = oor_timer_nonces(timer); lisp_xtr_t *xtr = oor_timer_owner(timer); mapping_t *map = map_local_entry_mapping(timer_arg->mle); locator_t *loct = timer_arg->loct; map_server_elt *ms = timer_arg->ms; uint64_t nonce; if ((nonces_list_size(nonces_lst) -1) < xtr->map_request_retries){ nonce = nonce_new(); if (nonces_list_size(nonces_lst) > 0) { OOR_LOG(LDBG_1,"Sent Info Request retry for mapping %s to %s from locator %s" "(%d retries)", lisp_addr_to_char(mapping_eid(map)), lisp_addr_to_char(ms->address), lisp_addr_to_char(locator_addr(loct)), nonces_list_size(nonces_lst)); } else { timer_encap_map_reg_stop_using_locator(timer_arg->mle, loct); OOR_LOG(LDBG_1,"Sent Info Request for mapping %s to %s from locator %s", lisp_addr_to_char(mapping_eid(map)),lisp_addr_to_char(ms->address), lisp_addr_to_char(locator_addr(loct))); } if (build_and_send_info_req(xtr, map, loct, ms, nonce) != GOOD){ return (BAD); } htable_nonces_insert(nonces_ht, nonce,nonces_lst); oor_timer_start(timer, OOR_INITIAL_INF_REQ_TIMEOUT); return (GOOD); }else{ /* We reached maximum number of retransmissions */ /* Reprogram time for next Info Request interval */ htable_nonces_reset_nonces_lst(nonces_ht,nonces_lst); oor_timer_start(timer, OOR_SLEEP_INF_REQ_TIMEOUT); OOR_LOG(LWRN,"Info Request of %s to %s from locator %s not received reply. Retry in %d seconds", lisp_addr_to_char(mapping_eid(map)), lisp_addr_to_char(ms->address), lisp_addr_to_char(locator_addr(loct)), OOR_SLEEP_INF_REQ_TIMEOUT); return (BAD); } } int program_info_req_per_loct(lisp_xtr_t *xtr, map_local_entry_t *mle, locator_t *loct) { oor_timer_t *timer; timer_inf_req_argument *timer_arg; map_server_elt *ms; glist_entry_t *ms_it; if (glist_size(xtr->map_servers) == 0){ return (BAD); } /* Program info request for each Map Server */ glist_for_each_entry(ms_it,xtr->map_servers){ ms = (map_server_elt *)glist_entry_data(ms_it); timer_arg = timer_inf_req_argument_new_init(mle,loct,ms); timer = oor_timer_with_nonce_new(INFO_REQUEST_TIMER, xtr, info_request_cb, timer_arg,(oor_timer_del_cb_arg_fn)timer_inf_req_arg_free); htable_ptrs_timers_add(ptrs_to_timers_ht, mle, timer); oor_timer_start(timer, OOR_INF_REQ_HANDOVER_TIMEOUT); } return(GOOD); } int program_initial_info_request_process(lisp_xtr_t *xtr) { void *map_local_entry_it; oor_timer_t *timer; timer_inf_req_argument *timer_arg; map_local_entry_t *mle; mapping_t *map; locator_t *loct; map_server_elt *ms; glist_entry_t *ms_it; if (glist_size(xtr->map_servers) == 0){ return (BAD); } local_map_db_foreach_entry(xtr->local_mdb, map_local_entry_it) { mle = (map_local_entry_t *)map_local_entry_it; map = map_local_entry_mapping(mle); /* Cancel timers associated to the info request process of the local map entry */ stop_timers_of_type_from_obj(mle,INFO_REQUEST_TIMER,ptrs_to_timers_ht, nonces_ht); mapping_foreach_active_locator(map,loct){ glist_for_each_entry(ms_it,xtr->map_servers){ ms = (map_server_elt *)glist_entry_data(ms_it); timer_arg = timer_inf_req_argument_new_init(mle,loct,ms); timer = oor_timer_with_nonce_new(INFO_REQUEST_TIMER, xtr, info_request_cb, timer_arg,(oor_timer_del_cb_arg_fn)timer_inf_req_arg_free); htable_ptrs_timers_add(ptrs_to_timers_ht, mle, timer); info_request_cb(timer); } }mapping_foreach_active_locator_end; } local_map_db_foreach_end; return(GOOD); } static int rloc_probing_cb(oor_timer_t *timer) { timer_rloc_probe_argument *rparg = oor_timer_cb_argument(timer); nonces_list_t *nonces_lst = oor_timer_nonces(timer); lisp_xtr_t *xtr = oor_timer_owner(timer); mapping_t *map = mcache_entry_mapping(rparg->mce); locator_t *loct = rparg->locator; lisp_addr_t * drloc; uint64_t nonce; mcache_entry_t * mce; // XXX alopez -> What we have to do with ELP and probe bit drloc = xtr->fwd_policy->get_fwd_ip_addr(locator_addr(loct), ctrl_rlocs(xtr->super.ctrl)); if ((nonces_list_size(nonces_lst) -1) < xtr->probe_retries){ nonce = nonce_new(); if (rloc_probing(xtr, map,loct,nonce) != GOOD){ return (BAD); } if (nonces_list_size(nonces_lst) > 0) { OOR_LOG(LDBG_1,"Retry Map-Request Probe for locator %s and " "EID: %s (%d retries)", lisp_addr_to_char(drloc), lisp_addr_to_char(mapping_eid(map)), nonces_list_size(nonces_lst)); } else { OOR_LOG(LDBG_1,"Map-Request Probe for locator %s and " "EID: %s", lisp_addr_to_char(drloc), lisp_addr_to_char(mapping_eid(map))); } htable_nonces_insert(nonces_ht, nonce,nonces_lst); oor_timer_start(timer, xtr->probe_retries_interval); return (GOOD); }else{ /* If we have reached maximum number of retransmissions, change remote * locator status */ if (locator_state(loct) == UP) { locator_set_state(loct, DOWN); OOR_LOG(LDBG_1,"rloc_probing: No Map-Reply Probe received for locator" " %s and EID: %s -> Locator state changes to DOWN", lisp_addr_to_char(drloc), lisp_addr_to_char(mapping_eid(map))); /* [re]Calculate forwarding info if it has been a change * of status*/ mce = mcache_lookup_exact(xtr->map_cache,mapping_eid(map)); if (mce == NULL){ /* It is a PeTR RLOC */ mce = get_proxy_etrs_for_afi(xtr,lisp_addr_ip_afi(mapping_eid(map))); if ( rparg->mce != mce ){ OOR_LOG(LERR,"rloc_probing: No map cache entry for EID %s. It should never happend", lisp_addr_to_char(mapping_eid(map))); return (BAD); } } xtr->fwd_policy->updated_map_cache_inf(xtr->fwd_policy_dev_parm,mce); notify_datap_rm_fwd_from_entry(&(xtr->super),mcache_entry_eid(mce),FALSE); } /* Reprogram time for next probe interval */ htable_nonces_reset_nonces_lst(nonces_ht,nonces_lst); oor_timer_start(timer, xtr->probe_interval); OOR_LOG(LDBG_2,"Reprogramed RLOC probing of the locator %s of the EID %s " "in %d seconds", lisp_addr_to_char(drloc), lisp_addr_to_char(mapping_eid(map)), xtr->probe_interval); return (BAD); } } /* Send a Map-Request probe to check status of 'loc'. If the number of * retries without answer is higher than rloc_probe_retries. Change the status * of the 'loc' to down */ static int rloc_probing(lisp_xtr_t *xtr, mapping_t *map, locator_t *loc, uint64_t nonce) { uconn_t uc; lisp_addr_t * deid = NULL; lisp_addr_t * drloc = NULL; lisp_addr_t empty; lbuf_t * b = NULL; glist_t * rlocs = NULL; void * hdr = NULL; int ret; deid = mapping_eid(map); // XXX alopez -> What we have to do with ELP and probe bit drloc = xtr->fwd_policy->get_fwd_ip_addr(locator_addr(loc), ctrl_rlocs(xtr->super.ctrl)); lisp_addr_set_lafi(&empty, LM_AFI_NO_ADDR); rlocs = ctrl_default_rlocs(xtr->super.ctrl); b = lisp_msg_mreq_create(&empty, rlocs, deid); glist_destroy(rlocs); if (b == NULL){ return (BAD); } hdr = lisp_msg_hdr(b); MREQ_NONCE(hdr) = nonce; MREQ_RLOC_PROBE(hdr) = 1; uconn_init(&uc, LISP_CONTROL_PORT, LISP_CONTROL_PORT, NULL, drloc); ret = send_msg(&xtr->super, b, &uc); lisp_msg_destroy(b); return (ret); } static void program_rloc_probing(lisp_xtr_t *xtr, mcache_entry_t *mce, locator_t *loc, int time) { oor_timer_t *timer; timer_rloc_probe_argument *arg; arg = timer_rloc_probe_argument_new_init(mce,loc); timer = oor_timer_with_nonce_new(RLOC_PROBING_TIMER,xtr,rloc_probing_cb, arg,(oor_timer_del_cb_arg_fn)timer_rloc_probe_argument_free); htable_ptrs_timers_add(ptrs_to_timers_ht, mce, timer); oor_timer_start(timer, time); OOR_LOG(LDBG_2,"Programming probing of EID's %s locator %s (%d seconds)", lisp_addr_to_char(mapping_eid(mcache_entry_mapping(mce))), lisp_addr_to_char(locator_addr(loc)), time); } /* Program RLOC probing for each locator of the mapping */ static void program_mce_rloc_probing(lisp_xtr_t *xtr, mcache_entry_t *mce) { mapping_t *map; locator_t *locator; if (xtr->probe_interval == 0) { return; } /* Cancel previous RLOCs Probing associated to this mce */ stop_timers_of_type_from_obj(mce,RLOC_PROBING_TIMER,ptrs_to_timers_ht, nonces_ht); map = mcache_entry_mapping(mce); /* Start rloc probing for each locator of the mapping */ mapping_foreach_active_locator(map,locator){ // XXX alopez: Check if RLOB probing available for all LCAF. ELP RLOC Probing bit program_rloc_probing(xtr, mce, locator, xtr->probe_interval); }mapping_foreach_active_locator_end; } int tr_mcache_add_mapping(lisp_xtr_t *xtr, mapping_t *m) { mcache_entry_t *mce; mce = mcache_entry_new(); if (mce == NULL){ return (BAD); } mcache_entry_init(mce, m); /* Precalculate routing information */ if (xtr->fwd_policy->init_map_cache_policy_inf(xtr->fwd_policy_dev_parm,mce) != GOOD){ OOR_LOG(LWRN, "tr_mcache_add_mapping: Couldn't initiate routing info for map cache entry %s!. Discarding it.", lisp_addr_to_char(mapping_eid(m))); mcache_entry_del(mce); return(BAD); } if (mcache_add_entry(xtr->map_cache, mapping_eid(m), mce) != GOOD) { OOR_LOG(LDBG_1, "tr_mcache_add_mapping: Couldn't add map cache entry %s to data base!. Discarding it.", lisp_addr_to_char(mapping_eid(m))); mcache_entry_del(mce); return(BAD); } mcache_entry_set_active(mce, ACTIVE); /* Reprogramming timers */ mc_entry_start_expiration_timer(xtr, mce); /* RLOC probing timer */ program_mce_rloc_probing(xtr, mce); return(GOOD); } int tr_mcache_add_static_mapping(lisp_xtr_t *xtr, mapping_t *m) { mcache_entry_t *mce = NULL; mce = mcache_entry_new(); if (mce == NULL){ return(BAD); } mcache_entry_init_static(mce, m); /* Precalculate routing information */ if (xtr->fwd_policy->init_map_cache_policy_inf(xtr->fwd_policy_dev_parm,mce) != GOOD){ OOR_LOG(LWRN, "tr_mcache_add_static_mapping: Couldn't initiate routing info for map cache entry %s!. Discarding it.", lisp_addr_to_char(mapping_eid(m))); mcache_entry_del(mce); return(BAD); } if (mcache_add_entry(xtr->map_cache, mapping_eid(m), mce) != GOOD) { OOR_LOG(LDBG_1, "tr_mcache_add_static_mapping: Couldn't add static map cache entry %s to data base!. Discarding it.", lisp_addr_to_char(mapping_eid(m))); return(BAD); } program_mce_rloc_probing(xtr, mce); return(GOOD); } int tr_mcache_remove_entry(lisp_xtr_t *xtr, mcache_entry_t *mce) { void *data = NULL; lisp_addr_t *eid = mapping_eid(mcache_entry_mapping(mce)); notify_datap_rm_fwd_from_entry(&(xtr->super),eid,FALSE); data = mcache_remove_entry(xtr->map_cache, eid); mcache_entry_del(data); mcache_dump_db(xtr->map_cache, LDBG_3); return (GOOD); } mapping_t * tr_mcache_lookup_mapping(lisp_xtr_t *xtr, lisp_addr_t *laddr) { mcache_entry_t *mce = NULL; mce = mcache_lookup(xtr->map_cache, laddr); if ((mce == NULL) || (mce->active == NOT_ACTIVE)) { return (NULL); } else { return (mcache_entry_mapping(mce)); } } mapping_t * tr_mcache_lookup_mapping_exact(lisp_xtr_t *xtr, lisp_addr_t *laddr) { mcache_entry_t *mce = NULL; mce = mcache_lookup_exact(xtr->map_cache, laddr); if (!mce || (mce->active == NOT_ACTIVE)) { return (NULL); } else { return (mcache_entry_mapping(mce)); } } int xtr_if_link_update(oor_ctrl_dev_t *dev, char *iface_name, uint8_t status) { lisp_xtr_t * xtr = lisp_xtr_cast(dev); iface_locators * if_loct = NULL; locator_t * locator = NULL; map_local_entry_t * map_loc_e = NULL; glist_entry_t * it = NULL; glist_entry_t * it_m = NULL; if_loct = (iface_locators *)shash_lookup(xtr->iface_locators_table,iface_name); if (if_loct == NULL){ OOR_LOG(LDBG_2, "xtr_if_status_change: Iface %s not found in the list of ifaces for xTR device", iface_name); return (BAD); } /* Change the status of the affected locators */ glist_for_each_entry(it,if_loct->ipv4_locators){ locator = (locator_t *)glist_entry_data(it); locator_set_state(locator,status); } glist_for_each_entry(it,if_loct->ipv6_locators){ locator = (locator_t *)glist_entry_data(it); locator_set_state(locator,status); } /* Transition check */ if (if_loct->status_changed == TRUE){ if_loct->status_changed = FALSE; }else{ if_loct->status_changed = TRUE; } /* Recalculate forwarding info of the affected mappings */ glist_for_each_entry(it_m, if_loct->map_loc_entries){ map_loc_e = (map_local_entry_t *)glist_entry_data(it_m); xtr->fwd_policy->updated_map_loc_inf(xtr->fwd_policy_dev_parm,map_loc_e); notify_datap_rm_fwd_from_entry(&(xtr->super),map_local_entry_eid(map_loc_e),TRUE); } if (xtr->super.mode == RTR_MODE && xtr->all_locs_map) { xtr->fwd_policy->updated_map_loc_inf(xtr->fwd_policy_dev_parm,xtr->all_locs_map); notify_datap_reset_all_fwd(&(xtr->super)); } xtr_iface_event_signaling(xtr, if_loct); return (GOOD); } int xtr_if_addr_update(oor_ctrl_dev_t *dev, char *iface_name, lisp_addr_t *old_addr, lisp_addr_t *new_addr, uint8_t status) { lisp_xtr_t * xtr = lisp_xtr_cast(dev); iface_locators * if_loct = NULL; glist_t * loct_list = NULL; glist_t * locators = NULL; locator_t * locator = NULL; map_local_entry_t * map_loc_e = NULL; mapping_t * mapping = NULL; int afi = AF_UNSPEC; glist_entry_t * it = NULL; glist_entry_t * it_aux = NULL; glist_entry_t * it_m = NULL; lisp_addr_t ** prev_addr = NULL; if_loct = (iface_locators *)shash_lookup(xtr->iface_locators_table,iface_name); if (if_loct == NULL){ OOR_LOG(LDBG_2, "xtr_if_addr_update: Iface %s not found in the list of ifaces for xTR device", iface_name); return (BAD); } if (old_addr != NULL && lisp_addr_cmp(old_addr, new_addr) == 0){ return (GOOD); } afi = lisp_addr_lafi(new_addr) == LM_AFI_IP ? lisp_addr_ip_afi(new_addr) : AF_UNSPEC; switch(afi){ case AF_INET: locators = if_loct->ipv4_locators; prev_addr = &(if_loct->ipv4_prev_addr); break; case AF_INET6: locators = if_loct->ipv6_locators; prev_addr = &(if_loct->ipv6_prev_addr); break; default: OOR_LOG(LDBG_2, "xtr_if_addr_update: Afi of the new address not known"); return (BAD); } /* Update the address of the affected locators */ glist_for_each_entry_safe(it,it_aux,locators){ locator = (locator_t *)glist_entry_data(it); /* The locator was not active during init process */ if (lisp_addr_is_no_addr(locator_addr(locator))==TRUE){ /* If locator was not active, activate it */ map_loc_e = get_map_loc_ent_containing_loct_ptr(xtr->local_mdb,locator); if(map_loc_e == NULL){ continue; } /* Check if exists an active locator with the same address. * If it exists, remove not activated locator: Duplicated */ mapping = map_local_entry_mapping(map_loc_e); if (mapping_get_loct_with_addr(mapping,new_addr) != NULL){ OOR_LOG(LDBG_2, "xtr_if_addr_change: A non active locator is duplicated. Removing it"); loct_list = mapping_get_loct_lst_with_afi(mapping,LM_AFI_NO_ADDR,0); iface_locators_unattach_locator(xtr->iface_locators_table,locator); glist_remove_obj_with_ptr(locator,loct_list); continue; } /* Activate locator */ mapping_activate_locator(mapping,locator,new_addr); /* Recalculate forwarding info of the mappings with activated locators */ xtr->fwd_policy->updated_map_loc_inf(xtr->fwd_policy_dev_parm,map_loc_e); notify_datap_rm_fwd_from_entry(&(xtr->super),map_local_entry_eid(map_loc_e),TRUE); }else{ locator_clone_addr(locator,new_addr); } } /* Transition check */ /* prev_addr is the previous address before starting the transition process */ if (*prev_addr != NULL){ if (lisp_addr_cmp(*prev_addr, new_addr) == 0){ lisp_addr_del(*prev_addr); *prev_addr = NULL; } }else{ if (old_addr != NULL){ *prev_addr = lisp_addr_clone(old_addr); }else{ *prev_addr = lisp_addr_new_lafi(LM_AFI_NO_ADDR); } } /* Reorder locators */ glist_for_each_entry(it_m, if_loct->map_loc_entries){ map_loc_e = (map_local_entry_t *)glist_entry_data(it_m); mapping = map_local_entry_mapping(map_loc_e); mapping_sort_locators(mapping, new_addr); } if (xtr->super.mode == RTR_MODE && xtr->all_locs_map) { xtr->fwd_policy->updated_map_loc_inf(xtr->fwd_policy_dev_parm,xtr->all_locs_map); notify_datap_reset_all_fwd(&(xtr->super)); } xtr_iface_event_signaling(xtr, if_loct); return (GOOD); } int xtr_route_update(oor_ctrl_dev_t *dev, int command, char *iface_name ,lisp_addr_t *src_pref, lisp_addr_t *dst_pref, lisp_addr_t *gateway) { lisp_xtr_t * xtr = lisp_xtr_cast(dev); iface_locators * if_loct = NULL; if_loct = (iface_locators *)shash_lookup(xtr->iface_locators_table,iface_name); xtr_iface_event_signaling(xtr, if_loct); return (GOOD); } /* Configure SMR or info request depending on NAT traversal */ int xtr_iface_event_signaling(lisp_xtr_t * xtr, iface_locators * if_loct) { locator_t *loct; lisp_addr_t *loct_addr; map_local_entry_t *mle; glist_t *timers_lst; glist_entry_t *mle_it, *timer_it; mapping_t *map; oor_timer_t *timer; if(xtr->nat_aware == TRUE){ if (glist_size(if_loct->ipv4_locators) == 0){ return (GOOD); } loct = glist_first_data(if_loct->ipv4_locators); loct_addr = locator_addr(loct); if (lisp_addr_is_no_addr(loct_addr)==TRUE){ return (GOOD); } glist_for_each_entry(mle_it,if_loct->map_loc_entries){ mle = (map_local_entry_t *)glist_entry_data(mle_it); map = map_local_entry_mapping(mle); loct = mapping_get_loct_with_addr(map,loct_addr); /* Stop timers associtated with the locator */ timer_inf_req_stop_using_locator(mle, loct); timer_encap_map_reg_stop_using_locator(mle, loct); if (locator_state(loct) == UP){ OOR_LOG(LDBG_2,"xtr_if_event: Reconfiguring Info Request process for locator %s of " "the mapping %s.", lisp_addr_to_char(loct_addr), lisp_addr_to_char(mapping_eid(map))); program_info_req_per_loct(xtr, mle, loct); }else{ /* Reprogram all the Encap Map Registers of the other interfaces associated to the mapping * If status is up this process will be done when receiving the Info Reply*/ timers_lst = htable_ptrs_timers_get_timers_of_type_from_obj(ptrs_to_timers_ht, mle, ENCAP_MAP_REGISTER_TIMER); glist_for_each_entry(timer_it, timers_lst){ timer = (oor_timer_t *)glist_entry_data(timer_it); oor_timer_start(timer, OOR_INF_REQ_HANDOVER_TIMEOUT); } glist_destroy(timers_lst); } } }else{ program_smr(xtr, OOR_SMR_TIMEOUT); } return (GOOD); } static int xtr_recv_msg(oor_ctrl_dev_t *dev, lbuf_t *msg, uconn_t *uc) { int ret = 0; lisp_msg_type_e type; lisp_xtr_t *xtr = lisp_xtr_cast(dev); type = lisp_msg_type(msg); if (type == LISP_ENCAP_CONTROL_TYPE) { if (lisp_msg_ecm_decap(msg, &uc->rp) != GOOD) { return (BAD); } type = lisp_msg_type(msg); } switch (type) { case LISP_MAP_REPLY: ret = tr_recv_map_reply(xtr, msg, uc); break; case LISP_MAP_REQUEST: ret = tr_recv_map_request(xtr, msg, uc); break; case LISP_MAP_REGISTER: break; case LISP_MAP_NOTIFY: ret = tr_recv_map_notify(xtr, msg); break; case LISP_INFO_NAT: ret = tr_recv_info_nat(xtr, msg, uc); break; default: OOR_LOG(LDBG_1, "xTR: Unidentified type (%d) control message received", type); ret = BAD; break; } if (ret != GOOD) { OOR_LOG(LDBG_1,"xTR: Failed to process LISP control message"); return (BAD); } else { OOR_LOG(LDBG_3, "xTR: Completed processing of LISP control message"); return (ret); } } map_server_elt * map_server_elt_new_init(lisp_addr_t *address,uint8_t key_type, char *key, uint8_t proxy_reply) { map_server_elt *ms = NULL; ms = xzalloc(sizeof(map_server_elt)); if (ms == NULL){ OOR_LOG(LWRN,"Couldn't allocate memory for a map_server_elt structure"); return (NULL); } ms->address = lisp_addr_clone(address); ms->key_type = key_type; ms->key = strdup(key); ms->proxy_reply = proxy_reply; return (ms); } void map_server_elt_del (map_server_elt *map_server) { if (map_server == NULL){ return; } lisp_addr_del (map_server->address); free(map_server->key); free(map_server); } static inline lisp_xtr_t * lisp_xtr_cast(oor_ctrl_dev_t *dev) { /* make sure */ lm_assert(dev->ctrl_class == &xtr_ctrl_class); return(CONTAINER_OF(dev, lisp_xtr_t, super)); } static oor_ctrl_dev_t * xtr_ctrl_alloc() { lisp_xtr_t *xtr; xtr = xzalloc(sizeof(lisp_xtr_t)); return(&xtr->super); } static int xtr_ctrl_construct(oor_ctrl_dev_t *dev) { lisp_xtr_t * xtr = lisp_xtr_cast(dev); lisp_addr_t addr; mapping_t * pxtr_4_map, *pxtr_6_map, *rtr_map; OOR_LOG(LDBG_1, "Creating map cache and local mapping database"); /* set up databases */ xtr->local_mdb = local_map_db_new(); xtr->map_cache = mcache_new(); xtr->map_servers = glist_new_managed((glist_del_fct)map_server_elt_del); xtr->map_resolvers = glist_new_managed((glist_del_fct)lisp_addr_del); xtr->pitrs = glist_new_managed((glist_del_fct)lisp_addr_del); xtr->petrs_ipv4 = mcache_entry_new(); xtr->petrs_ipv6 = mcache_entry_new(); xtr->rtrs = mcache_entry_new(); xtr->iface_locators_table = shash_new_managed((free_value_fn_t)iface_locators_del); if (!xtr->local_mdb || !xtr->map_cache || !xtr->map_servers || !xtr->map_resolvers || !xtr->pitrs || !xtr->petrs_ipv4 || !xtr->petrs_ipv6 || !xtr->rtrs || !xtr->iface_locators_table) { return(BAD); } lisp_addr_ippref_from_char(FULL_IPv4_ADDRESS_SPACE, &addr); pxtr_4_map = mapping_new_init(&addr); mapping_set_action(pxtr_4_map,ACT_NATIVE_FWD); mcache_entry_init_static(xtr->petrs_ipv4, pxtr_4_map); lisp_addr_ippref_from_char(FULL_IPv6_ADDRESS_SPACE, &addr); pxtr_6_map = mapping_new_init(&addr); mapping_set_action(pxtr_6_map,ACT_NATIVE_FWD); mcache_entry_init_static(xtr->petrs_ipv6, pxtr_6_map); lisp_addr_set_lafi(&addr,LM_AFI_NO_ADDR); rtr_map = mapping_new(); mapping_set_eid(rtr_map,&addr); mcache_entry_init_static(xtr->rtrs, rtr_map); OOR_LOG(LDBG_1, "Finished Constructing xTR"); return(GOOD); } static void xtr_ctrl_destruct(oor_ctrl_dev_t *dev) { map_local_entry_t * map_loc_e = NULL; void *it = NULL; lisp_xtr_t *xtr = lisp_xtr_cast(dev); local_map_db_foreach_entry(xtr->local_mdb, it) { map_loc_e = (map_local_entry_t *)it; ctrl_unregister_mapping_dp(dev,map_local_entry_mapping(map_loc_e)); } local_map_db_foreach_end; if (xtr->fwd_policy_dev_parm != NULL){ xtr->fwd_policy->del_dev_policy_inf(xtr->fwd_policy_dev_parm); } shash_destroy(xtr->iface_locators_table); mcache_del(xtr->map_cache); mcache_entry_del(xtr->petrs_ipv4); mcache_entry_del(xtr->petrs_ipv6); mcache_entry_del(xtr->rtrs); local_map_db_del(xtr->local_mdb); glist_destroy(xtr->map_resolvers); glist_destroy(xtr->pitrs); glist_destroy(xtr->map_servers); if (xtr->super.mode == RTR_MODE && xtr->all_locs_map){ map_local_entry_del(xtr->all_locs_map); } oor_timer_stop(xtr->smr_timer); OOR_LOG(LDBG_1,"xTR device destroyed"); } static void xtr_ctrl_dealloc(oor_ctrl_dev_t *dev) { lisp_xtr_t *xtr = lisp_xtr_cast(dev); free(xtr); OOR_LOG(LDBG_1, "Freed xTR ..."); } static void xtr_run(lisp_xtr_t *xtr) { map_local_entry_t *map_loc_e; locator_t *loct; void *it; int num_eids = 0; if (xtr->super.mode == MN_MODE){ OOR_LOG(LDBG_1, "\nStarting xTR MN ...\n"); } if (xtr->super.mode == xTR_MODE){ OOR_LOG(LDBG_1, "\nStarting xTR ...\n"); } if (glist_size(xtr->map_servers) == 0) { OOR_LOG(LWRN, "**** NO MAP SERVER CONFIGURED. Your EID will not be registered in the Mapping System."); oor_timer_sleep(2); } if (glist_size(xtr->map_resolvers) == 0) { OOR_LOG(LCRIT, "**** NO MAP RESOLVER CONFIGURED. You can not request mappings to the mapping system"); oor_timer_sleep(2); } if (mcache_has_locators(xtr->petrs_ipv4) == FALSE && mcache_has_locators(xtr->petrs_ipv6) == FALSE) { OOR_LOG(LWRN, "No Proxy-ETR defined. Packets to non-LISP destinations " "will be forwarded natively (no LISP encapsulation). This " "may prevent mobility in some scenarios."); oor_timer_sleep(2); } else { xtr->fwd_policy->updated_map_cache_inf(xtr->fwd_policy_dev_parm,xtr->petrs_ipv4); notify_datap_rm_fwd_from_entry(&(xtr->super),mcache_entry_eid(xtr->petrs_ipv4),FALSE); xtr->fwd_policy->updated_map_cache_inf(xtr->fwd_policy_dev_parm,xtr->petrs_ipv6); notify_datap_rm_fwd_from_entry(&(xtr->super),mcache_entry_eid(xtr->petrs_ipv6),FALSE); } /* Check configured parameters when NAT-T activated. */ if (xtr->nat_aware == TRUE) { if (glist_size(xtr->map_servers) > 1) { OOR_LOG(LERR, "NAT aware on -> This version of OOR is limited to one Map Server."); exit_cleanup(); } if (glist_size(xtr->map_servers) == 1 && lisp_addr_ip_afi(((map_server_elt *)glist_first_data(xtr->map_servers))->address) != AF_INET) { OOR_LOG(LERR, "NAT aware on -> This version of OOR is limited to IPv4 Map Server."); exit_cleanup(); } if (glist_size(xtr->map_resolvers) > 0) { OOR_LOG(LINF, "NAT aware on -> No Map Resolver will be used."); glist_remove_all(xtr->map_resolvers); } if (xtr->probe_interval > 0) { xtr->probe_interval = 0; OOR_LOG(LINF, "NAT aware on -> disabling RLOC Probing"); } /* Set local locators to unreachable*/ local_map_db_foreach_entry(xtr->local_mdb, it) { map_loc_e = (map_local_entry_t *)it; num_eids++; if (num_eids > 1){ OOR_LOG(LERR, "NAT aware on -> Only one EID prefix supported."); exit_cleanup(); } mapping_foreach_locator(map_local_entry_mapping(map_loc_e),loct){ locator_set_R_bit(loct,0); /* We don't support LCAF in NAT */ if (lisp_addr_lafi(locator_addr(loct)) == LM_AFI_LCAF){ OOR_LOG(LERR, "NAT aware on -> This version of OOR doesn't support LCAF when NAT is enabled."); exit_cleanup(); } }mapping_foreach_locator_end; } local_map_db_foreach_end; xtr->fwd_policy->init_map_cache_policy_inf(xtr->fwd_policy_dev_parm,xtr->rtrs); } if (xtr->super.mode == MN_MODE){ /* Check number of EID prefixes */ if (local_map_db_num_ip_eids(xtr->local_mdb, AF_INET) > 1) { OOR_LOG(LERR, "OOR in mobile node mode only supports one IPv4 EID " "prefix and one IPv6 EID prefix"); exit_cleanup(); } if (local_map_db_num_ip_eids(xtr->local_mdb, AF_INET6) > 1) { OOR_LOG(LERR, "OOR in mobile node mode only supports one IPv4 EID " "prefix and one IPv6 EID prefix"); exit_cleanup(); } } OOR_LOG(LDBG_1, "****** Summary of the xTR configuration ******"); local_map_db_dump(xtr->local_mdb, LDBG_1); mcache_dump_db(xtr->map_cache, LDBG_1); map_servers_dump(xtr, LDBG_1); OOR_LOG(LDBG_1, "************* %13s ***************", "Map Resolvers"); glist_dump(xtr->map_resolvers, (glist_to_char_fct)lisp_addr_to_char, LDBG_1); proxy_etrs_dump(xtr, LDBG_1); OOR_LOG(LDBG_1, "************* %13s ***************", "Proxy-ITRs"); glist_dump(xtr->pitrs, (glist_to_char_fct)lisp_addr_to_char, LDBG_1); local_map_db_foreach_entry(xtr->local_mdb, it) { /* Register EID prefix to control */ map_loc_e = (map_local_entry_t *)it; if (ctrl_register_mapping_dp(&(xtr->super),map_local_entry_mapping(map_loc_e))!=GOOD){ OOR_LOG(LERR, "Couldn't register the mapping %s in the data plane", lisp_addr_to_char(map_local_entry_eid(map_loc_e))); exit_cleanup(); } /* Update forwarding info of the local mappings. When it is created during conf file process, * the local rlocs are not set. For this reason should be calculated again. It can not be removed * from the conf file process -> In future could appear fwd_map_info parameters*/ xtr->fwd_policy->updated_map_loc_inf(xtr->fwd_policy_dev_parm,map_loc_e); } local_map_db_foreach_end; if (xtr->nat_aware){ program_initial_info_request_process(xtr); }else{ /* Register to the Map-Server(s) */ program_map_register(xtr); /* SMR proxy-ITRs list to be updated with new mappings */ program_smr(xtr, 1); } /* RLOC Probing proxy ETRs */ program_mce_rloc_probing(xtr, xtr->petrs_ipv4); program_mce_rloc_probing(xtr, xtr->petrs_ipv6); } static void rtr_run(lisp_xtr_t *xtr) { mapping_t * mapping = NULL; OOR_LOG(LINF, "\nStarting RTR ...\n"); if (xtr->nat_aware == TRUE){ OOR_LOG(LERR, "An RTR cannot be behind a NAT box. Disable nat_traversal_support ..."); exit_cleanup(); } if (glist_size(xtr->map_resolvers) == 0) { OOR_LOG(LCRIT, "**** NO MAP RESOLVER CONFIGURES. You can not request mappings to the mapping system"); oor_timer_sleep(2); } OOR_LOG(LINF, "****** Summary of the configuration ******"); local_map_db_dump(xtr->local_mdb, LINF); mcache_dump_db(xtr->map_cache, LINF); if (xtr->all_locs_map) { mapping = map_local_entry_mapping(xtr->all_locs_map); OOR_LOG(LINF, "Active interfaces status"); xtr->fwd_policy->updated_map_loc_inf(xtr->fwd_policy_dev_parm,xtr->all_locs_map); OOR_LOG(LINF, "%s", mapping_to_char(mapping)); } } static void xtr_ctrl_run(oor_ctrl_dev_t *dev) { lisp_xtr_t *xtr = lisp_xtr_cast(dev); if (xtr->super.mode == xTR_MODE || xtr->super.mode == MN_MODE) { xtr_run(xtr); } else if (xtr->super.mode == RTR_MODE) { rtr_run(xtr); } } /* implementation of ctrl base functions */ ctrl_dev_class_t xtr_ctrl_class = { .alloc = xtr_ctrl_alloc, .construct = xtr_ctrl_construct, .dealloc = xtr_ctrl_dealloc, .destruct = xtr_ctrl_destruct, .run = xtr_ctrl_run, .recv_msg = xtr_recv_msg, .if_link_update = xtr_if_link_update, .if_addr_update = xtr_if_addr_update, .route_update = xtr_route_update, .get_fwd_entry = tr_get_forwarding_entry }; static void proxy_etrs_dump(lisp_xtr_t *xtr, int log_level) { locator_t *locator = NULL; OOR_LOG(log_level, "***************** Proxy ETRs List for IPv4 EIDs **********************"); OOR_LOG(log_level, "| Locator (RLOC) | Status | Priority/Weight |"); /* Start rloc probing for each locator of the mapping */ mapping_foreach_active_locator(mcache_entry_mapping(xtr->petrs_ipv4),locator){ OOR_LOG(log_level,"%s",locator_to_char(locator)); }mapping_foreach_active_locator_end; OOR_LOG(log_level, "***************** Proxy ETRs List for IPv6 EIDs **********************"); OOR_LOG(log_level, "| Locator (RLOC) | Status | Priority/Weight |"); /* Start rloc probing for each locator of the mapping */ mapping_foreach_active_locator(mcache_entry_mapping(xtr->petrs_ipv6),locator){ OOR_LOG(log_level,"%s",locator_to_char(locator)); }mapping_foreach_active_locator_end; } void map_servers_dump(lisp_xtr_t *xtr, int log_level) { map_server_elt * ms = NULL; glist_entry_t * it = NULL; char str[80]; size_t str_size = sizeof(str); if (glist_size(xtr->map_servers) == 0 || is_loggable(log_level) == FALSE) { return; } OOR_LOG(log_level, "******************* Map-Servers list ********************************"); OOR_LOG(log_level, "| Locator (RLOC) | Key Type |"); glist_for_each_entry(it, xtr->map_servers) { ms = (map_server_elt *)glist_entry_data(it); snprintf(str,str_size, "| %39s |", lisp_addr_to_char(ms->address)); if (ms->key_type == NO_KEY) { snprintf(str + strlen(str), str_size - strlen(str), " NONE |"); } else if (ms->key_type == HMAC_SHA_1_96) { snprintf(str + strlen(str), str_size - strlen(str), " HMAC-SHA-1-96 |"); } else { snprintf(str + strlen(str), str_size - strlen(str), " HMAC-SHA-256-128 |"); } OOR_LOG(log_level, "%s", str); } } //static int //rtr_get_src_and_dst_from_lcaf(lisp_xtr_t *xtr, lisp_addr_t *laddr, lisp_addr_t **src, // lisp_addr_t **dst) //{ // lcaf_addr_t *lcaf = NULL; // elp_node_t *elp_node, *next_elp; // glist_entry_t *it = NULL, *rit; // lisp_addr_t *raddr; // glist_t *rlocs; // // lcaf = lisp_addr_get_lcaf(laddr); // switch (lcaf_addr_get_type(lcaf)) { // case LCAF_EXPL_LOC_PATH: // /* lookup in the elp list the first RLOC to also pertain to the RTR */ // glist_for_each_entry(it, lcaf_elp_node_list(lcaf)) { // elp_node = glist_entry_data(it); // rlocs = ctrl_rlocs(xtr->super.ctrl, // lisp_addr_ip_afi(elp_node->addr)); // // glist_for_each_entry(rit, rlocs) { // raddr = glist_entry_data(rit); // if (lisp_addr_cmp(raddr, elp_node->addr) == 0) { // next_elp = glist_entry_data(glist_next(it)); // *dst = next_elp->addr; // *src = elp_node->addr; // return (GOOD); // } // } // } // return (GOOD); // default: // LMLOG(LDBG_1, "get_locator_from_lcaf: Type % not supported!, ", // lcaf_addr_get_type(lcaf)); // return (BAD); // } // static fwd_info_t * tr_get_fwd_entry(lisp_xtr_t *xtr, packet_tuple_t *tuple) { fwd_info_t *fwd_info; mcache_entry_t *mce = NULL, *mce_petrs = NULL; map_local_entry_t *map_loc_e = NULL; lisp_addr_t *eid, *simple_eid; lisp_addr_t *src_eid, *dst_eid; int iidmlen; uint8_t native_fwd = FALSE; fwd_info = fwd_info_new(); if(fwd_info == NULL){ OOR_LOG(LWRN, "tr_get_fwd_entry: Couldn't allocate memory for fwd_info_t"); return (NULL); } if (xtr->super.mode == xTR_MODE || xtr->super.mode == MN_MODE) { /* lookup local mapping for source EID */ map_loc_e = local_map_db_lookup_eid(xtr->local_mdb, &tuple->src_addr, FALSE); if (!map_loc_e){ // In VPP we should continue with the pocess in order to crete a route to the gatway address #ifndef VPP OOR_LOG(LDBG_3, "The source address %s is not a local EID. This should never happen", lisp_addr_to_char(&tuple->src_addr)); return (NULL); #else native_fwd = TRUE; fwd_info->neg_map_reply_act = ACT_NATIVE_FWD; eid = &tuple->src_addr; simple_eid = eid; #endif }else{ eid = map_local_entry_eid(map_loc_e); simple_eid = lisp_addr_get_ip_pref_addr(eid); if (lisp_addr_is_iid(eid)){ tuple->iid = lcaf_iid_get_iid(lisp_addr_get_lcaf(eid)); }else{ tuple->iid = 0; } } mce_petrs = get_proxy_etrs_for_afi(xtr, lisp_addr_ip_afi(simple_eid)); }else { /* When RTR, iid is obtained from the desencapsulated packet */ map_loc_e = xtr->all_locs_map; } if (tuple->iid > 0){ iidmlen = (lisp_addr_ip_afi(&tuple->src_addr) == AF_INET) ? 32: 128; src_eid = lisp_addr_new_init_iid(tuple->iid, &tuple->src_addr, iidmlen); dst_eid = lisp_addr_new_init_iid(tuple->iid, &tuple->dst_addr, iidmlen); }else{ src_eid = lisp_addr_clone(&tuple->src_addr); dst_eid = lisp_addr_clone(&tuple->dst_addr); } if (xtr->nat_aware){ mce = xtr->rtrs; }else{ mce = mcache_lookup(xtr->map_cache, dst_eid); } if (!mce) { /* No map cache entry, initiate map cache miss process */ OOR_LOG(LDBG_1, "No map cache for EID %s. Sending Map-Request!", lisp_addr_to_char(dst_eid)); handle_map_cache_miss(xtr, dst_eid, src_eid); /* Get the temporal mce created */ mce = mcache_lookup(xtr->map_cache, dst_eid); fwd_info->associated_entry = lisp_addr_clone(mcache_entry_eid(mce)); } else{ fwd_info->associated_entry = lisp_addr_clone(mcache_entry_eid(mce)); if (mcache_entry_active(mce) == NOT_ACTIVE) { OOR_LOG(LDBG_2, "Already sent Map-Request for %s. Waiting for reply!", lisp_addr_to_char(dst_eid)); } } if (!native_fwd){ xtr->fwd_policy->get_fwd_info(xtr->fwd_policy_dev_parm,map_loc_e,mce,mce_petrs,tuple, fwd_info); } /* Assign encapsulated that should be used */ fwd_info->encap = xtr->encap_type; lisp_addr_del(src_eid); lisp_addr_del(dst_eid); return (fwd_info); } static fwd_info_t * tr_get_forwarding_entry(oor_ctrl_dev_t *dev, packet_tuple_t *tuple) { lisp_xtr_t *xtr; xtr = lisp_xtr_cast(dev); return(tr_get_fwd_entry(xtr, tuple)); } /* * Return the list of locators from the local mappings containing addr * @param local_db Database where to search locators * @param addr Address used during the search * @return Generic list containg locator_t elements */ glist_t * get_local_locators_with_address(local_map_db_t *local_db, lisp_addr_t *addr) { glist_t * locators = NULL; locator_t * locator = NULL; map_local_entry_t * map_loc_e = NULL; mapping_t * mapping = NULL; void * it = NULL; locators = glist_new(); local_map_db_foreach_entry(local_db, it) { map_loc_e = (map_local_entry_t *)it; mapping = map_local_entry_mapping(map_loc_e); locator = mapping_get_loct_with_addr(mapping, addr); if (locator != NULL){ glist_add_tail(locator,locators); } } local_map_db_foreach_end; return (locators); } map_local_entry_t * get_map_loc_ent_containing_loct_ptr(local_map_db_t *local_db, locator_t *locator) { map_local_entry_t *map_loc_e; map_local_entry_t *map_loc_e_res = NULL; mapping_t *mapping = NULL; uint8_t found = FALSE; void *it = NULL; local_map_db_foreach_entry_with_break(local_db, it, found) { map_loc_e = (map_local_entry_t *)it; mapping = map_local_entry_mapping(map_loc_e); if (mapping_has_locator(mapping, locator) == TRUE){ found = TRUE; map_loc_e_res = map_loc_e; } } local_map_db_foreach_with_break_end(found); if (!map_loc_e_res){ OOR_LOG(LDBG_2, "get_map_loc_ent_containing_loct_ptr: No mapping has been found with locator %s", lisp_addr_to_char(locator_addr(locator))); } return (map_loc_e_res); } /* * Return the list of mappings that has experimented changes in their * locators. At the same time iface_locators status is reseted * @param xtr * @return glist_t with the list of modified mappings (mapping_t *) */ glist_t * get_map_local_entry_to_smr(lisp_xtr_t *xtr) { glist_t * map_loc_e_to_smr = glist_new();// glist_t * iface_locators_list = NULL; iface_locators * if_loct = NULL; glist_entry_t * it = NULL; glist_entry_t * it_loc = NULL; glist_t * locators[2] = {NULL,NULL}; map_local_entry_t * map_loc_e = NULL; locator_t * locator = NULL; int ctr; iface_locators_list = shash_values(xtr->iface_locators_table); glist_for_each_entry(it,iface_locators_list){ if_loct = (iface_locators *)glist_entry_data(it); /* Select affected locators */ if (if_loct->status_changed == TRUE){ locators[0] = if_loct->ipv4_locators; locators[1] = if_loct->ipv6_locators; }else{ if(if_loct->ipv4_prev_addr != NULL){ locators[0] = if_loct->ipv4_locators; } if(if_loct->ipv6_prev_addr != NULL){ locators[1] = if_loct->ipv6_locators; } } /* Reset iface_locators status */ if_loct->status_changed = FALSE; lisp_addr_del(if_loct->ipv4_prev_addr); lisp_addr_del(if_loct->ipv6_prev_addr); if_loct->ipv4_prev_addr = NULL; if_loct->ipv6_prev_addr = NULL; /* Select not repeated mappings*/ for (ctr=0 ; ctr<2 ; ctr++){ if (locators[ctr] != NULL){ glist_for_each_entry(it_loc,locators[ctr]){ locator = (locator_t *)glist_entry_data(it_loc); map_loc_e = get_map_loc_ent_containing_loct_ptr(xtr->local_mdb, locator); if (map_loc_e != NULL && glist_contain(map_loc_e, map_loc_e_to_smr) == FALSE){ glist_add(map_loc_e, map_loc_e_to_smr); } } } } } glist_destroy(iface_locators_list); return (map_loc_e_to_smr); } static lisp_addr_t * get_map_resolver(lisp_xtr_t *xtr) { glist_entry_t * it = NULL; lisp_addr_t * addr = NULL; oor_ctrl_t * ctrl = NULL; int supported_afis; ctrl = xtr->super.ctrl; supported_afis = ctrl_supported_afis(ctrl); if ((supported_afis & IPv6_SUPPORT) != 0){ glist_for_each_entry(it,xtr->map_resolvers){ addr = (lisp_addr_t *)glist_entry_data(it); if (lisp_addr_ip_afi(addr) == AF_INET6){ return (addr); } } } if ((supported_afis & IPv4_SUPPORT) != 0){ glist_for_each_entry(it,xtr->map_resolvers){ addr = (lisp_addr_t *)glist_entry_data(it); if (lisp_addr_ip_afi(addr) == AF_INET){ return (addr); } } } OOR_LOG (LDBG_1,"get_map_resolver: No map resolver reachable"); return (NULL); } mcache_entry_t * get_proxy_etrs_for_afi(lisp_xtr_t *xtr, int afi) { switch (afi){ case AF_INET: return (xtr->petrs_ipv4); case AF_INET6: return (xtr->petrs_ipv6); default: return (NULL); } } // XXX This function is only used while we don't have support of L bit of ELPs static int mapping_has_elp_with_l_bit(mapping_t *map) { glist_t *loct_list; locator_t *loct; lisp_addr_t *addr; elp_t * elp; elp_node_t *elp_node; glist_entry_t *loct_it; glist_entry_t *elp_n_it; loct_list = mapping_get_loct_lst_with_afi(map,LM_AFI_LCAF,LCAF_EXPL_LOC_PATH); if (loct_list == NULL){ return (FALSE); } glist_for_each_entry(loct_it,loct_list){ loct = (locator_t *)glist_entry_data(loct_it); addr = locator_addr(loct); elp = (elp_t *)lisp_addr_lcaf_addr(addr); glist_for_each_entry(elp_n_it,elp->nodes){ elp_node = (elp_node_t *)glist_entry_data(elp_n_it); if (elp_node->L == true){ return (TRUE); } } } return (FALSE); } timer_rloc_probe_argument * timer_rloc_probe_argument_new_init(mcache_entry_t *mce,locator_t *locator) { timer_rloc_probe_argument *timer_arg = xmalloc(sizeof(timer_rloc_probe_argument)); timer_arg->mce = mce; timer_arg->locator = locator; return (timer_arg); } void timer_rloc_probe_argument_free(timer_rloc_probe_argument *timer_arg){ free (timer_arg); } timer_map_req_argument * timer_map_req_arg_new_init(mcache_entry_t *mce,lisp_addr_t *src_eid) { timer_map_req_argument *timer_arg = xmalloc(sizeof(timer_map_req_argument)); timer_arg->mce = mce; timer_arg->src_eid = lisp_addr_clone(src_eid); return(timer_arg); } void timer_map_req_arg_free(timer_map_req_argument * timer_arg) { lisp_addr_del(timer_arg->src_eid); free(timer_arg); } timer_map_reg_argument * timer_map_reg_argument_new_init(map_local_entry_t *mle, map_server_elt *ms) { timer_map_reg_argument *timer_arg = xmalloc(sizeof(timer_map_reg_argument)); timer_arg->mle = mle; timer_arg->ms = ms; return(timer_arg); } void timer_map_reg_arg_free(timer_map_reg_argument * timer_arg) { free(timer_arg); } timer_encap_map_reg_argument * timer_encap_map_reg_argument_new_init(map_local_entry_t *mle, map_server_elt *ms, locator_t *src_loct, lisp_addr_t *rtr_addr) { timer_encap_map_reg_argument *timer_arg = xmalloc(sizeof(timer_encap_map_reg_argument)); timer_arg->mle = mle; timer_arg->ms = ms; timer_arg->src_loct = src_loct; timer_arg->rtr_rloc = lisp_addr_clone(rtr_addr); return(timer_arg); } void timer_encap_map_reg_arg_free(timer_encap_map_reg_argument * timer_arg) { lisp_addr_del(timer_arg->rtr_rloc); free(timer_arg); } /* * Stop all the timers of type ENCAP_MAP_REGISTER_TIMER associated with the map local entry * introduced as a parameter and using the specified locator. */ void timer_encap_map_reg_stop_using_locator(map_local_entry_t *mle, locator_t *loct) { glist_t *timers_lst; glist_entry_t *timer_it; oor_timer_t *timer; timer_encap_map_reg_argument * timer_arg; timers_lst = htable_ptrs_timers_get_timers_of_type_from_obj(ptrs_to_timers_ht, mle, ENCAP_MAP_REGISTER_TIMER); glist_for_each_entry(timer_it,timers_lst){ timer = (oor_timer_t *)glist_entry_data(timer_it); timer_arg = (timer_encap_map_reg_argument *)oor_timer_cb_argument(timer); if (timer_arg->src_loct == loct){ stop_timer_from_obj(mle,timer,ptrs_to_timers_ht,nonces_ht); } } glist_destroy(timers_lst); } timer_inf_req_argument * timer_inf_req_argument_new_init(map_local_entry_t *mle, locator_t *loct, map_server_elt *ms) { timer_inf_req_argument *timer_arg = xmalloc(sizeof(timer_inf_req_argument)); timer_arg->mle = mle; timer_arg->loct = loct; timer_arg->ms = ms; return (timer_arg); } void timer_inf_req_arg_free(timer_inf_req_argument * timer_arg) { free(timer_arg); } /* * Stop all the timers of type INFO_REQUEST_TIMER associated with the map local entry * introduced as a parameter and using the specified locator. */ void timer_inf_req_stop_using_locator(map_local_entry_t *mle, locator_t *loct) { glist_t *timers_lst; glist_entry_t *timer_it; oor_timer_t *timer; timer_inf_req_argument * timer_arg; timers_lst = htable_ptrs_timers_get_timers_of_type_from_obj(ptrs_to_timers_ht, mle, INFO_REQUEST_TIMER); glist_for_each_entry(timer_it,timers_lst){ timer = (oor_timer_t *)glist_entry_data(timer_it); timer_arg = (timer_inf_req_argument *)oor_timer_cb_argument(timer); if (timer_arg->loct == loct){ stop_timer_from_obj(mle,timer,ptrs_to_timers_ht,nonces_ht); } } glist_destroy(timers_lst); } oor-1.2.0/oor/control/lisp_xtr.h000066400000000000000000000077541313612200500166130ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef LISP_XTR_H_ #define LISP_XTR_H_ #include "oor_ctrl_device.h" #include "../defs.h" #include "../fwd_policies/fwd_policy.h" #include "../lib/shash.h" typedef enum tr_type { xTR_TYPE, RTR_TYPE, PITR_TYPE, PETR_TYPE } tr_type_e; typedef enum { PREV_DRAF_VER_4, AFTER_DRAFT_VER_4 }nat_version; typedef struct lisp_xtr { oor_ctrl_dev_t super; /* base "class" */ tr_type_e tr_type; /* xtr interface */ mapping_t *(*lookup_eid_map_cache)(lisp_addr_t *eid); mapping_t *(*lookup_eid_local_map_db)(lisp_addr_t *eid); int (*add_mapping_to_map_cache)(mapping_t *mapping); int (*add_mapping_to_local_map_db)(mapping_t *mapping); int map_request_retries; int probe_interval; int probe_retries; int probe_retries_interval; mcache_entry_t *petrs_ipv4; // PeTR used for IPv4 EIDs mcache_entry_t *petrs_ipv6; // PeTR used for IPv6 EIDs glist_t *pitrs; // /* DATABASES */ map_cache_db_t *map_cache; local_map_db_t *local_mdb; /* FWD POLICY */ fwd_policy_class *fwd_policy; void *fwd_policy_dev_parm; /* MAP RESOLVERS */ glist_t *map_resolvers; // /* MAP SERVERs */ glist_t *map_servers; // /* NAT */ int nat_aware; int nat_status; lisp_site_id site_id; lisp_xtr_id xtr_id; mcache_entry_t *rtrs; /* TIMERS */ oor_timer_t *smr_timer; /* MAPPING IFACE TO LOCATORS */ shash_t *iface_locators_table; /* Key: Iface name, Value: iface_locators */ /* LOCAL IFACE MAPPING */ /* in case of RTR can be used for outgoing load balancing */ map_local_entry_t *all_locs_map; oor_encap_t encap_type; } lisp_xtr_t; typedef struct map_server_elt_t { lisp_addr_t * address; uint8_t key_type; char * key; uint8_t proxy_reply; } map_server_elt; typedef struct _timer_rloc_prob_argument { mcache_entry_t *mce; locator_t *locator; } timer_rloc_probe_argument; typedef struct _timer_map_req_argument { mcache_entry_t *mce; lisp_addr_t *src_eid; } timer_map_req_argument; typedef struct _timer_map_reg_argument { map_local_entry_t *mle; map_server_elt *ms; } timer_map_reg_argument; typedef struct _timer_encap_map_reg_argument { map_local_entry_t *mle; map_server_elt *ms; locator_t *src_loct; lisp_addr_t *rtr_rloc; } timer_encap_map_reg_argument; typedef struct _timer_inf_req_argument { map_local_entry_t *mle; locator_t *loct; map_server_elt *ms; }timer_inf_req_argument; map_server_elt * map_server_elt_new_init(lisp_addr_t *address,uint8_t key_type, char *key, uint8_t proxy_reply); void map_server_elt_del (map_server_elt *map_server); void map_servers_dump(lisp_xtr_t *, int log_level); int program_map_register(lisp_xtr_t *xtr); void send_smr_and_mreg_for_locl_mapping(lisp_xtr_t *xtr, map_local_entry_t *map_loc_e); int tr_mcache_add_mapping(lisp_xtr_t *, mapping_t *); int tr_mcache_add_static_mapping(lisp_xtr_t *, mapping_t *); int tr_mcache_remove_entry(lisp_xtr_t *xtr, mcache_entry_t *mce); mapping_t *tr_mcache_lookup_mapping(lisp_xtr_t *, lisp_addr_t *); mapping_t *tr_mcache_lookup_mapping_exact(lisp_xtr_t *, lisp_addr_t *); oor_encap_t tr_get_encap_type(lisp_xtr_t *tr); #endif /* LISP_XTR_H_ */ oor-1.2.0/oor/control/oor_control.c000066400000000000000000000214151313612200500172670ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include #include #include "oor_control.h" #include "oor_ctrl_device.h" #include "../data-plane/data-plane.h" #include "../lib/oor_log.h" #include "../lib/routing_tables_lib.h" #include "../lib/mem_util.h" #include "../net_mgr/net_mgr.h" static void set_rlocs(oor_ctrl_t *ctrl); static void set_rlocs(oor_ctrl_t *ctrl) { iface_t *iface; glist_entry_t *iface_it; glist_remove_all(ctrl->rlocs); glist_remove_all(ctrl->ipv4_rlocs); glist_remove_all(ctrl->ipv6_rlocs); ctrl->supported_afis = NO_AFI_SUPPOT; glist_for_each_entry(iface_it,interface_list){ iface = (iface_t *)glist_entry_data(iface_it); if (iface->ipv4_address && !lisp_addr_is_no_addr(iface->ipv4_address)) { glist_add_tail(iface->ipv4_address, ctrl->ipv4_rlocs); glist_add_tail(iface->ipv4_address, ctrl->rlocs); } if (iface->ipv6_address && !lisp_addr_is_no_addr(iface->ipv6_address)) { glist_add_tail(iface->ipv6_address, ctrl->ipv6_rlocs); glist_add_tail(iface->ipv6_address, ctrl->rlocs); } } if (glist_size(ctrl->ipv4_rlocs) > 0){ ctrl->supported_afis = ctrl->supported_afis | IPv4_SUPPORT; } if (glist_size(ctrl->ipv6_rlocs) > 0){ ctrl->supported_afis = ctrl->supported_afis | IPv6_SUPPORT; } } oor_ctrl_t * ctrl_create() { oor_ctrl_t *ctrl = xzalloc(sizeof(oor_ctrl_t)); if (ctrl == NULL){ return (NULL); } ctrl->devices = glist_new_managed((glist_del_fct)ctrl_dev_destroy); ctrl->rlocs = glist_new(); ctrl->ipv4_rlocs = glist_new(); ctrl->ipv6_rlocs = glist_new(); ctrl->control_data_plane = control_dp_select(); OOR_LOG(LINF, "Control created!"); return (ctrl); } void ctrl_destroy(oor_ctrl_t *ctrl) { if (ctrl == NULL){ return; } glist_destroy(ctrl->devices); glist_destroy(ctrl->rlocs); glist_destroy(ctrl->ipv4_rlocs); glist_destroy(ctrl->ipv6_rlocs); if (ctrl->control_data_plane != NULL){ ctrl->control_data_plane->control_dp_uninit(ctrl); } free(ctrl); OOR_LOG(LDBG_1,"Lisp controller destroyed"); } int ctrl_init(oor_ctrl_t *ctrl) { if (ctrl->control_data_plane->control_dp_init(ctrl,smaster)!= GOOD){ OOR_LOG(LERR, "Could not initialize control plane"); return (BAD); } set_rlocs(ctrl); OOR_LOG(LDBG_1, "Control initialized"); return (GOOD); } void ctrl_update_iface_info(oor_ctrl_t *ctrl) { glist_entry_t * iface_it = NULL; iface_t * iface = NULL; uint8_t new_ifaces = FALSE; glist_for_each_entry(iface_it,interface_list){ iface = (iface_t *)glist_entry_data(iface_it); if (iface->ipv4_address && !lisp_addr_is_no_addr(iface->ipv4_address)){ if (glist_contain_using_cmp_fct(iface->ipv4_address, ctrl->ipv4_rlocs, (glist_cmp_fct)lisp_addr_cmp) == FALSE){ new_ifaces = TRUE; break; } } if (iface->ipv6_address && !lisp_addr_is_no_addr(iface->ipv6_address)){ if (glist_contain_using_cmp_fct(iface->ipv6_address, ctrl->ipv6_rlocs, (glist_cmp_fct)lisp_addr_cmp) == FALSE){ new_ifaces = TRUE; break; } } } if (new_ifaces == TRUE){ set_rlocs(ctrl); net_mgr->netm_reload_routes(RT_TABLE_MAIN,AF_INET); net_mgr->netm_reload_routes(RT_TABLE_MAIN,AF_INET6); } } void ctrl_if_addr_update(oor_ctrl_t *ctrl,iface_t *iface, lisp_addr_t *old_addr, lisp_addr_t *new_addr) { oor_ctrl_dev_t *dev; dev = glist_first_data(ctrl->devices); ctrl->control_data_plane->control_dp_updated_addr(ctrl, iface, old_addr, new_addr); /* TODO: should store and pass updated rloc in the future * The old, and current solution is to keep a mapping between mapping_t * and iface to identify mapping_t(s) for which SMRs have to be sent. In * the future this should be decoupled and only the affected RLOC should * be passed to ctrl_dev */ ctrl_dev_if_addr_update(dev, iface->iface_name, old_addr,new_addr, iface_status(iface)); set_rlocs(ctrl); } void ctrl_if_link_update(oor_ctrl_t *ctrl, iface_t *iface, int old_iface_index, int new_iface_index, int status) { oor_ctrl_dev_t *dev; dev = glist_first_data(ctrl->devices); ctrl->control_data_plane->control_dp_update_link(ctrl, iface, old_iface_index, new_iface_index, status); ctrl_dev_if_link_update(dev, iface->iface_name, status); set_rlocs(ctrl); } void ctrl_route_update(oor_ctrl_t *ctrl, int command, iface_t *iface,lisp_addr_t *src, lisp_addr_t *dst_pref, lisp_addr_t *gateway) { oor_ctrl_dev_t *dev; dev = glist_first_data(ctrl->devices); ctrl->control_data_plane->control_dp_updated_route(ctrl, command, iface, src, dst_pref, gateway); ctrl_dev_route_update(dev, command, iface->iface_name, src, dst_pref, gateway); set_rlocs(ctrl); } lisp_addr_t * ctrl_default_rloc(oor_ctrl_t *ctrl, int afi) { return (ctrl->control_data_plane->control_dp_get_default_addr(ctrl,afi)); } /* * Return the default control rlocs in a list that shoud be released * by the user. * @param ctrl Lisp controller to be used * @return glist_t * with the lisp_addr_t * of the default rlocs */ glist_t * ctrl_default_rlocs(oor_ctrl_t * ctrl) { lisp_addr_t *addr; glist_t * dflt_rlocs = glist_new(); if (dflt_rlocs == NULL){ return (NULL); } addr = ctrl->control_data_plane->control_dp_get_default_addr(ctrl,AF_INET); if (addr != NULL){ glist_add(addr, dflt_rlocs); } addr = ctrl->control_data_plane->control_dp_get_default_addr(ctrl,AF_INET6); if (addr != NULL){ glist_add(addr, dflt_rlocs); } return (dflt_rlocs); } glist_t * ctrl_rlocs(oor_ctrl_t *ctrl){ return (ctrl->rlocs); } glist_t * ctrl_rlocs_with_afi(oor_ctrl_t *c, int afi) { switch(afi) { case AF_INET: return(c->ipv4_rlocs); case AF_INET6: return(c->ipv6_rlocs); } return(NULL); } inline int ctrl_supported_afis(oor_ctrl_t *ctrl) { return (ctrl->supported_afis); } fwd_info_t * ctrl_get_forwarding_info(packet_tuple_t *tuple) { oor_ctrl_dev_t *dev; dev = glist_first_data(lctrl->devices); return (ctrl_dev_get_fwd_entry(dev, tuple)); } int ctrl_register_device(oor_ctrl_t *ctrl, oor_ctrl_dev_t *dev) { char *device; device = ctrl_dev_type_to_char(dev->mode); OOR_LOG(LINF, "Device working in mode %s registering with control", device); glist_add(dev, ctrl->devices); return(GOOD); } int ctrl_register_mapping_dp(oor_ctrl_dev_t *dev, mapping_t *map) { oor_dev_type_e dev_type = dev->mode; int res = GOOD; if (dev_type == xTR_MODE || dev_type == MN_MODE || dev_type == RTR_MODE){ res = data_plane->datap_register_lcl_mapping(dev_type,map); }else{ OOR_LOG(LDBG_1, "Current version only supports the registration in control of " "EID prefixes from xTRs and MNs"); } return (res); } int ctrl_unregister_mapping_dp(oor_ctrl_dev_t *dev, mapping_t *map) { oor_dev_type_e dev_type = dev->mode; if (data_plane){ if (dev_type == xTR_MODE || dev_type == MN_MODE || dev_type == RTR_MODE){ data_plane->datap_deregister_lcl_mapping(dev_type,map); }else{ OOR_LOG(LDBG_1, "Current version only supports the unregistration in control of " "EID prefixes from xTRs"); } } return (GOOD); } int ctrl_datap_rm_fwd_from_entry(lisp_addr_t *eid_prefix, uint8_t is_local) { return (data_plane->datap_rm_fwd_from_entry(eid_prefix, is_local)); } int ctrl_datap_reset_all_fwd() { return (data_plane->datap_reset_all_fwd()); } /* * Multicast Interface to end-hosts */ void multicast_join_channel(lisp_addr_t *src, lisp_addr_t *grp) { lisp_addr_t *mceid = lisp_addr_build_mc(src, grp); /* re_join_channel(mceid); */ lisp_addr_del(mceid); } void multicast_leave_channel(lisp_addr_t *src, lisp_addr_t *grp) { lisp_addr_t *mceid = lisp_addr_build_mc(src, grp); /* re_leave_channel(mceid); */ lisp_addr_del(mceid); } oor-1.2.0/oor/control/oor_control.h000066400000000000000000000052141313612200500172730ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef OOR_CONTROL_H_ #define OOR_CONTROL_H_ #include "../iface_list.h" #include "../lib/sockets.h" #include "../liblisp/liblisp.h" #include "control-data-plane/control-data-plane.h" typedef struct oor_ctrl oor_ctrl_t; struct oor_ctrl { glist_t *devices; /* move ctrl interface here */ int supported_afis; glist_t *rlocs; glist_t *ipv4_rlocs; glist_t *ipv6_rlocs; control_dplane_struct_t *control_data_plane; }; oor_ctrl_t *ctrl_create(); void ctrl_destroy(oor_ctrl_t *ctrl); int ctrl_init(oor_ctrl_t *ctrl); void ctrl_update_iface_info(oor_ctrl_t *ctrl); lisp_addr_t *ctrl_default_rloc(oor_ctrl_t *c, int afi); /* * Return the default control rlocs in a list that shoud be released * by the user. * @param ctrl OOR controler to be used * @return glist_t * with the lisp_addr_t * of the default rlocs */ glist_t *ctrl_default_rlocs(oor_ctrl_t * ctrl); glist_t *ctrl_rlocs(oor_ctrl_t *ctrl); glist_t *ctrl_rlocs_with_afi(oor_ctrl_t *c, int afi) ; int ctrl_supported_afis(oor_ctrl_t *ctrl); void ctrl_if_addr_update(oor_ctrl_t *, iface_t *, lisp_addr_t *, lisp_addr_t *); void ctrl_if_link_update(oor_ctrl_t *ctrl, iface_t *iface, int old_iface_index, int new_iface_index, int status); void ctrl_route_update(oor_ctrl_t *ctrl, int command, iface_t *iface,lisp_addr_t *src_pref, lisp_addr_t *dst_pref, lisp_addr_t *gateway); fwd_info_t *ctrl_get_forwarding_info(packet_tuple_t *); int ctrl_register_device(oor_ctrl_t *ctrl, oor_ctrl_dev_t *dev); int ctrl_register_mapping_dp(oor_ctrl_dev_t *dev, mapping_t *map); int ctrl_unregister_mapping_dp(oor_ctrl_dev_t *dev, mapping_t *map); int ctrl_notify_mapping_change_to_dp(lisp_addr_t *eid_prefix, uint8_t is_local); int ctrl_datap_rm_fwd_from_entry(lisp_addr_t *eid_prefix, uint8_t is_local); int ctrl_datap_reset_all_fwd(); void multicast_join_channel(lisp_addr_t *src, lisp_addr_t *grp); void multicast_leave_channel(lisp_addr_t *src, lisp_addr_t *grp); #endif /* OOR_CONTROL_H_ */ oor-1.2.0/oor/control/oor_ctrl_device.c000066400000000000000000000073461313612200500201010ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "../oor_external.h" #include "../lib/packets.h" #include "../lib/sockets.h" #include "oor_ctrl_device.h" static ctrl_dev_class_t *reg_ctrl_dev_cls[4] = { &xtr_ctrl_class, &ms_ctrl_class, &xtr_ctrl_class,/* RTR */ &xtr_ctrl_class,/* MN */ }; inline oor_dev_type_e ctrl_dev_mode(oor_ctrl_dev_t *dev){ return dev->mode; } inline oor_ctrl_t * ctrl_dev_get_ctrl_t(oor_ctrl_dev_t *dev){ return dev->ctrl; } static ctrl_dev_class_t * ctrl_dev_class_find(oor_dev_type_e type) { return(reg_ctrl_dev_cls[type]); } int ctrl_dev_recv(oor_ctrl_dev_t *dev, lbuf_t *b, uconn_t *uc) { return(dev->ctrl_class->recv_msg(dev, b, uc)); } void ctrl_dev_run(oor_ctrl_dev_t *dev) { dev->ctrl_class->run(dev); } int ctrl_dev_create(oor_dev_type_e type, oor_ctrl_dev_t **devp) { oor_ctrl_dev_t *dev; ctrl_dev_class_t *class; *devp = NULL; /* find type of device */ class = ctrl_dev_class_find(type); dev = class->alloc(); dev->mode =type; dev->ctrl_class = class; dev->ctrl_class->construct(dev); ctrl_dev_set_ctrl(dev, lctrl); *devp = dev; return(GOOD); } void ctrl_dev_destroy(oor_ctrl_dev_t *dev) { if (!dev) { return; } dev->ctrl_class->destruct(dev); dev->ctrl_class->dealloc(dev); } int send_msg(oor_ctrl_dev_t *dev, lbuf_t *b, uconn_t *uc) { return(dev->ctrl->control_data_plane->control_dp_send_msg(dev->ctrl, b, uc)); } int notify_datap_rm_fwd_from_entry(oor_ctrl_dev_t *dev, lisp_addr_t *eid_prefix, uint8_t is_local) { return(ctrl_datap_rm_fwd_from_entry(eid_prefix, is_local)); } int notify_datap_reset_all_fwd(oor_ctrl_dev_t *dev) { return(ctrl_datap_reset_all_fwd()); } int ctrl_dev_if_link_update(oor_ctrl_dev_t *dev, char *iface_name, uint8_t status) { return(dev->ctrl_class->if_link_update(dev, iface_name, status)); } int ctrl_dev_if_addr_update(oor_ctrl_dev_t *dev, char *iface_name, lisp_addr_t *old_addr, lisp_addr_t *new_addr, uint8_t status) { return(dev->ctrl_class->if_addr_update(dev, iface_name, old_addr, new_addr, status)); } int ctrl_dev_route_update(oor_ctrl_dev_t *dev, int command, char *iface_name ,lisp_addr_t *pref, lisp_addr_t *dst_pref, lisp_addr_t *gateway) { return(dev->ctrl_class->route_update(dev,command,iface_name,pref,dst_pref,gateway)); } fwd_info_t * ctrl_dev_get_fwd_entry(oor_ctrl_dev_t *dev, packet_tuple_t *tuple) { return(dev->ctrl_class->get_fwd_entry(dev, tuple)); } int ctrl_dev_set_ctrl(oor_ctrl_dev_t *dev, oor_ctrl_t *ctrl) { dev->ctrl = ctrl; ctrl_register_device(ctrl, dev); return(GOOD); } char * ctrl_dev_type_to_char(oor_dev_type_e type) { static char device[15]; *device='\0'; switch (type){ case xTR_MODE: strcpy(device,"xTR"); break; case MS_MODE: strcpy(device,"Map Server"); break; case RTR_MODE: strcpy(device,"RTR"); break; case MN_MODE: strcpy(device,"Mobile Node"); break; default: strcpy(device,"Unknown"); break; } return (device); } oor-1.2.0/oor/control/oor_ctrl_device.h000066400000000000000000000057131313612200500201020ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef OOR_CTRL_DEVICE_H_ #define OOR_CTRL_DEVICE_H_ #include "../defs.h" #include "../liblisp/liblisp.h" #include "oor_local_db.h" #include "oor_map_cache.h" #include "oor_control.h" typedef struct oor_ctrl_dev oor_ctrl_dev_t; /* functions to control lisp control devices*/ typedef struct ctrl_dev_class_t { oor_ctrl_dev_t *(*alloc)(void); int (*construct)(oor_ctrl_dev_t *); void (*dealloc)(oor_ctrl_dev_t *); void (*destruct)(oor_ctrl_dev_t *); void (*init)(oor_ctrl_dev_t *); void (*run)(oor_ctrl_dev_t *dev); int (*recv_msg)(oor_ctrl_dev_t *, lbuf_t *, uconn_t *); int (*if_link_update)(oor_ctrl_dev_t *, char *, uint8_t); int (*if_addr_update)(oor_ctrl_dev_t *, char *, lisp_addr_t *,lisp_addr_t *, uint8_t); int (*route_update)(oor_ctrl_dev_t *, int , char *,lisp_addr_t *, lisp_addr_t *, lisp_addr_t *); fwd_info_t *(*get_fwd_entry)(oor_ctrl_dev_t *, packet_tuple_t *); } ctrl_dev_class_t; struct oor_ctrl_dev { oor_dev_type_e mode; const ctrl_dev_class_t *ctrl_class; /* pointer to lisp ctrl */ oor_ctrl_t *ctrl; }; extern ctrl_dev_class_t ms_ctrl_class; extern ctrl_dev_class_t xtr_ctrl_class; int ctrl_dev_create(oor_dev_type_e , oor_ctrl_dev_t **); void ctrl_dev_destroy(oor_ctrl_dev_t *); int ctrl_dev_recv(oor_ctrl_dev_t *, lbuf_t *, uconn_t *); void ctrl_dev_run(oor_ctrl_dev_t *); int ctrl_dev_if_link_update(oor_ctrl_dev_t *dev, char *iface_name, uint8_t status); int ctrl_dev_if_addr_update(oor_ctrl_dev_t *dev, char *iface_name, lisp_addr_t *old_addr, lisp_addr_t *new_addr, uint8_t status); int ctrl_dev_route_update(oor_ctrl_dev_t *dev, int command, char *iface_name, lisp_addr_t *src, lisp_addr_t *dst_pref, lisp_addr_t *gateway); oor_dev_type_e ctrl_dev_mode(oor_ctrl_dev_t *dev); oor_ctrl_t * ctrl_dev_get_ctrl_t(oor_ctrl_dev_t *dev); int ctrl_dev_set_ctrl(oor_ctrl_dev_t *, oor_ctrl_t *); fwd_info_t *ctrl_dev_get_fwd_entry(oor_ctrl_dev_t *, packet_tuple_t *); int notify_datap_rm_fwd_from_entry(oor_ctrl_dev_t *dev, lisp_addr_t *eid_prefix, uint8_t is_local); int notify_datap_reset_all_fwd(oor_ctrl_dev_t *dev); /* PRIVATE functions, used by xtr and ms */ int send_msg(oor_ctrl_dev_t *, lbuf_t *, uconn_t *); char * ctrl_dev_type_to_char(oor_dev_type_e type); #endif /* OOR_CTRL_DEVICE_H_ */ oor-1.2.0/oor/control/oor_local_db.c000066400000000000000000000137311313612200500173500ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "oor_local_db.h" #include "../oor_external.h" #include "../lib/oor_log.h" local_map_db_t * local_map_db_new() { local_map_db_t *db; db = xzalloc(sizeof(local_map_db_t)); if (!db) { OOR_LOG(LCRIT, "Could allocate local map database "); return(NULL); } db->db = mdb_new(); if (!db->db) { OOR_LOG(LCRIT, "Could allocate local map database "); return(NULL); } return(db); } void local_map_db_del(local_map_db_t *lmdb) { mdb_del(lmdb->db, (mdb_del_fct)map_local_entry_del); free(lmdb); } int local_map_db_add_entry(local_map_db_t *lmdb, map_local_entry_t *map_loc_e) { lisp_addr_t *eid, *ip_pref; eid = map_local_entry_eid(map_loc_e); ip_pref = lisp_addr_get_ip_pref_addr(eid); if (mdb_add_entry(lmdb->db, ip_pref, map_loc_e) != GOOD) { OOR_LOG(LDBG_3, "Couldn't add mapping for EID %s to local mappings database", lisp_addr_to_char(map_local_entry_eid(map_loc_e))); return(BAD); } return(GOOD); } map_local_entry_t * local_map_db_lookup_eid(local_map_db_t *lmdb, lisp_addr_t *eid, uint8_t check_iid) { map_local_entry_t *map_loc_e = NULL; uint32_t iid = 0; lisp_addr_t *ip_pref_eid, *db_eid; if (lisp_addr_is_lcaf(eid)){ if (lcaf_addr_is_iid (lisp_addr_get_lcaf(eid)) == FALSE){ OOR_LOG(LDBG_2, "local_map_db_lookup_eid: LCAF %d not supported for EID", lisp_addr_to_char(eid)); return (NULL); } iid = lcaf_iid_get_iid(lisp_addr_get_lcaf(eid)); ip_pref_eid = lisp_addr_get_ip_pref_addr(eid); }else{ ip_pref_eid = eid; } map_loc_e = (map_local_entry_t *)mdb_lookup_entry(lmdb->db, ip_pref_eid); if (!map_loc_e) { OOR_LOG(LDBG_3, "Couldn't find mapping for EID %s in local mappings database", lisp_addr_to_char(eid)); return (NULL); } if (check_iid){ db_eid = map_local_entry_eid(map_loc_e); if (iid > 0){ if (iid != lcaf_iid_get_iid(lisp_addr_get_lcaf(db_eid))){ OOR_LOG(LDBG_3, "Couldn't find mapping for EID %s in local mappings database. IID not match", lisp_addr_to_char(eid)); return (NULL); } }else if (lisp_addr_is_lcaf(db_eid)){ OOR_LOG(LDBG_3, "Couldn't find mapping for EID %s in local mappings database. Different IID", lisp_addr_to_char(eid)); return (NULL); } } return (map_loc_e); } map_local_entry_t * local_map_db_lookup_eid_exact(local_map_db_t *lmdb, lisp_addr_t *eid) { map_local_entry_t *map_loc_e; lisp_addr_t *ip_pref_eid, *db_eid; if (lisp_addr_is_lcaf(eid)){ if (lcaf_addr_is_iid (lisp_addr_get_lcaf(eid)) == FALSE){ OOR_LOG(LDBG_2, "local_map_db_lookup_eid: LCAF %d not supported for EID", lisp_addr_to_char(eid)); return (NULL); } ip_pref_eid = lisp_addr_get_ip_pref_addr(eid); }else{ ip_pref_eid = eid; } map_loc_e = (map_local_entry_t *)mdb_lookup_entry_exact(lmdb->db, ip_pref_eid); if (!map_loc_e) { OOR_LOG(LDBG_3, "Couldn't find mapping for EID %s in local mappings database", lisp_addr_to_char(eid)); return (NULL); } db_eid = map_local_entry_eid(map_loc_e); /* To check IID of local database we should compare both addresses */ if (lisp_addr_cmp(db_eid,eid) != 0){ OOR_LOG(LDBG_3, "Couldn't find mapping for EID %s in local mappings database.", lisp_addr_to_char(eid)); return (NULL); } return (map_loc_e); } void local_map_db_del_entry(local_map_db_t *lmdb, lisp_addr_t *eid) { map_local_entry_t *map_loc_e = NULL; map_loc_e = (map_local_entry_t *)mdb_remove_entry(lmdb->db, eid); if (map_loc_e != NULL) { map_local_entry_del(map_loc_e); } } lisp_addr_t * local_map_db_get_main_eid(local_map_db_t *lmdb, int afi) { void *it; lisp_addr_t *eid , *eid_res = NULL; uint8_t found = FALSE; mdb_foreach_ip_entry_with_break(lmdb->db, it, found) { eid = map_local_entry_eid((map_local_entry_t *)it); if (eid && lisp_addr_ip_afi(eid) == afi) { found = TRUE; eid_res = eid; } } mdb_foreach_ip_entry_with_break_end(found); return (eid_res); } int local_map_db_num_ip_eids(local_map_db_t *lmdb, int afi) { void *it = NULL; lisp_addr_t *eid = NULL; int ctr = 0; /* search could be better implemented but local db is small * so this should do for now */ mdb_foreach_ip_entry(lmdb->db, it) { eid = map_local_entry_eid((map_local_entry_t *)it); if (eid && lisp_addr_lafi(eid) == LM_AFI_IPPREF && lisp_addr_ip_afi(eid) == afi) { ctr ++; } } mdb_foreach_ip_entry_end; return (ctr); } inline int local_map_db_n_entries(local_map_db_t *lmdb) { return(lmdb->db->n_entries); } void local_map_db_dump(local_map_db_t *lmdb, int log_level) { map_local_entry_t *map_loc_e = NULL; void *it = NULL; OOR_LOG(log_level,"****************** LISP Local Mappings ****************\n"); mdb_foreach_entry(lmdb->db, it) { map_loc_e = (map_local_entry_t *)it; map_local_entry_dump(map_loc_e,log_level); } mdb_foreach_entry_end; OOR_LOG(log_level,"*******************************************************\n"); } oor-1.2.0/oor/control/oor_local_db.h000066400000000000000000000043701313612200500173540ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef OOR_LOCAL_DB_H_ #define OOR_LOCAL_DB_H_ #include "../defs.h" #include "../liblisp/liblisp.h" #include "../lib/map_local_entry.h" #include "../lib/mapping_db.h" typedef struct local_map_db_t_ { mdb_t *db; } local_map_db_t; local_map_db_t *local_map_db_new(); void local_map_db_del(local_map_db_t *lmdb); int local_map_db_add_entry(local_map_db_t *, map_local_entry_t *); void local_map_db_del_entry(local_map_db_t *, lisp_addr_t *); map_local_entry_t *local_map_db_lookup_eid(local_map_db_t *, lisp_addr_t *, uint8_t); map_local_entry_t *local_map_db_lookup_eid_exact(local_map_db_t *, lisp_addr_t *); lisp_addr_t *local_map_db_get_main_eid(local_map_db_t *, int ); int local_map_db_num_ip_eids(local_map_db_t *, int ); void local_map_db_dump(local_map_db_t *, int ); int local_map_db_n_entries(local_map_db_t *); #define local_map_db_foreach_entry(_LMDB, _EIT) \ mdb_foreach_entry((_LMDB)->db, (_EIT)) { \ #define local_map_db_foreach_end \ } mdb_foreach_entry_end #define local_map_db_foreach_entry_with_break(_LMDB, _EIT, _break) \ mdb_foreach_entry_with_break((_LMDB)->db, (_EIT), _break) { \ #define local_map_db_foreach_with_break_end(_break) \ } mdb_foreach_entry_with_break_end(_break) #define local_map_db_foreach_break #define local_map_db_foreach_ip_entry(LMDB, EIT) \ mdb_foreach_ip_entry((LMDB)->db, (EIT)) { \ #define local_map_db_foreach_ip_end \ } mdb_foreach_ip_entry_end #endif /*OOR_LOCAL_DB_H_*/ oor-1.2.0/oor/control/oor_map_cache.c000066400000000000000000000045751313612200500175170ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "oor_map_cache.h" #include "../lib/oor_log.h" #include map_cache_db_t* mcache_new() { map_cache_db_t *mcdb = xzalloc(sizeof(map_cache_db_t)); if (!mcdb) { OOR_LOG(LCRIT, "Could allocate map cache db "); return(NULL); } mcdb->db = mdb_new(); if (!mcdb->db) { OOR_LOG(LCRIT, "Could create map cache db "); return(NULL); } return(mcdb); } void mcache_del(map_cache_db_t *mcdb) { mdb_del(mcdb->db, (mdb_del_fct)mcache_entry_del); free(mcdb); } int mcache_add_entry(map_cache_db_t *mcdb, lisp_addr_t *key, mcache_entry_t *mce) { return(mdb_add_entry(mcdb->db, key, mce)); } void * mcache_remove_entry(map_cache_db_t *mcdb, lisp_addr_t *key) { return(mdb_remove_entry(mcdb->db, key)); } /* * Look up a given lisp_addr_t in the database, returning the * oor_map_cache_entry of this lisp_addr_t if it exists or NULL. */ mcache_entry_t * mcache_lookup(map_cache_db_t *mcdb, lisp_addr_t *laddr) { return(mdb_lookup_entry(mcdb->db, laddr)); } /* * Find an exact match for a prefix/prefixlen if possible */ mcache_entry_t * mcache_lookup_exact(map_cache_db_t *mcdb, lisp_addr_t *laddr) { return(mdb_lookup_entry_exact(mcdb->db, laddr)); } void mcache_dump_db(map_cache_db_t *mcdb, int log_level) { if (is_loggable(log_level) == FALSE) { return; } mcache_entry_t *mce; void *it; OOR_LOG(log_level,"**************** LISP Mapping Cache ******************\n"); mdb_foreach_entry(mcdb->db, it) { mce = (mcache_entry_t *)it; map_cache_entry_dump(mce, log_level); } mdb_foreach_entry_end; OOR_LOG(log_level,"*******************************************************\n"); } oor-1.2.0/oor/control/oor_map_cache.h000066400000000000000000000044211313612200500175120ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef OOR_MAP_CACAHE_DB_H_ #define OOR_MAP_CACAHE_DB_H_ #include "../defs.h" #include "../lib/map_cache_entry.h" #include "../lib/mapping_db.h" #include "../liblisp/liblisp.h" typedef struct map_cache_db { mdb_t *db; } map_cache_db_t; map_cache_db_t *mcache_new(); void mcache_del(map_cache_db_t *mcdb); int mcache_add_entry(map_cache_db_t *, lisp_addr_t *key, mcache_entry_t *entry); void *mcache_remove_entry(map_cache_db_t *, lisp_addr_t *key); void map_cache_del_entry(map_cache_db_t *, lisp_addr_t *laddr); mcache_entry_t *mcache_lookup_exact(map_cache_db_t *, lisp_addr_t *addr); mcache_entry_t *mcache_lookup(map_cache_db_t *, lisp_addr_t *addr); void mcache_dump_db(map_cache_db_t *, int log_level); #define mcache_foreach_entry(MC, EIT) \ mdb_foreach_entry((MC)->db, (EIT)) { #define mcache_foreach_active_entry(MC, EIT) \ mdb_foreach_entry((MC)->db, (EIT)) \ if (((mcache_entry_t *)(EIT))->active){ #define mcache_foreach_not_active_entry(MC, EIT) \ mdb_foreach_entry((MC)->db, (EIT)) \ if (((mcache_entry_t *)(EIT))->active == FALSE){ #define mcache_foreach_end \ } \ mdb_foreach_entry_end /* ugly .. */ #define mcache_foreach_active_entry_in_ip_eid_db(_MC_, _EID_, _EIT_) \ mdb_foreach_entry_in_ip_eid_db((_MC_)->db, (_EID_), (_EIT_)){ \ if ((_EIT_)->active) { #define mcache_foreach_active_entry_in_ip_eid_db_end \ } \ }mdb_foreach_entry_in_ip_eid_db_end #endif /*OOR_MAP_CACAHE_DB_H_*/ oor-1.2.0/oor/data-plane/000077500000000000000000000000001313612200500151075ustar00rootroot00000000000000oor-1.2.0/oor/data-plane/data-plane.c000066400000000000000000000016341313612200500172650ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "data-plane.h" data_plane_struct_t *data_plane = NULL; void data_plane_select() { #ifdef VPNAPI data_plane = &dplane_vpnapi; #elif VPP data_plane = &dplane_vpp; #else data_plane = &dplane_tun; #endif } oor-1.2.0/oor/data-plane/data-plane.h000066400000000000000000000040461313612200500172720ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef DATA_PLANE_H_ #define DATA_PLANE_H_ #include "../liblisp/liblisp.h" typedef struct iface iface_t; typedef struct sock sock_t; /* functions to manipulate routing */ typedef struct data_plane_struct { int (*datap_init)(oor_dev_type_e dev_type, oor_encap_t encap_type, ...); void (*datap_uninit)(); int (*datap_add_iface_addr)(iface_t *iface, int afi); int (*datap_add_iface_gw)(iface_t *iface, int afi); int (*datap_register_lcl_mapping)(oor_dev_type_e dev_type, mapping_t *map); int (*datap_deregister_lcl_mapping)(oor_dev_type_e dev_type, mapping_t *map); int (*datap_input_packet)(sock_t *sl); int (*datap_rtr_input_packet)(sock_t *sl); int (*datap_output_packet)(sock_t *sl); int (*datap_updated_route)(int command, iface_t *iface, lisp_addr_t *src_pref, lisp_addr_t *dst_pref, lisp_addr_t *gw); int (*datap_updated_addr)(iface_t *iface,lisp_addr_t *old_addr,lisp_addr_t *new_addr); int (*datap_update_link)(iface_t *iface, int old_iface_index, int new_iface_index, int status); int (*datap_rm_fwd_from_entry)(lisp_addr_t *eid_prefix, uint8_t is_local); int (*datap_reset_all_fwd)(); void *datap_data; } data_plane_struct_t; void data_plane_select(); extern data_plane_struct_t dplane_tun; extern data_plane_struct_t dplane_vpnapi; extern data_plane_struct_t dplane_vpp; #endif /* DATA_PLANE_H_ */ oor-1.2.0/oor/data-plane/encapsulations/000077500000000000000000000000001313612200500201375ustar00rootroot00000000000000oor-1.2.0/oor/data-plane/encapsulations/vxlan-gpe.c000066400000000000000000000047401313612200500222110ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "vxlan-gpe.h" #include "../../lib/oor_log.h" #include "../../lib/packets.h" vxlan_gpe_nprot_t vxlan_gpe_get_next_prot(lisp_addr_t *addr) { //XXX To be improved if (lisp_addr_ip_afi(addr) == AF_INET){ return (NP_IPv4); }else{ return (NP_IPv6); } } void vxlan_gpe_data_hdr_init(vxlan_gpe_hdr_t *vhdr, uint32_t vni, vxlan_gpe_nprot_t np) { memset (vhdr,0,sizeof(vxlan_gpe_hdr_t)); vhdr->vni_flag = 1; pkt_add_uint32_in_3bytes (vhdr->vni, vni); vhdr->next_prot_flag = 1; vhdr->next_proto = np; } void * vxlan_gpe_data_push_hdr(lbuf_t *b, uint32_t vni, vxlan_gpe_nprot_t next_prot) { vxlan_gpe_hdr_t *vhdr; vhdr = lbuf_push_uninit(b, sizeof(vxlan_gpe_hdr_t)); vxlan_gpe_data_hdr_init(vhdr, vni, next_prot); return(vhdr); } void * vxlan_gpe_data_encap(lbuf_t *b, int lp, int rp, lisp_addr_t *la, lisp_addr_t *ra, uint32_t vni) { int ttl = 0, tos = 0; vxlan_gpe_nprot_t next_prot; /* read ttl and tos */ ip_hdr_ttl_and_tos(lbuf_data(b), &ttl, &tos); switch (lisp_addr_ip_afi(la)){ case AF_INET: next_prot = NP_IPv4; break; case AF_INET6: next_prot = NP_IPv6; break; default: OOR_LOG(LDBG_1, "vxlan_gpe_data_encap: Next protocol not supported"); return (NULL); } /* push vxlan-gpe data hdr */ vxlan_gpe_data_push_hdr(b, vni, next_prot); /* push outer UDP and IP */ pkt_push_udp_and_ip(b, lp, rp, lisp_addr_ip(la), lisp_addr_ip(ra)); ip_hdr_set_ttl_and_tos(lbuf_data(b), ttl, tos); return(lbuf_data(b)); } void * vxlan_gpe_data_pull_hdr(lbuf_t *b) { void *dt = lbuf_pull(b, sizeof(vxlan_gpe_hdr_t)); return(dt); } uint32_t vxlan_gpe_hdr_get_vni(vxlan_gpe_hdr_t *hdr) { return (pkt_get_uint32_from_3bytes(hdr->vni)); } oor-1.2.0/oor/data-plane/encapsulations/vxlan-gpe.h000066400000000000000000000050131313612200500222100ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef VXLAN_GPE_H_ #define VXLAN_GPE_H_ #include "../../lib/lbuf.h" #include "../../lib/mem_util.h" #include "../../liblisp/lisp_address.h" #define VXLAN_GPE_DATA_PORT 4790 /* * VXLAN-GPE data packet header * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |R|R|Ver|I|P|R|O| Reserved |Next Protocol | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | VXLAN Network Identifier (VNI) | Reserved | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ typedef struct vxlan_gpe_hdr { #ifdef LITTLE_ENDIANS uint8_t oam_flag:1; uint8_t resv_flags_1:1; uint8_t next_prot_flag:1; uint8_t vni_flag:1; uint8_t vxlan_ver:2; uint8_t resv_flags_2:2; #else uint8_t resv_flags_2:2; uint8_t vxlan_ver:2; uint8_t vni_flag:1; uint8_t next_prot_flag:1; uint8_t resv_flags_1:1; uint8_t oam_flag:1; #endif uint8_t reserved_1[2]; uint8_t next_proto; uint8_t vni[3]; uint8_t reserved_2; } vxlan_gpe_hdr_t; typedef enum { NP_IPv4 = 0x1, NP_IPv6 = 0x2, NP_ETH = 0x3, NP_NSH = 0x4, NP_MLS = 0x5 }vxlan_gpe_nprot_t; vxlan_gpe_nprot_t vxlan_gpe_get_next_prot(lisp_addr_t *addr); void * vxlan_gpe_data_push_hdr(lbuf_t *b, uint32_t vni, vxlan_gpe_nprot_t np); void * vxlan_gpe_data_encap(lbuf_t *b, int lp, int rp, lisp_addr_t *la, lisp_addr_t *ra, uint32_t vni); void * vxlan_gpe_data_pull_hdr(lbuf_t *b); uint32_t vxlan_gpe_hdr_get_vni(vxlan_gpe_hdr_t *hdr); #define VXLAN_HDR_CAST(h_) ((vxlan_gpe_hdr_t *)(h_)) #define VXLAN_HDR_VNI_BIT(h_) (VXLAN_HDR_CAST((h_)))->vni_flag #endif /* VXLAN_GPE_H_ */ oor-1.2.0/oor/data-plane/ttable.c000066400000000000000000000061741313612200500165360ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "ttable.h" #include "../lib/mem_util.h" #include "../lib/packets.h" #include "../lib/oor_log.h" #include "../lib/sockets.h" #include "../fwd_policies/fwd_policy.h" #include "../liblisp/liblisp.h" /* Maximum size of the tuple table */ #define MAX_SIZE 10000 void ttable_remove_with_khiter(ttable_t *tt, khiter_t k); void ttable_init(ttable_t *tt) { tt->htable = kh_init(ttable); list_init(&tt->head_list); } void ttable_uninit(ttable_t *tt) { khiter_t k; fwd_info_t *fi; for (k = kh_begin(tt->htable); k != kh_end(tt->htable); ++k){ if (kh_exist(tt->htable, k)){ // The key is remove when removing value fi = kh_value(tt->htable,k); fwd_info_del(fi); } } kh_destroy(ttable, tt->htable); } ttable_t * ttable_create() { ttable_t *tt = xzalloc(sizeof(ttable_t)); ttable_init(tt); return(tt); } void ttable_destroy(ttable_t *tt) { ttable_uninit(tt); free(tt); } int ttable_insert(ttable_t *tt, packet_tuple_t *tpl, fwd_info_t *fi) { khiter_t k; int ret; /* If table is full remove old entries */ if (kh_size(tt->htable) >= MAX_SIZE) { OOR_LOG(LDBG_1,"ttable_insert: Max size of forwarding table reached."); return (BAD); } k = kh_put(ttable,tt->htable,tpl,&ret); kh_value(tt->htable, k) = fi; OOR_LOG(LDBG_3,"ttable_insert: Inserted tupla: %s ", pkt_tuple_to_char(tpl)); return (GOOD); } void ttable_remove(ttable_t *tt, packet_tuple_t *tpl) { khiter_t k; fwd_info_t *fi; k = kh_get(ttable,tt->htable, tpl); if (k == kh_end(tt->htable)){ return; } fi = kh_value(tt->htable,k); OOR_LOG(LDBG_3,"ttable_remove: Remove tupla: %s ", pkt_tuple_to_char(tpl)); // We don't remove the key (tuple). It is part of the fwd_info_t; /* Free value */ fwd_info_del(fi); /* Remove entry from hash table */ kh_del(ttable,tt->htable,k); } void ttable_remove_with_khiter(ttable_t *tt, khiter_t k) { fwd_info_t *fi; fi = kh_value(tt->htable,k); OOR_LOG(LDBG_3,"ttable_remove_with_khiter: Remove tupla: %s ", pkt_tuple_to_char((packet_tuple_t *)fi->dp_conf_inf)); fwd_info_del(fi); kh_del(ttable,tt->htable,k); } fwd_info_t * ttable_lookup(ttable_t *tt, packet_tuple_t *tpl) { fwd_info_t *fi; khiter_t k; k = kh_get(ttable,tt->htable, tpl); if (k == kh_end(tt->htable)){ return (NULL); } fi = kh_value(tt->htable,k); return (fi); } oor-1.2.0/oor/data-plane/ttable.h000066400000000000000000000026671313612200500165460ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef TTABLE_H_ #define TTABLE_H_ #include #include "../elibs/khash/khash.h" #include "../elibs/ovs/list.h" #include "../lib/packets.h" typedef struct fwd_info_ fwd_info_t; KHASH_INIT(ttable, packet_tuple_t *, fwd_info_t *, 1, pkt_tuple_hash, pkt_tuple_cmp) typedef struct ttable { khash_t(ttable) *htable; // struct ovs_list head_list; /* To order flows */ } ttable_t; void ttable_init(ttable_t *tt); void ttable_uninit(ttable_t *tt); ttable_t *ttable_create(); void ttable_destroy(ttable_t *tt); int ttable_insert(ttable_t *, packet_tuple_t *tpl, fwd_info_t *fe); void ttable_remove(ttable_t *tt, packet_tuple_t *tpl); fwd_info_t *ttable_lookup(ttable_t *tt, packet_tuple_t *tpl); #endif /* TTABLE_H_ */ oor-1.2.0/oor/data-plane/tun/000077500000000000000000000000001313612200500157155ustar00rootroot00000000000000oor-1.2.0/oor/data-plane/tun/tun.c000066400000000000000000000743211313612200500166760ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include #include "tun.h" #include "tun_input.h" #include "tun_output.h" #include "../data-plane.h" #include "../../oor_external.h" #include "../../fwd_policies/fwd_policy.h" #include "../../lib/interfaces_lib.h" #include "../../lib/oor_log.h" #include "../../lib/routing_tables_lib.h" int tun_configure_data_plane(oor_dev_type_e dev_type, oor_encap_t encap_type, ...); void tun_uninit_data_plane(); int tun_add_datap_iface_addr(iface_t *iface,int afi); int tun_add_datap_iface_gw(iface_t *iface, int afi); int tun_register_lcl_mapping(oor_dev_type_e dev_type, mapping_t *map); int tun_deregister_lcl_mapping(oor_dev_type_e dev_type, mapping_t *map); int configure_routing_to_tun_router(int afi); int configure_routing_to_tun_mn(lisp_addr_t *eid_addr); int remove_routing_to_tun_mn(lisp_addr_t *eid_addr); int configure_routing_to_tun_mn(lisp_addr_t *eid_addr); int set_tun_default_route_v4(); int del_tun_default_route_v4(); int set_tun_default_route_v6(); int del_tun_default_route_v6(); int tun_updated_route (int command, iface_t *iface, lisp_addr_t *src_pref, lisp_addr_t *dst_pref, lisp_addr_t *gateway); int tun_updated_addr(iface_t *iface,lisp_addr_t *old_addr,lisp_addr_t *new_addr); int tun_updated_link(iface_t *iface, int old_iface_index, int new_iface_index, int status); void tun_process_new_gateway(iface_t *iface,lisp_addr_t *gateway); void tun_process_rm_gateway(iface_t *iface,lisp_addr_t *gateway); void tun_set_default_output_ifaces(); void tun_iface_remove_routing_rules(iface_t *iface); int tun_rm_fwd_from_entry(lisp_addr_t *eid_prefix, uint8_t is_local); tun_dplane_data_t * tun_dplane_data_new_init(oor_encap_t encap_type); void tun_dplane_data_free(tun_dplane_data_t *data); data_plane_struct_t dplane_tun = { .datap_init = tun_configure_data_plane, .datap_uninit = tun_uninit_data_plane, .datap_add_iface_addr = tun_add_datap_iface_addr, .datap_add_iface_gw = tun_add_datap_iface_gw, .datap_register_lcl_mapping = tun_register_lcl_mapping, .datap_deregister_lcl_mapping = tun_deregister_lcl_mapping, .datap_input_packet = tun_process_input_packet, .datap_rtr_input_packet = tun_rtr_process_input_packet, .datap_output_packet = tun_output_recv, .datap_updated_route = tun_updated_route, .datap_updated_addr = tun_updated_addr, .datap_update_link = tun_updated_link, .datap_rm_fwd_from_entry = tun_rm_fwd_from_entry, .datap_reset_all_fwd = tun_reset_all_fwd, .datap_data = NULL }; inline tun_dplane_data_t * tun_get_datap_data() { return ((tun_dplane_data_t *)dplane_tun.datap_data); } /* * tun_configure_data_plane not has variable list of parameters */ int tun_configure_data_plane(oor_dev_type_e dev_type, oor_encap_t encap_type, ...) { int (*cb_func)(sock_t *) = NULL; int ipv4_data_input_fd = -1; int ipv6_data_input_fd = -1; int data_port; /* Configure data plane */ tun_receive_fd = create_tun_tap(TUN, TUN_IFACE_NAME, TUN_MTU); if (tun_receive_fd <= BAD){ return (BAD); } tun_ifindex = if_nametoindex (TUN_IFACE_NAME); switch (dev_type){ case MN_MODE: sockmstr_register_read_listener(smaster, tun_output_recv, NULL,tun_receive_fd); cb_func = tun_process_input_packet; break; case xTR_MODE: /* We add route tables for IPv4 and IPv6 even no EID exists for this afi*/ /* Rules created for EID will redirect traffic to this table*/ configure_routing_to_tun_router(AF_INET); configure_routing_to_tun_router(AF_INET6); sockmstr_register_read_listener(smaster, tun_output_recv, NULL,tun_receive_fd); cb_func = tun_process_input_packet; break; case RTR_MODE: cb_func = tun_rtr_process_input_packet; break; default: return (BAD); } switch (encap_type){ case ENCP_LISP: data_port = LISP_DATA_PORT; break; case ENCP_VXLAN_GPE: data_port = VXLAN_GPE_DATA_PORT; break; default: return (BAD); } /* Generate receive sockets for data port (4341) */ if (default_rloc_afi != AF_INET6) { ipv4_data_input_fd = open_data_raw_input_socket(AF_INET, data_port); sockmstr_register_read_listener(smaster, cb_func, NULL, ipv4_data_input_fd); } if (default_rloc_afi != AF_INET) { ipv6_data_input_fd = open_data_raw_input_socket(AF_INET6, data_port); sockmstr_register_read_listener(smaster, cb_func, NULL, ipv6_data_input_fd); } dplane_tun.datap_data = (void *)tun_dplane_data_new_init(encap_type); /* Select the default rlocs for output data packets and output control * packets */ tun_set_default_output_ifaces(); return (GOOD); } void tun_uninit_data_plane() { tun_dplane_data_t *data = (tun_dplane_data_t *)dplane_tun.datap_data; glist_entry_t *iface_it; iface_t *iface; if (data){ /* Remove routes associated to each interface */ glist_for_each_entry(iface_it, interface_list){ iface = (iface_t *)glist_entry_data(iface_it); tun_iface_remove_routing_rules(iface); } tun_dplane_data_free(data); } } int tun_add_datap_iface_addr(iface_t *iface, int afi) { int sock; lisp_addr_t *addr; tun_dplane_data_t *data; data = (tun_dplane_data_t *)dplane_tun.datap_data; addr = iface_address(iface, afi); if (!addr || lisp_addr_is_no_addr(addr)){ return (BAD); } sock = open_ip_raw_socket(afi); bind_socket(sock, afi,addr,0); add_rule(afi, 0, iface->iface_index, iface->iface_index, RTN_UNICAST, addr, NULL, 0); switch (afi){ case AF_INET: iface->out_socket_v4 = sock; if (data && !data->default_out_iface_v4){ // It will only enter here when adding interfaces after init process tun_set_default_output_ifaces(); } break; case AF_INET6: iface->out_socket_v6 = sock; if (data && !data->default_out_iface_v6){ // It will only enter here when adding interfaces after init process tun_set_default_output_ifaces(); } break; } return (GOOD); } int tun_add_datap_iface_gw(iface_t *iface, int afi) { lisp_addr_t *gw; int route_metric = 100; gw = iface_gateway(iface, afi); if (!gw || lisp_addr_is_no_addr(gw)){ return (BAD); } add_route(afi,iface->iface_index,NULL,NULL,gw,route_metric,iface->iface_index); return(GOOD); } int tun_register_lcl_mapping(oor_dev_type_e dev_type, mapping_t *map) { lisp_addr_t *eid_ip_prefix = lisp_addr_get_ip_pref_addr(mapping_eid(map)); switch(dev_type){ case xTR_MODE: /* Route to send dtraffic to TUN */ if (add_rule(lisp_addr_ip_afi(eid_ip_prefix), 0, LISP_TABLE, RULE_TO_LISP_TABLE_PRIORITY, RTN_UNICAST, eid_ip_prefix, NULL,0)!=GOOD){ return (BAD); } /* Route to avoid to encapsulate traffic destined to the RLOC lan */ if (add_rule(lisp_addr_ip_afi(eid_ip_prefix), 0, RT_TABLE_MAIN, RULE_AVOID_LISP_TABLE_PRIORITY, RTN_UNICAST, NULL, eid_ip_prefix, 0)!=GOOD){ return (BAD); } break; case MN_MODE: configure_routing_to_tun_mn(eid_ip_prefix); break; case RTR_MODE: default: break; } return (GOOD); } int tun_deregister_lcl_mapping(oor_dev_type_e dev_type, mapping_t *map){ lisp_addr_t *eid_prefix = mapping_eid(map); switch(dev_type){ case xTR_MODE: if (del_rule(lisp_addr_ip_afi(eid_prefix), 0, LISP_TABLE, RULE_TO_LISP_TABLE_PRIORITY, RTN_UNICAST, eid_prefix, NULL,0)!=GOOD){ return (BAD); } if (del_rule(lisp_addr_ip_afi(eid_prefix), 0, RT_TABLE_MAIN, RULE_AVOID_LISP_TABLE_PRIORITY, RTN_UNICAST, NULL, eid_prefix, 0)!=GOOD){ return (BAD); } break; case MN_MODE: remove_routing_to_tun_mn(eid_prefix); break; case RTR_MODE: default: break; } return (GOOD); } /* * For mobile node mode, we create two /1 routes covering the full IP addresses space to route all traffic * generated by the node to the lispTun0 interface * IPv4: 0.0.0.0/1 and 128.0.0.0/1 * IPv6: ::/1 and 8000::/1 */ int configure_routing_to_tun_mn(lisp_addr_t *eid_addr) { if (add_addr_to_iface(TUN_IFACE_NAME, eid_addr) != GOOD){ return (BAD); } switch (lisp_addr_ip_afi(eid_addr)){ case AF_INET: if (set_tun_default_route_v4() != GOOD){ return (BAD); } break; case AF_INET6: if (set_tun_default_route_v6() != GOOD){ return (BAD); } break; default: return (BAD); break; } return (GOOD); } /* * For mobile node mode, we remove two /1 routes covering the full IP addresses space to route all traffic * generated by the node to the lispTun0 interface * IPv4: 0.0.0.0/1 and 128.0.0.0/1 * IPv6: ::/1 and 8000::/1 */ int remove_routing_to_tun_mn(lisp_addr_t *eid_addr) { if (del_addr_from_iface(TUN_IFACE_NAME, eid_addr) != GOOD){ return (BAD); } switch (lisp_addr_ip_afi(eid_addr)){ case AF_INET: if (del_tun_default_route_v4() != GOOD){ return (BAD); } break; case AF_INET6: if (del_tun_default_route_v6() != GOOD){ return (BAD); } break; default: return (BAD); break; } return (GOOD); } /* * For router mode, add a new routing table with default route to tun interface. Using source routing, * We send all traffic generated by EIDs to this table. */ int configure_routing_to_tun_router(int afi) { uint32_t iface_index = 0; iface_index = if_nametoindex(TUN_IFACE_NAME); return add_route(afi,iface_index,NULL,NULL,NULL,RULE_TO_LISP_TABLE_PRIORITY,LISP_TABLE); } int set_tun_default_route_v4() { /* * Assign route to 0.0.0.0/1 and 128.0.0.0/1 via tun interface */ lisp_addr_t dest; lisp_addr_t *src = NULL; uint32_t metric = 0; metric = 0; lisp_addr_ippref_from_char("0.0.0.0/1",&dest); add_route(AF_INET, tun_ifindex, &dest, src, NULL, metric, RT_TABLE_MAIN); lisp_addr_ippref_from_char("128.0.0.0/1",&dest); add_route(AF_INET, tun_ifindex, &dest, src, NULL, metric, RT_TABLE_MAIN); return(GOOD); } int del_tun_default_route_v4() { /* * Assign route to 0.0.0.0/1 and 128.0.0.0/1 via tun interface */ lisp_addr_t dest; lisp_addr_t *src = NULL; uint32_t metric = 0; metric = 0; lisp_addr_ippref_from_char("0.0.0.0/1",&dest); del_route(AF_INET, tun_ifindex, &dest, src, NULL, metric, RT_TABLE_MAIN); lisp_addr_ippref_from_char("128.0.0.0/1",&dest); del_route(AF_INET, tun_ifindex, &dest, src, NULL, metric, RT_TABLE_MAIN); return(GOOD); } int set_tun_default_route_v6() { /* * Assign route to ::/1 and 8000::/1 via tun interface */ lisp_addr_t dest; lisp_addr_t *src = NULL; uint32_t metric = 0; metric = 512; lisp_addr_ippref_from_char("::/1",&dest); add_route(AF_INET6, tun_ifindex, &dest, src, NULL, metric, RT_TABLE_MAIN); lisp_addr_ippref_from_char("8000::/1",&dest); add_route(AF_INET6, tun_ifindex, &dest, src, NULL, metric, RT_TABLE_MAIN); return(GOOD); } int del_tun_default_route_v6() { /* * Assign route to ::/1 and 8000::/1 via tun interface */ lisp_addr_t dest; lisp_addr_t *src = NULL; lisp_addr_t *gw = NULL; uint32_t metric = 0; metric = 512; lisp_addr_ippref_from_char("::/1",&dest); del_route(AF_INET6, tun_ifindex, &dest, src, gw, metric, RT_TABLE_MAIN); lisp_addr_ippref_from_char("8000::/1",&dest); del_route(AF_INET6, tun_ifindex, &dest, src, gw, metric, RT_TABLE_MAIN); return(GOOD); } int tun_updated_route (int command, iface_t *iface, lisp_addr_t *src_pref, lisp_addr_t *dst_pref, lisp_addr_t *gateway) { /* We check if the new route message contains a destination. If * it is, then the gateway address is not a default route. * Discard it */ if (command == ADD){ if (lisp_addr_ip_afi(gateway) != LM_AFI_NO_ADDR && lisp_addr_ip_afi(dst_pref) == LM_AFI_NO_ADDR) { /* Check if the addres is a global address*/ if (ip_addr_is_link_local(lisp_addr_ip(gateway)) == TRUE) { OOR_LOG(LDBG_3,"tun_update_route: the extractet address " "from the netlink messages is a local link address: %s " "discarded", lisp_addr_to_char(gateway)); return (GOOD); } /* Process the new gateway */ OOR_LOG(LDBG_1, "tun_update_route: Process new gateway " "associated to the interface %s: %s", iface->iface_name, lisp_addr_to_char(gateway)); tun_process_new_gateway(iface,gateway); } }else{ if (lisp_addr_ip_afi(gateway) != LM_AFI_NO_ADDR && lisp_addr_ip_afi(dst_pref) == LM_AFI_NO_ADDR) { /* Check if the addres is a global address*/ if (ip_addr_is_link_local(lisp_addr_ip(gateway)) == TRUE) { OOR_LOG(LDBG_3,"tun_update_route: the extractet address " "from the netlink messages is a local link address: %s " "discarded", lisp_addr_to_char(gateway)); return (GOOD); } /* Process the new gateway */ OOR_LOG(LDBG_1, "tun_update_route: Process remove gateway " "associated to the interface %s: %s", iface->iface_name, lisp_addr_to_char(gateway)); tun_process_rm_gateway(iface,gateway); } } return (GOOD); } int tun_updated_addr(iface_t *iface, lisp_addr_t *old_addr, lisp_addr_t *new_addr) { int old_addr_lafi, new_addr_ip_afi; int sckt; tun_dplane_data_t *data; data = (tun_dplane_data_t *)dplane_tun.datap_data; old_addr_lafi = lisp_addr_lafi(old_addr); new_addr_ip_afi = lisp_addr_ip_afi(new_addr); /* Check if the detected change of address is the same. */ if (lisp_addr_cmp(old_addr, new_addr) == 0) { OOR_LOG(LDBG_2, "tun_updated_addr: The change of address detected " "for interface %s doesn't affect (%s)", iface->iface_name, lisp_addr_to_char(new_addr)); /* We must rebind the socket just in case the address is from a * virtual interface which has changed its interface number */ switch (new_addr_ip_afi) { case AF_INET: bind_socket(iface->out_socket_v4, AF_INET, new_addr, 0); break; case AF_INET6: bind_socket(iface->out_socket_v6, AF_INET6, new_addr, 0); break; } return (GOOD); } /* If interface was down during initial configuration process and now it * is up. Create sockets */ if (old_addr_lafi == LM_AFI_NO_ADDR) { OOR_LOG(LDBG_2, "tun_updated_addr: Generating sockets for the initialized interface " "%s", lisp_addr_to_char(new_addr)); switch(new_addr_ip_afi){ case AF_INET: iface->out_socket_v4 = open_ip_raw_socket(AF_INET); sckt = iface->out_socket_v4; break; case AF_INET6: iface->out_socket_v6 = open_ip_raw_socket(AF_INET6); sckt = iface->out_socket_v6; break; default: /* basically to calm compiler and let the following fail for AF_INET7 */ sckt=0; return BAD; } if (iface->status == UP) { /* If no default control interface, recalculate it */ if ((data->default_out_iface_v4 == NULL && new_addr_ip_afi == AF_INET) || (data->default_out_iface_v6 == NULL && new_addr_ip_afi == AF_INET6)) { OOR_LOG(LDBG_2, "No default output interface. Recalculate new " "output interface"); tun_set_default_output_ifaces(); } } }else{ switch(new_addr_ip_afi){ case AF_INET: sckt = iface->out_socket_v4; break; case AF_INET6: sckt = iface->out_socket_v6; break; default: /* basically to calm compiler and let the following fail for AF_INET7 */ sckt=0; return BAD; } del_rule(new_addr_ip_afi, 0, iface->iface_index, iface->iface_index, RTN_UNICAST, old_addr, NULL, 0); } /* Rebind socket and add new routing */ add_rule(new_addr_ip_afi, 0, iface->iface_index, iface->iface_index, RTN_UNICAST, new_addr, NULL, 0); bind_socket(sckt, new_addr_ip_afi, new_addr,0); return (GOOD); } int tun_updated_link(iface_t *iface, int old_iface_index, int new_iface_index, int status) { tun_dplane_data_t *data; data = (tun_dplane_data_t *)dplane_tun.datap_data; /* In some OS when a virtual interface is removed and added again, * the index of the interface change. Search iface_t by the interface * name and update the index. */ if (old_iface_index != new_iface_index){ OOR_LOG(LDBG_2, "process_nl_new_link: The new index of the interface " "%s is: %d. Updating tables", iface->iface_name, iface->iface_index); /* Update routing tables and reopen sockets*/ if (iface->ipv4_address && !lisp_addr_is_no_addr(iface->ipv4_address)) { del_rule(AF_INET, 0, old_iface_index, old_iface_index, RTN_UNICAST, iface->ipv4_address, NULL, 0); add_rule(AF_INET, 0, new_iface_index, new_iface_index, RTN_UNICAST, iface->ipv4_address, NULL, 0); close(iface->out_socket_v4); iface->out_socket_v4 = open_ip_raw_socket( AF_INET); bind_socket(iface->out_socket_v4, AF_INET, iface->ipv4_address, 0); } if (iface->ipv6_address && !lisp_addr_is_no_addr(iface->ipv6_address)) { del_rule(AF_INET6, 0, old_iface_index, old_iface_index, RTN_UNICAST, iface->ipv6_address, NULL, 0); add_rule(AF_INET6, 0, new_iface_index, new_iface_index, RTN_UNICAST, iface->ipv6_address, NULL, 0); close(iface->out_socket_v6); iface->out_socket_v6 = open_ip_raw_socket(AF_INET6); bind_socket(iface->out_socket_v6,AF_INET6, iface->ipv6_address, 0); } } if (data->default_out_iface_v4 == iface || data->default_out_iface_v6 == iface || data->default_out_iface_v4 == NULL || data->default_out_iface_v6 == NULL){ OOR_LOG(LDBG_2,"Default output interface down. Recalculate new output " "interface"); tun_set_default_output_ifaces(); } return (GOOD); } void tun_process_new_gateway(iface_t *iface,lisp_addr_t *gateway) { lisp_addr_t **gw_addr = NULL; int afi = LM_AFI_NO_ADDR; int route_metric = 100; switch(lisp_addr_ip_afi(gateway)){ case AF_INET: gw_addr = &(iface->ipv4_gateway); afi = AF_INET; break; case AF_INET6: gw_addr = &(iface->ipv6_gateway); afi = AF_INET6; break; default: return; } if (*gw_addr == NULL || lisp_addr_is_no_addr(*gw_addr)) { // The default gateway of this interface is not deffined yet lisp_addr_del(*gw_addr); *gw_addr = lisp_addr_new(); lisp_addr_copy(*gw_addr,gateway); }else if (lisp_addr_cmp(*gw_addr, gateway) == 0){ OOR_LOG(LDBG_3,"tun_process_new_gateway: the gatweay address has not changed: %s. Discard message.", lisp_addr_to_char(gateway)); return; }else{ lisp_addr_copy(*gw_addr,gateway); } add_route(afi,iface->iface_index,NULL,NULL,gateway,route_metric,iface->iface_index); } void tun_process_rm_gateway(iface_t *iface,lisp_addr_t *gateway) { lisp_addr_t **gw_addr = NULL; int afi = LM_AFI_NO_ADDR; int route_metric = 100; switch(lisp_addr_ip_afi(gateway)){ case AF_INET: gw_addr = &(iface->ipv4_gateway); afi = AF_INET; break; case AF_INET6: gw_addr = &(iface->ipv6_gateway); afi = AF_INET6; break; default: return; } if (*gw_addr == NULL || lisp_addr_is_no_addr(*gw_addr)){ return; } del_route(afi,iface->iface_index,NULL,NULL,gateway,route_metric,iface->iface_index); lisp_addr_del(*gw_addr); *gw_addr = lisp_addr_new_lafi(LM_AFI_NO_ADDR); } void tun_set_default_output_ifaces() { tun_dplane_data_t *data; data = (tun_dplane_data_t *)dplane_tun.datap_data; data->default_out_iface_v4 = get_any_output_iface(AF_INET); if (data->default_out_iface_v4 != NULL) { OOR_LOG(LDBG_2,"Default IPv4 data iface %s: %s\n",data->default_out_iface_v4->iface_name, lisp_addr_to_char(data->default_out_iface_v4->ipv4_address)); } data->default_out_iface_v6 = get_any_output_iface(AF_INET6); if (data->default_out_iface_v6 != NULL) { OOR_LOG(LDBG_2,"Default IPv6 data iface %s: %s\n", data->default_out_iface_v6->iface_name, lisp_addr_to_char(data->default_out_iface_v6->ipv6_address)); } if (!data->default_out_iface_v4 && !data->default_out_iface_v6){ OOR_LOG(LCRIT,"NO OUTPUT IFACE: all the locators are down"); } } lisp_addr_t * tun_get_default_output_address(int afi) { lisp_addr_t *addr = NULL; tun_dplane_data_t *data; data = (tun_dplane_data_t *)dplane_tun.datap_data; switch (afi) { case AF_INET: if (data->default_out_iface_v4 != NULL) { addr = data->default_out_iface_v4->ipv4_address; } break; case AF_INET6: if (data->default_out_iface_v6 != NULL) { addr = data->default_out_iface_v6->ipv6_address; } break; default: OOR_LOG(LDBG_2, "tun_get_default_output_address: AFI %s not valid", afi); return(NULL); } return(addr); } int tun_get_default_output_socket(int afi) { int out_socket = ERR_SOCKET; tun_dplane_data_t *data; data = (tun_dplane_data_t *)dplane_tun.datap_data; switch (afi) { case AF_INET: if (data->default_out_iface_v4 != NULL) { out_socket = data->default_out_iface_v4->out_socket_v4; } break; case AF_INET6: if (data->default_out_iface_v6 != NULL) { out_socket = data->default_out_iface_v6->out_socket_v6; } break; default: OOR_LOG(LDBG_2, "tun_get_default_output_socket: AFI %s not valid", afi); break; } return (out_socket); } void tun_iface_remove_routing_rules(iface_t *iface) { if (iface->ipv4_address && !lisp_addr_is_no_addr(iface->ipv4_address)) { if (iface->ipv4_gateway && !lisp_addr_is_no_addr(iface->ipv4_gateway)) { del_route(AF_INET, iface->iface_index, NULL, NULL, iface->ipv4_gateway, 0, iface->iface_index); } del_rule(AF_INET, 0, iface->iface_index, iface->iface_index, RTN_UNICAST, iface->ipv4_address, NULL, 0); } if (iface->ipv6_address && !lisp_addr_is_no_addr(iface->ipv6_address)) { if (iface->ipv6_gateway && !lisp_addr_is_no_addr(iface->ipv6_gateway)) { del_route(AF_INET6, iface->iface_index, NULL, NULL, iface->ipv6_gateway, 0, iface->iface_index); } del_rule(AF_INET6, 0, iface->iface_index, iface->iface_index, RTN_UNICAST, iface->ipv6_address, NULL, 0); } } int tun_rm_fwd_from_entry(lisp_addr_t *eid_prefix, uint8_t is_local) { char * eid_prefix_char = lisp_addr_to_char(eid_prefix); glist_t *fwd_tpl_list, *pxtr_fwd_tpl_list; glist_entry_t *tpl_it; fwd_info_t *fi; tun_dplane_data_t *data = (tun_dplane_data_t *)dplane_tun.datap_data; packet_tuple_t *tpl; if (is_local){ return (tun_reset_all_fwd()); } if (strcmp(eid_prefix_char,FULL_IPv4_ADDRESS_SPACE) == 0){ // Update of the PeTR list for IPv4 EIDs or RTR list OOR_LOG(LDBG_3, "tun_rm_fwd_from_entry: Removing all the forwading entries association with the PeTRs for IPv4 EIDs"); pxtr_fwd_tpl_list = (glist_t *)shash_lookup(data->eid_to_dp_entries,FULL_IPv4_ADDRESS_SPACE); /* Remove all the entries associated with the PxTR */ while (glist_size(pxtr_fwd_tpl_list) > 0){ tpl = (packet_tuple_t *)glist_first_data(pxtr_fwd_tpl_list); fi = ttable_lookup(&(data->ttable), tpl); // When we recurively call this function using the associated_entry we will execute "else" statement where we also // update the list of entries associated with PxTR. tun_rm_fwd_from_entry(fi->associated_entry,is_local); } }else if(strcmp(eid_prefix_char,FULL_IPv6_ADDRESS_SPACE) == 0){ // Update of the PeTR list for IPv6 EIDs or RTR list OOR_LOG(LDBG_3, "tun_rm_fwd_from_entry: Removing all the forwading entries association with the PeTRs for IPv6 EIDs"); pxtr_fwd_tpl_list = (glist_t *)shash_lookup(data->eid_to_dp_entries,FULL_IPv6_ADDRESS_SPACE); /* Remove all the entries associated with the PxTR */ while (glist_size(pxtr_fwd_tpl_list) > 0){ tpl = (packet_tuple_t *)glist_first_data(pxtr_fwd_tpl_list); fi = ttable_lookup(&(data->ttable), tpl); // When we recurively call this function using the associated_entry we will execute "else" statement where we also // update the list of entries associated with PxTR. tun_rm_fwd_from_entry(fi->associated_entry,is_local); } }else{ OOR_LOG(LDBG_3, "tun_rm_fwd_from_entry: Removing all the forwading entries association with the EID %s",eid_prefix_char); fwd_tpl_list = (glist_t *)shash_lookup(data->eid_to_dp_entries,eid_prefix_char); if (!fwd_tpl_list){ OOR_LOG(LDBG_1, "tun_rm_fwd_from_entry: Entry %s not found in the shasht!",eid_prefix_char); return (BAD); } /* Check if it is a negative entry in order to remove also from PxTRs list */ tpl = (packet_tuple_t *)glist_first_data(fwd_tpl_list); fi = ttable_lookup(&(data->ttable), tpl); if (fi->neg_map_reply_act == ACT_NATIVE_FWD){ //negative mapping switch (lisp_addr_ip_afi(fi->associated_entry)){ case AF_INET: pxtr_fwd_tpl_list = (glist_t *)shash_lookup(data->eid_to_dp_entries,FULL_IPv4_ADDRESS_SPACE); break; case AF_INET6: pxtr_fwd_tpl_list = (glist_t *)shash_lookup(data->eid_to_dp_entries,FULL_IPv6_ADDRESS_SPACE); break; default: OOR_LOG(LDBG_1, "tun_rm_fwd_from_entry: Associated entry is not IP"); return (BAD); } glist_for_each_entry(tpl_it,fwd_tpl_list){ tpl = (packet_tuple_t *)glist_entry_data(tpl_it); glist_remove_obj(tpl,pxtr_fwd_tpl_list); } } /* Remove associated entry from eid_to_dp_entries */ shash_remove(data->eid_to_dp_entries, eid_prefix_char); } return (GOOD); } /* Remove all the fwd programmed in the data plane * Used when a change is produced in the local mappings */ int tun_reset_all_fwd() { tun_dplane_data_t *data = (tun_dplane_data_t *)dplane_tun.datap_data; shash_destroy(data->eid_to_dp_entries); data->eid_to_dp_entries = shash_new_managed((free_value_fn_t)glist_destroy); /* Insert entry for PeTRs */ shash_insert(data->eid_to_dp_entries, strdup(FULL_IPv4_ADDRESS_SPACE), glist_new()); shash_insert(data->eid_to_dp_entries, strdup(FULL_IPv6_ADDRESS_SPACE), glist_new()); return (GOOD); } tun_dplane_data_t * tun_dplane_data_new_init(oor_encap_t encap_type) { tun_dplane_data_t * data; data = xmalloc(sizeof(tun_dplane_data_t)); if (!data){ return (NULL); } data->encap_type = encap_type; data->eid_to_dp_entries = shash_new_managed((free_value_fn_t)glist_destroy); /* Insert entry for PeTRs */ shash_insert(data->eid_to_dp_entries, strdup(FULL_IPv4_ADDRESS_SPACE), glist_new()); shash_insert(data->eid_to_dp_entries, strdup(FULL_IPv6_ADDRESS_SPACE), glist_new()); ttable_init(&(data->ttable)); return (data); } void tun_dplane_data_free(tun_dplane_data_t *data) { if (!data){ return; } shash_destroy(data->eid_to_dp_entries); ttable_uninit(&(data->ttable)); free(data); } /* * Editor modelines * * vi: set shiftwidth=4 tabstop=4 expandtab: * :indentSize=4:tabSize=4:noTabs=true: */ oor-1.2.0/oor/data-plane/tun/tun.h000066400000000000000000000047251313612200500167040ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef TUN_H_ #define TUN_H_ #include "../ttable.h" #include "../encapsulations/vxlan-gpe.h" #include "../../lib/shash.h" #include "../../liblisp/liblisp.h" #define TUN_IFACE_NAME "lispTun0" #define TUN_RECEIVE_SIZE 2048 /* * From section 5.4.1 of LISP RFC (6830) * 1 . Define H to be the size, in* octets, of the outer header an ITR prepends to a packet. This includes the UDP and LISP header lengths. 2. Define L to be the size, in octets, of the maximum-sized packet an ITR can send to an ETR without the need for the ITR or any intermediate routers to fragment the packet. 3. Define an architectural constant S for the maximum size of a packet, in octets, an ITR must receive so the effective MTU can be met. That is, S = L - H. [...] This specification RECOMMENDS that L be defined as 1500. */ /* H = 40 (IPv6 header) + 8 (UDP header) + 8 (LISP header) + 4 (extra/safety) = 60 */ #define TUN_MTU 1440 /* 1500 - 60 = 1440 */ /* Tun MN variables */ int tun_receive_fd; int tun_ifindex; uint8_t *tun_receive_buf; lisp_addr_t * tun_get_default_output_address(int afi); int tun_get_default_output_socket(int); typedef struct iface iface_t; typedef struct tun_dplane_data_{ oor_encap_t encap_type; iface_t *default_out_iface_v4; iface_t *default_out_iface_v6; /* < char *eid -> glist_t > Used to find the fwd entries to be removed * of the data plane when there is a change with the mapping of the eid */ shash_t *eid_to_dp_entries; //< char *eid -> glist_t > /* Hash table containg the forward info from a tupla */ ttable_t ttable; }tun_dplane_data_t; tun_dplane_data_t * tun_get_datap_data(); int tun_reset_all_fwd(); extern data_plane_struct_t dplane_tun; #endif /* TUN_H_ */ oor-1.2.0/oor/data-plane/tun/tun_input.c000066400000000000000000000076241313612200500201170ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include #include #include "tun.h" #include "tun_input.h" #include "tun_output.h" #include "../../lib/packets.h" #include "../../lib/mem_util.h" #include "../../liblisp/liblisp.h" #include "../../lib/oor_log.h" /* static buffer to receive packets */ static uint8_t pkt_recv_buf[MAX_IP_PKT_LEN+1]; static lbuf_t pkt_buf; int tun_read_and_decap_pkt(int sock, lbuf_t *b, uint32_t *iid) { uint8_t ttl = 0, tos = 0; int afi; struct udphdr *udph; lisp_data_hdr_t *lisph; vxlan_gpe_hdr_t *vxlanh; int port; if (sock_data_recv(sock, b, &afi, &ttl, &tos) != GOOD) { return(BAD); } if (afi == AF_INET){ /* With input RAW UDP sockets in IPv4, we get the whole external * IPv4 packet */ lbuf_reset_ip(b); pkt_pull_ip(b); lbuf_reset_udp(b); }else{ /* With input RAW UDP sockets in IPv6, we get the whole external * UDP packet */ lbuf_reset_udp(b); } udph = pkt_pull_udp(b); if (ntohs(udplen(udph)) < 16){//8 udp header + 8 lisp header return (ERR_NOT_ENCAP); } /* FILTER UDP: with input RAW UDP sockets, we receive all UDP packets, * we only want LISP data ones */ switch (ntohs(udpdport(udph))){ case LISP_DATA_PORT: lisph = lisp_data_pull_hdr(b); if (LDHDR_LSB_BIT(lisph)){ *iid = lisp_data_hdr_get_iid(lisph); }else{ *iid = 0; } port = LISP_DATA_PORT; break; case VXLAN_GPE_DATA_PORT: vxlanh = vxlan_gpe_data_pull_hdr(b); if (VXLAN_HDR_VNI_BIT(vxlanh)){ *iid = vxlan_gpe_hdr_get_vni(vxlanh); } port = VXLAN_GPE_DATA_PORT; break; default: return (ERR_NOT_ENCAP); } /* RESET L3: prepare for output */ lbuf_reset_l3(b); /* UPDATE IP TOS and TTL. Checksum is also updated for IPv4 * NOTE: we always assume an IP payload*/ ip_hdr_set_ttl_and_tos(lbuf_data(b), ttl, tos); OOR_LOG(LDBG_3, "INPUT (%d): %s",port, ip_src_and_dst_to_char(lbuf_l3(b), "Inner IP: %s -> %s")); return(GOOD); } int tun_process_input_packet(sock_t *sl) { uint32_t iid; lbuf_use_stack(&pkt_buf, &pkt_recv_buf, MAX_IP_PKT_LEN); if (tun_read_and_decap_pkt(sl->fd, &pkt_buf, &iid) != GOOD) { return (BAD); } /* XXX Destination packet should be checked it belongs to this xTR */ if ((write(tun_receive_fd, lbuf_l3(&pkt_buf), lbuf_size(&pkt_buf))) < 0) { OOR_LOG(LDBG_2, "lisp_input: write error: %s\n ", strerror(errno)); } return (GOOD); } int tun_rtr_process_input_packet(struct sock *sl) { packet_tuple_t tpl; lbuf_use_stack(&pkt_buf, &pkt_recv_buf, MAX_IP_PKT_LEN); /* Reserve space in case the received packet was IPv6. In this case the IPv6 header is * not provided */ lbuf_reserve(&pkt_buf,LBUF_STACK_OFFSET); if (tun_read_and_decap_pkt(sl->fd, &pkt_buf, &(tpl.iid)) != GOOD) { return (BAD); } OOR_LOG(LDBG_3, "Forwarding packet to OUPUT for re-encapsulation"); lbuf_point_to_l3(&pkt_buf); lbuf_reset_ip(&pkt_buf); if (pkt_parse_5_tuple(&pkt_buf, &tpl) != GOOD) { return (BAD); } tun_output(&pkt_buf, &tpl); return(GOOD); } oor-1.2.0/oor/data-plane/tun/tun_input.h000066400000000000000000000021271313612200500201150ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef TUN_INPUT_H_ #define TUN_INPUT_H_ #include #include #include #include #include #include #include "tun_output.h" #include "../../defs.h" #include "../../lib/sockets.h" #include "../../lib/cksum.h" int tun_process_input_packet(struct sock *sl); int tun_rtr_process_input_packet(struct sock *sl); #endif /*TUN_IFACE_LIST_H_*/ oor-1.2.0/oor/data-plane/tun/tun_output.c000066400000000000000000000227201313612200500203120ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include #include "tun.h" #include "tun_output.h" #include "../encapsulations/vxlan-gpe.h" #include "../../fwd_policies/fwd_policy.h" #include "../../fwd_policies/flow_balancing/fwd_entry_tuple.h" #include "../../liblisp/liblisp.h" #include "../../lib/packets.h" #include "../../lib/sockets.h" #include "../../control/oor_control.h" #include "../../lib/oor_log.h" #include "../../lib/sockets-util.h" /* static buffer to receive packets */ static uint8_t pkt_recv_buf[TUN_RECEIVE_SIZE]; static lbuf_t pkt_buf; static int tun_output_multicast(lbuf_t *b, packet_tuple_t *tuple); static int tun_output_unicast(lbuf_t *b, packet_tuple_t *tuple); static int tun_forward_native(lbuf_t *b, lisp_addr_t *dst); static int tun_forward_native(lbuf_t *b, lisp_addr_t *dst) { int ret, sock, afi; OOR_LOG(LDBG_3, "Forwarding native to destination %s", lisp_addr_to_char(dst)); afi = lisp_addr_ip_afi(dst); sock = tun_get_default_output_socket(afi); if (sock == ERR_SOCKET) { OOR_LOG(LDBG_2, "tun_forward_native: No output interface for afi %d", afi); return (BAD); } ret = send_raw_packet(sock, lbuf_data(b), lbuf_size(b), lisp_addr_ip(dst)); return (ret); } static int make_mcast_addr(packet_tuple_t *tuple, lisp_addr_t *addr){ /* TODO this really needs optimization */ uint16_t plen; lcaf_addr_t *lcaf; if (ip_addr_is_multicast(lisp_addr_ip(&tuple->dst_addr))) { if (lisp_addr_lafi(&tuple->src_addr) != LM_AFI_IP || lisp_addr_lafi(&tuple->src_addr) != LM_AFI_IP) { OOR_LOG(LDBG_1, "tuple_get_dst_lisp_addr: (S,G) (%s, %s)pair is not " "of IP syntax!", lisp_addr_to_char(&tuple->src_addr), lisp_addr_to_char(&tuple->dst_addr)); return(BAD); } lisp_addr_set_lafi(addr, LM_AFI_LCAF); plen = ip_afi_to_default_mask(lisp_addr_ip_afi(&tuple->dst_addr)); lcaf = lisp_addr_get_lcaf(addr); lcaf_addr_set_mc(lcaf, &tuple->src_addr, &tuple->dst_addr, plen, plen, 0); } else { lisp_addr_set_lafi(addr, LM_AFI_NO_ADDR); } return(GOOD); } void tun_rm_dp_entry(packet_tuple_t *tuple) { tun_dplane_data_t *data = tun_get_datap_data(); ttable_remove(&(data->ttable), tuple); } static int tun_output_multicast(lbuf_t *b, packet_tuple_t *tuple) { glist_t *or_list = NULL; lisp_addr_t *src_rloc = NULL, *daddr = NULL, *dst_rloc = NULL; locator_t *locator = NULL; glist_entry_t *it = NULL; int *out_sock = NULL; OOR_LOG(LDBG_1, "Multicast packets not supported for now!"); return(GOOD); /* convert tuple to lisp_addr_t, to be used for map-cache lookup * TODO: should be a tad more efficient */ daddr = lisp_addr_new(); if (make_mcast_addr(tuple, daddr) != GOOD) { OOR_LOG(LWRN, "tun_output_multicast: Unable to determine " "destination address from tuple: src %s dst %s", lisp_addr_to_char(&tuple->src_addr), lisp_addr_to_char(&tuple->dst_addr)); return(BAD); } /* get the output RLOC list */ /* or_list = re_get_orlist(dst_eid); */ if (!or_list) { return(BAD); } glist_for_each_entry(it, or_list) { /* TODO: take locator out, just send mcaddr and out socket */ locator = (locator_t *) glist_entry_data(it); src_rloc = lcaf_mc_get_src(lisp_addr_get_lcaf(locator_addr(locator))); dst_rloc = lcaf_mc_get_grp(lisp_addr_get_lcaf(locator_addr(locator))); out_sock = get_out_socket_ptr_from_address(src_rloc); if (out_sock == NULL){ return (BAD); } lisp_data_encap(b, LISP_DATA_PORT, LISP_DATA_PORT, src_rloc, dst_rloc, 0); send_raw_packet(*out_sock, lbuf_data(b), lbuf_size(b),lisp_addr_ip(dst_rloc)); } glist_destroy(or_list); return (GOOD); } static int tun_output_unicast(lbuf_t *b, packet_tuple_t *tuple) { fwd_info_t *fi; fwd_entry_tuple_t *fe; glist_t *fwd_tuple_lst, *pxtr_fwd_tuple_list; tun_dplane_data_t *dp_data; dp_data = tun_get_datap_data(); fi = ttable_lookup(&(dp_data->ttable), tuple); if (!fi) { fi = (fwd_info_t *)ctrl_get_forwarding_info(tuple); if (!fi){ return (BAD); } fe = (fwd_entry_tuple_t *)fi->dp_conf_inf; if (fe && fe->srloc && fe->drloc) { fe->out_sock = get_out_socket_ptr_from_address(fe->srloc); } // While we can not get iid from interface, we insert the tupla with iid = 0. // We only support a same EID prefix per xTR fe->tuple->iid = 0; // fe->tuple is cloned from tuple if (ttable_insert(&(dp_data->ttable), fe->tuple, fi) != GOOD){ /* If table is full, reset the data plane */ tun_reset_all_fwd(); ttable_insert(&(dp_data->ttable), fe->tuple, fi); } /* Associate eid with fwd_info */ fwd_tuple_lst = (glist_t *)shash_lookup(dp_data->eid_to_dp_entries,lisp_addr_to_char(fi->associated_entry)); if (!fwd_tuple_lst){ fwd_tuple_lst = glist_new_managed((glist_del_fct)tun_rm_dp_entry); shash_insert(dp_data->eid_to_dp_entries, strdup(lisp_addr_to_char(fi->associated_entry)), fwd_tuple_lst); } glist_add(fe->tuple,fwd_tuple_lst); OOR_LOG(LDBG_3, "tun_output_unicast: The tupla [%s] has been associated with the EID %s", pkt_tuple_to_char(tuple),lisp_addr_to_char(fi->associated_entry)); if(fi->neg_map_reply_act == ACT_NATIVE_FWD){ // Forwarding entry should be also associated with PeTRs list switch (lisp_addr_ip_afi(fi->associated_entry)){ case AF_INET: pxtr_fwd_tuple_list = (glist_t *)shash_lookup(dp_data->eid_to_dp_entries,FULL_IPv4_ADDRESS_SPACE); break; case AF_INET6: pxtr_fwd_tuple_list = (glist_t *)shash_lookup(dp_data->eid_to_dp_entries,FULL_IPv6_ADDRESS_SPACE); break; default: OOR_LOG(LDBG_3, "tun_output_unicast: Forwarding to PeTR is only for IP EIDs. It should never reach here"); return (BAD); } glist_add(fe->tuple,pxtr_fwd_tuple_list); OOR_LOG(LDBG_3, " and with PeTRs"); } }else{ fe = fi->dp_conf_inf; } /* Packets with no/negative map cache entry AND no PETR * OR packets with missing src or dst RLOCs*/ if (!fe || !fe->srloc || !fe->drloc) { switch (fi->neg_map_reply_act){ case ACT_NO_ACTION: case ACT_SEND_MREQ: case ACT_DROP: OOR_LOG(LDBG_3, "tun_output_unicast: Packet dropped"); return (GOOD); case ACT_NATIVE_FWD: return(tun_forward_native(b, &tuple->dst_addr)); } } OOR_LOG(LDBG_3,"OUTPUT: Sending encapsulated packet: RLOC %s -> %s\n", lisp_addr_to_char(fe->srloc), lisp_addr_to_char(fe->drloc)); switch (fi->encap){ case ENCP_LISP: lisp_data_encap(b, LISP_DATA_PORT, LISP_DATA_PORT, fe->srloc, fe->drloc, fe->iid); break; case ENCP_VXLAN_GPE: vxlan_gpe_data_encap(b, VXLAN_GPE_DATA_PORT, VXLAN_GPE_DATA_PORT, fe->srloc, fe->drloc, fe->iid); break; } return(send_raw_packet(*(fe->out_sock), lbuf_data(b), lbuf_size(b), lisp_addr_ip(fe->drloc))); } int tun_output(lbuf_t *b, packet_tuple_t *tpl) { OOR_LOG(LDBG_3,"OUTPUT: Received EID %s -> %s, Proto: %d, Port: %d -> %d ", lisp_addr_to_char(&tpl->src_addr), lisp_addr_to_char(&tpl->dst_addr), tpl->protocol, tpl->src_port, tpl->dst_port); /* If already LISP packet, do not encapsulate again */ if (pkt_tuple_is_lisp(tpl)) { OOR_LOG(LDBG_3,"OUTPUT: Is a lisp packet, do not encapsulate again"); return (tun_forward_native(b, &tpl->dst_addr)); } if (ip_addr_is_multicast(lisp_addr_ip(&tpl->dst_addr))) { tun_output_multicast(b, tpl); } else { tun_output_unicast(b, tpl); } return(GOOD); } int tun_output_recv(sock_t *sl) { packet_tuple_t tpl; lbuf_use_stack(&pkt_buf, &pkt_recv_buf, TUN_RECEIVE_SIZE); lbuf_reserve(&pkt_buf, LBUF_STACK_OFFSET); if (sock_recv(sl->fd, &pkt_buf) != GOOD) { OOR_LOG(LWRN, "OUTPUT: Error while reading from tun!"); return (BAD); } lbuf_reset_ip(&pkt_buf); if (pkt_parse_5_tuple(&pkt_buf, &tpl) != GOOD) { return (BAD); } /* XXX Since OOR doesn't support same local prefixes with different IIDs when * operating as a XTR or MN, we use IID = 0 to calculate the hash of the ttable. * The actual IID to be used on the encapsulation processed is already stored * in the forwarding entry, which is obtained on a ttable miss.*/ tpl.iid = 0; tun_output(&pkt_buf, &tpl); return (GOOD); } oor-1.2.0/oor/data-plane/tun/tun_output.h000066400000000000000000000021331313612200500203130ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef TUN_OUTPUT_H_ #define TUN_OUTPUT_H_ #include #include #include #include #include #include #include #include "../../defs.h" #include "../../iface_list.h" #include "../../oor_external.h" #include "../../lib/cksum.h" int tun_output_recv(sock_t *sl); int tun_output(lbuf_t *, packet_tuple_t *); #endif /*TUN_OUTPUT_H_*/ oor-1.2.0/oor/data-plane/vpnapi/000077500000000000000000000000001313612200500164045ustar00rootroot00000000000000oor-1.2.0/oor/data-plane/vpnapi/vpnapi.c000066400000000000000000000367701313612200500200620ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include #include "vpnapi.h" #include "vpnapi_input.h" #include "vpnapi_output.h" #include "../data-plane.h" #include "../encapsulations/vxlan-gpe.h" #include "../../iface_list.h" #include "../../oor_external.h" #include "../../oor_jni.h" #include "../../fwd_policies/fwd_policy.h" #include "../../lib/oor_log.h" #include "../../net_mgr/net_mgr.h" int vpnapi_init(oor_dev_type_e dev_type, oor_encap_t encap_type,...); void vpnapi_uninit(); int vpnapi_add_datap_iface_addr(iface_t *iface, int afi); int vpnapi_add_datap_iface_gw(iface_t *iface, int afi); int vpnapi_register_lcl_mapping(oor_dev_type_e dev_type, mapping_t *map); int vpnapi_deregister_lcl_mapping(oor_dev_type_e dev_type, mapping_t *map); int vpnapi_updated_route(int command, iface_t *iface, lisp_addr_t *src_pref, lisp_addr_t *dst_pref, lisp_addr_t *gw); void vpnapi_process_new_gateway(iface_t *iface,lisp_addr_t *gateway); int vpnapi_updated_addr(iface_t *iface,lisp_addr_t *old_addr,lisp_addr_t *new_addr); int vpnapi_update_link(iface_t *iface, int old_iface_index, int new_iface_index, int status); int vpnapi_reset_socket(int fd, int afi); int vpnapi_rm_fwd_from_entry(lisp_addr_t *eid_prefix, uint8_t is_local); vpnapi_data_t * vpnapi_data_new_init(oor_encap_t encap_type, int tun_socket, int ipv4_data_socket, int ipv6_data_socket); void vpnapi_data_free(vpnapi_data_t *data); data_plane_struct_t dplane_vpnapi = { .datap_init = vpnapi_init, .datap_uninit = vpnapi_uninit, .datap_add_iface_addr = vpnapi_add_datap_iface_addr, .datap_add_iface_gw = vpnapi_add_datap_iface_gw, .datap_register_lcl_mapping = vpnapi_register_lcl_mapping, .datap_deregister_lcl_mapping = vpnapi_deregister_lcl_mapping, .datap_input_packet = vpnapi_process_input_packet, .datap_rtr_input_packet = vpnapi_rtr_process_input_packet, .datap_output_packet = vpnapi_output_recv, .datap_updated_route = vpnapi_updated_route, .datap_updated_addr = vpnapi_updated_addr, .datap_update_link = vpnapi_update_link, .datap_rm_fwd_from_entry = vpnapi_rm_fwd_from_entry, .datap_reset_all_fwd = vpnapi_reset_all_fwd, .datap_data = NULL }; inline vpnapi_data_t * vpnapi_get_datap_data() { return ((vpnapi_data_t *)dplane_vpnapi.datap_data); } int vpnapi_init(oor_dev_type_e dev_type, oor_encap_t encap_type,...) { int (*cb_func)(sock_t *) = NULL; int tun_fd, ipv4_data_socket, ipv6_data_socket; va_list ap; int data_port; /* Get the extra parameter of the function */ va_start(ap, encap_type); tun_fd = va_arg(ap, int); va_end(ap); sockmstr_register_read_listener(smaster, vpnapi_output_recv, NULL,tun_fd); switch (dev_type){ case MN_MODE: case xTR_MODE: cb_func = vpnapi_process_input_packet; break; case RTR_MODE: cb_func = vpnapi_rtr_process_input_packet; break; default: return (BAD); } switch (encap_type){ case ENCP_LISP: data_port = LISP_DATA_PORT; break; case ENCP_VXLAN_GPE: data_port = VXLAN_GPE_DATA_PORT; break; } if (default_rloc_afi != AF_INET6){ ipv4_data_socket = open_data_datagram_input_socket(AF_INET, data_port); sockmstr_register_read_listener(smaster, cb_func, NULL,ipv4_data_socket); oor_jni_protect_socket(ipv4_data_socket); }else { ipv4_data_socket = ERR_SOCKET; } if (default_rloc_afi != AF_INET){ ipv6_data_socket = open_data_datagram_input_socket(AF_INET6, data_port); sockmstr_register_read_listener(smaster, cb_func, NULL,ipv6_data_socket); oor_jni_protect_socket(ipv6_data_socket); }else { ipv6_data_socket = ERR_SOCKET; } dplane_vpnapi.datap_data = (void *)vpnapi_data_new_init(encap_type, tun_fd, ipv4_data_socket, ipv6_data_socket); if (!(dplane_vpnapi.datap_data)){ return (BAD); } return (GOOD); } void vpnapi_uninit() { vpnapi_data_free(dplane_vpnapi.datap_data); } int vpnapi_add_datap_iface_addr(iface_t *iface, int afi) { return (GOOD); } int vpnapi_add_datap_iface_gw(iface_t *iface, int afi) { return (GOOD); } int vpnapi_register_lcl_mapping(oor_dev_type_e dev_type, mapping_t *map) { return (GOOD); } int vpnapi_deregister_lcl_mapping(oor_dev_type_e dev_type, mapping_t *map) { return (GOOD); } int vpnapi_updated_route(int command, iface_t *iface, lisp_addr_t *src_pref, lisp_addr_t *dst_pref, lisp_addr_t *gateway) { if (lisp_addr_ip_afi(gateway) != LM_AFI_NO_ADDR && lisp_addr_ip_afi(dst_pref) == LM_AFI_NO_ADDR) { /* Check if the addres is a global address*/ if (ip_addr_is_link_local(lisp_addr_ip(gateway)) == TRUE) { OOR_LOG(LDBG_3,"vpnapi_updated_route: the extractet address " "from the netlink messages is a local link address: %s " "discarded", lisp_addr_to_char(gateway)); return (GOOD); } /* Process the new gateway */ OOR_LOG(LDBG_1, "vpnapi_updated_route: Process new gateway " "associated to the interface %s: %s", iface->iface_name, lisp_addr_to_char(gateway)); vpnapi_process_new_gateway(iface,gateway); } return (GOOD); } void vpnapi_process_new_gateway(iface_t *iface,lisp_addr_t *gateway) { lisp_addr_t **gw_addr = NULL; int afi; vpnapi_data_t *data; afi = lisp_addr_ip_afi(gateway); switch(afi){ case AF_INET: gw_addr = &(iface->ipv4_gateway); break; case AF_INET6: gw_addr = &(iface->ipv6_gateway); break; default: return; } if (*gw_addr == NULL || lisp_addr_is_no_addr(*gw_addr)) { // The default gateway of this interface is not deffined yet lisp_addr_del (*gw_addr); *gw_addr = lisp_addr_new(); lisp_addr_copy(*gw_addr,gateway); }else if (lisp_addr_cmp(*gw_addr, gateway) == 0){ OOR_LOG(LDBG_3,"tun_process_new_gateway: the gatweay address has not changed: %s. Discard message.", lisp_addr_to_char(gateway)); return; }else{ lisp_addr_copy(*gw_addr,gateway); } if (iface->status != UP){ OOR_LOG(LDBG_1,"vpnapi_process_new_gateway: Probably the interface %s is UP " "but we didn't receive netlink indicating this. Checking it", iface->iface_name,iface->iface_name); iface->status = net_mgr->netm_get_iface_status(iface->iface_name); } data = (vpnapi_data_t *)dplane_vpnapi.datap_data; /* Recreate sockets */ if (afi == AF_INET){ vpnapi_reset_socket(data->ipv4_data_socket,AF_INET); }else{ vpnapi_reset_socket(data->ipv6_data_socket,AF_INET6); } } int vpnapi_updated_addr(iface_t *iface,lisp_addr_t *old_addr,lisp_addr_t *new_addr) { int new_addr_ip_afi; vpnapi_data_t * data; data = (vpnapi_data_t *)dplane_vpnapi.datap_data; new_addr_ip_afi = lisp_addr_ip_afi(new_addr); /* Check if the detected change of address id the same. */ if (lisp_addr_cmp(old_addr, new_addr) == 0) { OOR_LOG(LDBG_2, "vpnapi_updated_addr: The change of address detected " "for interface %s doesn't affect", iface->iface_name); return (GOOD); }; switch (new_addr_ip_afi){ case AF_INET: vpnapi_reset_socket(data->ipv4_data_socket, AF_INET); break; case AF_INET6: vpnapi_reset_socket(data->ipv6_data_socket, AF_INET6); break; default: return (BAD); } return (GOOD); } int vpnapi_update_link(iface_t *iface, int old_iface_index, int new_iface_index, int status) { vpnapi_data_t * data; data = (vpnapi_data_t *)dplane_vpnapi.datap_data; /* In some OS when a virtual interface is removed and added again, * the index of the interface change. Search iface_t by the interface * name and update the index. */ if (old_iface_index != new_iface_index){ OOR_LOG(LDBG_2, "vpnapi_update_link: The new index of the interface " "%s is: %d", iface->iface_name,iface->iface_index); } if (default_rloc_afi != AF_INET6){ vpnapi_reset_socket(data->ipv4_data_socket, AF_INET); } if (default_rloc_afi != AF_INET){ vpnapi_reset_socket(data->ipv6_data_socket, AF_INET6); } return (GOOD); } int vpnapi_reset_socket(int fd, int afi) { sock_t *old_sock; int new_fd; vpnapi_data_t * data; int src_port; data = (vpnapi_data_t *)dplane_vpnapi.datap_data; old_sock = sockmstr_register_get_by_fd(smaster,fd); switch (data->encap_type){ case ENCP_LISP: src_port = LISP_DATA_PORT; break; case ENCP_VXLAN_GPE: src_port = VXLAN_GPE_DATA_PORT; break; } switch (afi){ case AF_INET: OOR_LOG(LDBG_2,"reset_socket: Reset IPv4 data socket"); new_fd = open_data_datagram_input_socket(AF_INET,src_port); if (new_fd == ERR_SOCKET){ OOR_LOG(LDBG_2,"vpnapi_reset_socket: Error recreating the socket"); return (BAD); } data->ipv4_data_socket = new_fd; break; case AF_INET6: OOR_LOG(LDBG_2,"reset_socket: Reset IPv6 data socket"); new_fd = open_data_datagram_input_socket(AF_INET6,src_port); if (new_fd == ERR_SOCKET){ OOR_LOG(LDBG_2,"vpnapi_reset_socket: Error recreating the socket"); return (BAD); } data->ipv6_data_socket = new_fd; break; default: return (BAD); } sockmstr_register_read_listener(smaster,old_sock->recv_cb,old_sock->arg,new_fd); sockmstr_unregister_read_listenedr(smaster,old_sock); /* Protect the socket from loops in the system*/ oor_jni_protect_socket(new_fd); return (GOOD); } int vpnapi_rm_fwd_from_entry(lisp_addr_t *eid_prefix, uint8_t is_local) { char * eid_prefix_char = lisp_addr_to_char(eid_prefix); glist_t *fwd_tpl_list, *pxtr_fwd_tpl_list; glist_entry_t *tpl_it; fwd_info_t *fi; vpnapi_data_t *data = (vpnapi_data_t *)dplane_vpnapi.datap_data; packet_tuple_t *tpl; if (is_local){ return (vpnapi_reset_all_fwd()); } if (strcmp(eid_prefix_char,FULL_IPv4_ADDRESS_SPACE) == 0){ // Update of the PeTR list for IPv4 EIDs or RTR list OOR_LOG(LDBG_3, "vpnapi_rm_fwd_from_entry: Removing all the forwading entries association with the PeTRs for IPv4 EIDs"); pxtr_fwd_tpl_list = (glist_t *)shash_lookup(data->eid_to_dp_entries,FULL_IPv4_ADDRESS_SPACE); /* Remove all the entries associated with the PxTR */ while (glist_size(pxtr_fwd_tpl_list) > 0){ tpl = (packet_tuple_t *)glist_first_data(pxtr_fwd_tpl_list); fi = ttable_lookup(&(data->ttable), tpl); // When we recurively call this function using the associated_entry we will execute "else" statement where we also // update the list of entries associated with PxTR. vpnapi_rm_fwd_from_entry(fi->associated_entry,is_local); } }else if(strcmp(eid_prefix_char,FULL_IPv6_ADDRESS_SPACE) == 0){ // Update of the PeTR list for IPv6 EIDs or RTR list OOR_LOG(LDBG_3, "vpnapi_rm_fwd_from_entry: Removing all the forwading entries association with the PeTRs for IPv6 EIDs"); pxtr_fwd_tpl_list = (glist_t *)shash_lookup(data->eid_to_dp_entries,FULL_IPv6_ADDRESS_SPACE); /* Remove all the entries associated with the PxTR */ while (glist_size(pxtr_fwd_tpl_list) > 0){ tpl = (packet_tuple_t *)glist_first_data(pxtr_fwd_tpl_list); fi = ttable_lookup(&(data->ttable), tpl); // When we recurively call this function using the associated_entry we will execute "else" statement where we also // update the list of entries associated with PxTR. vpnapi_rm_fwd_from_entry(fi->associated_entry,is_local); } }else{ OOR_LOG(LDBG_3, "vpnapi_rm_fwd_from_entry: Removing all the forwading entries association with the EID %s",eid_prefix_char); fwd_tpl_list = (glist_t *)shash_lookup(data->eid_to_dp_entries,eid_prefix_char); if (!fwd_tpl_list){ OOR_LOG(LDBG_1, "vpnapi_rm_fwd_from_entry: Entry %s not found in the shasht!",eid_prefix_char); return (BAD); } /* Check if it is a negative entry in order to remove also from PxTRs list */ tpl = (packet_tuple_t *)glist_first_data(fwd_tpl_list); fi = ttable_lookup(&(data->ttable), tpl); if (fi->neg_map_reply_act == ACT_NATIVE_FWD){ //negative mapping switch (lisp_addr_ip_afi(fi->associated_entry)){ case AF_INET: pxtr_fwd_tpl_list = (glist_t *)shash_lookup(data->eid_to_dp_entries,FULL_IPv4_ADDRESS_SPACE); break; case AF_INET6: pxtr_fwd_tpl_list = (glist_t *)shash_lookup(data->eid_to_dp_entries,FULL_IPv6_ADDRESS_SPACE); break; default: OOR_LOG(LDBG_1, "vpnapi_rm_fwd_from_entry: Associated entry is not IP"); return (BAD); } glist_for_each_entry(tpl_it,fwd_tpl_list){ tpl = (packet_tuple_t *)glist_entry_data(tpl_it); glist_remove_obj(tpl,pxtr_fwd_tpl_list); } } /* Remove associated entry from eid_to_dp_entries */ shash_remove(data->eid_to_dp_entries, eid_prefix_char); } return (GOOD); } /* Remove all the fwd programmed in the data plane * Used when a change is produced in the local mappings */ int vpnapi_reset_all_fwd() { vpnapi_data_t *data = (vpnapi_data_t *)dplane_vpnapi.datap_data; shash_destroy(data->eid_to_dp_entries); data->eid_to_dp_entries = shash_new_managed((free_value_fn_t)glist_destroy); /* Insert entry for PeTRs */ shash_insert(data->eid_to_dp_entries, strdup(FULL_IPv4_ADDRESS_SPACE), glist_new()); shash_insert(data->eid_to_dp_entries, strdup(FULL_IPv6_ADDRESS_SPACE), glist_new()); return (GOOD); } vpnapi_data_t * vpnapi_data_new_init(oor_encap_t encap_type, int tun_socket, int ipv4_data_socket, int ipv6_data_socket) { vpnapi_data_t * data; data = xmalloc(sizeof(vpnapi_data_t)); if (!data){ return (NULL); } data->encap_type = encap_type; data->tun_socket = tun_socket; data->ipv4_data_socket = ipv4_data_socket; data->ipv6_data_socket = ipv6_data_socket; data->eid_to_dp_entries = shash_new_managed((free_value_fn_t)glist_destroy); /* Insert entry for PeTRs */ shash_insert(data->eid_to_dp_entries, strdup(FULL_IPv4_ADDRESS_SPACE), glist_new()); shash_insert(data->eid_to_dp_entries, strdup(FULL_IPv6_ADDRESS_SPACE), glist_new()); ttable_init(&(data->ttable)); return (data); } void vpnapi_data_free(vpnapi_data_t *data) { if (!data){ return; } shash_destroy(data->eid_to_dp_entries); ttable_uninit(&(data->ttable)); free(data); } oor-1.2.0/oor/data-plane/vpnapi/vpnapi.h000066400000000000000000000025121313612200500200520ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef VPN_API_H_ #define VPN_API_H_ #include "../ttable.h" #include "../../lib/shash.h" typedef struct vpnapi_data_ { oor_encap_t encap_type; int tun_socket; int ipv4_data_socket; int ipv6_data_socket; /* < char *eid -> glist_t > Used to find the fwd entries to be removed * of the data plane when there is a change with the mapping of the eid */ shash_t *eid_to_dp_entries; //< char *eid -> glist_t > /* Hash table containg the forward info from a tupla */ ttable_t ttable; } vpnapi_data_t; vpnapi_data_t * vpnapi_get_datap_data(); int vpnapi_reset_all_fwd(); #endif /* VPN_API_H_ */ oor-1.2.0/oor/data-plane/vpnapi/vpnapi_input.c000066400000000000000000000071761313612200500212770ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include #include #include "vpnapi.h" #include "vpnapi_input.h" #include "vpnapi_output.h" #include "../data-plane.h" #include "../encapsulations/vxlan-gpe.h" #include "../../lib/packets.h" #include "../../lib/mem_util.h" #include "../../liblisp/liblisp.h" #include "../../lib/oor_log.h" /* static buffer to receive packets */ static uint8_t pkt_recv_buf[MAX_IP_PKT_LEN+1]; static lbuf_t pkt_buf; int vpnapi_read_and_decap_pkt(int sock, lbuf_t *b, uint32_t *iid) { uint8_t ttl = 0, tos = 0; int afi, port; lisp_data_hdr_t *lisp_hdr; vxlan_gpe_hdr_t *vxlan_hdr; vpnapi_data_t *data; data = vpnapi_get_datap_data(); if (sock_data_recv(sock, b, &afi, &ttl, &tos) != GOOD) { return(BAD); } if (lbuf_size(b) < 8){ // 8-> At least LISP header size return (ERR_NOT_ENCAP); } switch (data->encap_type){ case ENCP_LISP: lisp_hdr = lisp_data_pull_hdr(b); if (LDHDR_LSB_BIT(lisp_hdr)){ *iid = lisp_data_hdr_get_iid(lisp_hdr); }else{ *iid = 0; } port = LISP_DATA_PORT; break; case ENCP_VXLAN_GPE: vxlan_hdr = vxlan_gpe_data_pull_hdr(b); if (VXLAN_HDR_VNI_BIT(vxlan_hdr)){ *iid = vxlan_gpe_hdr_get_vni(vxlan_hdr); } port = VXLAN_GPE_DATA_PORT; break; default: return (ERR_NOT_ENCAP); } /* RESET L3: prepare for output */ lbuf_reset_l3(b); /* UPDATE IP TOS and TTL. Checksum is also updated for IPv4 * NOTE: we always assume an IP payload*/ ip_hdr_set_ttl_and_tos(lbuf_data(b), ttl, tos); OOR_LOG(LDBG_3, "INPUT (%d): %s",port, ip_src_and_dst_to_char(lbuf_l3(b), "Inner IP: %s -> %s")); return(GOOD); } int vpnapi_process_input_packet(sock_t *sl) { uint32_t iid; vpnapi_data_t *data; data = (vpnapi_data_t *)dplane_vpnapi.datap_data; lbuf_use_stack(&pkt_buf, &pkt_recv_buf, MAX_IP_PKT_LEN); if (vpnapi_read_and_decap_pkt(sl->fd, &pkt_buf, &iid) != GOOD) { return (BAD); } /* XXX Destination packet should be checked it belongs to this xTR */ if ((write(data->tun_socket, lbuf_l3(&pkt_buf), lbuf_size(&pkt_buf))) < 0) { OOR_LOG(LDBG_2, "lisp_input: write error: %s\n ", strerror(errno)); } return (GOOD); } int vpnapi_rtr_process_input_packet(sock_t *sl) { packet_tuple_t tpl; lbuf_use_stack(&pkt_buf, &pkt_recv_buf, MAX_IP_PKT_LEN); /* Reserve space in case the received packet was IPv6. In this case the IPv6 header is * not provided */ lbuf_reserve(&pkt_buf,LBUF_STACK_OFFSET); if (vpnapi_read_and_decap_pkt(sl->fd, &pkt_buf, &(tpl.iid)) != GOOD) { return (BAD); } OOR_LOG(LDBG_3, "Forwarding packet to OUPUT for re-encapsulation"); lbuf_point_to_l3(&pkt_buf); lbuf_reset_ip(&pkt_buf); if (pkt_parse_5_tuple(&pkt_buf, &tpl) != GOOD) { return (BAD); } vpnapi_output(&pkt_buf, &tpl); return(GOOD); } oor-1.2.0/oor/data-plane/vpnapi/vpnapi_input.h000066400000000000000000000016101313612200500212670ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef VPNAPI_INPUT_H_ #define VPNAPI_INPUT_H_ #include "../../lib/sockets.h" int vpnapi_process_input_packet(sock_t *sl); int vpnapi_rtr_process_input_packet(sock_t *sl); #endif /* VPNAPI_INPUT_H_ */ oor-1.2.0/oor/data-plane/vpnapi/vpnapi_output.c000066400000000000000000000160571313612200500214760ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include #include "vpnapi_output.h" #include "vpnapi.h" #include "../data-plane.h" #include "../ttable.h" #include "../encapsulations/vxlan-gpe.h" #include "../../fwd_policies/fwd_policy.h" #include "../../fwd_policies/flow_balancing/fwd_entry_tuple.h" #include "../../liblisp/liblisp.h" #include "../../lib/packets.h" #include "../../lib/sockets.h" #include "../../control/oor_control.h" #include "../../lib/oor_log.h" #include "../../lib/sockets-util.h" /* static buffer to receive packets */ static uint8_t pkt_recv_buf[VPNAPI_RECEIVE_SIZE]; static lbuf_t pkt_buf; static int vpnapi_output_unicast(lbuf_t *b, packet_tuple_t *tuple); static int vpnapi_forward_native(lbuf_t *b, lisp_addr_t *dst); void vpnapi_rm_dp_entry(packet_tuple_t *tuple); static int vpnapi_forward_native(lbuf_t *b, lisp_addr_t *dst) { /* XXX Forward native not supported in VPNAPI */ return (BAD); } static int vpnapi_output_unicast(lbuf_t *b, packet_tuple_t *tuple) { fwd_info_t *fi; fwd_entry_tuple_t *fe; glist_t *fwd_tuple_lst, *pxtr_fwd_tuple_list; vpnapi_data_t *dp_data; int dst_port; dp_data = vpnapi_get_datap_data(); fi = ttable_lookup(&(dp_data->ttable), tuple); if (!fi) { fi = ctrl_get_forwarding_info(tuple); if (!fi){ return (BAD); } fe = (fwd_entry_tuple_t *)fi->dp_conf_inf; if (fe && fe->srloc && fe->drloc) { switch (lisp_addr_ip_afi(fe->srloc)){ case AF_INET: fe->out_sock = &(dp_data->ipv4_data_socket); break; case AF_INET6: fe->out_sock = &(dp_data->ipv6_data_socket); break; default: OOR_LOG(LDBG_3,"OUTPUT: No output socket for afi %d", lisp_addr_ip_afi(fe->srloc)); return(BAD); } } // While we can not get iid from interface, we insert the tupla with iid = 0. // We only support a same EID prefix per xTR fe->tuple->iid = 0; // fe->tuple is cloned from tuple if (ttable_insert(&(dp_data->ttable), fe->tuple, fi) != GOOD){ /* If table is full, reset the data plane */ vpnapi_reset_all_fwd(); ttable_insert(&(dp_data->ttable), fe->tuple, fi); } /* Associate eid with fwd_info.*/ fwd_tuple_lst = (glist_t *)shash_lookup(dp_data->eid_to_dp_entries,lisp_addr_to_char(fi->associated_entry)); if (!fwd_tuple_lst){ fwd_tuple_lst = glist_new_managed((glist_del_fct)vpnapi_rm_dp_entry); shash_insert(dp_data->eid_to_dp_entries, strdup(lisp_addr_to_char(fi->associated_entry)), fwd_tuple_lst); } glist_add(fe->tuple,fwd_tuple_lst); OOR_LOG(LDBG_3, "vpnapi_output_unicast: The tupla [%s] has been associated with the EID %s", pkt_tuple_to_char(tuple),lisp_addr_to_char(fi->associated_entry)); if(fi->neg_map_reply_act == ACT_NATIVE_FWD){ // Forwarding entry should be also associated with PeTRs list switch (lisp_addr_ip_afi(fi->associated_entry)){ case AF_INET: pxtr_fwd_tuple_list = (glist_t *)shash_lookup(dp_data->eid_to_dp_entries,FULL_IPv4_ADDRESS_SPACE); break; case AF_INET6: pxtr_fwd_tuple_list = (glist_t *)shash_lookup(dp_data->eid_to_dp_entries,FULL_IPv6_ADDRESS_SPACE); break; default: OOR_LOG(LDBG_3, "vpnapi_output_unicast: Forwarding to PeTR is only for IP EIDs. It should never reach here"); return (BAD); } glist_add(fe->tuple,pxtr_fwd_tuple_list); OOR_LOG(LDBG_3, " and with PeTRs"); } }else{ fe = fi->dp_conf_inf; } /* Packets with no/negative map cache entry AND no PETR * OR packets with missing src or dst RLOCs*/ if (!fe || !fe->srloc || !fe->drloc) { switch (fi->neg_map_reply_act){ case ACT_NO_ACTION: case ACT_SEND_MREQ: case ACT_NATIVE_FWD: case ACT_DROP: OOR_LOG(LDBG_3,"OUTPUT: Packet with non lisp destination. No PeTRs compatibles to be used. Discarding packet"); return (GOOD); } } OOR_LOG(LDBG_3,"OUTPUT: Sending encapsulated packet: RLOC %s -> %s\n", lisp_addr_to_char(fe->srloc), lisp_addr_to_char(fe->drloc)); switch (fi->encap){ case ENCP_LISP: lisp_data_push_hdr(b, fe->iid); dst_port = LISP_DATA_PORT; break; case ENCP_VXLAN_GPE: vxlan_gpe_data_push_hdr(b, fe->iid, vxlan_gpe_get_next_prot(fe->srloc)); dst_port = VXLAN_GPE_DATA_PORT; break; } return(send_datagram_packet (*(fe->out_sock), lbuf_data(b), lbuf_size(b), fe->drloc, dst_port)); } int vpnapi_output(lbuf_t *b, packet_tuple_t *tpl) { OOR_LOG(LDBG_3,"OUTPUT: Received EID %s -> %s, Proto: %d, Port: %d -> %d ", lisp_addr_to_char(&tpl->src_addr), lisp_addr_to_char(&tpl->dst_addr), tpl->protocol, tpl->src_port, tpl->dst_port); /* If already LISP packet, do not encapsulate again */ if (pkt_tuple_is_lisp(tpl)) { OOR_LOG(LDBG_3,"OUTPUT: Is a lisp packet, do not encapsulate again"); return (vpnapi_forward_native(b, &tpl->dst_addr)); } vpnapi_output_unicast(b, tpl); return(GOOD); } int vpnapi_output_recv(struct sock *sl) { packet_tuple_t tpl; lbuf_use_stack(&pkt_buf, &pkt_recv_buf, VPNAPI_RECEIVE_SIZE); lbuf_reserve(&pkt_buf, LBUF_STACK_OFFSET); if (sock_recv(sl->fd, &pkt_buf) != GOOD) { OOR_LOG(LWRN, "OUTPUT: Error while reading from tun!"); return (BAD); } lbuf_reset_ip(&pkt_buf); if (pkt_parse_5_tuple(&pkt_buf, &tpl) != GOOD) { return (BAD); } /* XXX Since OOR doesn't support same local prefixes with different IIDs when * operating as a XTR or MN, we use IID = 0 to calculate the hash of the ttable. * The actual IID to be used on the encapsulation processed is already stored * in the forwarding entry, which is obtained on a ttable miss.*/ tpl.iid = 0; vpnapi_output(&pkt_buf, &tpl); return (GOOD); } int vpnapi_send_ctrl_msg(lbuf_t *buf, uconn_t *udp_conn) { /* With VPNAI packets are send using his own interface */ return (BAD); } void vpnapi_rm_dp_entry(packet_tuple_t *tuple) { vpnapi_data_t *data = vpnapi_get_datap_data(); ttable_remove(&(data->ttable), tuple); } oor-1.2.0/oor/data-plane/vpnapi/vpnapi_output.h000066400000000000000000000020311313612200500214660ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef VPNAPI_OUTPUT_H_ #define VPNAPI_OUTPUT_H_ #include "../../lib/sockets.h" #define VPNAPI_RECEIVE_SIZE 2048 // Should probably tune to match largest MTU int vpnapi_output(lbuf_t *b, packet_tuple_t *tpl); int vpnapi_output_recv(struct sock *sl); int vpnapi_send_ctrl_msg(lbuf_t *buf, uconn_t *udp_conn); #endif /* VPNAPI_OUTPUT_H_ */ oor-1.2.0/oor/data-plane/vpp/000077500000000000000000000000001313612200500157145ustar00rootroot00000000000000oor-1.2.0/oor/data-plane/vpp/vpp.c000066400000000000000000000430631313612200500166730ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "vpp.h" #include "../data-plane.h" #include "../../lib/interfaces_lib.h" #include "../../lib/oor_log.h" #include "../../lib/sockets.h" #include "../../net_mgr/net_mgr.h" #include "../../oor_external.h" #include "../../control/oor_control.h" #include "../../fwd_policies/fwd_policy.h" #include "../../fwd_policies/vpp_balancing/fwd_entry_vpp.h" #include #include "../../lib/vpp_api/vpp_api_requests.h" #define vl_typedefs #include #undef vl_typedefs /* declare message handlers for each api */ #define vl_endianfun /* define message structures */ #include #undef vl_endianfun #include #include static uint8_t pkt_recv_buf[TAP_VPP_BUFFER_SIZE]; static lbuf_t pkt_buf; int vpp_init_data_plane(oor_dev_type_e dev_type, oor_encap_t encap_type, ...); void vpp_uninit_data_plane (oor_ctrl_t *ctrl); int vpp_add_datap_iface_addr(iface_t *iface, int afi); int vpp_add_datap_iface_gw(iface_t *iface, int afi); int vpp_register_lcl_mapping(oor_dev_type_e dev_type, mapping_t *map); int vpp_deregister_lcl_mapping(oor_dev_type_e dev_type, mapping_t *map); int vpp_process_input_packet(sock_t *sl); int vpp_rtr_process_input_packet(sock_t *sl); int vpp_output_recv(sock_t *sl); void vpp_remove_native_route(fwd_info_t *fi); void vpp_remove_drop_route(fwd_info_t *fi); void vpp_fwd_info_del(fwd_info_t *fi); int vpp_updated_route(int command, iface_t *iface, lisp_addr_t *src_pref, lisp_addr_t *dst_pref, lisp_addr_t *gw); int vpp_updated_addr(iface_t *iface,lisp_addr_t *old_addr,lisp_addr_t *new_addr); int vpp_updated_link(iface_t *iface, int old_iface_index, int new_iface_index, int status); int vpp_rm_fwd_from_entry(lisp_addr_t *eid_prefix, uint8_t local); vpp_dplane_data_t * vpp_dplane_data_new(); int vpp_reset_all_fwd(); typedef void (*remove_fwd_entry_fn)(fwd_info_t *); data_plane_struct_t dplane_vpp = { .datap_init = vpp_init_data_plane, .datap_uninit = vpp_uninit_data_plane, .datap_add_iface_addr = vpp_add_datap_iface_addr, .datap_add_iface_gw = vpp_add_datap_iface_gw, .datap_register_lcl_mapping = vpp_register_lcl_mapping, .datap_deregister_lcl_mapping = vpp_deregister_lcl_mapping, .datap_input_packet = vpp_process_input_packet, .datap_rtr_input_packet = vpp_rtr_process_input_packet, .datap_output_packet = vpp_output_recv, .datap_updated_route = vpp_updated_route, .datap_updated_addr = vpp_updated_addr, .datap_update_link = vpp_updated_link, .datap_rm_fwd_from_entry = vpp_rm_fwd_from_entry, .datap_reset_all_fwd = vpp_reset_all_fwd, .datap_data = NULL }; int vpp_init_data_plane(oor_dev_type_e dev_type, oor_encap_t encap_type, ...) { int vpp_data_fd = -1; if (encap_type == ENCP_VXLAN_GPE){ OOR_LOG(LERR, "OOR with VPP data plane doesn't support VXLAN encapsulation yet"); } /* Configure data plane */ if ((vpp_data_fd = create_tun_tap(TAP,TAP_VPP_MISS_IFACE_NAME, TAP_MTU_VPP)) == BAD){ return (BAD); } /* Enable oor pkt miss node in VPP */ if (vpp_oor_pkt_miss_enable_disable(TAP_VPP_MISS_IFACE_NAME, TRUE)!=GOOD){ OOR_LOG(LERR,"VPP: Could not initiate oor packet miss plugin. Check /var/log/syslog for more details"); return (BAD); } OOR_LOG(LDBG_2,"VPP: Enabled oor packet miss plugin."); sockmstr_register_read_listener(smaster, vpp_output_recv, NULL,vpp_data_fd); dplane_vpp.datap_data = vpp_dplane_data_new(); return (GOOD); } void vpp_uninit_data_plane (oor_ctrl_t *ctrl) { vpp_dplane_data_t *data = (vpp_dplane_data_t *)dplane_vpp.datap_data; if (data){ shash_destroy(data->eid_to_dp_entries); shash_destroy(data->iid_lst); free(data); /* Enable oor pkt miss node in VPP */ vpp_oor_pkt_miss_enable_disable(TAP_VPP_MISS_IFACE_NAME, FALSE); } } int vpp_add_datap_iface_addr(iface_t *iface, int afi) { return (GOOD); } int vpp_add_datap_iface_gw(iface_t *iface, int afi) { return (GOOD); } int vpp_register_lcl_mapping(oor_dev_type_e dev_type, mapping_t *map) { lisp_addr_t *eid_addr = mapping_eid(map); lisp_addr_t *eid_pref; int table_id = 0,vni = 0; char vni_str[9]; vpp_dplane_data_t *data = (vpp_dplane_data_t *)dplane_vpp.datap_data; glist_t *iid_eids_lst; char * iface_name; int iface_index; /* XXX The user should add the EID interface to the vni table before * starting OOR (before assigning IPs to the interface): * # vppctl set interface ip table */ if (lisp_addr_is_iid(eid_addr)){ eid_pref = lisp_addr_get_ip_pref_addr(eid_addr); vni = lcaf_iid_get_iid(lisp_addr_get_lcaf(eid_addr)); /* Check if the interface is associated with the table of the VNI */ iface_name = net_mgr->netm_get_iface_associated_with_pref(eid_addr); if (!iface_name){ return (BAD); } iface_index = net_mgr->netm_get_iface_index(iface_name); table_id = vpp_interface_get_table(iface_index, lisp_addr_ip_afi(eid_pref) == AF_INET ? 0 : 1); if (table_id != vni){ OOR_LOG(LERR,"VPP: Interface should be associated to the table of VNI. " \ "This process should be done before configuring addresses of the interface"); return (BAD); } } sprintf(vni_str, "%d",vni); /* Check if we already have configured this iid */ iid_eids_lst = shash_lookup(data->iid_lst,vni_str); if (!iid_eids_lst){ iid_eids_lst = glist_new(); glist_add(eid_addr,iid_eids_lst); shash_insert(data->iid_lst,strdup(vni_str),iid_eids_lst); /* Configure IID in data plane */ vpp_lisp_gpe_add_del_iface(table_id, vni, ADD); if (vni != 0){ vpp_lisp_eid_table_add_del_map (table_id, vni, ADD); } }else{ glist_add(eid_addr,iid_eids_lst); return (GOOD); } return (GOOD); } int vpp_deregister_lcl_mapping(oor_dev_type_e dev_type, mapping_t *map) { lisp_addr_t *eid_addr = mapping_eid(map); int table_id = 0,vni = 0; char vni_str[9]; vpp_dplane_data_t *data = (vpp_dplane_data_t *)dplane_vpp.datap_data; glist_t *iid_eids_lst; if (!data){ return (GOOD); } vpp_reset_all_fwd(); if (lisp_addr_is_iid(eid_addr)){ vni = lcaf_iid_get_iid(lisp_addr_get_lcaf(eid_addr)); table_id = vni; } sprintf(vni_str, "%d",vni); /* Check if we have to unregistered this iid from the dataplane */ iid_eids_lst = shash_lookup(data->iid_lst,vni_str); if (!iid_eids_lst){ OOR_LOG(LDBG_1,"vpp_deregister_lcl_mapping: It should never happen"); return (BAD); } if(glist_size(iid_eids_lst) > 1){ /* We don't remove IID from data plane. There are other eids using it */ glist_remove_obj(eid_addr, iid_eids_lst); return(GOOD); } shash_remove(data->iid_lst, vni_str); if (vni != 0){ vpp_lisp_eid_table_add_del_map (table_id, vni, RM); } vpp_lisp_gpe_add_del_iface(table_id, vni, RM); return (GOOD); } int vpp_process_input_packet(sock_t *sl) { return (GOOD); } int vpp_rtr_process_input_packet(sock_t *sl) { return (GOOD); } int associate_fwd_info_with_eid(fwd_info_t *fi, vpp_dplane_data_t *dp_data, remove_fwd_entry_fn rm_fwd_entry_fn) { glist_t *fwd_info_list; fwd_info_list = (glist_t *)shash_lookup(dp_data->eid_to_dp_entries,lisp_addr_to_char(fi->associated_entry)); if (!fwd_info_list){ fwd_info_list = glist_new_managed((glist_del_fct)rm_fwd_entry_fn); shash_insert(dp_data->eid_to_dp_entries, strdup(lisp_addr_to_char(fi->associated_entry)), fwd_info_list); } glist_add(fi,fwd_info_list); return (GOOD); } int associate_fwd_info_with_petrs(fwd_info_t *fi, vpp_dplane_data_t *dp_data) { glist_t *pxtr_fwd_info_list; switch (lisp_addr_ip_afi(fi->associated_entry)){ case AF_INET: pxtr_fwd_info_list = (glist_t *)shash_lookup(dp_data->eid_to_dp_entries,FULL_IPv4_ADDRESS_SPACE); break; case AF_INET6: pxtr_fwd_info_list = (glist_t *)shash_lookup(dp_data->eid_to_dp_entries,FULL_IPv6_ADDRESS_SPACE); break; default: OOR_LOG(LDBG_3, "vpp_output_recv: Forwarding to PeTR is only for IP EIDs. It should never reach here"); return (BAD); } glist_add(fi,pxtr_fwd_info_list); return (GOOD); } int vpp_output_recv(sock_t *sl) { packet_tuple_t tpl; fwd_info_t *fi; fwd_entry_vpp_t *fe; vpp_dplane_data_t *dp_data = (vpp_dplane_data_t *)dplane_vpp.datap_data; lbuf_t buff; uint8_t mac[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; lbuf_use_stack(&pkt_buf, &pkt_recv_buf, TAP_VPP_BUFFER_SIZE); lbuf_reserve(&pkt_buf, LBUF_STACK_OFFSET); if (sock_recv(sl->fd, &pkt_buf) != GOOD) { OOR_LOG(LWRN, "OUTPUT: Error while reading from tun!"); return (BAD); } buff = pkt_buf; lbuf_reset_ip(&pkt_buf); if (pkt_parse_5_tuple(&pkt_buf, &tpl) != GOOD) { return (BAD); } /* XXX The correct IID is updated in ctrl_get_forwarding_info */ tpl.iid = 0; OOR_LOG(LDBG_3, "OUTPUT: Received packet miss from data plane for %s", pkt_tuple_to_char(&tpl)); fi = (fwd_info_t *)ctrl_get_forwarding_info(&tpl); if (!fi){ return (BAD); } if (!(fi->dp_conf_inf)){ if (fi->neg_map_reply_act == ACT_NATIVE_FWD){ /* Configure the native route through the gateway */ vpp_oor_pkt_miss_native_route(fi->associated_entry,ADD); /* Associate eid with fwd_info */ associate_fwd_info_with_eid(fi, dp_data, (remove_fwd_entry_fn) vpp_remove_native_route); goto resend; } return (BAD); } fe = (fwd_entry_vpp_t *)(fi->dp_conf_inf); /* Associate eid with fwd_info */ switch(fi->neg_map_reply_act){ case ACT_NATIVE_FWD: /* Associate eid with petrs */ associate_fwd_info_with_petrs(fi,dp_data); break; case ACT_NO_ACTION: if (glist_size(fe->loc_pair_lst) == 0){ /* Negative mappings with no PeTRs available */ /* Configure a route to drop the packets to this destination prefix */ vpp_oor_pkt_miss_drop_route(fi->associated_entry,ADD,tpl.iid); /* Associate eid with fwd_info and petrs */ associate_fwd_info_with_eid(fi, dp_data, (remove_fwd_entry_fn) vpp_remove_drop_route); associate_fwd_info_with_petrs(fi,dp_data); goto resend; } break; case ACT_DROP: /* Configure a route to drop the packets to this destination prefix */ vpp_oor_pkt_miss_drop_route(fi->associated_entry,ADD,tpl.iid); /* Associate eid with fwd_info */ associate_fwd_info_with_eid(fi, dp_data, (remove_fwd_entry_fn) vpp_remove_drop_route); goto resend; default: OOR_LOG(LDBG_1,"vpp_output_recv: Unknown action"); return (BAD); } associate_fwd_info_with_eid(fi, dp_data, (remove_fwd_entry_fn) vpp_fwd_info_del); /* Configure vpp data plane*/ vpp_lisp_gpe_add_del_fwd_entry(fe,fi->neg_map_reply_act,ADD); resend: /* Reinsert the packet to VPP in order to reduce the number of packets lost */ pkt_push_eth(&buff, mac, mac, ETH_P_IP); if (write(sl->fd, lbuf_data(&buff), lbuf_size(&buff)) < 0 ){ OOR_LOG(LDBG_2, "write error: %s\n ", strerror(errno)); return(BAD); } return (GOOD); } void vpp_remove_native_route(fwd_info_t *fi) { vpp_oor_pkt_miss_native_route(fi->associated_entry,RM); fwd_info_del(fi); } void vpp_remove_drop_route(fwd_info_t *fi) { uint32_t table_id = 0; if (lisp_addr_is_iid(fi->associated_entry)){ table_id = lcaf_iid_get_iid(lisp_addr_get_lcaf(fi->associated_entry)); } vpp_oor_pkt_miss_drop_route(fi->associated_entry,RM,table_id); fwd_info_del(fi); } void vpp_fwd_info_del(fwd_info_t *fi) { vpp_lisp_gpe_add_del_fwd_entry((fwd_entry_vpp_t *)(fi->dp_conf_inf),fi->neg_map_reply_act,RM); fwd_info_del(fi); } int vpp_updated_route(int command, iface_t *iface, lisp_addr_t *src_pref, lisp_addr_t *dst_pref, lisp_addr_t *gw) { return (GOOD); } int vpp_updated_addr(iface_t *iface,lisp_addr_t *old_addr,lisp_addr_t *new_addr) { return (GOOD); } int vpp_updated_link(iface_t *iface, int old_iface_index, int new_iface_index, int status) { return (GOOD); } int vpp_rm_fwd_from_entry(lisp_addr_t *eid_prefix, uint8_t local) { char * eid_prefix_char = lisp_addr_to_char(eid_prefix); glist_t *fwd_info_list, *pxtr_fwd_info_list; glist_entry_t *fi_it; fwd_entry_vpp_t *fe; fwd_info_t *fi; vpp_dplane_data_t *data = (vpp_dplane_data_t *)dplane_vpp.datap_data; if (local){ vpp_reset_all_fwd(); return (GOOD); } if (strcmp(eid_prefix_char,FULL_IPv4_ADDRESS_SPACE) == 0){ // Update of the PeTR list for IPv4 EIDs or RTR list pxtr_fwd_info_list = (glist_t *)shash_lookup(data->eid_to_dp_entries,FULL_IPv4_ADDRESS_SPACE); // Remove all the entries associated with the PxTR while (glist_size(pxtr_fwd_info_list) > 0){ fi = (fwd_info_t *)glist_first_data(pxtr_fwd_info_list); // When we recurively call this function using the associated_entry we will execute "else" statement where we also // update the list of entries associated with PxTR. vpp_rm_fwd_from_entry(fi->associated_entry,local); } }else if (strcmp(eid_prefix_char,FULL_IPv6_ADDRESS_SPACE) == 0){ // Update of the PeTR list for IPv6 EIDs or RTR list pxtr_fwd_info_list = (glist_t *)shash_lookup(data->eid_to_dp_entries,FULL_IPv6_ADDRESS_SPACE); // Remove all the entries associated with the PxTR while (glist_size(pxtr_fwd_info_list) > 0){ fi = (fwd_info_t *)glist_first_data(pxtr_fwd_info_list); // When we recursively call this function using the associated_entry we will execute "else" statement where we also // update the list of entries associated with PxTR. vpp_rm_fwd_from_entry(fi->associated_entry,local); } }else{ fwd_info_list = (glist_t *)shash_lookup(data->eid_to_dp_entries,eid_prefix_char); if (!fwd_info_list){ OOR_LOG(LDBG_1, "vpp_rm_fwd_from_entry: Entry %s not found in the shasht!",eid_prefix_char); return (BAD); } /* Check if it is a negative entry in order to remove also from PxTRs list */ fi = (fwd_info_t *)glist_first_data(fwd_info_list); fe = (fwd_entry_vpp_t *)(fi->dp_conf_inf); if (fi->dp_conf_inf && (fi->neg_map_reply_act == ACT_NATIVE_FWD || //Negative mapping with PeTRs (fi->neg_map_reply_act == ACT_NO_ACTION && glist_size(fe->loc_pair_lst) == 0))){ // negative mapping without PeTRs switch (lisp_addr_ip_afi(fi->associated_entry)){ case AF_INET: pxtr_fwd_info_list = (glist_t *)shash_lookup(data->eid_to_dp_entries,FULL_IPv4_ADDRESS_SPACE); break; case AF_INET6: pxtr_fwd_info_list = (glist_t *)shash_lookup(data->eid_to_dp_entries,FULL_IPv6_ADDRESS_SPACE); break; default: OOR_LOG(LDBG_1, "vpp_rm_fwd_from_entry: Associated entry is not IP"); return (BAD); } /* Remove each fwd_info associated to the eid_prefix from the PeTR list */ glist_for_each_entry(fi_it,fwd_info_list){ fi = (fwd_info_t *)glist_entry_data(fi_it); glist_remove_obj(fi,pxtr_fwd_info_list); } } /* Remove associated entry from eid_to_dp_entries -> This will remove the list of fwd_info_list * associated with the eid_prefix. The list is a managed list initialized with a remove function */ shash_remove(data->eid_to_dp_entries, eid_prefix_char); } return (GOOD); } /* Remove all the fwd programmed in the data plane * Used when a change is produced in the local mappings */ int vpp_reset_all_fwd() { vpp_dplane_data_t *data = (vpp_dplane_data_t *)dplane_vpp.datap_data; shash_destroy(data->eid_to_dp_entries); data->eid_to_dp_entries = shash_new_managed((free_value_fn_t)glist_destroy); /* Insert entry for PeTRs */ shash_insert(data->eid_to_dp_entries, strdup(FULL_IPv4_ADDRESS_SPACE), glist_new()); shash_insert(data->eid_to_dp_entries, strdup(FULL_IPv6_ADDRESS_SPACE), glist_new()); return (GOOD); } vpp_dplane_data_t * vpp_dplane_data_new() { vpp_dplane_data_t * data; data = xmalloc(sizeof(vpp_dplane_data_t)); data->eid_to_dp_entries = shash_new_managed((free_value_fn_t)glist_destroy); /* Insert entry for PeTRs */ shash_insert(data->eid_to_dp_entries, strdup(FULL_IPv4_ADDRESS_SPACE), glist_new()); shash_insert(data->eid_to_dp_entries, strdup(FULL_IPv6_ADDRESS_SPACE), glist_new()); data->iid_lst = shash_new_managed((free_value_fn_t)glist_destroy); return (data); } oor-1.2.0/oor/data-plane/vpp/vpp.h000066400000000000000000000023421313612200500166730ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef VPP_H_ #define VPP_H_ #include "../../lib/shash.h" #define TAP_VPP_MISS_IFACE_NAME "oorDtap0" #define TAP_MTU_VPP 1440 #define TAP_VPP_BUFFER_SIZE 2048 typedef struct vpp_dplane_data_{ /* < char *eid -> glist_t > Used to find the fwd entries to be removed * of the data plane when there is a change with the mapping of the eid */ shash_t *eid_to_dp_entries; //< char *eid -> glist_t > shash_t *iid_lst; //< char *iid , glist of eids> }vpp_dplane_data_t; #endif /* VPP_H_ */ oor-1.2.0/oor/defs.h000066400000000000000000000120461313612200500141760ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef DEFS_H_ #define DEFS_H_ #include typedef enum { ENCP_LISP, ENCP_VXLAN_GPE }oor_encap_t; typedef enum { xTR_MODE , MS_MODE, RTR_MODE, MN_MODE } oor_dev_type_e; #ifdef __GNUC__ #define likely(x) __builtin_expect(!!(x), 1) #define unlikely(x) __builtin_expect(!!(x), 0) #else #define likely(x) (x) #define unlikely(x) (x) #endif typedef struct oor_ctrl_dev oor_ctrl_dev_t; typedef struct oor_ctrl oor_ctrl_t; typedef struct shash shash_t; typedef struct fwd_info_ fwd_info_t; typedef struct sockmstr sockmstr_t; typedef struct htable_ptrs htable_ptrs_t; typedef struct data_plane_struct data_plane_struct_t; typedef struct net_mgr_class net_mgr_class_t; typedef struct htable_nonces_ htable_nonces_t; /* Protocols constants related with timeouts */ #define OOR_INITIAL_MRQ_TIMEOUT 2 // Initial expiration timer for the first MRq #define OOR_INITIAL_SMR_TIMEOUT 3 // Initial expiration timer for the first MRq SMR #define OOR_INITIAL_MREG_TIMEOUT 3 // Initial expiration timer for the first Encapsulated Map Register #define OOR_INITIAL_INF_REQ_TIMEOUT 3 // Initial expiration timer for the first info request #define OOR_INF_REQ_HANDOVER_TIMEOUT 2 // Time before sending an info request after a handover #define OOR_SLEEP_INF_REQ_TIMEOUT 60 // When no info reply received after x retries. Sleep for x seconds #define OOR_SMR_TIMEOUT 4 // Time since interface status change until balancing arrays and SMR is done #define OOR_MAX_MRQ_TIMEOUT 32 // Max expiration timer for the subsequent MRq #define OOR_EXPIRE_TIMEOUT 1 // Time interval in which events are expired #define OOR_MAX_MR_RETRANSMIT 2 // Maximum amount of Map Request retransmissions #define OOR_MAX_SMR_RETRANSMIT 2 // Maximum amount of SMR MRq retransmissions #define OOR_MAX_PROBE_RETRANSMIT 1 // Maximum amount of RLOC probe MRq retransmissions #define OOR_MAX_RETRANSMITS 5 // Maximum amount of retransmits of a message #define OOR_MIN_RETRANSMIT_INTERVAL 1 // Minimum time between retransmits of control messages #define DEFAULT_MAP_REQUEST_RETRIES 3 #define MAP_REGISTER_INTERVAL 60 #define MS_SITE_EXPIRATION 180 #define RLOC_PROBING_INTERVAL 30 #define DEFAULT_RLOC_PROBING_RETRIES 2 #define DEFAULT_RLOC_PROBING_RETRIES_INTERVAL 5 /* Interval in seconds between RLOC probing retries */ #define DEFAULT_DATA_CACHE_TTL 10 #define DEFAULT_SELECT_TIMEOUT 1000/* ms */ #define FIELD_AFI_LEN 2 #define FIELD_PORT_LEN 2 /* * oor constants */ #define EVER ;; #define OOR_VERSION "v1.2.0" #define OOR "oor" #define PID_FILE "/var/run/oor.pid" #define DEVICE_ID_FILE "oor-id" /* * misc parameters */ #define IP6VERSION 6 /* what's the symbol? */ #define PACKED __attribute__ ((__packed__)) #define uchar u_char #define GOOD 1 #define BAD 0 #define ERR_SRC_ADDR -1 #define ERR_AFI -2 #define ERR_DB -3 #define ERR_MALLOC -4 #define ERR_EXIST -5 #define ERR_NO_EXIST -6 #define ERR_CTR_IFACE -7 #define ERR_NOT_ENCAP -8 #define ERR_SOCKET -9 #define ERR_NO_ROUTE -10 #define ERR_NO_REPLY -99 #define TRUE 1 #define FALSE 0 #define UP 1 #define DOWN 0 #define UNKNOWN -1 #define ADD 1 #define RM 0 #define NO_AFI_SUPPOT 0 #define IPv4_SUPPORT 1 #define IPv6_SUPPORT 2 #define FULL_IPv4_ADDRESS_SPACE "0.0.0.0/0" #define FULL_IPv6_ADDRESS_SPACE "::/0" /***** NAT status *******/ //#define UNKNOWN -1 #define NO_NAT 0 #define PARTIAL_NAT 1 #define FULL_NAT 2 /* * Structure to simplify netlink processing */ typedef struct nlsock_handle { int fd; // netlink socket fd uint32_t seq; // netlink message seq number } nlsock_handle; /* Use the nonce to calculate the source port for a map request * message. */ #define LISP_PKT_MAP_REQUEST_UDP_SPORT(Nonce) (0xf000 | (Nonce & 0xfff)) #define LISP_PKT_MAP_REQUEST_TTL 32 #define LISP_PKT_MAP_REQUEST_MAX_ITR_RLOCS 31 #endif /* DEFS_H_ */ oor-1.2.0/oor/elibs/000077500000000000000000000000001313612200500141775ustar00rootroot00000000000000oor-1.2.0/oor/elibs/bob/000077500000000000000000000000001313612200500147415ustar00rootroot00000000000000oor-1.2.0/oor/elibs/bob/lookup3.c000066400000000000000000000176201313612200500165070ustar00rootroot00000000000000/* ------------------------------------------------------------------------------- lookup3.c, by Bob Jenkins, May 2006, Public Domain. These are functions for producing 32-bit hashes for hash table lookup. hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final() are externally useful functions. Routines to test the hash are included if SELF_TEST is defined. You can use this free for any purpose. It's in the public domain. It has no warranty. You probably want to use hashlittle(). hashlittle() and hashbig() hash byte arrays. hashlittle() is is faster than hashbig() on little-endian machines. Intel and AMD are little-endian machines. On second thought, you probably want hashlittle2(), which is identical to hashlittle() except it returns two 32-bit hashes for the price of one. You could implement hashbig2() if you wanted but I haven't bothered here. If you want to find a hash of, say, exactly 7 integers, do a = i1; b = i2; c = i3; mix(a,b,c); a += i4; b += i5; c += i6; mix(a,b,c); a += i7; final(a,b,c); then use c as the hash value. If you have a variable length array of 4-byte integers to hash, use hashword(). If you have a byte array (like a character string), use hashlittle(). If you have several byte arrays, or a mix of things, see the comments above hashlittle(). Why is this so big? I read 12 bytes at a time into 3 4-byte integers, then mix those integers. This is fast (you can do a lot more thorough mixing with 12*3 instructions on 3 integers than you can with 3 instructions on 1 byte), but shoehorning those bytes into integers efficiently is messy. ------------------------------------------------------------------------------- Original code by Bob Jenkins. Modified by the LISPmob project. */ #define SELF_TEST 1 #include /* defines printf for tests */ #include /* defines time_t for timings in the test */ #include /* defines uint32_t etc */ #include /* attempt to define endianness */ #ifdef linux # include /* attempt to define endianness */ #endif /* * My best guess at if you are big-endian or little-endian. This may * need adjustment. */ #if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \ __BYTE_ORDER == __LITTLE_ENDIAN) || \ (defined(i386) || defined(__i386__) || defined(__i486__) || \ defined(__i586__) || defined(__i686__) || defined(vax) || defined(MIPSEL)) # define HASH_LITTLE_ENDIAN 1 # define HASH_BIG_ENDIAN 0 #elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \ __BYTE_ORDER == __BIG_ENDIAN) || \ (defined(sparc) || defined(POWERPC) || defined(mc68000) || defined(sel)) # define HASH_LITTLE_ENDIAN 0 # define HASH_BIG_ENDIAN 1 #else # define HASH_LITTLE_ENDIAN 0 # define HASH_BIG_ENDIAN 0 #endif #define hashsize(n) ((uint32_t)1<<(n)) #define hashmask(n) (hashsize(n)-1) #define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k)))) /* ------------------------------------------------------------------------------- mix -- mix 3 32-bit values reversibly. This is reversible, so any information in (a,b,c) before mix() is still in (a,b,c) after mix(). If four pairs of (a,b,c) inputs are run through mix(), or through mix() in reverse, there are at least 32 bits of the output that are sometimes the same for one pair and different for another pair. This was tested for: * pairs that differed by one bit, by two bits, in any combination of top bits of (a,b,c), or in any combination of bottom bits of (a,b,c). * "differ" is defined as +, -, ^, or ~^. For + and -, I transformed the output delta to a Gray code (a^(a>>1)) so a string of 1's (as is commonly produced by subtraction) look like a single 1-bit difference. * the base values were pseudorandom, all zero but one bit set, or all zero plus a counter that starts at zero. Some k values for my "a-=c; a^=rot(c,k); c+=b;" arrangement that satisfy this are 4 6 8 16 19 4 9 15 3 18 27 15 14 9 3 7 17 3 Well, "9 15 3 18 27 15" didn't quite get 32 bits diffing for "differ" defined as + with a one-bit base and a two-bit delta. I used http://burtleburtle.net/bob/hash/avalanche.html to choose the operations, constants, and arrangements of the variables. This does not achieve avalanche. There are input bits of (a,b,c) that fail to affect some output bits of (a,b,c), especially of a. The most thoroughly mixed value is c, but it doesn't really even achieve avalanche in c. This allows some parallelism. Read-after-writes are good at doubling the number of bits affected, so the goal of mixing pulls in the opposite direction as the goal of parallelism. I did what I could. Rotates seem to cost as much as shifts on every machine I could lay my hands on, and rotates are much kinder to the top and bottom bits, so I used rotates. ------------------------------------------------------------------------------- */ #define mix(a,b,c) \ { \ a -= c; a ^= rot(c, 4); c += b; \ b -= a; b ^= rot(a, 6); a += c; \ c -= b; c ^= rot(b, 8); b += a; \ a -= c; a ^= rot(c,16); c += b; \ b -= a; b ^= rot(a,19); a += c; \ c -= b; c ^= rot(b, 4); b += a; \ } /* ------------------------------------------------------------------------------- final -- final mixing of 3 32-bit values (a,b,c) into c Pairs of (a,b,c) values differing in only a few bits will usually produce values of c that look totally different. This was tested for * pairs that differed by one bit, by two bits, in any combination of top bits of (a,b,c), or in any combination of bottom bits of (a,b,c). * "differ" is defined as +, -, ^, or ~^. For + and -, I transformed the output delta to a Gray code (a^(a>>1)) so a string of 1's (as is commonly produced by subtraction) look like a single 1-bit difference. * the base values were pseudorandom, all zero but one bit set, or all zero plus a counter that starts at zero. These constants passed: 14 11 25 16 4 14 24 12 14 25 16 4 14 24 and these came close: 4 8 15 26 3 22 24 10 8 15 26 3 22 24 11 8 15 26 3 22 24 ------------------------------------------------------------------------------- */ #define final(a,b,c) \ { \ c ^= b; c -= rot(b,14); \ a ^= c; a -= rot(c,11); \ b ^= a; b -= rot(a,25); \ c ^= b; c -= rot(b,16); \ a ^= c; a -= rot(c,4); \ b ^= a; b -= rot(a,14); \ c ^= b; c -= rot(b,24); \ } /* -------------------------------------------------------------------- This works on all machines. To be useful, it requires -- that the key be an array of uint32_t's, and -- that the length be the number of uint32_t's in the key The function hashword() is identical to hashlittle() on little-endian machines, and identical to hashbig() on big-endian machines, except that the length has to be measured in uint32_ts rather than in bytes. hashlittle() is more complicated than hashword() only because hashlittle() has to dance around fitting the key bytes into registers. -------------------------------------------------------------------- */ uint32_t hashword( const uint32_t *k, /* the key, an array of uint32_t values */ size_t length, /* the length of the key, in uint32_ts */ uint32_t initval) /* the previous hash, or an arbitrary value */ { uint32_t a, b, c; /* Set up the internal state */ a = b = c = 0xdeadbeef + (((uint32_t) length) << 2) + initval; /*------------------------------------------------- handle most of the key */ while (length > 3) { a += k[0]; b += k[1]; c += k[2]; mix(a, b, c); length -= 3; k += 3; } /*------------------------------------------- handle the last 3 uint32_t's */ switch (length) { /* all the case statements fall through */ case 3: c += k[2]; case 2: b += k[1]; case 1: a += k[0]; final(a, b, c); case 0: /* case 0: nothing left to add */ break; } /*------------------------------------------------------ report the result */ return c; } oor-1.2.0/oor/elibs/khash/000077500000000000000000000000001313612200500152755ustar00rootroot00000000000000oor-1.2.0/oor/elibs/khash/khash.h000066400000000000000000000454341313612200500165560ustar00rootroot00000000000000/* The MIT License Copyright (c) 2008, 2009, 2011 by Attractive Chaos Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------- Original code by Attractive Chaos. Modified by the LISPmob project. */ /* An example: #include "khash.h" KHASH_MAP_INIT_INT(32, char) int main() { int ret, is_missing; khiter_t k; khash_t(32) *h = kh_init(32); k = kh_put(32, h, 5, &ret); if (!ret) kh_del(32, h, k); kh_value(h, k) = 10; k = kh_get(32, h, 10); is_missing = (k == kh_end(h)); k = kh_get(32, h, 5); kh_del(32, h, k); for (k = kh_begin(h); k != kh_end(h); ++k) if (kh_exist(h, k)) kh_value(h, k) = 1; kh_destroy(32, h); return 0; } */ /* 2011-09-16 (0.2.6): * The capacity is a power of 2. This seems to dramatically improve the speed for simple keys. Thank Zilong Tan for the suggestion. Reference: - http://code.google.com/p/ulib/ - http://nothings.org/computer/judy/ * Allow to optionally use linear probing which usually has better performance for random input. Double hashing is still the default as it is more robust to certain non-random input. * Added Wang's integer hash function (not used by default). This hash function is more robust to certain non-random input. 2011-02-14 (0.2.5): * Allow to declare global functions. 2009-09-26 (0.2.4): * Improve portability 2008-09-19 (0.2.3): * Corrected the example * Improved interfaces 2008-09-11 (0.2.2): * Improved speed a little in kh_put() 2008-09-10 (0.2.1): * Added kh_clear() * Fixed a compiling error 2008-09-02 (0.2.0): * Changed to token concatenation which increases flexibility. 2008-08-31 (0.1.2): * Fixed a bug in kh_get(), which has not been tested previously. 2008-08-31 (0.1.1): * Added destructor */ #ifndef __AC_KHASH_H #define __AC_KHASH_H /*! @header Generic hash table library. */ #define AC_VERSION_KHASH_H "0.2.6" #include #include #include /* compipler specific configuration */ #if UINT_MAX == 0xffffffffu typedef unsigned int khint32_t; #elif ULONG_MAX == 0xffffffffu typedef unsigned long khint32_t; #endif #if ULONG_MAX == ULLONG_MAX typedef unsigned long khint64_t; #else typedef unsigned long long khint64_t; #endif #ifdef _MSC_VER #define inline __inline #endif typedef khint32_t khint_t; typedef khint_t khiter_t; #define __ac_isempty(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&2) #define __ac_isdel(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&1) #define __ac_iseither(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&3) #define __ac_set_isdel_false(flag, i) (flag[i>>4]&=~(1ul<<((i&0xfU)<<1))) #define __ac_set_isempty_false(flag, i) (flag[i>>4]&=~(2ul<<((i&0xfU)<<1))) #define __ac_set_isboth_false(flag, i) (flag[i>>4]&=~(3ul<<((i&0xfU)<<1))) #define __ac_set_isdel_true(flag, i) (flag[i>>4]|=1ul<<((i&0xfU)<<1)) #ifdef KHASH_LINEAR #define __ac_inc(k, m) 1 #else #define __ac_inc(k, m) (((k)>>3 ^ (k)<<3) | 1) & (m) #endif #define __ac_fsize(m) ((m) < 16? 1 : (m)>>4) #ifndef kroundup32 #define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x)) #endif static const double __ac_HASH_UPPER = 0.77; #define KHASH_DECLARE(name, khkey_t, khval_t) \ typedef struct{ \ khint_t n_buckets, size, n_occupied, upper_bound; \ khint32_t *flags; \ khkey_t *keys; \ khval_t *vals; \ } kh_##name##_t; \ extern kh_##name##_t *kh_init_##name(); \ extern void kh_destroy_##name(kh_##name##_t *h); \ extern void kh_clear_##name(kh_##name##_t *h); \ extern khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key); \ extern void kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets); \ extern khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret); \ extern void kh_del_##name(kh_##name##_t *h, khint_t x); #define KHASH_INIT2(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \ typedef struct { \ khint_t n_buckets, size, n_occupied, upper_bound; \ khint32_t *flags; \ khkey_t *keys; \ khval_t *vals; \ } kh_##name##_t; \ SCOPE kh_##name##_t *kh_init_##name() { \ return (kh_##name##_t*)calloc(1, sizeof(kh_##name##_t)); \ } \ SCOPE void kh_destroy_##name(kh_##name##_t *h) \ { \ if (h) { \ free(h->keys); free(h->flags); \ free(h->vals); \ free(h); \ } \ } \ SCOPE void kh_clear_##name(kh_##name##_t *h) \ { \ if (h && h->flags) { \ memset(h->flags, 0xaa, __ac_fsize(h->n_buckets) * sizeof(khint32_t)); \ h->size = h->n_occupied = 0; \ } \ } \ SCOPE khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key) \ { \ if (h->n_buckets) { \ khint_t inc, k, i, last, mask; \ mask = h->n_buckets - 1; \ k = __hash_func(key); i = k & mask; \ inc = __ac_inc(k, mask); last = i; /* inc==1 for linear probing */ \ while (!__ac_isempty(h->flags, i) && (__ac_isdel(h->flags, i) || !__hash_equal(h->keys[i], key))) { \ i = (i + inc) & mask; \ if (i == last) return h->n_buckets; \ } \ return __ac_iseither(h->flags, i)? h->n_buckets : i; \ } else return 0; \ } \ SCOPE void kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets) \ { /* This function uses 0.25*n_bucktes bytes of working space instead of [sizeof(key_t+val_t)+.25]*n_buckets. */ \ khint32_t *new_flags = 0; \ khint_t j = 1; \ { \ kroundup32(new_n_buckets); \ if (new_n_buckets < 4) new_n_buckets = 4; \ if (h->size >= (khint_t)(new_n_buckets * __ac_HASH_UPPER + 0.5)) j = 0; /* requested size is too small */ \ else { /* hash table size to be changed (shrink or expand); rehash */ \ new_flags = (khint32_t*)malloc(__ac_fsize(new_n_buckets) * sizeof(khint32_t)); \ memset(new_flags, 0xaa, __ac_fsize(new_n_buckets) * sizeof(khint32_t)); \ if (h->n_buckets < new_n_buckets) { /* expand */ \ h->keys = (khkey_t*)realloc(h->keys, new_n_buckets * sizeof(khkey_t)); \ if (kh_is_map) h->vals = (khval_t*)realloc(h->vals, new_n_buckets * sizeof(khval_t)); \ } /* otherwise shrink */ \ } \ } \ if (j) { /* rehashing is needed */ \ for (j = 0; j != h->n_buckets; ++j) { \ if (__ac_iseither(h->flags, j) == 0) { \ khkey_t key = h->keys[j]; \ khval_t val; \ khint_t new_mask; \ new_mask = new_n_buckets - 1; \ if (kh_is_map) val = h->vals[j]; \ __ac_set_isdel_true(h->flags, j); \ while (1) { /* kick-out process; sort of like in Cuckoo hashing */ \ khint_t inc, k, i; \ k = __hash_func(key); \ i = k & new_mask; \ inc = __ac_inc(k, new_mask); \ while (!__ac_isempty(new_flags, i)) i = (i + inc) & new_mask; \ __ac_set_isempty_false(new_flags, i); \ if (i < h->n_buckets && __ac_iseither(h->flags, i) == 0) { /* kick out the existing element */ \ { khkey_t tmp = h->keys[i]; h->keys[i] = key; key = tmp; } \ if (kh_is_map) { khval_t tmp = h->vals[i]; h->vals[i] = val; val = tmp; } \ __ac_set_isdel_true(h->flags, i); /* mark it as deleted in the old hash table */ \ } else { /* write the element and jump out of the loop */ \ h->keys[i] = key; \ if (kh_is_map) h->vals[i] = val; \ break; \ } \ } \ } \ } \ if (h->n_buckets > new_n_buckets) { /* shrink the hash table */ \ h->keys = (khkey_t*)realloc(h->keys, new_n_buckets * sizeof(khkey_t)); \ if (kh_is_map) h->vals = (khval_t*)realloc(h->vals, new_n_buckets * sizeof(khval_t)); \ } \ free(h->flags); /* free the working space */ \ h->flags = new_flags; \ h->n_buckets = new_n_buckets; \ h->n_occupied = h->size; \ h->upper_bound = (khint_t)(h->n_buckets * __ac_HASH_UPPER + 0.5); \ } \ } \ SCOPE khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret) \ { \ khint_t x; \ if (h->n_occupied >= h->upper_bound) { /* update the hash table */ \ if (h->n_buckets > (h->size<<1)) kh_resize_##name(h, h->n_buckets - 1); /* clear "deleted" elements */ \ else kh_resize_##name(h, h->n_buckets + 1); /* expand the hash table */ \ } /* TODO: to implement automatically shrinking; resize() already support shrinking */ \ { \ khint_t inc, k, i, site, last, mask = h->n_buckets - 1; \ x = site = h->n_buckets; k = __hash_func(key); i = k & mask; \ if (__ac_isempty(h->flags, i)) x = i; /* for speed up */ \ else { \ inc = __ac_inc(k, mask); last = i; \ while (!__ac_isempty(h->flags, i) && (__ac_isdel(h->flags, i) || !__hash_equal(h->keys[i], key))) { \ if (__ac_isdel(h->flags, i)) site = i; \ i = (i + inc) & mask; \ if (i == last) { x = site; break; } \ } \ if (x == h->n_buckets) { \ if (__ac_isempty(h->flags, i) && site != h->n_buckets) x = site; \ else x = i; \ } \ } \ } \ if (__ac_isempty(h->flags, x)) { /* not present at all */ \ h->keys[x] = key; \ __ac_set_isboth_false(h->flags, x); \ ++h->size; ++h->n_occupied; \ *ret = 1; \ } else if (__ac_isdel(h->flags, x)) { /* deleted */ \ h->keys[x] = key; \ __ac_set_isboth_false(h->flags, x); \ ++h->size; \ *ret = 2; \ } else *ret = 0; /* Don't touch h->keys[x] if present and not deleted */ \ return x; \ } \ SCOPE void kh_del_##name(kh_##name##_t *h, khint_t x) \ { \ if (x != h->n_buckets && !__ac_iseither(h->flags, x)) { \ __ac_set_isdel_true(h->flags, x); \ --h->size; \ } \ } #define KHASH_INIT(name, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \ KHASH_INIT2(name, static inline, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) /* --- BEGIN OF HASH FUNCTIONS --- */ /*! @function @abstract Integer hash function @param key The integer [khint32_t] @return The hash value [khint_t] */ #define kh_int_hash_func(key) (khint32_t)(key) /*! @function @abstract Integer comparison function */ #define kh_int_hash_equal(a, b) ((a) == (b)) /*! @function @abstract 64-bit integer hash function @param key The integer [khint64_t] @return The hash value [khint_t] */ //#define kh_int64_hash_func(key) (khint32_t)((key)>>33^(key)^(key)<<11) //#define kh_int64_hash_func(key) (khint32_t)(((size_t)key)>>33^((size_t)key)^((size_t)key)<<11) #define kh_int64_hash_func(key) (khint32_t)(((uint64_t)key)>>33^((uint64_t)key)^((uint64_t)key)<<11) /*! @function @abstract 64-bit integer comparison function */ #define kh_int64_hash_equal(a, b) ((a) == (b)) /*! @function @abstract const char* hash function @param s Pointer to a null terminated string @return The hash value */ static inline khint_t __ac_X31_hash_string(const char *s) { khint_t h = *s; if (h) for (++s ; *s; ++s) h = (h << 5) - h + *s; return h; } /*! @function @abstract Another interface to const char* hash function @param key Pointer to a null terminated string [const char*] @return The hash value [khint_t] */ #define kh_str_hash_func(key) __ac_X31_hash_string(key) /*! @function @abstract Const char* comparison function */ #define kh_str_hash_equal(a, b) (strcmp(a, b) == 0) static inline khint_t __ac_Wang_hash(khint_t key) { key += ~(key << 15); key ^= (key >> 10); key += (key << 3); key ^= (key >> 6); key += ~(key << 11); key ^= (key >> 16); return key; } #define kh_int_hash_func2(k) __ac_Wang_hash((khint_t)key) /* --- END OF HASH FUNCTIONS --- */ /* Other convenient macros... */ /*! @abstract Type of the hash table. @param name Name of the hash table [symbol] */ #define khash_t(name) kh_##name##_t /*! @function @abstract Initiate a hash table. @param name Name of the hash table [symbol] @return Pointer to the hash table [khash_t(name)*] */ #define kh_init(name) kh_init_##name() /*! @function @abstract Destroy a hash table. @param name Name of the hash table [symbol] @param h Pointer to the hash table [khash_t(name)*] */ #define kh_destroy(name, h) kh_destroy_##name(h) /*! @function @abstract Reset a hash table without deallocating memory. @param name Name of the hash table [symbol] @param h Pointer to the hash table [khash_t(name)*] */ #define kh_clear(name, h) kh_clear_##name(h) /*! @function @abstract Resize a hash table. @param name Name of the hash table [symbol] @param h Pointer to the hash table [khash_t(name)*] @param s New size [khint_t] */ #define kh_resize(name, h, s) kh_resize_##name(h, s) /*! @function @abstract Insert a key to the hash table. @param name Name of the hash table [symbol] @param h Pointer to the hash table [khash_t(name)*] @param k Key [type of keys] @param r Extra return code: 0 if the key is present in the hash table; 1 if the bucket is empty (never used); 2 if the element in the bucket has been deleted [int*] @return Iterator to the inserted element [khint_t] */ #define kh_put(name, h, k, r) kh_put_##name(h, k, r) /*! @function @abstract Retrieve a key from the hash table. @param name Name of the hash table [symbol] @param h Pointer to the hash table [khash_t(name)*] @param k Key [type of keys] @return Iterator to the found element, or kh_end(h) is the element is absent [khint_t] */ #define kh_get(name, h, k) kh_get_##name(h, k) /*! @function @abstract Remove a key from the hash table. @param name Name of the hash table [symbol] @param h Pointer to the hash table [khash_t(name)*] @param k Iterator to the element to be deleted [khint_t] */ #define kh_del(name, h, k) kh_del_##name(h, k) /*! @function @abstract Test whether a bucket contains data. @param h Pointer to the hash table [khash_t(name)*] @param x Iterator to the bucket [khint_t] @return 1 if containing data; 0 otherwise [int] */ #define kh_exist(h, x) (!__ac_iseither((h)->flags, (x))) /*! @function @abstract Get key given an iterator @param h Pointer to the hash table [khash_t(name)*] @param x Iterator to the bucket [khint_t] @return Key [type of keys] */ #define kh_key(h, x) ((h)->keys[x]) /*! @function @abstract Get value given an iterator @param h Pointer to the hash table [khash_t(name)*] @param x Iterator to the bucket [khint_t] @return Value [type of values] @discussion For hash sets, calling this results in segfault. */ #define kh_val(h, x) ((h)->vals[x]) /*! @function @abstract Alias of kh_val() */ #define kh_value(h, x) ((h)->vals[x]) /*! @function @abstract Get the start iterator @param h Pointer to the hash table [khash_t(name)*] @return The start iterator [khint_t] */ #define kh_begin(h) (khint_t)(0) /*! @function @abstract Get the end iterator @param h Pointer to the hash table [khash_t(name)*] @return The end iterator [khint_t] */ #define kh_end(h) ((h)->n_buckets) /*! @function @abstract Get the number of elements in the hash table @param h Pointer to the hash table [khash_t(name)*] @return Number of elements in the hash table [khint_t] */ #define kh_size(h) ((h)->size) /*! @function @abstract Get the number of buckets in the hash table @param h Pointer to the hash table [khash_t(name)*] @return Number of buckets in the hash table [khint_t] */ #define kh_n_buckets(h) ((h)->n_buckets) /* More conenient interfaces */ /*! @function @abstract Instantiate a hash set containing integer keys @param name Name of the hash table [symbol] */ #define KHASH_SET_INIT_INT(name) \ KHASH_INIT(name, khint32_t, char, 0, kh_int_hash_func, kh_int_hash_equal) /*! @function @abstract Instantiate a hash map containing integer keys @param name Name of the hash table [symbol] @param khval_t Type of values [type] */ #define KHASH_MAP_INIT_INT(name, khval_t) \ KHASH_INIT(name, khint32_t, khval_t, 1, kh_int_hash_func, kh_int_hash_equal) /*! @function @abstract Instantiate a hash map containing 64-bit integer keys @param name Name of the hash table [symbol] */ #define KHASH_SET_INIT_INT64(name) \ KHASH_INIT(name, khint64_t, char, 0, kh_int64_hash_func, kh_int64_hash_equal) /*! @function @abstract Instantiate a hash map containing 64-bit integer keys @param name Name of the hash table [symbol] @param khval_t Type of values [type] */ #define KHASH_MAP_INIT_INT64(name, khval_t) \ KHASH_INIT(name, khint64_t, khval_t, 1, kh_int64_hash_func, kh_int64_hash_equal) typedef const char *kh_cstr_t; /*! @function @abstract Instantiate a hash map containing const char* keys @param name Name of the hash table [symbol] */ #define KHASH_SET_INIT_STR(name) \ KHASH_INIT(name, kh_cstr_t, char, 0, kh_str_hash_func, kh_str_hash_equal) /*! @function @abstract Instantiate a hash map containing const char* keys @param name Name of the hash table [symbol] @param khval_t Type of values [type] */ #define KHASH_MAP_INIT_STR(name, khval_t) \ KHASH_INIT(name, kh_cstr_t, khval_t, 1, kh_str_hash_func, kh_str_hash_equal) #endif /* __AC_KHASH_H */ oor-1.2.0/oor/elibs/mbedtls/000077500000000000000000000000001313612200500156315ustar00rootroot00000000000000oor-1.2.0/oor/elibs/mbedtls/md.c000066400000000000000000000276541313612200500164130ustar00rootroot00000000000000/** * \file mbedtls_md.c * * \brief Generic message digest wrapper for mbed TLS * * \author Adriaan de Jong * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * Copyright (C) 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is part of mbed TLS (https://tls.mbed.org) * * Original code by mbed TLS project. Modified by the LISPmob project. */ #include "md.h" #include "md_internal.h" #if defined(MBEDTLS_PLATFORM_C) #include "mbedtls/platform.h" #else #include #define mbedtls_calloc calloc #define mbedtls_free free #endif #include #if defined(MBEDTLS_FS_IO) #include #endif /* Implementation that should never be optimized out by the compiler */ static void mbedtls_zeroize( void *v, size_t n ) { volatile unsigned char *p = v; while( n-- ) *p++ = 0; } /* * Reminder: update profiles in x509_crt.c when adding a new hash! */ static const int supported_digests[] = { #if defined(MBEDTLS_SHA512_C) MBEDTLS_MD_SHA512, MBEDTLS_MD_SHA384, #endif #if defined(MBEDTLS_SHA256_C) MBEDTLS_MD_SHA256, MBEDTLS_MD_SHA224, #endif #if defined(MBEDTLS_SHA1_C) MBEDTLS_MD_SHA1, #endif #if defined(MBEDTLS_RIPEMD160_C) MBEDTLS_MD_RIPEMD160, #endif #if defined(MBEDTLS_MD5_C) MBEDTLS_MD_MD5, #endif #if defined(MBEDTLS_MD4_C) MBEDTLS_MD_MD4, #endif #if defined(MBEDTLS_MD2_C) MBEDTLS_MD_MD2, #endif MBEDTLS_MD_NONE }; const int *mbedtls_md_list( void ) { return( supported_digests ); } const mbedtls_md_info_t *mbedtls_md_info_from_string( const char *md_name ) { if( NULL == md_name ) return( NULL ); /* Get the appropriate digest information */ #if defined(MBEDTLS_MD2_C) if( !strcmp( "MD2", md_name ) ) return mbedtls_md_info_from_type( MBEDTLS_MD_MD2 ); #endif #if defined(MBEDTLS_MD4_C) if( !strcmp( "MD4", md_name ) ) return mbedtls_md_info_from_type( MBEDTLS_MD_MD4 ); #endif #if defined(MBEDTLS_MD5_C) if( !strcmp( "MD5", md_name ) ) return mbedtls_md_info_from_type( MBEDTLS_MD_MD5 ); #endif #if defined(MBEDTLS_RIPEMD160_C) if( !strcmp( "RIPEMD160", md_name ) ) return mbedtls_md_info_from_type( MBEDTLS_MD_RIPEMD160 ); #endif #if defined(MBEDTLS_SHA1_C) if( !strcmp( "SHA1", md_name ) || !strcmp( "SHA", md_name ) ) return mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ); #endif #if defined(MBEDTLS_SHA256_C) if( !strcmp( "SHA224", md_name ) ) return mbedtls_md_info_from_type( MBEDTLS_MD_SHA224 ); if( !strcmp( "SHA256", md_name ) ) return mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ); #endif #if defined(MBEDTLS_SHA512_C) if( !strcmp( "SHA384", md_name ) ) return mbedtls_md_info_from_type( MBEDTLS_MD_SHA384 ); if( !strcmp( "SHA512", md_name ) ) return mbedtls_md_info_from_type( MBEDTLS_MD_SHA512 ); #endif return( NULL ); } const mbedtls_md_info_t *mbedtls_md_info_from_type( mbedtls_md_type_t md_type ) { switch( md_type ) { #if defined(MBEDTLS_MD2_C) case MBEDTLS_MD_MD2: return( &mbedtls_md2_info ); #endif #if defined(MBEDTLS_MD4_C) case MBEDTLS_MD_MD4: return( &mbedtls_md4_info ); #endif #if defined(MBEDTLS_MD5_C) case MBEDTLS_MD_MD5: return( &mbedtls_md5_info ); #endif #if defined(MBEDTLS_RIPEMD160_C) case MBEDTLS_MD_RIPEMD160: return( &mbedtls_ripemd160_info ); #endif #if defined(MBEDTLS_SHA1_C) case MBEDTLS_MD_SHA1: return( &mbedtls_sha1_info ); #endif #if defined(MBEDTLS_SHA256_C) case MBEDTLS_MD_SHA224: return( &mbedtls_sha224_info ); case MBEDTLS_MD_SHA256: return( &mbedtls_sha256_info ); #endif #if defined(MBEDTLS_SHA512_C) case MBEDTLS_MD_SHA384: return( &mbedtls_sha384_info ); case MBEDTLS_MD_SHA512: return( &mbedtls_sha512_info ); #endif default: return( NULL ); } } void mbedtls_md_init( mbedtls_md_context_t *ctx ) { memset( ctx, 0, sizeof( mbedtls_md_context_t ) ); } void mbedtls_md_free( mbedtls_md_context_t *ctx ) { if( ctx == NULL || ctx->md_info == NULL ) return; if( ctx->md_ctx != NULL ) ctx->md_info->ctx_free_func( ctx->md_ctx ); if( ctx->hmac_ctx != NULL ) { mbedtls_zeroize( ctx->hmac_ctx, 2 * ctx->md_info->block_size ); mbedtls_free( ctx->hmac_ctx ); } mbedtls_zeroize( ctx, sizeof( mbedtls_md_context_t ) ); } int mbedtls_md_clone( mbedtls_md_context_t *dst, const mbedtls_md_context_t *src ) { if( dst == NULL || dst->md_info == NULL || src == NULL || src->md_info == NULL || dst->md_info != src->md_info ) { return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); } dst->md_info->clone_func( dst->md_ctx, src->md_ctx ); return( 0 ); } #if ! defined(MBEDTLS_DEPRECATED_REMOVED) int mbedtls_md_init_ctx( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info ) { return mbedtls_md_setup( ctx, md_info, 1 ); } #endif int mbedtls_md_setup( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac ) { if( md_info == NULL || ctx == NULL ) return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); if( ( ctx->md_ctx = md_info->ctx_alloc_func() ) == NULL ) return( MBEDTLS_ERR_MD_ALLOC_FAILED ); if( hmac != 0 ) { ctx->hmac_ctx = mbedtls_calloc( 2, md_info->block_size ); if( ctx->hmac_ctx == NULL ) { md_info->ctx_free_func( ctx->md_ctx ); return( MBEDTLS_ERR_MD_ALLOC_FAILED ); } } ctx->md_info = md_info; return( 0 ); } int mbedtls_md_starts( mbedtls_md_context_t *ctx ) { if( ctx == NULL || ctx->md_info == NULL ) return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); ctx->md_info->starts_func( ctx->md_ctx ); return( 0 ); } int mbedtls_md_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ) { if( ctx == NULL || ctx->md_info == NULL ) return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); ctx->md_info->update_func( ctx->md_ctx, input, ilen ); return( 0 ); } int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output ) { if( ctx == NULL || ctx->md_info == NULL ) return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); ctx->md_info->finish_func( ctx->md_ctx, output ); return( 0 ); } int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen, unsigned char *output ) { if( md_info == NULL ) return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); md_info->digest_func( input, ilen, output ); return( 0 ); } #if defined(MBEDTLS_FS_IO) int mbedtls_md_file( const mbedtls_md_info_t *md_info, const char *path, unsigned char *output ) { int ret; FILE *f; size_t n; mbedtls_md_context_t ctx; unsigned char buf[1024]; if( md_info == NULL ) return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); if( ( f = fopen( path, "rb" ) ) == NULL ) return( MBEDTLS_ERR_MD_FILE_IO_ERROR ); mbedtls_md_init( &ctx ); if( ( ret = mbedtls_md_setup( &ctx, md_info, 0 ) ) != 0 ) goto cleanup; md_info->starts_func( ctx.md_ctx ); while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) md_info->update_func( ctx.md_ctx, buf, n ); if( ferror( f ) != 0 ) { ret = MBEDTLS_ERR_MD_FILE_IO_ERROR; goto cleanup; } md_info->finish_func( ctx.md_ctx, output ); cleanup: fclose( f ); mbedtls_md_free( &ctx ); return( ret ); } #endif /* MBEDTLS_FS_IO */ int mbedtls_md_hmac_starts( mbedtls_md_context_t *ctx, const unsigned char *key, size_t keylen ) { unsigned char sum[MBEDTLS_MD_MAX_SIZE]; unsigned char *ipad, *opad; size_t i; if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); if( keylen > (size_t) ctx->md_info->block_size ) { ctx->md_info->starts_func( ctx->md_ctx ); ctx->md_info->update_func( ctx->md_ctx, key, keylen ); ctx->md_info->finish_func( ctx->md_ctx, sum ); keylen = ctx->md_info->size; key = sum; } ipad = (unsigned char *) ctx->hmac_ctx; opad = (unsigned char *) ctx->hmac_ctx + ctx->md_info->block_size; memset( ipad, 0x36, ctx->md_info->block_size ); memset( opad, 0x5C, ctx->md_info->block_size ); for( i = 0; i < keylen; i++ ) { ipad[i] = (unsigned char)( ipad[i] ^ key[i] ); opad[i] = (unsigned char)( opad[i] ^ key[i] ); } mbedtls_zeroize( sum, sizeof( sum ) ); ctx->md_info->starts_func( ctx->md_ctx ); ctx->md_info->update_func( ctx->md_ctx, ipad, ctx->md_info->block_size ); return( 0 ); } int mbedtls_md_hmac_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ) { if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); ctx->md_info->update_func( ctx->md_ctx, input, ilen ); return( 0 ); } int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output ) { unsigned char tmp[MBEDTLS_MD_MAX_SIZE]; unsigned char *opad; if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); opad = (unsigned char *) ctx->hmac_ctx + ctx->md_info->block_size; ctx->md_info->finish_func( ctx->md_ctx, tmp ); ctx->md_info->starts_func( ctx->md_ctx ); ctx->md_info->update_func( ctx->md_ctx, opad, ctx->md_info->block_size ); ctx->md_info->update_func( ctx->md_ctx, tmp, ctx->md_info->size ); ctx->md_info->finish_func( ctx->md_ctx, output ); return( 0 ); } int mbedtls_md_hmac_reset( mbedtls_md_context_t *ctx ) { unsigned char *ipad; if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); ipad = (unsigned char *) ctx->hmac_ctx; ctx->md_info->starts_func( ctx->md_ctx ); ctx->md_info->update_func( ctx->md_ctx, ipad, ctx->md_info->block_size ); return( 0 ); } int mbedtls_md_hmac( const mbedtls_md_info_t *md_info, const unsigned char *key, size_t keylen, const unsigned char *input, size_t ilen, unsigned char *output ) { mbedtls_md_context_t ctx; int ret; if( md_info == NULL ) return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); mbedtls_md_init( &ctx ); if( ( ret = mbedtls_md_setup( &ctx, md_info, 1 ) ) != 0 ) return( ret ); mbedtls_md_hmac_starts( &ctx, key, keylen ); mbedtls_md_hmac_update( &ctx, input, ilen ); mbedtls_md_hmac_finish( &ctx, output ); mbedtls_md_free( &ctx ); return( 0 ); } int mbedtls_md_process( mbedtls_md_context_t *ctx, const unsigned char *data ) { if( ctx == NULL || ctx->md_info == NULL ) return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); ctx->md_info->process_func( ctx->md_ctx, data ); return( 0 ); } unsigned char mbedtls_md_get_size( const mbedtls_md_info_t *md_info ) { if( md_info == NULL ) return( 0 ); return md_info->size; } mbedtls_md_type_t mbedtls_md_get_type( const mbedtls_md_info_t *md_info ) { if( md_info == NULL ) return( MBEDTLS_MD_NONE ); return md_info->type; } const char *mbedtls_md_get_name( const mbedtls_md_info_t *md_info ) { if( md_info == NULL ) return( NULL ); return md_info->name; } oor-1.2.0/oor/elibs/mbedtls/md.h000066400000000000000000000301651313612200500164070ustar00rootroot00000000000000/** * \file mbedtls_md.h * * \brief Generic message digest wrapper * * \author Adriaan de Jong * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * Copyright (C) 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is part of mbed TLS (https://tls.mbed.org) * * Original code by mbed TLS project. Modified by the LISPmob project. */ #ifndef MBEDTLS_MD_H #define MBEDTLS_MD_H #include #define MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE -0x5080 /**< The selected feature is not available. */ #define MBEDTLS_ERR_MD_BAD_INPUT_DATA -0x5100 /**< Bad input parameters to function. */ #define MBEDTLS_ERR_MD_ALLOC_FAILED -0x5180 /**< Failed to allocate memory. */ #define MBEDTLS_ERR_MD_FILE_IO_ERROR -0x5200 /**< Opening or reading of file failed. */ #ifdef __cplusplus extern "C" { #endif typedef enum { MBEDTLS_MD_NONE=0, MBEDTLS_MD_MD2, MBEDTLS_MD_MD4, MBEDTLS_MD_MD5, MBEDTLS_MD_SHA1, MBEDTLS_MD_SHA224, MBEDTLS_MD_SHA256, MBEDTLS_MD_SHA384, MBEDTLS_MD_SHA512, MBEDTLS_MD_RIPEMD160, } mbedtls_md_type_t; #if defined(MBEDTLS_SHA512_C) #define MBEDTLS_MD_MAX_SIZE 64 /* longest known is SHA512 */ #else #define MBEDTLS_MD_MAX_SIZE 32 /* longest known is SHA256 or less */ #endif /** * Opaque struct defined in md_internal.h */ typedef struct mbedtls_md_info_t mbedtls_md_info_t; /** * Generic message digest context. */ typedef struct { /** Information about the associated message digest */ const mbedtls_md_info_t *md_info; /** Digest-specific context */ void *md_ctx; /** HMAC part of the context */ void *hmac_ctx; } mbedtls_md_context_t; /** * \brief Returns the list of digests supported by the generic digest module. * * \return a statically allocated array of digests, the last entry * is 0. */ const int *mbedtls_md_list( void ); /** * \brief Returns the message digest information associated with the * given digest name. * * \param md_name Name of the digest to search for. * * \return The message digest information associated with md_name or * NULL if not found. */ const mbedtls_md_info_t *mbedtls_md_info_from_string( const char *md_name ); /** * \brief Returns the message digest information associated with the * given digest type. * * \param md_type type of digest to search for. * * \return The message digest information associated with md_type or * NULL if not found. */ const mbedtls_md_info_t *mbedtls_md_info_from_type( mbedtls_md_type_t md_type ); /** * \brief Initialize a md_context (as NONE) * This should always be called first. * Prepares the context for mbedtls_md_setup() or mbedtls_md_free(). */ void mbedtls_md_init( mbedtls_md_context_t *ctx ); /** * \brief Free and clear the internal structures of ctx. * Can be called at any time after mbedtls_md_init(). * Mandatory once mbedtls_md_setup() has been called. */ void mbedtls_md_free( mbedtls_md_context_t *ctx ); #if ! defined(MBEDTLS_DEPRECATED_REMOVED) #if defined(MBEDTLS_DEPRECATED_WARNING) #define MBEDTLS_DEPRECATED __attribute__((deprecated)) #else #define MBEDTLS_DEPRECATED #endif /** * \brief Select MD to use and allocate internal structures. * Should be called after mbedtls_md_init() or mbedtls_md_free(). * Makes it necessary to call mbedtls_md_free() later. * * \deprecated Superseded by mbedtls_md_setup() in 2.0.0 * * \param ctx Context to set up. * \param md_info Message digest to use. * * \returns \c 0 on success, * \c MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter failure, * \c MBEDTLS_ERR_MD_ALLOC_FAILED memory allocation failure. */ int mbedtls_md_init_ctx( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info ) MBEDTLS_DEPRECATED; #undef MBEDTLS_DEPRECATED #endif /* MBEDTLS_DEPRECATED_REMOVED */ /** * \brief Select MD to use and allocate internal structures. * Should be called after mbedtls_md_init() or mbedtls_md_free(). * Makes it necessary to call mbedtls_md_free() later. * * \param ctx Context to set up. * \param md_info Message digest to use. * \param hmac 0 to save some memory if HMAC will not be used, * non-zero is HMAC is going to be used with this context. * * \returns \c 0 on success, * \c MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter failure, * \c MBEDTLS_ERR_MD_ALLOC_FAILED memory allocation failure. */ int mbedtls_md_setup( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac ); /** * \brief Clone the state of an MD context * * \note The two contexts must have been setup to the same type * (cloning from SHA-256 to SHA-512 make no sense). * * \warning Only clones the MD state, not the HMAC state! (for now) * * \param dst The destination context * \param src The context to be cloned * * \return \c 0 on success, * \c MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter failure. */ int mbedtls_md_clone( mbedtls_md_context_t *dst, const mbedtls_md_context_t *src ); /** * \brief Returns the size of the message digest output. * * \param md_info message digest info * * \return size of the message digest output in bytes. */ unsigned char mbedtls_md_get_size( const mbedtls_md_info_t *md_info ); /** * \brief Returns the type of the message digest output. * * \param md_info message digest info * * \return type of the message digest output. */ mbedtls_md_type_t mbedtls_md_get_type( const mbedtls_md_info_t *md_info ); /** * \brief Returns the name of the message digest output. * * \param md_info message digest info * * \return name of the message digest output. */ const char *mbedtls_md_get_name( const mbedtls_md_info_t *md_info ); /** * \brief Prepare the context to digest a new message. * Generally called after mbedtls_md_setup() or mbedtls_md_finish(). * Followed by mbedtls_md_update(). * * \param ctx generic message digest context. * * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter * verification fails. */ int mbedtls_md_starts( mbedtls_md_context_t *ctx ); /** * \brief Generic message digest process buffer * Called between mbedtls_md_starts() and mbedtls_md_finish(). * May be called repeatedly. * * \param ctx Generic message digest context * \param input buffer holding the datal * \param ilen length of the input data * * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter * verification fails. */ int mbedtls_md_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ); /** * \brief Generic message digest final digest * Called after mbedtls_md_update(). * Usually followed by mbedtls_md_free() or mbedtls_md_starts(). * * \param ctx Generic message digest context * \param output Generic message digest checksum result * * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter * verification fails. */ int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output ); /** * \brief Output = message_digest( input buffer ) * * \param md_info message digest info * \param input buffer holding the data * \param ilen length of the input data * \param output Generic message digest checksum result * * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter * verification fails. */ int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen, unsigned char *output ); #if defined(MBEDTLS_FS_IO) /** * \brief Output = message_digest( file contents ) * * \param md_info message digest info * \param path input file name * \param output generic message digest checksum result * * \return 0 if successful, * MBEDTLS_ERR_MD_FILE_IO_ERROR if file input failed, * MBEDTLS_ERR_MD_BAD_INPUT_DATA if md_info was NULL. */ int mbedtls_md_file( const mbedtls_md_info_t *md_info, const char *path, unsigned char *output ); #endif /* MBEDTLS_FS_IO */ /** * \brief Set HMAC key and prepare to authenticate a new message. * Usually called after mbedtls_md_setup() or mbedtls_md_hmac_finish(). * * \param ctx HMAC context * \param key HMAC secret key * \param keylen length of the HMAC key in bytes * * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter * verification fails. */ int mbedtls_md_hmac_starts( mbedtls_md_context_t *ctx, const unsigned char *key, size_t keylen ); /** * \brief Generic HMAC process buffer. * Called between mbedtls_md_hmac_starts() or mbedtls_md_hmac_reset() * and mbedtls_md_hmac_finish(). * May be called repeatedly. * * \param ctx HMAC context * \param input buffer holding the data * \param ilen length of the input data * * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter * verification fails. */ int mbedtls_md_hmac_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ); /** * \brief Output HMAC. * Called after mbedtls_md_hmac_update(). * Usually followed my mbedtls_md_hmac_reset(), mbedtls_md_hmac_starts(), * or mbedtls_md_free(). * * \param ctx HMAC context * \param output Generic HMAC checksum result * * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter * verification fails. */ int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output); /** * \brief Prepare to authenticate a new message with the same key. * Called after mbedtls_md_hmac_finish() and before mbedtls_md_hmac_update(). * * \param ctx HMAC context to be reset * * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter * verification fails. */ int mbedtls_md_hmac_reset( mbedtls_md_context_t *ctx ); /** * \brief Output = Generic_HMAC( hmac key, input buffer ) * * \param md_info message digest info * \param key HMAC secret key * \param keylen length of the HMAC key in bytes * \param input buffer holding the data * \param ilen length of the input data * \param output Generic HMAC-result * * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter * verification fails. */ int mbedtls_md_hmac( const mbedtls_md_info_t *md_info, const unsigned char *key, size_t keylen, const unsigned char *input, size_t ilen, unsigned char *output ); /* Internal use */ int mbedtls_md_process( mbedtls_md_context_t *ctx, const unsigned char *data ); #ifdef __cplusplus } #endif #endif /* MBEDTLS_MD_H */ oor-1.2.0/oor/elibs/mbedtls/md_internal.h000066400000000000000000000062431313612200500203030ustar00rootroot00000000000000/** * \file md_internal.h * * \brief Message digest wrappers. * * \warning This in an internal header. Do not include directly. * * \author Adriaan de Jong * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * Copyright (C) 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is part of mbed TLS (https://tls.mbed.org) * * Original code by mbed TLS project. Modified by the LISPmob project. */ #ifndef MBEDTLS_MD_WRAP_H #define MBEDTLS_MD_WRAP_H #include "md.h" #ifdef __cplusplus extern "C" { #endif #define MBEDTLS_SHA256_C #define MBEDTLS_SHA1_C /** * Message digest information. * Allows message digest functions to be called in a generic way. */ struct mbedtls_md_info_t { /** Digest identifier */ mbedtls_md_type_t type; /** Name of the message digest */ const char * name; /** Output length of the digest function in bytes */ int size; /** Block length of the digest function in bytes */ int block_size; /** Digest initialisation function */ void (*starts_func)( void *ctx ); /** Digest update function */ void (*update_func)( void *ctx, const unsigned char *input, size_t ilen ); /** Digest finalisation function */ void (*finish_func)( void *ctx, unsigned char *output ); /** Generic digest function */ void (*digest_func)( const unsigned char *input, size_t ilen, unsigned char *output ); /** Allocate a new context */ void * (*ctx_alloc_func)( void ); /** Free the given context */ void (*ctx_free_func)( void *ctx ); /** Clone state from a context */ void (*clone_func)( void *dst, const void *src ); /** Internal use only */ void (*process_func)( void *ctx, const unsigned char *input ); }; #if defined(MBEDTLS_MD2_C) extern const mbedtls_md_info_t mbedtls_md2_info; #endif #if defined(MBEDTLS_MD4_C) extern const mbedtls_md_info_t mbedtls_md4_info; #endif #if defined(MBEDTLS_MD5_C) extern const mbedtls_md_info_t mbedtls_md5_info; #endif #if defined(MBEDTLS_RIPEMD160_C) extern const mbedtls_md_info_t mbedtls_ripemd160_info; #endif #if defined(MBEDTLS_SHA1_C) extern const mbedtls_md_info_t mbedtls_sha1_info; #endif #if defined(MBEDTLS_SHA256_C) extern const mbedtls_md_info_t mbedtls_sha224_info; extern const mbedtls_md_info_t mbedtls_sha256_info; #endif #if defined(MBEDTLS_SHA512_C) extern const mbedtls_md_info_t mbedtls_sha384_info; extern const mbedtls_md_info_t mbedtls_sha512_info; #endif #ifdef __cplusplus } #endif #endif /* MBEDTLS_MD_WRAP_H */ oor-1.2.0/oor/elibs/mbedtls/md_wrap.c000066400000000000000000000315421313612200500174330ustar00rootroot00000000000000/** * \file md_wrap.c * * \brief Generic message digest wrapper for mbed TLS * * \author Adriaan de Jong * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * Copyright (C) 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is part of mbed TLS (https://tls.mbed.org) * * Original code by mbed TLS project. Modified by the LISPmob project. */ #include "md_internal.h" #if defined(MBEDTLS_MD2_C) #include "md2.h" #endif #if defined(MBEDTLS_MD4_C) #include "md4.h" #endif #if defined(MBEDTLS_MD5_C) #include "md5.h" #endif #if defined(MBEDTLS_RIPEMD160_C) #include "ripemd160.h" #endif #if defined(MBEDTLS_SHA1_C) #include "sha1.h" #endif #if defined(MBEDTLS_SHA256_C) #include "sha256.h" #endif #if defined(MBEDTLS_SHA512_C) #include "sha512.h" #endif #if defined(MBEDTLS_PLATFORM_C) #include "platform.h" #else #include #define mbedtls_calloc calloc #define mbedtls_free free #endif #if defined(MBEDTLS_MD2_C) static void md2_starts_wrap( void *ctx ) { mbedtls_md2_starts( (mbedtls_md2_context *) ctx ); } static void md2_update_wrap( void *ctx, const unsigned char *input, size_t ilen ) { mbedtls_md2_update( (mbedtls_md2_context *) ctx, input, ilen ); } static void md2_finish_wrap( void *ctx, unsigned char *output ) { mbedtls_md2_finish( (mbedtls_md2_context *) ctx, output ); } static void *md2_ctx_alloc( void ) { void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_md2_context ) ); if( ctx != NULL ) mbedtls_md2_init( (mbedtls_md2_context *) ctx ); return( ctx ); } static void md2_ctx_free( void *ctx ) { mbedtls_md2_free( (mbedtls_md2_context *) ctx ); mbedtls_free( ctx ); } static void md2_clone_wrap( void *dst, const void *src ) { mbedtls_md2_clone( (mbedtls_md2_context *) dst, (const mbedtls_md2_context *) src ); } static void md2_process_wrap( void *ctx, const unsigned char *data ) { ((void) data); mbedtls_md2_process( (mbedtls_md2_context *) ctx ); } const mbedtls_md_info_t mbedtls_md2_info = { MBEDTLS_MD_MD2, "MD2", 16, 16, md2_starts_wrap, md2_update_wrap, md2_finish_wrap, mbedtls_md2, md2_ctx_alloc, md2_ctx_free, md2_clone_wrap, md2_process_wrap, }; #endif /* MBEDTLS_MD2_C */ #if defined(MBEDTLS_MD4_C) static void md4_starts_wrap( void *ctx ) { mbedtls_md4_starts( (mbedtls_md4_context *) ctx ); } static void md4_update_wrap( void *ctx, const unsigned char *input, size_t ilen ) { mbedtls_md4_update( (mbedtls_md4_context *) ctx, input, ilen ); } static void md4_finish_wrap( void *ctx, unsigned char *output ) { mbedtls_md4_finish( (mbedtls_md4_context *) ctx, output ); } static void *md4_ctx_alloc( void ) { void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_md4_context ) ); if( ctx != NULL ) mbedtls_md4_init( (mbedtls_md4_context *) ctx ); return( ctx ); } static void md4_ctx_free( void *ctx ) { mbedtls_md4_free( (mbedtls_md4_context *) ctx ); mbedtls_free( ctx ); } static void md4_clone_wrap( void *dst, const void *src ) { mbedtls_md4_clone( (mbedtls_md4_context *) dst, (const mbedtls_md4_context *) src ); } static void md4_process_wrap( void *ctx, const unsigned char *data ) { mbedtls_md4_process( (mbedtls_md4_context *) ctx, data ); } const mbedtls_md_info_t mbedtls_md4_info = { MBEDTLS_MD_MD4, "MD4", 16, 64, md4_starts_wrap, md4_update_wrap, md4_finish_wrap, mbedtls_md4, md4_ctx_alloc, md4_ctx_free, md4_clone_wrap, md4_process_wrap, }; #endif /* MBEDTLS_MD4_C */ #if defined(MBEDTLS_MD5_C) static void md5_starts_wrap( void *ctx ) { mbedtls_md5_starts( (mbedtls_md5_context *) ctx ); } static void md5_update_wrap( void *ctx, const unsigned char *input, size_t ilen ) { mbedtls_md5_update( (mbedtls_md5_context *) ctx, input, ilen ); } static void md5_finish_wrap( void *ctx, unsigned char *output ) { mbedtls_md5_finish( (mbedtls_md5_context *) ctx, output ); } static void *md5_ctx_alloc( void ) { void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_md5_context ) ); if( ctx != NULL ) mbedtls_md5_init( (mbedtls_md5_context *) ctx ); return( ctx ); } static void md5_ctx_free( void *ctx ) { mbedtls_md5_free( (mbedtls_md5_context *) ctx ); mbedtls_free( ctx ); } static void md5_clone_wrap( void *dst, const void *src ) { mbedtls_md5_clone( (mbedtls_md5_context *) dst, (const mbedtls_md5_context *) src ); } static void md5_process_wrap( void *ctx, const unsigned char *data ) { mbedtls_md5_process( (mbedtls_md5_context *) ctx, data ); } const mbedtls_md_info_t mbedtls_md5_info = { MBEDTLS_MD_MD5, "MD5", 16, 64, md5_starts_wrap, md5_update_wrap, md5_finish_wrap, mbedtls_md5, md5_ctx_alloc, md5_ctx_free, md5_clone_wrap, md5_process_wrap, }; #endif /* MBEDTLS_MD5_C */ #if defined(MBEDTLS_RIPEMD160_C) static void ripemd160_starts_wrap( void *ctx ) { mbedtls_ripemd160_starts( (mbedtls_ripemd160_context *) ctx ); } static void ripemd160_update_wrap( void *ctx, const unsigned char *input, size_t ilen ) { mbedtls_ripemd160_update( (mbedtls_ripemd160_context *) ctx, input, ilen ); } static void ripemd160_finish_wrap( void *ctx, unsigned char *output ) { mbedtls_ripemd160_finish( (mbedtls_ripemd160_context *) ctx, output ); } static void *ripemd160_ctx_alloc( void ) { void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ripemd160_context ) ); if( ctx != NULL ) mbedtls_ripemd160_init( (mbedtls_ripemd160_context *) ctx ); return( ctx ); } static void ripemd160_ctx_free( void *ctx ) { mbedtls_ripemd160_free( (mbedtls_ripemd160_context *) ctx ); mbedtls_free( ctx ); } static void ripemd160_clone_wrap( void *dst, const void *src ) { mbedtls_ripemd160_clone( (mbedtls_ripemd160_context *) dst, (const mbedtls_ripemd160_context *) src ); } static void ripemd160_process_wrap( void *ctx, const unsigned char *data ) { mbedtls_ripemd160_process( (mbedtls_ripemd160_context *) ctx, data ); } const mbedtls_md_info_t mbedtls_ripemd160_info = { MBEDTLS_MD_RIPEMD160, "RIPEMD160", 20, 64, ripemd160_starts_wrap, ripemd160_update_wrap, ripemd160_finish_wrap, mbedtls_ripemd160, ripemd160_ctx_alloc, ripemd160_ctx_free, ripemd160_clone_wrap, ripemd160_process_wrap, }; #endif /* MBEDTLS_RIPEMD160_C */ #if defined(MBEDTLS_SHA1_C) static void sha1_starts_wrap( void *ctx ) { mbedtls_sha1_starts( (mbedtls_sha1_context *) ctx ); } static void sha1_update_wrap( void *ctx, const unsigned char *input, size_t ilen ) { mbedtls_sha1_update( (mbedtls_sha1_context *) ctx, input, ilen ); } static void sha1_finish_wrap( void *ctx, unsigned char *output ) { mbedtls_sha1_finish( (mbedtls_sha1_context *) ctx, output ); } static void *sha1_ctx_alloc( void ) { void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_sha1_context ) ); if( ctx != NULL ) mbedtls_sha1_init( (mbedtls_sha1_context *) ctx ); return( ctx ); } static void sha1_clone_wrap( void *dst, const void *src ) { mbedtls_sha1_clone( (mbedtls_sha1_context *) dst, (const mbedtls_sha1_context *) src ); } static void sha1_ctx_free( void *ctx ) { mbedtls_sha1_free( (mbedtls_sha1_context *) ctx ); mbedtls_free( ctx ); } static void sha1_process_wrap( void *ctx, const unsigned char *data ) { mbedtls_sha1_process( (mbedtls_sha1_context *) ctx, data ); } const mbedtls_md_info_t mbedtls_sha1_info = { MBEDTLS_MD_SHA1, "SHA1", 20, 64, sha1_starts_wrap, sha1_update_wrap, sha1_finish_wrap, mbedtls_sha1, sha1_ctx_alloc, sha1_ctx_free, sha1_clone_wrap, sha1_process_wrap, }; #endif /* MBEDTLS_SHA1_C */ /* * Wrappers for generic message digests */ #if defined(MBEDTLS_SHA256_C) static void sha224_starts_wrap( void *ctx ) { mbedtls_sha256_starts( (mbedtls_sha256_context *) ctx, 1 ); } static void sha224_update_wrap( void *ctx, const unsigned char *input, size_t ilen ) { mbedtls_sha256_update( (mbedtls_sha256_context *) ctx, input, ilen ); } static void sha224_finish_wrap( void *ctx, unsigned char *output ) { mbedtls_sha256_finish( (mbedtls_sha256_context *) ctx, output ); } static void sha224_wrap( const unsigned char *input, size_t ilen, unsigned char *output ) { mbedtls_sha256( input, ilen, output, 1 ); } static void *sha224_ctx_alloc( void ) { void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_sha256_context ) ); if( ctx != NULL ) mbedtls_sha256_init( (mbedtls_sha256_context *) ctx ); return( ctx ); } static void sha224_ctx_free( void *ctx ) { mbedtls_sha256_free( (mbedtls_sha256_context *) ctx ); mbedtls_free( ctx ); } static void sha224_clone_wrap( void *dst, const void *src ) { mbedtls_sha256_clone( (mbedtls_sha256_context *) dst, (const mbedtls_sha256_context *) src ); } static void sha224_process_wrap( void *ctx, const unsigned char *data ) { mbedtls_sha256_process( (mbedtls_sha256_context *) ctx, data ); } const mbedtls_md_info_t mbedtls_sha224_info = { MBEDTLS_MD_SHA224, "SHA224", 28, 64, sha224_starts_wrap, sha224_update_wrap, sha224_finish_wrap, sha224_wrap, sha224_ctx_alloc, sha224_ctx_free, sha224_clone_wrap, sha224_process_wrap, }; static void sha256_starts_wrap( void *ctx ) { mbedtls_sha256_starts( (mbedtls_sha256_context *) ctx, 0 ); } static void sha256_wrap( const unsigned char *input, size_t ilen, unsigned char *output ) { mbedtls_sha256( input, ilen, output, 0 ); } const mbedtls_md_info_t mbedtls_sha256_info = { MBEDTLS_MD_SHA256, "SHA256", 32, 64, sha256_starts_wrap, sha224_update_wrap, sha224_finish_wrap, sha256_wrap, sha224_ctx_alloc, sha224_ctx_free, sha224_clone_wrap, sha224_process_wrap, }; #endif /* MBEDTLS_SHA256_C */ #if defined(MBEDTLS_SHA512_C) static void sha384_starts_wrap( void *ctx ) { mbedtls_sha512_starts( (mbedtls_sha512_context *) ctx, 1 ); } static void sha384_update_wrap( void *ctx, const unsigned char *input, size_t ilen ) { mbedtls_sha512_update( (mbedtls_sha512_context *) ctx, input, ilen ); } static void sha384_finish_wrap( void *ctx, unsigned char *output ) { mbedtls_sha512_finish( (mbedtls_sha512_context *) ctx, output ); } static void sha384_wrap( const unsigned char *input, size_t ilen, unsigned char *output ) { mbedtls_sha512( input, ilen, output, 1 ); } static void *sha384_ctx_alloc( void ) { void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_sha512_context ) ); if( ctx != NULL ) mbedtls_sha512_init( (mbedtls_sha512_context *) ctx ); return( ctx ); } static void sha384_ctx_free( void *ctx ) { mbedtls_sha512_free( (mbedtls_sha512_context *) ctx ); mbedtls_free( ctx ); } static void sha384_clone_wrap( void *dst, const void *src ) { mbedtls_sha512_clone( (mbedtls_sha512_context *) dst, (const mbedtls_sha512_context *) src ); } static void sha384_process_wrap( void *ctx, const unsigned char *data ) { mbedtls_sha512_process( (mbedtls_sha512_context *) ctx, data ); } const mbedtls_md_info_t mbedtls_sha384_info = { MBEDTLS_MD_SHA384, "SHA384", 48, 128, sha384_starts_wrap, sha384_update_wrap, sha384_finish_wrap, sha384_wrap, sha384_ctx_alloc, sha384_ctx_free, sha384_clone_wrap, sha384_process_wrap, }; static void sha512_starts_wrap( void *ctx ) { mbedtls_sha512_starts( (mbedtls_sha512_context *) ctx, 0 ); } static void sha512_wrap( const unsigned char *input, size_t ilen, unsigned char *output ) { mbedtls_sha512( input, ilen, output, 0 ); } const mbedtls_md_info_t mbedtls_sha512_info = { MBEDTLS_MD_SHA512, "SHA512", 64, 128, sha512_starts_wrap, sha384_update_wrap, sha384_finish_wrap, sha512_wrap, sha384_ctx_alloc, sha384_ctx_free, sha384_clone_wrap, sha384_process_wrap, }; #endif /* MBEDTLS_SHA512_C */ oor-1.2.0/oor/elibs/mbedtls/sha1.c000066400000000000000000000224371313612200500166410ustar00rootroot00000000000000/* * FIPS-180-1 compliant SHA-1 implementation * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * Copyright (C) 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is part of mbed TLS (https://tls.mbed.org) */ /* * The SHA-1 standard was published by NIST in 1993. * * http://www.itl.nist.gov/fipspubs/fip180-1.htm * * Original code by mbed TLS project. Modified by the LISPmob project. */ #include "sha1.h" #include #if !defined(MBEDTLS_SHA1_ALT) /* Implementation that should never be optimized out by the compiler */ static void mbedtls_zeroize( void *v, size_t n ) { volatile unsigned char *p = v; while( n-- ) *p++ = 0; } /* * 32-bit integer manipulation macros (big endian) */ #ifndef GET_UINT32_BE #define GET_UINT32_BE(n,b,i) \ { \ (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ | ( (uint32_t) (b)[(i) + 1] << 16 ) \ | ( (uint32_t) (b)[(i) + 2] << 8 ) \ | ( (uint32_t) (b)[(i) + 3] ); \ } #endif #ifndef PUT_UINT32_BE #define PUT_UINT32_BE(n,b,i) \ { \ (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ (b)[(i) + 3] = (unsigned char) ( (n) ); \ } #endif void mbedtls_sha1_init( mbedtls_sha1_context *ctx ) { memset( ctx, 0, sizeof( mbedtls_sha1_context ) ); } void mbedtls_sha1_free( mbedtls_sha1_context *ctx ) { if( ctx == NULL ) return; mbedtls_zeroize( ctx, sizeof( mbedtls_sha1_context ) ); } void mbedtls_sha1_clone( mbedtls_sha1_context *dst, const mbedtls_sha1_context *src ) { *dst = *src; } /* * SHA-1 context setup */ void mbedtls_sha1_starts( mbedtls_sha1_context *ctx ) { ctx->total[0] = 0; ctx->total[1] = 0; ctx->state[0] = 0x67452301; ctx->state[1] = 0xEFCDAB89; ctx->state[2] = 0x98BADCFE; ctx->state[3] = 0x10325476; ctx->state[4] = 0xC3D2E1F0; } #if !defined(MBEDTLS_SHA1_PROCESS_ALT) void mbedtls_sha1_process( mbedtls_sha1_context *ctx, const unsigned char data[64] ) { uint32_t temp, W[16], A, B, C, D, E; GET_UINT32_BE( W[ 0], data, 0 ); GET_UINT32_BE( W[ 1], data, 4 ); GET_UINT32_BE( W[ 2], data, 8 ); GET_UINT32_BE( W[ 3], data, 12 ); GET_UINT32_BE( W[ 4], data, 16 ); GET_UINT32_BE( W[ 5], data, 20 ); GET_UINT32_BE( W[ 6], data, 24 ); GET_UINT32_BE( W[ 7], data, 28 ); GET_UINT32_BE( W[ 8], data, 32 ); GET_UINT32_BE( W[ 9], data, 36 ); GET_UINT32_BE( W[10], data, 40 ); GET_UINT32_BE( W[11], data, 44 ); GET_UINT32_BE( W[12], data, 48 ); GET_UINT32_BE( W[13], data, 52 ); GET_UINT32_BE( W[14], data, 56 ); GET_UINT32_BE( W[15], data, 60 ); #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) #define R(t) \ ( \ temp = W[( t - 3 ) & 0x0F] ^ W[( t - 8 ) & 0x0F] ^ \ W[( t - 14 ) & 0x0F] ^ W[ t & 0x0F], \ ( W[t & 0x0F] = S(temp,1) ) \ ) #define P(a,b,c,d,e,x) \ { \ e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \ } A = ctx->state[0]; B = ctx->state[1]; C = ctx->state[2]; D = ctx->state[3]; E = ctx->state[4]; #define F(x,y,z) (z ^ (x & (y ^ z))) #define K 0x5A827999 P( A, B, C, D, E, W[0] ); P( E, A, B, C, D, W[1] ); P( D, E, A, B, C, W[2] ); P( C, D, E, A, B, W[3] ); P( B, C, D, E, A, W[4] ); P( A, B, C, D, E, W[5] ); P( E, A, B, C, D, W[6] ); P( D, E, A, B, C, W[7] ); P( C, D, E, A, B, W[8] ); P( B, C, D, E, A, W[9] ); P( A, B, C, D, E, W[10] ); P( E, A, B, C, D, W[11] ); P( D, E, A, B, C, W[12] ); P( C, D, E, A, B, W[13] ); P( B, C, D, E, A, W[14] ); P( A, B, C, D, E, W[15] ); P( E, A, B, C, D, R(16) ); P( D, E, A, B, C, R(17) ); P( C, D, E, A, B, R(18) ); P( B, C, D, E, A, R(19) ); #undef K #undef F #define F(x,y,z) (x ^ y ^ z) #define K 0x6ED9EBA1 P( A, B, C, D, E, R(20) ); P( E, A, B, C, D, R(21) ); P( D, E, A, B, C, R(22) ); P( C, D, E, A, B, R(23) ); P( B, C, D, E, A, R(24) ); P( A, B, C, D, E, R(25) ); P( E, A, B, C, D, R(26) ); P( D, E, A, B, C, R(27) ); P( C, D, E, A, B, R(28) ); P( B, C, D, E, A, R(29) ); P( A, B, C, D, E, R(30) ); P( E, A, B, C, D, R(31) ); P( D, E, A, B, C, R(32) ); P( C, D, E, A, B, R(33) ); P( B, C, D, E, A, R(34) ); P( A, B, C, D, E, R(35) ); P( E, A, B, C, D, R(36) ); P( D, E, A, B, C, R(37) ); P( C, D, E, A, B, R(38) ); P( B, C, D, E, A, R(39) ); #undef K #undef F #define F(x,y,z) ((x & y) | (z & (x | y))) #define K 0x8F1BBCDC P( A, B, C, D, E, R(40) ); P( E, A, B, C, D, R(41) ); P( D, E, A, B, C, R(42) ); P( C, D, E, A, B, R(43) ); P( B, C, D, E, A, R(44) ); P( A, B, C, D, E, R(45) ); P( E, A, B, C, D, R(46) ); P( D, E, A, B, C, R(47) ); P( C, D, E, A, B, R(48) ); P( B, C, D, E, A, R(49) ); P( A, B, C, D, E, R(50) ); P( E, A, B, C, D, R(51) ); P( D, E, A, B, C, R(52) ); P( C, D, E, A, B, R(53) ); P( B, C, D, E, A, R(54) ); P( A, B, C, D, E, R(55) ); P( E, A, B, C, D, R(56) ); P( D, E, A, B, C, R(57) ); P( C, D, E, A, B, R(58) ); P( B, C, D, E, A, R(59) ); #undef K #undef F #define F(x,y,z) (x ^ y ^ z) #define K 0xCA62C1D6 P( A, B, C, D, E, R(60) ); P( E, A, B, C, D, R(61) ); P( D, E, A, B, C, R(62) ); P( C, D, E, A, B, R(63) ); P( B, C, D, E, A, R(64) ); P( A, B, C, D, E, R(65) ); P( E, A, B, C, D, R(66) ); P( D, E, A, B, C, R(67) ); P( C, D, E, A, B, R(68) ); P( B, C, D, E, A, R(69) ); P( A, B, C, D, E, R(70) ); P( E, A, B, C, D, R(71) ); P( D, E, A, B, C, R(72) ); P( C, D, E, A, B, R(73) ); P( B, C, D, E, A, R(74) ); P( A, B, C, D, E, R(75) ); P( E, A, B, C, D, R(76) ); P( D, E, A, B, C, R(77) ); P( C, D, E, A, B, R(78) ); P( B, C, D, E, A, R(79) ); #undef K #undef F ctx->state[0] += A; ctx->state[1] += B; ctx->state[2] += C; ctx->state[3] += D; ctx->state[4] += E; } #endif /* !MBEDTLS_SHA1_PROCESS_ALT */ /* * SHA-1 process buffer */ void mbedtls_sha1_update( mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen ) { size_t fill; uint32_t left; if( ilen == 0 ) return; left = ctx->total[0] & 0x3F; fill = 64 - left; ctx->total[0] += (uint32_t) ilen; ctx->total[0] &= 0xFFFFFFFF; if( ctx->total[0] < (uint32_t) ilen ) ctx->total[1]++; if( left && ilen >= fill ) { memcpy( (void *) (ctx->buffer + left), input, fill ); mbedtls_sha1_process( ctx, ctx->buffer ); input += fill; ilen -= fill; left = 0; } while( ilen >= 64 ) { mbedtls_sha1_process( ctx, input ); input += 64; ilen -= 64; } if( ilen > 0 ) memcpy( (void *) (ctx->buffer + left), input, ilen ); } static const unsigned char sha1_padding[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* * SHA-1 final digest */ void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, unsigned char output[20] ) { uint32_t last, padn; uint32_t high, low; unsigned char msglen[8]; high = ( ctx->total[0] >> 29 ) | ( ctx->total[1] << 3 ); low = ( ctx->total[0] << 3 ); PUT_UINT32_BE( high, msglen, 0 ); PUT_UINT32_BE( low, msglen, 4 ); last = ctx->total[0] & 0x3F; padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); mbedtls_sha1_update( ctx, sha1_padding, padn ); mbedtls_sha1_update( ctx, msglen, 8 ); PUT_UINT32_BE( ctx->state[0], output, 0 ); PUT_UINT32_BE( ctx->state[1], output, 4 ); PUT_UINT32_BE( ctx->state[2], output, 8 ); PUT_UINT32_BE( ctx->state[3], output, 12 ); PUT_UINT32_BE( ctx->state[4], output, 16 ); } #endif /* !MBEDTLS_SHA1_ALT */ /* * output = SHA-1( input buffer ) */ void mbedtls_sha1( const unsigned char *input, size_t ilen, unsigned char output[20] ) { mbedtls_sha1_context ctx; mbedtls_sha1_init( &ctx ); mbedtls_sha1_starts( &ctx ); mbedtls_sha1_update( &ctx, input, ilen ); mbedtls_sha1_finish( &ctx, output ); mbedtls_sha1_free( &ctx ); } oor-1.2.0/oor/elibs/mbedtls/sha1.h000066400000000000000000000065511313612200500166450ustar00rootroot00000000000000/** * \file mbedtls_sha1.h * * \brief SHA-1 cryptographic hash function * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * Copyright (C) 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is part of mbed TLS (https://tls.mbed.org) * * Original code by mbed TLS project. Modified by the LISPmob project. */ #ifndef MBEDTLS_SHA1_H #define MBEDTLS_SHA1_H #include #include #if !defined(MBEDTLS_SHA1_ALT) // Regular implementation // #ifdef __cplusplus extern "C" { #endif /** * \brief SHA-1 context structure */ typedef struct { uint32_t total[2]; /*!< number of bytes processed */ uint32_t state[5]; /*!< intermediate digest state */ unsigned char buffer[64]; /*!< data block being processed */ } mbedtls_sha1_context; /** * \brief Initialize SHA-1 context * * \param ctx SHA-1 context to be initialized */ void mbedtls_sha1_init( mbedtls_sha1_context *ctx ); /** * \brief Clear SHA-1 context * * \param ctx SHA-1 context to be cleared */ void mbedtls_sha1_free( mbedtls_sha1_context *ctx ); /** * \brief Clone (the state of) a SHA-1 context * * \param dst The destination context * \param src The context to be cloned */ void mbedtls_sha1_clone( mbedtls_sha1_context *dst, const mbedtls_sha1_context *src ); /** * \brief SHA-1 context setup * * \param ctx context to be initialized */ void mbedtls_sha1_starts( mbedtls_sha1_context *ctx ); /** * \brief SHA-1 process buffer * * \param ctx SHA-1 context * \param input buffer holding the data * \param ilen length of the input data */ void mbedtls_sha1_update( mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen ); /** * \brief SHA-1 final digest * * \param ctx SHA-1 context * \param output SHA-1 checksum result */ void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, unsigned char output[20] ); /* Internal use */ void mbedtls_sha1_process( mbedtls_sha1_context *ctx, const unsigned char data[64] ); #ifdef __cplusplus } #endif #else /* MBEDTLS_SHA1_ALT */ #include "sha1_alt.h" #endif /* MBEDTLS_SHA1_ALT */ #ifdef __cplusplus extern "C" { #endif /** * \brief Output = SHA-1( input buffer ) * * \param input buffer holding the data * \param ilen length of the input data * \param output SHA-1 checksum result */ void mbedtls_sha1( const unsigned char *input, size_t ilen, unsigned char output[20] ); /** * \brief Checkup routine * * \return 0 if successful, or 1 if the test failed */ int mbedtls_sha1_self_test( int verbose ); #ifdef __cplusplus } #endif #endif /* mbedtls_sha1.h */ oor-1.2.0/oor/elibs/mbedtls/sha256.c000066400000000000000000000233711313612200500170130ustar00rootroot00000000000000/* * FIPS-180-2 compliant SHA-256 implementation * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * Copyright (C) 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is part of mbed TLS (https://tls.mbed.org) */ /* * The SHA-256 Secure Hash Standard was published by NIST in 2002. * * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf * * Original code by mbed TLS project. Modified by the LISPmob project. */ #include "sha256.h" #include #if !defined(MBEDTLS_SHA256_ALT) /* Implementation that should never be optimized out by the compiler */ static void mbedtls_zeroize( void *v, size_t n ) { volatile unsigned char *p = v; while( n-- ) *p++ = 0; } /* * 32-bit integer manipulation macros (big endian) */ #ifndef GET_UINT32_BE #define GET_UINT32_BE(n,b,i) \ do { \ (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ | ( (uint32_t) (b)[(i) + 1] << 16 ) \ | ( (uint32_t) (b)[(i) + 2] << 8 ) \ | ( (uint32_t) (b)[(i) + 3] ); \ } while( 0 ) #endif #ifndef PUT_UINT32_BE #define PUT_UINT32_BE(n,b,i) \ do { \ (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ (b)[(i) + 3] = (unsigned char) ( (n) ); \ } while( 0 ) #endif void mbedtls_sha256_init( mbedtls_sha256_context *ctx ) { memset( ctx, 0, sizeof( mbedtls_sha256_context ) ); } void mbedtls_sha256_free( mbedtls_sha256_context *ctx ) { if( ctx == NULL ) return; mbedtls_zeroize( ctx, sizeof( mbedtls_sha256_context ) ); } void mbedtls_sha256_clone( mbedtls_sha256_context *dst, const mbedtls_sha256_context *src ) { *dst = *src; } /* * SHA-256 context setup */ void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 ) { ctx->total[0] = 0; ctx->total[1] = 0; if( is224 == 0 ) { /* SHA-256 */ ctx->state[0] = 0x6A09E667; ctx->state[1] = 0xBB67AE85; ctx->state[2] = 0x3C6EF372; ctx->state[3] = 0xA54FF53A; ctx->state[4] = 0x510E527F; ctx->state[5] = 0x9B05688C; ctx->state[6] = 0x1F83D9AB; ctx->state[7] = 0x5BE0CD19; } else { /* SHA-224 */ ctx->state[0] = 0xC1059ED8; ctx->state[1] = 0x367CD507; ctx->state[2] = 0x3070DD17; ctx->state[3] = 0xF70E5939; ctx->state[4] = 0xFFC00B31; ctx->state[5] = 0x68581511; ctx->state[6] = 0x64F98FA7; ctx->state[7] = 0xBEFA4FA4; } ctx->is224 = is224; } #if !defined(MBEDTLS_SHA256_PROCESS_ALT) static const uint32_t K[] = { 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967, 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2, }; #define SHR(x,n) ((x & 0xFFFFFFFF) >> n) #define ROTR(x,n) (SHR(x,n) | (x << (32 - n))) #define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3)) #define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10)) #define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22)) #define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25)) #define F0(x,y,z) ((x & y) | (z & (x | y))) #define F1(x,y,z) (z ^ (x & (y ^ z))) #define R(t) \ ( \ W[t] = S1(W[t - 2]) + W[t - 7] + \ S0(W[t - 15]) + W[t - 16] \ ) #define P(a,b,c,d,e,f,g,h,x,K) \ { \ temp1 = h + S3(e) + F1(e,f,g) + K + x; \ temp2 = S2(a) + F0(a,b,c); \ d += temp1; h = temp1 + temp2; \ } void mbedtls_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[64] ) { uint32_t temp1, temp2, W[64]; uint32_t A[8]; unsigned int i; for( i = 0; i < 8; i++ ) A[i] = ctx->state[i]; #if defined(MBEDTLS_SHA256_SMALLER) for( i = 0; i < 64; i++ ) { if( i < 16 ) GET_UINT32_BE( W[i], data, 4 * i ); else R( i ); P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i], K[i] ); temp1 = A[7]; A[7] = A[6]; A[6] = A[5]; A[5] = A[4]; A[4] = A[3]; A[3] = A[2]; A[2] = A[1]; A[1] = A[0]; A[0] = temp1; } #else /* MBEDTLS_SHA256_SMALLER */ for( i = 0; i < 16; i++ ) GET_UINT32_BE( W[i], data, 4 * i ); for( i = 0; i < 16; i += 8 ) { P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i+0], K[i+0] ); P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], W[i+1], K[i+1] ); P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], W[i+2], K[i+2] ); P( A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], W[i+3], K[i+3] ); P( A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], W[i+4], K[i+4] ); P( A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], W[i+5], K[i+5] ); P( A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], W[i+6], K[i+6] ); P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], W[i+7], K[i+7] ); } for( i = 16; i < 64; i += 8 ) { P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], R(i+0), K[i+0] ); P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], R(i+1), K[i+1] ); P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], R(i+2), K[i+2] ); P( A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], R(i+3), K[i+3] ); P( A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], R(i+4), K[i+4] ); P( A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], R(i+5), K[i+5] ); P( A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], R(i+6), K[i+6] ); P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], R(i+7), K[i+7] ); } #endif /* MBEDTLS_SHA256_SMALLER */ for( i = 0; i < 8; i++ ) ctx->state[i] += A[i]; } #endif /* !MBEDTLS_SHA256_PROCESS_ALT */ /* * SHA-256 process buffer */ void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *input, size_t ilen ) { size_t fill; uint32_t left; if( ilen == 0 ) return; left = ctx->total[0] & 0x3F; fill = 64 - left; ctx->total[0] += (uint32_t) ilen; ctx->total[0] &= 0xFFFFFFFF; if( ctx->total[0] < (uint32_t) ilen ) ctx->total[1]++; if( left && ilen >= fill ) { memcpy( (void *) (ctx->buffer + left), input, fill ); mbedtls_sha256_process( ctx, ctx->buffer ); input += fill; ilen -= fill; left = 0; } while( ilen >= 64 ) { mbedtls_sha256_process( ctx, input ); input += 64; ilen -= 64; } if( ilen > 0 ) memcpy( (void *) (ctx->buffer + left), input, ilen ); } static const unsigned char sha256_padding[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* * SHA-256 final digest */ void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char output[32] ) { uint32_t last, padn; uint32_t high, low; unsigned char msglen[8]; high = ( ctx->total[0] >> 29 ) | ( ctx->total[1] << 3 ); low = ( ctx->total[0] << 3 ); PUT_UINT32_BE( high, msglen, 0 ); PUT_UINT32_BE( low, msglen, 4 ); last = ctx->total[0] & 0x3F; padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); mbedtls_sha256_update( ctx, sha256_padding, padn ); mbedtls_sha256_update( ctx, msglen, 8 ); PUT_UINT32_BE( ctx->state[0], output, 0 ); PUT_UINT32_BE( ctx->state[1], output, 4 ); PUT_UINT32_BE( ctx->state[2], output, 8 ); PUT_UINT32_BE( ctx->state[3], output, 12 ); PUT_UINT32_BE( ctx->state[4], output, 16 ); PUT_UINT32_BE( ctx->state[5], output, 20 ); PUT_UINT32_BE( ctx->state[6], output, 24 ); if( ctx->is224 == 0 ) PUT_UINT32_BE( ctx->state[7], output, 28 ); } #endif /* !MBEDTLS_SHA256_ALT */ /* * output = SHA-256( input buffer ) */ void mbedtls_sha256( const unsigned char *input, size_t ilen, unsigned char output[32], int is224 ) { mbedtls_sha256_context ctx; mbedtls_sha256_init( &ctx ); mbedtls_sha256_starts( &ctx, is224 ); mbedtls_sha256_update( &ctx, input, ilen ); mbedtls_sha256_finish( &ctx, output ); mbedtls_sha256_free( &ctx ); } oor-1.2.0/oor/elibs/mbedtls/sha256.h000066400000000000000000000072561313612200500170240ustar00rootroot00000000000000/** * \file mbedtls_sha256.h * * \brief SHA-224 and SHA-256 cryptographic hash function * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * Copyright (C) 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is part of mbed TLS (https://tls.mbed.org) * * Original code by mbed TLS project. Modified by the LISPmob project. */ #ifndef MBEDTLS_SHA256_H #define MBEDTLS_SHA256_H #include #include #if !defined(MBEDTLS_SHA256_ALT) // Regular implementation // #ifdef __cplusplus extern "C" { #endif /** * \brief SHA-256 context structure */ typedef struct { uint32_t total[2]; /*!< number of bytes processed */ uint32_t state[8]; /*!< intermediate digest state */ unsigned char buffer[64]; /*!< data block being processed */ int is224; /*!< 0 => SHA-256, else SHA-224 */ } mbedtls_sha256_context; /** * \brief Initialize SHA-256 context * * \param ctx SHA-256 context to be initialized */ void mbedtls_sha256_init( mbedtls_sha256_context *ctx ); /** * \brief Clear SHA-256 context * * \param ctx SHA-256 context to be cleared */ void mbedtls_sha256_free( mbedtls_sha256_context *ctx ); /** * \brief Clone (the state of) a SHA-256 context * * \param dst The destination context * \param src The context to be cloned */ void mbedtls_sha256_clone( mbedtls_sha256_context *dst, const mbedtls_sha256_context *src ); /** * \brief SHA-256 context setup * * \param ctx context to be initialized * \param is224 0 = use SHA256, 1 = use SHA224 */ void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 ); /** * \brief SHA-256 process buffer * * \param ctx SHA-256 context * \param input buffer holding the data * \param ilen length of the input data */ void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *input, size_t ilen ); /** * \brief SHA-256 final digest * * \param ctx SHA-256 context * \param output SHA-224/256 checksum result */ void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char output[32] ); /* Internal use */ void mbedtls_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[64] ); #ifdef __cplusplus } #endif #else /* MBEDTLS_SHA256_ALT */ #include "sha256_alt.h" #endif /* MBEDTLS_SHA256_ALT */ #ifdef __cplusplus extern "C" { #endif /** * \brief Output = SHA-256( input buffer ) * * \param input buffer holding the data * \param ilen length of the input data * \param output SHA-224/256 checksum result * \param is224 0 = use SHA256, 1 = use SHA224 */ void mbedtls_sha256( const unsigned char *input, size_t ilen, unsigned char output[32], int is224 ); /** * \brief Checkup routine * * \return 0 if successful, or 1 if the test failed */ int mbedtls_sha256_self_test( int verbose ); #ifdef __cplusplus } #endif #endif /* mbedtls_sha256.h */ oor-1.2.0/oor/elibs/ovs/000077500000000000000000000000001313612200500150065ustar00rootroot00000000000000oor-1.2.0/oor/elibs/ovs/list.h000066400000000000000000000230371313612200500161370ustar00rootroot00000000000000/* * Copyright (c) 2008, 2009, 2010, 2011, 2013, 2015 Nicira, Inc. * Copyright (C) 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Original code by the Open vSwitch project. Modified by the LISPmob project. */ #ifndef LIST_H #define LIST_H 1 /* Doubly linked list. */ #include #include #include #include "ovs_util.h" /* Doubly linked list head or element. */ struct ovs_list { struct ovs_list *prev; /* Previous list element. */ struct ovs_list *next; /* Next list element. */ }; /* "struct ovs_list" with pointers that will (probably) cause segfaults if * dereferenced and, better yet, show up clearly in a debugger. */ #define OVS_LIST_POISON \ (struct ovs_list) { (void *) (uintptr_t) 0xccccccccccccccccULL, \ (void *) (uintptr_t) 0xccccccccccccccccULL } static inline void list_init(struct ovs_list *); static inline void list_poison(struct ovs_list *); /* List insertion. */ static inline void list_insert(struct ovs_list *, struct ovs_list *); static inline void list_splice(struct ovs_list *before, struct ovs_list *first, struct ovs_list *last); static inline void list_push_front(struct ovs_list *, struct ovs_list *); static inline void list_push_back(struct ovs_list *, struct ovs_list *); static inline void list_replace(struct ovs_list *, const struct ovs_list *); static inline void list_moved(struct ovs_list *, const struct ovs_list *orig); static inline void list_move(struct ovs_list *dst, struct ovs_list *src); /* List removal. */ static inline struct ovs_list *list_remove(struct ovs_list *); static inline struct ovs_list *list_pop_front(struct ovs_list *); static inline struct ovs_list *list_pop_back(struct ovs_list *); /* List elements. */ static inline struct ovs_list *list_front(const struct ovs_list *); static inline struct ovs_list *list_back(const struct ovs_list *); /* List properties. */ static inline size_t list_size(const struct ovs_list *); static inline bool list_is_empty(const struct ovs_list *); static inline bool list_is_singleton(const struct ovs_list *); static inline bool list_is_short(const struct ovs_list *); #define LIST_FOR_EACH(ITER, MEMBER, LIST) \ for (INIT_CONTAINER(ITER, (LIST)->next, MEMBER); \ &(ITER)->MEMBER != (LIST); \ ASSIGN_CONTAINER(ITER, (ITER)->MEMBER.next, MEMBER)) #define LIST_FOR_EACH_CONTINUE(ITER, MEMBER, LIST) \ for (ASSIGN_CONTAINER(ITER, (ITER)->MEMBER.next, MEMBER); \ &(ITER)->MEMBER != (LIST); \ ASSIGN_CONTAINER(ITER, (ITER)->MEMBER.next, MEMBER)) #define LIST_FOR_EACH_REVERSE(ITER, MEMBER, LIST) \ for (INIT_CONTAINER(ITER, (LIST)->prev, MEMBER); \ &(ITER)->MEMBER != (LIST); \ ASSIGN_CONTAINER(ITER, (ITER)->MEMBER.prev, MEMBER)) #define LIST_FOR_EACH_REVERSE_CONTINUE(ITER, MEMBER, LIST) \ for (ASSIGN_CONTAINER(ITER, (ITER)->MEMBER.prev, MEMBER); \ &(ITER)->MEMBER != (LIST); \ ASSIGN_CONTAINER(ITER, (ITER)->MEMBER.prev, MEMBER)) #define LIST_FOR_EACH_SAFE(ITER, NEXT, MEMBER, LIST) \ for (INIT_CONTAINER(ITER, (LIST)->next, MEMBER); \ (&(ITER)->MEMBER != (LIST) \ ? INIT_CONTAINER(NEXT, (ITER)->MEMBER.next, MEMBER), 1 \ : 0); \ (ITER) = (NEXT)) #define LIST_FOR_EACH_POP(ITER, MEMBER, LIST) \ while (!list_is_empty(LIST) \ && (INIT_CONTAINER(ITER, list_pop_front(LIST), MEMBER), 1)) /* Inline implementations. */ /* Initializes 'list' as an empty list. */ static inline void list_init(struct ovs_list *list) { list->next = list->prev = list; } /* Initializes 'list' with pointers that will (probably) cause segfaults if * dereferenced and, better yet, show up clearly in a debugger. */ static inline void list_poison(struct ovs_list *list) { *list = OVS_LIST_POISON; } /* Inserts 'elem' just before 'before'. */ static inline void list_insert(struct ovs_list *before, struct ovs_list *elem) { elem->prev = before->prev; elem->next = before; before->prev->next = elem; before->prev = elem; } /* Removes elements 'first' though 'last' (exclusive) from their current list, then inserts them just before 'before'. */ static inline void list_splice(struct ovs_list *before, struct ovs_list *first, struct ovs_list *last) { if (first == last) { return; } last = last->prev; /* Cleanly remove 'first'...'last' from its current list. */ first->prev->next = last->next; last->next->prev = first->prev; /* Splice 'first'...'last' into new list. */ first->prev = before->prev; last->next = before; before->prev->next = first; before->prev = last; } /* Inserts 'elem' at the beginning of 'list', so that it becomes the front in 'list'. */ static inline void list_push_front(struct ovs_list *list, struct ovs_list *elem) { list_insert(list->next, elem); } /* Inserts 'elem' at the end of 'list', so that it becomes the back in * 'list'. */ static inline void list_push_back(struct ovs_list *list, struct ovs_list *elem) { list_insert(list, elem); } /* Puts 'elem' in the position currently occupied by 'position'. * Afterward, 'position' is not part of a list. */ static inline void list_replace(struct ovs_list *element, const struct ovs_list *position) { element->next = position->next; element->next->prev = element; element->prev = position->prev; element->prev->next = element; } /* Adjusts pointers around 'list' to compensate for 'list' having been moved * around in memory (e.g. as a consequence of realloc()), with original * location 'orig'. * * ('orig' likely points to freed memory, but this function does not * dereference 'orig', it only compares it to 'list'. In a very pedantic * language lawyer sense, this still yields undefined behavior, but it works * with actual compilers.) */ static inline void list_moved(struct ovs_list *list, const struct ovs_list *orig) { if (list->next == orig) { list_init(list); } else { list->prev->next = list->next->prev = list; } } /* Initializes 'dst' with the contents of 'src', compensating for moving it * around in memory. The effect is that, if 'src' was the head of a list, now * 'dst' is the head of a list containing the same elements. */ static inline void list_move(struct ovs_list *dst, struct ovs_list *src) { *dst = *src; list_moved(dst, src); } /* Removes 'elem' from its list and returns the element that followed it. Undefined behavior if 'elem' is not in a list. */ static inline struct ovs_list * list_remove(struct ovs_list *elem) { elem->prev->next = elem->next; elem->next->prev = elem->prev; return elem->next; } /* Removes the front element from 'list' and returns it. Undefined behavior if 'list' is empty before removal. */ static inline struct ovs_list * list_pop_front(struct ovs_list *list) { struct ovs_list *front = list->next; list_remove(front); return front; } /* Removes the back element from 'list' and returns it. Undefined behavior if 'list' is empty before removal. */ static inline struct ovs_list * list_pop_back(struct ovs_list *list) { struct ovs_list *back = list->prev; list_remove(back); return back; } /* Returns the front element in 'list_'. Undefined behavior if 'list_' is empty. */ static inline struct ovs_list * list_front(const struct ovs_list *list_) { struct ovs_list *list = CONST_CAST(struct ovs_list *, list_); assert(!list_is_empty(list)); return list->next; } /* Returns the back element in 'list_'. Undefined behavior if 'list_' is empty. */ static inline struct ovs_list * list_back(const struct ovs_list *list_) { struct ovs_list *list = CONST_CAST(struct ovs_list *, list_); assert(!list_is_empty(list)); return list->prev; } /* Returns the number of elements in 'list'. Runs in O(n) in the number of elements. */ static inline size_t list_size(const struct ovs_list *list) { const struct ovs_list *e; size_t cnt = 0; for (e = list->next; e != list; e = e->next) { cnt++; } return cnt; } /* Returns true if 'list' is empty, false otherwise. */ static inline bool list_is_empty(const struct ovs_list *list) { return list->next == list; } /* Returns true if 'list' has exactly 1 element, false otherwise. */ static inline bool list_is_singleton(const struct ovs_list *list) { return list_is_short(list) && !list_is_empty(list); } /* Returns true if 'list' has 0 or 1 elements, false otherwise. */ static inline bool list_is_short(const struct ovs_list *list) { return list->next == list->prev; } #endif /* list.h */ oor-1.2.0/oor/elibs/ovs/ovs_util.h000066400000000000000000000110041313612200500170170ustar00rootroot00000000000000/* * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 Nicira, Inc. * Copyright (C) 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Original code by the Open vSwitch project. Modified by the LISPmob project. */ #ifndef OVS_UTIL_H #define OVS_UTIL_H 1 #include #include #include #include #include #include #include #include #include #include /* Casts 'pointer' to 'type' and issues a compiler warning if the cast changes * anything other than an outermost "const" or "volatile" qualifier. * * The cast to int is present only to suppress an "expression using sizeof * bool" warning from "sparse" (see * http://permalink.gmane.org/gmane.comp.parsers.sparse/2967). */ /* XXX*/ #define CONST_CAST(TYPE, POINTER) \ ((void) sizeof ((int) ((POINTER) == (TYPE) (POINTER))), \ (TYPE) (POINTER)) #ifndef MIN #define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) #endif #ifndef MAX #define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) #endif #define OVS_NOT_REACHED() abort() /* Given a pointer-typed lvalue OBJECT, expands to a pointer type that may be * assigned to OBJECT. */ #ifdef __GNUC__ #define OVS_TYPEOF(OBJECT) typeof(OBJECT) #else #define OVS_TYPEOF(OBJECT) void * #endif /* Given OBJECT of type pointer-to-structure, expands to the offset of MEMBER * within an instance of the structure. * * The GCC-specific version avoids the technicality of undefined behavior if * OBJECT is null, invalid, or not yet initialized. This makes some static * checkers (like Coverity) happier. But the non-GCC version does not actually * dereference any pointer, so it would be surprising for it to cause any * problems in practice. */ /* XXX */ #ifdef __GNUC__ #define OBJECT_OFFSETOF(OBJECT, MEMBER) offsetof(typeof(*(OBJECT)), MEMBER) #else #define OBJECT_OFFSETOF(OBJECT, MEMBER) \ ((char *) &(OBJECT)->MEMBER - (char *) (OBJECT)) #endif /* Yields the size of MEMBER within STRUCT. */ #define MEMBER_SIZEOF(STRUCT, MEMBER) (sizeof(((STRUCT *) NULL)->MEMBER)) /* Given POINTER, the address of the given MEMBER in a STRUCT object, returns the STRUCT object. */ /* XXX */ #define CONTAINER_OF(POINTER, STRUCT, MEMBER) \ ((STRUCT *) (void *) ((char *) (POINTER) - offsetof (STRUCT, MEMBER))) /* Given POINTER, the address of the given MEMBER within an object of the type * that that OBJECT points to, returns OBJECT as an assignment-compatible * pointer type (either the correct pointer type or "void *"). OBJECT must be * an lvalue. * * This is the same as CONTAINER_OF except that it infers the structure type * from the type of '*OBJECT'. */ /* XXX */ #define OBJECT_CONTAINING(POINTER, OBJECT, MEMBER) \ ((OVS_TYPEOF(OBJECT)) (void *) \ ((char *) (POINTER) - OBJECT_OFFSETOF(OBJECT, MEMBER))) /* Given POINTER, the address of the given MEMBER within an object of the type * that that OBJECT points to, assigns the address of the outer object to * OBJECT, which must be an lvalue. * * Evaluates to (void) 0 as the result is not to be used. */ /* XXX */ #define ASSIGN_CONTAINER(OBJECT, POINTER, MEMBER) \ ((OBJECT) = OBJECT_CONTAINING(POINTER, OBJECT, MEMBER), (void) 0) /* As explained in the comment above OBJECT_OFFSETOF(), non-GNUC compilers * like MSVC will complain about un-initialized variables if OBJECT * hasn't already been initialized. To prevent such warnings, INIT_CONTAINER() * can be used as a wrapper around ASSIGN_CONTAINER. */ #define INIT_CONTAINER(OBJECT, POINTER, MEMBER) \ ((OBJECT) = NULL, ASSIGN_CONTAINER(OBJECT, POINTER, MEMBER)) /* Given ATTR, and TYPE, cast the ATTR to TYPE by first casting ATTR to * (void *). This is to suppress the alignment warning issued by clang. */ #define ALIGNED_CAST(TYPE, ATTR) ((TYPE) (void *) (ATTR)) #endif /* ovs_util.h */ oor-1.2.0/oor/elibs/patricia/000077500000000000000000000000001313612200500157735ustar00rootroot00000000000000oor-1.2.0/oor/elibs/patricia/patricia.c000066400000000000000000000574751313612200500177550ustar00rootroot00000000000000/* * $Id: patricia.c,v 1.7 2005/12/07 20:46:41 dplonka Exp $ * Dave Plonka * * This product includes software developed by the University of Michigan, * Merit Network, Inc., and their contributors. * * This file had been called "radix.c" in the MRT sources. * * I renamed it to "patricia.c" since it's not an implementation of a general * radix trie. Also I pulled in various requirements from "prefix.c" and * "demo.c" so that it could be used as a standalone API. * * * Bunch of mods from David Meyer (dmm613@gmail.com) to make * this deal with IPv6 in a more friendly fashion * * Original code by Dave Plonka. Modified by the LISPmob project. * */ #include /* assert */ #include /* isdigit */ #include /* errno */ #include /* sin */ #include /* NULL */ #include /* sprintf, fprintf, stderr */ #include /* free, atol, calloc */ #include /* memcpy, strchr, strlen */ #include /* BSD: for inet_addr */ #include /* BSD, Linux: for inet_addr */ #include #include /* BSD, Linux: for inet_addr */ #include /* BSD, Linux, Solaris: for inet_addr */ #include "patricia.h" #include "../../lib/mem_util.h" #define Delete free /* { from prefix.c */ /* prefix_tochar * convert prefix information to bytes */ u_char *prefix_tochar (prefix_t * prefix) { if (prefix == NULL) return (NULL); return ((u_char *) & prefix->add.sin); } int comp_with_mask (void *addr, void *dest, u_int mask) { if ( /* mask/8 == 0 || */ memcmp (addr, dest, mask / 8) == 0) { int n = mask / 8; int m = ((-1) << (8 - (mask % 8))); if (mask % 8 == 0 || (((u_char *)addr)[n] & m) == (((u_char *)dest)[n] & m)) return (1); } return (0); } /* this allows imcomplete prefix */ int my_inet_pton (int af, const char *src, void *dst) { if (af == AF_INET) { int i, c, val; u_char xp[sizeof(struct in_addr)] = {0, 0, 0, 0}; for (i = 0; ; i++) { c = *src++; if (!isdigit (c)) return (-1); val = 0; do { val = val * 10 + c - '0'; if (val > 255) return (0); c = *src++; } while (c && isdigit (c)); xp[i] = val; if (c == '\0') break; if (c != '.') return (0); if (i >= 3) return (0); } memcpy (dst, xp, sizeof(struct in_addr)); return (1); } else if (af == AF_INET6) { return (inet_pton (af, src, dst)); } else { return -1; } } #define PATRICIA_MAX_THREADS 16 /* * convert prefix information to ascii string with length * thread safe and (almost) re-entrant implementation */ char *prefix_toa2x (prefix_t *prefix, char *buff, int with_len) { if (prefix == NULL) return ("(Null)"); assert (prefix->ref_count >= 0); if (buff == NULL) { struct buffer { char buffs[PATRICIA_MAX_THREADS][48+5]; u_int i; } *buffp; # if 0 THREAD_SPECIFIC_DATA (struct buffer, buffp, 1); # else { /* for scope only */ static struct buffer local_buff; buffp = &local_buff; } # endif if (buffp == NULL) { /* XXX should we report an error? */ return (NULL); } buff = buffp->buffs[buffp->i++%PATRICIA_MAX_THREADS]; } if (prefix->family == AF_INET) { u_char *a; assert (prefix->bitlen <= sizeof(struct in_addr) * 8); a = prefix_touchar (prefix); if (with_len) { sprintf (buff, "%d.%d.%d.%d/%d", a[0], a[1], a[2], a[3], prefix->bitlen); } else { sprintf (buff, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]); } return (buff); } else if (prefix->family == AF_INET6) { char *r; r = (char *) inet_ntop (AF_INET6, &(prefix->add.sin6), buff, 48 /* a guess value */ ); if (r && with_len) { assert (prefix->bitlen <= sizeof(struct in6_addr) * 8); sprintf (buff + strlen (buff), "/%d", prefix->bitlen); } return (buff); } else return (NULL); } /* prefix_toa2 * convert prefix information to ascii string */ char *prefix_toa2 (prefix_t *prefix, char *buff) { return (prefix_toa2x (prefix, buff, 0)); } /* prefix_toa */ char *prefix_toa (prefix_t * prefix) { return (prefix_toa2 (prefix, (char *) NULL)); } prefix_t *New_Prefix2 (int family, void *dest, int bitlen, prefix_t *prefix) { int dynamic_allocated = 0; int default_bitlen = 0; if (prefix == NULL) { /* prefix = calloc(1, sizeof (prefix_t)); */ if ((prefix = (prefix_t *) xmalloc(sizeof(prefix_t))) == NULL) { syslog(LOG_DAEMON, "New_Prefix2: can't allocate new prefix"); return(0); } memset(prefix, 0, sizeof (prefix_t)); dynamic_allocated++; } switch(family) { case AF_INET: default_bitlen = sizeof(struct in_addr) * 8; memcpy (&prefix->add.sin, dest, sizeof(struct in_addr)); break; case AF_INET6: default_bitlen = sizeof(struct in6_addr) * 8; memcpy (&prefix->add.sin6, dest, sizeof(struct in6_addr)); break; default: free(prefix); return (NULL); } prefix->bitlen = (bitlen >= 0)? bitlen: default_bitlen; prefix->family = family; prefix->ref_count = 0; if (dynamic_allocated) { prefix->ref_count++; } return (prefix); } prefix_t *New_Prefix (int family, void *dest, int bitlen) { return (New_Prefix2 (family, dest, bitlen, NULL)); } /* ascii2prefix */ prefix_t * ascii2prefix (int family, char *string) { u_long bitlen = 0; u_long maxbitlen = 0; char *cp = NULL; int result = 0; struct in_addr sin; struct in6_addr sin6; char save[MAXLINE]; if (!string) return (NULL); switch(family) { /* set up maxbitlen */ case AF_INET: maxbitlen = sizeof(struct in_addr) * 8; break; case AF_INET6: maxbitlen = sizeof(struct in6_addr) * 8; break; default: fprintf(stderr, "unknown AFI (%d)\n", family); return(0); } if ((cp = strchr (string, '/')) != NULL) { bitlen = atol (cp + 1); /* *cp = '\0'; */ /* copy the string to save. Avoid destroying the string */ assert (cp - string < MAXLINE); memcpy (save, string, cp - string); save[cp - string] = '\0'; string = save; if (bitlen > maxbitlen) bitlen = maxbitlen; } else { bitlen = maxbitlen; } /* * now do the conversion */ switch(family) { case AF_INET: if ((result = my_inet_pton (AF_INET, string, &sin)) <= 0) return (NULL); return (New_Prefix (AF_INET, &sin, bitlen)); case AF_INET6: if ((result = inet_pton (AF_INET6, string, &sin6)) <= 0) return (NULL); return (New_Prefix (AF_INET6, &sin6, bitlen)); default: return (NULL); } } prefix_t *Ref_Prefix (prefix_t * prefix) { if (prefix == NULL) return (NULL); if (prefix->ref_count == 0) { /* make a copy in case of a static prefix */ return (New_Prefix2 (prefix->family, &prefix->add, prefix->bitlen, NULL)); } prefix->ref_count++; /* fprintf(stderr, "[A %s, %d]\n", prefix_toa (prefix), prefix->ref_count); */ return (prefix); } void Deref_Prefix (prefix_t * prefix) { if (prefix == NULL) return; /* for secure programming, raise an assert. no static prefix can call this */ assert (prefix->ref_count > 0); prefix->ref_count--; assert (prefix->ref_count >= 0); if (prefix->ref_count <= 0) { Delete (prefix); return; } } /* } */ /* #define PATRICIA_DEBUG 1 */ static int num_active_patricia = 0; /* these routines support continuous mask only */ patricia_tree_t * New_Patricia (int maxbits) { patricia_tree_t *patricia = xcalloc(1, sizeof *patricia); patricia->maxbits = maxbits; patricia->head = NULL; patricia->num_active_node = 0; assert (maxbits <= PATRICIA_MAXBITS); /* XXX */ num_active_patricia++; return (patricia); } /* * if func is supplied, it will be called as func(node->data) * before deleting the node */ void Clear_Patricia(patricia_tree_t *patricia, void_fn_t func) { assert(patricia); if (patricia->head) { patricia_node_t *Xstack[PATRICIA_MAXBITS + 1]; patricia_node_t **Xsp = Xstack; patricia_node_t *Xrn = patricia->head; while (Xrn) { patricia_node_t *l = Xrn->l; patricia_node_t *r = Xrn->r; if (Xrn->prefix) { Deref_Prefix(Xrn->prefix); if (Xrn->data && func) func(Xrn->data); } else { assert(Xrn->data == NULL); } Delete(Xrn); patricia->num_active_node--; if (l) { if (r) { *Xsp++ = r; } Xrn = l; } else if (r) { Xrn = r; } else if (Xsp != Xstack) { Xrn = *(--Xsp); } else { Xrn = NULL; } } } assert(patricia->num_active_node == 0); /* Delete (patricia); */ } void Destroy_Patricia (patricia_tree_t *patricia, void_fn_t func) { Clear_Patricia (patricia, func); Delete (patricia); num_active_patricia--; } /* * if func is supplied, it will be called as func(node->prefix, node->data) */ void patricia_process (patricia_tree_t *patricia, void_fn_t func) { patricia_node_t *node; assert (func); PATRICIA_WALK (patricia->head, node) { func (node->prefix, node->data); } PATRICIA_WALK_END; } size_t patricia_walk_inorder(patricia_node_t *node, void_fn_t func) { size_t n = 0; assert(func); if (node->l) { n += patricia_walk_inorder(node->l, func); } if (node->prefix) { func(node->prefix, node->data); n++; } if (node->r) { n += patricia_walk_inorder(node->r, func); } return n; } patricia_node_t * patricia_search_exact (patricia_tree_t *patricia, prefix_t *prefix) { patricia_node_t *node; u_char *addr; u_int bitlen; assert (patricia); assert (prefix); assert (prefix->bitlen <= patricia->maxbits);; if (patricia->head == NULL) return (NULL); node = patricia->head; addr = prefix_touchar (prefix); bitlen = prefix->bitlen; while (node->bit < bitlen) { if (BIT_TEST (addr[node->bit >> 3], 0x80 >> (node->bit & 0x07))) { #ifdef PATRICIA_DEBUG if (node->prefix) fprintf (stderr, "patricia_search_exact: take right %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); else fprintf (stderr, "patricia_search_exact: take right at %u\n", node->bit); #endif /* PATRICIA_DEBUG */ node = node->r; } else { #ifdef PATRICIA_DEBUG if (node->prefix) fprintf (stderr, "patricia_search_exact: take left %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); else fprintf (stderr, "patricia_search_exact: take left at %u\n", node->bit); #endif /* PATRICIA_DEBUG */ node = node->l; } if (node == NULL) return (NULL); } #ifdef PATRICIA_DEBUG if (node->prefix) fprintf (stderr, "patricia_search_exact: stop at %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); else fprintf (stderr, "patricia_search_exact: stop at %u\n", node->bit); #endif /* PATRICIA_DEBUG */ if (node->bit > bitlen || node->prefix == NULL) return (NULL); assert (node->bit == bitlen); assert (node->bit == node->prefix->bitlen); if (comp_with_mask (prefix_tochar (node->prefix), prefix_tochar (prefix), bitlen)) { #ifdef PATRICIA_DEBUG fprintf (stderr, "patricia_search_exact: found %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); #endif /* PATRICIA_DEBUG */ return (node); } return (NULL); } /* if inclusive != 0, "best" may be the given prefix itself */ patricia_node_t * patricia_search_best2 (patricia_tree_t *patricia, prefix_t *prefix, int inclusive) { patricia_node_t *node; patricia_node_t *stack[PATRICIA_MAXBITS + 1]; u_char *addr; u_int bitlen; int cnt = 0; assert (patricia); assert (prefix); assert (prefix->bitlen <= patricia->maxbits); if (patricia->head == NULL) return (NULL); node = patricia->head; addr = prefix_touchar (prefix); bitlen = prefix->bitlen; while (node->bit < bitlen) { if (node->prefix) { #ifdef PATRICIA_DEBUG fprintf (stderr, "patricia_search_best: push %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); #endif /* PATRICIA_DEBUG */ stack[cnt++] = node; } if (BIT_TEST (addr[node->bit >> 3], 0x80 >> (node->bit & 0x07))) { #ifdef PATRICIA_DEBUG if (node->prefix) fprintf (stderr, "patricia_search_best: take right %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); else fprintf (stderr, "patricia_search_best: take right at %u\n", node->bit); #endif /* PATRICIA_DEBUG */ node = node->r; } else { #ifdef PATRICIA_DEBUG if (node->prefix) fprintf (stderr, "patricia_search_best: take left %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); else fprintf (stderr, "patricia_search_best: take left at %u\n", node->bit); #endif /* PATRICIA_DEBUG */ node = node->l; } if (node == NULL) break; } if (inclusive && node && node->prefix) stack[cnt++] = node; #ifdef PATRICIA_DEBUG if (node == NULL) fprintf (stderr, "patricia_search_best: stop at null\n"); else if (node->prefix) fprintf (stderr, "patricia_search_best: stop at %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); else fprintf (stderr, "patricia_search_best: stop at %u\n", node->bit); #endif /* PATRICIA_DEBUG */ if (cnt <= 0) return (NULL); while (--cnt >= 0) { node = stack[cnt]; #ifdef PATRICIA_DEBUG fprintf (stderr, "patricia_search_best: pop %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); #endif /* PATRICIA_DEBUG */ if (comp_with_mask (prefix_tochar (node->prefix), prefix_tochar (prefix), node->prefix->bitlen) && node->prefix->bitlen <= bitlen) { #ifdef PATRICIA_DEBUG fprintf (stderr, "patricia_search_best: found %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); #endif /* PATRICIA_DEBUG */ return (node); } } return (NULL); } patricia_node_t * patricia_search_best (patricia_tree_t *patricia, prefix_t *prefix) { return (patricia_search_best2 (patricia, prefix, 1)); } patricia_node_t * patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix) { patricia_node_t *node, *new_node, *parent, *glue; u_char *addr, *test_addr; u_int bitlen, check_bit, differ_bit; int i, j, r; assert (patricia); assert (prefix); assert (prefix->bitlen <= patricia->maxbits); if (patricia->head == NULL) { node = xcalloc(1, sizeof *node); node->bit = prefix->bitlen; node->prefix = Ref_Prefix (prefix); node->parent = NULL; node->l = node->r = NULL; node->data = NULL; patricia->head = node; #ifdef PATRICIA_DEBUG fprintf (stderr, "patricia_lookup: new_node #0 %s/%d (head)\n", prefix_toa (prefix), prefix->bitlen); #endif /* PATRICIA_DEBUG */ patricia->num_active_node++; return (node); } addr = prefix_touchar (prefix); bitlen = prefix->bitlen; node = patricia->head; while (node->bit < bitlen || node->prefix == NULL) { if (node->bit < patricia->maxbits && BIT_TEST (addr[node->bit >> 3], 0x80 >> (node->bit & 0x07))) { if (node->r == NULL) break; #ifdef PATRICIA_DEBUG if (node->prefix) fprintf (stderr, "patricia_lookup: take right %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); else fprintf (stderr, "patricia_lookup: take right at %u\n", node->bit); #endif /* PATRICIA_DEBUG */ node = node->r; } else { if (node->l == NULL) break; #ifdef PATRICIA_DEBUG if (node->prefix) fprintf (stderr, "patricia_lookup: take left %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); else fprintf (stderr, "patricia_lookup: take left at %u\n", node->bit); #endif /* PATRICIA_DEBUG */ node = node->l; } assert (node); } assert (node->prefix); #ifdef PATRICIA_DEBUG fprintf (stderr, "patricia_lookup: stop at %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); #endif /* PATRICIA_DEBUG */ test_addr = prefix_touchar (node->prefix); /* find the first bit different */ check_bit = (node->bit < bitlen)? node->bit: bitlen; differ_bit = 0; for (i = 0; i*8 < check_bit; i++) { if ((r = (addr[i] ^ test_addr[i])) == 0) { differ_bit = (i + 1) * 8; continue; } /* I know the better way, but for now */ for (j = 0; j < 8; j++) { if (BIT_TEST (r, (0x80 >> j))) break; } /* must be found */ assert (j < 8); differ_bit = i * 8 + j; break; } if (differ_bit > check_bit) differ_bit = check_bit; #ifdef PATRICIA_DEBUG fprintf (stderr, "patricia_lookup: differ_bit %d\n", differ_bit); #endif /* PATRICIA_DEBUG */ parent = node->parent; while (parent && parent->bit >= differ_bit) { node = parent; parent = node->parent; #ifdef PATRICIA_DEBUG if (node->prefix) fprintf (stderr, "patricia_lookup: up to %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); else fprintf (stderr, "patricia_lookup: up to %u\n", node->bit); #endif /* PATRICIA_DEBUG */ } if (differ_bit == bitlen && node->bit == bitlen) { if (node->prefix) { #ifdef PATRICIA_DEBUG fprintf (stderr, "patricia_lookup: found %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); #endif /* PATRICIA_DEBUG */ return (node); } node->prefix = Ref_Prefix (prefix); #ifdef PATRICIA_DEBUG fprintf (stderr, "patricia_lookup: new node #1 %s/%d (glue mod)\n", prefix_toa (prefix), prefix->bitlen); #endif /* PATRICIA_DEBUG */ assert (node->data == NULL); return (node); } new_node = xcalloc(1, sizeof *new_node); new_node->bit = prefix->bitlen; new_node->prefix = Ref_Prefix (prefix); new_node->parent = NULL; new_node->l = new_node->r = NULL; new_node->data = NULL; patricia->num_active_node++; if (node->bit == differ_bit) { new_node->parent = node; if (node->bit < patricia->maxbits && BIT_TEST (addr[node->bit >> 3], 0x80 >> (node->bit & 0x07))) { assert (node->r == NULL); node->r = new_node; } else { assert (node->l == NULL); node->l = new_node; } #ifdef PATRICIA_DEBUG fprintf (stderr, "patricia_lookup: new_node #2 %s/%d (child)\n", prefix_toa (prefix), prefix->bitlen); #endif /* PATRICIA_DEBUG */ return (new_node); } if (bitlen == differ_bit) { if (bitlen < patricia->maxbits && BIT_TEST (test_addr[bitlen >> 3], 0x80 >> (bitlen & 0x07))) { new_node->r = node; } else { new_node->l = node; } new_node->parent = node->parent; if (node->parent == NULL) { assert (patricia->head == node); patricia->head = new_node; } else if (node->parent->r == node) { node->parent->r = new_node; } else { node->parent->l = new_node; } node->parent = new_node; #ifdef PATRICIA_DEBUG fprintf (stderr, "patricia_lookup: new_node #3 %s/%d (parent)\n", prefix_toa (prefix), prefix->bitlen); #endif /* PATRICIA_DEBUG */ } else { glue = xcalloc(1, sizeof *glue); glue->bit = differ_bit; glue->prefix = NULL; glue->parent = node->parent; glue->data = NULL; patricia->num_active_node++; if (differ_bit < patricia->maxbits && BIT_TEST (addr[differ_bit >> 3], 0x80 >> (differ_bit & 0x07))) { glue->r = new_node; glue->l = node; } else { glue->r = node; glue->l = new_node; } new_node->parent = glue; if (node->parent == NULL) { assert (patricia->head == node); patricia->head = glue; } else if (node->parent->r == node) { node->parent->r = glue; } else { node->parent->l = glue; } node->parent = glue; #ifdef PATRICIA_DEBUG fprintf (stderr, "patricia_lookup: new_node #4 %s/%d (glue+node)\n", prefix_toa (prefix), prefix->bitlen); #endif /* PATRICIA_DEBUG */ } return (new_node); } void patricia_remove (patricia_tree_t *patricia, patricia_node_t *node) { patricia_node_t *parent, *child; assert (patricia); assert (node); if (node->r && node->l) { #ifdef PATRICIA_DEBUG fprintf (stderr, "patricia_remove: #0 %s/%d (r & l)\n", prefix_toa (node->prefix), node->prefix->bitlen); #endif /* PATRICIA_DEBUG */ /* this might be a placeholder node -- have to check and make sure * there is a prefix aossciated with it ! */ if (node->prefix != NULL) Deref_Prefix (node->prefix); node->prefix = NULL; /* Also I needed to clear data pointer -- masaki */ node->data = NULL; return; } if (node->r == NULL && node->l == NULL) { #ifdef PATRICIA_DEBUG fprintf (stderr, "patricia_remove: #1 %s/%d (!r & !l)\n", prefix_toa (node->prefix), node->prefix->bitlen); #endif /* PATRICIA_DEBUG */ parent = node->parent; Deref_Prefix (node->prefix); Delete (node); patricia->num_active_node--; if (parent == NULL) { assert (patricia->head == node); patricia->head = NULL; return; } if (parent->r == node) { parent->r = NULL; child = parent->l; } else { assert (parent->l == node); parent->l = NULL; child = parent->r; } if (parent->prefix) return; /* we need to remove parent too */ if (parent->parent == NULL) { assert (patricia->head == parent); patricia->head = child; } else if (parent->parent->r == parent) { parent->parent->r = child; } else { assert (parent->parent->l == parent); parent->parent->l = child; } child->parent = parent->parent; Delete (parent); patricia->num_active_node--; return; } #ifdef PATRICIA_DEBUG fprintf (stderr, "patricia_remove: #2 %s/%d (r ^ l)\n", prefix_toa (node->prefix), node->prefix->bitlen); #endif /* PATRICIA_DEBUG */ if (node->r) { child = node->r; } else { assert (node->l); child = node->l; } parent = node->parent; child->parent = parent; Deref_Prefix (node->prefix); Delete (node); patricia->num_active_node--; if (parent == NULL) { assert (patricia->head == node); patricia->head = child; return; } if (parent->r == node) { parent->r = child; } else { assert (parent->l == node); parent->l = child; } } patricia_node_t * make_and_lookup (patricia_tree_t *tree, int afi, char *string) { prefix_t *prefix; patricia_node_t *node; prefix = ascii2prefix (afi, string); #if (DEBUG > 3) printf ("make_and_lookup: %s/%d\n", prefix_toa (prefix), prefix->bitlen); #endif node = patricia_lookup (tree, prefix); Deref_Prefix (prefix); return (node); } patricia_node_t * try_search_exact (patricia_tree_t *tree, int afi, char *string) { prefix_t *prefix; patricia_node_t *node; prefix = ascii2prefix (afi, string); node = patricia_search_exact (tree, prefix); #ifdef DEBUG if (node) printf ("try_search_exact: %s/%d found\n", prefix_toa (node->prefix), node->prefix->bitlen); else printf ("try_search_exact: not found\n"); #endif Deref_Prefix (prefix); return (node); } void lookup_then_remove (patricia_tree_t *tree, int afi, char *string) { patricia_node_t *node; if ((node = try_search_exact (tree, afi, string)) != NULL) patricia_remove (tree, node); } patricia_node_t * try_search_best (patricia_tree_t *tree, int afi, char *string) { prefix_t *prefix; patricia_node_t *node; prefix = ascii2prefix (afi, string); printf ("try_search_best: %s/%d\n", prefix_toa (prefix), prefix->bitlen); if ((node = patricia_search_best (tree, prefix)) == NULL) printf ("try_search_best: not found\n"); else printf ("try_search_best: %s/%d found\n", prefix_toa (node->prefix), node->prefix->bitlen); Deref_Prefix (prefix); return (node); /* was return(prefix) ...why? */ } /* } */ oor-1.2.0/oor/elibs/patricia/patricia.h000066400000000000000000000110611313612200500177370ustar00rootroot00000000000000/* * $Id: patricia.h,v 1.6 2005/12/07 20:53:01 dplonka Exp $ * Dave Plonka * * This product includes software developed by the University of Michigan, * Merit Network, Inc., and their contributors. * * This file had been called "radix.h" in the MRT sources. * * I renamed it to "patricia.h" since it's not an implementation of a general * radix trie. Also, pulled in various requirements from "mrt.h" and added * some other things it could be used as a standalone API. * * Original code by Dave Plonka. Modified by the LISPmob project. */ #ifndef _PATRICIA_H #define _PATRICIA_H #define HAVE_IPV6 /* typedef unsigned int u_int; */ typedef void (*void_fn_t)(); /* { from defs.h */ #define prefix_touchar(prefix) ((u_char *)&(prefix)->add.sin) #define MAXLINE 1024 #define BIT_TEST(f, b) ((f) & (b)) /* } */ #define addroute make_and_lookup #include /* for u_* definitions (on FreeBSD 5) */ #include /* for EAFNOSUPPORT */ #ifndef EAFNOSUPPORT # defined EAFNOSUPPORT WSAEAFNOSUPPORT # include #else # include /* for struct in_addr */ #endif #include /* for AF_INET */ /* { from mrt.h */ typedef struct _prefix4_t { u_short family; /* AF_INET | AF_INET6 */ u_short bitlen; /* same as mask? */ int ref_count; /* reference count */ struct in_addr sin; } prefix4_t; typedef struct _prefix_t { u_short family; /* AF_INET | AF_INET6 */ u_short bitlen; /* same as mask? */ int ref_count; /* reference count */ union { struct in_addr sin; struct in6_addr sin6; } add; } prefix_t; /* } */ typedef struct _patricia_node_t { u_int bit; /* flag if this node used */ prefix_t *prefix; /* who we are in patricia tree */ struct _patricia_node_t *l, *r; /* left and right children */ struct _patricia_node_t *parent;/* may be used */ void *data; /* pointer to data */ void *user1; /* pointer to usr data (ex. route flap info) */ } patricia_node_t; typedef struct _patricia_tree_t { patricia_node_t *head; u_int maxbits; /* for IP, 32 bit addresses */ int num_active_node; /* for debug purpose */ } patricia_tree_t; patricia_node_t *patricia_search_exact (patricia_tree_t *patricia, prefix_t *prefix); patricia_node_t *patricia_search_best (patricia_tree_t *patricia, prefix_t *prefix); patricia_node_t * patricia_search_best2 (patricia_tree_t *patricia, prefix_t *prefix, int inclusive); patricia_node_t *patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix); void patricia_remove (patricia_tree_t *patricia, patricia_node_t *node); patricia_tree_t *New_Patricia (int maxbits); void Clear_Patricia (patricia_tree_t *patricia, void_fn_t func); void Destroy_Patricia (patricia_tree_t *patricia, void_fn_t func); void patricia_process (patricia_tree_t *patricia, void_fn_t func); prefix_t *New_Prefix(int family, void *dest, int bitlen); void Deref_Prefix (prefix_t * prefix); /* { from demo.c */ prefix_t * ascii2prefix (int family, char *string); patricia_node_t * make_and_lookup (patricia_tree_t *tree, int afi, char *string); /* } */ #define PATRICIA_MAXBITS (sizeof(struct in6_addr) * 8) #define PATRICIA_NBIT(x) (0x80 >> ((x) & 0x7f)) #define PATRICIA_NBYTE(x) ((x) >> 3) #define PATRICIA_DATA_GET(node, type) (type *)((node)->data) #define PATRICIA_DATA_SET(node, value) ((node)->data = (void *)(value)) #define PATRICIA_WALK(Xhead, Xnode) \ do { \ patricia_node_t *Xstack[PATRICIA_MAXBITS+1]; \ patricia_node_t **Xsp = Xstack; \ patricia_node_t *Xrn = (Xhead); \ while ((Xnode = Xrn)) { \ if (Xnode->prefix) #define PATRICIA_WALK_ALL(Xhead, Xnode) \ do { \ patricia_node_t *Xstack[PATRICIA_MAXBITS+1]; \ patricia_node_t **Xsp = Xstack; \ patricia_node_t *Xrn = (Xhead); \ while ((Xnode = Xrn)) { \ if (1) #define PATRICIA_WALK_BREAK { \ if (Xsp != Xstack) { \ Xrn = *(--Xsp); \ } else { \ Xrn = (patricia_node_t *) 0; \ } \ continue; } #define PATRICIA_WALK_END \ if (Xrn->l) { \ if (Xrn->r) { \ *Xsp++ = Xrn->r; \ } \ Xrn = Xrn->l; \ } else if (Xrn->r) { \ Xrn = Xrn->r; \ } else if (Xsp != Xstack) { \ Xrn = *(--Xsp); \ } else { \ Xrn = (patricia_node_t *) 0; \ } \ } \ } while (0) /* prefix_toa */ char *prefix_toa (prefix_t * prefix); /* Defined to avoid implicit function warnings */ #endif /* _PATRICIA_H */ oor-1.2.0/oor/fwd_policies/000077500000000000000000000000001313612200500155505ustar00rootroot00000000000000oor-1.2.0/oor/fwd_policies/balancing_locators.c000066400000000000000000000306501313612200500215440ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "balancing_locators.h" #include "fwd_addr_func.h" #include "fwd_utils.h" #include "../lib/oor_log.h" static void balancing_locators_vecs_reset(balancing_locators_vecs *blv); static int select_best_priority_locators(glist_t *loct_list, locator_t **selected_locators, uint8_t is_mce); static locator_t **set_balancing_vector(locator_t **locators, int total_weight, int hcf, int *locators_vec_length); static inline void get_hcf_locators_weight(locator_t **locators, int *total_weight,int *hcf); static int highest_common_factor(int a, int b); static inline balancing_locators_vecs * balancing_locators_vecs_new() { balancing_locators_vecs * bal_loct_vec; bal_loct_vec = (balancing_locators_vecs *)xzalloc(sizeof(balancing_locators_vecs)); if (bal_loct_vec == NULL){ OOR_LOG(LWRN, "balancing_locators_vecs_new: Couldn't allocate memory for balancing_locators_vecs"); } return (bal_loct_vec); } void * balancing_locators_vecs_new_init(mapping_t *map, glist_t *loc_loct, uint8_t is_mce) { balancing_locators_vecs *bal_vec; bal_vec = balancing_locators_vecs_new(); if (!bal_vec){ return (NULL); } if (balancing_vectors_calculate(bal_vec, map, loc_loct, is_mce) != GOOD){ balancing_locators_vecs_del(bal_vec); OOR_LOG(LDBG_2,"balancing_locators_vecs_new_init: Error calculating balancing vectors"); return (NULL); } return((void *)bal_vec); } void balancing_locators_vecs_del(void * bal_vec) { balancing_locators_vecs_reset((balancing_locators_vecs *)bal_vec); free((balancing_locators_vecs *)bal_vec); } /* Print balancing locators vector information */ void balancing_locators_vec_dump(balancing_locators_vecs b_locators_vecs, mapping_t *mapping, int log_level) { int ctr; char str[3000]; if (is_loggable(log_level)) { OOR_LOG(log_level, "Balancing locator vector for %s: ", lisp_addr_to_char(mapping_eid(mapping))); sprintf(str, " IPv4 locators vector (%d locators): ", b_locators_vecs.v4_locators_vec_length); for (ctr = 0; ctr < b_locators_vecs.v4_locators_vec_length; ctr++) { if (strlen(str) > 2850) { sprintf(str + strlen(str), " ..."); break; } sprintf(str + strlen(str), " %s ", lisp_addr_to_char( b_locators_vecs.v4_balancing_locators_vec[ctr]->addr)); } OOR_LOG(log_level, "%s", str); sprintf(str, " IPv6 locators vector (%d locators): ", b_locators_vecs.v6_locators_vec_length); for (ctr = 0; ctr < b_locators_vecs.v6_locators_vec_length; ctr++) { if (strlen(str) > 2900) { sprintf(str + strlen(str), " ..."); break; } sprintf(str + strlen(str), " %s ", lisp_addr_to_char( b_locators_vecs.v6_balancing_locators_vec[ctr]->addr)); } OOR_LOG(log_level, "%s", str); sprintf(str, " IPv4 & IPv6 locators vector (%d locators): ", b_locators_vecs.locators_vec_length); for (ctr = 0; ctr < b_locators_vecs.locators_vec_length; ctr++) { if (strlen(str) > 2950) { sprintf(str + strlen(str), " ..."); break; } sprintf(str + strlen(str), " %s ", lisp_addr_to_char( b_locators_vecs.balancing_locators_vec[ctr]->addr)); } OOR_LOG(log_level, "%s", str); } } /* * Calculate the vectors used to distribute the load from the priority and weight of the locators of the mapping */ int balancing_vectors_calculate(balancing_locators_vecs *blv, mapping_t * map, glist_t *loc_loct, uint8_t is_mce) { // Store locators with same priority. Maximum 32 locators (33 to no get out of array) locator_t *locators[3][33]; // Aux list to classify all locators between IP4 and IPv6 glist_t *ipv4_loct_list = glist_new(); glist_t *ipv6_loct_list = glist_new(); int min_priority[2] = { 255, 255 }; int total_weight[3] = { 0, 0, 0 }; int hcf[3] = { 0, 0, 0 }; int ctr = 0; int ctr1 = 0; int pos = 0; locators[0][0] = NULL; locators[1][0] = NULL; balancing_locators_vecs_reset(blv); locators_classify_in_4_6(map,loc_loct,ipv4_loct_list,ipv6_loct_list, laddr_get_fwd_ip_addr); /* Fill the locator balancing vec using only IPv4 locators and according * to their priority and weight */ if (glist_size(ipv4_loct_list) != 0) { min_priority[0] = select_best_priority_locators( ipv4_loct_list, locators[0], is_mce); if (min_priority[0] != UNUSED_RLOC_PRIORITY) { get_hcf_locators_weight(locators[0], &total_weight[0], &hcf[0]); blv->v4_balancing_locators_vec = set_balancing_vector( locators[0], total_weight[0], hcf[0], &(blv->v4_locators_vec_length)); } } /* Fill the locator balancing vec using only IPv6 locators and according * to their priority and weight*/ if (glist_size(ipv6_loct_list) != 0) { min_priority[1] = select_best_priority_locators( ipv6_loct_list, locators[1], is_mce); if (min_priority[1] != UNUSED_RLOC_PRIORITY) { get_hcf_locators_weight(locators[1], &total_weight[1], &hcf[1]); blv->v6_balancing_locators_vec = set_balancing_vector( locators[1], total_weight[1], hcf[1], &(blv->v6_locators_vec_length)); } } /* Fill the locator balancing vec using IPv4 and IPv6 locators and according * to their priority and weight*/ if (blv->v4_balancing_locators_vec != NULL && blv->v6_balancing_locators_vec != NULL) { //Only IPv4 locators are involved (due to priority reasons) if (min_priority[0] < min_priority[1]) { blv->balancing_locators_vec = blv->v4_balancing_locators_vec; blv->locators_vec_length = blv->v4_locators_vec_length; } //Only IPv6 locators are involved (due to priority reasons) else if (min_priority[0] > min_priority[1]) { blv->balancing_locators_vec = blv->v6_balancing_locators_vec; blv->locators_vec_length = blv->v6_locators_vec_length; } //IPv4 and IPv6 locators are involved else { hcf[2] = highest_common_factor(hcf[0], hcf[1]); total_weight[2] = total_weight[0] + total_weight[1]; for (ctr = 0; ctr < 2; ctr++) { ctr1 = 0; while (locators[ctr][ctr1] != NULL) { locators[2][pos] = locators[ctr][ctr1]; ctr1++; pos++; } } locators[2][pos] = NULL; blv->balancing_locators_vec = set_balancing_vector( locators[2], total_weight[2], hcf[2], &(blv->locators_vec_length)); } } balancing_locators_vec_dump(*blv, map, LDBG_1); glist_destroy(ipv4_loct_list); glist_destroy(ipv6_loct_list); return (GOOD); } /* Initialize to 0 balancing_locators_vecs */ static void balancing_locators_vecs_reset(balancing_locators_vecs *blv) { /* IPv4 locators more priority -> IPv4_IPv6 vector = IPv4 locator vector * IPv6 locators more priority -> IPv4_IPv6 vector = IPv4 locator vector */ if (blv->balancing_locators_vec != NULL && blv->balancing_locators_vec != blv->v4_balancing_locators_vec && blv->balancing_locators_vec != blv->v6_balancing_locators_vec) { free(blv->balancing_locators_vec); } if (blv->v4_balancing_locators_vec != NULL) { free(blv->v4_balancing_locators_vec); } if (blv->v6_balancing_locators_vec != NULL) { free(blv->v6_balancing_locators_vec); } blv->v4_balancing_locators_vec = NULL; blv->v4_locators_vec_length = 0; blv->v6_balancing_locators_vec = NULL; blv->v6_locators_vec_length = 0; blv->balancing_locators_vec = NULL; blv->locators_vec_length = 0; } static int select_best_priority_locators(glist_t *loct_list, locator_t **selected_locators, uint8_t is_mce) { glist_entry_t *it_loct; locator_t *locator; int min_priority = UNUSED_RLOC_PRIORITY; int pos = 0; if (glist_size(loct_list) == 0){ return (BAD); } glist_for_each_entry(it_loct,loct_list){ locator = (locator_t *)glist_entry_data(it_loct); /* Only use locators with status UP */ if (locator_state(locator) == DOWN || locator_priority(locator) == UNUSED_RLOC_PRIORITY ) { continue; } /* For local mappings, the locator should be local */ if (!is_mce && locator_L_bit(locator) == 0){ continue; } /* If priority of the locator equal to min_priority, then add the * locator to the list */ if (locator_priority(locator) == min_priority) { selected_locators[pos] = locator; pos++; selected_locators[pos] = NULL; } /* If priority of the locator is minor than the min_priority, then * min_priority and list of rlocs is updated */ if (locator_priority(locator) < min_priority) { pos = 0; min_priority = locator_priority(locator); selected_locators[pos] = locator; pos++; selected_locators[pos] = NULL; } } return (min_priority); } static locator_t ** set_balancing_vector(locator_t **locators, int total_weight, int hcf, int *locators_vec_length) { locator_t **balancing_locators_vec; int vector_length = 0; int used_pos = 0; int ctr = 0; int ctr1 = 0; int pos = 0; if (total_weight != 0) { /* Length of the dynamic vector */ vector_length = total_weight / hcf; } else { /* If all locators have weight equal to 0, we assign one position for * each locator */ while (locators[ctr] != NULL) { ctr++; } vector_length = ctr; ctr = 0; } /* Reserve memory for the dynamic vector */ balancing_locators_vec = xmalloc(vector_length * sizeof(locator_t *)); *locators_vec_length = vector_length; while (locators[ctr] != NULL) { if (total_weight != 0) { used_pos = locator_weight(locators[ctr]) / hcf; } else { /* If all locators has weight equal to 0, we assign one position * for each locator. Simetric balancing */ used_pos = 1; } ctr1 = 0; for (ctr1 = 0; ctr1 < used_pos; ctr1++) { balancing_locators_vec[pos] = locators[ctr]; pos++; } ctr++; } return (balancing_locators_vec); } static inline void get_hcf_locators_weight(locator_t **locators, int *total_weight, int *hcf) { int ctr = 0; int weight = 0; int tmp_hcf = 0; if (locators[0] != NULL) { tmp_hcf = locator_weight(locators[0]); while (locators[ctr] != NULL) { weight = weight + locator_weight(locators[ctr]); tmp_hcf = highest_common_factor(tmp_hcf, locator_weight(locators[ctr])); ctr++; } } *total_weight = weight; *hcf = tmp_hcf; } static int highest_common_factor(int a, int b) { int c; if (b == 0) { return a; } if (a == 0) { return b; } if (a < b) { c = a; a = b; a = c; } c = 1; while (b != 0) { c = a % b; a = b; b = c; } return (a); } oor-1.2.0/oor/fwd_policies/balancing_locators.h000066400000000000000000000036111313612200500215460ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef OOR_FWD_POLICIES_BALANCING_LOCATORS_H_ #define OOR_FWD_POLICIES_BALANCING_LOCATORS_H_ /* * Used to select the locator to be used for an identifier according to locators' priority and weight. * v4_balancing_locators_vec: If we just have IPv4 RLOCs * v6_balancing_locators_vec: If we just hace IPv6 RLOCs * balancing_locators_vec: If we have IPv4 & IPv6 RLOCs * For each packet, a hash of its tuppla is calculaed. The result of this hash is one position of the array. */ #include "../liblisp/liblisp.h" typedef struct balancing_locators_vecs_ { locator_t **v4_balancing_locators_vec; locator_t **v6_balancing_locators_vec; locator_t **balancing_locators_vec; int v4_locators_vec_length; int v6_locators_vec_length; int locators_vec_length; } balancing_locators_vecs; void *balancing_locators_vecs_new_init(mapping_t *map, glist_t *loc_loct, uint8_t is_mce); void balancing_locators_vecs_del(void * bal_vec); int balancing_vectors_calculate(balancing_locators_vecs *blv, mapping_t * map, glist_t *loc_loct, uint8_t is_mce); void balancing_locators_vec_dump(balancing_locators_vecs b_locators_vecs, mapping_t *mapping, int log_level); #endif /* OOR_FWD_POLICIES_BALANCING_LOCATORS_H_ */ oor-1.2.0/oor/fwd_policies/flow_balancing/000077500000000000000000000000001313612200500205155ustar00rootroot00000000000000oor-1.2.0/oor/fwd_policies/flow_balancing/fb_addr_func.c000066400000000000000000000077121313612200500232640ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "fb_addr_func.h" #include "../../lib/oor_log.h" #include "../fwd_policy.h" lisp_addr_t *fb_elp_type_get_fwd_ip_addr(void *elp, glist_t *locl_rlocs_addr); lisp_addr_t * fb_rle_type_get_fwd_ip_addr(void *rle, glist_t *locl_rlocs_addr); get_fwd_ip_addr_fct fb_get_fwd_ip_addr_fcts[MAX_LCAFS] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, fb_elp_type_get_fwd_ip_addr, 0, 0, fb_rle_type_get_fwd_ip_addr, 0, 0}; lisp_addr_t * fb_addr_get_fwd_ip_addr(lisp_addr_t *addr, glist_t *locl_rlocs_addr) { switch (lisp_addr_lafi(addr)) { case LM_AFI_IP: return (addr); case LM_AFI_IPPREF: OOR_LOG(LWRN, "fb_lisp_addr_get_fwd_ip_addr: Not applicable to prefixes"); return (NULL); case LM_AFI_LCAF: return (fb_lcaf_get_fwd_ip_addr(lisp_addr_get_lcaf(addr),locl_rlocs_addr)); default: return (NULL); } return (NULL); } /* obtain fwd IP address from LCAF*/ lisp_addr_t * fb_lcaf_get_fwd_ip_addr(lcaf_addr_t *lcaf, glist_t *locl_rlocs_addr) { if (!fb_get_fwd_ip_addr_fcts[lcaf_addr_get_type(lcaf)]) { OOR_LOG(LDBG_1, "fb_lcaf_get_fwd_ip_addr: lcaf type %d not supported", lcaf_addr_get_type(lcaf)); return (NULL); } return (*fb_get_fwd_ip_addr_fcts[lcaf_addr_get_type(lcaf)])(lcaf_addr_get_addr(lcaf), locl_rlocs_addr); } lisp_addr_t * fb_elp_type_get_fwd_ip_addr(void *elp, glist_t *locl_rlocs_addr) { lisp_addr_t *addr; glist_entry_t *it; glist_t *elp_list = ((elp_t *)elp)->nodes; int elp_size = glist_size(elp_list); int elp_pos = 0; // XXX to be checked glist_for_each_entry(it,elp_list){ elp_pos ++; addr = elp_node_addr((elp_node_t *)glist_entry_data(it)); if (lisp_addr_is_lcaf(addr) && lisp_addr_lcaf_type(addr) == LCAF_EXPL_LOC_PATH){ addr = fb_addr_get_fwd_ip_addr(addr, locl_rlocs_addr); if (addr != NULL){ return (addr); } continue; } addr = lisp_addr_get_ip_addr(addr); if (glist_contain_using_cmp_fct(addr, locl_rlocs_addr,(glist_cmp_fct)lisp_addr_cmp) == TRUE){ if (elp_pos == elp_size){ // Command invoked by xTR of the ELP (RTR-RTR-RTR-xTR). // Return the last address -> It will be used as the source address of the ELP return (addr); } // Command invoked by an RTR of the ELP // Return the next ip addr of the ELP it = glist_next(it); addr = elp_node_addr((elp_node_t *)glist_entry_data(it)); return (lisp_addr_get_ip_addr(addr)); } } // Command invoked by an iTR return (lisp_addr_get_ip_addr(elp_node_addr((elp_node_t *)glist_first_data(elp_list)))); } lisp_addr_t * fb_rle_type_get_fwd_ip_addr(void *rle, glist_t *locl_rlocs_addr) { lisp_addr_t *addr = NULL; glist_entry_t *it; rle_node_t *rnode; int level = -1; /* find the first highest level replication node */ glist_for_each_entry(it, ((rle_t *)rle)->nodes) { rnode = glist_entry_data(it); if (rnode->level > level) { level = rnode->level; addr = rnode->addr; } } return(addr); } oor-1.2.0/oor/fwd_policies/flow_balancing/fb_addr_func.h000066400000000000000000000017351313612200500232700ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef FB_ADDR_FUNC_H_ #define FB_ADDR_FUNC_H_ #include "../../liblisp/liblisp.h" lisp_addr_t *fb_addr_get_fwd_ip_addr(lisp_addr_t *addr, glist_t *locl_rlocs_addr); lisp_addr_t *fb_lcaf_get_fwd_ip_addr(lcaf_addr_t *lcaf, glist_t *locl_rlocs_addr); #endif /* FB_ADDR_FUNC_H_ */ oor-1.2.0/oor/fwd_policies/flow_balancing/flow_balancing.c000066400000000000000000000250151313612200500236310ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "flow_balancing.h" #include "fwd_entry_tuple.h" #include "../balancing_locators.h" #include "../fwd_addr_func.h" #include "../fwd_policy.h" #include "../../lib/oor_log.h" #include "../../liblisp/liblisp.h" #include "../../control/oor_ctrl_device.h" fb_dev_parm *fb_dev_parm_new(); void *fb_new_dev_policy_inf(oor_ctrl_dev_t *ctrl_dev, fwd_policy_dev_parm *dev_parm_inf); void fb_del_dev_policy_inf(void *dev_parm); int fb_init_map_loc_policy_inf(void *dev_parm, map_local_entry_t *mle, fwd_policy_map_parm *map_parm); int fb_init_map_cache_policy_inf(void *dev_parm, mcache_entry_t *mce); int fb_get_fwd_entry(void *fwd_dev_parm, map_local_entry_t *mle, mcache_entry_t *mce, mcache_entry_t *petrs, packet_tuple_t *tuple, fwd_info_t *fwd_info); int fb_get_fwd_entry_2(void *fwd_dev_parm, map_local_entry_t *mle, mcache_entry_t *mce, packet_tuple_t *tuple, fwd_info_t *fwd_info); int fb_updated_map_loc_inf(void *dev_parm, map_local_entry_t *mle); int fb_updated_map_cache_inf(void *dev_parm, mcache_entry_t *mce); fwd_policy_class fwd_policy_flow_balancing = { .new_dev_policy_inf = fb_new_dev_policy_inf, .del_dev_policy_inf = fb_del_dev_policy_inf, .init_map_loc_policy_inf = fb_init_map_loc_policy_inf, .del_map_loc_policy_inf = balancing_locators_vecs_del, .init_map_cache_policy_inf = fb_init_map_cache_policy_inf, .del_map_cache_policy_inf = balancing_locators_vecs_del, .updated_map_loc_inf = fb_updated_map_loc_inf, .updated_map_cache_inf = fb_updated_map_cache_inf, .get_fwd_info = fb_get_fwd_entry, .get_fwd_ip_addr = laddr_get_fwd_ip_addr }; fb_dev_parm * fb_dev_parm_new() { fb_dev_parm *dev_parm; dev_parm = (fb_dev_parm *)xzalloc(sizeof(fb_dev_parm)); if(dev_parm == NULL){ OOR_LOG(LWRN, "fb_dev_parm_new: Couldn't allocate memory for fb_dev_parm"); } return(dev_parm); } void * fb_new_dev_policy_inf(oor_ctrl_dev_t *ctrl_dev, fwd_policy_dev_parm *dev_parm_inf) { fb_dev_parm * dev_parm; dev_parm = fb_dev_parm_new(); if(dev_parm == NULL){ return (NULL); } dev_parm->dev_type = ctrl_dev_mode(ctrl_dev); dev_parm->loc_loct = ctrl_rlocs(ctrl_dev_get_ctrl_t(ctrl_dev)); return(dev_parm); } inline void fb_del_dev_policy_inf(void *dev_parm) { free((fb_dev_parm *)dev_parm); } int fb_init_map_loc_policy_inf(void *dev_parm, map_local_entry_t *mle, fwd_policy_map_parm *map_parm) { fb_dev_parm *dev_p = (fb_dev_parm *)dev_parm; void * fwd_inf = balancing_locators_vecs_new_init(map_local_entry_mapping(mle),dev_p->loc_loct,FALSE); if (!fwd_inf){ return (BAD); } map_local_entry_set_fwd_info(mle, fwd_inf, balancing_locators_vecs_del); return (GOOD); } int fb_init_map_cache_policy_inf(void *dev_parm, mcache_entry_t *mce) { fb_dev_parm *dev_p = (fb_dev_parm *)dev_parm; void * routing_inf = balancing_locators_vecs_new_init(mcache_entry_mapping(mce),dev_p->loc_loct,TRUE); if (!routing_inf){ return (BAD); } mcache_entry_set_routing_info(mce, routing_inf, balancing_locators_vecs_del); return (GOOD); } int fb_updated_map_loc_inf(void *dev_parm,map_local_entry_t *mle){ fb_dev_parm *dev_p = (fb_dev_parm *)dev_parm; return (balancing_vectors_calculate(map_local_entry_fwd_info(mle), map_local_entry_mapping(mle),dev_p->loc_loct,FALSE)); } int fb_updated_map_cache_inf(void *dev_parm,mcache_entry_t *mce){ fb_dev_parm *dev_p = (fb_dev_parm *)dev_parm; return (balancing_vectors_calculate(mcache_entry_routing_info(mce), mcache_entry_mapping(mce),dev_p->loc_loct, TRUE)); } /* Select the source and destination RLOC according to the priority and weight. * The destination RLOC is selected according to the AFI of the selected source * RLOC */ int fb_get_fwd_entry(void *fwd_dev_parm, map_local_entry_t *mle, mcache_entry_t *mce, mcache_entry_t *petrs, packet_tuple_t *tuple, fwd_info_t *fwd_info) { mapping_t *dmap; lisp_addr_t * src_eid = map_local_entry_eid(mle); lisp_addr_t * dst_eid = mcache_entry_eid(mce); if (lisp_addr_cmp_afi(src_eid,dst_eid) != 0){ if (!(lisp_addr_is_no_addr(src_eid) || lisp_addr_is_no_addr(dst_eid))){ // RTRs OOR_LOG(LDBG_3, "fb_get_fwd_entry: Src (%s) and dst (%s) EID should be of the same type", lisp_addr_to_char(src_eid), lisp_addr_to_char(dst_eid)); fwd_info->neg_map_reply_act = ACT_NO_ACTION; return(ERR_NO_ROUTE); } } if (fb_get_fwd_entry_2(fwd_dev_parm,mle,mce,tuple,fwd_info) == ERR_NO_ROUTE){ dmap = mcache_entry_mapping(mce); if (lisp_addr_is_lcaf(mapping_eid(dmap))){ fwd_info->neg_map_reply_act = ACT_DROP; return (GOOD); } if(mapping_action(dmap) == ACT_NATIVE_FWD){ if (petrs){ // Try to send the packet to PeTRs if (fb_get_fwd_entry_2(fwd_dev_parm,mle,petrs,tuple,fwd_info) == ERR_NO_ROUTE){ if (mcache_has_locators(petrs) == TRUE){ OOR_LOG(LDBG_3, "fb_get_fwd_entry: No PETR compatible with local locators afi"); }else{ OOR_LOG(LDBG_3, "fb_get_fwd_entry: No compatible src and dst rlocs. No PeTRs configured"); } fwd_info->neg_map_reply_act = ACT_NO_ACTION; }else{ fwd_info->neg_map_reply_act = ACT_NATIVE_FWD; OOR_LOG(LDBG_3, "Forwarding packet to PeTR"); } }else{ fwd_info->neg_map_reply_act = ACT_NO_ACTION; } } } return (GOOD); } int fb_get_fwd_entry_2(void *fwd_dev_parm, map_local_entry_t *mle, mcache_entry_t *mce, packet_tuple_t *tuple, fwd_info_t *fwd_info) { fwd_entry_tuple_t *fwd_entry; fb_dev_parm * dev_parm = (fb_dev_parm *)fwd_dev_parm; balancing_locators_vecs * src_blv = (balancing_locators_vecs *)map_local_entry_fwd_info(mle); balancing_locators_vecs * dst_blv = (balancing_locators_vecs *)mcache_entry_routing_info(mce); int src_vec_len, dst_vec_len; uint32_t pos, hash; locator_t ** src_loc_vec; locator_t ** dst_loc_vec; locator_t * src_loct; locator_t * dst_loct; lisp_addr_t * src_addr; lisp_addr_t * dst_addr; lisp_addr_t * src_ip_addr = NULL; lisp_addr_t * dst_ip_addr = NULL; int afi, res; if (mapping_locator_count(mcache_entry_mapping(mce)) == 0){ fwd_info->neg_map_reply_act = mapping_action(mcache_entry_mapping(mce)); res = ERR_NO_ROUTE; OOR_LOG(LDBG_3, "fb_get_fwd_entry_2: No locators"); goto done; } if (src_blv->balancing_locators_vec != NULL && dst_blv->balancing_locators_vec != NULL) { src_loc_vec = src_blv->balancing_locators_vec; src_vec_len = src_blv->locators_vec_length; } else if (src_blv->v6_balancing_locators_vec != NULL && dst_blv->v6_balancing_locators_vec != NULL) { src_loc_vec = src_blv->v6_balancing_locators_vec; src_vec_len = src_blv->v6_locators_vec_length; } else if (src_blv->v4_balancing_locators_vec != NULL && dst_blv->v4_balancing_locators_vec != NULL) { src_loc_vec = src_blv->v4_balancing_locators_vec; src_vec_len = src_blv->v4_locators_vec_length; } else { if (src_blv->v4_balancing_locators_vec == NULL && src_blv->v6_balancing_locators_vec == NULL) { OOR_LOG(LDBG_3, "fb_get_fwd_entry: No SRC locators " "available"); }else if (dst_blv->v4_balancing_locators_vec == NULL && dst_blv->v6_balancing_locators_vec == NULL) { OOR_LOG(LDBG_3, "fb_get_fwd_entry: No DST locators " "available"); } else { OOR_LOG(LDBG_3, "fb_get_fwd_entry: Source and " "destination RLOCs are not compatible"); } res = ERR_NO_ROUTE; goto done; } hash = pkt_tuple_hash(tuple); if (hash == 0) { OOR_LOG(LDBG_1, "fb_get_fwd_entry_2: Couldn't get the hash of the tuple " "to select the rloc. Using the default rloc"); //pos = hash%x_vec_len -> 0%x_vec_len = 0; } pos = hash % src_vec_len; src_loct = src_loc_vec[pos]; src_addr = locator_addr(src_loct); /* decide dst afi based on src afi*/ src_ip_addr = laddr_get_fwd_ip_addr(src_addr,dev_parm->loc_loct); afi = lisp_addr_ip_afi(src_ip_addr); switch (afi) { case (AF_INET): dst_loc_vec = dst_blv->v4_balancing_locators_vec; dst_vec_len = dst_blv->v4_locators_vec_length; break; case (AF_INET6): dst_loc_vec = dst_blv->v6_balancing_locators_vec; dst_vec_len = dst_blv->v6_locators_vec_length; break; default: OOR_LOG(LDBG_2, "select_locs_from_maps: Unknown IP AFI %d", lisp_addr_ip_afi(src_addr)); res = ERR_NO_ROUTE; src_ip_addr = NULL; goto done; } pos = hash % dst_vec_len; dst_loct = dst_loc_vec[pos]; dst_addr = locator_addr(dst_loct); dst_ip_addr = laddr_get_fwd_ip_addr(dst_addr,dev_parm->loc_loct); res = GOOD; OOR_LOG(LDBG_3, "select_locs_from_maps: EID: %s -> %s, protocol: %d, " "port: %d -> %d\n --> RLOC: %s -> %s", lisp_addr_to_char(&(tuple->src_addr)), lisp_addr_to_char(&(tuple->dst_addr)), tuple->protocol, tuple->src_port, tuple->dst_port, lisp_addr_to_char(src_ip_addr), lisp_addr_to_char(dst_ip_addr)); done: if (fwd_info->dp_conf_inf){ fwd_entry_tuple_del(fwd_info->dp_conf_inf); } fwd_entry = fwd_entry_tuple_new_init(tuple, src_ip_addr, dst_ip_addr, tuple->iid, NULL); fwd_info->dp_conf_inf = fwd_entry; fwd_info->data_del_fn = (fwd_info_data_del_fn)fwd_entry_tuple_del; return (res); } oor-1.2.0/oor/fwd_policies/flow_balancing/flow_balancing.h000066400000000000000000000016731313612200500236420ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef FLOW_BALANCING_H_ #define FLOW_BALANCING_H_ #include "../../defs.h" #include "../../lib/generic_list.h" typedef struct fb_dev_parm_ { oor_dev_type_e dev_type; glist_t * loc_loct; }fb_dev_parm; #endif /* FLOW_BALANCING_H_ */ oor-1.2.0/oor/fwd_policies/flow_balancing/fwd_entry_tuple.c000066400000000000000000000027331313612200500241000ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "fwd_entry_tuple.h" inline fwd_entry_tuple_t * fwd_entry_tuple_new_init(packet_tuple_t *tuple, lisp_addr_t *srloc, lisp_addr_t *drloc, uint32_t iid, int *out_socket) { fwd_entry_tuple_t *fw_entry = xzalloc(sizeof(fwd_entry_tuple_t)); if (!fw_entry){ return (NULL); } fw_entry->tuple = pkt_tuple_clone(tuple); fw_entry->srloc = lisp_addr_clone(srloc); fw_entry->drloc = lisp_addr_clone(drloc); fw_entry->iid = iid; fw_entry->out_sock = out_socket; return (fw_entry); } inline void fwd_entry_tuple_del(fwd_entry_tuple_t *fwd_entry) { if (fwd_entry == NULL){ return; } pkt_tuple_del(fwd_entry->tuple); lisp_addr_del(fwd_entry->srloc); lisp_addr_del(fwd_entry->drloc); free(fwd_entry); fwd_entry = NULL; } oor-1.2.0/oor/fwd_policies/flow_balancing/fwd_entry_tuple.h000066400000000000000000000025131313612200500241010ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef OOR_FWD_POLICIES_FLOW_BALANCING_FWD_ENTRY_TUPLE_H_ #define OOR_FWD_POLICIES_FLOW_BALANCING_FWD_ENTRY_TUPLE_H_ #include "../../lib/packets.h" #include "../../liblisp/lisp_address.h" typedef struct fwd_entry_tuple_ { packet_tuple_t *tuple; // Must be the first element lisp_addr_t *srloc; lisp_addr_t *drloc; int *out_sock; uint32_t iid; } fwd_entry_tuple_t; fwd_entry_tuple_t *fwd_entry_tuple_new_init(packet_tuple_t *tuple, lisp_addr_t *srloc, lisp_addr_t *drloc, uint32_t iid, int *out_socket); void fwd_entry_tuple_del(fwd_entry_tuple_t *fwd_entry); #endif /* OOR_FWD_POLICIES_FLOW_BALANCING_FWD_ENTRY_TUPLE_H_ */ oor-1.2.0/oor/fwd_policies/fwd_addr_func.c000066400000000000000000000107501313612200500205040ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "../lib/oor_log.h" #include "fwd_addr_func.h" #include "fwd_policy.h" lisp_addr_t *lcaf_get_fwd_ip_addr(lcaf_addr_t *lcaf, glist_t *locl_rlocs_addr); lisp_addr_t *elp_type_get_fwd_ip_addr(void *elp, glist_t *locl_rlocs_addr); lisp_addr_t * rle_type_get_fwd_ip_addr(void *rle, glist_t *locl_rlocs_addr); get_fwd_ip_addr_fct fb_get_fwd_ip_addr_fcts[MAX_LCAFS] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, elp_type_get_fwd_ip_addr, 0, 0, rle_type_get_fwd_ip_addr, 0, 0}; lisp_addr_t * laddr_get_fwd_ip_addr(lisp_addr_t *addr, glist_t *locl_rlocs_addr) { switch (lisp_addr_lafi(addr)) { case LM_AFI_IP: return (addr); case LM_AFI_IPPREF: OOR_LOG(LWRN, "laddr_get_fwd_ip_addr: Not applicable to prefixes"); return (NULL); case LM_AFI_LCAF: return (lcaf_get_fwd_ip_addr(lisp_addr_get_lcaf(addr),locl_rlocs_addr)); default: return (NULL); } return (NULL); } /* obtain fwd IP address from LCAF*/ lisp_addr_t * lcaf_get_fwd_ip_addr(lcaf_addr_t *lcaf, glist_t *locl_rlocs_addr) { if (!fb_get_fwd_ip_addr_fcts[lcaf_addr_get_type(lcaf)]) { OOR_LOG(LDBG_1, "lcaf_get_fwd_ip_addr: lcaf type %d not supported", lcaf_addr_get_type(lcaf)); return (NULL); } return (*fb_get_fwd_ip_addr_fcts[lcaf_addr_get_type(lcaf)])(lcaf_addr_get_addr(lcaf), locl_rlocs_addr); } lisp_addr_t * elp_type_get_fwd_ip_addr(void *elp, glist_t *locl_rlocs_addr) { lisp_addr_t *addr; glist_entry_t *it; glist_t *elp_list = ((elp_t *)elp)->nodes; int elp_size = glist_size(elp_list); int elp_pos = 0; // XXX to be checked glist_for_each_entry(it,elp_list){ elp_pos ++; addr = elp_node_addr((elp_node_t *)glist_entry_data(it)); if (lisp_addr_is_lcaf(addr) && lisp_addr_lcaf_type(addr) == LCAF_EXPL_LOC_PATH){ addr = laddr_get_fwd_ip_addr(addr, locl_rlocs_addr); if (addr != NULL){ return (addr); } continue; } addr = lisp_addr_get_ip_addr(addr); if (glist_contain_using_cmp_fct(addr, locl_rlocs_addr,(glist_cmp_fct)lisp_addr_cmp) == TRUE){ if (elp_pos == elp_size){ // Command invoked by xTR of the ELP (RTR-RTR-RTR-xTR). // Return the last address -> It will be used as the source address of the ELP return (addr); } // Command invoked by an RTR of the ELP // Return the next ip addr of the ELP it = glist_next(it); addr = elp_node_addr((elp_node_t *)glist_entry_data(it)); return (lisp_addr_get_ip_addr(addr)); } } // Command invoked by an iTR return (lisp_addr_get_ip_addr(elp_node_addr((elp_node_t *)glist_first_data(elp_list)))); } lisp_addr_t * rle_type_get_fwd_ip_addr(void *rle, glist_t *locl_rlocs_addr) { lisp_addr_t *addr = NULL; glist_entry_t *it; rle_node_t *rnode; int level = -1; /* find the first highest level replication node */ glist_for_each_entry(it, ((rle_t *)rle)->nodes) { rnode = glist_entry_data(it); if (rnode->level > level) { level = rnode->level; addr = rnode->addr; } } return(addr); } lisp_addr_t * laddr_get_special_addr_from_type(lisp_addr_t *address) { lisp_addr_t *addr = lisp_addr_clone(address); lisp_addr_t *ip_pref = lisp_addr_get_ip_pref_addr(addr); if (!ip_pref){ return (NULL); } switch (lisp_addr_ip_afi(ip_pref)){ case AF_INET: lisp_addr_ippref_from_char(FULL_IPv4_ADDRESS_SPACE,ip_pref); break; case AF_INET6: lisp_addr_ippref_from_char(FULL_IPv6_ADDRESS_SPACE,ip_pref); break; } return(addr); } oor-1.2.0/oor/fwd_policies/fwd_addr_func.h000066400000000000000000000020021313612200500205000ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef OOR_FWD_POLICIES_FWD_ADDR_FUNC_H_ #define OOR_FWD_POLICIES_FWD_ADDR_FUNC_H_ #include "../liblisp/lisp_address.h" lisp_addr_t *laddr_get_fwd_ip_addr(lisp_addr_t *addr, glist_t *locl_rlocs_addr); lisp_addr_t *laddr_get_special_addr_from_type(lisp_addr_t *addr); #endif /* OOR_FWD_POLICIES_FWD_ADDR_FUNC_H_ */ oor-1.2.0/oor/fwd_policies/fwd_policy.c000066400000000000000000000054631313612200500200630ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "fwd_policy.h" #include "../lib/oor_log.h" static fwd_policy_class *fwd_policy_libs[2] = { &fwd_policy_flow_balancing, &fwd_policy_vpp_balancing }; void policy_loct_parm_del(fwd_policy_loct_parm *pol_loct); fwd_policy_class * fwd_policy_class_find(char *lib) { if (strcmp(lib,"flow_balancing") == 0){ return(fwd_policy_libs[0]); }else if (strcmp(lib,"vpp_balancing") == 0){ return(fwd_policy_libs[1]); } OOR_LOG(LERR, "The forward policy library \"%s\" has not been found",lib); return (NULL); } fwd_policy_dev_parm * fwd_policy_dev_parm_new() { fwd_policy_dev_parm *pol_dev = xzalloc(sizeof(fwd_policy_dev_parm)); pol_dev->paramiters = shash_new_managed((free_value_fn_t)free); return (pol_dev); } void fwd_policy_dev_parm_del(fwd_policy_dev_parm *pol_dev) { shash_destroy(pol_dev->paramiters); free (pol_dev); } fwd_policy_map_parm * policy_map_parm_new(lisp_addr_t *eid_prefix) { fwd_policy_map_parm *pol_map = xzalloc(sizeof(fwd_policy_map_parm)); pol_map->eid_prefix = lisp_addr_clone(eid_prefix); pol_map->paramiters = shash_new(); pol_map->locators = glist_new_managed((glist_del_fct)policy_loct_parm_del); return (pol_map); } void policy_map_parm_del (fwd_policy_map_parm *pol_map) { lisp_addr_del(pol_map->eid_prefix); shash_destroy(pol_map->paramiters); glist_destroy(pol_map->locators); free(pol_map); } fwd_policy_loct_parm * policy_loct_parm_new(lisp_addr_t *rloc_addr) { fwd_policy_loct_parm *pol_loct = xzalloc(sizeof(fwd_policy_loct_parm)); pol_loct->rloc_addr = lisp_addr_clone(rloc_addr); pol_loct->paramiters = shash_new(); return (pol_loct); } void policy_loct_parm_del(fwd_policy_loct_parm *pol_loct) { lisp_addr_del(pol_loct->rloc_addr); shash_destroy(pol_loct->paramiters); free(pol_loct); } fwd_info_t * fwd_info_new() { fwd_info_t * fi = xzalloc(sizeof(fwd_info_t)); return (fi); } void fwd_info_del(fwd_info_t * fwd_info) { if (fwd_info->data_del_fn){ fwd_info->data_del_fn(fwd_info->dp_conf_inf); } if(fwd_info->associated_entry){ lisp_addr_del(fwd_info->associated_entry); } free(fwd_info); } oor-1.2.0/oor/fwd_policies/fwd_policy.h000066400000000000000000000065541313612200500200720ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef ROUTING_POLICY_H_ #define ROUTING_POLICY_H_ #include "../lib/map_cache_entry.h" #include "../lib/map_local_entry.h" typedef struct packet_tuple packet_tuple_t; typedef lisp_addr_t *(*get_fwd_ip_addr_fct)(void *, glist_t *); typedef void (*fwd_info_data_del_fn)(void *); /* * Structure used to pass routing configuration parameters releated * to the device into the fwd module */ typedef struct fwd_policy_dev_parm_t{ shash_t *paramiters; } fwd_policy_dev_parm; /* * Structure used to pass routing configuration parameters releated * to a mapping into the fwd module */ typedef struct fwd_policy_map_parm_t{ lisp_addr_t *eid_prefix; shash_t *paramiters; glist_t *locators; } fwd_policy_map_parm; /* * Structure used to pass routing configuration parameters releated * to a locator into the fwd module */ typedef struct fwd_policy_loct_parm_t{ lisp_addr_t *rloc_addr; shash_t *paramiters; } fwd_policy_loct_parm; typedef struct fwd_info_{ lisp_addr_t *associated_entry; void *dp_conf_inf; lisp_action_e neg_map_reply_act; oor_encap_t encap; fwd_info_data_del_fn data_del_fn; }fwd_info_t; /* functions to manipulate routing */ typedef struct fwd_policy_class { void *(*new_dev_policy_inf)(oor_ctrl_dev_t *ctrl_dev, fwd_policy_dev_parm *dev_parm); void (*del_dev_policy_inf)(void *); int (*init_map_loc_policy_inf)(void *dev_parm, map_local_entry_t *mle, fwd_policy_map_parm *map_parm); void (*del_map_loc_policy_inf)(void *); int (*init_map_cache_policy_inf)(void *dev_parm, mcache_entry_t *mce); void (*del_map_cache_policy_inf)(void *); int (*updated_map_loc_inf)(void *dev_parm, map_local_entry_t *mle); int (*updated_map_cache_inf)(void *dev_parm, mcache_entry_t *mce); int (*get_fwd_info)(void *dev_parm, map_local_entry_t *mle, mcache_entry_t *mce, mcache_entry_t *petrs, packet_tuple_t *tuple, fwd_info_t *fdw_info); lisp_addr_t *(*get_fwd_ip_addr)(lisp_addr_t *addr, glist_t *locl_rlocs_addr); } fwd_policy_class; extern fwd_policy_class fwd_policy_flow_balancing; #ifdef VPP extern fwd_policy_class fwd_policy_vpp_balancing; #else fwd_policy_class fwd_policy_vpp_balancing; #endif fwd_policy_dev_parm *fwd_policy_dev_parm_new(); void fwd_policy_dev_parm_del(fwd_policy_dev_parm *pol_dev); fwd_policy_map_parm *fwd_policy_map_parm_new(lisp_addr_t *eid_prefix); void fwd_policy_map_parm_del (fwd_policy_map_parm *pol_map); fwd_policy_loct_parm *fwd_policy_loct_parm_new(lisp_addr_t *rloc_addr); void fwd_policy_loct_parm_del(fwd_policy_loct_parm *pol_loct); fwd_policy_class *fwd_policy_class_find(char *lib); fwd_info_t *fwd_info_new(); void fwd_info_del(fwd_info_t * fwd_info); #endif /* ROUTING_POLICY_H_ */ oor-1.2.0/oor/fwd_policies/fwd_utils.c000066400000000000000000000033031313612200500177130ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "fwd_utils.h" #include "../lib/oor_log.h" void locators_classify_in_4_6(mapping_t *mapping, glist_t *loc_loct_addr, glist_t *ipv4_loct_list, glist_t *ipv6_loct_list, get_fwd_ip_addr fwd_if) { locator_t *locator; lisp_addr_t *addr; lisp_addr_t *ip_addr; if (glist_size(mapping->locators_lists) == 0){ OOR_LOG(LDBG_3,"locators_classify_in_4_6: No locators to classify for mapping with eid %s", lisp_addr_to_char(mapping_eid(mapping))); return; } mapping_foreach_active_locator(mapping,locator){ addr = locator_addr(locator); ip_addr = fwd_if(addr,loc_loct_addr); if (ip_addr == NULL){ OOR_LOG(LDBG_2,"locators_classify_in_4_6: No IP address for %s", lisp_addr_to_char(addr)); continue; } if (lisp_addr_ip_afi(ip_addr) == AF_INET){ glist_add(locator,ipv4_loct_list); }else{ glist_add(locator,ipv6_loct_list); } }mapping_foreach_active_locator_end; } oor-1.2.0/oor/fwd_policies/fwd_utils.h000066400000000000000000000021151313612200500177200ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef OOR_FWD_POLICIES_FWD_UTILS_H_ #define OOR_FWD_POLICIES_FWD_UTILS_H_ #include "fwd_policy.h" #include "../liblisp/liblisp.h" typedef lisp_addr_t * (*get_fwd_ip_addr)(lisp_addr_t *, glist_t *); void locators_classify_in_4_6(mapping_t *mapping, glist_t *loc_loct_addr, glist_t *ipv4_loct_list, glist_t *ipv6_loct_list, get_fwd_ip_addr fn); #endif /* OOR_FWD_POLICIES_FWD_UTILS_H_ */ oor-1.2.0/oor/fwd_policies/vpp_balancing/000077500000000000000000000000001313612200500203535ustar00rootroot00000000000000oor-1.2.0/oor/fwd_policies/vpp_balancing/fwd_entry_vpp.c000066400000000000000000000050311313612200500234040ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "fwd_entry_vpp.h" #include "../../lib/oor_log.h" #include "../../liblisp/lisp_address.h" fwd_entry_vpp_t * fwd_entry_vpp_new_init(lisp_addr_t *seid,lisp_addr_t *deid,int iid) { fwd_entry_vpp_t * fwd_entry; fwd_entry = xzalloc(sizeof(fwd_entry_vpp_t)); if (!fwd_entry){ return (NULL); } fwd_entry->seid = lisp_addr_clone(seid); fwd_entry->deid = lisp_addr_clone(deid); fwd_entry->iid = iid; fwd_entry->loc_pair_lst = glist_new_managed((glist_del_fct)vpp_loct_pair_del); return (fwd_entry); } void fwd_entry_vpp_del(fwd_entry_vpp_t *fwd_entry) { if (!fwd_entry){ return; } lisp_addr_del(fwd_entry->seid); lisp_addr_del(fwd_entry->deid); glist_destroy(fwd_entry->loc_pair_lst); free(fwd_entry); fwd_entry = NULL; } vpp_loct_pair * vpp_loct_pair_new_init(lisp_addr_t *srloc,lisp_addr_t *drloc,int weight) { vpp_loct_pair * loc_pair; loc_pair = xzalloc(sizeof(vpp_loct_pair)); loc_pair->srloc = lisp_addr_clone(srloc); loc_pair->drloc = lisp_addr_clone(drloc); loc_pair->weight = weight; return (loc_pair); } void vpp_loct_pair_del(vpp_loct_pair *loc_pair) { lisp_addr_del(loc_pair->srloc); lisp_addr_del(loc_pair->drloc); free(loc_pair); loc_pair = NULL; } void fwd_entry_vpp_dump(fwd_entry_vpp_t *fwd_entry, int log_level){ vpp_loct_pair * loc_pair; glist_entry_t *it_pair; OOR_LOG(log_level, "VPP forward information for: %s -> %s (VNI: %d)", lisp_addr_to_char(fwd_entry->seid),lisp_addr_to_char(fwd_entry->deid), fwd_entry->iid); glist_for_each_entry(it_pair,fwd_entry->loc_pair_lst){ loc_pair = (vpp_loct_pair *)glist_entry_data(it_pair); OOR_LOG(log_level, "\t\t%s -> %s w:%d",lisp_addr_to_char(loc_pair->srloc), lisp_addr_to_char(loc_pair->drloc),loc_pair->weight); } } oor-1.2.0/oor/fwd_policies/vpp_balancing/fwd_entry_vpp.h000066400000000000000000000027751313612200500234250ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef OOR_FWD_POLICIES_VPP_BALANCING_FWD_ENTRY_VPP_H_ #define OOR_FWD_POLICIES_VPP_BALANCING_FWD_ENTRY_VPP_H_ #include "../../liblisp/lisp_address.h" typedef struct fwd_entry_vpp_ { lisp_addr_t *seid; lisp_addr_t *deid; glist_t *loc_pair_lst; // uint32_t iid; } fwd_entry_vpp_t; typedef struct vpp_loc_pair_ { lisp_addr_t *srloc; lisp_addr_t *drloc; int weight; } vpp_loct_pair; fwd_entry_vpp_t *fwd_entry_vpp_new_init(lisp_addr_t *seid,lisp_addr_t *deid,int iid); void fwd_entry_vpp_del(fwd_entry_vpp_t *fwd_entry); vpp_loct_pair *vpp_loct_pair_new_init(lisp_addr_t *srloc,lisp_addr_t *drloc,int weight); void vpp_loct_pair_del(vpp_loct_pair *loc_pair); void fwd_entry_vpp_dump(fwd_entry_vpp_t *fwd_entry, int log_level); #endif /* OOR_FWD_POLICIES_VPP_BALANCING_FWD_ENTRY_VPP_H_ */ oor-1.2.0/oor/fwd_policies/vpp_balancing/vpp_balancing.c000066400000000000000000000365051313612200500233330ustar00rootroot00000000000000/* * vpp_balancing.c * * Created on: Sep 14, 2016 * Author: alopez */ #include "fwd_entry_vpp.h" #include "vpp_balancing.h" #include "../fwd_policy.h" #include "../fwd_utils.h" #include "../fwd_addr_func.h" #include "../../control/oor_ctrl_device.h" #include "../../lib/oor_log.h" #include vpp_dev_parm *vpp_dev_parm_new(); void vpp_dev_parm_del(vpp_dev_parm * dev_parm); vpp_map_policy_inf *vpp_map_policy_inf_new(); void vpp_map_policy_inf_del(vpp_map_policy_inf * vpp_inf); int vpp_map_policy_inf_calc(vpp_map_policy_inf *pi, mapping_t * map, glist_t *loc_loct, uint8_t is_mce); void vpp_map_policy_inf_reset(vpp_map_policy_inf *pi); void * vpp_new_dev_policy_inf(oor_ctrl_dev_t *ctrl_dev,fwd_policy_dev_parm *dev_parm_inf); void vpp_del_dev_policy_inf(void * dev_parm); int vpp_init_map_loc_policy_inf(void *dev_parm, map_local_entry_t *mle, fwd_policy_map_parm *map_parm); void vpp_del_map_loc_policy_inf(void * map_loc_policy_inf); int vpp_init_map_cache_policy_inf(void *dev_parm, mcache_entry_t *mce); void vpp_del_map_cache_policy_inf(void * mcache_policy_inf); int vpp_updated_map_loc_inf(void *dev_parm,map_local_entry_t *mle); int vpp_updated_map_cache_inf(void *dev_parm,mcache_entry_t *mce); static int select_best_priority_loct_lst(glist_t *loct_list, uint8_t is_mce, glist_t *best_loct_list, int *min_priority, int *total_weight); int vpp_get_fwd_entry(void *fwd_dev_parm, map_local_entry_t *mle, mcache_entry_t *mce, mcache_entry_t *petrs, packet_tuple_t *tuple, fwd_info_t *fwd_info); int vpp_get_fwd_entry_2(void *fwd_dev_parm, map_local_entry_t *mle, mcache_entry_t *mce, packet_tuple_t *tuple, fwd_info_t *fwd_info); void fwd_entry_vpp_fill (fwd_entry_vpp_t *fwd_entry, glist_t *locl_loct, glist_t *rmt_loct, int weight_locl, int weight_rmt, glist_t *locl_rlocs_lst); fwd_policy_class fwd_policy_vpp_balancing = { .new_dev_policy_inf = vpp_new_dev_policy_inf, .del_dev_policy_inf = vpp_del_dev_policy_inf, .init_map_loc_policy_inf = vpp_init_map_loc_policy_inf, .del_map_loc_policy_inf = vpp_del_map_loc_policy_inf, .init_map_cache_policy_inf = vpp_init_map_cache_policy_inf, .del_map_cache_policy_inf = vpp_del_map_cache_policy_inf, .updated_map_loc_inf = vpp_updated_map_loc_inf, .updated_map_cache_inf = vpp_updated_map_cache_inf, .get_fwd_info = vpp_get_fwd_entry, .get_fwd_ip_addr = laddr_get_fwd_ip_addr }; inline vpp_dev_parm * vpp_dev_parm_new() { vpp_dev_parm *dev_parm; dev_parm = (vpp_dev_parm *)xzalloc(sizeof(vpp_dev_parm)); if(dev_parm == NULL){ OOR_LOG(LWRN, "vpp_dev_parm_new: Couldn't allocate memory for fb_dev_parm"); } return(dev_parm); } inline void vpp_dev_parm_del(vpp_dev_parm * dev_parm) { free(dev_parm); dev_parm = NULL; } inline vpp_map_policy_inf * vpp_map_policy_inf_new() { vpp_map_policy_inf * vpp_inf; vpp_inf = xzalloc(sizeof(vpp_map_policy_inf)); vpp_inf->ipv4_loct_lst = glist_new(); vpp_inf->ipv6_loct_lst = glist_new(); return (vpp_inf); } inline void vpp_map_policy_inf_del(vpp_map_policy_inf * vpp_inf) { glist_destroy(vpp_inf->ipv4_loct_lst); glist_destroy(vpp_inf->ipv6_loct_lst); free(vpp_inf); vpp_inf = NULL; } int vpp_map_policy_inf_calc(vpp_map_policy_inf *pi, mapping_t * map, glist_t *loc_loct, uint8_t is_mce) { glist_t *ipv4_loct_list = glist_new(); glist_t *ipv6_loct_list = glist_new(); vpp_map_policy_inf_reset(pi); locators_classify_in_4_6(map,loc_loct,ipv4_loct_list,ipv6_loct_list, laddr_get_fwd_ip_addr); if (glist_size(ipv4_loct_list) != 0){ select_best_priority_loct_lst(ipv4_loct_list,is_mce,pi->ipv4_loct_lst, &(pi->priority4),&(pi->sum_weight4)); } if (glist_size(ipv6_loct_list) != 0){ select_best_priority_loct_lst(ipv6_loct_list,is_mce,pi->ipv6_loct_lst, &(pi->priority6),&(pi->sum_weight6)); } return (GOOD); } void vpp_map_policy_inf_reset(vpp_map_policy_inf *pi) { glist_remove_all(pi->ipv4_loct_lst); glist_remove_all(pi->ipv6_loct_lst); pi->priority4 = 255; pi->priority6 = 255; pi->sum_weight4 = 0; pi->sum_weight6 = 0; } void * vpp_new_dev_policy_inf(oor_ctrl_dev_t *ctrl_dev,fwd_policy_dev_parm *dev_parm_inf) { vpp_dev_parm * dev_parm; dev_parm = vpp_dev_parm_new(); if(!dev_parm){ return (NULL); } dev_parm->dev_type = ctrl_dev_mode(ctrl_dev); dev_parm->loc_loct = ctrl_rlocs(ctrl_dev_get_ctrl_t(ctrl_dev)); return(dev_parm); } void vpp_del_dev_policy_inf(void * dev_parm) { vpp_dev_parm_del(dev_parm); } int vpp_init_map_loc_policy_inf(void *dev_parm, map_local_entry_t *mle, fwd_policy_map_parm *map_parm) { vpp_dev_parm *dev_p = (vpp_dev_parm *)dev_parm; vpp_map_policy_inf * fwd_inf = vpp_map_policy_inf_new(); if (!fwd_inf){ return (BAD); } vpp_map_policy_inf_calc(fwd_inf, map_local_entry_mapping(mle), dev_p->loc_loct, FALSE); map_local_entry_set_fwd_info(mle,(void *)fwd_inf,vpp_del_map_loc_policy_inf); return (GOOD); } void vpp_del_map_loc_policy_inf(void * map_loc_policy_inf) { vpp_map_policy_inf_del(map_loc_policy_inf); } int vpp_init_map_cache_policy_inf(void *dev_parm, mcache_entry_t *mce) { vpp_dev_parm *dev_p = (vpp_dev_parm *)dev_parm; vpp_map_policy_inf * routing_inf = vpp_map_policy_inf_new(); if (!routing_inf){ return (BAD); } vpp_map_policy_inf_calc(routing_inf, mcache_entry_mapping(mce), dev_p->loc_loct, TRUE); mcache_entry_set_routing_info(mce, routing_inf, vpp_del_map_cache_policy_inf); return (GOOD); } void vpp_del_map_cache_policy_inf(void * mcache_policy_inf) { vpp_map_policy_inf_del(mcache_policy_inf); } int vpp_updated_map_loc_inf(void *dev_parm,map_local_entry_t *mle) { vpp_dev_parm *dev_p = (vpp_dev_parm *)dev_parm; vpp_map_policy_inf_calc(map_local_entry_fwd_info(mle),map_local_entry_mapping(mle), dev_p->loc_loct, FALSE); return (GOOD); } int vpp_updated_map_cache_inf(void *dev_parm,mcache_entry_t *mce) { vpp_dev_parm *dev_p = (vpp_dev_parm *)dev_parm; vpp_map_policy_inf_calc(mcache_entry_routing_info(mce),mcache_entry_mapping(mce), dev_p->loc_loct, TRUE); return (GOOD); } static int select_best_priority_loct_lst(glist_t *loct_list, uint8_t is_mce, glist_t *best_loct_list, int *min_priority, int *total_weight) { locator_t *selected_locators[33]; glist_entry_t *it_loct; locator_t *locator; int min_pri = UNUSED_RLOC_PRIORITY - 1; int weight = 0; int pos = 0; if (glist_size(loct_list) == 0){ return (BAD); } selected_locators[0] = NULL; glist_for_each_entry(it_loct,loct_list){ locator = (locator_t *)glist_entry_data(it_loct); /* Only use locators with status UP */ if (locator_state(locator) == DOWN || locator_priority(locator) == UNUSED_RLOC_PRIORITY ) { continue; } /* For local mappings, the locator should be local */ if (!is_mce && locator_L_bit(locator) == 0){ continue; } /* If priority of the locator equal to min_pri, then add the * locator to the list */ if (locator_priority(locator) == min_pri) { selected_locators[pos] = locator; pos++; selected_locators[pos] = NULL; }else if (locator_priority(locator) < min_pri) { /* If priority of the locator is minor than the min_pri, then * min_pri and list of rlocs is updated */ pos = 0; min_pri = locator_priority(locator); selected_locators[pos] = locator; pos++; selected_locators[pos] = NULL; } } pos = 0; while (selected_locators[pos] != NULL){ weight+=locator_weight(selected_locators[pos]); glist_add(selected_locators[pos],best_loct_list); pos++; } *min_priority = min_pri; *total_weight = weight; return (GOOD); } int vpp_get_fwd_entry(void *fwd_dev_parm, map_local_entry_t *mle, mcache_entry_t *mce, mcache_entry_t *petrs, packet_tuple_t *tuple, fwd_info_t *fwd_info) { fwd_entry_vpp_t *fwd_entry; mapping_t *dmap; lisp_addr_t * src_eid = map_local_entry_eid(mle); lisp_addr_t * dst_eid = mcache_entry_eid(mce); uint8_t free_src_eid = FALSE, free_dst_eid = FALSE; if (lisp_addr_cmp_afi(src_eid,dst_eid) != 0){ if (lisp_addr_is_no_addr(src_eid)){ //RTR src_eid = laddr_get_special_addr_from_type(dst_eid); free_src_eid = TRUE; }else if(lisp_addr_is_no_addr(dst_eid)){ //RTRs (xTR with NAT) dst_eid = laddr_get_special_addr_from_type(src_eid); free_dst_eid = TRUE; }else{ OOR_LOG(LDBG_3, "fb_get_fwd_entry: Src (%s) and dst (%s) EID should be of the same type", lisp_addr_to_char(src_eid), lisp_addr_to_char(dst_eid)); fwd_info->neg_map_reply_act = ACT_NO_ACTION; return(ERR_NO_ROUTE); } } if (fwd_info->dp_conf_inf){ fwd_entry_vpp_del(fwd_info->dp_conf_inf); } fwd_entry = fwd_entry_vpp_new_init(src_eid,dst_eid,tuple->iid); fwd_info->dp_conf_inf = fwd_entry; fwd_info->data_del_fn = (fwd_info_data_del_fn)fwd_entry_vpp_del; if (vpp_get_fwd_entry_2(fwd_dev_parm,mle,mce,tuple,fwd_info) == ERR_NO_ROUTE){ dmap = mcache_entry_mapping(mce); // If the destination EID is an LCAF, we don't send traffic to PeTRs -> DROP packets if (lisp_addr_is_lcaf(mapping_eid(dmap))){ fwd_info->neg_map_reply_act = ACT_DROP; goto done; } if(mapping_action(dmap) == ACT_NATIVE_FWD){ if (petrs){ // Try to send the packet to PeTRs if (vpp_get_fwd_entry_2(fwd_dev_parm,mle,petrs,tuple,fwd_info) == ERR_NO_ROUTE){ if (mcache_has_locators(petrs) == TRUE){ OOR_LOG(LDBG_3, "fb_get_fwd_entry: No PETR compatible with local locators afi"); }else{ OOR_LOG(LDBG_3, "fb_get_fwd_entry: No compatible src and dst rlocs. No PeTRs configured"); } fwd_info->neg_map_reply_act = ACT_NO_ACTION; }else{ fwd_info->neg_map_reply_act = ACT_NATIVE_FWD; OOR_LOG(LDBG_3, "Forwarding packet to PeTR"); } }else{ // No PeTRs availables, drop packets fwd_info->neg_map_reply_act = ACT_NO_ACTION; } } } done: if (free_src_eid){ lisp_addr_del(src_eid); } if (free_dst_eid){ lisp_addr_del(dst_eid); } return (GOOD); } int vpp_get_fwd_entry_2(void *fwd_dev_parm, map_local_entry_t *mle, mcache_entry_t *mce, packet_tuple_t *tuple, fwd_info_t *fwd_info) { vpp_dev_parm * dev_parm = (vpp_dev_parm *)fwd_dev_parm; vpp_map_policy_inf * src_fwd_inf = (vpp_map_policy_inf *)map_local_entry_fwd_info(mle); vpp_map_policy_inf * dst_fwd_inf = (vpp_map_policy_inf *)mcache_entry_routing_info(mce); int afi_support = NO_AFI_SUPPOT; fwd_entry_vpp_t *fwd_entry = (fwd_entry_vpp_t *)fwd_info->dp_conf_inf; if (mapping_locator_count(mcache_entry_mapping(mce)) == 0){ fwd_info->neg_map_reply_act = mapping_action(mcache_entry_mapping(mce)); OOR_LOG(LDBG_3, "vpp_get_fwd_entry: No locators"); return (ERR_NO_ROUTE); } if (glist_size(src_fwd_inf->ipv4_loct_lst)>0 && glist_size(dst_fwd_inf->ipv4_loct_lst)>0){ afi_support = IPv4_SUPPORT; } if (glist_size(src_fwd_inf->ipv6_loct_lst)>0 && glist_size(dst_fwd_inf->ipv6_loct_lst)>0){ afi_support = afi_support | IPv6_SUPPORT; } if (afi_support == (IPv4_SUPPORT | IPv6_SUPPORT)){ /* If we have support for both IP families but one of the is more * preferable, use only this one */ if (dst_fwd_inf->priority4 < dst_fwd_inf->priority6){ afi_support = IPv4_SUPPORT; }else if (dst_fwd_inf->priority4 > dst_fwd_inf->priority6){ afi_support = IPv6_SUPPORT; } } switch (afi_support){ case NO_AFI_SUPPOT: OOR_LOG(LDBG_3, "vpp_get_fwd_entry: Source and destination RLOCs are not compatible"); return (ERR_NO_ROUTE); case IPv4_SUPPORT: fwd_entry_vpp_fill (fwd_entry,src_fwd_inf->ipv4_loct_lst,dst_fwd_inf->ipv4_loct_lst, src_fwd_inf->sum_weight4, dst_fwd_inf->sum_weight4,dev_parm->loc_loct); break; case IPv6_SUPPORT: fwd_entry_vpp_fill (fwd_entry,src_fwd_inf->ipv6_loct_lst,dst_fwd_inf->ipv6_loct_lst, src_fwd_inf->sum_weight6, dst_fwd_inf->sum_weight6,dev_parm->loc_loct); break; default: //IPv4 and IPv6 compatibles fwd_entry_vpp_fill (fwd_entry,src_fwd_inf->ipv4_loct_lst,dst_fwd_inf->ipv4_loct_lst, src_fwd_inf->sum_weight4, dst_fwd_inf->sum_weight4,dev_parm->loc_loct); fwd_entry_vpp_fill (fwd_entry,src_fwd_inf->ipv6_loct_lst,dst_fwd_inf->ipv6_loct_lst, src_fwd_inf->sum_weight6, dst_fwd_inf->sum_weight6,dev_parm->loc_loct); } fwd_entry_vpp_dump(fwd_entry,LDBG_3); return (GOOD); } void fwd_entry_vpp_fill (fwd_entry_vpp_t *fwd_entry, glist_t *locl_loct_lst, glist_t *rmt_loct_lst, int weight_locl, int weight_rmt, glist_t *locl_rlocs_lst) { vpp_loct_pair *loct_pair; float factor, decimal = 0, aux_weight; int w_locl = 0, w_rmt = 0; glist_entry_t *locl_lst_elt, *rmt_lst_elt, *l_head, *r_head, *aux_elt; locator_t *locl_loct, *rmt_loct; lisp_addr_t *src_addr, *dst_addr, *src_ip_addr, *dst_ip_addr; factor = (float)weight_rmt / weight_locl; locl_lst_elt = glist_head(locl_loct_lst); rmt_lst_elt = glist_head(rmt_loct_lst); l_head = locl_lst_elt; r_head = rmt_lst_elt; while(1){ if (w_locl == 0){ locl_lst_elt = glist_next(locl_lst_elt); if (locl_lst_elt == l_head){ break; } locl_loct = glist_entry_data(locl_lst_elt); aux_weight = locator_weight(locl_loct)*factor; aux_elt = glist_next(locl_lst_elt); if (aux_elt == l_head){ // Is the last element of the list w_locl = (int)ceil(aux_weight + decimal); }else{ w_locl = (int)floor(aux_weight); decimal += (aux_weight - w_locl); if (decimal >= 1){ w_locl += 1; decimal -= 1; } } } if (w_rmt == 0){ rmt_lst_elt = glist_next(rmt_lst_elt); if (rmt_lst_elt == r_head){ break; } rmt_loct = glist_entry_data(rmt_lst_elt); w_rmt = locator_weight(rmt_loct); } src_addr = locator_addr(locl_loct); src_ip_addr = laddr_get_fwd_ip_addr(src_addr,locl_rlocs_lst); dst_addr = locator_addr(rmt_loct); dst_ip_addr = laddr_get_fwd_ip_addr(dst_addr,locl_rlocs_lst); if (w_rmt >= w_locl){ loct_pair = vpp_loct_pair_new_init(src_ip_addr,dst_ip_addr,w_locl); w_rmt = w_rmt - w_locl; w_locl = 0; }else{ loct_pair = vpp_loct_pair_new_init(src_ip_addr,dst_ip_addr,w_rmt); w_locl = w_locl - w_rmt; w_rmt = 0; } glist_add(loct_pair,fwd_entry->loc_pair_lst); } return; } oor-1.2.0/oor/fwd_policies/vpp_balancing/vpp_balancing.h000066400000000000000000000011331313612200500233250ustar00rootroot00000000000000/* * vpp_balancing.h * * Created on: Sep 14, 2016 * Author: alopez */ #ifndef OOR_FWD_POLICIES_VPP_BALANCING_VPP_BALANCING_H_ #define OOR_FWD_POLICIES_VPP_BALANCING_VPP_BALANCING_H_ #include "../../lib/generic_list.h" typedef struct vpp_dev_parm_ { oor_dev_type_e dev_type; glist_t * loc_loct; }vpp_dev_parm; typedef struct vpp_map_policy_inf_ { glist_t *ipv4_loct_lst; glist_t *ipv6_loct_lst; int priority4; int priority6; int sum_weight4; int sum_weight6; }vpp_map_policy_inf; #endif /* OOR_FWD_POLICIES_VPP_BALANCING_VPP_BALANCING_H_ */ oor-1.2.0/oor/iface_list.c000066400000000000000000000323671313612200500153620ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include #include #include #include #include "data-plane/data-plane.h" #include "control/oor_control.h" #include "net_mgr/net_mgr.h" #include "iface_list.h" #include "oor_external.h" #include "lib/prefixes.h" #include "lib/routing_tables_lib.h" #include "lib/sockets.h" #include "lib/shash.h" #include "lib/sockets-util.h" #include "lib/oor_log.h" /* List with all the interfaces used by OOR */ glist_t *interface_list = NULL; shash_t *iface_addr_ht = NULL; int ifaces_init() { interface_list = glist_new_managed((glist_del_fct)iface_destroy); iface_addr_ht = net_mgr->netm_build_addr_to_if_name_hasht(); if (!iface_addr_ht){ return (BAD); } return(GOOD); } void iface_destroy(iface_t *iface) { /* Close sockets */ if (iface->out_socket_v4 != -1) { close(iface->out_socket_v4); } if (iface->out_socket_v6 != -1) { close(iface->out_socket_v6); } /* Free data structure */ free(iface->iface_name); lisp_addr_del(iface->ipv4_address); lisp_addr_del(iface->ipv6_address); lisp_addr_del(iface->ipv4_gateway); lisp_addr_del(iface->ipv6_gateway); free(iface); } inline void ifaces_destroy() { glist_destroy(interface_list); shash_destroy(iface_addr_ht); } int iface_configure (iface_t *iface, int afi) { glist_t *addr_list; lisp_addr_t *addr, *gw; if (afi == AF_INET && default_rloc_afi == AF_INET6){ return (BAD); } if (afi == AF_INET6 && default_rloc_afi == AF_INET){ return (BAD); } /* Configure the gateway */ gw = iface_gateway(iface, afi); if (!gw){ gw = net_mgr->netm_get_iface_gw(iface->iface_name, afi); switch (afi) { case AF_INET: iface->ipv4_gateway = gw; break; case AF_INET6: iface->ipv6_gateway = gw; break; default: OOR_LOG(LDBG_2,"iface_setup: Unknown afi: %d", afi); return (ERR_AFI); } if (!gw || lisp_addr_is_no_addr(gw)) { OOR_LOG(LDBG_1,"iface_configure: No %s gateway found for interface %s", afi == AF_INET ? "IPv4" : "IPv6", iface->iface_name); }else { OOR_LOG(LDBG_1,"iface_configure: %s gateway found for interface %s: %s", afi == AF_INET ? "IPv4" : "IPv6", iface->iface_name,lisp_addr_to_char(gw)); data_plane->datap_add_iface_gw(iface,afi); lctrl->control_data_plane->control_dp_add_iface_gw(lctrl,iface,afi); } } /* Get the correct address of the interface */ if (!iface_address(iface, afi)){ /* If we don't have gateway, we use the first address of the list of addresses of the interface*/ if (!gw || lisp_addr_is_no_addr(gw)){ addr_list = net_mgr->netm_get_iface_addr_list(iface->iface_name, afi); if (glist_size(addr_list) == 0){ OOR_LOG(LDBG_1, "iface_configure: No %s RLOC configured for interface " "%s\n", (afi == AF_INET) ? "IPv4" : "IPv6", iface->iface_name); addr = lisp_addr_new_lafi(LM_AFI_NO_ADDR); goto end; } addr = (lisp_addr_t *)glist_first_data(addr_list); goto end; } addr = net_mgr->netm_get_src_addr_to(gw); if (!addr){ OOR_LOG(LDBG_1, "iface_configure: Gateway %s is not reachable. This should never happen", lisp_addr_to_char(gw)); addr = lisp_addr_new_lafi(LM_AFI_NO_ADDR); } }else{ return (GOOD); } end: switch (afi) { case AF_INET: iface->ipv4_address = addr; break; case AF_INET6: iface->ipv6_address = addr; break; default: OOR_LOG(LDBG_2,"iface_setup: Unknown afi: %d", afi); return (ERR_AFI); } /* Configure the new address in the contol and data plane */ if (!lisp_addr_is_no_addr(addr)) { OOR_LOG(LDBG_1,"iface_configure: %s address selected for interface %s: %s", afi == AF_INET ? "IPv4" : "IPv6", iface->iface_name,lisp_addr_to_char(addr)); data_plane->datap_add_iface_addr(iface,afi); lctrl->control_data_plane->control_dp_add_iface_addr(lctrl,iface,afi); } return (GOOD); } char * iface_to_char(iface_t *iface) { static char buf[5][500]; static int i=0; if (iface == NULL){ sprintf(buf[i], "_NULL_"); return (buf[i]); } /* hack to allow more than one locator per line */ i++; i = i % 5; snprintf(buf[i],sizeof(buf[i]), "Iface: %s (%s), IPv4 addr: %s, IPv4 gw: %s, " "socket: %d, IPv6 addr: %s, IPv6 gw: %s, socket: %d", iface->iface_name, iface->status ? "Up" : "Down", lisp_addr_to_char(iface->ipv4_address),lisp_addr_to_char(iface->ipv4_gateway), iface->out_socket_v4, lisp_addr_to_char(iface->ipv6_address),lisp_addr_to_char(iface->ipv6_gateway), iface->out_socket_v6); return (buf[i]); } /* Return the interface if it already exists. If it doesn't exist, * create and add an interface element to the list of interfaces. * To configure address use iface_setup_addr after */ iface_t * add_interface(char *iface_name) { iface_t *iface; if (net_mgr->netm_get_iface_index(iface_name) == 0) { OOR_LOG(LERR, "Configuration file: INVALID INTERFACE or not initialized " "virtual interface: %s ", iface_name); return(NULL); } /* Creating the new interface*/ iface = xzalloc(sizeof(iface_t)); iface->iface_name = strdup(iface_name); /* MUST FREE */ iface->iface_index = net_mgr->netm_get_iface_index(iface_name); /* set up all fields to default, null values */ iface->ipv4_address = NULL; iface->ipv6_address = NULL; iface->out_socket_v4 = ERR_SOCKET; iface->out_socket_v6 = ERR_SOCKET; iface->status = net_mgr->netm_get_iface_status(iface_name); if (iface->status != UP){ iface->status = DOWN; } OOR_LOG(LDBG_1, "Adding interface %s with index %d to iface list", iface_name, iface->iface_index); iface->ipv4_gateway = NULL; iface->ipv6_gateway = NULL; /* Add iface to the list */ glist_add(iface,interface_list); OOR_LOG(LDBG_2, "Interface %s with index %d added to interfaces lists\n", iface_name, iface->iface_index); return (iface); } /* Look up an interface based in the iface_name. * Return the iface element if it is found or NULL if not. */ iface_t * get_interface(char *iface_name) { glist_entry_t * iface_it; iface_t * iface; iface_t * find_iface = NULL; glist_for_each_entry(iface_it,interface_list){ iface = (iface_t *)glist_entry_data(iface_it); if (strcmp(iface->iface_name, iface_name) == 0) { find_iface = iface; break; } } return (find_iface); } /* Look up an interface based in the index of the iface. * Return the iface element if it is found or NULL if not. */ iface_t * get_interface_from_index(int iface_index) { glist_entry_t * iface_it; iface_t * iface; iface_t * find_iface = NULL; glist_for_each_entry(iface_it,interface_list){ iface = (iface_t *)glist_entry_data(iface_it); if (iface->iface_index == 0) { iface->iface_index = net_mgr->netm_get_iface_index(iface->iface_name); } if (iface->iface_index == iface_index) { find_iface = iface; break; } } return (find_iface); } /* Return the interface having assigned the address passed as a parameter */ iface_t * get_interface_with_address(lisp_addr_t *address) { glist_entry_t * iface_it; iface_t * iface; glist_for_each_entry(iface_it,interface_list){ iface = (iface_t *)glist_entry_data(iface_it); switch (lisp_addr_ip_afi(address)) { case AF_INET: if (iface->ipv4_address && lisp_addr_cmp(address, iface->ipv4_address) == 0) { return (iface); } break; case AF_INET6: if (iface->ipv6_address && lisp_addr_cmp(address, iface->ipv6_address) == 0) { return (iface); } break; } } OOR_LOG(LDBG_2,"get_interface_with_address: No interface found for the address %s", lisp_addr_to_char(address)); return (NULL); } int * get_out_socket_ptr_from_address(lisp_addr_t *address) { iface_t * iface; int afi; afi = lisp_addr_ip_afi(address); iface = get_interface_with_address(address); if (iface == NULL){ return (NULL); } return(iface_socket_pointer(iface, afi)); } /* * Print the interfaces and locators of the lisp node */ void iface_list_to_char(int log_level) { glist_entry_t * iface_it; iface_t * iface; char str[4000]; size_t str_size = sizeof(str); if ((interface_list != NULL && glist_size(interface_list) == 0) || is_loggable(log_level) == FALSE) { return; } sprintf(str, "*** LISP RLOC Interfaces List ***\n\n"); glist_for_each_entry(iface_it,interface_list){ iface = (iface_t *)glist_entry_data(iface_it); snprintf(str + strlen(str),str_size - strlen(str),"== %s (%s)==\n", iface->iface_name, iface->status ? "Up" : "Down"); if (iface->ipv4_address) { snprintf(str + strlen(str),str_size - strlen(str), " IPv4 RLOC: %s \n", lisp_addr_to_char(iface->ipv4_address)); } if (iface->ipv6_address) { snprintf(str + strlen(str),str_size - strlen(str), " IPv6 RLOC: %s \n", lisp_addr_to_char(iface->ipv6_address)); } } OOR_LOG(log_level, "%s", str); } /* Search the iface list for the first UP iface that has an 'afi' address*/ iface_t * get_any_output_iface(int afi) { glist_entry_t * iface_it; iface_t * iface; iface_t * find_iface = NULL; switch (afi) { case AF_INET: glist_for_each_entry(iface_it,interface_list){ iface = (iface_t *)glist_entry_data(iface_it); if (iface->ipv4_address && !lisp_addr_is_no_addr(iface->ipv4_address) && (iface->status == UP)) { find_iface = iface; break; } } break; case AF_INET6: glist_for_each_entry(iface_it,interface_list){ iface = (iface_t *)glist_entry_data(iface_it); if (iface->ipv6_address && !lisp_addr_is_no_addr(iface->ipv6_address) && (iface->status == UP)) { find_iface = iface; break; } } break; default: OOR_LOG(LDBG_2, "get_output_iface: unknown afi %d", afi); break; } return (find_iface); } lisp_addr_t * iface_address(iface_t *iface, int afi) { lisp_addr_t *addr = NULL; switch (afi) { case AF_INET: addr = iface->ipv4_address; break; case AF_INET6: addr = iface->ipv6_address; break; } return (addr); } lisp_addr_t * iface_gateway(iface_t *iface, int afi) { lisp_addr_t *gw = NULL; switch (afi) { case AF_INET: gw = iface->ipv4_gateway; break; case AF_INET6: gw = iface->ipv6_gateway; break; } return (gw); } int iface_socket(iface_t *iface, int afi) { int out_socket = ERR_SOCKET; switch(afi){ case AF_INET: out_socket = iface->out_socket_v4; break; case AF_INET6: out_socket = iface->out_socket_v6; break; default: break; } return (out_socket); } int * iface_socket_pointer(iface_t *iface, int afi) { int * out_socket = NULL; switch(afi){ case AF_INET: out_socket = &(iface->out_socket_v4); break; case AF_INET6: out_socket = &(iface->out_socket_v6); break; default: out_socket = NULL; break; } return (out_socket); } /* * This function should only be used during the configuration process */ char * get_interface_name_from_address(lisp_addr_t *addr) { char *iface; if (lisp_addr_lafi(addr) != LM_AFI_IP) { OOR_LOG(LDBG_1, "get_interface_name_from_address: failed for %s. Function" " only supports IP syntax addresses!", lisp_addr_to_char(addr)); return(NULL); } iface = shash_lookup(iface_addr_ht, lisp_addr_to_char(addr)); if (iface) { return(iface); } else { return(NULL); } } /* * Editor modelines * * vi: set shiftwidth=4 tabstop=4 expandtab: * :indentSize=4:tabSize=4:noTabs=true: */ oor-1.2.0/oor/iface_list.h000066400000000000000000000044511313612200500153600ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef IFACE_LIST_H_ #define IFACE_LIST_H_ #include "liblisp/lisp_mapping.h" #include "defs.h" #include "lib/timers.h" /* Interface structure * =================== * Locator address (rloc) is linked to the interface address. If the address * of the interface changes, the locator address changes automatically */ typedef struct iface { char *iface_name; uint32_t iface_index; uint8_t status; lisp_addr_t *ipv4_address; lisp_addr_t *ipv6_address; lisp_addr_t *ipv4_gateway; lisp_addr_t *ipv6_gateway; int out_socket_v4; int out_socket_v6; } iface_t; extern glist_t *interface_list; // extern shash_t *iface_addr_ht; int ifaces_init(); void iface_destroy(iface_t *iface); void ifaces_destroy(); int iface_configure (iface_t *iface, int afi); char *iface_to_char(iface_t *iface); iface_t *add_interface(char *iface_name); iface_t *get_interface(char *iface_name); iface_t *get_interface_from_index(int iface_index); iface_t *get_interface_with_address(lisp_addr_t *address); int *get_out_socket_ptr_from_address(lisp_addr_t *address); /* Print the interfaces and locators of the lisp node */ void iface_list_to_char(int log_level); iface_t *get_any_output_iface(int); lisp_addr_t *iface_address(iface_t *iface, int afi); lisp_addr_t *iface_gateway(iface_t *iface, int afi); int iface_socket(iface_t *iface, int afi); int *iface_socket_pointer(iface_t *iface, int afi); static uint8_t iface_status(iface_t *iface); char *get_interface_name_from_address(lisp_addr_t *addr); static inline uint8_t iface_status(iface_t *iface) { return (iface->status); } #endif /*IFACE_LIST_H_*/ oor-1.2.0/oor/lib/000077500000000000000000000000001313612200500136475ustar00rootroot00000000000000oor-1.2.0/oor/lib/cksum.c000066400000000000000000000075621313612200500151470ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "cksum.h" #include "oor_log.h" #include "../liblisp/lisp_messages.h" #include #include #include #include uint16_t ip_checksum(uint16_t *buffer, int size) { uint32_t cksum = 0; while (size > 1) { cksum += *buffer++; size -= sizeof(uint16_t); } if (size) { cksum += *(uint8_t *) buffer; } cksum = (cksum >> 16) + (cksum & 0xffff); cksum += (cksum >> 16); return ((uint16_t) (~cksum)); } /* * * Calculate the IPv4 UDP checksum (calculated with the whole packet). * * Parameters: * * buff - pointer to the UDP header * len - the UDP packet length. * src - the IP source address (in network format). * dest - the IP destination address (in network format). * * Returns: The result of the checksum * */ uint16_t udp_ipv4_checksum(const void *b, unsigned int len, in_addr_t src, in_addr_t dst) { const uint16_t *buf = b; uint16_t *ip_src = (void *) &src; uint16_t *ip_dst = (void *) &dst; uint32_t length = len; uint32_t sum = 0; while (len > 1) { sum += *buf++; if (sum & 0x80000000) sum = (sum & 0xFFFF) + (sum >> 16); len -= 2; } /* Add the padding if the packet length is odd */ if (len & 1) sum += *((uint8_t *) buf); /* Add the pseudo-header */ sum += *(ip_src++); sum += *ip_src; sum += *(ip_dst++); sum += *ip_dst; sum += htons(IPPROTO_UDP); sum += htons(length); /* Add the carries */ while (sum >> 16) sum = (sum & 0xFFFF) + (sum >> 16); /* Return the one's complement of sum */ return ((uint16_t) (~sum)); } uint16_t udp_ipv6_checksum(const struct ip6_hdr *ip6, const struct udphdr *up, unsigned int len) { size_t i; register const u_int16_t *sp; uint32_t sum; union { struct { struct in6_addr ph_src; struct in6_addr ph_dst; u_int32_t ph_len; u_int8_t ph_zero[3]; u_int8_t ph_nxt; } ph; u_int16_t pa[20]; } phu; /* pseudo-header */ memset(&phu, 0, sizeof(phu)); phu.ph.ph_src = ip6->ip6_src; phu.ph.ph_dst = ip6->ip6_dst; phu.ph.ph_len = htonl(len); phu.ph.ph_nxt = IPPROTO_UDP; sum = 0; for (i = 0; i < sizeof(phu.pa) / sizeof(phu.pa[0]); i++) sum += phu.pa[i]; sp = (const u_int16_t *) up; for (i = 0; i < (len & ~1); i += 2) sum += *sp++; if (len & 1) sum += htons((*(const u_int8_t *) sp) << 8); while (sum > 0xffff) sum = (sum & 0xffff) + (sum >> 16); sum = ~sum & 0xffff; return (sum); } /* * upd_checksum * * Calculate the IPv4 or IPv6 UDP checksum */ uint16_t udp_checksum(struct udphdr *udph, int udp_len, void *iphdr, int afi) { switch (afi) { case AF_INET: return (udp_ipv4_checksum(udph, udp_len, ((struct ip *) iphdr)->ip_src.s_addr, ((struct ip *) iphdr)->ip_dst.s_addr)); case AF_INET6: return (udp_ipv6_checksum(iphdr, udph, udp_len)); default: OOR_LOG(LDBG_2, "udp_checksum: Unknown AFI"); return (~0); } } oor-1.2.0/oor/lib/cksum.h000066400000000000000000000017531313612200500151500ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef CKSUM_H_ #define CKSUM_H_ #include #include #include "../defs.h" uint16_t ip_checksum(uint16_t *buffer, int size); /* Calculate the IPv4 or IPv6 UDP checksum */ uint16_t udp_checksum(struct udphdr *udph, int udp_len, void *iphdr, int afi); #endif /* CKSUM_H_ */ oor-1.2.0/oor/lib/generic_list.c000066400000000000000000000205671313612200500164740ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include #include "generic_list.h" #include "oor_log.h" #include "mem_util.h" void glist_init_complete(glist_t *lst, glist_cmp_fct cmp_fct, glist_del_fct del_fct) { lst->cmp_fct = cmp_fct; lst->del_fct = del_fct; lst->size = 0; list_init(&(lst->head.list)); } void glist_init(glist_t *lst) { glist_init_complete(lst, NULL, NULL); } void glist_init_managed(glist_t *lst, glist_del_fct del_fct) { glist_init_complete(lst, NULL, del_fct); } /** * glist_new_complete - initializes the list * @cmp_fct: function to compare to data entries * @del_fct: function to deallocate a data entry */ glist_t * glist_new_complete(glist_cmp_fct cmp_fct, glist_del_fct del_fct) { glist_t *glist = NULL; glist = xzalloc(sizeof(glist_t)); glist_init_complete(glist, cmp_fct, del_fct); return(glist); } glist_t * glist_new(void) { return(glist_new_complete(NO_CMP, NO_DEL)); } /* memory managed. when destroy is called all inner data is freed*/ glist_t * glist_new_managed(glist_del_fct del) { return(glist_new_complete(NO_CMP, del)); } inline glist_cmp_fct glist_get_cmp_fct(glist_t *lst) { return (lst->cmp_fct); } inline glist_del_fct glist_get_del_fct(glist_t *lst) { return (lst->del_fct); } inline void glist_set_cmp_fct(glist_t *lst, glist_cmp_fct cmp_fct) { lst->cmp_fct = cmp_fct; } inline void glist_set_del_fct(glist_t *lst, glist_del_fct del_fct) { lst->del_fct = del_fct; } /* Use the indicated clone function to obtain a clone of the list */ glist_t * glist_clone(glist_t *src_list, glist_clone_obj clone_obj) { glist_t *list; glist_entry_t *it; void *obj; list = glist_new_complete(src_list->cmp_fct,src_list->del_fct); glist_for_each_entry(it, src_list){ obj = glist_entry_data(it); glist_add(clone_obj(obj),list); } return (list); } /** * glist_add - insert new value to the list * @data: new value to be added * @glist: list where data is to be inserteds * * Append a new entry to the list. * If cmp_fct is defined, it seeks incrementally, starting * at the head head. */ int glist_add(void *data, glist_t *glist) { glist_entry_t *new = NULL; glist_entry_t *tmp = NULL; int ctr = 0; int cmp = 0; new = xzalloc(sizeof(glist_entry_t)); new->data = data; list_init(&new->list); if (!glist->cmp_fct) { list_push_front(&glist->head.list, &new->list); } else { if (glist->size != 0) { glist_for_each_entry(tmp,glist){ /* insert where new element is bigger than current one */ cmp = (*glist->cmp_fct)(data, tmp->data); if( cmp == 2){ break; }else if (cmp < 0){ free(new); return (BAD); } ctr++; } if (ctr != glist->size){ list_push_front(tmp->list.prev, &new->list); }else{ // Add at the end of the list list_push_back(&(glist->head.list), &(new->list)); } }else{ list_push_front( &glist->head.list, &new->list); } } glist->size++; return(GOOD); } /** * glist_add_tail - insert new value to the list * @data: new value to be added * @glist: list where data is to be inserted * * Append a new entry to the end of the list. * If cmp_fct is defined, the element is not added */ int glist_add_tail(void *data, glist_t *glist) { glist_entry_t *new = NULL; if (glist->cmp_fct) { return(BAD); } new = xzalloc(sizeof(glist_entry_t)); new->data = data; list_init(&(new->list)); list_push_back(&(glist->head.list), &(new->list)); glist->size++; return(GOOD); } uint8_t glist_contain(void *data, glist_t *list) { glist_entry_t *entry = NULL; if (list->size == 0){ return (FALSE); } glist_for_each_entry(entry,list){ if(list->cmp_fct) { if((*list->cmp_fct)(data, entry->data) == 0){ return(TRUE); } }else{ if(entry->data == data){ return(TRUE); } } } return(FALSE); } uint8_t glist_contain_using_cmp_fct(void *data, glist_t *list,glist_cmp_fct cmp_fct) { glist_entry_t *entry = NULL; if (list->size == 0){ return (FALSE); } glist_for_each_entry(entry,list){ if(cmp_fct) { if((*cmp_fct)(data, entry->data) == 0){ return(TRUE); } }else{ if(entry->data == data){ return(TRUE); } } } return(FALSE); } void glist_dump(glist_t *list, glist_to_char_fct dump_fct, int log_level) { glist_entry_t * it = NULL; void * data = NULL; int ctr = 0; glist_for_each_entry(it,list){ ctr++; data = glist_entry_data (it); OOR_LOG(log_level,"[%d] => %s",ctr,dump_fct(data)); } } /** * glist_extract - remove entry from list without deleting object * @entry: entry to be removed * @list: list from which the entry is to be removed */ void glist_extract(glist_entry_t *entry, glist_t *list) { if (!entry || !list) { return; } list_remove(&(entry->list)); free(entry); list->size--; } /** * glist_remove - remove entry from list * @entry: entry to be removed * @list: list from which the entry is to be removed * * If del_fct is defined, entry->data will be freed using it * */ void glist_remove(glist_entry_t *entry, glist_t *list) { if (!entry || !list) { return; } list_remove(&(entry->list)); if(list->del_fct) { (*list->del_fct)(entry->data); } free(entry); list->size--; } /** * glist_remove_obj - remove object from list. The comparison function is used to get the entry to * be removed. If comparition function is not deffined, the value of the pointer is used to get the * elemnt to be removed * @data: object to be removed * @list: list from which the entry is to be removed */ void glist_remove_obj(void *data, glist_t *list) { glist_entry_t *remove_entry = NULL; glist_entry_t *entry; if (!list || list->size == 0) { return; } if(list->cmp_fct) { glist_for_each_entry(entry,list){ if((*list->cmp_fct)(data, entry->data) == 0){ remove_entry = entry; break; } } }else{ glist_for_each_entry(entry,list){ if(entry->data == data){ remove_entry = entry; break; } } } if (remove_entry != NULL){ glist_remove(remove_entry,list); } } /** * glist_remove_obj_with_ptr - remove object from list. The comparison function is * used to get the entry to be removed. IThe value of the pointer is used to get the * elemnt to be removed * @data: object to be removed * @list: list from which the entry is to be removed */ void glist_remove_obj_with_ptr(void *data, glist_t *list) { glist_entry_t *remove_entry = NULL; glist_entry_t *entry; if (!list || list->size == 0) { return; } glist_for_each_entry(entry,list){ if(entry->data == data){ remove_entry = entry; break; } } if (remove_entry != NULL){ glist_remove(remove_entry,list); } } void glist_remove_all(glist_t *lst) { glist_entry_t *tmp, *aux_tmp; if (!lst || lst->size == 0) { return; } glist_for_each_entry_safe(tmp, aux_tmp, lst) { glist_remove(tmp, lst); } } void glist_destroy(glist_t *lst) { if (!lst) { return; } glist_remove_all(lst); free(lst); } oor-1.2.0/oor/lib/generic_list.h000066400000000000000000000111041313612200500164640ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef GENERIC_LIST_H_ #define GENERIC_LIST_H_ #include #include "../elibs/ovs/list.h" #define NO_CMP NULL #define NO_DEL NULL typedef void (*glist_del_fct)(void *); /* * Return: * -1 if error in the comparison * 0 if both elements are equal * 1 if first element is bigger than the second one * 2 if second element is bigger than the first one */ typedef int (*glist_cmp_fct)(void *, void *); typedef char *(*glist_to_char_fct)(void *); typedef void *(*glist_clone_obj)(void *); typedef struct glist_entry_t_ { struct ovs_list list; void *data; } glist_entry_t; typedef struct { glist_entry_t head; int size; glist_cmp_fct cmp_fct; glist_del_fct del_fct; } glist_t; glist_t *glist_new(void); glist_t *glist_new_managed(glist_del_fct); glist_t *glist_new_complete(glist_cmp_fct, glist_del_fct); void glist_init_complete(glist_t *, glist_cmp_fct, glist_del_fct); void glist_init(glist_t *); void glist_init_managed(glist_t *lst, glist_del_fct del_fct); glist_cmp_fct glist_get_cmp_fct(glist_t *lst); glist_del_fct glist_get_del_fct(glist_t *lst); void glist_set_cmp_fct(glist_t *lst, glist_cmp_fct cmp_fct); void glist_set_del_fct(glist_t *lst, glist_del_fct del_fct); glist_t *glist_clone(glist_t *, glist_clone_obj clone_obj); int glist_add(void *data, glist_t *list); int glist_add_tail(void *data, glist_t *glist); uint8_t glist_contain(void *data, glist_t *list); uint8_t glist_contain_using_cmp_fct(void *data, glist_t *list, glist_cmp_fct cmp_fct); void glist_extract(glist_entry_t *entry, glist_t *list); void glist_remove(glist_entry_t *entry, glist_t *list); void glist_remove_obj(void * data,glist_t * list); void glist_remove_obj_with_ptr(void * data, glist_t * list); void glist_dump(glist_t *list, glist_to_char_fct dump_fct, int log_level); void glist_destroy(glist_t *lst); void glist_remove_all(glist_t *lst); static inline int glist_size(glist_t *list) { return(list->size); } static inline void * glist_entry_data(glist_entry_t *entry) { return(entry->data); } static inline glist_entry_t * glist_head(glist_t *lst) { return(&lst->head); } static inline glist_entry_t * glist_next(glist_entry_t *entry) { return(CONTAINER_OF(entry->list.next, glist_entry_t, list)); } static inline glist_entry_t * glist_prev(glist_entry_t *entry) { return(CONTAINER_OF(entry->list.prev, glist_entry_t, list)); } static inline glist_entry_t * glist_first(glist_t *lst) { if (lst->size == 0){ return (NULL); } //return (CONTAINER_OF(glist_next(&lst->head), glist_entry_t, list)); return (glist_next(&lst->head)); } static inline void * glist_first_data(glist_t *lst) { if (lst->size == 0){ return (NULL); } return(glist_entry_data(glist_first(lst))); } static inline glist_entry_t * glist_last(glist_t *lst) { if (lst->size == 0){ return (NULL); } //return (CONTAINER_OF(glist_prev(&lst->head), glist_entry_t, list)); return (glist_prev(&lst->head)); } static inline void * glist_last_data(glist_t *lst) { return(glist_entry_data(glist_last(lst))); } /** * generic_list_for_each_entry - iterates over list in generic_list_t * @ iter: * of glist_entry_t type, to use as loop iterator * @ lst: * the list of glist_t type, over whose elements to iterate */ #define glist_for_each_entry(iter_, lst_) \ LIST_FOR_EACH(iter_,list,&((lst_)->head.list)) /** * generic_list_for_each_entry - iterates over list in generic_list_t * safe against removal of list entry * @ iter: * of glist_entry_t type, to use as loop iterator * @ aux_iter: * of glist_entry_t type, to use as temporary storage * @ lst: * the list of glist_t type, over whose elements to iterate */ #define glist_for_each_entry_safe(iter_, aux_iter_, lst_) \ LIST_FOR_EACH_SAFE(iter_, aux_iter_, list,&((lst_)->head.list)) #endif /* GENERIC_LIST_H_ */ oor-1.2.0/oor/lib/hmac.c000066400000000000000000000063571313612200500147360ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include #include "hmac.h" #include "oor_log.h" #include "../elibs/mbedtls/md.h" #include "../liblisp/lisp_message_fields.h" /* * Compute and fill auth data field * * TODO Support more than SHA1 */ int complete_auth_fields(uint8_t key_id, const char *key, void *packet, size_t pckt_len, void *auth_data_pos) { const mbedtls_md_info_t *md_info; mbedtls_md_type_t md_type; size_t auth_data_len; switch (key_id) { case HMAC_SHA_1_96: md_type = MBEDTLS_MD_SHA1; auth_data_len = SHA1_AUTH_DATA_LEN; break; default: OOR_LOG(LDBG_2, "complete_auth_fields: HMAC unknown key type: %d", (int)key_id); return(BAD); } md_info = mbedtls_md_info_from_type(md_type); memset(auth_data_pos,0,auth_data_len); if (mbedtls_md_hmac(md_info, (const unsigned char *)key, strlen(key), (const unsigned char *)packet, pckt_len, (unsigned char *)auth_data_pos) != 0){ OOR_LOG(LDBG_2, "complete_auth_fields: Error using mbedtls"); return (BAD); } return (GOOD); } int check_auth_field(uint8_t key_id, const char *key, void *packet, size_t pckt_len, void *auth_data_pos) { size_t auth_data_len; uint8_t* auth_data_copy; const mbedtls_md_info_t *md_info; mbedtls_md_type_t md_type; switch (key_id) { case HMAC_SHA_1_96: md_type = MBEDTLS_MD_SHA1; auth_data_len = SHA1_AUTH_DATA_LEN; break; default: OOR_LOG(LDBG_2, "complete_auth_fields: HMAC unknown key type: %d", (int)key_id); return(BAD); } auth_data_copy = (uint8_t *) xmalloc(auth_data_len*sizeof(uint8_t)); if (auth_data_copy == NULL) { OOR_LOG(LERR, "check_sha1_hmac: malloc() failed"); return(ERR_MALLOC); } /* Copy the data to another location and put 0's on the auth data field of the packet */ memcpy(auth_data_copy,auth_data_pos,auth_data_len); memset(auth_data_pos,0,auth_data_len); md_info = mbedtls_md_info_from_type(md_type); if (mbedtls_md_hmac(md_info, (const unsigned char *)key, strlen(key), (const unsigned char *)packet, pckt_len, (unsigned char *)auth_data_pos) != 0){ OOR_LOG(LDBG_2, "check_auth_field: Error using mbedtls"); return (BAD); } if ((strncmp((char *)auth_data_pos, (char *)auth_data_copy, auth_data_len)) == 0) { free(auth_data_copy); return(GOOD); } else { free(auth_data_copy); return(BAD); } } oor-1.2.0/oor/lib/hmac.h000066400000000000000000000020761313612200500147350ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef HMAC_H_ #define HMAC_H_ #include #define SHA1_AUTH_DATA_LEN 20 #define SHA256_AUTH_DATA_LEN 32 int complete_auth_fields(uint8_t key_id, const char *key, void *packet, size_t pckt_len, void *auth_data_pos); int check_auth_field(uint8_t key_id, const char *key, void *packet, size_t pckt_len, void *auth_data_pos); #endif /* HMAC_H_ */ oor-1.2.0/oor/lib/iface_locators.c000066400000000000000000000156141313612200500167770ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "../defs.h" #include "../iface_list.h" #include "iface_locators.h" #include "oor_log.h" #include "sockets.h" iface_locators *iface_locators_get_element_with_loct(shash_t *iface_locators_table, locator_t *locator); /* * Creates and initialize a new iface_locator * @param iface_name Name of the interface * @return iface_locators element */ iface_locators * iface_locators_new(char *iface_name) { iface_locators *if_loct; if_loct = xzalloc(sizeof(iface_locators)); if_loct->iface_name = xstrdup(iface_name); if_loct->map_loc_entries = glist_new(); if_loct->ipv4_locators = glist_new(); if_loct->ipv6_locators = glist_new(); if_loct->status_changed = TRUE; if_loct->ipv4_prev_addr = NULL; if_loct->ipv6_prev_addr = NULL; return(if_loct); } /* * Release memory of an iface_locators structure * @param if_loct Element to be released */ void iface_locators_del(iface_locators *if_loct) { free(if_loct->iface_name); glist_destroy(if_loct->map_loc_entries); glist_destroy(if_loct->ipv4_locators); glist_destroy(if_loct->ipv6_locators); if (if_loct->ipv4_prev_addr != NULL){ lisp_addr_del(if_loct->ipv4_prev_addr); } if (if_loct->ipv6_prev_addr != NULL){ lisp_addr_del(if_loct->ipv6_prev_addr); } free(if_loct); } void iface_locators_attach_map_local_entry(shash_t *iface_locators_table, map_local_entry_t * map_loc_e) { mapping_t * mapping; locator_t * locator; iface_locators * iface_loct; mapping = map_local_entry_mapping(map_loc_e); mapping_foreach_locator(mapping,locator){ iface_loct = iface_locators_get_element_with_loct( iface_locators_table, locator); if (iface_loct != NULL && glist_contain(map_loc_e, iface_loct->map_loc_entries) == FALSE){ glist_add(map_loc_e, iface_loct->map_loc_entries); } }mapping_foreach_locator_end; } void iface_locators_unattach_mapping_and_loct(shash_t *iface_locators_table, map_local_entry_t * map_loc_e) { glist_t *iface_loct_list; glist_entry_t *it_if_loct; iface_locators *iface_loct; mapping_t *mapping; locator_t *locator; mapping = map_local_entry_mapping(map_loc_e); mapping_foreach_locator(mapping,locator){ iface_locators_unattach_locator(iface_locators_table, locator); }mapping_foreach_locator_end; iface_loct_list = shash_values(iface_locators_table); glist_for_each_entry(it_if_loct,iface_loct_list){ iface_loct = (iface_locators *)glist_entry_data(it_if_loct); glist_remove_obj(map_loc_e,iface_loct->map_loc_entries); } } /* * Remove a locator from the structure iface_locators associated to it. */ void iface_locators_unattach_locator(shash_t *iface_locators_table, locator_t *locator) { lisp_addr_t * ip_addr; lisp_addr_t * addr = locator_addr(locator); iface_locators * iface_loct; glist_t * loct_lists[2]; glist_entry_t * it_loct; locator_t * loct; int ctr; uint16_t afi = AF_UNSPEC; /* Get structure from where the locator is removed */ iface_loct = iface_locators_get_element_with_loct(iface_locators_table,locator); if (iface_loct == NULL){ return; } if (lisp_addr_is_no_addr(addr) == FALSE){ ip_addr = lisp_addr_get_ip_addr(addr); if (ip_addr == NULL) { OOR_LOG(LERR, "unattach_locator_from_iface: Can't determine RLOC's IP " "address %s", lisp_addr_to_char(addr)); return; } afi = lisp_addr_ip_afi(ip_addr); }else{ loct_lists[0] = iface_loct->ipv4_locators; loct_lists[1] = iface_loct->ipv6_locators; for (ctr=0;ctr<2;ctr++){ glist_for_each_entry(it_loct,loct_lists[ctr]){ loct = (locator_t *)glist_entry_data(it_loct); if (loct == locator){ if (ctr == 0){ afi = AF_INET; }else{ afi = AF_INET6; } break; } } if (afi != AF_UNSPEC){ break; } } } switch (afi){ case AF_INET: glist_remove_obj(locator,iface_loct->ipv4_locators); break; case AF_INET6: glist_remove_obj(locator,iface_loct->ipv6_locators); break; } return; } iface_locators * iface_locators_get_element_with_loct(shash_t *iface_locators_table, locator_t *locator) { glist_t * iface_loct_list; glist_entry_t * it; glist_entry_t * it_loct; iface_locators * iface_loct; glist_t * loct_lists[2]; locator_t * loct; lisp_addr_t * addr = locator_addr(locator); lisp_addr_t * ip_addr; char * iface_name; int ctr; if (lisp_addr_is_no_addr(addr) == FALSE) { ip_addr = lisp_addr_get_ip_addr(addr); if (ip_addr == NULL) { OOR_LOG(LERR, "iface_locators_get_element_with_loct: Can't determine RLOC's IP " "address %s", lisp_addr_to_char(addr)); return (NULL); } /* Find the interface name associated to the RLOC */ iface_name = get_interface_name_from_address(ip_addr); if (iface_name == NULL){ OOR_LOG(LERR, "iface_locators_get_element_with_loct: Can't find iface associated to " "address %s", lisp_addr_to_char(addr)); return (NULL); } /* Get iface-locators structure and add the mapping */ iface_loct = shash_lookup(iface_locators_table, iface_name); return (iface_loct); }else{ iface_loct_list = shash_values(iface_locators_table); glist_for_each_entry(it,iface_loct_list){ iface_loct = (iface_locators *)glist_entry_data(it); loct_lists[0] = iface_loct->ipv4_locators; loct_lists[1] = iface_loct->ipv6_locators; for (ctr=0;ctr<2;ctr++){ glist_for_each_entry(it_loct,loct_lists[ctr]){ loct = (locator_t *)glist_entry_data(it_loct); if (loct == locator){ glist_destroy(iface_loct_list); return (iface_loct); } } } } } glist_destroy(iface_loct_list); return (NULL); } oor-1.2.0/oor/lib/iface_locators.h000066400000000000000000000037101313612200500167760ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef IFACE_LOCATORS_H_ #define IFACE_LOCATORS_H_ #include "map_local_entry.h" #include "shash.h" #include "../liblisp/liblisp.h" typedef struct iface_locators_{ char *iface_name; glist_t *map_loc_entries; /*Mappings associated to this iface */ glist_t *ipv4_locators; /*IPv4 locators associated with this iface */ glist_t *ipv6_locators; /*IPv6 locators associated with this iface */ uint8_t status_changed; /*Iface change status --> Used to avioid transitions*/ lisp_addr_t *ipv4_prev_addr; /*Previous IPv4 address of the iface --> Used to avoid transitions A->B->A*/ lisp_addr_t *ipv6_prev_addr; /*Previous IPv6 address of the iface --> Used to avoid transitions A->B->A*/ }iface_locators; iface_locators *iface_locators_new(char *iface_name); void iface_locators_del(iface_locators *if_loct); void iface_locators_attach_map_local_entry( shash_t * iface_locators_table, map_local_entry_t * map_loc_e); void iface_locators_unattach_mapping_and_loct(shash_t *iface_locators_table, map_local_entry_t * map_loc_e); void iface_locators_unattach_locator(shash_t *iface_locators_table, locator_t *locator); #endif /* IFACE_LOCATORS_H_ */ oor-1.2.0/oor/lib/int_table.c000066400000000000000000000045631313612200500157640ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "int_table.h" #include "mem_util.h" int_htable * int_htable_new() { int_htable *ht; ht =xcalloc(1,sizeof(int_htable)); ht->htable = kh_init(int); return(ht); } int_htable * int_htable_new_managed(free_value_fn_t df) { int_htable *ht; ht =xcalloc(1,sizeof(int_htable)); ht->htable = kh_init(int); ht->free_value_fn = df; return(ht); } void int_htable_insert(int_htable *ht, int key, void *val) { khiter_t k; int ret; k = kh_put(int,ht->htable,key,&ret); kh_value(ht->htable, k) = val; } void int_htable_remove(int_htable *ht, int key) { khiter_t k; k = kh_get(int,ht->htable, key); if (k == kh_end(ht->htable)){ return; } if (ht->free_value_fn){ ht->free_value_fn(kh_value(ht->htable,k)); } kh_del(int,ht->htable,k); } void * int_htable_lookup(int_htable *ht, int key) { khiter_t k; k = kh_get(int,ht->htable, key); if (k == kh_end(ht->htable)){ return (NULL); } return (kh_value(ht->htable,k)); } void int_htable_destroy(int_htable *ht) { khiter_t k; if (!ht) { return; } for (k = kh_begin(sh->htable); k != kh_end(ht->htable); ++k){ if (kh_exist(ht->htable, k)){ if (ht->free_value_fn){ ht->free_value_fn(kh_value(ht->htable,k)); } } } kh_destroy(int, ht->htable); free(ht); } glist_t *int_htable_values(int_htable *ht) { glist_t *list; khiter_t k; list = glist_new(); for (k = kh_begin(sh->htable); k != kh_end(ht->htable); ++k){ if (kh_exist(ht->htable, k)){ glist_add(kh_value(ht->htable,k), list); } } return (list); } oor-1.2.0/oor/lib/int_table.h000066400000000000000000000052441313612200500157660ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef INT_TABLE_H_ #define INT_TABLE_H_ #include "generic_list.h" #include "../elibs/khash/khash.h" KHASH_INIT(int, int, void *, 1, kh_int_hash_func, kh_int_hash_equal) /* Prototype for a pointer to a free key function. */ typedef void (*free_value_fn_t)(const void *key); typedef struct int_htable_{ khash_t(int) *htable; free_value_fn_t free_value_fn; }int_htable; int_htable *int_htable_new(); int_htable *int_htable_new_managed(free_value_fn_t df); void int_htable_del(int_htable *); void int_htable_insert(int_htable *,int,void *); void int_htable_remove(int_htable *, int); void *int_htable_lookup(int_htable *, int); void int_htable_destroy(int_htable *ht); glist_t *int_htable_values(int_htable *ht); #define int_htable_foreach_key(_ht, _it) \ do { \ khiter_t _k_; \ for (_k_ = kh_begin(_ht->htable); _k_ != kh_end(_ht->htable); ++_k_){ \ if (kh_exist(_ht->htable, _k_)){ \ _it = kh_key(_ht->htable,_k_); #define int_htable_foreach_key_end \ } \ } \ } while (0) #define int_htable_foreach_value(_ht, _it) \ do { \ khiter_t _k_; \ for (_k_ = kh_begin(_ht->htable); _k_ != kh_end(_ht->htable); ++_k_){ \ if (kh_exist(_ht->htable, _k_)){ \ _it = kh_value(_ht->htable,_k_); #define int_htable_foreach_value_end \ } \ } \ } while (0) #endif /* INT_TABLE_H_ */ oor-1.2.0/oor/lib/interfaces_lib.c000066400000000000000000000224651313612200500167750ustar00rootroot00000000000000/* * Universal TUN/TAP device driver. * Copyright (C) 1999-2000 Maxim Krasnyansky * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include #include #include #include #include #include #include #include #include #include "interfaces_lib.h" #include "oor_log.h" #include "../oor_external.h" int create_tun_tap(iface_type_t type, const char *iface_name, int mtu) { struct ifreq ifr; int err = 0; int tmpsocket = 0; int flags = IFF_TAP | IFF_NO_PI; // Create a tunnel without persistence char *clonedev = CLONEDEV; int receive_fd; switch (type){ case TUN: flags = flags | IFF_TUN; break; case TAP: flags = flags | IFF_TAP; break; default: OOR_LOG(LCRIT, "create_tun_tap: Unknown interface type"); return (BAD); } /* Arguments taken by the function: * * char *dev: the name of an interface (or '\0'). MUST have enough * space to hold the interface name if '\0' is passed * int flags: interface flags (eg, IFF_TUN etc.) */ /* open the clone device */ if( (receive_fd = open(clonedev, O_RDWR)) < 0 ) { OOR_LOG(LCRIT, "TUN/TAP: Failed to open clone device"); return(BAD); } memset(&ifr, 0, sizeof(ifr)); ifr.ifr_flags = flags; strncpy(ifr.ifr_name, iface_name, IFNAMSIZ - 1); // try to create the device if ((err = ioctl(receive_fd, TUNSETIFF, (void *) &ifr)) < 0) { close(receive_fd); OOR_LOG(LCRIT, "TUN/TAP: Failed to create tunnel interface: %s.", strerror(errno)); if (errno == 16){ OOR_LOG(LCRIT, "Check no other instance of oor is running. Exiting ..."); } return(BAD); } // get the ifindex for the tun/tap tmpsocket = socket(AF_INET, SOCK_DGRAM, 0); // Dummy socket for the ioctl, type/details unimportant if ((err = ioctl(tmpsocket, SIOCGIFINDEX, (void *)&ifr)) < 0) { close(receive_fd); close(tmpsocket); OOR_LOG(LCRIT, "TUN/TAP: unable to determine ifindex for tunnel interface, errno: %d.", errno); return(BAD); } else { OOR_LOG(LDBG_3, "TUN/TAP ifindex is: %d", ifr.ifr_ifindex); // Set the MTU to the configured MTU ifr.ifr_ifru.ifru_mtu = mtu; if ((err = ioctl(tmpsocket, SIOCSIFMTU, &ifr)) < 0) { close(tmpsocket); OOR_LOG(LCRIT, "TUN/TAP: unable to set interface MTU to %d, errno: %d.", mtu, errno); return(BAD); } else { OOR_LOG(LDBG_1, "TUN/TAP mtu set to %d", mtu); } } close(tmpsocket); /* this is the special file descriptor that the caller will use to talk * with the virtual interface */ OOR_LOG(LDBG_2, "Tunnel fd at creation is %d", receive_fd); if (bring_up_iface(iface_name) != GOOD){ return (BAD); } return (receive_fd); } /* * bring_up_iface() * * Bring up interface */ int bring_up_iface(const char *iface_name) { struct ifinfomsg *ifi = NULL; struct nlmsghdr *nlh = NULL; char sndbuf[4096]; int retval = 0; int sockfd = 0; int ifindex = 0; ifindex = if_nametoindex (iface_name); sockfd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); if (sockfd < 0) { OOR_LOG(LERR, "bring_up_iface: Failed to connect to netlink socket"); return(BAD); } /* * Build the command */ memset(sndbuf, 0, 4096); nlh = (struct nlmsghdr *)sndbuf; nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); nlh->nlmsg_flags = NLM_F_REQUEST | (NLM_F_CREATE | NLM_F_REPLACE); nlh->nlmsg_type = RTM_SETLINK; ifi = (struct ifinfomsg *)(sndbuf + sizeof(struct nlmsghdr)); ifi->ifi_family = AF_UNSPEC; ifi->ifi_type = IFLA_UNSPEC; ifi->ifi_index = ifindex; ifi->ifi_flags = IFF_UP | IFF_RUNNING; // Bring it up ifi->ifi_change = 0xFFFFFFFF; retval = send(sockfd, sndbuf, nlh->nlmsg_len, 0); if (retval < 0) { OOR_LOG(LERR, "bring_up_iface: send() failed %s", strerror(errno)); close(sockfd); return(BAD); } OOR_LOG(LDBG_1, "Interface %s UP.", iface_name); close(sockfd); return(GOOD); } /* * tun_add_eid_to_iface() * * Add an EID to the TUN/TAP interface */ int add_addr_to_iface(const char *iface_name, lisp_addr_t *addr) { struct rtattr *rta = NULL; struct ifaddrmsg *ifa = NULL; struct nlmsghdr *nlh = NULL; char sndbuf[4096]; int retval = 0; int sockfd = 0; int ifindex = 0; int addr_size = 0; int prefix_length = 0; ifindex = if_nametoindex (iface_name); sockfd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); if (sockfd < 0) { OOR_LOG(LERR, "add_addr_to_iface: Failed to connect to netlink socket"); return(BAD); } switch (lisp_addr_ip_afi(addr)){ case AF_INET: addr_size = sizeof(struct in_addr); prefix_length = 32; break; case AF_INET6: addr_size = sizeof(struct in6_addr); prefix_length = 128; break; default: OOR_LOG(LERR, "add_addr_to_iface: Address no IP address %s", lisp_addr_to_char(addr)); return(BAD); } /* * Build the command */ memset(sndbuf, 0, 4096); nlh = (struct nlmsghdr *)sndbuf; nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg) + sizeof(struct rtattr) + addr_size); nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_REPLACE; nlh->nlmsg_type = RTM_NEWADDR; ifa = (struct ifaddrmsg *)(sndbuf + sizeof(struct nlmsghdr)); ifa->ifa_prefixlen = prefix_length; ifa->ifa_family = lisp_addr_ip_afi(addr); ifa->ifa_index = ifindex; ifa->ifa_scope = RT_SCOPE_UNIVERSE; ifa->ifa_flags = 0; // Bring it up rta = (struct rtattr *)(sndbuf + sizeof(struct nlmsghdr) + sizeof(struct ifaddrmsg)); rta->rta_type = IFA_LOCAL; rta->rta_len = sizeof(struct rtattr) + addr_size; lisp_addr_copy_to((void *)((char *)rta + sizeof(struct rtattr)),addr); retval = send(sockfd, sndbuf, nlh->nlmsg_len, 0); if (retval < 0) { OOR_LOG(LERR, "add_addr_to_iface: send() failed %s", strerror(errno)); close(sockfd); return(BAD); } OOR_LOG(LDBG_1, "Added %s to interface %s.",lisp_addr_to_char(addr), iface_name); close(sockfd); return(GOOD); } /* * del_addr_from_iface() * * Remove an EID to the TUN/TAP interface */ int del_addr_from_iface(const char *iface_name, lisp_addr_t *addr) { struct rtattr *rta = NULL; struct ifaddrmsg *ifa = NULL; struct nlmsghdr *nlh = NULL; char sndbuf[4096]; int retval = 0; int sockfd = 0; int ifindex = 0; int addr_size = 0; int prefix_length = 0; ifindex = if_nametoindex (iface_name); sockfd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); if (sockfd < 0) { OOR_LOG(LERR, "del_addr_from_iface: Failed to connect to netlink socket"); return(BAD); } switch (lisp_addr_ip_afi(addr)){ case AF_INET: addr_size = sizeof(struct in_addr); prefix_length = 32; break; case AF_INET6: addr_size = sizeof(struct in6_addr); prefix_length = 128; break; default: OOR_LOG(LERR, "del_addr_from_iface: Address no IP address %s", lisp_addr_to_char(addr)); return(BAD); } /* * Build the command */ memset(sndbuf, 0, 4096); nlh = (struct nlmsghdr *)sndbuf; nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg) + sizeof(struct rtattr) + addr_size); nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_REPLACE; nlh->nlmsg_type = RTM_DELADDR; ifa = (struct ifaddrmsg *)(sndbuf + sizeof(struct nlmsghdr)); ifa->ifa_prefixlen = prefix_length; ifa->ifa_family = lisp_addr_ip_afi(addr); ifa->ifa_index = ifindex; ifa->ifa_scope = RT_SCOPE_UNIVERSE; ifa->ifa_flags = 0; // Bring it up rta = (struct rtattr *)(sndbuf + sizeof(struct nlmsghdr) + sizeof(struct ifaddrmsg)); rta->rta_type = IFA_LOCAL; rta->rta_len = sizeof(struct rtattr) + addr_size; // memcopy_lisp_addr((void *)((char *)rta + sizeof(struct rtattr)),&eid_address); lisp_addr_copy_to((void *)((char *)rta + sizeof(struct rtattr)),addr); retval = send(sockfd, sndbuf, nlh->nlmsg_len, 0); if (retval < 0) { OOR_LOG(LERR, "del_addr_from_iface: send() failed %s", strerror(errno)); close(sockfd); return(BAD); } OOR_LOG(LDBG_1, "Removed %s from interface %s.",lisp_addr_to_char(addr), iface_name); close(sockfd); return(GOOD); } oor-1.2.0/oor/lib/interfaces_lib.h000066400000000000000000000022121313612200500167660ustar00rootroot00000000000000/* * Universal TUN/TAP device driver. * Copyright (C) 1999-2000 Maxim Krasnyansky * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #ifndef INTERFACES_LIB_H_ #define INTERFACES_LIB_H_ #include "../liblisp/lisp_address.h" typedef enum { TUN, TAP } iface_type_t; #ifdef ANDROID #define CLONEDEV "/dev/tun" #else #define CLONEDEV "/dev/net/tun" #endif int create_tun_tap(iface_type_t type, const char *iface_name, int mtu); int bring_up_iface(const char *iface_name); int add_addr_to_iface(const char *iface_name, lisp_addr_t *addr); int del_addr_from_iface(const char *iface_name, lisp_addr_t *addr); #endif /* INTERFACES_LIB_H_ */ oor-1.2.0/oor/lib/lbuf.c000066400000000000000000000152641313612200500147530ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include #include #include "lbuf.h" #include "oor_log.h" #include "mem_util.h" static void lbuf_init__(lbuf_t *b, uint32_t allocated, lbuf_source_e source) { b->allocated = allocated; b->source = source; b->size = 0; b->lisp = b->ip = b->udp = b->lhdr = b->l3 = b->l4 = UINT16_MAX; } static void lbuf_use__(lbuf_t *b, void *data, uint32_t allocated, lbuf_source_e source) { lbuf_set_base(b, data); lbuf_set_data(b, data); lbuf_init__(b, allocated, source); } /* Initializes 'b' as an empty lbuf that contains the 'allocated' bytes of * memory starting at 'base'. 'base' should be obtained with malloc(). It * will be freed on resized or freed */ void lbuf_use(lbuf_t *b, void *base, uint32_t allocated) { lbuf_use__(b, base, allocated, LBUF_MALLOC); } /* Initializes 'b' as an empty lbuf that contains the 'allocated' bytes of * memory starting at 'base'. 'base' should point to a buffer allocated on * the stack. There's no need to uninit the buffer */ void lbuf_use_stack(lbuf_t *b, void *base, uint32_t allocated) { lbuf_use__(b, base, allocated, LBUF_STACK); } void lbuf_init(lbuf_t *b, uint32_t size) { lbuf_use(b, size ? xzalloc(size) : NULL, size); } void lbuf_uninit(lbuf_t *b) { if (b) { if (b->source == LBUF_MALLOC) { free(b->base); } } } lbuf_t * lbuf_new(uint32_t size) { lbuf_t *b; b = xzalloc(sizeof(lbuf_t)); lbuf_init(b, size); return b; } inline void lbuf_del(lbuf_t *b) { if (b) { lbuf_uninit(b); free(b); } } lbuf_t * lbuf_new_with_headroom(uint32_t size, uint32_t headroom) { lbuf_t *b = lbuf_new(size + headroom); lbuf_reserve(b, headroom); return b; } /* Resizes b such that it has @new_headroom headroom and @new_tailroom * tailroom */ static void lbuf_resize_(lbuf_t *b, uint32_t new_headroom, size_t new_tailroom) { uint8_t *new_base; uint32_t new_allocated = new_headroom + b->size + new_tailroom; uint32_t diff_offset = new_headroom - lbuf_headroom(b); if (new_headroom == lbuf_headroom(b)) { b->base = xrealloc(b->base, new_allocated); } else { new_base = xmalloc(new_allocated); memcpy((uint8_t *)new_base + new_headroom, b->data, b->size); free(b->base); b->base = new_base; if (b->ip != UINT16_MAX){ b->ip = b->ip + diff_offset; } if (b->udp != UINT16_MAX){ b->udp = b->udp + diff_offset; } if (b->lhdr != UINT16_MAX){ b->lhdr = b->lhdr + diff_offset; } if (b->l3 != UINT16_MAX){ b->l3 = b->l3 + diff_offset; } if (b->l4 != UINT16_MAX){ b->l4 = b->l4 + diff_offset; } if (b->lisp != UINT16_MAX){ b->lisp = b->lisp + diff_offset; } } b->allocated = new_allocated; b->data = (uint8_t *)b->base + new_headroom; } void lbuf_prealloc_tailroom(lbuf_t *b, uint32_t size) { if (size > lbuf_tailroom(b)) { lbuf_resize_(b, lbuf_headroom(b), MAX(size, 64)); } } void lbuf_prealloc_headroom(lbuf_t *b, uint32_t size) { if (size > lbuf_headroom(b)) { lbuf_resize_(b, MAX(size, 64), lbuf_tailroom(b)); } } void * lbuf_put_uninit(lbuf_t *b, uint32_t size) { void *t; lbuf_prealloc_tailroom(b, size); t = lbuf_tail(b); b->size += size; return t; } void * lbuf_put(lbuf_t *b, void *data, uint32_t size) { void *dst = lbuf_put_uninit(b, size); memcpy(dst, data, size); return dst; } void * lbuf_push_uninit(lbuf_t *b, uint32_t size) { lbuf_prealloc_headroom(b, size); b->data = (char *)b->data - size; b->size += size; return b->data; } void * lbuf_push(lbuf_t *b, void *data, uint32_t size) { void *dst = lbuf_push_uninit(b, size); memcpy(dst, data, size); return dst; } void lbuf_reserve(lbuf_t *b, uint32_t size) { lbuf_prealloc_tailroom(b, size); b->data = (char *)b->base + size; } lbuf_t * lbuf_clone(lbuf_t *b) { lbuf_t *new_buf = lbuf_new(b->size); lbuf_put(new_buf->data, b->data, b->size); new_buf->lisp = b->lisp; return new_buf; } inline int lbuf_point_to_eth(lbuf_t *b) { if (b->eth == UINT16_MAX){ OOR_LOG(LDBG_2,"lbuf_data_to_eth: Ethernet header not specified in buffer"); return (BAD); } b->size = lbuf_tail(b) - lbuf_eth(b); b->data = lbuf_eth(b); return (GOOD); } inline int lbuf_point_to_ip(lbuf_t *b) { if (b->ip == UINT16_MAX){ OOR_LOG(LDBG_2,"lbuf_data_to_ip: IP header not specified in buffer"); return (BAD); } b->size = lbuf_tail(b) - lbuf_ip(b); b->data = lbuf_ip(b); return (GOOD); } inline int lbuf_point_to_udp(lbuf_t *b) { if (b->udp == UINT16_MAX){ OOR_LOG(LDBG_2,"lbuf_data_to_udp: UDP header not specified in buffer"); return (BAD); } b->size = lbuf_tail(b) - lbuf_udp(b); b->data = lbuf_udp(b); return (GOOD); } inline int lbuf_point_to_lisp_hdr(lbuf_t *b) { if (b->lhdr == UINT16_MAX){ OOR_LOG(LDBG_2,"lbuf_data_to_lisp_hdr: LISP Encap header not specified in buffer"); return (BAD); } b->size = lbuf_tail(b) - lbuf_lisp_hdr(b); b->data = lbuf_lisp_hdr(b); return (GOOD); } inline int lbuf_point_to_l3(lbuf_t *b) { if (b->l3 == UINT16_MAX){ OOR_LOG(LDBG_2,"lbuf_data_to_l3: Inner IP header not specified in buffer"); return (BAD); } b->size = lbuf_tail(b) - lbuf_l3(b); b->data = lbuf_l3(b); return (GOOD); } inline int lbuf_point_to_l4(lbuf_t *b) { if (b->l4 == UINT16_MAX){ OOR_LOG(LDBG_2,"lbuf_data_to_l4: Inner UDP header not specified in buffer"); return (BAD); } b->size = lbuf_tail(b) - lbuf_l4(b); b->data = lbuf_l4(b); return (GOOD); } inline int lbuf_point_to_lisp(lbuf_t *b) { if (b->lisp == UINT16_MAX){ OOR_LOG(LDBG_2,"lbuf_data_to_lisp: LISP header not specified in buffer"); return (BAD); } b->size = lbuf_tail(b) - lbuf_lisp(b); b->data = lbuf_lisp(b); return (GOOD); } oor-1.2.0/oor/lib/lbuf.h000066400000000000000000000150271313612200500147550ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef LBUF_H_ #define LBUF_H_ #include #include #include "../defs.h" #include "../elibs/ovs/list.h" #define LBUF_STACK_OFFSET 100 typedef enum lbuf_source { LBUF_MALLOC, LBUF_STACK } lbuf_source_e; struct lbuf { struct ovs_list list; /* for queueing, to be implemented*/ uint32_t allocated; /* allocated size */ uint32_t size; /* size in-use */ uint16_t eth; /* Eth hds offset */ uint16_t ip; /* IP hdr offset */ uint16_t udp; /* UDP hdr offset */ uint16_t lhdr; /* lisp hdr offset */ uint16_t l3; /* (inner) l3 hdr offset */ uint16_t l4; /* (inner) l4 hdr offset */ uint16_t lisp; /* lisp payload offset */ lbuf_source_e source; /* source of memory allocated as 'base' */ void *base; /* start of allocated space */ void *data; /* start of in-use space */ }; typedef struct lbuf lbuf_t; void lbuf_use(lbuf_t *, void *, uint32_t); void lbuf_use_stack(lbuf_t *, void *, uint32_t); void lbuf_init(lbuf_t *, uint32_t); void lbuf_uninit(lbuf_t *); lbuf_t *lbuf_new(uint32_t); lbuf_t *lbuf_new_with_headroom(uint32_t, uint32_t); lbuf_t *lbuf_clone(lbuf_t *); void lbuf_del(lbuf_t *); static inline void *lbuf_at(const lbuf_t *, uint32_t, uint32_t); static inline void *lbuf_tail(const lbuf_t *); static inline void *lbuf_end(const lbuf_t *); static inline void *lbuf_data(const lbuf_t *); static inline void *lbuf_base(const lbuf_t *); static inline uint32_t lbuf_size(const lbuf_t *); static inline void lbuf_set_size(lbuf_t *, uint32_t); void *lbuf_put_uninit(lbuf_t *, uint32_t); void *lbuf_put(lbuf_t *, void *, uint32_t); void *lbuf_push_uninit(lbuf_t *, uint32_t); void *lbuf_push(lbuf_t *, void *, uint32_t); static inline void *lbuf_pull(lbuf_t *b, uint32_t); void lbuf_reserve(lbuf_t *b, uint32_t size); lbuf_t *lbuf_clone(lbuf_t *b); void lbuf_prealloc_tailroom(lbuf_t *b, uint32_t); void lbuf_prealloc_headroom(lbuf_t *b, uint32_t); static inline void lbuf_set_base(lbuf_t *, void *); static inline void lbuf_set_data(lbuf_t *, void *); static inline void lbuf_reset_eth(lbuf_t *b); static inline void *lbuf_eth(lbuf_t *b); static inline void lbuf_reset_ip(lbuf_t *b); static inline void *lbuf_ip(lbuf_t *b); int lbuf_point_to_ip(lbuf_t *b); static inline void lbuf_reset_udp(lbuf_t *b); static inline void *lbuf_udp(lbuf_t *b); int lbuf_point_to_udp(lbuf_t *b); static inline void lbuf_reset_l3(lbuf_t *b); static inline void *lbuf_l3(lbuf_t *b); int lbuf_point_to_l3(lbuf_t *b); static inline void lbuf_reset_l4(lbuf_t *b); static inline void *lbuf_l4(lbuf_t *b); int lbuf_point_to_l4(lbuf_t *b); static inline void lbuf_reset_lisp(lbuf_t *b); static inline void *lbuf_lisp(lbuf_t*); int lbuf_point_to_lisp(lbuf_t *b); static inline void lbuf_reset_lisp_hdr(lbuf_t *b); static inline void *lbuf_lisp_hdr(lbuf_t*); int lbuf_point_to_lisp_hdr(lbuf_t *b); static inline void lbuf_set_base(lbuf_t *b, void *bs) { b->base = bs; } static inline void lbuf_set_data(lbuf_t *b, void *dt) { b->data = dt; } static inline void * lbuf_at(const lbuf_t *b, uint32_t offset, uint32_t size) { return offset + size <= lbuf_size(b) ? (char *)lbuf_data(b) + offset : NULL; } static inline void * lbuf_tail(const lbuf_t *b) { return (char *)lbuf_data(b) + lbuf_size(b); } static inline void * lbuf_end(const lbuf_t *b) { return (char *)lbuf_base(b) + b->allocated; } static inline uint32_t lbuf_headroom(const lbuf_t *b) { return ((char *)lbuf_data(b) - (char *)lbuf_base(b)); } static inline uint32_t lbuf_tailroom(const lbuf_t *b) { return (char *)lbuf_end(b) - (char *)lbuf_tail(b); } static inline void * lbuf_data(const lbuf_t *b) { return b->data; } static inline void * lbuf_base(const lbuf_t *b) { return b->base; } static inline uint32_t lbuf_size(const lbuf_t *b) { return b->size; } static inline void lbuf_set_size(lbuf_t *b, uint32_t sz) { b->size = sz; } /* moves 'data' pointer by 'size'. Returns first byte * of data removed */ static inline void * lbuf_pull(lbuf_t *b, uint32_t size) { if (size > b->size) { return NULL; } void *data = b->data; b->data = (uint8_t *) b->data + size; b->size -= size; return data; } static inline void lbuf_reset_eth(lbuf_t *b) { b->eth = (char *)lbuf_data(b) - (char *)lbuf_base(b); } static inline void * lbuf_eth(lbuf_t *b) { return b->eth != UINT16_MAX ? (char *)lbuf_base(b) + b->eth : NULL; } static inline void lbuf_reset_ip(lbuf_t *b) { b->ip = (char *)lbuf_data(b) - (char *)lbuf_base(b); } static inline void * lbuf_ip(lbuf_t *b) { return b->ip != UINT16_MAX ? (char *)lbuf_base(b) + b->ip : NULL; } static inline void lbuf_reset_udp(lbuf_t *b) { b->udp = (char *)lbuf_data(b) - (char *)lbuf_base(b); } static inline void * lbuf_udp(lbuf_t *b) { return b->udp != UINT16_MAX ? (char *)lbuf_base(b) + b->udp : NULL; } static inline void lbuf_reset_l3(lbuf_t *b) { b->l3 = (char *)lbuf_data(b) - (char *)lbuf_base(b); } static inline void * lbuf_l3(lbuf_t *b) { return b->l3 != UINT16_MAX ? (char *)lbuf_base(b) + b->l3 : NULL; } static inline void lbuf_reset_l4(lbuf_t *b) { b->l4 = (char *)lbuf_data(b) - (char *)lbuf_base(b); } static inline void * lbuf_l4(lbuf_t *b) { return b->l4 != UINT16_MAX ? (char *)lbuf_base(b) + b->l4 : NULL; } static inline void lbuf_reset_lisp(lbuf_t *b) { b->lisp = (char *)lbuf_data(b) - (char *)lbuf_base(b); } static inline void * lbuf_lisp(lbuf_t *b) { return b->lisp != UINT16_MAX ? (char *)lbuf_base(b) + b->lisp : NULL; } static inline void lbuf_reset_lisp_hdr(lbuf_t *b) { b->lhdr = (char *)lbuf_data(b) - (char *)lbuf_base(b); } static inline void * lbuf_lisp_hdr(lbuf_t *b) { return b->lhdr != UINT16_MAX ? (char *)lbuf_base(b) + b->lhdr : NULL; } #endif /* LBUF_H_ */ oor-1.2.0/oor/lib/lisp_site.c000066400000000000000000000034271313612200500160140ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "lisp_site.h" #include "timers_utils.h" #include "../defs.h" #include "../oor_external.h" lisp_site_prefix_t * lisp_site_prefix_init(lisp_addr_t *eid, uint32_t iid, int key_type, char *key, uint8_t more_specifics, uint8_t proxy_reply, uint8_t merge) { lisp_site_prefix_t *sp = NULL; int iidmlen; sp = xzalloc(sizeof(lisp_site_prefix_t)); if (iid > 0){ iidmlen = (lisp_addr_ip_afi(eid) == AF_INET) ? 32: 128; sp->eid_prefix = lisp_addr_new_init_iid(iid, eid, iidmlen); }else{ sp->eid_prefix = lisp_addr_clone(eid); } sp->key_type = key_type; sp->key = strdup(key); sp->accept_more_specifics = more_specifics; sp->proxy_reply = proxy_reply; sp->merge = merge; return(sp); } void lisp_site_prefix_del(lisp_site_prefix_t *sp) { if (!sp) return; if (sp->eid_prefix) lisp_addr_del(sp->eid_prefix); if (sp->key) free(sp->key); free(sp); } void lisp_reg_site_del(lisp_reg_site_t *rs) { stop_timers_from_obj(rs,ptrs_to_timers_ht,nonces_ht); mapping_del(rs->site_map); free(rs); } oor-1.2.0/oor/lib/lisp_site.h000066400000000000000000000027141313612200500160170ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef LISP_SITE_H_ #define LISP_SITE_H_ #include "../liblisp/liblisp.h" #include "timers.h" typedef struct lisp_site_prefix { lisp_addr_t *eid_prefix; uint8_t proxy_reply; uint8_t accept_more_specifics; lisp_key_type_e key_type; char *key; uint8_t merge; } lisp_site_prefix_t; typedef struct lisp_reg_site { mapping_t *site_map; } lisp_reg_site_t; lisp_site_prefix_t *lisp_site_prefix_init(lisp_addr_t *eid_prefix, uint32_t iid, int key_type, char *key, uint8_t more_specifics, uint8_t proxy_reply, uint8_t merge); void lisp_site_prefix_del(lisp_site_prefix_t *sp); void lisp_reg_site_del(lisp_reg_site_t *rs); static inline lisp_addr_t * lsite_prefix(lisp_site_prefix_t *ls) { return(ls->eid_prefix); } #endif /* LISP_SITE_H_ */ oor-1.2.0/oor/lib/map_cache_entry.c000066400000000000000000000062721313612200500171430ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include #include "map_cache_entry.h" #include "oor_log.h" #include "timers_utils.h" #include "../defs.h" inline mcache_entry_t * mcache_entry_new() { mcache_entry_t *mce; mce = xzalloc(sizeof(mcache_entry_t)); mce->active = NOT_ACTIVE; mce->timestamp = time(NULL); return(mce); } void mcache_entry_init(mcache_entry_t *mce, mapping_t *mapping) { mce->mapping = mapping; mce->how_learned = MCE_DYNAMIC; } void mcache_entry_init_static(mcache_entry_t *mce, mapping_t *mapping) { mce->active = ACTIVE; mce->mapping = mapping; mce->how_learned = MCE_STATIC; } void mcache_entry_del(mcache_entry_t *entry) { locator_t *loct; assert(entry); /* Stop timers associated to the locators */ mapping_foreach_locator(mcache_entry_mapping(entry),loct){ stop_timers_from_obj(loct,ptrs_to_timers_ht, nonces_ht); }mapping_foreach_locator_end; stop_timers_from_obj(entry,ptrs_to_timers_ht, nonces_ht); mapping_del(mcache_entry_mapping(entry)); if (entry->routing_info != NULL){ entry->routing_inf_del(entry->routing_info); } free(entry); } inline lisp_addr_t * mcache_entry_eid(mcache_entry_t *mce) { return(mapping_eid(mce->mapping)); } inline uint8_t mcache_has_locators(mcache_entry_t *m) { if (mapping_locator_count(m->mapping) > 0){ return (TRUE); }else{ return (FALSE); } } void map_cache_entry_dump (mcache_entry_t *entry, int log_level) { if (is_loggable(log_level) == FALSE){ return; } char buf[256], buf2[64]; time_t expiretime; time_t uptime; char str[400]; mapping_t *mapping = NULL; *buf = '\0'; *buf2 = '\0'; *str = '\0'; mapping = mcache_entry_mapping(entry); uptime = time(NULL); uptime = uptime - entry->timestamp; strftime(buf, 20, "%H:%M:%S", localtime(&uptime)); expiretime = (mapping_ttl(mcache_entry_mapping(entry)) * 60) - uptime; if (expiretime > 0) { strftime(buf2, 20, "%H:%M:%S", localtime(&expiretime)); } snprintf(str,sizeof(str), "ENTRY UPTIME: %s, EXPIRES: %s, ", buf, buf2); if (entry->how_learned == MCE_STATIC) { snprintf(str + strlen(str),sizeof(str) - strlen(str),"TYPE: Static, "); } else { snprintf(str + strlen(str),sizeof(str) - strlen(str),"TYPE: Dynamic, "); } snprintf(str + strlen(str),sizeof(str) - strlen(str),"ACTIVE: %s", entry->active == TRUE ? "Yes" : "No"); OOR_LOG(log_level, "%s\n%s\n", str, mapping_to_char(mapping)); } oor-1.2.0/oor/lib/map_cache_entry.h000066400000000000000000000061331313612200500171440ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef MAP_CACHE_ENTRY_H_ #define MAP_CACHE_ENTRY_H_ #include "timers.h" #include "../liblisp/lisp_mapping.h" /* * map-cache entry types (how_learned) */ typedef enum mce_type { MCE_= 0, MCE_DYNAMIC, MCE_STATIC } mce_type_e; /* * map-cache entry activated (received map reply) */ #define NOT_ACTIVE 0 #define ACTIVE 1 typedef void (*routing_info_del_fct)(void *); typedef struct map_cache_entry_ { uint8_t how_learned; mapping_t *mapping; /* mapping validity information */ /* TRUE if we have received a map reply for this entry */ uint8_t active; uint8_t active_witin_period; time_t timestamp; /* Routing info */ void * routing_info; routing_info_del_fct routing_inf_del; /* EID that requested the mapping. Helps with timers */ lisp_addr_t *requester; } mcache_entry_t; mcache_entry_t *mcache_entry_new(); void mcache_entry_init(mcache_entry_t *, mapping_t *); void mcache_entry_init_static(mcache_entry_t *, mapping_t *); void mcache_entry_del(mcache_entry_t *entry); void map_cache_entry_dump(mcache_entry_t *entry, int log_level); static inline mapping_t *mcache_entry_mapping(mcache_entry_t*); static inline void mcache_entry_set_mapping(mcache_entry_t* , mapping_t *); static inline uint8_t mcache_entry_active(mcache_entry_t *); static inline void mcache_entry_set_active(mcache_entry_t *, int); uint8_t mcache_has_locators(mcache_entry_t *m); static inline void *mcache_entry_routing_info(mcache_entry_t *); static inline void mcache_entry_set_routing_info(mcache_entry_t *, void *, routing_info_del_fct); lisp_addr_t *mcache_entry_eid(mcache_entry_t *mce); static inline mapping_t * mcache_entry_mapping(mcache_entry_t* mce) { return (mce->mapping); } static inline void mcache_entry_set_mapping(mcache_entry_t* mce, mapping_t *m) { mce->mapping = m; } static inline uint8_t mcache_entry_active(mcache_entry_t *mce) { return (mce->active); } static inline void mcache_entry_set_active(mcache_entry_t *mce, int state) { mce->active = state; } static inline void * mcache_entry_routing_info(mcache_entry_t *m) { return (m->routing_info); } static inline void mcache_entry_set_routing_info(mcache_entry_t *m, void *routing_inf, routing_info_del_fct del_fct) { m->routing_info = routing_inf; m->routing_inf_del = del_fct; } #endif /* MAP_CACHE_ENTRY_H_ */ oor-1.2.0/oor/lib/map_local_entry.c000066400000000000000000000146021313612200500171660ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "oor_log.h" #include "map_local_entry.h" #include "timers_utils.h" #include "../defs.h" static nat_info_t * nat_info_new(); static void nat_info_del(nat_info_t *nat_info); inline mapping_t * map_local_entry_mapping(map_local_entry_t *mle) { return (mle->mapping); } inline void map_local_entry_set_mapping( map_local_entry_t *mle, mapping_t *map) { mle->mapping = map; } inline void * map_local_entry_fwd_info(map_local_entry_t *mle) { return (mle->fwd_policy_info); } inline void map_local_entry_set_fwd_info( map_local_entry_t *mle, void *fwd_policy_info, fwd_policy_info_del_fct fn) { mle->fwd_policy_info = fwd_policy_info; if (!fn){ OOR_LOG(LDBG_1, "map_local_entry_set_fwd_info: No specified function to delete fwd info."); } mle->fwd_ply_inf_del = fn; } inline lisp_addr_t * map_local_entry_eid(map_local_entry_t *mle){ return (mapping_eid(map_local_entry_mapping(mle))); } map_local_entry_t * map_local_entry_new() { map_local_entry_t *mle; mle = xzalloc(sizeof(map_local_entry_t)); return (mle); } map_local_entry_t * map_local_entry_new_init(mapping_t *map) { map_local_entry_t *mle; mle = xzalloc(sizeof(map_local_entry_t)); if (mle == NULL){ OOR_LOG(LDBG_1, "map_local_entry_new_init: Can't create local database mapping with EID prefix %s.", lisp_addr_to_char(mapping_eid(map))); return (NULL); } mle->mapping = map; mle->nat_info = nat_info_new(); return (mle); } void map_local_entry_init(map_local_entry_t *mle, mapping_t *map) { mle->mapping = map; } void map_local_entry_del(map_local_entry_t *mle) { locator_t *loct; assert(mle); mapping_foreach_locator(map_local_entry_mapping(mle),loct){ stop_timers_from_obj(loct,ptrs_to_timers_ht, nonces_ht); }mapping_foreach_locator_end; stop_timers_from_obj(mle,ptrs_to_timers_ht, nonces_ht); mapping_del(mle->mapping); if (mle->fwd_policy_info != NULL){ mle->fwd_ply_inf_del(mle->fwd_policy_info); } nat_info_del(mle->nat_info); free(mle); } void map_local_entry_dump(map_local_entry_t *mle, int log_level) { // TODO OOR_LOG(log_level,mapping_to_char(mle->mapping)); } char * map_local_entry_to_char(map_local_entry_t *mle) { // TODO return (mapping_to_char(mle->mapping)); } static nat_info_t * nat_info_new() { nat_info_t *nat_info; nat_info = xmalloc(sizeof(nat_info_t)); if (!nat_info){ return (NULL); } nat_info->loct_addr_to_rtrs = shash_new_managed((free_value_fn_t)glist_destroy); nat_info->rtr_addr_to_locts = shash_new_managed((free_value_fn_t)glist_destroy); return(nat_info); } static void nat_info_del(nat_info_t *nat_info) { shash_destroy(nat_info->loct_addr_to_rtrs); shash_destroy(nat_info->rtr_addr_to_locts); free(nat_info); } void mle_nat_info_update(map_local_entry_t *mle, locator_t *loct, glist_t *new_rtr_list) { nat_info_t *nat_info = mle->nat_info; glist_t *loct_list; glist_t *rtr_list; glist_entry_t *rtr_it; mapping_t * map = map_local_entry_mapping(mle); locator_t * rtr_loct; lisp_addr_t *loct_addr = locator_addr(loct), *rtr_addr; rtr_list = shash_lookup(nat_info->loct_addr_to_rtrs, lisp_addr_to_char(loct_addr)); /* If we already have information of the RTRs for this locator, we have to * remove it before we can update it */ if (rtr_list){ glist_for_each_entry(rtr_it, rtr_list){ rtr_addr = (lisp_addr_t *)glist_entry_data(rtr_it); /* Remove loctor from list of locators associated to the rtr */ loct_list = shash_lookup(nat_info->rtr_addr_to_locts,lisp_addr_to_char(rtr_addr)); glist_remove_obj_with_ptr(loct,loct_list); if(glist_size(loct_list) == 0){ shash_remove(nat_info->rtr_addr_to_locts,lisp_addr_to_char(rtr_addr)); /* The RTR is not associated with any loctor. Remove the rtr locator from the mapping */ rtr_loct = mapping_get_loct_with_addr(map, rtr_addr); mapping_remove_locator(map,rtr_loct); } } shash_remove(nat_info->loct_addr_to_rtrs, lisp_addr_to_char(loct_addr)); } /* Update the nat information with the new list */ rtr_list = glist_clone(new_rtr_list,(glist_clone_obj)lisp_addr_clone); shash_insert( nat_info->loct_addr_to_rtrs, strdup(lisp_addr_to_char(loct_addr)), rtr_list); glist_for_each_entry(rtr_it, rtr_list){ rtr_addr = (lisp_addr_t *)glist_entry_data(rtr_it); loct_list = shash_lookup(nat_info->rtr_addr_to_locts,lisp_addr_to_char(rtr_addr)); if (!loct_list){ loct_list = glist_new(); shash_insert( nat_info->rtr_addr_to_locts, strdup(lisp_addr_to_char(rtr_addr)), loct_list); /* Create the logical locator for the RTR -> L=0, R=1 */ rtr_loct = locator_new_init(rtr_addr,UP,0,1,1,100,255,0); mapping_add_locator(map,rtr_loct); } glist_add(loct,loct_list); } } glist_t * mle_rtr_addr_list(map_local_entry_t *mle) { glist_t *rtr_addr_lst, *rtr_str_addr_lst; glist_entry_t *rtr_addr_it; lisp_addr_t * rtr_addr; char *rtr_str_addr; rtr_addr_lst = glist_new_managed((glist_del_fct)lisp_addr_del); rtr_str_addr_lst = shash_keys(mle->nat_info->rtr_addr_to_locts); glist_for_each_entry(rtr_addr_it, rtr_str_addr_lst){ rtr_str_addr = (char *)glist_entry_data(rtr_addr_it); rtr_addr = lisp_addr_new(); lisp_addr_ip_from_char(rtr_str_addr,rtr_addr); glist_add (rtr_addr, rtr_addr_lst); } glist_destroy(rtr_str_addr_lst); return (rtr_addr_lst); } oor-1.2.0/oor/lib/map_local_entry.h000066400000000000000000000040301313612200500171650ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef MAP_LOCAL_ENTRY_H_ #define MAP_LOCAL_ENTRY_H_ #include "../liblisp/lisp_mapping.h" #include "shash.h" typedef void (*fwd_policy_info_del_fct)(void *); typedef struct nat_info_ { shash_t *loct_addr_to_rtrs; shash_t *rtr_addr_to_locts; }nat_info_t; typedef struct map_local_entry_ { mapping_t * mapping; void * fwd_policy_info; fwd_policy_info_del_fct fwd_ply_inf_del; nat_info_t * nat_info; } map_local_entry_t; map_local_entry_t *map_local_entry_new(); map_local_entry_t *map_local_entry_new_init(mapping_t *map); void map_local_entry_init(map_local_entry_t *mle, mapping_t *map); void map_local_entry_del(map_local_entry_t *mle); void map_local_entry_dump(map_local_entry_t *mle, int log_level); char * map_local_entry_to_char(map_local_entry_t *mle); mapping_t *map_local_entry_mapping(map_local_entry_t *mle); void map_local_entry_set_mapping(map_local_entry_t *mle, mapping_t *map); void *map_local_entry_fwd_info(map_local_entry_t *mle); void map_local_entry_set_fwd_info(map_local_entry_t *mle,void *fwd_policy_info, fwd_policy_info_del_fct fn); lisp_addr_t *map_local_entry_eid(map_local_entry_t *mle); void mle_nat_info_update(map_local_entry_t *mle, locator_t *loct, glist_t *new_rtr_list); glist_t * mle_rtr_addr_list(map_local_entry_t *mle); #endif /* MAP_LOCAL_ENTRY_H_ */ oor-1.2.0/oor/lib/mapping_db.c000066400000000000000000000622211313612200500161160ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ /* * This defines a mappings database (mdb) that relies on patricia tries and hash tables * to store IP and LCAF based EIDs. Among the supported LCAFs are multicast of type (S,G) and IID. * It is used to implement both the mappings cache and the local mapping db. */ #include #include "mapping_db.h" #include "oor_log.h" patricia_node_t *pt_add_node(patricia_tree_t *pt, ip_addr_t *ipaddr, uint8_t prefixlen, void *data); int pt_add_ippref(patricia_tree_t *pt, ip_prefix_t *ippref, void *data); int pt_add_mc_addr(patricia_tree_t *pt, lcaf_addr_t *mcaddr, void *data); void *pt_remove_mc_addr(patricia_tree_t *pt, lcaf_addr_t *mcaddr); void *pt_remove_ippref(patricia_tree_t *pt, ip_prefix_t *ippref); patricia_node_t *pt_find_ip_node(patricia_tree_t *pt, ip_addr_t *ipaddr); patricia_node_t *pt_find_ip_node_exact(patricia_tree_t *pt, ip_addr_t *ipaddr, uint8_t prefixlen); patricia_node_t *pt_find_mc_node(patricia_tree_t *pt, lcaf_addr_t *mcaddr, uint8_t exact); void pt_remove_node(patricia_tree_t *pt, patricia_node_t *node); uint8_t pt_test_if_empty(patricia_tree_t *pt); prefix_t *pt_make_ip_prefix(ip_addr_t *ipaddr, uint8_t prefixlen); void mdb_for_each_entry_cb(mdb_t *mdb, void (*callback)(void *, void *), void *cb_data); static int _add_iid_entry(mdb_t *db, void *entry, lcaf_addr_t *iidaddr); static void *_rm_iid_entry(mdb_t *db, lcaf_addr_t *iidaddr); static patricia_node_t *_find_iid_node(mdb_t *db, lcaf_addr_t *iidaddr, uint8_t exact); /* * Return map cache data base */ static patricia_tree_t * get_ip_pt_from_afi(mdb_t *db, uint16_t afi) { switch (afi) { case AF_INET: return (db->AF4_ip_db->head->data); break; case AF_INET6: return (db->AF6_ip_db->head->data); break; default: OOR_LOG(LDBG_1, "get_ip_pt_from_afi: AFI %u not recognized!", afi); break; } return (NULL); } static patricia_tree_t * get_iid_pt_from_lcaf(mdb_t *db, lcaf_addr_t *iidaddr) { patricia_tree_t *pt; int_htable *ht; lisp_addr_t *addr; uint32_t iid; uint16_t afi; iid = iid_type_get_iid(lcaf_addr_get_iid(iidaddr)); addr = iid_type_get_addr(lcaf_addr_get_iid(iidaddr)); if (lisp_addr_lafi(addr) == LM_AFI_LCAF){ OOR_LOG(LDBG_1, "get_iid_pt_from_lcaf: Concurrent lcaf address not supported"); return (NULL); } afi = lisp_addr_ip_afi(addr); switch (afi){ case AF_INET: ht = db->AF4_iid_db; break; case AF_INET6: ht = db->AF6_iid_db; break; default: OOR_LOG(LDBG_1, "get_iid_pt_from_lcaf: AFI %u not recognized!", afi); return (NULL); } pt = int_htable_lookup(ht,iid); if (!pt){ return (NULL); } return (pt->head->data); } static patricia_tree_t * get_mc_pt_from_lcaf(mdb_t *db, lcaf_addr_t *lcaf) { uint16_t afi = lcaf_mc_get_afi(lcaf); switch (afi) { case AF_INET: return (db->AF4_mc_db); break; case AF_INET6: return (db->AF6_mc_db); break; default: OOR_LOG(LDBG_1, "_get_mc_pt_from_lcaf: AFI %u not recognized!", afi); break; } return (NULL); } static patricia_node_t * _find_ip_node(mdb_t *db, lisp_addr_t *laddr, uint8_t exact) { patricia_tree_t *pt = get_ip_pt_from_afi(db, lisp_addr_ip_afi(laddr)); if (exact) { return (pt_find_ip_node_exact(pt, lisp_addr_ip_get_addr(laddr), lisp_addr_ip_get_plen(laddr))); } else { return (pt_find_ip_node(pt, lisp_addr_ip_get_addr(laddr))); } } static patricia_node_t * _find_lcaf_node(mdb_t *db, lcaf_addr_t *lcaf, uint8_t exact) { switch (lcaf_addr_get_type(lcaf)) { case LCAF_IID: return (_find_iid_node(db,lcaf,exact)); case LCAF_MCAST_INFO: return (pt_find_mc_node(get_mc_pt_from_lcaf(db, lcaf), lcaf, exact)); default: OOR_LOG(LWRN, "_find_lcaf_node: Unknown LCAF type %u", lcaf_addr_get_type(lcaf)); } return (NULL); } static patricia_node_t * _find_node(mdb_t *db, lisp_addr_t *laddr, uint8_t exact) { switch (lisp_addr_lafi(laddr)) { case LM_AFI_IP: case LM_AFI_IPPREF: return (_find_ip_node(db, laddr, exact)); case LM_AFI_LCAF: return (_find_lcaf_node(db, lisp_addr_get_lcaf(laddr), exact)); break; default: OOR_LOG(LWRN, "_find_node: unsupported AFI %d", lisp_addr_lafi(laddr)); break; } return (NULL); } static patricia_tree_t * _get_grp_pt_for_mc_addr(patricia_tree_t *strie, lcaf_addr_t *mcaddr, uint8_t exact) { patricia_node_t *snode = NULL; lisp_addr_t *src = NULL; ip_addr_t *srcip = NULL; uint8_t splen; patricia_tree_t *gtrie = NULL; src = lcaf_mc_get_src(mcaddr); srcip = lisp_addr_ip(src); if (lisp_addr_lafi(src) != LM_AFI_IP) { OOR_LOG(LDBG_3, "pt_remove_mc_addr: only IP AFI supported for S and G"); return (NULL); } splen = lcaf_mc_get_src_plen(mcaddr); if (exact) { /* exact lookup for src node */ snode = pt_find_ip_node_exact(strie, srcip, splen); } else { /* longest prefix match to find the S/S-prefix node */ snode = pt_find_ip_node(strie, srcip); } if (snode == NULL) { OOR_LOG(LDBG_3, "_get_pt_for_mc_addr: The source prefix %s/%d does not" " exist in the map cache", ip_addr_to_char(srcip), splen); return (NULL); } /* using field data of a patricia node as pointer to a G lookup table */ gtrie = (patricia_tree_t *) snode->data; return (gtrie); } static int _add_ippref_entry(mdb_t *db, void *entry, ip_prefix_t *ippref) { if (pt_add_ippref(get_ip_pt_from_afi(db, ip_prefix_afi(ippref)), ippref, entry) != GOOD) { OOR_LOG(LDBG_3, "_add_ippref_entry: Attempting to insert (%s) in the " "map-cache but couldn't add the entry to the pt!", ip_prefix_to_char(ippref)); return (BAD); } OOR_LOG(LDBG_3, "_add_ippref_entry: Added map cache data for %s", ip_prefix_to_char(ippref)); return (GOOD); } static int _db_add_iid(mdb_t *db, uint32_t iid, uint16_t afi){ patricia_tree_t *pt; int_htable *ht; ip_addr_t ip; size_t size; memset(&ip, 0, sizeof(ip_addr_t)); switch (afi){ case AF_INET: ip_addr_set_afi(&ip, AF_INET); size = sizeof(struct in_addr); pt = New_Patricia( size * 8); ht = db->AF4_iid_db; break; case AF_INET6: ip_addr_set_afi(&ip, AF_INET6); size = sizeof(struct in6_addr); pt = New_Patricia(size * 8); ht = db->AF6_iid_db; break; default: OOR_LOG(LDBG_1, "_db_add_iid: AFI %u not recognized!", afi); return (BAD); } /* MC is stored as patricia in patricia, what follows is a HACK * to have compatible walk methods for both IP and MC. */ pt_add_node(pt, &ip, 0,(void *) New_Patricia(size * 8)); int_htable_insert(ht, iid, pt); return (GOOD); } static int _add_iid_entry(mdb_t *db, void *entry, lcaf_addr_t *iidaddr) { uint32_t iid; lisp_addr_t *ip_pref; patricia_tree_t *pt; uint16_t afi; iid = lcaf_iid_get_iid(iidaddr); ip_pref = lcaf_get_ip_pref_addr(iidaddr); if (!ip_pref){ return (BAD); } afi = lisp_addr_ip_afi(ip_pref); pt = get_iid_pt_from_lcaf(db, iidaddr); if (!pt){ if ((_db_add_iid(db,iid,afi))!=GOOD){ return (BAD); } pt = get_iid_pt_from_lcaf(db, iidaddr); } if (pt_add_ippref(pt, lisp_addr_get_ippref(ip_pref),entry) != GOOD) { OOR_LOG(LDBG_3, "_add_iid_entry: Attempting to insert (%s) in the " "map-cache but couldn't add the entry to the patricia tree!", lcaf_addr_to_char(iidaddr)); return (BAD); } OOR_LOG(LDBG_3, "_add_iid_entry: Added map cache data for %s", lcaf_addr_to_char(iidaddr)); return (GOOD); } static void * _rm_iid_entry(mdb_t *db, lcaf_addr_t *iidaddr) { lisp_addr_t *ip_pref; patricia_tree_t *pt; pt = get_iid_pt_from_lcaf(db, iidaddr); if (!pt){ OOR_LOG(LDBG_3, "_rm_iid_entry: Attempting to remove (%s) in the " "map-cache but it doesn't exist", lcaf_addr_to_char(iidaddr)); return (NULL); } ip_pref = lcaf_get_ip_pref_addr(iidaddr); if (!ip_pref){ return (NULL); } return (pt_remove_ippref(pt, lisp_addr_get_ippref(ip_pref))); } static patricia_node_t * _find_iid_node(mdb_t *db, lcaf_addr_t *iidaddr, uint8_t exact) { patricia_node_t * node; lisp_addr_t *ip_pref; patricia_tree_t *pt; pt = get_iid_pt_from_lcaf(db, iidaddr); if (!pt){ OOR_LOG(LDBG_3, "_find_iid_entry: Couldn't find (%s) in the " "map-cache. No iid",lcaf_addr_to_char(iidaddr)); return (NULL); } if (exact){ ip_pref = lcaf_get_ip_pref_addr(iidaddr); if (!ip_pref){ return (NULL); } node = pt_find_ip_node_exact(pt, lisp_addr_ip_get_addr(ip_pref), lisp_addr_ip_get_plen(ip_pref)); }else{ ip_pref = lcaf_get_ip_addr(iidaddr); if (!ip_pref){ ip_pref = lcaf_get_ip_pref_addr(iidaddr); if (!ip_pref){ return (NULL); } } node = pt_find_ip_node(pt, lisp_addr_ip_get_addr(ip_pref)); } return (node); } static int _add_mc_entry(mdb_t *db, void *entry, lcaf_addr_t *mcaddr) { if (pt_add_mc_addr(get_mc_pt_from_lcaf(db, mcaddr), mcaddr, entry) != GOOD) { OOR_LOG(LDBG_2, "_add_mc_entry: Attempting to insert %s to map cache " "but failed! ", mc_type_to_char(mcaddr)); return (BAD); } else { OOR_LOG(LDBG_3, "_add_mc_entry: Added entry %s to mdb!", lcaf_addr_to_char(mcaddr)); } return (GOOD); } static void * _rm_mc_entry(mdb_t *db, lcaf_addr_t *mcaddr) { patricia_tree_t *pt; pt = get_mc_pt_from_lcaf(db,mcaddr); return (pt_remove_mc_addr(pt, mcaddr)); } static int _add_lcaf_entry(mdb_t *db, void *entry, lcaf_addr_t *lcaf) { switch (lcaf_addr_get_type(lcaf)) { case LCAF_IID: return (_add_iid_entry(db, entry, lcaf)); case LCAF_MCAST_INFO: return (_add_mc_entry(db, entry, lcaf)); default: OOR_LOG(LDBG_3, "_add_lcaf_entry: LCAF type %d not supported!", lcaf_addr_get_type(lcaf)); } return (BAD); } static void * _del_lcaf_entry(mdb_t *db, lcaf_addr_t *lcaf) { switch (lcaf_addr_get_type(lcaf)) { case LCAF_IID: return (_rm_iid_entry(db,lcaf)); case LCAF_MCAST_INFO: return (_rm_mc_entry(db,lcaf)); default: OOR_LOG(LDBG_3, "_del_lcaf_entry: called with unknown LCAF type:%u", lcaf_addr_get_type(lcaf)); break; } return (NULL); } patricia_tree_t * _get_local_db_for_lcaf_addr(mdb_t *db, lcaf_addr_t *lcaf) { switch (lcaf_addr_get_type(lcaf)) { case LCAF_IID: return (get_iid_pt_from_lcaf(db,lcaf)); case LCAF_MCAST_INFO: return (get_mc_pt_from_lcaf(db, lcaf)); default: OOR_LOG(LDBG_3, "_get_local_db_for_lcaf_addr: LCAF type %d not supported!", lcaf_addr_get_type(lcaf)); break; } return (NULL); } patricia_tree_t * _get_local_db_for_addr(mdb_t *db, lisp_addr_t *addr) { switch (lisp_addr_lafi(addr)) { case LM_AFI_IP: case LM_AFI_IPPREF: return (get_ip_pt_from_afi(db, lisp_addr_ip_afi(addr))); case LM_AFI_LCAF: return (_get_local_db_for_lcaf_addr(db, lisp_addr_get_lcaf(addr))); default: OOR_LOG(LDBG_3, "_get_db_for_addr: called with unsupported afi(%d)", lisp_addr_lafi(addr)); } return (NULL); } mdb_t * mdb_new() { mdb_t *db = xzalloc(sizeof(mdb_t)); OOR_LOG(LDBG_3, " Creating mdb..."); db->AF4_ip_db = New_Patricia(sizeof(struct in_addr) * 8); db->AF6_ip_db = New_Patricia(sizeof(struct in6_addr) * 8); /* IID TABLES*/ db->AF4_iid_db = int_htable_new(); db->AF6_iid_db = int_htable_new(); /* MC is stored as patricia in patricia, what follows is a HACK * to have compatible walk methods for both IP and MC. */ ip_addr_t ipv4, ipv6; memset(&ipv4, 0, sizeof(ip_addr_t)); ip_addr_set_afi(&ipv4, AF_INET); memset(&ipv6, 0, sizeof(ip_addr_t)); ip_addr_set_afi(&ipv6, AF_INET6); pt_add_node(db->AF4_ip_db, &ipv4, 0, (void *) New_Patricia(sizeof(struct in_addr) * 8)); pt_add_node(db->AF6_ip_db, &ipv6, 0, (void *) New_Patricia(sizeof(struct in6_addr) * 8)); db->AF4_mc_db = New_Patricia(sizeof(struct in_addr) * 8); db->AF6_mc_db = New_Patricia(sizeof(struct in6_addr) * 8); if (!db->AF4_ip_db->head->data || !db->AF6_ip_db->head->data || !db->AF4_mc_db || !db->AF6_mc_db) { OOR_LOG(LCRIT, "mdb_init: Unable to allocate memory for mdb"); return(BAD); } db->n_entries = 0; return (db); } void mdb_del(mdb_t *db, mdb_del_fct del_fct) { patricia_node_t *node; void *value; Destroy_Patricia(db->AF4_ip_db->head->data, del_fct); Destroy_Patricia(db->AF4_ip_db, NULL); Destroy_Patricia(db->AF6_ip_db->head->data, del_fct); Destroy_Patricia(db->AF6_ip_db, NULL); /* Remove IID db */ int_htable_foreach_value(db->AF4_iid_db, value){ Destroy_Patricia(((patricia_tree_t *)value)->head->data, del_fct); Destroy_Patricia(value, NULL); }int_htable_foreach_value_end; int_htable_destroy(db->AF4_iid_db); int_htable_foreach_value(db->AF6_iid_db, value){ Destroy_Patricia(((patricia_tree_t *)value)->head->data, del_fct); Destroy_Patricia(value, NULL); }int_htable_foreach_value_end; int_htable_destroy(db->AF6_iid_db); if (db->AF4_mc_db->head) { PATRICIA_WALK(db->AF4_mc_db->head, node) { Destroy_Patricia(node->data, del_fct); } PATRICIA_WALK_END; } Destroy_Patricia(db->AF4_mc_db, NULL); if (db->AF6_mc_db->head) { PATRICIA_WALK(db->AF6_mc_db->head, node) { Destroy_Patricia(node->data, del_fct); } PATRICIA_WALK_END; } Destroy_Patricia(db->AF6_mc_db, NULL); free(db); } int mdb_add_entry(mdb_t *db, lisp_addr_t *addr, void *data) { int retval = 0; switch (lisp_addr_lafi(addr)) { case LM_AFI_IP: OOR_LOG(LWRN, "mdb_add_entry: mapping stores an IP prefix not an IP!"); break; case LM_AFI_IPPREF: retval = _add_ippref_entry(db, data, lisp_addr_get_ippref(addr)); break; case LM_AFI_LCAF: retval = _add_lcaf_entry(db, data, lisp_addr_get_lcaf(addr)); break; default: retval = BAD; OOR_LOG(LWRN, "mdb_add_entry: called with unknown AFI:%u", lisp_addr_lafi(addr)); break; } if (retval != GOOD) { OOR_LOG(LDBG_3, "mdb_add_entry: failed to insert entry %s", lisp_addr_to_char(addr)); return (BAD); } else { OOR_LOG(LDBG_3, "mdb_add_entry: inserted %s", lisp_addr_to_char(addr)); db->n_entries++; return (GOOD); } } void * mdb_remove_entry(mdb_t *db, lisp_addr_t *laddr) { ip_prefix_t *ippref; lisp_addr_t *taddr; void *ret = NULL; switch (lisp_addr_lafi(laddr)) { case LM_AFI_IP: /* make ippref */ taddr = lisp_addr_clone(laddr); lisp_addr_ip_to_ippref(taddr); ippref = lisp_addr_get_ippref(taddr); ret = pt_remove_ippref(get_ip_pt_from_afi(db, ip_prefix_afi(ippref)), ippref); lisp_addr_del(taddr); break; case LM_AFI_IPPREF: ippref = lisp_addr_get_ippref(laddr); ret = pt_remove_ippref( get_ip_pt_from_afi(db, ip_prefix_afi(ippref)), ippref); break; case LM_AFI_LCAF: ret = _del_lcaf_entry(db, lisp_addr_get_lcaf(laddr)); break; default: OOR_LOG(LWRN, "mdb_del_entry: called with unknown AFI:%u", lisp_addr_lafi(laddr)); break; } if (ret) { db->n_entries--; } return (ret); } void * mdb_lookup_entry(mdb_t *db, lisp_addr_t *laddr) { patricia_node_t *node; node = _find_node(db, laddr, NOT_EXACT); if (node){ return(node->data); }else{ return(NULL); } } void * mdb_lookup_entry_exact(mdb_t *db, lisp_addr_t *laddr) { patricia_node_t *node; node = _find_node(db, laddr, EXACT); if (node){ return(node->data); }else{ return(NULL); } } inline int mdb_n_entries(mdb_t *mdb) { return(mdb->n_entries); } /* * Patricia trie wrappers */ /* interface to insert entries into patricia */ int pt_add_ippref(patricia_tree_t *pt, ip_prefix_t *ippref, void *data) { patricia_node_t *node = NULL; node = pt_add_node(pt, ip_prefix_addr(ippref), ip_prefix_get_plen(ippref), data); if (!node) { return(BAD); } else { return(GOOD); } } int pt_add_mc_addr(patricia_tree_t *strie, lcaf_addr_t *mcaddr, void *data) { patricia_node_t *snode = NULL; patricia_node_t *gnode = NULL; lisp_addr_t *src = NULL; lisp_addr_t *grp = NULL; ip_addr_t *srcip = NULL; ip_addr_t *grpip = NULL; uint8_t splen, gplen; src = lcaf_mc_get_src(mcaddr); grp = lcaf_mc_get_grp(mcaddr); if (lisp_addr_lafi(src) != LM_AFI_IP || lisp_addr_lafi(grp) != LM_AFI_IP) { OOR_LOG(LWRN, "pt_add_mc_addr: only IP type supported for S %s and G %s for now!", lisp_addr_to_char(src), lisp_addr_to_char(grp)); return(BAD); } srcip = lisp_addr_ip(src); grpip = lisp_addr_ip(grp); splen = lcaf_mc_get_src_plen(mcaddr); gplen = lcaf_mc_get_grp_plen(mcaddr); /* insert src prefix in main db but without any data*/ snode = pt_add_node(strie, srcip, splen, NULL); if (snode == NULL) { OOR_LOG(LDBG_3, "pt_add_mc_addr: Attempting to " "insert S-EID %s/%d in strie pt but failed", ip_addr_to_char(srcip), splen); return(BAD); } /* insert the G in the user1 field of the unicast pt node */ if(!snode->data){ /* create the patricia if not initialized */ snode->data = (patricia_tree_t *)New_Patricia(ip_addr_get_size(grpip) * 8); if (!snode->data){ OOR_LOG(LDBG_3, "pt_add_mc_addr: Can't create group pt!"); return(BAD); } } /* insert grp in node->user1 db with the entry*/ gnode = pt_add_node((patricia_tree_t *)snode->data, grpip, gplen, data); if (gnode == NULL){ OOR_LOG(LDBG_3, "pt_add_mc_addr: Attempting to " "insert G %s/%d in the group pt but failed! ", ip_addr_to_char(grpip), gplen); return(BAD); } return(GOOD); } void * pt_remove_ippref(patricia_tree_t *pt, ip_prefix_t *ippref) { patricia_node_t *node = NULL; void *data = NULL; node = pt_find_ip_node_exact(pt, ip_prefix_addr(ippref), ip_prefix_get_plen(ippref)); if (node == NULL){ OOR_LOG(LDBG_3,"pt_remove_ip_addr: Unable to locate cache entry %s for deletion", ip_prefix_to_char(ippref)); return(BAD); } else { OOR_LOG(LDBG_3,"pt_remove_ip_addr: removing entry with key: %s", ip_prefix_to_char(ippref)); } data = node->data; pt_remove_node(pt, node); return(data); } void * pt_remove_mc_addr(patricia_tree_t *strie, lcaf_addr_t *mcaddr) { patricia_node_t *gnode = NULL; patricia_tree_t *gtrie = NULL; lisp_addr_t *src = NULL; lisp_addr_t *grp = NULL; void *data = NULL; if (!strie) { OOR_LOG(LDBG_3, "pt_remove_mc_addr: strie for %s not initialized. Aborting!", lcaf_addr_to_char(mcaddr)); return(NULL); } src = lcaf_mc_get_src(mcaddr); grp = lcaf_mc_get_grp(mcaddr); if (lisp_addr_lafi(src) != LM_AFI_IP || lisp_addr_lafi(grp) != LM_AFI_IP) { OOR_LOG(LDBG_3, "pt_remove_mc_addr: only IP AFI supported for S and G"); return(NULL); } gtrie = _get_grp_pt_for_mc_addr(strie, mcaddr, 1); if (!gtrie){ OOR_LOG(LDBG_3, "pt_remove_mc_addr: Couldn't find a group trie for mc " "address %s", lcaf_addr_to_char(mcaddr)); return(NULL); } gnode = pt_find_ip_node_exact(gtrie, lisp_addr_ip(grp), lcaf_mc_get_grp_plen(mcaddr)); if (!gnode){ OOR_LOG(LDBG_3, "pt_remove_mc_addr: The multicast address %s could not" " be found!", lcaf_addr_to_char(mcaddr)); return(NULL); } data = gnode->data; pt_remove_node(gtrie, gnode); if (pt_test_if_empty(gtrie)){ Destroy_Patricia(gtrie, NULL); pt_remove_node(strie, pt_find_ip_node_exact(strie, lisp_addr_ip(src), lcaf_mc_get_src_plen(mcaddr))); } return(data); } patricia_node_t * pt_add_node(patricia_tree_t *pt, ip_addr_t *ipaddr, uint8_t prefixlen, void *data) { patricia_node_t *node; prefix_t *prefix; prefix = pt_make_ip_prefix(ipaddr, prefixlen); node = patricia_lookup(pt, prefix); Deref_Prefix(prefix); if (!node) { OOR_LOG(LDBG_3, "pt_add_node: patricia_lookup did not return a node!"); return(NULL); } /* node already exists */ if (node->data) { OOR_LOG(LDBG_3, "pt_add_node: Node with prefix %s exists! Data won't be" " changed", ip_addr_to_char(ipaddr)); return(node); } node->data = data; return(node); } inline void pt_remove_node(patricia_tree_t *pt, patricia_node_t *node) { patricia_remove(pt, node); } patricia_node_t * pt_find_ip_node(patricia_tree_t *pt, ip_addr_t *ipaddr) { patricia_node_t *node; prefix_t *prefix; uint8_t default_plen; default_plen = (ip_addr_afi(ipaddr) == AF_INET) ? 32: 128; prefix = pt_make_ip_prefix(ipaddr, default_plen); node = patricia_search_best(pt, prefix); Deref_Prefix(prefix); return(node); } patricia_node_t *pt_find_ip_node_exact(patricia_tree_t *pt, ip_addr_t *ipaddr, uint8_t prefixlen) { patricia_node_t *node; prefix_t *prefix; prefix = pt_make_ip_prefix(ipaddr, prefixlen); node = patricia_search_exact(pt, prefix); Deref_Prefix(prefix); return(node); } patricia_node_t *pt_find_mc_node(patricia_tree_t *strie, lcaf_addr_t *mcaddr, uint8_t exact) { patricia_node_t *gnode = NULL; lisp_addr_t *src = NULL; lisp_addr_t *grp = NULL; patricia_tree_t *gtrie = NULL; if (!strie) { OOR_LOG(LDBG_3, "pt_remove_mc_addr: no S trie. Aborting"); return(NULL); } src = lcaf_mc_get_src(mcaddr); grp = lcaf_mc_get_grp(mcaddr); // src = lcaf_mc_get_src(mcaddr); // grp = lcaf_mc_get_grp(mcaddr); if (lisp_addr_lafi(src) != LM_AFI_IP || lisp_addr_lafi(grp) != LM_AFI_IP) { OOR_LOG(LDBG_3, "pt_remove_mc_addr: only IP AFI supported for S and G"); return(NULL); } gtrie = _get_grp_pt_for_mc_addr(strie, mcaddr, exact); if (!gtrie){ OOR_LOG(LDBG_3, "pt_find_mc_node: Couldn't find a group trie for mc address %s", lcaf_addr_to_char(mcaddr)); return(NULL); } // if (exact) // gnode = pt_find_ip_node_exact(gtrie, lisp_addr_get_ip(grp), lcaf_mc_get_grp_plen(mcaddr)); // else gnode = pt_find_ip_node(gtrie, lisp_addr_ip(grp)); return(gnode); } uint8_t pt_test_if_empty(patricia_tree_t *pt) { if (pt->num_active_node > 0) return(0); else return(1); } prefix_t *pt_make_ip_prefix(ip_addr_t *ipaddr, uint8_t prefixlen) { int afi = 0; prefix_t *prefix = NULL; afi = ip_addr_afi(ipaddr); if (afi != AF_INET && afi != AF_INET6) { OOR_LOG(LWRN, "make_ip_prefix_for_pt: Unsupported afi %s", afi); return(NULL); } (afi == AF_INET) ? assert(prefixlen <= 32) : assert(prefixlen <= 128); prefix = New_Prefix(afi, ip_addr_get_addr(ipaddr), prefixlen); if (!prefix) { OOR_LOG(LWRN, "make_ip_prefix_for_pt: Unable to allocate memory for " "prefix %s: %s", ip_addr_to_char(ipaddr), strerror(errno)); return(NULL); } return(prefix); } /* * use this function to access all entries in the map-cache */ void mdb_for_each_entry_cb(mdb_t *mdb, void (*callback)(void *, void *), void *cb_data) { void *it; mdb_foreach_ip_entry(mdb, it) { callback(it, cb_data); } mdb_foreach_ip_entry_end; mdb_foreach_mc_entry(mdb, it) { callback(it, cb_data); } mdb_foreach_mc_entry_end; } oor-1.2.0/oor/lib/mapping_db.h000066400000000000000000000275211313612200500161270ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ /* * This defines a mappings database (mdb) that relies on patricia tries and hash tables * to store IP and LCAF based EIDs. Among the supported LCAFs are multicast of type (S,G) and IID. * It is used to implement both the mappings cache and the local mapping db. */ #ifndef MAPPING_DB_H_ #define MAPPING_DB_H_ #include "int_table.h" #include "../elibs/patricia/patricia.h" #include "../liblisp/lisp_address.h" #define NOT_EXACT 0 #define EXACT 1 /* * Patricia tree based databases * for IP/IP-prefix and multicast addresses */ typedef struct { patricia_tree_t *AF4_ip_db; patricia_tree_t *AF6_ip_db; int_htable *AF4_iid_db; int_htable *AF6_iid_db; patricia_tree_t *AF4_mc_db; patricia_tree_t *AF6_mc_db; int n_entries; } mdb_t; typedef void (*mdb_del_fct)(void *); mdb_t *mdb_new(); void mdb_del(mdb_t *db, mdb_del_fct del_fct); int mdb_add_entry(mdb_t *db, lisp_addr_t *addr, void *data); void *mdb_remove_entry(mdb_t *db, lisp_addr_t *laddr); void *mdb_lookup_entry(mdb_t *db, lisp_addr_t *laddr); void *mdb_lookup_entry_exact(mdb_t *db, lisp_addr_t *laddr); int mdb_n_entries(mdb_t *); patricia_tree_t *_get_local_db_for_lcaf_addr(mdb_t *db, lcaf_addr_t *lcaf); patricia_tree_t *_get_local_db_for_addr(mdb_t *db, lisp_addr_t *addr); #define mdb_foreach_entry(_mdb, _it) \ do { \ void * _pt_; \ glist_entry_t *_pt_it_; \ patricia_tree_t *_ptree_; \ patricia_node_t *_node, *_nodein; \ glist_t *_pt_list_ = glist_new(); \ glist_add((_mdb)->AF4_ip_db,_pt_list_); \ glist_add((_mdb)->AF6_ip_db,_pt_list_); \ int_htable_foreach_value((_mdb)->AF4_iid_db,_pt_){ \ glist_add(_pt_,_pt_list_); \ }int_htable_foreach_value_end; \ int_htable_foreach_value((_mdb)->AF6_iid_db,_pt_){ \ glist_add(_pt_,_pt_list_); \ }int_htable_foreach_value_end; \ glist_add((_mdb)->AF4_mc_db,_pt_list_); \ glist_add((_mdb)->AF4_mc_db,_pt_list_); \ glist_for_each_entry(_pt_it_, _pt_list_){ \ _ptree_ = (patricia_tree_t *)glist_entry_data(_pt_it_); \ PATRICIA_WALK(_ptree_->head, _node) { \ PATRICIA_WALK(((patricia_tree_t *)(_node->data))->head, _nodein) { \ if ((_it = _nodein->data)){ #define mdb_foreach_entry_end \ } \ } PATRICIA_WALK_END; \ } PATRICIA_WALK_END; \ } \ glist_destroy(_pt_list_); \ } while (0) #define mdb_foreach_entry_with_break(_mdb, _it, _break) \ do { \ void * _pt_; \ glist_entry_t *_pt_it_; \ patricia_tree_t *_ptree_; \ patricia_node_t *_node, *_nodein; \ glist_t *_pt_list_ = glist_new(); \ glist_add((_mdb)->AF4_ip_db,_pt_list_); \ glist_add((_mdb)->AF6_ip_db,_pt_list_); \ int_htable_foreach_value((_mdb)->AF4_iid_db,_pt_){ \ glist_add(_pt_,_pt_list_); \ }int_htable_foreach_value_end; \ int_htable_foreach_value((_mdb)->AF6_iid_db,_pt_){ \ glist_add(_pt_,_pt_list_); \ }int_htable_foreach_value_end; \ glist_add((_mdb)->AF4_mc_db,_pt_list_); \ glist_add((_mdb)->AF4_mc_db,_pt_list_); \ glist_for_each_entry(_pt_it_, _pt_list_){ \ _ptree_ = (patricia_tree_t *)glist_entry_data(_pt_it_); \ PATRICIA_WALK(_ptree_->head, _node) { \ PATRICIA_WALK(((patricia_tree_t *)(_node->data))->head, _nodein) { \ if ((_it = _nodein->data)){ #define mdb_foreach_entry_with_break_end(_break) \ if (_break){ \ break; \ } \ } \ } PATRICIA_WALK_END; \ if (_break){ \ break; \ } \ } PATRICIA_WALK_END; \ if (_break){ \ break; \ } \ } \ glist_destroy(_pt_list_); \ } while (0) #define mdb_foreach_ip_entry(_mdb, _it) \ do { \ void * _pt_; \ glist_entry_t *_pt_it_; \ patricia_tree_t *_ptree_; \ patricia_node_t *_node, *_nodein; \ glist_t *_pt_list_ = glist_new(); \ glist_add((_mdb)->AF4_ip_db,_pt_list_); \ glist_add((_mdb)->AF6_ip_db,_pt_list_); \ int_htable_foreach_value((_mdb)->AF4_iid_db,_pt_){ \ glist_add(_pt_,_pt_list_); \ }int_htable_foreach_value_end; \ int_htable_foreach_value((_mdb)->AF6_iid_db,_pt_){ \ glist_add(_pt_,_pt_list_); \ }int_htable_foreach_value_end; \ glist_for_each_entry(_pt_it_, _pt_list_){ \ _ptree_ = (patricia_tree_t *)glist_entry_data(_pt_it_); \ PATRICIA_WALK(_ptree_->head, _node) { \ PATRICIA_WALK(((patricia_tree_t *)(_node->data))->head, _nodein) { \ if ((_it = _nodein->data)){ #define mdb_foreach_ip_entry_end \ } \ } PATRICIA_WALK_END; \ } PATRICIA_WALK_END; \ } \ glist_destroy(_pt_list_); \ } while (0) #define mdb_foreach_ip_entry_with_break(_mdb, _it, _break) \ do { \ void * _pt_; \ glist_entry_t *_pt_it_; \ patricia_tree_t *_ptree_; \ patricia_node_t *_node, *_nodein; \ glist_t *_pt_list_ = glist_new(); \ glist_add((_mdb)->AF4_ip_db,_pt_list_); \ glist_add((_mdb)->AF6_ip_db,_pt_list_); \ int_htable_foreach_value((_mdb)->AF4_iid_db,_pt_){ \ glist_add(_pt_,_pt_list_); \ }int_htable_foreach_value_end; \ int_htable_foreach_value((_mdb)->AF6_iid_db,_pt_){ \ glist_add(_pt_,_pt_list_); \ }int_htable_foreach_value_end; \ glist_for_each_entry(_pt_it_, _pt_list_){ \ _ptree_ = (patricia_tree_t *)glist_entry_data(_pt_it_); \ PATRICIA_WALK(_ptree_->head, _node) { \ PATRICIA_WALK(((patricia_tree_t *)(_node->data))->head, _nodein) { \ if ((_it = _nodein->data)){ #define mdb_foreach_ip_entry_with_break_end(_break) \ if (_break){ \ break; \ } \ } \ } PATRICIA_WALK_END; \ if (_break){ \ break; \ } \ } PATRICIA_WALK_END; \ if (_break){ \ break; \ } \ } glist_destroy(_pt_list_); \ } while (0) #define mdb_foreach_mc_entry(_mdb, _it) \ do { \ patricia_tree_t *_ptstack[2] = {(_mdb)->AF4_mc_db, (_mdb)->AF6_mc_db}; \ patricia_node_t *_node, *_nodemc; \ int _i; \ for (_i=0; _i < 2; _i++) { \ PATRICIA_WALK(_ptstack[_i]->head, _node) { \ PATRICIA_WALK(((patricia_tree_t *)(_node->data))->head, _nodemc) { \ if ((_it = _nodemc->data)){ #define mdb_foreach_mc_entry_end \ } \ } PATRICIA_WALK_END; \ } PATRICIA_WALK_END; \ } \ } while (0) #define mdb_foreach_entry_in_ip_eid_db(_mdb, _eid, _it) \ do { \ patricia_tree_t * _eid_db; \ patricia_node_t *_node; \ _eid_db = _get_local_db_for_addr(_mdb, (_eid)); \ if (_eid_db){ \ PATRICIA_WALK(_eid_db->head, _node){ \ if (((_it) = _node->data)){ #define mdb_foreach_entry_in_ip_eid_db_end \ } \ }PATRICIA_WALK_END; \ } \ } while(0) #endif /* MAPPING_DB_H_ */ oor-1.2.0/oor/lib/mem_util.c000066400000000000000000000043741313612200500156360ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "mem_util.h" #include "oor_log.h" static void out_of_memory(void) { OOR_LOG(LCRIT, "virtual memory exhausted"); abort(); } void * xcalloc(size_t count, size_t size) { void *p = count && size ? calloc(count, size) : malloc(1); if (p == NULL) { out_of_memory(); } return p; } void * xzalloc(size_t size) { return xcalloc(1, size); } void * xmalloc(size_t size) { void *p = malloc(size ? size : 1); if (p == NULL) { out_of_memory(); } return p; } void * xrealloc(void *p, size_t size) { p = realloc(p, size ? size : 1); if (p == NULL) { out_of_memory(); } return p; } void * xmemdup(const void *p_, size_t size) { void *p = xmalloc(size); memcpy(p, p_, size); return p; } char * xmemdup0(const char *p_, size_t length) { char *p = xmalloc(length + 1); memcpy(p, p_, length); p[length] = '\0'; return p; } char * xstrdup(const char *s) { return xmemdup0(s, strlen(s)); } void lm_assert_failure(const char *where, const char *function, const char *condition) { /* Prevent an infinite loop (or stack overflow) in case VLOG_ABORT happens * to trigger an assertion failure of its own. */ static int reentry = 0; switch (reentry++) { case 0: OOR_LOG(LCRIT, "%s: assertion %s failed in %s()", where, condition, function); abort(); case 1: fprintf(stderr, "%s: assertion %s failed in %s()", where, condition, function); abort(); default: abort(); } } oor-1.2.0/oor/lib/mem_util.h000066400000000000000000000062021313612200500156330ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef MEM_UTIL_H_ #define MEM_UTIL_H_ #include #include #include #include #include #include #include #include #include #include #include #include "../defs.h" //#include "../elibs/ovs/ovs_util.h" /* Determine endianness */ #if defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN #define BIG_ENDIANS 2 #elif defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN #define LITTLE_ENDIANS 1 #elif defined(_BYTE_ORDER) && _BYTE_ORDER == _BIG_ENDIAN #define BIG_ENDIANS 2 #elif defined(_BYTE_ORDER) && _BYTE_ORDER == _LITTLE_ENDIAN #define LITTLE_ENDIANS 1 #elif defined(BYTE_ORDR) && BYTE_ORDER == BIG_ENDIAN #define BIG_ENDIANS 2 #elif defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN #define LITTLE_ENDIANS 1 #elif defined(__386__) #define LITTLE_ENDIANS 1 #else # error "Can't determine endianness" #endif /* Calculate Offset: Try not to make dumb mistakes with pointer arithmetic */ #define CO(addr,len) (((uint8_t *) addr + len)) /* sockaddr length */ #define SA_LEN(a) ((a == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6)) #define ARRAY_SIZE(x) ((sizeof x) / (sizeof *x)) /* compile attributes */ #define NO_RETURN __attribute__((__noreturn__)) #define LM_LIKELY(CONDITION) __builtin_expect(!!(CONDITION), 1) #define LM_UNLIKELY(CONDITION) __builtin_expect(!!(CONDITION), 0) /* Expands to a string that looks like ":", e.g. "tmp.c:10". * * See http://c-faq.com/ansi/stringize.html for an explanation of STRINGIZE and * STRINGIZE2. */ #define SOURCE_LOCATOR __FILE__ ":" STRINGIZE(__LINE__) #define STRINGIZE(ARG) STRINGIZE2(ARG) #define STRINGIZE2(ARG) #ARG #define BOLD "\033[1m" #define RESET "\033[0m" /* Like the standard assert macro, except: * * - Writes the failure message to the log. * * - Not affected by NDEBUG. */ #define lm_assert(CONDITION) \ if (!LM_LIKELY(CONDITION)) { \ lm_assert_failure(SOURCE_LOCATOR, __func__, #CONDITION); \ } void lm_assert_failure(const char *, const char *, const char *) NO_RETURN; void *xmalloc(size_t size); void *xzalloc(size_t size); void *xcalloc(size_t count, size_t size); void *xrealloc(void *p, size_t size); void *xmemdup(const void *p_, size_t size); char *xmemdup0(const char *p_, size_t length); char *xstrdup(const char *s); #endif /* MEM_UTIL_H_ */ oor-1.2.0/oor/lib/nonces_table.c000066400000000000000000000117071313612200500164550ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include #include "nonces_table.h" #include "oor_log.h" #include "mem_util.h" int nonce_list_cmp_nonce(void *nonce1, void *nonce2); void nonce_list_free_nonce(void *nonce); htable_nonces_t * htable_nonces_new() { htable_nonces_t * nonces_lst; nonces_lst = (htable_nonces_t *)malloc(sizeof(htable_nonces_t)); nonces_lst->ht = kh_init(nonces); return(nonces_lst); } void htable_nonces_insert(htable_nonces_t *nonces_ht, uint64_t nonce, nonces_list_t *nonces_lst) { khiter_t k; int ret; uint64_t *nonce_val; nonce_val = xmalloc(sizeof(uint64_t)); *nonce_val = nonce; glist_add(nonce_val,nonces_lst->nonces_list); k = kh_put(nonces,nonces_ht->ht,nonce,&ret); kh_value(nonces_ht->ht, k) = nonces_lst; } nonces_list_t * htable_nonces_remove(htable_nonces_t *nonces_ht, uint64_t nonce) { khiter_t k; nonces_list_t *nonces_lst; k = kh_get(nonces,nonces_ht->ht, nonce); if (k == kh_end(nonces_ht->ht)){ return (NULL); } nonces_lst = kh_value(nonces_ht->ht, k); glist_remove_obj(&nonce,nonces_lst->nonces_list); /* We don't remove the value as it can be pointed by several nonces*/ kh_del(nonces,nonces_ht->ht,k); return (nonces_lst); } void htable_nonces_destroy(htable_nonces_t *nonces_ht) { khiter_t k; nonces_list_t *nonces_lst; if (!nonces_ht) { return; } for (k = kh_begin(nonces_ht->ht); k != kh_end(nonces_ht->ht); ++k){ if (kh_exist(nonces_ht->ht, k)){ nonces_lst = kh_value(nonces_ht->ht, k); nonces_list_free(nonces_lst); } } kh_destroy(nonces,nonces_ht->ht); free (nonces_ht); } nonces_list_t * htable_nonces_lookup(htable_nonces_t *nonces_ht, uint64_t nonce) { khiter_t k; k = kh_get(nonces,nonces_ht->ht, nonce); if (k == kh_end(nonces_ht->ht)){ return (NULL); } return (kh_value(nonces_ht->ht,k)); } void htable_nonces_reset_nonces_lst(htable_nonces_t *nonces_ht,nonces_list_t *nonces_lst) { glist_t *nonces = nonces_lst->nonces_list; glist_entry_t *nonce_it, *aux_nonce_it; uint64_t *nonce; khiter_t k; glist_for_each_entry_safe(nonce_it,aux_nonce_it,nonces){ nonce = (uint64_t *)glist_entry_data(nonce_it); k = kh_get(nonces,nonces_ht->ht, *nonce); if (k == kh_end(nonces_ht->ht)){ continue; } glist_remove(nonce_it,nonces); kh_del(nonces,nonces_ht->ht,k); } } /* Generates a nonce random number. Requires librt */ uint64_t nonce_build(int seed) { uint64_t nonce; uint32_t nonce_lower; uint32_t nonce_upper; struct timespec ts; /* * Put nanosecond clock in lower 32-bits and put an XOR of the nanosecond * clock with the seond clock in the upper 32-bits. */ clock_gettime(CLOCK_MONOTONIC, &ts); nonce_lower = ts.tv_nsec; nonce_upper = ts.tv_sec ^ htonl(nonce_lower); /* * OR in a caller provided seed to the low-order 32-bits. */ nonce_lower |= seed; /* * Return 64-bit nonce. */ nonce = nonce_upper; nonce = (nonce << 32) | nonce_lower; return (nonce); } uint64_t nonce_new() { return(nonce_build((unsigned int) time(NULL))); } inline glist_t * nonces_list_list(nonces_list_t * nonces_lst) { return (nonces_lst->nonces_list); } inline oor_timer_t * nonces_list_timer(nonces_list_t * nonces_lst) { return (nonces_lst->timer); } inline nonces_list_t * nonces_list_new_init(oor_timer_t *timer) { nonces_list_t *nonces_lst; nonces_lst = xzalloc(sizeof(nonces_list_t)); if (!nonces_lst){ return (NULL); } nonces_lst->timer = timer; nonces_lst->nonces_list = glist_new_complete( (glist_cmp_fct)nonce_list_cmp_nonce, (glist_del_fct)nonce_list_free_nonce); return (nonces_lst); } void nonces_list_free(nonces_list_t *nonces_lst) { glist_destroy(nonces_lst->nonces_list); free(nonces_lst); } inline int nonces_list_size(nonces_list_t *nonces_lst) { return (glist_size(nonces_lst->nonces_list)); } int nonce_list_cmp_nonce(void *nonce1, void *nonce2) { uint64_t nonce_a = *((uint64_t *)nonce1); uint64_t nonce_b = *((uint64_t *)nonce2); return (nonce_a == nonce_b); } void nonce_list_free_nonce(void *nonce) { free((uint64_t *)nonce); } oor-1.2.0/oor/lib/nonces_table.h000066400000000000000000000036311313612200500164570ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef NONCES_TABLE_H_ #define NONCES_TABLE_H_ #include "../defs.h" #include "../elibs/khash/khash.h" #include "timers.h" typedef struct { glist_t *nonces_list; // oor_timer_t *timer; } nonces_list_t; KHASH_INIT(nonces, uint64_t, nonces_list_t *, 1, kh_int64_hash_func, kh_int64_hash_equal) //KHASH_MAP_INIT_INT64(nonces, nonces_list_t *) typedef struct htable_nonces_{ khash_t(nonces) *ht; }htable_nonces_t; htable_nonces_t *htable_nonces_new(); void htable_nonces_insert(htable_nonces_t *nonces_ht, uint64_t nonce, nonces_list_t *nonces_lst); nonces_list_t *htable_nonces_remove(htable_nonces_t *nonces_ht, uint64_t nonce); nonces_list_t *htable_nonces_lookup(htable_nonces_t *nonce_ht, uint64_t nonce); void htable_nonces_destroy(htable_nonces_t *nonces_ht); void htable_nonces_reset_nonces_lst(htable_nonces_t *nonces_ht, nonces_list_t *nonces_lst); uint64_t nonce_build(int seed); uint64_t nonce_new(); glist_t *nonces_list_list(nonces_list_t * nonces_lst); oor_timer_t *nonces_list_timer(nonces_list_t * nonces_lst); nonces_list_t *nonces_list_new_init(oor_timer_t *timer); void nonces_list_free(nonces_list_t *nonces_lst); int nonces_list_size(nonces_list_t *nonces_lst); #endif /* NONCES_TABLE_H_ */ oor-1.2.0/oor/lib/oor_log.c000066400000000000000000000103571313612200500154610ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include #include #include #include #include #include #include "oor_log.h" #ifdef ANDROID #include #endif FILE *fp = NULL; void oor_log(int log_level, char *log_name, const char *format, va_list args); void llog(int oor_log_level, const char *format, ...) { va_list args; char *log_name; /* To store the log level in string format for printf output */ int log_level; va_start(args, format); switch (oor_log_level){ case LCRIT: log_name = "CRIT"; log_level = LOG_CRIT; oor_log(log_level, log_name, format, args); break; case LERR: log_name = "ERR"; log_level = LOG_ERR; oor_log(log_level, log_name, format, args); break; case LWRN: log_name = "WARNING"; log_level = LOG_WARNING; oor_log(log_level, log_name, format, args); break; case LINF: log_name = "INFO"; log_level = LOG_INFO; oor_log(log_level, log_name, format, args); break; case LDBG_1: if (debug_level > 0){ log_name = "DEBUG"; log_level = LOG_DEBUG; oor_log(log_level, log_name, format, args); } break; case LDBG_2: if (debug_level > 1){ log_name = "DEBUG-2"; log_level = LOG_DEBUG; oor_log(log_level, log_name, format, args); } break; case LDBG_3: if (debug_level > 2){ log_name = "DEBUG-3"; log_level = LOG_DEBUG; oor_log(log_level, log_name, format, args); } break; default: log_name = "LOG"; log_level = LOG_INFO; oor_log(log_level, log_name, format, args); break; } va_end (args); } inline void oor_log(int log_level, char *log_name, const char *format, va_list args) { time_t t = time(NULL); struct tm tm = *localtime(&t); #ifdef ANDROID __android_log_vprint(ANDROID_LOG_INFO, "OOR-C ==>", format,args); if (fp != NULL){ fprintf(fp,"[%d/%d/%d %d:%d:%d] %s: ", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, log_name); vfprintf(fp,format,args); fprintf(fp,"\n"); fflush(fp); }else{ vsyslog(log_level,format,args); } if(!daemonize){ printf("[%d/%d/%d %d:%d:%d] %s: ", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, log_name); vfprintf(stdout,format,args); printf("\n"); } #else if (daemonize){ if (fp != NULL){ fprintf(fp,"[%d/%d/%d %d:%d:%d] %s: ", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, log_name); vfprintf(fp,format,args); fprintf(fp,"\n"); fflush(fp); }else{ vsyslog(log_level,format,args); } }else{ printf("[%d/%d/%d %d:%d:%d] %s: ", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, log_name); vfprintf(stdout,format,args); printf("\n"); } #endif } void open_log_file(char *log_file) { if (log_file == NULL){ return; } /* Overwrite log file in each start */ fp = freopen(log_file, "w", stderr); if (fp == NULL){ OOR_LOG(LERR,"Couldn't open the log file %s: %s. Using syslog", log_file, strerror(errno)); } } void close_log_file() { if (fp != NULL){ fclose (fp); } } oor-1.2.0/oor/lib/oor_log.h000066400000000000000000000041351313612200500154630ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef OOR_LOG_H_ #define OOR_LOG_H_ #include "../oor_external.h" extern int debug_level; /* If these set of defines is modified, check the function is_loggable() */ #define LCRIT 1 /* critical conditions -> Exit program */ #define LERR 2 /* error conditions -> Not exit but should be considered by user */ #define LWRN 3 /* warning conditions -> Low level errors. Program doesn't finish */ #define LINF 4 /* informational -> Initial configuration, SMRs, interface change status*/ #define LDBG_1 5 /* low debug-level messages -> Control message */ #define LDBG_2 6 /* medium debug-level messages -> Errors in received packets. Wrong AFI, ... */ #define LDBG_3 7 /* high debug-level messages -> Log for each received or generated packet */ #define OOR_LOG(...) LLOG(__VA_ARGS__) #define LLOG(level__, ...) \ do { \ if (is_loggable(level__)) { \ llog(level__, __VA_ARGS__); \ } \ } while (0) void llog(int oor_log_level, const char *format, ...); void open_log_file(char *log_file); void close_log_file(); /* True if log_level is enough to print results */ static inline int is_loggable(int log_level) { if (log_level < LDBG_1) return (TRUE); else if (log_level <= LINF + debug_level) return (TRUE); return (FALSE); } #endif /*OOR_LOG_H_*/ oor-1.2.0/oor/lib/packets.c000066400000000000000000000460641313612200500154570ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include #include "cksum.h" #include "oor_log.h" #include "mem_util.h" #include "packets.h" #include "sockets.h" #include "../oor_external.h" /* needed for hashword */ #include "../elibs/bob/lookup3.c" #include "../liblisp/lisp_address.h" #define LISP_CONTROL_PORT 4342 #define LISP_DATA_PORT 4341 uint16_t ip_id = 0; /* Returns IP ID for the packet */ static inline uint16_t get_IP_ID() { ip_id++; return (ip_id); } void * pkt_pull_eth(lbuf_t *b) { return(lbuf_pull(b, sizeof(struct ether_header))); } void * pkt_pull_ipv4(lbuf_t *b) { return(lbuf_pull(b, sizeof(struct ip))); } void * pkt_pull_ipv6(lbuf_t *b) { return(lbuf_pull(b, sizeof(struct ip6_hdr))); } void * pkt_pull_ip(lbuf_t *b) { void *data; int ip_hdr_len; data = lbuf_data(b); ip_hdr_len = ip_hdr_ver_to_len(((struct ip *)data)->ip_v); if (ip_hdr_len < 1) { return(NULL); } return(lbuf_pull(b, ip_hdr_len)); } struct udphdr * pkt_pull_udp(lbuf_t *b) { struct udphdr *udph; udph = lbuf_data(b); /* Jump the UDP header */ lbuf_pull(b, sizeof(struct udphdr)); return(udph); } void * pkt_push_udp(lbuf_t *b, uint16_t sp, uint16_t dp) { struct udphdr *uh; int udp_len; udp_len = sizeof(struct udphdr) + lbuf_size(b); uh = lbuf_push_uninit(b, sizeof(struct udphdr)); udpsport(uh) = htons(sp); udpdport(uh) = htons(dp); udplen(uh) = htons(udp_len); udpsum(uh) = 0; /* to be filled in after IP is pushed */ return(uh); } void * pkt_push_eth(lbuf_t *b, uint8_t ether_dhost[ETHER_ADDR_LEN], uint8_t ether_shost[ETHER_ADDR_LEN], uint16_t ether_type) { struct ether_header *eth; eth = lbuf_push_uninit(b, sizeof(struct ether_header)); eth->ether_type = htons(ether_type); memcpy (&(eth->ether_dhost),ether_dhost, ETHER_ADDR_LEN*sizeof(uint8_t)); memcpy (&(eth->ether_shost),ether_shost, ETHER_ADDR_LEN*sizeof(uint8_t)); return(eth); } struct ip * pkt_push_ipv4(lbuf_t *b, struct in_addr *src, struct in_addr *dst, int proto) { struct ip *iph; iph = lbuf_push_uninit(b, sizeof(struct ip)); /* XXX: assume no other headers */ iph->ip_hl = 5; iph->ip_v = IPVERSION; iph->ip_tos = 0; iph->ip_len = htons(lbuf_size(b)); iph->ip_id = htons(get_IP_ID()); /* Do not fragment flag. See 5.4.1 in LISP RFC (6830) * TODO: decide if we allow fragments in case of control */ iph->ip_off = htons(IP_DF); iph->ip_ttl = 255; iph->ip_p = proto; iph->ip_src.s_addr = src->s_addr; iph->ip_dst.s_addr = dst->s_addr; /* FIXME: ip checksum could be offloaded to NIC*/ /* iph->ip_sum = 0; */ iph->ip_sum = ip_checksum((uint16_t *) iph, sizeof(struct ip)); return(iph); } struct ip6_hdr * pkt_push_ipv6(lbuf_t *b, struct in6_addr *src, struct in6_addr *dst, int proto) { struct ip6_hdr *ip6h; int len; len = lbuf_size(b); ip6h = lbuf_push_uninit(b, sizeof(struct ip6_hdr)); ip6h->ip6_hops = 255; ip6h->ip6_vfc = (IP6VERSION << 4); ip6h->ip6_nxt = proto; ip6h->ip6_plen = htons(len); memcpy(ip6h->ip6_src.s6_addr, src->s6_addr, sizeof(struct in6_addr)); memcpy(ip6h->ip6_dst.s6_addr, dst->s6_addr, sizeof(struct in6_addr)); return(ip6h); } void * pkt_push_ip(lbuf_t *b, ip_addr_t *src, ip_addr_t *dst, int proto) { void *iph = NULL; if (ip_addr_afi(src) != ip_addr_afi(dst)) { OOR_LOG(LDBG_1, "src %s and dst %s IP have different AFI! Discarding!", ip_addr_to_char(src), ip_addr_to_char(dst)); return(NULL); } switch (ip_addr_afi(src)) { case AF_INET: iph = pkt_push_ipv4(b, ip_addr_get_addr(src), ip_addr_get_addr(dst), proto); break; case AF_INET6: iph = pkt_push_ipv6(b, ip_addr_get_addr(src), ip_addr_get_addr(dst), proto); break; } return(iph); } //struct ether_header * //pkt_push_eth(lbuf_t *b, ether_dhost[ETH_ALEN], , int proto) //{ // struct ip6_hdr *ip6h; // int len; // // len = lbuf_size(b); // ip6h = lbuf_push_uninit(b, sizeof(struct ip6_hdr)); // // ip6h->ip6_hops = 255; // ip6h->ip6_vfc = (IP6VERSION << 4); // ip6h->ip6_nxt = proto; // ip6h->ip6_plen = htons(len); // memcpy(ip6h->ip6_src.s6_addr, src->s6_addr, sizeof(struct in6_addr)); // memcpy(ip6h->ip6_dst.s6_addr, dst->s6_addr, sizeof(struct in6_addr)); // return(ip6h); //} int pkt_push_udp_and_ip(lbuf_t *b, uint16_t sp, uint16_t dp, ip_addr_t *sip, ip_addr_t *dip) { uint16_t udpsum; struct udphdr *uh; if (pkt_push_udp(b, sp, dp) == NULL) { OOR_LOG(LDBG_1, "Failed to push UDP header! Discarding"); return(BAD); } lbuf_reset_udp(b); if (pkt_push_ip(b, sip, dip, IPPROTO_UDP) == NULL) { OOR_LOG(LDBG_1, "Failed to push IP header! Discarding"); return(BAD); } lbuf_reset_ip(b); uh = lbuf_udp(b); udpsum = udp_checksum(uh, ntohs(udplen(uh)), lbuf_ip(b), ip_addr_afi(sip)); if (udpsum == (uint16_t) ~ 0) { OOR_LOG(LDBG_1, "Failed UDP checksum! Discarding"); return (BAD); } udpsum(uh) = udpsum; return(GOOD); } /* Fill the tuple with the 5 tuples of a packet: * (SRC IP, DST IP, PROTOCOL, SRC PORT, DST PORT) */ int pkt_parse_5_tuple(lbuf_t *b, packet_tuple_t *tuple) { struct iphdr *iph = NULL; struct ip6_hdr *ip6h = NULL; struct udphdr *udp = NULL; struct tcphdr *tcp = NULL; lbuf_t packet = *b; iph = lbuf_ip(&packet); lisp_addr_set_lafi(&tuple->src_addr, LM_AFI_IP); lisp_addr_set_lafi(&tuple->dst_addr, LM_AFI_IP); switch (iph->version) { case 4: lisp_addr_ip_init(&tuple->src_addr, &iph->saddr, AF_INET); lisp_addr_ip_init(&tuple->dst_addr, &iph->daddr, AF_INET); tuple->protocol = iph->protocol; lbuf_pull(&packet, iph->ihl * 4); break; case 6: ip6h = (struct ip6_hdr *)iph; lisp_addr_ip_init(&tuple->src_addr, &ip6h->ip6_src, AF_INET6); lisp_addr_ip_init(&tuple->dst_addr, &ip6h->ip6_dst, AF_INET6); /* XXX: assuming no extra headers */ tuple->protocol = ip6h->ip6_nxt; lbuf_pull(&packet, sizeof(struct ip6_hdr)); break; default: OOR_LOG(LDBG_2, "pkt_parse_5_tuple: Not an IP packet!"); return (BAD); } if (tuple->protocol == IPPROTO_UDP) { udp = lbuf_data(&packet); tuple->src_port = ntohs(udpsport(udp)); tuple->dst_port = ntohs(udpdport(udp)); } else if (tuple->protocol == IPPROTO_TCP) { tcp = lbuf_data(&packet); tuple->src_port = ntohs(tcpsport(tcp)); tuple->dst_port = ntohs(tcpdport(tcp)); } else { /* If protocol is not TCP or UDP, ports of the tuple set to 0 */ tuple->src_port = 0; tuple->dst_port = 0; } return (GOOD); } /* Calculate the hash of the 5 tuples of a packet */ uint32_t pkt_tuple_hash(packet_tuple_t *tuple) { int hash = 0; int len = 0; int port = tuple->src_port; uint32_t *tuples = NULL; port = port + ((int)tuple->dst_port << 16); switch (lisp_addr_ip_afi(&tuple->src_addr)){ case AF_INET: /* 1 integer src_addr * + 1 integer dst_adr * + 1 integer (ports) * + 1 integer protocol * + 1 iid*/ len = 5; tuples = xmalloc(len * sizeof(uint32_t)); lisp_addr_copy_to(&tuples[0], &tuple->src_addr); lisp_addr_copy_to(&tuples[1], &tuple->dst_addr); tuples[2] = port; tuples[3] = tuple->protocol; tuples[4] = tuple->iid; break; case AF_INET6: /* 4 integer src_addr * + 4 integer dst_adr * + 1 integer (ports) * + 1 integer protocol * + 1 iid */ len = 11; tuples = xmalloc(len * sizeof(uint32_t)); lisp_addr_copy_to(&tuples[0], &tuple->src_addr); lisp_addr_copy_to(&tuples[4], &tuple->dst_addr); tuples[8] = port; tuples[9] = tuple->protocol; tuples[10] = tuple->iid; break; } /* XXX: why 2013 used as initial value? */ hash = hashword(tuples, len, 2013); free(tuples); return (hash); } /* Calculate the hash of the src, dst address of a packet */ uint32_t pkt_src_dst_hash(lisp_addr_t *src_addr, lisp_addr_t *dst_addr) { int hash = 0; int len = 0; uint32_t *tuples = NULL; switch (lisp_addr_ip_afi(src_addr)){ case AF_INET: /* 1 integer src_addr * + 1 integer dst_adr*/ len = 2; tuples = xmalloc(len * sizeof(uint32_t)); lisp_addr_copy_to(&tuples[0], src_addr); lisp_addr_copy_to(&tuples[1], dst_addr); break; case AF_INET6: /* 4 integer src_addr * + 4 integer dst_adr */ len = 8; tuples = xmalloc(len * sizeof(uint32_t)); lisp_addr_copy_to(&tuples[0], src_addr); lisp_addr_copy_to(&tuples[4], dst_addr); break; } /* XXX: why 2013 used as initial value? */ hash = hashword(tuples, len, 2013); free(tuples); return (hash); } int pkt_tuple_cmp(packet_tuple_t *t1, packet_tuple_t *t2) { return(t1->src_port == t2->src_port && t1->dst_port == t2->dst_port && (lisp_addr_cmp(&t1->src_addr, &t2->src_addr) == 0) && (lisp_addr_cmp(&t1->dst_addr, &t2->dst_addr) == 0) && t1->iid == t2->iid); } packet_tuple_t * pkt_tuple_clone(packet_tuple_t *tpl) { packet_tuple_t *cpy = xzalloc(sizeof(packet_tuple_t)); cpy->src_port = tpl->src_port; cpy->dst_port = tpl->dst_port; cpy->protocol = tpl->protocol; lisp_addr_copy(&cpy->src_addr, &tpl->src_addr); lisp_addr_copy(&cpy->dst_addr, &tpl->dst_addr); cpy->iid = tpl->iid; return(cpy); } void pkt_tuple_del(packet_tuple_t *tpl) { lisp_addr_dealloc(&tpl->dst_addr); lisp_addr_dealloc(&tpl->src_addr); free(tpl); tpl = NULL; } char * pkt_tuple_to_char(packet_tuple_t *tpl) { static char buf[2][200]; static int i=0; size_t buf_size = sizeof(buf[0]); /* hack to allow more than one locator per line */ i++; i = i % 2; *buf[i] = '\0'; if (tpl == NULL){ sprintf(buf[i], "_NULL_"); return (buf[i]); } snprintf(buf[i],buf_size, "Src_addr: %s, ", lisp_addr_to_char(&tpl->src_addr)); snprintf(buf[i] + strlen(buf[i]),buf_size - strlen(buf[i]),"Dst addr: %s, ", lisp_addr_to_char(&tpl->dst_addr)); snprintf(buf[i] + strlen(buf[i]),buf_size - strlen(buf[i]), "Proto: "); switch (tpl->protocol){ case IPPROTO_UDP: snprintf(buf[i] + strlen(buf[i]),buf_size - strlen(buf[i]), "UDP, "); break; case IPPROTO_TCP: snprintf(buf[i] + strlen(buf[i]),buf_size - strlen(buf[i]), "TCP, "); break; case IPPROTO_ICMP: snprintf(buf[i] + strlen(buf[i]),buf_size - strlen(buf[i]), "ICMP, "); break; default: snprintf(buf[i] + strlen(buf[i]),buf_size - strlen(buf[i]), "%d, ",tpl->protocol); break; } snprintf(buf[i] + strlen(buf[i]),buf_size - strlen(buf[i]), "Src Port: %d, ",tpl->src_port); snprintf(buf[i] + strlen(buf[i]),buf_size - strlen(buf[i]), "Dst Port: %d\n",tpl->dst_port); snprintf(buf[i] + strlen(buf[i]),buf_size - strlen(buf[i]), "IID|VNI: %d\n",tpl->iid); return (buf[i]); } inline int pkt_tuple_is_lisp(packet_tuple_t *tpl) { /* Don't encapsulate LISP messages */ if (tpl->protocol != IPPROTO_UDP) { return (FALSE); } /* If either of the udp ports are the control port or data, allow * to go out natively. This is a quick way around the * route filter which rewrites the EID as the source address. */ if (tpl->dst_port != LISP_CONTROL_PORT && tpl->src_port != LISP_CONTROL_PORT && tpl->src_port != LISP_DATA_PORT && tpl->dst_port != LISP_DATA_PORT) { return (FALSE); } return (TRUE); } int ip_hdr_set_ttl_and_tos(struct iphdr *iph, int ttl, int tos) { struct ip6_hdr *ip6h; if (iph->version == 4) { /*XXX It seems that there is a bug in uClibc that causes ttl=0 in * OpenWRT. This is a quick workaround */ if (ttl != 0) { iph->ttl = ttl; } iph->tos = tos; /* We need to recompute the checksum since we have changed the TTL * and TOS header fields. * * New checksum must be computed with the checksum header field * with 0s */ iph->check = 0; iph->check = ip_checksum((uint16_t*) iph, sizeof(struct iphdr)); } else if (iph->version == 6) { ip6h = (struct ip6_hdr *) iph; /*XXX It seems that there is a bug in uClibc that causes ttl=0 in * OpenWRT. This is a quick workaround */ if (ttl != 0) { /* ttl = Hops limit in IPv6 */ ip6h->ip6_hops = ttl; } /* tos = Traffic class field in IPv6 */ IPV6_SET_TC(ip6h, tos); } else { return(BAD); } return(GOOD); } int ip_hdr_ttl_and_tos(struct iphdr *iph, int *ttl, int *tos) { struct ip6_hdr *ip6h; switch (iph->version) { case 4: *tos = iph->tos; *ttl = iph->ttl; return(GOOD); case 6: ip6h = (struct ip6_hdr *) iph; *ttl = ip6h->ip6_hops; *tos = IPV6_GET_TC(*ip6h); return(GOOD); default: return(BAD); } } /* * Generate IP header. Returns the pointer to the transport header */ struct udphdr * build_ip_header(uint8_t *cur_ptr, lisp_addr_t *src_addr, lisp_addr_t *dst_addr, int ip_len) { struct ip *iph; struct ip6_hdr *ip6h; struct udphdr *udph; switch (lisp_addr_ip_afi(src_addr)) { case AF_INET: ip_len = ip_len + sizeof(struct ip); iph = (struct ip *) cur_ptr; iph->ip_hl = 5; iph->ip_v = IPVERSION; iph->ip_tos = 0; iph->ip_len = htons(ip_len); iph->ip_id = htons(get_IP_ID()); iph->ip_off = 0; /* XXX Control packets can be fragmented */ iph->ip_ttl = 255; iph->ip_p = IPPROTO_UDP; iph->ip_src.s_addr = ip_addr_get_v4(lisp_addr_ip(src_addr))->s_addr; iph->ip_dst.s_addr = ip_addr_get_v4(lisp_addr_ip(dst_addr))->s_addr; iph->ip_sum = 0; iph->ip_sum = ip_checksum((uint16_t *) cur_ptr, sizeof(struct ip)); udph = (struct udphdr *) CO(iph, sizeof(struct ip)); break; case AF_INET6: ip6h = (struct ip6_hdr *) cur_ptr; ip6h->ip6_hops = 255; ip6h->ip6_vfc = (IP6VERSION << 4); ip6h->ip6_nxt = IPPROTO_UDP; ip6h->ip6_plen = htons(ip_len); memcpy(ip6h->ip6_src.s6_addr,ip_addr_get_v6(lisp_addr_ip(src_addr)), sizeof(struct in6_addr)); memcpy(ip6h->ip6_dst.s6_addr,ip_addr_get_v6(lisp_addr_ip(dst_addr)), sizeof(struct in6_addr)); udph = (struct udphdr *) CO(ip6h, sizeof(struct ip6_hdr)); break; default: OOR_LOG(LDBG_2, "build_ip_header: Unknown AFI of the source address: %d", lisp_addr_ip_afi(src_addr)); return (NULL); } return (udph); } /* * Generates an IP header and an UDP header * and copies the original packet at the end */ uint8_t * build_ip_udp_pcket(uint8_t *orig_pkt, int orig_pkt_len,lisp_addr_t *addr_from, lisp_addr_t *addr_dest, int port_from,int port_dest, int *encap_pkt_len) { uint8_t *encap_pkt; void *iph_ptr; struct udphdr *udph_ptr; int ip_hdr_len; int udp_hdr_len; int udp_hdr_and_payload_len; uint16_t udpsum; if (lisp_addr_ip_afi(addr_from) != lisp_addr_ip_afi(addr_dest)) { OOR_LOG(LDBG_2, "add_ip_udp_header: Different AFI addresses %d (%s) and %d (%s)", lisp_addr_ip_afi(addr_from), lisp_addr_to_char(addr_from), lisp_addr_ip_afi(addr_dest), lisp_addr_to_char(addr_dest)); return (NULL); } if ((lisp_addr_ip_afi(addr_from) != AF_INET) && (lisp_addr_ip_afi(addr_from) != AF_INET6)) { OOR_LOG(LDBG_2, "add_ip_udp_header: Unknown AFI %d", lisp_addr_ip_afi(addr_from)); return (NULL); } /* Headers lengths */ ip_hdr_len = ip_sock_afi_to_hdr_len(lisp_addr_ip_afi(addr_from)); udp_hdr_len = sizeof(struct udphdr); udp_hdr_and_payload_len = udp_hdr_len + orig_pkt_len; /* Assign memory for the original packet plus the new headers */ *encap_pkt_len = ip_hdr_len + udp_hdr_len + orig_pkt_len; if ((encap_pkt = (uint8_t *) malloc(*encap_pkt_len)) == NULL) { OOR_LOG(LDBG_2, "add_ip_udp_header: Couldn't allocate memory for the packet to be generated %s", strerror(errno)); return (NULL); } /* Make sure it's clean */ memset(encap_pkt, 0, *encap_pkt_len); /* IP header */ iph_ptr = encap_pkt; if ((udph_ptr = build_ip_header(iph_ptr, addr_from, addr_dest, udp_hdr_and_payload_len)) == NULL) { OOR_LOG(LDBG_2, "add_ip_udp_header: Couldn't build the inner ip header"); free(encap_pkt); return (NULL); } /* UDP header */ udpsport(udph_ptr) = htons(port_from); udpdport(udph_ptr) = htons(port_dest); udplen(udph_ptr) = htons(udp_hdr_and_payload_len); udpsum(udph_ptr) = 0; /* Copy original packet after the headers */ memcpy(CO(udph_ptr, udp_hdr_len), orig_pkt, orig_pkt_len); /* * Now compute the headers checksums */ if ((udpsum = udp_checksum(udph_ptr, udp_hdr_and_payload_len, iph_ptr, lisp_addr_ip_afi(addr_from))) == (uint16_t) ~ 0) { free(encap_pkt); return (NULL); } udpsum(udph_ptr) = udpsum; return (encap_pkt); } char * ip_src_and_dst_to_char(struct iphdr *iph, char *fmt) { static char buf[150]; struct ip6_hdr *ip6h; *buf = '\0'; switch (iph->version) { case 4: sprintf(buf, fmt, ip_to_char(&iph->saddr, AF_INET), ip_to_char(&iph->daddr, AF_INET)); break; case 6: ip6h = (struct ip6_hdr *)iph; sprintf(buf, fmt, ip_to_char(&ip6h->ip6_src, AF_INET6), ip_to_char(&ip6h->ip6_dst, AF_INET6)); break; default: sprintf(buf, fmt, "NOT IP", "NOT IP"); } return(buf); } void pkt_add_uint32_in_3bytes (uint8_t *pkt, uint32_t val) { uint8_t *val_bytes; uint32_t net_val = htonl(val); val_bytes = (uint8_t *)&net_val; pkt[0] = val_bytes[1]; pkt[1] = val_bytes[2]; pkt[2] = val_bytes[3]; } uint32_t pkt_get_uint32_from_3bytes (uint8_t *pkt) { return (((uint32_t) pkt[0]) << 16) | (((uint32_t) pkt[1]) << 8) | ((uint32_t) pkt[2]); } oor-1.2.0/oor/lib/packets.h000066400000000000000000000165371313612200500154660ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef PACKETS_H_ #define PACKETS_H_ #include #include #include #include #include #include #include #include #include "lbuf.h" #include "mem_util.h" #include "../defs.h" #include "../liblisp/lisp_address.h" #define MAX_IP_PKT_LEN 4096 #define MAX_IP_HDR_LEN 40 /* without options or IPv6 hdr extensions */ #define UDP_HDR_LEN 8 #ifdef BSD #define udpsport(x) x->uh_sport #define udpdport(x) x->uh_dport #define udplen(x) x->uh_ulen #define udpsum(x) x->uh_sum #else #define udpsport(x) x->source #define udpdport(x) x->dest #define udplen(x) x->len #define udpsum(x) x->check #endif #ifdef BSD #define tcpsport(x) x->th_sport #define tcpdport(x) x->th_dport #else #define tcpsport(x) x->source #define tcpdport(x) x->dest #endif /* shared between data and control */ typedef struct packet_tuple { lisp_addr_t src_addr; lisp_addr_t dst_addr; uint16_t src_port; uint16_t dst_port; uint8_t protocol; uint32_t iid; } packet_tuple_t; /* * Generate IP header. Returns the poninter to the transport header */ struct udphdr *build_ip_header(uint8_t *cur_ptr, lisp_addr_t *src_addr, lisp_addr_t *dst_addr, int ip_len); /* * Generates an IP header and an UDP header * and copies the original packet at the end */ uint8_t *build_ip_udp_pcket(uint8_t *orig_pkt, int orig_pkt_len, lisp_addr_t *addr_from, lisp_addr_t *addr_dest, int port_from, int port_dest, int *pkt_len); void *pkt_pull_eth(lbuf_t *b); void *pkt_pull_ipv4(lbuf_t *b); void *pkt_pull_ipv6(lbuf_t *b); void *pkt_pull_ip(lbuf_t *); struct udphdr *pkt_pull_udp(lbuf_t *); struct ip *pkt_push_ipv4(lbuf_t *, struct in_addr *, struct in_addr *, int); struct ip6_hdr *pkt_push_ipv6(lbuf_t *, struct in6_addr *, struct in6_addr *, int); void *pkt_push_udp(lbuf_t *, uint16_t , uint16_t); void *pkt_push_eth(lbuf_t *b, uint8_t ether_dhost[ETHER_ADDR_LEN], uint8_t ether_shost[ETHER_ADDR_LEN], uint16_t ether_type); void *pkt_push_ip(lbuf_t *, ip_addr_t *, ip_addr_t *, int proto); int pkt_push_udp_and_ip(lbuf_t *, uint16_t, uint16_t, ip_addr_t *, ip_addr_t *); int ip_hdr_set_ttl_and_tos(struct iphdr *, int ttl, int tos); int ip_hdr_ttl_and_tos(struct iphdr *, int *ttl, int *tos); int pkt_parse_5_tuple(lbuf_t *b, packet_tuple_t *tuple); uint32_t pkt_tuple_hash(packet_tuple_t *tuple); uint32_t pkt_src_dst_hash(lisp_addr_t *src_addr, lisp_addr_t *dst_addr); int pkt_tuple_cmp(packet_tuple_t *t1, packet_tuple_t *t2); packet_tuple_t *pkt_tuple_clone(packet_tuple_t *); void pkt_tuple_del(packet_tuple_t *tpl); char *pkt_tuple_to_char(packet_tuple_t *tpl); int pkt_tuple_is_lisp(packet_tuple_t *tpl); char * ip_src_and_dst_to_char(struct iphdr *iph, char *fmt); void pkt_add_uint32_in_3bytes (uint8_t *pkt, uint32_t val); uint32_t pkt_get_uint32_from_3bytes (uint8_t *pkt); /* Macros extracted from ROHC library code: http://rohc-lib.org/ */ /* * Generic IP macros: */ /// Get a subpart of a 16-bit IP field #define IP_GET_16_SUBFIELD(field, bitmask, offset) \ ((ntohs(field) & (bitmask)) >> (offset)) /// Get a subpart of a 32-bit IP field #define IP_GET_32_SUBFIELD(field, bitmask, offset) \ ((ntohl(field) & (bitmask)) >> (offset)) /// Set a subpart of a 16-bit IP field #define IP_SET_16_SUBFIELD(field, bitmask, offset, value) \ (field) = (((field) & htons(~(bitmask))) | htons(((value) << (offset)) & (bitmask))) /// Set a subpart of a 32-bit IP field #define IP_SET_32_SUBFIELD(field, bitmask, offset, value) \ (field) = (((field) & htonl(~(bitmask))) | htonl(((value) << (offset)) & (bitmask))) /* * IPv4 definitions & macros: */ /// The offset for the DF flag in an ipv4_hdr->frag_off variable #define IPV4_DF_OFFSET 14 /// Get the IPv4 Don't Fragment (DF) bit from an ipv4_hdr object #define IPV4_GET_DF(ip4) \ IP_GET_16_SUBFIELD((ip4).frag_off, IP_DF, IPV4_DF_OFFSET) /// Set the IPv4 Don't Fragment (DF) bit in an ipv4_hdr object #define IPV4_SET_DF(ip4, value) \ IP_SET_16_SUBFIELD((ip4)->frag_off, IP_DF, IPV4_DF_OFFSET, (value)) /// The format to print an IPv4 address #define IPV4_ADDR_FORMAT \ "%02x%02x%02x%02x (%u.%u.%u.%u)" /// The data to print an IPv4 address in raw format #define IPV4_ADDR_RAW(x) \ (x)[0], (x)[1], (x)[2], (x)[3], \ (x)[0], (x)[1], (x)[2], (x)[3] /* * IPv6 definitions & macros: */ /// The offset for the Version field in an ipv6_hdr->ip6_flow variable #define IPV6_VERSION_OFFSET 28 /// The bitmask for the Traffic Class (TC) field in an ipv6_hdr->ip6_flow variable #define IPV6_TC_MASK 0x0ff00000 /// The offset for the Traffic Class (TC) field in an ipv6_hdr->ip6_flow variable #define IPV6_TC_OFFSET 20 /// The bitmask for the FLow Label field in an ipv6_hdr->ip6_flow variable #define IPV6_FLOW_LABEL_MASK 0x000fffff /// Get the IPv6 Version 4-bit field from ipv6_hdr object #define IPV6_GET_VERSION(ip6) \ IP_GET_32_SUBFIELD((ip6).ip6_flow, IPV6_VERSION_MASK_, IPV6_VERSION_OFFSET) /// Set the IPv6 Version 4-bit field in an ipv6_hdr object #define IPV6_SET_VERSION(ip6, value) \ IP_SET_32_SUBFIELD((ip6)->ip6_flow, IPV6_VERSION_MASK_, IPV6_VERSION_OFFSET, (value)) /// Get the IPv6 Traffic Class (TC) byte from an ipv6_hdr object #define IPV6_GET_TC(ip6) \ IP_GET_32_SUBFIELD((ip6).ip6_flow, IPV6_TC_MASK, IPV6_TC_OFFSET) /// Set the IPv6 Traffic Class (TC) byte in an ipv6_hdr object #define IPV6_SET_TC(ip6, value) \ IP_SET_32_SUBFIELD((ip6)->ip6_flow, IPV6_TC_MASK, IPV6_TC_OFFSET, (value)) /// Get the IPv6 Flow Label 20-bit field from an ipv6_hdr object #define IPV6_GET_FLOW_LABEL(ip6) \ IP_GET_32_SUBFIELD((ip6).ip6_flow, IPV6_FLOW_LABEL_MASK, 0) /// Set the IPv6 Flow Label 20-bit field in an ipv6_hdr variable #define IPV6_SET_FLOW_LABEL(ip6, value) \ IP_SET_32_SUBFIELD((ip6)->ip6_flow, IPV6_FLOW_LABEL_MASK, 0, (value)) /// The format to print an IPv6 address #define IPV6_ADDR_FORMAT \ "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x" /// The data to print an IPv6 address in (struct ipv6_addr *) format #define IPV6_ADDR_IN6(x) \ IPV6_ADDR_RAW((x)->s6_addr) /// The data to print an IPv6 address in raw format #define IPV6_ADDR_RAW(x) \ (x)[0], (x)[1], (x)[2], (x)[3], (x)[4], (x)[5], (x)[6], (x)[7], \ (x)[8], (x)[9], (x)[10], (x)[11], (x)[12], (x)[13], (x)[14], (x)[15] /// Compare two IPv6 addresses in (struct ipv6_addr *) format #define IPV6_ADDR_CMP(x, y) \ ((x)->s6_addr32[0] == (y)->s6_addr32[0] && \ (x)->s6_addr32[1] == (y)->s6_addr32[1] && \ (x)->s6_addr32[2] == (y)->s6_addr32[2] && \ (x)->s6_addr32[3] == (y)->s6_addr32[3]) #endif /*PACKETS_H_*/ oor-1.2.0/oor/lib/pointers_table.c000066400000000000000000000104471313612200500170330ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "pointers_table.h" #include "../defs.h" htable_ptrs_t * htable_ptrs_new() { htable_ptrs_t * ht; ht = (htable_ptrs_t *)xzalloc(sizeof(htable_ptrs_t)); ht->ht = kh_init(ptrs); return(ht); } void htable_ptrs_insert(htable_ptrs_t *ptr_ht, void *key, void *val) { khiter_t k; int ret; k = kh_put(ptrs,ptr_ht->ht,key,&ret); kh_value(ptr_ht->ht, k) = val; } void * htable_ptrs_remove(htable_ptrs_t *ptr_ht, void *key) { void *val; khiter_t k; k = kh_get(ptrs,ptr_ht->ht, key); if (k == kh_end(ptr_ht->ht)){ return (NULL); } val = kh_value(ptr_ht->ht, k); kh_del(ptrs,ptr_ht->ht,k); return (val); } void * htable_ptrs_lookup(htable_ptrs_t *ptr_ht, void *key) { khiter_t k; k = kh_get(ptrs,ptr_ht->ht, key); if (k == kh_end(ptr_ht->ht)){ return (NULL); } return (kh_value(ptr_ht->ht,k)); } void htable_ptrs_destroy(htable_ptrs_t *ptr_ht) { if (!ptr_ht) { return; } kh_destroy(ptrs, ptr_ht->ht); free(ptr_ht); } int htable_ptrs_timers_add(htable_ptrs_t *ptr_ht, void *key, oor_timer_t *timer) { glist_t *timer_lst; timer_lst = htable_ptrs_lookup(ptr_ht, key); if (!timer_lst){ timer_lst = glist_new(); if (!timer_lst){ return (BAD); } htable_ptrs_insert(ptr_ht, key, timer_lst); } return (glist_add(timer, timer_lst)); } /* Return the list of timers associated with the object */ glist_t * htable_ptrs_timers_get_timers(htable_ptrs_t *ptr_ht, void *key) { return(htable_ptrs_lookup(ptr_ht, key)); } /* Return the list the timers of the requested type associated with the object */ glist_t * htable_ptrs_timers_get_timers_of_type_from_obj(htable_ptrs_t *ptr_ht, void *key, timer_type type) { oor_timer_t *timer; glist_t *set_timers_lst; glist_t *timer_lst; glist_entry_t *timer_it, *timer_it_aux; set_timers_lst = glist_new(); timer_lst = htable_ptrs_lookup(ptr_ht, key); if (!timer_lst){ return (set_timers_lst); } glist_for_each_entry_safe(timer_it,timer_it_aux,timer_lst){ timer = (oor_timer_t*)glist_entry_data(timer_it); if (type == oor_timer_type(timer)){ glist_add(timer, set_timers_lst); } } return set_timers_lst; } /* Remove the entry from hash table and returns the list of timers associated * with the object */ glist_t * htable_ptrs_timers_rm(htable_ptrs_t *ptr_ht, void *key) { return ((glist_t *)htable_ptrs_remove(ptr_ht, key)); } /* Remove from the list the timers of the requested type associated with the object * The removed timers are returned in a list */ glist_t * htable_ptrs_timers_rm_timers_of_type(htable_ptrs_t *ptr_ht, void *key, timer_type type) { glist_t *rm_timers_lst = glist_new(); glist_t *timer_lst; glist_entry_t *timer_it, *timer_it_aux; oor_timer_t *timer; timer_lst = htable_ptrs_lookup(ptr_ht, key); if (!timer_lst){ return (rm_timers_lst); } glist_for_each_entry_safe(timer_it,timer_it_aux,timer_lst){ timer = (oor_timer_t*)glist_entry_data(timer_it); if (type == oor_timer_type(timer)){ glist_add(timer, rm_timers_lst); glist_remove(timer_it, timer_lst); } } return rm_timers_lst; } /* Remove the timer from the list. It doesn't stop the timer */ int htable_ptrs_timers_rm_timer(htable_ptrs_t *ptr_ht, void *key, oor_timer_t *timer) { glist_t *timer_lst; timer_lst = htable_ptrs_lookup(ptr_ht, key); if (!timer_lst){ return(ERR_NO_EXIST); } glist_remove_obj(timer, timer_lst); return (GOOD); } oor-1.2.0/oor/lib/pointers_table.h000066400000000000000000000052031313612200500170320ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef POINTERS_TABLE_H_ #define POINTERS_TABLE_H_ #include "../defs.h" #include "../elibs/khash/khash.h" #include "generic_list.h" #include "timers.h" #if UINTPTR_MAX == 0xffffffff KHASH_INIT(ptrs, void *, void *, 1, kh_int_hash_func, kh_int_hash_equal) #elif UINTPTR_MAX == 0xffffffffffffffff KHASH_INIT(ptrs, void *, void *, 1, kh_int64_hash_func, kh_int64_hash_equal) #endif typedef struct htable_ptrs{ khash_t(ptrs) *ht; }htable_ptrs_t; htable_ptrs_t *htable_ptrs_new(); void htable_ptrs_insert(htable_ptrs_t *ptr_ht, void *key, void *val); /* Remove entry of hash table and return the value */ void* htable_ptrs_remove(htable_ptrs_t *ptr_ht, void *key); void *htable_ptrs_lookup(htable_ptrs_t *ptr_ht, void *key); void htable_ptrs_destroy(htable_ptrs_t *ptr_ht); /* Add the timer to the list of timers associated to the object. Creats the entry into the * hash table if it doesn't exist. User is responsible to check if exists duplicate timers before * inserting the new one */ int htable_ptrs_timers_add(htable_ptrs_t *ptr_ht, void *key, oor_timer_t *timer); /* Return the list of timers associated with the object */ glist_t *htable_ptrs_timers_get_timers(htable_ptrs_t *ptr_ht, void *key); /* Return the list the timers of the requested type associated with the object */ glist_t *htable_ptrs_timers_get_timers_of_type_from_obj(htable_ptrs_t *ptr_ht, void *key, timer_type type); /* Remove the entry from hash table and returns the list of timers associated with the object */ glist_t *htable_ptrs_timers_rm(htable_ptrs_t *ptr_ht, void *key); /* Remove from the list the timers of the requested type associated with the object * The removed timers are returned in a list */ glist_t *htable_ptrs_timers_rm_timers_of_type(htable_ptrs_t *ptr_ht, void *key, timer_type type); /* Remove the timer from the list. It doesn't stop the timer */ int htable_ptrs_timers_rm_timer(htable_ptrs_t *ptr_ht, void *key, oor_timer_t *timer); #endif /* POINTERS_TABLE_H_ */ oor-1.2.0/oor/lib/prefixes.c000066400000000000000000000134501313612200500156430ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include #include "oor_log.h" #include "prefixes.h" static inline lisp_addr_t * pref_get_network_address_v4(lisp_addr_t *address); static inline lisp_addr_t * pref_get_network_address_v6(lisp_addr_t *address); /* * True if address belongs to the prefix */ int pref_is_addr_part_of_prefix(lisp_addr_t *addr, lisp_addr_t *pref) { lisp_addr_t ip_prefix; lisp_addr_t * network_addr; lisp_addr_t * ip_network_addr; int pref_len; int res; if (!lisp_addr_is_ip_pref(pref) || !lisp_addr_is_ip(addr)){ return FALSE; } if (lisp_addr_ip_afi(addr) != lisp_addr_ip_afi(pref)){ return FALSE; } network_addr = pref_get_network_address(pref); pref_len = lisp_addr_get_plen(pref); lisp_addr_copy(&ip_prefix, addr); lisp_addr_ip_to_ippref(&ip_prefix); lisp_addr_set_plen(&ip_prefix, pref_len); ip_network_addr = pref_get_network_address(&ip_prefix); if (lisp_addr_cmp (ip_network_addr, network_addr) == 0){ res = TRUE; }else{ res = FALSE; } lisp_addr_del(network_addr); lisp_addr_del(ip_network_addr); return (res); } /* * If prefix b is contained in prefix a, then return TRUE. Otherwise return FALSE. * If both prefixs are the same it also returns TRUE */ int pref_is_prefix_b_part_of_a (lisp_addr_t *a_prefix,lisp_addr_t *b_prefix) { lisp_addr_t * a_network_addr; lisp_addr_t * b_network_addr_prefix_a; int a_pref_len; int b_pref_len; int res; if (!lisp_addr_is_ip_pref(a_prefix) || !lisp_addr_is_ip_pref(b_prefix)){ return FALSE; } if (lisp_addr_ip_afi(a_prefix) != lisp_addr_ip_afi(b_prefix)){ return FALSE; } a_pref_len = lisp_addr_get_plen(a_prefix); b_pref_len = lisp_addr_get_plen(b_prefix); if (a_pref_len > b_pref_len){ return FALSE; } a_network_addr = pref_get_network_address(a_prefix); lisp_addr_set_plen(b_prefix, a_pref_len); b_network_addr_prefix_a = pref_get_network_address(b_prefix); lisp_addr_set_plen(b_prefix, b_pref_len); if (lisp_addr_cmp (a_network_addr, b_network_addr_prefix_a) == 0){ res = TRUE; }else{ res = FALSE; } lisp_addr_del(a_network_addr); lisp_addr_del(b_network_addr_prefix_a); return (res); } lisp_addr_t * pref_get_network_address(lisp_addr_t *address) { lisp_addr_t *network_address = NULL; if (!lisp_addr_is_ip_pref(address)){ OOR_LOG(LDBG_2, "get_network_address: Address %s is not a prefix ", lisp_addr_to_char(address)); return (NULL); } switch (lisp_addr_ip_afi(address)){ case AF_INET: network_address = pref_get_network_address_v4(address); break; case AF_INET6: network_address = pref_get_network_address_v6(address); break; default: OOR_LOG(LDBG_2, "get_network_address: Afi not supported (%d). It should never " "reach this point", lisp_addr_ip_afi(address)); break; } return (network_address); } static inline lisp_addr_t * pref_get_network_address_v4(lisp_addr_t *address) { lisp_addr_t * network_address; int prefix_length; uint32_t mask = 0xFFFFFFFF; uint32_t addr; prefix_length = lisp_addr_get_plen(address); addr = ntohl(ip_addr_get_v4(lisp_addr_ip_get_addr(address))->s_addr); if (prefix_length != 0){ mask = mask << (32 - prefix_length); }else{ mask = 0; } addr = addr & mask; network_address = lisp_addr_new_lafi(LM_AFI_IP); addr = htonl(addr); ip_addr_set_v4(lisp_addr_ip_get_addr(network_address), &addr); return network_address; } static inline lisp_addr_t * pref_get_network_address_v6(lisp_addr_t *address) { lisp_addr_t * network_address; uint32_t addr32[4]; struct in6_addr *addr; uint32_t mask[4] = {0,0,0,0}; int prefix_length; int ctr = 0; int a,b; prefix_length = lisp_addr_get_plen(address); a = (prefix_length) / 32; b = (prefix_length) % 32; for (ctr = 0; ctrs6_addr32[ctr]) & mask[ctr]); } network_address = lisp_addr_new_lafi(LM_AFI_IP); ip_addr_set_v6(lisp_addr_ip_get_addr(network_address), &addr32); return network_address; } /* * pref_get_network_prefix returns a prefix address from an IP prefix. * For instance: 10.0.1.1/8 -> 10.0.0.0/8 */ lisp_addr_t * pref_get_network_prefix(lisp_addr_t *address) { lisp_addr_t * prefix_addr; prefix_addr = pref_get_network_address(address); if (!prefix_addr){ return (NULL); } lisp_addr_set_plen(prefix_addr, lisp_addr_get_plen(address)); return (prefix_addr); } int pref_conv_to_netw_pref(lisp_addr_t *addr) { lisp_addr_t *ip_pref, *net_pref; ip_pref = lisp_addr_get_ip_pref_addr(addr); if (!ip_pref){ return (BAD); } net_pref = pref_get_network_prefix(ip_pref); lisp_addr_copy(ip_pref, net_pref); lisp_addr_del(net_pref); return (GOOD); } oor-1.2.0/oor/lib/prefixes.h000066400000000000000000000027471313612200500156570ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef PREFIXES_H_ #define PREFIXES_H_ #include "../liblisp/lisp_address.h" int pref_is_addr_part_of_prefix(lisp_addr_t *addr, lisp_addr_t *pref); /* * True if address belongs to the prefix */ int pref_is_addr_part_of_prefix(lisp_addr_t *addr, lisp_addr_t *pref); /* * If prefix b is contained in prefix a, then return TRUE. Otherwise return FALSE. * If both prefixs are the same it also returns TRUE */ int pref_is_prefix_b_part_of_a (lisp_addr_t *a_prefix,lisp_addr_t *b_prefix); lisp_addr_t *pref_get_network_address(lisp_addr_t *address); /* * pref_get_network_prefix returns a prefix address from an IP prefix. * For instance: 10.0.1.1/8 -> 10.0.0.0/8 */ lisp_addr_t * pref_get_network_prefix(lisp_addr_t *address); int pref_conv_to_netw_pref(lisp_addr_t *addr); #endif /* PREFIXES_H_ */ oor-1.2.0/oor/lib/routing_tables_lib.c000066400000000000000000000301431313612200500176630ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include #include #include #include #include #include "oor_log.h" #include "routing_tables_lib.h" #include "sockets-util.h" #include "../oor_external.h" /**************************** FUNCTION DECLARATION ***************************/ /* * ifindex: Output interface * dest: Destination address * gw: Gateway * prefix_len: Destination address mask (/n) * metric: Route metric * table: Routing table. 0 = main table * */ /* command could be add or del */ int modify_route(int command, int afi, uint32_t ifindex, lisp_addr_t *dest_pref, lisp_addr_t *src, lisp_addr_t *gw, uint32_t metric, uint32_t table); /* * This function modifies kernel's list of ip rules * @param afi AF_INE or AF_INET6 * @paramif_index interface index * @param command add or del the rule? * @param table rule for which routing table? * @param priority rule priority * @param type type of route * @param src_pref src prefix to match * @param dst_pref dst prefix to match * @param flags flags, if any */ int modify_rule (int afi, int if_index, int command, uint8_t table, uint32_t priority, uint8_t type, lisp_addr_t *src_pref, lisp_addr_t *dst_pref, int flags); /*****************************************************************************/ /* * This function modifies kernel's list of ip rules */ int modify_rule (int afi, int if_index, int command, uint8_t table, uint32_t priority, uint8_t type, lisp_addr_t *src_pref, lisp_addr_t *dst_pref, int flags) { struct nlmsghdr *nlh = NULL; struct rtmsg *rtm = NULL; struct rtattr *rta = NULL; char buf[4096]; int rta_len = 0; int addr_size = 0; int sockfd = 0; int result = BAD; int src_pref_len = 0; int dst_pref_len = 0; sockfd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); if (sockfd < 0) { OOR_LOG(LCRIT, "Failed to connect to netlink socket for creating route"); exit_cleanup(); } if (afi == AF_INET){ addr_size = sizeof(struct in_addr); } else{ addr_size = sizeof(struct in6_addr); } /* * Build the command */ memset(buf, 0, sizeof(buf)); nlh = (struct nlmsghdr *)buf; //rtm = (struct rtmsg *)(CO(buf,sizeof(struct nlmsghdr))); rtm = NLMSG_DATA(nlh); rta_len = sizeof(struct rtmsg); rta = (struct rtattr *)(CO(rtm, sizeof(struct rtmsg))); /* * Add src address for the route */ if (src_pref != NULL){ rta->rta_type = RTA_SRC; rta->rta_len = sizeof(struct rtattr) + addr_size; lisp_addr_copy_to(((char *)rta) + sizeof(struct rtattr),src_pref); rta_len += rta->rta_len; src_pref_len = lisp_addr_ip_get_plen(src_pref); } /* * Add the destination */ if (dst_pref != NULL){ if (rta_len > sizeof(struct rtmsg)){ rta = (struct rtattr *)(CO(rta, rta->rta_len)); } rta->rta_type = RTA_DST; rta->rta_len = sizeof(struct rtattr) + addr_size; lisp_addr_copy_to(((char *)rta) + sizeof(struct rtattr),dst_pref); rta_len += rta->rta_len; dst_pref_len = lisp_addr_ip_get_plen(dst_pref); } /* * Add priority */ if (priority != 0){ if (rta_len > sizeof(struct rtmsg)){ rta = (struct rtattr *)(CO(rta, rta->rta_len)); } rta->rta_type = RTA_PRIORITY; rta->rta_len = sizeof(struct rtattr) + sizeof(uint32_t); memcpy(((char *)rta) + sizeof(struct rtattr), &priority, sizeof(uint32_t)); rta_len += rta->rta_len; } /* * Select interface */ if (if_index != 0){ if (rta_len > sizeof(struct rtmsg)){ rta = (struct rtattr *)(CO(rta, rta->rta_len)); } rta->rta_type = RTA_IIF; rta->rta_len = sizeof(struct rtattr) + sizeof(int); memcpy(((char *)rta) + sizeof(struct rtattr), &if_index, sizeof(int)); rta_len += rta->rta_len; } /* * Fill up the netlink message flags and attributes */ nlh->nlmsg_len = NLMSG_LENGTH(rta_len); nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; if (command == RTM_NEWRULE) { nlh->nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE; nlh->nlmsg_type = RTM_NEWRULE; }else{ nlh->nlmsg_type = RTM_DELRULE; } rtm->rtm_family = afi; rtm->rtm_dst_len = dst_pref_len; rtm->rtm_src_len = src_pref_len; if (table == 0){ rtm->rtm_table = RT_TABLE_MAIN; }else{ rtm->rtm_table = table; } rtm->rtm_scope = RT_SCOPE_UNIVERSE; rtm->rtm_type = type; rtm->rtm_flags = flags; /* * Send the netlink message to kernel */ result = send(sockfd, buf, NLMSG_LENGTH(rta_len), 0); if (result < 0) { OOR_LOG(LCRIT, "mod_route: send netlink command failed %s", strerror(errno)); close(sockfd); exit_cleanup(); } close(sockfd); return(GOOD); } /* * This function adds a specific ip rule to * kernel's rule list */ int add_rule(int afi, int if_index, uint8_t table, uint32_t priority, uint8_t type, lisp_addr_t *src_pref, lisp_addr_t *dst_pref, int flags) { int result = BAD; result = modify_rule(afi, if_index, RTM_NEWRULE, table,priority, type, src_pref, dst_pref, flags); if (result == GOOD){ OOR_LOG(LDBG_1, "add_rule: Add rule -> Send packets with source address %s and destination address %s" " to the table %d with priority %d.",lisp_addr_to_char(src_pref), lisp_addr_to_char(dst_pref),table,priority); } return (result); } /* * This function deletes a specific ip rule to * kernel's rule list */ int del_rule(int afi, int if_index, uint8_t table, uint32_t priority, uint8_t type, lisp_addr_t *src_pref, lisp_addr_t *dst_pref, int flags) { int result = BAD; result = modify_rule(afi, if_index, RTM_DELRULE, table,priority, type, src_pref, dst_pref, flags); if (result == GOOD){ OOR_LOG(LDBG_1, "del_rule: Removed rule for source routing of src addr: %s", lisp_addr_to_char(src_pref)); } return (result); } /* * ifindex: Output interface * dest: Destination address * gw: Gateway * prefix_len: Destination address mask (/n) * metric: Route metric * table: Routing table. 0 = main table * */ int modify_route(int command, int afi, uint32_t ifindex, lisp_addr_t *dest_pref, lisp_addr_t *src_addr, lisp_addr_t *gw_addr, uint32_t metric, uint32_t table) { struct nlmsghdr *nlh = NULL; struct rtmsg *rtm = NULL; struct rtattr *rta = NULL; char sndbuf[4096]; int rta_len = 0; int retval = 0; int sockfd = 0; int addr_size = 0; int dst_pref_len = 0; if (afi == AF_INET){ addr_size = sizeof(struct in_addr); } else{ addr_size = sizeof(struct in6_addr); } addr_size = ip_sock_afi_to_size(afi); sockfd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); if (sockfd < 0) { OOR_LOG(LCRIT, "modify_route: Failed to connect to netlink socket"); exit_cleanup(); } /* * Build the command */ memset(sndbuf, 0, 4096); nlh = (struct nlmsghdr *)sndbuf; rtm = (struct rtmsg *)(CO(sndbuf,sizeof(struct nlmsghdr))); rta_len = sizeof(struct rtmsg); rta = (struct rtattr *)(CO(rtm, sizeof(struct rtmsg))); /* * Add the destination */ if (dest_pref != NULL){ rta->rta_type = RTA_DST; rta->rta_len = sizeof(struct rtattr) + addr_size; lisp_addr_copy_to(((char *)rta) + sizeof(struct rtattr), dest_pref); rta_len += rta->rta_len; dst_pref_len = lisp_addr_ip_get_plen(dest_pref); } /* * Add src address for the route */ if (src_addr != NULL){ if (rta_len > sizeof(struct rtmsg)){ rta = (struct rtattr *)(CO(rta, rta->rta_len)); } rta->rta_type = RTA_PREFSRC; rta->rta_len = sizeof(struct rtattr) + addr_size; lisp_addr_copy_to(((char *)rta) + sizeof(struct rtattr), src_addr); rta_len += rta->rta_len; } /* * Add the outgoing interface */ if (ifindex>0) { if (rta_len > sizeof(struct rtmsg)){ rta = (struct rtattr *)(CO(rta, rta->rta_len)); } rta->rta_type = RTA_OIF; rta->rta_len = sizeof(struct rtattr) + sizeof(uint32_t); // if_index memcpy(((char *)rta) + sizeof(struct rtattr), &ifindex, sizeof(uint32_t)); rta_len += rta->rta_len; } /* * Add the gateway */ if (gw_addr != NULL){ if (rta_len > sizeof(struct rtmsg)){ rta = (struct rtattr *)(CO(rta, rta->rta_len)); } rta->rta_type = RTA_GATEWAY; rta->rta_len = sizeof(struct rtattr) + addr_size; lisp_addr_copy_to(((char *)rta) + sizeof(struct rtattr), gw_addr); rta_len += rta->rta_len; } /* Add the route metric */ if (metric > 0){ if (rta_len > sizeof(struct rtmsg)){ rta = (struct rtattr *)(CO(rta, rta->rta_len)); } //rta->rta_type = RTA_METRICS; rta->rta_type = RTA_PRIORITY; /* This is the actual atr type to set the metric... */ rta->rta_len = sizeof(struct rtattr) + sizeof(uint32_t); memcpy(((char *)rta) + sizeof(struct rtattr), &metric, sizeof(uint32_t)); rta_len += rta->rta_len; } nlh->nlmsg_len = NLMSG_LENGTH(rta_len); if ( command == RTM_NEWROUTE){ nlh->nlmsg_flags = NLM_F_REQUEST | (NLM_F_CREATE | NLM_F_REPLACE); nlh->nlmsg_type = RTM_NEWROUTE; }else{ nlh->nlmsg_flags = NLM_F_REQUEST; nlh->nlmsg_type = RTM_DELROUTE; } rtm->rtm_family = afi; if (table == 0){ rtm->rtm_table = RT_TABLE_MAIN; }else{ rtm->rtm_table = table; } rtm->rtm_protocol = RTPROT_STATIC; rtm->rtm_scope = RT_SCOPE_UNIVERSE; rtm->rtm_type = RTN_UNICAST; rtm->rtm_src_len = 0; rtm->rtm_tos = 0; rtm->rtm_dst_len = dst_pref_len; retval = send(sockfd, sndbuf, NLMSG_LENGTH(rta_len), 0); if (retval < 0) { OOR_LOG(LCRIT, "modify_route: send netlink command failed %s", strerror(errno)); close(sockfd); exit_cleanup(); } close(sockfd); return(GOOD); } int add_route(int afi, uint32_t ifindex, lisp_addr_t *dest_pref, lisp_addr_t *src, lisp_addr_t *gw, uint32_t metric, uint32_t table) { int result = BAD; result = modify_route(RTM_NEWROUTE, afi,ifindex, dest_pref, src, gw, metric, table); if (result == GOOD){ OOR_LOG(LDBG_1, "add_route: added route to the system: src addr: %s, dst prefix:%s, gw: %s, table: %d", (src != NULL) ? lisp_addr_to_char(src) : "-", (dest_pref != NULL) ? lisp_addr_to_char(dest_pref) : "-", (gw != NULL) ? lisp_addr_to_char(gw) : "-", table); } return (result); } int del_route(int afi, uint32_t ifindex, lisp_addr_t *dest_pref, lisp_addr_t *src, lisp_addr_t *gw, uint32_t metric, uint32_t table) { int result = BAD; result = modify_route(RTM_DELROUTE, afi, ifindex, dest_pref, src, gw, metric, table); if (result == GOOD){ OOR_LOG(LDBG_1, "del_route: deleted route from the system: src addr: %s, dst prefix:%s, gw: %s, table: %d", (src != NULL) ? lisp_addr_to_char(src) : "-", (dest_pref != NULL) ? lisp_addr_to_char(dest_pref) : "-", (gw != NULL) ? lisp_addr_to_char(gw) : "-", table); } return (result); } oor-1.2.0/oor/lib/routing_tables_lib.h000066400000000000000000000043011313612200500176650ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef ROUTING_TABLES_LIB_H_ #define ROUTING_TABLES_LIB_H_ #include "../defs.h" #include "../liblisp/lisp_address.h" #define RULE_AVOID_LISP_TABLE_PRIORITY 99 #define RULE_TO_LISP_TABLE_PRIORITY 100 #define LISP_TABLE 100 /* * This function adds a specific ip rule to * kernel's rule list */ int add_rule(int afi, int if_index, uint8_t table, uint32_t priority, uint8_t type, lisp_addr_t *src_pref, lisp_addr_t *dst_pref, int flags); /* * This function deletes a specific ip rule to * kernel's rule list */ int del_rule(int afi, int if_index, uint8_t table, uint32_t priority, uint8_t type, lisp_addr_t *src_pref, lisp_addr_t *dst_pref, int flags); /* * Creates a routing entry in the specified table * ifindex: Output interface * dest: Destination address * gw: Gateway * prefix_len: Destination address mask (/n) * metric: Route metric * table: Routing table. 0 = main table */ int add_route(int afi, uint32_t ifindex, lisp_addr_t *dest_pref, lisp_addr_t *src, lisp_addr_t *gw, uint32_t metric, uint32_t table); /* * Deletes a routing entry in the specified table * ifindex: Output interface * dest: Destination address * gw: Gateway * prefix_len: Destination address mask (/n) * metric: Route metric * table: Routing table. 0 = main table */ int del_route(int afi, uint32_t ifindex, lisp_addr_t *dest_pref, lisp_addr_t *src, lisp_addr_t *gw, uint32_t metric, uint32_t table); #endif /* ROUTING_TABLES_LIB_H_ */ oor-1.2.0/oor/lib/shash.c000066400000000000000000000055461313612200500151330ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "shash.h" #include "mem_util.h" shash_t * shash_new() { shash_t *sh; sh =xcalloc(1,sizeof(shash_t)); sh->htable = kh_init(str); return(sh); } shash_t * shash_new_managed(free_value_fn_t df) { shash_t *sh; sh =xcalloc(1,sizeof(shash_t)); sh->htable = kh_init(str); sh->free_value_fn = df; return(sh); } void shash_insert(shash_t *sh, char *key, void *val) { khiter_t k; int ret; k = kh_get(str,sh->htable, key); if (k == kh_end(sh->htable)){ k = kh_put(str,sh->htable,key,&ret); }else{ free(key); if (sh->free_value_fn){ sh->free_value_fn(kh_value(sh->htable,k)); } } kh_value(sh->htable, k) = val; } void shash_remove(shash_t *sh, char *key) { khiter_t k; k = kh_get(str,sh->htable, key); if (k == kh_end(sh->htable)){ return; } free(kh_key(sh->htable,k)); if (sh->free_value_fn){ sh->free_value_fn(kh_value(sh->htable,k)); } kh_del(str,sh->htable,k); } void * shash_lookup(shash_t *sh, char *key) { khiter_t k; k = kh_get(str,sh->htable, key); if (k == kh_end(sh->htable)){ return (NULL); } return (kh_value(sh->htable,k)); } void shash_destroy(shash_t *sh) { khiter_t k; if (!sh) { return; } for (k = kh_begin(sh->htable); k != kh_end(sh->htable); ++k){ if (kh_exist(sh->htable, k)){ free(kh_key(sh->htable,k)); if (sh->free_value_fn){ sh->free_value_fn(kh_value(sh->htable,k)); } } } kh_destroy(str, sh->htable); free(sh); } glist_t * shash_keys(shash_t *sh) { glist_t *list; khiter_t k; list = glist_new(); for (k = kh_begin(sh->htable); k != kh_end(sh->htable); ++k){ if (kh_exist(sh->htable, k)){ glist_add(kh_key(sh->htable,k), list); } } return (list); } glist_t *shash_values(shash_t *sh) { glist_t *list; khiter_t k; list = glist_new(); for (k = kh_begin(sh->htable); k != kh_end(sh->htable); ++k){ if (kh_exist(sh->htable, k)){ glist_add(kh_value(sh->htable,k), list); } } return (list); } oor-1.2.0/oor/lib/shash.h000066400000000000000000000026571313612200500151400ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef SHASH_H_ #define SHASH_H_ #include "../elibs/khash/khash.h" #include "generic_list.h" //KHASH_MAP_INIT_STR(str, void *) KHASH_INIT(str, char *, void *, 1, kh_str_hash_func, kh_str_hash_equal) /* Prototype for a pointer to a free key function. */ typedef void (*free_value_fn_t)(const void *key); typedef struct shash { khash_t(str) *htable; free_value_fn_t free_value_fn; } shash_t; shash_t *shash_new(); shash_t *shash_new_managed(free_value_fn_t df); void shash_del(shash_t *); void shash_insert(shash_t *, char *, void *); void shash_remove(shash_t *, char *); void *shash_lookup(shash_t *, char *); void shash_destroy(shash_t *sh); glist_t *shash_keys(shash_t *sh); glist_t *shash_values(shash_t *sh); #endif /* SHASH_H_ */ oor-1.2.0/oor/lib/sockets-util.c000066400000000000000000000244201313612200500164430ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include #include #include #include #include #include "oor_log.h" #include "sockets-util.h" int open_ip_raw_socket(int afi) { int s; int on = 1; if ((s = socket(afi, SOCK_RAW, IPPROTO_RAW)) < 0) { OOR_LOG(LERR, "open_ip_raw_socket: socket creation failed" " %s", strerror(errno)); return (ERR_SOCKET); } if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(int)) == -1) { OOR_LOG(LWRN, "open_ip_raw_socket: socket option reuse %s", strerror(errno)); close(s); return (ERR_SOCKET); } OOR_LOG(LDBG_3, "open_ip_raw_socket: open socket %d with afi: %d", s, afi); return s; } int open_udp_raw_socket(int afi) { struct protoent *proto = NULL; int sock = ERR_SOCKET; int tr = 1; int protonum = 0; #ifdef ANDROID protonum = IPPROTO_UDP; #else if ((proto = getprotobyname("udp")) == NULL) { OOR_LOG(LERR, "open_udp_raw_socket: getprotobyname: %s", strerror(errno)); return(-1); } protonum = proto->p_proto; #endif /* * build the ipv4_data_input_fd, and make the port reusable */ if ((sock = socket(afi, SOCK_RAW, protonum)) < 0) { OOR_LOG(LERR, "open_udp_raw_socket: socket: %s", strerror(errno)); return (ERR_SOCKET); } OOR_LOG(LDBG_3, "open_udp_raw_socket: Created socket %d associated to %s addresses\n", sock, (afi == AF_INET) ? "IPv4":"IPv6"); if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &tr, sizeof(int)) == -1) { OOR_LOG(LWRN,"open_udp_raw_socket: setsockopt SO_REUSEADDR: %s", strerror(errno)); close(sock); return (ERR_SOCKET); } return (sock); } int open_udp_datagram_socket(int afi) { struct protoent *proto = NULL; int sock = ERR_SOCKET; int tr = 1; int protonum = 0; #ifdef ANDROID protonum = IPPROTO_UDP; #else if ((proto = getprotobyname("udp")) == NULL) { OOR_LOG(LERR, "open_udp_datagram_socket: getprotobyname: %s", strerror(errno)); return(ERR_SOCKET); } protonum = proto->p_proto; #endif if ((sock = socket(afi, SOCK_DGRAM, protonum)) < 0) { OOR_LOG(LERR, "open_udp_datagram_socket: socket: %s", strerror(errno)); return (ERR_SOCKET); } OOR_LOG(LDBG_3, "open_udp_datagram_socket: Created socket %d associated to %s addresses\n", sock, (afi == AF_INET) ? "IPv4":"IPv6"); if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &tr, sizeof(int)) == -1) { OOR_LOG(LWRN, "open_udp_datagram_socket: setsockopt SO_REUSEADDR: %s", strerror(errno)); return (ERR_SOCKET); } return sock; } int opent_netlink_socket() { int netlink_fd; struct sockaddr_nl addr; memset(&addr, 0, sizeof(addr)); addr.nl_family = AF_NETLINK; addr.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR | RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_ROUTE | RTMGRP_IPV4_MROUTE | RTMGRP_IPV6_MROUTE; netlink_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); if (netlink_fd < 0) { OOR_LOG(LERR, "opent_netlink_socket: Failed to connect to " "netlink socket"); return (ERR_SOCKET); } bind(netlink_fd, (struct sockaddr *) &addr, sizeof(addr)); return (netlink_fd); } /* XXX: binding might not work on all devices */ inline int socket_bindtodevice(int sock, char *device) { int device_len = 0; device_len = strlen(device); if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, device, device_len) == -1) { OOR_LOG(LWRN, "socket_bindtodevice: Error binding socket to device %s:", strerror(errno)); return (BAD); } return (GOOD); } inline int socket_conf_req_ttl_tos(int sock, int afi) { const int on = 1; switch (afi) { case AF_INET: /* IP_RECVTOS is requiered to get later the IPv4 original TOS */ if (setsockopt(sock, IPPROTO_IP, IP_RECVTOS, &on, sizeof(on)) < 0) { OOR_LOG(LWRN, "open_data_raw_input_socket: setsockopt IP_RECVTOS: %s", strerror(errno)); return (BAD); } /* IP_RECVTTL is requiered to get later the IPv4 original TTL */ if (setsockopt(sock, IPPROTO_IP, IP_RECVTTL, &on, sizeof(on)) < 0) { OOR_LOG(LWRN, "open_data_raw_input_socket: setsockopt IP_RECVTTL: %s", strerror(errno)); return (BAD); } break; case AF_INET6: /* IPV6_RECVTCLASS is requiered to get later the IPv6 original TOS */ if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVTCLASS, &on, sizeof(on)) < 0) { OOR_LOG(LWRN, "open_data_raw_input_socket: setsockopt IPV6_RECVTCLASS: %s", strerror(errno)); return (BAD); } /* IPV6_RECVHOPLIMIT is requiered to get later the IPv6 original TTL */ if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on, sizeof(on)) < 0) { OOR_LOG(LWRN, "open_data_raw_input_socket: setsockopt IPV6_RECVHOPLIMIT: %s", strerror(errno)); return (BAD); } break; default: return (BAD); } return (GOOD); } /* * Bind a socket to a specific address and port if specified * Afi is used when the src address is not specified */ int bind_socket(int sock, int afi, lisp_addr_t *src_addr, int src_port) { int result = TRUE; struct sockaddr *sock_addr; int sock_addr_len; struct sockaddr_in sock_addr_v4; struct sockaddr_in6 sock_addr_v6; switch(afi){ case AF_INET: memset ( ( char * ) &sock_addr_v4, 0, sizeof ( sock_addr_v4 ) ); sock_addr_v4.sin_family = AF_INET; if (src_port != 0){ sock_addr_v4.sin_port = htons(src_port); } if (src_addr != NULL){ sock_addr_v4.sin_addr.s_addr = ip_addr_get_v4(lisp_addr_ip(src_addr))->s_addr; }else{ sock_addr_v4.sin_addr.s_addr = INADDR_ANY; } sock_addr = ( struct sockaddr * ) &sock_addr_v4; sock_addr_len = sizeof ( struct sockaddr_in ); break; case AF_INET6: memset ( ( char * ) &sock_addr_v6, 0, sizeof ( sock_addr_v6 ) ); sock_addr_v6.sin6_family = AF_INET6; if (src_port != 0){ sock_addr_v6.sin6_port = htons(src_port); } if (src_addr != NULL){ memcpy(&(sock_addr_v6.sin6_addr),ip_addr_get_v6(lisp_addr_ip(src_addr)),sizeof(struct in6_addr)); }else{ sock_addr_v6.sin6_addr = in6addr_any; } sock_addr = ( struct sockaddr * ) &sock_addr_v6; sock_addr_len = sizeof ( struct sockaddr_in6 ); break; default: return (BAD); } if (bind(sock,sock_addr,sock_addr_len) != 0){ OOR_LOG(LDBG_1, "bind_socket: %s", strerror(errno)); result = BAD; }else{ OOR_LOG(LDBG_1, "bind_socket: Binded socket %d to source address %s and port %d with afi %d", sock, lisp_addr_to_char(src_addr),src_port, afi); } return (result); } /* Sends a raw packet out the socket file descriptor 'sfd' */ int send_raw_packet(int socket, const void *pkt, int plen, ip_addr_t *dip) { struct sockaddr *saddr = NULL; int slen, nbytes; struct sockaddr_in sa4; struct sockaddr_in6 sa6; /* build sock addr */ switch (ip_addr_afi(dip)) { case AF_INET: memset(&sa4, 0, sizeof(sa4)); sa4.sin_family = AF_INET; ip_addr_copy_to(&sa4.sin_addr, dip); slen = sizeof(struct sockaddr_in); saddr = (struct sockaddr *)&sa4; break; case AF_INET6: memset(&sa6, 0, sizeof(sa6)); sa6.sin6_family = AF_INET6; ip_addr_copy_to(&sa6.sin6_addr, dip); slen = sizeof(struct sockaddr_in6); saddr = (struct sockaddr *)&sa6; break; default: return(BAD); } nbytes = sendto(socket, pkt, plen, 0, saddr, slen); if (nbytes != plen) { OOR_LOG(LDBG_2, "send_raw_packet: send packet to %s using fail descriptor %d failed -> %s", ip_addr_to_char(dip), socket, strerror(errno)); return(BAD); } return (GOOD); } int send_datagram_packet (int sock, const void *packet, int packet_length, lisp_addr_t *addr_dest, int port_dest) { struct sockaddr_in sock_addr_v4; struct sockaddr_in6 sock_addr_v6; struct sockaddr *sock_addr = NULL; int sock_addr_len = 0; switch (lisp_addr_ip_afi(addr_dest)){ case AF_INET: memset(&sock_addr_v4,0,sizeof(sock_addr_v4)); /* be sure */ sock_addr_v4.sin_port = htons(port_dest); sock_addr_v4.sin_family = AF_INET; sock_addr_v4.sin_addr.s_addr = ip_addr_get_v4(lisp_addr_ip(addr_dest))->s_addr; sock_addr = (struct sockaddr *) &sock_addr_v4; sock_addr_len = sizeof(sock_addr_v4); break; case AF_INET6: memset(&sock_addr_v6,0,sizeof(sock_addr_v6)); /* be sure */ sock_addr_v6.sin6_family = AF_INET6; sock_addr_v6.sin6_port = htons(port_dest); memcpy(&sock_addr_v6.sin6_addr, ip_addr_get_v6(lisp_addr_ip(addr_dest)),sizeof(struct in6_addr)); sock_addr = (struct sockaddr *) &sock_addr_v6; sock_addr_len = sizeof(sock_addr_v6); break; default: OOR_LOG(LDBG_2, "send_datagram_packet: Unknown afi %d",lisp_addr_ip_afi(addr_dest)); return (BAD); } if (sendto(sock, packet, packet_length, 0, sock_addr, sock_addr_len) < 0){ OOR_LOG(LDBG_2, "send_datagram_packet: send failed %s.",strerror ( errno )); return (BAD); } return (GOOD); } oor-1.2.0/oor/lib/sockets-util.h000066400000000000000000000024261313612200500164520ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef SOCKETS_UTIL_H_ #define SOCKETS_UTIL_H_ #include "../liblisp/lisp_address.h" int open_ip_raw_socket(int afi); int open_udp_raw_socket(int afi); int opent_netlink_socket(); int open_udp_datagram_socket(int afi); int socket_bindtodevice(int sock, char *device); int socket_conf_req_ttl_tos(int sock, int afi); int bind_socket(int sock,int afi, lisp_addr_t *src_addr, int src_port); int send_raw_packet(int, const void *, int, ip_addr_t *); int send_datagram_packet (int sock, const void *packet, int packet_length, lisp_addr_t *addr_dest, int port_dest); #endif /* SOCKETS_UTIL_H_ */ oor-1.2.0/oor/lib/sockets.c000066400000000000000000000303021313612200500154640ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include #include #include #include "oor_log.h" #include "sockets.h" #include "sockets-util.h" #include "../iface_list.h" #include "../liblisp/liblisp.h" sockmstr_t * sockmstr_create() { sockmstr_t *sm; sm = xzalloc(sizeof(sockmstr_t)); return (sm); } static void sock_list_remove_all(sock_list_t *lst) { sock_t *sk, *next; sk = lst->head; while(sk) { next = sk->next; close(sk->fd); free(sk); sk = next; } } static inline void sock_list_add(sock_list_t *lst, sock_t *sock) { sock->next = NULL; sock->prev = lst->tail; if (lst->tail) { lst->tail->next = sock; } else { lst->head = sock; } lst->tail = sock; lst->count++; if (sock->fd > lst->maxfd) { lst->maxfd = sock->fd; } } static inline void sock_list_remove(sock_list_t *lst, struct sock *sock) { int fd; if (sock->prev == NULL){ lst->head = sock->next; if (sock->next != NULL){ sock->next->prev = NULL; } }else{ sock->prev->next = sock->next; if (sock->next != NULL){ sock->next->prev = sock->prev; } } fd = sock->fd; close(sock->fd); free(sock); lst->count--; if (fd == lst->maxfd){ sock= lst->head; if (sock == NULL){ lst->maxfd = 0; } while (sock != NULL){ if (sock->fd > lst->maxfd) { lst->maxfd = sock->fd; } sock = sock->next; } } } void sockmstr_destroy(sockmstr_t *sm) { if (sm == NULL){ return; } sock_list_remove_all(&sm->read); free(sm); OOR_LOG(LDBG_1,"Sockets closed"); } sock_t * sockmstr_register_get_by_fd(sockmstr_t *m, int fd){ sock_list_t *lst; sock_t * sock = NULL; lst = &m->read; sock = lst->head; if (sock == NULL){ return (NULL); } while (sock != NULL){ if (sock->fd == fd){ return (sock); } sock = sock->next; } return (sock); } sock_t * sockmstr_register_get_by_bind_port (sockmstr_t *m, int afi, uint16_t port) { sock_list_t *lst; sock_t * sock = NULL; struct sockaddr sa; socklen_t sa_len = sizeof(sa); lst = &m->read; sock = lst->head; if (sock == NULL){ return (NULL); } while (sock != NULL){ if (getsockname(sock->fd, (struct sockaddr *)&sa, &sa_len) == -1){ sock = sock->next; continue; } if (sa_len == sizeof(struct sockaddr_in)){ if (afi == AF_INET && port == ntohs(((struct sockaddr_in *)&sa)->sin_port)){ return (sock); } }else{ if (afi == AF_INET6 && port == ntohs(((struct sockaddr_in6 *)&sa)->sin6_port)){ return (sock); } } sock = sock->next; } return (sock); } sock_t * sockmstr_register_read_listener(sockmstr_t *m,int (*func)(struct sock *), void *arg, int fd) { struct sock *sock; sock = xzalloc(sizeof(struct sock)); sock->recv_cb = func; sock->type = SOCK_READ; sock->arg = arg; sock->fd = fd; sock_list_add(&m->read, sock); return (sock); } inline int sock_fd(struct sock * sock) { return (sock->fd); } int sockmstr_unregister_read_listenedr(sockmstr_t *m, struct sock *sock) { sock_list_remove(&m->read, sock); return (GOOD); } static void sock_process_fd(struct sock_list *lst, fd_set *fdset) { struct sock *sit; for (sit = lst->head; sit; sit = sit->next) { if (FD_ISSET(sit->fd, fdset)) (*sit->recv_cb)(sit); } } void sockmstr_process_all(sockmstr_t *m) { struct timeval tv; tv.tv_sec = 0; tv.tv_usec = DEFAULT_SELECT_TIMEOUT; while (1) { if (select(m->read.maxfd + 1, &m->readfds, NULL, NULL, &tv) == -1) { if (errno == EINTR) { continue; } else { OOR_LOG(LDBG_2, "sock_process_all: select error: %s", strerror(errno)); return; } } else { break; } } sock_process_fd(&m->read, &m->readfds); } void sockmstr_wait_on_all_read(sockmstr_t *m) { struct sock *sit; for (sit = m->read.head; sit; sit = sit->next) { FD_SET(sit->fd, &m->readfds); } } int open_control_input_socket(int afi) { const int on = 1; int sock = ERR_SOCKET; sock = open_udp_datagram_socket(afi); if (sock == ERR_SOCKET) { return (ERR_SOCKET); } bind_socket(sock, afi, NULL, LISP_CONTROL_PORT); switch (afi) { case AF_INET: /* IP_PKTINFO is requiered to get later the IPv4 destination address * of incoming control packets */ if (setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &on, sizeof(on)) < 0) { OOR_LOG(LWRN, "setsockopt IP_PKTINFO: %s", strerror(errno)); } break; case AF_INET6: /* IPV6_RECVPKTINFO is requiered to get later the IPv6 destination * address of incoming control packets */ if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on)) < 0) { OOR_LOG(LWRN, "setsockopt IPV6_RECVPKTINFO: %s", strerror(errno)); } break; default: return (ERR_SOCKET); } return (sock); } int open_data_raw_input_socket(int afi, uint16_t port) { int sock = ERR_SOCKET; int dummy_sock = ERR_SOCKET; /* To avoid ICMP port unreacheable packets */ sock = open_udp_raw_socket(afi); if (sock == ERR_SOCKET){ return (ERR_SOCKET); } dummy_sock = open_udp_datagram_socket(afi); dummy_sock = bind_socket(dummy_sock, afi, NULL, port); if (socket_conf_req_ttl_tos(sock,afi)!= GOOD){ close(sock); close(dummy_sock); return (ERR_SOCKET); } return (sock); } int open_data_datagram_input_socket(int afi, int port) { int sock = ERR_SOCKET; if ((sock = open_udp_datagram_socket(afi)) < 0){ return(ERR_SOCKET); } if(bind_socket(sock,afi,NULL,port) != GOOD){ close(sock); return(ERR_SOCKET); } if (socket_conf_req_ttl_tos(sock,afi)!= GOOD){ close(sock); return (ERR_SOCKET); } return (sock); } int sock_recv(int sfd, lbuf_t *b) { int nread; nread = read(sfd, lbuf_data(b), lbuf_tailroom(b)); if (nread == 0) { OOR_LOG(LWRN, "sock_recv: recvmsg error: %s", strerror(errno)); return (BAD); } lbuf_set_size(b, lbuf_size(b) + nread); return(GOOD); } /* Get a packet from the socket. It also returns the destination addres and * source port of the packet */ int sock_ctrl_recv(int sock, struct lbuf *buf, uconn_t *uc) { union control_data { struct cmsghdr cmsg; u_char data4[CMSG_SPACE(sizeof(struct in_pktinfo))]; u_char data6[CMSG_SPACE(sizeof(struct in6_pktinfo))]; }; union sockunion su; struct msghdr msg; struct iovec iov[1]; union control_data cmsg; struct cmsghdr *cmsgptr = NULL; int nbytes = 0; iov[0].iov_base = lbuf_data(buf); iov[0].iov_len = lbuf_tailroom(buf); memset(&msg, 0, sizeof msg); msg.msg_iov = iov; msg.msg_iovlen = 1; msg.msg_control = &cmsg; msg.msg_controllen = sizeof cmsg; msg.msg_name = &su; msg.msg_namelen = sizeof(union sockunion); nbytes = recvmsg(sock, &msg, 0); if (nbytes == -1) { OOR_LOG(LWRN, "sock_recv_ctrl: recvmsg error: %s", strerror(errno)); return (BAD); } lbuf_set_size(buf, lbuf_size(buf) + nbytes); /* read local address, remote port and remote address */ if (su.s4.sin_family == AF_INET) { for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) { if (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_PKTINFO) { lisp_addr_ip_init(&uc->la, &(((struct in_pktinfo *) (CMSG_DATA(cmsgptr)))->ipi_addr), AF_INET); break; } } lisp_addr_ip_init(&uc->ra, &su.s4.sin_addr, AF_INET); uc->rp = ntohs(su.s4.sin_port); } else { for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) { if (cmsgptr->cmsg_level == IPPROTO_IPV6 && cmsgptr->cmsg_type == IPV6_PKTINFO) { lisp_addr_ip_init(&uc->la, &(((struct in6_pktinfo *) (CMSG_DATA(cmsgptr)))->ipi6_addr), AF_INET6); break; } } lisp_addr_ip_init(&uc->ra, &su.s6.sin6_addr, AF_INET6); uc->rp = ntohs(su.s6.sin6_port); } return (GOOD); } int sock_data_recv(int sock, lbuf_t *b, int *afi, uint8_t *ttl, uint8_t *tos) { /* Space for TTL and TOS data */ union control_data { struct cmsghdr cmsg; u_char data[CMSG_SPACE(sizeof(int)) + CMSG_SPACE(sizeof(int))]; }; union sockunion su; struct msghdr msg; struct iovec iov[1]; union control_data cmsg; struct cmsghdr *cmsgptr = NULL; int nbytes = 0; iov[0].iov_base = lbuf_data(b); iov[0].iov_len = lbuf_tailroom(b); memset(&msg, 0, sizeof msg); msg.msg_iov = iov; msg.msg_iovlen = 1; msg.msg_control = &cmsg; msg.msg_controllen = sizeof cmsg; msg.msg_name = &su; msg.msg_namelen = sizeof(union sockunion); nbytes = recvmsg(sock, &msg, 0); if (nbytes == -1) { OOR_LOG(LWRN, "read_packet: recvmsg error: %s", strerror(errno)); return (BAD); } lbuf_set_size(b, lbuf_size(b) + nbytes); if (su.s4.sin_family == AF_INET) { for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) { if (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_TTL) { *ttl = *((uint8_t *) CMSG_DATA(cmsgptr)); } if (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_TOS) { *tos = *((uint8_t *) CMSG_DATA(cmsgptr)); } } *afi = AF_INET; } else { for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) { if (cmsgptr->cmsg_level == IPPROTO_IPV6 && cmsgptr->cmsg_type == IPV6_HOPLIMIT) { *ttl = *((uint8_t *) CMSG_DATA(cmsgptr)); } if (cmsgptr->cmsg_level == IPPROTO_IPV6 && cmsgptr->cmsg_type == IPV6_TCLASS) { *tos = *((uint8_t *) CMSG_DATA(cmsgptr)); } } *afi = AF_INET6; } return (GOOD); } inline int uconn_init(uconn_t *uc, int lp, int rp, lisp_addr_t *la,lisp_addr_t *ra) { uc->lp = lp; uc->rp = rp; la ? lisp_addr_copy(&uc->la, la) : lisp_addr_set_lafi(&uc->la, LM_AFI_NO_ADDR); ra ? lisp_addr_copy(&uc->ra, ra) : lisp_addr_set_lafi(&uc->ra, LM_AFI_NO_ADDR); return(GOOD); } void uconn_from_5_tuple (packet_tuple_t *tuple, uconn_t *udp_con, uint8_t is_pkt_rx) { if (is_pkt_rx){ lisp_addr_copy(&udp_con->la, &tuple->dst_addr); lisp_addr_copy(&udp_con->ra, &tuple->src_addr); udp_con->lp = tuple->dst_port; udp_con->rp = tuple->src_port; }else{ lisp_addr_copy(&udp_con->la, &tuple->src_addr); lisp_addr_copy(&udp_con->ra, &tuple->dst_addr); udp_con->lp = tuple->src_port; udp_con->rp = tuple->dst_port; } } oor-1.2.0/oor/lib/sockets.h000066400000000000000000000055501313612200500155000ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef SOCKETS_H_ #define SOCKETS_H_ #include "../defs.h" #include "sockets-util.h" #include "packets.h" #include "../liblisp/lisp_address.h" #include "lbuf.h" typedef enum { SOCK_READ, SOCK_WRITE, } sock_type_e; /* * inspired by quagga thread.c * It might be a little bit of an overkill for now * but it could prove useful in the future */ typedef struct sock_list { struct sock *head; struct sock *tail; int count; int maxfd; }sock_list_t; typedef struct sock { sock_type_e type; int (*recv_cb)(struct sock *); void *arg; int fd; struct sock *next; struct sock *prev; }sock_t; typedef struct uconn { /* TODO: decide if la, ra should be IP */ lisp_addr_t la; /* local address */ lisp_addr_t ra; /* remote address */ uint16_t lp; /* local port */ uint16_t rp; /* remote port */ } uconn_t; typedef struct sockmstr { sock_list_t read; // struct sock_list *write; // struct sock_list *netlink; fd_set readfds; // fd_set *writefds; // fd_set *netlinkfds; } sockmstr_t; union sockunion { struct sockaddr_in s4; struct sockaddr_in6 s6; }; typedef struct iface iface_t; sockmstr_t *sockmstr_create(); void sockmstr_destroy(sockmstr_t *sm); sock_t *sockmstr_register_get_by_fd(sockmstr_t *m, int fd); sock_t *sockmstr_register_get_by_bind_port (sockmstr_t *m, int afi, uint16_t port); sock_t *sockmstr_register_read_listener(sockmstr_t *m, int (*)(struct sock *), void *arg, int fd); int sock_fd(struct sock * sock); int sockmstr_unregister_read_listenedr(sockmstr_t *m, struct sock *sock); void sockmstr_process_all(sockmstr_t *m); void sockmstr_wait_on_all_read(sockmstr_t *m); int open_data_raw_input_socket(int afi, uint16_t port); int open_data_datagram_input_socket(int afi, int port); int open_control_input_socket(int afi); int sock_recv(int, lbuf_t *); int sock_ctrl_recv(int, lbuf_t *, uconn_t *); int sock_data_recv(int sock, lbuf_t *b, int *afi, uint8_t *ttl, uint8_t *tos); int uconn_init(uconn_t *uc, int lp, int rp, lisp_addr_t *la, lisp_addr_t *ra); void uconn_from_5_tuple (packet_tuple_t *tuple, uconn_t *udp_con, uint8_t is_pkt_rx); #endif /*SOCKETS_H_*/ oor-1.2.0/oor/lib/timers.c000066400000000000000000000257371313612200500153340ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include #include #include #include #include #include "oor_log.h" #include "timers.h" #include "mem_util.h" #include "../defs.h" #include "../oor_external.h" /* Seconds */ #define TICK_INTERVAL 1 /* Good for a little over an hour */ #define WHEEL_SIZE 4096 struct timer_wheel_{ int num_spokes; int current_spoke; oor_timer_links_t *spokes; timer_t tick_timer_id; int running_timers; int expirations; } timer_wheel = {.spokes=NULL}; /* We don't have signalfd in bionic, fake it. */ static int signal_pipe[2]; static timer_t timer_id; /* timers file descriptor */ int timers_fd = 0; static int destroy_timers_event_socket(); static int build_timers_event_socket(int *timers_fd); static int process_timer_signal(sock_t *sl); static void handle_timers(void); /* * create_timer_wheel() * * Creates the timer wheel structure and starts * the rotation timer. */ static int create_timer_wheel(void) { //timer_t tid; struct sigevent sev; struct itimerspec timerspec; sev.sigev_notify = SIGEV_SIGNAL; sev.sigev_signo = SIGRTMIN; sev.sigev_value.sival_ptr = &timer_id; if (timer_create(CLOCK_MONOTONIC, &sev, &timer_id) == -1) { OOR_LOG(LINF, "timer_create(): %s", strerror(errno)); return (BAD); } timerspec.it_value.tv_nsec = 0; timerspec.it_value.tv_sec = TICK_INTERVAL; timerspec.it_interval.tv_nsec = 0; timerspec.it_interval.tv_sec = TICK_INTERVAL; if (timer_settime(timer_id, 0, &timerspec, NULL) == -1) { OOR_LOG(LINF, "create_wheel_timer: timer start failed for %d %s", timer_id, strerror(errno)); return (BAD); } return(GOOD); } int oor_timers_init() { int i = 0; oor_timer_links_t *spoke; OOR_LOG(LDBG_1, "Initializing lmtimers..."); /* create timers event socket */ if (build_timers_event_socket(&timers_fd) == 0) { OOR_LOG(LCRIT, " Error programming the timer signal. Exiting..."); return(BAD); } if (create_timer_wheel() != GOOD) { OOR_LOG(LINF, "Failed to set up timers."); return(BAD); } timer_wheel.num_spokes = WHEEL_SIZE; timer_wheel.spokes = xmalloc(sizeof(oor_timer_links_t) * WHEEL_SIZE); timer_wheel.current_spoke = 0; timer_wheel.running_timers = 0; timer_wheel.expirations = 0; spoke = &timer_wheel.spokes[0]; for (i = 0; i < WHEEL_SIZE; i++) { spoke->next = spoke; spoke->prev = spoke; spoke++; } /* register timer fd with the socket master */ sockmstr_register_read_listener(smaster, process_timer_signal, NULL, timers_fd); return(GOOD); } void oor_timers_destroy() { int i; oor_timer_links_t *spoke, *sit, *next; oor_timer_t *t; if (timer_wheel.spokes == NULL){ return; } OOR_LOG(LDBG_1, "Destroying lmtimers ... "); destroy_timers_event_socket(); spoke = &timer_wheel.spokes[0]; for (i = 0; i < WHEEL_SIZE; i++) { /* the first link is NOT a timer */ sit = spoke->next; while (sit != spoke){ next = sit->next; t = CONTAINER_OF(sit, oor_timer_t, links); oor_timer_stop(t); sit = next; } spoke++; } free(timer_wheel.spokes); timer_delete(timer_id); } /* * create_timer() * * Convenience function to allocate and zero a new timer. */ oor_timer_t * oor_timer_create(timer_type type) { oor_timer_t *new_timer = xzalloc(sizeof(oor_timer_t)); new_timer->type = type; new_timer->links.prev = NULL; new_timer->links.next = NULL; return(new_timer); } void oor_timer_init(oor_timer_t *new_timer, void *owner, oor_timer_callback_t cb_fn, void *arg, oor_timer_del_cb_arg_fn del_arg_fn, void *nonces_lst) { new_timer->cb = cb_fn; new_timer->del_arg_fn = del_arg_fn; new_timer->cb_argument = arg; new_timer->owner = owner; new_timer->nonces_lst = nonces_lst; } inline void * oor_timer_owner(oor_timer_t *timer) { return(timer->owner); } inline void * oor_timer_cb_argument(oor_timer_t *timer) { return (timer->cb_argument); } inline timer_type oor_timer_type(oor_timer_t *timer) { return (timer->type); } inline void * oor_timer_nonces(oor_timer_t *timer) { return (timer->nonces_lst); } /* Insert a timer in the wheel at the appropriate location. */ static void insert_timer(oor_timer_t *tptr) { oor_timer_links_t *prev, *spoke; uint32_t pos; uint32_t ticks; uint32_t td; /* Number of ticks for this timer. */ ticks = tptr->duration; /* tick position, referenced from the * current index. */ td = (ticks % timer_wheel.num_spokes); /* Full rotations required before this timer expires */ tptr->rotation_count = (ticks / timer_wheel.num_spokes); /* Find the right spoke, and link the timer into the list at this position */ pos = ((timer_wheel.current_spoke + td) % timer_wheel.num_spokes); spoke = &timer_wheel.spokes[pos]; /* append to end of spoke */ prev = spoke->prev; tptr->links.next = spoke; tptr->links.prev = prev; prev->next = (oor_timer_links_t *) tptr; spoke->prev = (oor_timer_links_t *) tptr; return; } /* * start_timer() * * Starts a new timer with given expiration time, callback function, * and arguments. Returns a pointer to the new timer, which must be kept * to stop the timer later if desired. */ void oor_timer_start(oor_timer_t *tptr, int sexpiry) { oor_timer_links_t *next, *prev; /* See if this timer is also running. */ next = tptr->links.next; if (next != NULL) { prev = tptr->links.prev; next->prev = prev; prev->next = next; /* Update stats */ timer_wheel.running_timers--; } /* Hook up the callback */ tptr->duration = sexpiry; insert_timer(tptr); timer_wheel.running_timers++; return; } /* * stop_timer() * * Mark one of the global timers as stopped and remove it. * The nonces_lst should be removed outside the timer */ void oor_timer_stop(oor_timer_t *tptr) { oor_timer_links_t *next, *prev; if (tptr == NULL) { return; } next = tptr->links.next; prev = tptr->links.prev; if (next != NULL) { next->prev = prev; } if (prev != NULL) { prev->next = next; } tptr->links.next = NULL; tptr->links.prev = NULL; /* Update stats */ if (next != NULL || prev != NULL) { timer_wheel.running_timers--; } /* Free timer argument */ if (tptr->del_arg_fn){ tptr->del_arg_fn(tptr->cb_argument); } free(tptr); } /* * handle_timers() * * Update the wheel index, and expire any timers there, calling * the appropriate function to deal with it. */ static void handle_timers(void) { struct timeval nowtime; oor_timer_links_t *current_spoke, *next, *prev; oor_timer_t *tptr; oor_timer_callback_t callback; gettimeofday(&nowtime, NULL); timer_wheel.current_spoke = (timer_wheel.current_spoke + 1) % timer_wheel.num_spokes; current_spoke = &timer_wheel.spokes[timer_wheel.current_spoke]; tptr = (oor_timer_t *)current_spoke->next; while ((oor_timer_links_t *)tptr != current_spoke) { next = tptr->links.next; prev = tptr->links.prev; if (tptr->rotation_count > 0) { tptr->rotation_count--; } else { prev->next = next; next->prev = prev; tptr->links.next = NULL; tptr->links.prev = NULL; /* Update stats */ timer_wheel.running_timers--; timer_wheel.expirations++; callback = tptr->cb; (*callback)(tptr); } /* We can not use directly "next" as it could be released in the * callback function previously to be used */ tptr = (oor_timer_t *)(prev->next); } } static int process_timer_signal(sock_t *sl) { int sig; int bytes; bytes = read(sl->fd, &sig, sizeof(sig)); if (bytes != sizeof(sig)) { OOR_LOG(LWRN, "process_event_signal(): nothing to read"); return(-1); } if (sig == SIGRTMIN) { handle_timers(); } return(0); } /* * event_sig_handler * * Forward signal to the fd for handling in the event loop */ static void event_sig_handler(int sig) { if (write(signal_pipe[1], &sig, sizeof(sig)) != sizeof(sig)) { OOR_LOG(LWRN, "write signal %d: %s", sig, strerror(errno)); } } /* * build_timer_event_socket * * Set up the event handler socket. This is * used to serialize events like timer expirations that * we would rather deal with synchronously. This avoids * having to deal with all sorts of locking and multithreading * nonsense. */ static int build_timers_event_socket(int *timers_fd) { int flags; struct sigaction sa; if (pipe(signal_pipe) == -1) { OOR_LOG(LERR, "build_timers_event_socket: signal pipe setup failed %s", strerror(errno)); return (BAD); } *timers_fd = signal_pipe[0]; if ((flags = fcntl(*timers_fd, F_GETFL, 0)) == -1) { OOR_LOG(LERR, "build_timers_event_socket: fcntl() F_GETFL failed %s", strerror(errno)); return (BAD); } if (fcntl(*timers_fd, F_SETFL, flags | O_NONBLOCK) == -1) { OOR_LOG(LERR, "build_timers_event_socket: fcntl() set O_NONBLOCK failed " "%s", strerror(errno)); return (BAD); } memset(&sa, 0, sizeof(sa)); sa.sa_handler = event_sig_handler; sa.sa_flags = 0; sigemptyset(&sa.sa_mask); if (sigaction(SIGRTMIN, &sa, NULL) == -1) { OOR_LOG(LERR, "build_timers_event_socket: sigaction() failed %s", strerror(errno)); exit_cleanup(); } return(GOOD); } static int destroy_timers_event_socket() { struct sigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_handler = NULL; sa.sa_flags = 0; sigemptyset(&sa.sa_mask); if (sigaction(SIGRTMIN, &sa, NULL) == -1) { OOR_LOG(LERR, "destroy_timers_event_socket: sigaction() failed %s", strerror(errno)); } close(signal_pipe[0]); close(signal_pipe[1]); return(GOOD); } void oor_timer_sleep(int sec) { struct timespec timeout; timeout.tv_sec = sec; timeout.tv_nsec = 0; while (nanosleep(&timeout, &timeout) == -1 && errno == EINTR); } oor-1.2.0/oor/lib/timers.h000066400000000000000000000042051313612200500153240ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef TIMERS_H_ #define TIMERS_H_ #include "sockets.h" typedef enum { EXPIRE_MAP_CACHE_TIMER, MAP_REGISTER_TIMER, ENCAP_MAP_REGISTER_TIMER, MAP_REQUEST_RETRY_TIMER, RLOC_PROBING_TIMER, SMR_TIMER, SMR_INV_RETRY_TIMER, INFO_REQUEST_TIMER, RE_UPSTREAM_JOIN_TIMER, RE_ITR_RESOLUTION_TIMER, REG_SITE_EXPRY_TIMER } timer_type; #define TIMER_NAME_LEN 64 typedef struct oor_timer_links { struct oor_timer_links *prev; struct oor_timer_links *next; } oor_timer_links_t; struct oor_timer; typedef int (*oor_timer_callback_t)(struct oor_timer *t); typedef void (*oor_timer_del_cb_arg_fn)(void *arg); typedef struct oor_timer { oor_timer_links_t links; int duration; int rotation_count; oor_timer_callback_t cb; oor_timer_del_cb_arg_fn del_arg_fn; void *cb_argument; void *owner; void *nonces_lst; timer_type type; } oor_timer_t; int oor_timers_init(); void oor_timers_destroy(); oor_timer_t *oor_timer_create(timer_type type); void oor_timer_init(oor_timer_t *new_timer, void *owner, oor_timer_callback_t cb_fn, void *arg, oor_timer_del_cb_arg_fn del_arg_fn, void *nonces_lst); void oor_timer_start(oor_timer_t *, int); void oor_timer_stop(oor_timer_t *); void *oor_timer_owner(oor_timer_t *); void *oor_timer_cb_argument(oor_timer_t *); timer_type oor_timer_type(oor_timer_t *); void *oor_timer_nonces(oor_timer_t *); void oor_timer_sleep(int sec); #endif /*TIMERS_H_*/ oor-1.2.0/oor/lib/timers_utils.c000066400000000000000000000055441313612200500165460ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "timers_utils.h" oor_timer_t * oor_timer_with_nonce_new(timer_type type, void *owner, oor_timer_callback_t cb_fn, void *timer_arg,oor_timer_del_cb_arg_fn free_arg_fn) { oor_timer_t *timer; nonces_list_t *nonces_lst; timer = oor_timer_create(type); nonces_lst = nonces_list_new_init(timer); oor_timer_init(timer,owner,cb_fn,timer_arg,free_arg_fn,nonces_lst); return (timer); } int stop_timer_from_obj(void *obj,oor_timer_t *timer,htable_ptrs_t *ptrs_ht, htable_nonces_t *nonce_ht) { nonces_list_t *nonces_lst; htable_ptrs_timers_rm_timer(ptrs_ht, obj, timer); nonces_lst = oor_timer_nonces(timer); if (nonces_lst){ htable_nonces_reset_nonces_lst(nonce_ht,nonces_lst); nonces_list_free(nonces_lst); } oor_timer_stop(timer); return (GOOD); } int stop_timers_from_obj(void *obj,htable_ptrs_t *ptrs_ht, htable_nonces_t *nonce_ht) { glist_t *timer_lst; glist_entry_t *timer_it; oor_timer_t *timer; nonces_list_t *nonces_lst; timer_lst = htable_ptrs_timers_rm(ptrs_ht, obj); if (!timer_lst){ return (BAD); } glist_for_each_entry(timer_it,timer_lst){ timer = (oor_timer_t*)glist_entry_data(timer_it); nonces_lst = oor_timer_nonces(timer); if (nonces_lst){ htable_nonces_reset_nonces_lst(nonce_ht,nonces_lst); nonces_list_free(nonces_lst); } oor_timer_stop(timer); } glist_destroy(timer_lst); return (GOOD); } int stop_timers_of_type_from_obj(void *obj, timer_type type, htable_ptrs_t *ptrs_ht, htable_nonces_t *nonce_ht) { glist_t *timers_lst; glist_entry_t *timer_it; oor_timer_t *timer; nonces_list_t *nonces_lst; timers_lst = htable_ptrs_timers_rm_timers_of_type(ptrs_ht,obj,type); glist_for_each_entry(timer_it,timers_lst){ timer = (oor_timer_t*)glist_entry_data(timer_it); nonces_lst = oor_timer_nonces(timer); if (nonces_lst){ htable_nonces_reset_nonces_lst(nonce_ht,nonces_lst); nonces_list_free(nonces_lst); } oor_timer_stop(timer); } glist_destroy(timers_lst); return (GOOD); } oor-1.2.0/oor/lib/timers_utils.h000066400000000000000000000024541313612200500165500ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef TIMERS_UTILS_H_ #define TIMERS_UTILS_H_ #include "nonces_table.h" #include "pointers_table.h" oor_timer_t * oor_timer_with_nonce_new(timer_type type, void *owner, oor_timer_callback_t cb_fn, void *timer_arg, oor_timer_del_cb_arg_fn free_arg_fn); int stop_timer_from_obj(void *obj,oor_timer_t *timer,htable_ptrs_t *ptrs_ht, htable_nonces_t *nonce_ht); int stop_timers_from_obj(void *obj,htable_ptrs_t *ptrs_ht, htable_nonces_t *nonce_ht); int stop_timers_of_type_from_obj(void *obj, timer_type type, htable_ptrs_t *ptrs_ht, htable_nonces_t *nonce_ht); #endif /* TIMERS_UTILS_H_ */ oor-1.2.0/oor/lib/util.c000066400000000000000000000104011313612200500147640ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "util.h" #include "oor_log.h" static inline int convert_hex_char_to_byte (char val) { val = (char)toupper (val); switch (val){ case '0': return (0); case '1': return (1); case '2': return (2); case '3': return (3); case '4': return (4); case '5': return (5); case '6': return (6); case '7': return (7); case '8': return (8); case '9': return (9); case 'A': return (10); case 'B': return (11); case 'C': return (12); case 'D': return (13); case 'E': return (14); case 'F': return (15); default: return (-1); } } int convert_hex_string_to_bytes(char *hex, uint8_t *bytes, int bytes_len) { int ctr = 0; char hex_digit[2]; int partial_byte[2] = {0,0}; while (hex[ctr] != '\0' && ctr <= bytes_len * 2) { ctr++; } if (hex[ctr] != '\0' && ctr != bytes_len * 2) { return (BAD); } for (ctr = 0; ctr < bytes_len; ctr++) { hex_digit[0] = hex[ctr * 2]; hex_digit[1] = hex[ctr * 2 + 1]; partial_byte[0] = convert_hex_char_to_byte(hex_digit[0]); partial_byte[1] = convert_hex_char_to_byte(hex_digit[1]); if (partial_byte[0] == -1 || partial_byte[1] == -1) { OOR_LOG(LDBG_2, "convert_hex_string_to_bytes: Invalid hexadecimal" " number"); return (BAD); } bytes[ctr] = partial_byte[0] * 16 + partial_byte[1]; } return (GOOD); } char * get_char_from_xTR_ID (lisp_xtr_id *xtrid) { static char xTR_ID_str[33]; int ctr = 0; memset (xTR_ID_str,0,33); for (ctr = 0 ; ctr < 16; ctr++){ sprintf(xTR_ID_str, "%s%02x", xTR_ID_str, xtrid->byte[ctr]); } return (xTR_ID_str); } /* Remove the address from the list not compatible with the local RLOCs */ void addr_list_rm_not_compatible_addr(glist_t *addr_lst, int compatible_addr_flags) { glist_entry_t *it_addr, *aux_it_addr; lisp_addr_t *addr; glist_for_each_entry_safe(it_addr, aux_it_addr, addr_lst){ addr = (lisp_addr_t *)glist_entry_data(it_addr); if (!is_compatible_addr(addr,compatible_addr_flags)){ glist_remove(it_addr,addr_lst); } } } uint8_t is_compatible_addr(lisp_addr_t *addr, int compatible_addr_flags) { lisp_addr_t *ip_addr = lisp_addr_get_ip_addr(addr); int afi = lisp_addr_ip_afi(ip_addr); switch(afi){ case AF_INET: return ((compatible_addr_flags & IPv4_SUPPORT) != 0); case AF_INET6: return ((compatible_addr_flags & IPv6_SUPPORT) != 0); default: return (FALSE); } } /* * Fill dst from src removing spaces. * Dst should already be allocated and have enough space */ void str_rm_spaces(char *src, char *dst) { int s, d=0; for (s=0; src[s] != 0; s++){ if (src[s] != ' ') { dst[d] = src[s]; d++; } } dst[d] = 0; } /* * Fill dst from src removing double spaces. * Dst should already be allocated and have enough space */ void str_rm_double_spaces(char *src, char *dst) { int s, d=0; uint8_t is_prev_space = FALSE; for (s=0; src[s] != 0; s++){ if (src[s] == ' ') { if (is_prev_space == FALSE){ dst[d] = src[s]; d++; is_prev_space = TRUE; } }else{ dst[d] = src[s]; d++; is_prev_space = FALSE; } } dst[d] = 0; } oor-1.2.0/oor/lib/util.h000066400000000000000000000023351313612200500150000ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef UTIL_H_ #define UTIL_H_ #include "../liblisp/lisp_address.h" int convert_hex_string_to_bytes(char *hex, uint8_t *bytes, int bytes_len); char *get_char_from_xTR_ID (lisp_xtr_id *xtrid); /* Remove the address from the list not compatible with the local RLOCs */ void addr_list_rm_not_compatible_addr(glist_t *addr_lst, int compatible_addr_flags); uint8_t is_compatible_addr(lisp_addr_t *addr, int compatible_addr_flags); void str_rm_spaces(char *src, char *dst); void str_rm_double_spaces(char *src, char *dst); #endif /* UTIL_H_ */ oor-1.2.0/oor/lib/vpp_api/000077500000000000000000000000001313612200500153055ustar00rootroot00000000000000oor-1.2.0/oor/lib/vpp_api/ctrl_vpp_plugin.c000066400000000000000000000106641313612200500206670ustar00rootroot00000000000000 /* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include #include #include #include #include "../../defs.h" #include "../../lib/oor_log.h" /* Declare message IDs */ #include #include "vpp_api_requests.h" /* define message structures */ #define vl_typedefs #include #undef vl_typedefs /* declare message handlers for each api */ #define vl_endianfun /* define message structures */ #include #undef vl_endianfun /* instantiate all the print functions we know about */ #define vl_print(handle, ...) #define vl_printfun #include #undef vl_printfun /* Get the API version number. */ #define vl_api_version(n,v) static u32 oor_ctrl_api_version=(v); #include #undef vl_api_version uint16_t ctr_msg_id_base = ~0; #define foreach_standard_reply_retval_handler \ _(oor_ctrl_enable_disable_reply) #define _(n) \ static void vl_api_##n##_t_handler \ (vl_api_##n##_t * mp) \ { \ vpp_api_main_t * vam = vpp_api_main_get(); \ i32 retval = ntohl(mp->retval); \ if (vam->async_mode) { \ vam->async_errors += (retval < 0); \ } else { \ vam->retval = retval; \ vam->result_ready = 1; \ } \ } foreach_standard_reply_retval_handler; #undef _ /* M: construct, but don't yet send a message */ #define M(T,t) \ do { \ vam->result_ready = 0; \ mp = vl_msg_api_alloc(sizeof(*mp)); \ memset (mp, 0, sizeof (*mp)); \ mp->_vl_msg_id = ntohs (VL_API_##T + ctr_msg_id_base); \ mp->client_index = vam->my_client_index; \ } while(0); /* S: send a message */ #define S (vl_msg_api_send_shmem (vam->vl_input_queue, (u8 *)&mp)) int vpp_oor_ctrl_enable_disable (char *iface_name, uint8_t enable_disable) { vpp_api_main_t * vam = vpp_api_main_get(); vl_api_oor_ctrl_enable_disable_t * mp; /* Construct the API message */ M(OOR_CTRL_ENABLE_DISABLE, oor_ctrl_enable_disable); memcpy (mp->host_if_name, iface_name, strlen(iface_name)); mp->enable_disable = enable_disable; /* send it... */ S; if (vpp_wait(vam) == ERR_NO_REPLY){ OOR_LOG(LWRN,"VPP could not enable OOR control plugin"); return (BAD); } return (GOOD); } clib_error_t * ctrl_plugin_register (vpp_api_main_t * vam) { u8 * name; /* Ask the vpp engine for the first assigned message-id */ name = format (0, "oor_ctrl_%08x%c", oor_ctrl_api_version, 0); ctr_msg_id_base = vl_client_get_first_plugin_msg_id ((char *) name); vec_free(name); if (ctr_msg_id_base != (uint16_t) ~0){ vl_msg_api_set_handlers((VL_API_OOR_CTRL_ENABLE_DISABLE_REPLY + ctr_msg_id_base), \ "oor_ctrl_enable_disable_reply", \ vl_api_oor_ctrl_enable_disable_reply_t_handler, \ vl_noop_handler, \ vl_api_oor_ctrl_enable_disable_reply_t_endian, \ vl_api_oor_ctrl_enable_disable_reply_t_print, \ sizeof(vl_api_oor_ctrl_enable_disable_reply_t), 1); } return 0; } oor-1.2.0/oor/lib/vpp_api/pkt_miss_vpp_plugin.c000066400000000000000000000234721313612200500215550ustar00rootroot00000000000000 /* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include #include #include #include #include "../../defs.h" #include "../../lib/oor_log.h" /* Declare message IDs */ #include #include "vpp_api_requests.h" /* define message structures */ #define vl_typedefs #include #undef vl_typedefs /* declare message handlers for each api */ #define vl_endianfun /* define message structures */ #include #undef vl_endianfun /* instantiate all the print functions we know about */ #define vl_print(handle, ...) #define vl_printfun #include #undef vl_printfun #define vl_api_version(n,v) static u32 oor_pkt_miss_api_version=(v); #include #undef vl_api_version uint16_t pkt_miss_msg_id_base = ~0; #define foreach_standard_reply_retval_handler \ _(oor_pkt_miss_enable_disable_reply) \ _(oor_pkt_miss_native_route_reply) \ _(oor_pkt_miss_drop_route_reply) #define _(n) \ static void vl_api_##n##_t_handler \ (vl_api_##n##_t * mp) \ { \ vpp_api_main_t * vam = vpp_api_main_get(); \ i32 retval = ntohl(mp->retval); \ if (vam->async_mode) { \ vam->async_errors += (retval < 0); \ } else { \ vam->retval = retval; \ vam->result_ready = 1; \ } \ } foreach_standard_reply_retval_handler; #undef _ /********************** API REPLY HANDLER ***********************************/ static void vl_api_oor_pkt_miss_get_default_route_reply_t_handler(vl_api_oor_pkt_miss_get_default_route_reply_t * mp) { vpp_api_main_t * vam = vpp_api_main_get(); ; i32 retval = ntohl (mp->retval); int afi; lisp_addr_del(vam->gw); if (0 <= retval) { if (!mp->has_gateway){ vam->gw = lisp_addr_new_lafi(LM_AFI_NO_ADDR); }else{ vam->gw = lisp_addr_new_lafi(LM_AFI_IP); if (mp->is_ipv6){ afi = AF_INET6; }else{ afi = AF_INET; } ip_addr_init(lisp_addr_ip(vam->gw), &mp->address, afi); } } vam->retval = retval; vam->result_ready = 1; } /* M: construct, but don't yet send a message */ #define M(T,t) \ do { \ vam->result_ready = 0; \ mp = vl_msg_api_alloc(sizeof(*mp)); \ memset (mp, 0, sizeof (*mp)); \ mp->_vl_msg_id = ntohs (VL_API_##T + pkt_miss_msg_id_base); \ mp->client_index = vam->my_client_index; \ } while(0); /* S: send a message */ #define S (vl_msg_api_send_shmem (vam->vl_input_queue, (u8 *)&mp)) int vpp_oor_pkt_miss_enable_disable(char *iface_name, uint8_t enable_disable) { vpp_api_main_t * vam = vpp_api_main_get(); vl_api_oor_pkt_miss_enable_disable_t * mp; /* Construct the API message */ M (OOR_PKT_MISS_ENABLE_DISABLE, oor_pkt_miss_enable_disable); memcpy (mp->host_if_name, iface_name, strlen(iface_name)); mp->enable_disable = enable_disable; /* send it... */ S; if (vpp_wait(vam) == ERR_NO_REPLY){ OOR_LOG(LWRN,"VPP could not enable oor packet miss plugin"); return (BAD); } return (GOOD); } int vpp_oor_pkt_miss_native_route (lisp_addr_t *prefix, uint8_t is_add) { vpp_api_main_t * vam = vpp_api_main_get(); vl_api_oor_pkt_miss_native_route_t * mp; lisp_addr_t *ip_pref; int afi; ip_pref = lisp_addr_get_ip_pref_addr(prefix); afi = lisp_addr_ip_afi(ip_pref); /* Construct the API message */ M(OOR_PKT_MISS_NATIVE_ROUTE, oor_pkt_miss_native_route); mp->is_add = is_add; mp->is_ipv6 = afi == AF_INET6 ? 1 : 0; mp->mask_len = lisp_addr_ip_get_plen(ip_pref); ip_addr_copy_to(mp->address, lisp_addr_ip_get_addr(ip_pref)); /* send it... */ S; /* Wait for a reply... */ if (vpp_wait(vam) == ERR_NO_REPLY){ OOR_LOG(LWRN,"VPP could not %s native route for prefix %s", is_add == ADD ? "add" : "rm",lisp_addr_to_char(prefix)); return (BAD); } OOR_LOG(LDBG_2,"VPP %s native route for prefix %s", is_add == ADD ? "add" : "rm",lisp_addr_to_char(prefix)); return (GOOD); } int vpp_oor_pkt_miss_drop_route (lisp_addr_t *prefix, uint8_t is_add, uint32_t table_id) { vpp_api_main_t * vam = vpp_api_main_get(); vl_api_oor_pkt_miss_drop_route_t * mp; lisp_addr_t *ip_pref; int afi; ip_pref = lisp_addr_get_ip_pref_addr(prefix); afi = lisp_addr_ip_afi(ip_pref); /* Construct the API message */ M(OOR_PKT_MISS_DROP_ROUTE, oor_pkt_miss_drop_route); mp->is_add = is_add; mp->is_ipv6 = afi == AF_INET6 ? 1 : 0; mp->mask_len = lisp_addr_ip_get_plen(ip_pref); ip_addr_copy_to(mp->address, lisp_addr_ip_get_addr(ip_pref)); mp->table_id = table_id; /* send it... */ S; /* Wait for a reply... */ if (vpp_wait(vam) == ERR_NO_REPLY){ OOR_LOG(LWRN,"VPP could not %s drop route for prefix %s from table %d", is_add == ADD ? "add" : "rm", lisp_addr_to_char(prefix), table_id); return (BAD); } OOR_LOG(LDBG_3,"VPP %s drop route for prefix %s from table %d", is_add == ADD ? "add" : "rm", lisp_addr_to_char(prefix), table_id); return (GOOD); } lisp_addr_t * vpp_oor_pkt_miss_get_default_route (int afi) { vpp_api_main_t * vam = vpp_api_main_get(); vl_api_oor_pkt_miss_get_default_route_t * mp; /* Construct the API message */ M(OOR_PKT_MISS_GET_DEFAULT_ROUTE, oor_pkt_miss_get_default_route); mp->is_ipv6 = (afi == AF_INET6 ? 1 : 0); /* send it... */ S; /* Wait for a reply... */ if (vpp_wait(vam) == ERR_NO_REPLY){ OOR_LOG(LWRN,"VPP could not get %s gateway", afi == AF_INET6 ? "ipv6" : "ipv4"); return (BAD); } OOR_LOG(LDBG_2,"VPP gateway is %s", lisp_addr_to_char(vam->gw)); return (vam->gw); } clib_error_t * pkt_miss_plugin_register (vpp_api_main_t * vam) { u8 * name; /* Ask the vpp engine for the first assigned message-id */ name = format (0, "oor_pkt_miss_%08x%c", oor_pkt_miss_api_version, 0); pkt_miss_msg_id_base = vl_client_get_first_plugin_msg_id ((char *) name); vec_free(name); if (pkt_miss_msg_id_base != (uint16_t) ~0){ vl_msg_api_set_handlers((VL_API_OOR_PKT_MISS_ENABLE_DISABLE_REPLY + pkt_miss_msg_id_base), \ "oor_pkt_miss_enable_disable_reply", \ vl_api_oor_pkt_miss_enable_disable_reply_t_handler, \ vl_noop_handler, \ vl_api_oor_pkt_miss_enable_disable_reply_t_endian, \ vl_api_oor_pkt_miss_enable_disable_reply_t_print, \ sizeof(vl_api_oor_pkt_miss_enable_disable_reply_t), 1); vl_msg_api_set_handlers((VL_API_OOR_PKT_MISS_NATIVE_ROUTE_REPLY + pkt_miss_msg_id_base), \ "oor_pkt_miss_native_route_reply", \ vl_api_oor_pkt_miss_native_route_reply_t_handler, \ vl_noop_handler, \ vl_api_oor_pkt_miss_native_route_reply_t_endian, \ vl_api_oor_pkt_miss_native_route_reply_t_print, \ sizeof(vl_api_oor_pkt_miss_native_route_reply_t), 1); vl_msg_api_set_handlers((VL_API_OOR_PKT_MISS_DROP_ROUTE_REPLY + pkt_miss_msg_id_base), \ "oor_pkt_miss_drop_route_reply", \ vl_api_oor_pkt_miss_drop_route_reply_t_handler, \ vl_noop_handler, \ vl_api_oor_pkt_miss_drop_route_reply_t_endian, \ vl_api_oor_pkt_miss_drop_route_reply_t_print, \ sizeof(vl_api_oor_pkt_miss_drop_route_reply_t), 1); vl_msg_api_set_handlers((VL_API_OOR_PKT_MISS_GET_DEFAULT_ROUTE_REPLY + pkt_miss_msg_id_base), \ "oor_pkt_miss_get_default_route_reply", \ vl_api_oor_pkt_miss_get_default_route_reply_t_handler, \ vl_noop_handler, \ vl_api_oor_pkt_miss_get_default_route_reply_t_endian, \ vl_api_oor_pkt_miss_get_default_route_reply_t_print, \ sizeof(vl_api_oor_pkt_miss_get_default_route_reply_t), 1); } return 0; } oor-1.2.0/oor/lib/vpp_api/vpp_api.c000066400000000000000000000047021313612200500171120ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "vpp_api_requests.h" #include "../oor_log.h" #include "../../defs.h" #include #include #include vpp_api_main_t vpp_api_main; vlib_main_t vlib_global_main; vlib_main_t **vlib_mains; int vpp_is_enabled() { FILE *fp; char output[100]; fp = popen("pidof vpp", "r"); if (fp == NULL) { OOR_LOG(LDBG_1,"vpp_is_enabled: Couldn't check vpp status"); return (FALSE); } if (fgets(output, sizeof(output)-1, fp) == NULL){ OOR_LOG(LERR,"VPP is not running. Start VPP before starting OOR"); return (FALSE); } pclose(fp); return (TRUE); } int connect_to_vpe (char *name) { vpp_api_main_t *vam = &vpp_api_main; api_main_t *am = &api_main; if (vl_client_connect_to_vlib ("/vpe-api", name, 32) < 0){ return (BAD); } vam->vl_input_queue = am->shmem_hdr->vl_input_queue; vam->my_client_index = am->my_client_index; return 0; } int vpp_init_api() { vpp_api_main_t *vam = &vpp_api_main; uint8_t *heap; mheap_t *h; clib_mem_init (0, 128 << 20); heap = clib_mem_get_per_cpu_heap (); h = mheap_header (heap); /* make the main heap thread-safe */ h->flags |= MHEAP_FLAG_THREAD_SAFE; clib_time_init (&vam->clib_time); vat_api_hookup (vam); if (connect_to_vpe ("vpp_api_oor") < 0) { svm_region_exit (); OOR_LOG(LERR, "Couldn't connect to vpe, exiting...\n"); return(BAD); } ctrl_plugin_register(vam); pkt_miss_plugin_register(vam); return (GOOD); } inline int vpp_uninit_api() { vpp_api_main_t *vam = &vpp_api_main; glist_destroy(vam->ip_addr_lst); glist_destroy(vam->iface_list); vl_client_disconnect_from_vlib (); return (GOOD); } oor-1.2.0/oor/lib/vpp_api/vpp_api.h000066400000000000000000000003741313612200500171200ustar00rootroot00000000000000/* * vpp_api.h * * Created on: Feb 22, 2017 * Author: alopez */ #ifndef OOR_LIB_VPP_API_VPP_API_H_ #define OOR_LIB_VPP_API_VPP_API_H_ int vpp_is_enabled(); int vpp_init_api(); int vpp_uninit_api(); #endif /* OOR_LIB_VPP_API_VPP_API_H_ */ oor-1.2.0/oor/lib/vpp_api/vpp_api_reply.c000066400000000000000000000175551313612200500203370ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "../mem_util.h" #include "../oor_log.h" #include "../../defs.h" #include "../../liblisp/lisp_address.h" #include #include #include "vpp_api_requests.h" /* define message structures */ #define vl_typedefs #include #undef vl_typedefs /* declare message handlers for each api */ #define vl_endianfun /* define message structures */ #include #undef vl_endianfun /* instantiate all the print functions we know about */ #define vl_print(handle, ...) #define vl_printfun #include #undef vl_printfun #define vl_api_version(n,v) static u32 api_version=(v); #include #undef vl_api_version inline static vpp_api_iface_t * vpp_api_iface_new() { vpp_api_iface_t *iface = (vpp_api_iface_t *)xzalloc(sizeof(vpp_api_iface_t)); return (iface); } inline static void vpp_api_iface_free(vpp_api_iface_t *iface) { if (iface->iface_name){ free(iface->iface_name); } free (iface); iface = NULL; } #define foreach_standard_reply_retval_handler \ _(sw_interface_set_flags_reply) \ _(sw_interface_set_unnumbered_reply) \ _(gpe_enable_disable_reply) \ _(gpe_add_del_iface_reply) \ _(gpe_add_del_fwd_entry_reply) #define _(n) \ static void vl_api_##n##_t_handler (vl_api_##n##_t * mp) \ { \ vpp_api_main_t * vam = &vpp_api_main; \ uint32_t retval = ntohl(mp->retval); \ if (vam->async_mode) { \ vam->async_errors += (retval < 0); \ } else { \ vam->retval = retval; \ vam->result_ready = 1; \ } \ } foreach_standard_reply_retval_handler; #undef _ /* * Table of message reply handlers, must include boilerplate handlers * we just generated */ #define foreach_vpp_api_reply_msg \ _(SW_INTERFACE_DETAILS, sw_interface_details) \ _(SW_INTERFACE_SET_FLAGS_REPLY, sw_interface_set_flags_reply) \ _(SW_INTERFACE_SET_UNNUMBERED_REPLY,sw_interface_set_unnumbered_reply) \ _(CONTROL_PING_REPLY, control_ping_reply) \ _(IP_ADDRESS_DETAILS, ip_address_details) \ _(IP_FIB_DETAILS, ip_fib_details) \ _(IP6_FIB_DETAILS, ip6_fib_details) \ _(AF_PACKET_CREATE_REPLY, af_packet_create_reply) \ _(GPE_ENABLE_DISABLE_REPLY, gpe_enable_disable_reply) \ _(GPE_ADD_DEL_IFACE_REPLY, gpe_add_del_iface_reply) \ _(GPE_ADD_DEL_FWD_ENTRY_REPLY, gpe_add_del_fwd_entry_reply) \ _(SW_INTERFACE_GET_TABLE_REPLY, sw_interface_get_table_reply) u8 * format_ip4_address (u8 * s, va_list * args) { u8 *a = va_arg (*args, u8 *); return format (s, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]); } /********************** API REPLY HANDLER ***********************************/ static void vl_api_control_ping_reply_t_handler(vl_api_control_ping_reply_t * mp) { vpp_api_main_t *vam = &vpp_api_main; i32 retval = ntohl (mp->retval); if (vam->async_mode) { vam->async_errors += (retval < 0); } else { vam->retval = retval; vam->result_ready = 1; } } /* * Special-case: build the interface table, maintain * the next loopback sw_if_index vbl. */ static void vl_api_sw_interface_details_t_handler(vl_api_sw_interface_details_t * mp) { vpp_api_main_t *vam = &vpp_api_main; vpp_api_iface_t *iface = vpp_api_iface_new(); iface->iface_index = ntohl(mp->sw_if_index); iface->iface_name = strdup((char *)format (0, "%s%c", mp->interface_name, 0)); iface->status = (mp->admin_up_down == 1 && mp->link_up_down == 1) ? UP : FALSE; memcpy(iface->l2_address, mp->l2_address, sizeof(mp->l2_address)); glist_add(iface,vam->iface_list); } static void vl_api_ip_address_details_t_handler(vl_api_ip_address_details_t * mp) { vpp_api_main_t *vam = &vpp_api_main; lisp_addr_t *addr; addr = lisp_addr_new_lafi(LM_AFI_IP); ip_addr_init(lisp_addr_ip(addr), &mp->ip, vam->requested_ip_afi); lisp_addr_set_plen(addr,mp->prefix_length); glist_add(addr,vam->ip_addr_lst); } static void vl_api_af_packet_create_reply_t_handler(vl_api_af_packet_create_reply_t * mp) { vpp_api_main_t *vam = &vpp_api_main; i32 retval = ntohl (mp->retval); vam->retval = retval; vam->sw_if_index = ntohl (mp->sw_if_index); vam->result_ready = 1; } static void vl_api_sw_interface_get_table_reply_t_handler(vl_api_sw_interface_get_table_reply_t * mp) { vpp_api_main_t *vam = &vpp_api_main; vam->table_id = ntohl (mp->vrf_id); vam->retval = ntohl (mp->retval); vam->result_ready = 1; } #define vl_api_ip_fib_details_t_endian vl_noop_handler #define vl_api_ip_fib_details_t_print vl_noop_handler static void vl_api_ip_fib_details_t_handler (vl_api_ip_fib_details_t * mp) { vpp_api_main_t *vam = &vpp_api_main; lisp_addr_t *pref; pref = lisp_addr_new_lafi(LM_AFI_IPPREF); ip_addr_init(lisp_addr_ip(pref), &mp->address, AF_INET); lisp_addr_set_plen(pref,mp->address_length); glist_add(pref,vam->prefix_lst); } #define vl_api_ip6_fib_details_t_endian vl_noop_handler #define vl_api_ip6_fib_details_t_print vl_noop_handler static void vl_api_ip6_fib_details_t_handler (vl_api_ip6_fib_details_t * mp) { vpp_api_main_t *vam = &vpp_api_main; lisp_addr_t *pref; pref = lisp_addr_new_lafi(LM_AFI_IPPREF); ip_addr_init(lisp_addr_ip(pref), &mp->address, AF_INET6); lisp_addr_set_plen(pref,mp->address_length); glist_add(pref,vam->prefix_lst); } /***************************************************************************************/ #define _(N,n) \ static void vl_api_##n##_t_handler_uni \ (vl_api_##n##_t * mp) \ { \ vl_api_##n##_t_handler(mp); \ } foreach_vpp_api_reply_msg; #undef _ void vat_api_hookup (vpp_api_main_t * vam) { #define _(N,n) \ vl_msg_api_set_handlers(VL_API_##N, #n, \ vl_api_##n##_t_handler_uni, \ vl_noop_handler, \ vl_api_##n##_t_endian, \ vl_api_##n##_t_print, \ sizeof(vl_api_##n##_t), 1); foreach_vpp_api_reply_msg; #undef _ vl_msg_api_set_first_available_msg_id (VL_MSG_FIRST_AVAILABLE); vam->iface_list = glist_new_managed((glist_del_fct)vpp_api_iface_free); vam->ip_addr_lst = glist_new_managed((glist_del_fct)lisp_addr_del); vam->prefix_lst = glist_new_managed((glist_del_fct)lisp_addr_del); } oor-1.2.0/oor/lib/vpp_api/vpp_api_requests.c000066400000000000000000000205001313612200500210370ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "vpp_api_requests.h" #include "../generic_list.h" #include "../oor_log.h" #include "../../defs.h" #include #define vl_typedefs #include #undef vl_typedefs #define vl_endianfun /* define message structures */ #include #undef vl_endianfun void vlib_cli_output (struct vlib_main_t *vm, char *fmt, ...) { clib_warning ("BUG"); } int vpp_wait(vpp_api_main_t * vam) { f64 timeout; timeout = clib_time_now (&vam->clib_time) + 1.0; while (clib_time_now (&vam->clib_time) < timeout) { if (vam->result_ready == 1) { return (vam->retval); } } return(ERR_NO_REPLY); } int vpp_create_ap_iface(char *iface_name, uint8_t *mac) { vpp_api_main_t * vam = vpp_api_main_get(); vl_api_af_packet_create_t *mp; MSG (AF_PACKET_CREATE, af_packet_create); memcpy (mp->host_if_name, iface_name, strlen(iface_name)); memcpy (mp->hw_addr,mac,6); mp->use_random_hw_addr = 1; VPP_SEND; if (vpp_wait(vam) == ERR_NO_REPLY){ OOR_LOG(LWRN,"VPP could not create interface HOST-%s associated with interface %s" , iface_name, iface_name); return (0); } return (vam->sw_if_index); } int vpp_set_interface_status (uint32_t iface_index, uint8_t status) { vpp_api_main_t * vam = vpp_api_main_get(); vl_api_sw_interface_set_flags_t *mp; MSG (SW_INTERFACE_SET_FLAGS, sw_interface_set_flags); mp->sw_if_index = ntohl (iface_index); mp->admin_up_down = status; mp->link_up_down = status; VPP_SEND; if (vpp_wait(vam) == ERR_NO_REPLY){ OOR_LOG(LWRN,"VPP could not set status for interface %d", iface_index); return (BAD); } return (GOOD); } int vpp_set_interface_unnumbered (uint32_t iface_index, int action) { vpp_api_main_t * vam = vpp_api_main_get(); vl_api_sw_interface_set_unnumbered_t *mp; MSG (SW_INTERFACE_SET_UNNUMBERED, sw_interface_set_unnumbered); mp->sw_if_index = ntohl (iface_index); mp->unnumbered_sw_if_index = ntohl (iface_index); mp->is_add = action; VPP_SEND; if (vpp_wait(vam) == ERR_NO_REPLY){ OOR_LOG(LWRN,"VPP could not set interface %d as unnumbered", iface_index); return (BAD); } return (GOOD); } int vpp_lisp_gpe_enable_disable(uint8_t enable_lisp_gpe) { /* OOR_CTRL plugin enables lisp */ vpp_api_main_t * vam = vpp_api_main_get(); vl_api_gpe_enable_disable_t *mp; /* Construct the API message */ MSG (GPE_ENABLE_DISABLE, gpe_enable_disable); mp->is_en = 1; /* send it... */ VPP_SEND; if (vpp_wait(vam) == ERR_NO_REPLY){ OOR_LOG(LWRN,"VPP could not %s lisp gpe", enable_lisp_gpe ? "enable" : "disable"); return (BAD); } return (GOOD); } int vpp_lisp_gpe_add_del_iface(uint32_t table, uint32_t vni, uint8_t action) { vpp_api_main_t * vam = vpp_api_main_get(); vl_api_gpe_add_del_iface_t *mp; /* Construct the API message */ MSG (GPE_ADD_DEL_IFACE, gpe_add_del_iface); mp->is_add = action; mp->dp_table = table; mp->is_l2 = FALSE; mp->vni = vni; /* send it... */ VPP_SEND; if (vpp_wait(vam) == ERR_NO_REPLY){ OOR_LOG(LWRN,"VPP could not %s lisp gpe interface for vni %d", action == ADD ? "add" : "remove", vni); return (BAD); } OOR_LOG(LDBG_2,"VPP: LISP gpe interface associated with VNI %d has been %s", vni, action == ADD ? "added" : "removed"); return (GOOD); } /** * Add/delete mapping between vni and vrf */ int vpp_lisp_eid_table_add_del_map (uint32_t table, uint32_t vni, uint8_t action) { vpp_api_main_t * vam = vpp_api_main_get(); vl_api_lisp_eid_table_add_del_map_t *mp; MSG (LISP_EID_TABLE_ADD_DEL_MAP, lisp_eid_table_add_del_map); mp->is_add = action; mp->vni = htonl (vni); mp->dp_table = htonl (table); mp->is_l2 = FALSE; /* send */ VPP_SEND; if (vpp_wait(vam) == ERR_NO_REPLY){ OOR_LOG(LWRN,"VPP could not %s lisp gpe interface associated with VNI %d", action == ADD ? "map" : "unmap",vni); return (BAD); } OOR_LOG(LDBG_2,"VPP: LISP gpe interface associated with VNI %d has been %s", vni, action == ADD ? "mapped" : "unmapped"); return (GOOD); } typedef struct rloc_{ uint8_t is_ip4; /**< is locator an IPv4 address? */ uint8_t weight; /**< locator weight */ uint8_t addr[16]; /**< IPv4/IPv6 address */ }__attribute__ ((__packed__)) rloc_t; void vpp_write_rloc(void *buff, lisp_addr_t *addr, uint8_t weight) { rloc_t *vpp_rloc = buff; vpp_rloc->is_ip4 = lisp_addr_ip_afi(addr) == AF_INET ? 1 : 0; vpp_rloc->weight = weight; ip_addr_copy_to(vpp_rloc->addr, lisp_addr_ip(addr)); } int vpp_lisp_gpe_add_del_fwd_entry (fwd_entry_vpp_t *fe, lisp_action_e action, uint8_t is_add) { vpp_api_main_t * vam = vpp_api_main_get(); vl_api_gpe_add_del_fwd_entry_t *mp; lisp_addr_t *src_eid, *dst_eid; vpp_loct_pair * vpp_pair; glist_entry_t * pairs_it; int vni=0, ctr=0; src_eid = lisp_addr_get_ip_pref_addr(fe->seid); dst_eid = lisp_addr_get_ip_pref_addr(fe->deid); vni = fe->iid; /* Construct the API message */ MSG_PLUS (GPE_ADD_DEL_FWD_ENTRY, gpe_add_del_fwd_entry, sizeof (rloc_t) * glist_size(fe->loc_pair_lst)*2); mp->is_add = is_add; ip_addr_copy_to(mp->lcl_eid, lisp_addr_ip(src_eid)); ip_addr_copy_to(mp->rmt_eid, lisp_addr_ip(dst_eid)); mp->eid_type = lisp_addr_ip_afi(dst_eid) == AF_INET ? 0 : 1; mp->lcl_len = lisp_addr_ip_get_plen(src_eid); mp->rmt_len = lisp_addr_ip_get_plen(dst_eid); mp->action = action; mp->vni = htonl(vni); mp->dp_table = htonl(vni); mp->loc_num = htonl(glist_size(fe->loc_pair_lst)*2); if (mp->loc_num != 0) { glist_for_each_entry(pairs_it,fe->loc_pair_lst){ vpp_pair = (vpp_loct_pair *)glist_entry_data(pairs_it); vpp_write_rloc(CO(mp->locs,sizeof(rloc_t)*ctr), vpp_pair->srloc, 0); ctr++; } ctr = 0; glist_for_each_entry(pairs_it,fe->loc_pair_lst){ vpp_pair = (vpp_loct_pair *)glist_entry_data(pairs_it); vpp_write_rloc(CO(mp->locs,sizeof(rloc_t)*(ctr + glist_size(fe->loc_pair_lst))), vpp_pair->drloc, vpp_pair->weight); ctr++; } } /* send */ VPP_SEND; if (vpp_wait(vam) == ERR_NO_REPLY){ OOR_LOG(LWRN,"VPP could not add forward entry"); return (BAD); } return (GOOD); } int vpp_interface_get_table(uint32_t iface_index, uint8_t is_ipv6) { vpp_api_main_t * vam = vpp_api_main_get(); vl_api_sw_interface_get_table_t *mp; MSG (SW_INTERFACE_GET_TABLE, sw_interface_get_table); mp->sw_if_index = htonl (iface_index); mp->is_ipv6 = is_ipv6; VPP_SEND; if (vpp_wait(vam) == ERR_NO_REPLY){ OOR_LOG(LWRN,"VPP could not get table associated with interface %s"); return (ERR_NO_EXIST); } return (vam->table_id); } glist_t * vpp_ip_fib_prefixs(int afi) { glist_t *prefixs_list; vpp_api_main_t * vam = vpp_api_main_get(); vl_api_ip_fib_dump_t *mp; glist_remove_all(vam->prefix_lst); if (afi == AF_INET){ MSG (IP_FIB_DUMP, ip_fib_dump); }else{ MSG (IP6_FIB_DUMP, ip6_fib_dump); } VPP_SEND; /* Use a control ping for synchronization */ { vl_api_control_ping_t *mp; MSG (CONTROL_PING, control_ping); VPP_SEND; } if (vpp_wait(vam) == ERR_NO_REPLY){ OOR_LOG(LWRN,"VPP could not get fib table"); return (NULL); } prefixs_list = glist_clone(vam->prefix_lst, (glist_clone_obj)lisp_addr_clone); return (prefixs_list); } oor-1.2.0/oor/lib/vpp_api/vpp_api_requests.h000066400000000000000000000110021313612200500210410ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef OOR_LIB_VPP_API_VPP_API_REQUESTS_H_ #define OOR_LIB_VPP_API_VPP_API_REQUESTS_H_ #include "../generic_list.h" #include "../../fwd_policies/vpp_balancing/fwd_entry_vpp.h" #include #include #include typedef struct { /* vpe input queue */ unix_shared_memory_queue_t *vl_input_queue; /* interface list */ glist_t *iface_list; /* Address of the requested interface*/ glist_t *ip_addr_lst; // /* List of prefixes */ glist_t *prefix_lst; // /* Gateway */ lisp_addr_t *gw; int table_id; int requested_ip_afi; /* our client index */ uint32_t my_client_index; /* Main thread can spin (w/ timeout) here if needed */ uint32_t async_mode; uint32_t async_errors; volatile uint32_t result_ready; volatile int32_t retval; volatile uint32_t sw_if_index; /* Time is of the essence... */ clib_time_t clib_time; } vpp_api_main_t; //typedef struct //{ // u8 ip[16]; // u8 prefix_length; //} ip_address_details_t; typedef struct { uint32_t iface_index; char *iface_name; uint8_t status; uint8_t l2_address[8]; } vpp_api_iface_t; #define MSG(T,t) \ do { \ vam->result_ready = 0; \ mp = vl_msg_api_alloc_as_if_client(sizeof(*mp)); \ memset (mp, 0, sizeof (*mp)); \ mp->_vl_msg_id = ntohs (VL_API_##T); \ mp->client_index = vam->my_client_index; \ } while(0); #define MSG_PLUS(T,t,n) \ do { \ vam->result_ready = 0; \ mp = vl_msg_api_alloc(sizeof(*mp)+(n)); \ memset (mp, 0, sizeof (*mp)); \ mp->_vl_msg_id = ntohs (VL_API_##T); \ mp->client_index = vam->my_client_index; \ } while(0); #define MSG_PLUGIN(T,t,n) \ do { \ vam->result_ready = 0; \ mp = vl_msg_api_alloc(sizeof(*mp)); \ memset (mp, 0, sizeof (*mp)); \ mp->_vl_msg_id = ntohs (VL_API_##T + n); \ mp->client_index = vam->my_client_index; \ } while(0); /* VPP_SEND: send a message */ #define VPP_SEND (vl_msg_api_send_shmem (vam->vl_input_queue, (u8 *)&mp)) extern vpp_api_main_t vpp_api_main; extern vlib_main_t vlib_global_main; extern vlib_main_t **vlib_mains; /* vpp_wait: wait for results, with timeout */ int vpp_wait(vpp_api_main_t * vam); clib_error_t *pkt_miss_plugin_register (vpp_api_main_t * vam); clib_error_t *ctrl_plugin_register (vpp_api_main_t * vam); int vpp_create_ap_iface(char *iface_name, uint8_t *mac); int vpp_set_interface_unnumbered (uint32_t iface_index, int action); int vpp_lisp_gpe_enable_disable(uint8_t enable_lisp_gpe); int vpp_lisp_gpe_add_del_iface(uint32_t table, uint32_t vni, uint8_t action); int vpp_lisp_eid_table_add_del_map (uint32_t table, uint32_t vni, uint8_t action); int vpp_set_interface_status (uint32_t iface_indx, uint8_t status); int vpp_oor_pkt_miss_enable_disable(char *iface_name, uint8_t enable_disable); int vpp_oor_ctrl_enable_disable (char *iface_name, uint8_t enable_disable); int vpp_oor_pkt_miss_native_route (lisp_addr_t *prefix, uint8_t is_add); int vpp_oor_pkt_miss_drop_route (lisp_addr_t *prefix, uint8_t is_add, uint32_t table_id); lisp_addr_t *vpp_oor_pkt_miss_get_default_route (int afi); int vpp_lisp_gpe_add_del_fwd_entry (fwd_entry_vpp_t *fe, lisp_action_e action, uint8_t is_add); int vpp_interface_get_table(uint32_t iface_index, uint8_t is_ipv6); glist_t * vpp_ip_fib_prefixs(int afi); static inline vpp_api_main_t * vpp_api_main_get() { return (&vpp_api_main); } void vat_api_hookup (vpp_api_main_t * vam); #endif /* OOR_LIB_VPP_API_VPP_API_REQUESTS_H_ */ oor-1.2.0/oor/liblisp/000077500000000000000000000000001313612200500145375ustar00rootroot00000000000000oor-1.2.0/oor/liblisp/liblisp.c000066400000000000000000000474251313612200500163550ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "liblisp.h" #include "../lib/cksum.h" #include "../lib/hmac.h" #include "../lib/oor_log.h" #include "../lib/packets.h" static void increment_record_count(lbuf_t *b); lisp_msg_type_e lisp_msg_type(lbuf_t *b) { ecm_hdr_t *hdr = lbuf_lisp(b); if (!hdr) { return(NOT_LISP_MSG); } return(hdr->type); } static void * lisp_msg_pull_ecm_hdr(lbuf_t *b) { lbuf_reset_lisp_hdr(b); return(lbuf_pull(b, sizeof(ecm_hdr_t))); } /* Process encapsulated map request header: lisp header and the interal IP and * UDP header */ int lisp_msg_ecm_decap(lbuf_t *pkt, uint16_t *src_port) { uint16_t ipsum = 0; uint16_t udpsum = 0; int udp_len = 0; struct udphdr *udph; struct ip *iph; /* this is the new start of the packet */ lisp_msg_pull_ecm_hdr(pkt); /* Set and extract inner layer 3 packet */ lbuf_reset_l3(pkt); iph = pkt_pull_ip(pkt); /* Set and extract inner layer 4 packet */ lbuf_reset_l4(pkt); udph = pkt_pull_udp(pkt); /* Set the beginning of the LISP msg*/ lbuf_reset_lisp(pkt); /* This should overwrite the external port (dst_port in map-reply = * inner src_port in encap map-request) */ *src_port = ntohs(udpsport(udph)); udp_len = ntohs(udplen(udph)); /* Verify the checksums. */ if (iph->ip_v == IPVERSION) { ipsum = ip_checksum((uint16_t *) iph, sizeof(struct ip)); if (ipsum != 0) { OOR_LOG(LDBG_2, "IP checksum failed."); } } /* Verify UDP checksum only if different from 0. * This means we ACCEPT UDP checksum 0! */ if (udpsum(udph) != 0) { udpsum = udp_checksum(udph, udp_len, iph, ip_version_to_sock_afi(iph->ip_v)); if (udpsum != 0) { OOR_LOG(LDBG_2, "UDP checksum failed."); return (BAD); } } OOR_LOG(LDBG_2, "%s, inner IP: %s -> %s, inner UDP: %d -> %d", lisp_msg_hdr_to_char(pkt), ip_to_char(&iph->ip_src, ip_version_to_sock_afi(iph->ip_v)), ip_to_char(&iph->ip_dst, ip_version_to_sock_afi(iph->ip_v)), ntohs(udpsport(udph)), ntohs(udpdport(udph))); return (GOOD); } int lisp_msg_parse_addr(lbuf_t *msg, lisp_addr_t *eid) { int len = lisp_addr_parse(lbuf_data(msg), eid); if (len < 0) { return(BAD); } lbuf_pull(msg, len); return(GOOD); } /* Given a message buffer 'msg', extracts the EID out of an EID prefix field * and stores it in 'eid'. */ int lisp_msg_parse_eid_rec(lbuf_t *msg, lisp_addr_t *eid) { eid_record_hdr_t *hdr = lbuf_data(msg); int len = lisp_addr_parse(EID_REC_ADDR(hdr), eid); lbuf_pull(msg, len); lisp_addr_set_plen(eid, EID_REC_MLEN(hdr)); return(GOOD); } int lisp_msg_parse_itr_rlocs(lbuf_t *b, glist_t *rlocs) { lisp_addr_t *tloc; void *mreq_hdr = lbuf_lisp(b); int i; tloc = lisp_addr_new(); for (i = 0; i < MREQ_ITR_RLOC_COUNT(mreq_hdr) + 1; i++) { if (lisp_msg_parse_addr(b, tloc) != GOOD) { return(BAD); } glist_add(lisp_addr_clone(tloc), rlocs); OOR_LOG(LDBG_1," itr-rloc: %s", lisp_addr_to_char(tloc)); } lisp_addr_del(tloc); return(GOOD); } int lisp_msg_parse_loc(lbuf_t *b, locator_t *loc) { int len; void *hdr; hdr = lbuf_data(b); len = locator_parse(lbuf_data(b), loc); if (len <= 0) { return(BAD); } lbuf_pull(b, len); OOR_LOG(LDBG_1, " %s, addr: %s", locator_record_hdr_to_char(hdr), lisp_addr_to_char(locator_addr(loc))); return(GOOD); } int lisp_msg_parse_mapping_record_split(lbuf_t *b, lisp_addr_t *eid, glist_t *loc_list, locator_t **probed_) { void *mrec_hdr = NULL, *loc_hdr = NULL; locator_t *loc = NULL, *probed = NULL; int i = 0, len = 0; probed = NULL; mrec_hdr = lbuf_data(b); lbuf_pull(b, sizeof(mapping_record_hdr_t)); len = lisp_addr_parse(lbuf_data(b), eid); if (len <= 0) { return(BAD); } lbuf_pull(b, len); lisp_addr_set_plen(eid, MAP_REC_EID_PLEN(mrec_hdr)); OOR_LOG(LDBG_1, " %s eid: %s", mapping_record_hdr_to_char(mrec_hdr), lisp_addr_to_char(eid)); for (i = 0; i < MAP_REC_LOC_COUNT(mrec_hdr); i++) { loc_hdr = lbuf_data(b); loc = locator_new(); if (lisp_msg_parse_loc(b, loc) != GOOD) { return(BAD); } glist_add(loc, loc_list); if (LOC_PROBED(loc_hdr)) { if (probed != NULL) { OOR_LOG(LDBG_1, "Multiple probed locators! Probing only the first one: %s", lisp_addr_to_char(locator_addr(loc))); }else{ probed = loc; } } } if (probed_ != NULL) { *probed_ = probed; } return(GOOD); } /* extracts a mapping record out of lbuf 'b' and stores it into 'm'. 'm' must * be preallocated. If a locator is probed, a pointer to it is stored in * 'probed'. */ int lisp_msg_parse_mapping_record(lbuf_t *b, mapping_t *m, locator_t **probed) { glist_t *loc_list; glist_entry_t *lit; locator_t *loc; int ret; void *hdr; if (!m) { return(BAD); } hdr = lbuf_data(b); mapping_set_ttl(m, ntohl(MAP_REC_TTL(hdr))); mapping_set_action(m, MAP_REC_ACTION(hdr)); mapping_set_auth(m, MAP_REC_AUTH(hdr)); /* no free is called when destroyed*/ loc_list = glist_new(); ret = lisp_msg_parse_mapping_record_split(b, mapping_eid(m), loc_list, probed); if (ret != GOOD) { goto err; } glist_for_each_entry(lit, loc_list) { loc = glist_entry_data(lit); if ((ret = mapping_add_locator(m, loc)) != GOOD) { locator_del(loc); if (ret != ERR_EXIST){ goto err; } } } glist_destroy(loc_list); return(GOOD); err: glist_destroy(loc_list); return(BAD); } static unsigned int msg_type_to_hdr_len(lisp_msg_type_e type) { switch(type) { case LISP_MAP_REQUEST: return(sizeof(map_request_hdr_t)); case LISP_MAP_REPLY: return(sizeof(map_reply_hdr_t)); case LISP_MAP_REGISTER: return(sizeof(map_register_hdr_t)); case LISP_MAP_NOTIFY: return(sizeof(map_notify_hdr_t)); case LISP_INFO_NAT: return(sizeof(info_nat_hdr_t)); default: return(0); } } void * lisp_msg_pull_hdr(lbuf_t *b) { lisp_msg_type_e type = lisp_msg_type(b); return(lbuf_pull(b, msg_type_to_hdr_len(type))); } void * lisp_msg_pull_auth_field(lbuf_t *b) { void *hdr; lisp_key_type_e keyid; hdr = lbuf_pull(b, sizeof(auth_record_hdr_t)); keyid = ntohs(AUTH_REC_KEY_ID(hdr)); lbuf_pull(b, auth_data_get_len_for_type(keyid)); return(hdr); } void * lisp_msg_put_addr(lbuf_t *b, lisp_addr_t *addr) { void *ptr; int len; /* make sure there's enough space */ ptr = lbuf_put_uninit(b, lisp_addr_size_to_write(addr)); if ((len = lisp_addr_write(ptr, addr)) <= 0) { OOR_LOG(LDBG_3, "lisp_msg_put_addr: failed to write address %s", lisp_addr_to_char(addr)); return(NULL); } return(ptr); } void * lisp_msg_put_locator(lbuf_t *b, locator_t *locator) { locator_hdr_t *loc_ptr; loc_ptr = lbuf_put_uninit(b, sizeof(locator_hdr_t)); loc_ptr->priority = locator->priority; loc_ptr->weight = locator->weight; loc_ptr->mpriority = locator->mpriority; loc_ptr->mweight = locator->mweight; loc_ptr->local = locator->L_bit; loc_ptr->reachable = locator->R_bit; lisp_msg_put_addr(b, locator_addr(locator)); return(loc_ptr); } static void increment_record_count(lbuf_t *b) { void *hdr = lbuf_lisp(b); switch(lisp_msg_type(b)) { case LISP_MAP_REQUEST: MREQ_REC_COUNT(hdr) += 1; break; case LISP_MAP_REPLY: MREP_REC_COUNT(hdr) += 1; break; case LISP_MAP_REGISTER: MREG_REC_COUNT(hdr) += 1; break; case LISP_MAP_NOTIFY: MNTF_REC_COUNT(hdr) += 1; break; default: return; } } void * lisp_msg_put_mapping_hdr(lbuf_t *b) { void *hdr = lbuf_put_uninit(b, sizeof(mapping_record_hdr_t)); mapping_record_init_hdr(hdr); return(hdr); } void * lisp_msg_put_mapping( lbuf_t *b, mapping_t *m, lisp_addr_t *probed_loc) { mapping_record_hdr_t *rec = NULL; locator_hdr_t *ploc = NULL; lisp_addr_t *eid = NULL; locator_t *loct = NULL; int locator_count = 0; eid = mapping_eid(m); rec = lisp_msg_put_mapping_hdr(b); MAP_REC_EID_PLEN(rec) = lisp_addr_get_plen(eid); MAP_REC_TTL(rec) = htonl(m->ttl); MAP_REC_AUTH(rec) = m->authoritative; if (lisp_msg_put_addr(b, eid) == NULL) { return(NULL); } /* Add locators */ mapping_foreach_active_locator(m,loct){ if (locator_state(loct) == DOWN){ continue; } ploc = lisp_msg_put_locator(b, loct); if (probed_loc) if (probed_loc != NULL && lisp_addr_cmp(lisp_addr_get_ip_addr(locator_addr(loct)), probed_loc) == 0) { LOC_PROBED(ploc) = 1; } locator_count++; }mapping_foreach_active_locator_end; MAP_REC_LOC_COUNT(rec) = locator_count; increment_record_count(b); return(rec); } void * lisp_msg_put_neg_mapping(lbuf_t *b, lisp_addr_t *eid, int ttl, lisp_action_e act, lisp_authoritative_e a) { void *rec; rec = lisp_msg_put_mapping_hdr(b); MAP_REC_EID_PLEN(rec) = lisp_addr_get_plen(eid); MAP_REC_LOC_COUNT(rec) = 0; MAP_REC_TTL(rec) = htonl(ttl); MAP_REC_ACTION(rec) = act; MAP_REC_AUTH(rec) = a; if (lisp_msg_put_addr(b, eid) == NULL) { return(NULL); } increment_record_count(b); return(rec); } void * lisp_msg_put_itr_rlocs(lbuf_t *b, glist_t *itr_rlocs) { glist_entry_t *it; lisp_addr_t *rloc; void *hdr, *data; data = lbuf_data(b); if(glist_size(itr_rlocs) == 0){ return (NULL); } glist_for_each_entry(it, itr_rlocs) { rloc = glist_entry_data(it); if (lisp_msg_put_addr(b, rloc) == NULL) { return(NULL); } } hdr = lisp_msg_hdr(b); MREQ_ITR_RLOC_COUNT(hdr) = glist_size(itr_rlocs)-1; return(data); } void * lisp_msg_put_eid_rec(lbuf_t *b, lisp_addr_t *eid) { eid_record_hdr_t *hdr; hdr = lbuf_put_uninit(b, sizeof(eid_record_hdr_t)); eid_rec_hdr_init(hdr); EID_REC_MLEN(hdr) = lisp_addr_get_plen(eid); lisp_msg_put_addr(b, eid); increment_record_count(b); return(hdr); } void * lisp_msg_encap(lbuf_t *b, int lp, int rp, lisp_addr_t *la, lisp_addr_t *ra) { void *hdr; /* end of lisp msg */ lbuf_reset_lisp(b); lisp_addr_t *ip_la, *ip_ra; ip_la = lisp_addr_get_ip_addr(la); if (!ip_la){ ip_la = lisp_addr_get_ip_pref_addr(la); } ip_ra = lisp_addr_get_ip_addr(ra); if (!ip_ra){ ip_ra = lisp_addr_get_ip_pref_addr(ra); } /* push inner ip and udp */ pkt_push_udp_and_ip(b, lp, rp,lisp_addr_ip(ip_la),lisp_addr_ip(ip_ra)); /* push lisp ecm hdr */ hdr = lbuf_push_uninit(b, sizeof(ecm_hdr_t)); ecm_hdr_init(hdr); lbuf_reset_lisp_hdr(b); OOR_LOG(LDBG_1, "%s, inner IP: %s -> %s, inner UDP: %d -> %d", lisp_msg_ecm_hdr_to_char(b), lisp_addr_to_char(la), lisp_addr_to_char(ra), LISP_CONTROL_PORT, LISP_CONTROL_PORT); return(lbuf_data(b)); } lbuf_t * lisp_msg_create_buf() { lbuf_t* b; b = lbuf_new_with_headroom(MAX_IP_PKT_LEN, MAX_LISP_MSG_ENCAP_LEN); lbuf_reset_lisp(b); return(b); } lbuf_t* lisp_msg_create(lisp_msg_type_e type) { lbuf_t* b; void *hdr; b = lisp_msg_create_buf(); switch(type) { case LISP_MAP_REQUEST: hdr = lbuf_put_uninit(b, sizeof(map_request_hdr_t)); map_request_hdr_init(hdr); break; case LISP_MAP_REPLY: hdr = lbuf_put_uninit(b, sizeof(map_reply_hdr_t)); map_reply_hdr_init(hdr); break; case LISP_MAP_REGISTER: hdr = lbuf_put_uninit(b, sizeof(map_register_hdr_t)); map_register_hdr_init(hdr); break; case LISP_MAP_NOTIFY: hdr = lbuf_put_uninit(b, sizeof(map_notify_hdr_t)); map_notify_hdr_init(hdr); break; case LISP_INFO_NAT: hdr = lbuf_put_uninit(b, sizeof(info_nat_hdr_t)); info_nat_hdr_init(hdr); break; case LISP_ENCAP_CONTROL_TYPE: /* nothing to do */ break; default: OOR_LOG(LDBG_3, "lisp_msg_create: Unknown LISP message " "type %s", type); } return(b); } lbuf_t * lisp_msg_mreq_create(lisp_addr_t *seid, glist_t *itr_rlocs, lisp_addr_t *deid) { lbuf_t *b = lisp_msg_create(LISP_MAP_REQUEST); if (lisp_msg_put_addr(b, seid) == NULL) { lbuf_del(b); return(NULL); } if (lisp_msg_put_itr_rlocs(b, itr_rlocs) == NULL) { lbuf_del(b); return(NULL); } if (lisp_msg_put_eid_rec(b, deid) == NULL) { lbuf_del(b); return(NULL); } return(b); } lbuf_t * lisp_msg_neg_mrep_create(lisp_addr_t *eid, int ttl, lisp_action_e ac, lisp_authoritative_e a, uint64_t nonce) { lbuf_t *b; void *hdr; b = lisp_msg_create(LISP_MAP_REPLY); lisp_msg_put_neg_mapping(b, eid, ttl, ac, a); hdr = lisp_msg_hdr(b); MREP_NONCE(hdr) = nonce; return(b); } lbuf_t * lisp_msg_inf_req_create(mapping_t *m, lisp_key_type_e keyid) { lbuf_t *b = lisp_msg_create(LISP_INFO_NAT); lisp_addr_t addr; if (!lisp_msg_put_empty_auth_record(b, keyid)) { return(NULL); } if (!lisp_msg_put_inf_req_hdr_2(b, mapping_eid(m), 0)) { return(NULL); } lisp_addr_set_lafi(&addr, LM_AFI_NO_ADDR); if (lisp_msg_put_addr(b, &addr) == NULL) { return(NULL); } return(b); } lbuf_t * lisp_msg_mreg_create(mapping_t *m, lisp_key_type_e keyid) { lbuf_t *b = lisp_msg_create(LISP_MAP_REGISTER); if (!lisp_msg_put_empty_auth_record(b, keyid)) { return(NULL); } if (!lisp_msg_put_mapping(b, m, NULL)) { return(NULL); } return(b); } lbuf_t * lisp_msg_nat_mreg_create(mapping_t *m,lisp_site_id site_id, lisp_xtr_id *xtr_id, lisp_key_type_e keyid) { lbuf_t *b = lisp_msg_create(LISP_MAP_REGISTER); if (!lisp_msg_put_empty_auth_record(b, keyid)){ return(NULL); } if (!lisp_msg_put_mapping(b, m, NULL)) { return(NULL); } lbuf_put(b, xtr_id, sizeof(lisp_xtr_id)); lbuf_put(b, &site_id, sizeof(lisp_site_id)); return(b); } char * lisp_msg_hdr_to_char(lbuf_t *b) { void *h = lbuf_lisp(b); if (!h) { return(NULL); } switch(lisp_msg_type(b)) { case LISP_MAP_REQUEST: return(map_request_hdr_to_char(h)); case LISP_MAP_REPLY: return(map_reply_hdr_to_char(h)); case LISP_MAP_REGISTER: return(map_register_hdr_to_char(h)); case LISP_MAP_NOTIFY: return(map_notify_hdr_to_char(h)); case LISP_INFO_NAT: return(info_nat_hdr_to_char(h)); case LISP_ENCAP_CONTROL_TYPE: return(ecm_hdr_to_char(h)); default: OOR_LOG(LDBG_3, "Unknown LISP message type %d", lisp_msg_type(b)); return(NULL); } } char * lisp_msg_ecm_hdr_to_char(lbuf_t *b) { void *h = lbuf_lisp_hdr(b); if (!h) { return(NULL); } return(ecm_hdr_to_char(h)); } int lisp_msg_fill_auth_data(lbuf_t *b, lisp_key_type_e keyid, const char *key) { void *hdr = lisp_msg_auth_record(b); if (complete_auth_fields( keyid, key, lbuf_lisp(b), lbuf_size(b), AUTH_REC_DATA(hdr)) != GOOD) { return(BAD); } return(GOOD); } /* Checks auth field of Map-Register, Map-Notify and Info-Reply messages */ int lisp_msg_check_auth_field(lbuf_t *b, const char *key) { lisp_key_type_e keyid; uint16_t ad_len = 0; int ret = BAD; auth_record_hdr_t *hdr; hdr = lisp_msg_auth_record(b); keyid = ntohs(AUTH_REC_KEY_ID(hdr)); ad_len = auth_data_get_len_for_type(keyid); if (ad_len != ntohs(AUTH_REC_DATA_LEN(hdr))) { OOR_LOG(LDBG_3, "Auth Record record length is wrong: %d instead of %d", ntohs(AUTH_REC_DATA_LEN(hdr)), ad_len); return(BAD); } ret = check_auth_field( keyid, key, lbuf_lisp(b), lbuf_size(b), AUTH_REC_DATA(hdr)); return(ret); } void * lisp_msg_put_empty_auth_record(lbuf_t *b, lisp_key_type_e keyid) { void *hdr; uint16_t len = auth_data_get_len_for_type(keyid); hdr = lbuf_put_uninit(b, sizeof(auth_record_hdr_t) + len); AUTH_REC_KEY_ID(hdr) = htons(keyid); AUTH_REC_DATA_LEN(hdr) = htons(len); memset(AUTH_REC_DATA(hdr), 0, len); return(hdr); } void * lisp_msg_put_inf_req_hdr_2(lbuf_t *b, lisp_addr_t *eid_pref, uint8_t ttl) { void *hdr; lisp_addr_t *eid; hdr = lbuf_put_uninit(b, sizeof(info_nat_hdr_2_t)); INF_REQ_2_TTL(hdr) = ttl; eid = lisp_addr_get_ip_pref_addr(eid_pref); INF_REQ_2_EID_MASK(hdr) = lisp_addr_ip_get_plen(eid); if (lisp_msg_put_addr(b, eid) == NULL) { return(NULL); } return(hdr); } void * lisp_data_push_hdr(lbuf_t *b, uint32_t iid) { lisp_data_hdr_t *lhdr; lhdr = lbuf_push_uninit(b, sizeof(lisp_data_hdr_t)); lisp_data_hdr_init(lhdr, iid); return(lhdr); } void * lisp_data_encap(lbuf_t *b, int lp, int rp, lisp_addr_t *la, lisp_addr_t *ra, uint32_t iid) { int ttl = 0, tos = 0; /* read ttl and tos */ ip_hdr_ttl_and_tos(lbuf_data(b), &ttl, &tos); /* push lisp data hdr */ lisp_data_push_hdr(b, iid); /* push outer UDP and IP */ pkt_push_udp_and_ip(b, lp, rp, lisp_addr_ip(la), lisp_addr_ip(ra)); ip_hdr_set_ttl_and_tos(lbuf_data(b), ttl, tos); return(lbuf_data(b)); } void * lisp_data_pull_hdr(lbuf_t *b) { void *dt = lbuf_pull(b, sizeof(lisp_data_hdr_t)); return(dt); } /* returns in 'addr_' the first element of the list 'l' to have AFI 'afi' * caller must allocate and free 'addr_' */ int laddr_list_get_addr(glist_t *l, int afi, lisp_addr_t *addr) { glist_entry_t *it; lisp_addr_t *ait; int found = 0; if (!addr) { return(BAD); } glist_for_each_entry(it, l) { ait = (lisp_addr_t *)glist_entry_data(it); if (lisp_addr_ip_afi(ait) == afi) { lisp_addr_copy(addr, ait); found = 1; break; } } if (found) { return(GOOD); } else { return(BAD); } } char * laddr_list_to_char(glist_t *l) { static char buf[50*INET6_ADDRSTRLEN]; /* 50 addresses */ size_t buf_size = sizeof(buf); int i = 1, n; glist_entry_t *it; n = glist_size(l); *buf = '\0'; glist_for_each_entry(it, l) { if (i < n) { snprintf(buf + strlen(buf),buf_size-strlen(buf), "%s, ", lisp_addr_to_char(glist_entry_data(it))); } else { snprintf(buf + strlen(buf),buf_size-strlen(buf), "%s", lisp_addr_to_char(glist_entry_data(it))); } i++; } return(buf); } oor-1.2.0/oor/liblisp/liblisp.h000066400000000000000000000112671313612200500163550ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef LIBLISP_H_ #define LIBLISP_H_ #include "lisp_address.h" #include "lisp_locator.h" #include "lisp_mapping.h" #include "lisp_messages.h" #include "lisp_data.h" #include "../lib/generic_list.h" #include "../lib/lbuf.h" #define LISP_DATA_HDR_LEN 8 #define LISP_ECM_HDR_LEN 4 #define MAX_LISP_MSG_ENCAP_LEN 2*(MAX_IP_HDR_LEN + UDP_HDR_LEN)+ LISP_ECM_HDR_LEN #define MAX_LISP_PKT_ENCAP_LEN MAX_IP_HDR_LEN + UDP_HDR_LEN + LISP_DATA_HDR_LEN #define LISP_CONTROL_PORT 4342 #define LISP_DATA_PORT 4341 lisp_msg_type_e lisp_msg_type(lbuf_t *); int lisp_msg_parse_addr(lbuf_t *, lisp_addr_t *); int lisp_msg_parse_eid_rec(lbuf_t *, lisp_addr_t *); int lisp_msg_parse_itr_rlocs(lbuf_t *, glist_t *); int lisp_msg_parse_loc(lbuf_t *, locator_t *); int lisp_msg_parse_mapping_record_split(lbuf_t *, lisp_addr_t *, glist_t *, locator_t **); int lisp_msg_parse_mapping_record(lbuf_t *, mapping_t *, locator_t **); int lisp_msg_ecm_decap(struct lbuf *, uint16_t *); void *lisp_msg_put_addr(lbuf_t *, lisp_addr_t *); void *lisp_msg_put_locator(lbuf_t *, locator_t *); void *lisp_msg_put_mapping_hdr(lbuf_t *) ; void *lisp_msg_put_mapping(lbuf_t *, mapping_t *, lisp_addr_t *); void *lisp_msg_put_neg_mapping(lbuf_t *, lisp_addr_t *, int, lisp_action_e, lisp_authoritative_e a); void *lisp_msg_put_itr_rlocs(lbuf_t *, glist_t *); void *lisp_msg_put_eid_rec(lbuf_t *, lisp_addr_t *); void *lisp_msg_encap(lbuf_t *, int, int, lisp_addr_t *, lisp_addr_t *); lbuf_t *lisp_msg_create_buf(); lbuf_t* lisp_msg_create(); static inline void lisp_msg_destroy(lbuf_t *); static inline void *lisp_msg_hdr(lbuf_t *b); lbuf_t *lisp_msg_mreq_create(lisp_addr_t *, glist_t *, lisp_addr_t *); lbuf_t *lisp_msg_neg_mrep_create(lisp_addr_t *, int, lisp_action_e, lisp_authoritative_e, uint64_t); lbuf_t *lisp_msg_inf_req_create(mapping_t *m, lisp_key_type_e keyid); lbuf_t *lisp_msg_mreg_create(mapping_t *, lisp_key_type_e); lbuf_t *lisp_msg_nat_mreg_create(mapping_t *, lisp_site_id , lisp_xtr_id *, lisp_key_type_e ); char *lisp_msg_hdr_to_char(lbuf_t *b); char *lisp_msg_ecm_hdr_to_char(lbuf_t *b); int lisp_msg_fill_auth_data(lbuf_t *, lisp_key_type_e , const char *); int lisp_msg_check_auth_field(lbuf_t *, const char *); void *lisp_msg_put_empty_auth_record(lbuf_t *, lisp_key_type_e); void *lisp_msg_put_inf_req_hdr_2(lbuf_t *b, lisp_addr_t *eid_pref, uint8_t ttl); static inline void *lisp_msg_auth_record(lbuf_t *); void *lisp_msg_pull_hdr(lbuf_t *b); void *lisp_msg_pull_auth_field(lbuf_t *b); void *lisp_data_push_hdr(lbuf_t *b, uint32_t iid); void *lisp_data_pull_hdr(lbuf_t *b); void *lisp_data_encap(lbuf_t *, int, int, lisp_addr_t *, lisp_addr_t *, uint32_t); static inline glist_t *laddr_list_new(); static inline void laddr_list_init(glist_t *); static inline glist_t *laddr_sorted_list_new(); static inline void laddr_list_del(glist_t *); int laddr_list_get_addr(glist_t *, int, lisp_addr_t *); char *laddr_list_to_char(glist_t *l); static inline void lisp_msg_destroy(lbuf_t *b) { if (b) { lbuf_del(b); } } static inline void * lisp_msg_hdr(lbuf_t *b) { return(lbuf_lisp(b)); } static inline void * lisp_msg_ecm_hdr(lbuf_t *b) { return(lbuf_lisp_hdr(b)); } /* get pointer of auth field in a message */ static inline void * lisp_msg_auth_record(lbuf_t *b) { /* assumption here is that auth field in all messages is at * sizeof(map_notify_hdr_t) from the beginning of the lisp * message */ return((uint8_t *)lbuf_lisp(b) + sizeof(map_notify_hdr_t)); } static inline glist_t * laddr_list_new() { return(glist_new_managed((glist_del_fct)lisp_addr_del)); } static inline void laddr_list_del(glist_t *lst) { glist_destroy(lst); } static inline void laddr_list_init(glist_t *lst) { glist_init_managed(lst, (glist_del_fct)lisp_addr_del); } static inline glist_t * laddr_sorted_list_new() { return(glist_new_complete((glist_cmp_fct)lisp_addr_cmp, (glist_del_fct)lisp_addr_del)); } #endif /* LIBLISP_H_ */ oor-1.2.0/oor/liblisp/lisp_address.c000066400000000000000000000462231313612200500173660ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "lisp_address.h" #include "../lib/mem_util.h" #include "../lib/oor_log.h" static inline lm_afi_t get_lafi_(lisp_addr_t *laddr); static inline void set_lafi_(lisp_addr_t *laddr, lm_afi_t lafi); static inline lisp_addr_t *new_no_addr_(); static inline lisp_addr_t *new_ip_(); static inline lisp_addr_t *new_ippref_(); static inline lisp_addr_t *new_lcaf_(); static inline lisp_addr_t *new_lafi_(lm_afi_t afi); static inline ip_addr_t *get_ip_(lisp_addr_t *addr); static inline ip_prefix_t *get_ippref_(lisp_addr_t *addr); static inline lcaf_addr_t *get_lcaf_(lisp_addr_t *addr); static inline lm_afi_t get_lafi_(lisp_addr_t *laddr) { return (laddr->lafi); } static inline void set_lafi_(lisp_addr_t *laddr, lm_afi_t lafi) { laddr->lafi = lafi; } static inline lisp_addr_t * new_no_addr_() { lisp_addr_t *laddr = lisp_addr_new(); set_lafi_(laddr, LM_AFI_NO_ADDR); return (laddr); } static inline lisp_addr_t * new_ip_() { lisp_addr_t *laddr = lisp_addr_new(); set_lafi_(laddr, LM_AFI_IP); ip_addr_set_afi(get_ip_(laddr), AF_UNSPEC); return (laddr); } static inline lisp_addr_t * new_ippref_() { lisp_addr_t *laddr = lisp_addr_new(); set_lafi_(laddr, LM_AFI_IPPREF); return (laddr); } static inline lisp_addr_t * new_lcaf_() { lisp_addr_t *laddr; laddr = lisp_addr_new(); set_lafi_(laddr, LM_AFI_LCAF); return (laddr); } static inline lisp_addr_t * new_lafi_(lm_afi_t afi) { switch (afi) { case LM_AFI_NO_ADDR: return (new_no_addr_()); case LM_AFI_IP: return (new_ip_()); case LM_AFI_IPPREF: return (new_ippref_()); case LM_AFI_LCAF: return (new_lcaf_()); default: OOR_LOG(LWRN, "lisp_addr_new_afi: unknown lisp addr afi %d", afi); break; } return (NULL); } static inline ip_addr_t * get_ip_(lisp_addr_t *addr) { return (&addr->ip); } static inline ip_prefix_t * get_ippref_(lisp_addr_t *addr) { return (&addr->ippref); } static inline lcaf_addr_t * get_lcaf_(lisp_addr_t *addr) { return (&addr->lcaf); } inline lisp_addr_t * lisp_addr_new_lafi(uint8_t lafi) { return (new_lafi_(lafi)); } inline lisp_addr_t * lisp_addr_new() { return (xzalloc(sizeof(lisp_addr_t))); } inline void lisp_addr_del(lisp_addr_t *laddr) { if (!laddr) { return; } switch (lisp_addr_lafi(laddr)) { case LM_AFI_IP: case LM_AFI_IPPREF: case LM_AFI_NO_ADDR: free(laddr); break; case LM_AFI_LCAF: lcaf_addr_del_addr(get_lcaf_(laddr)); free(laddr); break; default: OOR_LOG(LWRN, "lisp_addr_delete: unknown lisp addr afi %d", lisp_addr_lafi(laddr)); return; } laddr = NULL; } inline uint16_t lisp_addr_get_iana_afi(lisp_addr_t *laddr) { switch (lisp_addr_lafi(laddr)) { case LM_AFI_IP: return (ip_addr_get_iana_afi(get_ip_(laddr))); break; case LM_AFI_IPPREF: return (ip_addr_get_iana_afi(ip_prefix_addr(get_ippref_(laddr)))); break; case LM_AFI_LCAF: return (LISP_AFI_LCAF); case LM_AFI_NO_ADDR: return (LISP_AFI_NO_ADDR); default: OOR_LOG(LDBG_2, "lisp_addr_get_iana_afi: unknown AFI (%d)", lisp_addr_lafi(laddr)); return (BAD); } } inline uint32_t lisp_addr_size_to_write(lisp_addr_t *laddr) { switch (lisp_addr_lafi(laddr)) { case LM_AFI_NO_ADDR: return (sizeof(uint16_t)); case LM_AFI_IP: return (ip_addr_get_size_to_write(get_ip_(laddr))); break; case LM_AFI_IPPREF: return (ip_addr_get_size_to_write( ip_prefix_addr(get_ippref_(laddr)))); break; case LM_AFI_LCAF: return (lcaf_addr_get_size_to_write(get_lcaf_(laddr))); default: OOR_LOG(LDBG_3, "lisp_addr_get_size_in_pkt: not defined for afi %d", lisp_addr_lafi(laddr)); break; } return (0); } inline uint16_t lisp_addr_get_plen(lisp_addr_t *laddr) { lisp_addr_t *pref_addr; switch (lisp_addr_lafi(laddr)) { case LM_AFI_IP: return (ip_addr_afi_to_default_mask(get_ip_(laddr))); case LM_AFI_IPPREF: return (ip_prefix_get_plen(get_ippref_(laddr))); case LM_AFI_LCAF: pref_addr = lisp_addr_get_ip_pref_addr(laddr); if (pref_addr){ return (ip_prefix_get_plen(get_ippref_(pref_addr))); } break; default: break; } return (0); } char * lisp_addr_to_char(lisp_addr_t *addr) { if (!addr) { return("_NULL_"); } switch (lisp_addr_lafi(addr)) { case LM_AFI_IP: return (ip_addr_to_char(get_ip_(addr))); case LM_AFI_IPPREF: return (ip_prefix_to_char(get_ippref_(addr))); break; case LM_AFI_LCAF: return (lcaf_addr_to_char(get_lcaf_(addr))); break; case LM_AFI_NO_ADDR: return ("_NO_ADDR_"); default: OOR_LOG(LDBG_3, "lisp_addr_to_char: Trying to convert" " to string unknown LISP AFI %d", lisp_addr_lafi(addr)); break; } return (NULL); } inline void lisp_addr_set_lafi(lisp_addr_t *addr, lm_afi_t afi) { set_lafi_(addr, afi); } inline void lisp_addr_ip_to_ippref(lisp_addr_t *laddr) { if (lisp_addr_lafi(laddr) != LM_AFI_IP && lisp_addr_lafi(laddr) != LM_AFI_IPPREF) { OOR_LOG(LDBG_3, "lisp_addr_ip_to_ippref: called, but addr has afi (%d)", lisp_addr_lafi(laddr)); return; } set_lafi_(laddr, LM_AFI_IPPREF); ip_prefix_set_plen(get_ippref_(laddr), ip_addr_afi_to_default_mask(lisp_addr_ip(laddr))); } inline uint16_t lisp_addr_ip_afi(lisp_addr_t *addr) { switch (get_lafi_(addr)) { case LM_AFI_IP: return (ip_addr_afi(get_ip_(addr))); case LM_AFI_IPPREF: return (ip_prefix_afi(get_ippref_(addr))); default: OOR_LOG(LDBG_1, "lisp_addr_ip_afi: not supported for afi %d", get_lafi_(addr)); return (0); } } void lisp_addr_set_ip_afi(lisp_addr_t *la, int afi) { switch (get_lafi_(la)) { case LM_AFI_IP: ip_addr_set_afi(get_ip_(la), afi); break; case LM_AFI_IPPREF: ip_prefix_set_afi(get_ippref_(la), afi); break; default: OOR_LOG(LWRN, "lisp_addr_ip_get_afi: not supported for afi %d", get_lafi_(la)); return; } } inline ip_addr_t * lisp_addr_ip_get_addr(lisp_addr_t *laddr) { if (get_lafi_(laddr) != LM_AFI_IP && get_lafi_(laddr) != LM_AFI_IPPREF) { OOR_LOG(LDBG_3, "lisp_addr_ip_get_addr: called, but addr has afi (%d)", get_lafi_(laddr)); return (NULL); } switch (get_lafi_(laddr)) { case LM_AFI_IP: return (get_ip_(laddr)); case LM_AFI_IPPREF: return (ip_prefix_addr(get_ippref_(laddr))); case LM_AFI_NO_ADDR: case LM_AFI_LCAF: OOR_LOG(LDBG_3, "lisp_addr_ip_get_addr: AFI (%s) not of IP type", get_lafi_(laddr)); break; default: OOR_LOG(LDBG_3, "lisp_addr_ip_get_addr: AFI (%s) not supported", get_lafi_(laddr)); } return (NULL); } inline uint8_t lisp_addr_ip_get_plen(lisp_addr_t *laddr) { switch (get_lafi_(laddr)) { case LM_AFI_IP: if (ip_addr_afi(get_ip_(laddr)) == AF_UNSPEC) { OOR_LOG(LWRN, "lisp_addr_ip_get_plen: called with AF_UNSPEC"); return (0); } return ((ip_addr_afi(get_ip_(laddr)) == AF_INET) ? 32 : 128); case LM_AFI_IPPREF: return (ip_prefix_get_plen(get_ippref_(laddr))); default: OOR_LOG(LDBG_3, "lisp_addr_ip_get_plen: called with AFI not IP or IPPREF"); } return (0); } inline void lisp_addr_ip_set_afi(lisp_addr_t *laddr, int afi) { switch (get_lafi_(laddr)) { case LM_AFI_IP: ip_addr_set_afi(get_ip_(laddr), afi); break; case LM_AFI_IPPREF: ip_prefix_set_afi(get_ippref_(laddr), afi); break; default: OOR_LOG(LDBG_3, "lisp_addr_ip_set_afi: called with LM AFI %d", get_lafi_(laddr)); break; } } inline void lisp_addr_set_plen(lisp_addr_t *laddr, uint8_t plen) { lisp_addr_t *laddr_pref; switch (get_lafi_(laddr)) { case LM_AFI_IP: set_lafi_(laddr, LM_AFI_IPPREF); ip_prefix_set_plen(get_ippref_(laddr), plen); break; case LM_AFI_IPPREF: ip_prefix_set_plen(get_ippref_(laddr), plen); break; case LM_AFI_LCAF: laddr_pref = lisp_addr_get_ip_pref_addr(laddr); if (!laddr_pref){ laddr_pref = lisp_addr_get_ip_addr(laddr); if (!laddr_pref){ OOR_LOG(LDBG_2, "lisp_addr_set_plen: lcaf address without prefix address"); return; } } lisp_addr_set_plen(laddr_pref,plen); break; default: OOR_LOG(LDBG_2, "lisp_addr_set_plen: not supported for afi %d", lisp_addr_lafi(laddr)); break; } } /** * lisp_addr_copy - copies src to dst. Still works if they have different internal * structures. Note that dst MUST be allocated prior to calling the function */ void lisp_addr_copy(lisp_addr_t *dst, lisp_addr_t *src) { set_lafi_(dst, lisp_addr_lafi(src)); switch (lisp_addr_lafi(src)) { case LM_AFI_NO_ADDR: OOR_LOG(LDBG_3, "lisp_addr_copy: No address element copied"); break; case LM_AFI_IP: ip_addr_copy(get_ip_(dst), get_ip_(src)); break; case LM_AFI_IPPREF: ip_prefix_copy(get_ippref_(dst), get_ippref_(src)); break; case LM_AFI_LCAF: lcaf_addr_copy(get_lcaf_(dst), get_lcaf_(src)); break; default: OOR_LOG(LDBG_2, "lisp_addr_copy: Unknown AFI type %d in EID", lisp_addr_lafi(dst)); break; } } lisp_addr_t * lisp_addr_clone(lisp_addr_t *src) { lisp_addr_t *dst; if (!src){ return (NULL); } dst = lisp_addr_new(); lisp_addr_copy(dst, src); return (dst); } inline uint32_t lisp_addr_copy_to(void *dst, lisp_addr_t *src) { switch (lisp_addr_lafi(src)) { case LM_AFI_IP: ip_addr_copy_to(dst, get_ip_(src)); return (ip_addr_get_size(get_ip_(src))); case LM_AFI_IPPREF: ip_addr_copy_to(dst, ip_prefix_addr(get_ippref_(src))); return (ip_addr_get_size(ip_prefix_addr(get_ippref_(src)))); case LM_AFI_LCAF: OOR_LOG(LDBG_3, "lisp_addr_copy_to: requeste for %s Not implemented for LCAF.", lisp_addr_to_char(src)); break; default: OOR_LOG(LDBG_3, "lisp_addr_copy_to: Unknown AFI type %d in EID", lisp_addr_lafi(src)); break; } return (0); } /** lisp_addr_write * * @offset: memory location * @laddr: the lisp address to be copied * Description: The function copies what is *CONTAINED* in a lisp address * to a certain memory location, NOT the whole structure! */ inline int lisp_addr_write(void *offset, lisp_addr_t *laddr) { switch (lisp_addr_lafi(laddr)) { case LM_AFI_IP: return (ip_addr_write_to_pkt(offset, get_ip_(laddr), 0)); case LM_AFI_IPPREF: return (ip_addr_write_to_pkt(offset, ip_prefix_addr(get_ippref_(laddr)), 0)); case LM_AFI_LCAF: return (lcaf_addr_write(offset, get_lcaf_(laddr))); case LM_AFI_NO_ADDR: memset(offset, 0, sizeof(uint16_t)); return (sizeof(uint16_t)); default: OOR_LOG(LDBG_3, "lisp_addr_write_to_pkt: Unknown afi %d", lisp_addr_lafi(laddr)); break; } return (0); } /* Parses a LISP address and returns number of bytes read */ int lisp_addr_parse(uint8_t *offset, lisp_addr_t *laddr) { lisp_afi_e afi; int len = 0; if (!laddr) { OOR_LOG(LDBG_3, "lisp_addr_parse: Called with unallocated address!"); return (0); } afi = ntohs(*((uint16_t *) offset)); switch (afi) { case LISP_AFI_IP: case LISP_AFI_IPV6: len = ip_addr_parse((void *) offset, afi, get_ip_(laddr)); set_lafi_(laddr, LM_AFI_IP); break; case LISP_AFI_LCAF: len = lcaf_addr_parse(offset, get_lcaf_(laddr)); set_lafi_(laddr, LM_AFI_LCAF); break; case LISP_AFI_NO_ADDR: len = sizeof(uint16_t); set_lafi_(laddr, LM_AFI_NO_ADDR); break; default: OOR_LOG(LDBG_2, "lisp_addr_read_from_pkt: Unknown AFI type %d in EID", afi); break; } return (len); } /* * Compare two lisp_addr_t. * Returns: * -1: If they are from different afi * 0: Both address are the same * 1: Addr1 is bigger than addr2 * 2: Addr2 is bigger than addr1 */ inline int lisp_addr_cmp(lisp_addr_t *addr1, lisp_addr_t *addr2) { int cmp; if (!addr1 || !addr2) { OOR_LOG(LDBG_3,"lisp_addr_cmp: One of the compared addresses is NULL"); return (-1); } if (lisp_addr_lafi(addr1) != lisp_addr_lafi(addr2)) { OOR_LOG(LDBG_3,"lisp_addr_cmp: Addresses with different lafi: %d - %d", lisp_addr_lafi(addr1),lisp_addr_lafi(addr2)); return (-1); } switch (lisp_addr_lafi(addr1)) { case LM_AFI_NO_ADDR: if (addr1 == addr2){ cmp = 0; }else{ cmp = 2; } break; case LM_AFI_IP: cmp = ip_addr_cmp(get_ip_(addr1), get_ip_(addr2)); break; case LM_AFI_IPPREF: cmp = ip_addr_cmp(ip_prefix_addr(get_ippref_(addr1)), ip_prefix_addr(get_ippref_(addr2))); break; case LM_AFI_LCAF: cmp = lcaf_addr_cmp(get_lcaf_(addr1), get_lcaf_(addr2)); break; default: cmp = -1; break; } return (cmp); } /* * Compare lafi and afit/type of two lisp_addr_t. * Returns: * 0: Both address has the same lafi and afi/type * 1: Addr1 is bigger than addr2 * 2: Addr2 is bigger than addr1 */ inline int lisp_addr_cmp_afi(lisp_addr_t *addr1, lisp_addr_t *addr2) { int lafi_a; int lafi_b; int afi_a; int afi_b; if (addr1 == NULL || addr2 == NULL){ return (-2); } lafi_a = lisp_addr_lafi(addr1); lafi_b = lisp_addr_lafi(addr2); if (lafi_a > lafi_b){ return (1); } if (lafi_a < lafi_b){ return (2); } switch(lafi_a){ case LM_AFI_NO_ADDR: return (0); case LM_AFI_IP: case LM_AFI_IPPREF: afi_a = lisp_addr_ip_afi(addr1); afi_b = lisp_addr_ip_afi(addr2); break; case LM_AFI_LCAF: afi_a = lisp_addr_lcaf_type(addr1); afi_b = lisp_addr_lcaf_type(addr2); break; default: OOR_LOG(LDBG_1,"lisp_addr_cmp_afi: wrong AFI"); return (-2); } if (afi_a > afi_b){ return (1); } if (afi_a < afi_b){ return (2); } return (0); } inline void lisp_addr_lcaf_set_addr(lisp_addr_t *laddr, void *addr) { laddr->lcaf.addr = addr; } inline void * lisp_addr_lcaf_addr(lisp_addr_t *laddr) { return (laddr->lcaf.addr); } inline lcaf_type_e lisp_addr_lcaf_type(lisp_addr_t *laddr) { return (laddr->lcaf.type); } inline void lisp_addr_lcaf_set_type(lisp_addr_t *laddr, int type) { laddr->lcaf.type = type; } inline void lisp_addr_ip_init(lisp_addr_t *addr, void *data, int afi) { set_lafi_(addr, LM_AFI_IP); ip_addr_init(get_ip_(addr), data, afi); } inline int lisp_addr_init_from_ip(lisp_addr_t *laddr, ip_addr_t *ip) { set_lafi_(laddr, LM_AFI_IP); ip_addr_copy(get_ip_(laddr), ip); return (GOOD); } inline int lisp_addr_init_from_ippref(lisp_addr_t *laddr, ip_addr_t *ip, uint8_t plen) { set_lafi_(laddr, LM_AFI_IPPREF); ip_prefix_set(get_ippref_(laddr), ip, plen); return (GOOD); } inline int lisp_addr_init_from_lcaf(lisp_addr_t *laddr, lcaf_addr_t *lcaf) { set_lafi_(laddr, LM_AFI_LCAF); lcaf_addr_copy(get_lcaf_(laddr), lcaf); return (GOOD); } inline uint16_t lisp_addr_iana_afi_to_lm_afi(uint16_t afi) { switch (afi) { case LISP_AFI_IP: case LISP_AFI_IPV6: return (LM_AFI_IP); case LISP_AFI_LCAF: return (LM_AFI_LCAF); default: OOR_LOG(LWRN, "lisp_addr_iana_afi_to_sock_afi: unknown IP AFI (%d)", afi); return (0); } } inline int lisp_addr_is_mc(lisp_addr_t *addr) { if (!addr) return (0); if (lisp_addr_is_lcaf(addr) && lcaf_addr_is_mc(get_lcaf_(addr))) return (1); else return (0); } lisp_addr_t * lisp_addr_get_ip_addr(lisp_addr_t *addr) { switch (lisp_addr_lafi(addr)) { case LM_AFI_IP: return (addr); case LM_AFI_IPPREF: OOR_LOG(LDBG_3, "lisp_addr_get_ip_addr: Not applicable to prefixes"); return (NULL); case LM_AFI_LCAF: return (lcaf_get_ip_addr(get_lcaf_(addr))); default: return (NULL); } return (NULL); } lisp_addr_t * lisp_addr_get_ip_pref_addr(lisp_addr_t *addr) { switch (lisp_addr_lafi(addr)) { case LM_AFI_IP: OOR_LOG(LDBG_3, "lisp_addr_get_ip_pref_addr: Not applicable to ip addressess"); return (NULL); case LM_AFI_IPPREF: return (addr); case LM_AFI_LCAF: return (lcaf_get_ip_pref_addr(get_lcaf_(addr))); default: return (NULL); } return (NULL); } /* Deallocates the address for LCAFs. Does nothing for other AFIs*/ void lisp_addr_dealloc(lisp_addr_t *addr) { switch (get_lafi_(addr)) { case LM_AFI_IP: case LM_AFI_IPPREF: case LM_AFI_NO_ADDR: break; case LM_AFI_LCAF: lcaf_addr_del_addr(get_lcaf_(addr)); break; default: break; } } /* Fill lisp_addr with the address. * Return GOOD if no error has been found */ int lisp_addr_ip_from_char(char *addr, lisp_addr_t *laddr) { if (ip_addr_from_char(addr, lisp_addr_ip(laddr)) == GOOD) { lisp_addr_set_lafi(laddr, LM_AFI_IP); return(GOOD); } else { lisp_addr_set_lafi(laddr, LM_AFI_NO_ADDR); return(BAD); } } /* Parse address and fill lisp_addr and mask. * Return GOOD if no error */ int lisp_addr_ippref_from_char(char *addr, lisp_addr_t *laddr) { if (ip_prefix_from_char(addr, get_ippref_(laddr)) == GOOD) { lisp_addr_set_lafi(laddr, LM_AFI_IPPREF); return(GOOD); } else { lisp_addr_set_lafi(laddr, LM_AFI_NO_ADDR); return(BAD); } } inline int lisp_addr_ip_afi_lcaf_type(lisp_addr_t *addr) { switch (addr->lafi){ case LM_AFI_NO_ADDR: return (0); case LM_AFI_IP: return (addr->ip.afi); case LM_AFI_IPPREF: return (addr->ippref.prefix.afi); case LM_AFI_LCAF: return (addr->lcaf.type); } return (-1); } oor-1.2.0/oor/liblisp/lisp_address.h000066400000000000000000000104531313612200500173670ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef LISPD_ADDRESS_H_ #define LISPD_ADDRESS_H_ #include "lisp_ip.h" #include "lisp_lcaf.h" #include "lisp_messages.h" /* * Lisp address structure */ typedef enum { LM_AFI_NO_ADDR = 0, LM_AFI_IP, LM_AFI_IPPREF, LM_AFI_LCAF, } lm_afi_t; /* TODO fcoras: The cool thing about the new lisp_addr_t * is that we can access in 2 ways the same data * either as old struct or as ip_addr_t. Still, would be nice * to deprecate the old struct */ typedef struct _lisp_addr_t lisp_addr_t; //typedef struct _lcaf_addr_t lcaf_addr_t; struct _lisp_addr_t { struct { union { ip_addr_t ip; ip_prefix_t ippref; lcaf_addr_t lcaf; }; lm_afi_t lafi; }; }; lisp_addr_t *lisp_addr_new(); lisp_addr_t *lisp_addr_new_lafi(uint8_t lafi); void lisp_addr_del(lisp_addr_t *laddr); void lisp_addr_dealloc(lisp_addr_t *addr); void lisp_addr_copy(lisp_addr_t *dst, lisp_addr_t *src); lisp_addr_t *lisp_addr_clone(lisp_addr_t *src); uint32_t lisp_addr_copy_to(void *dst, lisp_addr_t *src); int lisp_addr_write(void *offset, lisp_addr_t *laddr); int lisp_addr_parse(uint8_t *offset, lisp_addr_t *laddr); int lisp_addr_cmp(lisp_addr_t *addr1, lisp_addr_t *addr2); int lisp_addr_cmp_afi(lisp_addr_t *addr1, lisp_addr_t *addr2); uint32_t lisp_addr_size_to_write(lisp_addr_t *laddr); char *lisp_addr_to_char(lisp_addr_t *addr); void lisp_addr_set_lafi(lisp_addr_t *addr, lm_afi_t afi); void lisp_addr_set_plen(lisp_addr_t *laddr, uint8_t plen); void lisp_addr_set_ip(lisp_addr_t *addr, ip_addr_t *ip); static inline lm_afi_t lisp_addr_lafi(lisp_addr_t *addr) { return (addr->lafi); } static inline ip_addr_t * lisp_addr_ip(lisp_addr_t *addr) { return (&addr->ip); } static inline ip_prefix_t * lisp_addr_get_ippref(lisp_addr_t *addr) { return (&addr->ippref); } static inline lcaf_addr_t * lisp_addr_get_lcaf(lisp_addr_t *addr) { return (&addr->lcaf); } static inline int lisp_addr_is_ip(lisp_addr_t *addr) { return (addr->lafi == LM_AFI_IP); } static inline int lisp_addr_is_ip_pref(lisp_addr_t *addr) { return (addr->lafi == LM_AFI_IPPREF); } static inline int lisp_addr_is_no_addr(lisp_addr_t *addr) { return (addr->lafi == LM_AFI_NO_ADDR); } static inline int lisp_addr_is_lcaf(lisp_addr_t *addr) { return (addr->lafi == LM_AFI_LCAF); } uint16_t lisp_addr_ip_afi(lisp_addr_t *addr); ip_addr_t *lisp_addr_ip_get_addr(lisp_addr_t *laddr); uint8_t lisp_addr_ip_get_plen(lisp_addr_t *laddr); void lisp_addr_ip_set_afi(lisp_addr_t *laddr, int afi); void lisp_addr_set_ip_afi(lisp_addr_t *la, int afi); void lisp_addr_ip_to_ippref(lisp_addr_t *laddr); void lisp_addr_ip_init(lisp_addr_t *addr, void *data, int afi); int lisp_addr_is_lcaf(lisp_addr_t *laddr); void lisp_addr_lcaf_set_addr(lisp_addr_t *laddr, void *addr); void *lisp_addr_lcaf_addr(lisp_addr_t *laddr); lcaf_type_e lisp_addr_lcaf_type(lisp_addr_t *laddr); void lisp_addr_lcaf_set_type(lisp_addr_t *laddr, int type); int lisp_addr_init_from_ip(lisp_addr_t *, ip_addr_t *); int lisp_addr_init_from_ippref(lisp_addr_t *, ip_addr_t *, uint8_t); int lisp_addr_init_from_lcaf(lisp_addr_t *, lcaf_addr_t *); uint16_t lisp_addr_iana_afi_to_lm_afi(uint16_t afi); uint16_t lisp_addr_get_iana_afi(lisp_addr_t *laddr); uint16_t lisp_addr_get_plen(lisp_addr_t *laddr); int lisp_addr_is_mc(lisp_addr_t *addr); lisp_addr_t *lisp_addr_get_ip_addr(lisp_addr_t *addr); lisp_addr_t *lisp_addr_get_ip_pref_addr(lisp_addr_t *addr); int lisp_addr_ip_from_char(char *, lisp_addr_t *); int lisp_addr_ippref_from_char(char *, lisp_addr_t *); int lisp_addr_ip_afi_lcaf_type(lisp_addr_t *addr); #endif /* LISPD_ADDRESS_H_ */ oor-1.2.0/oor/liblisp/lisp_data.c000066400000000000000000000025331313612200500166460ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "lisp_data.h" #include "../lib/packets.h" uint32_t lisp_data_hdr_get_iid(lisp_data_hdr_t *hdr) { return (pkt_get_uint32_from_3bytes(hdr->iid)); } void lisp_data_hdr_init(lisp_data_hdr_t *lhdr, uint32_t iid) { lhdr->echo_nonce = 0; lhdr->lsb = 0; lhdr->lsb_bits = 0; lhdr->map_version = 0; lhdr->nonce[0] = 0; lhdr->nonce[1] = 0; lhdr->nonce[2] = 0; if (iid > 0){ lhdr->instance_id = 1; pkt_add_uint32_in_3bytes (lhdr->iid, iid);; }else{ lhdr->instance_id = 0; lhdr->iid[0] = 0; lhdr->iid[1] = 0; lhdr->iid[2] = 0; } lhdr->nonce_present = 0; lhdr->rflags = 0; } oor-1.2.0/oor/liblisp/lisp_data.h000066400000000000000000000030201313612200500166430ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef LISP_DATA_H_ #define LISP_DATA_H_ #include "../lib/mem_util.h" /* LISP data packet header */ typedef struct lisp_data_hdr { #ifdef LITTLE_ENDIANS uint8_t rflags:3; uint8_t instance_id:1; uint8_t map_version:1; uint8_t echo_nonce:1; uint8_t lsb:1; uint8_t nonce_present:1; #else uint8_t nonce_present:1; uint8_t lsb:1; uint8_t echo_nonce:1; uint8_t map_version:1; uint8_t instance_id:1; uint8_t rflags:3; #endif uint8_t nonce[3]; uint8_t iid[3]; uint8_t lsb_bits; } lisp_data_hdr_t; uint32_t lisp_data_hdr_get_iid(lisp_data_hdr_t *hdr); void lisp_data_hdr_init(lisp_data_hdr_t *lhdr, uint32_t iid); #define LISPDATA_HDR_CAST(h_) ((lisp_data_hdr_t *)(h_)) #define LDHDR_LSB_BIT(h_) (LISPDATA_HDR_CAST((h_)))->instance_id #endif /* LISP_DATA_H_ */ oor-1.2.0/oor/liblisp/lisp_ip.c000066400000000000000000000310421313612200500163420ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include #include "lisp_address.h" #include "../lib/mem_util.h" #include "../lib/oor_log.h" /* * ip_addr_t functions */ inline ip_addr_t * ip_addr_new() { return(xzalloc(sizeof(ip_addr_t))); } inline void ip_addr_del(ip_addr_t *ip) { free(ip); } inline int ip_addr_afi(ip_addr_t *ipaddr) { return(ipaddr->afi); } inline void * ip_addr_get_addr(ip_addr_t *ipaddr) { return (&(ipaddr->addr)); } inline struct in_addr * ip_addr_get_v4(ip_addr_t *ipaddr) { return(&(ipaddr->addr.v4)); } inline struct in6_addr * ip_addr_get_v6(ip_addr_t *ipaddr) { return(&(ipaddr->addr.v6)); } inline uint8_t ip_addr_get_size(ip_addr_t *ipaddr) { return(ip_sock_afi_to_size(ip_addr_afi(ipaddr))); } inline uint8_t ip_addr_get_size_to_write(ip_addr_t *ipaddr) { /* includes afi size */ return(ip_sock_afi_to_size(ip_addr_afi(ipaddr))+sizeof(uint16_t)); } inline uint16_t ip_addr_get_iana_afi(ip_addr_t *ipaddr) { return(ip_sock_to_iana_afi(ip_addr_afi(ipaddr))); } inline int ip_addr_set_afi(ip_addr_t *ipaddr, int afi) { if (afi != AF_INET && afi != AF_INET6 && afi != AF_UNSPEC) { OOR_LOG(LWRN, "ip_addr_set_afi: unknown IP AFI (%d)", afi); return(BAD); } ipaddr->afi = afi; return(GOOD); } void ip_addr_set_v4(ip_addr_t *ipaddr, void *src) { ip_addr_set_afi(ipaddr, AF_INET); memcpy(ip_addr_get_v4(ipaddr), src, sizeof(struct in_addr)); } inline void ip_addr_set_v6(ip_addr_t *ipaddr, void *src) { ip_addr_set_afi(ipaddr, AF_INET6); memcpy(ip_addr_get_v6(ipaddr), src, sizeof(struct in6_addr)); } inline void ip_addr_init(ip_addr_t *ipaddr, void *src, uint8_t afi) { switch(afi) { case AF_INET: ip_addr_set_v4(ipaddr, src); break; case AF_INET6: ip_addr_set_v6(ipaddr, src); break; default: OOR_LOG(LWRN, "ip_addr_init: unknown IP AFI (%d)", afi); break; } } char * ip_addr_to_char(ip_addr_t *addr) { return(ip_to_char(ip_addr_get_addr(addr), ip_addr_afi(addr))); } /* ip_addr_copy * * @dst : the destination where the ip should be copied * @src : the ip address to be copied * Description: The function copies src structure to dst * structure. It does a full memory copy */ inline void ip_addr_copy(ip_addr_t *dst, ip_addr_t *src) { if (!dst || !src) { return; } memcpy(dst, src, sizeof(ip_addr_t)); } /* ip_addr_copy_to * * @dst : memory location * @src : the ip address to be copied * Description: The function copies what is *CONTAINED* in an ip address * to a given memory location, NOT the whole structure! See ip_addr_copy * for copying ip addresses */ inline void ip_addr_copy_to(void *dst, ip_addr_t *src) { if (!dst || !src) { return; } memcpy(dst, ip_addr_get_addr(src), ip_addr_get_size(src)); } inline int ip_addr_write_to_pkt(void *dst, ip_addr_t *src, uint8_t convert) { *(uint16_t *)dst = htons(ip_addr_get_iana_afi(src)); dst = CO(dst, sizeof(uint16_t)); if (convert && ip_addr_afi(src) == AF_INET) { /* XXX: haven't encountered a case when this is used */ *((uint32_t *)dst) = htonl(ip_addr_get_v4(src)->s_addr); } else { memcpy(dst, ip_addr_get_addr(src), ip_addr_get_size(src)); } return(sizeof(uint16_t)+ip_addr_get_size(src)); } inline int ip_addr_cmp(ip_addr_t *ip1, ip_addr_t *ip2) { int res = 0; if (ip_addr_afi(ip1) != ip_addr_afi(ip2)){ OOR_LOG(LDBG_3,"ip_addr_cmp: Addresses with different afi: %d - %d", ip_addr_afi(ip1),ip_addr_afi(ip2)); return(-1); } res = memcmp(ip_addr_get_addr(ip1), ip_addr_get_addr(ip2), ip_addr_get_size(ip1)); if (res < 0){ res = 2; }else if (res > 0){ res = 1; } return(res); } inline int ip_addr_parse(void *offset, uint16_t iana_afi, ip_addr_t *dst) { if(ip_addr_set_afi(dst, ip_iana_to_sock_afi(iana_afi)) == BAD) return(0); memcpy(ip_addr_get_addr(dst), CO(offset, sizeof(uint16_t)), ip_iana_afi_to_size(iana_afi)); return(sizeof(uint16_t) + ip_iana_afi_to_size(iana_afi)); } inline uint8_t ip_addr_afi_to_default_mask(ip_addr_t *ip) { return(ip_afi_to_default_mask(ip_addr_afi(ip))); } /* * ip_prefix_t functions */ inline uint8_t ip_prefix_get_plen(ip_prefix_t *pref) { return(pref->plen); } inline ip_addr_t * ip_prefix_addr(ip_prefix_t *pref) { return(&(pref->prefix)); } inline uint8_t ip_prefix_afi(ip_prefix_t *pref) { return(ip_addr_afi(ip_prefix_addr(pref))); } inline void ip_prefix_set(ip_prefix_t *pref, ip_addr_t *ipaddr, uint8_t plen) { ip_addr_copy(ip_prefix_addr(pref), ipaddr); ip_prefix_set_plen(pref, plen); } inline void ip_prefix_set_plen(ip_prefix_t *pref, uint8_t plen) { pref->plen = plen; } inline void ip_prefix_set_afi(ip_prefix_t *pref, int afi) { ip_addr_set_afi(&pref->prefix, afi); } inline void ip_prefix_copy(ip_prefix_t *dst, ip_prefix_t *src) { ip_prefix_set_plen(dst, ip_prefix_get_plen(src)); ip_addr_copy(ip_prefix_addr(dst), ip_prefix_addr(src)); } char * ip_prefix_to_char(ip_prefix_t *pref) { static char address[10][INET6_ADDRSTRLEN+5]; static unsigned int i; /* Hack to allow more than one addresses per printf line. * Now maximum = 5 */ i++; i = i % 10; *address[i] = '\0'; sprintf(address[i], "%s/%d", ip_addr_to_char(ip_prefix_addr(pref)), ip_prefix_get_plen(pref)); return(address[i]); } int ip_addr_from_char(char *addr, ip_addr_t *ip) { int afi; afi = ip_afi_from_char(addr); if (inet_pton(afi, addr, ip_addr_get_addr(ip)) == 1) { ip_addr_set_afi(ip, afi); } else{ return(BAD); } return(GOOD); } int ip_prefix_from_char(char *addr, ip_prefix_t *ippref) { char *address = strdup(addr); char *token; int mask; if ((token = strtok(address, "/")) == NULL) { OOR_LOG(LDBG_1, "ip_prefix_from_char: Prefix not of the form " "prefix/length: %s", addr); free(address); return (BAD); } if (ip_addr_from_char(token, ip_prefix_addr(ippref)) == BAD) { free(address); return (BAD); } if ((token = strtok(NULL, "/")) == NULL) { OOR_LOG(LDBG_1, "ip_prefix_from_char: strtok: %s", strerror(errno)); free(address); return (BAD); } mask = atoi(token); free(address); if (ip_addr_afi(ip_prefix_addr(ippref)) == AF_INET) { if (mask < 0 || mask > 32){ OOR_LOG(LDBG_2, "ip_prefix_from_char: Invalid mask : %s",address); return (BAD); } } else { if (mask < 0 || mask > 128){ OOR_LOG(LDBG_2, "ip_prefix_from_char: Invalid mask : %s",address); return (BAD); } } /* convert the ip addr into a prefix */ ip_prefix_set_plen(ippref, mask); return (GOOD); } /* * other ip functions */ char * ip_to_char(void *ip, int afi) { static char address[10][INET6_ADDRSTRLEN+1]; static unsigned int i; i++; i = i % 10; *address[i] = '\0'; switch (afi) { case AF_INET: inet_ntop(AF_INET, ip, address[i], INET_ADDRSTRLEN); return(address[i]); case AF_INET6: inet_ntop(AF_INET6, ip, address[i], INET6_ADDRSTRLEN); return(address[i]); } return(NULL); } inline uint16_t ip_sock_to_iana_afi(uint16_t afi) { switch (afi){ case AF_INET: return(LISP_AFI_IP); case AF_INET6: return(LISP_AFI_IPV6); default: OOR_LOG(LWRN, "ip_sock_to_iana_afi: unknown IP AFI (%d)", afi); return(0); } } inline uint16_t ip_iana_to_sock_afi(uint16_t afi) { switch (afi) { case LISP_AFI_IP: return(AF_INET); case LISP_AFI_IPV6: return(AF_INET6); default: OOR_LOG(LWRN, "ip_iana_to_sock_afi: unknown IP AFI (%d)", afi); return(0); } } inline uint8_t ip_sock_afi_to_size(uint16_t afi) { switch (afi) { case AF_INET: return(sizeof(struct in_addr)); case AF_INET6: return(sizeof(struct in6_addr)); default: OOR_LOG(LWRN, "ip_sock_afi_to_size: unknown IP AFI (%d)", afi); return(0); } } /* given afi, get the IP header length */ inline int ip_sock_afi_to_hdr_len(int afi) { switch (afi) { /* == eid_afi */ case AF_INET: return(sizeof(struct ip)); case AF_INET6: return(sizeof(struct ip6_hdr)); default: OOR_LOG(LDBG_2, "get_ip_header_len: unknown AFI (%d)", afi); return(ERR_AFI); } } inline uint8_t ip_iana_afi_to_size(uint16_t afi) { switch(afi) { case LISP_AFI_IP: return(sizeof(struct in_addr)); case LISP_AFI_IPV6: return(sizeof(struct in6_addr)); default: OOR_LOG(LDBG_3, "ip_iana_afi_to_size: unknown AFI (%d)", afi); return(0); } return(0); } int ip_addr_is_link_local(ip_addr_t *ip) { return(ip_is_link_local(ip_addr_get_addr(ip), ip_addr_afi(ip))); } int ip_addr_is_any(ip_addr_t *ip) { switch (ip_addr_afi(ip)) { case AF_INET: { struct in_addr *ip4 = (struct in_addr *) ip_addr_get_addr(ip); return(ip4->s_addr == 0); } case AF_INET6: return(IN6_IS_ADDR_UNSPECIFIED((struct in6_addr *)ip_addr_get_addr(ip))); } return(0); } inline uint8_t ip_addr_is_multicast(ip_addr_t *addr) { return(ip_is_multicast(ip_addr_get_addr(addr), ip_addr_afi(addr))); } uint8_t ip_is_multicast(void *ip, int afi) { switch (afi) { case AF_INET: return ipv4_is_multicast(ip); break; case AF_INET6: return ipv6_is_multicast(ip); break; default: OOR_LOG(LWRN, "is_multicast_addr: Unknown afi %s", afi); break; } return(0); } uint8_t ipv4_is_multicast(struct in_addr *addr) { if (ntohl(addr->s_addr)>=MCASTMIN4 && ntohl(addr->s_addr)<=MCASTMAX4) return(1); else return(0); } uint8_t ipv6_is_multicast(struct in6_addr *addr) { return(IN6_IS_ADDR_MULTICAST(addr)); } uint8_t ip_version_to_sock_afi(uint8_t ver) { switch(ver) { case IPVERSION: return(AF_INET); case IP6VERSION: return(AF_INET6); default: return(0); } } int ip_afi_to_default_mask(int afi) { switch (afi) { case AF_INET: return(32); case AF_INET6: return(128); default: return(0); } // return(ip_sock_afi_to_size(afi)*8); } /* Return TRUE if the address belongs to: * IPv4: 169.254.0.0/16 * IPv6: fe80::/10 */ uint8_t ip_is_link_local(void *addr, int afi) { int is_link_local = FALSE; uint32_t ipv4_network = 0; uint32_t mask = 0; struct in_addr *ipv4; struct in6_addr *ipv6; switch (afi) { case AF_INET: ipv4 = addr; inet_pton(AF_INET,"169.254.0.0", &ipv4_network); inet_pton(AF_INET,"255.255.0.0", &mask); if ((ipv4->s_addr & mask) == ipv4_network) { is_link_local = TRUE; } break; case AF_INET6: /* if (((addr.address.ipv6.__in6_u.__u6_addr8[0] & 0xff) == 0xfe) && ((addr.address.ipv6.__in6_u.__u6_addr8[1] & 0xc0) == 0x80)){ } */ ipv6 = addr; if (IN6_IS_ADDR_LINKLOCAL(ipv6)) { is_link_local = TRUE; } break; } return(is_link_local); } int ip_hdr_ver_to_len(int ih_ver) { switch (ih_ver) { case IPVERSION: return(sizeof(struct ip)); case IP6VERSION: return(sizeof(struct ip6_hdr)); default: OOR_LOG(LDBG_2, "ip_hdr_ver_to_len: Unknown IP version %d!", ih_ver); return(BAD); } } /* Assume if there's a colon in str that its an IPv6 * address. Otherwise its v4. */ int ip_afi_from_char(char *str) { if (strchr(str,':')) /* poor-man's afi discriminator */ return(AF_INET6); else return(AF_INET); } oor-1.2.0/oor/liblisp/lisp_ip.h000066400000000000000000000071031313612200500163500ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef LISPD_IP_H_ #define LISPD_IP_H_ #include #include #include #include #include #include #include /* * Maximum length (in bytes) of an IP address */ #define MAX_INET_ADDRSTRLEN INET6_ADDRSTRLEN #define MCASTMIN4 0xE0000000 #define MCASTMAX4 0xEFFFFFFF /* * IP address type */ typedef struct { int afi; union { struct in_addr v4; struct in6_addr v6; } addr; } ip_addr_t; typedef struct { ip_addr_t prefix; uint8_t plen; } ip_prefix_t; /* * ip_addr_t functions */ ip_addr_t *ip_addr_new(); void ip_addr_del(ip_addr_t *ip); int ip_addr_afi(ip_addr_t *ipaddr); void *ip_addr_get_addr(ip_addr_t *ipaddr); struct in_addr *ip_addr_get_v4(ip_addr_t *ipaddr); struct in6_addr *ip_addr_get_v6(ip_addr_t *ipaddr); uint8_t ip_addr_get_size(ip_addr_t *ipaddr); uint8_t ip_addr_get_size_to_write(ip_addr_t *ipaddr); uint16_t ip_addr_get_iana_afi(ip_addr_t *ipaddr); int ip_addr_set_afi(ip_addr_t *ipaddr, int afi); void ip_addr_set_v4(ip_addr_t *ipaddr, void *src); void ip_addr_set_v6(ip_addr_t *ipaddr, void *src); void ip_addr_init(ip_addr_t *ipaddr, void *src, uint8_t afi); void ip_addr_copy(ip_addr_t *dst, ip_addr_t *src); void ip_addr_copy_to(void *dst, ip_addr_t *src); int ip_addr_write_to_pkt(void *dst, ip_addr_t *src, uint8_t convert); int ip_addr_parse(void *offset, uint16_t afi, ip_addr_t *dst); int ip_addr_cmp(ip_addr_t *ip1, ip_addr_t *ip2); uint8_t ip_addr_afi_to_default_mask(ip_addr_t *ip); char *ip_addr_to_char (ip_addr_t *addr); /* * ip_prefix_t functions */ uint8_t ip_prefix_get_plen(ip_prefix_t *pref); ip_addr_t *ip_prefix_addr(ip_prefix_t *pref); uint8_t ip_prefix_afi(ip_prefix_t *pref); void ip_prefix_set(ip_prefix_t *pref, ip_addr_t *ipaddr, uint8_t plen); void ip_prefix_set_plen(ip_prefix_t *pref, uint8_t plen); void ip_prefix_set_afi(ip_prefix_t *pref, int afi); void ip_prefix_copy(ip_prefix_t *dst, ip_prefix_t *src); char *ip_prefix_to_char(ip_prefix_t *pref); int ip_addr_from_char(char *address, ip_addr_t *ip); int ip_prefix_from_char(char *address, ip_prefix_t *ippref); int ip_addr_is_link_local(ip_addr_t *addr); int ip_addr_is_any(ip_addr_t *ip); uint8_t ip_addr_is_multicast(ip_addr_t *addr); /* IP-UTIL functions*/ char *ip_to_char(void *ip, int afi); uint16_t ip_sock_to_iana_afi(uint16_t afi); uint16_t ip_iana_to_sock_afi(uint16_t afi); uint8_t ip_sock_afi_to_size(uint16_t afi); int ip_sock_afi_to_hdr_len(int afi); uint8_t ip_iana_afi_to_size(uint16_t afi); uint8_t ip_is_multicast(void *ip, int afi); uint8_t ipv4_is_multicast(struct in_addr *addr); uint8_t ipv6_is_multicast(struct in6_addr *addr); uint8_t ip_version_to_sock_afi(uint8_t ver); int ip_afi_to_default_mask(int afi); uint8_t ip_is_link_local(void *, int afi); int ip_hdr_ver_to_len(int ih_ver); int ip_afi_from_char(char *str); #endif /* LISPD_IP_H_ */ oor-1.2.0/oor/liblisp/lisp_lcaf.c000066400000000000000000001540041313612200500166430ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include #include "lisp_lcaf.h" #include "lisp_address.h" #include "../defs.h" #include "../lib/mem_util.h" #include "../lib/oor_log.h" typedef void (*del_fct)(void *); typedef int (*parse_fct)(uint8_t *, void **); typedef char *(*to_char_fct)(void *); typedef void (*copy_fct)(void **, void *); typedef int (*cmp_fct)(void *, void *); typedef int (*write_fct)(uint8_t *, void *); typedef int (*size_in_pkt_fct)(void *); typedef lisp_addr_t *(*get_ip_addr_fct)(void *); typedef lisp_addr_t *(*get_ip_pref_addr_fct)(void *); del_fct del_fcts[MAX_LCAFS] = { 0, afi_list_type_del, iid_type_del, 0, 0, 0, geo_type_del, nat_type_del, 0, mc_type_del, elp_type_del, 0, 0, rle_type_del, 0, 0}; parse_fct parse_fcts[MAX_LCAFS] = { 0, afi_list_type_parse, iid_type_parse, 0, 0, 0, geo_type_parse, nat_type_parse, 0, mc_type_parse, elp_type_parse, 0, 0, rle_type_parse, 0, 0}; to_char_fct to_char_fcts[MAX_LCAFS] = { 0, afi_list_type_to_char, iid_type_to_char, 0, 0, 0, geo_type_to_char, nat_type_to_char, 0, mc_type_to_char, elp_type_to_char, 0, 0, rle_type_to_char, 0, 0 }; write_fct write_fcts[MAX_LCAFS] = { 0, afi_list_type_write_to_pkt, iid_type_write_to_pkt, 0, 0, 0, 0, nat_type_write_to_pkt, 0, mc_type_write_to_pkt, elp_type_write_to_pkt, 0, 0, rle_type_write_to_pkt, 0, 0}; copy_fct copy_fcts[MAX_LCAFS] = { 0, afi_list_type_copy, iid_type_copy, 0, 0, 0, geo_type_copy, nat_type_copy, 0, mc_type_copy, elp_type_copy, 0, 0, rle_type_copy, 0, 0}; cmp_fct cmp_fcts[MAX_LCAFS] = { 0, afi_list_type_cmp, iid_type_cmp, nat_type_cmp, 0, 0, 0, 0, 0, mc_type_cmp, elp_type_cmp, 0, 0, rle_type_cmp, 0, 0}; size_in_pkt_fct size_in_pkt_fcts[MAX_LCAFS] = { 0, afi_list_type_get_size_to_write, iid_type_get_size_to_write, 0, 0, 0, 0, nat_type_get_size_to_write, 0, mc_type_get_size_to_write, elp_type_get_size_to_write, 0, 0, rle_type_get_size_to_write, 0, 0}; get_ip_addr_fct get_ip_addr_fcts[MAX_LCAFS] = { 0, afi_list_type_get_ip_addr, iid_type_get_ip_addr, 0, 0, 0, 0, nat_type_get_ip_addr, 0, mc_type_get_ip_addr, elp_type_get_ip_addr, 0, 0, 0, 0, 0}; get_ip_pref_addr_fct get_ip_pref_addr_fcts[MAX_LCAFS] = { 0, afi_list_type_get_ip_pref_addr, iid_type_get_ip_pref_addr, 0, 0, 0, 0, nat_type_get_ip_pref_addr, 0, mc_type_get_ip_pref_addr,0, 0, 0, 0, 0, 0}; static inline lcaf_type_e get_type_(lcaf_addr_t *lcaf) { assert(lcaf); return(lcaf->type); } static inline void *get_addr_(lcaf_addr_t *lcaf) { assert(lcaf); return(lcaf->addr); } lcaf_addr_t * lcaf_addr_new() { return(xzalloc(sizeof(lcaf_addr_t))); } lcaf_addr_t * lcaf_addr_new_type(uint8_t type) { lcaf_addr_t *lcaf; lcaf = xzalloc(sizeof(lcaf_addr_t)); lcaf_addr_set_type(lcaf, type); switch(type) { case LCAF_IID: lcaf->addr = iid_type_new(); break; case LCAF_MCAST_INFO: lcaf->addr = mc_type_new(); break; case LCAF_GEO: break; default: break; } return(lcaf); } /* free only the address part */ void lcaf_addr_del_addr(lcaf_addr_t *lcaf) { if (!lcaf->addr) { return; } if (!del_fcts[get_type_(lcaf)]) { return; } (*del_fcts[get_type_(lcaf)])(get_addr_(lcaf)); } /* free an lcaf pointer */ void lcaf_addr_del(lcaf_addr_t *lcaf) { assert(lcaf); if (!del_fcts[get_type_(lcaf)]) { return; } (*del_fcts[get_type_(lcaf)])(get_addr_(lcaf)); free(lcaf); } /* * lcaf_addr_t functions */ int lcaf_addr_parse(uint8_t *offset, lcaf_addr_t *lcaf) { int len = 0; /* about to ovewrite 'addr', just free the old one */ if (get_addr_(lcaf)) { lcaf_addr_del_addr(lcaf); } lcaf_addr_set_type(lcaf, ((lcaf_hdr_t *)offset)->type); if (!parse_fcts[lcaf_addr_get_type(lcaf)]) { OOR_LOG(LDBG_3, "lcaf_addr_read_from_pkt: Cannot parse LCAF type %d:", lcaf_addr_get_type(lcaf)); return(BAD); } len = parse_fcts[lcaf_addr_get_type(lcaf)](offset, &lcaf->addr); if (len != ntohs(((lcaf_hdr_t *)offset)->len) + sizeof(lcaf_hdr_t)) { OOR_LOG(LDBG_3, "lcaf_addr_read_from_pkt: len field %d, without header, and the number of " "bytes read %d don't differ by 8 bytes!", ntohs(((lcaf_hdr_t *)offset)->len), len); return(BAD); } return(len); } char * lcaf_addr_to_char(lcaf_addr_t *lcaf) { assert(lcaf); if (!to_char_fcts[get_type_(lcaf)]) { return ("LCAF not supported"); } return((*to_char_fcts[get_type_(lcaf)])(lcaf_addr_get_addr(lcaf))); } inline lcaf_type_e lcaf_addr_get_type(lcaf_addr_t *lcaf) { assert(lcaf); return(lcaf->type); } inline mc_t * lcaf_addr_get_mc(lcaf_addr_t *lcaf) { assert(lcaf); return((mc_t *)lcaf_addr_get_addr(lcaf)); } inline geo_t * lcaf_addr_get_geo(lcaf_addr_t *lcaf) { assert(lcaf); return((geo_t *)lcaf_addr_get_addr(lcaf)); } inline iid_t * lcaf_addr_get_iid(lcaf_addr_t *lcaf) { assert(lcaf); return((iid_t *)lcaf_addr_get_addr(lcaf)); } inline nat_t * lcaf_addr_get_nat(lcaf_addr_t *lcaf) { assert(lcaf); return((nat_t *)lcaf_addr_get_addr(lcaf)); } inline void * lcaf_addr_get_addr(lcaf_addr_t *lcaf) { assert(lcaf); return(lcaf->addr); } inline int lcaf_addr_is_mc(lcaf_addr_t *lcaf) { if (lcaf_addr_get_type(lcaf) == LCAF_MCAST_INFO) return(TRUE); else return(FALSE); } inline int lcaf_addr_is_iid(lcaf_addr_t *lcaf) { if (lcaf_addr_get_type(lcaf) == LCAF_IID) return(TRUE); else return(FALSE); } inline void lcaf_addr_set(lcaf_addr_t *lcaf, void *newaddr, uint8_t type) { void *addr; addr = lcaf_addr_get_addr(lcaf); if (addr) lcaf_addr_del_addr(addr); lcaf_addr_set_type(lcaf, type); lcaf_addr_set_addr(lcaf, newaddr); } inline void lcaf_addr_set_addr(lcaf_addr_t *lcaf, void *addr) { assert(lcaf); assert(addr); lcaf->addr = addr; } inline void lcaf_addr_set_type(lcaf_addr_t *lcaf, uint8_t type) { assert(lcaf); lcaf->type = type; } inline uint32_t lcaf_addr_get_size_to_write(lcaf_addr_t *lcaf) { if (!size_in_pkt_fcts[get_type_(lcaf)]) { OOR_LOG(LWRN, "lcaf_addr_get_size_to_write: size not implemented for LCAF type %d", get_type_(lcaf)); return(BAD); } return((*size_in_pkt_fcts[get_type_(lcaf)])(get_addr_(lcaf))); } int lcaf_addr_copy(lcaf_addr_t *dst, lcaf_addr_t *src) { assert(src); if (!copy_fcts[lcaf_addr_get_type(src)]) { OOR_LOG(LWRN, "lcaf_addr_copy: copy not implemented for LCAF type %s",lcaf_addr_get_type(src)); return(BAD); } /* if 'addr' set, free it */ if (get_addr_(dst)) { lcaf_addr_del_addr(dst); } lcaf_addr_set_type(dst, get_type_(src)); (*copy_fcts[get_type_(src)])(&dst->addr, src->addr); return(GOOD); } inline int lcaf_addr_write(void *offset, lcaf_addr_t *lcaf) { assert(lcaf); if (!write_fcts[get_type_(lcaf)]) { OOR_LOG(LWRN, "lcaf_addr_write_to_pkt: write not implemented for LCAF type %d", get_type_(lcaf)); return(BAD); } return((*write_fcts[get_type_(lcaf)])(offset, get_addr_(lcaf))); } inline int lcaf_addr_cmp(lcaf_addr_t *addr1, lcaf_addr_t *addr2) { if (lcaf_addr_get_type(addr1) != lcaf_addr_get_type(addr2)){ OOR_LOG(LDBG_1,"lcaf_addr_cmp: Addresses with different lcaf type: %d - %d", lcaf_addr_get_type(addr1),lcaf_addr_get_type(addr2)); return(-1); } if (!(cmp_fcts[lcaf_addr_get_type(addr1)])) { OOR_LOG(LDBG_1, "lcaf_addr_cmp: cmp not implemented for type %d", lcaf_addr_get_type(addr1)); return(-1); } return((*cmp_fcts[lcaf_addr_get_type(addr1)])(lcaf_addr_get_addr(addr1), lcaf_addr_get_addr(addr2))); } inline uint8_t lcaf_addr_cmp_iids(lcaf_addr_t *addr1, lcaf_addr_t *addr2) { if (get_type_(addr1) != get_type_(addr2)) return(0); switch(get_type_(addr1)) { case LCAF_IID: return(lcaf_iid_get_iid(addr1) == lcaf_iid_get_iid(addr2)); case LCAF_MCAST_INFO: return(mc_type_get_iid(get_addr_(addr1)) == mc_type_get_iid(addr2)); default: return(0); } } /* * mc_addr_t functions */ /* external */ inline lisp_addr_t * lcaf_mc_get_src(lcaf_addr_t *mc) { assert(mc); if (lcaf_addr_get_type(mc) != LCAF_MCAST_INFO) return(NULL); return(mc_type_get_src(lcaf_addr_get_mc(mc))); } inline lisp_addr_t * lcaf_mc_get_grp(lcaf_addr_t *mc) { assert(mc); if (lcaf_addr_get_type(mc) != LCAF_MCAST_INFO) return(NULL); return(mc_type_get_grp(lcaf_addr_get_mc(mc))); } inline uint32_t lcaf_mc_get_iid(lcaf_addr_t *mc) { assert(mc); return(mc_type_get_iid(lcaf_addr_get_mc(mc))); } inline uint8_t lcaf_mc_get_src_plen(lcaf_addr_t *mc) { assert(mc); return(mc_type_get_src_plen(mc->addr)); } inline uint8_t lcaf_mc_get_grp_plen(lcaf_addr_t *mc) { assert(mc); return(mc_type_get_grp_plen(mc->addr)); } inline uint8_t lcaf_mc_get_afi(lcaf_addr_t *mc) { assert(mc); return(mc_type_get_afi(mc->addr)); } /* these shouldn't be called from outside */ inline mc_t * mc_type_new() { mc_t *mc = calloc(1, sizeof(mc_t)); mc->src = lisp_addr_new(); mc->grp = lisp_addr_new(); return(mc); } inline void mc_type_del(void *mc) { lisp_addr_del(mc_type_get_src(mc)); lisp_addr_del(mc_type_get_grp(mc)); free(mc); } inline void mc_type_set_src_plen(mc_t *mc, uint8_t plen) { assert(mc); mc->src_plen = plen; } inline void mc_type_set_grp_plen(mc_t *mc, uint8_t plen) { assert(mc); mc->grp_plen = plen; } inline void mc_type_set_iid(mc_t *mc, uint32_t iid) { assert(mc); mc->iid = iid; } inline void mc_type_set_src(void *mc, lisp_addr_t *src) { assert(mc); assert(src); lisp_addr_copy(mc_type_get_src(mc), src); } inline void mc_type_set_grp(mc_t *mc, lisp_addr_t *grp) { assert(mc); assert(grp); lisp_addr_copy(mc_type_get_grp(mc), grp); } inline void mc_type_copy(void **dst, void *src) { if (!(*dst)) *dst = mc_type_new(); mc_type_set_iid(*dst, mc_type_get_iid(src)); mc_type_set_src_plen(*dst, mc_type_get_src_plen(src)); mc_type_set_grp_plen(*dst, mc_type_get_grp_plen(src)); lisp_addr_copy(mc_type_get_src(*dst), mc_type_get_src(src)); lisp_addr_copy(mc_type_get_grp(*dst), mc_type_get_grp(src)); } inline int mc_type_cmp(void *mc1, void *mc2) { if ( (mc_type_get_iid(mc1) != mc_type_get_iid(mc2)) || (mc_type_get_src_plen(mc1) != mc_type_get_src_plen(mc2)) || (mc_type_get_grp_plen(mc1) != mc_type_get_grp_plen(mc2))) return(-1); /* XXX: rushed implementation * (S, G) comparison * First compare S and then G*/ int res = lisp_addr_cmp(mc_type_get_src(mc1), mc_type_get_src(mc2)); if (res == 0) return(lisp_addr_cmp(mc_type_get_grp(mc1), mc_type_get_grp(mc2))); else return(res); } inline void mc_type_set(mc_t *dst, lisp_addr_t *src, lisp_addr_t *grp, uint8_t splen, uint8_t gplen, uint32_t iid) { assert(src); assert(dst); assert(grp); mc_type_set_src(dst, src); mc_type_set_grp(dst, grp); mc_type_set_src_plen(dst, splen); mc_type_set_grp_plen(dst, gplen); mc_type_set_iid(dst, iid); } /** * mc_addr_init - makes an mc_addr_t from the parameters passed * @ src: source ip * @ grp: group ip * @ splen: source prefix length * @ gplen: group prefix length * @ iid: iid of the address */ mc_t * mc_type_init(lisp_addr_t *src, lisp_addr_t *grp, uint8_t splen, uint8_t gplen, uint32_t iid) { mc_t *mc; assert(src); assert(grp); mc = mc_type_new(); lisp_addr_copy(mc_type_get_src(mc), src); lisp_addr_copy(mc_type_get_grp(mc), grp); mc_type_set_src_plen(mc, splen); mc_type_set_grp_plen(mc, gplen); mc_type_set_iid(mc, iid); return(mc); } inline lisp_addr_t *mc_type_get_src(mc_t *mc) { assert(mc); return(mc->src); } inline lisp_addr_t * mc_type_get_grp(mc_t *mc) { assert(mc); return(mc->grp); } inline uint8_t mc_type_get_afi(mc_t *mc) { assert(mc); return(lisp_addr_ip_afi(mc_type_get_grp(mc))); } inline uint32_t mc_type_get_iid(void *mc) { assert(mc); return(((mc_t *)mc)->iid); } inline uint8_t mc_type_get_src_plen(mc_t *mc) { assert(mc); return(mc->src_plen); } inline uint8_t mc_type_get_grp_plen(mc_t *mc) { assert(mc); return(mc->grp_plen); } /* set functions common to all types */ char * mc_type_to_char(void *mc) { static char buf[10][INET6_ADDRSTRLEN*2+4]; static unsigned int i = 0; i++; i = i % 10; *buf[i] = '\0'; snprintf(buf[i],sizeof(buf[i]), "(%s/%d,%s/%d)", lisp_addr_to_char(mc_type_get_src((mc_t *)mc)), mc_type_get_src_plen((mc_t *)mc), lisp_addr_to_char(mc_type_get_grp((mc_t *)mc)), mc_type_get_src_plen((mc_t *)mc)); return(buf[i]); } int mc_type_get_size_to_write(void *mc) { return( sizeof(lcaf_mcinfo_hdr_t)+ lisp_addr_size_to_write(mc_type_get_src(mc)) + // sizeof(uint16_t)+ /* grp afi */ lisp_addr_size_to_write(mc_type_get_grp(mc)) ); } inline int mc_type_write_to_pkt(uint8_t *offset, void *mc) { int lena1 = 0, lena2 = 0; uint8_t *cur_ptr = NULL; ((lcaf_mcinfo_hdr_t *)offset)->afi = htons(LISP_AFI_LCAF); ((lcaf_mcinfo_hdr_t *)offset)->rsvd1 = 0; ((lcaf_mcinfo_hdr_t *)offset)->flags = 0; ((lcaf_mcinfo_hdr_t *)offset)->type = LCAF_MCAST_INFO; ((lcaf_mcinfo_hdr_t *)offset)->rsvd2 = 0; ((lcaf_mcinfo_hdr_t *)offset)->R = 0; ((lcaf_mcinfo_hdr_t *)offset)->L = 0; ((lcaf_mcinfo_hdr_t *)offset)->J = 0; ((lcaf_mcinfo_hdr_t *)offset)->iid = htonl(mc_type_get_iid(mc)); ((lcaf_mcinfo_hdr_t *)offset)->reserved = 0; ((lcaf_mcinfo_hdr_t *)offset)->src_mlen = mc_type_get_src_plen(mc); ((lcaf_mcinfo_hdr_t *)offset)->grp_mlen = mc_type_get_grp_plen(mc); cur_ptr = CO(offset, sizeof(lcaf_mcinfo_hdr_t)); cur_ptr = CO(cur_ptr, (lena1 = lisp_addr_write(cur_ptr, mc_type_get_src(mc)))); lena2 = lisp_addr_write(cur_ptr, mc_type_get_grp(mc)); ((lcaf_mcinfo_hdr_t *)offset)->len = htons(lena1+lena2+8*sizeof(uint8_t)); return(sizeof(lcaf_mcinfo_hdr_t)+lena1+lena2); } int mc_type_parse(uint8_t *offset, void **mc) { int srclen, grplen; srclen = grplen =0; *mc = mc_type_new(); mc_type_set_iid(*mc, ntohl(((lcaf_mcinfo_hdr_t *)offset)->iid)); mc_type_set_src_plen(*mc, ((lcaf_mcinfo_hdr_t *)offset)->src_mlen); mc_type_set_grp_plen(*mc, ((lcaf_mcinfo_hdr_t *)offset)->grp_mlen); offset = CO(offset, sizeof(lcaf_mcinfo_hdr_t)); srclen = lisp_addr_parse(offset, mc_type_get_src(*mc)); offset = CO(offset, srclen); grplen = lisp_addr_parse(offset, mc_type_get_grp(*mc)); return(sizeof(lcaf_mcinfo_hdr_t) + srclen + grplen); } /* Function that builds mc packets from packets on the wire. */ int lcaf_addr_set_mc(lcaf_addr_t *lcaf, lisp_addr_t *src, lisp_addr_t *grp, uint8_t splen, uint8_t gplen, uint32_t iid) { mc_t *mc; if (get_addr_(lcaf)) { lcaf_addr_del_addr(lcaf); } mc = mc_type_init(src, grp, splen, gplen, iid); lcaf_addr_set_type(lcaf, LCAF_MCAST_INFO); lcaf_addr_set_addr(lcaf, mc); return(GOOD); } lisp_addr_t * lisp_addr_build_mc(lisp_addr_t *src, lisp_addr_t *grp) { lisp_addr_t *mceid; uint8_t mlen; mlen = (lisp_addr_ip_afi(src) == AF_INET) ? 32 : 128; mceid = lisp_addr_new_lafi(LM_AFI_LCAF); lcaf_addr_set_mc(lisp_addr_get_lcaf(mceid), src, grp, mlen, mlen, 0); return(mceid); } inline int lisp_addr_is_mcinfo(lisp_addr_t *addr) { return(lisp_addr_lafi(addr) == LM_AFI_LCAF && lisp_addr_lcaf_type(addr) == LCAF_MCAST_INFO); } lisp_addr_t * mc_type_get_ip_addr (void *mc) { lisp_addr_t *addr = mc_type_get_src((mc_t*)(mc)); return(lisp_addr_get_ip_addr(addr)); } lisp_addr_t * mc_type_get_ip_pref_addr (void *mc) { lisp_addr_t *addr = mc_type_get_src((mc_t*)(mc)); return(lisp_addr_get_ip_pref_addr(addr)); } /* * iid_addr_t functions */ inline iid_t * iid_type_new() { iid_t *iid; iid = xzalloc(sizeof(iid_t)); iid->iidaddr = lisp_addr_new(); return(iid); } iid_t * iid_type_new_init(int iid, lisp_addr_t *addr, uint8_t mlen) { iid_t *iidt = iid_type_new(); iidt->iid = iid; lisp_addr_copy(iidt->iidaddr, addr); iidt->mlen = mlen; return(iidt); } inline void iid_type_del(void *iid) { lisp_addr_del(iid_type_get_addr((iid_t *)iid)); free(iid); iid = NULL; } inline uint8_t iid_type_get_mlen(iid_t *iid) { assert(iid); return(iid->mlen); } inline uint32_t lcaf_iid_get_iid(lcaf_addr_t *iid) { return(iid_type_get_iid(get_addr_(iid))); } inline uint32_t iid_type_get_iid(iid_t *iid) { assert(iid); return(iid->iid); } inline lisp_addr_t * iid_type_get_addr(void *iid) { assert(iid); return(((iid_t *)iid)->iidaddr); } inline void iid_type_set_iid(iid_t *iidt, uint32_t iid) { assert(iidt); iidt->iid = iid; } inline void iid_type_set_addr(iid_t *iidt, lisp_addr_t *iidaddr) { assert(iidt); assert(iidaddr); lisp_addr_copy (iidt->iidaddr,iidaddr); } inline void iid_type_set_mlen(iid_t *iid, uint8_t mlen) { assert(iid); iid->mlen = mlen; } inline int iid_type_cmp(void *iid1, void *iid2) { if ((iid_type_get_iid((iid_t *)iid1) != iid_type_get_iid((iid_t *)iid2))) return( (iid_type_get_iid((iid_t *)iid1) > iid_type_get_iid((iid_t *)iid2)) ? 1: 2); if ((iid_type_get_mlen((iid_t *)iid1) != iid_type_get_mlen((iid_t *)iid2))) return((iid_type_get_mlen((iid_t *)iid1) > iid_type_get_mlen((iid_t *)iid2)) ? 1 :2); return(lisp_addr_cmp(iid_type_get_addr((iid_t *)iid1), iid_type_get_addr((iid_t *)iid2))); } int iid_type_get_size_to_write(void *iid) { return( sizeof(lcaf_iid_hdr_t)+ lisp_addr_size_to_write(iid_type_get_addr(iid))); } inline int iid_type_write_to_pkt(uint8_t *offset, void *iid) { int len; uint8_t *cur_ptr = offset; ((lcaf_iid_hdr_t *)cur_ptr)->afi = htons(LISP_AFI_LCAF); ((lcaf_iid_hdr_t *)cur_ptr)->rsvd1 = 0; ((lcaf_iid_hdr_t *)cur_ptr)->flags = 0; ((lcaf_iid_hdr_t *)cur_ptr)->type = LCAF_IID; ((lcaf_iid_hdr_t *)cur_ptr)->mlen = iid_type_get_mlen(iid); ((lcaf_iid_hdr_t *)cur_ptr)->iid = htonl(iid_type_get_iid(iid)); offset = CO(offset, sizeof(lcaf_iid_hdr_t)); len = lisp_addr_write(offset, iid_type_get_addr(iid)); ((lcaf_iid_hdr_t *)cur_ptr)->len = htons(len + sizeof(uint32_t)); len += sizeof(lcaf_iid_hdr_t); return(len); } int iid_type_parse(uint8_t *offset, void **iid) { int len; *iid = iid_type_new(); iid_type_set_mlen(*iid, ((lcaf_iid_hdr_t *)offset)->mlen); iid_type_set_iid(*iid, ntohl(((lcaf_iid_hdr_t *)offset)->iid)); offset = CO(offset, sizeof(lcaf_iid_hdr_t)); len = lisp_addr_parse(offset, iid_type_get_addr(*iid)) + sizeof(lcaf_iid_hdr_t); return(len); } char * iid_type_to_char(void *iid) { static char buf[10][INET6_ADDRSTRLEN*2+4]; static unsigned int i = 0; i++; i = i % 10; *buf[i] = '\0'; snprintf(buf[i],sizeof(buf[i]),"(IID %d/%d, EID %s)", iid_type_get_iid(iid), iid_type_get_mlen(iid), lisp_addr_to_char(iid_type_get_addr(iid))); return(buf[i]); } void iid_type_copy(void **dst, void *src) { if (!(*dst)){ *dst = iid_type_new_init( iid_type_get_iid((iid_t *)src), iid_type_get_addr((iid_t *)src), iid_type_get_mlen(src)); }else{ lisp_addr_copy(iid_type_get_addr((iid_t *)*dst), iid_type_get_addr((iid_t *)src)); iid_type_set_iid((iid_t *)*dst, iid_type_get_iid((iid_t *)src)); iid_type_set_mlen((iid_t*)*dst, iid_type_get_mlen(src)); } } lisp_addr_t * iid_type_get_ip_addr(void *iid) { return (lisp_addr_get_ip_addr(((iid_t *)iid)->iidaddr)); } lisp_addr_t * iid_type_get_ip_pref_addr(void *iid) { return (lisp_addr_get_ip_pref_addr(((iid_t *)iid)->iidaddr)); } inline int lisp_addr_is_iid(lisp_addr_t *addr) { return(lisp_addr_lafi(addr) == LM_AFI_LCAF && lisp_addr_lcaf_type(addr) == LCAF_IID); } void lcaf_iid_init(lcaf_addr_t *iidaddr, int iid, lisp_addr_t *addr, uint8_t mlen) { if (!iidaddr->addr){ lcaf_addr_del_addr(iidaddr); } iidaddr->type = LCAF_IID; iidaddr->addr = iid_type_new_init(iid, addr, mlen); } inline lisp_addr_t * lisp_addr_new_init_iid(int iid, lisp_addr_t *addr, uint8_t mlen) { lisp_addr_t *iid_addr; iid_addr = lisp_addr_new_lafi(LM_AFI_LCAF); lcaf_iid_init(&iid_addr->lcaf, iid, addr,mlen); return (iid_addr); } /* * geo_addr_t functions */ inline geo_t * geo_type_new() { geo_t *geo; geo = (geo_t *)calloc(1, sizeof(geo_t)); geo->addr = lisp_addr_new(); return(geo); } inline void geo_type_del(void *geo) { lisp_addr_del(geo_type_get_addr((geo_t *)geo)); free(geo); } inline void geo_type_set_addr(geo_t *geo, lisp_addr_t *addr) { assert(addr); assert(geo); lisp_addr_copy(geo->addr, addr); } inline void geo_type_set_lat(geo_t *geo, uint8_t dir, uint16_t deg, uint8_t min, uint8_t sec) { assert(geo); geo->latitude.dir = dir; geo->latitude.deg = deg; geo->latitude.min = min; geo->latitude.sec = sec; } inline void geo_type_set_long(geo_t *geo, uint8_t dir, uint16_t deg, uint8_t min, uint8_t sec) { assert(geo); geo->longitude.dir = dir; geo->longitude.deg = deg; geo->longitude.min = min; geo->longitude.sec = sec; } inline void geo_type_set_lat_from_coord(geo_t *geo, geo_coordinates *coord) { assert(geo); geo->latitude.dir = coord->dir; geo->latitude.deg = coord->deg; geo->latitude.min = coord->min; geo->latitude.sec = coord->sec; } inline void geo_type_set_long_from_coord(geo_t *geo, geo_coordinates *coord) { assert(geo); geo->longitude.dir = coord->dir; geo->longitude.deg = coord->deg; geo->longitude.min = coord->min; geo->longitude.sec = coord->sec; } inline void geo_type_set_altitude(geo_t *geo, uint32_t altitude) { assert(geo); geo->altitude = altitude; } inline geo_coordinates * geo_type_get_lat(geo_t *geo) { assert(geo); return(&(geo->latitude)); } inline geo_coordinates * geo_type_get_long(geo_t *geo) { assert(geo); return(&(geo->longitude)); } inline uint32_t geo_type_get_altitude(geo_t *geo) { assert(geo); return(geo->altitude); } inline int geo_type_parse(uint8_t *offset, void **geo) { *geo = geo_type_new(); geo_type_set_lat(*geo, ((lcaf_geo_hdr_t *)offset)->latitude_dir, ((lcaf_geo_hdr_t *)offset)->latitude_deg, ((lcaf_geo_hdr_t *)offset)->latitude_min, ((lcaf_geo_hdr_t *)offset)->latitude_sec); geo_type_set_long(*geo, ((lcaf_geo_hdr_t *)offset)->longitude_dir, ((lcaf_geo_hdr_t *)offset)->longitude_deg, ((lcaf_geo_hdr_t *)offset)->longitude_min, ((lcaf_geo_hdr_t *)offset)->longitude_sec); geo_type_set_altitude(*geo, ((lcaf_geo_hdr_t *)offset)->altitude); offset = CO(offset, sizeof(lcaf_geo_hdr_t)); return(sizeof(lcaf_geo_hdr_t) + lisp_addr_parse(offset, geo_type_get_addr(*geo))); } inline lisp_addr_t * geo_type_get_addr(geo_t *geo) { return(geo->addr); } char * geo_type_to_char(void *geo) { static char buf[10][INET6_ADDRSTRLEN*2+4]; static unsigned int i = 0; i++; i = i % 10; *buf[i] = '\0'; snprintf(buf[i],sizeof(buf[i]),"(latitude: %s | longitude: %s | altitude: %d, EID %s)", geo_coord_to_char(geo_type_get_lat(geo)), geo_coord_to_char(geo_type_get_long(geo)), geo_type_get_altitude(geo), lisp_addr_to_char(geo_type_get_addr(geo))); return(buf[i]); } char * geo_coord_to_char(geo_coordinates *coord) { static char buf[INET6_ADDRSTRLEN*2+4]; *buf= '\0'; snprintf(buf,sizeof(buf), "dir %d deg %d min %d sec %d", coord->dir, coord->deg, coord->min, coord->sec); return(buf); } void geo_type_copy(void **dst, void *src) { assert(src); if(!(*dst)) *dst = geo_type_new(); geo_type_set_lat_from_coord((geo_t *)*dst, geo_type_get_lat(src)); geo_type_set_long_from_coord((geo_t *)*dst, geo_type_get_long(src)); geo_type_set_altitude((geo_t *)*dst, geo_type_get_altitude(src)); lisp_addr_copy(geo_type_get_addr((geo_t *)*dst), geo_type_get_addr(src)); } /* * nat_addr_t functions */ inline nat_t * nat_type_new() { nat_t *nat; nat = (nat_t*)xzalloc(sizeof(nat_t)); nat->ms_addr = lisp_addr_new(); nat->etr_pub_addr = lisp_addr_new(); nat->etr_prv_addr = lisp_addr_new(); nat->rtr_addr_lst = glist_new_managed((glist_del_fct)lisp_addr_del); return (nat); } nat_t * nat_type_new_init(uint16_t ms_port, lisp_addr_t *ms_addr, uint16_t etr_pub_port, lisp_addr_t *etr_pub_addr, lisp_addr_t *etr_prv_addr, glist_t *rtr_addr_lst) { nat_t *nat; nat = (nat_t*)xzalloc(sizeof(nat_t)); nat->ms_port = ms_port; nat->etr_pub_port = etr_pub_port; nat->ms_addr = lisp_addr_clone(ms_addr); nat->etr_pub_addr = lisp_addr_clone(etr_pub_addr); nat->etr_prv_addr = lisp_addr_clone(etr_prv_addr); nat->rtr_addr_lst = glist_clone(rtr_addr_lst, (glist_clone_obj)lisp_addr_clone); glist_set_del_fct(nat->rtr_addr_lst, (glist_del_fct)lisp_addr_del); return (nat); } inline void nat_type_del(void *nat) { lisp_addr_del(((nat_t *)nat)->ms_addr); lisp_addr_del(((nat_t *)nat)->etr_pub_addr); lisp_addr_del(((nat_t *)nat)->etr_prv_addr); glist_destroy(((nat_t *)nat)->rtr_addr_lst); free (nat); nat = NULL; } inline uint16_t nat_type_get_ms_port(nat_t *nat) { return (nat->ms_port); } inline uint16_t nat_type_get_etr_pub_port(nat_t *nat) { return (nat->etr_pub_port); } inline lisp_addr_t * nat_type_get_ms_addr(nat_t *nat) { return(nat->ms_addr); } inline lisp_addr_t * nat_type_get_etr_pub_addr(nat_t *nat) { return(nat->etr_pub_addr); } inline lisp_addr_t * nat_type_get_etr_priv_addr(nat_t *nat) { return(nat->etr_prv_addr); } inline glist_t * nat_type_get_rtr_addr_lst(nat_t *nat) { return(nat->rtr_addr_lst); } inline void nat_type_set_ms_port(nat_t *nat, uint16_t ms_port) { nat->ms_port = ms_port; } inline void nat_type_set_etr_pub_port(nat_t *nat, uint16_t etr_pub_port) { nat->etr_pub_port = etr_pub_port; } inline void nat_type_set_ms_addr(nat_t *nat, lisp_addr_t * ms_addr) { lisp_addr_copy(nat->ms_addr,ms_addr); } inline void nat_type_set_etr_pub_addr(nat_t *nat, lisp_addr_t * etr_pub_addr) { lisp_addr_copy(nat->etr_pub_addr, etr_pub_addr); } inline void nat_type_set_etr_priv_addr(nat_t *nat, lisp_addr_t * etr_prv_addr){ lisp_addr_copy(nat->etr_prv_addr, etr_prv_addr); } inline void nat_type_set_rtr_addr_lst(nat_t *nat, glist_t * rtr_addr_lst) { glist_destroy(nat->rtr_addr_lst); nat->rtr_addr_lst = glist_clone(rtr_addr_lst, (glist_clone_obj)lisp_addr_clone); glist_set_del_fct(nat->rtr_addr_lst, (glist_del_fct)lisp_addr_del); } inline int nat_type_cmp(void *nat1, void *nat2) { glist_entry_t *it_rtr; lisp_addr_t *rtr_addr; nat_t *n1 = (nat_t*)nat1; nat_t *n2 = (nat_t*)nat2; int ret = 0; if ((ret = lisp_addr_cmp(n1->etr_pub_addr,n2->etr_pub_addr)) != 0){ return (ret); } if ((ret = lisp_addr_cmp(n1->etr_prv_addr,n2->etr_prv_addr)) != 0){ return (ret); } if ((ret = lisp_addr_cmp(n1->ms_addr,n2->ms_addr)) != 0){ return (ret); } if (n1->etr_pub_port != n2->etr_pub_port){ return (n1->etr_pub_port > n2->etr_pub_port ? 1 : 2); } if (glist_size(n1->rtr_addr_lst) != glist_size(n2->rtr_addr_lst)){ return (glist_size(n1->rtr_addr_lst) > glist_size(n2->rtr_addr_lst) ? 1 : 2); } glist_for_each_entry(it_rtr,n1->rtr_addr_lst){ rtr_addr = (lisp_addr_t *)glist_entry_data(it_rtr); if (glist_contain_using_cmp_fct(rtr_addr, n1->rtr_addr_lst,(glist_cmp_fct)lisp_addr_cmp) != 0){ return (1); } } if (n1->ms_port != n2->ms_port){ return (n1->ms_port > n2->ms_port ? 1 : 2); } return (0); } int nat_type_get_size_to_write(void *nat) { uint32_t len; nat_t *nat_addr = (nat_t *)nat; glist_entry_t *it_rtr; len = sizeof (lcaf_nat_hdr_t); len += lisp_addr_size_to_write(nat_addr->etr_pub_addr); len += lisp_addr_size_to_write(nat_addr->ms_addr); len += lisp_addr_size_to_write(nat_addr->etr_prv_addr); glist_for_each_entry(it_rtr, nat_addr->rtr_addr_lst) { len += lisp_addr_size_to_write((lisp_addr_t *)glist_entry_data(it_rtr)); } return (len); } int nat_type_write_to_pkt(uint8_t *offset, void *nat) { uint32_t len, addrlen; uint8_t *cur_ptr = offset; nat_t *nat_addr = (nat_t *)nat; glist_entry_t *it_rtr; ((lcaf_nat_hdr_t*)cur_ptr)->afi = htons(LISP_AFI_LCAF); ((lcaf_nat_hdr_t*)cur_ptr)->flags = 0; ((lcaf_nat_hdr_t*)cur_ptr)->rsvd1 = 0; ((lcaf_nat_hdr_t*)cur_ptr)->rsvd2 = 0; ((lcaf_nat_hdr_t*)cur_ptr)->type = LCAF_NATT; NAT_MS_PORT(cur_ptr) = htons(nat_addr->ms_port); NAT_ETR_PORT(cur_ptr) = htons(nat_addr->etr_pub_port); len = sizeof (lcaf_nat_hdr_t); cur_ptr = CO(cur_ptr, sizeof(lcaf_nat_hdr_t)); addrlen = lisp_addr_write(cur_ptr, nat_addr->etr_pub_addr); if (addrlen <=0) return(BAD); len += addrlen; cur_ptr = CO(cur_ptr, addrlen); addrlen = lisp_addr_write(cur_ptr, nat_addr->ms_addr); if (addrlen <=0) return(BAD); len += addrlen; cur_ptr = CO(cur_ptr, addrlen); addrlen = lisp_addr_write(cur_ptr, nat_addr->etr_prv_addr); if (addrlen <=0) return(BAD); len += addrlen; cur_ptr = CO(cur_ptr, addrlen); glist_for_each_entry(it_rtr, nat_addr->rtr_addr_lst) { addrlen = lisp_addr_write(cur_ptr, (lisp_addr_t *)glist_entry_data(it_rtr)); if (addrlen <=0) return(BAD); len += addrlen; cur_ptr = CO(cur_ptr, addrlen); } /* length is only what follows the first 8 bytes of the lcaf hdr */ ((lcaf_hdr_t*)offset)->len = htons(len-sizeof(lcaf_hdr_t)); return (len); } int nat_type_parse(uint8_t *offset, void **nat) { int totallen, readlen, len; nat_t *nat_addr; lisp_addr_t *rtr_addr; *nat = nat_type_new(); nat_addr = *nat; totallen = ntohs((NAT_LEN(offset))) + sizeof(lcaf_hdr_t); nat_addr->ms_port = NAT_MS_PORT(offset); nat_addr->etr_pub_port = NAT_ETR_PORT(offset); readlen = sizeof(lcaf_nat_hdr_t); offset = CO(offset, readlen); len = lisp_addr_parse(offset, nat_addr->etr_pub_addr); if (len <= 0){ goto err; } readlen += len; offset = CO(offset, len); len = lisp_addr_parse(offset, nat_addr->ms_addr); if (len <= 0){ goto err; } readlen += len; offset = CO(offset, len); len = lisp_addr_parse(offset, nat_addr->etr_prv_addr); if (len <= 0){ goto err; } readlen += len; offset = CO(offset, len); while (totallen > readlen){ rtr_addr = lisp_addr_new(); len = lisp_addr_parse(offset, rtr_addr); if (len <= 0){ goto err; } readlen += len; offset = CO(offset, len); glist_add_tail(rtr_addr,nat_addr->rtr_addr_lst); } return (readlen); err: nat_type_del(nat_addr); return (BAD); } char * nat_type_to_char(void *nat) { static char buf[5][500]; size_t buf_size = sizeof(buf[0]); static unsigned int i = 0; nat_t *nat_addr = (nat_t *)nat; int j = 0; glist_entry_t * it_rtr; i++; i = i % 5; *buf[i] = '\0'; snprintf(buf[i],buf_size, "ETR Pub: %s:%d, ETR Prv: %s, MS: %s:%d - RTR list:", lisp_addr_to_char(nat_addr->etr_pub_addr),nat_addr->etr_pub_port, lisp_addr_to_char(nat_addr->etr_prv_addr),lisp_addr_to_char(nat_addr->ms_addr), nat_addr->ms_port); glist_for_each_entry(it_rtr, nat_addr->rtr_addr_lst) { j++; snprintf(buf[i]+strlen(buf[i]),buf_size - strlen(buf[i]), "[%d] %s ", j, lisp_addr_to_char((lisp_addr_t *)glist_entry_data(it_rtr))); } return(buf[i]); } void nat_type_copy(void **dst, void *src) { nat_t *snat_addr, *dnat_addr; glist_entry_t *rtr_it; lisp_addr_t *rtr_addr; if (!*dst){ *dst = nat_type_new(); } dnat_addr = (nat_t *)(*dst); snat_addr = (nat_t *)src; dnat_addr->etr_pub_port = snat_addr->etr_pub_port; dnat_addr->ms_port = snat_addr->ms_port; lisp_addr_copy(dnat_addr->etr_pub_addr, snat_addr->etr_pub_addr); lisp_addr_copy(dnat_addr->ms_addr, snat_addr->ms_addr); lisp_addr_copy(dnat_addr->etr_prv_addr, snat_addr->etr_prv_addr); glist_remove_all(dnat_addr->rtr_addr_lst); glist_for_each_entry(rtr_it, snat_addr->rtr_addr_lst) { rtr_addr = lisp_addr_clone((lisp_addr_t *)glist_entry_data(rtr_it)); glist_add(rtr_addr,dnat_addr->rtr_addr_lst); } } lisp_addr_t * nat_type_get_ip_addr(void *nat) { return (lisp_addr_get_ip_addr(((nat_t *)nat)->etr_prv_addr)); } lisp_addr_t * nat_type_get_ip_pref_addr(void *nat) { return (lisp_addr_get_ip_pref_addr(((nat_t *)nat)->etr_prv_addr)); } void lcaf_nat_init(lcaf_addr_t *nat_addr, uint16_t ms_port, lisp_addr_t *ms_addr, uint16_t etr_pub_port, lisp_addr_t *etr_pub_addr, lisp_addr_t *etr_prv_addr, glist_t *rtr_addr_lst) { if (!nat_addr->addr){ lcaf_addr_del_addr(nat_addr); } nat_addr->type = LCAF_NATT; nat_addr->addr = nat_type_new_init(ms_port, ms_addr, etr_pub_port, etr_pub_addr, etr_prv_addr, rtr_addr_lst); } inline int lisp_addr_is_nat(lisp_addr_t *addr) { return (lisp_addr_is_lcaf(addr) && lisp_addr_lcaf_type(addr) == LCAF_NATT); } lisp_addr_t * lisp_addr_new_init_nat(uint16_t ms_port, lisp_addr_t *ms_addr, uint16_t etr_pub_port, lisp_addr_t *etr_pub_addr, lisp_addr_t *etr_prv_addr, glist_t *rtr_addr_lst) { lisp_addr_t *nat_addr; nat_addr = lisp_addr_new_lafi(LM_AFI_LCAF); lcaf_nat_init(&nat_addr->lcaf,ms_port,ms_addr,etr_pub_port,etr_pub_addr, etr_prv_addr,rtr_addr_lst); return (nat_addr); } /* * elp_addr_t functions */ lisp_addr_t * lisp_addr_elp_new() { lisp_addr_t *address = NULL; elp_t *elp_list = NULL; elp_list = elp_type_new(); if(elp_list == NULL){ return (NULL); } address = lisp_addr_new_lafi(LM_AFI_LCAF); if (address == NULL){ elp_type_del(elp_list); return (NULL); } lisp_addr_lcaf_set_type(address, LCAF_EXPL_LOC_PATH); lisp_addr_lcaf_set_addr(address, elp_list); return (address); } inline elp_t * lcaf_elp_get_elp(lcaf_addr_t *elp) { return((elp_t *)(get_addr_(elp))); } elp_t * elp_type_new() { elp_t *elp; elp = xzalloc(sizeof(elp_t)); elp->nodes = glist_new_managed((glist_del_fct)elp_node_del); return(elp); } void elp_type_del(void *elp) { glist_destroy(((elp_t *)elp)->nodes); free(elp); } int elp_type_get_size_to_write(void *elp) { glist_entry_t *it = NULL; elp_node_t *node = NULL; uint32_t len = 0; len += sizeof(lcaf_hdr_t); glist_for_each_entry(it, ((elp_t *)elp)->nodes) { node = glist_entry_data(it); len += sizeof(elp_node_flags) + lisp_addr_size_to_write(node->addr); } return(len); } int elp_type_write_to_pkt(uint8_t *offset, void *elp) { uint32_t len = 0, addrlen; elp_node_t *node = NULL; uint8_t *cur_ptr = NULL; glist_entry_t *it = NULL; cur_ptr = offset; ((lcaf_hdr_t*)cur_ptr)->afi = htons(LISP_AFI_LCAF); ((lcaf_hdr_t*)cur_ptr)->flags = 0; ((lcaf_hdr_t*)cur_ptr)->rsvd1 = 0; ((lcaf_hdr_t*)cur_ptr)->rsvd2 = 0; ((lcaf_hdr_t*)cur_ptr)->type = LCAF_EXPL_LOC_PATH; len += sizeof(lcaf_hdr_t); cur_ptr = CO(cur_ptr, sizeof(lcaf_hdr_t)); glist_for_each_entry(it, ((elp_t *)elp)->nodes) { node = glist_entry_data(it); ((elp_node_flags *)cur_ptr)->L = node->L; ((elp_node_flags *)cur_ptr)->P = node->P; ((elp_node_flags *)cur_ptr)->S = node->S; ((elp_node_flags *)cur_ptr)->rsvd1 = 0; ((elp_node_flags *)cur_ptr)->rsvd2 = 0; cur_ptr = CO(cur_ptr, sizeof(elp_node_flags)); addrlen = lisp_addr_write(cur_ptr, node->addr); if (addrlen <=0) return(BAD); cur_ptr = CO(cur_ptr, addrlen); len += sizeof(elp_node_flags) + addrlen; } /* length is only what follows the first 8 bytes of the lcaf hdr */ ((lcaf_hdr_t*)offset)->len = htons(len-sizeof(lcaf_hdr_t)); return(len); } int elp_type_parse(uint8_t *offset, void **elp) { int len = 0, totallen = 0, readlen=0; elp_node_t *enode = NULL; elp_node_flags *flags = NULL; elp_t *elp_ptr = NULL; *elp = elp_type_new(); elp_ptr = *elp; totallen = ntohs(((lcaf_hdr_t *)offset)->len); readlen = sizeof(lcaf_hdr_t); offset = CO(offset, sizeof(lcaf_hdr_t)); while(totallen > 0) { enode = calloc(1, sizeof(elp_node_t)); flags = (elp_node_flags *)offset; enode->L = flags->L; enode->P = flags->P; enode->S = flags->S; offset = CO(offset, sizeof(elp_node_flags)); enode->addr = lisp_addr_new(); len = lisp_addr_parse(offset, enode->addr); if (len <= 0) goto err; offset = CO(offset, len); totallen = totallen - sizeof(elp_node_flags) - len; readlen += sizeof(elp_node_flags) + len; glist_add_tail(enode, elp_ptr->nodes); } if (totallen !=0) OOR_LOG(LDBG_1, "elp_type_read_from_pkt: Error encountered!"); return(readlen); err: glist_destroy(elp_ptr->nodes); return(BAD); } char * elp_type_to_char(void *elp) { static char buf[5][500]; size_t buf_size = sizeof(buf[0]); static unsigned int i = 0; int j = 0; glist_entry_t * it = NULL; elp_node_t * node = NULL; i++; i = i % 5; *buf[i] = '\0'; sprintf(buf[i], "ELP:"); glist_for_each_entry(it, ((elp_t *)elp)->nodes) { j++; node = (elp_node_t *)glist_entry_data(it); // sprintf(buf[i]+strlen(buf[i]), "[%d] %s f: %s%s%s", j, lisp_addr_to_char(node->addr), // (node->L) ? "L" : "l", (node->P) ? "P" : "p", (node->S) ? "S" : "s"); snprintf(buf[i]+strlen(buf[i]), buf_size - strlen(buf[i]), "[%d] %s ", j, lisp_addr_to_char(node->addr)); } return(buf[i]); } elp_node_t * elp_node_clone(elp_node_t *sen) { elp_node_t *en = xzalloc(sizeof(elp_node_t)); en->L = sen->L; en->P = sen->P; en->S = sen->S; en->addr = lisp_addr_clone(sen->addr); return(en); } void elp_type_copy(void **dst, void *src) { elp_t *elp_ptr = NULL; elp_node_t *node = NULL; elp_node_t *cp_node = NULL; glist_entry_t *it = NULL; if (!*dst){ *dst = elp_type_new(); } elp_ptr = *dst; glist_for_each_entry(it, ((elp_t *)src)->nodes) { node = (elp_node_t *)glist_entry_data(it); cp_node = elp_node_clone(node); glist_add_tail(cp_node, elp_ptr->nodes); } } int elp_type_cmp(void *elp1, void *elp2) { elp_node_t *node1 = NULL; elp_node_t *node2 = NULL; glist_entry_t *it1 = NULL; glist_entry_t *it2 = NULL; int ret = 0; if (glist_size (((elp_t*)elp1)->nodes) != glist_size (((elp_t*)elp1)->nodes)){ return (1); } it1 = glist_first(((elp_t*)elp1)->nodes); it2 = glist_first(((elp_t*)elp2)->nodes); while(it1 != glist_head(((elp_t*)elp1)->nodes) && it2 != glist_head(((elp_t*)elp2)->nodes)) { node1 = glist_entry_data(it1); node2 = glist_entry_data(it2); if ((ret = lisp_addr_cmp(node1->addr, node2->addr)) != 0){ if (ret < 0){ return (lisp_addr_cmp_afi(node1->addr,node2->addr)); } return (ret); } if (node1->L != node2->L || node1->S != node2->S || node1->P != node2->P) return(1); it1 = glist_prev(it1); it2 = glist_prev(it2); } return(0); } inline elp_node_t * elp_node_new_init(lisp_addr_t *addr, uint8_t lookup, uint8_t rloc_probe, uint8_t strict) { elp_node_t *node = NULL; node = xzalloc(sizeof(elp_node_t)); if (node == NULL){ return (NULL); } node->addr = lisp_addr_clone(addr); node->L = lookup; node->P = rloc_probe; node->S = strict; return (node); } inline lisp_addr_t * elp_node_addr(elp_node_t *enode) { return (enode->addr); } inline void elp_node_del(elp_node_t *enode) { lisp_addr_del(enode->addr); free(enode); enode = NULL; } inline void elp_add_node(elp_t *elp, elp_node_t *enode) { if (!elp->nodes) elp->nodes = glist_new_managed((glist_del_fct)elp_node_del); glist_add_tail(enode, elp->nodes); } inline glist_t * lcaf_elp_node_list(lcaf_addr_t *lcaf) { return(((elp_t *)lcaf->addr)->nodes); } inline int lisp_addr_is_elp(lisp_addr_t *addr) { return(lisp_addr_lafi(addr) == LM_AFI_LCAF && lisp_addr_lcaf_type(addr) == LCAF_EXPL_LOC_PATH); } lisp_addr_t * elp_type_get_ip_addr(void *elp) { elp_node_t *elp_node = NULL; lisp_addr_t *addr = NULL; elp_node = (elp_node_t *)glist_last_data(((elp_t *)elp)->nodes); if (elp_node == NULL){ return (NULL); } addr = elp_node->addr; return (lisp_addr_get_ip_addr(addr)); } /* * rle_addr_t functions */ inline rle_t * rle_type_new() { rle_t *rle = xzalloc(sizeof(rle_t)); rle->nodes = glist_new_managed((glist_del_fct)rle_node_del); return(rle); } inline void rle_type_del(void *rleaddr) { if (!rleaddr) { return; } glist_destroy(((rle_t *)rleaddr)->nodes); free(rleaddr); rleaddr = NULL; } int rle_type_parse(uint8_t *offset, void **rle) { int len = 0, totallen = 0, readlen = 0; rle_node_t *rnode = NULL; rle_node_hdr_t *rhdr = NULL; rle_t *rle_ptr = NULL; *rle = rle_type_new(); rle_ptr = *rle; totallen = ntohs(((lcaf_hdr_t *)offset)->len); readlen = sizeof(lcaf_hdr_t); offset = CO(offset, sizeof(lcaf_hdr_t)); while (totallen > 0) { rnode = xzalloc(sizeof(rle_node_t)); rhdr = (rle_node_hdr_t *)offset; rnode->level = rhdr->level; offset = CO(offset, sizeof(rle_node_hdr_t)); rnode->addr = lisp_addr_new(); len = lisp_addr_parse(offset, rnode->addr); if (len <= 0) { goto err; } offset = CO(offset, len); totallen = totallen - sizeof(rle_node_hdr_t) -len; readlen += sizeof(rle_node_hdr_t) + len; glist_add_tail(rnode, rle_ptr->nodes); } if (totallen !=0) { OOR_LOG(LDBG_1, "rle_type_read_from_pkt: Error encountered!"); } return(readlen); err: glist_destroy(rle_ptr->nodes); return(BAD); } int rle_type_write_to_pkt(uint8_t *offset, void *rle) { uint32_t len = 0, addrlen; rle_node_t *node = NULL; uint8_t *cur_ptr = NULL; glist_entry_t *it = NULL; cur_ptr = offset; ((lcaf_hdr_t*)cur_ptr)->afi = htons(LISP_AFI_LCAF); ((lcaf_hdr_t*)cur_ptr)->flags = 0; ((lcaf_hdr_t*)cur_ptr)->rsvd1 = 0; ((lcaf_hdr_t*)cur_ptr)->rsvd2 = 0; ((lcaf_hdr_t*)cur_ptr)->type = LCAF_RLE; len += sizeof(lcaf_hdr_t); cur_ptr = CO(cur_ptr, sizeof(lcaf_hdr_t)); glist_for_each_entry(it, ((rle_t *)rle)->nodes) { node = glist_entry_data(it); ((rle_node_hdr_t *)cur_ptr)->level = node->level; memset(((rle_node_hdr_t *)cur_ptr)->rsvd, 0, 3*sizeof(uint8_t)); cur_ptr = CO(cur_ptr, sizeof(rle_node_hdr_t)); addrlen = lisp_addr_write(cur_ptr, node->addr); if (addrlen <=0) return(BAD); cur_ptr = CO(cur_ptr, addrlen); len += sizeof(rle_node_hdr_t) + addrlen; } /* length is only what follows the first 8 bytes of the lcaf hdr */ ((lcaf_hdr_t*)offset)->len = htons(len-sizeof(lcaf_hdr_t)); return(len); } int rle_type_get_size_to_write(void *rle) { glist_entry_t *it = NULL; rle_node_t *node = NULL; uint32_t len = 0; len += sizeof(lcaf_hdr_t); glist_for_each_entry(it, ((rle_t *)rle)->nodes) { node = glist_entry_data(it); len += sizeof(rle_node_hdr_t) + lisp_addr_size_to_write(node->addr); } return(len); } char * rle_type_to_char(void *rle) { static char buf[3][500]; size_t buf_size = sizeof(buf[0]); static unsigned int i = 0; int j = 0; glist_entry_t * it = NULL; rle_node_t * node = NULL; i++; i = i % 10; *buf[i] = '\0'; sprintf(buf[i], "RLE:"); glist_for_each_entry(it, ((rle_t *)rle)->nodes) { j++; node = glist_entry_data(it); snprintf(buf[i]+strlen(buf[i]),buf_size - strlen(buf[i]), "[%d] %s ", node->level, lisp_addr_to_char(node->addr)); } return(buf[i]); } rle_node_t * rle_node_clone(rle_node_t *srn) { rle_node_t *rn = xzalloc(sizeof(rle_node_t)); rn->level = srn->level; rn->addr = lisp_addr_clone(srn->addr); return(rn); } inline rle_node_t * rle_node_new() { rle_node_t *rnode = xzalloc(sizeof(rle_node_t)); rnode->addr = lisp_addr_new(); return(rnode); } inline void rle_node_del(rle_node_t *rnode) { lisp_addr_del(rnode->addr); free(rnode); rnode = NULL; } inline glist_t * lcaf_rle_node_list(lcaf_addr_t *lcaf) { return(((rle_t *)lcaf->addr)->nodes); } void rle_type_copy(void **dst, void *src) { rle_t *rle_ptr = NULL; rle_node_t *node = NULL; rle_node_t *cp_node = NULL; glist_entry_t *it = NULL; if (!*dst) { *dst = rle_type_new(); } rle_ptr = *dst; glist_for_each_entry(it, ((rle_t *)src)->nodes) { node = glist_entry_data(it); cp_node = rle_node_clone(node); glist_add_tail(cp_node, rle_ptr->nodes); } } int rle_type_cmp(void *rle1, void *rle2) { rle_node_t *node1 = NULL; rle_node_t *node2 = NULL; glist_entry_t *it1 = NULL; glist_entry_t *it2 = NULL; int ret = 0; it1 = glist_first(((rle_t*)rle1)->nodes); it2 = glist_first(((rle_t*)rle2)->nodes); while(it1 != glist_head(((rle_t*)rle1)->nodes) && it2 != glist_head(((rle_t*)rle2)->nodes)) { node1 = glist_entry_data(it1); node2 = glist_entry_data(it2); if (node1->level != node2->level) { /* nodes closer to ITR are "more important" */ return(node1->level < node2->level ? 1 : 2); } if ((ret = lisp_addr_cmp(node1->addr, node2->addr)) != 0) return(ret); it1 = glist_next(it1); it2 = glist_next(it2); } return(0); } /* * AFI-list type functions */ inline afi_list_t * afi_list_type_new() { afi_list_t *afi_list = xzalloc(sizeof(afi_list_t)); afi_list->list_addr = glist_new_managed((glist_del_fct)lisp_addr_del); return(afi_list); } void afi_list_type_del(void *afil) { glist_destroy(((afi_list_t *)afil)->list_addr); } int afi_list_type_get_size_to_write(void *afil) { int len = 0; lisp_addr_t *addr = NULL; glist_entry_t *it = NULL; len = sizeof(lcaf_afi_list_hdr_t); glist_for_each_entry(it, ((afi_list_t *)afil)->list_addr){ addr = (lisp_addr_t *)glist_entry_data(it); len += lisp_addr_size_to_write(addr); } return(len); } int afi_list_type_write_to_pkt(uint8_t *offset, void *afil) { lisp_addr_t *addr = NULL; glist_entry_t *it = NULL; uint8_t *cur_ptr = NULL; int len = 0, lenw = 0; cur_ptr = offset; ((lcaf_afi_list_hdr_t *)cur_ptr)->afi = htons(LISP_AFI_LCAF); ((lcaf_afi_list_hdr_t *)cur_ptr)->flags = 0; ((lcaf_afi_list_hdr_t *)cur_ptr)->rsvd1 = 0; ((lcaf_afi_list_hdr_t *)cur_ptr)->rsvd2 = 0; ((lcaf_afi_list_hdr_t *)cur_ptr)->type = LCAF_AFI_LIST; cur_ptr = CO(cur_ptr, sizeof(lcaf_afi_list_hdr_t)); glist_for_each_entry(it, ((afi_list_t *)afil)->list_addr){ addr = (lisp_addr_t *)glist_entry_data(it); lenw = lisp_addr_write(cur_ptr, addr); if (lenw <= 0) return(BAD); cur_ptr = CO(cur_ptr, lenw); } len = cur_ptr-offset; ((lcaf_afi_list_hdr_t *)cur_ptr)->length = htons(len-sizeof(lcaf_afi_list_hdr_t)); return(len); } int afi_list_type_parse(uint8_t *offset, void **afilptr) { lisp_addr_t *addr = NULL; afi_list_t *afil = NULL; uint8_t *cur_ptr = NULL; int len = 0, rlen = 0; cur_ptr = offset; afil = *afilptr; if (!afil){ if(!(afil = afi_list_type_new())) return(BAD); } len = ntohs(((lcaf_afi_list_hdr_t *)offset)->length); cur_ptr = CO(cur_ptr, sizeof(lcaf_afi_list_hdr_t)); while(len > 0) { addr = lisp_addr_new(); if (!addr) goto err; rlen = lisp_addr_parse(cur_ptr, addr); glist_add_tail(addr, afil->list_addr); if (rlen <= 0) goto err; cur_ptr = CO(cur_ptr, rlen); len -= rlen; } return(cur_ptr - offset); err: afi_list_type_del(afil); return(BAD); } char * afi_list_type_to_char(void *afil) { lisp_addr_t * addr = NULL; glist_entry_t * it = NULL; static char buf[3][500]; size_t buf_size = sizeof(buf[0]); static int i = 0; int j = 0; i++; i = i % 10; *buf[i] = '\0'; glist_for_each_entry(it, ((afi_list_t *)afil)->list_addr){ addr = (lisp_addr_t *)glist_entry_data(it); snprintf(buf[i]+strlen(buf[i]),buf_size - strlen(buf[i]), "AFI %d: %s", j, lisp_addr_to_char(addr)); j++; } return(buf[i]); } void afi_list_type_copy(void **dst, void *src) { lisp_addr_t *addr_src = NULL; lisp_addr_t *addr_dst = NULL; glist_entry_t *it = NULL; if (!*dst){ *dst = afi_list_type_new(); } glist_for_each_entry(it, ((afi_list_t *)src)->list_addr){ addr_src = (lisp_addr_t *)glist_entry_data(it); addr_dst = lisp_addr_clone(addr_src); glist_add_tail(addr_dst, ((afi_list_t *)(*dst))->list_addr); } } int afi_list_type_cmp(void *al1, void *al2) { glist_entry_t *it_addr1 = NULL; glist_entry_t *it_addr2 = NULL; lisp_addr_t *addr1 = NULL; lisp_addr_t *addr2 = NULL; glist_t *list1 = ((afi_list_t *)al1)->list_addr; glist_t *list2 = ((afi_list_t *)al2)->list_addr; int l1_size = glist_size (list1); int l2_size = glist_size (list2); if (l1_size > l2_size){ return (1); }else if (l1_size < l2_size){ return (2); } int ret = 0; it_addr2 = glist_first(((afi_list_t *)al2)->list_addr); glist_for_each_entry(it_addr1, ((afi_list_t *)al1)->list_addr){ addr1 = (lisp_addr_t *)glist_entry_data(it_addr1); addr2 = (lisp_addr_t *)glist_entry_data(it_addr2); ret = lisp_addr_cmp(addr1, addr2); if (ret!=0){ return(ret); } it_addr2 = glist_next(it_addr2); } return(0); } /* * Returns the first IPv4 or IPv6 address of the list */ lisp_addr_t * afi_list_type_get_ip_addr(void *afi_list) { glist_entry_t *it = NULL; lisp_addr_t *addr = NULL; lisp_addr_t *ip_addr = NULL; glist_for_each_entry(it, ((afi_list_t *)afi_list)->list_addr){ addr = (lisp_addr_t *)glist_entry_data(it); ip_addr = lisp_addr_get_ip_addr(addr); if (ip_addr != NULL){ // XXX Study if this behaviour is correct return (ip_addr); } } return (NULL); } /* * Returns the first IPv4 or IPv6 prefix of the list */ lisp_addr_t * afi_list_type_get_ip_pref_addr(void *afi_list) { glist_entry_t *it = NULL; lisp_addr_t *addr = NULL; lisp_addr_t *ip_pref = NULL; glist_for_each_entry(it, ((afi_list_t *)afi_list)->list_addr){ addr = (lisp_addr_t *)glist_entry_data(it); ip_pref = lisp_addr_get_ip_pref_addr(addr); if (ip_pref != NULL){ // XXX Study if this behaviour is correct return (ip_pref); } } return (NULL); } /* obtain IP address from LCAF */ lisp_addr_t * lcaf_get_ip_addr(lcaf_addr_t *lcaf) { if (!get_ip_addr_fcts[get_type_(lcaf)]) { OOR_LOG(LDBG_1, "lcaf_get_ip_addr: lcaf type %d not supported", get_type_(lcaf)); return (NULL); } return (*get_ip_addr_fcts[get_type_(lcaf)])(get_addr_(lcaf)); } /* obtain IP Prefix from LCAF */ lisp_addr_t * lcaf_get_ip_pref_addr(lcaf_addr_t *lcaf) { if (!get_ip_pref_addr_fcts[get_type_(lcaf)]) { OOR_LOG(LDBG_1, "lcaf_get_ip_pref_addr: lcaf type %d not supported", get_type_(lcaf)); return (NULL); } return (*get_ip_pref_addr_fcts[get_type_(lcaf)])(get_addr_(lcaf)); } /* Set IP address in LCAF RLOCs. When LCAFs are used as local locators, the * address that determines the interface to which the LCAF is associated, must * be updated to point to the interface, instead of being static */ int lcaf_rloc_set_ip_addr(lisp_addr_t *addr, lisp_addr_t *if_addr) { lcaf_addr_t *lcaf = lisp_addr_get_lcaf(addr); switch (lcaf_addr_get_type(lcaf)) { case LCAF_EXPL_LOC_PATH: { elp_node_t *enode; enode = ((elp_node_t *)glist_last_data(lcaf_elp_node_list(lcaf))); lisp_addr_del(enode->addr); enode->addr = if_addr; break; } case LCAF_RLE: { rle_node_t *rit = NULL, *rnode = NULL; int level = -1; glist_entry_t *it = NULL; /* Find the first highest level replication node */ glist_for_each_entry(it, lcaf_rle_node_list(lcaf)) { rit = glist_entry_data(it); if (rit->level > level) { rnode = rit; } lisp_addr_del(rnode->addr); rnode->addr = if_addr; } break; } default: OOR_LOG(LDBG_1, "lcaf_rloc_set_ip_addr: lcaf type %d not supported", lcaf_addr_get_type(lcaf)); return(BAD); } return(GOOD); } oor-1.2.0/oor/liblisp/lisp_lcaf.h000066400000000000000000000244671313612200500166610ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef LISPD_LCAF_H_ #define LISPD_LCAF_H_ #include "lisp_ip.h" #include "../lib/generic_list.h" #include "lisp_messages.h" #define MAX_LCAFS 16 typedef struct _lisp_addr_t lisp_addr_t; typedef struct _lcaf_addr_t { lcaf_type_e type; void *addr; } lcaf_addr_t; #define MAX_IID 16777215 /* * Abstract representation of LCAFs */ typedef struct afi_list { glist_t *list_addr; } afi_list_t; typedef struct _iid_t { uint32_t iid; uint8_t mlen; lisp_addr_t *iidaddr; } iid_t; /* GEO */ typedef struct { uint8_t dir; uint16_t deg; uint8_t min; uint8_t sec; } geo_coordinates; typedef struct { geo_coordinates latitude; geo_coordinates longitude; uint32_t altitude; lisp_addr_t *addr; } geo_t; /* NAT */ typedef struct { uint16_t etr_pub_port; lisp_addr_t *etr_pub_addr; uint16_t ms_port; lisp_addr_t *ms_addr; lisp_addr_t *etr_prv_addr; glist_t *rtr_addr_lst; } nat_t; typedef struct { uint8_t src_plen; uint8_t grp_plen; uint32_t iid; lisp_addr_t *src; lisp_addr_t *grp; } mc_t; /* ELP */ typedef struct elp_node { uint8_t L:1; uint8_t P:1; uint8_t S:1; lisp_addr_t *addr; } elp_node_t; typedef struct _elp_t { glist_t *nodes; } elp_t; /* RLE */ typedef struct _rle_node_t { lisp_addr_t *addr; uint8_t level; } rle_node_t; typedef struct _rle_t { glist_t *nodes; } rle_t; lcaf_addr_t *lcaf_addr_new(); lcaf_addr_t *lcaf_addr_new_type(uint8_t type); void lcaf_addr_del_addr(lcaf_addr_t *lcaf); lcaf_type_e lcaf_addr_get_type(lcaf_addr_t *lcaf); void *lcaf_addr_get_addr(lcaf_addr_t *lcaf); mc_t *lcaf_addr_get_mc(lcaf_addr_t *lcaf); geo_t *lcaf_addr_get_geo(lcaf_addr_t *lcaf); iid_t *lcaf_addr_get_iid(lcaf_addr_t *lcaf); nat_t *lcaf_addr_get_nat(lcaf_addr_t *lcaf); int lcaf_addr_is_mc(lcaf_addr_t *lcaf); int lcaf_addr_is_iid(lcaf_addr_t *lcaf); void lcaf_addr_set(lcaf_addr_t *lcaf, void *newaddr, uint8_t type); void lcaf_addr_set_addr(lcaf_addr_t *lcaf, void *addr); void lcaf_addr_set_type(lcaf_addr_t *lcaf, uint8_t type); int lcaf_addr_parse(uint8_t *offset, lcaf_addr_t *lcaf_addr); char *lcaf_addr_to_char(lcaf_addr_t *lcaf); uint32_t lcaf_addr_get_size_to_write(lcaf_addr_t *lcaf); int lcaf_addr_copy(lcaf_addr_t *dst, lcaf_addr_t *src); int lcaf_addr_write(void *offset, lcaf_addr_t *lcaf); int lcaf_addr_cmp(lcaf_addr_t *addr1, lcaf_addr_t *addr2); uint8_t lcaf_addr_cmp_iids(lcaf_addr_t *addr1, lcaf_addr_t *addr2); /* * mc type functions */ lisp_addr_t *lcaf_mc_get_src(lcaf_addr_t *mc); lisp_addr_t *lcaf_mc_get_grp(lcaf_addr_t *mc); uint32_t lcaf_mc_get_iid(lcaf_addr_t *mc); uint8_t lcaf_mc_get_src_plen(lcaf_addr_t *mc); uint8_t lcaf_mc_get_grp_plen(lcaf_addr_t *mc); uint8_t lcaf_mc_get_afi(lcaf_addr_t *mc); mc_t *mc_type_new(); void mc_type_del(void *mc); mc_t *mc_type_init(lisp_addr_t *src, lisp_addr_t *grp, uint8_t splen, uint8_t gplen, uint32_t iid); void mc_type_set_src_plen(mc_t *mc, uint8_t plen); void mc_type_set_grp_plen(mc_t *mc, uint8_t plen); void mc_type_set_iid(mc_t *mc, uint32_t iid); void mc_type_set_src(void *mc, lisp_addr_t *src); void mc_type_set_grp(mc_t *mc, lisp_addr_t *grp); lisp_addr_t *mc_type_get_src(mc_t *mc); lisp_addr_t *mc_type_get_grp(mc_t *mc); uint8_t mc_type_get_afi(mc_t *mc); uint32_t mc_type_get_iid(void *mc); uint8_t mc_type_get_src_plen(mc_t *mc); uint8_t mc_type_get_grp_plen(mc_t *mc); char *mc_type_to_char (void *mc); int mc_type_get_size_to_write(void *mc); int mc_type_write_to_pkt(uint8_t *offset, void *mc); void mc_type_copy(void **dst, void *src); int mc_type_cmp(void *mc1, void *mc2); void mc_type_set(mc_t *dst, lisp_addr_t *src, lisp_addr_t *grp, uint8_t splen, uint8_t gplen, uint32_t iid); int mc_type_parse(uint8_t *offset, void **mc); lisp_addr_t * mc_type_get_ip_addr (void *mc); lisp_addr_t * mc_type_get_ip_pref_addr (void *mc); int lcaf_addr_set_mc(lcaf_addr_t *lcaf, lisp_addr_t *src, lisp_addr_t *grp, uint8_t splen, uint8_t gplen, uint32_t iid); lisp_addr_t *lisp_addr_build_mc(lisp_addr_t *src, lisp_addr_t *grp); int lisp_addr_is_mcinfo(lisp_addr_t *addr); /* * iid type functions */ iid_t *iid_type_new(); iid_t * iid_type_new_init(int iid, lisp_addr_t *addr, uint8_t mlen); void iid_type_del(void *iid); uint8_t iid_type_get_mlen(iid_t *iid); uint32_t lcaf_iid_get_iid(lcaf_addr_t *iid); uint32_t iid_type_get_iid(iid_t *iid); lisp_addr_t *iid_type_get_addr(void *iid); void iid_type_set_iid(iid_t *addr, uint32_t iid); void iid_type_set_addr(iid_t *addr, lisp_addr_t *iidaddr); void iid_type_set_mlen(iid_t *addr, uint8_t mlen); int iid_type_cmp(void *iid1, void *iid2); int iid_type_get_size_to_write(void *iid); int iid_type_write_to_pkt(uint8_t *offset, void *iid); int iid_type_parse(uint8_t *offset, void **iid); char *iid_type_to_char(void *iid); void iid_type_copy(void **dst, void *src); lisp_addr_t * iid_type_get_ip_addr(void *iid); lisp_addr_t * iid_type_get_ip_pref_addr(void *iid); void lcaf_iid_init(lcaf_addr_t *iidaddr, int iid, lisp_addr_t *addr, uint8_t mlen); int lisp_addr_is_iid(lisp_addr_t *addr); lisp_addr_t * lisp_addr_new_init_iid(int iid, lisp_addr_t *addr, uint8_t mlen); /* * geo type functions */ geo_t * geo_type_new(); void geo_type_del(void *geo); void geo_type_set_addr(geo_t *geo, lisp_addr_t *addr); void geo_type_set_lat(geo_t *geo, uint8_t dir, uint16_t deg, uint8_t min, uint8_t sec); void geo_type_set_long(geo_t *geo, uint8_t dir, uint16_t deg, uint8_t min, uint8_t sec); void geo_type_set_lat_from_coord(geo_t *geo, geo_coordinates *coord); void geo_type_set_long_from_coord(geo_t *geo, geo_coordinates *coord); void geo_type_set_altitude(geo_t *geo, uint32_t altitude); lisp_addr_t *geo_type_get_addr(geo_t *geo); geo_coordinates *geo_type_get_lat(geo_t *geo); geo_coordinates *geo_type_get_long(geo_t *geo); uint32_t geo_type_get_altitude(geo_t *geo); int geo_type_parse(uint8_t *offset, void **geo); char *geo_type_to_char(void *geo); void geo_type_copy(void **dst, void *src); char *geo_coord_to_char(geo_coordinates *coord); /* * NAT type functions */ nat_t * nat_type_new(); nat_t * nat_type_new_init(uint16_t ms_port, lisp_addr_t *ms_addr, uint16_t etr_pub_port, lisp_addr_t *etr_pub_addr, lisp_addr_t *etr_prv_addr, glist_t *rtr_addr_lst); void nat_type_del(void *nat); uint16_t nat_type_get_ms_port(nat_t *nat); uint16_t nat_type_get_etr_pub_port(nat_t *nat); lisp_addr_t * nat_type_get_ms_addr(nat_t *nat); lisp_addr_t * nat_type_get_etr_pub_addr(nat_t *nat); lisp_addr_t * nat_type_get_etr_priv_addr(nat_t *nat); glist_t * nat_type_get_rtr_addr_lst(nat_t *nat); void nat_type_set_ms_port(nat_t *nat, uint16_t ms_port); void nat_type_set_etr_pub_port(nat_t *nat, uint16_t etr_pub_port); void nat_type_set_ms_addr(nat_t *nat, lisp_addr_t * ms_addr); void nat_type_set_etr_pub_addr(nat_t *nat, lisp_addr_t * etr_pub_addr); void nat_type_set_etr_priv_addr(nat_t *nat, lisp_addr_t * etr_prv_addr); void nat_type_set_rtr_addr_lst(nat_t *nat, glist_t * rtr_addr_lst); int nat_type_cmp(void *nat1, void *nat2); int nat_type_get_size_to_write(void *nat); int nat_type_write_to_pkt(uint8_t *offset, void *nat); int nat_type_parse(uint8_t *offset, void **nat); char *nat_type_to_char(void *nat); void nat_type_copy(void **dst, void *src); lisp_addr_t * nat_type_get_ip_addr(void *nat); lisp_addr_t * nat_type_get_ip_pref_addr(void *nat); void lcaf_nat_init(lcaf_addr_t *nat_addr, uint16_t ms_port, lisp_addr_t *ms_addr, uint16_t etr_pub_port, lisp_addr_t *etr_pub_addr, lisp_addr_t *etr_prv_addr, glist_t *rtr_addr_lst); int lisp_addr_is_nat(lisp_addr_t *addr); lisp_addr_t * lisp_addr_new_init_nat(uint16_t ms_port, lisp_addr_t *ms_addr, uint16_t etr_pub_port, lisp_addr_t *etr_pub_addr, lisp_addr_t *etr_prv_addr, glist_t *rtr_addr_lst); /* * RLE type functions */ rle_t * rle_type_new(); void rle_type_del(void *rleaddr); int rle_type_parse(uint8_t *offset, void **rle); int rle_type_write_to_pkt(uint8_t *offset, void *rle); int rle_type_get_size_to_write(void *elp); char * rle_type_to_char(void *rle); void rle_type_copy(void **dst, void *src); int rle_type_cmp(void *elp1, void *elp2); rle_node_t * rle_node_clone(rle_node_t *srn); rle_node_t * rle_node_new(); void rle_node_del(rle_node_t *rnode); glist_t * lcaf_rle_node_list(lcaf_addr_t *lcaf); /* * ELP type functions */ lisp_addr_t * lisp_addr_elp_new(); elp_t * lcaf_elp_get_elp(lcaf_addr_t *elp); elp_t *elp_type_new(); void elp_type_del(void *elp); int elp_type_get_size_to_write(void *elp); int elp_type_write_to_pkt(uint8_t *offset, void *elp); int elp_type_parse(uint8_t *offset, void **elp); char *elp_type_to_char(void *elp); void elp_type_copy(void **dst, void *src); int elp_type_cmp(void *elp1, void *elp2); lisp_addr_t * elp_type_get_ip_addr(void *elp); elp_node_t * elp_node_new_init(lisp_addr_t *addr, uint8_t lookup, uint8_t rloc_probe, uint8_t strict); lisp_addr_t * elp_node_addr(elp_node_t *enode); void elp_node_del(elp_node_t *enode); void elp_add_node(elp_t *elp, elp_node_t *enode); glist_t * lcaf_elp_node_list(lcaf_addr_t *lcaf); int lisp_addr_is_elp(lisp_addr_t *addr); /* * AFI-list type functions */ afi_list_t *afi_list_type_new(); void afi_list_type_del(void *afil); int afi_list_type_get_size_to_write(void *afil); int afi_list_type_write_to_pkt(uint8_t *offset, void *afil); int afi_list_type_parse(uint8_t *offset, void **afil); char *afi_list_type_to_char(void *afil); void afi_list_type_copy(void **dst, void *src); int afi_list_type_cmp(void *afil1, void *afil2); lisp_addr_t * afi_list_type_get_ip_addr(void *afi_list); lisp_addr_t * afi_list_type_get_ip_pref_addr(void *afi_list); lisp_addr_t * lcaf_get_ip_addr(lcaf_addr_t *lcaf); lisp_addr_t * lcaf_get_ip_pref_addr(lcaf_addr_t *lcaf); int lcaf_rloc_set_ip_addr(lisp_addr_t *, lisp_addr_t *if_addr); #endif /* LISPD_LCAF_H_ */ oor-1.2.0/oor/liblisp/lisp_locator.c000066400000000000000000000176771313612200500174170ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include #include "lisp_locator.h" #include "../lib/oor_log.h" locator_t * locator_new() { return (xzalloc(sizeof(locator_t))); } locator_t * locator_new_init(lisp_addr_t* addr,uint8_t state,uint8_t L_bit,uint8_t R_bit, uint8_t priority, uint8_t weight,uint8_t mpriority, uint8_t mweight) { locator_t* locator; locator = locator_new(); if (locator == NULL){ return (NULL); } locator->addr = lisp_addr_clone(addr); locator->state = state; locator->L_bit = L_bit; locator->R_bit = R_bit; locator->priority = priority; locator->weight = weight; locator->mpriority = mpriority; locator->mweight = mweight; return (locator); } char * locator_to_char(locator_t *l) { static char buf[5][500]; size_t buf_size = sizeof(buf[0]); static int i=0; if (l == NULL){ sprintf(buf[i], "_NULL_"); return (buf[i]); } /* hack to allow more than one locator per line */ i++; i = i % 5; *buf[i] = '\0'; snprintf(buf[i] + strlen(buf[i]),buf_size - strlen(buf[i]),"%s, ", lisp_addr_to_char(locator_addr(l))); snprintf(buf[i] + strlen(buf[i]),buf_size - strlen(buf[i]), "%s, ", l->state ? "Up" : "Down"); snprintf(buf[i] + strlen(buf[i]),buf_size - strlen(buf[i]), "%d/%-d, %d/%d", l->priority, l->weight, l->mpriority, l->mweight); return (buf[i]); } int locator_parse(void *ptr, locator_t *loc) { locator_hdr_t *hdr; uint8_t status = UP; int len; hdr = ptr; if (!LOC_REACHABLE(hdr) && LOC_LOCAL(hdr)) { status = DOWN; } if (!loc->addr) { loc->addr = lisp_addr_new(); } len = lisp_addr_parse(LOC_ADDR(hdr), loc->addr); if (len <= 0) { return (BAD); } loc->state = status; loc->L_bit = LOC_LOCAL(hdr); loc->R_bit = LOC_REACHABLE(hdr); loc->priority = LOC_PRIORITY(hdr); loc->weight = LOC_WEIGHT(hdr); loc->mpriority = LOC_MPRIORITY(hdr); loc->mweight = LOC_MWEIGHT(hdr); return (sizeof(locator_hdr_t) + len); } int locator_cmp(locator_t *l1, locator_t *l2) { int ret = 0; if ((ret = lisp_addr_cmp(locator_addr(l1), locator_addr(l2))) != 0) { return (1); } if (l1->priority != l2->priority) return (1); if (l1->weight != l2->weight) return (1); if (l1->mpriority != l2->mpriority) return (1); if (l1->mweight != l2->mweight) return (1); return (0); } void locator_del(locator_t *locator) { if (!locator) { return; } lisp_addr_del(locator->addr); free(locator); locator = NULL; } locator_t * locator_clone(locator_t *loc) { locator_t *locator = locator_new_init(loc->addr, loc->state,loc->L_bit, loc->R_bit, loc->priority, loc->weight, loc->mpriority, loc->mweight); return (locator); } /* * Compare lisp_addr_t of two locators. * Returns: * -1: If they are from different afi * 0: Both address are the same * 1: Addr1 is bigger than addr2 * 2: Addr2 is bigger than addr1 */ inline int locator_cmp_addr (locator_t *loct1, locator_t *loct2) { return (lisp_addr_cmp(locator_addr(loct1),locator_addr(loct2))); } /* * Get lafi and type of a list */ void locator_list_lafi_type (glist_t *loct_list,int *lafi,int *type) { locator_t *loct = NULL; lisp_addr_t *addr = NULL; *lafi = 0; *type = 0; if (loct_list == NULL || glist_size(loct_list) == 0){ return; } loct = (locator_t *)glist_first_data(loct_list); addr = locator_addr(loct); *lafi = lisp_addr_lafi(addr); switch(*lafi){ case LM_AFI_NO_ADDR: *type = 0; return; case LM_AFI_IP: *type = lisp_addr_ip_afi(addr); return; case LM_AFI_IPPREF: OOR_LOG(LDBG_2, "locator_list_lafi_type: locator list should not contain prefixes"); return; case LM_AFI_LCAF: *type = lisp_addr_lcaf_type(addr); return; } } /* Return the locator from the list that contains the address passed as a * parameter */ locator_t * locator_list_get_locator_with_addr(glist_t *loct_list,lisp_addr_t *addr) { locator_t *locator = NULL; glist_entry_t *it = NULL; if (!loct_list || glist_size(loct_list) == 0 || addr == NULL){ return (NULL); } glist_for_each_entry(it,loct_list){ locator = (locator_t *)glist_entry_data(it); if (lisp_addr_cmp(locator_addr(locator), addr) == 0) { return (locator); } } return (NULL); } /* Extract the locator of locators list that match with the address. * The locator is removed from the list */ locator_t * locator_list_extract_locator_with_addr(glist_t *loct_list,lisp_addr_t *addr) { locator_t *locator = NULL; glist_entry_t *it = NULL; if (!loct_list || glist_size(loct_list) == 0 || addr == NULL){ return (NULL); } glist_for_each_entry(it,loct_list){ locator = (locator_t *)glist_entry_data(it); if (lisp_addr_cmp(locator_addr(locator), addr) == 0) { glist_extract(it,loct_list); return (locator); } } return (NULL); } /* Extract the locator of locators list comparing the pointer to the structure. * The locator is removed from the list */ int locator_list_extract_locator_with_ptr(glist_t *loct_list,locator_t *locator) { glist_entry_t *it = NULL; locator_t *loct = NULL; if (!loct_list || glist_size(loct_list) == 0 || locator == NULL){ return (BAD); } glist_for_each_entry(it,loct_list){ loct = (locator_t *)glist_entry_data(it); if (loct == locator){ glist_extract(it,loct_list); return(GOOD); } } return(ERR_NO_EXIST); } /* Clones locators list BUT it DISCARDS probing nonces and timers! */ glist_t * locator_list_clone(glist_t *loct_list) { glist_t *new_loct_list = NULL; glist_entry_t *it_loct = NULL; locator_t *loct1 = NULL; locator_t *loct2 = NULL; if (loct_list == NULL || glist_size(loct_list) == 0){ return (NULL); } new_loct_list = glist_new_complete( (glist_cmp_fct)locator_cmp_addr, (glist_del_fct)locator_del); glist_for_each_entry(it_loct, loct_list){ loct1 = (locator_t *)glist_entry_data(it_loct); loct2 = locator_clone(loct1); glist_add(loct2,new_loct_list); } return (new_loct_list); } int locator_list_cmp_afi(glist_t *loct_list_a,glist_t *loct_list_b) { locator_t * loct_a = NULL; locator_t * loct_b = NULL; lisp_addr_t * addr_a = NULL; lisp_addr_t * addr_b = NULL; if (loct_list_a == NULL || loct_list_b == NULL){ return (-2); } if(glist_size(loct_list_a) == 0 || glist_size(loct_list_b) == 0){ OOR_LOG(LDBG_2, "locator_list_cmp_afi: One of the compared list is empty"); return (-2); } loct_a = (locator_t *)glist_first_data(loct_list_a); loct_b = (locator_t *)glist_first_data(loct_list_b); addr_a = locator_addr(loct_a); addr_b = locator_addr(loct_b); return (lisp_addr_cmp_afi(addr_a,addr_b)); } inline void locator_clone_addr(locator_t *loc, lisp_addr_t *addr) { if (!loc->addr) { loc->addr = lisp_addr_new(); } lisp_addr_copy(loc->addr, addr); } oor-1.2.0/oor/liblisp/lisp_locator.h000066400000000000000000000064441313612200500174120ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef LISP_LOCATOR_H_ #define LISP_LOCATOR_H_ #include "lisp_address.h" #include "../lib/mem_util.h" #define MAX_PRIORITY 0 #define MIN_PRIORITY 254 #define UNUSED_RLOC_PRIORITY 255 #define MIN_WEIGHT 0 #define MAX_WEIGHT 255 typedef struct locator { lisp_addr_t *addr; /* UP , DOWN */ uint8_t state; uint8_t L_bit; uint8_t R_bit; uint8_t priority; uint8_t weight; uint8_t mpriority; uint8_t mweight; } locator_t; locator_t *locator_new(); locator_t * locator_new_init(lisp_addr_t* addr,uint8_t state,uint8_t L_bit,uint8_t R_bit, uint8_t priority, uint8_t weight,uint8_t mpriority, uint8_t mweight); char *locator_to_char(locator_t *); int locator_cmp(locator_t *l1, locator_t *l2); int locator_parse(void *ptr, locator_t *loc); void locator_del(locator_t *loc); locator_t *locator_clone(locator_t *loc); void locator_list_lafi_type (glist_t *loct_list, int *lafi, int *type); locator_t *locator_list_get_locator_with_addr(glist_t *loct_list, lisp_addr_t *addr); locator_t *locator_list_extract_locator_with_addr(glist_t *loct_list,lisp_addr_t *addr); int locator_list_extract_locator_with_ptr(glist_t *loct_list,locator_t *locator); int locator_cmp_addr (locator_t *loct1,locator_t *loct2); glist_t *locator_list_clone(glist_t *llist); int locator_list_cmp_afi(glist_t *loct_list_a, glist_t *loct_list_b); void locator_clone_addr(locator_t *loc, lisp_addr_t *addr); static inline lisp_addr_t *locator_addr(locator_t *locator) { return (locator->addr); } static inline uint8_t locator_state(locator_t *locator) { return (locator->state); } static inline uint8_t locator_L_bit(locator_t *locator) { return (locator->L_bit); } static inline uint8_t locator_R_bit(locator_t *locator) { return (locator->R_bit); } static inline uint8_t locator_priority(locator_t *locator) { return (locator->priority); } static inline uint8_t locator_weight(locator_t *locator) { return (locator->weight); } static inline uint8_t locator_mpriority(locator_t *locator) { return (locator->mpriority); } static inline uint8_t locator_mweight(locator_t *locator) { return (locator->mweight); } static inline void locator_set_addr(locator_t *loc, lisp_addr_t *addr) { /* Addr is linked to corresponding interface address */ loc->addr = addr; } static inline void locator_set_state(locator_t *locator, uint8_t state) { locator->state = state; } static inline void locator_set_L_bit(locator_t *locator, uint8_t L_bit) { locator->L_bit = L_bit; } static inline void locator_set_R_bit(locator_t *locator, uint8_t R_bit) { locator->R_bit = R_bit; } #endif /* LISP_LOCATOR_H_ */ oor-1.2.0/oor/liblisp/lisp_mapping.c000066400000000000000000000320761313612200500173750ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "../lib/oor_log.h" #include "lisp_mapping.h" inline mapping_t * mapping_new() { mapping_t *mapping; mapping = xzalloc(sizeof(mapping_t)); if (mapping == NULL){ return (NULL); } mapping->locators_lists = glist_new_complete( (glist_cmp_fct) locator_list_cmp_afi, (glist_del_fct) glist_destroy); if (mapping->locators_lists == NULL){ free(mapping); return (NULL); } return(mapping); } inline mapping_t * mapping_new_init(lisp_addr_t *eid) { mapping_t *mapping; lisp_addr_t *ip_pref; /* If eid is an IP address, convert it to IP prefix */ if (lisp_addr_get_ip_pref_addr(eid) == NULL){ ip_pref = lisp_addr_get_ip_addr(eid); if (!ip_pref){ OOR_LOG(LWRN, "mapping_new_init: Couldn't get eid prefix from %s", lisp_addr_to_char(eid)); return (NULL); } lisp_addr_ip_to_ippref(ip_pref); } mapping = mapping_new(); if (!mapping){ OOR_LOG(LWRN, "mapping_new_init: Couldn't allocate mapping_t structure"); return (NULL); } lisp_addr_copy(&(mapping->eid_prefix), eid); return (mapping); } void mapping_del(mapping_t *m) { if (!m) { return; } /* Free the locators list*/ glist_destroy(m->locators_lists); /* MUST free lcaf addr */ lisp_addr_dealloc(mapping_eid(m)); free(m); } /* compare two mappings * returns 0 if they are the same and 1 otherwise */ int mapping_cmp(mapping_t *m1, mapping_t *m2) { glist_t *loct_list1 = NULL; glist_t *loct_list2 = NULL; locator_t *loct1 = NULL; locator_t *loct2 = NULL; glist_entry_t *it_list1 = NULL; glist_entry_t *it_list2 = NULL; glist_entry_t *it_loct1 = NULL; glist_entry_t *it_loct2 = NULL; if (lisp_addr_cmp(mapping_eid(m1), mapping_eid(m2)) != 0) { return (1); } if (m1->locator_count != m2->locator_count) { return (1); } if (glist_size(m1->locators_lists) != glist_size(m2->locators_lists)){ return (1); } it_list2 = glist_first(m2->locators_lists); glist_for_each_entry(it_list1,m1->locators_lists){ loct_list1 = (glist_t *)glist_entry_data(it_list1); loct_list2 = (glist_t *)glist_entry_data(it_list2); if (glist_size(loct_list1) != glist_size(loct_list2)){ return (1); } it_loct2 = glist_first(loct_list2); glist_for_each_entry(it_loct1,loct_list1){ loct1 = (locator_t *)glist_entry_data(it_loct1); loct2 = (locator_t *)glist_entry_data(it_loct2); if (locator_cmp(loct1, loct2) != 0) { return (1); } it_loct2 = glist_next(it_loct2); } it_list2 = glist_next(it_list2); } return (0); } /* Clones a mapping_t data structure * NOTE: it does not clone the 'extended_info'! This should be done by the * caller and in the future it shouldn't be done at all. 'extended_info' * should be moved out */ //XXX IT IS NOT CLONING LOCATORS mapping_t * mapping_clone(mapping_t *m) { mapping_t *cm = mapping_new(); mapping_set_eid(cm, mapping_eid(m)); cm->action = m->action; cm->authoritative = m->authoritative; cm->locator_count = m->locator_count; cm->ttl = m->ttl; return(cm); } char * mapping_to_char(mapping_t *m) { locator_t *locator = NULL; static char buf[500]; size_t buf_size = sizeof(buf); *buf = '\0'; snprintf(buf,buf_size, "EID: %s, ttl: %d, loc-count: %d, action: %s, " "auth: %d\n", lisp_addr_to_char(mapping_eid(m)), mapping_ttl(m), mapping_locator_count(m), mapping_action_to_char(mapping_action(m)), mapping_auth(m)); if (m->locator_count > 0) { mapping_foreach_active_locator(m,locator){ snprintf(buf+strlen(buf), buf_size - strlen(buf)," RLOC: %s\n", locator_to_char(locator)); }mapping_foreach_active_locator_end; } return(buf); } int mapping_add_locator( mapping_t *mapping, locator_t *loct) { lisp_addr_t *addr = NULL; glist_t *loct_list = NULL; locator_t *aux_loct = NULL; int result = GOOD; addr = locator_addr(loct); loct_list = mapping_get_loct_lst_with_addr_type(mapping,addr); if (loct_list == NULL){ loct_list = glist_new_complete( (glist_cmp_fct)locator_cmp_addr, (glist_del_fct)locator_del); // The locator is added firstly in order the list has an associated afi if ((result = glist_add(loct,loct_list)) == GOOD){ result = glist_add(loct_list,mapping->locators_lists); } }else { if (glist_contain(loct, loct_list) == TRUE){ OOR_LOG(LDBG_2, "mapping_add_locator: The locator %s already exists " "for the EID %s. Discarding the one with less priority", lisp_addr_to_char(locator_addr(loct)), lisp_addr_to_char(mapping_eid(mapping))); aux_loct = mapping_get_loct_with_addr(mapping, locator_addr(loct)); if (locator_priority(aux_loct) > locator_priority(loct)){ /* Returns good in order the caller of this functione doesn't free the memory of the locator */ glist_remove_obj_with_ptr(aux_loct,loct_list); return (glist_add(loct,loct_list)); }else{ /* Return error in order the caller of this functione frees the memory of the locator */ return (ERR_EXIST); } }else { result = glist_add(loct,loct_list); } } if (result == GOOD) { OOR_LOG(LDBG_2, "mapping_add_locator: Added locator %s to the mapping with" " EID %s.", lisp_addr_to_char(locator_addr(loct)), lisp_addr_to_char(mapping_eid(mapping))); if (lisp_addr_is_no_addr(addr) == FALSE){ mapping->locator_count++; } result = GOOD; } else { if (glist_size(loct_list) == 0){ glist_remove_obj_with_ptr(loct_list,mapping->locators_lists); } result = BAD; } return (result); } /* This function extract the locator from the list of locators of the mapping */ int mapping_remove_locator( mapping_t *mapping, locator_t *loct) { lisp_addr_t *addr = NULL; glist_t *loct_list = NULL; addr = locator_addr(loct); loct_list = mapping_get_loct_lst_with_addr_type(mapping,addr); if (loct_list == NULL){ OOR_LOG(LDBG_2,"mapping_remove_locator: The locator %s has not been found in the mapping", lisp_addr_to_char(locator_addr(loct))); return (GOOD); } if (locator_list_extract_locator_with_ptr(loct_list,loct) != GOOD){ OOR_LOG(LDBG_2,"mapping_remove_locator: The locator %s has not been found in the mapping", lisp_addr_to_char(locator_addr(loct))); return (GOOD); } if (glist_size(loct_list) == 0){ glist_remove_obj_with_ptr(loct_list, mapping->locators_lists); } if (!lisp_addr_is_no_addr(addr)){ mapping->locator_count = mapping->locator_count - 1; } if (lisp_addr_is_no_addr(addr) == FALSE){ mapping->locator_count++; } OOR_LOG(LDBG_2, "mapping_remove_locator: Removed locator %s from the mapping with" " EID %s.", lisp_addr_to_char(locator_addr(loct)), lisp_addr_to_char(mapping_eid(mapping))); return (GOOD); } void mapping_remove_locators(mapping_t *mapping) { glist_remove_all(mapping->locators_lists); mapping->locator_count = 0; } void mapping_update_locators(mapping_t *mapping, glist_t *locts_lists) { glist_t *loct_list = NULL; glist_t *new_loct_list = NULL; glist_entry_t *it_list = NULL; locator_t *locator = NULL; int loct_ctr = 0; if (!mapping || !locts_lists) { return; } /* TODO: do a comparison first */ glist_remove_all(mapping->locators_lists); glist_for_each_entry(it_list,locts_lists){ loct_list = (glist_t *)glist_entry_data(it_list); new_loct_list = locator_list_clone(loct_list); glist_add(new_loct_list,mapping->locators_lists); locator = (locator_t*)glist_first_data(new_loct_list); if (lisp_addr_is_no_addr(locator_addr(locator)) == FALSE){ loct_ctr = loct_ctr + glist_size(new_loct_list); } } mapping->locator_count = loct_ctr; } /* * Returns the locators with the address passed as a parameter */ locator_t * mapping_get_loct_with_addr(mapping_t *mapping, lisp_addr_t *address) { locator_t *locator = NULL; glist_t *locator_list = NULL; locator_list = mapping_get_loct_lst_with_addr_type(mapping,address); locator = locator_list_get_locator_with_addr(locator_list, address); return (locator); } glist_t * mapping_get_loct_lst_with_afi( mapping_t * mapping, lm_afi_t lafi, int afi) { glist_entry_t *it = NULL; glist_t *loct_list = NULL; locator_t *loct = NULL; lisp_addr_t *addr = NULL; glist_for_each_entry(it, mapping->locators_lists){ loct_list = (glist_t *)glist_entry_data(it); loct = (locator_t *)glist_first_data(loct_list); addr = locator_addr(loct); if ( lisp_addr_lafi(addr) == lafi){ switch (lafi){ case LM_AFI_NO_ADDR: return (loct_list); case LM_AFI_IP: if (lisp_addr_ip_afi(addr) == afi){ return (loct_list); } break; case LM_AFI_IPPREF: OOR_LOG(LDBG_1,"mapping_get_locators_with_afi: No locators of type prefix"); return (NULL); case LM_AFI_LCAF: if (lisp_addr_lcaf_type(addr) == afi){ return (loct_list); } break; } } } OOR_LOG(LDBG_2,"mapping_get_locators_with_afi: List for OOR AFI %d and afi %d not yet created",lafi,afi); return (NULL); } glist_t * mapping_get_loct_lst_with_addr_type( mapping_t * mapping, lisp_addr_t *addr) { lm_afi_t lafi; int afi; lafi = lisp_addr_lafi(addr); afi = lisp_addr_ip_afi_lcaf_type(addr); return (mapping_get_loct_lst_with_afi(mapping,lafi,afi)); } /* * Check if the locator is part of the mapping */ uint8_t mapping_has_locator( mapping_t *mapping, locator_t *loct) { glist_t *loct_list = NULL; glist_entry_t *it = NULL; lisp_addr_t *addr = locator_addr(loct); loct_list = mapping_get_loct_lst_with_addr_type(mapping,addr); if (loct_list == NULL || glist_size(loct_list) == 0 || addr == NULL){ return (FALSE); } glist_for_each_entry(it,loct_list){ if (loct == (locator_t *)glist_entry_data(it)){ return (TRUE); } } return (FALSE); } /* This function sorts the locator list with IP = changed_loc_addr */ int mapping_sort_locators(mapping_t *mapping, lisp_addr_t *changed_loc_addr) { glist_t *loct_list = NULL; locator_t *locator = NULL; int res = 0; loct_list = mapping_get_loct_lst_with_addr_type(mapping,changed_loc_addr); locator = locator_list_extract_locator_with_addr(loct_list, changed_loc_addr); if (locator != NULL){ res = glist_add(locator,loct_list); }else{ res = BAD; } return (res); } /* * Remove the locator from the non active locators list and reinsert in the correct list * The address of the locator should be modified before calling this function * This function is only used when an interface is down during the initial configuration * process and then is activated */ int mapping_activate_locator( mapping_t *mapping, locator_t *loct, lisp_addr_t *new_addr) { int res = GOOD; glist_t *loct_list = NULL; loct_list = mapping_get_loct_lst_with_afi(mapping,LM_AFI_NO_ADDR,0); if (loct_list == NULL){ return (BAD); } mapping_remove_locator(mapping, loct); locator_clone_addr(loct,new_addr); res = mapping_add_locator(mapping,loct); if (res == GOOD){ OOR_LOG(LDBG_1,"mapping_activate_locator: The locator %s of the mapping %s has been activated", lisp_addr_to_char(locator_addr(loct)), lisp_addr_to_char(&(mapping->eid_prefix))); OOR_LOG(LDBG_2,"mapping_activate_locator: Updated mapping -> %s",mapping_to_char(mapping)); }else{ locator_del(loct); OOR_LOG(LDBG_1,"mapping_activate_locator: Error activating the locator %s of the mapping %s. Locator couldn't be reinserted", lisp_addr_to_char(locator_addr(loct)), lisp_addr_to_char(&(mapping->eid_prefix))); } return (res); } oor-1.2.0/oor/liblisp/lisp_mapping.h000066400000000000000000000132061313612200500173740ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef MAPPING_H_ #define MAPPING_H_ #include "lisp_address.h" #include "lisp_locator.h" typedef enum { MAPPING_LOCAL, MAPPING_REMOTE, MAPPING_RE, } mapping_type; typedef void (*extended_info_del_fct)(void *); typedef struct mapping { lisp_addr_t eid_prefix; uint16_t locator_count; glist_t *locators_lists; // uint32_t ttl; uint8_t action; uint8_t authoritative; uint32_t iid; /*to remove in future*/ } mapping_t; mapping_t *mapping_new(); mapping_t *mapping_new_init(lisp_addr_t *); void mapping_del(mapping_t *); int mapping_cmp(mapping_t *, mapping_t *); mapping_t *mapping_clone(mapping_t *); char *mapping_to_char(mapping_t *m); int mapping_add_locator(mapping_t *, locator_t *); /* This function extract the locator from the list of locators of the mapping */ int mapping_remove_locator(mapping_t *mapping,locator_t *loct); void mapping_remove_locators(mapping_t *mapping); void mapping_update_locators(mapping_t *, glist_t *); locator_t *mapping_get_loct_with_addr(mapping_t *, lisp_addr_t *); glist_t *mapping_get_loct_lst_with_afi(mapping_t *mapping, lm_afi_t lafi, int afi); glist_t *mapping_get_loct_lst_with_addr_type(mapping_t * mapping,lisp_addr_t *addr); uint8_t mapping_has_locator(mapping_t *mapping, locator_t *loct); int mapping_sort_locators(mapping_t *, lisp_addr_t *); int mapping_activate_locator(mapping_t *map,locator_t *loct, lisp_addr_t *new_addr); static inline lisp_addr_t *mapping_eid(mapping_t *m); static inline void mapping_set_eid(mapping_t *m, lisp_addr_t *addr); static inline void mapping_set_iid(mapping_t *m, uint32_t iid); static inline glist_t *mapping_locators_lists(mapping_t *m); static inline uint16_t mapping_locator_count(mapping_t *); static inline uint32_t mapping_ttl(mapping_t *); static inline void mapping_set_ttl(mapping_t *, uint32_t); static inline uint8_t mapping_action(mapping_t *); static inline void mapping_set_action(mapping_t *, uint8_t); static inline uint8_t mapping_auth(const mapping_t *); static inline void mapping_set_auth(mapping_t *, uint8_t); /*****************************************************************************/ static inline lisp_addr_t *mapping_eid(mapping_t *m) { return (&m->eid_prefix); } static inline void mapping_set_eid(mapping_t *m, lisp_addr_t *addr) { lisp_addr_copy(mapping_eid(m), addr); } static inline void mapping_set_iid(mapping_t *m, uint32_t iid) { m->iid = iid; } static inline glist_t *mapping_locators_lists(mapping_t *m) { return (m->locators_lists); } static inline uint16_t mapping_locator_count(mapping_t *m) { return(m->locator_count); } static inline uint32_t mapping_ttl(mapping_t *m) { return(m->ttl); } static inline void mapping_set_ttl(mapping_t *m, uint32_t t) { m->ttl = t; } static inline uint8_t mapping_action(mapping_t *m) { return(m->action); } static inline void mapping_set_action(mapping_t *m, uint8_t a) { m->action = a; } static inline uint8_t mapping_auth(const mapping_t *m) { return(m->authoritative); } static inline void mapping_set_auth(mapping_t *m, uint8_t a) { m->authoritative = a; } /* For all locators */ #define mapping_foreach_locator(_map, _loct) \ do { \ glist_t *_loct_list_; \ glist_entry_t *_it_list_; \ glist_entry_t *_it_loct_; \ \ glist_for_each_entry(_it_list_,_map->locators_lists){ \ _loct_list_ = (glist_t *)glist_entry_data(_it_list_); \ if (glist_size(_loct_list_) == 0){ \ continue; \ } \ glist_for_each_entry(_it_loct_,_loct_list_){ \ _loct = (locator_t *)glist_entry_data(_it_loct_); \ #define mapping_foreach_locator_end \ } \ } \ }while(0) /* For each locator that has an active address. If the locator status is down it will * also be returned */ #define mapping_foreach_active_locator(_map, _loct) \ do { \ glist_t *_loct_list_; \ glist_entry_t *_it_list_; \ glist_entry_t *_it_loct_; \ locator_t *_locator_; \ \ glist_for_each_entry(_it_list_,_map->locators_lists){ \ _loct_list_ = (glist_t *)glist_entry_data(_it_list_); \ if (glist_size(_loct_list_) == 0){ \ continue; \ } \ _locator_ = (locator_t *)glist_first_data(_loct_list_); \ if (lisp_addr_is_no_addr(locator_addr(_locator_)) == TRUE){ \ continue; \ } \ glist_for_each_entry(_it_loct_,_loct_list_){ \ _loct = (locator_t *)glist_entry_data(_it_loct_); \ #define mapping_foreach_active_locator_end \ } \ } \ }while(0) #endif /* MAPPING_H_ */ oor-1.2.0/oor/liblisp/lisp_message_fields.c000066400000000000000000000061061313612200500207070ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include #include "lisp_message_fields.h" void mapping_record_init_hdr(mapping_record_hdr_t *h) { h->ttl = htonl(DEFAULT_DATA_CACHE_TTL); h->locator_count = 1; h->eid_prefix_length = 0; h->action = 0; h->authoritative = 1; h->version_hi = 0; h->version_low = 0; h->reserved1 = 0; h->reserved2 = 0; h->reserved3 = 0; } char * mapping_action_to_char(int act) { static char buf[30]; *buf = '\0'; switch(act) { case ACT_NO_ACTION: sprintf(buf, "no-action"); break; case ACT_NATIVE_FWD: sprintf(buf, "native-forward"); break; case ACT_SEND_MREQ: sprintf(buf, "send-map-request"); break; case ACT_DROP: sprintf(buf, "drop"); break; default: sprintf(buf, "unknown-action"); } return(buf); } char * mapping_record_hdr_to_char(mapping_record_hdr_t *h) { static char buf[100]; if (!h) { return(NULL); } *buf = '\0'; snprintf(buf,sizeof(buf), "Mapping-record -> ttl: %d loc-count: %d action: %s auth: %d" " map-version: %d", ntohl(h->ttl), h->locator_count, mapping_action_to_char(h->action), h->authoritative, MAP_REC_VERSION(h)); return(buf); } char * locator_record_flags_to_char(locator_hdr_t *h) { static char buf[15]; *buf = '\0'; h->local ? sprintf(buf+strlen(buf), "L=1,") : sprintf(buf+strlen(buf), "L=0,"); h->probed ? sprintf(buf+strlen(buf), "p=1,") : sprintf(buf+strlen(buf), "p=0,"); h->reachable ? sprintf(buf+strlen(buf), "R=1") : sprintf(buf+strlen(buf), "R=0"); return(buf); } char * locator_record_hdr_to_char(locator_hdr_t *h) { static char buf[100]; if (!h) { return(NULL); } *buf = '\0'; snprintf(buf,sizeof(buf), "Locator-record -> flags: %s, p/w: %d/%d %d/%d", locator_record_flags_to_char(h), h->priority, h->weight, h->mpriority, h->mweight); return(buf); } /* Returns the length of the auth data field based on the key_id value */ uint16_t auth_data_get_len_for_type(lisp_key_type_e key_id) { switch (key_id) { default: // HMAC_SHA_1_96 return (LISP_SHA1_AUTH_DATA_LEN); //TODO support more auth algorithms } } void eid_rec_hdr_init(eid_record_hdr_t *ptr) { ptr->eid_prefix_length = 0; ptr->reserved = 0; } oor-1.2.0/oor/liblisp/lisp_message_fields.h000066400000000000000000000465471313612200500207310ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef LISP_MESSAGE_FIELDS_H_ #define LISP_MESSAGE_FIELDS_H_ //#include #include "../lib/generic_list.h" #include #include "../lib/mem_util.h" /* * ADDRESS FIELD */ /* LISP AFI codes */ typedef enum { LISP_AFI_NO_ADDR, LISP_AFI_IP, LISP_AFI_IPV6, LISP_AFI_LCAF = 16387 } lisp_afi_e; /* LCAF types */ typedef enum { LCAF_NULL = 0, LCAF_AFI_LIST, LCAF_IID, LCAF_ASN, LCAF_APP_DATA, LCAF_GEO = 5, LCAF_OKEY, LCAF_NATT, LCAF_NONCE_LOC, LCAF_MCAST_INFO, LCAF_EXPL_LOC_PATH = 10, LCAF_SEC_KEY, LCAF_TUPLE, LCAF_RLE, LCAF_DATA_MODEL, LCAF_KEY_VALUE } lcaf_type_e; /* * LISP Canonical Address Format * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI = 16387 | Rsvd1 | Flags | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type | Rsvd2 | Length | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ typedef struct _lcaf_hdr_t { uint16_t afi; uint8_t rsvd1; uint8_t flags; uint8_t type; uint8_t rsvd2; uint16_t len; } __attribute__ ((__packed__)) lcaf_hdr_t; /* AFI-list LCAF type */ typedef struct _lcaf_afi_list_hdr_t { uint16_t afi; uint8_t rsvd1; uint8_t flags; uint8_t type; uint8_t rsvd2; uint16_t length; } __attribute__ ((__packed__)) lcaf_afi_list_hdr_t; #define LCAF_CAST(ptr_) ((lcaf_hdr_t *)(ptr_)) #define LCAF_TYPE(ptr_) LCAF_CAST((ptr_))->type #define LCAF_AFI(ptr_) LCAF_CAST((ptr_))->afi /* Instance ID * Only the low order 24 bits should be used * Using signed integer, negative value means "don't send LCAF/IID field" * resulting in a non-explicit default IID value of 0 */ /* * Instance ID * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI = 16387 | Rsvd1 | Flags | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type = 2 | IID mask-len | 4 + n | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Instance ID | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI = x | Address ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ typedef struct lispd_pkt_lcaf_iid_t_ { uint32_t iid; uint16_t afi; } __attribute__ ((__packed__)) lispd_pkt_lcaf_iid_t; typedef struct _lcaf_iid_hdr_t{ uint16_t afi; uint8_t rsvd1; uint8_t flags; uint8_t type; uint8_t mlen; uint16_t len; uint32_t iid; } __attribute__ ((__packed__)) lcaf_iid_hdr_t; /* Geo Coordinate LISP Canonical Address Format: * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI = 16387 | Rsvd1 | Flags | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type = 5 | Rsvd2 | 12 + n | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |N| Latitude Degrees | Minutes | Seconds | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |E| Longitude Degrees | Minutes | Seconds | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Altitude | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI = x | Address ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ typedef struct _lcaf_geo_hdr_t{ uint16_t afi; uint8_t rsvd1; uint8_t flags; uint8_t type; uint8_t rsvd2; uint16_t length; #ifdef LITTLE_ENDIANS uint16_t latitude_deg:15; uint16_t latitude_dir:1; #else uint16_t latitude_dir:1; uint16_t latitude_deg:15; #endif uint8_t latitude_min; uint8_t latitude_sec; #ifdef LITTLE_ENDIANS uint16_t longitude_deg:15; uint16_t longitude_dir:1; #else uint16_t longitude_dir:1; uint16_t longitude_deg:15; #endif uint8_t longitude_min; uint8_t longitude_sec; uint32_t altitude; } __attribute__ ((__packed__)) lcaf_geo_hdr_t; /* * * NAT-Traversal Canonical Address Format: * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI = 16387 | Rsvd1 | Flags | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type = 7 | Rsvd2 | 4 + n | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | MS UDP Port Number | ETR UDP Port Number | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI = x | Global ETR RLOC Address ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI = x | MS RLOC Address ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI = x | Private ETR RLOC Address ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI = x | RTR RLOC Address 1 ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI = x | RTR RLOC Address k ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ typedef struct _lcaf_nat_hdr_t{ uint16_t afi; uint8_t rsvd1; uint8_t flags; uint8_t type; uint8_t rsvd2; uint16_t length; uint16_t ms_port; uint16_t etr_port; } __attribute__ ((__packed__)) lcaf_nat_hdr_t; #define NAT_CAST(ptr_)((lcaf_nat_hdr_t *)(ptr_)) #define NAT_LEN(ptr_) NAT_CAST((ptr_))->length #define NAT_MS_PORT(ptr_) NAT_CAST((ptr_))->ms_port #define NAT_ETR_PORT(ptr_) NAT_CAST((ptr_))->etr_port /* Multicast Info Canonical Address Format: * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI = 16387 | Rsvd1 | Flags | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type = 9 | Rsvd2 |R|L|J| 8 + n | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Instance-ID | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Reserved | Source MaskLen| Group MaskLen | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI = x | Source/Subnet Address ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI = x | Group Address ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ typedef struct _lcaf_mcinfo_hdr_t{ uint16_t afi; uint8_t rsvd1; uint8_t flags; uint8_t type; #ifdef LITTLE_ENDIANS uint8_t J:1; uint8_t L:1; uint8_t R:1; uint8_t rsvd2:5; #else uint8_t rsvd2:5; uint8_t R:1; uint8_t L:1; uint8_t J:1; #endif uint16_t len; uint32_t iid; uint16_t reserved; uint8_t src_mlen; uint8_t grp_mlen; } __attribute__ ((__packed__)) lcaf_mcinfo_hdr_t; typedef struct mrsignaling_flags_t_ { uint8_t rbit; uint8_t jbit; uint8_t lbit; } mrsignaling_flags_t; #define MCINFO_CAST(ptr_)((lcaf_mcinfo_hdr_t *)(ptr_)) #define MCINFO_RBIT(ptr_) MCINFO_CAST((ptr_))->R #define MCINFO_LBIT(ptr_) MCINFO_CAST((ptr_))->L #define MCINFO_JBIT(ptr_) MCINFO_CAST((ptr_))->J /* Explicit Locator Path (ELP) * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI = 16387 | Rsvd1 | Flags | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type = 10 | Rsvd2 | n | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Rsvd3 |L|P|S| AFI = x | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Reencap Hop 1 ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Rsvd3 |L|P|S| AFI = x | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Reencap Hop k ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * */ typedef struct _elp_node_flags { uint8_t rsvd1; #ifdef LITTLE_ENDIANS uint8_t S:1; uint8_t P:1; uint8_t L:1; uint8_t rsvd2:5; #else uint8_t rsvd2:5; uint8_t L:1; uint8_t P:1; uint8_t S:1; #endif } elp_node_flags; #define ELP_NODE_CAST(ptr_)((elp_node_flags *)(ptr_)) #define ELP_NODE_LBIT(ptr_) ELP_NODE_CAST((ptr_))->L #define ELP_NODE_PBIT(ptr_) ELP_NODE_CAST((ptr_))->P #define ELP_NODE_SBIT(ptr_) ELP_NODE_CAST((ptr_))->S /* Replication List Entry Address Format: * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI = 16387 | Rsvd1 | Flags | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type = 13 | Rsvd2 | 4 + n | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Rsvd3 | Rsvd4 | Level Value | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI = x | RTR/ETR #1 ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Rsvd3 | Rsvd4 | Level Value | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI = x | RTR/ETR #n ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ typedef struct _rle_node_hdr { uint8_t rsvd[3]; uint8_t level; } rle_node_hdr_t; typedef struct _address_hdr_t { uint16_t afi; } address_hdr_t; /* * LOCATOR FIELD */ /* * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * /| Priority | Weight | M Priority | M Weight | * L +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * o | Unused Flags |L|p|R| Loc-AFI | * c +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * \| Locator | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * * Fixed portion of the mapping record locator. Variable length * locator address follows. */ typedef struct _locator_hdr { uint8_t priority; uint8_t weight; uint8_t mpriority; uint8_t mweight; uint8_t unused1; #ifdef LITTLE_ENDIANS uint8_t reachable:1; uint8_t probed:1; uint8_t local:1; uint8_t unused2:5; #else uint8_t unused2:5; uint8_t local:1; uint8_t probed:1; uint8_t reachable:1; #endif } __attribute__ ((__packed__)) locator_hdr_t; #define LOC_CAST(h_) ((locator_hdr_t *)(h_)) #define LOC_PROBED(h_) LOC_CAST(h_)->probed #define LOC_PRIORITY(h_) LOC_CAST(h_)->priority #define LOC_WEIGHT(h_) LOC_CAST(h_)->weight #define LOC_MPRIORITY(h_) LOC_CAST(h_)->mpriority #define LOC_MWEIGHT(h_) LOC_CAST(h_)->mweight #define LOC_REACHABLE(h_) LOC_CAST(h_)->reachable #define LOC_LOCAL(h_) LOC_CAST(h_)->local #define LOC_ADDR(h_) ((uint8_t *)(h_) + sizeof(locator_hdr_t)) /* * MAPPING RECORD */ /* * Mapping record used in all LISP control messages. * * +---> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | | Record TTL | * | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * R | Locator Count | EID mask-len | ACT |A| Reserved | * e +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * c | Rsvd | Map-Version Number | EID-AFI | * o +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * r | EID-prefix | * d +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | /| Priority | Weight | M Priority | M Weight | * | / +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Loc | Unused Flags |L|p|R| Loc-AFI | * | \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | \| Locator | * +---> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ /* * Fixed portion of the mapping record. EID prefix address and * locators follow. */ typedef struct _mapping_record_hdr_t { uint32_t ttl; uint8_t locator_count; uint8_t eid_prefix_length; #ifdef LITTLE_ENDIANS uint8_t reserved1:4; uint8_t authoritative:1; uint8_t action:3; #else uint8_t action:3; uint8_t authoritative:1; uint8_t reserved1:4; #endif uint8_t reserved2; #ifdef LITTLE_ENDIANS uint8_t version_hi:4; uint8_t reserved3:4; #else uint8_t reserved3:4; uint8_t version_hi:4; #endif uint8_t version_low; } __attribute__ ((__packed__)) mapping_record_hdr_t; void mapping_record_init_hdr(mapping_record_hdr_t *h); char *mapping_action_to_char(int act); char *mapping_record_hdr_to_char(mapping_record_hdr_t *h); #define MAP_REC_EID_PLEN(h) ((mapping_record_hdr_t *)(h))->eid_prefix_length #define MAP_REC_LOC_COUNT(h) ((mapping_record_hdr_t *)(h))->locator_count #define MAP_REC_ACTION(h) ((mapping_record_hdr_t *)(h))->action #define MAP_REC_AUTH(h) ((mapping_record_hdr_t *)(h))->authoritative #define MAP_REC_TTL(h) ((mapping_record_hdr_t *)(h))->ttl #define MAP_REC_EID(h) (uint8_t *)(h)+sizeof(mapping_record_hdr_t) #define MAP_REC_VERSION(h) (h)->version_hi << 8 | (h)->version_low typedef enum lisp_actions { ACT_NO_ACTION = 0, ACT_NATIVE_FWD, ACT_SEND_MREQ, ACT_DROP } lisp_action_e; typedef enum lisp_authoritative { A_NO_AUTHORITATIVE = 0, A_AUTHORITATIVE } lisp_authoritative_e; /* * EID RECORD FIELD */ /* * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * / | Reserved | EID mask-len | EID-prefix-AFI | * Rec +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * \ | EID-prefix ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ typedef struct _eid_prefix_record_hdr { uint8_t reserved; uint8_t eid_prefix_length; } __attribute__ ((__packed__)) eid_record_hdr_t; void eid_rec_hdr_init(eid_record_hdr_t *ptr); #define EID_REC_CAST(h_) ((eid_record_hdr_t *)(h_)) #define EID_REC_MLEN(h_) EID_REC_CAST((h_))->eid_prefix_length #define EID_REC_ADDR(h) (uint8_t *)(h) + sizeof(eid_record_hdr_t) /* * AUTHENTICATION FIELD (Map-Register and Map-Notify) */ /* * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Key ID | Authentication Data Length | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * ~ Authentication Data ~ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * */ typedef struct auth_field_hdr { uint16_t key_id; uint16_t auth_data_len; } __attribute__ ((__packed__)) auth_record_hdr_t; typedef enum lisp_key_type { NO_KEY, HMAC_SHA_1_96, HMAC_SHA_256_128 } lisp_key_type_e; #define LISP_SHA1_AUTH_DATA_LEN 20 uint16_t auth_data_get_len_for_type(lisp_key_type_e key_id); #define AUTH_REC_CAST(h_) ((auth_record_hdr_t *)(h_)) #define AUTH_REC_KEY_ID(h_) AUTH_REC_CAST((h_))->key_id #define AUTH_REC_DATA_LEN(h_) AUTH_REC_CAST((h_))->auth_data_len #define AUTH_REC_DATA(h_) ((uint8_t *)(h_))+sizeof(auth_record_hdr_t) /* * RTR AUTHENTICATION FIELD (Map-Register and Map-Notify) */ /* * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |AD Type| Reserved | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | MS-RTR Key ID | MS-RTR Auth. Data Length | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * ~ MS-RTR Authentication Data ~ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ typedef enum rtr_auth_ad_type_ { RTR_AUTH_DATA = 2 } rtr_auth_data_type; typedef struct _rtr_auth_field_hdr { #ifdef LITTLE_ENDIANS uint16_t reserved1; uint8_t reserved2; uint8_t reserved3:3; uint8_t ad_type:5; #else uint8_t ad_type:5; uint8_t reserved3:3; uint8_t reserved2; uint16_t reserved1; #endif uint16_t key_id; uint16_t rtr_auth_data_len; } __attribute__ ((__packed__)) rtr_auth_field_hdr; /* NAT MAP-REGISTER FIELDS */ typedef struct lispd_xTR_ID_{ uint8_t byte[16]; } lisp_xtr_id; typedef uint64_t lisp_site_id; char *locator_record_hdr_to_char(locator_hdr_t *h); #endif /* LISP_MESSAGE_FIELDS_H_ */ oor-1.2.0/oor/liblisp/lisp_messages.c000066400000000000000000000215301313612200500175420ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include #include #include "lisp_messages.h" #include "../lib/mem_util.h" //#include /* The maximum length of the headers, when we have IPv6 encapsulated control messages * is 100 bytes. Allocate 150 for safety */ #define MAX_HEADERS_LEN 150 void map_request_hdr_init(void *ptr) { map_request_hdr_t *mrp = ptr; mrp->type = LISP_MAP_REQUEST; mrp->authoritative = 0; mrp->map_data_present = 0; /* default no map-data present */ mrp->rloc_probe = 0; /* default not rloc probe */ mrp->solicit_map_request = 0; /* default not smr */ mrp->smr_invoked = 0; /* default not smr-invoked */ mrp->additional_itr_rloc_count = 0; /* to be filled in later */ mrp->record_count = 0; /* to be filled in later */ mrp->nonce = 0; /* to be filled in later */ mrp->pitr = 0; /* default not sent by PITR */ mrp->reserved1 = 0; mrp->reserved2 = 0; } void map_reply_hdr_init(void *ptr) { map_reply_hdr_t *mrp = ptr; mrp->type = LISP_MAP_REPLY; mrp->rloc_probe = 0; /* default not rloc-probe */ mrp->record_count = 0; /* to be filled in later */ mrp->echo_nonce = 0; /* default not reply to echo nonce req */ mrp->security = 0; /* default no security */ mrp->nonce = 0; /* to be filled in later */ mrp->reserved1 = 0; mrp->reserved2 = 0; mrp->reserved3 = 0; } void map_register_hdr_init(void *ptr) { map_register_hdr_t *mrp = ptr; mrp->type = LISP_MAP_REGISTER; mrp->proxy_reply = 0; /* default no proxy-map-reply */ mrp->map_notify = 1; /* default want map-notify */ mrp->nonce = 0; /* to be filled in later */ mrp->record_count = 0; /* to be filled in later */ mrp->rbit = 0; /* default not NATT */ mrp->ibit = 0; /* default not NATT */ mrp->reserved1 = 0; mrp->reserved2 = 0; mrp->reserved3 = 0; } void map_notify_hdr_init(void *ptr) { map_notify_hdr_t *mrp = ptr; mrp->type = LISP_MAP_NOTIFY; mrp->record_count = 0; /* to be filled in later */ mrp->rtr_auth_present = 0; /* to be filled in later */ mrp->xtr_id_present = 0; /* to be filled in later */ mrp->nonce = 0; /* to be filled in later */ mrp->reserved1 = 0; mrp->reserved2 = 0; } void ecm_hdr_init(void *ptr) { ecm_hdr_t *ecm = ptr; ecm->type = LISP_ENCAP_CONTROL_TYPE; ecm->s_bit = 0; ecm->d_bit = 0; ecm->r_bit = 0; memset(ecm->reserved2, 0, sizeof(ecm->reserved2)); } void info_nat_hdr_init(void *ptr) { info_nat_hdr_t *irp = ptr; irp->type = LISP_INFO_NAT; irp->nonce = 0; irp->r_bit_info_reply = INFO_REQUEST; irp->reserved1 = 0; irp->reserved2[0] = 0; irp->reserved2[1] = 0; irp->reserved2[2] = 0; } void info_nat_hdr_2_init(void *ptr) { info_nat_hdr_2_t *irp = ptr; irp->eid_mask_len = 0; irp->ttl = 0; irp->reserved = 0; } char * mreq_flags_to_char(map_request_hdr_t *h) { static char buf[25]; *buf = '\0'; h->authoritative ? sprintf(buf+strlen(buf), "a=1,") : sprintf(buf+strlen(buf), "a=0,"); h->map_data_present ? sprintf(buf+strlen(buf), "m=1,") : sprintf(buf+strlen(buf), "m=0,"); h->rloc_probe ? sprintf(buf+strlen(buf), "p=1,") : sprintf(buf+strlen(buf), "p=0,"); h->solicit_map_request ? sprintf(buf+strlen(buf), "s=1,") : sprintf(buf+strlen(buf), "s=0,"); h->pitr ? sprintf(buf+strlen(buf), "P=1,") : sprintf(buf+strlen(buf), "P=0,"); h->smr_invoked ? sprintf(buf+strlen(buf), "S=1") : sprintf(buf+strlen(buf), "S=0"); return(buf); } char * map_request_hdr_to_char(map_request_hdr_t *h) { static char buf[120]; if (!h) { return(NULL); } *buf = '\0'; snprintf(buf,sizeof(buf), BOLD "Map-Request" RESET"-> flags:%s, irc: %d (+1), record-count: %d, " "nonce: %"PRIx64, mreq_flags_to_char(h), h->additional_itr_rloc_count, h->record_count, h->nonce); return(buf); } char * mrep_flags_to_char(map_reply_hdr_t *h) { static char buf[12]; *buf = '\0'; h->rloc_probe ? sprintf(buf+strlen(buf), "P=1,") : sprintf(buf+strlen(buf), "P=0,"); h->echo_nonce ? sprintf(buf+strlen(buf), "E=1,") : sprintf(buf+strlen(buf), "E=0,"); h->security ? sprintf(buf+strlen(buf), "S=1") : sprintf(buf+strlen(buf), "S=0"); return(buf); } char * map_reply_hdr_to_char(map_reply_hdr_t *h) { static char buf[100]; if (!h) { return(NULL); } snprintf(buf,sizeof(buf), BOLD "Map-Reply" RESET "-> flags:%s, record-count: %d, nonce: %"PRIx64, mrep_flags_to_char(h), h->record_count, h->nonce); return(buf); } char * info_nat_hdr_to_char(info_nat_hdr_t *h) { static char buf[100]; if (!h) { return(NULL); } *buf = '\0'; if (INF_REQ_R_bit(h) == INFO_REQUEST){ sprintf(buf, BOLD "Info Request" RESET " -> nonce %"PRIx64,h->nonce); }else{ sprintf(buf, BOLD "Info Reply" RESET " -> nonce %"PRIx64,h->nonce); } return(buf); } char * mreg_flags_to_char(map_register_hdr_t *h) { static char buf[5]; *buf = '\0'; h->proxy_reply ? sprintf(buf, "P") : sprintf(buf+strlen(buf), "p"); h->ibit ? sprintf(buf+strlen(buf), "I") : sprintf(buf+strlen(buf), "i"); h->rbit ? sprintf(buf+strlen(buf), "R") : sprintf(buf+strlen(buf), "r"); h->map_notify ? sprintf(buf+strlen(buf), "M") : sprintf(buf+strlen(buf), "m"); return(buf); } char * map_register_hdr_to_char(map_register_hdr_t *h) { static char buf[100]; if (!h) { return(NULL); } *buf = '\0'; snprintf(buf,sizeof(buf), BOLD "Map-Register" RESET " -> flags:%s record-count: %d nonce %"PRIx64, mreg_flags_to_char(h), h->record_count, h->nonce); return(buf); } char * mntf_flags_to_char(map_notify_hdr_t *h) { static char buf[3]; h->xtr_id_present ? sprintf(buf, "I") : sprintf(buf, "i"); h->rtr_auth_present ? sprintf(buf+strlen(buf), "R") : sprintf(buf+strlen(buf), "r"); return(buf); } char * map_notify_hdr_to_char(map_notify_hdr_t *h) { static char buf[100]; if (!h) { return(NULL); } *buf = '\0'; snprintf(buf,sizeof(buf), BOLD "Map-Notify" RESET "-> flags:%s, record-count: %d, nonce %"PRIX64, mntf_flags_to_char(h), h->record_count, h->nonce); return(buf); } char * ecm_flags_to_char(ecm_hdr_t *h) { static char buf[2]; h->s_bit ? sprintf(buf, "S") : sprintf(buf, "s"); return(buf); } char * ecm_hdr_to_char(ecm_hdr_t *h) { static char buf[50]; if (!h) { return(NULL); } snprintf(buf,sizeof(buf), BOLD "ECM" RESET " -> flags:%s", ecm_flags_to_char(h)); return(buf); } /* Given the start of an address field, @addr, checks if the address is an * MCAST_INFO LCAF that carries mrsignaling flags */ uint8_t is_mrsignaling(address_hdr_t *addr) { return(ntohs(LCAF_AFI(addr)) == LISP_AFI_LCAF && LCAF_TYPE(addr) == LCAF_MCAST_INFO && (MCINFO_JBIT(addr) || MCINFO_LBIT(addr))); } /* Given the start of an address field, @addr, checks if the address is used * for mrsignaling, in which case it returns the mrsignaling flags */ mrsignaling_flags_t mrsignaling_flags(address_hdr_t *addr) { lcaf_mcinfo_hdr_t *hdr; mrsignaling_flags_t mc_flags = {.rbit = 0, .jbit = 0, .lbit = 0}; if (!is_mrsignaling(addr)) { return(mc_flags); } hdr = (lcaf_mcinfo_hdr_t *)addr; if (hdr->J == 1 && hdr->L == 1) { // lmlog(LDBG_1, "Both join and leave flags are set in " // "mrsignaling msg. Discarding!"); return(mc_flags); } mc_flags = (mrsignaling_flags_t){.rbit = hdr->R, .jbit = hdr->J, .lbit = hdr->L}; return(mc_flags); } /** * @offset: pointer to start of the mapping record */ void mrsignaling_set_flags_in_pkt(uint8_t *offset, mrsignaling_flags_t *mrsig) { lcaf_mcinfo_hdr_t *mc_ptr; // offset = CO(offset, sizeof(mapping_record_hdr_t) + sizeof(uint16_t)); mc_ptr = (lcaf_mcinfo_hdr_t *) offset; mc_ptr->J = mrsig->jbit; mc_ptr->L = mrsig->lbit; mc_ptr->R = mrsig->rbit; } oor-1.2.0/oor/liblisp/lisp_messages.h000066400000000000000000000501211313612200500175450ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef LISP_MESSAGES_H_ #define LISP_MESSAGES_H_ #include "lisp_message_fields.h" #include #include "../lib/mem_util.h" /* LISP Types */ typedef enum lisp_msg_type_ { NOT_LISP_MSG, LISP_MAP_REQUEST = 1, LISP_MAP_REPLY, LISP_MAP_REGISTER, LISP_MAP_NOTIFY, LISP_INFO_NAT = 7, LISP_ENCAP_CONTROL_TYPE = 8 } lisp_msg_type_e; /* * ENCAPSULATED CONTROL MESSAGE */ /* * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * / | IPv4 or IPv6 Header | * OH | (uses RLOC addresses) | * \ | | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * / | Source Port = xxxx | Dest Port = 4342 | * UDP +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * \ | UDP Length | UDP Checksum | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * LH |Type=8 |S| Reserved | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * / | IPv4 or IPv6 Header | * IH | (uses RLOC or EID addresses) | * \ | | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * / | Source Port = xxxx | Dest Port = yyyy | * UDP +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * \ | UDP Length | UDP Checksum | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * LCM | LISP Control Message | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ /* * Encapsulated control message header. This is followed by the IP * header of the encapsulated LISP control message. * * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |Type=8 |S|D|R| Reserved | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ typedef struct ecm_hdr { #ifdef LITTLE_ENDIANS uint8_t n_bit:1; // RTR relays the ECM-ed Map-Register to a Map-Server uint8_t r_bit:1; // The encapsulated msg is to be processed by an RTR uint8_t d_bit:1; // DDT originated uint8_t s_bit:1; uint8_t type:4; #else uint8_t type:4; uint8_t s_bit:1; uint8_t d_bit:1; uint8_t r_bit:1; uint8_t n_bit:1; #endif uint8_t reserved2[3]; } ecm_hdr_t; char *ecm_hdr_to_char(ecm_hdr_t *h); void ecm_hdr_init(void *ptr); #define ECM_HDR_CAST(h_) ((ecm_hdr_t *)(h_)) #define ECM_TYPE(h_) (ECM_HDR_CAST(h_))->type #define ECM_SECURITY_BIT(h_) (ECM_HDR_CAST(h_))->s_bit #define ECM_DDT_BIT(h_) (ECM_HDR_CAST(h_))->d_bit #define ECM_RTR_PROCESS_BIT(h_) (ECM_HDR_CAST(h_))->r_bit /* * MAP-REQUEST MESSAGE */ /* * Map-Request Message Format * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |Type=1 |A|M|P|S|p|s| Reserved | IRC | Record Count | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Nonce . . . | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | . . . Nonce | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Source-EID-AFI | Source EID Address ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | ITR-RLOC-AFI 1 | ITR-RLOC Address 1 ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | ITR-RLOC-AFI n | ITR-RLOC Address n ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * / | Reserved | EID mask-len | EID-prefix-AFI | * Rec +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * \ | EID-prefix ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Map-Reply Record ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Mapping Protocol Data | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ /* * Fixed size portion of the map request. Variable size source EID * address, originating ITR RLOC AFIs and addresses and then map * request records follow. */ typedef struct map_request_hdr { #ifdef LITTLE_ENDIANS uint8_t solicit_map_request:1; uint8_t rloc_probe:1; uint8_t map_data_present:1; uint8_t authoritative:1; uint8_t type:4; #else uint8_t type:4; uint8_t authoritative:1; uint8_t map_data_present:1; uint8_t rloc_probe:1; uint8_t solicit_map_request:1; #endif #ifdef LITTLE_ENDIANS uint8_t reserved1:6; uint8_t smr_invoked:1; uint8_t pitr:1; #else uint8_t pitr:1; uint8_t smr_invoked:1; uint8_t reserved1:6; #endif #ifdef LITTLE_ENDIANS uint8_t additional_itr_rloc_count:5; uint8_t reserved2:3; #else uint8_t reserved2:3; uint8_t additional_itr_rloc_count:5; #endif uint8_t record_count; uint64_t nonce; } __attribute__ ((__packed__)) map_request_hdr_t; void map_request_hdr_init(void *ptr); char *map_request_hdr_to_char(map_request_hdr_t *h); #define MREQ_HDR_CAST(h_) ((map_request_hdr_t *)(h_)) #define MREQ_REC_COUNT(h_) (MREQ_HDR_CAST(h_))->record_count #define MREQ_RLOC_PROBE(h_) (MREQ_HDR_CAST(h_))->rloc_probe #define MREQ_ITR_RLOC_COUNT(h_) (MREQ_HDR_CAST(h_))->additional_itr_rloc_count #define MREQ_NONCE(h_) (MREQ_HDR_CAST(h_))->nonce #define MREQ_SMR(h_) (MREQ_HDR_CAST(h_))->solicit_map_request #define MREQ_SMR_INVOKED(h_) (MREQ_HDR_CAST(h_))->smr_invoked /* * MAP-REPLY MESSAGE */ /* Map Reply action codes */ #define LISP_ACTION_NO_ACTION 0 #define LISP_ACTION_FORWARD 1 #define LISP_ACTION_DROP 2 #define LISP_ACTION_SEND_MAP_REQUEST 3 /* * Map-Reply Message Format * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |Type=2 |P|E|S| Reserved | Record Count | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Nonce . . . | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | . . . Nonce | * +-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | | Record TTL | * | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * R | Locator Count | EID mask-len | ACT |A| Reserved | * e +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * c | Rsvd | Map-Version Number | EID-AFI | * o +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * r | EID-prefix | * d +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | /| Priority | Weight | M Priority | M Weight | * | L +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | o | Unused Flags |L|p|R| Loc-AFI | * | c +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | \| Locator | * +-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Mapping Protocol Data | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ /* * Fixed size portion of the map reply. */ typedef struct map_reply_hdr { #ifdef LITTLE_ENDIANS uint8_t reserved1:1; uint8_t security:1; uint8_t echo_nonce:1; uint8_t rloc_probe:1; uint8_t type:4; #else uint8_t type:4; uint8_t rloc_probe:1; uint8_t echo_nonce:1; uint8_t security:1; uint8_t reserved1:1; #endif uint8_t reserved2; uint8_t reserved3; uint8_t record_count; uint64_t nonce; } __attribute__ ((__packed__)) map_reply_hdr_t; void map_reply_hdr_init(void *ptr); char *map_reply_hdr_to_char(map_reply_hdr_t *h); #define MREP_HDR_CAST(h_) ((map_reply_hdr_t *)(h_)) #define MREP_REC_COUNT(h_) MREP_HDR_CAST(h_)->record_count #define MREP_RLOC_PROBE(h_) MREP_HDR_CAST(h_)->rloc_probe #define MREP_NONCE(h_) MREP_HDR_CAST(h_)->nonce /* * MAP-NOTIFY MESSAGE */ /* * Map-Notify Message Format * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |Type=4 |I|R| Reserved | Record Count | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Nonce . . . | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | . . . Nonce | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Key ID | Authentication Data Length | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * ~ Authentication Data ~ * +-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | | Record TTL | * | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * R | Locator Count | EID mask-len | ACT |A| Reserved | * e +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * c | Rsvd | Map-Version Number | EID-prefix-AFI | * o +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * r | EID-prefix | * d +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | /| Priority | Weight | M Priority | M Weight | * | L +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | o | Unused Flags |L|p|R| Loc-AFI | * | c +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | \| Locator | * +-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ typedef struct map_notify_hdr { #ifdef LITTLE_ENDIANS uint8_t reserved1:2; uint8_t rtr_auth_present:1; uint8_t xtr_id_present:1; uint8_t type:4; #else uint8_t type:4; uint8_t xtr_id_present:1; uint8_t rtr_auth_present:1; uint8_t reserved1:2; #endif uint16_t reserved2; uint8_t record_count; uint64_t nonce; } __attribute__ ((__packed__)) map_notify_hdr_t; void map_notify_hdr_init(void *ptr); char *map_notify_hdr_to_char(map_notify_hdr_t *h); #define MNTF_HDR_CAST(h_) ((map_notify_hdr_t *)(h_)) #define MNTF_I_BIT(h_) (MNTF_HDR_CAST((h_)))->xtr_id_present #define MNTF_XTR_ID_PRESENT(h_) (MNTF_HDR_CAST((h_)))->xtr_id_present #define MNTF_R_BIT(h_) (MNTF_HDR_CAST((h_)))->rtr_auth_present #define MNTF_RTR_AUTH_PRESENT(h_) (MNTF_HDR_CAST((h_)))->rtr_auth_present #define MNTF_REC_COUNT(h_) MNTF_HDR_CAST((h_))->record_count #define MNTF_NONCE(h_) MNTF_HDR_CAST((h_))->nonce /* * MAP-REGISTER MESSAGE */ /* * Map-Registers have an authentication header before the UDP header. * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |Type=3 |P| |I|R| Reserved |M| Record Count | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Nonce . . . | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | . . . Nonce | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Key ID | Authentication Data Length | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * ~ Authentication Data ~ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Mapping Records ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ /* * Map-Register Message Format * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |Type=3 |P| |I|R| Reserved |M| Record Count | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Nonce . . . | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | . . . Nonce | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Key ID | Authentication Data Length | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * ~ Authentication Data ~ * +-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | | Record TTL | * | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * R | Locator Count | EID mask-len | ACT |A| Reserved | * e +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * c | Rsvd | Map-Version Number | EID-prefix-AFI | * o +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * r | EID-prefix | * d +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | /| Priority | Weight | M Priority | M Weight | * | L +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | o | Unused Flags |L|p|R| Loc-AFI | * | c +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | \| Locator | * +-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ /* I and R bit are defined on NAT tarversal draft*/ typedef struct map_register_hdr { #ifdef LITTLE_ENDIANS uint8_t rbit:1; uint8_t ibit:1; uint8_t reserved1:1; uint8_t proxy_reply:1; uint8_t type:4; #else uint8_t type:4; uint8_t proxy_reply:1; uint8_t reserved1:1; uint8_t ibit:1; uint8_t rbit:1; #endif uint8_t reserved2; #ifdef LITTLE_ENDIANS uint8_t map_notify:1; uint8_t lisp_mn:1; uint8_t reserved3:6; #else uint8_t reserved3:6; uint8_t lisp_mn:1; uint8_t map_notify:1; #endif uint8_t record_count; uint64_t nonce; } __attribute__ ((__packed__)) map_register_hdr_t; void map_register_hdr_init(void *ptr); char *map_register_hdr_to_char(map_register_hdr_t *h); #define MREG_HDR_CAST(h_) ((map_register_hdr_t *)(h_)) #define MREG_REC_COUNT(h_) MREG_HDR_CAST((h_))->record_count #define MREG_WANT_MAP_NOTIFY(h_) (MREG_HDR_CAST(h_))->map_notify #define MREG_NONCE(h_) (MREG_HDR_CAST(h_))->nonce #define MREG_PROXY_REPLY(h_)(MREG_HDR_CAST(h_))->proxy_reply #define MREG_IBIT(h_)(MREG_HDR_CAST(h_))->ibit #define MREG_RBIT(h_)(MREG_HDR_CAST(h_))->rbit /* Info Request type */ #define INFO_REQUEST 0 #define INFO_REPLY 1 /* * Info Request Message Format * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |Type=7 |R| Reserved | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Nonce . . . | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | . . . Nonce | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Key ID | Authentication Data Length | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * ~ Authentication Data ~ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | TTL | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Reserved | EID mask-len | EID-prefix-AFI | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | EID-prefix | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI = 0 | | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ **/ typedef struct info_nat_hdr { #ifdef LITTLE_ENDIANS uint8_t reserved1:3; uint8_t r_bit_info_reply:1; uint8_t type:4; #else uint8_t type:4; uint8_t r_bit_info_reply:1; uint8_t reserved1:3; #endif uint8_t reserved2[3]; uint64_t nonce; } __attribute__ ((__packed__)) info_nat_hdr_t; typedef struct info_nat_hdr_2 { uint32_t ttl; uint8_t reserved; uint8_t eid_mask_len; } __attribute__ ((__packed__)) info_nat_hdr_2_t; char *info_nat_hdr_to_char(info_nat_hdr_t *h); void info_nat_hdr_init(void *ptr); void info_nat_hdr_2_init(void *ptr); #define INF_REQ_HDR_CAST(h_) ((info_nat_hdr_t *)(h_)) #define INF_REQ_R_bit(h_) (INF_REQ_HDR_CAST(h_))->r_bit_info_reply #define INF_REQ_NONCE(h_) (INF_REQ_HDR_CAST(h_))->nonce #define INF_REQ_HDR_2_CAST(h_) ((info_nat_hdr_2_t *)(h_)) #define INF_REQ_2_TTL(h_) (INF_REQ_HDR_2_CAST(h_))->ttl #define INF_REQ_2_EID_MASK(h_) (INF_REQ_HDR_2_CAST(h_))->eid_mask_len uint8_t is_mrsignaling(address_hdr_t *addr); mrsignaling_flags_t mrsignaling_flags(address_hdr_t *addr); void mrsignaling_set_flags_in_pkt(uint8_t *offset, mrsignaling_flags_t *mrsig); #endif /* LISP_MESSAGES_H_ */ oor-1.2.0/oor/modelines000066400000000000000000000001641313612200500150040ustar00rootroot00000000000000 /* * Editor modelines * * vi: set shiftwidth=4 tabstop=4 expandtab: * :indentSize=4:tabSize=4:noTabs=true: */ oor-1.2.0/oor/net_mgr/000077500000000000000000000000001313612200500145345ustar00rootroot00000000000000oor-1.2.0/oor/net_mgr/kernel/000077500000000000000000000000001313612200500160145ustar00rootroot00000000000000oor-1.2.0/oor/net_mgr/kernel/iface_mgmt.c000066400000000000000000000455631313612200500202700ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include #include #include #include #include #include "iface_mgmt.h" #include "netm_kernel.h" #include "../net_mgr.h" #include "../net_mgr_proc_fc.h" #include "../../defs.h" #include "../../oor_external.h" #include "../../lib/oor_log.h" #include "../../lib/prefixes.h" #include "../../lib/sockets-util.h" /************************* FUNCTION DECLARTAION ********************************/ void process_nl_add_address (struct nlmsghdr *nlh); void process_nl_del_address (struct nlmsghdr *nlh); void process_nl_new_link (struct nlmsghdr *nlh); void process_nl_new_route (struct nlmsghdr *nlh); void process_nl_new_unicast_route (struct rtmsg *rtm, int rt_length); void process_nl_new_multicast_route (struct rtmsg *rtm, int rt_length); void process_nl_del_route (struct nlmsghdr *nlh); void process_nl_del_unicast_route(struct rtmsg *rtm, int rt_length); void process_nl_del_multicast_route (struct rtmsg *rtm, int rt_length); int process_nl_mcast_route_attributes(struct rtmsg *rtm, int rt_length, lisp_addr_t *src, lisp_addr_t *grp); /*******************************************************************************/ int process_netlink_msg(struct sock *sl) { int len = 0; char buffer[4096]; struct iovec iov; struct sockaddr_nl dst_addr; struct msghdr msgh; struct nlmsghdr *nlh; nlh = (struct nlmsghdr *) buffer; memset(&iov, 0, sizeof(iov)); iov.iov_base = (void *) nlh; iov.iov_len = sizeof(nlh); memset(&msgh, 0, sizeof(msgh)); msgh.msg_name = (void *) &(dst_addr); msgh.msg_namelen = sizeof(dst_addr); msgh.msg_iov = &iov; msgh.msg_iovlen = 1; while ((len = recv(sl->fd, nlh, 4096, MSG_DONTWAIT)) > 0) { for (; (NLMSG_OK(nlh, len)) && (nlh->nlmsg_type != NLMSG_DONE); nlh = NLMSG_NEXT(nlh, len)) { switch (nlh->nlmsg_type) { case RTM_NEWADDR: OOR_LOG(LDBG_2, "==>process_netlink_msg: Received new address " "message"); process_nl_add_address(nlh); break; case RTM_DELADDR: OOR_LOG(LDBG_2, "==>process_netlink_msg: Received del address " "message"); process_nl_del_address(nlh); break; case RTM_NEWLINK: OOR_LOG(LDBG_2, "==>process_netlink_msg: Received link " "message"); process_nl_new_link(nlh); break; case RTM_NEWROUTE: OOR_LOG(LDBG_2, "==>process_netlink_msg: Received new route " "message"); process_nl_new_route(nlh); break; case RTM_DELROUTE: OOR_LOG(LDBG_2, "==>process_netlink_msg: Received delete route " "message"); process_nl_del_route(nlh); break; default: break; } } nlh = (struct nlmsghdr *) buffer; memset(nlh, 0, 4096); } return (GOOD); } void process_nl_add_address (struct nlmsghdr *nlh) { struct ifaddrmsg *ifa; struct rtattr *rth; int iface_index; int rt_length; lisp_addr_t new_addr = { .lafi = LM_AFI_IP }; /* * Get the new address from the net link message */ ifa = (struct ifaddrmsg *) NLMSG_DATA (nlh); iface_index = ifa->ifa_index; rth = IFA_RTA (ifa); rt_length = IFA_PAYLOAD(nlh); for (;rt_length && RTA_OK (rth, rt_length);rth = RTA_NEXT (rth,rt_length)) { if (ifa->ifa_family == AF_INET && rth->rta_type == IFA_LOCAL){ lisp_addr_ip_init(&new_addr, RTA_DATA(rth), ifa->ifa_family); nm_process_address_change (ADD,iface_index, &new_addr); } if (ifa->ifa_family == AF_INET6 && rth->rta_type == IFA_ADDRESS){ lisp_addr_ip_init(&new_addr, RTA_DATA(rth), ifa->ifa_family); nm_process_address_change (ADD, iface_index, &new_addr); } } } void process_nl_del_address(struct nlmsghdr *nlh) { struct ifaddrmsg *ifa; struct rtattr *rth; int iface_index; int rt_length; lisp_addr_t new_addr; ifa = (struct ifaddrmsg *) NLMSG_DATA(nlh); iface_index = ifa->ifa_index; rth = IFA_RTA(ifa); rt_length = IFA_PAYLOAD(nlh); for (; rt_length && RTA_OK(rth, rt_length);rth = RTA_NEXT(rth, rt_length)) { if ((ifa->ifa_family == AF_INET && rth->rta_type == IFA_LOCAL) || (ifa->ifa_family == AF_INET6 && rth->rta_type == IFA_ADDRESS)){ lisp_addr_ip_init(&new_addr, RTA_DATA(rth), ifa->ifa_family); break; } } nm_process_address_change (RM,iface_index, &new_addr); } void process_nl_new_link(struct nlmsghdr *nlh) { struct ifinfomsg *ifi; iface_t *iface; int iface_index; int old_iface_index; uint8_t new_status; char iface_name[IF_NAMESIZE]; ifi = (struct ifinfomsg *) NLMSG_DATA (nlh); iface_index = ifi->ifi_index; iface = get_interface_from_index(iface_index); if (iface == NULL) { /* * In some OS when a virtual interface is removed and added again, * the index of the interface change. Search iface_t by the interface * name and update the index. */ if (if_indextoname(iface_index, iface_name) != NULL) { iface = get_interface(iface_name); } if (iface == NULL) { OOR_LOG(LDBG_2, "process_nl_new_link: the netlink message is not for " "any interface associated with RLOCs (%s)", iface_name); return; } else { old_iface_index = iface->iface_index; } }else{ old_iface_index = iface_index; } /* Get the new status */ if ((ifi->ifi_flags & IFF_RUNNING) != 0) { new_status = UP; } else { new_status = DOWN; } nm_process_link_change(old_iface_index, iface_index, new_status); } void process_nl_new_route (struct nlmsghdr *nlh) { struct rtmsg *rtm; int rt_length; rtm = (struct rtmsg *) NLMSG_DATA (nlh); rt_length = RTM_PAYLOAD(nlh); /* Interested only in unicast or multicast updates */ if (rtm->rtm_type == RTN_UNICAST) { process_nl_new_unicast_route(rtm, rt_length); } else if (rtm->rtm_type == RTN_MULTICAST) { process_nl_new_multicast_route(rtm, rt_length); } } void process_nl_new_unicast_route(struct rtmsg *rtm, int rt_length) { struct rtattr *rt_attr; int iface_index = ~0; lisp_addr_t gateway = { .lafi = LM_AFI_IP }; lisp_addr_t src = { .lafi = LM_AFI_IP }; lisp_addr_t dst = { .lafi = LM_AFI_IP }; int src_len; int dst_len; /* Interested only in main table updates for unicast */ if (rtm->rtm_table != RT_TABLE_MAIN) return; if ( rtm->rtm_family != AF_INET && rtm->rtm_family != AF_INET6 ) { OOR_LOG(LDBG_3,"process_nl_new_unicast_route: New unicast route of " "unknown address family %d", rtm->rtm_family); return; } src_len = rtm->rtm_src_len; dst_len = rtm->rtm_dst_len; rt_attr = (struct rtattr *)RTM_RTA(rtm); for (; RTA_OK(rt_attr, rt_length); rt_attr = RTA_NEXT(rt_attr, rt_length)) { switch (rt_attr->rta_type) { case RTA_OIF: iface_index = *(int *)RTA_DATA(rt_attr); break; case RTA_GATEWAY: lisp_addr_ip_init(&gateway, RTA_DATA(rt_attr), rtm->rtm_family); break; case RTA_SRC: lisp_addr_ip_init(&src, RTA_DATA(rt_attr), rtm->rtm_family); lisp_addr_set_plen(&src,src_len); break; case RTA_DST: lisp_addr_ip_init(&dst, RTA_DATA(rt_attr), rtm->rtm_family); lisp_addr_set_plen(&dst,dst_len); break; default: break; } } nm_process_route_change(ADD, iface_index, &src,&dst,&gateway); } void process_nl_new_multicast_route(struct rtmsg *rtm, int rt_length) { // lisp_addr_t srcaddr = {.lafi = LM_AFI_IP}; // lisp_addr_t grpaddr = {.lafi = LM_AFI_IP}; OOR_LOG(LDBG_1, "process_nl_new_multicast_route: Not yet implented, ignored!"); // /* IPv4 multicast routes are part of the default table and have // * family 128, while IPv6 multicast routes are part of the main table // * and have family 129 ... */ // if ( !((rtm->rtm_table == RT_TABLE_DEFAULT && rtm->rtm_family == 128) || // (rtm->rtm_table == RT_TABLE_MAIN && rtm->rtm_family == 129) ) ) // return; // // if (process_nl_mcast_route_attributes(rtm, rt_length, &srcaddr, &grpaddr) // == BAD) { // return; // } // // multicast_join_channel(&srcaddr, &grpaddr); } int process_nl_mcast_route_attributes(struct rtmsg *rtm, int rt_length, lisp_addr_t *rt_srcaddr, lisp_addr_t *rt_grpaddr) { struct rtattr *rt_attr; iface_t *iface; int iface_index; char iface_name[IF_NAMESIZE+1]; struct rtnexthop *rt_nh; int nb_oifs = 0; int rtnh_length = 0; char ifnames[1024] = { 0 }; rt_attr = (struct rtattr *)RTM_RTA(rtm); for (; RTA_OK(rt_attr, rt_length); rt_attr = RTA_NEXT(rt_attr, rt_length)) { switch (rt_attr->rta_type) { case RTA_DST: switch(rtm->rtm_family) { case 128: lisp_addr_ip_init(rt_grpaddr, RTA_DATA(rt_attr), AF_INET); break; case 129: lisp_addr_ip_init(rt_grpaddr, RTA_DATA(rt_attr), AF_INET6); break; default: break; } break; case RTA_SRC: switch (rtm->rtm_family) { case 128: lisp_addr_ip_init(rt_srcaddr, RTA_DATA(rt_attr), AF_INET); break; case 129: lisp_addr_ip_init(rt_srcaddr, RTA_DATA(rt_attr), AF_INET6); break; default: break; } break; case RTA_MULTIPATH: rt_nh = (struct rtnexthop *)RTA_DATA(rt_attr); rtnh_length = RTA_PAYLOAD(rt_attr); for (; RTNH_OK(rt_nh, rtnh_length); rt_nh = RTNH_NEXT(rt_nh)) { /* Check if one of the interfaces is the gateway */ iface = get_interface_from_index(rt_nh->rtnh_ifindex); iface_index = *(int *)RTA_DATA(rt_attr); iface = get_interface_from_index(iface_index); if (iface != NULL){ if_indextoname(iface_index, iface_name); OOR_LOG(LINF, "process_nl_new_multicast_route: the " "multicast route message is for an interface " "that has RLOCs associated (%s). Ignoring!", iface_name); return BAD; } /* Prepare output for debug */ if_indextoname(rt_nh->rtnh_ifindex, iface_name); sprintf(ifnames, "%s ", iface_name); nb_oifs++; } break; default: break; } } if (nb_oifs == 0){ OOR_LOG(LDBG_1, "process_nl_new_multicast_route: New multicast route has " "no output interface list, ignored!"); return BAD; } OOR_LOG(LINF, "New multicast route with source %s, group %s for interfaces " "%s", lisp_addr_to_char(rt_srcaddr), lisp_addr_to_char(rt_grpaddr), ifnames); return GOOD; } void process_nl_del_route(struct nlmsghdr *nlh) { struct rtmsg *rtm; int rt_length; rtm = (struct rtmsg *) NLMSG_DATA (nlh); rt_length = RTM_PAYLOAD(nlh); /* Interested only in unicast or multicast updates */ if (rtm->rtm_type == RTN_UNICAST) { process_nl_del_unicast_route(rtm, rt_length); } else if (rtm->rtm_type == RTN_MULTICAST) { process_nl_del_multicast_route(rtm, rt_length); } } void process_nl_del_unicast_route(struct rtmsg *rtm, int rt_length) { struct rtattr *rt_attr; int iface_index = ~0; lisp_addr_t gateway = { .lafi = LM_AFI_IP }; lisp_addr_t src = { .lafi = LM_AFI_IP }; lisp_addr_t dst = { .lafi = LM_AFI_IP }; int src_len; int dst_len; /* Interested only in main table updates for unicast */ if (rtm->rtm_table != RT_TABLE_MAIN) return; if ( rtm->rtm_family != AF_INET && rtm->rtm_family != AF_INET6 ) { OOR_LOG(LDBG_3,"process_nl_del_unicast_route: New unicast route of " "unknown address family %d", rtm->rtm_family); return; } src_len = rtm->rtm_src_len; dst_len = rtm->rtm_dst_len; rt_attr = (struct rtattr *)RTM_RTA(rtm); for (; RTA_OK(rt_attr, rt_length); rt_attr = RTA_NEXT(rt_attr, rt_length)) { switch (rt_attr->rta_type) { case RTA_OIF: iface_index = *(int *)RTA_DATA(rt_attr); break; case RTA_GATEWAY: lisp_addr_ip_init(&gateway, RTA_DATA(rt_attr), rtm->rtm_family); break; case RTA_SRC: lisp_addr_ip_init(&src, RTA_DATA(rt_attr), rtm->rtm_family); lisp_addr_set_plen(&src,src_len); break; case RTA_DST: lisp_addr_ip_init(&dst, RTA_DATA(rt_attr), rtm->rtm_family); lisp_addr_set_plen(&dst,dst_len); break; default: break; } } nm_process_route_change(RM, iface_index, &src,&dst,&gateway); } void process_nl_del_multicast_route (struct rtmsg *rtm, int rt_length) { lisp_addr_t rt_groupaddr = {.lafi=LM_AFI_IP}; lisp_addr_t rt_srcaddr = {.lafi=LM_AFI_IP}; if ( !((rtm->rtm_table == RT_TABLE_DEFAULT && rtm->rtm_family == 128) || (rtm->rtm_table == RT_TABLE_MAIN && rtm->rtm_family == 129) ) ) return; if (process_nl_mcast_route_attributes(rtm, rt_length, &rt_srcaddr, &rt_groupaddr) == BAD) return; //multicast_leave_channel(&rt_srcaddr, &rt_groupaddr); } void iface_mac_address(char *iface_name, uint8_t *mac) { int fd; struct ifreq ifr; int i = 0; fd = socket(AF_INET, SOCK_DGRAM, 0); memset(&ifr, 0, sizeof(ifr)); ifr.ifr_addr.sa_family = AF_INET; strncpy(ifr.ifr_name, iface_name, IFNAMSIZ-1); ioctl(fd, SIOCGIFHWADDR, &ifr); close(fd); for (i = 0 ; i < 6 ; i++){ mac[i] = (unsigned char)ifr.ifr_hwaddr.sa_data[i]; } return; } lisp_addr_t * get_network_pref_of_host(lisp_addr_t *address) { lisp_addr_t net_prefix = { .lafi = LM_AFI_IP }; int netlink_fd; struct sockaddr_nl addr; struct nlmsghdr *nlh, *rcvhdr; struct rtmsg *rtm, *recv_rtm; struct rtattr *rt_attr; char sndbuf[4096],rcvbuf[4096]; int rta_len = 0, retval, readlen, recv_pyload_len, afi; memset(&addr, 0, sizeof(addr)); addr.nl_family = AF_NETLINK; if (lisp_addr_ip_afi(address) == AF_INET){ afi = AF_INET; addr.nl_groups = RTMGRP_IPV4_ROUTE; }else{ afi = AF_INET6; addr.nl_groups = RTMGRP_IPV6_ROUTE; } netlink_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); if (netlink_fd < 0) { OOR_LOG(LERR, "get_network_associated_addrress: Failed to connect to " "netlink socket"); return (NULL); } bind(netlink_fd, (struct sockaddr *) &addr, sizeof(addr)); memset(sndbuf, 0, 4096); nlh = (struct nlmsghdr *)sndbuf; rtm = (struct rtmsg *)(CO(sndbuf,sizeof(struct nlmsghdr))); rta_len = sizeof(struct rtmsg); nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; nlh->nlmsg_type = RTM_GETROUTE; nlh->nlmsg_len = NLMSG_LENGTH(rta_len); rtm->rtm_family = afi; rtm->rtm_table = RT_TABLE_MAIN; rtm->rtm_protocol = RTPROT_STATIC; rtm->rtm_scope = RT_SCOPE_UNIVERSE; rtm->rtm_type = RTN_UNICAST; rtm->rtm_src_len = 0; rtm->rtm_tos = 0; rtm->rtm_dst_len = 0; retval = send(netlink_fd, sndbuf, nlh->nlmsg_len, 0); if (retval < 0) { OOR_LOG(LCRIT, "get_network_associated_addrress: send netlink command failed %s", strerror(errno)); return (NULL); } /* * Receive the responses from the kernel */ while ((readlen = recv(netlink_fd,rcvbuf,4096,MSG_DONTWAIT)) > 0){ rcvhdr = (struct nlmsghdr *)rcvbuf; /* * Walk through everything it sent us */ for (; NLMSG_OK(rcvhdr, (unsigned int)readlen); rcvhdr = NLMSG_NEXT(rcvhdr, readlen)) { recv_pyload_len = RTM_PAYLOAD(rcvhdr); if (rcvhdr->nlmsg_type == RTM_NEWROUTE) { recv_rtm = (struct rtmsg *)NLMSG_DATA(rcvhdr); rt_attr = (struct rtattr *)RTM_RTA(recv_rtm); for (; RTA_OK(rt_attr, recv_pyload_len); rt_attr = RTA_NEXT(rt_attr, recv_pyload_len)) { switch (rt_attr->rta_type) { case RTA_DST: if ((rtm->rtm_family == AF_INET && recv_rtm->rtm_dst_len == 32) || (rtm->rtm_family == AF_INET6 && recv_rtm->rtm_dst_len == 128) ){ break; } lisp_addr_ip_init(&net_prefix, RTA_DATA(rt_attr), rtm->rtm_family); lisp_addr_set_plen(&net_prefix,recv_rtm->rtm_dst_len); if (pref_is_addr_part_of_prefix(address,&net_prefix) == TRUE){ goto find; } break; default: break; } } } } } close(netlink_fd); OOR_LOG(LDBG_3, "get_network_pref_of_host: No network prefix found for host %s", lisp_addr_to_char(address)); return (NULL); find: close(netlink_fd); OOR_LOG(LDBG_3, "get_network_pref_of_host: Network prefix for host %s is %s", lisp_addr_to_char(address), lisp_addr_to_char(&net_prefix)); return (lisp_addr_clone(&net_prefix)); } oor-1.2.0/oor/net_mgr/kernel/iface_mgmt.h000066400000000000000000000020141313612200500202550ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef IFACE_MGMT_H_ #define IFACE_MGMT_H_ #include "iface_list.h" #include "lib/sockets.h" int process_netlink_msg(sock_t *sl); int get_all_ifaces_name_list(char ***ifaces,int *count); lisp_addr_t * get_network_pref_of_host(lisp_addr_t *address); lisp_addr_t * iface_get_getway(int iface_index, int afi); #endif /* IFACE_MGMT_H_ */ oor-1.2.0/oor/net_mgr/kernel/netm_kernel.c000066400000000000000000000560121313612200500204670ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include #ifndef ANDROID #include #endif #include #include #include #include "iface_mgmt.h" #include "netm_kernel.h" #include "../net_mgr.h" #include "../../lib/oor_log.h" #include "../../lib/sockets.h" int krn_netm_init(); void krn_netm_uninit(); glist_t * krn_get_ifaces_names(); glist_t * krn_get_iface_addr_list(char *iface_name, int afi); lisp_addr_t * krn_get_src_addr_to(lisp_addr_t * addr); lisp_addr_t * krn_get_iface_gw(char *iface_name, int afi); uint8_t krn_get_iface_status(char * iface_name); int krn_get_iface_index(char *iface_name); void krn_get_iface_mac_addr(char *iface_name, uint8_t *mac); int krn_reload_routes(uint32_t table, int afi); shash_t *krn_build_addr_to_if_name_hasht(); #ifdef ANDROID int getifaddrs(ifaddrs **addrlist); int freeifaddrs(ifaddrs *addrlist); #endif net_mgr_class_t netm_kernel = { .netm_init = krn_netm_init, .netm_uninit = krn_netm_uninit, .netm_get_ifaces_names = krn_get_ifaces_names, .netm_get_iface_addr_list = krn_get_iface_addr_list, .netm_get_src_addr_to = krn_get_src_addr_to, .netm_get_iface_gw = krn_get_iface_gw, .netm_get_iface_status = krn_get_iface_status, .netm_get_iface_index = krn_get_iface_index, .netm_get_iface_mac_addr = krn_get_iface_mac_addr, .netm_reload_routes = krn_reload_routes, .netm_build_addr_to_if_name_hasht = krn_build_addr_to_if_name_hasht, .data = NULL }; int krn_netm_init() { netm_data_type *data; data = xzalloc(sizeof(netm_data_type)); if (!data){ return (BAD); } netm_kernel.data = data; /* Create net_link socket to receive notifications of changes of RLOC * status. */ data->netlink_fd = opent_netlink_socket(); sockmstr_register_read_listener(smaster, process_netlink_msg, NULL, data->netlink_fd); return (GOOD); } void krn_netm_uninit() { netm_data_type *data = (netm_data_type *)netm_kernel.data; //socket is closed by sockmstr free(data); } glist_t * krn_get_ifaces_names() { glist_t *iface_names = glist_new_managed((glist_del_fct)free); struct nlmsghdr *nlh, *rcvhdr; struct ifinfomsg *ifm, *if_msg; char sndbuf[4096],rcvbuf[4096],name[IF_NAMESIZE]; int ifa_len, retval,readlen; int netlk_fd; netlk_fd = opent_netlink_socket(); if (netlk_fd == ERR_SOCKET){ OOR_LOG(LERR, "krn_get_ifaces_names: Error opening netlink socket"); return (BAD); } /* * Build the command */ memset(sndbuf, 0, 4096); nlh = (struct nlmsghdr *)sndbuf; ifm = (struct ifinfomsg *)(CO(sndbuf,sizeof(struct nlmsghdr))); ifa_len = sizeof(struct ifinfomsg); nlh->nlmsg_len = NLMSG_LENGTH(ifa_len); nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; nlh->nlmsg_type = RTM_GETLINK; ifm->ifi_family = AF_PACKET; retval = send(netlk_fd, sndbuf, NLMSG_LENGTH(ifa_len), 0); if (retval < 0) { OOR_LOG(LERR, "krn_get_ifaces_names: send netlink command failed: %s", strerror(errno)); close(netlk_fd); return(NULL); } /* * Receive the responses from the kernel */ while ((readlen = recv(netlk_fd,rcvbuf,4096,MSG_DONTWAIT)) > 0){ rcvhdr = (struct nlmsghdr *)rcvbuf; /* * Walk through everything it sent us */ for (; NLMSG_OK(rcvhdr, (unsigned int)readlen); rcvhdr = NLMSG_NEXT(rcvhdr, readlen)) { if (rcvhdr->nlmsg_type == RTM_NEWLINK) { if_msg = (struct ifinfomsg *)NLMSG_DATA(rcvhdr); if (if_indextoname(if_msg->ifi_index, name) != NULL){ glist_add(strdup(name),iface_names); } } } } close(netlk_fd); return (iface_names); } glist_t * krn_get_iface_addr_list(char *iface_name, int afi) { glist_t *addr_list = glist_new_managed((glist_del_fct)lisp_addr_del); lisp_addr_t *addr; struct ifaddrs *ifaddr; struct ifaddrs *ifa; struct sockaddr_in *s4; struct sockaddr_in6 *s6; ip_addr_t ip; /* search for the interface */ if (getifaddrs(&ifaddr) !=0) { OOR_LOG(LDBG_2, "krn_get_iface_addr_list: getifaddrs error: %s", strerror(errno)); return(addr_list); } for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { if ((ifa->ifa_addr == NULL) || ((ifa->ifa_flags & IFF_UP) == 0) || (ifa->ifa_addr->sa_family != afi) || strcmp(ifa->ifa_name, iface_name) != 0) { continue; } switch (ifa->ifa_addr->sa_family) { case AF_INET: s4 = (struct sockaddr_in *) ifa->ifa_addr; ip_addr_init(&ip, &s4->sin_addr, AF_INET); if (ip_addr_is_link_local(&ip) == TRUE) { OOR_LOG(LDBG_2, "krn_get_iface_addr_list: interface address from " "%s discarded (%s)", iface_name, ip_addr_to_char(&ip)); continue; } break; case AF_INET6: s6 = (struct sockaddr_in6 *) ifa->ifa_addr; ip_addr_init(&ip, &s6->sin6_addr, AF_INET6); if (ip_addr_is_link_local(&ip) == TRUE) { OOR_LOG(LDBG_2, "krn_get_iface_addr_list: interface address from " "%s discarded (%s)", iface_name, ip_addr_to_char(&ip)); continue; } break; default: continue; /* XXX */ } addr = lisp_addr_new(); lisp_addr_init_from_ip(addr, &ip); glist_add(addr, addr_list); } freeifaddrs(ifaddr); if (glist_size(addr_list) == 0){ OOR_LOG(LDBG_3, "krn_get_iface_addr_list: No %s RLOC configured for interface " "%s\n", (afi == AF_INET) ? "IPv4" : "IPv6", iface_name); } return(addr_list); } lisp_addr_t * krn_get_src_addr_to(lisp_addr_t * dst_addr){ lisp_addr_t src_addr; int netlink_fd; struct sockaddr_nl addr; struct nlmsghdr *nlh, *rcvhdr; struct rtmsg *rtm, *recv_rtm; struct rtattr *rt_attr; char sndbuf[4096],rcvbuf[4096]; int retval, readlen, recv_pyload_len; int afi; afi = lisp_addr_ip_afi(dst_addr); /* Open netlink socket */ memset(&addr, 0, sizeof(addr)); addr.nl_family = AF_NETLINK; if (afi == AF_INET){ addr.nl_groups = RTMGRP_IPV4_ROUTE; }else{ addr.nl_groups = RTMGRP_IPV6_ROUTE; } netlink_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); if (netlink_fd < 0) { OOR_LOG(LERR, "krn_get_src_addr_to: Failed to connect to " "netlink socket"); return (NULL); } bind(netlink_fd, (struct sockaddr *) &addr, sizeof(addr)); /* Request route to destination address */ memset(sndbuf, 0, 4096); nlh = (struct nlmsghdr *)sndbuf; rtm = (struct rtmsg *)(CO(sndbuf,sizeof(struct nlmsghdr))); rt_attr = (struct rtattr *)(CO(rtm, sizeof(struct rtmsg))); nlh->nlmsg_flags = NLM_F_REQUEST; nlh->nlmsg_type = RTM_GETROUTE; rtm->rtm_family = afi; rtm->rtm_table = RT_TABLE_MAIN; rtm->rtm_protocol = RTPROT_STATIC; rtm->rtm_scope = RT_SCOPE_UNIVERSE; rtm->rtm_type = RTN_UNICAST; rtm->rtm_src_len = 0; rtm->rtm_tos = 0; rtm->rtm_dst_len = (afi == AF_INET ? 32 : 128); /* * Add dst address */ rt_attr->rta_type = RTA_DST; rt_attr->rta_len = sizeof(struct rtattr) + ip_sock_afi_to_size(afi); lisp_addr_copy_to(((char *)rt_attr) + sizeof(struct rtattr), dst_addr); nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg) + rt_attr->rta_len); retval = send(netlink_fd, sndbuf,nlh->nlmsg_len, 0); if (retval < 0) { OOR_LOG(LCRIT, "krn_get_src_addr_to: send netlink command failed %s", strerror(errno)); close(netlink_fd); return (NULL); } /* Receive answer */ while ((readlen = recv(netlink_fd,rcvbuf,4096,MSG_DONTWAIT)) > 0){ rcvhdr = (struct nlmsghdr *)rcvbuf; /* * Walk through everything it sent us */ for (; NLMSG_OK(rcvhdr, (unsigned int)readlen); rcvhdr = NLMSG_NEXT(rcvhdr, readlen)) { recv_pyload_len = RTM_PAYLOAD(rcvhdr); if (rcvhdr->nlmsg_type == RTM_NEWROUTE) { recv_rtm = (struct rtmsg *)NLMSG_DATA(rcvhdr); rt_attr = (struct rtattr *)RTM_RTA(recv_rtm); for (; RTA_OK(rt_attr, recv_pyload_len); rt_attr = RTA_NEXT(rt_attr, recv_pyload_len)) { switch (rt_attr->rta_type) { case RTA_PREFSRC: lisp_addr_ip_init(&src_addr, RTA_DATA(rt_attr), rtm->rtm_family); close(netlink_fd); return (lisp_addr_clone(&src_addr)); default: break; } } } } } close(netlink_fd); return (NULL); } lisp_addr_t * krn_get_iface_gw(char *iface_name, int afi) { lisp_addr_t gateway = { .lafi = LM_AFI_IP }; int netlink_fd; struct sockaddr_nl addr; struct nlmsghdr *nlh, *rcvhdr; struct rtmsg *rtm, *recv_rtm; struct rtattr *rt_attr; char sndbuf[4096],rcvbuf[4096]; int rta_len = 0, retval, readlen, recv_pyload_len, iface_id, attrs; uint32_t iface_index; iface_index= if_nametoindex(iface_name); memset(&addr, 0, sizeof(addr)); addr.nl_family = AF_NETLINK; if (afi == AF_INET){ addr.nl_groups = RTMGRP_IPV4_ROUTE; }else{ addr.nl_groups = RTMGRP_IPV6_ROUTE; } netlink_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); if (netlink_fd < 0) { OOR_LOG(LERR, "krn_get_iface_gw: Failed to connect to " "netlink socket"); return (NULL); } bind(netlink_fd, (struct sockaddr *) &addr, sizeof(addr)); memset(sndbuf, 0, 4096); nlh = (struct nlmsghdr *)sndbuf; rtm = (struct rtmsg *)(CO(sndbuf,sizeof(struct nlmsghdr))); rta_len = sizeof(struct rtmsg); nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; nlh->nlmsg_type = RTM_GETROUTE; nlh->nlmsg_len = NLMSG_LENGTH(rta_len); rtm->rtm_family = afi; rtm->rtm_table = RT_TABLE_MAIN; rtm->rtm_protocol = RTPROT_STATIC; rtm->rtm_scope = RT_SCOPE_UNIVERSE; rtm->rtm_type = RTN_UNICAST; rtm->rtm_src_len = 0; rtm->rtm_tos = 0; rtm->rtm_dst_len = 0; retval = send(netlink_fd, sndbuf, nlh->nlmsg_len, 0); if (retval < 0) { OOR_LOG(LCRIT, "iface_get_getway: send netlink command failed %s", strerror(errno)); return (NULL); } /* * Receive the responses from the kernel */ while ((readlen = recv(netlink_fd,rcvbuf,4096,MSG_DONTWAIT)) > 0){ rcvhdr = (struct nlmsghdr *)rcvbuf; /* * Walk through everything it sent us */ for (; NLMSG_OK(rcvhdr, (unsigned int)readlen); rcvhdr = NLMSG_NEXT(rcvhdr, readlen)) { recv_pyload_len = RTM_PAYLOAD(rcvhdr); iface_id = 0; if (rcvhdr->nlmsg_type == RTM_NEWROUTE) { recv_rtm = (struct rtmsg *)NLMSG_DATA(rcvhdr); rt_attr = (struct rtattr *)RTM_RTA(recv_rtm); attrs = 0; for (; RTA_OK(rt_attr, recv_pyload_len); rt_attr = RTA_NEXT(rt_attr, recv_pyload_len)) { switch (rt_attr->rta_type) { case RTA_OIF: iface_id = *(int *)RTA_DATA(rt_attr); attrs++; break; case RTA_GATEWAY: lisp_addr_ip_init(&gateway, RTA_DATA(rt_attr), rtm->rtm_family); attrs++; break; default: break; } } if (iface_id == iface_index && attrs == 2 ){ goto find; } } } } OOR_LOG(LDBG_3, "iface_get_getway: No gateway detected for interface %s",iface_name); close(netlink_fd); return (NULL); find: close(netlink_fd); OOR_LOG(LDBG_3, "iface_get_getway: The gateway for interface %s is %s", iface_name, lisp_addr_to_char(&gateway)); return (lisp_addr_clone(&gateway)); } uint8_t krn_get_iface_status(char * iface_name) { uint8_t status = ERR_NO_EXIST; struct nlmsghdr *nlh, *rcvhdr; struct ifinfomsg *ifm, *if_msg; char sndbuf[4096],rcvbuf[4096]; int ifa_len, retval,readlen; int netlk_fd; int iface_index; iface_index = if_nametoindex(iface_name); if (iface_index == 0){ OOR_LOG(LERR, "krn_get_iface_status: Iface %s doesn't exist",iface_name); return (ERR_NO_EXIST); } netlk_fd = opent_netlink_socket(); if (netlk_fd == ERR_SOCKET){ OOR_LOG(LERR, "krn_get_iface_status: Error opening netlink socket"); return (ERR_SOCKET); } /* * Build the command */ memset(sndbuf, 0, 4096); nlh = (struct nlmsghdr *)sndbuf; ifm = (struct ifinfomsg *)(CO(sndbuf,sizeof(struct nlmsghdr))); ifa_len = sizeof(struct ifinfomsg); nlh->nlmsg_len = NLMSG_LENGTH(ifa_len); nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; nlh->nlmsg_type = RTM_GETLINK; ifm->ifi_family = AF_PACKET; retval = send(netlk_fd, sndbuf, NLMSG_LENGTH(ifa_len), 0); if (retval < 0) { OOR_LOG(LERR, "krn_get_iface_status: send netlink command failed: %s", strerror(errno)); close(netlk_fd); return(ERR_SOCKET); } /* * Receive the responses from the kernel */ while ((readlen = recv(netlk_fd,rcvbuf,4096,MSG_DONTWAIT)) > 0){ rcvhdr = (struct nlmsghdr *)rcvbuf; /* * Walk through everything it sent us */ for (; NLMSG_OK(rcvhdr, (unsigned int)readlen); rcvhdr = NLMSG_NEXT(rcvhdr, readlen)) { if (rcvhdr->nlmsg_type == RTM_NEWLINK) { if_msg = (struct ifinfomsg *)NLMSG_DATA(rcvhdr); if (if_msg->ifi_index == iface_index){ /* Get the new status */ if ((if_msg->ifi_flags & IFF_RUNNING) != 0) { status = UP; } else { status = DOWN; } break; } } } } close(netlk_fd); return (status); } int krn_get_iface_index(char *iface_name) { return (if_nametoindex(iface_name)); } void krn_get_iface_mac_addr(char *iface_name, uint8_t *mac) { int fd; struct ifreq ifr; int i = 0; fd = socket(AF_INET, SOCK_DGRAM, 0); memset(&ifr, 0, sizeof(ifr)); ifr.ifr_addr.sa_family = AF_INET; strncpy(ifr.ifr_name, iface_name, IFNAMSIZ-1); ioctl(fd, SIOCGIFHWADDR, &ifr); close(fd); for (i = 0 ; i < 6 ; i++){ mac[i] = (unsigned char)ifr.ifr_hwaddr.sa_data[i]; } return; } /* * Request to the kernel the routing table with the selected afi */ int krn_reload_routes(uint32_t table, int afi) { struct nlmsghdr *nlh = NULL; struct rtmsg *rtm = NULL; char sndbuf[4096]; int rta_len = 0; int retval = 0; netm_data_type *data; /* * Build the command */ memset(sndbuf, 0, 4096); nlh = (struct nlmsghdr *)sndbuf; rtm = (struct rtmsg *)(CO(sndbuf,sizeof(struct nlmsghdr))); rta_len = sizeof(struct rtmsg); nlh->nlmsg_len = NLMSG_LENGTH(rta_len); nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; nlh->nlmsg_type = RTM_GETROUTE; rtm->rtm_family = afi; if (table == 0){ rtm->rtm_table = RT_TABLE_MAIN; }else{ rtm->rtm_table = table; } rtm->rtm_protocol = RTPROT_STATIC; rtm->rtm_scope = RT_SCOPE_UNIVERSE; rtm->rtm_type = RTN_UNICAST; rtm->rtm_src_len = 0; rtm->rtm_tos = 0; rtm->rtm_dst_len = 0; data = (netm_data_type *)netm_kernel.data; retval = send(data->netlink_fd, sndbuf, NLMSG_LENGTH(rta_len), 0); if (retval < 0) { OOR_LOG(LCRIT, "krn_reload_routes: send netlink command failed %s", strerror(errno)); return (BAD); } return (GOOD); } shash_t *krn_build_addr_to_if_name_hasht() { shash_t *ht; struct ifaddrs *ifaddr, *ifa; int family, s; char host[NI_MAXHOST]; OOR_LOG(LDBG_1, "Building address to interface hash table"); if (getifaddrs(&ifaddr) == -1) { OOR_LOG(LCRIT, "Can't read the interfaces of the system. Exiting .. "); exit_cleanup(); } ht = shash_new_managed((free_value_fn_t)free); for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { if (ifa->ifa_addr == NULL) { continue; } family = ifa->ifa_addr->sa_family; if (family == AF_INET || family == AF_INET6) { s = getnameinfo(ifa->ifa_addr, (family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6), host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); if (s != 0) { OOR_LOG(LWRN, "getnameinfo() failed: %s. Skipping interface. ", gai_strerror(s)); continue; } shash_insert(ht, strdup(host), strdup(ifa->ifa_name)); OOR_LOG(LDBG_2, "Found interface %s with address %s", ifa->ifa_name, host); } } freeifaddrs(ifaddr); return(ht); } #ifdef ANDROID /* * populate_ifaddr_entry() * * Fill in the ifaddr data structure with the info from * the rtnetlink message. */ int populate_ifaddr_entry(ifaddrs *ifaddr, int family, void *data, int ifindex, size_t count) { char buf[IFNAMSIZ]; char *name; int sockfd; struct ifreq ifr; int retval; struct sockaddr_in * sock_addr4; struct sockaddr_in6 * sock_addr6; name = if_indextoname(ifindex, buf); if (name == NULL) { return (BAD); } ifaddr->ifa_name = strdup(name); // Must free elsewhere XXX sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd == -1) { free(ifaddr->ifa_name); close(sockfd); return (BAD); } memset(&ifr, 0, sizeof(ifr)); strcpy(ifr.ifr_name, name); //ifr_name space reserved by the structure retval = ioctl(sockfd, SIOCGIFFLAGS, &ifr); if (retval == -1) { free(ifaddr->ifa_name); close(sockfd); return (BAD); } ifaddr->ifa_flags = ifr.ifr_flags; ifaddr->ifa_index = ifindex; if (family == AF_INET){ sock_addr4 = xzalloc(sizeof(struct sockaddr_in)); sock_addr4->sin_family = AF_INET; memcpy(&sock_addr4->sin_addr, data, sizeof(struct in_addr)); ifaddr->ifa_addr = (struct sockaddr *)sock_addr4; }else if (family == AF_INET6){ sock_addr6 = xzalloc(sizeof(struct sockaddr_in6)); sock_addr6->sin6_family = AF_INET6; memcpy(&sock_addr6->sin6_addr, data, sizeof(struct in6_addr)); ifaddr->ifa_addr = (struct sockaddr *)sock_addr6; } close(sockfd); return (GOOD); } /* * getifaddrs() * * Android (and other) compatible getifaddrs function, using * rtnetlink. Enumerates all interfaces on the device. */ int getifaddrs(ifaddrs **addrlist) { request_struct req; struct ifaddrmsg *addr; ifaddrs *prev; struct rtattr *rta; int afi; size_t msglen; int sockfd; char rcvbuf[4096]; int readlen; int retval; struct nlmsghdr *rcvhdr; lisp_addr_t new_addr = { .lafi = LM_AFI_IP }; *addrlist = NULL; /* * We open a separate socket here so the response can * be synchronous */ sockfd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); if (sockfd < 0) { return -1; } /* * Construct the request */ memset (&req,0,sizeof(request_struct)); req.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; //NLM_F_MATCH; req.nlh.nlmsg_type = RTM_GETADDR; req.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg)); req.rtmsg.rtgen_family = AF_UNSPEC; /* * Send it */ retval = send(sockfd, &req, req.nlh.nlmsg_len, 0); if (retval <= 0) { close(sockfd); return -1; } /* * Receive the responses from the kernel */ while ((readlen = read(sockfd, rcvbuf, 4096)) > 0) { rcvhdr = (struct nlmsghdr *)rcvbuf; /* * Walk through everything it sent us */ for (; NLMSG_OK(rcvhdr, (unsigned int)readlen); rcvhdr = NLMSG_NEXT(rcvhdr, readlen)) { switch (rcvhdr->nlmsg_type) { case NLMSG_DONE: close(sockfd); return 0; case NLMSG_ERROR: close(sockfd); return -1; case RTM_NEWADDR: addr = (struct ifaddrmsg *)NLMSG_DATA(rcvhdr); rta = IFA_RTA(addr); msglen = IFA_PAYLOAD(rcvhdr); while (RTA_OK(rta, msglen)) { /* * Only care about local addresses of our interfaces */ if (rta->rta_type == IFA_ADDRESS) { afi = addr->ifa_family; if (*addrlist) { prev = *addrlist; } else { prev = NULL; } *addrlist = calloc(1,sizeof(ifaddrs)); // Must free elsewhere XXX (*addrlist)->ifa_next = prev; lisp_addr_ip_init(&new_addr, RTA_DATA(rta), afi); if ((populate_ifaddr_entry(*addrlist, afi, RTA_DATA(rta), addr->ifa_index, RTA_PAYLOAD(rta)))!=GOOD){ free (addrlist); } } rta = RTA_NEXT(rta, msglen); } break; default: break; } } } close(sockfd); return (0); } int freeifaddrs(ifaddrs *addrlist) { ifaddrs *ifa = addrlist; ifaddrs *ifa_prev; while (ifa){ free (ifa->ifa_name); switch (ifa->ifa_addr->sa_family){ case AF_INET: free ((struct sockaddr_in *)ifa->ifa_addr); break; case AF_INET6: free ((struct sockaddr_in6 *)ifa->ifa_addr); break; } ifa_prev = ifa; ifa = ifa->ifa_next; free (ifa_prev); } return (0); } #endif oor-1.2.0/oor/net_mgr/kernel/netm_kernel.h000066400000000000000000000024701313612200500204730ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef NETM_KERNEL_H_ #define NETM_KERNEL_H_ #ifdef ANDROID #include #include #endif typedef struct netm_data_type_ { int netlink_fd; }netm_data_type; #ifdef ANDROID /* * Different from oor_if_t to maintain * linux system call compatibility. */ typedef struct ifaddrs { struct ifaddrs *ifa_next; char *ifa_name; unsigned int ifa_flags; struct sockaddr *ifa_addr; int ifa_index; } ifaddrs; typedef struct { struct nlmsghdr nlh; struct rtgenmsg rtmsg; } request_struct; #endif #endif /* NETM_KERNEL_H_ */ oor-1.2.0/oor/net_mgr/net_mgr.c000066400000000000000000000015311313612200500163330ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "net_mgr.h" net_mgr_class_t *net_mgr = NULL; void net_mgr_select() { #ifdef VPP net_mgr = &netm_vpp; #else net_mgr = &netm_kernel; #endif } oor-1.2.0/oor/net_mgr/net_mgr.h000066400000000000000000000031571313612200500163460ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef NET_MGR_H_ #define NET_MGR_H_ #include "../lib/generic_list.h" #include "../lib/shash.h" #include "../liblisp/lisp_address.h" typedef struct net_mgr_class { int (*netm_init)(); void (*netm_uninit)(); glist_t *(*netm_get_ifaces_names)(); glist_t *(*netm_get_iface_addr_list)(char *, int); /*netm_get_src_addr_to only works for the gw*/ lisp_addr_t *(*netm_get_src_addr_to)(lisp_addr_t *); lisp_addr_t *(*netm_get_iface_gw)(char *,int); uint8_t (*netm_get_iface_status)(char *); int (*netm_get_iface_index)(char *); void (*netm_get_iface_mac_addr)(char *, uint8_t *); int (*netm_reload_routes)(uint32_t table, int afi); shash_t *(*netm_build_addr_to_if_name_hasht)(); char *(*netm_get_iface_associated_with_pref)(lisp_addr_t *addr); void * data; } net_mgr_class_t; void net_mgr_select(); extern net_mgr_class_t netm_kernel; extern net_mgr_class_t netm_vpp; #endif /* NET_MGR_H_ */ oor-1.2.0/oor/net_mgr/net_mgr_proc_fc.c000066400000000000000000000156611313612200500200370ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "net_mgr_proc_fc.h" #include "../control/oor_control.h" #include "../data-plane/data-plane.h" #include "../lib/oor_log.h" /* Change the address of the interface. If the address belongs to a not * initialized locator, activate it. Program SMR */ void nm_process_address_change(uint8_t act, uint32_t iface_index, lisp_addr_t *new_addr) { iface_t *iface; lisp_addr_t *iface_addr; lisp_addr_t *new_addr_cpy; lisp_addr_t *old_addr_cpy; int new_addr_ip_afi; iface = get_interface_from_index(iface_index); if (iface == NULL) { OOR_LOG(LDBG_2, "nm_process_address_change: the notification message is not " "for any interface associated with RLOCs (%d)", iface_index); return; } if (act == RM){ OOR_LOG(LDBG_2,"nm_process_address_change: Address %s removed from interface %s", lisp_addr_to_char(new_addr),iface->iface_name); return; } new_addr_ip_afi = lisp_addr_ip_afi(new_addr); iface_addr = iface_address(iface,new_addr_ip_afi); if (iface_addr == NULL){ OOR_LOG(LDBG_2,"nm_process_address_change: OOR not configured to use %s address for the interface %s", (new_addr_ip_afi == AF_INET ? "IPv4" : "IPv6"),iface->iface_name); return; } /* Check if the addres is a global address*/ if (ip_addr_is_link_local(lisp_addr_ip(new_addr)) == TRUE) { OOR_LOG(LDBG_2,"nm_process_address_change: the address is a local link " "address: %s discarded",lisp_addr_to_char(new_addr)); return; } /* If default RLOC afi defined (-a 4 or 6), only accept addresses of the * specified afi */ if (default_rloc_afi != AF_UNSPEC && default_rloc_afi != new_addr_ip_afi) { OOR_LOG(LDBG_2,"nm_process_address_change: Default RLOC afi defined (-a #): " "Skipped %s address in iface %s", (new_addr_ip_afi == AF_INET) ? "IPv4" : "IPv6", iface->iface_name); return; } /* Detected a valid change of address */ OOR_LOG(LDBG_2,"nm_process_address_change: New address detected for interface " "%s. Address changed from %s to %s", iface->iface_name, lisp_addr_to_char(iface_addr), lisp_addr_to_char(new_addr)); old_addr_cpy = lisp_addr_clone(iface_addr); new_addr_cpy = lisp_addr_clone(new_addr); /* Update interface */ lisp_addr_copy(iface_addr, new_addr); /* raise event to data plane */ OOR_LOG(LDBG_3,"nm_process_address_change: Updating data plane"); data_plane->datap_updated_addr(iface,old_addr_cpy,new_addr_cpy); /* raise event in ctrl */ OOR_LOG(LDBG_3,"nm_process_address_change: Updating control data plane"); ctrl_if_addr_update(lctrl, iface, old_addr_cpy, new_addr_cpy); lisp_addr_del(old_addr_cpy); lisp_addr_del(new_addr_cpy); } void nm_process_link_change(uint32_t old_iface_index, uint32_t new_iface_index, uint8_t new_status) { iface_t *iface; iface = get_interface_from_index(old_iface_index); if (!iface) { OOR_LOG(LDBG_2, "nm_process_link_change: the link change notification is not for " "any interface associated with RLOCs "); return; } /* Check if status has changed */ if (iface->status == new_status){ OOR_LOG(LDBG_2,"nm_process_link_change: The detected change of status" " doesn't affect"); return; } OOR_LOG(LDBG_2, "nm_process_link_change: The interface %s has changed its status to %s", iface->iface_name, new_status == UP ? "UP" : "DOWN"); /* Update iface */ iface->status = new_status; iface->iface_index = new_iface_index; /* raise event to data plane */ OOR_LOG(LDBG_3,"nm_process_link_change: Updating data plane"); data_plane->datap_update_link(iface, old_iface_index, new_iface_index, new_status); /* raise event in ctrl */ OOR_LOG(LDBG_3,"nm_process_link_change: Updating control data plane"); ctrl_if_link_update(lctrl, iface, old_iface_index, new_iface_index, new_status); } void nm_process_route_change(uint8_t act, uint32_t iface_index, lisp_addr_t *src, lisp_addr_t *dst, lisp_addr_t *gateway) { iface_t *iface; iface = get_interface_from_index(iface_index); if (iface == NULL){ OOR_LOG(LDBG_2, "nm_process_route_change: the route message is not for any " "interface associated with RLOCs (%d)", iface_index); return; } /* Check default afi*/ if (lisp_addr_ip_afi(src) != LM_AFI_NO_ADDR && default_rloc_afi != AF_UNSPEC && default_rloc_afi != lisp_addr_ip_afi(src)) { OOR_LOG(LDBG_1, "nm_process_route_change: Default RLOC afi " "defined (-a #): Skipped route with source address %s in iface %s", (lisp_addr_ip_afi(src)== AF_INET) ? "IPv4" : "IPv6", iface->iface_name); return; } if (lisp_addr_ip_afi(dst) != LM_AFI_NO_ADDR && default_rloc_afi != AF_UNSPEC && default_rloc_afi != lisp_addr_ip_afi(dst)) { OOR_LOG(LDBG_1, "nm_process_route_change: Default RLOC afi " "defined (-a #): Skipped route with destination address %s in iface %s", (lisp_addr_ip_afi(dst)== AF_INET) ? "IPv4" : "IPv6", iface->iface_name); return; } if (lisp_addr_ip_afi(gateway) != LM_AFI_NO_ADDR && default_rloc_afi != AF_UNSPEC && default_rloc_afi != lisp_addr_ip_afi(gateway)) { OOR_LOG(LDBG_1, "nm_process_route_change gateway %s in iface %s", (lisp_addr_ip_afi(gateway)== AF_INET) ? "IPv4" : "IPv6", iface->iface_name); return; } OOR_LOG(LDBG_2, "nm_process_route_change: %s route: src: %s, dst: %s , gw: %s", act == ADD ? "Added" : "Removed", lisp_addr_to_char(src), lisp_addr_to_char(dst), lisp_addr_to_char(gateway)); /* raise event to data plane */ OOR_LOG(LDBG_3,"nm_process_route_change: Updating data plane"); data_plane->datap_updated_route(act, iface, src, dst, gateway); /* raise event to control plane */ OOR_LOG(LDBG_3,"nm_process_route_change: Updating control data plane"); ctrl_route_update(lctrl, act, iface, src, dst, gateway); } oor-1.2.0/oor/net_mgr/net_mgr_proc_fc.h000066400000000000000000000024301313612200500200320ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef OOR_NET_MGR_NET_MGR_PROC_FC_H_ #define OOR_NET_MGR_NET_MGR_PROC_FC_H_ #include "../iface_list.h" /* Change the address of the interface. If the address belongs to a not * initialized locator, activate it. Program SMR */ void nm_process_address_change(uint8_t act, uint32_t iface_index, lisp_addr_t *new_addr); void nm_process_link_change(uint32_t old_iface_index, uint32_t new_iface_index, uint8_t new_status); void nm_process_route_change(uint8_t act, uint32_t iface_index, lisp_addr_t *src, lisp_addr_t *dst, lisp_addr_t *gateway); #endif /* OOR_NET_MGR_NET_MGR_PROC_FC_H_ */ oor-1.2.0/oor/net_mgr/vpp/000077500000000000000000000000001313612200500153415ustar00rootroot00000000000000oor-1.2.0/oor/net_mgr/vpp/netm_vpp.c000066400000000000000000000405311313612200500173400ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "netm_vpp.h" #include "../net_mgr.h" #include "../net_mgr_proc_fc.h" #include "../../iface_list.h" #include "../../lib/oor_log.h" #include "../../lib/prefixes.h" #include "../../lib/sockets.h" #include "../../lib/util.h" #include #include "../../lib/vpp_api/vpp_api_requests.h" #define vl_typedefs #include #undef vl_typedefs /* declare message handlers for each api */ #define vl_endianfun /* define message structures */ #include #undef vl_endianfun #include int vpp_netm_init(); void vpp_netm_uninit(); glist_t * vpp_get_ifaces_names(); glist_t * vpp_get_iface_addr_list(char *iface_name, int afi); lisp_addr_t * vpp_get_src_addr_to(lisp_addr_t *addr); lisp_addr_t * vpp_get_iface_gw(char *iface_name, int afi); uint8_t vpp_get_iface_status(char *iface_name); int vpp_get_iface_index(char *iface_name); void vpp_get_iface_mac_addr(char *iface_name, uint8_t *mac); char * vpp_get_iface_name_associated_with_prefix(lisp_addr_t * pref); int vpp_reload_routes(uint32_t table, int afi); shash_t * vpp_build_addr_to_if_name_hasht(); inline static netm_vpp_data_t * netm_vpp_data_new(); inline static void netm_vpp_data_free(netm_vpp_data_t * vpp_data); int process_vpp_link_msg(struct sock *sl); void vpp_process_link_change(vpp_nl_link_info *link_info, uint8_t status); void vpp_process_addr_change(vpp_nl_addr_info *addr_info,uint8_t act); net_mgr_class_t netm_vpp = { .netm_init = vpp_netm_init, .netm_uninit = vpp_netm_uninit, .netm_get_ifaces_names = vpp_get_ifaces_names, .netm_get_iface_index = vpp_get_iface_index, .netm_get_iface_addr_list = vpp_get_iface_addr_list, .netm_get_src_addr_to = vpp_get_src_addr_to, .netm_get_iface_gw = vpp_get_iface_gw, .netm_get_iface_status = vpp_get_iface_status, .netm_get_iface_mac_addr = vpp_get_iface_mac_addr, .netm_reload_routes = vpp_reload_routes, .netm_build_addr_to_if_name_hasht = vpp_build_addr_to_if_name_hasht, .netm_get_iface_associated_with_pref = vpp_get_iface_name_associated_with_prefix, .data = NULL }; int vpp_netm_init() { netm_vpp_data_t *data = netm_vpp_data_new(); int error; int fd,rc; size_t fd_size; data->zmq_context = zmq_ctx_new(); data->zmq_socket = zmq_socket(data->zmq_context, ZMQ_PULL); error = zmq_bind(data->zmq_socket, VPP_IPC_FILE); if (error != 0){ OOR_LOG(LDBG_1,"vpp_netm_init: Error while ZMQ binding on server: %s\n",zmq_strerror (errno)); netm_vpp_data_free(data); return (BAD); } netm_vpp.data = data; OOR_LOG(LDBG_1,"vpp_netm_init: VPP network notification socket initiated using ZMQ\n"); /* Get socket FD. When we receive an event in this socket, we should double check by checking * ZMQ_EVENTS option */ fd_size = sizeof(int); rc = zmq_getsockopt(data->zmq_socket, ZMQ_FD, &fd, &fd_size); if (rc == -1){ OOR_LOG(LDBG_1,"vpp_netm_init: Error while getting the fd of the ZMQ socket: %s\n",zmq_strerror (errno)); } sockmstr_register_read_listener(smaster, process_vpp_link_msg, NULL,fd); return (GOOD); } void vpp_netm_uninit() { netm_vpp_data_t *data = (netm_vpp_data_t *)netm_vpp.data; if (!data){ return; } zmq_close (data->zmq_socket); zmq_ctx_destroy (data->zmq_context); netm_vpp_data_free(data); } int process_vpp_link_msg(struct sock *sl){ uint8_t *buffer; int nbytes,rc; buffer = xzalloc(4096); netm_vpp_data_t *data = (netm_vpp_data_t *)netm_vpp.data; uint32_t events_flag; size_t fd_size; vpp_nl_msg *nl_msg; /* Check socket is ready to read */ fd_size = sizeof(uint32_t); rc = zmq_getsockopt(data->zmq_socket, ZMQ_EVENTS, &events_flag, &fd_size); if (rc == -1){ OOR_LOG(LDBG_1,"process_vpp_link_msg: Error while processing event type of ZMQ socket: %s\n",zmq_strerror (errno)); } if (!(events_flag & ZMQ_POLLIN)){ OOR_LOG(LDBG_3,"process_vpp_link_msg: ZMQ socket not ready to be read"); return (GOOD); } /* Process the packet */ nbytes = zmq_recv(data->zmq_socket, buffer, 4096, ZMQ_DONTWAIT); if (nbytes == -1){ OOR_LOG(LERR,"process_vpp_link_msg: Error while ZMQ receiving: %s\n",zmq_strerror (errno)); return (BAD); } nl_msg = (vpp_nl_msg *)buffer; switch(nl_msg->type){ case VPP_NEWLINK: vpp_process_link_change((vpp_nl_link_info *)(buffer+sizeof(vpp_nl_msg)), UP); break; case VPP_DELLINK: vpp_process_link_change((vpp_nl_link_info *)(buffer+sizeof(vpp_nl_msg)), DOWN); break; case VPP_NEWADDR: vpp_process_addr_change((vpp_nl_addr_info *)(buffer+sizeof(vpp_nl_msg)), ADD); break; case VPP_DELADDR: vpp_process_addr_change((vpp_nl_addr_info *)(buffer+sizeof(vpp_nl_msg)), RM); break; default: OOR_LOG(LERR,"process_vpp_link_msg: Unknown message type\n"); } return (GOOD); } void vpp_process_link_change(vpp_nl_link_info *link_info, uint8_t status) { OOR_LOG(LDBG_2, "vpp_process_link_change: Status of interface %d has changed to %s", link_info->ifi_index, status == UP ? "UP":"DOWN"); nm_process_link_change(link_info->ifi_index, link_info->ifi_index, status); } void vpp_process_addr_change(vpp_nl_addr_info *addr_info, uint8_t act) { lisp_addr_t new_addr = { .lafi = LM_AFI_IP }; switch (addr_info->ifa_family){ case AF_INET: lisp_addr_ip_init(&new_addr, CO(addr_info,sizeof(vpp_nl_addr_info)), AF_INET); break; case AF_INET6: lisp_addr_ip_init(&new_addr, CO(addr_info,sizeof(vpp_nl_addr_info)), AF_INET6); } nm_process_address_change(act,addr_info->ifa_index, &new_addr); } glist_t * vpp_get_ifaces_names() { glist_t *iface_names = glist_new_managed((glist_del_fct)free); vpp_api_main_t * vam = vpp_api_main_get(); vl_api_sw_interface_dump_t *mp; glist_entry_t *iface_it; vpp_api_iface_t *iface_info; glist_remove_all(vam->iface_list); /* Get list of ethernets */ MSG (SW_INTERFACE_DUMP, sw_interface_dump); mp->name_filter_valid = 1; strncpy ((char *) mp->name_filter, "Ether", sizeof (mp->name_filter) - 1); VPP_SEND; /* Use a control ping for synchronization */ { vl_api_control_ping_t *mp; MSG (CONTROL_PING, control_ping); VPP_SEND; } if (vpp_wait(vam) == ERR_NO_REPLY){ OOR_LOG(LERR,"vpp_get_ifaces_names: Couldn't obtain the list of interfaces"); glist_destroy(iface_names); return (NULL); } glist_for_each_entry(iface_it,vam->iface_list){ iface_info = (vpp_api_iface_t *)glist_entry_data(iface_it); glist_add(strdup(iface_info->iface_name),iface_names); } glist_remove_all(vam->iface_list); return (iface_names); } glist_t * vpp_get_iface_addr_list(char *iface_name, int afi) { glist_t *addr_list = glist_new_managed((glist_del_fct)lisp_addr_del); vl_api_ip_address_dump_t *mp; vpp_api_main_t * vam = vpp_api_main_get(); lisp_addr_t *addr; iface_t * iface; uint32_t iface_index; glist_entry_t *addr_it; glist_remove_all(vam->ip_addr_lst); iface = get_interface(iface_name); if (!iface){ iface_index = vpp_get_iface_index(iface_name); if (iface_index == 0){ OOR_LOG(LDBG_1,"vpp_get_iface_addr_list: Unknown interface %s",iface_name); return (addr_list); } }else{ iface_index = iface->iface_index; } MSG (IP_ADDRESS_DUMP, ip_address_dump); mp->sw_if_index = ntohl (iface_index); if (afi == AF_INET6){ mp->is_ipv6 = 1; } vam->requested_ip_afi = afi; VPP_SEND; /* Use a control ping for synchronization */ { vl_api_control_ping_t *mp; MSG (CONTROL_PING, control_ping); VPP_SEND; } if (vpp_wait(vam) == ERR_NO_REPLY){ return (addr_list); } glist_for_each_entry(addr_it,vam->ip_addr_lst){ addr = (lisp_addr_t *)glist_entry_data(addr_it); lisp_addr_set_lafi(addr,LM_AFI_IP); if (ip_addr_is_link_local(lisp_addr_ip(addr)) == TRUE) { OOR_LOG(LDBG_2, "vpp_get_iface_addr_list: interface address from " "%s discarded (%s)", iface_name, lisp_addr_to_char(addr)); }else { glist_add (lisp_addr_clone(addr), addr_list); } } if (glist_size(addr_list) == 0){ OOR_LOG(LDBG_2, "vpp_get_iface_addr_list: No %s RLOC configured for interface " "%s\n", (afi == AF_INET) ? "IPv4" : "IPv6", iface_name); } glist_remove_all(vam->ip_addr_lst); return(addr_list); } /* This function only works if the addr is directly connected to OOR */ lisp_addr_t * vpp_get_src_addr_to(lisp_addr_t *addr) { lisp_addr_t *src_addr = NULL, *pref, *iface_addr; glist_t *addr_list, *net_pref_list; glist_entry_t *add_list_it, *net_pref_list_it; int afi = lisp_addr_ip_afi(addr); uint8_t pref_found = FALSE; shash_t *addr_to_iface; net_pref_list = vpp_ip_fib_prefixs(afi); glist_for_each_entry(net_pref_list_it, net_pref_list){ pref = (lisp_addr_t *)glist_entry_data(net_pref_list_it); if (pref_is_addr_part_of_prefix(addr,pref)){ pref_found = TRUE; break; } } if (!pref_found){ OOR_LOG(LDBG_1,"vpp_get_src_addr_to: netm_get_src_addr_to should only be used with" "directly connected addresses (%s)",lisp_addr_to_char(addr)); goto end; } addr_to_iface = vpp_build_addr_to_if_name_hasht(); addr_list = shash_keys(addr_to_iface); iface_addr = lisp_addr_new(); glist_for_each_entry(add_list_it,addr_list){ lisp_addr_ip_from_char((char *)glist_entry_data(add_list_it), iface_addr); if (pref_is_addr_part_of_prefix(iface_addr,pref) == TRUE){ src_addr = lisp_addr_clone(iface_addr); goto end; } } OOR_LOG(LDBG_1,"netm_get_src_addr_to: No src address slected to reach %s. It should never happen", lisp_addr_to_char(addr)); end: glist_destroy(net_pref_list); glist_destroy(addr_list); shash_destroy(addr_to_iface); lisp_addr_del(iface_addr); return (src_addr); } lisp_addr_t * vpp_get_iface_gw(char *iface_name, int afi) { /* We only support one default gateway */ lisp_addr_t *gw; gw = vpp_oor_pkt_miss_get_default_route(afi); return (lisp_addr_clone(gw)); } uint8_t vpp_get_iface_status(char *iface_name) { vpp_api_main_t * vam = vpp_api_main_get(); vl_api_sw_interface_dump_t *mp; vpp_api_iface_t *iface_info; glist_remove_all(vam->iface_list); /* Get list of ethernets */ MSG (SW_INTERFACE_DUMP, sw_interface_dump); mp->name_filter_valid = 1; strncpy ((char *) mp->name_filter, iface_name, sizeof (mp->name_filter) - 1); VPP_SEND; /* Use a control ping for synchronization */ { vl_api_control_ping_t *mp; MSG (CONTROL_PING, control_ping); VPP_SEND; } vpp_wait(vam); if (glist_size(vam->iface_list) == 0){ OOR_LOG(LDBG_1,"vpp_get_iface_index: Unknown interface %s",iface_name); return (ERR_NO_EXIST); } iface_info = (vpp_api_iface_t *)glist_first_data(vam->iface_list); return (iface_info->status); } int vpp_get_iface_index(char *iface_name) { vpp_api_main_t * vam = vpp_api_main_get(); vl_api_sw_interface_dump_t *mp; vpp_api_iface_t *iface_info; glist_remove_all(vam->iface_list); /* Get list of ethernets */ MSG (SW_INTERFACE_DUMP, sw_interface_dump); mp->name_filter_valid = 1; strncpy ((char *) mp->name_filter, iface_name, sizeof (mp->name_filter) - 1); VPP_SEND; /* Use a control ping for synchronization */ { vl_api_control_ping_t *mp; MSG (CONTROL_PING, control_ping); VPP_SEND; } vpp_wait(vam); if (glist_size(vam->iface_list) == 0){ OOR_LOG(LDBG_1,"vpp_get_iface_index: Unknown interface %s",iface_name); return (0); } iface_info = (vpp_api_iface_t *)glist_first_data(vam->iface_list); return (iface_info->iface_index); } void vpp_get_iface_mac_addr(char *iface_name, uint8_t *mac) { vpp_api_main_t * vam = vpp_api_main_get(); vl_api_sw_interface_dump_t *mp; vpp_api_iface_t *iface_info; glist_remove_all(vam->iface_list); /* Get list of ethernets */ MSG (SW_INTERFACE_DUMP, sw_interface_dump); mp->name_filter_valid = 1; strncpy ((char *) mp->name_filter, iface_name, sizeof (mp->name_filter) - 1); VPP_SEND; /* Use a control ping for synchronization */ { vl_api_control_ping_t *mp; MSG (CONTROL_PING, control_ping); VPP_SEND; } vpp_wait(vam); if (glist_size(vam->iface_list) == 0){ OOR_LOG(LDBG_1,"vpp_get_iface_index: Unknown interface %s",iface_name); return; } iface_info = (vpp_api_iface_t *)glist_first_data(vam->iface_list); memcpy(mac, iface_info->l2_address, 6*sizeof(uint8_t)); return; } char * vpp_get_iface_name_associated_with_prefix(lisp_addr_t * pref) { shash_t *addr_to_iface; glist_t *iface_addr_lst; glist_entry_t *addr_it; lisp_addr_t *iface_addr = lisp_addr_new(); lisp_addr_t *ip_pref_addr = lisp_addr_get_ip_pref_addr(pref); char * iface_name = NULL; //XXX This process is not optim. VPP API not offer to obtain interface from IP addr_to_iface = vpp_build_addr_to_if_name_hasht(); iface_addr_lst = shash_keys(addr_to_iface); glist_for_each_entry(addr_it,iface_addr_lst){ lisp_addr_ip_from_char((char *)glist_entry_data(addr_it), iface_addr); if (pref_is_addr_part_of_prefix(iface_addr,ip_pref_addr) == TRUE){ iface_name = strdup(shash_lookup(addr_to_iface, lisp_addr_to_char(iface_addr))); goto end; } } OOR_LOG(LERR,"VPP: Not found interface associated with prefix %s",lisp_addr_to_char(pref)); end: glist_destroy(iface_addr_lst); shash_destroy(addr_to_iface); lisp_addr_del(iface_addr); return (iface_name); } /* * Request to the kernel the routing table with the selected afi */ int vpp_reload_routes(uint32_t table, int afi) { return (GOOD); } shash_t * vpp_build_addr_to_if_name_hasht() { shash_t *ht; glist_t *iface_name_list, *addr_list; glist_entry_t *iface_name_it, *addr_it; char *iface_name; lisp_addr_t *addr; OOR_LOG(LDBG_2, "Building address to interface hash table"); iface_name_list = vpp_get_ifaces_names(); if (!iface_name_list){ return (NULL); } ht = shash_new_managed((free_value_fn_t)free); glist_for_each_entry(iface_name_it,iface_name_list){ iface_name = (char *)glist_entry_data(iface_name_it); addr_list = vpp_get_iface_addr_list(iface_name, AF_INET); glist_for_each_entry(addr_it, addr_list){ addr = (lisp_addr_t *)glist_entry_data(addr_it); shash_insert(ht, strdup(lisp_addr_to_char(addr)), strdup(iface_name)); OOR_LOG(LDBG_2, "Found interface %s with address %s", iface_name, lisp_addr_to_char(addr)); } glist_destroy (addr_list); addr_list = vpp_get_iface_addr_list(iface_name, AF_INET6); glist_for_each_entry(addr_it, addr_list){ addr = (lisp_addr_t *)glist_entry_data(addr_it); shash_insert(ht, strdup(lisp_addr_to_char(addr)), strdup(iface_name)); OOR_LOG(LDBG_2, "Found interface %s with address %s", iface_name, lisp_addr_to_char(addr)); } glist_destroy (addr_list); } return (ht); } inline static netm_vpp_data_t * netm_vpp_data_new() { return (xzalloc(sizeof(netm_vpp_data_t))); } inline static void netm_vpp_data_free(netm_vpp_data_t * vpp_data) { free(vpp_data); } oor-1.2.0/oor/net_mgr/vpp/netm_vpp.h000066400000000000000000000025221313612200500173430ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef NETM_VPP_H_ #define NETM_VPP_H_ #include #define VPP_IPC_FILE "ipc:///tmp/oor-vpp-ipc" typedef struct netm_vpp_data_ { void *zmq_context; void *zmq_socket; } netm_vpp_data_t; typedef enum vpp_netlink_msg_type_ { VPP_NEWADDR, VPP_DELADDR, VPP_NEWLINK, VPP_DELLINK, VPP_NEWROUTE, VPP_DELROUTE } vpp_netlink_msg_type_e; typedef struct vpp_nl_msg_{ vpp_netlink_msg_type_e type; uint32_t len; }vpp_nl_msg; typedef struct{ uint32_t ifi_index; }vpp_nl_link_info; typedef struct{ uint8_t ifa_family; uint8_t ifa_prefixlen; uint32_t ifa_index; }vpp_nl_addr_info; #endif /* NETM_VPP_H_ */ oor-1.2.0/oor/oor.c000066400000000000000000000355711313612200500140570ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include #include #include #include #include #include #include #include "oor.h" #if !defined(ANDROID) && !defined(OPENWRT) #include "config/oor_api_internals.h" #endif #ifdef OPENWRT #include "config/oor_config_uci.h" #else #include "config/oor_config_confuse.h" #endif #include "cmdline.h" #include "iface_list.h" #include "control/oor_control.h" #include "control/lisp_xtr.h" #include "control/lisp_ms.h" #include "data-plane/data-plane.h" #include "net_mgr/net_mgr.h" #include "lib/oor_log.h" #include "lib/nonces_table.h" #include "lib/pointers_table.h" #include "lib/sockets.h" #include "lib/timers.h" #include "lib/routing_tables_lib.h" #ifdef VPP #include "lib/vpp_api/vpp_api.h" #endif #include "liblisp/liblisp.h" #include "lib/shash.h" #include "lib/generic_list.h" #ifdef VPNAPI #include "oor_jni.h" #endif /* system calls - look to libc for function to system call mapping */ extern int capset(cap_user_header_t header, cap_user_data_t data); extern int capget(cap_user_header_t header, const cap_user_data_t data); #ifdef ANDROID #define CAP_TO_MASK(x) (1 << ((x) & 31)) #endif /* config paramaters */ char *config_file = NULL; int debug_level = -1; int default_rloc_afi = AF_UNSPEC; int daemonize = FALSE; uint32_t iseed = 0; /* initial random number generator */ /* various globals */ pid_t pid = 0; /* child pid */ pid_t sid = 0; /* sockets (fds) */ int ipv4_data_input_fd = -1; int ipv6_data_input_fd = -1; int netlink_fd = -1; sockmstr_t *smaster = NULL; oor_ctrl_dev_t *ctrl_dev; oor_ctrl_t *lctrl; #ifdef VPNAPI int oor_running; #endif #if !defined(ANDROID) && !defined(OPENWRT) /* OOR's API connection structure */ oor_api_connection_t oor_api_connection; #endif htable_nonces_t *nonces_ht; htable_ptrs_t *ptrs_to_timers_ht; /**************************** FUNCTION DECLARATION ***************************/ /* Check if oor is already running: /var/run/oor.pid */ int pid_file_check_not_exist(); /* Creates the PID file of the process */ int pid_file_create(); /* Remove the PID file of the process */ void pid_file_remove(); /*****************************************************************************/ /* Check if oor is already running: /var/run/oor.pid */ int pid_file_check_not_exist() { FILE *pid_file; pid_file = fopen(PID_FILE, "r"); if (pid_file != NULL) { OOR_LOG(LCRIT, "Check no other instance of oor is running. If no instance is running, remove %s",PID_FILE); fclose(pid_file); return (BAD); } return (GOOD); } /* Creates the PID file of the process */ int pid_file_create() { FILE *pid_file; int pid = getpid(); pid_file = fopen(PID_FILE , "w"); if (pid_file == NULL){ OOR_LOG(LCRIT, "pid_file_create: Error creating PID file: %s",strerror(errno)); return (BAD); } fprintf(pid_file, "%d\n",pid); fclose(pid_file); OOR_LOG(LDBG_1, "PID file created: %s -> %d",PID_FILE, pid); return (GOOD); } /* Remove the PID file of the process */ void pid_file_remove() { FILE *pid_file; pid_file = fopen(PID_FILE, "r"); if (pid_file == NULL){ return; } fclose(pid_file); if (remove(PID_FILE) != 0){ OOR_LOG(LWRN,"pid_file_remove: PID file couldn't be removed: %s", PID_FILE); }else{ OOR_LOG(LDBG_1,"PID file removed"); } } /* * Check for superuser privileges */ #ifndef ANDROID int check_capabilities() { struct __user_cap_header_struct cap_header; struct __user_cap_data_struct cap_data; cap_header.pid = getpid(); cap_header.version = _LINUX_CAPABILITY_VERSION; /* Check if oor is already running: /var/run/oor.pid */ if (capget(&cap_header, &cap_data) < 0) { OOR_LOG(LCRIT, "Could not retrieve capabilities"); return BAD; } OOR_LOG(LDBG_1, "Rights: Effective [%u] Permitted [%u]", cap_data.effective, cap_data.permitted); /* check for capabilities */ if( (cap_data.effective & CAP_TO_MASK(CAP_NET_ADMIN)) && (cap_data.effective & CAP_TO_MASK(CAP_NET_RAW)) ) { } else { OOR_LOG(LCRIT, "Insufficient rights, you need CAP_NET_ADMIN and CAP_NET_RAW. See README"); return BAD; } return GOOD; } #else int check_capabilities() { if (geteuid() != 0) { OOR_LOG(LCRIT,"Running Open Overlay Router requires superuser privileges! Exiting...\n"); return (BAD); } return (GOOD); } #endif void signal_handler(int sig) { switch (sig) { case SIGHUP: /* TODO: SIGHUP should trigger reloading the configuration file */ OOR_LOG(LDBG_1, "Received SIGHUP signal."); break; case SIGTERM: /* SIGTERM is the default signal sent by 'kill'. Exit cleanly */ OOR_LOG(LDBG_1, "Received SIGTERM signal. Cleaning up..."); exit_cleanup(); break; case SIGINT: /* SIGINT is sent by pressing Ctrl-C. Exit cleanly */ OOR_LOG(LDBG_1, "Terminal interrupt. Cleaning up..."); exit_cleanup(); break; default: OOR_LOG(LDBG_1,"Unhandled signal (%d)", sig); exit(EXIT_FAILURE); } } /* * exit_cleanup() * * Close opened sockets and file descriptors */ void exit_cleanup(void) { OOR_LOG(LDBG_2,"Exit Cleanup"); #ifndef ANDROID pid_file_remove(); #endif // Order is important ctrl_destroy(lctrl); if (data_plane){ data_plane->datap_uninit(); } if (net_mgr){ net_mgr->netm_uninit(); } ifaces_destroy(); sockmstr_destroy(smaster); oor_timers_destroy(); htable_ptrs_destroy(ptrs_to_timers_ht); htable_nonces_destroy(nonces_ht); close_log_file(); #ifndef VPNAPI OOR_LOG(LINF,"Exiting ..."); exit(EXIT_SUCCESS); #else jni_uninit(); #endif #ifdef VPP vpp_uninit_api(); #endif } /* * handle_oor_command_line -- */ static void handle_oor_command_line(int argc, char **argv) { struct gengetopt_args_info args_info; if (cmdline_parser(argc, argv, &args_info) != 0) { exit_cleanup(); } if (args_info.daemonize_given) { daemonize = TRUE; } if (args_info.config_file_given) { config_file = strdup(args_info.config_file_arg); } if (args_info.debug_given) { debug_level = args_info.debug_arg; } if (args_info.afi_given) { switch (args_info.afi_arg) { case 0: /* afi given = 4 */ default_rloc_afi = AF_INET; break; case 1: /* afi given = 6 */ default_rloc_afi = AF_INET6; break; default: OOR_LOG(LINF, "AFI must be IPv4 (-a 4) or IPv6 (-a 6)\n"); break; } } else { default_rloc_afi = AF_UNSPEC; } #ifdef VPP default_rloc_afi = AF_INET; OOR_LOG(LINF, "VPP: Disabling IPv6 RLOCs\n"); #endif cmdline_parser_free(&args_info); } static void demonize_start() { if (daemonize) { OOR_LOG(LDBG_1, "Starting the daemonizing process"); if ((pid = fork()) < 0) { exit_cleanup(); } umask(0); if (pid > 0){ exit(EXIT_SUCCESS); } if ((sid = setsid()) < 0){ exit_cleanup(); } if ((chdir("/")) < 0){ exit_cleanup(); } close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); } } static void setup_signal_handlers() { signal(SIGHUP, signal_handler); signal(SIGTERM, signal_handler); signal(SIGINT, signal_handler); signal(SIGQUIT, signal_handler); } static int parse_config_file() { int err; err = handle_config_file(); return (err); } static int initial_setup() { int selected = 0; #ifdef OPENWRT OOR_LOG(LINF,"Open Overlay Router %s compiled for openWRT\n", OOR_VERSION); selected ++; #endif #ifdef VPP OOR_LOG(LINF,"Open Overlay Router %s compiled for linux with VPP data plane\n", OOR_VERSION); selected ++; #endif #ifdef ANDROID #ifdef VPNAPI OOR_LOG(LINF,"Open Overlay Router %s compiled for not rooted Android\n", OOR_VERSION); selected ++; #else OOR_LOG(LINF,"Open Overlay Router %s compiled for rooted Android\n", OOR_VERSION); selected ++; #endif #endif if (selected > 1){ OOR_LOG(LERR,"Wrong platform selection"); return (BAD); }else if (selected == 0){ OOR_LOG(LINF,"Open Overlay Router %s compiled for linux\n", OOR_VERSION); } #if UINTPTR_MAX == 0xffffffff OOR_LOG(LDBG_1,"x32 system"); #elif UINTPTR_MAX == 0xffffffffffffffff OOR_LOG(LDBG_1,"x64 system"); #else OOR_LOG(LERR,"Unknow system. Please contact the Open Overlay Router team providing your hardware"); #endif #ifndef VPNAPI if (check_capabilities() != GOOD){ return (BAD); } if(pid_file_check_not_exist() == BAD){ return (BAD); } pid_file_create(); #endif /* Initialize the random number generator */ iseed = (unsigned int) time(NULL); srandom(iseed); setup_signal_handlers(); /* Initialize hash table that control timers */ nonces_ht = htable_nonces_new(); ptrs_to_timers_ht = htable_ptrs_new(); #ifdef VPP if (vpp_is_enabled() == FALSE || vpp_init_api() != GOOD){ return (BAD); } #endif return(GOOD); } #ifndef VPNAPI int main(int argc, char **argv) { oor_dev_type_e dev_type; lisp_xtr_t *tunnel_router; if (initial_setup() != GOOD){ exit(EXIT_SUCCESS); } handle_oor_command_line(argc, argv); /* see if we need to daemonize, and if so, do it */ demonize_start(); /* Detect the data plane type */ data_plane_select(); net_mgr_select(); /* create socket master, timer wheel, initialize interfaces */ smaster = sockmstr_create(); oor_timers_init(); if (ifaces_init() != GOOD){ exit_cleanup(); } /* create control. Only one instance for now */ if ((lctrl = ctrl_create())==NULL){ exit_cleanup(); } /* parse config and create ctrl_dev */ if (parse_config_file() != GOOD){ exit_cleanup(); } dev_type = ctrl_dev_mode(ctrl_dev); #ifdef VPP if (dev_type != xTR_MODE){ OOR_LOG(LERR, "VPP is only supported in xTR mode"); exit_cleanup(); } #endif if (dev_type == xTR_MODE || dev_type == RTR_MODE || dev_type == MN_MODE) { OOR_LOG(LDBG_2, "Configuring data plane"); tunnel_router = CONTAINER_OF(ctrl_dev, lisp_xtr_t, super); if (data_plane->datap_init(dev_type,tr_get_encap_type(tunnel_router))!=GOOD){ data_plane = NULL; exit_cleanup(); } OOR_LOG(LDBG_1, "Data plane initialized"); } /* The control should be initialized after data plane */ if (ctrl_init(lctrl) != GOOD){ exit_cleanup(); } if (net_mgr->netm_init() != GOOD){ exit_cleanup(); } /* run lisp control device xtr/ms */ ctrl_dev_run(ctrl_dev); OOR_LOG(LINF,"\n\n Open Overlay Router (%s): started... \n\n",OOR_VERSION); #if !defined(ANDROID) && !defined(OPENWRT) /* Initialize API for external access */ oor_api_init_server(&oor_api_connection); for (;;) { sockmstr_wait_on_all_read(smaster); sockmstr_process_all(smaster); oor_api_loop(&oor_api_connection); } #else for (;;) { sockmstr_wait_on_all_read(smaster); sockmstr_process_all(smaster); } #endif /* event_loop returned: bad! */ OOR_LOG(LINF, "Exiting..."); exit_cleanup(); return(0); } #else JNIEXPORT jint JNICALL Java_org_openoverlayrouter_noroot_OOR_1JNI_oor_1start (JNIEnv *env, jobject thisObj, jint vpn_tun_fd, jstring storage_path) { oor_dev_type_e dev_type; jintArray fd_list; uint32_t iseed = 0; /* initial random number generator */ pid_t pid = 0; /* child pid */ pid_t sid = 0; char log_file[1024]; const char *path = NULL; lisp_xtr_t *tunnel_router; memset (log_file,0,sizeof(char)*1024); initial_setup(); jni_init(env,thisObj); /* create socket master, timer wheel, initialize interfaces */ smaster = sockmstr_create(); oor_timers_init(); /* create control. Only one instance for now */ lctrl = ctrl_create(); /* Detect the data plane type */ data_plane_select(); net_mgr_select(); if (ifaces_init()!=GOOD){ exit_cleanup(); close(vpn_tun_fd); return (BAD); } /** parse config and create ctrl_dev **/ /* obtain the configuration file */ path = (*env)->GetStringUTFChars(env, storage_path, 0); config_file = calloc(1024, sizeof(char)); strcat(config_file,path); strcat(config_file,"oor.conf"); strcat(log_file,path); strcat(log_file,"oor.log"); (*env)->ReleaseStringUTFChars(env, storage_path, path); open_log_file(log_file); if (parse_config_file()!=GOOD){ exit_cleanup(); close(vpn_tun_fd); return (BAD); } dev_type = ctrl_dev_mode(ctrl_dev); if (dev_type == xTR_MODE || dev_type == RTR_MODE || dev_type == MN_MODE) { OOR_LOG(LDBG_2, "Configuring data plane"); tunnel_router = CONTAINER_OF(ctrl_dev, lisp_xtr_t, super); if (data_plane->datap_init(dev_type, tr_get_encap_type(tunnel_router), vpn_tun_fd) != GOOD){ data_plane = NULL; return (BAD); } OOR_LOG(LDBG_1, "Data plane initialized"); } ctrl_init(lctrl); if (net_mgr->netm_init() != GOOD){ exit_cleanup(); } return (GOOD); } JNIEXPORT void JNICALL Java_org_openoverlayrouter_noroot_OOR_1JNI_oor_1loop(JNIEnv * env, jclass cl) { oor_running = TRUE; ctrl_dev_run(ctrl_dev); /* EVENT LOOP */ while (oor_running) { sockmstr_wait_on_all_read(smaster); sockmstr_process_all(smaster); } /* event_loop returned: bad! */ exit_cleanup(); } JNIEXPORT void JNICALL Java_org_openoverlayrouter_noroot_OOR_1JNI_oor_1exit(JNIEnv * env, jclass cl) { oor_running = false; } #endif /* * Editor modelines * * vi: set shiftwidth=4 tabstop=4 expandtab: * :indentSize=4:tabSize=4:noTabs=true: */ oor-1.2.0/oor/oor.conf.example000066400000000000000000000242571313612200500162130ustar00rootroot00000000000000################################################ # # General configuration # # debug: Debug levels [0..3] # map-request-retries: Additional Map-Requests to send per map cache miss # log-file: Specifies log file used in daemon mode. If it is not specified, # messages are written in syslog file debug = 0 map-request-retries = 2 log-file = /var/log/oor.log # Define the type of LISP device LISPmob will operate as # # operating-mode can be any of: # xTR, RTR, MN, MS # operating-mode = xTR # For the rest of this file you can delete the sections that does not apply to # the LISP device selected in operating-mode ################################################ # # MS configuration # # Control messages are received and generated through this interface # Only one interface is supported control-iface = # Define an allowed lisp-site to be registered into the Map Server. Several # lisp-site can be defined. # # eid-prefix: Accepted EID prefix (IPvX/mask) # key-type: Only 1 supported (HMAC-SHA-1-96) # key: Password to authenticate the received Map-Registers # iid: Instance ID associated with the lisp site [0-16777215] # accept-more-specifics [true/false]: Accept more specific prefixes # with same authentication information lisp-site { eid-prefix = key-type = 1 key = iid = 0 accept-more-specifics = } # Define a static registered mapping. New Map-Registers overwrites # the information of this mapping. You can define several eid-prefix. # eid-prefix: EID prefix (IPvX/mask) of the mapping # iid: Instance ID associated with the lisp site [0-16777215] # address: It could be one of the following cases # - IPv4 or IPv6 address of the RLOC # - ELP name # priority [0-255]: Priority for the RLOC of the interface. Locators # with lower values are more preferable. This is used for both incoming # policy announcements and outgoing traffic policy management # weight [0-255]: When priorities are the same for multiple RLOCs, the weight # indicates how to balance unicast traffic between them ms-static-registered-site { eid-prefix = iid = 0 rloc-address { address = priority = weight = } } ############################################### # # Tunnel Router general configuration # Common for xTR, RTR & MN # # encapsulation: Encapsulation that will use OOR in the data plane. Could be # LISP or VXLAN-GPE. LISP is selected by default encapsulation = # RLOC probing configuration # rloc-probe-interval: interval at which periodic RLOC probes are sent # (seconds). A value of 0 disables RLOC probing # rloc-probe-retries: RLOC probe retries before setting the locator with # status down. [0..5] # rloc-probe-retries-interval: interval at which RLOC probes retries are # sent (seconds) [1..rloc-probe-interval] rloc-probing { rloc-probe-interval = 30 rloc-probe-retries = 2 rloc-probe-retries-interval = 5 } # Encapsulated Map-Requests are sent to this Map-Resolver # You can define several Map-Resolvers, seprated by comma. Encapsulated # Map-Request messages will be sent to only one. # address: IPv4 or IPv6 address of the map-resolver map-resolver = { } # Static Map Entry of the Map Cache. Several eid-prefix can be defined. # eid-prefix: EID prefix (ip-prefix/mask) of the mapping # iid: Instance ID associated to the EID. When using VXLAN-GPE, iid configures # the VNI of the mapping. [0-16777215] # address: It could be one of the following cases # - IPv4 or IPv6 address of the RLOC # - ELP name # priority [0-255]: Priority for the RLOC. Locators with # lower values are more preferable. This is used for both incoming # policy announcements and outgoing traffic policy management. # weight [0-255]: When priorities are the same for multiple RLOCs, the weight # indicates how to balance unicast traffic between them. static-map-cache { eid-prefix = iid = 0 rloc-address { address = priority = weight = } } ############################################### # # RTR configuration # # List of interfaces to be used as outgoing interfaces for the packets sent # by the RTR. Several rtr-ifaces can be defined. # iface: interface containing the RLOCs to be used for outgoing traffic # ip_version: 4 to use the IPv4 address of the interface and 6 to use the IPv6 # address of the interface # priority [0-255]: Priority for the RLOC of the interface. Locators # with lower values are more preferable. This is used for outgoing # traffic policy management. # weight [0-255]: When priorities are the same for multiple RLOCs, the weight # indicates how to balance unicast traffic between them. rtr-ifaces { rtr-iface { iface = ip_version = <4/6> priority = weight = } } ############################################### # # xTR & MN configuration # # NAT Traversl configuration. # nat_traversal_support: check if the node is behind NAT. nat_traversal_support = off # Map-Registers are sent to this Map-Server # You can define several Map-Servers. Map-Register messages will be sent to all # of them. # address: IPv4 or IPv6 address of the map-server # key-type: Only 1 supported (HMAC-SHA-1-96) # key: password to authenticate with the map-server # proxy-reply [on/off]: Configure map-server to Map-Reply on behalf of the xTR map-server { address = key-type = 1 key = proxy-reply = } # Packets addressed to non-LISP sites will be encapsulated to this Proxy-ETR # You can define several Proxy-ETR for IPv4 EIDs and for IPv6 EIDs. Traffic # will be balanced according to the priority and weight. # address: IPv4 or IPv6 address of the Proxy-ETR # priority [0-255]: Proxy-ETR with lower values are more preferable. # weight [0-255]: When priorities are the same for multiple Proxy-ETRs, # the weight indicates how to balance unicast traffic between them. # Proxy for IPv4 EIDs proxy-etr-ipv4 { address = priority = weight = } # Proxy for IPv6 EIDs proxy-etr-ipv6 { address = priority = weight = } # IPv4 / IPv6 EID of the node. # eid-prefix: EID prefix (ip-prefix/mask) of the mapping # iid: Instance ID associated to the EID. When using VXLAN-GPE, iid configures # the VNI of the mapping. [0-16777215] # Two types of RLOCs can be defined: # rloc-address: Specifies directly the RLOC of the interface # address: It could be one of the following cases # - IPv4 or IPv6 address of the RLOC. Address should exist and # be assigned to an UP interface during startup process otherwise # it is discarded. # - ELP name # rloc-iface: Specifies the interface associated with the RLOC # interface: interface containing the RLOCs associated to this mapping # ip_version: 4 to use the IPv4 address of the interface and 6 to use the IPv6 # address of the interface # Both types of RLOCs use priority and weight # priority [0-255]: Priority for the RLOC of the interface. Locators # with lower values are more preferable. This is used for both incoming # policy announcements and outgoing traffic policy management. # weight [0-255]: When priorities are the same for multiple RLOCs, the weight # indicates how to balance unicast traffic between them. database-mapping { eid-prefix = iid = 0 rloc-address { address = priority = weight = } rloc-iface{ interface = ip_version = <4/6> priority = weight = } } # Current LISP beta-network (lisp4.net/lisp6.net) PITR addresses # Uncomment the IPv4 or IPv6 list based on your current locators and # comment the previous 'proxy-itrs' section #proxy-itrs = { # LISP beta-network IPv4 PITRs # 69.31.31.98, # eqx-ash-pxtr # 129.250.1.63, # ntt-amer-pxtr # 217.8.98.33, # intouch-pxtr-1 # 193.162.145.46, # tdc-pxtr # 158.38.1.92, # uninett-pxtr # 203.181.249.172, # apan-pxtr # 202.51.247.10 # sg-nus-pxtr # LISP beta-network IPv6 PITRs # 2001:590::451f:1f62, # eqx-ash-pxtr # 2001:418:0:1000::63, # ntt-amer-pxtr # 2001:200:e000:17::17, # intouch-pxtr-1 # 2001:6C8:130:600::1, # tdc-pxtr # 2001:700:0:52E::4, # uninett-pxtr # 2001:200:e000:17::172 # apan-pxtr #} ############################################### # # Miscellaneous configuration # # Structure to define a path involving multiple hops # elp-name: Name to define the ELP used as a reference in the rest of the # configuration # elp-node: Defines each of the hops of the ELP. Several ones can be defined. # In most cases, the last elp-node would be the local RLOC of an xTR # address: IPv4 or IPv6 address of the RLOC. The address of the last elp-node # should exist and be assigned to an UP interface during startup process # otherwise it is discarded. # strict [true/false]: Not yet implemented. Use false # probe [true/false]: Not yet implemented. Use false # lookup [true/false]: Not yet implemented. Use false explicit-locator-path { elp-name = elp-node { address = strict = probe = lookup = } elp-node { address = strict = probe = lookup = } } oor-1.2.0/oor/oor.ggo000066400000000000000000000021461313612200500144010ustar00rootroot00000000000000# # # Copyright (C) 2011, 2015 Cisco Systems, Inc. # Copyright (C) 2015 CBA research group, Technical University of Catalonia. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # package "oor" version "1.2.0" defmode "oorconfig" modeoption "debug" d "Debugging output [0..3]" int values="0","1","2","3" enum mode="oorconfig" optional modeoption "afi" a "Default RLOCs afi [4,6]" int values="4","6" enum mode="oorconfig" optional modeoption "daemonize" D "Daemonize oor" mode="oorconfig" optional modeoption "config-file" f "Alternate config file" string typestr="config-file" mode="oorconfig" optional oor-1.2.0/oor/oor.h000066400000000000000000000023521313612200500140530ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef OOR_H_ #define OOR_H_ #include "defs.h" /* * Netlink mcast groups oor is interested in * for interface management */ #define OOR_IFACE_NLMGRPS (RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV4_ROUTE) /* #define OOR_IFACE_NLMGRPS (RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR \ | RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_ROUTE ) */ void exit_cleanup(void); #endif /*OOR_H_*/ /* * Editor modelines * * vi: set shiftwidth=4 tabstop=4 expandtab: * :indentSize=4:tabSize=4:noTabs=true: */ oor-1.2.0/oor/oor_external.h000066400000000000000000000023741313612200500157610ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef OOR_EXTERNAL_H_ #define OOR_EXTERNAL_H_ #include "defs.h" extern char *config_file; extern int daemonize; extern int default_rloc_afi; extern sockmstr_t *smaster; extern int netlink_fd; extern oor_ctrl_dev_t *ctrl_dev; extern oor_ctrl_t *lctrl; extern data_plane_struct_t *data_plane; extern net_mgr_class_t *net_mgr; extern void exit_cleanup(); extern htable_nonces_t *nonces_ht; extern htable_ptrs_t *ptrs_to_timers_ht; #endif /*OOR_EXTERNAL_H_*/ /* * Editor modelines * * vi: set shiftwidth=4 tabstop=4 expandtab: * :indentSize=4:tabSize=4:noTabs=true: */ oor-1.2.0/oor/oor_jni.c000066400000000000000000000036131313612200500147070ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include #include "defs.h" #include "oor_jni.h" #include "lib/oor_log.h" static JNIEnv *jni_env; static jobject jni_object; static jclass class_android_jni; void jni_init(JNIEnv *env, jobject object) { jni_env = env; jni_object = (*jni_env)->NewGlobalRef(jni_env, object); class_android_jni = (*jni_env)->FindClass(jni_env,"org/openoverlayrouter/noroot/OOR_JNI"); if (class_android_jni == NULL){ OOR_LOG(LINF,"JNI Error: Class not found: org.openoverlayrouter.noroot.OOR_JNI"); return; } class_android_jni = (*jni_env)->NewGlobalRef(jni_env, class_android_jni); } void jni_uninit() { (*jni_env)->DeleteGlobalRef(jni_env, jni_object); (*jni_env)->DeleteGlobalRef(jni_env, class_android_jni); jni_object = NULL; class_android_jni = NULL; } void oor_jni_protect_socket(int socket) { jmethodID meth_protect = NULL; meth_protect = (*jni_env)->GetMethodID(jni_env,class_android_jni, "jni_protect_socket", "(I)V"); if (meth_protect == NULL){ OOR_LOG(LINF,"JNI Error: Method not found: org.openoverlayrouter.noroot.OOR_JNI:jni_protect_socket"); return; } (*jni_env)->CallVoidMethod(jni_env,jni_object, meth_protect, socket); } oor-1.2.0/oor/oor_jni.h000066400000000000000000000030631313612200500147130ustar00rootroot00000000000000/* * * Copyright (C) 2011, 2015 Cisco Systems, Inc. * Copyright (C) 2015 CBA research group, Technical University of Catalonia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include #ifndef OOR_JNI_H_ #define OOR_JNI_H_ #ifdef __cplusplus extern "C" { #endif /* * Class: org_openoverlayrouter_noroot_OOR_JNI * Method: oor_start * Signature: (I)[I */ JNIEXPORT jint JNICALL Java_org_openoverlayrouter_noroot_OOR_1JNI_oor_1start (JNIEnv * env, jobject thisObj, jint vpn_tun_fd, jstring storage_path); /* * Class: org_openoverlayrouter_noroot_OOR_JNI * Method: oor_loop * Signature: ()V */ JNIEXPORT void JNICALL Java_org_openoverlayrouter_noroot_OOR_1JNI_oor_1loop (JNIEnv * env, jclass cl); /* * Class: org_openoverlayrouter_noroot_OOR_JNI * Method: oor_exit * Signature: ()V */ JNIEXPORT void JNICALL Java_org_openoverlayrouter_noroot_OOR_1JNI_oor_1exit (JNIEnv * env, jclass cl); void jni_init(JNIEnv *env, jobject object); void jni_uninit(); void oor_jni_protect_socket(int socket); #ifdef __cplusplus } #endif #endif /* OOR_JNI_H_ */ oor-1.2.0/tests/000077500000000000000000000000001313612200500134445ustar00rootroot00000000000000oor-1.2.0/tests/.gitignore000066400000000000000000000001621313612200500154330ustar00rootroot00000000000000# Vi(m) swap files .*.swp # Compiled executables udp_echo_server udp_echo_client tcp_echo_server tcp_echo_client oor-1.2.0/tests/Makefile000066400000000000000000000004361313612200500151070ustar00rootroot00000000000000all: tests tests: udp tcp udp: gcc -o udp_echo_server udp_echo_server.c gcc -o udp_echo_client udp_echo_client.c tcp: gcc -o tcp_echo_server tcp_echo_server.c gcc -o tcp_echo_client tcp_echo_client.c clean: rm -f udp_echo_server udp_echo_client tcp_echo_server tcp_echo_client oor-1.2.0/tests/clientserver.h000066400000000000000000000001031313612200500163140ustar00rootroot00000000000000#define BUFLEN 512 #define NPACK 1000000 oor-1.2.0/tests/tcp_echo.h000066400000000000000000000003611313612200500154010ustar00rootroot00000000000000#define BUFLEN 512 #define NPACK 1000000 #define SPORT 50000 #define SADDR "127.0.0.1" /* Server address */ /* Max pending connection requests (TCP only)*/ #define QUEUELENGTH 2 oor-1.2.0/tests/tcp_echo_client.c000066400000000000000000000033711313612200500167360ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include "tcp_echo.h" int main(int argc, char **argv) { struct sockaddr_in si_server; int port, s, i, slen = sizeof(si_server); char buf[BUFLEN]; char srv_addr[16]; fd_set readfds; struct timeval tv; int ret; /* TCP socket creation */ if ((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { perror("socket"); exit(EXIT_FAILURE); } /* Server sockaddr structure */ memset((char *) &si_server, 0, sizeof(si_server)); si_server.sin_family = AF_INET; si_server.sin_port = htons(SPORT); if (inet_aton(SADDR, &si_server.sin_addr) == 0) { fprintf(stderr, "inet_aton() failed\n"); exit(EXIT_FAILURE); } /* Establish connection */ if (connect(s, (struct sockaddr *) &si_server, sizeof(si_server)) == -1) { fprintf(stderr, "connect() failed\n"); exit(EXIT_FAILURE); } /* Send-Recv loop */ for (i = 0; i < NPACK; i++) { sprintf(buf, "DATA PACKET # %d", i); printf("Sending -- %s -- to %s:%d\n", buf, inet_ntoa(si_server.sin_addr), ntohs(si_server.sin_port)); if (send(s, buf, BUFLEN, 0) == -1) { perror("send()"); exit(EXIT_FAILURE); } ret = recv(s, buf, BUFLEN, 0); if (ret > 0) { printf("Received -- %s -- from %s:%d\n", buf, inet_ntoa(si_server.sin_addr), ntohs(si_server.sin_port)); } else { perror("recv()"); exit(EXIT_FAILURE); } sleep(2); } close(s); return 0; } oor-1.2.0/tests/tcp_echo_server.c000066400000000000000000000033711313612200500167660ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include "tcp_echo.h" int main(int argc, char **argv) { struct sockaddr_in si_server; int port, s, i, slen = sizeof(si_server); char buf[BUFLEN]; char srv_addr[16]; fd_set readfds; struct timeval tv; int ret; /* TCP socket creation */ if ((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { perror("socket"); exit(EXIT_FAILURE); } /* Server sockaddr structure */ memset((char *) &si_server, 0, sizeof(si_server)); si_server.sin_family = AF_INET; si_server.sin_port = htons(SPORT); if (inet_aton(SADDR, &si_server.sin_addr) == 0) { fprintf(stderr, "inet_aton() failed\n"); exit(EXIT_FAILURE); } /* Establish connection */ if (connect(s, (struct sockaddr *) &si_server, sizeof(si_server)) == -1) { fprintf(stderr, "connect() failed\n"); exit(EXIT_FAILURE); } /* Send-Recv loop */ for (i = 0; i < NPACK; i++) { sprintf(buf, "DATA PACKET # %d", i); printf("Sending -- %s -- to %s:%d\n", buf, inet_ntoa(si_server.sin_addr), ntohs(si_server.sin_port)); if (send(s, buf, BUFLEN, 0) == -1) { perror("send()"); exit(EXIT_FAILURE); } ret = recv(s, buf, BUFLEN, 0); if (ret > 0) { printf("Received -- %s -- from %s:%d\n", buf, inet_ntoa(si_server.sin_addr), ntohs(si_server.sin_port)); } else { perror("recv()"); exit(EXIT_FAILURE); } sleep(2); } close(s); return 0; } oor-1.2.0/tests/udp_echo_client.c000066400000000000000000000037471313612200500167470ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include "clientserver.h" void error(const char *msg) { perror(msg); exit(EXIT_FAILURE); } int main(int argc, char **argv) { struct sockaddr_in si_server; int port, s, i, slen = sizeof(si_server); char buf[BUFLEN]; char *srv_addr; fd_set readfds; struct timeval tv; int ret; if (argc < 3) { printf("Usage: %s ip_add port\n", argv[0]); exit(1); } port = atoi(argv[2]); srv_addr = argv[1]; if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) { error("socket"); } memset((char *) &si_server, 0, sizeof(si_server)); si_server.sin_family = AF_INET; si_server.sin_port = htons(port); if (inet_aton(srv_addr, &si_server.sin_addr) == 0) { fprintf(stderr, "inet_aton() failed\n"); exit(EXIT_FAILURE); } for (i = 0; i < NPACK; i++) { sprintf(buf, "DATA PACKET # %d", i); printf("Sending -- %s -- to %s:%d\n", buf, inet_ntoa(si_server.sin_addr), ntohs(si_server.sin_port)); slen = sizeof(si_server); if (sendto(s, buf, BUFLEN, 0, (struct sockaddr *) &si_server, slen) == -1) { error("sendto()"); } FD_ZERO(&readfds); FD_SET(s, &readfds); tv.tv_sec = 1; tv.tv_usec = 0; if (select(s + 1, &readfds, NULL, NULL, &tv) == -1) { error("select()"); } if (FD_ISSET(s, &readfds)) { ret = recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *) &si_server, &slen); if (ret > 0) { printf("Received -- %s -- from %s:%d\n", buf, inet_ntoa(si_server.sin_addr), ntohs(si_server.sin_port)); } } sleep(2); } close(s); return 0; } oor-1.2.0/tests/udp_echo_server.c000066400000000000000000000034531313612200500167710ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include "clientserver.h" void error(const char *msg) { perror(msg); exit(EXIT_FAILURE); } int main(int argc, char **argv) { struct sockaddr_in si_local, si_remote; int s; int port; int slen; char buf[BUFLEN]; if (argc < 2) { printf("Usage: %s port\n", argv[0]); exit(1); } port = atoi(argv[1]); slen = sizeof(si_remote); if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) { error("socket"); } memset((char *) &si_local, 0, sizeof(si_local)); si_local.sin_family = AF_INET; si_local.sin_port = htons(port); si_local.sin_addr.s_addr = INADDR_ANY; if (bind(s, (const struct sockaddr *) &si_local, sizeof(si_local)) == -1) { error("bind"); } while (1) { slen = sizeof(si_remote); memset(buf, 0, sizeof(char) * BUFLEN); memset(&si_remote, 0, sizeof(si_remote)); if (recvfrom (s, buf, BUFLEN, 0, (struct sockaddr *) &si_remote, &slen) == -1) { error("recvfrom()"); } else { printf("Received -- %s -- from %s:%d\n", buf, inet_ntoa(si_remote.sin_addr), ntohs(si_remote.sin_port)); printf("Sending -- %s -- to %s:%d\n", buf, inet_ntoa(si_remote.sin_addr), ntohs(si_remote.sin_port)); slen = sizeof(si_remote); if (sendto (s, buf, BUFLEN, 0, (struct sockaddr *) &si_remote, slen) == -1) { error("recvfrom()"); } } } close(s); exit(EXIT_SUCCESS); }