Scroll to navigation

sock_diag(7) Miscellaneous Information Manual sock_diag(7)

الاسم

sock_diag - الحصول على معلومات حول المقابس

موجز

#include <sys/socket.h>
#include <linux/sock_diag.h>
#include <linux/unix_diag.h> /* for UNIX domain sockets */
#include <linux/inet_diag.h> /* for IPv4 and IPv6 sockets */
diag_socket = socket(AF_NETLINK, socket_type, NETLINK_SOCK_DIAG);

الوصف

النظام الفرعي sock_diag netlink يوفر آلية للحصول على معلومات حول مقابس من عائلات عناوين مختلفة من النواة. يمكن استخدام هذا النظام الفرعي للحصول على معلومات حول مقابس فردية أو طلب قائمة بالمقابس.

في الطلب، يمكن للمتصل تحديد معلومات إضافية يرغب في الحصول عليها حول المقبس، على سبيل المثال، معلومات الذاكرة أو معلومات خاصة بعائلة العنوان.

عند طلب قائمة بالمقابس، يمكن للمتصل تحديد مرشحات تطبقها النواة لاختيار مجموعة فرعية من المقابس للإبلاغ عنها. حالياً، توجد فقط القدرة على تصفية المقابس حسب الحالة (متصل، مستمع، وهكذا).

لاحظ أن sock_diag يبلغ فقط عن تلك المقابس التي لها اسم؛ أي إما مقابس مربوطة صراحةً بـ bind(2) أو مقابس رُبطت آلياً بعنوان (مثلاً، بواسطة connect(2)). هذه هي نفس مجموعة المقابس المتاحة عبر /proc/net/unix، /proc/net/tcp، /proc/net/udp، وهكذا.

طلب

يبدأ الطلب برأس struct nlmsghdr الموصوف في netlink(7) مع حقل nlmsg_type مضبوط على SOCK_DIAG_BY_FAMILY. يتبعه رأس خاص بعائلة العنوان يبدأ بجزء مشترك بين جميع عائلات العناوين:


struct sock_diag_req {

__u8 sdiag_family;
__u8 sdiag_protocol; };

حقول هذا الهيكل هي كالتالي:

عائلة عنوان. يجب ضبطها على الثابت AF_* المناسب.
يعتمد على sdiag_family. يجب ضبطه على الثابت IPPROTO_* المناسب لـ AF_INET و AF_INET6، وإلى 0 خلاف ذلك.

إذا كان حقل nlmsg_flags لرأس struct nlmsghdr يحتوي على العلم NLM_F_DUMP مضبوطاً، فهذا يعني أن قائمة بالمقابس تُطلب؛ وإلا فهو استعلام عن مقبس فردي.

استجابة

تبدأ الاستجابة برأس struct nlmsghdr ويتبعها مصفوفة من الكائنات الخاصة بعائلة العنوان. يتم الوصول إلى المصفوفة باستخدام وحدات الماكرو القياسية NLMSG_* من واجهة برمجة التطبيقات netlink(3).

كل كائن هو قائمة NLA (سمات netlink) يتم الوصول إليها باستخدام وحدات الماكرو RTA_* من واجهة برمجة التطبيقات rtnetlink(3).

مقابس نطاق UNIX

بالنسبة لمقابس نطاق UNIX، يتم تمثيل الطلب في البنية التالية:


struct unix_diag_req {

__u8 sdiag_family;
__u8 sdiag_protocol;
__u16 pad;
__u32 udiag_states;
__u32 udiag_ino;
__u32 udiag_show;
__u32 udiag_cookie[2]; };

حقول هذا الهيكل هي كالتالي:

عائلة العنوان؛ يجب ضبطها على AF_UNIX.

sdiag_protocol

pad
يجب ضبط هذه الحقول على 0.
هذه قناع بتات يحدد مرشحًا لحالات المقابس. سيتم الإبلاغ فقط عن المقابس التي تكون حالاتها ضمن هذا القناع. يُتجاهل عند الاستعلام عن مقبس فردي. القيم المدعومة هي:

1 << TCP_ESTABLISHED

1 << TCP_LISTEN

