rtnetlink消息解析遇到的问题记录

折腾了两天一个解析rtnetlink消息的程序,总是莫名其妙的crash,最终发现是rtattr数组定的时候忘记了加一。之后,查看了一下iproute2中的代码,如下解析IP地址的函数,rta_tb数组的个数为:IFA_MAX+1,进行了加一操作。

int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
{
    struct ifaddrmsg *ifa = NLMSG_DATA(n);
    int len = n->nlmsg_len;
    struct rtattr *rta_tb[IFA_MAX+1];

    ...

    parse_rtattr(rta_tb, IFA_MAX, IFA_RTA(ifa),
             n->nlmsg_len - NLMSG_LENGTH(sizeof(*ifa)));

宏IFA_MAX的定义如下,其等于最大值__IFA_MAX减去一,即等于IFA_RT_PRIORITY,所以定义rtattr数据的时候,IFA_MAX必须进行加一。

enum {
    IFA_UNSPEC,
    IFA_ADDRESS,
    IFA_LOCAL,
    IFA_LABEL,
    IFA_BROADCAST,
    IFA_ANYCAST,
    IFA_CACHEINFO,
    IFA_MULTICAST,
    IFA_FLAGS,
    IFA_RT_PRIORITY,  /* u32, priority/metric for prefix route */
    __IFA_MAX,
};   

#define IFA_MAX (__IFA_MAX - 1)

解析函数parse_rtattr,在调用memset进行清空操作时,也对最大值进行了加一。

int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len)
{
    return parse_rtattr_flags(tb, max, rta, len, 0);
}

int parse_rtattr_flags(struct rtattr *tb[], int max, struct rtattr *rta,
               int len, unsigned short flags)
{
    unsigned short type;

    memset(tb, 0, sizeof(struct rtattr *) * (max + 1));

内核部分代码的解析代码,如函数rtm_to_ifaddr,也是类似。

static struct in_ifaddr *rtm_to_ifaddr(struct net *net, struct nlmsghdr *nlh,
                       __u32 *pvalid_lft, __u32 *pprefered_lft,
                       struct netlink_ext_ack *extack)
{
    struct nlattr *tb[IFA_MAX+1];
    struct in_ifaddr *ifa;
    struct ifaddrmsg *ifm;

    err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv4_policy, extack);
    if (err < 0)
        goto errout;
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页