最近公司一网络产品需要在WEB和SNMP的基础上添加CLI接口。
本身CLI(Command Line Interface)在产品中借助某芯片有简单ssdk_sh,由于客户要求CLI要想Cisco那样。(不知何故,特别指出并不看重web和snmp,只看重CLI)
只好研究通用的zebra-vtysh。
1. Zebra是一个路由软件包,提供基于TCP/IP路由服务,支持RIPv1, RIPv2, RIPng, OSPFv2, OSPFv3, BGP- 4, 和 BGP-4+等众多路由协议。Zebra还支持BGP特性路由反射器(Route Reflector)。除了传统的 IPv4路由协议,Zebra也支持IPv6路由协议。如果运行的SNMP守护进程(需要ucd-snmp)支持SMUX协 议,Zebra还能支持路由协议MIBs。
其中,出现的各种协议,不懂的google。
2. 其次zebra-vtysh是一开源软件,可以从官网上下载(目前最高版本是zebra-0.95a.tar.gz)。
具体怎么安装可以google下就可以。
但是关于zebra源码的分析就很少了,希望在这里开始我的源码和改造之路,和大家一起分享。
1. Zebra 功能认识
ZEBRA 提供了一个类Cisco命令行的分级多用户命令解析引擎--VTY(Virtual Terminal)。它是类似于Linux Shell的虚拟终端接口,负责对访问的安全验证、数据缓冲、命令解析、模式切换和命令调用。
用户通过VTYSH的每一次接口访问都会发起一个对应的VTY。VTY会根据用户优先级初始化并挂载相应的命令集Command Node。Command Node中以链表的形式包含了该用户可以访问和使用的Command。
用户通过各种接口访问VTY,VTY解析用户的每个命令,并且通过命令集链表找到并执行Command相应函数。这样,通过访问VTY实现基于命令集的管理功能。
2. Zebra 架构
Zebra采用模块化的架构,,整个程序由一系列的守护进程构成,每个路由协议都有自己单独的路由处理进程,同时,它提供一个管理内核路由表的zebra 守护进程。路由处理程序通过zebra 守护程序管理内核路由表。
由图示可知,在Zebra中,总共有五个路由守护进程,和一个管理进程。这些路由进程可以和管理进程分布在不同的机器上,每一个进程可以分别监听从不同的端口来的VTY连接。
3. 编译Zebra为我所用
一般的路由产品都可以拿来Zebra稍加改动就可以使用了。如果你只需要VTY连接功能,通过接口增、改、删命令的话,Zebra是支持模块的删除和屏蔽的。
比如只需要VTY,那么你编译的时候可以在congfigure的时候加上如下参数就可以了。
...
cd ../zebra-vtysh && (test -e config.status ||(touch config.status && ./configure --disable-ipv6 --disable-bgpd --disable-ripngd --disable-ospf6d --disable-bgp-announce --enable-vtysh --disable-ospfd --disable-ripd --disable-zebra --prefix=/ --with-cflags="-O2 -Wall" --build=i386 --host=mips-linux --target=mips)) &&
...
(其中,config.status是configure的状态记录信息,以备下次使用)
这样,编译完zebra后,就可以运行vtysh了,查看它的各种模式(下篇文章会讲),就可以开始你的快乐之旅了。
参考:http://
分析Zebra-VTYSH的源码,首先从main函数开始,在ztysh-main.c中找到main函数,来进一步分析流程执行如下图所示:
在平时的使用中我们会发现,配置的时候有很多的视图(View),每个视图中有不同的命令可供用户输入进行配置。
这里,根据源码,视图可以认为是Node,而每一个命令称为element,他们之间的结构如下图所示:
如图中所示,用到的数据结构如下:
-
-
struct _vector
-
{
-
unsigned int max;
-
unsigned int alloced;
-
void **index;
-
};
-
-
-
struct cmd_node
-
{
-
-
enum node_type node;
-
-
-
char *prompt;
-
-
-
int vtysh;
-
-
-
int (*func) (struct vty *);
-
-
-
vector cmd_vector;
-
};
-
-
-
struct cmd_element
-
{
-
char *string;
-
int (*func) (struct cmd_element *, struct vty *, int, char **);
-
char *doc;
-
int daemon;
-
vector strvec;
-
int cmdsize;
-
char *config;
-
vector subconfig;
-
};
-
-
struct _vector
-
{
-
unsigned int max;
-
unsigned int alloced;
-
void **index;
-
};
-
-
-
struct cmd_node
-
{
-
-
enum node_type node;
-
-
-
char *prompt;
-
-
-
int vtysh;
-
-
-
int (*func) (struct vty *);
-
-
-
vector cmd_vector;
-
};
-
-
-
struct cmd_element
-
{
-
char *string;
-
int (*func) (struct cmd_element *, struct vty *, int, char **);
-
char *doc;
-
int daemon;
-
vector strvec;
-
int cmdsize;
-
char *config;
-
vector subconfig;
-
};
下面我们所要做的事情就是在node和element中添加我们自己的命令,如果一切顺利,稍加处理就可以在图一中的最后一步也就是loop循环中的vtysh_execute函数中来实现我们的执行过程了。
一 视图介绍
由上面几篇文章分析可见,所有的命令都是包含在node中的,根据Cisco或者H3常见路由器或者交换机的CLI格式可见,一个node就对应着一个视图(View)。常用的视图包括:普通视图,管理视图,文件系统视图,配置视图,以及接口配置视图和VLAN视图等。
在Zebra-VTYSH源码中,实现了的有Enable视图和配置视图。如下图所示:
-
/ # vtysh
-
-
Copyright 2010-2011 IBM Co., Ltd.
-
-
CLI> enable
-
CLI#
-
clear Reset functions
-
configure Configuration from vty interface
-
copy Copy from one file to another
-
debug Debugging functions (see also 'undebug')
-
disable Turn off privileged mode command
-
end End current mode and down to previous mode
-
exit Exit current mode and down to previous mode
-
list Print command list
-
no Negate a command or set its defaults
-
ping send echo messages
-
quit Exit current mode and down to previous mode
-
show Show running system information
-
start-shell Start UNIX shell
-
telnet Open a telnet connection
-
terminal Set terminal line parameters
-
traceroute Trace route to destination
-
undebug Disable debugging functions (see also 'debug')
-
write Write running configuration to memory, network, or terminal
-
CLI# configure terminal
-
CLI(config)#
-
access-list Add an access list entry
-
bgp BGP information
-
debug Debugging functions (see also 'undebug')
-
device-config Device configuration
-
dump Dump packet
-
enable Modify enable password parameters
-
end End current mode and down to previous mode
-
exit Exit current mode and down to previous mode
-
hostname Set system's network name
-
interface Select an interface to configure
-
ip IP information
-
ipv6 IPv6 information
-
key Authentication key management
-
list Print command list
-
log Logging control
-
no Negate a command or set its defaults
-
password Assign the terminal connection password
-
route-map Create route-map or enter route-map command mode
-
router Enable a routing process
-
system-config System and management configuration
-
username
-
write Write running configuration to memory, network, or terminal
-
CLI(config)# system-config
-
CLI(config-system)#
-
access Set CPE access ND flag
-
admin-idle-time Set system idle time
-
admin-psw Set system administrator password
-
admin-username Set system administrator username
-
connection-mode Set network connection mode : static and dynamic
-
datetime Set date time (format:2000-01-01 00:00:00)
-
default-gateway Set system's network default gateway
-
dns-server-1 Set system network DNS server 1
-
dns-server-2 Set system network DNS server 2
-
exit Exit current mode and down to previous mode
-
factory-defaults Restore ALL configure to factory default values( 0: reset all 1: reset with network parameters unchanged)
-
hostname Set system's network name
-
image-upgrade Upgrade image via ftp method
-
ip Set system ip address and netmask
-
list Print command list
-
managment-ip-range Set management IP range and netmask
-
managment-ip-range-flag Set management IP range service flag
-
mgr-vlan-id Set management VLAN ID
-
ntpserver Set NTP server
-
quit Exit current mode and down to previous mode
-
reset Reset system
-
snmp-refresh-time Set SNMP service refresh time cycle
-
snmp-rwcommunicty Set SNMP read/write community
-
snmp-service Set SNMP service enable or disable
-
snmp-trap-ip1 Set SNMP trap ip 1 address
-
snmp-trap-ip2 Set SNMP trap ip 2 address
-
snmp-trap1-ip-flag Set SNMP trap ip 1 service flag(enable/disable)
-
snmp-trap2-ip-flag Set SNMP trap ip 2 service flag(enable/disable)
-
ssh Set ssh service port and timeout values
-
ssh-service Set ssh service flag
-
telnet Set telnet PORT
-
telnet-service Set telnet service flag
-
timesync Set time sync service flag
-
timezone Set time zone (0:ShangHai,1:ChongQing)
-
CLI(config-system)# quit
-
CLI(config)# device-config
-
CLI(config-device)#
-
exit Exit current mode and down to previous mode
-
list Print command list
-
port-mirror-analysis-port Device configuration: Set analysis port(1: eth1 2: eth2)
-
port-mirror-flag Device configuration: Enable or disable port mirror service(0:disable,1:enable)
-
port-mirror-packet Device configuration: Set packet type to be mirrored(1:Import & Export 2: Import 3: Export)
-
port-mirror-port Device configuration:Set port to be mirrored
-
port1-rate Device configuration: set duplex mode and import/export/broadcast/unkown/multicast rate limit.
-
port2-rate Device configuration: set duplex mode and import/export/broadcast/unkown/multicast rate limit.
-
quit Exit current mode and down to previous mode
-
CLI(config-device)#
-
CLI(config-device)#
-
/ # vtysh
-
-
Copyright 2010-2011 IBM Co., Ltd.
-
-
CLI> enable
-
CLI#
-
clear Reset functions
-
configure Configuration from vty interface
-
copy Copy from one file to another
-
debug Debugging functions (see also 'undebug')
-
disable Turn off privileged mode command
-
end End current mode and down to previous mode
-
exit Exit current mode and down to previous mode
-
list Print command list
-
no Negate a command or set its defaults
-
ping send echo messages
-
quit Exit current mode and down to previous mode
-
show Show running system information
-
start-shell Start UNIX shell
-
telnet Open a telnet connection
-
terminal Set terminal line parameters
-
traceroute Trace route to destination
-
undebug Disable debugging functions (see also 'debug')
-
write Write running configuration to memory, network, or terminal
-
CLI# configure terminal
-
CLI(config)#
-
access-list Add an access list entry
-
bgp BGP information
-
debug Debugging functions (see also 'undebug')
-
device-config Device configuration
-
dump Dump packet
-
enable Modify enable password parameters
-
end End current mode and down to previous mode
-
exit Exit current mode and down to previous mode
-
hostname Set system's network name
-
interface Select an interface to configure
-
ip IP information
-
ipv6 IPv6 information
-
key Authentication key management
-
list Print command list
-
log Logging control
-
no Negate a command or set its defaults
-
password Assign the terminal connection password
-
route-map Create route-map or enter route-map command mode
-
router Enable a routing process
-
system-config System and management configuration
-
username
-
write Write running configuration to memory, network, or terminal
-
CLI(config)# system-config
-
CLI(config-system)#
-
access Set CPE access ND flag
-
admin-idle-time Set system idle time
-
admin-psw Set system administrator password
-
admin-username Set system administrator username
-
connection-mode Set network connection mode : static and dynamic
-
datetime Set date time (format:2000-01-01 00:00:00)
-
default-gateway Set system's network default gateway
-
dns-server-1 Set system network DNS server 1
-
dns-server-2 Set system network DNS server 2
-
exit Exit current mode and down to previous mode
-
factory-defaults Restore ALL configure to factory default values( 0: reset all 1: reset with network parameters unchanged)
-
hostname Set system's network name
-
image-upgrade Upgrade image via ftp method
-
ip Set system ip address and netmask
-
list Print command list
-
managment-ip-range Set management IP range and netmask
-
managment-ip-range-flag Set management IP range service flag
-
mgr-vlan-id Set management VLAN ID
-
ntpserver Set NTP server
-
quit Exit current mode and down to previous mode
-
reset Reset system
-
snmp-refresh-time Set SNMP service refresh time cycle
-
snmp-rwcommunicty Set SNMP read/write community
-
snmp-service Set SNMP service enable or disable
-
snmp-trap-ip1 Set SNMP trap ip 1 address
-
snmp-trap-ip2 Set SNMP trap ip 2 address
-
snmp-trap1-ip-flag Set SNMP trap ip 1 service flag(enable/disable)
-
snmp-trap2-ip-flag Set SNMP trap ip 2 service flag(enable/disable)
-
ssh Set ssh service port and timeout values
-
ssh-service Set ssh service flag
-
telnet Set telnet PORT
-
telnet-service Set telnet service flag
-
timesync Set time sync service flag
-
timezone Set time zone (0:ShangHai,1:ChongQing)
-
CLI(config-system)# quit
-
CLI(config)# device-config
-
CLI(config-device)#
-
exit Exit current mode and down to previous mode
-
list Print command list
-
port-mirror-analysis-port Device configuration: Set analysis port(1: eth1 2: eth2)
-
port-mirror-flag Device configuration: Enable or disable port mirror service(0:disable,1:enable)
-
port-mirror-packet Device configuration: Set packet type to be mirrored(1:Import & Export 2: Import 3: Export)
-
port-mirror-port Device configuration:Set port to be mirrored
-
port1-rate Device configuration: set duplex mode and import/export/broadcast/unkown/multicast rate limit.
-
port2-rate Device configuration: set duplex mode and import/export/broadcast/unkown/multicast rate limit.
-
quit Exit current mode and down to previous mode
-
CLI(config-device)#
-
CLI(config-device)#
如果想要添加自己的命令,可以在原有的视图上增加(也就是在原有的node中增加commands),或者新开自己的视图,然后在新视图中添加自己的commands。
二 添加命令
进入vtysh目录中,查看vtysh_main.c文件的main函数,也就是和vtysh初始化相关的一切都在这里,基本上在这里可以完成你需要的一些基本命令。
在函数vtysh_init_vty()中,有个
-
-
Void cmd_init (int terminal)
-
-
Void cmd_init (int terminal)
的函数,就是负责初始化command接口,安装node和命令的。
比如你就可以添加自己的视图如下:
-
-
install_element (CONFIG_NODE, &vtysh_sysconfig_cmd);
-
install_element (CONFIG_NODE, &vtysh_devconfig_cmd);
-
-
install_element (CONFIG_NODE, &vtysh_sysconfig_cmd);
-
install_element (CONFIG_NODE, &vtysh_devconfig_cmd);
(其中,安装的system和device配置的视图)
-
-
-
-
DEFUN (system_config,
-
vtysh_sysconfig_cmd,
-
"system-config",
-
SYS_CFG_STR
-
"\n")
-
{
-
-
-
vty->node = SYSCONFIG_NODE;
-
-
return CMD_SUCCESS;
-
}
-
DEFUN (device_config,
-
vtysh_devconfig_cmd,
-
"device-config",
-
DEV_CFG_STR
-
"\n")
-
{
-
-
-
-
vty->node = DEVCONFIG_NODE;
-
-
return CMD_SUCCESS;
-
}
-
DEFUN定义为:
-
-
#define DEFUN(funcname, cmdname, cmdstr, helpstr) \
-
int funcname (struct cmd_element *, struct vty *, int, char **); \
-
struct cmd_element cmdname = \
-
{ \
-
cmdstr, \
-
funcname, \
-
helpstr \
-
}; \
-
int funcname \
-
(struct cmd_element *self, struct vty *vty, int argc, char **argv)
-
-
-
-
DEFUN (system_config,
-
vtysh_sysconfig_cmd,
-
"system-config",
-
SYS_CFG_STR
-
"\n")
-
{
-
-
-
vty->node = SYSCONFIG_NODE;
-
-
return CMD_SUCCESS;
-
}
-
DEFUN (device_config,
-
vtysh_devconfig_cmd,
-
"device-config",
-
DEV_CFG_STR
-
"\n")
-
{
-
-
-
-
vty->node = DEVCONFIG_NODE;
-
-
return CMD_SUCCESS;
-
}
-
DEFUN定义为:
-
-
#define DEFUN(funcname, cmdname, cmdstr, helpstr) \
-
int funcname (struct cmd_element *, struct vty *, int, char **); \
-
struct cmd_element cmdname = \
-
{ \
-
cmdstr, \
-
funcname, \
-
helpstr \
-
}; \
-
int funcname \
-
(struct cmd_element *self, struct vty *vty, int argc, char **argv)
SYSCONFIG_NODE和DEVCONFIG_NODE要添加进enum node_type{}中去。
最后就要在init_cmd的最后加进自己的command了
比如
-
-
-
-
-
-
install_element (SYSCONFIG_NODE, &vtysh_system_cfg_ip_cmd);
-
-
-
-
-
-
install_element (SYSCONFIG_NODE, &vtysh_system_cfg_ip_cmd);
其中,函数指针需要定义先:
-
DEFUN (vtysh_system_cfg_ip,
-
vtysh_system_cfg_ip_cmd,
-
"ip ADDRESS NETMASK",
-
"Set system ip address and netmask\n")
-
{
-
applyCfg(argv[0],"IPADDR");
-
applyCfg(argv[1],"NETMASK");
-
system(NETWORK_SETTING_SCRIPT);
-
return CMD_SUCCESS;
-
}
-
DEFUN (vtysh_system_cfg_ip,
-
vtysh_system_cfg_ip_cmd,
-
"ip ADDRESS NETMASK",
-
"Set system ip address and netmask\n")
-
{
-
applyCfg(argv[0],"IPADDR");
-
applyCfg(argv[1],"NETMASK");
-
system(NETWORK_SETTING_SCRIPT);
-
return CMD_SUCCESS;
-
}
这样,基本上完成了添加node和命令的任务了。
其他Zebra-VTYH自带的命令如果不想要的话删除掉就行了。
(总完)