diff --git a/router-container/Dockerfile b/router-container/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..56a9b94f92e34794b07384c2a46ee20f78976519 --- /dev/null +++ b/router-container/Dockerfile @@ -0,0 +1,93 @@ +FROM ubuntu:18.04 + +MAINTAINER mislav.novakovic@sartura.hr + +RUN \ + apt-get update && apt-get install -y \ + # general tools + git \ + cmake \ + build-essential \ + vim \ + supervisor \ + # libyang + libpcre3-dev \ + pkg-config \ + # sysrepo + libavl-dev \ + libev-dev \ + libprotobuf-c-dev \ + protobuf-c-compiler \ + # netopeer2 \ + libssh-dev \ + libssl-dev \ + # bindings + swig \ + python-dev + +# add netconf user +RUN \ + adduser --system netconf && \ + echo "netconf:netconf" | chpasswd + +# generate ssh keys for netconf user +RUN \ + mkdir -p /home/netconf/.ssh && \ + ssh-keygen -A && \ + ssh-keygen -t dsa -P '' -f /home/netconf/.ssh/id_dsa && \ + cat /home/netconf/.ssh/id_dsa.pub > /home/netconf/.ssh/authorized_keys + +# use /opt/dev as working directory +RUN mkdir /opt/dev +WORKDIR /opt/dev + +# libyang +RUN \ + git clone https://github.com/CESNET/libyang.git && \ + cd libyang && mkdir build && cd build && \ + cmake -DCMAKE_BUILD_TYPE:String="Debug" -DENABLE_BUILD_TESTS=OFF .. && \ + make -j2 && \ + make install && \ + ldconfig + +# sysrepo +RUN \ + git clone https://github.com/sysrepo/sysrepo.git && \ + cd sysrepo && mkdir build && cd build && \ + cmake -DCMAKE_BUILD_TYPE:String="Debug" -DREQUEST_TIMEOUT=60 -DENABLE_TESTS=OFF -DREPOSITORY_LOC:PATH=/etc/sysrepo .. && \ + make -j2 && \ + make install && \ + ldconfig + +# libnetconf2 +RUN \ + git clone https://github.com/CESNET/libnetconf2.git && \ + cd libnetconf2 && mkdir build && cd build && \ + cmake -DCMAKE_BUILD_TYPE:String="Debug" -DENABLE_BUILD_TESTS=OFF .. && \ + make -j2 && \ + make install && \ + ldconfig + +# netopeer2 +RUN \ + cd /opt/dev && \ + git clone https://github.com/CESNET/Netopeer2.git && \ + cd Netopeer2/server && mkdir build && cd build && \ + cmake -DCMAKE_BUILD_TYPE:String="Debug" .. && \ + make -j2 && \ + make install && \ + cd ../../cli && mkdir build && cd build && \ + cmake -DCMAKE_BUILD_TYPE:String="Debug" .. && \ + make -j2 && \ + make install + +ENV EDITOR vim +EXPOSE 830 + +COPY configuration.yang /opt/dev/configuration.yang +COPY junos-extension.yang /opt/dev/junos-extension.yang +RUN /usr/local/bin/sysrepoctl -i -g /opt/dev/configuration.yang +RUN /usr/local/bin/sysrepoctl -i -g /opt/dev/junos-extension.yang + +COPY supervisord.conf /etc/supervisord.conf +CMD ["/usr/bin/supervisord", "-c", "/etc/supervisord.conf"] diff --git a/router-container/configuration.yang b/router-container/configuration.yang new file mode 100644 index 0000000000000000000000000000000000000000..e8f3ec88fe863ca82c850adf71794fcd53a28abc --- /dev/null +++ b/router-container/configuration.yang @@ -0,0 +1,833 @@ + module configuration { + namespace "http://xml.juniper.net/xnm/1.1/xnm"; + prefix jc; + import junos-extension { + prefix junos; + } + + organization + "Juniper Networks, Inc."; + + description + "Junos YANG module for a subset of configuration hierarchies - it represents a route rules that are used by Firewall on Demand"; + + typedef daemon { + type string; + } + typedef filename { + type string; + } + typedef client-filename { + type string; + } + typedef hostname { + type string; + } + typedef ipaddr { + type string; + } + typedef sysid { + type string; + } + typedef interface-device { + type string; + } + typedef ddl-bits { + type string; + } + typedef isoaddr { + type string; + } + typedef ipprefix { + type string; + } + typedef ipprefix-mandatory { + type string; + } + typedef interface-unit { + type string; + } + typedef ipaddr-or-interface { + type string; + } + typedef areaid { + type string; + } + typedef interface-name { + type string; + } + typedef community { + type string; + } + typedef interface-wildcard { + type string; + } + typedef unreadable { + type string; + } + typedef ipprefix-optional { + type string; + } + typedef policy-algebra { + type string; + } + typedef regular-expression { + type string; + } + typedef group-glob { + type string; + } + typedef atm-vci { + type string; + } + typedef ipprefix-only { + type string; + } + typedef ipv4addr { + type string; + } + typedef ipv4prefix { + type string; + } + typedef ipv4prefix-mandatory { + type string; + } + typedef ipv4addr-or-interface { + type string; + } + typedef ipv4prefix-optional { + type string; + } + typedef ipv4prefix-only { + type string; + } + typedef ipv6addr { + type string; + } + typedef ipv6prefix { + type string; + } + typedef ipv6prefix-mandatory { + type string; + } + typedef ipv6addr-or-interface { + type string; + } + typedef ipv6prefix-optional { + type string; + } + typedef ipv6prefix-only { + type string; + } + typedef interface-device-wildcard { + type string; + } + typedef time { + type string; + } + typedef mac-addr { + type string; + } + typedef mac-addr-prefix { + type string; + } + typedef mac-unicaset { + type string; + } + typedef mac-unicast-prefix { + type string; + } + typedef mac-multicast { + type string; + } + typedef mac-multicast-prefix { + type string; + } + typedef mpls-label { + type string; + } + typedef unsigned-float { + type string; + } + typedef isoprefix { + type string; + } + typedef isosysid { + type string; + } + typedef string-huge { + type string; + } + typedef variable { + type string; + } + typedef glob-variable { + type string; + } + typedef vlan-range { + type string; + } + typedef interface-range-wild { + type string; + } + typedef fc-addr { + type string; + } + typedef wwn { + type string; + } + typedef logfilename { + type string; + } + typedef range { + type string; + } + typedef esi { + type string; + } + + container configuration { + config true; + uses juniper-config; + } + grouping juniper-config { + leaf rcsid { + description "Revision control system identifier"; + type string; + } + leaf version { + description "Software version information"; + type string; + } + container routing-options { + description "Protocol-independent routing option configuration"; + uses juniper-routing-options; + } + } + grouping juniper-routing-options { + uses apply-advanced; + container flow { + description "Locally defined flow routing information"; + uses apply-advanced; + list route { + key name; + ordered-by user; + description "Flow route"; + uses flow-route-inet; + } + } + leaf router-id { + description "Router identifier"; + type ipv4addr; + } + } + + grouping apply-advanced { + description "Apply advanced configuration logic"; + leaf-list apply-groups { + description "Groups from which to inherit configuration data"; + type string; + } + leaf-list apply-groups-except { + description "Don't inherit configuration data from these groups"; + type string; + } + } + grouping flow-route-inet { + leaf name { + description "(null)"; + type string; + } + uses apply-advanced; + leaf no-install { + description "Don't install firewall filter in forwarding"; + type empty; + } + container then { + description "Actions to take for this flow"; + uses flow-route-op; + } + container match { + description "Flow definition"; + uses flow-route-qualifier-inet; + } + } + grouping flow-route-inet6 { + leaf route_name { + description "(null)"; + type string; + } + uses apply-advanced; + leaf no-install { + description "Don't install firewall filter in forwarding"; + type empty; + } + container then { + description "Actions to take for this flow"; + uses flow-route-op; + } + container match { + description "Flow definition"; + uses flow-route-qualifier-inet6; + } + } + grouping flow-route-op { + uses apply-advanced; + leaf community { + description "Name of BGP community"; + type string; + } + choice flow_op_action { + leaf accept { + description "Allow traffic through"; + type empty; + } + leaf discard { + description "Discard all traffic for this flow"; + type empty; + } + leaf rate-limit { + description "Rate in bits/sec to limit the flow traffic"; + type string; + } + } + leaf routing-instance { + description "Redirect to instance identified via Route Target community"; + type string { + junos:posix-pattern "^[a-z]+:[0-9.]+L?:[0-9]+$"; + junos:pattern-message "Use format 'target:x:y' where 'x' is an AS number followed by an optional 'L' (To indicate 4 byte AS), or an IP address and 'y' is a number. e.g. target:123456L:100"; + } + } + leaf sample { + description "Sample traffic that matches this flow"; + type empty; + } + leaf mark { + description "Set DSCP value for traffic that matches this flow"; + type uint32 { + range "0 .. 63"; + } + } + leaf next-term { + description "Continue the filter evaluation after matching this flow"; + type empty; + } + } + grouping flow-route-qualifier-inet6 { + uses apply-advanced; + leaf-list protocol { + description "IP protocol value"; + type enumeration { + enum icmp { + description "Internet Control Message Protocol"; + } + enum igmp { + description "Internet Group Management Protocol"; + } + enum ipip { + description "IP in IP"; + } + enum tcp { + description "Transmission Control Protocol"; + } + enum egp { + description "Exterior gateway protocol"; + } + enum udp { + description "User Datagram Protocol"; + } + enum rsvp { + description "Resource Reservation Protocol"; + } + enum gre { + description "Generic routing encapsulation"; + } + enum esp { + description "IPSec Encapsulating Security Payload"; + } + enum ah { + description "IP Security authentication header"; + } + enum icmp6 { + description "Internet Control Message Protocol Version 6"; + } + enum ospf { + description "Open Shortest Path First"; + } + enum pim { + description "Protocol Independent Multicast"; + } + enum sctp { + description "Stream Control Transmission Protocol"; + } + enum expression { + description "(null)"; + } + } + } + leaf-list port { + ordered-by user; + description "Source or destination TCP/UDP port"; + junos:must "(!((\".. source-port\" || \".. destination-port\")))"; + junos:must-message "'port' statement cannot be included along with either of 'source-port' and 'destination-port' statements"; + /* uses flow-qual-port; */ + type string; + + } + leaf-list destination-port { + ordered-by user; + description "Destination TCP/UDP port"; + /* uses flow-qual-port; */ + type string; + + } + leaf-list source-port { + ordered-by user; + description "Source TCP/UDP port"; + /* uses flow-qual-port; */ + type string; + + } + leaf-list tcp-flags { + description "TCP flags"; + type enumeration { + enum fin { + description "FIN"; + } + enum syn { + description "SYN"; + } + enum rst { + description "RST"; + } + enum push { + description "PUSH"; + } + enum ack { + description "ACK"; + } + enum urgent { + description "Urgent"; + } + enum expression { + description "(null)"; + } + } + } + leaf-list packet-length { + description "Packet length (0-65535)"; + type policy-algebra; + } + leaf-list dscp { + description "Differentiated Services (DiffServ) code point (DSCP) (0-63)"; + type policy-algebra; + } + leaf-list fragment { + description "(null)"; + type enumeration { + enum dont-fragment { + description "Don't Fragment flag is set"; + } + enum not-a-fragment { + description "Not a fragment"; + } + enum is-fragment { + description "Fragmented packet"; + } + enum first-fragment { + description "First fragment"; + } + enum last-fragment { + description "Last fragment"; + } + } + } + container destination { + description "Destination prefix for this traffic flow"; + uses flow-prefix-with-offset; + } + container source { + description "Source prefix for this traffic flow"; + uses flow-prefix-with-offset; + } + leaf-list icmp6-type { + description "ICMP message type"; + type enumeration { + enum echo-request { + description "Echo request"; + } + enum echo-reply { + description "Echo reply"; + } + enum destination-unreachable { + description "Unreachable"; + } + enum router-advertisement { + description "Router advertisement"; + } + enum router-solicit { + description "Router solicit"; + } + enum time-exceeded { + description "Time exceeded"; + } + enum parameter-problem { + description "Parameter problem"; + } + enum packet-too-big { + description "Packet too big"; + } + enum membership-query { + description "Query for multicast listener"; + } + enum membership-report { + description "Report for multicast listener"; + } + enum membership-termination { + description "Terminate multicast listener"; + } + enum redirect { + description "Router informs host of a better first hop for a destination"; + } + enum neighbor-solicit { + description "Request link-layer address of neighbor"; + } + enum neighbor-advertisement { + description "Provide link-layer address to neighbor"; + } + enum router-renumbering { + description "Router renumbering command"; + } + enum node-information-request { + description "Query for information on address or name"; + } + enum node-information-reply { + description "Reply to node information request"; + } + enum expression { + description "(null)"; + } + } + } + leaf-list icmp6-code { + description "ICMP message code"; + type enumeration { + enum no-route-to-destination { + description "Route to destination not found"; + } + enum administratively-prohibited { + description "Communication with destination prohibited by filter"; + } + enum address-unreachable { + description "Problem with resolving address or other link-specific problem"; + } + enum port-unreachable { + description "Port unreachable"; + } + enum ttl-eq-zero-during-transit { + description "TTL eq zero during transit"; + } + enum ttl-eq-zero-during-reassembly { + description "TTL eq zero during reassembly"; + } + enum ip6-header-bad { + description "IP header bad"; + } + enum unrecognized-next-header { + description "Unrecognized next header type encountered"; + } + enum unrecognized-option { + description "Unrecogzined IPv6 option"; + } + enum expression { + description "(null)"; + } + } + } + leaf-list flow-label { + description "Flow-label (0-1048575)"; + type policy-algebra; + } + } + grouping flow-route-qualifier-inet { + uses apply-advanced; + leaf-list protocol { + description "IP protocol value"; + type enumeration { + enum icmp { + description "Internet Control Message Protocol"; + } + enum igmp { + description "Internet Group Management Protocol"; + } + enum ipip { + description "IP in IP"; + } + enum tcp { + description "Transmission Control Protocol"; + } + enum egp { + description "Exterior gateway protocol"; + } + enum udp { + description "User Datagram Protocol"; + } + enum rsvp { + description "Resource Reservation Protocol"; + } + enum gre { + description "Generic routing encapsulation"; + } + enum esp { + description "IPSec Encapsulating Security Payload"; + } + enum ah { + description "IP Security authentication header"; + } + enum icmp6 { + description "Internet Control Message Protocol Version 6"; + } + enum ospf { + description "Open Shortest Path First"; + } + enum pim { + description "Protocol Independent Multicast"; + } + enum sctp { + description "Stream Control Transmission Protocol"; + } + enum expression { + description "(null)"; + } + } + } + leaf-list port { + ordered-by user; + description "Source or destination TCP/UDP port"; + junos:must "(!((\".. source-port\" || \".. destination-port\")))"; + junos:must-message "'port' statement cannot be included along with either of 'source-port' and 'destination-port' statements"; + /* uses flow-qual-port; */ + type string; + } + leaf-list destination-port { + ordered-by user; + description "Destination TCP/UDP port"; + /* uses flow-qual-port; */ + type string; + + } + leaf-list source-port { + ordered-by user; + description "Source TCP/UDP port"; + /* uses flow-qual-port; */ + type string; + + } + leaf-list tcp-flags { + description "TCP flags"; + type enumeration { + enum fin { + description "FIN"; + } + enum syn { + description "SYN"; + } + enum rst { + description "RST"; + } + enum push { + description "PUSH"; + } + enum ack { + description "ACK"; + } + enum urgent { + description "Urgent"; + } + enum expression { + description "(null)"; + } + } + } + leaf-list packet-length { + description "Packet length (0-65535)"; + type policy-algebra; + } + leaf-list dscp { + description "Differentiated Services (DiffServ) code point (DSCP) (0-63)"; + type policy-algebra; + } + leaf-list fragment { + description "(null)"; + type enumeration { + enum dont-fragment { + description "Don't Fragment flag is set"; + } + enum not-a-fragment { + description "Not a fragment"; + } + enum is-fragment { + description "Fragmented packet"; + } + enum first-fragment { + description "First fragment"; + } + enum last-fragment { + description "Last fragment"; + } + } + } + leaf destination { + description "Destination prefix for this traffic flow"; + type ipprefix; + } + leaf source { + description "Source prefix for this traffic flow"; + type ipprefix; + } + leaf-list icmp-code { + description "ICMP message code"; + type enumeration { + enum network-unreachable { + description "Network unreachable"; + } + enum host-unreachable { + description "Host unreachable"; + } + enum protocol-unreachable { + description "Protocol unreachable"; + } + enum port-unreachable { + description "Port unreachable"; + } + enum fragmentation-needed { + description "Fragmentation needed"; + } + enum source-route-failed { + description "Source route failed"; + } + enum destination-network-unknown { + description "Destination network unknown"; + } + enum destination-host-unknown { + description "Destination host unknown"; + } + enum source-host-isolated { + description "Source host isolated"; + } + enum destination-network-prohibited { + description "Destination network prohibited"; + } + enum destination-host-prohibited { + description "Destination host prohibited"; + } + enum network-unreachable-for-tos { + description "Network unreachable for ToS"; + } + enum host-unreachable-for-tos { + description "Host unreachable for ToS"; + } + enum communication-prohibited-by-filtering { + description "Communication prohibited by filtering"; + } + enum host-precedence-violation { + description "Host precedence violation"; + } + enum precedence-cutoff-in-effect { + description "Precedence cutoff in effect"; + } + enum redirect-for-network { + description "Redirect for network"; + } + enum redirect-for-host { + description "Redirect for host"; + } + enum redirect-for-tos-and-net { + description "Redirect for ToS and net"; + } + enum redirect-for-tos-and-host { + description "Redirect for ToS and host"; + } + enum ttl-eq-zero-during-transit { + description "TTL eq zero during transit"; + } + enum ttl-eq-zero-during-reassembly { + description "TTL eq zero during reassembly"; + } + enum ip-header-bad { + description "IP header bad"; + } + enum required-option-missing { + description "Required option missing"; + } + enum expression { + description "(null)"; + } + } + } + leaf-list icmp-type { + description "ICMP message type"; + type enumeration { + enum echo-request { + description "Echo request"; + } + enum echo-reply { + description "Echo reply"; + } + enum unreachable { + description "Unreachable"; + } + enum source-quench { + description "Source quench"; + } + enum redirect { + description "Redirect"; + } + enum router-advertisement { + description "Router advertisement"; + } + enum router-solicit { + description "Router solicit"; + } + enum time-exceeded { + description "Time exceeded"; + } + enum parameter-problem { + description "Parameter problem"; + } + enum timestamp { + description "Timestamp"; + } + enum timestamp-reply { + description "Timestamp reply"; + } + enum info-request { + description "Informational request"; + } + enum info-reply { + description "Informational reply"; + } + enum mask-request { + description "Mask request"; + } + enum mask-reply { + description "Mask reply"; + } + enum expression { + description "(null)"; + } + } + } + } + grouping flow-prefix-with-offset { + leaf prefix { + description "(null)"; + type ipprefix; + + } + leaf prefix-offset { + description "Offset from where prefix match will start"; + type uint32; + } + } +} diff --git a/router-container/junos-extension.yang b/router-container/junos-extension.yang new file mode 100644 index 0000000000000000000000000000000000000000..8c4f05b2eb82e9002f99eff49eff0cc26d783f45 --- /dev/null +++ b/router-container/junos-extension.yang @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2017 Juniper Networks, Inc. + * All rights reserved. + */ + + module junos-extension { + namespace "http://xml.juniper.net/junos/15.1F6/junos"; + prefix junos; + + import ietf-yang-metadata { + prefix md; + } + + organization + "Juniper Networks, Inc."; + + description + "This module contains definitions for Junos YANG extensions."; + + extension must { + argument "stmt-algebra"; + description " + expression of configuration-statement paths having special + keywords like any, all, unique"; + } + extension must-message { + argument "message-string"; + description " + When specifying the junos:must constraint, a must-message should + also be specified so that when the contraint is not met,the + warning message informs users what the constraints are. + + If the must-message is missing, the input file will compile, + but the warning message will say (null) which won't be + helpful for users to fix the problem"; + } + extension posix-pattern { + argument "value"; + description " + expression of pattern in posix format"; + } + extension pattern-message { + argument "value"; + description " + Error message in case of mismatch"; + } + + md:annotation commit-seconds { + type uint64; + } + + md:annotation commit-localtime { + type string; + } + + md:annotation commit-user { + type string; + } + } diff --git a/router-container/run.txt b/router-container/run.txt new file mode 100644 index 0000000000000000000000000000000000000000..1f85de181cfe401833cd4597b29482761c3ab057 --- /dev/null +++ b/router-container/run.txt @@ -0,0 +1,6 @@ +docker build -t juniper . +docker run -it --name juniper -p 830:830 --rm juniper:latest + +netopeer2-cli +> connect -l netconf -p 830 localhost +Password: netconf diff --git a/router-container/supervisord.conf b/router-container/supervisord.conf new file mode 100644 index 0000000000000000000000000000000000000000..5e40e25471c77c424762bdfdb3af14944f7b6533 --- /dev/null +++ b/router-container/supervisord.conf @@ -0,0 +1,22 @@ +[supervisord] +nodaemon=true +logfile=/var/log/supervisord.log +loglevel=debug + +[program:sysrepod] +command=/usr/local/bin/sysrepod -d +autorestart=true +redirect_stderr=true +priority=1 + +[program:application_example] +command=/opt/dev/sysrepo/build/examples/application_example configuration +autorestart=true +redirect_stderr=true +priority=2 + +[program:netopeer2-server] +command=/usr/local/bin/netopeer2-server -d -c MSG +autorestart=true +redirect_stderr=true +priority=3