Messages in this thread | | | Date | Tue, 24 Dec 2002 08:47:45 +0530 (IST) | From | Prasad <> | Subject | Re: Create and send packet from kernel |
| |
The following is the code i once downloaded from the net... Apart from this one, the code of khttpd (linux/net/khttpd) would be very useful...
Go through thug_receive, thug_accept, thug_send, thug_listen... They should be sufficient for most of the networking...
Prasad IIIT-Hyderabad, INDIA.
--------- START OF CODE ----------
/* * * * Networking code for thug * * */
#include <linux/config.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/malloc.h> #include <linux/socket.h> #include <linux/in.h> #include <linux/locks.h> #include <linux/smp_lock.h> #include <asm/fcntl.h> #include <net/scm.h> #include <asm/uaccess.h> #include <linux/socket.h> #include <linux/inet.h> #include <asm/errno.h>
#include "thugd.h"
void fput(struct file *file);
struct socket *socki_lookup(struct inode *inode) { return &inode->u.socket_i; }
struct socket* thug_connect(struct sockaddr_in* sock_addr) { int retval; struct socket *sock; retval = sock_create(AF_INET,SOCK_STREAM,0,&sock);
if (retval < 0) { printk("thug_connect: error creating socket\n"); return NULL; }
retval = sock->ops->connect(sock,(struct sockaddr *)sock_addr,sizeof(struct sockaddr_in),0);
if (retval < 0) { printk("thug_connect: error on connect: %d\n",retval); sock_release(sock); return NULL; }
thug_print("Connection ok\n");
return sock; } struct socket* thug_listen(void) { struct socket *sock; struct sockaddr_in servaddr;
if (sock_create(AF_INET,SOCK_STREAM,0,&sock) < 0) { printk("thug_listen: error creating socket\n"); return NULL; }
memset(&servaddr,0,sizeof(servaddr));
servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(THUG_PORT);
if(sock->ops->bind(sock, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) { printk("thug_listen: bind error\n"); sock_release(sock); return NULL; }
if (sock->ops->listen(sock,5) < 0) { printk("thug_listen: listen error\n"); sock_release(sock); return NULL; }
return sock; }
struct socket* thug_accept(struct socket* sock) { struct inode* inode; struct socket* newsock; int err; struct sockaddr_in sin; int slen;
if (!(newsock = sock_alloc())) { printk("thug_accept: error creating socket(2)\n"); return NULL; }
inode = newsock->inode; newsock->type = sock->type; newsock->ops = sock->ops;
/*if (sock->ops->dup(newsock,sock) < 0) { printk("thug_accept: error dupping socket\n"); sock_release(newsock); return NULL; }*/
if ((err = newsock->ops->accept(sock,newsock,0)) < 0) { sock_release(newsock); return ERR_PTR(err); }
slen = sizeof(sin);
if ( (err = newsock->ops->getname(newsock,(struct sockaddr*)&sin,&slen,1)) < 0) { printk("thug_accept: error on getname: %d\n",err); sock_release(newsock); return ERR_PTR(err); }
newsock = socki_lookup(inode);
return newsock; }
int thug_receive(struct socket* sock,unsigned char* buf,int len) { struct msghdr msg; struct iovec iov; mm_segment_t oldfs; int size = 0;
iov.iov_base = buf; iov.iov_len = len;
msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_control = NULL; msg.msg_name = NULL; msg.msg_namelen = 0;
oldfs = get_fs(); set_fs(KERNEL_DS); size = sock_recvmsg(sock,&msg,len,0); set_fs(oldfs);
if (size < 0) printk("thug_read_from_socket: sock_recvmsg error: %d\n",size);
return size; }
int thug_read_from_socket(struct socket* sock,unsigned char* buf,int len) { int result; int received = 0;
while(received < len) { result = thug_receive(sock,buf + received,len - received);
if (result == 0) return -EIO; else if (result < 0) return result;
received += result; }
return received; }
int thug_send(struct socket* sock,unsigned char* buf,int len) { struct msghdr msg; struct iovec iov; mm_segment_t oldfs; int size = 0;
iov.iov_base = buf; iov.iov_len = len;
msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_control = NULL; msg.msg_controllen = 0; msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_flags = 0;
oldfs = get_fs(); set_fs(KERNEL_DS); size = sock_sendmsg(sock,&msg,len); set_fs(oldfs); if (size < 0) printk("thug_write_to_socket: sock_sendmsg error: %d\n",size);
return size; }
int thug_write_to_socket(struct socket* sock,unsigned char* buf,int len) { int result; int sent = 0;
while (sent < len) { result = thug_send(sock,buf + sent,len - sent);
if (result == 0) return -EIO; else if (result < 0) return result;
sent += result; }
return sent; }
int send_ack(struct socket* sock) { unsigned char buf = 0;
if (thug_write_to_socket(sock,&buf,1) != 1) { printk("Error sending ack"); return -1; }
return 0; }
int send_break(struct socket* sock) { unsigned char buf = 1;
if (thug_write_to_socket(sock,&buf,1) != 1) { printk("Error sending break"); return -1; }
return 0; }
int get_ack(struct socket* sock) { unsigned char buf;
if (thug_read_from_socket(sock,&buf,1) != 1) { printk("Error getting ack"); return -1; }
if (buf != 0) return -1;
return 0; }
void decodeui(unsigned int* dest,char* src) { if (dest && src) { *dest = 0; *dest = (src[0] << 24) & 0xFF000000; *dest |= (src[1] << 16) & 0xFF0000; *dest |= (src[2] << 8) & 0xFF00; *dest |= src[3] & 0xFF; } }
void encodeui(char* dest,unsigned int src) { if (dest) { dest[0] = (src & 0xFF000000) >> 24; dest[1] = (src & 0xFF0000) >> 16; dest[2] = (src & 0xFF00) >> 8; dest[3] = src & 0xFF; } }
void encodeus(char* dest,unsigned short src) { if (dest) { dest[0] = (src & 0xFF00) >> 8; dest[1] = src & 0xFF; } }
void decodeus(unsigned short* dest,char* src) { if (dest && src) { *dest = 0; *dest = src[0] << 8; *dest |= src[1] & 0xFF; } }
void decodel(long* dest,char* src) { if (dest && src) { *dest = 0; *dest = (src[0] << 24) & 0xFF000000; *dest |= (src[1] << 16) & 0xFF0000; *dest |= (src[2] << 8) & 0xFF00; *dest |= src[3] & 0xFF; } }
void encodel(char* dest,long src) { if (dest) { dest[0] = (src & 0xFF000000) >> 24; dest[1] = (src & 0xFF0000) >> 16; dest[2] = (src & 0xFF00) >> 8; dest[3] = src & 0xFF; } }
void decodeul(unsigned long* dest,char* src) { if (dest && src) { *dest = 0; *dest = (src[0] << 24) & 0xFF000000; *dest |= (src[1] << 16) & 0xFF0000; *dest |= (src[2] << 8) & 0xFF00; *dest |= src[3] & 0xFF; } }
void encodeul(char* dest,unsigned long src) { if (dest) { dest[0] = (src & 0xFF000000) >> 24; dest[1] = (src & 0xFF0000) >> 16; dest[2] = (src & 0xFF00) >> 8; dest[3] = src & 0xFF; } }
void decodell(long long* dest,char* src) { if (dest && src) { *dest = 0; *dest = (src[0] << 56) & 0xFF00000000000000; *dest |= (src[1] << 48) & 0xFF000000000000; *dest |= (src[2] << 40) & 0xFF0000000000; *dest |= (src[3] << 32) & 0xFF00000000; *dest |= (src[4] << 24) & 0xFF000000; *dest |= (src[5] << 16) & 0xFF0000; *dest |= (src[6] << 8) & 0xFF00; *dest |= src[7] & 0xFF; } }
void encodell(char* dest,long long src) { if (dest) { dest[0] = (src & 0xFF00000000000000) >> 56; dest[1] = (src & 0x00FF000000000000) >> 48; dest[2] = (src & 0x0000FF0000000000) >> 40; dest[3] = (src & 0x000000FF00000000) >> 32; dest[4] = (src & 0x00000000FF000000) >> 24; dest[5] = (src & 0x0000000000FF0000) >> 16; dest[6] = (src & 0x000000000000FF00) >> 8; dest[7] = src & 0x00000000000000FF; } }
void decodei(int* dest,char* src) { if (dest && src) { *dest = 0; *dest = (src[0] << 24) & 0xFF000000; *dest |= (src[1] << 16) & 0xFF0000; *dest |= (src[2] << 8) & 0xFF00; *dest |= src[3] & 0xFF; } }
void encodei(char* dest,int src) { if (dest) { dest[0] = (src & 0xFF000000) >> 24; dest[1] = (src & 0xFF0000) >> 16; dest[2] = (src & 0xFF00) >> 8; dest[3] = src & 0xFF; } }
/* must be called with the socket locked */ int thug_request(struct mfs_sb_info* thug_sb, unsigned int msglen) { unsigned short len; unsigned long flags; int error = 0; int mask; sigset_t old_set;
spin_lock_irqsave(¤t->sigmask_lock, flags); old_set = current->blocked; mask = sigmask(SIGKILL) | sigmask(SIGSTOP); siginitsetinv(¤t->blocked,mask); recalc_sigpending(current); spin_unlock_irqrestore(¤t->sigmask_lock, flags);
if ((error = thug_write_to_socket(thug_sb->sock, thug_sb->packet, msglen)) != msglen) { printk("thug_request: error sending request to server\n"); goto out; }
memset(thug_sb->packet, 0, thug_sb->packet_len);
if ((error = thug_read_from_socket(thug_sb->sock, thug_sb->packet, 2)) != 2) { printk("thug_request: error reading reply length from socket\n"); goto out; }
decodeus(&len, thug_sb->packet);
if ((error = thug_read_from_socket(thug_sb->sock, thug_sb->packet + 2, len)) != len) { printk("thug_request: error reading reply body from socket (%d)\n",len); goto out; }
out: spin_lock_irqsave(¤t->sigmask_lock, flags); current->blocked = old_set; recalc_sigpending(current); spin_unlock_irqrestore(¤t->sigmask_lock, flags);
return error; }
void encode_iattr(char* dest, struct iattr* attr) { encodeui(dest, attr->ia_valid); encodeus(dest + 4, attr->ia_mode); encodeui(dest + 6, attr->ia_uid); encodeui(dest + 10, attr->ia_gid); encodell(dest + 14, attr->ia_size); encodel(dest + 22, attr->ia_atime); encodel(dest + 26, attr->ia_mtime); encodel(dest + 30, attr->ia_ctime); encodeui(dest + 34, attr->ia_attr_flags); }
void decode_iattr(struct iattr* dest, char* src) { decodeui(&dest->ia_valid, src); decodeus(&dest->ia_mode, src + 4); decodeui(&dest->ia_uid, src + 6); decodeui(&dest->ia_gid, src + 10); decodell(&dest->ia_size, src + 14); decodel(&dest->ia_atime, src + 22); decodel(&dest->ia_mtime, src + 26); decodel(&dest->ia_ctime, src + 30); decodeui(&dest->ia_attr_flags, src + 34); }
----------- END OF CODE ------------
On Mon, 23 Dec 2002, Jelena Mirkovic wrote:
> I am trying (in vain) to create and send a single TCP packet from kernel, > from scratch (i.e. sk_buff and sock both need to be created and > initialized). I read the source code for various functions in net and > net/ipv4 but I am not sure I am doing all steps and in correct order, as > the kernel keeps crashing. Is there a sample code someone could send me or > a good book on this matter? I am using 2.4.9 version. > > If this question is not appropriate for this list, could someone point me > to more suitable list? > > Thanks > Jelena > > - > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > Please read the FAQ at http://www.tux.org/lkml/ >
-- Failure is not an option
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |