1 /*
2  *  ircd-ratbox: A slightly useful ircd.
3  *  m_version.c: Shows ircd version information.
4  *
5  *  Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
6  *  Copyright (C) 1996-2002 Hybrid Development Team
7  *  Copyright (C) 2002-2005 ircd-ratbox development team
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 2 of the License, or
12  *  (at your option) 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
22  *  USA
23  *
24  *  $Id: m_version.c 26357 2008-12-22 21:18:30Z androsyn $
25  */
26 
27 #include "stdinc.h"
28 #include "struct.h"
29 #include "client.h"
30 #include "ircd.h"
31 #include "numeric.h"
32 #include "s_conf.h"
33 #include "s_serv.h"
34 #include "supported.h"
35 #include "send.h"
36 #include "parse.h"
37 #include "modules.h"
38 
39 static char *confopts(void);
40 
41 static int m_version(struct Client *, struct Client *, int, const char **);
42 static int mo_version(struct Client *, struct Client *, int, const char **);
43 
44 struct Message version_msgtab = {
45 	"VERSION", 0, 0, 0, MFLG_SLOW,
46 	{mg_unreg, {m_version, 0}, {mo_version, 0}, {mo_version, 0}, mg_ignore, {mo_version, 0}}
47 };
48 
49 mapi_clist_av1 version_clist[] = { &version_msgtab, NULL };
50 
51 DECLARE_MODULE_AV1(version, NULL, NULL, version_clist, NULL, NULL, "$Revision: 26357 $");
52 
53 /*
54  * m_version - VERSION command handler
55  *      parv[0] = sender prefix
56  *      parv[1] = remote server
57  */
58 static int
m_version(struct Client * client_p,struct Client * source_p,int parc,const char * parv[])59 m_version(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
60 {
61 	static time_t last_used = 0L;
62 	if(parc > 1)
63 	{
64 		if((last_used + ConfigFileEntry.pace_wait) > rb_current_time())
65 		{
66 			/* safe enough to give this on a local connect only */
67 			sendto_one(source_p, form_str(RPL_LOAD2HI),
68 				   me.name, source_p->name, "VERSION");
69 			return 0;
70 		}
71 		else
72 			last_used = rb_current_time();
73 
74 		if(hunt_server(client_p, source_p, ":%s VERSION :%s", 1, parc, parv) != HUNTED_ISME)
75 			return 0;
76 	}
77 	sendto_one_numeric(source_p, RPL_VERSION, form_str(RPL_VERSION),
78 			   ircd_version, serno, me.name, confopts(), TS_CURRENT, ServerInfo.sid);
79 
80 	show_isupport(source_p);
81 
82 	return 0;
83 }
84 
85 /*
86  * mo_version - VERSION command handler
87  *      parv[0] = sender prefix
88  *      parv[1] = remote server
89  */
90 static int
mo_version(struct Client * client_p,struct Client * source_p,int parc,const char * parv[])91 mo_version(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
92 {
93 	if(hunt_server(client_p, source_p, ":%s VERSION :%s", 1, parc, parv) == HUNTED_ISME)
94 	{
95 		sendto_one_numeric(source_p, RPL_VERSION, form_str(RPL_VERSION),
96 				   ircd_version, serno,
97 				   me.name, confopts(), TS_CURRENT, ServerInfo.sid);
98 		show_isupport(source_p);
99 	}
100 
101 	return 0;
102 }
103 
104 /* confopts()
105  * input  -
106  * output - ircd.conf option string
107  * side effects - none
108  */
109 static char *
confopts(void)110 confopts(void)
111 {
112 	static char result[15];
113 	char *p;
114 
115 	result[0] = '\0';
116 	p = result;
117 
118 	if(ConfigChannel.use_except)
119 		*p++ = 'e';
120 
121 	if(ConfigFileEntry.glines)
122 		*p++ = 'g';
123 	*p++ = 'G';
124 
125 	/* might wanna hide this :P */
126 	if(ServerInfo.hub)
127 		*p++ = 'H';
128 
129 	if(ConfigChannel.use_invex)
130 		*p++ = 'I';
131 
132 	if(ConfigChannel.use_knock)
133 		*p++ = 'K';
134 
135 	*p++ = 'M';
136 	*p++ = 'p';
137 
138 #ifdef HAVE_ZLIB
139 	*p++ = 'Z';
140 #endif
141 
142 #ifdef RB_IPV6
143 	*p++ = '6';
144 #endif
145 
146 	*p = '\0';
147 
148 	return result;
149 }
150