aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoseph Hunkeler <jhunk@stsci.edu>2009-09-10 23:58:02 -0400
committerJoseph Hunkeler <jhunk@stsci.edu>2009-09-10 23:58:02 -0400
commit223298860b2ce45ee23e4b1ba60dcbe09eeb8b6b (patch)
tree5dca232c184320dd748d6e14458afe7ad25ebb6c
parentfa3bd4af5e0301ef905873cd674932b00209f74b (diff)
downloadNetNuke-223298860b2ce45ee23e4b1ba60dcbe09eeb8b6b.tar.gz
Assloads of changes
-rw-r--r--netnuke.c298
-rw-r--r--netnuke.h39
2 files changed, 223 insertions, 114 deletions
diff --git a/netnuke.c b/netnuke.c
index 19c98a9..1b7c072 100644
--- a/netnuke.c
+++ b/netnuke.c
@@ -42,13 +42,22 @@
/* Global variables */
static int64_t error;
+
+nukeLevel_t udef_nukelevel = NUKE_PATTERN; /* Static patterns is default */
bool udef_verbose = false;
+bool udef_verbose_high = false;
int8_t udef_wmode = 0; /* O_SYNC is default */
-int32_t udef_nukelevel = 1; /* Static patterns is default */
-int32_t udef_passes = 2;
+int32_t udef_passes = 1;
bool udef_testmode = true; /* Test mode should always be enabled by default. */
int32_t udef_blocksize = 512; /* 1 block = 512 bytes*/
+const char sPattern[] = {
+ 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0,
+ 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1,
+ 0xA2, 0xB2, 0xC2, 0xD2, 0xE2, 0xF2,
+ 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3
+};
+
/* List of media types that we can nuke */
#ifdef __FreeBSD__
const char* mediaList[17] = {
@@ -76,40 +85,50 @@ int32_t udef_blocksize = 512; /* 1 block = 512 bytes*/
};
#endif
-/* Prototypes */
-void fillRandom(int32_t buffer[], uint64_t length);
-int32_t nuke(const char* media, uint64_t size);
-uint64_t getSize(const char* media);
-void echoList(void);
-int humanize_number(char *buf, size_t len, int64_t bytes,
- const char *suffix, int scale, int flags);
-
-void fillRandom(int32_t buffer[], uint64_t length)
+void fillRandom(char buffer[], uint64_t length)
{
- uint32_t random, random_count;
+ uint32_t random = 0, random_count = 0;
+ int32_t linebreak = 0;
/* Initialize random seed */
srand(time(NULL) * time(NULL) / 3 + 6201985 * 3.14159);
- /* Fills the write buffer with random garbage */
- int32_t linebreak = 0;
- for(random_count = 0; random_count < length; random_count++)
+ /* Define a single static pattern */
+ if(udef_nukelevel == NUKE_PATTERN)
{
- random = rand() % RAND_MAX;
- buffer[random_count] = random;
- /*
- printf("0x%0.8X ", (char)random);
+ random = rand() % strlen(sPattern) + 1;
+ //printf("size = %d STATIC = ### %x ###\n", strlen(sPattern), (int)random);
+ buffer[random_count] = sPattern[random];
+ }
- if(linebreak == 5)
- {
- printf("\n");
- linebreak = -1;
- }
- */
- linebreak++;
+ /* Fills the write buffer with random garbage */
+ for(random_count = 0; random_count < length; random_count++)
+ {
+ if(udef_nukelevel == NUKE_RANDOM_SLOW || udef_nukelevel == NUKE_RANDOM_FAST)
+ {
+ random = rand() % RAND_MAX;
+ //printf("RANDOM = ### %x ###\n", random);
+ buffer[random_count] = random;
+ }
+
+ /* This is a debug feature to prove the random generator is functioning */
+ if(udef_verbose_high)
+ {
+ printf("0x%08X ", (char)random);
+
+ if(linebreak == 5)
+ {
+ printf("\n");
+ linebreak = -1;
+ }
+
+ linebreak++;
+ }
}
- //printf("\n");
+ if(udef_verbose_high)
+ putchar('\n');
+
}
int nuke(const char* media, uint64_t size)
@@ -120,13 +139,18 @@ int nuke(const char* media, uint64_t size)
char mediaSize[BUFSIZ];
char writeSize[BUFSIZ];
char writePerSecond[BUFSIZ];
+ int32_t pass;
uint64_t byteSize = 1024;
uint64_t times, block;
- int32_t wTable[byteSize];
+ char wTable[byteSize];
uint32_t startTime, currentTime, endTime;
int32_t retainer = 0;
- int fd = open("/dev/null", O_WRONLY | O_ASYNC);
+ /* Set the IO mode */
+ int O_UFLAG = udef_wmode ? O_ASYNC : O_SYNC;
+ //char* testflag = udef_testmode ? "/dev/null" : media;
+
+ int fd = open(media, O_WRONLY | O_UFLAG);
if(!fd)
{
perror("nuke");
@@ -136,62 +160,77 @@ int nuke(const char* media, uint64_t size)
/* Generate a size string based on the media size. example: 256M */
humanize_number(mediaSize, 5, (uint64_t)size, "",
HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
-
printf("Wiping %s: %ju (%s)\n", media, (intmax_t)size, mediaSize);
- /* Determine how many writes and at what byte size */
+
+ /* Determine how many writes to perform, and at what byte size */
times = size / byteSize;
+
/* Dump random garbage to the write table */
- fillRandom(&wTable, byteSize);
+ if(udef_nukelevel == NUKE_RANDOM_SLOW || udef_nukelevel == NUKE_RANDOM_FAST)
+ fillRandom(wTable, byteSize);
+ else if(udef_nukelevel == NUKE_ZERO)
+ memset(wTable, 0, byteSize);
+ else
+ staticPattern(wTable, byteSize);
- startTime = time(NULL);
- for( block = 0 ; block <= times ; block++)
- {
- currentTime = time(NULL);
- long double bytes = (float)(size / times * block);
- error = write(fd, (char*)wTable, sizeof(wTable));
-
- switch(error)
- {
- case EIO:
- {
- int64_t blockPosition = (int64_t)lseek(fd, -1, SEEK_CUR);
- printf("I/O Error: Unable to write to block \"%jd\"\n", blockPosition);
- }
- break;
-
- default:
- break;
- };
-
- /* Generate a size string based on bytes written. example: 256M */
- humanize_number(writeSize, 5,
- bytes, "", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
-
- /* Generate a size string based on writes per second. example: 256M */
- humanize_number(writePerSecond, 5,
- (intmax_t)((long double)bytes / ((long double)currentTime - (long double)startTime)), "",
- HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
-
- /* Save I/O by printing our progress every X iterations with a retainer*/
- if(retainer > 128 || block == times)
- {
- /* Output our progress */
- printf("\t%jd of %jd blocks [ %s / %3.1Lf%% / %s/s ]\r",
- block,
- times,
- writeSize,
- (bytes / (long double)size) * 100L,
- writePerSecond
- );
- retainer = -1;
-
- /* Recycle the write table with random garbage */
- fillRandom(&wTable, byteSize);
- }
- ++retainer;
- }
- endTime = time(NULL);
+ for( pass = 1; pass <= udef_passes ; pass++ )
+ {
+ startTime = time(NULL);
+ for( block = 0 ; block <= times ; block++)
+ {
+ currentTime = time(NULL);
+ long double bytes = (float)(size / times * block);
+
+ error = write(fd, (char*)wTable, sizeof(wTable));
+
+ switch(error)
+ {
+ case EIO:
+ {
+ int64_t blockPosition = (int64_t)lseek(fd, -1, SEEK_CUR);
+ printf("I/O Error: Unable to write to block \"%jd\"\n", blockPosition);
+ }
+ break;
+
+ default:
+ break;
+ };
+
+ /* Generate a size string based on bytes written. example: 256M */
+ humanize_number(writeSize, 5,
+ bytes, "", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
+
+ /* Generate a size string based on writes per second. example: 256M */
+ humanize_number(writePerSecond, 5,
+ (intmax_t)((long double)bytes / ((long double)currentTime - (long double)startTime)), "",
+ HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
+
+ /* Save I/O by printing our progress every X iterations with a retainer*/
+ if(retainer > RETAINER || block == times)
+ {
+ if(udef_passes > 1)
+ printf("pass %d ", pass);
+
+ /* Output our progress */
+ printf("\t%jd of %jd blocks [ %s / %3.1Lf%% / %s/s ]\r",
+ block,
+ times,
+ writeSize,
+ (bytes / (long double)size) * 100L,
+ writePerSecond
+ );
+ retainer = -1;
+
+ /* Recycle the write table with random garbage */
+ if(udef_nukelevel == NUKE_RANDOM_SLOW)
+ fillRandom(wTable, byteSize);
+ }
+
+ ++retainer;
+ } /* BLOCK WRITE */
+ endTime = time(NULL);
+ } /* PASSES */
putchar('\n');
close(fd);
@@ -219,6 +258,9 @@ void echoList()
sprintf(media, "/dev/%s%c", mediaList[mt], 'a' + i);
#endif
+ if(udef_testmode)
+ sprintf(media, "/dev/null");
+
/* Set media size */
size = getSize(media);
@@ -292,8 +334,7 @@ uint64_t getSize(const char* media)
void usage(const char* cmd)
{
- putchar('\n');
- printf("usage: %s\n", cmd);
+ printf("usage: %s [options] ...\n", cmd);
printf("--help -h This message\n");
printf("--write-mode s -w s Valid values:\n\
0: Synchronous (default)\n\
@@ -302,12 +343,13 @@ void usage(const char* cmd)
0: Zero out (quick wipe)\n\
1: Static patterns (0xA, 0xB, ...)\n\
2: Fast random (single random buffer across media)\n\
- 3: Slow random (generate random buffer every 128 blocks)\n\
+ 3: Slow random (regenerate random buffer)\n\
4: Ultra-slow re-writing method\n");
printf("--passes n -p n Number of wipes to perform on a single device\n");
printf("--disable-test Disables test-mode, and allows write operations\n");
printf("--block-size n -b n Blocks at once\n");
printf("--verbose -v\n");
+ printf("--verbose-high -v Debug level verbosity\n");
printf("--version -V\n");
putchar('\n');
}
@@ -326,32 +368,11 @@ void version(const char* cmd)
printf("That source code (from libutil) is licensed under the BSD software license.\n\n");
}
-#define ARGMATCH(arg) strncmp(argv[tok], arg, strlen(arg)) == 0
-#define ARGNULL(arg) if(argv[tok arg] == NULL) exit(1);
-#define ARGVALINT(ref) tok++; ref = atoi(argv[tok])
-#define ARGVALSTR(ref) tok++; ref = argv[tok];
-
-#define NOZERO 0
-#define NONEGATIVE 2
-#define NEEDNUM 4
-#define NEEDSTR 8
int filterArg(const char* key, char* value, short flags)
{
int test;
int length = strlen(value);
- if((flags & NEEDNUM) > 0)
- {
- for(test = 0; test < length; test++)
- {
- if(!isdigit(value[test]))
- {
- printf("argument %s did not receive an integer\n", key);
- exit(1);
- }
- }
- }
-
if((flags & NONEGATIVE) > 0)
{
if((atoi(value) < 0))
@@ -371,6 +392,18 @@ int filterArg(const char* key, char* value, short flags)
}
+ if((flags & NEEDNUM) > 0)
+ {
+ for(test = 0; test < length; test++)
+ {
+ if(!isdigit(value[test]))
+ {
+ printf("argument %s did not receive an integer\n", key);
+ exit(1);
+ }
+ }
+ }
+
return 0;
}
@@ -395,7 +428,11 @@ int main(int argc, char* argv[])
{
udef_verbose = true;
}
-
+ if(ARGMATCH("--verbose-high") || ARGMATCH("-vv"))
+ {
+ udef_verbose_high = true;
+ udef_verbose = true;
+ }
}
/* Dynamic arguments come second */
@@ -407,23 +444,52 @@ int main(int argc, char* argv[])
ARGNULL(+1);
if(filterArg(argv[tok], argv[tok+1], NONEGATIVE|NEEDNUM) == 0)
{
- ARGVALINT(udef_wmode);
+ ARGVALINT(udef_wmode);
}
if(udef_verbose)
- printf("write mode is %d\n", udef_wmode);
+ printf("Write mode: %cSYNC\n", udef_wmode ? 'A' : 0);
}
if(ARGMATCH("--nuke-level") || ARGMATCH("-n"))
{
ARGNULL(+1);
if(filterArg(argv[tok-1], argv[tok+1], NONEGATIVE|NEEDNUM) == 0)
{
- ARGVALINT(udef_nukelevel);
- }
-
+ ARGVALINT(udef_nukelevel);
+ if(udef_nukelevel > NUKE_REWRITE)
+ udef_nukelevel = NUKE_PATTERN;
+ }
+ /* TODO: Remove this when it is implemented! */
+ if(udef_nukelevel == NUKE_REWRITE)
+ {
+ printf("*** Rewrite mode is not implemented, using default.\n");
+ udef_nukelevel = NUKE_PATTERN;
+ }
+
if(udef_verbose)
- printf("nuke level is %d\n", udef_nukelevel);
-
+ {
+ char* nlstr = {0};
+ switch(udef_nukelevel)
+ {
+ case NUKE_ZERO:
+ nlstr = "Zeroing";
+ break;
+ case NUKE_PATTERN:
+ nlstr = "Pattern";
+ break;
+ case NUKE_RANDOM_SLOW:
+ nlstr = "Slow Random";
+ break;
+ case NUKE_RANDOM_FAST:
+ nlstr = "Fast Random";
+ break;
+ default:
+ nlstr = "Unknown";
+ break;
+ }
+
+ printf("Wipe method: %s\n", nlstr);
+ }
}
if(ARGMATCH("--passes") || ARGMATCH("-p"))
{
@@ -436,7 +502,7 @@ int main(int argc, char* argv[])
}
if(udef_verbose)
- printf("passes is %u\n", udef_passes);
+ printf("Pass #: %u\n", udef_passes);
}
if(ARGMATCH("--disable-test"))
@@ -455,7 +521,7 @@ int main(int argc, char* argv[])
}
if(udef_verbose)
- printf("block size is %d\n", udef_blocksize);
+ printf("Block size: %d\n", udef_blocksize);
}
if(argv[tok+1] == NULL)
@@ -484,6 +550,10 @@ int main(int argc, char* argv[])
#else
sprintf(media, "/dev/%s%c", mediaList[mt], 'a' + i);
#endif
+
+ if(udef_testmode)
+ sprintf(media, "/dev/null");
+
/* Set media size */
size = getSize(media);
diff --git a/netnuke.h b/netnuke.h
index 4bd26f7..9147beb 100644
--- a/netnuke.h
+++ b/netnuke.h
@@ -1,6 +1,20 @@
#ifndef NETNUKE_H
#define NETNUKE_H
+/* Prototypes */
+void fillRandom(char buffer[], uint64_t length);
+void staticPattern() __attribute__((alias("fillRandom")));
+int32_t nuke(const char* media, uint64_t size);
+uint64_t getSize(const char* media);
+void echoList(void);
+void usage(const char* cmd);
+void version(const char* cmd);
+#ifndef __FreeBSD__
+int humanize_number(char *buf, size_t len, int64_t bytes,
+ const char *suffix, int scale, int flags);
+#endif
+
+/* Defines */
#define NETNUKE_VERSION_MAJOR 1
#define NETNUKE_VERSION_MINOR 0
#ifdef _SVN_SUPPORT
@@ -24,5 +38,30 @@
You should have received a copy of the GNU General Public License\n\
along with this program. If not, see <http://www.gnu.org/licenses/>."
+/* Output update speed based on writes */
+#define RETAINER 512
+
+/* Used to assist argument parsing */
+#define ARGMATCH(arg) strncmp(argv[tok], arg, strlen(arg)) == 0
+#define ARGNULL(arg) if(argv[tok arg] == NULL) exit(1);
+#define ARGVALINT(ref) tok++; ref = atoi(argv[tok])
+#define ARGVALSTR(ref) tok++; ref = argv[tok];
+
+/* Flags for filterArgs */
+#define NOZERO 0
+#define NONEGATIVE 2
+#define NEEDNUM 4
+#define NEEDSTR 8
+
+/* Enumerated lists */
+typedef enum nlevel
+{
+ NUKE_ZERO=0,
+ NUKE_PATTERN,
+ NUKE_RANDOM_FAST,
+ NUKE_RANDOM_SLOW,
+ NUKE_REWRITE
+} nukeLevel_t;
+
#endif /* NETNUKE_H */