]>
Commit | Line | Data |
---|---|---|
1 | # HG changeset patch | |
2 | # Parent f6fcd33ea732f2d526a06264e4d34b1b1ecbc131 | |
3 | ||
4 | diff -r f6fcd33ea732 include/client.h | |
5 | --- a/include/client.h Fri Jul 19 22:21:04 2013 +0100 | |
6 | +++ b/include/client.h Fri Jul 19 22:21:39 2013 +0100 | |
7 | @@ -92,6 +92,9 @@ | |
8 | /** String containing valid user modes, in no particular order. */ | |
9 | #define infousermodes "dioswkgxRXInP" | |
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 */ | |
25 | @@ -601,6 +605,8 @@ | |
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)) | |
34 | @@ -642,6 +648,8 @@ | |
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. */ | |
43 | diff -r f6fcd33ea732 include/numeric.h | |
44 | --- a/include/numeric.h Fri Jul 19 22:21:04 2013 +0100 | |
45 | +++ b/include/numeric.h Fri Jul 19 22:21:39 2013 +0100 | |
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 */ | |
54 | diff -r f6fcd33ea732 include/s_user.h | |
55 | --- a/include/s_user.h Fri Jul 19 22:21:04 2013 +0100 | |
56 | +++ b/include/s_user.h Fri Jul 19 22:21:39 2013 +0100 | |
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, | |
69 | diff -r f6fcd33ea732 include/send.h | |
70 | --- a/include/send.h Fri Jul 19 22:21:04 2013 +0100 | |
71 | +++ b/include/send.h Fri Jul 19 22:21:39 2013 +0100 | |
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, | |
86 | diff -r f6fcd33ea732 include/struct.h | |
87 | --- a/include/struct.h Fri Jul 19 22:21:04 2013 +0100 | |
88 | +++ b/include/struct.h Fri Jul 19 22:21:39 2013 +0100 | |
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 */ | |
113 | diff -r f6fcd33ea732 ircd/ircd_parser.y | |
114 | --- a/ircd/ircd_parser.y Fri Jul 19 22:21:04 2013 +0100 | |
115 | +++ b/ircd/ircd_parser.y Fri Jul 19 22:21:39 2013 +0100 | |
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. */ | |
127 | diff -r f6fcd33ea732 ircd/ircd_reslib.c | |
128 | --- a/ircd/ircd_reslib.c Fri Jul 19 22:21:04 2013 +0100 | |
129 | +++ b/ircd/ircd_reslib.c Fri Jul 19 22:21:39 2013 +0100 | |
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" | |
139 | diff -r f6fcd33ea732 ircd/m_account.c | |
140 | --- a/ircd/m_account.c Fri Jul 19 22:21:04 2013 +0100 | |
141 | +++ b/ircd/m_account.c Fri Jul 19 22:21:39 2013 +0100 | |
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 | } | |
241 | diff -r f6fcd33ea732 ircd/m_check.c | |
242 | --- a/ircd/m_check.c Fri Jul 19 22:21:04 2013 +0100 | |
243 | +++ b/ircd/m_check.c Fri Jul 19 22:21:39 2013 +0100 | |
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 */ | |
252 | diff -r f6fcd33ea732 ircd/m_oper.c | |
253 | --- a/ircd/m_oper.c Fri Jul 19 22:21:04 2013 +0100 | |
254 | +++ b/ircd/m_oper.c Fri Jul 19 22:21:39 2013 +0100 | |
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 | } | |
322 | diff -r f6fcd33ea732 ircd/m_server.c | |
323 | --- a/ircd/m_server.c Fri Jul 19 22:21:04 2013 +0100 | |
324 | +++ b/ircd/m_server.c Fri Jul 19 22:21:39 2013 +0100 | |
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; | |
346 | diff -r f6fcd33ea732 ircd/m_whois.c | |
347 | --- a/ircd/m_whois.c Fri Jul 19 22:21:04 2013 +0100 | |
348 | +++ b/ircd/m_whois.c Fri Jul 19 22:21:39 2013 +0100 | |
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); | |
362 | diff -r f6fcd33ea732 ircd/memdebug.c | |
363 | --- a/ircd/memdebug.c Fri Jul 19 22:21:04 2013 +0100 | |
364 | +++ b/ircd/memdebug.c Fri Jul 19 22:21:39 2013 +0100 | |
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" | |
371 | diff -r f6fcd33ea732 ircd/s_auth.c | |
372 | --- a/ircd/s_auth.c Fri Jul 19 22:21:04 2013 +0100 | |
373 | +++ b/ircd/s_auth.c Fri Jul 19 22:21:39 2013 +0100 | |
374 | @@ -1957,10 +1957,17 @@ | |
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); | |
394 | diff -r f6fcd33ea732 ircd/s_bsd.c | |
395 | --- a/ircd/s_bsd.c Fri Jul 19 22:21:04 2013 +0100 | |
396 | +++ b/ircd/s_bsd.c Fri Jul 19 22:21:39 2013 +0100 | |
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)); | |
406 | diff -r f6fcd33ea732 ircd/s_err.c | |
407 | --- a/ircd/s_err.c Fri Jul 19 22:21:04 2013 +0100 | |
408 | +++ b/ircd/s_err.c Fri Jul 19 22:21:39 2013 +0100 | |
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 */ | |
418 | diff -r f6fcd33ea732 ircd/s_serv.c | |
419 | --- a/ircd/s_serv.c Fri Jul 19 22:21:04 2013 +0100 | |
420 | +++ b/ircd/s_serv.c Fri Jul 19 22:21:39 2013 +0100 | |
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), | |
470 | diff -r f6fcd33ea732 ircd/s_stats.c | |
471 | --- a/ircd/s_stats.c Fri Jul 19 22:21:04 2013 +0100 | |
472 | +++ b/ircd/s_stats.c Fri Jul 19 22:21:39 2013 +0100 | |
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)), | |
497 | diff -r f6fcd33ea732 ircd/s_user.c | |
498 | --- a/ircd/s_user.c Fri Jul 19 22:21:04 2013 +0100 | |
499 | +++ b/ircd/s_user.c Fri Jul 19 22:21:39 2013 +0100 | |
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 | } | |
575 | @@ -844,16 +870,26 @@ | |
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 | ||
606 | @@ -1228,9 +1264,29 @@ | |
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)) | |
638 | @@ -1391,13 +1447,16 @@ | |
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 | } | |
659 | @@ -1418,7 +1477,23 @@ | |
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); | |
683 | @@ -1439,7 +1514,7 @@ | |
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; | |
692 | @@ -1456,30 +1531,40 @@ | |
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); | |
747 | @@ -1497,11 +1582,12 @@ | |
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 | ||
761 | @@ -1531,6 +1617,12 @@ | |
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 */ | |
774 | @@ -1564,6 +1656,16 @@ | |
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, | |
791 | diff -r f6fcd33ea732 ircd/send.c | |
792 | --- a/ircd/send.c Fri Jul 19 22:21:04 2013 +0100 | |
793 | +++ b/ircd/send.c Fri Jul 19 22:21:39 2013 +0100 | |
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). |