libmnl  1.0.3
rtnl-route-dump.c
00001 /* This example is placed in the public domain. */
00002 #include <stdio.h>
00003 #include <stdlib.h>
00004 #include <unistd.h>
00005 #include <time.h>
00006 #include <arpa/inet.h>
00007 
00008 #include <libmnl/libmnl.h>
00009 #include <linux/if.h>
00010 #include <linux/if_link.h>
00011 #include <linux/rtnetlink.h>
00012 
00013 static int data_attr_cb2(const struct nlattr *attr, void *data)
00014 {
00015         /* skip unsupported attribute in user-space */
00016         if (mnl_attr_type_valid(attr, RTAX_MAX) < 0)
00017                 return MNL_CB_OK;
00018 
00019         if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
00020                 perror("mnl_attr_validate");
00021                 return MNL_CB_ERROR;
00022         }
00023         return MNL_CB_OK;
00024 }
00025 
00026 static void attributes_show_ipv4(struct nlattr *tb[])
00027 {
00028         if (tb[RTA_TABLE]) {
00029                 printf("table=%u ", mnl_attr_get_u32(tb[RTA_TABLE]));
00030         }
00031         if (tb[RTA_DST]) {
00032                 struct in_addr *addr = mnl_attr_get_payload(tb[RTA_DST]);
00033                 printf("dst=%s ", inet_ntoa(*addr));
00034         }
00035         if (tb[RTA_SRC]) {
00036                 struct in_addr *addr = mnl_attr_get_payload(tb[RTA_SRC]);
00037                 printf("src=%s ", inet_ntoa(*addr));
00038         }
00039         if (tb[RTA_OIF]) {
00040                 printf("oif=%u ", mnl_attr_get_u32(tb[RTA_OIF]));
00041         }
00042         if (tb[RTA_FLOW]) {
00043                 printf("flow=%u ", mnl_attr_get_u32(tb[RTA_FLOW]));
00044         }
00045         if (tb[RTA_PREFSRC]) {
00046                 struct in_addr *addr = mnl_attr_get_payload(tb[RTA_PREFSRC]);
00047                 printf("prefsrc=%s ", inet_ntoa(*addr));
00048         }
00049         if (tb[RTA_GATEWAY]) {
00050                 struct in_addr *addr = mnl_attr_get_payload(tb[RTA_GATEWAY]);
00051                 printf("gw=%s ", inet_ntoa(*addr));
00052         }
00053         if (tb[RTA_METRICS]) {
00054                 int i;
00055                 struct nlattr *tbx[RTAX_MAX+1] = {};
00056 
00057                 mnl_attr_parse_nested(tb[RTA_METRICS], data_attr_cb2, tbx);
00058 
00059                 for (i=0; i<RTAX_MAX; i++) {
00060                         if (tbx[i]) {
00061                                 printf("metrics[%d]=%u ",
00062                                         i, mnl_attr_get_u32(tbx[i]));
00063                         }
00064                 }
00065         }
00066         printf("\n");
00067 }
00068 
00069 static int data_attr_cb(const struct nlattr *attr, void *data)
00070 {
00071         const struct nlattr **tb = data;
00072         int type = mnl_attr_get_type(attr);
00073 
00074         /* skip unsupported attribute in user-space */
00075         if (mnl_attr_type_valid(attr, RTA_MAX) < 0)
00076                 return MNL_CB_OK;
00077 
00078         switch(type) {
00079         case RTA_TABLE:
00080         case RTA_DST:
00081         case RTA_SRC:
00082         case RTA_OIF:
00083         case RTA_FLOW:
00084         case RTA_PREFSRC:
00085         case RTA_GATEWAY:
00086                 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
00087                         perror("mnl_attr_validate");
00088                         return MNL_CB_ERROR;
00089                 }
00090                 break;
00091         case RTA_METRICS:
00092                 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) {
00093                         perror("mnl_attr_validate");
00094                         return MNL_CB_ERROR;
00095                 }
00096                 break;
00097         }
00098         tb[type] = attr;
00099         return MNL_CB_OK;
00100 }
00101 
00102 static int data_cb(const struct nlmsghdr *nlh, void *data)
00103 {
00104         struct nlattr *tb[RTA_MAX+1] = {};
00105         struct rtmsg *rm = mnl_nlmsg_get_payload(nlh);
00106 
00107         /* protocol family = AF_INET | AF_INET6 */
00108         printf("family=%u ", rm->rtm_family);
00109 
00110         /* destination CIDR, eg. 24 or 32 for IPv4 */
00111         printf("dst_len=%u ", rm->rtm_dst_len);
00112 
00113         /* source CIDR */
00114         printf("src_len=%u ", rm->rtm_src_len);
00115 
00116         /* type of service (TOS), eg. 0 */
00117         printf("tos=%u ", rm->rtm_tos);
00118 
00119         /* table id:
00120          *      RT_TABLE_UNSPEC         = 0
00121          *
00122          *      ... user defined values ...
00123          *
00124          *      RT_TABLE_COMPAT         = 252
00125          *      RT_TABLE_DEFAULT        = 253
00126          *      RT_TABLE_MAIN           = 254
00127          *      RT_TABLE_LOCAL          = 255
00128          *      RT_TABLE_MAX            = 0xFFFFFFFF
00129          *
00130          * Synonimous attribute: RTA_TABLE.
00131          */
00132         printf("table=%u ", rm->rtm_table);
00133 
00134         /* type:
00135          *      RTN_UNSPEC      = 0
00136          *      RTN_UNICAST     = 1
00137          *      RTN_LOCAL       = 2
00138          *      RTN_BROADCAST   = 3
00139          *      RTN_ANYCAST     = 4
00140          *      RTN_MULTICAST   = 5
00141          *      RTN_BLACKHOLE   = 6
00142          *      RTN_UNREACHABLE = 7
00143          *      RTN_PROHIBIT    = 8
00144          *      RTN_THROW       = 9
00145          *      RTN_NAT         = 10
00146          *      RTN_XRESOLVE    = 11
00147          *      __RTN_MAX       = 12
00148          */
00149         printf("type=%u ", rm->rtm_type);
00150 
00151         /* scope:
00152          *      RT_SCOPE_UNIVERSE       = 0   : everywhere in the universe
00153          *
00154          *      ... user defined values ...
00155          *
00156          *      RT_SCOPE_SITE           = 200
00157          *      RT_SCOPE_LINK           = 253 : destination attached to link
00158          *      RT_SCOPE_HOST           = 254 : local address
00159          *      RT_SCOPE_NOWHERE        = 255 : not existing destination
00160          */
00161         printf("scope=%u ", rm->rtm_scope);
00162 
00163         /* protocol:
00164          *      RTPROT_UNSPEC   = 0
00165          *      RTPROT_REDIRECT = 1
00166          *      RTPROT_KERNEL   = 2 : route installed by kernel
00167          *      RTPROT_BOOT     = 3 : route installed during boot
00168          *      RTPROT_STATIC   = 4 : route installed by administrator
00169          *
00170          * Values >= RTPROT_STATIC are not interpreted by kernel, they are
00171          * just user-defined.
00172          */
00173         printf("proto=%u ", rm->rtm_protocol);
00174 
00175         /* flags:
00176          *      RTM_F_NOTIFY    = 0x100: notify user of route change
00177          *      RTM_F_CLONED    = 0x200: this route is cloned
00178          *      RTM_F_EQUALIZE  = 0x400: Multipath equalizer: NI
00179          *      RTM_F_PREFIX    = 0x800: Prefix addresses
00180          */
00181         printf("flags=%x\n", rm->rtm_flags);
00182 
00183         mnl_attr_parse(nlh, sizeof(*rm), data_attr_cb, tb);
00184 
00185         switch(rm->rtm_family) {
00186         case AF_INET:
00187                 attributes_show_ipv4(tb);
00188                 break;
00189         }
00190 
00191         return MNL_CB_OK;
00192 }
00193 
00194 int main(void)
00195 {
00196         struct mnl_socket *nl;
00197         char buf[MNL_SOCKET_BUFFER_SIZE];
00198         struct nlmsghdr *nlh;
00199         struct rtmsg *rtm;
00200         int ret;
00201         unsigned int seq, portid;
00202 
00203         nlh = mnl_nlmsg_put_header(buf);
00204         nlh->nlmsg_type = RTM_GETROUTE;
00205         nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
00206         nlh->nlmsg_seq = seq = time(NULL);
00207         rtm = mnl_nlmsg_put_extra_header(nlh, sizeof(struct rtmsg));
00208         rtm->rtm_family = AF_INET;
00209 
00210         nl = mnl_socket_open(NETLINK_ROUTE);
00211         if (nl == NULL) {
00212                 perror("mnl_socket_open");
00213                 exit(EXIT_FAILURE);
00214         }
00215 
00216         if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
00217                 perror("mnl_socket_bind");
00218                 exit(EXIT_FAILURE);
00219         }
00220         portid = mnl_socket_get_portid(nl);
00221 
00222         if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
00223                 perror("mnl_socket_send");
00224                 exit(EXIT_FAILURE);
00225         }
00226 
00227         ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
00228         while (ret > 0) {
00229                 ret = mnl_cb_run(buf, ret, seq, portid, data_cb, NULL);
00230                 if (ret <= MNL_CB_STOP)
00231                         break;
00232                 ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
00233         }
00234         if (ret == -1) {
00235                 perror("error");
00236                 exit(EXIT_FAILURE);
00237         }
00238 
00239         mnl_socket_close(nl);
00240 
00241         return 0;
00242 }