]> andersk Git - libfaim.git/blame - src/rxhandlers.c
Nod.
[libfaim.git] / src / rxhandlers.c
CommitLineData
9de3ca7e 1/*
24286d93 2 * aim_rxhandlers.c
3 *
4 * This file contains most all of the incoming packet handlers, along
5 * with aim_rxdispatch(), the Rx dispatcher. Queue/list management is
6 * actually done in aim_rxqueue.c.
7 *
9de3ca7e 8 */
9
37ee990e 10#define FAIM_INTERNAL
dd60ff8b 11#include <aim.h>
9de3ca7e 12
24286d93 13/*
14 * Bleck functions get called when there's no non-bleck functions
15 * around to cleanup the mess...
16 */
78b3fb13 17faim_internal int bleck(struct aim_session_t *sess,struct command_rx_struct *workingPtr, ...)
9de3ca7e 18{
19 u_short family;
20 u_short subtype;
01b59e1e 21
22 u_short maxf;
23 u_short maxs;
24
25 /* XXX: this is ugly. and big just for debugging. */
26 char *literals[14][25] = {
27 {"Invalid",
28 NULL
29 },
30 {"General",
31 "Invalid",
32 "Error",
33 "Client Ready",
34 "Server Ready",
35 "Service Request",
36 "Redirect",
37 "Rate Information Request",
38 "Rate Information",
39 "Rate Information Ack",
40 NULL,
41 "Rate Information Change",
42 "Server Pause",
43 NULL,
44 "Server Resume",
45 "Request Personal User Information",
46 "Personal User Information",
47 "Evil Notification",
48 NULL,
49 "Migration notice",
50 "Message of the Day",
51 "Set Privacy Flags",
52 "Well Known URL",
53 "NOP"
54 },
55 {"Location",
56 "Invalid",
57 "Error",
58 "Request Rights",
59 "Rights Information",
60 "Set user information",
61 "Request User Information",
62 "User Information",
63 "Watcher Sub Request",
64 "Watcher Notification"
65 },
66 {"Buddy List Management",
67 "Invalid",
68 "Error",
69 "Request Rights",
70 "Rights Information",
71 "Add Buddy",
72 "Remove Buddy",
73 "Watcher List Query",
74 "Watcher List Response",
75 "Watcher SubRequest",
76 "Watcher Notification",
77 "Reject Notification",
78 "Oncoming Buddy",
79 "Offgoing Buddy"
80 },
81 {"Messeging",
82 "Invalid",
83 "Error",
84 "Add ICBM Parameter",
85 "Remove ICBM Parameter",
86 "Request Parameter Information",
87 "Parameter Information",
88 "Outgoing Message",
89 "Incoming Message",
90 "Evil Request",
91 "Evil Reply",
92 "Missed Calls",
93 "Message Error",
94 "Host Ack"
95 },
96 {"Advertisements",
97 "Invalid",
98 "Error",
99 "Request Ad",
100 "Ad Data (GIFs)"
101 },
102 {"Invitation / Client-to-Client",
103 "Invalid",
104 "Error",
105 "Invite a Friend",
106 "Invitation Ack"
107 },
108 {"Administrative",
109 "Invalid",
110 "Error",
111 "Information Request",
112 "Information Reply",
113 "Information Change Request",
114 "Information Chat Reply",
115 "Account Confirm Request",
116 "Account Confirm Reply",
117 "Account Delete Request",
118 "Account Delete Reply"
119 },
120 {"Popups",
121 "Invalid",
122 "Error",
123 "Display Popup"
124 },
125 {"BOS",
126 "Invalid",
127 "Error",
128 "Request Rights",
129 "Rights Response",
130 "Set group permission mask",
131 "Add permission list entries",
132 "Delete permission list entries",
133 "Add deny list entries",
134 "Delete deny list entries",
135 "Server Error"
136 },
137 {"User Lookup",
138 "Invalid",
139 "Error",
140 "Search Request",
141 "Search Response"
142 },
143 {"Stats",
144 "Invalid",
145 "Error",
146 "Set minimum report interval",
147 "Report Events"
148 },
149 {"Translate",
150 "Invalid",
151 "Error",
152 "Translate Request",
153 "Translate Reply",
154 },
155 {"Chat Navigation",
156 "Invalid",
157 "Error",
158 "Request rights",
159 "Request Exchange Information",
160 "Request Room Information",
161 "Request Occupant List",
162 "Search for Room",
163 "Outgoing Message",
164 "Incoming Message",
165 "Evil Request",
166 "Evil Reply",
167 "Chat Error",
168 }
169 };
170
171 maxf = sizeof(literals) / sizeof(literals[0]);
172 maxs = sizeof(literals[0]) / sizeof(literals[0][0]);
173
174 family = aimutil_get16(workingPtr->data+0);
175 subtype= aimutil_get16(workingPtr->data+2);
176
177 if((family < maxf) && (subtype+1 < maxs) && (literals[family][subtype] != NULL))
646c6b52 178 faimdprintf(sess, 0, "bleck: null handler for %04x/%04x (%s)\n", family, subtype, literals[family][subtype+1]);
01b59e1e 179 else
646c6b52 180 faimdprintf(sess, 0, "bleck: null handler for %04x/%04x (no literal)\n",family,subtype);
01b59e1e 181
9de3ca7e 182 return 1;
183}
184
78b3fb13 185faim_export int aim_conn_addhandler(struct aim_session_t *sess,
a25832e6 186 struct aim_conn_t *conn,
9de3ca7e 187 u_short family,
188 u_short type,
189 rxcallback_t newhandler,
190 u_short flags)
191{
871e2fd0 192 struct aim_rxcblist_t *newcb;
9de3ca7e 193
194 if (!conn)
195 return -1;
196
646c6b52 197 faimdprintf(sess, 1, "aim_conn_addhandler: adding for %04x/%04x\n", family, type);
9de3ca7e 198
871e2fd0 199 if (!(newcb = (struct aim_rxcblist_t *)calloc(1, sizeof(struct aim_rxcblist_t))))
200 return -1;
a15d82b1 201 newcb->family = family;
202 newcb->type = type;
203 newcb->flags = flags;
9de3ca7e 204 if (!newhandler)
a15d82b1 205 newcb->handler = &bleck;
9de3ca7e 206 else
a15d82b1 207 newcb->handler = newhandler;
208 newcb->next = NULL;
9de3ca7e 209
871e2fd0 210 if (!conn->handlerlist)
a15d82b1 211 conn->handlerlist = newcb;
871e2fd0 212 else {
213 struct aim_rxcblist_t *cur;
214
215 cur = conn->handlerlist;
216
217 while (cur->next)
218 cur = cur->next;
219 cur->next = newcb;
220 }
9de3ca7e 221
222 return 0;
223}
224
78b3fb13 225faim_export int aim_clearhandlers(struct aim_conn_t *conn)
9de3ca7e 226{
871e2fd0 227 struct aim_rxcblist_t *cur;
228
9de3ca7e 229 if (!conn)
230 return -1;
231
55e77c8a 232 for (cur = conn->handlerlist; cur; ) {
871e2fd0 233 struct aim_rxcblist_t *tmp;
234
235 tmp = cur->next;
236 free(cur);
237 cur = tmp;
238 }
55e77c8a 239 conn->handlerlist = NULL;
871e2fd0 240
9de3ca7e 241 return 0;
242}
243
646c6b52 244faim_internal rxcallback_t aim_callhandler(struct aim_session_t *sess,
245 struct aim_conn_t *conn,
246 unsigned short family,
247 unsigned short type)
9de3ca7e 248{
249 struct aim_rxcblist_t *cur;
250
251 if (!conn)
252 return NULL;
253
646c6b52 254 faimdprintf(sess, 1, "aim_callhandler: calling for %04x/%04x\n", family, type);
9de3ca7e 255
646c6b52 256 for (cur = conn->handlerlist; cur; cur = cur->next) {
257 if ((cur->family == family) && (cur->type == type))
258 return cur->handler;
259 }
9de3ca7e 260
646c6b52 261 if (type == AIM_CB_SPECIAL_DEFAULT) {
262 faimdprintf(sess, 1, "aim_callhandler: no default handler for family 0x%04x\n", family);
263 return NULL; /* prevent infinite recursion */
264 }
265
266 faimdprintf(sess, 1, "aim_callhandler: no handler for 0x%04x/0x%04x\n", family, type);
871e2fd0 267
646c6b52 268 return aim_callhandler(sess, conn, family, AIM_CB_SPECIAL_DEFAULT);
9de3ca7e 269}
270
78b3fb13 271faim_internal int aim_callhandler_noparam(struct aim_session_t *sess,
272 struct aim_conn_t *conn,
273 u_short family,
274 u_short type,
275 struct command_rx_struct *ptr)
9de3ca7e 276{
277 rxcallback_t userfunc = NULL;
646c6b52 278 userfunc = aim_callhandler(sess, conn, family, type);
9de3ca7e 279 if (userfunc)
a25832e6 280 return userfunc(sess, ptr);
b8d0da45 281 return 1; /* XXX */
9de3ca7e 282}
283
284/*
285 aim_rxdispatch()
286
287 Basically, heres what this should do:
288 1) Determine correct packet handler for this packet
289 2) Mark the packet handled (so it can be dequeued in purge_queue())
290 3) Send the packet to the packet handler
291 4) Go to next packet in the queue and start over
292 5) When done, run purge_queue() to purge handled commands
293
294 Note that any unhandlable packets should probably be left in the
295 queue. This is the best way to prevent data loss. This means
296 that a single packet may get looked at by this function multiple
297 times. This is more good than bad! This behavior may change.
298
299 Aren't queue's fun?
300
301 TODO: Get rid of all the ugly if's.
302 TODO: Clean up.
303 TODO: More support for mid-level handlers.
304 TODO: Allow for NULL handlers.
305
306 */
78b3fb13 307faim_export int aim_rxdispatch(struct aim_session_t *sess)
9de3ca7e 308{
309 int i = 0;
310 struct command_rx_struct *workingPtr = NULL;
311
b8d0da45 312 if (sess->queue_incoming == NULL) {
646c6b52 313 faimdprintf(sess, 1, "parse_generic: incoming packet queue empty.\n");
b8d0da45 314 return 0;
315 } else {
316 workingPtr = sess->queue_incoming;
50443ea0 317 for (i = 0; workingPtr != NULL; workingPtr = workingPtr->next, i++) {
bb010ae0 318 unsigned short family,subtype;
319
b8d0da45 320 /*
321 * XXX: This is still fairly ugly.
322 */
50443ea0 323 if (workingPtr->handled)
324 continue;
325
b69540e3 326 /*
327 * This is a debugging/sanity check only and probably could/should be removed
328 * for stable code.
329 */
330 if (((workingPtr->hdrtype == AIM_FRAMETYPE_OFT) &&
331 (workingPtr->conn->type != AIM_CONN_TYPE_RENDEZVOUS)) ||
332 ((workingPtr->hdrtype == AIM_FRAMETYPE_OSCAR) &&
333 (workingPtr->conn->type == AIM_CONN_TYPE_RENDEZVOUS))) {
646c6b52 334 faimdprintf(sess, 0, "rxhandlers: incompatible frame type %d on connection type 0x%04x\n", workingPtr->hdrtype, workingPtr->conn->type);
b69540e3 335 workingPtr->handled = 1;
336 continue;
337 }
338
bb010ae0 339 if (workingPtr->conn->type == AIM_CONN_TYPE_RENDEZVOUS) {
340 /* make sure that we only get OFT frames on these connections */
341 if (workingPtr->hdrtype != AIM_FRAMETYPE_OFT) {
342 faimdprintf(sess, 0, "internal error: non-OFT frames on OFT connection\n");
343 workingPtr->handled = 1; /* get rid of it */
344 } else {
345 /* XXX: implement this */
346 faimdprintf(sess, 0, "faim: OFT frame!\n");
347 workingPtr->handled = 1; /* get rid of it */
b8d0da45 348 }
bb010ae0 349 continue;
b8d0da45 350 }
5e02cf44 351
bb010ae0 352 if (workingPtr->conn->type == AIM_CONN_TYPE_RENDEZVOUS_OUT) {
353 /* not possible */
354 faimdprintf(sess, 0, "rxdispatch called on RENDEZVOUS_OUT connection!\n");
355 workingPtr->handled = 1;
356 continue;
357 }
5e02cf44 358
bb010ae0 359 if ((workingPtr->commandlen == 4) &&
360 (aimutil_get32(workingPtr->data) == 0x00000001)) {
361 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, workingPtr);
362 continue;
363 }
64c78745 364
bb010ae0 365 if (workingPtr->hdr.oscar.type == 0x04) {
366 workingPtr->handled = aim_negchan_middle(sess, workingPtr);
367 continue;
368 }
369
370 family = aimutil_get16(workingPtr->data);
371 subtype = aimutil_get16(workingPtr->data+2);
372
373 if (family == 0x0001) {
64c78745 374
bb010ae0 375 if (subtype == 0x0001)
376 workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
377 else if (subtype == 0x0003)
64c78745 378 workingPtr->handled = aim_parse_hostonline(sess, workingPtr);
bb010ae0 379 else if (subtype == 0x0005)
380 workingPtr->handled = aim_handleredirect_middle(sess, workingPtr);
381 else if (subtype == 0x0007)
382 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0007, workingPtr);
383 else if (subtype == 0x000a)
384 workingPtr->handled = aim_parse_ratechange_middle(sess, workingPtr);
385 else if (subtype == 0x000f)
386 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x000f, workingPtr);
387 else if (subtype == 0x0010)
388 workingPtr->handled = aim_parse_evilnotify_middle(sess, workingPtr);
389 else if (subtype == 0x0013)
390 workingPtr->handled = aim_parsemotd_middle(sess, workingPtr);
391 else if (subtype == 0x0018)
392 workingPtr->handled = aim_parse_hostversions(sess, workingPtr);
393 else
394 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0xffff, workingPtr);
395
396 } else if (family == 0x0002) {
397
398 if (subtype == 0x0001)
399 workingPtr->handled = aim_parse_locateerr(sess, workingPtr);
400 else if (subtype == 0x0003)
401 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0002, 0x0003, workingPtr);
402 else if (subtype == 0x0006)
403 workingPtr->handled = aim_parse_userinfo_middle(sess, workingPtr);
404 else
405 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_LOC, AIM_CB_LOC_DEFAULT, workingPtr);
406
407 } else if (family == 0x0003) {
408
409 if (subtype == 0x0001)
410 workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
411 else if (subtype == 0x0003)
412 workingPtr->handled = aim_parse_buddyrights(sess, workingPtr);
413 else if (subtype == 0x000b)
414 workingPtr->handled = aim_parse_oncoming_middle(sess, workingPtr);
415 else if (subtype == 0x000c)
416 workingPtr->handled = aim_parse_offgoing_middle(sess, workingPtr);
417 else
418 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_BUD, AIM_CB_BUD_DEFAULT, workingPtr);
419
420 } else if (family == 0x0004) {
421
422 if (subtype == 0x0001)
423 workingPtr->handled = aim_parse_msgerror_middle(sess, workingPtr);
424 else if (subtype == 0x0005)
425 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0004, 0x0005, workingPtr);
426 else if (subtype == 0x0006)
427 workingPtr->handled = aim_parse_outgoing_im_middle(sess, workingPtr);
428 else if (subtype == 0x0007)
429 workingPtr->handled = aim_parse_incoming_im_middle(sess, workingPtr);
430 else if (subtype == 0x000a)
431 workingPtr->handled = aim_parse_missedcall(sess, workingPtr);
432 else if (subtype == 0x000c)
433 workingPtr->handled = aim_parse_msgack_middle(sess, workingPtr);
434 else
435 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_MSG, AIM_CB_MSG_DEFAULT, workingPtr);
436
437 } else if (family == 0x0007) {
438
439 if (subtype == 0x0003)
440 workingPtr->handled = aim_parse_infochange(sess, workingPtr);
441 else if (subtype == 0x0005)
442 workingPtr->handled = aim_parse_infochange(sess, workingPtr);
443 else if (subtype == 0x0007)
444 workingPtr->handled = aim_parse_accountconfirm(sess, workingPtr);
64c78745 445 break;
bb010ae0 446
447 } else if (family == 0x0009) {
448
449 if (subtype == 0x0001)
450 workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
451 else if (subtype == 0x0003)
452 workingPtr->handled = aim_parse_bosrights(sess, workingPtr);
453 else
454 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_BOS, AIM_CB_BOS_DEFAULT, workingPtr);
455
456 } else if (family == 0x000a) {
457
458 if (subtype == 0x0001)
459 workingPtr->handled = aim_parse_searcherror(sess, workingPtr);
460 else if (subtype == 0x0003)
461 workingPtr->handled = aim_parse_searchreply(sess, workingPtr);
462 else
463 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_LOK, AIM_CB_LOK_DEFAULT, workingPtr);
464
465 } else if (family == 0x000b) {
466
467 if (subtype == 0x0001)
468 workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
469 else if (subtype == 0x0002)
470 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x000b, 0x0002, workingPtr);
471 else
472 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_STS, AIM_CB_STS_DEFAULT, workingPtr);
473
474 } else if (family == 0x000d) {
475
476 if (subtype == 0x0009)
b8d0da45 477 workingPtr->handled = aim_chatnav_parse_info(sess, workingPtr);
bb010ae0 478
479 } else if (family == 0x000e) {
480
481 if (subtype == 0x0002)
482 workingPtr->handled = aim_chat_parse_infoupdate(sess, workingPtr);
483 else if (subtype == 0x0003)
484 workingPtr->handled = aim_chat_parse_joined(sess, workingPtr);
485 else if (subtype == 0x0004)
486 workingPtr->handled = aim_chat_parse_leave(sess, workingPtr);
487 else if (subtype == 0x0006)
488 workingPtr->handled = aim_chat_parse_incoming(sess, workingPtr);
489
490 } else if (family == 0x0013) {
491
492 faimdprintf(sess, 0, "lalala: 0x%04x/0x%04x\n", family, subtype);
493
494 } else if (family == 0x0017) { /* New login protocol */
495
496 if (subtype == 0x0001)
497 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0017, 0x0001, workingPtr);
498 else if (subtype == 0x0003)
499 workingPtr->handled = aim_authparse(sess, workingPtr);
500 else if (subtype == 0x0007)
501 workingPtr->handled = aim_authkeyparse(sess, workingPtr);
502 else
503 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0017, 0xffff, workingPtr);
504
505 } else if (family == AIM_CB_FAM_SPECIAL) {
506
507 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, family, subtype, workingPtr);
508
7392c79f 509 }
64f46cec 510
511 /* Try it raw and see if we can get it to happen... */
512 if (!workingPtr->handled) /* XXX this is probably bad. */
513 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, family, subtype, workingPtr);
514
9de3ca7e 515 }
b8d0da45 516 }
9de3ca7e 517
b8d0da45 518 /*
519 * This doesn't have to be called here. It could easily be done
520 * by a seperate thread or something. It's an administrative operation,
521 * and can take a while. Though the less you call it the less memory
522 * you'll have :)
523 */
524 aim_purge_rxqueue(sess);
9de3ca7e 525
526 return 0;
527}
528
78b3fb13 529faim_internal int aim_parse_msgack_middle(struct aim_session_t *sess, struct command_rx_struct *command)
1a8c261b 530{
531 rxcallback_t userfunc = NULL;
532 char sn[MAXSNLEN];
533 unsigned short type;
534 int i = 10+8; /* skip SNAC and cookie */
535 int ret = 1;
536 unsigned char snlen;
537
538 type = aimutil_get16(command->data+i);
539 i += 2;
540
541 snlen = aimutil_get8(command->data+i);
542 i++;
543
544 memset(sn, 0, sizeof(sn));
78b3fb13 545 strncpy(sn, (char *)command->data+i, snlen);
1a8c261b 546
646c6b52 547 if ((userfunc = aim_callhandler(sess, command->conn, 0x0004, 0x000c)))
1a8c261b 548 ret = userfunc(sess, command, type, sn);
549
550 return ret;
551}
552
d6c9fcf0 553/*
554 * The Rate Limiting System, An Abridged Guide to Nonsense.
555 *
556 * OSCAR defines several 'rate classes'. Each class has seperate
557 * rate limiting properties (limit level, alert level, disconnect
558 * level, etc), and a set of SNAC family/type pairs associated with
559 * it. The rate classes, their limiting properties, and the definitions
560 * of which SNACs are belong to which class, are defined in the
561 * Rate Response packet at login to each host.
562 *
563 * Logically, all rate offenses within one class count against further
564 * offenses for other SNACs in the same class (ie, sending messages
565 * too fast will limit the number of user info requests you can send,
566 * since those two SNACs are in the same rate class).
567 *
568 * Since the rate classes are defined dynamically at login, the values
569 * below may change. But they seem to be fairly constant.
570 *
571 * Currently, BOS defines five rate classes, with the commonly used
572 * members as follows...
573 *
574 * Rate class 0x0001:
575 * - Everything thats not in any of the other classes
576 *
577 * Rate class 0x0002:
578 * - Buddy list add/remove
579 * - Permit list add/remove
580 * - Deny list add/remove
581 *
582 * Rate class 0x0003:
583 * - User information requests
584 * - Outgoing ICBMs
585 *
586 * Rate class 0x0004:
587 * - A few unknowns: 2/9, 2/b, and f/2
588 *
589 * Rate class 0x0005:
590 * - Chat room create
591 * - Outgoing chat ICBMs
592 *
593 * The only other thing of note is that class 5 (chat) has slightly looser
594 * limiting properties than class 3 (normal messages). But thats just a
595 * small bit of trivia for you.
596 *
597 * The last thing that needs to be learned about the rate limiting
598 * system is how the actual numbers relate to the passing of time. This
599 * seems to be a big mystery.
600 *
601 */
78b3fb13 602faim_internal int aim_parse_ratechange_middle(struct aim_session_t *sess, struct command_rx_struct *command)
1a8c261b 603{
604 rxcallback_t userfunc = NULL;
1a8c261b 605 int ret = 1;
275a2ff8 606 int i;
607 int code;
d6c9fcf0 608 unsigned long rateclass, windowsize, clear, alert, limit, disconnect;
275a2ff8 609 unsigned long currentavg, maxavg;
1a8c261b 610
275a2ff8 611 i = 10;
612
613 code = aimutil_get16(command->data+i);
614 i += 2;
615
d6c9fcf0 616 rateclass = aimutil_get16(command->data+i);
275a2ff8 617 i += 2;
618
619 windowsize = aimutil_get32(command->data+i);
620 i += 4;
621 clear = aimutil_get32(command->data+i);
622 i += 4;
623 alert = aimutil_get32(command->data+i);
624 i += 4;
625 limit = aimutil_get32(command->data+i);
626 i += 4;
627 disconnect = aimutil_get32(command->data+i);
628 i += 4;
629 currentavg = aimutil_get32(command->data+i);
630 i += 4;
631 maxavg = aimutil_get32(command->data+i);
632 i += 4;
1a8c261b 633
646c6b52 634 if ((userfunc = aim_callhandler(sess, command->conn, 0x0001, 0x000a)))
d6c9fcf0 635 ret = userfunc(sess, command, code, rateclass, windowsize, clear, alert, limit, disconnect, currentavg, maxavg);
1a8c261b 636
637 return ret;
638}
639
78b3fb13 640faim_internal int aim_parse_evilnotify_middle(struct aim_session_t *sess, struct command_rx_struct *command)
98c88242 641{
642 rxcallback_t userfunc = NULL;
06bc8607 643 int ret = 1;
644 int i;
645 unsigned short newevil;
646 struct aim_userinfo_s userinfo;
98c88242 647
06bc8607 648 i = 10;
649 newevil = aimutil_get16(command->data+10);
650 i += 2;
98c88242 651
06bc8607 652 memset(&userinfo, 0, sizeof(struct aim_userinfo_s));
653 if (command->commandlen-i)
646c6b52 654 i += aim_extractuserinfo(sess, command->data+i, &userinfo);
98c88242 655
646c6b52 656 if ((userfunc = aim_callhandler(sess, command->conn, 0x0001, 0x0010)))
06bc8607 657 ret = userfunc(sess, command, newevil, &userinfo);
98c88242 658
659 return ret;
660}
661
78b3fb13 662faim_internal int aim_parsemotd_middle(struct aim_session_t *sess,
663 struct command_rx_struct *command, ...)
9de3ca7e 664{
665 rxcallback_t userfunc = NULL;
01b59e1e 666 char *msg;
667 int ret=1;
668 struct aim_tlvlist_t *tlvlist;
669 u_short id;
670
671 /*
98c88242 672 * Code.
673 *
674 * Valid values:
675 * 1 Mandatory upgrade
676 * 2 Advisory upgrade
677 * 3 System bulletin
678 * 4 Nothing's wrong ("top o the world" -- normal)
679 *
01b59e1e 680 */
681 id = aimutil_get16(command->data+10);
682
683 /*
684 * TLVs follow
685 */
b13c9e13 686 if (!(tlvlist = aim_readtlvchain(command->data+12, command->commandlen-12)))
687 return ret;
688
689 if (!(msg = aim_gettlv_str(tlvlist, 0x000b, 1))) {
690 aim_freetlvchain(&tlvlist);
691 return ret;
692 }
01b59e1e 693
646c6b52 694 userfunc = aim_callhandler(sess, command->conn, 0x0001, 0x0013);
01b59e1e 695 if (userfunc)
696 ret = userfunc(sess, command, id, msg);
9de3ca7e 697
01b59e1e 698 aim_freetlvchain(&tlvlist);
b13c9e13 699 free(msg);
9de3ca7e 700
b13c9e13 701 return ret;
9de3ca7e 702}
703
ee49b735 704faim_internal int aim_parse_hostonline(struct aim_session_t *sess,
705 struct command_rx_struct *command, ...)
706{
707 rxcallback_t userfunc = NULL;
708 int ret = 1;
709 unsigned short *families = NULL;
710 int famcount = 0, i;
711
712 famcount = (command->commandlen-10)/2;
713 if (!(families = malloc(command->commandlen-10)))
714 return ret;
715
716 for (i = 0; i < famcount; i++)
717 families[i] = aimutil_get16(command->data+((i*2)+10));
718
646c6b52 719 if ((userfunc = aim_callhandler(sess, command->conn, 0x0001, 0x0003)))
ee49b735 720 ret = userfunc(sess, command, famcount, families);
721
722 free(families);
723
724 return ret;
725}
726
64c78745 727faim_internal int aim_parse_accountconfirm(struct aim_session_t *sess,
728 struct command_rx_struct *command)
729{
730 rxcallback_t userfunc = NULL;
731 int ret = 1;
732 int status = -1;
733
734 status = aimutil_get16(command->data+10);
735
646c6b52 736 if ((userfunc = aim_callhandler(sess, command->conn, 0x0007, 0x0007)))
64c78745 737 ret = userfunc(sess, command, status);
738
739 return ret;
740}
741
742faim_internal int aim_parse_infochange(struct aim_session_t *sess,
743 struct command_rx_struct *command)
744{
745 unsigned short subtype; /* called for both reply and change-reply */
746 int i;
747
748 subtype = aimutil_get16(command->data+2);
749
750 /*
751 * struct {
752 * unsigned short perms;
753 * unsigned short tlvcount;
754 * aim_tlv_t tlvs[tlvcount];
755 * } admin_info[n];
756 */
757 for (i = 10; i < command->commandlen; ) {
758 int perms, tlvcount;
759
760 perms = aimutil_get16(command->data+i);
761 i += 2;
762
763 tlvcount = aimutil_get16(command->data+i);
764 i += 2;
765
766 while (tlvcount) {
767 rxcallback_t userfunc;
768 struct aim_tlv_t *tlv;
769 int str = 0;
770
771 if ((aimutil_get16(command->data+i) == 0x0011) ||
772 (aimutil_get16(command->data+i) == 0x0004))
773 str = 1;
774
775 if (str)
776 tlv = aim_grabtlvstr(command->data+i);
777 else
778 tlv = aim_grabtlv(command->data+i);
779
780 /* XXX fix so its only called once for the entire packet */
646c6b52 781 if ((userfunc = aim_callhandler(sess, command->conn, 0x0007, subtype)))
64c78745 782 userfunc(sess, command, perms, tlv->type, tlv->length, tlv->value, str);
783
784 if (tlv)
785 i += 2+2+tlv->length;
786
787 if (tlv && tlv->value)
788 free(tlv->value);
789 if (tlv)
790 free(tlv);
791
792 tlvcount--;
793 }
794 }
795
796 return 1;
797}
798
ee49b735 799faim_internal int aim_parse_hostversions(struct aim_session_t *sess,
800 struct command_rx_struct *command, ...)
801{
802 rxcallback_t userfunc = NULL;
803 int ret = 1;
804 int vercount;
805
806 vercount = (command->commandlen-10)/4;
807
646c6b52 808 if ((userfunc = aim_callhandler(sess, command->conn, 0x0001, 0x0018)))
ee49b735 809 ret = userfunc(sess, command, vercount, command->data+10);
810
811 return ret;
812}
813
78b3fb13 814faim_internal int aim_handleredirect_middle(struct aim_session_t *sess,
ee49b735 815 struct command_rx_struct *command, ...)
9de3ca7e 816{
1ea867e3 817 int serviceid = 0;
818 unsigned char *cookie = NULL;
9de3ca7e 819 char *ip = NULL;
820 rxcallback_t userfunc = NULL;
01b59e1e 821 struct aim_tlvlist_t *tlvlist;
822 int ret = 1;
823
1ea867e3 824 tlvlist = aim_readtlvchain(command->data+10, command->commandlen-10);
825
826 if (aim_gettlv(tlvlist, 0x000d, 1))
827 serviceid = aim_gettlv16(tlvlist, 0x000d, 1);
828 if (aim_gettlv(tlvlist, 0x0005, 1))
829 ip = aim_gettlv_str(tlvlist, 0x0005, 1);
830 if (aim_gettlv(tlvlist, 0x0006, 1))
831 cookie = aim_gettlv_str(tlvlist, 0x0006, 1);
832
833 if ((serviceid == AIM_CONN_TYPE_CHAT) && sess->pendingjoin) {
834
835 /*
836 * Chat hack.
837 *
838 */
646c6b52 839 if ((userfunc = aim_callhandler(sess, command->conn, 0x0001, 0x0005)))
1ea867e3 840 ret = userfunc(sess, command, serviceid, ip, cookie, sess->pendingjoin, (int)sess->pendingjoinexchange);
0c20631f 841 free(sess->pendingjoin);
842 sess->pendingjoin = NULL;
9f20a4e3 843 sess->pendingjoinexchange = 0;
1ea867e3 844 } else if (!serviceid || !ip || !cookie) { /* yeep! */
845 ret = 1;
846 } else {
646c6b52 847 if ((userfunc = aim_callhandler(sess, command->conn, 0x0001, 0x0005)))
1ea867e3 848 ret = userfunc(sess, command, serviceid, ip, cookie);
849 }
850
851 if (ip)
852 free(ip);
853 if (cookie)
854 free(cookie);
0e2be272 855
01b59e1e 856 aim_freetlvchain(&tlvlist);
857
858 return ret;
9de3ca7e 859}
860
78b3fb13 861faim_internal int aim_parse_unknown(struct aim_session_t *sess,
862 struct command_rx_struct *command, ...)
9de3ca7e 863{
864 u_int i = 0;
865
22517493 866 if (!sess || !command)
867 return 1;
868
646c6b52 869 faimdprintf(sess, 1, "\nRecieved unknown packet:");
9de3ca7e 870
871 for (i = 0; i < command->commandlen; i++)
872 {
873 if ((i % 8) == 0)
646c6b52 874 faimdprintf(sess, 1, "\n\t");
9de3ca7e 875
646c6b52 876 faimdprintf(sess, 1, "0x%2x ", command->data[i]);
9de3ca7e 877 }
878
646c6b52 879 faimdprintf(sess, 1, "\n\n");
9de3ca7e 880
881 return 1;
882}
883
884
78b3fb13 885faim_internal int aim_negchan_middle(struct aim_session_t *sess,
886 struct command_rx_struct *command)
5e02cf44 887{
888 struct aim_tlvlist_t *tlvlist;
889 char *msg = NULL;
890 unsigned short code = 0;
5e02cf44 891 rxcallback_t userfunc = NULL;
892 int ret = 1;
893
bb010ae0 894 /* Used only by the older login protocol */
895 /* XXX remove this special case? */
896 if (command->conn->type == AIM_CONN_TYPE_AUTH)
897 return aim_authparse(sess, command);
898
5e02cf44 899 tlvlist = aim_readtlvchain(command->data, command->commandlen);
900
1ea867e3 901 if (aim_gettlv(tlvlist, 0x0009, 1))
902 code = aim_gettlv16(tlvlist, 0x0009, 1);
5e02cf44 903
1ea867e3 904 if (aim_gettlv(tlvlist, 0x000b, 1))
5e02cf44 905 msg = aim_gettlv_str(tlvlist, 0x000b, 1);
906
646c6b52 907 if ((userfunc = aim_callhandler(sess, command->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR)))
5e02cf44 908 ret = userfunc(sess, command, code, msg);
909
910 aim_freetlvchain(&tlvlist);
1ea867e3 911
912 if (msg)
913 free(msg);
5e02cf44 914
915 return ret;
916}
917
9de3ca7e 918/*
919 * aim_parse_generalerrs()
920 *
921 * Middle handler for 0x0001 snac of each family.
922 *
923 */
78b3fb13 924faim_internal int aim_parse_generalerrs(struct aim_session_t *sess,
925 struct command_rx_struct *command, ...)
9de3ca7e 926{
1449ad2b 927 unsigned short family;
928 unsigned short subtype;
929 int ret = 1;
930 int error = 0;
931 rxcallback_t userfunc = NULL;
a25832e6 932
933 family = aimutil_get16(command->data+0);
934 subtype= aimutil_get16(command->data+2);
9de3ca7e 935
1449ad2b 936 if (command->commandlen > 10)
937 error = aimutil_get16(command->data+10);
9de3ca7e 938
646c6b52 939 if ((userfunc = aim_callhandler(sess, command->conn, family, subtype)))
1449ad2b 940 ret = userfunc(sess, command, error);
941
942 return ret;
9de3ca7e 943}
944
945
946
This page took 0.408272 seconds and 5 git commands to generate.