هذا رقم عقدة (inode) عند الاستعلام عن مقبس فردي. يُتجاهل عند الاستعلام عن قائمة مقابس.
هذه مجموعة من الأعلام تحدد نوع المعلومات المراد الإبلاغ عنها. يُبلغ عن كل نوع مطلوب من المعلومات كخاصية netlink كما هو موضح أدناه:
الخاصية المبلغ عنها ردًا على هذا الطلب هي UNIX_DIAG_NAME. المحتوى المرتبط بهذه الخاصية هو اسم المسار الذي رُبط به المقبس (سلسلة من البايتات يصل حجمها إلى UNIX_PATH_MAX).
الخاصية المبلغ عنها ردًا على هذا الطلب هي UNIX_DIAG_VFS. المحتوى المرتبط بهذه الخاصية ممثل في البنية التالية:

struct unix_diag_vfs {

__u32 udiag_vfs_dev;
__u32 udiag_vfs_ino; };

حقول هذا الهيكل هي كالتالي:
رقم الجهاز لعقدة المقبس المقابلة على القرص.
رقم عقدة المقبس المقابلة على القرص.
الخاصية المبلغ عنها ردًا على هذا الطلب هي UNIX_DIAG_PEER. المحتوى المرتبط بهذه الخاصية هو قيمة __u32 تمثل رقم عقدة النظير. تُبلغ هذه الخاصية للمقابس المتصلة فقط.
الخاصية المبلغ عنها ردًا على هذا الطلب هي UNIX_DIAG_ICONS. المحتوى المرتبط بهذه الخاصية هو مصفوفة من قيم __u32 تمثل أرقام عقد المقابس التي مرت باستدعاء connect(2) ولكن لم تُعالج بعد باستخدام accept(2). تُبلغ هذه الخاصية لمقابس الاستماع فقط.
الخاصية المبلغ عنها ردًا على هذا الطلب هي UNIX_DIAG_RQLEN. المحتوى المرتبط بهذه الخاصية ممثل في البنية التالية:

struct unix_diag_rqlen {

__u32 udiag_rqueue;
__u32 udiag_wqueue; };

حقول هذا الهيكل هي كالتالي:
لمقابس الاستماع: عدد الاتصالات المعلقة. حجم المصفوفة المرتبطة بخاصية الاستجابة UNIX_DIAG_ICONS يساوي هذه القيمة.
للمقابس المنشأة: كمية البيانات في قائمة الانتظار الواردة.
للمقابس المستمعة: حجم التراكم الذي يساوي القيمة الممررة كوسيط ثانٍ إلى listen(2).
للمقابس المنشأة: كمية الذاكرة المتاحة للإرسال.
السمة المبلغ عنها ردًا على هذا الطلب هي UNIX_DIAG_MEMINFO. الحمولة المرتبطة بهذه السمة هي مصفوفة من قيم __u32 الموصوفة أدناه في القسم الفرعي "معلومات ذاكرة المقبس".

السمات التالية تُبلغ دون أي طلب محدد:

الحمولة المرتبطة بهذه السمة هي قيمة __u8 تمثل بتات حالة shutdown(2).
هذه مصفوفة من معرفات غير شفافة يمكن استخدامها مع udiag_ino لتحديد مقبس فردي. تُتجاهل عند الاستعلام عن قائمة مقابس، وكذلك عندما تُضبط جميع عناصرها على -1.

الاستجابة لاستعلام عن مقابس نطاق UNIX تمثل كمصفوفة من


struct unix_diag_msg {

__u8 udiag_family;
__u8 udiag_type;
__u8 udiag_state;
__u8 pad;
__u32 udiag_ino;
__u32 udiag_cookie[2]; };

متبوعة بسمات netlink.

حقول هذا الهيكل هي كالتالي:

لهذا الحقل نفس المعنى كما في struct unix_diag_req.
يُضبط هذا على واحد من SOCK_PACKET أو SOCK_STREAM أو SOCK_SEQPACKET.
يُضبط هذا على واحد من TCP_LISTEN أو TCP_ESTABLISHED.
يُضبط هذا الحقل على 0.
هذا هو رقم inode للمقبس.
هذه مصفوفة من معرفات غير شفافة يمكن استخدامها في استعلامات لاحقة.

مقابس IPv4 و IPv6

لمقابس IPv4 و IPv6، يُعرض الطلب في البنية التالية:


