#if 0 i have written this sample program to get the interface address but it seems to give me only the lo interface how do i get information about the eth0 interface can somebody gimme some pointers here -SIGTERM amit #endif /* original name = testIPv6.c */ /* author: amit.limaye@patni.com */ /* gcc [-DSENDTO] -O2 rtnl_test.c -o rtnl_test */ #include #include #include #include #include #include #include #include //#include ///#define SENDTO 1 // undef => use bind/send, defined => use sendto; #define PROGNAME "rtnl_test" #define VERSION "0.1" #define BUFF_SIZE (64 * 1024) #define TEMP_SIZE 50 #define RTA_SESSION (RTA_CACHEINFO + 1) #define RTA_HOPLIMIT (RTA_SESSION + 1) #define RTA_RTINFO (RTA_HOPLIMIT + 1) struct rta_rtinfo { __s32 rta_obsolete; __u32 rta_sernum; }; int seqnum = 0; void die (char *msg) { if (errno) fprintf (stderr, "[%s]: err = %d (0x%x)\n", msg, errno, errno); exit (2); } void usage (void) { fprintf (stderr, "%s [options] {ver. %s}\n", PROGNAME, VERSION); fprintf (stderr, " options: -h help\n"); fprintf (stderr, " -r route info (IPv4)\n"); fprintf (stderr, " -s route info (IPv6)\n"); exit (1); } int route_info (char which) { int route4info = which == 'r'; int sockfd = 0; struct sockaddr_nl nladdr; char buff[BUFF_SIZE]; struct iovec iov = { .iov_base = buff, .iov_len = BUFF_SIZE }; struct msghdr buff_msghdr = { .msg_name = (void *)&nladdr, .msg_namelen = sizeof(nladdr), .msg_iov = &iov, .msg_iovlen = 1, .msg_control = NULL, .msg_controllen = 0, .msg_flags = 0 }; char temp_addr[TEMP_SIZE] = ""; int len = 0; int err; struct { struct nlmsghdr nlh; struct rtmsg rtm; } req; struct nlmsghdr *reply; struct rtmsg *rtm; struct rtattr *rta; struct rta_cacheinfo *rtcache; struct rta_rtinfo *rtinfo; memset(buff, 0, BUFF_SIZE); // get a NETLINK_ROUTE[6] socket: sockfd = socket(PF_NETLINK, SOCK_DGRAM, route4info ? NETLINK_ROUTE : NETLINK_ROUTE6); if (sockfd < 0) die ("socket"); nladdr.nl_family = AF_NETLINK; nladdr.nl_pad = 0; nladdr.nl_pid = 0; // target in kernel nladdr.nl_groups = 0; #ifndef SENDTO err = bind(sockfd, (struct sockaddr *)&nladdr, sizeof(struct sockaddr_nl)); if (err < 0) die ("bind"); #endif memset (&req, 0, sizeof (req)); req.nlh.nlmsg_len = sizeof (req); req.nlh.nlmsg_type = RTM_GETROUTE; req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_REQUEST; req.nlh.nlmsg_pid = 0; req.nlh.nlmsg_seq = ++seqnum; req.rtm.rtm_family = route4info ? AF_INET : AF_INET6; ///req.rtm.rtm_flags |= RTM_F_CLONED; // TBD: ??? #ifndef SENDTO err = send(sockfd, &req, req.nlh.nlmsg_len, 0); #else err = sendto(sockfd, &req, req.nlh.nlmsg_len, 0, (struct sockaddr *)&nladdr, sizeof(struct sockaddr_nl)); #endif if (err < 0) die ("send(to)"); err = recvmsg(sockfd, &buff_msghdr, 0); if (err < 0) die ("recvmsg"); reply = (struct nlmsghdr *)buff; rtm = NLMSG_DATA(reply); rta = IFLA_RTA(rtm); len = reply->nlmsg_len; printf("Length is %d\n", len); printf ("static rtmsg header fields:\n"); printf (" family: %d | dst_len: %d | src_len: %d | TOS: %d\n", rtm->rtm_family, rtm->rtm_dst_len, rtm->rtm_src_len, rtm->rtm_tos); printf (" rttblID: %d | protocol: %d | scope: %d | type: %d | flags: 0x%x\n", rtm->rtm_table, rtm->rtm_protocol, rtm->rtm_scope, rtm->rtm_type, rtm->rtm_flags); printf ("rtm attributes:\n"); while(RTA_OK(rta, len)) { switch(rta->rta_type) { case RTA_DST: ///inet_ntop(AF_INET, RTA_DATA(rta), temp_addr, TEMP_SIZE); printf("route_dst_addr: %s\n", temp_addr); break; case RTA_SRC: ///inet_ntop(AF_INET, RTA_DATA(rta), temp_addr, TEMP_SIZE); printf("route_src_addr: %s\n", temp_addr); break; case RTA_IIF: printf("input iface index: %d\n", RTA_DATA(rta)); break; case RTA_OIF: printf("output iface index: %d\n", RTA_DATA(rta)); break; case RTA_GATEWAY: ///inet_ntop(AF_INET, RTA_DATA(rta), temp_addr, TEMP_SIZE); printf("route_gw_addr: %s\n", temp_addr); break; case RTA_PRIORITY: printf("route priority: %d\n", RTA_DATA(rta)); break; case RTA_PREFSRC: printf("preferred src: %d\n", RTA_DATA(rta)); break; case RTA_METRICS: printf("route metric: %d\n", RTA_DATA(rta)); break; case RTA_MULTIPATH: printf("route mpath: %d\n", RTA_DATA(rta)); break; case RTA_PROTOINFO: printf("route proto info: %d\n", RTA_DATA(rta)); break; case RTA_FLOW: printf("route flow: %d\n", RTA_DATA(rta)); break; case RTA_CACHEINFO: rtcache = (struct rta_cacheinfo *) &buff; printf("cache info: clntref: %d, lastuse: %d, expires: %d, error: %d, used: %d\n", rtcache->rta_clntref, rtcache->rta_lastuse, rtcache->rta_expires, rtcache->rta_error, rtcache->rta_used); printf(" id: %d, ts: %d, tsage: %d\n", rtcache->rta_id, rtcache->rta_ts, rtcache->rta_tsage); break; case RTA_RTINFO: rtinfo = (struct rta_rtinfo *) &buff; printf ("route info2: obsolete: %d, sernum: %d\n", rtinfo->rta_obsolete, rtinfo->rta_sernum); break; default: printf("Unknown rta_type (%d)\n", rta->rta_type); break; } printf("\nLooping to next RTA_\n"); rta = RTA_NEXT(rta, len); } return 0; } // end route_info; int main (int argc, char *argv []) { int ix; char ch; if (argc == 1) usage (); for (ix = 1; ix < argc; ix++) { if (*argv [ix] != '-') usage (); ch = *(argv [ix] + 1); switch (ch) { case 'r': case 's': route_info (ch); break; default: case 'h': usage (); break; } } } // end main; // end rtnl_test.c;