change a whole bunch of ethereal into wireshark
[obnox/wireshark/wip.git] / epan / dissectors / packet-sqloracle.c
1 /* packet-sqloracle.c
2  * Routines for SQL ORcle packet dissection
3  *
4  * The initial Wireshark version of this file was imported from the
5  * ClearSight source code package.
6  * No author/copyright given in the original file.
7  *
8  * $Id$
9  *
10  * Wireshark - Network traffic analyzer
11  * 
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  * 
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  * 
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25  */
26 #define TCP_PORT_TNS 1522 /* XXX 1521 collides with packet-tns.c */
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <glib.h>
32 #include <ctype.h>
33 #include <string.h>
34 #include <epan/packet.h>
35 #include "packet-sqloracle.h"
36 #define SWAP_UI16(ui16) (((ui16)>>8 & 0xff) | ((ui16)<<8 & 0xff00))
37
38 /* option flag 1 */
39 #define OPTION_CANCEL 0x80
40 #define OPTION_FETCH  0x40
41 #define OPTION_EXCUTE  0x20
42 #define OPTION_DEFINE  0x10
43 #define OPTION_BIND  0x08
44 #define OPTION_DESC_BIND  0x04
45 #define OPTION_PARSE  0x02
46
47 /* option flag 2 */
48 #define OPTION_PLSQL 0x80
49 #define OPTION_PARSE2  0x40
50 #define OPTION_VECTOR  0x04
51 #define OPTION_FETCH2  0x02
52 #define OPTION_COMMIT  0x01
53
54
55
56 /* protocol */
57 static gint proto_sqloracle = -1;
58 static gint ett_sqloracle = -1;
59 static gint ett_sqloracle_operation = -1;
60
61 static int hf_sqloracle_operation = -1;
62 static int hf_sqloracle_func_type = -1;
63 /* static int hf_sqloracle_stmt_length = -1; */
64 static int hf_sqloracle_stmt = -1;
65 /* static int hf_sqloracle_v8ttluds_tname = -1;
66 static int hf_sqloracle_v8ttluds_sname = -1;
67 static int hf_sqloracle_v8ttluds_columnname = -1;
68 static int hf_sqloracle_v8ttluds_scrlength = -1;
69 static int hf_sqloracle_v8ttluds_nullallow = -1;
70 static int hf_sqloracle_v8ttluds_header= -1;
71 static int hf_sqloracle_v8ttloac_formuse = -1;
72 static int hf_sqloracle_v8ttloac_ncs = -1;
73 static int hf_sqloracle_v8ttloac_oid = -1;
74 static int hf_sqloracle_v8ttloac_header =-1;
75 static int hf_sqloracle_ttloac_flag2 = -1;
76 static int hf_sqloracle_ttloac_mal = -1;
77 static int hf_sqloracle_ttloac_varcharlen = -1;
78 static int hf_sqloracle_ttloac_dummy = -1;
79 static int hf_sqloracle_ttloac_scalesize = -1;
80 static int hf_sqloracle_ttloac_prefix = -1;
81 static int hf_sqloracle_ttloac_flag1 = -1;
82 static int hf_sqloracle_ttloac_type = -1;
83 static int hf_sqloracle_ttloac_header = -1;
84 */
85 static int hf_sqloracle_flag = -1;
86 static int hf_sqloracle_num_column = -1;
87 /* static int hf_sqloracle_v8ttloac_vsn = -1; */
88 static int hf_sqloracle_itemNum = -1;
89 static int hf_sqloracle_numItersThisTime = -1;
90 static int hf_sqloracle_uacBufLength = -1;
91
92 static dissector_handle_t data_handle;
93 static  dissector_handle_t sqloracle_handle;
94 static char m_pCurQuery[2025];
95
96 static int m_numOfUpdate =0;
97 /* static int m_tnsErrors = 0; */
98 static int m_numOfSelect = 0;
99 static int m_numOfInsert = 0;
100 static int m_numOfDelete = 0;
101 static int m_numOfRollback = 0;
102 static int m_numOfSet = 0;
103 static int m_numOfStart = 0;
104 static int m_numOfCommit = 0;
105 static int m_numOfOtherStatement = 0;
106 static int m_numOfTransaction = 0;
107 /* static int m_bReAssembling = 0; */
108 /* SQLORACLE flags */
109 /*static const true_false_string flags_set_truth =
110 {
111   " ",
112   "No "
113 }; */
114 static const value_string sqloracle_operation_type[] = {
115         {NET8_TYPE_SETPROP,   "Set protocol" },
116         {NET8_TYPE_SETDATAREP,    "Set data representations" },
117         {NET8_TYPE_USERTOSERVER,       "User request" },
118         {NET8_TYPE_ERRORSTATUS,    "Error: No data found" },
119         {NET8_TYPE_AUAS,  "Access user address space" },
120         {NET8_TYPE_ROWTRANSFER,      "Row transfer header" },
121         {NET8_TYPE_ROWDATA,      "Row transfer data follows" },
122         {NET8_TYPE_OPIPARAM,     "Return OPI parameter" },
123         {NET8_TYPE_FUNCCOMPLETE,    "Oracle function complete"},
124         {NET8_TYPE_TTINOER,    "N Error return definitions follow"},
125         {NET8_TYPE_TTIIOV, "Sending I/O Vec only for fast UPI"},
126         {NET8_TYPE_TTISLG,   "Send long for fast UPI"},
127         {NET8_TYPE_TTIICA,   "Invoke user callback"},
128         {NET8_TYPE_TTILOBD,   "LOB/FILE data follows"},
129         {NET8_TYPE_TTIWRN,   "Warning messages - may be a set of them"},
130         {NET8_TYPE_DESCINFO,   "Describe information"},
131         {NET8_TYPE_PIGGYBACKFUNC,   "Piggyback function follows"},
132         {NET8_TYPE_TTI3GL,   "signals special action for untrusted callout support"},
133         {NET8_TYPE_TTIFOB,   "Flush Out Bind data in DML/w RETURN when error"},
134         {NET8_TYPE_SECURENEG,   "Secure Network Services Negotiation"},
135         {0,     "Unknown"},
136         {0, NULL}
137 };
138 static const value_string sql_func_type[] = {
139     {NET8_USER_FUNC_OLOGON,   " Logon to Oracle"},
140     {NET8_USER_FUNC_OPENCURSOR,    "Open cursor" },              
141     {NET8_USER_FUNC_PARSE,     "Parse statement" },                
142     {NET8_USER_FUNC_EXECUTE,    "Execute statement" },               
143     {NET8_USER_FUNC_OFETCH,   " Fetch row" },              
144     {NET8_USER_FUNC_CLOSECURSOR,   "Close cursor" },              
145     {NET8_USER_FUNC_OLOGOFF,  "Logoff" },             
146     {NET8_USER_FUNC_ODSCRIBE, "Describe select list column" },            
147     {NET8_USER_FUNC_ODEFIN,   "Define where column goes" },              
148     {NET8_USER_FUNC_OCOMON,   "Autocommit On" },              
149     {NET8_USER_FUNC_OCOMOFF,  "Autocommit Off" },             
150     {NET8_USER_FUNC_OCOMMIT,  "Commit" },             
151     {NET8_USER_FUNC_OROLLBACK,    "Rollback" },               
152     {NET8_USER_FUNC_OSFE,     "Set fatal error options" },                
153     {NET8_USER_FUNC_ORESUME,  "Resume current operation" },             
154     {NET8_USER_FUNC_OVERSN,   "Get version-date string" },              
155     {NET8_USER_FUNC_OTEMP,    "(Obsolete)" },               
156     {NET8_USER_FUNC_CANCEL,  "Cancel Operation" },             
157     {NET8_USER_FUNC_OGEM,     "Get error message" },                
158     {NET8_USER_FUNC_OSPECIAL, "Special function" },            
159     {NET8_USER_FUNC_OABORT,   "Abort" },              
160     {NET8_USER_FUNC_ODQRID,   "Dequeue by rowid" },              
161     {NET8_USER_FUNC_OLNGF6,   "Fetch long value" },              
162     {NET8_USER_FUNC_OHOWMANY, "How Many Items?" },            
163     {NET8_USER_FUNC_OINIT,    "Initialize Database" },               
164     {NET8_USER_FUNC_OCHANGEU, "Change user_id" },            
165     {NET8_USER_FUNC_OBINDRP,  "Bind by reference positional" },             
166     {NET8_USER_FUNC_OGETBV,   "Get n'th Bind Variable" },              
167     {NET8_USER_FUNC_OGETIV,   "Get n'th Into Variable" },              
168     {NET8_USER_FUNC_OBINDRV,  "Bind by reference" },             
169     {NET8_USER_FUNC_OBINDRN,  "Bind by reference numeric" },             
170     {NET8_USER_FUNC_OPARSEX,  "Parse And Execute" },             
171     {NET8_USER_FUNC_OPARSYN,  "Parse for Syntax only" },             
172     {NET8_USER_FUNC_OPARSDI,  "Parse for Syntax & SQL Dictionary lookup" },
173     {NET8_USER_FUNC_OCONTINUE, "Continue serving after eof" },            
174     {NET8_USER_FUNC_ODSCRARR, "Describe Columns" },            
175     {NET8_USER_FUNC_OLCCINI,  "Init sys pars command table" },             
176     {NET8_USER_FUNC_OLCCFIN,  "Finalize sys pars command table" },             
177     {NET8_USER_FUNC_OLCCPUT,  "Put sys par in command table" },             
178     {NET8_USER_FUNC_OV6STRT,  "Start Oracle (V6)" },             
179     {NET8_USER_FUNC_OV6STOP,  "Poll for shut down Oracle (V6)" },             
180     {NET8_USER_FUNC_ORIP,     "Run independent process (V6)" },                
181     {NET8_USER_FUNC_OARCHIVE, "Archive op (V6)" },            
182     {NET8_USER_FUNC_OMRSTART, "Media recovery - start (V6)" },            
183     {NET8_USER_FUNC_OMRRECTS, "Media recovery - record tablespace to recover (V6)"},          
184     {NET8_USER_FUNC_OMRGSLSQ, "Media recovery - get starting log seq # (V6)" },
185     {NET8_USER_FUNC_OMRREC,   "Media recovery - recover using offline log (V6)" },
186     {NET8_USER_FUNC_OMRCAN,   "Media recovery - cancel media recovery (V6)" },
187     {NET8_USER_FUNC_O2LOGON,  "Logon to ORACLE" },             
188     {NET8_USER_FUNC_OVERSION, "Get Version/Date String" },
189     {NET8_USER_FUNC_OINIT2,   "New init call (supersedes OINIT)" },              
190     {NET8_USER_FUNC_OCLOALL,  "Reserved for MAC; close all cursors" },             
191     {NET8_USER_FUNC_OALL,     "Bundled execution call" },                
192     {NET8_USER_FUNC_OTEX,     "Transaction execute call (OS/2)" },                
193     {NET8_USER_FUNC_OSDAUTH,  "Set DBA authorization call (OS/2)" },             
194     {NET8_USER_FUNC_OUDLFUN,  "Direct loader: functions" },             
195     {NET8_USER_FUNC_OUDLBUF,  "Direct loader: buffer transfer" },             
196     {NET8_USER_FUNC_OK2RPC,   "Distrib. trans. mgr. RPC" },              
197     {NET8_USER_FUNC_ODSCIDX,  "Describe indexes for distributed query" },
198     {NET8_USER_FUNC_OSESOPN,  "Session operations" },             
199     {NET8_USER_FUNC_OEXECSCN, "Execute using synchronized system commit numbers" },
200     {NET8_USER_FUNC_OALL7,    "New V8 Bundle call" },               
201     {NET8_USER_FUNC_OLONGF,   "Long fetch version 7" },              
202     {NET8_USER_FUNC_OEXECA,   "Call opiexe from opiall" },             
203     {NET8_USER_FUNC_OSQL7,    "Parse call" },               
204     {NET8_USER_FUNC_OOBS,     "(Obsolete)" },
205     {NET8_USER_FUNC_ORPC,     "RPC Call from pl" },                
206     {NET8_USER_FUNC_OEXFEN,   "OEXFEN" },
207     {NET8_USER_FUNC_OXAOPN,   "XA operation" },              
208     {NET8_USER_FUNC_OKGL,     "KGL call" },
209     {NET8_USER_FUNC_03LOGON,  "LogonB"},
210     {NET8_USER_FUNC_03LOGA,   "LogonA"},
211     {NET8_USER_FUNC_OFNSTM,   "Do Streaming Operation"},
212     {NET8_USER_FUNC_OPENSESS, "Open Session"},  
213     {NET8_USER_FUNC_O71XAOPN,  "X/Open XA operations"},
214     {NET8_USER_FUNC_ODEBUG,   "Debug"},
215     {NET8_USER_FUNC_ODEBUGS,  "Special Debug"},
216     {NET8_USER_FUNC_OXAST,    "XA Start"},
217     {NET8_USER_FUNC_OXACM,    "XA Commit"},
218     {NET8_USER_FUNC_OXAPR,    "XA Prepare"},
219     {NET8_USER_FUNC_OXDP,     "XA Import"},
220     {NET8_USER_FUNC_OKOD,     "Get Object Value From Reference"},
221     {NET8_USER_FUNC_OCONNECT, "Connect"},
222         {NET8_USER_FUNC_OCBK,           "call (kernel side only)"},
223         {NET8_USER_FUNC_OALL8,     "OALL8"},
224         {NET8_USER_FUNC_OFNSTM2,   "OFNSTM without the begintxn"},
225         {NET8_USER_FUNC_OLOBOPS,   "LOB Operation"},
226         {NET8_USER_FUNC_OFILECRT,  "FILE create call"},
227         {NET8_USER_FUNC_ODNY,      "New Describe"},
228         {NET8_USER_FUNC_OCONNECT,  "code for non blocking attach host"},
229         {NET8_USER_FUNC_OOPENRCS,  "Open a recursive cursor"},
230         {NET8_USER_FUNC_OKPRALL,   "Bundled KPR execution"},
231         {NET8_USER_FUNC_OPLS,      "Bundled PL/SQL execution"},
232         {NET8_USER_FUNC_OTXSE,      "transaction start, attach, detach"},
233         {NET8_USER_FUNC_OTXEN,      "transaction commit, rollback, recover"},
234         {NET8_USER_FUNC_OCCA,      "Cursor Close All"},
235         {NET8_USER_FUNC_OFOI,      "Failover info piggyback"},
236         {NET8_USER_FUNC_O80SES,    "V8 session switching piggyback"},
237         {NET8_USER_FUNC_ODDF,      "Do Dummy Defines"},
238         {NET8_USER_FUNC_OLRMINI,   "init sys pars"},
239         {NET8_USER_FUNC_OLRMFIN,   "finalize sys pars"},
240         {NET8_USER_FUNC_OLRMPUT,   "put sys par in par space"},
241         {NET8_USER_FUNC_OLRMTRM,   "terminate sys pars"},
242         {NET8_USER_FUNC_OEXFENA,   "execute but don't unmap (used from opiall0)"},
243         {NET8_USER_FUNC_OINIUCB,   "OINIT for Untrusted CallBacks"},
244         {NET8_USER_FUNC_AUTH,     "Authentication Call"},
245         {NET8_USER_FUNC_OFGI,      "FailOver Get Instance Info"},
246         {NET8_USER_FUNC_OOTCO,      "Oracle Transaction service COmmit remote sites"},
247         {NET8_USER_FUNC_GETSESSKEY,  "Get the session key"},
248         {NET8_USER_FUNC_ODSY,      "V8 Describe Any"},
249         {NET8_USER_FUNC_OCANA,     "Cancel All"},
250         {NET8_USER_FUNC_OAQEQ,      "AQ EnQueue"},
251         {NET8_USER_FUNC_OAQDQ,      "AQ Dequeue"},
252         {NET8_USER_FUNC_ORFS,       "RFS call"},
253         {NET8_USER_FUNC_OKPN,      "Kernel Programmatic Notification"},
254     {0,       "Unknown type"},
255         {0, NULL}
256 };
257
258
259 #if 0
260 /* jtse */
261 /*+------------------------------------------------------
262  * 
263  * Convert hex data to character string
264  *--------------------------------------------------------
265 -*/
266 char * convertHexToString(BYTE *pSrc, UI16_T length)
267 {
268     char buf[150];
269         char * hexString;
270         char hex[17] = "0123456789ABCDEF";
271         int i;
272     int limit = 2*length;
273     if (limit >= sizeof(buf) - 3)
274         limit = sizeof(buf) - 3;
275
276
277     for( i=0; i<limit; i+=2)
278     {
279         buf[i] = hex[*pSrc>>4];
280         buf[i+1] = hex[*pSrc&0x0F];
281                 pSrc++;
282     }
283         buf[i] = '\0';
284
285     /*
286         for(int i=0; i<length*2; i++)
287         {
288                 buf[i]   = hex[*pSrc>>4];
289                 buf[++i] = hex[*pSrc&0x0F];
290                 pSrc++;
291         }
292         buf[length*2] = '\0';
293     */
294
295     /* hexString = buf; */
296         strcpy (hexString, buf);
297         return hexString;
298 }
299 #endif
300
301 static void ParseSqlStatement(/*char  *appMsg,*/ UI8_P pSqlData, UI16_T dataLen)
302 {
303         char  *pSqlModifyData = (I8_P)m_pCurQuery;
304         int   i = 0;
305
306         while (*pSqlData != '\1' && *pSqlData != '\0' && i < dataLen)
307         {
308                 if (*pSqlData < ' ')
309                 {
310                         *pSqlModifyData = ' ';
311                 }
312                 else
313                 {
314                         *pSqlModifyData = *pSqlData;
315                 }
316
317                 pSqlModifyData++;
318                 pSqlData++;
319                 i++;
320         }
321
322         *pSqlModifyData = '\0';
323
324 #if 0
325         appMsg = (I8_P)m_pCurQuery;
326 #endif
327
328         if (strncasecmp((I8_P)m_pCurQuery, "update", 6) == 0)
329         {
330                 m_numOfUpdate++;
331 #if 0
332                 pSummaryStat->m_numOfUpdate++;
333                 if (m_pServerNode != NULL)
334                     m_pServerNode->m_numOfUpdate++;
335 #endif
336         }
337         else if (strncasecmp((I8_P)m_pCurQuery, "select", 6) == 0)
338         {
339                 m_numOfSelect++;
340 #if 0
341                 pSummaryStat->m_numOfSelect++;
342                 if (m_pServerNode != NULL)
343                     m_pServerNode->m_numOfSelect++;
344 #endif
345         }
346         else if (strncasecmp((I8_P)m_pCurQuery, "insert", 6) == 0)
347         {
348                 m_numOfInsert++;
349 #if 0
350                 pSummaryStat->m_numOfInsert++;
351                 if (m_pServerNode != NULL)
352                         m_pServerNode->m_numOfInsert++;
353 #endif
354         }
355         else if (strncasecmp((I8_P)m_pCurQuery, "delete", 6) == 0)
356         {
357                 m_numOfDelete++;
358 #if 0
359                 pSummaryStat->m_numOfDelete++;
360                 if (m_pServerNode != NULL)
361                         m_pServerNode->m_numOfDelete++;
362 #endif
363         }
364         else if (strncasecmp((I8_P)m_pCurQuery, "rollback", 8) == 0)
365         {
366                 m_numOfRollback++;
367 #if 0
368                 pSummaryStat->m_numOfRollback++;
369                 if (m_pServerNode != NULL)
370                         m_pServerNode->m_numOfRollback++;
371 #endif
372         }
373         else if (strncasecmp((I8_P)m_pCurQuery, "set", 3) == 0)
374         {
375                 m_numOfSet++;
376 #if 0
377                 pSummaryStat->m_numOfSet++;
378                 if (m_pServerNode != NULL)
379                         m_pServerNode->m_numOfSet++;
380 #endif
381         }
382         else if (strncasecmp((I8_P)m_pCurQuery, "start", 5) == 0)
383         {
384                 m_numOfStart++;
385 #if 0
386                 pSummaryStat->m_numOfStart++;
387                 if (m_pServerNode != NULL)
388                         m_pServerNode->m_numOfStart++;
389 #endif
390         }
391         else if (strncasecmp((I8_P)m_pCurQuery, "commit", 6) == 0)
392         {
393                 m_numOfCommit++;
394 #if 0
395                 pSummaryStat->m_numOfCommit++;
396                 if (m_pServerNode != NULL)
397                         m_pServerNode->m_numOfCommit++;
398 #endif
399         }
400         else 
401         {
402                 m_numOfOtherStatement++;
403 #if 0
404                 pSummaryStat->m_numOfOtherStatement++;
405                 if (m_pServerNode != NULL)
406                         m_pServerNode->m_numOfOtherStatement++;
407 #endif
408         }
409
410         m_numOfTransaction++;
411 #if 0
412         m_pSummaryStat->m_numOfTransaction++;
413         if (m_pServerNode != NULL)
414                 m_pServerNode->m_numOfTransaction++;
415 #endif
416 }
417
418
419 static gboolean FindBeginningSQLString(UI8_P *pBuf, UI16_T *pDataLen, int lookSize)
420 {
421         /* the position could still be off by x bytes, check if it happened to be landing on an address */
422 /*      int i = 31;     /+ allow upto 8 bad bytes */
423         UI8_P pString = *pBuf;
424         gboolean bAlpha1 = isalpha(pString[0]) != 0;
425         gboolean bAlpha2 = isalpha(pString[1]) != 0;
426         gboolean bAlpha3 = isalpha(pString[2]) != 0;
427         gboolean bAlpha4 = isalpha(pString[3]) != 0;
428         gboolean bComment = FALSE;
429         UI16_T dataLen = *pDataLen;
430         while ( (dataLen > 2) && (lookSize > 0) && ((bAlpha1 == FALSE) || (bAlpha2 == FALSE) || (bAlpha3 == FALSE) || (bAlpha4 == FALSE)))
431         {
432                 /* check if we need to find the ending comment */
433                 if (bComment)
434                 {
435                         if (*((UI16_P)pString) == 0x2F2A)       /* ending comment */
436                         {
437                                 bComment = FALSE;
438                                 pString ++;     /* skip the comment */
439                                 dataLen --;
440                         }
441                         pString ++;
442                         dataLen --;
443                 }
444                 else
445                 {
446                         /* check if there is a comment string prepended to the statement */
447                         if (*((UI16_P)pString) == 0x2A2F)       /* beginning of comment */
448                         {
449                                 bComment = TRUE;
450                                 dataLen -= 2;
451                                 pString += 2;
452                                 bAlpha2 = isalpha(pString[1]) != 0;
453                                 bAlpha3 = isalpha(pString[2]) != 0;
454                                 bAlpha4 = isalpha(pString[3]) != 0;
455                                 continue;
456                         }
457                         pString++;
458                         bAlpha1 = bAlpha2;
459                         bAlpha2 = isalpha(pString[1]) != 0;
460                         bAlpha3 = isalpha(pString[2]) != 0;
461                         bAlpha4 = isalpha(pString[3]) != 0;
462                         dataLen --;
463             /* don't count the zeros */
464             if (*((UI8_P)pString) != 0x0)
465                             lookSize--;
466                 }
467         }
468         if (bAlpha1 && bAlpha2 && bAlpha3 && bAlpha4)
469         {
470                 *pBuf = pString;
471                 *pDataLen = dataLen;
472                 return TRUE;
473         }
474         else
475                 return FALSE;
476 }
477
478 static gboolean ParseCommand(proto_tree *tree,tvbuff_t *tvb, int offset, packet_info *pinfo,UI16_T dataLen)
479 {
480         UI8_T pAddress[1024];
481         UI16_T SQLDataLen = dataLen;
482         int i;
483         UI8_P pAddr;
484         for (i=0; i<1024;i++)
485         {
486                 pAddress[i] = '\0';
487         }
488         tvb_memcpy (tvb, pAddress,offset, dataLen);
489         pAddr = (UI8_P)pAddress;
490         /* see if SQL statement is there */
491         if (FindBeginningSQLString((UI8_P*)&pAddr, &SQLDataLen, 0x30) == TRUE)
492         {
493                 ParseSqlStatement( pAddr, dataLen);
494                 if (tree)
495                         proto_tree_add_text(tree, tvb, offset+dataLen-SQLDataLen, SQLDataLen,
496                             "SQL statement = %s",m_pCurQuery);
497     if (check_col(pinfo->cinfo, COL_INFO))
498         col_clear(pinfo->cinfo, COL_INFO);
499             if (check_col(pinfo->cinfo, COL_INFO))
500                    col_add_fstr(pinfo->cinfo, COL_INFO, "%s",m_pCurQuery );
501                 return TRUE;
502         }
503         return FALSE;
504 }
505
506 #if 0
507 static gboolean ParseNewCommand( proto_tree *tree,tvbuff_t *tvb, int offset, packet_info *pinfo, UI16_T dataLen)
508 {
509         UI8_T pAddress[1024];
510         /* find the first sequence of zeros */
511         int amount = dataLen - 12;
512         int i = 0, sqlamount;
513         UI8_P pAddr;
514         tvb_memcpy (tvb, pAddress,offset, dataLen);
515         pAddr = (UI8_P)&pAddress;
516         for (; i < amount; i++)
517         {
518                 if (*((UI32_P)((UI8_P)pAddr++)) == 0x0000)
519                         break;
520         }
521         /* was there a sequence of 4 zeros */
522         if (i >= amount)
523         {
524         /*      free(pAddr); */
525                 return FALSE;           /* went past, can not be a sql command */
526         }
527         /* look for the end of the zeros */
528         amount = dataLen - i - 4;       /* rest of the data */
529         pAddr += 3;
530         for (i = 0; *pAddr++ == 0 && i < amount; i++);
531         if (i >= amount)
532         {
533                 /* free (pAddr); */
534                 return FALSE;   /* no values after zeros */
535         }
536
537         amount -= i + 1;        /* rest of the data */
538
539         /* see if SQL statement is there */
540         sqlamount = amount;
541         if (FindBeginningSQLString((UI8_P*)&pAddr, (UI16_P)&sqlamount, 13) == TRUE)
542         {
543                 ParseSqlStatement( pAddr, amount);
544     if (check_col(pinfo->cinfo, COL_INFO))
545         col_clear(pinfo->cinfo, COL_INFO);
546             if (check_col(pinfo->cinfo, COL_INFO))
547                    col_add_fstr(pinfo->cinfo, COL_INFO, "%s",m_pCurQuery );
548                 proto_tree_add_text(tree, tvb, offset+amount-sqlamount, sqlamount,
549                             "SQL statement = %s",m_pCurQuery);
550                 return TRUE;
551         }
552         return FALSE;
553 }
554 #endif
555
556
557
558
559 static void
560 dissect_sqloracle(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) 
561 {
562         proto_item      *ti = NULL;
563         proto_tree      *sqloracle_tree = NULL;
564         int offset = 0,dataLen,nocol,numItersThisTime,flag,iterNum,uacBufLength;
565         guint8  header_operation,func_type=0;
566         m_pCurQuery[0] = '0';
567
568
569         pinfo->current_proto = "SQLORACLE";
570         if ( check_col( pinfo->cinfo, COL_PROTOCOL ))
571                 col_set_str( pinfo->cinfo, COL_PROTOCOL, "SQL" );
572     if (check_col(pinfo->cinfo, COL_INFO))
573         col_clear(pinfo->cinfo, COL_INFO);
574
575         header_operation = tvb_get_guint8(tvb, offset);
576         dataLen = tvb_reported_length_remaining(tvb, offset);
577         if (header_operation != NET8_TYPE_FUNCCOMPLETE)
578                 func_type = tvb_get_guint8(tvb, offset+1);
579
580         if ( check_col(pinfo->cinfo, COL_INFO))
581         {
582            col_add_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str(header_operation, sqloracle_operation_type, ""));
583         }
584
585         if ( tree ) 
586         { 
587                 ti = proto_tree_add_item(tree, proto_sqloracle, tvb, 0, -1, FALSE);
588                 sqloracle_tree = proto_item_add_subtree(ti, ett_sqloracle);
589             proto_tree_add_uint(sqloracle_tree, hf_sqloracle_operation, tvb, offset, 1,header_operation);
590                 if (func_type && header_operation !=NET8_TYPE_ROWTRANSFER)
591                         proto_tree_add_uint(sqloracle_tree, hf_sqloracle_func_type, tvb, offset+1, 1,func_type);
592         }
593
594         switch (header_operation)
595         {
596                 case NET8_TYPE_USERTOSERVER: /* 0x3 */
597                         if ( check_col(pinfo->cinfo, COL_INFO))
598                         {
599                 col_append_fstr(pinfo->cinfo, COL_INFO, ":%s ", val_to_str(func_type, sql_func_type, ""));
600                         }
601                         switch (func_type)
602                         {
603                                 case NET8_USER_FUNC_PARSE:
604                                         ParseCommand(sqloracle_tree,tvb,offset+0x0B,pinfo,dataLen-0x0B);
605                                         break;
606                                 case NET8_USER_FUNC_OALL:
607                                 case NET8_USER_FUNC_OALL8:
608                                         /* command could be embedded in this packet
609                                          * filtered_for_hh02_and_hh05.enc has commands that are not 0x2f offset
610                                          * try to detect the difference by looking at the offset 0x12 for 6 zeros
611                                          */
612                                         if (dataLen > (0x19 + 8))       /* assume minimum of 8 chars for the command */
613                                         {
614                                                 /* piggybacked functions will recursive call this routine to process the command */
615                                                 if (ParseCommand(sqloracle_tree,tvb, offset+0x12, pinfo,dataLen - 0x12) == TRUE)
616                                                         break;
617                                         }
618                                         break;
619                                 case NET8_USER_FUNC_OSQL7:                      /* 0x4A */
620                                         /* command could be embedded in this packet */
621                                         /* aig oracle.enc has smaller data */
622                                         if (dataLen > (0x2A /*0x30/0x14*/ + 8)) /* minimum of 8 chars */
623                                         {
624                                                 if (ParseCommand(sqloracle_tree,tvb, offset + 0x2A /*0x30/0x14*/, pinfo,dataLen - 0x2A /*0x30/0x14*/) == TRUE)
625                                                                 break;
626                                         }
627                                         break;
628
629                                 case NET8_USER_FUNC_OALL7:                      /* 0x47 */
630                                         /* command could be embedded in this packet */
631                                         if (dataLen > (0x2A /*0x30/0x14*/ + 8)) /* minimum of 8 chars */
632                                         {
633                                                 if (ParseCommand(sqloracle_tree,tvb, offset + 0x14, pinfo,dataLen - 0x14) == TRUE)
634                                                 {
635                                                         if (check_col(pinfo->cinfo, COL_INFO))
636                                                                 col_add_fstr(pinfo->cinfo, COL_INFO, "%s",m_pCurQuery );
637                                                         break;
638                                                 }
639                                                 else
640                                                         /* appdncr.enc has this smaller command */
641                                                 if (ParseCommand(sqloracle_tree,tvb, offset + 0x30, pinfo,dataLen - 0x30) == TRUE)
642                                                         break;
643                                         }
644                                         break;
645                         }
646                         break;
647                 case NET8_TYPE_ROWTRANSFER:             /* 0x06 */
648                         flag = func_type;
649                         proto_tree_add_uint(sqloracle_tree, hf_sqloracle_flag, tvb, offset+1, 1,flag);
650                         nocol = tvb_get_guint8(tvb, offset+2);
651                         iterNum = tvb_get_guint8(tvb, offset+3);
652                         numItersThisTime = tvb_get_ntohs(tvb, offset+5);
653                         uacBufLength = tvb_get_ntohs(tvb, offset+7);
654                         proto_tree_add_uint(sqloracle_tree, hf_sqloracle_num_column, tvb, offset+2, 1,nocol);
655                         proto_tree_add_uint(sqloracle_tree, hf_sqloracle_itemNum, tvb, offset+3, 1,iterNum);
656                         proto_tree_add_uint(sqloracle_tree, hf_sqloracle_numItersThisTime, tvb, offset+5, 2,numItersThisTime);
657                         proto_tree_add_uint(sqloracle_tree, hf_sqloracle_uacBufLength, tvb, offset+7, 2,uacBufLength);
658
659                         break;
660                 default:
661                         return;
662                         break;
663         }
664
665 } /* dissect_sqloracle */
666
667 void
668 proto_register_sqloracle(void)
669 {
670         static hf_register_info hf[] =
671         {
672                 { &hf_sqloracle_operation,
673                   { "Basic Operation", "sqloracle.operation", FT_UINT8, BASE_DEC, VALS(sqloracle_operation_type), 0x0, "", HFILL }
674                 },
675                 { &hf_sqloracle_func_type,
676                   { "Function Type", "sqloracle.type", FT_UINT8, BASE_DEC, VALS(sql_func_type), 0x0, "", HFILL }
677                 },
678                 { &hf_sqloracle_flag,
679                   { "flag", "sqloracle.flag", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
680                 },
681                 { &hf_sqloracle_num_column,
682                         { "Number of Columns", "sqloracle.nocolumn", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
683                 },
684                 { &hf_sqloracle_itemNum,
685                   { "Iteration Number", "sqloracle.itemNum", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
686                 },
687                 { &hf_sqloracle_numItersThisTime,
688                   { "# of iterations this time", "sqloracle.numItersThisTime", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
689                 },
690                 { &hf_sqloracle_uacBufLength,
691                   { "user access buffer length", "sqloracle.uacBufLength", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
692                 },
693 /*              { &hf_sqloracle_ttloac_header,
694                         { "TTLOAC Header", "sqloracle.ttloac_header", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
695                 },
696
697                 { &hf_sqloracle_ttloac_type,
698                         { "type", "sqloracle.ttloac_type", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
699                 },
700                 { &hf_sqloracle_ttloac_flag1,
701                   { "flag1", "sqloracle.ttloac_flag1", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
702                 },
703                 { &hf_sqloracle_ttloac_prefix,
704                 { "prefix",             "sqloracle.ttloac_prefix", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
705                 },
706                 { &hf_sqloracle_ttloac_scalesize,
707                 { "scale size",         "sqloracle.ttloac_scalesize", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
708                 },
709                 { &hf_sqloracle_ttloac_dummy,
710                 { "dummy",              "sqloracle.ottloac_dummy", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
711                 },
712                 { &hf_sqloracle_ttloac_varcharlen,
713                 { "varcharlen",         "sqloracle.ttloac_varcharlen", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
714                 },
715                 { &hf_sqloracle_ttloac_mal,
716                 { "mal",                "sqloracle.ttloac_mal", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
717                 },
718                 { &hf_sqloracle_ttloac_flag2,
719                 { "flag2",              "sqloracle.ttloac_flag2", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
720                 },
721                 { &hf_sqloracle_v8ttloac_header,
722                         { "V8TTLOAC Header", "sqloracle.v8ttloac_header", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
723                 },
724
725                 { &hf_sqloracle_v8ttloac_oid,
726                         { "oid", "sqloracle.v8ttloac_oid", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
727                 },
728                 { &hf_sqloracle_v8ttloac_vsn,
729                   { "vsn", "sqloracle.v8ttloac_vsn", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
730                 },
731                 { &hf_sqloracle_v8ttloac_ncs,
732                 { "ncs",                "sqloracle.v8ttloac_ncs", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
733                 },
734                 { &hf_sqloracle_v8ttloac_formuse,
735                 { "FormUse",            "sqloracle.v8ttloac_formuse", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
736                 },
737                 { &hf_sqloracle_v8ttluds_header,
738                         { "V8TTLUDS Header", "sqloracle.v8ttluds_header", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
739                 },
740
741                 { &hf_sqloracle_v8ttluds_nullallow,
742                         { "null allowed", "sqloracle.v8ttluds_nullallow", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
743                 },
744                 { &hf_sqloracle_v8ttluds_scrlength,
745                   { "screen length", "sqloracle.v8ttluds_scrlength", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
746                 },
747                 { &hf_sqloracle_v8ttluds_columnname,
748                   { "column name", "sqloracle.v8ttluds_columnname", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
749                 },
750                 { &hf_sqloracle_v8ttluds_sname,
751                   { "sName", "sqloracle.v8ttluds_snname", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
752                 },
753                 { &hf_sqloracle_v8ttluds_tname,
754                   { "tName", "sqloracle.v8ttluds_tname", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
755                 },
756                 { &hf_sqloracle_stmt_length,
757                 { "SQL Statement Length",       "sqloracle.stmtlength", FT_UINT8, BASE_DEC, NULL, 0x0,
758                         "", HFILL }},
759 */              { &hf_sqloracle_stmt,
760                         { "SQL statement", "sqloracle.stmt", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }
761                 },
762                 };
763
764         static gint *ett[] =
765         {
766                 &ett_sqloracle,
767                 &ett_sqloracle_operation,
768         };
769
770         proto_sqloracle = proto_register_protocol("SQL -Net8 Data", "SQL", "sqloracle");
771         proto_register_field_array(proto_sqloracle, hf, array_length(hf));
772         proto_register_subtree_array(ett, array_length(ett));
773
774         
775         register_dissector("sqloracle", dissect_sqloracle, proto_sqloracle);
776 }
777
778 void
779 proto_reg_handoff_sqloracle(void)
780 {
781
782         sqloracle_handle = create_dissector_handle(dissect_sqloracle, proto_sqloracle);
783         dissector_add("tns.port", TCP_PORT_TNS, sqloracle_handle);
784         data_handle = find_dissector("data");
785 }
786