struct inet_diag_req_v2 {

__u8 sdiag_family;
__u8 sdiag_protocol;
__u8 idiag_ext;
__u8 pad;
__u32 idiag_states;
struct inet_diag_sockid id; };

حيث يُعرّف struct inet_diag_sockid كالتالي:


struct inet_diag_sockid {

__be16 idiag_sport;
__be16 idiag_dport;
__be32 idiag_src[4];
__be32 idiag_dst[4];
__u32 idiag_if;
__u32 idiag_cookie[2]; };

حقول struct inet_diag_req_v2 هي كالتالي:

يجب ضبط هذا على AF_INET أو AF_INET6 لمقابس IPv4 أو IPv6 على التوالي.
يجب ضبط هذا على أحد IPPROTO_TCP أو IPPROTO_UDP أو IPPROTO_UDPLITE.
هذه مجموعة من الأعلام تُعرّف نوع المعلومات الموسعة المطلوب الإبلاغ عنها. يُبلَغ عن كل نوع مطلوب من المعلومات كخاصية netlink كما هو موصوف أدناه:
الحمولة المرتبطة بهذه الخاصية هي قيمة __u8 تمثل TOS للمقبس.
الحمولة المرتبطة بهذه الخاصية هي قيمة __u8 تمثل TClass للمقبس. مقابس IPv6 فقط. بالنسبة لمقابس LISTEN و CLOSE، يتبع ذلك خاصية INET_DIAG_SKV6ONLY مع قيمة حمولة __u8 تشير إلى ما إذا كان المقبس مخصصًا لـ IPv6 فقط أم لا.
الحمولة المرتبطة بهذه الخاصية ممثلة في الهيكل التالي:

struct inet_diag_meminfo {

__u32 idiag_rmem;
__u32 idiag_wmem;
__u32 idiag_fmem;
__u32 idiag_tmem; };

حقول هذا الهيكل هي كالتالي:
كمية البيانات في طابور الاستقبال.
كمية البيانات المُصطفة بواسطة TCP ولكن لم تُرسَل بعد.
كمية الذاكرة المُجدوَلة للاستخدام المستقبلي (TCP فقط).
كمية البيانات في طابور الإرسال.
الحمولة المرتبطة بهذه الخاصية هي مصفوفة من قيم __u32 موصوفة أدناه في القسم الفرعي "معلومات ذاكرة المقبس".
الحمولة المرتبطة بهذه السمة خاصة بعائلة العنوان. لمقابس TCP، هي كائن من النوع struct tcp_info.
الحمولة المرتبطة بهذه السمة هي سلسلة تصف خوارزمية التحكم في الازدحام المستخدمة. لمقابس TCP فقط.
يجب ضبط هذا على 0.
هذه قناع بتات يعرّف مرشحًا لحالات المقبس. فقط تلك المقابس التي حالاتها ضمن هذا القناع سيتم الإبلاغ عنها. يتم تجاهله عند الاستعلام عن مقبس فردي.
هذا كائن معرف مقبس يُستخدم في طلبات التفريغ، وفي الاستعلامات عن مقابس فردية، ويُبلغ عنه في كل استجابة. على عكس مقابس نطاق UNIX، يتم تعريف مقابس IPv4 و IPv6 باستخدام العناوين والمنافذ. جميع القيم بترتيب بايت الشبكة.

حقول struct inet_diag_sockid هي كما يلي:

منفذ المصدر.
منفذ الوجهة.
عنوان المصدر.
عنوان الوجهة.
رقم الواجهة الذي يرتبط به المقبس.
هذه مصفوفة من المعرفات المعتمة التي يمكن استخدامها مع حقول أخرى من هذه البنية لتحديد مقبس فردي. يتم تجاهلها عند الاستعلام عن قائمة مقابس، وكذلك عندما تكون جميع عناصرها مضبوطة على -1.

الاستجابة لاستعلام عن مقابس IPv4 أو IPv6 ممثلة كمصفوفة من


struct inet_diag_msg {

__u8 idiag_family;
__u8 idiag_state;
__u8 idiag_timer;
__u8 idiag_retrans;
struct inet_diag_sockid id;
__u32 idiag_expires;
__u32 idiag_rqueue;
__u32 idiag_wqueue;
__u32 idiag_uid;
__u32 idiag_inode; };

