netlink(7)

الاسم
نتلينك - اتصال بين النواة وفضاء المستخدم (AF_NETLINK)

موجز
#include <asm/types.h>
#include <sys/socket.h>
#include <linux/netlink.h>

netlink_socket = socket(AF_NETLINK, socket_type, netlink_family);

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

نتلينك هي خدمة موجهة للبيانات. كلا من SOCK_RAW و SOCK_DGRAM قيمتان صالحتان لـ socket_type. ومع ذلك، لا يميز بروتوكول نتلينك بين مقابس البيانات والمقابس الخام.

يختار netlink_family وحدة النواة أو مجموعة نتلينك للتواصل معها. عائلات نتلينك المعينة حاليًا هي:

NETLINK_ROUTE
    تستقبل تحديثات التوجيه والارتباط ويمكن استخدامها لتعديل جداول التوجيه (IPv4 و IPv6)، وعناوين IP، ومعلمات الارتباط، وإعدادات الجيران، وتخصصات الطابور، وفئات المرور، ومصنفات الحزم (انظر rtnetlink(7)).

NETLINK_W1 (لينكس 2.6.13 إلى لينكس 2.16.17)
    رسائل من النظام الفرعي للسلك الواحد.

NETLINK_USERSOCK
    محجوزة لبروتوكولات مقابس وضع المستخدم.

NETLINK_FIREWALL (حتى لينكس 3.4 شاملاً)
    تنقل حزم IPv4 من netfilter إلى فضاء المستخدم. تُستخدم بواسطة وحدة النواة ip_queue. بعد فترة طويلة من الإعلان عن تقادمها (لصالح الميزة الأكثر تقدمًا nfnetlink_queue)، أُزيلت NETLINK_FIREWALL في لينكس 3.5.

NETLINK_SOCK_DIAG (منذ لينكس 3.3)
    استعلام عن معلومات حول مقابس عائلات بروتوكولات مختلفة من النواة (انظر sock_diag(7)).

NETLINK_INET_DIAG (منذ لينكس 2.6.14)
    مرادف قديم لـ NETLINK_SOCK_DIAG.

NETLINK_NFLOG (حتى لينكس 3.16 شاملاً)
    ULOG لـ Netfilter/iptables.

NETLINK_XFRM
    IPsec.

NETLINK_SELINUX (منذ لينكس 2.6.4)
    إشعارات أحداث SELinux.

NETLINK_ISCSI (منذ لينكس 2.6.15)
    Open-iSCSI.

NETLINK_AUDIT (منذ لينكس 2.6.6)
    التدقيق.

NETLINK_FIB_LOOKUP (منذ لينكس 2.6.13)
    الوصول إلى بحث FIB من مساحة المستخدم.

NETLINK_CONNECTOR (منذ لينكس 2.6.14)
    موصل النواة. انظر Documentation/driver-api/connector.rst (أو /Documentation/connector/connector.* في لينكس 5.2 والإصدارات الأقدم) في شجرة مصدر نواة لينكس لمزيد من المعلومات.

NETLINK_NETFILTER (منذ لينكس 2.6.14)
    النظام الفرعي Netfilter.

NETLINK_SCSITRANSPORT (منذ لينكس 2.6.19)
    نقلات SCSI.

NETLINK_RDMA (منذ لينكس 3.0)
    RDMA إنفينيباند.

NETLINK_IP6_FW (حتى لينكس 3.4 وما يشمل)
    نقل حزم IPv6 من netfilter إلى مساحة المستخدم. يُستخدم بواسطة وحدة النواة ip6_queue.

NETLINK_DNRTMSG
    رسائل توجيه DECnet.

NETLINK_KOBJECT_UEVENT (منذ لينكس 2.6.10)
    رسائل النواة إلى مساحة المستخدم.

NETLINK_GENERIC (منذ لينكس 2.6.15)
    عائلة netlink عامة لاستخدام netlink مبسط.

NETLINK_CRYPTO (منذ لينكس 3.2)
    واجهة netlink لطلب معلومات حول الشفرات المسجلة مع واجهة برمجة تطبيقات التشفير للنواة وكذلك السماح بتكوين واجهة برمجة تطبيقات التشفير للنواة.

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

في الرسائل متعددة الأجزاء (رؤوس nlmsghdr متعددة مع حمولة مرتبطة في تيار بايت واحد) يتم تعيين علامة NLM_F_MULTI للرأس الأول وجميع الرؤوس التالية، باستثناء الرأس الأخير الذي له النوع NLMSG_DONE.

بعد كل nlmsghdr تتبع الحمولة.

    struct nlmsghdr {
        __u32 nlmsg_len;    /* Size of message including header */
        __u16 nlmsg_type;   /* Type of message content */
        __u16 nlmsg_flags;  /* Additional flags */
        __u32 nlmsg_seq;    /* Sequence number */
        __u32 nlmsg_pid;    /* Sender port ID */
    };

