-
Notifications
You must be signed in to change notification settings - Fork 0
/
linux网络源码读取笔记
1124 lines (969 loc) · 26.5 KB
/
linux网络源码读取笔记
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
struct socket {
short type;
socket_state state;
long flags;
struct proto_ops *ops;
void *data;
struct socket *conn;
struct socket *iconn;
struct socket *next;
struct wait_queue **wait;
struct inode *inode;
struct fasync_struct *fasync_list;
}
struct proto_ops{
int family;
int (*create)(...)
...
}
struct sockaddr {
unsigned short sa_family;
char sa_data[14];
}
struct linger {
int l_onoff;
int l_linger;
}
int sock_wake_sync(struct socket *sock,int how)
int sock_register(int family,struct proto_ops *ops)
int sock_unregister(int family)
struct socket *sock_alloc(void)
void sock_release(struct socket *sock)
struct old_rtentry{
uunssigned longrt_genmask;
struct sockaddr rt_dst;
struct sockaddr rt_gateway;
short rt_flags;
short rt_refcnt;
unsigned longrt_use;
char *rt_dev;
};
struct rtentry{
unsigned longrt_hash;
struct sockaddr rt_dst;
struct sockaddr rt_gateway;
struct sockaddr rt_genmask;
short rt_flags;
short rt_refcnt;
unsigned longrt_use;
struct ifnet *rt_ifp;
short rt_metric;
char *rt_dev;
unsigned longrt_mss;
unsigned longrt_window;
}
网络层对应的普通文件操作函数集合
struct file_operations socket_file_ops={
sock_lseek,
sock_read,
sock-write,
sock_readdir,
sock_select,
sock_ioctl,
sock_close,
sock_fasync
};
int get_fd(struct inode *inode)
{
.....
current->files->fd[fd]=file;
file->f_op=&socket_file_ops;
return (fd);
}
socket 查询函数
inline struct socket*socki_lookup(struct inode*inode)
{
return &inode->u.socket_i;
}
struct socket *sockfd_lookup(int fd, struct file **pfile)
{
...
inode=file->f_inode;
return socki_lookup(inode);
}
分配socket结构
struct socket *sock_alloc(void)
{ ...
inode=get_empty_inode();
初始化inode...
sock=inode->u.socket_i;
初始化sock...
sock->inode=inode;
...
return sock;
}
被socket_release调用
socket_release_peer(struct socket *peer)
{
peer->state=SS_DISCONNECTING;
wake_up_interruptible(peer->wait);
sock_wake_async(peer,1);
}
sock_release(struct socket *sock)
{
。。。
释放sock的所有的iconn;
。。。
sock_ops_release(sock,peersock);
if(sock->conn)
sock_release_peer(sock->conn);
iput(inode);
}
close函数
sock_close(struct inode*inode,struct file*filp)
{
...
sock=socki_llokup(inode);
sock_fasync(inode,filp,0);
sock_release(sock);
}
注意:sock_fasync根据第三个参数决定是申请fasync_struct还是释放
其他函数实现
int sock_lseek(struct inode *inode,struct file *file,off_t offset,int whence)
{
return (-ESPIPE);(未实现)
}
int sock_read(struct inode*inode ,struct file*file,chaar *ubuf,int size)
{
...根据inode查找socket
....效验参数
return(sock->ops-read)(sock,ubuf,size,(flags..))
}
int sock_write(struct inode*inode,struct file *file,char *buf,iont size))
{
...根据inode查找socket
....效验参数
return(sock->ops->write)(sock,ubuf,size,(flags..))
}
int sock_readdir(struct inode*inode,struct file *file,char *buf,iont size))
{
return (EBADF);未实现
}
int sock_ioctl(struct inode*inode,struct file *file,char *buf,iont size))
{
...根据inode查找socket
....效验参数
return(sock->ops->ioctl)(sock,ubuf,size,(flags..))
}
int sock_select(struct inode*inode,struct file *file,char *buf,iont size))
{
...根据inode查找socket
....效验参数
return(sock->ops->select)(sock,sel_type,wait)
}
分配sock结构
int sock_socket(int family,int type,int protocol)
{
...
根据family匹配pops[i]->family
找不到返回非法值
检查type是否合法不合法返回非法值
分配sock结构
初始化sock的type与ops
获取空的fd关联sock
返回fd
}
int sock_socketpair(int family,int type,int protocol,unsigned long usockvec[2])
{
...
fd1=soco_socket(...)
判断fd1合法
sock1=sockfd_lookup(fd1,NULL);
检查sock->ops->socketpair是否存在不存在返回非法值
同样方法获取sock2
sock1->conn=sock2
sock2->conn=sock1
sock1->state=SS_CONNECTED
sock2->state=SS_CONNECTED
赋值给usocjvew
返回0
}
int sock_bind(int fd,struct sockaddr *umyaddr,int addrlen)
{
参数检查
sock=sockfd_lookup(fd,NULL);
读取用户态地址
i=sock->ops->bind(sock,(struct address*)umyaddr,addrlen);
判断返回
}
int sock_listen(int fd,int backlog)
{
参数检查
sock=sockfd_lookup(fd,NULL);
判断sock->state是否为SS_UNCONNECTED不是即返回
根据是否存在sock->ops->listen决定是否调用sock->ops->listen(sock,backlog);
sock->flags|=SS_ACCEPTCON;
返回0
}
int sock_accept(int fd,struct sockaddr *upeer_sockaddr,int upeer_addrlen)
{
参数检查
sock=sockfd_lookup(fd,&file);
判断sock->state是否等于SS_UNCONNECTED(要求等于)
判断sock->flags是否包含SO_ACCEPTCON(必须包含)
分配newsock=sock_alloc();
newsock->type=sock->type;
newsock->ops=sock->ops;ervaddr,
调用i=newsock->ops->accept(sock,newsock,file->f_flags);
判断返回值int
fd=get_fd(SOCK_INODE(NEWSOCK));
如果upeer_sockaddr不为空调用newsock->ops->getname)获取对端地址信息返回用户空间
return fd;
}
int sock_connect(int fd, struct sockaddr*uservaddr,int addrlen)
{
参数检查
sock=sockfd_lookup(fd,&file);
从用户态读取地址
判断当前sock->state
如果是SS_UNCONNEECTED
break;
如果是SS_CONNECTED
{
判断sock->type==SOCK_DGRAM)
返回错误值
否则break;
}
如果是SS_CONNECTING
break;
default
返回非法值
调用i=sock->ops->connect(sock,(struct sockaddr*)address,addrlen,file->f_flags);
return i;
return 0;
}
获取本端地址信息(IP and port)
int sock_getsockname(int fd, struct sockaddr *uservaddr,int uservaddrlen)
{
参数检查
sock=sockfd_lookup(fd,NULL);
sock->ops->getname(sock,(struct sockaddr*)address,&len,0);
赋值到用户态
}
获取对端地址信息
int sock_getpeername(int fd, struct sockaddr *uservaddr,int uservaddrlen
{
参数检查
sock=sockfd_lookup(fd,NULL);
sock->ops->getname(sock,(struct sockaddr*)address,&len,1);//最后一位决定获取对端还是本端
赋值到用户态
}
int sock_send(int fd,void*buff,int len,unsigned flags)
{
参数检查
sock=sockfd_lookup(fd,NULL);
return sock->ops->send(sock,buff,len,(file->f_flags)&O_NOBLOCK),flags);
}
int sock_sendto(int fd,void*buff,int len,unsigned flags,struct sockaddr &addr,int addrlen)
{
参数检查
sock=sockfd_lookup(fd,NULL);
读取用户态地址
return sock->ops->sendto(sock,buff,len,(file->f_flags)&O_NOBLOCK),flags,sockaddr,addrlen);
}
int sock_recv(int fd,void*buff,int len,unsigned flags)
{
参数检查
sock=sockfd_lookup(fd,NULL);
return sock->ops->recv(sock,buff,len,(file->f_flags)&O_NOBLOCK),flags);
}
int sock_recvfrom(int fd,void*buff,int len,unsigned flags,struct sockaddr &addr,int addrlen)
{
参数检查
sock=sockfd_lookup(fd,NULL);
len=sock->ops->recvfrom((sock,buff,len,(file->f_flags)&O_NOBLOCK),flags,sockaddr,addrlen);
若addr不为空将地址赋值给用户态
返回len
}
int sock_setsockopt(int fd,int level,int optname,char *optval,int optlen)
{
参数检查
sock=sockfd_lookup(fd,NULL);
return sock->ops->setsockopt(sock,level,optname,optval,optlen);
}
int sock_getsockopt(int fd,int level,int optname,char *optval,int *optlen)
{
参数检查
sock=sockfd_lookup(fd,NULL);
return sock->ops->getsockopt(sock,leveloptname,optval.optlen);
}
int sock_shutdown(int fd,int how)
{
参数检查
sock=sockfd_lookup(fd,NULL);
return sock->ops->shutdown(sock,how);
}
int sock_fcntl(struct file*filp,unsigned int cmd,unsigned long arg)
{
sock=sockfd_lookup(filp->i_inode);
return sock->ops->fcntl(sock,cmd,arg);
}
sys_socketcall(int call, unsigned long *args)
{
根据call分发调用对应函数
}
注册协议
int sock_register(int family,struct proto_ops *ops)
{
遍历pops数组找个空闲位置插入ops
pops[i]=ops;
pops[i]->family=family;
return i;
}
int sock_unregister(int family)
{
查找pops[i]->family=family;
pops[i]=NULL;
return i;
}
获取当前使用的套接字总数
sock_get_info(char *buff,char **start,off_t offset,int length)
{
....
socket_in_uses计数
...
}
struct sock {
struct options *opt;//IP选项缓存于此处
//当前写缓冲区大小
volatile unsigned long wmem_alloc;
//当前读缓冲区大小
volitile unsigned long rmem_alloc;
//写序列
unsigned long write_seq;
//已发送序列
unsigned long sent_seq;
//已确认序列
unsigned long acked_seq;
//已接收单未读取的数据第一个字节
unsigned long copied_seq;
//表示远端对本地已经应答acked的序列号
unsigned long rcv_ack_seq;
//窗口的大小
unsigned long window_seq;
//当接收到对方fin数据包的最后一个字节+1
unsigned long fin_seq;
//紧急数据最大序列号
unsigned long urg_seq;
//紧急数据
unsigned long urg_data;
volatile char inuse,//inuse=1表示其他进程在使用sock
dead, //dead=1表示此sock已经被释放
urginline,//=1表示紧急数据当做普通数据处理
intr,
blog, //=1 表示sock处于节制状态,接受的数据包都被丢弃
done,
reuse,
keepopen,//=1表示使用保活定时器
linger,//=1表示在关闭套接字时需要等待
一段时间以确认其关闭
delay_acks,//=1表示延迟应答,可一次对多个数据包应答
destroy, //=1表示该sock等待销毁
ack_timed,
no_check,
zapped,//当本地接受到远端发送的复位数据包置1
broadcast,
bonagle;//=1表示不使用nagle算法
unsigned long lingertime;//表示等待关闭的时间
int proc;//该sock结构所属进程的进程号
struct sock *next;
struct sock *prev;
struct sock *pair;
//send_head、send_tail用于tcp协议重发队列
struct sk_buff *volitile send_head;
struct sk_buff *volitile send_tail;
//back_log为接收的数据包缓存队列
struct sk_buff_head back_log;
//partial为用于创建最大长度待发送数据包(聚合数据包)
struct sk_buff *partial
//partial_timer用于按时发送partial指向的数据包
struct time_list partial_timer;
long retransmits;//表示重发次数
/*write_queue表示待发送数据包,
struct sk_buff *receive_queue表示待被应用程序读取的数据包队列
从back_log中取下放在此队列供应用程序读取
*/
struct sk_buff_head write_queue,receive_queue;
struct proto *prot;//指向传输层处理函数集
struct wait_queue **sleep;//进程等待队列
unsigned long daddr;//sock结构所代表套接字的远端地址
unsigned long saddr;//本地地址
unsigned short max_unacked;//最大未处理请求连接数
unsigned short window;//远端窗口大小
unsigned short bytes_rcv;//已接收未应答字节总数
unsigned short mtu;//协商的mtu大小
volatile unsigned short mss;//mss=mtu-ip以及tcp首部长度
volatile unsigned usre_mss;//用户指定mss
volatile unsigned short max_window;//最大窗口大小
unsigned long window_clamp;//窗口大小钳制值
unsigned shrot num;//本地端口号
volatile unsigned short cong_window;
volatile unsigned short cong_count;
volatile unsigned short ssthresh;
//本地已发送但是未得到应答的数据包数目
volatile unsigned short packets_out;
volatile unsigned short shutdown;//本地关闭标志位
volatile unsigned long rtt;//RTTS
volatile unsigned long mdev;//RTTD绝对偏差
volatile unsigned long rto;//算法算出延迟时间
volatile unsigned long backoff;//退避算法度量值
volatile short err;//错误标志值
unsigned char protocol;//传输层协议值
volatile unsigned char state;//套接字状态值
volatile unsigned char ack_backlog;//缓存未应答数据包个数
volatile char max_ack_backlog;//缓存未应答的数据包最大的个数
unsigned char priority;//该套接字优先级
unsigned char debug;
unsigned short rcvbuf;//最大接收缓冲区大小
unsigned short sndbuf;//最大发送缓冲区大小
unsigned short type;//套接字类型
unsigned char localroute;//表示只是用本地路由
int ip_ttl;//ttl值
int ip_tos;//TOS值
//用于缓存tcp首部,在tcp中创建发送一个数据包时可利用此字段快速创建
struct tcphdr dummy_th;
struct time_list keepalive_timer;//保活定时器
struct time_list restransmit_timer;//重发定时器,用于数据包重发
struct time_list ack_timer;//设置定时器发送应答数据包
int ip_xmit_timeout;//用于定时器超时原因
struct time_list timer;//
struct timeval stamp;//时间戳
struct socket *socket;
void (*state_change)(struct sock*sk);
void (*data_ready)(struct sock*sk,int bytes);
void (*write_sapce)(struct sock *sk);
void (*error_report)(struct sock *sk);
}
struct proto {
...
操作函数指针
...
unsigned short max_header;
unsigned long retransmits;
//num%256插入对应的sock_array链表
struct sock sock_array[SOCK_ARRAY_SIZE];
char name[80];
int inuse,highestinuse;
}
检测端口号是否被使用
int sk_inuse(struct proto *prot,int num)
{
...
sk=prot->sock_array[num&(SOCK_ARRAY_SIZE-1)];
if(sk->num==num)
return 1;
遍历完了查不到
return 0;
}
分配端口号
get_new_socknum(struct proto *prot,unsigned short base)
{
...
根据base查找端口号是否未使用若未使用直接返回
否则查找一个未使用
确认是否在使用中
返回端口号
}
//将一个确定端口号的sock加入sock_array[]
数组
put_sock(unsigned short num,struct sock *sk)
{
。。。
sk->proto->inuse+=1;
....
sk->next=sk->prot->sock_array[num];
sk->prot->sock_array[num]=sk;
...
}
//从sock_array中删除指定的sock
remove_sock(struct sock *sk)
{
...
sk->prot->inuse-=1;
....
sk2->next=sk->next;
...
}
//销毁一个连接包括sock
destroy_sock(struct sock*sk)
{
...
sk->inuse=1;
..检查sk->dead
remove_sock(sk);
delete_timer(sk);
del_timer(&sk->retransmits_timer);
释放partial数据包
清空写队列clean sk->write_queue
判断sk->dead标志
清空待读取的数据包队列sk->receive_queue
判断是否是监听套接字若是skb->sk->dead=1;skb->sk->prot->close(skb->sk,0)
清空重发对列 sk->send_head
清空数据包缓存队列sk->back_log
判断sk->pair 若存在则sk->pair->dead=1;sk->pair->prot->close(sk->pair,0);sk->pair=NULL;
若sk->dead标志设置且sk->rmem_allpc==0&&sk->wmem_alloc==0,释放sk
否则设置个定时器等其他进程释放缓冲区后释放sk
}
int inet_fcntl(struct socket *sock,unsigned int cmd,unsigned long arg)
{
....
sk=(struct sock*)sock->data;
//仅仅提供设置和读取套接字属主的功能
...
}
int inet_setsockopt(struct socket *sock,int level,int optname,char *optval,int optlen)
{
...
sk=(struct sock*)sock->data;
...
判断sk->prot->setsockopt是否存在存在则调用(sk,level,optname,optval,optlen);
否则返回EOPNOTSUPP
}
int inet_getsockopt(struct socket *sock,int level,int optname,char *optval,int optlen)
{
...
sk=(struct sock*)sock->data;
...
判断sk->prot->getsockopt是否存在存在则调用(sk,level,optname,optval,optlen);
否则返回EOPNOTSUPP
}
int inet_autobind(struct sock *sk)
{
...
if(sk->num==0)
sk->num=get_new_socknum(sk->prot,0);
如果分配失败返回EAGAIN错误
put_sock(sk->num,sk);
sk->dummy_th.source=ntohs(sk->num);
return 0;
}
int inet_listen(struct socket *sock,int backlog)
{
struct sock *sk=(struct sock *)sock->data;
if(inet_autobind(sk)!=0)
return -EAGAIN;
判断参数合法
sk->max_ack_backlog=backlog;
如果sk->state!=TCP_LISTEN
sk->ack_backlog=0;
sk->state=TCP_LISTEN;
return 0;
}
//事件通知回调函数
void def_callback1(struct sock *sk)
{
if(!sk->dead)
wake_up_interruptible(sk->sleep);//唤醒睡眠在sk->sleep上的进程
}
void def_callback2(struct sock *sk,int len)
{
if(!sk->dead)
{
wake_up_interruptible(sk->sleep);
sock_wake_async(sk->socket,1);//注意传参不同
}
}
void def_callback3(struct sock *sk)
{
if(!sk->dead)
{
wake_up_interruptible(sk->sleep);
sock_wake_async(sk->socket,2);
}
}
//sock创建以及初始化
int inet_create(struct socket *sock,int protocol)
{
。。。
分配个sk
。。。判断
初始化sk->num=0、sk->reuse=0;
根据sock->type判断protocol是否为对应的IPPROTO_TCP\IPPROTO_UDP\IPPROTO_RAW\IPPROTO_PACKET;
初始化sk->proto为对应的tcp_proto\udp_proto\raw_proto\packet_proto
tcp_proto:sk->no_check=TCP_NO_CHECK;
udp_proto:sk->no_check=UDP_NO_CHECK;
raw_proto:sk->no_check=0;sk->reuse=1;sk->num=protocol;
pckets_proto:sk->reuse=1;sk->no_check=0;sk->num=protocol;
sk->sock=sock;
//初始化sk->nonagle=1\0;
sk->type=sock->type;
sk->stamp.tv_sec=0;
sk->protocol=protocol;
//初始化sk_wmem\rmerm_alloc=0;
//初始化sk->sndbuf\rcvbuf=SK_WMEME_MAX\SK_RMEM_MAX;
sk->[air=NULL;
sk->opt=NULL;
sk->write_seq=0;
sk->acked_seq=0;
sk->copied_seq=0;
sk->fin_seq=0;
sk->urg_seq=0;
sk->urg_data=0;
sk->proc=0;
sk->rtt=0;
sk->rto=TCP_TIMEOUT_INET;
sk->mdev=0;
sk->backoff=0;
sk->packets_out=0;
sk->cong_window=1;
sk->cong_count=0;
sk->ssthresh=0;
sk->max_window=0;
sk->urgline=0;
sk->intr=0;
sk->linger=0;
sk->destroy=0;
sk->priority=1;
sk->shutdown=0;
sk->keepopen=0;
sk->zapped=0;
sk->done=0;
sk->ack_backlog=0;
sk->window=0;
sk->bytes=0;
sk->state=TCP_CLOSE;
sk->dead=0;
sk->ack_timed=0;
sk->partial=NULL;
sk->user_mss=0;
sk->debug=0;
sk->unacked=2048;
sk->max_ack_backoff=0;
sk->inuse=0;
sk->delay_acks=0
skb_queue_head_init(&sk->write_queue);
skb_queue_head_init(&sk->receive_queue);
sk->mtu=576;
sk->prot=prot;//前面已初始化
sk->sleep=sock->wait;
sk->daddr=0;
sk->saddr=0;
sk->err=0;
sk->next=NULL;
sk->pair=NULL;
sk->sendtail=NULL;
sk->send_head=NULL;
sk->timeout=0;
sk->broadcast=0;
sk->localroute=0;
init_timer(&sk->timer);
init_timer(&sk->restransmit_time);
sk->timer.data=(unsigned long )sk;
sk->timer.funcation=&net_timer;
skb_queue_head_init(&sk->back_log);
sk->blog=0;
sock->data=(void*)sk;
//tcp初始化
sk->dummy_th.doff=sizeof(sk->dummy_th)/4;
sk->dummy_th.res1=0;
sk->dummy_th.res2=0;
sk->dummy_th.urg_prt=0;
sk->dummy_th.fin=0;
sk->dummy_th.syn=0;
sk->dummy_th.rst=0;
sk->dummy_th.psh=0;
sk->dummy_th.ack=0;
sk->dummy_th.urg=0;
sk->dummy_th.dest=0;
sk->ip_tos=0;
sk->ip_ttl=64;
//多播初始化
sk->ip_mc_loop=1;
sk->ip_mc_ttl=1;
sk->ipmc_name=0;
sk->ip_mc_list=NULL;
//初始化回调函数
sk->state_change=def_callback1;
sk->data_ready=def_callback2;
sk->write_sapce=def_callback3;
sk->error_report=def_callback1;
//如果定义了num
put_sock(sk->num,sk);
sk->dummy_th.source=ntos(sk->num);
//若定义了sk->prot->init
则调用sk->prot->init(sk);
return 0;
}
}
//赋值sk
int inet_dup(struct socket *newsock,struct socket*oldsock)
{
rteturn (inet_create(newsock,((struct sock*)oldsock->data)->protocol));
}
//套接字状态检测
inline int closing(struct sock *sk)
{
判断sk->state是否为TCP_FIN_WAITE1\
TCP_CLOSING;
TCP_LAST_ACK;
也就是还有数据没有发送完
return 1;
否则return 0;
}
//套接字释放
int inet_release(struct socket*sock,struct socket*peer)
{
sk=(struct sock*)socket->data;
sk->state_change(sk);
//判断sk->lingertime是否为0
若为0则sk->prot->close(sk,0);
否则sk->prot_close(sk,0);并将当前进程处于睡眠中时间为lingertime;
while(closing(sk)&&timeout>0)
可中断睡眠
自然超时
sk->dead=1;
sk->inuse=1;
release_sock(sk);
sock->data=NULL;
sk->socket=NULL;
return(0);
}
int inet_bind(struct socket*sock,struct sockaddr*uaddr,int addr_len)
{
sk=(struct sock*)sock_data;
//判断ssk->state是否为TCP_CLOSE;
若sock->type不为SOCK_RAW;
判定传入端口是否为0 为0 自动分配一个snum;
检查地址是否为本地网卡地址且不是多播地址则出错
进行端口检查以及地址检查
然后
//以下包括raw套接字
remove_sock(sk);
put_sock(snum,sk);
sk->dummy_th.source=ntos(sk->num);
sk->daddr=0;
sk->dummy_th.dest=0;
return 0;
}
//获取错误
int inet_error(struct sock *sk)
{
err=sk->err;
sk->err=0;
return -err;
}
enum{
TCP_ESTABLISHED=1;
TCP_SYN_SENT,
TCP_SYN_RECV,
TCP_FIN_WAIT1,
TCP_FIN_WAIT2,
TCP_TIME_WAIT,
TCP_CLOSE,
TCP_CLOSE_WAIT,
TCP_LAST_ACK,
TCP_LISTEN,
TCP_CLOSING};
int inet_connect(struct socket *sock,struct sockaddr *uaddr,int addr_len,int flags)
{
sk=(struct sock *)sock->data;
if(sock->state==SS_CONNECTING&&tcp_connected(sk->state))
直接将sock->state==SS_CONNECTED;
return 0;
if(sock->state==SS_CONNECTING&&SK->PROTOCOL==IPPROTO_TCP&&(flags&O_NONBLOCK))
return -EALREADY;//正在连接非阻塞直接返回
if(sock->state!=SS_CONNECTING)
inet_autobind(sk);//绑定sk
sk->prot->connect(sk,(struct sockaddr_in*)uaddr,addr_len)//调用prot->connect
//将sock->state==SS_CONNECTING
if(sk->state>TCP_FIN_WAIT2&&sock->state==SS_CONNECTING)
//将sock->state==SS_UNCONNECTED;
err=sk->err//获取错误
return err;
if(sk->state!=TCP_ESTABLISHED&&(flags&O_NONBLOCK))
return -EINPROGRESS;//返回进行中
while(sk->state==TCP_SYN_SENT||sk->state==TCP_SYN_RECV)
{
可中断睡眠在sk->sleep上
//下面为唤醒
if(sk->err&&sk->0protocol==IPPROTO_TCP)
sock->state==SS_UNCONNECTED
err=-sk->err;
return err;
}
//这一步说明是握手完成
sock->state==SS_CONNECTED;
//排除sk->state非TCP_ESTABLEISHED异常情况
if(sk->state!=TCP_ESTABLISHED&&sk->err)
sock->state==SS_UNCONNECTED;
err=-sk->err;
return err;
return 0;
}
2.6不支持inet_socketpair
accept的inet层实现
int inet_accept(struct socket &sock,struct socket*newsock,int flags)
{
sk1=(struct sock*)sock->data;
//判断newsock的sk存在则释放
if(newsock->data)
{
sk=(struct sock*)newsock->data;
newsock->data=NULL;
sk->dead=1;
destroy_sock(sk);
}
//判断sk1->prot->accept是否存在不存咋则返回
if(sk1->pair!=NULL)
sk2=sk1->pair;
sk1->pair=NULL;
else
sk2=-sk1->prot->accept(sk1,flags);
if(sk2==NULL)
//出错
err=sk1->err;
sk1->err=0;
return -err;
}
//没有出错
newsock0->data=(void*)sk2;
//初始化新的sk2的值
sk2->sleep=newsock->wait;
sk2->socket=newsock;
newsock->conn=NULL;
//如果非阻塞直接返回0
if(flags&O_NONBLOCK)
return 0;
while(sk2->state==TCP_SYN_RECV)
{
可中断睡眠在sk2->sleep注意是新的sk2
}
if(sk2->state!=TCP_ESTABLISHED&&sk2->err>0)
{
err=-sk2->err;
sk2->err=0;
sk2->dead=1;
destroy_sock(sk2);
newsock->data=NULL;
return err;
}
newsock->state==SS_CONNECTED;
return 0;
}
//用于获取本段和对端的地址
int inet_getname(struct socket *sock,struct sockaddr*uaddr,int uaddr_len,int peer)
{
sin=(struct sockaddr_in*)uaddr;
sin->sin_family=AF_INET;
sk=(struct sock*)sock->data;
if(peer)
{
//获取对端地址信息
//判定是否是连接状态否则返回
if(!tcp_connected(sk->state))
return -ENOTCONN;
sin->sin_port=sk->dummy_th.dest;
sin->sin_addr.s_addr=sk->daddr;
}
else
{
//获取本端地址信息
sin->sin_port=sk->dummy_th.source;