Home Corsi Programmazione Linux Parlare con il kernel: i Linux Netlink

In evidenza

SMAU a Bologna con Research to Business

SMAU a Bologna con Research to Business

Il 6 e 7 giugno il Roadshow Smau Business torna a far tappa al Padiglione 33 della Fiera di Bologna e...
Gli articolisti del Portale

Gli articolisti del Portale

Abbiamo deciso di dare più visibilità a tutti coloro che hanno pubblicato articoli per noi, questo perché...
SMAU festeggia il suo quinto anno nel NordEst a Padova

SMAU festeggia il suo quinto anno nel NordEst a Padova

Il 18 e 19 aprile al padiglione 5 di Padova Fiere si terrà la prossima tappa di SMAU Business Roadshow. All'evento...
SMAU risale l’Italia e arriva a Roma

SMAU risale l’Italia e arriva a Roma

Il 21 e 22 marzo nella Nuova Fiera di Roma si terrà la prossima tappa di SMAU Business Roadshow. L'evento...

Bandi di Concorso

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

Esperto di servizi e tecnologie cloud al Digit PA

Procedura comparativa per il conferimento di un incarico di collaborazione coordinata e continuativa per un profilo senior di “Esperto di servizi e tecnologie cloud”, nell’ambito del progetto europeo “Open Dai” presso l' Ente nazionale per la digitalizzazione della Pubblica Amministrazione...

18 Apr 2012 - Letture:34

Selezione per addetto servizi informatici all'Autorità Portuale di Brindisi