يمكن أن يكون nlmsg_type أحد أنواع الرسائل القياسية: رسالة NLMSG_NOOP يجب تجاهلها، رسالة NLMSG_ERROR تشير إلى خطأ وتحتوي الحمولة على بنية nlmsgerr، رسالة NLMSG_DONE تنهي رسالة متعددة الأجزاء. تُلحق رسائل الخطأ بالطلب الأصلي، ما لم يطلب المستخدم تقييد رسالة الخطأ، وتُحصل على بيانات خطأ إضافية إذا طُلب ذلك.

    struct nlmsgerr {
        int error;        /* Negative errno or 0 for acknowledgements */
        struct nlmsghdr msg;  /* Message header that caused the error */
        /*
         * followed by the message contents
         * unless NETLINK_CAP_ACK was set
         * or the ACK indicates success (error == 0).
         * For example Generic Netlink message with attributes.
         * message size is aligned with NLMSG_ALIGN()
         */
        /*
         * followed by TLVs defined in enum nlmsgerr_attrs
         * if NETLINK_EXT_ACK was set
         */
    };

عادةً ما تحدد عائلة netlink أنواع رسائل إضافية، راجع صفحات الدليل المناسبة لذلك، على سبيل المثال، rtnetlink(7) لـ NETLINK_ROUTE.
بتات الأعلام القياسية في nlmsg_flags
NLM_F_REQUEST | يجب تعيينه على جميع رسائل الطلب.
NLM_F_MULTI | هذه الرسالة جزء من رسالة متعددة الأجزاء تنتهي بـ NLMSG_DONE.
NLM_F_ACK | طلب إقرار عند النجاح.
NLM_F_ECHO | صدى هذا الطلب.
بتات أعلام إضافية لطلبات GET
NLM_F_ROOT | إرجاع الجدول الكامل بدلاً من إدخال واحد.
NLM_F_MATCH | يُرجع جميع الإدخالات التي تتطابق مع المعايير المُرسلة في محتوى الرسالة. لم تنفذ بعد.
NLM_F_ATOMIC | إرجاع لقطة ذرية للجدول.
NLM_F_DUMP | ماكرو اختصار؛ يعادل (NLM_F_ROOT|NLM_F_MATCH).

لاحظ أن NLM_F_ATOMIC يتطلب صلاحية CAP_NET_ADMIN أو UID فعال بقيمة 0.
بتات أعلام إضافية لطلبات NEW
NLM_F_REPLACE | استبدال الكائن المطابق الموجود.
NLM_F_EXCL | لا تستبدل إذا كان الكائن موجودًا مسبقًا.
NLM_F_CREATE | إنشاء الكائن إذا لم يكن موجودًا مسبقًا.
NLM_F_APPEND | إضافة إلى نهاية قائمة الكائنات.

يُستخدم nlmsg_seq وnlmsg_pid لتتبع الرسائل. يُظهر nlmsg_pid أصل الرسالة. لاحظ عدم وجود علاقة 1:1 بين nlmsg_pid ومعرف العملية (PID) إذا نشأت الرسالة من مقبس netlink. راجع قسم ADDRESS FORMATS لمزيد من المعلومات.

كلا nlmsg_seq وnlmsg_pid غير شفافين لنواة netlink.

Netlink ليس بروتوكولًا موثوقًا. يبذل قصارى جهده لتوصيل رسالة إلى وجهتها (وجهاتها)، لكنه قد يُسقط الرسائل عند حدوث حالة نفاد الذاكرة أو خطأ آخر. للنقل الموثوق، يمكن للمُرسِل طلب إقرار من المُستقبِل بتعيين العلم NLM_F_ACK. الإقرار هو حزمة NLMSG_ERROR مع تعيين حقل الخطأ إلى 0. يجب على التطبيق توليد إقرارات للرسائل المستلمة بنفسه. تحاول النواة إرسال رسالة NLMSG_ERROR لكل حزمة فاشلة. يجب على عملية المستخدم اتباع هذا الاصطلاح أيضًا.

ومع ذلك، فإن الإرسالات الموثوقة من النواة إلى المستخدم مستحيلة في أي حال. لا تستطيع النواة إرسال رسالة netlink إذا كان مخزن المقبس ممتلئًا: سيتم إسقاط الرسالة ولن يكون للنواة وعملية مساحة المستخدم نفس الرؤية لحالة النواة. يقع على عاتق التطبيق اكتشاف متى يحدث هذا (عبر خطأ ENOBUFS الذي يُرجعه recvmsg(2)) وإعادة المزامنة.

  تنسيقات العناوين
