00001
00002
00003
00004
00005
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
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
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
00113 printf("family=%u ", rm->rtm_family);
00114
00115
00116 printf("dst_len=%u ", rm->rtm_dst_len);
00117
00118
00119 printf("src_len=%u ", rm->rtm_src_len);
00120
00121
00122 printf("tos=%u ", rm->rtm_tos);
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137 printf("table=%u ", rm->rtm_table);
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154 printf("type=%u ", rm->rtm_type);
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166 printf("scope=%u ", rm->rtm_scope);
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178 printf("proto=%u ", rm->rtm_protocol);
00179
00180
00181
00182
00183
00184
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 }