]>
Commit | Line | Data |
---|---|---|
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 | 16 | int bleck(struct aim_session_t *sess,struct command_rx_struct *workingPtr, ...) |
9de3ca7e | 17 | { |
18 | u_short family; | |
19 | u_short subtype; | |
20 | family = (workingPtr->data[0] << 8) + workingPtr->data[1]; | |
21 | subtype = (workingPtr->data[2] << 8) + workingPtr->data[3]; | |
24286d93 | 22 | printf("bleck: null handler for %04x/%04x\n", family, subtype); |
9de3ca7e | 23 | return 1; |
24 | } | |
25 | ||
a25832e6 | 26 | int aim_conn_addhandler(struct aim_session_t *sess, |
27 | struct aim_conn_t *conn, | |
9de3ca7e | 28 | u_short family, |
29 | u_short type, | |
30 | rxcallback_t newhandler, | |
31 | u_short flags) | |
32 | { | |
33 | struct aim_rxcblist_t *new,*cur; | |
34 | ||
35 | if (!conn) | |
36 | return -1; | |
37 | ||
38 | #if debug > 0 | |
39 | printf("aim_conn_addhandler: adding for %04x/%04x\n", family, type); | |
40 | #endif | |
41 | ||
42 | new = (struct aim_rxcblist_t *)calloc(1, sizeof(struct aim_rxcblist_t)); | |
43 | new->family = family; | |
44 | new->type = type; | |
45 | new->flags = flags; | |
46 | if (!newhandler) | |
47 | new->handler = &bleck; | |
48 | else | |
49 | new->handler = newhandler; | |
50 | new->next = NULL; | |
51 | ||
52 | cur = conn->handlerlist; | |
53 | if (!cur) | |
54 | conn->handlerlist = new; | |
55 | else | |
56 | { | |
57 | while (cur->next) | |
58 | cur = cur->next; | |
59 | cur->next = new; | |
60 | } | |
61 | ||
62 | return 0; | |
63 | } | |
64 | ||
65 | int aim_clearhandlers(struct aim_conn_t *conn) | |
66 | { | |
67 | struct aim_rxcblist_t *cur,*tmp; | |
68 | if (!conn) | |
69 | return -1; | |
70 | ||
71 | cur = conn->handlerlist; | |
72 | while(cur) | |
73 | { | |
74 | tmp = cur->next; | |
75 | free(cur); | |
76 | cur = tmp; | |
77 | } | |
78 | return 0; | |
79 | } | |
80 | ||
81 | rxcallback_t aim_callhandler(struct aim_conn_t *conn, | |
82 | u_short family, | |
83 | u_short type) | |
84 | { | |
85 | struct aim_rxcblist_t *cur; | |
86 | ||
87 | if (!conn) | |
88 | return NULL; | |
89 | ||
90 | #if debug > 0 | |
91 | printf("aim_callhandler: calling for %04x/%04x\n", family, type); | |
92 | #endif | |
93 | ||
94 | cur = conn->handlerlist; | |
95 | while(cur) | |
96 | { | |
97 | if ( (cur->family == family) && (cur->type == type) ) | |
98 | return cur->handler; | |
99 | cur = cur->next; | |
100 | } | |
101 | ||
102 | if (type==0xffff) | |
103 | return NULL; | |
104 | return aim_callhandler(conn, family, 0xffff); | |
105 | } | |
106 | ||
a25832e6 | 107 | int aim_callhandler_noparam(struct aim_session_t *sess, |
108 | struct aim_conn_t *conn, | |
9de3ca7e | 109 | u_short family, |
110 | u_short type, | |
111 | struct command_rx_struct *ptr) | |
112 | { | |
113 | rxcallback_t userfunc = NULL; | |
114 | userfunc = aim_callhandler(conn, family, type); | |
115 | if (userfunc) | |
a25832e6 | 116 | return userfunc(sess, ptr); |
9de3ca7e | 117 | return 0; |
118 | } | |
119 | ||
120 | /* | |
121 | aim_rxdispatch() | |
122 | ||
123 | Basically, heres what this should do: | |
124 | 1) Determine correct packet handler for this packet | |
125 | 2) Mark the packet handled (so it can be dequeued in purge_queue()) | |
126 | 3) Send the packet to the packet handler | |
127 | 4) Go to next packet in the queue and start over | |
128 | 5) When done, run purge_queue() to purge handled commands | |
129 | ||
130 | Note that any unhandlable packets should probably be left in the | |
131 | queue. This is the best way to prevent data loss. This means | |
132 | that a single packet may get looked at by this function multiple | |
133 | times. This is more good than bad! This behavior may change. | |
134 | ||
135 | Aren't queue's fun? | |
136 | ||
137 | TODO: Get rid of all the ugly if's. | |
138 | TODO: Clean up. | |
139 | TODO: More support for mid-level handlers. | |
140 | TODO: Allow for NULL handlers. | |
141 | ||
142 | */ | |
a25832e6 | 143 | int aim_rxdispatch(struct aim_session_t *sess) |
9de3ca7e | 144 | { |
145 | int i = 0; | |
146 | struct command_rx_struct *workingPtr = NULL; | |
147 | ||
a25832e6 | 148 | if (sess->queue_incoming == NULL) |
9de3ca7e | 149 | /* this shouldn't really happen, unless the main loop's select is broke */ |
150 | printf("parse_generic: incoming packet queue empty.\n"); | |
151 | else | |
152 | { | |
a25832e6 | 153 | workingPtr = sess->queue_incoming; |
9de3ca7e | 154 | for (i = 0; workingPtr != NULL; i++) |
155 | { | |
156 | switch(workingPtr->conn->type) | |
157 | { | |
158 | case AIM_CONN_TYPE_AUTH: | |
a25832e6 | 159 | { |
160 | u_long head; | |
161 | ||
162 | head = aimutil_get32(workingPtr->data); | |
163 | if (head == 0x00000001) | |
164 | { | |
9de3ca7e | 165 | #if debug > 0 |
a25832e6 | 166 | printf("got connection ack on auth line\n"); |
9de3ca7e | 167 | #endif |
a25832e6 | 168 | workingPtr->handled = 1; |
169 | } | |
170 | else | |
171 | { | |
172 | /* any user callbacks will be called from here */ | |
173 | workingPtr->handled = aim_authparse(sess, workingPtr); | |
174 | } | |
175 | } | |
9de3ca7e | 176 | break; |
177 | case AIM_CONN_TYPE_BOS: | |
178 | { | |
179 | u_short family; | |
180 | u_short subtype; | |
a25832e6 | 181 | |
182 | family = aimutil_get16(workingPtr->data); | |
183 | subtype = aimutil_get16(workingPtr->data+2); | |
184 | ||
9de3ca7e | 185 | switch (family) |
186 | { | |
187 | case 0x0000: /* not really a family, but it works */ | |
188 | if (subtype == 0x0001) | |
a25832e6 | 189 | workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0000, 0x0001, workingPtr); |
9de3ca7e | 190 | else |
a25832e6 | 191 | workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, workingPtr); |
9de3ca7e | 192 | break; |
193 | case 0x0001: /* Family: General */ | |
194 | switch (subtype) | |
195 | { | |
196 | case 0x0001: | |
a25832e6 | 197 | workingPtr->handled = aim_parse_generalerrs(sess, workingPtr); |
9de3ca7e | 198 | break; |
199 | case 0x0003: | |
a25832e6 | 200 | workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0003, workingPtr); |
9de3ca7e | 201 | break; |
202 | case 0x0005: | |
a25832e6 | 203 | workingPtr->handled = aim_handleredirect_middle(sess, workingPtr); |
9de3ca7e | 204 | break; |
205 | case 0x0007: | |
a25832e6 | 206 | workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0007, workingPtr); |
9de3ca7e | 207 | break; |
208 | case 0x000a: | |
a25832e6 | 209 | workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x000a, workingPtr); |
9de3ca7e | 210 | break; |
211 | case 0x000f: | |
a25832e6 | 212 | workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x000f, workingPtr); |
9de3ca7e | 213 | break; |
214 | case 0x0013: | |
a25832e6 | 215 | workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0013, workingPtr); |
9de3ca7e | 216 | break; |
217 | default: | |
a25832e6 | 218 | workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_GEN, AIM_CB_GEN_DEFAULT, workingPtr); |
9de3ca7e | 219 | } |
220 | break; | |
221 | case 0x0002: /* Family: Location */ | |
222 | switch (subtype) | |
223 | { | |
224 | case 0x0001: | |
a25832e6 | 225 | workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0002, 0x0001, workingPtr); |
9de3ca7e | 226 | break; |
227 | case 0x0003: | |
a25832e6 | 228 | workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0002, 0x0003, workingPtr); |
9de3ca7e | 229 | break; |
230 | case 0x0006: | |
a25832e6 | 231 | workingPtr->handled = aim_parse_userinfo_middle(sess, workingPtr); |
9de3ca7e | 232 | break; |
233 | default: | |
a25832e6 | 234 | workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_LOC, AIM_CB_LOC_DEFAULT, workingPtr); |
9de3ca7e | 235 | } |
236 | break; | |
237 | case 0x0003: /* Family: Buddy List */ | |
238 | switch (subtype) | |
239 | { | |
240 | case 0x0001: | |
a25832e6 | 241 | workingPtr->handled = aim_parse_generalerrs(sess, workingPtr); |
9de3ca7e | 242 | break; |
243 | case 0x0003: | |
a25832e6 | 244 | workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0003, 0x0003, workingPtr); |
9de3ca7e | 245 | break; |
246 | case 0x000b: /* oncoming buddy */ | |
a25832e6 | 247 | workingPtr->handled = aim_parse_oncoming_middle(sess, workingPtr); |
9de3ca7e | 248 | break; |
249 | case 0x000c: /* offgoing buddy */ | |
a25832e6 | 250 | workingPtr->handled = aim_parse_offgoing_middle(sess, workingPtr); |
9de3ca7e | 251 | break; |
252 | default: | |
a25832e6 | 253 | workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_BUD, AIM_CB_BUD_DEFAULT, workingPtr); |
9de3ca7e | 254 | } |
255 | break; | |
256 | case 0x0004: /* Family: Messeging */ | |
257 | switch (subtype) | |
258 | { | |
259 | case 0x0001: | |
a25832e6 | 260 | workingPtr->handled = aim_parse_msgerror_middle(sess, workingPtr); |
9de3ca7e | 261 | break; |
262 | case 0x0005: | |
a25832e6 | 263 | workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0004, 0x0005, workingPtr); |
9de3ca7e | 264 | break; |
265 | case 0x0007: | |
a25832e6 | 266 | workingPtr->handled = aim_parse_incoming_im_middle(sess, workingPtr); |
9de3ca7e | 267 | break; |
268 | case 0x000a: | |
a25832e6 | 269 | workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0004, 0x000a, workingPtr); |
9de3ca7e | 270 | break; |
271 | default: | |
a25832e6 | 272 | workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_MSG, AIM_CB_MSG_DEFAULT, workingPtr); |
9de3ca7e | 273 | } |
274 | break; | |
275 | case 0x0009: | |
276 | if (subtype == 0x0001) | |
a25832e6 | 277 | workingPtr->handled = aim_parse_generalerrs(sess, workingPtr); |
9de3ca7e | 278 | else if (subtype == 0x0003) |
a25832e6 | 279 | workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0009, 0x0003, workingPtr); |
9de3ca7e | 280 | else |
a25832e6 | 281 | workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_BOS, AIM_CB_BOS_DEFAULT, workingPtr); |
9de3ca7e | 282 | break; |
283 | case 0x000a: /* Family: User lookup */ | |
284 | switch (subtype) | |
285 | { | |
286 | case 0x0001: | |
a25832e6 | 287 | workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x000a, 0x0001, workingPtr); |
9de3ca7e | 288 | break; |
289 | case 0x0003: | |
a25832e6 | 290 | workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x000a, 0x0003, workingPtr); |
9de3ca7e | 291 | break; |
292 | default: | |
a25832e6 | 293 | workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_LOK, AIM_CB_LOK_DEFAULT, workingPtr); |
9de3ca7e | 294 | } |
295 | break; | |
296 | case 0x000b: | |
297 | if (subtype == 0x0001) | |
a25832e6 | 298 | workingPtr->handled = aim_parse_generalerrs(sess, workingPtr); |
9de3ca7e | 299 | else if (subtype == 0x0002) |
a25832e6 | 300 | workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x000b, 0x0002, workingPtr); |
9de3ca7e | 301 | else |
a25832e6 | 302 | workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_STS, AIM_CB_STS_DEFAULT, workingPtr); |
9de3ca7e | 303 | break; |
304 | default: | |
a25832e6 | 305 | workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, workingPtr); |
9de3ca7e | 306 | break; |
307 | } | |
308 | } | |
309 | break; | |
310 | case AIM_CONN_TYPE_CHATNAV: | |
311 | { | |
312 | u_short family; | |
313 | u_short subtype; | |
a25832e6 | 314 | family = aimutil_get16(workingPtr->data); |
315 | subtype= aimutil_get16(workingPtr->data+2); | |
316 | ||
317 | if ((family == 0x0002) && (subtype == 0x0006)) | |
9de3ca7e | 318 | { |
319 | workingPtr->handled = 1; | |
320 | aim_conn_setstatus(workingPtr->conn, AIM_CONN_STATUS_READY); | |
321 | } | |
322 | else | |
323 | { | |
a25832e6 | 324 | workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, family, subtype, workingPtr); |
9de3ca7e | 325 | } |
326 | } | |
327 | break; | |
328 | case AIM_CONN_TYPE_CHAT: | |
24286d93 | 329 | printf("\nAHH! Dont know what to do with CHAT stuff yet!\n"); |
a25832e6 | 330 | workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_DEFAULT, workingPtr); |
9de3ca7e | 331 | break; |
332 | default: | |
24286d93 | 333 | printf("\nAHHHHH! UNKNOWN CONNECTION TYPE! (0x%02x)\n\n", workingPtr->conn->type); |
a25832e6 | 334 | workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, workingPtr); |
9de3ca7e | 335 | break; |
336 | } | |
a25832e6 | 337 | /* move to next command */ |
9de3ca7e | 338 | workingPtr = workingPtr->next; |
339 | } | |
340 | } | |
341 | ||
a25832e6 | 342 | sess->queue_incoming = aim_purge_rxqueue(sess->queue_incoming); |
9de3ca7e | 343 | |
344 | return 0; | |
345 | } | |
346 | ||
347 | /* | |
348 | * TODO: check and cure memory leakage in this function. | |
a25832e6 | 349 | * TODO: update to use new tlvlist routines |
9de3ca7e | 350 | */ |
a25832e6 | 351 | int aim_authparse(struct aim_session_t *sess, |
352 | struct command_rx_struct *command) | |
9de3ca7e | 353 | { |
354 | rxcallback_t userfunc = NULL; | |
355 | int iserror = 0; | |
356 | struct aim_tlv_t *tlv = NULL; | |
357 | char *errorurl = NULL; | |
358 | short errorcode = 0x00; | |
359 | u_int z = 0; | |
a25832e6 | 360 | u_short family,subtype; |
9de3ca7e | 361 | |
a25832e6 | 362 | family = aimutil_get16(command->data); |
363 | subtype= aimutil_get16(command->data+2); | |
364 | ||
365 | if ( (family == 0x0001) && | |
366 | (subtype== 0x0003) ) | |
9de3ca7e | 367 | { |
368 | /* "server ready" -- can be ignored */ | |
369 | userfunc = aim_callhandler(command->conn, AIM_CB_FAM_GEN, AIM_CB_GEN_SERVERREADY); | |
370 | } | |
a25832e6 | 371 | else if ( (family == 0x0007) && |
372 | (subtype== 0x0005) ) | |
9de3ca7e | 373 | { |
374 | /* "information change reply" */ | |
375 | userfunc = aim_callhandler(command->conn, AIM_CB_FAM_ADM, AIM_CB_ADM_INFOCHANGE_REPLY); | |
376 | } | |
377 | else | |
378 | { | |
379 | /* anything else -- usually used for login; just parse as pure TLVs */ | |
380 | ||
381 | /* | |
382 | * Free up the loginstruct first. | |
383 | */ | |
a25832e6 | 384 | sess->logininfo.screen_name[0] = '\0'; |
385 | if (sess->logininfo.BOSIP) | |
9de3ca7e | 386 | { |
a25832e6 | 387 | free(sess->logininfo.BOSIP); |
388 | sess->logininfo.BOSIP = NULL; | |
9de3ca7e | 389 | } |
a25832e6 | 390 | if (sess->logininfo.email) |
9de3ca7e | 391 | { |
a25832e6 | 392 | free(sess->logininfo.email); |
393 | sess->logininfo.email = NULL; | |
9de3ca7e | 394 | } |
a25832e6 | 395 | sess->logininfo.regstatus = 0; |
9de3ca7e | 396 | |
397 | /* all this block does is figure out if it's an | |
398 | error or a success, nothing more */ | |
399 | while (z < command->commandlen) | |
400 | { | |
401 | tlv = aim_grabtlvstr(&(command->data[z])); | |
402 | switch(tlv->type) | |
403 | { | |
404 | case 0x0001: /* screen name */ | |
a25832e6 | 405 | if (tlv->length >= MAXSNLEN) |
406 | { | |
407 | /* SN too large... truncate */ | |
408 | printf("faim: login: screen name from OSCAR too long! (%d)\n", tlv->length); | |
409 | strncpy(sess->logininfo.screen_name, tlv->value, MAXSNLEN); | |
410 | } | |
411 | else | |
412 | strncpy(sess->logininfo.screen_name, tlv->value, tlv->length); | |
9de3ca7e | 413 | z += 2 + 2 + tlv->length; |
414 | free(tlv); | |
415 | tlv = NULL; | |
416 | break; | |
417 | case 0x0004: /* error URL */ | |
418 | errorurl = tlv->value; | |
419 | z += 2 + 2 + tlv->length; | |
420 | free(tlv); | |
421 | tlv = NULL; | |
422 | break; | |
423 | case 0x0005: /* BOS IP */ | |
a25832e6 | 424 | sess->logininfo.BOSIP = tlv->value; |
9de3ca7e | 425 | z += 2 + 2 + tlv->length; |
426 | free(tlv); | |
427 | tlv = NULL; | |
428 | break; | |
429 | case 0x0006: /* auth cookie */ | |
a25832e6 | 430 | memcpy(sess->logininfo.cookie, tlv->value, AIM_COOKIELEN); |
9de3ca7e | 431 | z += 2 + 2 + tlv->length; |
432 | free(tlv); | |
433 | tlv=NULL; | |
434 | break; | |
435 | case 0x0011: /* email addy */ | |
a25832e6 | 436 | sess->logininfo.email = tlv->value; |
9de3ca7e | 437 | z += 2 + 2 + tlv->length; |
438 | free(tlv); | |
439 | tlv = NULL; | |
440 | break; | |
441 | case 0x0013: /* registration status */ | |
a25832e6 | 442 | sess->logininfo.regstatus = *(tlv->value); |
9de3ca7e | 443 | z += 2 + 2 + tlv->length; |
444 | aim_freetlv(&tlv); | |
445 | break; | |
446 | case 0x0008: /* error code */ | |
447 | errorcode = *(tlv->value); | |
448 | z += 2 + 2 + tlv->length; | |
449 | aim_freetlv(&tlv); | |
450 | iserror = 1; | |
451 | break; | |
452 | default: | |
453 | z += 2 + 2 + tlv->length; | |
454 | aim_freetlv(&tlv); | |
455 | /* dunno */ | |
456 | } | |
457 | } | |
458 | ||
459 | if (iserror && | |
460 | errorurl) | |
461 | { | |
462 | userfunc = aim_callhandler(command->conn, AIM_CB_FAM_GEN, AIM_CB_GEN_ERROR); | |
463 | if (userfunc) | |
a25832e6 | 464 | return userfunc(sess, command, errorurl, errorcode); |
9de3ca7e | 465 | return 0; |
466 | } | |
a25832e6 | 467 | else if (sess->logininfo.screen_name[0] && |
468 | sess->logininfo.cookie[0] && sess->logininfo.BOSIP) | |
9de3ca7e | 469 | { |
470 | userfunc = aim_callhandler(command->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_AUTHSUCCESS); | |
471 | if (userfunc) | |
a25832e6 | 472 | return userfunc(sess, command); |
9de3ca7e | 473 | return 0; |
474 | } | |
475 | else | |
476 | userfunc = aim_callhandler(command->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_AUTHOTHER); | |
477 | } | |
478 | ||
479 | if (userfunc) | |
a25832e6 | 480 | return userfunc(sess, command); |
9de3ca7e | 481 | printf("handler not available!\n"); |
482 | return 0; | |
483 | } | |
484 | ||
485 | /* | |
486 | * TODO: check for and cure any memory leaks here. | |
487 | */ | |
a25832e6 | 488 | int aim_handleredirect_middle(struct aim_session_t *sess, |
489 | struct command_rx_struct *command, ...) | |
9de3ca7e | 490 | { |
491 | struct aim_tlv_t *tlv = NULL; | |
492 | u_int z = 10; | |
493 | int serviceid = 0x00; | |
494 | char *cookie = NULL; | |
495 | char *ip = NULL; | |
496 | rxcallback_t userfunc = NULL; | |
497 | ||
498 | while (z < command->commandlen) | |
499 | { | |
500 | tlv = aim_grabtlvstr(&(command->data[z])); | |
501 | switch(tlv->type) | |
502 | { | |
503 | case 0x000d: /* service id */ | |
504 | aim_freetlv(&tlv); | |
505 | /* regrab as an int */ | |
506 | tlv = aim_grabtlv(&(command->data[z])); | |
a25832e6 | 507 | serviceid = aimutil_get16(tlv->value); |
9de3ca7e | 508 | z += 2 + 2 + tlv->length; |
509 | aim_freetlv(&tlv); | |
510 | break; | |
511 | case 0x0005: /* service server IP */ | |
512 | ip = tlv->value; | |
513 | z += 2 + 2 + tlv->length; | |
514 | free(tlv); | |
515 | tlv = NULL; | |
516 | break; | |
517 | case 0x0006: /* auth cookie */ | |
518 | cookie = tlv->value; | |
519 | z += 2 + 2 + tlv->length; | |
520 | free(tlv); | |
521 | tlv = NULL; | |
522 | break; | |
523 | default: | |
524 | /* dunno */ | |
525 | z += 2 + 2 + tlv->length; | |
526 | aim_freetlv(&tlv); | |
527 | } | |
528 | } | |
529 | userfunc = aim_callhandler(command->conn, 0x0001, 0x0005); | |
530 | if (userfunc) | |
a25832e6 | 531 | return userfunc(sess, command, serviceid, ip, cookie); |
9de3ca7e | 532 | return 0; |
533 | } | |
534 | ||
a25832e6 | 535 | int aim_parse_unknown(struct aim_session_t *sess, |
536 | struct command_rx_struct *command, ...) | |
9de3ca7e | 537 | { |
538 | u_int i = 0; | |
539 | ||
540 | printf("\nRecieved unknown packet:"); | |
541 | ||
542 | for (i = 0; i < command->commandlen; i++) | |
543 | { | |
544 | if ((i % 8) == 0) | |
545 | printf("\n\t"); | |
546 | ||
547 | printf("0x%2x ", command->data[i]); | |
548 | } | |
549 | ||
550 | printf("\n\n"); | |
551 | ||
552 | return 1; | |
553 | } | |
554 | ||
555 | ||
556 | /* | |
557 | * aim_parse_generalerrs() | |
558 | * | |
559 | * Middle handler for 0x0001 snac of each family. | |
560 | * | |
561 | */ | |
a25832e6 | 562 | int aim_parse_generalerrs(struct aim_session_t *sess, |
563 | struct command_rx_struct *command, ...) | |
9de3ca7e | 564 | { |
565 | u_short family; | |
566 | u_short subtype; | |
a25832e6 | 567 | |
568 | family = aimutil_get16(command->data+0); | |
569 | subtype= aimutil_get16(command->data+2); | |
9de3ca7e | 570 | |
571 | switch(family) | |
572 | { | |
573 | default: | |
574 | /* Unknown family */ | |
a25832e6 | 575 | return aim_callhandler_noparam(sess, command->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, command); |
9de3ca7e | 576 | } |
577 | ||
578 | return 1; | |
579 | } | |
580 | ||
581 | ||
582 |