Linux Can';t使用netlink API(libnl librabry)从C代码向网桥分配IP地址

Linux Can';t使用netlink API(libnl librabry)从C代码向网桥分配IP地址,linux,networking,netlink,Linux,Networking,Netlink,我在libnl的帮助下创建了网桥。但现在我无法为它分配IP地址。我查阅了几次文档,但没有看到问题所在。我的代码是: /* Creates network bridge with 'bridgename' name. returns 0 on success returns netlink error code otherwise */ static int create_bridge(const char *bridge_name) { /* libnl's stuff *

我在libnl的帮助下创建了网桥。但现在我无法为它分配IP地址。我查阅了几次文档,但没有看到问题所在。我的代码是:

/*

Creates network bridge with 'bridgename' name.

returns 0 on success 
returns netlink error code otherwise 

*/

static int create_bridge(const char *bridge_name) {

    /* libnl's stuff */
    struct rtnl_link *link;
    struct nl_sock *sk;
    int err = 0;

    /* Sanity checks */

    if(!bridge_name) {
        fprintf(stderr,"Bad bridge name.\n");
        return -1;
    }

    /* We need socket to work with link objects */
    /* NETLINK_ROUTE - we can send IPv4/IPv6 packets and a lot of other stuff 
    through that type of socket, like changing routing table etc. */

    sk = nl_socket_alloc();
    if ((err = nl_connect(sk, NETLINK_ROUTE)) < 0) {
        nl_perror(err, "Unable to create socket.");
        return err;
    }

    /* Allocates link object */
    link = rtnl_link_alloc();
    if ((err = rtnl_link_set_type(link, "bridge")) < 0) {
        nl_perror(err, "Unable to allocate link object.");
        rtnl_link_put(link);
        return err;
    }

    /* Configuring new link */
    rtnl_link_set_name(link, bridge_name);

    /* NLM_F_CREATE flag allows to create link if it does not exist */
    if ((err = rtnl_link_add(sk, link, NLM_F_CREATE)) < 0) { 
        nl_perror(err, "Unable to create link.");
        return err;
    }

    /* Frees previously allocated socket */
    nl_socket_free(sk);

    /* Frees previously allocated link object */
    rtnl_link_put(link);

    return 0;
}


/*

Creates network bridge with 'bridgename' name.

returns 0 on success 
returns 1 if there is no "bridge_name" bridge
returns 2 if "bridge_name" is not a bridge device 
returns 3 if interface index for "bridge_name" is not set
returns netlink error code otherwise 

*/

