@@ -73,9 +73,11 @@ extern const char *backend_stat;
7373
7474static uint32_t connid = 0 ;
7575static struct tree ctl_conns ;
76+ static struct tree ctl_count ;
7677static struct stat_digest digest ;
7778
78- #define CONTROL_FD_RESERVE 5
79+ #define CONTROL_FD_RESERVE 5
80+ #define CONTROL_MAXCONN_PER_CLIENT 5
7981
8082static void
8183control_imsg (struct mproc * p , struct imsg * imsg )
@@ -282,6 +284,7 @@ control(void)
282284 signal (SIGHUP , SIG_IGN );
283285
284286 tree_init (& ctl_conns );
287+ tree_init (& ctl_count );
285288
286289 memset (& digest , 0 , sizeof digest );
287290 digest .startup = time (NULL );
@@ -330,6 +333,9 @@ control_accept(int listenfd, short event, void *arg)
330333 socklen_t len ;
331334 struct sockaddr_un sun ;
332335 struct ctl_conn * c ;
336+ size_t * count ;
337+ uid_t euid ;
338+ gid_t egid ;
333339
334340 if (getdtablesize () - getdtablecount () < CONTROL_FD_RESERVE )
335341 goto pause ;
@@ -346,16 +352,30 @@ control_accept(int listenfd, short event, void *arg)
346352
347353 session_socket_blockmode (connfd , BM_NONBLOCK );
348354
349- c = xcalloc (1 , sizeof (* c ), "control_accept" );
350- if (getpeereid (connfd , & c -> euid , & c -> egid ) == -1 )
355+ if (getpeereid (connfd , & euid , & egid ) == -1 )
351356 fatal ("getpeereid" );
357+
358+ count = tree_get (& ctl_count , euid );
359+ if (count == NULL )
360+ count = xcalloc (1 , sizeof * count , "control_accept" );
361+
362+ if (* count == CONTROL_MAXCONN_PER_CLIENT ) {
363+ close (connfd );
364+ return ;
365+ }
366+ (* count )++ ;
367+
368+ c = xcalloc (1 , sizeof (* c ), "control_accept" );
369+ c -> euid = euid ;
370+ c -> egid = egid ;
352371 c -> id = ++ connid ;
353372 c -> mproc .proc = PROC_CLIENT ;
354373 c -> mproc .handler = control_dispatch_ext ;
355374 c -> mproc .data = c ;
356375 mproc_init (& c -> mproc , connfd );
357376 mproc_enable (& c -> mproc );
358377 tree_xset (& ctl_conns , c -> id , c );
378+ tree_set (& ctl_count , c -> euid , count );
359379
360380 stat_backend -> increment ("control.session" , 1 );
361381 return ;
@@ -368,6 +388,16 @@ control_accept(int listenfd, short event, void *arg)
368388static void
369389control_close (struct ctl_conn * c )
370390{
391+ size_t * count ;
392+
393+ count = tree_get (& ctl_count , c -> euid );
394+ (* count )-- ;
395+ if (* count == 0 ) {
396+ tree_xpop (& ctl_count , c -> euid );
397+ free (count );
398+ }
399+ else
400+ tree_set (& ctl_count , c -> euid , count );
371401 tree_xpop (& ctl_conns , c -> id );
372402 mproc_clear (& c -> mproc );
373403 free (c );
0 commit comments