/*** * 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__););
/*** * 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__););
/*** * 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; }
/*** * 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; }