--- linux.orig/include/linux/netfilter_ipv4/ip_queue.h 2003-10-16 01:47:01.000000000 +0200 +++ linux/include/linux/netfilter_ipv4/ip_queue.h 2003-10-16 23:53:17.000000000 +0200 @@ -47,10 +47,20 @@ unsigned char payload[0]; /* Optional replacement packet */ } ipq_verdict_msg_t; +typedef struct ipq_vwmark_msg { + unsigned int value; /* Verdict to hand to netfilter */ + unsigned long id; /* Packet ID for this verdict */ + size_t data_len; /* Length of replacement data */ + unsigned char payload[0]; /* Optional replacement packet */ + unsigned long nfmark; /* Mark for the Packet */ +} ipq_vwmark_msg_t; + + typedef struct ipq_peer_msg { union { ipq_verdict_msg_t verdict; ipq_mode_msg_t mode; + ipq_vwmark_msg_t vwmark; } msg; } ipq_peer_msg_t; @@ -67,6 +77,7 @@ #define IPQM_MODE (IPQM_BASE + 1) /* Mode request from peer */ #define IPQM_VERDICT (IPQM_BASE + 2) /* Verdict from peer */ #define IPQM_PACKET (IPQM_BASE + 3) /* Packet from kernel */ -#define IPQM_MAX (IPQM_BASE + 4) +#define IPQM_VWMARK (IPQM_BASE + 4) /* Verdict and mark from peer */ +#define IPQM_MAX (IPQM_BASE + 5) #endif /*_IP_QUEUE_H*/ --- linux.orig/net/ipv4/netfilter/ip_queue.c 2003-10-16 01:46:27.000000000 +0200 +++ linux/net/ipv4/netfilter/ip_queue.c 2003-10-16 23:54:11.000000000 +0200 @@ -417,6 +417,33 @@ } static int +ipq_set_vwmark(struct ipq_vwmark_msg *vmsg, unsigned int len) +{ + struct ipq_queue_entry *entry; + + if (vmsg->value > NF_MAX_VERDICT) + return -EINVAL; + + entry = ipq_find_dequeue_entry(id_cmp, vmsg->id); + if (entry == NULL) + return -ENOENT; + else { + int verdict = vmsg->value; + + if (vmsg->data_len && vmsg->data_len == len) + if (ipq_mangle_ipv4((ipq_verdict_msg_t *)vmsg, entry) < 0) + verdict = NF_DROP; + + /* set mark of associated skb */ + entry->skb->nfmark = vmsg->nfmark; + + ipq_issue_verdict(entry, verdict); + return 0; + } +} + + +static int ipq_receive_peer(struct ipq_peer_msg *pmsg, unsigned char type, unsigned int len) { @@ -438,6 +465,14 @@ status = ipq_set_verdict(&pmsg->msg.verdict, len - sizeof(*pmsg)); break; + case IPQM_VWMARK: + if (pmsg->msg.verdict.value > NF_MAX_VERDICT) + status = -EINVAL; + else + status = ipq_set_vwmark(&pmsg->msg.vwmark, + len - sizeof(*pmsg)); + break; + default: status = -EINVAL; }