static int set_bridge_ipv4(const char *bridge_name, const char *ipv4address) {

    /* libnl's stuff */
    struct rtnl_link *link = NULL;
    struct nl_sock *sk = NULL;
    struct rtnl_addr *ipv4_addr = NULL;
    struct nl_addr* lo_ipv4_addr = NULL;
    struct nl_cache *link_cache = NULL;

    int err = 0;
    int ifindex = 0;

    /* Sanity checks */

    if(!bridge_name) {
        fprintf(stderr,"Bad bridge name.\n");
        return -1;
    }

    if(!ipv4address) {
        fprintf(stderr,"Bad ipv4 address.\n");
        return -1;
    }

    /* We need socket to work with link objects */
    /* NETLINK_ROUTE - we can send IPv4/IPv6 packets and a lot of other stuff 
    through that type of socket, like changing routing table etc. */

    sk = nl_socket_alloc();
    if ((err = nl_connect(sk, NETLINK_ROUTE)) < 0) {
        nl_perror(err, "Unable to create socket.");
        return err;
    }

    /* Allocates link object */
    link = rtnl_link_alloc();
    if ((err = rtnl_link_set_type(link, "bridge")) < 0) {
        nl_perror(err, "Unable to allocate link object.");
        rtnl_link_put(link);
        return err;
    }

    /* Allocates nl_addr object with 8 bytes max size 
       Allocates rtnl_addr object                   */
    ipv4_addr = rtnl_addr_alloc();
    lo_ipv4_addr = nl_addr_alloc(8);
    if ((err = nl_addr_parse(ipv4address, AF_INET, &lo_ipv4_addr)) < 0) {
        nl_perror(err, "Unable to parse local IPv4 address.");
        return err;
    }

    /* Copying nl_addr to rtnl_addr */
    if((err = rtnl_addr_set_local(ipv4_addr, lo_ipv4_addr)) < 0) {
        nl_perror(err, "Unable to set address.\n");
        return err;
    }

    /* Allocates list of link objects, which will be filled with current links from kernel */
    if ((err = rtnl_link_alloc_cache(sk, AF_UNSPEC, &link_cache)) < 0) {
        nl_perror(err, "Unable to allocate cache.");
        return err;
    }

    /* Getting our bridge by name*/
    if((link = rtnl_link_get_by_name(link_cache, bridge_name)) == 0) {
        fprintf(stderr,"There is no %s bridge. Use create_bridge(\"%s\") function to create one.\n", bridge_name, bridge_name);
        return 1;
    }

    /* Check if it's a bridge at all */
    if(rtnl_link_is_bridge(link) == 0) {
        fprintf(stderr, "%s is not a bridge device.\n",bridge_name);
        return 2;
    }

    /* Get index of the bridge */
    if((ifindex = rtnl_link_get_ifindex(link)) == 0) {
        fprintf(stderr,"Interface index of %s bridge is not set.\n", bridge_name);
        return 3;
    }

    /* Setting interface index to rtnl_addr */
    rtnl_addr_set_ifindex(ipv4_addr, ifindex);

    /* Setting IP address*/
    rtnl_addr_set_link(ipv4_addr, link);

    /* Sending rtnl_addr into the kernel*/
    if ((err = rtnl_addr_add(sk, ipv4_addr, 0)) < 0) {
        nl_perror(err, "Unable to add rtnl_addr.");
        return err;
    }

    /* Deleting rtnl_addr */
    if ((err = rtnl_addr_delete(sk, ipv4_addr, 0)) < 0) {
        nl_perror(err, "Unable to delete rtnl_addr.");
        return err;
    }

    /* Frees previously allocated nl_addrs object */
    nl_addr_put(lo_ipv4_addr);

    /* Frees previously allocated rtnl_addrs object */
    rtnl_addr_put(ipv4_addr);

    /* Frees previously allocated list of link objects */
    nl_cache_free(link_cache);

    /* Frees previously allocated socket */
    nl_socket_free(sk);

    /* Frees previously allocated link object */
    rtnl_link_put(link);

    return 0;
}
/*
使用“bridgename”名称创建网桥。
成功时返回0
否则返回netlink错误代码
*/
静态int创建桥(常量字符*桥名称){
/*利本尔的东西*/
结构rtnl_链接*链接;
结构nl_sock*sk;
int err=0;
/*健康检查*/
如果(!桥名称){
fprintf(stderr,“坏桥名。\n”);
返回-1;
}
/*我们需要套接字来处理链接对象*/
/*NETLINK_路由-我们可以发送IPv4/IPv6数据包和其他很多东西
通过这种类型的套接字,如更改路由表等*/
sk=nl_socket_alloc();
如果((错误=nl_连接(sk,网络链接_路由))<0){
nl_perror(错误,“无法创建套接字”);
返回错误;
}
/*分配链接对象*/
link=rtnl_link_alloc();
如果((err=rtnl_链接_设置_类型(链接,“桥接”))<0){
nl_perror(错误,“无法分配链接对象”);
rtnl_链路_put(链路);
返回错误;
}
/*配置新链接*/
rtnl\u链接\u set\u name(链接、桥接名称);
/*NLM_F_CREATE标志允许在链接不存在时创建链接*/
如果((err=rtnl_link_add(sk,link,NLM_F_CREATE))<0){
nl_perror(错误,“无法创建链接”);
返回错误;
}
/*释放以前分配的套接字*/
无插座(sk);
/*释放以前分配的链接对象*/
rtnl_链路_put(链路);
返回0;
}
/*
使用“bridgename”名称创建网桥。
成功时返回0
如果没有“网桥名称”网桥,则返回1
如果“网桥名称”不是网桥设备,则返回2
如果未设置“网桥名称”的接口索引,则返回3
否则返回netlink错误代码
*/
静态int set_bridge_ipv4(const char*bridge_name,const char*ipv4地址){
/*libnl的东西*/
struct rtnl_link*link=NULL;
结构nl_sock*sk=NULL;
结构rtnl_addr*ipv4_addr=NULL;
结构nl_addr*lo_ipv4_addr=NULL;
结构nl_缓存*链接_缓存=空;
int err=0;
int-ifindex=0;
/*健康检查*/
如果(!桥名称){
fprintf(stderr,“坏桥名。\n”);
返回-1;
}
如果(!ipv4address){
fprintf(stderr,“错误的ipv4地址。\n”);
返回-1;
}
/*我们需要套接字来处理链接对象*/
/*NETLINK_路由-我们可以发送IPv4/IPv6数据包和其他很多东西
通过这种类型的套接字,如更改路由表等*/
sk=nl_socket_alloc();
如果((错误=nl_连接(sk,网络链接_路由))<0){
nl_perror(错误,“无法创建套接字”);
返回错误;
}
/*分配链接对象*/
link=rtnl_link_alloc();
如果((err=rtnl_链接_设置_类型(链接,“桥接”))<0){
nl_perror(错误,“无法分配链接对象”);
rtnl_链路_put(链路);
返回错误;
}
/*分配最大大小为8字节的nl_addr对象
分配rtnl_addr对象*/
ipv4_addr=rtnl_addr_alloc();
lo_ipv4_addr=nl_addr_alloc(8);
if((err=nl_addr_parse(ipv4address、AF_INET和lo_ipv4_addr))<0){
nl_perror(错误,“无法解析本地IPv4地址”);
返回错误;
}
/*正在将nl_addr复制到rtnl_addr*/
如果((err=rtnl\u addr\u set\u local(ipv4\u addr,lo\u ipv4\u addr))<0){
nl_perror(错误,“无法设置地址。\n”);
返回错误;
}
/*分配链接对象列表,该列表将由内核中的当前链接填充*/
if((err=rtnl_link_alloc_缓存(sk、AF_unsec和link_缓存))<0){
nl_perror(错误,“无法分配缓存”);
返回错误;
}
/*通过名字找到我们的桥*/
if((link=rtnl\u link\u get\u by\u name(link\u cache,bridge\u name))==0){
fprintf(stderr,“没有%s桥。使用create\u bridge(\“%s\”)函数创建一个。\n”,bridge\u name,bridge\u name);
返回1;
}
/*看看它到底是不是一座桥*/
如果(rtnl_链路_是_桥(链路)==0){
fprintf(stderr,“%s不是网桥设备。\n”,网桥名称);
返回2;
}
/*获取桥的索引*/
如果((ifindex=rtnl\u link\u get\u ifindex(link))==0){
fprintf(stderr,“未设置%s网桥的接口索引。\n”,网桥名称);
返回3;
}
/*将接口索引设置为rtnl_addr*/
rtnl地址集ifindex(ipv4地址,ifindex);
/*设置IP地址*/
rtnl地址设置链接(ipv4地址,链接);
/*将rtnl_addr发送到内核*/
如果((err=rtnl\u addr\u add(sk,ipv4\u addr,0))<0){
nl_peror(错误,“无法添加rtnl_addr”);
返回错误;
}
/*删除rtnl_addr*/
如果((err=rtnl\u addr\u delete(sk,ipv4\u addr,0))<0){
nl_perror(错误,“无法删除rtnl_地址”);
返回错误;
}
/*释放以前分配的nl_addrs对象*/
nl地址(lo地址);
/*释放以前分配的rtnl_addrs对象*/
rtnl地址(ipv4地址);
/*释放以前分配的链接对象列表*/
nl_缓存免费(链接缓存);
/*释放以前分配的套接字*/
无插座(sk);
/*释放以前分配的链接对象*/
rtnl_链路_put(链路);
返回0;
}
在主要功能中,我具有以下功能:

