1 /* modules/m_services.c
2 * Copyright (C) 2005 Lee Hardy <lee -at- leeh.co.uk>
3 * Copyright (C) 2005 ircd-ratbox development team
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
9 * 1.Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 * 2.Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3.The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
21 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
25 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
26 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
42 #include "s_newconf.h"
48 #include "sprintf_irc.h"
52 static int me_su(struct Client
*, struct Client
*, int, const char **);
53 static int me_login(struct Client
*, struct Client
*, int, const char **);
54 static int me_rsfnc(struct Client
*, struct Client
*, int, const char **);
55 static int me_nickdelay(struct Client
*, struct Client
*, int, const char **);
57 static void h_svc_server_introduced(hook_data_client
*);
58 static void h_svc_whois(hook_data_client
*);
59 static void h_svc_stats(hook_data_int
*);
61 struct Message su_msgtab
= {
62 "SU", 0, 0, 0, MFLG_SLOW
,
63 {mg_ignore
, mg_ignore
, mg_ignore
, mg_ignore
, {me_su
, 2}, mg_ignore
}
65 struct Message login_msgtab
= {
66 "LOGIN", 0, 0, 0, MFLG_SLOW
,
67 {mg_ignore
, mg_ignore
, mg_ignore
, mg_ignore
, {me_login
, 2}, mg_ignore
}
69 struct Message rsfnc_msgtab
= {
70 "RSFNC", 0, 0, 0, MFLG_SLOW
,
71 {mg_ignore
, mg_ignore
, mg_ignore
, mg_ignore
, {me_rsfnc
, 4}, mg_ignore
}
73 struct Message nickdelay_msgtab
= {
74 "NICKDELAY", 0, 0, 0, MFLG_SLOW
,
75 {mg_unreg
, mg_ignore
, mg_ignore
, mg_ignore
, {me_nickdelay
, 3}, mg_ignore
}
78 mapi_clist_av1 services_clist
[] = {
79 &su_msgtab
, &login_msgtab
, &rsfnc_msgtab
, &nickdelay_msgtab
, NULL
81 mapi_hfn_list_av1 services_hfnlist
[] = {
82 { "doing_stats", (hookfn
) h_svc_stats
},
83 { "doing_whois", (hookfn
) h_svc_whois
},
84 { "doing_whois_global", (hookfn
) h_svc_whois
},
85 { "server_introduced", (hookfn
) h_svc_server_introduced
},
89 DECLARE_MODULE_AV1(services
, NULL
, NULL
, services_clist
, NULL
, services_hfnlist
, "$Revision: 147 $");
92 me_su(struct Client
*client_p
, struct Client
*source_p
,
93 int parc
, const char *parv
[])
95 struct Client
*target_p
;
97 if(!(source_p
->flags
& FLAGS_SERVICE
))
100 if((target_p
= find_client(parv
[1])) == NULL
)
106 if(EmptyString(parv
[2]))
107 target_p
->user
->suser
[0] = '\0';
109 strlcpy(target_p
->user
->suser
, parv
[2], sizeof(target_p
->user
->suser
));
111 invalidate_bancache_user(target_p
);
117 me_login(struct Client
*client_p
, struct Client
*source_p
,
118 int parc
, const char *parv
[])
120 if(!IsPerson(source_p
))
123 strlcpy(source_p
->user
->suser
, parv
[1], sizeof(source_p
->user
->suser
));
128 clean_nick(const char *nick
)
132 if(EmptyString(nick
) || *nick
== '-' || IsDigit(*nick
))
138 if(!IsNickChar(*nick
))
149 me_rsfnc(struct Client
*client_p
, struct Client
*source_p
,
150 int parc
, const char *parv
[])
152 struct Client
*target_p
;
153 struct Client
*exist_p
;
156 if(!(source_p
->flags
& FLAGS_SERVICE
))
159 if((target_p
= find_person(parv
[1])) == NULL
)
162 if(!MyClient(target_p
))
165 if(!clean_nick(parv
[2]))
168 curts
= atol(parv
[4]);
170 /* if tsinfo is different from what it was when services issued the
171 * RSFNC, then we ignore it. This can happen when a client changes
172 * nicknames before the RSFNC arrives.. --anfl
174 if(target_p
->tsinfo
!= curts
)
177 if((exist_p
= find_named_client(parv
[2])))
181 /* this would be one hell of a race condition to trigger
182 * this one given the tsinfo check above, but its here for
185 if(target_p
== exist_p
)
188 if(MyClient(exist_p
))
189 sendto_one(exist_p
, ":%s KILL %s :(Nickname regained by services)",
190 me
.name
, exist_p
->name
);
192 exist_p
->flags
|= FLAGS_KILLED
;
193 /* Do not send kills to servers for unknowns -- jilles */
194 if(IsClient(exist_p
))
195 kill_client_serv_butone(NULL
, exist_p
, "%s (Nickname regained by services)",
198 snprintf(buf
, sizeof(buf
), "Killed (%s (Nickname regained by services))",
200 exit_client(NULL
, exist_p
, &me
, buf
);
203 newts
= atol(parv
[3]);
205 /* timestamp is older than 15mins, ignore it */
206 if(newts
< (CurrentTime
- 900))
207 newts
= CurrentTime
- 900;
209 target_p
->tsinfo
= newts
;
211 monitor_signoff(target_p
);
213 invalidate_bancache_user(target_p
);
215 sendto_realops_snomask(SNO_NCHANGE_GLOBAL
, L_NETWIDE
,
216 "Nick change: From %s to %s [%s@%s]",
217 target_p
->name
, parv
[2], target_p
->username
,
220 sendto_realops_snomask(SNO_NCHANGE
, L_ALL
,
221 "Nick change: From %s to %s [%s@%s]",
222 target_p
->name
, parv
[2], target_p
->username
,
225 sendto_common_channels_local(target_p
, ":%s!%s@%s NICK :%s",
226 target_p
->name
, target_p
->username
,
227 target_p
->host
, parv
[2]);
229 add_history(target_p
, 1);
230 sendto_server(NULL
, NULL
, CAP_TS6
, NOCAPS
, ":%s NICK %s :%ld",
231 use_id(target_p
), parv
[2], (long) target_p
->tsinfo
);
232 sendto_server(NULL
, NULL
, NOCAPS
, CAP_TS6
, ":%s NICK %s :%ld",
233 target_p
->name
, parv
[2], (long) target_p
->tsinfo
);
235 del_from_client_hash(target_p
->name
, target_p
);
236 strcpy(target_p
->name
, parv
[2]);
237 add_to_client_hash(target_p
->name
, target_p
);
239 monitor_signon(target_p
);
241 del_all_accepts(target_p
);
243 comm_note(target_p
->localClient
->fd
, "Nick: %s", target_p
->name
);
249 ** parv[0] = sender prefix
250 ** parv[1] = duration in seconds (0 to remove)
254 me_nickdelay(struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[])
259 if(!(source_p
->flags
& FLAGS_SERVICE
))
262 duration
= atoi(parv
[1]);
265 nd
= hash_find_nd(parv
[2]);
271 if (duration
> 86400)
273 add_nd_entry(parv
[2]);
274 nd
= hash_find_nd(parv
[2]);
276 nd
->expire
= CurrentTime
+ duration
;
283 h_svc_server_introduced(hook_data_client
*hdata
)
287 DLINK_FOREACH(ptr
, service_list
.head
)
289 if(!irccmp((const char *) ptr
->data
, hdata
->target
->name
))
291 hdata
->target
->flags
|= FLAGS_SERVICE
;
298 h_svc_whois(hook_data_client
*data
)
300 char *p
= data
->target
->user
->suser
;
303 /* Try to strip off any leading digits as this may be used to
304 * store both an ID number and an account name in one field.
305 * If only digits are present, leave as is.
310 p
= data
->target
->user
->suser
;
312 sendto_one(data
->client
, form_str(RPL_WHOISLOGGEDIN
),
313 get_id(&me
, data
->client
),
314 get_id(data
->client
, data
->client
),
315 data
->target
->name
, p
);
320 h_svc_stats(hook_data_int
*data
)
322 char statchar
= (char) data
->arg2
;
325 if (statchar
== 'U' && IsOperStaffer(data
->client
))
327 DLINK_FOREACH(ptr
, service_list
.head
)
329 sendto_one_numeric(data
->client
, RPL_STATSULINE
,
330 form_str(RPL_STATSULINE
),
331 ptr
->data
, "*", "*", "s");