aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/skbuff.c
diff options
context:
space:
mode:
authorLinus Lüssing <linus.luessing@c0d3.blue>2015-05-02 08:01:07 -0400
committerDavid S. Miller <davem@davemloft.net>2015-05-04 14:49:23 -0400
commit9afd85c9e4552b276e2f4cfefd622bdeeffbbf26 (patch)
tree3657b92f850d03ec3a8f67e6171d5b61abdf3ae0 /net/core/skbuff.c
parent3c9e4f870012350a36dc3091c7a57f5ba2799afe (diff)
net: Export IGMP/MLD message validation code
With this patch, the IGMP and MLD message validation functions are moved from the bridge code to IPv4/IPv6 multicast files. Some small refactoring was done to enhance readibility and to iron out some differences in behaviour between the IGMP and MLD parsing code (e.g. the skb-cloning of MLD messages is now only done if necessary, just like the IGMP part always did). Finally, these IGMP and MLD message validation functions are exported so that not only the bridge can use it but batman-adv later, too. Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core/skbuff.c')
-rw-r--r--net/core/skbuff.c87
1 files changed, 87 insertions, 0 deletions
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 3cfff2a3d651..1e4278a4dd7e 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -4030,6 +4030,93 @@ int skb_checksum_setup(struct sk_buff *skb, bool recalculate)
4030} 4030}
4031EXPORT_SYMBOL(skb_checksum_setup); 4031EXPORT_SYMBOL(skb_checksum_setup);
4032 4032
4033/**
4034 * skb_checksum_maybe_trim - maybe trims the given skb
4035 * @skb: the skb to check
4036 * @transport_len: the data length beyond the network header
4037 *
4038 * Checks whether the given skb has data beyond the given transport length.
4039 * If so, returns a cloned skb trimmed to this transport length.
4040 * Otherwise returns the provided skb. Returns NULL in error cases
4041 * (e.g. transport_len exceeds skb length or out-of-memory).
4042 *
4043 * Caller needs to set the skb transport header and release the returned skb.
4044 * Provided skb is consumed.
4045 */
4046static struct sk_buff *skb_checksum_maybe_trim(struct sk_buff *skb,
4047 unsigned int transport_len)
4048{
4049 struct sk_buff *skb_chk;
4050 unsigned int len = skb_transport_offset(skb) + transport_len;
4051 int ret;
4052
4053 if (skb->len < len) {
4054 kfree_skb(skb);
4055 return NULL;
4056 } else if (skb->len == len) {
4057 return skb;
4058 }
4059
4060 skb_chk = skb_clone(skb, GFP_ATOMIC);
4061 kfree_skb(skb);
4062
4063 if (!skb_chk)
4064 return NULL;
4065
4066 ret = pskb_trim_rcsum(skb_chk, len);
4067 if (ret) {
4068 kfree_skb(skb_chk);
4069 return NULL;
4070 }
4071
4072 return skb_chk;
4073}
4074
4075/**
4076 * skb_checksum_trimmed - validate checksum of an skb
4077 * @skb: the skb to check
4078 * @transport_len: the data length beyond the network header
4079 * @skb_chkf: checksum function to use
4080 *
4081 * Applies the given checksum function skb_chkf to the provided skb.
4082 * Returns a checked and maybe trimmed skb. Returns NULL on error.
4083 *
4084 * If the skb has data beyond the given transport length, then a
4085 * trimmed & cloned skb is checked and returned.
4086 *
4087 * Caller needs to set the skb transport header and release the returned skb.
4088 * Provided skb is consumed.
4089 */
4090struct sk_buff *skb_checksum_trimmed(struct sk_buff *skb,
4091 unsigned int transport_len,
4092 __sum16(*skb_chkf)(struct sk_buff *skb))
4093{
4094 struct sk_buff *skb_chk;
4095 unsigned int offset = skb_transport_offset(skb);
4096 int ret;
4097
4098 skb_chk = skb_checksum_maybe_trim(skb, transport_len);
4099 if (!skb_chk)
4100 return NULL;
4101
4102 if (!pskb_may_pull(skb_chk, offset)) {
4103 kfree_skb(skb_chk);
4104 return NULL;
4105 }
4106
4107 __skb_pull(skb_chk, offset);
4108 ret = skb_chkf(skb_chk);
4109 __skb_push(skb_chk, offset);
4110
4111 if (ret) {
4112 kfree_skb(skb_chk);
4113 return NULL;
4114 }
4115
4116 return skb_chk;
4117}
4118EXPORT_SYMBOL(skb_checksum_trimmed);
4119
4033void __skb_warn_lro_forwarding(const struct sk_buff *skb) 4120void __skb_warn_lro_forwarding(const struct sk_buff *skb)
4034{ 4121{
4035 net_warn_ratelimited("%s: received packets cannot be forwarded while LRO is enabled\n", 4122 net_warn_ratelimited("%s: received packets cannot be forwarded while LRO is enabled\n",