Logo Search packages:      
Sourcecode: yersinia version File versions

isl.c

/* isl.c
 * Implementation and attacks for Inter-Switch Link Protocol
 *
 * Yersinia
 * By David Barroso <tomac@wasahero.org> and Alfredo Andres <slay@wasahero.org>
 * Copyright 2005 Alfredo Andres and David Barroso
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

#ifndef lint
static const char rcsid[] = 
       "$Id: isl.c,v 1.5 2005/09/13 12:10:39 t0mac Exp $";
#endif

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#define _REENTRANT

#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>       

#ifdef HAVE_NETINET_IN_SYSTM_H
#include <netinet/in_systm.h>
#else
#ifdef HAVE_NETINET_IN_SYSTEM_H
#include <netinet/in_system.h>
#endif
#endif

#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <time.h>

#ifdef TIME_WITH_SYS_TIME
#include <sys/time.h>
#endif

#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif

#ifdef HAVE_STRING_H
#include <string.h>
#endif

#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif

#ifdef HAVE_BSTRING_H
#include <bstring.h>
#endif

#ifdef STDC_HEADERS
#include <stdlib.h>
#endif

#ifdef HAVE_PTHREAD_H
#include <pthread.h>
#endif

#ifdef HAVE_GETOPT_LONG_ONLY
#include <getopt.h>
#else
#include "getopt.h"
#endif

#include <stdarg.h>

#include "isl.h"


void
isl_register(void)
{
    protocol_register(PROTO_ISL, "ISL", "Inter-Switch Link Protocol", sizeof(struct isl_data), isl_init_attribs, NULL,
          isl_get_printable_packet, isl_get_printable_store, NULL, NULL, NULL, isl_help, isl_parser, isl_fields, isl_get_info, NULL, isl_features);
}


/* 
 * Return formated strings of each ISL field
 */
char **
isl_get_printable_packet(struct pcap_data *data)
{
    char **field_values;
    u_int16_t aux_short;

    if (data && (data->header->caplen < (14+8+8)) ) /* Undersized packet!! */
       return NULL;

    if ((field_values = (char **) protocol_create_printable(ISL_TOTAL_FIELDS, isl_fields)) == NULL) {
          write_log(0, "Error in calloc\n");
          return NULL;
    }

    /* Source MAC */
    snprintf(field_values[ISL_SMAC], 18, "%02X:%02X:%02X:%02X:%02X:%02X",
       data->packet[6], data->packet[7], data->packet[8],
       data->packet[9], data->packet[10], data->packet[11]);
    /* Destination MAC */
    snprintf(field_values[ISL_DMAC], 18, "%02X:%02X:%02X:%02X:%02X:%02X",
       data->packet[0], data->packet[1], data->packet[2],
       data->packet[3], data->packet[4], 0x00);
    
    snprintf(field_values[ISL_TYPE], 2, "%01X", (*(u_int8_t *)(data->packet+5) & 0xF0));

    snprintf(field_values[ISL_USER], 2, "%01X", (*(u_int8_t *)(data->packet+5) & 0x0F));

    snprintf(field_values[ISL_LEN], 5, "%04X", (ntohs(*((u_int16_t *)data->packet+12))));

    snprintf(field_values[ISL_SNAP], 7, "%02X%02X%02X", (*(u_int8_t *)(data->packet+14)), (*(u_int8_t *)(data->packet+15)), 
            (*(u_int8_t *)(data->packet + 16)));

    snprintf(field_values[ISL_HSA], 7, "%02X%02X%02X", (*(u_int8_t *)(data->packet+17)), (*(u_int8_t *)(data->packet+18)), 
            (*(u_int8_t *)(data->packet + 19)));

    aux_short = ntohs(*((u_int16_t *)(data->packet+20)));
    aux_short >>= 1;
    snprintf(field_values[ISL_VLAN], 5, "%04X", aux_short);

    snprintf(field_values[ISL_BPDU], 2, "%01d", (ntohs(*((u_int16_t *)(data->packet+20))) & 0x1));

    snprintf(field_values[ISL_INDEX], 5, "%04X", (ntohs(*((u_int16_t *)(data->packet+22)))));

    snprintf(field_values[ISL_RES], 5, "%04X", (ntohs(*((u_int16_t *)(data->packet+24)))));
    
    return (char **)field_values;    
}


char *
isl_get_info(u_int8_t field, char *value)
{
    u_int8_t i;
    
    i = 0;

    switch (field) {
        case ISL_TYPE:
            while (isl_type[i].desc) {
                if (isl_type[i].type == strtoul(value, NULL, 16))
                    return isl_type[i].desc;
                i++;
            }
        break;
    }
        
    return "UNKN";
}


