rmnet_wlan_fragment.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /* Copyright (c) 2021, The Linux Foundation. All rights reserved.
  3. * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  4. *
  5. * RMNET WLAN fragment handler framework
  6. *
  7. */
  8. #include <linux/types.h>
  9. #include <linux/skbuff.h>
  10. #include <net/ip.h>
  11. #include <net/ipv6.h>
  12. #include <linux/rcupdate.h>
  13. #include <linux/list.h>
  14. #include <linux/rculist.h>
  15. #include <linux/hashtable.h>
  16. #include <linux/hrtimer.h>
  17. #include "rmnet_wlan.h"
  18. #include "rmnet_wlan_stats.h"
  19. #include "rmnet_wlan_fragment.h"
  20. #define DATARMNET598d70a086 ((0xeb7+1158-0x132d))
  21. #define DATARMNETeaee3af609 (const_ilog2(DATARMNET598d70a086))
  22. #define DATARMNET63a285d479 (100000000)
  23. struct DATARMNETdadb4e2c65{union{__be32 DATARMNETdfe430c2d6;struct in6_addr
  24. DATARMNET815cbb4bf5;};union{__be32 DATARMNET2cb607d686;struct in6_addr
  25. DATARMNETc3f31215b7;};__be32 id;u16 DATARMNET611d08d671;u16 DATARMNETb65c469a15;
  26. u8 DATARMNET0d956cc77a;};struct DATARMNET6f3b954709{struct hlist_node
  27. DATARMNETe8608dd267;struct list_head DATARMNET0f34bf3ea9;struct rcu_head
  28. DATARMNET28bfe9e6ad;struct hrtimer DATARMNET9f31ce5d2d;struct
  29. DATARMNETdadb4e2c65 DATARMNET54338da2ff;struct DATARMNET8d3c2559ca*
  30. DATARMNET7ed5754a5c;};static DEFINE_SPINLOCK(DATARMNET531b038fcd);static
  31. DEFINE_HASHTABLE(DATARMNET6e79f38051,DATARMNETeaee3af609);static int
  32. DATARMNET24669a931d(const struct sk_buff*DATARMNET543491eb0f,unsigned int*
  33. DATARMNETb65c469a15,int DATARMNETbfd7eb99fe,unsigned short*DATARMNET0823b5e89c,
  34. int*DATARMNETfb0677cc3c){unsigned int DATARMNETab6f68a65c=skb_network_offset(
  35. DATARMNET543491eb0f)+sizeof(struct ipv6hdr);u8 nexthdr=ipv6_hdr(
  36. DATARMNET543491eb0f)->nexthdr;bool DATARMNET1034358542;if(DATARMNET0823b5e89c)*
  37. DATARMNET0823b5e89c=(0xd2d+202-0xdf7);if(*DATARMNETb65c469a15){struct ipv6hdr
  38. DATARMNET982faca395,*DATARMNETc46d75f0b8;DATARMNETc46d75f0b8=skb_header_pointer(
  39. DATARMNET543491eb0f,*DATARMNETb65c469a15,sizeof(DATARMNET982faca395),&
  40. DATARMNET982faca395);if(!DATARMNETc46d75f0b8||(DATARMNETc46d75f0b8->version!=
  41. (0xd03+244-0xdf1)))return-EBADMSG;DATARMNETab6f68a65c=*DATARMNETb65c469a15+
  42. sizeof(struct ipv6hdr);nexthdr=DATARMNETc46d75f0b8->nexthdr;}do{struct
  43. ipv6_opt_hdr DATARMNETb18a0d17a5,*DATARMNET7c56b76ea0;unsigned int
  44. DATARMNET4593c3f2c2;DATARMNET1034358542=(nexthdr==DATARMNETbfd7eb99fe);if((!
  45. ipv6_ext_hdr(nexthdr))||nexthdr==NEXTHDR_NONE){if(DATARMNETbfd7eb99fe<
  46. (0xd2d+202-0xdf7)||DATARMNET1034358542)break;return-ENOENT;}DATARMNET7c56b76ea0=
  47. skb_header_pointer(DATARMNET543491eb0f,DATARMNETab6f68a65c,sizeof(
  48. DATARMNETb18a0d17a5),&DATARMNETb18a0d17a5);if(!DATARMNET7c56b76ea0)return-
  49. EBADMSG;if(nexthdr==NEXTHDR_ROUTING){struct ipv6_rt_hdr DATARMNET942c8f7153,*
  50. DATARMNETb2650cb3cb;DATARMNETb2650cb3cb=skb_header_pointer(DATARMNET543491eb0f,
  51. DATARMNETab6f68a65c,sizeof(DATARMNET942c8f7153),&DATARMNET942c8f7153);if(!
  52. DATARMNETb2650cb3cb)return-EBADMSG;if(DATARMNETfb0677cc3c&&(*DATARMNETfb0677cc3c
  53. &IP6_FH_F_SKIP_RH)&&DATARMNETb2650cb3cb->segments_left==(0xd2d+202-0xdf7))
  54. DATARMNET1034358542=false;}if(nexthdr==NEXTHDR_FRAGMENT){unsigned short
  55. DATARMNET3ed4d6b164;__be16*DATARMNET748d4c9015;if(DATARMNETfb0677cc3c)*
  56. DATARMNETfb0677cc3c|=IP6_FH_F_FRAG;DATARMNET748d4c9015=skb_header_pointer(
  57. DATARMNET543491eb0f,DATARMNETab6f68a65c+offsetof(struct frag_hdr,frag_off),
  58. sizeof(DATARMNET3ed4d6b164),&DATARMNET3ed4d6b164);if(!DATARMNET748d4c9015)return
  59. -EBADMSG;DATARMNET3ed4d6b164=ntohs(*DATARMNET748d4c9015)&~(0xcfc+267-0xe00);if(
  60. DATARMNET3ed4d6b164){if(DATARMNETbfd7eb99fe<(0xd2d+202-0xdf7)&&((!ipv6_ext_hdr(
  61. DATARMNET7c56b76ea0->nexthdr))||DATARMNET7c56b76ea0->nexthdr==NEXTHDR_NONE)){if(
  62. DATARMNET0823b5e89c)*DATARMNET0823b5e89c=DATARMNET3ed4d6b164;return
  63. DATARMNET7c56b76ea0->nexthdr;}if(!DATARMNET1034358542)return-ENOENT;if(
  64. DATARMNET0823b5e89c)*DATARMNET0823b5e89c=DATARMNET3ed4d6b164;break;}
  65. DATARMNET4593c3f2c2=(0xd35+210-0xdff);}else if(nexthdr==NEXTHDR_AUTH){if(
  66. DATARMNETfb0677cc3c&&(*DATARMNETfb0677cc3c&IP6_FH_F_AUTH)&&(DATARMNETbfd7eb99fe<
  67. (0xd2d+202-0xdf7)))break;DATARMNET4593c3f2c2=ipv6_authlen(DATARMNET7c56b76ea0);}
  68. else DATARMNET4593c3f2c2=ipv6_optlen(DATARMNET7c56b76ea0);if(!
  69. DATARMNET1034358542){nexthdr=DATARMNET7c56b76ea0->nexthdr;DATARMNETab6f68a65c+=
  70. DATARMNET4593c3f2c2;}}while(!DATARMNET1034358542);*DATARMNETb65c469a15=
  71. DATARMNETab6f68a65c;return nexthdr;}static void DATARMNETc7c83f614f(struct
  72. DATARMNET6f3b954709*DATARMNET63b1a086d5,bool DATARMNET7a9bcaf1a3){struct
  73. DATARMNET8d3c2559ca*DATARMNET54338da2ff;int(*DATARMNET456ac0e8eb)(struct sk_buff
  74. *DATARMNET543491eb0f);struct sk_buff*DATARMNET543491eb0f,*DATARMNET0386f6f82a;
  75. DATARMNET456ac0e8eb=(DATARMNET7a9bcaf1a3)?netif_receive_skb:netif_rx;
  76. DATARMNET54338da2ff=DATARMNET63b1a086d5->DATARMNET7ed5754a5c;
  77. list_for_each_entry_safe(DATARMNET543491eb0f,DATARMNET0386f6f82a,&
  78. DATARMNET63b1a086d5->DATARMNET0f34bf3ea9,list){u32 DATARMNET248f120dd5;
  79. list_del_init(&DATARMNET543491eb0f->list);if(IS_ERR_OR_NULL(DATARMNET54338da2ff)
  80. ){DATARMNET456ac0e8eb(DATARMNET543491eb0f);continue;}if(DATARMNET4899053671(
  81. DATARMNET543491eb0f,DATARMNET54338da2ff)){DATARMNET248f120dd5=
  82. DATARMNETba232077da;DATARMNET456ac0e8eb(DATARMNET543491eb0f);}else{
  83. DATARMNET248f120dd5=DATARMNET7a58a5c1fc;}DATARMNET5ca94dbc3c(DATARMNET248f120dd5
  84. );}}static enum hrtimer_restart DATARMNETef43eced5f(struct hrtimer*
  85. DATARMNET6e4292679f){struct DATARMNET6f3b954709*DATARMNET63b1a086d5;unsigned
  86. long DATARMNETfb0677cc3c;spin_lock_irqsave(&DATARMNET531b038fcd,
  87. DATARMNETfb0677cc3c);DATARMNET63b1a086d5=container_of(DATARMNET6e4292679f,struct
  88. DATARMNET6f3b954709,DATARMNET9f31ce5d2d);hash_del_rcu(&DATARMNET63b1a086d5->
  89. DATARMNETe8608dd267);DATARMNETc7c83f614f(DATARMNET63b1a086d5,false);kfree_rcu(
  90. DATARMNET63b1a086d5,DATARMNET28bfe9e6ad);spin_unlock_irqrestore(&
  91. DATARMNET531b038fcd,DATARMNETfb0677cc3c);DATARMNET5ca94dbc3c(DATARMNETd691057b85
  92. );return HRTIMER_NORESTART;}static bool DATARMNETc529ac78b2(struct
  93. DATARMNETdadb4e2c65*DATARMNET75decd6f60,struct DATARMNETdadb4e2c65*
  94. DATARMNET6745cad668){if(DATARMNET75decd6f60->DATARMNET0d956cc77a!=
  95. DATARMNET6745cad668->DATARMNET0d956cc77a||DATARMNET75decd6f60->id!=
  96. DATARMNET6745cad668->id)return false;if(DATARMNET75decd6f60->DATARMNET0d956cc77a
  97. ==(0xd11+230-0xdf3))return DATARMNET75decd6f60->DATARMNETdfe430c2d6==
  98. DATARMNET6745cad668->DATARMNETdfe430c2d6&&DATARMNET75decd6f60->
  99. DATARMNET2cb607d686==DATARMNET6745cad668->DATARMNET2cb607d686;return!
  100. ipv6_addr_cmp(&DATARMNET75decd6f60->DATARMNET815cbb4bf5,&DATARMNET6745cad668->
  101. DATARMNET815cbb4bf5)&&!ipv6_addr_cmp(&DATARMNET75decd6f60->DATARMNETc3f31215b7,&
  102. DATARMNET6745cad668->DATARMNETc3f31215b7);}static struct DATARMNET6f3b954709*
  103. DATARMNET52b387f6cd(struct DATARMNETdadb4e2c65*DATARMNET54338da2ff){struct
  104. DATARMNET6f3b954709*DATARMNET63b1a086d5;unsigned long DATARMNETfb0677cc3c;
  105. spin_lock_irqsave(&DATARMNET531b038fcd,DATARMNETfb0677cc3c);
  106. hash_for_each_possible_rcu(DATARMNET6e79f38051,DATARMNET63b1a086d5,
  107. DATARMNETe8608dd267,DATARMNET54338da2ff->id){if(DATARMNETc529ac78b2(
  108. DATARMNET54338da2ff,&DATARMNET63b1a086d5->DATARMNET54338da2ff))goto
  109. DATARMNETbf4095f79e;}DATARMNET63b1a086d5=kzalloc(sizeof(*DATARMNET63b1a086d5),
  110. GFP_ATOMIC);if(!DATARMNET63b1a086d5)goto DATARMNETbf4095f79e;INIT_LIST_HEAD(&
  111. DATARMNET63b1a086d5->DATARMNET0f34bf3ea9);memcpy(&DATARMNET63b1a086d5->
  112. DATARMNET54338da2ff,DATARMNET54338da2ff,sizeof(*DATARMNET54338da2ff));
  113. hrtimer_init(&DATARMNET63b1a086d5->DATARMNET9f31ce5d2d,CLOCK_MONOTONIC,
  114. HRTIMER_MODE_REL);DATARMNET63b1a086d5->DATARMNET9f31ce5d2d.function=
  115. DATARMNETef43eced5f;hrtimer_start(&DATARMNET63b1a086d5->DATARMNET9f31ce5d2d,
  116. DATARMNET63a285d479,HRTIMER_MODE_REL);INIT_HLIST_NODE(&DATARMNET63b1a086d5->
  117. DATARMNETe8608dd267);hash_add_rcu(DATARMNET6e79f38051,&DATARMNET63b1a086d5->
  118. DATARMNETe8608dd267,DATARMNET54338da2ff->id);DATARMNETbf4095f79e:
  119. spin_unlock_irqrestore(&DATARMNET531b038fcd,DATARMNETfb0677cc3c);return
  120. DATARMNET63b1a086d5;}static int DATARMNET9d6ad3b16f(struct sk_buff*
  121. DATARMNET543491eb0f,struct DATARMNETb89ecedefc*DATARMNET3396919a68,struct
  122. DATARMNETdadb4e2c65*DATARMNET54338da2ff,struct DATARMNET8d3c2559ca*
  123. DATARMNET2d4b4cfc9e)__must_hold(RCU){struct DATARMNET6f3b954709*
  124. DATARMNET63b1a086d5;int DATARMNET61c2303133=(0xd26+209-0xdf6);
  125. DATARMNET5ca94dbc3c(DATARMNETd8273aa7e1);DATARMNET63b1a086d5=DATARMNET52b387f6cd
  126. (DATARMNET54338da2ff);if(!DATARMNET63b1a086d5){DATARMNET61c2303133=(-
  127. (0xd26+209-0xdf6));goto DATARMNETbf4095f79e;}if(unlikely(!hrtimer_is_queued(&
  128. DATARMNET63b1a086d5->DATARMNET9f31ce5d2d))){goto DATARMNETbf4095f79e;}
  129. hrtimer_start(&DATARMNET63b1a086d5->DATARMNET9f31ce5d2d,DATARMNET63a285d479,
  130. HRTIMER_MODE_REL);if(DATARMNET63b1a086d5->DATARMNET7ed5754a5c){if(IS_ERR(
  131. DATARMNET63b1a086d5->DATARMNET7ed5754a5c))goto DATARMNETbf4095f79e;if(!
  132. DATARMNET4899053671(DATARMNET543491eb0f,DATARMNET63b1a086d5->DATARMNET7ed5754a5c
  133. )){DATARMNET5ca94dbc3c(DATARMNET7a58a5c1fc);DATARMNET61c2303133=
  134. (0xd2d+202-0xdf7);goto DATARMNETbf4095f79e;}DATARMNET5ca94dbc3c(
  135. DATARMNETba232077da);goto DATARMNETbf4095f79e;}if(DATARMNET54338da2ff->
  136. DATARMNETb65c469a15){list_add_tail(&DATARMNET543491eb0f->list,&
  137. DATARMNET63b1a086d5->DATARMNET0f34bf3ea9);DATARMNET61c2303133=(0xd2d+202-0xdf7);
  138. DATARMNET5ca94dbc3c(DATARMNETe75ad1a949);goto DATARMNETbf4095f79e;}if(
  139. DATARMNET3396919a68->DATARMNET4924e79411==IPPROTO_TCP||DATARMNET3396919a68->
  140. DATARMNET4924e79411==IPPROTO_UDP){struct udphdr*DATARMNET75be5f3406=(struct
  141. udphdr*)(DATARMNET543491eb0f->data+DATARMNET54338da2ff->DATARMNET611d08d671);
  142. DATARMNET3396919a68->DATARMNETf0d9de7e2f=DATARMNET75be5f3406->dest;if(
  143. DATARMNETa8b2566e6a(DATARMNET543491eb0f,DATARMNET3396919a68,DATARMNET54338da2ff
  144. ->DATARMNET611d08d671)){if(DATARMNET0a4704e5e0(DATARMNET3396919a68)){kfree_skb(
  145. DATARMNET543491eb0f);DATARMNET61c2303133=(0xd2d+202-0xdf7);DATARMNET5ca94dbc3c(
  146. DATARMNET0981317411);goto DATARMNETbf4095f79e;}DATARMNET5ca94dbc3c(
  147. DATARMNETd1ad664d00);goto DATARMNET07fc49caf2;}}else if(DATARMNET3396919a68->
  148. DATARMNET4924e79411==IPPROTO_ESP){struct ip_esp_hdr*DATARMNET73ee6a7020=(struct
  149. ip_esp_hdr*)(DATARMNET543491eb0f->data+DATARMNET54338da2ff->DATARMNET611d08d671)
  150. ;DATARMNET3396919a68->DATARMNET906b2ee561=DATARMNET73ee6a7020->spi;}if(
  151. DATARMNET4eafcdee07(DATARMNET3396919a68)){u32 DATARMNET248f120dd5;
  152. DATARMNET63b1a086d5->DATARMNET7ed5754a5c=DATARMNET2d4b4cfc9e;if(!
  153. DATARMNET4899053671(DATARMNET543491eb0f,DATARMNET2d4b4cfc9e)){
  154. DATARMNET248f120dd5=DATARMNET7a58a5c1fc;DATARMNET61c2303133=(0xd2d+202-0xdf7);}
  155. else{DATARMNET248f120dd5=DATARMNETba232077da;}DATARMNET5ca94dbc3c(
  156. DATARMNET248f120dd5);DATARMNETc7c83f614f(DATARMNET63b1a086d5,true);goto
  157. DATARMNETbf4095f79e;}DATARMNET07fc49caf2:DATARMNET63b1a086d5->
  158. DATARMNET7ed5754a5c=ERR_PTR(-EINVAL);DATARMNETc7c83f614f(DATARMNET63b1a086d5,
  159. true);DATARMNETbf4095f79e:return DATARMNET61c2303133;}int DATARMNET579f75aa50(
  160. struct sk_buff*DATARMNET543491eb0f,int DATARMNET611d08d671,struct
  161. DATARMNETb89ecedefc*DATARMNET3396919a68,struct DATARMNET8d3c2559ca*
  162. DATARMNET2d4b4cfc9e)__must_hold(RCU){struct DATARMNETdadb4e2c65
  163. DATARMNET54338da2ff={};struct iphdr*DATARMNET86f1f2cdc9=ip_hdr(
  164. DATARMNET543491eb0f);if(DATARMNET3396919a68->DATARMNET4924e79411!=IPPROTO_TCP&&
  165. DATARMNET3396919a68->DATARMNET4924e79411!=IPPROTO_UDP&&DATARMNET3396919a68->
  166. DATARMNET4924e79411!=IPPROTO_ESP)return-(0xd26+209-0xdf6);DATARMNET54338da2ff.
  167. DATARMNET0d956cc77a=(0xd11+230-0xdf3);DATARMNET54338da2ff.DATARMNETdfe430c2d6=
  168. DATARMNET86f1f2cdc9->saddr;DATARMNET54338da2ff.DATARMNET2cb607d686=
  169. DATARMNET86f1f2cdc9->daddr;DATARMNET54338da2ff.id=htonl((u32)ntohs(
  170. DATARMNET86f1f2cdc9->id));DATARMNET54338da2ff.DATARMNETb65c469a15=htons(
  171. DATARMNET86f1f2cdc9->frag_off)&IP_OFFSET;DATARMNET54338da2ff.DATARMNET611d08d671
  172. =(u16)DATARMNET611d08d671;return DATARMNET9d6ad3b16f(DATARMNET543491eb0f,
  173. DATARMNET3396919a68,&DATARMNET54338da2ff,DATARMNET2d4b4cfc9e);}int
  174. DATARMNETaca8ca54ed(struct sk_buff*DATARMNET543491eb0f,int DATARMNET611d08d671,
  175. struct DATARMNETb89ecedefc*DATARMNET3396919a68,struct DATARMNET8d3c2559ca*
  176. DATARMNET2d4b4cfc9e)__must_hold(RCU){struct DATARMNETdadb4e2c65
  177. DATARMNET54338da2ff={};struct ipv6hdr*DATARMNETbf55123e5b=ipv6_hdr(
  178. DATARMNET543491eb0f);struct frag_hdr*frag_hdr;unsigned int DATARMNET7b34b7b5be;
  179. if(DATARMNET3396919a68->DATARMNET4924e79411!=IPPROTO_TCP&&DATARMNET3396919a68->
  180. DATARMNET4924e79411!=IPPROTO_UDP&&DATARMNET3396919a68->DATARMNET4924e79411!=
  181. IPPROTO_ESP&&DATARMNET3396919a68->DATARMNET4924e79411!=NEXTHDR_FRAGMENT)return-
  182. (0xd26+209-0xdf6);if(DATARMNET24669a931d(DATARMNET543491eb0f,&
  183. DATARMNET7b34b7b5be,NEXTHDR_FRAGMENT,NULL,NULL)<(0xd2d+202-0xdf7))return-
  184. (0xd26+209-0xdf6);frag_hdr=(struct frag_hdr*)(DATARMNET543491eb0f->data+
  185. DATARMNET7b34b7b5be);DATARMNET54338da2ff.DATARMNET0d956cc77a=(0xd03+244-0xdf1);
  186. memcpy(&DATARMNET54338da2ff.DATARMNET815cbb4bf5,&DATARMNETbf55123e5b->saddr,
  187. sizeof(DATARMNETbf55123e5b->saddr));memcpy(&DATARMNET54338da2ff.
  188. DATARMNETc3f31215b7,&DATARMNETbf55123e5b->daddr,sizeof(DATARMNETbf55123e5b->
  189. daddr));DATARMNET54338da2ff.id=frag_hdr->identification;DATARMNET54338da2ff.
  190. DATARMNETb65c469a15=htons(frag_hdr->frag_off)&IP6_OFFSET;DATARMNET54338da2ff.
  191. DATARMNET611d08d671=(u16)DATARMNET611d08d671;if(DATARMNET3396919a68->
  192. DATARMNET4924e79411==NEXTHDR_FRAGMENT)DATARMNET54338da2ff.DATARMNET611d08d671+=
  193. sizeof(*frag_hdr);return DATARMNET9d6ad3b16f(DATARMNET543491eb0f,
  194. DATARMNET3396919a68,&DATARMNET54338da2ff,DATARMNET2d4b4cfc9e);}void
  195. DATARMNET8c0e010dfb(void){struct DATARMNET6f3b954709*DATARMNET63b1a086d5;int
  196. DATARMNET5c2fd31d7b;rcu_read_lock();hash_for_each_rcu(DATARMNET6e79f38051,
  197. DATARMNET5c2fd31d7b,DATARMNET63b1a086d5,DATARMNETe8608dd267)hrtimer_cancel(&
  198. DATARMNET63b1a086d5->DATARMNET9f31ce5d2d);rcu_read_unlock();}void
  199. DATARMNETedae8262e1(struct DATARMNET8d3c2559ca*DATARMNET54338da2ff){struct
  200. DATARMNET6f3b954709*DATARMNET63b1a086d5;int DATARMNET5c2fd31d7b;rcu_read_lock();
  201. hash_for_each_rcu(DATARMNET6e79f38051,DATARMNET5c2fd31d7b,DATARMNET63b1a086d5,
  202. DATARMNETe8608dd267){if(DATARMNET63b1a086d5->DATARMNET7ed5754a5c==
  203. DATARMNET54338da2ff)DATARMNET63b1a086d5->DATARMNET7ed5754a5c=ERR_PTR(-EINVAL);}
  204. rcu_read_unlock();}