1 /*This will initiate an outgoing connection.*/
2 int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, intaddr_len)3 {4 struct sockaddr_in *usin = (struct sockaddr_in *)uaddr;5 struct inet_sock *inet =inet_sk(sk);6 struct tcp_sock *tp =tcp_sk(sk);7 __be16 orig_sport, orig_dport;8 __be32 daddr, nexthop;9 struct flowi4 *fl4;10 struct rtable *rt;11 interr;12 struct ip_options_rcu *inet_opt;13
14 /*timewait控制块结构*/
15 struct inet_timewait_death_row *tcp_death_row = &sock_net(sk)->ipv4.tcp_death_row;16
17 /*地址长度不合法*/
18 if (addr_len < sizeof(structsockaddr_in))19 return -EINVAL;20
21 /*地址族不合法*/
22 if (usin->sin_family !=AF_INET)23 return -EAFNOSUPPORT;24
25 /*设置下一跳和目的地址*/
26 nexthop = daddr = usin->sin_addr.s_addr;27
28 /*获取ip选项*/
29 inet_opt = rcu_dereference_protected(inet->inet_opt,30 lockdep_sock_is_held(sk));31
32 /*使用了源路由选项*/
33 if (inet_opt && inet_opt->opt.srr) {34 if (!daddr)35 return -EINVAL;36 /*下一跳地址设置为选项中的地址*/
37 nexthop = inet_opt->opt.faddr;38 }39
40 /*获取源端口目的端口*/
41 orig_sport = inet->inet_sport;42 orig_dport = usin->sin_port;43
44 /*查找路由*/
45 fl4 = &inet->cork.fl.u.ip4;46 rt = ip_route_connect(fl4, nexthop, inet->inet_saddr,47 RT_CONN_FLAGS(sk), sk->sk_bound_dev_if,48 IPPROTO_TCP,49 orig_sport, orig_dport, sk);50 /*查找失败*/
51 if(IS_ERR(rt)) {52 err =PTR_ERR(rt);53 if (err == -ENETUNREACH)54 IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTNOROUTES);55 returnerr;56 }57
58
59 /*查找成功*/
60
61 /*路由是组播或者广播*/
62 if (rt->rt_flags & (RTCF_MULTICAST |RTCF_BROADCAST)) {63 ip_rt_put(rt);64 return -ENETUNREACH;65 }66
67 /*选项为空或者未启用源路由选项*/
68 /*设置目的地址为路由缓存中地址*/
69 if (!inet_opt || !inet_opt->opt.srr)70 daddr = fl4->daddr;71
72 /*源地址为空*/
73 /*使用路由缓存中的源地址*/
74 if (!inet->inet_saddr)75 inet->inet_saddr = fl4->saddr;76 /*设置接收地址为源地址*/
77 sk_rcv_saddr_set(sk, inet->inet_saddr);78
79 /*控制块中的时间戳存在&& 目的地址不是当前地址*/
80 /*控制块被使用过,重新初始化*/
81 if (tp->rx_opt.ts_recent_stamp && inet->inet_daddr !=daddr) {82 /*Reset inherited state*/
83 tp->rx_opt.ts_recent = 0;84 tp->rx_opt.ts_recent_stamp = 0;85 if (likely(!tp->repair))86 tp->write_seq = 0;87 }88
89 /*设置目的端口*/
90 inet->inet_dport = usin->sin_port;91 /*设置目的地址*/
92 sk_daddr_set(sk, daddr);93
94 /*获取ip选项长度*/
95 inet_csk(sk)->icsk_ext_hdr_len = 0;96 if(inet_opt)97 inet_csk(sk)->icsk_ext_hdr_len = inet_opt->opt.optlen;98
99 /*设置mss*/
100 tp->rx_opt.mss_clamp =TCP_MSS_DEFAULT;101
102 /*Socket identity is still unknown (sport may be zero).103 * However we set state to SYN-SENT and not releasing socket104 * lock select source port, enter ourselves into the hash tables and105 * complete initialization after this.106 */
107 /*设置连接状态为TCP_SYN_SENT*/
108 tcp_set_state(sk, TCP_SYN_SENT);109
110 /*端口绑定,加入ehash*/
111 err =inet_hash_connect(tcp_death_row, sk);112 if(err)113 gotofailure;114
115 /*设置hash值*/
116 sk_set_txhash(sk);117
118 /*
119 如果源端口或者目的端口发生变化,120 重新获取路由,并更新sk的路由缓存121 */
122 rt =ip_route_newports(fl4, rt, orig_sport, orig_dport,123 inet->inet_sport, inet->inet_dport, sk);124 if(IS_ERR(rt)) {125 err =PTR_ERR(rt);126 rt =NULL;127 gotofailure;128 }129 /*OK, now commit destination to socket.*/
130 sk->sk_gso_type =SKB_GSO_TCPV4;131
132 /*存储目的路由缓存和网络设备特性到控制块*/
133 sk_setup_caps(sk, &rt->dst);134 rt =NULL;135
136 if (likely(!tp->repair)) {137 /*获取发送序号*/
138 if (!tp->write_seq)139 tp->write_seq = secure_tcp_seq(inet->inet_saddr,140 inet->inet_daddr,141 inet->inet_sport,142 usin->sin_port);143 /*时间戳偏移*/
144 tp->tsoffset = secure_tcp_ts_off(inet->inet_saddr,145 inet->inet_daddr);146 }147
148 /*设置ip首部的id*/
149 inet->inet_id = tp->write_seq ^jiffies;150
151 /*fastopen*/
152 if (tcp_fastopen_defer_connect(sk, &err))153 returnerr;154 if(err)155 gotofailure;156
157 /*发送syn*/
158 err =tcp_connect(sk);159
160 if(err)161 gotofailure;162
163 return 0;164
165 failure:166 /*
167 * This unhashes the socket and releases the local port,168 * if necessary.169 */
170 tcp_set_state(sk, TCP_CLOSE);171 ip_rt_put(rt);172 sk->sk_route_caps = 0;173 inet->inet_dport = 0;174 returnerr;175 }