]> andersk Git - libfaim.git/blob - aim_rxhandlers.c
- Fixed a robustness problem in aim_handleredirect_middle()
[libfaim.git] / aim_rxhandlers.c
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 <faim/aim.h>
11
12 /*
13  * Bleck functions get called when there's no non-bleck functions
14  * around to cleanup the mess...
15  */
16 int bleck(struct aim_session_t *sess,struct command_rx_struct *workingPtr, ...)
17 {
18   u_short family;
19   u_short subtype;
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
181   return 1;
182 }
183
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 #if debug > 0
197   printf("aim_conn_addhandler: adding for %04x/%04x\n", family, type);
198 #endif
199
200   new = (struct aim_rxcblist_t *)calloc(1, sizeof(struct aim_rxcblist_t));
201   new->family = family;
202   new->type = type;
203   new->flags = flags;
204   if (!newhandler)
205     new->handler = &bleck;
206   else
207     new->handler = newhandler;
208   new->next = NULL;
209   
210   cur = conn->handlerlist;
211   if (!cur)
212     conn->handlerlist = new;
213   else 
214     {
215       while (cur->next)
216         cur = cur->next;
217       cur->next = new;
218     }
219
220   return 0;
221 }
222
223 int aim_clearhandlers(struct aim_conn_t *conn)
224 {
225  struct aim_rxcblist_t *cur,*tmp;
226  if (!conn)
227    return -1;
228
229  cur = conn->handlerlist;
230  while(cur)
231    {
232      tmp = cur->next;
233      free(cur);
234      cur = tmp;
235    }
236  return 0;
237 }
238
239 rxcallback_t aim_callhandler(struct aim_conn_t *conn,
240                     u_short family,
241                     u_short type)
242 {
243   struct aim_rxcblist_t *cur;
244
245   if (!conn)
246     return NULL;
247
248 #if debug > 0
249   printf("aim_callhandler: calling for %04x/%04x\n", family, type);
250 #endif
251   
252   cur = conn->handlerlist;
253   while(cur)
254     {
255       if ( (cur->family == family) && (cur->type == type) )
256         return cur->handler;
257       cur = cur->next;
258     }
259
260   if (type==0xffff)
261     return NULL;
262   return aim_callhandler(conn, family, 0xffff);
263 }
264
265 int aim_callhandler_noparam(struct aim_session_t *sess,
266                             struct aim_conn_t *conn,
267                             u_short family,
268                             u_short type,
269                             struct command_rx_struct *ptr)
270 {
271   rxcallback_t userfunc = NULL;
272   userfunc = aim_callhandler(conn, family, type);
273   if (userfunc)
274     return userfunc(sess, ptr);
275   return 0;
276 }
277
278 /*
279   aim_rxdispatch()
280
281   Basically, heres what this should do:
282     1) Determine correct packet handler for this packet
283     2) Mark the packet handled (so it can be dequeued in purge_queue())
284     3) Send the packet to the packet handler
285     4) Go to next packet in the queue and start over
286     5) When done, run purge_queue() to purge handled commands
287
288   Note that any unhandlable packets should probably be left in the
289   queue.  This is the best way to prevent data loss.  This means
290   that a single packet may get looked at by this function multiple
291   times.  This is more good than bad!  This behavior may change.
292
293   Aren't queue's fun? 
294
295   TODO: Get rid of all the ugly if's.
296   TODO: Clean up.
297   TODO: More support for mid-level handlers.
298   TODO: Allow for NULL handlers.
299   
300  */
301 int aim_rxdispatch(struct aim_session_t *sess)
302 {
303   int i = 0;
304   struct command_rx_struct *workingPtr = NULL;
305   
306   if (sess->queue_incoming == NULL)
307     /* this shouldn't really happen, unless the main loop's select is broke  */
308     printf("parse_generic: incoming packet queue empty.\n");
309   else
310     {
311       workingPtr = sess->queue_incoming;
312       for (i = 0; workingPtr != NULL; i++)
313         {
314           /*
315            * XXX: This is still fairly ugly.
316            */
317           switch(workingPtr->conn->type)
318             {
319             case -1:
320               /*
321                * This can happen if we have a queued command
322                * that was recieved after a connection has 
323                * been terminated.  In which case, the handler
324                * list has been cleared, and there's nothing we
325                * can do for it.  We can only cancel it.
326                */
327               workingPtr->handled = 1;
328               break;
329             case AIM_CONN_TYPE_AUTH:
330               {
331                 u_long head;
332
333                 head = aimutil_get32(workingPtr->data);
334                 if (head == 0x00000001)
335                   {
336 #if debug > 0
337                     printf("got connection ack on auth line\n");
338 #endif
339                     workingPtr->handled = 1;
340                   }
341                 else
342                   {
343                     u_short family,subtype;
344
345                     family = aimutil_get16(workingPtr->data);
346                     subtype = aimutil_get16(workingPtr->data+2);
347                     
348                     switch (family)
349                       {
350                         /* New login protocol */
351 #ifdef SNACLOGIN
352                       case 0x0017:
353                         if (subtype == 0x0001)
354                           workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0017, 0x0001, workingPtr);
355                         else if (subtype == 0x0003)
356                           workingPtr->handled = aim_authparse(sess, workingPtr);
357                         else if (subtype == 0x0007)
358                           workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0017, 0x0007, workingPtr);
359                         else
360                           workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0017, 0xffff, workingPtr);
361                         break;
362 #else
363                         /* XXX: this isnt foolproof */
364                       case 0x0001:
365                         if (subtype == 0x0003)
366                           workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_GEN, AIM_CB_GEN_SERVERREADY, workingPtr);
367                         else
368                           workingPtr->handled = aim_authparse(sess, workingPtr);
369                         break;
370                       case 0x0007:
371                         if (subtype == 0x0005)
372                           workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_ADM, AIM_CB_ADM_INFOCHANGE_REPLY, workingPtr);
373                         break;
374                       default:
375                         /* Old login protocol */
376                         /* any user callbacks will be called from here */
377                         workingPtr->handled = aim_authparse(sess, workingPtr);
378 #endif
379                       }
380                   }
381               }
382               break;
383             case AIM_CONN_TYPE_BOS:
384               {
385                 u_short family;
386                 u_short subtype;
387
388                 family = aimutil_get16(workingPtr->data);
389                 subtype = aimutil_get16(workingPtr->data+2);
390
391                 switch (family)
392                   {
393                   case 0x0000: /* not really a family, but it works */
394                     if (subtype == 0x0001)
395                       workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0000, 0x0001, workingPtr);
396                     else
397                       workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, workingPtr);
398                     break;
399                   case 0x0001: /* Family: General */
400                     switch (subtype)
401                       {
402                       case 0x0001:
403                         workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
404                         break;
405                       case 0x0003:
406                         workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0003, workingPtr);
407                         break;
408                       case 0x0005:
409                         workingPtr->handled = aim_handleredirect_middle(sess, workingPtr);
410                         break;
411                       case 0x0007:
412                         workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0007, workingPtr);
413                         break;
414                       case 0x000a:
415                         workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x000a, workingPtr);
416                         break;
417                       case 0x000f:
418                         workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x000f, workingPtr);
419                         break;
420                       case 0x0013:
421                         workingPtr->handled = aim_parsemotd_middle(sess, workingPtr);
422                         break;
423                       default:
424                         workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_GEN, AIM_CB_GEN_DEFAULT, workingPtr);
425                       }
426                     break;
427                   case 0x0002: /* Family: Location */
428                     switch (subtype)
429                       {
430                       case 0x0001:
431                         workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0002, 0x0001, workingPtr);
432                         break;
433                       case 0x0003:
434                         workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0002, 0x0003, workingPtr);
435                         break;
436                       case 0x0006:
437                         workingPtr->handled = aim_parse_userinfo_middle(sess, workingPtr);
438                         break;
439                       default:
440                         workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_LOC, AIM_CB_LOC_DEFAULT, workingPtr);
441                       }
442                     break;
443                   case 0x0003: /* Family: Buddy List */
444                     switch (subtype)
445                       {
446                       case 0x0001:
447                         workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
448                         break;
449                       case 0x0003:
450                         workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0003, 0x0003, workingPtr);
451                         break;
452                       case 0x000b: /* oncoming buddy */
453                         workingPtr->handled = aim_parse_oncoming_middle(sess, workingPtr);
454                         break;
455                       case 0x000c: /* offgoing buddy */
456                         workingPtr->handled = aim_parse_offgoing_middle(sess, workingPtr);
457                         break;
458                       default:
459                         workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_BUD, AIM_CB_BUD_DEFAULT, workingPtr);
460                       }
461                     break;
462                   case 0x0004: /* Family: Messeging */
463                     switch (subtype)
464                       {
465                       case 0x0001:
466                         workingPtr->handled = aim_parse_msgerror_middle(sess, workingPtr);
467                         break;
468                       case 0x0005:
469                         workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0004, 0x0005, workingPtr);
470                         break;
471                       case 0x0007:
472                         workingPtr->handled = aim_parse_incoming_im_middle(sess, workingPtr);
473                         break;
474                       case 0x000a:
475                         workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0004, 0x000a, workingPtr);
476                         break;
477                       default:
478                         workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_MSG, AIM_CB_MSG_DEFAULT, workingPtr);
479                       }
480                     break;
481                   case 0x0009:
482                     if (subtype == 0x0001)
483                       workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
484                     else if (subtype == 0x0003)
485                       workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0009, 0x0003, workingPtr);
486                     else
487                       workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_BOS, AIM_CB_BOS_DEFAULT, workingPtr);
488                     break;
489                   case 0x000a:  /* Family: User lookup */
490                     switch (subtype)
491                       {
492                       case 0x0001:
493                         workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x000a, 0x0001, workingPtr);
494                         break;
495                       case 0x0003:
496                         workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x000a, 0x0003, workingPtr);
497                         break;
498                       default:
499                         workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_LOK, AIM_CB_LOK_DEFAULT, workingPtr);
500                       }
501                     break;
502                   case 0x000b:
503                     if (subtype == 0x0001)
504                       workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
505                     else if (subtype == 0x0002)
506                       workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x000b, 0x0002, workingPtr);
507                     else
508                       workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_STS, AIM_CB_STS_DEFAULT, workingPtr);
509                     break;
510                   default:
511                     workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, workingPtr);
512                     break;
513                   }
514               }
515               break;
516             case AIM_CONN_TYPE_CHATNAV:
517               {
518                 u_short family;
519                 u_short subtype;
520                 family = aimutil_get16(workingPtr->data);
521                 subtype= aimutil_get16(workingPtr->data+2);
522
523                 if ((family == 0x0002) && (subtype == 0x0006))
524                   {
525                     workingPtr->handled = 1;
526                     aim_conn_setstatus(workingPtr->conn, AIM_CONN_STATUS_READY);
527                   }
528                 else if ((family == 0x000d) && (subtype == 0x0009))
529                   workingPtr->handled = aim_chatnav_parse_info(sess, workingPtr);
530                 else
531                   {
532                     workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, family, subtype, workingPtr);
533                   }
534               }
535               break;
536             case AIM_CONN_TYPE_CHAT:
537               {
538                 u_short family, subtype;
539
540                 family = aimutil_get16(workingPtr->data);
541                 subtype= aimutil_get16(workingPtr->data+2);
542                 
543                 if ((family == 0x0000) && (subtype == 0x00001))
544                   workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0000, 0x0001, workingPtr);
545                 else if (family == 0x0001)
546                   {
547                     if (subtype == 0x0001)
548                       workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0001, workingPtr);
549                     else if (subtype == 0x0003)
550                       workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0003, workingPtr);
551                     else if (subtype == 0x0007)
552                       workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0007, workingPtr);
553                     else
554                       printf("Chat: unknown snac %04x/%04x\n", family, subtype);
555                   }
556                 else if (family == 0x000e)
557                   {
558                     if (subtype == 0x0002)
559                       workingPtr->handled = aim_chat_parse_infoupdate(sess, workingPtr);
560                     else if (subtype == 0x0003)
561                       workingPtr->handled = aim_chat_parse_joined(sess, workingPtr);    
562                     else if (subtype == 0x0004)
563                       workingPtr->handled = aim_chat_parse_leave(sess, workingPtr);     
564                     else if (subtype == 0x0006)
565                       workingPtr->handled = aim_chat_parse_incoming(sess, workingPtr);
566                     else        
567                       printf("Chat: unknown snac %04x/%04x\n", family, subtype); 
568                   }
569                 else
570                   {
571                     printf("Chat: unknown snac %04x/%04x\n", family, subtype);
572                     workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_DEFAULT, workingPtr);
573                   }
574               }
575               break;
576             default:
577               printf("\nAHHHHH! UNKNOWN CONNECTION TYPE! (type = %d, fd = %d, channel = %02x, commandlen = %02x)\n\n", workingPtr->conn->type, workingPtr->conn->fd, workingPtr->type, workingPtr->commandlen);
578               workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, workingPtr);
579               break;
580             }
581           /* move to next command */
582           workingPtr = workingPtr->next;
583         }
584     }
585
586   sess->queue_incoming = aim_purge_rxqueue(sess->queue_incoming);
587   
588   return 0;
589 }
590
591 int aim_parsemotd_middle(struct aim_session_t *sess,
592                               struct command_rx_struct *command, ...)
593 {
594   rxcallback_t userfunc = NULL;
595   char *msg;
596   int ret=1;
597   struct aim_tlvlist_t *tlvlist;
598   u_short id;
599
600   /*
601    * Dunno.
602    */
603   id = aimutil_get16(command->data+10);
604
605   /* 
606    * TLVs follow 
607    */
608   tlvlist = aim_readtlvchain(command->data+12, command->commandlen-12);
609   
610   msg = aim_gettlv_str(tlvlist, 0x000b, 1);
611   
612   userfunc = aim_callhandler(command->conn, 0x0001, 0x0013);
613   if (userfunc)
614     ret =  userfunc(sess, command, id, msg);
615
616   aim_freetlvchain(&tlvlist);
617
618   return ret;
619   
620 }
621
622 int aim_handleredirect_middle(struct aim_session_t *sess,
623                               struct command_rx_struct *command, ...)
624 {
625   struct aim_tlv_t *tmptlv = NULL;
626   int serviceid = 0x00;
627   char cookie[AIM_COOKIELEN];
628   char *ip = NULL;
629   rxcallback_t userfunc = NULL;
630   struct aim_tlvlist_t *tlvlist;
631   int ret = 1;
632   
633   if (!(tlvlist = aim_readtlvchain(command->data+10, command->commandlen-10)))
634     {
635       printf("libfaim: major bug: unable to read tlvchain from redirect\n");
636       return ret;
637     }
638   
639   if (!(tmptlv = aim_gettlv(tlvlist, 0x000d, 1))) 
640     {
641       printf("libfaim: major bug: no service ID in tlvchain from redirect\n");
642       aim_freetlvchain(&tlvlist);
643       return ret;
644     }
645   serviceid = aimutil_get16(tmptlv->value);
646
647   if (!(ip = aim_gettlv_str(tlvlist, 0x0005, 1))) 
648     {
649       printf("libfaim: major bug: no IP in tlvchain from redirect (service 0x%02x)\n", serviceid);
650       aim_freetlvchain(&tlvlist);
651       return ret;
652     }
653   
654   if (!(tmptlv = aim_gettlv(tlvlist, 0x0006, 1)))
655     {
656       printf("libfaim: major bug: no cookie in tlvchain from redirect (service 0x%02x)\n", serviceid);
657       aim_freetlvchain(&tlvlist);
658       return ret;
659     }
660   memcpy(cookie, tmptlv->value, AIM_COOKIELEN);
661
662   if (serviceid == AIM_CONN_TYPE_CHAT)
663     {
664       /*
665        * Chat hack.
666        *
667        */
668       userfunc = aim_callhandler(command->conn, 0x0001, 0x0005);
669       if (userfunc)
670         ret =  userfunc(sess, command, serviceid, ip, cookie, sess->pendingjoin);
671       free(sess->pendingjoin);
672       sess->pendingjoin = NULL;
673     }
674   else
675     {
676       userfunc = aim_callhandler(command->conn, 0x0001, 0x0005);
677       if (userfunc)
678         ret =  userfunc(sess, command, serviceid, ip, cookie);
679     }
680
681   /*
682    * XXX: Is there a leak here?  Where does IP get freed?
683    */
684   aim_freetlvchain(&tlvlist);
685
686   return ret;
687 }
688
689 int aim_parse_unknown(struct aim_session_t *sess,
690                       struct command_rx_struct *command, ...)
691 {
692   u_int i = 0;
693
694   printf("\nRecieved unknown packet:");
695
696   for (i = 0; i < command->commandlen; i++)
697     {
698       if ((i % 8) == 0)
699         printf("\n\t");
700
701       printf("0x%2x ", command->data[i]);
702     }
703   
704   printf("\n\n");
705
706   return 1;
707 }
708
709
710 /*
711  * aim_parse_generalerrs()
712  *
713  * Middle handler for 0x0001 snac of each family.
714  *
715  */
716 int aim_parse_generalerrs(struct aim_session_t *sess,
717                           struct command_rx_struct *command, ...)
718 {
719   u_short family;
720   u_short subtype;
721   
722   family = aimutil_get16(command->data+0);
723   subtype= aimutil_get16(command->data+2);
724   
725   switch(family)
726     {
727     default:
728       /* Unknown family */
729       return aim_callhandler_noparam(sess, command->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, command);
730     }
731
732   return 1;
733 }
734
735
736
This page took 0.175064 seconds and 5 git commands to generate.