237
|
1 /*
|
|
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 *
|
|
8 */
|
|
9
|
|
10 #include <aim.h>
|
2
|
11
|
|
12 /*
|
237
|
13 * Bleck functions get called when there's no non-bleck functions
|
|
14 * around to cleanup the mess...
|
2
|
15 */
|
237
|
16 int bleck(struct aim_session_t *sess,struct command_rx_struct *workingPtr, ...)
|
|
17 {
|
|
18 u_short family;
|
|
19 u_short subtype;
|
2
|
20
|
237
|
21 u_short maxf;
|
|
22 u_short maxs;
|
2
|
23
|
237
|
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 };
|
2
|
169
|
237
|
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
|
2
|
181 return 1;
|
|
182 }
|
|
183
|
237
|
184 int aim_conn_addhandler(struct aim_session_t *sess,
|
|
185 struct aim_conn_t *conn,
|
|
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
|
|
196 faimdprintf(1, "aim_conn_addhandler: adding for %04x/%04x\n", family, type);
|
|
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
|
|
221 int aim_clearhandlers(struct aim_conn_t *conn)
|
|
222 {
|
|
223 struct aim_rxcblist_t *cur,*tmp;
|
|
224 if (!conn)
|
|
225 return -1;
|
2
|
226
|
237
|
227 cur = conn->handlerlist;
|
|
228 while(cur)
|
|
229 {
|
|
230 tmp = cur->next;
|
|
231 free(cur);
|
|
232 cur = tmp;
|
|
233 }
|
|
234 return 0;
|
|
235 }
|
2
|
236
|
237
|
237 rxcallback_t aim_callhandler(struct aim_conn_t *conn,
|
|
238 u_short family,
|
|
239 u_short type)
|
2
|
240 {
|
237
|
241 struct aim_rxcblist_t *cur;
|
|
242
|
|
243 if (!conn)
|
|
244 return NULL;
|
|
245
|
|
246 faimdprintf(1, "aim_callhandler: calling for %04x/%04x\n", family, type);
|
2
|
247
|
237
|
248 cur = conn->handlerlist;
|
|
249 while(cur)
|
2
|
250 {
|
237
|
251 if ( (cur->family == family) && (cur->type == type) )
|
|
252 return cur->handler;
|
|
253 cur = cur->next;
|
2
|
254 }
|
237
|
255
|
|
256 if (type==0xffff)
|
|
257 return NULL;
|
|
258 return aim_callhandler(conn, family, 0xffff);
|
|
259 }
|
|
260
|
|
261 int aim_callhandler_noparam(struct aim_session_t *sess,
|
|
262 struct aim_conn_t *conn,
|
|
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)
|
|
270 return userfunc(sess, ptr);
|
|
271 return 1; /* XXX */
|
2
|
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 */
|
237
|
297 int aim_rxdispatch(struct aim_session_t *sess)
|
2
|
298 {
|
|
299 int i = 0;
|
|
300 struct command_rx_struct *workingPtr = NULL;
|
|
301
|
237
|
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;
|
|
307 for (i = 0; workingPtr != NULL; workingPtr = workingPtr->next, i++) {
|
|
308 /*
|
|
309 * XXX: This is still fairly ugly.
|
|
310 */
|
|
311 if (workingPtr->handled)
|
|
312 continue;
|
|
313
|
|
314 switch(workingPtr->conn->type) {
|
|
315 case -1:
|
|
316 /*
|
|
317 * This can happen if we have a queued command
|
|
318 * that was recieved after a connection has
|
|
319 * been terminated. In which case, the handler
|
|
320 * list has been cleared, and there's nothing we
|
|
321 * can do for it. We can only cancel it.
|
|
322 */
|
|
323 workingPtr->handled = 1;
|
|
324 break;
|
|
325 case AIM_CONN_TYPE_AUTH: {
|
|
326 u_long head;
|
|
327
|
|
328 head = aimutil_get32(workingPtr->data);
|
|
329 if (head == 0x00000001) {
|
|
330 faimdprintf(1, "got connection ack on auth line\n");
|
|
331 workingPtr->handled = 1;
|
|
332 } else {
|
|
333 u_short family,subtype;
|
|
334
|
|
335 family = aimutil_get16(workingPtr->data);
|
|
336 subtype = aimutil_get16(workingPtr->data+2);
|
|
337
|
|
338 switch (family) {
|
|
339 /* New login protocol */
|
|
340 #ifdef SNACLOGIN
|
|
341 case 0x0017:
|
|
342 if (subtype == 0x0001)
|
|
343 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0017, 0x0001, workingPtr);
|
|
344 else if (subtype == 0x0003)
|
|
345 workingPtr->handled = aim_authparse(sess, workingPtr);
|
|
346 else if (subtype == 0x0007)
|
|
347 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0017, 0x0007, workingPtr);
|
|
348 else
|
|
349 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0017, 0xffff, workingPtr);
|
|
350 break;
|
|
351 #else
|
|
352 /* XXX: this isnt foolproof */
|
|
353 case 0x0001:
|
|
354 if (subtype == 0x0003)
|
|
355 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_GEN, AIM_CB_GEN_SERVERREADY, workingPtr);
|
|
356 else
|
|
357 workingPtr->handled = aim_authparse(sess, workingPtr);
|
|
358 break;
|
|
359 case 0x0007:
|
|
360 if (subtype == 0x0005)
|
|
361 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_ADM, AIM_CB_ADM_INFOCHANGE_REPLY, workingPtr);
|
|
362 break;
|
|
363 default:
|
|
364 /* Old login protocol */
|
|
365 /* any user callbacks will be called from here */
|
|
366 workingPtr->handled = aim_authparse(sess, workingPtr);
|
2
|
367 #endif
|
237
|
368 }
|
2
|
369 }
|
237
|
370 break;
|
|
371 }
|
|
372 case AIM_CONN_TYPE_BOS: {
|
|
373 u_short family;
|
|
374 u_short subtype;
|
|
375
|
|
376 family = aimutil_get16(workingPtr->data);
|
|
377 subtype = aimutil_get16(workingPtr->data+2);
|
|
378
|
|
379 switch (family) {
|
|
380 case 0x0000: /* not really a family, but it works */
|
|
381 if (subtype == 0x0001)
|
|
382 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0000, 0x0001, workingPtr);
|
|
383 else
|
|
384 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, workingPtr);
|
|
385 break;
|
|
386 case 0x0001: /* Family: General */
|
|
387 switch (subtype) {
|
|
388 case 0x0001:
|
|
389 workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
|
|
390 break;
|
|
391 case 0x0003:
|
|
392 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0003, workingPtr);
|
|
393 break;
|
|
394 case 0x0005:
|
|
395 workingPtr->handled = aim_handleredirect_middle(sess, workingPtr);
|
|
396 break;
|
|
397 case 0x0007:
|
|
398 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0007, workingPtr);
|
|
399 break;
|
|
400 case 0x000a:
|
|
401 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x000a, workingPtr);
|
|
402 break;
|
|
403 case 0x000f:
|
|
404 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x000f, workingPtr);
|
|
405 break;
|
|
406 case 0x0013:
|
|
407 workingPtr->handled = aim_parsemotd_middle(sess, workingPtr);
|
|
408 break;
|
|
409 default:
|
|
410 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_GEN, AIM_CB_GEN_DEFAULT, workingPtr);
|
|
411 break;
|
|
412 }
|
|
413 case 0x0002: /* Family: Location */
|
|
414 switch (subtype) {
|
|
415 case 0x0001:
|
|
416 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0002, 0x0001, workingPtr);
|
|
417 break;
|
|
418 case 0x0003:
|
|
419 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0002, 0x0003, workingPtr);
|
|
420 break;
|
|
421 case 0x0006:
|
|
422 workingPtr->handled = aim_parse_userinfo_middle(sess, workingPtr);
|
|
423 break;
|
|
424 default:
|
|
425 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_LOC, AIM_CB_LOC_DEFAULT, workingPtr);
|
|
426 break;
|
|
427 }
|
|
428 case 0x0003: /* Family: Buddy List */
|
|
429 switch (subtype) {
|
|
430 case 0x0001:
|
|
431 workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
|
|
432 break;
|
|
433 case 0x0003:
|
|
434 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0003, 0x0003, workingPtr);
|
|
435 break;
|
|
436 case 0x000b: /* oncoming buddy */
|
|
437 workingPtr->handled = aim_parse_oncoming_middle(sess, workingPtr);
|
|
438 break;
|
|
439 case 0x000c: /* offgoing buddy */
|
|
440 workingPtr->handled = aim_parse_offgoing_middle(sess, workingPtr);
|
|
441 break;
|
|
442 default:
|
|
443 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_BUD, AIM_CB_BUD_DEFAULT, workingPtr);
|
|
444 }
|
|
445 break;
|
|
446 case 0x0004: /* Family: Messeging */
|
|
447 switch (subtype) {
|
|
448 case 0x0001:
|
|
449 workingPtr->handled = aim_parse_msgerror_middle(sess, workingPtr);
|
|
450 break;
|
|
451 case 0x0005:
|
|
452 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0004, 0x0005, workingPtr);
|
|
453 break;
|
|
454 case 0x0007:
|
|
455 workingPtr->handled = aim_parse_incoming_im_middle(sess, workingPtr);
|
|
456 break;
|
|
457 case 0x000a:
|
|
458 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0004, 0x000a, workingPtr);
|
|
459 break;
|
|
460 default:
|
|
461 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_MSG, AIM_CB_MSG_DEFAULT, workingPtr);
|
|
462 }
|
|
463 break;
|
|
464 case 0x0009:
|
|
465 if (subtype == 0x0001)
|
|
466 workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
|
|
467 else if (subtype == 0x0003)
|
|
468 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0009, 0x0003, workingPtr);
|
|
469 else
|
|
470 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_BOS, AIM_CB_BOS_DEFAULT, workingPtr);
|
|
471 break;
|
|
472 case 0x000a: /* Family: User lookup */
|
|
473 switch (subtype) {
|
|
474 case 0x0001:
|
|
475 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x000a, 0x0001, workingPtr);
|
|
476 break;
|
|
477 case 0x0003:
|
|
478 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x000a, 0x0003, workingPtr);
|
|
479 break;
|
|
480 default:
|
|
481 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_LOK, AIM_CB_LOK_DEFAULT, workingPtr);
|
|
482 }
|
|
483 break;
|
|
484 case 0x000b:
|
|
485 if (subtype == 0x0001)
|
|
486 workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
|
|
487 else if (subtype == 0x0002)
|
|
488 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x000b, 0x0002, workingPtr);
|
|
489 else
|
|
490 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_STS, AIM_CB_STS_DEFAULT, workingPtr);
|
|
491 break;
|
|
492 default:
|
|
493 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, workingPtr);
|
|
494 break;
|
|
495 }
|
|
496 break;
|
|
497 }
|
|
498 case AIM_CONN_TYPE_CHATNAV: {
|
|
499 u_short family;
|
|
500 u_short subtype;
|
|
501 family = aimutil_get16(workingPtr->data);
|
|
502 subtype= aimutil_get16(workingPtr->data+2);
|
|
503
|
|
504 if ((family == 0x0002) && (subtype == 0x0006)) {
|
|
505 workingPtr->handled = 1;
|
|
506 aim_conn_setstatus(workingPtr->conn, AIM_CONN_STATUS_READY);
|
|
507 } else if ((family == 0x000d) && (subtype == 0x0009)) {
|
|
508 workingPtr->handled = aim_chatnav_parse_info(sess, workingPtr);
|
|
509 } else {
|
|
510 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, family, subtype, workingPtr);
|
|
511 }
|
|
512 break;
|
|
513 }
|
|
514 case AIM_CONN_TYPE_CHAT: {
|
|
515 u_short family, subtype;
|
|
516
|
|
517 family = aimutil_get16(workingPtr->data);
|
|
518 subtype= aimutil_get16(workingPtr->data+2);
|
|
519
|
|
520 if ((family == 0x0000) && (subtype == 0x00001))
|
|
521 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0000, 0x0001, workingPtr);
|
|
522 else if (family == 0x0001) {
|
|
523 if (subtype == 0x0001)
|
|
524 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0001, workingPtr);
|
|
525 else if (subtype == 0x0003)
|
|
526 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0003, workingPtr);
|
|
527 else if (subtype == 0x0007)
|
|
528 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0007, workingPtr);
|
|
529 else
|
|
530 printf("Chat: unknown snac %04x/%04x\n", family, subtype);
|
|
531 } else if (family == 0x000e) {
|
|
532 if (subtype == 0x0002)
|
|
533 workingPtr->handled = aim_chat_parse_infoupdate(sess, workingPtr);
|
|
534 else if (subtype == 0x0003)
|
|
535 workingPtr->handled = aim_chat_parse_joined(sess, workingPtr);
|
|
536 else if (subtype == 0x0004)
|
|
537 workingPtr->handled = aim_chat_parse_leave(sess, workingPtr);
|
|
538 else if (subtype == 0x0006)
|
|
539 workingPtr->handled = aim_chat_parse_incoming(sess, workingPtr);
|
|
540 else
|
|
541 printf("Chat: unknown snac %04x/%04x\n", family, subtype);
|
|
542 } else {
|
|
543 printf("Chat: unknown snac %04x/%04x\n", family, subtype);
|
|
544 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_DEFAULT, workingPtr);
|
|
545 }
|
|
546 break;
|
|
547 }
|
|
548 default:
|
|
549 printf("\ninternal error: unknown connection type (very bad.) (type = %d, fd = %d, channel = %02x, commandlen = %02x)\n\n", workingPtr->conn->type, workingPtr->conn->fd, workingPtr->type, workingPtr->commandlen);
|
|
550 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, workingPtr);
|
|
551 break;
|
|
552 }
|
2
|
553 }
|
237
|
554 }
|
2
|
555
|
237
|
556 /*
|
|
557 * This doesn't have to be called here. It could easily be done
|
|
558 * by a seperate thread or something. It's an administrative operation,
|
|
559 * and can take a while. Though the less you call it the less memory
|
|
560 * you'll have :)
|
|
561 */
|
|
562 aim_purge_rxqueue(sess);
|
2
|
563
|
|
564 return 0;
|
|
565 }
|
|
566
|
237
|
567 int aim_parsemotd_middle(struct aim_session_t *sess,
|
|
568 struct command_rx_struct *command, ...)
|
2
|
569 {
|
237
|
570 rxcallback_t userfunc = NULL;
|
|
571 char *msg;
|
|
572 int ret=1;
|
|
573 struct aim_tlvlist_t *tlvlist;
|
|
574 u_short id;
|
|
575
|
|
576 /*
|
|
577 * Dunno.
|
|
578 */
|
|
579 id = aimutil_get16(command->data+10);
|
|
580
|
|
581 /*
|
|
582 * TLVs follow
|
|
583 */
|
|
584 tlvlist = aim_readtlvchain(command->data+12, command->commandlen-12);
|
|
585
|
|
586 msg = aim_gettlv_str(tlvlist, 0x000b, 1);
|
|
587
|
|
588 userfunc = aim_callhandler(command->conn, 0x0001, 0x0013);
|
|
589 if (userfunc)
|
|
590 ret = userfunc(sess, command, id, msg);
|
|
591
|
|
592 aim_freetlvchain(&tlvlist);
|
|
593
|
|
594 return ret;
|
|
595
|
|
596 }
|
2
|
597
|
237
|
598 int aim_handleredirect_middle(struct aim_session_t *sess,
|
|
599 struct command_rx_struct *command, ...)
|
|
600 {
|
|
601 struct aim_tlv_t *tmptlv = NULL;
|
|
602 int serviceid = 0x00;
|
|
603 char cookie[AIM_COOKIELEN];
|
|
604 char *ip = NULL;
|
|
605 rxcallback_t userfunc = NULL;
|
|
606 struct aim_tlvlist_t *tlvlist;
|
|
607 int ret = 1;
|
|
608
|
|
609 if (!(tlvlist = aim_readtlvchain(command->data+10, command->commandlen-10)))
|
2
|
610 {
|
237
|
611 printf("libfaim: major bug: unable to read tlvchain from redirect\n");
|
|
612 return ret;
|
|
613 }
|
|
614
|
|
615 if (!(tmptlv = aim_gettlv(tlvlist, 0x000d, 1)))
|
|
616 {
|
|
617 printf("libfaim: major bug: no service ID in tlvchain from redirect\n");
|
|
618 aim_freetlvchain(&tlvlist);
|
|
619 return ret;
|
2
|
620 }
|
237
|
621 serviceid = aimutil_get16(tmptlv->value);
|
|
622
|
|
623 if (!(ip = aim_gettlv_str(tlvlist, 0x0005, 1)))
|
|
624 {
|
|
625 printf("libfaim: major bug: no IP in tlvchain from redirect (service 0x%02x)\n", serviceid);
|
|
626 aim_freetlvchain(&tlvlist);
|
|
627 return ret;
|
|
628 }
|
|
629
|
|
630 if (!(tmptlv = aim_gettlv(tlvlist, 0x0006, 1)))
|
2
|
631 {
|
237
|
632 printf("libfaim: major bug: no cookie in tlvchain from redirect (service 0x%02x)\n", serviceid);
|
|
633 aim_freetlvchain(&tlvlist);
|
|
634 return ret;
|
|
635 }
|
|
636 memcpy(cookie, tmptlv->value, AIM_COOKIELEN);
|
|
637
|
|
638 if (serviceid == AIM_CONN_TYPE_CHAT)
|
|
639 {
|
|
640 /*
|
|
641 * Chat hack.
|
|
642 *
|
|
643 */
|
|
644 userfunc = aim_callhandler(command->conn, 0x0001, 0x0005);
|
|
645 if (userfunc)
|
|
646 ret = userfunc(sess, command, serviceid, ip, cookie, sess->pendingjoin);
|
|
647 free(sess->pendingjoin);
|
|
648 sess->pendingjoin = NULL;
|
2
|
649 }
|
|
650 else
|
|
651 {
|
237
|
652 userfunc = aim_callhandler(command->conn, 0x0001, 0x0005);
|
|
653 if (userfunc)
|
|
654 ret = userfunc(sess, command, serviceid, ip, cookie);
|
|
655 }
|
2
|
656
|
237
|
657 /*
|
|
658 * XXX: Is there a leak here? Where does IP get freed?
|
|
659 */
|
|
660 aim_freetlvchain(&tlvlist);
|
2
|
661
|
237
|
662 return ret;
|
2
|
663 }
|
|
664
|
237
|
665 int aim_parse_unknown(struct aim_session_t *sess,
|
|
666 struct command_rx_struct *command, ...)
|
2
|
667 {
|
237
|
668 u_int i = 0;
|
2
|
669
|
237
|
670 faimdprintf(1, "\nRecieved unknown packet:");
|
2
|
671
|
|
672 for (i = 0; i < command->commandlen; i++)
|
|
673 {
|
|
674 if ((i % 8) == 0)
|
|
675 printf("\n\t");
|
|
676
|
|
677 printf("0x%2x ", command->data[i]);
|
|
678 }
|
|
679
|
|
680 printf("\n\n");
|
|
681
|
|
682 return 1;
|
|
683 }
|
|
684
|
|
685
|
|
686 /*
|
|
687 * aim_parse_generalerrs()
|
|
688 *
|
|
689 * Middle handler for 0x0001 snac of each family.
|
|
690 *
|
|
691 */
|
237
|
692 int aim_parse_generalerrs(struct aim_session_t *sess,
|
|
693 struct command_rx_struct *command, ...)
|
2
|
694 {
|
|
695 u_short family;
|
|
696 u_short subtype;
|
237
|
697
|
|
698 family = aimutil_get16(command->data+0);
|
|
699 subtype= aimutil_get16(command->data+2);
|
2
|
700
|
|
701 switch(family)
|
|
702 {
|
|
703 default:
|
|
704 /* Unknown family */
|
237
|
705 return aim_callhandler_noparam(sess, command->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, command);
|
2
|
706 }
|
|
707
|
|
708 return 1;
|
|
709 }
|
|
710
|
|
711
|
|
712
|