diff options
| author | Gerrit Renker <gerrit@erg.abdn.ac.uk> | 2006-11-27 14:10:57 -0500 |
|---|---|---|
| committer | David S. Miller <davem@sunset.davemloft.net> | 2006-12-03 00:22:46 -0500 |
| commit | ba4e58eca8aa9473b44fdfd312f26c4a2e7798b3 (patch) | |
| tree | 700f8f989f48da480beb83b983637cfd2b5a3f67 /include | |
| parent | 6051e2f4fb68fc8e5343db58fa680ece376f405c (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>
Diffstat (limited to 'include')
| -rw-r--r-- | include/linux/in.h | 1 | ||||
| -rw-r--r-- | include/linux/socket.h | 1 | ||||
| -rw-r--r-- | include/linux/udp.h | 12 | ||||
| -rw-r--r-- | include/net/ipv6.h | 12 | ||||
| -rw-r--r-- | include/net/transp_v6.h | 2 | ||||
| -rw-r--r-- | include/net/udp.h | 91 | ||||
| -rw-r--r-- | include/net/udplite.h | 149 | ||||
| -rw-r--r-- | include/net/xfrm.h | 2 |
8 files changed, 263 insertions, 7 deletions
diff --git a/include/linux/in.h b/include/linux/in.h index 2619859f6e..1912e7c0bc 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 3614090946..592b666798 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 014b41d1e3..564f3b0501 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 | ||
| 42 | struct udp_sock { | 43 | struct 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 | ||
| 55 | static inline struct udp_sock *udp_sk(const struct sock *sk) | 66 | static 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 3c266ad99a..9390649bbf 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 | }) |
| 160 | DECLARE_SNMP_STAT(struct udp_mib, udp_stats_in6); | 160 | DECLARE_SNMP_STAT(struct udp_mib, udp_stats_in6); |
| 161 | #define UDP6_INC_STATS(field) SNMP_INC_STATS(udp_stats_in6, field) | 161 | DECLARE_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 | ||
| 165 | int snmp6_register_dev(struct inet6_dev *idev); | 169 | int snmp6_register_dev(struct inet6_dev *idev); |
| 166 | int snmp6_unregister_dev(struct inet6_dev *idev); | 170 | int snmp6_unregister_dev(struct inet6_dev *idev); |
| @@ -604,6 +608,8 @@ extern int tcp6_proc_init(void); | |||
| 604 | extern void tcp6_proc_exit(void); | 608 | extern void tcp6_proc_exit(void); |
| 605 | extern int udp6_proc_init(void); | 609 | extern int udp6_proc_init(void); |
| 606 | extern void udp6_proc_exit(void); | 610 | extern void udp6_proc_exit(void); |
| 611 | extern int udplite6_proc_init(void); | ||
| 612 | extern void udplite6_proc_exit(void); | ||
| 607 | extern int ipv6_misc_proc_init(void); | 613 | extern int ipv6_misc_proc_init(void); |
| 608 | extern void ipv6_misc_proc_exit(void); | 614 | extern void ipv6_misc_proc_exit(void); |
| 609 | 615 | ||
diff --git a/include/net/transp_v6.h b/include/net/transp_v6.h index 61f724c103..409da3a9a4 100644 --- a/include/net/transp_v6.h +++ b/include/net/transp_v6.h | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | 11 | ||
| 12 | extern struct proto rawv6_prot; | 12 | extern struct proto rawv6_prot; |
| 13 | extern struct proto udpv6_prot; | 13 | extern struct proto udpv6_prot; |
| 14 | extern struct proto udplitev6_prot; | ||
| 14 | extern struct proto tcpv6_prot; | 15 | extern struct proto tcpv6_prot; |
| 15 | 16 | ||
| 16 | struct flowi; | 17 | struct flowi; |
| @@ -24,6 +25,7 @@ extern void ipv6_destopt_init(void); | |||
| 24 | /* transport protocols */ | 25 | /* transport protocols */ |
| 25 | extern void rawv6_init(void); | 26 | extern void rawv6_init(void); |
| 26 | extern void udpv6_init(void); | 27 | extern void udpv6_init(void); |
| 28 | extern void udplitev6_init(void); | ||
| 27 | extern void tcpv6_init(void); | 29 | extern void tcpv6_init(void); |
| 28 | 30 | ||
| 29 | extern int udpv6_connect(struct sock *sk, | 31 | extern int udpv6_connect(struct sock *sk, |
diff --git a/include/net/udp.h b/include/net/udp.h index db0c05f675..4f0626735e 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 | */ | ||
| 40 | struct 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 | ||
| 33 | extern struct hlist_head udp_hash[UDP_HTABLE_SIZE]; | 52 | extern struct hlist_head udp_hash[UDP_HTABLE_SIZE]; |
| 34 | extern rwlock_t udp_hash_lock; | 53 | extern rwlock_t udp_hash_lock; |
| @@ -47,6 +66,62 @@ extern struct proto udp_prot; | |||
| 47 | 66 | ||
| 48 | struct sk_buff; | 67 | struct sk_buff; |
| 49 | 68 | ||
| 69 | /* | ||
| 70 | * Generic checksumming routines for UDP(-Lite) v4 and v6 | ||
| 71 | */ | ||
| 72 | static 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 | |||
| 80 | static __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 | */ | ||
| 92 | static 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 */ | ||
| 103 | static inline void udp_lib_hash(struct sock *sk) | ||
| 104 | { | ||
| 105 | BUG(); | ||
| 106 | } | ||
| 107 | |||
| 108 | static 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 | |||
| 118 | static inline void udp_lib_close(struct sock *sk, long timeout) | ||
| 119 | { | ||
| 120 | sk_common_release(sk); | ||
| 121 | } | ||
| 122 | |||
| 123 | |||
| 124 | /* net/ipv4/udp.c */ | ||
| 50 | extern int udp_get_port(struct sock *sk, unsigned short snum, | 125 | extern 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 *)); |
| 52 | extern void udp_err(struct sk_buff *, u32); | 127 | extern 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 | ||
| 63 | DECLARE_SNMP_STAT(struct udp_mib, udp_statistics); | 138 | DECLARE_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 */ |
| 69 | struct udp_seq_afinfo { | 150 | struct 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 | ||
| 77 | struct udp_iter_state { | 159 | struct 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 0000000000..1473b3e490 --- /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 | |||
| 11 | extern struct proto udplite_prot; | ||
| 12 | extern struct hlist_head udplite_hash[UDP_HTABLE_SIZE]; | ||
| 13 | |||
| 14 | /* UDP-Lite does not have a standardized MIB yet, so we inherit from UDP */ | ||
| 15 | DECLARE_SNMP_STAT(struct udp_mib, udplite_statistics); | ||
| 16 | |||
| 17 | /* | ||
| 18 | * Checksum computation is all in software, hence simpler getfrag. | ||
| 19 | */ | ||
| 20 | static __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 */ | ||
| 27 | static 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 | */ | ||
| 36 | static 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 | |||
| 75 | static __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 | |||
| 86 | static __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 | |||
| 97 | static 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 | |||
| 127 | static 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 | |||
| 146 | extern void udplite4_register(void); | ||
| 147 | extern 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 81c91e8a32..3878a88ff6 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; |
