aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bus.c145
-rw-r--r--src/netnuke.c226
-rw-r--r--src/netnuke.h64
-rw-r--r--src/nukectl.c147
-rw-r--r--src/output_redirect.c81
5 files changed, 663 insertions, 0 deletions
diff --git a/src/bus.c b/src/bus.c
new file mode 100644
index 0000000..a551aa0
--- /dev/null
+++ b/src/bus.c
@@ -0,0 +1,145 @@
+/**
+ * NetNuke - Erases all storage media detected by the system
+ * Copyright (C) 2009-2010 Joseph Hunkeler <jhunkeler@gmail.com, jhunk@stsci.edu>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ **/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <glob.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <linux/fs.h>
+#include <sys/ioctl.h>
+#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/src/netnuke.c b/src/netnuke.c
new file mode 100644
index 0000000..acbbc82
--- /dev/null
+++ b/src/netnuke.c
@@ -0,0 +1,226 @@
+/**
+ * NetNuke - Erases all storage media detected by the system
+ * Copyright (C) 2009-2010 Joseph Hunkeler <jhunkeler@gmail.com, jhunk@stsci.edu>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ **/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <libgen.h> /* for basename() */
+#include <fcntl.h>
+#include <linux/fs.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <time.h>
+#include <errno.h>
+#include <ftw.h>
+#include <glob.h>
+#include <pthread.h>
+#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;
+
+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)
+ {
+ fprintf(stderr, "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();
+
+ 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/src/netnuke.h b/src/netnuke.h
new file mode 100644
index 0000000..96aac63
--- /dev/null
+++ b/src/netnuke.h
@@ -0,0 +1,64 @@
+/**
+ * NetNuke - Erases all storage media detected by the system
+ * Copyright (C) 2009-2010 Joseph Hunkeler <jhunkeler@gmail.com, jhunk@stsci.edu>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ **/
+
+#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__
+
+#define _FILE_OFFSET_BITS 64
+
+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/src/nukectl.c b/src/nukectl.c
new file mode 100644
index 0000000..8b0897b
--- /dev/null
+++ b/src/nukectl.c
@@ -0,0 +1,147 @@
+/**
+ * NetNuke - Erases all storage media detected by the system
+ * Copyright (C) 2009-2010 Joseph Hunkeler <jhunkeler@gmail.com, jhunk@stsci.edu>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ **/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <pthread.h>
+#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)
+{
+ nndevice_t* d = (nndevice_t*)device;
+ int output_progress = 0;
+ unsigned long int blocks = d->blksz * d->blks;
+ unsigned long long blocks_written = 0;
+ long double percent = 0.0L;
+
+ FILE* 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 %llu, total bytes %llu\n",
+ d->path, d->blksz, d->blks, d->sz);
+
+ srand(nngetseed());
+ while(blocks_written < blocks)
+ {
+ pthread_mutex_lock(&lock_global);
+ blocks_written += nnwrite(fp, d->blksz);
+ pthread_mutex_unlock(&lock_global);
+
+ if(output_progress >= 102400)
+ {
+ percent = (long double)((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)
+{
+ unsigned 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/src/output_redirect.c b/src/output_redirect.c
new file mode 100644
index 0000000..0537639
--- /dev/null
+++ b/src/output_redirect.c
@@ -0,0 +1,81 @@
+/**
+ * NetNuke - Erases all storage media detected by the system
+ * Copyright (C) 2009-2010 Joseph Hunkeler <jhunkeler@gmail.com, jhunk@stsci.edu>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ **/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <errno.h>
+#include <time.h>
+#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;
+}