]> andersk Git - libfaim.git/blame - src/rxhandlers.c
- Fri Mar 23 01:45:28 UTC 2001
[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;
154b4093 311 static int critical = 0;
9de3ca7e 312
154b4093 313 if (critical)
314 return 0; /* don't call recursively! */
315
316 critical = 1;
317
b8d0da45 318 if (sess->queue_incoming == NULL) {
646c6b52 319 faimdprintf(sess, 1, "parse_generic: incoming packet queue empty.\n");
b8d0da45 320 } else {
321 workingPtr = sess->queue_incoming;
50443ea0 322 for (i = 0; workingPtr != NULL; workingPtr = workingPtr->next, i++) {
bb010ae0 323 unsigned short family,subtype;
324
b8d0da45 325 /*
326 * XXX: This is still fairly ugly.
327 */
50443ea0 328 if (workingPtr->handled)
329 continue;
330
b69540e3 331 /*
332 * This is a debugging/sanity check only and probably could/should be removed
333 * for stable code.
334 */
335 if (((workingPtr->hdrtype == AIM_FRAMETYPE_OFT) &&
336 (workingPtr->conn->type != AIM_CONN_TYPE_RENDEZVOUS)) ||
337 ((workingPtr->hdrtype == AIM_FRAMETYPE_OSCAR) &&
338 (workingPtr->conn->type == AIM_CONN_TYPE_RENDEZVOUS))) {
646c6b52 339 faimdprintf(sess, 0, "rxhandlers: incompatible frame type %d on connection type 0x%04x\n", workingPtr->hdrtype, workingPtr->conn->type);
b69540e3 340 workingPtr->handled = 1;
341 continue;
342 }
343
bb010ae0 344 if (workingPtr->conn->type == AIM_CONN_TYPE_RENDEZVOUS) {
345 /* make sure that we only get OFT frames on these connections */
346 if (workingPtr->hdrtype != AIM_FRAMETYPE_OFT) {
347 faimdprintf(sess, 0, "internal error: non-OFT frames on OFT connection\n");
348 workingPtr->handled = 1; /* get rid of it */
349 } else {
350 /* XXX: implement this */
351 faimdprintf(sess, 0, "faim: OFT frame!\n");
352 workingPtr->handled = 1; /* get rid of it */
b8d0da45 353 }
bb010ae0 354 continue;
b8d0da45 355 }
5e02cf44 356
bb010ae0 357 if (workingPtr->conn->type == AIM_CONN_TYPE_RENDEZVOUS_OUT) {
358 /* not possible */
359 faimdprintf(sess, 0, "rxdispatch called on RENDEZVOUS_OUT connection!\n");
360 workingPtr->handled = 1;
361 continue;
362 }
5e02cf44 363
bb010ae0 364 if ((workingPtr->commandlen == 4) &&
365 (aimutil_get32(workingPtr->data) == 0x00000001)) {
366 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, workingPtr);
367 continue;
368 }
64c78745 369
bb010ae0 370 if (workingPtr->hdr.oscar.type == 0x04) {
371 workingPtr->handled = aim_negchan_middle(sess, workingPtr);
372 continue;
373 }
374
375 family = aimutil_get16(workingPtr->data);
376 subtype = aimutil_get16(workingPtr->data+2);
377
378 if (family == 0x0001) {
64c78745 379
bb010ae0 380 if (subtype == 0x0001)
381 workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
382 else if (subtype == 0x0003)
64c78745 383 workingPtr->handled = aim_parse_hostonline(sess, workingPtr);
bb010ae0 384 else if (subtype == 0x0005)
385 workingPtr->handled = aim_handleredirect_middle(sess, workingPtr);
386 else if (subtype == 0x0007)
387 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0007, workingPtr);
388 else if (subtype == 0x000a)
389 workingPtr->handled = aim_parse_ratechange_middle(sess, workingPtr);
390 else if (subtype == 0x000f)
391 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x000f, workingPtr);
392 else if (subtype == 0x0010)
393 workingPtr->handled = aim_parse_evilnotify_middle(sess, workingPtr);
394 else if (subtype == 0x0013)
395 workingPtr->handled = aim_parsemotd_middle(sess, workingPtr);
396 else if (subtype == 0x0018)
397 workingPtr->handled = aim_parse_hostversions(sess, workingPtr);
398 else
399 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0xffff, workingPtr);
400
401 } else if (family == 0x0002) {
402
403 if (subtype == 0x0001)
404 workingPtr->handled = aim_parse_locateerr(sess, workingPtr);
405 else if (subtype == 0x0003)
406 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0002, 0x0003, workingPtr);
407 else if (subtype == 0x0006)
408 workingPtr->handled = aim_parse_userinfo_middle(sess, workingPtr);
409 else
410 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_LOC, AIM_CB_LOC_DEFAULT, workingPtr);
411
412 } else if (family == 0x0003) {
413
414 if (subtype == 0x0001)
415 workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
416 else if (subtype == 0x0003)
417 workingPtr->handled = aim_parse_buddyrights(sess, workingPtr);
418 else if (subtype == 0x000b)
419 workingPtr->handled = aim_parse_oncoming_middle(sess, workingPtr);
420 else if (subtype == 0x000c)
421 workingPtr->handled = aim_parse_offgoing_middle(sess, workingPtr);
422 else
423 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_BUD, AIM_CB_BUD_DEFAULT, workingPtr);
424
425 } else if (family == 0x0004) {
426
427 if (subtype == 0x0001)
428 workingPtr->handled = aim_parse_msgerror_middle(sess, workingPtr);
429 else if (subtype == 0x0005)
430 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0004, 0x0005, workingPtr);
431 else if (subtype == 0x0006)
432 workingPtr->handled = aim_parse_outgoing_im_middle(sess, workingPtr);
433 else if (subtype == 0x0007)
434 workingPtr->handled = aim_parse_incoming_im_middle(sess, workingPtr);
435 else if (subtype == 0x000a)
436 workingPtr->handled = aim_parse_missedcall(sess, workingPtr);
437 else if (subtype == 0x000c)
438 workingPtr->handled = aim_parse_msgack_middle(sess, workingPtr);
439 else
440 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_MSG, AIM_CB_MSG_DEFAULT, workingPtr);
441
442 } else if (family == 0x0007) {
443
444 if (subtype == 0x0003)
445 workingPtr->handled = aim_parse_infochange(sess, workingPtr);
446 else if (subtype == 0x0005)
447 workingPtr->handled = aim_parse_infochange(sess, workingPtr);
448 else if (subtype == 0x0007)
449 workingPtr->handled = aim_parse_accountconfirm(sess, workingPtr);
64c78745 450 break;
bb010ae0 451
452 } else if (family == 0x0009) {
453
454 if (subtype == 0x0001)
455 workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
456 else if (subtype == 0x0003)
457 workingPtr->handled = aim_parse_bosrights(sess, workingPtr);
458 else
459 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_BOS, AIM_CB_BOS_DEFAULT, workingPtr);
460
461 } else if (family == 0x000a) {
462
463 if (subtype == 0x0001)
464 workingPtr->handled = aim_parse_searcherror(sess, workingPtr);
465 else if (subtype == 0x0003)
466 workingPtr->handled = aim_parse_searchreply(sess, workingPtr);
467 else
468 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_LOK, AIM_CB_LOK_DEFAULT, workingPtr);
469
470 } else if (family == 0x000b) {
471
472 if (subtype == 0x0001)
473 workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
474 else if (subtype == 0x0002)
475 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x000b, 0x0002, workingPtr);
476 else
477 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_STS, AIM_CB_STS_DEFAULT, workingPtr);
478
479 } else if (family == 0x000d) {
480
481 if (subtype == 0x0009)
b8d0da45 482 workingPtr->handled = aim_chatnav_parse_info(sess, workingPtr);
bb010ae0 483
484 } else if (family == 0x000e) {
485
486 if (subtype == 0x0002)
487 workingPtr->handled = aim_chat_parse_infoupdate(sess, workingPtr);
488 else if (subtype == 0x0003)
489 workingPtr->handled = aim_chat_parse_joined(sess, workingPtr);
490 else if (subtype == 0x0004)
491 workingPtr->handled = aim_chat_parse_leave(sess, workingPtr);
492 else if (subtype == 0x0006)
493 workingPtr->handled = aim_chat_parse_incoming(sess, workingPtr);
494
495 } else if (family == 0x0013) {
496
497 faimdprintf(sess, 0, "lalala: 0x%04x/0x%04x\n", family, subtype);
498
499 } else if (family == 0x0017) { /* New login protocol */
500
501 if (subtype == 0x0001)
502 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0017, 0x0001, workingPtr);
503 else if (subtype == 0x0003)
504 workingPtr->handled = aim_authparse(sess, workingPtr);
505 else if (subtype == 0x0007)
506 workingPtr->handled = aim_authkeyparse(sess, workingPtr);
507 else
508 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0017, 0xffff, workingPtr);
509
510 } else if (family == AIM_CB_FAM_SPECIAL) {
511
512 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, family, subtype, workingPtr);
513
7392c79f 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);
154b4093 525
526 critical = 0;
9de3ca7e 527
528 return 0;
529}
530
78b3fb13 531faim_internal int aim_parse_msgack_middle(struct aim_session_t *sess, struct command_rx_struct *command)
1a8c261b 532{
533 rxcallback_t userfunc = NULL;
534 char sn[MAXSNLEN];
535 unsigned short type;
536 int i = 10+8; /* skip SNAC and cookie */
537 int ret = 1;
538 unsigned char snlen;
539
540 type = aimutil_get16(command->data+i);
541 i += 2;
542
543 snlen = aimutil_get8(command->data+i);
544 i++;
545
546 memset(sn, 0, sizeof(sn));
78b3fb13 547 strncpy(sn, (char *)command->data+i, snlen);
1a8c261b 548
646c6b52 549 if ((userfunc = aim_callhandler(sess, command->conn, 0x0004, 0x000c)))
1a8c261b 550 ret = userfunc(sess, command, type, sn);
551
552 return ret;
553}
554
d6c9fcf0 555/*
556 * The Rate Limiting System, An Abridged Guide to Nonsense.
557 *
558 * OSCAR defines several 'rate classes'. Each class has seperate
559 * rate limiting properties (limit level, alert level, disconnect
560 * level, etc), and a set of SNAC family/type pairs associated with
561 * it. The rate classes, their limiting properties, and the definitions
562 * of which SNACs are belong to which class, are defined in the
563 * Rate Response packet at login to each host.
564 *
565 * Logically, all rate offenses within one class count against further
566 * offenses for other SNACs in the same class (ie, sending messages
567 * too fast will limit the number of user info requests you can send,
568 * since those two SNACs are in the same rate class).
569 *
570 * Since the rate classes are defined dynamically at login, the values
571 * below may change. But they seem to be fairly constant.
572 *
573 * Currently, BOS defines five rate classes, with the commonly used
574 * members as follows...
575 *
576 * Rate class 0x0001:
577 * - Everything thats not in any of the other classes
578 *
579 * Rate class 0x0002:
580 * - Buddy list add/remove
581 * - Permit list add/remove
582 * - Deny list add/remove
583 *
584 * Rate class 0x0003:
585 * - User information requests
586 * - Outgoing ICBMs
587 *
588 * Rate class 0x0004:
589 * - A few unknowns: 2/9, 2/b, and f/2
590 *
591 * Rate class 0x0005:
592 * - Chat room create
593 * - Outgoing chat ICBMs
594 *
595 * The only other thing of note is that class 5 (chat) has slightly looser
596 * limiting properties than class 3 (normal messages). But thats just a
597 * small bit of trivia for you.
598 *
599 * The last thing that needs to be learned about the rate limiting
600 * system is how the actual numbers relate to the passing of time. This
601 * seems to be a big mystery.
602 *
603 */
78b3fb13 604faim_internal int aim_parse_ratechange_middle(struct aim_session_t *sess, struct command_rx_struct *command)
1a8c261b 605{
606 rxcallback_t userfunc = NULL;
1a8c261b 607 int ret = 1;
275a2ff8 608 int i;
609 int code;
d6c9fcf0 610 unsigned long rateclass, windowsize, clear, alert, limit, disconnect;
275a2ff8 611 unsigned long currentavg, maxavg;
1a8c261b 612
275a2ff8 613 i = 10;
614
615 code = aimutil_get16(command->data+i);
616 i += 2;
617
d6c9fcf0 618 rateclass = aimutil_get16(command->data+i);
275a2ff8 619 i += 2;
620
621 windowsize = aimutil_get32(command->data+i);
622 i += 4;
623 clear = aimutil_get32(command->data+i);
624 i += 4;
625 alert = aimutil_get32(command->data+i);
626 i += 4;
627 limit = aimutil_get32(command->data+i);
628 i += 4;
629 disconnect = aimutil_get32(command->data+i);
630 i += 4;
631 currentavg = aimutil_get32(command->data+i);
632 i += 4;
633 maxavg = aimutil_get32(command->data+i);
634 i += 4;
1a8c261b 635
646c6b52 636 if ((userfunc = aim_callhandler(sess, command->conn, 0x0001, 0x000a)))
d6c9fcf0 637 ret = userfunc(sess, command, code, rateclass, windowsize, clear, alert, limit, disconnect, currentavg, maxavg);
1a8c261b 638
639 return ret;
640}
641
78b3fb13 642faim_internal int aim_parse_evilnotify_middle(struct aim_session_t *sess, struct command_rx_struct *command)
98c88242 643{
644 rxcallback_t userfunc = NULL;
06bc8607 645 int ret = 1;
646 int i;
647 unsigned short newevil;
648 struct aim_userinfo_s userinfo;
98c88242 649
06bc8607 650 i = 10;
651 newevil = aimutil_get16(command->data+10);
652 i += 2;
98c88242 653
06bc8607 654 memset(&userinfo, 0, sizeof(struct aim_userinfo_s));
655 if (command->commandlen-i)
646c6b52 656 i += aim_extractuserinfo(sess, command->data+i, &userinfo);
98c88242 657
646c6b52 658 if ((userfunc = aim_callhandler(sess, command->conn, 0x0001, 0x0010)))
06bc8607 659 ret = userfunc(sess, command, newevil, &userinfo);
98c88242 660
661 return ret;
662}
663
78b3fb13 664faim_internal int aim_parsemotd_middle(struct aim_session_t *sess,
665 struct command_rx_struct *command, ...)
9de3ca7e 666{
667 rxcallback_t userfunc = NULL;
01b59e1e 668 char *msg;
669 int ret=1;
670 struct aim_tlvlist_t *tlvlist;
671 u_short id;
672
673 /*
98c88242 674 * Code.
675 *
676 * Valid values:
677 * 1 Mandatory upgrade
678 * 2 Advisory upgrade
679 * 3 System bulletin
680 * 4 Nothing's wrong ("top o the world" -- normal)
681 *
01b59e1e 682 */
683 id = aimutil_get16(command->data+10);
684
685 /*
686 * TLVs follow
687 */
b13c9e13 688 if (!(tlvlist = aim_readtlvchain(command->data+12, command->commandlen-12)))
689 return ret;
690
691 if (!(msg = aim_gettlv_str(tlvlist, 0x000b, 1))) {
692 aim_freetlvchain(&tlvlist);
693 return ret;
694 }
01b59e1e 695
646c6b52 696 userfunc = aim_callhandler(sess, command->conn, 0x0001, 0x0013);
01b59e1e 697 if (userfunc)
698 ret = userfunc(sess, command, id, msg);
9de3ca7e 699
01b59e1e 700 aim_freetlvchain(&tlvlist);
b13c9e13 701 free(msg);
9de3ca7e 702
b13c9e13 703 return ret;
9de3ca7e 704}
705
ee49b735 706faim_internal int aim_parse_hostonline(struct aim_session_t *sess,
707 struct command_rx_struct *command, ...)
708{
709 rxcallback_t userfunc = NULL;
710 int ret = 1;
711 unsigned short *families = NULL;
712 int famcount = 0, i;
713
714 famcount = (command->commandlen-10)/2;
715 if (!(families = malloc(command->commandlen-10)))
716 return ret;
717
718 for (i = 0; i < famcount; i++)
719 families[i] = aimutil_get16(command->data+((i*2)+10));
720
646c6b52 721 if ((userfunc = aim_callhandler(sess, command->conn, 0x0001, 0x0003)))
ee49b735 722 ret = userfunc(sess, command, famcount, families);
723
724 free(families);
725
726 return ret;
727}
728
64c78745 729faim_internal int aim_parse_accountconfirm(struct aim_session_t *sess,
730 struct command_rx_struct *command)
731{
732 rxcallback_t userfunc = NULL;
733 int ret = 1;
734 int status = -1;
735
736 status = aimutil_get16(command->data+10);
737
646c6b52 738 if ((userfunc = aim_callhandler(sess, command->conn, 0x0007, 0x0007)))
64c78745 739 ret = userfunc(sess, command, status);
740
741 return ret;
742}
743
744faim_internal int aim_parse_infochange(struct aim_session_t *sess,
745 struct command_rx_struct *command)
746{
747 unsigned short subtype; /* called for both reply and change-reply */
748 int i;
749
750 subtype = aimutil_get16(command->data+2);
751
752 /*
753 * struct {
754 * unsigned short perms;
755 * unsigned short tlvcount;
756 * aim_tlv_t tlvs[tlvcount];
757 * } admin_info[n];
758 */
759 for (i = 10; i < command->commandlen; ) {
760 int perms, tlvcount;
761
762 perms = aimutil_get16(command->data+i);
763 i += 2;
764
765 tlvcount = aimutil_get16(command->data+i);
766 i += 2;
767
768 while (tlvcount) {
769 rxcallback_t userfunc;
770 struct aim_tlv_t *tlv;
771 int str = 0;
772
773 if ((aimutil_get16(command->data+i) == 0x0011) ||
774 (aimutil_get16(command->data+i) == 0x0004))
775 str = 1;
776
777 if (str)
778 tlv = aim_grabtlvstr(command->data+i);
779 else
780 tlv = aim_grabtlv(command->data+i);
781
782 /* XXX fix so its only called once for the entire packet */
646c6b52 783 if ((userfunc = aim_callhandler(sess, command->conn, 0x0007, subtype)))
64c78745 784 userfunc(sess, command, perms, tlv->type, tlv->length, tlv->value, str);
785
786 if (tlv)
787 i += 2+2+tlv->length;
788
789 if (tlv && tlv->value)
790 free(tlv->value);
791 if (tlv)
792 free(tlv);
793
794 tlvcount--;
795 }
796 }
797
798 return 1;
799}
800
ee49b735 801faim_internal int aim_parse_hostversions(struct aim_session_t *sess,
802 struct command_rx_struct *command, ...)
803{
804 rxcallback_t userfunc = NULL;
805 int ret = 1;
806 int vercount;
807
808 vercount = (command->commandlen-10)/4;
809
646c6b52 810 if ((userfunc = aim_callhandler(sess, command->conn, 0x0001, 0x0018)))
ee49b735 811 ret = userfunc(sess, command, vercount, command->data+10);
812
813 return ret;
814}
815
78b3fb13 816faim_internal int aim_handleredirect_middle(struct aim_session_t *sess,
ee49b735 817 struct command_rx_struct *command, ...)
9de3ca7e 818{
1ea867e3 819 int serviceid = 0;
820 unsigned char *cookie = NULL;
9de3ca7e 821 char *ip = NULL;
822 rxcallback_t userfunc = NULL;
01b59e1e 823 struct aim_tlvlist_t *tlvlist;
824 int ret = 1;
825
1ea867e3 826 tlvlist = aim_readtlvchain(command->data+10, command->commandlen-10);
827
828 if (aim_gettlv(tlvlist, 0x000d, 1))
829 serviceid = aim_gettlv16(tlvlist, 0x000d, 1);
830 if (aim_gettlv(tlvlist, 0x0005, 1))
831 ip = aim_gettlv_str(tlvlist, 0x0005, 1);
832 if (aim_gettlv(tlvlist, 0x0006, 1))
833 cookie = aim_gettlv_str(tlvlist, 0x0006, 1);
834
835 if ((serviceid == AIM_CONN_TYPE_CHAT) && sess->pendingjoin) {
836
837 /*
838 * Chat hack.
839 *
840 */
646c6b52 841 if ((userfunc = aim_callhandler(sess, command->conn, 0x0001, 0x0005)))
1ea867e3 842 ret = userfunc(sess, command, serviceid, ip, cookie, sess->pendingjoin, (int)sess->pendingjoinexchange);
0c20631f 843 free(sess->pendingjoin);
844 sess->pendingjoin = NULL;
9f20a4e3 845 sess->pendingjoinexchange = 0;
1ea867e3 846 } else if (!serviceid || !ip || !cookie) { /* yeep! */
847 ret = 1;
848 } else {
646c6b52 849 if ((userfunc = aim_callhandler(sess, command->conn, 0x0001, 0x0005)))
1ea867e3 850 ret = userfunc(sess, command, serviceid, ip, cookie);
851 }
852
853 if (ip)
854 free(ip);
855 if (cookie)
856 free(cookie);
0e2be272 857
01b59e1e 858 aim_freetlvchain(&tlvlist);
859
860 return ret;
9de3ca7e 861}
862
78b3fb13 863faim_internal int aim_parse_unknown(struct aim_session_t *sess,
864 struct command_rx_struct *command, ...)
9de3ca7e 865{
866 u_int i = 0;
867
22517493 868 if (!sess || !command)
869 return 1;
870
646c6b52 871 faimdprintf(sess, 1, "\nRecieved unknown packet:");
9de3ca7e 872
873 for (i = 0; i < command->commandlen; i++)
874 {
875 if ((i % 8) == 0)
646c6b52 876 faimdprintf(sess, 1, "\n\t");
9de3ca7e 877
646c6b52 878 faimdprintf(sess, 1, "0x%2x ", command->data[i]);
9de3ca7e 879 }
880
646c6b52 881 faimdprintf(sess, 1, "\n\n");
9de3ca7e 882
883 return 1;
884}
885
886
78b3fb13 887faim_internal int aim_negchan_middle(struct aim_session_t *sess,
888 struct command_rx_struct *command)
5e02cf44 889{
890 struct aim_tlvlist_t *tlvlist;
891 char *msg = NULL;
892 unsigned short code = 0;
5e02cf44 893 rxcallback_t userfunc = NULL;
894 int ret = 1;
895
bb010ae0 896 /* Used only by the older login protocol */
897 /* XXX remove this special case? */
898 if (command->conn->type == AIM_CONN_TYPE_AUTH)
899 return aim_authparse(sess, command);
900
5e02cf44 901 tlvlist = aim_readtlvchain(command->data, command->commandlen);
902
1ea867e3 903 if (aim_gettlv(tlvlist, 0x0009, 1))
904 code = aim_gettlv16(tlvlist, 0x0009, 1);
5e02cf44 905
1ea867e3 906 if (aim_gettlv(tlvlist, 0x000b, 1))
5e02cf44 907 msg = aim_gettlv_str(tlvlist, 0x000b, 1);
908
646c6b52 909 if ((userfunc = aim_callhandler(sess, command->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR)))
5e02cf44 910 ret = userfunc(sess, command, code, msg);
911
912 aim_freetlvchain(&tlvlist);
1ea867e3 913
914 if (msg)
915 free(msg);
5e02cf44 916
917 return ret;
918}
919
9de3ca7e 920/*
921 * aim_parse_generalerrs()
922 *
923 * Middle handler for 0x0001 snac of each family.
924 *
925 */
78b3fb13 926faim_internal int aim_parse_generalerrs(struct aim_session_t *sess,
927 struct command_rx_struct *command, ...)
9de3ca7e 928{
1449ad2b 929 unsigned short family;
930 unsigned short subtype;
931 int ret = 1;
932 int error = 0;
933 rxcallback_t userfunc = NULL;
a25832e6 934
935 family = aimutil_get16(command->data+0);
936 subtype= aimutil_get16(command->data+2);
9de3ca7e 937
1449ad2b 938 if (command->commandlen > 10)
939 error = aimutil_get16(command->data+10);
9de3ca7e 940
646c6b52 941 if ((userfunc = aim_callhandler(sess, command->conn, family, subtype)))
1449ad2b 942 ret = userfunc(sess, command, error);
943
944 return ret;
9de3ca7e 945}
946
947
948
This page took 0.204051 seconds and 5 git commands to generate.