diff options
Diffstat (limited to 'net/netlink')
| -rw-r--r-- | net/netlink/af_netlink.c | 24 | ||||
| -rw-r--r-- | net/netlink/genetlink.c | 4 |
2 files changed, 19 insertions, 9 deletions
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 4c5972ba8c78..acbbae1e89b5 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
| @@ -1093,6 +1093,7 @@ static inline int do_one_set_err(struct sock *sk, | |||
| 1093 | struct netlink_set_err_data *p) | 1093 | struct netlink_set_err_data *p) |
| 1094 | { | 1094 | { |
| 1095 | struct netlink_sock *nlk = nlk_sk(sk); | 1095 | struct netlink_sock *nlk = nlk_sk(sk); |
| 1096 | int ret = 0; | ||
| 1096 | 1097 | ||
| 1097 | if (sk == p->exclude_sk) | 1098 | if (sk == p->exclude_sk) |
| 1098 | goto out; | 1099 | goto out; |
| @@ -1104,10 +1105,15 @@ static inline int do_one_set_err(struct sock *sk, | |||
| 1104 | !test_bit(p->group - 1, nlk->groups)) | 1105 | !test_bit(p->group - 1, nlk->groups)) |
| 1105 | goto out; | 1106 | goto out; |
| 1106 | 1107 | ||
| 1108 | if (p->code == ENOBUFS && nlk->flags & NETLINK_RECV_NO_ENOBUFS) { | ||
| 1109 | ret = 1; | ||
| 1110 | goto out; | ||
| 1111 | } | ||
| 1112 | |||
| 1107 | sk->sk_err = p->code; | 1113 | sk->sk_err = p->code; |
| 1108 | sk->sk_error_report(sk); | 1114 | sk->sk_error_report(sk); |
| 1109 | out: | 1115 | out: |
| 1110 | return 0; | 1116 | return ret; |
| 1111 | } | 1117 | } |
| 1112 | 1118 | ||
| 1113 | /** | 1119 | /** |
| @@ -1116,12 +1122,16 @@ out: | |||
| 1116 | * @pid: the PID of a process that we want to skip (if any) | 1122 | * @pid: the PID of a process that we want to skip (if any) |
| 1117 | * @groups: the broadcast group that will notice the error | 1123 | * @groups: the broadcast group that will notice the error |
| 1118 | * @code: error code, must be negative (as usual in kernelspace) | 1124 | * @code: error code, must be negative (as usual in kernelspace) |
| 1125 | * | ||
| 1126 | * This function returns the number of broadcast listeners that have set the | ||
| 1127 | * NETLINK_RECV_NO_ENOBUFS socket option. | ||
| 1119 | */ | 1128 | */ |
| 1120 | void netlink_set_err(struct sock *ssk, u32 pid, u32 group, int code) | 1129 | int netlink_set_err(struct sock *ssk, u32 pid, u32 group, int code) |
| 1121 | { | 1130 | { |
| 1122 | struct netlink_set_err_data info; | 1131 | struct netlink_set_err_data info; |
| 1123 | struct hlist_node *node; | 1132 | struct hlist_node *node; |
| 1124 | struct sock *sk; | 1133 | struct sock *sk; |
| 1134 | int ret = 0; | ||
| 1125 | 1135 | ||
| 1126 | info.exclude_sk = ssk; | 1136 | info.exclude_sk = ssk; |
| 1127 | info.pid = pid; | 1137 | info.pid = pid; |
| @@ -1132,9 +1142,10 @@ void netlink_set_err(struct sock *ssk, u32 pid, u32 group, int code) | |||
| 1132 | read_lock(&nl_table_lock); | 1142 | read_lock(&nl_table_lock); |
| 1133 | 1143 | ||
| 1134 | sk_for_each_bound(sk, node, &nl_table[ssk->sk_protocol].mc_list) | 1144 | sk_for_each_bound(sk, node, &nl_table[ssk->sk_protocol].mc_list) |
| 1135 | do_one_set_err(sk, &info); | 1145 | ret += do_one_set_err(sk, &info); |
| 1136 | 1146 | ||
| 1137 | read_unlock(&nl_table_lock); | 1147 | read_unlock(&nl_table_lock); |
| 1148 | return ret; | ||
| 1138 | } | 1149 | } |
| 1139 | EXPORT_SYMBOL(netlink_set_err); | 1150 | EXPORT_SYMBOL(netlink_set_err); |
| 1140 | 1151 | ||
| @@ -1978,12 +1989,12 @@ static int netlink_seq_show(struct seq_file *seq, void *v) | |||
| 1978 | if (v == SEQ_START_TOKEN) | 1989 | if (v == SEQ_START_TOKEN) |
| 1979 | seq_puts(seq, | 1990 | seq_puts(seq, |
| 1980 | "sk Eth Pid Groups " | 1991 | "sk Eth Pid Groups " |
| 1981 | "Rmem Wmem Dump Locks Drops\n"); | 1992 | "Rmem Wmem Dump Locks Drops Inode\n"); |
| 1982 | else { | 1993 | else { |
| 1983 | struct sock *s = v; | 1994 | struct sock *s = v; |
| 1984 | struct netlink_sock *nlk = nlk_sk(s); | 1995 | struct netlink_sock *nlk = nlk_sk(s); |
| 1985 | 1996 | ||
| 1986 | seq_printf(seq, "%p %-3d %-6d %08x %-8d %-8d %p %-8d %-8d\n", | 1997 | seq_printf(seq, "%p %-3d %-6d %08x %-8d %-8d %p %-8d %-8d %-8lu\n", |
| 1987 | s, | 1998 | s, |
| 1988 | s->sk_protocol, | 1999 | s->sk_protocol, |
| 1989 | nlk->pid, | 2000 | nlk->pid, |
| @@ -1992,7 +2003,8 @@ static int netlink_seq_show(struct seq_file *seq, void *v) | |||
| 1992 | sk_wmem_alloc_get(s), | 2003 | sk_wmem_alloc_get(s), |
| 1993 | nlk->cb, | 2004 | nlk->cb, |
| 1994 | atomic_read(&s->sk_refcnt), | 2005 | atomic_read(&s->sk_refcnt), |
| 1995 | atomic_read(&s->sk_drops) | 2006 | atomic_read(&s->sk_drops), |
| 2007 | sock_i_ino(s) | ||
| 1996 | ); | 2008 | ); |
| 1997 | 2009 | ||
| 1998 | } | 2010 | } |
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index d07ecda0a92d..a4b6e148c5de 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c | |||
| @@ -681,9 +681,7 @@ static int ctrl_dumpfamily(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 681 | int chains_to_skip = cb->args[0]; | 681 | int chains_to_skip = cb->args[0]; |
| 682 | int fams_to_skip = cb->args[1]; | 682 | int fams_to_skip = cb->args[1]; |
| 683 | 683 | ||
| 684 | for (i = 0; i < GENL_FAM_TAB_SIZE; i++) { | 684 | for (i = chains_to_skip; i < GENL_FAM_TAB_SIZE; i++) { |
| 685 | if (i < chains_to_skip) | ||
| 686 | continue; | ||
| 687 | n = 0; | 685 | n = 0; |
| 688 | list_for_each_entry(rt, genl_family_chain(i), family_list) { | 686 | list_for_each_entry(rt, genl_family_chain(i), family_list) { |
| 689 | if (!rt->netnsok && !net_eq(net, &init_net)) | 687 | if (!rt->netnsok && !net_eq(net, &init_net)) |
