Subject: Re: CVS commit: src/sys
To: Jason Thorpe <thorpej@wasabisystems.com>
From: Jonathan Stone <jonathan@DSG.Stanford.EDU>
List: tech-net
Date: 08/24/2003 11:42:42
[moved from source-changes]

There is a technical issue with IPv4-mapped v6 addresses being passed
downward, through TCP (or UDP), into ip_output and thus into IPsec.
The IPsec code (whichever flavour) then has to look up an appropriate
policy for a v6 in6pcb or a v4 inpcb, respectively.

The reason for this is that IPsec state is cached in the pcb
(either in6pcb or inpcb). But in NetBSD, those structures are different.
programming-language terms, the interface is polymorphic.

Instead of passing the object that IPsec wants -- the pcb,
specifically the inp_sp or in6p_sp_ -- KAME code passes a handle to
that object, namely, the struct socket*.

The way I see it, passing handles is a kludge, the kind of thing which
should not have gone into the tree in the first place.

Again, the way I see it, the right way to do this is for the portions
of the inpcb which need to be shared between ip4 and ipv6, is to make
the necessarily-shared state to in fact be common.  Diffs to achieve
this this aren't pretty, but I submit that passing around handles
isn't a good solution, ether.

The code below is a sample of what I'm suggesting, as a compromise.
(If the V6 code had been written according the policy of the NetBSD
project in the first place, such a shim wouldn't be necessary.)

Jason,

Whatever happens, netinet6/in6_pcb.h should be fixed. It just doesn't
pass muster.  Have you looked at the layout of fields within struct in6pcb?



struct inpcb_hdr {
	/*
	 * KAME does not follow use sys/queue.h, or share
	 * common PCB hash links with INET(4), so we need a union of
	 * disjoint inpcb and in6pcb link fields even for the header.
	 */
	union	{
		struct {
			LIST_ENTRY(inpcb) hdru4_hash;
			CIRCLEQ_ENTRY(inpcb) hdru4_queue;
		} hdru_in4pcb;
		struct {
			struct	in6pcb *hdru6_next, *hdru6_prev;
					/* pointers to other pcb's */
			struct	in6pcb *hdru6_head;
		  			/* pointer back to chain of
					   in6pcb's for this protocol */
		} hdru_in6pcb;
	} hdr_u;
	struct socket *inphdr_socket;
	struct inpcbpolicy *inphdr_sp;	/* security policy. */
	caddr_t	inphdr_ppcb;		/* pointer to per-protocol pcb */
	/* XXX these  are commom but are they worth sharing? */
	u_int16_t inphdr_fport;		/* foreign port */
	u_int16_t inphdr_lport;		/* local port */
};

/* inet4 compatibility names */
#ifdef INET
#define inp_hash	inphdr.hdr_u.hdru_in4pcb.hdru4_hash
#define inp_queue	inphdr.hdr_u.hdru_in4pcb.hdru4_queue
#define inp_ppcb	inphdr.inphdr_ppcb
#define inp_socket	inphdr.inphdr_socket
#define inp_sp		inphdr.inphdr_sp
#define	inp_fport	inphdr.inphdr_fport
#define	inp_lport	inphdr.inphdr_lport
#endif

/* inet6 compatibility names */
#ifdef INET6
#define in6p_next	inphdr.hdr_u.hdru_in6pcb.hdru6_next
#define in6p_prev	inphdr.hdr_u.hdru_in6pcb.hdru6_prev
#define in6p_head	inphdr.hdr_u.hdru_in6pcb.hdru6_head
#define in6p_ppcb	inphdr.inphdr_ppcb
#define in6p_socket	inphdr.inphdr_socket
#define in6p_sp		inphdr.inphdr_sp
#define in6p_fport	inphdr.inphdr_fport
#define in6p_lport	inphdr.inphdr_lport
#endif

#endif /* __NETINET_IN_PCB_COMMON_H__ */