char **
isl_get_printable_store(struct term_node *node)
{
    struct isl_data *isl_tmp;
    char **field_values;
#ifdef LBL_ALIGN
    u_int8_t *aux;
#endif
    
    if ((field_values = (char **) protocol_create_printable(ISL_TOTAL_FIELDS, isl_fields)) == NULL) {
          write_log(0, "Error in calloc\n");
          return NULL;
    }

      if (node == NULL)
            isl_tmp = protocols[PROTO_ISL].default_values;
      else
        isl_tmp = (struct isl_data *) node->protocol[PROTO_ISL].tmp_data;

    /* Source MAC */
    snprintf(field_values[ISL_SMAC], 18, "%02X:%02X:%02X:%02X:%02X:%02X",
          isl_tmp->mac_source[0], isl_tmp->mac_source[1],
          isl_tmp->mac_source[2], isl_tmp->mac_source[3],
          isl_tmp->mac_source[4], isl_tmp->mac_source[5]);

    /* Destination MAC */
    snprintf(field_values[ISL_DMAC], 18, "%02X:%02X:%02X:%02X:%02X:%02X",
        isl_tmp->mac_dest[0], isl_tmp->mac_dest[1], isl_tmp->mac_dest[2],
        isl_tmp->mac_dest[3], isl_tmp->mac_dest[4], isl_tmp->mac_dest[5]);

    snprintf(field_values[ISL_TYPE], 2, "%01X", isl_tmp->type & 0x0F);

    snprintf(field_values[ISL_USER], 2, "%01X", isl_tmp->user & 0x0F);

    snprintf(field_values[ISL_LEN], 5, "%04X", isl_tmp->len);

    snprintf(field_values[ISL_SNAP], 7, "%02X%02X%02X", isl_tmp->snap[0], isl_tmp->snap[1],
            isl_tmp->snap[2]);

    snprintf(field_values[ISL_HSA], 7, "%02X%02X%02X", isl_tmp->hsa[0], isl_tmp->hsa[1],
            isl_tmp->hsa[2]);

    snprintf(field_values[ISL_VLAN], 5, "%04X", isl_tmp->vlan);

    snprintf(field_values[ISL_BPDU], 2, "%01d", isl_tmp->bpdu & 0x01);

    snprintf(field_values[ISL_INDEX], 5, "%04X", isl_tmp->index);
    
    snprintf(field_values[ISL_RES], 5, "%04X", isl_tmp->res);
               
    /* Source IP */
    parser_get_formated_inet_address(isl_tmp->src_ip, field_values[ISL_SRC_IP], 16);
    
    /* Destination IP */
    parser_get_formated_inet_address(isl_tmp->dst_ip, field_values[ISL_DST_IP], 16);

    /* IP protocol */
    snprintf(field_values[ISL_IP_PROTO], 3, "%02d",isl_tmp->ip_proto);

    return (char **)field_values;
}


int8_t
isl_init_attribs(struct term_node *node)
{
    struct isl_data *isl_data;

    isl_data = node->protocol[PROTO_ISL].tmp_data;

    attack_gen_mac(isl_data->mac_source);

    isl_data->mac_source[0] &= 0x0E; 
    
    parser_vrfy_mac(ISL_DFL_MAC_DST, isl_data->mac_dest);
    
    isl_data->type      = ISL_DFL_TYPE;
    isl_data->user      = 0x0;
    isl_data->len       = 0x0;
    memcpy((void *)isl_data->snap, (void *)ISL_DFL_SNAP, 3);
    memcpy((void *)isl_data->hsa, "\x00\x00\x00", 3);

    isl_data->vlan = libnet_get_prand(LIBNET_PRu16);

    isl_data->bpdu       = 0x0;
    isl_data->index      = 0x0;
    isl_data->res        = 0x0;

    isl_data->src_ip = ntohl(inet_addr("10.0.0.1"));
    isl_data->dst_ip = ntohl(inet_addr("255.255.255.255"));

    isl_data->ip_proto = 1;
    
    return 0;
}


void
isl_help(void)
{
    write_log(2,"%s\n", bin_data);
    write_log(2,"\nUsage: %s isl [-hM] [-i interface]\n", PACKAGE);
    write_log(2,"       [-smac hw_addr] [-dmac hw_addr] [-vlan vlan_id]\n");
    write_log(2,"       [-type type] [-user user] [-len len] [-bpdu 0|1] [-snap snap]\n");
    write_log(2,"       [-hsa hsa] [-index index] [-res res] [-ipsource ip_addr]\n");
    write_log(2,"       [-ipdest ip_addr] [-attack attack]\n\n");
    write_log(2,"           -h    This help screen.\n\n");         

    write_log(2,"Please, see the man page for a full list of options and many examples.\n");
    write_log(2,"Send your bugs & suggestions to the Yersinia developers <yersinia@wasahero.org>\n\n");  
}


/*
 * ISL parser...
 */
