1 /* 2 * Definitions for the UDP-Lite (RFC 3828) code. 3 */ 4 #ifndef _UDPLITE_H 5 #define _UDPLITE_H 6 7 #include <net/ip6_checksum.h> 8 9 /* UDP-Lite socket options */ 10 #define UDPLITE_SEND_CSCOV 10 /* sender partial coverage (as sent) */ 11 #define UDPLITE_RECV_CSCOV 11 /* receiver partial coverage (threshold ) */ 12 13 extern struct proto udplite_prot; 14 extern struct hlist_head udplite_hash[UDP_HTABLE_SIZE]; 15 16 /* UDP-Lite does not have a standardized MIB yet, so we inherit from UDP */ 17 DECLARE_SNMP_STAT(struct udp_mib, udplite_statistics); 18 19 /* 20 * Checksum computation is all in software, hence simpler getfrag. 21 */ 22 static __inline__ int udplite_getfrag(void *from, char *to, int offset, 23 int len, int odd, struct sk_buff *skb) 24 { 25 return memcpy_fromiovecend(to, (struct iovec *) from, offset, len); 26 } 27 28 /* Designate sk as UDP-Lite socket */ 29 static inline int udplite_sk_init(struct sock *sk) 30 { 31 udp_sk(sk)->pcflag = UDPLITE_BIT; 32 return 0; 33 } 34 35 /* 36 * Checksumming routines 37 */ 38 static inline int udplite_checksum_init(struct sk_buff *skb, struct udphdr *uh) 39 { 40 u16 cscov; 41 42 /* In UDPv4 a zero checksum means that the transmitter generated no 43 * checksum. UDP-Lite (like IPv6) mandates checksums, hence packets 44 * with a zero checksum field are illegal. */ 45 if (uh->check == 0) { 46 LIMIT_NETDEBUG(KERN_DEBUG "UDPLITE: zeroed checksum field\n"); 47 return 1; 48 } 49 50 cscov = ntohs(uh->len); 51 52 if (cscov == 0) /* Indicates that full coverage is required. */ 53 ; 54 else if (cscov < 8 || cscov > skb->len) { 55 /* 56 * Coverage length violates RFC 3828: log and discard silently. 57 */ 58 LIMIT_NETDEBUG(KERN_DEBUG "UDPLITE: bad csum coverage %d/%d\n", 59 cscov, skb->len); 60 return 1; 61 62 } else if (cscov < skb->len) { 63 UDP_SKB_CB(skb)->partial_cov = 1; 64 UDP_SKB_CB(skb)->cscov = cscov; 65 if (skb->ip_summed == CHECKSUM_COMPLETE) 66 skb->ip_summed = CHECKSUM_NONE; 67 } 68 69 return 0; 70 } 71 72 static inline int udplite_sender_cscov(struct udp_sock *up, struct udphdr *uh) 73 { 74 int cscov = up->len; 75 76 /* 77 * Sender has set `partial coverage' option on UDP-Lite socket 78 */ 79 if (up->pcflag & UDPLITE_SEND_CC) { 80 if (up->pcslen < up->len) { 81 /* up->pcslen == 0 means that full coverage is required, 82 * partial coverage only if 0 < up->pcslen < up->len */ 83 if (0 < up->pcslen) { 84 cscov = up->pcslen; 85 } 86 uh->len = htons(up->pcslen); 87 } 88 /* 89 * NOTE: Causes for the error case `up->pcslen > up->len': 90 * (i) Application error (will not be penalized). 91 * (ii) Payload too big for send buffer: data is split 92 * into several packets, each with its own header. 93 * In this case (e.g. last segment), coverage may 94 * exceed packet length. 95 * Since packets with coverage length > packet length are 96 * illegal, we fall back to the defaults here. 97 */ 98 } 99 return cscov; 100 } 101 102 static inline __wsum udplite_csum_outgoing(struct sock *sk, struct sk_buff *skb) 103 { 104 int off, len, cscov = udplite_sender_cscov(udp_sk(sk), skb->h.uh); 105 __wsum csum = 0; 106 107 skb->ip_summed = CHECKSUM_NONE; /* no HW support for checksumming */ 108 109 skb_queue_walk(&sk->sk_write_queue, skb) { 110 off = skb->h.raw - skb->data; 111 len = skb->len - off; 112 113 csum = skb_checksum(skb, off, (cscov > len)? len : cscov, csum); 114 115 if ((cscov -= len) <= 0) 116 break; 117 } 118 return csum; 119 } 120 121 extern void udplite4_register(void); 122 extern int udplite_get_port(struct sock *sk, unsigned short snum, 123 int (*scmp)(const struct sock *, const struct sock *)); 124 #endif /* _UDPLITE_H */ 125