aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/sunrpc/svcsock.c57
1 files changed, 29 insertions, 28 deletions
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index 962dbf43a728..6e9dc8f96495 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -1105,17 +1105,30 @@ static struct svc_xprt *svc_tcp_accept(struct svc_xprt *xprt)
1105 1105
1106 svc_sock_received(newsvsk); 1106 svc_sock_received(newsvsk);
1107 1107
1108 /* make sure that we don't have too many active connections. 1108 if (serv->sv_stats)
1109 * If we have, something must be dropped. 1109 serv->sv_stats->nettcpconn++;
1110 * 1110
1111 * There's no point in trying to do random drop here for 1111 return &newsvsk->sk_xprt;
1112 * DoS prevention. The NFS clients does 1 reconnect in 15 1112
1113 * seconds. An attacker can easily beat that. 1113failed:
1114 * 1114 sock_release(newsock);
1115 * The only somewhat efficient mechanism would be if drop 1115 return NULL;
1116 * old connections from the same IP first. But right now 1116}
1117 * we don't even record the client IP in svc_sock. 1117
1118 */ 1118/*
1119 * Make sure that we don't have too many active connections. If we
1120 * have, something must be dropped.
1121 *
1122 * There's no point in trying to do random drop here for DoS
1123 * prevention. The NFS clients does 1 reconnect in 15 seconds. An
1124 * attacker can easily beat that.
1125 *
1126 * The only somewhat efficient mechanism would be if drop old
1127 * connections from the same IP first. But right now we don't even
1128 * record the client IP in svc_sock.
1129 */
1130static void svc_check_conn_limits(struct svc_serv *serv)
1131{
1119 if (serv->sv_tmpcnt > (serv->sv_nrthreads+3)*20) { 1132 if (serv->sv_tmpcnt > (serv->sv_nrthreads+3)*20) {
1120 struct svc_sock *svsk = NULL; 1133 struct svc_sock *svsk = NULL;
1121 spin_lock_bh(&serv->sv_lock); 1134 spin_lock_bh(&serv->sv_lock);
@@ -1123,13 +1136,9 @@ static struct svc_xprt *svc_tcp_accept(struct svc_xprt *xprt)
1123 if (net_ratelimit()) { 1136 if (net_ratelimit()) {
1124 /* Try to help the admin */ 1137 /* Try to help the admin */
1125 printk(KERN_NOTICE "%s: too many open TCP " 1138 printk(KERN_NOTICE "%s: too many open TCP "
1126 "sockets, consider increasing the " 1139 "sockets, consider increasing the "
1127 "number of nfsd threads\n", 1140 "number of nfsd threads\n",
1128 serv->sv_name); 1141 serv->sv_name);
1129 printk(KERN_NOTICE
1130 "%s: last TCP connect from %s\n",
1131 serv->sv_name, __svc_print_addr(sin,
1132 buf, sizeof(buf)));
1133 } 1142 }
1134 /* 1143 /*
1135 * Always select the oldest socket. It's not fair, 1144 * Always select the oldest socket. It's not fair,
@@ -1147,17 +1156,7 @@ static struct svc_xprt *svc_tcp_accept(struct svc_xprt *xprt)
1147 svc_sock_enqueue(svsk); 1156 svc_sock_enqueue(svsk);
1148 svc_sock_put(svsk); 1157 svc_sock_put(svsk);
1149 } 1158 }
1150
1151 } 1159 }
1152
1153 if (serv->sv_stats)
1154 serv->sv_stats->nettcpconn++;
1155
1156 return &newsvsk->sk_xprt;
1157
1158failed:
1159 sock_release(newsock);
1160 return NULL;
1161} 1160}
1162 1161
1163/* 1162/*
@@ -1574,6 +1573,8 @@ svc_recv(struct svc_rqst *rqstp, long timeout)
1574 } else if (test_bit(SK_LISTENER, &svsk->sk_flags)) { 1573 } else if (test_bit(SK_LISTENER, &svsk->sk_flags)) {
1575 struct svc_xprt *newxpt; 1574 struct svc_xprt *newxpt;
1576 newxpt = svsk->sk_xprt.xpt_ops->xpo_accept(&svsk->sk_xprt); 1575 newxpt = svsk->sk_xprt.xpt_ops->xpo_accept(&svsk->sk_xprt);
1576 if (newxpt)
1577 svc_check_conn_limits(svsk->sk_server);
1577 svc_sock_received(svsk); 1578 svc_sock_received(svsk);
1578 } else { 1579 } else {
1579 dprintk("svc: server %p, pool %u, socket %p, inuse=%d\n", 1580 dprintk("svc: server %p, pool %u, socket %p, inuse=%d\n",