]> jfr.im git - irc/quakenet/snircd-patchqueue.git/blame - accountflags.patch
rename patch files
[irc/quakenet/snircd-patchqueue.git] / accountflags.patch
CommitLineData
edb26b39 1# HG changeset patch
6fe1b135 2# Parent 5440fc22cc1d524bb5bca9cfc1a8a7b6bf9dd0f3
edb26b39 3
6fe1b135
P
4diff -r 5440fc22cc1d include/client.h
5--- a/include/client.h Sat Jul 20 14:48:02 2013 +0100
6+++ b/include/client.h Sat Jul 20 14:48:06 2013 +0100
edb26b39
P
7@@ -92,6 +92,9 @@
8 /** String containing valid user modes, in no particular order. */
6fe1b135 9 #define infousermodes "diOoswkgxRXInP"
edb26b39
P
10
11+/** Character to indicate no oper name available */
12+#define NOOPERNAMECHARACTER '-'
13+
14 /** Operator privileges. */
15 enum Priv
16 {
17@@ -173,6 +176,7 @@
18 FLAG_NOCHAN, /**< user's channels are hidden */
19 FLAG_NOIDLE, /**< user's idletime is hidden */
20 FLAG_XTRAOP, /**< oper has special powers */
21+ FLAG_OPERNAME, /**< Server sends oper name in mode string */
22
23 FLAG_LAST_FLAG, /**< number of flags */
24 FLAG_LOCAL_UMODES = FLAG_LOCOP, /**< First local mode flag */
6fe1b135 25@@ -603,6 +607,8 @@
edb26b39
P
26 /** Return non-zero if the client should receive notices when someone
27 * does a whois on it. */
28 #define IsParanoid(x) HasFlag(x, FLAG_PARANOID)
29+/** Return non-zero if the server should send opername information */
30+#define IsSendOperName(x) HasFlag(x, FLAG_OPERNAME)
31
32 /** Return non-zero if the client has operator or server privileges. */
33 #define IsPrivileged(x) (IsAnOper(x) || IsServer(x))
6fe1b135 34@@ -644,6 +650,8 @@
edb26b39
P
35 #define SetHub(x) SetFlag(x, FLAG_HUB)
36 /** Mark a client as being an IPv6-grokking server. */
37 #define SetIPv6(x) SetFlag(x, FLAG_IPV6)
38+/** Mark a server as sending opername */
39+#define SetOperName(x) SetFlag(x, FLAG_OPERNAME)
40 /** Mark a client as being a services server. */
41 #define SetService(x) SetFlag(x, FLAG_SERVICE)
42 /** Mark a client as having an account stamp. */
6fe1b135
P
43diff -r 5440fc22cc1d include/numeric.h
44--- a/include/numeric.h Sat Jul 20 14:48:02 2013 +0100
45+++ b/include/numeric.h Sat Jul 20 14:48:06 2013 +0100
edb26b39
P
46@@ -259,6 +259,7 @@
47 #define RPL_USERIP 340 /* Undernet extension */
48 #define RPL_INVITING 341
49 /* RPL_SUMMONING 342 removed from RFC1459 */
50+#define RPL_WHOISOPERNAME 343 /* QuakeNet Extension */
51
52 #define RPL_ISSUEDINVITE 345 /* Undernet extension */
53 #define RPL_INVITELIST 346 /* IRCnet, Undernet extension */
6fe1b135
P
54diff -r 5440fc22cc1d include/s_user.h
55--- a/include/s_user.h Sat Jul 20 14:48:02 2013 +0100
56+++ b/include/s_user.h Sat Jul 20 14:48:06 2013 +0100
edb26b39
P
57@@ -100,9 +100,9 @@
58 int MustBeOper, const char *pattern,
59 int server, int parc, char *parv[]);
60 extern struct Client* next_client(struct Client* next, const char* ch);
61-extern char *umode_str(struct Client *cptr);
62+extern char *umode_str(struct Client *cptr, int type);
63 extern void send_umode(struct Client *cptr, struct Client *sptr,
64- struct Flags *old, int sendset);
65+ struct Flags *old, int sendset, int opernames);
66 extern void set_snomask(struct Client *, unsigned int, int);
67 extern int is_snomask(char *);
68 extern int check_target_limit(struct Client *sptr, void *target, const char *name,
6fe1b135
P
69diff -r 5440fc22cc1d include/send.h
70--- a/include/send.h Sat Jul 20 14:48:02 2013 +0100
71+++ b/include/send.h Sat Jul 20 14:48:06 2013 +0100
edb26b39
P
72@@ -50,6 +50,13 @@
73 int require, int forbid,
74 const char *pattern, ...);
75
76+/* Send command to servers by flag arrays except one */
77+void sendcmdto_flagarray_serv_butone(struct Client *from, const char *cmd,
78+ const char *tok, struct Client *one,
79+ int *require, unsigned int requiresize,
80+ int *forbid, unsigned int forbidsize,
81+ const char *pattern, ...);
82+
83 /* Send command to all servers except one */
84 extern void sendcmdto_serv_butone(struct Client *from, const char *cmd,
85 const char *tok, struct Client *one,
6fe1b135
P
86diff -r 5440fc22cc1d include/struct.h
87--- a/include/struct.h Sat Jul 20 14:48:02 2013 +0100
88+++ b/include/struct.h Sat Jul 20 14:48:06 2013 +0100
edb26b39
P
89@@ -32,6 +32,13 @@
90 #include "ircd_defs.h" /* sizes */
91 #endif
92
93+#ifdef HAVE_STDINT_H
94+#ifndef INCLUDED_stdint_h
95+#include <stdint.h>
96+#define INCLUDED_stdint_h
97+#endif
98+#endif
99+
100 struct DLink;
101 struct Client;
102 struct User;
103@@ -85,6 +92,9 @@
104 char realhost[HOSTLEN + 1]; /**< actual hostname */
105 char account[ACCOUNTLEN + 1]; /**< IRC account name */
106 time_t acc_create; /**< IRC account timestamp */
107+ unsigned long acc_id; /**< IRC account unique id */
108+ uint64_t acc_flags; /**< IRC account flags */
109+ char* opername; /**< IRC Oper Account name */
110 };
111
112 #endif /* INCLUDED_struct_h */
6fe1b135
P
113diff -r 5440fc22cc1d ircd/ircd_parser.y
114--- a/ircd/ircd_parser.y Sat Jul 20 14:48:02 2013 +0100
115+++ b/ircd/ircd_parser.y Sat Jul 20 14:48:06 2013 +0100
edb26b39
P
116@@ -580,6 +580,10 @@
117
118 if (name == NULL)
119 parse_error("Missing name in operator block");
120+ else if (strlen(name) > ACCOUNTLEN)
121+ parse_error("Operator name in operator block is too long");
122+ else if ((name[0] == NOOPERNAMECHARACTER) && (name[1] == '\0'))
123+ parse_error("Operator name can not be '%c'",NOOPERNAMECHARACTER);
124 else if (pass == NULL)
125 parse_error("Missing password in operator block");
126 /* Do not check password length because it may be crypted. */
6fe1b135
P
127diff -r 5440fc22cc1d ircd/ircd_reslib.c
128--- a/ircd/ircd_reslib.c Sat Jul 20 14:48:02 2013 +0100
129+++ b/ircd/ircd_reslib.c Sat Jul 20 14:48:06 2013 +0100
edb26b39
P
130@@ -80,6 +80,8 @@
131 * - Dianora
132 */
133
134+#include "config.h"
135+
136 #include "ircd.h"
137 #include "res.h"
138 #include "ircd_reslib.h"
6fe1b135
P
139diff -r 5440fc22cc1d ircd/m_account.c
140--- a/ircd/m_account.c Sat Jul 20 14:48:02 2013 +0100
141+++ b/ircd/m_account.c Sat Jul 20 14:48:06 2013 +0100
edb26b39
P
142@@ -90,6 +90,7 @@
143 #include "s_debug.h"
144 #include "s_user.h"
145 #include "send.h"
146+#include "s_misc.h"
147
148 /* #include <assert.h> -- Now using assert in ircd_log.h */
149 #include <stdlib.h>
150@@ -101,13 +102,19 @@
151 * parv[0] = sender prefix
152 * parv[1] = numeric of client to act on
153 * parv[2] = account name (12 characters or less)
154+ * parv[3] = account timestamp
155+ * parv[4] = account id
156+ * parv[5] = account flags (optional)
157 */
158 int ms_account(struct Client* cptr, struct Client* sptr, int parc,
159 char* parv[])
160 {
161 struct Client *acptr;
162+ time_t acc_create;
163+ unsigned long acc_id;
164+ unsigned long long acc_flags;
165
166- if (parc < 3)
167+ if (parc < 5)
168 return need_more_params(sptr, "ACCOUNT");
169
170 if (!IsServer(sptr))
171@@ -117,10 +124,35 @@
172 if (!(acptr = findNUser(parv[1])))
173 return 0; /* Ignore ACCOUNT for a user that QUIT; probably crossed */
174
175- if (IsAccount(acptr))
176- return protocol_violation(cptr, "ACCOUNT for already registered user %s "
177- "(%s -> %s)", cli_name(acptr),
178- cli_user(acptr)->account, parv[2]);
179+ acc_create = atoi(parv[3]);
180+ acc_id = strtoul(parv[4], NULL, 10);
181+ if (parc > 5) {
182+ acc_flags = strtoull(parv[5], NULL, 10);
183+ } else {
184+ acc_flags = 0;
185+ }
186+
187+ /* this section is used for updating acc_flags when
188+ * all other elements match
189+ */
190+ if (IsAccount(acptr)) {
191+ if (strcmp(cli_user(acptr)->account, parv[2]) ||
192+ (cli_user(acptr)->acc_create != acc_create) ||
193+ (cli_user(acptr)->acc_id != acc_id))
194+ return protocol_violation(cptr, "ACCOUNT for already registered user %s "
195+ "(%s -> %s)", cli_name(acptr),
196+ cli_user(acptr)->account, parv[2]);
197+
198+ cli_user(acptr)->acc_flags = acc_flags;
199+
200+ sendcmdto_serv_butone(sptr, CMD_ACCOUNT, cptr, "%C %s %Tu %lu %"PRIu64,
201+ acptr, cli_user(acptr)->account,
202+ cli_user(acptr)->acc_create,
203+ cli_user(acptr)->acc_id,
204+ cli_user(acptr)->acc_flags);
205+
206+ return 0;
207+ }
208
209 assert(0 == cli_user(acptr)->account[0]);
210
211@@ -129,20 +161,19 @@
212 "Received account (%s) longer than %d for %s; "
213 "ignoring.",
214 parv[2], ACCOUNTLEN, cli_name(acptr));
215-
216- if (parc > 3) {
217- cli_user(acptr)->acc_create = atoi(parv[3]);
218- Debug((DEBUG_DEBUG, "Received timestamped account: account \"%s\", "
219- "timestamp %Tu", parv[2], cli_user(acptr)->acc_create));
220- }
221+
222+ cli_user(acptr)->acc_create = acc_create;
223+ cli_user(acptr)->acc_id = acc_id;
224+ cli_user(acptr)->acc_flags = acc_flags;
225
226 ircd_strncpy(cli_user(acptr)->account, parv[2], ACCOUNTLEN);
227 hide_hostmask(acptr, FLAG_ACCOUNT);
228
229- sendcmdto_serv_butone(sptr, CMD_ACCOUNT, cptr,
230- cli_user(acptr)->acc_create ? "%C %s %Tu" : "%C %s",
231- acptr, cli_user(acptr)->account,
232- cli_user(acptr)->acc_create);
233+ sendcmdto_serv_butone(sptr, CMD_ACCOUNT, cptr, "%C %s %Tu %lu %"PRIu64,
234+ acptr, cli_user(acptr)->account,
235+ cli_user(acptr)->acc_create,
236+ cli_user(acptr)->acc_id,
237+ cli_user(acptr)->acc_flags);
238
239 return 0;
240 }
6fe1b135
P
241diff -r 5440fc22cc1d ircd/m_check.c
242--- a/ircd/m_check.c Sat Jul 20 14:48:02 2013 +0100
243+++ b/ircd/m_check.c Sat Jul 20 14:48:06 2013 +0100
edb26b39
P
244@@ -413,6 +413,7 @@
245 struct Membership *lp;
246 struct irc_sockaddr sin;
247 char outbuf[BUFSIZE];
248+ char *umodes;
249 time_t nowr;
250
251 /* Header */
6fe1b135
P
252diff -r 5440fc22cc1d ircd/m_oper.c
253--- a/ircd/m_oper.c Sat Jul 20 14:48:02 2013 +0100
254+++ b/ircd/m_oper.c Sat Jul 20 14:48:06 2013 +0100
edb26b39
P
255@@ -150,8 +150,8 @@
256 if (!aconf || IsIllegal(aconf))
257 {
258 send_reply(sptr, ERR_NOOPERHOST);
259- sendto_opmask_butone(0, SNO_OLDREALOP, "Failed OPER attempt by %s (%s@%s)",
260- parv[0], cli_user(sptr)->realusername, cli_sockhost(sptr));
261+ sendto_opmask_butone(0, SNO_OLDREALOP, "Failed OPER attempt by %s (%s@%s) as %s",
262+ parv[0], cli_user(sptr)->realusername, cli_sockhost(sptr), name);
263 return 0;
264 }
265 assert(0 != (aconf->status & CONF_OPERATOR));
266@@ -163,8 +163,8 @@
267 if (ACR_OK != attach_conf(sptr, aconf)) {
268 send_reply(sptr, ERR_NOOPERHOST);
269 sendto_opmask_butone(0, SNO_OLDREALOP, "Failed OPER attempt by %s "
270- "(%s@%s)", parv[0], cli_user(sptr)->realusername,
271- cli_sockhost(sptr));
272+ "(%s@%s) as %s", parv[0], cli_user(sptr)->realusername,
273+ cli_sockhost(sptr), aconf->name);
274 return 0;
275 }
276 SetLocOp(sptr);
277@@ -177,6 +177,12 @@
278 }
279 cli_handler(cptr) = OPER_HANDLER;
280
281+ if (cli_user(sptr)->opername)
282+ MyFree(cli_user(sptr)->opername);
283+ cli_user(sptr)->opername = (char*) MyMalloc(strlen(name) + 1);
284+ assert(0 != cli_user(sptr)->opername);
285+ ircd_strncpy(cli_user(sptr)->opername,aconf->name,ACCOUNTLEN);
286+
287 SetFlag(sptr, FLAG_WALLOP);
288 SetFlag(sptr, FLAG_SERVNOTICE);
289 SetFlag(sptr, FLAG_DEBUG);
290@@ -186,17 +192,17 @@
291 send_umode_out(cptr, sptr, &old_mode, HasPriv(sptr, PRIV_PROPAGATE));
292 send_reply(sptr, RPL_YOUREOPER);
293
294- sendto_opmask_butone(0, SNO_OLDSNO, "%s (%s@%s) is now operator (%c)",
295+ sendto_opmask_butone(0, SNO_OLDSNO, "%s (%s@%s) is now operator (%c) as %s",
296 parv[0], cli_user(sptr)->realusername, cli_sockhost(sptr),
297- IsOper(sptr) ? 'O' : 'o');
298+ IsOper(sptr) ? 'O' : 'o', cli_user(sptr)->opername);
299
300 log_write(LS_OPER, L_INFO, 0, "OPER (%s) by (%#R)", name, sptr);
301 }
302 else
303 {
304 send_reply(sptr, ERR_PASSWDMISMATCH);
305- sendto_opmask_butone(0, SNO_OLDREALOP, "Failed OPER attempt by %s (%s@%s)",
306- parv[0], cli_user(sptr)->realusername, cli_sockhost(sptr));
307+ sendto_opmask_butone(0, SNO_OLDREALOP, "Failed OPER attempt by %s (%s@%s) as %s",
308+ parv[0], cli_user(sptr)->realusername, cli_sockhost(sptr), aconf->name);
309 }
310 return 0;
311 }
312@@ -215,7 +221,8 @@
313 {
314 ++UserStats.opers;
315 SetFlag(sptr, FLAG_OPER);
316- sendcmdto_serv_butone(sptr, CMD_MODE, cptr, "%s :+o", parv[0]);
317+ sendcmdto_flag_serv_butone(sptr, CMD_MODE, cptr, FLAG_LAST_FLAG, FLAG_OPERNAME, "%s :+o", parv[0]);
318+ sendcmdto_flag_serv_butone(sptr, CMD_MODE, cptr, FLAG_OPERNAME, FLAG_LAST_FLAG, "%s :+o %c", parv[0], NOOPERNAMECHARACTER);
319 }
320 return 0;
321 }
6fe1b135
P
322diff -r 5440fc22cc1d ircd/m_server.c
323--- a/ircd/m_server.c Sat Jul 20 14:48:02 2013 +0100
324+++ b/ircd/m_server.c Sat Jul 20 14:48:06 2013 +0100
edb26b39
P
325@@ -492,6 +492,7 @@
326 case 'h': SetHub(cptr); break;
327 case 's': SetService(cptr); break;
328 case '6': SetIPv6(cptr); break;
329+ case 'n': SetOperName(cptr); break;
330 }
331 }
332
333@@ -776,10 +777,11 @@
334 continue;
335 if (0 == match(cli_name(&me), cli_name(acptr)))
336 continue;
337- sendcmdto_one(sptr, CMD_SERVER, bcptr, "%s %d 0 %s %s %s%s +%s%s%s :%s",
338+ sendcmdto_one(sptr, CMD_SERVER, bcptr, "%s %d 0 %s %s %s%s +%s%s%s%s :%s",
339 cli_name(acptr), hop + 1, parv[4], parv[5],
340 NumServCap(acptr), IsHub(acptr) ? "h" : "",
341 IsService(acptr) ? "s" : "", IsIPv6(acptr) ? "6" : "",
342+ IsSendOperName(acptr) ? "n" : "",
343 cli_info(acptr));
344 }
345 return 0;
6fe1b135
P
346diff -r 5440fc22cc1d ircd/m_whois.c
347--- a/ircd/m_whois.c Sat Jul 20 14:48:02 2013 +0100
348+++ b/ircd/m_whois.c Sat Jul 20 14:48:06 2013 +0100
edb26b39
P
349@@ -205,8 +205,11 @@
350 if (user->away)
351 send_reply(sptr, RPL_AWAY, name, user->away);
352
353- if (SeeOper(sptr,acptr))
354+ if (SeeOper(sptr,acptr)) {
355 send_reply(sptr, RPL_WHOISOPERATOR, name);
356+ if (IsAnOper(sptr) && user->opername)
357+ send_reply(sptr, RPL_WHOISOPERNAME, name, user->opername);
358+ }
359
360 if (IsAccount(acptr))
361 send_reply(sptr, RPL_WHOISACCOUNT, name, user->account);
6fe1b135
P
362diff -r 5440fc22cc1d ircd/memdebug.c
363--- a/ircd/memdebug.c Sat Jul 20 14:48:02 2013 +0100
364+++ b/ircd/memdebug.c Sat Jul 20 14:48:06 2013 +0100
edb26b39
P
365@@ -1,4 +1,5 @@
366 #include <sys/types.h>
367+#include "config.h"
368 #include "ircd.h"
369 #include "ircd_alloc.h"
370 #include "ircd_log.h"
6fe1b135
P
371diff -r 5440fc22cc1d ircd/s_auth.c
372--- a/ircd/s_auth.c Sat Jul 20 14:48:02 2013 +0100
373+++ b/ircd/s_auth.c Sat Jul 20 14:48:06 2013 +0100
374@@ -1975,10 +1975,17 @@
edb26b39
P
375 /* If account has a creation timestamp, use it. */
376 assert(cli_user(cli) != NULL);
377 if (params[0][len] == ':') {
378- cli_user(cli)->acc_create = strtoul(params[0] + len + 1, NULL, 10);
379- params[0][len] = '\0';
380+ char *end;
381+ cli_user(cli)->acc_create = strtoul(params[0] + len + 1, &end, 10);
382+ if (*end == ':') {
383+ char *end2;
384+ cli_user(cli)->acc_id = strtoul(end + 1, &end2, 10);
385+ if (*end2 == ':')
386+ cli_user(cli)->acc_flags = strtoull(end2 + 1, NULL, 10);
387+ }
388 }
389
390+
391 /* Copy account name to User structure. */
392 ircd_strncpy(cli_user(cli)->account, params[0], ACCOUNTLEN);
393 SetAccount(cli);
6fe1b135
P
394diff -r 5440fc22cc1d ircd/s_bsd.c
395--- a/ircd/s_bsd.c Sat Jul 20 14:48:02 2013 +0100
396+++ b/ircd/s_bsd.c Sat Jul 20 14:48:06 2013 +0100
edb26b39
P
397@@ -354,7 +354,7 @@
398 cli_lasttime(cptr) = CurrentTime;
399 ClearPingSent(cptr);
400
401- sendrawto_one(cptr, MSG_SERVER " %s 1 %Tu %Tu J%s %s%s +%s6 :%s",
402+ sendrawto_one(cptr, MSG_SERVER " %s 1 %Tu %Tu J%s %s%s +%s6n :%s",
403 cli_name(&me), cli_serv(&me)->timestamp, newts,
404 MAJOR_PROTOCOL, NumServCap(&me),
405 feature_bool(FEAT_HUB) ? "h" : "", cli_info(&me));
6fe1b135
P
406diff -r 5440fc22cc1d ircd/s_err.c
407--- a/ircd/s_err.c Sat Jul 20 14:48:02 2013 +0100
408+++ b/ircd/s_err.c Sat Jul 20 14:48:06 2013 +0100
edb26b39
P
409@@ -718,7 +718,7 @@
410 /* 342 */
411 { 0 },
412 /* 343 */
413- { 0 },
414+ { RPL_WHOISOPERNAME, "%s %s :is opered as", "343" },
415 /* 344 */
416 { 0 },
417 /* 345 */
6fe1b135
P
418diff -r 5440fc22cc1d ircd/s_serv.c
419--- a/ircd/s_serv.c Sat Jul 20 14:48:02 2013 +0100
420+++ b/ircd/s_serv.c Sat Jul 20 14:48:06 2013 +0100
edb26b39
P
421@@ -128,7 +128,7 @@
422 /*
423 * Pass my info to the new server
424 */
425- sendrawto_one(cptr, MSG_SERVER " %s 1 %Tu %Tu J%s %s%s +%s6 :%s",
426+ sendrawto_one(cptr, MSG_SERVER " %s 1 %Tu %Tu J%s %s%s +%s6n :%s",
427 cli_name(&me), cli_serv(&me)->timestamp,
428 cli_serv(cptr)->timestamp, MAJOR_PROTOCOL, NumServCap(&me),
429 feature_bool(FEAT_HUB) ? "h" : "",
430@@ -184,10 +184,10 @@
431 if (!match(cli_name(&me), cli_name(cptr)))
432 continue;
433 sendcmdto_one(&me, CMD_SERVER, acptr,
434- "%s 2 0 %Tu J%02u %s%s +%s%s%s :%s", cli_name(cptr),
435+ "%s 2 0 %Tu J%02u %s%s +%s%s%s%s :%s", cli_name(cptr),
436 cli_serv(cptr)->timestamp, Protocol(cptr), NumServCap(cptr),
437 IsHub(cptr) ? "h" : "", IsService(cptr) ? "s" : "",
438- IsIPv6(cptr) ? "6" : "", cli_info(cptr));
439+ IsIPv6(cptr) ? "6" : "", IsSendOperName(cptr) ? "n" : "", cli_info(cptr));
440 }
441
442 /* Send these as early as possible so that glined users/juped servers can
443@@ -227,11 +227,11 @@
444 if (0 == match(cli_name(&me), cli_name(acptr)))
445 continue;
446 sendcmdto_one(cli_serv(acptr)->up, CMD_SERVER, cptr,
447- "%s %d 0 %Tu %s%u %s%s +%s%s%s :%s", cli_name(acptr),
448+ "%s %d 0 %Tu %s%u %s%s +%s%s%s%s :%s", cli_name(acptr),
449 cli_hopcount(acptr) + 1, cli_serv(acptr)->timestamp,
450 protocol_str, Protocol(acptr), NumServCap(acptr),
451 IsHub(acptr) ? "h" : "", IsService(acptr) ? "s" : "",
452- IsIPv6(acptr) ? "6" : "", cli_info(acptr));
453+ IsIPv6(acptr) ? "6" : "", IsSendOperName(cptr) ? "n" : "", cli_info(acptr));
454 }
455 }
456
457@@ -243,7 +243,11 @@
458 if (IsUser(acptr))
459 {
460 char xxx_buf[25];
461- char *s = umode_str(acptr);
462+ char *s;
463+ if (IsSendOperName(cptr))
464+ s = umode_str(acptr, UMODE_ALL_PARAMS);
465+ else
466+ s = umode_str(acptr, UMODE_ALL_PARAMS_BUT_OPERID);
467 sendcmdto_one(cli_user(acptr)->server, CMD_NICK, cptr,
468 "%s %d %Tu %s %s %s%s%s%s %s%s :%s",
469 cli_name(acptr), cli_hopcount(acptr) + 1, cli_lastnick(acptr),
6fe1b135
P
470diff -r 5440fc22cc1d ircd/s_stats.c
471--- a/ircd/s_stats.c Sat Jul 20 14:48:02 2013 +0100
472+++ b/ircd/s_stats.c Sat Jul 20 14:48:06 2013 +0100
edb26b39
P
473@@ -493,12 +493,12 @@
474 */
475 if (sd->sd_funcdata) {
476 send_reply(sptr, SND_EXPLICIT | RPL_STATSVERBOSE,
477- "%-20s %-20s Flags Hops Numeric Lag RTT Up Down "
478+ "%-20s %-20s Flags Hops Numeric Lag RTT Up Down "
479 "Clients/Max Proto %-10s :Info", "Servername", "Uplink",
480 "LinkTS");
481- fmt = "%-20s %-20s %c%c%c%c%c %4i %s %-4i %5i %4i %4i %4i %5i %5i P%-2i %Tu :%s";
482+ fmt = "%-20s %-20s %c%c%c%c%c%c %4i %s %-4i %5i %4i %4i %4i %5i %5i P%-2i %Tu :%s";
483 } else {
484- fmt = "%s %s %c%c%c%c%c %i %s %i %i %i %i %i %i %i P%i %Tu :%s";
485+ fmt = "%s %s %c%c%c%c%c%c %i %s %i %i %i %i %i %i %i P%i %Tu :%s";
486 }
487
488 for (acptr = GlobalClientList; acptr; acptr = cli_next(acptr))
489@@ -516,6 +516,7 @@
490 IsHub(acptr) ? 'H' : '-',
491 IsService(acptr) ? 'S' : '-',
492 IsIPv6(acptr) ? '6' : '-',
493+ IsSendOperName(acptr) ? 'n' : '-',
494 cli_hopcount(acptr),
495 NumServ(acptr),
496 base64toint(cli_yxx(acptr)),
6fe1b135
P
497diff -r 5440fc22cc1d ircd/s_user.c
498--- a/ircd/s_user.c Sat Jul 20 14:48:02 2013 +0100
499+++ b/ircd/s_user.c Sat Jul 20 14:48:06 2013 +0100
edb26b39
P
500@@ -113,6 +113,8 @@
501 if (--user->refcnt == 0) {
502 if (user->away)
503 MyFree(user->away);
504+ if (user->opername)
505+ MyFree(user->opername);
506 /*
507 * sanity check
508 */
509@@ -347,6 +349,7 @@
510 char* tmpstr;
511 struct User* user = cli_user(sptr);
512 char ip_base64[25];
513+ int ipv6andopername[] = {FLAG_IPV6,FLAG_OPERNAME};
514
515 user->last = CurrentTime;
516 parv[0] = cli_name(sptr);
517@@ -458,10 +461,11 @@
518 if (IsOper(sptr))
519 ++UserStats.opers;
520
521- tmpstr = umode_str(sptr);
522- /* Send full IP address to IPv6-grokking servers. */
523+ tmpstr = umode_str(sptr, UMODE_ALL_PARAMS_BUT_OPERID);
524+
525+ /* Do not send oper name and send full IP address to IPv6-grokking servers. */
526 sendcmdto_flag_serv_butone(user->server, CMD_NICK, cptr,
527- FLAG_IPV6, FLAG_LAST_FLAG,
528+ FLAG_IPV6, FLAG_OPERNAME,
529 "%s %d %Tu %s %s %s%s%s%s %s%s :%s",
530 cli_name(sptr), cli_hopcount(sptr) + 1,
531 cli_lastnick(sptr),
532@@ -469,9 +473,31 @@
533 *tmpstr ? "+" : "", tmpstr, *tmpstr ? " " : "",
534 iptobase64(ip_base64, &cli_ip(sptr), sizeof(ip_base64), 1),
535 NumNick(sptr), cli_info(sptr));
536- /* Send fake IPv6 addresses to pre-IPv6 servers. */
537+ /* Do not send oper name and send fake IPv6 addresses to pre-IPv6 servers. */
538+ sendcmdto_flagarray_serv_butone(user->server, CMD_NICK, cptr,
539+ NULL, 0, ipv6andopername, 2,
540+ "%s %d %Tu %s %s %s%s%s%s %s%s :%s",
541+ cli_name(sptr), cli_hopcount(sptr) + 1,
542+ cli_lastnick(sptr),
543+ user->realusername, user->realhost,
544+ *tmpstr ? "+" : "", tmpstr, *tmpstr ? " " : "",
545+ iptobase64(ip_base64, &cli_ip(sptr), sizeof(ip_base64), 0),
546+ NumNick(sptr), cli_info(sptr));
547+
548+ tmpstr = umode_str(sptr, UMODE_ALL_PARAMS);
549+ /* Send oper name and full IP address to IPv6-grokking servers. */
550+ sendcmdto_flagarray_serv_butone(user->server, CMD_NICK, cptr,
551+ ipv6andopername, 2, NULL, 0,
552+ "%s %d %Tu %s %s %s%s%s%s %s%s :%s",
553+ cli_name(sptr), cli_hopcount(sptr) + 1,
554+ cli_lastnick(sptr),
555+ user->realusername, user->realhost,
556+ *tmpstr ? "+" : "", tmpstr, *tmpstr ? " " : "",
557+ iptobase64(ip_base64, &cli_ip(sptr), sizeof(ip_base64), 1),
558+ NumNick(sptr), cli_info(sptr));
559+ /* Send oper name and fake IPv6 addresses to pre-IPv6 servers. */
560 sendcmdto_flag_serv_butone(user->server, CMD_NICK, cptr,
561- FLAG_LAST_FLAG, FLAG_IPV6,
562+ FLAG_OPERNAME, FLAG_IPV6,
563 "%s %d %Tu %s %s %s%s%s%s %s%s :%s",
564 cli_name(sptr), cli_hopcount(sptr) + 1,
565 cli_lastnick(sptr),
566@@ -492,7 +518,7 @@
567 else
568 FlagClr(&flags, FLAG_ACCOUNT);
569 client_set_privs(sptr, NULL);
570- send_umode(cptr, sptr, &flags, ALL_UMODES);
571+ send_umode(cptr, sptr, &flags, ALL_UMODES, 0);
572 if ((cli_snomask(sptr) != SNO_DEFAULT) && HasFlag(sptr, FLAG_SERVNOTICE))
573 send_reply(sptr, RPL_SNOMASK, cli_snomask(sptr), cli_snomask(sptr));
574 }
6fe1b135 575@@ -845,16 +871,26 @@
edb26b39
P
576 int i;
577 struct Client *acptr;
578
579- send_umode(NULL, sptr, old, prop ? SEND_UMODES : SEND_UMODES_BUT_OPER);
580+ send_umode(NULL, sptr, old, prop ? SEND_UMODES : SEND_UMODES_BUT_OPER, 0);
581
582 for (i = HighestFd; i >= 0; i--)
583 {
584 if ((acptr = LocalClientArray[i]) && IsServer(acptr) &&
585- (acptr != cptr) && (acptr != sptr) && *umodeBuf)
586- sendcmdto_one(sptr, CMD_MODE, acptr, "%s %s", cli_name(sptr), umodeBuf);
587+ (acptr != cptr) && (acptr != sptr) && !IsSendOperName(acptr) && *umodeBuf)
588+ sendcmdto_one(sptr, CMD_MODE, acptr, "%s %s", cli_name(sptr), umodeBuf);
589 }
590+
591+ send_umode(NULL, sptr, old, prop ? SEND_UMODES : SEND_UMODES_BUT_OPER, 1);
592+
593+ for (i = HighestFd; i >= 0; i--)
594+ {
595+ if ((acptr = LocalClientArray[i]) && IsServer(acptr) &&
596+ (acptr != cptr) && (acptr != sptr) && IsSendOperName(acptr) && *umodeBuf)
597+ sendcmdto_one(sptr, CMD_MODE, acptr, "%s %s", cli_name(sptr), umodeBuf);
598+ }
599+
600 if (cptr && MyUser(cptr))
601- send_umode(cptr, sptr, old, ALL_UMODES);
602+ send_umode(cptr, sptr, old, ALL_UMODES, 0);
603 }
604
605
6fe1b135 606@@ -1230,9 +1266,29 @@
edb26b39
P
607 ClearWallops(sptr);
608 break;
609 case 'o':
610- if (what == MODE_ADD)
611+ if (what == MODE_ADD) {
612 SetOper(sptr);
613- else {
614+ if (IsServer(cptr) && IsSendOperName(cptr)) {
615+ if (*(p + 1)) {
616+ opername = *++p;
617+ if (cli_user(sptr)->opername)
618+ MyFree(cli_user(sptr)->opername);
619+ if ((opername[0] == NOOPERNAMECHARACTER) && (opername[1] == '\0')) {
620+ cli_user(sptr)->opername = NULL;
621+ } else {
622+ opernamelen = strlen(opername);
623+ if (opernamelen > ACCOUNTLEN) {
624+ protocol_violation(cptr, "Received opername (%s) longer than %d for %s; ignoring.", opername, ACCOUNTLEN, cli_name(sptr));
625+ cli_user(sptr)->opername = NULL;
626+ } else {
627+ cli_user(sptr)->opername = (char*) MyMalloc(opernamelen + 1);
628+ assert(0 != cli_user(sptr)->opername);
629+ ircd_strncpy(cli_user(sptr)->opername,opername,ACCOUNTLEN);
630+ }
631+ }
632+ }
633+ }
634+ } else {
635 ClrFlag(sptr, FLAG_OPER);
636 ClrFlag(sptr, FLAG_LOCOP);
637 if (MyConnect(sptr))
6fe1b135 638@@ -1420,13 +1476,16 @@
edb26b39
P
639 */
640 if (!FlagHas(&setflags, FLAG_ACCOUNT) && IsAccount(sptr)) {
641 int len = ACCOUNTLEN;
642- char *ts;
643+ char *pts, *ts;
644 if ((ts = strchr(account, ':'))) {
645 len = (ts++) - account;
646 cli_user(sptr)->acc_create = atoi(ts);
647- Debug((DEBUG_DEBUG, "Received timestamped account in user mode; "
648- "account \"%s\", timestamp %Tu", account,
649- cli_user(sptr)->acc_create));
650+ if ((pts = strchr(ts, ':'))) {
651+ char *pflags;
652+ cli_user(sptr)->acc_id = strtoul(pts + 1, &pflags, 10);
653+ if (*pflags == ':')
654+ cli_user(sptr)->acc_flags = strtoull(pflags + 1, NULL, 10);
655+ }
656 }
657 ircd_strncpy(cli_user(sptr)->account, account, len);
658 }
6fe1b135 659@@ -1447,7 +1506,23 @@
edb26b39
P
660 /* user no longer oper */
661 assert(UserStats.opers > 0);
662 --UserStats.opers;
663+
664+ /* notify my operators an operator has deOPERed on the network - wiebe */
665+ if (MyConnect(sptr)) {
666+ sendto_opmask_butone(0, SNO_OLDSNO, "%s (%s@%s) is no longer operator (O) as %s",
667+ cli_name(sptr), cli_user(sptr)->realusername, cli_user(sptr)->realhost,
668+ cli_user(sptr)->opername ? cli_user(sptr)->opername : "<unknown>");
669+ } else {
670+ sendto_opmask_butone(0, SNO_OLDSNO, "%s (%s@%s) is no longer operator (O) as %s on %s",
671+ cli_name(sptr), cli_user(sptr)->realusername, cli_user(sptr)->realhost,
672+ cli_user(sptr)->opername ? cli_user(sptr)->opername : "<unknown>", cli_name(cli_user(sptr)->server));
673+ }
674+
675 client_set_privs(sptr, NULL); /* will clear propagate privilege */
676+ if (cli_user(sptr)->opername) {
677+ MyFree(cli_user(sptr)->opername);
678+ cli_user(sptr)->opername = NULL;
679+ }
680 }
681 if (FlagHas(&setflags, FLAG_INVISIBLE) && !IsInvisible(sptr)) {
682 assert(UserStats.inv_clients > 0);
6fe1b135 683@@ -1468,7 +1543,7 @@
edb26b39
P
684 * @param[in] cptr Some user.
685 * @return Pointer to a static buffer.
686 */
687-char *umode_str(struct Client *cptr)
688+char *umode_str(struct Client *cptr, int type)
689 {
690 /* Maximum string size: "owidgrx\0" */
691 char *m = umodeBuf;
6fe1b135 692@@ -1485,30 +1560,40 @@
edb26b39
P
693 *m++ = userModeList[i].c;
694 }
695
696+ /* OperID is wanted */
697+ if (type == UMODE_ALL_PARAMS && IsOper(cptr))
698+ {
699+ *m++ = ' ';
700+ if (cli_user(cptr)->opername) {
701+ char* t = cli_user(cptr)->opername;
702+ while ((*m++ = *t++))
703+ ; /* Empty loop */
704+ m--; /* Step back over the '\0' */
705+ } else {
706+ *m++ = NOOPERNAMECHARACTER;
707+ }
708+ }
709+
710 if (IsAccount(cptr))
711 {
712- char* t = cli_user(cptr)->account;
713+ char *t, nbuf[64+ACCOUNTLEN];
714
715- *m++ = ' ';
716+ if ( type == UMODE_AND_ACCOUNT_SHORT)
717+ ircd_snprintf(0, t = nbuf, sizeof(nbuf), " %s", cli_user(cptr)->account);
718+ else
719+ ircd_snprintf(0, t = nbuf, sizeof(nbuf), " %s:%Tu:%lu:%"PRIu64,
720+ cli_user(cptr)->account, cli_user(cptr)->acc_create,
721+ cli_user(cptr)->acc_id, cli_user(cptr)->acc_flags);
722+
723+
724 while ((*m++ = *t++))
725 ; /* Empty loop */
726
727- if (cli_user(cptr)->acc_create) {
728- char nbuf[20];
729- Debug((DEBUG_DEBUG, "Sending timestamped account in user mode for "
730- "account \"%s\"; timestamp %Tu", cli_user(cptr)->account,
731- cli_user(cptr)->acc_create));
732- ircd_snprintf(0, t = nbuf, sizeof(nbuf), ":%Tu",
733- cli_user(cptr)->acc_create);
734- m--; /* back up over previous nul-termination */
735- while ((*m++ = *t++))
736- ; /* Empty loop */
737- }
738 m--; /* Step back over the '\0' */
739 }
740
741 /* sethost parameter is wanted */
742- if (type != UMODE_AND_ACCOUNT && IsSetHost(cptr)) {
743+ if ((type != UMODE_AND_ACCOUNT && type != UMODE_AND_ACCOUNT_SHORT) && IsSetHost(cptr)) {
744 *m++ = ' ';
745 ircd_snprintf(0, m, USERLEN + HOSTLEN + 2, "%s@%s", cli_user(cptr)->username,
746 cli_user(cptr)->host);
6fe1b135 747@@ -1526,11 +1611,12 @@
edb26b39
P
748 * SEND_UMODES, to select which changed user modes to send.
749 */
750 void send_umode(struct Client *cptr, struct Client *sptr, struct Flags *old,
751- int sendset)
752+ int sendset, int opernames)
753 {
754 int i;
755 int flag;
756 int needhost = 0;
757+ int needoper = 0;
758 char *m;
759 int what = MODE_NULL;
760
6fe1b135 761@@ -1560,6 +1646,12 @@
edb26b39
P
762 continue;
763 break;
764 }
765+ /* Special case for OPER.. */
766+ if (flag == FLAG_OPER) {
767+ /* If we're setting +o, add the opername later */
768+ if (!FlagHas(old, flag))
769+ needoper++;
770+ }
771 /* Special case for SETHOST.. */
772 if (flag == FLAG_SETHOST) {
773 /* Don't send to users */
6fe1b135 774@@ -1593,6 +1685,16 @@
edb26b39
P
775 }
776 }
777 }
778+ if (opernames && needoper) {
779+ *m++ = ' ';
780+ if (cli_user(sptr)->opername) {
781+ char* t = cli_user(sptr)->opername;
782+ while ((*m++ = *t++))
783+ ; /* Empty loop */
784+ } else {
785+ *m++ = NOOPERNAMECHARACTER;
786+ }
787+ }
788 if (needhost) {
789 *m++ = ' ';
790 ircd_snprintf(0, m, USERLEN + HOSTLEN + 1, "%s@%s", cli_user(sptr)->username,
6fe1b135
P
791diff -r 5440fc22cc1d ircd/send.c
792--- a/ircd/send.c Sat Jul 20 14:48:02 2013 +0100
793+++ b/ircd/send.c Sat Jul 20 14:48:06 2013 +0100
edb26b39
P
794@@ -405,6 +405,70 @@
795 }
796
797 /**
798+ * Send a (prefixed) command to all servers matching or not matching a
799+ * flag but one.
800+ * @param[in] from Client sending the command.
801+ * @param[in] cmd Long name of command (ignored).
802+ * @param[in] tok Short name of command.
803+ * @param[in] one Client direction to skip (or NULL).
804+ * @param[in] require Only send to servers with all Flag bits in the array set.
805+ * @param[in] requiresize Size of require flag array
806+ * @param[in] forbid Do not send to servers with any Flag bits in the array set.
807+ * @param[in] forbidsize Size of forbid flag array
808+ * @param[in] pattern Format string for command arguments.
809+ */
810+void sendcmdto_flagarray_serv_butone(struct Client *from, const char *cmd,
811+ const char *tok, struct Client *one,
812+ int *require, unsigned int requiresize,
813+ int *forbid, unsigned int forbidsize,
814+ const char *pattern, ...)
815+{
816+ struct VarData vd;
817+ struct MsgBuf *mb;
818+ struct DLink *lp;
819+ unsigned int i, skip;
820+
821+ vd.vd_format = pattern; /* set up the struct VarData for %v */
822+ va_start(vd.vd_args, pattern);
823+
824+ /* use token */
825+ mb = msgq_make(&me, "%C %s %v", from, tok, &vd);
826+ va_end(vd.vd_args);
827+
828+ /* send it to our downlinks */
829+ for (lp = cli_serv(&me)->down; lp; lp = lp->next) {
830+ if (one && lp->value.cptr == cli_from(one))
831+ continue;
832+
833+ skip = 0;
834+
835+ for (i = 0; i < requiresize; i++) {
836+ if ((require[i] < FLAG_LAST_FLAG) && !HasFlag(lp->value.cptr, require[i])) {
837+ skip = 1;
838+ break;
839+ }
840+ }
841+
842+ if (skip)
843+ continue;
844+
845+ for (i = 0; i < forbidsize; i++) {
846+ if ((forbid[i] < FLAG_LAST_FLAG) && HasFlag(lp->value.cptr, forbid[i])) {
847+ skip = 1;
848+ break;
849+ }
850+ }
851+
852+ if (skip)
853+ continue;
854+
855+ send_buffer(lp->value.cptr, mb, 0);
856+ }
857+
858+ msgq_clean(mb);
859+}
860+
861+/**
862 * Send a (prefixed) command to all servers but one.
863 * @param[in] from Client sending the command.
864 * @param[in] cmd Long name of command (ignored).