Author: Bleep <tomh@inxpress.net>
[ircu2.10.12-pk.git] / ircd / m_uping.c
1 /*
2  * IRC - Internet Relay Chat, ircd/m_uping.c
3  * Copyright (C) 1990 Jarkko Oikarinen and
4  *                    University of Oulu, Computing Center
5  *
6  * See file AUTHORS in IRC package for additional names of
7  * the programmers.
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 1, or (at your option)
12  * any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  *
23  * $Id$
24  */
25
26 /*
27  * m_functions execute protocol messages on this server:
28  *
29  *    cptr    is always NON-NULL, pointing to a *LOCAL* client
30  *            structure (with an open socket connected!). This
31  *            identifies the physical socket where the message
32  *            originated (or which caused the m_function to be
33  *            executed--some m_functions may call others...).
34  *
35  *    sptr    is the source of the message, defined by the
36  *            prefix part of the message if present. If not
37  *            or prefix not found, then sptr==cptr.
38  *
39  *            (!IsServer(cptr)) => (cptr == sptr), because
40  *            prefixes are taken *only* from servers...
41  *
42  *            (IsServer(cptr))
43  *                    (sptr == cptr) => the message didn't
44  *                    have the prefix.
45  *
46  *                    (sptr != cptr && IsServer(sptr) means
47  *                    the prefix specified servername. (?)
48  *
49  *                    (sptr != cptr && !IsServer(sptr) means
50  *                    that message originated from a remote
51  *                    user (not local).
52  *
53  *            combining
54  *
55  *            (!IsServer(sptr)) means that, sptr can safely
56  *            taken as defining the target structure of the
57  *            message in this server.
58  *
59  *    *Always* true (if 'parse' and others are working correct):
60  *
61  *    1)      sptr->from == cptr  (note: cptr->from == cptr)
62  *
63  *    2)      MyConnect(sptr) <=> sptr == cptr (e.g. sptr
64  *            *cannot* be a local connection, unless it's
65  *            actually cptr!). [MyConnect(x) should probably
66  *            be defined as (x == x->from) --msa ]
67  *
68  *    parc    number of variable parameter strings (if zero,
69  *            parv is allowed to be NULL)
70  *
71  *    parv    a NULL terminated list of parameter pointers,
72  *
73  *                    parv[0], sender (prefix string), if not present
74  *                            this points to an empty string.
75  *                    parv[1]...parv[parc-1]
76  *                            pointers to additional parameters
77  *                    parv[parc] == NULL, *always*
78  *
79  *            note:   it is guaranteed that parv[0]..parv[parc-1] are all
80  *                    non-NULL pointers.
81  */
82 #if 0
83 /*
84  * No need to include handlers.h here the signatures must match
85  * and we don't need to force a rebuild of all the handlers everytime
86  * we add a new one to the list. --Bleep
87  */
88 #include "handlers.h"
89 #endif /* 0 */
90 #include "client.h"
91 #include "hash.h"
92 #include "ircd.h"
93 #include "ircd_reply.h"
94 #include "ircd_string.h"
95 #include "match.h"
96 #include "msg.h"
97 #include "numeric.h"
98 #include "numnicks.h"
99 #include "s_conf.h"
100 #include "s_user.h"
101 #include "send.h"
102 #include "uping.h"
103
104
105 #include <assert.h>
106 #include <stdlib.h>
107 #include <string.h>
108
109 /*
110  * ms_uping - server message handler
111  *
112  * m_uping  -- by Run
113  *
114  * parv[0] = sender prefix
115  * parv[1] = pinged server
116  * parv[2] = port
117  * parv[3] = hunted server
118  * parv[4] = number of requested pings
119  */
120 int ms_uping(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
121 {
122   struct ConfItem *aconf;
123   int port;
124   int count;
125
126   assert(0 != cptr);
127   assert(0 != sptr);
128
129   if (!IsAnOper(sptr)) {
130     sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
131     return 0;
132   }
133
134   if (parc < 5) {
135     sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "UPING");
136     return 0;
137   }
138
139   if (hunt_server(1, cptr, sptr, "%s%s " TOK_UPING " %s %s %s %s", 3, parc, parv) != HUNTED_ISME)
140     return 0;
141   /*
142    * Determine port: First user supplied, then default : 7007
143    */
144   if (EmptyString(parv[2]) || (port = atoi(parv[2])) <= 0)
145     port = atoi(UDP_PORT);
146
147   if (EmptyString(parv[4]) || (count = atoi(parv[4])) <= 0)
148   {
149     if (MyUser(sptr))
150       sendto_one(sptr, ":%s NOTICE %s :UPING: Illegal number of packets: %s",
151                  me.name, parv[0], parv[4]);
152     else
153       sendto_one(sptr, "%s " TOK_NOTICE " %s%s :UPING: Illegal number of packets: %s",
154                  NumServ(&me), NumNick(sptr), parv[4]);
155     return 0;
156   }
157   /* 
158    * Check if a CONNECT would be possible at all (adapted from m_connect)
159    */
160   if ((aconf = conf_find_server(parv[1])))
161     uping_server(sptr, aconf, port, count);
162   else {
163     if (MyUser(sptr))
164       sendto_one(sptr, ":%s NOTICE %s :UPING: Host %s not listed in ircd.conf",
165                  me.name, parv[0], parv[1]);
166     else
167       sendto_one(sptr, "%s " TOK_NOTICE " %s%s :UPING: Host %s not listed in ircd.conf",
168                  NumServ(&me), NumNick(sptr), parv[1]);
169   }
170   return 0;
171 }
172
173 /*
174  * mo_uping - oper message handler
175  *
176  * m_uping  -- by Run
177  *
178  * parv[0] = sender prefix
179  * parv[1] = pinged server
180  * parv[2] = port
181  * parv[3] = hunted server
182  * parv[4] = number of requested pings
183  */
184 int mo_uping(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
185 {
186   struct ConfItem *aconf;
187   int port;
188   int count;
189
190   assert(0 != cptr);
191   assert(0 != sptr);
192   assert(cptr == sptr);
193
194   assert(IsAnOper(sptr));
195
196   if (parc < 2) {
197     sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "UPING");
198     return 0;
199   }
200
201   if (parc == 2) {
202     parv[parc++] = UDP_PORT;
203     parv[parc++] = me.name;
204     parv[parc++] = "5";
205   }
206   else if (parc == 3) {
207     if (IsDigit(*parv[2]))
208       parv[parc++] = me.name;
209     else {
210       parv[parc++] = parv[2];
211       parv[2] = UDP_PORT;
212     }
213     parv[parc++] = "5";
214   }
215   else if (parc == 4) {
216     if (IsDigit(*parv[2])) {
217       if (IsDigit(*parv[3])) {
218         parv[parc++] = parv[3];
219         parv[3] = me.name;
220       }
221       else
222         parv[parc++] = "5";
223     }
224     else {
225       parv[parc++] = parv[3];
226       parv[3] = parv[2];
227       parv[2] = UDP_PORT;
228     }
229   }
230   if (hunt_server(1, cptr, sptr, "%s%s " TOK_UPING " %s %s %s %s", 3, parc, parv) != HUNTED_ISME)
231     return 0;
232   /*
233    * Determine port: First user supplied, then default : 7007
234    */
235   if (EmptyString(parv[2]) || (port = atoi(parv[2])) <= 0)
236     port = atoi(UDP_PORT);
237
238   if (EmptyString(parv[4]) || (count = atoi(parv[4])) <= 0)
239   {
240     if (MyUser(sptr))
241       sendto_one(sptr, ":%s NOTICE %s :UPING: Illegal number of packets: %s",
242                  me.name, parv[0], parv[4]);
243     else
244       sendto_one(sptr, "%s " TOK_NOTICE " %s%s :UPING: Illegal number of packets: %s",
245                  NumServ(&me), NumNick(sptr), parv[4]);
246     return 0;
247   }
248   /* 
249    * Check if a CONNECT would be possible at all (adapted from m_connect)
250    */
251   if ((aconf = conf_find_server(parv[1])))
252     uping_server(sptr, aconf, port, count);
253   else {
254     if (MyUser(sptr))
255       sendto_one(sptr, ":%s NOTICE %s :UPING: Host %s not listed in ircd.conf",
256                  me.name, parv[0], parv[1]);
257     else
258       sendto_one(sptr, "%s " TOK_NOTICE " %s%s :UPING: Host %s not listed in ircd.conf",
259                  NumServ(&me), NumNick(sptr), parv[1]);
260   }
261   return 0;
262 }
263
264
265 #if 0
266 /*
267  * m_uping  -- by Run
268  *
269  * parv[0] = sender prefix
270  * parv[1] = pinged server
271  * parv[2] = port
272  * parv[3] = hunted server
273  * parv[4] = number of requested pings
274  */
275 int m_uping(struct Client* cptr, struct Client *sptr, int parc, char *parv[])
276 {
277   struct ConfItem *aconf;
278   int port;
279   int fd;
280   struct UPing* pptr = 0;
281
282   if (!IsPrivileged(sptr))
283   {
284     sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
285     return -1;
286   }
287
288   if (parc < 2)
289   {
290     sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "UPING");
291     return 0;
292   }
293
294   if (MyUser(sptr))
295   {
296     if (parc == 2)
297     {
298       parv[parc++] = UDP_PORT;
299       parv[parc++] = me.name;
300       parv[parc++] = "5";
301     }
302     else if (parc == 3)
303     {
304       if (IsDigit(*parv[2]))
305         parv[parc++] = me.name;
306       else
307       {
308         parv[parc++] = parv[2];
309         parv[2] = UDP_PORT;
310       }
311       parv[parc++] = "5";
312     }
313     else if (parc == 4)
314     {
315       if (IsDigit(*parv[2]))
316       {
317         if (IsDigit(*parv[3]))
318         {
319           parv[parc++] = parv[3];
320           parv[3] = me.name;
321         }
322         else
323           parv[parc++] = "5";
324       }
325       else
326       {
327         parv[parc++] = parv[3];
328         parv[3] = parv[2];
329         parv[2] = UDP_PORT;
330       }
331     }
332   }
333   if (hunt_server(1, cptr, sptr, ":%s UPING %s %s %s %s", 3, parc, parv) != HUNTED_ISME)
334     return 0;
335
336   if (BadPtr(parv[4]) || atoi(parv[4]) <= 0)
337   {
338     if (MyUser(sptr) || Protocol(cptr) < 10)
339       sendto_one(sptr, ":%s NOTICE %s :UPING: Illegal number of packets: %s",
340           me.name, parv[0], parv[4]);
341     else
342       sendto_one(sptr, "%s NOTICE %s%s :UPING: Illegal number of packets: %s",
343           NumServ(&me), NumNick(sptr), parv[4]);
344     return 0;
345   }
346
347   /* Check if a CONNECT would be possible at all (adapted from m_connect) */
348   for (aconf = GlobalConfList; aconf; aconf = aconf->next)
349   {
350     if (aconf->status == CONF_SERVER &&
351         match(parv[1], aconf->name) == 0)
352       break;
353   }
354   if (!aconf)
355   {
356     for (aconf = GlobalConfList; aconf; aconf = aconf->next)
357     {
358       if (aconf->status == CONF_SERVER &&
359           (match(parv[1], aconf->host) == 0 ||
360            match(parv[1], strchr(aconf->host, '@') + 1) == 0))
361         break;
362     }
363   }
364   if (!aconf)
365   {
366     if (MyUser(sptr) || Protocol(cptr) < 10)
367       sendto_one(sptr, ":%s NOTICE %s :UPING: Host %s not listed in ircd.conf",
368           me.name, parv[0], parv[1]);
369     else
370       sendto_one(sptr,
371           "%s NOTICE %s%s :UPING: Host %s not listed in ircd.conf",
372           NumServ(&me), NumNick(sptr), parv[1]);
373     return 0;
374   }
375
376   if (IsUPing(sptr))
377     cancel_ping(sptr, sptr);  /* Cancel previous ping request */
378
379   /*
380    * Determine port: First user supplied, then default : 7007
381    */
382   if (BadPtr(parv[2]) || (port = atoi(parv[2])) <= 0)
383     port = atoi(UDP_PORT);
384
385   if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
386     int err = errno;
387     sendto_ops("m_uping: socket: %s", (err != EMFILE) 
388                 ? ((strerror(err)) ? strerror(err) : "Unknown error") : "No more sockets");
389     if (MyUser(sptr) || Protocol(cptr) < 10)
390       sendto_one(sptr, 
391                  ":%s NOTICE %s :UPING: Unable to create udp ping socket",
392                  me.name, parv[0]);
393     else
394       sendto_one(sptr,
395                  "%s NOTICE %s%s :UPING: Unable to create udp ping socket",
396                  NumServ(&me), NumNick(sptr));
397     ircd_log(L_ERROR, "UPING: Unable to create UDP socket");
398     return 0;
399   }
400
401   if (!os_set_nonblocking(fd)) {
402     if (MyUser(sptr) || Protocol(cptr) < 10)
403       sendto_one(sptr, ":%s NOTICE %s :UPING: Can't set fd non-blocking",
404             me.name, parv[0]);
405     else
406       sendto_one(sptr, "%s NOTICE %s%s :UPING: Can't set fd non-blocking",
407             NumServ(&me), NumNick(sptr));
408     close(fd);
409     return 0;
410   }
411   pptr = (struct UPing*) MyMalloc(sizeof(struct UPing));
412   assert(0 != pptr);
413   memset(pptr, 0, sizeof(struct UPing));
414
415   pptr->fd = fd;
416   pptr->sin.sin_port = htons(port);
417   pptr->sin.sin_addr.s_addr = aconf->ipnum.s_addr;
418   pptr->sin.sin_family = AF_INET;
419   pptr->count = IRCD_MIN(20, atoi(parv[4]));
420   strcpy(pptr->name, aconf->host);
421   pptr->client = sptr;
422   pptr->index = -1;
423
424   pptr->next = pingList;
425   pingList = pptr;
426
427   SetUPing(sptr);
428   ping_server(pptr);
429   return 0;
430 }
431 #endif /* 0 */
432