diff options
Diffstat (limited to 'net/l2tp/l2tp_core.c')
-rw-r--r-- | net/l2tp/l2tp_core.c | 118 |
1 files changed, 13 insertions, 105 deletions
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index a4e37d7158dc..bea259043205 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c | |||
@@ -495,52 +495,6 @@ out: | |||
495 | spin_unlock_bh(&session->reorder_q.lock); | 495 | spin_unlock_bh(&session->reorder_q.lock); |
496 | } | 496 | } |
497 | 497 | ||
498 | static inline int l2tp_verify_udp_checksum(struct sock *sk, | ||
499 | struct sk_buff *skb) | ||
500 | { | ||
501 | struct udphdr *uh = udp_hdr(skb); | ||
502 | u16 ulen = ntohs(uh->len); | ||
503 | __wsum psum; | ||
504 | |||
505 | if (sk->sk_no_check || skb_csum_unnecessary(skb)) | ||
506 | return 0; | ||
507 | |||
508 | #if IS_ENABLED(CONFIG_IPV6) | ||
509 | if (sk->sk_family == PF_INET6 && !l2tp_tunnel(sk)->v4mapped) { | ||
510 | if (!uh->check) { | ||
511 | LIMIT_NETDEBUG(KERN_INFO "L2TP: IPv6: checksum is 0\n"); | ||
512 | return 1; | ||
513 | } | ||
514 | if ((skb->ip_summed == CHECKSUM_COMPLETE) && | ||
515 | !csum_ipv6_magic(&ipv6_hdr(skb)->saddr, | ||
516 | &ipv6_hdr(skb)->daddr, ulen, | ||
517 | IPPROTO_UDP, skb->csum)) { | ||
518 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
519 | return 0; | ||
520 | } | ||
521 | skb->csum = ~csum_unfold(csum_ipv6_magic(&ipv6_hdr(skb)->saddr, | ||
522 | &ipv6_hdr(skb)->daddr, | ||
523 | skb->len, IPPROTO_UDP, | ||
524 | 0)); | ||
525 | } else | ||
526 | #endif | ||
527 | { | ||
528 | struct inet_sock *inet; | ||
529 | if (!uh->check) | ||
530 | return 0; | ||
531 | inet = inet_sk(sk); | ||
532 | psum = csum_tcpudp_nofold(inet->inet_saddr, inet->inet_daddr, | ||
533 | ulen, IPPROTO_UDP, 0); | ||
534 | |||
535 | if ((skb->ip_summed == CHECKSUM_COMPLETE) && | ||
536 | !csum_fold(csum_add(psum, skb->csum))) | ||
537 | return 0; | ||
538 | skb->csum = psum; | ||
539 | } | ||
540 | |||
541 | return __skb_checksum_complete(skb); | ||
542 | } | ||
543 | |||
544 | static int l2tp_seq_check_rx_window(struct l2tp_session *session, u32 nr) | 498 | static int l2tp_seq_check_rx_window(struct l2tp_session *session, u32 nr) |
545 | { | 499 | { |
546 | u32 nws; | 500 | u32 nws; |
@@ -895,8 +849,7 @@ static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb, | |||
895 | u16 version; | 849 | u16 version; |
896 | int length; | 850 | int length; |
897 | 851 | ||
898 | if (tunnel->sock && l2tp_verify_udp_checksum(tunnel->sock, skb)) | 852 | /* UDP has verifed checksum */ |
899 | goto discard_bad_csum; | ||
900 | 853 | ||
901 | /* UDP always verifies the packet length. */ | 854 | /* UDP always verifies the packet length. */ |
902 | __skb_pull(skb, sizeof(struct udphdr)); | 855 | __skb_pull(skb, sizeof(struct udphdr)); |
@@ -979,14 +932,6 @@ static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb, | |||
979 | 932 | ||
980 | return 0; | 933 | return 0; |
981 | 934 | ||
982 | discard_bad_csum: | ||
983 | LIMIT_NETDEBUG("%s: UDP: bad checksum\n", tunnel->name); | ||
984 | UDP_INC_STATS_USER(tunnel->l2tp_net, UDP_MIB_INERRORS, 0); | ||
985 | atomic_long_inc(&tunnel->stats.rx_errors); | ||
986 | kfree_skb(skb); | ||
987 | |||
988 | return 0; | ||
989 | |||
990 | error: | 935 | error: |
991 | /* Put UDP header back */ | 936 | /* Put UDP header back */ |
992 | __skb_push(skb, sizeof(struct udphdr)); | 937 | __skb_push(skb, sizeof(struct udphdr)); |
@@ -1128,7 +1073,7 @@ static int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb, | |||
1128 | } | 1073 | } |
1129 | 1074 | ||
1130 | /* Queue the packet to IP for output */ | 1075 | /* Queue the packet to IP for output */ |
1131 | skb->local_df = 1; | 1076 | skb->ignore_df = 1; |
1132 | #if IS_ENABLED(CONFIG_IPV6) | 1077 | #if IS_ENABLED(CONFIG_IPV6) |
1133 | if (tunnel->sock->sk_family == PF_INET6 && !tunnel->v4mapped) | 1078 | if (tunnel->sock->sk_family == PF_INET6 && !tunnel->v4mapped) |
1134 | error = inet6_csk_xmit(tunnel->sock, skb, NULL); | 1079 | error = inet6_csk_xmit(tunnel->sock, skb, NULL); |
@@ -1150,31 +1095,6 @@ static int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb, | |||
1150 | return 0; | 1095 | return 0; |
1151 | } | 1096 | } |
1152 | 1097 | ||
1153 | #if IS_ENABLED(CONFIG_IPV6) | ||
1154 | static void l2tp_xmit_ipv6_csum(struct sock *sk, struct sk_buff *skb, | ||
1155 | int udp_len) | ||
1156 | { | ||
1157 | struct ipv6_pinfo *np = inet6_sk(sk); | ||
1158 | struct udphdr *uh = udp_hdr(skb); | ||
1159 | |||
1160 | if (!skb_dst(skb) || !skb_dst(skb)->dev || | ||
1161 | !(skb_dst(skb)->dev->features & NETIF_F_IPV6_CSUM)) { | ||
1162 | __wsum csum = skb_checksum(skb, 0, udp_len, 0); | ||
1163 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
1164 | uh->check = csum_ipv6_magic(&np->saddr, &sk->sk_v6_daddr, udp_len, | ||
1165 | IPPROTO_UDP, csum); | ||
1166 | if (uh->check == 0) | ||
1167 | uh->check = CSUM_MANGLED_0; | ||
1168 | } else { | ||
1169 | skb->ip_summed = CHECKSUM_PARTIAL; | ||
1170 | skb->csum_start = skb_transport_header(skb) - skb->head; | ||
1171 | skb->csum_offset = offsetof(struct udphdr, check); | ||
1172 | uh->check = ~csum_ipv6_magic(&np->saddr, &sk->sk_v6_daddr, | ||
1173 | udp_len, IPPROTO_UDP, 0); | ||
1174 | } | ||
1175 | } | ||
1176 | #endif | ||
1177 | |||
1178 | /* If caller requires the skb to have a ppp header, the header must be | 1098 | /* If caller requires the skb to have a ppp header, the header must be |
1179 | * inserted in the skb data before calling this function. | 1099 | * inserted in the skb data before calling this function. |
1180 | */ | 1100 | */ |
@@ -1186,7 +1106,6 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len | |||
1186 | struct flowi *fl; | 1106 | struct flowi *fl; |
1187 | struct udphdr *uh; | 1107 | struct udphdr *uh; |
1188 | struct inet_sock *inet; | 1108 | struct inet_sock *inet; |
1189 | __wsum csum; | ||
1190 | int headroom; | 1109 | int headroom; |
1191 | int uhlen = (tunnel->encap == L2TP_ENCAPTYPE_UDP) ? sizeof(struct udphdr) : 0; | 1110 | int uhlen = (tunnel->encap == L2TP_ENCAPTYPE_UDP) ? sizeof(struct udphdr) : 0; |
1192 | int udp_len; | 1111 | int udp_len; |
@@ -1235,33 +1154,17 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len | |||
1235 | uh->dest = inet->inet_dport; | 1154 | uh->dest = inet->inet_dport; |
1236 | udp_len = uhlen + hdr_len + data_len; | 1155 | udp_len = uhlen + hdr_len + data_len; |
1237 | uh->len = htons(udp_len); | 1156 | uh->len = htons(udp_len); |
1238 | uh->check = 0; | ||
1239 | 1157 | ||
1240 | /* Calculate UDP checksum if configured to do so */ | 1158 | /* Calculate UDP checksum if configured to do so */ |
1241 | #if IS_ENABLED(CONFIG_IPV6) | 1159 | #if IS_ENABLED(CONFIG_IPV6) |
1242 | if (sk->sk_family == PF_INET6 && !tunnel->v4mapped) | 1160 | if (sk->sk_family == PF_INET6 && !tunnel->v4mapped) |
1243 | l2tp_xmit_ipv6_csum(sk, skb, udp_len); | 1161 | udp6_set_csum(udp_get_no_check6_tx(sk), |
1162 | skb, &inet6_sk(sk)->saddr, | ||
1163 | &sk->sk_v6_daddr, udp_len); | ||
1244 | else | 1164 | else |
1245 | #endif | 1165 | #endif |
1246 | if (sk->sk_no_check == UDP_CSUM_NOXMIT) | 1166 | udp_set_csum(sk->sk_no_check_tx, skb, inet->inet_saddr, |
1247 | skb->ip_summed = CHECKSUM_NONE; | 1167 | inet->inet_daddr, udp_len); |
1248 | else if ((skb_dst(skb) && skb_dst(skb)->dev) && | ||
1249 | (!(skb_dst(skb)->dev->features & NETIF_F_V4_CSUM))) { | ||
1250 | skb->ip_summed = CHECKSUM_COMPLETE; | ||
1251 | csum = skb_checksum(skb, 0, udp_len, 0); | ||
1252 | uh->check = csum_tcpudp_magic(inet->inet_saddr, | ||
1253 | inet->inet_daddr, | ||
1254 | udp_len, IPPROTO_UDP, csum); | ||
1255 | if (uh->check == 0) | ||
1256 | uh->check = CSUM_MANGLED_0; | ||
1257 | } else { | ||
1258 | skb->ip_summed = CHECKSUM_PARTIAL; | ||
1259 | skb->csum_start = skb_transport_header(skb) - skb->head; | ||
1260 | skb->csum_offset = offsetof(struct udphdr, check); | ||
1261 | uh->check = ~csum_tcpudp_magic(inet->inet_saddr, | ||
1262 | inet->inet_daddr, | ||
1263 | udp_len, IPPROTO_UDP, 0); | ||
1264 | } | ||
1265 | break; | 1168 | break; |
1266 | 1169 | ||
1267 | case L2TP_ENCAPTYPE_IP: | 1170 | case L2TP_ENCAPTYPE_IP: |
@@ -1490,6 +1393,11 @@ static int l2tp_tunnel_sock_create(struct net *net, | |||
1490 | sizeof(udp6_addr), 0); | 1393 | sizeof(udp6_addr), 0); |
1491 | if (err < 0) | 1394 | if (err < 0) |
1492 | goto out; | 1395 | goto out; |
1396 | |||
1397 | if (cfg->udp6_zero_tx_checksums) | ||
1398 | udp_set_no_check6_tx(sock->sk, true); | ||
1399 | if (cfg->udp6_zero_rx_checksums) | ||
1400 | udp_set_no_check6_rx(sock->sk, true); | ||
1493 | } else | 1401 | } else |
1494 | #endif | 1402 | #endif |
1495 | { | 1403 | { |
@@ -1518,7 +1426,7 @@ static int l2tp_tunnel_sock_create(struct net *net, | |||
1518 | } | 1426 | } |
1519 | 1427 | ||
1520 | if (!cfg->use_udp_checksums) | 1428 | if (!cfg->use_udp_checksums) |
1521 | sock->sk->sk_no_check = UDP_CSUM_NOXMIT; | 1429 | sock->sk->sk_no_check_tx = 1; |
1522 | 1430 | ||
1523 | break; | 1431 | break; |
1524 | 1432 | ||