• Main Page
  • Modules
  • Data Structures
  • Files
  • File List

rtnl-route-dump.c

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

Generated on Sun Dec 26 2010 22:23:55 for libmnl by  doxygen 1.7.1