udp.c (8a517c514d5893602cf85c1b4c47afbbc04d2198) udp.c (6ce9e7b5fe3195d1ae6e3a0753d4ddcac5cd699e)
1/*
2 * UDP over IPv6
3 * Linux INET6 implementation
4 *
5 * Authors:
6 * Pedro Roque <roque@di.fc.ul.pt>
7 *
8 * Based on linux/ipv4/udp.c

--- 624 unchanged lines hidden (view full) ---

633 udp_flush_pending_frames(sk);
634 else if (up->pending) {
635 up->len = 0;
636 up->pending = 0;
637 ip6_flush_pending_frames(sk);
638 }
639}
640
1/*
2 * UDP over IPv6
3 * Linux INET6 implementation
4 *
5 * Authors:
6 * Pedro Roque <roque@di.fc.ul.pt>
7 *
8 * Based on linux/ipv4/udp.c

--- 624 unchanged lines hidden (view full) ---

633 udp_flush_pending_frames(sk);
634 else if (up->pending) {
635 up->len = 0;
636 up->pending = 0;
637 ip6_flush_pending_frames(sk);
638 }
639}
640
641/**
642 * udp6_hwcsum_outgoing - handle outgoing HW checksumming
643 * @sk: socket we are sending on
644 * @skb: sk_buff containing the filled-in UDP header
645 * (checksum field must be zeroed out)
646 */
647static void udp6_hwcsum_outgoing(struct sock *sk, struct sk_buff *skb,
648 const struct in6_addr *saddr,
649 const struct in6_addr *daddr, int len)
650{
651 unsigned int offset;
652 struct udphdr *uh = udp_hdr(skb);
653 __wsum csum = 0;
654
655 if (skb_queue_len(&sk->sk_write_queue) == 1) {
656 /* Only one fragment on the socket. */
657 skb->csum_start = skb_transport_header(skb) - skb->head;
658 skb->csum_offset = offsetof(struct udphdr, check);
659 uh->check = ~csum_ipv6_magic(saddr, daddr, len, IPPROTO_UDP, 0);
660 } else {
661 /*
662 * HW-checksum won't work as there are two or more
663 * fragments on the socket so that all csums of sk_buffs
664 * should be together
665 */
666 offset = skb_transport_offset(skb);
667 skb->csum = skb_checksum(skb, offset, skb->len - offset, 0);
668
669 skb->ip_summed = CHECKSUM_NONE;
670
671 skb_queue_walk(&sk->sk_write_queue, skb) {
672 csum = csum_add(csum, skb->csum);
673 }
674
675 uh->check = csum_ipv6_magic(saddr, daddr, len, IPPROTO_UDP,
676 csum);
677 if (uh->check == 0)
678 uh->check = CSUM_MANGLED_0;
679 }
680}
681
641/*
642 * Sending
643 */
644
645static int udp_v6_push_pending_frames(struct sock *sk)
646{
647 struct sk_buff *skb;
648 struct udphdr *uh;

--- 14 unchanged lines hidden (view full) ---

663 uh = udp_hdr(skb);
664 uh->source = fl->fl_ip_sport;
665 uh->dest = fl->fl_ip_dport;
666 uh->len = htons(up->len);
667 uh->check = 0;
668
669 if (is_udplite)
670 csum = udplite_csum_outgoing(sk, skb);
682/*
683 * Sending
684 */
685
686static int udp_v6_push_pending_frames(struct sock *sk)
687{
688 struct sk_buff *skb;
689 struct udphdr *uh;

--- 14 unchanged lines hidden (view full) ---

704 uh = udp_hdr(skb);
705 uh->source = fl->fl_ip_sport;
706 uh->dest = fl->fl_ip_dport;
707 uh->len = htons(up->len);
708 uh->check = 0;
709
710 if (is_udplite)
711 csum = udplite_csum_outgoing(sk, skb);
671 else
712 else if (skb->ip_summed == CHECKSUM_PARTIAL) { /* UDP hardware csum */
713 udp6_hwcsum_outgoing(sk, skb, &fl->fl6_src, &fl->fl6_dst,
714 up->len);
715 goto send;
716 } else
672 csum = udp_csum_outgoing(sk, skb);
673
674 /* add protocol-dependent pseudo-header */
675 uh->check = csum_ipv6_magic(&fl->fl6_src, &fl->fl6_dst,
676 up->len, fl->proto, csum );
677 if (uh->check == 0)
678 uh->check = CSUM_MANGLED_0;
679
717 csum = udp_csum_outgoing(sk, skb);
718
719 /* add protocol-dependent pseudo-header */
720 uh->check = csum_ipv6_magic(&fl->fl6_src, &fl->fl6_dst,
721 up->len, fl->proto, csum );
722 if (uh->check == 0)
723 uh->check = CSUM_MANGLED_0;
724
725send:
680 err = ip6_push_pending_frames(sk);
726 err = ip6_push_pending_frames(sk);
727 if (err) {
728 if (err == -ENOBUFS && !inet6_sk(sk)->recverr) {
729 UDP6_INC_STATS_USER(sock_net(sk),
730 UDP_MIB_SNDBUFERRORS, is_udplite);
731 err = 0;
732 }
733 } else
734 UDP6_INC_STATS_USER(sock_net(sk),
735 UDP_MIB_OUTDATAGRAMS, is_udplite);
681out:
682 up->len = 0;
683 up->pending = 0;
736out:
737 up->len = 0;
738 up->pending = 0;
684 if (!err)
685 UDP6_INC_STATS_USER(sock_net(sk),
686 UDP_MIB_OUTDATAGRAMS, is_udplite);
687 return err;
688}
689
690int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk,
691 struct msghdr *msg, size_t len)
692{
693 struct ipv6_txoptions opt_space;
694 struct udp_sock *up = udp_sk(sk);

--- 200 unchanged lines hidden (view full) ---

895 if (ipv6_addr_is_multicast(&fl.fl6_dst))
896 hlimit = np->mcast_hops;
897 else
898 hlimit = np->hop_limit;
899 if (hlimit < 0)
900 hlimit = ip6_dst_hoplimit(dst);
901 }
902
739 return err;
740}
741
742int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk,
743 struct msghdr *msg, size_t len)
744{
745 struct ipv6_txoptions opt_space;
746 struct udp_sock *up = udp_sk(sk);

--- 200 unchanged lines hidden (view full) ---

947 if (ipv6_addr_is_multicast(&fl.fl6_dst))
948 hlimit = np->mcast_hops;
949 else
950 hlimit = np->hop_limit;
951 if (hlimit < 0)
952 hlimit = ip6_dst_hoplimit(dst);
953 }
954
903 if (tclass < 0) {
955 if (tclass < 0)
904 tclass = np->tclass;
956 tclass = np->tclass;
905 if (tclass < 0)
906 tclass = 0;
907 }
908
909 if (msg->msg_flags&MSG_CONFIRM)
910 goto do_confirm;
911back_from_confirm:
912
913 lock_sock(sk);
914 if (unlikely(up->pending)) {
915 /* The socket is already corked while preparing it. */

--- 111 unchanged lines hidden (view full) ---

1027 char __user *optval, int __user *optlen)
1028{
1029 if (level == SOL_UDP || level == SOL_UDPLITE)
1030 return udp_lib_getsockopt(sk, level, optname, optval, optlen);
1031 return compat_ipv6_getsockopt(sk, level, optname, optval, optlen);
1032}
1033#endif
1034
957
958 if (msg->msg_flags&MSG_CONFIRM)
959 goto do_confirm;
960back_from_confirm:
961
962 lock_sock(sk);
963 if (unlikely(up->pending)) {
964 /* The socket is already corked while preparing it. */

--- 111 unchanged lines hidden (view full) ---

1076 char __user *optval, int __user *optlen)
1077{
1078 if (level == SOL_UDP || level == SOL_UDPLITE)
1079 return udp_lib_getsockopt(sk, level, optname, optval, optlen);
1080 return compat_ipv6_getsockopt(sk, level, optname, optval, optlen);
1081}
1082#endif
1083
1084static int udp6_ufo_send_check(struct sk_buff *skb)
1085{
1086 struct ipv6hdr *ipv6h;
1087 struct udphdr *uh;
1088
1089 if (!pskb_may_pull(skb, sizeof(*uh)))
1090 return -EINVAL;
1091
1092 ipv6h = ipv6_hdr(skb);
1093 uh = udp_hdr(skb);
1094
1095 uh->check = ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, skb->len,
1096 IPPROTO_UDP, 0);
1097 skb->csum_start = skb_transport_header(skb) - skb->head;
1098 skb->csum_offset = offsetof(struct udphdr, check);
1099 skb->ip_summed = CHECKSUM_PARTIAL;
1100 return 0;
1101}
1102
1103static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, int features)
1104{
1105 struct sk_buff *segs = ERR_PTR(-EINVAL);
1106 unsigned int mss;
1107 unsigned int unfrag_ip6hlen, unfrag_len;
1108 struct frag_hdr *fptr;
1109 u8 *mac_start, *prevhdr;
1110 u8 nexthdr;
1111 u8 frag_hdr_sz = sizeof(struct frag_hdr);
1112 int offset;
1113 __wsum csum;
1114
1115 mss = skb_shinfo(skb)->gso_size;
1116 if (unlikely(skb->len <= mss))
1117 goto out;
1118
1119 if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) {
1120 /* Packet is from an untrusted source, reset gso_segs. */
1121 int type = skb_shinfo(skb)->gso_type;
1122
1123 if (unlikely(type & ~(SKB_GSO_UDP | SKB_GSO_DODGY) ||
1124 !(type & (SKB_GSO_UDP))))
1125 goto out;
1126
1127 skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(skb->len, mss);
1128
1129 segs = NULL;
1130 goto out;
1131 }
1132
1133 /* Do software UFO. Complete and fill in the UDP checksum as HW cannot
1134 * do checksum of UDP packets sent as multiple IP fragments.
1135 */
1136 offset = skb->csum_start - skb_headroom(skb);
1137 csum = skb_checksum(skb, offset, skb->len- offset, 0);
1138 offset += skb->csum_offset;
1139 *(__sum16 *)(skb->data + offset) = csum_fold(csum);
1140 skb->ip_summed = CHECKSUM_NONE;
1141
1142 /* Check if there is enough headroom to insert fragment header. */
1143 if ((skb_headroom(skb) < frag_hdr_sz) &&
1144 pskb_expand_head(skb, frag_hdr_sz, 0, GFP_ATOMIC))
1145 goto out;
1146
1147 /* Find the unfragmentable header and shift it left by frag_hdr_sz
1148 * bytes to insert fragment header.
1149 */
1150 unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr);
1151 nexthdr = *prevhdr;
1152 *prevhdr = NEXTHDR_FRAGMENT;
1153 unfrag_len = skb_network_header(skb) - skb_mac_header(skb) +
1154 unfrag_ip6hlen;
1155 mac_start = skb_mac_header(skb);
1156 memmove(mac_start-frag_hdr_sz, mac_start, unfrag_len);
1157
1158 skb->mac_header -= frag_hdr_sz;
1159 skb->network_header -= frag_hdr_sz;
1160
1161 fptr = (struct frag_hdr *)(skb_network_header(skb) + unfrag_ip6hlen);
1162 fptr->nexthdr = nexthdr;
1163 fptr->reserved = 0;
1164 ipv6_select_ident(fptr);
1165
1166 /* Fragment the skb. ipv6 header and the remaining fields of the
1167 * fragment header are updated in ipv6_gso_segment()
1168 */
1169 segs = skb_segment(skb, features);
1170
1171out:
1172 return segs;
1173}
1174
1035static struct inet6_protocol udpv6_protocol = {
1036 .handler = udpv6_rcv,
1037 .err_handler = udpv6_err,
1175static struct inet6_protocol udpv6_protocol = {
1176 .handler = udpv6_rcv,
1177 .err_handler = udpv6_err,
1178 .gso_send_check = udp6_ufo_send_check,
1179 .gso_segment = udp6_ufo_fragment,
1038 .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
1039};
1040
1041/* ------------------------------------------------------------------------ */
1042#ifdef CONFIG_PROC_FS
1043
1044static void udp6_sock_seq_show(struct seq_file *seq, struct sock *sp, int bucket)
1045{

--- 129 unchanged lines hidden ---
1180 .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
1181};
1182
1183/* ------------------------------------------------------------------------ */
1184#ifdef CONFIG_PROC_FS
1185
1186static void udp6_sock_seq_show(struct seq_file *seq, struct sock *sp, int bucket)
1187{

--- 129 unchanged lines hidden ---