예제 #1
0
파일: icmp.c 프로젝트: ChunHungLiu/xenomai
/***
 *  common reply function
 */
static void rt_icmp_send_reply(struct icmp_bxm *icmp_param, struct rtskb *skb)
{
    struct dest_route   rt;
    int                 err;


    icmp_param->head.icmph.checksum = 0;
    icmp_param->csum = 0;

    /* route back to the source address via the incoming device */
    if (rt_ip_route_output(&rt, skb->nh.iph->saddr,
			   skb->rtdev->local_ip) != 0)
	return;

    rt_socket_reference(icmp_socket);
    err = rt_ip_build_xmit(icmp_socket, rt_icmp_glue_reply_bits, icmp_param,
			   sizeof(struct icmphdr) + icmp_param->data_len,
			   &rt, MSG_DONTWAIT);
    if (err)
	    rt_socket_dereference(icmp_socket);

    rtdev_dereference(rt.rtdev);

    RTNET_ASSERT(err == 0,
		 rtdm_printk("RTnet: %s() error in xmit\n", __FUNCTION__););
예제 #2
0
/*
 * This function returns an rtskb that contains the complete, accumulated IP message.
 * If not all fragments of the IP message have been received yet, it returns NULL
 * Note: the IP header must have already been pulled from the rtskb!
 * */
struct rtskb *rt_ip_defrag(struct rtskb *skb, struct rtinet_protocol *ipprot)
{
    unsigned int more_frags;
    unsigned int offset;
    struct rtsocket *sock;
    struct iphdr *iph = skb->nh.iph;
    int ret;


    counter++;

    /* Parse the IP header */
    offset = ntohs(iph->frag_off);
    more_frags = offset & IP_MF;
    offset &= IP_OFFSET;
    offset <<= 3;   /* offset is in 8-byte chunks */

    /* First fragment? */
    if (offset == 0)
    {
        /* Get the destination socket */
        if ((sock = ipprot->dest_socket(skb)) == NULL) {
            /* Drop the rtskb */
            kfree_rtskb(skb);
            return NULL;
        }

        /* Acquire the rtskb at the expense of the protocol pool */
        ret = rtskb_acquire(skb, &sock->skb_pool);

        /* socket is now implicitely locked by the rtskb */
        rt_socket_dereference(sock);

        if (ret != 0) {
            /* Drop the rtskb */
            kfree_rtskb(skb);
        } else {
            /* Allocates a new collector */
            alloc_collector(skb, sock);
        }
        return NULL;
    }
    else
    {
        /* Add to an existing collector */
        return add_to_collector(skb, offset, more_frags);
    }
}
예제 #3
0
/***
 *  rt_ip_local_deliver
 */
static inline int rt_ip_local_deliver(struct rtskb *skb)
{
    struct iphdr *iph       = skb->nh.iph;
    unsigned short protocol = iph->protocol;
    struct rtinet_protocol *ipprot;
    struct rtsocket *sock;
    int ret;


    ipprot = rt_inet_protocols[rt_inet_hashkey(protocol)];

    /* Check if we are supporting the protocol */
    if ((ipprot != NULL) && (ipprot->protocol == protocol))
    {
        __rtskb_pull(skb, iph->ihl*4);

        /* Point into the IP datagram, just past the header. */
        skb->h.raw = skb->data;

        /* Reassemble IP fragments */
        if (iph->frag_off & htons(IP_MF|IP_OFFSET)) {
            skb = rt_ip_defrag(skb, ipprot);
            if (!skb)
                return 0;
        } else {
            /* Get the destination socket */
            if ((sock = ipprot->dest_socket(skb)) == NULL) {
                kfree_rtskb(skb);
                return 0;
            }

            /* Acquire the rtskb at the expense of the protocol pool */
            ret = rtskb_acquire(skb, &sock->skb_pool);

            /* Socket is now implicitely locked by the rtskb */
            rt_socket_dereference(sock);

            if (ret != 0) {
                kfree_rtskb(skb);
                return 0;
            }
        }

        /* Deliver the packet to the next layer */
        ret = ipprot->rcv_handler(skb);
    } else {
#ifdef CONFIG_RTNET_ADDON_PROXY
        /* If a fallback handler for IP protocol has been installed,
         * call it! */
        if (ip_fallback_handler) {
            ret = ip_fallback_handler(skb);
            if (ret) {
                rtos_print("RTnet: fallback handler failed\n");
            }
            return ret;
        }
#endif /* CONFIG_RTNET_ADDON_PROXY */
        rtos_print("RTnet: no protocol found\n");
        kfree_rtskb(skb);
        ret = 0;
    }

    return ret;
}