netlink 를 통한 NETLINKINET_DIAG 프로 토 콜 은 현재 시스템 의 모든 TCP 연결 정 보 를 가 져 옵 니 다.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <asm/types.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#include <linux/inet_diag.h>
#include <netinet/tcp.h>
int main(int argc, char **argv)
{
int fd;
struct sockaddr_nl src_addr, dest_addr;
struct
{
struct nlmsghdr nlh;
struct inet_diag_req r;
} req;
struct inet_diag_msg *pkg;
struct msghdr msg;
char buf[8192];
char src_ip[40];
char dest_ip[40];
struct iovec iov;
if ((fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_INET_DIAG)) < 0)
return -1;
int ret;
ret = fcntl(fd, F_SETFL, O_NONBLOCK);
if (ret < 0) {
fprintf(stderr, "Can't set socket flags");
close(fd);
return -1;
}
//src addr
memset(&src_addr, 0, sizeof(struct sockaddr_nl));
src_addr.nl_family = AF_NETLINK;
src_addr.nl_pid = getpid();
src_addr.nl_groups = 0;
if (bind(fd, (struct sockaddr *)&src_addr, sizeof(struct sockaddr_nl)) < 0) {
fprintf(stderr, "bind socket error %s
", 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_MATCH | NLM_F_REQUEST | NLM_F_ROOT;
// req.nlh.nlmsg_flags = NLM_F_REQUEST ;
req.nlh.nlmsg_pid = 0;
memset(&req.r, 0, sizeof(req.r));
req.r.idiag_family = AF_INET;
req.r.idiag_states = ((1 << TCP_CLOSING + 1) - 1); //states to dump
//send msg to kernel
iov.iov_base = &req;
iov.iov_len = sizeof(req);
//dest addr
memset(&dest_addr, 0, sizeof(struct sockaddr_nl));
dest_addr.nl_family = AF_NETLINK;
dest_addr.nl_pid = 0;
dest_addr.nl_groups = 0;
msg.msg_name = (void *)&dest_addr;
msg.msg_namelen = sizeof(dest_addr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
if (sendmsg(fd, &msg, 0) < 0) {
printf("%s
", strerror(errno));
return -1;
}
//recv msg from kernel
iov.iov_base = buf;
iov.iov_len = sizeof(buf);
while (1) {
//printf("while1
");
int status;
struct nlmsghdr *h;
msg = (struct msghdr)
{
(void *)&dest_addr, sizeof(struct sockaddr_nl),
&iov, 1, NULL, 0, 0
};
//length of recv data
status = recvmsg(fd, &msg, 0);
//status = recv(fd, buf, sizeof(buf), 0);
printf("status = %d
", status);
if (status < 0) {
if (errno == EINTR) {
continue;
}
printf("errno = %d
", errno);
continue;
}
if (status == 0) {
close(fd);
printf("EOF
");
return 0;
}
h = (struct nlmsghdr *)buf;
while (NLMSG_OK(h, status)) {
//printf("while2
");
if (h->nlmsg_type == NLMSG_DONE) {
close(fd);
printf("NLMSG_DONE
");
return 0;
}
if (h->nlmsg_type == NLMSG_ERROR) {
struct nlmsgerr *err;
err = (struct nlmsgerr*)NLMSG_DATA(h);
fprintf(stderr, "%d Error %d:%s
", __LINE__, -(err->error), strerror(-(err->error)));
close(fd);
printf("NLMSG_ERROR
");
return 0;
}
pkg = (struct inet_diag_msg *)NLMSG_DATA(h);
memset(src_ip, 0, sizeof(src_ip));
memset(dest_ip, 0, sizeof(dest_ip));
inet_ntop(pkg->idiag_family, pkg->id.idiag_src, src_ip, sizeof(src_ip));
inet_ntop(pkg->idiag_family, pkg->id.idiag_dst, dest_ip, sizeof(dest_ip));
printf("%-8s %4d %40s:%-6hu %40s:%-6hu
", pkg->idiag_family == AF_INET ? "AF_INET" : "AF_INET6", pkg->idiag_state
, src_ip, ntohs(pkg->id.idiag_sport), dest_ip, ntohs(pkg->id.idiag_dport));
// get_tcp_state(pkg->idiag_state);
h = NLMSG_NEXT(h, status);
//printf("status = %d
", status);
}//while
}//while
close(fd);
return 0;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
dns netstat route arp tcpdumpcat/etc/resolv.conf#dns 정보 netstat -r -n # 라우팅 테이블, 게이트웨이 정보 route -n ifconfig #ip 정보, 적용, package 보내기 arp# IP와 맥 주소를 연결...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.