Пример #1
0
/***
 *  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 functions runs in rtai context.
 * It is called from rtnetproxy_user_srq whenever there is frame to sent out
 * Copy the standard linux sk_buff buffer to a rtnet buffer and send it out
 * using rtnet functions.
 * ************************************************************************ */
static inline void send_data_out(struct sk_buff *skb)
{

    struct rtskb *rtskb;
    struct rt_rtable *rt;

    struct skb_data_format
    {
        struct ethhdr ethhdr;
        char   reserved[12]; /* Ugly but it works... All the not-interesting header bytes */
        u32    ip_src;
        u32    ip_dst;
    } __attribute__ ((packed));  /* Important to have this structure packed!
                                  * It represents the ethernet frame on the line and
                                  * thus no spaces are allowed! */

    struct skb_data_format *pData;
    int rc;

    /* Copy the data from the standard sk_buff to the realtime sk_buff:
     * Both have the same length. */
    rtskb = alloc_rtskb(skb->len);
    if (NULL == rtskb) {
        return;
    }

    memcpy(rtskb->data, skb->data, skb->len);
    rtskb->len = skb->len;

    pData = (struct skb_data_format*) rtskb->data;

    /* Determine the device to use: Only ip routing is used here.
     * Non-ip protocols are not supported... */
    rc = rt_ip_route_output(&rt, pData->ip_dst, pData->ip_src);
    if (rc == 0)
    {
        struct rtnet_device *rtdev = rt->rt_dev;
        rtskb->dst = rt;
        rtskb->rtdev = rt->rt_dev;

        /* Fill in the ethernet headers: There is already space for the header
         * but they contain zeros only => Fill it */
        memcpy(pData->ethhdr.h_source, rtdev->dev_addr, rtdev->addr_len);
        memcpy(pData->ethhdr.h_dest, rt->rt_dst_mac_addr, rtdev->addr_len);

        /* Call the actual transmit function (this function is semaphore
         * protected): */
        rtdev_xmit(rtskb);
        /* The rtskb is freed somewhere deep in the driver...
         * No need to do it here. */
    }
    else
    {
        /* Routing failed => Free rtskb here... */
        kfree_rtskb(rtskb);
    }

}
Пример #3
0
/***
 *  common reply function
 */