تصف بنية sockaddr_nl عميل netlink في مساحة المستخدم أو في النواة. يمكن أن يكون sockaddr_nl إما أحادي الإرسال (يُرسل إلى نظير واحد فقط) أو يُرسل إلى مجموعات الإرسال المتعدد netlink (nl_groups لا يساوي 0).

    struct sockaddr_nl {
        sa_family_t     nl_family;  /* AF_NETLINK */
        unsigned short  nl_pad;     /* Zero */
        pid_t           nl_pid;     /* Port ID */
        __u32           nl_groups;  /* Multicast groups mask */
    };

nl_pid هو عنوان أحادي الإرسال لمقبس netlink. يكون دائمًا 0 إذا كانت الوجهة في النواة. بالنسبة لعملية مساحة المستخدم، nl_pid عادةً ما يكون معرف العملية (PID) للعملية التي تملك مقبس الوجهة. ومع ذلك، يُحدد nl_pid مقبس netlink، وليس عملية. إذا امتلكت عملية عدة مقابس netlink، فإن nl_pid يمكن أن يساوي معرف العملية فقط لمقبس واحد على الأكثر. هناك طريقتان لتعيين nl_pid لمقبس netlink. إذا عيّن التطبيق nl_pid قبل استدعاء bind(2)، فإنه يقع على عاتق التطبيق التأكد من أن nl_pid فريد. إذا عيّنه التطبيق إلى 0، تتولى النواة تعيينه. تُسند النواة معرف العملية إلى أول مقبس netlink تفتحه العملية وتُسند nl_pid فريدًا لكل مقبس netlink تنشئه العملية لاحقًا.

nl_groups هو قناع بتات حيث يمثل كل بت رقم مجموعة netlink. لكل عائلة netlink مجموعة من 32 مجموعة إرسال متعدد. عند استدعاء bind(2) على المقبس، يجب تعيين حقل nl_groups في sockaddr_nl إلى قناع بتات للمجموعات التي ترغب في الاستماع إليها. القيمة المبدئية لهذا الحقل هي صفر مما يعني عدم استقبال أي إرسال متعدد. يمكن لمقبس إرسال رسائل متعددة إلى أي من مجموعات الإرسال المتعدد بتعيين nl_groups إلى قناع بتات للمجموعات التي يرغب في الإرسال إليها عند استدعاء sendmsg(2) أو تنفيذ connect(2). فقط العمليات التي لديها UID فعال 0 أو صلاحية CAP_NET_ADMIN يمكنها الإرسال أو الاستماع إلى مجموعة إرسال متعدد netlink. منذ Linux 2.6.13، لا يمكن بث الرسائل إلى مجموعات متعددة. يجب إرسال أي ردود على رسالة مستلمة لمجموعة إرسال متعدد مرة أخرى إلى PID المُرسِل ومجموعة الإرسال المتعدد. قد تسمح بعض أنظمة النواة الفرعية Linux بالإضافة إلى ذلك لمستخدمين آخرين بالإرسال و/أو الاستقبال. اعتبارًا من Linux 3.0، تسمح المجموعات NETLINK_KOBJECT_UEVENT وNETLINK_GENERIC وNETLINK_ROUTE وNETLINK_SELINUX لمستخدمين آخرين باستقبال الرسائل. لا تسمح أي مجموعات لمستخدمين آخرين بإرسال الرسائل.

  خيارات المقبس
لتعيين أو الحصول على خيار مقبس netlink، استدع getsockopt(2) للقراءة أو setsockopt(2) للكتابة مع تعيين وسيطة مستوى الخيار إلى SOL_NETLINK. ما لم يُذكر خلاف ذلك، optval هو مؤشر إلى int.

NETLINK_PKTINFO (منذ Linux 2.6.14)
    تمكين رسائل التحكم nl_pktinfo للحزم المستلمة للحصول على رقم مجموعة الوجهة الموسعة.

NETLINK_ADD_MEMBERSHIP
NETLINK_DROP_MEMBERSHIP (منذ Linux 2.6.14)
    الانضمام/المغادرة من مجموعة محددة بواسطة optval.

NETLINK_LIST_MEMBERSHIPS (منذ Linux 4.2)
    استرداد جميع المجموعات التي يكون المقبس عضوًا فيها. optval هو مؤشر إلى __u32 وoptlen هو حجم المصفوفة. تُملأ المصفوفة بمجموعة العضوية الكاملة للمقبس، ويُعاد حجم المصفوفة المطلوب في optlen.

NETLINK_BROADCAST_ERROR (منذ Linux 2.6.30)
    عند عدم التعيين، يُبلغ netlink_broadcast() عن أخطاء ESRCH فقط ويتجاهل بصمت أخطاء ENOBUFS.

