libmnl
1.0.3
|
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 }