adding header in kernel to data passed from user space

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

My name is anand and I am trying to develop a system call that adds
twelve bytes of header to data passed from user space. This twelve
bytes of data is to facilitate the RTP (Real-time Transport Protocol)
. Basically the file rtpsendto.c contains my code for the systemc
call. It calls two external functions rtpsendmsg in udp.c and
ip_generic_getfrag_anand in ip_output.c. I modified and added theses
two functions to /usr/src/linux/net/ipv4/udp.c and
/usr/src/linux/net/ipv4/ip_output.c in my distribution.


Basically my rtpsendmsg functions and ip_generic_getfrag_anand
functions are exactly the same as the udpsendmsg and
ip_generic_getfrag function s already present in linux except that
ip_generic_getfrag adds the 12 bytes of header.

I added and compiled the sytem call successfully but it doesnt work
properly. If I send 'anand' from server to client I get the character
ACK on the client side.

I suspect that the header that is 12 bytes does not handle network
byte order, and I think if I pass the number of bytes to be
transferred as a certain number then it doesnt take the extra 12 bytes
into account. Can anyone help me on this? I have cut and paste my code
at the end of this email


Thanks

/* the system call rtpsendto*/




#include<linux/linkage.h>

#include<asm/system.h>

#include<asm/uaccess.h>

#include<asm/ioctls.h>

#include <linux/types.h>

#include<linux/fcntl.h>

#include<linux/module.h>

#include<linux/socket.h>

#include<linux/sockios.h>

#include<linux/igmp.h>

#include<linux/in.h>

#include<linux/errno.h>

#include<linux/timer.h>

#include<linux/mm.h>

#include<linux/inet.h>

#include<linux/ipv6.h>

#include<linux/netdevice.h>

#include<net/snmp.h>

#include<net/ip.h>

#include<net/tcp_states.h>

#include<net/protocol.h>

#include<linux/skbuff.h>

#include<linux/proc_fs.h>

#include<linux/seq_file.h>

#include<net/sock.h>

#include<net/udp.h>

#include<net/icmp.h>

#include<net/route.h>

#include<net/inet_common.h>

#include<net/checksum.h>

#include<net/xfrm.h>

#include<linux/moduleparam.h>

#defineMAX_SOCK_ADDR 128

externint rtpsendmsg(struct sock* sk, struct msghdr *msg, int len);

externint ret_inet_autobind(struct sock* sk);

asmlinkage long sys_rtpsendto(int fd1, char * buff1, size_t
numbytes1,struct sockaddr* to1, int addrlen1 )

{

struct socket *sock1;

struct sock *sk;

char address1[MAX_SOCK_ADDR];

int err1;

struct msghdr msg1;

struct iovec iov1;



sock1 = sockfd_lookup(fd1, &err1);



iov1.iov_base=buff1;

iov1.iov_len=numbytes1;

msg1.msg_name=NULL;

msg1.msg_iov=&iov1;

msg1.msg_iovlen=1;

msg1.msg_control=NULL;

msg1.msg_controllen=0;

msg1.msg_namelen=0;

err1 = move_addr_to_kernel(to1, addrlen1, address1);

msg1.msg_name = address1;

msg1.msg_namelen = addrlen1;

sk = sock1->sk;

// if (sk->num==0 && inet_autobind(sk) != 0)

// return -EAGAIN;



if (!inet_sk(sk)->num && ret_inet_autobind(sk))

return -EAGAIN;

err1 = rtpsendmsg(sk, &msg1, numbytes1);



return err1;

}

/* end of system call rtpsendto */




/* ip_generic_getfrag_anand */


intip_generic_getfrag_anand(void *from, char *to, int offset, int len,
int odd, struct sk_buff *skb){

struct iovec *iov = from;

struct timeval *tv;

long ts2;

static int seqno=0;

// do_gettimeofday(tv);

// static long ts= (long)tv->tv_sec * 1000000 + (long) tv->tv_usec ;



tv = kmalloc(sizeof(struct timeval), GFP_KERNEL);

do_gettimeofday(tv);

ts2= (long)tv->tv_sec * 1000000 + (long) tv->tv_usec ;

// ts2 = ts2 -ts;

to = kmalloc(12*sizeof(char), GFP_KERNEL);

to[0]= 0x80;

to[1]= 0x20;

to[2]= ((seqno%65536)<<16)>>24;

to[3]= ((seqno%65536)<<24)>>24;

to[4]= (ts2<<32)>> 56;

to[5]= (ts2<<40)>>56;

to[6]= (ts2<<48)>>56;

to[7]= (ts2<<56)>>56;

to[8]= 0x40;

to[9]= 0x51;

to[10]= 0x52;

to[11]= 0x34;

if (skb->ip_summed == CHECKSUM_HW) {

if (memcpy_fromiovecend((to+ 12), iov, offset, len) < 0)

return -EFAULT;

} else {

unsigned int csum = 0;

if (csum_partial_copy_fromiovecend((to+ 12), iov, offset, len, &csum) < 0)

return -EFAULT;

skb->csum = csum_block_add(skb->csum, csum, odd);

}

seqno++;

return 0;

}

/*end of ip_generic_getfrag_anand */





/* rtpsendmsg */