/* Creates the bridges */
if ((err = create_bridge(BRIDGE1_NAME)) < 0) {
    fprintf(stderr,"Unable to create bridge.\n");
    return err;
}

if ((err = create_bridge(BRIDGE2_NAME)) < 0) {
    fprintf(stderr,"Unable to create bridge.\n");
    return err;
}

/* Setting the IP address to the bridges */
if ((err = set_bridge_ipv4(BRIDGE1_NAME, IP1)) != 0) {
    fprintf(stderr,"Unable to set IPv4 address to the bridge.\n");
    return err;
}

if ((err = set_bridge_ipv4(BRIDGE1_NAME, IP1)) != 0) {
    fprintf(stderr,"Unable to set IPv4 address to the bridge.\n");
    return err;
}
/*创建桥接器*/
如果((err=create_bridge(BRIDGE1_NAME))<0){
fprintf(stderr,“无法创建桥。\n”);
返回错误;
}
如果((err=create_bridge(BRIDGE2_NAME))<0){
fprintf(stderr,“无法创建桥。\n”);
返回错误;
}
/*设置网桥的IP地址*/
if((err=set_bridge_ipv4(BRIDGE1_NAME,IP1))!=0){
fprintf(stderr,“无法将IPv4地址设置为网桥。\n”);
返回错误;
}
if((err=set_bridge_ipv4(BRIDGE1_NAME,IP1))!=0){
fprintf(标准