- 论坛徽章:
- 0
|
各位好,我想通过netlink的NETLINK_INET_DIAG协议获取指定套接字的链接状态,但是每次执行的时候都会有下面的错误:
edsionte@edsionte-VirtualBox ~/netlink $ ./a.out
enter while1..
89 Error 116:Stale NFS file handle
不知道这是怎么回事?
程序如下:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <asm/types.h> //NLMSG_OK()
#include <sys/socket.h> //
#include <linux/netlink.h>
#include <linux/inet_diag.h>
int main(int argc, char **argv)
{
int fd;
struct sockaddr_nl nladdr;
struct {
struct nlmsghdr nlh;
struct inet_diag_req r;
} req;
struct inet_diag_msg *pkg;
struct msghdr msg;
char buf[8192];
struct iovec iov;
if ((fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_INET_DIAG)) < 0)
return -1;
memset(&nladdr, 0, sizeof(nladdr));
nladdr.nl_family = AF_NETLINK;
nladdr.nl_pid = 0;
nladdr.nl_groups = 0;
if (bind(fd, (struct sockaddr *)&nladdr, sizeof(nladdr)) < 0) {
fprintf(stderr, "bind socket error %s\n", strerror(errno));
}
memset(&req, 0, sizeof(req));
req.nlh.nlmsg_len = sizeof(req);
req.nlh.nlmsg_type = TCPDIAG_GETSOCK;
req.nlh.nlmsg_flags = NLM_F_REQUEST;
req.nlh.nlmsg_pid = getpid();
//req.nlh.nlmsg_seq = 123456;
memset(&req.r, 0, sizeof(req.r));
req.r.idiag_family = AF_INET;
//req.r.idiag_states = 0; //states to dump
req.r.id.idiag_sport = htons(53);
req.r.id.idiag_dport = htons(0);
inet_pton(AF_INET, "127.0.0.1", req.r.id.idiag_src);
inet_pton(AF_INET, "0.0.0.0", req.r.id.idiag_dst);
//send msg to kernel
iov.iov_base = &req;
iov.iov_len = sizeof(req);
msg.msg_name = (void *)&nladdr;
msg.msg_namelen = sizeof(nladdr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
if (sendmsg(fd, &msg, 0) < 0)
return -1;
/*
//recv msg from kernel
iov.iov_base = buf;
iov.iov_len = sizeof(buf);
*/
printf("enter while1..\n");
while (1) {
int status;
struct nlmsghdr *h;
/*
msg = (struct msghdr) {
(void *)&nladdr, sizeof(nladdr),
&iov, 1, NULL, 0, 0
};
*/
// status = recvmsg(fd, &msg, 0);
status = recv(fd, buf, sizeof(buf), 0);
if (status < 0)
break;
h = (struct nlmsghdr *)buf;
while (NLMSG_OK(h, status)) {
if (h->nlmsg_type == NLMSG_DONE)
break;
if (h->nlmsg_type == NLMSG_ERROR) {
struct nlmsgerr *err;
err = (struct nlmsgerr*)NLMSG_DATA(h);
fprintf(stderr, "%d Error %d:%s\n", __LINE__, -(err->error), strerror(-(err->error)));
break;
}
pkg = (struct inet_diag_msg *)NLMSG_DATA(h);
fprintf(stderr, "Get a PKG:\n");
fprintf(stderr, "Family:%s", pkg->idiag_family == AF_INET ? "AF_INET" : "AF_INET6");
}//while
h = NLMSG_NEXT(h, status);
/*
if (status < 0) {
if (errno == EINTR)
continue;
perror("OVERRUN");
continue;
}
if (status == 0) {
fprintf(stderr, "EOF on netlink\n");
close(fd);
return 0;
}
printf("fwrite..\n");
// fwrite(buf, 1, NLMSG_ALIGN(status), stdout);
h = (struct nlmsghdr *)buf;
while (NLMSG_OK(h, status)) {
int err;
struct inet_diag_msg *r = NLMSG_DATA(h);
if (h->nlmsg_seq != 123456)
goto skip_it;
if (h->nlmsg_type == NLMSG_DONE) {
close(fd);
return 0;
}
if (h->nlmsg_type == NLMSG_ERROR) {
struct nlmsger *err = (struct nlmsgerr *)NLMSG_DATA(h);
if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr))) {
fprintf(stderr, "ERROR truncated\n");
} else {
// errno = -err->error;
perror("TCPDIAG answers");
}
close (fd);
return 0;
}
skip_it:
h = NLMSG_NEXT(h, status);
}//while
if (msg.msg_flags & MSG_TRUNC) {
fprintf(stderr, "Message truncated\n");
continue;
}
if (status) {
fprintf(stderr," !!Remnant of size %d\n", status);
exit(1);
}
*/
}//while
close(fd);
return 0;
} |
|