quagga源码学习--BGP协议对等体连接tcp md5签名认证选项

bgp使用tcp连接,每个bgp实例自身是peer的一个tcp server端,同时也是peer的tcp client端。

1、在bgp_create之后都建立自己的socket服务端开始监听179端口:

 bgp = bgp_create(as, name);
bgp_router_id_set(bgp, &router_id_zebra);
*bgp_val = bgp; /* Create BGP server socket, if first instance. */
if (list_isempty(bm->bgp)
&& !bgp_option_check(BGP_OPT_NO_LISTEN)) {
if (bgp_socket(bm->port, bm->address) < ) return BGP_ERR_INVALID_VALUE;
} listnode_add(bm->bgp, bgp);

bgp_socket里完成server socket的创建与监听。

2、在bgp_start函数里开始对peer的connect操作。在connect之前会清楚一些peer的设置,避免与上一个连接session的混淆。

 status = bgp_connect(peer);

如果定义了HAVE_DECL_TCP_MD5SIG宏,或者更老的linux 2.4内核版本的宏 HAVE_TCP_MD5_LINUX24,即会添加TCP MD5签名验证选项。

为了跟上时代的步伐,这里我们就只看高版本的内核了。

 int keylen = password ? strlen(password) : ;
struct tcp_md5sig md5sig;
union sockunion *su2, *susock; ...... memset(&md5sig, , sizeof(md5sig));
memcpy(&md5sig.tcpm_addr, su2, sizeof(*su2));
md5sig.tcpm_keylen = keylen;
if (keylen) memcpy(md5sig.tcpm_key, password, keylen);
sockunion_free(susock); if ((ret = setsockopt(sock, IPPROTO_TCP, TCP_MD5SIG, &md5sig, sizeof md5sig)) < ) {
/* ENOENT is harmless. It is returned when we clear a password for which
one was not previously set. */
if (ENOENT == errno) ret = ;
else zlog_err("sockopt_tcp_signature: setsockopt(%d): %s",
sock, safe_strerror(errno));
}
return ret;

上面的代码即完成MD5SIG选项。

如果md5值不正确或者密码错误,内核会丢弃当前的报文。

4.1.3版本内核对md5sig的结构定义:

 struct tcp_md5sig {
struct __kernel_sockaddr_storage tcpm_addr; /* address associated */
__u16 __tcpm_pad1; /* zero */
__u16 tcpm_keylen; /* key length */
__u32 __tcpm_pad2; /* zero */
__u8 tcpm_key[TCP_MD5SIG_MAXKEYLEN]; /* key (binary) */
};

在int tcp_v4_rcv(struct sk_buff *skb)函数里:

 #ifdef CONFIG_TCP_MD5SIG
/*
* We really want to reject the packet as early as possible
* if:
* o We're expecting an MD5'd packet and this is no MD5 tcp option
* o There is an MD5 option and we're not expecting one
*/
if (tcp_v4_inbound_md5_hash(sk, skb))
goto discard_and_relse;
#endif

因此在服务端,直接由内核在tcp接收处理时就完成了签名验证。

上一篇:学习笔记:CentOS7学习之二十五:shell中色彩处理和awk使用技巧


下一篇:【Windows核心编程】重载类成员函数new / new[] / delete / delete[]