1diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linuxppc-020802-newnat/net/ipv4/netfilter/nfnetlink.c linuxppc-020802-newnat14-ctnl/net/ipv4/netfilter/nfnetlink.c
2--- linuxppc-020802-newnat/net/ipv4/netfilter/nfnetlink.c	Thu Jan  1 01:00:00 1970
3+++ linuxppc-020802-newnat14-ctnl/net/ipv4/netfilter/nfnetlink.c	Fri Aug  2 16:35:39 2002
4@@ -0,0 +1,344 @@
5+/* Netfilter messages via netlink socket. Allows for user space
6+ * protocol helpers and general trouble making from userspace.
7+ *
8+ * (C) 2001 by Jay Schulist <jschlst@samba.org>,
9+ * (C) 2002 by Harald Welte <laforge@gnumonks.org>
10+ *
11+ * Initial netfilter messages via netlink development funded and
12+ * generally made possible by Network Robots, Inc. (www.networkrobots.com)
13+ *
14+ * Further development of this code funded by Astaro AG (http://www.astaro.com)
15+ *
16+ * This software may be used and distributed according to the terms
17+ * of the GNU General Public License, incorporated herein by reference.
18+ */
19+
20+#include <linux/config.h>
21+#include <linux/module.h>
22+#include <linux/types.h>
23+#include <linux/socket.h>
24+#include <linux/kernel.h>
25+#include <linux/major.h>
26+#include <linux/sched.h>
27+#include <linux/timer.h>
28+#include <linux/string.h>
29+#include <linux/sockios.h>
30+#include <linux/net.h>
31+#include <linux/fcntl.h>
32+#include <linux/skbuff.h>
33+#include <asm/uaccess.h>
34+#include <asm/system.h>
35+#include <net/sock.h>
36+#include <linux/init.h>
37+#include <linux/spinlock.h>
38+#include <linux/list.h>
39+
40+#include <linux/netfilter.h>
41+#include <linux/netlink.h>
42+#include <linux/nfnetlink.h>
43+
44+MODULE_LICENSE("GPL");
45+
46+char nfversion[] = "0.11";
47+int nf_debug_level = 1;
48+#define nf_debug(level, format, arg...) \
49+        if(nf_debug_level > level)  \
50+                printk(__FUNCTION__ ": " format, ## arg)
51+
52+static struct sock *nfnl = NULL;
53+static LIST_HEAD(subsys_list);
54+static struct nfnetlink_subsystem *subsys_table[NFNL_SUBSYS_COUNT];
55+DECLARE_MUTEX(nfnl_sem);
56+
57+void nfnl_lock(void)
58+{
59+	nfnl_shlock();
60+	nfnl_exlock();
61+}
62+
63+void nfnl_unlock(void)
64+{
65+	nfnl_exunlock();
66+	nfnl_shunlock();
67+}
68+
69+struct nfnetlink_subsystem *nfnetlink_subsys_alloc(int cb_count)
70+{
71+	int size;
72+	struct nfnetlink_subsystem *ss;
73+
74+	size = sizeof(struct nfnetlink_subsystem)
75+		+ (cb_count * sizeof(struct nfnl_callback));
76+
77+	ss = kmalloc(size, GFP_KERNEL);
78+	if (!ss)
79+		return NULL;
80+	memset(ss, 0, size);
81+
82+	return ss;
83+}
84+
85+int nfnetlink_subsys_register(struct nfnetlink_subsystem *n)
86+{
87+	MOD_INC_USE_COUNT;
88+
89+	nf_debug(0, "registering subsystem ID %u\n", n->subsys_id);
90+
91+	nfnl_lock();
92+	list_add(&n->list, &subsys_list);
93+	subsys_table[n->subsys_id] = n;
94+	nfnl_unlock();
95+
96+	return 0;
97+}
98+
99+int nfnetlink_subsys_unregister(struct nfnetlink_subsystem *n)
100+{
101+	nf_debug(0, "unregistering subsystem ID %u\n", n->subsys_id);
102+
103+	nfnl_lock();
104+	subsys_table[n->subsys_id] = NULL;
105+	list_del(&n->list);
106+	nfnl_unlock();
107+
108+	MOD_DEC_USE_COUNT;
109+
110+	return 0;
111+}
112+
113+struct nfnl_callback *nfnetlink_find_client(u_int16_t nlmsg_type)
114+{
115+	struct nfnetlink_subsystem *ss;
116+	u_int8_t subsys_id = NFNL_SUBSYS_ID(nlmsg_type);
117+	u_int8_t type = NFNL_MSG_TYPE(nlmsg_type);
118+
119+	if (subsys_id >= NFNL_SUBSYS_COUNT
120+	    || subsys_table[subsys_id] == NULL)
121+		return NULL;
122+
123+	ss = subsys_table[subsys_id];
124+
125+	if (type >= ss->cb_count) {
126+		nf_debug(0, "msgtype %u >= %u, returning\n", type, 
127+			 ss->cb_count);
128+		return NULL;
129+	}
130+
131+	return &ss->cb[type];
132+}
133+
134+void __nfa_fill(struct sk_buff *skb, int attrtype, int attrlen,
135+		const void *data)
136+{
137+	struct nfattr *nfa;
138+	int size = NFA_LENGTH(attrlen);
139+
140+	nfa = (struct nfattr *)skb_put(skb, NFA_ALIGN(size));
141+	nfa->nfa_type = attrtype;
142+	nfa->nfa_len  = size;
143+	memcpy(NFA_DATA(nfa), data, attrlen);
144+}
145+
146+int nfattr_parse(struct nfattr *tb[], int maxattr, struct nfattr *nfa, int len)
147+{
148+	memset(tb, 0, sizeof(struct nfattr *)*maxattr);
149+
150+	while (NFA_OK(nfa, len)) {
151+		unsigned flavor = nfa->nfa_type;
152+		if (flavor && flavor <= maxattr)
153+			tb[flavor-1] = nfa;
154+		nfa = NFA_NEXT(nfa, len);
155+	}
156+
157+	return 0;
158+}
159+
160+/**
161+ * nfnetlink_check_attributes - check and parse nfnetlink attributes
162+ *
163+ * subsys: nfnl subsystem for which this message is to be parsed
164+ * nlmsghdr: netlink message to be checked/parsed
165+ * cda: array of pointers, needs to be at least subsys->attr_count big
166+ *
167+ */
168+int
169+nfnetlink_check_attributes(struct nfnetlink_subsystem *subsys,
170+			   struct nlmsghdr *nlh, struct nfattr *cda[])
171+{
172+	int min_len;
173+
174+	/* check attribute lengths. */
175+	min_len = sizeof(struct nfgenmsg);
176+	if (nlh->nlmsg_len < min_len)
177+		return -EINVAL;
178+
179+	if (nlh->nlmsg_len > min_len) {
180+		struct nfattr *attr = NFM_NFA(NLMSG_DATA(nlh));
181+		int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len);
182+
183+		while (NFA_OK(attr, attrlen)) {
184+			unsigned flavor = attr->nfa_type;
185+			if (flavor) {
186+				if (flavor > subsys->attr_count)
187+					return -EINVAL;
188+				cda[flavor - 1] = attr;
189+			}
190+			attr = NFA_NEXT(attr, attrlen);
191+		}
192+	} else
193+		return -EINVAL;
194+
195+        return 0;
196+}
197+
198+int nfnetlink_send(struct sk_buff *skb, u32 pid, unsigned group, int echo)
199+{
200+	int err = 0;
201+
202+	NETLINK_CB(skb).dst_groups = group;
203+	if (echo)
204+		atomic_inc(&skb->users);
205+	netlink_broadcast(nfnl, skb, pid, group, GFP_KERNEL);
206+	if (echo)
207+		err = netlink_unicast(nfnl, skb, pid, MSG_DONTWAIT);
208+
209+	return err;
210+}
211+
212+/* Process one complete nfnetlink message. */
213+static inline int nfnetlink_rcv_msg(struct sk_buff *skb,
214+				    struct nlmsghdr *nlh, int *errp)
215+{
216+	struct nfnl_callback *nc;
217+	int type, err = 0;
218+
219+	nf_debug(0, "entered; subsys=%u, msgtype=%u\n",
220+		 NFNL_SUBSYS_ID(nlh->nlmsg_type),
221+		 NFNL_MSG_TYPE(nlh->nlmsg_type));
222+
223+	/* Only requests are handled by kernel now. */
224+	if (!(nlh->nlmsg_flags & NLM_F_REQUEST)) {
225+		nf_debug(0, "received non-request message\n");
226+		return 0;
227+	}
228+
229+	/* Unknown message: reply with EINVAL */
230+	type = nlh->nlmsg_type;
231+	if (NFNL_SUBSYS_ID(type) > NFNL_SUBSYS_COUNT) {
232+		nf_debug(0, "subsys_id > subsys_count\n");
233+		goto err_inval;
234+	}
235+
236+	/* All the messages must have at least 1 byte length */
237+	if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(struct nfgenmsg))) {
238+		nf_debug(0, "received message was too short\n");
239+		return 0;
240+	}
241+
242+	nc = nfnetlink_find_client(type);
243+	if (!nc) {
244+		nf_debug(0, "unable to find client for type %d\n", type);
245+		goto err_inval;
246+	}
247+
248+	if (nc->cap_required && 
249+	    !cap_raised(NETLINK_CB(skb).eff_cap, nc->cap_required)) {
250+		nf_debug(0, "permission denied for type %d\n", type);
251+		*errp = -EPERM;
252+		return -1;
253+	}
254+
255+	err = nc->call(nfnl, skb, nlh, errp);
256+	*errp = err;
257+	return err;
258+
259+err_inval:
260+	*errp = -EINVAL;
261+	return -1;
262+}
263+
264+/* Process one packet of messages. */
265+static inline int nfnetlink_rcv_skb(struct sk_buff *skb)
266+{
267+	int err;
268+	struct nlmsghdr *nlh;
269+
270+	while (skb->len >= NLMSG_SPACE(0)) {
271+		u32 rlen;
272+
273+		nlh = (struct nlmsghdr *)skb->data;
274+		if (nlh->nlmsg_len < sizeof(struct nlmsghdr)
275+		    || skb->len < nlh->nlmsg_len)
276+			return 0;
277+		rlen = NLMSG_ALIGN(nlh->nlmsg_len);
278+		if (rlen > skb->len)
279+			rlen = skb->len;
280+		if (nfnetlink_rcv_msg(skb, nlh, &err)) {
281+			if (!err)
282+				return -1;
283+			netlink_ack(skb, nlh, err);
284+		} else
285+			if (nlh->nlmsg_flags & NLM_F_ACK)
286+				netlink_ack(skb, nlh, 0);
287+		skb_pull(skb, rlen);
288+	}
289+
290+	return 0;
291+}
292+
293+static void nfnetlink_rcv(struct sock *sk, int len)
294+{
295+	do {
296+		struct sk_buff *skb;
297+
298+		if (nfnl_shlock_nowait())
299+			return;
300+
301+		while ((skb = skb_dequeue(&sk->receive_queue)) != NULL) {
302+			if (nfnetlink_rcv_skb(skb)) {
303+				if (skb->len)
304+					skb_queue_head(&sk->receive_queue, skb);
305+				else
306+					kfree_skb(skb);
307+				break;
308+			}
309+			kfree_skb(skb);
310+		}
311+
312+		up(&nfnl_sem);
313+	} while(nfnl && nfnl->receive_queue.qlen);
314+}
315+
316+void __exit nfnetlink_exit(void)
317+{
318+	printk("Netfilter removing netlink socket.\n");
319+	sock_release(nfnl->socket);
320+	return;
321+}
322+
323+int __init nfnetlink_init(void)
324+{
325+	int i;
326+	printk("Netfilter messages via NETLINK v%s.\n", nfversion);
327+
328+	for (i = 0; i < NFNL_SUBSYS_COUNT; i++)
329+		subsys_table[i] = NULL;
330+
331+	nfnl = netlink_kernel_create(NETLINK_NETFILTER, nfnetlink_rcv);
332+	if (!nfnl) {
333+		printk(KERN_ERR "cannot initialize nfnetlink!\n");
334+		return -1;
335+	}
336+
337+	return 0;
338+}
339+
340+module_init(nfnetlink_init);
341+module_exit(nfnetlink_exit);
342+
343+EXPORT_SYMBOL_GPL(nfnetlink_subsys_alloc);
344+EXPORT_SYMBOL_GPL(nfnetlink_subsys_register);
345+EXPORT_SYMBOL_GPL(nfnetlink_subsys_unregister);
346+EXPORT_SYMBOL_GPL(nfnetlink_check_attributes);
347+EXPORT_SYMBOL_GPL(nfnetlink_send);
348+EXPORT_SYMBOL_GPL(__nfa_fill);
349diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linuxppc-020802-newnat/net/ipv4/netfilter/nfnetlink_conntrack.c linuxppc-020802-newnat14-ctnl/net/ipv4/netfilter/nfnetlink_conntrack.c
350--- linuxppc-020802-newnat/net/ipv4/netfilter/nfnetlink_conntrack.c	Thu Jan  1 01:00:00 1970
351+++ linuxppc-020802-newnat14-ctnl/net/ipv4/netfilter/nfnetlink_conntrack.c	Fri Aug  2 16:00:42 2002
352@@ -0,0 +1,717 @@
353+/* Connection tracking via netlink socket. Allows for user space
354+ * protocol helpers and general trouble making from userspace.
355+ *
356+ * (C) 2001 by Jay Schulist <jschlst@samba.org>
357+ * (C) 2002 by Harald Welte <laforge@gnumonks.org>
358+ *
359+ * Initial connection tracking via netlink development funded and 
360+ * generally made possible by Network Robots, Inc. (www.networkrobots.com)
361+ *
362+ * Further development of this code funded by Astaro AG (http://www.asaro.com)
363+ *
364+ * This software may be used and distributed according to the terms
365+ * of the GNU General Public License, incorporated herein by reference.
366+ */
367+
368+#include <linux/config.h>
369+#include <linux/module.h>
370+#include <linux/types.h>
371+#include <linux/socket.h>
372+#include <linux/kernel.h>
373+#include <linux/major.h>
374+#include <linux/sched.h>
375+#include <linux/timer.h>
376+#include <linux/string.h>
377+#include <linux/sockios.h>
378+#include <linux/net.h>
379+#include <linux/fcntl.h>
380+#include <linux/skbuff.h>
381+#include <asm/uaccess.h>
382+#include <asm/system.h>
383+#include <net/sock.h>
384+#include <linux/init.h>
385+#include <linux/netlink.h>
386+#include <linux/spinlock.h>
387+#include <linux/rtnetlink.h>
388+
389+#include <linux/netfilter.h>
390+#include <linux/netfilter_ipv4.h>
391+#include <linux/netfilter_ipv4/ip_tables.h>
392+#include <linux/netfilter_ipv4/ip_conntrack.h>
393+#include <linux/netfilter_ipv4/ip_conntrack_core.h>
394+
395+#include <linux/nfnetlink.h>
396+#include <linux/nfnetlink_conntrack.h>
397+
398+#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_conntrack_lock)
399+#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_conntrack_lock)
400+#include <linux/netfilter_ipv4/listhelp.h>
401+
402+MODULE_LICENSE("GPL");
403+
404+char ctversion[] = "0.11";
405+int ct_debug_level = 1;
406+#define ct_debug(level, format, arg...) \
407+	if(ct_debug_level > level)  \
408+		printk(__FUNCTION__ ": " format, ## arg)
409+
410+
411+#define DEBUGP(format, args...)	ct_debug(0, format, ## args)
412+
413+static struct nfnetlink_subsystem *ctnl_subsys;
414+
415+static int
416+ctnetlink_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
417+		    int event, 
418+		    int nowait, 
419+		    const struct ip_conntrack *ct, 
420+		    const enum ip_conntrack_info *ctinfo, 
421+		    unsigned char proto,
422+		    const struct net_device *in,
423+		    const struct net_device *out)
424+{
425+	struct nlmsghdr *nlh;
426+	struct nfgenmsg *nfmsg;
427+	struct cta_proto cp;
428+	unsigned long s;
429+	unsigned char *b;
430+
431+	b = skb->tail;
432+	nlh = NLMSG_PUT(skb, pid, seq, (NFNL_SUBSYS_CTNETLINK<<8)|event, 
433+			sizeof(struct nfgenmsg));
434+	nfmsg = NLMSG_DATA(nlh);
435+
436+	nlh->nlmsg_flags 	= (nowait && pid) ? NLM_F_MULTI : 0;
437+	nfmsg->nfgen_family	= AF_INET;
438+	NFA_PUT(skb, CTA_ORIG, sizeof(struct ip_conntrack_tuple), 
439+		&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
440+	NFA_PUT(skb, CTA_RPLY, sizeof(struct ip_conntrack_tuple),
441+		&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
442+	s = ct->status;
443+	NFA_PUT(skb, CTA_STATUS, sizeof(unsigned long), &s);
444+	if (in)
445+		NFA_PUT(skb, CTA_IIF, IFNAMSIZ, in->name);
446+	if (out)
447+		NFA_PUT(skb, CTA_OIF, IFNAMSIZ, out->name);
448+	if (ctinfo)
449+		NFA_PUT(skb, CTA_INFO, sizeof(unsigned long), ctinfo);
450+
451+	cp.num_proto = proto;
452+	memcpy(&cp.proto, &ct->proto, sizeof (cp.proto));
453+	NFA_PUT(skb, CTA_PROTOINFO, sizeof(cp), &cp);
454+
455+	if (ct->helper) {
456+		struct cta_help ch;
457+
458+		memcpy(&ch.tuple, &ct->helper->tuple, 
459+			sizeof(struct ip_conntrack_tuple));
460+		memcpy(&ch.mask, &ct->helper->mask,
461+			sizeof(struct ip_conntrack_tuple));
462+		strncpy((char *)&ch.name, ct->helper->name, sizeof(ch.name));
463+		memcpy(&ch.help, &ct->help, sizeof(ch.help));
464+		NFA_PUT(skb, CTA_HELPINFO, sizeof(ch), &ch);
465+	}
466+
467+#ifdef CONFIG_IP_NF_NAT_NEEDED
468+	if (ct->nat.info.initialized && ct->nat.info.num_manips) {
469+		const struct ip_nat_info *nat = &ct->nat.info;
470+		struct cta_nat cn;
471+
472+		cn.num_manips = nat->num_manips;
473+		memcpy(&cn.manips, &nat->manips, (nat->num_manips 
474+			* sizeof(struct ip_nat_info_manip)));
475+		NFA_PUT(skb, CTA_NATINFO, sizeof(struct cta_nat), &cn);
476+	}
477+#endif /* CONFIG_IP_NF_NAT_NEEDED */
478+
479+	nlh->nlmsg_len = skb->tail - b;
480+	return skb->len;
481+
482+nlmsg_failure:
483+nfattr_failure:
484+	skb_trim(skb, b - skb->data);
485+	return -1;
486+}
487+
488+static inline struct sk_buff *
489+ctnetlink_event_build_msg(const struct ip_conntrack *ct, 
490+			  const enum ip_conntrack_info ctinfo, 
491+			  const unsigned char proto,
492+			  const struct net_device *in,
493+			  const struct net_device *out)
494+{
495+	struct sk_buff *skb;
496+	int err;
497+
498+	skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
499+	if (!skb)
500+		return NULL;
501+
502+	err = ctnetlink_fill_info(skb, 0, 0, CTNL_MSG_NEWCONNTRACK, 1, ct,
503+				  &ctinfo, proto, in, out);
504+	if (err <= 0)
505+		goto nlmsg_failure;
506+	return skb;
507+
508+nlmsg_failure:
509+	if (skb)
510+		kfree_skb(skb);
511+        return NULL;
512+}
513+
514+static void
515+ctnetlink_create(struct ip_conntrack *ct,
516+		 enum ip_conntrack_info ctinfo,
517+		 const struct net_device *in, 
518+		 const struct net_device *out)
519+{
520+	u16 proto = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum;
521+	struct sk_buff *skb;
522+
523+	skb = ctnetlink_event_build_msg(ct, ctinfo, proto, in, out);
524+	if (!skb)
525+		return;
526+
527+	if (proto == IPPROTO_TCP) {
528+		nfnetlink_send(skb, 0, NFGRP_IPV4_CT_TCP, 0);
529+		return;
530+       	} else if (proto == IPPROTO_UDP) {
531+		nfnetlink_send(skb, 0, NFGRP_IPV4_CT_UDP, 0);
532+		return;
533+       	} else if (proto == IPPROTO_ICMP) {
534+		nfnetlink_send(skb, 0, NFGRP_IPV4_CT_ICMP, 0);
535+		return;
536+	} else {
537+		nfnetlink_send(skb, 0, NFGRP_IPV4_CT_OTHER, 0);
538+		return;
539+	}
540+	kfree_skb(skb);
541+	return;
542+}
543+
544+#if 0
545+static void ctnetlink_destroy(struct ip_conntrack *ct)
546+{
547+        ctnetlink_create(ct, IP_CT_DELETE, NULL, NULL);
548+}
549+#endif
550+
551+static inline int ctnetlink_kill(const struct ip_conntrack *i, void *data)
552+{
553+	struct ip_conntrack *t = (struct ip_conntrack *)data;
554+
555+	if (!memcmp(&i->tuplehash[IP_CT_DIR_ORIGINAL], 
556+	    &t->tuplehash[IP_CT_DIR_ORIGINAL], 
557+	    sizeof(struct ip_conntrack_tuple_hash))) {
558+		//ip_conntrack_put(t);
559+		nf_conntrack_put(&t->infos[0]);
560+		return 1;
561+	}
562+
563+	return 0;
564+}
565+
566+static int
567+ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb, 
568+			struct nlmsghdr *nlh, int *errp)
569+{
570+        struct ip_conntrack_tuple_hash *h;
571+	struct ip_conntrack_tuple *tuple;
572+	struct nfattr *cda[CTA_MAX];
573+
574+	ct_debug(0, "entered\n");
575+
576+	if (nfnetlink_check_attributes(ctnl_subsys, nlh, cda) < 0)
577+		return -EINVAL;
578+
579+	if (cda[CTA_ORIG-1])
580+		tuple = NFA_DATA(cda[CTA_ORIG-1]);
581+	else {
582+		if (cda[CTA_RPLY-1])
583+			tuple = NFA_DATA(cda[CTA_RPLY-1]);
584+		else {
585+			ct_debug(0, "no tuple found in request\n");
586+			return -EINVAL;
587+		}
588+	}
589+
590+	h = ip_conntrack_find_get(tuple, NULL);
591+        if (!h) {
592+		ct_debug(0, "tuple not found in conntrack hash:");
593+		DUMP_TUPLE(tuple);
594+		return -ENOENT;
595+	}
596+
597+	ct_debug(0, "calling selective_cleanup\n");
598+	ip_ct_selective_cleanup(ctnetlink_kill, h->ctrack);
599+
600+	return 0;
601+}
602+
603+static int ctnetlink_done(struct netlink_callback *cb)
604+{
605+	ct_debug(0, "entering\n");
606+        return 0;
607+}
608+
609+static int
610+ctnetlink_dump_build_msg(const struct ip_conntrack_tuple_hash *hash,
611+			 struct sk_buff *skb, u32 pid, u32 seq)
612+{
613+	struct ip_conntrack *ct;
614+	int err, proto;
615+
616+	/* Only count originals */
617+	if (DIRECTION(hash))
618+		return 0;
619+
620+	ct = hash->ctrack;
621+	if (!ct)
622+		goto nlmsg_failure;
623+
624+	proto = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum;
625+	err = ctnetlink_fill_info(skb, pid, seq, CTNL_MSG_NEWCONNTRACK, 1,
626+				  ct, NULL, proto, NULL, NULL);
627+	if (err <= 0)
628+		goto nlmsg_failure;
629+	return 0;
630+
631+nlmsg_failure:
632+	if (skb)
633+		kfree_skb(skb);
634+	return -1;
635+}
636+
637+static int
638+ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
639+{
640+	int i;
641+	int idx;
642+	int s_idx = cb->args[0];
643+
644+	/* Traverse hash; send originals then reply. */
645+	READ_LOCK(&ip_conntrack_lock);
646+        for (i = 0, idx = 0; i < ip_conntrack_htable_size; i++, idx++) {
647+		if (idx < s_idx)
648+			continue;
649+		if (LIST_FIND(&ip_conntrack_hash[i], ctnetlink_dump_build_msg,
650+			      struct ip_conntrack_tuple_hash *, skb,
651+			      NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq))
652+			continue;
653+	}
654+	READ_UNLOCK(&ip_conntrack_lock);
655+
656+	cb->args[0] = idx;
657+	return skb->len;
658+}
659+
660+static int
661+ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, 
662+			struct nlmsghdr *nlh, int *errp)
663+{
664+	struct ip_conntrack_tuple_hash *h;
665+	struct ip_conntrack_tuple *tuple;
666+	struct nfattr *cda[CTA_MAX];
667+	struct ip_conntrack *ct;
668+	struct sk_buff *skb2 = NULL;
669+	int err, proto;
670+
671+	ct_debug(0, "entered\n");
672+
673+	if (nlh->nlmsg_flags & NLM_F_DUMP) {
674+		struct nfgenmsg *msg = NLMSG_DATA(nlh);
675+		u32 rlen;
676+
677+		if (msg->nfgen_family != AF_INET)
678+			return -EAFNOSUPPORT;
679+
680+		ct_debug(0, "starting dump\n");
681+                if ((*errp = netlink_dump_start(ctnl, skb, nlh,
682+		    				ctnetlink_dump_table,
683+						ctnetlink_done)) != 0)
684+			return -EINVAL;
685+		rlen = NLMSG_ALIGN(nlh->nlmsg_len);
686+		if (rlen > skb->len)
687+			rlen = skb->len;
688+		skb_pull(skb, rlen);
689+		return 0;
690+	}
691+
692+	if (nfnetlink_check_attributes(ctnl_subsys, nlh, cda) < 0)
693+		return -EINVAL;
694+
695+	if (cda[CTA_ORIG-1])
696+		tuple = NFA_DATA(cda[CTA_ORIG-1]);
697+	else {
698+		if (cda[CTA_RPLY-1])
699+			tuple = NFA_DATA(cda[CTA_RPLY-1]);
700+		else
701+			return -EINVAL;
702+	}
703+
704+	h = ip_conntrack_find_get(tuple, NULL);
705+	if (!h)
706+		return -ENOENT;
707+
708+	ct = h->ctrack;
709+	if (!ct)
710+		goto nlmsg_failure;
711+
712+	skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
713+	if (!skb2)
714+		return -ENOMEM;
715+	NETLINK_CB(skb2).dst_pid = NETLINK_CB(skb).pid;
716+
717+        proto = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum;
718+	err = ctnetlink_fill_info(skb2, NETLINK_CB(skb).pid, nlh->nlmsg_seq, 
719+				  CTNL_MSG_NEWCONNTRACK, 1, ct, NULL, 
720+				  proto, NULL, NULL);
721+	ip_conntrack_put(ct);
722+	if (err <= 0)
723+		goto nlmsg_failure;
724+
725+	err = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT);
726+	if (err < 0)
727+		return err;
728+	return 0;
729+
730+nlmsg_failure:
731+	if (skb2)
732+		kfree_skb(skb2);
733+	return -1;
734+}
735+
736+/* Finish me: should support NLM_F_CREATE and NLM_F_REPLACE. */
737+static int 
738+ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, 
739+			struct nlmsghdr *nlh, int *errp)
740+{
741+	return -EOPNOTSUPP;
742+}
743+
744+
745+/* EXPECT */
746+
747+static int
748+ctnetlink_exp_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
749+		    int event, 
750+		    int nowait, 
751+		    const struct ip_conntrack_expect *exp)
752+{
753+	struct nlmsghdr *nlh;
754+	struct nfgenmsg *nfmsg;
755+	unsigned char *b;
756+
757+	b = skb->tail;
758+	nlh = NLMSG_PUT(skb, pid, seq, (NFNL_SUBSYS_CTNETLINK<<8)|event, 
759+			sizeof(struct nfgenmsg));
760+	nlh->nlmsg_flags 	= (nowait && pid) ? NLM_F_MULTI : 0;
761+	nfmsg = NLMSG_DATA(nlh);
762+	nfmsg->nfgen_family = AF_INET;
763+
764+	NFA_PUT(skb, CTA_EXP_TUPLE, sizeof(struct ip_conntrack_tuple),
765+		&exp->tuple);
766+	NFA_PUT(skb, CTA_EXP_MASK, sizeof(struct ip_conntrack_tuple),
767+		&exp->mask);
768+	NFA_PUT(skb, CTA_EXP_SEQNO, sizeof(u_int32_t), &exp->seq);
769+	NFA_PUT(skb, CTA_EXP_HELP, sizeof(union ip_conntrack_expect_help),
770+		&exp->help);
771+
772+	
773+
774+#ifdef CONFIG_IP_NF_NAT_NEEDED
775+#endif /* CONFIG_IP_NF_NAT_NEEDED */
776+
777+	nlh->nlmsg_len = skb->tail - b;
778+	return skb->len;
779+
780+nlmsg_failure:
781+nfattr_failure:
782+	skb_trim(skb, b - skb->data);
783+	return -1;
784+}
785+
786+static inline struct sk_buff *
787+ctnetlink_exp_event_build_msg(const struct ip_conntrack_expect *exp)
788+{
789+	struct sk_buff *skb;
790+	int err;
791+
792+	skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
793+	if (!skb)
794+		return NULL;
795+
796+	err = ctnetlink_exp_fill_info(skb, 0, 0, CTNL_MSG_NEWEXPECT, 1, exp);
797+	if (err <= 0)
798+		goto nlmsg_failure;
799+	return skb;
800+
801+nlmsg_failure:
802+	if (skb)
803+		kfree_skb(skb);
804+        return NULL;
805+}
806+
807+static void
808+ctnetlink_exp_create(struct ip_conntrack_expect *exp)
809+{
810+	u16 proto = exp->tuple.dst.protonum;
811+	struct sk_buff *skb;
812+
813+	skb = ctnetlink_exp_event_build_msg(exp);
814+	if (!skb)
815+		return;
816+
817+	if (proto == IPPROTO_TCP) {
818+		nfnetlink_send(skb, 0, NFGRP_IPV4_CT_TCP, 0);
819+		return;
820+       	} else if (proto == IPPROTO_UDP) {
821+		nfnetlink_send(skb, 0, NFGRP_IPV4_CT_UDP, 0);
822+		return;
823+       	} else if (proto == IPPROTO_ICMP) {
824+		nfnetlink_send(skb, 0, NFGRP_IPV4_CT_ICMP, 0);
825+		return;
826+	} else {
827+		nfnetlink_send(skb, 0, NFGRP_IPV4_CT_OTHER, 0);
828+		return;
829+	}
830+	kfree_skb(skb);
831+	return;
832+}
833+
834+
835+static int
836+ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, 
837+		     struct nlmsghdr *nlh, int *errp)
838+{
839+        struct ip_conntrack_expect *exp;
840+	struct ip_conntrack_tuple *tuple;
841+	struct nfattr *cda[CTA_MAX];
842+
843+	if (nfnetlink_check_attributes(ctnl_subsys, nlh, cda) < 0)
844+		return -EINVAL;
845+
846+	if (cda[CTA_ORIG-1])
847+		tuple = NFA_DATA(cda[CTA_ORIG-1]);
848+	else {
849+		if (cda[CTA_RPLY-1])
850+			tuple = NFA_DATA(cda[CTA_RPLY-1]);
851+		else
852+			return -EINVAL;
853+	}
854+
855+	/* bump usage count to 2 */
856+	exp = ip_conntrack_expect_find_get(tuple);
857+	if (!exp)
858+		return -ENOENT;
859+
860+	/* after list removal, usage count == 1 */
861+	ip_conntrack_unexpect_related(exp);
862+	/* we have put what we 'get' above. after this line usage count == 0 */
863+	ip_conntrack_expect_put(exp);
864+
865+	return 0;
866+}
867+
868+static int
869+ctnetlink_exp_dump_build_msg(const struct ip_conntrack_expect *exp,
870+			 struct sk_buff *skb, u32 pid, u32 seq)
871+{
872+	int err, proto;
873+
874+	proto = exp->tuple.dst.protonum;
875+	err = ctnetlink_exp_fill_info(skb, pid, seq, CTNL_MSG_NEWEXPECT, 1, 
876+				      exp);
877+	if (err <= 0)
878+		goto nlmsg_failure;
879+	return 0;
880+
881+nlmsg_failure:
882+	if (skb)
883+		kfree_skb(skb);
884+	return -1;
885+}
886+
887+static int
888+ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
889+{
890+	ct_debug(0, "entered\n");
891+	if (cb->args[0] == 0) {
892+		READ_LOCK(&ip_conntrack_lock);
893+		LIST_FIND(&ip_conntrack_expect_list, 
894+			  ctnetlink_exp_dump_build_msg,
895+			  struct ip_conntrack_expect *, skb,
896+			  NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq);
897+		READ_UNLOCK(&ip_conntrack_lock);
898+		cb->args[0] = 1;
899+	}
900+	ct_debug(0, "returning\n");
901+
902+	return skb->len;
903+}
904+
905+
906+static int
907+ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, 
908+		     struct nlmsghdr *nlh, int *errp)
909+{
910+	struct ip_conntrack_expect *exp;
911+	struct ip_conntrack_tuple *tuple;
912+	struct nfattr *cda[CTA_MAX];
913+	struct sk_buff *skb2 = NULL;
914+	int err, proto;
915+
916+	ct_debug(0, "entered\n");
917+
918+	if (nlh->nlmsg_flags & NLM_F_DUMP) {
919+		struct nfgenmsg *msg = NLMSG_DATA(nlh);
920+		u32 rlen;
921+
922+		if (msg->nfgen_family != AF_INET)
923+			return -EAFNOSUPPORT;
924+
925+		ct_debug(0, "starting dump\n");
926+                if ((*errp = netlink_dump_start(ctnl, skb, nlh,
927+		    				ctnetlink_exp_dump_table,
928+						ctnetlink_done)) != 0)
929+			return -EINVAL;
930+		rlen = NLMSG_ALIGN(nlh->nlmsg_len);
931+		if (rlen > skb->len)
932+			rlen = skb->len;
933+		skb_pull(skb, rlen);
934+		return 0;
935+	}
936+
937+	if (nfnetlink_check_attributes(ctnl_subsys, nlh, cda) < 0)
938+		return -EINVAL;
939+
940+	if (cda[CTA_ORIG-1])
941+		tuple = NFA_DATA(cda[CTA_ORIG-1]);
942+	else {
943+		if (cda[CTA_RPLY-1])
944+			tuple = NFA_DATA(cda[CTA_RPLY-1]);
945+		else
946+			return -EINVAL;
947+	}
948+
949+	exp = ip_conntrack_expect_find_get(tuple);
950+	if (!exp)
951+		return -ENOENT;
952+
953+	skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
954+	if (!skb2)
955+		return -ENOMEM;
956+	NETLINK_CB(skb2).dst_pid = NETLINK_CB(skb).pid;
957+	proto = exp->tuple.dst.protonum;
958+	
959+	err = ctnetlink_exp_fill_info(skb2, NETLINK_CB(skb).pid, 
960+				      nlh->nlmsg_seq, CTNL_MSG_NEWEXPECT,
961+				      1, exp);
962+	if (err <= 0)
963+		goto nlmsg_failure;
964+
965+	err = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT);
966+	if (err < 0)
967+		return err;
968+	return 0;
969+
970+nlmsg_failure:
971+	if (skb2)
972+		kfree_skb(skb2);
973+	return -1;
974+}
975+
976+static int
977+ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb,
978+		     struct nlmsghdr *nlh, int *errp)
979+{
980+	return -EOPNOTSUPP;
981+}
982+
983+/* struct conntrack_expect stuff */
984+
985+#if 0
986+static struct ip_conntrack_notify ctnl_notify = { { NULL, NULL },
987+						ctnetlink_destroy,
988+						ctnetlink_create };
989+
990+static struct ip_conntrack_notify ctnl_exp_notify;
991+#endif
992+
993+static void __exit ctnetlink_exit(void)
994+{
995+	printk("ctnetlink: unregistering with nfnetlink.\n");
996+//	ip_conntrack_notify_unregister(&ctnl_exp_notify);
997+//	ip_conntrack_notify_unregister(&ctnl_notify);
998+	nfnetlink_subsys_unregister(ctnl_subsys);
999+	kfree(ctnl_subsys);
1000+	return;
1001+}
1002+
1003+static int __init ctnetlink_init(void)
1004+{
1005+	int ret;
1006+
1007+	ctnl_subsys = nfnetlink_subsys_alloc(CTNL_MSG_COUNT);
1008+	if (!ctnl_subsys) {
1009+		ret = -ENOMEM;
1010+		goto err_out; 
1011+	}
1012+
1013+	ctnl_subsys->name = "conntrack";
1014+	ctnl_subsys->subsys_id = NFNL_SUBSYS_CTNETLINK;
1015+	ctnl_subsys->cb_count = CTNL_MSG_COUNT;
1016+	ctnl_subsys->attr_count = CTA_MAX;
1017+	ctnl_subsys->cb[CTNL_MSG_NEWCONNTRACK].call = ctnetlink_new_conntrack;
1018+	ctnl_subsys->cb[CTNL_MSG_NEWCONNTRACK].cap_required = CAP_NET_ADMIN;
1019+	ctnl_subsys->cb[CTNL_MSG_DELCONNTRACK].call = ctnetlink_del_conntrack;
1020+	ctnl_subsys->cb[CTNL_MSG_DELCONNTRACK].cap_required = CAP_NET_ADMIN;
1021+	ctnl_subsys->cb[CTNL_MSG_GETCONNTRACK].call = ctnetlink_get_conntrack;
1022+	ctnl_subsys->cb[CTNL_MSG_GETCONNTRACK].cap_required = 0;
1023+	ctnl_subsys->cb[CTNL_MSG_NEWEXPECT].call = ctnetlink_new_expect;
1024+	ctnl_subsys->cb[CTNL_MSG_NEWEXPECT].cap_required = CAP_NET_ADMIN;
1025+	ctnl_subsys->cb[CTNL_MSG_DELEXPECT].call = ctnetlink_del_expect;
1026+	ctnl_subsys->cb[CTNL_MSG_DELEXPECT].cap_required = CAP_NET_ADMIN;
1027+	ctnl_subsys->cb[CTNL_MSG_GETEXPECT].call = ctnetlink_get_expect;
1028+	ctnl_subsys->cb[CTNL_MSG_GETEXPECT].cap_required = 0;
1029+	// FIXME: CONFIRM
1030+
1031+	printk("ctnetlink: registering with nfnetlink v%s.\n", ctversion);
1032+	if (nfnetlink_subsys_register(ctnl_subsys) < 0) {
1033+		printk("ctnetlink_init: cannot register with nfnetlink.\n");
1034+		ret = -1;
1035+		goto err_free_subsys;
1036+	}
1037+
1038+
1039+#if 0
1040+	if (ip_conntrack_notify_register(&ctnl_notify) < 0) {
1041+		printk("ctnetlink_init: cannot register notifier.\n");
1042+		ret = -1;
1043+		goto err_unreg_subsys;
1044+	}
1045+
1046+	if (ip_conntrack_notify_register(&ctnl_exp_notify) < 0) {
1047+		printk("ctnetlink_init: cannot register exp notifier\n");
1048+		ret = -1;
1049+		goto err_unreg_notify;
1050+	}
1051+#endif
1052+
1053+
1054+	return 0;
1055+	
1056+#if 0
1057+err_unreg_notify:
1058+	ip_conntrack_notify_unregister(&ctnl_notify);
1059+#endif 
1060+err_unreg_subsys:
1061+	nfnetlink_subsys_unregister(ctnl_subsys);
1062+err_free_subsys:
1063+	kfree(ctnl_subsys);
1064+err_out:
1065+	return ret;
1066+}
1067+
1068+module_init(ctnetlink_init);
1069+module_exit(ctnetlink_exit);
1070diff -Nru linuxppc-020802-newnat/include/linux/nfnetlink.h linuxppc-020802-newnat14-ctnl/include/linux/nfnetlink.h
1071--- linuxppc-020802-newnat/include/linux/nfnetlink.h	Thu Jan  1 01:00:00 1970
1072+++ linuxppc-020802-newnat14-ctnl/include/linux/nfnetlink.h	Fri Aug  2 15:58:27 2002
1073@@ -0,0 +1,158 @@
1074+#ifndef _NFNETLINK_H
1075+#define _NFNETLINK_H
1076+#include <linux/types.h>
1077+
1078+/* Generic structure for encapsulation optional netfilter information.
1079+ * It is reminiscent of sockaddr, but with sa_family replaced
1080+ * with attribute type. 
1081+ * ! This should someday be put somewhere generic as now rtnetlink and
1082+ * ! nfnetlink use the same attributes methods. - J. Schulist.
1083+ */
1084+
1085+struct nfattr
1086+{
1087+	unsigned short  nfa_len;
1088+	unsigned short  nfa_type;
1089+};
1090+
1091+#define NFA_ALIGNTO     4
1092+#define NFA_ALIGN(len)	(((len) + NFA_ALIGNTO - 1) & ~(NFA_ALIGNTO - 1))
1093+#define NFA_OK(nfa,len)	((len) > 0 && (nfa)->nfa_len >= sizeof(struct nfattr) \
1094+	&& (nfa)->nfa_len <= (len))
1095+#define NFA_NEXT(nfa,attrlen)	((attrlen) -= NFA_ALIGN((nfa)->nfa_len), \
1096+	(struct nfattr *)(((char *)(nfa)) + NFA_ALIGN((nfa)->nfa_len)))
1097+#define NFA_LENGTH(len)	(NFA_ALIGN(sizeof(struct nfattr)) + (len))
1098+#define NFA_SPACE(len)	NFA_ALIGN(NFA_LENGTH(len))
1099+#define NFA_DATA(nfa)   ((void *)(((char *)(nfa)) + NFA_LENGTH(0)))
1100+#define NFA_PAYLOAD(nfa) ((int)((nfa)->nfa_len) - NFA_LENGTH(0))
1101+
1102+/* General form of address family dependent message.
1103+ */
1104+struct nfgenmsg {
1105+	unsigned char nfgen_family;
1106+};
1107+
1108+#if 0
1109+struct iptgenmsg {
1110+	unsigned char 	iptgen_family;
1111+	char 		iptgen_table[IPT_TABLE_MAXNAMELEN];
1112+};
1113+
1114+struct iptmsg {
1115+	unsigned char	iptm_family;
1116+	char		iptm_table[IPT_TABLE_MAXNAMELEN];
1117+	char		iptm_chain[IPT_FUNCTION_MAXNAMELEN];
1118+	unsigned int	iptm_entry_num;
1119+};
1120+
1121+enum iptattr_type_t
1122+{
1123+        IPTA_UNSPEC,	/* [none] I don't know (unspecified). */
1124+	IPTA_IP,	/* [ipt_ip] */
1125+	IPTA_NFCACHE,	/* [u_int] */
1126+	IPTA_COUNTERS,	/* [ipt_counters] */
1127+	IPTA_MATCH,	/* [ipt_info] */
1128+	IPTA_TARGET,	/* [ipt_info] */
1129+        IPTA_MAX = IPTA_TARGET
1130+};
1131+
1132+struct ipta_info {
1133+	u_int16_t 	size;
1134+	char 		name[IPT_FUNCTION_MAXNAMELEN];
1135+	unsigned char 	data[0];
1136+};
1137+
1138+#define NFM_IPTA(n)	((struct nfattr *)(((char *)(n)) \
1139+	+ NLMSG_ALIGN(sizeof(struct iptmsg))))
1140+
1141+#endif
1142+
1143+#define NFM_NFA(n)      ((struct nfattr *)(((char *)(n)) \
1144+        + NLMSG_ALIGN(sizeof(struct nfgenmsg))))
1145+#define NFM_PAYLOAD(n)  NLMSG_PAYLOAD(n, sizeof(struct nfgenmsg))
1146+
1147+
1148+#ifndef NETLINK_NETFILTER
1149+#define NETLINK_NETFILTER	6
1150+#endif
1151+
1152+/* netfilter netlink message types are split in two pieces:
1153+ * 8 bit subsystem, 8bit operation.
1154+ */
1155+
1156+#define NFNL_SUBSYS_ID(x)	((x & 0xff00) >> 8)
1157+#define NFNL_MSG_TYPE(x)	(x & 0x00ff)
1158+
1159+enum nfnl_subsys_id {
1160+	NFNL_SUBSYS_NONE = 0,
1161+	NFNL_SUBSYS_CTNETLINK,
1162+	NFNL_SUBSYS_CTNETLINK_EXP,
1163+	NFNL_SUBSYS_IPTNETLINK,
1164+	NFNL_SUBSYS_QUEUE,
1165+	NFNL_SUBSYS_ULOG,
1166+	NFNL_SUBSYS_COUNT,
1167+};
1168+
1169+#ifdef __KERNEL__
1170+
1171+#include <linux/capability.h>
1172+
1173+struct nfnl_callback
1174+{
1175+	kernel_cap_t cap_required; /* capabilities required for this msg */
1176+	int (*call)(struct sock *nl, struct sk_buff *skb, 
1177+		struct nlmsghdr *nlh, int *errp);
1178+};
1179+
1180+struct nfnetlink_subsystem
1181+{
1182+	/* Internal use. */
1183+	struct list_head list;
1184+	
1185+	const char *name;
1186+	__u8 subsys_id;		/* nfnetlink subsystem ID */
1187+	__u8 cb_count;		/* number of callbacks */
1188+	u_int32_t attr_count;	/* number of nfattr's */
1189+	struct nfnl_callback cb[0]; /* callback for individual types */
1190+};
1191+
1192+extern void __nfa_fill(struct sk_buff *skb, int attrtype,
1193+        int attrlen, const void *data);
1194+#define NFA_PUT(skb, attrtype, attrlen, data) \
1195+({ if (skb_tailroom(skb) < (int)NFA_SPACE(attrlen)) goto nfattr_failure; \
1196+   __nfa_fill(skb, attrtype, attrlen, data); })
1197+
1198+extern struct semaphore nfnl_sem;
1199+#define nfnl_exlock()		do { } while(0)
1200+#define nfnl_exunlock()		do { } while(0)
1201+#define nfnl_exlock_nowait()	(0)
1202+
1203+#define nfnl_shlock()		down(&nfnl_sem)
1204+#define nfnl_shlock_nowait()	down_trylock(&nfnl_sem)
1205+
1206+#ifndef CONFIG_NF_NETLINK
1207+#define nfnl_shunlock()		up(&nfnl_sem)
1208+#else
1209+#define nfnl_shunlock()		do { up(&nfnl_sem); \
1210+                             		if(nfnl && nfnl->receive_queue.qlen) \
1211+                                     		nfnl->data_ready(nfnl, 0); \
1212+                        	} while(0)
1213+#endif
1214+
1215+extern void nfnl_lock(void);
1216+extern void nfnl_unlock(void);
1217+
1218+extern struct nfnetlink_subsystem *nfnetlink_subsys_alloc(int cb_count);
1219+extern int nfnetlink_subsys_register(struct nfnetlink_subsystem *n);
1220+extern int nfnetlink_subsys_unregister(struct nfnetlink_subsystem *n);
1221+
1222+extern int nfnetlink_check_attributes(struct nfnetlink_subsystem *subsys,
1223+				      struct nlmsghdr *nlh, 
1224+				      struct nfattr *cda[]);
1225+extern int nfattr_parse(struct nfattr *tb[], int maxattr, 
1226+			struct nfattr *nfa, int len);
1227+extern int nfnetlink_send(struct sk_buff *skb, u32 pid, unsigned group, 
1228+			  int echo);
1229+
1230+#endif	/* __KERNEL__ */
1231+#endif	/* _NFNETLINK_H */
1232diff -Nru linuxppc-020802-newnat/include/linux/nfnetlink_conntrack.h linuxppc-020802-newnat14-ctnl/include/linux/nfnetlink_conntrack.h
1233--- linuxppc-020802-newnat/include/linux/nfnetlink_conntrack.h	Thu Jan  1 01:00:00 1970
1234+++ linuxppc-020802-newnat14-ctnl/include/linux/nfnetlink_conntrack.h	Fri Aug  2 16:09:29 2002
1235@@ -0,0 +1,84 @@
1236+#ifndef _NFNETLINK_CONNTRACK_H
1237+#define _NFNETLINK_CONNTRACK_H
1238+#include <linux/nfnetlink.h>
1239+#include <linux/netfilter_ipv4/ip_conntrack.h>
1240+//#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
1241+
1242+/* CTNETLINK for ip_conntrack */
1243+
1244+enum cntl_msg_types {
1245+	CTNL_MSG_NEWCONNTRACK,
1246+	CTNL_MSG_GETCONNTRACK,
1247+	CTNL_MSG_DELCONNTRACK,
1248+
1249+	CTNL_MSG_NEWEXPECT,
1250+	CTNL_MSG_GETEXPECT,
1251+	CTNL_MSG_DELEXPECT,
1252+	CTNL_MSG_CONFIRMEXPECT,
1253+
1254+	CTNL_MSG_COUNT,
1255+};
1256+
1257+/* ctnetlink attribute types.
1258+ */
1259+enum ctattr_type_t
1260+{
1261+        CTA_UNSPEC,     /* [none] I don't know (unspecified). */
1262+        CTA_ORIG,       /* [ip_conntrack_tuple] Original tuple. */
1263+        CTA_RPLY,       /* [ip_conntrack_tuple] Reply tuple. */
1264+        CTA_IIF,        /* [char] Input interface name (ie eth0). */
1265+        CTA_OIF,        /* [char] Output interface name (ie eth1). */
1266+        CTA_STATUS,     /* [unsigned long] Status of connection. */
1267+        CTA_INFO,       /* [unsigned long] Information (ctinfo). */
1268+        CTA_PROTOINFO,  /* [cta_proto] Protocol specific ct information. */
1269+        CTA_HELPINFO,   /* [cta_help] Helper specific information. */
1270+        CTA_NATINFO,    /* [cta_nat] Any NAT transformations. */
1271+	CTA_TIMEOUT,	/* [unsigne long] timer */
1272+
1273+	CTA_EXP_TIMEOUT,
1274+	CTA_EXP_TUPLE,	/* [ip_conntrack_tuple] Expected tuple */
1275+	CTA_EXP_MASK,	/* [ip_conntrack_tuple] Mask for EXP_TUPLE */
1276+	CTA_EXP_SEQNO,	/* [u_int32_t] sequence number */
1277+	CTA_EXP_PROTO,	/* [cta_exp_proto] */
1278+	CTA_EXP_HELP,	/* [cta_exp_help] */
1279+
1280+        CTA_MAX = CTA_EXP_HELP
1281+};
1282+
1283+/* Attribute specific data structures.
1284+ */
1285+
1286+#ifdef CONFIG_IP_NF_NAT_NEEDED
1287+#include <linux/netfilter_ipv4/ip_nat.h>
1288+struct cta_nat {
1289+	unsigned int num_manips;
1290+        struct ip_nat_info_manip manips[IP_NAT_MAX_MANIPS];
1291+};
1292+#endif /* CONFIG_IP_NF_NAT_NEEDED */
1293+
1294+struct cta_proto {
1295+	unsigned char num_proto;	/* Protocol number IPPROTO_X */
1296+	union ip_conntrack_proto proto;
1297+};
1298+
1299+struct cta_help {
1300+	struct ip_conntrack_tuple tuple;
1301+        struct ip_conntrack_tuple mask;
1302+	char name[31];			/* name of conntrack helper */
1303+	union ip_conntrack_help help;
1304+};
1305+
1306+/* ctnetlink multicast groups: reports any change of ctinfo,
1307+ * ctstatus, or protocol state change.
1308+ */
1309+#define NFGRP_IPV4_CT_TCP	0x01
1310+#define NFGRP_IPV4_CT_UDP	0x02
1311+#define NFGRP_IPV4_CT_ICMP	0x04
1312+#define NFGRP_IPV4_CT_OTHER 	0x08
1313+
1314+#define NFGRP_IPV6_CT_TCP       0x10
1315+#define NFGRP_IPV6_CT_UDP       0x20
1316+#define NFGRP_IPV6_CT_ICMP      0x40
1317+#define NFGRP_IPV6_CT_OTHER 	0x80
1318+
1319+#endif /* _NFNETLINK_CONNTRACK_H */
1320