diff options
Diffstat (limited to 'ospfd')
45 files changed, 6420 insertions, 1053 deletions
diff --git a/ospfd/.cvsignore b/ospfd/.cvsignore index d7e3a7e2..876c4348 100644 --- a/ospfd/.cvsignore +++ b/ospfd/.cvsignore @@ -1,4 +1,5 @@ Makefile +Makefile.in *.o ospfd ospfd.conf diff --git a/ospfd/ChangeLog b/ospfd/ChangeLog index b7794f72..7720adcc 100644 --- a/ospfd/ChangeLog +++ b/ospfd/ChangeLog @@ -1,3 +1,50 @@ +2003-05-24 Kenji Yabuuchi + + * ospf_interface.c(ospf_if_lookup_recv_if): Use the most specific + match for interface lookup. + +2003-05-18 Hasso Tepper <hasso@estpak.ee> + + * ospf_vty.c: Show NSSA LSA route info in "show ip ospf database" + output + +2003-05-16 Hasso Tepper <hasso@estpak.ee> + + * ospf_lsa.c: Fix handling of NSSA + +2003-04-23 Hasso Tepper <hasso@estpak.ee> + + * ospf_vty.c: fix "router xxx" node commands in vtysh + +2003-04-19 Hasso Tepper <hasso@estpak.ee> + + * {ospf_abr,ospfd}.c: area id's DECIMAL -> ADDRESS + * ospf_routemap.c: sync daemon's route-map commands to have same + syntax. + +2003-04-19 Sergey Vyshnevetskiy <serg@vostok.net> + + * ospf_packet.c: Add missing param to zlog + * ospf_flood.c: remove unused vars + +2003-04-17 Denis Ovsienko <zebra@pilot.org.ua> + + * ospf_interface.c: fix incorrect memset + +2003-04-10 Amir Guindehi <amir@datacore.ch> + + * ospf_lsa.[ch]: opaque LSA fix, use ospf_lookup. + +2003-04-03 David Watson <dwatson@eecs.umich.edu> + + * ospf_lsa.c: byte order fix + +2002-03-17 Amir Guindehi <amir@datacore.ch> + + * ospf_apiserver.[ch]: Merge Ralph Keller's OSPFAPI support. + * ospf_api.[ch]: Merge Ralph Keller's OSPFAPI support. + * ospfclient: OSPFAPI demonstration client. + 2003-01-23 Masahiko Endo <endo@suri.co.jp> * ospf_ism.c: NSM event schedule bug fix. diff --git a/ospfd/Makefile.am b/ospfd/Makefile.am index 81f212c4..81315dae 100644 --- a/ospfd/Makefile.am +++ b/ospfd/Makefile.am @@ -28,7 +28,7 @@ noinst_HEADERS = \ ospfd_SOURCES = \ ospf_main.c $(libospf_a_SOURCES) -ospfd_LDADD = -L../lib -lzebra @LIBCAP@ +ospfd_LDADD = -L../lib -lzebra sysconf_DATA = ospfd.conf.sample diff --git a/ospfd/Makefile.in b/ospfd/Makefile.in deleted file mode 100644 index 7182572a..00000000 --- a/ospfd/Makefile.in +++ /dev/null @@ -1,461 +0,0 @@ -# Makefile.in generated by automake 1.6.3 from Makefile.am. -# @configure_input@ - -# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 -# Free Software Foundation, Inc. -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ -SHELL = @SHELL@ - -srcdir = @srcdir@ -top_srcdir = @top_srcdir@ -VPATH = @srcdir@ -prefix = @prefix@ -exec_prefix = @exec_prefix@ - -bindir = @bindir@ -sbindir = @sbindir@ -libexecdir = @libexecdir@ -datadir = @datadir@ -sysconfdir = @sysconfdir@ -sharedstatedir = @sharedstatedir@ -localstatedir = @localstatedir@ -libdir = @libdir@ -infodir = @infodir@ -mandir = @mandir@ -includedir = @includedir@ -oldincludedir = /usr/include -pkgdatadir = $(datadir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -top_builddir = .. - -ACLOCAL = @ACLOCAL@ -AUTOCONF = @AUTOCONF@ -AUTOMAKE = @AUTOMAKE@ -AUTOHEADER = @AUTOHEADER@ - -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -INSTALL = @INSTALL@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_DATA = @INSTALL_DATA@ -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_HEADER = $(INSTALL_DATA) -transform = @program_transform_name@ -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -host_alias = @host_alias@ -host_triplet = @host@ - -EXEEXT = @EXEEXT@ -OBJEXT = @OBJEXT@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -AMTAR = @AMTAR@ -AR = @AR@ -AWK = @AWK@ -BGPD = @BGPD@ -CC = @CC@ -CPP = @CPP@ -CURSES = @CURSES@ -DEPDIR = @DEPDIR@ -IF_METHOD = @IF_METHOD@ -IF_PROC = @IF_PROC@ - -INCLUDES = @INCLUDES@ -I.. -I$(top_srcdir) -I$(top_srcdir)/lib -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -IPFORWARD = @IPFORWARD@ -KERNEL_METHOD = @KERNEL_METHOD@ -LIBPAM = @LIBPAM@ -LIB_IPV6 = @LIB_IPV6@ -LIB_REGEX = @LIB_REGEX@ -MULTIPATH_NUM = @MULTIPATH_NUM@ -OSPF6D = @OSPF6D@ -OSPFD = @OSPFD@ -OTHER_METHOD = @OTHER_METHOD@ -PACKAGE = @PACKAGE@ -RANLIB = @RANLIB@ -RIPD = @RIPD@ -RIPNGD = @RIPNGD@ -RTREAD_METHOD = @RTREAD_METHOD@ -RT_METHOD = @RT_METHOD@ -STRIP = @STRIP@ -VERSION = @VERSION@ -VTYSH = @VTYSH@ -ZEBRA = @ZEBRA@ -am__include = @am__include@ -am__quote = @am__quote@ -install_sh = @install_sh@ -DEFS = @DEFS@ $(LOCAL_OPTS) -DSYSCONFDIR=\"$(sysconfdir)/\" -INSTALL_SDATA = @INSTALL@ -m 600 - -noinst_LIBRARIES = libospf.a -sbin_PROGRAMS = ospfd - -libospf_a_SOURCES = \ - ospfd.c ospf_zebra.c ospf_interface.c ospf_ism.c ospf_neighbor.c \ - ospf_nsm.c ospf_dump.c ospf_network.c ospf_packet.c ospf_lsa.c \ - ospf_spf.c ospf_route.c ospf_ase.c ospf_abr.c ospf_ia.c ospf_flood.c \ - ospf_lsdb.c ospf_asbr.c ospf_routemap.c ospf_snmp.c \ - ospf_opaque.c ospf_te.c ospf_vty.c - - -noinst_HEADERS = \ - ospf_dump.h ospf_interface.h ospf_ism.h ospf_neighbor.h \ - ospf_network.h ospf_nsm.h ospf_packet.h ospf_zebra.h ospfd.h \ - ospf_lsa.h ospf_spf.h ospf_route.h ospf_ase.h ospf_abr.h ospf_ia.h \ - ospf_flood.h ospf_lsdb.h ospf_asbr.h ospf_snmp.h ospf_opaque.h \ - ospf_te.h ospf_vty.h - - -ospfd_SOURCES = \ - ospf_main.c $(libospf_a_SOURCES) - - -ospfd_LDADD = ../lib/libzebra.a - -sysconf_DATA = ospfd.conf.sample - -EXTRA_DIST = $(sysconf_DATA) OSPF-MIB.txt OSPF-TRAP-MIB.txt ChangeLog.opaque.txt -subdir = ospfd -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs -CONFIG_HEADER = $(top_builddir)/config.h -CONFIG_CLEAN_FILES = -LIBRARIES = $(noinst_LIBRARIES) - -libospf_a_AR = $(AR) cru -libospf_a_LIBADD = -am_libospf_a_OBJECTS = ospfd.$(OBJEXT) ospf_zebra.$(OBJEXT) \ - ospf_interface.$(OBJEXT) ospf_ism.$(OBJEXT) \ - ospf_neighbor.$(OBJEXT) ospf_nsm.$(OBJEXT) ospf_dump.$(OBJEXT) \ - ospf_network.$(OBJEXT) ospf_packet.$(OBJEXT) ospf_lsa.$(OBJEXT) \ - ospf_spf.$(OBJEXT) ospf_route.$(OBJEXT) ospf_ase.$(OBJEXT) \ - ospf_abr.$(OBJEXT) ospf_ia.$(OBJEXT) ospf_flood.$(OBJEXT) \ - ospf_lsdb.$(OBJEXT) ospf_asbr.$(OBJEXT) ospf_routemap.$(OBJEXT) \ - ospf_snmp.$(OBJEXT) ospf_opaque.$(OBJEXT) ospf_te.$(OBJEXT) \ - ospf_vty.$(OBJEXT) -libospf_a_OBJECTS = $(am_libospf_a_OBJECTS) -sbin_PROGRAMS = ospfd$(EXEEXT) -PROGRAMS = $(sbin_PROGRAMS) - -am__objects_1 = ospfd.$(OBJEXT) ospf_zebra.$(OBJEXT) \ - ospf_interface.$(OBJEXT) ospf_ism.$(OBJEXT) \ - ospf_neighbor.$(OBJEXT) ospf_nsm.$(OBJEXT) ospf_dump.$(OBJEXT) \ - ospf_network.$(OBJEXT) ospf_packet.$(OBJEXT) ospf_lsa.$(OBJEXT) \ - ospf_spf.$(OBJEXT) ospf_route.$(OBJEXT) ospf_ase.$(OBJEXT) \ - ospf_abr.$(OBJEXT) ospf_ia.$(OBJEXT) ospf_flood.$(OBJEXT) \ - ospf_lsdb.$(OBJEXT) ospf_asbr.$(OBJEXT) ospf_routemap.$(OBJEXT) \ - ospf_snmp.$(OBJEXT) ospf_opaque.$(OBJEXT) ospf_te.$(OBJEXT) \ - ospf_vty.$(OBJEXT) -am_ospfd_OBJECTS = ospf_main.$(OBJEXT) $(am__objects_1) -ospfd_OBJECTS = $(am_ospfd_OBJECTS) -ospfd_DEPENDENCIES = ../lib/libzebra.a -ospfd_LDFLAGS = -DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) -CPPFLAGS = @CPPFLAGS@ -LDFLAGS = @LDFLAGS@ -LIBS = @LIBS@ -depcomp = $(SHELL) $(top_srcdir)/depcomp -am__depfiles_maybe = depfiles -@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/ospf_abr.Po ./$(DEPDIR)/ospf_asbr.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/ospf_ase.Po ./$(DEPDIR)/ospf_dump.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/ospf_flood.Po ./$(DEPDIR)/ospf_ia.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/ospf_interface.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/ospf_ism.Po ./$(DEPDIR)/ospf_lsa.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/ospf_lsdb.Po ./$(DEPDIR)/ospf_main.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/ospf_neighbor.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/ospf_network.Po ./$(DEPDIR)/ospf_nsm.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/ospf_opaque.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/ospf_packet.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/ospf_route.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/ospf_routemap.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/ospf_snmp.Po ./$(DEPDIR)/ospf_spf.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/ospf_te.Po ./$(DEPDIR)/ospf_vty.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/ospf_zebra.Po ./$(DEPDIR)/ospfd.Po -COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ - $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -CCLD = $(CC) -LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ -CFLAGS = @CFLAGS@ -DIST_SOURCES = $(libospf_a_SOURCES) $(ospfd_SOURCES) -DATA = $(sysconf_DATA) - -HEADERS = $(noinst_HEADERS) - -DIST_COMMON = $(noinst_HEADERS) ChangeLog Makefile.am Makefile.in -SOURCES = $(libospf_a_SOURCES) $(ospfd_SOURCES) - -all: all-am - -.SUFFIXES: -.SUFFIXES: .c .o .obj -$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) - cd $(top_srcdir) && \ - $(AUTOMAKE) --foreign ospfd/Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) - -clean-noinstLIBRARIES: - -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) -libospf.a: $(libospf_a_OBJECTS) $(libospf_a_DEPENDENCIES) - -rm -f libospf.a - $(libospf_a_AR) libospf.a $(libospf_a_OBJECTS) $(libospf_a_LIBADD) - $(RANLIB) libospf.a -sbinPROGRAMS_INSTALL = $(INSTALL_PROGRAM) -install-sbinPROGRAMS: $(sbin_PROGRAMS) - @$(NORMAL_INSTALL) - $(mkinstalldirs) $(DESTDIR)$(sbindir) - @list='$(sbin_PROGRAMS)'; for p in $$list; do \ - p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ - if test -f $$p \ - ; then \ - f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ - echo " $(INSTALL_PROGRAM_ENV) $(sbinPROGRAMS_INSTALL) $$p $(DESTDIR)$(sbindir)/$$f"; \ - $(INSTALL_PROGRAM_ENV) $(sbinPROGRAMS_INSTALL) $$p $(DESTDIR)$(sbindir)/$$f; \ - else :; fi; \ - done - -uninstall-sbinPROGRAMS: - @$(NORMAL_UNINSTALL) - @list='$(sbin_PROGRAMS)'; for p in $$list; do \ - f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ - echo " rm -f $(DESTDIR)$(sbindir)/$$f"; \ - rm -f $(DESTDIR)$(sbindir)/$$f; \ - done - -clean-sbinPROGRAMS: - -test -z "$(sbin_PROGRAMS)" || rm -f $(sbin_PROGRAMS) -ospfd$(EXEEXT): $(ospfd_OBJECTS) $(ospfd_DEPENDENCIES) - @rm -f ospfd$(EXEEXT) - $(LINK) $(ospfd_LDFLAGS) $(ospfd_OBJECTS) $(ospfd_LDADD) $(LIBS) - -mostlyclean-compile: - -rm -f *.$(OBJEXT) core *.core - -distclean-compile: - -rm -f *.tab.c - -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf_abr.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf_asbr.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf_ase.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf_dump.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf_flood.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf_ia.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf_interface.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf_ism.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf_lsa.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf_lsdb.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf_main.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf_neighbor.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf_network.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf_nsm.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf_opaque.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf_packet.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf_route.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf_routemap.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf_snmp.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf_spf.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf_te.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf_vty.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf_zebra.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospfd.Po@am__quote@ - -distclean-depend: - -rm -rf ./$(DEPDIR) - -.c.o: -@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ -@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ - $(COMPILE) -c `test -f '$<' || echo '$(srcdir)/'`$< - -.c.obj: -@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ -@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ - $(COMPILE) -c `cygpath -w $<` -CCDEPMODE = @CCDEPMODE@ -uninstall-info-am: -sysconfDATA_INSTALL = $(INSTALL_DATA) - -uninstall-sysconfDATA: - @$(NORMAL_UNINSTALL) - @list='$(sysconf_DATA)'; for p in $$list; do \ - f="`echo $$p | sed -e 's|^.*/||'`"; \ - echo " rm -f $(DESTDIR)$(sysconfdir)/$$f"; \ - rm -f $(DESTDIR)$(sysconfdir)/$$f; \ - done - -ETAGS = etags -ETAGSFLAGS = - -tags: TAGS - -ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ - mkid -fID $$unique - -TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - tags=; \ - here=`pwd`; \ - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ - test -z "$(ETAGS_ARGS)$$tags$$unique" \ - || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$tags $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && cd $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) $$here - -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) - -top_distdir = .. -distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) - -distdir: $(DISTFILES) - @list='$(DISTFILES)'; for file in $$list; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test "$$dir" != "$$file" && test "$$dir" != "."; then \ - dir="/$$dir"; \ - $(mkinstalldirs) "$(distdir)$$dir"; \ - else \ - dir=''; \ - fi; \ - if test -d $$d/$$file; then \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ - fi; \ - cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ - else \ - test -f $(distdir)/$$file \ - || cp -p $$d/$$file $(distdir)/$$file \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-am -all-am: Makefile $(LIBRARIES) $(PROGRAMS) $(DATA) $(HEADERS) - -installdirs: - $(mkinstalldirs) $(DESTDIR)$(sbindir) $(DESTDIR)$(sysconfdir) - -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - INSTALL_STRIP_FLAG=-s \ - `test -z '$(STRIP)' || \ - echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -rm -f Makefile $(CONFIG_CLEAN_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-am - -clean-am: clean-generic clean-noinstLIBRARIES clean-sbinPROGRAMS \ - mostlyclean-am - -distclean: distclean-am - -distclean-am: clean-am distclean-compile distclean-depend \ - distclean-generic distclean-tags - -dvi: dvi-am - -dvi-am: - -info: info-am - -info-am: - -install-data-am: - -install-exec-am: install-sbinPROGRAMS install-sysconfDATA - -install-info: install-info-am - -install-man: - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-compile mostlyclean-generic - -uninstall-am: uninstall-info-am uninstall-sbinPROGRAMS \ - uninstall-sysconfDATA - -.PHONY: GTAGS all all-am check check-am clean clean-generic \ - clean-noinstLIBRARIES clean-sbinPROGRAMS distclean \ - distclean-compile distclean-depend distclean-generic \ - distclean-tags distdir dvi dvi-am info info-am install \ - install-am install-data install-data-am install-exec \ - install-exec-am install-info install-info-am install-man \ - install-sbinPROGRAMS install-strip install-sysconfDATA \ - installcheck installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-compile \ - mostlyclean-generic tags uninstall uninstall-am \ - uninstall-info-am uninstall-sbinPROGRAMS uninstall-sysconfDATA - - -install-sysconfDATA: $(sysconf_DATA) - @$(NORMAL_INSTALL) - $(mkinstalldirs) $(DESTDIR)$(sysconfdir) - @list='$(sysconf_DATA)'; for p in $$list; do \ - if test -f $(srcdir)/$$p; then \ - echo " $(INSTALL_SDATA) $(srcdir)/$$p $(DESTDIR)$(sysconfdir)/$$p"; \ - $(INSTALL_SDATA) $(srcdir)/$$p $(DESTDIR)$(sysconfdir)/$$p; \ - else if test -f $$p; then \ - echo " $(INSTALL_SDATA) $$p $(DESTDIR)$(sysconfdir)/$$p"; \ - $(INSTALL_SDATA) $$p $(DESTDIR)$(sysconfdir)/$$p; \ - fi; fi; \ - done -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/ospfd/ospf_abr.c b/ospfd/ospf_abr.c index 181fe190..638cf1cc 100644 --- a/ospfd/ospf_abr.c +++ b/ospfd/ospf_abr.c @@ -201,7 +201,7 @@ ospf_area_range_set (struct ospf *ospf, struct in_addr area_id, { struct ospf_area *area; struct ospf_area_range *range; - int ret = OSPF_AREA_ID_FORMAT_DECIMAL; + int ret = OSPF_AREA_ID_FORMAT_ADDRESS; area = ospf_area_get (ospf, area_id, ret); if (area == NULL) @@ -237,7 +237,7 @@ ospf_area_range_cost_set (struct ospf *ospf, struct in_addr area_id, { struct ospf_area *area; struct ospf_area_range *range; - int ret = OSPF_AREA_ID_FORMAT_DECIMAL; + int ret = OSPF_AREA_ID_FORMAT_ADDRESS; area = ospf_area_get (ospf, area_id, ret); if (area == NULL) @@ -286,7 +286,7 @@ ospf_area_range_substitute_set (struct ospf *ospf, struct in_addr area_id, { struct ospf_area *area; struct ospf_area_range *range; - int ret = OSPF_AREA_ID_FORMAT_DECIMAL; + int ret = OSPF_AREA_ID_FORMAT_ADDRESS; area = ospf_area_get (ospf, area_id, ret); range = ospf_area_range_lookup (area, p); diff --git a/ospfd/ospf_abr.h b/ospfd/ospf_abr.h index c025f514..3b385c32 100644 --- a/ospfd/ospf_abr.h +++ b/ospfd/ospf_abr.h @@ -75,10 +75,10 @@ int ospf_area_range_substitute_unset (struct ospf *, struct in_addr, struct ospf_area_range *ospf_area_range_match_any (struct ospf *, struct prefix_ipv4 *); int ospf_area_range_active (struct ospf_area_range *); -int ospf_act_bb_connection (struct ospf *); +int ospf_act_bb_connection (); -void ospf_check_abr_status (struct ospf *); -void ospf_abr_task (struct ospf *); -void ospf_schedule_abr_task (struct ospf *); +void ospf_check_abr_status (); +void ospf_abr_task (); +void ospf_schedule_abr_task (); #endif /* _ZEBRA_OSPF_ABR_H */ diff --git a/ospfd/ospf_api.c b/ospfd/ospf_api.c new file mode 100644 index 00000000..cd69336c --- /dev/null +++ b/ospfd/ospf_api.c @@ -0,0 +1,647 @@ +/* + * API message handling module for OSPF daemon and client. + * Copyright (C) 2001, 2002 Ralph Keller + * + * 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. + */ + +#include <zebra.h> + +#ifdef SUPPORT_OSPF_API +#ifndef HAVE_OPAQUE_LSA +#error "Core Opaque-LSA module must be configured." +#endif /* HAVE_OPAQUE_LSA */ + +#include "linklist.h" +#include "prefix.h" +#include "if.h" +#include "table.h" +#include "memory.h" +#include "command.h" +#include "vty.h" +#include "stream.h" +#include "log.h" +#include "thread.h" +#include "hash.h" +#include "sockunion.h" /* for inet_aton() */ +#include "buffer.h" +#include "network.h" + +#include "ospfd/ospfd.h" +#include "ospfd/ospf_interface.h" +#include "ospfd/ospf_ism.h" +#include "ospfd/ospf_asbr.h" +#include "ospfd/ospf_lsa.h" +#include "ospfd/ospf_lsdb.h" +#include "ospfd/ospf_neighbor.h" +#include "ospfd/ospf_nsm.h" +#include "ospfd/ospf_flood.h" +#include "ospfd/ospf_packet.h" +#include "ospfd/ospf_spf.h" +#include "ospfd/ospf_dump.h" +#include "ospfd/ospf_route.h" +#include "ospfd/ospf_ase.h" +#include "ospfd/ospf_zebra.h" + +#include "ospfd/ospf_api.h" + + +/* For debugging only, will be removed */ +void +api_opaque_lsa_print (struct lsa_header *data) +{ + struct opaque_lsa + { + struct lsa_header header; + u_char mydata[0]; + }; + + struct opaque_lsa *olsa; + int opaquelen; + int i; + + ospf_lsa_header_dump (data); + + olsa = (struct opaque_lsa *) data; + + opaquelen = ntohs (data->length) - OSPF_LSA_HEADER_SIZE; + zlog_warn ("apiserver_lsa_print: opaquelen=%d\n", opaquelen); + + for (i = 0; i < opaquelen; i++) + { + zlog_warn ("0x%x ", olsa->mydata[i]); + } + zlog_warn ("\n"); +} + +/* ----------------------------------------------------------- + * Generic messages + * ----------------------------------------------------------- + */ + +struct msg * +msg_new (u_char msgtype, void *msgbody, u_int32_t seqnum, u_int16_t msglen) +{ + struct msg *new; + + new = XMALLOC (MTYPE_OSPF_API_MSG, sizeof (struct msg)); + memset (new, 0, sizeof (struct msg)); + + new->hdr.version = OSPF_API_VERSION; + new->hdr.msgtype = msgtype; + new->hdr.msglen = htons (msglen); + new->hdr.msgseq = htonl (seqnum); + + new->s = stream_new (msglen); + assert (new->s); + stream_put (new->s, msgbody, msglen); + + return new; +} + + +/* Duplicate a message by copying content. */ +struct msg * +msg_dup (struct msg *msg) +{ + struct msg *new; + + assert (msg); + + new = msg_new (msg->hdr.msgtype, STREAM_DATA (msg->s), + ntohl (msg->hdr.msgseq), ntohs (msg->hdr.msglen)); + return new; +} + + +/* XXX only for testing, will be removed */ + +struct nametab { + int value; + const char *name; +}; + +const char * +ospf_api_typename (int msgtype) +{ + struct nametab NameTab[] = { + { MSG_REGISTER_OPAQUETYPE, "Register opaque-type", }, + { MSG_UNREGISTER_OPAQUETYPE, "Unregister opaque-type", }, + { MSG_REGISTER_EVENT, "Register event", }, + { MSG_SYNC_LSDB, "Sync LSDB", }, + { MSG_ORIGINATE_REQUEST, "Originate request", }, + { MSG_DELETE_REQUEST, "Delete request", }, + { MSG_REPLY, "Reply", }, + { MSG_READY_NOTIFY, "Ready notify", }, + { MSG_LSA_UPDATE_NOTIFY, "LSA update notify", }, + { MSG_LSA_DELETE_NOTIFY, "LSA delete notify", }, + { MSG_NEW_IF, "New interface", }, + { MSG_DEL_IF, "Del interface", }, + { MSG_ISM_CHANGE, "ISM change", }, + { MSG_NSM_CHANGE, "NSM change", }, + }; + + int i, n = sizeof (NameTab) / sizeof (NameTab[0]); + const char *name = NULL; + + for (i = 0; i < n; i++) + { + if (NameTab[i].value == msgtype) + { + name = NameTab[i].name; + break; + } + } + + return name ? name : "?"; +} + +const char * +ospf_api_errname (int errcode) +{ + struct nametab NameTab[] = { + { OSPF_API_OK, "OK", }, + { OSPF_API_NOSUCHINTERFACE, "No such interface", }, + { OSPF_API_NOSUCHAREA, "No such area", }, + { OSPF_API_NOSUCHLSA, "No such LSA", }, + { OSPF_API_ILLEGALLSATYPE, "Illegal LSA type", }, + { OSPF_API_OPAQUETYPEINUSE, "Opaque type in use", }, + { OSPF_API_OPAQUETYPENOTREGISTERED, "Opaque type not registered", }, + { OSPF_API_NOTREADY, "Not ready", }, + { OSPF_API_NOMEMORY, "No memory", }, + { OSPF_API_ERROR, "Other error", }, + { OSPF_API_UNDEF, "Undefined", }, + }; + + int i, n = sizeof (NameTab) / sizeof (NameTab[0]); + const char *name = NULL; + + for (i = 0; i < n; i++) + { + if (NameTab[i].value == errcode) + { + name = NameTab[i].name; + break; + } + } + + return name ? name : "?"; +} + +void +msg_print (struct msg *msg) +{ + if (!msg) + { + zlog_warn ("msg_print msg=NULL!\n"); + return; + } + +#ifdef ORIGINAL_CODING + zlog_warn + ("msg=%p msgtype=%d msglen=%d msgseq=%d streamdata=%p streamsize=%lu\n", + msg, msg->hdr.msgtype, ntohs (msg->hdr.msglen), ntohl (msg->hdr.msgseq), + STREAM_DATA (msg->s), STREAM_SIZE (msg->s)); +#else /* ORIGINAL_CODING */ + /* API message common header part. */ + zlog_info + ("API-msg [%s]: type(%d),len(%d),seq(%lu),data(%p),size(%lu)", + ospf_api_typename (msg->hdr.msgtype), msg->hdr.msgtype, + ntohs (msg->hdr.msglen), (unsigned long) ntohl (msg->hdr.msgseq), + STREAM_DATA (msg->s), STREAM_SIZE (msg->s)); + + /* API message body part. */ +#ifdef ndef + /* Generic Hex/Ascii dump */ + DumpBuf (STREAM_DATA (msg->s), STREAM_SIZE (msg->s)); /* Sorry, deleted! */ +#else /* ndef */ + /* Message-type dependent dump function. */ +#endif /* ndef */ + + return; +#endif /* ORIGINAL_CODING */ +} + +void +msg_free (struct msg *msg) +{ + if (msg->s) + stream_free (msg->s); + + XFREE (MTYPE_OSPF_API_MSG, msg); +} + + +/* Set sequence number of message */ +void +msg_set_seq (struct msg *msg, u_int32_t seqnr) +{ + assert (msg); + msg->hdr.msgseq = htonl (seqnr); +} + +/* Get sequence number of message */ +u_int32_t +msg_get_seq (struct msg *msg) +{ + assert (msg); + return ntohl (msg->hdr.msgseq); +} + +/* ----------------------------------------------------------- + * Message fifo queues + * ----------------------------------------------------------- + */ + +struct msg_fifo * +msg_fifo_new () +{ + struct msg_fifo *new; + + new = XMALLOC (MTYPE_OSPF_API_FIFO, sizeof (struct msg_fifo)); + memset (new, 0, sizeof (struct msg_fifo)); + + return new; +} + +/* Add new message to fifo. */ +void +msg_fifo_push (struct msg_fifo *fifo, struct msg *msg) +{ + if (fifo->tail) + fifo->tail->next = msg; + else + fifo->head = msg; + + fifo->tail = msg; + fifo->count++; +} + + +/* Remove first message from fifo. */ +struct msg * +msg_fifo_pop (struct msg_fifo *fifo) +{ + struct msg *msg; + + msg = fifo->head; + if (msg) + { + fifo->head = msg->next; + + if (fifo->head == NULL) + fifo->tail = NULL; + + fifo->count--; + } + return msg; +} + +/* Return first fifo entry but do not remove it. */ +struct msg * +msg_fifo_head (struct msg_fifo *fifo) +{ + return fifo->head; +} + +/* Flush message fifo. */ +void +msg_fifo_flush (struct msg_fifo *fifo) +{ + struct msg *op; + struct msg *next; + + for (op = fifo->head; op; op = next) + { + next = op->next; + msg_free (op); + } + + fifo->head = fifo->tail = NULL; + fifo->count = 0; +} + +/* Free API message fifo. */ +void +msg_fifo_free (struct msg_fifo *fifo) +{ + msg_fifo_flush (fifo); + + XFREE (MTYPE_OSPF_API_FIFO, fifo); +} + +struct msg * +msg_read (int fd) +{ + struct msg *msg; + struct apimsghdr hdr; + char buf[OSPF_API_MAX_MSG_SIZE]; + int bodylen; + int rlen; + + /* Read message header */ + rlen = readn (fd, (char *) &hdr, sizeof (struct apimsghdr)); + + if (rlen < 0) + { + zlog_warn ("msg_read: readn %s", strerror (errno)); + return NULL; + } + else if (rlen == 0) + { + zlog_warn ("msg_read: Connection closed by peer"); + return NULL; + } + else if (rlen != sizeof (struct apimsghdr)) + { + zlog_warn ("msg_read: Cannot read message header!"); + return NULL; + } + + /* Check version of API protocol */ + if (hdr.version != OSPF_API_VERSION) + { + zlog_warn ("msg_read: OSPF API protocol version mismatch"); + return NULL; + } + + /* Determine body length. */ + bodylen = ntohs (hdr.msglen); + if (bodylen > 0) + { + + /* Read message body */ + rlen = readn (fd, buf, bodylen); + if (rlen < 0) + { + zlog_warn ("msg_read: readn %s", strerror (errno)); + return NULL; + } + else if (rlen == 0) + { + zlog_warn ("msg_read: Connection closed by peer"); + return NULL; + } + else if (rlen != bodylen) + { + zlog_warn ("msg_read: Cannot read message body!"); + return NULL; + } + } + + /* Allocate new message */ + msg = msg_new (hdr.msgtype, buf, ntohl (hdr.msgseq), ntohs (hdr.msglen)); + + return msg; +} + +int +msg_write (int fd, struct msg *msg) +{ + u_char buf[OSPF_API_MAX_MSG_SIZE]; + int l; + int wlen; + + assert (msg); + assert (msg->s); + + /* Length of message including header */ + l = sizeof (struct apimsghdr) + ntohs (msg->hdr.msglen); + + /* Make contiguous memory buffer for message */ + memcpy (buf, &msg->hdr, sizeof (struct apimsghdr)); + memcpy (buf + sizeof (struct apimsghdr), STREAM_DATA (msg->s), + ntohs (msg->hdr.msglen)); + + wlen = writen (fd, buf, l); + if (wlen < 0) + { + zlog_warn ("msg_write: writen %s", strerror (errno)); + return -1; + } + else if (wlen == 0) + { + zlog_warn ("msg_write: Connection closed by peer"); + return -1; + } + else if (wlen != l) + { + zlog_warn ("msg_write: Cannot write API message"); + return -1; + } + return 0; +} + +/* ----------------------------------------------------------- + * Specific messages + * ----------------------------------------------------------- + */ + +struct msg * +new_msg_register_opaque_type (u_int32_t seqnum, u_char ltype, u_char otype) +{ + struct msg_register_opaque_type rmsg; + + rmsg.lsatype = ltype; + rmsg.opaquetype = otype; + memset (&rmsg.pad, 0, sizeof (rmsg.pad)); + + return msg_new (MSG_REGISTER_OPAQUETYPE, &rmsg, seqnum, + sizeof (struct msg_register_opaque_type)); +} + +struct msg * +new_msg_register_event (u_int32_t seqnum, struct lsa_filter_type *filter) +{ + u_char buf[OSPF_API_MAX_MSG_SIZE]; + struct msg_register_event *emsg; + int len; + + emsg = (struct msg_register_event *) buf; + len = sizeof (struct msg_register_event) + + filter->num_areas * sizeof (struct in_addr); + emsg->filter.typemask = htons (filter->typemask); + emsg->filter.origin = filter->origin; + emsg->filter.num_areas = filter->num_areas; + return msg_new (MSG_REGISTER_EVENT, emsg, seqnum, len); +} + +struct msg * +new_msg_sync_lsdb (u_int32_t seqnum, struct lsa_filter_type *filter) +{ + u_char buf[OSPF_API_MAX_MSG_SIZE]; + struct msg_sync_lsdb *smsg; + int len; + + smsg = (struct msg_sync_lsdb *) buf; + len = sizeof (struct msg_sync_lsdb) + + filter->num_areas * sizeof (struct in_addr); + smsg->filter.typemask = htons (filter->typemask); + smsg->filter.origin = filter->origin; + smsg->filter.num_areas = filter->num_areas; + return msg_new (MSG_SYNC_LSDB, smsg, seqnum, len); +} + + +struct msg * +new_msg_originate_request (u_int32_t seqnum, + struct in_addr ifaddr, + struct in_addr area_id, struct lsa_header *data) +{ + struct msg_originate_request *omsg; + int omsglen; + char buf[OSPF_API_MAX_MSG_SIZE]; + + omsglen = sizeof (struct msg_originate_request) - sizeof (struct lsa_header) + + ntohs (data->length); + + omsg = (struct msg_originate_request *) buf; + omsg->ifaddr = ifaddr; + omsg->area_id = area_id; + memcpy (&omsg->data, data, ntohs (data->length)); + + return msg_new (MSG_ORIGINATE_REQUEST, omsg, seqnum, omsglen); +} + +struct msg * +new_msg_delete_request (u_int32_t seqnum, + struct in_addr area_id, u_char lsa_type, + u_char opaque_type, u_int32_t opaque_id) +{ + struct msg_delete_request dmsg; + dmsg.area_id = area_id; + dmsg.lsa_type = lsa_type; + dmsg.opaque_type = opaque_type; + dmsg.opaque_id = htonl (opaque_id); + memset (&dmsg.pad, 0, sizeof (dmsg.pad)); + + return msg_new (MSG_DELETE_REQUEST, &dmsg, seqnum, + sizeof (struct msg_delete_request)); +} + + +struct msg * +new_msg_reply (u_int32_t seqnr, u_char rc) +{ + struct msg *msg; + struct msg_reply rmsg; + + /* Set return code */ + rmsg.errcode = rc; + memset (&rmsg.pad, 0, sizeof (rmsg.pad)); + + msg = msg_new (MSG_REPLY, &rmsg, seqnr, sizeof (struct msg_reply)); + + return msg; +} + +struct msg * +new_msg_ready_notify (u_int32_t seqnr, u_char lsa_type, + u_char opaque_type, struct in_addr addr) +{ + struct msg_ready_notify rmsg; + + rmsg.lsa_type = lsa_type; + rmsg.opaque_type = opaque_type; + memset (&rmsg.pad, 0, sizeof (rmsg.pad)); + rmsg.addr = addr; + + return msg_new (MSG_READY_NOTIFY, &rmsg, seqnr, + sizeof (struct msg_ready_notify)); +} + +struct msg * +new_msg_new_if (u_int32_t seqnr, + struct in_addr ifaddr, struct in_addr area_id) +{ + struct msg_new_if nmsg; + + nmsg.ifaddr = ifaddr; + nmsg.area_id = area_id; + + return msg_new (MSG_NEW_IF, &nmsg, seqnr, sizeof (struct msg_new_if)); +} + +struct msg * +new_msg_del_if (u_int32_t seqnr, struct in_addr ifaddr) +{ + struct msg_del_if dmsg; + + dmsg.ifaddr = ifaddr; + + return msg_new (MSG_DEL_IF, &dmsg, seqnr, sizeof (struct msg_del_if)); +} + +struct msg * +new_msg_ism_change (u_int32_t seqnr, struct in_addr ifaddr, + struct in_addr area_id, u_char status) +{ + struct msg_ism_change imsg; + + imsg.ifaddr = ifaddr; + imsg.area_id = area_id; + imsg.status = status; + memset (&imsg.pad, 0, sizeof (imsg.pad)); + + return msg_new (MSG_ISM_CHANGE, &imsg, seqnr, + sizeof (struct msg_ism_change)); +} + +struct msg * +new_msg_nsm_change (u_int32_t seqnr, struct in_addr ifaddr, + struct in_addr nbraddr, + struct in_addr router_id, u_char status) +{ + struct msg_nsm_change nmsg; + + nmsg.ifaddr = ifaddr; + nmsg.nbraddr = nbraddr; + nmsg.router_id = router_id; + nmsg.status = status; + memset (&nmsg.pad, 0, sizeof (nmsg.pad)); + + return msg_new (MSG_NSM_CHANGE, &nmsg, seqnr, + sizeof (struct msg_nsm_change)); +} + +struct msg * +new_msg_lsa_change_notify (u_char msgtype, + u_int32_t seqnum, + struct in_addr ifaddr, + struct in_addr area_id, + u_char is_self_originated, struct lsa_header *data) +{ + u_char buf[OSPF_API_MAX_MSG_SIZE]; + struct msg_lsa_change_notify *nmsg; + int len; + + assert (data); + + nmsg = (struct msg_lsa_change_notify *) buf; + len = ntohs (data->length) + sizeof (struct msg_lsa_change_notify) + - sizeof (struct lsa_header); + nmsg->ifaddr = ifaddr; + nmsg->area_id = area_id; + nmsg->is_self_originated = is_self_originated; + memset (&nmsg->pad, 0, sizeof (nmsg->pad)); + memcpy (&nmsg->data, data, ntohs (data->length)); + + return msg_new (msgtype, nmsg, seqnum, len); +} + +#endif /* SUPPORT_OSPF_API */ diff --git a/ospfd/ospf_api.h b/ospfd/ospf_api.h new file mode 100644 index 00000000..e7867614 --- /dev/null +++ b/ospfd/ospf_api.h @@ -0,0 +1,357 @@ +/* + * API message handling module for OSPF daemon and client. + * Copyright (C) 2001, 2002 Ralph Keller + * + * 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. + */ + + +/* This file is used both by the OSPFd and client applications to + define message formats used for communication. */ + +#ifndef _OSPF_API_H +#define _OSPF_API_H + +#define OSPF_API_VERSION 1 + +/* MTYPE definition is not reflected to "memory.h". */ +#define MTYPE_OSPF_API_MSG MTYPE_TMP +#define MTYPE_OSPF_API_FIFO MTYPE_TMP + +/* Default API server port to accept connection request from client-side. */ +/* This value could be overridden by "ospfapi" entry in "/etc/services". */ +#define OSPF_API_SYNC_PORT 2607 + +/* ----------------------------------------------------------- + * Generic messages + * ----------------------------------------------------------- + */ + +/* Message header structure, fields are in network byte order and + aligned to four octets. */ +struct apimsghdr +{ + u_char version; /* OSPF API protocol version */ + u_char msgtype; /* Type of message */ + u_int16_t msglen; /* Length of message w/o header */ + u_int32_t msgseq; /* Sequence number */ +}; + +/* Message representation with header and body */ +struct msg +{ + struct msg *next; /* to link into fifo */ + + /* Message header */ + struct apimsghdr hdr; + + /* Message body */ + struct stream *s; +}; + +/* Prototypes for generic messages. */ +struct msg *msg_new (u_char msgtype, void *msgbody, + u_int32_t seqnum, u_int16_t msglen); +struct msg *msg_dup (struct msg *msg); +void msg_print (struct msg *msg); /* XXX debug only */ +void msg_free (struct msg *msg); +struct msg *msg_read (int fd); +int msg_write (int fd, struct msg *msg); + +/* For requests, the message sequence number is between MIN_SEQ and + MAX_SEQ. For notifications, the sequence number is 0. */ + +#define MIN_SEQ 1 +#define MAX_SEQ 2147483647 + +void msg_set_seq (struct msg *msg, u_int32_t seqnr); +u_int32_t msg_get_seq (struct msg *msg); + +/* ----------------------------------------------------------- + * Message fifo queues + * ----------------------------------------------------------- + */ + +/* Message queue structure. */ +struct msg_fifo +{ + unsigned long count; + + struct msg *head; + struct msg *tail; +}; + +/* Prototype for message fifo queues. */ +struct msg_fifo *msg_fifo_new (); +void msg_fifo_push (struct msg_fifo *, struct msg *msg); +struct msg *msg_fifo_pop (struct msg_fifo *fifo); +struct msg *msg_fifo_head (struct msg_fifo *fifo); +void msg_fifo_flush (struct msg_fifo *fifo); +void msg_fifo_free (struct msg_fifo *fifo); + +/* ----------------------------------------------------------- + * Specific message type and format definitions + * ----------------------------------------------------------- + */ + +/* Messages to OSPF daemon. */ +#define MSG_REGISTER_OPAQUETYPE 1 +#define MSG_UNREGISTER_OPAQUETYPE 2 +#define MSG_REGISTER_EVENT 3 +#define MSG_SYNC_LSDB 4 +#define MSG_ORIGINATE_REQUEST 5 +#define MSG_DELETE_REQUEST 6 + +/* Messages from OSPF daemon. */ +#define MSG_REPLY 10 +#define MSG_READY_NOTIFY 11 +#define MSG_LSA_UPDATE_NOTIFY 12 +#define MSG_LSA_DELETE_NOTIFY 13 +#define MSG_NEW_IF 14 +#define MSG_DEL_IF 15 +#define MSG_ISM_CHANGE 16 +#define MSG_NSM_CHANGE 17 + +struct msg_register_opaque_type +{ + u_char lsatype; + u_char opaquetype; + u_char pad[2]; /* padding */ +}; + +struct msg_unregister_opaque_type +{ + u_char lsatype; + u_char opaquetype; + u_char pad[2]; /* padding */ +}; + +/* Power2 is needed to convert LSA types into bit positions, + * see typemask below. Type definition starts at 1, so + * Power2[0] is not used. */ + + +#ifdef ORIGINAL_CODING +static const u_int16_t + Power2[] = { 0x0, 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, + 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000 +}; +#else +static const u_int16_t + Power2[] = { 0, (1 << 0), (1 << 1), (1 << 2), (1 << 3), (1 << 4), + (1 << 5), (1 << 6), (1 << 7), (1 << 8), (1 << 9), + (1 << 10), (1 << 11), (1 << 12), (1 << 13), (1 << 14), + (1 << 15) +}; +#endif /* ORIGINAL_CODING */ + +struct lsa_filter_type +{ + u_int16_t typemask; /* bitmask for selecting LSA types (1..16) */ + u_char origin; /* selects according to origin. */ +#define NON_SELF_ORIGINATED 0 +#define SELF_ORIGINATED (OSPF_LSA_SELF) +#define ANY_ORIGIN 2 + + u_char num_areas; /* number of areas in the filter. */ + /* areas, if any, go here. */ +}; + +struct msg_register_event +{ + struct lsa_filter_type filter; +}; + +struct msg_sync_lsdb +{ + struct lsa_filter_type filter; +}; + +struct msg_originate_request +{ + /* Used for LSA type 9 otherwise ignored */ + struct in_addr ifaddr; + + /* Used for LSA type 10 otherwise ignored */ + struct in_addr area_id; + + /* LSA header and LSA-specific part */ + struct lsa_header data; +}; + +struct msg_delete_request +{ + struct in_addr area_id; /* "0.0.0.0" for AS-external opaque LSAs */ + u_char lsa_type; + u_char opaque_type; + u_char pad[2]; /* padding */ + u_int32_t opaque_id; +}; + +struct msg_reply +{ + char errcode; +#define OSPF_API_OK 0 +#define OSPF_API_NOSUCHINTERFACE (-1) +#define OSPF_API_NOSUCHAREA (-2) +#define OSPF_API_NOSUCHLSA (-3) +#define OSPF_API_ILLEGALLSATYPE (-4) +#define OSPF_API_OPAQUETYPEINUSE (-5) +#define OSPF_API_OPAQUETYPENOTREGISTERED (-6) +#define OSPF_API_NOTREADY (-7) +#define OSPF_API_NOMEMORY (-8) +#define OSPF_API_ERROR (-9) +#define OSPF_API_UNDEF (-10) + u_char pad[3]; /* padding to four byte alignment */ +}; + +/* Message to tell client application that it ospf daemon is + * ready to accept opaque LSAs for a given interface or area. */ + +struct msg_ready_notify +{ + u_char lsa_type; + u_char opaque_type; + u_char pad[2]; /* padding */ + struct in_addr addr; /* interface address or area address */ +}; + +/* These messages have a dynamic length depending on the embodied LSA. + They are aligned to four octets. msg_lsa_change_notify is used for + both LSA update and LSAs delete. */ + +struct msg_lsa_change_notify +{ + /* Used for LSA type 9 otherwise ignored */ + struct in_addr ifaddr; + /* Area ID. Not valid for AS-External and Opaque11 LSAs. */ + struct in_addr area_id; + u_char is_self_originated; /* 1 if self originated. */ + u_char pad[3]; + struct lsa_header data; +}; + +struct msg_new_if +{ + struct in_addr ifaddr; /* interface IP address */ + struct in_addr area_id; /* area this interface belongs to */ +}; + +struct msg_del_if +{ + struct in_addr ifaddr; /* interface IP address */ +}; + +struct msg_ism_change +{ + struct in_addr ifaddr; /* interface IP address */ + struct in_addr area_id; /* area this interface belongs to */ + u_char status; /* interface status (up/down) */ + u_char pad[3]; /* not used */ +}; + +struct msg_nsm_change +{ + struct in_addr ifaddr; /* attached interface */ + struct in_addr nbraddr; /* Neighbor interface address */ + struct in_addr router_id; /* Router ID of neighbor */ + u_char status; /* NSM status */ + u_char pad[3]; +}; + +/* We make use of a union to define a structure that covers all + possible API messages. This allows us to find out how much memory + needs to be reserved for the largest API message. */ +struct apimsg +{ + struct apimsghdr hdr; + union + { + struct msg_register_opaque_type register_opaque_type; + struct msg_register_event register_event; + struct msg_sync_lsdb sync_lsdb; + struct msg_originate_request originate_request; + struct msg_delete_request delete_request; + struct msg_reply reply; + struct msg_ready_notify ready_notify; + struct msg_new_if new_if; + struct msg_del_if del_if; + struct msg_ism_change ism_change; + struct msg_nsm_change nsm_change; + struct msg_lsa_change_notify lsa_change_notify; + } + u; +}; + +#define OSPF_API_MAX_MSG_SIZE (sizeof(struct apimsg) + OSPF_MAX_LSA_SIZE) + +/* ----------------------------------------------------------- + * Prototypes for specific messages + * ----------------------------------------------------------- + */ + +/* For debugging only. */ +void api_opaque_lsa_print (struct lsa_header *data); + +/* Messages sent by client */ +struct msg *new_msg_register_opaque_type (u_int32_t seqnum, u_char ltype, + u_char otype); +struct msg *new_msg_register_event (u_int32_t seqnum, + struct lsa_filter_type *filter); +struct msg *new_msg_sync_lsdb (u_int32_t seqnum, + struct lsa_filter_type *filter); +struct msg *new_msg_originate_request (u_int32_t seqnum, + struct in_addr ifaddr, + struct in_addr area_id, + struct lsa_header *data); +struct msg *new_msg_delete_request (u_int32_t seqnum, + struct in_addr area_id, + u_char lsa_type, + u_char opaque_type, u_int32_t opaque_id); + +/* Messages sent by OSPF daemon */ +struct msg *new_msg_reply (u_int32_t seqnum, u_char rc); + +struct msg *new_msg_ready_notify (u_int32_t seqnr, u_char lsa_type, + u_char opaque_type, struct in_addr addr); + +struct msg *new_msg_new_if (u_int32_t seqnr, + struct in_addr ifaddr, struct in_addr area); + +struct msg *new_msg_del_if (u_int32_t seqnr, struct in_addr ifaddr); + +struct msg *new_msg_ism_change (u_int32_t seqnr, struct in_addr ifaddr, + struct in_addr area, u_char status); + +struct msg *new_msg_nsm_change (u_int32_t seqnr, struct in_addr ifaddr, + struct in_addr nbraddr, + struct in_addr router_id, u_char status); + +/* msgtype is MSG_LSA_UPDATE_NOTIFY or MSG_LSA_DELETE_NOTIFY */ +struct msg *new_msg_lsa_change_notify (u_char msgtype, + u_int32_t seqnum, + struct in_addr ifaddr, + struct in_addr area_id, + u_char is_self_originated, + struct lsa_header *data); + +/* string printing functions */ +const char *ospf_api_errname (int errcode); +const char *ospf_api_typename (int msgtype); + +#endif /* _OSPF_API_H */ diff --git a/ospfd/ospf_apiserver.c b/ospfd/ospf_apiserver.c new file mode 100644 index 00000000..94167842 --- /dev/null +++ b/ospfd/ospf_apiserver.c @@ -0,0 +1,2700 @@ +/* + * Server side of OSPF API. + * Copyright (C) 2001, 2002 Ralph Keller + * + * 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. + */ + +#include <zebra.h> + +#ifdef SUPPORT_OSPF_API +#ifndef HAVE_OPAQUE_LSA +#error "Core Opaque-LSA module must be configured." +#endif /* HAVE_OPAQUE_LSA */ + +#include "linklist.h" +#include "prefix.h" +#include "if.h" +#include "table.h" +#include "memory.h" +#include "command.h" +#include "vty.h" +#include "stream.h" +#include "log.h" +#include "thread.h" +#include "hash.h" +#include "sockunion.h" /* for inet_aton() */ +#include "buffer.h" + +#include <sys/types.h> + +#include "ospfd/ospfd.h" /* for "struct thread_master" */ +#include "ospfd/ospf_interface.h" +#include "ospfd/ospf_ism.h" +#include "ospfd/ospf_asbr.h" +#include "ospfd/ospf_lsa.h" +#include "ospfd/ospf_lsdb.h" +#include "ospfd/ospf_neighbor.h" +#include "ospfd/ospf_nsm.h" +#include "ospfd/ospf_flood.h" +#include "ospfd/ospf_packet.h" +#include "ospfd/ospf_spf.h" +#include "ospfd/ospf_dump.h" +#include "ospfd/ospf_route.h" +#include "ospfd/ospf_ase.h" +#include "ospfd/ospf_zebra.h" + +#include "ospfd/ospf_api.h" +#include "ospfd/ospf_apiserver.h" + +/* This is an implementation of an API to the OSPF daemon that allows + * external applications to access the OSPF daemon through socket + * connections. The application can use this API to inject its own + * opaque LSAs and flood them to other OSPF daemons. Other OSPF + * daemons then receive these LSAs and inform applications through the + * API by sending a corresponding message. The application can also + * register to receive all LSA types (in addition to opaque types) and + * use this information to reconstruct the OSPF's LSDB. The OSPF + * daemon supports multiple applications concurrently. */ + +/* List of all active connections. */ +list apiserver_list; + +/* ----------------------------------------------------------- + * Functions to lookup interfaces + * ----------------------------------------------------------- + */ + +struct ospf_interface * +ospf_apiserver_if_lookup_by_addr (struct in_addr address) +{ + listnode node; + struct ospf_interface *oi; + struct ospf *ospf; + + ospf = ospf_lookup (); + + for (node = listhead (ospf->oiflist); node; nextnode (node)) + { + if ((oi = getdata (node)) != NULL + && oi->type != OSPF_IFTYPE_VIRTUALLINK) + { + if (IPV4_ADDR_SAME (&address, &oi->address->u.prefix4)) + return oi; + } + } + return NULL; +} + +struct ospf_interface * +ospf_apiserver_if_lookup_by_ifp (struct interface *ifp) +{ + listnode node; + struct ospf_interface *oi; + struct ospf *ospf; + + ospf = ospf_lookup (); + + for (node = listhead (ospf->oiflist); node; nextnode (node)) + { + if ((oi = getdata (node)) && oi->ifp == ifp) + { + return oi; + } + } + return NULL; +} + +/* ----------------------------------------------------------- + * Initialization + * ----------------------------------------------------------- + */ + +unsigned short +ospf_apiserver_getport (void) +{ + struct servent *sp = getservbyname ("ospfapi", "tcp"); + + return sp ? ntohs (sp->s_port) : OSPF_API_SYNC_PORT; +} + +/* Initialize OSPF API module. Invoked from ospf_opaque_init() */ +int +ospf_apiserver_init (void) +{ + int fd; + int rc = -1; + + /* Create new socket for synchronous messages. */ + fd = ospf_apiserver_serv_sock_family (ospf_apiserver_getport (), AF_INET); + + if (fd < 0) + goto out; + + /* Schedule new thread that handles accepted connections. */ + ospf_apiserver_event (OSPF_APISERVER_ACCEPT, fd, NULL); + + /* Initialize list that keeps track of all connections. */ + apiserver_list = list_new (); + + /* Register opaque-independent call back functions. These functions + are invoked on ISM, NSM changes and LSA update and LSA deletes */ + rc = + ospf_register_opaque_functab (0 /* all LSAs */, + 0 /* all opaque types */, + ospf_apiserver_new_if, + ospf_apiserver_del_if, + ospf_apiserver_ism_change, + ospf_apiserver_nsm_change, + NULL, + NULL, + NULL, + NULL, /* ospf_apiserver_show_info */ + NULL, /* originator_func */ + NULL, /* ospf_apiserver_lsa_refresher */ + ospf_apiserver_lsa_update, + ospf_apiserver_lsa_delete); + if (rc != 0) + { + zlog_warn ("ospf_apiserver_init: Failed to register opaque type [0/0]"); + } + + rc = 0; + +out: + return rc; +} + +/* Terminate OSPF API module. */ +void +ospf_apiserver_term (void) +{ + listnode node; + + /* Unregister wildcard [0/0] type */ + ospf_delete_opaque_functab (0 /* all LSAs */, + 0 /* all opaque types */); + + /* Free all client instances */ + for (node = listhead (apiserver_list); node; nextnode (node)) + { + struct ospf_apiserver *apiserv = + (struct ospf_apiserver *) getdata (node); + ospf_apiserver_free (apiserv); + } + + /* Free client list itself */ + list_delete (apiserver_list); + + /* Free wildcard list */ + /* XXX */ +} + +static struct ospf_apiserver * +lookup_apiserver (u_char lsa_type, u_char opaque_type) +{ + listnode n1, n2; + struct registered_opaque_type *r; + struct ospf_apiserver *apiserv, *found = NULL; + + for (n1 = listhead (apiserver_list); n1; nextnode (n1)) + { + apiserv = (struct ospf_apiserver *) getdata (n1); + + for (n2 = listhead (apiserv->opaque_types); n2; nextnode (n2)) + { + r = (struct registered_opaque_type *) getdata (n2); + + if (r->lsa_type == lsa_type && r->opaque_type == opaque_type) + { + found = apiserv; + goto out; + } + } + } +out: + return found; +} + +static struct ospf_apiserver * +lookup_apiserver_by_lsa (struct ospf_lsa *lsa) +{ + struct lsa_header *lsah = lsa->data; + struct ospf_apiserver *found = NULL; + + if (IS_OPAQUE_LSA (lsah->type)) + { + found = lookup_apiserver (lsah->type, + GET_OPAQUE_TYPE (ntohl (lsah->id.s_addr))); + } + return found; +} + +/* ----------------------------------------------------------- + * Followings are functions to manage client connections. + * ----------------------------------------------------------- + */ +static int +ospf_apiserver_new_lsa_hook (struct ospf_lsa *lsa) +{ + if (IS_DEBUG_OSPF_EVENT) + zlog_info ("API: Put LSA(%p)[%s] into reserve, total=%ld", lsa, dump_lsa_key (lsa), lsa->lsdb->total); + return 0; +} + +static int +ospf_apiserver_del_lsa_hook (struct ospf_lsa *lsa) +{ + if (IS_DEBUG_OSPF_EVENT) + zlog_info ("API: Get LSA(%p)[%s] from reserve, total=%ld", lsa, dump_lsa_key (lsa), lsa->lsdb->total); + return 0; +} + +/* Allocate new connection structure. */ +struct ospf_apiserver * +ospf_apiserver_new (int fd_sync, int fd_async) +{ + struct ospf_apiserver *new = + XMALLOC (MTYPE_OSPF_APISERVER, sizeof (struct ospf_apiserver)); + + new->filter = + XMALLOC (MTYPE_OSPF_APISERVER_MSGFILTER, sizeof (struct lsa_filter_type)); + + new->fd_sync = fd_sync; + new->fd_async = fd_async; + + /* list of registered opaque types that application uses */ + new->opaque_types = list_new (); + + /* Initialize temporary strage for LSA instances to be refreshed. */ + memset (&new->reserve, 0, sizeof (struct ospf_lsdb)); + ospf_lsdb_init (&new->reserve); + + new->reserve.new_lsa_hook = ospf_apiserver_new_lsa_hook; /* debug */ + new->reserve.del_lsa_hook = ospf_apiserver_del_lsa_hook; /* debug */ + + new->out_sync_fifo = msg_fifo_new (); + new->out_async_fifo = msg_fifo_new (); + new->t_sync_read = NULL; +#ifdef USE_ASYNC_READ + new->t_async_read = NULL; +#endif /* USE_ASYNC_READ */ + new->t_sync_write = NULL; + new->t_async_write = NULL; + + new->filter->typemask = 0; /* filter all LSAs */ + new->filter->origin = ANY_ORIGIN; + new->filter->num_areas = 0; + + return new; +} + +void +ospf_apiserver_event (enum event event, int fd, + struct ospf_apiserver *apiserv) +{ + struct thread *apiserver_serv_thread; + + switch (event) + { + case OSPF_APISERVER_ACCEPT: + apiserver_serv_thread = + thread_add_read (master, ospf_apiserver_accept, apiserv, fd); + break; + case OSPF_APISERVER_SYNC_READ: + apiserv->t_sync_read = + thread_add_read (master, ospf_apiserver_read, apiserv, fd); + break; +#ifdef USE_ASYNC_READ + case OSPF_APISERVER_ASYNC_READ: + apiserv->t_async_read = + thread_add_read (master, ospf_apiserver_read, apiserv, fd); + break; +#endif /* USE_ASYNC_READ */ + case OSPF_APISERVER_SYNC_WRITE: + if (!apiserv->t_sync_write) + { + apiserv->t_sync_write = + thread_add_write (master, ospf_apiserver_sync_write, apiserv, fd); + } + break; + case OSPF_APISERVER_ASYNC_WRITE: + if (!apiserv->t_async_write) + { + apiserv->t_async_write = + thread_add_write (master, ospf_apiserver_async_write, apiserv, fd); + } + break; + } +} + +/* Free instance. First unregister all opaque types used by + application, flush opaque LSAs injected by application + from network and close connection. */ +void +ospf_apiserver_free (struct ospf_apiserver *apiserv) +{ + listnode node; + + /* Cancel read and write threads. */ + if (apiserv->t_sync_read) + { + thread_cancel (apiserv->t_sync_read); + } +#ifdef USE_ASYNC_READ + if (apiserv->t_async_read) + { + thread_cancel (apiserv->t_async_read); + } +#endif /* USE_ASYNC_READ */ + if (apiserv->t_sync_write) + { + thread_cancel (apiserv->t_sync_write); + } + + if (apiserv->t_async_write) + { + thread_cancel (apiserv->t_async_write); + } + + /* Unregister all opaque types that application registered + and flush opaque LSAs if still in LSDB. */ + + while ((node = listhead (apiserv->opaque_types)) != NULL) + { + + struct registered_opaque_type *regtype = node->data; + + ospf_apiserver_unregister_opaque_type (apiserv, regtype->lsa_type, + regtype->opaque_type); + + } + + /* Close connections to OSPFd. */ + if (apiserv->fd_sync > 0) + { + close (apiserv->fd_sync); + } + + if (apiserv->fd_async > 0) + { + close (apiserv->fd_async); + } + + /* Free fifos */ + msg_fifo_free (apiserv->out_sync_fifo); + msg_fifo_free (apiserv->out_async_fifo); + + /* Clear temporary strage for LSA instances to be refreshed. */ + ospf_lsdb_delete_all (&apiserv->reserve); + ospf_lsdb_cleanup (&apiserv->reserve); + + /* Remove from the list of active clients. */ + listnode_delete (apiserver_list, apiserv); + + if (IS_DEBUG_OSPF_EVENT) + zlog_info ("API: Delete apiserv(%p), total#(%d)", apiserv, apiserver_list->count); + + /* And free instance. */ + XFREE (MTYPE_OSPF_APISERVER, apiserv); +} + +int +ospf_apiserver_read (struct thread *thread) +{ + struct ospf_apiserver *apiserv; + struct msg *msg; + int fd; + int rc = -1; + enum event event; + + apiserv = THREAD_ARG (thread); + fd = THREAD_FD (thread); + + if (fd == apiserv->fd_sync) + { + event = OSPF_APISERVER_SYNC_READ; + apiserv->t_sync_read = NULL; + + if (IS_DEBUG_OSPF_EVENT) + zlog_info ("API: ospf_apiserver_read: Peer: %s/%u", + inet_ntoa (apiserv->peer_sync.sin_addr), + ntohs (apiserv->peer_sync.sin_port)); + } +#ifdef USE_ASYNC_READ + else if (fd == apiserv->fd_async) + { + event = OSPF_APISERVER_ASYNC_READ; + apiserv->t_async_read = NULL; + + if (IS_DEBUG_OSPF_EVENT) + zlog_info ("API: ospf_apiserver_read: Peer: %s/%u", + inet_ntoa (apiserv->peer_async.sin_addr), + ntohs (apiserv->peer_async.sin_port)); + } +#endif /* USE_ASYNC_READ */ + else + { + zlog_warn ("ospf_apiserver_read: Unknown fd(%d)", fd); + ospf_apiserver_free (apiserv); + goto out; + } + + /* Read message from fd. */ + msg = msg_read (fd); + if (msg == NULL) + { + zlog_warn + ("ospf_apiserver_read: read failed on fd=%d, closing connection", fd); + + /* Perform cleanup. */ + ospf_apiserver_free (apiserv); + goto out; + } + + if (IS_DEBUG_OSPF_EVENT) + msg_print (msg); + + /* Dispatch to corresponding message handler. */ + rc = ospf_apiserver_handle_msg (apiserv, msg); + + /* Prepare for next message, add read thread. */ + ospf_apiserver_event (event, fd, apiserv); + + msg_free (msg); + +out: + return rc; +} + +int +ospf_apiserver_sync_write (struct thread *thread) +{ + struct ospf_apiserver *apiserv; + struct msg *msg; + int fd; + int rc = -1; + + apiserv = THREAD_ARG (thread); + assert (apiserv); + fd = THREAD_FD (thread); + + apiserv->t_sync_write = NULL; + + /* Sanity check */ + if (fd != apiserv->fd_sync) + { + zlog_warn ("ospf_apiserver_sync_write: Unknown fd=%d", fd); + goto out; + } + + if (IS_DEBUG_OSPF_EVENT) + zlog_info ("API: ospf_apiserver_sync_write: Peer: %s/%u", + inet_ntoa (apiserv->peer_sync.sin_addr), + ntohs (apiserv->peer_sync.sin_port)); + + /* Check whether there is really a message in the fifo. */ + msg = msg_fifo_pop (apiserv->out_sync_fifo); + if (!msg) + { + zlog_warn ("API: ospf_apiserver_sync_write: No message in Sync-FIFO?"); + return 0; + } + + if (IS_DEBUG_OSPF_EVENT) + msg_print (msg); + + rc = msg_write (fd, msg); + + /* Once a message is dequeued, it should be freed anyway. */ + msg_free (msg); + + if (rc < 0) + { + zlog_warn + ("ospf_apiserver_sync_write: write failed on fd=%d", fd); + goto out; + } + + + /* If more messages are in sync message fifo, schedule write thread. */ + if (msg_fifo_head (apiserv->out_sync_fifo)) + { + ospf_apiserver_event (OSPF_APISERVER_SYNC_WRITE, apiserv->fd_sync, + apiserv); + } + + out: + + if (rc < 0) + { + /* Perform cleanup and disconnect with peer */ + ospf_apiserver_free (apiserv); + } + + return rc; +} + + +int +ospf_apiserver_async_write (struct thread *thread) +{ + struct ospf_apiserver *apiserv; + struct msg *msg; + int fd; + int rc = -1; + + apiserv = THREAD_ARG (thread); + assert (apiserv); + fd = THREAD_FD (thread); + + apiserv->t_async_write = NULL; + + /* Sanity check */ + if (fd != apiserv->fd_async) + { + zlog_warn ("ospf_apiserver_async_write: Unknown fd=%d", fd); + goto out; + } + + if (IS_DEBUG_OSPF_EVENT) + zlog_info ("API: ospf_apiserver_async_write: Peer: %s/%u", + inet_ntoa (apiserv->peer_async.sin_addr), + ntohs (apiserv->peer_async.sin_port)); + + /* Check whether there is really a message in the fifo. */ + msg = msg_fifo_pop (apiserv->out_async_fifo); + if (!msg) + { + zlog_warn ("API: ospf_apiserver_async_write: No message in Async-FIFO?"); + return 0; + } + + if (IS_DEBUG_OSPF_EVENT) + msg_print (msg); + + rc = msg_write (fd, msg); + + /* Once a message is dequeued, it should be freed anyway. */ + msg_free (msg); + + if (rc < 0) + { + zlog_warn + ("ospf_apiserver_async_write: write failed on fd=%d", fd); + goto out; + } + + + /* If more messages are in async message fifo, schedule write thread. */ + if (msg_fifo_head (apiserv->out_async_fifo)) + { + ospf_apiserver_event (OSPF_APISERVER_ASYNC_WRITE, apiserv->fd_async, + apiserv); + } + + out: + + if (rc < 0) + { + /* Perform cleanup and disconnect with peer */ + ospf_apiserver_free (apiserv); + } + + return rc; +} + + +int +ospf_apiserver_serv_sock_family (unsigned short port, int family) +{ + union sockunion su; + int accept_sock; + int rc; + + memset (&su, 0, sizeof (union sockunion)); + su.sa.sa_family = family; + + /* Make new socket */ + accept_sock = sockunion_stream_socket (&su); + if (accept_sock < 0) + return accept_sock; + + /* This is a server, so reuse address and port */ + sockopt_reuseaddr (accept_sock); + sockopt_reuseport (accept_sock); + + /* Bind socket to address and given port. */ + rc = sockunion_bind (accept_sock, &su, port, NULL); + if (rc < 0) + { + close (accept_sock); /* Close socket */ + return rc; + } + + /* Listen socket under queue length 3. */ + rc = listen (accept_sock, 3); + if (rc < 0) + { + zlog_warn ("ospf_apiserver_serv_sock_family: listen: %s", + strerror (errno)); + close (accept_sock); /* Close socket */ + return rc; + } + return accept_sock; +} + + +/* Accept connection request from external applications. For each + accepted connection allocate own connection instance. */ +int +ospf_apiserver_accept (struct thread *thread) +{ + int accept_sock; + int new_sync_sock; + int new_async_sock; + union sockunion su; + struct ospf_apiserver *apiserv; + struct sockaddr_in peer_async; + struct sockaddr_in peer_sync; + int peerlen; + int ret; + + /* THREAD_ARG (thread) is NULL */ + accept_sock = THREAD_FD (thread); + + /* Keep hearing on socket for further connections. */ + ospf_apiserver_event (OSPF_APISERVER_ACCEPT, accept_sock, NULL); + + memset (&su, 0, sizeof (union sockunion)); + /* Accept connection for synchronous messages */ + new_sync_sock = sockunion_accept (accept_sock, &su); + if (new_sync_sock < 0) + { + zlog_warn ("ospf_apiserver_accept: accept: %s", strerror (errno)); + return -1; + } + + /* Get port address and port number of peer to make reverse connection. + The reverse channel uses the port number of the peer port+1. */ + + memset(&peer_sync, 0, sizeof(struct sockaddr_in)); + peerlen = sizeof (struct sockaddr_in); + + ret = getpeername (new_sync_sock, (struct sockaddr *)&peer_sync, &peerlen); + if (ret < 0) + { + zlog_warn ("ospf_apiserver_accept: getpeername: %s", strerror (errno)); + close (new_sync_sock); + return -1; + } + + if (IS_DEBUG_OSPF_EVENT) + zlog_info ("API: ospf_apiserver_accept: New peer: %s/%u", + inet_ntoa (peer_sync.sin_addr), ntohs (peer_sync.sin_port)); + + /* Create new socket for asynchronous messages. */ + peer_async = peer_sync; + peer_async.sin_port = htons(ntohs(peer_sync.sin_port) + 1); + + /* Check if remote port number to make reverse connection is valid one. */ + if (ntohs (peer_async.sin_port) == ospf_apiserver_getport ()) + { + zlog_warn ("API: ospf_apiserver_accept: Peer(%s/%u): Invalid async port number?", + inet_ntoa (peer_async.sin_addr), ntohs (peer_async.sin_port)); + close (new_sync_sock); + return -1; + } + + new_async_sock = socket (AF_INET, SOCK_STREAM, 0); + if (new_async_sock < 0) + { + zlog_warn ("ospf_apiserver_accept: socket: %s", strerror (errno)); + close (new_sync_sock); + return -1; + } + + ret = connect (new_async_sock, (struct sockaddr *) &peer_async, + sizeof (struct sockaddr_in)); + + if (ret < 0) + { + zlog_warn ("ospf_apiserver_accept: connect: %s", strerror (errno)); + close (new_sync_sock); + close (new_async_sock); + return -1; + } + +#ifdef USE_ASYNC_READ +#else /* USE_ASYNC_READ */ + /* Make the asynchronous channel write-only. */ + ret = shutdown (new_async_sock, SHUT_RD); + if (ret < 0) + { + zlog_warn ("ospf_apiserver_accept: shutdown: %s", strerror (errno)); + close (new_sync_sock); + close (new_async_sock); + return -1; + } +#endif /* USE_ASYNC_READ */ + + /* Allocate new server-side connection structure */ + apiserv = ospf_apiserver_new (new_sync_sock, new_async_sock); + + /* Add to active connection list */ + listnode_add (apiserver_list, apiserv); + apiserv->peer_sync = peer_sync; + apiserv->peer_async = peer_async; + + /* And add read threads for new connection */ + ospf_apiserver_event (OSPF_APISERVER_SYNC_READ, new_sync_sock, apiserv); +#ifdef USE_ASYNC_READ + ospf_apiserver_event (OSPF_APISERVER_ASYNC_READ, new_async_sock, apiserv); +#endif /* USE_ASYNC_READ */ + + if (IS_DEBUG_OSPF_EVENT) + zlog_warn ("API: New apiserv(%p), total#(%d)", apiserv, apiserver_list->count); + + return 0; +} + + +/* ----------------------------------------------------------- + * Send reply with return code to client application + * ----------------------------------------------------------- + */ + +int +ospf_apiserver_send_msg (struct ospf_apiserver *apiserv, struct msg *msg) +{ + struct msg_fifo *fifo; + struct msg *msg2; + enum event event; + int fd; + + switch (msg->hdr.msgtype) + { + case MSG_REPLY: + fifo = apiserv->out_sync_fifo; + fd = apiserv->fd_sync; + event = OSPF_APISERVER_SYNC_WRITE; + break; + case MSG_READY_NOTIFY: + case MSG_LSA_UPDATE_NOTIFY: + case MSG_LSA_DELETE_NOTIFY: + case MSG_NEW_IF: + case MSG_DEL_IF: + case MSG_ISM_CHANGE: + case MSG_NSM_CHANGE: + fifo = apiserv->out_async_fifo; + fd = apiserv->fd_async; + event = OSPF_APISERVER_ASYNC_WRITE; + break; + default: + zlog_warn ("ospf_apiserver_send_msg: Unknown message type %d", + msg->hdr.msgtype); + return -1; + } + + /* Make a copy of the message and put in the fifo. Once the fifo + gets drained by the write thread, the message will be freed. */ + /* NB: Given "msg" is untouched in this function. */ + msg2 = msg_dup (msg); + + /* Enqueue message into corresponding fifo queue */ + msg_fifo_push (fifo, msg2); + + /* Schedule write thread */ + ospf_apiserver_event (event, fd, apiserv); + return 0; +} + +int +ospf_apiserver_send_reply (struct ospf_apiserver *apiserv, u_int32_t seqnr, + u_char rc) +{ + struct msg *msg = new_msg_reply (seqnr, rc); + int ret; + + if (!msg) + { + zlog_warn ("ospf_apiserver_send_reply: msg_new failed"); +#ifdef NOTYET + /* Cannot allocate new message. What should we do? */ + ospf_apiserver_free (apiserv); +#endif + return -1; + } + + ret = ospf_apiserver_send_msg (apiserv, msg); + msg_free (msg); + return ret; +} + + +/* ----------------------------------------------------------- + * Generic message dispatching handler function + * ----------------------------------------------------------- + */ + +int +ospf_apiserver_handle_msg (struct ospf_apiserver *apiserv, struct msg *msg) +{ + int rc; + + /* Call corresponding message handler function. */ + switch (msg->hdr.msgtype) + { + case MSG_REGISTER_OPAQUETYPE: + rc = ospf_apiserver_handle_register_opaque_type (apiserv, msg); + break; + case MSG_UNREGISTER_OPAQUETYPE: + rc = ospf_apiserver_handle_unregister_opaque_type (apiserv, msg); + break; + case MSG_REGISTER_EVENT: + rc = ospf_apiserver_handle_register_event (apiserv, msg); + break; + case MSG_SYNC_LSDB: + rc = ospf_apiserver_handle_sync_lsdb (apiserv, msg); + break; + case MSG_ORIGINATE_REQUEST: + rc = ospf_apiserver_handle_originate_request (apiserv, msg); + break; + case MSG_DELETE_REQUEST: + rc = ospf_apiserver_handle_delete_request (apiserv, msg); + break; + default: + zlog_warn ("ospf_apiserver_handle_msg: Unknown message type: %d", + msg->hdr.msgtype); + rc = -1; + } + return rc; +} + + +/* ----------------------------------------------------------- + * Following are functions for opaque type registration + * ----------------------------------------------------------- + */ + +int +ospf_apiserver_register_opaque_type (struct ospf_apiserver *apiserv, + u_char lsa_type, u_char opaque_type) +{ + struct registered_opaque_type *regtype; + int (*originator_func) (void *arg); + int rc; + + switch (lsa_type) + { + case OSPF_OPAQUE_LINK_LSA: + originator_func = ospf_apiserver_lsa9_originator; + break; + case OSPF_OPAQUE_AREA_LSA: + originator_func = ospf_apiserver_lsa10_originator; + break; + case OSPF_OPAQUE_AS_LSA: + originator_func = ospf_apiserver_lsa11_originator; + break; + default: + zlog_warn ("ospf_apiserver_register_opaque_type: lsa_type(%d)", + lsa_type); + return OSPF_API_ILLEGALLSATYPE; + } + + + /* Register opaque function table */ + /* NB: Duplicated registration will be detected inside the function. */ + rc = + ospf_register_opaque_functab (lsa_type, opaque_type, + NULL, /* ospf_apiserver_new_if */ + NULL, /* ospf_apiserver_del_if */ + NULL, /* ospf_apiserver_ism_change */ + NULL, /* ospf_apiserver_nsm_change */ + NULL, + NULL, + NULL, + ospf_apiserver_show_info, + originator_func, + ospf_apiserver_lsa_refresher, + NULL, /* ospf_apiserver_lsa_update */ + NULL /* ospf_apiserver_lsa_delete */); + + if (rc != 0) + { + zlog_warn ("Failed to register opaque type [%d/%d]", + lsa_type, opaque_type); + return OSPF_API_OPAQUETYPEINUSE; + } + + /* Remember the opaque type that application registers so when + connection shuts down, we can flush all LSAs of this opaque + type. */ + + regtype = + XMALLOC (MTYPE_OSPF_APISERVER, sizeof (struct registered_opaque_type)); + memset (regtype, 0, sizeof (struct registered_opaque_type)); + regtype->lsa_type = lsa_type; + regtype->opaque_type = opaque_type; + + /* Add to list of registered opaque types */ + listnode_add (apiserv->opaque_types, regtype); + + if (IS_DEBUG_OSPF_EVENT) + zlog_info ("API: Add LSA-type(%d)/Opaque-type(%d) into apiserv(%p), total#(%d)", lsa_type, opaque_type, apiserv, listcount (apiserv->opaque_types)); + + return 0; +} + +int +ospf_apiserver_unregister_opaque_type (struct ospf_apiserver *apiserv, + u_char lsa_type, u_char opaque_type) +{ + listnode node; + + for (node = listhead (apiserv->opaque_types); node; nextnode (node)) + { + struct registered_opaque_type *regtype = node->data; + + /* Check if we really registered this opaque type */ + if (regtype->lsa_type == lsa_type && + regtype->opaque_type == opaque_type) + { + + /* Yes, we registered this opaque type. Flush + all existing opaque LSAs of this type */ + + ospf_apiserver_flush_opaque_lsa (apiserv, lsa_type, opaque_type); + ospf_delete_opaque_functab (lsa_type, opaque_type); + + /* Remove from list of registered opaque types */ + listnode_delete (apiserv->opaque_types, regtype); + + if (IS_DEBUG_OSPF_EVENT) + zlog_info ("API: Del LSA-type(%d)/Opaque-type(%d) from apiserv(%p), total#(%d)", lsa_type, opaque_type, apiserv, listcount (apiserv->opaque_types)); + + return 0; + } + } + + /* Opaque type is not registered */ + zlog_warn ("Failed to unregister opaque type [%d/%d]", + lsa_type, opaque_type); + return OSPF_API_OPAQUETYPENOTREGISTERED; +} + + +int +apiserver_is_opaque_type_registered (struct ospf_apiserver *apiserv, + u_char lsa_type, u_char opaque_type) +{ + listnode node; + + for (node = listhead (apiserv->opaque_types); node; nextnode (node)) + { + struct registered_opaque_type *regtype = node->data; + + /* Check if we really registered this opaque type */ + if (regtype->lsa_type == lsa_type && + regtype->opaque_type == opaque_type) + { + /* Yes registered */ + return 1; + } + } + /* Not registered */ + return 0; +} + +int +ospf_apiserver_handle_register_opaque_type (struct ospf_apiserver *apiserv, + struct msg *msg) +{ + struct msg_register_opaque_type *rmsg; + u_char lsa_type; + u_char opaque_type; + int rc = 0; + + /* Extract parameters from register opaque type message */ + rmsg = (struct msg_register_opaque_type *) STREAM_DATA (msg->s); + + lsa_type = rmsg->lsatype; + opaque_type = rmsg->opaquetype; + + rc = ospf_apiserver_register_opaque_type (apiserv, lsa_type, opaque_type); + + /* Send a reply back to client including return code */ + rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc); + if (rc < 0) + goto out; + + /* Now inform application about opaque types that are ready */ + switch (lsa_type) + { + case OSPF_OPAQUE_LINK_LSA: + ospf_apiserver_notify_ready_type9 (apiserv); + break; + case OSPF_OPAQUE_AREA_LSA: + ospf_apiserver_notify_ready_type10 (apiserv); + break; + case OSPF_OPAQUE_AS_LSA: + ospf_apiserver_notify_ready_type11 (apiserv); + break; + } +out: + return rc; +} + + +/* Notify specific client about all opaque types 9 that are ready. */ +void +ospf_apiserver_notify_ready_type9 (struct ospf_apiserver *apiserv) +{ + listnode node; + listnode n2; + struct ospf *ospf; + + ospf = ospf_lookup (); + + for (node = listhead (ospf->oiflist); node; nextnode (node)) + { + struct ospf_interface *oi = (struct ospf_interface *) getdata (node); + + /* Check if this interface is indeed ready for type 9 */ + if (!ospf_apiserver_is_ready_type9 (oi)) + continue; + + /* Check for registered opaque type 9 types */ + for (n2 = listhead (apiserv->opaque_types); n2; nextnode (n2)) + { + struct registered_opaque_type *r = + (struct registered_opaque_type *) getdata (n2); + struct msg *msg; + + if (r->lsa_type == OSPF_OPAQUE_LINK_LSA) + { + + /* Yes, this opaque type is ready */ + msg = new_msg_ready_notify (0, OSPF_OPAQUE_LINK_LSA, + r->opaque_type, + oi->address->u.prefix4); + if (!msg) + { + zlog_warn ("apiserver_notify_ready_type9: msg_new failed"); +#ifdef NOTYET + /* Cannot allocate new message. What should we do? */ + ospf_apiserver_free (apiserv); +#endif + goto out; + } + ospf_apiserver_send_msg (apiserv, msg); + msg_free (msg); + } + } + } + +out: + return; +} + + +/* Notify specific client about all opaque types 10 that are ready. */ +void +ospf_apiserver_notify_ready_type10 (struct ospf_apiserver *apiserv) +{ + listnode node; + listnode n2; + struct ospf *ospf; + + ospf = ospf_lookup (); + + for (node = listhead (ospf->areas); node; nextnode (node)) + { + struct ospf_area *area = getdata (node); + + if (!ospf_apiserver_is_ready_type10 (area)) + { + continue; + } + + /* Check for registered opaque type 10 types */ + for (n2 = listhead (apiserv->opaque_types); n2; nextnode (n2)) + { + struct registered_opaque_type *r = + (struct registered_opaque_type *) getdata (n2); + struct msg *msg; + + if (r->lsa_type == OSPF_OPAQUE_AREA_LSA) + { + /* Yes, this opaque type is ready */ + msg = + new_msg_ready_notify (0, OSPF_OPAQUE_AREA_LSA, + r->opaque_type, area->area_id); + if (!msg) + { + zlog_warn ("apiserver_notify_ready_type10: msg_new failed"); +#ifdef NOTYET + /* Cannot allocate new message. What should we do? */ + ospf_apiserver_free (apiserv); +#endif + goto out; + } + ospf_apiserver_send_msg (apiserv, msg); + msg_free (msg); + } + } + } + +out: + return; +} + +/* Notify specific client about all opaque types 11 that are ready */ +void +ospf_apiserver_notify_ready_type11 (struct ospf_apiserver *apiserv) +{ + listnode n2; + struct ospf *ospf; + + ospf = ospf_lookup (); + + /* Can type 11 be originated? */ + if (!ospf_apiserver_is_ready_type11 (ospf)) + goto out;; + + /* Check for registered opaque type 11 types */ + for (n2 = listhead (apiserv->opaque_types); n2; nextnode (n2)) + { + struct registered_opaque_type *r = + (struct registered_opaque_type *) getdata (n2); + struct msg *msg; + struct in_addr noarea_id = { 0L }; + + if (r->lsa_type == OSPF_OPAQUE_AS_LSA) + { + /* Yes, this opaque type is ready */ + msg = new_msg_ready_notify (0, OSPF_OPAQUE_AS_LSA, + r->opaque_type, noarea_id); + + if (!msg) + { + zlog_warn ("apiserver_notify_ready_type11: msg_new failed"); +#ifdef NOTYET + /* Cannot allocate new message. What should we do? */ + ospf_apiserver_free (apiserv); +#endif + goto out; + } + ospf_apiserver_send_msg (apiserv, msg); + msg_free (msg); + } + } + +out: + return; +} + +int +ospf_apiserver_handle_unregister_opaque_type (struct ospf_apiserver *apiserv, + struct msg *msg) +{ + struct msg_unregister_opaque_type *umsg; + u_char ltype; + u_char otype; + int rc = 0; + + /* Extract parameters from unregister opaque type message */ + umsg = (struct msg_unregister_opaque_type *) STREAM_DATA (msg->s); + + ltype = umsg->lsatype; + otype = umsg->opaquetype; + + rc = ospf_apiserver_unregister_opaque_type (apiserv, ltype, otype); + + /* Send a reply back to client including return code */ + rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc); + + return rc; +} + + +/* ----------------------------------------------------------- + * Following are functions for event (filter) registration. + * ----------------------------------------------------------- + */ +int +ospf_apiserver_handle_register_event (struct ospf_apiserver *apiserv, + struct msg *msg) +{ + struct msg_register_event *rmsg; + int rc; + u_int32_t seqnum; + + rmsg = (struct msg_register_event *) STREAM_DATA (msg->s); + + /* Get request sequence number */ + seqnum = msg_get_seq (msg); + + /* Free existing filter in apiserv. */ + XFREE (MTYPE_OSPF_APISERVER_MSGFILTER, apiserv->filter); + /* Alloc new space for filter. */ + + apiserv->filter = XMALLOC (MTYPE_OSPF_APISERVER_MSGFILTER, + ntohs (msg->hdr.msglen)); + if (apiserv->filter) + { + /* copy it over. */ + memcpy (apiserv->filter, &rmsg->filter, ntohs (msg->hdr.msglen)); + rc = OSPF_API_OK; + } + else + { + rc = OSPF_API_NOMEMORY; + } + /* Send a reply back to client with return code */ + rc = ospf_apiserver_send_reply (apiserv, seqnum, rc); + return rc; +} + + +/* ----------------------------------------------------------- + * Followings are functions for LSDB synchronization. + * ----------------------------------------------------------- + */ + +int +apiserver_sync_callback (struct ospf_lsa *lsa, void *p_arg, int int_arg) +{ + struct ospf_apiserver *apiserv; + int seqnum; + struct msg *msg; + struct param_t + { + struct ospf_apiserver *apiserv; + struct lsa_filter_type *filter; + } + *param; + int rc = -1; + + /* Sanity check */ + assert (lsa->data); + assert (p_arg); + + param = (struct param_t *) p_arg; + apiserv = param->apiserv; + seqnum = (u_int32_t) int_arg; + + /* Check origin in filter. */ + if ((param->filter->origin == ANY_ORIGIN) || + (param->filter->origin == (lsa->flags & OSPF_LSA_SELF))) + { + + /* Default area for AS-External and Opaque11 LSAs */ + struct in_addr area_id = { 0L }; + + /* Default interface for non Opaque9 LSAs */ + struct in_addr ifaddr = { 0L }; + + if (lsa->area) + { + area_id = lsa->area->area_id; + } + if (lsa->data->type == OSPF_OPAQUE_LINK_LSA) + { + ifaddr = lsa->oi->address->u.prefix4; + } + + msg = new_msg_lsa_change_notify (MSG_LSA_UPDATE_NOTIFY, + seqnum, + ifaddr, area_id, + lsa->flags & OSPF_LSA_SELF, lsa->data); + if (!msg) + { + zlog_warn ("apiserver_sync_callback: new_msg_update failed"); +#ifdef NOTYET + /* Cannot allocate new message. What should we do? */ +/* ospf_apiserver_free (apiserv);*//* Do nothing here XXX */ +#endif + goto out; + } + + /* Send LSA */ + ospf_apiserver_send_msg (apiserv, msg); + msg_free (msg); + } + rc = 0; + +out: + return rc; +} + +int +ospf_apiserver_handle_sync_lsdb (struct ospf_apiserver *apiserv, + struct msg *msg) +{ + listnode node; + u_int32_t seqnum; + int rc = 0; + struct msg_sync_lsdb *smsg; + struct param_t + { + struct ospf_apiserver *apiserv; + struct lsa_filter_type *filter; + } + param; + u_int16_t mask; + struct route_node *rn; + struct ospf_lsa *lsa; + struct ospf *ospf; + + ospf = ospf_lookup (); + + /* Get request sequence number */ + seqnum = msg_get_seq (msg); + /* Set sync msg. */ + smsg = (struct msg_sync_lsdb *) STREAM_DATA (msg->s); + + /* Set parameter struct. */ + param.apiserv = apiserv; + param.filter = &smsg->filter; + + /* Remember mask. */ + mask = ntohs (smsg->filter.typemask); + + /* Iterate over all areas. */ + for (node = listhead (ospf->areas); node; nextnode (node)) + { + struct ospf_area *area = node->data; + int i; + u_int32_t *area_id = NULL; + /* Compare area_id with area_ids in sync request. */ + if ((i = smsg->filter.num_areas) > 0) + { + /* Let area_id point to the list of area IDs, + * which is at the end of smsg->filter. */ + area_id = (u_int32_t *) (&smsg->filter + 1); + while (i) + { + if (*area_id == area->area_id.s_addr) + { + break; + } + i--; + area_id++; + } + } + else + { + i = 1; + } + + /* If area was found, then i>0 here. */ + if (i) + { + /* Check msg type. */ + if (mask & Power2[OSPF_ROUTER_LSA]) + LSDB_LOOP (ROUTER_LSDB (area), rn, lsa) + apiserver_sync_callback(lsa, (void *) ¶m, seqnum); + if (mask & Power2[OSPF_NETWORK_LSA]) + LSDB_LOOP (NETWORK_LSDB (area), rn, lsa) + apiserver_sync_callback(lsa, (void *) ¶m, seqnum); + if (mask & Power2[OSPF_SUMMARY_LSA]) + LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa) + apiserver_sync_callback(lsa, (void *) ¶m, seqnum); + if (mask & Power2[OSPF_ASBR_SUMMARY_LSA]) + LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa) + apiserver_sync_callback(lsa, (void *) ¶m, seqnum); + if (mask & Power2[OSPF_OPAQUE_LINK_LSA]) + LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa) + apiserver_sync_callback(lsa, (void *) ¶m, seqnum); + if (mask & Power2[OSPF_OPAQUE_AREA_LSA]) + LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa) + apiserver_sync_callback(lsa, (void *) ¶m, seqnum); + } + } + + /* For AS-external LSAs */ + if (ospf->lsdb) + { + if (mask & Power2[OSPF_AS_EXTERNAL_LSA]) + LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa) + apiserver_sync_callback(lsa, (void *) ¶m, seqnum); + } + + /* For AS-external opaque LSAs */ + if (ospf->lsdb) + { + if (mask & Power2[OSPF_OPAQUE_AS_LSA]) + LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa) + apiserver_sync_callback(lsa, (void *) ¶m, seqnum); + } + + /* Send a reply back to client with return code */ + rc = ospf_apiserver_send_reply (apiserv, seqnum, rc); + return rc; +} + + +/* ----------------------------------------------------------- + * Followings are functions to originate or update LSA + * from an application. + * ----------------------------------------------------------- + */ + +/* Create a new internal opaque LSA by taking prototype and filling in + missing fields such as age, sequence number, advertising router, + checksum and so on. The interface parameter is used for type 9 + LSAs, area parameter for type 10. Type 11 LSAs do neither need area + nor interface. */ + +struct ospf_lsa * +ospf_apiserver_opaque_lsa_new (struct ospf_area *area, + struct ospf_interface *oi, + struct lsa_header *protolsa) +{ + struct stream *s; + struct lsa_header *newlsa; + struct ospf_lsa *new = NULL; + u_char options = 0x0; + u_int16_t length; + + struct ospf *ospf; + + ospf = ospf_lookup(); + assert(ospf); + + /* Create a stream for internal opaque LSA */ + if ((s = stream_new (OSPF_MAX_LSA_SIZE)) == NULL) + { + zlog_warn ("ospf_apiserver_opaque_lsa_new: stream_new failed"); + return NULL; + } + + newlsa = (struct lsa_header *) STREAM_DATA (s); + + /* XXX If this is a link-local LSA or an AS-external LSA, how do we + have to set options? */ + + if (area) + { + options = LSA_OPTIONS_GET (area); +#ifdef HAVE_NSSA + options |= LSA_NSSA_GET (area); +#endif /* HAVE_NSSA */ + } + + options |= OSPF_OPTION_O; /* Don't forget to set option bit */ + + if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) + { + zlog_info ("LSA[Type%d:%s]: Creating an Opaque-LSA instance", + protolsa->type, inet_ntoa (protolsa->id)); + } + + /* Set opaque-LSA header fields. */ + lsa_header_set (s, options, protolsa->type, protolsa->id, + ospf->router_id); + + /* Set opaque-LSA body fields. */ + stream_put (s, ((u_char *) protolsa) + sizeof (struct lsa_header), + ntohs (protolsa->length) - sizeof (struct lsa_header)); + + /* Determine length of LSA. */ + length = stream_get_endp (s); + newlsa->length = htons (length); + + /* Create OSPF LSA. */ + if ((new = ospf_lsa_new ()) == NULL) + { + zlog_warn ("ospf_apiserver_opaque_lsa_new: ospf_lsa_new() ?"); + stream_free (s); + return NULL; + } + + if ((new->data = ospf_lsa_data_new (length)) == NULL) + { + zlog_warn ("ospf_apiserver_opaque_lsa_new: ospf_lsa_data_new() ?"); + ospf_lsa_free (new); + new = NULL; + stream_free (s); + return NULL; + } + + new->area = area; + new->oi = oi; + + SET_FLAG (new->flags, OSPF_LSA_SELF); + memcpy (new->data, newlsa, length); + stream_free (s); + + return new; +} + + +int +ospf_apiserver_is_ready_type9 (struct ospf_interface *oi) +{ + /* Type 9 opaque LSA can be originated if there is at least one + active opaque-capable neighbor attached to the outgoing + interface. */ + + return (ospf_nbr_count_opaque_capable (oi) > 0); +} + +int +ospf_apiserver_is_ready_type10 (struct ospf_area *area) +{ + /* Type 10 opaque LSA can be originated if there is at least one + interface belonging to the area that has an active opaque-capable + neighbor. */ + listnode node; + + for (node = listhead (area->oiflist); node; nextnode (node)) + { + struct ospf_interface *oi = getdata (node); + + /* Is there an active neighbor attached to this interface? */ + if (ospf_apiserver_is_ready_type9 (oi)) + { + return 1; + } + } + /* No active neighbor in area */ + return 0; +} + +int +ospf_apiserver_is_ready_type11 (struct ospf *ospf) +{ + /* Type 11 opaque LSA can be originated if there is at least one interface + that has an active opaque-capable neighbor. */ + listnode node; + + for (node = listhead (ospf->oiflist); node; nextnode (node)) + { + struct ospf_interface *oi = getdata (node); + + /* Is there an active neighbor attached to this interface? */ + if (ospf_apiserver_is_ready_type9 (oi)) + return 1; + } + /* No active neighbor at all */ + return 0; +} + + +int +ospf_apiserver_handle_originate_request (struct ospf_apiserver *apiserv, + struct msg *msg) +{ + struct msg_originate_request *omsg; + struct lsa_header *data; + struct ospf_lsa *new; + struct ospf_lsa *old; + struct ospf_area *area = NULL; + struct ospf_interface *oi = NULL; + struct ospf_lsdb *lsdb = NULL; + struct ospf *ospf; + int lsa_type, opaque_type; + int ready = 0; + int rc = 0; + + ospf = ospf_lookup(); + + /* Extract opaque LSA data from message */ + omsg = (struct msg_originate_request *) STREAM_DATA (msg->s); + data = &omsg->data; + + /* Determine interface for type9 or area for type10 LSAs. */ + switch (data->type) + { + case OSPF_OPAQUE_LINK_LSA: + oi = ospf_apiserver_if_lookup_by_addr (omsg->ifaddr); + if (!oi) + { + zlog_warn ("apiserver_originate: unknown interface %s", + inet_ntoa (omsg->ifaddr)); + rc = OSPF_API_NOSUCHINTERFACE; + goto out; + } + area = oi->area; + lsdb = area->lsdb; + break; + case OSPF_OPAQUE_AREA_LSA: + area = ospf_area_lookup_by_area_id (ospf, omsg->area_id); + if (!area) + { + zlog_warn ("apiserver_originate: unknown area %s", + inet_ntoa (omsg->area_id)); + rc = OSPF_API_NOSUCHAREA; + goto out; + } + lsdb = area->lsdb; + break; + case OSPF_OPAQUE_AS_LSA: + lsdb = ospf->lsdb; + break; + default: + /* We can only handle opaque types here */ + zlog_warn ("apiserver_originate: Cannot originate non-opaque LSA type %d", + data->type); + rc = OSPF_API_ILLEGALLSATYPE; + goto out; + } + + /* Check if we registered this opaque type */ + lsa_type = data->type; + opaque_type = GET_OPAQUE_TYPE (ntohl (data->id.s_addr)); + + if (!apiserver_is_opaque_type_registered (apiserv, lsa_type, opaque_type)) + { + zlog_warn ("apiserver_originate: LSA-type(%d)/Opaque-type(%d): Not registered", lsa_type, opaque_type); + rc = OSPF_API_OPAQUETYPENOTREGISTERED; + goto out; + } + + /* Make sure that the neighbors are ready before we can originate */ + switch (data->type) + { + case OSPF_OPAQUE_LINK_LSA: + ready = ospf_apiserver_is_ready_type9 (oi); + break; + case OSPF_OPAQUE_AREA_LSA: + ready = ospf_apiserver_is_ready_type10 (area); + break; + case OSPF_OPAQUE_AS_LSA: + ready = ospf_apiserver_is_ready_type11 (ospf); + break; + default: + break; + } + + if (!ready) + { + zlog_warn ("Neighbors not ready to originate type %d", data->type); + rc = OSPF_API_NOTREADY; + goto out; + } + + /* Create OSPF's internal opaque LSA representation */ + new = ospf_apiserver_opaque_lsa_new (area, oi, data); + if (!new) + { + rc = OSPF_API_NOMEMORY; /* XXX */ + goto out; + } + + /* Determine if LSA is new or an update for an existing one. */ + old = ospf_lsdb_lookup (lsdb, new); + + if (!old) + { + /* New LSA install in LSDB. */ + rc = ospf_apiserver_originate1 (new); + } + else + { + /* + * Keep the new LSA instance in the "waiting place" until the next + * refresh timing. If several LSA update requests for the same LSID + * have issued by peer, the last one takes effect. + */ + new->lsdb = &apiserv->reserve; + ospf_lsdb_add (&apiserv->reserve, new); + + /* Kick the scheduler function. */ + ospf_opaque_lsa_refresh_schedule (old); + } + +out: + + /* Send a reply back to client with return code */ + rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc); + return rc; +} + + +/* ----------------------------------------------------------- + * Flood an LSA within its flooding scope. + * ----------------------------------------------------------- + */ + +/* XXX We can probably use ospf_flood_through instead of this function + but then we need the neighbor parameter. If we set nbr to + NULL then ospf_flood_through crashes due to dereferencing NULL. */ + +void +ospf_apiserver_flood_opaque_lsa (struct ospf_lsa *lsa) +{ + assert (lsa); + + switch (lsa->data->type) + { + case OSPF_OPAQUE_LINK_LSA: + /* Increment counters? XXX */ + + /* Flood LSA through local network. */ + ospf_flood_through_area (lsa->area, NULL /*nbr */ , lsa); + break; + case OSPF_OPAQUE_AREA_LSA: + /* Update LSA origination count. */ + assert (lsa->area); + lsa->area->ospf->lsa_originate_count++; + + /* Flood LSA through area. */ + ospf_flood_through_area (lsa->area, NULL /*nbr */ , lsa); + break; + case OSPF_OPAQUE_AS_LSA: + { + struct ospf *ospf; + + ospf = ospf_lookup(); + assert(ospf); + + /* Increment counters? XXX */ + + /* Flood LSA through AS. */ + ospf_flood_through_as (ospf, NULL /*nbr */ , lsa); + break; + } + } +} + +int +ospf_apiserver_originate1 (struct ospf_lsa *lsa) +{ + struct ospf *ospf; + + ospf = ospf_lookup(); + assert(ospf); + + /* Install this LSA into LSDB. */ + if (ospf_lsa_install (ospf, lsa->oi, lsa) == NULL) + { + zlog_warn ("ospf_apiserver_originate1: ospf_lsa_install failed"); + return -1; + } + + /* Flood LSA within scope */ + +#ifdef NOTYET + /* + * NB: Modified version of "ospf_flood_though ()" accepts NULL "inbr" + * parameter, and thus it does not cause SIGSEGV error. + */ + ospf_flood_through (NULL /*nbr */ , lsa); +#else /* NOTYET */ + + ospf_apiserver_flood_opaque_lsa (lsa); +#endif /* NOTYET */ + + return 0; +} + + +/* Opaque LSAs of type 9 on a specific interface can now be + originated. Tell clients that registered type 9. */ +int +ospf_apiserver_lsa9_originator (void *arg) +{ + struct ospf_interface *oi; + + oi = (struct ospf_interface *) arg; + if (listcount (apiserver_list) > 0) { + ospf_apiserver_clients_notify_ready_type9 (oi); + } + return 0; +} + +int +ospf_apiserver_lsa10_originator (void *arg) +{ + struct ospf_area *area; + + area = (struct ospf_area *) arg; + if (listcount (apiserver_list) > 0) { + ospf_apiserver_clients_notify_ready_type10 (area); + } + return 0; +} + +int +ospf_apiserver_lsa11_originator (void *arg) +{ + struct ospf *ospf; + + ospf = (struct ospf *) arg; + if (listcount (apiserver_list) > 0) { + ospf_apiserver_clients_notify_ready_type11 (ospf); + } + return 0; +} + + +/* Periodically refresh opaque LSAs so that they do not expire in + other routers. */ +void +ospf_apiserver_lsa_refresher (struct ospf_lsa *lsa) +{ + struct ospf_apiserver *apiserv; + struct ospf_lsa *new = NULL; + struct ospf * ospf; + + ospf = ospf_lookup(); + assert(ospf); + + apiserv = lookup_apiserver_by_lsa (lsa); + if (!apiserv) + { + zlog_warn ("ospf_apiserver_lsa_refresher: LSA[%s]: No apiserver?", dump_lsa_key (lsa)); + lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); /* Flush it anyway. */ + } + + if (IS_LSA_MAXAGE (lsa)) + { + ospf_opaque_lsa_flush_schedule (lsa); + goto out; + } + + /* Check if updated version of LSA instance has already prepared. */ + new = ospf_lsdb_lookup (&apiserv->reserve, lsa); + if (!new) + { + /* This is a periodic refresh, driven by core OSPF mechanism. */ + new = ospf_apiserver_opaque_lsa_new (lsa->area, lsa->oi, lsa->data); + if (!new) + { + zlog_warn ("ospf_apiserver_lsa_refresher: Cannot create a new LSA?"); + goto out; + } + } + else + { + /* This is a forcible refresh, requested by OSPF-API client. */ + ospf_lsdb_delete (&apiserv->reserve, new); + new->lsdb = NULL; + } + + /* Increment sequence number */ + new->data->ls_seqnum = lsa_seqnum_increment (lsa); + + /* New LSA is in same area. */ + new->area = lsa->area; + SET_FLAG (new->flags, OSPF_LSA_SELF); + + /* Install LSA into LSDB. */ + if (ospf_lsa_install (ospf, new->oi, new) == NULL) + { + zlog_warn ("ospf_apiserver_lsa_refresher: ospf_lsa_install failed"); + ospf_lsa_free (new); + goto out; + } + + /* Flood updated LSA through interface, area or AS */ + +#ifdef NOTYET + ospf_flood_through (NULL /*nbr */ , new); +#endif /* NOTYET */ + ospf_apiserver_flood_opaque_lsa (new); + + /* Debug logging. */ + if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) + { + zlog_info ("LSA[Type%d:%s]: Refresh Opaque LSA", + new->data->type, inet_ntoa (new->data->id)); + ospf_lsa_header_dump (new->data); + } + +out: + return; +} + + +/* ----------------------------------------------------------- + * Followings are functions to delete LSAs + * ----------------------------------------------------------- + */ + +int +ospf_apiserver_handle_delete_request (struct ospf_apiserver *apiserv, + struct msg *msg) +{ + struct msg_delete_request *dmsg; + struct ospf_lsa *old; + struct ospf_area *area = NULL; + struct in_addr id; + int lsa_type, opaque_type; + int rc = 0; + struct ospf * ospf; + + ospf = ospf_lookup(); + assert(ospf); + + /* Extract opaque LSA from message */ + dmsg = (struct msg_delete_request *) STREAM_DATA (msg->s); + + /* Lookup area for link-local and area-local opaque LSAs */ + switch (dmsg->lsa_type) + { + case OSPF_OPAQUE_LINK_LSA: + case OSPF_OPAQUE_AREA_LSA: + area = ospf_area_lookup_by_area_id (ospf, dmsg->area_id); + if (!area) + { + zlog_warn ("ospf_apiserver_lsa_delete: unknown area %s", + inet_ntoa (dmsg->area_id)); + rc = OSPF_API_NOSUCHAREA; + goto out; + } + break; + case OSPF_OPAQUE_AS_LSA: + /* AS-external opaque LSAs have no designated area */ + area = NULL; + break; + default: + zlog_warn + ("ospf_apiserver_lsa_delete: Cannot delete non-opaque LSA type %d", + dmsg->lsa_type); + rc = OSPF_API_ILLEGALLSATYPE; + goto out; + } + + /* Check if we registered this opaque type */ + lsa_type = dmsg->lsa_type; + opaque_type = dmsg->opaque_type; + + if (!apiserver_is_opaque_type_registered (apiserv, lsa_type, opaque_type)) + { + zlog_warn ("ospf_apiserver_lsa_delete: LSA-type(%d)/Opaque-type(%d): Not registered", lsa_type, opaque_type); + rc = OSPF_API_OPAQUETYPENOTREGISTERED; + goto out; + } + + /* opaque_id is in network byte order */ + id.s_addr = htonl (SET_OPAQUE_LSID (dmsg->opaque_type, + ntohl (dmsg->opaque_id))); + + /* + * Even if the target LSA has once scheduled to flush, it remains in + * the LSDB until it is finally handled by the maxage remover thread. + * Therefore, the lookup function below may return non-NULL result. + */ + old = ospf_lsa_lookup (area, dmsg->lsa_type, id, ospf->router_id); + if (!old) + { + zlog_warn ("ospf_apiserver_lsa_delete: LSA[Type%d:%s] not in LSDB", + dmsg->lsa_type, inet_ntoa (id)); + rc = OSPF_API_NOSUCHLSA; + goto out; + } + + /* Schedule flushing of LSA from LSDB */ + /* NB: Multiple scheduling will produce a warning message, but harmless. */ + ospf_opaque_lsa_flush_schedule (old); + +out: + + /* Send reply back to client including return code */ + rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc); + return rc; +} + +/* Flush self-originated opaque LSA */ +int +apiserver_flush_opaque_type_callback (struct ospf_lsa *lsa, + void *p_arg, int int_arg) +{ + struct param_t + { + struct ospf_apiserver *apiserv; + u_char lsa_type; + u_char opaque_type; + } + *param; + + /* Sanity check */ + assert (lsa->data); + assert (p_arg); + param = (struct param_t *) p_arg; + + /* If LSA matches type and opaque type then delete it */ + if (IS_LSA_SELF (lsa) && lsa->data->type == param->lsa_type + && GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)) == param->opaque_type) + { + ospf_opaque_lsa_flush_schedule (lsa); + } + return 0; +} + +/* Delete self-originated opaque LSAs of a given opaque type. This + function is called when an application unregisters a given opaque + type or a connection to an application closes and all those opaque + LSAs need to be flushed the LSDB. */ +void +ospf_apiserver_flush_opaque_lsa (struct ospf_apiserver *apiserv, + u_char lsa_type, u_char opaque_type) +{ + struct param_t + { + struct ospf_apiserver *apiserv; + u_char lsa_type; + u_char opaque_type; + } + param; + listnode node; + struct ospf * ospf; + + ospf = ospf_lookup(); + assert(ospf); + + /* Set parameter struct. */ + param.apiserv = apiserv; + param.lsa_type = lsa_type; + param.opaque_type = opaque_type; + +#ifdef ORIGINAL_CODING + /* Iterate over all areas */ + for (node = listhead (ospf_top->areas); node; nextnode (node)) + { + struct ospf_area *area = node->data; + + foreach_lsa (OPAQUE_LINK_LSDB (area), (void *) ¶m, 0, + apiserver_flush_opaque_type_callback); + foreach_lsa (OPAQUE_AREA_LSDB (area), (void *) ¶m, 0, + apiserver_flush_opaque_type_callback); + } + + /* For AS-external opaque LSAs */ + if (ospf->lsdb) + { + foreach_lsa (OPAQUE_AS_LSDB (ospf_top), (void *) ¶m, 0, + apiserver_flush_opaque_type_callback); + } +#else /* ORIGINAL_CODING */ + switch (lsa_type) + { + struct route_node *rn; + struct ospf_lsa *lsa; + + case OSPF_OPAQUE_LINK_LSA: + for (node = listhead (ospf->areas); node; nextnode (node)) + { + struct ospf_area *area = node->data; + LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa) + apiserver_flush_opaque_type_callback(lsa, (void *) ¶m, 0); + } + break; + case OSPF_OPAQUE_AREA_LSA: + for (node = listhead (ospf->areas); node; nextnode (node)) + { + struct ospf_area *area = node->data; + LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa) + apiserver_flush_opaque_type_callback(lsa, (void *) ¶m, 0); + } + break; + case OSPF_OPAQUE_AS_LSA: + LSDB_LOOP (OPAQUE_LINK_LSDB (ospf), rn, lsa) + apiserver_flush_opaque_type_callback(lsa, (void *) ¶m, 0); + break; + default: + break; + } + return; +#endif /* ORIGINAL_CODING */ +} + + +/* ----------------------------------------------------------- + * Followings are callback functions to handle opaque types + * ----------------------------------------------------------- + */ + +int +ospf_apiserver_new_if (struct interface *ifp) +{ + struct ospf_interface *oi; + + /* For some strange reason it seems possible that we are invoked + with an interface that has no name. This seems to happen during + initialization. Return if this happens */ + + if (ifp->name[0] == '\0') { + /* interface has empty name */ + zlog_warn ("ospf_apiserver_new_if: interface has no name?"); + return 0; + } + + /* zlog_warn for debugging */ + zlog_warn ("ospf_apiserver_new_if"); + zlog_warn ("ifp name=%s status=%d index=%d", ifp->name, ifp->status, + ifp->ifindex); + + if (ifp->name[0] == '\0') { + /* interface has empty name */ + zlog_warn ("ospf_apiserver_new_if: interface has no name?"); + return 0; + } + + oi = ospf_apiserver_if_lookup_by_ifp (ifp); + + if (!oi) { + /* This interface is known to Zebra but not to OSPF daemon yet. */ + zlog_warn ("ospf_apiserver_new_if: interface %s not known to OSPFd?", + ifp->name); + return 0; + } + + assert (oi); + + /* New interface added to OSPF, tell clients about it */ + if (listcount (apiserver_list) > 0) { + ospf_apiserver_clients_notify_new_if (oi); + } + return 0; +} + +int +ospf_apiserver_del_if (struct interface *ifp) +{ + struct ospf_interface *oi; + + /* zlog_warn for debugging */ + zlog_warn ("ospf_apiserver_del_if"); + zlog_warn ("ifp name=%s status=%d index=%d\n", ifp->name, ifp->status, + ifp->ifindex); + + oi = ospf_apiserver_if_lookup_by_ifp (ifp); + + if (!oi) { + /* This interface is known to Zebra but not to OSPF daemon + anymore. No need to tell clients about it */ + return 0; + } + + /* Interface deleted, tell clients about it */ + if (listcount (apiserver_list) > 0) { + ospf_apiserver_clients_notify_del_if (oi); + } + return 0; +} + +void +ospf_apiserver_ism_change (struct ospf_interface *oi, int old_state) +{ + /* Tell clients about interface change */ + + /* zlog_warn for debugging */ + zlog_warn ("ospf_apiserver_ism_change"); + if (listcount (apiserver_list) > 0) { + ospf_apiserver_clients_notify_ism_change (oi); + } + + zlog_warn ("oi->ifp->name=%s", oi->ifp->name); + zlog_warn ("old_state=%d", old_state); + zlog_warn ("oi->state=%d", oi->state); +} + +void +ospf_apiserver_nsm_change (struct ospf_neighbor *nbr, int old_status) +{ + /* Neighbor status changed, tell clients about it */ + zlog_warn ("ospf_apiserver_nsm_change"); + if (listcount (apiserver_list) > 0) { + ospf_apiserver_clients_notify_nsm_change (nbr); + } +} + +void +ospf_apiserver_show_info (struct vty *vty, struct ospf_lsa *lsa) +{ + struct opaque_lsa + { + struct lsa_header header; + u_char data[1]; /* opaque data have variable length. This is start + address */ + }; + struct opaque_lsa *olsa; + int opaquelen; + + olsa = (struct opaque_lsa *) lsa->data; + + if (VALID_OPAQUE_INFO_LEN (lsa->data)) + { + opaquelen = ntohs (lsa->data->length) - OSPF_LSA_HEADER_SIZE; + } + else + { + opaquelen = 0; + } + + /* Output information about opaque LSAs */ + if (vty != NULL) + { + int i; + vty_out (vty, " Added using OSPF API: %u octets of opaque data %s%s", + opaquelen, + VALID_OPAQUE_INFO_LEN (lsa->data) ? "" : "(Invalid length?)", + VTY_NEWLINE); + vty_out (vty, " Opaque data: "); + + for (i = 0; i < opaquelen; i++) + { + vty_out (vty, "0x%x ", olsa->data[i]); + } + vty_out (vty, "%s", VTY_NEWLINE); + } + else + { + int i; + zlog_info (" Added using OSPF API: %u octets of opaque data %s", + opaquelen, + VALID_OPAQUE_INFO_LEN (lsa-> + data) ? "" : "(Invalid length?)"); + zlog_info (" Opaque data: "); + + for (i = 0; i < opaquelen; i++) + { + zlog_info ("0x%x ", olsa->data[i]); + } + zlog_info ("\n"); + } + return; +} + +/* ----------------------------------------------------------- + * Followings are functions to notify clients about events + * ----------------------------------------------------------- + */ + +/* Send a message to all clients. This is useful for messages + that need to be notified to all clients (such as interface + changes) */ + +void +ospf_apiserver_clients_notify_all (struct msg *msg) +{ + listnode node; + + /* Send message to all clients */ + for (node = listhead (apiserver_list); node; nextnode (node)) + { + struct ospf_apiserver *apiserv = + (struct ospf_apiserver *) getdata (node); + + ospf_apiserver_send_msg (apiserv, msg); + } +} + +/* An interface is now ready to accept opaque LSAs. Notify all + clients that registered to use this opaque type */ +void +ospf_apiserver_clients_notify_ready_type9 (struct ospf_interface *oi) +{ + listnode node; + struct msg *msg; + + assert (oi); + if (!oi->address) + { + zlog_warn ("Interface has no address?"); + return; + } + + if (!ospf_apiserver_is_ready_type9 (oi)) + { + zlog_warn ("Interface not ready for type 9?"); + return; + } + + for (node = listhead (apiserver_list); node; nextnode (node)) + { + struct ospf_apiserver *apiserv = + (struct ospf_apiserver *) getdata (node); + listnode n2; + + for (n2 = listhead (apiserv->opaque_types); n2; nextnode (n2)) + { + struct registered_opaque_type *r = + (struct registered_opaque_type *) getdata (n2); + if (r->lsa_type == OSPF_OPAQUE_LINK_LSA) + { + msg = new_msg_ready_notify (0, OSPF_OPAQUE_LINK_LSA, + r->opaque_type, + oi->address->u.prefix4); + if (!msg) + { + zlog_warn + ("ospf_apiserver_clients_notify_ready_type9: new_msg_ready_notify failed"); +#ifdef NOTYET + /* Cannot allocate new message. What should we do? */ + ospf_apiserver_free (apiserv); +#endif + goto out; + } + + ospf_apiserver_send_msg (apiserv, msg); + msg_free (msg); + } + } + } + +out: + return; +} + +void +ospf_apiserver_clients_notify_ready_type10 (struct ospf_area *area) +{ + listnode node; + struct msg *msg; + + assert (area); + + if (!ospf_apiserver_is_ready_type10 (area)) + { + zlog_warn ("Area not ready for type 10?"); + return; + } + + for (node = listhead (apiserver_list); node; nextnode (node)) + { + struct ospf_apiserver *apiserv = + (struct ospf_apiserver *) getdata (node); + listnode n2; + + for (n2 = listhead (apiserv->opaque_types); n2; nextnode (n2)) + { + struct registered_opaque_type *r = + (struct registered_opaque_type *) getdata (n2); + if (r->lsa_type == OSPF_OPAQUE_AREA_LSA) + { + msg = new_msg_ready_notify (0, OSPF_OPAQUE_AREA_LSA, + r->opaque_type, area->area_id); + if (!msg) + { + zlog_warn + ("ospf_apiserver_clients_notify_ready_type10: new_msg_ready_nofity failed"); +#ifdef NOTYET + /* Cannot allocate new message. What should we do? */ + ospf_apiserver_free (apiserv); +#endif + goto out; + } + + ospf_apiserver_send_msg (apiserv, msg); + msg_free (msg); + } + } + } + +out: + return; +} + + +void +ospf_apiserver_clients_notify_ready_type11 (struct ospf *top) +{ + listnode node; + struct msg *msg; + struct in_addr id_null = { 0L }; + + assert (top); + + if (!ospf_apiserver_is_ready_type11 (top)) + { + zlog_warn ("AS not ready for type 11?"); + return; + } + + for (node = listhead (apiserver_list); node; nextnode (node)) + { + struct ospf_apiserver *apiserv = + (struct ospf_apiserver *) getdata (node); + listnode n2; + + for (n2 = listhead (apiserv->opaque_types); n2; nextnode (n2)) + { + struct registered_opaque_type *r = + (struct registered_opaque_type *) getdata (n2); + if (r->lsa_type == OSPF_OPAQUE_AS_LSA) + { + msg = new_msg_ready_notify (0, OSPF_OPAQUE_AS_LSA, + r->opaque_type, id_null); + if (!msg) + { + zlog_warn + ("ospf_apiserver_clients_notify_ready_type11: new_msg_ready_notify failed"); +#ifdef NOTYET + /* Cannot allocate new message. What should we do? */ + ospf_apiserver_free (apiserv); +#endif + goto out; + } + + ospf_apiserver_send_msg (apiserv, msg); + msg_free (msg); + } + } + } + +out: + return; +} + +void +ospf_apiserver_clients_notify_new_if (struct ospf_interface *oi) +{ + struct msg *msg; + + msg = new_msg_new_if (0, oi->address->u.prefix4, oi->area->area_id); + if (msg != NULL) + { + ospf_apiserver_clients_notify_all (msg); + msg_free (msg); + } +} + +void +ospf_apiserver_clients_notify_del_if (struct ospf_interface *oi) +{ + struct msg *msg; + + msg = new_msg_del_if (0, oi->address->u.prefix4); + if (msg != NULL) + { + ospf_apiserver_clients_notify_all (msg); + msg_free (msg); + } +} + +void +ospf_apiserver_clients_notify_ism_change (struct ospf_interface *oi) +{ + struct msg *msg; + struct in_addr ifaddr = { 0L }; + struct in_addr area_id = { 0L }; + + assert (oi); + assert (oi->ifp); + + if (oi->address) + { + ifaddr = oi->address->u.prefix4; + } + if (oi->area) + { + area_id = oi->area->area_id; + } + + msg = new_msg_ism_change (0, ifaddr, area_id, oi->ifp->status); + if (!msg) + { + zlog_warn ("apiserver_clients_notify_ism_change: msg_new failed"); + return; + } + + ospf_apiserver_clients_notify_all (msg); + msg_free (msg); +} + +void +ospf_apiserver_clients_notify_nsm_change (struct ospf_neighbor *nbr) +{ + struct msg *msg; + struct in_addr ifaddr = { 0L }; + struct in_addr nbraddr = { 0L }; + + assert (nbr); + + if (nbr->oi) + { + ifaddr = nbr->oi->address->u.prefix4; + } + + nbraddr = nbr->address.u.prefix4; + + msg = new_msg_nsm_change (0, ifaddr, nbraddr, nbr->router_id, nbr->state); + if (!msg) + { + zlog_warn ("apiserver_clients_notify_nsm_change: msg_new failed"); + return; + } + + ospf_apiserver_clients_notify_all (msg); + msg_free (msg); +} + +void +apiserver_clients_lsa_change_notify (u_char msgtype, struct ospf_lsa *lsa) +{ + struct msg *msg; + listnode node; + + /* Default area for AS-External and Opaque11 LSAs */ + struct in_addr area_id = { 0L }; + + /* Default interface for non Opaque9 LSAs */ + struct in_addr ifaddr = { 0L }; + + if (lsa->area) + { + area_id = lsa->area->area_id; + } + if (lsa->data->type == OSPF_OPAQUE_LINK_LSA) + { + assert (lsa->oi); + ifaddr = lsa->oi->address->u.prefix4; + } + + /* Prepare message that can be sent to clients that have a matching + filter */ + msg = new_msg_lsa_change_notify (msgtype, 0L, /* no sequence number */ + ifaddr, area_id, + lsa->flags & OSPF_LSA_SELF, lsa->data); + if (!msg) + { + zlog_warn ("apiserver_clients_lsa_change_notify: msg_new failed"); + return; + } + + /* Now send message to all clients with a matching filter */ + for (node = listhead (apiserver_list); node; nextnode (node)) + { + struct ospf_apiserver *apiserv = (struct ospf_apiserver *) node->data; + struct lsa_filter_type *filter; + u_int16_t mask; + u_int32_t *area; + int i; + + /* Check filter for this client. */ + filter = apiserv->filter; + + /* Check area IDs in case of non AS-E LSAs. + * If filter has areas (num_areas > 0), + * then one of the areas must match the area ID of this LSA. */ + + i = filter->num_areas; + if ((lsa->data->type == OSPF_AS_EXTERNAL_LSA) || + (lsa->data->type == OSPF_OPAQUE_AS_LSA)) + { + i = 0; + } + + if (i > 0) + { + area = (u_int32_t *) (filter + 1); + while (i) + { + if (*area == area_id.s_addr) + { + break; + } + i--; + area++; + } + } + else + { + i = 1; + } + + if (i > 0) + { + /* Area match. Check LSA type. */ + mask = ntohs (filter->typemask); + + if (mask & Power2[lsa->data->type]) + { + /* Type also matches. Check origin. */ + if ((filter->origin == ANY_ORIGIN) || + (filter->origin == IS_LSA_SELF (lsa))) + { + ospf_apiserver_send_msg (apiserv, msg); + } + } + } + } + /* Free message since it is not used anymore */ + msg_free (msg); +} + + +/* ------------------------------------------------------------- + * Followings are hooks invoked when LSAs are updated or deleted + * ------------------------------------------------------------- + */ + + +int +apiserver_notify_clients_lsa (u_char msgtype, struct ospf_lsa *lsa) +{ + struct msg *msg; + /* default area for AS-External and Opaque11 LSAs */ + struct in_addr area_id = { 0L }; + + /* default interface for non Opaque9 LSAs */ + struct in_addr ifaddr = { 0L }; + + /* Only notify this update if the LSA's age is smaller than + MAXAGE. Otherwise clients would see LSA updates with max age just + before they are deleted from the LSDB. LSA delete messages have + MAXAGE too but should not be filtered. */ + if (IS_LSA_MAXAGE(lsa) && (msgtype == MSG_LSA_UPDATE_NOTIFY)) { + return 0; + } + + if (lsa->area) + { + area_id = lsa->area->area_id; + } + if (lsa->data->type == OSPF_OPAQUE_LINK_LSA) + { + ifaddr = lsa->oi->address->u.prefix4; + } + msg = new_msg_lsa_change_notify (msgtype, 0L, /* no sequence number */ + ifaddr, area_id, + lsa->flags & OSPF_LSA_SELF, lsa->data); + if (!msg) + { + zlog_warn ("notify_clients_lsa: msg_new failed"); + return -1; + } + /* Notify all clients that new LSA is added/updated */ + apiserver_clients_lsa_change_notify (msgtype, lsa); + + /* Clients made their own copies of msg so we can free msg here */ + msg_free (msg); + + return 0; +} + +int +ospf_apiserver_lsa_update (struct ospf_lsa *lsa) +{ + return apiserver_notify_clients_lsa (MSG_LSA_UPDATE_NOTIFY, lsa); +} + +int +ospf_apiserver_lsa_delete (struct ospf_lsa *lsa) +{ + return apiserver_notify_clients_lsa (MSG_LSA_DELETE_NOTIFY, lsa); +} + +#endif /* SUPPORT_OSPF_API */ + diff --git a/ospfd/ospf_apiserver.h b/ospfd/ospf_apiserver.h new file mode 100644 index 00000000..c7145782 --- /dev/null +++ b/ospfd/ospf_apiserver.h @@ -0,0 +1,201 @@ +/* + * Server side of OSPF API. + * Copyright (C) 2001, 2002 Ralph Keller + * + * 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 _OSPF_APISERVER_H +#define _OSPF_APISERVER_H + +/* MTYPE definition is not reflected to "memory.h". */ +#define MTYPE_OSPF_APISERVER MTYPE_TMP +#define MTYPE_OSPF_APISERVER_MSGFILTER MTYPE_TMP + +/* List of opaque types that application registered */ +struct registered_opaque_type +{ + u_char lsa_type; + u_char opaque_type; +}; + + +/* Server instance for each accepted client connection. */ +struct ospf_apiserver +{ + /* Socket connections for synchronous commands and asynchronous + notifications */ + int fd_sync; /* synchronous requests */ + struct sockaddr_in peer_sync; + + int fd_async; /* asynchronous notifications */ + struct sockaddr_in peer_async; + + /* List of all opaque types that application registers to use. Using + a single connection with the OSPF daemon, multiple + <lsa,opaque_type> pairs can be registered. However, each + combination can only be registered once by all applications. */ + list opaque_types; /* of type registered_opaque_type */ + + /* Temporary storage for LSA instances to be refreshed. */ + struct ospf_lsdb reserve; + + /* filter for LSA update/delete notifies */ + struct lsa_filter_type *filter; + + /* Fifo buffers for outgoing messages */ + struct msg_fifo *out_sync_fifo; + struct msg_fifo *out_async_fifo; + + /* Read and write threads */ + struct thread *t_sync_read; +#ifdef USE_ASYNC_READ + struct thread *t_async_read; +#endif /* USE_ASYNC_READ */ + struct thread *t_sync_write; + struct thread *t_async_write; +}; + +enum event +{ + OSPF_APISERVER_ACCEPT, + OSPF_APISERVER_SYNC_READ, +#ifdef USE_ASYNC_READ + OSPF_APISERVER_ASYNC_READ, +#endif /* USE_ASYNC_READ */ + OSPF_APISERVER_SYNC_WRITE, + OSPF_APISERVER_ASYNC_WRITE +}; + +/* ----------------------------------------------------------- + * Followings are functions to manage client connections. + * ----------------------------------------------------------- + */ + +unsigned short ospf_apiserver_getport (void); +int ospf_apiserver_init (void); +void ospf_apiserver_term (void); +struct ospf_apiserver *ospf_apiserver_new (int fd_sync, int fd_async); +void ospf_apiserver_free (struct ospf_apiserver *apiserv); +void ospf_apiserver_event (enum event event, int fd, + struct ospf_apiserver *apiserv); +int ospf_apiserver_serv_sock_family (unsigned short port, int family); +int ospf_apiserver_accept (struct thread *thread); +int ospf_apiserver_read (struct thread *thread); +int ospf_apiserver_sync_write (struct thread *thread); +int ospf_apiserver_async_write (struct thread *thread); +int ospf_apiserver_send_reply (struct ospf_apiserver *apiserv, + u_int32_t seqnr, u_char rc); + +/* ----------------------------------------------------------- + * Followings are message handler functions + * ----------------------------------------------------------- + */ + +int ospf_apiserver_lsa9_originator (void *arg); +int ospf_apiserver_lsa10_originator (void *arg); +int ospf_apiserver_lsa11_originator (void *arg); + +void ospf_apiserver_clients_notify_all (struct msg *msg); + +void ospf_apiserver_clients_notify_ready_type9 (struct ospf_interface *oi); +void ospf_apiserver_clients_notify_ready_type10 (struct ospf_area *area); +void ospf_apiserver_clients_notify_ready_type11 (struct ospf *top); + +void ospf_apiserver_clients_notify_new_if (struct ospf_interface *oi); +void ospf_apiserver_clients_notify_del_if (struct ospf_interface *oi); +void ospf_apiserver_clients_notify_ism_change (struct ospf_interface *oi); +void ospf_apiserver_clients_notify_nsm_change (struct ospf_neighbor *nbr); + +int ospf_apiserver_is_ready_type9 (struct ospf_interface *oi); +int ospf_apiserver_is_ready_type10 (struct ospf_area *area); +int ospf_apiserver_is_ready_type11 (struct ospf *ospf); + +void ospf_apiserver_notify_ready_type9 (struct ospf_apiserver *apiserv); +void ospf_apiserver_notify_ready_type10 (struct ospf_apiserver *apiserv); +void ospf_apiserver_notify_ready_type11 (struct ospf_apiserver *apiserv); + +int ospf_apiserver_handle_msg (struct ospf_apiserver *apiserv, + struct msg *msg); +int ospf_apiserver_handle_register_opaque_type (struct ospf_apiserver + *apiserv, struct msg *msg); +int ospf_apiserver_handle_unregister_opaque_type (struct ospf_apiserver + *apiserv, struct msg *msg); +int ospf_apiserver_handle_register_event (struct ospf_apiserver *apiserv, + struct msg *msg); +int ospf_apiserver_handle_originate_request (struct ospf_apiserver *apiserv, + struct msg *msg); +int ospf_apiserver_handle_delete_request (struct ospf_apiserver *apiserv, + struct msg *msg); +int ospf_apiserver_handle_sync_lsdb (struct ospf_apiserver *apiserv, + struct msg *msg); + + +/* ----------------------------------------------------------- + * Followings are functions for LSA origination/deletion + * ----------------------------------------------------------- + */ + +int ospf_apiserver_register_opaque_type (struct ospf_apiserver *apiserver, + u_char lsa_type, u_char opaque_type); +int ospf_apiserver_unregister_opaque_type (struct ospf_apiserver *apiserver, + u_char lsa_type, + u_char opaque_type); +struct ospf_lsa *ospf_apiserver_opaque_lsa_new (struct ospf_area *area, + struct ospf_interface *oi, + struct lsa_header *protolsa); +struct ospf_interface *ospf_apiserver_if_lookup_by_addr (struct in_addr + address); +struct ospf_interface *ospf_apiserver_if_lookup_by_ifp (struct interface + *ifp); +int ospf_apiserver_originate1 (struct ospf_lsa *lsa); +void ospf_apiserver_flood_opaque_lsa (struct ospf_lsa *lsa); + + +/* ----------------------------------------------------------- + * Followings are callback functions to handle opaque types + * ----------------------------------------------------------- + */ + +int ospf_apiserver_new_if (struct interface *ifp); +int ospf_apiserver_del_if (struct interface *ifp); +void ospf_apiserver_ism_change (struct ospf_interface *oi, int old_status); +void ospf_apiserver_nsm_change (struct ospf_neighbor *nbr, int old_status); +void ospf_apiserver_config_write_router (struct vty *vty); +void ospf_apiserver_config_write_if (struct vty *vty, struct interface *ifp); +void ospf_apiserver_show_info (struct vty *vty, struct ospf_lsa *lsa); +int ospf_ospf_apiserver_lsa_originator (void *arg); +void ospf_apiserver_lsa_refresher (struct ospf_lsa *lsa); +void ospf_apiserver_flush_opaque_lsa (struct ospf_apiserver *apiserv, + u_char lsa_type, u_char opaque_type); + +/* ----------------------------------------------------------- + * Followings are hooks when LSAs are updated or deleted + * ----------------------------------------------------------- + */ + + +/* Hooks that are invoked from ospf opaque module */ + +int ospf_apiserver_lsa_update (struct ospf_lsa *lsa); +int ospf_apiserver_lsa_delete (struct ospf_lsa *lsa); + +void ospf_apiserver_clients_lsa_change_notify (u_char msgtype, + struct ospf_lsa *lsa); + +#endif /* _OSPF_APISERVER_H */ diff --git a/ospfd/ospf_asbr.c b/ospfd/ospf_asbr.c index fda32ae1..d13bbc43 100644 --- a/ospfd/ospf_asbr.c +++ b/ospfd/ospf_asbr.c @@ -43,16 +43,15 @@ #include "ospfd/ospf_route.h" #include "ospfd/ospf_zebra.h" #include "ospfd/ospf_dump.h" - /* Remove external route. */ void -ospf_external_route_remove (struct ospf *ospf, struct prefix_ipv4 *p) +ospf_external_route_remove (struct prefix_ipv4 *p) { struct route_node *rn; struct ospf_route *or; - rn = route_node_lookup (ospf->old_external_route, (struct prefix *) p); + rn = route_node_lookup (ospf_top->old_external_route, (struct prefix *) p); if (rn) if ((or = rn->info)) { @@ -77,12 +76,11 @@ ospf_external_route_remove (struct ospf *ospf, struct prefix_ipv4 *p) /* Lookup external route. */ struct ospf_route * -ospf_external_route_lookup (struct ospf *ospf, - struct prefix_ipv4 *p) +ospf_external_route_lookup (struct prefix_ipv4 *p) { struct route_node *rn; - rn = route_node_lookup (ospf->old_external_route, (struct prefix *) p); + rn = route_node_lookup (ospf_top->old_external_route, (struct prefix *) p); if (rn) { route_unlock_node (rn); @@ -205,15 +203,14 @@ ospf_external_info_lookup (u_char type, struct prefix_ipv4 *p) } struct ospf_lsa * -ospf_external_info_find_lsa (struct ospf *ospf, - struct prefix_ipv4 *p) +ospf_external_info_find_lsa (struct prefix_ipv4 *p) { struct ospf_lsa *lsa; struct as_external_lsa *al; struct in_addr mask, id; - lsa = ospf_lsdb_lookup_by_id (ospf->lsdb, OSPF_AS_EXTERNAL_LSA, - p->prefix, ospf->router_id); + lsa = ospf_lsdb_lookup_by_id (ospf_top->lsdb, OSPF_AS_EXTERNAL_LSA, + p->prefix, ospf_top->router_id); if (!lsa) return NULL; @@ -225,8 +222,8 @@ ospf_external_info_find_lsa (struct ospf *ospf, if (mask.s_addr != al->mask.s_addr) { id.s_addr = p->prefix.s_addr | (~mask.s_addr); - lsa = ospf_lsdb_lookup_by_id (ospf->lsdb, OSPF_AS_EXTERNAL_LSA, - id, ospf->router_id); + lsa = ospf_lsdb_lookup_by_id (ospf_top->lsdb, OSPF_AS_EXTERNAL_LSA, + id, ospf_top->router_id); if (!lsa) return NULL; } @@ -237,7 +234,7 @@ ospf_external_info_find_lsa (struct ospf *ospf, /* Update ASBR status. */ void -ospf_asbr_status_update (struct ospf *ospf, u_char status) +ospf_asbr_status_update (u_char status) { zlog_info ("ASBR[Status:%d]: Update", status); @@ -245,49 +242,46 @@ ospf_asbr_status_update (struct ospf *ospf, u_char status) if (status) { /* Already ASBR. */ - if (IS_OSPF_ASBR (ospf)) + if (OSPF_IS_ASBR) { zlog_info ("ASBR[Status:%d]: Already ASBR", status); return; } - SET_FLAG (ospf->flags, OSPF_FLAG_ASBR); + SET_FLAG (ospf_top->flags, OSPF_FLAG_ASBR); } else { /* Already non ASBR. */ - if (! IS_OSPF_ASBR (ospf)) + if (! OSPF_IS_ASBR) { zlog_info ("ASBR[Status:%d]: Already non ASBR", status); return; } - UNSET_FLAG (ospf->flags, OSPF_FLAG_ASBR); + UNSET_FLAG (ospf_top->flags, OSPF_FLAG_ASBR); } /* Transition from/to status ASBR, schedule timer. */ - ospf_spf_calculate_schedule (ospf); - OSPF_TIMER_ON (ospf->t_router_lsa_update, + ospf_spf_calculate_schedule (); + OSPF_TIMER_ON (ospf_top->t_router_lsa_update, ospf_router_lsa_update_timer, OSPF_LSA_UPDATE_DELAY); } void ospf_redistribute_withdraw (u_char type) { - struct ospf *ospf; struct route_node *rn; struct external_info *ei; - ospf = ospf_lookup (); - /* Delete external info for specified type. */ if (EXTERNAL_INFO (type)) for (rn = route_top (EXTERNAL_INFO (type)); rn; rn = route_next (rn)) if ((ei = rn->info)) - if (ospf_external_info_find_lsa (ospf, &ei->p)) + if (ospf_external_info_find_lsa (&ei->p)) { if (is_prefix_default (&ei->p) && - ospf->default_originate != DEFAULT_ORIGINATE_NONE) + ospf_top->default_originate != DEFAULT_ORIGINATE_NONE) continue; - ospf_external_lsa_flush (ospf, type, &ei->p, ei->ifindex, ei->nexthop); + ospf_external_lsa_flush (type, &ei->p, ei->ifindex, ei->nexthop); ospf_external_info_delete (type, ei->p); } } diff --git a/ospfd/ospf_asbr.h b/ospfd/ospf_asbr.h index ddfa9fae..f368246d 100644 --- a/ospfd/ospf_asbr.h +++ b/ospfd/ospf_asbr.h @@ -54,23 +54,22 @@ struct external_info #define OSPF_ASBR_CHECK_DELAY 30 -void ospf_external_route_remove (struct ospf *, struct prefix_ipv4 *); +void ospf_external_route_remove (struct prefix_ipv4 *p); struct external_info *ospf_external_info_new (u_char); -void ospf_reset_route_map_set_values (struct route_map_set_values *); -int ospf_route_map_set_compare (struct route_map_set_values *, - struct route_map_set_values *); +void ospf_reset_route_map_set_values (struct route_map_set_values *values); +int ospf_route_map_set_compare (struct route_map_set_values *values1, + struct route_map_set_values *values2); struct external_info *ospf_external_info_add (u_char, struct prefix_ipv4, unsigned int, struct in_addr); void ospf_external_info_delete (u_char, struct prefix_ipv4); struct external_info *ospf_external_info_lookup (u_char, struct prefix_ipv4 *); -void ospf_asbr_status_update (struct ospf *, u_char); +void ospf_asbr_status_update (u_char); void ospf_redistribute_withdraw (u_char); void ospf_asbr_check (); void ospf_schedule_asbr_check (); void ospf_asbr_route_install_lsa (struct ospf_lsa *); -struct ospf_lsa *ospf_external_info_find_lsa (struct ospf *, - struct prefix_ipv4 *p); +struct ospf_lsa *ospf_external_info_find_lsa (struct prefix_ipv4 *p); #endif /* _ZEBRA_OSPF_ASBR_H */ diff --git a/ospfd/ospf_ase.c b/ospfd/ospf_ase.c index b28626db..5605933b 100644 --- a/ospfd/ospf_ase.c +++ b/ospfd/ospf_ase.c @@ -155,7 +155,7 @@ ospf_ase_forward_address_check (struct ospf *ospf, struct in_addr fwd_addr) for (ifn = listhead (ospf->oiflist); ifn; nextnode (ifn)) if ((oi = getdata (ifn)) != NULL) - if (if_is_up (oi->ifp)) + if (if_is_operative (oi->ifp)) if (oi->type != OSPF_IFTYPE_VIRTUALLINK) if (IPV4_ADDR_SAME (&oi->address->u.prefix4, &fwd_addr)) return 0; @@ -644,6 +644,10 @@ ospf_ase_calculate_timer (struct thread *t) LSDB_LOOP (NSSA_LSDB (area), rn, lsa) ospf_ase_calculate_route (ospf, lsa); } + /* kevinm: And add the NSSA routes in ospf_top */ + LSDB_LOOP (NSSA_LSDB (ospf),rn,lsa) + ospf_ase_calculate_route(ospf,lsa); + #endif /* HAVE_NSSA */ /* Compare old and new external routing table and install the diff --git a/ospfd/ospf_ase.h b/ospfd/ospf_ase.h index d2fee1a1..f403e26d 100644 --- a/ospfd/ospf_ase.h +++ b/ospfd/ospf_ase.h @@ -24,18 +24,18 @@ #define _ZEBRA_OSPF_ASE_H -struct ospf_route *ospf_find_asbr_route (struct ospf *, struct route_table *, +struct ospf_route *ospf_find_asbr_route (struct route_table *, struct prefix_ipv4 *); struct ospf_route *ospf_find_asbr_route_through_area(struct route_table *, struct prefix_ipv4 *, struct ospf_area *); -int ospf_ase_calculate_route (struct ospf *, struct ospf_lsa *); -void ospf_ase_calculate_schedule (struct ospf *); -void ospf_ase_calculate_timer_add (struct ospf *); +int ospf_ase_calculate_route (struct ospf_lsa *, void *, int); +void ospf_ase_calculate_schedule (); +void ospf_ase_calculate_timer_add (); void ospf_ase_external_lsas_finish (struct route_table *); -void ospf_ase_incremental_update (struct ospf *, struct ospf_lsa *); +void ospf_ase_incremental_update (struct ospf_lsa *, struct ospf *); void ospf_ase_register_external_lsa (struct ospf_lsa *, struct ospf *); void ospf_ase_unregister_external_lsa (struct ospf_lsa *, struct ospf *); diff --git a/ospfd/ospf_dump.c b/ospfd/ospf_dump.c index da2e0973..f563fb89 100644 --- a/ospfd/ospf_dump.c +++ b/ospfd/ospf_dump.c @@ -1470,6 +1470,8 @@ DEFUN (show_debugging_ospf, if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE)) vty_out (vty, " OSPF Zebra redistribute debugging is on%s", VTY_NEWLINE); } + if (IS_DEBUG_OSPF (nssa, NSSA) == OSPF_DEBUG_NSSA) + vty_out (vty, " OSPF NSSA debugging is on%s", VTY_NEWLINE); return CMD_SUCCESS; } diff --git a/ospfd/ospf_flood.c b/ospfd/ospf_flood.c index cf88761e..1c8cbbf5 100644 --- a/ospfd/ospf_flood.c +++ b/ospfd/ospf_flood.c @@ -654,6 +654,7 @@ ospf_flood_through_as (struct ospf *ospf, struct ospf_neighbor *inbr, /* Type-7, flood NSSA area */ if (lsa->data->type == OSPF_AS_NSSA_LSA && area == lsa->area) + /* We will send it. */ continue_flag = 0; else continue_flag = 1; /* Skip this NSSA area for Type-5's et al */ diff --git a/ospfd/ospf_flood.h b/ospfd/ospf_flood.h index 2e3f0832..1a6ab979 100644 --- a/ospfd/ospf_flood.h +++ b/ospfd/ospf_flood.h @@ -20,17 +20,14 @@ * Boston, MA 02111-1307, USA. */ -#ifndef _ZEBRA_OSPF_FLOOD_H -#define _ZEBRA_OSPF_FLOOD_H +#ifndef _ZEBRA_OSPF_FLOODING_H +#define _ZEBRA_OSPF_FLOODING_H -int ospf_flood (struct ospf *, struct ospf_neighbor *, struct ospf_lsa *, - struct ospf_lsa *); -int ospf_flood_through (struct ospf *, struct ospf_neighbor *, - struct ospf_lsa *); +int ospf_flood (struct ospf_neighbor *, struct ospf_lsa *, struct ospf_lsa *); +int ospf_flood_through (struct ospf_neighbor *, struct ospf_lsa *); int ospf_flood_through_area (struct ospf_area *, struct ospf_neighbor *, struct ospf_lsa *); -int ospf_flood_through_as (struct ospf *, struct ospf_neighbor *, - struct ospf_lsa *); +int ospf_flood_through_as (struct ospf_neighbor *, struct ospf_lsa *); unsigned long ospf_ls_request_count (struct ospf_neighbor *); int ospf_ls_request_isempty (struct ospf_neighbor *); @@ -50,18 +47,19 @@ void ospf_ls_retransmit_delete (struct ospf_neighbor *, struct ospf_lsa *); void ospf_ls_retransmit_clear (struct ospf_neighbor *); struct ospf_lsa *ospf_ls_retransmit_lookup (struct ospf_neighbor *, struct ospf_lsa *); -void ospf_ls_retransmit_delete_nbr_area (struct ospf_area *, - struct ospf_lsa *); -void ospf_ls_retransmit_delete_nbr_as (struct ospf *, struct ospf_lsa *); +void ospf_ls_retransmit_delete_nbr_all (struct ospf_area *, struct ospf_lsa *); void ospf_ls_retransmit_add_nbr_all (struct ospf_interface *, struct ospf_lsa *); void ospf_flood_lsa_area (struct ospf_lsa *, struct ospf_area *); void ospf_flood_lsa_as (struct ospf_lsa *); void ospf_lsa_flush_area (struct ospf_lsa *, struct ospf_area *); -void ospf_lsa_flush_as (struct ospf *, struct ospf_lsa *); +void ospf_lsa_flush_as (struct ospf_lsa *); +void ospf_flush_through_as (struct ospf_lsa *); struct external_info *ospf_external_info_check (struct ospf_lsa *); +void debug_ospf_ls_retransmit (struct ospf_neighbor *); + void ospf_lsdb_init (struct ospf_lsdb *); -#endif /* _ZEBRA_OSPF_FLOOD_H */ +#endif /* _ZEBRA_OSPF_FLOODING_H */ diff --git a/ospfd/ospf_ia.c b/ospfd/ospf_ia.c index 59f86669..32c8d86b 100644 --- a/ospfd/ospf_ia.c +++ b/ospfd/ospf_ia.c @@ -71,9 +71,8 @@ ospf_find_abr_route (struct route_table *rtrs, } void -ospf_ia_network_route (struct ospf *ospf, struct route_table *rt, - struct prefix_ipv4 *p, struct ospf_route *new_or, - struct ospf_route *abr_or) +ospf_ia_network_route (struct route_table *rt, struct prefix_ipv4 *p, + struct ospf_route *new_or, struct ospf_route *abr_or) { struct route_node *rn1; struct ospf_route *or; @@ -95,7 +94,7 @@ ospf_ia_network_route (struct ospf *ospf, struct route_table *rt, zlog_info ("ospf_ia_network_route(): " "Found a route to the same network"); /* Check the existing route. */ - if ((res = ospf_route_cmp (ospf, new_or, or)) < 0) + if ((res = ospf_route_cmp (new_or, or)) < 0) { /* New route is better, so replace old one. */ ospf_route_subst (rn1, new_or, abr_or); @@ -128,19 +127,18 @@ ospf_ia_network_route (struct ospf *ospf, struct route_table *rt, } void -ospf_ia_router_route (struct ospf *ospf, struct route_table *rtrs, - struct prefix_ipv4 *p, +ospf_ia_router_route (struct route_table *rt, struct prefix_ipv4 *p, struct ospf_route *new_or, struct ospf_route *abr_or) { - struct ospf_route *or = NULL; struct route_node *rn; + struct ospf_route *or = NULL; int ret; if (IS_DEBUG_OSPF_EVENT) zlog_info ("ospf_ia_router_route(): considering %s/%d", inet_ntoa (p->prefix), p->prefixlen); /* Find a route to the same dest */ - rn = route_node_get (rtrs, (struct prefix *) p); + rn = route_node_get (rt,(struct prefix *) p); if (rn->info == NULL) /* This is a new route */ @@ -148,11 +146,11 @@ ospf_ia_router_route (struct ospf *ospf, struct route_table *rtrs, else { struct ospf_area *or_area; - or_area = ospf_area_lookup_by_area_id (ospf, new_or->u.std.area_id); + or_area = ospf_area_lookup_by_area_id (new_or->u.std.area_id); assert (or_area); /* This is an additional route */ route_unlock_node (rn); - or = ospf_find_asbr_route_through_area (rtrs, p, or_area); + or = ospf_find_asbr_route_through_area (rt, p, or_area); } if (or) @@ -161,7 +159,7 @@ ospf_ia_router_route (struct ospf *ospf, struct route_table *rtrs, zlog_info ("ospf_ia_router_route(): " "a route to the same ABR through the same area exists"); /* New route is better */ - if ((ret = ospf_route_cmp (ospf, new_or, or)) < 0) + if ((ret = ospf_route_cmp (new_or, or)) < 0) { listnode_delete (rn->info, or); ospf_route_free (or); @@ -196,21 +194,28 @@ ospf_ia_router_route (struct ospf *ospf, struct route_table *rtrs, } +struct ia_args +{ + struct route_table *rt; + struct route_table *rtrs; + struct ospf_area *area; +}; + int -process_summary_lsa (struct ospf_area *area, struct route_table *rt, - struct route_table *rtrs, struct ospf_lsa *lsa) +process_summary_lsa (struct ospf_lsa *l, void *v, int i) { - struct ospf *ospf = area->ospf; struct ospf_area_range *range; struct ospf_route *abr_or, *new_or; struct summary_lsa *sl; struct prefix_ipv4 p, abr; u_int32_t metric; + struct ia_args *args; - if (lsa == NULL) + if (l == NULL) return 0; - sl = (struct summary_lsa *) lsa->data; + args = (struct ia_args *) v; + sl = (struct summary_lsa *) l->data; if (IS_DEBUG_OSPF_EVENT) zlog_info ("process_summary_lsa(): LS ID: %s", inet_ntoa (sl->header.id)); @@ -220,10 +225,10 @@ process_summary_lsa (struct ospf_area *area, struct route_table *rt, if (metric == OSPF_LS_INFINITY) return 0; - if (IS_LSA_MAXAGE (lsa)) + if (IS_LSA_MAXAGE (l)) return 0; - if (ospf_lsa_is_self_originated (area->ospf, lsa)) + if (ospf_lsa_is_self_originated (l)) return 0; p.family = AF_INET; @@ -237,12 +242,12 @@ process_summary_lsa (struct ospf_area *area, struct route_table *rt, apply_mask_ipv4 (&p); if (sl->header.type == OSPF_SUMMARY_LSA && - (range = ospf_area_range_match_any (ospf, &p)) && + (range = ospf_area_range_match_any (ospf_top, &p)) && ospf_area_range_active (range)) return 0; - if (ospf->abr_type != OSPF_ABR_STAND && - area->external_routing != OSPF_AREA_DEFAULT && + if (ospf_top->abr_type != OSPF_ABR_STAND && + args->area->external_routing != OSPF_AREA_DEFAULT && p.prefix.s_addr == OSPF_DEFAULT_DESTINATION && p.prefixlen == 0) return 0; /* Ignore summary default from a stub area */ @@ -252,7 +257,7 @@ process_summary_lsa (struct ospf_area *area, struct route_table *rt, abr.prefixlen = IPV4_MAX_BITLEN; apply_mask_ipv4 (&abr); - abr_or = ospf_find_abr_route (rtrs, &abr, area); + abr_or = ospf_find_abr_route (args->rtrs, &abr, args->area); if (abr_or == NULL) return 0; @@ -264,35 +269,32 @@ process_summary_lsa (struct ospf_area *area, struct route_table *rt, new_or->u.std.options = sl->header.options; new_or->u.std.origin = (struct lsa_header *) sl; new_or->cost = abr_or->cost + metric; - new_or->u.std.area_id = area->area_id; + new_or->u.std.area_id = args->area->area_id; #ifdef HAVE_NSSA - new_or->u.std.external_routing = area->external_routing; + new_or->u.std.external_routing = args->area->external_routing; #endif /* HAVE_NSSA */ new_or->path_type = OSPF_PATH_INTER_AREA; if (sl->header.type == OSPF_SUMMARY_LSA) - ospf_ia_network_route (ospf, rt, &p, new_or, abr_or); + ospf_ia_network_route (args->rt, &p, new_or, abr_or); else { new_or->type = OSPF_DESTINATION_ROUTER; new_or->u.std.flags = ROUTER_LSA_EXTERNAL; - ospf_ia_router_route (ospf, rtrs, &p, new_or, abr_or); + ospf_ia_router_route (args->rtrs, &p, new_or, abr_or); } return 0; } void -ospf_examine_summaries (struct ospf_area *area, +ospf_examine_summaries (struct ospf_area * area, struct route_table *lsdb_rt, struct route_table *rt, struct route_table *rtrs) { - struct ospf_lsa *lsa; - struct route_node *rn; - - LSDB_LOOP (lsdb_rt, rn, lsa) - process_summary_lsa (area, rt, rtrs, lsa); + struct ia_args args = {rt, rtrs, area}; + foreach_lsa (lsdb_rt, &args, 0, process_summary_lsa); } int @@ -303,8 +305,7 @@ ospf_area_is_transit (struct ospf_area *area) } void -ospf_update_network_route (struct ospf *ospf, - struct route_table *rt, +ospf_update_network_route (struct route_table *rt, struct route_table *rtrs, struct summary_lsa *lsa, struct prefix_ipv4 *p, @@ -335,7 +336,7 @@ ospf_update_network_route (struct ospf *ospf, if (! rn) { - if (ospf->abr_type != OSPF_ABR_SHORTCUT) + if (ospf_top->abr_type != OSPF_ABR_SHORTCUT) return; /* Standard ABR can update only already installed backbone paths */ if (IS_DEBUG_OSPF_EVENT) @@ -374,7 +375,7 @@ ospf_update_network_route (struct ospf *ospf, return; } - if (ospf->abr_type == OSPF_ABR_SHORTCUT) + if (ospf_top->abr_type == OSPF_ABR_SHORTCUT) { if (or->path_type == OSPF_PATH_INTRA_AREA && !OSPF_IS_AREA_ID_BACKBONE (or->u.std.area_id)) @@ -419,7 +420,7 @@ ospf_update_network_route (struct ospf *ospf, ospf_route_subst_nexthops (or, abr_or->path); or->cost = cost; - if ((ospf->abr_type == OSPF_ABR_SHORTCUT) && + if ((ospf_top->abr_type == OSPF_ABR_SHORTCUT) && !OSPF_IS_AREA_ID_BACKBONE (or->u.std.area_id)) { or->path_type = OSPF_PATH_INTER_AREA; @@ -436,8 +437,7 @@ ospf_update_network_route (struct ospf *ospf, } void -ospf_update_router_route (struct ospf *ospf, - struct route_table *rtrs, +ospf_update_router_route (struct route_table *rtrs, struct summary_lsa *lsa, struct prefix_ipv4 *p, struct ospf_area *area) @@ -465,17 +465,17 @@ ospf_update_router_route (struct ospf *ospf, /* First try to find a backbone path, because standard ABR can update only BB-associated paths */ - if ((ospf->backbone == NULL) && - (ospf->abr_type != OSPF_ABR_SHORTCUT)) + if ((ospf_top->backbone == NULL) && + (ospf_top->abr_type != OSPF_ABR_SHORTCUT)) /* no BB area, not Shortcut ABR, exiting */ return; - or = ospf_find_asbr_route_through_area (rtrs, p, ospf->backbone); + or = ospf_find_asbr_route_through_area (rtrs, p, ospf_top->backbone); if (or == NULL) { - if (ospf->abr_type != OSPF_ABR_SHORTCUT) + if (ospf_top->abr_type != OSPF_ABR_SHORTCUT) /* route to ASBR through the BB not found the router is not Shortcut ABR, exiting */ @@ -500,7 +500,7 @@ ospf_update_router_route (struct ospf *ospf, #endif /* HAVE_NSSA */ new_or->path_type = OSPF_PATH_INTER_AREA; new_or->u.std.flags = ROUTER_LSA_EXTERNAL; - ospf_ia_router_route (ospf, rtrs, p, new_or, abr_or); + ospf_ia_router_route (rtrs, p, new_or, abr_or); return; } @@ -537,22 +537,22 @@ ospf_update_router_route (struct ospf *ospf, } int -process_transit_summary_lsa (struct ospf_area *area, struct route_table *rt, - struct route_table *rtrs, struct ospf_lsa *lsa) +process_transit_summary_lsa (struct ospf_lsa *l, void *v, int i) { - struct ospf *ospf = area->ospf; struct summary_lsa *sl; struct prefix_ipv4 p; u_int32_t metric; + struct ia_args *args; - if (lsa == NULL) + if (l == NULL) return 0; - sl = (struct summary_lsa *) lsa->data; + args = (struct ia_args *) v; + sl = (struct summary_lsa *) l->data; if (IS_DEBUG_OSPF_EVENT) zlog_info ("process_transit_summaries(): LS ID: %s", - inet_ntoa (lsa->data->id)); + inet_ntoa (l->data->id)); metric = GET_METRIC (sl->metric); if (metric == OSPF_LS_INFINITY) @@ -562,14 +562,14 @@ process_transit_summary_lsa (struct ospf_area *area, struct route_table *rt, return 0; } - if (IS_LSA_MAXAGE (lsa)) + if (IS_LSA_MAXAGE (l)) { if (IS_DEBUG_OSPF_EVENT) zlog_info ("process_transit_summaries(): This LSA is too old"); return 0; } - if (ospf_lsa_is_self_originated (area->ospf, lsa)) + if (ospf_lsa_is_self_originated (l)) { if (IS_DEBUG_OSPF_EVENT) zlog_info ("process_transit_summaries(): This LSA is mine, skip"); @@ -587,29 +587,28 @@ process_transit_summary_lsa (struct ospf_area *area, struct route_table *rt, apply_mask_ipv4 (&p); if (sl->header.type == OSPF_SUMMARY_LSA) - ospf_update_network_route (ospf, rt, rtrs, sl, &p, area); + ospf_update_network_route (args->rt, args->rtrs, sl, &p, args->area); else - ospf_update_router_route (ospf, rtrs, sl, &p, area); + ospf_update_router_route (args->rtrs, sl, &p, args->area); return 0; } void ospf_examine_transit_summaries (struct ospf_area *area, + /* struct ospf_lsdb *lsdb, */ struct route_table *lsdb_rt, struct route_table *rt, struct route_table *rtrs) { - struct ospf_lsa *lsa; - struct route_node *rn; + struct ia_args args = {rt, rtrs, area}; - LSDB_LOOP (lsdb_rt, rn, lsa) - process_transit_summary_lsa (area, rt, rtrs, lsa); + /* ospf_lsdb_iterator (lsdb, &args, 0, process_transit_summary_lsa); */ + foreach_lsa (lsdb_rt, &args, 0, process_transit_summary_lsa); } void -ospf_ia_routing (struct ospf *ospf, - struct route_table *rt, +ospf_ia_routing (struct route_table *rt, struct route_table *rtrs) { struct ospf_area * area; @@ -617,18 +616,18 @@ ospf_ia_routing (struct ospf *ospf, if (IS_DEBUG_OSPF_EVENT) zlog_info ("ospf_ia_routing():start"); - if (IS_OSPF_ABR (ospf)) + if (OSPF_IS_ABR) { listnode node; struct ospf_area *area; - switch (ospf->abr_type) + switch (ospf_top->abr_type) { case OSPF_ABR_STAND: if (IS_DEBUG_OSPF_EVENT) zlog_info ("ospf_ia_routing():Standard ABR"); - if ((area = ospf->backbone)) + if ((area = ospf_top->backbone)) { listnode node; @@ -640,9 +639,9 @@ ospf_ia_routing (struct ospf *ospf, OSPF_EXAMINE_SUMMARIES_ALL (area, rt, rtrs); - for (node = listhead (ospf->areas); node; nextnode (node)) + for (node = listhead (ospf_top->areas); node; nextnode (node)) if ((area = getdata (node)) != NULL) - if (area != ospf->backbone) + if (area != ospf_top->backbone) if (ospf_area_is_transit (area)) OSPF_EXAMINE_TRANSIT_SUMMARIES_ALL (area, rt, rtrs); } @@ -654,10 +653,10 @@ ospf_ia_routing (struct ospf *ospf, case OSPF_ABR_CISCO: if (IS_DEBUG_OSPF_EVENT) zlog_info ("ospf_ia_routing():Alternative Cisco/IBM ABR"); - area = ospf->backbone; /* Find the BB */ + area = ospf_top->backbone; /* Find the BB */ /* If we have an active BB connection */ - if (area && ospf_act_bb_connection (ospf)) + if (area && ospf_act_bb_connection ()) { if (IS_DEBUG_OSPF_EVENT) { @@ -667,9 +666,9 @@ ospf_ia_routing (struct ospf *ospf, OSPF_EXAMINE_SUMMARIES_ALL (area, rt, rtrs); - for (node = listhead (ospf->areas); node; nextnode (node)) + for (node = listhead (ospf_top->areas); node; nextnode (node)) if ((area = getdata (node)) != NULL) - if (area != ospf->backbone) + if (area != ospf_top->backbone) if (ospf_area_is_transit (area)) OSPF_EXAMINE_TRANSIT_SUMMARIES_ALL (area, rt, rtrs); } @@ -678,7 +677,7 @@ ospf_ia_routing (struct ospf *ospf, if (IS_DEBUG_OSPF_EVENT) zlog_info ("ospf_ia_routing(): " "Active BB connection not found"); - for (node = listhead (ospf->areas); node; nextnode (node)) + for (node = listhead (ospf_top->areas); node; nextnode (node)) if ((area = getdata (node)) != NULL) OSPF_EXAMINE_SUMMARIES_ALL (area, rt, rtrs); } @@ -686,10 +685,10 @@ ospf_ia_routing (struct ospf *ospf, case OSPF_ABR_SHORTCUT: if (IS_DEBUG_OSPF_EVENT) zlog_info ("ospf_ia_routing():Alternative Shortcut"); - area = ospf->backbone; /* Find the BB */ + area = ospf_top->backbone; /* Find the BB */ /* If we have an active BB connection */ - if (area && ospf_act_bb_connection (ospf)) + if (area && ospf_act_bb_connection ()) { if (IS_DEBUG_OSPF_EVENT) { @@ -699,12 +698,12 @@ ospf_ia_routing (struct ospf *ospf, OSPF_EXAMINE_SUMMARIES_ALL (area, rt, rtrs); } - for (node = listhead (ospf->areas); node; nextnode (node)) + for (node = listhead (ospf_top->areas); node; nextnode (node)) if ((area = getdata (node)) != NULL) - if (area != ospf->backbone) + if (area != ospf_top->backbone) if (ospf_area_is_transit (area) || ((area->shortcut_configured != OSPF_SHORTCUT_DISABLE) && - ((ospf->backbone == NULL) || + ((ospf_top->backbone == NULL) || ((area->shortcut_configured == OSPF_SHORTCUT_ENABLE) && area->shortcut_capability)))) OSPF_EXAMINE_TRANSIT_SUMMARIES_ALL (area, rt, rtrs); @@ -720,7 +719,7 @@ ospf_ia_routing (struct ospf *ospf, if (IS_DEBUG_OSPF_EVENT) zlog_info ("ospf_ia_routing():not ABR, considering all areas"); - for (node = listhead (ospf->areas); node; nextnode (node)) + for (node = listhead (ospf_top->areas); node; nextnode (node)) if ((area = getdata (node)) != NULL) OSPF_EXAMINE_SUMMARIES_ALL (area, rt, rtrs); } diff --git a/ospfd/ospf_ia.h b/ospfd/ospf_ia.h index 4eb3c9d8..afb2d4d5 100644 --- a/ospfd/ospf_ia.h +++ b/ospfd/ospf_ia.h @@ -36,8 +36,7 @@ ospf_examine_transit_summaries ((A), ASBR_SUMMARY_LSDB ((A)), (N), (R)); \ } -void ospf_ia_routing (struct ospf *, struct route_table *, - struct route_table *); +void ospf_ia_routing (struct route_table *, struct route_table *); int ospf_area_is_transit (struct ospf_area *); #endif /* _ZEBRA_OSPF_IA_H */ diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c index a1b10c74..08bc7fbe 100644 --- a/ospfd/ospf_interface.c +++ b/ospfd/ospf_interface.c @@ -489,9 +489,9 @@ ospf_new_if_params () UNSET_IF_PARAM (oip, auth_simple); UNSET_IF_PARAM (oip, auth_crypt); UNSET_IF_PARAM (oip, auth_type); - - oip->auth_crypt = list_new (); + oip->auth_crypt = list_new (); + return oip; } @@ -625,9 +625,6 @@ ospf_if_new_hook (struct interface *ifp) SET_IF_PARAM (IF_DEF_PARAMS (ifp), auth_simple); memset (IF_DEF_PARAMS (ifp)->auth_simple, 0, OSPF_AUTH_SIMPLE_SIZE); - SET_IF_PARAM (IF_DEF_PARAMS (ifp), auth_crypt); - IF_DEF_PARAMS (ifp)->auth_crypt = list_new (); - SET_IF_PARAM (IF_DEF_PARAMS (ifp), auth_type); IF_DEF_PARAMS (ifp)->auth_type = OSPF_AUTH_NOTSET; @@ -646,6 +643,7 @@ ospf_if_delete_hook (struct interface *ifp) #endif /* HAVE_OPAQUE_LSA */ route_table_finish (IF_OIFS (ifp)); route_table_finish (IF_OIFS_PARAMS (ifp)); + ospf_del_if_params ((struct ospf_if_params *) IF_DEF_PARAMS (ifp)); XFREE (MTYPE_OSPF_IF_INFO, ifp->info); ifp->info = NULL; diff --git a/ospfd/ospf_interface.h b/ospfd/ospf_interface.h index 1dc0ce74..6dc01aea 100644 --- a/ospfd/ospf_interface.h +++ b/ospfd/ospf_interface.h @@ -190,13 +190,12 @@ struct ospf_interface u_int32_t discarded; /* discarded input count by error. */ u_int32_t state_change; /* Number of status change. */ - u_int32_t full_nbrs; + u_int full_nbrs; }; /* Prototypes. */ char *ospf_if_name (struct ospf_interface *); -struct ospf_interface *ospf_if_new (struct ospf *, struct interface *, - struct prefix *); +struct ospf_interface *ospf_if_new (); void ospf_if_cleanup (struct ospf_interface *); void ospf_if_free (struct ospf_interface *); int ospf_if_up (struct ospf_interface *); @@ -204,17 +203,13 @@ int ospf_if_down (struct ospf_interface *); int ospf_if_is_up (struct ospf_interface *); struct ospf_interface *ospf_if_lookup_by_name (char *); -struct ospf_interface *ospf_if_lookup_by_local_addr (struct ospf *, - struct interface *, - struct in_addr); -struct ospf_interface *ospf_if_lookup_by_prefix (struct ospf *, - struct prefix_ipv4 *); -struct ospf_interface *ospf_if_addr_local (struct in_addr); -struct ospf_interface *ospf_if_lookup_recv_if (struct ospf *, struct in_addr); -struct ospf_interface *ospf_if_is_configured (struct ospf *, struct in_addr *); - -struct ospf_if_params *ospf_lookup_if_params (struct interface *, - struct in_addr); +struct ospf_interface *ospf_if_lookup_by_local_addr (struct interface *, struct in_addr); +struct ospf_interface *ospf_if_lookup_by_prefix (struct prefix_ipv4 *); +struct ospf_interface *ospf_if_addr_local (struct in_addr src); +struct ospf_interface *ospf_if_lookup_recv_interface (struct in_addr src); +struct ospf_interface *ospf_if_is_configured (struct in_addr *); + +struct ospf_if_params *ospf_lookup_if_params (struct interface *, struct in_addr); struct ospf_if_params *ospf_get_if_params (struct interface *, struct in_addr); void ospf_del_if_params (struct ospf_if_params *); void ospf_free_if_params (struct interface *, struct in_addr); @@ -229,21 +224,22 @@ int ospf_if_is_enable (struct ospf_interface *); int ospf_if_get_output_cost (struct ospf_interface *); void ospf_if_recalculate_output_cost (struct interface *); -struct ospf_interface *ospf_vl_new (struct ospf *, struct ospf_vl_data *); +struct ospf_interface *ospf_vl_new (struct ospf_vl_data *); struct ospf_vl_data *ospf_vl_data_new (struct ospf_area *, struct in_addr); struct ospf_vl_data *ospf_vl_lookup (struct ospf_area *, struct in_addr); void ospf_vl_data_free (struct ospf_vl_data *); -void ospf_vl_add (struct ospf *, struct ospf_vl_data *); -void ospf_vl_delete (struct ospf *, struct ospf_vl_data *); +void ospf_vl_add (struct ospf_vl_data *); +void ospf_vl_delete (struct ospf_vl_data *); void ospf_vl_up_check (struct ospf_area *, struct in_addr, struct vertex *); -void ospf_vl_unapprove (struct ospf *); -void ospf_vl_shut_unapproved (struct ospf *); +void ospf_vl_unapprove (); +void ospf_vl_shut_unapproved (); int ospf_full_virtual_nbrs (struct ospf_area *); int ospf_vls_in_area (struct ospf_area *); struct crypt_key *ospf_crypt_key_lookup (list, u_char); struct crypt_key *ospf_crypt_key_new (); void ospf_crypt_key_add (list, struct crypt_key *); -int ospf_crypt_key_delete (list, u_char); +int ospf_crypt_key_delete (list, u_char key_id); + #endif /* _ZEBRA_OSPF_INTERFACE_H */ diff --git a/ospfd/ospf_ism.c b/ospfd/ospf_ism.c new file mode 100644 index 00000000..5f4d5461 --- /dev/null +++ b/ospfd/ospf_ism.c @@ -0,0 +1,658 @@ +/* + * OSPF version 2 Interface State Machine + * From RFC2328 [OSPF Version 2] + * Copyright (C) 1999, 2000 Toshiaki Takada + * + * 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. + */ + +#include <zebra.h> + +#include "thread.h" +#include "linklist.h" +#include "prefix.h" +#include "if.h" +#include "table.h" +#include "log.h" + +#include "ospfd/ospfd.h" +#include "ospfd/ospf_interface.h" +#include "ospfd/ospf_ism.h" +#include "ospfd/ospf_asbr.h" +#include "ospfd/ospf_lsa.h" +#include "ospfd/ospf_lsdb.h" +#include "ospfd/ospf_neighbor.h" +#include "ospfd/ospf_nsm.h" +#include "ospfd/ospf_network.h" +#include "ospfd/ospf_dump.h" +#include "ospfd/ospf_packet.h" +#include "ospfd/ospf_flood.h" +#include "ospfd/ospf_abr.h" + +/* elect DR and BDR. Refer to RFC2319 section 9.4 */ +struct ospf_neighbor * +ospf_dr_election_sub (list routers) +{ + listnode node; + struct ospf_neighbor *nbr, *max = NULL; + + /* Choose highest router priority. + In case of tie, choose highest Router ID. */ + for (node = listhead (routers); node; nextnode (node)) + { + nbr = getdata (node); + + if (max == NULL) + max = nbr; + else + { + if (max->priority < nbr->priority) + max = nbr; + else if (max->priority == nbr->priority) + if (IPV4_ADDR_CMP (&max->router_id, &nbr->router_id) < 0) + max = nbr; + } + } + + return max; +} + +struct ospf_neighbor * +ospf_elect_dr (struct ospf_interface *oi, list el_list) +{ + list dr_list; + listnode node; + struct ospf_neighbor *nbr, *dr = NULL, *bdr = NULL; + + dr_list = list_new (); + + /* Add neighbors to the list. */ + for (node = listhead (el_list); node; nextnode (node)) + { + nbr = getdata (node); + + /* neighbor declared to be DR. */ + if (NBR_IS_DR (nbr)) + listnode_add (dr_list, nbr); + + /* Preserve neighbor BDR. */ + if (IPV4_ADDR_SAME (&BDR (oi), &nbr->address.u.prefix4)) + bdr = nbr; + } + + /* Elect Designated Router. */ + if (listcount (dr_list) > 0) + dr = ospf_dr_election_sub (dr_list); + else + dr = bdr; + + /* Set DR to interface. */ + if (dr) + { + DR (oi) = dr->address.u.prefix4; + dr->d_router = dr->address.u.prefix4; + } + else + DR (oi).s_addr = 0; + + list_delete (dr_list); + + return dr; +} + +struct ospf_neighbor * +ospf_elect_bdr (struct ospf_interface *oi, list el_list) +{ + list bdr_list, no_dr_list; + listnode node; + struct ospf_neighbor *nbr, *bdr = NULL; + + bdr_list = list_new (); + no_dr_list = list_new (); + + /* Add neighbors to the list. */ + for (node = listhead (el_list); node; nextnode (node)) + { + nbr = getdata (node); + + /* neighbor declared to be DR. */ + if (NBR_IS_DR (nbr)) + continue; + + /* neighbor declared to be BDR. */ + if (NBR_IS_BDR (nbr)) + listnode_add (bdr_list, nbr); + + listnode_add (no_dr_list, nbr); + } + + /* Elect Backup Designated Router. */ + if (listcount (bdr_list) > 0) + bdr = ospf_dr_election_sub (bdr_list); + else + bdr = ospf_dr_election_sub (no_dr_list); + + /* Set BDR to interface. */ + if (bdr) + { + BDR (oi) = bdr->address.u.prefix4; + bdr->bd_router = bdr->address.u.prefix4; + } + else + BDR (oi).s_addr = 0; + + list_delete (bdr_list); + list_delete (no_dr_list); + + return bdr; +} + +int +ospf_ism_state (struct ospf_interface *oi) +{ + if (IPV4_ADDR_SAME (&DR (oi), &oi->address->u.prefix4)) + return ISM_DR; + else if (IPV4_ADDR_SAME (&BDR (oi), &oi->address->u.prefix4)) + return ISM_Backup; + else + return ISM_DROther; +} + +void +ospf_dr_eligible_routers (struct route_table *nbrs, list el_list) +{ + struct route_node *rn; + struct ospf_neighbor *nbr; + + for (rn = route_top (nbrs); rn; rn = route_next (rn)) + if ((nbr = rn->info) != NULL) + /* Ignore 0.0.0.0 node*/ + if (nbr->router_id.s_addr != 0) + /* Is neighbor eligible? */ + if (nbr->priority != 0) + /* Is neighbor upper 2-Way? */ + if (nbr->state >= NSM_TwoWay) + listnode_add (el_list, nbr); +} + +/* Generate AdjOK? NSM event. */ +void +ospf_dr_change (struct ospf *ospf, struct route_table *nbrs) +{ + struct route_node *rn; + struct ospf_neighbor *nbr; + + for (rn = route_top (nbrs); rn; rn = route_next (rn)) + if ((nbr = rn->info) != NULL) + /* Ignore 0.0.0.0 node*/ + if (nbr->router_id.s_addr != 0) + /* Is neighbor upper 2-Way? */ + if (nbr->state >= NSM_TwoWay) + /* Ignore myself. */ + if (!IPV4_ADDR_SAME (&nbr->router_id, &ospf->router_id)) + OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_AdjOK); +} + +int +ospf_dr_election (struct ospf_interface *oi) +{ + struct in_addr old_dr, old_bdr; + int old_state, new_state; + list el_list; + struct ospf_neighbor *dr, *bdr; + + /* backup current values. */ + old_dr = DR (oi); + old_bdr = BDR (oi); + old_state = oi->state; + + el_list = list_new (); + + /* List eligible routers. */ + ospf_dr_eligible_routers (oi->nbrs, el_list); + + /* First election of DR and BDR. */ + bdr = ospf_elect_bdr (oi, el_list); + dr = ospf_elect_dr (oi, el_list); + + new_state = ospf_ism_state (oi); + + zlog_info ("DR-Election[1st]: Backup %s", inet_ntoa (BDR (oi))); + zlog_info ("DR-Election[1st]: DR %s", inet_ntoa (DR (oi))); + + if (new_state != old_state && + !(new_state == ISM_DROther && old_state < ISM_DROther)) + { + ospf_elect_bdr (oi, el_list); + ospf_elect_dr (oi, el_list); + + new_state = ospf_ism_state (oi); + + zlog_info ("DR-Election[2nd]: Backup %s", inet_ntoa (BDR (oi))); + zlog_info ("DR-Election[2nd]: DR %s", inet_ntoa (DR (oi))); + } + + list_delete (el_list); + + /* if DR or BDR changes, cause AdjOK? neighbor event. */ + if (!IPV4_ADDR_SAME (&old_dr, &DR (oi)) || + !IPV4_ADDR_SAME (&old_bdr, &BDR (oi))) + ospf_dr_change (oi->ospf, oi->nbrs); + + if (oi->type == OSPF_IFTYPE_BROADCAST || oi->type == OSPF_IFTYPE_POINTOPOINT) + { + /* Multicast group change. */ + if ((old_state != ISM_DR && old_state != ISM_Backup) && + (new_state == ISM_DR || new_state == ISM_Backup)) + ospf_if_add_alldrouters (oi->ospf, oi->address, oi->ifp->ifindex); + else if ((old_state == ISM_DR || old_state == ISM_Backup) && + (new_state != ISM_DR && new_state != ISM_Backup)) + ospf_if_drop_alldrouters (oi->ospf, oi->address, oi->ifp->ifindex); + } + + return new_state; +} + + +int +ospf_hello_timer (struct thread *thread) +{ + struct ospf_interface *oi; + + oi = THREAD_ARG (thread); + oi->t_hello = NULL; + + if (IS_DEBUG_OSPF (ism, ISM_TIMERS)) + zlog (NULL, LOG_DEBUG, "ISM[%s]: Timer (Hello timer expire)", + IF_NAME (oi)); + + /* Sending hello packet. */ + ospf_hello_send (oi); + + /* Hello timer set. */ + OSPF_ISM_TIMER_ON (oi->t_hello, ospf_hello_timer, + OSPF_IF_PARAM (oi, v_hello)); + + return 0; +} + +int +ospf_wait_timer (struct thread *thread) +{ + struct ospf_interface *oi; + + oi = THREAD_ARG (thread); + oi->t_wait = NULL; + + if (IS_DEBUG_OSPF (ism, ISM_TIMERS)) + zlog (NULL, LOG_DEBUG, "ISM[%s]: Timer (Wait timer expire)", + IF_NAME (oi)); + + OSPF_ISM_EVENT_SCHEDULE (oi, ISM_WaitTimer); + + return 0; +} + +/* Hook function called after ospf ISM event is occured. And vty's + network command invoke this function after making interface + structure. */ +void +ism_timer_set (struct ospf_interface *oi) +{ + switch (oi->state) + { + case ISM_Down: + /* First entry point of ospf interface state machine. In this state + interface parameters must be set to initial values, and timers are + reset also. */ + OSPF_ISM_TIMER_OFF (oi->t_hello); + OSPF_ISM_TIMER_OFF (oi->t_wait); + OSPF_ISM_TIMER_OFF (oi->t_ls_ack); + break; + case ISM_Loopback: + /* In this state, the interface may be looped back and will be + unavailable for regular data traffic. */ + OSPF_ISM_TIMER_OFF (oi->t_hello); + OSPF_ISM_TIMER_OFF (oi->t_wait); + OSPF_ISM_TIMER_OFF (oi->t_ls_ack); + break; + case ISM_Waiting: + /* The router is trying to determine the identity of DRouter and + BDRouter. The router begin to receive and send Hello Packets. */ + /* send first hello immediately */ + OSPF_ISM_TIMER_ON (oi->t_hello, ospf_hello_timer, 1); + OSPF_ISM_TIMER_ON (oi->t_wait, ospf_wait_timer, + OSPF_IF_PARAM (oi, v_wait)); + OSPF_ISM_TIMER_OFF (oi->t_ls_ack); + break; + case ISM_PointToPoint: + /* The interface connects to a physical Point-to-point network or + virtual link. The router attempts to form an adjacency with + neighboring router. Hello packets are also sent. */ + /* send first hello immediately */ + OSPF_ISM_TIMER_ON (oi->t_hello, ospf_hello_timer, 1); + + OSPF_ISM_TIMER_OFF (oi->t_wait); + OSPF_ISM_TIMER_ON (oi->t_ls_ack, ospf_ls_ack_timer, oi->v_ls_ack); + break; + case ISM_DROther: + /* The network type of the interface is broadcast or NBMA network, + and the router itself is neither Designated Router nor + Backup Designated Router. */ + OSPF_ISM_TIMER_ON (oi->t_hello, ospf_hello_timer, + OSPF_IF_PARAM (oi, v_hello)); + OSPF_ISM_TIMER_OFF (oi->t_wait); + OSPF_ISM_TIMER_ON (oi->t_ls_ack, ospf_ls_ack_timer, oi->v_ls_ack); + break; + case ISM_Backup: + /* The network type of the interface is broadcast os NBMA network, + and the router is Backup Designated Router. */ + OSPF_ISM_TIMER_ON (oi->t_hello, ospf_hello_timer, + OSPF_IF_PARAM (oi, v_hello)); + OSPF_ISM_TIMER_OFF (oi->t_wait); + OSPF_ISM_TIMER_ON (oi->t_ls_ack, ospf_ls_ack_timer, oi->v_ls_ack); + break; + case ISM_DR: + /* The network type of the interface is broadcast or NBMA network, + and the router is Designated Router. */ + OSPF_ISM_TIMER_ON (oi->t_hello, ospf_hello_timer, + OSPF_IF_PARAM (oi, v_hello)); + OSPF_ISM_TIMER_OFF (oi->t_wait); + OSPF_ISM_TIMER_ON (oi->t_ls_ack, ospf_ls_ack_timer, oi->v_ls_ack); + break; + } +} + +int +ism_stop (struct ospf_interface *oi) +{ + return 0; +} + +int +ism_interface_up (struct ospf_interface *oi) +{ + int next_state = 0; + + /* if network type is point-to-point, Point-to-MultiPoint or virtual link, + the state transitions to Point-to-Point. */ + if (oi->type == OSPF_IFTYPE_POINTOPOINT || + oi->type == OSPF_IFTYPE_POINTOMULTIPOINT || + oi->type == OSPF_IFTYPE_VIRTUALLINK) + next_state = ISM_PointToPoint; + /* Else if the router is not eligible to DR, the state transitions to + DROther. */ + else if (PRIORITY (oi) == 0) /* router is eligible? */ + next_state = ISM_DROther; + else + /* Otherwise, the state transitions to Waiting. */ + next_state = ISM_Waiting; + + if (oi->type == OSPF_IFTYPE_NBMA) + ospf_nbr_nbma_if_update (oi->ospf, oi); + + /* ospf_ism_event (t); */ + return next_state; +} + +int +ism_loop_ind (struct ospf_interface *oi) +{ + int ret = 0; + + /* call ism_interface_down. */ + /* ret = ism_interface_down (oi); */ + + return ret; +} + +/* Interface down event handler. */ +int +ism_interface_down (struct ospf_interface *oi) +{ + ospf_if_cleanup (oi); + return 0; +} + + +int +ism_backup_seen (struct ospf_interface *oi) +{ + return ospf_dr_election (oi); +} + +int +ism_wait_timer (struct ospf_interface *oi) +{ + return ospf_dr_election (oi); +} + +int +ism_neighbor_change (struct ospf_interface *oi) +{ + return ospf_dr_election (oi); +} + +int +ism_ignore (struct ospf_interface *oi) +{ + if (IS_DEBUG_OSPF (ism, ISM_EVENTS)) + zlog (NULL, LOG_INFO, "ISM[%s]: ism_ignore called", IF_NAME (oi)); + + return 0; +} + +/* Interface State Machine */ +struct { + int (*func) (); + int next_state; +} ISM [OSPF_ISM_STATE_MAX][OSPF_ISM_EVENT_MAX] = +{ + { + /* DependUpon: dummy state. */ + { ism_ignore, ISM_DependUpon }, /* NoEvent */ + { ism_ignore, ISM_DependUpon }, /* InterfaceUp */ + { ism_ignore, ISM_DependUpon }, /* WaitTimer */ + { ism_ignore, ISM_DependUpon }, /* BackupSeen */ + { ism_ignore, ISM_DependUpon }, /* NeighborChange */ + { ism_ignore, ISM_DependUpon }, /* LoopInd */ + { ism_ignore, ISM_DependUpon }, /* UnloopInd */ + { ism_ignore, ISM_DependUpon }, /* InterfaceDown */ + }, + { + /* Down:*/ + { ism_ignore, ISM_DependUpon }, /* NoEvent */ + { ism_interface_up, ISM_DependUpon }, /* InterfaceUp */ + { ism_ignore, ISM_Down }, /* WaitTimer */ + { ism_ignore, ISM_Down }, /* BackupSeen */ + { ism_ignore, ISM_Down }, /* NeighborChange */ + { ism_loop_ind, ISM_Loopback }, /* LoopInd */ + { ism_ignore, ISM_Down }, /* UnloopInd */ + { ism_interface_down, ISM_Down }, /* InterfaceDown */ + }, + { + /* Loopback: */ + { ism_ignore, ISM_DependUpon }, /* NoEvent */ + { ism_ignore, ISM_Loopback }, /* InterfaceUp */ + { ism_ignore, ISM_Loopback }, /* WaitTimer */ + { ism_ignore, ISM_Loopback }, /* BackupSeen */ + { ism_ignore, ISM_Loopback }, /* NeighborChange */ + { ism_ignore, ISM_Loopback }, /* LoopInd */ + { ism_ignore, ISM_Down }, /* UnloopInd */ + { ism_interface_down, ISM_Down }, /* InterfaceDown */ + }, + { + /* Waiting: */ + { ism_ignore, ISM_DependUpon }, /* NoEvent */ + { ism_ignore, ISM_Waiting }, /* InterfaceUp */ + { ism_wait_timer, ISM_DependUpon }, /* WaitTimer */ + { ism_backup_seen, ISM_DependUpon }, /* BackupSeen */ + { ism_ignore, ISM_Waiting }, /* NeighborChange */ + { ism_loop_ind, ISM_Loopback }, /* LoopInd */ + { ism_ignore, ISM_Waiting }, /* UnloopInd */ + { ism_interface_down, ISM_Down }, /* InterfaceDown */ + }, + { + /* Point-to-Point: */ + { ism_ignore, ISM_DependUpon }, /* NoEvent */ + { ism_ignore, ISM_PointToPoint }, /* InterfaceUp */ + { ism_ignore, ISM_PointToPoint }, /* WaitTimer */ + { ism_ignore, ISM_PointToPoint }, /* BackupSeen */ + { ism_ignore, ISM_PointToPoint }, /* NeighborChange */ + { ism_loop_ind, ISM_Loopback }, /* LoopInd */ + { ism_ignore, ISM_PointToPoint }, /* UnloopInd */ + { ism_interface_down, ISM_Down }, /* InterfaceDown */ + }, + { + /* DROther: */ + { ism_ignore, ISM_DependUpon }, /* NoEvent */ + { ism_ignore, ISM_DROther }, /* InterfaceUp */ + { ism_ignore, ISM_DROther }, /* WaitTimer */ + { ism_ignore, ISM_DROther }, /* BackupSeen */ + { ism_neighbor_change, ISM_DependUpon }, /* NeighborChange */ + { ism_loop_ind, ISM_Loopback }, /* LoopInd */ + { ism_ignore, ISM_DROther }, /* UnloopInd */ + { ism_interface_down, ISM_Down }, /* InterfaceDown */ + }, + { + /* Backup: */ + { ism_ignore, ISM_DependUpon }, /* NoEvent */ + { ism_ignore, ISM_Backup }, /* InterfaceUp */ + { ism_ignore, ISM_Backup }, /* WaitTimer */ + { ism_ignore, ISM_Backup }, /* BackupSeen */ + { ism_neighbor_change, ISM_DependUpon }, /* NeighborChange */ + { ism_loop_ind, ISM_Loopback }, /* LoopInd */ + { ism_ignore, ISM_Backup }, /* UnloopInd */ + { ism_interface_down, ISM_Down }, /* InterfaceDown */ + }, + { + /* DR: */ + { ism_ignore, ISM_DependUpon }, /* NoEvent */ + { ism_ignore, ISM_DR }, /* InterfaceUp */ + { ism_ignore, ISM_DR }, /* WaitTimer */ + { ism_ignore, ISM_DR }, /* BackupSeen */ + { ism_neighbor_change, ISM_DependUpon }, /* NeighborChange */ + { ism_loop_ind, ISM_Loopback }, /* LoopInd */ + { ism_ignore, ISM_DR }, /* UnloopInd */ + { ism_interface_down, ISM_Down }, /* InterfaceDown */ + }, +}; + +static char *ospf_ism_event_str[] = +{ + "NoEvent", + "InterfaceUp", + "WaitTimer", + "BackupSeen", + "NeighborChange", + "LoopInd", + "UnLoopInd", + "InterfaceDown", +}; + +void +ism_change_state (struct ospf_interface *oi, int state) +{ + int old_state; + struct ospf_lsa *lsa; + + /* Logging change of state. */ + if (IS_DEBUG_OSPF (ism, ISM_STATUS)) + zlog (NULL, LOG_INFO, "ISM[%s]: State change %s -> %s", IF_NAME (oi), + LOOKUP (ospf_ism_state_msg, oi->state), + LOOKUP (ospf_ism_state_msg, state)); + + old_state = oi->state; + oi->state = state; + oi->state_change++; + + if (old_state == ISM_Down || state == ISM_Down) + ospf_check_abr_status (oi->ospf); + + /* Originate router-LSA. */ + if (oi->area) + { + if (state == ISM_Down) + { + if (oi->area->act_ints > 0) + oi->area->act_ints--; + } + else if (old_state == ISM_Down) + oi->area->act_ints++; + + /* schedule router-LSA originate. */ + ospf_router_lsa_timer_add (oi->area); + } + + /* Originate network-LSA. */ + if (old_state != ISM_DR && state == ISM_DR) + ospf_network_lsa_timer_add (oi); + else if (old_state == ISM_DR && state != ISM_DR) + { + /* Free self originated network LSA. */ + lsa = oi->network_lsa_self; + if (lsa) + { + ospf_lsa_flush_area (lsa, oi->area); + OSPF_TIMER_OFF (oi->t_network_lsa_self); + } + + ospf_lsa_unlock (oi->network_lsa_self); + oi->network_lsa_self = NULL; + } + +#ifdef HAVE_OPAQUE_LSA + ospf_opaque_ism_change (oi, old_state); +#endif /* HAVE_OPAQUE_LSA */ + + /* Check area border status. */ + ospf_check_abr_status (oi->ospf); +} + +/* Execute ISM event process. */ +int +ospf_ism_event (struct thread *thread) +{ + int event; + int next_state; + struct ospf_interface *oi; + + oi = THREAD_ARG (thread); + event = THREAD_VAL (thread); + + /* Call function. */ + next_state = (*(ISM [oi->state][event].func))(oi); + + if (! next_state) + next_state = ISM [oi->state][event].next_state; + + if (IS_DEBUG_OSPF (ism, ISM_EVENTS)) + zlog (NULL, LOG_INFO, "ISM[%s]: %s (%s)", IF_NAME (oi), + LOOKUP (ospf_ism_state_msg, oi->state), + ospf_ism_event_str[event]); + + /* If state is changed. */ + if (next_state != oi->state) + ism_change_state (oi, next_state); + + /* Make sure timer is set. */ + ism_timer_set (oi); + + return 0; +} + diff --git a/ospfd/ospf_ism.h b/ospfd/ospf_ism.h index 6de8b8e2..b04865af 100644 --- a/ospfd/ospf_ism.h +++ b/ospfd/ospf_ism.h @@ -46,17 +46,17 @@ #define ISM_InterfaceDown 7 #define OSPF_ISM_EVENT_MAX 8 -#define OSPF_ISM_WRITE_ON(O) \ +#define OSPF_ISM_WRITE_ON() \ do \ { \ if (oi->on_write_q == 0) \ { \ - listnode_add ((O)->oi_write_q, oi); \ + listnode_add (ospf_top->oi_write_q, oi); \ oi->on_write_q = 1; \ } \ - if ((O)->t_write == NULL) \ - (O)->t_write = \ - thread_add_write (master, ospf_write, (O), (O)->fd); \ + if (ospf_top->t_write == NULL) \ + ospf_top->t_write = \ + thread_add_write (master, ospf_write, ospf_top, ospf_top->fd); \ } while (0) /* Macro for OSPF ISM timer turn on. */ diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c index 5d5ad08a..34cbc446 100644 --- a/ospfd/ospf_lsa.c +++ b/ospfd/ospf_lsa.c @@ -615,7 +615,8 @@ lsa_link_ptomp_set (struct stream *s, struct ospf_interface *oi) link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, 0); links++; - zlog_info ("PointToMultipoint: running ptomultip_set"); + if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) + zlog_info ("PointToMultipoint: running ptomultip_set"); /* Search neighbor, */ for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) @@ -628,8 +629,9 @@ lsa_link_ptomp_set (struct stream *s, struct ospf_interface *oi) link_info_set (s, nbr->router_id, oi->address->u.prefix4, LSA_LINK_TYPE_POINTOPOINT, 0, oi->output_cost); links++; - zlog_info ("PointToMultipoint: set link to %s", - inet_ntoa(oi->address->u.prefix4)); + if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) + zlog_info ("PointToMultipoint: set link to %s", + inet_ntoa(oi->address->u.prefix4)); } return links; @@ -648,7 +650,7 @@ router_lsa_link_set (struct stream *s, struct ospf_area *area) struct interface *ifp = oi->ifp; /* Check interface is up, OSPF is enable. */ - if (if_is_up (ifp)) + if (if_is_operative (ifp)) { if (oi->state != ISM_Down) { @@ -1402,7 +1404,7 @@ ospf_external_lsa_nexthop_get (struct ospf *ospf, struct in_addr nexthop) { struct ospf_interface *oi = getdata (n1); - if (if_is_up (oi->ifp)) + if (if_is_operative (oi->ifp)) if (oi->address->family == AF_INET) if (prefix_match (oi->address, &nh)) return nexthop; @@ -1423,7 +1425,7 @@ ospf_get_ip_from_ifp (struct ospf_interface *oi) fwd.s_addr = 0; - if (if_is_up (oi->ifp)) + if (if_is_operative (oi->ifp)) return oi->address->u.prefix4; return fwd; @@ -1444,7 +1446,7 @@ ospf_get_nssa_ip (struct ospf_area *area) { struct ospf_interface *oi = getdata (n1); - if (if_is_up (oi->ifp)) + if (if_is_operative (oi->ifp)) if (oi->area->external_routing == OSPF_AREA_NSSA) if (oi->address && oi->address->family == AF_INET) { @@ -1454,6 +1456,8 @@ ospf_get_nssa_ip (struct ospf_area *area) return oi->address->u.prefix4; } } + if (best_default.s_addr != 0) + return best_default; if (best_default.s_addr != 0) return best_default; @@ -1632,7 +1636,6 @@ ospf_install_flood_nssa (struct ospf *ospf, /* make lsa duplicate, lock=1 */ new2 = ospf_lsa_dup (lsa); - new2->area = area; new2->data->type = OSPF_AS_NSSA_LSA; @@ -1662,13 +1665,13 @@ ospf_install_flood_nssa (struct ospf *ospf, if (extlsa->e[0].fwd_addr.s_addr == 0) extlsa->e[0].fwd_addr = ospf_get_nssa_ip(area); /* this NSSA area in ifp */ - if (IS_DEBUG_OSPF_NSSA) - if (extlsa->e[0].fwd_addr.s_addr == 0) - { - zlog_info ("LSA[Type-7]: Could not build FWD-ADDR"); - ospf_lsa_discard(new2); - return; - } + if (extlsa->e[0].fwd_addr.s_addr == 0) + { + if (IS_DEBUG_OSPF_NSSA) + zlog_info ("LSA[Type-7]: Could not build FWD-ADDR"); + ospf_lsa_discard(new2); + return; + } } /* Re-calculate checksum. */ ospf_lsa_checksum (new2->data); @@ -1857,6 +1860,39 @@ ospf_default_originate_timer (struct thread *thread) return 0; } +#ifdef HAVE_NSSA +/* Flush any NSSA LSAs for given prefix */ +void +ospf_nssa_lsa_flush (struct ospf *ospf, struct prefix_ipv4 *p) +{ + struct listnode *node; + struct ospf_lsa *lsa; + struct ospf_area *area; + + for (node = listhead (ospf->areas); node; nextnode (node)) + { + if (((area = getdata (node)) != NULL) + && (area->external_routing == OSPF_AREA_NSSA)) + { + if (!(lsa = ospf_lsa_lookup (area, OSPF_AS_NSSA_LSA, p->prefix, + ospf->router_id))) + { + if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) + zlog_warn ("LSA: There is no such AS-NSSA-LSA %s/%d in LSDB", + inet_ntoa (p->prefix), p->prefixlen); + continue; + } + ospf_ls_retransmit_delete_nbr_area (area, lsa); + if (!IS_LSA_MAXAGE (lsa)) + { + ospf_refresher_unregister_lsa (ospf, lsa); + ospf_lsa_flush_area (lsa, area); + } + } + } +} +#endif /* HAVE_NSSA */ + /* Flush an AS-external-LSA from LSDB and routing domain. */ void ospf_external_lsa_flush (struct ospf *ospf, @@ -1877,6 +1913,13 @@ ospf_external_lsa_flush (struct ospf *ospf, inet_ntoa (p->prefix), p->prefixlen); return; } +#ifdef HAVE_NSSA + /* If LSA is selforiginated and there is NSSA area, flush + * Type-7 LSA's at first. */ + + if (IS_LSA_SELF(lsa) && (ospf->anyNSSA)) + ospf_nssa_lsa_flush (ospf, p); +#endif /* HAVE_NSSA */ /* Sweep LSA from Link State Retransmit List. */ ospf_ls_retransmit_delete_nbr_as (ospf, lsa); @@ -2186,6 +2229,13 @@ ospf_external_lsa_install (struct ospf *ospf, struct ospf_lsa *new, ospf_ase_incremental_update (ospf, new); } +#ifdef HAVE_NSSA + /* There is no point to register selforiginate Type-7 LSA for + * refreshing. We rely on refreshing Type-5 LSA's */ + if (IS_LSA_SELF (new) && (new->data->type == OSPF_AS_NSSA_LSA)) + return new; +#endif /* HAVE_NSSA */ + /* Register self-originated LSA to refresh queue. */ if (IS_LSA_SELF (new)) ospf_refresher_register_lsa (ospf, new); @@ -2216,6 +2266,12 @@ ospf_discard_from_db (struct ospf *ospf, ospf_ls_retransmit_delete_nbr_as (ospf, old); ospf_ase_unregister_external_lsa (old, ospf); break; +#ifdef HAVE_NSSA + case OSPF_AS_NSSA_LSA: + ospf_ls_retransmit_delete_nbr_area (old->area, old); + ospf_ase_unregister_external_lsa (old, ospf); + break; +#endif /* HAVE_NSSA */ default: ospf_ls_retransmit_delete_nbr_area (old->area, old); break; @@ -2587,7 +2643,6 @@ ospf_lsa_maxage_walker_remover (struct ospf *ospf, struct ospf_lsa *lsa) ospf_spf_calculate_schedule (ospf); break; } - ospf_lsa_maxage (ospf, lsa); } @@ -2623,9 +2678,13 @@ ospf_lsa_maxage_walker (struct thread *thread) LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa) ospf_lsa_maxage_walker_remover (ospf, lsa); #endif /* HAVE_OPAQUE_LSA */ +#ifdef HAVE_NSSA + LSDB_LOOP (NSSA_LSDB (area), rn, lsa) + ospf_lsa_maxage_walker_remover (ospf, lsa); +#endif /* HAVE_NSSA */ } - /* for AS-eternal-LSAs. */ + /* for AS-external-LSAs. */ if (ospf->lsdb) { LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa) @@ -2676,6 +2735,9 @@ struct ospf_lsa * ospf_lsa_lookup (struct ospf_area *area, u_int32_t type, struct in_addr id, struct in_addr adv_router) { + struct ospf *ospf = ospf_lookup(); + assert(ospf); + switch (type) { case OSPF_ROUTER_LSA: @@ -2695,7 +2757,7 @@ ospf_lsa_lookup (struct ospf_area *area, u_int32_t type, #ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_AS_LSA: #endif /* HAVE_OPAQUE_LSA */ - return ospf_lsdb_lookup_by_id (area->ospf->lsdb, type, id, adv_router); + return ospf_lsdb_lookup_by_id (ospf->lsdb, type, id, adv_router); break; default: break; @@ -2840,7 +2902,7 @@ ospf_lsa_different (struct ospf_lsa *l1, struct ospf_lsa *l2) if (l1->data->length == 0) return 1; - assert (l1->data->length > OSPF_LSA_HEADER_SIZE); + assert ( ntohs(l1->data->length) > OSPF_LSA_HEADER_SIZE); p1 = (char *) l1->data; p2 = (char *) l2->data; @@ -3218,9 +3280,9 @@ ospf_lsa_refresh (struct ospf *ospf, struct ospf_lsa *lsa) case OSPF_OPAQUE_AS_LSA: ospf_opaque_lsa_refresh (lsa); break; +#endif /* HAVE_OPAQUE_LSA */ default: break; -#endif /* HAVE_OPAQUE_LSA */ } } @@ -3260,6 +3322,8 @@ ospf_refresher_register_lsa (struct ospf *ospf, struct ospf_lsa *lsa) ospf->lsa_refresh_queue.qs[index] = list_new (); listnode_add (ospf->lsa_refresh_queue.qs[index], ospf_lsa_lock (lsa)); lsa->refresh_list = index; + if (IS_DEBUG_OSPF (lsa, LSA_REFRESH)) + zlog_info ("LSA[Refresh]: ospf_refresher_register_lsa(): setting refresh_list on lsa %p (slod %d)", lsa, index); } } @@ -3324,7 +3388,7 @@ ospf_lsa_refresh_walker (struct thread *t) next = node->next; if (IS_DEBUG_OSPF (lsa, LSA_REFRESH)) - zlog_info ("LSA[Refresh]: ospf_lsa_refresh_walker(): refresh lsa %p", lsa); + zlog_info ("LSA[Refresh]: ospf_lsa_refresh_walker(): refresh lsa %p (slot %d)", lsa, i); list_delete_node (refresh_list, node); ospf_lsa_unlock (lsa); diff --git a/ospfd/ospf_lsa.h b/ospfd/ospf_lsa.h index 3271409f..b12feebc 100644 --- a/ospfd/ospf_lsa.h +++ b/ospfd/ospf_lsa.h @@ -266,6 +266,7 @@ struct ospf_lsa *ospf_summary_asbr_lsa_refresh (struct ospf *, struct ospf_lsa * struct ospf_lsa *ospf_lsa_install (struct ospf *, struct ospf_interface *, struct ospf_lsa *); +void ospf_nssa_lsa_flush (struct ospf *ospf, struct prefix_ipv4 *p); void ospf_external_lsa_flush (struct ospf *, u_char, struct prefix_ipv4 *, unsigned int, struct in_addr); @@ -319,4 +320,8 @@ int metric_value (struct ospf *, u_char); struct in_addr ospf_get_nssa_ip (struct ospf_area *); #endif /* HAVE NSSA */ +#ifdef HAVE_NSSA +struct in_addr ospf_get_nssa_ip (struct ospf_area *); +#endif + #endif /* _ZEBRA_OSPF_LSA_H */ diff --git a/ospfd/ospf_lsdb.c b/ospfd/ospf_lsdb.c index 71a98ddc..46d8d705 100644 --- a/ospfd/ospf_lsdb.c +++ b/ospfd/ospf_lsdb.c @@ -282,3 +282,18 @@ ospf_lsdb_isempty (struct ospf_lsdb *lsdb) { return (lsdb->total == 0); } + +struct ospf_lsa * +foreach_lsa (struct route_table *table, void *p_arg, int int_arg, + int (*callback) (struct ospf_lsa *, void *, int)) +{ + struct route_node *rn; + struct ospf_lsa *lsa; + + for (rn = route_top (table); rn; rn = route_next (rn)) + if ((lsa = rn->info) != NULL) + if (callback (lsa, p_arg, int_arg)) + return lsa; + + return NULL; +} diff --git a/ospfd/ospf_lsdb.h b/ospfd/ospf_lsdb.h index 302dddea..34344b3b 100644 --- a/ospfd/ospf_lsdb.h +++ b/ospfd/ospf_lsdb.h @@ -42,9 +42,8 @@ struct ospf_lsdb }; /* Macros. */ -#define LSDB_LOOP(T,N,L) \ - if ((T) != NULL) \ - for ((N) = route_top ((T)); ((N)); ((N)) = route_next ((N))) \ +#define LSDB_LOOP(T,N,L) \ + for ((N) = route_top ((T)); ((N)); ((N)) = route_next ((N))) \ if (((L) = (N)->info)) #define ROUTER_LSDB(A) ((A)->lsdb->type[OSPF_ROUTER_LSA].db) @@ -78,5 +77,7 @@ unsigned long ospf_lsdb_count_all (struct ospf_lsdb *); unsigned long ospf_lsdb_count (struct ospf_lsdb *, int); unsigned long ospf_lsdb_count_self (struct ospf_lsdb *, int); unsigned long ospf_lsdb_isempty (struct ospf_lsdb *); +struct ospf_lsa *foreach_lsa (struct route_table *, void *, int, + int (*callback) (struct ospf_lsa *, void *, int)); #endif /* _ZEBRA_OSPF_LSDB_H */ diff --git a/ospfd/ospf_main.c b/ospfd/ospf_main.c index b1d1fd4c..0ac82a68 100644 --- a/ospfd/ospf_main.c +++ b/ospfd/ospf_main.c @@ -36,8 +36,6 @@ #include "stream.h" #include "log.h" #include "memory.h" -#include "privs.h" -#include "debug.h" #include "ospfd/ospfd.h" #include "ospfd/ospf_interface.h" @@ -49,29 +47,6 @@ #include "ospfd/ospf_zebra.h" #include "ospfd/ospf_vty.h" -/* ospfd privileges */ -zebra_capabilities_t _caps_p [] = -{ - ZCAP_RAW, - ZCAP_BIND, - ZCAP_BROADCAST, - ZCAP_ADMIN, -}; - -struct zebra_privs_t ospfd_privs = -{ -#if defined(ZEBRA_USER) && defined(ZEBRA_GROUP) - .user = ZEBRA_USER, - .group = ZEBRA_GROUP, -#endif -#if defined(VTY_GROUP) - .vty_group = VTY_GROUP, -#endif - .caps_p = _caps_p, - .cap_num_p = sizeof(_caps_p)/sizeof(_caps_p[0]), - .cap_num_i = 0 -}; - /* Configuration filename and directory. */ char config_current[] = OSPF_DEFAULT_CONFIG; char config_default[] = SYSCONFDIR OSPF_DEFAULT_CONFIG; @@ -86,7 +61,6 @@ struct option longopts[] = { "help", no_argument, NULL, 'h'}, { "vty_addr", required_argument, NULL, 'A'}, { "vty_port", required_argument, NULL, 'P'}, - { "user", required_argument, NULL, 'u'}, { "version", no_argument, NULL, 'v'}, { 0 } }; @@ -114,7 +88,6 @@ Daemon which manages OSPF.\n\n\ -i, --pid_file Set process identifier file name\n\ -A, --vty_addr Set vty's bind address\n\ -P, --vty_port Set vty's port number\n\ --u, --user User and group to run as\n\ -v, --version Print program version\n\ -h, --help Display this help and exit\n\ \n\ @@ -189,11 +162,6 @@ signal_init () signal_set (SIGTTOU, SIG_IGN); #endif signal_set (SIGUSR1, sigusr1); -#ifdef HAVE_GLIBC_BACKTRACE - signal_set (SIGBUS, debug_print_trace); - signal_set (SIGSEGV, debug_print_trace); - signal_set (SIGILL, debug_print_trace); -#endif /* HAVE_GLIBC_BACKTRACE */ } /* OSPFd main routine. */ @@ -232,7 +200,7 @@ main (int argc, char **argv) { int opt; - opt = getopt_long (argc, argv, "dlf:hA:P:u:v", longopts, 0); + opt = getopt_long (argc, argv, "dlf:hA:P:v", longopts, 0); if (opt == EOF) break; @@ -264,9 +232,6 @@ main (int argc, char **argv) vty_port = atoi (optarg); vty_port = (vty_port ? vty_port : OSPF_VTY_PORT); break; - case 'u': - ospfd_privs.group = ospfd_privs.user = optarg; - break; case 'v': print_version (progname); exit (0); @@ -284,7 +249,6 @@ main (int argc, char **argv) master = om->master; /* Library inits. */ - zprivs_init (&ospfd_privs); signal_init (); cmd_init (1); debug_init (); diff --git a/ospfd/ospf_neighbor.c b/ospfd/ospf_neighbor.c new file mode 100644 index 00000000..ccef0559 --- /dev/null +++ b/ospfd/ospf_neighbor.c @@ -0,0 +1,319 @@ +/* + * OSPF Neighbor functions. + * Copyright (C) 1999, 2000 Toshiaki Takada + * + * 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. + */ + +#include <zebra.h> + +#include "linklist.h" +#include "prefix.h" +#include "memory.h" +#include "command.h" +#include "thread.h" +#include "stream.h" +#include "table.h" +#include "log.h" + +#include "ospfd/ospfd.h" +#include "ospfd/ospf_interface.h" +#include "ospfd/ospf_asbr.h" +#include "ospfd/ospf_lsa.h" +#include "ospfd/ospf_lsdb.h" +#include "ospfd/ospf_neighbor.h" +#include "ospfd/ospf_nsm.h" +#include "ospfd/ospf_packet.h" +#include "ospfd/ospf_network.h" +#include "ospfd/ospf_flood.h" +#include "ospfd/ospf_dump.h" + +struct ospf_neighbor * +ospf_nbr_new (struct ospf_interface *oi) +{ + struct ospf_neighbor *nbr; + + /* Allcate new neighbor. */ + nbr = XMALLOC (MTYPE_OSPF_NEIGHBOR, sizeof (struct ospf_neighbor)); + memset (nbr, 0, sizeof (struct ospf_neighbor)); + + /* Relate neighbor to the interface. */ + nbr->oi = oi; + + /* Set default values. */ + nbr->state = NSM_Down; + + /* Set inheritance values. */ + nbr->v_inactivity = OSPF_IF_PARAM (oi, v_wait); + nbr->v_db_desc = OSPF_IF_PARAM (oi, retransmit_interval); + nbr->v_ls_req = OSPF_IF_PARAM (oi, retransmit_interval); + nbr->v_ls_upd = OSPF_IF_PARAM (oi, retransmit_interval); + nbr->priority = -1; + + /* DD flags. */ + nbr->dd_flags = OSPF_DD_FLAG_MS|OSPF_DD_FLAG_M|OSPF_DD_FLAG_I; + + /* Last received and sent DD. */ + nbr->last_send = NULL; + + nbr->nbr_nbma = NULL; + + ospf_lsdb_init (&nbr->db_sum); + ospf_lsdb_init (&nbr->ls_rxmt); + ospf_lsdb_init (&nbr->ls_req); + + nbr->crypt_seqnum = 0; + + return nbr; +} + +void +ospf_nbr_free (struct ospf_neighbor *nbr) +{ + /* Free DB summary list. */ + if (ospf_db_summary_count (nbr)) + ospf_db_summary_clear (nbr); + /* ospf_db_summary_delete_all (nbr); */ + + /* Free ls request list. */ + if (ospf_ls_request_count (nbr)) + ospf_ls_request_delete_all (nbr); + + /* Free retransmit list. */ + if (ospf_ls_retransmit_count (nbr)) + ospf_ls_retransmit_clear (nbr); + + /* Cleanup LSDBs. */ + ospf_lsdb_cleanup (&nbr->db_sum); + ospf_lsdb_cleanup (&nbr->ls_req); + ospf_lsdb_cleanup (&nbr->ls_rxmt); + + /* Clear last send packet. */ + if (nbr->last_send) + ospf_packet_free (nbr->last_send); + + if (nbr->nbr_nbma) + { + nbr->nbr_nbma->nbr = NULL; + nbr->nbr_nbma = NULL; + } + + /* Cancel all timers. */ + OSPF_NSM_TIMER_OFF (nbr->t_inactivity); + OSPF_NSM_TIMER_OFF (nbr->t_db_desc); + OSPF_NSM_TIMER_OFF (nbr->t_ls_req); + OSPF_NSM_TIMER_OFF (nbr->t_ls_upd); + + /* Cancel all events. *//* Thread lookup cost would be negligible. */ + thread_cancel_event (master, nbr); + + XFREE (MTYPE_OSPF_NEIGHBOR, nbr); +} + +/* Delete specified OSPF neighbor from interface. */ +void +ospf_nbr_delete (struct ospf_neighbor *nbr) +{ + struct ospf_interface *oi; + struct route_node *rn; + struct prefix p; + + oi = nbr->oi; + + /* Unlink ospf neighbor from the interface. */ + p.family = AF_INET; + p.prefixlen = IPV4_MAX_BITLEN; + p.u.prefix4 = nbr->src; + + rn = route_node_lookup (oi->nbrs, &p); + if (rn) + { + if (rn->info) + { + rn->info = NULL; + route_unlock_node (rn); + } + else + zlog_info ("Can't find neighbor %s in the interface %s", + inet_ntoa (nbr->src), IF_NAME (oi)); + + route_unlock_node (rn); + } + + /* Free ospf_neighbor structure. */ + ospf_nbr_free (nbr); +} + +/* Check myself is in the neighbor list. */ +int +ospf_nbr_bidirectional (struct in_addr *router_id, + struct in_addr *neighbors, int size) +{ + int i; + int max; + + max = size / sizeof (struct in_addr); + + for (i = 0; i < max; i ++) + if (IPV4_ADDR_SAME (router_id, &neighbors[i])) + return 1; + + return 0; +} + +/* Add self to nbr list. */ +void +ospf_nbr_add_self (struct ospf_interface *oi) +{ + struct ospf_neighbor *nbr; + struct prefix p; + struct route_node *rn; + + p.family = AF_INET; + p.prefixlen = 32; + p.u.prefix4 = oi->address->u.prefix4; + + rn = route_node_get (oi->nbrs, &p); + if (rn->info) + { + /* There is already pseudo neighbor. */ + nbr = rn->info; + route_unlock_node (rn); + } + else + rn->info = oi->nbr_self; +} + +/* Get neighbor count by status. + Specify status = 0, get all neighbor other than myself. */ +int +ospf_nbr_count (struct ospf_interface *oi, int state) +{ + struct ospf_neighbor *nbr; + struct route_node *rn; + int count = 0; + + for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) + if ((nbr = rn->info)) + if (!IPV4_ADDR_SAME (&nbr->router_id, &oi->ospf->router_id)) + if (state == 0 || nbr->state == state) + count++; + + return count; +} + +#ifdef HAVE_OPAQUE_LSA +int +ospf_nbr_count_opaque_capable (struct ospf_interface *oi) +{ + struct ospf_neighbor *nbr; + struct route_node *rn; + int count = 0; + + for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) + if ((nbr = rn->info)) + if (!IPV4_ADDR_SAME (&nbr->router_id, &oi->ospf->router_id)) + if (nbr->state == NSM_Full) + if (CHECK_FLAG (nbr->options, OSPF_OPTION_O)) + count++; + + return count; +} +#endif /* HAVE_OPAQUE_LSA */ + +struct ospf_neighbor * +ospf_nbr_lookup_by_addr (struct route_table *nbrs, + struct in_addr *addr) +{ + struct prefix p; + struct route_node *rn; + struct ospf_neighbor *nbr; + + p.family = AF_INET; + p.prefixlen = IPV4_MAX_BITLEN; + p.u.prefix4 = *addr; + + rn = route_node_lookup (nbrs, &p); + if (! rn) + return NULL; + + if (rn->info == NULL) + { + route_unlock_node (rn); + return NULL; + } + + nbr = (struct ospf_neighbor *) rn->info; + route_unlock_node (rn); + + return nbr; +} + +struct ospf_neighbor * +ospf_nbr_lookup_by_routerid (struct route_table *nbrs, + struct in_addr *id) +{ + struct route_node *rn; + struct ospf_neighbor *nbr; + + for (rn = route_top (nbrs); rn; rn = route_next (rn)) + if ((nbr = rn->info) != NULL) + if (IPV4_ADDR_SAME (&nbr->router_id, id)) + { + route_unlock_node(rn); + return nbr; + } + + return NULL; +} + +void +ospf_renegotiate_optional_capabilities (struct ospf *top) +{ + listnode node; + struct ospf_interface *oi; + struct route_table *nbrs; + struct route_node *rn; + struct ospf_neighbor *nbr; + + /* At first, flush self-originated LSAs from routing domain. */ + ospf_flush_self_originated_lsas_now (top); + + /* Revert all neighbor status to ExStart. */ + for (node = listhead (top->oiflist); node; nextnode (node)) + { + if ((oi = getdata (node)) == NULL || (nbrs = oi->nbrs) == NULL) + continue; + + for (rn = route_top (nbrs); rn; rn = route_next (rn)) + { + if ((nbr = rn->info) == NULL || nbr == oi->nbr_self) + continue; + + if (nbr->state < NSM_ExStart) + continue; + + if (IS_DEBUG_OSPF_EVENT) + zlog_info ("Renegotiate optional capabilities with neighbor(%s)", inet_ntoa (nbr->router_id)); + + OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch); + } + } + + return; +} diff --git a/ospfd/ospf_neighbor.h b/ospfd/ospf_neighbor.h index 485b548b..f7b18742 100644 --- a/ospfd/ospf_neighbor.h +++ b/ospfd/ospf_neighbor.h @@ -93,9 +93,9 @@ void ospf_nbr_free (struct ospf_neighbor *); void ospf_nbr_delete (struct ospf_neighbor *); int ospf_nbr_bidirectional (struct in_addr *, struct in_addr *, int); void ospf_nbr_add_self (struct ospf_interface *); -int ospf_nbr_count (struct ospf_interface *, int); +int ospf_nbr_count (struct route_table *, int); #ifdef HAVE_OPAQUE_LSA -int ospf_nbr_count_opaque_capable (struct ospf_interface *); +int ospf_opaque_capable_nbr_count (struct route_table *nbrs, int status); #endif /* HAVE_OPAQUE_LSA */ struct ospf_neighbor *ospf_nbr_lookup_by_addr (struct route_table *, struct in_addr *); diff --git a/ospfd/ospf_network.c b/ospfd/ospf_network.c index 87aec1e5..56ec8647 100644 --- a/ospfd/ospf_network.c +++ b/ospfd/ospf_network.c @@ -29,9 +29,6 @@ #include "sockunion.h" #include "log.h" #include "sockopt.h" -#include "privs.h" - -extern struct zebra_privs_t ospfd_privs; #include "ospfd/ospfd.h" #include "ospfd/ospf_network.h" @@ -42,8 +39,6 @@ extern struct zebra_privs_t ospfd_privs; #include "ospfd/ospf_neighbor.h" #include "ospfd/ospf_packet.h" - - /* Join to the OSPF ALL SPF ROUTERS multicast group. */ int ospf_if_add_allspfrouters (struct ospf *top, struct prefix *p, @@ -156,20 +151,12 @@ ospf_sock_init (void) int ospf_sock; int ret, tos, hincl = 1; - if ( ospfd_privs.change (ZPRIVS_RAISE) ) - zlog_err ("ospf_sock_init: could not raise privs, %s", - strerror (errno) ); - ospf_sock = socket (AF_INET, SOCK_RAW, IPPROTO_OSPFIGP); if (ospf_sock < 0) { - if ( ospfd_privs.change (ZPRIVS_LOWER) ) - zlog_err ("ospf_sock_init: could not lower privs, %s", - strerror (errno) ); zlog_warn ("ospf_read_sock_init: socket: %s", strerror (errno)); return -1; } - /* Set precedence field. */ #ifdef IPTOS_PREC_INTERNETCONTROL @@ -178,9 +165,6 @@ ospf_sock_init (void) (char *) &tos, sizeof (int)); if (ret < 0) { - if ( ospfd_privs.change (ZPRIVS_LOWER) ) - zlog_err ("ospf_sock_init: could not lower privs, %s", - strerror (errno) ); zlog_warn ("can't set sockopt IP_TOS %d to socket %d", tos, ospf_sock); close (ospf_sock); /* Prevent sd leak. */ return ret; @@ -190,40 +174,19 @@ ospf_sock_init (void) /* we will include IP header with packet */ ret = setsockopt (ospf_sock, IPPROTO_IP, IP_HDRINCL, &hincl, sizeof (hincl)); if (ret < 0) - { - if ( ospfd_privs.change (ZPRIVS_LOWER) ) - zlog_err ("ospf_sock_init: could not lower privs, %s", - strerror (errno) ); - zlog_warn ("Can't set IP_HDRINCL option"); - } + zlog_warn ("Can't set IP_HDRINCL option"); #if defined (IP_PKTINFO) ret = setsockopt (ospf_sock, IPPROTO_IP, IP_PKTINFO, &hincl, sizeof (hincl)); if (ret < 0) - { - if ( ospfd_privs.change (ZPRIVS_LOWER) ) - zlog_err ("ospf_sock_init: could not lower privs, %s", - strerror (errno) ); - zlog_warn ("Can't set IP_PKTINFO option"); - } + zlog_warn ("Can't set IP_PKTINFO option"); #elif defined (IP_RECVIF) ret = setsockopt (ospf_sock, IPPROTO_IP, IP_RECVIF, &hincl, sizeof (hincl)); if (ret < 0) - { - if ( ospfd_privs.change (ZPRIVS_LOWER) ) - zlog_err ("ospf_sock_init: could not lower privs, %s", - strerror (errno) ); - zlog_warn ("Can't set IP_RECVIF option"); - } + zlog_warn ("Can't set IP_RECVIF option"); #else #warning "cannot be able to receive link information on this OS" #endif - - if (ospfd_privs.change (ZPRIVS_LOWER)) - { - zlog_err ("ospf_sock_init: could not lower privs, %s", - strerror (errno) ); - } return ospf_sock; } diff --git a/ospfd/ospf_nsm.c b/ospfd/ospf_nsm.c new file mode 100644 index 00000000..a8efdcc1 --- /dev/null +++ b/ospfd/ospf_nsm.c @@ -0,0 +1,877 @@ +/* + * OSPF version 2 Neighbor State Machine + * From RFC2328 [OSPF Version 2] + * Copyright (C) 1999, 2000 Toshiaki Takada + * + * 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. + */ + +#include <zebra.h> + +#include "thread.h" +#include "memory.h" +#include "hash.h" +#include "linklist.h" +#include "prefix.h" +#include "if.h" +#include "table.h" +#include "stream.h" +#include "table.h" +#include "log.h" + +#include "ospfd/ospfd.h" +#include "ospfd/ospf_interface.h" +#include "ospfd/ospf_ism.h" +#include "ospfd/ospf_asbr.h" +#include "ospfd/ospf_lsa.h" +#include "ospfd/ospf_lsdb.h" +#include "ospfd/ospf_neighbor.h" +#include "ospfd/ospf_nsm.h" +#include "ospfd/ospf_network.h" +#include "ospfd/ospf_packet.h" +#include "ospfd/ospf_dump.h" +#include "ospfd/ospf_flood.h" +#include "ospfd/ospf_abr.h" + +void nsm_reset_nbr (struct ospf_neighbor *); + + +/* OSPF NSM Timer functions. */ +int +ospf_inactivity_timer (struct thread *thread) +{ + struct ospf_neighbor *nbr; + + nbr = THREAD_ARG (thread); + nbr->t_inactivity = NULL; + + if (IS_DEBUG_OSPF (nsm, NSM_TIMERS)) + zlog (NULL, LOG_DEBUG, "NSM[%s:%s]: Timer (Inactivity timer expire)", + IF_NAME (nbr->oi), inet_ntoa (nbr->router_id)); + + OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_InactivityTimer); + + return 0; +} + +int +ospf_db_desc_timer (struct thread *thread) +{ + struct ospf_interface *oi; + struct ospf_neighbor *nbr; + + nbr = THREAD_ARG (thread); + nbr->t_db_desc = NULL; + + oi = nbr->oi; + + if (IS_DEBUG_OSPF (nsm, NSM_TIMERS)) + zlog (NULL, LOG_INFO, "NSM[%s:%s]: Timer (DD Retransmit timer expire)", + IF_NAME (nbr->oi), inet_ntoa (nbr->src)); + + /* resent last send DD packet. */ + assert (nbr->last_send); + ospf_db_desc_resend (nbr); + + /* DD Retransmit timer set. */ + OSPF_NSM_TIMER_ON (nbr->t_db_desc, ospf_db_desc_timer, nbr->v_db_desc); + + return 0; +} + +/* Hook function called after ospf NSM event is occured. */ + +void +nsm_timer_set (struct ospf_neighbor *nbr) +{ + switch (nbr->state) + { + case NSM_Down: + OSPF_NSM_TIMER_OFF (nbr->t_db_desc); + OSPF_NSM_TIMER_OFF (nbr->t_ls_upd); + break; + case NSM_Attempt: + OSPF_NSM_TIMER_OFF (nbr->t_db_desc); + OSPF_NSM_TIMER_OFF (nbr->t_ls_upd); + break; + case NSM_Init: + OSPF_NSM_TIMER_OFF (nbr->t_db_desc); + OSPF_NSM_TIMER_OFF (nbr->t_ls_upd); + break; + case NSM_TwoWay: + OSPF_NSM_TIMER_OFF (nbr->t_db_desc); + OSPF_NSM_TIMER_OFF (nbr->t_ls_upd); + break; + case NSM_ExStart: + OSPF_NSM_TIMER_ON (nbr->t_db_desc, ospf_db_desc_timer, nbr->v_db_desc); + OSPF_NSM_TIMER_OFF (nbr->t_ls_upd); + break; + case NSM_Exchange: + OSPF_NSM_TIMER_ON (nbr->t_ls_upd, ospf_ls_upd_timer, nbr->v_ls_upd); + if (!IS_SET_DD_MS (nbr->dd_flags)) + OSPF_NSM_TIMER_OFF (nbr->t_db_desc); + break; + case NSM_Loading: + OSPF_NSM_TIMER_OFF (nbr->t_db_desc); + break; + case NSM_Full: + OSPF_NSM_TIMER_OFF (nbr->t_db_desc); + break; + default: + OSPF_NSM_TIMER_OFF (nbr->t_db_desc); + break; + } +} + + +/* OSPF NSM functions. */ +int +nsm_ignore (struct ospf_neighbor *nbr) +{ + if (IS_DEBUG_OSPF (nsm, NSM_EVENTS)) + zlog (NULL, LOG_INFO, "NSM[%s:%s]: nsm_ignore called", + IF_NAME (nbr->oi), inet_ntoa (nbr->router_id)); + + return 0; +} + +int +nsm_hello_received (struct ospf_neighbor *nbr) +{ + /* Start or Restart Inactivity Timer. */ + OSPF_NSM_TIMER_OFF (nbr->t_inactivity); + + OSPF_NSM_TIMER_ON (nbr->t_inactivity, ospf_inactivity_timer, + nbr->v_inactivity); + + if (nbr->oi->type == OSPF_IFTYPE_NBMA && nbr->nbr_nbma) + OSPF_POLL_TIMER_OFF (nbr->nbr_nbma->t_poll); + + return 0; +} + +int +nsm_start (struct ospf_neighbor *nbr) +{ + + nsm_reset_nbr (nbr); + + if (nbr->nbr_nbma) + OSPF_POLL_TIMER_OFF (nbr->nbr_nbma->t_poll); + + OSPF_NSM_TIMER_OFF (nbr->t_inactivity); + + OSPF_NSM_TIMER_ON (nbr->t_inactivity, ospf_inactivity_timer, + nbr->v_inactivity); + + return 0; +} + +int +nsm_twoway_received (struct ospf_neighbor *nbr) +{ + struct ospf_interface *oi; + int next_state = NSM_TwoWay; + + oi = nbr->oi; + + /* These netowork types must be adjacency. */ + if (oi->type == OSPF_IFTYPE_POINTOPOINT || + oi->type == OSPF_IFTYPE_POINTOMULTIPOINT || + oi->type == OSPF_IFTYPE_VIRTUALLINK) + next_state = NSM_ExStart; + + /* Router itself is the DRouter or the BDRouter. */ + if (IPV4_ADDR_SAME (&oi->address->u.prefix4, &DR (oi)) || + IPV4_ADDR_SAME (&oi->address->u.prefix4, &BDR (oi))) + next_state = NSM_ExStart; + + /* Neighboring Router is the DRouter or the BDRouter. */ + if (IPV4_ADDR_SAME (&nbr->address.u.prefix4, &nbr->d_router) || + IPV4_ADDR_SAME (&nbr->address.u.prefix4, &nbr->bd_router)) + next_state = NSM_ExStart; + + return next_state; +} + +int +ospf_db_summary_count (struct ospf_neighbor *nbr) +{ + return ospf_lsdb_count_all (&nbr->db_sum); +} + +int +ospf_db_summary_isempty (struct ospf_neighbor *nbr) +{ + return ospf_lsdb_isempty (&nbr->db_sum); +} + +int +ospf_db_summary_add (struct ospf_neighbor *nbr, struct ospf_lsa *lsa) +{ +#ifdef HAVE_OPAQUE_LSA + switch (lsa->data->type) + { + case OSPF_OPAQUE_LINK_LSA: + /* Exclude type-9 LSAs that does not have the same "oi" with "nbr". */ + if (lsa->oi != nbr->oi) + return 0; + break; + case OSPF_OPAQUE_AREA_LSA: + /* + * It is assured by the caller function "nsm_negotiation_done()" + * that every given LSA belongs to the same area with "nbr". + */ + break; + case OSPF_OPAQUE_AS_LSA: + default: + break; + } +#endif /* HAVE_OPAQUE_LSA */ + +#ifdef HAVE_NSSA + /* Stay away from any Local Translated Type-7 LSAs */ + if (CHECK_FLAG (lsa->flags, OSPF_LSA_LOCAL_XLT)) + return 0; +#endif /* HAVE_NSSA */ + + if (IS_LSA_MAXAGE (lsa)) + ospf_ls_retransmit_add (nbr, lsa); + else + ospf_lsdb_add (&nbr->db_sum, lsa); + + return 0; +} + +void +ospf_db_summary_clear (struct ospf_neighbor *nbr) +{ + struct ospf_lsdb *lsdb; + int i; + + lsdb = &nbr->db_sum; + for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++) + { + struct route_table *table = lsdb->type[i].db; + struct route_node *rn; + + for (rn = route_top (table); rn; rn = route_next (rn)) + if (rn->info) + ospf_lsdb_delete (&nbr->db_sum, rn->info); + } +} + + + +/* The area link state database consists of the router-LSAs, + network-LSAs and summary-LSAs contained in the area structure, + along with the AS-external-LSAs contained in the global structure. + AS-external-LSAs are omitted from a virtual neighbor's Database + summary list. AS-external-LSAs are omitted from the Database + summary list if the area has been configured as a stub. */ +int +nsm_negotiation_done (struct ospf_neighbor *nbr) +{ + struct ospf_area *area = nbr->oi->area; + struct ospf_lsa *lsa; + struct route_node *rn; + + LSDB_LOOP (ROUTER_LSDB (area), rn, lsa) + ospf_db_summary_add (nbr, lsa); + LSDB_LOOP (NETWORK_LSDB (area), rn, lsa) + ospf_db_summary_add (nbr, lsa); + LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa) + ospf_db_summary_add (nbr, lsa); + LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa) + ospf_db_summary_add (nbr, lsa); + +#ifdef HAVE_OPAQUE_LSA + /* Process only if the neighbor is opaque capable. */ + if (CHECK_FLAG (nbr->options, OSPF_OPTION_O)) + { + LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa) + ospf_db_summary_add (nbr, lsa); + LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa) + ospf_db_summary_add (nbr, lsa); + } +#endif /* HAVE_OPAQUE_LSA */ + + if (nbr->oi->type != OSPF_IFTYPE_VIRTUALLINK + && area->external_routing == OSPF_AREA_DEFAULT) + LSDB_LOOP (EXTERNAL_LSDB (nbr->oi->ospf), rn, lsa) + ospf_db_summary_add (nbr, lsa); + +#ifdef HAVE_OPAQUE_LSA + if (CHECK_FLAG (nbr->options, OSPF_OPTION_O) + && (nbr->oi->type != OSPF_IFTYPE_VIRTUALLINK + && area->external_routing == OSPF_AREA_DEFAULT)) + LSDB_LOOP (OPAQUE_AS_LSDB (nbr->oi->ospf), rn, lsa) + ospf_db_summary_add (nbr, lsa); +#endif /* HAVE_OPAQUE_LSA */ + + return 0; +} + +int +nsm_exchange_done (struct ospf_neighbor *nbr) +{ + if (ospf_ls_request_isempty (nbr)) + return NSM_Full; + + /* Cancel dd retransmit timer. */ + /* OSPF_NSM_TIMER_OFF (nbr->t_db_desc); */ + + /* Send Link State Request. */ + ospf_ls_req_send (nbr); + + return NSM_Loading; +} + +int +nsm_bad_ls_req (struct ospf_neighbor *nbr) +{ + /* Clear neighbor. */ + nsm_reset_nbr (nbr); + + return 0; +} + +int +nsm_adj_ok (struct ospf_neighbor *nbr) +{ + struct ospf_interface *oi; + int next_state; + int flag = 0; + + oi = nbr->oi; + next_state = nbr->state; + + /* These netowork types must be adjacency. */ + if (oi->type == OSPF_IFTYPE_POINTOPOINT + || oi->type == OSPF_IFTYPE_POINTOMULTIPOINT + || oi->type == OSPF_IFTYPE_VIRTUALLINK) + flag = 1; + + /* Router itself is the DRouter or the BDRouter. */ + if (IPV4_ADDR_SAME (&oi->address->u.prefix4, &DR (oi)) + || IPV4_ADDR_SAME (&oi->address->u.prefix4, &BDR (oi))) + flag = 1; + + if (IPV4_ADDR_SAME (&nbr->address.u.prefix4, &DR (oi)) + || IPV4_ADDR_SAME (&nbr->address.u.prefix4, &BDR (oi))) + flag = 1; + + if (nbr->state == NSM_TwoWay && flag == 1) + next_state = NSM_ExStart; + else if (nbr->state >= NSM_ExStart && flag == 0) + next_state = NSM_TwoWay; + + return next_state; +} + +int +nsm_seq_number_mismatch (struct ospf_neighbor *nbr) +{ + /* Clear neighbor. */ + nsm_reset_nbr (nbr); + + return 0; +} + +int +nsm_oneway_received (struct ospf_neighbor *nbr) +{ + /* Clear neighbor. */ + nsm_reset_nbr (nbr); + + return 0; +} + +void +nsm_reset_nbr (struct ospf_neighbor *nbr) +{ + /* Clear Database Summary list. */ + if (!ospf_db_summary_isempty (nbr)) + ospf_db_summary_clear (nbr); + + /* Clear Link State Request list. */ + if (!ospf_ls_request_isempty (nbr)) + ospf_ls_request_delete_all (nbr); + + /* Clear Link State Retransmission list. */ + if (!ospf_ls_retransmit_isempty (nbr)) + ospf_ls_retransmit_clear (nbr); + + /* Cancel thread. */ + OSPF_NSM_TIMER_OFF (nbr->t_db_desc); + OSPF_NSM_TIMER_OFF (nbr->t_ls_req); + OSPF_NSM_TIMER_OFF (nbr->t_ls_upd); + OSPF_NSM_TIMER_OFF (nbr->t_hello_reply); + +#ifdef HAVE_OPAQUE_LSA + if (CHECK_FLAG (nbr->options, OSPF_OPTION_O)) + UNSET_FLAG (nbr->options, OSPF_OPTION_O); +#endif /* HAVE_OPAQUE_LSA */ +} + +int +nsm_kill_nbr (struct ospf_neighbor *nbr) +{ + /* call it here because we cannot call it from ospf_nsm_event */ + nsm_change_state (nbr, NSM_Down); + + /* Reset neighbor. */ + nsm_reset_nbr (nbr); + + if (nbr->oi->type == OSPF_IFTYPE_NBMA && nbr->nbr_nbma != NULL) + { + struct ospf_nbr_nbma *nbr_nbma = nbr->nbr_nbma; + + nbr_nbma->nbr = NULL; + nbr_nbma->state_change = nbr->state_change; + + nbr->nbr_nbma = NULL; + + OSPF_POLL_TIMER_ON (nbr_nbma->t_poll, ospf_poll_timer, + nbr_nbma->v_poll); + + if (IS_DEBUG_OSPF (nsm, NSM_EVENTS)) + zlog_info ("NSM[%s:%s]: Down (PollIntervalTimer scheduled)", + IF_NAME (nbr->oi), inet_ntoa (nbr->address.u.prefix4)); + } + + /* Delete neighbor from interface. */ + ospf_nbr_delete (nbr); + + return 0; +} + +int +nsm_inactivity_timer (struct ospf_neighbor *nbr) +{ + /* Kill neighbor. */ + nsm_kill_nbr (nbr); + + return 0; +} + +int +nsm_ll_down (struct ospf_neighbor *nbr) +{ + /* Reset neighbor. */ + /*nsm_reset_nbr (nbr);*/ + + /* Kill neighbor. */ + nsm_kill_nbr (nbr); + + return 0; +} + +/* Neighbor State Machine */ +struct { + int (*func) (); + int next_state; +} NSM [OSPF_NSM_STATE_MAX][OSPF_NSM_EVENT_MAX] = +{ + { + /* DependUpon: dummy state. */ + { nsm_ignore, NSM_DependUpon }, /* NoEvent */ + { nsm_ignore, NSM_DependUpon }, /* HelloReceived */ + { nsm_ignore, NSM_DependUpon }, /* Start */ + { nsm_ignore, NSM_DependUpon }, /* 2-WayReceived */ + { nsm_ignore, NSM_DependUpon }, /* NegotiationDone */ + { nsm_ignore, NSM_DependUpon }, /* ExchangeDone */ + { nsm_ignore, NSM_DependUpon }, /* BadLSReq */ + { nsm_ignore, NSM_DependUpon }, /* LoadingDone */ + { nsm_ignore, NSM_DependUpon }, /* AdjOK? */ + { nsm_ignore, NSM_DependUpon }, /* SeqNumberMismatch */ + { nsm_ignore, NSM_DependUpon }, /* 1-WayReceived */ + { nsm_ignore, NSM_DependUpon }, /* KillNbr */ + { nsm_ignore, NSM_DependUpon }, /* InactivityTimer */ + { nsm_ignore, NSM_DependUpon }, /* LLDown */ + }, + { + /* Down: */ + { nsm_ignore, NSM_DependUpon }, /* NoEvent */ + { nsm_hello_received, NSM_Init }, /* HelloReceived */ + { nsm_start, NSM_Attempt }, /* Start */ + { nsm_ignore, NSM_Down }, /* 2-WayReceived */ + { nsm_ignore, NSM_Down }, /* NegotiationDone */ + { nsm_ignore, NSM_Down }, /* ExchangeDone */ + { nsm_ignore, NSM_Down }, /* BadLSReq */ + { nsm_ignore, NSM_Down }, /* LoadingDone */ + { nsm_ignore, NSM_Down }, /* AdjOK? */ + { nsm_ignore, NSM_Down }, /* SeqNumberMismatch */ + { nsm_ignore, NSM_Down }, /* 1-WayReceived */ + { nsm_kill_nbr, NSM_Down }, /* KillNbr */ + { nsm_inactivity_timer, NSM_Down }, /* InactivityTimer */ + { nsm_ll_down, NSM_Down }, /* LLDown */ + }, + { + /* Attempt: */ + { nsm_ignore, NSM_DependUpon }, /* NoEvent */ + { nsm_hello_received, NSM_Init }, /* HelloReceived */ + { nsm_ignore, NSM_Attempt }, /* Start */ + { nsm_ignore, NSM_Attempt }, /* 2-WayReceived */ + { nsm_ignore, NSM_Attempt }, /* NegotiationDone */ + { nsm_ignore, NSM_Attempt }, /* ExchangeDone */ + { nsm_ignore, NSM_Attempt }, /* BadLSReq */ + { nsm_ignore, NSM_Attempt }, /* LoadingDone */ + { nsm_ignore, NSM_Attempt }, /* AdjOK? */ + { nsm_ignore, NSM_Attempt }, /* SeqNumberMismatch */ + { nsm_ignore, NSM_Attempt }, /* 1-WayReceived */ + { nsm_kill_nbr, NSM_Down }, /* KillNbr */ + { nsm_inactivity_timer, NSM_Down }, /* InactivityTimer */ + { nsm_ll_down, NSM_Down }, /* LLDown */ + }, + { + /* Init: */ + { nsm_ignore, NSM_DependUpon }, /* NoEvent */ + { nsm_hello_received, NSM_Init }, /* HelloReceived */ + { nsm_ignore, NSM_Init }, /* Start */ + { nsm_twoway_received, NSM_DependUpon }, /* 2-WayReceived */ + { nsm_ignore, NSM_Init }, /* NegotiationDone */ + { nsm_ignore, NSM_Init }, /* ExchangeDone */ + { nsm_ignore, NSM_Init }, /* BadLSReq */ + { nsm_ignore, NSM_Init }, /* LoadingDone */ + { nsm_ignore, NSM_Init }, /* AdjOK? */ + { nsm_ignore, NSM_Init }, /* SeqNumberMismatch */ + { nsm_ignore, NSM_Init }, /* 1-WayReceived */ + { nsm_kill_nbr, NSM_Down }, /* KillNbr */ + { nsm_inactivity_timer, NSM_Down }, /* InactivityTimer */ + { nsm_ll_down, NSM_Down }, /* LLDown */ + }, + { + /* 2-Way: */ + { nsm_ignore, NSM_DependUpon }, /* NoEvent */ + { nsm_hello_received, NSM_TwoWay }, /* HelloReceived */ + { nsm_ignore, NSM_TwoWay }, /* Start */ + { nsm_ignore, NSM_TwoWay }, /* 2-WayReceived */ + { nsm_ignore, NSM_TwoWay }, /* NegotiationDone */ + { nsm_ignore, NSM_TwoWay }, /* ExchangeDone */ + { nsm_ignore, NSM_TwoWay }, /* BadLSReq */ + { nsm_ignore, NSM_TwoWay }, /* LoadingDone */ + { nsm_adj_ok, NSM_DependUpon }, /* AdjOK? */ + { nsm_ignore, NSM_TwoWay }, /* SeqNumberMismatch */ + { nsm_oneway_received, NSM_Init }, /* 1-WayReceived */ + { nsm_kill_nbr, NSM_Down }, /* KillNbr */ + { nsm_inactivity_timer, NSM_Down }, /* InactivityTimer */ + { nsm_ll_down, NSM_Down }, /* LLDown */ + }, + { + /* ExStart: */ + { nsm_ignore, NSM_DependUpon }, /* NoEvent */ + { nsm_hello_received, NSM_ExStart }, /* HelloReceived */ + { nsm_ignore, NSM_ExStart }, /* Start */ + { nsm_ignore, NSM_ExStart }, /* 2-WayReceived */ + { nsm_negotiation_done, NSM_Exchange }, /* NegotiationDone */ + { nsm_ignore, NSM_ExStart }, /* ExchangeDone */ + { nsm_ignore, NSM_ExStart }, /* BadLSReq */ + { nsm_ignore, NSM_ExStart }, /* LoadingDone */ + { nsm_adj_ok, NSM_DependUpon }, /* AdjOK? */ + { nsm_ignore, NSM_ExStart }, /* SeqNumberMismatch */ + { nsm_oneway_received, NSM_Init }, /* 1-WayReceived */ + { nsm_kill_nbr, NSM_Down }, /* KillNbr */ + { nsm_inactivity_timer, NSM_Down }, /* InactivityTimer */ + { nsm_ll_down, NSM_Down }, /* LLDown */ + }, + { + /* Exchange: */ + { nsm_ignore, NSM_DependUpon }, /* NoEvent */ + { nsm_hello_received, NSM_Exchange }, /* HelloReceived */ + { nsm_ignore, NSM_Exchange }, /* Start */ + { nsm_ignore, NSM_Exchange }, /* 2-WayReceived */ + { nsm_ignore, NSM_Exchange }, /* NegotiationDone */ + { nsm_exchange_done, NSM_DependUpon }, /* ExchangeDone */ + { nsm_bad_ls_req, NSM_ExStart }, /* BadLSReq */ + { nsm_ignore, NSM_Exchange }, /* LoadingDone */ + { nsm_adj_ok, NSM_DependUpon }, /* AdjOK? */ + { nsm_seq_number_mismatch, NSM_ExStart }, /* SeqNumberMismatch */ + { nsm_oneway_received, NSM_Init }, /* 1-WayReceived */ + { nsm_kill_nbr, NSM_Down }, /* KillNbr */ + { nsm_inactivity_timer, NSM_Down }, /* InactivityTimer */ + { nsm_ll_down, NSM_Down }, /* LLDown */ + }, + { + /* Loading: */ + { nsm_ignore, NSM_DependUpon }, /* NoEvent */ + { nsm_hello_received, NSM_Loading }, /* HelloReceived */ + { nsm_ignore, NSM_Loading }, /* Start */ + { nsm_ignore, NSM_Loading }, /* 2-WayReceived */ + { nsm_ignore, NSM_Loading }, /* NegotiationDone */ + { nsm_ignore, NSM_Loading }, /* ExchangeDone */ + { nsm_bad_ls_req, NSM_ExStart }, /* BadLSReq */ + { nsm_ignore, NSM_Full }, /* LoadingDone */ + { nsm_adj_ok, NSM_DependUpon }, /* AdjOK? */ + { nsm_seq_number_mismatch, NSM_ExStart }, /* SeqNumberMismatch */ + { nsm_oneway_received, NSM_Init }, /* 1-WayReceived */ + { nsm_kill_nbr, NSM_Down }, /* KillNbr */ + { nsm_inactivity_timer, NSM_Down }, /* InactivityTimer */ + { nsm_ll_down, NSM_Down }, /* LLDown */ + }, + { /* Full: */ + { nsm_ignore, NSM_DependUpon }, /* NoEvent */ + { nsm_hello_received, NSM_Full }, /* HelloReceived */ + { nsm_ignore, NSM_Full }, /* Start */ + { nsm_ignore, NSM_Full }, /* 2-WayReceived */ + { nsm_ignore, NSM_Full }, /* NegotiationDone */ + { nsm_ignore, NSM_Full }, /* ExchangeDone */ + { nsm_bad_ls_req, NSM_ExStart }, /* BadLSReq */ + { nsm_ignore, NSM_Full }, /* LoadingDone */ + { nsm_adj_ok, NSM_DependUpon }, /* AdjOK? */ + { nsm_seq_number_mismatch, NSM_ExStart }, /* SeqNumberMismatch */ + { nsm_oneway_received, NSM_Init }, /* 1-WayReceived */ + { nsm_kill_nbr, NSM_Down }, /* KillNbr */ + { nsm_inactivity_timer, NSM_Down }, /* InactivityTimer */ + { nsm_ll_down, NSM_Down }, /* LLDown */ + }, +}; + +static char *ospf_nsm_event_str[] = +{ + "NoEvent", + "HelloReceived", + "Start", + "2-WayReceived", + "NegotiationDone", + "ExchangeDone", + "BadLSReq", + "LoadingDone", + "AdjOK?", + "SeqNumberMismatch", + "1-WayReceived", + "KillNbr", + "InactivityTimer", + "LLDown", +}; + +void +nsm_change_state (struct ospf_neighbor *nbr, int state) +{ + struct ospf_interface *oi = nbr->oi; + struct ospf_area *vl_area = NULL; + u_char old_state; + int x; + int force = 1; + + /* Logging change of status. */ + if (IS_DEBUG_OSPF (nsm, NSM_STATUS)) + zlog_info ("NSM[%s:%s]: State change %s -> %s", + IF_NAME (nbr->oi), inet_ntoa (nbr->router_id), + LOOKUP (ospf_nsm_state_msg, nbr->state), + LOOKUP (ospf_nsm_state_msg, state)); + + /* Preserve old status. */ + old_state = nbr->state; + + /* Change to new status. */ + nbr->state = state; + + /* Statistics. */ + nbr->state_change++; + + if (oi->type == OSPF_IFTYPE_VIRTUALLINK) + vl_area = ospf_area_lookup_by_area_id (oi->ospf, oi->vl_data->vl_area_id); + + /* One of the neighboring routers changes to/from the FULL state. */ + if ((old_state != NSM_Full && state == NSM_Full) || + (old_state == NSM_Full && state != NSM_Full)) + { + if (state == NSM_Full) + { + oi->full_nbrs++; + oi->area->full_nbrs++; + + ospf_check_abr_status (oi->ospf); + + if (oi->type == OSPF_IFTYPE_VIRTUALLINK && vl_area) + if (++vl_area->full_vls == 1) + ospf_schedule_abr_task (oi->ospf); + + /* kevinm: refresh any redistributions */ + for (x = ZEBRA_ROUTE_SYSTEM; x < ZEBRA_ROUTE_MAX; x++) + { + if (x == ZEBRA_ROUTE_OSPF || x == ZEBRA_ROUTE_OSPF6) + continue; + ospf_external_lsa_refresh_type (oi->ospf, x, force); + } + } + else + { + oi->full_nbrs--; + oi->area->full_nbrs--; + + ospf_check_abr_status (oi->ospf); + + if (oi->type == OSPF_IFTYPE_VIRTUALLINK && vl_area) + if (vl_area->full_vls > 0) + if (--vl_area->full_vls == 0) + ospf_schedule_abr_task (oi->ospf); + + /* clear neighbor retransmit list */ + if (!ospf_ls_retransmit_isempty (nbr)) + ospf_ls_retransmit_clear (nbr); + } + + zlog_info ("nsm_change_state(): " + "scheduling new router-LSA origination"); + + ospf_router_lsa_timer_add (oi->area); + + if (oi->type == OSPF_IFTYPE_VIRTUALLINK) + { + struct ospf_area *vl_area = + ospf_area_lookup_by_area_id (oi->ospf, oi->vl_data->vl_area_id); + + if (vl_area) + ospf_router_lsa_timer_add (vl_area); + } + + /* Originate network-LSA. */ + if (oi->state == ISM_DR) + { + if (oi->network_lsa_self && oi->full_nbrs == 0) + { + ospf_lsa_flush_area (oi->network_lsa_self, oi->area); + ospf_lsa_unlock (oi->network_lsa_self); + oi->network_lsa_self = NULL; + OSPF_TIMER_OFF (oi->t_network_lsa_self); + } + else + ospf_network_lsa_timer_add (oi); + } + } + +#ifdef HAVE_OPAQUE_LSA + ospf_opaque_nsm_change (nbr, old_state); +#endif /* HAVE_OPAQUE_LSA */ + + /* Start DD exchange protocol */ + if (state == NSM_ExStart) + { + if (nbr->dd_seqnum == 0) + nbr->dd_seqnum = time (NULL); + else + nbr->dd_seqnum++; + + nbr->dd_flags = OSPF_DD_FLAG_I|OSPF_DD_FLAG_M|OSPF_DD_FLAG_MS; + ospf_db_desc_send (nbr); + } + + /* clear cryptographic sequence number */ + if (state == NSM_Down) + nbr->crypt_seqnum = 0; + + /* Generete NeighborChange ISM event. */ +#ifdef BUGGY_ISM_TRANSITION + if ((old_state < NSM_TwoWay && state >= NSM_TwoWay) || + (old_state >= NSM_TwoWay && state < NSM_TwoWay)) + OSPF_ISM_EVENT_EXECUTE (oi, ISM_NeighborChange); +#else /* BUGGY_ISM_TRANSITION */ + switch (oi->state) { + case ISM_DROther: + case ISM_Backup: + case ISM_DR: + if ((old_state < NSM_TwoWay && state >= NSM_TwoWay) || + (old_state >= NSM_TwoWay && state < NSM_TwoWay)) + OSPF_ISM_EVENT_EXECUTE (oi, ISM_NeighborChange); + break; + default: + /* ISM_PointToPoint -> ISM_Down, ISM_Loopback -> ISM_Down, etc. */ + break; + } +#endif /* BUGGY_ISM_TRANSITION */ + + /* Performance hack. Send hello immideately when some neighbor enter + Init state. This whay we decrease neighbor discovery time. Gleb.*/ + if (state == NSM_Init) + { + OSPF_ISM_TIMER_OFF (oi->t_hello); + OSPF_ISM_TIMER_ON (oi->t_hello, ospf_hello_timer, 1); + } + + /* Preserve old status? */ +} + +/* Execute NSM event process. */ +int +ospf_nsm_event (struct thread *thread) +{ + int event; + int next_state; + struct ospf_neighbor *nbr; + struct in_addr router_id; + int old_state; + struct ospf_interface *oi; + + nbr = THREAD_ARG (thread); + event = THREAD_VAL (thread); + router_id = nbr->router_id; + + old_state = nbr->state; + oi = nbr->oi ; + + /* Call function. */ + next_state = (*(NSM [nbr->state][event].func))(nbr); + + /* When event is NSM_KillNbr or InactivityTimer, the neighbor is + deleted. */ + if (event == NSM_KillNbr || event == NSM_InactivityTimer) + { + if (IS_DEBUG_OSPF (nsm, NSM_EVENTS)) + zlog_info ("NSM[%s:%s]: neighbor deleted", + IF_NAME (oi), inet_ntoa (router_id)); + + /* Timers are canceled in ospf_nbr_free, moreover we cannot call + nsm_timer_set here because nbr is freed already!!!*/ + /*nsm_timer_set (nbr);*/ + + return 0; + } + + if (! next_state) + next_state = NSM [nbr->state][event].next_state; + + if (IS_DEBUG_OSPF (nsm, NSM_EVENTS)) + zlog_info ("NSM[%s:%s]: %s (%s)", IF_NAME (oi), + inet_ntoa (nbr->router_id), + LOOKUP (ospf_nsm_state_msg, nbr->state), + ospf_nsm_event_str [event]); + + /* If state is changed. */ + if (next_state != nbr->state) + nsm_change_state (nbr, next_state); + + /* Make sure timer is set. */ + nsm_timer_set (nbr); + + return 0; +} + +/* Check loading state. */ +void +ospf_check_nbr_loading (struct ospf_neighbor *nbr) +{ + if (nbr->state == NSM_Loading) + { + if (ospf_ls_request_isempty (nbr)) + OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_LoadingDone); + else if (nbr->ls_req_last == NULL) + ospf_ls_req_event (nbr); + } +} diff --git a/ospfd/ospf_nsm.h b/ospfd/ospf_nsm.h index 6c3dc4dd..3d257305 100644 --- a/ospfd/ospf_nsm.h +++ b/ospfd/ospf_nsm.h @@ -54,28 +54,28 @@ #define OSPF_NSM_EVENT_MAX 14 /* Macro for OSPF NSM timer turn on. */ -#define OSPF_NSM_TIMER_ON(T,F,V) \ - do { \ - if (!(T)) \ - (T) = thread_add_timer (master, (F), nbr, (V)); \ +#define OSPF_NSM_TIMER_ON(T,F,V) \ + do { \ + if (!(T)) \ + (T) = thread_add_timer (master, (F), nbr, (V)); \ } while (0) /* Macro for OSPF NSM timer turn off. */ -#define OSPF_NSM_TIMER_OFF(X) \ - do { \ - if (X) \ - { \ - thread_cancel (X); \ - (X) = NULL; \ - } \ +#define OSPF_NSM_TIMER_OFF(X) \ + do { \ + if (X) \ + { \ + thread_cancel (X); \ + (X) = NULL; \ + } \ } while (0) /* Macro for OSPF NSM schedule event. */ -#define OSPF_NSM_EVENT_SCHEDULE(N,E) \ +#define OSPF_NSM_EVENT_SCHEDULE(N,E) \ thread_add_event (master, ospf_nsm_event, (N), (E)) /* Macro for OSPF NSM execute event. */ -#define OSPF_NSM_EVENT_EXECUTE(N,E) \ +#define OSPF_NSM_EVENT_EXECUTE(N,E) \ thread_execute (master, ospf_nsm_event, (N), (E)) /* Prototypes. */ @@ -85,6 +85,7 @@ void ospf_check_nbr_loading (struct ospf_neighbor *); int ospf_db_summary_isempty (struct ospf_neighbor *); int ospf_db_summary_count (struct ospf_neighbor *); void ospf_db_summary_clear (struct ospf_neighbor *); +/* void ospf_db_summary_delete_all (struct ospf_neighbor *); */ #endif /* _ZEBRA_OSPF_NSM_H */ diff --git a/ospfd/ospf_opaque.c b/ospfd/ospf_opaque.c index 1ce70462..f1fe783c 100644 --- a/ospfd/ospf_opaque.c +++ b/ospfd/ospf_opaque.c @@ -66,6 +66,11 @@ #include "ospfd/ospf_te.h" #endif /* HAVE_OSPF_TE */ +#ifdef SUPPORT_OSPF_API +int ospf_apiserver_init (void); +void ospf_apiserver_term (void); +#endif /* SUPPORT_OSPF_API */ + static void ospf_opaque_register_vty (void); static void ospf_opaque_funclist_init (void); static void ospf_opaque_funclist_term (void); @@ -85,6 +90,11 @@ ospf_opaque_init (void) exit (1); #endif /* HAVE_OSPF_TE */ +#ifdef SUPPORT_OSPF_API + if (ospf_apiserver_init () != 0) + exit (1); +#endif /* SUPPORT_OSPF_API */ + return; } @@ -95,6 +105,10 @@ ospf_opaque_term (void) ospf_mpls_te_term (); #endif /* HAVE_OSPF_TE */ +#ifdef SUPPORT_OSPF_API + ospf_apiserver_term (); +#endif /* SUPPORT_OSPF_API */ + ospf_opaque_funclist_term (); return; } diff --git a/ospfd/ospf_route.c b/ospfd/ospf_route.c index 3733ca55..96f7531f 100644 --- a/ospfd/ospf_route.c +++ b/ospfd/ospf_route.c @@ -206,22 +206,22 @@ ospf_route_delete_uniq (struct route_table *rt, struct route_table *cmprt) /* Install routes to table. */ void -ospf_route_install (struct ospf *ospf, struct route_table *rt) +ospf_route_install (struct route_table *rt) { struct route_node *rn; struct ospf_route *or; /* rt contains new routing table, new_table contains an old one. updating pointers */ - if (ospf->old_table) - ospf_route_table_free (ospf->old_table); - - ospf->old_table = ospf->new_table; - ospf->new_table = rt; + if (ospf_top->old_table) + ospf_route_table_free (ospf_top->old_table); + + ospf_top->old_table = ospf_top->new_table; + ospf_top->new_table = rt; /* Delete old routes. */ - if (ospf->old_table) - ospf_route_delete_uniq (ospf->old_table, rt); + if (ospf_top->old_table) + ospf_route_delete_uniq (ospf_top->old_table, rt); /* Install new routes. */ for (rn = route_top (rt); rn; rn = route_next (rn)) @@ -229,12 +229,12 @@ ospf_route_install (struct ospf *ospf, struct route_table *rt) { if (or->type == OSPF_DESTINATION_NETWORK) { - if (! ospf_route_match_same (ospf->old_table, + if (! ospf_route_match_same (ospf_top->old_table, (struct prefix_ipv4 *)&rn->p, or)) ospf_zebra_add ((struct prefix_ipv4 *) &rn->p, or); } else if (or->type == OSPF_DESTINATION_DISCARD) - if (! ospf_route_match_same (ospf->old_table, + if (! ospf_route_match_same (ospf_top->old_table, (struct prefix_ipv4 *) &rn->p, or)) ospf_zebra_add_discard ((struct prefix_ipv4 *) &rn->p); } @@ -595,7 +595,7 @@ ospf_intra_add_stub (struct route_table *rt, struct router_lsa_link *link, if (IS_DEBUG_OSPF_EVENT) zlog_info ("ospf_intra_add_stub(): this network is on this router"); - if ((oi = ospf_if_lookup_by_prefix (area->ospf, &p))) + if ((oi = ospf_if_lookup_by_prefix (&p))) { if (IS_DEBUG_OSPF_EVENT) zlog_info ("ospf_intra_add_stub(): the interface is %s", @@ -676,15 +676,12 @@ ospf_route_table_dump (struct route_table *rt) void ospf_terminate () { - struct ospf *ospf; - listnode node; - - LIST_LOOP (om->ospf, ospf, node) + if (ospf_top) { - if (ospf->new_table) - ospf_route_delete (ospf->new_table); - if (ospf->old_external_route) - ospf_route_delete (ospf->old_external_route); + if (ospf_top->new_table) + ospf_route_delete (ospf_top->new_table); + if (ospf_top->old_external_route) + ospf_route_delete (ospf_top->old_external_route); } } @@ -693,8 +690,7 @@ ospf_terminate () o The other paths, intra-area backbone paths and inter-area paths, are of equal preference. */ int -ospf_asbr_route_cmp (struct ospf *ospf, struct ospf_route *r1, - struct ospf_route *r2) +ospf_asbr_route_cmp (struct ospf_route *r1, struct ospf_route *r2) { u_char r1_type, r2_type; @@ -702,7 +698,7 @@ ospf_asbr_route_cmp (struct ospf *ospf, struct ospf_route *r1, r2_type = r2->path_type; /* If RFC1583Compat flag is on -- all paths are equal. */ - if (CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE)) + if (CHECK_FLAG (ospf_top->config, OSPF_RFC1583_COMPATIBLE)) return 0; /* r1/r2 itself is backbone, and it's Inter-area path. */ @@ -719,8 +715,7 @@ ospf_asbr_route_cmp (struct ospf *ospf, struct ospf_route *r1, ret == 0 -- r1 and r2 are the same. ret > 0 -- r2 is better. */ int -ospf_route_cmp (struct ospf *ospf, struct ospf_route *r1, - struct ospf_route *r2) +ospf_route_cmp (struct ospf_route *r1, struct ospf_route *r2) { int ret = 0; @@ -737,9 +732,9 @@ ospf_route_cmp (struct ospf *ospf, struct ospf_route *r1, case OSPF_PATH_INTER_AREA: break; case OSPF_PATH_TYPE1_EXTERNAL: - if (!CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE)) + if (!CHECK_FLAG (ospf_top->config, OSPF_RFC1583_COMPATIBLE)) { - ret = ospf_asbr_route_cmp (ospf, r1->u.ext.asbr, r2->u.ext.asbr); + ret = ospf_asbr_route_cmp (r1->u.ext.asbr, r2->u.ext.asbr); if (ret != 0) return ret; } @@ -748,9 +743,9 @@ ospf_route_cmp (struct ospf *ospf, struct ospf_route *r1, if ((ret = (r1->u.ext.type2_cost - r2->u.ext.type2_cost))) return ret; - if (!CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE)) + if (!CHECK_FLAG (ospf_top->config, OSPF_RFC1583_COMPATIBLE)) { - ret = ospf_asbr_route_cmp (ospf, r1->u.ext.asbr, r2->u.ext.asbr); + ret = ospf_asbr_route_cmp (r1->u.ext.asbr, r2->u.ext.asbr); if (ret != 0) return ret; } diff --git a/ospfd/ospf_route.h b/ospfd/ospf_route.h index 4222f528..81f59c48 100644 --- a/ospfd/ospf_route.h +++ b/ospfd/ospf_route.h @@ -124,14 +124,14 @@ struct ospf_route }; struct ospf_path *ospf_path_new (); -void ospf_path_free (struct ospf_path *); +void ospf_path_free (struct ospf_path *op); struct ospf_path *ospf_path_lookup (list, struct ospf_path *); struct ospf_route *ospf_route_new (); -void ospf_route_free (struct ospf_route *); -void ospf_route_delete (struct route_table *); -void ospf_route_table_free (struct route_table *); +void ospf_route_free (struct ospf_route *or); +void ospf_route_delete (struct route_table *rt); +void ospf_route_table_free (struct route_table *rt); -void ospf_route_install (struct ospf *, struct route_table *); +void ospf_route_install (struct route_table *); void ospf_route_table_dump (struct route_table *); void ospf_intra_add_router (struct route_table *, struct vertex *, @@ -143,7 +143,7 @@ void ospf_intra_add_transit (struct route_table *, struct vertex *, void ospf_intra_add_stub (struct route_table *, struct router_lsa_link *, struct vertex *, struct ospf_area *); -int ospf_route_cmp (struct ospf *, struct ospf_route *, struct ospf_route *); +int ospf_route_cmp (struct ospf_route *, struct ospf_route *); void ospf_route_copy_nexthops (struct ospf_route *, list); void ospf_route_copy_nexthops_from_vertex (struct ospf_route *, struct vertex * ); diff --git a/ospfd/ospf_routemap.c b/ospfd/ospf_routemap.c index 017acb2b..64822d61 100644 --- a/ospfd/ospf_routemap.c +++ b/ospfd/ospf_routemap.c @@ -756,8 +756,8 @@ DEFUN (set_metric_type, "set metric-type (type-1|type-2)", SET_STR "Type of metric for destination routing protocol\n" - "OSPF external type 1 metric\n" - "OSPF external type 2 metric\n") + "OSPF[6] external type 1 metric\n" + "OSPF[6] external type 2 metric\n") { if (strcmp (argv[0], "1") == 0) return ospf_route_set_add (vty, vty->index, "metric-type", "type-1"); @@ -786,8 +786,8 @@ ALIAS (no_set_metric_type, NO_STR SET_STR "Type of metric for destination routing protocol\n" - "OSPF external type 1 metric\n" - "OSPF external type 2 metric\n") + "OSPF[6] external type 1 metric\n" + "OSPF[6] external type 2 metric\n") /* Route-map init */ void diff --git a/ospfd/ospf_snmp.c b/ospfd/ospf_snmp.c index 0fe9cae6..2e1a9b3c 100644 --- a/ospfd/ospf_snmp.c +++ b/ospfd/ospf_snmp.c @@ -24,6 +24,9 @@ #include <zebra.h> #ifdef HAVE_SNMP +#ifdef HAVE_NETSNMP +#include <net-snmp/net-snmp-config.h> +#endif #include <asn1.h> #include <snmp.h> #include <snmp_impl.h> @@ -1437,7 +1440,7 @@ ospf_snmp_if_update (struct interface *ifp) /* Lookup first IPv4 address entry. */ LIST_LOOP (ifp->connected, ifc, nn) { - if (if_is_pointopoint (ifp)) + if (ifc_pointopoint (ifc)) p = ifc->destination; else p = ifc->address; diff --git a/ospfd/ospf_spf.c b/ospfd/ospf_spf.c index 412e44d7..33616d83 100644 --- a/ospfd/ospf_spf.c +++ b/ospfd/ospf_spf.c @@ -372,7 +372,6 @@ ospf_nexthop_calculation (struct ospf_area *area, { struct prefix_ipv4 la; la.prefixlen = oi->address->prefixlen; - /* We link to them on PtMP interface - find the interface on w */ while ((l2 = ospf_get_next_link (w, v, l2))) diff --git a/ospfd/ospf_spf.h b/ospfd/ospf_spf.h index e71224bd..7fe682ee 100644 --- a/ospfd/ospf_spf.h +++ b/ospfd/ospf_spf.h @@ -44,7 +44,7 @@ struct vertex_nexthop struct vertex *parent; }; -void ospf_spf_calculate_schedule (struct ospf *); +void ospf_spf_calculate_schedule (); void ospf_rtrs_free (struct route_table *); /* void ospf_spf_calculate_timer_add (); */ diff --git a/ospfd/ospf_te.c b/ospfd/ospf_te.c index 2129e354..aedac32a 100644 --- a/ospfd/ospf_te.c +++ b/ospfd/ospf_te.c @@ -414,8 +414,8 @@ set_linkparams_link_id (struct ospf_interface *oi, struct mpls_te_link *lp) { case OSPF_IFTYPE_POINTOPOINT: /* Take the router ID of the neighbor. */ - if ((nbr = ospf_nbr_lookup_ptop (oi)) - && nbr->state == NSM_Full) + if (((nbr = ospf_nbr_lookup_ptop (oi->nbrs, oi->area->top->router_id))) + && (nbr->state == NSM_Full)) { lp->link_id.value = nbr->router_id; done = 1; @@ -429,7 +429,7 @@ set_linkparams_link_id (struct ospf_interface *oi, struct mpls_te_link *lp) if (nbr->state == NSM_Full || (IPV4_ADDR_SAME (&oi->address->u.prefix4, &DR (oi)) - && ospf_nbr_count (oi, NSM_Full) > 0)) + && ospf_nbr_count (oi->nbrs, NSM_Full) > 0)) { lp->link_id.value = DR (oi); done = 1; @@ -628,7 +628,7 @@ ospf_mpls_te_ism_change (struct ospf_interface *oi, int old_state) zlog_warn ("ospf_mpls_te_ism_change: Cannot get linkparams from OI(%s)?", IF_NAME (oi)); goto out; } - if (oi->area == NULL || oi->area->ospf == NULL) + if (oi->area == NULL || oi->area->top == NULL) { zlog_warn ("ospf_mpls_te_ism_change: Cannot refer to OSPF from OI(%s)?", IF_NAME (oi)); @@ -891,7 +891,7 @@ ospf_mpls_te_lsa_new (struct ospf_area *area, struct mpls_te_link *lp) zlog_info ("LSA[Type%d:%s]: Create an Opaque-LSA/MPLS-TE instance", lsa_type, inet_ntoa (lsa_id)); /* Set opaque-LSA header fields. */ - lsa_header_set (s, options, lsa_type, lsa_id, area->ospf->router_id); + lsa_header_set (s, options, lsa_type, lsa_id); /* Set opaque-LSA body fields. */ ospf_mpls_te_lsa_body_set (s, lp); @@ -939,7 +939,7 @@ ospf_mpls_te_lsa_originate1 (struct ospf_area *area, struct mpls_te_link *lp) } /* Install this LSA into LSDB. */ - if (ospf_lsa_install (area->ospf, NULL/*oi*/, new) == NULL) + if (ospf_lsa_install (NULL/*oi*/, new) == NULL) { zlog_warn ("ospf_mpls_te_lsa_originate1: ospf_lsa_install() ?"); ospf_lsa_free (new); @@ -950,7 +950,7 @@ ospf_mpls_te_lsa_originate1 (struct ospf_area *area, struct mpls_te_link *lp) lp->flags |= LPFLG_LSA_ENGAGED; /* Update new LSA origination count. */ - area->ospf->lsa_originate_count++; + area->top->lsa_originate_count++; /* Flood new LSA through area. */ ospf_flood_through_area (area, NULL/*nbr*/, new); @@ -1059,7 +1059,7 @@ ospf_mpls_te_lsa_refresh (struct ospf_lsa *lsa) /* Install this LSA into LSDB. */ /* Given "lsa" will be freed in the next function. */ - if (ospf_lsa_install (area->ospf, NULL/*oi*/, new) == NULL) + if (ospf_lsa_install (NULL/*oi*/, new) == NULL) { zlog_warn ("ospf_mpls_te_lsa_refresh: ospf_lsa_install() ?"); ospf_lsa_free (new); diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 4896d352..ed4b4fd1 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -223,7 +223,7 @@ DEFUN (ospf_router_id, } ALIAS (ospf_router_id, - router_id_cmd, + router_ospf_id_cmd, "router-id A.B.C.D", "router-id for the OSPF process\n" "OSPF router-id in IP address format\n") @@ -245,13 +245,13 @@ DEFUN (no_ospf_router_id, } ALIAS (no_ospf_router_id, - no_router_id_cmd, + no_router_ospf_id_cmd, "no router-id", NO_STR "router-id for the OSPF process\n") -DEFUN (passive_interface, - passive_interface_addr_cmd, +DEFUN (ospf_passive_interface, + ospf_passive_interface_addr_cmd, "passive-interface IFNAME A.B.C.D", "Suppress routing updates on an interface\n" "Interface's name\n") @@ -291,14 +291,14 @@ DEFUN (passive_interface, return CMD_SUCCESS; } -ALIAS (passive_interface, - passive_interface_cmd, +ALIAS (ospf_passive_interface, + ospf_passive_interface_cmd, "passive-interface IFNAME", "Suppress routing updates on an interface\n" "Interface's name\n") -DEFUN (no_passive_interface, - no_passive_interface_addr_cmd, +DEFUN (no_ospf_passive_interface, + no_ospf_passive_interface_addr_cmd, "no passive-interface IFNAME A.B.C.D", NO_STR "Allow routing updates on an interface\n" @@ -346,15 +346,15 @@ DEFUN (no_passive_interface, return CMD_SUCCESS; } -ALIAS (no_passive_interface, - no_passive_interface_cmd, +ALIAS (no_ospf_passive_interface, + no_ospf_passive_interface_cmd, "no passive-interface IFNAME", NO_STR "Allow routing updates on an interface\n" "Interface's name\n") -DEFUN (network_area, - network_area_cmd, +DEFUN (ospf_network_area, + ospf_network_area_cmd, "network A.B.C.D/M area (A.B.C.D|<0-4294967295>)", "Enable routing on an IP network\n" "OSPF network prefix\n" @@ -381,8 +381,8 @@ DEFUN (network_area, return CMD_SUCCESS; } -DEFUN (no_network_area, - no_network_area_cmd, +DEFUN (no_ospf_network_area, + no_ospf_network_area_cmd, "no network A.B.C.D/M area (A.B.C.D|<0-4294967295>)", NO_STR "Enable routing on an IP network\n" @@ -412,8 +412,8 @@ DEFUN (no_network_area, } -DEFUN (area_range, - area_range_cmd, +DEFUN (ospf_area_range, + ospf_area_range_cmd, "area (A.B.C.D|<0-4294967295>) range A.B.C.D/M", "OSPF area parameters\n" "OSPF area ID in IP address format\n" @@ -440,8 +440,8 @@ DEFUN (area_range, return CMD_SUCCESS; } -ALIAS (area_range, - area_range_advertise_cmd, +ALIAS (ospf_area_range, + ospf_area_range_advertise_cmd, "area (A.B.C.D|<0-4294967295>) range A.B.C.D/M advertise", "OSPF area parameters\n" "OSPF area ID in IP address format\n" @@ -450,8 +450,8 @@ ALIAS (area_range, "Area range prefix\n" "Advertise this range (default)\n") -ALIAS (area_range, - area_range_cost_cmd, +ALIAS (ospf_area_range, + ospf_area_range_cost_cmd, "area (A.B.C.D|<0-4294967295>) range A.B.C.D/M cost <0-16777215>", "OSPF area parameters\n" "OSPF area ID in IP address format\n" @@ -461,8 +461,8 @@ ALIAS (area_range, "User specified metric for this range\n" "Advertised metric for this range\n") -ALIAS (area_range, - area_range_advertise_cost_cmd, +ALIAS (ospf_area_range, + ospf_area_range_advertise_cost_cmd, "area (A.B.C.D|<0-4294967295>) range A.B.C.D/M advertise cost <0-16777215>", "OSPF area parameters\n" "OSPF area ID in IP address format\n" @@ -473,8 +473,8 @@ ALIAS (area_range, "User specified metric for this range\n" "Advertised metric for this range\n") -DEFUN (area_range_not_advertise, - area_range_not_advertise_cmd, +DEFUN (ospf_area_range_not_advertise, + ospf_area_range_not_advertise_cmd, "area (A.B.C.D|<0-4294967295>) range A.B.C.D/M not-advertise", "OSPF area parameters\n" "OSPF area ID in IP address format\n" @@ -496,8 +496,8 @@ DEFUN (area_range_not_advertise, return CMD_SUCCESS; } -DEFUN (no_area_range, - no_area_range_cmd, +DEFUN (no_ospf_area_range, + no_ospf_area_range_cmd, "no area (A.B.C.D|<0-4294967295>) range A.B.C.D/M", NO_STR "OSPF area parameters\n" @@ -519,8 +519,8 @@ DEFUN (no_area_range, return CMD_SUCCESS; } -ALIAS (no_area_range, - no_area_range_advertise_cmd, +ALIAS (no_ospf_area_range, + no_ospf_area_range_advertise_cmd, "no area (A.B.C.D|<0-4294967295>) range A.B.C.D/M (advertise|not-advertise)", NO_STR "OSPF area parameters\n" @@ -531,8 +531,8 @@ ALIAS (no_area_range, "Advertise this range (default)\n" "DoNotAdvertise this range\n") -ALIAS (no_area_range, - no_area_range_cost_cmd, +ALIAS (no_ospf_area_range, + no_ospf_area_range_cost_cmd, "no area (A.B.C.D|<0-4294967295>) range A.B.C.D/M cost <0-16777215>", NO_STR "OSPF area parameters\n" @@ -543,8 +543,8 @@ ALIAS (no_area_range, "User specified metric for this range\n" "Advertised metric for this range\n") -ALIAS (no_area_range, - no_area_range_advertise_cost_cmd, +ALIAS (no_ospf_area_range, + no_ospf_area_range_advertise_cost_cmd, "no area (A.B.C.D|<0-4294967295>) range A.B.C.D/M advertise cost <0-16777215>", NO_STR "OSPF area parameters\n" @@ -556,8 +556,8 @@ ALIAS (no_area_range, "User specified metric for this range\n" "Advertised metric for this range\n") -DEFUN (area_range_substitute, - area_range_substitute_cmd, +DEFUN (ospf_area_range_substitute, + ospf_area_range_substitute_cmd, "area (A.B.C.D|<0-4294967295>) range A.B.C.D/M substitute A.B.C.D/M", "OSPF area parameters\n" "OSPF area ID in IP address format\n" @@ -581,8 +581,8 @@ DEFUN (area_range_substitute, return CMD_SUCCESS; } -DEFUN (no_area_range_substitute, - no_area_range_substitute_cmd, +DEFUN (no_ospf_area_range_substitute, + no_ospf_area_range_substitute_cmd, "no area (A.B.C.D|<0-4294967295>) range A.B.C.D/M substitute A.B.C.D/M", NO_STR "OSPF area parameters\n" @@ -871,8 +871,8 @@ ospf_vl_set (struct ospf *ospf, struct ospf_vl_config_data *vl_config) "Use MD5 algorithm\n" \ "The OSPF password (key)" -DEFUN (area_vlink, - area_vlink_cmd, +DEFUN (ospf_area_vlink, + ospf_area_vlink_cmd, "area (A.B.C.D|<0-4294967295>) virtual-link A.B.C.D", VLINK_HELPSTR_IPADDR) { @@ -1005,8 +1005,8 @@ DEFUN (area_vlink, } -DEFUN (no_area_vlink, - no_area_vlink_cmd, +DEFUN (no_ospf_area_vlink, + no_ospf_area_vlink_cmd, "no area (A.B.C.D|<0-4294967295>) virtual-link A.B.C.D", NO_STR VLINK_HELPSTR_IPADDR) @@ -1121,23 +1121,23 @@ DEFUN (no_area_vlink, return ospf_vl_set (ospf, &vl_config); } -ALIAS (area_vlink, - area_vlink_param1_cmd, +ALIAS (ospf_area_vlink, + ospf_area_vlink_param1_cmd, "area (A.B.C.D|<0-4294967295>) virtual-link A.B.C.D " "(hello-interval|retransmit-interval|transmit-delay|dead-interval) <1-65535>", VLINK_HELPSTR_IPADDR VLINK_HELPSTR_TIME_PARAM) -ALIAS (no_area_vlink, - no_area_vlink_param1_cmd, +ALIAS (no_ospf_area_vlink, + no_ospf_area_vlink_param1_cmd, "no area (A.B.C.D|<0-4294967295>) virtual-link A.B.C.D " "(hello-interval|retransmit-interval|transmit-delay|dead-interval)", NO_STR VLINK_HELPSTR_IPADDR VLINK_HELPSTR_TIME_PARAM) -ALIAS (area_vlink, - area_vlink_param2_cmd, +ALIAS (ospf_area_vlink, + ospf_area_vlink_param2_cmd, "area (A.B.C.D|<0-4294967295>) virtual-link A.B.C.D " "(hello-interval|retransmit-interval|transmit-delay|dead-interval) <1-65535> " "(hello-interval|retransmit-interval|transmit-delay|dead-interval) <1-65535>", @@ -1145,8 +1145,8 @@ ALIAS (area_vlink, VLINK_HELPSTR_TIME_PARAM VLINK_HELPSTR_TIME_PARAM) -ALIAS (no_area_vlink, - no_area_vlink_param2_cmd, +ALIAS (no_ospf_area_vlink, + no_ospf_area_vlink_param2_cmd, "no area (A.B.C.D|<0-4294967295>) virtual-link A.B.C.D " "(hello-interval|retransmit-interval|transmit-delay|dead-interval) " "(hello-interval|retransmit-interval|transmit-delay|dead-interval)", @@ -1155,8 +1155,8 @@ ALIAS (no_area_vlink, VLINK_HELPSTR_TIME_PARAM VLINK_HELPSTR_TIME_PARAM) -ALIAS (area_vlink, - area_vlink_param3_cmd, +ALIAS (ospf_area_vlink, + ospf_area_vlink_param3_cmd, "area (A.B.C.D|<0-4294967295>) virtual-link A.B.C.D " "(hello-interval|retransmit-interval|transmit-delay|dead-interval) <1-65535> " "(hello-interval|retransmit-interval|transmit-delay|dead-interval) <1-65535> " @@ -1166,8 +1166,8 @@ ALIAS (area_vlink, VLINK_HELPSTR_TIME_PARAM VLINK_HELPSTR_TIME_PARAM) -ALIAS (no_area_vlink, - no_area_vlink_param3_cmd, +ALIAS (no_ospf_area_vlink, + no_ospf_area_vlink_param3_cmd, "no area (A.B.C.D|<0-4294967295>) virtual-link A.B.C.D " "(hello-interval|retransmit-interval|transmit-delay|dead-interval) " "(hello-interval|retransmit-interval|transmit-delay|dead-interval) " @@ -1178,8 +1178,8 @@ ALIAS (no_area_vlink, VLINK_HELPSTR_TIME_PARAM VLINK_HELPSTR_TIME_PARAM) -ALIAS (area_vlink, - area_vlink_param4_cmd, +ALIAS (ospf_area_vlink, + ospf_area_vlink_param4_cmd, "area (A.B.C.D|<0-4294967295>) virtual-link A.B.C.D " "(hello-interval|retransmit-interval|transmit-delay|dead-interval) <1-65535> " "(hello-interval|retransmit-interval|transmit-delay|dead-interval) <1-65535> " @@ -1191,8 +1191,8 @@ ALIAS (area_vlink, VLINK_HELPSTR_TIME_PARAM VLINK_HELPSTR_TIME_PARAM) -ALIAS (no_area_vlink, - no_area_vlink_param4_cmd, +ALIAS (no_ospf_area_vlink, + no_ospf_area_vlink_param4_cmd, "no area (A.B.C.D|<0-4294967295>) virtual-link A.B.C.D " "(hello-interval|retransmit-interval|transmit-delay|dead-interval) " "(hello-interval|retransmit-interval|transmit-delay|dead-interval) " @@ -1205,60 +1205,60 @@ ALIAS (no_area_vlink, VLINK_HELPSTR_TIME_PARAM VLINK_HELPSTR_TIME_PARAM) -ALIAS (area_vlink, - area_vlink_authtype_args_cmd, +ALIAS (ospf_area_vlink, + ospf_area_vlink_authtype_args_cmd, "area (A.B.C.D|<0-4294967295>) virtual-link A.B.C.D " "(authentication|) (message-digest|null)", VLINK_HELPSTR_IPADDR VLINK_HELPSTR_AUTHTYPE_ALL) -ALIAS (area_vlink, - area_vlink_authtype_cmd, +ALIAS (ospf_area_vlink, + ospf_area_vlink_authtype_cmd, "area (A.B.C.D|<0-4294967295>) virtual-link A.B.C.D " "(authentication|)", VLINK_HELPSTR_IPADDR VLINK_HELPSTR_AUTHTYPE_SIMPLE) -ALIAS (no_area_vlink, - no_area_vlink_authtype_cmd, +ALIAS (no_ospf_area_vlink, + no_ospf_area_vlink_authtype_cmd, "no area (A.B.C.D|<0-4294967295>) virtual-link A.B.C.D " "(authentication|)", NO_STR VLINK_HELPSTR_IPADDR VLINK_HELPSTR_AUTHTYPE_SIMPLE) -ALIAS (area_vlink, - area_vlink_md5_cmd, +ALIAS (ospf_area_vlink, + ospf_area_vlink_md5_cmd, "area (A.B.C.D|<0-4294967295>) virtual-link A.B.C.D " "(message-digest-key|) <1-255> md5 KEY", VLINK_HELPSTR_IPADDR VLINK_HELPSTR_AUTH_MD5) -ALIAS (no_area_vlink, - no_area_vlink_md5_cmd, +ALIAS (no_ospf_area_vlink, + no_ospf_area_vlink_md5_cmd, "no area (A.B.C.D|<0-4294967295>) virtual-link A.B.C.D " "(message-digest-key|) <1-255>", NO_STR VLINK_HELPSTR_IPADDR VLINK_HELPSTR_AUTH_MD5) -ALIAS (area_vlink, - area_vlink_authkey_cmd, +ALIAS (ospf_area_vlink, + ospf_area_vlink_authkey_cmd, "area (A.B.C.D|<0-4294967295>) virtual-link A.B.C.D " "(authentication-key|) AUTH_KEY", VLINK_HELPSTR_IPADDR VLINK_HELPSTR_AUTH_SIMPLE) -ALIAS (no_area_vlink, - no_area_vlink_authkey_cmd, +ALIAS (no_ospf_area_vlink, + no_ospf_area_vlink_authkey_cmd, "no area (A.B.C.D|<0-4294967295>) virtual-link A.B.C.D " "(authentication-key|)", NO_STR VLINK_HELPSTR_IPADDR VLINK_HELPSTR_AUTH_SIMPLE) -ALIAS (area_vlink, - area_vlink_authtype_args_authkey_cmd, +ALIAS (ospf_area_vlink, + ospf_area_vlink_authtype_args_authkey_cmd, "area (A.B.C.D|<0-4294967295>) virtual-link A.B.C.D " "(authentication|) (message-digest|null) " "(authentication-key|) AUTH_KEY", @@ -1266,8 +1266,8 @@ ALIAS (area_vlink, VLINK_HELPSTR_AUTHTYPE_ALL VLINK_HELPSTR_AUTH_SIMPLE) -ALIAS (area_vlink, - area_vlink_authtype_authkey_cmd, +ALIAS (ospf_area_vlink, + ospf_area_vlink_authtype_authkey_cmd, "area (A.B.C.D|<0-4294967295>) virtual-link A.B.C.D " "(authentication|) " "(authentication-key|) AUTH_KEY", @@ -1275,8 +1275,8 @@ ALIAS (area_vlink, VLINK_HELPSTR_AUTHTYPE_SIMPLE VLINK_HELPSTR_AUTH_SIMPLE) -ALIAS (no_area_vlink, - no_area_vlink_authtype_authkey_cmd, +ALIAS (no_ospf_area_vlink, + no_ospf_area_vlink_authtype_authkey_cmd, "no area (A.B.C.D|<0-4294967295>) virtual-link A.B.C.D " "(authentication|) " "(authentication-key|)", @@ -1285,8 +1285,8 @@ ALIAS (no_area_vlink, VLINK_HELPSTR_AUTHTYPE_SIMPLE VLINK_HELPSTR_AUTH_SIMPLE) -ALIAS (area_vlink, - area_vlink_authtype_args_md5_cmd, +ALIAS (ospf_area_vlink, + ospf_area_vlink_authtype_args_md5_cmd, "area (A.B.C.D|<0-4294967295>) virtual-link A.B.C.D " "(authentication|) (message-digest|null) " "(message-digest-key|) <1-255> md5 KEY", @@ -1294,8 +1294,8 @@ ALIAS (area_vlink, VLINK_HELPSTR_AUTHTYPE_ALL VLINK_HELPSTR_AUTH_MD5) -ALIAS (area_vlink, - area_vlink_authtype_md5_cmd, +ALIAS (ospf_area_vlink, + ospf_area_vlink_authtype_md5_cmd, "area (A.B.C.D|<0-4294967295>) virtual-link A.B.C.D " "(authentication|) " "(message-digest-key|) <1-255> md5 KEY", @@ -1303,8 +1303,8 @@ ALIAS (area_vlink, VLINK_HELPSTR_AUTHTYPE_SIMPLE VLINK_HELPSTR_AUTH_MD5) -ALIAS (no_area_vlink, - no_area_vlink_authtype_md5_cmd, +ALIAS (no_ospf_area_vlink, + no_ospf_area_vlink_authtype_md5_cmd, "no area (A.B.C.D|<0-4294967295>) virtual-link A.B.C.D " "(authentication|) " "(message-digest-key|)", @@ -1314,8 +1314,8 @@ ALIAS (no_area_vlink, VLINK_HELPSTR_AUTH_MD5) -DEFUN (area_shortcut, - area_shortcut_cmd, +DEFUN (ospf_area_shortcut, + ospf_area_shortcut_cmd, "area (A.B.C.D|<0-4294967295>) shortcut (default|enable|disable)", "OSPF area parameters\n" "OSPF area ID in IP address format\n" @@ -1354,8 +1354,8 @@ DEFUN (area_shortcut, return CMD_SUCCESS; } -DEFUN (no_area_shortcut, - no_area_shortcut_cmd, +DEFUN (no_ospf_area_shortcut, + no_ospf_area_shortcut_cmd, "no area (A.B.C.D|<0-4294967295>) shortcut (enable|disable)", NO_STR "OSPF area parameters\n" @@ -1382,8 +1382,8 @@ DEFUN (no_area_shortcut, } -DEFUN (area_stub, - area_stub_cmd, +DEFUN (ospf_area_stub, + ospf_area_stub_cmd, "area (A.B.C.D|<0-4294967295>) stub", "OSPF area parameters\n" "OSPF area ID in IP address format\n" @@ -1409,8 +1409,8 @@ DEFUN (area_stub, return CMD_SUCCESS; } -DEFUN (area_stub_no_summary, - area_stub_no_summary_cmd, +DEFUN (ospf_area_stub_no_summary, + ospf_area_stub_no_summary_cmd, "area (A.B.C.D|<0-4294967295>) stub no-summary", "OSPF stub parameters\n" "OSPF area ID in IP address format\n" @@ -1437,8 +1437,8 @@ DEFUN (area_stub_no_summary, return CMD_SUCCESS; } -DEFUN (no_area_stub, - no_area_stub_cmd, +DEFUN (no_ospf_area_stub, + no_ospf_area_stub_cmd, "no area (A.B.C.D|<0-4294967295>) stub", NO_STR "OSPF area parameters\n" @@ -1458,8 +1458,8 @@ DEFUN (no_area_stub, return CMD_SUCCESS; } -DEFUN (no_area_stub_no_summary, - no_area_stub_no_summary_cmd, +DEFUN (no_ospf_area_stub_no_summary, + no_ospf_area_stub_no_summary_cmd, "no area (A.B.C.D|<0-4294967295>) stub no-summary", NO_STR "OSPF area parameters\n" @@ -1479,8 +1479,8 @@ DEFUN (no_area_stub_no_summary, } #ifdef HAVE_NSSA -DEFUN (area_nssa, - area_nssa_cmd, +DEFUN (ospf_area_nssa, + ospf_area_nssa_cmd, "area (A.B.C.D|<0-4294967295>) nssa", "OSPF area parameters\n" "OSPF area ID in IP address format\n" @@ -1520,8 +1520,8 @@ DEFUN (area_nssa, return CMD_SUCCESS; } -ALIAS (area_nssa, - area_nssa_translate_no_summary_cmd, +ALIAS (ospf_area_nssa, + ospf_area_nssa_translate_no_summary_cmd, "area (A.B.C.D|<0-4294967295>) nssa (translate-candidate|translate-never|translate-always) (no-summary|)", "OSPF area parameters\n" "OSPF area ID in IP address format\n" @@ -1533,8 +1533,8 @@ ALIAS (area_nssa, "Do not inject inter-area routes into nssa\n" "dummy\n") -ALIAS (area_nssa, - area_nssa_translate_cmd, +ALIAS (ospf_area_nssa, + ospf_area_nssa_translate_cmd, "area (A.B.C.D|<0-4294967295>) nssa (translate-candidate|translate-never|translate-always)", "OSPF area parameters\n" "OSPF area ID in IP address format\n" @@ -1544,8 +1544,8 @@ ALIAS (area_nssa, "Configure NSSA-ABR to never translate\n" "Configure NSSA-ABR to always translate\n") -DEFUN (area_nssa_no_summary, - area_nssa_no_summary_cmd, +DEFUN (ospf_area_nssa_no_summary, + ospf_area_nssa_no_summary_cmd, "area (A.B.C.D|<0-4294967295>) nssa no-summary", "OSPF area parameters\n" "OSPF area ID in IP address format\n" @@ -1572,8 +1572,8 @@ DEFUN (area_nssa_no_summary, return CMD_SUCCESS; } -DEFUN (no_area_nssa, - no_area_nssa_cmd, +DEFUN (no_ospf_area_nssa, + no_ospf_area_nssa_cmd, "no area (A.B.C.D|<0-4294967295>) nssa", NO_STR "OSPF area parameters\n" @@ -1593,8 +1593,8 @@ DEFUN (no_area_nssa, return CMD_SUCCESS; } -DEFUN (no_area_nssa_no_summary, - no_area_nssa_no_summary_cmd, +DEFUN (no_ospf_area_nssa_no_summary, + no_ospf_area_nssa_no_summary_cmd, "no area (A.B.C.D|<0-4294967295>) nssa no-summary", NO_STR "OSPF area parameters\n" @@ -1615,8 +1615,8 @@ DEFUN (no_area_nssa_no_summary, #endif /* HAVE_NSSA */ -DEFUN (area_default_cost, - area_default_cost_cmd, +DEFUN (ospf_area_default_cost, + ospf_area_default_cost_cmd, "area (A.B.C.D|<0-4294967295>) default-cost <0-16777215>", "OSPF area parameters\n" "OSPF area ID in IP address format\n" @@ -1646,8 +1646,8 @@ DEFUN (area_default_cost, return CMD_SUCCESS; } -DEFUN (no_area_default_cost, - no_area_default_cost_cmd, +DEFUN (no_ospf_area_default_cost, + no_ospf_area_default_cost_cmd, "no area (A.B.C.D|<0-4294967295>) default-cost <0-16777215>", NO_STR "OSPF area parameters\n" @@ -1682,8 +1682,8 @@ DEFUN (no_area_default_cost, return CMD_SUCCESS; } -DEFUN (area_export_list, - area_export_list_cmd, +DEFUN (ospf_area_export_list, + ospf_area_export_list_cmd, "area (A.B.C.D|<0-4294967295>) export-list NAME", "OSPF area parameters\n" "OSPF area ID in IP address format\n" @@ -1704,8 +1704,8 @@ DEFUN (area_export_list, return CMD_SUCCESS; } -DEFUN (no_area_export_list, - no_area_export_list_cmd, +DEFUN (no_ospf_area_export_list, + no_ospf_area_export_list_cmd, "no area (A.B.C.D|<0-4294967295>) export-list NAME", NO_STR "OSPF area parameters\n" @@ -1731,8 +1731,8 @@ DEFUN (no_area_export_list, } -DEFUN (area_import_list, - area_import_list_cmd, +DEFUN (ospf_area_import_list, + ospf_area_import_list_cmd, "area (A.B.C.D|<0-4294967295>) import-list NAME", "OSPF area parameters\n" "OSPF area ID in IP address format\n" @@ -1753,8 +1753,8 @@ DEFUN (area_import_list, return CMD_SUCCESS; } -DEFUN (no_area_import_list, - no_area_import_list_cmd, +DEFUN (no_ospf_area_import_list, + no_ospf_area_import_list_cmd, "no area (A.B.C.D|<0-4294967295>) import-list NAME", NO_STR "OSPF area parameters\n" @@ -1778,8 +1778,8 @@ DEFUN (no_area_import_list, return CMD_SUCCESS; } -DEFUN (area_filter_list, - area_filter_list_cmd, +DEFUN (ospf_area_filter_list, + ospf_area_filter_list_cmd, "area (A.B.C.D|<0-4294967295>) filter-list prefix WORD (in|out)", "OSPF area parameters\n" "OSPF area ID in IP address format\n" @@ -1822,8 +1822,8 @@ DEFUN (area_filter_list, return CMD_SUCCESS; } -DEFUN (no_area_filter_list, - no_area_filter_list_cmd, +DEFUN (no_ospf_area_filter_list, + no_ospf_area_filter_list_cmd, "no area (A.B.C.D|<0-4294967295>) filter-list prefix WORD (in|out)", NO_STR "OSPF area parameters\n" @@ -1878,8 +1878,8 @@ DEFUN (no_area_filter_list, } -DEFUN (area_authentication_message_digest, - area_authentication_message_digest_cmd, +DEFUN (ospf_area_authentication_message_digest, + ospf_area_authentication_message_digest_cmd, "area (A.B.C.D|<0-4294967295>) authentication message-digest", "OSPF area parameters\n" "Enable authentication\n" @@ -1898,8 +1898,8 @@ DEFUN (area_authentication_message_digest, return CMD_SUCCESS; } -DEFUN (area_authentication, - area_authentication_cmd, +DEFUN (ospf_area_authentication, + ospf_area_authentication_cmd, "area (A.B.C.D|<0-4294967295>) authentication", "OSPF area parameters\n" "OSPF area ID in IP address format\n" @@ -1919,8 +1919,8 @@ DEFUN (area_authentication, return CMD_SUCCESS; } -DEFUN (no_area_authentication, - no_area_authentication_cmd, +DEFUN (no_ospf_area_authentication, + no_ospf_area_authentication_cmd, "no area (A.B.C.D|<0-4294967295>) authentication", NO_STR "OSPF area parameters\n" @@ -2059,8 +2059,8 @@ ALIAS (no_ospf_compatible_rfc1583, "OSPF specific commands\n" "Disable the RFC1583Compatibility flag\n") -DEFUN (timers_spf, - timers_spf_cmd, +DEFUN (ospf_timers_spf, + ospf_timers_spf_cmd, "timers spf <0-4294967295> <0-4294967295>", "Adjust routing timers\n" "OSPF SPF timers\n" @@ -2078,8 +2078,8 @@ DEFUN (timers_spf, return CMD_SUCCESS; } -DEFUN (no_timers_spf, - no_timers_spf_cmd, +DEFUN (no_ospf_timers_spf, + no_ospf_timers_spf_cmd, "no timers spf", NO_STR "Adjust routing timers\n" @@ -2094,8 +2094,8 @@ DEFUN (no_timers_spf, } -DEFUN (neighbor, - neighbor_cmd, +DEFUN (ospf_neighbor, + ospf_neighbor_cmd, "neighbor A.B.C.D", NEIGHBOR_STR "Neighbor IP address\n") @@ -2122,8 +2122,8 @@ DEFUN (neighbor, return CMD_SUCCESS; } -ALIAS (neighbor, - neighbor_priority_poll_interval_cmd, +ALIAS (ospf_neighbor, + ospf_neighbor_priority_poll_interval_cmd, "neighbor A.B.C.D priority <0-255> poll-interval <1-65535>", NEIGHBOR_STR "Neighbor IP address\n" @@ -2132,16 +2132,16 @@ ALIAS (neighbor, "Dead Neighbor Polling interval\n" "Seconds\n") -ALIAS (neighbor, - neighbor_priority_cmd, +ALIAS (ospf_neighbor, + ospf_neighbor_priority_cmd, "neighbor A.B.C.D priority <0-255>", NEIGHBOR_STR "Neighbor IP address\n" "Neighbor Priority\n" "Seconds\n") -DEFUN (neighbor_poll_interval, - neighbor_poll_interval_cmd, +DEFUN (ospf_neighbor_poll_interval, + ospf_neighbor_poll_interval_cmd, "neighbor A.B.C.D poll-interval <1-65535>", NEIGHBOR_STR "Neighbor IP address\n" @@ -2170,8 +2170,8 @@ DEFUN (neighbor_poll_interval, return CMD_SUCCESS; } -ALIAS (neighbor_poll_interval, - neighbor_poll_interval_priority_cmd, +ALIAS (ospf_neighbor_poll_interval, + ospf_neighbor_poll_interval_priority_cmd, "neighbor A.B.C.D poll-interval <1-65535> priority <0-255>", NEIGHBOR_STR "Neighbor address\n" @@ -2180,8 +2180,8 @@ ALIAS (neighbor_poll_interval, "OSPF priority of non-broadcast neighbor\n" "Priority\n") -DEFUN (no_neighbor, - no_neighbor_cmd, +DEFUN (no_ospf_neighbor, + no_ospf_neighbor_cmd, "no neighbor A.B.C.D", NO_STR NEIGHBOR_STR @@ -2198,8 +2198,8 @@ DEFUN (no_neighbor, return CMD_SUCCESS; } -ALIAS (no_neighbor, - no_neighbor_priority_cmd, +ALIAS (no_ospf_neighbor, + no_ospf_neighbor_priority_cmd, "no neighbor A.B.C.D priority <0-255>", NO_STR NEIGHBOR_STR @@ -2207,8 +2207,8 @@ ALIAS (no_neighbor, "Neighbor Priority\n" "Priority\n") -ALIAS (no_neighbor, - no_neighbor_poll_interval_cmd, +ALIAS (no_ospf_neighbor, + no_ospf_neighbor_poll_interval_cmd, "no neighbor A.B.C.D poll-interval <1-65535>", NO_STR NEIGHBOR_STR @@ -2216,8 +2216,8 @@ ALIAS (no_neighbor, "Dead Neighbor Polling interval\n" "Seconds\n") -ALIAS (no_neighbor, - no_neighbor_priority_pollinterval_cmd, +ALIAS (no_ospf_neighbor, + no_ospf_neighbor_priority_pollinterval_cmd, "no neighbor A.B.C.D priority <0-255> poll-interval <1-65535>", NO_STR NEIGHBOR_STR @@ -2228,7 +2228,7 @@ ALIAS (no_neighbor, "Seconds\n") -DEFUN (refresh_timer, refresh_timer_cmd, +DEFUN (ospf_refresh_timer, ospf_refresh_timer_cmd, "refresh timer <10-1800>", "Adjust refresh parameters\n" "Set refresh timer\n" @@ -2245,7 +2245,7 @@ DEFUN (refresh_timer, refresh_timer_cmd, return CMD_SUCCESS; } -DEFUN (no_refresh_timer, no_refresh_timer_val_cmd, +DEFUN (no_ospf_refresh_timer, no_ospf_refresh_timer_val_cmd, "no refresh timer <10-1800>", "Adjust refresh parameters\n" "Unset refresh timer\n" @@ -2268,14 +2268,14 @@ DEFUN (no_refresh_timer, no_refresh_timer_val_cmd, return CMD_SUCCESS; } -ALIAS (no_refresh_timer, - no_refresh_timer_cmd, +ALIAS (no_ospf_refresh_timer, + no_ospf_refresh_timer_cmd, "no refresh timer", "Adjust refresh parameters\n" "Unset refresh timer\n") -DEFUN (auto_cost_reference_bandwidth, - auto_cost_reference_bandwidth_cmd, +DEFUN (ospf_auto_cost_reference_bandwidth, + ospf_auto_cost_reference_bandwidth_cmd, "auto-cost reference-bandwidth <1-4294967>", "Calculate OSPF interface cost according to bandwidth\n" "Use reference bandwidth method to assign OSPF cost\n" @@ -2306,8 +2306,8 @@ DEFUN (auto_cost_reference_bandwidth, return CMD_SUCCESS; } -DEFUN (no_auto_cost_reference_bandwidth, - no_auto_cost_reference_bandwidth_cmd, +DEFUN (no_ospf_auto_cost_reference_bandwidth, + no_ospf_auto_cost_reference_bandwidth_cmd, "no auto-cost reference-bandwidth", NO_STR "Calculate OSPF interface cost according to bandwidth\n" @@ -2513,12 +2513,11 @@ show_ip_ospf_interface_sub (struct vty *vty, struct ospf *ospf, oi_count = ospf_oi_count (ifp); /* Is interface up? */ - if (if_is_up (ifp)) - vty_out (vty, "%s is up, line protocol is up%s", ifp->name, VTY_NEWLINE); - else - { - vty_out (vty, "%s is down, line protocol is down%s", ifp->name, - VTY_NEWLINE); + if (if_is_operative (ifp)) { + vty_out (vty, "%s is up%s", ifp->name, VTY_NEWLINE); + } else + { + vty_out (vty, "%s is down%s", ifp->name, VTY_NEWLINE); if (oi_count == 0) @@ -3101,6 +3100,9 @@ show_lsa_summary (struct vty *vty, struct ospf_lsa *lsa, int self) vty_out (vty, " %s/%d", inet_ntoa (p.prefix), p.prefixlen); break; case OSPF_AS_EXTERNAL_LSA: +#ifdef HAVE_NSSA + case OSPF_AS_NSSA_LSA: +#endif /* HAVE_NSSA */ asel = (struct as_external_lsa *) lsa->data; p.family = AF_INET; @@ -7375,6 +7377,7 @@ ospf_vty_if_init () install_node (&interface_node, config_write_interface); install_element (CONFIG_NODE, &interface_cmd); + install_element (CONFIG_NODE, &no_interface_cmd); install_default (INTERFACE_NODE); /* "description" commands. */ @@ -7583,14 +7586,14 @@ ospf_vty_init () /* "ospf router-id" commands. */ install_element (OSPF_NODE, &ospf_router_id_cmd); install_element (OSPF_NODE, &no_ospf_router_id_cmd); - install_element (OSPF_NODE, &router_id_cmd); - install_element (OSPF_NODE, &no_router_id_cmd); + install_element (OSPF_NODE, &router_ospf_id_cmd); + install_element (OSPF_NODE, &no_router_ospf_id_cmd); /* "passive-interface" commands. */ - install_element (OSPF_NODE, &passive_interface_addr_cmd); - install_element (OSPF_NODE, &passive_interface_cmd); - install_element (OSPF_NODE, &no_passive_interface_addr_cmd); - install_element (OSPF_NODE, &no_passive_interface_cmd); + install_element (OSPF_NODE, &ospf_passive_interface_addr_cmd); + install_element (OSPF_NODE, &ospf_passive_interface_cmd); + install_element (OSPF_NODE, &no_ospf_passive_interface_addr_cmd); + install_element (OSPF_NODE, &no_ospf_passive_interface_cmd); /* "ospf abr-type" commands. */ install_element (OSPF_NODE, &ospf_abr_type_cmd); @@ -7603,111 +7606,111 @@ ospf_vty_init () install_element (OSPF_NODE, &no_ospf_compatible_rfc1583_cmd); /* "network area" commands. */ - install_element (OSPF_NODE, &network_area_cmd); - install_element (OSPF_NODE, &no_network_area_cmd); + install_element (OSPF_NODE, &ospf_network_area_cmd); + install_element (OSPF_NODE, &no_ospf_network_area_cmd); /* "area authentication" commands. */ - install_element (OSPF_NODE, &area_authentication_message_digest_cmd); - install_element (OSPF_NODE, &area_authentication_cmd); - install_element (OSPF_NODE, &no_area_authentication_cmd); + install_element (OSPF_NODE, &ospf_area_authentication_message_digest_cmd); + install_element (OSPF_NODE, &ospf_area_authentication_cmd); + install_element (OSPF_NODE, &no_ospf_area_authentication_cmd); /* "area range" commands. */ - install_element (OSPF_NODE, &area_range_cmd); - install_element (OSPF_NODE, &area_range_advertise_cmd); - install_element (OSPF_NODE, &area_range_cost_cmd); - install_element (OSPF_NODE, &area_range_advertise_cost_cmd); - install_element (OSPF_NODE, &area_range_not_advertise_cmd); - install_element (OSPF_NODE, &no_area_range_cmd); - install_element (OSPF_NODE, &no_area_range_advertise_cmd); - install_element (OSPF_NODE, &no_area_range_cost_cmd); - install_element (OSPF_NODE, &no_area_range_advertise_cost_cmd); - install_element (OSPF_NODE, &area_range_substitute_cmd); - install_element (OSPF_NODE, &no_area_range_substitute_cmd); + install_element (OSPF_NODE, &ospf_area_range_cmd); + install_element (OSPF_NODE, &ospf_area_range_advertise_cmd); + install_element (OSPF_NODE, &ospf_area_range_cost_cmd); + install_element (OSPF_NODE, &ospf_area_range_advertise_cost_cmd); + install_element (OSPF_NODE, &ospf_area_range_not_advertise_cmd); + install_element (OSPF_NODE, &no_ospf_area_range_cmd); + install_element (OSPF_NODE, &no_ospf_area_range_advertise_cmd); + install_element (OSPF_NODE, &no_ospf_area_range_cost_cmd); + install_element (OSPF_NODE, &no_ospf_area_range_advertise_cost_cmd); + install_element (OSPF_NODE, &ospf_area_range_substitute_cmd); + install_element (OSPF_NODE, &no_ospf_area_range_substitute_cmd); /* "area virtual-link" commands. */ - install_element (OSPF_NODE, &area_vlink_cmd); - install_element (OSPF_NODE, &no_area_vlink_cmd); + install_element (OSPF_NODE, &ospf_area_vlink_cmd); + install_element (OSPF_NODE, &no_ospf_area_vlink_cmd); - install_element (OSPF_NODE, &area_vlink_param1_cmd); - install_element (OSPF_NODE, &no_area_vlink_param1_cmd); + install_element (OSPF_NODE, &ospf_area_vlink_param1_cmd); + install_element (OSPF_NODE, &no_ospf_area_vlink_param1_cmd); - install_element (OSPF_NODE, &area_vlink_param2_cmd); - install_element (OSPF_NODE, &no_area_vlink_param2_cmd); + install_element (OSPF_NODE, &ospf_area_vlink_param2_cmd); + install_element (OSPF_NODE, &no_ospf_area_vlink_param2_cmd); - install_element (OSPF_NODE, &area_vlink_param3_cmd); - install_element (OSPF_NODE, &no_area_vlink_param3_cmd); + install_element (OSPF_NODE, &ospf_area_vlink_param3_cmd); + install_element (OSPF_NODE, &no_ospf_area_vlink_param3_cmd); - install_element (OSPF_NODE, &area_vlink_param4_cmd); - install_element (OSPF_NODE, &no_area_vlink_param4_cmd); + install_element (OSPF_NODE, &ospf_area_vlink_param4_cmd); + install_element (OSPF_NODE, &no_ospf_area_vlink_param4_cmd); - install_element (OSPF_NODE, &area_vlink_authtype_args_cmd); - install_element (OSPF_NODE, &area_vlink_authtype_cmd); - install_element (OSPF_NODE, &no_area_vlink_authtype_cmd); + install_element (OSPF_NODE, &ospf_area_vlink_authtype_args_cmd); + install_element (OSPF_NODE, &ospf_area_vlink_authtype_cmd); + install_element (OSPF_NODE, &no_ospf_area_vlink_authtype_cmd); - install_element (OSPF_NODE, &area_vlink_md5_cmd); - install_element (OSPF_NODE, &no_area_vlink_md5_cmd); + install_element (OSPF_NODE, &ospf_area_vlink_md5_cmd); + install_element (OSPF_NODE, &no_ospf_area_vlink_md5_cmd); - install_element (OSPF_NODE, &area_vlink_authkey_cmd); - install_element (OSPF_NODE, &no_area_vlink_authkey_cmd); + install_element (OSPF_NODE, &ospf_area_vlink_authkey_cmd); + install_element (OSPF_NODE, &no_ospf_area_vlink_authkey_cmd); - install_element (OSPF_NODE, &area_vlink_authtype_args_authkey_cmd); - install_element (OSPF_NODE, &area_vlink_authtype_authkey_cmd); - install_element (OSPF_NODE, &no_area_vlink_authtype_authkey_cmd); + install_element (OSPF_NODE, &ospf_area_vlink_authtype_args_authkey_cmd); + install_element (OSPF_NODE, &ospf_area_vlink_authtype_authkey_cmd); + install_element (OSPF_NODE, &no_ospf_area_vlink_authtype_authkey_cmd); - install_element (OSPF_NODE, &area_vlink_authtype_args_md5_cmd); - install_element (OSPF_NODE, &area_vlink_authtype_md5_cmd); - install_element (OSPF_NODE, &no_area_vlink_authtype_md5_cmd); + install_element (OSPF_NODE, &ospf_area_vlink_authtype_args_md5_cmd); + install_element (OSPF_NODE, &ospf_area_vlink_authtype_md5_cmd); + install_element (OSPF_NODE, &no_ospf_area_vlink_authtype_md5_cmd); /* "area stub" commands. */ - install_element (OSPF_NODE, &area_stub_no_summary_cmd); - install_element (OSPF_NODE, &area_stub_cmd); - install_element (OSPF_NODE, &no_area_stub_no_summary_cmd); - install_element (OSPF_NODE, &no_area_stub_cmd); + install_element (OSPF_NODE, &ospf_area_stub_no_summary_cmd); + install_element (OSPF_NODE, &ospf_area_stub_cmd); + install_element (OSPF_NODE, &no_ospf_area_stub_no_summary_cmd); + install_element (OSPF_NODE, &no_ospf_area_stub_cmd); #ifdef HAVE_NSSA /* "area nssa" commands. */ - install_element (OSPF_NODE, &area_nssa_cmd); - install_element (OSPF_NODE, &area_nssa_translate_no_summary_cmd); - install_element (OSPF_NODE, &area_nssa_translate_cmd); - install_element (OSPF_NODE, &area_nssa_no_summary_cmd); - install_element (OSPF_NODE, &no_area_nssa_cmd); - install_element (OSPF_NODE, &no_area_nssa_no_summary_cmd); + install_element (OSPF_NODE, &ospf_area_nssa_cmd); + install_element (OSPF_NODE, &ospf_area_nssa_translate_no_summary_cmd); + install_element (OSPF_NODE, &ospf_area_nssa_translate_cmd); + install_element (OSPF_NODE, &ospf_area_nssa_no_summary_cmd); + install_element (OSPF_NODE, &no_ospf_area_nssa_cmd); + install_element (OSPF_NODE, &no_ospf_area_nssa_no_summary_cmd); #endif /* HAVE_NSSA */ - install_element (OSPF_NODE, &area_default_cost_cmd); - install_element (OSPF_NODE, &no_area_default_cost_cmd); + install_element (OSPF_NODE, &ospf_area_default_cost_cmd); + install_element (OSPF_NODE, &no_ospf_area_default_cost_cmd); - install_element (OSPF_NODE, &area_shortcut_cmd); - install_element (OSPF_NODE, &no_area_shortcut_cmd); + install_element (OSPF_NODE, &ospf_area_shortcut_cmd); + install_element (OSPF_NODE, &no_ospf_area_shortcut_cmd); - install_element (OSPF_NODE, &area_export_list_cmd); - install_element (OSPF_NODE, &no_area_export_list_cmd); + install_element (OSPF_NODE, &ospf_area_export_list_cmd); + install_element (OSPF_NODE, &no_ospf_area_export_list_cmd); - install_element (OSPF_NODE, &area_filter_list_cmd); - install_element (OSPF_NODE, &no_area_filter_list_cmd); + install_element (OSPF_NODE, &ospf_area_filter_list_cmd); + install_element (OSPF_NODE, &no_ospf_area_filter_list_cmd); - install_element (OSPF_NODE, &area_import_list_cmd); - install_element (OSPF_NODE, &no_area_import_list_cmd); + install_element (OSPF_NODE, &ospf_area_import_list_cmd); + install_element (OSPF_NODE, &no_ospf_area_import_list_cmd); - install_element (OSPF_NODE, &timers_spf_cmd); - install_element (OSPF_NODE, &no_timers_spf_cmd); + install_element (OSPF_NODE, &ospf_timers_spf_cmd); + install_element (OSPF_NODE, &no_ospf_timers_spf_cmd); - install_element (OSPF_NODE, &refresh_timer_cmd); - install_element (OSPF_NODE, &no_refresh_timer_val_cmd); - install_element (OSPF_NODE, &no_refresh_timer_cmd); + install_element (OSPF_NODE, &ospf_refresh_timer_cmd); + install_element (OSPF_NODE, &no_ospf_refresh_timer_val_cmd); + install_element (OSPF_NODE, &no_ospf_refresh_timer_cmd); - install_element (OSPF_NODE, &auto_cost_reference_bandwidth_cmd); - install_element (OSPF_NODE, &no_auto_cost_reference_bandwidth_cmd); + install_element (OSPF_NODE, &ospf_auto_cost_reference_bandwidth_cmd); + install_element (OSPF_NODE, &no_ospf_auto_cost_reference_bandwidth_cmd); /* "neighbor" commands. */ - install_element (OSPF_NODE, &neighbor_cmd); - install_element (OSPF_NODE, &neighbor_priority_poll_interval_cmd); - install_element (OSPF_NODE, &neighbor_priority_cmd); - install_element (OSPF_NODE, &neighbor_poll_interval_cmd); - install_element (OSPF_NODE, &neighbor_poll_interval_priority_cmd); - install_element (OSPF_NODE, &no_neighbor_cmd); - install_element (OSPF_NODE, &no_neighbor_priority_cmd); - install_element (OSPF_NODE, &no_neighbor_poll_interval_cmd); + install_element (OSPF_NODE, &ospf_neighbor_cmd); + install_element (OSPF_NODE, &ospf_neighbor_priority_poll_interval_cmd); + install_element (OSPF_NODE, &ospf_neighbor_priority_cmd); + install_element (OSPF_NODE, &ospf_neighbor_poll_interval_cmd); + install_element (OSPF_NODE, &ospf_neighbor_poll_interval_priority_cmd); + install_element (OSPF_NODE, &no_ospf_neighbor_cmd); + install_element (OSPF_NODE, &no_ospf_neighbor_priority_cmd); + install_element (OSPF_NODE, &no_ospf_neighbor_poll_interval_cmd); /* Init interface related vty commands. */ ospf_vty_if_init (); diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c index 833dd706..bdb0c0f5 100644 --- a/ospfd/ospf_zebra.c +++ b/ospfd/ospf_zebra.c @@ -67,6 +67,8 @@ ospf_interface_add (int command, struct zclient *zclient, zebra_size_t length) zlog_info ("Zebra: interface add %s index %d flags %ld metric %d mtu %d", ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu); + assert(ifp->info); + if (!OSPF_IF_PARAM_CONFIGURED (IF_DEF_PARAMS (ifp), type)) { SET_IF_PARAM (IF_DEF_PARAMS (ifp), type); @@ -157,6 +159,7 @@ zebra_interface_if_set_value (struct stream *s, struct interface *ifp) ifp->ifindex = stream_getl (s); /* Read interface's value. */ + ifp->status = stream_getc (s); ifp->flags = stream_getl (s); ifp->metric = stream_getl (s); ifp->mtu = stream_getl (s); @@ -178,7 +181,7 @@ ospf_interface_state_up (int command, struct zclient *zclient, return 0; /* Interface is already up. */ - if (if_is_up (ifp)) + if (if_is_operative (ifp)) { /* Temporarily keep ifp values. */ memcpy (&if_tmp, ifp, sizeof (struct interface)); diff --git a/ospfd/ospf_zebra.h b/ospfd/ospf_zebra.h index 6e91f042..5dbf5739 100644 --- a/ospfd/ospf_zebra.h +++ b/ospfd/ospf_zebra.h @@ -50,26 +50,28 @@ void ospf_zebra_delete_discard (struct prefix_ipv4 *); int ospf_default_originate_timer (struct thread *); -int ospf_redistribute_check (struct ospf *, struct external_info *, int *); -int ospf_distribute_check_connected (struct ospf *, struct external_info *); -void ospf_distribute_list_update (struct ospf *, int); +int ospf_redistribute_check (struct external_info *, int *); +int ospf_distribute_check_connected (struct external_info *); +void ospf_distribute_list_update (int); int ospf_is_type_redistributed (int); -void ospf_distance_reset (struct ospf *); +int ospf_redistribute_unset (int); + +void ospf_distance_reset (); u_char ospf_distance_apply (struct prefix_ipv4 *, struct ospf_route *); struct vty; -int ospf_redistribute_set (struct ospf *, int, int, int); -int ospf_redistribute_unset (struct ospf *, int); -int ospf_redistribute_default_set (struct ospf *, int, int, int); -int ospf_redistribute_default_unset (struct ospf *); -int ospf_distribute_list_out_set (struct ospf *, int, char *); -int ospf_distribute_list_out_unset (struct ospf *, int, char *); -void ospf_routemap_set (struct ospf *, int, char *); -void ospf_routemap_unset (struct ospf *, int); -int ospf_distance_set (struct vty *, struct ospf *, char *, char *, char *); -int ospf_distance_unset (struct vty *, struct ospf *, char *, char *, char *); +int ospf_redistribute_set (int, int, int); +int ospf_redistribute_unset (int); +int ospf_redistribute_default_set (int, int, int); +int ospf_redistribute_default_unset (); +int ospf_distribute_list_out_set (int, char *); +int ospf_distribute_list_out_unset (int, char *); +void ospf_routemap_set (int, char *); +void ospf_routemap_unset (int); +int ospf_distance_set (struct vty *, char *, char *, char *); +int ospf_distance_unset (struct vty *, char *, char *, char *); void ospf_zebra_init (); #endif /* _ZEBRA_OSPF_ZEBRA_H */ diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c index a12a0115..d8646f07 100644 --- a/ospfd/ospfd.c +++ b/ospfd/ospfd.c @@ -53,7 +53,6 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "ospfd/ospf_ase.h" - /* OSPF process wide configuration. */ static struct ospf_master ospf_master; |