aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGerrit Renker <gerrit@erg.abdn.ac.uk>2006-11-27 14:10:57 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2006-12-03 00:22:46 -0500
commitba4e58eca8aa9473b44fdfd312f26c4a2e7798b3 (patch)
tree700f8f989f48da480beb83b983637cfd2b5a3f67
parent6051e2f4fb68fc8e5343db58fa680ece376f405c (diff)
[NET]: Supporting UDP-Lite (RFC 3828) in Linux
This is a revision of the previously submitted patch, which alters the way files are organized and compiled in the following manner: * UDP and UDP-Lite now use separate object files * source file dependencies resolved via header files net/ipv{4,6}/udp_impl.h * order of inclusion files in udp.c/udplite.c adapted accordingly [NET/IPv4]: Support for the UDP-Lite protocol (RFC 3828) This patch adds support for UDP-Lite to the IPv4 stack, provided as an extension to the existing UDPv4 code: * generic routines are all located in net/ipv4/udp.c * UDP-Lite specific routines are in net/ipv4/udplite.c * MIB/statistics support in /proc/net/snmp and /proc/net/udplite * shared API with extensions for partial checksum coverage [NET/IPv6]: Extension for UDP-Lite over IPv6 It extends the existing UDPv6 code base with support for UDP-Lite in the same manner as per UDPv4. In particular, * UDPv6 generic and shared code is in net/ipv6/udp.c * UDP-Litev6 specific extensions are in net/ipv6/udplite.c * MIB/statistics support in /proc/net/snmp6 and /proc/net/udplite6 * support for IPV6_ADDRFORM * aligned the coding style of protocol initialisation with af_inet6.c * made the error handling in udpv6_queue_rcv_skb consistent; to return `-1' on error on all error cases * consolidation of shared code [NET]: UDP-Lite Documentation and basic XFRM/Netfilter support The UDP-Lite patch further provides * API documentation for UDP-Lite * basic xfrm support * basic netfilter support for IPv4 and IPv6 (LOG target) Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--Documentation/networking/udplite.txt281
-rw-r--r--include/linux/in.h1
-rw-r--r--include/linux/socket.h1
-rw-r--r--include/linux/udp.h12
-rw-r--r--include/net/ipv6.h12
-rw-r--r--include/net/transp_v6.h2
-rw-r--r--include/net/udp.h91
-rw-r--r--include/net/udplite.h149
-rw-r--r--include/net/xfrm.h2
-rw-r--r--net/ipv4/Makefile3
-rw-r--r--net/ipv4/af_inet.c8
-rw-r--r--net/ipv4/netfilter/ipt_LOG.c11
-rw-r--r--net/ipv4/proc.c13
-rw-r--r--net/ipv4/udp.c518
-rw-r--r--net/ipv4/udp_impl.h38
-rw-r--r--net/ipv4/udplite.c119
-rw-r--r--net/ipv4/xfrm4_policy.c1
-rw-r--r--net/ipv6/Makefile4
-rw-r--r--net/ipv6/af_inet6.c21
-rw-r--r--net/ipv6/ipv6_sockglue.c11
-rw-r--r--net/ipv6/netfilter/ip6t_LOG.c10
-rw-r--r--net/ipv6/proc.c11
-rw-r--r--net/ipv6/udp.c361
-rw-r--r--net/ipv6/udp_impl.h34
-rw-r--r--net/ipv6/udplite.c105
-rw-r--r--net/ipv6/xfrm6_policy.c1
-rw-r--r--net/netfilter/xt_multiport.c5
-rw-r--r--net/netfilter/xt_tcpudp.c20
28 files changed, 1442 insertions, 403 deletions
diff --git a/Documentation/networking/udplite.txt b/Documentation/networking/udplite.txt
new file mode 100644
index 000000000000..dd6f46b83dab
--- /dev/null
+++ b/Documentation/networking/udplite.txt
@@ -0,0 +1,281 @@
1 ===========================================================================
2 The UDP-Lite protocol (RFC 3828)
3 ===========================================================================
4
5
6 UDP-Lite is a Standards-Track IETF transport protocol whose characteristic
7 is a variable-length checksum. This has advantages for transport of multimedia
8 (video, VoIP) over wireless networks, as partly damaged packets can still be
9 fed into the codec instead of being discarded due to a failed checksum test.
10
11 This file briefly describes the existing kernel support and the socket API.
12 For in-depth information, you can consult:
13
14 o The UDP-Lite Homepage: http://www.erg.abdn.ac.uk/users/gerrit/udp-lite/
15 Fom here you can also download some example application source code.
16
17 o The UDP-Lite HOWTO on
18 http://www.erg.abdn.ac.uk/users/gerrit/udp-lite/files/UDP-Lite-HOWTO.txt
19
20 o The Wireshark UDP-Lite WiKi (with capture files):
21 http://wiki.wireshark.org/Lightweight_User_Datagram_Protocol
22
23 o The Protocol Spec, RFC 3828, http://www.ietf.org/rfc/rfc3828.txt
24
25
26 I) APPLICATIONS
27
28 Several applications have been ported successfully to UDP-Lite. Ethereal
29 (now called wireshark) has UDP-Litev4/v6 support by default. The tarball on
30
31 http://www.erg.abdn.ac.uk/users/gerrit/udp-lite/files/udplite_linux.tar.gz
32
33 has source code for several v4/v6 client-server and network testing examples.
34
35 Porting applications to UDP-Lite is straightforward: only socket level and
36 IPPROTO need to be changed; senders additionally set the checksum coverage
37 length (default = header length = 8). Details are in the next section.
38
39
40 II) PROGRAMMING API
41
42 UDP-Lite provides a connectionless, unreliable datagram service and hence
43 uses the same socket type as UDP. In fact, porting from UDP to UDP-Lite is
44 very easy: simply add `IPPROTO_UDPLITE' as the last argument of the socket(2)
45 call so that the statement looks like:
46
47 s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDPLITE);
48
49 or, respectively,
50
51 s = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDPLITE);
52
53 With just the above change you are able to run UDP-Lite services or connect
54 to UDP-Lite servers. The kernel will assume that you are not interested in
55 using partial checksum coverage and so emulate UDP mode (full coverage).
56
57 To make use of the partial checksum coverage facilities requires setting a
58 single socket option, which takes an integer specifying the coverage length:
59
60 * Sender checksum coverage: UDPLITE_SEND_CSCOV
61
62 For example,
63
64 int val = 20;
65 setsockopt(s, SOL_UDPLITE, UDPLITE_SEND_CSCOV, &val, sizeof(int));
66
67 sets the checksum coverage length to 20 bytes (12b data + 8b header).
68 Of each packet only the first 20 bytes (plus the pseudo-header) will be
69 checksummed. This is useful for RTP applications which have a 12-byte
70 base header.
71
72
73 * Receiver checksum coverage: UDPLITE_RECV_CSCOV
74
75 This option is the receiver-side analogue. It is truly optional, i.e. not
76 required to enable traffic with partial checksum coverage. Its function is
77 that of a traffic filter: when enabled, it instructs the kernel to drop
78 all packets which have a coverage _less_ than this value. For example, if
79 RTP and UDP headers are to be protected, a receiver can enforce that only
80 packets with a minimum coverage of 20 are admitted:
81
82 int min = 20;
83 setsockopt(s, SOL_UDPLITE, UDPLITE_RECV_CSCOV, &min, sizeof(int));
84
85 The calls to getsockopt(2) are analogous. Being an extension and not a stand-
86 alone protocol, all socket options known from UDP can be used in exactly the
87 same manner as before, e.g. UDP_CORK or UDP_ENCAP.
88
89 A detailed discussion of UDP-Lite checksum coverage options is in section IV.
90
91
92 III) HEADER FILES
93
94 The socket API requires support through header files in /usr/include:
95
96 * /usr/include/netinet/in.h
97 to define IPPROTO_UDPLITE
98
99 * /usr/include/netinet/udplite.h
100 for UDP-Lite header fields and protocol constants
101
102 For testing purposes, the following can serve as a `mini' header file:
103
104 #define IPPROTO_UDPLITE 136
105 #define SOL_UDPLITE 136
106 #define UDPLITE_SEND_CSCOV 10
107 #define UDPLITE_RECV_CSCOV 11
108
109 Ready-made header files for various distros are in the UDP-Lite tarball.
110
111
112 IV) KERNEL BEHAVIOUR WITH REGARD TO THE VARIOUS SOCKET OPTIONS
113
114 To enable debugging messages, the log level need to be set to 8, as most
115 messages use the KERN_DEBUG level (7).
116
117 1) Sender Socket Options
118
119 If the sender specifies a value of 0 as coverage length, the module
120 assumes full coverage, transmits a packet with coverage length of 0
121 and according checksum. If the sender specifies a coverage < 8 and
122 different from 0, the kernel assumes 8 as default value. Finally,
123 if the specified coverage length exceeds the packet length, the packet
124 length is used instead as coverage length.
125
126 2) Receiver Socket Options
127
128 The receiver specifies the minimum value of the coverage length it
129 is willing to accept. A value of 0 here indicates that the receiver
130 always wants the whole of the packet covered. In this case, all
131 partially covered packets are dropped and an error is logged.
132
133 It is not possible to specify illegal values (<0 and <8); in these
134 cases the default of 8 is assumed.
135
136 All packets arriving with a coverage value less than the specified
137 threshold are discarded, these events are also logged.
138
139 3) Disabling the Checksum Computation
140
141 On both sender and receiver, checksumming will always be performed
142 and can not be disabled using SO_NO_CHECK. Thus
143
144 setsockopt(sockfd, SOL_SOCKET, SO_NO_CHECK, ... );
145
146 will always will be ignored, while the value of
147
148 getsockopt(sockfd, SOL_SOCKET, SO_NO_CHECK, &value, ...);
149
150 is meaningless (as in TCP). Packets with a zero checksum field are
151 illegal (cf. RFC 3828, sec. 3.1) will be silently discarded.
152
153 4) Fragmentation
154
155 The checksum computation respects both buffersize and MTU. The size
156 of UDP-Lite packets is determined by the size of the send buffer. The
157 minimum size of the send buffer is 2048 (defined as SOCK_MIN_SNDBUF
158 in include/net/sock.h), the default value is configurable as
159 net.core.wmem_default or via setting the SO_SNDBUF socket(7)
160 option. The maximum upper bound for the send buffer is determined
161 by net.core.wmem_max.
162
163 Given a payload size larger than the send buffer size, UDP-Lite will
164 split the payload into several individual packets, filling up the
165 send buffer size in each case.
166
167 The precise value also depends on the interface MTU. The interface MTU,
168 in turn, may trigger IP fragmentation. In this case, the generated
169 UDP-Lite packet is split into several IP packets, of which only the
170 first one contains the L4 header.
171
172 The send buffer size has implications on the checksum coverage length.
173 Consider the following example:
174
175 Payload: 1536 bytes Send Buffer: 1024 bytes
176 MTU: 1500 bytes Coverage Length: 856 bytes
177
178 UDP-Lite will ship the 1536 bytes in two separate packets:
179
180 Packet 1: 1024 payload + 8 byte header + 20 byte IP header = 1052 bytes
181 Packet 2: 512 payload + 8 byte header + 20 byte IP header = 540 bytes
182
183 The coverage packet covers the UDP-Lite header and 848 bytes of the
184 payload in the first packet, the second packet is fully covered. Note
185 that for the second packet, the coverage length exceeds the packet
186 length. The kernel always re-adjusts the coverage length to the packet
187 length in such cases.
188
189 As an example of what happens when one UDP-Lite packet is split into
190 several tiny fragments, consider the following example.
191
192 Payload: 1024 bytes Send buffer size: 1024 bytes
193 MTU: 300 bytes Coverage length: 575 bytes
194
195 +-+-----------+--------------+--------------+--------------+
196 |8| 272 | 280 | 280 | 280 |
197 +-+-----------+--------------+--------------+--------------+
198 280 560 840 1032
199 ^
200 *****checksum coverage*************
201
202 The UDP-Lite module generates one 1032 byte packet (1024 + 8 byte
203 header). According to the interface MTU, these are split into 4 IP
204 packets (280 byte IP payload + 20 byte IP header). The kernel module
205 sums the contents of the entire first two packets, plus 15 bytes of
206 the last packet before releasing the fragments to the IP module.
207
208 To see the analogous case for IPv6 fragmentation, consider a link
209 MTU of 1280 bytes and a write buffer of 3356 bytes. If the checksum
210 coverage is less than 1232 bytes (MTU minus IPv6/fragment header
211 lengths), only the first fragment needs to be considered. When using
212 larger checksum coverage lengths, each eligible fragment needs to be
213 checksummed. Suppose we have a checksum coverage of 3062. The buffer
214 of 3356 bytes will be split into the following fragments:
215
216 Fragment 1: 1280 bytes carrying 1232 bytes of UDP-Lite data
217 Fragment 2: 1280 bytes carrying 1232 bytes of UDP-Lite data
218 Fragment 3: 948 bytes carrying 900 bytes of UDP-Lite data
219
220 The first two fragments have to be checksummed in full, of the last
221 fragment only 598 (= 3062 - 2*1232) bytes are checksummed.
222
223 While it is important that such cases are dealt with correctly, they
224 are (annoyingly) rare: UDP-Lite is designed for optimising multimedia
225 performance over wireless (or generally noisy) links and thus smaller
226 coverage lenghts are likely to be expected.
227
228
229 V) UDP-LITE RUNTIME STATISTICS AND THEIR MEANING
230
231 Exceptional and error conditions are logged to syslog at the KERN_DEBUG
232 level. Live statistics about UDP-Lite are available in /proc/net/snmp
233 and can (with newer versions of netstat) be viewed using
234
235 netstat -svu
236
237 This displays UDP-Lite statistics variables, whose meaning is as follows.
238
239 InDatagrams: Total number of received datagrams.
240
241 NoPorts: Number of packets received to an unknown port.
242 These cases are counted separately (not as InErrors).
243
244 InErrors: Number of erroneous UDP-Lite packets. Errors include:
245 * internal socket queue receive errors
246 * packet too short (less than 8 bytes or stated
247 coverage length exceeds received length)
248 * xfrm4_policy_check() returned with error
249 * application has specified larger min. coverage
250 length than that of incoming packet
251 * checksum coverage violated
252 * bad checksum
253
254 OutDatagrams: Total number of sent datagrams.
255
256 These statistics derive from the UDP MIB (RFC 2013).
257
258
259 VI) IPTABLES
260
261 There is packet match support for UDP-Lite as well as support for the LOG target.
262 If you copy and paste the following line into /etc/protcols,
263
264 udplite 136 UDP-Lite # UDP-Lite [RFC 3828]
265
266 then
267 iptables -A INPUT -p udplite -j LOG
268
269 will produce logging output to syslog. Dropping and rejecting packets also works.
270
271
272 VII) MAINTAINER ADDRESS
273
274 The UDP-Lite patch was developed at
275 University of Aberdeen
276 Electronics Research Group
277 Department of Engineering
278 Fraser Noble Building
279 Aberdeen AB24 3UE; UK
280 The current maintainer is Gerrit Renker, <gerrit@erg.abdn.ac.uk>. Initial
281 code was developed by William Stanislaus, <william@erg.abdn.ac.uk>.
diff --git a/include/linux/in.h b/include/linux/in.h
index 2619859f6e1b..1912e7c0bc26 100644
--- a/include/linux/in.h
+++ b/include/linux/in.h
@@ -45,6 +45,7 @@ enum {
45 45
46 IPPROTO_COMP = 108, /* Compression Header protocol */ 46 IPPROTO_COMP = 108, /* Compression Header protocol */
47 IPPROTO_SCTP = 132, /* Stream Control Transport Protocol */ 47 IPPROTO_SCTP = 132, /* Stream Control Transport Protocol */
48 IPPROTO_UDPLITE = 136, /* UDP-Lite (RFC 3828) */
48 49
49 IPPROTO_RAW = 255, /* Raw IP packets */ 50 IPPROTO_RAW = 255, /* Raw IP packets */
50 IPPROTO_MAX 51 IPPROTO_MAX
diff --git a/include/linux/socket.h b/include/linux/socket.h
index 361409094649..592b66679823 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -264,6 +264,7 @@ struct ucred {
264#define SOL_IPV6 41 264#define SOL_IPV6 41
265#define SOL_ICMPV6 58 265#define SOL_ICMPV6 58
266#define SOL_SCTP 132 266#define SOL_SCTP 132
267#define SOL_UDPLITE 136 /* UDP-Lite (RFC 3828) */
267#define SOL_RAW 255 268#define SOL_RAW 255
268#define SOL_IPX 256 269#define SOL_IPX 256
269#define SOL_AX25 257 270#define SOL_AX25 257
diff --git a/include/linux/udp.h b/include/linux/udp.h
index 014b41d1e308..564f3b050105 100644
--- a/include/linux/udp.h
+++ b/include/linux/udp.h
@@ -38,6 +38,7 @@ struct udphdr {
38#include <linux/types.h> 38#include <linux/types.h>
39 39
40#include <net/inet_sock.h> 40#include <net/inet_sock.h>
41#define UDP_HTABLE_SIZE 128
41 42
42struct udp_sock { 43struct udp_sock {
43 /* inet_sock has to be the first member */ 44 /* inet_sock has to be the first member */
@@ -50,12 +51,23 @@ struct udp_sock {
50 * when the socket is uncorked. 51 * when the socket is uncorked.
51 */ 52 */
52 __u16 len; /* total length of pending frames */ 53 __u16 len; /* total length of pending frames */
54 /*
55 * Fields specific to UDP-Lite.
56 */
57 __u16 pcslen;
58 __u16 pcrlen;
59/* indicator bits used by pcflag: */
60#define UDPLITE_BIT 0x1 /* set by udplite proto init function */
61#define UDPLITE_SEND_CC 0x2 /* set via udplite setsockopt */
62#define UDPLITE_RECV_CC 0x4 /* set via udplite setsocktopt */
63 __u8 pcflag; /* marks socket as UDP-Lite if > 0 */
53}; 64};
54 65
55static inline struct udp_sock *udp_sk(const struct sock *sk) 66static inline struct udp_sock *udp_sk(const struct sock *sk)
56{ 67{
57 return (struct udp_sock *)sk; 68 return (struct udp_sock *)sk;
58} 69}
70#define IS_UDPLITE(__sk) (udp_sk(__sk)->pcflag)
59 71
60#endif 72#endif
61 73
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 3c266ad99a02..9390649bbfec 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -158,9 +158,13 @@ DECLARE_SNMP_STAT(struct icmpv6_mib, icmpv6_statistics);
158 SNMP_INC_STATS_OFFSET_BH(icmpv6_statistics, field, _offset); \ 158 SNMP_INC_STATS_OFFSET_BH(icmpv6_statistics, field, _offset); \
159}) 159})
160DECLARE_SNMP_STAT(struct udp_mib, udp_stats_in6); 160DECLARE_SNMP_STAT(struct udp_mib, udp_stats_in6);
161#define UDP6_INC_STATS(field) SNMP_INC_STATS(udp_stats_in6, field) 161DECLARE_SNMP_STAT(struct udp_mib, udplite_stats_in6);
162#define UDP6_INC_STATS_BH(field) SNMP_INC_STATS_BH(udp_stats_in6, field) 162#define UDP6_INC_STATS_BH(field, is_udplite) do { \
163#define UDP6_INC_STATS_USER(field) SNMP_INC_STATS_USER(udp_stats_in6, field) 163 if (is_udplite) SNMP_INC_STATS_BH(udplite_stats_in6, field); \
164 else SNMP_INC_STATS_BH(udp_stats_in6, field); } while(0)
165#define UDP6_INC_STATS_USER(field, is_udplite) do { \
166 if (is_udplite) SNMP_INC_STATS_USER(udplite_stats_in6, field); \
167 else SNMP_INC_STATS_USER(udp_stats_in6, field); } while(0)
164 168
165int snmp6_register_dev(struct inet6_dev *idev); 169int snmp6_register_dev(struct inet6_dev *idev);
166int snmp6_unregister_dev(struct inet6_dev *idev); 170int snmp6_unregister_dev(struct inet6_dev *idev);
@@ -604,6 +608,8 @@ extern int tcp6_proc_init(void);
604extern void tcp6_proc_exit(void); 608extern void tcp6_proc_exit(void);
605extern int udp6_proc_init(void); 609extern int udp6_proc_init(void);
606extern void udp6_proc_exit(void); 610extern void udp6_proc_exit(void);
611extern int udplite6_proc_init(void);
612extern void udplite6_proc_exit(void);
607extern int ipv6_misc_proc_init(void); 613extern int ipv6_misc_proc_init(void);
608extern void ipv6_misc_proc_exit(void); 614extern void ipv6_misc_proc_exit(void);
609 615
diff --git a/include/net/transp_v6.h b/include/net/transp_v6.h
index 61f724c1036f..409da3a9a455 100644
--- a/include/net/transp_v6.h
+++ b/include/net/transp_v6.h
@@ -11,6 +11,7 @@
11 11
12extern struct proto rawv6_prot; 12extern struct proto rawv6_prot;
13extern struct proto udpv6_prot; 13extern struct proto udpv6_prot;
14extern struct proto udplitev6_prot;
14extern struct proto tcpv6_prot; 15extern struct proto tcpv6_prot;
15 16
16struct flowi; 17struct flowi;
@@ -24,6 +25,7 @@ extern void ipv6_destopt_init(void);
24/* transport protocols */ 25/* transport protocols */
25extern void rawv6_init(void); 26extern void rawv6_init(void);
26extern void udpv6_init(void); 27extern void udpv6_init(void);
28extern void udplitev6_init(void);
27extern void tcpv6_init(void); 29extern void tcpv6_init(void);
28 30
29extern int udpv6_connect(struct sock *sk, 31extern int udpv6_connect(struct sock *sk,
diff --git a/include/net/udp.h b/include/net/udp.h
index db0c05f67546..4f0626735ed3 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -26,9 +26,28 @@
26#include <net/inet_sock.h> 26#include <net/inet_sock.h>
27#include <net/sock.h> 27#include <net/sock.h>
28#include <net/snmp.h> 28#include <net/snmp.h>
29#include <net/ip.h>
30#include <linux/ipv6.h>
29#include <linux/seq_file.h> 31#include <linux/seq_file.h>
30 32
31#define UDP_HTABLE_SIZE 128 33/**
34 * struct udp_skb_cb - UDP(-Lite) private variables
35 *
36 * @header: private variables used by IPv4/IPv6
37 * @cscov: checksum coverage length (UDP-Lite only)
38 * @partial_cov: if set indicates partial csum coverage
39 */
40struct udp_skb_cb {
41 union {
42 struct inet_skb_parm h4;
43#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
44 struct inet6_skb_parm h6;
45#endif
46 } header;
47 __u16 cscov;
48 __u8 partial_cov;
49};
50#define UDP_SKB_CB(__skb) ((struct udp_skb_cb *)((__skb)->cb))
32 51
33extern struct hlist_head udp_hash[UDP_HTABLE_SIZE]; 52extern struct hlist_head udp_hash[UDP_HTABLE_SIZE];
34extern rwlock_t udp_hash_lock; 53extern rwlock_t udp_hash_lock;
@@ -47,6 +66,62 @@ extern struct proto udp_prot;
47 66
48struct sk_buff; 67struct sk_buff;
49 68
69/*
70 * Generic checksumming routines for UDP(-Lite) v4 and v6
71 */
72static inline u16 __udp_lib_checksum_complete(struct sk_buff *skb)
73{
74 if (! UDP_SKB_CB(skb)->partial_cov)
75 return __skb_checksum_complete(skb);
76 return csum_fold(skb_checksum(skb, 0, UDP_SKB_CB(skb)->cscov,
77 skb->csum));
78}
79
80static __inline__ int udp_lib_checksum_complete(struct sk_buff *skb)
81{
82 return skb->ip_summed != CHECKSUM_UNNECESSARY &&
83 __udp_lib_checksum_complete(skb);
84}
85
86/**
87 * udp_csum_outgoing - compute UDPv4/v6 checksum over fragments
88 * @sk: socket we are writing to
89 * @skb: sk_buff containing the filled-in UDP header
90 * (checksum field must be zeroed out)
91 */
92static inline u32 udp_csum_outgoing(struct sock *sk, struct sk_buff *skb)
93{
94 u32 csum = csum_partial(skb->h.raw, sizeof(struct udphdr), 0);
95
96 skb_queue_walk(&sk->sk_write_queue, skb) {
97 csum = csum_add(csum, skb->csum);
98 }
99 return csum;
100}
101
102/* hash routines shared between UDPv4/6 and UDP-Litev4/6 */
103static inline void udp_lib_hash(struct sock *sk)
104{
105 BUG();
106}
107
108static inline void udp_lib_unhash(struct sock *sk)
109{
110 write_lock_bh(&udp_hash_lock);
111 if (sk_del_node_init(sk)) {
112 inet_sk(sk)->num = 0;
113 sock_prot_dec_use(sk->sk_prot);
114 }
115 write_unlock_bh(&udp_hash_lock);
116}
117
118static inline void udp_lib_close(struct sock *sk, long timeout)
119{
120 sk_common_release(sk);
121}
122
123
124/* net/ipv4/udp.c */
50extern int udp_get_port(struct sock *sk, unsigned short snum, 125extern int udp_get_port(struct sock *sk, unsigned short snum,
51 int (*saddr_cmp)(const struct sock *, const struct sock *)); 126 int (*saddr_cmp)(const struct sock *, const struct sock *));
52extern void udp_err(struct sk_buff *, u32); 127extern void udp_err(struct sk_buff *, u32);
@@ -61,21 +136,29 @@ extern unsigned int udp_poll(struct file *file, struct socket *sock,
61 poll_table *wait); 136 poll_table *wait);
62 137
63DECLARE_SNMP_STAT(struct udp_mib, udp_statistics); 138DECLARE_SNMP_STAT(struct udp_mib, udp_statistics);
64#define UDP_INC_STATS(field) SNMP_INC_STATS(udp_statistics, field) 139/*
65#define UDP_INC_STATS_BH(field) SNMP_INC_STATS_BH(udp_statistics, field) 140 * SNMP statistics for UDP and UDP-Lite
66#define UDP_INC_STATS_USER(field) SNMP_INC_STATS_USER(udp_statistics, field) 141 */
142#define UDP_INC_STATS_USER(field, is_udplite) do { \
143 if (is_udplite) SNMP_INC_STATS_USER(udplite_statistics, field); \
144 else SNMP_INC_STATS_USER(udp_statistics, field); } while(0)
145#define UDP_INC_STATS_BH(field, is_udplite) do { \
146 if (is_udplite) SNMP_INC_STATS_BH(udplite_statistics, field); \
147 else SNMP_INC_STATS_BH(udp_statistics, field); } while(0)
67 148
68/* /proc */ 149/* /proc */
69struct udp_seq_afinfo { 150struct udp_seq_afinfo {
70 struct module *owner; 151 struct module *owner;
71 char *name; 152 char *name;
72 sa_family_t family; 153 sa_family_t family;
154 struct hlist_head *hashtable;
73 int (*seq_show) (struct seq_file *m, void *v); 155 int (*seq_show) (struct seq_file *m, void *v);
74 struct file_operations *seq_fops; 156 struct file_operations *seq_fops;
75}; 157};
76 158
77struct udp_iter_state { 159struct udp_iter_state {
78 sa_family_t family; 160 sa_family_t family;
161 struct hlist_head *hashtable;
79 int bucket; 162 int bucket;
80 struct seq_operations seq_ops; 163 struct seq_operations seq_ops;
81}; 164};
diff --git a/include/net/udplite.h b/include/net/udplite.h
new file mode 100644
index 000000000000..1473b3e49044
--- /dev/null
+++ b/include/net/udplite.h
@@ -0,0 +1,149 @@
1/*
2 * Definitions for the UDP-Lite (RFC 3828) code.
3 */
4#ifndef _UDPLITE_H
5#define _UDPLITE_H
6
7/* UDP-Lite socket options */
8#define UDPLITE_SEND_CSCOV 10 /* sender partial coverage (as sent) */
9#define UDPLITE_RECV_CSCOV 11 /* receiver partial coverage (threshold ) */
10
11extern struct proto udplite_prot;
12extern struct hlist_head udplite_hash[UDP_HTABLE_SIZE];
13
14/* UDP-Lite does not have a standardized MIB yet, so we inherit from UDP */
15DECLARE_SNMP_STAT(struct udp_mib, udplite_statistics);
16
17/*
18 * Checksum computation is all in software, hence simpler getfrag.
19 */
20static __inline__ int udplite_getfrag(void *from, char *to, int offset,
21 int len, int odd, struct sk_buff *skb)
22{
23 return memcpy_fromiovecend(to, (struct iovec *) from, offset, len);
24}
25
26/* Designate sk as UDP-Lite socket */
27static inline int udplite_sk_init(struct sock *sk)
28{
29 udp_sk(sk)->pcflag = UDPLITE_BIT;
30 return 0;
31}
32
33/*
34 * Checksumming routines
35 */
36static inline int udplite_checksum_init(struct sk_buff *skb, struct udphdr *uh)
37{
38 u16 cscov;
39
40 /* In UDPv4 a zero checksum means that the transmitter generated no
41 * checksum. UDP-Lite (like IPv6) mandates checksums, hence packets
42 * with a zero checksum field are illegal. */
43 if (uh->check == 0) {
44 LIMIT_NETDEBUG(KERN_DEBUG "UDPLITE: zeroed checksum field\n");
45 return 1;
46 }
47
48 UDP_SKB_CB(skb)->partial_cov = 0;
49 cscov = ntohs(uh->len);
50
51 if (cscov == 0) /* Indicates that full coverage is required. */
52 cscov = skb->len;
53 else if (cscov < 8 || cscov > skb->len) {
54 /*
55 * Coverage length violates RFC 3828: log and discard silently.
56 */
57 LIMIT_NETDEBUG(KERN_DEBUG "UDPLITE: bad csum coverage %d/%d\n",
58 cscov, skb->len);
59 return 1;
60
61 } else if (cscov < skb->len)
62 UDP_SKB_CB(skb)->partial_cov = 1;
63
64 UDP_SKB_CB(skb)->cscov = cscov;
65
66 /*
67 * There is no known NIC manufacturer supporting UDP-Lite yet,
68 * hence ip_summed is always (re-)set to CHECKSUM_NONE.
69 */
70 skb->ip_summed = CHECKSUM_NONE;
71
72 return 0;
73}
74
75static __inline__ int udplite4_csum_init(struct sk_buff *skb, struct udphdr *uh)
76{
77 int rc = udplite_checksum_init(skb, uh);
78
79 if (!rc)
80 skb->csum = csum_tcpudp_nofold(skb->nh.iph->saddr,
81 skb->nh.iph->daddr,
82 skb->len, IPPROTO_UDPLITE, 0);
83 return rc;
84}
85
86static __inline__ int udplite6_csum_init(struct sk_buff *skb, struct udphdr *uh)
87{
88 int rc = udplite_checksum_init(skb, uh);
89
90 if (!rc)
91 skb->csum = ~csum_ipv6_magic(&skb->nh.ipv6h->saddr,
92 &skb->nh.ipv6h->daddr,
93 skb->len, IPPROTO_UDPLITE, 0);
94 return rc;
95}
96
97static inline int udplite_sender_cscov(struct udp_sock *up, struct udphdr *uh)
98{
99 int cscov = up->len;
100
101 /*
102 * Sender has set `partial coverage' option on UDP-Lite socket
103 */
104 if (up->pcflag & UDPLITE_SEND_CC) {
105 if (up->pcslen < up->len) {
106 /* up->pcslen == 0 means that full coverage is required,
107 * partial coverage only if 0 < up->pcslen < up->len */
108 if (0 < up->pcslen) {
109 cscov = up->pcslen;
110 }
111 uh->len = htons(up->pcslen);
112 }
113 /*
114 * NOTE: Causes for the error case `up->pcslen > up->len':
115 * (i) Application error (will not be penalized).
116 * (ii) Payload too big for send buffer: data is split
117 * into several packets, each with its own header.
118 * In this case (e.g. last segment), coverage may
119 * exceed packet length.
120 * Since packets with coverage length > packet length are
121 * illegal, we fall back to the defaults here.
122 */
123 }
124 return cscov;
125}
126
127static inline u32 udplite_csum_outgoing(struct sock *sk, struct sk_buff *skb)
128{
129 u32 csum = 0;
130 int off, len, cscov = udplite_sender_cscov(udp_sk(sk), skb->h.uh);
131
132 skb->ip_summed = CHECKSUM_NONE; /* no HW support for checksumming */
133
134 skb_queue_walk(&sk->sk_write_queue, skb) {
135 off = skb->h.raw - skb->data;
136 len = skb->len - off;
137
138 csum = skb_checksum(skb, off, (cscov > len)? len : cscov, csum);
139
140 if ((cscov -= len) <= 0)
141 break;
142 }
143 return csum;
144}
145
146extern void udplite4_register(void);
147extern int udplite_get_port(struct sock *sk, unsigned short snum,
148 int (*scmp)(const struct sock *, const struct sock *));
149#endif /* _UDPLITE_H */
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 81c91e8a328f..3878a88ff618 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -468,6 +468,7 @@ __be16 xfrm_flowi_sport(struct flowi *fl)
468 switch(fl->proto) { 468 switch(fl->proto) {
469 case IPPROTO_TCP: 469 case IPPROTO_TCP:
470 case IPPROTO_UDP: 470 case IPPROTO_UDP:
471 case IPPROTO_UDPLITE:
471 case IPPROTO_SCTP: 472 case IPPROTO_SCTP:
472 port = fl->fl_ip_sport; 473 port = fl->fl_ip_sport;
473 break; 474 break;
@@ -493,6 +494,7 @@ __be16 xfrm_flowi_dport(struct flowi *fl)
493 switch(fl->proto) { 494 switch(fl->proto) {
494 case IPPROTO_TCP: 495 case IPPROTO_TCP:
495 case IPPROTO_UDP: 496 case IPPROTO_UDP:
497 case IPPROTO_UDPLITE:
496 case IPPROTO_SCTP: 498 case IPPROTO_SCTP:
497 port = fl->fl_ip_dport; 499 port = fl->fl_ip_dport;
498 break; 500 break;
diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile
index 15645c51520c..7a068626feea 100644
--- a/net/ipv4/Makefile
+++ b/net/ipv4/Makefile
@@ -8,7 +8,8 @@ obj-y := route.o inetpeer.o protocol.o \
8 inet_timewait_sock.o inet_connection_sock.o \ 8 inet_timewait_sock.o inet_connection_sock.o \
9 tcp.o tcp_input.o tcp_output.o tcp_timer.o tcp_ipv4.o \ 9 tcp.o tcp_input.o tcp_output.o tcp_timer.o tcp_ipv4.o \
10 tcp_minisocks.o tcp_cong.o \ 10 tcp_minisocks.o tcp_cong.o \
11 datagram.o raw.o udp.o arp.o icmp.o devinet.o af_inet.o igmp.o \ 11 datagram.o raw.o udp.o udplite.o \
12 arp.o icmp.o devinet.o af_inet.o igmp.o \
12 sysctl_net_ipv4.o fib_frontend.o fib_semantics.o 13 sysctl_net_ipv4.o fib_frontend.o fib_semantics.o
13 14
14obj-$(CONFIG_IP_FIB_HASH) += fib_hash.o 15obj-$(CONFIG_IP_FIB_HASH) += fib_hash.o
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 4a81d54a7569..8db39f7e3bf0 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -104,6 +104,7 @@
104#include <net/inet_connection_sock.h> 104#include <net/inet_connection_sock.h>
105#include <net/tcp.h> 105#include <net/tcp.h>
106#include <net/udp.h> 106#include <net/udp.h>
107#include <net/udplite.h>
107#include <linux/skbuff.h> 108#include <linux/skbuff.h>
108#include <net/sock.h> 109#include <net/sock.h>
109#include <net/raw.h> 110#include <net/raw.h>
@@ -1223,10 +1224,13 @@ static int __init init_ipv4_mibs(void)
1223 tcp_statistics[1] = alloc_percpu(struct tcp_mib); 1224 tcp_statistics[1] = alloc_percpu(struct tcp_mib);
1224 udp_statistics[0] = alloc_percpu(struct udp_mib); 1225 udp_statistics[0] = alloc_percpu(struct udp_mib);
1225 udp_statistics[1] = alloc_percpu(struct udp_mib); 1226 udp_statistics[1] = alloc_percpu(struct udp_mib);
1227 udplite_statistics[0] = alloc_percpu(struct udp_mib);
1228 udplite_statistics[1] = alloc_percpu(struct udp_mib);
1226 if (! 1229 if (!
1227 (net_statistics[0] && net_statistics[1] && ip_statistics[0] 1230 (net_statistics[0] && net_statistics[1] && ip_statistics[0]
1228 && ip_statistics[1] && tcp_statistics[0] && tcp_statistics[1] 1231 && ip_statistics[1] && tcp_statistics[0] && tcp_statistics[1]
1229 && udp_statistics[0] && udp_statistics[1])) 1232 && udp_statistics[0] && udp_statistics[1]
1233 && udplite_statistics[0] && udplite_statistics[1] ) )
1230 return -ENOMEM; 1234 return -ENOMEM;
1231 1235
1232 (void) tcp_mib_init(); 1236 (void) tcp_mib_init();
@@ -1313,6 +1317,8 @@ static int __init inet_init(void)
1313 /* Setup TCP slab cache for open requests. */ 1317 /* Setup TCP slab cache for open requests. */
1314 tcp_init(); 1318 tcp_init();
1315 1319
1320 /* Add UDP-Lite (RFC 3828) */
1321 udplite4_register();
1316 1322
1317 /* 1323 /*
1318 * Set the ICMP layer up 1324 * Set the ICMP layer up
diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c
index 7dc820df8bc5..46eee64a11f6 100644
--- a/net/ipv4/netfilter/ipt_LOG.c
+++ b/net/ipv4/netfilter/ipt_LOG.c
@@ -171,11 +171,15 @@ static void dump_packet(const struct nf_loginfo *info,
171 } 171 }
172 break; 172 break;
173 } 173 }
174 case IPPROTO_UDP: { 174 case IPPROTO_UDP:
175 case IPPROTO_UDPLITE: {
175 struct udphdr _udph, *uh; 176 struct udphdr _udph, *uh;
176 177
177 /* Max length: 10 "PROTO=UDP " */ 178 if (ih->protocol == IPPROTO_UDP)
178 printk("PROTO=UDP "); 179 /* Max length: 10 "PROTO=UDP " */
180 printk("PROTO=UDP " );
181 else /* Max length: 14 "PROTO=UDPLITE " */
182 printk("PROTO=UDPLITE ");
179 183
180 if (ntohs(ih->frag_off) & IP_OFFSET) 184 if (ntohs(ih->frag_off) & IP_OFFSET)
181 break; 185 break;
@@ -341,6 +345,7 @@ static void dump_packet(const struct nf_loginfo *info,
341 /* IP: 40+46+6+11+127 = 230 */ 345 /* IP: 40+46+6+11+127 = 230 */
342 /* TCP: 10+max(25,20+30+13+9+32+11+127) = 252 */ 346 /* TCP: 10+max(25,20+30+13+9+32+11+127) = 252 */
343 /* UDP: 10+max(25,20) = 35 */ 347 /* UDP: 10+max(25,20) = 35 */
348 /* UDPLITE: 14+max(25,20) = 39 */
344 /* ICMP: 11+max(25, 18+25+max(19,14,24+3+n+10,3+n+10)) = 91+n */ 349 /* ICMP: 11+max(25, 18+25+max(19,14,24+3+n+10,3+n+10)) = 91+n */
345 /* ESP: 10+max(25)+15 = 50 */ 350 /* ESP: 10+max(25)+15 = 50 */
346 /* AH: 9+max(25)+15 = 49 */ 351 /* AH: 9+max(25)+15 = 49 */
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
index 9c6cbe3d9fb8..cd873da54cbe 100644
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -38,6 +38,7 @@
38#include <net/protocol.h> 38#include <net/protocol.h>
39#include <net/tcp.h> 39#include <net/tcp.h>
40#include <net/udp.h> 40#include <net/udp.h>
41#include <net/udplite.h>
41#include <linux/inetdevice.h> 42#include <linux/inetdevice.h>
42#include <linux/proc_fs.h> 43#include <linux/proc_fs.h>
43#include <linux/seq_file.h> 44#include <linux/seq_file.h>
@@ -66,6 +67,7 @@ static int sockstat_seq_show(struct seq_file *seq, void *v)
66 tcp_death_row.tw_count, atomic_read(&tcp_sockets_allocated), 67 tcp_death_row.tw_count, atomic_read(&tcp_sockets_allocated),
67 atomic_read(&tcp_memory_allocated)); 68 atomic_read(&tcp_memory_allocated));
68 seq_printf(seq, "UDP: inuse %d\n", fold_prot_inuse(&udp_prot)); 69 seq_printf(seq, "UDP: inuse %d\n", fold_prot_inuse(&udp_prot));
70 seq_printf(seq, "UDPLITE: inuse %d\n", fold_prot_inuse(&udplite_prot));
69 seq_printf(seq, "RAW: inuse %d\n", fold_prot_inuse(&raw_prot)); 71 seq_printf(seq, "RAW: inuse %d\n", fold_prot_inuse(&raw_prot));
70 seq_printf(seq, "FRAG: inuse %d memory %d\n", ip_frag_nqueues, 72 seq_printf(seq, "FRAG: inuse %d memory %d\n", ip_frag_nqueues,
71 atomic_read(&ip_frag_mem)); 73 atomic_read(&ip_frag_mem));
@@ -304,6 +306,17 @@ static int snmp_seq_show(struct seq_file *seq, void *v)
304 fold_field((void **) udp_statistics, 306 fold_field((void **) udp_statistics,
305 snmp4_udp_list[i].entry)); 307 snmp4_udp_list[i].entry));
306 308
309 /* the UDP and UDP-Lite MIBs are the same */
310 seq_puts(seq, "\nUdpLite:");
311 for (i = 0; snmp4_udp_list[i].name != NULL; i++)
312 seq_printf(seq, " %s", snmp4_udp_list[i].name);
313
314 seq_puts(seq, "\nUdpLite:");
315 for (i = 0; snmp4_udp_list[i].name != NULL; i++)
316 seq_printf(seq, " %lu",
317 fold_field((void **) udplite_statistics,
318 snmp4_udp_list[i].entry) );
319
307 seq_putc(seq, '\n'); 320 seq_putc(seq, '\n');
308 return 0; 321 return 0;
309} 322}
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 9e1bd374875e..98ba75096175 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -92,22 +92,16 @@
92#include <linux/timer.h> 92#include <linux/timer.h>
93#include <linux/mm.h> 93#include <linux/mm.h>
94#include <linux/inet.h> 94#include <linux/inet.h>
95#include <linux/ipv6.h>
96#include <linux/netdevice.h> 95#include <linux/netdevice.h>
97#include <net/snmp.h>
98#include <net/ip.h>
99#include <net/tcp_states.h> 96#include <net/tcp_states.h>
100#include <net/protocol.h>
101#include <linux/skbuff.h> 97#include <linux/skbuff.h>
102#include <linux/proc_fs.h> 98#include <linux/proc_fs.h>
103#include <linux/seq_file.h> 99#include <linux/seq_file.h>
104#include <net/sock.h>
105#include <net/udp.h>
106#include <net/icmp.h> 100#include <net/icmp.h>
107#include <net/route.h> 101#include <net/route.h>
108#include <net/inet_common.h>
109#include <net/checksum.h> 102#include <net/checksum.h>
110#include <net/xfrm.h> 103#include <net/xfrm.h>
104#include "udp_impl.h"
111 105
112/* 106/*
113 * Snmp MIB for the UDP layer 107 * Snmp MIB for the UDP layer
@@ -120,26 +114,30 @@ DEFINE_RWLOCK(udp_hash_lock);
120 114
121static int udp_port_rover; 115static int udp_port_rover;
122 116
123static inline int udp_lport_inuse(u16 num) 117static inline int __udp_lib_lport_inuse(__be16 num, struct hlist_head udptable[])
124{ 118{
125 struct sock *sk; 119 struct sock *sk;
126 struct hlist_node *node; 120 struct hlist_node *node;
127 121
128 sk_for_each(sk, node, &udp_hash[num & (UDP_HTABLE_SIZE - 1)]) 122 sk_for_each(sk, node, &udptable[num & (UDP_HTABLE_SIZE - 1)])
129 if (inet_sk(sk)->num == num) 123 if (inet_sk(sk)->num == num)
130 return 1; 124 return 1;
131 return 0; 125 return 0;
132} 126}
133 127
134/** 128/**
135 * udp_get_port - common port lookup for IPv4 and IPv6 129 * __udp_lib_get_port - UDP/-Lite port lookup for IPv4 and IPv6
136 * 130 *
137 * @sk: socket struct in question 131 * @sk: socket struct in question
138 * @snum: port number to look up 132 * @snum: port number to look up
133 * @udptable: hash list table, must be of UDP_HTABLE_SIZE
134 * @port_rover: pointer to record of last unallocated port
139 * @saddr_comp: AF-dependent comparison of bound local IP addresses 135 * @saddr_comp: AF-dependent comparison of bound local IP addresses
140 */ 136 */
141int udp_get_port(struct sock *sk, unsigned short snum, 137int __udp_lib_get_port(struct sock *sk, unsigned short snum,
142 int (*saddr_cmp)(const struct sock *sk1, const struct sock *sk2)) 138 struct hlist_head udptable[], int *port_rover,
139 int (*saddr_comp)(const struct sock *sk1,
140 const struct sock *sk2 ) )
143{ 141{
144 struct hlist_node *node; 142 struct hlist_node *node;
145 struct hlist_head *head; 143 struct hlist_head *head;
@@ -150,15 +148,15 @@ int udp_get_port(struct sock *sk, unsigned short snum,
150 if (snum == 0) { 148 if (snum == 0) {
151 int best_size_so_far, best, result, i; 149 int best_size_so_far, best, result, i;
152 150
153 if (udp_port_rover > sysctl_local_port_range[1] || 151 if (*port_rover > sysctl_local_port_range[1] ||
154 udp_port_rover < sysctl_local_port_range[0]) 152 *port_rover < sysctl_local_port_range[0])
155 udp_port_rover = sysctl_local_port_range[0]; 153 *port_rover = sysctl_local_port_range[0];
156 best_size_so_far = 32767; 154 best_size_so_far = 32767;
157 best = result = udp_port_rover; 155 best = result = *port_rover;
158 for (i = 0; i < UDP_HTABLE_SIZE; i++, result++) { 156 for (i = 0; i < UDP_HTABLE_SIZE; i++, result++) {
159 int size; 157 int size;
160 158
161 head = &udp_hash[result & (UDP_HTABLE_SIZE - 1)]; 159 head = &udptable[result & (UDP_HTABLE_SIZE - 1)];
162 if (hlist_empty(head)) { 160 if (hlist_empty(head)) {
163 if (result > sysctl_local_port_range[1]) 161 if (result > sysctl_local_port_range[1])
164 result = sysctl_local_port_range[0] + 162 result = sysctl_local_port_range[0] +
@@ -179,15 +177,15 @@ int udp_get_port(struct sock *sk, unsigned short snum,
179 result = sysctl_local_port_range[0] 177 result = sysctl_local_port_range[0]
180 + ((result - sysctl_local_port_range[0]) & 178 + ((result - sysctl_local_port_range[0]) &
181 (UDP_HTABLE_SIZE - 1)); 179 (UDP_HTABLE_SIZE - 1));
182 if (!udp_lport_inuse(result)) 180 if (! __udp_lib_lport_inuse(result, udptable))
183 break; 181 break;
184 } 182 }
185 if (i >= (1 << 16) / UDP_HTABLE_SIZE) 183 if (i >= (1 << 16) / UDP_HTABLE_SIZE)
186 goto fail; 184 goto fail;
187gotit: 185gotit:
188 udp_port_rover = snum = result; 186 *port_rover = snum = result;
189 } else { 187 } else {
190 head = &udp_hash[snum & (UDP_HTABLE_SIZE - 1)]; 188 head = &udptable[snum & (UDP_HTABLE_SIZE - 1)];
191 189
192 sk_for_each(sk2, node, head) 190 sk_for_each(sk2, node, head)
193 if (inet_sk(sk2)->num == snum && 191 if (inet_sk(sk2)->num == snum &&
@@ -195,12 +193,12 @@ gotit:
195 (!sk2->sk_reuse || !sk->sk_reuse) && 193 (!sk2->sk_reuse || !sk->sk_reuse) &&
196 (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if 194 (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if
197 || sk2->sk_bound_dev_if == sk->sk_bound_dev_if) && 195 || sk2->sk_bound_dev_if == sk->sk_bound_dev_if) &&
198 (*saddr_cmp)(sk, sk2) ) 196 (*saddr_comp)(sk, sk2) )
199 goto fail; 197 goto fail;
200 } 198 }
201 inet_sk(sk)->num = snum; 199 inet_sk(sk)->num = snum;
202 if (sk_unhashed(sk)) { 200 if (sk_unhashed(sk)) {
203 head = &udp_hash[snum & (UDP_HTABLE_SIZE - 1)]; 201 head = &udptable[snum & (UDP_HTABLE_SIZE - 1)];
204 sk_add_node(sk, head); 202 sk_add_node(sk, head);
205 sock_prot_inc_use(sk->sk_prot); 203 sock_prot_inc_use(sk->sk_prot);
206 } 204 }
@@ -210,7 +208,13 @@ fail:
210 return error; 208 return error;
211} 209}
212 210
213static inline int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2) 211__inline__ int udp_get_port(struct sock *sk, unsigned short snum,
212 int (*scmp)(const struct sock *, const struct sock *))
213{
214 return __udp_lib_get_port(sk, snum, udp_hash, &udp_port_rover, scmp);
215}
216
217inline int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2)
214{ 218{
215 struct inet_sock *inet1 = inet_sk(sk1), *inet2 = inet_sk(sk2); 219 struct inet_sock *inet1 = inet_sk(sk1), *inet2 = inet_sk(sk2);
216 220
@@ -224,34 +228,20 @@ static inline int udp_v4_get_port(struct sock *sk, unsigned short snum)
224 return udp_get_port(sk, snum, ipv4_rcv_saddr_equal); 228 return udp_get_port(sk, snum, ipv4_rcv_saddr_equal);
225} 229}
226 230
227
228static void udp_v4_hash(struct sock *sk)
229{
230 BUG();
231}
232
233static void udp_v4_unhash(struct sock *sk)
234{
235 write_lock_bh(&udp_hash_lock);
236 if (sk_del_node_init(sk)) {
237 inet_sk(sk)->num = 0;
238 sock_prot_dec_use(sk->sk_prot);
239 }
240 write_unlock_bh(&udp_hash_lock);
241}
242
243/* UDP is nearly always wildcards out the wazoo, it makes no sense to try 231/* UDP is nearly always wildcards out the wazoo, it makes no sense to try
244 * harder than this. -DaveM 232 * harder than this. -DaveM
245 */ 233 */
246static struct sock *udp_v4_lookup_longway(__be32 saddr, __be16 sport, 234static struct sock *__udp4_lib_lookup(__be32 saddr, __be16 sport,
247 __be32 daddr, __be16 dport, int dif) 235 __be32 daddr, __be16 dport,
236 int dif, struct hlist_head udptable[])
248{ 237{
249 struct sock *sk, *result = NULL; 238 struct sock *sk, *result = NULL;
250 struct hlist_node *node; 239 struct hlist_node *node;
251 unsigned short hnum = ntohs(dport); 240 unsigned short hnum = ntohs(dport);
252 int badness = -1; 241 int badness = -1;
253 242
254 sk_for_each(sk, node, &udp_hash[hnum & (UDP_HTABLE_SIZE - 1)]) { 243 read_lock(&udp_hash_lock);
244 sk_for_each(sk, node, &udptable[hnum & (UDP_HTABLE_SIZE - 1)]) {
255 struct inet_sock *inet = inet_sk(sk); 245 struct inet_sock *inet = inet_sk(sk);
256 246
257 if (inet->num == hnum && !ipv6_only_sock(sk)) { 247 if (inet->num == hnum && !ipv6_only_sock(sk)) {
@@ -285,20 +275,10 @@ static struct sock *udp_v4_lookup_longway(__be32 saddr, __be16 sport,
285 } 275 }
286 } 276 }
287 } 277 }
288 return result; 278 if (result)
289} 279 sock_hold(result);
290
291static __inline__ struct sock *udp_v4_lookup(__be32 saddr, __be16 sport,
292 __be32 daddr, __be16 dport, int dif)
293{
294 struct sock *sk;
295
296 read_lock(&udp_hash_lock);
297 sk = udp_v4_lookup_longway(saddr, sport, daddr, dport, dif);
298 if (sk)
299 sock_hold(sk);
300 read_unlock(&udp_hash_lock); 280 read_unlock(&udp_hash_lock);
301 return sk; 281 return result;
302} 282}
303 283
304static inline struct sock *udp_v4_mcast_next(struct sock *sk, 284static inline struct sock *udp_v4_mcast_next(struct sock *sk,
@@ -340,7 +320,7 @@ found:
340 * to find the appropriate port. 320 * to find the appropriate port.
341 */ 321 */
342 322
343void udp_err(struct sk_buff *skb, u32 info) 323void __udp4_lib_err(struct sk_buff *skb, u32 info, struct hlist_head udptable[])
344{ 324{
345 struct inet_sock *inet; 325 struct inet_sock *inet;
346 struct iphdr *iph = (struct iphdr*)skb->data; 326 struct iphdr *iph = (struct iphdr*)skb->data;
@@ -351,7 +331,8 @@ void udp_err(struct sk_buff *skb, u32 info)
351 int harderr; 331 int harderr;
352 int err; 332 int err;
353 333
354 sk = udp_v4_lookup(iph->daddr, uh->dest, iph->saddr, uh->source, skb->dev->ifindex); 334 sk = __udp4_lib_lookup(iph->daddr, uh->dest, iph->saddr, uh->source,
335 skb->dev->ifindex, udptable );
355 if (sk == NULL) { 336 if (sk == NULL) {
356 ICMP_INC_STATS_BH(ICMP_MIB_INERRORS); 337 ICMP_INC_STATS_BH(ICMP_MIB_INERRORS);
357 return; /* No socket for error */ 338 return; /* No socket for error */
@@ -405,6 +386,11 @@ out:
405 sock_put(sk); 386 sock_put(sk);
406} 387}
407 388
389__inline__ void udp_err(struct sk_buff *skb, u32 info)
390{
391 return __udp4_lib_err(skb, info, udp_hash);
392}
393
408/* 394/*
409 * Throw away all pending data and cancel the corking. Socket is locked. 395 * Throw away all pending data and cancel the corking. Socket is locked.
410 */ 396 */
@@ -419,16 +405,56 @@ static void udp_flush_pending_frames(struct sock *sk)
419 } 405 }
420} 406}
421 407
408/**
409 * udp4_hwcsum_outgoing - handle outgoing HW checksumming
410 * @sk: socket we are sending on
411 * @skb: sk_buff containing the filled-in UDP header
412 * (checksum field must be zeroed out)
413 */
414static void udp4_hwcsum_outgoing(struct sock *sk, struct sk_buff *skb,
415 __be32 src, __be32 dst, int len )
416{
417 unsigned int csum = 0, offset;
418 struct udphdr *uh = skb->h.uh;
419
420 if (skb_queue_len(&sk->sk_write_queue) == 1) {
421 /*
422 * Only one fragment on the socket.
423 */
424 skb->csum = offsetof(struct udphdr, check);
425 uh->check = ~csum_tcpudp_magic(src, dst, len, IPPROTO_UDP, 0);
426 } else {
427 /*
428 * HW-checksum won't work as there are two or more
429 * fragments on the socket so that all csums of sk_buffs
430 * should be together
431 */
432 offset = skb->h.raw - skb->data;
433 skb->csum = skb_checksum(skb, offset, skb->len - offset, 0);
434
435 skb->ip_summed = CHECKSUM_NONE;
436
437 skb_queue_walk(&sk->sk_write_queue, skb) {
438 csum = csum_add(csum, skb->csum);
439 }
440
441 uh->check = csum_tcpudp_magic(src, dst, len, IPPROTO_UDP, csum);
442 if (uh->check == 0)
443 uh->check = -1;
444 }
445}
446
422/* 447/*
423 * Push out all pending data as one UDP datagram. Socket is locked. 448 * Push out all pending data as one UDP datagram. Socket is locked.
424 */ 449 */
425static int udp_push_pending_frames(struct sock *sk, struct udp_sock *up) 450int udp_push_pending_frames(struct sock *sk, struct udp_sock *up)
426{ 451{
427 struct inet_sock *inet = inet_sk(sk); 452 struct inet_sock *inet = inet_sk(sk);
428 struct flowi *fl = &inet->cork.fl; 453 struct flowi *fl = &inet->cork.fl;
429 struct sk_buff *skb; 454 struct sk_buff *skb;
430 struct udphdr *uh; 455 struct udphdr *uh;
431 int err = 0; 456 int err = 0;
457 u32 csum = 0;
432 458
433 /* Grab the skbuff where UDP header space exists. */ 459 /* Grab the skbuff where UDP header space exists. */
434 if ((skb = skb_peek(&sk->sk_write_queue)) == NULL) 460 if ((skb = skb_peek(&sk->sk_write_queue)) == NULL)
@@ -443,52 +469,28 @@ static int udp_push_pending_frames(struct sock *sk, struct udp_sock *up)
443 uh->len = htons(up->len); 469 uh->len = htons(up->len);
444 uh->check = 0; 470 uh->check = 0;
445 471
446 if (sk->sk_no_check == UDP_CSUM_NOXMIT) { 472 if (up->pcflag) /* UDP-Lite */
473 csum = udplite_csum_outgoing(sk, skb);
474
475 else if (sk->sk_no_check == UDP_CSUM_NOXMIT) { /* UDP csum disabled */
476
447 skb->ip_summed = CHECKSUM_NONE; 477 skb->ip_summed = CHECKSUM_NONE;
448 goto send; 478 goto send;
449 }
450 479
451 if (skb_queue_len(&sk->sk_write_queue) == 1) { 480 } else if (skb->ip_summed == CHECKSUM_PARTIAL) { /* UDP hardware csum */
452 /*
453 * Only one fragment on the socket.
454 */
455 if (skb->ip_summed == CHECKSUM_PARTIAL) {
456 skb->csum = offsetof(struct udphdr, check);
457 uh->check = ~csum_tcpudp_magic(fl->fl4_src, fl->fl4_dst,
458 up->len, IPPROTO_UDP, 0);
459 } else {
460 skb->csum = csum_partial((char *)uh,
461 sizeof(struct udphdr), skb->csum);
462 uh->check = csum_tcpudp_magic(fl->fl4_src, fl->fl4_dst,
463 up->len, IPPROTO_UDP, skb->csum);
464 if (uh->check == 0)
465 uh->check = -1;
466 }
467 } else {
468 unsigned int csum = 0;
469 /*
470 * HW-checksum won't work as there are two or more
471 * fragments on the socket so that all csums of sk_buffs
472 * should be together.
473 */
474 if (skb->ip_summed == CHECKSUM_PARTIAL) {
475 int offset = (unsigned char *)uh - skb->data;
476 skb->csum = skb_checksum(skb, offset, skb->len - offset, 0);
477 481
478 skb->ip_summed = CHECKSUM_NONE; 482 udp4_hwcsum_outgoing(sk, skb, fl->fl4_src,fl->fl4_dst, up->len);
479 } else { 483 goto send;
480 skb->csum = csum_partial((char *)uh, 484
481 sizeof(struct udphdr), skb->csum); 485 } else /* `normal' UDP */
482 } 486 csum = udp_csum_outgoing(sk, skb);
487
488 /* add protocol-dependent pseudo-header */
489 uh->check = csum_tcpudp_magic(fl->fl4_src, fl->fl4_dst, up->len,
490 sk->sk_protocol, csum );
491 if (uh->check == 0)
492 uh->check = -1;
483 493
484 skb_queue_walk(&sk->sk_write_queue, skb) {
485 csum = csum_add(csum, skb->csum);
486 }
487 uh->check = csum_tcpudp_magic(fl->fl4_src, fl->fl4_dst,
488 up->len, IPPROTO_UDP, csum);
489 if (uh->check == 0)
490 uh->check = -1;
491 }
492send: 494send:
493 err = ip_push_pending_frames(sk); 495 err = ip_push_pending_frames(sk);
494out: 496out:
@@ -497,12 +499,6 @@ out:
497 return err; 499 return err;
498} 500}
499 501
500
501static unsigned short udp_check(struct udphdr *uh, int len, __be32 saddr, __be32 daddr, unsigned long base)
502{
503 return(csum_tcpudp_magic(saddr, daddr, len, IPPROTO_UDP, base));
504}
505
506int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, 502int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
507 size_t len) 503 size_t len)
508{ 504{
@@ -516,8 +512,9 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
516 __be32 daddr, faddr, saddr; 512 __be32 daddr, faddr, saddr;
517 __be16 dport; 513 __be16 dport;
518 u8 tos; 514 u8 tos;
519 int err; 515 int err, is_udplite = up->pcflag;
520 int corkreq = up->corkflag || msg->msg_flags&MSG_MORE; 516 int corkreq = up->corkflag || msg->msg_flags&MSG_MORE;
517 int (*getfrag)(void *, char *, int, int, int, struct sk_buff *);
521 518
522 if (len > 0xFFFF) 519 if (len > 0xFFFF)
523 return -EMSGSIZE; 520 return -EMSGSIZE;
@@ -622,7 +619,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
622 { .daddr = faddr, 619 { .daddr = faddr,
623 .saddr = saddr, 620 .saddr = saddr,
624 .tos = tos } }, 621 .tos = tos } },
625 .proto = IPPROTO_UDP, 622 .proto = sk->sk_protocol,
626 .uli_u = { .ports = 623 .uli_u = { .ports =
627 { .sport = inet->sport, 624 { .sport = inet->sport,
628 .dport = dport } } }; 625 .dport = dport } } };
@@ -668,8 +665,9 @@ back_from_confirm:
668 665
669do_append_data: 666do_append_data:
670 up->len += ulen; 667 up->len += ulen;
671 err = ip_append_data(sk, ip_generic_getfrag, msg->msg_iov, ulen, 668 getfrag = is_udplite ? udplite_getfrag : ip_generic_getfrag;
672 sizeof(struct udphdr), &ipc, rt, 669 err = ip_append_data(sk, getfrag, msg->msg_iov, ulen,
670 sizeof(struct udphdr), &ipc, rt,
673 corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags); 671 corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags);
674 if (err) 672 if (err)
675 udp_flush_pending_frames(sk); 673 udp_flush_pending_frames(sk);
@@ -684,7 +682,7 @@ out:
684 if (free) 682 if (free)
685 kfree(ipc.opt); 683 kfree(ipc.opt);
686 if (!err) { 684 if (!err) {
687 UDP_INC_STATS_USER(UDP_MIB_OUTDATAGRAMS); 685 UDP_INC_STATS_USER(UDP_MIB_OUTDATAGRAMS, is_udplite);
688 return len; 686 return len;
689 } 687 }
690 /* 688 /*
@@ -695,7 +693,7 @@ out:
695 * seems like overkill. 693 * seems like overkill.
696 */ 694 */
697 if (err == -ENOBUFS || test_bit(SOCK_NOSPACE, &sk->sk_socket->flags)) { 695 if (err == -ENOBUFS || test_bit(SOCK_NOSPACE, &sk->sk_socket->flags)) {
698 UDP_INC_STATS_USER(UDP_MIB_SNDBUFERRORS); 696 UDP_INC_STATS_USER(UDP_MIB_SNDBUFERRORS, is_udplite);
699 } 697 }
700 return err; 698 return err;
701 699
@@ -707,8 +705,8 @@ do_confirm:
707 goto out; 705 goto out;
708} 706}
709 707
710static int udp_sendpage(struct sock *sk, struct page *page, int offset, 708int udp_sendpage(struct sock *sk, struct page *page, int offset,
711 size_t size, int flags) 709 size_t size, int flags)
712{ 710{
713 struct udp_sock *up = udp_sk(sk); 711 struct udp_sock *up = udp_sk(sk);
714 int ret; 712 int ret;
@@ -795,29 +793,18 @@ int udp_ioctl(struct sock *sk, int cmd, unsigned long arg)
795 return(0); 793 return(0);
796} 794}
797 795
798static __inline__ int __udp_checksum_complete(struct sk_buff *skb)
799{
800 return __skb_checksum_complete(skb);
801}
802
803static __inline__ int udp_checksum_complete(struct sk_buff *skb)
804{
805 return skb->ip_summed != CHECKSUM_UNNECESSARY &&
806 __udp_checksum_complete(skb);
807}
808
809/* 796/*
810 * This should be easy, if there is something there we 797 * This should be easy, if there is something there we
811 * return it, otherwise we block. 798 * return it, otherwise we block.
812 */ 799 */
813 800
814static int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, 801int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
815 size_t len, int noblock, int flags, int *addr_len) 802 size_t len, int noblock, int flags, int *addr_len)
816{ 803{
817 struct inet_sock *inet = inet_sk(sk); 804 struct inet_sock *inet = inet_sk(sk);
818 struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name; 805 struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name;
819 struct sk_buff *skb; 806 struct sk_buff *skb;
820 int copied, err; 807 int copied, err, copy_only, is_udplite = IS_UDPLITE(sk);
821 808
822 /* 809 /*
823 * Check any passed addresses 810 * Check any passed addresses
@@ -839,15 +826,25 @@ try_again:
839 msg->msg_flags |= MSG_TRUNC; 826 msg->msg_flags |= MSG_TRUNC;
840 } 827 }
841 828
842 if (skb->ip_summed==CHECKSUM_UNNECESSARY) { 829 /*
843 err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov, 830 * Decide whether to checksum and/or copy data.
844 copied); 831 *
845 } else if (msg->msg_flags&MSG_TRUNC) { 832 * UDP: checksum may have been computed in HW,
846 if (__udp_checksum_complete(skb)) 833 * (re-)compute it if message is truncated.
834 * UDP-Lite: always needs to checksum, no HW support.
835 */
836 copy_only = (skb->ip_summed==CHECKSUM_UNNECESSARY);
837
838 if (is_udplite || (!copy_only && msg->msg_flags&MSG_TRUNC)) {
839 if (__udp_lib_checksum_complete(skb))
847 goto csum_copy_err; 840 goto csum_copy_err;
848 err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov, 841 copy_only = 1;
849 copied); 842 }
850 } else { 843
844 if (copy_only)
845 err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr),
846 msg->msg_iov, copied );
847 else {
851 err = skb_copy_and_csum_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov); 848 err = skb_copy_and_csum_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov);
852 849
853 if (err == -EINVAL) 850 if (err == -EINVAL)
@@ -880,7 +877,7 @@ out:
880 return err; 877 return err;
881 878
882csum_copy_err: 879csum_copy_err:
883 UDP_INC_STATS_BH(UDP_MIB_INERRORS); 880 UDP_INC_STATS_BH(UDP_MIB_INERRORS, is_udplite);
884 881
885 skb_kill_datagram(sk, skb, flags); 882 skb_kill_datagram(sk, skb, flags);
886 883
@@ -912,11 +909,6 @@ int udp_disconnect(struct sock *sk, int flags)
912 return 0; 909 return 0;
913} 910}
914 911
915static void udp_close(struct sock *sk, long timeout)
916{
917 sk_common_release(sk);
918}
919
920/* return: 912/* return:
921 * 1 if the the UDP system should process it 913 * 1 if the the UDP system should process it
922 * 0 if we should drop this packet 914 * 0 if we should drop this packet
@@ -1022,7 +1014,7 @@ static int udp_encap_rcv(struct sock * sk, struct sk_buff *skb)
1022 * Note that in the success and error cases, the skb is assumed to 1014 * Note that in the success and error cases, the skb is assumed to
1023 * have either been requeued or freed. 1015 * have either been requeued or freed.
1024 */ 1016 */
1025static int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) 1017int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
1026{ 1018{
1027 struct udp_sock *up = udp_sk(sk); 1019 struct udp_sock *up = udp_sk(sk);
1028 int rc; 1020 int rc;
@@ -1030,10 +1022,8 @@ static int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
1030 /* 1022 /*
1031 * Charge it to the socket, dropping if the queue is full. 1023 * Charge it to the socket, dropping if the queue is full.
1032 */ 1024 */
1033 if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb)) { 1025 if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))
1034 kfree_skb(skb); 1026 goto drop;
1035 return -1;
1036 }
1037 nf_reset(skb); 1027 nf_reset(skb);
1038 1028
1039 if (up->encap_type) { 1029 if (up->encap_type) {
@@ -1057,31 +1047,68 @@ static int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
1057 if (ret < 0) { 1047 if (ret < 0) {
1058 /* process the ESP packet */ 1048 /* process the ESP packet */
1059 ret = xfrm4_rcv_encap(skb, up->encap_type); 1049 ret = xfrm4_rcv_encap(skb, up->encap_type);
1060 UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS); 1050 UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS, up->pcflag);
1061 return -ret; 1051 return -ret;
1062 } 1052 }
1063 /* FALLTHROUGH -- it's a UDP Packet */ 1053 /* FALLTHROUGH -- it's a UDP Packet */
1064 } 1054 }
1065 1055
1066 if (sk->sk_filter && skb->ip_summed != CHECKSUM_UNNECESSARY) { 1056 /*
1067 if (__udp_checksum_complete(skb)) { 1057 * UDP-Lite specific tests, ignored on UDP sockets
1068 UDP_INC_STATS_BH(UDP_MIB_INERRORS); 1058 */
1069 kfree_skb(skb); 1059 if ((up->pcflag & UDPLITE_RECV_CC) && UDP_SKB_CB(skb)->partial_cov) {
1070 return -1; 1060
1061 /*
1062 * MIB statistics other than incrementing the error count are
1063 * disabled for the following two types of errors: these depend
1064 * on the application settings, not on the functioning of the
1065 * protocol stack as such.
1066 *
1067 * RFC 3828 here recommends (sec 3.3): "There should also be a
1068 * way ... to ... at least let the receiving application block
1069 * delivery of packets with coverage values less than a value
1070 * provided by the application."
1071 */
1072 if (up->pcrlen == 0) { /* full coverage was set */
1073 LIMIT_NETDEBUG(KERN_WARNING "UDPLITE: partial coverage "
1074 "%d while full coverage %d requested\n",
1075 UDP_SKB_CB(skb)->cscov, skb->len);
1076 goto drop;
1071 } 1077 }
1078 /* The next case involves violating the min. coverage requested
1079 * by the receiver. This is subtle: if receiver wants x and x is
1080 * greater than the buffersize/MTU then receiver will complain
1081 * that it wants x while sender emits packets of smaller size y.
1082 * Therefore the above ...()->partial_cov statement is essential.
1083 */
1084 if (UDP_SKB_CB(skb)->cscov < up->pcrlen) {
1085 LIMIT_NETDEBUG(KERN_WARNING
1086 "UDPLITE: coverage %d too small, need min %d\n",
1087 UDP_SKB_CB(skb)->cscov, up->pcrlen);
1088 goto drop;
1089 }
1090 }
1091
1092 if (sk->sk_filter && skb->ip_summed != CHECKSUM_UNNECESSARY) {
1093 if (__udp_lib_checksum_complete(skb))
1094 goto drop;
1072 skb->ip_summed = CHECKSUM_UNNECESSARY; 1095 skb->ip_summed = CHECKSUM_UNNECESSARY;
1073 } 1096 }
1074 1097
1075 if ((rc = sock_queue_rcv_skb(sk,skb)) < 0) { 1098 if ((rc = sock_queue_rcv_skb(sk,skb)) < 0) {
1076 /* Note that an ENOMEM error is charged twice */ 1099 /* Note that an ENOMEM error is charged twice */
1077 if (rc == -ENOMEM) 1100 if (rc == -ENOMEM)
1078 UDP_INC_STATS_BH(UDP_MIB_RCVBUFERRORS); 1101 UDP_INC_STATS_BH(UDP_MIB_RCVBUFERRORS, up->pcflag);
1079 UDP_INC_STATS_BH(UDP_MIB_INERRORS); 1102 goto drop;
1080 kfree_skb(skb);
1081 return -1;
1082 } 1103 }
1083 UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS); 1104
1105 UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS, up->pcflag);
1084 return 0; 1106 return 0;
1107
1108drop:
1109 UDP_INC_STATS_BH(UDP_MIB_INERRORS, up->pcflag);
1110 kfree_skb(skb);
1111 return -1;
1085} 1112}
1086 1113
1087/* 1114/*
@@ -1090,14 +1117,16 @@ static int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
1090 * Note: called only from the BH handler context, 1117 * Note: called only from the BH handler context,
1091 * so we don't need to lock the hashes. 1118 * so we don't need to lock the hashes.
1092 */ 1119 */
1093static int udp_v4_mcast_deliver(struct sk_buff *skb, struct udphdr *uh, 1120static int __udp4_lib_mcast_deliver(struct sk_buff *skb,
1094 __be32 saddr, __be32 daddr) 1121 struct udphdr *uh,
1122 __be32 saddr, __be32 daddr,
1123 struct hlist_head udptable[])
1095{ 1124{
1096 struct sock *sk; 1125 struct sock *sk;
1097 int dif; 1126 int dif;
1098 1127
1099 read_lock(&udp_hash_lock); 1128 read_lock(&udp_hash_lock);
1100 sk = sk_head(&udp_hash[ntohs(uh->dest) & (UDP_HTABLE_SIZE - 1)]); 1129 sk = sk_head(&udptable[ntohs(uh->dest) & (UDP_HTABLE_SIZE - 1)]);
1101 dif = skb->dev->ifindex; 1130 dif = skb->dev->ifindex;
1102 sk = udp_v4_mcast_next(sk, uh->dest, daddr, uh->source, saddr, dif); 1131 sk = udp_v4_mcast_next(sk, uh->dest, daddr, uh->source, saddr, dif);
1103 if (sk) { 1132 if (sk) {
@@ -1131,65 +1160,75 @@ static int udp_v4_mcast_deliver(struct sk_buff *skb, struct udphdr *uh,
1131 * Otherwise, csum completion requires chacksumming packet body, 1160 * Otherwise, csum completion requires chacksumming packet body,
1132 * including udp header and folding it to skb->csum. 1161 * including udp header and folding it to skb->csum.
1133 */ 1162 */
1134static void udp_checksum_init(struct sk_buff *skb, struct udphdr *uh, 1163static inline void udp4_csum_init(struct sk_buff *skb, struct udphdr *uh)
1135 unsigned short ulen, __be32 saddr, __be32 daddr)
1136{ 1164{
1137 if (uh->check == 0) { 1165 if (uh->check == 0) {
1138 skb->ip_summed = CHECKSUM_UNNECESSARY; 1166 skb->ip_summed = CHECKSUM_UNNECESSARY;
1139 } else if (skb->ip_summed == CHECKSUM_COMPLETE) { 1167 } else if (skb->ip_summed == CHECKSUM_COMPLETE) {
1140 if (!udp_check(uh, ulen, saddr, daddr, skb->csum)) 1168 if (!csum_tcpudp_magic(skb->nh.iph->saddr, skb->nh.iph->daddr,
1169 skb->len, IPPROTO_UDP, skb->csum ))
1141 skb->ip_summed = CHECKSUM_UNNECESSARY; 1170 skb->ip_summed = CHECKSUM_UNNECESSARY;
1142 } 1171 }
1143 if (skb->ip_summed != CHECKSUM_UNNECESSARY) 1172 if (skb->ip_summed != CHECKSUM_UNNECESSARY)
1144 skb->csum = csum_tcpudp_nofold(saddr, daddr, ulen, IPPROTO_UDP, 0); 1173 skb->csum = csum_tcpudp_nofold(skb->nh.iph->saddr,
1174 skb->nh.iph->daddr,
1175 skb->len, IPPROTO_UDP, 0);
1145 /* Probably, we should checksum udp header (it should be in cache 1176 /* Probably, we should checksum udp header (it should be in cache
1146 * in any case) and data in tiny packets (< rx copybreak). 1177 * in any case) and data in tiny packets (< rx copybreak).
1147 */ 1178 */
1179
1180 /* UDP = UDP-Lite with a non-partial checksum coverage */
1181 UDP_SKB_CB(skb)->partial_cov = 0;
1148} 1182}
1149 1183
1150/* 1184/*
1151 * All we need to do is get the socket, and then do a checksum. 1185 * All we need to do is get the socket, and then do a checksum.
1152 */ 1186 */
1153 1187
1154int udp_rcv(struct sk_buff *skb) 1188int __udp4_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[],
1189 int is_udplite)
1155{ 1190{
1156 struct sock *sk; 1191 struct sock *sk;
1157 struct udphdr *uh; 1192 struct udphdr *uh = skb->h.uh;
1158 unsigned short ulen; 1193 unsigned short ulen;
1159 struct rtable *rt = (struct rtable*)skb->dst; 1194 struct rtable *rt = (struct rtable*)skb->dst;
1160 __be32 saddr = skb->nh.iph->saddr; 1195 __be32 saddr = skb->nh.iph->saddr;
1161 __be32 daddr = skb->nh.iph->daddr; 1196 __be32 daddr = skb->nh.iph->daddr;
1162 int len = skb->len;
1163 1197
1164 /* 1198 /*
1165 * Validate the packet and the UDP length. 1199 * Validate the packet.
1166 */ 1200 */
1167 if (!pskb_may_pull(skb, sizeof(struct udphdr))) 1201 if (!pskb_may_pull(skb, sizeof(struct udphdr)))
1168 goto no_header; 1202 goto drop; /* No space for header. */
1169
1170 uh = skb->h.uh;
1171 1203
1172 ulen = ntohs(uh->len); 1204 ulen = ntohs(uh->len);
1173 1205 if (ulen > skb->len)
1174 if (ulen > len || ulen < sizeof(*uh))
1175 goto short_packet; 1206 goto short_packet;
1176 1207
1177 if (pskb_trim_rcsum(skb, ulen)) 1208 if(! is_udplite ) { /* UDP validates ulen. */
1178 goto short_packet; 1209
1210 if (ulen < sizeof(*uh) || pskb_trim_rcsum(skb, ulen))
1211 goto short_packet;
1179 1212
1180 udp_checksum_init(skb, uh, ulen, saddr, daddr); 1213 udp4_csum_init(skb, uh);
1214
1215 } else { /* UDP-Lite validates cscov. */
1216 if (udplite4_csum_init(skb, uh))
1217 goto csum_error;
1218 }
1181 1219
1182 if(rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST)) 1220 if(rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST))
1183 return udp_v4_mcast_deliver(skb, uh, saddr, daddr); 1221 return __udp4_lib_mcast_deliver(skb, uh, saddr, daddr, udptable);
1184 1222
1185 sk = udp_v4_lookup(saddr, uh->source, daddr, uh->dest, skb->dev->ifindex); 1223 sk = __udp4_lib_lookup(saddr, uh->source, daddr, uh->dest,
1224 skb->dev->ifindex, udptable );
1186 1225
1187 if (sk != NULL) { 1226 if (sk != NULL) {
1188 int ret = udp_queue_rcv_skb(sk, skb); 1227 int ret = udp_queue_rcv_skb(sk, skb);
1189 sock_put(sk); 1228 sock_put(sk);
1190 1229
1191 /* a return value > 0 means to resubmit the input, but 1230 /* a return value > 0 means to resubmit the input, but
1192 * it it wants the return to be -protocol, or 0 1231 * it wants the return to be -protocol, or 0
1193 */ 1232 */
1194 if (ret > 0) 1233 if (ret > 0)
1195 return -ret; 1234 return -ret;
@@ -1201,10 +1240,10 @@ int udp_rcv(struct sk_buff *skb)
1201 nf_reset(skb); 1240 nf_reset(skb);
1202 1241
1203 /* No socket. Drop packet silently, if checksum is wrong */ 1242 /* No socket. Drop packet silently, if checksum is wrong */
1204 if (udp_checksum_complete(skb)) 1243 if (udp_lib_checksum_complete(skb))
1205 goto csum_error; 1244 goto csum_error;
1206 1245
1207 UDP_INC_STATS_BH(UDP_MIB_NOPORTS); 1246 UDP_INC_STATS_BH(UDP_MIB_NOPORTS, is_udplite);
1208 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); 1247 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
1209 1248
1210 /* 1249 /*
@@ -1215,36 +1254,40 @@ int udp_rcv(struct sk_buff *skb)
1215 return(0); 1254 return(0);
1216 1255
1217short_packet: 1256short_packet:
1218 LIMIT_NETDEBUG(KERN_DEBUG "UDP: short packet: From %u.%u.%u.%u:%u %d/%d to %u.%u.%u.%u:%u\n", 1257 LIMIT_NETDEBUG(KERN_DEBUG "UDP%s: short packet: From %u.%u.%u.%u:%u %d/%d to %u.%u.%u.%u:%u\n",
1258 is_udplite? "-Lite" : "",
1219 NIPQUAD(saddr), 1259 NIPQUAD(saddr),
1220 ntohs(uh->source), 1260 ntohs(uh->source),
1221 ulen, 1261 ulen,
1222 len, 1262 skb->len,
1223 NIPQUAD(daddr), 1263 NIPQUAD(daddr),
1224 ntohs(uh->dest)); 1264 ntohs(uh->dest));
1225no_header: 1265 goto drop;
1226 UDP_INC_STATS_BH(UDP_MIB_INERRORS);
1227 kfree_skb(skb);
1228 return(0);
1229 1266
1230csum_error: 1267csum_error:
1231 /* 1268 /*
1232 * RFC1122: OK. Discards the bad packet silently (as far as 1269 * RFC1122: OK. Discards the bad packet silently (as far as
1233 * the network is concerned, anyway) as per 4.1.3.4 (MUST). 1270 * the network is concerned, anyway) as per 4.1.3.4 (MUST).
1234 */ 1271 */
1235 LIMIT_NETDEBUG(KERN_DEBUG "UDP: bad checksum. From %d.%d.%d.%d:%d to %d.%d.%d.%d:%d ulen %d\n", 1272 LIMIT_NETDEBUG(KERN_DEBUG "UDP%s: bad checksum. From %d.%d.%d.%d:%d to %d.%d.%d.%d:%d ulen %d\n",
1273 is_udplite? "-Lite" : "",
1236 NIPQUAD(saddr), 1274 NIPQUAD(saddr),
1237 ntohs(uh->source), 1275 ntohs(uh->source),
1238 NIPQUAD(daddr), 1276 NIPQUAD(daddr),
1239 ntohs(uh->dest), 1277 ntohs(uh->dest),
1240 ulen); 1278 ulen);
1241drop: 1279drop:
1242 UDP_INC_STATS_BH(UDP_MIB_INERRORS); 1280 UDP_INC_STATS_BH(UDP_MIB_INERRORS, is_udplite);
1243 kfree_skb(skb); 1281 kfree_skb(skb);
1244 return(0); 1282 return(0);
1245} 1283}
1246 1284
1247static int udp_destroy_sock(struct sock *sk) 1285__inline__ int udp_rcv(struct sk_buff *skb)
1286{
1287 return __udp4_lib_rcv(skb, udp_hash, 0);
1288}
1289
1290int udp_destroy_sock(struct sock *sk)
1248{ 1291{
1249 lock_sock(sk); 1292 lock_sock(sk);
1250 udp_flush_pending_frames(sk); 1293 udp_flush_pending_frames(sk);
@@ -1293,6 +1336,32 @@ static int do_udp_setsockopt(struct sock *sk, int level, int optname,
1293 } 1336 }
1294 break; 1337 break;
1295 1338
1339 /*
1340 * UDP-Lite's partial checksum coverage (RFC 3828).
1341 */
1342 /* The sender sets actual checksum coverage length via this option.
1343 * The case coverage > packet length is handled by send module. */
1344 case UDPLITE_SEND_CSCOV:
1345 if (!up->pcflag) /* Disable the option on UDP sockets */
1346 return -ENOPROTOOPT;
1347 if (val != 0 && val < 8) /* Illegal coverage: use default (8) */
1348 val = 8;
1349 up->pcslen = val;
1350 up->pcflag |= UDPLITE_SEND_CC;
1351 break;
1352
1353 /* The receiver specifies a minimum checksum coverage value. To make
1354 * sense, this should be set to at least 8 (as done below). If zero is
1355 * used, this again means full checksum coverage. */
1356 case UDPLITE_RECV_CSCOV:
1357 if (!up->pcflag) /* Disable the option on UDP sockets */
1358 return -ENOPROTOOPT;
1359 if (val != 0 && val < 8) /* Avoid silly minimal values. */
1360 val = 8;
1361 up->pcrlen = val;
1362 up->pcflag |= UDPLITE_RECV_CC;
1363 break;
1364
1296 default: 1365 default:
1297 err = -ENOPROTOOPT; 1366 err = -ENOPROTOOPT;
1298 break; 1367 break;
@@ -1301,21 +1370,21 @@ static int do_udp_setsockopt(struct sock *sk, int level, int optname,
1301 return err; 1370 return err;
1302} 1371}
1303 1372
1304static int udp_setsockopt(struct sock *sk, int level, int optname, 1373int udp_setsockopt(struct sock *sk, int level, int optname,
1305 char __user *optval, int optlen) 1374 char __user *optval, int optlen)
1306{ 1375{
1307 if (level != SOL_UDP) 1376 if (level == SOL_UDP || level == SOL_UDPLITE)
1308 return ip_setsockopt(sk, level, optname, optval, optlen); 1377 return do_udp_setsockopt(sk, level, optname, optval, optlen);
1309 return do_udp_setsockopt(sk, level, optname, optval, optlen); 1378 return ip_setsockopt(sk, level, optname, optval, optlen);
1310} 1379}
1311 1380
1312#ifdef CONFIG_COMPAT 1381#ifdef CONFIG_COMPAT
1313static int compat_udp_setsockopt(struct sock *sk, int level, int optname, 1382int compat_udp_setsockopt(struct sock *sk, int level, int optname,
1314 char __user *optval, int optlen) 1383 char __user *optval, int optlen)
1315{ 1384{
1316 if (level != SOL_UDP) 1385 if (level == SOL_UDP || level == SOL_UDPLITE)
1317 return compat_ip_setsockopt(sk, level, optname, optval, optlen); 1386 return do_udp_setsockopt(sk, level, optname, optval, optlen);
1318 return do_udp_setsockopt(sk, level, optname, optval, optlen); 1387 return compat_ip_setsockopt(sk, level, optname, optval, optlen);
1319} 1388}
1320#endif 1389#endif
1321 1390
@@ -1342,6 +1411,16 @@ static int do_udp_getsockopt(struct sock *sk, int level, int optname,
1342 val = up->encap_type; 1411 val = up->encap_type;
1343 break; 1412 break;
1344 1413
1414 /* The following two cannot be changed on UDP sockets, the return is
1415 * always 0 (which corresponds to the full checksum coverage of UDP). */
1416 case UDPLITE_SEND_CSCOV:
1417 val = up->pcslen;
1418 break;
1419
1420 case UDPLITE_RECV_CSCOV:
1421 val = up->pcrlen;
1422 break;
1423
1345 default: 1424 default:
1346 return -ENOPROTOOPT; 1425 return -ENOPROTOOPT;
1347 }; 1426 };
@@ -1353,21 +1432,21 @@ static int do_udp_getsockopt(struct sock *sk, int level, int optname,
1353 return 0; 1432 return 0;
1354} 1433}
1355 1434
1356static int udp_getsockopt(struct sock *sk, int level, int optname, 1435int udp_getsockopt(struct sock *sk, int level, int optname,
1357 char __user *optval, int __user *optlen) 1436 char __user *optval, int __user *optlen)
1358{ 1437{
1359 if (level != SOL_UDP) 1438 if (level == SOL_UDP || level == SOL_UDPLITE)
1360 return ip_getsockopt(sk, level, optname, optval, optlen); 1439 return do_udp_getsockopt(sk, level, optname, optval, optlen);
1361 return do_udp_getsockopt(sk, level, optname, optval, optlen); 1440 return ip_getsockopt(sk, level, optname, optval, optlen);
1362} 1441}
1363 1442
1364#ifdef CONFIG_COMPAT 1443#ifdef CONFIG_COMPAT
1365static int compat_udp_getsockopt(struct sock *sk, int level, int optname, 1444int compat_udp_getsockopt(struct sock *sk, int level, int optname,
1366 char __user *optval, int __user *optlen) 1445 char __user *optval, int __user *optlen)
1367{ 1446{
1368 if (level != SOL_UDP) 1447 if (level == SOL_UDP || level == SOL_UDPLITE)
1369 return compat_ip_getsockopt(sk, level, optname, optval, optlen); 1448 return do_udp_getsockopt(sk, level, optname, optval, optlen);
1370 return do_udp_getsockopt(sk, level, optname, optval, optlen); 1449 return compat_ip_getsockopt(sk, level, optname, optval, optlen);
1371} 1450}
1372#endif 1451#endif
1373/** 1452/**
@@ -1387,7 +1466,8 @@ unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait)
1387{ 1466{
1388 unsigned int mask = datagram_poll(file, sock, wait); 1467 unsigned int mask = datagram_poll(file, sock, wait);
1389 struct sock *sk = sock->sk; 1468 struct sock *sk = sock->sk;
1390 1469 int is_lite = IS_UDPLITE(sk);
1470
1391 /* Check for false positives due to checksum errors */ 1471 /* Check for false positives due to checksum errors */
1392 if ( (mask & POLLRDNORM) && 1472 if ( (mask & POLLRDNORM) &&
1393 !(file->f_flags & O_NONBLOCK) && 1473 !(file->f_flags & O_NONBLOCK) &&
@@ -1397,8 +1477,8 @@ unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait)
1397 1477
1398 spin_lock_bh(&rcvq->lock); 1478 spin_lock_bh(&rcvq->lock);
1399 while ((skb = skb_peek(rcvq)) != NULL) { 1479 while ((skb = skb_peek(rcvq)) != NULL) {
1400 if (udp_checksum_complete(skb)) { 1480 if (udp_lib_checksum_complete(skb)) {
1401 UDP_INC_STATS_BH(UDP_MIB_INERRORS); 1481 UDP_INC_STATS_BH(UDP_MIB_INERRORS, is_lite);
1402 __skb_unlink(skb, rcvq); 1482 __skb_unlink(skb, rcvq);
1403 kfree_skb(skb); 1483 kfree_skb(skb);
1404 } else { 1484 } else {
@@ -1420,7 +1500,7 @@ unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait)
1420struct proto udp_prot = { 1500struct proto udp_prot = {
1421 .name = "UDP", 1501 .name = "UDP",
1422 .owner = THIS_MODULE, 1502 .owner = THIS_MODULE,
1423 .close = udp_close, 1503 .close = udp_lib_close,
1424 .connect = ip4_datagram_connect, 1504 .connect = ip4_datagram_connect,
1425 .disconnect = udp_disconnect, 1505 .disconnect = udp_disconnect,
1426 .ioctl = udp_ioctl, 1506 .ioctl = udp_ioctl,
@@ -1431,8 +1511,8 @@ struct proto udp_prot = {
1431 .recvmsg = udp_recvmsg, 1511 .recvmsg = udp_recvmsg,
1432 .sendpage = udp_sendpage, 1512 .sendpage = udp_sendpage,
1433 .backlog_rcv = udp_queue_rcv_skb, 1513 .backlog_rcv = udp_queue_rcv_skb,
1434 .hash = udp_v4_hash, 1514 .hash = udp_lib_hash,
1435 .unhash = udp_v4_unhash, 1515 .unhash = udp_lib_unhash,
1436 .get_port = udp_v4_get_port, 1516 .get_port = udp_v4_get_port,
1437 .obj_size = sizeof(struct udp_sock), 1517 .obj_size = sizeof(struct udp_sock),
1438#ifdef CONFIG_COMPAT 1518#ifdef CONFIG_COMPAT
@@ -1451,7 +1531,7 @@ static struct sock *udp_get_first(struct seq_file *seq)
1451 1531
1452 for (state->bucket = 0; state->bucket < UDP_HTABLE_SIZE; ++state->bucket) { 1532 for (state->bucket = 0; state->bucket < UDP_HTABLE_SIZE; ++state->bucket) {
1453 struct hlist_node *node; 1533 struct hlist_node *node;
1454 sk_for_each(sk, node, &udp_hash[state->bucket]) { 1534 sk_for_each(sk, node, state->hashtable + state->bucket) {
1455 if (sk->sk_family == state->family) 1535 if (sk->sk_family == state->family)
1456 goto found; 1536 goto found;
1457 } 1537 }
@@ -1472,7 +1552,7 @@ try_again:
1472 } while (sk && sk->sk_family != state->family); 1552 } while (sk && sk->sk_family != state->family);
1473 1553
1474 if (!sk && ++state->bucket < UDP_HTABLE_SIZE) { 1554 if (!sk && ++state->bucket < UDP_HTABLE_SIZE) {
1475 sk = sk_head(&udp_hash[state->bucket]); 1555 sk = sk_head(state->hashtable + state->bucket);
1476 goto try_again; 1556 goto try_again;
1477 } 1557 }
1478 return sk; 1558 return sk;
@@ -1522,6 +1602,7 @@ static int udp_seq_open(struct inode *inode, struct file *file)
1522 if (!s) 1602 if (!s)
1523 goto out; 1603 goto out;
1524 s->family = afinfo->family; 1604 s->family = afinfo->family;
1605 s->hashtable = afinfo->hashtable;
1525 s->seq_ops.start = udp_seq_start; 1606 s->seq_ops.start = udp_seq_start;
1526 s->seq_ops.next = udp_seq_next; 1607 s->seq_ops.next = udp_seq_next;
1527 s->seq_ops.show = afinfo->seq_show; 1608 s->seq_ops.show = afinfo->seq_show;
@@ -1588,7 +1669,7 @@ static void udp4_format_sock(struct sock *sp, char *tmpbuf, int bucket)
1588 atomic_read(&sp->sk_refcnt), sp); 1669 atomic_read(&sp->sk_refcnt), sp);
1589} 1670}
1590 1671
1591static int udp4_seq_show(struct seq_file *seq, void *v) 1672int udp4_seq_show(struct seq_file *seq, void *v)
1592{ 1673{
1593 if (v == SEQ_START_TOKEN) 1674 if (v == SEQ_START_TOKEN)
1594 seq_printf(seq, "%-127s\n", 1675 seq_printf(seq, "%-127s\n",
@@ -1611,6 +1692,7 @@ static struct udp_seq_afinfo udp4_seq_afinfo = {
1611 .owner = THIS_MODULE, 1692 .owner = THIS_MODULE,
1612 .name = "udp", 1693 .name = "udp",
1613 .family = AF_INET, 1694 .family = AF_INET,
1695 .hashtable = udp_hash,
1614 .seq_show = udp4_seq_show, 1696 .seq_show = udp4_seq_show,
1615 .seq_fops = &udp4_seq_fops, 1697 .seq_fops = &udp4_seq_fops,
1616}; 1698};
diff --git a/net/ipv4/udp_impl.h b/net/ipv4/udp_impl.h
new file mode 100644
index 000000000000..f6f4277ba6dc
--- /dev/null
+++ b/net/ipv4/udp_impl.h
@@ -0,0 +1,38 @@
1#ifndef _UDP4_IMPL_H
2#define _UDP4_IMPL_H
3#include <net/udp.h>
4#include <net/udplite.h>
5#include <net/protocol.h>
6#include <net/inet_common.h>
7
8extern int __udp4_lib_rcv(struct sk_buff *, struct hlist_head [], int );
9extern void __udp4_lib_err(struct sk_buff *, u32, struct hlist_head []);
10
11extern int __udp_lib_get_port(struct sock *sk, unsigned short snum,
12 struct hlist_head udptable[], int *port_rover,
13 int (*)(const struct sock*,const struct sock*));
14extern int ipv4_rcv_saddr_equal(const struct sock *, const struct sock *);
15
16
17extern int udp_setsockopt(struct sock *sk, int level, int optname,
18 char __user *optval, int optlen);
19extern int udp_getsockopt(struct sock *sk, int level, int optname,
20 char __user *optval, int __user *optlen);
21
22#ifdef CONFIG_COMPAT
23extern int compat_udp_setsockopt(struct sock *sk, int level, int optname,
24 char __user *optval, int optlen);
25extern int compat_udp_getsockopt(struct sock *sk, int level, int optname,
26 char __user *optval, int __user *optlen);
27#endif
28extern int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
29 size_t len, int noblock, int flags, int *addr_len);
30extern int udp_sendpage(struct sock *sk, struct page *page, int offset,
31 size_t size, int flags);
32extern int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb);
33extern int udp_destroy_sock(struct sock *sk);
34
35#ifdef CONFIG_PROC_FS
36extern int udp4_seq_show(struct seq_file *seq, void *v);
37#endif
38#endif /* _UDP4_IMPL_H */
diff --git a/net/ipv4/udplite.c b/net/ipv4/udplite.c
new file mode 100644
index 000000000000..561de6d8c734
--- /dev/null
+++ b/net/ipv4/udplite.c
@@ -0,0 +1,119 @@
1/*
2 * UDPLITE An implementation of the UDP-Lite protocol (RFC 3828).
3 *
4 * Version: $Id: udplite.c,v 1.25 2006/10/19 07:22:36 gerrit Exp $
5 *
6 * Authors: Gerrit Renker <gerrit@erg.abdn.ac.uk>
7 *
8 * Changes:
9 * Fixes:
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version
13 * 2 of the License, or (at your option) any later version.
14 */
15#include "udp_impl.h"
16DEFINE_SNMP_STAT(struct udp_mib, udplite_statistics) __read_mostly;
17
18struct hlist_head udplite_hash[UDP_HTABLE_SIZE];
19static int udplite_port_rover;
20
21__inline__ int udplite_get_port(struct sock *sk, unsigned short p,
22 int (*c)(const struct sock *, const struct sock *))
23{
24 return __udp_lib_get_port(sk, p, udplite_hash, &udplite_port_rover, c);
25}
26
27static __inline__ int udplite_v4_get_port(struct sock *sk, unsigned short snum)
28{
29 return udplite_get_port(sk, snum, ipv4_rcv_saddr_equal);
30}
31
32__inline__ int udplite_rcv(struct sk_buff *skb)
33{
34 return __udp4_lib_rcv(skb, udplite_hash, 1);
35}
36
37__inline__ void udplite_err(struct sk_buff *skb, u32 info)
38{
39 return __udp4_lib_err(skb, info, udplite_hash);
40}
41
42static struct net_protocol udplite_protocol = {
43 .handler = udplite_rcv,
44 .err_handler = udplite_err,
45 .no_policy = 1,
46};
47
48struct proto udplite_prot = {
49 .name = "UDP-Lite",
50 .owner = THIS_MODULE,
51 .close = udp_lib_close,
52 .connect = ip4_datagram_connect,
53 .disconnect = udp_disconnect,
54 .ioctl = udp_ioctl,
55 .init = udplite_sk_init,
56 .destroy = udp_destroy_sock,
57 .setsockopt = udp_setsockopt,
58 .getsockopt = udp_getsockopt,
59 .sendmsg = udp_sendmsg,
60 .recvmsg = udp_recvmsg,
61 .sendpage = udp_sendpage,
62 .backlog_rcv = udp_queue_rcv_skb,
63 .hash = udp_lib_hash,
64 .unhash = udp_lib_unhash,
65 .get_port = udplite_v4_get_port,
66 .obj_size = sizeof(struct udp_sock),
67#ifdef CONFIG_COMPAT
68 .compat_setsockopt = compat_udp_setsockopt,
69 .compat_getsockopt = compat_udp_getsockopt,
70#endif
71};
72
73static struct inet_protosw udplite4_protosw = {
74 .type = SOCK_DGRAM,
75 .protocol = IPPROTO_UDPLITE,
76 .prot = &udplite_prot,
77 .ops = &inet_dgram_ops,
78 .capability = -1,
79 .no_check = 0, /* must checksum (RFC 3828) */
80 .flags = INET_PROTOSW_PERMANENT,
81};
82
83#ifdef CONFIG_PROC_FS
84static struct file_operations udplite4_seq_fops;
85static struct udp_seq_afinfo udplite4_seq_afinfo = {
86 .owner = THIS_MODULE,
87 .name = "udplite",
88 .family = AF_INET,
89 .hashtable = udplite_hash,
90 .seq_show = udp4_seq_show,
91 .seq_fops = &udplite4_seq_fops,
92};
93#endif
94
95void __init udplite4_register(void)
96{
97 if (proto_register(&udplite_prot, 1))
98 goto out_register_err;
99
100 if (inet_add_protocol(&udplite_protocol, IPPROTO_UDPLITE) < 0)
101 goto out_unregister_proto;
102
103 inet_register_protosw(&udplite4_protosw);
104
105#ifdef CONFIG_PROC_FS
106 if (udp_proc_register(&udplite4_seq_afinfo)) /* udplite4_proc_init() */
107 printk(KERN_ERR "%s: Cannot register /proc!\n", __FUNCTION__);
108#endif
109 return;
110
111out_unregister_proto:
112 proto_unregister(&udplite_prot);
113out_register_err:
114 printk(KERN_CRIT "%s: Cannot add UDP-Lite protocol.\n", __FUNCTION__);
115}
116
117EXPORT_SYMBOL(udplite_hash);
118EXPORT_SYMBOL(udplite_prot);
119EXPORT_SYMBOL(udplite_get_port);
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index da766234607b..d4107bb701b5 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -199,6 +199,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl)
199 if (!(iph->frag_off & htons(IP_MF | IP_OFFSET))) { 199 if (!(iph->frag_off & htons(IP_MF | IP_OFFSET))) {
200 switch (iph->protocol) { 200 switch (iph->protocol) {
201 case IPPROTO_UDP: 201 case IPPROTO_UDP:
202 case IPPROTO_UDPLITE:
202 case IPPROTO_TCP: 203 case IPPROTO_TCP:
203 case IPPROTO_SCTP: 204 case IPPROTO_SCTP:
204 case IPPROTO_DCCP: 205 case IPPROTO_DCCP:
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile
index addcc011bc01..8bacda109b7f 100644
--- a/net/ipv6/Makefile
+++ b/net/ipv6/Makefile
@@ -5,8 +5,8 @@
5obj-$(CONFIG_IPV6) += ipv6.o 5obj-$(CONFIG_IPV6) += ipv6.o
6 6
7ipv6-objs := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o \ 7ipv6-objs := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o \
8 route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o raw.o \ 8 route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o udplite.o \
9 protocol.o icmp.o mcast.o reassembly.o tcp_ipv6.o \ 9 raw.o protocol.o icmp.o mcast.o reassembly.o tcp_ipv6.o \
10 exthdrs.o sysctl_net_ipv6.o datagram.o proc.o \ 10 exthdrs.o sysctl_net_ipv6.o datagram.o proc.o \
11 ip6_flowlabel.o ipv6_syms.o inet6_connection_sock.o 11 ip6_flowlabel.o ipv6_syms.o inet6_connection_sock.o
12 12
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 92bfccf62cb7..1eb1c7f261d4 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -49,6 +49,7 @@
49#include <net/ip.h> 49#include <net/ip.h>
50#include <net/ipv6.h> 50#include <net/ipv6.h>
51#include <net/udp.h> 51#include <net/udp.h>
52#include <net/udplite.h>
52#include <net/tcp.h> 53#include <net/tcp.h>
53#include <net/ipip.h> 54#include <net/ipip.h>
54#include <net/protocol.h> 55#include <net/protocol.h>
@@ -737,8 +738,13 @@ static int __init init_ipv6_mibs(void)
737 if (snmp6_mib_init((void **)udp_stats_in6, sizeof (struct udp_mib), 738 if (snmp6_mib_init((void **)udp_stats_in6, sizeof (struct udp_mib),
738 __alignof__(struct udp_mib)) < 0) 739 __alignof__(struct udp_mib)) < 0)
739 goto err_udp_mib; 740 goto err_udp_mib;
741 if (snmp6_mib_init((void **)udplite_stats_in6, sizeof (struct udp_mib),
742 __alignof__(struct udp_mib)) < 0)
743 goto err_udplite_mib;
740 return 0; 744 return 0;
741 745
746err_udplite_mib:
747 snmp6_mib_free((void **)udp_stats_in6);
742err_udp_mib: 748err_udp_mib:
743 snmp6_mib_free((void **)icmpv6_statistics); 749 snmp6_mib_free((void **)icmpv6_statistics);
744err_icmp_mib: 750err_icmp_mib:
@@ -753,6 +759,7 @@ static void cleanup_ipv6_mibs(void)
753 snmp6_mib_free((void **)ipv6_statistics); 759 snmp6_mib_free((void **)ipv6_statistics);
754 snmp6_mib_free((void **)icmpv6_statistics); 760 snmp6_mib_free((void **)icmpv6_statistics);
755 snmp6_mib_free((void **)udp_stats_in6); 761 snmp6_mib_free((void **)udp_stats_in6);
762 snmp6_mib_free((void **)udplite_stats_in6);
756} 763}
757 764
758static int __init inet6_init(void) 765static int __init inet6_init(void)
@@ -780,10 +787,14 @@ static int __init inet6_init(void)
780 if (err) 787 if (err)
781 goto out_unregister_tcp_proto; 788 goto out_unregister_tcp_proto;
782 789
783 err = proto_register(&rawv6_prot, 1); 790 err = proto_register(&udplitev6_prot, 1);
784 if (err) 791 if (err)
785 goto out_unregister_udp_proto; 792 goto out_unregister_udp_proto;
786 793
794 err = proto_register(&rawv6_prot, 1);
795 if (err)
796 goto out_unregister_udplite_proto;
797
787 798
788 /* Register the socket-side information for inet6_create. */ 799 /* Register the socket-side information for inet6_create. */
789 for(r = &inetsw6[0]; r < &inetsw6[SOCK_MAX]; ++r) 800 for(r = &inetsw6[0]; r < &inetsw6[SOCK_MAX]; ++r)
@@ -837,6 +848,8 @@ static int __init inet6_init(void)
837 goto proc_tcp6_fail; 848 goto proc_tcp6_fail;
838 if (udp6_proc_init()) 849 if (udp6_proc_init())
839 goto proc_udp6_fail; 850 goto proc_udp6_fail;
851 if (udplite6_proc_init())
852 goto proc_udplite6_fail;
840 if (ipv6_misc_proc_init()) 853 if (ipv6_misc_proc_init())
841 goto proc_misc6_fail; 854 goto proc_misc6_fail;
842 855
@@ -862,6 +875,7 @@ static int __init inet6_init(void)
862 875
863 /* Init v6 transport protocols. */ 876 /* Init v6 transport protocols. */
864 udpv6_init(); 877 udpv6_init();
878 udplitev6_init();
865 tcpv6_init(); 879 tcpv6_init();
866 880
867 ipv6_packet_init(); 881 ipv6_packet_init();
@@ -879,6 +893,8 @@ proc_if6_fail:
879proc_anycast6_fail: 893proc_anycast6_fail:
880 ipv6_misc_proc_exit(); 894 ipv6_misc_proc_exit();
881proc_misc6_fail: 895proc_misc6_fail:
896 udplite6_proc_exit();
897proc_udplite6_fail:
882 udp6_proc_exit(); 898 udp6_proc_exit();
883proc_udp6_fail: 899proc_udp6_fail:
884 tcp6_proc_exit(); 900 tcp6_proc_exit();
@@ -902,6 +918,8 @@ out_unregister_sock:
902 sock_unregister(PF_INET6); 918 sock_unregister(PF_INET6);
903out_unregister_raw_proto: 919out_unregister_raw_proto:
904 proto_unregister(&rawv6_prot); 920 proto_unregister(&rawv6_prot);
921out_unregister_udplite_proto:
922 proto_unregister(&udplitev6_prot);
905out_unregister_udp_proto: 923out_unregister_udp_proto:
906 proto_unregister(&udpv6_prot); 924 proto_unregister(&udpv6_prot);
907out_unregister_tcp_proto: 925out_unregister_tcp_proto:
@@ -919,6 +937,7 @@ static void __exit inet6_exit(void)
919 ac6_proc_exit(); 937 ac6_proc_exit();
920 ipv6_misc_proc_exit(); 938 ipv6_misc_proc_exit();
921 udp6_proc_exit(); 939 udp6_proc_exit();
940 udplite6_proc_exit();
922 tcp6_proc_exit(); 941 tcp6_proc_exit();
923 raw6_proc_exit(); 942 raw6_proc_exit();
924#endif 943#endif
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index de6b91981b30..1eafcfc95e81 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -51,6 +51,7 @@
51#include <net/inet_common.h> 51#include <net/inet_common.h>
52#include <net/tcp.h> 52#include <net/tcp.h>
53#include <net/udp.h> 53#include <net/udp.h>
54#include <net/udplite.h>
54#include <net/xfrm.h> 55#include <net/xfrm.h>
55 56
56#include <asm/uaccess.h> 57#include <asm/uaccess.h>
@@ -239,6 +240,7 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
239 struct sk_buff *pktopt; 240 struct sk_buff *pktopt;
240 241
241 if (sk->sk_protocol != IPPROTO_UDP && 242 if (sk->sk_protocol != IPPROTO_UDP &&
243 sk->sk_protocol != IPPROTO_UDPLITE &&
242 sk->sk_protocol != IPPROTO_TCP) 244 sk->sk_protocol != IPPROTO_TCP)
243 break; 245 break;
244 246
@@ -276,11 +278,15 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
276 sk->sk_family = PF_INET; 278 sk->sk_family = PF_INET;
277 tcp_sync_mss(sk, icsk->icsk_pmtu_cookie); 279 tcp_sync_mss(sk, icsk->icsk_pmtu_cookie);
278 } else { 280 } else {
281 struct proto *prot = &udp_prot;
282
283 if (sk->sk_protocol == IPPROTO_UDPLITE)
284 prot = &udplite_prot;
279 local_bh_disable(); 285 local_bh_disable();
280 sock_prot_dec_use(sk->sk_prot); 286 sock_prot_dec_use(sk->sk_prot);
281 sock_prot_inc_use(&udp_prot); 287 sock_prot_inc_use(prot);
282 local_bh_enable(); 288 local_bh_enable();
283 sk->sk_prot = &udp_prot; 289 sk->sk_prot = prot;
284 sk->sk_socket->ops = &inet_dgram_ops; 290 sk->sk_socket->ops = &inet_dgram_ops;
285 sk->sk_family = PF_INET; 291 sk->sk_family = PF_INET;
286 } 292 }
@@ -813,6 +819,7 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
813 switch (optname) { 819 switch (optname) {
814 case IPV6_ADDRFORM: 820 case IPV6_ADDRFORM:
815 if (sk->sk_protocol != IPPROTO_UDP && 821 if (sk->sk_protocol != IPPROTO_UDP &&
822 sk->sk_protocol != IPPROTO_UDPLITE &&
816 sk->sk_protocol != IPPROTO_TCP) 823 sk->sk_protocol != IPPROTO_TCP)
817 return -EINVAL; 824 return -EINVAL;
818 if (sk->sk_state != TCP_ESTABLISHED) 825 if (sk->sk_state != TCP_ESTABLISHED)
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c
index 0cf537d30185..3cb6bb79cc05 100644
--- a/net/ipv6/netfilter/ip6t_LOG.c
+++ b/net/ipv6/netfilter/ip6t_LOG.c
@@ -270,11 +270,15 @@ static void dump_packet(const struct nf_loginfo *info,
270 } 270 }
271 break; 271 break;
272 } 272 }
273 case IPPROTO_UDP: { 273 case IPPROTO_UDP:
274 case IPPROTO_UDPLITE: {
274 struct udphdr _udph, *uh; 275 struct udphdr _udph, *uh;
275 276
276 /* Max length: 10 "PROTO=UDP " */ 277 if (currenthdr == IPPROTO_UDP)
277 printk("PROTO=UDP "); 278 /* Max length: 10 "PROTO=UDP " */
279 printk("PROTO=UDP " );
280 else /* Max length: 14 "PROTO=UDPLITE " */
281 printk("PROTO=UDPLITE ");
278 282
279 if (fragment) 283 if (fragment)
280 break; 284 break;
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c
index 4158d386b0aa..35249d8487bb 100644
--- a/net/ipv6/proc.c
+++ b/net/ipv6/proc.c
@@ -49,6 +49,8 @@ static int sockstat6_seq_show(struct seq_file *seq, void *v)
49 fold_prot_inuse(&tcpv6_prot)); 49 fold_prot_inuse(&tcpv6_prot));
50 seq_printf(seq, "UDP6: inuse %d\n", 50 seq_printf(seq, "UDP6: inuse %d\n",
51 fold_prot_inuse(&udpv6_prot)); 51 fold_prot_inuse(&udpv6_prot));
52 seq_printf(seq, "UDPLITE6: inuse %d\n",
53 fold_prot_inuse(&udplitev6_prot));
52 seq_printf(seq, "RAW6: inuse %d\n", 54 seq_printf(seq, "RAW6: inuse %d\n",
53 fold_prot_inuse(&rawv6_prot)); 55 fold_prot_inuse(&rawv6_prot));
54 seq_printf(seq, "FRAG6: inuse %d memory %d\n", 56 seq_printf(seq, "FRAG6: inuse %d memory %d\n",
@@ -133,6 +135,14 @@ static struct snmp_mib snmp6_udp6_list[] = {
133 SNMP_MIB_SENTINEL 135 SNMP_MIB_SENTINEL
134}; 136};
135 137
138static struct snmp_mib snmp6_udplite6_list[] = {
139 SNMP_MIB_ITEM("UdpLite6InDatagrams", UDP_MIB_INDATAGRAMS),
140 SNMP_MIB_ITEM("UdpLite6NoPorts", UDP_MIB_NOPORTS),
141 SNMP_MIB_ITEM("UdpLite6InErrors", UDP_MIB_INERRORS),
142 SNMP_MIB_ITEM("UdpLite6OutDatagrams", UDP_MIB_OUTDATAGRAMS),
143 SNMP_MIB_SENTINEL
144};
145
136static unsigned long 146static unsigned long
137fold_field(void *mib[], int offt) 147fold_field(void *mib[], int offt)
138{ 148{
@@ -167,6 +177,7 @@ static int snmp6_seq_show(struct seq_file *seq, void *v)
167 snmp6_seq_show_item(seq, (void **)ipv6_statistics, snmp6_ipstats_list); 177 snmp6_seq_show_item(seq, (void **)ipv6_statistics, snmp6_ipstats_list);
168 snmp6_seq_show_item(seq, (void **)icmpv6_statistics, snmp6_icmp6_list); 178 snmp6_seq_show_item(seq, (void **)icmpv6_statistics, snmp6_icmp6_list);
169 snmp6_seq_show_item(seq, (void **)udp_stats_in6, snmp6_udp6_list); 179 snmp6_seq_show_item(seq, (void **)udp_stats_in6, snmp6_udp6_list);
180 snmp6_seq_show_item(seq, (void **)udplite_stats_in6, snmp6_udplite6_list);
170 } 181 }
171 return 0; 182 return 0;
172} 183}
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 886300d13a59..5a64027bf2fc 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -38,26 +38,18 @@
38#include <linux/skbuff.h> 38#include <linux/skbuff.h>
39#include <asm/uaccess.h> 39#include <asm/uaccess.h>
40 40
41#include <net/sock.h>
42#include <net/snmp.h>
43
44#include <net/ipv6.h>
45#include <net/ndisc.h> 41#include <net/ndisc.h>
46#include <net/protocol.h> 42#include <net/protocol.h>
47#include <net/transp_v6.h> 43#include <net/transp_v6.h>
48#include <net/ip6_route.h> 44#include <net/ip6_route.h>
49#include <net/addrconf.h>
50#include <net/ip.h>
51#include <net/udp.h>
52#include <net/raw.h> 45#include <net/raw.h>
53#include <net/inet_common.h>
54#include <net/tcp_states.h> 46#include <net/tcp_states.h>
55
56#include <net/ip6_checksum.h> 47#include <net/ip6_checksum.h>
57#include <net/xfrm.h> 48#include <net/xfrm.h>
58 49
59#include <linux/proc_fs.h> 50#include <linux/proc_fs.h>
60#include <linux/seq_file.h> 51#include <linux/seq_file.h>
52#include "udp_impl.h"
61 53
62DEFINE_SNMP_STAT(struct udp_mib, udp_stats_in6) __read_mostly; 54DEFINE_SNMP_STAT(struct udp_mib, udp_stats_in6) __read_mostly;
63 55
@@ -66,23 +58,9 @@ static inline int udp_v6_get_port(struct sock *sk, unsigned short snum)
66 return udp_get_port(sk, snum, ipv6_rcv_saddr_equal); 58 return udp_get_port(sk, snum, ipv6_rcv_saddr_equal);
67} 59}
68 60
69static void udp_v6_hash(struct sock *sk) 61static struct sock *__udp6_lib_lookup(struct in6_addr *saddr, __be16 sport,
70{ 62 struct in6_addr *daddr, __be16 dport,
71 BUG(); 63 int dif, struct hlist_head udptable[])
72}
73
74static void udp_v6_unhash(struct sock *sk)
75{
76 write_lock_bh(&udp_hash_lock);
77 if (sk_del_node_init(sk)) {
78 inet_sk(sk)->num = 0;
79 sock_prot_dec_use(sk->sk_prot);
80 }
81 write_unlock_bh(&udp_hash_lock);
82}
83
84static struct sock *udp_v6_lookup(struct in6_addr *saddr, u16 sport,
85 struct in6_addr *daddr, u16 dport, int dif)
86{ 64{
87 struct sock *sk, *result = NULL; 65 struct sock *sk, *result = NULL;
88 struct hlist_node *node; 66 struct hlist_node *node;
@@ -90,7 +68,7 @@ static struct sock *udp_v6_lookup(struct in6_addr *saddr, u16 sport,
90 int badness = -1; 68 int badness = -1;
91 69
92 read_lock(&udp_hash_lock); 70 read_lock(&udp_hash_lock);
93 sk_for_each(sk, node, &udp_hash[hnum & (UDP_HTABLE_SIZE - 1)]) { 71 sk_for_each(sk, node, &udptable[hnum & (UDP_HTABLE_SIZE - 1)]) {
94 struct inet_sock *inet = inet_sk(sk); 72 struct inet_sock *inet = inet_sk(sk);
95 73
96 if (inet->num == hnum && sk->sk_family == PF_INET6) { 74 if (inet->num == hnum && sk->sk_family == PF_INET6) {
@@ -132,20 +110,11 @@ static struct sock *udp_v6_lookup(struct in6_addr *saddr, u16 sport,
132} 110}
133 111
134/* 112/*
135 *
136 */
137
138static void udpv6_close(struct sock *sk, long timeout)
139{
140 sk_common_release(sk);
141}
142
143/*
144 * This should be easy, if there is something there we 113 * This should be easy, if there is something there we
145 * return it, otherwise we block. 114 * return it, otherwise we block.
146 */ 115 */
147 116
148static int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk, 117int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk,
149 struct msghdr *msg, size_t len, 118 struct msghdr *msg, size_t len,
150 int noblock, int flags, int *addr_len) 119 int noblock, int flags, int *addr_len)
151{ 120{
@@ -153,7 +122,7 @@ static int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk,
153 struct inet_sock *inet = inet_sk(sk); 122 struct inet_sock *inet = inet_sk(sk);
154 struct sk_buff *skb; 123 struct sk_buff *skb;
155 size_t copied; 124 size_t copied;
156 int err; 125 int err, copy_only, is_udplite = IS_UDPLITE(sk);
157 126
158 if (addr_len) 127 if (addr_len)
159 *addr_len=sizeof(struct sockaddr_in6); 128 *addr_len=sizeof(struct sockaddr_in6);
@@ -172,15 +141,21 @@ try_again:
172 msg->msg_flags |= MSG_TRUNC; 141 msg->msg_flags |= MSG_TRUNC;
173 } 142 }
174 143
175 if (skb->ip_summed==CHECKSUM_UNNECESSARY) { 144 /*
176 err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov, 145 * Decide whether to checksum and/or copy data.
177 copied); 146 */
178 } else if (msg->msg_flags&MSG_TRUNC) { 147 copy_only = (skb->ip_summed==CHECKSUM_UNNECESSARY);
179 if (__skb_checksum_complete(skb)) 148
149 if (is_udplite || (!copy_only && msg->msg_flags&MSG_TRUNC)) {
150 if (__udp_lib_checksum_complete(skb))
180 goto csum_copy_err; 151 goto csum_copy_err;
181 err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov, 152 copy_only = 1;
182 copied); 153 }
183 } else { 154
155 if (copy_only)
156 err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr),
157 msg->msg_iov, copied );
158 else {
184 err = skb_copy_and_csum_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov); 159 err = skb_copy_and_csum_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov);
185 if (err == -EINVAL) 160 if (err == -EINVAL)
186 goto csum_copy_err; 161 goto csum_copy_err;
@@ -231,14 +206,15 @@ csum_copy_err:
231 skb_kill_datagram(sk, skb, flags); 206 skb_kill_datagram(sk, skb, flags);
232 207
233 if (flags & MSG_DONTWAIT) { 208 if (flags & MSG_DONTWAIT) {
234 UDP6_INC_STATS_USER(UDP_MIB_INERRORS); 209 UDP6_INC_STATS_USER(UDP_MIB_INERRORS, is_udplite);
235 return -EAGAIN; 210 return -EAGAIN;
236 } 211 }
237 goto try_again; 212 goto try_again;
238} 213}
239 214
240static void udpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, 215void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
241 int type, int code, int offset, __be32 info) 216 int type, int code, int offset, __be32 info,
217 struct hlist_head udptable[] )
242{ 218{
243 struct ipv6_pinfo *np; 219 struct ipv6_pinfo *np;
244 struct ipv6hdr *hdr = (struct ipv6hdr*)skb->data; 220 struct ipv6hdr *hdr = (struct ipv6hdr*)skb->data;
@@ -248,8 +224,8 @@ static void udpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
248 struct sock *sk; 224 struct sock *sk;
249 int err; 225 int err;
250 226
251 sk = udp_v6_lookup(daddr, uh->dest, saddr, uh->source, inet6_iif(skb)); 227 sk = __udp6_lib_lookup(daddr, uh->dest,
252 228 saddr, uh->source, inet6_iif(skb), udptable);
253 if (sk == NULL) 229 if (sk == NULL)
254 return; 230 return;
255 231
@@ -270,31 +246,55 @@ out:
270 sock_put(sk); 246 sock_put(sk);
271} 247}
272 248
273static inline int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) 249static __inline__ void udpv6_err(struct sk_buff *skb,
250 struct inet6_skb_parm *opt, int type,
251 int code, int offset, __u32 info )
252{
253 return __udp6_lib_err(skb, opt, type, code, offset, info, udp_hash);
254}
255
256int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
274{ 257{
258 struct udp_sock *up = udp_sk(sk);
275 int rc; 259 int rc;
276 260
277 if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) { 261 if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb))
278 kfree_skb(skb); 262 goto drop;
279 return -1;
280 }
281 263
282 if (skb_checksum_complete(skb)) { 264 /*
283 UDP6_INC_STATS_BH(UDP_MIB_INERRORS); 265 * UDP-Lite specific tests, ignored on UDP sockets (see net/ipv4/udp.c).
284 kfree_skb(skb); 266 */
285 return 0; 267 if ((up->pcflag & UDPLITE_RECV_CC) && UDP_SKB_CB(skb)->partial_cov) {
268
269 if (up->pcrlen == 0) { /* full coverage was set */
270 LIMIT_NETDEBUG(KERN_WARNING "UDPLITE6: partial coverage"
271 " %d while full coverage %d requested\n",
272 UDP_SKB_CB(skb)->cscov, skb->len);
273 goto drop;
274 }
275 if (UDP_SKB_CB(skb)->cscov < up->pcrlen) {
276 LIMIT_NETDEBUG(KERN_WARNING "UDPLITE6: coverage %d "
277 "too small, need min %d\n",
278 UDP_SKB_CB(skb)->cscov, up->pcrlen);
279 goto drop;
280 }
286 } 281 }
287 282
283 if (udp_lib_checksum_complete(skb))
284 goto drop;
285
288 if ((rc = sock_queue_rcv_skb(sk,skb)) < 0) { 286 if ((rc = sock_queue_rcv_skb(sk,skb)) < 0) {
289 /* Note that an ENOMEM error is charged twice */ 287 /* Note that an ENOMEM error is charged twice */
290 if (rc == -ENOMEM) 288 if (rc == -ENOMEM)
291 UDP6_INC_STATS_BH(UDP_MIB_RCVBUFERRORS); 289 UDP6_INC_STATS_BH(UDP_MIB_RCVBUFERRORS, up->pcflag);
292 UDP6_INC_STATS_BH(UDP_MIB_INERRORS); 290 goto drop;
293 kfree_skb(skb);
294 return 0;
295 } 291 }
296 UDP6_INC_STATS_BH(UDP_MIB_INDATAGRAMS); 292 UDP6_INC_STATS_BH(UDP_MIB_INDATAGRAMS, up->pcflag);
297 return 0; 293 return 0;
294drop:
295 UDP6_INC_STATS_BH(UDP_MIB_INERRORS, up->pcflag);
296 kfree_skb(skb);
297 return -1;
298} 298}
299 299
300static struct sock *udp_v6_mcast_next(struct sock *sk, 300static struct sock *udp_v6_mcast_next(struct sock *sk,
@@ -338,15 +338,15 @@ static struct sock *udp_v6_mcast_next(struct sock *sk,
338 * Note: called only from the BH handler context, 338 * Note: called only from the BH handler context,
339 * so we don't need to lock the hashes. 339 * so we don't need to lock the hashes.
340 */ 340 */
341static void udpv6_mcast_deliver(struct udphdr *uh, 341static int __udp6_lib_mcast_deliver(struct sk_buff *skb, struct in6_addr *saddr,
342 struct in6_addr *saddr, struct in6_addr *daddr, 342 struct in6_addr *daddr, struct hlist_head udptable[])
343 struct sk_buff *skb)
344{ 343{
345 struct sock *sk, *sk2; 344 struct sock *sk, *sk2;
345 const struct udphdr *uh = skb->h.uh;
346 int dif; 346 int dif;
347 347
348 read_lock(&udp_hash_lock); 348 read_lock(&udp_hash_lock);
349 sk = sk_head(&udp_hash[ntohs(uh->dest) & (UDP_HTABLE_SIZE - 1)]); 349 sk = sk_head(&udptable[ntohs(uh->dest) & (UDP_HTABLE_SIZE - 1)]);
350 dif = inet6_iif(skb); 350 dif = inet6_iif(skb);
351 sk = udp_v6_mcast_next(sk, uh->dest, daddr, uh->source, saddr, dif); 351 sk = udp_v6_mcast_next(sk, uh->dest, daddr, uh->source, saddr, dif);
352 if (!sk) { 352 if (!sk) {
@@ -364,9 +364,34 @@ static void udpv6_mcast_deliver(struct udphdr *uh,
364 udpv6_queue_rcv_skb(sk, skb); 364 udpv6_queue_rcv_skb(sk, skb);
365out: 365out:
366 read_unlock(&udp_hash_lock); 366 read_unlock(&udp_hash_lock);
367 return 0;
367} 368}
368 369
369static int udpv6_rcv(struct sk_buff **pskb) 370static inline int udp6_csum_init(struct sk_buff *skb, struct udphdr *uh)
371
372{
373 if (uh->check == 0) {
374 /* RFC 2460 section 8.1 says that we SHOULD log
375 this error. Well, it is reasonable.
376 */
377 LIMIT_NETDEBUG(KERN_INFO "IPv6: udp checksum is 0\n");
378 return 1;
379 }
380 if (skb->ip_summed == CHECKSUM_COMPLETE &&
381 !csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr,
382 skb->len, IPPROTO_UDP, skb->csum ))
383 skb->ip_summed = CHECKSUM_UNNECESSARY;
384
385 if (skb->ip_summed != CHECKSUM_UNNECESSARY)
386 skb->csum = ~csum_ipv6_magic(&skb->nh.ipv6h->saddr,
387 &skb->nh.ipv6h->daddr,
388 skb->len, IPPROTO_UDP, 0);
389
390 return (UDP_SKB_CB(skb)->partial_cov = 0);
391}
392
393int __udp6_lib_rcv(struct sk_buff **pskb, struct hlist_head udptable[],
394 int is_udplite)
370{ 395{
371 struct sk_buff *skb = *pskb; 396 struct sk_buff *skb = *pskb;
372 struct sock *sk; 397 struct sock *sk;
@@ -383,44 +408,39 @@ static int udpv6_rcv(struct sk_buff **pskb)
383 uh = skb->h.uh; 408 uh = skb->h.uh;
384 409
385 ulen = ntohs(uh->len); 410 ulen = ntohs(uh->len);
411 if (ulen > skb->len)
412 goto short_packet;
386 413
387 /* Check for jumbo payload */ 414 if(! is_udplite ) { /* UDP validates ulen. */
388 if (ulen == 0)
389 ulen = skb->len;
390 415
391 if (ulen > skb->len || ulen < sizeof(*uh)) 416 /* Check for jumbo payload */
392 goto short_packet; 417 if (ulen == 0)
418 ulen = skb->len;
393 419
394 if (uh->check == 0) { 420 if (ulen < sizeof(*uh))
395 /* RFC 2460 section 8.1 says that we SHOULD log 421 goto short_packet;
396 this error. Well, it is reasonable.
397 */
398 LIMIT_NETDEBUG(KERN_INFO "IPv6: udp checksum is 0\n");
399 goto discard;
400 }
401 422
402 if (ulen < skb->len) { 423 if (ulen < skb->len) {
403 if (pskb_trim_rcsum(skb, ulen)) 424 if (pskb_trim_rcsum(skb, ulen))
404 goto discard; 425 goto short_packet;
405 saddr = &skb->nh.ipv6h->saddr; 426 saddr = &skb->nh.ipv6h->saddr;
406 daddr = &skb->nh.ipv6h->daddr; 427 daddr = &skb->nh.ipv6h->daddr;
407 uh = skb->h.uh; 428 uh = skb->h.uh;
408 } 429 }
409 430
410 if (skb->ip_summed == CHECKSUM_COMPLETE && 431 if (udp6_csum_init(skb, uh))
411 !csum_ipv6_magic(saddr, daddr, ulen, IPPROTO_UDP, skb->csum)) 432 goto discard;
412 skb->ip_summed = CHECKSUM_UNNECESSARY;
413 433
414 if (skb->ip_summed != CHECKSUM_UNNECESSARY) 434 } else { /* UDP-Lite validates cscov. */
415 skb->csum = ~csum_ipv6_magic(saddr, daddr, ulen, IPPROTO_UDP, 0); 435 if (udplite6_csum_init(skb, uh))
436 goto discard;
437 }
416 438
417 /* 439 /*
418 * Multicast receive code 440 * Multicast receive code
419 */ 441 */
420 if (ipv6_addr_is_multicast(daddr)) { 442 if (ipv6_addr_is_multicast(daddr))
421 udpv6_mcast_deliver(uh, saddr, daddr, skb); 443 return __udp6_lib_mcast_deliver(skb, saddr, daddr, udptable);
422 return 0;
423 }
424 444
425 /* Unicast */ 445 /* Unicast */
426 446
@@ -428,15 +448,16 @@ static int udpv6_rcv(struct sk_buff **pskb)
428 * check socket cache ... must talk to Alan about his plans 448 * check socket cache ... must talk to Alan about his plans
429 * for sock caches... i'll skip this for now. 449 * for sock caches... i'll skip this for now.
430 */ 450 */
431 sk = udp_v6_lookup(saddr, uh->source, daddr, uh->dest, inet6_iif(skb)); 451 sk = __udp6_lib_lookup(saddr, uh->source,
452 daddr, uh->dest, inet6_iif(skb), udptable);
432 453
433 if (sk == NULL) { 454 if (sk == NULL) {
434 if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) 455 if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb))
435 goto discard; 456 goto discard;
436 457
437 if (skb_checksum_complete(skb)) 458 if (udp_lib_checksum_complete(skb))
438 goto discard; 459 goto discard;
439 UDP6_INC_STATS_BH(UDP_MIB_NOPORTS); 460 UDP6_INC_STATS_BH(UDP_MIB_NOPORTS, is_udplite);
440 461
441 icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0, dev); 462 icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0, dev);
442 463
@@ -451,14 +472,20 @@ static int udpv6_rcv(struct sk_buff **pskb)
451 return(0); 472 return(0);
452 473
453short_packet: 474short_packet:
454 if (net_ratelimit()) 475 LIMIT_NETDEBUG(KERN_DEBUG "UDP%sv6: short packet: %d/%u\n",
455 printk(KERN_DEBUG "UDP: short packet: %d/%u\n", ulen, skb->len); 476 is_udplite? "-Lite" : "", ulen, skb->len);
456 477
457discard: 478discard:
458 UDP6_INC_STATS_BH(UDP_MIB_INERRORS); 479 UDP6_INC_STATS_BH(UDP_MIB_INERRORS, is_udplite);
459 kfree_skb(skb); 480 kfree_skb(skb);
460 return(0); 481 return(0);
461} 482}
483
484static __inline__ int udpv6_rcv(struct sk_buff **pskb)
485{
486 return __udp6_lib_rcv(pskb, udp_hash, 0);
487}
488
462/* 489/*
463 * Throw away all pending data and cancel the corking. Socket is locked. 490 * Throw away all pending data and cancel the corking. Socket is locked.
464 */ 491 */
@@ -484,6 +511,7 @@ static int udp_v6_push_pending_frames(struct sock *sk, struct udp_sock *up)
484 struct inet_sock *inet = inet_sk(sk); 511 struct inet_sock *inet = inet_sk(sk);
485 struct flowi *fl = &inet->cork.fl; 512 struct flowi *fl = &inet->cork.fl;
486 int err = 0; 513 int err = 0;
514 u32 csum = 0;
487 515
488 /* Grab the skbuff where UDP header space exists. */ 516 /* Grab the skbuff where UDP header space exists. */
489 if ((skb = skb_peek(&sk->sk_write_queue)) == NULL) 517 if ((skb = skb_peek(&sk->sk_write_queue)) == NULL)
@@ -498,35 +526,17 @@ static int udp_v6_push_pending_frames(struct sock *sk, struct udp_sock *up)
498 uh->len = htons(up->len); 526 uh->len = htons(up->len);
499 uh->check = 0; 527 uh->check = 0;
500 528
501 if (sk->sk_no_check == UDP_CSUM_NOXMIT) { 529 if (up->pcflag)
502 skb->ip_summed = CHECKSUM_NONE; 530 csum = udplite_csum_outgoing(sk, skb);
503 goto send; 531 else
504 } 532 csum = udp_csum_outgoing(sk, skb);
505
506 if (skb_queue_len(&sk->sk_write_queue) == 1) {
507 skb->csum = csum_partial((char *)uh,
508 sizeof(struct udphdr), skb->csum);
509 uh->check = csum_ipv6_magic(&fl->fl6_src,
510 &fl->fl6_dst,
511 up->len, fl->proto, skb->csum);
512 } else {
513 u32 tmp_csum = 0;
514
515 skb_queue_walk(&sk->sk_write_queue, skb) {
516 tmp_csum = csum_add(tmp_csum, skb->csum);
517 }
518 tmp_csum = csum_partial((char *)uh,
519 sizeof(struct udphdr), tmp_csum);
520 tmp_csum = csum_ipv6_magic(&fl->fl6_src,
521 &fl->fl6_dst,
522 up->len, fl->proto, tmp_csum);
523 uh->check = tmp_csum;
524 533
525 } 534 /* add protocol-dependent pseudo-header */
535 uh->check = csum_ipv6_magic(&fl->fl6_src, &fl->fl6_dst,
536 up->len, fl->proto, csum );
526 if (uh->check == 0) 537 if (uh->check == 0)
527 uh->check = -1; 538 uh->check = -1;
528 539
529send:
530 err = ip6_push_pending_frames(sk); 540 err = ip6_push_pending_frames(sk);
531out: 541out:
532 up->len = 0; 542 up->len = 0;
@@ -534,7 +544,7 @@ out:
534 return err; 544 return err;
535} 545}
536 546
537static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, 547int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk,
538 struct msghdr *msg, size_t len) 548 struct msghdr *msg, size_t len)
539{ 549{
540 struct ipv6_txoptions opt_space; 550 struct ipv6_txoptions opt_space;
@@ -554,6 +564,8 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk,
554 int corkreq = up->corkflag || msg->msg_flags&MSG_MORE; 564 int corkreq = up->corkflag || msg->msg_flags&MSG_MORE;
555 int err; 565 int err;
556 int connected = 0; 566 int connected = 0;
567 int is_udplite = up->pcflag;
568 int (*getfrag)(void *, char *, int, int, int, struct sk_buff *);
557 569
558 /* destination address check */ 570 /* destination address check */
559 if (sin6) { 571 if (sin6) {
@@ -694,7 +706,7 @@ do_udp_sendmsg:
694 opt = fl6_merge_options(&opt_space, flowlabel, opt); 706 opt = fl6_merge_options(&opt_space, flowlabel, opt);
695 opt = ipv6_fixup_options(&opt_space, opt); 707 opt = ipv6_fixup_options(&opt_space, opt);
696 708
697 fl.proto = IPPROTO_UDP; 709 fl.proto = sk->sk_protocol;
698 ipv6_addr_copy(&fl.fl6_dst, daddr); 710 ipv6_addr_copy(&fl.fl6_dst, daddr);
699 if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr)) 711 if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr))
700 ipv6_addr_copy(&fl.fl6_src, &np->saddr); 712 ipv6_addr_copy(&fl.fl6_src, &np->saddr);
@@ -761,7 +773,8 @@ back_from_confirm:
761 773
762do_append_data: 774do_append_data:
763 up->len += ulen; 775 up->len += ulen;
764 err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov, ulen, 776 getfrag = is_udplite ? udplite_getfrag : ip_generic_getfrag;
777 err = ip6_append_data(sk, getfrag, msg->msg_iov, ulen,
765 sizeof(struct udphdr), hlimit, tclass, opt, &fl, 778 sizeof(struct udphdr), hlimit, tclass, opt, &fl,
766 (struct rt6_info*)dst, 779 (struct rt6_info*)dst,
767 corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags); 780 corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags);
@@ -793,7 +806,7 @@ do_append_data:
793out: 806out:
794 fl6_sock_release(flowlabel); 807 fl6_sock_release(flowlabel);
795 if (!err) { 808 if (!err) {
796 UDP6_INC_STATS_USER(UDP_MIB_OUTDATAGRAMS); 809 UDP6_INC_STATS_USER(UDP_MIB_OUTDATAGRAMS, is_udplite);
797 return len; 810 return len;
798 } 811 }
799 /* 812 /*
@@ -804,7 +817,7 @@ out:
804 * seems like overkill. 817 * seems like overkill.
805 */ 818 */
806 if (err == -ENOBUFS || test_bit(SOCK_NOSPACE, &sk->sk_socket->flags)) { 819 if (err == -ENOBUFS || test_bit(SOCK_NOSPACE, &sk->sk_socket->flags)) {
807 UDP6_INC_STATS_USER(UDP_MIB_SNDBUFERRORS); 820 UDP6_INC_STATS_USER(UDP_MIB_SNDBUFERRORS, is_udplite);
808 } 821 }
809 return err; 822 return err;
810 823
@@ -816,7 +829,7 @@ do_confirm:
816 goto out; 829 goto out;
817} 830}
818 831
819static int udpv6_destroy_sock(struct sock *sk) 832int udpv6_destroy_sock(struct sock *sk)
820{ 833{
821 lock_sock(sk); 834 lock_sock(sk);
822 udp_v6_flush_pending_frames(sk); 835 udp_v6_flush_pending_frames(sk);
@@ -854,7 +867,6 @@ static int do_udpv6_setsockopt(struct sock *sk, int level, int optname,
854 release_sock(sk); 867 release_sock(sk);
855 } 868 }
856 break; 869 break;
857
858 case UDP_ENCAP: 870 case UDP_ENCAP:
859 switch (val) { 871 switch (val) {
860 case 0: 872 case 0:
@@ -866,6 +878,24 @@ static int do_udpv6_setsockopt(struct sock *sk, int level, int optname,
866 } 878 }
867 break; 879 break;
868 880
881 case UDPLITE_SEND_CSCOV:
882 if (!up->pcflag) /* Disable the option on UDP sockets */
883 return -ENOPROTOOPT;
884 if (val != 0 && val < 8) /* Illegal coverage: use default (8) */
885 val = 8;
886 up->pcslen = val;
887 up->pcflag |= UDPLITE_SEND_CC;
888 break;
889
890 case UDPLITE_RECV_CSCOV:
891 if (!up->pcflag) /* Disable the option on UDP sockets */
892 return -ENOPROTOOPT;
893 if (val != 0 && val < 8) /* Avoid silly minimal values. */
894 val = 8;
895 up->pcrlen = val;
896 up->pcflag |= UDPLITE_RECV_CC;
897 break;
898
869 default: 899 default:
870 err = -ENOPROTOOPT; 900 err = -ENOPROTOOPT;
871 break; 901 break;
@@ -874,22 +904,21 @@ static int do_udpv6_setsockopt(struct sock *sk, int level, int optname,
874 return err; 904 return err;
875} 905}
876 906
877static int udpv6_setsockopt(struct sock *sk, int level, int optname, 907int udpv6_setsockopt(struct sock *sk, int level, int optname,
878 char __user *optval, int optlen) 908 char __user *optval, int optlen)
879{ 909{
880 if (level != SOL_UDP) 910 if (level == SOL_UDP || level == SOL_UDPLITE)
881 return ipv6_setsockopt(sk, level, optname, optval, optlen); 911 return do_udpv6_setsockopt(sk, level, optname, optval, optlen);
882 return do_udpv6_setsockopt(sk, level, optname, optval, optlen); 912 return ipv6_setsockopt(sk, level, optname, optval, optlen);
883} 913}
884 914
885#ifdef CONFIG_COMPAT 915#ifdef CONFIG_COMPAT
886static int compat_udpv6_setsockopt(struct sock *sk, int level, int optname, 916int compat_udpv6_setsockopt(struct sock *sk, int level, int optname,
887 char __user *optval, int optlen) 917 char __user *optval, int optlen)
888{ 918{
889 if (level != SOL_UDP) 919 if (level == SOL_UDP || level == SOL_UDPLITE)
890 return compat_ipv6_setsockopt(sk, level, optname, 920 return do_udpv6_setsockopt(sk, level, optname, optval, optlen);
891 optval, optlen); 921 return compat_ipv6_setsockopt(sk, level, optname, optval, optlen);
892 return do_udpv6_setsockopt(sk, level, optname, optval, optlen);
893} 922}
894#endif 923#endif
895 924
@@ -916,6 +945,14 @@ static int do_udpv6_getsockopt(struct sock *sk, int level, int optname,
916 val = up->encap_type; 945 val = up->encap_type;
917 break; 946 break;
918 947
948 case UDPLITE_SEND_CSCOV:
949 val = up->pcslen;
950 break;
951
952 case UDPLITE_RECV_CSCOV:
953 val = up->pcrlen;
954 break;
955
919 default: 956 default:
920 return -ENOPROTOOPT; 957 return -ENOPROTOOPT;
921 }; 958 };
@@ -927,22 +964,21 @@ static int do_udpv6_getsockopt(struct sock *sk, int level, int optname,
927 return 0; 964 return 0;
928} 965}
929 966
930static int udpv6_getsockopt(struct sock *sk, int level, int optname, 967int udpv6_getsockopt(struct sock *sk, int level, int optname,
931 char __user *optval, int __user *optlen) 968 char __user *optval, int __user *optlen)
932{ 969{
933 if (level != SOL_UDP) 970 if (level == SOL_UDP || level == SOL_UDPLITE)
934 return ipv6_getsockopt(sk, level, optname, optval, optlen); 971 return do_udpv6_getsockopt(sk, level, optname, optval, optlen);
935 return do_udpv6_getsockopt(sk, level, optname, optval, optlen); 972 return ipv6_getsockopt(sk, level, optname, optval, optlen);
936} 973}
937 974
938#ifdef CONFIG_COMPAT 975#ifdef CONFIG_COMPAT
939static int compat_udpv6_getsockopt(struct sock *sk, int level, int optname, 976int compat_udpv6_getsockopt(struct sock *sk, int level, int optname,
940 char __user *optval, int __user *optlen) 977 char __user *optval, int __user *optlen)
941{ 978{
942 if (level != SOL_UDP) 979 if (level == SOL_UDP || level == SOL_UDPLITE)
943 return compat_ipv6_getsockopt(sk, level, optname, 980 return do_udpv6_getsockopt(sk, level, optname, optval, optlen);
944 optval, optlen); 981 return compat_ipv6_getsockopt(sk, level, optname, optval, optlen);
945 return do_udpv6_getsockopt(sk, level, optname, optval, optlen);
946} 982}
947#endif 983#endif
948 984
@@ -983,7 +1019,7 @@ static void udp6_sock_seq_show(struct seq_file *seq, struct sock *sp, int bucket
983 atomic_read(&sp->sk_refcnt), sp); 1019 atomic_read(&sp->sk_refcnt), sp);
984} 1020}
985 1021
986static int udp6_seq_show(struct seq_file *seq, void *v) 1022int udp6_seq_show(struct seq_file *seq, void *v)
987{ 1023{
988 if (v == SEQ_START_TOKEN) 1024 if (v == SEQ_START_TOKEN)
989 seq_printf(seq, 1025 seq_printf(seq,
@@ -1002,6 +1038,7 @@ static struct udp_seq_afinfo udp6_seq_afinfo = {
1002 .owner = THIS_MODULE, 1038 .owner = THIS_MODULE,
1003 .name = "udp6", 1039 .name = "udp6",
1004 .family = AF_INET6, 1040 .family = AF_INET6,
1041 .hashtable = udp_hash,
1005 .seq_show = udp6_seq_show, 1042 .seq_show = udp6_seq_show,
1006 .seq_fops = &udp6_seq_fops, 1043 .seq_fops = &udp6_seq_fops,
1007}; 1044};
@@ -1021,7 +1058,7 @@ void udp6_proc_exit(void) {
1021struct proto udpv6_prot = { 1058struct proto udpv6_prot = {
1022 .name = "UDPv6", 1059 .name = "UDPv6",
1023 .owner = THIS_MODULE, 1060 .owner = THIS_MODULE,
1024 .close = udpv6_close, 1061 .close = udp_lib_close,
1025 .connect = ip6_datagram_connect, 1062 .connect = ip6_datagram_connect,
1026 .disconnect = udp_disconnect, 1063 .disconnect = udp_disconnect,
1027 .ioctl = udp_ioctl, 1064 .ioctl = udp_ioctl,
@@ -1031,8 +1068,8 @@ struct proto udpv6_prot = {
1031 .sendmsg = udpv6_sendmsg, 1068 .sendmsg = udpv6_sendmsg,
1032 .recvmsg = udpv6_recvmsg, 1069 .recvmsg = udpv6_recvmsg,
1033 .backlog_rcv = udpv6_queue_rcv_skb, 1070 .backlog_rcv = udpv6_queue_rcv_skb,
1034 .hash = udp_v6_hash, 1071 .hash = udp_lib_hash,
1035 .unhash = udp_v6_unhash, 1072 .unhash = udp_lib_unhash,
1036 .get_port = udp_v6_get_port, 1073 .get_port = udp_v6_get_port,
1037 .obj_size = sizeof(struct udp6_sock), 1074 .obj_size = sizeof(struct udp6_sock),
1038#ifdef CONFIG_COMPAT 1075#ifdef CONFIG_COMPAT
diff --git a/net/ipv6/udp_impl.h b/net/ipv6/udp_impl.h
new file mode 100644
index 000000000000..ec9878899128
--- /dev/null
+++ b/net/ipv6/udp_impl.h
@@ -0,0 +1,34 @@
1#ifndef _UDP6_IMPL_H
2#define _UDP6_IMPL_H
3#include <net/udp.h>
4#include <net/udplite.h>
5#include <net/protocol.h>
6#include <net/addrconf.h>
7#include <net/inet_common.h>
8
9extern int __udp6_lib_rcv(struct sk_buff **, struct hlist_head [], int );
10extern void __udp6_lib_err(struct sk_buff *, struct inet6_skb_parm *,
11 int , int , int , __be32 , struct hlist_head []);
12
13extern int udpv6_getsockopt(struct sock *sk, int level, int optname,
14 char __user *optval, int __user *optlen);
15extern int udpv6_setsockopt(struct sock *sk, int level, int optname,
16 char __user *optval, int optlen);
17#ifdef CONFIG_COMPAT
18extern int compat_udpv6_setsockopt(struct sock *sk, int level, int optname,
19 char __user *optval, int optlen);
20extern int compat_udpv6_getsockopt(struct sock *sk, int level, int optname,
21 char __user *optval, int __user *optlen);
22#endif
23extern int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk,
24 struct msghdr *msg, size_t len);
25extern int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk,
26 struct msghdr *msg, size_t len,
27 int noblock, int flags, int *addr_len);
28extern int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb);
29extern int udpv6_destroy_sock(struct sock *sk);
30
31#ifdef CONFIG_PROC_FS
32extern int udp6_seq_show(struct seq_file *seq, void *v);
33#endif
34#endif /* _UDP6_IMPL_H */
diff --git a/net/ipv6/udplite.c b/net/ipv6/udplite.c
new file mode 100644
index 000000000000..e0ec5e63004a
--- /dev/null
+++ b/net/ipv6/udplite.c
@@ -0,0 +1,105 @@
1/*
2 * UDPLITEv6 An implementation of the UDP-Lite protocol over IPv6.
3 * See also net/ipv4/udplite.c
4 *
5 * Version: $Id: udplite.c,v 1.9 2006/10/19 08:28:10 gerrit Exp $
6 *
7 * Authors: Gerrit Renker <gerrit@erg.abdn.ac.uk>
8 *
9 * Changes:
10 * Fixes:
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version
14 * 2 of the License, or (at your option) any later version.
15 */
16#include "udp_impl.h"
17
18DEFINE_SNMP_STAT(struct udp_mib, udplite_stats_in6) __read_mostly;
19
20static __inline__ int udplitev6_rcv(struct sk_buff **pskb)
21{
22 return __udp6_lib_rcv(pskb, udplite_hash, 1);
23}
24
25static __inline__ void udplitev6_err(struct sk_buff *skb,
26 struct inet6_skb_parm *opt,
27 int type, int code, int offset, __u32 info)
28{
29 return __udp6_lib_err(skb, opt, type, code, offset, info, udplite_hash);
30}
31
32static struct inet6_protocol udplitev6_protocol = {
33 .handler = udplitev6_rcv,
34 .err_handler = udplitev6_err,
35 .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
36};
37
38static __inline__ int udplite_v6_get_port(struct sock *sk, unsigned short snum)
39{
40 return udplite_get_port(sk, snum, ipv6_rcv_saddr_equal);
41}
42
43struct proto udplitev6_prot = {
44 .name = "UDPLITEv6",
45 .owner = THIS_MODULE,
46 .close = udp_lib_close,
47 .connect = ip6_datagram_connect,
48 .disconnect = udp_disconnect,
49 .ioctl = udp_ioctl,
50 .init = udplite_sk_init,
51 .destroy = udpv6_destroy_sock,
52 .setsockopt = udpv6_setsockopt,
53 .getsockopt = udpv6_getsockopt,
54 .sendmsg = udpv6_sendmsg,
55 .recvmsg = udpv6_recvmsg,
56 .backlog_rcv = udpv6_queue_rcv_skb,
57 .hash = udp_lib_hash,
58 .unhash = udp_lib_unhash,
59 .get_port = udplite_v6_get_port,
60 .obj_size = sizeof(struct udp6_sock),
61#ifdef CONFIG_COMPAT
62 .compat_setsockopt = compat_udpv6_setsockopt,
63 .compat_getsockopt = compat_udpv6_getsockopt,
64#endif
65};
66
67static struct inet_protosw udplite6_protosw = {
68 .type = SOCK_DGRAM,
69 .protocol = IPPROTO_UDPLITE,
70 .prot = &udplitev6_prot,
71 .ops = &inet6_dgram_ops,
72 .capability = -1,
73 .no_check = 0,
74 .flags = INET_PROTOSW_PERMANENT,
75};
76
77void __init udplitev6_init(void)
78{
79 if (inet6_add_protocol(&udplitev6_protocol, IPPROTO_UDPLITE) < 0)
80 printk(KERN_ERR "%s: Could not register.\n", __FUNCTION__);
81
82 inet6_register_protosw(&udplite6_protosw);
83}
84
85#ifdef CONFIG_PROC_FS
86static struct file_operations udplite6_seq_fops;
87static struct udp_seq_afinfo udplite6_seq_afinfo = {
88 .owner = THIS_MODULE,
89 .name = "udplite6",
90 .family = AF_INET6,
91 .hashtable = udplite_hash,
92 .seq_show = udp6_seq_show,
93 .seq_fops = &udplite6_seq_fops,
94};
95
96int __init udplite6_proc_init(void)
97{
98 return udp_proc_register(&udplite6_seq_afinfo);
99}
100
101void udplite6_proc_exit(void)
102{
103 udp_proc_unregister(&udplite6_seq_afinfo);
104}
105#endif
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 2fba1f0739aa..8dffd4daae9c 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -274,6 +274,7 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl)
274 break; 274 break;
275 275
276 case IPPROTO_UDP: 276 case IPPROTO_UDP:
277 case IPPROTO_UDPLITE:
277 case IPPROTO_TCP: 278 case IPPROTO_TCP:
278 case IPPROTO_SCTP: 279 case IPPROTO_SCTP:
279 case IPPROTO_DCCP: 280 case IPPROTO_DCCP:
diff --git a/net/netfilter/xt_multiport.c b/net/netfilter/xt_multiport.c
index b4293058c6ff..1602086c7fd6 100644
--- a/net/netfilter/xt_multiport.c
+++ b/net/netfilter/xt_multiport.c
@@ -1,5 +1,5 @@
1/* Kernel module to match one of a list of TCP/UDP/SCTP/DCCP ports: ports are in 1/* Kernel module to match one of a list of TCP/UDP(-Lite)/SCTP/DCCP ports:
2 the same place so we can treat them as equal. */ 2 ports are in the same place so we can treat them as equal. */
3 3
4/* (C) 1999-2001 Paul `Rusty' Russell 4/* (C) 1999-2001 Paul `Rusty' Russell
5 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org> 5 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
@@ -162,6 +162,7 @@ check(u_int16_t proto,
162{ 162{
163 /* Must specify supported protocol, no unknown flags or bad count */ 163 /* Must specify supported protocol, no unknown flags or bad count */
164 return (proto == IPPROTO_TCP || proto == IPPROTO_UDP 164 return (proto == IPPROTO_TCP || proto == IPPROTO_UDP
165 || proto == IPPROTO_UDPLITE
165 || proto == IPPROTO_SCTP || proto == IPPROTO_DCCP) 166 || proto == IPPROTO_SCTP || proto == IPPROTO_DCCP)
166 && !(ip_invflags & XT_INV_PROTO) 167 && !(ip_invflags & XT_INV_PROTO)
167 && (match_flags == XT_MULTIPORT_SOURCE 168 && (match_flags == XT_MULTIPORT_SOURCE
diff --git a/net/netfilter/xt_tcpudp.c b/net/netfilter/xt_tcpudp.c
index e76a68e0bc66..46414b562a19 100644
--- a/net/netfilter/xt_tcpudp.c
+++ b/net/netfilter/xt_tcpudp.c
@@ -10,7 +10,7 @@
10#include <linux/netfilter_ipv4/ip_tables.h> 10#include <linux/netfilter_ipv4/ip_tables.h>
11#include <linux/netfilter_ipv6/ip6_tables.h> 11#include <linux/netfilter_ipv6/ip6_tables.h>
12 12
13MODULE_DESCRIPTION("x_tables match for TCP and UDP, supports IPv4 and IPv6"); 13MODULE_DESCRIPTION("x_tables match for TCP and UDP(-Lite), supports IPv4 and IPv6");
14MODULE_LICENSE("GPL"); 14MODULE_LICENSE("GPL");
15MODULE_ALIAS("xt_tcp"); 15MODULE_ALIAS("xt_tcp");
16MODULE_ALIAS("xt_udp"); 16MODULE_ALIAS("xt_udp");
@@ -234,6 +234,24 @@ static struct xt_match xt_tcpudp_match[] = {
234 .proto = IPPROTO_UDP, 234 .proto = IPPROTO_UDP,
235 .me = THIS_MODULE, 235 .me = THIS_MODULE,
236 }, 236 },
237 {
238 .name = "udplite",
239 .family = AF_INET,
240 .checkentry = udp_checkentry,
241 .match = udp_match,
242 .matchsize = sizeof(struct xt_udp),
243 .proto = IPPROTO_UDPLITE,
244 .me = THIS_MODULE,
245 },
246 {
247 .name = "udplite",
248 .family = AF_INET6,
249 .checkentry = udp_checkentry,
250 .match = udp_match,
251 .matchsize = sizeof(struct xt_udp),
252 .proto = IPPROTO_UDPLITE,
253 .me = THIS_MODULE,
254 },
237}; 255};
238 256
239static int __init xt_tcpudp_init(void) 257static int __init xt_tcpudp_init(void)