Quagga源码编译笔记

Quagga源码编译笔记

Quagga是一个路由套件,其前身是Zebra,而其后继是Frrouting。目前只有Frrouting还处于开发状态,Quagga和Zebra现在开发都停滞了, gnu.org上有一些介绍:https://www.gnu.org/software/zebra/https://www.gnu.org/savannah-checkouts/non-gnu/quagga/

最近在开发功能的时候需要用到一些netlink机制,虽然Frrouting也支持,但是太复杂了,打算在Quagga上找一些参考,于是编译了一下Quagga,发现这方面的资料都是很早之前的,在最新的Debian 12开发环境上遇到了一些新问题,特此记录一下。

1.下载源代码,这里使用的是Quagga发布的最后一个版本1.2.4,下载地址在github上。事实上https://www.nongnu.org/quagga/这里除了DocumentationResources外,其他资源链接都失效了,幸好https://github.com/Quagga/quagga这里还可以访问。然后就是用wget下载,具体命令如下:

wget https://github.com/Quagga/quagga/releases/download/quagga-1.2.4/quagga-1.2.4.tar.gz

2.本地解压,具体命令如下:

tar zxvf quagga-1.2.4.tar.gz

3.开始编译前的配置,执行./configure,遇到错误:

checking for gawk… not-in-PATH
configure: error: GNU awk is required for lib/memtype.h made by memtypes.awk.
BSD awk complains: awk: gensub doesn't support backreferences (subst "\1")

安装gawk解决:sudo apt install gawk

继续./configure, 遇到错误:

checking for main in -lreadline… no
configure: error: vtysh needs libreadline but was not found and usable on your system.

安装libreadline解决:sudo apt install libreadline-dev

继续./configure, 遇到错误:

checking for CARES… no
configure: error: in `/home/thinkdancer/SourceCode/quagga-1.2.4':
configure: error: The pkg-config script could not be found or is too old. Make sure it
is in your PATH or set the PKG_CONFIG environment variable to the full
path to pkg-config.

安装pkg-config解决:sudo apt install pkg-config

继续./configure,遇到错误:

checking whether system has GNU regex… checking for regexec in -lc… yes
checking for CARES… no
configure: error: Package requirements (libcares) were not met:
Package 'libcares', required by 'virtual:world', not found
Consider adjusting the PKG_CONFIG_PATH environment variable if you
installed software in a non-standard prefix.
Alternatively, you may set the environment variables CARES_CFLAGS
and CARES_LIBS to avoid the need to call pkg-config.
See the pkg-config man page for more details.

安装libc-ares-dev解决:sudo apt install libc-ares-dev

如果没有其他错误的话,执行完成后会打印如下输出,表明配置完成,可以编译了。

Quagga configuration

quagga version : 1.2.4
host operating system : linux-gnu
source code location : .
compiler : gcc
compiler flags : -g -O2 -g -Os -fstack-protector-strong --param=ssp-buffer-size=4 -D_FORTIFY_SOURCE=2 -Wformat -Wformat-security -fpie -fno-omit-frame-pointer -Wall -Wextra -Wmissing-prototypes -Wmissing-declarations -Wpointer-arith -Wbad-function-cast -Wwrite-strings -Wno-unused-result -Wno-unused-parameter -Wno-missing-field-initializers
make : make
linker flags : -lcrypt -lrt -lreadline -ltermcap -lm
state file directory : /var/run
config file directory : /usr/local/etc
example directory : /usr/local/etc
user to run as : quagga
group to run as : quagga
group for vty sockets :
config file mask : 0600
log file mask : 0600
zebra protobuf enabled : no
The above user and group must have read/write access to the state file
directory and to the config files in the config file directory.

4.开始编译,执行make,遇到如下的错误:

/usr/bin/ld: .libs/sockunion.o:/home/thinkdancer/SourceCode/quagga-1.2.4/lib/prefix.h:47: multiple definition of __packed'; .libs/vty.o:/home/thinkdancer/SourceCode/quagga-1.2.4/lib/prefix.h:47: first defined here /usr/bin/ld: .libs/prefix.o:/home/thinkdancer/SourceCode/quagga-1.2.4/lib/prefix.h:47: multiple definition of__packed'; .libs/vty.o:/home/thinkdancer/SourceCode/quagga-1.2.4/lib/prefix.h:47: first defined here
/usr/bin/ld: .libs/if.o:/home/thinkdancer/SourceCode/quagga-1.2.4/lib/prefix.h:47: multiple definition of __packed'; .libs/vty.o:/home/thinkdancer/SourceCode/quagga-1.2.4/lib/prefix.h:47: first defined here /usr/bin/ld: .libs/table.o:/home/thinkdancer/SourceCode/quagga-1.2.4/lib/prefix.h:47: multiple definition of__packed'; .libs/vty.o:/home/thinkdancer/SourceCode/quagga-1.2.4/lib/prefix.h:47: first defined here
/usr/bin/ld: .libs/filter.o:/home/thinkdancer/SourceCode/quagga-1.2.4/lib/prefix.h:47: multiple definition of __packed'; .libs/vty.o:/home/thinkdancer/SourceCode/quagga-1.2.4/lib/prefix.h:47: first defined here /usr/bin/ld: .libs/routemap.o:/home/thinkdancer/SourceCode/quagga-1.2.4/lib/prefix.h:47: multiple definition of__packed'; .libs/vty.o:/home/thinkdancer/SourceCode/quagga-1.2.4/lib/prefix.h:47: first defined here
/usr/bin/ld: .libs/stream.o:/home/thinkdancer/SourceCode/quagga-1.2.4/lib/prefix.h:47: multiple definition of __packed'; .libs/vty.o:/home/thinkdancer/SourceCode/quagga-1.2.4/lib/prefix.h:47: first defined here /usr/bin/ld: .libs/plist.o:/home/thinkdancer/SourceCode/quagga-1.2.4/lib/prefix.h:47: multiple definition of__packed'; .libs/vty.o:/home/thinkdancer/SourceCode/quagga-1.2.4/lib/prefix.h:47: first defined here
/usr/bin/ld: .libs/zclient.o:/home/thinkdancer/SourceCode/quagga-1.2.4/lib/prefix.h:47: multiple definition of __packed'; .libs/vty.o:/home/thinkdancer/SourceCode/quagga-1.2.4/lib/prefix.h:47: first defined here /usr/bin/ld: .libs/vrf.o:/home/thinkdancer/SourceCode/quagga-1.2.4/lib/prefix.h:47: multiple definition of__packed'; .libs/vty.o:/home/thinkdancer/SourceCode/quagga-1.2.4/lib/prefix.h:47: first defined here
/usr/bin/ld: .libs/nexthop.o:/home/thinkdancer/SourceCode/quagga-1.2.4/lib/prefix.h:47: multiple definition of `__packed'; .libs/vty.o:/home/thinkdancer/SourceCode/quagga-1.2.4/lib/prefix.h:47: first defined here
collect2: error: ld returned 1 exit status
make[3]: *** [Makefile:502: libzebra.la] Error 1
make[3]: Leaving directory '/home/thinkdancer/SourceCode/quagga-1.2.4/lib'
make[2]: *** [Makefile:430: all] Error 2
make[2]: Leaving directory '/home/thinkdancer/SourceCode/quagga-1.2.4/lib'
make[1]: *** [Makefile:467: all-recursive] Error 1
make[1]: Leaving directory '/home/thinkdancer/SourceCode/quagga-1.2.4'
make: *** [Makefile:399: all] Error 2
thinkdancer@VM-debian-60:~/SourceCode/quagga-1.2.4$