static void rt_icmp_send_reply(struct icmp_bxm *icmp_param, struct rtskb *skb)
{
    struct dest_route   rt;
    u32                 daddr;
    int                 err;


    daddr = skb->nh.iph->saddr;

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

    if (rt_ip_route_output(&rt, daddr) != 0)
        return;

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

    rtdev_dereference(rt.rtdev);

    RTNET_ASSERT(err == 0,
                 rtos_print("RTnet: %s() error in xmit\n", __FUNCTION__););
Пример #4
0
/***
 *  rt_udp_sendmsg
 */
ssize_t rt_udp_sendmsg(struct rtdm_dev_context *context, int call_flags,
                       const struct msghdr *msg, int msg_flags)
{
    struct rtsocket     *sock = (struct rtsocket *)&context->dev_private;
    size_t              len   = rt_iovec_len(msg->msg_iov, msg->msg_iovlen);
    int                 ulen  = len + sizeof(struct udphdr);
    struct sockaddr_in  *usin;
    struct udpfakehdr   ufh;
    struct dest_route   rt;
    u32                 saddr;
    u32                 daddr;
    u16                 dport;
    int                 err;
    unsigned long       flags;


    if ((len < 0) || (len > 0xFFFF-sizeof(struct iphdr)-sizeof(struct udphdr)))
        return -EMSGSIZE;

    if (msg_flags & MSG_OOB)   /* Mirror BSD error message compatibility */
        return -EOPNOTSUPP;

    if (msg_flags & ~(MSG_DONTROUTE|MSG_DONTWAIT) )
        return -EINVAL;

    if ((msg->msg_name) && (msg->msg_namelen==sizeof(struct sockaddr_in))) {
        usin = (struct sockaddr_in*) msg->msg_name;

        if ((usin->sin_family != AF_INET) && (usin->sin_family != AF_UNSPEC))
            return -EINVAL;

        daddr = usin->sin_addr.s_addr;
        dport = usin->sin_port;

        rtos_spin_lock_irqsave(&sock->param_lock, flags);
    } else {
        rtos_spin_lock_irqsave(&sock->param_lock, flags);

        if (sock->prot.inet.state != TCP_ESTABLISHED)
            return -ENOTCONN;

        daddr = sock->prot.inet.daddr;
        dport = sock->prot.inet.dport;
    }
    saddr         = sock->prot.inet.saddr;
    ufh.uh.source = sock->prot.inet.sport;

    rtos_spin_unlock_irqrestore(&sock->param_lock, flags);

    if ((daddr | dport) == 0)
        return -EINVAL;

    /* get output route */
    err = rt_ip_route_output(&rt, daddr);
    if (err)
        return err;

    /* check if specified source address fits */
    if ((saddr != INADDR_ANY) && (saddr != rt.rtdev->local_ip)) {
        rtdev_dereference(rt.rtdev);
        return -EHOSTUNREACH;
    }

    /* we found a route, remember the routing dest-addr could be the netmask */
    ufh.saddr     = rt.rtdev->local_ip;
    ufh.daddr     = daddr;
    ufh.uh.dest   = dport;
    ufh.uh.len    = htons(ulen);
    ufh.uh.check  = 0;
    ufh.iov       = msg->msg_iov;
    ufh.iovlen    = msg->msg_iovlen;
    ufh.wcheck    = 0;

    err = rt_ip_build_xmit(sock, rt_udp_getfrag, &ufh, ulen, &rt, msg_flags);

    rtdev_dereference(rt.rtdev);

    if (!err)
        return len;
    else
        return err;
}
Пример #5
0
/***
 *  rt_udp_sendmsg
 */
int rt_udp_sendmsg(struct rtsocket *s, const struct msghdr *msg, size_t len, int flags)
{
    int ulen = len + sizeof(struct udphdr);

    struct udpfakehdr ufh;
    struct rt_rtable *rt = NULL;

    u32 daddr;
    u16 dport;
    int err;

    if ((len < 0) || (len > 0xFFFF-sizeof(struct iphdr)-sizeof(struct udphdr)))
        return -EMSGSIZE;

    if (flags & MSG_OOB)   /* Mirror BSD error message compatibility */
        return -EOPNOTSUPP;

    if (flags & ~(MSG_DONTROUTE|MSG_DONTWAIT) )
        return -EINVAL;

    if ((msg->msg_name) && (msg->msg_namelen==sizeof(struct sockaddr_in))) {
        struct sockaddr_in *usin = (struct sockaddr_in*) msg->msg_name;

        if ((usin->sin_family!=AF_INET) && (usin->sin_family!=AF_UNSPEC))
            return -EINVAL;

        daddr = usin->sin_addr.s_addr;
        dport = usin->sin_port;
    } else {
        if (s->state != TCP_ESTABLISHED)
            return -ENOTCONN;

        daddr = s->prot.inet.daddr;
        dport = s->prot.inet.dport;
    }

#ifdef DEBUG
    rtos_print("sendmsg to %x:%d\n", ntohl(daddr), ntohs(dport));
#endif
    if ((daddr==0) || (dport==0))
        return -EINVAL;

    err = rt_ip_route_output(&rt, daddr, s->prot.inet.saddr);
    if (err)
        goto out;

    /* we found a route, remember the routing dest-addr could be the netmask */
    ufh.saddr     = rt->rt_src;
    ufh.daddr     = daddr;
    ufh.uh.source = s->prot.inet.sport;
    ufh.uh.dest   = dport;
    ufh.uh.len    = htons(ulen);
    ufh.uh.check  = 0;
    ufh.iov       = msg->msg_iov;
    ufh.iovlen    = msg->msg_iovlen;
    ufh.wcheck    = 0;

    err = rt_ip_build_xmit(s, rt_udp_getfrag, &ufh, ulen, rt, flags);

out:
    if (!err)
        return len;
    else
        return err;
}