1#include <netlink/netlink.h> 2#include <netlink/route/link.h> 3#include <netlink/route/link/bridge.h> 4 5#define TEST_BRIDGE_NAME "testbridge" 6#define TEST_INTERFACE_NAME "testtap1" 7 8int create_bridge(struct nl_sock *sk, struct nl_cache *link_cache, const char *name) { 9 struct rtnl_link *link; 10 int err; 11 12 link = rtnl_link_alloc(); 13 if ((err = rtnl_link_set_type(link, "bridge")) < 0) { 14 rtnl_link_put(link); 15 return err; 16 } 17 rtnl_link_set_name(link, name); 18 19 if ((err = rtnl_link_add(sk, link, NLM_F_CREATE)) < 0) { 20 return err; 21 } 22 rtnl_link_put(link); 23 24 return 0; 25} 26 27int main(int argc, char *argv[]) 28{ 29 struct rtnl_link *link; 30 struct nl_cache *link_cache; 31 struct nl_sock *sk; 32 int err; 33 34 sk = nl_socket_alloc(); 35 if ((err = nl_connect(sk, NETLINK_ROUTE)) < 0) { 36 nl_perror(err, "Unable to connect socket"); 37 return err; 38 } 39 40 if ((err = rtnl_link_alloc_cache(sk, AF_UNSPEC, &link_cache)) < 0) { 41 nl_perror(err, "Unable to allocate cache"); 42 return err; 43 } 44 45 if ((err = create_bridge(sk, link_cache, TEST_BRIDGE_NAME)) < 0) { 46 nl_perror(err, "Unable to allocate testbridge"); 47 return err; 48 } 49 50 nl_cache_refill(sk, link_cache); 51 52 link = rtnl_link_get_by_name(link_cache, TEST_BRIDGE_NAME); 53 struct rtnl_link *ltap = rtnl_link_get_by_name(link_cache, TEST_INTERFACE_NAME); 54 if (!ltap) { 55 fprintf(stderr, "You should create a tap interface before lunch this test (# tunctl -t %s)\n", TEST_INTERFACE_NAME); 56 return -1; 57 } 58 59 if ((err = rtnl_link_enslave(sk, link, ltap)) < 0) { 60 nl_perror(err, "Unable to enslave interface to his bridge\n"); 61 return err; 62 } 63 64 if(rtnl_link_is_bridge(link) == 0) { 65 fprintf(stderr, "Link is not a bridge\n"); 66 return -2; 67 } 68 if(rtnl_link_get_master(ltap) <= 0) { 69 fprintf(stderr, "Interface is not attached to a bridge\n"); 70 return -3; 71 } 72 73 rtnl_link_put(ltap); 74 rtnl_link_put(link); 75 76 nl_cache_free(link_cache); 77 nl_socket_free(sk); 78 79 return 0; 80} 81