1/*	$NetBSD: ipsec_osdep.h,v 1.22 2008/01/20 18:09:12 joerg Exp $	*/
2/*	$FreeBSD: /repoman/r/ncvs/src/sys/netipsec/ipsec_osdep.h,v 1.1 2003/09/29 22:47:45 sam Exp $	*/
3
4/*
5 * Copyright (c) 2003 Jonathan Stone (jonathan@cs.stanford.edu)
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
25 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#ifndef _NETIPSEC_OSDEP_H_
30#define _NETIPSEC_OSDEP_H_
31
32#ifdef _KERNEL
33/*
34 *  Hide porting differences across different 4.4BSD-derived platforms.
35 *
36 * 1.  KASSERT() differences:
37 * 2.  Kernel  Random-number API differences.
38 * 3.  Is packet data in an mbuf object writeable?
39 * 4.  Packet-header semantics.
40 * 5.  Fast mbuf-cluster allocation.
41 * 6.  Network packet-output macros.
42 * 7.  Elased time, in seconds.
43 * 8.  Test if a  socket object opened by  a privileged (super) user.
44 * 9.  Global SLIST of all open raw sockets.
45 * 10. Global SLIST of known interface addresses.
46 * 11. Type of initialization functions.
47 * 12. Byte order of ip_off
48 */
49
50/*
51 *  1. KASSERT and spl differences
52 *
53 * FreeBSD takes an expression and  parenthesized printf() argument-list.
54 * NetBSD takes one arg: the expression being asserted.
55 * FreeBSD's SPLASSERT() takes an SPL level as 1st arg and a
56 * parenthesized printf-format argument list as the second argument.
57 *
58 * This difference is hidden by two 2-argument macros and one 1-arg macro:
59 *    IPSEC_ASSERT(expr, msg)
60 *    IPSEC_SPLASSERT(spl, msg)
61 * One further difference is the spl names:
62 *    NetBSD splsoftnet equates to FreeBSD splnet;
63 *    NetBSD splnet equates to FreeBSD splimp.
64 * which is hidden by the macro IPSEC_SPLASSERT_SOFTNET(msg).
65 */
66#ifdef __FreeBSD__
67#define IPSEC_SPLASSERT(x,y) SPLASSERT(x, y)
68#define IPSEC_ASSERT(c,m) KASSERT(c, m)
69#define IPSEC_SPLASSERT_SOFTNET(m) SPLASSERT(splnet, m)
70#endif	/* __FreeBSD__ */
71
72#ifdef	__NetBSD__
73#define IPSEC_SPLASSERT(x,y) (void)0
74#define IPSEC_ASSERT(c,m) KASSERT(c)
75#define IPSEC_SPLASSERT_SOFTNET(m) IPSEC_SPLASSERT(softnet, m)
76#endif	/* __NetBSD__ */
77
78/*
79 * 2. Kernel Randomness API.
80 * FreeBSD uses:
81 *    u_int read_random(void *outbuf, int nbytes).
82 */
83#ifdef __FreeBSD__
84#include <sys/random.h>
85/* do nothing, use native random code. */
86#endif /* __FreeBSD__ */
87
88#ifdef	__NetBSD__
89#include <sys/cprng.h>
90static __inline u_int read_random(void *p, u_int len);
91
92static __inline u_int
93read_random(void *bufp, u_int len)
94{
95	return cprng_fast(bufp, len);
96}
97#endif	/* __NetBSD__ */
98
99/*
100 * 3. Test for mbuf mutability
101 * FreeBSD 4.x uses: M_EXT_WRITABLE
102 * NetBSD has M_READONLY(). Use !M_READONLY().
103 * Not an exact match to FreeBSD semantics, but adequate for IPsec purposes.
104 *
105 */
106#ifdef __NetBSD__
107/* XXX wrong, but close enough for restricted ipsec usage. */
108#define M_EXT_WRITABLE(m) (!M_READONLY(m))
109#endif	/* __NetBSD__ */
110
111/*
112 * 4. mbuf packet-header/packet-tag semantics.
113 */
114/*
115 * nothing.
116 */
117
118/*
119 * 5. Fast mbuf-cluster allocation.
120 */
121/*
122 * nothing.
123 */
124
125/*
126 * 6. Network output macros
127 * FreeBSD uses the  IF_HANDOFF(), which raises SPL, enqueues
128 * a packet, and updates interface counters. NetBSD has IFQ_ENQUE(),
129 * which leaves SPL changes up to the caller.
130 * For now, we provide an emulation of IF_HANOOFF() which works
131 * for protocol input queues.
132 */
133#ifdef __FreeBSD__
134/* nothing to do */
135#endif /* __FreeBSD__ */
136#ifdef __NetBSD__
137#define IF_HANDOFF(ifq, m, f) if_handoff(ifq, m, f, 0)
138
139#include <net/if.h>
140
141static __inline int
142if_handoff(struct ifqueue *ifq, struct mbuf *m, struct ifnet *ifp, int adjust)
143{
144	int need_if_start = 0;
145	int s = splnet();
146
147	if (IF_QFULL(ifq)) {
148		IF_DROP(ifq);
149		splx(s);
150		m_freem(m);
151		return (0);
152	}
153	if (ifp != NULL) {
154		ifp->if_obytes += m->m_pkthdr.len + adjust;
155		if (m->m_flags & M_MCAST)
156			ifp->if_omcasts++;
157		need_if_start = !(ifp->if_flags & IFF_OACTIVE);
158	}
159	IF_ENQUEUE(ifq, m);
160	if (need_if_start)
161		(*ifp->if_start)(ifp);
162	splx(s);
163	return (1);
164}
165#endif /* __NetBSD__ */
166
167/*
168 * 7. Elapsed Time: time_second as time in seconds.
169 * Original FreeBSD fast-ipsec code references a FreeBSD kernel global,
170 * time_second().
171 * XXX is this the right time scale - shouldn't we measure timeout/life times
172 * using a monotonic time scale (time_uptime, mono_time) - why if the FreeBSD
173 * base code using UTC based time for this ?
174 */
175
176/* protosw glue */
177#ifdef __NetBSD__
178#include <sys/protosw.h>
179#define ipprotosw protosw
180#endif	/* __NetBSD__ */
181
182/*
183 * 8. Test for "privileged" socket opened by superuser.
184 * FreeBSD tests  ((so)->so_cred && (so)->so_cred.cr_uid == 0),
185 * NetBSD (1.6N) tests (so)->so_uid == 0).
186 * This difference is wrapped inside  the IPSEC_PRIVILEGED_SO() macro.
187 *
188 */
189#ifdef __FreeBSD__
190#define IPSEC_PRIVILEGED_SO(so) ((so)->so_cred && (so)->so_cred.cr_uid == 0)
191#endif	/* __FreeBSD__ */
192
193#ifdef __NetBSD__
194/* superuser opened socket? */
195#define IPSEC_PRIVILEGED_SO(so) ((so)->so_uidinfo->ui_uid == 0)
196#endif	/* __NetBSD__ */
197
198/*
199 * 9. Raw socket list
200 * FreeBSD uses: listhead = rawcb_list, SLIST()-next field "list".
201 * NetBSD  uses: listhead = rawcb, SLIST()-next field "list"
202 *
203 * This version of fast-ipsec source code  uses rawcb_list as the head,
204 *  and (to avoid namespace collisions) uses rcb_list as the "next" field.
205 */
206#ifdef __FreeBSD__
207#define rcb_list list
208#endif /* __FreeBSD__ */
209#ifdef __NetBSD__
210#define rawcb_list rawcb
211#endif	/* __NetBSD__ */
212
213
214/*
215 * 10. List of all known network interfaces.
216 * FreeBSD has listhead in_ifaddrhead, with ia_link as link.
217 * NetBSD has listhead in_ifaddr, with ia_list as link.
218 * No name-clahses, so just #define the appropriate names on NetBSD.
219 * NB: Is it worth introducing iterator (find-first-list/find-next-list)
220 * functions or macros to encapsulate these?
221 */
222#ifdef __FreeBSD__
223/* nothing to do for raw interface list */
224#endif	/* FreeBSD */
225#ifdef __NetBSD__
226#define ia_link ia_list
227#endif	/* __NetBSD__ */
228
229/*
230 * 11.  Type of initialization functions.
231 */
232#ifdef __FreeBSD__
233#define INITFN static
234#endif
235#ifdef __NetBSD__
236#define INITFN extern
237#endif
238
239/* 12. On FreeBSD, ip_off  assumed in host endian;
240 * it is converted (if necessary) by ip_input().
241 * On NetBSD, ip_off is in network byte order.
242 * We hide the difference with the macro IP_OFF_CONVERT
243 */
244
245#ifdef __FreeBSD__
246#define IP_OFF_CONVERT(x) (x)
247#endif
248
249#ifdef __NetBSD__
250#define IP_OFF_CONVERT(x) (htons(x))
251#endif
252
253/*
254 * 13. IPv6 support, and "generic" inpcb vs. IPv4 pcb vs. IPv6 pcb.
255 * To IPv6 V4-mapped addresses (and the KAME-derived implementation
256 * of IPv6 v4-mapped addresses)  we must support limited polymorphism:
257 * partway down the stack we detect an IPv6 protocol address is really
258 * a mapped V4 address, and then start dispatching that address to
259 * native IPv4 PCB lookup. In KAME-derived IPsec (including fas-ipsec)
260 * some functions must handle arguments which (dynamically) may be either
261 * a IPv4 pcb (struct inpcb *) or an IPv6 pcb (struct in6pcb *).
262 *
263 * In FreeBSD 4.x, sgtrucr in6pcb is syntactic sugar for struct inpcb,
264 * so punning between struct inpcb* and struct in6pcb* is trivial.
265 * NetBSD until recently used completely different structs for IPv4
266 * and IPv6 PCBs. To simplify fast-ipsec coexisting with IPv6,
267 * NetBSD's struct inpcb and struct in6pcb were changed to both have
268 * common struct, struct inpcb_hdr, as their first member.  NetBSD can
269 * thus pass arguments as struct inpcb_hdr*, and dispatch on a v4/v6
270 * flag in the inpcb_hdr at runtime.
271 *
272 * We hide the NetBSD-vs-FreeBSD differences inside the following abstraction:
273 *
274 *  PCB_T:  a macro name for a struct type which is used as a "generic"
275 *      argument for actual arguments  an in4pcb or an in6pcb.
276 *
277 * PCB_FAMILY(p): given a "generic" pcb_t p, returns the protocol
278 *	family (AF_INET, AF_INET6) of the unperlying inpcb/in6pcb.
279 *
280 * PCB_SOCKET(p): given a "generic" pcb_t p, returns the associated
281 *	socket pointer
282 *
283 * PCB_TO_IN4PCB(p): given generic pcb_t *p, returns a struct inpcb *
284 * PCB_TO_IN6PCB(p): given generic pcb_t *p, returns a struct in6pcb *
285 *
286 * IN4PCB_TO_PCB(inp):  given a struct inpcb *inp,   returns a pcb_t *
287 * IN6PCB_TO_PCB(in6p): given a struct in6pcb *in6p, returns a pcb_t *
288 */
289#ifdef __FreeBSD__
290#define PCB_T		struct inpcb
291#define PCB_FAMILY(p)	((p)->inp_socket->so_proto->pr_domain->dom_family)
292#define	PCB_SOCKET(p)	((p)->inp_socket)
293
294/* Convert generic pcb to IPv4/IPv6 pcb */
295#define PCB_TO_IN4PCB(p) (p)
296#define PCB_TO_IN6PCB(p) (p)
297
298/* Convert IPv4/IPv6 pcb to generic pcb, for callers of fast-ipsec */
299#define IN4PCB_TO_PCB(p) (p)
300#define IN6PCB_TO_PCB(p) (p)
301#endif	/* __FreeBSD__ */
302
303#ifdef __NetBSD__
304#define PCB_T		struct inpcb_hdr
305#define PCB_FAMILY(p)	((p)->inph_af)
306#define PCB_SOCKET(p)	((p)->inph_socket)
307
308#define PCB_TO_IN4PCB(p) ((struct inpcb *)(p))
309#define PCB_TO_IN6PCB(p) ((struct in6pcb *)(p))
310
311#define IN4PCB_TO_PCB(p) ((PCB_T *)(&(p)->inp_head))
312#define IN6PCB_TO_PCB(p) ((PCB_T *)(&(p)->in6p_head))
313#endif	/* __NetBSD__ */
314
315/*
316 * Differences that we don't attempt to hide:
317 *
318 * A. Initialization code.  This  is the largest difference of all.
319 *
320 *   FreeBSD uses compile/link-time perl hackery to generate special
321 * .o files  with linker sections  that give the moral equivalent of
322 * C++ file-level-object constructors. NetBSD has no such facility.
323 *
324 * Either we implement it (ideally, in a way that can emulate
325 * FreeBSD's SYSINIT() macros), or we must take other means
326 * to have the per-file init functions called at some appropriate time.
327 *
328 * In the absence of SYSINIT(), all the file-level init functions
329 * now have "extern" linkage. There is a new fast-ipsec init()
330 * function which calls each of the per-file in an appropriate order.
331 * init_main will arrange to call the fast-ipsec init function
332 * after the crypto framework has registered its transforms (including
333 * any autoconfigured hardware crypto  accelerators) but before
334 * initializing the network stack to send or receive  packet.
335 *
336 * B. Protosw() differences.
337 * CSRG-style BSD TCP/IP uses a generic protocol-dispatch-function
338 * where the specific request is identified by an enum argument.
339 * FreeBSD replaced that with an array of request-specific
340 * function pointers.
341 *
342 * These differences affect the handlers for key-protocol user requests
343 * so pervasively that I gave up on the fast-ipsec code, and re-worked the
344 * NetBSD KAME code to match the (relative few) API differences
345 * between NetBSD and FreeBSD's KAME netkey, and Fast-IPsec netkey.
346 *
347 * C. Timeout() versus callout(9):
348 * The FreeBSD 4.x netipsec/ code still uses timeout().
349 * FreeBSD 4.7 has callout(9), so I just replaced
350 * timeout_*() with the nearest callout_*() equivalents,
351 * and added a callout handle to the ipsec context.
352 *
353 * D. SPL name differences.
354 * FreeBSD splnet() equates directly to NetBSD's splsoftnet();
355 * FreeBSD uses splimp() where (for networking) NetBSD would use splnet().
356 */
357#endif /* _KERNEL */
358#endif /* !_NETIPSEC_OSDEP_H_ */
359