@@ -70,20 +70,22 @@ static int inet_diag_fill(struct sk_buff *skb, struct sock *sk,
70
70
nlh -> nlmsg_flags = nlmsg_flags ;
71
71
72
72
r = NLMSG_DATA (nlh );
73
- if (sk -> sk_state != TCP_TIME_WAIT ) {
74
- if (ext & (1 << (INET_DIAG_MEMINFO - 1 )))
75
- minfo = INET_DIAG_PUT (skb , INET_DIAG_MEMINFO ,
76
- sizeof (* minfo ));
77
- if (ext & (1 << (INET_DIAG_INFO - 1 )))
78
- info = INET_DIAG_PUT (skb , INET_DIAG_INFO ,
79
- handler -> idiag_info_size );
80
-
81
- if ((ext & (1 << (INET_DIAG_CONG - 1 ))) && icsk -> icsk_ca_ops ) {
82
- size_t len = strlen (icsk -> icsk_ca_ops -> name );
83
- strcpy (INET_DIAG_PUT (skb , INET_DIAG_CONG , len + 1 ),
84
- icsk -> icsk_ca_ops -> name );
85
- }
73
+ BUG_ON (sk -> sk_state == TCP_TIME_WAIT );
74
+
75
+ if (ext & (1 << (INET_DIAG_MEMINFO - 1 )))
76
+ minfo = INET_DIAG_PUT (skb , INET_DIAG_MEMINFO , sizeof (* minfo ));
77
+
78
+ if (ext & (1 << (INET_DIAG_INFO - 1 )))
79
+ info = INET_DIAG_PUT (skb , INET_DIAG_INFO ,
80
+ handler -> idiag_info_size );
81
+
82
+ if ((ext & (1 << (INET_DIAG_CONG - 1 ))) && icsk -> icsk_ca_ops ) {
83
+ const size_t len = strlen (icsk -> icsk_ca_ops -> name );
84
+
85
+ strcpy (INET_DIAG_PUT (skb , INET_DIAG_CONG , len + 1 ),
86
+ icsk -> icsk_ca_ops -> name );
86
87
}
88
+
87
89
r -> idiag_family = sk -> sk_family ;
88
90
r -> idiag_state = sk -> sk_state ;
89
91
r -> idiag_timer = 0 ;
@@ -93,37 +95,6 @@ static int inet_diag_fill(struct sk_buff *skb, struct sock *sk,
93
95
r -> id .idiag_cookie [0 ] = (u32 )(unsigned long )sk ;
94
96
r -> id .idiag_cookie [1 ] = (u32 )(((unsigned long )sk >> 31 ) >> 1 );
95
97
96
- if (r -> idiag_state == TCP_TIME_WAIT ) {
97
- const struct inet_timewait_sock * tw = inet_twsk (sk );
98
- long tmo = tw -> tw_ttd - jiffies ;
99
- if (tmo < 0 )
100
- tmo = 0 ;
101
-
102
- r -> id .idiag_sport = tw -> tw_sport ;
103
- r -> id .idiag_dport = tw -> tw_dport ;
104
- r -> id .idiag_src [0 ] = tw -> tw_rcv_saddr ;
105
- r -> id .idiag_dst [0 ] = tw -> tw_daddr ;
106
- r -> idiag_state = tw -> tw_substate ;
107
- r -> idiag_timer = 3 ;
108
- r -> idiag_expires = (tmo * 1000 + HZ - 1 ) / HZ ;
109
- r -> idiag_rqueue = 0 ;
110
- r -> idiag_wqueue = 0 ;
111
- r -> idiag_uid = 0 ;
112
- r -> idiag_inode = 0 ;
113
- #if defined(CONFIG_IPV6 ) || defined (CONFIG_IPV6_MODULE )
114
- if (r -> idiag_family == AF_INET6 ) {
115
- const struct inet6_timewait_sock * tw6 = inet6_twsk (sk );
116
-
117
- ipv6_addr_copy ((struct in6_addr * )r -> id .idiag_src ,
118
- & tw6 -> tw_v6_rcv_saddr );
119
- ipv6_addr_copy ((struct in6_addr * )r -> id .idiag_dst ,
120
- & tw6 -> tw_v6_daddr );
121
- }
122
- #endif
123
- nlh -> nlmsg_len = skb -> tail - b ;
124
- return skb -> len ;
125
- }
126
-
127
98
r -> id .idiag_sport = inet -> sport ;
128
99
r -> id .idiag_dport = inet -> dport ;
129
100
r -> id .idiag_src [0 ] = inet -> rcv_saddr ;
@@ -185,6 +156,62 @@ static int inet_diag_fill(struct sk_buff *skb, struct sock *sk,
185
156
return -1 ;
186
157
}
187
158
159
+ static int inet_twsk_diag_fill (struct inet_timewait_sock * tw ,
160
+ struct sk_buff * skb , int ext , u32 pid ,
161
+ u32 seq , u16 nlmsg_flags ,
162
+ const struct nlmsghdr * unlh )
163
+ {
164
+ long tmo ;
165
+ struct inet_diag_msg * r ;
166
+ const unsigned char * previous_tail = skb -> tail ;
167
+ struct nlmsghdr * nlh = NLMSG_PUT (skb , pid , seq ,
168
+ unlh -> nlmsg_type , sizeof (* r ));
169
+
170
+ r = NLMSG_DATA (nlh );
171
+ BUG_ON (tw -> tw_state != TCP_TIME_WAIT );
172
+
173
+ nlh -> nlmsg_flags = nlmsg_flags ;
174
+
175
+ tmo = tw -> tw_ttd - jiffies ;
176
+ if (tmo < 0 )
177
+ tmo = 0 ;
178
+
179
+ r -> idiag_family = tw -> tw_family ;
180
+ r -> idiag_state = tw -> tw_state ;
181
+ r -> idiag_timer = 0 ;
182
+ r -> idiag_retrans = 0 ;
183
+ r -> id .idiag_if = tw -> tw_bound_dev_if ;
184
+ r -> id .idiag_cookie [0 ] = (u32 )(unsigned long )tw ;
185
+ r -> id .idiag_cookie [1 ] = (u32 )(((unsigned long )tw >> 31 ) >> 1 );
186
+ r -> id .idiag_sport = tw -> tw_sport ;
187
+ r -> id .idiag_dport = tw -> tw_dport ;
188
+ r -> id .idiag_src [0 ] = tw -> tw_rcv_saddr ;
189
+ r -> id .idiag_dst [0 ] = tw -> tw_daddr ;
190
+ r -> idiag_state = tw -> tw_substate ;
191
+ r -> idiag_timer = 3 ;
192
+ r -> idiag_expires = (tmo * 1000 + HZ - 1 ) / HZ ;
193
+ r -> idiag_rqueue = 0 ;
194
+ r -> idiag_wqueue = 0 ;
195
+ r -> idiag_uid = 0 ;
196
+ r -> idiag_inode = 0 ;
197
+ #if defined(CONFIG_IPV6 ) || defined (CONFIG_IPV6_MODULE )
198
+ if (tw -> tw_family == AF_INET6 ) {
199
+ const struct inet6_timewait_sock * tw6 =
200
+ inet6_twsk ((struct sock * )tw );
201
+
202
+ ipv6_addr_copy ((struct in6_addr * )r -> id .idiag_src ,
203
+ & tw6 -> tw_v6_rcv_saddr );
204
+ ipv6_addr_copy ((struct in6_addr * )r -> id .idiag_dst ,
205
+ & tw6 -> tw_v6_daddr );
206
+ }
207
+ #endif
208
+ nlh -> nlmsg_len = skb -> tail - previous_tail ;
209
+ return skb -> len ;
210
+ nlmsg_failure :
211
+ skb_trim (skb , previous_tail - skb -> data );
212
+ return -1 ;
213
+ }
214
+
188
215
static int inet_diag_get_exact (struct sk_buff * in_skb ,
189
216
const struct nlmsghdr * nlh )
190
217
{
@@ -450,6 +477,42 @@ static int inet_diag_dump_sock(struct sk_buff *skb, struct sock *sk,
450
477
cb -> nlh -> nlmsg_seq , NLM_F_MULTI , cb -> nlh );
451
478
}
452
479
480
+ static int inet_twsk_diag_dump (struct inet_timewait_sock * tw ,
481
+ struct sk_buff * skb ,
482
+ struct netlink_callback * cb )
483
+ {
484
+ struct inet_diag_req * r = NLMSG_DATA (cb -> nlh );
485
+
486
+ if (cb -> nlh -> nlmsg_len > 4 + NLMSG_SPACE (sizeof (* r ))) {
487
+ struct inet_diag_entry entry ;
488
+ struct rtattr * bc = (struct rtattr * )(r + 1 );
489
+
490
+ entry .family = tw -> tw_family ;
491
+ #if defined(CONFIG_IPV6 ) || defined (CONFIG_IPV6_MODULE )
492
+ if (tw -> tw_family == AF_INET6 ) {
493
+ struct inet6_timewait_sock * tw6 =
494
+ inet6_twsk ((struct sock * )tw );
495
+ entry .saddr = tw6 -> tw_v6_rcv_saddr .s6_addr32 ;
496
+ entry .daddr = tw6 -> tw_v6_daddr .s6_addr32 ;
497
+ } else
498
+ #endif
499
+ {
500
+ entry .saddr = & tw -> tw_rcv_saddr ;
501
+ entry .daddr = & tw -> tw_daddr ;
502
+ }
503
+ entry .sport = tw -> tw_num ;
504
+ entry .dport = ntohs (tw -> tw_dport );
505
+ entry .userlocks = 0 ;
506
+
507
+ if (!inet_diag_bc_run (RTA_DATA (bc ), RTA_PAYLOAD (bc ), & entry ))
508
+ return 0 ;
509
+ }
510
+
511
+ return inet_twsk_diag_fill (tw , skb , r -> idiag_ext ,
512
+ NETLINK_CB (cb -> skb ).pid ,
513
+ cb -> nlh -> nlmsg_seq , NLM_F_MULTI , cb -> nlh );
514
+ }
515
+
453
516
static int inet_diag_fill_req (struct sk_buff * skb , struct sock * sk ,
454
517
struct request_sock * req , u32 pid , u32 seq ,
455
518
const struct nlmsghdr * unlh )
@@ -696,9 +759,10 @@ static int inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb)
696
759
}
697
760
698
761
if (r -> idiag_states & TCPF_TIME_WAIT ) {
699
- sk_for_each (sk , node ,
762
+ struct inet_timewait_sock * tw ;
763
+
764
+ inet_twsk_for_each (tw , node ,
700
765
& hashinfo -> ehash [i + hashinfo -> ehash_size ].chain ) {
701
- const struct inet_timewait_sock * tw = inet_twsk (sk );
702
766
703
767
if (num < s_num )
704
768
goto next_dying ;
@@ -708,7 +772,7 @@ static int inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb)
708
772
if (r -> id .idiag_dport != tw -> tw_dport &&
709
773
r -> id .idiag_dport )
710
774
goto next_dying ;
711
- if (inet_diag_dump_sock ( skb , sk , cb ) < 0 ) {
775
+ if (inet_twsk_diag_dump ( tw , skb , cb ) < 0 ) {
712
776
read_unlock_bh (& head -> lock );
713
777
goto done ;
714
778
}
0 commit comments