int8_t
isl_parser( struct term_node *node, int8_t argc, char **args, void *tmp_data)
{
    int8_t carac, indx, aux, tmp, ifaces;
    int opt_ind;
    struct isl_data *isl_data;
    struct term_tty *term_tty=NULL;
    struct attack *first_attack;
    u_int16_t aux_short;
    static struct option options[] =
    {
        { "help",        0, 0, 'h' },        
        { "M",           0, 0, 'M' },        
        { "attack",      1, 0, 0 },
        { "X",           1, 0, 0 },
        { "i",           1, 0, 1 },
        { "vlan",        1, 0, 2 },
        { "smac",        1, 0, 3 },
        { "dmac",        1, 0, 4 },
        { "type",        1, 0, 5 },
        { "user",        1, 0, 6 },
        { "len",         1, 0, 7 },
        { "bpdu",        1, 0, 8 },
        { "snap",        1, 0, 9 },
        { "hsa",         1, 0, 10 },
        { "index",       1, 0, 11 },
        { "res",         1, 0, 12 },
        { "ipsource",    1, 0, 13 },
        { "ipdest",      1, 0, 14 },
        { 0, 0, 0, 0 }
    };

    isl_data = node->protocol[PROTO_DOT1Q].tmp_data;

    ifaces = 0;

    term_tty = node->specific;

    while( (carac=getopt_long_only(argc,args,"hd",
                    options, &opt_ind)) != EOF)
    {
        switch(carac) 
        {
            case 0:
                aux=atoi(optarg);
                aux--;  /* Because our array starts with zero but user starts with 1... :) */
                indx = parser_command2index(isl_attack, aux);
                if (isl_attack[indx].s != NULL )
                    term_tty->attack = indx;
                else
                {
                    write_log(2,"\n  Ouch!! Invalid attack!! Valid %s ATTACK types are:\n", PACKAGE);
                    first_attack = isl_attack;
                    while (first_attack->s != NULL) 
                    {
                        write_log(2,"         %d: %s attack %s\n",first_attack->v+1,
                                (first_attack->type)?"DOS":"NONDOS",
                                first_attack->s);
                        ++first_attack;
                    }
                    write_log(2,"\n");
                    return -1;
                }
                break;

            case 1:
                if ((tmp = interfaces_get(optarg)) == -1)
                {
                   write_log(2,"Unable to use interface %s!! (Maybe nonexistent?)\n\n",optarg);
                   return -1;
                }
                 /* Don't repeat interface...*/
                if (!node->used_ints[tmp])
                {
                    if ((tmp = interfaces_add(optarg)) == -1)
                    {
                       write_log(2,"Unable to use interface %s!! (Maybe nonexistent?)\n\n",optarg);
                       return -1;
                    }
                    node->used_ints[tmp] = 1;
                    ifaces++;
                }
            break;

            case 2:
                aux_short = atoi(optarg);
                if (aux_short > 4095)
                {
                   write_log(2, " VLAN id incorrect!!\n");
                   return -1;
                }
                isl_data->vlan = aux_short;
            break;

            case 3:
                if (parser_vrfy_mac(optarg, isl_data->mac_source)) {
                    write_log(2, "Source MAC address incorrect!!\n");
                    return -1;
                }

            case 4: 
                if ( parser_vrfy_mac(optarg, isl_data->mac_dest) )
                {
                    write_log(2,"Destination MAC address incorrect!!\n");
                    return -1;
                }
            break;

            case 5:
                isl_data->type = atoi(optarg);
            break;

            case 6:
                isl_data->user = atoi(optarg);
            break;

            case 7:
                isl_data->len = atoi(optarg);
            break;

            case 8:
                isl_data->bpdu = atoi(optarg);
            break;

            case 13: /* IP source */

            break;

            case 14: /* IP destination */

            break;

            case 'h': 
                  isl_help();
                  return 0;
            break;

                  case 'M':
                     node->mac_spoofing = 0;
                  break;

            case '?': return -1;
            break;       
        }
    }

    /* select a default device if not specified */
    if (!ifaces)  {
        if (strlen(interfaces[0].ifname)) {
            write_log(2,"Warning: interface %s selected as the default one\n", &interfaces[0].ifname);
            if ((tmp = interfaces_add(interfaces[0].ifname)) == -1)
            {
               write_log(2,"Unable to use interface %s!! (Maybe nonexistent?)\n\n", interfaces[0].ifname);
               return -1;
            }
            else
                node->used_ints[tmp] = 1;
                ifaces++;
        } else {
            write_log(2,"Hmm... you don't have any valid interface. Go and get a life!\n");
            return -1;
        }
    }

   return 0;
}

/* vim:set tabstop=4:set expandtab:set shiftwidth=4:set textwidth=78: */


Generated by  Doxygen 1.6.0   Back to index