7

Sto scrivendo il driver di rete ethernet per linux. Voglio ricevere pacchetti, modificarli e inviarli nuovamente. So come modificare il pacchetto nella funzione packet_interceptor, ma come posso eliminare i pacchetti in entrata in questa funzione ??Come filtrare e intercettare i pacchetti Linux usando l'API net_dev_add()?

#include <linux/netdevice.h> 
#include <linux/skbuff.h> 
#include <linux/ip.h> 
#include <net/sock.h> 

struct packet_type my_proto; 

int packet_interceptor(struct sk_buff *skb, 
    struct net_device *dev, 
    struct packet_type *pt, 
    struct net_device *orig_dev) { 

    // I dont want certain packets go to upper in net_devices for further processing. 
    // How can I drop sk_buff here?! 

    return 0; 
} 

static int hello_init(void) { 
    printk(KERN_INFO "Hello, world!\n"); 

    my_proto.type = htons(ETH_P_ALL); 
    my_proto.dev = NULL; 
    my_proto.func = packet_interceptor; 

    dev_add_pack(&my_proto); 
    return 0; 
}  

static void hello_exit(void) { 
    dev_remove_pack(&my_proto); 
    printk(KERN_INFO "Bye, world\n"); 
} 

module_init(hello_init); 
module_exit(hello_exit); 
+0

Hai provato con la mia soluzione? – Atle

+0

Ciao @Atle, ho qualche problema con il mio computer in questi giorni. Grazie per la tua risposta, lo verificherò, non appena posso avviare il mio PC: D. Ma ricordo che non ti ho chiesto, ho provato questa soluzione, ma non ha funzionato. Lo vassoio di nuovo. –

risposta

6

Si sta facendo in modo che il modulo gestisca tutti i pacchetti Ethernet. Linux invierà pacchetti a tutti i gestori di protocollo corrispondenti. Poiché IP è già registrato nel tuo kernel, sia il tuo modulo che ip_rcv riceveranno tutti gli SKB con intestazioni IP.

Non è possibile modificare questo comportamento senza modificare il codice del kernel. Una possibilità è creare invece un modulo netfilter. In questo modo, è possibile intercettare il pacchetto dopo la funzione ip_rcv e rilasciarlo se si desidera (in Netfilters PREROUTING hook).

Ecco un piccolo modulo Netfilter che ho estratto da un codice che avevo già scritto. Questo modulo è incompleto, ma le cose principali sono a posto.

#include <linux/netfilter.h> 
#include <linux/netfilter_ipv4.h> 

// Handler function 
static unsigned int my_handler (
    unsigned int hook, 
    struct sk_buff *skb, 
    const struct net_device *in, 
    const struct net_device *out, 
    int (*okfn)(struct sk_buff *)) 
{ 
    return NF_ACCEPT; 
// or 
    return NF_DROP; 
} 

// Handler registering struct 
static struct nf_hook_ops my_hook __read_mostly = { 
    .hook = my_handler, 
    .pf = NFPROTO_IPV4, 
    .hooknum = (1 << NF_INET_PRE_ROUTING), 
    .priority = NF_IP_PRI_FIRST // My hook will be run before any other netfilter hook 
}; 

int my_init() { 
    int err = nf_register_hook (&my_hook); 
    if (err) { 
      printk (KERN_ERR "Could not register hook\n"); 
    } 
    return err; 
} 
+0

Ho provato il netfilter, funziona molto bene, ma ho bisogno di rilasciare con gli hook 'dev_add_pack()'.la mia domanda è, se il sistema ha due gestori (ip_rcv, my_packet_interceptor), quando cambio lo skb in uno dei miei gestori, quali di questi sono validi? (Presumo che ho cambiato lo skb in my_packet_interceptor così ho due skb, '' L'originale e changed', chi di loro vanno ulteriore elaborazione?) –

+1

I gestori vengono eseguite dopo la vicenda. Direi che l'IP viene eseguito per primo poiché probabilmente è registrato prima del tuo modulo. Non penso che lo SKB sia copiato in questa fase, quindi l'IP verrà probabilmente fatto con esso prima di cambiarlo. – Atle

+0

Quindi, se i gestori vengono eseguiti uno dopo l'altro, Perché non posso rilasciare i pacchetti? –

6

ho passato il Kernel codice di rete (un anno da quando ho fatto nulla all'interno lì), e credo che si dovrebbe fare essere in grado di fare questo senza perdite nulla:

kfree_skb(skb); 
return NET_RX_DROP; 

Modifica

Questo viene eseguito in altri gestori di protocollo come ip_rcv e arp_rcv (l'ultimo restituisce 0 invece di NET_RX_DROP, ma non penso che il valore restituito sia molto importante). Ricorda di non chiamare nessun altro gestore se lasci cadere il skb.

guardare il codice per ip_rcv a ip.c (in basso): http://lxr.free-electrons.com/source/net/ipv4/ip_input.c#L375

Se tutto va bene, passa lo skb a Netfilter che poi chiama ip_rcv_finish (se non cadere). Se qualcosa va storto, libera lo skb e ritorna.

Modifica

Se più di un gestore di protocollo corrisponde a una SKB, il kernel lo invierà a tutti loro. Quando si kfree_skb() in uno dei moduli, lo SKB continuerà a vivere negli altri gestori.

+0

Oggi ho provato, ma non ha funzionato. Qual è il problema con esso? –

+0

Cosa intendi con "non ha funzionato"? Il pacchetto è stato ricevuto dal sistema invece di essere scaricato? I pacchetti entrano persino nel tuo modulo? – Atle

+1

Ricevo tutti i pacchetti nel gestore 'packet_interceptor', ma tutti i pacchetti ricevuti dal sistema. http://paste.ubuntu.com/6324987/ –