NETLINK_NO_ENOBUFS (منذ لينكس 2.6.30)
    يمكن استخدام هذه العلامة بواسطة مستمعي الإرسال الأحادي والبث لتجنب استقبال أخطاء ENOBUFS.

NETLINK_LISTEN_ALL_NSID (منذ لينكس 4.2)
    عند التعيين، سيستقبل هذا المقبس إشعارات netlink من جميع مساحات أسماء الشبكة التي لديها nsid معين في مساحة اسم الشبكة حيث فُتح المقبس. يُرسل nsid إلى مساحة المستخدم عبر بيانات مساعدة.

NETLINK_CAP_ACK (منذ لينكس 4.3)
    قد يفشل النواة في تخصيص المساحة اللازمة لرسالة الإقرار العائدة إلى مساحة المستخدم. يقلص هذا الخيار حمولة رسالة netlink الأصلية. لا يزال رأس رسالة netlink مضمنًا، لذا يمكن للمستخدم تخمين من رقم التسلسل أي رسالة أثارت الإقرار.

الإصدارات
ظهرت واجهة المقبس لـ netlink لأول مرة في لينكس 2.2.

دعم لينكس 2.0 واجهة netlink بدائية قائمة على الجهاز (والتي لا تزال متاحة كخيار توافق). لا تُوصف هذه الواجهة القديمة هنا.

ملاحظات
غالبًا ما يكون استخدام netlink عبر libnetlink أو libnl أفضل من استخدام واجهة النواة منخفضة المستوى.

العلل
صفحة الدليل هذه غير كاملة.

أمثلة
المثال التالي ينشئ مقبس netlink من نوع NETLINK_ROUTE سيستمع إلى مجموعات البث المتعدد RTMGRP_LINK (أحداث إنشاء/حذف/تشغيل/إيقاف واجهة الشبكة) وRTMGRP_IPV4_IFADDR (أحداث إضافة/حذف عناوين IPv4).

    struct sockaddr_nl sa;

    memset(&sa, 0, sizeof(sa));
    sa.nl_family = AF_NETLINK;
    sa.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR;

    fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
    bind(fd, (struct sockaddr *) &sa, sizeof(sa));

المثال التالي يوضح كيفية إرسال رسالة netlink إلى النواة (pid 0). لاحظ أن التطبيق يجب أن يعتني بأرقام تسلسل الرسائل لتتبع الإقرارات بشكل موثوق.

    struct nlmsghdr *nh;    /* The nlmsghdr with payload to send */
    struct sockaddr_nl sa;
    struct iovec iov = { nh, nh->nlmsg_len };
    struct msghdr msg;

    msg = { &sa, sizeof(sa), &iov, 1, NULL, 0, 0 };
    memset(&sa, 0, sizeof(sa));
    sa.nl_family = AF_NETLINK;
    nh->nlmsg_pid = 0;
    nh->nlmsg_seq = ++sequence_number;
    /* Request an ack from kernel by setting NLM_F_ACK */
    nh->nlmsg_flags |= NLM_F_ACK;

    sendmsg(fd, &msg, 0);

والمثال الأخير يتعلق بقراءة رسالة netlink.

    int size;
    /* 8192 to avoid message truncation on platforms with
       page size > 4096 */
    struct nlmsghdr buf[8192/sizeof(struct nlmsghdr)];
    struct iovec iov = { buf, sizeof(buf) };
    struct sockaddr_nl sa;
    struct msghdr msg;
    struct nlmsghdr *nh;

    msg = { &sa, sizeof(sa), &iov, 1, NULL, 0, 0 };
    size = recvmsg(fd, &msg, 0);

    for (nh = (struct nlmsghdr *) buf; NLMSG_OK (nh, size);
         nh = NLMSG_NEXT (nh, size)) {
        /* The end of multipart message */
        if (nh->nlmsg_type == NLMSG_DONE)
            return;

        if (nh->nlmsg_type == NLMSG_ERROR)
            /* Do some error handling */
        ...

        /* Continue with parsing payload */
        ...
    }

انظر أيضًا
cmsg(3), netlink(3), capabilities(7), rtnetlink(7), sock_diag(7)

معلومات حول libnetlink (ftp://ftp.inr.ac.ru/ip-routing/iproute2*)

معلومات حول libnl (http://www.infradead.org/~tgr/libnl/)

RFC 3549 "Linux Netlink as an IP Services Protocol"

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

هذه الترجمة هي وثيقة مجانية؛ راجع رخصة جنو العامة الإصدار 3 (https://www.gnu.org/licenses/gpl-3.0.html) أو ما بعده للاطلاع على شروط حقوق النشر. لا توجد أي ضمانات.

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