/****************************************************************************
   Program:     $Id: dnetspoof.c,v 1.2 2006/11/19 21:01:17 rbeverly Exp $
   Author:      Rob Beverly <rbeverly@mit.edu>
   Date:        $Date: 2006/11/19 21:01:17 $
   Description: Spoofer utility routines
****************************************************************************/
#include "spoof.h"

#ifdef _WIN32
#include "dnet.h"

#define INT_NAME_LEN 10
#define MAX_INTERFACES 10
static char intlist[INT_NAME_LEN * MAX_INTERFACES];
static int intcount = 0;
static int intselected = 0;
static struct eth_hdr eh;
static eth_t *e = NULL;

int etherOpen(char *dev) {
    if (e != NULL) 
        return(-1);
    
    if ((e = eth_open(dev)) == NULL) {
        printf("err: eth_open: %s\n", dev);
        return(-1);
    }
    return(0);
}

int etherClose() {
    if (e == NULL)
        return(-1);
    e = NULL;
    return(0);
}

void print_eth(eth_addr_t *ea) {
    uint8_t *u;
    int i;
    u = (uint8_t *)ea;
    for (i=0;i<ETH_ADDR_LEN;i++) {
        if (DEBUG) printf("Byte[%d]: %02x\n", i, *u);
        printf("%02x", *u);
        if (i < ETH_ADDR_LEN-1) printf(":");
        u++;
    }
    printf("\n");
}

struct addr getRoute(char *dst) {
    route_t *r;
    struct route_entry re;

    memset(&re, 0, sizeof(struct route_entry));
    if ((r = route_open()) == NULL)
        printf("err: route_open()\n");
    re.route_dst.addr_ip = inet_addr(dst);
    re.route_dst.addr_type = ADDR_TYPE_IP;
    re.route_dst.addr_bits = IP_ADDR_BITS;
    if (route_get(r, &re) < 0)
        if (DEBUG) printf("err: route_get()\n");
    route_close(r);
    return (re.route_gw);
}

struct addr getARP(struct addr *pa) {
    arp_t *a;
    struct arp_entry ae;

    memset(&ae, 0, sizeof(struct arp_entry));
    if ((a = arp_open()) == NULL)
        printf("err: arp_open()\n");
    ae.arp_pa = *pa;
    if (arp_get(a, &ae) < 0)
        printf("err: arp_get()\n");
    arp_close(a);
    return (ae.arp_ha);
}

int grabEther(struct eth_hdr *eh) {
    eth_addr_t ea;
    struct addr gw;
    struct addr gw_eth;

    memset(&gw, 0, sizeof(struct addr));
    memset(&gw_eth, 0, sizeof(struct addr));

    
    printf(">> Fetching MAC address of %s...", &intlist[intselected*INT_NAME_LEN]);
    eth_get(e, &ea);
    print_eth(&ea);

    if (DEBUG) printf(">> Fetching route toward: %s...", SERVER);
    gw = getRoute(SERVER);
    
    /* if no route found, server may be local, so arp for server */
    if (gw.addr_ip == 0) {
        gw.addr_ip = inet_addr(SERVER);
        gw.addr_type = ADDR_TYPE_IP;
        gw.addr_bits = IP_ADDR_BITS;
    } 
    if (DEBUG) printf("%d.%d.%d.%d\n", NIPQUAD(gw.addr_ip));

    printf(">> Fetching arp entry for %d.%d.%d.%d...", NIPQUAD(gw.addr_ip));
    gw_eth = getARP(&gw);
    if (gw_eth.addr_type == ADDR_TYPE_NONE) {
        fatal("\n*** FATAL: Couldn't determine destination MAC address.  Bailing.\n");
    }
    print_eth(&gw_eth.addr_eth);
    eh->eth_type = htons(ETH_TYPE_IP);
    memcpy(&eh->eth_src, &ea, ETH_ADDR_LEN);
    memcpy(&eh->eth_dst, &gw_eth.addr_eth, ETH_ADDR_LEN);
    
    eth_close(e);
	return(0);
}

static int print_intf(const struct intf_entry *entry, void *ar) {
    char *p;

    /* skip loopback */
    if (strstr(entry->intf_name, "lo") != NULL) 
        return(0);
    /* skip ppp */
    if (strstr(entry->intf_name, "ppp") != NULL) 
        return(0);
    /* skip slip */
    if (strstr(entry->intf_name, "slip") != NULL) 
        return(0);
    /* only consider numbered interfaces */
    if (entry->intf_addr.addr_type != ADDR_TYPE_IP)
        return(0);
    /* only consider up interfaces */
    if (entry->intf_flags & INTF_FLAG_UP) {
        if (DEBUG) printf("%s:\n", entry->intf_name);
        p = &intlist[intcount*INT_NAME_LEN];
        snprintf(p, INT_NAME_LEN, "%s", entry->intf_name);
        intcount++;
    }
    return(0);
}

int findInterfaces() {
    static intf_t *intf;

    if ((intf = intf_open()) == NULL) {
        printf("err: intf_open()\n");
        return(-1);
    }
    if (intf_loop(intf, print_intf, NULL) < 0) {
        printf("err: intf_loop()\n");
        return(-1);
    }
    intf_close(intf);
    return(intcount);
}

void selectInterface() {
    int i;
    int input=0;
    for (i=0;i<intcount;i++) {
        printf("IP Interface[%d]: %s\n", i, &intlist[i*INT_NAME_LEN]);
    }
    while ( (input < 48) || (input > (47 + intcount)) ) {
        printf("\nSelect Interface [0-%d]>", intcount-1);
        input = getchar();
    }
    printf("Selected Interface: [%s]\n", &intlist[(input-48)*INT_NAME_LEN]);
    intselected = input-48;
}

int registerEther() {
    memset(&eh, 0, sizeof(struct eth_hdr));
    etherOpen(&intlist[intselected*INT_NAME_LEN]);
    grabEther(&eh);
    if (DEBUG) {
        printf("registerEther()\n");
        print_eth(&eh.eth_src);
        print_eth(&eh.eth_dst);
    }
    return(0);
}

int deregisterEther() {
    memset(&eh, 0, sizeof(struct eth_hdr));
    intcount = intselected = 0;
    etherClose();
    return(0);
}

int etherSend(void *msg, int len) {
    char buf[BUFSIZE];
    int packetlen = 0;
    int ret = 0;

    packetlen = ETH_HDR_LEN + len;
    if (packetlen > BUFSIZE) 
        return(-1);

    /* RB: Unclear why I have to close and reopen each time.  Fix later */
    etherClose();
    etherOpen(&intlist[intselected*INT_NAME_LEN]);

    eh.eth_type = htons(ETH_TYPE_IP);
    memcpy(&buf[0], &eh, sizeof(struct eth_hdr));
    memcpy(&buf[ETH_HDR_LEN], msg, len);
    ip_checksum(&buf[ETH_HDR_LEN], len);
    if ((ret = eth_send(e, buf, packetlen)) != packetlen)
        printf("err: eth_send\n");

    if (DEBUG) printf("Sent %d bytes\n", ret);
    return(ret);
}

#endif


syntax highlighted by Code2HTML, v. 0.9.1