intrtpsendmsg(struct sock* sk, struct msghdr *msg, int len){

structinet_sock *inet = inet_sk(sk);

struct udp_sock *up = udp_sk(sk);

int ulen = len;

struct ipcm_cookie ipc;

struct rtable *rt = NULL;

int free = 0;

int connected = 0;

u32 daddr, faddr, saddr;

u16 dport;

u8 tos;

int err;

int corkreq = up->corkflag || msg->msg_flags&MSG_MORE;

if (len > 0xFFFF)

return -EMSGSIZE;

/*

* Check the flags.

*/

if (msg->msg_flags&MSG_OOB) /* Mirror BSD error message compatibility */

return -EOPNOTSUPP;

ipc.opt = NULL;

if (up->pending) {

/*

* There are pending frames.

* The socket lock must be held while it's corked.

*/

lock_sock(sk);

if (likely(up->pending)) {

if (unlikely(up->pending != AF_INET)) {

release_sock(sk);

return -EINVAL;

}

goto do_append_data;

}

release_sock(sk);

}

ulen += sizeof(struct udphdr);

/*

* Get and verify the address.

*/

if (msg->msg_name) {

struct sockaddr_in * usin = (struct sockaddr_in*)msg->msg_name;

if (msg->msg_namelen < sizeof(*usin))

return -EINVAL;

if (usin->sin_family != AF_INET) {

if (usin->sin_family != AF_UNSPEC)

return -EAFNOSUPPORT;

}

daddr = usin->sin_addr.s_addr;

dport = usin->sin_port;

if (dport == 0)

return -EINVAL;

} else {

if (sk->sk_state != TCP_ESTABLISHED)

return -EDESTADDRREQ;

daddr = inet->daddr;

dport = inet->dport;

/* Open fast path for connected socket.

Route will not be used, if at least one option is set.

*/

connected = 1;

}

ipc.addr = inet->saddr;

ipc.oif = sk->sk_bound_dev_if;

if (msg->msg_controllen) {

err = ip_cmsg_send(msg, &ipc);

if (err)

return err;

if (ipc.opt)

free = 1;

connected = 0;

}

if (!ipc.opt)

ipc.opt = inet->opt;

saddr = ipc.addr;

ipc.addr = faddr = daddr;

if (ipc.opt && ipc.opt->srr) {

if (!daddr)

return -EINVAL;

faddr = ipc.opt->faddr;

connected = 0;

}

tos = RT_TOS(inet->tos);

if (sock_flag(sk, SOCK_LOCALROUTE) ||

(msg->msg_flags & MSG_DONTROUTE) ||

(ipc.opt && ipc.opt->is_strictroute)) {

tos |= RTO_ONLINK;

connected = 0;

}

if (MULTICAST(daddr)) {

if (!ipc.oif)

ipc.oif = inet->mc_index;

if (!saddr)

saddr = inet->mc_addr;

connected = 0;

}

if (connected)

rt = (struct rtable*)sk_dst_check(sk, 0);

if (rt == NULL) {

struct flowi fl = { .oif = ipc.oif,

.nl_u = { .ip4_u =

{ .daddr = faddr,

.saddr = saddr,

.tos = tos } },

.proto = IPPROTO_UDP,

.uli_u = { .ports =

{ .sport = inet->sport,

.dport = dport } } };

err = ip_route_output_flow(&rt, &fl, sk, !(msg->msg_flags&MSG_DONTWAIT));

if (err)

goto out;

err = -EACCES;

if ((rt->rt_flags & RTCF_BROADCAST) &&

!sock_flag(sk, SOCK_BROADCAST))

goto out;

if (connected)

sk_dst_set(sk, dst_clone(&rt->u.dst));

}

if (msg->msg_flags&MSG_CONFIRM)

goto do_confirm;

back_from_confirm:

saddr = rt->rt_src;

if (!ipc.addr)

daddr = ipc.addr = rt->rt_dst;

lock_sock(sk);

if (unlikely(up->pending)) {

/* The socket is already corked while preparing it. */

/* ... which is an evident application bug. --ANK */

release_sock(sk);

LIMIT_NETDEBUG(KERN_DEBUG "udp cork app bug 2\n");

err = -EINVAL;

goto out;

}

/*

* Now cork the socket to pend data.

*/

inet->cork.fl.fl4_dst = daddr;

inet->cork.fl.fl_ip_dport = dport;

inet->cork.fl.fl4_src = saddr;

inet->cork.fl.fl_ip_sport = inet->sport;

up->pending = AF_INET;

do_append_data:

up->len += ulen;

err = ip_append_data(sk, ip_generic_getfrag_anand, msg->msg_iov, ulen,

sizeof(struct udphdr), &ipc, rt,

corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags);

if (err)

udp_flush_pending_frames(sk);

else if (!corkreq)

err = udp_push_pending_frames(sk, up);

release_sock(sk);

out:

ip_rt_put(rt);

if (free)

kfree(ipc.opt);

if (!err) {

UDP_INC_STATS_USER(UDP_MIB_OUTDATAGRAMS);

return len;

}

return err;

do_confirm:

dst_confirm(&rt->u.dst);

if (!(msg->msg_flags&MSG_PROBE) || len)

goto back_from_confirm;

err = 0;

goto out;

}

/*end of rtpsendmsg */
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux