Pregunta

Para un proyecto, estoy tratando de enviar paquetes UDP desde el kernel-space de Linux. Actualmente estoy 'codificando' mi código en el kernel (lo cual agradezco que no sea la mejor / mejor manera) pero estoy tratando de hacer que funcione una prueba simple (enviando '' PRUEBA ''). Cabe mencionar que soy un novato en el hackeo de kernel. ¡No estoy tan al tanto de muchos principios y técnicas!

Cada vez que se ejecuta mi código, el sistema se cuelga y tengo que reiniciar; no hay respuesta del mouse / teclado y las luces de las teclas de desplazamiento y bloqueo de mayúsculas parpadean juntas. No estoy seguro de lo que esto significa, pero supongo que es un kernel panic?

El código repeat_send es innecesario para este código de prueba, sin embargo, cuando funciona, quiero enviar mensajes grandes que pueden requerir múltiples 'envíos'. ¿No estoy seguro de si podría ser la causa de mis problemas?

N.B. Este código se está insertando en neighbour.c de linux-source / net / core / origin, de ahí el uso de NEIGH_PRINTK1, es solo un macro wrapper round printk.

Realmente estoy golpeando mi cabeza contra una pared de ladrillos aquí, no puedo ver nada obvio, ¿alguien puede señalarme en la dirección correcta (o detectar ese error cegadoramente obvio!)?

Esto es lo que tengo hasta ahora:

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);
}

Cualquier ayuda sería muy apreciada, ¡gracias!

¿Fue útil?

Solución

Puede que le resulte más fácil utilizar la netpoll API para UDP. Eche un vistazo a netconsole para ver un ejemplo de cómo es usado. Las API que está utilizando están más destinadas al espacio de usuario (¡nunca debería tener que jugar con descriptores de segmento para enviar datos de red!)

Otros consejos

Ejecute su código cuando esté en una consola de modo de texto (es decir, presione Ctrl + Alt + F1 para ir a la consola de texto). De esta manera, el kernel panic imprimirá el seguimiento de la pila y cualquier información adicional sobre lo que salió mal.

Si eso no lo ayuda, actualice su pregunta con el seguimiento de la pila.

No soy un gran desarrollador de Linux Kernel, pero ¿puedes tirar algunos printk y ver dmesg antes de que se caiga? ¿O ha pensado en conectarse con un depurador de kernel?

Creo que debería intentar poner todas las variables fuera de la función mymethod () y hacerlas estáticas. Recuerde, que el tamaño de la pila del kernel es limitado a 8 KB, por lo que una gran cantidad de variables locales demasiado grandes puede causar un desbordamiento de la pila y el bloqueo del sistema.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top