Commit Diff


commit - 13a5358a3d9a439e2f6d70f7770d4b7673bfbbc1
commit + ec5ab4fcd1bc361cacb56e999b2b8f0a00caf5a9
blob - dde1498d47b49b5d70302d0bb60a8d84e04cd53e
blob + e4f009045cd42717ea2ef265e307b9c8e58d5549
--- doc/Commands.txt
+++ doc/Commands.txt
@@ -451,17 +451,21 @@ Status and Informational Commands
 	Show statistics and other information of type <query> of a particular
 	IRC server in the network.
 	.
-	The following <query> types are supported (case-insensitive):
+	The following <query> types are supported (case-insensitive where
+	applicable):
 	.
 	 - g  Network-wide bans ("G-Lines").
 	 - k  Server-local bans ("K-Lines").
-	 - l  Link status (parent server and own link only).
+	 - L  Link status (servers and user links).
+	 - l  Link status (servers and own link).
 	 - m  Command usage count.
 	 - u  Server uptime.
 	.
 	<target> can be a server name, the nickname of a client connected to
 	a specific server, or a mask matching a server name in the network.
 	The server of the current connection is used when <target> is omitted.
+	.
+	To use "STATS L" the user must be an IRC Operator.
 
 	References:
 	 - RFC 2812, 3.4.4 "Stats message"
blob - 1c250a442bc8143dab65692fba4a4f26ce913d8c
blob + 79a157c24bf658fb91309ba65c566dff4ab9322a
--- src/ngircd/irc-info.c
+++ src/ngircd/irc-info.c
@@ -41,6 +41,7 @@
 #include "irc-macros.h"
 #include "irc-write.h"
 #include "client-cap.h"
+#include "op.h"
 
 #include "exp.h"
 #include "irc-info.h"
@@ -865,6 +866,7 @@ IRC_STATS( CLIENT *Client, REQUEST *Req )
 	unsigned int days, hrs, mins;
 	struct list_head *list;
 	struct list_elem *list_item;
+	bool more_links = false;
 
 	assert(Client != NULL);
 	assert(Req != NULL);
@@ -909,16 +911,20 @@ IRC_STATS( CLIENT *Client, REQUEST *Req )
 				list_item = Lists_GetNext(list_item);
 			}
 		break;
+	case 'L':	/* Link status (servers and user links) */
+		if (!Op_Check(from, Req))
+			return Op_NoPrivileges(from, Req);
+		more_links = true;
+
 	case 'l':	/* Link status (servers and own link) */
-	case 'L':
 		time_now = time(NULL);
 		for (con = Conn_First(); con != NONE; con = Conn_Next(con)) {
 			cl = Conn_GetClient(con);
 			if (!cl)
 				continue;
-			if ((Client_Type(cl) == CLIENT_SERVER)
-			    || (cl == Client)) {
-				/* Server link or our own connection */
+			if (Client_Type(cl) == CLIENT_SERVER ||
+			    cl == Client ||
+			    (more_links && Client_Type(cl) == CLIENT_USER)) {
 #ifdef ZLIB
 				if (Conn_Options(con) & CONN_ZIP) {
 					if (!IRC_WriteStrClient