Skip to contentSkip to conversation

updates for libctnetlink

PATCH New Pablo Neira 1 participant 1 message Mar 27, 2005 netfilter

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 updates for libctnetlink

This includes all the modifications done to libctnetlink user space library. Some comments:

o get_conntrack_handler has been killed, now ctnl_get_conntrack uses list_conntrack_handler.

o ctnl_new_conntrack now let us create and update new conntracks.

libctnetlink.c +120 -32
Index: libctnetlink.c
===================================================================
@@ -27,14 +27,12 @@
 #include <linux/netfilter_ipv4/ip_conntrack.h>
 #include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
 #include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
-#include <linux/netfilter_ipv4/ip_conntrack_icmp.h>
 #include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
 #include <linux/nfnetlink_conntrack.h>
 
 #include "libctnetlink.h"
 
-#define ctnl_error(format, args...) \
-	fprintf(stderr, "%s: " format, __FUNCTION__, ## args)
+#define ctnl_error printf
 
 /***********************************************************************
  * low level stuff 
@@ -65,11 +63,17 @@
 	int type = NFNL_MSG_TYPE(n->nlmsg_type);
 	struct ctnl_msg_handler *hdlr = cth->handler[type];
 	int ret;
+	struct nlmsgerr *msgerr;
 
 	/* end of messages reached, let's return */
 	if (n->nlmsg_type == NLMSG_DONE)
 		return -100;
 
+	if (n->nlmsg_type == NLMSG_ERROR) {
+		msgerr = NLMSG_DATA(n);
+		return msgerr->error;
+	}
+
 	if (NFNL_SUBSYS_ID(n->nlmsg_type) != NFNL_SUBSYS_CTNETLINK) {
 		ctnl_error("received message for wrong subsys, skipping\n");
 		nfnl_dump_packet(n, n->nlmsg_len, "list_conntrack_handler");
@@ -81,28 +85,16 @@
 		return 0;
 	}
 
+	if (!hdlr->handler) {
+		ctnl_error("no handler function for type %d\n", type);
+		return 0;
+	}
+
 	ret = hdlr->handler(nladdr, n, arg);
 
 	return ret;
 }
 
-/* handler used for nfnl_listen */
-static int get_conntrack_handler(struct sockaddr_nl *nladdr,
-                                  struct nlmsghdr *n, void *arg)
-{
-	struct nfgenmsg *cm = NLMSG_DATA(n);
-	struct nfattr **cb = (struct nfattr **)arg;
-
-	/* this is what we get when there's no match */
-	if (NFNL_SUBSYS_ID(n->nlmsg_type) != NFNL_SUBSYS_CTNETLINK)
-		return -1;
-        
-	nfnl_parse_attr(cb, CTA_MAX, NFM_NFA(cm), n->nlmsg_len);
-	
-	return -100; /* to get nfnl_listen to break out of the loop */
-}
-
-
 /***********************************************************************
  * high level stuff 
  ***********************************************************************/
@@ -189,42 +181,61 @@
 
 }
 
+/* TODO: Don't user list_conntrack_handler */
+int ctnl_event_conntrack(struct ctnl_handle *cth, int family)
+{
+	return nfnl_listen(&cth->nfnlh, &list_conntrack_handler, cth);
+}
+
 /**
  * ctnl_get_conntrack - get a connection from conntrack hashtable
  * cth: libctnetlink handle
  * t: tuple of connection to get
  * cb: a struct nfattr to put the connection in
  */
