added some files
[NextIRCd.git] / src / ircd_parse.c
1 /* ircd_client.c - NextIRCd
2  * Copyright (C) 2012-2013  Philipp Kreil (pk910)
3  * 
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  * 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  * 
14  * You should have received a copy of the GNU General Public License 
15  * along with this program. If not, see <http://www.gnu.org/licenses/>. 
16  */
17
18 #include "tools.h"
19 #include "IOHandler/IOSockets.h"
20
21 typedef int cmd_client_t(struct Client *client, char *argv[], int argc);
22 typedef int cmd_auth_t(struct Auth *auth, char *argv[], int argc);
23 typedef int cmd_server_t(struct Server *server, char *argv[], int argc);
24
25 static struct ServerMsg parse_static_srvmsg;
26
27 #define PARSE_CLIFLAG_OPONLY 0x01
28
29 //include all commands
30 #include "cmd_ping.h"
31
32
33 struct {
34         struct {
35                 const char *client;
36                 const char *server;
37         } tokens;
38         struct {
39                 cmd_client_t *function;
40                 unsigned int min_argc : 8;
41                 unsigned int max_argc : 8;
42                 unsigned int flags : 8;
43         } client;
44         struct {
45                 cmd_auth_t *function;
46                 unsigned int min_argc : 8;
47                 unsigned int max_argc : 8;
48                 unsigned int flags : 8;
49         } auth;
50         struct {
51                 cmd_server_t *function;
52                 unsigned int min_argc : 8;
53                 unsigned int max_argc : 8;
54                 unsigned int flags : 8;
55         } server;
56         
57 } parse_command_list {
58         {{"PING", "P"}, /* Ping Command */
59                 {NULL, 0, 1, 0}, /* Client */
60                 {NULL, 0, 1, 0}, /* Unauthed */
61                 {NULL, 0, 1, 0}  /* Server */
62         },
63         {{"PASS", NULL}, /* PASS Command */
64                 {NULL, 0, 1, 0}, /* Client */
65                 {NULL, 0, 1, 0}, /* Unauthed */
66                 {NULL, 0, 1, 0}  /* Server */
67         },
68         {{"NICK", "N"}, /* Nick Command */
69                 {cmd_nick_cli, 0, 1, 0}, /* Client */
70                 {cmd_nick_auth, 0, 1, 0}, /* Unauthed */
71                 {NULL, 0, 1, 0}  /* Server */
72         },
73         {{"USER", "U"}, /* User Command */
74                 {NULL, 0, 1, 0}, /* Client */
75                 {NULL, 0, 1, 0}, /* Unauthed */
76                 {NULL, 0, 1, 0}  /* Server */
77         },
78         
79         {{NULL, NULL},{NULL, 0, 0, 0},{NULL, 0, 0, 0},{NULL, 0, 0, 0}}
80 };
81
82 static char *parse_irc_token(char **data) {
83         //find next " "
84         int i;
85         char *token = *data;
86         for(i = 0; *data[i]; i++) {
87                 if(*data[i] != ' ') {
88                         *data[i] = '\0';
89                         *data += i+1;
90                         break;
91                 }
92         }
93         return token;
94 }
95
96 static char **parse_irc_params(char *data, int *argc, int maxargs) {
97         if(maxargs == 0) {
98                 *argc = 0;
99                 return NULL;
100         }
101     char **argv = calloc(maxargs, sizeof(*argv));
102     while(*data) {
103         //skip leading spaces
104         while (*line == ' ')
105             *line++ = 0;
106         if (*line == ':') {
107            //the rest is a single parameter
108            argv[*argc++] = line + 1;
109            break;
110         }
111         argv[*argc++] = line;
112         if (argc >= maxargs)
113             break;
114         while (*line != ' ' && *line)
115             line++;
116     }
117     return argv;
118 }
119
120 /* Client Data Format
121 * <TOKEN> <arg1> <arg2>
122 */
123 void parse_client_data(struct Client *client, char *data) {
124     char *token = parse_irc_token(&data);
125         int found = 0;
126         int i;
127         for(i = 0; (parse_command_list[i].tokens.client ||  parse_command_list[i].tokens.server); i++) {
128                 if(stricmp(parse_command_list[i].tokens.client, token)) {
129                         found = 1;
130                         break;
131                 }
132         }
133         if(found && !parse_command_list[i].client.function) {
134                 // reply 462 You may not reregister
135         } else if(found) {
136                 int argc;
137                 char **argv = parse_irc_params(data, &argc, parse_command_list[i].client.max_argc);
138                 if(argc < parse_command_list[i].client.min_argc) {
139                         // reply 461 Not enough parameters
140                 } else {
141                         int ret = parse_command_list[i].client.function(client, argv, argc);
142                         if(ret) {
143                                 // error occurred!
144                                 // do something?
145                         }
146                 }
147                 free(argv);
148         } else {
149                 // reply 421 Unknown command
150         }
151 }
152
153 void parse_unauth_data(struct Auth *auth, char *data) {
154         char *token = parse_irc_token(&data);
155         int found = 0;
156         int i;
157         for(i = 0; (parse_command_list[i].tokens.client ||  parse_command_list[i].tokens.server); i++) {
158                 if(stricmp(parse_command_list[i].tokens.client, token)) {
159                         found = 1;
160                         break;
161                 }
162         }
163         if(found && !parse_command_list[i].auth.function) {
164                 // reply 451 Register first.
165         } else if(found) {
166                 int argc;
167                 char **argv = parse_irc_params(data, &argc, parse_command_list[i].auth.max_argc);
168                 if(argc < parse_command_list[i].auth.min_argc) {
169                         // reply 461 Not enough parameters
170                 } else {
171                         int ret = parse_command_list[i].auth.function(auth, argv, argc);
172                         if(ret) {
173                                 // error occurred!
174                                 // do something?
175                         }
176                 }
177                 free(argv);
178         } else {
179                 // reply 421 Unknown command
180         }
181 }
182
183 /* Unicast                  Multicast                 Broadcast
184 * <src-srvnum> 4 Bytes      <source>     4 Bytes      <source>     4 Bytes
185 * <length>     2 Bytes      <length>     2 Bytes      <length>     2 Bytes
186 * <flags>      1 Byte       <flags>      1 Byte       <flags>      1 Byte
187 * <token>      x Bytes      <token>      x Bytes      <token>      x Bytes
188 * " "          1 Byte       " "          1 Byte       " "          1 Byte
189 * <dst-srvnum> 4 Bytes      <servers>    1 Byte       <ttl>        1 Byte
190 *                           <dst-srv01>  4 Bytes      
191 *                           <dst-srv02>  4 Bytes      
192 * <args>                    <args>                    <args>
193 */
194 void parse_server_data(struct Server *server, struct IOSocketBuffer *buffer) {
195         struct ServerMsg *srvmsg = &parse_static_srvmsg;
196         unsigned char *buf = (unsigned char *)buffer->buffer;
197         unsigned int buflen, require_more = 0;
198         int i;
199         
200         while(buffer->bufpos >= 9 && !require_more) { //require at least 9 Bytes
201                 srvmsg->source.srvnum = ((buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]);
202                 srvmsg->resolved_source = 0;
203                 srvmsg->msglen = ((buf[4] << 8) | buf[5]);
204                 srvmsg->msgflags = buf[6];
205                 srvmsg->msgtype  = (buf[6] & SERVERMSG_TYPEMASK);
206                 
207                 if(buffer->bufpos < srvmsg->msglen) {
208                         require_more = 1;
209                         break;
210                 }
211                 
212                 for(i = 0; buffer->bufpos > i+7; i++) {
213                         if(buf[i+7] == ' ') {
214                                 if(i >= MAXSERVERTOKENLEN)
215                                         srvmsg->token[MAXSERVERTOKENLEN] = '\0';
216                                 else
217                                         srvmsg->token[i] = '\0';
218                                 break;
219                         }
220                         if(i >= MAXSERVERTOKENLEN)
221                                 continue;
222                         srvmsg->token[i] = buf[i+7];
223                 }
224                 if(buf[i+7] != ' ') {
225                         require_more = 1;
226                         break;
227                 }
228                 buf += i+8;
229                 buflen = buffer->bufpos - (i+8);
230                 
231                 switch(srvmsg->msgtype) {
232                 case SERVERMSG_TYPE_UNICAST:
233                         if(buflen < 4) {
234                                 require_more = 1;
235                                 break;
236                         }
237                         srvmsg->destinations = malloc(sizeof(struct ServerMsgDstMap));
238                         srvmsg->destinations->dstcount = 1;
239                         srvmsg->destinations->dst[0].destination.srvnum = ((buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]);
240                         srvmsg->destinations->dst[0].destination.resolved_destination = 0;
241                         break;
242                 case SERVERMSG_TYPE_MULTICAST:
243                         if(buflen < 5) {
244                                 require_more = 1;
245                                 break;
246                         }
247                         unsigned int srvcount = buf[0];
248                         buf++;
249                         buflen--;
250                         if(buflen < (srvcount * 4)) {
251                                 require_more = 1;
252                                 break;
253                         }
254                         srvmsg->destinations = malloc(sizeof(struct ServerMsgDstMap) + (sizeof(struct ServerMsgDestination) * (srvcount - 1)));
255                         srvmsg->destinations->dstcount = srvcount;
256                         for(i = 0; i < srvcount; i++) {
257                                 srvmsg->destinations->dst[i].destination.srvnum = ((buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]);
258                                 srvmsg->destinations->dst[i].destination.resolved_destination = 0;
259                                 buf += 4;
260                                 buflen -= 4;
261                         }
262                         break;
263                 case SERVERMSG_TYPE_BROADCAST:
264                         if(buflen == 0) {
265                                 require_more = 1;
266                                 break;
267                         }
268                         srvmsg->destinations = NULL;
269                         srvmsg->msgttl = buf[0];
270                         buf++;
271                         buflen--;
272                         break;
273                 default:
274                         // PARSE ERROR
275                         goto parse_server_data_finish;
276                 }
277                 
278                 srvmsg->arglen = srvmsg->msglen - (buf - buffer->buffer);
279                 srvmsg->args = buf;
280                 
281                 int found = 0;
282                 for(i = 0; (parse_command_list[i].tokens.client ||  parse_command_list[i].tokens.server); i++) {
283                         if(stricmp(parse_command_list[i].tokens.server, srvmsg->token)) {
284                                 found = 1;
285                                 break;
286                         }
287                 }
288                 if(!found)
289                         goto parse_server_data_finish;
290                 
291                 //exec command function
292                 
293         
294                 parse_server_data_finish:
295                 if(srvmsg->destinations)
296                         free(srvmsg->destinations);
297                 
298                 if(srvmsg->msglen > buffer->bufpos) {
299                         memmove(buffer->buffer, buffer->buffer + srvmsg->msglen, srvmsg->msglen - buffer->bufpos);
300                         buffer->bufpos -= srvmsg->msglen;
301                 } else 
302                         srvmsg->bufpos = 0;
303         }
304 }
305