tcp当主动发出syn_TCP主动打开 之 第一次握手-发送SYN

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 }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值