예제 #1
0
파일: ip_output.c 프로젝트: Abioy/kasan
/*
 *		Add an ip header to a skbuff and send it out.
 *
 */
int ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk,
			  __be32 saddr, __be32 daddr, struct ip_options_rcu *opt)
{
	struct inet_sock *inet = inet_sk(sk);
	struct rtable *rt = skb_rtable(skb);
	struct iphdr *iph;

	/* Build the IP header. */
	skb_push(skb, sizeof(struct iphdr) + (opt ? opt->opt.optlen : 0));
	skb_reset_network_header(skb);
	iph = ip_hdr(skb);
	iph->version  = 4;
	iph->ihl      = 5;
	iph->tos      = inet->tos;
	if (ip_dont_fragment(sk, &rt->dst))
		iph->frag_off = htons(IP_DF);
	else
		iph->frag_off = 0;
	iph->ttl      = ip_select_ttl(inet, &rt->dst);
	iph->daddr    = (opt && opt->opt.srr ? opt->opt.faddr : daddr);
	iph->saddr    = saddr;
	iph->protocol = sk->sk_protocol;
	ip_select_ident(skb, sk);

	if (opt && opt->opt.optlen) {
		iph->ihl += opt->opt.optlen>>2;
		ip_options_build(skb, &opt->opt, daddr, rt, 0);
	}
예제 #2
0
/* 
 *		Add an ip header to a skbuff and send it out.
 *
 */
int ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk,
			  u32 saddr, u32 daddr, struct ip_options *opt)
{
	struct inet_sock *inet = inet_sk(sk);
	struct rtable *rt = (struct rtable *)skb->dst;
	struct iphdr *iph;

	/* Build the IP header. */
	if (opt)
		iph=(struct iphdr *)skb_push(skb,sizeof(struct iphdr) + opt->optlen);
	else
		iph=(struct iphdr *)skb_push(skb,sizeof(struct iphdr));

	iph->version  = 4;
	iph->ihl      = 5;
	iph->tos      = inet->tos;
	if (ip_dont_fragment(sk, &rt->u.dst))
		iph->frag_off = htons(IP_DF);
	else
		iph->frag_off = 0;
	iph->ttl      = ip_select_ttl(inet, &rt->u.dst);
	iph->daddr    = rt->rt_dst;
	iph->saddr    = rt->rt_src;
	iph->protocol = sk->sk_protocol;
	iph->tot_len  = htons(skb->len);
	ip_select_ident(iph, &rt->u.dst, sk);
	skb->nh.iph   = iph;

	if (opt && opt->optlen) {
		iph->ihl += opt->optlen>>2;
		ip_options_build(skb, opt, daddr, rt, 0);
	}
예제 #3
0
파일: ip_output.c 프로젝트: lehoon/fast-tcp
int ip_format_and_send_pkt(struct sk_buff *skb,struct sock*sk,__be32 saddr, __be32 daddr,u16 tcp_len)
{
	int ret	= 0;
	struct net 			*pnet 	= sock_net(sk);
	struct netns_ipv4	*n_ipv4 = &pnet->ipv4;
	struct inet_sock 	*inet 	= inet_sk(sk);
	struct tcphdr 		*th 	= tcp_hdr(skb);
	struct iphdr 		*iph	= ip_hdr(skb);

	iph->tos 		= inet->tos;
	iph->tot_len 	= htons(sizeof(struct iphdr) + tcp_len);
	iph->frag_off 	= htons(IP_DF);
	ip_select_ident(skb, sk);
	iph->ttl      	= ip_select_ttl(sk);
	iph->protocol 	= sk->sk_protocol;
	iph->daddr    	= daddr;
	iph->saddr    	= saddr;
	iph->check	  	= 0; 
	th->check 		= 0;	
	th->check 		= get_ipv4_psd_sum(iph);

	if(n_ipv4->aft_route_out){
		ret = n_ipv4->aft_route_out(skb);
		if(ret < 0)
			return US_ENETUNREACH;
	}

	return mbuf_format_and_send(skb, tcp_len);
}
예제 #4
0
파일: ip_output.c 프로젝트: lehoon/fast-tcp
int ip_queue_xmit(struct sk_buff *skb)
{	
	//smallboy:    We delete all the route here;
	//smallboy:    ROUTE ROUTE  ROUTE  ROUTE !!!!!
	
	struct sock 		*sk 	= skb->sk;
	struct inet_sock 	*inet 	= inet_sk(sk);
	struct tcphdr 	 	*th		= tcp_hdr(skb);
	struct net 			*pnet 	= sock_net(sk);
	struct netns_ipv4	*n_ipv4 = &pnet->ipv4;

	struct iphdr *iph;
	u32 ihl;
	s32 ret = 0;

	//ihl = sizeof(struct iphdr) + (inet_opt ? inet_opt->optlen : 0);
	ihl = sizeof(struct iphdr);
	skb_push(skb, ihl);
	
	skb_reset_network_header(skb);
	
	iph = ip_hdr(skb);
	
	iph->version = 4;					//smallboy: Attention for ipv6;
	iph->ihl 	 = ihl>>2;

	iph->tos	 = inet->tos;
	iph->tot_len = htons(skb->len);
	
	iph->frag_off = htons(IP_DF);
	iph->ttl	  = ip_select_ttl(sk);
	iph->protocol = sk->sk_protocol;
	
	iph->daddr	= inet->inet_daddr;			//
	iph->saddr	= inet->inet_rcv_saddr; 	//smallboy:Attention here;

	ip_select_ident_more(iph, sk, (skb->gso_segs ?: 1) - 1);
	
	th->check	= 0;
	//th->check	= get_ipv4_udptcp_checksum(iph , th);
	
	iph->check	= 0;

	th->check = get_ipv4_psd_sum(iph);
	//iph->check  = ip_fast_csum(iph, iph->ihl);

	if(n_ipv4->aft_route_out){
		ret = n_ipv4->aft_route_out(skb);
		if(ret < 0){
			skb_reset_data_header(skb);	
			return ret;
		}
	}

	ret = ip_local_out(skb);

	return ret;
}
예제 #5
0
파일: ip_output.c 프로젝트: lehoon/fast-tcp
/*
 *		Add an ip header to a skbuff and send it out.
 *
 */
int ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk,__be32 saddr, __be32 daddr)
{
	int ret = 0;
	struct inet_sock 	*inet 	= inet_sk(sk);
	struct tcphdr 		*th 	= tcp_hdr(skb);
	struct net 			*pnet 	= sock_net(sk);
	struct netns_ipv4	*n_ipv4 = &pnet->ipv4;
	struct iphdr *iph;

	// Build the IP header. 
	skb_push(skb, sizeof(struct iphdr));  ////+ (opt ? opt->opt.optlen : 0)
	skb_reset_network_header(skb);
	iph = ip_hdr(skb);
	
	iph->version  = 4;
	iph->ihl      = 5;		
	//iph->tos      = 0;//inet->tos;
	iph->tos      = inet->tos;
	iph->tot_len  = htons(skb->len);
	iph->frag_off = htons(IP_DF);		//smallboy :must before ip_select_ident;
	
	ip_select_ident(skb, sk);
	iph->ttl      = ip_select_ttl(sk);
	iph->protocol = sk->sk_protocol;
	iph->daddr    = daddr;
	iph->saddr    = saddr;
	
	iph->check	  = 0;
	//iph->check    = ip_fast_csum(iph, iph->ihl);

	th->check = 0;
	//th->check = get_ipv4_udptcp_checksum(iph , th);
	th->check = get_ipv4_psd_sum(iph);
	
	//skb->mark = sk->sk_mark;

	//fprintf(stderr,"TH:%u,src:%s,dst:%s,sport:%u,dport:%u,seq:%-12u,ack:%-12u,ipid:%-12u,len:%-12u,SYN:%u;PSH:%u;ACK:%u;FIN:%u;RST:%u; send!!!\n"
	//		,US_GET_LCORE(),trans_ip(iph->saddr),trans_ip(iph->daddr)
	//		,ntohs(th->source),ntohs(th->dest)
	//		,ntohl(th->seq),ntohl(th->ack_seq)
	//		,iph->id,skb->len,th->syn,th->psh,th->ack,th->fin,th->rst);	

	if(n_ipv4->aft_route_out){
		ret = n_ipv4->aft_route_out(skb);
		if(ret < 0)
			return US_ENETUNREACH;
	}

	// Send it out. 
	return ip_local_out(skb);		
}
예제 #6
0
int serval_ipv4_xmit(struct sk_buff *skb)
{
        struct sock *sk = skb->sk;
        int err = 0;
#if defined(OS_LINUX_KERNEL)

	/*
          This is pretty much a copy paste from ip_queue_xmit
          (ip_output.c), but which modifications that take into
          account Serval specific stuff.
          
          It will route the packet according to the IP stack's routing
          table and output for standard IP output processing.
         */
        struct iphdr *iph;
        struct rtable *rt;
        struct inet_sock *inet = inet_sk(sk);
	struct ip_options *opt = NULL; /*inet->inet_opt; */
        int ifindex;

	/*
	   The SAL has dirtied the control block that IP expects to be
	zeroed out. 
	We need to make sure it is initialized again. Otherwise, there
	might be stack corruptions when IP functions try to read the
	IPCB. (This happens in, e.g., icmp_send when reading ip options.)  
	*/
        memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
        
	/* 
         * Skip all of this if the packet is already routed,
         */
        rcu_read_lock();

        rt = skb_rtable(skb);

        if (rt != NULL) {
                LOG_PKT("Packet already routed\n");
                goto packet_routed;
        }
        /* Make sure we can route this packet. */
        rt = (struct rtable *)__sk_dst_check(sk, 0);

        if (skb->dev) {
                ifindex = skb->dev->ifindex;
        } else {
                ifindex = sk->sk_bound_dev_if;
        }

        if (rt == NULL) {
                struct flowi fl;

                serval_flow_init_output(&fl, ifindex, 
                                        sk->sk_mark, 
                                        RT_CONN_FLAGS(sk), 0,
                                        skb->protocol,
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28))
                                        inet_sk_flowi_flags(sk),
#else
                                        0,
#endif
                                        inet->inet_daddr,
                                        inet->inet_saddr,
                                        0, 0);
                
                serval_security_sk_classify_flow(sk, &fl);
                
                rt = serval_ip_route_output_flow(sock_net(sk), &fl, sk, 0);

                if (!rt) {
                        LOG_DBG("No route!\n");
                        err = -EHOSTUNREACH;
                        rcu_read_unlock();
                        goto drop;
                }

                /* Setup the socket to use this route in the future */
                sk_setup_caps(sk, route_dst(rt));

        } else {
                LOG_PKT("Using route already associated with socket\n");
        }
        
