Loading net/ipv4/inet_diag.c +111 −47 Original line number Diff line number Diff line Loading @@ -70,20 +70,22 @@ static int inet_diag_fill(struct sk_buff *skb, struct sock *sk, nlh->nlmsg_flags = nlmsg_flags; r = NLMSG_DATA(nlh); if (sk->sk_state != TCP_TIME_WAIT) { BUG_ON(sk->sk_state == TCP_TIME_WAIT); if (ext & (1 << (INET_DIAG_MEMINFO - 1))) minfo = INET_DIAG_PUT(skb, INET_DIAG_MEMINFO, sizeof(*minfo)); minfo = INET_DIAG_PUT(skb, INET_DIAG_MEMINFO, sizeof(*minfo)); if (ext & (1 << (INET_DIAG_INFO - 1))) info = INET_DIAG_PUT(skb, INET_DIAG_INFO, handler->idiag_info_size); if ((ext & (1 << (INET_DIAG_CONG - 1))) && icsk->icsk_ca_ops) { size_t len = strlen(icsk->icsk_ca_ops->name); const size_t len = strlen(icsk->icsk_ca_ops->name); strcpy(INET_DIAG_PUT(skb, INET_DIAG_CONG, len + 1), icsk->icsk_ca_ops->name); } } r->idiag_family = sk->sk_family; r->idiag_state = sk->sk_state; r->idiag_timer = 0; Loading @@ -93,37 +95,6 @@ static int inet_diag_fill(struct sk_buff *skb, struct sock *sk, r->id.idiag_cookie[0] = (u32)(unsigned long)sk; r->id.idiag_cookie[1] = (u32)(((unsigned long)sk >> 31) >> 1); if (r->idiag_state == TCP_TIME_WAIT) { const struct inet_timewait_sock *tw = inet_twsk(sk); long tmo = tw->tw_ttd - jiffies; if (tmo < 0) tmo = 0; r->id.idiag_sport = tw->tw_sport; r->id.idiag_dport = tw->tw_dport; r->id.idiag_src[0] = tw->tw_rcv_saddr; r->id.idiag_dst[0] = tw->tw_daddr; r->idiag_state = tw->tw_substate; r->idiag_timer = 3; r->idiag_expires = (tmo * 1000 + HZ - 1) / HZ; r->idiag_rqueue = 0; r->idiag_wqueue = 0; r->idiag_uid = 0; r->idiag_inode = 0; #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) if (r->idiag_family == AF_INET6) { const struct inet6_timewait_sock *tw6 = inet6_twsk(sk); ipv6_addr_copy((struct in6_addr *)r->id.idiag_src, &tw6->tw_v6_rcv_saddr); ipv6_addr_copy((struct in6_addr *)r->id.idiag_dst, &tw6->tw_v6_daddr); } #endif nlh->nlmsg_len = skb->tail - b; return skb->len; } r->id.idiag_sport = inet->sport; r->id.idiag_dport = inet->dport; r->id.idiag_src[0] = inet->rcv_saddr; Loading Loading @@ -185,6 +156,62 @@ static int inet_diag_fill(struct sk_buff *skb, struct sock *sk, return -1; } static int inet_twsk_diag_fill(struct inet_timewait_sock *tw, struct sk_buff *skb, int ext, u32 pid, u32 seq, u16 nlmsg_flags, const struct nlmsghdr *unlh) { long tmo; struct inet_diag_msg *r; const unsigned char *previous_tail = skb->tail; struct nlmsghdr *nlh = NLMSG_PUT(skb, pid, seq, unlh->nlmsg_type, sizeof(*r)); r = NLMSG_DATA(nlh); BUG_ON(tw->tw_state != TCP_TIME_WAIT); nlh->nlmsg_flags = nlmsg_flags; tmo = tw->tw_ttd - jiffies; if (tmo < 0) tmo = 0; r->idiag_family = tw->tw_family; r->idiag_state = tw->tw_state; r->idiag_timer = 0; r->idiag_retrans = 0; r->id.idiag_if = tw->tw_bound_dev_if; r->id.idiag_cookie[0] = (u32)(unsigned long)tw; r->id.idiag_cookie[1] = (u32)(((unsigned long)tw >> 31) >> 1); r->id.idiag_sport = tw->tw_sport; r->id.idiag_dport = tw->tw_dport; r->id.idiag_src[0] = tw->tw_rcv_saddr; r->id.idiag_dst[0] = tw->tw_daddr; r->idiag_state = tw->tw_substate; r->idiag_timer = 3; r->idiag_expires = (tmo * 1000 + HZ - 1) / HZ; r->idiag_rqueue = 0; r->idiag_wqueue = 0; r->idiag_uid = 0; r->idiag_inode = 0; #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) if (tw->tw_family == AF_INET6) { const struct inet6_timewait_sock *tw6 = inet6_twsk((struct sock *)tw); ipv6_addr_copy((struct in6_addr *)r->id.idiag_src, &tw6->tw_v6_rcv_saddr); ipv6_addr_copy((struct in6_addr *)r->id.idiag_dst, &tw6->tw_v6_daddr); } #endif nlh->nlmsg_len = skb->tail - previous_tail; return skb->len; nlmsg_failure: skb_trim(skb, previous_tail - skb->data); return -1; } static int inet_diag_get_exact(struct sk_buff *in_skb, const struct nlmsghdr *nlh) { Loading Loading @@ -450,6 +477,42 @@ static int inet_diag_dump_sock(struct sk_buff *skb, struct sock *sk, cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh); } static int inet_twsk_diag_dump(struct inet_timewait_sock *tw, struct sk_buff *skb, struct netlink_callback *cb) { struct inet_diag_req *r = NLMSG_DATA(cb->nlh); if (cb->nlh->nlmsg_len > 4 + NLMSG_SPACE(sizeof(*r))) { struct inet_diag_entry entry; struct rtattr *bc = (struct rtattr *)(r + 1); entry.family = tw->tw_family; #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) if (tw->tw_family == AF_INET6) { struct inet6_timewait_sock *tw6 = inet6_twsk((struct sock *)tw); entry.saddr = tw6->tw_v6_rcv_saddr.s6_addr32; entry.daddr = tw6->tw_v6_daddr.s6_addr32; } else #endif { entry.saddr = &tw->tw_rcv_saddr; entry.daddr = &tw->tw_daddr; } entry.sport = tw->tw_num; entry.dport = ntohs(tw->tw_dport); entry.userlocks = 0; if (!inet_diag_bc_run(RTA_DATA(bc), RTA_PAYLOAD(bc), &entry)) return 0; } return inet_twsk_diag_fill(tw, skb, r->idiag_ext, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh); } static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk, struct request_sock *req, u32 pid, u32 seq, const struct nlmsghdr *unlh) Loading Loading @@ -696,9 +759,10 @@ static int inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) } if (r->idiag_states & TCPF_TIME_WAIT) { sk_for_each(sk, node, struct inet_timewait_sock *tw; inet_twsk_for_each(tw, node, &hashinfo->ehash[i + hashinfo->ehash_size].chain) { const struct inet_timewait_sock *tw = inet_twsk(sk); if (num < s_num) goto next_dying; Loading @@ -708,7 +772,7 @@ static int inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) if (r->id.idiag_dport != tw->tw_dport && r->id.idiag_dport) goto next_dying; if (inet_diag_dump_sock(skb, sk, cb) < 0) { if (inet_twsk_diag_dump(tw, skb, cb) < 0) { read_unlock_bh(&head->lock); goto done; } Loading Loading
net/ipv4/inet_diag.c +111 −47 Original line number Diff line number Diff line Loading @@ -70,20 +70,22 @@ static int inet_diag_fill(struct sk_buff *skb, struct sock *sk, nlh->nlmsg_flags = nlmsg_flags; r = NLMSG_DATA(nlh); if (sk->sk_state != TCP_TIME_WAIT) { BUG_ON(sk->sk_state == TCP_TIME_WAIT); if (ext & (1 << (INET_DIAG_MEMINFO - 1))) minfo = INET_DIAG_PUT(skb, INET_DIAG_MEMINFO, sizeof(*minfo)); minfo = INET_DIAG_PUT(skb, INET_DIAG_MEMINFO, sizeof(*minfo)); if (ext & (1 << (INET_DIAG_INFO - 1))) info = INET_DIAG_PUT(skb, INET_DIAG_INFO, handler->idiag_info_size); if ((ext & (1 << (INET_DIAG_CONG - 1))) && icsk->icsk_ca_ops) { size_t len = strlen(icsk->icsk_ca_ops->name); const size_t len = strlen(icsk->icsk_ca_ops->name); strcpy(INET_DIAG_PUT(skb, INET_DIAG_CONG, len + 1), icsk->icsk_ca_ops->name); } } r->idiag_family = sk->sk_family; r->idiag_state = sk->sk_state; r->idiag_timer = 0; Loading @@ -93,37 +95,6 @@ static int inet_diag_fill(struct sk_buff *skb, struct sock *sk, r->id.idiag_cookie[0] = (u32)(unsigned long)sk; r->id.idiag_cookie[1] = (u32)(((unsigned long)sk >> 31) >> 1); if (r->idiag_state == TCP_TIME_WAIT) { const struct inet_timewait_sock *tw = inet_twsk(sk); long tmo = tw->tw_ttd - jiffies; if (tmo < 0) tmo = 0; r->id.idiag_sport = tw->tw_sport; r->id.idiag_dport = tw->tw_dport; r->id.idiag_src[0] = tw->tw_rcv_saddr; r->id.idiag_dst[0] = tw->tw_daddr; r->idiag_state = tw->tw_substate; r->idiag_timer = 3; r->idiag_expires = (tmo * 1000 + HZ - 1) / HZ; r->idiag_rqueue = 0; r->idiag_wqueue = 0; r->idiag_uid = 0; r->idiag_inode = 0; #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) if (r->idiag_family == AF_INET6) { const struct inet6_timewait_sock *tw6 = inet6_twsk(sk); ipv6_addr_copy((struct in6_addr *)r->id.idiag_src, &tw6->tw_v6_rcv_saddr); ipv6_addr_copy((struct in6_addr *)r->id.idiag_dst, &tw6->tw_v6_daddr); } #endif nlh->nlmsg_len = skb->tail - b; return skb->len; } r->id.idiag_sport = inet->sport; r->id.idiag_dport = inet->dport; r->id.idiag_src[0] = inet->rcv_saddr; Loading Loading @@ -185,6 +156,62 @@ static int inet_diag_fill(struct sk_buff *skb, struct sock *sk, return -1; } static int inet_twsk_diag_fill(struct inet_timewait_sock *tw, struct sk_buff *skb, int ext, u32 pid, u32 seq, u16 nlmsg_flags, const struct nlmsghdr *unlh) { long tmo; struct inet_diag_msg *r; const unsigned char *previous_tail = skb->tail; struct nlmsghdr *nlh = NLMSG_PUT(skb, pid, seq, unlh->nlmsg_type, sizeof(*r)); r = NLMSG_DATA(nlh); BUG_ON(tw->tw_state != TCP_TIME_WAIT); nlh->nlmsg_flags = nlmsg_flags; tmo = tw->tw_ttd - jiffies; if (tmo < 0) tmo = 0; r->idiag_family = tw->tw_family; r->idiag_state = tw->tw_state; r->idiag_timer = 0; r->idiag_retrans = 0; r->id.idiag_if = tw->tw_bound_dev_if; r->id.idiag_cookie[0] = (u32)(unsigned long)tw; r->id.idiag_cookie[1] = (u32)(((unsigned long)tw >> 31) >> 1); r->id.idiag_sport = tw->tw_sport; r->id.idiag_dport = tw->tw_dport; r->id.idiag_src[0] = tw->tw_rcv_saddr; r->id.idiag_dst[0] = tw->tw_daddr; r->idiag_state = tw->tw_substate; r->idiag_timer = 3; r->idiag_expires = (tmo * 1000 + HZ - 1) / HZ; r->idiag_rqueue = 0; r->idiag_wqueue = 0; r->idiag_uid = 0; r->idiag_inode = 0; #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) if (tw->tw_family == AF_INET6) { const struct inet6_timewait_sock *tw6 = inet6_twsk((struct sock *)tw); ipv6_addr_copy((struct in6_addr *)r->id.idiag_src, &tw6->tw_v6_rcv_saddr); ipv6_addr_copy((struct in6_addr *)r->id.idiag_dst, &tw6->tw_v6_daddr); } #endif nlh->nlmsg_len = skb->tail - previous_tail; return skb->len; nlmsg_failure: skb_trim(skb, previous_tail - skb->data); return -1; } static int inet_diag_get_exact(struct sk_buff *in_skb, const struct nlmsghdr *nlh) { Loading Loading @@ -450,6 +477,42 @@ static int inet_diag_dump_sock(struct sk_buff *skb, struct sock *sk, cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh); } static int inet_twsk_diag_dump(struct inet_timewait_sock *tw, struct sk_buff *skb, struct netlink_callback *cb) { struct inet_diag_req *r = NLMSG_DATA(cb->nlh); if (cb->nlh->nlmsg_len > 4 + NLMSG_SPACE(sizeof(*r))) { struct inet_diag_entry entry; struct rtattr *bc = (struct rtattr *)(r + 1); entry.family = tw->tw_family; #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) if (tw->tw_family == AF_INET6) { struct inet6_timewait_sock *tw6 = inet6_twsk((struct sock *)tw); entry.saddr = tw6->tw_v6_rcv_saddr.s6_addr32; entry.daddr = tw6->tw_v6_daddr.s6_addr32; } else #endif { entry.saddr = &tw->tw_rcv_saddr; entry.daddr = &tw->tw_daddr; } entry.sport = tw->tw_num; entry.dport = ntohs(tw->tw_dport); entry.userlocks = 0; if (!inet_diag_bc_run(RTA_DATA(bc), RTA_PAYLOAD(bc), &entry)) return 0; } return inet_twsk_diag_fill(tw, skb, r->idiag_ext, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh); } static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk, struct request_sock *req, u32 pid, u32 seq, const struct nlmsghdr *unlh) Loading Loading @@ -696,9 +759,10 @@ static int inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) } if (r->idiag_states & TCPF_TIME_WAIT) { sk_for_each(sk, node, struct inet_timewait_sock *tw; inet_twsk_for_each(tw, node, &hashinfo->ehash[i + hashinfo->ehash_size].chain) { const struct inet_timewait_sock *tw = inet_twsk(sk); if (num < s_num) goto next_dying; Loading @@ -708,7 +772,7 @@ static int inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) if (r->id.idiag_dport != tw->tw_dport && r->id.idiag_dport) goto next_dying; if (inet_diag_dump_sock(skb, sk, cb) < 0) { if (inet_twsk_diag_dump(tw, skb, cb) < 0) { read_unlock_bh(&head->lock); goto done; } Loading