modernize backfire 10.03 so it can be operational again master
authoracoul <alex@ozo.com>
Tue, 19 Jul 2016 13:53:16 +0000 (16:53 +0300)
committeracoul <alex@ozo.com>
Tue, 19 Jul 2016 13:53:16 +0000 (16:53 +0300)
74 files changed:
include/depends.mk
include/package-ipkg.mk
include/package.mk
include/target.mk
package/bird/Makefile [new file with mode: 0644]
package/bird/files/bird4.conf [new file with mode: 0644]
package/bird/files/bird4.init [new file with mode: 0644]
package/bird/files/bird4loop [new file with mode: 0644]
package/bird/files/bird6.conf [new file with mode: 0644]
package/bird/files/bird6.init [new file with mode: 0644]
package/bird/files/bird6loop [new file with mode: 0644]
package/busybox/Makefile
package/busybox/config/Config.in
package/dnsmasq/Makefile
package/dnsmasq/patches/100-fix-dhcp-no-address-warning.patch [new file with mode: 0644]
package/dnsmasq/patches/101-ipv6.patch [deleted file]
package/dnsmasq/patches/110-ipset-remove-old-kernel-support.patch [new file with mode: 0644]
package/dnsmasq/patches/210-dnssec-improve-timestamp-heuristic.patch [new file with mode: 0644]
package/dnsmasq/patches/230-fix-poll-h-include-warning-on-musl.patch [new file with mode: 0644]
package/mtd/Makefile
package/mtd/src/Makefile
package/mtd/src/bcm_tag.h [new symlink]
package/mtd/src/fis.c
package/mtd/src/imagetag.c [new file with mode: 0644]
package/mtd/src/jffs2.c
package/mtd/src/md5.c [new file with mode: 0644]
package/mtd/src/md5.h [new file with mode: 0644]
package/mtd/src/mtd-api.h [deleted file]
package/mtd/src/mtd.c
package/mtd/src/mtd.h
package/mtd/src/seama.c [new file with mode: 0644]
package/mtd/src/seama.h [new file with mode: 0644]
package/mtd/src/trx.c
package/quagga/Makefile [new file with mode: 0644]
package/quagga/files/quagga [new file with mode: 0644]
package/quagga/files/quagga.conf [new file with mode: 0644]
package/quagga/files/quagga.init [new file with mode: 0644]
package/quagga/not-patches/patches-nopes/120-quagga_manet.patch [new file with mode: 0644]
package/quagga/not-patches/patches-nopes/158-next-hop-self_all.patch [new file with mode: 0644]
package/quagga/not-patches/patches-nopes/159-share_aspath.patch [new file with mode: 0644]
package/quagga/not-patches/patches-old/100-bgpd_Display_configured_dampening_parameters.patch [new file with mode: 0644]
package/quagga/not-patches/patches-old/110-bgpd_suppress_value_not_less_reuse_value.patch [new file with mode: 0644]
package/quagga/not-patches/patches-old/130-bgpd_ignore_stale_entry.patch [new file with mode: 0644]
package/quagga/not-patches/patches-old/140-bgpd-routes_from_established_peers.patch [new file with mode: 0644]
package/quagga/not-patches/patches-old/160-bgpd-enable_bgp_log-neighbor-changes.patch [new file with mode: 0644]
package/quagga/not-patches/patches-old/220-bgpd_dampening_command_tree.patch [new file with mode: 0644]
package/quagga/not-patches/patches-old/nopes/180-bgpd-lower_default_keepalive_holdtime.patch [new file with mode: 0644]
package/quagga/not-patches/patches-old/nopes/200-bgpd-implicit_updates_withdrawal_from_zebra.patch [new file with mode: 0644]
package/quagga/not-patches/patches-pgbgp/140-holdtimer-set.patch [new file with mode: 0644]
package/quagga/not-patches/patches-pgbgp/150-no-cross-fs-link.patch [new file with mode: 0644]
package/quagga/not-patches/patches-pgbgp/160-pgbgp.patch [new file with mode: 0644]
package/quagga/not-patches/patches-pgbgp/161-pgbgp-addon.patch [new file with mode: 0644]
package/quagga/not-patches/patches-pgbgp/162-bgp_table_wrapper.patch [new file with mode: 0644]
package/quagga/not-patches/patches-pgbgp/162-pgbgp-bgp_table_wrapper.patch [new file with mode: 0644]
package/quagga/not-patches/patches-pgbgp/170-use-supported-pagers.patch [new file with mode: 0644]
package/quagga/not-patches/patches-upstream/old/140-holdtimer-set.patch [new file with mode: 0644]
package/quagga/not-patches/patches-upstream/old/150-no-cross-fs-link.patch [new file with mode: 0644]
package/quagga/not-patches/patches-upstream/old/170-use-supported-pagers.patch [new file with mode: 0644]
package/quagga/patches-upstream/150-unknown_afi.patch [new file with mode: 0644]
package/quagga/patches-upstream/200-bgp_dampening.patch [new file with mode: 0644]
package/quagga/patches-upstream/210-dampening_commands.patch [new file with mode: 0644]
package/quagga/patches-upstream/300-fix_MRT.patch [new file with mode: 0644]
package/quagga/patches-upstream/320-fix_uninitialized_variables.patch [new file with mode: 0644]
package/quagga/patches-upstream/400-vpnv4_stat_fix.patch [new file with mode: 0644]
package/quagga/patches-upstream/999-old_uclibc.patch [new file with mode: 0644]
package/udevtrigger/patches/001-no_debug.patch
rules.mk
target/linux/atheros/Makefile
target/linux/atheros/config-2.6.30
target/linux/generic-2.6/patches-2.6.30/999-timeconst.patch [new file with mode: 0644]
toolchain/binutils/Makefile
toolchain/gcc/Makefile
toolchain/gcc/patches/4.4.1/999-gcc5.patch [new file with mode: 0644]
toolchain/gcc/patches/4.4.1/999-kill_inline.patch [new file with mode: 0644]

index 65e9b25..828ceb8 100644 (file)
@@ -13,7 +13,7 @@
 
 DEP_FINDPARAMS := -x "*/.svn*" -x ".*" -x "*:*" -x "*\!*" -x "* *" -x "*\\\#*" -x "*/.*_check"
 
-find_md5=find $(1) -type f $(patsubst -x,-and -not -path,$(DEP_FINDPARAMS) $(2)) | md5s
+find_md5=$(SH_FUNC) find $(1) -type f $(patsubst -x,-and -not -path,$(DEP_FINDPARAMS) $(2)) | md5s
 
 define rdep
   .PRECIOUS: $(2)
index 0dd398e..5728b08 100644 (file)
@@ -30,7 +30,7 @@ IPKG_STATE_DIR:=$(TARGET_DIR)/usr/lib/opkg
 define BuildIPKGVariable
 ifdef Package/$(1)/$(2)
   $(call shexport,Package/$(1)/$(2))
-  $(1)_COMMANDS += var2file "$(call shvar,Package/$(1)/$(2))" $(2);
+  $(1)_COMMANDS += $(SH_FUNC) var2file "$(call shvar,Package/$(1)/$(2))" $(2);
 endif
 endef
 
index 4c1d138..9815aa8 100644 (file)
@@ -131,7 +131,7 @@ define Build/DefaultTargets
                $(call $(hook),$(TMP_DIR)/stage-$(PKG_NAME),$(TMP_DIR)/stage-$(PKG_NAME)/host)$(sep)\
        )
        if [ -d $(TMP_DIR)/stage-$(PKG_NAME) ]; then \
-               (cd $(TMP_DIR)/stage-$(PKG_NAME); find ./ > $(STAGING_DIR)/packages/$(STAGING_FILES_LIST)); \
+               (cd $(TMP_DIR)/stage-$(PKG_NAME); $(SH_FUNC) find ./ > $(STAGING_DIR)/packages/$(STAGING_FILES_LIST)); \
                $(CP) $(TMP_DIR)/stage-$(PKG_NAME)/* $(STAGING_DIR)/; \
        fi
        rm -rf $(TMP_DIR)/stage-$(PKG_NAME)
index 0db3815..f5e4609 100644 (file)
@@ -67,10 +67,10 @@ define Profile
                echo "Target-Profile-Kconfig: yes"; \
        fi; \
        echo "Target-Profile-Config: "; \
-       getvar "$(call shvar,Profile/$(1)/Config)"; \
+       $(SH_FUNC) getvar "$(call shvar,Profile/$(1)/Config)"; \
        echo "@@"; \
        echo "Target-Profile-Description:"; \
-       getvar "$(call shvar,Profile/$(1)/Description)"; \
+       $(SH_FUNC) getvar "$(call shvar,Profile/$(1)/Description)"; \
        echo "@@"; \
        echo;
   ifeq ($(CONFIG_TARGET_$(call target_conf,$(BOARD)_$(if $(SUBTARGET),$(SUBTARGET)_)$(1))),y)
@@ -186,7 +186,7 @@ define BuildTargets/DumpCurrent
         echo 'Linux-Release: $(LINUX_RELEASE)'; \
         echo 'Linux-Kernel-Arch: $(LINUX_KARCH)'; \
         echo 'Target-Description:'; \
-        getvar $(call shvar,Target/Description); \
+        $(SH_FUNC) getvar $(call shvar,Target/Description); \
         echo '@@'; \
         echo 'Default-Packages: $(DEFAULT_PACKAGES)'; \
         $(DUMPINFO)
diff --git a/package/bird/Makefile b/package/bird/Makefile
new file mode 100644 (file)
index 0000000..68e85a2
--- /dev/null
@@ -0,0 +1,214 @@
+# 
+# Copyright (C) 2009-2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=bird
+PKG_VERSION:=1.6.0
+PKG_RELEASE:=1
+
+PKG_SOURCE:=bird-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=ftp://bird.network.cz/pub/bird
+PKG_MD5SUM:=4c92ec3548a2a120243879b6ef7046dd
+PKG_BUILD_DEPENDS:=libncurses libreadline
+PKG_MAINTAINER:=Álvaro Fernández Rojas <noltari@gmail.com>
+
+PKG_LICENSE:=GPL-2.0
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/bird/Default
+  TITLE:=The BIRD Internet Routing Daemon
+  URL:=http://bird.network.cz/
+  DEPENDS:=+libpthread
+endef
+
+define Package/birdc/Default
+  TITLE:=The BIRD command-line client
+  URL:=http://bird.network.cz/
+  DEPENDS:= +libreadline +libncurses
+endef
+
+define Package/birdcl/Default
+  TITLE:=The BIRD lightweight command-line client
+  URL:=http://bird.network.cz/
+endef
+
+define Package/bird/Default/description1
+BIRD is an internet routing daemon which manages TCP/IP routing tables
+with support of modern routing protocols, easy to use configuration
+interface and powerful route filtering language. It is lightweight and
+efficient and therefore appropriate for small embedded routers.
+
+endef
+
+define Package/bird/Default/description2
+In BGP, BIRD supports communities, multiprotocol extensions, MD5
+authentication, 32bit AS numbers and could act as a route server or a
+route reflector. BIRD also supports multiple RIBs, multiple kernel
+routing tables and redistribution between the protocols with a powerful
+configuration syntax.
+
+endef
+
+define Package/bird/Default/description3
+This is a BIRD command-line client. It is used to send commands to BIRD,
+commands can perform simple actions such as enabling/disabling of
+protocols, telling BIRD to show various information, telling it to show
+a routing table filtered by a filter, or asking BIRD to reconfigure.
+
+Unless you can't afford dependency on ncurses and readline, you
+should install BIRD command-line client together with BIRD.
+
+endef
+
+define Package/bird/Default/description4
+This is a BIRD lightweight command-line client. It is used to send commands to BIRD,
+commands can perform simple actions such as enabling/disabling of
+protocols, telling BIRD to show various information, telling it to show
+a routing table filtered by a filter, or asking BIRD to reconfigure.
+
+endef
+
+define Package/bird4
+$(call Package/bird/Default)
+  SECTION:=net
+  CATEGORY:=Network
+  SUBMENU:=Routing and Redirection
+  TITLE+= (IPv4)
+endef
+
+define Package/birdc4
+$(call Package/birdc/Default)
+  SECTION:=net
+  CATEGORY:=Network
+  SUBMENU:=Routing and Redirection
+  TITLE+= (IPv4)
+  DEPENDS+= +bird4
+endef
+
+define Package/birdcl4
+$(call Package/birdcl/Default)
+  SECTION:=net
+  CATEGORY:=Network
+  SUBMENU:=Routing and Redirection
+  TITLE+= (IPv4)
+  DEPENDS+= +bird4
+endef
+
+define Package/bird6
+$(call Package/bird/Default)
+  SECTION:=net
+  CATEGORY:=Network
+  SUBMENU:=Routing and Redirection
+  TITLE+= (IPv6)
+endef
+
+define Package/birdc6
+$(call Package/birdc/Default)
+  SECTION:=net
+  CATEGORY:=Network
+  SUBMENU:=Routing and Redirection
+  TITLE+= (IPv6)
+  DEPENDS+= +bird6
+endef
+
+define Package/birdcl6
+$(call Package/birdcl/Default)
+  SECTION:=net
+  CATEGORY:=Network
+  SUBMENU:=Routing and Redirection
+  TITLE+= (IPv6)
+  DEPENDS+= +bird6
+endef
+
+define Package/bird4/description
+$(call Package/bird/Default/description1)
+This is IPv4 version of BIRD, it supports OSPFv2, RIPv2 and BGP
+protocols.
+
+$(call Package/bird/Default/description2)
+endef
+
+define Package/birdc4/description
+$(call Package/bird/Default/description1)
+$(call Package/bird/Default/description3)
+endef
+
+define Package/birdcl4/description
+$(call Package/bird/Default/description1)
+$(call Package/bird/Default/description4)
+endef
+
+define Package/bird6/description
+$(call Package/bird/Default/description1)
+This is IPv6 version of BIRD, it supports OSPFv3, RIPng and BGP
+protocols.
+
+$(call Package/bird/Default/description2)
+endef
+
+define Package/birdc6/description
+$(call Package/bird/Default/description1)
+$(call Package/bird/Default/description3)
+endef
+
+define Package/birdcl6/description
+$(call Package/bird/Default/description1)
+$(call Package/bird/Default/description4)
+endef
+
+CONFIGURE_ARGS += --with-linux-headers="$(LINUX_DIR)"
+
+TARGET_CFLAGS+=-std=gnu89
+
+define Build/Template
+
+$(STAMP_BUILT)-$(2): $(STAMP_PREPARED)
+       $(call Build/Configure/Default,$(3))
+       $(call Build/Compile/Default,)
+       ( cd $(PKG_BUILD_DIR); mv -f bird bird$(2); mv -f birdc birdc$(2); mv -f birdcl birdcl$(2) )
+       -$(MAKE) -C $(PKG_BUILD_DIR) clean
+       touch $$@
+
+$(STAMP_BUILT): $(STAMP_BUILT)-$(2)
+
+define Package/bird$(2)/install
+       $(INSTALL_DIR)  $$(1)/usr/sbin
+       $(INSTALL_BIN)  $$(PKG_BUILD_DIR)/bird$(2) $$(1)/usr/sbin/
+       $(INSTALL_DIR)  $$(1)/etc
+       $(INSTALL_DATA) ./files/bird$(2).conf $$(1)/etc/
+       $(INSTALL_DIR)  $$(1)/etc/init.d
+       $(INSTALL_BIN)  ./files/bird$(2).init $$(1)/etc/init.d/bird$(2)
+
+endef
+
+define Package/bird$(2)/conffiles
+/etc/bird$(2).conf
+endef
+
+define Package/birdc$(2)/install
+       $(INSTALL_DIR) $$(1)/usr/sbin
+       $(INSTALL_BIN) $$(PKG_BUILD_DIR)/birdc$(2) $$(1)/usr/sbin/
+endef
+
+define Package/birdcl$(2)/install
+       $(INSTALL_DIR) $$(1)/usr/sbin
+       $(INSTALL_BIN) $$(PKG_BUILD_DIR)/birdcl$(2) $$(1)/usr/sbin/
+endef
+
+endef
+
+
+$(eval $(call Build/Template,bird4,4, --disable-ipv6))
+$(eval $(call Build/Template,bird6,6, --enable-ipv6))
+
+$(eval $(call BuildPackage,bird4))
+$(eval $(call BuildPackage,birdc4))
+$(eval $(call BuildPackage,birdcl4))
+$(eval $(call BuildPackage,bird6))
+$(eval $(call BuildPackage,birdc6))
+$(eval $(call BuildPackage,birdcl6))
diff --git a/package/bird/files/bird4.conf b/package/bird/files/bird4.conf
new file mode 100644 (file)
index 0000000..8616a0a
--- /dev/null
@@ -0,0 +1,121 @@
+
+# THIS CONFIG FILE IS NOT A COMPLETE DOCUMENTATION
+# PLEASE LOOK IN THE BIRD DOCUMENTATION FOR MORE INFO
+
+# However, most of options used here are just for example
+# and will be removed in real-life configs.
+
+log syslog all;
+
+# Override router ID
+#router id 192.168.0.1;
+
+# Turn on global debugging of all protocols
+#debug protocols all;
+
+
+# Define a route filter...
+# filter test_filter {
+#      if net ~ 10.0.0.0/16 then accept;
+#      else reject;
+# }
+
+# The direct protocol automatically generates device routes to all network
+# interfaces. Can exist in as many instances as you wish if you want to
+# populate multiple routing tables with device routes. Because device routes
+# are handled by Linux kernel, this protocol is  usually not needed.
+# protocol direct {
+#      interface "*";  # Restrict network interfaces it works with
+# }
+
+# This pseudo-protocol performs synchronization between BIRD's routing
+# tables and the kernel. You can run multiple instances of the kernel
+# protocol and synchronize different kernel tables with different BIRD tables.
+protocol kernel {
+#      learn;                  # Learn all alien routes from the kernel
+#      persist;                # Don't remove routes on bird shutdown
+       scan time 20;           # Scan kernel routing table every 20 seconds
+#      import none;            # Default is import all
+#      export all;             # Default is export none
+}
+
+# This pseudo-protocol watches all interface up/down events.
+protocol device {
+       scan time 10;           # Scan interfaces every 10 seconds
+}
+
+# Static routes (again, there can be multiple instances, so that you
+# can disable/enable various groups of static routes on the fly).
+protocol static {
+#      export all;             # Default is export none
+#      route 0.0.0.0/0 via 62.168.0.13;
+#      route 10.0.0.0/8 reject;
+#      route 192.168.0.0/16 reject;
+}
+
+
+#protocol rip {
+#      disabled;
+#      import all;
+#      export all;
+#      export filter test_filter;
+
+#      port 1520;
+#      period 7;
+#      infinity 16;
+#      garbage time 60;
+#      interface "*" { mode broadcast; };
+#      honor neighbor;
+#      honor always;
+#      honor never;
+#      authentication none;
+#}
+
+
+#protocol ospf {
+#      disabled;
+#      import all;
+#      export all;
+#      export where source = RTS_STATIC;
+
+#      area 0 {
+#              interface "eth*" {
+#                      cost 10;
+#                      hello 3;
+#                      retransmit 2;
+#                      wait 5;
+#                      dead 20;
+#                      type broadcast;
+#                      authentication simple;
+#                      password "pass";
+#              };
+#      };
+#}
+
+
+#protocol bgp {
+#      disabled;
+#      import all;
+#      export all;
+#      export where source = RTS_STATIC;
+
+#      local as 65000;
+#      neighbor 192.168.1.1 as 65001;
+#      multihop 20 via 192.168.2.1;
+
+#      hold time 240;
+#      startup hold time 240;
+#      connect retry time 120;
+#      keepalive time 80;      # defaults to hold time / 3
+#      start delay time 5;     # How long do we wait before initial connect
+#      error wait time 60, 300;# Minimum and maximum time we wait after an error (when consecutive
+#                              # errors occur, we increase the delay exponentially ...
+#      error forget time 300;  # ... until this timeout expires)
+#      disable after error;    # Disable the protocol automatically when an error occurs
+#      next hop self;          # Disable next hop processing and always advertise our local address as nexthop
+#      source address 62.168.0.14;     # What local address we use for the TCP connection
+#      password "secret"       # Password used for MD5 authentication
+#      rr client;              # I am a route reflector and the neighor is my client
+#      rr cluster id 1.0.0.1   # Use this value for cluster id instead of my router id 
+#      };
+#}
diff --git a/package/bird/files/bird4.init b/package/bird/files/bird4.init
new file mode 100644 (file)
index 0000000..8ac5e75
--- /dev/null
@@ -0,0 +1,21 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2010-2011 OpenWrt.org
+
+START=50
+
+SERVICE_DAEMONIZE=1
+SERVICE_WRITE_PID=1
+
+start() {
+       service_start /usr/sbin/bird4 -d
+#      ( SERVICE_MATCH_NAME=1 service_start /usr/sbin/bird4loop )
+}
+
+stop() {
+#      ( SERVICE_MATCH_NAME=1 service_stop /usr/sbin/bird4loop )
+       service_stop /usr/sbin/bird4
+}
+
+reload() {
+       service_reload /usr/sbin/bird4
+}
diff --git a/package/bird/files/bird4loop b/package/bird/files/bird4loop
new file mode 100644 (file)
index 0000000..074a9a2
--- /dev/null
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+BIRD=/usr/sbin/bird4
+
+$BIRD -p || return 1
+
+. /lib/functions.sh
+. /lib/functions/service.sh
+
+SERVICE_DAEMONIZE=1
+SERVICE_WRITE_PID=1
+
+sig_handler() {
+       running=0
+       service_stop $BIRD
+}
+
+running=1
+trap sig_handler INT
+trap sig_handler TERM
+while [ $running -gt 0 ]; do
+       service_check $BIRD || service_start $BIRD -d "$@"
+       sleep 3
+done
diff --git a/package/bird/files/bird6.conf b/package/bird/files/bird6.conf
new file mode 100644 (file)
index 0000000..8616a0a
--- /dev/null
@@ -0,0 +1,121 @@
+
+# THIS CONFIG FILE IS NOT A COMPLETE DOCUMENTATION
+# PLEASE LOOK IN THE BIRD DOCUMENTATION FOR MORE INFO
+
+# However, most of options used here are just for example
+# and will be removed in real-life configs.
+
+log syslog all;
+
+# Override router ID
+#router id 192.168.0.1;
+
+# Turn on global debugging of all protocols
+#debug protocols all;
+
+
+# Define a route filter...
+# filter test_filter {
+#      if net ~ 10.0.0.0/16 then accept;
+#      else reject;
+# }
+
+# The direct protocol automatically generates device routes to all network
+# interfaces. Can exist in as many instances as you wish if you want to
+# populate multiple routing tables with device routes. Because device routes
+# are handled by Linux kernel, this protocol is  usually not needed.
+# protocol direct {
+#      interface "*";  # Restrict network interfaces it works with
+# }
+
+# This pseudo-protocol performs synchronization between BIRD's routing
+# tables and the kernel. You can run multiple instances of the kernel
+# protocol and synchronize different kernel tables with different BIRD tables.
+protocol kernel {
+#      learn;                  # Learn all alien routes from the kernel
+#      persist;                # Don't remove routes on bird shutdown
+       scan time 20;           # Scan kernel routing table every 20 seconds
+#      import none;            # Default is import all
+#      export all;             # Default is export none
+}
+
+# This pseudo-protocol watches all interface up/down events.
+protocol device {
+       scan time 10;           # Scan interfaces every 10 seconds
+}
+
+# Static routes (again, there can be multiple instances, so that you
+# can disable/enable various groups of static routes on the fly).
+protocol static {
+#      export all;             # Default is export none
+#      route 0.0.0.0/0 via 62.168.0.13;
+#      route 10.0.0.0/8 reject;
+#      route 192.168.0.0/16 reject;
+}
+
+
+#protocol rip {
+#      disabled;
+#      import all;
+#      export all;
+#      export filter test_filter;
+
+#      port 1520;
+#      period 7;
+#      infinity 16;
+#      garbage time 60;
+#      interface "*" { mode broadcast; };
+#      honor neighbor;
+#      honor always;
+#      honor never;
+#      authentication none;
+#}
+
+
+#protocol ospf {
+#      disabled;
+#      import all;
+#      export all;
+#      export where source = RTS_STATIC;
+
+#      area 0 {
+#              interface "eth*" {
+#                      cost 10;
+#                      hello 3;
+#                      retransmit 2;
+#                      wait 5;
+#                      dead 20;
+#                      type broadcast;
+#                      authentication simple;
+#                      password "pass";
+#              };
+#      };
+#}
+
+
+#protocol bgp {
+#      disabled;
+#      import all;
+#      export all;
+#      export where source = RTS_STATIC;
+
+#      local as 65000;
+#      neighbor 192.168.1.1 as 65001;
+#      multihop 20 via 192.168.2.1;
+
+#      hold time 240;
+#      startup hold time 240;
+#      connect retry time 120;
+#      keepalive time 80;      # defaults to hold time / 3
+#      start delay time 5;     # How long do we wait before initial connect
+#      error wait time 60, 300;# Minimum and maximum time we wait after an error (when consecutive
+#                              # errors occur, we increase the delay exponentially ...
+#      error forget time 300;  # ... until this timeout expires)
+#      disable after error;    # Disable the protocol automatically when an error occurs
+#      next hop self;          # Disable next hop processing and always advertise our local address as nexthop
+#      source address 62.168.0.14;     # What local address we use for the TCP connection
+#      password "secret"       # Password used for MD5 authentication
+#      rr client;              # I am a route reflector and the neighor is my client
+#      rr cluster id 1.0.0.1   # Use this value for cluster id instead of my router id 
+#      };
+#}
diff --git a/package/bird/files/bird6.init b/package/bird/files/bird6.init
new file mode 100644 (file)
index 0000000..2efb4f0
--- /dev/null
@@ -0,0 +1,21 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2010-2011 OpenWrt.org
+
+START=50
+
+SERVICE_DAEMONIZE=1
+SERVICE_WRITE_PID=1
+
+start() {
+       service_start /usr/sbin/bird6 -d
+#      ( SERVICE_MATCH_NAME=1 service_start /usr/sbin/bird6loop )
+}
+
+stop() {
+#      ( SERVICE_MATCH_NAME=1 service_stop /usr/sbin/bird6loop )
+       service_stop /usr/sbin/bird6
+}
+
+reload() {
+       service_reload /usr/sbin/bird6
+}
diff --git a/package/bird/files/bird6loop b/package/bird/files/bird6loop
new file mode 100644 (file)
index 0000000..c01cf2e
--- /dev/null
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+BIRD=/usr/sbin/bird6
+
+$BIRD -p || return 1
+
+. /lib/functions.sh
+. /lib/functions/service.sh
+
+SERVICE_DAEMONIZE=1
+SERVICE_WRITE_PID=1
+
+sig_handler() {
+       running=0
+       service_stop $BIRD
+}
+
+running=1
+trap sig_handler INT
+trap sig_handler TERM
+while [ $running -gt 0 ]; do
+       service_check $BIRD || service_start $BIRD -d "$@"
+       sleep 3
+done
index ac41b64..06d6341 100644 (file)
@@ -20,7 +20,7 @@ PKG_MD5SUM:=6059ac9456de6fb18dc8ee4cd0ec9240
 include $(INCLUDE_DIR)/package.mk
 
 ifeq ($(DUMP),)
-  STAMP_CONFIGURED:=$(strip $(STAMP_CONFIGURED))_$(shell grep '^CONFIG_BUSYBOX_' $(TOPDIR)/.config | md5s)
+  STAMP_CONFIGURED:=$(strip $(STAMP_CONFIGURED))_$(shell $(SH_FUNC) grep '^CONFIG_BUSYBOX_' $(TOPDIR)/.config | md5s)
 endif
 
 init-y :=
index 3beb0d1..acf71c9 100644 (file)
@@ -397,7 +397,7 @@ config BUSYBOX_CONFIG_FEATURE_SHARED_BUSYBOX
 
 config BUSYBOX_CONFIG_LFS
        bool
-       default y
+       default n
        select BUSYBOX_CONFIG_FDISK_SUPPORT_LARGE_DISKS
        help
          If you want to build BusyBox with large file support, then enable
index 19eb663..05872ec 100644 (file)
@@ -8,15 +8,27 @@
 include $(TOPDIR)/rules.mk
 
 PKG_NAME:=dnsmasq
-PKG_VERSION:=2.55
-PKG_RELEASE:=6.1
+PKG_VERSION:=2.76
+PKG_RELEASE:=3
 
-PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
 PKG_SOURCE_URL:=http://thekelleys.org.uk/dnsmasq
-PKG_MD5SUM:=b093d7c6bc7f97ae6fd35d048529232a
+PKG_MD5SUM:=00f5ee66b4e4b7f14538bf62ae3c9461
 
 include $(INCLUDE_DIR)/package.mk
 
+TARGET_CFLAGS += -ffunction-sections -fdata-sections
+TARGET_LDFLAGS += -Wl,--gc-sections
+
+COPTS = -DNO_IPV6 -DNO_DHCP6 -DNO_AUTH -DNO_IPSET -DNO_LARGEFILE -DNO_INOTIFY
+
+MAKE_FLAGS := \
+       $(TARGET_CONFIGURE_OPTS) \
+       CFLAGS="$(TARGET_CFLAGS)" \
+       LDFLAGS="$(TARGET_LDFLAGS)" \
+       COPTS="$(COPTS)" \
+       PREFIX="/usr"
+
 define Package/dnsmasq
   SECTION:=net
   CATEGORY:=Base system
@@ -35,6 +47,7 @@ endef
 
 define Build/Compile
        $(MAKE) -C $(PKG_BUILD_DIR) \
+               $(MAKE_FLAGS) \
                $(TARGET_CONFIGURE_OPTS) \
                CFLAGS="$(TARGET_CFLAGS)" \
                BINDIR="/usr/sbin" MANDIR="/usr/man" \
diff --git a/package/dnsmasq/patches/100-fix-dhcp-no-address-warning.patch b/package/dnsmasq/patches/100-fix-dhcp-no-address-warning.patch
new file mode 100644 (file)
index 0000000..5fc62ff
--- /dev/null
@@ -0,0 +1,47 @@
+--- a/src/dhcp.c
++++ b/src/dhcp.c
+@@ -147,7 +147,7 @@ void dhcp_packet(time_t now, int pxe_fd)
+   ssize_t sz; 
+   int iface_index = 0, unicast_dest = 0, is_inform = 0;
+   int rcvd_iface_index;
+-  struct in_addr iface_addr;
++  struct in_addr iface_addr, *addrp = NULL;
+   struct iface_param parm;
+ #ifdef HAVE_LINUX_NETWORK
+   struct arpreq arp_req;
+@@ -277,11 +277,9 @@ void dhcp_packet(time_t now, int pxe_fd)
+     {
+       ifr.ifr_addr.sa_family = AF_INET;
+       if (ioctl(daemon->dhcpfd, SIOCGIFADDR, &ifr) != -1 )
+-      iface_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
+-      else
+       {
+-        my_syslog(MS_DHCP | LOG_WARNING, _("DHCP packet received on %s which has no address"), ifr.ifr_name);
+-        return;
++        addrp = &iface_addr;
++        iface_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
+       }
+       
+       for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
+@@ -300,7 +298,7 @@ void dhcp_packet(time_t now, int pxe_fd)
+       parm.relay_local.s_addr = 0;
+       parm.ind = iface_index;
+       
+-      if (!iface_check(AF_INET, (struct all_addr *)&iface_addr, ifr.ifr_name, NULL))
++      if (!iface_check(AF_INET, (struct all_addr *)addrp, ifr.ifr_name, NULL))
+       {
+         /* If we failed to match the primary address of the interface, see if we've got a --listen-address
+            for a secondary */
+@@ -320,6 +318,12 @@ void dhcp_packet(time_t now, int pxe_fd)
+         complete_context(match.addr, iface_index, NULL, match.netmask, match.broadcast, &parm);
+       }    
+       
++      if (!addrp)
++        {
++          my_syslog(MS_DHCP | LOG_WARNING, _("DHCP packet received on %s which has no address"), ifr.ifr_name);
++          return;
++        }
++
+       if (!iface_enumerate(AF_INET, &parm, complete_context))
+       return;
diff --git a/package/dnsmasq/patches/101-ipv6.patch b/package/dnsmasq/patches/101-ipv6.patch
deleted file mode 100644 (file)
index 2876d3e..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
---- a/src/config.h
-+++ b/src/config.h
-@@ -269,8 +269,9 @@ NOTES:
- /* We assume that systems which don't have IPv6
-    headers don't have ntop and pton either */
--#if defined(INET6_ADDRSTRLEN) && defined(IPV6_V6ONLY) && !defined(NO_IPV6)
-+#if defined(INET6_ADDRSTRLEN) && !defined(NO_IPV6)
- #  define HAVE_IPV6
-+#  define IPV6_V6ONLY 26
- #  define ADDRSTRLEN INET6_ADDRSTRLEN
- #  if defined(SOL_IPV6)
- #    define IPV6_LEVEL SOL_IPV6
diff --git a/package/dnsmasq/patches/110-ipset-remove-old-kernel-support.patch b/package/dnsmasq/patches/110-ipset-remove-old-kernel-support.patch
new file mode 100644 (file)
index 0000000..61b09d5
--- /dev/null
@@ -0,0 +1,110 @@
+--- a/src/ipset.c
++++ b/src/ipset.c
+@@ -22,7 +22,6 @@
+ #include <errno.h>
+ #include <sys/types.h>
+ #include <sys/socket.h>
+-#include <sys/utsname.h>
+ #include <arpa/inet.h>
+ #include <linux/version.h>
+ #include <linux/netlink.h>
+@@ -72,7 +71,7 @@ struct my_nfgenmsg {
+ #define NL_ALIGN(len) (((len)+3) & ~(3))
+ static const struct sockaddr_nl snl = { .nl_family = AF_NETLINK };
+-static int ipset_sock, old_kernel;
++static int ipset_sock;
+ static char *buffer;
+ static inline void add_attr(struct nlmsghdr *nlh, uint16_t type, size_t len, const void *data)
+@@ -87,25 +86,7 @@ static inline void add_attr(struct nlmsg
+ void ipset_init(void)
+ {
+-  struct utsname utsname;
+-  int version;
+-  char *split;
+-  
+-  if (uname(&utsname) < 0)
+-    die(_("failed to find kernel version: %s"), NULL, EC_MISC);
+-  
+-  split = strtok(utsname.release, ".");
+-  version = (split ? atoi(split) : 0);
+-  split = strtok(NULL, ".");
+-  version = version * 256 + (split ? atoi(split) : 0);
+-  split = strtok(NULL, ".");
+-  version = version * 256 + (split ? atoi(split) : 0);
+-  old_kernel = (version < KERNEL_VERSION(2,6,32));
+-  
+-  if (old_kernel && (ipset_sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) != -1)
+-    return;
+-  
+-  if (!old_kernel && 
++  if ( 
+       (buffer = safe_malloc(BUFF_SZ)) &&
+       (ipset_sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_NETFILTER)) != -1 &&
+       (bind(ipset_sock, (struct sockaddr *)&snl, sizeof(snl)) != -1))
+@@ -168,62 +149,16 @@ static int new_add_to_ipset(const char *
+ }
+-static int old_add_to_ipset(const char *setname, const struct all_addr *ipaddr, int remove)
+-{
+-  socklen_t size;
+-  struct ip_set_req_adt_get {
+-    unsigned op;
+-    unsigned version;
+-    union {
+-      char name[IPSET_MAXNAMELEN];
+-      uint16_t index;
+-    } set;
+-    char typename[IPSET_MAXNAMELEN];
+-  } req_adt_get;
+-  struct ip_set_req_adt {
+-    unsigned op;
+-    uint16_t index;
+-    uint32_t ip;
+-  } req_adt;
+-  
+-  if (strlen(setname) >= sizeof(req_adt_get.set.name)) 
+-    {
+-      errno = ENAMETOOLONG;
+-      return -1;
+-    }
+-  
+-  req_adt_get.op = 0x10;
+-  req_adt_get.version = 3;
+-  strcpy(req_adt_get.set.name, setname);
+-  size = sizeof(req_adt_get);
+-  if (getsockopt(ipset_sock, SOL_IP, 83, &req_adt_get, &size) < 0)
+-    return -1;
+-  req_adt.op = remove ? 0x102 : 0x101;
+-  req_adt.index = req_adt_get.set.index;
+-  req_adt.ip = ntohl(ipaddr->addr.addr4.s_addr);
+-  if (setsockopt(ipset_sock, SOL_IP, 83, &req_adt, sizeof(req_adt)) < 0)
+-    return -1;
+-  
+-  return 0;
+-}
+-
+-
+-
+ int add_to_ipset(const char *setname, const struct all_addr *ipaddr, int flags, int remove)
+ {
+   int af = AF_INET;
+ #ifdef HAVE_IPV6
+   if (flags & F_IPV6)
+-    {
+       af = AF_INET6;
+-      /* old method only supports IPv4 */
+-      if (old_kernel)
+-      return -1;
+-    }
+ #endif
+   
+-  return old_kernel ? old_add_to_ipset(setname, ipaddr, remove) : new_add_to_ipset(setname, ipaddr, af, remove);
++  return new_add_to_ipset(setname, ipaddr, af, remove);
+ }
+ #endif
diff --git a/package/dnsmasq/patches/210-dnssec-improve-timestamp-heuristic.patch b/package/dnsmasq/patches/210-dnssec-improve-timestamp-heuristic.patch
new file mode 100644 (file)
index 0000000..ca5a806
--- /dev/null
@@ -0,0 +1,47 @@
+From 79e60e145f8a595bca5a784c00b437216d51de68 Mon Sep 17 00:00:00 2001
+From: Steven Barth <steven@midlink.org>
+Date: Mon, 13 Apr 2015 09:45:20 +0200
+Subject: [PATCH] dnssec: improve timestamp heuristic
+
+Signed-off-by: Steven Barth <steven@midlink.org>
+---
+ src/dnssec.c | 15 +++++++++++----
+ 1 file changed, 11 insertions(+), 4 deletions(-)
+
+--- a/src/dnssec.c
++++ b/src/dnssec.c
+@@ -462,17 +462,24 @@ static time_t timestamp_time;
+ int setup_timestamp(void)
+ {
+   struct stat statbuf;
++  time_t now;
++  time_t base = 1420070400; /* 1-1-2015 */
+   
+   daemon->back_to_the_future = 0;
+   
+   if (!daemon->timestamp_file)
+     return 0;
++
++  now = time(NULL);
++
++  if (!stat("/proc/self/exe", &statbuf) && difftime(statbuf.st_mtime, base) > 0)
++    base = statbuf.st_mtime;
+   
+   if (stat(daemon->timestamp_file, &statbuf) != -1)
+     {
+       timestamp_time = statbuf.st_mtime;
+     check_and_exit:
+-      if (difftime(timestamp_time, time(0)) <=  0)
++      if (difftime(now, base) >= 0 && difftime(timestamp_time, now) <= 0)
+       {
+         /* time already OK, update timestamp, and do key checking from the start. */
+         if (utime(daemon->timestamp_file, NULL) == -1)
+@@ -493,7 +500,7 @@ int setup_timestamp(void)
+         close(fd);
+         
+-        timestamp_time = timbuf.actime = timbuf.modtime = 1420070400; /* 1-1-2015 */
++        timestamp_time = timbuf.actime = timbuf.modtime = base;
+         if (utime(daemon->timestamp_file, &timbuf) == 0)
+           goto check_and_exit;
+       }
diff --git a/package/dnsmasq/patches/230-fix-poll-h-include-warning-on-musl.patch b/package/dnsmasq/patches/230-fix-poll-h-include-warning-on-musl.patch
new file mode 100644 (file)
index 0000000..19300f7
--- /dev/null
@@ -0,0 +1,18 @@
+dnsmasq: fix warning with poll.h include on musl
+
+Warning is:
+  #warning redirecting incorrect #include <sys/poll.h> to <poll.h>
+
+Signed-off-by: Kevin Darbyshire-Bryant <kevin@darbyshire-bryant.me.uk>
+
+--- a/src/dnsmasq.h
++++ b/src/dnsmasq.h
+@@ -82,7 +82,7 @@ typedef unsigned long long u64;
+ #if defined(HAVE_SOLARIS_NETWORK)
+ #  include <sys/sockio.h>
+ #endif
+-#include <sys/poll.h>
++#include <poll.h>
+ #include <sys/wait.h>
+ #include <sys/time.h>
+ #include <sys/un.h>
index 332ce30..1eb3b4a 100644 (file)
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2006-2009 OpenWrt.org
+# Copyright (C) 2006-2012 OpenWrt.org
 #
 # This is free software, licensed under the GNU General Public License v2.
 # See /LICENSE for more information.
@@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
 include $(INCLUDE_DIR)/kernel.mk
 
 PKG_NAME:=mtd
-PKG_RELEASE:=13
+PKG_RELEASE:=18.1
 
 PKG_BUILD_DIR := $(KERNEL_BUILD_DIR)/$(PKG_NAME)
 STAMP_PREPARED := $(STAMP_PREPARED)_$(call confvar,CONFIG_MTD_REDBOOT_PARTS)
@@ -23,7 +23,7 @@ define Package/mtd
 endef
 
 define Package/mtd/description
- This package contains an utility useful to upgrade from other firmware or 
+ This package contains an utility useful to upgrade from other firmware or
  older OpenWrt releases.
 endef
 
@@ -35,7 +35,7 @@ endef
 target=$(firstword $(subst -, ,$(BOARD)))
 
 MAKE_FLAGS += TARGET="$(target)"
-TARGET_CFLAGS += -Dtarget_$(target)=1 -Wall
+TARGET_CFLAGS := -I$(LINUX_DIR)/include $(TARGET_CFLAGS) -Dtarget_$(target)=1 -Wall
 
 ifdef CONFIG_MTD_REDBOOT_PARTS
   MAKE_FLAGS += FIS_SUPPORT=1
index bb509be..4e6aee8 100644 (file)
@@ -2,8 +2,12 @@ CC = gcc
 CFLAGS += -Wall
 
 obj = mtd.o jffs2.o crc32.o
+obj.seama = seama.o md5.o
+obj.ar71xx = trx.o
 obj.brcm = trx.o
 obj.brcm47xx = $(obj.brcm)
+obj.brcm63xx = imagetag.o
+obj.ramips = $(obj.seama)
 
 ifdef FIS_SUPPORT
   obj += fis.o
@@ -11,4 +15,4 @@ endif
 
 mtd: $(obj) $(obj.$(TARGET))
 clean:
-       rm -f *.o jffs2 
+       rm -f *.o jffs2
diff --git a/package/mtd/src/bcm_tag.h b/package/mtd/src/bcm_tag.h
new file mode 120000 (symlink)
index 0000000..2e977a2
--- /dev/null
@@ -0,0 +1 @@
+../../../target/linux/brcm63xx/files/arch/mips/include/asm/mach-bcm63xx/bcm_tag.h
\ No newline at end of file
index 559ca95..f825f59 100644 (file)
@@ -143,6 +143,8 @@ fis_remap(struct fis_part *old, int n_old, struct fis_part *new, int n_new)
        struct fis_image_desc *redboot = NULL;
        struct fis_image_desc *first = NULL;
        struct fis_image_desc *last = NULL;
+       struct fis_image_desc *first_fb = NULL;
+       struct fis_image_desc *last_fb = NULL;
        struct fis_image_desc *desc;
        struct fis_part *part;
        uint32_t offset = 0, size = 0;
@@ -184,13 +186,21 @@ fis_remap(struct fis_part *old, int n_old, struct fis_part *new, int n_new)
        }
        desc--;
 
+       first_fb = first;
+       last_fb = last;
+
+       if (first_fb->hdr.flash_base > last_fb->hdr.flash_base) {
+               first_fb = last;
+               last_fb = first;
+       }
+
        /* determine size of available space */
        desc = (struct fis_image_desc *) start;
        while ((char *) desc < end) {
                if (!desc->hdr.name[0] || (desc->hdr.name[0] == 0xff))
                        break;
 
-               if (desc->hdr.flash_base > last->hdr.flash_base &&
+               if (desc->hdr.flash_base > last_fb->hdr.flash_base &&
                    desc->hdr.flash_base < offset)
                        offset = desc->hdr.flash_base;
 
@@ -198,7 +208,7 @@ fis_remap(struct fis_part *old, int n_old, struct fis_part *new, int n_new)
        }
        desc--;
 
-       size = offset - first->hdr.flash_base;
+       size = offset - first_fb->hdr.flash_base;
 
 #ifdef notyet
        desc = first - 1;
@@ -214,7 +224,7 @@ fis_remap(struct fis_part *old, int n_old, struct fis_part *new, int n_new)
 
        last++;
        desc = first + n_new;
-       offset = first->hdr.flash_base;
+       offset = first_fb->hdr.flash_base;
 
        if (desc != last) {
                if (desc > last)
diff --git a/package/mtd/src/imagetag.c b/package/mtd/src/imagetag.c
new file mode 100644 (file)
index 0000000..a4ce86d
--- /dev/null
@@ -0,0 +1,315 @@
+/*
+ * imagetag.c
+ *
+ * Copyright (C) 2005 Mike Baker
+ * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
+ * Copyrigth (C) 2010 Daniel Dickinson <openwrt@cshore.neomailbox.net>
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <errno.h>
+
+#include <sys/ioctl.h>
+#include <mtd/mtd-user.h>
+#include "mtd.h"
+#include "crc32.h"
+#include "bcm_tag.h"
+
+ssize_t pread(int fd, void *buf, size_t count, off_t offset);
+ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset);
+
+#define CRC_START 0xFFFFFFFF
+
+static uint32_t strntoul(char *str, char **endptr, int base, size_t len) {
+  char *newstr;
+  uint32_t res = 0;
+
+  newstr = calloc(len + 1, sizeof(char));
+  if (newstr) {
+       strncpy(newstr, str, len); 
+       res = strtoul(newstr, endptr, base);
+       free(newstr);
+  }
+  return res;
+}
+
+uint32_t compute_crc32(uint32_t crc, off_t start, size_t compute_len, int fd)
+{
+       uint8_t readbuf[1024];
+       ssize_t res;
+       off_t offset = start;
+
+       /* Read a buffer's worth of bytes  */
+       while (fd && (compute_len >= sizeof(readbuf))) {
+               res = pread(fd, readbuf, sizeof(readbuf), offset);
+               crc = crc32(crc, readbuf, res);
+               compute_len = compute_len - res;
+               offset += res;
+       }
+
+       /* Less than buffer-size bytes remains, read compute_len bytes */
+       if (fd && (compute_len > 0)) {
+         res = pread(fd, readbuf, compute_len, offset);
+         crc = crc32(crc, readbuf, res);
+       }
+
+       return crc;
+}
+
+int
+trx_fixup(int fd, const char *name)
+{
+       struct mtd_info_user mtdInfo;
+       unsigned long len;
+       void *ptr, *scan;
+       int bfd;
+       struct bcm_tag *tag;
+       ssize_t res;
+       uint32_t cfelen, imagelen, imagestart, rootfslen;
+       uint32_t imagecrc, rootfscrc, headercrc;
+       uint32_t offset = 0;
+       cfelen = imagelen = imagestart = imagecrc = rootfscrc = headercrc = rootfslen = 0;
+
+
+       if (ioctl(fd, MEMGETINFO, &mtdInfo) < 0) {
+               fprintf(stderr, "Failed to get mtd info\n");
+               goto err;
+       }
+
+       len = mtdInfo.size;
+       if (mtdInfo.size <= 0) {
+               fprintf(stderr, "Invalid MTD device size\n");
+               goto err;
+       }
+
+       bfd = mtd_open(name, true);
+       ptr = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, bfd, 0);
+       if (!ptr || (ptr == (void *) -1)) {
+               perror("mmap");
+               goto err1;
+       }
+
+       tag = (struct bcm_tag *) (ptr);
+
+       cfelen = strntoul(&tag->cfeLength[0], NULL, 10, IMAGE_LEN);
+       if (cfelen) {
+         fprintf(stderr, "Non-zero CFE length.  This is currently unsupported.\n");
+         exit(1);
+       }
+
+       headercrc = compute_crc32(CRC_START, offset, offsetof(struct bcm_tag, headerCRC), fd);
+       if (headercrc != *(uint32_t *)(&tag->headerCRC[0])) {
+               fprintf(stderr, "Tag verify failed.  This may not be a valid image.\n");
+               exit(1);
+       }
+
+       sprintf(&tag->flashRootLength[0], "%lu", 0);
+       strncpy(&tag->totalLength[0], &tag->kernelLength[0], IMAGE_LEN);
+
+       imagestart = sizeof(tag);
+       memcpy(&tag->imageCRC[0], &tag->kernelCRC[0], CRC_LEN);
+       memcpy(&tag->fskernelCRC[0], &tag->kernelCRC[0], CRC_LEN);
+       rootfscrc = CRC_START;
+       memcpy(&tag->rootfsCRC[0], &rootfscrc, sizeof(uint32_t));
+       headercrc = crc32(CRC_START, tag, offsetof(struct bcm_tag, headerCRC));
+       memcpy(&tag->headerCRC[0], &headercrc, sizeof(uint32_t));
+
+       msync(ptr, sizeof(struct bcm_tag), MS_SYNC|MS_INVALIDATE);
+       munmap(ptr, len);
+       close(bfd);
+       return 0;
+
+err1:
+       close(bfd);
+err:
+       fprintf(stderr, "Error fixing up imagetag header\n");
+       return -1;
+}
+
+
+int
+trx_check(int imagefd, const char *mtd, char *buf, int *len)
+{
+    struct bcm_tag *tag = (const struct bcm_tag *) buf;
+       int fd;
+       uint32_t headerCRC;
+       uint32_t imageLen;
+
+       if (strcmp(mtd, "linux") != 0)
+               return 1;
+
+       *len = read(imagefd, buf, sizeof(struct bcm_tag));
+       if (*len < sizeof(struct bcm_tag)) {
+               fprintf(stdout, "Could not get image header, file too small (%d bytes)\n", *len);
+               return 0;
+       }
+       headerCRC = crc32buf(buf, offsetof(struct bcm_tag, headerCRC));
+       if (*(uint32_t *)(&tag->headerCRC[0]) != headerCRC) {
+  
+         if (quiet < 2) {
+               fprintf(stderr, "Bad header CRC got %08lx, calculated %08lx\n",
+                               *(uint32_t *)(&tag->headerCRC[0]), headerCRC);
+               fprintf(stderr, "This is not the correct file format; refusing to flash.\n"
+                               "Please specify the correct file or use -f to force.\n");
+         }
+         return 0;
+       }
+
+       /* check if image fits to mtd device */
+       fd = mtd_check_open(mtd);
+       if(fd < 0) {
+               fprintf(stderr, "Could not open mtd device: %s\n", mtd);
+               exit(1);
+       }
+
+       imageLen = strntoul(&tag->totalLength[0], NULL, 10, IMAGE_LEN);
+       
+       if(mtdsize < imageLen) {
+               fprintf(stderr, "Image too big for partition: %s\n", mtd);
+               close(fd);
+               return 0;
+       }
+
+       close(fd);
+       return 1;
+}
+
+int
+mtd_fixtrx(const char *mtd, size_t offset)
+{
+       int fd;
+       struct bcm_tag *tag;
+       char *buf;
+       ssize_t res;
+       size_t block_offset;
+       uint32_t cfelen, imagelen, imagestart, rootfslen;
+       uint32_t imagecrc, rootfscrc, headercrc;
+       cfelen = imagelen = imagestart = imagecrc = rootfscrc = headercrc = rootfslen = 0;
+
+       if (quiet < 2)
+               fprintf(stderr, "Trying to fix trx header in %s at 0x%x...\n", mtd, offset);
+
+       block_offset = offset & ~(erasesize - 1);
+       offset -= block_offset;
+
+       fd = mtd_check_open(mtd);
+       if(fd < 0) {
+               fprintf(stderr, "Could not open mtd device: %s\n", mtd);
+               exit(1);
+       }
+
+       if (block_offset + erasesize > mtdsize) {
+               fprintf(stderr, "Offset too large, device size 0x%x\n", mtdsize);
+               exit(1);
+       }
+
+       buf = malloc(erasesize);
+       if (!buf) {
+               perror("malloc");
+               exit(1);
+       }
+
+       res = pread(fd, buf, erasesize, block_offset);
+       if (res != erasesize) {
+               perror("pread");
+               exit(1);
+       }
+
+       tag = (struct bcm_tag *) (buf + offset);
+
+       cfelen = strntoul(&tag->cfeLength[0], NULL, 10, IMAGE_LEN);
+       if (cfelen) {
+         fprintf(stderr, "Non-zero CFE length.  This is currently unsupported.\n");
+         exit(1);
+       }
+
+       if (quiet < 2) {
+         fprintf(stderr, "Verifying we actually have an imagetag.\n");
+       }
+
+       headercrc = compute_crc32(CRC_START, offset, offsetof(struct bcm_tag, headerCRC), fd);
+       if (headercrc != *(uint32_t *)(&tag->headerCRC[0])) {
+               fprintf(stderr, "Tag verify failed.  This may not be a valid image.\n");
+               exit(1);
+       }
+
+       if (quiet < 2) {
+         fprintf(stderr, "Checking current fixed status.\n");
+       }
+
+       rootfslen = strntoul(&tag->flashRootLength[0], NULL, 10, IMAGE_LEN);
+       if (rootfslen == 0) {
+         if (quiet < 2) 
+               fprintf(stderr, "Header already fixed, exiting\n");
+         close(fd);
+         return 0;
+       }
+
+       if (quiet < 2) {
+         fprintf(stderr, "Setting root length to 0.\n");
+       }
+
+       sprintf(&tag->flashRootLength[0], "%lu", 0);
+       strncpy(&tag->totalLength[0], &tag->kernelLength[0], IMAGE_LEN);
+
+       if (quiet < 2) {
+         fprintf(stderr, "Recalculating CRCs.\n");
+       }
+
+       imagestart = sizeof(tag);
+       memcpy(&tag->imageCRC[0], &tag->kernelCRC[0], CRC_LEN);
+       memcpy(&tag->fskernelCRC[0], &tag->kernelCRC[0], CRC_LEN);
+       rootfscrc = CRC_START;
+       memcpy(&tag->rootfsCRC[0], &rootfscrc, sizeof(uint32_t));
+       headercrc = crc32(CRC_START, tag, offsetof(struct bcm_tag, headerCRC));
+       memcpy(&tag->headerCRC[0], &headercrc, sizeof(uint32_t));
+
+       if (quiet < 2) {
+         fprintf(stderr, "Erasing imagetag block\n");
+       }
+
+       if (mtd_erase_block(fd, block_offset)) {
+               fprintf(stderr, "Can't erase block at 0x%x (%s)\n", block_offset, strerror(errno));
+               exit(1);
+       }
+
+       if (quiet < 2) {
+         fprintf(stderr, "New image crc32: 0x%x, rewriting block\n", 
+                         *(uint32_t *)(&tag->imageCRC[0]));
+         fprintf(stderr, "New header crc32: 0x%x, rewriting block\n", headercrc);  
+       }
+
+       if (pwrite(fd, buf, erasesize, block_offset) != erasesize) {
+               fprintf(stderr, "Error writing block (%s)\n", strerror(errno));
+               exit(1);
+       }
+
+       if (quiet < 2)
+               fprintf(stderr, "Done.\n");
+
+       close (fd);
+       sync();
+       return 0;
+
+}
index 49a7d56..2a83bd4 100644 (file)
@@ -244,10 +244,7 @@ int mtd_replace_jffs2(const char *mtd, int fd, int ofs, const char *filename)
        pad(erasesize);
        free(buf);
 
-#ifdef target_brcm
-       trx_fixup(outfd, mtd);
-#endif
-       return 0;
+       return (mtdofs - ofs);
 }
 
 void mtd_parse_jffs2data(const char *buf, const char *dir)
@@ -347,9 +344,9 @@ int mtd_write_jffs2(const char *mtd, const char *filename, const char *dir)
 
        err = 0;
 
-#ifdef target_brcm
-       trx_fixup(outfd, mtd);
-#endif
+       if (trx_fixup) {
+         trx_fixup(outfd, mtd);
+       }
 
 done:
        close(outfd);
diff --git a/package/mtd/src/md5.c b/package/mtd/src/md5.c
new file mode 100644 (file)
index 0000000..2039760
--- /dev/null
@@ -0,0 +1,307 @@
+
+
+/*
+ ***********************************************************************
+ ** md5.c -- the source code for MD5 routines                         **
+ ** RSA Data Security, Inc. MD5 Message-Digest Algorithm              **
+ ** Created: 2/17/90 RLR                                              **
+ ** Revised: 1/91 SRD,AJ,BSK,JT Reference C ver., 7/10 constant corr. **
+ ***********************************************************************
+ */
+
+/*
+ ***********************************************************************
+ ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved.  **
+ **                                                                   **
+ ** License to copy and use this software is granted provided that    **
+ ** it is identified as the "RSA Data Security, Inc. MD5 Message-     **
+ ** Digest Algorithm" in all material mentioning or referencing this  **
+ ** software or this function.                                        **
+ **                                                                   **
+ ** License is also granted to make and use derivative works          **
+ ** provided that such works are identified as "derived from the RSA  **
+ ** Data Security, Inc. MD5 Message-Digest Algorithm" in all          **
+ ** material mentioning or referencing the derived work.              **
+ **                                                                   **
+ ** RSA Data Security, Inc. makes no representations concerning       **
+ ** either the merchantability of this software or the suitability    **
+ ** of this software for any particular purpose.  It is provided "as  **
+ ** is" without express or implied warranty of any kind.              **
+ **                                                                   **
+ ** These notices must be retained in any copies of any part of this  **
+ ** documentation and/or software.                                    **
+ ***********************************************************************
+ */
+
+#include <string.h>
+#include "md5.h"
+
+/*
+ ***********************************************************************
+ **  Message-digest routines:                                         **
+ **  To form the message digest for a message M                       **
+ **    (1) Initialize a context buffer mdContext using MD5_Init       **
+ **    (2) Call MD5_Update on mdContext and M                         **
+ **    (3) Call MD5_Final on mdContext                                **
+ **  The message digest is now in mdContext->digest[0...15]           **
+ ***********************************************************************
+ */
+
+/* forward declaration */
+static void Transform ();
+
+static unsigned char PADDING[64] = {
+  0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+/* F, G, H and I are basic MD5 functions */
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define I(x, y, z) ((y) ^ ((x) | (~z)))
+
+/* ROTATE_LEFT rotates x left n bits */
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */
+/* Rotation is separate from addition to prevent recomputation */
+#define FF(a, b, c, d, x, s, ac) \
+  {(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
+   (a) = ROTATE_LEFT ((a), (s)); \
+   (a) += (b); \
+  }
+#define GG(a, b, c, d, x, s, ac) \
+  {(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
+   (a) = ROTATE_LEFT ((a), (s)); \
+   (a) += (b); \
+  }
+#define HH(a, b, c, d, x, s, ac) \
+  {(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
+   (a) = ROTATE_LEFT ((a), (s)); \
+   (a) += (b); \
+  }
+#define II(a, b, c, d, x, s, ac) \
+  {(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
+   (a) = ROTATE_LEFT ((a), (s)); \
+   (a) += (b); \
+  }
+
+#ifdef __STDC__
+#define UL(x)  x##U
+#else
+#define UL(x)  x
+#endif
+
+/* The routine MD5_Init initializes the message-digest context
+   mdContext. All fields are set to zero.
+ */
+void MD5_Init (mdContext)
+MD5_CTX *mdContext;
+{
+  mdContext->i[0] = mdContext->i[1] = (UINT4)0;
+
+  /* Load magic initialization constants.
+   */
+  mdContext->buf[0] = (UINT4)0x67452301;
+  mdContext->buf[1] = (UINT4)0xefcdab89;
+  mdContext->buf[2] = (UINT4)0x98badcfe;
+  mdContext->buf[3] = (UINT4)0x10325476;
+}
+
+/* The routine MD5Update updates the message-digest context to
+   account for the presence of each of the characters inBuf[0..inLen-1]
+   in the message whose digest is being computed.
+ */
+void MD5_Update (mdContext, inBuf, inLen)
+MD5_CTX *mdContext;
+unsigned char *inBuf;
+unsigned int inLen;
+{
+  UINT4 in[16];
+  int mdi;
+  unsigned int i, ii;
+
+  /* compute number of bytes mod 64 */
+  mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
+
+  /* update number of bits */
+  if ((mdContext->i[0] + ((UINT4)inLen << 3)) < mdContext->i[0])
+    mdContext->i[1]++;
+  mdContext->i[0] += ((UINT4)inLen << 3);
+  mdContext->i[1] += ((UINT4)inLen >> 29);
+
+  while (inLen--) {
+    /* add new character to buffer, increment mdi */
+    mdContext->in[mdi++] = *inBuf++;
+
+    /* transform if necessary */
+    if (mdi == 0x40) {
+      for (i = 0, ii = 0; i < 16; i++, ii += 4)
+        in[i] = (((UINT4)mdContext->in[ii+3]) << 24) |
+                (((UINT4)mdContext->in[ii+2]) << 16) |
+                (((UINT4)mdContext->in[ii+1]) << 8) |
+                ((UINT4)mdContext->in[ii]);
+      Transform (mdContext->buf, in);
+      mdi = 0;
+    }
+  }
+}
+
+/* The routine MD5Final terminates the message-digest computation and
+   ends with the desired message digest in mdContext->digest[0...15].
+ */
+void MD5_Final (hash, mdContext)
+unsigned char hash[];
+MD5_CTX *mdContext;
+{
+  UINT4 in[16];
+  int mdi;
+  unsigned int i, ii;
+  unsigned int padLen;
+
+  /* save number of bits */
+  in[14] = mdContext->i[0];
+  in[15] = mdContext->i[1];
+
+  /* compute number of bytes mod 64 */
+  mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
+
+  /* pad out to 56 mod 64 */
+  padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi);
+  MD5_Update (mdContext, PADDING, padLen);
+
+  /* append length in bits and transform */
+  for (i = 0, ii = 0; i < 14; i++, ii += 4)
+    in[i] = (((UINT4)mdContext->in[ii+3]) << 24) |
+            (((UINT4)mdContext->in[ii+2]) << 16) |
+            (((UINT4)mdContext->in[ii+1]) << 8) |
+            ((UINT4)mdContext->in[ii]);
+  Transform (mdContext->buf, in);
+
+  /* store buffer in digest */
+  for (i = 0, ii = 0; i < 4; i++, ii += 4) {
+    mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF);
+    mdContext->digest[ii+1] =
+      (unsigned char)((mdContext->buf[i] >> 8) & 0xFF);
+    mdContext->digest[ii+2] =
+      (unsigned char)((mdContext->buf[i] >> 16) & 0xFF);
+    mdContext->digest[ii+3] =
+      (unsigned char)((mdContext->buf[i] >> 24) & 0xFF);
+  }
+  memcpy(hash, mdContext->digest, 16);
+}
+
+/* Basic MD5 step. Transforms buf based on in.
+ */
+static void Transform (buf, in)
+UINT4 *buf;
+UINT4 *in;
+{
+  UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
+
+  /* Round 1 */
+#define S11 7
+#define S12 12
+#define S13 17
+#define S14 22
+  FF ( a, b, c, d, in[ 0], S11, UL(3614090360)); /* 1 */
+  FF ( d, a, b, c, in[ 1], S12, UL(3905402710)); /* 2 */
+  FF ( c, d, a, b, in[ 2], S13, UL( 606105819)); /* 3 */
+  FF ( b, c, d, a, in[ 3], S14, UL(3250441966)); /* 4 */
+  FF ( a, b, c, d, in[ 4], S11, UL(4118548399)); /* 5 */
+  FF ( d, a, b, c, in[ 5], S12, UL(1200080426)); /* 6 */
+  FF ( c, d, a, b, in[ 6], S13, UL(2821735955)); /* 7 */
+  FF ( b, c, d, a, in[ 7], S14, UL(4249261313)); /* 8 */
+  FF ( a, b, c, d, in[ 8], S11, UL(1770035416)); /* 9 */
+  FF ( d, a, b, c, in[ 9], S12, UL(2336552879)); /* 10 */
+  FF ( c, d, a, b, in[10], S13, UL(4294925233)); /* 11 */
+  FF ( b, c, d, a, in[11], S14, UL(2304563134)); /* 12 */
+  FF ( a, b, c, d, in[12], S11, UL(1804603682)); /* 13 */
+  FF ( d, a, b, c, in[13], S12, UL(4254626195)); /* 14 */
+  FF ( c, d, a, b, in[14], S13, UL(2792965006)); /* 15 */
+  FF ( b, c, d, a, in[15], S14, UL(1236535329)); /* 16 */
+
+  /* Round 2 */
+#define S21 5
+#define S22 9
+#define S23 14
+#define S24 20
+  GG ( a, b, c, d, in[ 1], S21, UL(4129170786)); /* 17 */
+  GG ( d, a, b, c, in[ 6], S22, UL(3225465664)); /* 18 */
+  GG ( c, d, a, b, in[11], S23, UL( 643717713)); /* 19 */
+  GG ( b, c, d, a, in[ 0], S24, UL(3921069994)); /* 20 */
+  GG ( a, b, c, d, in[ 5], S21, UL(3593408605)); /* 21 */
+  GG ( d, a, b, c, in[10], S22, UL(  38016083)); /* 22 */
+  GG ( c, d, a, b, in[15], S23, UL(3634488961)); /* 23 */
+  GG ( b, c, d, a, in[ 4], S24, UL(3889429448)); /* 24 */
+  GG ( a, b, c, d, in[ 9], S21, UL( 568446438)); /* 25 */
+  GG ( d, a, b, c, in[14], S22, UL(3275163606)); /* 26 */
+  GG ( c, d, a, b, in[ 3], S23, UL(4107603335)); /* 27 */
+  GG ( b, c, d, a, in[ 8], S24, UL(1163531501)); /* 28 */
+  GG ( a, b, c, d, in[13], S21, UL(2850285829)); /* 29 */
+  GG ( d, a, b, c, in[ 2], S22, UL(4243563512)); /* 30 */
+  GG ( c, d, a, b, in[ 7], S23, UL(1735328473)); /* 31 */
+  GG ( b, c, d, a, in[12], S24, UL(2368359562)); /* 32 */
+
+  /* Round 3 */
+#define S31 4
+#define S32 11
+#define S33 16
+#define S34 23
+  HH ( a, b, c, d, in[ 5], S31, UL(4294588738)); /* 33 */
+  HH ( d, a, b, c, in[ 8], S32, UL(2272392833)); /* 34 */
+  HH ( c, d, a, b, in[11], S33, UL(1839030562)); /* 35 */
+  HH ( b, c, d, a, in[14], S34, UL(4259657740)); /* 36 */
+  HH ( a, b, c, d, in[ 1], S31, UL(2763975236)); /* 37 */
+  HH ( d, a, b, c, in[ 4], S32, UL(1272893353)); /* 38 */
+  HH ( c, d, a, b, in[ 7], S33, UL(4139469664)); /* 39 */
+  HH ( b, c, d, a, in[10], S34, UL(3200236656)); /* 40 */
+  HH ( a, b, c, d, in[13], S31, UL( 681279174)); /* 41 */
+  HH ( d, a, b, c, in[ 0], S32, UL(3936430074)); /* 42 */
+  HH ( c, d, a, b, in[ 3], S33, UL(3572445317)); /* 43 */
+  HH ( b, c, d, a, in[ 6], S34, UL(  76029189)); /* 44 */
+  HH ( a, b, c, d, in[ 9], S31, UL(3654602809)); /* 45 */
+  HH ( d, a, b, c, in[12], S32, UL(3873151461)); /* 46 */
+  HH ( c, d, a, b, in[15], S33, UL( 530742520)); /* 47 */
+  HH ( b, c, d, a, in[ 2], S34, UL(3299628645)); /* 48 */
+
+  /* Round 4 */
+#define S41 6
+#define S42 10
+#define S43 15
+#define S44 21
+  II ( a, b, c, d, in[ 0], S41, UL(4096336452)); /* 49 */
+  II ( d, a, b, c, in[ 7], S42, UL(1126891415)); /* 50 */
+  II ( c, d, a, b, in[14], S43, UL(2878612391)); /* 51 */
+  II ( b, c, d, a, in[ 5], S44, UL(4237533241)); /* 52 */
+  II ( a, b, c, d, in[12], S41, UL(1700485571)); /* 53 */
+  II ( d, a, b, c, in[ 3], S42, UL(2399980690)); /* 54 */
+  II ( c, d, a, b, in[10], S43, UL(4293915773)); /* 55 */
+  II ( b, c, d, a, in[ 1], S44, UL(2240044497)); /* 56 */
+  II ( a, b, c, d, in[ 8], S41, UL(1873313359)); /* 57 */
+  II ( d, a, b, c, in[15], S42, UL(4264355552)); /* 58 */
+  II ( c, d, a, b, in[ 6], S43, UL(2734768916)); /* 59 */
+  II ( b, c, d, a, in[13], S44, UL(1309151649)); /* 60 */
+  II ( a, b, c, d, in[ 4], S41, UL(4149444226)); /* 61 */
+  II ( d, a, b, c, in[11], S42, UL(3174756917)); /* 62 */
+  II ( c, d, a, b, in[ 2], S43, UL( 718787259)); /* 63 */
+  II ( b, c, d, a, in[ 9], S44, UL(3951481745)); /* 64 */
+
+  buf[0] += a;
+  buf[1] += b;
+  buf[2] += c;
+  buf[3] += d;
+}
+
+/*
+ ***********************************************************************
+ ** End of md5.c                                                      **
+ ******************************** (cut) ********************************
+ */
diff --git a/package/mtd/src/md5.h b/package/mtd/src/md5.h
new file mode 100644 (file)
index 0000000..f7a0c96
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ ***********************************************************************
+ ** md5.h -- header file for implementation of MD5                    **
+ ** RSA Data Security, Inc. MD5 Message-Digest Algorithm              **
+ ** Created: 2/17/90 RLR                                              **
+ ** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version               **
+ ** Revised (for MD5): RLR 4/27/91                                    **
+ **   -- G modified to have y&~z instead of y&z                       **
+ **   -- FF, GG, HH modified to add in last register done             **
+ **   -- Access pattern: round 2 works mod 5, round 3 works mod 3     **
+ **   -- distinct additive constant for each step                     **
+ **   -- round 4 added, working mod 7                                 **
+ ***********************************************************************
+ */
+
+/*
+ ***********************************************************************
+ ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved.  **
+ **                                                                   **
+ ** License to copy and use this software is granted provided that    **
+ ** it is identified as the "RSA Data Security, Inc. MD5 Message-     **
+ ** Digest Algorithm" in all material mentioning or referencing this  **
+ ** software or this function.                                        **
+ **                                                                   **
+ ** License is also granted to make and use derivative works          **
+ ** provided that such works are identified as "derived from the RSA  **
+ ** Data Security, Inc. MD5 Message-Digest Algorithm" in all          **
+ ** material mentioning or referencing the derived work.              **
+ **                                                                   **
+ ** RSA Data Security, Inc. makes no representations concerning       **
+ ** either the merchantability of this software or the suitability    **
+ ** of this software for any particular purpose.  It is provided "as  **
+ ** is" without express or implied warranty of any kind.              **
+ **                                                                   **
+ ** These notices must be retained in any copies of any part of this  **
+ ** documentation and/or software.                                    **
+ ***********************************************************************
+ */
+
+#ifndef __MD5_INCLUDE__
+
+/* typedef a 32-bit type */
+#ifdef _LP64
+typedef unsigned int UINT4;
+typedef int          INT4;
+#else
+typedef unsigned long UINT4;
+typedef long          INT4;
+#endif
+#define _UINT4_T
+
+/* Data structure for MD5 (Message-Digest) computation */
+typedef struct {
+  UINT4 i[2];                   /* number of _bits_ handled mod 2^64 */
+  UINT4 buf[4];                                    /* scratch buffer */
+  unsigned char in[64];                              /* input buffer */
+  unsigned char digest[16];     /* actual digest after MD5Final call */
+} MD5_CTX;
+
+void MD5_Init ();
+void MD5_Update ();
+void MD5_Final ();
+
+#define __MD5_INCLUDE__
+#endif /* __MD5_INCLUDE__ */
diff --git a/package/mtd/src/mtd-api.h b/package/mtd/src/mtd-api.h
deleted file mode 100644 (file)
index 272043d..0000000
+++ /dev/null
@@ -1,304 +0,0 @@
-
-
-#ifndef __MTD_MTD_H__
-#define __MTD_MTD_H__
-
-#ifdef __KERNEL__
-
-#include <linux/config.h>
-#include <linux/version.h>
-#include <linux/types.h>
-#include <linux/mtd/compatmac.h>
-#include <linux/notifier.h>
-#include <linux/module.h>
-#include <linux/uio.h>
-
-#endif /* __KERNEL__ */
-
-struct erase_info_user {
-       u_int32_t start;
-       u_int32_t length;
-};
-
-struct mtd_oob_buf {
-       u_int32_t start;
-       u_int32_t length;
-       unsigned char *ptr;
-};
-
-
-#define MTD_CHAR_MAJOR 90
-#define MTD_BLOCK_MAJOR 31
-#define MAX_MTD_DEVICES 16
-
-
-
-#define MTD_ABSENT             0
-#define MTD_RAM                        1
-#define MTD_ROM                        2
-#define MTD_NORFLASH           3
-#define MTD_NANDFLASH          4
-#define MTD_PEROM              5
-#define MTD_OTHER              14
-#define MTD_UNKNOWN            15
-
-
-
-#define MTD_CLEAR_BITS         1       // Bits can be cleared (flash)
-#define MTD_SET_BITS           2       // Bits can be set
-#define MTD_ERASEABLE          4       // Has an erase function
-#define MTD_WRITEB_WRITEABLE   8       // Direct IO is possible
-#define MTD_VOLATILE           16      // Set for RAMs
-#define MTD_XIP                        32      // eXecute-In-Place possible
-#define MTD_OOB                        64      // Out-of-band data (NAND flash)
-#define MTD_ECC                        128     // Device capable of automatic ECC
-
-// Some common devices / combinations of capabilities
-#define MTD_CAP_ROM            0
-#define MTD_CAP_RAM            (MTD_CLEAR_BITS|MTD_SET_BITS|MTD_WRITEB_WRITEABLE)
-#define MTD_CAP_NORFLASH        (MTD_CLEAR_BITS|MTD_ERASEABLE)
-#define MTD_CAP_NANDFLASH       (MTD_CLEAR_BITS|MTD_ERASEABLE|MTD_OOB)
-#define MTD_WRITEABLE          (MTD_CLEAR_BITS|MTD_SET_BITS)
-
-
-// Types of automatic ECC/Checksum available
-#define MTD_ECC_NONE           0       // No automatic ECC available
-#define MTD_ECC_RS_DiskOnChip  1       // Automatic ECC on DiskOnChip
-#define MTD_ECC_SW             2       // SW ECC for Toshiba & Samsung devices
-
-struct mtd_info_user {
-       u_char type;
-       u_int32_t flags;
-       u_int32_t size;  // Total size of the MTD
-       u_int32_t erasesize;
-       u_int32_t oobblock;  // Size of OOB blocks (e.g. 512)
-       u_int32_t oobsize;   // Amount of OOB data per block (e.g. 16)
-       u_int32_t ecctype;
-       u_int32_t eccsize;
-};
-
-struct region_info_user {
-       u_int32_t offset;               /* At which this region starts, 
-                                        * from the beginning of the MTD */
-       u_int32_t erasesize;            /* For this region */
-       u_int32_t numblocks;            /* Number of blocks in this region */
-       u_int32_t regionindex;
-};
-
-#define MEMGETINFO              _IOR('M', 1, struct mtd_info_user)
-#define MEMERASE                _IOW('M', 2, struct erase_info_user)
-#define MEMWRITEOOB             _IOWR('M', 3, struct mtd_oob_buf)
-#define MEMREADOOB              _IOWR('M', 4, struct mtd_oob_buf)
-#define MEMLOCK                 _IOW('M', 5, struct erase_info_user)
-#define MEMUNLOCK               _IOW('M', 6, struct erase_info_user)
-#define MEMGETREGIONCOUNT      _IOR('M', 7, int)
-#define MEMGETREGIONINFO       _IOWR('M', 8, struct region_info_user)
-#define        MEMREADDATA             _IOWR('M', 9, struct mtd_oob_buf)
-#define        MEMWRITEDATA            _IOWR('M', 10, struct mtd_oob_buf)
-#define MTDREFRESH                             _IO('M', 23)
-
-#ifndef __KERNEL__
-
-typedef struct mtd_info_user mtd_info_t;
-typedef struct erase_info_user erase_info_t;
-typedef struct region_info_user region_info_t;
-
-       /* User-space ioctl definitions */
-
-
-#else /* __KERNEL__ */
-
-
-#define MTD_ERASE_PENDING              0x01
-#define MTD_ERASING            0x02
-#define MTD_ERASE_SUSPEND      0x04
-#define MTD_ERASE_DONE          0x08
-#define MTD_ERASE_FAILED        0x10
-
-struct erase_info {
-       struct mtd_info *mtd;
-       u_int32_t addr;
-       u_int32_t len;
-       u_long time;
-       u_long retries;
-       u_int dev;
-       u_int cell;
-       void (*callback) (struct erase_info *self);
-       u_long priv;
-       u_char state;
-       struct erase_info *next;
-};
-
-struct mtd_erase_region_info {
-       u_int32_t offset;                       /* At which this region starts, from the beginning of the MTD */
-       u_int32_t erasesize;            /* For this region */
-       u_int32_t numblocks;            /* Number of blocks of erasesize in this region */
-};
-
-struct mtd_info {
-       u_char type;
-       u_int32_t flags;
-       u_int32_t size;  // Total size of the MTD
-
-       /* "Major" erase size for the device. Naïve users may take this
-        * to be the only erase size available, or may use the more detailed
-        * information below if they desire
-        */
-       u_int32_t erasesize;
-
-       u_int32_t oobblock;  // Size of OOB blocks (e.g. 512)
-       u_int32_t oobsize;   // Amount of OOB data per block (e.g. 16)
-       u_int32_t ecctype;
-       u_int32_t eccsize;
-
-       // Kernel-only stuff starts here.
-       char *name;
-       int index;
-
-       /* Data for variable erase regions. If numeraseregions is zero,
-        * it means that the whole device has erasesize as given above. 
-        */
-       int numeraseregions;
-       struct mtd_erase_region_info *eraseregions; 
-
-       /* This really shouldn't be here. It can go away in 2.5 */
-       u_int32_t bank_size;
-
-       struct module *module;
-       int (*erase) (struct mtd_info *mtd, struct erase_info *instr);
-
-       /* This stuff for eXecute-In-Place */
-       int (*point) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf);
-
-       /* We probably shouldn't allow XIP if the unpoint isn't a NULL */
-       void (*unpoint) (struct mtd_info *mtd, u_char * addr, loff_t from, size_t len);
-
-
-       int (*read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
-       int (*write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);
-
-       int (*read_ecc) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf, u_char *eccbuf, int oobsel);
-       int (*write_ecc) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf, u_char *eccbuf, int oobsel);
-
-       int (*read_oob) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
-       int (*write_oob) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);
-
-       /* 
-        * Methods to access the protection register area, present in some 
-        * flash devices. The user data is one time programmable but the
-        * factory data is read only. 
-        */
-       int (*read_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
-
-       int (*read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
-
-       /* This function is not yet implemented */
-       int (*write_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
-
-       /* iovec-based read/write methods. We need these especially for NAND flash,
-          with its limited number of write cycles per erase.
-          NB: The 'count' parameter is the number of _vectors_, each of 
-          which contains an (ofs, len) tuple.
-       */
-       int (*readv) (struct mtd_info *mtd, struct iovec *vecs, unsigned long count, loff_t from, size_t *retlen);
-       int (*readv_ecc) (struct mtd_info *mtd, struct iovec *vecs, unsigned long count, loff_t from, 
-               size_t *retlen, u_char *eccbuf, int oobsel);
-       int (*writev) (struct mtd_info *mtd, const struct iovec *vecs, unsigned long count, loff_t to, size_t *retlen);
-       int (*writev_ecc) (struct mtd_info *mtd, const struct iovec *vecs, unsigned long count, loff_t to, 
-               size_t *retlen, u_char *eccbuf, int oobsel);
-
-       /* Sync */
-       void (*sync) (struct mtd_info *mtd);
-
-       /* Chip-supported device locking */
-       int (*lock) (struct mtd_info *mtd, loff_t ofs, size_t len);
-       int (*unlock) (struct mtd_info *mtd, loff_t ofs, size_t len);
-
-       /* Power Management functions */
-       int (*suspend) (struct mtd_info *mtd);
-       void (*resume) (struct mtd_info *mtd);
-
-       struct notifier_block reboot_notifier;
-
-       void *priv;
-};
-
-
-       /* Kernel-side ioctl definitions */
-
-extern int add_mtd_device(struct mtd_info *mtd);
-extern int del_mtd_device (struct mtd_info *mtd);
-
-extern struct mtd_info *__get_mtd_device(struct mtd_info *mtd, int num);
-
-static inline struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num)
-{
-       struct mtd_info *ret;
-       
-       ret = __get_mtd_device(mtd, num);
-
-       if (ret && ret->module && !try_inc_mod_count(ret->module))
-               return NULL;
-
-       return ret;
-}
-
-static inline void put_mtd_device(struct mtd_info *mtd)
-{
-       if (mtd->module)
-              __MOD_DEC_USE_COUNT(mtd->module);
-}
-
-
-struct mtd_notifier {
-       void (*add)(struct mtd_info *mtd);
-       void (*remove)(struct mtd_info *mtd);
-       struct mtd_notifier *next;
-};
-
-
-extern void register_mtd_user (struct mtd_notifier *new);
-extern int unregister_mtd_user (struct mtd_notifier *old);
-
-int default_mtd_writev(struct mtd_info *mtd, const struct iovec *vecs,
-                      unsigned long count, loff_t to, size_t *retlen);
-
-int default_mtd_readv(struct mtd_info *mtd, struct iovec *vecs,
-                     unsigned long count, loff_t from, size_t *retlen);
-
-#ifndef MTDC
-#define MTD_ERASE(mtd, args...) (*(mtd->erase))(mtd, args)
-#define MTD_POINT(mtd, a,b,c,d) (*(mtd->point))(mtd, a,b,c, (u_char **)(d))
-#define MTD_UNPOINT(mtd, arg) (*(mtd->unpoint))(mtd, (u_char *)arg)
-#define MTD_READ(mtd, args...) (*(mtd->read))(mtd, args)
-#define MTD_WRITE(mtd, args...) (*(mtd->write))(mtd, args)
-#define MTD_READV(mtd, args...) (*(mtd->readv))(mtd, args)
-#define MTD_WRITEV(mtd, args...) (*(mtd->writev))(mtd, args)
-#define MTD_READECC(mtd, args...) (*(mtd->read_ecc))(mtd, args)
-#define MTD_WRITEECC(mtd, args...) (*(mtd->write_ecc))(mtd, args)
-#define MTD_READOOB(mtd, args...) (*(mtd->read_oob))(mtd, args)
-#define MTD_WRITEOOB(mtd, args...) (*(mtd->write_oob))(mtd, args)
-#define MTD_SYNC(mtd) do { if (mtd->sync) (*(mtd->sync))(mtd);  } while (0) 
-#endif /* MTDC */
-
-/*
- * Debugging macro and defines
- */
-#define MTD_DEBUG_LEVEL0       (0)     /* Quiet   */
-#define MTD_DEBUG_LEVEL1       (1)     /* Audible */
-#define MTD_DEBUG_LEVEL2       (2)     /* Loud    */
-#define MTD_DEBUG_LEVEL3       (3)     /* Noisy   */
-
-#ifdef CONFIG_MTD_DEBUG
-#define DEBUG(n, args...)                              \
-       do {                                            \
-               if (n <= CONFIG_MTD_DEBUG_VERBOSE)      \
-                       printk(KERN_INFO args);         \
-       } while(0)
-#else /* CONFIG_MTD_DEBUG */
-#define DEBUG(n, args...)
-#endif /* CONFIG_MTD_DEBUG */
-
-#endif /* __KERNEL__ */
-
-#endif /* __MTD_MTD_H__ */
index ff75fcb..9a6e65d 100644 (file)
 #include <sys/stat.h>
 #include <sys/reboot.h>
 #include <linux/reboot.h>
-#include "mtd-api.h"
+#include <mtd/mtd-user.h>
 #include "fis.h"
 #include "mtd.h"
-#include "crc32.h"
 
-#define MAX_ARGS 8
-#define JFFS2_DEFAULT_DIR      "" /* directory name without /, empty means root dir */
-
-#if __BYTE_ORDER == __BIG_ENDIAN
-#define STORE32_LE(X)           ((((X) & 0x000000FF) << 24) | (((X) & 0x0000FF00) << 8) | (((X) & 0x00FF0000) >> 8) | (((X) & 0xFF000000) >> 24))
-#elif __BYTE_ORDER == __LITTLE_ENDIAN
-#define STORE32_LE(X)           (X)
-#else
-#error unkown endianness!
+#ifndef MTDREFRESH
+#define MTDREFRESH     _IO('M', 50)
 #endif
 
-ssize_t pread(int fd, void *buf, size_t count, off_t offset);
-ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset);
-
-#define TRX_MAGIC       0x30524448      /* "HDR0" */
-struct trx_header {
-       uint32_t magic;         /* "HDR0" */
-       uint32_t len;           /* Length of file including header */
-       uint32_t crc32;         /* 32-bit CRC from flag_version to end of file */
-       uint32_t flag_version;  /* 0:15 flags, 16:31 version */
-       uint32_t offsets[3];    /* Offsets of partitions from start of header */
-};
+#define MAX_ARGS 8
+#define JFFS2_DEFAULT_DIR      "" /* directory name without /, empty means root dir */
 
 static char *buf = NULL;
 static char *imagefile = NULL;
 static char *jffs2file = NULL, *jffs2dir = JFFS2_DEFAULT_DIR;
 static int buflen = 0;
 int quiet;
+int no_erase;
 int mtdsize = 0;
 int erasesize = 0;
 
@@ -150,9 +134,10 @@ static int
 image_check(int imagefd, const char *mtd)
 {
        int ret = 1;
-#ifdef target_brcm
-       ret = trx_check(imagefd, mtd, buf, &buflen);
-#endif
+       if (trx_check) {
+         ret = trx_check(imagefd, mtd, buf, &buflen);
+       }
+
        return ret;
 }
 
@@ -264,82 +249,6 @@ mtd_erase(const char *mtd)
 
 }
 
-static int
-mtd_fixtrx(const char *mtd, size_t offset)
-{
-       int fd;
-       struct trx_header *trx;
-       char *buf;
-       ssize_t res;
-       size_t block_offset;
-
-       if (quiet < 2)
-               fprintf(stderr, "Trying to fix trx header in %s at 0x%x...\n", mtd, offset);
-
-       block_offset = offset & ~(erasesize - 1);
-       offset -= block_offset;
-
-       fd = mtd_check_open(mtd);
-       if(fd < 0) {
-               fprintf(stderr, "Could not open mtd device: %s\n", mtd);
-               exit(1);
-       }
-
-       if (block_offset + erasesize > mtdsize) {
-               fprintf(stderr, "Offset too large, device size 0x%x\n", mtdsize);
-               exit(1);
-       }
-
-       buf = malloc(erasesize);
-       if (!buf) {
-               perror("malloc");
-               exit(1);
-       }
-
-       res = pread(fd, buf, erasesize, block_offset);
-       if (res != erasesize) {
-               perror("pread");
-               exit(1);
-       }
-
-       trx = (struct trx_header *) (buf + offset);
-       if (trx->magic != STORE32_LE(0x30524448)) {
-               fprintf(stderr, "No trx magic found\n");
-               exit(1);
-       }
-
-       if (trx->len == STORE32_LE(erasesize - offset)) {
-               if (quiet < 2)
-                       fprintf(stderr, "Header already fixed, exiting\n");
-               close(fd);
-               return 0;
-       }
-
-       trx->len = STORE32_LE(erasesize - offset);
-
-       trx->crc32 = STORE32_LE(crc32buf((char*) &trx->flag_version, erasesize - offset - 3*4));
-       if (mtd_erase_block(fd, block_offset)) {
-               fprintf(stderr, "Can't erease block at 0x%x (%s)\n", block_offset, strerror(errno));
-               exit(1);
-       }
-
-       if (quiet < 2)
-               fprintf(stderr, "New crc32: 0x%x, rewriting block\n", trx->crc32);
-
-       if (pwrite(fd, buf, erasesize, block_offset) != erasesize) {
-               fprintf(stderr, "Error writing block (%s)\n", strerror(errno));
-               exit(1);
-       }
-
-       if (quiet < 2)
-               fprintf(stderr, "Done.\n");
-
-       close (fd);
-       sync();
-       return 0;
-
-}
-
 static int
 mtd_refresh(const char *mtd)
 {
@@ -367,14 +276,26 @@ mtd_refresh(const char *mtd)
        return 0;
 }
 
+static void
+indicate_writing(const char *mtd)
+{
+       if (quiet < 2)
+               fprintf(stderr, "\nWriting from %s to %s ... ", imagefile, mtd);
+
+       if (!quiet)
+               fprintf(stderr, " [ ]");
+}
+
 static int
-mtd_write(int imagefd, const char *mtd, char *fis_layout)
+mtd_write(int imagefd, const char *mtd, char *fis_layout, size_t part_offset)
 {
        char *next = NULL;
        char *str = NULL;
        int fd, result;
        ssize_t r, w, e;
+       ssize_t skip = 0;
        uint32_t offset = 0;
+       int jffs2_replaced = 0;
 
 #ifdef FIS_SUPPORT
        static struct fis_part new_parts[MAX_ARGS];
@@ -451,13 +372,14 @@ resume:
                exit(1);
        }
 
-       if (quiet < 2)
-               fprintf(stderr, "Writing from %s to %s ... ", imagefile, mtd);
+       if (part_offset > 0) {
+               fprintf(stderr, "Seeking on mtd device '%s' to: %u\n", mtd, part_offset);
+               lseek(fd, part_offset, SEEK_SET);
+       }
 
-       w = e = 0;
-       if (!quiet)
-               fprintf(stderr, " [ ]");
+       indicate_writing(mtd);
 
+       w = e = 0;
        for (;;) {
                /* buffer may contain data already (from trx check or last mtd partition write attempt) */
                while (buflen < erasesize) {
@@ -480,6 +402,15 @@ resume:
                if (buflen == 0)
                        break;
 
+               if (skip > 0) {
+                       skip -= buflen;
+                       buflen = 0;
+                       if (skip <= 0)
+                               indicate_writing(mtd);
+
+                       continue;
+               }
+
                if (jffs2file) {
                        if (memcmp(buf, JFFS2_EOF, sizeof(JFFS2_EOF) - 1) == 0) {
                                if (!quiet)
@@ -487,8 +418,18 @@ resume:
                                if (quiet < 2)
                                        fprintf(stderr, "\nAppending jffs2 data from %s to %s...", jffs2file, mtd);
                                /* got an EOF marker - this is the place to add some jffs2 data */
-                               mtd_replace_jffs2(mtd, fd, e, jffs2file);
-                               goto done;
+                               skip = mtd_replace_jffs2(mtd, fd, e, jffs2file);
+                               jffs2_replaced = 1;
+
+                               /* don't add it again */
+                               jffs2file = NULL;
+
+                               w += skip;
+                               e += skip;
+                               skip -= buflen;
+                               buflen = 0;
+                               offset = 0;
+                               continue;
                        }
                        /* no EOF marker, make sure we figure out the last inode number
                         * before appending some data */
@@ -496,31 +437,34 @@ resume:
                }
 
                /* need to erase the next block before writing data to it */
-               while (w + buflen > e) {
-                       if (!quiet)
-                               fprintf(stderr, "\b\b\b[e]");
-
-
-                       if (mtd_erase_block(fd, e) < 0) {
-                               if (next) {
-                                       if (w < e) {
-                                               write(fd, buf + offset, e - w);
-                                               offset = e - w;
+               if(!no_erase)
+               {
+                       while (w + buflen > e) {
+                               if (!quiet)
+                                       fprintf(stderr, "\b\b\b[e]");
+
+
+                               if (mtd_erase_block(fd, e) < 0) {
+                                       if (next) {
+                                               if (w < e) {
+                                                       write(fd, buf + offset, e - w);
+                                                       offset = e - w;
+                                               }
+                                               w = 0;
+                                               e = 0;
+                                               close(fd);
+                                               mtd = next;
+                                               fprintf(stderr, "\b\b\b   \n");
+                                               goto resume;
+                                       } else {
+                                               fprintf(stderr, "Failed to erase block\n");
+                                               exit(1);
                                        }
-                                       w = 0;
-                                       e = 0;
-                                       close(fd);
-                                       mtd = next;
-                                       fprintf(stderr, "\b\b\b   \n");
-                                       goto resume;
-                               } else {
-                                       fprintf(stderr, "Failed to erase block\n");
-                                       exit(1);
                                }
-                       }
 
-                       /* erase the chunk */
-                       e += erasesize;
+                               /* erase the chunk */
+                               e += erasesize;
+                       }
                }
 
                if (!quiet)
@@ -541,6 +485,10 @@ resume:
                offset = 0;
        }
 
+       if (jffs2_replaced && trx_fixup) {
+               trx_fixup(fd, mtd);
+       }
+
        if (!quiet)
                fprintf(stderr, "\b\b\b\b    ");
 
@@ -568,17 +516,31 @@ static void usage(void)
        "        refresh                 refresh mtd partition\n"
        "        erase                   erase all data on device\n"
        "        write <imagefile>|-     write <imagefile> (use - for stdin) to device\n"
-       "        jffs2write <file>       append <file> to the jffs2 partition on the device\n"
-       "        fixtrx                  fix the checksum in a trx header on first boot\n"
+       "        jffs2write <file>       append <file> to the jffs2 partition on the device\n");
+       if (mtd_fixtrx) {
+           fprintf(stderr,
+       "        fixtrx                  fix the checksum in a trx header on first boot\n");
+       }
+       if (mtd_fixseama) {
+           fprintf(stderr,
+       "        fixseama                fix the checksum in a seama header on first boot\n");
+       }
+    fprintf(stderr,
        "Following options are available:\n"
        "        -q                      quiet mode (once: no [w] on writing,\n"
        "                                           twice: no status messages)\n"
+       "        -n                      write without first erasing the blocks\n"
        "        -r                      reboot after successful command\n"
        "        -f                      force write without trx checks\n"
        "        -e <device>             erase <device> before executing the command\n"
        "        -d <name>               directory for jffs2write, defaults to \"tmp\"\n"
        "        -j <name>               integrate <file> into jffs2 data when writing an image\n"
-       "        -o offset               offset of the trx header in the partition (for fixtrx)\n"
+       "        -p                      write beginning at partition offset\n");
+       if (mtd_fixtrx) {
+           fprintf(stderr,
+       "        -o offset               offset of the image header in the partition(for fixtrx)\n");
+    }
+       fprintf(stderr,
 #ifdef FIS_SUPPORT
        "        -F <part>[:<size>[:<entrypoint>]][,<part>...]\n"
        "                                alter the fis partition table to create new partitions replacing\n"
@@ -609,7 +571,7 @@ int main (int argc, char **argv)
        int ch, i, boot, imagefd = 0, force, unlocked;
        char *erase[MAX_ARGS], *device = NULL;
        char *fis_layout = NULL;
-       size_t offset = 0;
+       size_t offset = 0, part_offset = 0;
        enum {
                CMD_ERASE,
                CMD_WRITE,
@@ -617,6 +579,7 @@ int main (int argc, char **argv)
                CMD_REFRESH,
                CMD_JFFS2WRITE,
                CMD_FIXTRX,
+               CMD_FIXSEAMA,
        } cmd = -1;
 
        erase[0] = NULL;
@@ -624,12 +587,13 @@ int main (int argc, char **argv)
        force = 0;
        buflen = 0;
        quiet = 0;
+       no_erase = 0;
 
        while ((ch = getopt(argc, argv,
 #ifdef FIS_SUPPORT
                        "F:"
 #endif
-                       "frqe:d:j:o:")) != -1)
+                       "frnqe:d:j:p:o:")) != -1)
                switch (ch) {
                        case 'f':
                                force = 1;
@@ -637,6 +601,9 @@ int main (int argc, char **argv)
                        case 'r':
                                boot = 1;
                                break;
+                       case 'n':
+                               no_erase = 1;
+                               break;
                        case 'j':
                                jffs2file = optarg;
                                break;
@@ -654,7 +621,19 @@ int main (int argc, char **argv)
                        case 'd':
                                jffs2dir = optarg;
                                break;
+                       case 'p':
+                               errno = 0;
+                               part_offset = strtoul(optarg, 0, 0);
+                               if (errno) {
+                                       fprintf(stderr, "-p: illegal numeric string\n");
+                                       usage();
+                               }
+                               break;
                        case 'o':
+                               if (!mtd_fixtrx) {
+                                       fprintf(stderr, "-o: is not available on this platform\n");
+                                       usage();
+                               }
                                errno = 0;
                                offset = strtoul(optarg, 0, 0);
                                if (errno) {
@@ -686,9 +665,12 @@ int main (int argc, char **argv)
        } else if ((strcmp(argv[0], "erase") == 0) && (argc == 2)) {
                cmd = CMD_ERASE;
                device = argv[1];
-       } else if ((strcmp(argv[0], "fixtrx") == 0) && (argc == 2)) {
+       } else if (((strcmp(argv[0], "fixtrx") == 0) && (argc == 2)) && mtd_fixtrx) {
                cmd = CMD_FIXTRX;
                device = argv[1];
+       } else if (((strcmp(argv[0], "fixseama") == 0) && (argc == 2)) && mtd_fixseama) {
+               cmd = CMD_FIXSEAMA;
+               device = argv[1];
        } else if ((strcmp(argv[0], "write") == 0) && (argc == 3)) {
                cmd = CMD_WRITE;
                device = argv[2];
@@ -751,7 +733,7 @@ int main (int argc, char **argv)
                case CMD_WRITE:
                        if (!unlocked)
                                mtd_unlock(device);
-                       mtd_write(imagefd, device, fis_layout);
+                       mtd_write(imagefd, device, fis_layout, part_offset);
                        break;
                case CMD_JFFS2WRITE:
                        if (!unlocked)
@@ -762,7 +744,12 @@ int main (int argc, char **argv)
                        mtd_refresh(device);
                        break;
                case CMD_FIXTRX:
-                       mtd_fixtrx(device, offset);
+                   if (mtd_fixtrx) {
+                           mtd_fixtrx(device, offset);
+            }
+               case CMD_FIXSEAMA:
+                       if (mtd_fixseama)
+                           mtd_fixseama(device, 0);
                        break;
        }
 
index a018031..c2133fc 100644 (file)
@@ -21,8 +21,9 @@ extern int mtd_write_jffs2(const char *mtd, const char *filename, const char *di
 extern int mtd_replace_jffs2(const char *mtd, int fd, int ofs, const char *filename);
 extern void mtd_parse_jffs2data(const char *buf, const char *dir);
 
-/* target specific */
-extern int trx_fixup(int fd, const char *name);
-extern int trx_check(int imagefd, const char *mtd, char *buf, int *len);
-
+/* target specific functions */
+extern int trx_fixup(int fd, const char *name)  __attribute__ ((weak));
+extern int trx_check(int imagefd, const char *mtd, char *buf, int *len) __attribute__ ((weak));
+extern int mtd_fixtrx(const char *mtd, size_t offset) __attribute__ ((weak));
+extern int mtd_fixseama(const char *mtd, size_t offset) __attribute__ ((weak));
 #endif /* __mtd_h */
diff --git a/package/mtd/src/seama.c b/package/mtd/src/seama.c
new file mode 100644 (file)
index 0000000..b0c8bf3
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * seama.c
+ *
+ * Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * Based on the trx fixup code:
+ *   Copyright (C) 2005 Mike Baker
+ *   Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <errno.h>
+#include <arpa/inet.h>
+
+#include <sys/ioctl.h>
+#include <mtd/mtd-user.h>
+#include "mtd.h"
+#include "seama.h"
+#include "md5.h"
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define STORE32_LE(X)           ((((X) & 0x000000FF) << 24) | (((X) & 0x0000FF00) << 8) | (((X) & 0x00FF0000) >> 8) | (((X) & 0xFF000000) >> 24))
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
+#define STORE32_LE(X)           (X)
+#else
+#error unknown endianness!
+#endif
+
+ssize_t pread(int fd, void *buf, size_t count, off_t offset);
+ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset);
+
+int
+seama_fix_md5(char *buf, size_t len)
+{
+       struct seama_hdr *shdr;
+       char *data;
+       size_t msize;
+       size_t isize;
+       MD5_CTX ctx;
+       unsigned char digest[16];
+       int i;
+
+       if (len < sizeof(struct seama_hdr))
+               return -1;
+
+       shdr = (struct seama_hdr *) buf;
+       if (shdr->magic != htonl(SEAMA_MAGIC)) {
+               fprintf(stderr, "no SEAMA header found\n");
+               return -1;
+       }
+
+       isize = ntohl(shdr->size);
+       msize = ntohs(shdr->metasize);
+       if (isize == 0) {
+               /* the image contains no checksum */
+               return -1;
+       }
+
+       len -= sizeof(struct seama_hdr) + sizeof(digest) + msize;
+       if (isize > len)
+               isize = len;
+
+       data = buf + sizeof(struct seama_hdr) + sizeof(digest) + msize;
+
+       MD5_Init(&ctx);
+       MD5_Update(&ctx, data, isize);
+       MD5_Final(digest, &ctx);
+
+       if (!memcmp(digest, &buf[sizeof(struct seama_hdr)], sizeof(digest))) {
+               if (quiet < 2)
+                       fprintf(stderr, "the header is fixed already\n");
+               return -1;
+       }
+
+       if (quiet < 2) {
+               fprintf(stderr, "new size:%u, new MD5: ", isize);
+               for (i = 0; i < sizeof(digest); i++)
+                       fprintf(stderr, "%02x", digest[i]);
+
+               fprintf(stderr, "\n");
+       }
+
+       /* update the size in the image */
+       shdr->size = htonl(isize);
+
+       /* update the checksum in the image */
+       for (i = 0; i < sizeof(digest); i++)
+               buf[sizeof(struct seama_hdr) + i] = digest[i];
+
+       return 0;
+}
+
+int
+mtd_fixseama(const char *mtd, size_t offset)
+{
+       int fd;
+       char *buf;
+       ssize_t res;
+       size_t block_offset;
+
+       if (quiet < 2)
+               fprintf(stderr, "Trying to fix SEAMA header in %s at 0x%x...\n",
+                       mtd, offset);
+
+       block_offset = offset & ~(erasesize - 1);
+       offset -= block_offset;
+
+       fd = mtd_check_open(mtd);
+       if(fd < 0) {
+               fprintf(stderr, "Could not open mtd device: %s\n", mtd);
+               exit(1);
+       }
+
+       if (block_offset + erasesize > mtdsize) {
+               fprintf(stderr, "Offset too large, device size 0x%x\n",
+                       mtdsize);
+               exit(1);
+       }
+
+       buf = malloc(mtdsize);
+       if (!buf) {
+               perror("malloc");
+               exit(1);
+       }
+
+       res = pread(fd, buf, mtdsize, block_offset);
+       if (res != mtdsize) {
+               perror("pread");
+               exit(1);
+       }
+
+       if (seama_fix_md5(buf, mtdsize))
+               goto out;
+
+       if (mtd_erase_block(fd, block_offset)) {
+               fprintf(stderr, "Can't erease block at 0x%x (%s)\n",
+                       block_offset, strerror(errno));
+               exit(1);
+       }
+
+       if (quiet < 2)
+               fprintf(stderr, "Rewriting block at 0x%x\n", block_offset);
+
+       if (pwrite(fd, buf, erasesize, block_offset) != erasesize) {
+               fprintf(stderr, "Error writing block (%s)\n", strerror(errno));
+               exit(1);
+       }
+
+       if (quiet < 2)
+               fprintf(stderr, "Done.\n");
+
+out:
+       close (fd);
+       sync();
+
+       return 0;
+}
+
diff --git a/package/mtd/src/seama.h b/package/mtd/src/seama.h
new file mode 100644 (file)
index 0000000..02683b6
--- /dev/null
@@ -0,0 +1,108 @@
+/* vi: set sw=4 ts=4: */
+/*
+ *     (SEA)ttle i(MA)ge is the image which used in project seattle.
+ *
+ *     Created by David Hsieh <david_hsieh@alphanetworks.com>
+ *     Copyright (C) 2008-2009 Alpha Networks, Inc.
+ *
+ *     This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU Lesser General Public
+ *     License as published by the Free Software Foundation; either'
+ *     version 2.1 of the License, or (at your option) any later version.
+ *
+ *     The GNU C Library 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
+ *     Lesser General Public License for more details.
+ *
+ *     You should have received a copy of the GNU Lesser General Public
+ *     License along with the GNU C Library; if not, write to the Free
+ *     Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *     02111-1307 USA.
+ */
+
+#ifndef __SEAMA_HEADER_FILE__
+#define __SEAMA_HEADER_FILE__
+
+#include <stdint.h>
+
+#define SEAMA_MAGIC            0x5EA3A417
+
+/*
+ *     SEAMA looks like the following map.
+ *     All the data of the header should be in network byte order.
+ *
+ *  +-------------+-------------+------------
+ *     | SEAMA magic               |     ^
+ *  +-------------+-------------+     |
+ *     | reserved    | meta size   |     |
+ *  +-------------+-------------+   header
+ *     | image size (0 bytes)      |     |
+ *  +-------------+-------------+     |
+ *     ~ Meta data                 ~     v
+ *  +-------------+-------------+------------
+ *     | SEAMA magic               |   ^     ^
+ *  +-------------+-------------+   |     |
+ *     | reserved    | meta size   |   |     |
+ *  +-------------+-------------+   |     |
+ *     | image size                |   |     |
+ *  +-------------+-------------+ header  |
+ *     |                           |   |     |
+ *     | 16 bytes of MD5 digest    |   |     |
+ *     |                           |   |     |
+ *     |                           |   |     |
+ *  +-------------+-------------+   |     |
+ *     ~ Meta data                 ~   v     |
+ *  +-------------+-------------+-------  |
+ *     |                           |         |
+ *     | Image of the 1st entity   |         |
+ *     ~                           ~ 1st entity
+ *     |                           |         |
+ *     |                           |         v
+ *  +-------------+-------------+-------------
+ *     | SEAMA magic               |   ^     ^
+ *  +-------------+-------------+   |     |
+ *     | reserved    | meta size   |   |     |
+ *  +-------------+-------------+   |     |
+ *     | image size                |   |     |
+ *  +-------------+-------------+ header  |
+ *     |                           |   |     |
+ *     | 16 bytes of MD5 digest    |   |     |
+ *     |                           |   |     |
+ *     |                           |   |     |
+ *  +-------------+-------------+   |     |
+ *     ~ Meta data                 ~   v     |
+ *  +-------------+-------------+-------  |
+ *     |                           |         |
+ *     | Image of the 2nd entity   |         |
+ *     ~                           ~ 2nd entity
+ *     |                           |         |
+ *     |                           |         v
+ *  +-------------+-------------+-------------
+ */
+
+
+/*
+ *     SEAMA header
+ *
+ *     |<-------- 32 bits -------->|
+ *  +-------------+-------------+
+ *     | SEAMA magic               |
+ *  +-------------+-------------+
+ *     | reserved    | meta size   |
+ *  +-------------+-------------+
+ *     | image size                |
+ *  +-------------+-------------+
+ */
+/* seama header */
+typedef struct seama_hdr       seamahdr_t;
+struct seama_hdr
+{
+       uint32_t        magic;                  /* should always be SEAMA_MAGIC. */
+       uint16_t        reserved;               /* reserved for  */
+       uint16_t        metasize;               /* size of the META data */
+       uint32_t        size;                   /* size of the image */
+} __attribute__ ((packed));
+
+
+#endif
index 7094ef6..65c2440 100644 (file)
 #include <sys/mman.h>
 #include <sys/stat.h>
 #include <string.h>
+#include <errno.h>
 
 #include <sys/ioctl.h>
-#include "mtd-api.h"
+#include <mtd/mtd-user.h>
 #include "mtd.h"
 #include "crc32.h"
 
 #define TRX_MAGIC       0x30524448      /* "HDR0" */
 struct trx_header {
-       unsigned magic;         /* "HDR0" */
-       unsigned len;           /* Length of file including header */
-       unsigned crc32;         /* 32-bit CRC from flag_version to end of file */
-       unsigned flag_version;  /* 0:15 flags, 16:31 version */
-       unsigned offsets[3];    /* Offsets of partitions from start of header */
+       uint32_t magic;         /* "HDR0" */
+       uint32_t len;           /* Length of file including header */
+       uint32_t crc32;         /* 32-bit CRC from flag_version to end of file */
+       uint32_t flag_version;  /* 0:15 flags, 16:31 version */
+       uint32_t offsets[3];    /* Offsets of partitions from start of header */
 };
 
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define STORE32_LE(X)           ((((X) & 0x000000FF) << 24) | (((X) & 0x0000FF00) << 8) | (((X) & 0x00FF0000) >> 8) | (((X) & 0xFF000000) >> 24))
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
+#define STORE32_LE(X)           (X)
+#else
+#error unknown endianness!
+#endif
+
+ssize_t pread(int fd, void *buf, size_t count, off_t offset);
+ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset);
+
 int
 trx_fixup(int fd, const char *name)
 {
@@ -130,3 +142,79 @@ trx_check(int imagefd, const char *mtd, char *buf, int *len)
        return 1;
 }
 
+int
+mtd_fixtrx(const char *mtd, size_t offset)
+{
+       int fd;
+       struct trx_header *trx;
+       char *buf;
+       ssize_t res;
+       size_t block_offset;
+
+       if (quiet < 2)
+               fprintf(stderr, "Trying to fix trx header in %s at 0x%x...\n", mtd, offset);
+
+       fd = mtd_check_open(mtd);
+       if(fd < 0) {
+               fprintf(stderr, "Could not open mtd device: %s\n", mtd);
+               exit(1);
+       }
+
+       block_offset = offset & ~(erasesize - 1);
+       offset -= block_offset;
+
+       if (block_offset + erasesize > mtdsize) {
+               fprintf(stderr, "Offset too large, device size 0x%x\n", mtdsize);
+               exit(1);
+       }
+
+       buf = malloc(erasesize);
+       if (!buf) {
+               perror("malloc");
+               exit(1);
+       }
+
+       res = pread(fd, buf, erasesize, block_offset);
+       if (res != erasesize) {
+               perror("pread");
+               exit(1);
+       }
+
+       trx = (struct trx_header *) (buf + offset);
+       if (trx->magic != STORE32_LE(0x30524448)) {
+               fprintf(stderr, "No trx magic found\n");
+               exit(1);
+       }
+
+       if (trx->len == STORE32_LE(erasesize - offset)) {
+               if (quiet < 2)
+                       fprintf(stderr, "Header already fixed, exiting\n");
+               close(fd);
+               return 0;
+       }
+
+       trx->len = STORE32_LE(erasesize - offset);
+
+       trx->crc32 = STORE32_LE(crc32buf((char*) &trx->flag_version, erasesize - offset - 3*4));
+       if (mtd_erase_block(fd, block_offset)) {
+               fprintf(stderr, "Can't erease block at 0x%x (%s)\n", block_offset, strerror(errno));
+               exit(1);
+       }
+
+       if (quiet < 2)
+               fprintf(stderr, "New crc32: 0x%x, rewriting block\n", trx->crc32);
+
+       if (pwrite(fd, buf, erasesize, block_offset) != erasesize) {
+               fprintf(stderr, "Error writing block (%s)\n", strerror(errno));
+               exit(1);
+       }
+
+       if (quiet < 2)
+               fprintf(stderr, "Done.\n");
+
+       close (fd);
+       sync();
+       return 0;
+
+}
+
diff --git a/package/quagga/Makefile b/package/quagga/Makefile
new file mode 100644 (file)
index 0000000..4673e51
--- /dev/null
@@ -0,0 +1,321 @@
+#
+# Copyright (C) 2006-2013 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=quagga
+PKG_VERSION:=1.0.20160315
+PKG_RELEASE:=2
+PKG_MD5SUM:=61bfd0c8fb696dd778234ee8b05821bc
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=http://download.savannah.gnu.org/releases/quagga/
+PKG_CONFIG_DEPENDS:= \
+       CONFIG_IPV6 \
+       CONFIG_PACKAGE_quagga-watchquagga \
+       CONFIG_PACKAGE_quagga-zebra \
+       CONFIG_PACKAGE_quagga-libzebra \
+       CONFIG_PACKAGE_quagga-libospf \
+       CONFIG_PACKAGE_quagga-bgpd \
+       CONFIG_PACKAGE_quagga-isisd \
+       CONFIG_PACKAGE_quagga-ospf6d \
+       CONFIG_PACKAGE_quagga-ripd \
+       CONFIG_PACKAGE_quagga-ripngd \
+       CONFIG_PACKAGE_quagga-babeld \
+       CONFIG_PACKAGE_quagga-vtysh \
+       CONFIG_PACKAGE_quagga-pgbgp
+PKG_BUILD_PARALLEL:=1
+PKG_FIXUP:=autoreconf
+PKG_INSTALL:=1
+
+PATCH_DIR:=patches-pgbgp
+ifeq ($(CONFIG_PACKAGE_quagga-pgbgp),)
+PATCH_DIR:=patches-upstream
+endif
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/quagga/Default
+  SECTION:=net
+  CATEGORY:=Network
+  SUBMENU:=Routing and Redirection
+  DEPENDS:=quagga
+  TITLE:=The Quagga Software Routing Suite
+  URL:=http://www.quagga.net
+  MAINTAINER:=Vasilis Tsiligiannis <b_tsiligiannis@silverton.gr>
+endef
+
+define Package/quagga
+  $(call Package/quagga/Default)
+  DEPENDS:=+librt
+  MENU:=1
+endef
+
+define Package/quagga/description
+  A routing software package that provides TCP/IP based routing services
+  with routing protocols support such as RIPv1, RIPv2, RIPng, OSPFv2,
+  OSPFv3, BGP-4, and BGP-4+
+endef
+
+define Package/quagga-watchquagga
+  $(call Package/quagga/Default)
+  TITLE:=Quagga watchdog
+  DEPENDS+=+quagga-libzebra
+  DEFAULT:=y if PACKAGE_quagga
+endef
+
+define Package/quagga-zebra
+  $(call Package/quagga/Default)
+  TITLE:=Zebra daemon
+  DEPENDS+=+quagga-libzebra
+  DEFAULT:=y if PACKAGE_quagga
+endef
+
+define Package/quagga-libzebra
+  $(call Package/quagga/Default)
+  TITLE:=zebra library
+endef
+
+define Package/quagga-libospf
+  $(call Package/quagga/Default)
+  TITLE:=OSPF library
+endef
+
+define Package/quagga-bgpd
+  $(call Package/quagga/Default)
+  DEPENDS+=+quagga-libzebra
+  TITLE:=BGPv4, BGPv4+, BGPv4- routing engine
+endef
+
+define Package/quagga-isisd
+  $(call Package/quagga/Default)
+  DEPENDS+=+quagga-libzebra
+  TITLE:=IS-IS routing engine
+endef
+
+define Package/quagga-ospfd
+  $(call Package/quagga/Default)
+  DEPENDS+=+quagga-libospf +quagga-libzebra
+  TITLE:=OSPFv2 routing engine
+endef
+
+define Package/quagga-ospf6d
+  $(call Package/quagga/Default)
+  DEPENDS+=+quagga-libospf +quagga-libzebra @IPV6
+  TITLE:=OSPFv3 routing engine
+endef
+
+define Package/quagga-ripd
+  $(call Package/quagga/Default)
+  DEPENDS+=+quagga-libzebra
+  TITLE:=RIP routing engine
+endef
+
+define Package/quagga-ripngd
+  $(call Package/quagga/Default)
+  DEPENDS+=+quagga-libzebra @IPV6
+  TITLE:=RIPNG routing engine
+endef
+
+define Package/quagga-babeld
+  $(call Package/quagga/Default)
+  DEPENDS+=+quagga-libzebra @IPV6
+  TITLE:=Babel routing engine
+endef
+
+define Package/quagga-vtysh
+  $(call Package/quagga/Default)
+  DEPENDS+=+quagga-libzebra +libreadline +libncurses
+  TITLE:=integrated shell for Quagga routing software
+endef
+
+define Package/quagga-pgbgp
+  $(call Package/quagga/Default)
+  DEPENDS+=+quagga-bgpd
+  TITLE:=include Pretty Good BGP functionality
+endef
+
+define Package/quagga-zebra/conffiles
+/etc/quagga/zebra.conf
+endef
+
+define Package/quagga-bgpd/conffiles
+/etc/quagga/bgpd.conf
+endef
+
+define Package/quagga-isisd/conffiles
+/etc/quagga/isisd.conf
+endef
+
+define Package/quagga-ospfd/conffiles
+/etc/quagga/ospfd.conf
+endef
+
+define Package/quagga-ospf6d/conffiles
+/etc/quagga/ospf6d.conf
+endef
+
+define Package/quagga-ripd/conffiles
+/etc/quagga/ripd.conf
+endef
+
+define Package/quagga-ripngd/conffiles
+/etc/quagga/ripngd.conf
+endef
+
+define Package/quagga-babeld/conffiles
+/etc/quagga/babeld.conf
+endef
+
+ifneq ($(SDK),)
+CONFIG_PACKAGE_quagga-libzebra:=m
+CONFIG_PACKAGE_quagga-libospf:=m
+CONFIG_PACKAGE_quagga-watchquagga:=m
+CONFIG_PACKAGE_quagga-zebra:=m
+CONFIG_PACKAGE_quagga-bgpd:=m
+CONFIG_PACKAGE_quagga-isisd:=m
+CONFIG_PACKAGE_quagga-ospf6d:=m
+CONFIG_PACKAGE_quagga-ripd:=m
+CONFIG_PACKAGE_quagga-ripngd:=m
+CONFIG_PACKAGE_quagga-babeld:=m
+CONFIG_PACKAGE_quagga-vtysh:=m
+endif
+
+CONFIGURE_ARGS+= \
+       --localstatedir=/var/run/quagga \
+       --sysconfdir=/etc/quagga/ \
+       --enable-shared \
+       --disable-static \
+       --enable-user=network \
+       --enable-group=network \
+       --enable-pie=no \
+       --enable-multipath=8 \
+       --disable-ospfclient \
+       --disable-capabilities \
+       --disable-doc \
+       $(call autoconf_bool,CONFIG_PACKAGE_quagga-libzebra,zebra) \
+       $(call autoconf_bool,CONFIG_PACKAGE_quagga-libospf,ospfd) \
+       $(call autoconf_bool,CONFIG_PACKAGE_quagga-bgpd,bgpd) \
+       $(call autoconf_bool,CONFIG_PACKAGE_quagga-isisd,isisd) \
+       $(call autoconf_bool,CONFIG_PACKAGE_quagga-ospf6d,ospf6d) \
+       $(call autoconf_bool,CONFIG_PACKAGE_quagga-ripd,ripd) \
+       $(call autoconf_bool,CONFIG_PACKAGE_quagga-ripngd,ripngd) \
+       $(call autoconf_bool,CONFIG_PACKAGE_quagga-babeld,babeld) \
+       $(call autoconf_bool,CONFIG_PACKAGE_quagga-vtysh,vtysh) \
+       $(call autoconf_bool,CONFIG_PACKAGE_quagga-pgbgp,pgbgp) \
+
+MAKE_FLAGS += \
+       CFLAGS="$(TARGET_CFLAGS) -std=gnu99"
+
+define Package/quagga/install
+       $(INSTALL_DIR) $(1)/usr/sbin
+       $(INSTALL_BIN) ./files/quagga $(1)/usr/sbin/quagga.init
+       $(INSTALL_DIR) $(1)/etc/init.d
+       $(INSTALL_BIN) ./files/quagga.init $(1)/etc/init.d/quagga
+endef
+
+define Package/quagga-watchquagga/install
+       $(INSTALL_DIR) $(1)/usr/sbin
+       $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/watchquagga $(1)/usr/sbin/
+endef
+
+define Package/quagga-zebra/install
+       $(INSTALL_DIR) $(1)/usr/sbin
+       $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/zebra $(1)/usr/sbin/
+       $(INSTALL_DIR) $(1)/etc/quagga
+       chmod 0750 $(1)/etc/quagga
+       $(INSTALL_CONF) ./files/quagga.conf $(1)/etc/quagga/zebra.conf
+endef
+
+define Package/quagga-bgpd/install
+       $(INSTALL_DIR) $(1)/usr/sbin
+       $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/bgpd $(1)/usr/sbin/
+       $(INSTALL_DIR) $(1)/etc/quagga
+       chmod 0750 $(1)/etc/quagga
+       $(INSTALL_CONF) ./files/quagga.conf $(1)/etc/quagga/bgpd.conf
+endef
+
+define Package/quagga-isisd/install
+       $(INSTALL_DIR) $(1)/usr/sbin
+       $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/isisd $(1)/usr/sbin/
+       $(INSTALL_DIR) $(1)/etc/quagga
+       chmod 0750 $(1)/etc/quagga
+       $(INSTALL_CONF) ./files/quagga.conf $(1)/etc/quagga/isisd.conf
+endef
+
+define Package/quagga-ospfd/install
+       $(INSTALL_DIR) $(1)/usr/sbin
+       $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/ospfd $(1)/usr/sbin/
+       $(INSTALL_DIR) $(1)/etc/quagga
+       chmod 0750 $(1)/etc/quagga
+       $(INSTALL_CONF) ./files/quagga.conf $(1)/etc/quagga/ospfd.conf
+endef
+
+define Package/quagga-ospf6d/install
+       $(INSTALL_DIR) $(1)/usr/sbin
+       $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/ospf6d $(1)/usr/sbin/
+       $(INSTALL_DIR) $(1)/etc/quagga
+       chmod 0750 $(1)/etc/quagga
+       $(INSTALL_CONF) ./files/quagga.conf $(1)/etc/quagga/ospf6d.conf
+endef
+
+define Package/quagga-ripd/install
+       $(INSTALL_DIR) $(1)/usr/sbin
+       $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/ripd $(1)/usr/sbin/
+       $(INSTALL_DIR) $(1)/etc/quagga
+       chmod 0750 $(1)/etc/quagga
+       $(INSTALL_CONF) ./files/quagga.conf $(1)/etc/quagga/ripd.conf
+endef
+
+define Package/quagga-ripngd/install
+       $(INSTALL_DIR) $(1)/usr/sbin
+       $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/ripngd $(1)/usr/sbin/
+       $(INSTALL_DIR) $(1)/etc/quagga
+       chmod 0750 $(1)/etc/quagga
+       $(INSTALL_CONF) ./files/quagga.conf $(1)/etc/quagga/ripngd.conf
+endef
+
+define Package/quagga-babeld/install
+       $(INSTALL_DIR) $(1)/usr/sbin
+       $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/babeld $(1)/usr/sbin/
+       $(INSTALL_DIR) $(1)/etc/quagga
+       chmod 0750 $(1)/etc/quagga
+       $(INSTALL_CONF) ./files/quagga.conf $(1)/etc/quagga/babeld.conf
+endef
+
+define Package/quagga-vtysh/install
+       $(INSTALL_DIR) $(1)/usr/bin
+       $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/vtysh $(1)/usr/bin/
+endef
+
+define Package/quagga-pgbgp/install
+endef
+
+define Package/quagga-libospf/install
+       $(INSTALL_DIR) $(1)/usr/lib
+       $(CP) $(PKG_INSTALL_DIR)/usr/lib/libospf.so.* $(1)/usr/lib/
+endef
+
+define Package/quagga-libzebra/install
+       $(INSTALL_DIR) $(1)/usr/lib
+       $(CP) $(PKG_INSTALL_DIR)/usr/lib/libzebra.so.* $(1)/usr/lib/
+endef
+
+$(eval $(call BuildPackage,quagga))
+$(eval $(call BuildPackage,quagga-libzebra))
+$(eval $(call BuildPackage,quagga-libospf))
+$(eval $(call BuildPackage,quagga-watchquagga))
+$(eval $(call BuildPackage,quagga-zebra))
+$(eval $(call BuildPackage,quagga-bgpd))
+$(eval $(call BuildPackage,quagga-pgbgp))
+$(eval $(call BuildPackage,quagga-isisd))
+$(eval $(call BuildPackage,quagga-ospfd))
+$(eval $(call BuildPackage,quagga-ospf6d))
+$(eval $(call BuildPackage,quagga-ripd))
+$(eval $(call BuildPackage,quagga-ripngd))
+$(eval $(call BuildPackage,quagga-babeld))
+$(eval $(call BuildPackage,quagga-vtysh))
diff --git a/package/quagga/files/quagga b/package/quagga/files/quagga
new file mode 100644 (file)
index 0000000..b172090
--- /dev/null
@@ -0,0 +1,335 @@
+#!/bin/sh
+#
+# quagga       Starts/stops quagga daemons and watchquagga.
+#              Create a daemon.conf file to have that routing daemon
+#              started/stopped automagically when using this script
+#              without any daemon names as args.
+#              If watchquagga is available, it will also be
+#              started/stopped if the script is called without
+#              any daemon names.
+#
+
+ME=$(basename $0)
+
+usage() {
+       echo "Usage: ${ME} {start|stop|restart} [daemon ...]"
+       exit 2
+}
+
+if [ -z "$1" ]
+then
+       usage
+else
+       COMMAND=$1
+fi
+shift
+ARG_DAEMONS=$*
+BINDIR=/usr/sbin
+CONFDIR=/etc/quagga
+STATEDIR=/var/run/quagga
+RUNUSER=network
+RUNGROUP=$RUNUSER
+DAEMONS="zebra ripd ripngd ospfd ospf6d bgpd"
+DAEMON_FLAGS=-d
+WATCHQUAGGA_FLAGS="-d -z -T 60 -R"
+WATCHQUAGGA_CMD="$0 watchrestart"
+if [ ${COMMAND} != "watchrestart" -a -x "${BINDIR}/watchquagga" ]
+then
+       DAEMONS="${DAEMONS} watchquagga"
+fi
+DAEMONS_STARTSEQ=${DAEMONS}
+
+reverse()
+{
+       local revlist r
+        revlist=
+        for r
+       do
+                revlist="$r $revlist"
+        done
+        echo $revlist
+}
+
+DAEMONS_STOPSEQ=$(reverse ${DAEMONS_STARTSEQ})
+
+#pidof() {
+#      ps ax | awk 'match($5, "(^|/)'"$1"'$") > 0 { printf " %s", $1 }'
+#}
+
+quit() {
+       echo "${ME}: $1"
+       exit 0
+}
+
+die() {
+       echo "${ME}: $1"
+       exit 1
+}
+
+is_in() {
+       local i
+       for i in $2
+       do
+               [ "$1" = "$i" ] && return 0
+       done
+       return 1
+}
+
+select_subset() {
+       local unknown i j
+       unknown=
+       RESULT=
+       for i in $1
+       do
+               is_in $i "$2" || unknown="$unknown $i"
+       done
+       if [ -n "$unknown" ]
+       then
+               RESULT=$unknown
+               return 1
+       else
+               for j in $2
+               do
+                       is_in $j "$1" && RESULT="$RESULT $j"
+               done
+               return 0
+       fi
+}
+
+# check command
+
+case ${COMMAND}
+in
+       start|stop|restart)
+               ;;
+       watchrestart)
+               if [ -n "$ARG_DAEMONS" ]
+               then
+                       echo "${ME}: watchrestart mode is only for use by watchquagga"
+                       exit 2
+               fi
+               ;;
+       *)
+               usage
+               ;;
+esac
+
+# select daemons to start
+
+case ${COMMAND}
+in
+       start|restart|watchrestart)
+               START_DAEMONS=
+               for d in ${DAEMONS_STARTSEQ}
+               do
+                       [ -x "${BINDIR}/${d}" -a -f "${CONFDIR}/${d}.conf" ] \
+                       && START_DAEMONS="${START_DAEMONS}${d} "
+               done
+               WATCHQUAGGA_DAEMONS=${START_DAEMONS}
+               if is_in watchquagga "${DAEMONS_STARTSEQ}"
+               then
+                       START_DAEMONS="${START_DAEMONS} watchquagga"
+               fi
+               if [ -n "${ARG_DAEMONS}" ]
+               then
+                       if select_subset "${ARG_DAEMONS}" "${DAEMONS}"
+                       then
+                               if select_subset "${ARG_DAEMONS}" "${START_DAEMONS}"
+                               then
+                                       START_DAEMONS=${RESULT}
+                               else
+                                       die "these daemons are not startable:${RESULT}."
+                               fi
+                       else
+                               die "unknown daemons:${RESULT}; choose from: ${DAEMONS}."
+                       fi
+               fi
+               ;;
+esac
+
+# select daemons to stop
+
+case ${COMMAND}
+in
+       stop|restart|watchrestart)
+               STOP_DAEMONS=${DAEMONS_STOPSEQ}
+               if [ -n "${ARG_DAEMONS}" ]
+               then
+                       if select_subset "${ARG_DAEMONS}" "${STOP_DAEMONS}"
+                       then
+                               STOP_DAEMONS=${RESULT}
+                       else
+                               die "unknown daemons:${RESULT}; choose from: ${DAEMONS}."
+                       fi
+               fi
+               stop_daemons=
+               for d in ${STOP_DAEMONS}
+               do
+                       pidfile=${STATEDIR}/${d}.pid
+                       if [ -f "${pidfile}" -o -n "$(pidof ${d})" ]
+                       then
+                               stop_daemons="${stop_daemons}${d} "
+                       elif [ -n "${ARG_DAEMONS}" ]
+                       then
+                               echo "${ME}: found no ${d} process running."
+                       fi
+               done
+               STOP_DAEMONS=${stop_daemons}
+               ;;
+esac
+
+# stop daemons
+
+for d in $STOP_DAEMONS
+do
+       echo -n "${ME}: Stopping ${d} ... "
+       pidfile=${STATEDIR}/${d}.pid
+       if [ -f "${pidfile}" ]
+       then
+               file_pid=$(cat ${pidfile})
+               if [ -z "${file_pid}" ]
+               then
+                       echo -n "no pid file entry found ... "
+               fi
+       else
+               file_pid=
+               echo -n "no pid file found ... "
+       fi
+       proc_pid=$(pidof ${d})
+       if [ -z "${proc_pid}" ]
+       then
+               echo -n "found no ${d} process running ... "
+       else
+               count=0
+               notinpidfile=
+               for p in ${proc_pid}
+               do
+                       count=$((${count}+1))
+                       if kill ${p}
+                       then
+                               echo -n "killed ${p} ... "
+                       else
+                               echo -n "failed to kill ${p} ... "
+                       fi
+                       [ "${p}" = "${file_pid}" ] \
+                       || notinpidfile="${notinpidfile} ${p}"
+               done
+               [ ${count} -le 1 ] \
+               || echo -n "WARNING: ${count} ${d} processes were found running ... "
+               for n in ${notinpidfile}
+               do
+                       echo -n "WARNING: process ${n} was not in pid file ... "
+               done
+       fi
+       count=0
+       survivors=$(pidof ${d})
+       while [ -n "${survivors}" ]
+       do
+               sleep 1
+               count=$((${count}+1))
+               survivors=$(pidof ${d})
+               [ -z "${survivors}" -o ${count} -gt 5 ] && break
+               for p in ${survivors}
+               do
+                       sleep 1
+                       echo -n "${p} "
+                       kill ${p}
+               done
+       done
+       survivors=$(pidof ${d})
+       [ -n "${survivors}" ] && \
+       if kill -KILL ${survivors}
+       then
+               echo -n "KILLed ${survivors} ... "
+       else
+               echo -n "failed to KILL ${survivors} ... "
+       fi
+       sleep 1
+       survivors=$(pidof ${d})
+       if [ -z "${survivors}" ]
+       then
+               echo -n "done."
+               if [ -f "${pidfile}" ]
+               then
+                       rm -f ${pidfile} \
+                       || echo -n " Failed to remove pidfile."
+               fi
+       else
+               echo -n "failed to stop ${survivors} - giving up."
+               if [ "${survivors}" != "${file_pid}" ]
+               then
+                       if echo "${survivors}" > ${pidfile}
+                       then
+                               chown ${RUNUSER}:${RUNGROUP} ${pidfile}
+                               echo -n " Wrote ${survivors} to pidfile."
+                       else
+                               echo -n " Failed to write ${survivors} to pidfile."
+                       fi
+               fi
+       fi
+       echo
+done
+
+# start daemons
+
+if [ -n "$START_DAEMONS" ]
+then
+       [ -d ${CONFDIR} ] \
+       || quit "${ME}: no config directory ${CONFDIR} - exiting."
+       chown -R ${RUNUSER}:${RUNGROUP} ${CONFDIR}
+       [ -d ${STATEDIR} ] || mkdir -p ${STATEDIR} \
+       || die "${ME}: could not create state directory ${STATEDIR} - exiting."
+       chown -R ${RUNUSER}:${RUNGROUP} ${STATEDIR}
+
+       for d in $START_DAEMONS
+       do
+               echo -n "${ME}: Starting ${d} ... "
+               proc_pid=$(pidof ${d})
+               pidfile=${STATEDIR}/${d}.pid
+               file_pid=
+               if [ -f "${pidfile}" ]
+               then
+                       file_pid=$(cat ${pidfile})
+                       if [ -n "${file_pid}" ]
+                       then
+                               echo -n "found old pid file entry ${file_pid} ... "
+                       fi
+               fi
+               if [ -n "${proc_pid}" ]
+               then
+                       echo -n "found ${d} running (${proc_pid}) - skipping ${d}."
+                       if [ "${proc_pid}" != "${file_pid}" ]
+                       then
+                               if echo "${proc_pid}" > ${pidfile}
+                               then
+                                       chown ${RUNUSER}:${RUNGROUP} ${pidfile}
+                                       echo -n " Wrote ${proc_pid} to pidfile."
+                               else
+                                       echo -n " Failed to write ${proc_pid} to pidfile."
+                               fi
+                       fi
+               elif rm -f "${pidfile}"
+               then
+                       if [ "${d}" = "watchquagga" ]
+                       then
+                               "${BINDIR}/${d}" \
+                                       ${WATCHQUAGGA_FLAGS} \
+                                       "${WATCHQUAGGA_CMD}" \
+                                       ${WATCHQUAGGA_DAEMONS}
+                               status=$?
+                       else
+                               "${BINDIR}/${d}" ${DAEMON_FLAGS}
+                               status=$?
+                       fi
+                       if [ $status -eq 0 ]
+                       then
+                               echo -n "done."
+                       else
+                               echo -n "failed."
+                       fi
+               else
+                       echo -n " failed to remove pidfile."
+               fi
+               echo
+       done
+fi
diff --git a/package/quagga/files/quagga.conf b/package/quagga/files/quagga.conf
new file mode 100644 (file)
index 0000000..fb7a54e
--- /dev/null
@@ -0,0 +1,7 @@
+password zebra
+!
+access-list vty permit 127.0.0.0/8
+access-list vty deny any
+!
+line vty
+ access-class vty
diff --git a/package/quagga/files/quagga.init b/package/quagga/files/quagga.init
new file mode 100644 (file)
index 0000000..21fbf2c
--- /dev/null
@@ -0,0 +1,11 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2006 OpenWrt.org
+
+START=60
+start() {
+       /usr/sbin/quagga.init start
+}
+
+stop() {
+       /usr/sbin/quagga.init stop
+}
diff --git a/package/quagga/not-patches/patches-nopes/120-quagga_manet.patch b/package/quagga/not-patches/patches-nopes/120-quagga_manet.patch
new file mode 100644 (file)
index 0000000..4277704
--- /dev/null
@@ -0,0 +1,243 @@
+--- a/lib/log.c
++++ b/lib/log.c
+@@ -925,13 +925,19 @@ proto_redistnum(int afi, const char *s)
+       return ZEBRA_ROUTE_STATIC;
+       else if (strncmp (s, "r", 1) == 0)
+       return ZEBRA_ROUTE_RIP;
+-      else if (strncmp (s, "o", 1) == 0)
++      else if (strncmp (s, "os", 2) == 0)
+       return ZEBRA_ROUTE_OSPF;
+       else if (strncmp (s, "i", 1) == 0)
+       return ZEBRA_ROUTE_ISIS;
+       else if (strncmp (s, "bg", 2) == 0)
+       return ZEBRA_ROUTE_BGP;
+-      else if (strncmp (s, "ba", 2) == 0)
++      else if (strncmp (s, "h", 1) == 0)
++      return ZEBRA_ROUTE_HSLS;
++      else if (strncmp (s, "ol", 2) == 0)
++      return ZEBRA_ROUTE_OLSR;
++      else if (strncmp (s, "bat", 3) == 0)
++      return ZEBRA_ROUTE_BATMAN;
++      else if (strncmp (s, "bab", 3) == 0)
+       return ZEBRA_ROUTE_BABEL;
+     }
+   if (afi == AFI_IP6)
+@@ -944,13 +950,19 @@ proto_redistnum(int afi, const char *s)
+       return ZEBRA_ROUTE_STATIC;
+       else if (strncmp (s, "r", 1) == 0)
+       return ZEBRA_ROUTE_RIPNG;
+-      else if (strncmp (s, "o", 1) == 0)
++      else if (strncmp (s, "os", 2) == 0)
+       return ZEBRA_ROUTE_OSPF6;
+       else if (strncmp (s, "i", 1) == 0)
+       return ZEBRA_ROUTE_ISIS;
+       else if (strncmp (s, "bg", 2) == 0)
+       return ZEBRA_ROUTE_BGP;
+-      else if (strncmp (s, "ba", 2) == 0)
++      else if (strncmp (s, "h", 1) == 0)
++      return ZEBRA_ROUTE_HSLS;
++      else if (strncmp (s, "ol", 2) == 0)
++      return ZEBRA_ROUTE_OLSR;
++      else if (strncmp (s, "bat", 3) == 0)
++      return ZEBRA_ROUTE_BATMAN;
++      else if (strncmp (s, "bab", 3) == 0)
+       return ZEBRA_ROUTE_BABEL;
+     }
+   return -1;
+--- a/lib/route_types.txt
++++ b/lib/route_types.txt
+@@ -51,13 +51,9 @@ ZEBRA_ROUTE_OSPF,       ospf,      ospfd
+ ZEBRA_ROUTE_OSPF6,      ospf6,     ospf6d, 'O', 0, 1, "OSPFv6"
+ ZEBRA_ROUTE_ISIS,       isis,      isisd,  'I', 1, 1, "IS-IS"
+ ZEBRA_ROUTE_BGP,        bgp,       bgpd,   'B', 1, 1, "BGP"
+-# HSLS and OLSR both are AFI independent (so: 1, 1), however
+-# we want to disable for them for general Quagga distribution.
+-# This at least makes it trivial for users of these protocols
+-# to 'switch on' redist support (direct numeric entry remaining
+-# possible).
+-ZEBRA_ROUTE_HSLS,       hsls,      hslsd,  'H', 0, 0, "HSLS"
+-ZEBRA_ROUTE_OLSR,       olsr,      olsrd,  'o', 0, 0, "OLSR"
++ZEBRA_ROUTE_HSLS,       hsls,      hslsd,  'H', 1, 1, "HSLS"
++ZEBRA_ROUTE_OLSR,       olsr,      olsrd,  'o', 1, 1, "OLSR"
++ZEBRA_ROUTE_BATMAN,     batman,    batmand,'b', 1, 1, "BATMAN"
+ ZEBRA_ROUTE_BABEL,      babel,     babeld, 'A', 1, 1, "Babel"
+ ## help strings
+@@ -72,5 +68,6 @@ ZEBRA_ROUTE_OSPF6,  "Open Shortest Path
+ ZEBRA_ROUTE_ISIS,   "Intermediate System to Intermediate System (IS-IS)"
+ ZEBRA_ROUTE_BGP,    "Border Gateway Protocol (BGP)"
+ ZEBRA_ROUTE_HSLS,   "Hazy-Sighted Link State Protocol (HSLS)"
+-ZEBRA_ROUTE_OLSR,   "Optimised Link State Routing (OLSR)"
++ZEBRA_ROUTE_OLSR,   "Optimized Link State Routing (OLSR)"
++ZEBRA_ROUTE_BATMAN, "Better Approach to Mobile Ad-Hoc Networking (BATMAN)"
+ ZEBRA_ROUTE_BABEL,  "Babel routing protocol (Babel)"
+--- a/ripd/rip_zebra.c
++++ b/ripd/rip_zebra.c
+@@ -206,9 +206,12 @@ static struct {
+   {ZEBRA_ROUTE_KERNEL,  1, "kernel"},
+   {ZEBRA_ROUTE_CONNECT, 1, "connected"},
+   {ZEBRA_ROUTE_STATIC,  1, "static"},
+-  {ZEBRA_ROUTE_OSPF,    1, "ospf"},
++  {ZEBRA_ROUTE_OSPF,    2, "ospf"},
+   {ZEBRA_ROUTE_BGP,     2, "bgp"},
+-  {ZEBRA_ROUTE_BABEL,   2, "babel"},
++  {ZEBRA_ROUTE_HSLS,    1, "hsls"},
++  {ZEBRA_ROUTE_OLSR,    2, "olsr"},
++  {ZEBRA_ROUTE_BATMAN,  3, "batman"},
++  {ZEBRA_ROUTE_BABEL,   3, "babel"},
+   {0, 0, NULL}
+ };
+--- a/ripngd/ripng_zebra.c
++++ b/ripngd/ripng_zebra.c
+@@ -216,9 +216,12 @@ static struct {
+   {ZEBRA_ROUTE_KERNEL,  1, "kernel"},
+   {ZEBRA_ROUTE_CONNECT, 1, "connected"},
+   {ZEBRA_ROUTE_STATIC,  1, "static"},
+-  {ZEBRA_ROUTE_OSPF6,   1, "ospf6"},
++  {ZEBRA_ROUTE_OSPF6,   2, "ospf6"},
+   {ZEBRA_ROUTE_BGP,     2, "bgp"},
+-  {ZEBRA_ROUTE_BABEL,   2, "babel"},
++  {ZEBRA_ROUTE_HSLS,    1, "hsls"},
++  {ZEBRA_ROUTE_OLSR,    2, "olsr"},
++  {ZEBRA_ROUTE_BATMAN,  3, "batman"},
++  {ZEBRA_ROUTE_BABEL,   3, "babel"},
+   {0, 0, NULL}
+ };
+--- a/zebra/rt_netlink.c
++++ b/zebra/rt_netlink.c
+@@ -1810,6 +1810,9 @@ netlink_route_multipath (int cmd, struct
+       if (rta->rta_len > RTA_LENGTH (0))
+         addattr_l (&req.n, NL_PKT_BUF_SIZE, RTA_MULTIPATH, RTA_DATA (rta),
+                    RTA_PAYLOAD (rta));
++
++     if (rib->type == ZEBRA_ROUTE_OLSR)
++       req.r.rtm_scope = RT_SCOPE_LINK;
+     }
+   /* If there is no useful nexthop then return. */
+--- a/zebra/zebra_rib.c
++++ b/zebra/zebra_rib.c
+@@ -68,6 +68,9 @@ static const struct
+   [ZEBRA_ROUTE_OSPF6]   = {ZEBRA_ROUTE_OSPF6,   110},
+   [ZEBRA_ROUTE_ISIS]    = {ZEBRA_ROUTE_ISIS,    115},
+   [ZEBRA_ROUTE_BGP]     = {ZEBRA_ROUTE_BGP,      20  /* IBGP is 200. */},
++  [ZEBRA_ROUTE_HSLS]    = {ZEBRA_ROUTE_HSLS,      0},
++  [ZEBRA_ROUTE_OLSR]    = {ZEBRA_ROUTE_OLSR,      0},
++  [ZEBRA_ROUTE_BATMAN]  = {ZEBRA_ROUTE_BATMAN,    0},
+   [ZEBRA_ROUTE_BABEL]   = {ZEBRA_ROUTE_BABEL,    95},
+   /* no entry/default: 150 */
+ };
+@@ -538,6 +541,18 @@ nexthop_active_ipv4 (struct rib *rib, st
+                 }
+             return resolved;
+           }
++        else if (match->type == ZEBRA_ROUTE_OLSR)
++          {
++            for (newhop = match->nexthop; newhop; newhop = newhop->next)
++              if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
++                  && newhop->type == NEXTHOP_TYPE_IFINDEX)
++                {
++                  if (nexthop->type == NEXTHOP_TYPE_IPV4)
++                    nexthop->ifindex = newhop->ifindex;
++                  return 1;
++                }
++            return 0;
++          }
+         else
+           {
+             return 0;
+@@ -674,6 +689,18 @@ nexthop_active_ipv6 (struct rib *rib, st
+                 }
+             return resolved;
+           }
++        else if (match->type == ZEBRA_ROUTE_OLSR)
++          {
++            for (newhop = match->nexthop; newhop; newhop = newhop->next)
++              if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
++                  && newhop->type == NEXTHOP_TYPE_IFINDEX)
++                {
++                  if (nexthop->type == NEXTHOP_TYPE_IPV6)
++                    nexthop->ifindex = newhop->ifindex;
++                  return 1;
++                }
++            return 0;
++          }
+         else
+           {
+             return 0;
+@@ -1509,6 +1536,8 @@ static const u_char meta_queue_map[ZEBRA
+   [ZEBRA_ROUTE_ISIS]    = 2,
+   [ZEBRA_ROUTE_BGP]     = 3,
+   [ZEBRA_ROUTE_HSLS]    = 4,
++  [ZEBRA_ROUTE_OLSR]    = 4,
++  [ZEBRA_ROUTE_BATMAN]  = 4,
+   [ZEBRA_ROUTE_BABEL]   = 2,
+ };
+--- a/zebra/zebra_snmp.c
++++ b/zebra/zebra_snmp.c
+@@ -245,6 +245,12 @@ proto_trans(int type)
+       return 1; /* shouldn't happen */
+     case ZEBRA_ROUTE_BGP:
+       return 14; /* bgp */
++    case ZEBRA_ROUTE_HSLS:
++      return 1; /* other */
++    case ZEBRA_ROUTE_OLSR:
++      return 1; /* other */
++    case ZEBRA_ROUTE_BATMAN:
++      return 1; /* other */
+     default:
+       return 1; /* other */
+     }
+--- a/zebra/zebra_vty.c
++++ b/zebra/zebra_vty.c
+@@ -559,7 +559,10 @@ vty_show_ip_route_detail (struct vty *vt
+         || rib->type == ZEBRA_ROUTE_OSPF
+         || rib->type == ZEBRA_ROUTE_BABEL
+         || rib->type == ZEBRA_ROUTE_ISIS
+-        || rib->type == ZEBRA_ROUTE_BGP)
++        || rib->type == ZEBRA_ROUTE_BGP
++        || rib->type == ZEBRA_ROUTE_HSLS
++        || rib->type == ZEBRA_ROUTE_OLSR
++        || rib->type == ZEBRA_ROUTE_BATMAN)
+       {
+         time_t uptime;
+         struct tm *tm;
+@@ -754,7 +757,10 @@ vty_show_ip_route (struct vty *vty, stru
+         || rib->type == ZEBRA_ROUTE_OSPF
+         || rib->type == ZEBRA_ROUTE_BABEL
+         || rib->type == ZEBRA_ROUTE_ISIS
+-        || rib->type == ZEBRA_ROUTE_BGP)
++        || rib->type == ZEBRA_ROUTE_BGP
++        || rib->type == ZEBRA_ROUTE_HSLS
++        || rib->type == ZEBRA_ROUTE_OLSR
++        || rib->type == ZEBRA_ROUTE_BATMAN)
+       {
+         time_t uptime;
+         struct tm *tm;
+@@ -1550,7 +1556,10 @@ vty_show_ipv6_route_detail (struct vty *
+         || rib->type == ZEBRA_ROUTE_OSPF6
+         || rib->type == ZEBRA_ROUTE_BABEL
+         || rib->type == ZEBRA_ROUTE_ISIS
+-        || rib->type == ZEBRA_ROUTE_BGP)
++        || rib->type == ZEBRA_ROUTE_BGP
++        || rib->type == ZEBRA_ROUTE_HSLS
++        || rib->type == ZEBRA_ROUTE_OLSR
++        || rib->type == ZEBRA_ROUTE_BATMAN)
+       {
+         time_t uptime;
+         struct tm *tm;
+@@ -1692,7 +1701,10 @@ vty_show_ipv6_route (struct vty *vty, st
+         || rib->type == ZEBRA_ROUTE_OSPF6
+         || rib->type == ZEBRA_ROUTE_BABEL
+         || rib->type == ZEBRA_ROUTE_ISIS
+-        || rib->type == ZEBRA_ROUTE_BGP)
++        || rib->type == ZEBRA_ROUTE_BGP
++        || rib->type == ZEBRA_ROUTE_HSLS
++        || rib->type == ZEBRA_ROUTE_OLSR
++        || rib->type == ZEBRA_ROUTE_BATMAN)
+       {
+         time_t uptime;
+         struct tm *tm;
diff --git a/package/quagga/not-patches/patches-nopes/158-next-hop-self_all.patch b/package/quagga/not-patches/patches-nopes/158-next-hop-self_all.patch
new file mode 100644 (file)
index 0000000..6bfb800
--- /dev/null
@@ -0,0 +1,131 @@
+From: Timo Teräs <timo.teras@iki.fi>
+Date: Thu, 24 Apr 2014 07:22:37 +0000 (+0300)
+Subject: bgpd: implement "next-hop-self all"
+X-Git-Url: http://git.ozo.com/?p=quagga%2F.git;a=commitdiff_plain;h=9e7a53c179f6897128b24435452b5d3d0f8c715a
+
+bgpd: implement "next-hop-self all"
+
+As specified in:
+http://www.cisco.com/c/en/us/td/docs/ios-xml/ios/iproute_bgp/command/irg-cr-book/bgp-m1.html#wp4972925610
+
+This allows overriding next-hop for ibgp learned routes on an
+RR for reflected routes.
+
+Especially useful for using iBGP in DMVPN setups. See:
+http://blog.ipspace.net/2014/04/changes-in-ibgp-next-hop-processing.html
+
+Signed-off-by: Timo Teräs <timo.teras@iki.fi>
+---
+
+--- a/bgpd/bgp_route.c
++++ b/bgpd/bgp_route.c
+@@ -973,7 +973,8 @@ bgp_announce_check (struct bgp_info *ri,
+     }
+   /* next-hop-set */
+-  if (transparent || reflect
++  if (transparent
++      || (reflect && ! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_SELF_ALL))
+       || (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
+         && ((p->family == AF_INET && attr->nexthop.s_addr)
+ #ifdef HAVE_IPV6
+--- a/bgpd/bgp_vty.c
++++ b/bgpd/bgp_vty.c
+@@ -2093,25 +2093,41 @@ DEFUN (no_neighbor_capability_orf_prefix
+ /* neighbor next-hop-self. */
+ DEFUN (neighbor_nexthop_self,
+        neighbor_nexthop_self_cmd,
+-       NEIGHBOR_CMD2 "next-hop-self",
++       NEIGHBOR_CMD2 "next-hop-self {all}",
+        NEIGHBOR_STR
+        NEIGHBOR_ADDR_STR2
+-       "Disable the next hop calculation for this neighbor\n")
++       "Disable the next hop calculation for this neighbor\n"
++       "Apply also to ibgp-learned routes when acting as a route reflector\n")
+ {
+-  return peer_af_flag_set_vty (vty, argv[0], bgp_node_afi (vty),
+-                             bgp_node_safi (vty), PEER_FLAG_NEXTHOP_SELF);
++  u_int32_t flags = PEER_FLAG_NEXTHOP_SELF, unset = 0;
++  int rc;
++
++  /* Check if "all" is specified */
++  if (argv[1] != NULL)
++    flags |= PEER_FLAG_NEXTHOP_SELF_ALL;
++  else
++    unset |= PEER_FLAG_NEXTHOP_SELF_ALL;
++
++  rc = peer_af_flag_set_vty (vty, argv[0], bgp_node_afi (vty),
++                           bgp_node_safi (vty), flags);
++  if ( rc == CMD_SUCCESS && unset )
++    rc = peer_af_flag_unset_vty (vty, argv[0], bgp_node_afi (vty),
++                               bgp_node_safi (vty), unset);
++  return rc;
+ }
+ DEFUN (no_neighbor_nexthop_self,
+        no_neighbor_nexthop_self_cmd,
+-       NO_NEIGHBOR_CMD2 "next-hop-self",
++       NO_NEIGHBOR_CMD2 "next-hop-self {all}",
+        NO_STR
+        NEIGHBOR_STR
+        NEIGHBOR_ADDR_STR2
+-       "Disable the next hop calculation for this neighbor\n")
++       "Disable the next hop calculation for this neighbor\n"
++       "Apply also to ibgp-learned routes when acting as a route reflector\n")
+ {
+   return peer_af_flag_unset_vty (vty, argv[0], bgp_node_afi (vty),
+-                               bgp_node_safi (vty), PEER_FLAG_NEXTHOP_SELF);
++                               bgp_node_safi (vty),
++                               PEER_FLAG_NEXTHOP_SELF|PEER_FLAG_NEXTHOP_SELF_ALL);
+ }
+ /* neighbor remove-private-AS. */
+--- a/bgpd/bgpd.c
++++ b/bgpd/bgpd.c
+@@ -2355,6 +2355,7 @@ static const struct peer_flag_action pee
+     { PEER_FLAG_ORF_PREFIX_SM,            1, peer_change_reset },
+     { PEER_FLAG_ORF_PREFIX_RM,            1, peer_change_reset },
+     { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED,  0, peer_change_reset_out },
++    { PEER_FLAG_NEXTHOP_SELF_ALL,         1, peer_change_reset_out },
+     { 0, 0, 0 }
+   };
+@@ -4990,7 +4991,9 @@ bgp_config_write_peer (struct vty *vty,
+   /* Nexthop self. */
+   if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
+       && ! peer->af_group[afi][safi])
+-    vty_out (vty, " neighbor %s next-hop-self%s", addr, VTY_NEWLINE);
++    vty_out (vty, " neighbor %s next-hop-self%s%s", addr,
++           peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF_ALL) ?
++           " all" : "", VTY_NEWLINE);
+   /* Remove private AS. */
+   if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
+--- a/bgpd/bgpd.h
++++ b/bgpd/bgpd.h
+@@ -412,6 +412,7 @@ struct peer
+ #define PEER_FLAG_MAX_PREFIX                (1 << 14) /* maximum prefix */
+ #define PEER_FLAG_MAX_PREFIX_WARNING        (1 << 15) /* maximum prefix warning-only */
+ #define PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED   (1 << 16) /* leave link-local nexthop unchanged */
++#define PEER_FLAG_NEXTHOP_SELF_ALL          (1 << 17) /* next-hop-self all */
+   /* MD5 password */
+   char *password;
+--- a/doc/bgpd.texi
++++ b/doc/bgpd.texi
+@@ -299,10 +299,12 @@ This command is deprecated and may be re
+ use should be avoided.
+ @end deffn
+-@deffn {BGP} {neighbor @var{peer} next-hop-self} {}
+-@deffnx {BGP} {no neighbor @var{peer} next-hop-self} {}
++@deffn {BGP} {neighbor @var{peer} next-hop-self [all]} {}
++@deffnx {BGP} {no neighbor @var{peer} next-hop-self [all]} {}
+ This command specifies an announced route's nexthop as being equivalent
+-to the address of the bgp router.
++to the address of the bgp router if it is learned via eBGP.
++If the optional keyword @code{all} is specified the modifiation is done
++also for routes learned via iBGP.
+ @end deffn
+ @deffn {BGP} {neighbor @var{peer} update-source @var{<ifname|address>}} {}
diff --git a/package/quagga/not-patches/patches-nopes/159-share_aspath.patch b/package/quagga/not-patches/patches-nopes/159-share_aspath.patch
new file mode 100644 (file)
index 0000000..cd5a669
--- /dev/null
@@ -0,0 +1,115 @@
+From: Timo Teräs <timo.teras@iki.fi>
+Date: Tue, 20 May 2014 06:04:49 +0000 (+0300)
+Subject: bgpd: route-map: share aspath object compilation code where possible
+X-Git-Url: http://git.ozo.com/?p=quagga%2F.git;a=commitdiff_plain;h=b304dcb8abc4e5b93f86a4024990980746e730be
+
+bgpd: route-map: share aspath object compilation code where possible
+
+Signed-off-by: Timo Teräs <timo.teras@iki.fi>
+---
+
+--- a/bgpd/bgp_routemap.c
++++ b/bgpd/bgp_routemap.c
+@@ -101,6 +101,26 @@ o Local extention
+ */ 
++ /* generic as path object to be shared in multiple rules */
++
++static void *
++route_aspath_compile (const char *arg)
++{
++  struct aspath *aspath;
++
++  aspath = aspath_str2aspath (arg);
++  if (! aspath)
++    return NULL;
++  return aspath;
++}
++
++static void
++route_aspath_free (void *rule)
++{
++  struct aspath *aspath = rule;
++  aspath_free (aspath);
++}
++
+  /* 'match peer (A.B.C.D|X:X::X:X)' */
+ /* Compares the peer specified in the 'match peer' clause with the peer
+@@ -1228,33 +1248,13 @@ route_set_aspath_prepend (void *rule, st
+   return RMAP_OKAY;
+ }
+-/* Compile function for as-path prepend. */
+-static void *
+-route_set_aspath_prepend_compile (const char *arg)
+-{
+-  struct aspath *aspath;
+-
+-  aspath = aspath_str2aspath (arg);
+-  if (! aspath)
+-    return NULL;
+-  return aspath;
+-}
+-
+-/* Compile function for as-path prepend. */
+-static void
+-route_set_aspath_prepend_free (void *rule)
+-{
+-  struct aspath *aspath = rule;
+-  aspath_free (aspath);
+-}
+-
+ /* Set metric rule structure. */
+ struct route_map_rule_cmd route_set_aspath_prepend_cmd = 
+ {
+   "as-path prepend",
+   route_set_aspath_prepend,
+-  route_set_aspath_prepend_compile,
+-  route_set_aspath_prepend_free,
++  route_aspath_compile,
++  route_aspath_free,
+ };
+ /* `set as-path exclude ASn' */
+@@ -1282,37 +1282,13 @@ route_set_aspath_exclude (void *rule, st
+   return RMAP_OKAY;
+ }
+-/* FIXME: consider using route_set_aspath_prepend_compile() and
+- * route_set_aspath_prepend_free(), which two below function are
+- * exact clones of.
+- */
+-
+-/* Compile function for as-path exclude. */
+-static void *
+-route_set_aspath_exclude_compile (const char *arg)
+-{
+-  struct aspath *aspath;
+-
+-  aspath = aspath_str2aspath (arg);
+-  if (! aspath)
+-    return NULL;
+-  return aspath;
+-}
+-
+-static void
+-route_set_aspath_exclude_free (void *rule)
+-{
+-  struct aspath *aspath = rule;
+-  aspath_free (aspath);
+-}
+-
+ /* Set ASn exlude rule structure. */
+ struct route_map_rule_cmd route_set_aspath_exclude_cmd = 
+ {
+   "as-path exclude",
+   route_set_aspath_exclude,
+-  route_set_aspath_exclude_compile,
+-  route_set_aspath_exclude_free,
++  route_aspath_compile,
++  route_aspath_free,
+ };
+ /* `set community COMMUNITY' */
diff --git a/package/quagga/not-patches/patches-old/100-bgpd_Display_configured_dampening_parameters.patch b/package/quagga/not-patches/patches-old/100-bgpd_Display_configured_dampening_parameters.patch
new file mode 100644 (file)
index 0000000..ecbda67
--- /dev/null
@@ -0,0 +1,70 @@
+From 06bd420d4646333bc7ed9964e348f19a942fcfe2 Mon Sep 17 00:00:00 2001
+From: Balaji <balajig81@gmail.com>
+Date: Mon, 16 Mar 2015 16:55:29 +0000
+Subject: [PATCH] bgpd: Display of configured dampening parameters
+
+Function to display configured bgp dampening parameters.
+
+Signed-off-by: Balaji.G <balajig81@gmail.com>
+[DL: formatting adjustments]
+Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
+---
+ bgpd/bgp_damp.c | 33 +++++++++++++++++++++++++++++++++
+ bgpd/bgp_damp.h |  2 ++
+ 2 files changed, 35 insertions(+)
+
+diff --git a/bgpd/bgp_damp.c b/bgpd/bgp_damp.c
+index 0ffafb7..dd6c759 100644
+--- a/bgpd/bgp_damp.c
++++ b/bgpd/bgp_damp.c
+@@ -639,3 +639,36 @@ bgp_damp_reuse_time_vty (struct vty *vty, struct bgp_info *binfo,
+   return  bgp_get_reuse_time (penalty, timebuf, len);
+ }
++
++int
++bgp_show_dampening_parameters (struct vty *vty, afi_t afi, safi_t safi)
++{
++  struct bgp *bgp;
++  bgp = bgp_get_default();
++
++  if (bgp == NULL)
++    {
++      vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE);
++      return CMD_WARNING;
++    }
++
++  if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING))
++    {
++      vty_out (vty, "Half-life time: %ld min%s",
++                    damp->half_life / 60, VTY_NEWLINE);
++      vty_out (vty, "Reuse penalty: %d%s",
++                    damp->reuse_limit, VTY_NEWLINE);
++      vty_out (vty, "Suppress penalty: %d%s",
++                    damp->suppress_value, VTY_NEWLINE);
++      vty_out (vty, "Max suppress time: %ld min%s",
++                    damp->max_suppress_time / 60, VTY_NEWLINE);
++      vty_out (vty, "Max supress penalty: %u%s",
++                    damp->ceiling, VTY_NEWLINE);
++      vty_out (vty, "%s", VTY_NEWLINE);
++    }
++  else
++    vty_out (vty, "dampening not enabled for %s%s",
++                  afi == AFI_IP ? "IPv4" : "IPv6", VTY_NEWLINE);
++
++  return CMD_SUCCESS;
++}
+diff --git a/bgpd/bgp_damp.h b/bgpd/bgp_damp.h
+index e1d319b..16fd367 100644
+--- a/bgpd/bgp_damp.h
++++ b/bgpd/bgp_damp.h
+@@ -144,4 +144,6 @@ extern void bgp_damp_info_vty (struct vty *, struct bgp_info *);
+ extern const char * bgp_damp_reuse_time_vty (struct vty *, struct bgp_info *,
+                                              char *, size_t);
++extern int bgp_show_dampening_parameters (struct vty *vty, afi_t, safi_t);
++
+ #endif /* _QUAGGA_BGP_DAMP_H */
+-- 
+2.7.0
+
diff --git a/package/quagga/not-patches/patches-old/110-bgpd_suppress_value_not_less_reuse_value.patch b/package/quagga/not-patches/patches-old/110-bgpd_suppress_value_not_less_reuse_value.patch
new file mode 100644 (file)
index 0000000..e549f61
--- /dev/null
@@ -0,0 +1,36 @@
+From aa7dbb1067b7d02e1354fe1e5664ccb7d259d649 Mon Sep 17 00:00:00 2001
+From: Balaji <balajig81@gmail.com>
+Date: Mon, 16 Mar 2015 16:55:26 +0000
+Subject: [PATCH] bgpd: Configured suppress value cannot be less than the reuse
+ value in bgp dampening
+
+RFC 2439, Section 4.2; the values pair up for hysteresis.
+
+Signed-off-by: Balaji.G <balajig81@gmail.com>
+Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
+---
+ bgpd/bgp_route.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
+index e7357e5..f84a72d 100644
+--- a/bgpd/bgp_route.c
++++ b/bgpd/bgp_route.c
+@@ -11976,6 +11976,14 @@ DEFUN (bgp_damp_set,
+     }
+   bgp = vty->index;
++
++  if (suppress < reuse)
++    {
++      vty_out (vty, "Suppress value cannot be less than reuse value %s",
++                    VTY_NEWLINE);
++      return 0;
++    }
++
+   return bgp_damp_enable (bgp, bgp_node_afi (vty), bgp_node_safi (vty),
+                         half, reuse, suppress, max);
+ }
+-- 
+2.7.0
+
diff --git a/package/quagga/not-patches/patches-old/130-bgpd_ignore_stale_entry.patch b/package/quagga/not-patches/patches-old/130-bgpd_ignore_stale_entry.patch
new file mode 100644 (file)
index 0000000..33a8610
--- /dev/null
@@ -0,0 +1,52 @@
+From bd4b7f1559ab5cb52bbe9dc2db9e50a032ccdbb7 Mon Sep 17 00:00:00 2001
+From: vivek <vivek@cumulusnetworks.com>
+Date: Tue, 30 Sep 2014 15:54:45 -0700
+Subject: [PATCH] bgpd: Ignore stale entry candidates during bestpath
+ selection.
+
+During best path selection, if one of the candidates is a stale entry, do not
+perform the neighbor address comparison as that information is invalid for
+the stale entry. Attempting to perform the comparison results in a bgpd
+exception.
+
+Signed-off-by: Vivek Venkataraman <vivek@cumulusnetworks.com>
+Reviewed-by: Dinesh G Dutt <ddutt@cumulusnetworks.com>
+---
+ bgpd/bgp_route.c | 14 +++++++++++++-
+ 1 file changed, 13 insertions(+), 1 deletion(-)
+
+diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
+index 34ba1ab..648dc9c 100644
+--- a/bgpd/bgp_route.c
++++ b/bgpd/bgp_route.c
+@@ -524,7 +524,11 @@ bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist,
+       return 0;
+     }
+-  /* 11. Rourter-ID comparision. */
++  /* 11. Router-ID comparision. */
++  /* If one of the paths is "stale", the corresponding peer router-id will
++   * be 0 and would always win over the other path. If originator id is
++   * used for the comparision, it will decide which path is better.
++   */
+   if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
+     new_id.s_addr = newattre->originator_id.s_addr;
+   else
+@@ -553,6 +557,14 @@ bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist,
+     return 0;
+   /* 13. Neighbor address comparision. */
++  /* Do this only if neither path is "stale" as stale paths do not have
++   * valid peer information (as the connection may or may not be up).
++   */
++  if (CHECK_FLAG (exist->flags, BGP_INFO_STALE))
++    return 1;
++  if (CHECK_FLAG (new->flags, BGP_INFO_STALE))
++    return 0;
++
+   ret = sockunion_cmp (new->peer->su_remote, exist->peer->su_remote);
+   if (ret == 1)
+-- 
+2.7.0
+
diff --git a/package/quagga/not-patches/patches-old/140-bgpd-routes_from_established_peers.patch b/package/quagga/not-patches/patches-old/140-bgpd-routes_from_established_peers.patch
new file mode 100644 (file)
index 0000000..cf0516f
--- /dev/null
@@ -0,0 +1,63 @@
+From 234e5c8d5a35339fb319affb952581bf5abb48a7 Mon Sep 17 00:00:00 2001
+From: Dinesh G Dutt <ddutt@cumulusnetworks.com>
+Date: Sun, 1 Feb 2015 00:56:12 -0800
+Subject: [PATCH] bgpd: Only use routes from Established peers for best path
+ selection
+
+Ensure that routes from a peer are not considered for best path
+comparison if the peer is not in an Established state. There can
+be a window between a peer being deleted and the background
+thread that actually clears the routes (marks them as "removed")
+runs during which best path may run. If this path selection
+compared two prefixes all the way down to peer IP addresses and
+one of these two peers had just been deleted, that peer would
+not have its sockunion structures, especially su_remote, resulting
+in a BGPD exception.
+
+Signed-off-by: Vivek Venkatraman <vivek@cumulusnetworks.com>
+---
+ bgpd/bgp_route.c | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
+index 648dc9c..02c926f 100644
+--- a/bgpd/bgp_route.c
++++ b/bgpd/bgp_route.c
+@@ -1345,6 +1345,9 @@ bgp_best_selection (struct bgp *bgp, struct bgp_node *rn,
+         continue;
+       if (BGP_INFO_HOLDDOWN (ri1))
+         continue;
++        if (ri1->peer && ri1->peer != bgp->peer_self)
++          if (ri1->peer->status != Established)
++            continue;
+       new_select = ri1;
+       if (do_mpath)
+@@ -1357,6 +1360,11 @@ bgp_best_selection (struct bgp *bgp, struct bgp_node *rn,
+               continue;
+             if (BGP_INFO_HOLDDOWN (ri2))
+               continue;
++              if (ri2->peer &&
++                  ri2->peer != bgp->peer_self &&
++                  !CHECK_FLAG (ri2->peer->sflags, PEER_STATUS_NSF_WAIT))
++                if (ri2->peer->status != Established)
++                  continue;
+             if (aspath_cmp_left (ri1->attr->aspath, ri2->attr->aspath)
+                 || aspath_cmp_left_confed (ri1->attr->aspath,
+@@ -1408,6 +1416,12 @@ bgp_best_selection (struct bgp *bgp, struct bgp_node *rn,
+           continue;
+         }
++      if (ri->peer &&
++          ri->peer != bgp->peer_self &&
++          !CHECK_FLAG (ri->peer->sflags, PEER_STATUS_NSF_WAIT))
++        if (ri->peer->status != Established)
++          continue;
++
+       if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED)
+           && (! CHECK_FLAG (ri->flags, BGP_INFO_DMED_SELECTED)))
+       {
+-- 
+2.7.0
+
diff --git a/package/quagga/not-patches/patches-old/160-bgpd-enable_bgp_log-neighbor-changes.patch b/package/quagga/not-patches/patches-old/160-bgpd-enable_bgp_log-neighbor-changes.patch
new file mode 100644 (file)
index 0000000..f6a7783
--- /dev/null
@@ -0,0 +1,37 @@
+From c37b9bccdcc1266f52e50fa3e5a8dc81086c3fe7 Mon Sep 17 00:00:00 2001
+From: Daniel Walton <dwalton@cumulusnetworks.com>
+Date: Wed, 21 Oct 2015 06:42:50 -0700
+Subject: [PATCH] bgpd: Enable "bgp log-neighbor-changes" by default
+
+Signed-off-by: Daniel Walton <dwalton@cumulusnetworks.com>
+Reviewed-by:   Donald Sharp <sharpd@cumulusnetworks.com>
+---
+ bgpd/bgpd.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
+index c94c381..c7f22e8 100644
+--- a/bgpd/bgpd.c
++++ b/bgpd/bgpd.c
+@@ -1974,6 +1974,7 @@ bgp_create (as_t *as, const char *name)
+   bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
+   bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
+   bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
++  bgp_flag_set (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES);
+   bgp->as = *as;
+@@ -5259,8 +5260,8 @@ bgp_config_write (struct vty *vty)
+                VTY_NEWLINE);
+       /* BGP log-neighbor-changes. */
+-      if (bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
+-      vty_out (vty, " bgp log-neighbor-changes%s", VTY_NEWLINE);
++      if (!bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
++      vty_out (vty, " no bgp log-neighbor-changes%s", VTY_NEWLINE);
+       /* BGP configuration. */
+       if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
+-- 
+2.7.0
+
diff --git a/package/quagga/not-patches/patches-old/220-bgpd_dampening_command_tree.patch b/package/quagga/not-patches/patches-old/220-bgpd_dampening_command_tree.patch
new file mode 100644 (file)
index 0000000..63a05de
--- /dev/null
@@ -0,0 +1,251 @@
+diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
+index 34cb7c0..438fb0c 100644
+--- a/bgpd/bgp_route.c
++++ b/bgpd/bgp_route.c
+@@ -7169,6 +7169,17 @@ DEFUN (show_ip_bgp_flap_regexp,
+                         bgp_show_type_flap_regexp);
+ }
++ALIAS (show_ip_bgp_flap_regexp,
++       show_ip_bgp_damp_flap_regexp_cmd,
++       "show ip bgp dampening flap-statistics regexp .LINE",
++       SHOW_STR
++       IP_STR
++       BGP_STR
++       "Display detailed information about dampening\n"
++       "Display flap statistics of routes\n"
++       "Display routes matching the AS path regular expression\n"
++       "A regular-expression to match the BGP AS paths\n")
++
+ DEFUN (show_ip_bgp_ipv4_regexp, 
+        show_ip_bgp_ipv4_regexp_cmd,
+        "show ip bgp ipv4 (unicast|multicast) regexp .LINE",
+@@ -7284,6 +7295,17 @@ DEFUN (show_ip_bgp_flap_prefix_list,
+                              bgp_show_type_flap_prefix_list);
+ }
++ALIAS (show_ip_bgp_flap_prefix_list,
++       show_ip_bgp_damp_flap_prefix_list_cmd,
++       "show ip bgp dampening flap-statistics prefix-list WORD",
++       SHOW_STR
++       IP_STR
++       BGP_STR
++       "Display detailed information about dampening\n"
++       "Display flap statistics of routes\n"
++       "Display routes conforming to the prefix-list\n"
++       "IP prefix-list name\n")
++
+ DEFUN (show_ip_bgp_ipv4_prefix_list, 
+        show_ip_bgp_ipv4_prefix_list_cmd,
+        "show ip bgp ipv4 (unicast|multicast) prefix-list WORD",
+@@ -7398,6 +7420,17 @@ DEFUN (show_ip_bgp_flap_filter_list,
+                              bgp_show_type_flap_filter_list);
+ }
++ALIAS (show_ip_bgp_flap_filter_list, 
++       show_ip_bgp_damp_flap_filter_list_cmd,
++       "show ip bgp dampening flap-statistics filter-list WORD",
++       SHOW_STR
++       IP_STR
++       BGP_STR
++       "Display detailed information about dampening\n"
++       "Display flap statistics of routes\n"
++       "Display routes conforming to the filter-list\n"
++       "Regular expression access list name\n")
++
+ DEFUN (show_ip_bgp_ipv4_filter_list, 
+        show_ip_bgp_ipv4_filter_list_cmd,
+        "show ip bgp ipv4 (unicast|multicast) filter-list WORD",
+@@ -7469,6 +7502,18 @@ DEFUN (show_ipv6_mbgp_filter_list,
+ }
+ #endif /* HAVE_IPV6 */
++DEFUN (show_ip_bgp_dampening_info,
++       show_ip_bgp_dampening_params_cmd,
++       "show ip bgp dampening parameters",
++       SHOW_STR
++       IP_STR
++       BGP_STR
++       "Display detailed information about dampening\n"
++       "Display detail of configured dampening parameters\n")
++{
++    return bgp_show_dampening_parameters (vty, AFI_IP, SAFI_UNICAST);
++}
++
+ static int
+ bgp_show_route_map (struct vty *vty, const char *rmap_str, afi_t afi,
+                   safi_t safi, enum bgp_show_type type)
+@@ -7513,6 +7558,17 @@ DEFUN (show_ip_bgp_flap_route_map,
+                            bgp_show_type_flap_route_map);
+ }
++ALIAS (show_ip_bgp_flap_route_map, 
++       show_ip_bgp_damp_flap_route_map_cmd,
++       "show ip bgp dampening flap-statistics route-map WORD",
++       SHOW_STR
++       IP_STR
++       BGP_STR
++       "Display detailed information about dampening\n"
++       "Display flap statistics of routes\n"
++       "Display routes matching the route-map\n"
++       "A route-map to match on\n")
++
+ DEFUN (show_ip_bgp_ipv4_route_map, 
+        show_ip_bgp_ipv4_route_map_cmd,
+        "show ip bgp ipv4 (unicast|multicast) route-map WORD",
+@@ -7579,6 +7635,16 @@ DEFUN (show_ip_bgp_flap_cidr_only,
+                  bgp_show_type_flap_cidr_only, NULL);
+ }
++ALIAS (show_ip_bgp_flap_cidr_only,
++       show_ip_bgp_damp_flap_cidr_only_cmd,
++       "show ip bgp dampening flap-statistics cidr-only",
++       SHOW_STR
++       IP_STR
++       BGP_STR
++       "Display detailed information about dampening\n"
++       "Display flap statistics of routes\n"
++       "Display only routes with non-natural netmasks\n")
++
+ DEFUN (show_ip_bgp_ipv4_cidr_only,
+        show_ip_bgp_ipv4_cidr_only_cmd,
+        "show ip bgp ipv4 (unicast|multicast) cidr-only",
+@@ -9062,6 +9128,17 @@ DEFUN (show_ip_bgp_flap_prefix_longer,
+                                bgp_show_type_flap_prefix_longer);
+ }
++ALIAS (show_ip_bgp_flap_prefix_longer,
++       show_ip_bgp_damp_flap_prefix_longer_cmd,
++       "show ip bgp dampening flap-statistics A.B.C.D/M longer-prefixes",
++       SHOW_STR
++       IP_STR
++       BGP_STR
++       "Display detailed information about dampening\n"
++       "Display flap statistics of routes\n"
++       "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
++       "Display route and more specific routes\n")
++
+ DEFUN (show_ip_bgp_ipv4_prefix_longer,
+        show_ip_bgp_ipv4_prefix_longer_cmd,
+        "show ip bgp ipv4 (unicast|multicast) A.B.C.D/M longer-prefixes",
+@@ -9095,6 +9172,16 @@ DEFUN (show_ip_bgp_flap_address,
+                                bgp_show_type_flap_address);
+ }
++ALIAS (show_ip_bgp_flap_address,
++       show_ip_bgp_damp_flap_address_cmd,
++       "show ip bgp dampening flap-statistics A.B.C.D",
++       SHOW_STR
++       IP_STR
++       BGP_STR
++       "Display detailed information about dampening\n"
++       "Display flap statistics of routes\n"
++       "Network in the BGP routing table to display\n")
++
+ DEFUN (show_ip_bgp_flap_prefix,
+        show_ip_bgp_flap_prefix_cmd,
+        "show ip bgp flap-statistics A.B.C.D/M",
+@@ -9107,6 +9194,17 @@ DEFUN (show_ip_bgp_flap_prefix,
+   return bgp_show_prefix_longer (vty, argv[0], AFI_IP, SAFI_UNICAST,
+                                bgp_show_type_flap_prefix);
+ }
++
++ALIAS (show_ip_bgp_flap_prefix,
++       show_ip_bgp_damp_flap_prefix_cmd,
++       "show ip bgp dampening flap-statistics A.B.C.D/M",
++       SHOW_STR
++       IP_STR
++       BGP_STR
++       "Display detailed information about dampening\n"
++       "Display flap statistics of routes\n"
++       "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
++
+ #ifdef HAVE_IPV6
+ DEFUN (show_bgp_prefix_longer,
+        show_bgp_prefix_longer_cmd,
+@@ -11981,6 +12079,15 @@ DEFUN (show_ip_bgp_dampened_paths,
+                    NULL);
+ }
++ALIAS (show_ip_bgp_dampened_paths,
++       show_ip_bgp_damp_dampened_paths_cmd,
++       "show ip bgp dampening dampened-paths",
++       SHOW_STR
++       IP_STR
++       BGP_STR
++       "Display detailed information about dampening\n"
++       "Display paths suppressed due to dampening\n")
++
+ DEFUN (show_ip_bgp_flap_statistics,
+        show_ip_bgp_flap_statistics_cmd,
+        "show ip bgp flap-statistics",
+@@ -11993,6 +12100,15 @@ DEFUN (show_ip_bgp_flap_statistics,
+                    bgp_show_type_flap_statistics, NULL);
+ }
++ALIAS (show_ip_bgp_flap_statistics,
++       show_ip_bgp_damp_flap_statistics_cmd,
++       "show ip bgp dampening flap-statistics",
++       SHOW_STR
++       IP_STR
++       BGP_STR
++       "Display detailed information about dampening\n"
++       "Display flap statistics of routes\n")
++
+ /* Display specified route of BGP table. */
+ static int
+ bgp_clear_damp_route (struct vty *vty, const char *view_name, 
+@@ -12506,16 +12622,25 @@ bgp_route_init (void)
+   install_element (VIEW_NODE, &show_ip_bgp_ipv4_neighbor_routes_cmd);
+   install_element (VIEW_NODE, &show_ip_bgp_neighbor_received_prefix_filter_cmd);
+   install_element (VIEW_NODE, &show_ip_bgp_ipv4_neighbor_received_prefix_filter_cmd);
++  install_element (VIEW_NODE, &show_ip_bgp_dampening_params_cmd);
+   install_element (VIEW_NODE, &show_ip_bgp_dampened_paths_cmd);
++  install_element (VIEW_NODE, &show_ip_bgp_damp_dampened_paths_cmd);
+   install_element (VIEW_NODE, &show_ip_bgp_flap_statistics_cmd);
++  install_element (VIEW_NODE, &show_ip_bgp_damp_flap_statistics_cmd);
+   install_element (VIEW_NODE, &show_ip_bgp_flap_address_cmd);
++  install_element (VIEW_NODE, &show_ip_bgp_damp_flap_address_cmd);
+   install_element (VIEW_NODE, &show_ip_bgp_flap_prefix_cmd);
+   install_element (VIEW_NODE, &show_ip_bgp_flap_cidr_only_cmd);
++  install_element (VIEW_NODE, &show_ip_bgp_damp_flap_cidr_only_cmd);
+   install_element (VIEW_NODE, &show_ip_bgp_flap_regexp_cmd);
+   install_element (VIEW_NODE, &show_ip_bgp_flap_filter_list_cmd);
++  install_element (VIEW_NODE, &show_ip_bgp_damp_flap_filter_list_cmd);
+   install_element (VIEW_NODE, &show_ip_bgp_flap_prefix_list_cmd);
++  install_element (VIEW_NODE, &show_ip_bgp_damp_flap_prefix_list_cmd);
+   install_element (VIEW_NODE, &show_ip_bgp_flap_prefix_longer_cmd);
++  install_element (VIEW_NODE, &show_ip_bgp_damp_flap_prefix_longer_cmd);
+   install_element (VIEW_NODE, &show_ip_bgp_flap_route_map_cmd);
++  install_element (VIEW_NODE, &show_ip_bgp_damp_flap_route_map_cmd);
+   install_element (VIEW_NODE, &show_ip_bgp_neighbor_flap_cmd);
+   install_element (VIEW_NODE, &show_ip_bgp_neighbor_damp_cmd);
+   install_element (VIEW_NODE, &show_ip_bgp_rsclient_cmd);
+@@ -12639,16 +12764,27 @@ bgp_route_init (void)
+   install_element (ENABLE_NODE, &show_ip_bgp_ipv4_neighbor_routes_cmd);
+   install_element (ENABLE_NODE, &show_ip_bgp_neighbor_received_prefix_filter_cmd);
+   install_element (ENABLE_NODE, &show_ip_bgp_ipv4_neighbor_received_prefix_filter_cmd);
++  install_element (ENABLE_NODE, &show_ip_bgp_dampening_params_cmd);
+   install_element (ENABLE_NODE, &show_ip_bgp_dampened_paths_cmd);
++  install_element (ENABLE_NODE, &show_ip_bgp_damp_dampened_paths_cmd);
+   install_element (ENABLE_NODE, &show_ip_bgp_flap_statistics_cmd);
++  install_element (ENABLE_NODE, &show_ip_bgp_damp_flap_statistics_cmd);
+   install_element (ENABLE_NODE, &show_ip_bgp_flap_address_cmd);
++  install_element (ENABLE_NODE, &show_ip_bgp_damp_flap_address_cmd);
+   install_element (ENABLE_NODE, &show_ip_bgp_flap_prefix_cmd);
+   install_element (ENABLE_NODE, &show_ip_bgp_flap_cidr_only_cmd);
++  install_element (ENABLE_NODE, &show_ip_bgp_damp_flap_cidr_only_cmd);
+   install_element (ENABLE_NODE, &show_ip_bgp_flap_regexp_cmd);
++  install_element (ENABLE_NODE, &show_ip_bgp_damp_flap_regexp_cmd);
+   install_element (ENABLE_NODE, &show_ip_bgp_flap_filter_list_cmd);
++  install_element (ENABLE_NODE, &show_ip_bgp_damp_flap_filter_list_cmd);
+   install_element (ENABLE_NODE, &show_ip_bgp_flap_prefix_list_cmd);
++  install_element (ENABLE_NODE, &show_ip_bgp_damp_flap_prefix_list_cmd);
++  install_element (ENABLE_NODE, &show_ip_bgp_damp_flap_prefix_list_cmd);
+   install_element (ENABLE_NODE, &show_ip_bgp_flap_prefix_longer_cmd);
++  install_element (ENABLE_NODE, &show_ip_bgp_damp_flap_prefix_longer_cmd);
+   install_element (ENABLE_NODE, &show_ip_bgp_flap_route_map_cmd);
++  install_element (ENABLE_NODE, &show_ip_bgp_damp_flap_route_map_cmd);
+   install_element (ENABLE_NODE, &show_ip_bgp_neighbor_flap_cmd);
+   install_element (ENABLE_NODE, &show_ip_bgp_neighbor_damp_cmd);
+   install_element (ENABLE_NODE, &show_ip_bgp_rsclient_cmd);
diff --git a/package/quagga/not-patches/patches-old/nopes/180-bgpd-lower_default_keepalive_holdtime.patch b/package/quagga/not-patches/patches-old/nopes/180-bgpd-lower_default_keepalive_holdtime.patch
new file mode 100644 (file)
index 0000000..d0476f5
--- /dev/null
@@ -0,0 +1,29 @@
+From f89b09be92bed03b1e5add55dc14ef92e94c52e1 Mon Sep 17 00:00:00 2001
+From: Daniel Walton <dwalton@cumulusnetworks.com>
+Date: Wed, 21 Oct 2015 06:42:52 -0700
+Subject: [PATCH] bgpd: Lower BGP's default keepalive/holdtime to 3s/9s
+
+Signed-off-by: Daniel Walton <dwalton@cumulusnetworks.com>
+Reviewed-by:   Donald Sharp <sharpd@cumulusnetworks.com>
+---
+ bgpd/bgpd.h | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
+index 105912e..d4c8dbd 100644
+--- a/bgpd/bgpd.h
++++ b/bgpd/bgpd.h
+@@ -742,8 +742,8 @@ struct bgp_nlri
+ /* BGP timers default value.  */
+ #define BGP_INIT_START_TIMER                     5
+-#define BGP_DEFAULT_HOLDTIME                   180
+-#define BGP_DEFAULT_KEEPALIVE                   60 
++#define BGP_DEFAULT_HOLDTIME                     9
++#define BGP_DEFAULT_KEEPALIVE                    3
+ #define BGP_DEFAULT_EBGP_ROUTEADV               30
+ #define BGP_DEFAULT_IBGP_ROUTEADV                5
+ #define BGP_CLEAR_CONNECT_RETRY                 20
+-- 
+2.7.0
+
diff --git a/package/quagga/not-patches/patches-old/nopes/200-bgpd-implicit_updates_withdrawal_from_zebra.patch b/package/quagga/not-patches/patches-old/nopes/200-bgpd-implicit_updates_withdrawal_from_zebra.patch
new file mode 100644 (file)
index 0000000..0117d03
--- /dev/null
@@ -0,0 +1,125 @@
+From 64e0ac29ddc43bb5b1a2999a8ebedbdff115e3ca Mon Sep 17 00:00:00 2001
+From: Paul Jakma <paul.jakma@hpe.com>
+Date: Wed, 18 Nov 2015 16:00:54 +0000
+Subject: [PATCH] bgpd: Implicit updates in BGP may require a withdrawal from
+ zebra RIB
+
+*  J Yu <jackiesyu@hotmail.com> noted a problem with bgpd of routes not
+   having their nexthop updated correctly.
+
+   Martin Winter <mwinter@opensourcerouting.org> pinned this down to the
+   case where a BGP route is updated from one with a valid nexthop to an
+   invalid next-hop, using a test tool. Once the problem occurs, the incorrect
+   route may remain, even after further UPDATEs, so long as the nexthop in the
+   zebra RIB does not match the BGP route's nexthop.
+
+   Jacqueline Yu then pinned the issue down further to being due to bgpd
+   sending the DELETE for the route to zebra with the new nexthop after a
+   BGP UPDATE updates an existing route, but then is found to be invalid,
+   and zebra not finding the route as it requires a match on all attributes.
+
+* bgp_zebra.c: (bgp_zebra_withdraw) When deleting a prefix, we want it gone.
+  Do not send additional matching attributes like the nexthop, which can
+  only cause incorrect non-matches.
+Acked-by: Donald Sharp <sharpd@cumulusnetworks.com>
+---
+ bgpd/bgp_zebra.c | 46 +++++-----------------------------------------
+ 1 file changed, 5 insertions(+), 41 deletions(-)
+
+diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
+index e534bee..186657b 100644
+--- a/bgpd/bgp_zebra.c
++++ b/bgpd/bgp_zebra.c
+@@ -863,18 +863,14 @@ bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info, safi_t safi)
+   if (p->family == AF_INET)
+     {
+       struct zapi_ipv4 api;
+-      struct in_addr *nexthop;
+       api.vrf_id = VRF_DEFAULT;
+       api.flags = flags;
+-      nexthop = &info->attr->nexthop;
+       api.type = ZEBRA_ROUTE_BGP;
+       api.message = 0;
+       api.safi = safi;
+-      SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
+-      api.nexthop_num = 1;
+-      api.nexthop = &nexthop;
++      api.nexthop_num = 0;
+       api.ifindex_num = 0;
+       SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
+       api.metric = info->attr->med;
+@@ -882,10 +878,9 @@ bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info, safi_t safi)
+       if (BGP_DEBUG(zebra, ZEBRA))
+       {
+         char buf[2][INET_ADDRSTRLEN];
+-        zlog_debug("Zebra send: IPv4 route delete %s/%d nexthop %s metric %u",
++        zlog_debug("Zebra send: IPv4 route delete %s/%d metric %u",
+                    inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])),
+                    p->prefixlen,
+-                   inet_ntop(AF_INET, nexthop, buf[1], sizeof(buf[1])),
+                    api.metric);
+       }
+@@ -897,54 +892,23 @@ bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info, safi_t safi)
+   if (p->family == AF_INET6)
+     {
+       struct zapi_ipv6 api;
+-      unsigned int ifindex;
+-      struct in6_addr *nexthop;
+-      
+-      assert (info->attr->extra);
+       
+-      ifindex = 0;
+-      nexthop = NULL;
+-
+-      /* Only global address nexthop exists. */
+-      if (info->attr->extra->mp_nexthop_len == 16)
+-      nexthop = &info->attr->extra->mp_nexthop_global;
+-
+-      /* If both global and link-local address present. */
+-      if (info->attr->extra->mp_nexthop_len == 32)
+-      {
+-        nexthop = &info->attr->extra->mp_nexthop_local;
+-        if (info->peer->nexthop.ifp)
+-          ifindex = info->peer->nexthop.ifp->ifindex;
+-      }
+-
+-      if (nexthop == NULL)
+-      return;
+-
+-      if (IN6_IS_ADDR_LINKLOCAL (nexthop) && ! ifindex)
+-      if (info->peer->ifname)
+-        ifindex = ifname2ifindex (info->peer->ifname);
+-
+       api.vrf_id = VRF_DEFAULT;
+       api.flags = flags;
+       api.type = ZEBRA_ROUTE_BGP;
+       api.message = 0;
+       api.safi = safi;
+-      SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
+-      api.nexthop_num = 1;
+-      api.nexthop = &nexthop;
+-      SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
+-      api.ifindex_num = 1;
+-      api.ifindex = &ifindex;
++      api.nexthop_num = 0;
++      api.ifindex_num = 0;
+       SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
+       api.metric = info->attr->med;
+       if (BGP_DEBUG(zebra, ZEBRA))
+       {
+         char buf[2][INET6_ADDRSTRLEN];
+-        zlog_debug("Zebra send: IPv6 route delete %s/%d nexthop %s metric %u",
++        zlog_debug("Zebra send: IPv6 route delete %s/%d metric %u",
+                    inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])),
+                    p->prefixlen,
+-                   inet_ntop(AF_INET6, nexthop, buf[1], sizeof(buf[1])),
+                    api.metric);
+       }
+-- 
+2.7.0
+
diff --git a/package/quagga/not-patches/patches-pgbgp/140-holdtimer-set.patch b/package/quagga/not-patches/patches-pgbgp/140-holdtimer-set.patch
new file mode 100644 (file)
index 0000000..83482d3
--- /dev/null
@@ -0,0 +1,22 @@
+--- a/bgpd/bgp_network.c
++++ b/bgpd/bgp_network.c
+@@ -256,8 +256,7 @@ bgp_accept (struct thread *thread)
+     peer->fd = bgp_sock;
+     peer->status = Active;
+     peer->local_id = peer1->local_id;
+-    peer->v_holdtime = peer1->v_holdtime;
+-    peer->v_keepalive = peer1->v_keepalive;
++    peer->v_holdtime = BGP_LARGE_HOLDTIME;
+     /* Make peer's address string. */
+     sockunion2str (&su, buf, SU_ADDRSTRLEN);
+--- a/bgpd/bgpd.h
++++ b/bgpd/bgpd.h
+@@ -739,6 +739,7 @@ struct bgp_nlri
+ /* BGP timers default value.  */
+ #define BGP_INIT_START_TIMER                     5
+ #define BGP_ERROR_START_TIMER                   30
++#define BGP_LARGE_HOLDTIME                     240
+ #define BGP_DEFAULT_HOLDTIME                   180
+ #define BGP_DEFAULT_KEEPALIVE                   60 
+ #define BGP_DEFAULT_ASORIGINATE                 15
diff --git a/package/quagga/not-patches/patches-pgbgp/150-no-cross-fs-link.patch b/package/quagga/not-patches/patches-pgbgp/150-no-cross-fs-link.patch
new file mode 100644 (file)
index 0000000..a8e9f84
--- /dev/null
@@ -0,0 +1,40 @@
+--- a/lib/command.c
++++ b/lib/command.c
+@@ -3064,6 +3064,13 @@ DEFUN (config_write_file,
+                VTY_NEWLINE);
+         goto finished;
+       }
++
++#if 0
++  /* This code fails on UNION MOUNTs and similar filesystems if the
++   * config file is still on the RO layer. Hardlinks across layers
++   * will not work and cause quagga to fail saving the configuration...
++   * should use rename() to move files around...
++   */
+   if (link (config_file, config_file_sav) != 0)
+     {
+       vty_out (vty, "Can't backup old configuration file %s.%s", config_file_sav,
+@@ -3077,7 +3084,23 @@ DEFUN (config_write_file,
+               VTY_NEWLINE);
+       goto finished;
+     }
++#else
++  /* And this is the code that hopefully does work */
++  if (rename (config_file, config_file_sav) != 0)
++    {
++      vty_out (vty, "Can't backup old configuration file %s.%s", config_file_sav,
++              VTY_NEWLINE);
++      goto finished;
++    }
++  sync ();
++#endif
++
++#if 0
++  /* same here. Please no cross-filesystem hardlinks... */
+   if (link (config_file_tmp, config_file) != 0)
++#else
++  if (rename (config_file_tmp, config_file) != 0)
++#endif
+     {
+       vty_out (vty, "Can't save configuration file %s.%s", config_file,
+              VTY_NEWLINE);
diff --git a/package/quagga/not-patches/patches-pgbgp/160-pgbgp.patch b/package/quagga/not-patches/patches-pgbgp/160-pgbgp.patch
new file mode 100644 (file)
index 0000000..860c6c1
--- /dev/null
@@ -0,0 +1,3098 @@
+From: Josh Karlin <karlinjf@cs.unm.edu>
+Date: Mon, 18 Aug 2008 13:17:21 +0000 (+0100)
+Subject: [bgp] Add support for Pretty-Good BGP
+X-Git-Url: http://git.ozo.com/?p=quagga-pgbg.git;a=commitdiff_plain;h=c2ee55705cad607f4b86ff143f7af92d538dc946
+
+[bgp] Add support for Pretty-Good BGP
+
+2008-7-7 Josh Karlin <karlinjf@cs.unm.edu>
+
+       * bgpd/bgp_pgbgp.c: Added file
+       * bgpd/bgp_pgbgp.h: Added file
+       * bgpd/Makefile.am: Added bgp_pgbgp.h and bgp_pgbgp.c
+       * bgpd/bgp_aspath.h: Externed the hash of as paths (ashash)
+       * bgpd/bgp_route.c: . Added PGBGP depref check to decision process.
+                           . Informs PGBGP of new updates and selected routes
+                           . Added anomaly status for show ip bgp
+                           . Added PGBGP commands
+       * bgpd/bgp_route.h: Added suspicious route flags
+       * bgpd/bgp_table.h: Added PGBGP history pointer to struct bgp_node
+       * bgpd/bgpd.h:      Defined BGP_CONFIG_PGBGP
+       * lib/hash.c:       Added "hash_iterate_until" to be able to break out
+       * lib/hash.h:       Definition for "hash_iterate_until"
+       * lib/memtypes.c:   Added PGBGP memory types
+---
+
+--- a/bgpd/Makefile.am
++++ b/bgpd/Makefile.am
+@@ -15,14 +15,14 @@ libbgp_a_SOURCES = \
+       bgp_debug.c bgp_route.c bgp_zebra.c bgp_open.c bgp_routemap.c \
+       bgp_packet.c bgp_network.c bgp_filter.c bgp_regex.c bgp_clist.c \
+       bgp_dump.c bgp_snmp.c bgp_ecommunity.c bgp_mplsvpn.c bgp_nexthop.c \
+-      bgp_damp.c bgp_table.c bgp_advertise.c bgp_vty.c bgp_mpath.c
++      bgp_damp.c bgp_table.c bgp_advertise.c bgp_vty.c bgp_mpath.c bgp_pgbgp.c
+ noinst_HEADERS = \
+       bgp_aspath.h bgp_attr.h bgp_community.h bgp_debug.h bgp_fsm.h \
+       bgp_network.h bgp_open.h bgp_packet.h bgp_regex.h bgp_route.h \
+       bgpd.h bgp_filter.h bgp_clist.h bgp_dump.h bgp_zebra.h \
+       bgp_ecommunity.h bgp_mplsvpn.h bgp_nexthop.h bgp_damp.h bgp_table.h \
+-      bgp_advertise.h bgp_snmp.h bgp_vty.h bgp_mpath.h
++      bgp_advertise.h bgp_snmp.h bgp_vty.h bgp_mpath.h bgp_pgbgp.h
+ bgpd_SOURCES = bgp_main.c
+ bgpd_LDADD = libbgp.a ../lib/libzebra.la @LIBCAP@ @LIBM@
+--- /dev/null
++++ b/bgpd/bgp_pgbgp.c
+@@ -0,0 +1,2401 @@
++/* 
++   BGP Pretty Good BGP
++   Copyright (C) 2008 University of New Mexico (Josh Karlin)
++
++This file is part of GNU Zebra.
++
++GNU Zebra 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, or (at your option) any
++later version.
++
++GNU Zebra 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.
++
++You should have received a copy of the GNU General Public License
++along with GNU Zebra; see the file COPYING.  If not, write to the Free
++Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
++02111-1307, USA. 
++*/
++
++/*
++  Quagga based Pretty Good BGP:
++
++  Summary 
++  ------- 
++  Pretty Good BGP (PGBGP) is a soft security enhancement to BGP.
++  It uses independently collected (therefore completely distributed)
++  historical routing information to determine network topology and
++  prefix ownership.  Abberations to the historical database are considered
++  anomalous and avoided when possible.
++
++  What PGBGP can protect against: prefix hijacks, sub-prefix hijacks, and
++  spoofed edges.
++
++  Further reading is available at http://cs.unm.edu/~karlinjf/pgbgp/
++
++  Route updates are forwarded to PGBGP, which determines if the route
++  is anomalous.  Anomalous routes are flagged as suspicious and
++  avoided where feasible for 24 hours.  If the anomalous
++  characteristic is still in the RIB after 24 hours, consider it valid
++  and enter it into the normal database.
++
++  Cases for anomalous routes
++  --------------------------
++  case 1) New origin AS - prefix pair (one not recently seen in the RIB):
++     response) label the route with BGP_INFO_SUSPICIOUS_O and avoid for 24 hours if possible
++
++  case 2) New edge in path (one not recently seen in the RIB): 
++     response) label the route with BGP_INFO_SUSPICIOUS_E and avoid for 24 hours
++               if possible
++
++  case 3) New prefix that is a sub-prefix of a prefix in recent history 
++          and that path differs from the current less-specific's path
++     response) label the sub-prefix routes with BGP_INFO_IGNORED_P and 
++               prevent it from entering FIB for 24 hours
++     response) label the super-net routes from the same next-hop as BGP_INFO_SUSPICIOUS_P 
++               and try to avoid it for 24 hours if possible
++     response) while no super-net route is selected, remove the BGP_INFO_IGNORED_P flags
++  
++
++  Normal Database (history)
++  -------------------------
++  Recently Seen) A route characteristic (edge, prefix/origin pair, prefix) 
++                 that has resided within the RIB within the last X hours 
++               where X is user defined for each characteristic.
++  Storage) Prefix and Origin history are stored in bgp_node structs with the
++           "hist" pointer. 
++         Edge information is stored in a separate hash table, where the edge
++         is the key to the hash.
++  Updates) The history's primary function is the keep track of when each route 
++           characteristic was last seen.  For each route announcement, update 
++           the history's 'last seen' time.  Periodically run the garbage collector 
++         which updates 'last seen' times for objects currently in the RIB.
++  
++  Garbage Collection
++  ------------------
++  Periodically the garbage collector (gc) is called to remove stale history 
++  information and update the lastSeen time of objects that reside in the RIB 
++  at the time of collection.  This is relatively expensive as it walks
++  the RIB as well as the list of AS paths.
++
++  What is removed) Objects that have not been seen in the RIB within a user-defined
++                   time.
++                 Suspicious objcets that are 24 hours old that have not been in the RIB
++                 since the last collection.
++  
++  Reuse Priority Queue
++  --------------------
++  After 24 hours, routes that are flagged as suspicious have the flags removed.  
++  This is not run on a timer.  Instead, for each update that PGBGP is informed of,
++  it checks the reuse queue to determine if any routes need to be updated.
++
++*/
++
++
++/*
++  Things that must be ensured:
++  . GC updates lastSeen so it must be called at least twice as often as the lowest BUFFER_TIME
++  . GC should be called at least twice per day
++  . Delay times must be shorter than history window lengths
++*/
++
++
++/*
++  Changes made to original PGBGP thinking
++  . Don't check for things in the RIB all of the time, periodically 
++    update the lastSeen values and just use lastSeen
++*/
++
++/*
++  Changes made to original protocol
++  . sub-prefixes are only ignored while the super-net has a selected 
++    route and it's non-anomalous (not to a neighbor that announced 
++    the sub-prefix)
++  
++  . At point of reuse, don't delete the item if it's not in the RIB. 
++    delete it if it hasn't been in the RIB since the last storage.  
++    This saves a lot of processing time for new edges
++
++  . Changed heuristic from "if new sub-prefix and trusted AS on path 
++    then it's okay" to  "if new sub-prefix and same path is used to reach 
++    super-prefix, then it's okay".  Might be better to change to "if old 
++    path is prefix of new path, then okay"
++*/
++
++#include <zebra.h>
++#include <math.h>
++
++#include "prefix.h"
++#include "memory.h"
++#include "command.h"
++#include "log.h"
++#include "pqueue.h"
++#include "table.h"
++#include "hash.h"
++#include "str.h"
++
++#include "bgpd/bgpd.h"
++#include "bgpd/bgp_aspath.h"
++#include "bgpd/bgp_pgbgp.h"
++#include "bgpd/bgp_table.h"
++#include "bgpd/bgp_route.h"
++#include "bgpd/bgp_attr.h"
++#include "bgpd/bgp_advertise.h"
++
++
++#define true 1
++#define false 0
++
++struct hash * ashash;
++
++static void *edge_hash_alloc (void *arg);
++static unsigned int edge_key_make (void *p);
++static int edge_cmp (const void *arg1, const void *args);
++
++// Helper Functions
++static struct bgp_pgbgp_pathSet bgp_pgbgp_pathOrigin (struct aspath *);
++static int bgp_pgbgp_pathLength (struct aspath *asp);
++static int bgp_pgbgp_gc (struct bgp_table *);
++static int bgp_pgbgp_clean (struct bgp_table *);
++static int bgp_pgbgp_reuse (time_t);
++static struct bgp_node *findSuper (struct bgp_table *table, struct prefix *p,
++                            time_t t_now);
++static int bgp_pgbgp_store (struct bgp_table *table);
++static int bgp_pgbgp_restore (void);
++static struct bgp_info *bgp_pgbgp_selected (struct bgp_node *node);
++static int originInRIB (struct bgp_node *node, struct bgp_pgbgp_origin *origin);
++static int prefixInRIB (struct bgp_node *node, struct bgp_pgbgp_prefix *prefix);
++static int edgeInRIB (struct bgp_pgbgp_edge *e);
++
++// MOAS Functions
++static void bgp_pgbgp_logOriginAnomaly (as_t asn, struct bgp_node *rn,
++                                 struct attr *);
++static int bgp_pgbgp_reuseOrigin (struct bgp_pgbgp_r_origin);
++static void bgp_pgbgp_cleanHistTable (struct bgp_table *);
++static int bgp_pgbgp_garbageCollectHistTable (struct bgp_table *);
++static void bgp_pgbgp_storeHistTable (struct bgp_table *table, FILE * file);
++static int bgp_pgbgp_updateOrigin (struct bgp_pgbgp_hist *, struct bgp_info *,
++                            struct attr *, struct bgp_node *, time_t, int);
++
++
++// Sub-Prefix Hijack Detector Functions
++static int bgp_pgbgp_shouldIgnore (struct bgp_node *super, struct bgp_info *selected);
++static void bgp_pgbgp_logSubprefixAnomaly (as_t asn, struct bgp_node *rn,
++                                    struct attr *, struct bgp_node *super);
++static int bgp_pgbgp_reusePrefix (struct bgp_pgbgp_r_prefix);
++static int bgp_pgbgp_updatePrefix (struct bgp_pgbgp_hist *hist, struct bgp_node *,
++                            struct bgp_info *, struct attr *,
++                            struct bgp_node *, time_t, int);
++
++
++// Spoofed Edge Detector Functions
++static void bgp_pgbgp_cleanEdges (void);
++static void bgp_pgbgp_logEdgeAnomaly (struct bgp_node *rn, struct attr *,
++                               struct edge *edge);
++static int bgp_pgbgp_reuseEdge (struct bgp_pgbgp_r_edge);
++static void bgp_pgbgp_storeEdges (struct bgp_table *, FILE *);
++static int bgp_pgbgp_garbageCollectEdges (struct bgp_table *);
++static int bgp_pgbgp_updateEdge (struct bgp_pgbgp_hist *hist, struct bgp_info *,
++                          struct attr *, struct bgp_node *, time_t, int);
++static int bgp_pgbgp_restoreEdge (FILE * file);
++static void bgp_pgbgp_storeEdges (struct bgp_table *table, FILE * file);
++
++
++
++// New Peer Detector Functions
++static int bgp_pgbgp_updatePeer (struct bgp_info *binfo, time_t now);
++
++
++/* --------------- Global Variables ------------------ */
++struct bgp_pgbgp_config bgp_pgbgp_cfg;
++struct bgp_pgbgp_config *pgbgp = &bgp_pgbgp_cfg;
++/*! --------------- Global Variables ------------------ !*/
++
++/* --------------- VTY (others exist in bgp_route.c)  ------------------ */
++
++struct nsearch
++{
++  struct vty *pvty;
++  time_t time;
++  as_t asn;
++};
++
++static void
++edge_neighbor_iterator (struct hash_backet *backet, struct nsearch *pns)
++{
++  struct bgp_pgbgp_edge *hedge = backet->data;
++  if ((hedge->e.a == pns->asn || hedge->e.b == pns->asn)
++      && hedge->e.a != hedge->e.b)
++    {
++      struct vty *vty = pns->pvty;
++      if (hedge->deprefUntil > pns->time)
++        vty_out (pns->pvty, "Untrusted: %d -- %d%s", hedge->e.a, hedge->e.b,
++                 VTY_NEWLINE);
++      else
++        vty_out (pns->pvty, "Trusted: %d -- %d%s", hedge->e.a, hedge->e.b,
++                 VTY_NEWLINE);
++    }
++}
++
++static int
++bgp_pgbgp_stats_neighbors (struct vty *vty, afi_t afi, safi_t safi, as_t asn)
++{
++  struct nsearch ns;
++  ns.pvty = vty;
++  ns.time = time (NULL);
++  ns.asn = asn;
++
++  hash_iterate (pgbgp->edgeT,
++                (void (*)(struct hash_backet *, void *))
++                edge_neighbor_iterator, &ns);
++  return CMD_SUCCESS;
++}
++
++static int
++bgp_pgbgp_stats_origins (struct vty *vty, afi_t afi, safi_t safi,
++                         const char *prefix)
++{
++  struct bgp *bgp;
++  struct bgp_table *table;
++  time_t t_now = time (NULL);
++  bgp = bgp_get_default ();
++  if (bgp == NULL)
++    return CMD_WARNING;
++  if (bgp->rib == NULL)
++    return CMD_WARNING;
++  table = bgp->rib[afi][safi];
++  if (table == NULL)
++    return CMD_WARNING;
++
++  struct prefix p;
++  str2prefix (prefix, &p);
++  struct bgp_node *rn = bgp_node_match (table, &p);
++  vty_out (vty, "%s%s", prefix, VTY_NEWLINE);
++  if (rn)
++    {
++      if (rn->hist)
++        {
++          for (struct bgp_pgbgp_origin * cur = rn->hist->o; cur != NULL;
++               cur = cur->next)
++            {
++              if (cur->deprefUntil > t_now)
++                vty_out (vty, "Untrusted Origin AS: %d%s", cur->originAS,
++                         VTY_NEWLINE);
++              else
++                vty_out (vty, "Trusted Origin AS: %d%s", cur->originAS,
++                         VTY_NEWLINE);
++            }
++        }
++      bgp_unlock_node (rn);
++    }
++  return CMD_SUCCESS;
++}
++
++static int
++bgp_pgbgp_stats (struct vty *vty, afi_t afi, safi_t safi)
++{
++  struct bgp *bgp;
++  struct bgp_table *table;
++
++
++  bgp = bgp_get_default ();
++  if (bgp == NULL)
++    return CMD_WARNING;
++  if (bgp->rib == NULL)
++    return CMD_WARNING;
++  table = bgp->rib[afi][safi];
++  if (table == NULL)
++    return CMD_WARNING;
++
++  //    bgp_pgbgp_store(table);
++
++  // Print out the number of anomalous routes
++  int anomalous = 0;
++  int routes = 0;
++  int num_selected = 0;
++  int num_origin = 0;
++  int num_super = 0;
++  int num_ignored = 0;
++  int num_edge = 0;
++
++  for (struct bgp_node * rn = bgp_table_top (table); rn;
++       rn = bgp_route_next (rn))
++    {
++      for (struct bgp_info * ri = rn->info; ri; ri = ri->next)
++        {
++          routes += 1;
++          if (ANOMALOUS (ri->flags))
++            {
++              anomalous += 1;
++              if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED))
++                num_selected += 1;
++
++              if (CHECK_FLAG (ri->flags, BGP_INFO_SUSPICIOUS_O))
++                num_origin += 1;
++              if (CHECK_FLAG (ri->flags, BGP_INFO_SUSPICIOUS_E))
++                num_edge += 1;
++              if (CHECK_FLAG (ri->flags, BGP_INFO_SUSPICIOUS_P))
++                num_super += 1;
++              if (CHECK_FLAG (ri->flags, BGP_INFO_IGNORED_P))
++                num_ignored += 1;
++            }
++        }
++    }
++
++  vty_out (vty, "%-30s: %10d%s", "Routes in the RIB", routes, VTY_NEWLINE);
++  vty_out (vty, "%-30s: %10d%s", "Anomalous routes in RIB", anomalous,
++           VTY_NEWLINE);
++  vty_out (vty, "%-30s: %10d%s", "Selected anomalous routes", num_selected,
++           VTY_NEWLINE);
++  vty_out (vty, "-----------------------------%s", VTY_NEWLINE);
++  vty_out (vty, "%-30s: %10d%s", "Routes with anomalous origins", num_origin,
++           VTY_NEWLINE);
++  vty_out (vty, "%-30s: %10d%s", "Routes with anomalous edges", num_edge,
++           VTY_NEWLINE);
++  vty_out (vty, "%-30s: %10d%s", "Routes ignored for sub-prefix", num_ignored,
++           VTY_NEWLINE);
++  vty_out (vty, "%-30s: %10d%s", "Less specific routes to avoid", num_super,
++           VTY_NEWLINE);
++  /*
++     vty_out (vty, "There are %d routes in the RIB.%s", routes, VTY_NEWLINE); 
++     vty_out (vty, "%d are anomalous.%s", anomalous, VTY_NEWLINE);
++     vty_out (vty, "%d anomalous routes are selected.%s", num_selected, VTY_NEWLINE);
++     vty_out (vty, "%s", VTY_NEWLINE);
++     vty_out (vty, "Anomaly breakdown:%s", VTY_NEWLINE);
++     vty_out (vty, "%d contain anomalous origins%s", num_origin, VTY_NEWLINE);
++     vty_out (vty, "%d contain anomalous edges.%s", num_edge, VTY_NEWLINE);
++     vty_out (vty, "%d are for ignored sub-prefixes.%s", num_ignored, VTY_NEWLINE);
++     vty_out (vty, "%d are super-net routes through peers that announced anomalous sub-prefixes.%s", num_super, VTY_NEWLINE);
++   */
++  return CMD_SUCCESS;
++}
++
++
++DEFUN (show_ip_bgp_pgbgp,
++       show_ip_bgp_pgbgp_cmd,
++       "show ip bgp pgbgp",
++       SHOW_STR IP_STR BGP_STR "Display PGBGP statistics\n")
++{
++  return bgp_pgbgp_stats (vty, AFI_IP, SAFI_UNICAST);
++}
++
++DEFUN (show_ip_bgp_pgbgp_neighbors,
++       show_ip_bgp_pgbgp_neighbors_cmd,
++       "show ip bgp pgbgp neighbors WORD",
++       SHOW_STR
++       IP_STR
++       BGP_STR
++       "BGP pgbgp\n"
++       "BGP pgbgp neighbors\n" "ASN whos neighbors should be displayed\n")
++{
++  return bgp_pgbgp_stats_neighbors (vty, AFI_IP, SAFI_UNICAST,
++                                    atoi (argv[0]));
++}
++
++DEFUN (show_ip_bgp_pgbgp_origins,
++       show_ip_bgp_pgbgp_origins_cmd,
++       "show ip bgp pgbgp origins A.B.C.D/M",
++       SHOW_STR
++       IP_STR
++       BGP_STR
++       "BGP pgbgp\n"
++       "BGP pgbgp neighbors\n" "Prefix to look up origin ASes of\n")
++{
++  return bgp_pgbgp_stats_origins (vty, AFI_IP, SAFI_UNICAST, argv[0]);
++}
++
++
++
++
++/*! --------------- VTY (others exist in bgp_route.c)  ------------------ !*/
++
++
++
++
++
++
++
++/* --------------- Helper Functions ------------------ */
++/*
++  If the origin hasn't been seen/verified lately, look for it in the RIB
++*/
++int
++originInRIB (struct bgp_node *node, struct bgp_pgbgp_origin *origin)
++{
++  for (struct bgp_info * ri = node->info; ri; ri = ri->next)
++    {
++      struct bgp_pgbgp_pathSet pathOrigins;
++      pathOrigins = bgp_pgbgp_pathOrigin (ri->attr->aspath);
++      for (int i = 0; i < pathOrigins.length; ++i)
++        {
++          if (pathOrigins.ases[i] == origin->originAS)
++            {
++              return true;
++            }
++        }
++    }
++  return false;
++}
++
++
++/*
++  If the prefix hasn't been seen/verified lately, look for it in the RIB
++*/
++int
++prefixInRIB (struct bgp_node *node, struct bgp_pgbgp_prefix *prefix)
++{
++  if (node->info)
++    return true;
++  return false;
++}
++
++static int
++edge_inRIB_iterator (struct hash_backet *backet, struct bgp_pgbgp_edge *hedge)
++{
++  struct aspath *p = backet->data;
++  char first = true;
++  struct edge curEdge;
++  curEdge.a = 0;
++  curEdge.b = 0;
++
++  struct assegment *seg;
++
++  for (seg = p->segments; seg; seg = seg->next)
++    {
++      for (int i = 0; i < seg->length; i++)
++        {
++          curEdge.a = curEdge.b;
++          curEdge.b = seg->as[i];
++          if (first)
++            {
++              first = false;
++              continue;
++            }
++          // Is this the edge we're looking for?
++          if (curEdge.a == hedge->e.a && curEdge.b == hedge->e.b)
++            {
++              hedge->lastSeen = time (NULL);
++              return false;
++            }
++        }
++    }
++
++  return true;
++}
++
++/*
++  If the edge hasn't been seen/verified lately, look for it in the AS path list
++  This function is expensive, use sparingly
++*/
++int
++edgeInRIB (struct bgp_pgbgp_edge *e)
++{
++  int completed;
++  completed = hash_iterate_until (ashash,
++                                  (int (*)(struct hash_backet *, void *))
++                                  edge_inRIB_iterator, e);
++  if (completed)
++    return false;
++
++  return true;
++}
++
++
++
++/*
++  Return the selected route for the given route node
++ */
++
++struct bgp_info *
++bgp_pgbgp_selected (struct bgp_node *node)
++{
++  for (struct bgp_info * ri = node->info; ri; ri = ri->next)
++    {
++      if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED))
++        return ri;
++    }
++  return NULL;
++}
++
++static int
++reuse_cmp (void *node1, void *node2)
++{
++  struct bgp_pgbgp_reuse *a;
++  struct bgp_pgbgp_reuse *b;
++  a = (struct bgp_pgbgp_reuse *) node1;
++  b = (struct bgp_pgbgp_reuse *) node2;
++  return a->deprefUntil - b->deprefUntil;
++}
++
++int
++bgp_pgbgp_pathLength (struct aspath *asp)
++{
++  struct assegment *seg;
++  if ((asp == NULL) || (asp->segments == NULL))
++    return 0;
++  int count = 0;
++  seg = asp->segments;
++  while (seg->next != NULL)
++    {
++      count += seg->length;
++      seg = seg->next;
++    }
++  return count;
++}
++
++
++
++/* Find the origin(s) of the path
++   All ASes in the final set are considered origins */
++static struct bgp_pgbgp_pathSet
++bgp_pgbgp_pathOrigin (struct aspath *asp)
++{
++  struct assegment *seg, *last;
++  struct bgp_pgbgp_pathSet tmp;
++  tmp.length = 0;
++  tmp.ases = NULL;
++
++  assert (asp != NULL && asp->segments != NULL);
++
++  /*    if ( (asp == NULL) || (asp->segments == NULL) )
++     return tmp;
++   */
++  seg = asp->segments;
++  last = NULL;
++  while (seg->next != NULL)
++    {
++      if (seg->type != AS_SET && seg->type != AS_CONFED_SET)
++        last = seg;
++      seg = seg->next;
++    }
++
++  if (seg->type == AS_SET || seg->type == AS_CONFED_SET)
++    seg = last;
++
++  assert (seg);
++  tmp.length = 1;
++  tmp.ases = &seg->as[seg->length - 1];
++
++  /*
++     if (seg->type == AS_SET || seg->type == AS_CONFED_SET)
++     {
++     tmp.length = seg->length;
++     tmp.ases = seg->as;
++     }
++     else
++     {
++     tmp.length = 1;
++     tmp.ases = &seg->as[seg->length - 1];
++     }
++   */
++  assert (tmp.length >= 1);
++  return tmp;
++  //    return seg->as[seg->length-1];
++}
++
++int
++bgp_pgbgp_reuse (time_t t_now)
++{
++
++  struct bgp_pgbgp_reuse *cur = NULL;
++
++  while (pgbgp->rq_size > 0)
++    {
++      cur = pqueue_dequeue (pgbgp->reuse_q);
++      pgbgp->rq_size -= 1;
++
++      // Is the next item ready to be reused?
++      if (t_now < cur->deprefUntil)
++        {
++          pqueue_enqueue (cur, pgbgp->reuse_q);
++          pgbgp->rq_size += 1;
++          break;
++        }
++
++      // Okay, it needs to be reused now
++      if (cur->type == PGBGP_REUSE_ORIGIN)
++        bgp_pgbgp_reuseOrigin (cur->data.origin);
++
++      else if (cur->type == PGBGP_REUSE_PREFIX)
++        bgp_pgbgp_reusePrefix (cur->data.prefix);
++
++      else if (cur->type == PGBGP_REUSE_EDGE)
++        bgp_pgbgp_reuseEdge (cur->data.edge);
++
++
++      XFREE (MTYPE_BGP_PGBGP_REUSE, cur);
++    }
++  return 0;
++}
++
++/* Check bit of the prefix. */
++static int
++check_bit (u_char * prefix, u_char prefixlen)
++{
++  int offset;
++  int shift;
++  u_char *p = (u_char *) prefix;
++
++  assert (prefixlen <= 128);
++
++  offset = prefixlen / 8;
++  shift = 7 - (prefixlen % 8);
++
++  return (p[offset] >> shift & 1);
++}
++
++/*
++  Find a super-net in the tree that's not currently anomalous if one exists
++*/
++struct bgp_node *
++findSuper (struct bgp_table *table, struct prefix *p, time_t t_now)
++{
++  struct bgp_node *node;
++  struct bgp_node *matched;
++
++  matched = NULL;
++  node = table->top;
++
++  while (node && node->p.prefixlen < p->prefixlen &&
++         prefix_match (&node->p, p))
++    {
++      // Node may not yet have its info set when reading in from pgbgp log files
++      if (node->hist && node->p.prefixlen >= 8)
++        {
++          if (node->hist->p != NULL && node->hist->p->ignoreUntil < t_now)
++            //if (node->hist->p != NULL && prefixInRIB (node, NULL))
++            //if (node->hist->p != NULL)
++            matched = node;
++        }
++      node = node->link[check_bit (&p->u.prefix, node->p.prefixlen)];
++    }
++  if (matched)
++    return bgp_lock_node (matched);
++  return NULL;
++}
++
++
++
++
++
++/*! --------------- Helper Functions ------------------ !*/
++
++
++
++
++
++
++
++/* --------------- Public PGBGP Interface ------------------ */
++int
++bgp_pgbgp_enable (struct bgp *bgp, afi_t afi, safi_t safi,
++                  int ost, int est, int sst, int oht, int pht, int eht,
++                  const char *file, const char *anoms)
++{
++
++  if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_PGBGP))
++    {
++      if (pgbgp->storage && pgbgp->anomalies)
++        {
++          if (pgbgp->origin_sus_time == ost
++              && pgbgp->edge_sus_time == est
++              && pgbgp->sub_sus_time == sst
++              && pgbgp->origin_hist_time == oht
++              && pgbgp->prefix_hist_time == pht
++              && pgbgp->edge_hist_time == eht
++              && strcmp (pgbgp->storage, file) == 0
++              && strcmp (pgbgp->anomalies, anoms) == 0)
++
++            return 0;
++        }
++    }
++
++  SET_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_PGBGP);
++
++#ifndef PGBGP_DEBUG
++  time_t hour = 3600;
++  time_t day = 86400;
++#endif
++#ifdef PGBGP_DEBUG
++  time_t hour = 2;
++  time_t day = 5;
++#endif
++
++  pgbgp->origin_sus_time = ost * hour;
++  pgbgp->edge_sus_time = est * hour;
++  pgbgp->sub_sus_time = sst * hour;
++  pgbgp->origin_hist_time = oht * day;
++  pgbgp->prefix_hist_time = pht * day;
++  pgbgp->edge_hist_time = eht * day;
++  pgbgp->peer_hist_time = DEFAULT_ORIGIN_HIST;
++
++  if (file != NULL)
++    pgbgp->storage = strdup (file);
++  else
++    pgbgp->storage = NULL;
++
++  if (anoms != NULL)
++    pgbgp->anomalies = strdup (anoms);
++  else
++    pgbgp->anomalies = NULL;
++
++
++  pgbgp->reuse_q = pqueue_create ();
++  pgbgp->reuse_q->cmp = reuse_cmp;
++  pgbgp->rq_size = 0;
++  pgbgp->lastgc = time (NULL);
++  pgbgp->lastStore = time (NULL);
++  pgbgp->startTime = time (NULL);
++  install_element (VIEW_NODE, &show_ip_bgp_pgbgp_cmd);
++  install_element (ENABLE_NODE, &show_ip_bgp_pgbgp_cmd);
++  install_element (VIEW_NODE, &show_ip_bgp_pgbgp_neighbors_cmd);
++  install_element (ENABLE_NODE, &show_ip_bgp_pgbgp_neighbors_cmd);
++  install_element (VIEW_NODE, &show_ip_bgp_pgbgp_origins_cmd);
++  install_element (ENABLE_NODE, &show_ip_bgp_pgbgp_origins_cmd);
++  pgbgp->edgeT = hash_create_size (131072, edge_key_make, edge_cmp);
++  bgp_pgbgp_restore ();
++  return 0;
++}
++
++int
++bgp_pgbgp_disable (struct bgp *bgp, afi_t afi, safi_t safi)
++{
++  UNSET_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_PGBGP);
++
++  // Clean the tables
++  if (bgp->rib[afi][safi] != NULL)
++    bgp_pgbgp_clean (bgp->rib[afi][safi]);
++
++  bgp_pgbgp_cleanEdges ();
++
++  if (pgbgp->storage != NULL)
++    free (pgbgp->storage);
++
++  if (pgbgp->anomalies != NULL)
++    free (pgbgp->anomalies);
++
++  struct bgp_pgbgp_peerTime *pr = pgbgp->peerLast;
++  while (pr)
++    {
++      struct bgp_pgbgp_peerTime *cur = pr;
++      pr = pr->next;
++      XFREE (MTYPE_BGP_PGBGP_PEER, cur);
++    }
++
++  return 0;
++}
++
++int
++bgp_pgbgp_clean (struct bgp_table *table)
++{
++  struct bgp_pgbgp_reuse *rnode = NULL;
++
++  while (pgbgp->rq_size > 0)
++    {
++      rnode = (struct bgp_pgbgp_reuse *) pqueue_dequeue (pgbgp->reuse_q);
++      pgbgp->rq_size -= 1;
++      XFREE (MTYPE_BGP_PGBGP_REUSE, rnode);
++    }
++  pqueue_delete (pgbgp->reuse_q);
++
++  if (table == NULL)
++    return 0;
++
++  // Clean the detectors
++  bgp_pgbgp_cleanHistTable (table);
++
++  bgp_pgbgp_cleanEdges ();
++
++
++  // Clean up the RIB nodes
++  for (struct bgp_node * rn = bgp_table_top (table); rn;
++       rn = bgp_route_next (rn))
++    {
++      int changed = 0;
++      for (struct bgp_info * ri = rn->info; ri; ri = ri->next)
++        {
++          if (CHECK_FLAG (ri->flags, BGP_INFO_SUSPICIOUS_O
++                          | BGP_INFO_SUSPICIOUS_P | BGP_INFO_SUSPICIOUS_E
++                          | BGP_INFO_IGNORED_P))
++            {
++              changed = 1;
++              UNSET_FLAG (ri->flags, BGP_INFO_SUSPICIOUS_O
++                          | BGP_INFO_SUSPICIOUS_P | BGP_INFO_SUSPICIOUS_E
++                          | BGP_INFO_IGNORED_P);
++            }
++        }
++      if (changed && rn->info)
++        {
++          struct bgp_info *ri = rn->info;
++          bgp_process (ri->peer->bgp, rn, rn->table->afi, rn->table->safi);
++        }
++    }
++
++  hash_free (pgbgp->edgeT);
++  return 0;
++}
++
++
++int
++bgp_pgbgp_gc (struct bgp_table *table)
++{
++  struct bgp *bgp = bgp_get_default ();
++  if (!bgp)
++    return 0;
++
++  // Collect each AFI/SAFI RIB
++  for (afi_t afi = AFI_IP; afi < AFI_MAX; afi++)
++    for (safi_t safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
++      {
++        if (!CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_PGBGP))
++          continue;
++        struct bgp_table *curTable = bgp->rib[afi][safi];
++        if (!curTable)
++          continue;
++        bgp_pgbgp_garbageCollectHistTable (curTable);
++      }
++
++  bgp_pgbgp_garbageCollectEdges (table);
++
++  return 0;
++}
++
++int
++bgp_pgbgp_restore (void)
++{
++
++  if (pgbgp->storage == NULL)
++    return 0;
++  FILE *file = fopen (pgbgp->storage, "r");
++  if (!file)
++    return 0;
++
++  int type = 0;
++  struct prefix p;
++  struct bgp *bgp = bgp_get_default ();
++  struct bgp_node *curNode = NULL;
++
++  // Get the log store time
++  long long int writetime;
++  fscanf (file, "%lld", &writetime);
++  time_t swtime = writetime;
++
++  // If it's too old (more than 1 week old), start fresh
++  if (time (NULL) - swtime > 86400 * 7)
++    {
++      fclose (file);
++      return 0;
++    }
++
++
++  // Get the PGBGP init time
++  long long int stime;
++  fscanf (file, "%lld", &stime);
++  pgbgp->startTime = stime;
++
++  while (fscanf (file, "%d", &type) != EOF)
++    {
++
++      if (type == PREFIX_ID)
++        {
++          char pre[128];
++          unsigned int afi;
++          unsigned int safi;
++          long long int time;
++          fscanf (file, "%s %u %u %lld", pre, &afi, &safi, &time);
++          str2prefix (pre, &p);
++          struct bgp_table *curTable = bgp->rib[afi][safi];
++          assert (curTable != NULL);
++
++          // Create and lock the node
++          curNode = bgp_node_get (curTable, &p);
++          assert (curNode->hist == NULL);
++
++          //              bgp_lock_node(curNode);
++
++          curNode->hist =
++            XCALLOC (MTYPE_BGP_PGBGP_HIST, sizeof (struct bgp_pgbgp_hist));
++          assert (curNode->hist != NULL);
++
++          curNode->hist->p =
++            XCALLOC (MTYPE_BGP_PGBGP_PREFIX,
++                     sizeof (struct bgp_pgbgp_prefix));
++          assert (curNode->hist->p != NULL);
++
++          curNode->hist->p->lastSeen = time;
++        }
++      else if (type == ORIGIN_ID)
++        {
++          unsigned int ASN;
++          long long int time;
++          fscanf (file, "%u %lld", &ASN, &time);
++          struct bgp_pgbgp_origin *or = XCALLOC (MTYPE_BGP_PGBGP_ORIGIN,
++                                                 sizeof (struct
++                                                         bgp_pgbgp_origin));
++          or->lastSeen = time;
++          or->originAS = ASN;
++          or->next = curNode->hist->o;
++          curNode->hist->o = or;
++        }
++      else if (type == EDGE_ID)
++        {
++          bgp_pgbgp_restoreEdge (file);
++        }
++      else if (type == PEER_ID)
++        {
++          struct bgp_pgbgp_peerTime *pr;
++          long long int time;
++          union sockunion su;
++          char szsu[128];
++          fscanf (file, "%s %lld", szsu, &time);
++          str2sockunion (szsu, &su);
++          pr =
++            XCALLOC (MTYPE_BGP_PGBGP_PEER,
++                     sizeof (struct bgp_pgbgp_peerTime));
++          pr->su = su;
++          pr->lastSeen = time;
++          pr->next = pgbgp->peerLast;
++          pgbgp->peerLast = pr;
++        }
++    }
++
++  fclose (file);
++  return 0;
++}
++
++int
++bgp_pgbgp_store (struct bgp_table *table)
++{
++  if (pgbgp->storage == NULL)
++    return 0;
++  char *tmpname = malloc (sizeof (char) * (1 + 4 + strlen (pgbgp->storage)));
++  strcpy (tmpname, pgbgp->storage);
++  strcat (tmpname, ".tmp");
++  FILE *file = fopen (tmpname, "w");
++
++  if (!file)
++    {
++      free (tmpname);
++      return 0;
++    }
++
++  // Store the current time
++  fprintf (file, "%lld\n", (long long int) time (NULL));
++
++  // Store the init time
++  fprintf (file, "%lld\n", (long long int) pgbgp->startTime);
++
++  // Store the peer times
++  for (struct bgp_pgbgp_peerTime * pr = pgbgp->peerLast; pr; pr = pr->next)
++    {
++      char strSock[128];
++      sockunion2str (&pr->su, strSock, sizeof (strSock));
++
++      if (pr->deprefUntil < time (NULL))
++        {
++          fprintf (file, "%d %s %lld\n", PEER_ID, strSock,
++                   (long long int) pr->lastSeen);
++        }
++    }
++
++  // Store the tables
++  bgp_pgbgp_storeHistTable (table, file);
++  bgp_pgbgp_storeEdges (table, file);
++
++  fclose (file);
++
++  rename (tmpname, pgbgp->storage);
++
++  free (tmpname);
++  return 0;
++}
++
++/*
++  Check to see if we've seen the peer recently
++  If not, then we need to return true and not delay routes
++  for awhile
++*/
++int
++bgp_pgbgp_updatePeer (struct bgp_info *binfo, time_t now)
++{
++  int status = false;
++  // Find the peer
++  struct bgp_pgbgp_peerTime *pr = pgbgp->peerLast;
++  for (; pr; pr = pr->next)
++    if (sockunion_same (&pr->su, &binfo->peer->su))
++      break;
++
++  // If this is a new peer, create it
++  if (pr == NULL)
++    {
++      pr = XCALLOC (MTYPE_BGP_PGBGP_PEER, sizeof (struct bgp_pgbgp_peerTime));
++      pr->su = binfo->peer->su;
++      pr->next = pgbgp->peerLast;
++      pgbgp->peerLast = pr;
++
++    }
++  // Is it currently marked as new?
++  if (pr->deprefUntil > now)
++    goto UPPEER_DEPREF;
++
++  // Have we seen the peer recently?
++  if (pr->lastSeen + pgbgp->peer_hist_time > now)
++    goto UPPEER_CLEAN;
++
++  // It must not have been seen lately, depref it
++  pr->deprefUntil = now + PGBGP_PEER_GRACE;
++
++
++UPPEER_DEPREF:
++  status = true;
++
++UPPEER_CLEAN:
++  pr->lastSeen = now;
++
++  return status;
++}
++
++
++/*
++  Returns whether or not the sub-prefix should be ignored
++*/
++int
++bgp_pgbgp_shouldIgnore (struct bgp_node *super, struct bgp_info *selected)
++{
++  if (!selected || CHECK_FLAG (selected->flags, BGP_INFO_SUSPICIOUS_P))
++    return false;
++  return true;
++}
++
++/*
++  This is a special case function for smoothly handling sub-prefix hijacks.
++
++  It handles the following 2 events:
++
++  Event 1: The super-prefix of an anomalous prefix has a route through a non-anomalous
++
++  Event 1: An anomalous sub-prefix is ignored, but no best route for the super-prefix exists
++  Response: Announce the sub-prefix until the super-prefix comes back
++
++  Event 2: A super-prefix comes back to the RIB and its anomalous sub-prefix is in use
++  Response: Ignore the sub-prefix again
++ */
++
++
++int
++bgp_pgbgp_rib_updated (struct bgp_node *rn, struct bgp_info *old_best,
++                       struct bgp_info *new_best)
++{
++  //  return 0;
++  struct bgp_pgbgp_hist *hist = rn->hist;
++  if (!hist)
++    return 0;
++  if (!hist->p)
++    return 0;
++  time_t t_now = time (NULL);
++
++  /*
++     If we can't avoid the sub-prefix by routing to the super-prefix,
++     then route as normal to the sub-prefix
++   */
++  if (!bgp_pgbgp_shouldIgnore (rn, new_best))
++    {
++      for (struct bgp_pgbgp_avoid * cur = hist->p->avoid; cur;
++           cur = cur->next)
++        {
++          if (cur->avoidUntil > t_now)
++            {
++              int changed = false;
++              for (struct bgp_info * ri = cur->sub->info; ri; ri = ri->next)
++                {
++                  if (CHECK_FLAG (ri->flags, BGP_INFO_IGNORED_P))
++                    {
++                      changed = true;
++                      UNSET_FLAG (ri->flags, BGP_INFO_IGNORED_P);
++                    }
++                }
++              if (changed)
++                {
++                  struct bgp_info *ri = cur->sub->info;
++                  if (ri && ri->peer && ri->peer->bgp)
++                    bgp_process (ri->peer->bgp, cur->sub,
++                                 cur->sub->table->afi, cur->sub->table->safi);
++
++                }
++
++            }
++        }
++    }
++
++  /* 
++     If we can avoid the sub-prefix by routing to the super-prefix,
++     then do so
++   */
++
++  else
++    {
++      for (struct bgp_pgbgp_avoid * cur = hist->p->avoid; cur;
++           cur = cur->next)
++        {
++          if (cur->avoidUntil > t_now)
++            {
++              int changed = false;
++              for (struct bgp_info * ri = cur->sub->info; ri; ri = ri->next)
++                {
++                  if (!CHECK_FLAG (ri->flags, BGP_INFO_IGNORED_P))
++                    {
++                      changed = true;
++                      SET_FLAG (ri->flags, BGP_INFO_IGNORED_P);
++                    }
++                }
++              if (changed)
++                {
++                  struct bgp_info *ri = cur->sub->info;
++                  if (ri && ri->peer && ri->peer->bgp)
++                    bgp_process (ri->peer->bgp, cur->sub,
++                                 cur->sub->table->afi, cur->sub->table->safi);
++                }
++            }
++        }
++    }
++
++  /*
++     if (old_best && !new_best)
++     {
++     time_t t_now = time(NULL);
++     for (struct bgp_pgbgp_avoid * cur = hist->p->avoid; cur;
++     cur = cur->next)
++     {
++     if (cur->avoidUntil > t_now)
++     {
++     for (struct bgp_info * ri = cur->sub->info; ri; ri = ri->next)
++     UNSET_FLAG (ri->flags, BGP_INFO_IGNORED_P);
++
++     struct bgp_info *ri = cur->sub->info;
++     if (ri && ri->peer && ri->peer->bgp)
++     bgp_process (ri->peer->bgp, cur->sub, cur->sub->table->afi,
++     cur->sub->table->safi);
++     }
++     }      
++     }
++
++
++     else if (!old_best && new_best)
++     {
++     time_t t_now = time(NULL);
++     for (struct bgp_pgbgp_avoid * av = hist->p->avoid; av; av = av->next)
++     {
++     struct bgp_info * ri = av->sub->info;
++     if (av->avoidUntil > t_now && ri && !CHECK_FLAG(ri->flags, BGP_INFO_IGNORED_P)) 
++     {
++     for (; ri; ri = ri->next)
++     SET_FLAG (ri->flags, BGP_INFO_IGNORED_P);
++     ri = av->sub->info;
++     if (ri && ri->peer && ri->peer->bgp)
++     bgp_process (ri->peer->bgp, av->sub,
++     av->sub->table->afi, av->sub->table->safi);
++
++     }
++     }      
++     }
++   */
++  return 0;
++}
++
++int
++bgp_pgbgp_update (struct bgp_info *binfo, struct attr *at,
++                  struct bgp_node *rn)
++{
++  time_t t_now = time (NULL);
++
++  // Clean up the reuse list
++  bgp_pgbgp_reuse (t_now);
++
++
++  if (!rn->hist)
++    {
++      rn->hist =
++        XCALLOC (MTYPE_BGP_PGBGP_HIST, sizeof (struct bgp_pgbgp_hist));
++      // Get the PGBGP history lock on rn
++      bgp_lock_node (rn);
++    }
++
++  struct bgp_node *superhn = NULL;
++
++  // implicit lock from node_get
++  superhn = findSuper (rn->table, &rn->p, t_now);
++
++  int newPeer = bgp_pgbgp_updatePeer (binfo, t_now);
++  bgp_pgbgp_updateOrigin (rn->hist, binfo, at, rn, t_now, newPeer);
++  bgp_pgbgp_updatePrefix (rn->hist, superhn, binfo, at, rn, t_now, newPeer);
++  bgp_pgbgp_updateEdge (rn->hist, binfo, at, rn, t_now, newPeer);
++
++  if (superhn != NULL)
++    bgp_unlock_node (superhn);
++
++
++
++  // GC and storage must be last, as they update lastSeen values of objects
++  // which would cause new routes to be recently seen, which is undesired behavior
++  // Make sure you don't collect anything that might be in use!
++  if (t_now >= pgbgp->lastgc + PGBGP_GC_DELTA)
++    {
++      bgp_pgbgp_gc (rn->table);
++      pgbgp->lastgc = t_now;
++    }
++
++  if (t_now >= pgbgp->lastStore + PGBGP_STORE_DELTA)
++    {
++      bgp_pgbgp_store (rn->table);
++      pgbgp->lastStore = t_now;
++    }
++
++
++
++  return 0;
++}
++
++
++
++
++/*! --------------- Public PGBGP Interface ------------------ !*/
++
++
++
++
++
++
++
++
++
++/* --------------- MOAS Detection ------------------ */
++void
++bgp_pgbgp_storeHistTable (struct bgp_table *table, FILE * file)
++{
++  time_t t_now;
++  t_now = time (NULL);
++
++  struct bgp *bgp = bgp_get_default ();
++  if (!bgp)
++    return;
++
++  // Store each AFI/SAFI RIB
++  for (afi_t afi = AFI_IP; afi < AFI_MAX; afi++)
++    for (safi_t safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
++      {
++        if (!CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_PGBGP))
++          continue;
++        struct bgp_table *curTable = bgp->rib[afi][safi];
++        if (!curTable)
++          continue;
++
++        for (struct bgp_node * rn = bgp_table_top (curTable); rn;
++             rn = bgp_route_next (rn))
++          {
++            struct bgp_pgbgp_hist *hist = rn->hist;
++            if (hist == NULL)
++              continue;
++            char szPrefix[128];
++            prefix2str (&rn->p, szPrefix, sizeof (szPrefix));
++
++
++            struct bgp_pgbgp_prefix *pre = hist->p;
++            if (pre && pre->ignoreUntil <= t_now)
++              {
++                if (pre->lastSeen + pgbgp->prefix_hist_time > t_now)
++                  fprintf (file, "%d %s %u %u %lld\n", PREFIX_ID, szPrefix,
++                           (unsigned int) afi, (unsigned int) safi,
++                           (long long int) pre->lastSeen);
++                else
++                  continue;
++              }
++            /* Need a prefix in the file before the origins, 
++               if no prefix.. skip origins */
++            else
++              continue;
++
++            for (struct bgp_pgbgp_origin * cur = hist->o; cur;
++                 cur = cur->next)
++              {
++                if (cur->deprefUntil > t_now)
++                  continue;
++
++                if (cur->lastSeen + pgbgp->origin_hist_time > t_now)
++                  fprintf (file, "%d %u %lld\n", ORIGIN_ID, cur->originAS,
++                           (long long int) cur->lastSeen);
++              }
++
++          }
++      }
++}
++
++
++int
++bgp_pgbgp_garbageCollectHistTable (struct bgp_table *table)
++{
++  time_t t_now;
++  t_now = time (NULL);
++
++
++  for (struct bgp_node * rn = bgp_table_top (table); rn;
++       rn = bgp_route_next (rn))
++    {
++      int collect = false;
++      struct bgp_pgbgp_hist *hist = rn->hist;
++      if (hist == NULL)
++        continue;
++
++      struct bgp_pgbgp_origin *cur = hist->o;
++      struct bgp_pgbgp_prefix *pre = hist->p;
++      struct bgp_pgbgp_origin *parent = NULL;
++
++      int used = false;
++      if (cur != NULL || pre != NULL)
++        used = true;
++
++      while (cur != NULL)
++        {
++          // Update the lastSeen time w/ originInRIB
++          if (originInRIB (rn, cur))
++            cur->lastSeen = t_now;
++
++          collect = false;
++
++          // Collect if old
++          if (cur->lastSeen + pgbgp->origin_hist_time <= t_now)
++            collect = true;
++
++          // Collect if anomaly just became okay but not seen since last collection
++          if (cur->deprefUntil != 0 && cur->deprefUntil < t_now)
++            {
++              if (cur->lastSeen < pgbgp->lastgc)
++                collect = true;
++              cur->deprefUntil = 0;
++            }
++
++          if (collect)
++            {
++              if (parent == NULL)
++                hist->o = cur->next;
++              else
++                parent->next = cur->next;
++
++              // Delete cur, parent doesn't change
++              struct bgp_pgbgp_origin *del = cur;
++              cur = cur->next;
++              XFREE (MTYPE_BGP_PGBGP_ORIGIN, del);
++            }
++          else
++            {
++              parent = cur;
++              cur = cur->next;
++            }
++        }
++
++      // Update the lastSeen time w/ prefixInRIB
++      if (pre && prefixInRIB (rn, pre))
++        pre->lastSeen = t_now;
++
++      collect = false;
++
++      // Collect if old
++      if (pre && pre->lastSeen + pgbgp->prefix_hist_time <= t_now)
++        collect = true;
++
++      // Collect if anomaly just became okay but not seen since last collection
++      if (pre && pre->ignoreUntil != 0 && pre->ignoreUntil < t_now)
++        {
++          if (pre->lastSeen < pgbgp->lastgc)
++            collect = true;
++          pre->ignoreUntil = 0;
++        }
++
++      if (collect)
++        {
++          for (struct bgp_pgbgp_avoid * av = pre->avoid; av;)
++            {
++              struct bgp_pgbgp_avoid *del = av;
++              av = av->next;
++              bgp_unlock_node (del->sub);
++              XFREE (MTYPE_BGP_PGBGP_AVOID, del);
++            }
++
++          XFREE (MTYPE_BGP_PGBGP_PREFIX, pre);
++          hist->p = NULL;
++        }
++
++      // If the node isn't in use, remove it
++      if (used && hist->o == NULL && hist->p == NULL)
++        {
++          XFREE (MTYPE_BGP_PGBGP_HIST, hist);
++          rn->hist = NULL;
++          bgp_unlock_node (rn);
++        }
++    }
++
++  return 0;
++}
++
++void
++bgp_pgbgp_cleanHistTable (struct bgp_table *table)
++{
++  // Clean up the RIB nodes
++  for (struct bgp_node * rn = bgp_table_top (table); rn;
++       rn = bgp_route_next (rn))
++    {
++      struct bgp_pgbgp_hist *hist = rn->hist;
++      if (hist == NULL)
++        continue;
++
++      if (hist->p)
++        {
++          for (struct bgp_pgbgp_avoid * av = hist->p->avoid; av;)
++            {
++              struct bgp_pgbgp_avoid *del = av;
++              av = av->next;
++              bgp_unlock_node (del->sub);
++              XFREE (MTYPE_BGP_PGBGP_AVOID, del);
++            }
++          hist->p->avoid = NULL;
++          XFREE (MTYPE_BGP_PGBGP_PREFIX, hist->p);
++          hist->p = NULL;
++        }
++
++      for (struct bgp_pgbgp_origin * cur = hist->o; cur;)
++        {
++          struct bgp_pgbgp_origin *next = cur->next;
++          XFREE (MTYPE_BGP_PGBGP_ORIGIN, cur);
++          cur = next;
++        }
++      hist->o = NULL;
++      XFREE (MTYPE_BGP_PGBGP_HIST, hist);
++      rn->hist = NULL;
++      bgp_unlock_node (rn);
++    }
++}
++
++void
++bgp_pgbgp_logOriginAnomaly (as_t asn, struct bgp_node *rn, struct attr *at)
++{
++  assert (pgbgp);
++  if (!pgbgp->anomalies)
++    return;
++  FILE *file = fopen (pgbgp->anomalies, "a");
++  if (!file)
++    return;
++
++  char pre[256];
++  prefix2str (&rn->p, pre, sizeof (pre));
++
++  // MOAS | TIME | NEXTHOP | PREFIX | SUSPICIOUS_ORIGIN | TRUSTED_ORIGINS | PATH
++  fprintf (file, "%d|%lld|%s|%s|%d|", MOAS, (long long int) time (NULL),
++           inet_ntoa (at->nexthop), pre, asn);
++
++
++  // Print the trusted origins
++  assert (rn->hist);
++  assert (rn->hist->o);
++
++  struct bgp_pgbgp_hist *hist = rn->hist;
++
++  for (struct bgp_pgbgp_origin * cur = hist->o; cur != NULL; cur = cur->next)
++    {
++      if (cur->deprefUntil > time (NULL))
++        continue;
++      fprintf (file, "%d", cur->originAS);
++      if (cur->next != NULL)
++        fprintf (file, " ");
++    }
++
++  fprintf (file, " |%s\n", aspath_print (at->aspath));
++  fclose (file);
++}
++
++int
++bgp_pgbgp_updateOrigin (struct bgp_pgbgp_hist *hist, struct bgp_info *binfo,
++                        struct attr *at, struct bgp_node *rn, time_t t_now,
++                        int newPeer)
++{
++  struct bgp_pgbgp_pathSet pathOrigins;
++  struct bgp_pgbgp_origin *pi = NULL;
++  int status = 0;
++  struct bgp_pgbgp_reuse *r;
++  pathOrigins = bgp_pgbgp_pathOrigin (at->aspath);
++
++
++  for (int i = 0; i < pathOrigins.length; i++)
++    {
++      as_t pathOrigin = pathOrigins.ases[i];
++
++      /* Is the Origin AS in the history? */
++      for (pi = hist->o; pi; pi = pi->next)
++        if (pi->originAS == pathOrigin)
++          break;
++
++      if (pi == NULL)
++        {
++          pi =
++            XCALLOC (MTYPE_BGP_PGBGP_ORIGIN,
++                     sizeof (struct bgp_pgbgp_origin));
++          pi->next = hist->o;
++          pi->originAS = pathOrigin;
++          hist->o = pi;
++        }
++
++      // If this is our first origin for the prefix, let the sub-prefix
++      // check take care of it
++      if (pi->next == NULL)
++        goto UPO_CLEAN;
++
++      /* Is the origin currently marked as suspicious? */
++      if (pi->deprefUntil > t_now)
++        goto UPO_DEPREF;
++
++      /* Have we seen the origin recently? */
++      if (pi->lastSeen + pgbgp->origin_hist_time > t_now)
++        goto UPO_CLEAN;
++
++#ifndef PGBGP_DEBUG
++      /* Are we within the initial grace period? */
++      if (newPeer)
++        goto UPO_CLEAN;
++#endif
++
++      /* It must not be in recent history, depref origin for first time */
++      pi->deprefUntil = t_now + pgbgp->origin_sus_time;
++      bgp_pgbgp_logOriginAnomaly (pathOrigin, rn, at);
++
++      r = XCALLOC (MTYPE_BGP_PGBGP_REUSE, sizeof (struct bgp_pgbgp_reuse));
++      r->type = PGBGP_REUSE_ORIGIN;
++      r->deprefUntil = pi->deprefUntil;
++      r->data.origin.originAS = pathOrigin;
++      r->data.origin.rn = rn;
++      bgp_lock_node (rn);
++      pqueue_enqueue (r, pgbgp->reuse_q);
++      pgbgp->rq_size += 1;
++
++
++    UPO_DEPREF:
++      SET_FLAG (binfo->flags, BGP_INFO_SUSPICIOUS_O);
++      status = BGP_INFO_SUSPICIOUS_O;
++
++    UPO_CLEAN:
++      pi->lastSeen = t_now;
++    }
++  return status;
++}
++
++int
++bgp_pgbgp_reuseOrigin (struct bgp_pgbgp_r_origin data)
++{
++  struct bgp_info *ri;
++  int numChanged = 0;
++  time_t t_now = time (NULL);
++  assert (data.rn->hist != NULL);
++
++  // Repreference paths for this prefix that are now okay
++  for (ri = data.rn->info; ri; ri = ri->next)
++    {
++      if (CHECK_FLAG (ri->flags, BGP_INFO_SUSPICIOUS_O))
++        {
++          struct bgp_pgbgp_pathSet pathOrigins;
++          pathOrigins = bgp_pgbgp_pathOrigin (ri->attr->aspath);
++          int numOkay = 0;
++          for (int i = 0; i < pathOrigins.length; i++)
++            {
++              as_t pathOrigin = pathOrigins.ases[i];
++              // Find the origin
++              struct bgp_pgbgp_origin *o = NULL;
++              for (o = data.rn->hist->o; o != NULL; o = o->next)
++                if (o->originAS == pathOrigin)
++                  break;
++              /*
++                 if (o == NULL) {
++                 for(struct bgp_pgbgp_origin * z = data.rn->hist->o; z != NULL; z = z->next)
++                 printf("Known origin: %d\n", z->originAS);
++                 char pre[128];
++                 prefix2str(&data.rn->p, pre, 128);
++                 printf("%s : %s : %d\n", pre, ri->attr->aspath->str, pathOrigin);
++                 }
++               */
++              assert (o != NULL);
++
++              if (o->deprefUntil <= t_now)
++                numOkay += 1;
++            }
++          if (numOkay == pathOrigins.length)
++            {
++              UNSET_FLAG (ri->flags, BGP_INFO_SUSPICIOUS_O);
++              numChanged += 1;
++            }
++        }
++    }
++
++  ri = data.rn->info;
++
++  // Rerun the decision process?
++  if (numChanged > 0)
++    bgp_process (ri->peer->bgp, data.rn, data.rn->table->afi,
++                 data.rn->table->safi);
++
++
++  /*
++     // Remove this (origin,prefix) pair from the normal database
++     // if it's not still in the RIB
++     struct bgp_pgbgp_hist *hist = rn->hist;
++     struct bgp_pgbgp_origin * cur = hist->o;
++     struct bgp_pgbgp_origin * parent = NULL;
++
++     // Find the origin AS node
++     while(cur != NULL)
++     {
++     if (cur->originAS == data.originAS)
++     {
++     // Delete the node if it hasn't been seen
++     // since the last storage run
++     if (cur->lastSeen < pgbgp->lastStore) {
++     // Delete this node
++     if (parent == NULL)
++     hist->o = cur->next;
++     else
++     parent->next = cur->next;
++
++     XFREE(MTYPE_BGP_PGBGP_ORIGIN, cur);
++     }
++     break;
++     }      
++     parent = cur;
++     cur = cur->next;
++     }
++   */
++
++  bgp_unlock_node (data.rn);
++  return 0;
++}
++
++/*! --------------- MOAS Detection ------------------ !*/
++
++
++/* --------------- Sub-Prefix Detection ------------------ */
++
++
++
++
++
++void
++bgp_pgbgp_logSubprefixAnomaly (as_t asn, struct bgp_node *rn, struct attr *at,
++                               struct bgp_node *super)
++{
++  assert (pgbgp);
++  if (!pgbgp->anomalies)
++    return;
++  FILE *file = fopen (pgbgp->anomalies, "a");
++  if (!file)
++    return;
++
++  char pre[256];
++  prefix2str (&rn->p, pre, sizeof (pre));
++
++  char superpre[256];
++  prefix2str (&super->p, superpre, sizeof (superpre));
++
++  // SUBPREFIX | TIME | NEXTHOP | PREFIX | SUPER-PREFIX | SUSPICIOUS_ORIGIN | TRUSTED_ORIGINS | PATH
++  fprintf (file, "%d|%lld|%s|%s|%s|%d|", SUBPREFIX,
++           (long long int) time (NULL), inet_ntoa (at->nexthop), pre,
++           superpre, asn);
++
++  // Print the trusted origins
++  assert (super->hist);
++  assert (super->hist->o);
++
++  struct bgp_pgbgp_hist *hist = super->hist;
++
++  for (struct bgp_pgbgp_origin * cur = hist->o; cur != NULL; cur = cur->next)
++    {
++      if (cur->deprefUntil > time (NULL))
++        continue;
++      fprintf (file, "%d", cur->originAS);
++      if (cur->next != NULL)
++        fprintf (file, " ");
++    }
++
++  fprintf (file, " |%s\n", aspath_print (at->aspath));
++  fclose (file);
++}
++
++/*
++  If the first path is a prefix of the second, then return true  
++ */
++
++static int
++bgp_pgbgp_pathIsPrefix(struct aspath *trusted, struct aspath * new)
++{
++  if (trusted == new)
++    return true;
++  
++  struct assegment *seg1 = trusted->segments;
++  struct assegment *seg2 = new->segments;
++  
++  while (seg1 || seg2)
++    {
++      if ((!seg1 && seg2) || (seg1 && !seg2))
++      return false;
++      if (seg1->type != seg2->type)
++      return false;
++      
++      if (seg1->length > seg2->length)
++      return false;
++        
++      for(int i = 0; i < seg1->length; i++)
++      if (seg1->as[i] != seg2->as[i])
++        return false;
++
++      seg1 = seg1->next;
++      seg2 = seg2->next;
++    }  
++
++  return true;
++}
++
++int
++bgp_pgbgp_updatePrefix (struct bgp_pgbgp_hist *hist,
++                        struct bgp_node *supernode, struct bgp_info *binfo,
++                        struct attr *at, struct bgp_node *rn, time_t t_now,
++                        int newPeer)
++{
++  struct bgp_pgbgp_prefix *pre = NULL;
++  struct bgp_pgbgp_reuse *r = NULL;
++  int status = 0;
++  int changed = false;
++
++  pre = hist->p;
++
++
++  /* Do we have this prefix? */
++  if (pre == NULL)
++    {
++      pre =
++        XCALLOC (MTYPE_BGP_PGBGP_PREFIX, sizeof (struct bgp_pgbgp_prefix));
++      hist->p = pre;
++    }
++
++  /* Is the prefix currently marked as suspicious? */
++  if (pre->ignoreUntil > t_now)
++    {
++      goto UPP_IGNORE;
++    }
++
++  /* Should this neighbor be avoided for this prefix because it
++     sent us info. about a suspicious sub-prefix? */
++  for (struct bgp_pgbgp_avoid * av = hist->p->avoid; av; av = av->next)
++    {
++      if (binfo->peer->as == av->peerASN && av->avoidUntil > t_now)
++        {
++          SET_FLAG (binfo->flags, BGP_INFO_SUSPICIOUS_P);
++          status = BGP_INFO_SUSPICIOUS_P;
++          goto UPP_DONE;
++        }
++    }
++
++  /* Have we seen the prefix recently? */
++  if (pre->lastSeen + pgbgp->prefix_hist_time > t_now)
++    goto UPP_DONE;
++
++#ifndef PGBGP_DEBUG
++  /* Are we within the initial grace period? */
++  if (newPeer)
++    goto UPP_DONE;
++#endif
++
++  /* Is there a less specific *in recent history* that this could be hijacking? */
++  if (supernode == NULL)
++    goto UPP_DONE;
++
++  /* Does this path the super-net's non-anomalous path from this peer?  If so it's okay */
++  int found = false;
++  for (struct bgp_info * ri = supernode->info; ri; ri = ri->next)
++    {
++      if (ri->peer->as == binfo->peer->as)
++      {
++        if (!ANOMALOUS(ri->flags) && bgp_pgbgp_pathIsPrefix(ri->attr->aspath, at->aspath))
++            found = true;
++        break;
++      }
++    }
++
++  if (found)
++    goto UPP_DONE;
++
++  /* 
++     It's not in recent history, and there is a less specific currently in use
++     Response:
++     . Ignore this prefix
++     . Make the less specific's route for this neighbor suspicious
++   */
++
++
++  pre->ignoreUntil = t_now + pgbgp->sub_sus_time;
++
++  struct bgp_pgbgp_pathSet pathOrigins;
++  pathOrigins = bgp_pgbgp_pathOrigin (at->aspath);
++  for (int i = 0; i < pathOrigins.length; i++)
++    bgp_pgbgp_logSubprefixAnomaly (pathOrigins.ases[i], rn, at, supernode);
++
++
++
++  r = XCALLOC (MTYPE_BGP_PGBGP_REUSE, sizeof (struct bgp_pgbgp_reuse));
++  r->type = PGBGP_REUSE_PREFIX;
++  r->deprefUntil = pre->ignoreUntil;
++  r->data.prefix.rn = rn;
++  r->data.prefix.rnsuper = supernode;
++  bgp_lock_node (rn);
++  bgp_lock_node (supernode);
++  pqueue_enqueue (r, pgbgp->reuse_q);
++  pgbgp->rq_size += 1;
++
++UPP_IGNORE:
++  // Sanity check
++  if (supernode == NULL)
++    goto UPP_DONE;
++    
++  /* Set the less specific's route from this peer to suspicious */
++  changed = false;
++
++  for (struct bgp_info * ri = supernode->info; ri; ri = ri->next)
++    {
++      if (ri->peer->as == binfo->peer->as)
++        {
++          if (!CHECK_FLAG (ri->flags, BGP_INFO_SUSPICIOUS_P))
++            {
++              SET_FLAG (ri->flags, BGP_INFO_SUSPICIOUS_P);
++              changed = true;
++            }
++          break;
++        }
++    }
++
++  // Make note of it in the less specific's history information
++  found = false;
++  struct bgp_pgbgp_hist *superhist = supernode->hist;
++
++  if (superhist && superhist->p)
++    {
++      for (struct bgp_pgbgp_avoid * av = superhist->p->avoid; av;
++           av = av->next)
++        {
++          if (av->peerASN == binfo->peer->as)
++            {
++              if (av->avoidUntil < pre->ignoreUntil)
++                av->avoidUntil = pre->ignoreUntil;
++              found = true;
++              break;
++            }
++        }
++      if (!found)
++        {
++          struct bgp_pgbgp_avoid *newavoid =
++            XCALLOC (MTYPE_BGP_PGBGP_AVOID, sizeof (struct bgp_pgbgp_avoid));
++          newavoid->peerASN = binfo->peer->as;
++          newavoid->avoidUntil = pre->ignoreUntil;
++          newavoid->next = superhist->p->avoid;
++          newavoid->sub = rn;
++          bgp_lock_node (rn);
++          superhist->p->avoid = newavoid;
++        }
++    }
++  /* 
++     ignore this route unless the supernet's node
++     is only a placeholder from loaded pgbgp data
++   */
++  if (bgp_pgbgp_shouldIgnore (supernode, bgp_pgbgp_selected (supernode)))
++    {
++      SET_FLAG (binfo->flags, BGP_INFO_IGNORED_P);
++      status = BGP_INFO_IGNORED_P;
++    }
++  if (changed)
++    {
++      struct bgp_info *ri = supernode->info;
++      bgp_process (ri->peer->bgp, supernode, supernode->table->afi,
++                   supernode->table->safi);
++    }
++
++UPP_DONE:
++  pre->lastSeen = t_now;
++
++  return status;
++}
++
++int
++bgp_pgbgp_reusePrefix (struct bgp_pgbgp_r_prefix data)
++{
++  struct bgp_info *ri = NULL;
++
++  time_t t_now = time (NULL);
++
++  // Repreference all routes for this node
++  for (ri = data.rn->info; ri; ri = ri->next)
++    UNSET_FLAG (ri->flags, BGP_INFO_IGNORED_P);
++  ri = data.rn->info;
++
++  // Rerun the decision process
++  if (ri != NULL)
++    bgp_process (ri->peer->bgp, data.rn, data.rn->table->afi,
++                 data.rn->table->safi);
++
++
++  // Remove the avoid nodes from the super
++  struct bgp_pgbgp_hist *superhist = data.rnsuper->hist;
++  if (superhist != NULL && superhist->p != NULL)
++    {
++      struct bgp_pgbgp_avoid *parent = NULL;
++      for (struct bgp_pgbgp_avoid * av = superhist->p->avoid; av;)
++        {
++          int numChanged = 0;
++          if (av->avoidUntil <= t_now)
++            {
++              struct bgp_pgbgp_avoid *del = av;
++              av = av->next;
++              if (parent == NULL)
++                superhist->p->avoid = av;
++              else
++                parent->next = av;
++
++              // Repreference any routes
++              for (ri = data.rnsuper->info; ri; ri = ri->next)
++                {
++                  if (ri->peer->as == del->peerASN)
++                    {
++                      UNSET_FLAG (ri->flags, BGP_INFO_SUSPICIOUS_P);
++                      numChanged += 1;
++                      break;
++                    }
++                }
++              ri = data.rnsuper->info;
++
++              if (numChanged > 0 && ri != NULL)
++                bgp_process (ri->peer->bgp, data.rnsuper,
++                             data.rnsuper->table->afi,
++                             data.rnsuper->table->safi);
++              bgp_unlock_node (del->sub);
++              XFREE (MTYPE_BGP_PGBGP_AVOID, del);
++            }
++          else
++            {
++              parent = av;
++              av = av->next;
++            }
++        }
++    }
++
++  // Remove this prefix from the normal database
++  // if it hasn't been seen in the RIB since the last
++  // storage run
++  /*
++     struct bgp_pgbgp_hist *hist = rn->hist;
++     struct bgp_pgbgp_prefix * pre = hist->p;
++
++     if (pre && pre->lastSeen < pgbgp->lastStore)
++     {
++     // Delete this node
++     for(struct bgp_pgbgp_avoid * av = hist->p->avoid; av;)
++     {
++     struct bgp_pgbgp_avoid *del = av;
++     av = av->next;
++     bgp_unlock_node(del->sub);
++     XFREE (MTYPE_BGP_PGBGP_AVOID, del);
++     }
++     XFREE(MTYPE_BGP_PGBGP_PREFIX, pre);
++     hist->p = NULL;      
++     }
++   */
++  bgp_unlock_node (data.rn);
++  bgp_unlock_node (data.rnsuper);
++  return 0;
++}
++
++/*! --------------- Sub-Prefix Detection ------------------ !*/
++
++
++
++
++
++/* --------------- Edge Detection ------------------ */
++
++static void
++edge_store_clear_iterator (struct hash_backet *backet, void *file)
++{
++  struct bgp_pgbgp_edge *hedge = backet->data;
++}
++
++static void
++edge_store_iterator (struct hash_backet *backet, FILE * file)
++{
++  struct bgp_pgbgp_edge *hedge = backet->data;
++  time_t t_now = time (NULL);
++  if (hedge->deprefUntil > t_now)
++    return;
++  if (hedge->lastSeen + pgbgp->edge_hist_time > t_now)
++    {
++      fprintf (file, "%d %u %u %lld\n", EDGE_ID, hedge->e.a, hedge->e.b,
++               (long long int) hedge->lastSeen);
++    }
++}
++
++
++void
++bgp_pgbgp_storeEdges (struct bgp_table *table, FILE * file)
++{
++  hash_iterate (pgbgp->edgeT,
++                (void (*)(struct hash_backet *, void *))
++                edge_store_iterator, file);
++  return;
++}
++
++
++int
++bgp_pgbgp_restoreEdge (FILE * file)
++{
++  unsigned int a, b;
++  long long int lastSeen;
++  fscanf (file, "%u %u %lld", &a, &b, &lastSeen);
++  struct bgp_pgbgp_edge finder;
++  finder.e.a = a;
++  finder.e.b = b;
++  finder.lastSeen = lastSeen;
++  struct bgp_pgbgp_edge *hedge =
++    hash_get (pgbgp->edgeT, &finder, edge_hash_alloc);
++  hedge->lastSeen = finder.lastSeen;
++  return 0;
++}
++
++unsigned int
++edge_key_make (void *p)
++{
++  struct bgp_pgbgp_edge *pe = p;
++  struct edge *e = &pe->e;
++  return (e->a << 16) + e->b;
++}
++
++static int
++edge_cmp (const void *arg1, const void *arg2)
++{
++
++  const struct edge *e1 = &((const struct bgp_pgbgp_edge *) arg1)->e;
++  const struct edge *e2 = &((const struct bgp_pgbgp_edge *) arg2)->e;
++  if (e1->a == e2->a && e1->b == e2->b)
++    return 1;
++  return 0;
++}
++
++static void *
++edge_hash_alloc (void *arg)
++{
++  struct bgp_pgbgp_edge *hedge =
++    XCALLOC (MTYPE_BGP_PGBGP_EDGE, sizeof (struct bgp_pgbgp_edge));
++  struct bgp_pgbgp_edge *lookup = arg;
++  if (hedge == NULL)
++    return NULL;
++  hedge->e = lookup->e;
++  return hedge;
++}
++
++
++static void
++edge_gc_iterator (struct hash_backet *backet, time_t * time)
++{
++  time_t t_now = *time;
++  struct bgp_pgbgp_edge *hedge = backet->data;
++
++  int collect = false;
++
++  // Collect if we haven't seen it in awhile
++  if (hedge->lastSeen + pgbgp->edge_hist_time <= t_now)
++    collect = true;
++
++  // Collect if it has just gotten out of anomaly stage
++  // but hasn't been in the RIB since the last GC
++  if (hedge->deprefUntil != 0 && hedge->deprefUntil < t_now)
++    {
++      if (hedge->lastSeen < pgbgp->lastgc)
++        collect = true;
++      hedge->deprefUntil = 0;
++    }
++
++  if (collect)
++    {
++      struct bgp_pgbgp_edge *ret = hash_release (pgbgp->edgeT, hedge);
++      assert (ret != NULL);
++      XFREE (MTYPE_BGP_PGBGP_EDGE, hedge);
++    }
++}
++
++
++
++static void
++edge_update_iterator (struct hash_backet *backet, void *v)
++{
++  struct aspath *p = backet->data;
++  time_t t_now = time (NULL);
++  int first = true;
++
++  struct edge cur;
++  cur.a = 0;
++  cur.b = 0;
++  struct assegment *seg;
++  struct bgp_pgbgp_edge *hedge = NULL;
++  for (seg = p->segments; seg; seg = seg->next)
++    {
++      for (int i = 0; i < seg->length; i++)
++        {
++          cur.a = cur.b;
++          cur.b = seg->as[i];
++          if (first)
++            {
++              first = false;
++              continue;
++            }
++          if (cur.a == cur.b)
++            continue;
++          //              printf("%d -- %d\n", cur.a, cur.b);
++          struct bgp_pgbgp_edge finder;
++          finder.e = cur;
++          hedge = hash_lookup (pgbgp->edgeT, &finder);
++
++          if (!hedge)
++            continue;
++          hedge->lastSeen = t_now;
++        }
++    }
++}
++
++int
++bgp_pgbgp_garbageCollectEdges (struct bgp_table *table)
++{
++  // Update the timings
++  hash_iterate (ashash,
++                (void (*)(struct hash_backet *, void *))
++                edge_update_iterator, NULL);
++
++  // Perform the collection
++  time_t t_now = time (NULL);
++  hash_iterate (pgbgp->edgeT,
++                (void (*)(struct hash_backet *, void *))
++                edge_gc_iterator, &t_now);
++  return 0;
++}
++
++static void
++edge_clean_iterator (struct hash_backet *backet, void *a1)
++{
++  struct bgp_pgbgp_edge *hedge = backet->data;
++  struct bgp_pgbgp_edge *ret = hash_release (pgbgp->edgeT, hedge);
++  assert (ret != NULL);
++  XFREE (MTYPE_BGP_PGBGP_EDGE, hedge);
++}
++
++static void
++bgp_pgbgp_cleanEdges (void)
++{
++  if (pgbgp->edgeT != NULL)
++    {
++      hash_iterate (pgbgp->edgeT,
++                    (void (*)(struct hash_backet *, void *))
++                    edge_clean_iterator, NULL);
++      hash_free (pgbgp->edgeT);
++    }
++  return;
++}
++
++void
++bgp_pgbgp_logEdgeAnomaly (struct bgp_node *rn, struct attr *at,
++                          struct edge *edge)
++{
++  assert (pgbgp);
++  if (!pgbgp->anomalies)
++    return;
++  FILE *file = fopen (pgbgp->anomalies, "a");
++  if (!file)
++    return;
++
++  char pre[256];
++  prefix2str (&rn->p, pre, sizeof (pre));
++
++  // EDGE | TIME | NEXTHOP | PREFIX | PATH | Edge.a | Edge.b
++
++  fprintf (file, "%d|%lld|%s|%s|%s|%d|%d\n", EDGE,
++           (long long int) time (NULL), inet_ntoa (at->nexthop), pre,
++           aspath_print (at->aspath), edge->a, edge->b);
++
++  fclose (file);
++}
++
++
++int
++bgp_pgbgp_updateEdge (struct bgp_pgbgp_hist *hist, struct bgp_info *binfo,
++                      struct attr *at, struct bgp_node *rn, time_t t_now,
++                      int newPeer)
++{
++
++  char first = true;
++  struct edge curEdge;
++  curEdge.a = 0;
++  curEdge.b = 0;
++
++
++  if (at->aspath == NULL)
++    return 0;
++  struct assegment *seg = at->aspath->segments;
++  if (seg == NULL)
++    return 0;
++  time_t max_depref = 0;
++  for (seg = at->aspath->segments; seg; seg = seg->next)
++    {
++      for (int i = 0; i < seg->length; i++)
++        {
++          curEdge.a = curEdge.b;
++          curEdge.b = seg->as[i];
++          if (first)
++            {
++              first = false;
++              continue;
++            }
++          if (curEdge.a == curEdge.b)
++            continue;
++
++          // We have an edge to consider
++          struct bgp_pgbgp_edge finder;
++          finder.e = curEdge;
++          struct bgp_pgbgp_edge *hedge =
++            hash_get (pgbgp->edgeT, &finder, edge_hash_alloc);
++
++          // Is this edge marked as suspicious?
++          if (hedge->deprefUntil > t_now)
++            goto UPE_DEPREF;
++
++          // Have we seen the edge recently?
++          if (hedge->lastSeen + pgbgp->edge_hist_time > t_now)
++            goto UPE_CLEAN;
++#ifndef PGBGP_DEBUG
++          /* Are we within the initial grace period? */
++          if (newPeer)
++            goto UPE_CLEAN;
++#endif
++          // It must not be in recent history, depref edge for first time
++          hedge->deprefUntil = t_now + pgbgp->edge_sus_time;
++          bgp_pgbgp_logEdgeAnomaly (rn, at, &curEdge);
++
++
++        UPE_DEPREF:
++          if (hedge->deprefUntil > max_depref)
++            max_depref = hedge->deprefUntil;
++        UPE_CLEAN:
++          hedge->lastSeen = t_now;
++        }
++    }
++  if (max_depref)
++    {
++      SET_FLAG (binfo->flags, BGP_INFO_SUSPICIOUS_E);
++      if (!hist->pEdgeReuse)
++        {
++          struct bgp_pgbgp_reuse *r;
++          r =
++            XCALLOC (MTYPE_BGP_PGBGP_REUSE, sizeof (struct bgp_pgbgp_reuse));
++          r->type = PGBGP_REUSE_EDGE;
++          r->deprefUntil = max_depref;
++          r->data.edge.rn = rn;
++          bgp_lock_node (rn);
++          pqueue_enqueue (r, pgbgp->reuse_q);
++          pgbgp->rq_size += 1;
++          hist->pEdgeReuse = r;
++        }
++      return BGP_INFO_SUSPICIOUS_E;
++    }
++
++  return 0;
++}
++
++int
++bgp_pgbgp_reuseEdge (struct bgp_pgbgp_r_edge data)
++{
++
++  // Okay, go through all of the paths for the prefix
++  // and find the path that needs to be updated next and
++  // enqueue it
++  time_t minMax = 0;
++  int numChanged = 0;
++  time_t t_now = time (NULL);
++
++  for (struct bgp_info * ri = data.rn->info; ri; ri = ri->next)
++    {
++      char first = true;
++      struct edge curEdge = { 0, 0 };
++      struct assegment *seg;
++      time_t max_depref = 0;
++
++      for (seg = ri->attr->aspath->segments; seg; seg = seg->next)
++        {
++          for (int i = 0; i < seg->length; i++)
++            {
++              curEdge.a = curEdge.b;
++              curEdge.b = seg->as[i];
++              if (first)
++                {
++                  first = false;
++                  continue;
++                }
++              struct bgp_pgbgp_edge finder;
++              finder.e = curEdge;
++              struct bgp_pgbgp_edge *hedge =
++                hash_lookup (pgbgp->edgeT, &finder);
++              if (!hedge)
++                continue;
++              // Is this edge suspicious?
++              if (hedge->deprefUntil > t_now
++                  && hedge->deprefUntil > max_depref)
++                max_depref = hedge->deprefUntil;
++            }
++        }
++
++      if (max_depref)
++        {
++          if (!minMax || max_depref < minMax)
++            minMax = max_depref;
++        }
++      else
++        {
++          if (CHECK_FLAG (ri->flags, BGP_INFO_SUSPICIOUS_E))
++            {
++              UNSET_FLAG (ri->flags, BGP_INFO_SUSPICIOUS_E);
++              numChanged += 1;
++            }
++        }
++    }
++  struct bgp_info *ri = data.rn->info;
++  if (numChanged > 0 && ri)
++    bgp_process (ri->peer->bgp, data.rn, data.rn->table->afi,
++                 data.rn->table->safi);
++
++  struct bgp_pgbgp_hist *hist = data.rn->hist;
++  hist->pEdgeReuse = NULL;
++
++  if (minMax)
++    {
++      struct bgp_pgbgp_reuse *r;
++      r = XCALLOC (MTYPE_BGP_PGBGP_REUSE, sizeof (struct bgp_pgbgp_reuse));
++      r->type = PGBGP_REUSE_EDGE;
++      r->deprefUntil = minMax;
++      r->data.edge.rn = data.rn;
++      pqueue_enqueue (r, pgbgp->reuse_q);
++      pgbgp->rq_size += 1;
++      hist->pEdgeReuse = r;
++    }
++  else
++    {
++      bgp_unlock_node (data.rn);
++    }
++
++  return 0;
++}
+--- /dev/null
++++ b/bgpd/bgp_pgbgp.h
+@@ -0,0 +1,286 @@
++/* BGP Pretty Good BGP
++   Copyright (C) 2008 University of New Mexico (Josh Karlin)
++
++This file is part of GNU Zebra.
++
++GNU Zebra 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, or (at your option) any
++later version.
++
++GNU Zebra 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.
++
++You should have received a copy of the GNU General Public License
++along with GNU Zebra; see the file COPYING.  If not, write to the Free
++Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
++02111-1307, USA.  */
++
++#ifndef _QUAGGA_BGP_PGBGP_H
++#define _QUAGGA_BGP_PGBGP_H
++
++#include "bgpd.h"
++#include "bgp_route.h"
++#include "table.h"
++
++#define MOAS 0
++#define SUBPREFIX 1
++#define EDGE 2
++
++/* Global PGBGP data */
++struct bgp_pgbgp_config
++{
++  /* Depref time for a new origin AS */
++  time_t origin_sus_time;
++
++  /* Depref time for a new edge */
++  time_t edge_sus_time;
++
++  /* Depref time for a new sub-prefix */
++  time_t sub_sus_time;
++
++  /* Origin AS Mapping History Length */
++  time_t origin_hist_time;
++
++  /* Prefix Mapping History Length */
++  time_t prefix_hist_time;
++
++  /* Edge Mapping History Length */
++  time_t edge_hist_time;
++
++  /* Peer Mapping History Length */
++  time_t peer_hist_time;
++
++  /* The list of depreferenced routes */
++  struct pqueue *reuse_q;
++  int rq_size;
++
++  /* Time that the last garbage collection (gc) took place */
++  time_t lastgc;
++
++  /* History table */
++  //    struct route_table *histT;
++
++  /* Edge Hash Table */
++  struct hash *edgeT;
++
++  /* File path for history storage */
++  char *storage;
++
++  /* File path for dump of anomalous routes */
++  char *anomalies;
++
++  /* The time that we last stored to disk */
++  time_t lastStore;
++
++  /* The time that PGBGP started counting */
++  time_t startTime;
++
++  /* Last time each peer was seen */
++  struct bgp_pgbgp_peerTime *peerLast;
++
++};
++
++
++struct bgp_pgbgp_peerTime
++{
++  struct bgp_pgbgp_peerTime *next;
++  time_t lastSeen;
++  union sockunion su;
++  time_t deprefUntil;
++};
++
++struct edge
++{
++  as_t a;
++  as_t b;
++};
++
++/*
++  Avoid the neighbors for the less specific that told you about
++  the more specific
++ */
++struct bgp_pgbgp_avoid
++{
++  struct bgp_pgbgp_avoid *next;
++  time_t avoidUntil;
++  as_t peerASN;
++  struct bgp_node *sub;
++};
++
++/* A list of origin ASes for a path
++   Usually it's only one but if the last AS
++   in the path is an AS set, then the whole
++   set must be returned 
++*/
++struct bgp_pgbgp_pathSet
++{
++  int length;
++  as_t *ases;
++};
++
++/*
++  Avoid paths with suspicious origins
++ */
++struct bgp_pgbgp_origin
++{
++  struct bgp_pgbgp_origin *next;
++  time_t lastSeen;
++  time_t deprefUntil;
++  as_t originAS;
++};
++
++/*
++  Ignore routes for this prefix
++ */
++struct bgp_pgbgp_prefix
++{
++  time_t lastSeen;
++  time_t ignoreUntil;
++  struct bgp_pgbgp_avoid *avoid;
++};
++
++struct bgp_pgbgp_edge
++{
++  time_t lastSeen;
++  time_t deprefUntil;
++  struct edge e;
++};
++
++struct bgp_pgbgp_hist
++{
++  struct bgp_pgbgp_origin *o;
++  struct bgp_pgbgp_prefix *p;
++  struct bgp_pgbgp_reuse *pEdgeReuse;
++};
++
++struct bgp_pgbgp_r_origin
++{
++  as_t originAS;
++  struct bgp_node *rn;
++};
++
++struct bgp_pgbgp_r_prefix
++{
++  struct bgp_node *rn;
++  struct bgp_node *rnsuper;
++};
++
++/*
++  This node contained a route with a bad edge, check 
++  it again for bad edges in 24 hours
++*/
++struct bgp_pgbgp_r_edge
++{
++  struct bgp_node *rn;
++};
++
++
++union reuseTypes
++{
++  struct bgp_pgbgp_r_origin origin;
++  struct bgp_pgbgp_r_prefix prefix;
++  struct bgp_pgbgp_r_edge edge;
++};
++
++struct bgp_pgbgp_reuse
++{
++  union reuseTypes data;
++  short type;
++  time_t deprefUntil;
++};
++
++#define ANOMALOUS(V) \
++(CHECK_FLAG(V, BGP_INFO_SUSPICIOUS_O | BGP_INFO_SUSPICIOUS_P \
++          | BGP_INFO_SUSPICIOUS_E | BGP_INFO_IGNORED_P))
++
++#define PGBGP_REUSE_ORIGIN 0
++#define PGBGP_REUSE_PREFIX 1
++#define PGBGP_REUSE_EDGE 2
++
++#define BGP_PGBGP_NONE      0
++#define BGP_PGBGP_DEPREFFED 1
++
++// For storage
++#define ORIGIN_ID 0
++#define PREFIX_ID 1
++#define EDGE_ID 2
++#define PEER_ID 3
++
++/* Default timing values */
++#define DEFAULT_ORIGIN_SUS       (86400 * 1)
++#define DEFAULT_EDGE_SUS         (86400 * 1)
++#define DEFAULT_SUB_SUS          (86400 * 1)
++#define DEFAULT_ORIGIN_HIST      (86400 * 30)
++#define DEFAULT_PREFIX_HIST      (86400 * 10)
++#define DEFAULT_EDGE_HIST        (86400 * 60)
++// Time between garbage collections
++#define PGBGP_GC_DELTA           (3600)
++// Time between file stores
++#define PGBGP_STORE_DELTA        (28800)
++// Time that a new peer's routes are not considered suspicious
++#define PGBGP_PEER_GRACE         (86400 * 1)
++
++
++
++///////// PUBLIC PGBGP FUNCTIONS /////////
++
++/*
++  bgp_pgbgp_enable:
++  Enable PGBGP depreferencing / history tracking for this afi/safi
++  
++  Arguments:
++  . ost: Depref. time of new prefix origins (in hours)
++  . est: Depref. time of new edges (in hours)
++  . sst: Depref. time of new sub-prefixes (in hours)
++  . oht: Storage time of known origins for prefixes (in days)
++  . pht: Storage time of known prefixes (in days)
++  . eht: Storage time of known edges (in days)
++  . storage: File to periodically store history in (can be /dev/null)
++  . anoms: File to store history of depreferenced routes (can be /dev/null)
++
++  Caution:
++  It is important that the storage times are longer than the depreference times
++*/
++extern int bgp_pgbgp_enable (struct bgp *, afi_t afi, safi_t safi, int ost,
++                             int est, int sst, int oht, int pht, int eht,
++                             const char *storage, const char *anoms);
++extern int bgp_pgbgp_disable (struct bgp *, afi_t afi, safi_t safi);
++
++/*
++  bgp_pgbgp_update:
++  Call on the event of an announcement update
++  
++  Arguments:
++  bgp_info: The route
++  at: The new route's attributes
++*/
++extern int bgp_pgbgp_update (struct bgp_info *, struct attr *at,
++                             struct bgp_node *);
++
++/*
++  bgp_pgbgp_rib_updated:
++  Call upon discovery of a new best path (or lack thereof)
++
++  This is a special case function for smoothly handling sub-prefix hijacks.
++
++  It handles the following 2 events:
++
++  Event 1: An anomalous sub-prefix is ignored, but no best route for the super-prefix exists
++  Response: Announce the sub-prefix until the super-prefix comes back
++
++  Event 2: A super-prefix comes back to the RIB and its anomalous sub-prefix is in use
++  Response: Ignore the sub-prefix again
++
++  Arguments:
++  rn: The route node that a new best path was found for
++  old_best: The old best route (NULL if one did not exist)
++  new_best: The current best route (NULL if one does not exist)
++ */
++extern int
++bgp_pgbgp_rib_updated (struct bgp_node *rn, struct bgp_info *old_best,
++                       struct bgp_info *new_best);
++
++#endif
+--- a/bgpd/bgp_route.c
++++ b/bgpd/bgp_route.c
+@@ -51,6 +51,7 @@ Software Foundation, Inc., 59 Temple Pla
+ #include "bgpd/bgp_mplsvpn.h"
+ #include "bgpd/bgp_nexthop.h"
+ #include "bgpd/bgp_damp.h"
++#include "bgpd/bgp_pgbgp.h"
+ #include "bgpd/bgp_advertise.h"
+ #include "bgpd/bgp_zebra.h"
+ #include "bgpd/bgp_vty.h"
+@@ -353,6 +354,12 @@ bgp_info_cmp (struct bgp *bgp, struct bg
+   if (exist == NULL)
+     return 1;
++  /* 0.5 PGBGP Depref. Check */
++  if (ANOMALOUS(exist->flags) && !ANOMALOUS(new->flags))
++    return 1;
++  if (!ANOMALOUS(exist->flags) && ANOMALOUS(new->flags))
++    return 0;
++
+   newattr = new->attr;
+   existattr = exist->attr;
+   newattre = newattr->extra;
+@@ -1602,6 +1609,10 @@ bgp_process_main (struct work_queue *wq,
+       UNSET_FLAG (new_select->flags, BGP_INFO_MULTIPATH_CHG);
+     }
++  /* PGBGP needs to know about selected routes  */
++  if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_PGBGP))
++    bgp_pgbgp_rib_updated(rn, old_select, new_select);
++
+   /* Check each BGP peer. */
+   for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
+@@ -1925,6 +1936,11 @@ bgp_update_rsclient (struct peer *rsclie
+   /* If the update is implicit withdraw. */
+   if (ri)
+     {
++      /* Update PGBGP state, and mark the route as anomalous if necessary */
++      if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_PGBGP)
++        && peer_sort(peer) == BGP_PEER_EBGP) 
++      bgp_pgbgp_update(ri, attr_new, rn);
++
+       ri->uptime = bgp_clock ();
+       /* Same attribute comes in. */
+@@ -2356,6 +2372,11 @@ bgp_update_main (struct peer *peer, stru
+   /* Increment prefix */
+   bgp_aggregate_increment (bgp, p, new, afi, safi);
+   
++  /* Update PGBGP state, and mark the route as anomalous if necessary */
++  if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_PGBGP)
++      && peer_sort(peer) == BGP_PEER_EBGP) 
++    bgp_pgbgp_update(new, attr_new, rn);
++  
+   /* Register new BGP information. */
+   bgp_info_add (rn, new);
+   
+@@ -5626,6 +5647,20 @@ enum bgp_display_type
+ static void
+ route_vty_short_status_out (struct vty *vty, struct bgp_info *binfo)
+ {
++  if (ANOMALOUS(binfo->flags))
++    {
++      vty_out(vty, "a[");
++      if (CHECK_FLAG(binfo->flags, BGP_INFO_SUSPICIOUS_P))
++      vty_out(vty, "i");
++      if (CHECK_FLAG(binfo->flags, BGP_INFO_SUSPICIOUS_O))
++      vty_out(vty, "p");
++      if (CHECK_FLAG(binfo->flags, BGP_INFO_SUSPICIOUS_E))
++      vty_out(vty, "e");
++      if (CHECK_FLAG(binfo->flags, BGP_INFO_IGNORED_P))
++      vty_out(vty, "s");
++      vty_out(vty, "] ");
++    }
++
+  /* Route status display. */
+   if (CHECK_FLAG (binfo->flags, BGP_INFO_REMOVED))
+     vty_out (vty, "R");
+@@ -6135,6 +6170,8 @@ route_vty_out_detail (struct vty *vty, s
+ #define BGP_SHOW_SCODE_HEADER "Status codes: s suppressed, d damped, "\
+                             "h history, * valid, > best, = multipath,%s"\
+               "              i internal, r RIB-failure, S Stale, R Removed%s"
++#define BGP_SHOW_PCODE_HEADER "Status code: a (anomalous) of:  [p] prefix hijack, [s] sub-prefix hijack,%s"\
++                "              [i] informant of sub-prefix [e] new edge%s"
+ #define BGP_SHOW_OCODE_HEADER "Origin codes: i - IGP, e - EGP, ? - incomplete%s%s"
+ #define BGP_SHOW_HEADER "   Network          Next Hop            Metric LocPrf Weight Path%s"
+ #define BGP_SHOW_DAMP_HEADER "   Network          From             Reuse    Path%s"
+@@ -6166,7 +6203,8 @@ enum bgp_show_type
+   bgp_show_type_flap_route_map,
+   bgp_show_type_flap_neighbor,
+   bgp_show_type_dampend_paths,
+-  bgp_show_type_damp_neighbor
++  bgp_show_type_damp_neighbor,
++  bgp_show_type_anomalous_paths
+ };
+ static int
+@@ -6333,11 +6371,17 @@ bgp_show_table (struct vty *vty, struct
+                   || CHECK_FLAG (ri->flags, BGP_INFO_HISTORY))
+                 continue;
+             }
++          if (type == bgp_show_type_anomalous_paths)
++            {
++              if (! ANOMALOUS(ri->flags))
++                continue;
++            }
+           if (header)
+             {
+               vty_out (vty, "BGP table version is 0, local router ID is %s%s", inet_ntoa (*router_id), VTY_NEWLINE);
+               vty_out (vty, BGP_SHOW_SCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE);
++              vty_out (vty, BGP_SHOW_PCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE);
+               vty_out (vty, BGP_SHOW_OCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE);
+               if (type == bgp_show_type_dampend_paths
+                   || type == bgp_show_type_damp_neighbor)
+@@ -6415,6 +6459,7 @@ bgp_show (struct vty *vty, struct bgp *b
+   return bgp_show_table (vty, table, &bgp->router_id, type, output_arg);
+ }
++
+ /* Header of detailed BGP route information */
+ static void
+ route_vty_out_detail_header (struct vty *vty, struct bgp *bgp,
+@@ -11987,6 +12032,64 @@ DEFUN (bgp_damp_set,
+                         half, reuse, suppress, max);
+ }
++DEFUN (bgp_pgbgp_arg,
++       bgp_pgbgp_arg_cmd,
++       "bgp pgbgp <1-100> <1-100> <1-100> <1-365> <1-365> <1-365> WORD WORD",
++       "BGP Specific commands\n"
++       "Enable Pretty Good BGP\n"
++       "New origin depref time (in hours)\n"
++       "New edge depref time (in hours)\n"
++       "New sub-prefix depref time (in hours)\n"
++       "Origin history time (in days)\n"
++       "Prefix history time (in days)\n"
++       "Edge history time (in days)\n"
++       "Log file for history data\n"
++       "Log file of anomalies\n")
++{
++  struct bgp *bgp;
++
++  int ost = DEFAULT_ORIGIN_SUS;
++  int est = DEFAULT_EDGE_SUS;
++  int sst = DEFAULT_SUB_SUS;
++  int oht = DEFAULT_ORIGIN_HIST;
++  int pht = DEFAULT_PREFIX_HIST;
++  int eht = DEFAULT_EDGE_HIST;
++  const char* path = "/var/log/quagga/pgbgp_hist";
++  const char* anoms = "/var/log/quagga/pgbgp_anomalies";
++
++ if (argc == 8)
++    {
++      VTY_GET_INTEGER("origin depref time", ost, argv[0]);
++      VTY_GET_INTEGER("edge depref time", est, argv[1]);
++      VTY_GET_INTEGER("sub-prefix depref time", sst, argv[2]);
++      VTY_GET_INTEGER("origin history time", oht, argv[3]);
++      VTY_GET_INTEGER("prefix history time", pht, argv[4]);
++      VTY_GET_INTEGER("edge history time", eht, argv[5]);
++      path = argv[6];
++      anoms = argv[7];
++    }
++ 
++  bgp = vty->index;
++  return bgp_pgbgp_enable(bgp, bgp_node_afi (vty), bgp_node_safi (vty), 
++                        ost, est, sst, oht, pht, eht, path, anoms);
++}
++
++ALIAS (bgp_pgbgp_arg,
++       bgp_pgbgp_cmd,
++       "bgp pgbgp",
++       "BGP specific commands\n"
++       "Enable Pretty Good BGP\n")
++
++DEFUN (bgp_pgbgp_unset,
++       bgp_pgbgp_unset_cmd,
++       "no bgp pgbgp\n",
++       "BGP specific commands\n")
++{
++  struct bgp *bgp;
++  bgp = vty->index;
++  return bgp_pgbgp_disable (bgp, bgp_node_afi (vty), bgp_node_safi (vty));
++}
++
+ ALIAS (bgp_damp_set,
+        bgp_damp_set2_cmd,
+        "bgp dampening <1-45>",
+@@ -12036,6 +12139,19 @@ DEFUN (show_ip_bgp_dampened_paths,
+                    NULL);
+ }
++DEFUN (show_ip_bgp_anomalous_paths,
++       show_ip_bgp_anomalous_paths_cmd,
++       "show ip bgp anomalous-paths",
++       SHOW_STR
++       IP_STR
++       BGP_STR
++       "Display anomalous paths (less likely to be used)\n")
++{
++  return bgp_show (vty, NULL, AFI_IP, SAFI_UNICAST, bgp_show_type_anomalous_paths,
++                 NULL);
++}
++
++
+ DEFUN (show_ip_bgp_flap_statistics,
+        show_ip_bgp_flap_statistics_cmd,
+        "show ip bgp flap-statistics",
+@@ -12562,6 +12678,7 @@ bgp_route_init (void)
+   install_element (VIEW_NODE, &show_ip_bgp_neighbor_received_prefix_filter_cmd);
+   install_element (VIEW_NODE, &show_ip_bgp_ipv4_neighbor_received_prefix_filter_cmd);
+   install_element (VIEW_NODE, &show_ip_bgp_dampened_paths_cmd);
++  install_element (VIEW_NODE, &show_ip_bgp_anomalous_paths_cmd);
+   install_element (VIEW_NODE, &show_ip_bgp_flap_statistics_cmd);
+   install_element (VIEW_NODE, &show_ip_bgp_flap_address_cmd);
+   install_element (VIEW_NODE, &show_ip_bgp_flap_prefix_cmd);
+@@ -12695,6 +12812,7 @@ bgp_route_init (void)
+   install_element (ENABLE_NODE, &show_ip_bgp_neighbor_received_prefix_filter_cmd);
+   install_element (ENABLE_NODE, &show_ip_bgp_ipv4_neighbor_received_prefix_filter_cmd);
+   install_element (ENABLE_NODE, &show_ip_bgp_dampened_paths_cmd);
++  install_element (ENABLE_NODE, &show_ip_bgp_anomalous_paths_cmd);
+   install_element (ENABLE_NODE, &show_ip_bgp_flap_statistics_cmd);
+   install_element (ENABLE_NODE, &show_ip_bgp_flap_address_cmd);
+   install_element (ENABLE_NODE, &show_ip_bgp_flap_prefix_cmd);
+@@ -13085,6 +13203,10 @@ bgp_route_init (void)
+   install_element (BGP_IPV4_NODE, &bgp_damp_unset_cmd);
+   install_element (BGP_IPV4_NODE, &bgp_damp_unset2_cmd);
+   
++  install_element (BGP_NODE, &bgp_pgbgp_cmd);
++  install_element (BGP_NODE, &bgp_pgbgp_arg_cmd);
++  install_element (BGP_NODE, &bgp_pgbgp_unset_cmd);
++
+   /* Deprecated AS-Pathlimit commands */
+   install_element (BGP_NODE, &bgp_network_ttl_cmd);
+   install_element (BGP_NODE, &bgp_network_mask_ttl_cmd);
+--- a/bgpd/bgp_route.h
++++ b/bgpd/bgp_route.h
+@@ -1,3 +1,4 @@
++
+ /* BGP routing information base
+    Copyright (C) 1996, 97, 98, 2000 Kunihiro Ishiguro
+@@ -68,7 +69,7 @@ struct bgp_info
+   int lock;
+   
+   /* BGP information status.  */
+-  u_int16_t flags;
++  u_int32_t flags;
+ #define BGP_INFO_IGP_CHANGED    (1 << 0)
+ #define BGP_INFO_DAMPED         (1 << 1)
+ #define BGP_INFO_HISTORY        (1 << 2)
+@@ -82,6 +83,10 @@ struct bgp_info
+ #define BGP_INFO_COUNTED      (1 << 10)
+ #define BGP_INFO_MULTIPATH      (1 << 11)
+ #define BGP_INFO_MULTIPATH_CHG  (1 << 12)
++#define BGP_INFO_SUSPICIOUS_O   (1 << 13)
++#define BGP_INFO_SUSPICIOUS_P   (1 << 14)
++#define BGP_INFO_IGNORED_P      (1 << 15)
++#define BGP_INFO_SUSPICIOUS_E   (1 << 16)
+   /* BGP route type.  This can be static, RIP, OSPF, BGP etc.  */
+   u_char type;
+@@ -126,7 +131,7 @@ struct bgp_static
+ /* Flags which indicate a route is unuseable in some form */
+ #define BGP_INFO_UNUSEABLE \
+-  (BGP_INFO_HISTORY|BGP_INFO_DAMPED|BGP_INFO_REMOVED)
++  (BGP_INFO_HISTORY|BGP_INFO_DAMPED|BGP_INFO_REMOVED|BGP_INFO_IGNORED_P)
+ /* Macro to check BGP information is alive or not.  Sadly,
+  * not equivalent to just checking previous, because of the
+  * sense of the additional VALID flag.
+--- a/bgpd/bgp_table.h
++++ b/bgpd/bgp_table.h
+@@ -63,6 +63,8 @@ struct bgp_node
+   struct bgp_node *prn;
++  struct bgp_pgbgp_hist *hist;
++
+   u_char flags;
+ #define BGP_NODE_PROCESS_SCHEDULED    (1 << 0)
+ };
+--- a/bgpd/bgpd.h
++++ b/bgpd/bgpd.h
+@@ -125,6 +125,7 @@ struct bgp
+   /* BGP Per AF flags */
+   u_int16_t af_flags[AFI_MAX][SAFI_MAX];
+ #define BGP_CONFIG_DAMPENING              (1 << 0)
++#define BGP_CONFIG_PGBGP                  (1 << 1)
+   /* Static route configuration.  */
+   struct bgp_table *route[AFI_MAX][SAFI_MAX];
+--- a/lib/hash.c
++++ b/lib/hash.c
+@@ -225,6 +225,35 @@ hash_iterate (struct hash *hash,
+       }
+ }
++/*
++  Iterates until 0 is returned or until completion
++  Return: 1 if iteration completed
++  Return: 0 if iteration was interrupted
++*/
++
++int
++hash_iterate_until(struct hash *hash,
++                 int (*func) (struct hash_backet *, void *), void *arg)
++{
++  unsigned int i;
++  struct hash_backet *hb;
++  struct hash_backet *hbnext;
++  int ret;
++  
++  for (i = 0; i < hash->size; i++)
++    for (hb = hash->index[i]; hb; hb = hbnext)
++      {
++      /* get pointer to next hash backet here, in case (*func)
++       * decides to delete hb by calling hash_release
++       */
++      hbnext = hb->next;
++      ret = (*func) (hb, arg);
++      if (!ret)
++        return 0;
++      }
++  return 1;
++}
++
+ /* Clean up hash.  */
+ void
+ hash_clean (struct hash *hash, void (*free_func) (void *))
+--- a/lib/hash.h
++++ b/lib/hash.h
+@@ -70,7 +70,8 @@ extern void *hash_release (struct hash *
+ extern void hash_iterate (struct hash *, 
+                  void (*) (struct hash_backet *, void *), void *);
+-
++extern int hash_iterate_until(struct hash *,
++                            int (*) (struct hash_backet *, void *), void *);
+ extern void hash_clean (struct hash *, void (*) (void *));
+ extern void hash_free (struct hash *);
+--- a/lib/memtypes.c
++++ b/lib/memtypes.c
+@@ -149,6 +149,15 @@ struct memory_list memory_list_bgp[] =
+   { MTYPE_PEER_UPDATE_SOURCE, "BGP peer update interface"     },
+   { MTYPE_BGP_DAMP_INFO,      "Dampening info"                },
+   { MTYPE_BGP_DAMP_ARRAY,     "BGP Dampening array"           },
++  { 0, NULL },
++  { MTYPE_BGP_PGBGP_ORIGIN,     "BGP PGBGP Origin AS Node"      },
++  { MTYPE_BGP_PGBGP_PREFIX,     "BGP PGBGP Prefix AS Node"      },
++  { MTYPE_BGP_PGBGP_EDGE,       "BGP PGBGP Edge Node"           },
++  { MTYPE_BGP_PGBGP_REUSE,      "BGP PGBGP Reuse Node"          },
++  { MTYPE_BGP_PGBGP_HIST,       "BGP PGBGP History Node"        },
++  { MTYPE_BGP_PGBGP_AVOID,      "BGP PGBGP Avoid Peer Node"     },
++  { MTYPE_BGP_PGBGP_PEER,       "BGP PGBGP Peer Timing"         },
++  { 0, NULL },
+   { MTYPE_BGP_REGEXP,         "BGP regexp"                    },
+   { MTYPE_BGP_AGGREGATE,      "BGP aggregate"                 },
+   { MTYPE_BGP_ADDR,           "BGP own address"               },
diff --git a/package/quagga/not-patches/patches-pgbgp/161-pgbgp-addon.patch b/package/quagga/not-patches/patches-pgbgp/161-pgbgp-addon.patch
new file mode 100644 (file)
index 0000000..49874a0
--- /dev/null
@@ -0,0 +1,318 @@
+From: Paul Jakma <paul.jakma@sun.com>
+Date: Thu, 4 Sep 2008 22:27:13 +0000 (+0100)
+Subject: [bgp/pgbgp] Add some pgbgp commands to restricted-mode and other command tweaks
+X-Git-Url: http://git.ozo.com/?p=quagga-pgbg.git;a=commitdiff_plain;h=06ac72f9f6021635e9e1e5105c3e22bf7eb0d6c3
+
+[bgp/pgbgp] Add some pgbgp commands to restricted-mode and other command tweaks
+
+* bgp_pgbgp.c:
+  (edge_neighbor_iterator) make ASN==0 mean 'iterate over all ASNs'
+  (bgp_pgbgp_stats_origin_one) new function, to display one origin AS status.
+  (bgp_pgbgp_stats_origins) adapt to use previous.
+  Adapt to iterate over all stats if no prefix was giving.
+  (show_ip_bgp_pgbgp_neighbors_cmd) recognise no ASN argument case
+  (show_ip_bgp_pgbgp_neighbors_all_cmd) Iterate over all
+  (show_ip_bgp_pgbgp_origins_cmd) similar
+  (show_ip_bgp_pgbgp_origins_all_cmd)
+  (bgp_pgbgp_enable) install the lookup commands to ther new RESTRICTED_NODE
+* bgp_route.c:
+  (route_vty_short_status_out) only allowed to print one char for anomalous
+  status.
+  (route_vty_out_detail) Add support for printing out more detail on
+  PG-BGP status
+---
+
+--- a/bgpd/bgp_pgbgp.c
++++ b/bgpd/bgp_pgbgp.c
+@@ -227,7 +227,7 @@ static void
+ edge_neighbor_iterator (struct hash_backet *backet, struct nsearch *pns)
+ {
+   struct bgp_pgbgp_edge *hedge = backet->data;
+-  if ((hedge->e.a == pns->asn || hedge->e.b == pns->asn)
++  if ((!pns->asn || hedge->e.a == pns->asn || hedge->e.b == pns->asn)
+       && hedge->e.a != hedge->e.b)
+     {
+       struct vty *vty = pns->pvty;
+@@ -254,13 +254,39 @@ bgp_pgbgp_stats_neighbors (struct vty *v
+   return CMD_SUCCESS;
+ }
++static void
++bgp_pgbgp_stats_origin_one (struct vty *vty, struct bgp_node *rn,
++                            time_t t_now)
++{
++  char str[INET6_BUFSIZ];
++  
++  if (!rn->hist)
++    return;
++  
++  prefix2str (&rn->p, str, sizeof(str));
++  vty_out (vty, "%s%s", str, VTY_NEWLINE);
++  
++  for (struct bgp_pgbgp_origin * cur = rn->hist->o; cur != NULL;
++       cur = cur->next)
++    {
++      if (cur->deprefUntil > t_now)
++        vty_out (vty, "Untrusted Origin AS: %d%s", cur->originAS,
++                 VTY_NEWLINE);
++      else
++        vty_out (vty, "Trusted Origin AS: %d%s", cur->originAS,
++                 VTY_NEWLINE);
++    } 
++}
++
+ static int
+ bgp_pgbgp_stats_origins (struct vty *vty, afi_t afi, safi_t safi,
+                          const char *prefix)
+ {
+   struct bgp *bgp;
+   struct bgp_table *table;
++  struct bgp_node *rn;
+   time_t t_now = time (NULL);
++  
+   bgp = bgp_get_default ();
+   if (bgp == NULL)
+     return CMD_WARNING;
+@@ -269,28 +295,22 @@ bgp_pgbgp_stats_origins (struct vty *vty
+   table = bgp->rib[afi][safi];
+   if (table == NULL)
+     return CMD_WARNING;
+-
+-  struct prefix p;
+-  str2prefix (prefix, &p);
+-  struct bgp_node *rn = bgp_node_match (table, &p);
+-  vty_out (vty, "%s%s", prefix, VTY_NEWLINE);
+-  if (rn)
++  
++  if (prefix)
+     {
++      struct prefix p;
++      str2prefix (prefix, &p);
++      rn = bgp_node_match (table, &p);
+       if (rn->hist)
+-        {
+-          for (struct bgp_pgbgp_origin * cur = rn->hist->o; cur != NULL;
+-               cur = cur->next)
+-            {
+-              if (cur->deprefUntil > t_now)
+-                vty_out (vty, "Untrusted Origin AS: %d%s", cur->originAS,
+-                         VTY_NEWLINE);
+-              else
+-                vty_out (vty, "Trusted Origin AS: %d%s", cur->originAS,
+-                         VTY_NEWLINE);
+-            }
+-        }
++        bgp_pgbgp_stats_origin_one (vty, rn, t_now);
+       bgp_unlock_node (rn);
++      return CMD_SUCCESS;
+     }
++  
++  for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
++    if (rn->hist)
++      bgp_pgbgp_stats_origin_one (vty, rn, t_now);
++
+   return CMD_SUCCESS;
+ }
+@@ -377,7 +397,7 @@ bgp_pgbgp_stats (struct vty *vty, afi_t
+ DEFUN (show_ip_bgp_pgbgp,
+        show_ip_bgp_pgbgp_cmd,
+        "show ip bgp pgbgp",
+-       SHOW_STR IP_STR BGP_STR "Display PGBGP statistics\n")
++       SHOW_STR IP_STR BGP_STR "Pretty-Good BGP statistics\n")
+ {
+   return bgp_pgbgp_stats (vty, AFI_IP, SAFI_UNICAST);
+ }
+@@ -385,29 +405,46 @@ DEFUN (show_ip_bgp_pgbgp,
+ DEFUN (show_ip_bgp_pgbgp_neighbors,
+        show_ip_bgp_pgbgp_neighbors_cmd,
+        "show ip bgp pgbgp neighbors WORD",
+-       SHOW_STR
+-       IP_STR
+-       BGP_STR
+-       "BGP pgbgp\n"
+-       "BGP pgbgp neighbors\n" "ASN whos neighbors should be displayed\n")
++       SHOW_STR IP_STR BGP_STR
++       "Pretty-Good BGP statistics\n"
++       "PG-BGP neighbor information\n"
++       "AS to show neighbors of\n")
+ {
+   return bgp_pgbgp_stats_neighbors (vty, AFI_IP, SAFI_UNICAST,
+-                                    atoi (argv[0]));
++                                    argc == 1 ? atoi (argv[0]) : 0);
+ }
++ALIAS (show_ip_bgp_pgbgp_neighbors,
++       show_ip_bgp_pgbgp_neighbors_all_cmd,
++       "show ip bgp pgbgp neighbors",
++       SHOW_STR
++       IP_STR
++       BGP_STR
++       "Pretty-Good BGP statistics\n"
++       "PG-BGP neighbors information\n")
++
+ DEFUN (show_ip_bgp_pgbgp_origins,
+        show_ip_bgp_pgbgp_origins_cmd,
+        "show ip bgp pgbgp origins A.B.C.D/M",
+        SHOW_STR
+        IP_STR
+        BGP_STR
+-       "BGP pgbgp\n"
+-       "BGP pgbgp neighbors\n" "Prefix to look up origin ASes of\n")
++       "Pretty-Good BGP statistics\n"
++       "PG-BGP prefix origin information\n"
++       "Prefix to look up origin ASes of\n")
+ {
+-  return bgp_pgbgp_stats_origins (vty, AFI_IP, SAFI_UNICAST, argv[0]);
++  return bgp_pgbgp_stats_origins (vty, AFI_IP, SAFI_UNICAST,
++                                  argc == 1 ? argv[0] : NULL);
+ }
+-
++ALIAS (show_ip_bgp_pgbgp_origins,
++       show_ip_bgp_pgbgp_origins_all_cmd,
++       "show ip bgp pgbgp origins",
++       SHOW_STR
++       IP_STR
++       BGP_STR
++       "Pretty-Good BGP statistics\n"
++       "PG-BGP prefixes origin information")
+ /*! --------------- VTY (others exist in bgp_route.c)  ------------------ !*/
+@@ -749,12 +786,19 @@ bgp_pgbgp_enable (struct bgp *bgp, afi_t
+   pgbgp->lastgc = time (NULL);
+   pgbgp->lastStore = time (NULL);
+   pgbgp->startTime = time (NULL);
++  install_element (RESTRICTED_NODE, &show_ip_bgp_pgbgp_cmd);
++  install_element (RESTRICTED_NODE, &show_ip_bgp_pgbgp_neighbors_cmd);
++  install_element (RESTRICTED_NODE, &show_ip_bgp_pgbgp_origins_cmd);
+   install_element (VIEW_NODE, &show_ip_bgp_pgbgp_cmd);
+-  install_element (ENABLE_NODE, &show_ip_bgp_pgbgp_cmd);
+   install_element (VIEW_NODE, &show_ip_bgp_pgbgp_neighbors_cmd);
+-  install_element (ENABLE_NODE, &show_ip_bgp_pgbgp_neighbors_cmd);
+   install_element (VIEW_NODE, &show_ip_bgp_pgbgp_origins_cmd);
++  install_element (VIEW_NODE, &show_ip_bgp_pgbgp_neighbors_all_cmd);
++  install_element (VIEW_NODE, &show_ip_bgp_pgbgp_origins_all_cmd);
++  install_element (ENABLE_NODE, &show_ip_bgp_pgbgp_cmd);
++  install_element (ENABLE_NODE, &show_ip_bgp_pgbgp_neighbors_cmd);
+   install_element (ENABLE_NODE, &show_ip_bgp_pgbgp_origins_cmd);
++  install_element (ENABLE_NODE, &show_ip_bgp_pgbgp_neighbors_all_cmd);
++  install_element (ENABLE_NODE, &show_ip_bgp_pgbgp_origins_all_cmd);
+   pgbgp->edgeT = hash_create_size (131072, edge_key_make, edge_cmp);
+   bgp_pgbgp_restore ();
+   return 0;
+--- a/bgpd/bgp_route.c
++++ b/bgpd/bgp_route.c
+@@ -5647,20 +5647,6 @@ enum bgp_display_type
+ static void
+ route_vty_short_status_out (struct vty *vty, struct bgp_info *binfo)
+ {
+-  if (ANOMALOUS(binfo->flags))
+-    {
+-      vty_out(vty, "a[");
+-      if (CHECK_FLAG(binfo->flags, BGP_INFO_SUSPICIOUS_P))
+-      vty_out(vty, "i");
+-      if (CHECK_FLAG(binfo->flags, BGP_INFO_SUSPICIOUS_O))
+-      vty_out(vty, "p");
+-      if (CHECK_FLAG(binfo->flags, BGP_INFO_SUSPICIOUS_E))
+-      vty_out(vty, "e");
+-      if (CHECK_FLAG(binfo->flags, BGP_INFO_IGNORED_P))
+-      vty_out(vty, "s");
+-      vty_out(vty, "] ");
+-    }
+-
+  /* Route status display. */
+   if (CHECK_FLAG (binfo->flags, BGP_INFO_REMOVED))
+     vty_out (vty, "R");
+@@ -5676,6 +5662,17 @@ route_vty_short_status_out (struct vty *
+   /* Selected */
+   if (CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
+     vty_out (vty, "h");
++  else if (ANOMALOUS(binfo->flags))
++    {
++      if (CHECK_FLAG(binfo->flags, BGP_INFO_SUSPICIOUS_O)) 
++        vty_out(vty, "p");
++      else if (CHECK_FLAG(binfo->flags, BGP_INFO_IGNORED_P))
++        vty_out(vty, "P");
++      else if (CHECK_FLAG(binfo->flags, BGP_INFO_SUSPICIOUS_P))
++        vty_out(vty, "a");
++      if (CHECK_FLAG(binfo->flags, BGP_INFO_SUSPICIOUS_E))
++        vty_out(vty, "a");
++    }
+   else if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED))
+     vty_out (vty, "d");
+   else if (CHECK_FLAG (binfo->flags, BGP_INFO_SELECTED))
+@@ -6156,7 +6153,22 @@ route_vty_out_detail (struct vty *vty, s
+       if (binfo->extra && binfo->extra->damp_info)
+       bgp_damp_info_vty (vty, binfo);
+-      /* Line 7 display Uptime */
++      /* 8: PGBGP status */
++      if (ANOMALOUS(binfo->flags))
++        {
++        vty_out (vty, "      Anomalous:");
++        if (CHECK_FLAG(binfo->flags, BGP_INFO_SUSPICIOUS_P))
++          vty_out (vty, " divergent sub-prefixes,");
++        if (CHECK_FLAG(binfo->flags, BGP_INFO_SUSPICIOUS_O))
++          vty_out (vty, " origin AS (prefix hijack?),");
++        if (CHECK_FLAG(binfo->flags, BGP_INFO_SUSPICIOUS_E))
++          vty_out (vty, " new edge in path,");
++        if (CHECK_FLAG(binfo->flags, BGP_INFO_IGNORED_P))
++          vty_out (vty, " origin AS (sub-prefix hijack?),");
++        vty_out (vty, "%s", VTY_NEWLINE);
++      } 
++
++      /* Line 9 display Uptime */     
+ #ifdef HAVE_CLOCK_MONOTONIC
+       tbuf = time(NULL) - (bgp_clock() - binfo->uptime);
+       vty_out (vty, "      Last update: %s", ctime(&tbuf));
+@@ -6169,9 +6181,8 @@ route_vty_out_detail (struct vty *vty, s
+ #define BGP_SHOW_SCODE_HEADER "Status codes: s suppressed, d damped, "\
+                             "h history, * valid, > best, = multipath,%s"\
+-              "              i internal, r RIB-failure, S Stale, R Removed%s"
+-#define BGP_SHOW_PCODE_HEADER "Status code: a (anomalous) of:  [p] prefix hijack, [s] sub-prefix hijack,%s"\
+-                "              [i] informant of sub-prefix [e] new edge%s"
++              "              i internal, r RIB-failure, S Stale, R Removed,%s"\
++              "              p prefix hijack, P sub-prefix hijack, a other anomaly%s"
+ #define BGP_SHOW_OCODE_HEADER "Origin codes: i - IGP, e - EGP, ? - incomplete%s%s"
+ #define BGP_SHOW_HEADER "   Network          Next Hop            Metric LocPrf Weight Path%s"
+ #define BGP_SHOW_DAMP_HEADER "   Network          From             Reuse    Path%s"
+@@ -6380,8 +6391,7 @@ bgp_show_table (struct vty *vty, struct
+           if (header)
+             {
+               vty_out (vty, "BGP table version is 0, local router ID is %s%s", inet_ntoa (*router_id), VTY_NEWLINE);
+-              vty_out (vty, BGP_SHOW_SCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE);
+-              vty_out (vty, BGP_SHOW_PCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE);
++              vty_out (vty, BGP_SHOW_SCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
+               vty_out (vty, BGP_SHOW_OCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE);
+               if (type == bgp_show_type_dampend_paths
+                   || type == bgp_show_type_damp_neighbor)
+@@ -9913,7 +9923,7 @@ show_adj_route (struct vty *vty, struct
+                         PEER_STATUS_DEFAULT_ORIGINATE))
+     {
+       vty_out (vty, "BGP table version is 0, local router ID is %s%s", inet_ntoa (bgp->router_id), VTY_NEWLINE);
+-      vty_out (vty, BGP_SHOW_SCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE);
++      vty_out (vty, BGP_SHOW_SCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
+       vty_out (vty, BGP_SHOW_OCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE);
+       vty_out (vty, "Originating default network 0.0.0.0%s%s",
+@@ -9930,7 +9940,7 @@ show_adj_route (struct vty *vty, struct
+             if (header1)
+               {
+                 vty_out (vty, "BGP table version is 0, local router ID is %s%s", inet_ntoa (bgp->router_id), VTY_NEWLINE);
+-                vty_out (vty, BGP_SHOW_SCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE);
++                vty_out (vty, BGP_SHOW_SCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
+                 vty_out (vty, BGP_SHOW_OCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE);
+                 header1 = 0;
+               }
+@@ -9954,7 +9964,7 @@ show_adj_route (struct vty *vty, struct
+             if (header1)
+               {
+                 vty_out (vty, "BGP table version is 0, local router ID is %s%s", inet_ntoa (bgp->router_id), VTY_NEWLINE);
+-                vty_out (vty, BGP_SHOW_SCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE);
++                vty_out (vty, BGP_SHOW_SCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
+                 vty_out (vty, BGP_SHOW_OCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE);
+                 header1 = 0;
+               }
diff --git a/package/quagga/not-patches/patches-pgbgp/162-bgp_table_wrapper.patch b/package/quagga/not-patches/patches-pgbgp/162-bgp_table_wrapper.patch
new file mode 100644 (file)
index 0000000..09157f7
--- /dev/null
@@ -0,0 +1,121 @@
+--- a/bgpd/bgp_pgbgp.c
++++ b/bgpd/bgp_pgbgp.c
+@@ -694,7 +694,7 @@ findSuper (struct bgp_table *table, stru
+   struct bgp_node *matched;
+   matched = NULL;
+-  node = table->top;
++  node = bgp_table_top_nolock (table);
+   while (node && node->p.prefixlen < p->prefixlen &&
+          prefix_match (&node->p, p))
+@@ -874,7 +874,8 @@ bgp_pgbgp_clean (struct bgp_table *table
+       if (changed && rn->info)
+         {
+           struct bgp_info *ri = rn->info;
+-          bgp_process (ri->peer->bgp, rn, rn->table->afi, rn->table->safi);
++          bgp_process (ri->peer->bgp, rn, bgp_node_table (rn)->afi, 
++                      bgp_node_table (rn)->safi);
+         }
+     }
+@@ -1166,7 +1167,8 @@ bgp_pgbgp_rib_updated (struct bgp_node *
+                   struct bgp_info *ri = cur->sub->info;
+                   if (ri && ri->peer && ri->peer->bgp)
+                     bgp_process (ri->peer->bgp, cur->sub,
+-                                 cur->sub->table->afi, cur->sub->table->safi);
++                                 bgp_node_table (cur->sub)->afi, 
++                                                bgp_node_table (cur->sub)->safi);
+                 }
+@@ -1200,7 +1202,8 @@ bgp_pgbgp_rib_updated (struct bgp_node *
+                   struct bgp_info *ri = cur->sub->info;
+                   if (ri && ri->peer && ri->peer->bgp)
+                     bgp_process (ri->peer->bgp, cur->sub,
+-                                 cur->sub->table->afi, cur->sub->table->safi);
++                                 bgp_node_table (cur->sub)->afi, 
++                                      bgp_node_table (cur->sub)->safi);
+                 }
+             }
+         }
+@@ -1270,7 +1273,7 @@ bgp_pgbgp_update (struct bgp_info *binfo
+   struct bgp_node *superhn = NULL;
+   // implicit lock from node_get
+-  superhn = findSuper (rn->table, &rn->p, t_now);
++  superhn = findSuper (bgp_node_table (rn), &rn->p, t_now);
+   int newPeer = bgp_pgbgp_updatePeer (binfo, t_now);
+   bgp_pgbgp_updateOrigin (rn->hist, binfo, at, rn, t_now, newPeer);
+@@ -1287,13 +1290,13 @@ bgp_pgbgp_update (struct bgp_info *binfo
+   // Make sure you don't collect anything that might be in use!
+   if (t_now >= pgbgp->lastgc + PGBGP_GC_DELTA)
+     {
+-      bgp_pgbgp_gc (rn->table);
++      bgp_pgbgp_gc (bgp_node_table (rn));
+       pgbgp->lastgc = t_now;
+     }
+   if (t_now >= pgbgp->lastStore + PGBGP_STORE_DELTA)
+     {
+-      bgp_pgbgp_store (rn->table);
++      bgp_pgbgp_store (bgp_node_table (rn));
+       pgbgp->lastStore = t_now;
+     }
+@@ -1682,8 +1685,8 @@ bgp_pgbgp_reuseOrigin (struct bgp_pgbgp_
+   // Rerun the decision process?
+   if (numChanged > 0)
+-    bgp_process (ri->peer->bgp, data.rn, data.rn->table->afi,
+-                 data.rn->table->safi);
++    bgp_process (ri->peer->bgp, data.rn, bgp_node_table (data.rn)->afi,
++                 bgp_node_table (data.rn)->safi);
+   /*
+@@ -1962,8 +1965,8 @@ UPP_IGNORE:
+   if (changed)
+     {
+       struct bgp_info *ri = supernode->info;
+-      bgp_process (ri->peer->bgp, supernode, supernode->table->afi,
+-                   supernode->table->safi);
++      bgp_process (ri->peer->bgp, supernode, bgp_node_table (supernode)->afi,
++                   bgp_node_table (supernode)->safi);
+     }
+ UPP_DONE:
+@@ -1986,8 +1989,8 @@ bgp_pgbgp_reusePrefix (struct bgp_pgbgp_
+   // Rerun the decision process
+   if (ri != NULL)
+-    bgp_process (ri->peer->bgp, data.rn, data.rn->table->afi,
+-                 data.rn->table->safi);
++    bgp_process (ri->peer->bgp, data.rn, bgp_node_table (data.rn)->afi,
++                 bgp_node_table (data.rn)->safi);
+   // Remove the avoid nodes from the super
+@@ -2021,8 +2024,8 @@ bgp_pgbgp_reusePrefix (struct bgp_pgbgp_
+               if (numChanged > 0 && ri != NULL)
+                 bgp_process (ri->peer->bgp, data.rnsuper,
+-                             data.rnsuper->table->afi,
+-                             data.rnsuper->table->safi);
++                             bgp_node_table (data.rnsuper)->afi,
++                             bgp_node_table (data.rnsuper)->safi);
+               bgp_unlock_node (del->sub);
+               XFREE (MTYPE_BGP_PGBGP_AVOID, del);
+             }
+@@ -2419,8 +2422,8 @@ bgp_pgbgp_reuseEdge (struct bgp_pgbgp_r_
+     }
+   struct bgp_info *ri = data.rn->info;
+   if (numChanged > 0 && ri)
+-    bgp_process (ri->peer->bgp, data.rn, data.rn->table->afi,
+-                 data.rn->table->safi);
++    bgp_process (ri->peer->bgp, data.rn, bgp_node_table (data.rn)->afi,
++                 bgp_node_table (data.rn)->safi);
+   struct bgp_pgbgp_hist *hist = data.rn->hist;
+   hist->pEdgeReuse = NULL;
diff --git a/package/quagga/not-patches/patches-pgbgp/162-pgbgp-bgp_table_wrapper.patch b/package/quagga/not-patches/patches-pgbgp/162-pgbgp-bgp_table_wrapper.patch
new file mode 100644 (file)
index 0000000..b5a508e
--- /dev/null
@@ -0,0 +1,120 @@
+--- a/bgpd/bgp_pgbgp.c
++++ b/bgpd/bgp_pgbgp.c
+@@ -694,7 +694,7 @@ findSuper (struct bgp_table *table, stru
+   struct bgp_node *matched;
+   matched = NULL;
+-  node = table->top;
++  node = bgp_table_top_nolock (table);
+   while (node && node->p.prefixlen < p->prefixlen &&
+          prefix_match (&node->p, p))
+@@ -874,7 +874,7 @@ bgp_pgbgp_clean (struct bgp_table *table
+       if (changed && rn->info)
+         {
+           struct bgp_info *ri = rn->info;
+-          bgp_process (ri->peer->bgp, rn, rn->table->afi, rn->table->safi);
++          bgp_process (ri->peer->bgp, rn, table->afi, table->safi);
+         }
+     }
+@@ -1166,7 +1166,8 @@ bgp_pgbgp_rib_updated (struct bgp_node *
+                   struct bgp_info *ri = cur->sub->info;
+                   if (ri && ri->peer && ri->peer->bgp)
+                     bgp_process (ri->peer->bgp, cur->sub,
+-                                 cur->sub->table->afi, cur->sub->table->safi);
++                                 bgp_node_table (cur->sub)->afi, 
++                                      bgp_node_table (cur->sub)->safi);
+                 }
+@@ -1200,7 +1201,8 @@ bgp_pgbgp_rib_updated (struct bgp_node *
+                   struct bgp_info *ri = cur->sub->info;
+                   if (ri && ri->peer && ri->peer->bgp)
+                     bgp_process (ri->peer->bgp, cur->sub,
+-                                 cur->sub->table->afi, cur->sub->table->safi);
++                                 bgp_node_table (cur->sub)->afi, 
++                                      bgp_node_table (cur->sub)->safi);
+                 }
+             }
+         }
+@@ -1270,7 +1272,7 @@ bgp_pgbgp_update (struct bgp_info *binfo
+   struct bgp_node *superhn = NULL;
+   // implicit lock from node_get
+-  superhn = findSuper (rn->table, &rn->p, t_now);
++  superhn = findSuper (bgp_node_table (rn), &rn->p, t_now);
+   int newPeer = bgp_pgbgp_updatePeer (binfo, t_now);
+   bgp_pgbgp_updateOrigin (rn->hist, binfo, at, rn, t_now, newPeer);
+@@ -1287,13 +1289,13 @@ bgp_pgbgp_update (struct bgp_info *binfo
+   // Make sure you don't collect anything that might be in use!
+   if (t_now >= pgbgp->lastgc + PGBGP_GC_DELTA)
+     {
+-      bgp_pgbgp_gc (rn->table);
++      bgp_pgbgp_gc (bgp_node_table (rn));
+       pgbgp->lastgc = t_now;
+     }
+   if (t_now >= pgbgp->lastStore + PGBGP_STORE_DELTA)
+     {
+-      bgp_pgbgp_store (rn->table);
++      bgp_pgbgp_store (bgp_node_table (rn));
+       pgbgp->lastStore = t_now;
+     }
+@@ -1682,8 +1684,8 @@ bgp_pgbgp_reuseOrigin (struct bgp_pgbgp_
+   // Rerun the decision process?
+   if (numChanged > 0)
+-    bgp_process (ri->peer->bgp, data.rn, data.rn->table->afi,
+-                 data.rn->table->safi);
++    bgp_process (ri->peer->bgp, data.rn, bgp_node_table (data.rn)->afi,
++                 bgp_node_table (data.rn)->safi);
+   /*
+@@ -1962,8 +1964,8 @@ UPP_IGNORE:
+   if (changed)
+     {
+       struct bgp_info *ri = supernode->info;
+-      bgp_process (ri->peer->bgp, supernode, supernode->table->afi,
+-                   supernode->table->safi);
++      bgp_process (ri->peer->bgp, supernode, bgp_node_table (supernode)->afi,
++                   bgp_node_table (supernode)->safi);
+     }
+ UPP_DONE:
+@@ -1986,8 +1988,8 @@ bgp_pgbgp_reusePrefix (struct bgp_pgbgp_
+   // Rerun the decision process
+   if (ri != NULL)
+-    bgp_process (ri->peer->bgp, data.rn, data.rn->table->afi,
+-                 data.rn->table->safi);
++    bgp_process (ri->peer->bgp, data.rn, bgp_node_table (data.rn)->afi,
++                 bgp_node_table (data.rn)->safi);
+   // Remove the avoid nodes from the super
+@@ -2021,8 +2023,8 @@ bgp_pgbgp_reusePrefix (struct bgp_pgbgp_
+               if (numChanged > 0 && ri != NULL)
+                 bgp_process (ri->peer->bgp, data.rnsuper,
+-                             data.rnsuper->table->afi,
+-                             data.rnsuper->table->safi);
++                             bgp_node_table (data.rnsuper)->afi,
++                             bgp_node_table (data.rnsuper)->safi);
+               bgp_unlock_node (del->sub);
+               XFREE (MTYPE_BGP_PGBGP_AVOID, del);
+             }
+@@ -2419,8 +2421,8 @@ bgp_pgbgp_reuseEdge (struct bgp_pgbgp_r_
+     }
+   struct bgp_info *ri = data.rn->info;
+   if (numChanged > 0 && ri)
+-    bgp_process (ri->peer->bgp, data.rn, data.rn->table->afi,
+-                 data.rn->table->safi);
++    bgp_process (ri->peer->bgp, data.rn, bgp_node_table (data.rn)->afi,
++                 bgp_node_table (data.rn)->safi);
+   struct bgp_pgbgp_hist *hist = data.rn->hist;
+   hist->pEdgeReuse = NULL;
diff --git a/package/quagga/not-patches/patches-pgbgp/170-use-supported-pagers.patch b/package/quagga/not-patches/patches-pgbgp/170-use-supported-pagers.patch
new file mode 100644 (file)
index 0000000..0a7d7f9
--- /dev/null
@@ -0,0 +1,29 @@
+--- a/vtysh/vtysh.c
++++ b/vtysh/vtysh.c
+@@ -268,7 +268,7 @@ vtysh_pager_init (void)
+   if (pager_defined)
+     vtysh_pager_name = strdup (pager_defined);
+   else
+-    vtysh_pager_name = strdup ("more");
++    vtysh_pager_name = strdup ("cat");
+ }
+ /* Command execution over the vty interface. */
+@@ -1885,7 +1885,7 @@ DEFUN (vtysh_terminal_length,
+ {
+   int lines;
+   char *endptr = NULL;
+-  char default_pager[10];
++  char default_pager[12];
+   lines = strtol (argv[0], &endptr, 10);
+   if (lines < 0 || lines > 512 || *endptr != '\0')
+@@ -1902,7 +1902,7 @@ DEFUN (vtysh_terminal_length,
+   if (lines != 0)
+     {
+-      snprintf(default_pager, 10, "more -%i", lines);
++      snprintf(default_pager, 12, "head -n %i", lines);
+       vtysh_pager_name = strdup (default_pager);
+     }
diff --git a/package/quagga/not-patches/patches-upstream/old/140-holdtimer-set.patch b/package/quagga/not-patches/patches-upstream/old/140-holdtimer-set.patch
new file mode 100644 (file)
index 0000000..83482d3
--- /dev/null
@@ -0,0 +1,22 @@
+--- a/bgpd/bgp_network.c
++++ b/bgpd/bgp_network.c
+@@ -256,8 +256,7 @@ bgp_accept (struct thread *thread)
+     peer->fd = bgp_sock;
+     peer->status = Active;
+     peer->local_id = peer1->local_id;
+-    peer->v_holdtime = peer1->v_holdtime;
+-    peer->v_keepalive = peer1->v_keepalive;
++    peer->v_holdtime = BGP_LARGE_HOLDTIME;
+     /* Make peer's address string. */
+     sockunion2str (&su, buf, SU_ADDRSTRLEN);
+--- a/bgpd/bgpd.h
++++ b/bgpd/bgpd.h
+@@ -739,6 +739,7 @@ struct bgp_nlri
+ /* BGP timers default value.  */
+ #define BGP_INIT_START_TIMER                     5
+ #define BGP_ERROR_START_TIMER                   30
++#define BGP_LARGE_HOLDTIME                     240
+ #define BGP_DEFAULT_HOLDTIME                   180
+ #define BGP_DEFAULT_KEEPALIVE                   60 
+ #define BGP_DEFAULT_ASORIGINATE                 15
diff --git a/package/quagga/not-patches/patches-upstream/old/150-no-cross-fs-link.patch b/package/quagga/not-patches/patches-upstream/old/150-no-cross-fs-link.patch
new file mode 100644 (file)
index 0000000..a8e9f84
--- /dev/null
@@ -0,0 +1,40 @@
+--- a/lib/command.c
++++ b/lib/command.c
+@@ -3064,6 +3064,13 @@ DEFUN (config_write_file,
+                VTY_NEWLINE);
+         goto finished;
+       }
++
++#if 0
++  /* This code fails on UNION MOUNTs and similar filesystems if the
++   * config file is still on the RO layer. Hardlinks across layers
++   * will not work and cause quagga to fail saving the configuration...
++   * should use rename() to move files around...
++   */
+   if (link (config_file, config_file_sav) != 0)
+     {
+       vty_out (vty, "Can't backup old configuration file %s.%s", config_file_sav,
+@@ -3077,7 +3084,23 @@ DEFUN (config_write_file,
+               VTY_NEWLINE);
+       goto finished;
+     }
++#else
++  /* And this is the code that hopefully does work */
++  if (rename (config_file, config_file_sav) != 0)
++    {
++      vty_out (vty, "Can't backup old configuration file %s.%s", config_file_sav,
++              VTY_NEWLINE);
++      goto finished;
++    }
++  sync ();
++#endif
++
++#if 0
++  /* same here. Please no cross-filesystem hardlinks... */
+   if (link (config_file_tmp, config_file) != 0)
++#else
++  if (rename (config_file_tmp, config_file) != 0)
++#endif
+     {
+       vty_out (vty, "Can't save configuration file %s.%s", config_file,
+              VTY_NEWLINE);
diff --git a/package/quagga/not-patches/patches-upstream/old/170-use-supported-pagers.patch b/package/quagga/not-patches/patches-upstream/old/170-use-supported-pagers.patch
new file mode 100644 (file)
index 0000000..0a7d7f9
--- /dev/null
@@ -0,0 +1,29 @@
+--- a/vtysh/vtysh.c
++++ b/vtysh/vtysh.c
+@@ -268,7 +268,7 @@ vtysh_pager_init (void)
+   if (pager_defined)
+     vtysh_pager_name = strdup (pager_defined);
+   else
+-    vtysh_pager_name = strdup ("more");
++    vtysh_pager_name = strdup ("cat");
+ }
+ /* Command execution over the vty interface. */
+@@ -1885,7 +1885,7 @@ DEFUN (vtysh_terminal_length,
+ {
+   int lines;
+   char *endptr = NULL;
+-  char default_pager[10];
++  char default_pager[12];
+   lines = strtol (argv[0], &endptr, 10);
+   if (lines < 0 || lines > 512 || *endptr != '\0')
+@@ -1902,7 +1902,7 @@ DEFUN (vtysh_terminal_length,
+   if (lines != 0)
+     {
+-      snprintf(default_pager, 10, "more -%i", lines);
++      snprintf(default_pager, 12, "head -n %i", lines);
+       vtysh_pager_name = strdup (default_pager);
+     }
diff --git a/package/quagga/patches-upstream/150-unknown_afi.patch b/package/quagga/patches-upstream/150-unknown_afi.patch
new file mode 100644 (file)
index 0000000..e5e402a
--- /dev/null
@@ -0,0 +1,28 @@
+--- a/bgpd/bgp_packet.c
++++ b/bgpd/bgp_packet.c
+@@ -1631,7 +1631,7 @@ bgp_update_receive (struct peer *peer, b
+     NLRI_TYPE_MAX,
+   };
+   struct bgp_nlri nlris[NLRI_TYPE_MAX];
+-
++  
+   /* Status must be Established. */
+   if (peer->status != Established) 
+     {
+@@ -1645,6 +1645,7 @@ bgp_update_receive (struct peer *peer, b
+   memset (&attr, 0, sizeof (struct attr));
+   memset (&extra, 0, sizeof (struct attr_extra));
+   memset (&nlris, 0, sizeof nlris);
++  
+   attr.extra = &extra;
+   s = peer->ibuf;
+@@ -1781,6 +1782,8 @@ bgp_update_receive (struct peer *peer, b
+   /* Parse any given NLRIs */
+   for (i = NLRI_UPDATE; i < NLRI_TYPE_MAX; i++)
+     {
++      if (!nlris[i].nlri) continue;
++      
+       /* We use afi and safi as indices into tables and what not.  It would
+        * be impossible, at this time, to support unknown afi/safis.  And
+        * anyway, the peer needs to be configured to enable the afi/safi
diff --git a/package/quagga/patches-upstream/200-bgp_dampening.patch b/package/quagga/patches-upstream/200-bgp_dampening.patch
new file mode 100644 (file)
index 0000000..ccb0d32
--- /dev/null
@@ -0,0 +1,25 @@
+From f99d2f1c5cfdb21be1fa28dabc5fc48a7cd71ed8 Mon Sep 17 00:00:00 2001
+From: Balaji <balajig81@gmail.com>
+Date: Wed, 20 Jan 2016 17:29:27 +0000
+Subject: bgpd: Addition of bgp dampening configuration commands under IPv4/multicast
+
+Signed-off-by: Balaji Gurudoss <balajig81@gmail.com>
+Tested-by: NetDEF CI System <cisystem@netdef.org>
+---
+--- a/bgpd/bgp_route.c
++++ b/bgpd/bgp_route.c
+@@ -16264,6 +16264,14 @@ bgp_route_init (void)
+   install_element (BGP_IPV4_NODE, &bgp_damp_set3_cmd);
+   install_element (BGP_IPV4_NODE, &bgp_damp_unset_cmd);
+   install_element (BGP_IPV4_NODE, &bgp_damp_unset2_cmd);
++
++  /* IPv4 Multicast Mode */
++  install_element (BGP_IPV4M_NODE, &bgp_damp_set_cmd);
++  install_element (BGP_IPV4M_NODE, &bgp_damp_set2_cmd);
++  install_element (BGP_IPV4M_NODE, &bgp_damp_set3_cmd);
++  install_element (BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
++  install_element (BGP_IPV4M_NODE, &bgp_damp_unset2_cmd);
++
+   
+   /* Deprecated AS-Pathlimit commands */
+   install_element (BGP_NODE, &bgp_network_ttl_cmd);
diff --git a/package/quagga/patches-upstream/210-dampening_commands.patch b/package/quagga/patches-upstream/210-dampening_commands.patch
new file mode 100644 (file)
index 0000000..6163e3d
--- /dev/null
@@ -0,0 +1,100 @@
+From 5cfa8d706450a65660ba589581790da8bd0e4adc Mon Sep 17 00:00:00 2001
+From: Balaji <balajig81@gmail.com>
+Date: Wed, 20 Jan 2016 17:29:26 +0000
+Subject: bgpd: Addition of dampening show commands under v4 unicast/multicast tree
+
+Patch contains addition of show ip bgp ipv4 (unicast| multicast)
+dampening tree.
+
+Signed-off-by: Balaji Gurudoss <balajig81@gmail.com>
+---
+--- a/bgpd/bgp_route.c
++++ b/bgpd/bgp_route.c
+@@ -8603,6 +8603,66 @@ DEFUN (show_bgp_ipv6_filter_list,
+                              bgp_show_type_filter_list);
+ }
++
++DEFUN (show_ip_bgp_ipv4_dampening_parameters, 
++       show_ip_bgp_ipv4_dampening_parameters_cmd,
++       "show ip bgp ipv4 (unicast|multicast) dampening parameters",
++       SHOW_STR
++       IP_STR
++       BGP_STR
++       "Address family\n"
++       "Address Family modifier\n"
++       "Address Family modifier\n"
++       "Display detailed information about dampening\n"
++       "Display detail of configured dampening parameters\n")
++{
++    if (strncmp(argv[0], "m", 1) == 0)
++      return bgp_show_dampening_parameters (vty, AFI_IP, SAFI_MULTICAST);
++
++    return bgp_show_dampening_parameters (vty, AFI_IP, SAFI_UNICAST);
++}
++
++
++DEFUN (show_ip_bgp_ipv4_dampening_flap_stats,
++       show_ip_bgp_ipv4_dampening_flap_stats_cmd,
++       "show ip bgp ipv4 (unicast|multicast) dampening flap-statistics",
++       SHOW_STR
++       IP_STR
++       BGP_STR
++       "Address family\n"
++       "Address Family modifier\n"
++       "Address Family modifier\n"
++       "Display detailed information about dampening\n"
++       "Display flap statistics of routes\n")
++{
++    if (strncmp(argv[0], "m", 1) == 0)      
++      return bgp_show (vty, NULL, AFI_IP, SAFI_MULTICAST,
++                     bgp_show_type_flap_statistics, NULL);
++
++    return bgp_show (vty, NULL, AFI_IP, SAFI_MULTICAST,
++                 bgp_show_type_flap_statistics, NULL);
++}
++
++DEFUN (show_ip_bgp_ipv4_dampening_dampd_paths, 
++       show_ip_bgp_ipv4_dampening_dampd_paths_cmd,
++       "show ip bgp ipv4 (unicast|multicast) dampening dampened-paths",
++       SHOW_STR
++       IP_STR
++       BGP_STR
++       "Address family\n"
++       "Address Family modifier\n"
++       "Address Family modifier\n"
++       "Display detailed information about dampening\n"
++       "Display paths suppressed due to dampening\n")
++{
++    if (strncmp(argv[0], "m", 1) == 0)      
++      return bgp_show (vty, NULL, AFI_IP, SAFI_MULTICAST,
++                     bgp_show_type_dampend_paths, NULL);
++
++    return bgp_show (vty, NULL, AFI_IP, SAFI_MULTICAST,
++                 bgp_show_type_dampend_paths, NULL);
++}
++
+ static int
+ bgp_show_route_map (struct vty *vty, const char *rmap_str, afi_t afi,
+                   safi_t safi, enum bgp_show_type type)
+@@ -16376,7 +16436,10 @@ bgp_route_init (void)
+   install_element (VIEW_NODE, &show_ip_bgp_neighbor_received_prefix_filter_cmd);
+   install_element (VIEW_NODE, &show_ip_bgp_ipv4_neighbor_received_prefix_filter_cmd);
+   install_element (VIEW_NODE, &show_ip_bgp_dampening_params_cmd);
++  install_element (VIEW_NODE, &show_ip_bgp_ipv4_dampening_parameters_cmd);
+   install_element (VIEW_NODE, &show_ip_bgp_dampened_paths_cmd);
++  install_element (VIEW_NODE, &show_ip_bgp_ipv4_dampening_dampd_paths_cmd);
++  install_element (VIEW_NODE, &show_ip_bgp_ipv4_dampening_flap_stats_cmd);
+   install_element (VIEW_NODE, &show_ip_bgp_damp_dampened_paths_cmd);
+   install_element (VIEW_NODE, &show_ip_bgp_flap_statistics_cmd);
+   install_element (VIEW_NODE, &show_ip_bgp_damp_flap_statistics_cmd);
+@@ -16490,6 +16553,9 @@ bgp_route_init (void)