Author: Kev <klmitch@mit.edu>
[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     send_reply(sptr, ERR_NOPRIVILEGES);
131     return 0;
132   }
133
134   if (parc < 5) {
135     send_reply(sptr, ERR_NEEDMOREPARAMS, "UPING");
136     return 0;
137   }
138
139   if (hunt_server_cmd(sptr, CMD_UPING, cptr, 1, "%s %s %C %s", 3, parc, parv)
140       != HUNTED_ISME)
141     return 0;
142   /*
143    * Determine port: First user supplied, then default : 7007
144    */
145   if (EmptyString(parv[2]) || (port = atoi(parv[2])) <= 0)
146     port = atoi(UDP_PORT);
147
148   if (EmptyString(parv[4]) || (count = atoi(parv[4])) <= 0)
149   {
150     sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :UPING : Illegal number of "
151                   "packets: %s", sptr, parv[4]);
152     return 0;
153   }
154   /* 
155    * Check if a CONNECT would be possible at all (adapted from m_connect)
156    */
157   if ((aconf = conf_find_server(parv[1])))
158     uping_server(sptr, aconf, port, count);
159   else
160     sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :UPING: Host %s not listed in "
161                   "ircd.conf", sptr, parv[1]);
162
163   return 0;
164 }
165
166 /*
167  * mo_uping - oper message handler
168  *
169  * m_uping  -- by Run
170  *
171  * parv[0] = sender prefix
172  * parv[1] = pinged server
173  * parv[2] = port
174  * parv[3] = hunted server
175  * parv[4] = number of requested pings
176  */
177 int mo_uping(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
178 {
179   struct ConfItem *aconf;
180   int port;
181   int count;
182
183   assert(0 != cptr);
184   assert(0 != sptr);
185   assert(cptr == sptr);
186
187   assert(IsAnOper(sptr));
188
189   if (parc < 2) {
190     send_reply(sptr, ERR_NEEDMOREPARAMS, "UPING");
191     return 0;
192   }
193
194   if (parc == 2) {
195     parv[parc++] = UDP_PORT;
196     parv[parc++] = me.name;
197     parv[parc++] = "5";
198   }
199   else if (parc == 3) {
200     if (IsDigit(*parv[2]))
201       parv[parc++] = me.name;
202     else {
203       parv[parc++] = parv[2];
204       parv[2] = UDP_PORT;
205     }
206     parv[parc++] = "5";
207   }
208   else if (parc == 4) {
209     if (IsDigit(*parv[2])) {
210       if (IsDigit(*parv[3])) {
211         parv[parc++] = parv[3];
212         parv[3] = me.name;
213       }
214       else
215         parv[parc++] = "5";
216     }
217     else {
218       parv[parc++] = parv[3];
219       parv[3] = parv[2];
220       parv[2] = UDP_PORT;
221     }
222   }
223   if (hunt_server_cmd(sptr, CMD_UPING, sptr, 1, "%s %s %C %s", 3, parc, parv)
224       != HUNTED_ISME)
225     return 0;
226   /*
227    * Determine port: First user supplied, then default : 7007
228    */
229   if (EmptyString(parv[2]) || (port = atoi(parv[2])) <= 0)
230     port = atoi(UDP_PORT);
231
232   if (EmptyString(parv[4]) || (count = atoi(parv[4])) <= 0)
233   {
234     sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :UPING: Illegal number of "
235                   "packets: %s", sptr, parv[4]);
236     return 0;
237   }
238   /* 
239    * Check if a CONNECT would be possible at all (adapted from m_connect)
240    */
241   if ((aconf = conf_find_server(parv[1])))
242     uping_server(sptr, aconf, port, count);
243   else {
244     sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :UPING: Host %s not listed in "
245                   "ircd.conf", sptr, parv[1]);
246   }
247   return 0;
248 }
249
250
251 #if 0
252 /*
253  * m_uping  -- by Run
254  *
255  * parv[0] = sender prefix
256  * parv[1] = pinged server
257  * parv[2] = port
258  * parv[3] = hunted server
259  * parv[4] = number of requested pings
260  */
261 int m_uping(struct Client* cptr, struct Client *sptr, int parc, char *parv[])
262 {
263   struct ConfItem *aconf;
264   int port;
265   int fd;
266   struct UPing* pptr = 0;
267
268   if (!IsPrivileged(sptr))
269   {
270     sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]); /* XXX DEAD */
271     return -1;
272   }
273
274   if (parc < 2)
275   {
276     sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "UPING"); /* XXX DEAD */
277     return 0;
278   }
279
280   if (MyUser(sptr))
281   {
282     if (parc == 2)
283     {
284       parv[parc++] = UDP_PORT;
285       parv[parc++] = me.name;
286       parv[parc++] = "5";
287     }
288     else if (parc == 3)
289     {
290       if (IsDigit(*parv[2]))
291         parv[parc++] = me.name;
292       else
293       {
294         parv[parc++] = parv[2];
295         parv[2] = UDP_PORT;
296       }
297       parv[parc++] = "5";
298     }
299     else if (parc == 4)
300     {
301       if (IsDigit(*parv[2]))
302       {
303         if (IsDigit(*parv[3]))
304         {
305           parv[parc++] = parv[3];
306           parv[3] = me.name;
307         }
308         else
309           parv[parc++] = "5";
310       }
311       else
312       {
313         parv[parc++] = parv[3];
314         parv[3] = parv[2];
315         parv[2] = UDP_PORT;
316       }
317     }
318   }
319   if (hunt_server(1, cptr, sptr, ":%s UPING %s %s %s %s", 3, parc, parv) != HUNTED_ISME) /* XXX DEAD */
320     return 0;
321
322   if (BadPtr(parv[4]) || atoi(parv[4]) <= 0)
323   {
324     if (MyUser(sptr) || Protocol(cptr) < 10)
325       sendto_one(sptr, ":%s NOTICE %s :UPING: Illegal number of packets: %s", /* XXX DEAD */
326           me.name, parv[0], parv[4]);
327     else
328       sendto_one(sptr, "%s NOTICE %s%s :UPING: Illegal number of packets: %s", /* XXX DEAD */
329           NumServ(&me), NumNick(sptr), parv[4]);
330     return 0;
331   }
332
333   /* Check if a CONNECT would be possible at all (adapted from m_connect) */
334   for (aconf = GlobalConfList; aconf; aconf = aconf->next)
335   {
336     if (aconf->status == CONF_SERVER &&
337         match(parv[1], aconf->name) == 0)
338       break;
339   }
340   if (!aconf)
341   {
342     for (aconf = GlobalConfList; aconf; aconf = aconf->next)
343     {
344       if (aconf->status == CONF_SERVER &&
345           (match(parv[1], aconf->host) == 0 ||
346            match(parv[1], strchr(aconf->host, '@') + 1) == 0))
347         break;
348     }
349   }
350   if (!aconf)
351   {
352     if (MyUser(sptr) || Protocol(cptr) < 10)
353       sendto_one(sptr, ":%s NOTICE %s :UPING: Host %s not listed in ircd.conf", /* XXX DEAD */
354           me.name, parv[0], parv[1]);
355     else
356       sendto_one(sptr, /* XXX DEAD */
357           "%s NOTICE %s%s :UPING: Host %s not listed in ircd.conf",
358           NumServ(&me), NumNick(sptr), parv[1]);
359     return 0;
360   }
361
362   if (IsUPing(sptr))
363     cancel_ping(sptr, sptr);  /* Cancel previous ping request */
364
365   /*
366    * Determine port: First user supplied, then default : 7007
367    */
368   if (BadPtr(parv[2]) || (port = atoi(parv[2])) <= 0)
369     port = atoi(UDP_PORT);
370
371   if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
372     int err = errno;
373     sendto_ops("m_uping: socket: %s", (err != EMFILE)  /* XXX DEAD */
374                 ? ((strerror(err)) ? strerror(err) : "Unknown error") : "No more sockets");
375     if (MyUser(sptr) || Protocol(cptr) < 10)
376       sendto_one(sptr,  /* XXX DEAD */
377                  ":%s NOTICE %s :UPING: Unable to create udp ping socket",
378                  me.name, parv[0]);
379     else
380       sendto_one(sptr, /* XXX DEAD */
381                  "%s NOTICE %s%s :UPING: Unable to create udp ping socket",
382                  NumServ(&me), NumNick(sptr));
383     ircd_log(L_ERROR, "UPING: Unable to create UDP socket");
384     return 0;
385   }
386
387   if (!os_set_nonblocking(fd)) {
388     if (MyUser(sptr) || Protocol(cptr) < 10)
389       sendto_one(sptr, ":%s NOTICE %s :UPING: Can't set fd non-blocking", /* XXX DEAD */
390             me.name, parv[0]);
391     else
392       sendto_one(sptr, "%s NOTICE %s%s :UPING: Can't set fd non-blocking", /* XXX DEAD */
393             NumServ(&me), NumNick(sptr));
394     close(fd);
395     return 0;
396   }
397   pptr = (struct UPing*) MyMalloc(sizeof(struct UPing));
398   assert(0 != pptr);
399   memset(pptr, 0, sizeof(struct UPing));
400
401   pptr->fd = fd;
402   pptr->sin.sin_port = htons(port);
403   pptr->sin.sin_addr.s_addr = aconf->ipnum.s_addr;
404   pptr->sin.sin_family = AF_INET;
405   pptr->count = IRCD_MIN(20, atoi(parv[4]));
406   strcpy(pptr->name, aconf->host);
407   pptr->client = sptr;
408   pptr->index = -1;
409
410   pptr->next = pingList;
411   pingList = pptr;
412
413   SetUPing(sptr);
414   ping_server(pptr);
415   return 0;
416 }
417 #endif /* 0 */
418