Domanda

Voglio usare netlink per comunicare tra un'applicazione e lo spazio del kernel. La mia versione del kernel Linux è 2.6.28 e il codice sbagliato è il seguente:

nf_sock=netlink_kernel_create(NL_PROTO,0,nl_user_skb,THIS_MODULE);

Il messaggio di errore abbreviato è:

error: too few arguments to function 'netlink_kernel_create'

Nel file < linux / netlink.h > , la funzione netlink_kernel_create () è definita come

extern struct sock *netlink_kernel_create(struct net *net,int unit,unsigned int groups,void (*input)(struct sk_buff *skb),struct mutex *cb_mutex,struct module *module)

Non capisco cosa usare per il primo argomento, net . Qualcuno può spiegare cosa dovrei usare qui?

È stato utile?

Soluzione

Una struct net contiene informazioni sullo spazio dei nomi di rete, un insieme di risorse di rete disponibili per i processi. Si noti che potrebbero esserci più spazi dei nomi di rete (ovvero più istanze dello stack di rete), ma la maggior parte dei driver utilizza lo spazio dei nomi init_net.

Probabilmente la tua chiamata dovrebbe essere simile alla seguente

nf_sock = netlink_kernel_create(&init_net,
                                NETLINK_USERSOCK,
                                0,
                                nl_rcv_func,
                                NULL,
                                THIS_MODULE);

dove nl_rcv_func è una funzione che prende struct sk_buff * skb come unico argomento ed elabora il messaggio netlink ricevuto.

Altri suggerimenti

Sembra che stia seguendo una guida come questa , che ( essendo dal 2005) potrebbe essere stato superato dallo sviluppo del kernel. Sembra che l'API interna per creare un netlink dal lato del kernel sia cambiata.

O controlla la cartella Documentation / nel tuo albero del kernel locale per qualche documentazione (si spera più fresca), o leggi il codice stesso. Puoi anche trawl gli archivi della mailing list del kernel Linux per qualsiasi menzione delle modifiche che sembra essere successo.

Qui è l'implementazione effettiva al 2.6.29, se preferisci risolverlo all'indietro (e non l'hai già verificato nel tuo albero, ovviamente).

Sì, struct net è effettivamente per lo spazio dei nomi net, ma non è corretto usare sempre init_net, dovresti registrare le tue operazioni pernet, in questo modo:

static struct pernet_operations fib_net_ops = {
        .init = fib_net_init,
        .exit = fib_net_exit,
};

static int __net_init fib_net_init(struct net *net)
{
        int error;

#ifdef CONFIG_IP_ROUTE_CLASSID
        net->ipv4.fib_num_tclassid_users = 0;
#endif
        error = ip_fib_net_init(net);
        if (error < 0)
                goto out;
        error = nl_fib_lookup_init(net);
        if (error < 0)
                goto out_nlfl;
        error = fib_proc_init(net);
        if (error < 0)
                goto out_proc;
out:
        return error;

out_proc:
        nl_fib_lookup_exit(net);
out_nlfl:
        ip_fib_net_exit(net);
        goto out;
}

static int __net_init nl_fib_lookup_init(struct net *net)
{
        struct sock *sk;
        struct netlink_kernel_cfg cfg = {
                .input  = nl_fib_input,
        };

        sk = netlink_kernel_create(net, NETLINK_FIB_LOOKUP, &cfg);
        if (sk == NULL)
                return -EAFNOSUPPORT;
        net->ipv4.fibnl = sk;
        return 0;
}

e infine:

register_pernet_subsys(&fib_net_ops);

Suggerirei ioctl per la comunicazione kernel / utente. L'interfaccia ioctl è standard e le possibilità di aggiornamento tra i kernel sono ridotte.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top