متبوعة بسمات netlink.

حقول هذا الهيكل هي كالتالي:

هذا هو نفس الحقل الموجود في struct inet_diag_req_v2.
يشير هذا إلى حالة المقبس كما في struct inet_diag_req_v2.
بالنسبة لمقابس TCP، يصف هذا الحقل نوع المؤقت النشط حالياً للمقبس. يُضبط على أحد الثوابت التالية:
0
لا يوجد مؤقت نشط
1
مؤقت إعادة إرسال
2
مؤقت البقاء على قيد الحياة
3
مؤقت TIME_WAIT
4
مؤقت استقصاء النافذة الصفرية
بالنسبة للمقابس غير TCP، يُضبط هذا الحقل على 0.
بالنسبة لقيم idiag_timer 1 و2 و4، يحتوي هذا الحقل على عدد عمليات إعادة الإرسال. بالنسبة لقيم idiag_timer الأخرى، يُضبط هذا الحقل على 0.
بالنسبة لمقابس TCP التي تحتوي على مؤقت نشط، يصف هذا الحقل وقت انتهاء صلاحيته بالمللي ثانية. بالنسبة للمقابس الأخرى، يُضبط هذا الحقل على 0.
بالنسبة لمقابس الاستماع: عدد الاتصالات المعلقة.
بالنسبة للمقابس الأخرى: كمية البيانات في قائمة الانتظار الواردة.
بالنسبة لمقابس الاستماع: حجم التراكم.
بالنسبة للمقابس الأخرى: مقدار الذاكرة المتاحة للإرسال.
هذا هو UID مالك المقبس.
هذا هو رقم inode للمقبس.

معلومات ذاكرة المقبس

الحمولة المرتبطة بسمات netlink UNIX_DIAG_MEMINFO و INET_DIAG_SKMEMINFO هي مصفوفة من قيم __u32 التالية:

كمية البيانات في طابور الاستقبال.
مخزن المقبس المؤقت للاستقبال كما هو مضبوط بواسطة SO_RCVBUF.
كمية البيانات في طابور الإرسال.
مخزن المقبس المؤقت للإرسال كما هو مضبوط بواسطة SO_SNDBUF.
كمية الذاكرة المُجدوَلة للاستخدام المستقبلي (TCP فقط).
كمية البيانات المصفوفة بواسطة TCP، ولكن لم تُرسل بعد.
كمية الذاكرة المخصصة لاحتياجات خدمة المقبس (مثل، مرشح المقبس).
كمية الحزم في backlog (لم تُعالج بعد).

الإصدارات

NETLINK_INET_DIAG أُدخل في Linux 2.6.14 ودعم مقابس AF_INET و AF_INET6 فقط. في Linux 3.3، أُعيدت تسميته إلى NETLINK_SOCK_DIAG ووُسع لدعم مقابس AF_UNIX.

UNIX_DIAG_MEMINFO و INET_DIAG_SKMEMINFO أُدخلا في Linux 3.6.

المعايير

لينكس.

أمثلة

يطبع برنامج المثال التالي رقم inode، ورقم inode النظير، واسم جميع مقابس نطاق UNIX في مساحة الأسماء الحالية.

