Domanda

Per un progetto, sto cercando di inviare pacchetti UDP dallo spazio kernel Linux. Attualmente sto "codificando" il mio codice nel kernel (che apprezzo non è il modo migliore / più accurato) ma sto cercando di far funzionare un semplice test (invio di "TEST"). Dovrebbe essere menzionato che sono un principiante dell'hacking del kernel - non sono così informato su molti principi e tecniche!

Ogni volta che il mio codice viene eseguito il sistema si blocca e devo riavviare - nessuna risposta da mouse / tastiera e le spie dei tasti di scorrimento e blocco maiuscole lampeggiano insieme - Non sono sicuro di cosa significhi, ma suppongo sia un panico del kernel?

Il codice repeat_send non è necessario per questo codice di prova, ma quando funziona voglio inviare messaggi di grandi dimensioni che potrebbero richiedere più "invii - non sono sicuro che se potrebbe essere una causa dei miei problemi?

NB. Questo codice viene inserito in neighbour.c di linux-source / net / core / origin, quindi l'uso di NEIGH_PRINTK1, è solo un macro wrapper attorno a printk.

Sto davvero sbattendo la testa contro un muro di mattoni qui, non riesco a individuare nulla di ovvio, qualcuno può indicarmi la giusta direzione (o individuare quell'errore accecantemente ovvio!)?

Ecco quello che ho finora:

void mymethod()
{
    struct socket sock;
    struct sockaddr_in addr_in;
    int ret_val;
    unsigned short port = htons(2048);
    unsigned int host = in_aton("192.168.1.254");
    unsigned int length = 5;
    char *buf = "TEST\0";
    struct msghdr msg;
    struct iovec iov;
    int len = 0, written = 0, left = length;
    mm_segment_t oldmm;

    NEIGH_PRINTK1("forwarding sk_buff at: %p.\n", skb);

    if ((ret_val = sock_create(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock)) < 0) {
        NEIGH_PRINTK1("Error during creation of socket; terminating. code: %d\n", ret_val);
        return;
    }

    memset(&addr_in, 0, sizeof(struct sockaddr_in));
    addr_in.sin_family=AF_INET;
    addr_in.sin_port = port;
    addr_in.sin_addr.s_addr = host;

    if((ret_val = sock.ops->bind(&sock, (struct sockaddr *)&addr_in, sizeof(struct sockaddr_in))) < 0) {
    NEIGH_PRINTK1("Error trying to bind socket. code: %d\n", ret_val);
    goto close;
    }

    memset(&msg, 0, sizeof(struct msghdr));
    msg.msg_flags = 0;
    msg.msg_name = &addr_in;
    msg.msg_namelen = sizeof(struct sockaddr_in);
    msg.msg_iov = &iov;
    msg.msg_iovlen = 1;
    msg.msg_control = NULL;
    msg.msg_controllen = 0;

repeat_send:
    msg.msg_iov->iov_len = left;
    msg.msg_iov->iov_base = (char *)buf + written;

    oldmm = get_fs(); 
    set_fs(KERNEL_DS);
    len = sock_sendmsg(&sock, &msg, left);
    set_fs(oldmm);

    if (len == -ERESTARTSYS)
        goto repeat_send;
    if (len > 0) {
        written += len;
        left -= len;
        if (left)
            goto repeat_send;
    }

close:
    sock_release(&sock);
}

Qualsiasi aiuto sarebbe molto apprezzato, grazie!

È stato utile?

Soluzione

Potresti trovare più facile usare API netpoll per UDP. Dai un'occhiata a netconsole per un esempio di come è usato. Le API che stai utilizzando sono più destinate allo spazio utenti (non devi mai giocare con i descrittori di segmenti per inviare dati di rete!)

Altri suggerimenti

Esegui il codice quando sei in una console in modalità testo (ovvero premi Ctrl + Alt + F1 per accedere alla console di testo). In questo modo un panico del kernel stamperà la traccia dello stack e qualsiasi ulteriore informazione su cosa è andato storto.

Se ciò non ti aiuta, aggiorna la tua domanda con la traccia dello stack.

Non sono uno sviluppatore del kernel Linux, ma puoi buttarci dentro alcuni printk e guardare dmesg prima che vada giù? O hai pensato di collegarti con un debugger del kernel?

Penso che dovresti provare a mettere tutte le variabili fuori dalla funzione mymethod () e renderle statiche. Ricorda che le dimensioni dello stack del kernel sono limitate a 8 KiB, quindi a gran parte delle variabili locali troppo grandi possono causare overflow dello stack e blocco del sistema.

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