Avviso di selezione pubblica per titoli e prova orale per l’assunzione di n. 1 “addetto ai servizi informatici”, a tempo pieno ed determinato triennale, previo periodo di prova, da inquadrare nell’Area Amministrativa. (Inquadramento al III Livello del C.C.N.L. dei Lavoratori...

12 Feb 2012 - Letture:435

Concorso pubblico per informatico alla Corte dei Conti

E' indetto un concorso pubblico, per   esami,   per   il reclutamento di tre unità di informatici da inquadrare nella III area, fascia retributiva F1, da destinare agli Uffici della Corte dei Conti con sede in Roma. Requisiti: laurea triennale in scienze e...

05 Feb 2012 - Letture:306

Istruttore informatico L.68/1999 al Comune di Potenza

Concorso pubblico, per esami, per la copertura di n. 2 posti di Istruttore Informatico, categoria C, posizione economica C1, a tempo pieno e indeterminato, con riserva assoluta alle categorie dilavoratori di cui all'art. 1 della legge n. 68/1999 (norme per...

21 Gen 2012 - Letture:244

Senior Business Consultant presso Lombardia Informatica

Selezione per figura Senior Business Consultant presso Lombardia Informatica. Il collaboratore dovrà fornire consulenza strategica e di business sulle tematiche verticali della Socio-Sanità. Requisiti di ammissione: Laurea in Ingegneria, Economia e Commercio o Scienze dell’Informazione; Percorsi di formazione professionale in ambito sanitario e socio-sanitario, su...

11 Gen 2012 - Letture:284

Bando progetto TAG (Toscana Area Giovani) per giovani talenti digitali

UPI Toscana ha indetto un avviso pubblico per la selezione di 20 giovani (2 per ciascuna delle 10 province della Toscana), da impiegare come formatori all'interno del Progetto TAG (Toscana Area Giovani). Il bando è finalizzato a valorizzare al meglio i...

03 Gen 2012 - Letture:271

Avviso pubblico per giovani dottori di ricerca per Uffici di Gabinetto

Avviso pubblico per il conferimento di n. 6 incarichi presso gli Uffici di diretta collaborazione del Ministro dell'istruzione dell'università e della ricerca, per soggetti estranei alla pubblica amministrazione. Ambiti di esperienza e Aree di competenza: Nuovi Media: nuove forma di comunicazione tra...

02 Gen 2012 - Letture:217

I più attivi

Dati e punteggi dell'ultimo anno

Giovanna Casamassima Giovanna Casamassima
46 articoli
15,989 punti totali
Rodolfo Giometti Rodolfo Giometti
49 articoli
5,061 punti totali
Vittorio D'Aversa Vittorio D'Aversa
33 articoli
3,425 punti totali
Fabio Bronzini Fabio Bronzini
9 articoli
0,318 punti totali
Fulvio Lucchetti Fulvio Lucchetti
9 articoli
0,275 punti totali

Ci hanno visitato

Oggi:1450
Ieri:2498
Totali (14/04/09):1162297

I nostri numeri

Articoli pubblicati: 552
Iscritti al portale: 766
Iscritti all'Elenco: 184
Iscritti ML Discussioni: 351
Iscritti ML Articoli: 30
Iscritti ML Lavoro: 166
 
Parlare con il kernel: i Linux Netlink Stampa E-mail
(0 voti, media 0 di 5)
Area Corsi - Programmazione Linux
Scritto da Rodolfo Giometti   
Giovedì 22 Luglio 2010 08:02
Articolo letto 1340 volte

Ogni qual volta ci sia la necessità di scambiare dati tra il kernel e lo spazio utente si può pensare di definire una chiamata di sistema ad hoc, questo però genera non poche difficoltà poiché le chiamate di sistema dovrebbero assolvere a compiti molto generali (si pensi ad esempio alla read() o alla write()) e non dovrebbero servire per soddisfare compiti specifici.

Una soluzione a questo problema viene proposta dall'RFC3549 introducendo i «Linux Netlink as an IP Services Protocol».

Cosa sono

I netlink sono dei particolari tipi di socket che permettono di scambiare dati tra applicazioni e il kernel, ad esempio possono servire per scambiare dati tra un processo e il sottosistema di networking di Linux per controllarne lo stato ed impostarne certi parametri di funzionamento.

I netlink possono però anche essere usati per scambiare dati tra processi.

Col passare del tempo i netlink sono diventati molto popolari all'interno di Linux e ne sono nate diverse tipologie (o famiglie), ognuna delle quali per assolvere ad un ben determinato scopo. Questo ha fatto ha causato la nascita di un gran numero di tipi diversi di socket netlink all'interno del kernel il che (intorno al kernel 2.6.19) ha portato alla definizione di una famiglia generica (generic netlink) per assolvere a tutti quei compiti particolari e di poco interesse generale.

Una applicazione che fa largo uso dei netlink per comunicare con il kernel è iproute2. In questo articolo ci soffermeremo sull'uso dei socket AF_NETLINK per comunicare con il kernel e per gestire/monitorare il sottosistema di rete.

Come si usano

Utilizzare i netlink è abbastanza facile, basta aprire un socket nel domain AF_NETLINK e quindi specificare a quale famiglia siamo interessati. Le pagine di man di socket() dicono:

NAME
socket - create an endpoint for communication

SYNOPSIS
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>

int socket(int domain, int type, int protocol);

DESCRIPTION
socket()  creates  an endpoint for communication and returns a descrip-
tor.

The domain argument specifies a communication domain; this selects  the
protocol  family  which will be used for communication.  These families
are  defined  in  <sys/socket.h>.   The  currently  understood  formats
include:

Name                Purpose                          Man page
AF_UNIX, AF_LOCAL   Local communication              unix(7)
AF_INET             IPv4 Internet protocols          ip(7)
AF_INET6            IPv6 Internet protocols          ipv6(7)
AF_IPX              IPX - Novell protocols
AF_NETLINK          Kernel user interface device     netlink(7)
AF_X25              ITU-T X.25 / ISO-8208 protocol   x25(7)
AF_AX25             Amateur radio AX.25 protocol
AF_ATMPVC           Access to raw ATM PVCs
AF_APPLETALK        Appletalk                        ddp(7)
AF_PACKET           Low level packet interface       packet(7)

Quindi dalle pagine di netlink(7) si legge:

NAME
netlink - Communication between kernel and userspace (AF_NETLINK)

SYNOPSIS
#include <asm/types.h>
#include <sys/socket.h>
#include <linux/netlink.h>

netlink_socket = socket(AF_NETLINK, socket_type, netlink_family);

DESCRIPTION
Netlink  is  used  to transfer information between kernel and userspace
processes.  It consists  of  a  standard  sockets-based  interface  for
userspace processes and an internal kernel API for kernel modules.
  The
internal kernel interface is not documented in this manual page.  There
is  also  an  obsolete netlink interface via netlink character devices;
this interface is not documented here and is only  provided  for  back-
wards compatibility.

Netlink  is  a datagram-oriented service.  Both SOCK_RAW and SOCK_DGRAM
are valid values for socket_type.  However, the netlink  protocol  does
not distinguish between datagram and raw sockets.

netlink_family  selects  the kernel module or netlink group to communi-
cate with.  The currently assigned netlink families are:

NETLINK_ROUTE
Receives routing and link updates and may be used to modify  the
routing  tables (both IPv4 and IPv6), IP addresses, link parame-
ters, neighbor setups, queueing disciplines, traffic classes and
packet classifiers (see rtnetlink(7)).

...

Ad esempio, per aprire un canale dove ottenere tutti gli eventi relativi alla creazione, cancellazione, attivazione e disattivazione di una interfaccia di rete nonché gli eventi relativi alla creazione e cancellazione di indirizzi IP si può fare:

struct sockaddr_nl sa;

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

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

I valori possibili per nl_groups sono riportati nel file linux/include/linux/rtnetlink.h.

A questo punto per inviare un messaggio al kernel ( individuato dal pid 0) si può fare:

struct nlmsghdr *nh;    /* The nlmsghdr with payload to send. */
struct sockaddr_nl sa;
struct iovec iov = {
        (void *) nh,
        nh->nlmsg_len
};
struct msghdr
msg = {
        (void *) &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(sock, &msg, 0);

mentre per la ricezione si ha:

int len;
char buf[4096];
struct iovec iov = { buf, sizeof(buf) };
struct sockaddr_nl sa;

struct nlmsghdr *nh;
struct msghdr msg = {
        (void *) &sa,
        sizeof(sa),
        &iov,
        1, NULL, 0, 0
};

len = recvmsg(sock, &msg, 0);
for (nh = (struct nlmsghdr *) buf; NLMSG_OK(nh, len);
                nh = NLMSG_NEXT (nh, len)) {
        /* 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. */
        ...
}

Ma facciamo un esempio pratico: supponiamo di voler monitorare lo stato degli indirizzi di rete definiiti sulle interfaccie di rete del nostro sistema; sapere quindi, ad esempio, quando ad una interfaccia di rete viene cambiato l'indirizzo IP.

Riprendendo quanto appena detto si ha allora che una possibile soluzione potrebbe essere la seguente:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <asm/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <net/if.h>

int main(int argc, char *argv[])
{
        int sock, len;
        char buf[4096];
        struct iovec iov = {
                buf,
                sizeof(buf)
        };      
        struct sockaddr_nl sa;
        struct msghdr msg = {
                (void *) &sa,
                sizeof(sa),
                &iov,
                1, NULL, 0, 0
        };
        struct nlmsghdr *nlh = (struct nlmsghdr *) buf;
        struct nlmsghdr *nh;
        struct ifaddrmsg *ifa;
        struct rtattr *rth;
        int rtl;
        char name[IFNAMSIZ];
        unsigned int ipaddr;

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

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

        printf("---\n");
        while (1) {
                len = recvmsg(sock, &msg, 0);
                if (len < 0) {
                        perror("recvmsg");
                        exit(EXIT_FAILURE);
                }

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

                        if (nh->nlmsg_type == NLMSG_ERROR) {
                                fprintf(stderr, "netlink error!");
                                break;
                        }

                        printf("new event arrived\n");

                        ifa = (struct ifaddrmsg *) NLMSG_DATA(nlh);
                        rth = IFA_RTA(ifa);
                        rtl = IFA_PAYLOAD(nlh);
                        for ( ;rtl && RTA_OK(rth, rtl);
                                        rth = RTA_NEXT(rth,rtl)) {
                                if (rth->rta_type != IFA_LOCAL)
                                        continue;

                                ipaddr = *((unsigned int *) RTA_DATA(rth));
                                ipaddr = htonl(ipaddr);

                                printf("%s is now %X rta_type: %d\n",
                                        if_indextoname(ifa->ifa_index,name),
                                        ipaddr, rth->rta_type);
                        }
                }
        }

        return 0;
}

Una volta salvato nel file netlink.c, compilato ed eseguito si ha:

$ ./netlink
---

Il processo inizializza il canale di comunicazione come descritto prima e quindi si mette in attesa di dati. Se ora andiamo a modificare l'indirizzo IP di un interfaccia di rete del sistema con i comandi:

# ifconfig wlan0 192.168.1.1
# ifconfig wlan0 192.168.1.2
# ifconfig wlan0 192.168.1.3

dal nostro programma si ottiene:

new event arrived
wlan0 is now C0A80104 rta_type: 2
new event arrived
wlan0 is now C0A80101 rta_type: 2
new event arrived
wlan0 is now C0A80101 rta_type: 2
new event arrived
wlan0 is now C0A80102 rta_type: 2
new event arrived
wlan0 is now C0A80102 rta_type: 2
new event arrived
wlan0 is now C0A80103 rta_type: 2

 


Questa dispensa del corso Programmazione Linux è opera di Rodolfo Giometti (Copyright © 2010) ed è rilasciata dall'autore «as is» (così com'è) e distribuita sotto licenza Creative Commons Attribuzione – Condividi allo stesso modo 2.5 Italia.

 
 

In primo piano

Simons Voss: un mondo senza chiavi

Simons Voss: un mondo senza chiavi

Il sistema di gestione e di controllo degli accessi 3060 si presenta come un’alternativa con enormi vantaggi...
Pubblicità mirata dei prodotti

Pubblicità mirata dei prodotti

Hai un prodotto o un servizio da pubblicizzare? Fallo su consulenti-ict.it! Pubblicizzare un prodotto...
Recensioni sul Portale

Recensioni sul Portale

Hai un prodotto hardware/software o un libro riguardante uno dei temi dell'ICT? Vuoi farlo conoscere...

Offerte di lavoro

Visualizza Topic »

Eventi

Non ci sono eventi in programma
Maggio 2012
D L M M G V S
29 30 1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31 1 2
Giugno 2012
D L M M G V S
27 28 29 30 31 1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30

Sondaggi

busyCaricamento Sondaggio...