#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <linux/sock_diag.h>
#include <linux/unix_diag.h>
static int
send_query(int fd)
{

struct sockaddr_nl nladdr = {
.nl_family = AF_NETLINK
};
struct
{
struct nlmsghdr nlh;
struct unix_diag_req udr;
} req = {
.nlh = {
.nlmsg_len = sizeof(req),
.nlmsg_type = SOCK_DIAG_BY_FAMILY,
.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP
},
.udr = {
.sdiag_family = AF_UNIX,
.udiag_states = -1,
.udiag_show = UDIAG_SHOW_NAME | UDIAG_SHOW_PEER
}
};
struct iovec iov = {
.iov_base = &req,
.iov_len = sizeof(req)
};
struct msghdr msg = {
.msg_name = &nladdr,
.msg_namelen = sizeof(nladdr),
.msg_iov = &iov,
.msg_iovlen = 1
};
for (;;) {
if (sendmsg(fd, &msg, 0) < 0) {
if (errno == EINTR)
continue;
perror("sendmsg");
return -1;
}
return 0;
} } static int print_diag(const struct unix_diag_msg *diag, unsigned int size) {
if (size < NLMSG_LENGTH(sizeof(*diag))) {
fputs("short response\n", stderr);
return -1;
}
if (diag->udiag_family != AF_UNIX) {
fprintf(stderr, "unexpected family %u\n", diag->udiag_family);
return -1;
}
unsigned int rta_len = size - NLMSG_LENGTH(sizeof(*diag));
unsigned int peer = 0;
size_t path_len = 0;
char path[sizeof(((struct sockaddr_un *) 0)->sun_path) + 1];
for (struct rtattr *attr = (struct rtattr *) (diag + 1);
RTA_OK(attr, rta_len); attr = RTA_NEXT(attr, rta_len)) {
switch (attr->rta_type) {
case UNIX_DIAG_NAME:
if (!path_len) {
path_len = RTA_PAYLOAD(attr);
if (path_len > sizeof(path) - 1)
path_len = sizeof(path) - 1;
memcpy(path, RTA_DATA(attr), path_len);
path[path_len] = '\0';
}
break;
case UNIX_DIAG_PEER:
if (RTA_PAYLOAD(attr) >= sizeof(peer))
peer = *(unsigned int *) RTA_DATA(attr);
break;
}
}
printf("inode=%u", diag->udiag_ino);
if (peer)
printf(", peer=%u", peer);
if (path_len)
printf(", name=%s%s", *path ? "" : "@",
*path ? path : path + 1);
putchar('\n');
return 0; } static int receive_responses(int fd) {
long buf[8192 / sizeof(long)];
struct sockaddr_nl nladdr;
struct iovec iov = {
.iov_base = buf,
.iov_len = sizeof(buf)
};
int flags = 0;
for (;;) {
struct msghdr msg = {
.msg_name = &nladdr,
.msg_namelen = sizeof(nladdr),
.msg_iov = &iov,
.msg_iovlen = 1
};
ssize_t ret = recvmsg(fd, &msg, flags);
if (ret < 0) {
if (errno == EINTR)
continue;
perror("recvmsg");
return -1;
}
if (ret == 0)
return 0;
if (nladdr.nl_family != AF_NETLINK) {
fputs("!AF_NETLINK\n", stderr);
return -1;
}
const struct nlmsghdr *h = (struct nlmsghdr *) buf;
if (!NLMSG_OK(h, ret)) {
fputs("!NLMSG_OK\n", stderr);
return -1;
}
for (; NLMSG_OK(h, ret); h = NLMSG_NEXT(h, ret)) {
if (h->nlmsg_type == NLMSG_DONE)
return 0;
if (h->nlmsg_type == NLMSG_ERROR) {
const struct nlmsgerr *err = NLMSG_DATA(h);
if (h->nlmsg_len < NLMSG_LENGTH(sizeof(*err))) {
fputs("NLMSG_ERROR\n", stderr);
} else {
errno = -err->error;
perror("NLMSG_ERROR");
}
return -1;
}
if (h->nlmsg_type != SOCK_DIAG_BY_FAMILY) {
fprintf(stderr, "unexpected nlmsg_type %u\n",
(unsigned) h->nlmsg_type);
return -1;
}
if (print_diag(NLMSG_DATA(h), h->nlmsg_len))
return -1;
}
} } int main(void) {
int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_SOCK_DIAG);
if (fd < 0) {
perror("socket");
return 1;
}
int ret = send_query(fd) || receive_responses(fd);
close(fd);
return ret; }

انظر أيضًا

netlink(3)، rtnetlink(3)، netlink(7)، tcp(7)

ترجمة

تُرجمت هذه الصفحة من الدليل بواسطة زايد السعيدي <zayed.alsaidi@gmail.com>

هذه الترجمة هي وثيقة مجانية؛ راجع رخصة جنو العامة الإصدار 3 أو ما بعده للاطلاع على شروط حقوق النشر. لا توجد أي ضمانات.

إذا وجدت أي أخطاء في ترجمة صفحة الدليل هذه، يرجى إرسال بريد إلكتروني إلى قائمة بريد المترجمين: kde-l10n-ar@kde.org.

8 فبراير 2026 صفحات دليل لينكس (لم تصدر بعد)