18
18
#include <linux/kallsyms.h>
19
19
#include <linux/kprobes.h>
20
20
#include <linux/if_vlan.h>
21
+ #include <linux/ipv6.h>
22
+ #include <net/ipv6.h>
23
+ #include <net/transp_v6.h>
24
+ #include <net/ip6_route.h>
21
25
#include <net/inet_common.h>
22
26
#include <net/tcp.h>
23
27
#include <net/dst.h>
24
28
#include <net/tls.h>
29
+ #include <net/addrconf.h>
30
+ #include <net/secure_seq.h>
25
31
26
32
#include "chtls.h"
27
33
#include "chtls_cm.h"
34
+ #include "clip_tbl.h"
28
35
29
36
/*
30
37
* State transitions and actions for close. Note that if we are in SYN_SENT
@@ -82,15 +89,36 @@ static void chtls_sock_release(struct kref *ref)
82
89
kfree (csk );
83
90
}
84
91
85
- static struct net_device * chtls_ipv4_netdev (struct chtls_dev * cdev ,
92
+ static struct net_device * chtls_find_netdev (struct chtls_dev * cdev ,
86
93
struct sock * sk )
87
94
{
88
95
struct net_device * ndev = cdev -> ports [0 ];
96
+ struct net_device * temp ;
97
+ int addr_type ;
98
+
99
+ switch (sk -> sk_family ) {
100
+ case PF_INET :
101
+ if (likely (!inet_sk (sk )-> inet_rcv_saddr ))
102
+ return ndev ;
103
+ ndev = ip_dev_find (& init_net , inet_sk (sk )-> inet_rcv_saddr );
104
+ break ;
105
+ case PF_INET6 :
106
+ addr_type = ipv6_addr_type (& sk -> sk_v6_rcv_saddr );
107
+ if (likely (addr_type == IPV6_ADDR_ANY ))
108
+ return ndev ;
109
+
110
+ for_each_netdev_rcu (& init_net , temp ) {
111
+ if (ipv6_chk_addr (& init_net , (struct in6_addr * )
112
+ & sk -> sk_v6_rcv_saddr , temp , 1 )) {
113
+ ndev = temp ;
114
+ break ;
115
+ }
116
+ }
117
+ break ;
118
+ default :
119
+ return NULL ;
120
+ }
89
121
90
- if (likely (!inet_sk (sk )-> inet_rcv_saddr ))
91
- return ndev ;
92
-
93
- ndev = ip_dev_find (& init_net , inet_sk (sk )-> inet_rcv_saddr );
94
122
if (!ndev )
95
123
return NULL ;
96
124
@@ -446,7 +474,10 @@ void chtls_destroy_sock(struct sock *sk)
446
474
free_tls_keyid (sk );
447
475
kref_put (& csk -> kref , chtls_sock_release );
448
476
csk -> cdev = NULL ;
449
- sk -> sk_prot = & tcp_prot ;
477
+ if (sk -> sk_family == AF_INET )
478
+ sk -> sk_prot = & tcp_prot ;
479
+ else
480
+ sk -> sk_prot = & tcpv6_prot ;
450
481
sk -> sk_prot -> destroy (sk );
451
482
}
452
483
@@ -473,7 +504,8 @@ static void chtls_disconnect_acceptq(struct sock *listen_sk)
473
504
while (* pprev ) {
474
505
struct request_sock * req = * pprev ;
475
506
476
- if (req -> rsk_ops == & chtls_rsk_ops ) {
507
+ if (req -> rsk_ops == & chtls_rsk_ops ||
508
+ req -> rsk_ops == & chtls_rsk_opsv6 ) {
477
509
struct sock * child = req -> sk ;
478
510
479
511
* pprev = req -> dl_next ;
@@ -600,14 +632,13 @@ int chtls_listen_start(struct chtls_dev *cdev, struct sock *sk)
600
632
struct listen_ctx * ctx ;
601
633
struct adapter * adap ;
602
634
struct port_info * pi ;
635
+ bool clip_valid ;
603
636
int stid ;
604
637
int ret ;
605
638
606
- if (sk -> sk_family != PF_INET )
607
- return - EAGAIN ;
608
-
639
+ clip_valid = false;
609
640
rcu_read_lock ();
610
- ndev = chtls_ipv4_netdev (cdev , sk );
641
+ ndev = chtls_find_netdev (cdev , sk );
611
642
rcu_read_unlock ();
612
643
if (!ndev )
613
644
return - EBADF ;
@@ -638,16 +669,35 @@ int chtls_listen_start(struct chtls_dev *cdev, struct sock *sk)
638
669
if (!listen_hash_add (cdev , sk , stid ))
639
670
goto free_stid ;
640
671
641
- ret = cxgb4_create_server (ndev , stid ,
642
- inet_sk (sk )-> inet_rcv_saddr ,
643
- inet_sk (sk )-> inet_sport , 0 ,
644
- cdev -> lldi -> rxq_ids [0 ]);
672
+ if (sk -> sk_family == PF_INET ) {
673
+ ret = cxgb4_create_server (ndev , stid ,
674
+ inet_sk (sk )-> inet_rcv_saddr ,
675
+ inet_sk (sk )-> inet_sport , 0 ,
676
+ cdev -> lldi -> rxq_ids [0 ]);
677
+ } else {
678
+ int addr_type ;
679
+
680
+ addr_type = ipv6_addr_type (& sk -> sk_v6_rcv_saddr );
681
+ if (addr_type != IPV6_ADDR_ANY ) {
682
+ ret = cxgb4_clip_get (ndev , (const u32 * )
683
+ & sk -> sk_v6_rcv_saddr , 1 );
684
+ if (ret )
685
+ goto del_hash ;
686
+ clip_valid = true;
687
+ }
688
+ ret = cxgb4_create_server6 (ndev , stid ,
689
+ & sk -> sk_v6_rcv_saddr ,
690
+ inet_sk (sk )-> inet_sport ,
691
+ cdev -> lldi -> rxq_ids [0 ]);
692
+ }
645
693
if (ret > 0 )
646
694
ret = net_xmit_errno (ret );
647
695
if (ret )
648
696
goto del_hash ;
649
697
return 0 ;
650
698
del_hash :
699
+ if (clip_valid )
700
+ cxgb4_clip_release (ndev , (const u32 * )& sk -> sk_v6_rcv_saddr , 1 );
651
701
listen_hash_del (cdev , sk );
652
702
free_stid :
653
703
cxgb4_free_stid (cdev -> tids , stid , sk -> sk_family );
@@ -661,6 +711,8 @@ int chtls_listen_start(struct chtls_dev *cdev, struct sock *sk)
661
711
void chtls_listen_stop (struct chtls_dev * cdev , struct sock * sk )
662
712
{
663
713
struct listen_ctx * listen_ctx ;
714
+ struct chtls_sock * csk ;
715
+ int addr_type = 0 ;
664
716
int stid ;
665
717
666
718
stid = listen_hash_del (cdev , sk );
@@ -671,7 +723,16 @@ void chtls_listen_stop(struct chtls_dev *cdev, struct sock *sk)
671
723
chtls_reset_synq (listen_ctx );
672
724
673
725
cxgb4_remove_server (cdev -> lldi -> ports [0 ], stid ,
674
- cdev -> lldi -> rxq_ids [0 ], 0 );
726
+ cdev -> lldi -> rxq_ids [0 ], sk -> sk_family == PF_INET6 );
727
+
728
+ if (sk -> sk_family == PF_INET6 ) {
729
+ csk = rcu_dereference_sk_user_data (sk );
730
+ addr_type = ipv6_addr_type ((const struct in6_addr * )
731
+ & sk -> sk_v6_rcv_saddr );
732
+ if (addr_type != IPV6_ADDR_ANY )
733
+ cxgb4_clip_release (csk -> egress_dev , (const u32 * )
734
+ & sk -> sk_v6_rcv_saddr , 1 );
735
+ }
675
736
chtls_disconnect_acceptq (sk );
676
737
}
677
738
@@ -880,7 +941,10 @@ static unsigned int chtls_select_mss(const struct chtls_sock *csk,
880
941
tp = tcp_sk (sk );
881
942
tcpoptsz = 0 ;
882
943
883
- iphdrsz = sizeof (struct iphdr ) + sizeof (struct tcphdr );
944
+ if (sk -> sk_family == AF_INET6 )
945
+ iphdrsz = sizeof (struct ipv6hdr ) + sizeof (struct tcphdr );
946
+ else
947
+ iphdrsz = sizeof (struct iphdr ) + sizeof (struct tcphdr );
884
948
if (req -> tcpopt .tstamp )
885
949
tcpoptsz += round_up (TCPOLEN_TIMESTAMP , 4 );
886
950
@@ -1045,11 +1109,29 @@ static struct sock *chtls_recv_sock(struct sock *lsk,
1045
1109
if (!newsk )
1046
1110
goto free_oreq ;
1047
1111
1048
- dst = inet_csk_route_child_sock (lsk , newsk , oreq );
1049
- if (!dst )
1050
- goto free_sk ;
1112
+ if (lsk -> sk_family == AF_INET ) {
1113
+ dst = inet_csk_route_child_sock (lsk , newsk , oreq );
1114
+ if (!dst )
1115
+ goto free_sk ;
1051
1116
1052
- n = dst_neigh_lookup (dst , & iph -> saddr );
1117
+ n = dst_neigh_lookup (dst , & iph -> saddr );
1118
+ } else {
1119
+ const struct ipv6hdr * ip6h ;
1120
+ struct flowi6 fl6 ;
1121
+
1122
+ ip6h = (const struct ipv6hdr * )network_hdr ;
1123
+ memset (& fl6 , 0 , sizeof (fl6 ));
1124
+ fl6 .flowi6_proto = IPPROTO_TCP ;
1125
+ fl6 .saddr = ip6h -> daddr ;
1126
+ fl6 .daddr = ip6h -> saddr ;
1127
+ fl6 .fl6_dport = inet_rsk (oreq )-> ir_rmt_port ;
1128
+ fl6 .fl6_sport = htons (inet_rsk (oreq )-> ir_num );
1129
+ security_req_classify_flow (oreq , flowi6_to_flowi (& fl6 ));
1130
+ dst = ip6_dst_lookup_flow (sock_net (lsk ), lsk , & fl6 , NULL );
1131
+ if (IS_ERR (dst ))
1132
+ goto free_sk ;
1133
+ n = dst_neigh_lookup (dst , & ip6h -> saddr );
1134
+ }
1053
1135
if (!n )
1054
1136
goto free_sk ;
1055
1137
@@ -1072,9 +1154,28 @@ static struct sock *chtls_recv_sock(struct sock *lsk,
1072
1154
tp = tcp_sk (newsk );
1073
1155
newinet = inet_sk (newsk );
1074
1156
1075
- newinet -> inet_daddr = iph -> saddr ;
1076
- newinet -> inet_rcv_saddr = iph -> daddr ;
1077
- newinet -> inet_saddr = iph -> daddr ;
1157
+ if (iph -> version == 0x4 ) {
1158
+ newinet -> inet_daddr = iph -> saddr ;
1159
+ newinet -> inet_rcv_saddr = iph -> daddr ;
1160
+ newinet -> inet_saddr = iph -> daddr ;
1161
+ } else {
1162
+ struct tcp6_sock * newtcp6sk = (struct tcp6_sock * )newsk ;
1163
+ struct inet_request_sock * treq = inet_rsk (oreq );
1164
+ struct ipv6_pinfo * newnp = inet6_sk (newsk );
1165
+ struct ipv6_pinfo * np = inet6_sk (lsk );
1166
+
1167
+ inet_sk (newsk )-> pinet6 = & newtcp6sk -> inet6 ;
1168
+ memcpy (newnp , np , sizeof (struct ipv6_pinfo ));
1169
+ newsk -> sk_v6_daddr = treq -> ir_v6_rmt_addr ;
1170
+ newsk -> sk_v6_rcv_saddr = treq -> ir_v6_loc_addr ;
1171
+ inet6_sk (newsk )-> saddr = treq -> ir_v6_loc_addr ;
1172
+ newnp -> ipv6_fl_list = NULL ;
1173
+ newnp -> pktoptions = NULL ;
1174
+ newsk -> sk_bound_dev_if = treq -> ir_iif ;
1175
+ newinet -> inet_opt = NULL ;
1176
+ newinet -> inet_daddr = LOOPBACK4_IPV6 ;
1177
+ newinet -> inet_saddr = LOOPBACK4_IPV6 ;
1178
+ }
1078
1179
1079
1180
oreq -> ts_recent = PASS_OPEN_TID_G (ntohl (req -> tos_stid ));
1080
1181
sk_setup_caps (newsk , dst );
@@ -1156,6 +1257,7 @@ static void chtls_pass_accept_request(struct sock *sk,
1156
1257
struct sk_buff * reply_skb ;
1157
1258
struct chtls_sock * csk ;
1158
1259
struct chtls_dev * cdev ;
1260
+ struct ipv6hdr * ip6h ;
1159
1261
struct tcphdr * tcph ;
1160
1262
struct sock * newsk ;
1161
1263
struct ethhdr * eh ;
@@ -1196,37 +1298,50 @@ static void chtls_pass_accept_request(struct sock *sk,
1196
1298
if (sk_acceptq_is_full (sk ))
1197
1299
goto reject ;
1198
1300
1199
- oreq = inet_reqsk_alloc (& chtls_rsk_ops , sk , true);
1200
- if (!oreq )
1201
- goto reject ;
1202
-
1203
- oreq -> rsk_rcv_wnd = 0 ;
1204
- oreq -> rsk_window_clamp = 0 ;
1205
- oreq -> cookie_ts = 0 ;
1206
- oreq -> mss = 0 ;
1207
- oreq -> ts_recent = 0 ;
1208
1301
1209
1302
eth_hdr_len = T6_ETH_HDR_LEN_G (ntohl (req -> hdr_len ));
1210
1303
if (eth_hdr_len == ETH_HLEN ) {
1211
1304
eh = (struct ethhdr * )(req + 1 );
1212
1305
iph = (struct iphdr * )(eh + 1 );
1306
+ ip6h = (struct ipv6hdr * )(eh + 1 );
1213
1307
network_hdr = (void * )(eh + 1 );
1214
1308
} else {
1215
1309
vlan_eh = (struct vlan_ethhdr * )(req + 1 );
1216
1310
iph = (struct iphdr * )(vlan_eh + 1 );
1311
+ ip6h = (struct ipv6hdr * )(vlan_eh + 1 );
1217
1312
network_hdr = (void * )(vlan_eh + 1 );
1218
1313
}
1219
- if (iph -> version != 0x4 )
1220
- goto free_oreq ;
1221
1314
1222
- tcph = (struct tcphdr * )(iph + 1 );
1223
- skb_set_network_header (skb , (void * )iph - (void * )req );
1315
+ if (iph -> version == 0x4 ) {
1316
+ tcph = (struct tcphdr * )(iph + 1 );
1317
+ skb_set_network_header (skb , (void * )iph - (void * )req );
1318
+ oreq = inet_reqsk_alloc (& chtls_rsk_ops , sk , true);
1319
+ } else {
1320
+ tcph = (struct tcphdr * )(ip6h + 1 );
1321
+ skb_set_network_header (skb , (void * )ip6h - (void * )req );
1322
+ oreq = inet_reqsk_alloc (& chtls_rsk_opsv6 , sk , false);
1323
+ }
1324
+
1325
+ if (!oreq )
1326
+ goto reject ;
1327
+
1328
+ oreq -> rsk_rcv_wnd = 0 ;
1329
+ oreq -> rsk_window_clamp = 0 ;
1330
+ oreq -> cookie_ts = 0 ;
1331
+ oreq -> mss = 0 ;
1332
+ oreq -> ts_recent = 0 ;
1224
1333
1225
1334
tcp_rsk (oreq )-> tfo_listener = false;
1226
1335
tcp_rsk (oreq )-> rcv_isn = ntohl (tcph -> seq );
1227
1336
chtls_set_req_port (oreq , tcph -> source , tcph -> dest );
1228
- chtls_set_req_addr (oreq , iph -> daddr , iph -> saddr );
1229
- ip_dsfield = ipv4_get_dsfield (iph );
1337
+ if (iph -> version == 0x4 ) {
1338
+ chtls_set_req_addr (oreq , iph -> daddr , iph -> saddr );
1339
+ ip_dsfield = ipv4_get_dsfield (iph );
1340
+ } else {
1341
+ inet_rsk (oreq )-> ir_v6_rmt_addr = ipv6_hdr (skb )-> saddr ;
1342
+ inet_rsk (oreq )-> ir_v6_loc_addr = ipv6_hdr (skb )-> daddr ;
1343
+ ip_dsfield = ipv6_get_dsfield (ipv6_hdr (skb ));
1344
+ }
1230
1345
if (req -> tcpopt .wsf <= 14 &&
1231
1346
sock_net (sk )-> ipv4 .sysctl_tcp_window_scaling ) {
1232
1347
inet_rsk (oreq )-> wscale_ok = 1 ;
@@ -1243,7 +1358,7 @@ static void chtls_pass_accept_request(struct sock *sk,
1243
1358
1244
1359
newsk = chtls_recv_sock (sk , oreq , network_hdr , req , cdev );
1245
1360
if (!newsk )
1246
- goto reject ;
1361
+ goto free_oreq ;
1247
1362
1248
1363
if (chtls_get_module (newsk ))
1249
1364
goto reject ;
0 commit comments