/* * www.c * * Módulo que cria um servidor www * Para compreender melhor este módulo é necessário * ter conhecimentos mínimos de sockets.. * * Kernel thread são processos que rodam somente em kernel mode. * kernel_thread e a funcao que cria as kernel threads.. * * Este modulo cria NUM_THREAD kernel thread, que ficam respondendo * pedidos na porta 80, ou qualquer outra, apenas troque o int. * Para terminar as kernel threads vc tem que requisitar a pagina * exit.html, algo como * * lynx http://localhost/exit.html * * PS: Vc tem que fazer esta requisicao para cada uma das kernel threads * que vc criou... * * Para ver as K.T use ps -aux | grep www_server * * 25/03/2002 */ #include <linux/module.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/net.h> #include <linux/types.h> #include <linux/socket.h> #include <net/tcp.h> #include <net/ip.h> #include <linux/inet.h> #include <net/protocol.h> #include <net/sock.h> #include <linux/string.h> #define NUM_THREAD 5 struct socket *MainSocket=NULL; int pid[NUM_THREAD]; int ServerPort = 80; int Accept(void *unused) { struct socket *newsock; int error; struct msghdr msg; struct iovec iov; mm_segment_t oldfs; char *fonte; char buf[2048], *sair = NULL; char header[]= "HTTP/1.1 200 OK\r\nContent-type: text/html\r\n\r\n"; char pagina[] = "<HTML><HEAD><TITLE>SWS</TITLE></HEAD><BODY><H1>Success - Connection Established</BODY></HTML>"; daemonize(); sprintf(current->comm,"www_server"); while(!sair){ newsock = sock_alloc(); if (newsock==NULL) { printk(KERN_ALERT "kernel_thread : Erro durante criacao newsock\n"); return -1; } else printk(KERN_ALERT "kernel_thread : newsock OK\n"); newsock->type = MainSocket->type; newsock->ops = MainSocket->ops; error = MainSocket->ops->accept(MainSocket, newsock, O_RDWR); if (error<0) { printk(KERN_ALERT "kernel_thread : ERRO accept\n"); return -1; } newsock->sk->reuse = 1; if (MainSocket->sk->state != TCP_LISTEN) { printk(KERN_ALERT "kernel_thread : TCP DON´T LISTEN!!!\n"); return -1; } else printk(KERN_ALERT "kernel_thread : TCP LISTEN\n"); fonte = in_ntoa(newsock->sk->daddr); printk(KERN_ALERT "kernel_thread : fonte = %s\n",fonte); printk(KERN_ALERT "kernel_thread : pid = %d\n",current->pid); buf[0] = 0; iov.iov_base = (void *)buf; iov.iov_len = sizeof(buf); msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_control = NULL; msg.msg_controllen = 0; msg.msg_flags = 0; oldfs = get_fs(); set_fs(KERNEL_DS); error = sock_recvmsg(newsock, &msg, sizeof(buf), 0); set_fs(oldfs); /* Se vc quiser ver o que o browser manda pelo socket descomente isto */ //printk(KERN_ALERT "Recebi %s\n",buf); iov.iov_base = (void *)header; iov.iov_len = sizeof(header); msg.msg_iov = &iov; oldfs = get_fs(); set_fs(KERNEL_DS); error = sock_sendmsg(newsock, &msg, sizeof(header)); set_fs(oldfs); if (error<0) printk(KERN_ALERT "ERRO during send = %d\n",error); else printk(KERN_ALERT "Send msg ok\n"); iov.iov_base = (void *)pagina; iov.iov_len = sizeof(pagina); msg.msg_iov = &iov; oldfs = get_fs(); set_fs(KERNEL_DS); error = sock_sendmsg(newsock, &msg, sizeof(pagina)); set_fs(oldfs); if (error<0) printk(KERN_ALERT "ERRO during send = %d\n",error); else printk(KERN_ALERT "Send msg ok\n"); sair = strstr(buf, "/exit.html"); sock_release(newsock); } printk(KERN_ALERT "Kernel_Thread exit\n"); return 0; } int Socket_Create(void) { struct sockaddr_in server; int error; printk(KERN_ALERT "Socket_Create : Hello !!\n"); error = sock_create(PF_INET,SOCK_STREAM,IPPROTO_TCP,&MainSocket); if (error<0) { printk(KERN_ALERT "Socket_Create : Error durante a criacao socket; terminating\n"); return -1; } server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY; server.sin_port = htons((unsigned short)(ServerPort)); MainSocket->sk->reuse = 1; error = MainSocket->ops->bind(MainSocket,(struct sockaddr*)&server,sizeof(server)); if (error<0) { printk(KERN_ALERT "Socket_Create : Error binding socket\n"); return 1; } error = MainSocket->ops->listen(MainSocket,1); if (error!=0) { printk(KERN_ALERT "Socket_Create : Error listening on socket\n"); return -1; } else printk(KERN_ALERT "Socket_Create : Listening Socket OK !\n"); printk(KERN_ALERT "Socket_Create : Server state %d\n",MainSocket->sk->state); return 0; } int www_init_module(void) { int binding, i; printk(KERN_ALERT "Servidor www 1.0\n"); binding = Socket_Create(); if (binding==0) { for (i=0;i<NUM_THREAD;i++) { pid[i] = kernel_thread(Accept, NULL, CLONE_SIGHAND); if (pid[i] < 0) printk(KERN_ALERT "www: ERRO during kernel thread creation = %d\n",i); else printk(KERN_ALERT "www : kernel thread ok pid = %d\n",pid[i]); } } else printk(KERN_ALERT "ERRO www: binding, no threads\n"); return 0; } void www_cleanup_module(void) { sock_release(MainSocket); printk(KERN_ALERT "Servidor www. Bye\n"); } module_init(www_init_module); module_exit(www_cleanup_module); MODULE_DESCRIPTION("Exemplo de kernel thread e sockets"); MODULE_AUTHOR("Thobias Salazar Trevisan"); MODULE_LICENSE("GPL"); EXPORT_NO_SYMBOLS;