From 1e0dccae06eee40d62f8e80a22f3ff29a6f22449 Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Tue, 30 Nov 2010 09:26:07 -0500 Subject: Initial commit --- Makefile | 13 +++ bus.c | 145 +++++++++++++++++++++++++++++++++ netnuke.c | 239 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ netnuke.h | 62 ++++++++++++++ nukectl.c | 160 ++++++++++++++++++++++++++++++++++++ output_redirect.c | 81 ++++++++++++++++++ 6 files changed, 700 insertions(+) create mode 100644 Makefile create mode 100644 bus.c create mode 100644 netnuke.c create mode 100644 netnuke.h create mode 100644 nukectl.c create mode 100644 output_redirect.c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..af12fca --- /dev/null +++ b/Makefile @@ -0,0 +1,13 @@ +CFLAGS=-Wall -O2 -s +LDFLAGS=-lpthread +OBJS= \ + bus.c \ + netnuke.c \ + nukectl.c \ + output_redirect.c + +all: + cc ${CFLAGS} ${LDFLAGS} -o netnuke ${OBJS} + du -sh netnuke +clean: + rm -rf netnuke diff --git a/bus.c b/bus.c new file mode 100644 index 0000000..a551aa0 --- /dev/null +++ b/bus.c @@ -0,0 +1,145 @@ +/** + * NetNuke - Erases all storage media detected by the system + * Copyright (C) 2009-2010 Joseph Hunkeler + * + * This file is part of NetNuke. + * + * NetNuke 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 3 of the License, or + * (at your option) any later version. + * + * NetNuke 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 NetNuke. If not, see . + **/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "netnuke.h" + +extern char* scsi_device_glob[]; +extern char* ide_device_glob[]; + +int scanbus(nndevice_t** device, int mask) +{ + int fd = -1; + int i = 0; + unsigned int j = 0; + int blocksize = 512; + unsigned long blocks = 0; + unsigned long size = 0; + + + if(mask & BUS_SCSI) + { + for( i = 0 ; scsi_device_glob[i] != NULL ; i++ ) + { + glob_t entries; + if(glob(scsi_device_glob[i], 0, NULL, &entries) == 0) + { + for( j = 0 ; j < entries.gl_pathc ; j++ ) + { + fd = open(entries.gl_pathv[j], O_RDONLY | O_NONBLOCK); + if(fd >= 0) + { + if((ioctl(fd, BLKGETSIZE, &blocks)) == 0) + { + device[j] = (nndevice_t*)malloc(sizeof(nndevice_t)); + if(device[j] == NULL) + { + perror("device"); + exit(1); + } + COM(self, "device[%d] = %d\n", j, sizeof(nndevice_t)); + size = blocks * blocksize; + + strncpy(device[j]->path, entries.gl_pathv[j], sizeof(device[j]->path)); + device[j]->blks = blocks; + device[j]->sz = size; + device[j]->blksz = 512; + + printf("%s ", device[j]->path); + printf("%llu %llu %.2f\n", device[j]->blks, device[j]->sz, (double)device[j]->sz / (1024 * 1024 * 1024)); + + } + close(fd); + } + } + globfree(&entries); + } + } + + } + + if(mask & BUS_IDE) + { + for( i = 0 ; ide_device_glob[i] != NULL ; i++ ) + { + glob_t entries; + if(glob(ide_device_glob[i], 0, NULL, &entries) == 0) + { + for( j = 0 ; j < entries.gl_pathc ; j++ ) + { + fd = open(entries.gl_pathv[j], O_RDONLY | O_NONBLOCK); + if(fd >= 0) + { + + if((ioctl(fd, BLKGETSIZE, &blocks)) == 0) + { + size = blocks * blocksize; + printf("%s ", entries.gl_pathv[j]); + printf("%lu %lu %.2f\n", blocks, size, (double)size / (1024 * 1024 * 1024)); + } + close(fd); + } + } + globfree(&entries); + } + } + } + + return 0; +} + +int selectbus(char** flags) +{ + int mask = 0; + int i = 0; + + if(flags == NULL) + { + return (mask = BUS_BOTH); + } + + mask = 0; + while(flags[i] != NULL) + { + if(!strcmp(flags[i], "ide")) + { + mask |= BUS_IDE; + printf("IDE (0x%02X)\n", mask); + } + + if(!strcmp(flags[i], "scsi")) + { + mask |= BUS_SCSI; + printf("SCSI (0x%02X)\n", mask); + } + + i++; + } + + return mask; +} + diff --git a/netnuke.c b/netnuke.c new file mode 100644 index 0000000..1c82fd8 --- /dev/null +++ b/netnuke.c @@ -0,0 +1,239 @@ +/** + * NetNuke - Erases all storage media detected by the system + * Copyright (C) 2009-2010 Joseph Hunkeler + * + * This file is part of NetNuke. + * + * NetNuke 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 3 of the License, or + * (at your option) any later version. + * + * NetNuke 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 NetNuke. If not, see . + **/ + +#include +#include +#include +#include +#include /* for basename() */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "netnuke.h" + +pthread_mutex_t lock_global = PTHREAD_MUTEX_INITIALIZER; +pthread_mutex_t lock_write = PTHREAD_MUTEX_INITIALIZER; +extern unsigned long total_written_bytes; +int verbose_flag = 0; +int bus_mask = 0; +int device_timeout = 0; +char** bus_flags = NULL; +/* +struct tm *logtm; +time_t logtime; +char timestr[64]; +*/ +static struct option long_options[] = +{ + {"help", no_argument, 0, 0}, + {"verbose", no_argument, &verbose_flag, 1}, + {"quiet", no_argument, &verbose_flag, 0}, + {"ignore-first", no_argument, 0, 'i'}, + {"timeout", required_argument, 0, 't'}, + {"scheme", required_argument, 0, 's'}, + {"device-type", required_argument, 0, 'd'}, + {NULL, 0, 0, 0} +}; + +static char* long_options_help[] = +{ + "\tThis message", + "More output", + "Suppress output", + "Ignore first device", + "Set timeout-to-failure (in seconds)", + "Set nuking scheme:\n\ + 0 = zero\n\ + 1 = static pattern\n\ + 2 = pure random", + "Select bus:\n\ + ide\n\ + scsi", + NULL +}; + +char *scsi_device_glob[] = +{ + "/dev/sd*[!0-9]", + "/dev/nsr*", + "/dev/tape*", + NULL +}; + +char *ide_device_glob[] = +{ + "/dev/hd*[!0-9]", + NULL +}; + + +void usage(const char* progname) +{ + int i; + printf("%s v%d.%d %s %s\n", progname, VERSION_MAJOR, VERSION_MINOR, LICENSE, AUTHOR); + printf("usage: %s ", progname); + for( i = 0 ; long_options[i].name != NULL ; i++ ) + { + if(!long_options[i].has_arg) + { + if(strncasecmp("help", long_options[i].name, strlen(long_options[i].name)) != 0) + printf("[--%s] ", long_options[i].name); + } + + if(long_options[i].has_arg) + printf("[-%c val] ", (char)long_options[i].val); + } + putchar('\n'); + + for( i = 0 ; long_options[i].name != NULL ; i++) + { + printf(" --%s\t", long_options[i].name); + if(long_options[i].has_arg) + { + printf("-%c\t", (char)long_options[i].val); + } + else + { + printf("\t"); + } + printf("%s\n", long_options_help[i]); + } + exit(0); +} + +int main(int argc, char* argv[]) +{ + if((nnlogcleanup()) != 0) + { + printf("Failed to cleanup %s: %s\n", NNLOGFILE, strerror(errno)); + } + COM(self, "Program start\n"); + + if(argc < 2) usage(basename(argv[0])); + int c; + int option_index = 0; + + while((c = getopt_long (argc, argv, "is:d:t:", long_options, &option_index)) > 0) + { + switch (c) + { + case 0: + { + if (long_options[option_index].flag != 0) break; + printf ("option %s", long_options[option_index].name); + if (optarg) printf (" with arg %s", optarg); + printf ("\n"); + break; + } + case 's': + { + break; + } + case 't': + { + device_timeout = atoi(optarg); + COM(self, "%ds timeout set\n", device_timeout); + break; + } + case 'd': + { + int i = 0; + char* tok = strtok(optarg, ","); + bus_flags = (char**)malloc(1024); + while(tok !=NULL) + { + bus_flags[i] = (char*)malloc(strlen(tok)); + strncpy(bus_flags[i], tok, strlen(tok)); + i++; + tok = strtok(NULL, ","); + } + break; + } + case 'h': + case ':': + case '?': + usage(basename(argv[0])); + break; + } + } + + if (optind < argc) + { + printf ("non-option ARGV-elements: "); + while (optind < argc) + printf ("%s ", argv[optind++]); + putchar ('\n'); + } + + nndevice_t** device; + device = (nndevice_t**)malloc(MAXTHREAD * sizeof(nndevice_t)); + if(device == NULL) + { + perror("device list"); + exit(1); + } + pthread_t thread[MAXTHREAD]; + int thread_count = 0; + int i; + + bus_mask = selectbus(bus_flags); + scanbus(device, bus_mask); + nnrandinit(); + +/* + nndevice_t device[] = { + {"./test", 512,20468,1048000}, + {"./test1",512,20468,1048000}, + {"./test2",512,20468,1048000}, + {"./test3",512,20468,1048000}, + {0,0,0,0} + }; +*/ + COM(self, "Initializing mutex\n"); + pthread_mutex_init(&lock_global, NULL); + + COM(self, "Generating threads\n"); + for( i = 0 ; device[i] != NULL ; i++ ) + { + printf("%d\n", i); + thread[i] = (pthread_t)nnthread(device[i]); + COM(self, "thread id: %ld\n", thread[i]); + } + + COM(self, "Joining all threads\n"); + thread_count = i; + for( i = 0 ; i < thread_count ; i++ ) + { + pthread_join(thread[i], NULL); + } + + COM(self, "Destroying mutex\n"); + pthread_mutex_destroy(&lock_global); + + COM(self, "Total bytes written: %lu\n", total_written_bytes); + nnrandfree(); + return 0; +} diff --git a/netnuke.h b/netnuke.h new file mode 100644 index 0000000..9e606cb --- /dev/null +++ b/netnuke.h @@ -0,0 +1,62 @@ +/** + * NetNuke - Erases all storage media detected by the system + * Copyright (C) 2009-2010 Joseph Hunkeler + * + * This file is part of NetNuke. + * + * NetNuke 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 3 of the License, or + * (at your option) any later version. + * + * NetNuke 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 NetNuke. If not, see . + **/ + +#ifndef NETNUKE_H +#define NETNUKE_H + +#define AUTHOR "Joseph Hunkeler" +#define LICENSE "GPLv3" +#define VERSION_MAJOR 2 +#define VERSION_MINOR 0 + +#define BUS_SCSI 0x02 +#define BUS_IDE 0x04 +#define BUS_BOTH (BUS_SCSI | BUS_IDE) +#define MAXLINE 512 +#define MAXTHREAD 255 + +#define NNLOGFILE "netnuke.log" +#define self __FUNCTION__ + +typedef struct nndevice_t +{ + char path[50]; + unsigned int blksz; + unsigned long long blks; + unsigned long long sz; +} nndevice_t; + +int nnlogcleanup(); +int COM(const char* func, char *format, ...); +void* wipe(void* device); +pthread_t nnthread(nndevice_t* device); +int nnwrite(FILE* fp, int bsize); +void nnrandinit(); +void nnrandfree(); +unsigned int nngetseed(); +unsigned int nnrand(int min, int max); +char* randstr(int size); +int scanbus(nndevice_t** device,int mask); +void showbus(int mask); +int selectbus(char** flags); +void usage(const char* progname); + + +#endif //NETNUKE_H diff --git a/nukectl.c b/nukectl.c new file mode 100644 index 0000000..4613997 --- /dev/null +++ b/nukectl.c @@ -0,0 +1,160 @@ +/** + * NetNuke - Erases all storage media detected by the system + * Copyright (C) 2009-2010 Joseph Hunkeler + * + * This file is part of NetNuke. + * + * NetNuke 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 3 of the License, or + * (at your option) any later version. + * + * NetNuke 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 NetNuke. If not, see . + **/ + +#include +#include +#include +#include +#include +#include +#include "netnuke.h" + +FILE* randfp; +unsigned int randseed; +unsigned long long total_written_bytes; +extern pthread_mutex_t lock_global; +extern pthread_mutex_t lock_write; + +void* wipe(void* device) +{ + srand(nngetseed()); + char buf = '\0'; + nndevice_t* d = (nndevice_t*)device; + FILE* fp; + FILE* fptmp = fopen(d->path, "w+t"); + if(fptmp == NULL) + { + COM(self, "Unable to open %s: %s\n", d->path, strerror(errno)); + return (int*)1; + } + fseek(fptmp, d->sz, SEEK_CUR); + fwrite(&buf, sizeof(char), 1, fptmp); + fclose(fptmp); + + fp = NULL; + fp = fopen(d->path, "w+t"); + if(fp == NULL) + { + COM(self, "Unable to open %s: %s\n", d->path, strerror(errno)); + return (int*)1; + } + COM(self, "path: %s, block size %d, blocks %lu, total bytes %lu\n", + d->path, d->blksz, d->blks, d->sz); + + int output_progress = 0; + unsigned int blocks = d->blksz * d->blks; + unsigned long long blocks_written = 0; + while(blocks_written < blocks) + { + pthread_mutex_lock(&lock_global); + blocks_written += nnwrite(fp, d->blksz); + pthread_mutex_unlock(&lock_global); + + + if(output_progress >= 102400) + { + long double percent = (blocks_written / (long double)d->sz) * 100; + printf("%s: %llu of %llu (%0.2Lf%%)\n", d->path, blocks_written, d->sz, percent); + output_progress = 0; + } + + ++output_progress; + } + COM(self, "%s complete\n", d->path); + pthread_exit(NULL); + + return NULL; +} + +pthread_t nnthread(nndevice_t* device) +{ + pthread_t thread; + if((pthread_create(&thread, NULL, wipe, device)) != 0) + { + COM(self, "Failed to create thread %lu\n", thread); + return 1; + } + + return thread; +} + +int nnwrite(FILE* fp, int bsize) +{ + int bytes_written = 0; + char* buffer = randstr(bsize); + pthread_mutex_lock(&lock_write); + //bytes_written = fwrite(buffer, sizeof(char), bsize, fp); + bytes_written += bsize; //temporary testing + total_written_bytes += bytes_written; + pthread_mutex_unlock(&lock_write); + + free(buffer); + return bytes_written; +} + +void nnrandinit() +{ + COM(self, "Initializing random seed\n"); + randfp = fopen("/dev/urandom", "r"); + if(randfp == NULL) + { + COM(self, "urandom: %s\n", strerror(errno)); + return; + } + srand(nngetseed()); +} + +void nnrandfree() +{ + COM(self, "Closing urandom\n"); + fclose(randfp); +} + +unsigned int nngetseed() +{ + if((fread(&randseed, 1, sizeof(int), randfp)) > 0) + { + COM(self, "(urandom) Seed is %lu\n", randseed); + return randseed; + } + + unsigned int t = time(NULL); + COM(self, "(UNIX Epoch) Seed is %lu\n", t); + return t; +} + +unsigned int nnrand(int min, int max) +{ + return rand()%(min + max); +} + +char* randstr(int size) +{ + char* buffer = (char*)malloc(sizeof(char) * size + 1); + unsigned char c; + int i; + for( i = 0 ; i < size ; i++ ) + { + c = nnrand(1, 256); + buffer[i] = c; + } + + return buffer; +} diff --git a/output_redirect.c b/output_redirect.c new file mode 100644 index 0000000..0537639 --- /dev/null +++ b/output_redirect.c @@ -0,0 +1,81 @@ +/** + * NetNuke - Erases all storage media detected by the system + * Copyright (C) 2009-2010 Joseph Hunkeler + * + * This file is part of NetNuke. + * + * NetNuke 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 3 of the License, or + * (at your option) any later version. + * + * NetNuke 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 NetNuke. If not, see . + **/ + +#include +#include +#include +#include +#include +#include +#include +#include "netnuke.h" + +extern int verbose_flag; + +int nnlogcleanup() +{ + int status = 0; + if((access(NNLOGFILE, W_OK)) == 0) + { + status = unlink(NNLOGFILE); + } + + return status; +} + +int COM(const char* func, char *format, ...) +{ + struct tm *logtm; + time_t logtime = time(NULL); + char timestr[64]; + char *str = (char*)malloc(sizeof(char) * 256); + char tmpstr[255]; + int n; + + /*FILE *logfp = fopen(NNLOGFILE, "a+"); + if(logfp == NULL) + { + COM(self, "Unable to open %s\n", NNLOGFILE); + verbose_flag = 1; + }*/ + va_list args; + va_start (args, format); + n = vsprintf (str, format, args); + va_end (args); + + logtm = localtime(&logtime); + snprintf(timestr, sizeof(timestr), "%02d-%02d-%02d %02d:%02d:%02d", logtm->tm_year+1900, logtm->tm_mon+1, logtm->tm_mday, logtm->tm_hour, logtm->tm_min, logtm->tm_sec); + snprintf(tmpstr, sizeof(tmpstr), "%s _%s_: %s", timestr, func, str); + + if(verbose_flag) + { + fprintf(stdout, "%s", tmpstr); + //fprintf(logfp, "%s", tmpstr); + } + else + { + /*fprintf(logfp, "%s", tmpstr);*/ + } + + free(str); + /*fclose(logfp);*/ + + return 0; +} -- cgit