-int ctnl_get_conntrack(struct ctnl_handle *cth,
-		     struct ip_conntrack_tuple *t,
-		     struct nfattr **cb)
+int ctnl_get_conntrack(struct ctnl_handle *cth, 
+		       struct ip_conntrack_tuple *tuple,
+		       enum ctattr_type_t t,
+		       unsigned long id)
 {
 	struct {
 		struct nlmsghdr nlh;
 		struct nfgenmsg g;
 	} *req;
 
-	char buf[sizeof(*req) + NFA_LENGTH(sizeof(*t))];
+	char buf[sizeof(*req) + NFA_LENGTH(sizeof(*tuple))
+		 + NFA_LENGTH(sizeof(unsigned long))];
 	memset(&buf, 0, sizeof(buf));
 
 	req = (void *) &buf;
-	
+
+	if (tuple == NULL) {
+		ctnl_error("tuple must be specified\n");
+		return -1;
+	}
+
 	nfnl_fill_hdr(&cth->nfnlh, (struct nlmsghdr *) &buf,
 			0, AF_INET, CTNL_MSG_GETCONNTRACK,
 			NLM_F_REQUEST);
 
-	if (nfnl_addattr_l(&req->nlh, sizeof(buf), CTA_ORIG, t,
-			sizeof(*t)) < 0) {
+	if (nfnl_addattr_l(&req->nlh, sizeof(buf), t, tuple,
+				sizeof(*tuple)) < 0) {
 		ctnl_error("error during nfnl_addattr_l\n");
 		return -1;
 	}
+
+	if (nfnl_addattr_l(&req->nlh, sizeof(buf), CTA_ID, &id,
+			sizeof(unsigned int)) < 0) {
+		ctnl_error("error during nfnl_addattr_l\n");
+		return -1;
+	}
 	
 	if (nfnl_send(&cth->nfnlh, (struct nlmsghdr *)&buf) < 0 ) {
 		ctnl_error("error while nfnl_send\n");
 		return -1;
 	}
 
-	return nfnl_listen(&cth->nfnlh, &get_conntrack_handler, cb);
+	return nfnl_listen(&cth->nfnlh, &list_conntrack_handler, cth);
 }
 
 /**
@@ -232,32 +243,109 @@
  * cth: libctnetlink handle
  * t: tuple of to-be-deleted connection
  */
-int ctnl_del_conntrack(struct ctnl_handle *cth, struct ip_conntrack_tuple *t)
+int ctnl_del_conntrack(struct ctnl_handle *cth, 
+		       struct ip_conntrack_tuple *tuple,
+		       enum ctattr_type_t t,
+		       unsigned long id)
 {
 	struct {
 		struct nlmsghdr nlh;
 		struct nfgenmsg nfmsg;
 	} *req;
 
-	char buf[sizeof(*req) + NFA_LENGTH(sizeof(*t))];
+	char buf[sizeof(*req) + NFA_LENGTH(sizeof(*tuple))
+		 + NFA_LENGTH(sizeof(unsigned long))];
 	memset(&buf, 0, sizeof(buf));
 
 	req = (void *) &buf;
 
+	if (tuple == NULL) {
+		ctnl_error("tuple must be specified\n");
+		return -1;
+	}
+	
 	nfnl_fill_hdr(&cth->nfnlh, (struct nlmsghdr *) &buf,
 		      0, AF_INET, CTNL_MSG_DELCONNTRACK,
 		      NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST);
 
-	if (nfnl_addattr_l(&req->nlh, sizeof(buf), CTA_ORIG, t, 
-			   sizeof(*t)) < 0) {
+	if (nfnl_addattr_l(&req->nlh, sizeof(buf), t, tuple, 
+			   sizeof(*tuple)) < 0) {
 		ctnl_error("error during nfnl_addattr_l\n");
 		return -1;
 	}
 
+	if (nfnl_addattr_l(&req->nlh, sizeof(buf), CTA_ID, &id,
+			   sizeof(unsigned int)) < 0) {
+		ctnl_error("error during nfnl_addattr_l\n");
+		return -1;
+	}
+
 	return nfnl_send(&cth->nfnlh, (struct nlmsghdr *)&buf);
 }
 
 /**
+ * ctnl_new_conntrack - create a connection in the conntrack hashtable
+ * cth: libctnetlink handle
+ * t: tuple of to-be-created connection
+ */
+int ctnl_new_conntrack(struct ctnl_handle *cth,
+		       struct ip_conntrack_tuple *orig,
+		       struct ip_conntrack_tuple *reply, 
+		       unsigned long timeout, struct cta_proto *proto,
+		       unsigned int status)
+{
+	struct {
+		struct nlmsghdr nlh;
+		struct nfgenmsg nfmsg;
+	} *req;
+
+	char buf[sizeof(*req) + NFA_LENGTH(sizeof(*orig))
+		 + NFA_LENGTH(sizeof(*reply)) 
+		 + NFA_LENGTH(sizeof(unsigned long))
+		 + NFA_LENGTH(sizeof(*proto))
+		 + NFA_LENGTH(sizeof(unsigned int))];
+	memset(&buf, 0, sizeof(buf));
+
+	req = (void *) &buf;
+
+	nfnl_fill_hdr(&cth->nfnlh, (struct nlmsghdr *) &buf,
+		      0, AF_INET, CTNL_MSG_NEWCONNTRACK,
+		      NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST|NLM_F_CREATE);
+
+	if (nfnl_addattr_l(&req->nlh, sizeof(buf), CTA_ORIG, orig, 
+			   sizeof(*orig)) < 0) {
+		ctnl_error("error during nfnl_addattr_l\n");
+		return -1;
+	}
+
+	if (nfnl_addattr_l(&req->nlh, sizeof(buf), CTA_RPLY, reply, 
+			   sizeof(*reply)) < 0) {
+		ctnl_error("error during nfnl_addattr_l\n");
+		return -1;
+	}
+
+	if (nfnl_addattr_l(&req->nlh, sizeof(buf), CTA_TIMEOUT, &timeout, 
+			   sizeof(unsigned long)) < 0) {
+		ctnl_error("error during nfnl_addattr_l\n");
+		return -1;
+	}
+
+	if (nfnl_addattr_l(&req->nlh, sizeof(buf), CTA_PROTOINFO, proto, 
+			   sizeof(*proto)) < 0) {
+		ctnl_error("error during nfnl_addattr_l\n");
+		return -1;
+	}
+
+	if (nfnl_addattr_l(&req->nlh, sizeof(buf), CTA_STATUS, &status,
+			   sizeof(unsigned int)) < 0) {
+		ctnl_error("error during nfnl_addattr_l\n");
+		return -1;
+	}
+
+	return nfnl_send(&cth->nfnlh, (struct nlmsghdr *)&buf);
+}
+
+/**
  * ctnl_list_expect - retrieve a list of expectations from conntrack subsys
  * cth: libctnetlink handle
  * family: AF_INET, ...
libctnetlink.h +5 -2
Index: libctnetlink.h
===================================================================
@@ -37,9 +37,12 @@
 				 struct ctnl_msg_handler *hndlr);
 extern int ctnl_get_conntrack(struct ctnl_handle *cth,
 			      struct ip_conntrack_tuple *tuple,
-			      struct nfattr **cb);
+			      enum ctattr_type_t t,
+			      unsigned long id);
 extern int ctnl_del_conntrack(struct ctnl_handle *cth,
-			      struct ip_conntrack_tuple *t);
+			      struct ip_conntrack_tuple *tuple,
+			      enum ctattr_type_t t,
+			      unsigned long id);
 extern int ctnl_list_conntrack(struct ctnl_handle *cth, int family);
 
 extern int ctnl_list_expect(struct ctnl_handle *cth, int family);