Index: libdnet-20050421/test/dnet/dccp.c
===================================================================
--- libdnet-20050421.orig/test/dnet/dccp.c	2005-05-20 21:10:42.000000000 -0300
+++ libdnet-20050421/test/dnet/dccp.c	2005-05-23 18:31:46.000000000 -0300
@@ -22,7 +22,22 @@
 void
 dccp_usage(void)
 {
-	fprintf(stderr, "Usage: dnet dccp [sport|dport|type|seq|ack ...\n");
+	fprintf(stderr, "Usage: dnet dccp [sport|dport|type|seq|ack ...] "
+			"<option=value,value...>\n");
+	exit(1);
+}
+
+void
+dccp_option_usage(unsigned char option)
+{
+	switch (option) {
+		case DCCPO_MIN_RESERVED:
+			fprintf(stderr, "lower_reserved=[%i ... %i], "
+					"[value]\n", DCCPO_MIN_RESERVED,
+					DCCPO_MAX_RESERVED);
+		default:
+			break;
+	}
 	exit(1);
 }
 
@@ -54,19 +69,96 @@
 	return dccp_packet_names[pkt] != NULL ? pkt : -1;
 }
 
+static struct {
+	unsigned char	type;
+	char		*name;
+} dccp_options[] = {
+	{ DCCPO_PADDING, "padding" },
+	{ DCCPO_MANDATORY, "mandatory" },
+	{ DCCPO_SLOW_RECEIVER, "slow_receiver" },
+	{ DCCPO_MIN_RESERVED, "lower_reserved" },
+	{ 255,	NULL },
+};
+
+int
+dccp_add_option(char *options, char *value, int size)
+{
+	int		i,
+			retval;
+	char		*option,
+			*args;
+	unsigned char	opt_type;
+
+	args = strchr(value, '=');
+
+	/* "option" or "option=val,val,val,..." */
+	if (!args)
+		args = value + strlen(value);
+	option = (char *) malloc((args - value) + 1);
+	if (option == NULL)
+		return -1;
+	memset(option, 0, (args - value) + 1);
+	memcpy(option, value, args - value);
+
+	for (i = 0; dccp_options[i].name != NULL; i++) {
+		if (strcmp(dccp_options[i].name, option) == 0)
+			break;
+	}
+	if (dccp_options[i].name == NULL) {
+		fprintf(stderr, "Unknown option: %s\n", option);
+		retval = -1;
+		goto exit;
+	}
+
+	opt_type = dccp_options[i].type;
+	retval = 1;
+	switch (opt_type) {
+		case DCCPO_PADDING ... DCCPO_SLOW_RECEIVER:
+			options[0] = opt_type;
+			break;
+		case DCCPO_MIN_RESERVED:
+		{
+			char		t[15],
+					*v;
+			if (!args || strlen(args) == 0 || 
+			    (v = strchr(args, ',')) == NULL ||
+			    strlen(++v) == 0) {
+				dccp_option_usage(opt_type);
+				return -1;	/* just to shut up gcc */
+			}
+			memset(t, 0, sizeof(t));
+			args++;	/* eat '=' */
+			memcpy(t, args, strchr(args, ',') - args);
+			options[0] = (unsigned char)atoi(t);
+			options[1] = (unsigned char)atoi(v);
+			if (options[0] < DCCPO_MIN_RESERVED ||
+			    options[0] > DCCPO_MAX_RESERVED) {
+				dccp_option_usage(opt_type);
+			}
+		}	
+		default:
+			break;
+	}
+exit:
+	free(option);
+	return retval;
+}
+
+
 int
 dccp_main(int argc, char *argv[])
 {
 	struct dccp_hdr *dh;
 	struct dccp_hdr_ext *dhx;
 	struct dccp_hdr_ack_bits *dha;
-	u_char *p, buf[IP_LEN_MAX];	/* XXX */
+	u_char *p, buf[IP_LEN_MAX], options[IP_LEN_MAX]; /* XXX */
 	char *name, *value;
-	int c, len;
+	int c, len, options_len = 0;
 	
 	srand(time(NULL));
 
 	memset(buf, 0, sizeof(buf));
+	memset(options, 0, sizeof(options));
 	
 	dh = dccp_hdr(buf);
 	dhx = dccp_hdrx(buf);
@@ -95,11 +187,24 @@
 			if (pkt < 0)
 				dccp_usage();
 			dh->dccph_type = pkt;
+		} else if (strcmp(name, "option") == 0) {
+			int	size;
+			size = dccp_add_option(options + options_len, value,
+					    sizeof(options) - options_len);
+			if (size < 0)
+				dccp_usage();
+			options_len += size;
 		} else
 			dccp_usage();
 	}
 
-	dh->dccph_doff = dccp_hdr_len(buf) / 4;
+	if (options_len) {
+		/* options buffer was filled with 0, padding, so it's ok */
+		if (options_len % 4)
+			options_len += 4 - (options_len % 4);
+		memcpy(buf + dccp_hdr_len(buf), options, options_len);
+	}
+	dh->dccph_doff = (dccp_hdr_len(buf) + options_len) / 4;
 
 	argc -= c;
 	argv += c;
