thom311 / libnl

Netlink Library Suite
GNU Lesser General Public License v2.1
419 stars 311 forks source link

need help about rtnl_route_nh_set_via #365

Closed calvin2021y closed 10 months ago

calvin2021y commented 10 months ago

I want to do ip route replace 192.168.2.0/24 dev eth10 via 10.2.3.1 src 10.1.3.1 with libnl

#include <libnl3/netlink/netlink.h>
#include <libnl3/netlink/cache.h>
#include <libnl3/netlink/socket.h>

#include <libnl3/netlink/route/addr.h>
#include <libnl3/netlink/route/route.h>
#include <libnl3/netlink/route/nexthop.h>
#include <libnl3/netlink/route/link.h>

#include <errno.h>
#include <unistd.h>

#include <linux/netlink.h>
#include <linux/if_link.h>
#include <net/if.h>

int main(){
    const char *ifname = "eth10";
    const char *ip = "10.1.3.1" ;
    const char *gw = "10.2.3.1";
    const char *subnet = "192.168.2.0/24";
    int errn0 =0;
    int line  =0;
    struct nl_sock *sock        = NULL;
    struct nl_cache *link_cache = NULL;
    struct rtnl_route *route    = NULL;
    struct rtnl_link *link      = NULL;
    struct nl_addr *gw_addr     = NULL;
    struct nl_addr *src_addr    = NULL;
    struct nl_addr *dst_addr    = NULL;
    switch(1) default : {
        int family =  AF_INET;
        sock = nl_socket_alloc();
        if( sock == NULL ) {
            line = __LINE__;
            break;
        }
        errn0 = nl_connect(sock, NETLINK_ROUTE);
        if( errn0 < 0 ) {
            line = __LINE__;
            break;
        }
        errn0 = rtnl_link_alloc_cache(sock, AF_UNSPEC, &link_cache);
        if( errn0 < 0 ) {
            line = __LINE__;
            break;
        }
        link = rtnl_link_get_by_name(link_cache, ifname);
        if( link == NULL ) {
            printf("can not find iface=%s\n", ifname);
            line = __LINE__;
            break;
        }
        int ifindex = rtnl_link_get_ifindex(link);
        if( ifindex == 0 ) {
            line = __LINE__;
            break;
        }
        route = rtnl_route_alloc();
        if( route == NULL ) {
            line = __LINE__;
            break;
        }
        errn0 = nl_addr_parse(subnet, family, &dst_addr);
        if( dst_addr == NULL ) {
            line = __LINE__;
            break;
        }
        errn0   = rtnl_route_set_dst(route, dst_addr);
        if( errn0 < 0 ) {
            line = __LINE__;
            break;
        }
        errn0 = nl_addr_parse(ip, family, &src_addr);
        if( src_addr == NULL ) {
            line = __LINE__;
            break;
        }
        errn0   = rtnl_route_set_pref_src(route, src_addr);
        if( errn0 < 0 ) {
            line = __LINE__;
            break;
        }
        struct rtnl_nexthop *nh = rtnl_route_nh_alloc();
        if( nh == NULL ) {
            line = __LINE__;
            break;
        }
        errn0 = rtnl_route_nh_set_newdst(nh, dst_addr);
        if( errn0 < 0 ) {
            line = __LINE__;
            break;
        }
        errn0 = nl_addr_parse(gw, family, &gw_addr);
        if( gw_addr == NULL ) {
            line = __LINE__;
            break;
        }
        errn0   = rtnl_route_nh_set_via(nh, gw_addr);
        if( errn0 < 0 ) {
            line = __LINE__;
            break;
        }
        errn0   = rtnl_route_set_type(route, RTN_UNICAST);
        if( errn0 < 0 ) {
            line = __LINE__;
            break;
        }
        rtnl_route_nh_set_ifindex(nh, ifindex);
        rtnl_route_add_nexthop(route, nh);
        errn0   = rtnl_route_set_family(route, family);
        if( errn0 < 0 ) {
            line = __LINE__;
            break;
        }
        rtnl_route_set_priority(route, RTN_UNSPEC);
        rtnl_route_set_table(route, RT_TABLE_MAIN);
        rtnl_route_set_iif(route, ifindex);
        errn0   = rtnl_route_add(sock, route, NLM_F_CREATE | NLM_F_REPLACE);
        if( errn0 < 0 ) {
            line = __LINE__;
            break;
        }
        line    = 0;
    }
    if( gw_addr != NULL ) {
        nl_addr_put(gw_addr);
    }
    if( dst_addr != NULL ) {
        nl_addr_put(dst_addr);
    }
    if( link != NULL ) {
        rtnl_link_put(link);
    }
    if( link_cache != NULL ) {
        nl_cache_free(link_cache);
    }
    if( route != NULL ) {
        rtnl_route_put(route);
    }
    if( sock != NULL ) {
        nl_socket_free(sock);
    }
    if( line != 0 ) {
        printf("errno %d %s from %d\n", errn0,  nl_geterror(errn0), line);
    }
    return 0;
}

get error Unspecific failure from rtnl_route_add.

I can not find example of rtnl_route_nh_set_via from google.

calvin2021y commented 10 months ago

https://stackoverflow.com/questions/77359368/need-help-about-rtnl-route-nh-set-via-from-libnl