/*************************************************************************************/ /* xtraf.c */ /* para compilar se requiere de las librerias */ /* motif, openmotif o lesstif, libX11 y libpcap. */ /* http://bsdero.gulags.org.mx bsdero@gmail.com */ /*************************************************************************************/ /* COMPILACION: */ /* Linux: */ /* gcc -o xtraf xtraf.c -I/usr/X11R6/include -L/usr/X11R6/lib -lXm -lXt -lX11 -lpcap */ /* */ /* FreeBSD, NetBSD, OpenBSD: */ /* gcc -o xtraf xtraf.c -I/usr/local/include -L/usr/local/lib -lXm -lXt -lX11 -lpcap */ /* */ /* Solaris: */ /* gcc -o xtraf xtraf.c -I/opt/csw/include -L/opt/csw/lib -lXm -lXt -lX11 -lpcap */ /* */ /* Irix: */ /* gcc -o xtraf xtraf.c -lXm -lXt -lX11 -lpcap */ /*************************************************************************************/ /* HEADERS */ /*************************************************************************************/ #include /* header para libpcap */ #include #include #include #include #include #include #include #include #include /*************************************************************************************/ /* MOTIF HEADERS */ /*************************************************************************************/ #include #include #include #include #include #include #include #include #include #include /*************************************************************************************/ /* DEFINICIONES */ /*************************************************************************************/ /* default snap length (maximum bytes per packet to capture) */ #define SNAP_LEN 1518 /* ethernet headers are always exactly 14 bytes [1] */ #define SIZE_ETHERNET 14 /* Ethernet addresses are 6 bytes */ #define ETHER_ADDR_LEN 6 /* numero de paquetes a capturar */ #define PACKET_NUM 1000 #define STRLIST_LEN 2000 #define BIGSTRLIST_LEN 32768 /*************************************************************************************/ /* ESTRUCTURAS DE DATOS */ /*************************************************************************************/ /* Ethernet header */ struct sniff_ethernet { u_char ether_dhost[ETHER_ADDR_LEN]; /* destination host address */ u_char ether_shost[ETHER_ADDR_LEN]; /* source host address */ u_short ether_type; /* IP? ARP? RARP? etc */ }; /* IP header */ struct sniff_ip { u_char ip_vhl; /* version << 4 | header length >> 2 */ u_char ip_tos; /* type of service */ u_short ip_len; /* total length */ u_short ip_id; /* identification */ u_short ip_off; /* fragment offset field */ #define IP_RF 0x8000 /* reserved fragment flag */ #define IP_DF 0x4000 /* dont fragment flag */ #define IP_MF 0x2000 /* more fragments flag */ #define IP_OFFMASK 0x1fff /* mask for fragmenting bits */ u_char ip_ttl; /* time to live */ u_char ip_p; /* protocol */ u_short ip_sum; /* checksum */ struct in_addr ip_src,ip_dst; /* source and dest address */ }; #define IP_HL(ip) (((ip)->ip_vhl) & 0x0f) #define IP_V(ip) (((ip)->ip_vhl) >> 4) /* TCP header */ typedef u_int tcp_seq; struct sniff_tcp { u_short th_sport; /* source port */ u_short th_dport; /* destination port */ tcp_seq th_seq; /* sequence number */ tcp_seq th_ack; /* acknowledgement number */ u_char th_offx2; /* data offset, rsvd */ #define TH_OFF(th) (((th)->th_offx2 & 0xf0) >> 4) u_char th_flags; #define TH_FIN 0x01 #define TH_SYN 0x02 #define TH_RST 0x04 #define TH_PUSH 0x08 #define TH_ACK 0x10 #define TH_URG 0x20 #define TH_ECE 0x40 #define TH_CWR 0x80 #define TH_FLAGS (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG|TH_ECE|TH_CWR) u_short th_win; /* window */ u_short th_sum; /* checksum */ u_short th_urp; /* urgent pointer */ }; /* header udp */ struct sniff_udp { u_short udp_sport; /* source port */ u_short udp_dport; /*destination port */ u_short udp_length; /* data length */ u_short udp_checksum; /* checksum */ }; /* icmp */ struct sniff_icmp{ unsigned char icmp_type; unsigned char icmp_code; u_short icmp_checksum; }; /************************************************************************************************/ /* prototype functions DECLARACION DE FUNCIONES */ /************************************************************************************************/ /* evento, se genera cuando se captura un paquete */ void got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet); /* despliega el contenido del paquete */ void print_payload(const u_char *payload, int len); /* desplegar el contenido en hexadecimal */ void print_hex_ascii_line(const u_char *payload, int len, int offset); /* evento para salir */ void quit_call(Widget , int); /* evento para el submenu archivo */ void menu1_call(Widget , int); /* evento para submenu sniffer */ void menu2_call(Widget , int); /* evento para ayuda */ void help_call(void); /* inicializa sniffer */ void init_sniffer(); /* rellena la lista de paquetes */ void fill_list(); /* despliega el contenido del paquete */ void display_packet( Widget w, XtPointer data, XmListCallbackStruct *list_cbs); /* iniciar la esnifeada */ void start_scan(); /* ajustar la seleccion de protocolos */ void set_selection(Widget widget, XtPointer client_data, XmToggleButtonCallbackStruct *state); void guarda_historico(); /*************************************************************************************/ /* VARIABLES GLOBALES */ /*************************************************************************************/ /* el tipo widget son cualquiera de los componentes del formulario: botones, radios, campos de texto, labels, ventanas y otras cosas */ Widget label; Widget top_wid, main_w, help, list; Widget menubar, menu1, menu2, widget, rowcol, text_wid; Widget opt_w, rowcol1, rowcol2, rowcol3, rowcol4; Widget radio1, radio2, radio3, radio4; Widget label1, label2, label3; Widget edit1, edit2; Widget button1; Widget separator1; /* tabla de cadenas, util para Motif */ XmStringTable str_list; int pkg_num; /* numero de paquetes a sniffear */ int radio_status; /* estado del menu de botones de radio */ int max_pkg, prot_port; /* maximo de paquetes a sniffear, y protocolo a sniffear, todo capturado de la interfaz */ /* tipo de ICMP y mensajes */ char icmp_type_strings[][40] = { "Echo reply ", /* icmp tipo 0 */ "Reserved ", /* icmp tipo 1 */ "Reserved ", /* icmp tipo 2 */ "Destination unreachable ", /* .... */ "Source quench ", "Redirect ", "Alternate Host Address ", "Reserved ", "Echo request ", "Router advertisement ", "Router solicitation ", /* tipo 10*/ "Time exceeded ", "Parameter problem ", "Timestamp request ", "Timestamp reply ", "Information request ", "Information reply ", "Address mask request ", "Address mask reply ", "Reserved (for security). ", "Reserved (for robustness experiment) ", /* 20 */ "Reserved (for robustness experiment) ", "Reserved (for robustness experiment) ", "Reserved (for robustness experiment) ", "Reserved (for robustness experiment) ", "Reserved (for robustness experiment) ", "Reserved (for robustness experiment) ", "Reserved (for robustness experiment) ", "Reserved (for robustness experiment) ", "Reserved (for robustness experiment) ", "Traceroute ", /* 30 */ "Conversion error ", "Mobile Host Redirect ", "IPv6 Where-Are-You ", "IPv6 I-Am-Here ", "Mobile Registration Request ", "Mobile Registration Reply ", "Domain Name request ", "Domain Name reply ", "SKIP Algorithm Discovery Protocol " }; /* tabla de paquetes */ /* aca se guardan los datos de los paquetes capturados */ char cadenas[PACKET_NUM+1][STRLIST_LEN]; /* aqui lo que se presenta en la lista */ char pkg_data[PACKET_NUM+1][BIGSTRLIST_LEN]; /* aca lo del editor de texto */ /*************************************************************************************/ /* gui_start: */ /* inicializa la interfaz grafica */ /*************************************************************************************/ void gui_start(int argc, char **argv){ XtAppContext app; XColor back, fore, spare; /* etiquetas */ XmString acerca_str, archivo_str, sniffer_str, guardar_str, salir_str, configuracion_str, iniciar_str, label_str; int n = 0, i; Arg args[10]; #ifdef _DEBUG printf("\r\nDEBUG5"); fflush( stdout); #endif /* Inicializar motif */ top_wid = XtVaAppInitialize(&app, "xtraf", NULL, 0, &argc, argv, NULL, NULL); /* crear ventana principal */ main_w = XtVaCreateManagedWidget("main_window", xmMainWindowWidgetClass, top_wid, XmNwidth, 900, XmNheight, 550, NULL); /* crear dialogo de seleccion de protocolos, numero de puertos y demas */ opt_w = XmCreateFormDialog( top_wid, "opt_win", NULL, 0); /* asignar valores por default al dialogo */ XtVaSetValues( opt_w, XmNhorizontalSpacing, 4, XmNverticalSpacing, 4, XmNdeleteResponse, XmDO_NOTHING, NULL ); /* primero hay que crear las cadenas de los menus */ archivo_str = XmStringCreateLocalized("Archivo"); sniffer_str = XmStringCreateLocalized("Sniffer"); guardar_str = XmStringCreateLocalized("Guardar Historico..."); salir_str = XmStringCreateLocalized("Salir"); iniciar_str = XmStringCreateLocalized("Iniciar"); /* Crear la barra de menu con dos opciones en la ventana principal */ menubar = XmVaCreateSimpleMenuBar(main_w, "menubar", XmVaCASCADEBUTTON, archivo_str, 'A', XmVaCASCADEBUTTON, sniffer_str, 'S', NULL); XmStringFree(archivo_str); /* ya creamos ventana y barra de menu, eliminar cadenas */ XmStringFree(sniffer_str); /* crear submenu archivo -- evento es menu1_call() */ menu1 = XmVaCreateSimplePulldownMenu(menubar, "archivo_menu", 0, menu1_call, XmVaPUSHBUTTON, guardar_str, 'G', NULL, NULL, XmVaPUSHBUTTON, salir_str, 'S', NULL, NULL, XmNradioBehavior, True, /* select radio behavior in Menu */ XmNradioAlwaysOne, True, NULL); /* crear submenu sniffer, evento es menu2_call() */ menu2 = XmVaCreateSimplePulldownMenu(menubar, "sniffer_menu", 1, menu2_call, XmVaPUSHBUTTON, iniciar_str, 'I', NULL, NULL, XmNradioBehavior, True, /* select radio behavior in Menu */ XmNradioAlwaysOne, True, NULL); /* liberar cadenas */ XmStringFree(iniciar_str); XmStringFree(guardar_str); XmStringFree(salir_str); n=0; /* reset n */ /* crear ultimo menu */ help = XtVaCreateManagedWidget( "Help", xmCascadeButtonWidgetClass, menubar, XmNmnemonic, 'H', NULL); /* asignarle el evento help call */ XtAddCallback(help, XmNactivateCallback, help_call, NULL); /* decirle al menubar, cual boton es el de ayuda */ /* configurar parametros */ XtSetArg(args[n],XmNmenuHelpWidget,help); n++; /* asignar al menu */ XtSetValues(menubar,args,n); n=0; /* reset n */ /* inicializar menubar */ XtManageChild(menubar); /* crear espaciador vertical, en la ventana principal */ rowcol = XtVaCreateManagedWidget("rowcolumn", xmRowColumnWidgetClass, main_w, XmNorientation, XmVERTICAL, XmNpacking, XmPACK_COLUMN, NULL); /* para depurar */ #ifdef _DEBUG printf("\r\nDEBUG6"); fflush( stdout); #endif /* crear una lista */ XtSetArg(args[0], XmNvisibleItemCount, 10); XtSetArg(args[1], XmNitemCount, 0); XtSetArg(args[2], XmNwidth, 40); XtSetArg(args[3], XmNheight, 10); XtSetArg(args[4], XmNscrollBarDisplayPolicy, XmSTATIC); XtSetArg(args[5], XmNlistSizePolicy, XmVARIABLE); list = XmCreateScrolledList( rowcol, "list", args, 6); /* y su evento correspondiente cuando den click en alguna opcion es display_packet */ XtAddCallback(list, XmNdefaultActionCallback, display_packet, NULL); /* añadirlo al manejador */ XtManageChild(list); /* crear un contenedor de textos */ XtSetArg(args[0], XmNrows, 16); XtSetArg(args[1], XmNcolumns, 80); XtSetArg(args[2], XmNeditable, False); XtSetArg(args[3], XmNeditMode, XmMULTI_LINE_EDIT); text_wid = XmCreateScrolledText(rowcol, "text_wid", args, 4); XtManageChild(text_wid); /* aqui se van a crear los componentes del dialogo de captura */ /* crear los contenedores de componentes para el dialogo de captura */ rowcol1 = XtVaCreateManagedWidget("rowcolumn2", xmRowColumnWidgetClass, opt_w, XmNorientation, XmVERTICAL, XmNpacking, XmPACK_COLUMN, NULL); rowcol2 = XtVaCreateManagedWidget("rowcolumn3", xmRowColumnWidgetClass, rowcol1, XmNorientation, XmHORIZONTAL, XmNpacking, XmPACK_COLUMN, XmNradioBehavior, True, NULL); rowcol3 = XtVaCreateManagedWidget("rowcolumn4", xmRowColumnWidgetClass, rowcol2, XmNorientation, XmVERTICAL, XmNpacking, XmPACK_COLUMN, XmNradioBehavior, True, NULL); rowcol4 = XtVaCreateManagedWidget("rowcolumn4", xmRowColumnWidgetClass, rowcol2, XmNorientation, XmVERTICAL, XmNpacking, XmPACK_COLUMN, XmNradioBehavior, True, NULL); /* crear etiqueta */ label1 = XmCreateLabel( rowcol3, "Seleccione el protocolo", NULL, 0); XtManageChild( label1); /* y botones de radio con seleccion de protocolo */ radio1 = XmCreateToggleButton( rowcol3, "IP", NULL, 0); XtManageChild( radio1); radio2 = XmCreateToggleButton( rowcol3, "TCP", NULL, 0); XtManageChild( radio2); radio3 = XmCreateToggleButton( rowcol3, "UDP", NULL, 0); XtManageChild( radio3); radio4 = XmCreateToggleButton( rowcol3, "ICMP", NULL, 0); XtManageChild( radio4); /* crear otra etiqueta */ label2 = XmCreateLabel( rowcol4, "Puerto(TCP o UDP)/Tipo (ICMP)", NULL, 0); XtManageChild( label2); /* campo de texto para capturar puerto */ edit1 = XmCreateText(rowcol4, "text1", NULL, 0); XtManageChild( edit1); XmTextSetString( edit1, ""); /* crear un separador */ separator1 = XmCreateSeparator( rowcol4, "separator", NULL , 0); XtManageChild( separator1); /* otra etiqueta mas */ label3 = XmCreateLabel( rowcol4, "Capture el numero de paquetes", NULL, 0); XtManageChild( label3); /* campo de texto para capturar el numero de paquetes */ edit2 = XmCreateText(rowcol4, "text2", NULL, 0); XtManageChild( edit2); XmTextSetString( edit2, ""); /* crear boton */ XtSetArg(args[0], XmNwidth, 50); XtSetArg(args[1], XmNheight, 20); button1 = XmCreatePushButton( rowcol1, "Capturar paquetes", args, 2); XtAddCallback(button1, XmNarmCallback, start_scan, NULL); XtManageChild( button1); /* añadir eventos para los botones de radio */ XtAddCallback( radio1, XmNvalueChangedCallback, set_selection, NULL); XtAddCallback( radio2, XmNvalueChangedCallback, set_selection, NULL); XtAddCallback( radio3, XmNvalueChangedCallback, set_selection, NULL); XtAddCallback( radio4, XmNvalueChangedCallback, set_selection, NULL); /* dibujar formulario principal */ XtRealizeWidget(top_wid); /* pasarlo al ciclo principal de la aplicacion */ XtAppMainLoop(app); } /*************************************************************************************/ /* set_selection: (evento que se genera cuando dan click en boton de radio) */ /* obtener la seleccion de protocolo */ /*************************************************************************************/ void set_selection(Widget widget, XtPointer client_data, XmToggleButtonCallbackStruct *state){ char cadena[10]; if( state->set ){ strcpy( cadena, XtName( widget)); /* obtener el nombre del radio pulsado */ if( !strcmp( cadena, "IP")){ radio_status = 1; }else if( !strcmp( cadena, "TCP")){ radio_status = 2; }else if( !strcmp( cadena, "UDP")){ radio_status = 3; }else if( !strcmp( cadena, "ICMP")){ radio_status = 4; } printf("\r\nradio_status = %d\r\n", radio_status); } } /*************************************************************************************/ /* start_scan: (evento que se genera cuando presionan el boton OK dialogo rastreo) */ /* comenzar el rastreo de paquetes */ /*************************************************************************************/ void start_scan(){ char strnumpacks[128], strport[128]; XtUnmanageChild(opt_w); /* quitar el dialogo de captura */ strcpy( strnumpacks, XmTextGetString( edit2)); /* sacar el numero de paquetes */ strcpy( strport, XmTextGetString( edit1)); /* y de puerto */ /* convertir a numeros */ max_pkg = strtol(strnumpacks, (char **)NULL, 10); prot_port = strtol(strport, (char **)NULL, 10); printf("\r\nradio_status = %d\r\n", radio_status); printf("numpacks = %s:%d\r\n", strnumpacks, max_pkg); printf("port = %s:%d\r\n", strport, prot_port); XmListDeleteAllItems( list); /* borrar todos los elementos de la lista */ init_sniffer(); /* inicializar sniffer */ fill_list(); /* llena la lista */ return; } /*************************************************************************************/ /* fill_list: */ /* llenar la lista de paquetes */ /*************************************************************************************/ void fill_list(){ int i; XmString xmstr; /* para depurar */ #ifdef _DEBUG printf("\r\npkg_num=%d", pkg_num); fflush( stdout); #endif for (i = 0; i < pkg_num; i++){ xmstr = XmStringCreateSimple(cadenas[i]); /* crear cadena a partir del elemento i del array*/ XmListAddItemUnselected( list, xmstr, 0); /* lo añadimos a la lista */ XmStringFree(xmstr); /* liberar cadena */ } } /*************************************************************************************/ /* display_packet:(evento generado cuando dan doble click en elemento de la lista) */ /* despliega el contenido del paquete en el contenedor de textos */ /*************************************************************************************/ void display_packet( Widget w, XtPointer data, XmListCallbackStruct *list_cbs){ int n =0, j; Arg args[1]; String selection; char *tdata; char c; /* XmStringGetLtoR(list_cbs->item, XmSTRING_DEFAULT_CHARSET, &selection);*/ n = list_cbs->item_position-1; /* item_position contiene el subindice del item marcado */ printf("\r\n\r\n%s\r\n\r\n", pkg_data[n]); printf("\r\nSeleccion: %d", n); fflush( stdout); /* colocar texto en contenedor */ XmTextSetString( text_wid, pkg_data[n]); /* para depurar */ #ifdef _DEBUG printf("\r\nDEBUG DISPLAY_PACKET"); fflush( stdout); #endif } /*************************************************************************************/ /* close_app:(evento generado cuando dan click en opcion Salir del menu ) */ /* cierra la aplicacion */ /*************************************************************************************/ void close_app(){ exit(0); } /*************************************************************************************/ /* select_archivo: (evento generado cuando dan click en OK en el dialogo de */ /* guardar el historial) */ /*************************************************************************************/ void select_archivo(Widget widget, XtPointer client_data, XmFileSelectionBoxCallbackStruct *selection){ /* function opens file (text) and prints to stdout */ FILE *fp; char *filename, line[200]; int i; /* obtener el nombre del archivo en filename */ XmStringGetLtoR(selection->value, XmSTRING_DEFAULT_CHARSET, &filename); /* abrir el archivo */ if ( (fp = fopen(filename,"w")) == NULL) perror("CANNOT OPEN FILE"); else{ for( i = 0; i < pkg_num; i++) /* guardar la informacion */ fprintf( fp, "\r\n\r\n--------------------------------------------------\r\n%s", pkg_data[i]); /* cerrar archivo */ fclose(fp); } /* quitar dialogo de guardar */ XtUnmanageChild(widget); } /*************************************************************************************/ /* cancel_archivo: (evento) */ /* se genera cuando el usuario presiona cancelar en el cuadro de dialogo del */ /* historial. */ /*************************************************************************************/ void cancel_archivo(Widget widget, XtPointer client_data, XmFileSelectionBoxCallbackStruct *selection){ XtUnmanageChild(widget); /* undisplay widget/cerrar cuadro de dialogo */ } /*************************************************************************************/ /* guarda_historico:(evento) */ /* se genera cuando el usuario presiona OK en el cuadro de dialogo del */ /* historial. Crea formulario de guardar archivo historico. */ /*************************************************************************************/ void guarda_historico(){ Widget dialog, remove; XmString mask; Arg args[1]; /* Create the FileSelectionDialog */ mask = XmStringCreateLocalized("*.txt"); /* *.txt: mascara de archivo */ XtSetArg(args[0], XmNdirMask, mask); /* largo y ancho del dialogo */ XtSetArg(args[1], XmNheight, 480); XtSetArg(args[2], XmNwidth, 640); /* crear el dialogo de seleccion de archivo */ dialog = XmCreateFileSelectionDialog(main_w, "seleccion", args, 3); /* añadir eventos para cuando presionan OK o CANCEL */ XtAddCallback(dialog, XmNokCallback, select_archivo, NULL); XtAddCallback(dialog, XmNcancelCallback, cancel_archivo, NULL); /* eliminar boton de ayuda */ remove = XmSelectionBoxGetChild(dialog, XmDIALOG_HELP_BUTTON); XtUnmanageChild(remove); /* delete HELP BUTTON */ /* desplegar dialogo */ XtManageChild(dialog); XtPopup(XtParent(dialog), XtGrabNone); } /*************************************************************************************/ /* menu1_call: (evento) */ /* se genera cuando el usuario presiona cualquier opcion del menu "archivo" */ /*************************************************************************************/ void menu1_call(Widget w, int item_no){ int n =0; Arg args[1]; XmString label_str; char t[] = "PRUEBA1"; if( item_no == 1){ close_app(); /* si la opcion fue la 1 (Salir), ir a close_app */ } guarda_historico(); /* si no, la otra opcion fue la que se selecciono, por lo tanto guardar */ } /*************************************************************************************/ /* menu2_call: (evento) */ /* se genera cuando el usuario presiona la unica opcion del menu "sniffer" */ /*************************************************************************************/ void menu2_call(Widget w, int item_no){ XtManageChild(opt_w);/* aparecer el dialogo de rastreo */ } /*************************************************************************************/ /* help_call : (evento) */ /* se genera cuando el usuario presiona la unica opcion del menu "help" */ /*************************************************************************************/ void help_call(){ printf("Sorry, I'm Not Much Help\n"); } /*************************************************************************************/ /* print_hex_ascii_line : */ /* va desplegando y guardando una linea hexadecimal-ascii */ /*************************************************************************************/ void print_hex_ascii_line(const u_char *payload, int len, int offset){ int i; int gap; const u_char *ch; char bigstr[BIGSTRLIST_LEN]; /* offset */ printf("%05d ", offset); sprintf( bigstr, "%05d ", offset); strcat( pkg_data[pkg_num], bigstr); /* hex */ ch = payload; for(i = 0; i < len; i++) { printf("%02x ", *ch); sprintf( bigstr, "%02x ", *ch); strcat( pkg_data[pkg_num], bigstr); ch++; /* print extra space after 8th byte for visual aid */ if (i == 7){ printf(" "); strcat( pkg_data[pkg_num], " "); } } /* print space to handle line less than 8 bytes */ if (len < 8){ printf(" "); strcat( pkg_data[pkg_num], " "); } /* fill hex gap with spaces if not full line */ if (len < 16) { gap = 16 - len; for (i = 0; i < gap; i++) { printf(" "); strcat( pkg_data[pkg_num], " "); } } printf(" "); strcat( pkg_data[pkg_num], " "); /* ascii (if printable) */ ch = payload; for(i = 0; i < len; i++) { if (isprint(*ch)){ printf("%c", *ch); sprintf( bigstr, "%c", *ch); strcat( pkg_data[pkg_num], bigstr); }else{ printf("."); strcat( pkg_data[pkg_num], "."); } ch++; } printf("\n"); strcpy( bigstr, pkg_data[pkg_num]); sprintf( pkg_data[pkg_num], "%s\n", bigstr); return; } /*************************************************************************************/ /* print_payload: */ /* despliega el contenido de un paquete */ /*************************************************************************************/ void print_payload(const u_char *payload, int len){ int len_rem = len; int line_width = 16; /* number of bytes per line */ int line_len; int offset = 0; /* zero-based offset counter */ const u_char *ch = payload; /* strcpy( pkg_data[pkg_num], "");*/ if (len <= 0) return; /* data fits on one line */ if (len <= line_width) { print_hex_ascii_line(ch, len, offset); return; } /* data spans multiple lines */ for ( ;; ) { /* compute current line length */ line_len = line_width % len_rem; /* print line */ print_hex_ascii_line(ch, line_len, offset); /* compute total remaining */ len_rem = len_rem - line_len; /* shift pointer to remaining bytes to print */ ch = ch + line_len; /* add offset */ offset = offset + line_width; /* check if we have line width chars or less */ if (len_rem <= line_width) { /* print last line and get out */ print_hex_ascii_line(ch, len_rem, offset); break; } } printf( "\r\n\r\n%s\r\n\r\n", pkg_data[pkg_num]); return; } /*************************************************************************************/ /* got_packet: (evento) */ /* se genera cuando se obtiene un paquete por pcap */ /*************************************************************************************/ void got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet){ /* declare pointers to packet headers */ const struct sniff_ethernet *ethernet; /* The ethernet header [1] */ const struct sniff_ip *ip; /* The IP header */ const struct sniff_tcp *tcp; /* The TCP header */ const struct sniff_udp *udp; const struct sniff_icmp *icmp; const char *payload; /* Packet payload */ const char *udp_data; int j, l; char cad[200], sp[12], dp[12], sip[20], dip[20]; char bigstr[BIGSTRLIST_LEN]; int size_ip; int size_tcp; int size_payload; int size_udp_data; strcpy( pkg_data[pkg_num], ""); /* en pkg_data se guarda el contenido de paquetes */ printf("\nPacket number %d:\n", pkg_num+1); sprintf( bigstr, "\nPacket number %d:\n", pkg_num+1); strcat( pkg_data[pkg_num], bigstr); /* define ethernet header */ ethernet = (struct sniff_ethernet*)(packet); /* define/compute ip header offset */ ip = (struct sniff_ip*)(packet + SIZE_ETHERNET); size_ip = IP_HL(ip)*4; if (size_ip < 20) { printf(" * Invalid IP header length: %u bytes\n", size_ip); pkg_num++; return; } /* print source and destination IP addresses */ printf(" From: %s\n", inet_ntoa(ip->ip_src)); printf(" To: %s\n", inet_ntoa(ip->ip_dst)); sprintf( bigstr, "\n From: %s", inet_ntoa(ip->ip_src)); strcat( pkg_data[pkg_num], bigstr); sprintf( bigstr, "\n To: %s", inet_ntoa(ip->ip_dst)); strcat( pkg_data[pkg_num], bigstr); /* ajustar tamaños de cadenas con direcciones IP */ strcpy( sip, inet_ntoa(ip->ip_src)); strcpy( dip, inet_ntoa(ip->ip_dst)); l = 15 - strlen( sip); for( j = 0; j < l; j++) strcat( sip, " "); l = 15 - strlen( dip); for( j = 0; j < l; j++) strcat( dip, " "); switch( ip->ip_p){ case IPPROTO_TCP:{ printf("\r\n Protocol: TCP"); strcat( pkg_data[pkg_num], "\n Protocol: TCP\n"); /* define/compute tcp header offset */ tcp = (struct sniff_tcp*)(packet + SIZE_ETHERNET + size_ip); size_tcp = TH_OFF(tcp)*4; if (size_tcp < 20) { printf(" * Invalid TCP header length: %u bytes\n", size_tcp); return; } sprintf( sp, "%d", ntohs(tcp->th_sport)); for( j = strlen( sp); j <= 6; j++) strcat( sp, " "); sprintf( dp, "%d", ntohs(tcp->th_dport)); for( j = strlen( dp); j <= 6; j++) strcat( dp, " "); sprintf( cad, "TCP | SRC:%s | DST:%s | SRCPORT:%s| DSTPORT:%s| FRAGMENT:%d | SEQ:%u", sip, dip, sp, dp, ntohs(ip->ip_off), ntohs(tcp->th_seq)); printf( "%d\tTCP\t\t%s-->%s\t\t%d-->%d", pkg_num, sip, dip, sp, dp ); strcpy( cadenas[pkg_num], cad); printf(" Src port: %s\n", sp); printf(" Dst port: %s\n", dp); /* define/compute tcp payload (segment) offset */ payload = (u_char *)(packet + SIZE_ETHERNET + size_ip + size_tcp); /* compute tcp payload (segment) size */ size_payload = ntohs(ip->ip_len) - (size_ip + size_tcp); /* * Print payload data; it might be binary, so don't just * treat it as a string. */ if (size_payload > 0) { printf(" Payload (%d bytes):\n", size_payload); print_payload(payload, size_payload); } pkg_num++; return; break; } case IPPROTO_UDP:{ printf(" Protocol: UDP\n"); strcat( pkg_data[pkg_num], "\n Protocol: UDP\n"); udp = (struct sniff_udp*)(packet + SIZE_ETHERNET + size_ip); sprintf( sp, "%d", ntohs(udp->udp_sport)); for( j = strlen( sp); j <= 6; j++) strcat( sp, " "); sprintf( dp, "%d", ntohs(udp->udp_dport)); for( j = strlen( dp); j <= 6; j++) strcat( dp, " "); sprintf( cad, "UDP | SRC:%s | DST:%s | SRCPORT:%s| DSTPORT:%s| FRAGMENT:%d", sip, dip, sp, dp, ntohs(ip->ip_off)); strcpy( cadenas[pkg_num], cad); printf(" Src port: %s\n", sp); printf(" Dst port: %s\n", dp); /* define/compute tcp payload (segment) offset*/ payload = (u_char *)(packet + SIZE_ETHERNET + size_ip + sizeof(struct sniff_udp)); /* compute tcp payload (segment) size */ size_payload = ntohs( udp->udp_length); /* * Print payload data; it might be binary, so don't just * treat it as a string. */ if (size_payload > 0){ printf(" Payload (%d bytes):\n", size_payload); print_payload(payload, size_payload); } pkg_num++; return; break; } case IPPROTO_ICMP:{ printf(" Protocol: ICMP\n"); icmp = ( struct sniff_icmp*)(packet + SIZE_ETHERNET + size_ip); strcat( pkg_data[pkg_num], "\n Protocol: ICMP\n"); sprintf( cad, "ICMP | SRC:%s | DST:%s | Type: %d->%s | Code: %d\r\n", sip, dip, icmp->icmp_type, icmp_type_strings[icmp->icmp_type], icmp->icmp_code ); printf("ICMP Type: %d->%s\t\tCode: %d\r\n", icmp->icmp_type, icmp_type_strings[icmp->icmp_type], icmp->icmp_code ); strcpy( cadenas[pkg_num], cad); pkg_num++; return; } case IPPROTO_IP:{ printf("\r\n Protocol: IP\n"); strcat( pkg_data[pkg_num], "\n Protocol: IP\n"); sprintf( cadenas[pkg_num], "IP\t\t%s-->%s", inet_ntoa(ip->ip_src), inet_ntoa(ip->ip_dst)); pkg_num++; return; } default:{ printf(" Protocol: unknown\n"); pkg_num++; return; } }/* switch */ } /*************************************************************************************/ /* init_sniffer: */ /* inicializa el sniffer y prepara pcap */ /*************************************************************************************/ void init_sniffer(){ char *dev = NULL; /* capture device name */ char errbuf[PCAP_ERRBUF_SIZE]; /* error buffer */ pcap_t *handle; /* packet capture handle */ char pcad[10]; char filter_exp[32]; /* filter expression [3] */ struct bpf_program fp; /* compiled filter program (expression) */ bpf_u_int32 mask; /* subnet mask */ bpf_u_int32 net; /* ip */ int i; int num_packets = max_pkg; /* number of packets to capture */ pkg_num = 0; strcpy( filter_exp, ""); switch( radio_status ){ case 1: strcpy( filter_exp, "ip"); break; case 2: strcpy( filter_exp, "tcp"); break; case 3: strcpy( filter_exp, "udp"); break; case 4: strcpy( filter_exp, "icmp"); break; } if( prot_port > 0){ strcat( filter_exp, " port "); sprintf( pcad, "%d", prot_port); strcat( filter_exp, pcad); } printf("\r\nfilter=%s\r\n", filter_exp); memset( &cadenas, 0, sizeof( cadenas)); memset( &pkg_data, 0, sizeof( pkg_data)); if( num_packets == 0) num_packets = 10; dev = pcap_lookupdev(errbuf); if (dev == NULL) { fprintf(stderr, "Couldn't find default device: %s\n",errbuf); exit(EXIT_FAILURE); } /* get network number and mask associated with capture device */ if (pcap_lookupnet(dev, &net, &mask, errbuf) == -1) { fprintf(stderr, "Couldn't get netmask for device %s: %s\n", dev, errbuf); net = 0; mask = 0; } #ifdef _DEBUG printf("\r\nDEBUG1"); fflush( stdout); #endif /* print capture info */ printf("Device: %s\n", dev); printf("Number of packets: %d\n", num_packets); printf("Filter expression: %s\n", filter_exp); /* open capture device */ handle = pcap_open_live(dev, SNAP_LEN, 1, 1000, errbuf); if (handle == NULL) { fprintf(stderr, "Couldn't open device %s: %s\n", dev, errbuf); exit(EXIT_FAILURE); } /* make sure we're capturing on an Ethernet device [2] */ if (pcap_datalink(handle) != DLT_EN10MB) { fprintf(stderr, "%s is not an Ethernet\n", dev); exit(EXIT_FAILURE); } /* compile the filter expression */ if (pcap_compile(handle, &fp, filter_exp, 0, net) == -1) { fprintf(stderr, "Couldn't parse filter %s: %s\n", filter_exp, pcap_geterr(handle)); exit(EXIT_FAILURE); } /* apply the compiled filter */ if (pcap_setfilter(handle, &fp) == -1) { fprintf(stderr, "Couldn't install filter %s: %s\n", filter_exp, pcap_geterr(handle)); exit(EXIT_FAILURE); } #ifdef _DEBUG printf("\r\nDEBUG2"); fflush( stdout); #endif /* now we can set our callback function */ pcap_loop(handle, num_packets, got_packet, NULL); /* cleanup */ #ifdef _DEBUG printf("\r\nDEBUG3"); fflush( stdout); #endif pcap_freecode(&fp); pcap_close(handle); #ifdef _DEBUG printf("\r\nDEBUG4"); fflush( stdout); #endif for( i = 0; i < pkg_num; i++) printf("\r\n%d.-%s", i, cadenas[i]); } /*************************************************************************************/ /* MAIN */ /*************************************************************************************/ int main(int argc, char **argv){ gui_start( argc, argv); }