DEV: udp: add support for random packet corruption

-c sets a corruption rate in % of the packets.
-o sets the start offset of the area to be corrupted.
-w sets the length of the area to be corrupted.

A single byte within that area will then be randomly XORed with a
random value.
diff --git a/dev/udp/udp-perturb.c b/dev/udp/udp-perturb.c
index 3df0f79..098e61c 100644
--- a/dev/udp/udp-perturb.c
+++ b/dev/udp/udp-perturb.c
@@ -77,6 +77,9 @@
 } history[MAXREORDER];
 int history_idx = 0;
 unsigned int rand_rate = 0;
+unsigned int corr_rate = 0;
+unsigned int corr_span = 1;
+unsigned int corr_base = 0;
 
 struct conn conns[MAXCONN];        // sole connection for now
 int fd_frt;
@@ -319,6 +322,14 @@
 	if (ret < 0)
 		return errno == EAGAIN ? 0 : -1;
 
+	if (corr_rate > 0 && prng(100) < corr_rate) {
+		unsigned int rnd = prng(corr_span * 256); // pos and value
+		unsigned int pos = corr_base + (rnd >> 8);
+
+		if (pos < ret)
+			pktbuf[pos] ^= rnd;
+	}
+
 	conn = NULL;
 	for (i = 0; i < nbconn; i++) {
 		if (addr.ss_family != conns[i].cli_addr.ss_family)
@@ -421,6 +432,9 @@
 	    "  -h           display this help\n"
 	    "  -r rate      reorder/duplicate/lose around <rate>%% of packets\n"
 	    "  -s seed      force initial random seed (currently %#x)\n"
+	    "  -c rate      corrupt around <rate>%% of packets\n"
+	    "  -o ofs       start offset of corrupted area (def: 0)\n"
+	    "  -w width     width of the corrupted area (def: 1)\n"
 	    "", name, prng_state);
 }
 
@@ -435,7 +449,7 @@
 	err.size = 100;
 	err.msg = malloc(err.size);
 
-	while ((opt = getopt(argc, argv, "hr:s:")) != -1) {
+	while ((opt = getopt(argc, argv, "hr:s:c:o:w:")) != -1) {
 		switch (opt) {
 		case 'r': // rand_rate%
 			rand_rate = atoi(optarg);
@@ -443,6 +457,15 @@
 		case 's': // seed
 			prng_state = atol(optarg);
 			break;
+		case 'c': // corruption rate
+			corr_rate = atol(optarg);
+			break;
+		case 'o': // corruption offset
+			corr_base = atol(optarg);
+			break;
+		case 'w': // corruption width
+			corr_span = atol(optarg);
+			break;
 		default: // help, anything else
 			usage(0, argv[0]);
 		}