Changeset 32089


Ignore:
Timestamp:
May 18, 2017, 9:37:42 AM (2 months ago)
Author:
brainslayer
Message:

update radvd

Location:
src/router/radvd
Files:
30 edited

Legend:

Unmodified
Added
Removed
  • src/router/radvd/CHANGES

    r29984 r32089  
     12017/02/01      Release v2.16
     2
     32017/01/10      Fixed ExecReload in systemd service file <Harald Albrecht>
     4
     52016/11/11      Allow selection of RA source address. <Robin H. Johnson>
     6
     72016/09/24      Release v2.15
     8
     92016/09/18      Moved auto prefix code from config file parse to send_ra.
     10
     112016/08/08      Merged ARPHRD_6LOWPAN netlink query from <Alexander Aring>
     12                Add systemd service file <Craig Andrews>
     13
     142016/07/05      Fixed bug in new vs old address list comparison when
     15                responding to netlink messages.
     16                Release v2.14
     17
    1182016/04/02      Fix netlink bug where RADVD reacts to RTM_NEWADDR
    219                messages when there weren't actually any new addresses
  • src/router/radvd/Makefile.am

    r29984 r32089  
    149149        radvd.conf.5.man \
    150150        radvd.conf.example \
     151        radvd.service.in \
    151152        radvdump.8.man \
     153        redhat/radvd-tmpfs.conf \
    152154        redhat/radvd.conf.empty \
    153155        redhat/radvd.init \
    154156        redhat/radvd.spec \
    155157        redhat/radvd.sysconfig \
    156         redhat/radvd-tmpfs.conf \
    157158        test/check.c \
    158159        test/print_safe_buffer.c \
     
    270271        @CONDITIONAL_SOURCES@ \
    271272        libradvd-parser.a
     273
     274DISTCHECK_CONFIGURE_FLAGS = \
     275  --with-systemdsystemunitdir=$$dc_install_base/$(systemdsystemunitdir)
     276
     277if HAVE_SYSTEMD
     278systemdsystemunit_DATA = radvd.service
     279endif
     280
  • src/router/radvd/Makefile.in

    r29984 r32089  
    1 # Makefile.in generated by automake 1.13.4 from Makefile.am.
     1# Makefile.in generated by automake 1.15 from Makefile.am.
    22# @configure_input@
    33
    4 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
     4# Copyright (C) 1994-2014 Free Software Foundation, Inc.
    55
    66# This Makefile.in is free software; the Free Software Foundation
     
    3333
    3434
     35
    3536VPATH = @srcdir@
    36 am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
     37am__is_gnu_make = { \
     38  if test -z '$(MAKELEVEL)'; then \
     39    false; \
     40  elif test -n '$(MAKE_HOST)'; then \
     41    true; \
     42  elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
     43    true; \
     44  else \
     45    false; \
     46  fi; \
     47}
    3748am__make_running_with_option = \
    3849  case $${target_option-} in \
     
    102113check_PROGRAMS = check_all$(EXEEXT)
    103114subdir = .
    104 DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
    105         $(top_srcdir)/configure $(am__configure_deps) \
    106         $(srcdir)/config.h.in $(top_srcdir)/redhat/radvd.spec.in \
    107         gram.h gram.c scanner.c depcomp ylwrap test-driver README TODO \
    108         compile config.guess config.sub install-sh missing ltmain.sh
    109115ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
    110116am__aclocal_m4_deps = $(top_srcdir)/configure.ac
    111117am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
    112118        $(ACLOCAL_M4)
     119DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \
     120        $(am__configure_deps) $(am__DIST_COMMON)
    113121am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
    114122 configure.lineno config.status.lineno
    115123mkinstalldirs = $(install_sh) -d
    116124CONFIG_HEADER = config.h
    117 CONFIG_CLEAN_FILES = redhat/radvd.spec
     125CONFIG_CLEAN_FILES = radvd.service redhat/radvd.spec
    118126CONFIG_CLEAN_VPATH_FILES =
    119127LIBRARIES = $(noinst_LIBRARIES)
     
    130138libradvd_parser_a_OBJECTS = $(am_libradvd_parser_a_OBJECTS)
    131139am__installdirs = "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man5dir)" \
    132         "$(DESTDIR)$(man8dir)"
     140        "$(DESTDIR)$(man8dir)" "$(DESTDIR)$(systemdsystemunitdir)"
    133141PROGRAMS = $(sbin_PROGRAMS)
    134142am__dirstamp = $(am__leading_dot)dirstamp
     
    239247NROFF = nroff
    240248MANS = $(man_MANS)
     249DATA = $(systemdsystemunit_DATA)
    241250am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \
    242251        $(LISP)config.h.in
     
    437446TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \
    438447        $(TEST_LOG_FLAGS)
     448am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in \
     449        $(srcdir)/radvd.service.in $(top_srcdir)/redhat/radvd.spec.in \
     450        README TODO compile config.guess config.sub depcomp gram.c \
     451        gram.h install-sh ltmain.sh missing scanner.c test-driver \
     452        ylwrap
    439453DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
    440454distdir = $(PACKAGE)-$(VERSION)
     
    521535RANLIB = @RANLIB@
    522536RM = @RM@
     537SBINDIR = @SBINDIR@
    523538SED = @SED@
    524539SET_MAKE = @SET_MAKE@
     
    575590srcdir = @srcdir@
    576591sysconfdir = @sysconfdir@
     592systemdsystemunitdir = @systemdsystemunitdir@
    577593target = @target@
    578594target_alias = @target_alias@
     
    669685        radvd.conf.5.man \
    670686        radvd.conf.example \
     687        radvd.service.in \
    671688        radvdump.8.man \
     689        redhat/radvd-tmpfs.conf \
    672690        redhat/radvd.conf.empty \
    673691        redhat/radvd.init \
    674692        redhat/radvd.spec \
    675693        redhat/radvd.sysconfig \
    676         redhat/radvd-tmpfs.conf \
    677694        test/check.c \
    678695        test/print_safe_buffer.c \
     
    729746        libradvd-parser.a
    730747
     748DISTCHECK_CONFIGURE_FLAGS = \
     749  --with-systemdsystemunitdir=$$dc_install_base/$(systemdsystemunitdir)
     750
     751@HAVE_SYSTEMD_TRUE@systemdsystemunit_DATA = radvd.service
    731752all: config.h
    732753        $(MAKE) $(AM_MAKEFLAGS) all-am
     
    749770        $(am__cd) $(top_srcdir) && \
    750771          $(AUTOMAKE) --foreign Makefile
    751 .PRECIOUS: Makefile
    752772Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
    753773        @case '$?' in \
     
    770790
    771791config.h: stamp-h1
    772         @if test ! -f $@; then rm -f stamp-h1; else :; fi
    773         @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) stamp-h1; else :; fi
     792        @test -f $@ || rm -f stamp-h1
     793        @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1
    774794
    775795stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
     
    783803distclean-hdr:
    784804        -rm -f config.h stamp-h1
     805radvd.service: $(top_builddir)/config.status $(srcdir)/radvd.service.in
     806        cd $(top_builddir) && $(SHELL) ./config.status $@
    785807redhat/radvd.spec: $(top_builddir)/config.status $(top_srcdir)/redhat/radvd.spec.in
    786808        cd $(top_builddir) && $(SHELL) ./config.status $@
     
    12011223              -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
    12021224        dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir)
     1225install-systemdsystemunitDATA: $(systemdsystemunit_DATA)
     1226        @$(NORMAL_INSTALL)
     1227        @list='$(systemdsystemunit_DATA)'; test -n "$(systemdsystemunitdir)" || list=; \
     1228        if test -n "$$list"; then \
     1229          echo " $(MKDIR_P) '$(DESTDIR)$(systemdsystemunitdir)'"; \
     1230          $(MKDIR_P) "$(DESTDIR)$(systemdsystemunitdir)" || exit 1; \
     1231        fi; \
     1232        for p in $$list; do \
     1233          if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
     1234          echo "$$d$$p"; \
     1235        done | $(am__base_list) | \
     1236        while read files; do \
     1237          echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(systemdsystemunitdir)'"; \
     1238          $(INSTALL_DATA) $$files "$(DESTDIR)$(systemdsystemunitdir)" || exit $$?; \
     1239        done
     1240
     1241uninstall-systemdsystemunitDATA:
     1242        @$(NORMAL_UNINSTALL)
     1243        @list='$(systemdsystemunit_DATA)'; test -n "$(systemdsystemunitdir)" || list=; \
     1244        files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
     1245        dir='$(DESTDIR)$(systemdsystemunitdir)'; $(am__uninstall_files_from_dir)
    12031246
    12041247ID: $(am__tagged_files)
     
    12911334          echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \
    12921335               "recursion detected" >&2; \
    1293         else \
     1336        elif test -n "$$redo_logs"; then \
    12941337          am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \
    12951338        fi; \
     
    14831526
    14841527dist-tarZ: distdir
     1528        @echo WARNING: "Support for distribution archives compressed with" \
     1529                       "legacy program 'compress' is deprecated." >&2
     1530        @echo WARNING: "It will be removed altogether in Automake 2.0" >&2
    14851531        tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
    14861532        $(am__post_remove_distdir)
    14871533
    14881534dist-shar: distdir
     1535        @echo WARNING: "Support for shar distribution archives is" \
     1536                       "deprecated." >&2
     1537        @echo WARNING: "It will be removed altogether in Automake 2.0" >&2
    14891538        shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
    14901539        $(am__post_remove_distdir)
     
    15211570        chmod -R a-w $(distdir)
    15221571        chmod u+w $(distdir)
    1523         mkdir $(distdir)/_build $(distdir)/_inst
     1572        mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst
    15241573        chmod a-w $(distdir)
    15251574        test -d $(distdir)/_build || exit 0; \
     
    15271576          && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
    15281577          && am__cwd=`pwd` \
    1529           && $(am__cd) $(distdir)/_build \
    1530           && ../configure --srcdir=.. --prefix="$$dc_install_base" \
     1578          && $(am__cd) $(distdir)/_build/sub \
     1579          && ../../configure \
    15311580            $(AM_DISTCHECK_CONFIGURE_FLAGS) \
    15321581            $(DISTCHECK_CONFIGURE_FLAGS) \
     1582            --srcdir=../.. --prefix="$$dc_install_base" \
    15331583          && $(MAKE) $(AM_MAKEFLAGS) \
    15341584          && $(MAKE) $(AM_MAKEFLAGS) dvi \
     
    15871637        $(MAKE) $(AM_MAKEFLAGS) check-TESTS
    15881638check: check-am
    1589 all-am: Makefile $(LIBRARIES) $(PROGRAMS) $(MANS) config.h
     1639all-am: Makefile $(LIBRARIES) $(PROGRAMS) $(MANS) $(DATA) config.h
    15901640installdirs:
    1591         for dir in "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man8dir)"; do \
     1641        for dir in "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man8dir)" "$(DESTDIR)$(systemdsystemunitdir)"; do \
    15921642          test -z "$$dir" || $(MKDIR_P) "$$dir"; \
    15931643        done
     
    16531703info-am:
    16541704
    1655 install-data-am: install-man
     1705install-data-am: install-man install-systemdsystemunitDATA
    16561706
    16571707install-dvi: install-dvi-am
     
    17001750ps-am:
    17011751
    1702 uninstall-am: uninstall-man uninstall-sbinPROGRAMS
     1752uninstall-am: uninstall-man uninstall-sbinPROGRAMS \
     1753        uninstall-systemdsystemunitDATA
    17031754
    17041755uninstall-man: uninstall-man5 uninstall-man8
     
    17181769        install-info install-info-am install-man install-man5 \
    17191770        install-man8 install-pdf install-pdf-am install-ps \
    1720         install-ps-am install-sbinPROGRAMS install-strip installcheck \
    1721         installcheck-am installdirs maintainer-clean \
    1722         maintainer-clean-generic mostlyclean mostlyclean-compile \
    1723         mostlyclean-generic pdf pdf-am ps ps-am recheck tags tags-am \
    1724         uninstall uninstall-am uninstall-man uninstall-man5 \
    1725         uninstall-man8 uninstall-sbinPROGRAMS
     1771        install-ps-am install-sbinPROGRAMS install-strip \
     1772        install-systemdsystemunitDATA installcheck installcheck-am \
     1773        installdirs maintainer-clean maintainer-clean-generic \
     1774        mostlyclean mostlyclean-compile mostlyclean-generic pdf pdf-am \
     1775        ps ps-am recheck tags tags-am uninstall uninstall-am \
     1776        uninstall-man uninstall-man5 uninstall-man8 \
     1777        uninstall-sbinPROGRAMS uninstall-systemdsystemunitDATA
     1778
     1779.PRECIOUS: Makefile
    17261780
    17271781
  • src/router/radvd/TODO

    r26390 r32089  
    5252do some logging and nothing else.
    5353
    54 radvd does not support splitting up RAs to multiple packets (RFC4861 6.2.3
    55 last paragraph). In practise this limits advertising to ~45 prefixes on a
    56 link, but there is no reason to be able to so.  In order to avoid
    57 fragmenting packets yet support receiving full-size frames, our hack is to
    58 have a bigger receive than send buffer. We could try using setsockopt
    59 IPV6_DONTFRAG, but at least Linux glibc doesn't appear to support it yet.
    60 
    6154Triggered by: https://bugzilla.redhat.com/show_bug.cgi?id=554125
    6255Known problems (probably can't do anything about these):
  • src/router/radvd/aclocal.m4

    r29984 r32089  
    1 # generated automatically by aclocal 1.13.4 -*- Autoconf -*-
    2 
    3 # Copyright (C) 1996-2013 Free Software Foundation, Inc.
     1# generated automatically by aclocal 1.15 -*- Autoconf -*-
     2
     3# Copyright (C) 1996-2014 Free Software Foundation, Inc.
    44
    55# This file is free software; the Free Software Foundation
     
    236236])# PKG_CHECK_VAR
    237237
    238 # Copyright (C) 2002-2013 Free Software Foundation, Inc.
     238# Copyright (C) 2002-2014 Free Software Foundation, Inc.
    239239#
    240240# This file is free software; the Free Software Foundation
     
    248248# (This private macro should not be called outside this file.)
    249249AC_DEFUN([AM_AUTOMAKE_VERSION],
    250 [am__api_version='1.13'
     250[am__api_version='1.15'
    251251dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
    252252dnl require some minimum version.  Point them to the right macro.
    253 m4_if([$1], [1.13.4], [],
     253m4_if([$1], [1.15], [],
    254254      [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
    255255])
     
    267267# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
    268268AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
    269 [AM_AUTOMAKE_VERSION([1.13.4])dnl
     269[AM_AUTOMAKE_VERSION([1.15])dnl
    270270m4_ifndef([AC_AUTOCONF_VERSION],
    271271  [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
     
    274274# AM_AUX_DIR_EXPAND                                         -*- Autoconf -*-
    275275
    276 # Copyright (C) 2001-2013 Free Software Foundation, Inc.
     276# Copyright (C) 2001-2014 Free Software Foundation, Inc.
    277277#
    278278# This file is free software; the Free Software Foundation
     
    319319
    320320AC_DEFUN([AM_AUX_DIR_EXPAND],
    321 [dnl Rely on autoconf to set up CDPATH properly.
    322 AC_PREREQ([2.50])dnl
    323 # expand $ac_aux_dir to an absolute path
    324 am_aux_dir=`cd $ac_aux_dir && pwd`
     321[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl
     322# Expand $ac_aux_dir to an absolute path.
     323am_aux_dir=`cd "$ac_aux_dir" && pwd`
    325324])
    326325
    327326# AM_CONDITIONAL                                            -*- Autoconf -*-
    328327
    329 # Copyright (C) 1997-2013 Free Software Foundation, Inc.
     328# Copyright (C) 1997-2014 Free Software Foundation, Inc.
    330329#
    331330# This file is free software; the Free Software Foundation
     
    358357fi])])
    359358
    360 # Copyright (C) 1999-2013 Free Software Foundation, Inc.
     359# Copyright (C) 1999-2014 Free Software Foundation, Inc.
    361360#
    362361# This file is free software; the Free Software Foundation
     
    549548# Generate code to set up dependency tracking.              -*- Autoconf -*-
    550549
    551 # Copyright (C) 1999-2013 Free Software Foundation, Inc.
     550# Copyright (C) 1999-2014 Free Software Foundation, Inc.
    552551#
    553552# This file is free software; the Free Software Foundation
     
    625624# Do all the work for Automake.                             -*- Autoconf -*-
    626625
    627 # Copyright (C) 1996-2013 Free Software Foundation, Inc.
     626# Copyright (C) 1996-2014 Free Software Foundation, Inc.
    628627#
    629628# This file is free software; the Free Software Foundation
     
    633632# This macro actually does too much.  Some checks are only needed if
    634633# your package does certain things.  But this isn't really a big deal.
     634
     635dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O.
     636m4_define([AC_PROG_CC],
     637m4_defn([AC_PROG_CC])
     638[_AM_PROG_CC_C_O
     639])
    635640
    636641# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
     
    709714# <http://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
    710715AC_SUBST([mkdir_p], ['$(MKDIR_P)'])
    711 # We need awk for the "check" target.  The system "awk" is bad on
    712 # some platforms.
     716# We need awk for the "check" target (and possibly the TAP driver).  The
     717# system "awk" is bad on some platforms.
    713718AC_REQUIRE([AC_PROG_AWK])dnl
    714719AC_REQUIRE([AC_PROG_MAKE_SET])dnl
     
    742747[m4_provide_if([_AM_COMPILER_EXEEXT],
    743748  [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl
     749
     750# POSIX will say in a future version that running "rm -f" with no argument
     751# is OK; and we want to be able to make that assumption in our Makefile
     752# recipes.  So use an aggressive probe to check that the usage we want is
     753# actually supported "in the wild" to an acceptable degree.
     754# See automake bug#10828.
     755# To make any issue more visible, cause the running configure to be aborted
     756# by default if the 'rm' program in use doesn't match our expectations; the
     757# user can still override this though.
     758if rm -f && rm -fr && rm -rf; then : OK; else
     759  cat >&2 <<'END'
     760Oops!
     761
     762Your 'rm' program seems unable to run without file operands specified
     763on the command line, even when the '-f' option is present.  This is contrary
     764to the behaviour of most rm programs out there, and not conforming with
     765the upcoming POSIX standard: <http://austingroupbugs.net/view.php?id=542>
     766
     767Please tell bug-automake@gnu.org about your system, including the value
     768of your $PATH and any error possibly output before this message.  This
     769can help us improve future automake versions.
     770
     771END
     772  if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then
     773    echo 'Configuration will proceed anyway, since you have set the' >&2
     774    echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2
     775    echo >&2
     776  else
     777    cat >&2 <<'END'
     778Aborting the configuration process, to ensure you take notice of the issue.
     779
     780You can download and install GNU coreutils to get an 'rm' implementation
     781that behaves properly: <http://www.gnu.org/software/coreutils/>.
     782
     783If you want to complete the configuration process using your problematic
     784'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
     785to "yes", and re-run configure.
     786
     787END
     788    AC_MSG_ERROR([Your 'rm' program is bad, sorry.])
     789  fi
     790fi
     791dnl The trailing newline in this macro's definition is deliberate, for
     792dnl backward compatibility and to allow trailing 'dnl'-style comments
     793dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841.
    744794])
    745795
     
    749799m4_define([_AC_COMPILER_EXEEXT],
    750800m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])])
    751 
    752801
    753802# When config.status generates a header, we must update the stamp-h file.
     
    772821echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
    773822
    774 # Copyright (C) 2001-2013 Free Software Foundation, Inc.
     823# Copyright (C) 2001-2014 Free Software Foundation, Inc.
    775824#
    776825# This file is free software; the Free Software Foundation
     
    783832AC_DEFUN([AM_PROG_INSTALL_SH],
    784833[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
    785 if test x"${install_sh}" != xset; then
     834if test x"${install_sh+set}" != xset; then
    786835  case $am_aux_dir in
    787836  *\ * | *\     *)
     
    793842AC_SUBST([install_sh])])
    794843
    795 # Copyright (C) 2003-2013 Free Software Foundation, Inc.
     844# Copyright (C) 2003-2014 Free Software Foundation, Inc.
    796845#
    797846# This file is free software; the Free Software Foundation
     
    812861AC_SUBST([am__leading_dot])])
    813862
    814 # Copyright (C) 1998-2013 Free Software Foundation, Inc.
     863# Copyright (C) 1998-2014 Free Software Foundation, Inc.
    815864#
    816865# This file is free software; the Free Software Foundation
     
    832881# Check to see how 'make' treats includes.                  -*- Autoconf -*-
    833882
    834 # Copyright (C) 2001-2013 Free Software Foundation, Inc.
     883# Copyright (C) 2001-2014 Free Software Foundation, Inc.
    835884#
    836885# This file is free software; the Free Software Foundation
     
    882931# Fake the existence of programs that GNU maintainers use.  -*- Autoconf -*-
    883932
    884 # Copyright (C) 1997-2013 Free Software Foundation, Inc.
     933# Copyright (C) 1997-2014 Free Software Foundation, Inc.
    885934#
    886935# This file is free software; the Free Software Foundation
     
    923972# error messages when used, to smooth transition.
    924973#
    925 # Copyright (C) 1996-2013 Free Software Foundation, Inc.
     974# Copyright (C) 1996-2014 Free Software Foundation, Inc.
    926975#
    927976# This file is free software; the Free Software Foundation
     
    950999# Helper functions for option handling.                     -*- Autoconf -*-
    9511000
    952 # Copyright (C) 2001-2013 Free Software Foundation, Inc.
     1001# Copyright (C) 2001-2014 Free Software Foundation, Inc.
    9531002#
    9541003# This file is free software; the Free Software Foundation
     
    9791028[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
    9801029
     1030# Copyright (C) 1999-2014 Free Software Foundation, Inc.
     1031#
     1032# This file is free software; the Free Software Foundation
     1033# gives unlimited permission to copy and/or distribute it,
     1034# with or without modifications, as long as this notice is preserved.
     1035
     1036# _AM_PROG_CC_C_O
     1037# ---------------
     1038# Like AC_PROG_CC_C_O, but changed for automake.  We rewrite AC_PROG_CC
     1039# to automatically call this.
     1040AC_DEFUN([_AM_PROG_CC_C_O],
     1041[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
     1042AC_REQUIRE_AUX_FILE([compile])dnl
     1043AC_LANG_PUSH([C])dnl
     1044AC_CACHE_CHECK(
     1045  [whether $CC understands -c and -o together],
     1046  [am_cv_prog_cc_c_o],
     1047  [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])])
     1048  # Make sure it works both with $CC and with simple cc.
     1049  # Following AC_PROG_CC_C_O, we do the test twice because some
     1050  # compilers refuse to overwrite an existing .o file with -o,
     1051  # though they will create one.
     1052  am_cv_prog_cc_c_o=yes
     1053  for am_i in 1 2; do
     1054    if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \
     1055         && test -f conftest2.$ac_objext; then
     1056      : OK
     1057    else
     1058      am_cv_prog_cc_c_o=no
     1059      break
     1060    fi
     1061  done
     1062  rm -f core conftest*
     1063  unset am_i])
     1064if test "$am_cv_prog_cc_c_o" != yes; then
     1065   # Losing compiler, so override with the script.
     1066   # FIXME: It is wrong to rewrite CC.
     1067   # But if we don't then we get into trouble of one sort or another.
     1068   # A longer-term fix would be to have automake use am__CC in this case,
     1069   # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
     1070   CC="$am_aux_dir/compile $CC"
     1071fi
     1072AC_LANG_POP([C])])
     1073
     1074# For backward compatibility.
     1075AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])])
     1076
     1077# Copyright (C) 2001-2014 Free Software Foundation, Inc.
     1078#
     1079# This file is free software; the Free Software Foundation
     1080# gives unlimited permission to copy and/or distribute it,
     1081# with or without modifications, as long as this notice is preserved.
     1082
     1083# AM_RUN_LOG(COMMAND)
     1084# -------------------
     1085# Run COMMAND, save the exit status in ac_status, and log it.
     1086# (This has been adapted from Autoconf's _AC_RUN_LOG macro.)
     1087AC_DEFUN([AM_RUN_LOG],
     1088[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD
     1089   ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD
     1090   ac_status=$?
     1091   echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
     1092   (exit $ac_status); }])
     1093
    9811094# Check to make sure that the build environment is sane.    -*- Autoconf -*-
    9821095
    983 # Copyright (C) 1996-2013 Free Software Foundation, Inc.
     1096# Copyright (C) 1996-2014 Free Software Foundation, Inc.
    9841097#
    9851098# This file is free software; the Free Software Foundation
     
    10621175])
    10631176
    1064 # Copyright (C) 2009-2013 Free Software Foundation, Inc.
     1177# Copyright (C) 2009-2014 Free Software Foundation, Inc.
    10651178#
    10661179# This file is free software; the Free Software Foundation
     
    11221235])
    11231236
    1124 # Copyright (C) 2001-2013 Free Software Foundation, Inc.
     1237# Copyright (C) 2001-2014 Free Software Foundation, Inc.
    11251238#
    11261239# This file is free software; the Free Software Foundation
     
    11501263AC_SUBST([INSTALL_STRIP_PROGRAM])])
    11511264
    1152 # Copyright (C) 2006-2013 Free Software Foundation, Inc.
     1265# Copyright (C) 2006-2014 Free Software Foundation, Inc.
    11531266#
    11541267# This file is free software; the Free Software Foundation
     
    11691282# Check how to create a tarball.                            -*- Autoconf -*-
    11701283
    1171 # Copyright (C) 2004-2013 Free Software Foundation, Inc.
     1284# Copyright (C) 2004-2014 Free Software Foundation, Inc.
    11721285#
    11731286# This file is free software; the Free Software Foundation
  • src/router/radvd/configure

    r29984 r32089  
    11#! /bin/sh
    22# Guess values for system-dependent variables and create Makefiles.
    3 # Generated by GNU Autoconf 2.69 for radvd 2.13.
     3# Generated by GNU Autoconf 2.69 for radvd 2.16.
    44#
    55#
     
    578578PACKAGE_NAME='radvd'
    579579PACKAGE_TARNAME='radvd'
    580 PACKAGE_VERSION='2.13'
    581 PACKAGE_STRING='radvd 2.13'
     580PACKAGE_VERSION='2.16'
     581PACKAGE_STRING='radvd 2.16'
    582582PACKAGE_BUGREPORT=''
    583583PACKAGE_URL=''
     
    624624LTLIBOBJS
    625625LIBOBJS
     626HAVE_SYSTEMD_FALSE
     627HAVE_SYSTEMD_TRUE
     628systemdsystemunitdir
     629SBINDIR
    626630LOG_FACILITY
    627631PATH_RADVD_LOG
     
    752756with_configfile
    753757with_facility
     758with_systemdsystemunitdir
    754759'
    755760      ac_precious_vars='build_alias
     
    13091314  # This message is too long to be a string in the A/UX 3.1 sh.
    13101315  cat <<_ACEOF
    1311 \`configure' configures radvd 2.13 to adapt to many kinds of systems.
     1316\`configure' configures radvd 2.16 to adapt to many kinds of systems.
    13121317
    13131318Usage: $0 [OPTION]... [VAR=VALUE]...
     
    13801385if test -n "$ac_init_help"; then
    13811386  case $ac_init_help in
    1382      short | recursive ) echo "Configuration of radvd 2.13:";;
     1387     short | recursive ) echo "Configuration of radvd 2.16:";;
    13831388   esac
    13841389  cat <<\_ACEOF
     
    14031408  --with-configfile       Path to the radvd config file SYSCONF/radvd.conf
    14041409  --with-facility         Syslog facility to use when using syslog logging
     1410  --with-systemdsystemunitdir=DIR
     1411                          Directory for systemd service files
    14051412
    14061413Some influential environment variables:
     
    14941501if $ac_init_version; then
    14951502  cat <<\_ACEOF
    1496 radvd configure 2.13
     1503radvd configure 2.16
    14971504generated by GNU Autoconf 2.69
    14981505
     
    18591866running configure, to aid debugging if configure makes a mistake.
    18601867
    1861 It was created by radvd $as_me 2.13, which was
     1868It was created by radvd $as_me 2.16, which was
    18621869generated by GNU Autoconf 2.69.  Invocation command line was
    18631870
     
    23482355  program_prefix=${target_alias}-
    23492356
    2350 am__api_version='1.13'
     2357am__api_version='1.15'
    23512358
    23522359# Find a good install program.  We prefer a C program (faster),
     
    25202527program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"`
    25212528
    2522 # expand $ac_aux_dir to an absolute path
    2523 am_aux_dir=`cd $ac_aux_dir && pwd`
     2529# Expand $ac_aux_dir to an absolute path.
     2530am_aux_dir=`cd "$ac_aux_dir" && pwd`
    25242531
    25252532if test x"${MISSING+set}" != xset; then
     
    25402547fi
    25412548
    2542 if test x"${install_sh}" != xset; then
     2549if test x"${install_sh+set}" != xset; then
    25432550  case $am_aux_dir in
    25442551  *\ * | *\     *)
     
    28342841# Define the identity of the package.
    28352842 PACKAGE='radvd'
    2836  VERSION='2.13'
     2843 VERSION='2.16'
    28372844
    28382845
     
    28682875mkdir_p='$(MKDIR_P)'
    28692876
    2870 # We need awk for the "check" target.  The system "awk" is bad on
    2871 # some platforms.
     2877# We need awk for the "check" target (and possibly the TAP driver).  The
     2878# system "awk" is bad on some platforms.
    28722879# Always define AMTAR for backward compatibility.  Yes, it's still used
    28732880# in the wild :-(  We should find a proper way to deprecate it ...
     
    28842891
    28852892
     2893
     2894# POSIX will say in a future version that running "rm -f" with no argument
     2895# is OK; and we want to be able to make that assumption in our Makefile
     2896# recipes.  So use an aggressive probe to check that the usage we want is
     2897# actually supported "in the wild" to an acceptable degree.
     2898# See automake bug#10828.
     2899# To make any issue more visible, cause the running configure to be aborted
     2900# by default if the 'rm' program in use doesn't match our expectations; the
     2901# user can still override this though.
     2902if rm -f && rm -fr && rm -rf; then : OK; else
     2903  cat >&2 <<'END'
     2904Oops!
     2905
     2906Your 'rm' program seems unable to run without file operands specified
     2907on the command line, even when the '-f' option is present.  This is contrary
     2908to the behaviour of most rm programs out there, and not conforming with
     2909the upcoming POSIX standard: <http://austingroupbugs.net/view.php?id=542>
     2910
     2911Please tell bug-automake@gnu.org about your system, including the value
     2912of your $PATH and any error possibly output before this message.  This
     2913can help us improve future automake versions.
     2914
     2915END
     2916  if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then
     2917    echo 'Configuration will proceed anyway, since you have set the' >&2
     2918    echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2
     2919    echo >&2
     2920  else
     2921    cat >&2 <<'END'
     2922Aborting the configuration process, to ensure you take notice of the issue.
     2923
     2924You can download and install GNU coreutils to get an 'rm' implementation
     2925that behaves properly: <http://www.gnu.org/software/coreutils/>.
     2926
     2927If you want to complete the configuration process using your problematic
     2928'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
     2929to "yes", and re-run configure.
     2930
     2931END
     2932    as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5
     2933  fi
     2934fi
    28862935
    28872936
     
    38113860ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
    38123861ac_compiler_gnu=$ac_cv_c_compiler_gnu
     3862
     3863ac_ext=c
     3864ac_cpp='$CPP $CPPFLAGS'
     3865ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
     3866ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
     3867ac_compiler_gnu=$ac_cv_c_compiler_gnu
     3868{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5
     3869$as_echo_n "checking whether $CC understands -c and -o together... " >&6; }
     3870if ${am_cv_prog_cc_c_o+:} false; then :
     3871  $as_echo_n "(cached) " >&6
     3872else
     3873  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
     3874/* end confdefs.h.  */
     3875
     3876int
     3877main ()
     3878{
     3879
     3880  ;
     3881  return 0;
     3882}
     3883_ACEOF
     3884  # Make sure it works both with $CC and with simple cc.
     3885  # Following AC_PROG_CC_C_O, we do the test twice because some
     3886  # compilers refuse to overwrite an existing .o file with -o,
     3887  # though they will create one.
     3888  am_cv_prog_cc_c_o=yes
     3889  for am_i in 1 2; do
     3890    if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5
     3891   ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5
     3892   ac_status=$?
     3893   echo "$as_me:$LINENO: \$? = $ac_status" >&5
     3894   (exit $ac_status); } \
     3895         && test -f conftest2.$ac_objext; then
     3896      : OK
     3897    else
     3898      am_cv_prog_cc_c_o=no
     3899      break
     3900    fi
     3901  done
     3902  rm -f core conftest*
     3903  unset am_i
     3904fi
     3905{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5
     3906$as_echo "$am_cv_prog_cc_c_o" >&6; }
     3907if test "$am_cv_prog_cc_c_o" != yes; then
     3908   # Losing compiler, so override with the script.
     3909   # FIXME: It is wrong to rewrite CC.
     3910   # But if we don't then we get into trouble of one sort or another.
     3911   # A longer-term fix would be to have automake use am__CC in this case,
     3912   # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
     3913   CC="$am_aux_dir/compile $CC"
     3914fi
     3915ac_ext=c
     3916ac_cpp='$CPP $CPPFLAGS'
     3917ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
     3918ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
     3919ac_compiler_gnu=$ac_cv_c_compiler_gnu
     3920
    38133921
    38143922depcc="$CC"   am_compiler_list=
     
    56675775
    56685776
     5777# Default value for sbindir
     5778prefix_temp=$prefix
     5779exec_prefix_temp=$exec_prefix
     5780
     5781test "${prefix}" = "NONE" && prefix="${ac_default_prefix}"
     5782test "${exec_prefix}" = "NONE" && exec_prefix='${prefix}'
     5783
     5784# Initial Value is $exec_prefix/sbin
     5785sbintemp="${sbindir}"
     5786
     5787# Expands to $prefix/sbin
     5788eval sbintemp=\"${sbintemp}\"
     5789# Expands to /usr/local/sbin or /usr/sbin if --prefix is passed
     5790eval sbintemp=\"${sbintemp}\"
     5791SBINDIR=${sbintemp}
     5792
     5793
     5794
     5795
     5796
     5797
     5798
     5799
     5800
     5801
     5802if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
     5803        if test -n "$ac_tool_prefix"; then
     5804  # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args.
     5805set dummy ${ac_tool_prefix}pkg-config; ac_word=$2
     5806{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
     5807$as_echo_n "checking for $ac_word... " >&6; }
     5808if ${ac_cv_path_PKG_CONFIG+:} false; then :
     5809  $as_echo_n "(cached) " >&6
     5810else
     5811  case $PKG_CONFIG in
     5812  [\\/]* | ?:[\\/]*)
     5813  ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
     5814  ;;
     5815  *)
     5816  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
     5817for as_dir in $PATH
     5818do
     5819  IFS=$as_save_IFS
     5820  test -z "$as_dir" && as_dir=.
     5821    for ac_exec_ext in '' $ac_executable_extensions; do
     5822  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     5823    ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
     5824    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     5825    break 2
     5826  fi
     5827done
     5828  done
     5829IFS=$as_save_IFS
     5830
     5831  ;;
     5832esac
     5833fi
     5834PKG_CONFIG=$ac_cv_path_PKG_CONFIG
     5835if test -n "$PKG_CONFIG"; then
     5836  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5
     5837$as_echo "$PKG_CONFIG" >&6; }
     5838else
     5839  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
     5840$as_echo "no" >&6; }
     5841fi
     5842
     5843
     5844fi
     5845if test -z "$ac_cv_path_PKG_CONFIG"; then
     5846  ac_pt_PKG_CONFIG=$PKG_CONFIG
     5847  # Extract the first word of "pkg-config", so it can be a program name with args.
     5848set dummy pkg-config; ac_word=$2
     5849{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
     5850$as_echo_n "checking for $ac_word... " >&6; }
     5851if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then :
     5852  $as_echo_n "(cached) " >&6
     5853else
     5854  case $ac_pt_PKG_CONFIG in
     5855  [\\/]* | ?:[\\/]*)
     5856  ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path.
     5857  ;;
     5858  *)
     5859  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
     5860for as_dir in $PATH
     5861do
     5862  IFS=$as_save_IFS
     5863  test -z "$as_dir" && as_dir=.
     5864    for ac_exec_ext in '' $ac_executable_extensions; do
     5865  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     5866    ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
     5867    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     5868    break 2
     5869  fi
     5870done
     5871  done
     5872IFS=$as_save_IFS
     5873
     5874  ;;
     5875esac
     5876fi
     5877ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG
     5878if test -n "$ac_pt_PKG_CONFIG"; then
     5879  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5
     5880$as_echo "$ac_pt_PKG_CONFIG" >&6; }
     5881else
     5882  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
     5883$as_echo "no" >&6; }
     5884fi
     5885
     5886  if test "x$ac_pt_PKG_CONFIG" = x; then
     5887    PKG_CONFIG=""
     5888  else
     5889    case $cross_compiling:$ac_tool_warned in
     5890yes:)
     5891{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
     5892$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
     5893ac_tool_warned=yes ;;
     5894esac
     5895    PKG_CONFIG=$ac_pt_PKG_CONFIG
     5896  fi
     5897else
     5898  PKG_CONFIG="$ac_cv_path_PKG_CONFIG"
     5899fi
     5900
     5901fi
     5902if test -n "$PKG_CONFIG"; then
     5903        _pkg_min_version=0.9.0
     5904        { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5
     5905$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; }
     5906        if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
     5907                { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
     5908$as_echo "yes" >&6; }
     5909        else
     5910                { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
     5911$as_echo "no" >&6; }
     5912                PKG_CONFIG=""
     5913        fi
     5914fi
     5915
     5916# Check whether --with-systemdsystemunitdir was given.
     5917if test "${with_systemdsystemunitdir+set}" = set; then :
     5918  withval=$with_systemdsystemunitdir;
     5919else
     5920  with_systemdsystemunitdir=auto
     5921fi
     5922
     5923if test "x$with_systemdsystemunitdir" = "xyes" -o "x$with_systemdsystemunitdir" = "xauto"; then :
     5924
     5925     def_systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd)
     5926
     5927     if test "x$def_systemdsystemunitdir" = "x"; then :
     5928  if test "x$with_systemdsystemunitdir" = "xyes"; then :
     5929  as_fn_error $? "systemd support requested but pkg-config unable to query systemd package" "$LINENO" 5
     5930fi
     5931    with_systemdsystemunitdir=no
     5932else
     5933  with_systemdsystemunitdir="$def_systemdsystemunitdir"
     5934fi
     5935fi
     5936if test "x$with_systemdsystemunitdir" != "xno"; then :
     5937  systemdsystemunitdir=$with_systemdsystemunitdir
     5938
     5939fi
     5940 if test "x$with_systemdsystemunitdir" != "xno"; then
     5941  HAVE_SYSTEMD_TRUE=
     5942  HAVE_SYSTEMD_FALSE='#'
     5943else
     5944  HAVE_SYSTEMD_TRUE='#'
     5945  HAVE_SYSTEMD_FALSE=
     5946fi
     5947
     5948
    56695949ac_config_headers="$ac_config_headers config.h"
    56705950
    5671 ac_config_files="$ac_config_files Makefile redhat/radvd.spec"
     5951ac_config_files="$ac_config_files Makefile radvd.service redhat/radvd.spec"
    56725952
    56735953cat >confcache <<\_ACEOF
     
    58036083Usually this means the macro was only invoked conditionally." "$LINENO" 5
    58046084fi
     6085if test -z "${HAVE_SYSTEMD_TRUE}" && test -z "${HAVE_SYSTEMD_FALSE}"; then
     6086  as_fn_error $? "conditional \"HAVE_SYSTEMD\" was never defined.
     6087Usually this means the macro was only invoked conditionally." "$LINENO" 5
     6088fi
    58056089
    58066090: "${CONFIG_STATUS=./config.status}"
     
    62006484# values after options handling.
    62016485ac_log="
    6202 This file was extended by radvd $as_me 2.13, which was
     6486This file was extended by radvd $as_me 2.16, which was
    62036487generated by GNU Autoconf 2.69.  Invocation command line was
    62046488
     
    62666550ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
    62676551ac_cs_version="\\
    6268 radvd config.status 2.13
     6552radvd config.status 2.16
    62696553configured by $0, generated by GNU Autoconf 2.69,
    62706554  with options \\"\$ac_cs_config\\"
     
    63986682    "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
    63996683    "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
     6684    "radvd.service") CONFIG_FILES="$CONFIG_FILES radvd.service" ;;
    64006685    "redhat/radvd.spec") CONFIG_FILES="$CONFIG_FILES redhat/radvd.spec" ;;
    64016686
  • src/router/radvd/configure.ac

    r29984 r32089  
    1414
    1515dnl If adding rcX to version, be sure to separate with a '-'
    16 AC_INIT(radvd, [2.13])
     16AC_INIT(radvd, [2.16])
    1717AC_CONFIG_SRCDIR(radvd.c)
    1818AC_CANONICAL_SYSTEM
     
    202202AC_SUBST(LOG_FACILITY)
    203203
     204# Default value for sbindir
     205prefix_temp=$prefix
     206exec_prefix_temp=$exec_prefix
     207
     208test "${prefix}" = "NONE" && prefix="${ac_default_prefix}"
     209test "${exec_prefix}" = "NONE" && exec_prefix='${prefix}'
     210
     211# Initial Value is $exec_prefix/sbin
     212sbintemp="${sbindir}"
     213
     214# Expands to $prefix/sbin
     215eval sbintemp=\"${sbintemp}\"
     216# Expands to /usr/local/sbin or /usr/sbin if --prefix is passed
     217eval sbintemp=\"${sbintemp}\"
     218SBINDIR=${sbintemp}
     219
     220AC_SUBST(SBINDIR)
     221
     222PKG_PROG_PKG_CONFIG
     223AC_ARG_WITH([systemdsystemunitdir],
     224     [AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files])],,
     225     [with_systemdsystemunitdir=auto])
     226AS_IF([test "x$with_systemdsystemunitdir" = "xyes" -o "x$with_systemdsystemunitdir" = "xauto"], [
     227     def_systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd)
     228
     229     AS_IF([test "x$def_systemdsystemunitdir" = "x"],
     230   [AS_IF([test "x$with_systemdsystemunitdir" = "xyes"],
     231    [AC_MSG_ERROR([systemd support requested but pkg-config unable to query systemd package])])
     232    with_systemdsystemunitdir=no],
     233   [with_systemdsystemunitdir="$def_systemdsystemunitdir"])])
     234AS_IF([test "x$with_systemdsystemunitdir" != "xno"],
     235      [AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir])])
     236AM_CONDITIONAL([HAVE_SYSTEMD], [test "x$with_systemdsystemunitdir" != "xno"])
     237
    204238AM_CONFIG_HEADER(config.h)
    205 AC_OUTPUT(Makefile redhat/radvd.spec)
     239AC_OUTPUT(
     240        Makefile \
     241        radvd.service \
     242        redhat/radvd.spec\
     243)
    206244
    207245cat << EOF
  • src/router/radvd/defaults.h

    r29984 r32089  
    2323#define MSG_SIZE_RECV                   1500
    2424#define MSG_SIZE_SEND                   1452
     25#define RFC2460_MIN_MTU                 1280 /* RFC2460 5. Packet Size Issues: lowest valid MTU supported by IPv6 */
    2526
    2627#define MAX2(X,Y) ( (( X ) >=  ( Y )) ? ( X ) : ( Y ))
     
    4445#define DFLT_MinDelayBetweenRAs         MIN_DELAY_BETWEEN_RAS
    4546#define DFLT_AdvDefaultPreference       0
     47#define DFLT_AdvRAMTU                   RFC2460_MIN_MTU
    4648
    4749/* Options sent with RA */
     
    112114#define MAX_AdvDefaultLifetime          9000
    113115
    114 #define MIN_AdvLinkMTU                  1280
     116#define MIN_AdvLinkMTU                  RFC2460_MIN_MTU
    115117#define MAX_AdvLinkMTU                  131072
     118
     119#define MIN_AdvRAMTU                    MIN_AdvLinkMTU
     120#define MAX_AdvRAMTU                    MAX_AdvLinkMTU
    116121
    117122#define MIN_AdvReachableTime            100
  • src/router/radvd/device-bsd44.c

    r26390 r32089  
    4141        iface->sllao.if_maxmtu = ifr.ifr_mtu;
    4242
     43        /* RFC 2460: 5. Packet Size Issues */
     44        iface->props.max_ra_option_size = iface->AdvRAMTU;
     45        iface->props.max_ra_option_size = MIN(iface->props.max_ra_option_size, MAX(iface->sllao.if_maxmtu, RFC2460_MIN_MTU));
     46
    4347        if (getifaddrs(&addresses) != 0) {
    4448                flog(LOG_ERR, "getifaddrs failed: %s(%d)", strerror(errno), errno);
     
    7074                case IFT_ISO88023:
    7175                        iface->sllao.if_prefix_len = 64;
     76                        iface->props.max_ra_option_size -= 14; /* RFC 2464 */
    7277                        break;
    7378                case IFT_FDDI:
    7479                        iface->sllao.if_prefix_len = 64;
     80                        iface->props.max_ra_option_size -= 22; /* RFC 2109 */
    7581                        break;
    7682                default:
    7783                        iface->sllao.if_prefix_len = -1;
    7884                        iface->sllao.if_maxmtu = -1;
     85                        /* Assume fragmentation handled at a lower layer. */
     86                        iface->props.max_ra_option_size -= 0;
    7987                        break;
    8088                }
     
    101109
    102110                freeifaddrs(addresses);
     111                // Regardless of link-layer, every RA message will have an IPV6 header & RA header
     112                iface->props.max_ra_option_size -= sizeof(struct ip6_hdr);
     113                iface->props.max_ra_option_size -= sizeof(struct nd_router_advert);
    103114                return 0;
    104115        }
  • src/router/radvd/device-common.c

    r29984 r32089  
    175175                        dlog(LOG_DEBUG, 4, "%s address: %s", iface->props.name, addr_str);
    176176                }
     177                /* AdvRASrcAddress: allow operator selection of RA source address */
     178                if(iface->AdvRASrcAddressList != NULL) {
     179                        iface->props.if_addr_rasrc = NULL;
     180                        for (struct AdvRASrcAddress * current = iface->AdvRASrcAddressList; current; current = current->next) {
     181                                for (int i = 0; i < iface->props.addrs_count; i++) {
     182                                        struct in6_addr cmp_addr = iface->props.if_addrs[i];
     183                                        if (0 == memcmp(&cmp_addr, &current->address, sizeof(struct in6_addr))) {
     184                                                addrtostr(&(cmp_addr), addr_str, sizeof(addr_str));
     185                                                dlog(LOG_DEBUG, 4, "AdvRASrcAddress selecting: %s", addr_str);
     186                                                iface->props.if_addr_rasrc = &iface->props.if_addrs[i];
     187                                                break;
     188                                        }
     189                                }
     190                                if(NULL != iface->props.if_addr_rasrc)
     191                                        break;
     192                        }
     193                } else {
     194                        /* AdvRASrcAddress default: Just take the first link-local */
     195                        iface->props.if_addr_rasrc = &iface->props.if_addr;
     196                }
    177197        } else {
    178198                if (iface->IgnoreIfMissing)
  • src/router/radvd/device-linux.c

    r29984 r32089  
    1818#include "defaults.h"
    1919#include "pathnames.h"
     20#include "netlink.h"
    2021
    2122#ifndef IPV6_ADDR_LINKLOCAL
     
    2324#endif
    2425
     26#ifndef ARPHRD_6LOWPAN
     27#define ARPHRD_6LOWPAN  825     /* IPv6 over LoWPAN */
     28#endif
     29
    2530static char const *hwstr(unsigned short sa_family);
     31uint32_t get_interface_linkmtu(const char *);
    2632
    2733/*
     
    4349        iface->sllao.if_maxmtu = ifr.ifr_mtu;
    4450        dlog(LOG_DEBUG, 3, "%s mtu: %d", iface->props.name, ifr.ifr_mtu);
     51
     52        /* RFC 2460: 5. Packet Size Issues */
     53        /* Get the smallest MTU between the SIOCGIFMTU value and the protocol MTU
     54         * /proc/sys/net/ipv6/conf/eth0/mtu
     55         * Because the protocol MTU _may_ be different than the physical link MTU
     56         *
     57         * If Link-layer MTU <= 1280: use 1280 (enforced by iface->AdvRAMTU)
     58         * If Link-layer MTU > 1280: use the lower of:
     59         *   - RA MTU
     60         *   - link-layer MTU
     61         *   - per-protocol MTU
     62         */
     63        iface->props.max_ra_option_size = iface->AdvRAMTU;
     64        iface->props.max_ra_option_size = MIN(iface->props.max_ra_option_size, MAX(iface->sllao.if_maxmtu, RFC2460_MIN_MTU));
     65        iface->props.max_ra_option_size = MIN(iface->props.max_ra_option_size, MAX(get_interface_linkmtu(iface->props.name), RFC2460_MIN_MTU));
    4566
    4667        if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) {
     
    6687                /* *INDENT-ON* */
    6788                dlog(LOG_DEBUG, 3, "%s hardware address: %s", iface->props.name, hwaddr);
     89                iface->props.max_ra_option_size -= 14; /* RFC 2464 */
    6890                break;
    6991#ifdef ARPHRD_FDDI
     
    7193                iface->sllao.if_hwaddr_len = 48;
    7294                iface->sllao.if_prefix_len = 64;
     95                iface->props.max_ra_option_size -= 22; /* RFC 2109 */
    7396                break;
    7497#endif                          /* ARPHDR_FDDI */
     
    78101                iface->sllao.if_prefix_len = -1;
    79102                iface->sllao.if_maxmtu = -1;
     103                /* RFC1201: fragmentation handled at a lower layer.
     104                 * native packet size is 256-512 bytes */
     105                iface->props.max_ra_option_size -= 0;
    80106                break;
    81107#endif                          /* ARPHDR_ARCNET */
    82 #ifdef ARPHRD_IEEE802154
    83         case ARPHRD_IEEE802154:
    84                 iface->sllao.if_hwaddr_len = 64;
    85                 iface->sllao.if_prefix_len = 64;
    86                 break;
    87 #endif
     108        case ARPHRD_6LOWPAN:
     109#ifdef HAVE_NETLINK
     110                /* hwaddr length differs on some L2 type lets detect them */
     111                iface->sllao.if_hwaddr_len = netlink_get_device_addr_len(iface);
     112                if (iface->sllao.if_hwaddr_len != -1) {
     113                        iface->sllao.if_hwaddr_len *= 8;
     114                        iface->sllao.if_prefix_len = 64;
     115                } else {
     116                        iface->sllao.if_prefix_len = -1;
     117                }
     118#else
     119                iface->sllao.if_hwaddr_len = -1;
     120                iface->sllao.if_prefix_len = -1;
     121#endif
     122                /* RFC4944: fragmentation handled at a lower layer.
     123                 * native packet size maxes at 127 bytes */
     124                iface->props.max_ra_option_size -= 0;
     125                break;
    88126        default:
    89127                iface->sllao.if_hwaddr_len = -1;
    90128                iface->sllao.if_prefix_len = -1;
    91129                iface->sllao.if_maxmtu = -1;
     130                /* Assume fragmentation handled at a lower layer. */
     131                iface->props.max_ra_option_size -= 0;
    92132                break;
    93133        }
     
    120160                prefix = prefix->next;
    121161        }
     162
     163        // Regardless of link-layer, every RA message will have an IPV6 header & RA header
     164        iface->props.max_ra_option_size -= sizeof(struct ip6_hdr);
     165        iface->props.max_ra_option_size -= sizeof(struct nd_router_advert);
    122166
    123167        return 0;
     
    144188
    145189        return 0;
     190}
     191
     192uint32_t get_interface_linkmtu(const char *iface)
     193{
     194        int value;
     195        FILE *fp = NULL;
     196        char proc_path[sizeof(PROC_SYS_IP6_LINKMTU) + IFNAMSIZ];
     197
     198        snprintf(proc_path, sizeof(PROC_SYS_IP6_LINKMTU) + IFNAMSIZ, PROC_SYS_IP6_LINKMTU, iface);
     199
     200        fp = fopen(proc_path, "r");
     201        if (fp) {
     202                int rc = fscanf(fp, "%d", &value);
     203                if (rc != 1) {
     204                        flog(LOG_ERR, "cannot read value from %s: %s", proc_path, strerror(errno));
     205                        exit(1);
     206                }
     207                fclose(fp);
     208        } else {
     209                flog(LOG_DEBUG,
     210                     "Correct IPv6 MTU entry not found, " "perhaps the procfs is disabled, "
     211                     "or the kernel interface has changed?");
     212                value = 1280; /* RFC2460: section 5 */
     213        }
     214
     215        return value;
    146216}
    147217
     
    391461                break;
    392462#endif
     463#ifdef ARPHRD_6LOWPAN
     464        case ARPHRD_6LOWPAN:
     465                rc = "ARPHRD_6LOWPAN";
     466                break;
     467#endif
    393468#ifdef ARPHRD_VOID
    394469        case ARPHRD_VOID:
  • src/router/radvd/gram.y

    r29984 r32089  
    2020
    2121#define YYERROR_VERBOSE 1
    22 static int countbits(int b);
    23 static int count_mask(struct sockaddr_in6 *m);
    24 static struct in6_addr get_prefix6(struct in6_addr const *addr, struct in6_addr const *mask);
    2522
    2623#if 0 /* no longer necessary? */
     
    5552%token          T_LOWPANCO
    5653%token          T_ABRO
     54%token          T_RASRCADDRESS
    5755
    5856%token  <str>   STRING
     
    7270%token          T_AdvOtherConfigFlag
    7371%token          T_AdvLinkMTU
     72%token          T_AdvRAMTU
    7473%token          T_AdvReachableTime
    7574%token          T_AdvRetransTimer
     
    127126%type   <str>   name
    128127%type   <pinfo> prefixdef
    129 %type   <ainfo> clientslist v6addrlist
     128%type   <ainfo> clientslist v6addrlist_clients
    130129%type   <rinfo> routedef
    131130%type   <rdnssinfo> rdnssdef
     
    134133%type   <abroinfo> abrodef
    135134%type   <num>   number_or_infinity
     135%type   <rasrcaddressinfo> rasrcaddresslist v6addrlist_rasrcaddress
    136136
    137137%union {
     
    148148        struct AdvLowpanCo      *lowpancoinfo;
    149149        struct AdvAbro          *abroinfo;
     150        struct AdvRASrcAddress  *rasrcaddressinfo;
    150151};
    151152
     
    231232                | lowpancodef   { ADD_TO_LL(struct AdvLowpanCo, AdvLowpanCoList, $1); }
    232233                | abrodef       { ADD_TO_LL(struct AdvAbro, AdvAbroList, $1); }
     234                | rasrcaddresslist { ADD_TO_LL(struct AdvRASrcAddress, AdvRASrcAddressList, $1); }
    233235                ;
    234236
     
    277279                        iface->AdvLinkMTU = $2;
    278280                }
     281                | T_AdvRAMTU NUMBER ';'
     282                {
     283                        iface->AdvRAMTU = $2;
     284                        iface->AdvRAMTU = MAX(MIN_AdvLinkMTU, iface->AdvRAMTU);
     285                        iface->AdvRAMTU = MIN(MAX_AdvLinkMTU, iface->AdvRAMTU);
     286                }
    279287                | T_AdvReachableTime NUMBER ';'
    280288                {
     
    331339                ;
    332340
    333 clientslist     : T_CLIENTS '{' v6addrlist '}' ';'
     341clientslist     : T_CLIENTS '{' v6addrlist_clients '}' ';'
    334342                {
    335343                        $$ = $3;
     
    337345                ;
    338346
    339 v6addrlist      : IPV6ADDR ';'
     347v6addrlist_clients      : IPV6ADDR ';'
    340348                {
    341349                        struct Clients *new = calloc(1, sizeof(struct Clients));
     
    348356                        $$ = new;
    349357                }
    350                 | v6addrlist IPV6ADDR ';'
     358                | v6addrlist_clients IPV6ADDR ';'
    351359                {
    352360                        struct Clients *new = calloc(1, sizeof(struct Clients));
     
    362370                ;
    363371
     372rasrcaddresslist        : T_RASRCADDRESS '{' v6addrlist_rasrcaddress '}' ';'
     373                {
     374                        $$ = $3;
     375                }
     376                ;
     377
     378v6addrlist_rasrcaddress : IPV6ADDR ';'
     379                {
     380                        struct AdvRASrcAddress *new = calloc(1, sizeof(struct AdvRASrcAddress));
     381                        if (new == NULL) {
     382                                flog(LOG_CRIT, "calloc failed: %s", strerror(errno));
     383                                ABORT;
     384                        }
     385
     386                        memcpy(&(new->address), $1, sizeof(struct in6_addr));
     387                        $$ = new;
     388                }
     389                | v6addrlist_rasrcaddress IPV6ADDR ';'
     390                {
     391                        struct AdvRASrcAddress *new = calloc(1, sizeof(struct AdvRASrcAddress));
     392                        if (new == NULL) {
     393                                flog(LOG_CRIT, "calloc failed: %s", strerror(errno));
     394                                ABORT;
     395                        }
     396
     397                        memcpy(&(new->address), $2, sizeof(struct in6_addr));
     398                        new->next = $1;
     399                        $$ = new;
     400                }
     401                ;
    364402
    365403prefixdef       : prefixhead optional_prefixplist ';'
     
    376414                                }
    377415
    378                                 if ( prefix->if6[0] && prefix->if6to4[0]) {
    379                                         flog(LOG_ERR, "Base6Interface and Base6to4Interface are mutually exclusive at this time");
    380                                         ABORT;
    381                                 }
    382 
    383                                 if ( prefix->if6to4[0] )
    384                                 {
    385                                         if (get_v4addr(prefix->if6to4, &dst) < 0)
    386                                         {
    387                                                 flog(LOG_ERR, "interface %s has no IPv4 addresses, disabling 6to4 prefix", prefix->if6to4 );
    388                                                 prefix->enabled = 0;
    389                                         }
    390                                         else
    391                                         {
    392                                                 *((uint16_t *)(prefix->Prefix.s6_addr)) = htons(0x2002);
    393                                                 memcpy( prefix->Prefix.s6_addr + 2, &dst, sizeof( dst ) );
    394                                         }
    395                                 }
    396 
    397416                                if ( prefix->if6[0] )
    398417                                {
    399 #ifndef HAVE_IFADDRS_H
    400                                         flog(LOG_ERR, "Base6Interface not supported in %s, line %d", filename, num_lines);
    401                                         ABORT;
    402 #else
    403                                         struct ifaddrs *ifap = 0, *ifa = 0;
    404                                         struct AdvPrefix *next = prefix->next;
    405 
    406418                                        if (prefix->PrefixLen != 64) {
    407419                                                flog(LOG_ERR, "only /64 is allowed with Base6Interface.  %s:%d", filename, num_lines);
    408420                                                ABORT;
    409421                                        }
    410 
    411                                         if (getifaddrs(&ifap) != 0)
    412                                                 flog(LOG_ERR, "getifaddrs failed: %s", strerror(errno));
    413 
    414                                         for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
    415                                                 struct sockaddr_in6 *s6 = 0;
    416                                                 struct sockaddr_in6 *mask = (struct sockaddr_in6 *)ifa->ifa_netmask;
    417                                                 struct in6_addr base6prefix;
    418                                                 char buf[INET6_ADDRSTRLEN];
    419                                                 int i;
    420 
    421                                                 if (strncmp(ifa->ifa_name, prefix->if6, IFNAMSIZ))
    422                                                         continue;
    423 
    424                                                 if (ifa->ifa_addr->sa_family != AF_INET6)
    425                                                         continue;
    426 
    427                                                 s6 = (struct sockaddr_in6 *)(ifa->ifa_addr);
    428 
    429                                                 if (IN6_IS_ADDR_LINKLOCAL(&s6->sin6_addr))
    430                                                         continue;
    431 
    432                                                 base6prefix = get_prefix6(&s6->sin6_addr, &mask->sin6_addr);
    433                                                 for (i = 0; i < 8; ++i) {
    434                                                         prefix->Prefix.s6_addr[i] &= ~mask->sin6_addr.s6_addr[i];
    435                                                         prefix->Prefix.s6_addr[i] |= base6prefix.s6_addr[i];
    436                                                 }
    437                                                 memset(&prefix->Prefix.s6_addr[8], 0, 8);
    438                                                 prefix->AdvRouterAddr = 1;
    439                                                 prefix->AutoSelected = 1;
    440                                                 prefix->next = next;
    441 
    442                                                 if (inet_ntop(ifa->ifa_addr->sa_family, (void *)&(prefix->Prefix), buf, sizeof(buf)) == NULL)
    443                                                         flog(LOG_ERR, "%s: inet_ntop failed in %s, line %d!", ifa->ifa_name, filename, num_lines);
    444                                                 else
    445                                                         dlog(LOG_DEBUG, 3, "auto-selected prefix %s/%d on interface %s from interface %s",
    446                                                                 buf, prefix->PrefixLen, iface->props.name, ifa->ifa_name);
    447 
    448                                                 /* Taking only one prefix from the Base6Interface.  Taking more than one would require allocating new
    449                                                    prefixes and building a list.  I'm not sure how to do that from here. So for now, break. */
    450                                                 break;
    451                                         }
    452 
    453                                         if (ifap)
    454                                                 freeifaddrs(ifap);
    455 #endif /* ifndef HAVE_IFADDRS_H */
    456422                                }
    457423                        }
     
    467433
    468434                        if (!memcmp($2, &zeroaddr, sizeof(struct in6_addr))) {
    469 #ifndef HAVE_IFADDRS_H
    470                                 flog(LOG_ERR, "invalid all-zeros prefix in %s, line %d", filename, num_lines);
    471                                 ABORT;
    472 #else
    473                                 struct ifaddrs *ifap = 0, *ifa = 0;
    474                                 struct AdvPrefix *next = iface->AdvPrefixList;
    475 
    476                                 while (next) {
    477                                         if (next->AutoSelected) {
    478                                                 flog(LOG_ERR, "auto selecting prefixes works only once per interface.  See %s, line %d", filename, num_lines);
    479                                                 ABORT;
    480                                         }
    481                                         next = next->next;
    482                                 }
    483                                 next = 0;
    484 
    485                                 dlog(LOG_DEBUG, 5, "all-zeros prefix in %s, line %d", filename, num_lines);
    486 
    487                                 if (getifaddrs(&ifap) != 0)
    488                                         flog(LOG_ERR, "getifaddrs failed: %s", strerror(errno));
    489 
    490                                 for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
    491                                         struct sockaddr_in6 *s6 = (struct sockaddr_in6 *)ifa->ifa_addr;
    492                                         struct sockaddr_in6 *mask = (struct sockaddr_in6 *)ifa->ifa_netmask;
    493                                         char buf[INET6_ADDRSTRLEN];
    494 
    495                                         if (strncmp(ifa->ifa_name, iface->props.name, IFNAMSIZ))
    496                                                 continue;
    497 
    498                                         if (ifa->ifa_addr->sa_family != AF_INET6)
    499                                                 continue;
    500 
    501                                         s6 = (struct sockaddr_in6 *)(ifa->ifa_addr);
    502 
    503                                         if (IN6_IS_ADDR_LINKLOCAL(&s6->sin6_addr))
    504                                                 continue;
    505 
    506                                         prefix = malloc(sizeof(struct AdvPrefix));
    507 
    508                                         if (prefix == NULL) {
    509                                                 flog(LOG_CRIT, "malloc failed: %s", strerror(errno));
    510                                                 ABORT;
    511                                         }
    512 
    513                                         prefix_init_defaults(prefix);
    514                                         prefix->Prefix = get_prefix6(&s6->sin6_addr, &mask->sin6_addr);
    515                                         prefix->AdvRouterAddr = 1;
    516                                         prefix->AutoSelected = 1;
    517                                         prefix->next = next;
    518                                         next = prefix;
    519 
    520                                         if (prefix->PrefixLen == 0)
    521                                                 prefix->PrefixLen = count_mask(mask);
    522 
    523                                         if (inet_ntop(ifa->ifa_addr->sa_family, (void *)&(prefix->Prefix), buf, sizeof(buf)) == NULL)
    524                                                 flog(LOG_ERR, "%s: inet_ntop failed in %s, line %d!", ifa->ifa_name, filename, num_lines);
    525                                         else
    526                                                 dlog(LOG_DEBUG, 3, "auto-selected prefix %s/%d on interface %s", buf, prefix->PrefixLen, ifa->ifa_name);
    527                                 }
    528 
    529                                 if (!prefix) {
    530                                         flog(LOG_WARNING, "no auto-selected prefix on interface %s, disabling advertisements",  iface->props.name);
    531                                 }
    532 
    533                                 if (ifap)
    534                                         freeifaddrs(ifap);
    535 #endif /* ifndef HAVE_IFADDRS_H */
    536                         }
    537                         else {
    538                                 prefix = malloc(sizeof(struct AdvPrefix));
    539 
    540                                 if (prefix == NULL) {
    541                                         flog(LOG_CRIT, "malloc failed: %s", strerror(errno));
    542                                         ABORT;
    543                                 }
    544 
    545                                 prefix_init_defaults(prefix);
    546 
    547                                 if ($4 > MAX_PrefixLen)
    548                                 {
    549                                         flog(LOG_ERR, "invalid prefix length in %s, line %d", filename, num_lines);
    550                                         ABORT;
    551                                 }
    552 
    553                                 prefix->PrefixLen = $4;
    554 
    555                                 memcpy(&prefix->Prefix, $2, sizeof(struct in6_addr));
    556                         }
     435                                flog(LOG_WARNING, "invalid all-zeros prefix in %s, line %d", filename, num_lines);
     436                        }
     437                        prefix = malloc(sizeof(struct AdvPrefix));
     438
     439                        if (prefix == NULL) {
     440                                flog(LOG_CRIT, "malloc failed: %s", strerror(errno));
     441                                ABORT;
     442                        }
     443
     444                        prefix_init_defaults(prefix);
     445
     446                        if ($4 > MAX_PrefixLen)
     447                        {
     448                                flog(LOG_ERR, "invalid prefix length in %s, line %d", filename, num_lines);
     449                                ABORT;
     450                        }
     451
     452                        prefix->PrefixLen = $4;
     453
     454                        memcpy(&prefix->Prefix, $2, sizeof(struct in6_addr));
    557455                }
    558456                ;
     
    570468                {
    571469                        if (prefix) {
    572                                 if (prefix->AutoSelected) {
    573                                         struct AdvPrefix *p = prefix;
    574                                         do {
    575                                                 p->AdvOnLinkFlag = $2;
    576                                                 p = p->next;
    577                                         } while (p && p->AutoSelected);
    578                                 }
    579                                 else
    580                                         prefix->AdvOnLinkFlag = $2;
     470                                prefix->AdvOnLinkFlag = $2;
    581471                        }
    582472                }
     
    584474                {
    585475                        if (prefix) {
    586                                 if (prefix->AutoSelected) {
    587                                         struct AdvPrefix *p = prefix;
    588                                         do {
    589                                                 p->AdvAutonomousFlag = $2;
    590                                                 p = p->next;
    591                                         } while (p && p->AutoSelected);
    592                                 }
    593                                 else
    594                                         prefix->AdvAutonomousFlag = $2;
     476                                prefix->AdvAutonomousFlag = $2;
    595477                        }
    596478                }
     
    598480                {
    599481                        if (prefix) {
    600                                 if (prefix->AutoSelected && $2 == 0)
    601                                         flog(LOG_WARNING, "prefix automatically selected, AdvRouterAddr always enabled, ignoring config line %d", num_lines);
    602                                 else
    603                                         prefix->AdvRouterAddr = $2;
     482                                prefix->AdvRouterAddr = $2;
    604483                        }
    605484                }
     
    607486                {
    608487                        if (prefix) {
    609                                 if (prefix->AutoSelected) {
    610                                         struct AdvPrefix *p = prefix;
    611                                         do {
    612                                                 p->AdvValidLifetime = $2;
    613                                                 p->curr_validlft = $2;
    614                                                 p = p->next;
    615                                         } while (p && p->AutoSelected);
    616                                 }
    617                                 else {
    618                                         prefix->AdvValidLifetime = $2;
    619                                         prefix->curr_validlft = $2;
    620                                 }
     488                                prefix->AdvValidLifetime = $2;
     489                                prefix->curr_validlft = $2;
    621490                        }
    622491                }
     
    624493                {
    625494                        if (prefix) {
    626                                 if (prefix->AutoSelected) {
    627                                         struct AdvPrefix *p = prefix;
    628                                         do {
    629                                                 p->AdvPreferredLifetime = $2;
    630                                                 p->curr_preferredlft = $2;
    631                                                 p = p->next;
    632                                         } while (p && p->AutoSelected);
    633                                 }
    634                                 else {
    635                                         prefix->AdvPreferredLifetime = $2;
    636                                         prefix->curr_preferredlft = $2;
    637                                 }
     495                                prefix->AdvPreferredLifetime = $2;
     496                                prefix->curr_preferredlft = $2;
    638497                        }
    639498                }
     
    652511                | T_Base6Interface name ';'
    653512                {
     513#ifndef HAVE_IFADDRS_H
     514                        flog(LOG_ERR, "Base6Interface not supported in %s, line %d", filename, num_lines);
     515                        ABORT;
     516#else
    654517                        if (prefix) {
    655                                 if (prefix->AutoSelected) {
    656                                         flog(LOG_ERR, "automatically selecting the prefix and Base6Interface are mutually exclusive");
    657                                         ABORT;
    658                                 } /* fallthrough */
    659518                                dlog(LOG_DEBUG, 4, "using prefixes on interface %s for prefixes on interface %s", $2, iface->props.name);
    660519                                strncpy(prefix->if6, $2, IFNAMSIZ-1);
    661520                                prefix->if6[IFNAMSIZ-1] = '\0';
    662521                        }
     522#endif
    663523                }
    664524
    665525                | T_Base6to4Interface name ';'
    666526                {
     527#ifndef HAVE_IFADDRS_H
     528                        flog(LOG_ERR, "Base6to4Interface not supported in %s, line %d", filename, num_lines);
     529                        ABORT;
     530#else
    667531                        if (prefix) {
    668                                 if (prefix->AutoSelected) {
    669                                         flog(LOG_ERR, "automatically selecting the prefix and Base6to4Interface are mutually exclusive");
    670                                         ABORT;
    671                                 } /* fallthrough */
    672532                                dlog(LOG_DEBUG, 4, "using interface %s for 6to4 prefixes on interface %s", $2, iface->props.name);
    673533                                strncpy(prefix->if6to4, $2, IFNAMSIZ-1);
    674534                                prefix->if6to4[IFNAMSIZ-1] = '\0';
    675535                        }
     536#endif
    676537                }
    677538                ;
     
    1037898%%
    1038899
    1039 static int countbits(int b)
    1040 {
    1041         int count;
    1042 
    1043         for (count = 0; b != 0; count++) {
    1044                 b &= b - 1; // this clears the LSB-most set bit
    1045         }
    1046 
    1047         return (count);
    1048 }
    1049 
    1050 static int count_mask(struct sockaddr_in6 *m)
    1051 {
    1052         struct in6_addr *in6 = &m->sin6_addr;
    1053         int i;
    1054         int count = 0;
    1055 
    1056         for (i = 0; i < 16; ++i) {
    1057                 count += countbits(in6->s6_addr[i]);
    1058         }
    1059         return count;
    1060 }
    1061 
    1062 static struct in6_addr get_prefix6(struct in6_addr const *addr, struct in6_addr const *mask)
    1063 {
    1064         struct in6_addr prefix = *addr;
    1065         int i = 0;
    1066 
    1067         for (; i < 16; ++i) {
    1068                 prefix.s6_addr[i] &= mask->s6_addr[i];
    1069         }
    1070 
    1071         return prefix;
    1072 }
    1073 
    1074900static void cleanup(void)
    1075901{
  • src/router/radvd/interface.c

    r29984 r32089  
    4747
    4848        iface->AdvLinkMTU = DFLT_AdvLinkMTU;
     49        iface->AdvRAMTU = DFLT_AdvRAMTU;
    4950
    5051}
     
    8889         * iface->props.if_addr and keep a list off all addrs in iface->props.if_addrs */
    8990        if (setup_iface_addrs(iface) < 0) {
     91                return -1;
     92        }
     93
     94        /* Check if we a usable RA source address */
     95        if(iface->props.if_addr_rasrc == NULL) {
     96                dlog(LOG_DEBUG, 5, "no configured AdvRASrcAddress present, skipping send");
    9097                return -1;
    9198        }
     
    114121        prefix->DeprecatePrefixFlag = DFLT_DeprecatePrefixFlag;
    115122        prefix->DecrementLifetimesFlag = DFLT_DecrementLifetimesFlag;
    116         prefix->if6to4[0] = 0;
    117         prefix->enabled = 1;
    118123
    119124        prefix->curr_validlft = prefix->AdvValidLifetime;
     
    151156        int res = 0;
    152157        int MIPv6 = 0;
     158        struct in6_addr zeroaddr;
     159        memset(&zeroaddr, 0, sizeof(zeroaddr));
    153160
    154161        /* Check if we use Mobile IPv6 extensions */
     
    265272                        flog(LOG_ERR, "invalid route prefix length (%u) for %s", route->PrefixLen, iface->props.name);
    266273                        res = -1;
     274                }
     275
     276                /* For the default route 0::/0, we need to explicitly check the
     277                 * lifetime against the AdvDefaultLifetime value.
     278                 *
     279                 * If exactly one of the two has a zero value, then nodes processing
     280                 * the RA may have a flap in their default route.
     281                 *
     282                 * AdvDefaultLifetime == 0 && route.AdvRouteLifetime > 0:
     283                 * - default route is deleted and then re-added.
     284                 * AdvDefaultLifetime > 0 && route.AdvRouteLifetime == 0:
     285                 * - default route is added and then deleted.
     286                 */
     287                if(IN6_IS_ADDR_UNSPECIFIED(&(route->Prefix))) {
     288                        int route_zerolife = (route->AdvRouteLifetime == 0);
     289                        int defaultroute_zerolife = (iface->ra_header_info.AdvDefaultLifetime == 0);
     290                        if( route_zerolife ^ defaultroute_zerolife ) {
     291                                flog(LOG_ERR, "route 0::/0 lifetime (%u) conflicts with AdvDefaultLifetime (%u), default routes will flap!",
     292                                                route->AdvRouteLifetime, iface->ra_header_info.AdvDefaultLifetime);
     293                                // res = -1; // In some future version, abort on this configuration error.
     294                        }
    267295                }
    268296
  • src/router/radvd/log.c

    r26390 r32089  
    3636        case L_STDERR:
    3737                break;
     38        case L_STDERR_CLEAN:
     39                /* fallthrough */
    3840        case L_STDERR_SYSLOG:
    3941                /* fallthrough */
     
    9193
    9294                fprintf(stderr, "[%s] %s (%d): %s\n", tstamp, log_ident, getpid(), buff);
     95                fflush(stderr);
     96                break;
     97        case L_STDERR_CLEAN:
     98                fprintf(stderr, "%s\n", buff);
    9399                fflush(stderr);
    94100                break;
  • src/router/radvd/log.h

    r26390 r32089  
    2020#define L_STDERR_SYSLOG 3
    2121#define L_LOGFILE       4
     22#define L_STDERR_CLEAN  5
    2223
    2324#define LOG_TIME_FORMAT "%b %d %H:%M:%S"
  • src/router/radvd/netlink.c

    r29987 r32089  
    3636#endif
    3737
     38
     39struct iplink_req {
     40        struct nlmsghdr         n;
     41        struct ifinfomsg        i;
     42        char                    buf[1024];
     43};
     44
     45int netlink_get_device_addr_len(struct Interface *iface)
     46{
     47        struct iplink_req req = {};
     48        struct iovec iov = { &req, sizeof(req) };
     49        struct sockaddr_nl sa = {};
     50        struct msghdr msg = { (void *)&sa, sizeof(sa), &iov, 1, NULL, 0, 0 };
     51        int sock, len, addr_len = -1;
     52        unsigned short type;
     53        char answer[32768];
     54        struct rtattr *tb;
     55
     56        /* nl_pid (for linux kernel) and nl_groups (unicast) should be zero */
     57        sa.nl_family = AF_NETLINK;
     58        req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
     59        req.n.nlmsg_flags = NLM_F_REQUEST;
     60        req.n.nlmsg_type = RTM_GETLINK;
     61        req.i.ifi_index = iface->props.if_index;
     62
     63        sock = netlink_socket();
     64        if (sock == -1)
     65                return -1;
     66
     67        len = sendmsg(sock, &msg, 0);
     68        if (len == -1) {
     69                flog(LOG_ERR, "netlink: sendmsg for addr_len failed: %s", strerror(errno));
     70                goto out;
     71        }
     72
     73        iov.iov_base = answer;
     74        iov.iov_len = sizeof(answer);
     75        len = recvmsg(sock, &msg, 0);
     76        if (len == -1) {
     77                flog(LOG_ERR, "netlink: recvmsg for addr_len failed: %s", strerror(errno));
     78                goto out;
     79        }
     80
     81        if (len < NLMSG_LENGTH(sizeof(struct ifinfomsg)))
     82                goto out;
     83        len -= NLMSG_LENGTH(sizeof(struct ifinfomsg));
     84
     85        tb = (struct rtattr *)(answer + NLMSG_LENGTH(sizeof(struct ifinfomsg)));
     86        while (RTA_OK(tb, len)) {
     87                type = tb->rta_type & ~NLA_F_NESTED;
     88                if (type == IFLA_ADDRESS) {
     89                        addr_len = RTA_PAYLOAD(tb);
     90                        break;
     91                }
     92                tb = RTA_NEXT(tb, len);
     93        }
     94
     95out:
     96        close(sock);
     97
     98        return addr_len;
     99}
    38100
    39101void process_netlink_msg(int sock, struct Interface * ifaces)
     
    127189                                int count = get_iface_addrs(iface->props.name, NULL, &if_addrs);
    128190
    129                                 if (count != iface->props.addrs_count &&
     191                                if (count != iface->props.addrs_count ||
    130192                                        0 != memcmp(if_addrs, iface->props.if_addrs, count * sizeof(struct in6_addr))) {
    131193                                        dlog(LOG_DEBUG, 3, "netlink: %s, ifindex %d, addresses are different",
  • src/router/radvd/netlink.h

    r26390 r32089  
    1818#include "radvd.h"
    1919
     20int netlink_get_device_addr_len(struct Interface *iface);
    2021void process_netlink_msg(int sock, struct Interface * ifaces);
    2122int netlink_socket(void);
  • src/router/radvd/process.c

    r29984 r32089  
    256256                                while (prefix) {
    257257                                        char prefix_str[INET6_ADDRSTRLEN];
    258                                         if (prefix->enabled && (prefix->PrefixLen == pinfo->nd_opt_pi_prefix_len)
     258                                        if ((prefix->PrefixLen == pinfo->nd_opt_pi_prefix_len)
    259259                                            && addr_match(&prefix->Prefix, &pinfo->nd_opt_pi_prefix, prefix->PrefixLen)) {
    260260                                                addrtostr(&prefix->Prefix, prefix_str, sizeof(prefix_str));
  • src/router/radvd/radvd.8.man

    r26390 r32089  
    169169Pierre Ossman   <pierre@ossman.eu>      - RFC6106 (DNSSL) support
    170170Varka Bhadram   <varkabhadram@gmail.com> - 6LoWPAN-ND (RFC6775) support
     171Robin H. Johnson        <robbat2@gentoo.org>    - RA splitting per RFC 6980 & RFC4861#6.2.3
    171172.fi
  • src/router/radvd/radvd.c

    r26390 r32089  
    3838"  -h, --help              Show this help screen.\n"
    3939"  -l, --logfile=PATH      Set the log file.\n"
    40 "  -m, --logmethod=X       Set method to: syslog, stderr, stderr_syslog, logfile, or none.\n"
     40"  -m, --logmethod=X       Set method to: syslog, stderr, stderr_syslog, logfile,\n"
     41"                          stderr_clean, or none.\n"
    4142"  -n, --nodaemon          Prevent the daemonizing.\n"
    4243"  -p, --pidfile=PATH      Set the pid file.\n"
     
    232233                        } else if (!strcmp(optarg, "stderr")) {
    233234                                log_method = L_STDERR;
     235                        } else if (!strcmp(optarg, "stderr_clean")) {
     236                                log_method = L_STDERR_CLEAN;
    234237                        } else if (!strcmp(optarg, "logfile")) {
    235238                                log_method = L_LOGFILE;
     
    290293        if (configtest) {
    291294                set_debuglevel(1);
    292                 log_method = L_STDERR;
     295                switch (log_method) {
     296                        case L_STDERR:
     297                        case L_STDERR_CLEAN:
     298                                break;
     299                        case L_STDERR_SYSLOG:
     300                        case L_NONE:
     301                        case L_SYSLOG:
     302                        case L_LOGFILE:
     303                        default:
     304                                log_method = L_STDERR;
     305                        break;
     306                }
    293307        }
    294308
  • src/router/radvd/radvd.conf.5.man

    r29984 r32089  
    3333        list of DNSSL definitions
    3434        list of ABRO definitions
     35        list of acceptable RA source addresses
    3536.B };
    3637.fi
     
    104105.nf
    105106.BR clients " " {
     107        list of IPv6 addresses
     108.B };
     109.fi
     110
     111By default radvd will use the first link-local address for the interface as the
     112source address for route advertisements. This can be overwritten by manually
     113setting the list of acceptable source addresses. If done, radvd will use the
     114first address from the interface that is present in the configured source
     115addresses only. This functionality will NOT spoof the source address, but may be useful in combination with VRRP or other functionality that
     116
     117.nf
     118.BR AdvRASrcAddress " " {
    106119        list of IPv6 addresses
    107120.B };
     
    732745Z. Shelby, S. Chakrabarti, E. Nordmark and  C. Bormann " Neighbor Discovery Optimization for IPv6 over Low-Power
    733746Wireless Personal Area Networks (6LoWPANs)", RFC 6775, November 2012.
     747.PP
     748Gont, F. "Security Implications of IPv6 Fragmentation with IPv6 Neighbor Discovery",
     749RFC 6980, August 2013.
     750.PP
     751Yourtchenko, A. and Colitti, L. "Reducing Energy Consumption of Router Advertisements",
     752RFC 7772, February 2016.
     753
    734754.SH "SEE ALSO"
    735755
    736756.BR radvd (8),
    737757.BR radvdump (8)
    738 
    739 .SH BUGS
    740 radvd does not support splitting up RAs to multiple packets (RFC4861 6.2.3 last paragraph).
    741 In practise this limits advertising to ~45 prefixes on a link, but there is no reason to
    742 be able to so.
    743 
  • src/router/radvd/radvd.h

    r29984 r32089  
    4444#define SAFE_BUFFER_INIT (struct safe_buffer){.should_free = 0, .allocated = 0, .used = 0, .buffer = 0}
    4545
     46struct safe_buffer_list {
     47        struct safe_buffer *sb;
     48        struct safe_buffer_list *next;
     49};
    4650
    4751struct Interface {
     
    7074                struct in6_addr *if_addrs; /* all the addrs */
    7175                int addrs_count;
     76                struct in6_addr *if_addr_rasrc; /* selected AdvRASrcAddress or NULL */
     77                uint32_t max_ra_option_size;
    7278        } props;
    7379
     
    95101
    96102        uint32_t AdvLinkMTU; /* XXX: sllao also has an if_maxmtu value...Why? */
     103        uint32_t AdvRAMTU; /* MTU used for RA */
    97104
    98105        struct sllao {
     
    118125        struct AdvAbro *AdvAbroList;
    119126
     127        struct AdvRASrcAddress *AdvRASrcAddressList;
     128
    120129        int lineno; /* On what line in the config file was this iface defined? */
    121130};
     
    145154        /* 6to4 etc. extensions */
    146155        char if6to4[IFNAMSIZ];
    147         int enabled;
    148         int AutoSelected;
    149156
    150157        /* Select prefixes from this interface. */
     
    208215
    209216        struct AdvAbro *next;
     217};
     218
     219struct AdvRASrcAddress {
     220        struct in6_addr address;
     221
     222        struct AdvRASrcAddress *next;
    210223};
    211224
     
    311324
    312325/* util.c */
     326int countbits(int b);
     327int count_mask(struct sockaddr_in6 *m);
     328struct in6_addr get_prefix6(struct in6_addr const *addr, struct in6_addr const *mask);
    313329char * strdupf(char const * format, ...) __attribute__ ((format(printf, 1, 2)));
    314330double rand_between(double, double);
    315331int check_dnssl_presence(struct AdvDNSSL *, const char *);
    316332int check_rdnss_presence(struct AdvRDNSS *, struct in6_addr *);
     333void safe_buffer_resize(struct safe_buffer * sb, size_t new_capacity);
    317334size_t safe_buffer_append(struct safe_buffer * sb, void const * m, size_t count);
    318335size_t safe_buffer_pad(struct safe_buffer * sb, size_t count);
     
    320337ssize_t writen(int fd, const void *buf, size_t count);
    321338struct safe_buffer * new_safe_buffer(void);
    322 void addrtostr(struct in6_addr *, char *, size_t);
     339void addrtostr(struct in6_addr const *, char *, size_t);
    323340void safe_buffer_free(struct safe_buffer * sb);
     341struct safe_buffer_list * new_safe_buffer_list(void);
     342void safe_buffer_list_free(struct safe_buffer_list * sbl);
     343struct safe_buffer_list * safe_buffer_list_append(struct safe_buffer_list * sbl);
     344void safe_buffer_list_to_safe_buffer(struct safe_buffer_list * sbl, struct safe_buffer *sb);
    324345
    325346/* privsep.c */
  • src/router/radvd/redhat/radvd.spec

    r29984 r32089  
    66Summary: A Router Advertisement daemon
    77Name: radvd
    8 Version: 2.13
     8Version: 2.16
    99Release: 1
    1010# The code includes the advertising clause, so it's GPL-incompatible
  • src/router/radvd/scanner.l

    r26390 r32089  
    5151lowpanco                { return T_LOWPANCO; }
    5252abro                    { return T_ABRO; }
     53AdvRASrcAddress { return T_RASRCADDRESS; }
    5354
    5455IgnoreIfMissing         { return T_IgnoreIfMissing; }
     
    5960AdvOtherConfigFlag      { return T_AdvOtherConfigFlag; }
    6061AdvLinkMTU              { return T_AdvLinkMTU; }
     62AdvRAMTU                { return T_AdvRAMTU; }
    6163AdvReachableTime        { return T_AdvReachableTime; }
    6264AdvRetransTimer         { return T_AdvRetransTimer; }
  • src/router/radvd/send.c

    r29984 r32089  
    2020static int really_send(int sock, struct in6_addr const *dest, struct properties const *props, struct safe_buffer const *sb);
    2121static int send_ra(int sock, struct Interface *iface, struct in6_addr const *dest);
    22 static void build_ra(struct safe_buffer * sb, struct Interface const * iface);
     22static struct safe_buffer_list * build_ra_options(struct Interface const * iface, struct in6_addr const *dest);
    2323
    2424static int ensure_iface_setup(int sock, struct Interface *iface);
     
    2626static void update_iface_times(struct Interface * iface);
    2727
     28// Option helpers
     29static size_t serialize_domain_names(struct safe_buffer * safe_buffer, struct AdvDNSSL const *dnssl);
     30
     31// Options that only need a single block
    2832static void add_ra_header(struct safe_buffer * sb, struct ra_header_info const * ra_header_info, int cease_adv);
    29 static void add_prefix(struct safe_buffer * sb, struct AdvPrefix const * prefix, int cease_adv);
    30 static void add_route(struct safe_buffer * sb, struct AdvRoute const *route, int cease_adv);
    31 static void add_rdnss(struct safe_buffer * sb, struct AdvRDNSS const *rdnss, int cease_adv);
    32 static size_t serialize_domain_names(struct safe_buffer * safe_buffer, struct AdvDNSSL const *dnssl);
    33 static void add_dnssl(struct safe_buffer * sb, struct AdvDNSSL const *dnssl, int cease_adv);
    34 static void add_mtu(struct safe_buffer * sb, uint32_t AdvLinkMTU);
    35 static void add_sllao(struct safe_buffer * sb, struct sllao const *sllao);
    36 static void add_mipv6_rtr_adv_interval(struct safe_buffer * sb, double MaxRtrAdvInterval);
    37 static void add_mipv6_home_agent_info(struct safe_buffer * sb, struct mipv6 const * mipv6);
    38 static void add_lowpanco(struct safe_buffer * sb, struct AdvLowpanCo const *lowpanco);
    39 static void add_abro(struct safe_buffer * sb, struct AdvAbro const *abroo);
     33static void add_ra_option_prefix(struct safe_buffer * sb, struct AdvPrefix const * prefix, int cease_adv);
     34static void add_ra_option_mtu(struct safe_buffer * sb, uint32_t AdvLinkMTU);
     35static void add_ra_option_sllao(struct safe_buffer * sb, struct sllao const *sllao);
     36static void add_ra_option_mipv6_rtr_adv_interval(struct safe_buffer * sb, double MaxRtrAdvInterval);
     37static void add_ra_option_mipv6_home_agent_info(struct safe_buffer * sb, struct mipv6 const * mipv6);
     38static void add_ra_option_lowpanco(struct safe_buffer * sb, struct AdvLowpanCo const *lowpanco);
     39static void add_ra_option_abro(struct safe_buffer * sb, struct AdvAbro const *abroo);
     40
     41// Options that generate 0 or more blocks
     42static struct safe_buffer_list* add_ra_options_prefix(struct safe_buffer_list * sbl, struct Interface const * iface, char const * ifname, struct AdvPrefix const * prefix, int cease_adv, struct in6_addr const *dest);
     43static struct safe_buffer_list* add_ra_options_route(struct safe_buffer_list * sbl, struct Interface const * iface, struct AdvRoute const *route, int cease_adv, struct in6_addr const *dest);
     44static struct safe_buffer_list* add_ra_options_rdnss(struct safe_buffer_list * sbl, struct Interface const * iface, struct AdvRDNSS const *rdnss, int cease_adv, struct in6_addr const *dest);
     45static struct safe_buffer_list* add_ra_options_dnssl(struct safe_buffer_list * sbl, struct Interface const * iface, struct AdvDNSSL const *dnssl, int cease_adv, struct in6_addr const *dest);
     46
     47// Scheduling of options per RFC7772
     48static int schedule_helper(struct in6_addr const *dest, struct Interface const *iface, int option_lifetime);
     49static int schedule_option_prefix(struct in6_addr const *dest, struct Interface const *iface, struct AdvPrefix const *prefix);
     50static int schedule_option_route(struct in6_addr const *dest, struct Interface const *iface, struct AdvRoute const *route);
     51static int schedule_option_rdnss(struct in6_addr const *dest, struct Interface const *iface, struct AdvRDNSS const *rdnss);
     52static int schedule_option_dnssl(struct in6_addr const *dest, struct Interface const *iface, struct AdvDNSSL const *dnssl);
     53static int schedule_option_mtu(struct in6_addr const *dest, struct Interface const *iface);
     54static int schedule_option_sllao(struct in6_addr const *dest, struct Interface const *iface);
     55static int schedule_option_mipv6_rtr_adv_interval(struct in6_addr const *dest, struct Interface const *iface);
     56static int schedule_option_mipv6_home_agent_info(struct in6_addr const *dest, struct Interface const *iface);
     57static int schedule_option_lowpanco(struct in6_addr const *dest, struct Interface const *iface);
     58static int schedule_option_abro(struct in6_addr const *dest, struct Interface const *iface);
    4059
    4160#ifdef UNIT_TEST
     
    91110        if (get_debuglevel() >= 5) {
    92111                char address_text[INET6_ADDRSTRLEN] = { "" };
    93                 inet_ntop(AF_INET6, dest, address_text, INET6_ADDRSTRLEN);
     112                addrtostr(dest, address_text, INET6_ADDRSTRLEN);
    94113                dlog(LOG_DEBUG, 5, "Not answering request from %s, not configured", address_text);
    95114        }
     
    139158        struct AdvPrefix *prefix = iface->AdvPrefixList;
    140159        while (prefix) {
    141                 if (prefix->enabled && (!prefix->DecrementLifetimesFlag || prefix->curr_preferredlft > 0)) {
     160                if ((!prefix->DecrementLifetimesFlag || prefix->curr_preferredlft > 0)) {
    142161                        if (!(iface->state_info.cease_adv && prefix->DeprecatePrefixFlag)) {
    143162                                if (prefix->DecrementLifetimesFlag) {
     
    192211}
    193212
    194 static void add_prefix(struct safe_buffer * sb, struct AdvPrefix const *prefix, int cease_adv)
     213static void add_ra_option_prefix(struct safe_buffer * sb, struct AdvPrefix const * prefix, int cease_adv)
     214{
     215        struct nd_opt_prefix_info pinfo;
     216
     217        memset(&pinfo, 0, sizeof(pinfo));
     218
     219        pinfo.nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION;
     220        pinfo.nd_opt_pi_len = 4;
     221        pinfo.nd_opt_pi_prefix_len = prefix->PrefixLen;
     222
     223        pinfo.nd_opt_pi_flags_reserved = (prefix->AdvOnLinkFlag) ? ND_OPT_PI_FLAG_ONLINK : 0;
     224        pinfo.nd_opt_pi_flags_reserved |= (prefix->AdvAutonomousFlag) ? ND_OPT_PI_FLAG_AUTO : 0;
     225        /* Mobile IPv6 ext */
     226        pinfo.nd_opt_pi_flags_reserved |= (prefix->AdvRouterAddr) ? ND_OPT_PI_FLAG_RADDR : 0;
     227
     228        if (cease_adv && prefix->DeprecatePrefixFlag) {
     229                /* RFC4862, 5.5.3, step e) */
     230                if (prefix->curr_validlft < MIN_AdvValidLifetime) {
     231                        pinfo.nd_opt_pi_valid_time = htonl(prefix->curr_validlft);
     232                } else {
     233                        pinfo.nd_opt_pi_valid_time = htonl(MIN_AdvValidLifetime);
     234                }
     235                pinfo.nd_opt_pi_preferred_time = 0;
     236        } else {
     237                pinfo.nd_opt_pi_valid_time = htonl(prefix->curr_validlft);
     238                pinfo.nd_opt_pi_preferred_time = htonl(prefix->curr_preferredlft);
     239        }
     240
     241        memcpy(&pinfo.nd_opt_pi_prefix, &prefix->Prefix, sizeof(struct in6_addr));
     242
     243        safe_buffer_append(sb, &pinfo, sizeof(pinfo));
     244}
     245
     246static struct safe_buffer_list * add_auto_prefixes_6to4(struct safe_buffer_list * sbl, struct Interface const * iface, char const * ifname, struct AdvPrefix const *prefix, int cease_adv, struct in6_addr const *dest)
     247{
     248#ifdef HAVE_IFADDRS_H
     249        struct AdvPrefix xprefix = *prefix;
     250        unsigned int dst;
     251        if (get_v4addr(prefix->if6to4, &dst) < 0) {
     252                flog(LOG_ERR, "Base6to4interface %s has no IPv4 addresses", prefix->if6to4);
     253        } else {
     254                memcpy(xprefix.Prefix.s6_addr + 2, &dst, sizeof(dst));
     255                *((uint16_t *)(xprefix.Prefix.s6_addr)) = htons(0x2002);
     256                xprefix.PrefixLen = 64;
     257
     258                char pfx_str[INET6_ADDRSTRLEN];
     259                addrtostr(&xprefix.Prefix, pfx_str, sizeof(pfx_str));
     260                dlog(LOG_DEBUG, 3, "auto-selected prefix %s/%d on interface %s",
     261                        pfx_str, xprefix.PrefixLen, ifname);
     262
     263                /* TODO: Something must be done with these. */
     264                (void)xprefix.curr_validlft;
     265                (void)xprefix.curr_preferredlft;
     266
     267                if(cease_adv || schedule_option_prefix(dest, iface, &xprefix)) {
     268                        sbl = safe_buffer_list_append(sbl);
     269                        add_ra_option_prefix(sbl->sb, &xprefix, cease_adv);
     270                }
     271        }
     272#endif
     273        return sbl;
     274}
     275
     276
     277static struct safe_buffer_list * add_auto_prefixes(struct safe_buffer_list * sbl, struct Interface const * iface, char const * ifname, struct AdvPrefix const *prefix, int cease_adv, struct in6_addr const *dest)
     278{
     279#ifdef HAVE_IFADDRS_H
     280        struct AdvPrefix xprefix;
     281        struct ifaddrs *ifap = 0, *ifa = 0;
     282
     283        if (getifaddrs(&ifap) != 0)
     284                flog(LOG_ERR, "getifaddrs failed: %s", strerror(errno));
     285
     286        for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
     287
     288                if (strncmp(ifa->ifa_name, ifname, IFNAMSIZ))
     289                        continue;
     290
     291                if (ifa->ifa_addr->sa_family != AF_INET6)
     292                        continue;
     293
     294                struct sockaddr_in6 *s6 = (struct sockaddr_in6 *)ifa->ifa_addr;
     295                struct sockaddr_in6 *mask = (struct sockaddr_in6 *)ifa->ifa_netmask;
     296
     297                if (IN6_IS_ADDR_LINKLOCAL(&s6->sin6_addr))
     298                        continue;
     299
     300                xprefix = *prefix;
     301                xprefix.Prefix = get_prefix6(&s6->sin6_addr, &mask->sin6_addr);
     302                xprefix.PrefixLen = count_mask(mask);
     303
     304                char pfx_str[INET6_ADDRSTRLEN];
     305                addrtostr(&xprefix.Prefix, pfx_str, sizeof(pfx_str));
     306                dlog(LOG_DEBUG, 3, "auto-selected prefix %s/%d on interface %s",
     307                        pfx_str, xprefix.PrefixLen, ifname);
     308
     309                /* TODO: Something must be done with these. */
     310                (void)xprefix.curr_validlft;
     311                (void)xprefix.curr_preferredlft;
     312
     313                if(cease_adv || schedule_option_prefix(dest, iface, &xprefix)) {
     314                        sbl = safe_buffer_list_append(sbl);
     315                        add_ra_option_prefix(sbl->sb, &xprefix, cease_adv);
     316                }
     317        }
     318
     319        if (ifap)
     320                freeifaddrs(ifap);
     321#endif
     322        return sbl;
     323}
     324
     325static struct safe_buffer_list* add_ra_options_prefix(struct safe_buffer_list * sbl, struct Interface const * iface, char const * ifname, struct AdvPrefix const *prefix, int cease_adv, struct in6_addr const *dest)
    195326{
    196327        while (prefix) {
    197                 if (prefix->enabled && (!prefix->DecrementLifetimesFlag || prefix->curr_preferredlft > 0)) {
    198                         struct nd_opt_prefix_info pinfo;
    199 
    200                         memset(&pinfo, 0, sizeof(pinfo));
    201 
    202                         pinfo.nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION;
    203                         pinfo.nd_opt_pi_len = 4;
    204                         pinfo.nd_opt_pi_prefix_len = prefix->PrefixLen;
    205 
    206                         pinfo.nd_opt_pi_flags_reserved = (prefix->AdvOnLinkFlag) ? ND_OPT_PI_FLAG_ONLINK : 0;
    207                         pinfo.nd_opt_pi_flags_reserved |= (prefix->AdvAutonomousFlag) ? ND_OPT_PI_FLAG_AUTO : 0;
    208                         /* Mobile IPv6 ext */
    209                         pinfo.nd_opt_pi_flags_reserved |= (prefix->AdvRouterAddr) ? ND_OPT_PI_FLAG_RADDR : 0;
    210 
    211                         if (cease_adv && prefix->DeprecatePrefixFlag) {
    212                                 /* RFC4862, 5.5.3, step e) */
    213                                 if (prefix->curr_validlft < MIN_AdvValidLifetime) {
    214                                         pinfo.nd_opt_pi_valid_time = htonl(prefix->curr_validlft);
    215                                 } else {
    216                                         pinfo.nd_opt_pi_valid_time = htonl(MIN_AdvValidLifetime);
     328                if ((!prefix->DecrementLifetimesFlag || prefix->curr_preferredlft > 0)) {
     329                        struct in6_addr zero = {};
     330                        if (prefix->if6to4[0] || prefix->if6[0] || 0 == memcmp(&prefix->Prefix, &zero, sizeof(zero))) {
     331                                if (prefix->if6to4[0]) {
     332                                        dlog(LOG_DEBUG, 4, "if6to4 auto prefix detected on iface %s", ifname);
     333                                        sbl = add_auto_prefixes_6to4(sbl, iface, prefix->if6to4, prefix, cease_adv, dest);
    217334                                }
    218                                 pinfo.nd_opt_pi_preferred_time = 0;
     335                                if (prefix->if6[0]) {
     336                                        dlog(LOG_DEBUG, 4, "if6 auto prefix detected on iface %s", ifname);
     337                                        sbl = add_auto_prefixes(sbl, iface, prefix->if6, prefix, cease_adv, dest);
     338                                }
     339                                if (0 == memcmp(&prefix->Prefix, &zero, sizeof(zero))) {
     340                                        dlog(LOG_DEBUG, 4, "::/64 auto prefix detected on iface %s", ifname);
     341                                        sbl = add_auto_prefixes(sbl, iface, iface->props.name, prefix, cease_adv, dest);
     342                                }
    219343                        } else {
    220                                 pinfo.nd_opt_pi_valid_time = htonl(prefix->curr_validlft);
    221                                 pinfo.nd_opt_pi_preferred_time = htonl(prefix->curr_preferredlft);
     344                                if(cease_adv || schedule_option_prefix(dest, iface, prefix)) {
     345                                        sbl = safe_buffer_list_append(sbl);
     346                                        add_ra_option_prefix(sbl->sb, prefix, cease_adv);
     347                                }
    222348                        }
    223 
    224                         memcpy(&pinfo.nd_opt_pi_prefix, &prefix->Prefix, sizeof(struct in6_addr));
    225 
    226                         safe_buffer_append(sb, &pinfo, sizeof(pinfo));
    227349                }
    228350
    229351                prefix = prefix->next;
    230352        }
     353        return sbl;
    231354}
    232355
     
    268391                                label_len = (unsigned char)(strchr(label, '.') - label);
    269392
     393                        // +8 is for null & padding, only allocate once.
     394                        safe_buffer_resize(safe_buffer, safe_buffer->used + sizeof(label_len) + label_len + 8);
    270395                        len += safe_buffer_append(safe_buffer, &label_len, sizeof(label_len));
    271396                        len += safe_buffer_append(safe_buffer, label, label_len);
     
    286411}
    287412
    288 static void add_route(struct safe_buffer * sb, struct AdvRoute const *route, int cease_adv)
     413static struct safe_buffer_list* add_ra_options_route(struct safe_buffer_list *sbl, struct Interface const * iface, struct AdvRoute const *route, int cease_adv, struct in6_addr const *dest)
    289414{
    290415        while (route) {
    291416                struct nd_opt_route_info_local rinfo;
     417
     418                if(!cease_adv && !schedule_option_route(dest, iface, route)) {
     419                        route = route->next;
     420                        continue;
     421                }
    292422
    293423                memset(&rinfo, 0, sizeof(rinfo));
     
    307437                memcpy(&rinfo.nd_opt_ri_prefix, &route->Prefix, sizeof(struct in6_addr));
    308438
    309                 safe_buffer_append(sb, &rinfo, sizeof(rinfo));
     439                sbl = safe_buffer_list_append(sbl);
     440                safe_buffer_append(sbl->sb, &rinfo, sizeof(rinfo));
    310441
    311442                route = route->next;
    312443        }
    313 }
    314 
    315 static void add_rdnss(struct safe_buffer * sb, struct AdvRDNSS const *rdnss, int cease_adv)
     444        return sbl;
     445}
     446
     447static struct safe_buffer_list * add_ra_options_rdnss(struct safe_buffer_list * sbl, struct Interface const * iface, struct AdvRDNSS const *rdnss, int cease_adv, struct in6_addr const *dest)
    316448{
    317449        while (rdnss) {
    318450                struct nd_opt_rdnss_info_local rdnssinfo;
     451
     452                if(!cease_adv && !schedule_option_rdnss(dest, iface, rdnss)) {
     453                        rdnss = rdnss->next;
     454                        continue;
     455                }
    319456
    320457                memset(&rdnssinfo, 0, sizeof(rdnssinfo));
     
    334471                memcpy(&rdnssinfo.nd_opt_rdnssi_addr3, &rdnss->AdvRDNSSAddr3, sizeof(struct in6_addr));
    335472
    336                 safe_buffer_append(sb, &rdnssinfo, sizeof(rdnssinfo) - (3 - rdnss->AdvRDNSSNumber) * sizeof(struct in6_addr));
     473                sbl = safe_buffer_list_append(sbl);
     474                safe_buffer_append(sbl->sb, &rdnssinfo, sizeof(rdnssinfo) - (3 - rdnss->AdvRDNSSNumber) * sizeof(struct in6_addr));
    337475
    338476                rdnss = rdnss->next;
    339477        }
    340 }
    341 
    342 static void add_dnssl(struct safe_buffer * safe_buffer, struct AdvDNSSL const *dnssl, int cease_adv)
    343 {
     478
     479        return sbl;
     480}
     481
     482static struct safe_buffer_list * add_ra_options_dnssl(struct safe_buffer_list * sbl, struct Interface const * iface, struct AdvDNSSL const *dnssl, int cease_adv, struct in6_addr const *dest)
     483{
     484        struct safe_buffer *serialized_domains = new_safe_buffer();
    344485        while (dnssl) {
    345486
     
    402543                struct nd_opt_dnssl_info_local dnsslinfo;
    403544
     545                if(!cease_adv && !schedule_option_dnssl(dest, iface, dnssl)) {
     546                        dnssl = dnssl->next;
     547                        continue;
     548                }
     549
    404550                memset(&dnsslinfo, 0, sizeof(dnsslinfo));
    405551
    406                 size_t const domain_name_bytes = serialize_domain_names(0, dnssl);
     552                serialized_domains->used = 0;
     553                size_t const domain_name_bytes = serialize_domain_names(serialized_domains, dnssl);
    407554                size_t const bytes = sizeof(dnsslinfo) + domain_name_bytes;
     555                if(bytes > (256 * 8)) {
     556                        flog(LOG_ERR, "DNSSL too long for RA option, must be < 2048 bytes.  Exiting.");
     557                        exit(1);
     558                }
    408559               
    409560                dnsslinfo.nd_opt_dnssli_type = ND_OPT_DNSSL_INFORMATION;
     
    419570                size_t const padding = dnsslinfo.nd_opt_dnssli_len * 8 - bytes;
    420571
    421                 safe_buffer_append(safe_buffer, &dnsslinfo, sizeof(dnsslinfo));
    422                 serialize_domain_names(safe_buffer, dnssl);
    423                 safe_buffer_pad(safe_buffer, padding);
     572                sbl = safe_buffer_list_append(sbl);
     573                safe_buffer_resize(sbl->sb, sbl->sb->used + sizeof(dnsslinfo) + domain_name_bytes + padding);
     574                safe_buffer_append(sbl->sb, &dnsslinfo, sizeof(dnsslinfo));
     575                safe_buffer_append(sbl->sb, serialized_domains->buffer, serialized_domains->used);
     576                safe_buffer_pad(sbl->sb, padding);
     577                //abort();
    424578
    425579                dnssl = dnssl->next;
    426580        }
    427 
     581        return sbl;
     582        safe_buffer_free(serialized_domains);
    428583
    429584}
     
    432587 * add Source Link-layer Address option
    433588 */
    434 static void add_sllao(struct safe_buffer * sb, struct sllao const *sllao)
     589static void add_ra_option_sllao(struct safe_buffer * sb, struct sllao const *sllao)
    435590{
    436591        /* *INDENT-OFF* */
     
    479634}
    480635
    481 static void add_mtu(struct safe_buffer * sb, uint32_t AdvLinkMTU)
     636static void add_ra_option_mtu(struct safe_buffer * sb, uint32_t AdvLinkMTU)
    482637{
    483638        struct nd_opt_mtu mtu;
     
    497652 * movement detection of mobile nodes
    498653 */
    499 static void add_mipv6_rtr_adv_interval(struct safe_buffer * sb, double MaxRtrAdvInterval)
     654static void add_ra_option_mipv6_rtr_adv_interval(struct safe_buffer * sb, double MaxRtrAdvInterval)
    500655{
    501656        uint32_t ival = 1000;
     
    523678 * Dynamic Home Agent Address Discovery
    524679 */
    525 static void add_mipv6_home_agent_info(struct safe_buffer * sb, struct mipv6 const * mipv6)
     680static void add_ra_option_mipv6_home_agent_info(struct safe_buffer * sb, struct mipv6 const * mipv6)
    526681{
    527682        struct HomeAgentInfo ha_info;
     
    541696 * Add 6co option
    542697 */
    543 static void add_lowpanco(struct safe_buffer * sb, struct AdvLowpanCo const *lowpanco)
     698static void add_ra_option_lowpanco(struct safe_buffer * sb, struct AdvLowpanCo const *lowpanco)
    544699{
    545700        struct nd_opt_6co co;
     
    558713}
    559714
    560 static void add_abro(struct safe_buffer * sb, struct AdvAbro const *abroo)
     715static void add_ra_option_abro(struct safe_buffer * sb, struct AdvAbro const *abroo)
    561716{
    562717        struct nd_opt_abro abro;
     
    575730
    576731
    577 static void build_ra(struct safe_buffer * sb, struct Interface const * iface)
    578 {
    579         add_ra_header(sb, &iface->ra_header_info, iface->state_info.cease_adv);
     732static struct safe_buffer_list * build_ra_options(struct Interface const * iface, struct in6_addr const *dest)
     733{
     734        struct safe_buffer_list *sbl = new_safe_buffer_list();
     735        struct safe_buffer_list *cur = sbl;
    580736
    581737        if (iface->AdvPrefixList) {
    582                 add_prefix(sb, iface->AdvPrefixList, iface->state_info.cease_adv);
     738                cur = add_ra_options_prefix(cur, iface, iface->props.name, iface->AdvPrefixList, iface->state_info.cease_adv, dest);
    583739        }
    584740
    585741        if (iface->AdvRouteList) {
    586                 add_route(sb, iface->AdvRouteList, iface->state_info.cease_adv);
     742                cur = add_ra_options_route(cur, iface, iface->AdvRouteList, iface->state_info.cease_adv, dest);
    587743        }
    588744
    589745        if (iface->AdvRDNSSList) {
    590                 add_rdnss(sb, iface->AdvRDNSSList, iface->state_info.cease_adv);
     746                cur = add_ra_options_rdnss(cur, iface, iface->AdvRDNSSList, iface->state_info.cease_adv, dest);
    591747        }
    592748
    593749        if (iface->AdvDNSSLList) {
    594                 add_dnssl(sb, iface->AdvDNSSLList, iface->state_info.cease_adv);
    595         }
    596 
    597         if (iface->AdvLinkMTU != 0) {
    598                 add_mtu(sb, iface->AdvLinkMTU);
    599         }
    600 
    601         if (iface->AdvSourceLLAddress && iface->sllao.if_hwaddr_len > 0) {
    602                 add_sllao(sb, &iface->sllao);
    603         }
    604 
    605         if (iface->mipv6.AdvIntervalOpt) {
    606                 add_mipv6_rtr_adv_interval(sb, iface->MaxRtrAdvInterval);
    607         }
    608 
    609         if (iface->mipv6.AdvHomeAgentInfo
     750                cur = add_ra_options_dnssl(cur, iface, iface->AdvDNSSLList, iface->state_info.cease_adv, dest);
     751        }
     752
     753        if (iface->AdvLinkMTU != 0 && schedule_option_mtu(dest, iface)) {
     754                cur->next = new_safe_buffer_list();
     755                cur = cur->next;
     756                add_ra_option_mtu(cur->sb, iface->AdvLinkMTU);
     757        }
     758
     759        if (iface->AdvSourceLLAddress && iface->sllao.if_hwaddr_len > 0 && schedule_option_sllao(dest, iface)) {
     760                cur->next = new_safe_buffer_list();
     761                cur = cur->next;
     762                add_ra_option_sllao(cur->sb, &iface->sllao);
     763        }
     764
     765        if (iface->mipv6.AdvIntervalOpt && schedule_option_mipv6_rtr_adv_interval(dest, iface)) {
     766                cur->next = new_safe_buffer_list();
     767                cur = cur->next;
     768                add_ra_option_mipv6_rtr_adv_interval(cur->sb, iface->MaxRtrAdvInterval);
     769        }
     770
     771        if (iface->mipv6.AdvHomeAgentInfo && schedule_option_mipv6_home_agent_info(dest, iface)
    610772            && (iface->mipv6.AdvMobRtrSupportFlag || iface->mipv6.HomeAgentPreference != 0
    611773                || iface->mipv6.HomeAgentLifetime != iface->ra_header_info.AdvDefaultLifetime)) {
    612                 add_mipv6_home_agent_info(sb, &iface->mipv6);
    613         }
    614 
    615         if (iface->AdvLowpanCoList) {
    616                 add_lowpanco(sb, iface->AdvLowpanCoList);
    617         }
    618 
    619         if (iface->AdvAbroList) {
    620                 add_abro(sb, iface->AdvAbroList);
    621         }
     774                cur->next = new_safe_buffer_list();
     775                cur = cur->next;
     776                add_ra_option_mipv6_home_agent_info(cur->sb, &iface->mipv6);
     777        }
     778
     779        if (iface->AdvLowpanCoList && schedule_option_lowpanco(dest, iface)) {
     780                cur->next = new_safe_buffer_list();
     781                cur = cur->next;
     782                add_ra_option_lowpanco(cur->sb, iface->AdvLowpanCoList);
     783        }
     784
     785        if (iface->AdvAbroList && schedule_option_abro(dest, iface)) {
     786                cur->next = new_safe_buffer_list();
     787                cur = cur->next;
     788                add_ra_option_abro(cur->sb, iface->AdvAbroList);
     789        }
     790
     791        // Return the root of the list
     792        return sbl;
    622793}
    623794
     
    637808        update_iface_times(iface);
    638809
    639         char address_text[INET6_ADDRSTRLEN] = { "" };
    640         inet_ntop(AF_INET6, dest, address_text, INET6_ADDRSTRLEN);
    641         dlog(LOG_DEBUG, 5, "sending RA to %s on %s", address_text, iface->props.name);
    642 
    643         struct safe_buffer safe_buffer = SAFE_BUFFER_INIT;
    644 
    645         build_ra(&safe_buffer, iface);
    646 
    647         int err = really_send(sock, dest, &iface->props, &safe_buffer);
    648 
    649         safe_buffer_free(&safe_buffer);
    650 
    651         if (err < 0) {
    652                 if (!iface->IgnoreIfMissing || !(errno == EINVAL || errno == ENODEV))
    653                         flog(LOG_WARNING, "sendmsg: %s", strerror(errno));
    654                 else
    655                         dlog(LOG_DEBUG, 3, "sendmsg: %s", strerror(errno));
    656                 return -1;
    657         }
     810        char dest_text[INET6_ADDRSTRLEN] = { "" };
     811        char src_text[INET6_ADDRSTRLEN] = { "" };
     812        addrtostr(dest, dest_text, INET6_ADDRSTRLEN);
     813        addrtostr(iface->props.if_addr_rasrc, src_text, INET6_ADDRSTRLEN);
     814
     815        // Build RA header
     816        struct safe_buffer *ra_hdr = new_safe_buffer();
     817        add_ra_header(ra_hdr, &iface->ra_header_info, iface->state_info.cease_adv);
     818        // Build RA option list
     819        struct safe_buffer_list *ra_opts = build_ra_options(iface, dest);
     820
     821        /* *INDENT-OFF* */
     822        /*
     823         *      RFC4861: 6.2.3.  Router Advertisement Message Content
     824         *         If including all options causes the size of an advertisement to
     825         *         exceed the link MTU, multiple advertisements can be sent, each
     826         *         containing a subset of the options.
     827         *
     828         *      RFC6980: 5.  Specification
     829         *              Nodes MUST NOT employ IPv6 fragmentation for sending any of the
     830         *              following Neighbor Discovery and SEcure Neighbor Discovery messages:
     831         *
     832         *              o  Neighbor Solicitation
     833         *              o  Neighbor Advertisement
     834         *              o  Router Solicitation
     835         *              o  Router Advertisement
     836         *              o  Redirect
     837         *              o  Certification Path Solicitation
     838         *
     839         *              Nodes SHOULD NOT employ IPv6 fragmentation for sending the following
     840         *              messages (see Section 6.4.2 of [RFC3971]):
     841         *
     842         *              o  Certification Path Advertisement
     843         *
     844        */
     845        /* *INDENT-ON* */
     846
     847        // Send out one or more RAs, all in the form of (hdr+options),
     848        // such that none of the RAs exceed the link MTU
     849        // (max size is pre-computed in iface->props.max_ra_option_size)
     850
     851        struct safe_buffer_list *cur = ra_opts;
     852        struct safe_buffer *sb = new_safe_buffer();
     853        unsigned long int total_seen_options = 0;
     854        do {
     855                unsigned long int option_count = 0;
     856                sb->used = 0;
     857                // Duplicate the RA header
     858                safe_buffer_append(sb, ra_hdr->buffer, ra_hdr->used);
     859                // Copy in as many RA options as we can fit.
     860                while(NULL != cur) {
     861                        if(sb->used == 0) {
     862                                dlog(LOG_DEBUG, 5, "send_ra: Saw empty buffer!");
     863                                cur = cur->next;
     864                                continue;
     865                        }
     866                        // Ok, it's more than 0 bytes in length
     867                        total_seen_options++;
     868                        // Not enough room for the next option in our buffer, just send the buffer now.
     869                        if(sb->used + cur->sb->used > iface->props.max_ra_option_size) {
     870                                // But make sure we send at least one option in each RA
     871                                // TODO: a future improvement would be to optimize packing of
     872                                // the options in the minimal number of RAs, such that each one
     873                                // does not exceed the MTU where possible.
     874                                if(option_count > 0)
     875                                        break;
     876                        }
     877                        // It's possible that a single option is larger than the MTU, so
     878                        // fragmentation will always happen in that case.
     879                        // One known case is a very long DNSSL, which is documented in
     880                        // RFC6106 errata #4864
     881                        // In this case, the RA will contain a single option, consisting of
     882                        // ONLY the DNSSL, without other options. RFC6980-conforming nodes
     883                        // should then ignore the DNSSL.
     884                        if(cur->sb->used > iface->props.max_ra_option_size) {
     885                                flog(LOG_WARNING,
     886                                                "send_ra: RA option (type=%hhd) too long for MTU, fragmenting anyway (violates RFC6980)",
     887                                                (unsigned char)(cur->sb->buffer[0]));
     888                        }
     889                        // Add this option to the buffer.
     890                        safe_buffer_append(sb, cur->sb->buffer, cur->sb->used);
     891                        option_count++;
     892                        /*
     893                        if(cur->sb->used > 0 && (unsigned char)(cur->sb->buffer[0]) == ND_OPT_DNSSL_INFORMATION) {
     894                                abort();
     895                        }
     896                        */
     897                        cur = cur->next;
     898                }
     899
     900                if(option_count == 0 && total_seen_options > 0) {
     901                        // If option_count == 0 and total_seen_options==0 we make sure to
     902                        // send ONE RA out, so that clients get the RA header fields.
     903                } else if(option_count == 0 && total_seen_options > 0) {
     904                        // None of the RA options are scheduled for this window.
     905                        dlog(LOG_DEBUG, 5, "No RA options scheduled in this pass, staying quiet; already sent at least one RA packet");
     906                        break;
     907                }
     908
     909                // RA built, now send it.
     910                dlog(LOG_DEBUG, 5, "sending RA to %s on %s (%s), %lu options (using %lu/%u bytes)", dest_text, iface->props.name, src_text, option_count, sb->used, iface->props.max_ra_option_size);
     911                int err = really_send(sock, dest, &iface->props, sb);
     912                if (err < 0) {
     913                        if (!iface->IgnoreIfMissing || !(errno == EINVAL || errno == ENODEV))
     914                                flog(LOG_WARNING, "sendmsg: %s", strerror(errno));
     915                        else
     916                                dlog(LOG_DEBUG, 3, "sendmsg: %s", strerror(errno));
     917                        safe_buffer_free(sb);
     918                        safe_buffer_list_free(ra_opts);
     919                        safe_buffer_free(ra_hdr);
     920                        return -1;
     921                }
     922
     923        } while(NULL != cur);
     924
     925        safe_buffer_free(sb);
     926        safe_buffer_list_free(ra_opts);
     927        safe_buffer_free(ra_hdr);
    658928
    659929        return 0;
     
    682952        struct in6_pktinfo *pkt_info = (struct in6_pktinfo *)CMSG_DATA(cmsg);
    683953        pkt_info->ipi6_ifindex = props->if_index;
    684         memcpy(&pkt_info->ipi6_addr, &props->if_addr, sizeof(struct in6_addr));
     954        memcpy(&pkt_info->ipi6_addr, props->if_addr_rasrc, sizeof(struct in6_addr));
    685955
    686956#ifdef HAVE_SIN6_SCOPE_ID
     
    700970        return sendmsg(sock, &mhdr, 0);
    701971}
     972
     973
     974static int schedule_option_prefix(struct in6_addr const *dest, struct Interface const *iface, struct AdvPrefix const *prefix)
     975{
     976        return schedule_helper(dest, iface, prefix->curr_preferredlft);
     977}
     978
     979static int schedule_option_route(struct in6_addr const *dest, struct Interface const *iface, struct AdvRoute const *route)
     980{
     981        return schedule_helper(dest, iface, route->AdvRouteLifetime);
     982}
     983
     984static int schedule_option_rdnss(struct in6_addr const *dest, struct Interface const *iface, struct AdvRDNSS const *rdnss)
     985{
     986        return schedule_helper(dest, iface, rdnss->AdvRDNSSLifetime);
     987}
     988
     989static int schedule_option_dnssl(struct in6_addr const *dest, struct Interface const *iface, struct AdvDNSSL const *dnssl)
     990{
     991        return schedule_helper(dest, iface, dnssl->AdvDNSSLLifetime);
     992}
     993
     994static int schedule_option_mtu(struct in6_addr const *dest, struct Interface const *iface)
     995{
     996        return schedule_helper(dest, iface, iface->ra_header_info.AdvDefaultLifetime);
     997}
     998
     999static int schedule_option_sllao(struct in6_addr const *dest, struct Interface const *iface)
     1000{
     1001        return schedule_helper(dest, iface, iface->ra_header_info.AdvDefaultLifetime);
     1002}
     1003
     1004static int schedule_option_mipv6_rtr_adv_interval(struct in6_addr const *dest, struct Interface const *iface)
     1005{
     1006        return schedule_helper(dest, iface, iface->ra_header_info.AdvDefaultLifetime);
     1007}
     1008
     1009static int schedule_option_mipv6_home_agent_info(struct in6_addr const *dest, struct Interface const *iface)
     1010{
     1011        return schedule_helper(dest, iface, iface->mipv6.HomeAgentLifetime);
     1012}
     1013
     1014static int schedule_option_lowpanco(struct in6_addr const *dest, struct Interface const *iface)
     1015{
     1016        return schedule_helper(dest, iface, iface->AdvLowpanCoList->AdvLifeTime);
     1017}
     1018
     1019static int schedule_option_abro(struct in6_addr const *dest, struct Interface const *iface)
     1020{
     1021        return schedule_helper(dest, iface, iface->AdvAbroList->ValidLifeTime);
     1022}
     1023
     1024static int schedule_helper(struct in6_addr const *dest, struct Interface const *iface, int option_lifetime)
     1025{
     1026        return 1;
     1027        // 1.
     1028        // Cases to schedule a complete RA blast:
     1029        // - Server received a RS
     1030        // - We're in the initial-RAs phase of startup
     1031        // - The (unicast) destination was first seen very recently, and probably
     1032        //   has NOT got a full set of RAs yet.
     1033
     1034        // 2.
     1035        // If the dest has existed for a while
     1036        // (unicast destination): spread RAs out to at least 1/N of the option lifetime
     1037        // (multicast destination): spread RAs out to at least 1/N of the option lifetime
     1038};
  • src/router/radvd/test/print_safe_buffer.c

    r26391 r32089  
    66#include <stdio.h>
    77
    8 void print_safe_buffer(struct safe_buffer * sb)
     8void print_safe_buffer(struct safe_buffer const * sb)
    99{
    10         printf("unsigned char expected[] = {");
     10        char buf[4096];
     11        snprint_safe_buffer(buf, sizeof(buf), sb);
     12        printf("%s", buf);
     13}
     14
     15size_t snprint_safe_buffer(char *s, size_t size, struct safe_buffer const * sb)
     16{
     17        size_t count = 0;
     18
     19        count += snprintf((s+count), (size-count), "unsigned char expected[] = {");
     20        count--;
    1121
    1222        for (size_t i = 0; i < sb->used; ++i) {
    1323                if (i % 8 == 0) {
    14                         printf("\n\t0x%02x,", sb->buffer[i]);
     24                        count += snprintf((s+count), (size-count), "\n\t0x%02x,", sb->buffer[i]);
    1525                } else {
    16                         printf(" 0x%02x,", sb->buffer[i]);
     26                        count += snprintf((s+count), (size-count), " 0x%02x,", sb->buffer[i]);
    1727                }
     28                count--;
    1829        }
    1930
    20         printf("\n};\n");
     31        count += snprintf((s+count), (size-count), "\n};\n");
     32        return count;
    2133}
    22 
  • src/router/radvd/test/print_safe_buffer.h

    r26391 r32089  
    55#include "../radvd.h"
    66
    7 void print_safe_buffer(struct safe_buffer * sb);
     7size_t snprint_safe_buffer(char *s, size_t size, struct safe_buffer const * sb);
     8void print_safe_buffer(struct safe_buffer const * sb);
    89
  • src/router/radvd/test/send.c

    r26391 r32089  
    4242
    4343#ifdef PRINT_SAFE_BUFFER
    44         print_safe_buffer(&sb);
     44        char buf[4096];
     45        snprint_safe_buffer(buf, 4096, &sb);
     46        ck_assert_msg(0, "\n%s", &buf);
    4547#else
    4648        unsigned char expected[] = {
     
    5759END_TEST
    5860
    59 START_TEST (test_add_prefix)
    60 {
    61         ck_assert_ptr_ne(0, iface);
    62 
    63         struct safe_buffer sb = SAFE_BUFFER_INIT;
    64         add_prefix(&sb, iface->AdvPrefixList, iface->state_info.cease_adv);
    65 
    66 #ifdef PRINT_SAFE_BUFFER
    67         print_safe_buffer(&sb);
     61START_TEST (test_add_ra_options_prefix)
     62{
     63        ck_assert_ptr_ne(0, iface);
     64
     65        struct safe_buffer_list *sbl = new_safe_buffer_list();
     66        struct safe_buffer sb = SAFE_BUFFER_INIT;
     67
     68        add_ra_options_prefix(sbl, iface, iface->props.name, iface->AdvPrefixList, iface->state_info.cease_adv, NULL);
     69
     70        safe_buffer_list_to_safe_buffer(sbl, &sb);
     71        safe_buffer_list_free(sbl);
     72
     73#ifdef PRINT_SAFE_BUFFER
     74        char buf[4096];
     75        snprint_safe_buffer(buf, 4096, &sb);
     76        ck_assert_msg(0, "\n%s", &buf);
    6877#else
    6978        unsigned char expected[] = {
     
    9099END_TEST
    91100
    92 START_TEST (test_add_route)
    93 {
    94         ck_assert_ptr_ne(0, iface);
    95 
    96         struct safe_buffer sb = SAFE_BUFFER_INIT;
    97         add_route(&sb, iface->AdvRouteList, iface->state_info.cease_adv);
    98 
    99 #ifdef PRINT_SAFE_BUFFER
    100         print_safe_buffer(&sb);
     101START_TEST (test_add_ra_options_route)
     102{
     103        ck_assert_ptr_ne(0, iface);
     104
     105        struct safe_buffer_list *sbl = new_safe_buffer_list();
     106        struct safe_buffer sb = SAFE_BUFFER_INIT;
     107
     108        add_ra_options_route(sbl, iface, iface->AdvRouteList, iface->state_info.cease_adv, NULL);
     109
     110        safe_buffer_list_to_safe_buffer(sbl, &sb);
     111        safe_buffer_list_free(sbl);
     112
     113#ifdef PRINT_SAFE_BUFFER
     114        char buf[4096];
     115        snprint_safe_buffer(buf, 4096, &sb);
     116        ck_assert_msg(0, "\n%s", &buf);
    101117#else
    102118        unsigned char expected[] = {
     
    120136
    121137
    122 START_TEST (test_add_rdnss)
    123 {
    124         ck_assert_ptr_ne(0, iface);
    125 
    126         struct safe_buffer sb = SAFE_BUFFER_INIT;
    127         add_rdnss(&sb, iface->AdvRDNSSList, iface->state_info.cease_adv);
    128 
    129 #ifdef PRINT_SAFE_BUFFER
    130         print_safe_buffer(&sb);
     138START_TEST (test_add_ra_options_rdnss)
     139{
     140        ck_assert_ptr_ne(0, iface);
     141
     142        struct safe_buffer_list *sbl = new_safe_buffer_list();
     143        struct safe_buffer sb = SAFE_BUFFER_INIT;
     144
     145        add_ra_options_rdnss(sbl, iface, iface->AdvRDNSSList, iface->state_info.cease_adv, NULL);
     146
     147        safe_buffer_list_to_safe_buffer(sbl, &sb);
     148        safe_buffer_list_free(sbl);
     149
     150#ifdef PRINT_SAFE_BUFFER
     151        char buf[4096];
     152        snprint_safe_buffer(buf, 4096, &sb);
     153        ck_assert_msg(0, "\n%s", &buf);
    131154#else
    132155        unsigned char expected[] = {
     
    149172
    150173
    151 START_TEST (test_add_rdnss2)
     174START_TEST (test_add_ra_options_rdnss2)
    152175{
    153176        static struct Interface * iface = 0;
     
    155178        ck_assert_ptr_ne(0, iface);
    156179
    157         struct safe_buffer sb = SAFE_BUFFER_INIT;
    158         add_rdnss(&sb, iface->AdvRDNSSList, iface->state_info.cease_adv);
     180        struct safe_buffer_list *sbl = new_safe_buffer_list();
     181        struct safe_buffer sb = SAFE_BUFFER_INIT;
     182
     183        add_ra_options_rdnss(sbl, iface, iface->AdvRDNSSList, iface->state_info.cease_adv, NULL);
     184
     185        safe_buffer_list_to_safe_buffer(sbl, &sb);
     186        safe_buffer_list_free(sbl);
    159187        free_ifaces(iface);
    160188
    161189#ifdef PRINT_SAFE_BUFFER
    162         print_safe_buffer(&sb);
     190        char buf[4096];
     191        snprint_safe_buffer(buf, 4096, &sb);
     192        ck_assert_msg(0, "\n%s", &buf);
    163193#else
    164194        unsigned char expected[] = {
     
    177207
    178208
    179 START_TEST (test_add_dnssl)
    180 {
    181         ck_assert_ptr_ne(0, iface);
    182 
    183         struct safe_buffer sb = SAFE_BUFFER_INIT;
    184         add_dnssl(&sb, iface->AdvDNSSLList, iface->state_info.cease_adv);
    185 
    186 #ifdef PRINT_SAFE_BUFFER
    187         print_safe_buffer(&sb);
     209START_TEST (test_add_ra_options_dnssl)
     210{
     211        ck_assert_ptr_ne(0, iface);
     212
     213        struct safe_buffer_list *sbl = new_safe_buffer_list();
     214        struct safe_buffer sb = SAFE_BUFFER_INIT;
     215
     216        add_ra_options_dnssl(sbl, iface, iface->AdvDNSSLList, iface->state_info.cease_adv, NULL);
     217
     218        safe_buffer_list_to_safe_buffer(sbl, &sb);
     219        safe_buffer_list_free(sbl);
     220
     221#ifdef PRINT_SAFE_BUFFER
     222        char buf[4096];
     223        snprint_safe_buffer(buf, 4096, &sb);
     224        ck_assert_msg(0, "\n%s", &buf);
    188225#else
    189226        unsigned char expected[] = {
     
    224261
    225262
    226 START_TEST (test_add_mtu)
    227 {
    228         ck_assert_ptr_ne(0, iface);
    229 
    230         struct safe_buffer sb = SAFE_BUFFER_INIT;
    231         add_mtu(&sb, iface->AdvLinkMTU);
    232 
    233 #ifdef PRINT_SAFE_BUFFER
    234         print_safe_buffer(&sb);
     263START_TEST (test_add_ra_option_mtu)
     264{
     265        ck_assert_ptr_ne(0, iface);
     266
     267        struct safe_buffer sb = SAFE_BUFFER_INIT;
     268        add_ra_option_mtu(&sb, iface->AdvLinkMTU);
     269
     270#ifdef PRINT_SAFE_BUFFER
     271        char buf[4096];
     272        snprint_safe_buffer(buf, 4096, &sb);
     273        ck_assert_msg(0, "\n%s", &buf);
    235274#else
    236275        unsigned char expected[] = {
     
    246285END_TEST
    247286
    248 START_TEST (test_add_sllao)
     287START_TEST (test_add_ra_option_sllao)
    249288{
    250289        struct sllao sllao48 = {
     
    256295       
    257296        struct safe_buffer sb = SAFE_BUFFER_INIT;
    258         add_sllao(&sb, &sllao48);
    259 
    260 #ifdef PRINT_SAFE_BUFFER
    261         print_safe_buffer(&sb);
     297        add_ra_option_sllao(&sb, &sllao48);
     298
     299#ifdef PRINT_SAFE_BUFFER
     300        char buf[4096];
     301        snprint_safe_buffer(buf, 4096, &sb);
     302        ck_assert_msg(0, "\n%s", &buf);
    262303#else
    263304        unsigned char expected48[] = {
     
    279320       
    280321        sb = SAFE_BUFFER_INIT;
    281         add_sllao(&sb, &sllao64);
    282 
    283 #ifdef PRINT_SAFE_BUFFER
    284         print_safe_buffer(&sb);
     322        add_ra_option_sllao(&sb, &sllao64);
     323
     324#ifdef PRINT_SAFE_BUFFER
     325        snprint_safe_buffer(buf, 4096, &sb);
     326        ck_assert_msg(0, "\n%s", &buf);
    285327#else
    286328        unsigned char expected64[] = {
     
    297339END_TEST
    298340
    299 START_TEST (test_add_lowpanco)
    300 {
    301         ck_assert_ptr_ne(0, iface);
    302 
    303         struct safe_buffer sb = SAFE_BUFFER_INIT;
    304         add_lowpanco(&sb, iface->AdvLowpanCoList);
    305 
    306 #ifdef PRINT_SAFE_BUFFER
    307         print_safe_buffer(&sb);
     341START_TEST (test_add_ra_option_lowpanco)
     342{
     343        ck_assert_ptr_ne(0, iface);
     344
     345        struct safe_buffer sb = SAFE_BUFFER_INIT;
     346        add_ra_option_lowpanco(&sb, iface->AdvLowpanCoList);
     347
     348#ifdef PRINT_SAFE_BUFFER
     349        char buf[4096];
     350        snprint_safe_buffer(buf, 4096, &sb);
     351        ck_assert_msg(0, "\n%s", &buf);
    308352#else
    309353        unsigned char expected[] = {
     
    322366
    323367
    324 START_TEST (test_add_abro)
    325 {
    326         ck_assert_ptr_ne(0, iface);
    327 
    328         struct safe_buffer sb = SAFE_BUFFER_INIT;
    329         add_abro(&sb, iface->AdvAbroList);
    330 
    331 #ifdef PRINT_SAFE_BUFFER
    332         print_safe_buffer(&sb);
     368START_TEST (test_add_ra_option_abro)
     369{
     370        ck_assert_ptr_ne(0, iface);
     371
     372        struct safe_buffer sb = SAFE_BUFFER_INIT;
     373        add_ra_option_abro(&sb, iface->AdvAbroList);
     374
     375#ifdef PRINT_SAFE_BUFFER
     376        char buf[4096];
     377        snprint_safe_buffer(buf, 4096, &sb);
     378        ck_assert_msg(0, "\n%s", &buf);
    333379#else
    334380        unsigned char expected[] = {
     
    355401        tcase_add_unchecked_fixture(tc_build, iface_setup, iface_teardown);
    356402        tcase_add_test(tc_build, test_add_ra_header);
    357         tcase_add_test(tc_build, test_add_prefix);
    358         tcase_add_test(tc_build, test_add_route);
    359         tcase_add_test(tc_build, test_add_rdnss);
    360         tcase_add_test(tc_build, test_add_rdnss2);
    361         tcase_add_test(tc_build, test_add_dnssl);
    362         tcase_add_test(tc_build, test_add_mtu);
    363         tcase_add_test(tc_build, test_add_sllao);
    364         tcase_add_test(tc_build, test_add_lowpanco);
    365         tcase_add_test(tc_build, test_add_abro);
     403        tcase_add_test(tc_build, test_add_ra_options_prefix);
     404        tcase_add_test(tc_build, test_add_ra_options_route);
     405        tcase_add_test(tc_build, test_add_ra_options_rdnss);
     406        tcase_add_test(tc_build, test_add_ra_options_rdnss2);
     407        tcase_add_test(tc_build, test_add_ra_options_dnssl);
     408        tcase_add_test(tc_build, test_add_ra_option_mtu);
     409        tcase_add_test(tc_build, test_add_ra_option_sllao);
     410        tcase_add_test(tc_build, test_add_ra_option_lowpanco);
     411        tcase_add_test(tc_build, test_add_ra_option_abro);
    366412
    367413        Suite *s = suite_create("send");
  • src/router/radvd/test/util.c

    r26391 r32089  
    2626END_TEST
    2727
     28START_TEST (test_safe_buffer_resize)
     29{
     30        struct safe_buffer sb = SAFE_BUFFER_INIT;
     31        for(int i = 0; i < 5000; i += 17) {
     32                safe_buffer_resize(&sb, i);
     33                ck_assert_int_ge(sb.allocated, i);
     34        }
     35        safe_buffer_free(&sb);
     36}
     37END_TEST
     38
    2839START_TEST (test_safe_buffer_append)
    2940{
     
    6172       
    6273        safe_buffer_free(&sb);
     74}
     75END_TEST
     76
     77START_TEST (test_safe_buffer_list)
     78{
     79        struct safe_buffer_list *sbl = new_safe_buffer_list();
     80        ck_assert_ptr_ne(0, sbl->sb);
     81        ck_assert_ptr_eq(0, sbl->sb->buffer);
     82        ck_assert_int_eq(0, sbl->sb->used);
     83        ck_assert_ptr_eq(0, sbl->next);
     84        safe_buffer_list_free(sbl);
     85}
     86END_TEST
     87
     88START_TEST (test_safe_buffer_list_to_safe_buffer)
     89{
     90        struct safe_buffer_list *sbl = new_safe_buffer_list();
     91        struct safe_buffer sb = SAFE_BUFFER_INIT;
     92        char array[] = {"This is a test"};
     93
     94        safe_buffer_append(sbl->sb, array, sizeof(array));
     95        sbl->next = new_safe_buffer_list();
     96        safe_buffer_append(sbl->next->sb, array, sizeof(array));
     97
     98        safe_buffer_list_to_safe_buffer(sbl, &sb);
     99
     100        ck_assert_str_eq(sb.buffer, array);
     101        ck_assert_str_eq(sb.buffer + sizeof(array), array);
     102        ck_assert_int_eq(sb.used, 2*sizeof(array));
     103       
     104        safe_buffer_free(&sb);
     105        safe_buffer_list_free(sbl);
    63106}
    64107END_TEST
     
    227270        TCase * tc_safe_buffer = tcase_create("safe_buffer");
    228271        tcase_add_test(tc_safe_buffer, test_safe_buffer);
     272        tcase_add_test(tc_safe_buffer, test_safe_buffer_resize);
    229273        tcase_add_test(tc_safe_buffer, test_safe_buffer_append);
    230274        tcase_add_test(tc_safe_buffer, test_safe_buffer_append2);
    231275        tcase_add_test(tc_safe_buffer, test_safe_buffer_pad);
     276       
     277        TCase * tc_safe_buffer_list = tcase_create("safe_buffer_list");
     278        tcase_add_test(tc_safe_buffer, test_safe_buffer_list);
     279        tcase_add_test(tc_safe_buffer, test_safe_buffer_list_to_safe_buffer);
    232280
    233281        TCase * tc_str = tcase_create("str");
  • src/router/radvd/util.c

    r26390 r32089  
    4040}
    4141
     42/**
     43 * Requests that the safe_buffer capacity be least n bytes in size.
     44 *
     45 * If n is greater than the current capacity, the function causes the container
     46 * to reallocate its storage increasing its capacity to n (or greater).
     47 *
     48 * In all other cases, the function call does not cause a reallocation and the
     49 * capacity is not affected.
     50 *
     51 * @param sb safe_buffer to enlarge
     52 * @param b Minimum capacity for the safe_buffer.
     53 */
     54void safe_buffer_resize(struct safe_buffer * sb, size_t n)
     55{
     56        const int blocksize = 1 << 6; // MUST BE POWER OF 2.
     57        if (sb->allocated < n) {
     58                if(n % blocksize > 0) {
     59                        n |= (blocksize-1); // Set all the low bits
     60                        n++;
     61                }
     62                if (n > 64*1024) {
     63                        flog(LOG_ERR, "Requested buffer too large for any possible IPv6 ND, even with jumbogram.  Exiting.");
     64                        exit(1);
     65                }
     66                sb->allocated = n;
     67                sb->buffer = realloc(sb->buffer, sb->allocated);
     68        }
     69}
     70
    4271size_t safe_buffer_pad(struct safe_buffer * sb, size_t count)
    4372{
    44         size_t rc = 0;
    45         unsigned char zero = 0;
    46 
    47         while (count--) {
    48                 rc += safe_buffer_append(sb, &zero, 1);
    49         }
    50 
    51         return rc;
     73        safe_buffer_resize(sb, sb->used + count);
     74        memset(&sb->buffer[sb->used], (uint8_t)0, count);
     75        sb->used += count;
     76        return count;
    5277}
    5378
     
    5681        if (sb) {
    5782                unsigned const char * m = (unsigned const char *)v;
    58                 if (sb->allocated <= sb->used + count) {
    59                         sb->allocated = sb->used + count + MSG_SIZE_SEND;
    60                         sb->buffer = realloc(sb->buffer, sb->allocated);
    61                 }
     83                safe_buffer_resize(sb, sb->used + count);
    6284                memcpy(&sb->buffer[sb->used], m, count);
    6385                sb->used += count;
    64 
    65                 if (sb->used >= MSG_SIZE_SEND) {
    66                         flog(LOG_ERR, "Too many prefixes, routes, rdnss or dnssl to fit in buffer.  Exiting.");
    67                         exit(1);
    68                 }
    6986        }
    7087
    7188        return count;
     89}
     90
     91/**
     92 * Create a new safe_buffer_list
     93 *
     94 * @return new safe_buffer_list, with a safe_buffer on the heap.
     95 */
     96struct safe_buffer_list * new_safe_buffer_list(void)
     97{
     98        struct safe_buffer_list * sbl = malloc(sizeof(struct safe_buffer_list));
     99        sbl->sb = new_safe_buffer();
     100        sbl->next = NULL;
     101        return sbl;
     102}
     103
     104/**
     105 * Ensure list tail has an empty buffer ready to accept data.
     106 *
     107 * If the present element is empty of data, just return it.
     108 * Otherwise return a new safe_buffer_list ready to accept data.
     109 *
     110 * @param sbl safe_buffer_list.
     111 * @return new tail of list.
     112 */
     113struct safe_buffer_list * safe_buffer_list_append(struct safe_buffer_list * sbl)
     114{
     115        // Only allocate a new entry if this one has bytes in it.
     116        if(sbl->sb && sbl->sb->used > 0) {
     117                struct safe_buffer_list * next = new_safe_buffer_list();
     118                sbl->next = next;
     119                sbl = next;
     120        }
     121        return sbl;
     122}
     123
     124/**
     125 * Convert an entire safe_buffer_list to a single safe_buffer.
     126 *
     127 * @param sbl safe_buffer_list source.
     128 * @param sb  safe_buffer destination.
     129 */
     130void safe_buffer_list_to_safe_buffer(struct safe_buffer_list * sbl, struct safe_buffer *sb)
     131{
     132        struct safe_buffer_list *cur;
     133        for(cur = sbl; cur; cur = cur->next) {
     134                if(cur->sb)
     135                        safe_buffer_append(sb, cur->sb->buffer, cur->sb->used);
     136        }
     137}
     138
     139/**
     140 * Free all memory used by a safe_buffer_list
     141 *
     142 * @param sbl safe_buffer_list to free.
     143 */
     144void safe_buffer_list_free(struct safe_buffer_list * sbl)
     145{
     146        struct safe_buffer_list * next;
     147        for (struct safe_buffer_list *current = sbl; current; current = next) {
     148                if(current->sb)
     149                        safe_buffer_free(current->sb);
     150                next = current->next;
     151                free(current);
     152        }
    72153}
    73154
     
    94175
    95176/* This assumes that str is not null and str_size > 0 */
    96 void addrtostr(struct in6_addr *addr, char *str, size_t str_size)
     177void addrtostr(struct in6_addr const *addr, char *str, size_t str_size)
    97178{
    98179        const char *res;
    99180
    100         res = inet_ntop(AF_INET6, (void *)addr, str, str_size);
     181        res = inet_ntop(AF_INET6, (void const*)addr, str, str_size);
    101182
    102183        if (res == NULL) {
     
    172253        return n;
    173254}
     255
     256int countbits(int b)
     257{
     258        int count;
     259
     260        for (count = 0; b != 0; count++) {
     261                b &= b - 1; // this clears the LSB-most set bit
     262        }
     263
     264        return (count);
     265}
     266
     267int count_mask(struct sockaddr_in6 *m)
     268{
     269        struct in6_addr *in6 = &m->sin6_addr;
     270        int i;
     271        int count = 0;
     272
     273        for (i = 0; i < 16; ++i) {
     274                count += countbits(in6->s6_addr[i]);
     275        }
     276        return count;
     277}
     278
     279struct in6_addr get_prefix6(struct in6_addr const *addr, struct in6_addr const *mask)
     280{
     281        struct in6_addr prefix = *addr;
     282        int i = 0;
     283
     284        for (; i < 16; ++i) {
     285                prefix.s6_addr[i] &= mask->s6_addr[i];
     286        }
     287
     288        return prefix;
     289}
     290
     291
Note: See TracChangeset for help on using the changeset viewer.