- Fix memory leak in TC_COMMIT()  (Markus Sundberg)
- Cleanup error path of TC_COMMIT()
- Correctly propagate errors of setsockopt to calling function
diff --git a/libiptc/libiptc.c b/libiptc/libiptc.c
index 452ac13..3538cca 100644
--- a/libiptc/libiptc.c
+++ b/libiptc/libiptc.c
@@ -2034,13 +2034,13 @@
 	new_number = iptcc_compile_table_prep(*handle, &new_size);
 	if (new_number < 0) {
 		errno = ENOMEM;
-		return 0;
+		goto out_zero;
 	}
 
 	repl = malloc(sizeof(*repl) + new_size);
 	if (!repl) {
 		errno = ENOMEM;
-		return 0;
+		goto out_zero;
 	}
 	memset(repl, 0, sizeof(*repl) + new_size);
 
@@ -2055,17 +2055,14 @@
 	repl->counters = malloc(sizeof(STRUCT_COUNTERS)
 				* (*handle)->info.num_entries);
 	if (!repl->counters) {
-		free(repl);
 		errno = ENOMEM;
-		return 0;
+		goto out_free_repl;
 	}
 	/* These are the counters we're going to put back, later. */
 	newcounters = malloc(counterlen);
 	if (!newcounters) {
-		free(repl->counters);
-		free(repl);
 		errno = ENOMEM;
-		return 0;
+		goto out_free_repl_counters;
 	}
 	memset(newcounters, 0, counterlen);
 
@@ -2082,9 +2079,7 @@
 	ret = iptcc_compile_table(*handle, repl);
 	if (ret < 0) {
 		errno = ret;
-		free(repl->counters);
-		free(repl);
-		return 0;
+		goto out_free_newcounters;
 	}
 
 
@@ -2099,12 +2094,11 @@
 	}
 #endif
 
-	if (setsockopt(sockfd, TC_IPPROTO, SO_SET_REPLACE, repl,
-		       sizeof(*repl) + repl->size) < 0) {
-		free(repl->counters);
-		free(repl);
-		free(newcounters);
-		return 0;
+	ret = setsockopt(sockfd, TC_IPPROTO, SO_SET_REPLACE, repl,
+			 sizeof(*repl) + repl->size);
+	if (ret < 0) {
+		errno = ret;
+		goto out_free_newcounters;
 	}
 
 	/* Put counters back. */
@@ -2194,21 +2188,29 @@
 	}
 #endif
 
-	if (setsockopt(sockfd, TC_IPPROTO, SO_SET_ADD_COUNTERS,
-		       newcounters, counterlen) < 0) {
-		free(repl->counters);
-		free(repl);
-		free(newcounters);
-		return 0;
+	ret = setsockopt(sockfd, TC_IPPROTO, SO_SET_ADD_COUNTERS,
+			 newcounters, counterlen);
+	if (ret < 0) {
+		errno = ret;
+		goto out_free_newcounters;
 	}
 
 	free(repl->counters);
 	free(repl);
 	free(newcounters);
 
- finished:
+finished:
 	TC_FREE(handle);
 	return 1;
+
+out_free_newcounters:
+	free(newcounters);
+out_free_repl_counters:
+	free(repl->counters);
+out_free_repl:
+	free(repl);
+out_zero:
+	return 0;
 }
 
 /* Get raw socket. */