2 * IRC - Internet Relay Chat, ircd/m_svsnick.c
3 * Written by David Herrmann.
7 * m_functions execute protocol messages on this server:
9 * cptr is always NON-NULL, pointing to a *LOCAL* client
10 * structure (with an open socket connected!). This
11 * identifies the physical socket where the message
12 * originated (or which caused the m_function to be
13 * executed--some m_functions may call others...).
15 * sptr is the source of the message, defined by the
16 * prefix part of the message if present. If not
17 * or prefix not found, then sptr==cptr.
19 * (!IsServer(cptr)) => (cptr == sptr), because
20 * prefixes are taken *only* from servers...
23 * (sptr == cptr) => the message didn't
26 * (sptr != cptr && IsServer(sptr) means
27 * the prefix specified servername. (?)
29 * (sptr != cptr && !IsServer(sptr) means
30 * that message originated from a remote
35 * (!IsServer(sptr)) means that, sptr can safely
36 * taken as defining the target structure of the
37 * message in this server.
39 * *Always* true (if 'parse' and others are working correct):
41 * 1) sptr->from == cptr (note: cptr->from == cptr)
43 * 2) MyConnect(sptr) <=> sptr == cptr (e.g. sptr
44 * *cannot* be a local connection, unless it's
45 * actually cptr!). [MyConnect(x) should probably
46 * be defined as (x == x->from) --msa ]
48 * parc number of variable parameter strings (if zero,
49 * parv is allowed to be NULL)
51 * parv a NULL terminated list of parameter pointers,
53 * parv[0], sender (prefix string), if not present
54 * this points to an empty string.
55 * parv[1]...parv[parc-1]
56 * pointers to additional parameters
57 * parv[parc] == NULL, *always*
59 * note: it is guaranteed that parv[0]..parv[parc-1] are all
67 #include "ircd_features.h"
69 #include "ircd_reply.h"
70 #include "ircd_string.h"
83 /* Copied from m_nick.c.
85 * do_nick_name checks the nickname. WARNING: It MAY modify the nickname
86 * RETURNS the length of the final NICKNAME (0, if nickname is invalid)
88 * Nickname characters are in range 'A'..'}', '_', '-', '0'..'9'
89 * anything outside the above set will terminate nickname.
90 * In addition, the first character cannot be '-' or a Digit.
92 static int do_nick_name(char* nick) {
94 char *end = ch + NICKLEN;
97 /* first character in [0..9-] */
98 if(*ch == '-' || IsDigit(*ch)) return 0;
99 for( ; (ch < end) && *ch; ++ch) {
100 if(!IsNickChar(*ch)) break;
107 * SVSNICK is forwarded to the users server, hence, it can be called
110 int m_svsnick(struct Client *cptr, struct Client *sptr, int parc, char *parv[]) {
111 struct Client *acptr = NULL;
112 char nick[NICKLEN + 2];
115 if (!IsNetServ(sptr) || !HasFlag(sptr, FLAG_SECURITY_SERV))
116 return send_reply(sptr, ERR_NOPRIVILEGES);
119 return protocol_violation(cptr, "Too few arguments for SVSNICK");
122 if(!(acptr = FindUser(parv[1]))) {
123 return 0; /* Ignore SVSNICK for a user that has quit */
126 /* Limit the nicklen to NICKLEN. */
128 if(strlen(arg) > IRCD_MIN(NICKLEN, feature_int(FEAT_NICKLEN))) {
129 arg[IRCD_MIN(NICKLEN, feature_int(FEAT_NICKLEN))] = '\0';
133 if(!do_nick_name(nick)) {
134 /* Invalid nickname. */
138 /* Check whether nickname is already set. */
139 if(ircd_strcmp(cli_name(acptr), parv[2]) == 0) {
143 /* Check whether the nick is already used. */
149 /* Forward the message to the server where the user is connected to. */
150 if(!MyConnect(acptr)) {
151 const struct User* user = cli_user(acptr);
152 struct Client *server = user->server;
153 sendcmdto_one(sptr, CMD_SVSNICK, acptr, "%s%s %s", cli_yxx(server), cli_yxx(acptr), nick);
158 set_nick_name(acptr, acptr, nick, parc, parv, 1);
163 /* ms_svsnick - server message handler
164 * parv[0] = sender prefix
165 * parv[1] = target numeric
166 * parv[2] = new nickname
168 signed int ms_svsnick(struct Client* cptr, struct Client* sptr, signed int parc, char* parv[]) {
169 struct Client *acptr = NULL;
170 char nick[NICKLEN + 2];
175 return protocol_violation(cptr, "Too few arguments for SVSNICK");
178 if(!(acptr = findNUser(parv[1]))) {
179 return 0; /* Ignore SVSNICK for a user that has quit */
182 /* Limit the nicklen to NICKLEN. */
184 if(strlen(arg) > IRCD_MIN(NICKLEN, feature_int(FEAT_NICKLEN))) {
185 arg[IRCD_MIN(NICKLEN, feature_int(FEAT_NICKLEN))] = '\0';
189 if(!do_nick_name(nick)) {
190 /* Invalid nickname. */
194 /* Check whether nickname is already set. */
195 if(ircd_strcmp(cli_name(acptr), parv[2]) == 0) {
199 /* Check whether the nick is already used. */
205 /* Forward the message to the server where the user is connected to. */
206 if(!MyConnect(acptr)) {
207 sendcmdto_one(sptr, CMD_SVSNICK, acptr, "%s %s", parv[1], nick);
211 #ifndef UNRESTRICTED_SERV
213 set_nick_name(acptr, acptr, nick, parc, parv, 1);
219 * ms_svsnick_old - server message handler
220 * parv[0] = sender prefix
221 * parv[1] = Target numeric
222 * parv[2] = New nickname
224 int ms_svsnick_old(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) {
225 struct Client* acptr = NULL;
226 char nick[NICKLEN + 2];
231 return(need_more_params(sptr, "SVSNICK"));
233 if(!(acptr = findNUser(parv[1])))
234 return 0; /* Ignore SVSNICK for a user that has quit */
236 if(!find_conf_byhost(cli_confs(cptr), cli_name(sptr), CONF_UWORLD)) {
237 return protocol_violation(cptr, "Non-U:lined server %s sets svsnick on user %s", cli_name(sptr), cli_name(acptr));
241 * Don't let them send make us send back a really long string of
245 if(strlen(arg) > IRCD_MIN(NICKLEN, feature_int(FEAT_NICKLEN)))
246 arg[IRCD_MIN(NICKLEN, feature_int(FEAT_NICKLEN))] = '\0';
248 if((s = strchr(arg, '~')))
254 * If do_nick_name() returns a null name then reject it.
256 if(0 == do_nick_name(nick))
259 if(ircd_strcmp(cli_name(acptr), nick) == 0)
260 return 0; /* Nick already set to what SVSNICK wants, ignoring... */
263 return 0; /* Target nick is in use */
265 set_nick_name(acptr, acptr, nick, parc, parv, 1);
266 sendcmdto_serv_butone(sptr, CMD_SVSNICK_OLD, cptr, "%s %s", parv[1], nick);