#if defined(ENABLE_DEBUG)
        {
                char src[18], dst[18];
                LOG_PKT("Route found %s -> %s %s\n",
                        inet_ntop(AF_INET, &rt->rt_src, 
                                  src, sizeof(src)),
                        inet_ntop(AF_INET, &rt->rt_dst, 
                                  dst, sizeof(dst)),
                        route_dst(rt)->dev ? 
                        route_dst(rt)->dev->name : "(null)");
        }
#endif

#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35))
        skb_dst_set(skb, dst_clone(route_dst(rt)));
#else
        skb_dst_set_noref(skb, route_dst(rt));
#endif
 packet_routed:
        if (opt && opt->is_strictroute && rt->rt_dst != rt->rt_gateway) {
                err = -EHOSTUNREACH;
                rcu_read_unlock();
                LOG_DBG("dest is not gateway!\n");
                goto drop;
        }


	/* OK, we know where to send it, allocate and build IP header. */
	skb_push(skb, sizeof(struct iphdr) + (opt ? opt->optlen : 0));
	skb_reset_network_header(skb);
	iph = ip_hdr(skb);
	*((__be16 *)iph) = htons((4 << 12) | (5 << 8) | (inet->tos & 0xff));
	if (ip_dont_fragment(sk, route_dst(rt)) && !skb->local_df)
		iph->frag_off = htons(IP_DF);
	else
		iph->frag_off = 0;
	iph->ttl      = ip_select_ttl(inet, route_dst(rt));
	iph->protocol = skb->protocol;
	iph->saddr    = rt->rt_src;
	iph->daddr    = rt->rt_dst;

	if (opt && opt->optlen) {
                LOG_WARN("IP options not implemented\n");
                /* For some reason, enabling the code below gives the
                 * error: "Unknown symbol ip_options_build (err 0)"
                 * when loading the serval.ko module. Seems the
                 * ip_options_build function is not exported.
                 */
                /*
		iph->ihl += opt->optlen >> 2;
		ip_options_build(skb, opt, inet->inet_daddr, rt, 0);
                */
	}
        
        ip_select_ident_more(iph, route_dst(rt), sk,
			     (skb_shinfo(skb)->gso_segs ?: 1) - 1);

	skb->priority = sk->sk_priority;

#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25))
	skb->mark = sk->sk_mark;
#endif
	err = serval_ip_local_out(skb);

	rcu_read_unlock();
#else
        /*
          FIXME: We should not rely on an outgoing interface here.
          Instead, we should route the packet like we do in the
          kernel. But, we currently do not have an IP routing table
          for userlevel.
         */

        if (!skb->dev)
                skb->dev = __dev_get_by_index(sock_net(sk),
                                              sk->sk_bound_dev_if);

        if (!skb->dev) {
                LOG_ERR("no output device set in skb!\n");
                err = -ENODEV;
                goto drop;
        }
        err = serval_ipv4_fill_in_hdr(sk, skb, inet_sk(sk)->inet_saddr,
                                      inet_sk(sk)->inet_daddr);
        
        if (err < 0) {
                LOG_ERR("hdr failed\n");
                goto drop;
        }

        /* Transmit */
        err = serval_ip_local_out(skb);
#endif /* OS_LINUX_KERNEL */    
 out:
        if (err < 0) {
                LOG_ERR("xmit failed: %d\n", err);
        }

        return err;
drop:
        LOG_DBG("Dropping skb!\n");

        FREE_SKB(skb);
        
        goto out;
}