1 /* $Id$ */
2 /*
3 ** Copyright (C) 2002-2009 Sourcefire, Inc.
4 ** Copyright (C) 1998-2002 Martin Roesch <roesch@sourcefire.com>
5 **
6 ** This program is free software; you can redistribute it and/or modify
7 ** it under the terms of the GNU General Public License Version 2 as
8 ** published by the Free Software Foundation.  You may not use, modify or
9 ** distribute this program under any other version of the GNU General
10 ** Public License.
11 **
12 ** This program is distributed in the hope that it will be useful,
13 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 ** GNU General Public License for more details.
16 **
17 ** You should have received a copy of the GNU General Public License
18 ** along with this program; if not, write to the Free Software
19 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21 
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25 
26 #include <sys/types.h>
27 #include <stdlib.h>
28 #include <string.h>
29 
30 #ifdef HAVE_STRINGS_H
31 #include <strings.h>
32 #endif
33 
34 #ifndef WIN32
35 #include <sys/socket.h>
36 #include <netinet/in.h>
37 #include <arpa/inet.h>
38 #endif /* !WIN32 */
39 #include <errno.h>
40 #include <signal.h>
41 
42 #include "log.h"
43 #include "util.h"
44 #include "debug.h"
45 
46 #include "barnyard2.h"
47 #include "log_text.h"
48 
49 #ifdef SUP_IP6
50 #include "sfutil/sf_ip.h"
51 #endif
52 
53 //extern OptTreeNode *otn_tmp;    /* global ptr to current rule data */
54 
55 /*--------------------------------------------------------------------
56  * utility functions
57  *--------------------------------------------------------------------
58  */
LogTimeStamp(TextLog * log,Packet * p)59 void LogTimeStamp(TextLog* log, Packet* p)
60 {
61     char timestamp[TIMEBUF_SIZE];
62     ts_print((struct timeval*)&p->pkth->ts, timestamp);
63     TextLog_Puts(log, timestamp);
64 }
65 
66 /*--------------------------------------------------------------------
67  * alert stuff cloned from log.c
68  *--------------------------------------------------------------------
69  */
70 /*--------------------------------------------------------------------
71  * Function: LogPriorityData()
72  *
73  * Purpose: Prints out priority data associated with an alert
74  *
75  * Arguments: log => pointer to TextLog to write the data to
76  *            doNewLine => tack a \n to the end of the line or not (bool)
77  *
78  * Returns: void function
79  *--------------------------------------------------------------------
80  */
LogPriorityData(TextLog * log,uint32_t classification_id,uint32_t priority_id,bool doNewLine)81 void LogPriorityData(TextLog* log, uint32_t classification_id, uint32_t priority_id, bool doNewLine)
82 {
83 	ClassType			*cn = ClassTypeLookupById(barnyard2_conf, classification_id);
84 
85     if ( cn != NULL )
86     {
87         TextLog_Print(
88             log, "[Classification: %s] [Priority: %d] ",
89             cn->name, cn->priority
90         );
91     }
92     else
93     {
94         TextLog_Print(
95             log, "[Classification ID: %d] [Priority ID: %d] ",
96             classification_id, priority_id
97         );
98     }
99     if ( doNewLine )
100         TextLog_NewLine(log);
101 }
102 
103 /*--------------------------------------------------------------------
104  * Layer 2 header stuff cloned from log.c
105  *--------------------------------------------------------------------
106  */
107 #ifndef NO_NON_ETHER_DECODER
108 /*--------------------------------------------------------------------
109  * Function: LogTrHeader(TextLog*, Packet*)
110  *
111  * Purpose: Print the packet TokenRing header to the given TextLog
112  *
113  * Arguments: log => pointer to TextLog to print to
114  *
115  * Returns: void function
116  *--------------------------------------------------------------------
117  */
118 
LogTrHeader(TextLog * log,Packet * p)119 void LogTrHeader(TextLog* log, Packet* p)
120 {
121 
122     TextLog_Print(log, "%X:%X:%X:%X:%X:%X -> ", p->trh->saddr[0],
123             p->trh->saddr[1], p->trh->saddr[2], p->trh->saddr[3],
124             p->trh->saddr[4], p->trh->saddr[5]);
125     TextLog_Print(log, "%X:%X:%X:%X:%X:%X\n", p->trh->daddr[0],
126             p->trh->daddr[1], p->trh->daddr[2], p->trh->daddr[3],
127             p->trh->daddr[4], p->trh->daddr[5]);
128 
129     TextLog_Print(log, "access control:0x%X frame control:0x%X\n", p->trh->ac,
130             p->trh->fc);
131     if(!p->trhllc)
132         return;
133     TextLog_Print(log, "DSAP: 0x%X SSAP 0x%X protoID: %X%X%X Ethertype: %X\n",
134             p->trhllc->dsap, p->trhllc->ssap, p->trhllc->protid[0],
135             p->trhllc->protid[1], p->trhllc->protid[2], p->trhllc->ethertype);
136     if(p->trhmr)
137     {
138         TextLog_Print(log, "RIF structure is present:\n");
139         TextLog_Print(log, "bcast: 0x%X length: 0x%X direction: 0x%X largest"
140                 "fr. size: 0x%X res: 0x%X\n",
141                 TRH_MR_BCAST(p->trhmr), TRH_MR_LEN(p->trhmr),
142         TRH_MR_DIR(p->trhmr), TRH_MR_LF(p->trhmr),
143                 TRH_MR_RES(p->trhmr));
144         TextLog_Print(log, "rseg -> %X:%X:%X:%X:%X:%X:%X:%X\n",
145                 p->trhmr->rseg[0], p->trhmr->rseg[1], p->trhmr->rseg[2],
146                 p->trhmr->rseg[3], p->trhmr->rseg[4], p->trhmr->rseg[5],
147                 p->trhmr->rseg[6], p->trhmr->rseg[7]);
148     }
149 }
150 #endif  // NO_NON_ETHER_DECODER
151 
152 /*--------------------------------------------------------------------
153  * Function: LogEthHeader()
154  *
155  * Purpose: Print the packet Ethernet header to the given TextLog
156  *
157  * Arguments: log => pointer to TextLog to print to
158  *
159  * Returns: void function
160  *--------------------------------------------------------------------
161  */
LogEthHeader(TextLog * log,Packet * p)162 static void LogEthHeader(TextLog* log, Packet* p)
163 {
164     /* src addr */
165     TextLog_Print(log, "%X:%X:%X:%X:%X:%X -> ", p->eh->ether_src[0],
166             p->eh->ether_src[1], p->eh->ether_src[2], p->eh->ether_src[3],
167             p->eh->ether_src[4], p->eh->ether_src[5]);
168 
169     /* dest addr */
170     TextLog_Print(log, "%X:%X:%X:%X:%X:%X ", p->eh->ether_dst[0],
171             p->eh->ether_dst[1], p->eh->ether_dst[2], p->eh->ether_dst[3],
172             p->eh->ether_dst[4], p->eh->ether_dst[5]);
173 
174     /* protocol and pkt size */
175     TextLog_Print(log, "type:0x%X len:0x%X\n", ntohs(p->eh->ether_type), p->pkth->len);
176 }
177 
178 #ifdef MPLS
LogMPLSHeader(TextLog * log,Packet * p)179 static void LogMPLSHeader(TextLog* log, Packet* p)
180 {
181 
182     TextLog_Print(log,"label:0x%05X exp:0x%X bos:0x%X ttl:0x%X\n",
183             p->mplsHdr.label, p->mplsHdr.exp, p->mplsHdr.bos, p->mplsHdr.ttl);
184 }
185 #endif
186 #ifndef NO_NON_ETHER_DECODER
187 /*--------------------------------------------------------------------
188  * Function: LogSLLHeader(TextLog* )
189  *
190  * Purpose: Print the packet SLL (fake) header to the given TextLog
191  * (piece partly is borrowed from tcpdump :))
192  *
193  * Arguments: log => pointer to TextLog to print to
194  *
195  * Returns: void function
196  *--------------------------------------------------------------------
197  */
198 #ifdef DLT_LINUX_SLL
LogSLLHeader(TextLog * log,Packet * p)199 static void LogSLLHeader(TextLog* log, Packet* p)
200 {
201     switch (ntohs(p->sllh->sll_pkttype)) {
202         case LINUX_SLL_HOST:
203             TextLog_Puts(log, "< ");
204             break;
205         case LINUX_SLL_BROADCAST:
206             TextLog_Puts(log, "B ");
207             break;
208         case LINUX_SLL_MULTICAST:
209             TextLog_Puts(log, "M ");
210             break;
211         case LINUX_SLL_OTHERHOST:
212             TextLog_Puts(log, "P ");
213             break;
214         case LINUX_SLL_OUTGOING:
215             TextLog_Puts(log, "> ");
216             break;
217         default:
218             TextLog_Puts(log, "? ");
219             break;
220         }
221 
222     /* mac addr */
223     TextLog_Print(log, "l/l len: %i l/l type: 0x%X %X:%X:%X:%X:%X:%X\n",
224             htons(p->sllh->sll_halen), ntohs(p->sllh->sll_hatype),
225             p->sllh->sll_addr[0], p->sllh->sll_addr[1], p->sllh->sll_addr[2],
226             p->sllh->sll_addr[3], p->sllh->sll_addr[4], p->sllh->sll_addr[5]);
227 
228     /* protocol and pkt size */
229     TextLog_Print(log, "pkt type:0x%X proto: 0x%X len:0x%X\n",
230                  ntohs(p->sllh->sll_pkttype),
231                  ntohs(p->sllh->sll_protocol), p->pkth->len);
232 }
233 #endif
234 
235 /*--------------------------------------------------------------------
236  * Function: LogWifiHeader(TextLog* )
237  *
238  * Purpose: Print the packet 802.11 header to the given TextLog
239  *
240  * Arguments: log => pointer to TextLog to print to
241  *
242  * Returns: void function
243  *--------------------------------------------------------------------
244  */
LogWifiHeader(TextLog * log,Packet * p)245 static void LogWifiHeader(TextLog* log, Packet * p)
246 {
247   /* This assumes we are printing a data packet, could be changed
248      to print other types as well */
249   const u_char *da = NULL, *sa = NULL, *bssid = NULL, *ra = NULL,
250     *ta = NULL;
251   /* per table 4, IEEE802.11 section 7.2.2 */
252   if ((p->wifih->frame_control & WLAN_FLAG_TODS) &&
253       (p->wifih->frame_control & WLAN_FLAG_FROMDS)) {
254     ra = p->wifih->addr1;
255     ta = p->wifih->addr2;
256     da = p->wifih->addr3;
257     sa = p->wifih->addr4;
258   }
259   else if (p->wifih->frame_control & WLAN_FLAG_TODS) {
260     bssid = p->wifih->addr1;
261     sa = p->wifih->addr2;
262     da = p->wifih->addr3;
263   }
264   else if (p->wifih->frame_control & WLAN_FLAG_FROMDS) {
265     da = p->wifih->addr1;
266     bssid = p->wifih->addr2;
267     sa = p->wifih->addr3;
268   }
269   else {
270     da = p->wifih->addr1;
271     sa = p->wifih->addr2;
272     bssid = p->wifih->addr3;
273   }
274 
275   /* DO this switch to provide additional info on the type */
276   switch(p->wifih->frame_control & 0x00ff)
277   {
278   case WLAN_TYPE_MGMT_BEACON:
279     TextLog_Puts(log, "Beacon ");
280     break;
281     /* management frames */
282   case WLAN_TYPE_MGMT_ASREQ:
283     TextLog_Puts(log, "Assoc. Req. ");
284     break;
285   case WLAN_TYPE_MGMT_ASRES:
286     TextLog_Puts(log, "Assoc. Resp. ");
287     break;
288   case WLAN_TYPE_MGMT_REREQ:
289     TextLog_Puts(log, "Reassoc. Req. ");
290     break;
291   case WLAN_TYPE_MGMT_RERES:
292     TextLog_Puts(log, "Reassoc. Resp. ");
293     break;
294   case WLAN_TYPE_MGMT_PRREQ:
295     TextLog_Puts(log, "Probe Req. ");
296     break;
297   case WLAN_TYPE_MGMT_PRRES:
298     TextLog_Puts(log, "Probe Resp. ");
299     break;
300   case WLAN_TYPE_MGMT_ATIM:
301     TextLog_Puts(log, "ATIM ");
302     break;
303   case WLAN_TYPE_MGMT_DIS:
304     TextLog_Puts(log, "Dissassoc. ");
305     break;
306   case WLAN_TYPE_MGMT_AUTH:
307     TextLog_Puts(log, "Authent. ");
308     break;
309   case WLAN_TYPE_MGMT_DEAUTH:
310     TextLog_Puts(log, "Deauthent. ");
311     break;
312 
313     /* Control frames */
314   case WLAN_TYPE_CONT_PS:
315   case WLAN_TYPE_CONT_RTS:
316   case WLAN_TYPE_CONT_CTS:
317   case WLAN_TYPE_CONT_ACK:
318   case WLAN_TYPE_CONT_CFE:
319   case WLAN_TYPE_CONT_CFACK:
320     TextLog_Puts(log, "Control ");
321     break;
322   }
323 
324   if (sa != NULL) {
325     TextLog_Print(log, "%X:%X:%X:%X:%X:%X -> ", sa[0],
326         sa[1], sa[2], sa[3], sa[4], sa[5]);
327   }
328   else if (ta != NULL) {
329     TextLog_Print(log, "ta: %X:%X:%X:%X:%X:%X da: ", ta[0],
330         ta[1], ta[2], ta[3], ta[4], ta[5]);
331   }
332 
333   TextLog_Print(log, "%X:%X:%X:%X:%X:%X\n", da[0],
334       da[1], da[2], da[3], da[4], da[5]);
335 
336   if (bssid != NULL)
337   {
338       TextLog_Print(log, "bssid: %X:%X:%X:%X:%X:%X", bssid[0],
339               bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]);
340   }
341 
342   if (ra != NULL) {
343     TextLog_Print(log, " ra: %X:%X:%X:%X:%X:%X", ra[0],
344         ra[1], ra[2], ra[3], ra[4], ra[5]);
345   }
346   TextLog_Puts(log, " Flags:");
347   if (p->wifih->frame_control & WLAN_FLAG_TODS)    TextLog_Puts(log," ToDs");
348   if (p->wifih->frame_control & WLAN_FLAG_TODS)    TextLog_Puts(log," FrDs");
349   if (p->wifih->frame_control & WLAN_FLAG_FRAG)    TextLog_Puts(log," Frag");
350   if (p->wifih->frame_control & WLAN_FLAG_RETRY)   TextLog_Puts(log," Re");
351   if (p->wifih->frame_control & WLAN_FLAG_PWRMGMT) TextLog_Puts(log," Pwr");
352   if (p->wifih->frame_control & WLAN_FLAG_MOREDAT) TextLog_Puts(log," MD");
353   if (p->wifih->frame_control & WLAN_FLAG_WEP)     TextLog_Puts(log," Wep");
354   if (p->wifih->frame_control & WLAN_FLAG_ORDER)   TextLog_Puts(log," Ord");
355   TextLog_NewLine(log);
356 }
357 #endif  // NO_NON_ETHER_DECODER
358 
359 /*--------------------------------------------------------------------
360  * Function: Log2ndHeader(TextLog* , Packet p)
361  *
362  * Purpose: Log2ndHeader -- prints second layber  header info.
363  *
364  * Arguments: log => pointer to TextLog to print to
365  *
366  * Returns: void function
367  *--------------------------------------------------------------------
368  */
Log2ndHeader(TextLog * log,Packet * p)369 void Log2ndHeader(TextLog* log, Packet* p)
370 {
371 
372     switch(datalink)
373     {
374         case DLT_EN10MB:        /* Ethernet */
375             if(p && p->eh)
376                 LogEthHeader(log, p);
377             break;
378 #ifndef NO_NON_ETHER_DECODER
379 #ifdef DLT_IEEE802_11
380         case DLT_IEEE802_11:
381             if(p && p->wifih)
382                 LogWifiHeader(log, p);
383             break;
384 #endif
385         case DLT_IEEE802:                /* Token Ring */
386             if(p && p->trh)
387                 LogTrHeader(log, p);
388             break;
389 #ifdef DLT_LINUX_SLL
390         case DLT_LINUX_SLL:
391             if (p && p->sllh)
392                 LogSLLHeader(log, p);  /* Linux cooked sockets */
393             break;
394 #endif
395 #endif  // NO_NON_ETHER_DECODER
396         default:
397             if (BcLogVerbose())
398             {
399                 ErrorMessage("Datalink %i type 2nd layer display is not "
400                              "supported\n", datalink);
401             }
402     }
403 }
404 
405 /*-------------------------------------------------------------------
406  * IP stuff cloned from log.c
407  *-------------------------------------------------------------------
408  */
LogIpOptions(TextLog * log,Packet * p)409 static void LogIpOptions(TextLog*  log, Packet * p)
410 {
411     int i;
412     int j;
413     u_long init_offset;
414     u_long print_offset;
415 
416     init_offset = TextLog_Tell(log);
417 
418     if(!p->ip_option_count || p->ip_option_count > 40)
419         return;
420 
421     TextLog_Print(log, "IP Options (%d) => ", p->ip_option_count);
422 
423     for(i = 0; i < (int) p->ip_option_count; i++)
424     {
425         print_offset = TextLog_Tell(log);
426 
427         if((print_offset - init_offset) > 60)
428         {
429             TextLog_Puts(log, "\nIP Options => ");
430             init_offset = TextLog_Tell(log);
431         }
432 
433         switch(p->ip_options[i].code)
434         {
435             case IPOPT_RR:
436                 TextLog_Puts(log, "RR ");
437                 break;
438 
439             case IPOPT_EOL:
440                 TextLog_Puts(log, "EOL ");
441                 break;
442 
443             case IPOPT_NOP:
444                 TextLog_Puts(log, "NOP ");
445                 break;
446 
447             case IPOPT_TS:
448                 TextLog_Puts(log, "TS ");
449                 break;
450 
451             case IPOPT_ESEC:
452                 TextLog_Puts(log, "ESEC ");
453                 break;
454 
455             case IPOPT_SECURITY:
456                 TextLog_Puts(log, "SEC ");
457                 break;
458 
459             case IPOPT_LSRR:
460             case IPOPT_LSRR_E:
461                 TextLog_Puts(log, "LSRR ");
462                 break;
463 
464             case IPOPT_SATID:
465                 TextLog_Puts(log, "SID ");
466                 break;
467 
468             case IPOPT_SSRR:
469                 TextLog_Puts(log, "SSRR ");
470                 break;
471 
472             case IPOPT_RTRALT:
473                 TextLog_Puts(log, "RTRALT ");
474                 break;
475 
476             default:
477                 TextLog_Print(log, "Opt %d: ", p->ip_options[i].code);
478 
479                 if(p->ip_options[i].len)
480                 {
481                     for(j = 0; j < p->ip_options[i].len; j++)
482                     {
483                         if (p->ip_options[i].data)
484                             TextLog_Print(log, "%02X", p->ip_options[i].data[j]);
485                         else
486                             TextLog_Print(log, "%02X", 0);
487 
488                         if((j % 2) == 0)
489                             TextLog_Putc(log, ' ');
490                     }
491                 }
492                 break;
493         }
494     }
495     TextLog_NewLine(log);
496 }
497 
498 /*--------------------------------------------------------------------
499  * Function: LogIPHeader(TextLog* )
500  *
501  * Purpose: Dump the IP header info to the given TextLog
502  *
503  * Arguments: log => TextLog to print to
504  *
505  * Returns: void function
506  *--------------------------------------------------------------------
507  */
LogIPHeader(TextLog * log,Packet * p)508 void LogIPHeader(TextLog*  log, Packet * p)
509 {
510     if(!IPH_IS_VALID(p))
511     {
512         TextLog_Print(log, "IP header truncated\n");
513         return;
514     }
515 
516     if(p->frag_flag)
517     {
518         /* just print the straight IP header */
519         TextLog_Puts(log, inet_ntoa(GET_SRC_ADDR(p)));
520         TextLog_Puts(log, " -> ");
521         TextLog_Puts(log, inet_ntoa(GET_DST_ADDR(p)));
522     }
523     else
524     {
525         if(GET_IPH_PROTO(p) != IPPROTO_TCP && GET_IPH_PROTO(p) != IPPROTO_UDP)
526         {
527             /* just print the straight IP header */
528             TextLog_Puts(log, inet_ntoa(GET_SRC_ADDR(p)));
529             TextLog_Puts(log, " -> ");
530             TextLog_Puts(log, inet_ntoa(GET_DST_ADDR(p)));
531         }
532         else
533         {
534             if (!BcObfuscate())
535             {
536                 /* print the header complete with port information */
537                 TextLog_Puts(log, inet_ntoa(GET_SRC_ADDR(p)));
538                 TextLog_Print(log, ":%d -> ", p->sp);
539                 TextLog_Puts(log, inet_ntoa(GET_DST_ADDR(p)));
540                 TextLog_Print(log, ":%d", p->dp);
541             }
542             else
543             {
544                 /* print the header complete with port information */
545                 if(IS_IP4(p))
546                     TextLog_Print(log, "xxx.xxx.xxx.xxx:%d -> xxx.xxx.xxx.xxx:%d", p->sp, p->dp);
547                 else if(IS_IP6(p))
548                     TextLog_Print(log, "x:x:x:x:x:x:x:x:%d -> x:x:x:x:x:x:x:x:%d", p->sp, p->dp);
549             }
550         }
551     }
552 
553     if(!BcOutputDataLink())
554     {
555         TextLog_NewLine(log);
556     }
557     else
558     {
559         TextLog_Putc(log, ' ');
560     }
561 
562     TextLog_Print(log, "%s TTL:%u TOS:0x%X ID:%u IpLen:%u DgmLen:%u",
563             protocol_names[GET_IPH_PROTO(p)],
564             GET_IPH_TTL(p),
565             GET_IPH_TOS(p),
566             IS_IP6(p) ? ntohl(GET_IPH_ID(p)) : ntohs((uint16_t)GET_IPH_ID(p)),
567             GET_IPH_HLEN(p) << 2,
568             GET_IP_DGMLEN(p));
569 
570     /* print the reserved bit if it's set */
571     if((uint8_t)((ntohs(GET_IPH_OFF(p)) & 0x8000) >> 15) == 1)
572         TextLog_Puts(log, " RB");
573 
574     /* printf more frags/don't frag bits */
575     if((uint8_t)((ntohs(GET_IPH_OFF(p)) & 0x4000) >> 14) == 1)
576         TextLog_Puts(log, " DF");
577 
578     if((uint8_t)((ntohs(GET_IPH_OFF(p)) & 0x2000) >> 13) == 1)
579         TextLog_Puts(log, " MF");
580 
581     TextLog_NewLine(log);
582 
583     /* print IP options */
584     if(p->ip_option_count != 0)
585     {
586         LogIpOptions(log, p);
587     }
588 
589     /* print fragment info if necessary */
590     if(p->frag_flag)
591     {
592         TextLog_Print(log, "Frag Offset: 0x%04X   Frag Size: 0x%04X\n",
593                 (p->frag_offset & 0x1FFF),
594                 GET_IP_PAYLEN(p));
595     }
596 }
597 
598 /*-------------------------------------------------------------------
599  * TCP stuff cloned from log.c
600  *-------------------------------------------------------------------
601  */
LogTcpOptions(TextLog * log,Packet * p)602 static void LogTcpOptions(TextLog*  log, Packet * p)
603 {
604     int i;
605     int j;
606     u_char tmp[5];
607     u_long init_offset;
608     u_long print_offset;
609 
610     init_offset = TextLog_Tell(log);
611 
612     TextLog_Print(log, "TCP Options (%d) => ", p->tcp_option_count);
613 
614     if(p->tcp_option_count > 40 || !p->tcp_option_count)
615         return;
616 
617     for(i = 0; i < (int) p->tcp_option_count; i++)
618     {
619         print_offset = TextLog_Tell(log);
620         /**
621         if((print_offset - init_offset) > 60)
622         {
623             TextLog_Puts(log, "\nTCP Options => ");
624             init_offset = TextLog_Tell(log);
625         }
626         **/
627         switch(p->tcp_options[i].code)
628         {
629             case TCPOPT_MAXSEG:
630                 memset((char*)tmp, 0, sizeof(tmp));
631                 TextLog_Puts(log, "MSS: ");
632                 if (p->tcp_options[i].data)
633                     memcpy(tmp, p->tcp_options[i].data, 2);
634                 TextLog_Print(log, "%u ", EXTRACT_16BITS(tmp));
635                 break;
636 
637             case TCPOPT_EOL:
638                 TextLog_Puts(log, "EOL ");
639                 break;
640 
641             case TCPOPT_NOP:
642                 TextLog_Puts(log, "NOP ");
643                 break;
644 
645             case TCPOPT_WSCALE:
646                 if (p->tcp_options[i].data)
647                     TextLog_Print(log, "WS: %u ", p->tcp_options[i].data[0]);
648                 else
649                     TextLog_Print(log, "WS: %u ", 0);
650                 break;
651             case TCPOPT_SACK:
652                 memset((char*)tmp, 0, sizeof(tmp));
653                 if (p->tcp_options[i].data && (p->tcp_options[i].len >= 2))
654                     memcpy(tmp, p->tcp_options[i].data, 2);
655                 TextLog_Print(log, "Sack: %u@", EXTRACT_16BITS(tmp));
656                 memset((char*)tmp, 0, sizeof(tmp));
657                 if (p->tcp_options[i].data && (p->tcp_options[i].len >= 4))
658                     memcpy(tmp, (p->tcp_options[i].data) + 2, 2);
659                 TextLog_Print(log, "%u ", EXTRACT_16BITS(tmp));
660                 break;
661 
662             case TCPOPT_SACKOK:
663                 TextLog_Puts(log, "SackOK ");
664                 break;
665 
666             case TCPOPT_ECHO:
667                 memset((char*)tmp, 0, sizeof(tmp));
668                 if (p->tcp_options[i].data)
669                     memcpy(tmp, p->tcp_options[i].data, 4);
670                 TextLog_Print(log, "Echo: %u ", EXTRACT_32BITS(tmp));
671                 break;
672 
673             case TCPOPT_ECHOREPLY:
674                 memset((char*)tmp, 0, sizeof(tmp));
675                 if (p->tcp_options[i].data)
676                     memcpy(tmp, p->tcp_options[i].data, 4);
677                 TextLog_Print(log, "Echo Rep: %u ", EXTRACT_32BITS(tmp));
678                 break;
679 
680             case TCPOPT_TIMESTAMP:
681                 memset((char*)tmp, 0, sizeof(tmp));
682                 if (p->tcp_options[i].data)
683                     memcpy(tmp, p->tcp_options[i].data, 4);
684                 TextLog_Print(log, "TS: %u ", EXTRACT_32BITS(tmp));
685                 memset((char*)tmp, 0, sizeof(tmp));
686                 if (p->tcp_options[i].data)
687                     memcpy(tmp, (p->tcp_options[i].data) + 4, 4);
688                 TextLog_Print(log, "%u ", EXTRACT_32BITS(tmp));
689                 break;
690 
691             case TCPOPT_CC:
692                 memset((char*)tmp, 0, sizeof(tmp));
693                 if (p->tcp_options[i].data)
694                     memcpy(tmp, p->tcp_options[i].data, 4);
695                 TextLog_Print(log, "CC %u ", EXTRACT_32BITS(tmp));
696                 break;
697 
698             case TCPOPT_CCNEW:
699                 memset((char*)tmp, 0, sizeof(tmp));
700                 if (p->tcp_options[i].data)
701                     memcpy(tmp, p->tcp_options[i].data, 4);
702                 TextLog_Print(log, "CCNEW: %u ", EXTRACT_32BITS(tmp));
703                 break;
704 
705             case TCPOPT_CCECHO:
706                 memset((char*)tmp, 0, sizeof(tmp));
707                 if (p->tcp_options[i].data)
708                     memcpy(tmp, p->tcp_options[i].data, 4);
709                 TextLog_Print(log, "CCECHO: %u ", EXTRACT_32BITS(tmp));
710                 break;
711 
712             default:
713                 if(p->tcp_options[i].len)
714                 {
715                     TextLog_Print(log, "Opt %d (%d): ", p->tcp_options[i].code,
716                             (int) p->tcp_options[i].len);
717 
718                     for(j = 0; j < p->tcp_options[i].len; j++)
719                     {
720                         if (p->tcp_options[i].data)
721                             TextLog_Print(log, "%02X", p->tcp_options[i].data[j]);
722                         else
723                             TextLog_Print(log, "%02X", 0);
724 
725                         if ((j + 1) % 2 == 0)
726                             TextLog_Putc(log, ' ');
727                     }
728 
729                     TextLog_Putc(log, ' ');
730                 }
731                 else
732                 {
733                     TextLog_Print(log, "Opt %d ", p->tcp_options[i].code);
734                 }
735                 break;
736         }
737     }
738 
739     TextLog_NewLine(log);
740 }
741 
742 /*--------------------------------------------------------------------
743  * Function: LogTCPHeader(TextLog* )
744  *
745  * Purpose: Dump the TCP header info to the given TextLog
746  *
747  * Arguments: log => pointer to TextLog to print data to
748  *
749  * Returns: void function
750  *--------------------------------------------------------------------
751  */
LogTCPHeader(TextLog * log,Packet * p)752 void LogTCPHeader(TextLog*  log, Packet * p)
753 {
754     char tcpFlags[9];
755 
756     if(p->tcph == NULL)
757     {
758         TextLog_Print(log, "TCP header truncated\n");
759         return;
760     }
761     /* print TCP flags */
762     CreateTCPFlagString(p, tcpFlags);
763     TextLog_Puts(log, tcpFlags); /* We don't care about the NULL */
764 
765     /* print other TCP info */
766     TextLog_Print(log, " Seq: 0x%lX  Ack: 0x%lX  Win: 0x%X  TcpLen: %d",
767             (u_long) ntohl(p->tcph->th_seq),
768             (u_long) ntohl(p->tcph->th_ack),
769             ntohs(p->tcph->th_win), TCP_OFFSET(p->tcph) << 2);
770 
771     if((p->tcph->th_flags & TH_URG) != 0)
772     {
773         TextLog_Print(log, "  UrgPtr: 0x%X\n", (uint16_t) ntohs(p->tcph->th_urp));
774     }
775     else
776     {
777         TextLog_NewLine(log);
778     }
779 
780     /* dump the TCP options */
781     if(p->tcp_option_count != 0)
782     {
783         LogTcpOptions(log, p);
784     }
785 }
786 
787 /*-------------------------------------------------------------------
788  * UDP stuff cloned from log.c
789  *-------------------------------------------------------------------
790  */
791 /*--------------------------------------------------------------------
792  * Function: LogUDPHeader(TextLog* )
793  *
794  * Purpose: Dump the UDP header to the given TextLog
795  *
796  * Arguments: log => pointer to TextLog
797  *
798  * Returns: void function
799  *--------------------------------------------------------------------
800  */
LogUDPHeader(TextLog * log,Packet * p)801 void LogUDPHeader(TextLog* log, Packet* p)
802 {
803 
804     if(p->udph == NULL)
805     {
806         TextLog_Print(log, "UDP header truncated\n");
807         return;
808     }
809     /* not much to do here... */
810     TextLog_Print(log, "Len: %d\n", ntohs(p->udph->uh_len) - UDP_HEADER_LEN);
811 }
812 
813 /*--------------------------------------------------------------------
814  * ICMP stuff cloned from log.c
815  *--------------------------------------------------------------------
816  */
817 /*--------------------------------------------------------------------
818  * Function: LogEmbeddedICMPHeader(TextLog* , ICMPHdr *)
819  *
820  * Purpose: Prints the 64 bits of the original IP payload in an ICMP packet
821  *          that requires it
822  *
823  * Arguments: log => pointer to TextLog
824  *            icmph  => ICMPHdr struct pointing to original ICMP
825  *
826  * Returns: void function
827  *--------------------------------------------------------------------
828  */
LogEmbeddedICMPHeader(TextLog * log,const ICMPHdr * icmph)829 static void LogEmbeddedICMPHeader(TextLog* log, const ICMPHdr *icmph)
830 {
831     if (log == NULL || icmph == NULL)
832         return;
833 
834     TextLog_Print(log, "Type: %d  Code: %d  Csum: %u",
835             icmph->type, icmph->code, ntohs(icmph->csum));
836 
837     switch (icmph->type)
838     {
839         case ICMP_DEST_UNREACH:
840         case ICMP_TIME_EXCEEDED:
841         case ICMP_SOURCE_QUENCH:
842             break;
843 
844         case ICMP_PARAMETERPROB:
845             if (icmph->code == 0)
846                 TextLog_Print(log, "  Ptr: %u", icmph->s_icmp_pptr);
847             break;
848 
849         case ICMP_REDIRECT:
850 #ifdef SUP_IP6
851 // XXX-IPv6 "NOT YET IMPLEMENTED - ICMP printing"
852 #else
853             TextLog_Print(log, "  New Gwy: %s", inet_ntoa(icmph->s_icmp_gwaddr));
854 #endif
855             break;
856 
857         case ICMP_ECHO:
858         case ICMP_ECHOREPLY:
859         case ICMP_TIMESTAMP:
860         case ICMP_TIMESTAMPREPLY:
861         case ICMP_INFO_REQUEST:
862         case ICMP_INFO_REPLY:
863         case ICMP_ADDRESS:
864         case ICMP_ADDRESSREPLY:
865             TextLog_Print(log, "  Id: %u  SeqNo: %u",
866                     ntohs(icmph->s_icmp_id), ntohs(icmph->s_icmp_seq));
867             break;
868 
869         case ICMP_ROUTER_ADVERTISE:
870             TextLog_Print(log, "  Addrs: %u  Size: %u  Lifetime: %u",
871                     icmph->s_icmp_num_addrs, icmph->s_icmp_wpa,
872                     ntohs(icmph->s_icmp_lifetime));
873             break;
874 
875         default:
876             break;
877     }
878 
879     TextLog_NewLine(log);
880 
881     return;
882 }
883 
884 /*--------------------------------------------------------------------
885  * Function: LogICMPEmbeddedIP(TextLog* , Packet *)
886  *
887  * Purpose: Prints the original/encapsulated IP header + 64 bits of the
888  *          original IP payload in an ICMP packet
889  *
890  * Arguments: log => pointer to TextLog
891  *            p  => packet struct
892  *
893  * Returns: void function
894  *--------------------------------------------------------------------
895  */
LogICMPEmbeddedIP(TextLog * log,Packet * p)896 static void LogICMPEmbeddedIP(TextLog* log, Packet *p)
897 {
898     Packet op;
899     Packet *orig_p;
900     uint32_t orig_ip_hlen;
901 
902     if (log == NULL || p == NULL)
903         return;
904 
905     memset((char*)&op, 0, sizeof(op));
906     orig_p = &op;
907 
908     orig_p->iph = p->orig_iph;
909     orig_p->tcph = p->orig_tcph;
910     orig_p->udph = p->orig_udph;
911     orig_p->sp = p->orig_sp;
912     orig_p->dp = p->orig_dp;
913     orig_p->icmph = p->orig_icmph;
914 #ifdef SUP_IP6
915     orig_p->iph_api = p->orig_iph_api;
916     orig_p->ip4h = p->orig_ip4h;
917     orig_p->ip6h = p->orig_ip6h;
918     orig_p->family = p->orig_family;
919 #endif
920 
921     if(orig_p->iph != NULL)
922     {
923         TextLog_Print(log, "\n** ORIGINAL DATAGRAM DUMP:\n");
924         LogIPHeader(log, orig_p);
925         orig_ip_hlen = IP_HLEN(p->orig_iph) << 2;
926 
927         switch(GET_IPH_PROTO(orig_p))
928         {
929             case IPPROTO_TCP:
930                 if(orig_p->tcph != NULL)
931                     TextLog_Print(log, "Seq: 0x%lX\n",
932                             (u_long)ntohl(orig_p->tcph->th_seq));
933                 break;
934 
935             case IPPROTO_UDP:
936                 if(orig_p->udph != NULL)
937                     TextLog_Print(log, "Len: %d  Csum: %d\n",
938                             ntohs(orig_p->udph->uh_len) - UDP_HEADER_LEN,
939                             ntohs(orig_p->udph->uh_chk));
940                 break;
941 
942             case IPPROTO_ICMP:
943                 if(orig_p->icmph != NULL)
944                     LogEmbeddedICMPHeader(log, orig_p->icmph);
945                 break;
946 
947             default:
948                 TextLog_Print(log, "Protocol: 0x%X (unknown or "
949                         "header truncated)", GET_IPH_PROTO(orig_p));
950                 break;
951         }       /* switch */
952 
953         /* if more than 8 bytes of original IP payload sent */
954         if (p->dsize - orig_ip_hlen > 8)
955         {
956             TextLog_Print(log, "(%d more bytes of original packet)\n",
957                     p->dsize - orig_ip_hlen - 8);
958         }
959 
960         TextLog_Puts(log, "** END OF DUMP");
961     }
962     else
963     {
964         TextLog_Puts(log, "\nORIGINAL DATAGRAM TRUNCATED");
965     }
966 }
967 
968 /*--------------------------------------------------------------------
969  * Function: LogICMPHeader(TextLog* )
970  *
971  * Purpose: Print ICMP header
972  *
973  * Arguments: log => pointer to TextLog
974  *
975  * Returns: void function
976  *--------------------------------------------------------------------
977  */
LogICMPHeader(TextLog * log,Packet * p)978 void LogICMPHeader(TextLog*  log, Packet * p)
979 {
980 #ifdef SUP_IP6
981     /* 32 digits plus 7 colons and a NULL byte */
982     char buf[8*4 + 7 + 1];
983 #endif
984 
985     if(p->icmph == NULL)
986     {
987         TextLog_Puts(log, "ICMP header truncated\n");
988         return;
989     }
990 
991     TextLog_Print(log, "Type:%d  Code:%d  ", p->icmph->type, p->icmph->code);
992 
993     switch(p->icmph->type)
994     {
995         case ICMP_ECHOREPLY:
996             TextLog_Print(log, "ID:%d  Seq:%d  ", ntohs(p->icmph->s_icmp_id),
997                     ntohs(p->icmph->s_icmp_seq));
998             TextLog_Puts(log, "ECHO REPLY");
999             break;
1000 
1001         case ICMP_DEST_UNREACH:
1002             TextLog_Puts(log, "DESTINATION UNREACHABLE: ");
1003             switch(p->icmph->code)
1004             {
1005                 case ICMP_NET_UNREACH:
1006                     TextLog_Puts(log, "NET UNREACHABLE");
1007                     break;
1008 
1009                 case ICMP_HOST_UNREACH:
1010                     TextLog_Puts(log, "HOST UNREACHABLE");
1011                     break;
1012 
1013                 case ICMP_PROT_UNREACH:
1014                     TextLog_Puts(log, "PROTOCOL UNREACHABLE");
1015                     break;
1016 
1017                 case ICMP_PORT_UNREACH:
1018                     TextLog_Puts(log, "PORT UNREACHABLE");
1019                     break;
1020 
1021                 case ICMP_FRAG_NEEDED:
1022                     TextLog_Print(log, "FRAGMENTATION NEEDED, DF SET\n"
1023                             "NEXT LINK MTU: %u",
1024                             ntohs(p->icmph->s_icmp_nextmtu));
1025                     break;
1026 
1027                 case ICMP_SR_FAILED:
1028                     TextLog_Puts(log, "SOURCE ROUTE FAILED");
1029                     break;
1030 
1031                 case ICMP_NET_UNKNOWN:
1032                     TextLog_Puts(log, "NET UNKNOWN");
1033                     break;
1034 
1035                 case ICMP_HOST_UNKNOWN:
1036                     TextLog_Puts(log, "HOST UNKNOWN");
1037                     break;
1038 
1039                 case ICMP_HOST_ISOLATED:
1040                     TextLog_Puts(log, "HOST ISOLATED");
1041                     break;
1042 
1043                 case ICMP_PKT_FILTERED_NET:
1044                     TextLog_Puts(log, "ADMINISTRATIVELY PROHIBITED NETWORK FILTERED");
1045                     break;
1046 
1047                 case ICMP_PKT_FILTERED_HOST:
1048                     TextLog_Puts(log, "ADMINISTRATIVELY PROHIBITED HOST FILTERED");
1049                     break;
1050 
1051                 case ICMP_NET_UNR_TOS:
1052                     TextLog_Puts(log, "NET UNREACHABLE FOR TOS");
1053                     break;
1054 
1055                 case ICMP_HOST_UNR_TOS:
1056                     TextLog_Puts(log, "HOST UNREACHABLE FOR TOS");
1057                     break;
1058 
1059                 case ICMP_PKT_FILTERED:
1060                     TextLog_Puts(log, "ADMINISTRATIVELY PROHIBITED,\nPACKET FILTERED");
1061                     break;
1062 
1063                 case ICMP_PREC_VIOLATION:
1064                     TextLog_Puts(log, "PREC VIOLATION");
1065                     break;
1066 
1067                 case ICMP_PREC_CUTOFF:
1068                     TextLog_Puts(log, "PREC CUTOFF");
1069                     break;
1070 
1071                 default:
1072                     TextLog_Puts(log, "UNKNOWN");
1073                     break;
1074 
1075             }
1076 
1077 
1078             LogICMPEmbeddedIP(log, p);
1079 
1080             break;
1081 
1082         case ICMP_SOURCE_QUENCH:
1083             TextLog_Puts(log, "SOURCE QUENCH");
1084 
1085             LogICMPEmbeddedIP(log, p);
1086 
1087             break;
1088 
1089         case ICMP_REDIRECT:
1090             TextLog_Puts(log, "REDIRECT");
1091             switch(p->icmph->code)
1092             {
1093                 case ICMP_REDIR_NET:
1094                     TextLog_Puts(log, " NET");
1095                     break;
1096 
1097                 case ICMP_REDIR_HOST:
1098                     TextLog_Puts(log, " HOST");
1099                     break;
1100 
1101                 case ICMP_REDIR_TOS_NET:
1102                     TextLog_Puts(log, " TOS NET");
1103                     break;
1104 
1105                 case ICMP_REDIR_TOS_HOST:
1106                     TextLog_Puts(log, " TOS HOST");
1107                     break;
1108             }
1109 
1110 #ifdef SUP_IP6
1111 /* written this way since inet_ntoa was typedef'ed to use sfip_ntoa
1112  * which requires sfip_t instead of inaddr's.  This call to inet_ntoa
1113  * is a rare case that doesn't use sfip_t's. */
1114 
1115 // XXX-IPv6 NOT YET IMPLEMENTED - IPV6 addresses technically not supported - need to change ICMP
1116 
1117             /* no inet_ntop in Windows */
1118             sfip_raw_ntop(AF_INET, (const void *)(&p->icmph->s_icmp_gwaddr.s_addr),
1119                           buf, sizeof(buf));
1120             TextLog_Print(log, " NEW GW: %s", buf);
1121 #else
1122             TextLog_Print(log, " NEW GW: %s", inet_ntoa(p->icmph->s_icmp_gwaddr));
1123 #endif
1124 
1125             LogICMPEmbeddedIP(log, p);
1126 
1127             break;
1128 
1129         case ICMP_ECHO:
1130             TextLog_Print(log, "ID:%d   Seq:%d  ", ntohs(p->icmph->s_icmp_id),
1131                     ntohs(p->icmph->s_icmp_seq));
1132             TextLog_Puts(log, "ECHO");
1133             break;
1134 
1135         case ICMP_ROUTER_ADVERTISE:
1136             TextLog_Print(log, "ROUTER ADVERTISMENT: "
1137                     "Num addrs: %d Addr entry size: %d Lifetime: %u",
1138                     p->icmph->s_icmp_num_addrs, p->icmph->s_icmp_wpa,
1139                     ntohs(p->icmph->s_icmp_lifetime));
1140             break;
1141 
1142         case ICMP_ROUTER_SOLICIT:
1143             TextLog_Puts(log, "ROUTER SOLICITATION");
1144             break;
1145 
1146         case ICMP_TIME_EXCEEDED:
1147             TextLog_Puts(log, "TTL EXCEEDED");
1148             switch(p->icmph->code)
1149             {
1150                 case ICMP_TIMEOUT_TRANSIT:
1151                     TextLog_Puts(log, " IN TRANSIT");
1152                     break;
1153 
1154                 case ICMP_TIMEOUT_REASSY:
1155                     TextLog_Puts(log, " TIME EXCEEDED IN FRAG REASSEMBLY");
1156                     break;
1157             }
1158 
1159             LogICMPEmbeddedIP(log, p);
1160 
1161             break;
1162 
1163         case ICMP_PARAMETERPROB:
1164             TextLog_Puts(log, "PARAMETER PROBLEM");
1165             switch(p->icmph->code)
1166             {
1167                 case ICMP_PARAM_BADIPHDR:
1168                     TextLog_Print(log, ": BAD IP HEADER BYTE %u",
1169                             p->icmph->s_icmp_pptr);
1170                     break;
1171 
1172                 case ICMP_PARAM_OPTMISSING:
1173                     TextLog_Puts(log, ": OPTION MISSING");
1174                     break;
1175 
1176                 case ICMP_PARAM_BAD_LENGTH:
1177                     TextLog_Puts(log, ": BAD LENGTH");
1178                     break;
1179             }
1180 
1181             LogICMPEmbeddedIP(log, p);
1182 
1183             break;
1184 
1185         case ICMP_TIMESTAMP:
1186             TextLog_Print(log, "ID: %u  Seq: %u  TIMESTAMP REQUEST",
1187                     ntohs(p->icmph->s_icmp_id), ntohs(p->icmph->s_icmp_seq));
1188             break;
1189 
1190         case ICMP_TIMESTAMPREPLY:
1191             TextLog_Print(log, "ID: %u  Seq: %u  TIMESTAMP REPLY:\n"
1192                     "Orig: %u Rtime: %u  Ttime: %u",
1193                     ntohs(p->icmph->s_icmp_id), ntohs(p->icmph->s_icmp_seq),
1194                     p->icmph->s_icmp_otime, p->icmph->s_icmp_rtime,
1195                     p->icmph->s_icmp_ttime);
1196             break;
1197 
1198         case ICMP_INFO_REQUEST:
1199             TextLog_Print(log, "ID: %u  Seq: %u  INFO REQUEST",
1200                     ntohs(p->icmph->s_icmp_id), ntohs(p->icmph->s_icmp_seq));
1201             break;
1202 
1203         case ICMP_INFO_REPLY:
1204             TextLog_Print(log, "ID: %u  Seq: %u  INFO REPLY",
1205                     ntohs(p->icmph->s_icmp_id), ntohs(p->icmph->s_icmp_seq));
1206             break;
1207 
1208         case ICMP_ADDRESS:
1209             TextLog_Print(log, "ID: %u  Seq: %u  ADDRESS REQUEST",
1210                     ntohs(p->icmph->s_icmp_id), ntohs(p->icmph->s_icmp_seq));
1211             break;
1212 
1213         case ICMP_ADDRESSREPLY:
1214             TextLog_Print(log, "ID: %u  Seq: %u  ADDRESS REPLY: 0x%08X",
1215                     ntohs(p->icmph->s_icmp_id), ntohs(p->icmph->s_icmp_seq),
1216                     (u_int) ntohl(p->icmph->s_icmp_mask));
1217             break;
1218 
1219         default:
1220             TextLog_Puts(log, "UNKNOWN");
1221 
1222             break;
1223     }
1224 
1225     TextLog_NewLine(log);
1226 
1227 }
1228 
1229 /*--------------------------------------------------------------------
1230  * reference stuff cloned from signature.c
1231  *--------------------------------------------------------------------
1232  */
1233 /* print a reference node */
LogReference(TextLog * log,ReferenceNode * refNode)1234 static void LogReference(TextLog* log, ReferenceNode *refNode)
1235 {
1236     if(refNode)
1237     {
1238         if(refNode->system)
1239         {
1240             if(refNode->system->url)
1241                 TextLog_Print(log, "[Xref => %s%s]", refNode->system->url,
1242                         refNode->id);
1243             else
1244                 TextLog_Print(log, "[Xref => %s %s]", refNode->system->name,
1245                         refNode->id);
1246         }
1247         else
1248         {
1249             TextLog_Print(log, "[Xref => %s]", refNode->id);
1250         }
1251     }
1252     return;
1253 }
1254 
1255 /*
1256  * Function: LogXrefs(TextLog* )
1257  *
1258  * Purpose: Prints out cross reference data associated with an alert
1259  *
1260  * Arguments: log => pointer to TextLog to write the data to
1261  *            doNewLine => tack a \n to the end of the line or not (bool)
1262  *
1263  * Returns: void function
1264  */
LogXrefs(TextLog * log,SigNode * sn,int doNewLine)1265 void LogXrefs(TextLog* log, SigNode *sn, int doNewLine)
1266 {
1267     ReferenceNode *refNode = NULL;
1268 
1269     if(sn != NULL)
1270     {
1271         refNode = sn->refs;
1272 
1273         while(refNode  != NULL)
1274         {
1275             LogReference(log, refNode);
1276             refNode = refNode->next;
1277 
1278             /* on the last loop through, print a newline in
1279                Full mode */
1280             if(doNewLine && (refNode == NULL))
1281                 TextLog_NewLine(log);
1282         }
1283     }
1284 }
1285 
1286 /*--------------------------------------------------------------------
1287  * payload stuff cloned from log.c
1288  *--------------------------------------------------------------------
1289  */
1290 /*--------------------------------------------------------------------
1291  * Function: LogCharData(TextLog*, char*, int)
1292  *
1293  * Purpose: Dump the printable ASCII data from a packet
1294  *
1295  * Arguments: log => ptr to TextLog to print to
1296  *            data => pointer to buffer data
1297  *            len => length of data buffer
1298  *
1299  * Returns: void function
1300  *--------------------------------------------------------------------
1301  */
LogCharData(TextLog * log,char * data,int len)1302 static void LogCharData(TextLog* log, char *data, int len)
1303 {
1304     const char* pb = data;
1305     const char* end = data + len;
1306     int lineCount = 0;
1307 
1308     if ( !data )
1309     {
1310         return;
1311     }
1312 
1313     while ( pb < end )
1314     {
1315         if ( *pb > 0x1F && *pb < 0x7F)
1316         {   /* printable */
1317             TextLog_Putc(log, *pb);
1318         }
1319         else
1320         {   /* not printable */
1321             TextLog_Putc(log, '.');
1322         }
1323 
1324         if ( ++lineCount == 64 )
1325         {
1326             TextLog_Putc(log, ' ');
1327             TextLog_NewLine(log);
1328             lineCount = 0;
1329         }
1330         pb++;
1331     }
1332     /* slam a \n on the back */
1333     TextLog_Putc(log, ' ');
1334     TextLog_NewLine(log);
1335     TextLog_Putc(log, ' ');
1336 }
1337 
1338 /*
1339  * Function: LogNetData(TextLog*, u_char *,int)
1340  *
1341  * Purpose: Do a side by side dump of a buffer, hex on
1342  *          the left, decoded ASCII on the right.
1343  *
1344  * Arguments: log => ptr to TextLog to print to
1345  *            data => pointer to buffer data
1346  *            len => length of data buffer
1347  *
1348  * Returns: void function
1349  */
1350 #define BYTES_PER_FRAME 16
1351 /* middle of packet:"41 02 43 04 45 06 47 08 49 0A 4B 0C 4D 0E 4F 0F  A.C.E.G.I.K.M.O."*/
1352 /* at end of packet:"41 02 43 04 45 06 47 08                          A.C.E.G."*/
1353 static char* pad3 = "                                                 ";
1354 
LogNetData(TextLog * log,const u_char * data,const int len)1355 static void LogNetData (TextLog* log, const u_char* data, const int len)
1356 {
1357     const u_char* pb = data;
1358     const u_char* end = data + len;
1359 
1360     int offset = 0;
1361     char conv[] = "0123456789ABCDEF";   /* xlation lookup table */
1362 
1363     if ( !len )
1364     {
1365         TextLog_NewLine(log);
1366         return;
1367     }
1368     if ( !data )
1369     {
1370         TextLog_Print(log, "Got NULL ptr in LogNetData()\n");
1371         return;
1372     }
1373 
1374     if ( len > IP_MAXPACKET )
1375     {
1376         if (BcLogVerbose())
1377         {
1378             TextLog_Print(
1379                 log, "Got bogus buffer length (%d) for LogNetData, "
1380                 "defaulting to %d bytes!\n", len, BYTES_PER_FRAME
1381             );
1382         }
1383         end = data + BYTES_PER_FRAME;
1384     }
1385 
1386     /* loop thru the whole buffer */
1387     while ( pb < end )
1388     {
1389         int i = 0;
1390 
1391         if (BcVerboseByteDump())
1392         {
1393             TextLog_Print(log, "0x%04X: ", offset);
1394             offset += BYTES_PER_FRAME;
1395         }
1396         /* process one frame */
1397         /* first print the binary as ascii hex */
1398         for (i = 0; i < BYTES_PER_FRAME && pb+i < end; i++)
1399         {
1400             char b = pb[i];
1401             TextLog_Putc(log, conv[(b & 0xFF) >> 4]);
1402             TextLog_Putc(log, conv[(b & 0xFF) & 0x0F]);
1403             TextLog_Putc(log, ' ');
1404         }
1405         /* print ' ' past end of packet and before ascii */
1406         TextLog_Puts(log, pad3+(3*i));
1407 
1408         /* then print the actual ascii chars */
1409         /* or a '.' for control chars */
1410         for (i = 0; i < BYTES_PER_FRAME && pb+i < end; i++)
1411         {
1412             char b = pb[i];
1413 
1414             if ( b > 0x1F && b < 0x7F)
1415                 TextLog_Putc(log, (char)(b & 0xFF));
1416             else
1417                 TextLog_Putc(log, '.');
1418         }
1419         pb += BYTES_PER_FRAME;
1420         TextLog_NewLine(log);
1421     }
1422     TextLog_NewLine(log);
1423 }
1424 
1425 /*--------------------------------------------------------------------
1426  * Function: LogIPPkt(TextLog*, int, Packet *)
1427  *
1428  * Purpose: Dump the packet to the given TextLog
1429  *
1430  * Arguments: log => pointer to print data to
1431  *            type => packet protocol
1432  *            p => pointer to decoded packet struct
1433  *
1434  * Returns: void function
1435  *--------------------------------------------------------------------
1436  */
1437 
1438 #ifdef SUP_IP6
1439 #define DATA_PTR(p) \
1440     ((u_char*)p->iph + (GET_IPH_HLEN(p) << 2))
1441 #define DATA_LEN(p) \
1442     (p->actual_ip_len - (GET_IPH_HLEN(p) << 2))
1443 #else
1444 #define DATA_PTR(p) \
1445     ((u_char *)p->iph + (IP_HLEN(p->iph) << 2))
1446 #define DATA_LEN(p) \
1447     (p->actual_ip_len - (IP_HLEN(p->iph) << 2))
1448 #endif
1449 
1450 #define SEPARATOR \
1451     "=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+"
1452 
LogIPPkt(TextLog * log,int type,Packet * p)1453 void LogIPPkt(TextLog* log, int type, Packet * p)
1454 {
1455     DEBUG_WRAP(DebugMessage(DEBUG_LOG, "LogIPPkt type = %d\n", type););
1456 
1457     /* dump the timestamp */
1458     LogTimeStamp(log, p);
1459 
1460     /* dump the ethernet header if we're doing that sort of thing */
1461     if (BcOutputDataLink())
1462     {
1463         Log2ndHeader(log, p);
1464     }
1465 
1466 #ifdef MPLS
1467     if(p->mpls)
1468     {
1469         LogMPLSHeader(log, p);
1470     }
1471 #endif
1472     /* etc */
1473     LogIPHeader(log, p);
1474 
1475     /* if this isn't a fragment, print the other header info */
1476     if ( !p->frag_flag )
1477     {
1478         switch (GET_IPH_PROTO(p))
1479         {
1480             case IPPROTO_TCP:
1481                 if ( p->tcph != NULL )
1482 
1483                 {
1484                     LogTCPHeader(log, p);
1485                 }
1486                 else
1487                 {
1488                     LogNetData(log, DATA_PTR(p), DATA_LEN(p));
1489                 }
1490                 break;
1491 
1492             case IPPROTO_UDP:
1493                 if ( p->udph != NULL )
1494                 {
1495                     LogUDPHeader(log, p);
1496                 }
1497                 else
1498                 {
1499                     LogNetData(log, DATA_PTR(p), DATA_LEN(p));
1500                 }
1501 
1502                 break;
1503 
1504             case IPPROTO_ICMP:
1505                 if ( p->icmph != NULL )
1506                 {
1507                     LogICMPHeader(log, p);
1508                 }
1509                 else
1510                 {
1511                     LogNetData(log, DATA_PTR(p), GET_IP_PAYLEN(p));
1512                 }
1513                 break;
1514 
1515             default:
1516                 break;
1517         }
1518     }
1519 
1520     /* dump the application layer data */
1521     if (BcOutputAppData() && !BcVerboseByteDump())
1522     {
1523         if (BcOutputCharData())
1524             LogCharData(log, (char*) p->data, p->dsize);
1525         else
1526             LogNetData(log, p->data, p->dsize);
1527     }
1528     else if (BcVerboseByteDump())
1529     {
1530         LogNetData(log, p->pkt, p->pkth->caplen);
1531     }
1532 
1533     TextLog_Print(log, "%s\n\n", SEPARATOR);
1534 }
1535 
1536 #ifndef NO_NON_ETHER_DECODER
1537 /*--------------------------------------------------------------------
1538  * ARP stuff cloned from log.c
1539  *--------------------------------------------------------------------
1540  */
1541 
1542 #ifndef SUP_IP6
1543 static unsigned char ezero[6];  /* crap for ARP */
1544 #endif
1545 
LogArpHeader(TextLog * log,Packet * p)1546 void LogArpHeader(TextLog* log, Packet * p)
1547 {
1548 #ifdef SUP_IP6
1549 // XXX-IPv6 "NOT YET IMPLEMENTED - printing ARP header"
1550 #else
1551     struct in_addr ip_addr;
1552     const uint8_t *mac_src = NULL;
1553     const uint8_t *mac_dst = NULL;
1554 
1555     memset((struct in_addr *) &ip_addr, 0, sizeof(struct in_addr));
1556 
1557     /* determine what to use as MAC src and dst */
1558     if (p->eh != NULL)
1559     {
1560         mac_src = p->eh->ether_src;
1561         mac_dst = p->eh->ether_dst;
1562     } /* per table 4, 802.11 section 7.2.2 */
1563     else if (p->wifih != NULL &&
1564              (p->wifih->frame_control & WLAN_FLAG_FROMDS))
1565     {
1566         mac_src = p->wifih->addr3;
1567         mac_dst = p->wifih->addr2;
1568     }
1569     else if (p->wifih != NULL &&
1570              (p->wifih->frame_control & WLAN_FLAG_TODS))
1571     {
1572         mac_src = p->wifih->addr2;
1573         mac_dst = p->wifih->addr3;
1574     }
1575     else if (p->wifih != NULL)
1576     {
1577         mac_src = p->wifih->addr2;
1578         mac_dst = p->wifih->addr1;
1579     }
1580 
1581     /*
1582      * if these are null this function will break, exit until
1583      * someone writes a function for it...
1584      */
1585     if(mac_src == NULL || mac_dst == NULL)
1586     {
1587         return;
1588     }
1589 
1590     /* dump the timestamp */
1591     LogTimeStamp(log, p);
1592 
1593     if(ntohs(p->ah->ea_hdr.ar_pro) != ETHERNET_TYPE_IP)
1594     {
1595         TextLog_Print(log, "ARP #%d for protocol #%.4X (%d) hardware #%d (%d)\n",
1596                 ntohs(p->ah->ea_hdr.ar_op), ntohs(p->ah->ea_hdr.ar_pro),
1597                 p->ah->ea_hdr.ar_pln, ntohs(p->ah->ea_hdr.ar_hrd),
1598                 p->ah->ea_hdr.ar_hln);
1599 
1600         return;
1601     }
1602 
1603     switch(ntohs(p->ah->ea_hdr.ar_op))
1604     {
1605         case ARPOP_REQUEST:
1606 	    /* bcopy() deprecated, replaced with memmove() */
1607 	    memmove((void *) &ip_addr, (void *)p->ah->arp_tpa, sizeof(ip_addr));
1608             TextLog_Print(log, "ARP who-has %s", inet_ntoa(ip_addr));
1609 
1610             if(memcmp((char *) ezero, (char *) p->ah->arp_tha, 6) != 0)
1611             {
1612                 TextLog_Print(log, " (%X:%X:%X:%X:%X:%X)", p->ah->arp_tha[0],
1613                         p->ah->arp_tha[1], p->ah->arp_tha[2], p->ah->arp_tha[3],
1614                         p->ah->arp_tha[4], p->ah->arp_tha[5]);
1615             }
1616 	    /* bcopy() deprecated, replaced with memmove() */
1617 	    memmove((void *) &ip_addr, (void *)p->ah->arp_spa, sizeof(ip_addr));
1618             TextLog_Print(log, " tell %s", inet_ntoa(ip_addr));
1619 
1620             if(memcmp((char *) mac_src, (char *) p->ah->arp_sha, 6) != 0)
1621             {
1622                 TextLog_Print(log, " (%X:%X:%X:%X:%X:%X)", p->ah->arp_sha[0],
1623                         p->ah->arp_sha[1], p->ah->arp_sha[2], p->ah->arp_sha[3],
1624                         p->ah->arp_sha[4], p->ah->arp_sha[5]);
1625             }
1626             break;
1627 
1628         case ARPOP_REPLY:
1629 	    /* bcopy() deprecated, replaced with memmove() */
1630 	    memmove((void *) &ip_addr, (void *)p->ah->arp_spa, sizeof(ip_addr));
1631             TextLog_Print(log, "ARP reply %s", inet_ntoa(ip_addr));
1632 
1633             /* print out the originating request if we're on a weirder
1634              * wireless protocol */
1635             if(memcmp((char *) mac_src, (char *) p->ah->arp_sha, 6) != 0)
1636             {
1637                 TextLog_Print(log, " (%X:%X:%X:%X:%X:%X)", mac_src[0],
1638                         mac_src[1], mac_src[2], mac_src[3],
1639                         mac_src[4], mac_src[5]);
1640             }
1641             TextLog_Print(log, " is-at %X:%X:%X:%X:%X:%X", p->ah->arp_sha[0],
1642                     p->ah->arp_sha[1], p->ah->arp_sha[2], p->ah->arp_sha[3],
1643                     p->ah->arp_sha[4], p->ah->arp_sha[5]);
1644 
1645             if(memcmp((char *) mac_dst, (char *) p->ah->arp_tha, 6) != 0)
1646             {
1647                 TextLog_Print(log, " (%X:%X:%X:%X:%X:%X)", p->ah->arp_tha[0],
1648                         p->ah->arp_tha[1], p->ah->arp_tha[2], p->ah->arp_tha[3],
1649                         p->ah->arp_tha[4], p->ah->arp_tha[5]);
1650             }
1651             break;
1652 
1653         case ARPOP_RREQUEST:
1654             TextLog_Print(log, "RARP who-is %X:%X:%X:%X:%X:%X tell %X:%X:%X:%X:%X:%X",
1655                     p->ah->arp_tha[0], p->ah->arp_tha[1], p->ah->arp_tha[2],
1656                     p->ah->arp_tha[3], p->ah->arp_tha[4], p->ah->arp_tha[5],
1657                     p->ah->arp_sha[0], p->ah->arp_sha[1], p->ah->arp_sha[2],
1658                     p->ah->arp_sha[3], p->ah->arp_sha[4], p->ah->arp_sha[5]);
1659 
1660             break;
1661 
1662         case ARPOP_RREPLY:
1663 	    /* bcopy() deprecated, replaced with memmove() */
1664 	    memmove((void *) &ip_addr, (void *)p->ah->arp_tpa, sizeof(ip_addr));
1665             TextLog_Print(log, "RARP reply %X:%X:%X:%X:%X:%X at %s",
1666                     p->ah->arp_tha[0], p->ah->arp_tha[1], p->ah->arp_tha[2],
1667                     p->ah->arp_tha[3], p->ah->arp_tha[4], p->ah->arp_tha[5],
1668                     inet_ntoa(ip_addr));
1669 
1670             break;
1671 
1672         default:
1673             TextLog_Print(log, "Unknown operation: %d", ntohs(p->ah->ea_hdr.ar_op));
1674             break;
1675     }
1676 
1677     TextLog_Puts(log, "\n\n");
1678 #endif
1679 }
1680 #endif  // NO_NON_ETHER_DECODER
1681 
1682