]> andersk Git - libfaim.git/blame - aim_rxhandlers.c
- Sat Sep 2 23:42:37 UTC 2000
[libfaim.git] / aim_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
a25832e6 10#include <faim/aim.h>
9de3ca7e 11
24286d93 12/*
13 * Bleck functions get called when there's no non-bleck functions
14 * around to cleanup the mess...
15 */
a25832e6 16int bleck(struct aim_session_t *sess,struct command_rx_struct *workingPtr, ...)
9de3ca7e 17{
18 u_short family;
19 u_short subtype;
01b59e1e 20
21 u_short maxf;
22 u_short maxs;
23
24 /* XXX: this is ugly. and big just for debugging. */
25 char *literals[14][25] = {
26 {"Invalid",
27 NULL
28 },
29 {"General",
30 "Invalid",
31 "Error",
32 "Client Ready",
33 "Server Ready",
34 "Service Request",
35 "Redirect",
36 "Rate Information Request",
37 "Rate Information",
38 "Rate Information Ack",
39 NULL,
40 "Rate Information Change",
41 "Server Pause",
42 NULL,
43 "Server Resume",
44 "Request Personal User Information",
45 "Personal User Information",
46 "Evil Notification",
47 NULL,
48 "Migration notice",
49 "Message of the Day",
50 "Set Privacy Flags",
51 "Well Known URL",
52 "NOP"
53 },
54 {"Location",
55 "Invalid",
56 "Error",
57 "Request Rights",
58 "Rights Information",
59 "Set user information",
60 "Request User Information",
61 "User Information",
62 "Watcher Sub Request",
63 "Watcher Notification"
64 },
65 {"Buddy List Management",
66 "Invalid",
67 "Error",
68 "Request Rights",
69 "Rights Information",
70 "Add Buddy",
71 "Remove Buddy",
72 "Watcher List Query",
73 "Watcher List Response",
74 "Watcher SubRequest",
75 "Watcher Notification",
76 "Reject Notification",
77 "Oncoming Buddy",
78 "Offgoing Buddy"
79 },
80 {"Messeging",
81 "Invalid",
82 "Error",
83 "Add ICBM Parameter",
84 "Remove ICBM Parameter",
85 "Request Parameter Information",
86 "Parameter Information",
87 "Outgoing Message",
88 "Incoming Message",
89 "Evil Request",
90 "Evil Reply",
91 "Missed Calls",
92 "Message Error",
93 "Host Ack"
94 },
95 {"Advertisements",
96 "Invalid",
97 "Error",
98 "Request Ad",
99 "Ad Data (GIFs)"
100 },
101 {"Invitation / Client-to-Client",
102 "Invalid",
103 "Error",
104 "Invite a Friend",
105 "Invitation Ack"
106 },
107 {"Administrative",
108 "Invalid",
109 "Error",
110 "Information Request",
111 "Information Reply",
112 "Information Change Request",
113 "Information Chat Reply",
114 "Account Confirm Request",
115 "Account Confirm Reply",
116 "Account Delete Request",
117 "Account Delete Reply"
118 },
119 {"Popups",
120 "Invalid",
121 "Error",
122 "Display Popup"
123 },
124 {"BOS",
125 "Invalid",
126 "Error",
127 "Request Rights",
128 "Rights Response",
129 "Set group permission mask",
130 "Add permission list entries",
131 "Delete permission list entries",
132 "Add deny list entries",
133 "Delete deny list entries",
134 "Server Error"
135 },
136 {"User Lookup",
137 "Invalid",
138 "Error",
139 "Search Request",
140 "Search Response"
141 },
142 {"Stats",
143 "Invalid",
144 "Error",
145 "Set minimum report interval",
146 "Report Events"
147 },
148 {"Translate",
149 "Invalid",
150 "Error",
151 "Translate Request",
152 "Translate Reply",
153 },
154 {"Chat Navigation",
155 "Invalid",
156 "Error",
157 "Request rights",
158 "Request Exchange Information",
159 "Request Room Information",
160 "Request Occupant List",
161 "Search for Room",
162 "Outgoing Message",
163 "Incoming Message",
164 "Evil Request",
165 "Evil Reply",
166 "Chat Error",
167 }
168 };
169
170 maxf = sizeof(literals) / sizeof(literals[0]);
171 maxs = sizeof(literals[0]) / sizeof(literals[0][0]);
172
173 family = aimutil_get16(workingPtr->data+0);
174 subtype= aimutil_get16(workingPtr->data+2);
175
176 if((family < maxf) && (subtype+1 < maxs) && (literals[family][subtype] != NULL))
177 printf("bleck: null handler for %04x/%04x (%s)\n", family, subtype, literals[family][subtype+1]);
178 else
179 printf("bleck: null handler for %04x/%04x (no literal)\n",family,subtype);
180
9de3ca7e 181 return 1;
182}
183
a25832e6 184int aim_conn_addhandler(struct aim_session_t *sess,
185 struct aim_conn_t *conn,
9de3ca7e 186 u_short family,
187 u_short type,
188 rxcallback_t newhandler,
189 u_short flags)
190{
191 struct aim_rxcblist_t *new,*cur;
192
193 if (!conn)
194 return -1;
195
b8d0da45 196 faimdprintf(1, "aim_conn_addhandler: adding for %04x/%04x\n", family, type);
9de3ca7e 197
198 new = (struct aim_rxcblist_t *)calloc(1, sizeof(struct aim_rxcblist_t));
199 new->family = family;
200 new->type = type;
201 new->flags = flags;
202 if (!newhandler)
203 new->handler = &bleck;
204 else
205 new->handler = newhandler;
206 new->next = NULL;
207
208 cur = conn->handlerlist;
209 if (!cur)
210 conn->handlerlist = new;
211 else
212 {
213 while (cur->next)
214 cur = cur->next;
215 cur->next = new;
216 }
217
218 return 0;
219}
220
221int aim_clearhandlers(struct aim_conn_t *conn)
222{
223 struct aim_rxcblist_t *cur,*tmp;
224 if (!conn)
225 return -1;
226
227 cur = conn->handlerlist;
228 while(cur)
229 {
230 tmp = cur->next;
231 free(cur);
232 cur = tmp;
233 }
234 return 0;
235}
236
237rxcallback_t aim_callhandler(struct aim_conn_t *conn,
238 u_short family,
239 u_short type)
240{
241 struct aim_rxcblist_t *cur;
242
243 if (!conn)
244 return NULL;
245
b8d0da45 246 faimdprintf(1, "aim_callhandler: calling for %04x/%04x\n", family, type);
9de3ca7e 247
248 cur = conn->handlerlist;
249 while(cur)
250 {
251 if ( (cur->family == family) && (cur->type == type) )
252 return cur->handler;
253 cur = cur->next;
254 }
255
256 if (type==0xffff)
257 return NULL;
258 return aim_callhandler(conn, family, 0xffff);
259}
260
a25832e6 261int aim_callhandler_noparam(struct aim_session_t *sess,
262 struct aim_conn_t *conn,
9de3ca7e 263 u_short family,
264 u_short type,
265 struct command_rx_struct *ptr)
266{
267 rxcallback_t userfunc = NULL;
268 userfunc = aim_callhandler(conn, family, type);
269 if (userfunc)
a25832e6 270 return userfunc(sess, ptr);
b8d0da45 271 return 1; /* XXX */
9de3ca7e 272}
273
274/*
275 aim_rxdispatch()
276
277 Basically, heres what this should do:
278 1) Determine correct packet handler for this packet
279 2) Mark the packet handled (so it can be dequeued in purge_queue())
280 3) Send the packet to the packet handler
281 4) Go to next packet in the queue and start over
282 5) When done, run purge_queue() to purge handled commands
283
284 Note that any unhandlable packets should probably be left in the
285 queue. This is the best way to prevent data loss. This means
286 that a single packet may get looked at by this function multiple
287 times. This is more good than bad! This behavior may change.
288
289 Aren't queue's fun?
290
291 TODO: Get rid of all the ugly if's.
292 TODO: Clean up.
293 TODO: More support for mid-level handlers.
294 TODO: Allow for NULL handlers.
295
296 */
a25832e6 297int aim_rxdispatch(struct aim_session_t *sess)
9de3ca7e 298{
299 int i = 0;
300 struct command_rx_struct *workingPtr = NULL;
301
b8d0da45 302 if (sess->queue_incoming == NULL) {
303 faimdprintf(1, "parse_generic: incoming packet queue empty.\n");
304 return 0;
305 } else {
306 workingPtr = sess->queue_incoming;
50443ea0 307 for (i = 0; workingPtr != NULL; workingPtr = workingPtr->next, i++) {
b8d0da45 308 /*
309 * XXX: This is still fairly ugly.
310 */
50443ea0 311 if (workingPtr->handled)
312 continue;
313
b69540e3 314 /*
315 * This is a debugging/sanity check only and probably could/should be removed
316 * for stable code.
317 */
318 if (((workingPtr->hdrtype == AIM_FRAMETYPE_OFT) &&
319 (workingPtr->conn->type != AIM_CONN_TYPE_RENDEZVOUS)) ||
320 ((workingPtr->hdrtype == AIM_FRAMETYPE_OSCAR) &&
321 (workingPtr->conn->type == AIM_CONN_TYPE_RENDEZVOUS))) {
322 printf("faim: rxhandlers: incompatible frame type %d on connection type 0x%04x\n", workingPtr->hdrtype, workingPtr->conn->type);
323 workingPtr->handled = 1;
324 continue;
325 }
326
b8d0da45 327 switch(workingPtr->conn->type) {
328 case -1:
329 /*
330 * This can happen if we have a queued command
331 * that was recieved after a connection has
332 * been terminated. In which case, the handler
333 * list has been cleared, and there's nothing we
334 * can do for it. We can only cancel it.
335 */
336 workingPtr->handled = 1;
337 break;
338 case AIM_CONN_TYPE_AUTH: {
339 u_long head;
340
341 head = aimutil_get32(workingPtr->data);
342 if (head == 0x00000001) {
343 faimdprintf(1, "got connection ack on auth line\n");
344 workingPtr->handled = 1;
f0a7908e 345 } else if (workingPtr->hdr.oscar.type == 0x0004) {
346 workingPtr->handled = aim_authparse(sess, workingPtr);
347 } else {
b8d0da45 348 u_short family,subtype;
349
350 family = aimutil_get16(workingPtr->data);
351 subtype = aimutil_get16(workingPtr->data+2);
352
353 switch (family) {
354 /* New login protocol */
b8d0da45 355 case 0x0017:
356 if (subtype == 0x0001)
357 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0017, 0x0001, workingPtr);
358 else if (subtype == 0x0003)
359 workingPtr->handled = aim_authparse(sess, workingPtr);
360 else if (subtype == 0x0007)
b5bc2a8c 361 workingPtr->handled = aim_authkeyparse(sess, workingPtr);
b8d0da45 362 else
363 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0017, 0xffff, workingPtr);
364 break;
b5bc2a8c 365 case 0x0007:
366 if (subtype == 0x0005)
367 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_ADM, AIM_CB_ADM_INFOCHANGE_REPLY, workingPtr);
368 break;
369 case AIM_CB_FAM_SPECIAL:
370 if (subtype == AIM_CB_SPECIAL_DEBUGCONN_CONNECT) {
371 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, family, subtype, workingPtr);
372 break;
373 } /* others fall through */
374 default:
375#if 0
376 /* Old login protocol */
377 /* any user callbacks will be called from here */
378 workingPtr->handled = aim_authparse(sess, workingPtr);
b8d0da45 379 break;
01b59e1e 380#endif
b8d0da45 381 }
382 }
383 break;
384 }
385 case AIM_CONN_TYPE_BOS: {
386 u_short family;
387 u_short subtype;
5e02cf44 388
b69540e3 389 if (workingPtr->hdr.oscar.type == 0x04) {
5e02cf44 390 workingPtr->handled = aim_negchan_middle(sess, workingPtr);
391 break;
392 }
393
b8d0da45 394 family = aimutil_get16(workingPtr->data);
395 subtype = aimutil_get16(workingPtr->data+2);
396
397 switch (family) {
398 case 0x0000: /* not really a family, but it works */
399 if (subtype == 0x0001)
400 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0000, 0x0001, workingPtr);
401 else
402 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, workingPtr);
403 break;
404 case 0x0001: /* Family: General */
405 switch (subtype) {
406 case 0x0001:
407 workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
408 break;
409 case 0x0003:
410 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0003, workingPtr);
411 break;
412 case 0x0005:
413 workingPtr->handled = aim_handleredirect_middle(sess, workingPtr);
414 break;
415 case 0x0007:
416 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0007, workingPtr);
417 break;
418 case 0x000a:
1a8c261b 419 workingPtr->handled = aim_parse_ratechange_middle(sess, workingPtr);
b8d0da45 420 break;
421 case 0x000f:
422 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x000f, workingPtr);
423 break;
98c88242 424 case 0x0010:
425 workingPtr->handled = aim_parse_evilnotify_middle(sess, workingPtr);
426 break;
b8d0da45 427 case 0x0013:
428 workingPtr->handled = aim_parsemotd_middle(sess, workingPtr);
429 break;
430 default:
431 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_GEN, AIM_CB_GEN_DEFAULT, workingPtr);
432 break;
433 }
96f8b1ed 434 break;
b8d0da45 435 case 0x0002: /* Family: Location */
436 switch (subtype) {
437 case 0x0001:
96f8b1ed 438 workingPtr->handled = aim_parse_locateerr(sess, workingPtr);
b8d0da45 439 break;
440 case 0x0003:
441 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0002, 0x0003, workingPtr);
442 break;
443 case 0x0006:
444 workingPtr->handled = aim_parse_userinfo_middle(sess, workingPtr);
445 break;
446 default:
447 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_LOC, AIM_CB_LOC_DEFAULT, workingPtr);
448 break;
449 }
96f8b1ed 450 break;
b8d0da45 451 case 0x0003: /* Family: Buddy List */
452 switch (subtype) {
453 case 0x0001:
454 workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
455 break;
456 case 0x0003:
96f8b1ed 457 workingPtr->handled = aim_parse_buddyrights(sess, workingPtr);
b8d0da45 458 break;
459 case 0x000b: /* oncoming buddy */
460 workingPtr->handled = aim_parse_oncoming_middle(sess, workingPtr);
461 break;
462 case 0x000c: /* offgoing buddy */
463 workingPtr->handled = aim_parse_offgoing_middle(sess, workingPtr);
464 break;
465 default:
466 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_BUD, AIM_CB_BUD_DEFAULT, workingPtr);
467 }
468 break;
469 case 0x0004: /* Family: Messeging */
470 switch (subtype) {
471 case 0x0001:
472 workingPtr->handled = aim_parse_msgerror_middle(sess, workingPtr);
473 break;
474 case 0x0005:
475 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0004, 0x0005, workingPtr);
476 break;
e5012450 477 case 0x0006:
478 workingPtr->handled = aim_parse_outgoing_im_middle(sess, workingPtr);
479 break;
b8d0da45 480 case 0x0007:
481 workingPtr->handled = aim_parse_incoming_im_middle(sess, workingPtr);
482 break;
483 case 0x000a:
96f8b1ed 484 workingPtr->handled = aim_parse_missedcall(sess, workingPtr);
b8d0da45 485 break;
1a8c261b 486 case 0x000c:
487 workingPtr->handled = aim_parse_msgack_middle(sess, workingPtr);
488 break;
b8d0da45 489 default:
490 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_MSG, AIM_CB_MSG_DEFAULT, workingPtr);
491 }
492 break;
493 case 0x0009:
494 if (subtype == 0x0001)
495 workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
496 else if (subtype == 0x0003)
96f8b1ed 497 workingPtr->handled = aim_parse_bosrights(sess, workingPtr);
b8d0da45 498 else
499 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_BOS, AIM_CB_BOS_DEFAULT, workingPtr);
500 break;
501 case 0x000a: /* Family: User lookup */
502 switch (subtype) {
503 case 0x0001:
504 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x000a, 0x0001, workingPtr);
505 break;
506 case 0x0003:
507 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x000a, 0x0003, workingPtr);
508 break;
509 default:
510 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_LOK, AIM_CB_LOK_DEFAULT, workingPtr);
511 }
512 break;
96f8b1ed 513 case 0x000b: {
b8d0da45 514 if (subtype == 0x0001)
515 workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
516 else if (subtype == 0x0002)
517 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x000b, 0x0002, workingPtr);
518 else
519 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_STS, AIM_CB_STS_DEFAULT, workingPtr);
520 break;
96f8b1ed 521 }
522 case AIM_CB_FAM_SPECIAL:
523 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, family, subtype, workingPtr);
524 break;
b8d0da45 525 default:
526 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, workingPtr);
527 break;
96f8b1ed 528 } /* switch(family) */
b8d0da45 529 break;
96f8b1ed 530 } /* AIM_CONN_TYPE_BOS */
b8d0da45 531 case AIM_CONN_TYPE_CHATNAV: {
532 u_short family;
533 u_short subtype;
534 family = aimutil_get16(workingPtr->data);
535 subtype= aimutil_get16(workingPtr->data+2);
536
537 if ((family == 0x0002) && (subtype == 0x0006)) {
538 workingPtr->handled = 1;
539 aim_conn_setstatus(workingPtr->conn, AIM_CONN_STATUS_READY);
540 } else if ((family == 0x000d) && (subtype == 0x0009)) {
541 workingPtr->handled = aim_chatnav_parse_info(sess, workingPtr);
542 } else {
543 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, family, subtype, workingPtr);
9de3ca7e 544 }
b8d0da45 545 break;
546 }
547 case AIM_CONN_TYPE_CHAT: {
548 u_short family, subtype;
549
550 family = aimutil_get16(workingPtr->data);
551 subtype= aimutil_get16(workingPtr->data+2);
552
553 if ((family == 0x0000) && (subtype == 0x00001))
554 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0000, 0x0001, workingPtr);
555 else if (family == 0x0001) {
556 if (subtype == 0x0001)
557 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0001, workingPtr);
558 else if (subtype == 0x0003)
559 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0003, workingPtr);
560 else if (subtype == 0x0007)
561 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0007, workingPtr);
562 else
cd71e19b 563 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, family, subtype, workingPtr);
b8d0da45 564 } else if (family == 0x000e) {
565 if (subtype == 0x0002)
566 workingPtr->handled = aim_chat_parse_infoupdate(sess, workingPtr);
567 else if (subtype == 0x0003)
568 workingPtr->handled = aim_chat_parse_joined(sess, workingPtr);
569 else if (subtype == 0x0004)
570 workingPtr->handled = aim_chat_parse_leave(sess, workingPtr);
571 else if (subtype == 0x0006)
572 workingPtr->handled = aim_chat_parse_incoming(sess, workingPtr);
573 else
574 printf("Chat: unknown snac %04x/%04x\n", family, subtype);
575 } else {
576 printf("Chat: unknown snac %04x/%04x\n", family, subtype);
577 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_DEFAULT, workingPtr);
578 }
579 break;
580 }
b69540e3 581 case AIM_CONN_TYPE_RENDEZVOUS: {
582 /* make sure that we only get OFT frames on these connections */
583 if (workingPtr->hdrtype != AIM_FRAMETYPE_OFT) {
584 printf("faim: internal error: non-OFT frames on OFT connection\n");
585 workingPtr->handled = 1; /* get rid of it */
586 break;
587 }
588
589 /* XXX: implement this */
590 printf("faim: OFT frame!\n");
591
592 break;
593 }
7392c79f 594 case AIM_CONN_TYPE_RENDEZVOUS_OUT: {
595 /* not possible */
596 break;
597 }
b8d0da45 598 default:
b69540e3 599 printf("\ninternal error: unknown connection type (very bad.) (type = %d, fd = %d, commandlen = %02x)\n\n", workingPtr->conn->type, workingPtr->conn->fd, workingPtr->commandlen);
b8d0da45 600 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, workingPtr);
601 break;
602 }
9de3ca7e 603 }
b8d0da45 604 }
9de3ca7e 605
b8d0da45 606 /*
607 * This doesn't have to be called here. It could easily be done
608 * by a seperate thread or something. It's an administrative operation,
609 * and can take a while. Though the less you call it the less memory
610 * you'll have :)
611 */
612 aim_purge_rxqueue(sess);
9de3ca7e 613
614 return 0;
615}
616
1a8c261b 617int aim_parse_msgack_middle(struct aim_session_t *sess, struct command_rx_struct *command)
618{
619 rxcallback_t userfunc = NULL;
620 char sn[MAXSNLEN];
621 unsigned short type;
622 int i = 10+8; /* skip SNAC and cookie */
623 int ret = 1;
624 unsigned char snlen;
625
626 type = aimutil_get16(command->data+i);
627 i += 2;
628
629 snlen = aimutil_get8(command->data+i);
630 i++;
631
632 memset(sn, 0, sizeof(sn));
633 strncpy(sn, command->data+i, snlen);
634
635 if ((userfunc = aim_callhandler(command->conn, 0x0004, 0x000c)))
636 ret = userfunc(sess, command, type, sn);
637
638 return ret;
639}
640
641int aim_parse_ratechange_middle(struct aim_session_t *sess, struct command_rx_struct *command)
642{
643 rxcallback_t userfunc = NULL;
1a8c261b 644 int ret = 1;
645 unsigned long newrate;
646
647 if (command->commandlen != 0x2f) {
648 printf("faim: unknown rate change length 0x%04x\n", command->commandlen);
649 return 1;
650 }
651
652 newrate = aimutil_get32(command->data+34);
653
654 if ((userfunc = aim_callhandler(command->conn, 0x0001, 0x000a)))
655 ret = userfunc(sess, command, newrate);
656
657 return ret;
658}
659
98c88242 660int aim_parse_evilnotify_middle(struct aim_session_t *sess, struct command_rx_struct *command)
661{
662 rxcallback_t userfunc = NULL;
663 int ret = 1, pos;
664 char *sn = NULL;
665
666 if(command->commandlen < 12) /* a warning level dec sends this */
667 return 1;
668
669 if ((pos = aimutil_get8(command->data+ 12)) > MAXSNLEN)
670 return 1;
671
672 if(!(sn = (char *)calloc(1, pos+1)))
673 return 1;
674
675 memcpy(sn, command->data+13, pos);
676
677 if ((userfunc = aim_callhandler(command->conn, 0x0001, 0x0010)))
678 ret = userfunc(sess, command, sn);
679
0e80bdc3 680 free(sn);
681
98c88242 682 return ret;
683}
684
01b59e1e 685int aim_parsemotd_middle(struct aim_session_t *sess,
7392c79f 686 struct command_rx_struct *command, ...)
9de3ca7e 687{
688 rxcallback_t userfunc = NULL;
01b59e1e 689 char *msg;
690 int ret=1;
691 struct aim_tlvlist_t *tlvlist;
692 u_short id;
693
694 /*
98c88242 695 * Code.
696 *
697 * Valid values:
698 * 1 Mandatory upgrade
699 * 2 Advisory upgrade
700 * 3 System bulletin
701 * 4 Nothing's wrong ("top o the world" -- normal)
702 *
01b59e1e 703 */
704 id = aimutil_get16(command->data+10);
705
706 /*
707 * TLVs follow
708 */
b13c9e13 709 if (!(tlvlist = aim_readtlvchain(command->data+12, command->commandlen-12)))
710 return ret;
711
712 if (!(msg = aim_gettlv_str(tlvlist, 0x000b, 1))) {
713 aim_freetlvchain(&tlvlist);
714 return ret;
715 }
01b59e1e 716
717 userfunc = aim_callhandler(command->conn, 0x0001, 0x0013);
718 if (userfunc)
719 ret = userfunc(sess, command, id, msg);
9de3ca7e 720
01b59e1e 721 aim_freetlvchain(&tlvlist);
b13c9e13 722 free(msg);
9de3ca7e 723
b13c9e13 724 return ret;
9de3ca7e 725}
726
a25832e6 727int aim_handleredirect_middle(struct aim_session_t *sess,
728 struct command_rx_struct *command, ...)
9de3ca7e 729{
01b59e1e 730 struct aim_tlv_t *tmptlv = NULL;
9de3ca7e 731 int serviceid = 0x00;
01b59e1e 732 char cookie[AIM_COOKIELEN];
9de3ca7e 733 char *ip = NULL;
734 rxcallback_t userfunc = NULL;
01b59e1e 735 struct aim_tlvlist_t *tlvlist;
736 int ret = 1;
737
0e2be272 738 if (!(tlvlist = aim_readtlvchain(command->data+10, command->commandlen-10)))
739 {
740 printf("libfaim: major bug: unable to read tlvchain from redirect\n");
741 return ret;
742 }
01b59e1e 743
0e2be272 744 if (!(tmptlv = aim_gettlv(tlvlist, 0x000d, 1)))
745 {
746 printf("libfaim: major bug: no service ID in tlvchain from redirect\n");
747 aim_freetlvchain(&tlvlist);
748 return ret;
749 }
01b59e1e 750 serviceid = aimutil_get16(tmptlv->value);
751
0e2be272 752 if (!(ip = aim_gettlv_str(tlvlist, 0x0005, 1)))
753 {
754 printf("libfaim: major bug: no IP in tlvchain from redirect (service 0x%02x)\n", serviceid);
b13c9e13 755 free(ip);
0e2be272 756 aim_freetlvchain(&tlvlist);
757 return ret;
758 }
01b59e1e 759
0e2be272 760 if (!(tmptlv = aim_gettlv(tlvlist, 0x0006, 1)))
761 {
762 printf("libfaim: major bug: no cookie in tlvchain from redirect (service 0x%02x)\n", serviceid);
b13c9e13 763 free(ip);
0e2be272 764 aim_freetlvchain(&tlvlist);
765 return ret;
766 }
01b59e1e 767 memcpy(cookie, tmptlv->value, AIM_COOKIELEN);
9de3ca7e 768
0c20631f 769 if (serviceid == AIM_CONN_TYPE_CHAT)
770 {
771 /*
772 * Chat hack.
773 *
774 */
775 userfunc = aim_callhandler(command->conn, 0x0001, 0x0005);
776 if (userfunc)
777 ret = userfunc(sess, command, serviceid, ip, cookie, sess->pendingjoin);
778 free(sess->pendingjoin);
779 sess->pendingjoin = NULL;
780 }
781 else
782 {
783 userfunc = aim_callhandler(command->conn, 0x0001, 0x0005);
784 if (userfunc)
785 ret = userfunc(sess, command, serviceid, ip, cookie);
786 }
0e2be272 787
b13c9e13 788 free(ip);
01b59e1e 789 aim_freetlvchain(&tlvlist);
790
791 return ret;
9de3ca7e 792}
793
a25832e6 794int aim_parse_unknown(struct aim_session_t *sess,
795 struct command_rx_struct *command, ...)
9de3ca7e 796{
797 u_int i = 0;
798
b8d0da45 799 faimdprintf(1, "\nRecieved unknown packet:");
9de3ca7e 800
801 for (i = 0; i < command->commandlen; i++)
802 {
803 if ((i % 8) == 0)
71e609e9 804 faimdprintf(1, "\n\t");
9de3ca7e 805
71e609e9 806 faimdprintf(1, "0x%2x ", command->data[i]);
9de3ca7e 807 }
808
b1a4ea45 809 faimdprintf(1, "\n\n");
9de3ca7e 810
811 return 1;
812}
813
814
5e02cf44 815int aim_negchan_middle(struct aim_session_t *sess,
816 struct command_rx_struct *command)
817{
818 struct aim_tlvlist_t *tlvlist;
819 char *msg = NULL;
820 unsigned short code = 0;
821 struct aim_tlv_t *tmptlv;
822 rxcallback_t userfunc = NULL;
823 int ret = 1;
824
825 tlvlist = aim_readtlvchain(command->data, command->commandlen);
826
827 if ((tmptlv = aim_gettlv(tlvlist, 0x0009, 1)))
828 code = aimutil_get16(tmptlv->value);
829
830 if ((tmptlv = aim_gettlv(tlvlist, 0x000b, 1)))
831 msg = aim_gettlv_str(tlvlist, 0x000b, 1);
832
833 userfunc = aim_callhandler(command->conn,
834 AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR);
835 if (userfunc)
836 ret = userfunc(sess, command, code, msg);
837
838 aim_freetlvchain(&tlvlist);
839 free(msg);
840
841 return ret;
842}
843
9de3ca7e 844/*
845 * aim_parse_generalerrs()
846 *
847 * Middle handler for 0x0001 snac of each family.
848 *
849 */
a25832e6 850int aim_parse_generalerrs(struct aim_session_t *sess,
851 struct command_rx_struct *command, ...)
9de3ca7e 852{
853 u_short family;
854 u_short subtype;
a25832e6 855
856 family = aimutil_get16(command->data+0);
857 subtype= aimutil_get16(command->data+2);
9de3ca7e 858
859 switch(family)
860 {
861 default:
862 /* Unknown family */
a25832e6 863 return aim_callhandler_noparam(sess, command->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, command);
9de3ca7e 864 }
865
866 return 1;
867}
868
869
870
This page took 3.373322 seconds and 5 git commands to generate.