TCP被动打开 之 第二次握手-发送SYN+ACK
时间:2019-10-28
本文章向大家介绍TCP被动打开 之 第二次握手-发送SYN+ACK,主要包括TCP被动打开 之 第二次握手-发送SYN+ACK使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
假定客户端执行主动打开,发送syn包到服务器,服务器执行完该包的第一次握手操作后,调用af_ops->send_synack向客户端发送syn+ack包,该回调实际调用tcp_v4_send_synack函数;
1 int tcp_conn_request(struct request_sock_ops *rsk_ops, 2 const struct tcp_request_sock_ops *af_ops, 3 struct sock *sk, struct sk_buff *skb) 4 { 5 /* 第一次握手的服务器处理 */ 6 7 /* 发送syn+ack */ 8 af_ops->send_synack(sk, dst, &fl, req, &foc, 9 !want_cookie ? TCP_SYNACK_NORMAL : 10 TCP_SYNACK_COOKIE); 11 return 0; 12 }
tcp_v4_send_synack完成路由查找,构造syn+ack包,构造ip包,然后发送出去;
1 /* 2 * Send a SYN-ACK after having received a SYN. 3 * This still operates on a request_sock only, not on a big 4 * socket. 5 */ 6 static int tcp_v4_send_synack(const struct sock *sk, struct dst_entry *dst, 7 struct flowi *fl, 8 struct request_sock *req, 9 struct tcp_fastopen_cookie *foc, 10 enum tcp_synack_type synack_type) 11 { 12 const struct inet_request_sock *ireq = inet_rsk(req); 13 struct flowi4 fl4; 14 int err = -1; 15 struct sk_buff *skb; 16 17 /* First, grab a route. */ 18 /* 路由为空则查路由 */ 19 if (!dst && (dst = inet_csk_route_req(sk, &fl4, req)) == NULL) 20 return -1; 21 22 /* 构造syn+ack包 */ 23 skb = tcp_make_synack(sk, dst, req, foc, synack_type); 24 25 if (skb) { 26 /* 生成校验码 */ 27 __tcp_v4_send_check(skb, ireq->ir_loc_addr, ireq->ir_rmt_addr); 28 29 /* 构造ip包并发送 */ 30 err = ip_build_and_send_pkt(skb, sk, ireq->ir_loc_addr, 31 ireq->ir_rmt_addr, 32 ireq->opt); 33 34 /* 返回错误是否为本地阻塞判断 */ 35 err = net_xmit_eval(err); 36 } 37 38 return err; 39 }
tcp_make_synack函数完成skb分配,tcp首部的构造;
1 struct sk_buff *tcp_make_synack(const struct sock *sk, struct dst_entry *dst, 2 struct request_sock *req, 3 struct tcp_fastopen_cookie *foc, 4 enum tcp_synack_type synack_type) 5 { 6 struct inet_request_sock *ireq = inet_rsk(req); 7 const struct tcp_sock *tp = tcp_sk(sk); 8 struct tcp_md5sig_key *md5 = NULL; 9 struct tcp_out_options opts; 10 struct sk_buff *skb; 11 int tcp_header_size; 12 struct tcphdr *th; 13 int mss; 14 15 /* 分配skb */ 16 skb = alloc_skb(MAX_TCP_HEADER, GFP_ATOMIC); 17 if (unlikely(!skb)) { 18 dst_release(dst); 19 return NULL; 20 } 21 /* Reserve space for headers. */ 22 /* 保留头部空间 */ 23 skb_reserve(skb, MAX_TCP_HEADER); 24 25 switch (synack_type) { 26 case TCP_SYNACK_NORMAL: 27 /* skb关联控制块 */ 28 skb_set_owner_w(skb, req_to_sk(req)); 29 break; 30 case TCP_SYNACK_COOKIE: 31 /* Under synflood, we do not attach skb to a socket, 32 * to avoid false sharing. 33 */ 34 break; 35 case TCP_SYNACK_FASTOPEN: 36 /* sk is a const pointer, because we want to express multiple 37 * cpu might call us concurrently. 38 * sk->sk_wmem_alloc in an atomic, we can promote to rw. 39 */ 40 skb_set_owner_w(skb, (struct sock *)sk); 41 break; 42 } 43 44 /* 设置路由缓存 */ 45 skb_dst_set(skb, dst); 46 47 /* mss取从路由表中查询的mss与user_mss之间的较小值 */ 48 mss = tcp_mss_clamp(tp, dst_metric_advmss(dst)); 49 50 memset(&opts, 0, sizeof(opts)); 51 #ifdef CONFIG_SYN_COOKIES 52 if (unlikely(req->cookie_ts)) 53 skb->skb_mstamp.stamp_jiffies = cookie_init_timestamp(req); 54 else 55 #endif 56 57 /* 获取时间戳 */ 58 skb_mstamp_get(&skb->skb_mstamp); 59 60 #ifdef CONFIG_TCP_MD5SIG 61 rcu_read_lock(); 62 md5 = tcp_rsk(req)->af_specific->req_md5_lookup(sk, req_to_sk(req)); 63 #endif 64 65 /* 设置hash */ 66 skb_set_hash(skb, tcp_rsk(req)->txhash, PKT_HASH_TYPE_L4); 67 /* 设置tcp选项 */ 68 tcp_header_size = tcp_synack_options(req, mss, skb, &opts, md5, foc) + 69 sizeof(*th); 70 71 /* 构造填充tcp头 */ 72 skb_push(skb, tcp_header_size); 73 skb_reset_transport_header(skb); 74 75 th = (struct tcphdr *)skb->data; 76 memset(th, 0, sizeof(struct tcphdr)); 77 /* 设置syn+ack标记 */ 78 th->syn = 1; 79 th->ack = 1; 80 tcp_ecn_make_synack(req, th); 81 /* 设置源目的端口 */ 82 th->source = htons(ireq->ir_num); 83 th->dest = ireq->ir_rmt_port; 84 /* Setting of flags are superfluous here for callers (and ECE is 85 * not even correctly set) 86 */ 87 88 /* 初始化无数据的skb,标志为syn+ack */ 89 tcp_init_nondata_skb(skb, tcp_rsk(req)->snt_isn, 90 TCPHDR_SYN | TCPHDR_ACK); 91 92 /* 设置序号和确认序号 */ 93 th->seq = htonl(TCP_SKB_CB(skb)->seq); 94 /* XXX data is queued and acked as is. No buffer/window check */ 95 th->ack_seq = htonl(tcp_rsk(req)->rcv_nxt); 96 97 /* RFC1323: The window in SYN & SYN/ACK segments is never scaled. */ 98 /* 设置窗口 */ 99 th->window = htons(min(req->rsk_rcv_wnd, 65535U)); 100 101 /* 写入选项 */ 102 tcp_options_write((__be32 *)(th + 1), NULL, &opts); 103 104 /* 设置首部长度 */ 105 th->doff = (tcp_header_size >> 2); 106 __TCP_INC_STATS(sock_net(sk), TCP_MIB_OUTSEGS); 107 108 #ifdef CONFIG_TCP_MD5SIG 109 /* Okay, we have all we need - do the md5 hash if needed */ 110 if (md5) 111 tcp_rsk(req)->af_specific->calc_md5_hash(opts.hash_location, 112 md5, req_to_sk(req), skb); 113 rcu_read_unlock(); 114 #endif 115 116 /* Do not fool tcpdump (if any), clean our debris */ 117 skb->tstamp = 0; 118 return skb; 119 }
原文地址:https://www.cnblogs.com/wanpengcoder/p/11750789.html
- “熊医生”出诊正确率超九成 医院:人工智能更多是辅助
- PLC编程优化方法,让程序运行提速!
- 这是硅谷狂人马斯克对未来做出的11个大胆预测,人工智能比核武器更危险
- 在腾讯云上使用自建DNS
- Spring 4.0.2 学习笔记(1) - 最基本的注入
- 关于女神SQLite的疑惑(2)
- WordPress纯代码仿无觅相关文章图文模式功能(增强版)
- 人工智能时代已悄然来临……
- 人民日报发布周鸿祎署名文章:迎接“大安全”时代的新威胁
- Mono 3.2 上跑NUnit测试
- 为WordPress 文章中的链接自动添加 nofollow标签
- 腾讯刘炽平:海外用户破7000万 微信带开发者“出海”
- 研究称性别不均衡或导致人工智能持有性别偏见
- ASP.NET 2.0加密Web.config 配置文件
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- XLOG段文件跳号现象分析
- codeforce 227E 矩阵快速幂求斐波那契+N个连续数求最大公约数+斐波那契数列的性质
- 疯子的算法总结(五) 矩阵乘法 (矩阵快速幂)
- codeforce 227D Naughty Stone Piles (贪心+递归+递推)
- POJ3614防晒霜 这个贪心有点东西(贪心+优先队列)
- 环形均分纸牌问题(中位数)
- POJ 1176 Party Lamps&& USACO 2.2 派对灯(搜索)
- P1522 牛的旅行 Cow Tours(floyd)
- P1468 派对灯 Party Lamps(BIG 模拟)
- 【JVM系统学习之路系列】 JVM 概述篇
- P1518 两只塔姆沃斯牛 The Tamworth Two(简单的搜索题)
- P1466 集合 Subset Sums 搜索+递推+背包三种做法
- P1465 序言页码 Preface Numbering (手推)
- P1460 健康的荷斯坦奶牛 Healthy Holsteins (简单的dfs)
- P1459 三值的排序 Sorting a Three-Valued