重点是这一句:

/usr/bin/ld: .libs/nexthop.o:/home/thinkdancer/SourceCode/quagga-1.2.4/lib/prefix.h:47: multiple definition of `__packed'; .libs/vty.o:/home/thinkdancer/SourceCode/quagga-1.2.4/lib/prefix.h:47: first defined here

说明代码中存在重复定义,具体说就是prefix.h中定义的结构体__packed在多个文件中被包含,导致链接的时候检测到重复定义。在不修改代码的前提下,可以通过在链接的时候加入-Xlinker -zmuldefs选项解决,具体说就是在config阶段设置CFLAGS标志,然后再make就可以了, GCC的链接选项含义可以看这里https://gcc.gnu.org/onlinedocs/gcc/Link-Options.html

./configure CFLAGS="-Xlinker -zmuldefs"

make

另一种方法是修改Quagga代码,将头文件中定义修改为extern,如果提示有些变量未定义,则在任意引用到的源文件中再增加额外的定义即可。推荐使用上述编译选项的方式,因为修改源代码就涉及对于具体代码的理解,在编译阶段最好不去修改代码,另外Quagga 1.2.4在以前的编译环境上,GCC版本比较低,可能就没有暴露这个多重定义的问题,这也是以前可以编译过的原因。

编译完成后,执行zebra/zebra可以看到下面的输出,说明构建正常。

~/SourceCode/quagga-1.2.4/zebra$ ./zebra -h
Usage : zebra [OPTION…]

Daemon which manages kernel routing table management and redistribution between different routing protocols.

-b, --batch Runs in batch mode
-d, --daemon Runs in daemon mode
-f, --config_file Set configuration file name
-F, --fpm_format Set fpm format to 'netlink' or 'protobuf'
-i, --pid_file Set process identifier file name
-z, --socket Set path of zebra socket
-k, --keep_kernel Don't delete old routes which installed by zebra.
-C, --dryrun Check configuration for validity and exit
-A, --vty_addr Set vty's bind address
-P, --vty_port Set vty's port number
-r, --retain When program terminates, retain added route by zebra.
-u, --user User to run as
-g, --group Group to run as
-s, --nl-bufsize Set netlink receive buffer size
-v, --version Print program version
-h, --help Display this help and exit

Report bugs to https://bugzilla.quagga.net
Comments are closed.