| 1 | /* $NetBSD: ipsec_osdep.h,v 1.26 2016/06/22 10:44:32 knakahara 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> |
| 90 | static __inline u_int read_random(void *p, u_int len); |
| 91 | |
| 92 | static __inline u_int |
| 93 | read_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 | |
| 141 | static __inline int |
| 142 | if_handoff(struct ifqueue *ifq, struct mbuf *m, struct ifnet *ifp, int adjust) |
| 143 | { |
| 144 | int s = splnet(); |
| 145 | |
| 146 | KERNEL_LOCK(1, NULL); |
| 147 | if (IF_QFULL(ifq)) { |
| 148 | IF_DROP(ifq); |
| 149 | KERNEL_UNLOCK_ONE(NULL); |
| 150 | splx(s); |
| 151 | m_freem(m); |
| 152 | return (0); |
| 153 | } |
| 154 | if (ifp != NULL) |
| 155 | (void)if_transmit_lock(ifp, m); |
| 156 | |
| 157 | KERNEL_UNLOCK_ONE(NULL); |
| 158 | splx(s); |
| 159 | return (1); |
| 160 | } |
| 161 | #endif /* __NetBSD__ */ |
| 162 | |
| 163 | /* |
| 164 | * 7. Elapsed Time: time_second as time in seconds. |
| 165 | * Original FreeBSD fast-ipsec code references a FreeBSD kernel global, |
| 166 | * time_second(). |
| 167 | * XXX is this the right time scale - shouldn't we measure timeout/life times |
| 168 | * using a monotonic time scale (time_uptime, mono_time) - why if the FreeBSD |
| 169 | * base code using UTC based time for this ? |
| 170 | */ |
| 171 | |
| 172 | /* protosw glue */ |
| 173 | #ifdef __NetBSD__ |
| 174 | #include <sys/protosw.h> |
| 175 | #define ipprotosw protosw |
| 176 | #endif /* __NetBSD__ */ |
| 177 | |
| 178 | /* |
| 179 | * 8. Test for "privileged" socket opened by superuser. |
| 180 | * FreeBSD tests ((so)->so_cred && (so)->so_cred.cr_uid == 0), |
| 181 | * NetBSD (1.6N) tests (so)->so_uid == 0). |
| 182 | * This difference is wrapped inside the IPSEC_PRIVILEGED_SO() macro. |
| 183 | * |
| 184 | */ |
| 185 | #ifdef __FreeBSD__ |
| 186 | #define IPSEC_PRIVILEGED_SO(so) ((so)->so_cred && (so)->so_cred.cr_uid == 0) |
| 187 | #endif /* __FreeBSD__ */ |
| 188 | |
| 189 | #ifdef __NetBSD__ |
| 190 | /* superuser opened socket? */ |
| 191 | #define IPSEC_PRIVILEGED_SO(so) ((so)->so_uidinfo->ui_uid == 0) |
| 192 | #endif /* __NetBSD__ */ |
| 193 | |
| 194 | /* |
| 195 | * 9. Raw socket list |
| 196 | * FreeBSD uses: listhead = rawcb_list, SLIST()-next field "list". |
| 197 | * NetBSD uses: listhead = rawcb, SLIST()-next field "list" |
| 198 | * |
| 199 | * This version of fast-ipsec source code uses rawcb_list as the head, |
| 200 | * and (to avoid namespace collisions) uses rcb_list as the "next" field. |
| 201 | */ |
| 202 | #ifdef __FreeBSD__ |
| 203 | #define rcb_list list |
| 204 | #endif /* __FreeBSD__ */ |
| 205 | #ifdef __NetBSD__ |
| 206 | #define rawcb_list rawcb |
| 207 | #endif /* __NetBSD__ */ |
| 208 | |
| 209 | |
| 210 | /* |
| 211 | * 10. List of all known network interfaces. |
| 212 | * FreeBSD has listhead in_ifaddrhead, with ia_link as link. |
| 213 | * NetBSD has listhead in_ifaddr, with ia_list as link. |
| 214 | * No name-clahses, so just #define the appropriate names on NetBSD. |
| 215 | * NB: Is it worth introducing iterator (find-first-list/find-next-list) |
| 216 | * functions or macros to encapsulate these? |
| 217 | */ |
| 218 | #ifdef __FreeBSD__ |
| 219 | /* nothing to do for raw interface list */ |
| 220 | #endif /* FreeBSD */ |
| 221 | #ifdef __NetBSD__ |
| 222 | #define ia_link ia_list |
| 223 | #endif /* __NetBSD__ */ |
| 224 | |
| 225 | /* |
| 226 | * 11. Type of initialization functions. |
| 227 | */ |
| 228 | #ifdef __FreeBSD__ |
| 229 | #define INITFN static |
| 230 | #endif |
| 231 | #ifdef __NetBSD__ |
| 232 | #define INITFN extern |
| 233 | #endif |
| 234 | |
| 235 | /* 12. On FreeBSD, ip_off assumed in host endian; |
| 236 | * it is converted (if necessary) by ip_input(). |
| 237 | * On NetBSD, ip_off is in network byte order. |
| 238 | * We hide the difference with the macro IP_OFF_CONVERT |
| 239 | */ |
| 240 | |
| 241 | #ifdef __FreeBSD__ |
| 242 | #define IP_OFF_CONVERT(x) (x) |
| 243 | #endif |
| 244 | |
| 245 | #ifdef __NetBSD__ |
| 246 | #define IP_OFF_CONVERT(x) (htons(x)) |
| 247 | #endif |
| 248 | |
| 249 | /* |
| 250 | * 13. IPv6 support, and "generic" inpcb vs. IPv4 pcb vs. IPv6 pcb. |
| 251 | * To IPv6 V4-mapped addresses (and the KAME-derived implementation |
| 252 | * of IPv6 v4-mapped addresses) we must support limited polymorphism: |
| 253 | * partway down the stack we detect an IPv6 protocol address is really |
| 254 | * a mapped V4 address, and then start dispatching that address to |
| 255 | * native IPv4 PCB lookup. In KAME-derived IPsec (including fas-ipsec) |
| 256 | * some functions must handle arguments which (dynamically) may be either |
| 257 | * a IPv4 pcb (struct inpcb *) or an IPv6 pcb (struct in6pcb *). |
| 258 | * |
| 259 | * In FreeBSD 4.x, sgtrucr in6pcb is syntactic sugar for struct inpcb, |
| 260 | * so punning between struct inpcb* and struct in6pcb* is trivial. |
| 261 | * NetBSD until recently used completely different structs for IPv4 |
| 262 | * and IPv6 PCBs. To simplify fast-ipsec coexisting with IPv6, |
| 263 | * NetBSD's struct inpcb and struct in6pcb were changed to both have |
| 264 | * common struct, struct inpcb_hdr, as their first member. NetBSD can |
| 265 | * thus pass arguments as struct inpcb_hdr*, and dispatch on a v4/v6 |
| 266 | * flag in the inpcb_hdr at runtime. |
| 267 | * |
| 268 | * We hide the NetBSD-vs-FreeBSD differences inside the following abstraction: |
| 269 | * |
| 270 | * PCB_T: a macro name for a struct type which is used as a "generic" |
| 271 | * argument for actual arguments an in4pcb or an in6pcb. |
| 272 | * |
| 273 | * PCB_FAMILY(p): given a "generic" pcb_t p, returns the protocol |
| 274 | * family (AF_INET, AF_INET6) of the unperlying inpcb/in6pcb. |
| 275 | * |
| 276 | * PCB_SOCKET(p): given a "generic" pcb_t p, returns the associated |
| 277 | * socket pointer |
| 278 | * |
| 279 | * PCB_TO_IN4PCB(p): given generic pcb_t *p, returns a struct inpcb * |
| 280 | * PCB_TO_IN6PCB(p): given generic pcb_t *p, returns a struct in6pcb * |
| 281 | * |
| 282 | * IN4PCB_TO_PCB(inp): given a struct inpcb *inp, returns a pcb_t * |
| 283 | * IN6PCB_TO_PCB(in6p): given a struct in6pcb *in6p, returns a pcb_t * |
| 284 | */ |
| 285 | #ifdef __FreeBSD__ |
| 286 | #define PCB_T struct inpcb |
| 287 | #define PCB_FAMILY(p) ((p)->inp_socket->so_proto->pr_domain->dom_family) |
| 288 | #define PCB_SOCKET(p) ((p)->inp_socket) |
| 289 | |
| 290 | /* Convert generic pcb to IPv4/IPv6 pcb */ |
| 291 | #define PCB_TO_IN4PCB(p) (p) |
| 292 | #define PCB_TO_IN6PCB(p) (p) |
| 293 | |
| 294 | /* Convert IPv4/IPv6 pcb to generic pcb, for callers of fast-ipsec */ |
| 295 | #define IN4PCB_TO_PCB(p) (p) |
| 296 | #define IN6PCB_TO_PCB(p) (p) |
| 297 | #endif /* __FreeBSD__ */ |
| 298 | |
| 299 | #ifdef __NetBSD__ |
| 300 | #define PCB_T struct inpcb_hdr |
| 301 | #define PCB_FAMILY(p) ((p)->inph_af) |
| 302 | #define PCB_SOCKET(p) ((p)->inph_socket) |
| 303 | |
| 304 | #define PCB_TO_IN4PCB(p) ((struct inpcb *)(p)) |
| 305 | #define PCB_TO_IN6PCB(p) ((struct in6pcb *)(p)) |
| 306 | |
| 307 | #define IN4PCB_TO_PCB(p) ((PCB_T *)(&(p)->inp_head)) |
| 308 | #define IN6PCB_TO_PCB(p) ((PCB_T *)(&(p)->in6p_head)) |
| 309 | #endif /* __NetBSD__ */ |
| 310 | |
| 311 | /* |
| 312 | * Differences that we don't attempt to hide: |
| 313 | * |
| 314 | * A. Initialization code. This is the largest difference of all. |
| 315 | * |
| 316 | * FreeBSD uses compile/link-time perl hackery to generate special |
| 317 | * .o files with linker sections that give the moral equivalent of |
| 318 | * C++ file-level-object constructors. NetBSD has no such facility. |
| 319 | * |
| 320 | * Either we implement it (ideally, in a way that can emulate |
| 321 | * FreeBSD's SYSINIT() macros), or we must take other means |
| 322 | * to have the per-file init functions called at some appropriate time. |
| 323 | * |
| 324 | * In the absence of SYSINIT(), all the file-level init functions |
| 325 | * now have "extern" linkage. There is a new fast-ipsec init() |
| 326 | * function which calls each of the per-file in an appropriate order. |
| 327 | * init_main will arrange to call the fast-ipsec init function |
| 328 | * after the crypto framework has registered its transforms (including |
| 329 | * any autoconfigured hardware crypto accelerators) but before |
| 330 | * initializing the network stack to send or receive packet. |
| 331 | * |
| 332 | * B. Protosw() differences. |
| 333 | * CSRG-style BSD TCP/IP uses a generic protocol-dispatch-function |
| 334 | * where the specific request is identified by an enum argument. |
| 335 | * FreeBSD replaced that with an array of request-specific |
| 336 | * function pointers. |
| 337 | * |
| 338 | * These differences affect the handlers for key-protocol user requests |
| 339 | * so pervasively that I gave up on the fast-ipsec code, and re-worked the |
| 340 | * NetBSD KAME code to match the (relative few) API differences |
| 341 | * between NetBSD and FreeBSD's KAME netkey, and Fast-IPsec netkey. |
| 342 | * |
| 343 | * C. Timeout() versus callout(9): |
| 344 | * The FreeBSD 4.x netipsec/ code still uses timeout(). |
| 345 | * FreeBSD 4.7 has callout(9), so I just replaced |
| 346 | * timeout_*() with the nearest callout_*() equivalents, |
| 347 | * and added a callout handle to the ipsec context. |
| 348 | * |
| 349 | * D. SPL name differences. |
| 350 | * FreeBSD splnet() equates directly to NetBSD's splsoftnet(); |
| 351 | * FreeBSD uses splimp() where (for networking) NetBSD would use splnet(). |
| 352 | */ |
| 353 | #endif /* _KERNEL */ |
| 354 | #endif /* !_NETIPSEC_OSDEP_H_ */ |
| 355 | |