1 /*
2  *  ircd-ratbox: A slightly useful ircd.
3  *  m_away.c: Negotiates capabilities with a remote server.
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-2012 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_capab.c 27411 2012-12-31 21:20:29Z androsyn $
25  */
26 
27 #include "stdinc.h"
28 #include "struct.h"
29 #include "client.h"
30 #include "match.h"
31 #include "s_serv.h"
32 #include "parse.h"
33 #include "modules.h"
34 
35 static int mr_capab(struct Client *, struct Client *, int, const char **);
36 static int me_gcap(struct Client *, struct Client *, int, const char **);
37 
38 struct Message capab_msgtab = {
39 	"CAPAB", 0, 0, 0, MFLG_SLOW | MFLG_UNREG,
40 	{{mr_capab, 2}, mg_ignore, mg_ignore, mg_ignore, mg_ignore, mg_ignore}
41 };
42 
43 struct Message gcap_msgtab = {
44 	"GCAP", 0, 0, 0, MFLG_SLOW,
45 	{mg_ignore, mg_ignore, mg_ignore, mg_ignore, {me_gcap, 2}, mg_ignore}
46 };
47 
48 mapi_clist_av1 capab_clist[] = { &capab_msgtab, &gcap_msgtab, NULL };
49 
50 DECLARE_MODULE_AV1(capab, NULL, NULL, capab_clist, NULL, NULL, "$Revision: 27411 $");
51 
52 /*
53  * mr_capab - CAPAB message handler
54  *      parv[0] = sender prefix
55  *      parv[1] = space-separated list of capabilities
56  *
57  */
58 static int
mr_capab(struct Client * client_p,struct Client * source_p,int parc,const char * parv[])59 mr_capab(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
60 {
61 	struct Capability *cap;
62 	int i;
63 	char *p;
64 	char *s;
65 
66 	/* ummm, this shouldn't happen. Could argue this should be logged etc. */
67 	if(client_p->localClient == NULL)
68 		return 0;
69 
70 	/* CAP_TS6 is set in PASS, so is valid.. */
71 	if((client_p->localClient->caps & ~CAP_TS6) != 0)
72 	{
73 		exit_client(client_p, client_p, client_p, "CAPAB received twice");
74 		return 0;
75 	}
76 	else
77 		client_p->localClient->caps |= CAP_CAP;
78 
79 	rb_free(client_p->localClient->fullcaps);
80 	client_p->localClient->fullcaps = rb_strdup(parv[1]);
81 
82 	for(i = 1; i < parc; i++)
83 	{
84 		char *t = LOCAL_COPY(parv[i]);
85 		for(s = rb_strtok_r(t, " ", &p); s; s = rb_strtok_r(NULL, " ", &p))
86 		{
87 			for(cap = captab; cap->name; cap++)
88 			{
89 				if(!irccmp(cap->name, s))
90 				{
91 					client_p->localClient->caps |= cap->cap;
92 					break;
93 				}
94 			}
95 		}
96 	}
97 
98 	return 0;
99 }
100 
101 static int
me_gcap(struct Client * client_p,struct Client * source_p,int parc,const char * parv[])102 me_gcap(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
103 {
104 	struct Capability *cap;
105 	char *t = LOCAL_COPY(parv[1]);
106 	char *s;
107 	char *p;
108 
109 	if(!IsServer(source_p))
110 		return 0;
111 
112 	/* already had GCAPAB?! */
113 	if(!EmptyString(source_p->serv->fullcaps))
114 		return 0;
115 
116 	source_p->serv->fullcaps = rb_strdup(parv[1]);
117 
118 	for(s = rb_strtok_r(t, " ", &p); s; s = rb_strtok_r(NULL, " ", &p))
119 	{
120 		for(cap = captab; cap->name; cap++)
121 		{
122 			if(!irccmp(cap->name, s))
123 			{
124 				source_p->serv->caps |= cap->cap;
125 				break;
126 			}
127 		}
128 	}
129 
130 	return 0;
131 }
132