X-Git-Url: http://git.onelab.eu/?p=ipfw.git;a=blobdiff_plain;f=glue.h;h=622ca4bf3ee319a4f276cc327d3de35365851bb4;hp=de0ab23ff59352b0d9ddd14026af1d94e8f099a2;hb=HEAD;hpb=4e189c94aef3d3e9a4e8edfd2bb989feeb5d5e26 diff --git a/glue.h b/glue.h index de0ab23..622ca4b 100644 --- a/glue.h +++ b/glue.h @@ -23,18 +23,22 @@ * SUCH DAMAGE. */ /* - * $Id: glue.h 4661 2010-01-04 11:56:12Z luigi $ + * $Id: glue.h 11277 2012-06-10 17:44:15Z marta $ * * glue code to adapt the FreeBSD version to linux and windows, * userland and kernel. * This is included before any other headers, so we do not have * a chance to override any #define that should appear in other * headers. + * First handle headers for userland and kernel. Then common code + * (including headers that require a specific order of inclusion), + * then the user- and kernel- specific parts. */ #ifndef _GLUE_H #define _GLUE_H + /* * common definitions to allow portability */ @@ -42,26 +46,29 @@ #define __FBSDID(x) #endif /* FBSDID */ -/* - * emulation of FreeBSD's sockopt and thread - * This was in sockopt.h - */ -enum sopt_dir { SOPT_GET, SOPT_SET }; +#ifndef KERNEL_MODULE /* Userland headers */ -#ifndef KERNEL_MODULE /* Userland part */ +#if defined(__CYGWIN32__) && !defined(_WIN32) +#define _WIN32 +#endif -#include /* linux needs this in addition to sys/types.h */ +#if defined(TCC) && defined(_WIN32) +#include +#endif /* TCC */ -#include /* for size_t */ +#include /* linux needs it in addition to sys/types.h */ +#include /* for size_t */ #include #include #include +#ifdef __linux__ +#include /* linux only 20111031 */ +#endif -#include +#else /* KERNEL_MODULE, kernel headers */ -#else /* KERNEL_MODULE, kernel part */ +#ifdef __linux__ -#ifndef _WIN32 #include #define ifnet net_device /* remap */ @@ -72,18 +79,22 @@ enum sopt_dir { SOPT_GET, SOPT_SET }; #include /* linux kernel */ #include /* linux kernel */ - #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) // or 2.4.x #include /* linux/msg.h require this */ #include /* just MAX_ADDR_LEN 8 on 2.4 32 on 2.6, also brings in byteorder */ #endif -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) && \ - LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) // under 2.6.22 compilation is required by msg.h +/* on 2.6.22, msg.h requires spinlock_types.h */ +/* XXX spinlock_type.h was introduced in 2.6.14 */ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13) && \ + LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) #include #endif -#include /* XXX m_type define conflict with include/sys/mbuf.h, - * so early include this file (to be solved) */ +/* XXX m_type define conflict with include/sys/mbuf.h, + * so early include msg.h (to be solved) +*/ +#include + #include #include /* struct in_addr */ #include /* struct in6_addr */ @@ -94,61 +105,148 @@ enum sopt_dir { SOPT_GET, SOPT_SET }; */ #undef LIST_HEAD -#define IF_NAMESIZE 16 -typedef uint32_t in_addr_t; +#define IF_NAMESIZE (16) +typedef uint32_t in_addr_t; #define printf(fmt, arg...) printk(KERN_ERR fmt, ##arg) +#endif /* __linux__ */ + +#endif /* KERNEL_MODULE end of kernel headers */ + + +/* + * Part 2: common userland and kernel definitions + */ + +#ifndef ETHER_ADDR_LEN +#define ETHER_ADDR_LEN (6+0) /* length of an Ethernet address */ +#endif + +#define ICMP6_DST_UNREACH_NOROUTE 0 /* no route to destination */ +#define ICMP6_DST_UNREACH_ADMIN 1 /* administratively prohibited */ +#define ICMP6_DST_UNREACH_ADDR 3 /* address unreachable */ +#define ICMP6_DST_UNREACH_NOPORT 4 /* port unreachable */ + +/* + * linux: sysctl are mapped into /sys/module/ipfw_mod parameters + * windows: they are emulated via get/setsockopt + */ +#define CTLFLAG_RD 1 +#define CTLFLAG_RDTUN 1 +#define CTLFLAG_RW 2 +#define CTLFLAG_SECURE3 0 // unsupported +#define CTLFLAG_VNET 0 /* unsupported */ -#endif /* !_WIN32 */ -#endif /* KERNEL_MODULE */ +/* if needed, queue.h must be included here after list.h */ /* + * struct thread is used in linux and windows kernel. * In windows, we need to emulate the sockopt interface * so also the userland needs to have the struct sockopt defined. - * No need to declare struct thread on linux, but we need on windows. + * In order to achieve 64 bit compatibility, padding has been inserted. */ - struct thread { void *sopt_td; void *td_ucred; }; +enum sopt_dir { SOPT_GET, SOPT_SET }; + struct sockopt { enum sopt_dir sopt_dir; /* is this a get or a set? */ int sopt_level; /* second arg of [gs]etsockopt */ int sopt_name; /* third arg of [gs]etsockopt */ - void *sopt_val; /* fourth arg of [gs]etsockopt */ - size_t sopt_valsize; /* (almost) fifth arg of [gs]etsockopt */ - struct thread *sopt_td; /* calling thread or null if kernel */ +#ifdef _X64EMU + void* pad1; + void* pad2; +#endif + void *sopt_val; /* fourth arg of [gs]etsockopt */ + size_t sopt_valsize; /* (almost) fifth arg of [gs]etsockopt */ +#ifdef _X64EMU + void* pad3; + void* pad4; +#endif + struct thread *sopt_td; /* calling thread or null if kernel */ }; -/* This must be included here after list.h */ -#include /* both the kernel side and nat.c needs this */ +#define INET_ADDRSTRLEN (16) /* missing in netinet/in.h */ + +/* + * List of values used for set/getsockopt options. + * The base value on FreeBSD is defined as a macro, + * if not available we will use our own enum. + * The TABLE_BASE value is used in the kernel. + */ +#ifndef IP_FW_TABLE_ADD +#define _IPFW_SOCKOPT_BASE 100 /* 40 on freebsd */ +enum ipfw_msg_type { + IP_FW_TABLE_ADD = _IPFW_SOCKOPT_BASE, + IP_FW_TABLE_DEL, + IP_FW_TABLE_FLUSH, + IP_FW_TABLE_GETSIZE, + IP_FW_TABLE_LIST, + IP_FW_DYN_GET, /* new addition */ + + /* IP_FW3 and IP_DUMMYNET3 are the new API */ + IP_FW3 = _IPFW_SOCKOPT_BASE + 8, + IP_DUMMYNET3, + + IP_FW_ADD = _IPFW_SOCKOPT_BASE + 10, + IP_FW_DEL, + IP_FW_FLUSH, + IP_FW_ZERO, + IP_FW_GET, + IP_FW_RESETLOG, + + IP_FW_NAT_CFG, + IP_FW_NAT_DEL, + IP_FW_NAT_GET_CONFIG, + IP_FW_NAT_GET_LOG, + + IP_DUMMYNET_CONFIGURE, + IP_DUMMYNET_DEL , + IP_DUMMYNET_FLUSH, + /* 63 is missing */ + IP_DUMMYNET_GET = _IPFW_SOCKOPT_BASE + 24, + _IPFW_SOCKOPT_END +}; +#endif /* IP_FW_TABLE_ADD */ + +/* + * Part 3: userland stuff + */ #ifndef KERNEL_MODULE -/* define internals for struct in6_addr netinet/in6.h on FreeBSD */ -#define __u6_addr in6_u -#define __u6_addr32 u6_addr32 -/* define missing type for ipv6 (linux 2.6.28) */ -#define in6_u __in6_u +/* + * internal names in struct in6_addr (netinet/in6.h) differ, + * so we remap the FreeBSD names to the platform-specific ones. + */ +#ifndef _WIN32 +#define __u6_addr in6_u +#define __u6_addr32 u6_addr32 +#define in6_u __in6_u /* missing type for ipv6 (linux 2.6.28) */ +#else /* _WIN32 uses different naming */ +#define __u6_addr __u6 +#define __u6_addr32 __s6_addr32 +#endif /* _WIN32 */ /* missing in linux netinet/ip.h */ -#define IPTOS_ECN_ECT0 0x02 /* ECN-capable transport (0) */ -#define IPTOS_ECN_CE 0x03 /* congestion experienced */ +#define IPTOS_ECN_ECT0 0x02 /* ECN-capable transport (0) */ +#define IPTOS_ECN_CE 0x03 /* congestion experienced */ /* defined in freebsd netinet/icmp6.h */ -#define ICMP6_MAXTYPE 201 +#define ICMP6_MAXTYPE 201 /* on freebsd sys/socket.h pf specific */ -#define NET_RT_IFLIST 3 /* survey interface list */ +#define NET_RT_IFLIST 3 /* survey interface list */ +#if defined(__linux__) || defined(__CYGWIN32__) /* on freebsd net/if.h XXX used */ struct if_data { - /* ... */ - u_long ifi_mtu; /* maximum transmission unit */ + u_long ifi_mtu; /* maximum transmission unit */ }; /* @@ -157,21 +255,21 @@ struct if_data { * This is used in nat.c */ struct if_msghdr { - u_short ifm_msglen; /* to skip over non-understood messages */ + u_short ifm_msglen; /* to skip over unknown messages */ u_char ifm_version; /* future binary compatibility */ u_char ifm_type; /* message type */ int ifm_addrs; /* like rtm_addrs */ int ifm_flags; /* value of if_flags */ u_short ifm_index; /* index for associated ifp */ - struct if_data ifm_data;/* statistics and other data about if */ + struct if_data ifm_data;/* stats and other ifdata */ }; /* - * Message format for use in obtaining information about interface addresses - * from getkerninfo and the routing socket + * Message format for use in obtaining information about interface + * addresses from getkerninfo and the routing socket */ struct ifa_msghdr { - u_short ifam_msglen; /* to skip over non-understood messages */ + u_short ifam_msglen; /* to skip over unknown messages */ u_char ifam_version; /* future binary compatibility */ u_char ifam_type; /* message type */ int ifam_addrs; /* like rtm_addrs */ @@ -206,12 +304,16 @@ struct clockinfo { int profhz; /* profiling clock frequency */ }; +/* no sin_len in sockaddr, we only remap in userland */ +#define sin_len sin_zero[0] + +#endif /* Linux/Win */ + /* * linux does not have a reentrant version of qsort, * so we the FreeBSD stdlib version. */ -void -qsort_r(void *a, size_t n, size_t es, void *thunk, +void qsort_r(void *a, size_t n, size_t es, void *thunk, int cmp_t(void *, const void *, const void *)); /* prototypes from libutil */ @@ -233,83 +335,246 @@ int expand_number(const char *_buf, int64_t *_num); extern int optreset; /* not present in linux */ size_t strlcpy(char * dst, const char * src, size_t siz); -long long int -strtonum(const char *nptr, long long minval, long long maxval, - const char **errstr); +long long int strtonum(const char *nptr, long long minval, + long long maxval, const char **errstr); -int -sysctlbyname(const char *name, void *oldp, size_t *oldlenp, void *newp, - size_t newlen); +int sysctlbyname(const char *name, void *oldp, size_t *oldlenp, + void *newp, size_t newlen); -#ifdef __linux__ -/* linux does not have sin_len in sockaddr, we only remap in userland */ -#define sin_len sin_zero[0] -#endif /* __linux__ */ #else /* KERNEL_MODULE */ +/* + * Part 4: kernel stuff + */ + /* linux and windows kernel do not have bcopy ? */ #define bcopy(_s, _d, _l) memcpy(_d, _s, _l) +/* definitions useful for the kernel side */ +struct route_in6 { + int dummy; +}; + +#ifdef __linux__ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) // or 2.4.x #include #endif -/* skb_dst() was introduced from linux 2.6.31 */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31) // or 2.4.x -#define skb_dst(_dummy) skb->dst +/* skb_dst() and skb_dst_set() was introduced from linux 2.6.31 */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31) +void skb_dst_set(struct sk_buff *skb, struct dst_entry *dst); +struct dst_entry *skb_dst(const struct sk_buff *skb); #endif -/* definitions useful for the kernel side */ +/* The struct flowi changed */ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38) // check boundaries +#define flow_daddr fl.u.ip4 +#else +#define flow_daddr fl.nl_u.ip4_u +#endif -struct route_in6 { }; +#endif /* __linux__ */ + +/* + * Do not load prio_heap.h header because of conflicting names + * with our heap functions defined in include/netinet/ipfw/dn_heap.h + */ +#define _LINUX_PRIO_HEAP_H +/* + * The following define prevent the ipv6.h header to be loaded. + * Starting from the 2.6.38 kernel the ipv6.h file, which is included + * by include/net/inetpeer.h in turn included by net/route.h + * include the system tcp.h file while we want to include + * our include/net/tcp.h instead. + */ +#ifndef _NET_IPV6_H +#define _NET_IPV6_H +static inline void ipv6_addr_copy(struct in6_addr *a1, const struct in6_addr *a2) +{ + memcpy(a1, a2, sizeof(struct in6_addr)); +} +#endif /* _NET_IPV6_H */ #endif /* KERNEL_MODULE */ -/* missing in netinet/in.h */ +/* + * Part 5: windows specific stuff + */ -#define INET_ADDRSTRLEN 16 +#ifdef _WIN32 +#ifndef KERNEL_MODULE +#define CTL_CODE( DeviceType, Function, Method, Access ) ( \ + ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \ +) + +#define METHOD_BUFFERED 0 +#define METHOD_IN_DIRECT 1 +#define METHOD_OUT_DIRECT 2 +#define METHOD_NEITHER 3 +#define FILE_ANY_ACCESS 0 +#define FILE_READ_DATA ( 0x0001 ) // file & pipe +#define FILE_WRITE_DATA ( 0x0002 ) // file & pipe +#endif /* !KERNEL_MODULE */ + +#define FILE_DEVICE_IPFW 0x00654324 +#define IP_FW_BASE_CTL 0x840 +#define IP_FW_SETSOCKOPT \ + CTL_CODE(FILE_DEVICE_IPFW, IP_FW_BASE_CTL + 1, METHOD_BUFFERED, FILE_WRITE_DATA) +#define IP_FW_GETSOCKOPT \ + CTL_CODE(FILE_DEVICE_IPFW, IP_FW_BASE_CTL + 2, METHOD_BUFFERED, FILE_ANY_ACCESS) + +/********************************* +* missing declarations in altq.c * +**********************************/ + +#define _IOWR(x,y,t) _IOW(x,y,t) + +/********************************** +* missing declarations in ipfw2.c * +***********************************/ + +#define ICMP_UNREACH_NET 0 /* bad net */ +#define ICMP_UNREACH_HOST 1 /* bad host */ +#define ICMP_UNREACH_PROTOCOL 2 /* bad protocol */ +#define ICMP_UNREACH_PORT 3 /* bad port */ +#define ICMP_UNREACH_NEEDFRAG 4 /* IP_DF caused drop */ +#define ICMP_UNREACH_SRCFAIL 5 /* src route failed */ +#define ICMP_UNREACH_NET_UNKNOWN 6 /* unknown net */ +#define ICMP_UNREACH_HOST_UNKNOWN 7 /* unknown host */ +#define ICMP_UNREACH_ISOLATED 8 /* src host isolated */ +#define ICMP_UNREACH_NET_PROHIB 9 /* prohibited access */ +#define ICMP_UNREACH_HOST_PROHIB 10 /* ditto */ +#define ICMP_UNREACH_TOSNET 11 /* bad tos for net */ +#define ICMP_UNREACH_TOSHOST 12 /* bad tos for host */ +#define ICMP_UNREACH_FILTER_PROHIB 13 /* admin prohib */ +#define ICMP_UNREACH_HOST_PRECEDENCE 14 /* host prec vio. */ +#define ICMP_UNREACH_PRECEDENCE_CUTOFF 15 /* prec cutoff */ + +#define __unused + + +struct ether_addr; +struct ether_addr * ether_aton(const char *a); + +/********************************* +* missing declarations in ipv6.c * +**********************************/ + +struct hostent* gethostbyname2(const char *name, int af); + + +/******************** +* windows wrappings * +*********************/ + +int my_socket(int domain, int ty, int proto); +#define socket(_a, _b, _c) my_socket(_a, _b, _c) + +#endif /* _WIN32 */ +/******************* +* SYSCTL emulation * +********************/ +#if defined (_WIN32) || defined (EMULATE_SYSCTL) +#define STRINGIFY(x) #x + +/* flag is set with the last 2 bits for access, as defined in glue.h + * and the rest for type + */ +enum { + SYSCTLTYPE_INT = 0, + SYSCTLTYPE_UINT, + SYSCTLTYPE_SHORT, + SYSCTLTYPE_USHORT, + SYSCTLTYPE_LONG, + SYSCTLTYPE_ULONG, + SYSCTLTYPE_STRING, +}; +struct sysctlhead { + uint32_t blocklen; //total size of the entry + uint32_t namelen; //strlen(name) + '\0' + uint32_t flags; //type and access + uint32_t datalen; +}; -/* - * List of values used for set/getsockopt options. - * The base value on FreeBSD is defined as a macro, - * if not available we will use our own enum. - * The TABLE_BASE value is used in the kernel. +#ifdef _KERNEL + +#ifdef SYSCTL_NODE +#undef SYSCTL_NODE +#endif +#define SYSCTL_NODE(a,b,c,d,e,f) +#define SYSCTL_DECL(a) +#define SYSCTL_VNET_PROC(a,b,c,d,e,f,g,h,i) + +#define GST_HARD_LIMIT 100 + +/* In the module, GST is implemented as an array of + * sysctlentry, but while passing data to the userland + * pointers are useless, the buffer is actually made of: + * - sysctlhead (fixed size, containing lengths) + * - data (typically 32 bit) + * - name (zero-terminated and padded to mod4) */ -#ifndef IP_FW_TABLE_ADD -#define _IPFW_SOCKOPT_BASE 100 /* 40 on freebsd */ -enum ipfw_msg_type { - IP_FW_TABLE_ADD = _IPFW_SOCKOPT_BASE, - IP_FW_TABLE_DEL, - IP_FW_TABLE_FLUSH, - IP_FW_TABLE_GETSIZE, - IP_FW_TABLE_LIST, - IP_FW_DYN_GET, /* new addition */ - /* IP_FW3 and IP_DUMMYNET3 are the new API */ - IP_FW3 = _IPFW_SOCKOPT_BASE + 8, - IP_DUMMYNET3, +struct sysctlentry { + struct sysctlhead head; + char* name; + void* data; +}; - IP_FW_ADD = _IPFW_SOCKOPT_BASE + 10, - IP_FW_DEL, - IP_FW_FLUSH, - IP_FW_ZERO, - IP_FW_GET, - IP_FW_RESETLOG, +struct sysctltable { + int count; //number of valid tables + int totalsize; //total size of valid entries of al the valid tables + void* namebuffer; //a buffer for all chained names + struct sysctlentry entry[GST_HARD_LIMIT]; +}; - IP_FW_NAT_CFG, - IP_FW_NAT_DEL, - IP_FW_NAT_GET_CONFIG, - IP_FW_NAT_GET_LOG, +#ifdef SYSBEGIN +#undef SYSBEGIN +#endif +#define SYSBEGIN(x) void sysctl_addgroup_##x() { +#ifdef SYSEND +#undef SYSEND +#endif +#define SYSEND } - IP_DUMMYNET_CONFIGURE, - IP_DUMMYNET_DEL , - IP_DUMMYNET_FLUSH, - /* 63 is missing */ - IP_DUMMYNET_GET = _IPFW_SOCKOPT_BASE + 24, - _IPFW_SOCKOPT_END -}; -#endif /* IP_FW_TABLE_ADD */ +/* XXX remove duplication */ +#define SYSCTL_INT(a,b,c,d,e,f,g) \ + sysctl_pushback(STRINGIFY(a) "." STRINGIFY(c) + 1, \ + (d) | (SYSCTLTYPE_INT << 2), sizeof(*e), e) + +#define SYSCTL_VNET_INT(a,b,c,d,e,f,g) \ + sysctl_pushback(STRINGIFY(a) "." STRINGIFY(c) + 1, \ + (d) | (SYSCTLTYPE_INT << 2), sizeof(*e), e) + +#define SYSCTL_UINT(a,b,c,d,e,f,g) \ + sysctl_pushback(STRINGIFY(a) "." STRINGIFY(c) + 1, \ + (d) | (SYSCTLTYPE_UINT << 2), sizeof(*e), e) + +#define SYSCTL_LONG(a,b,c,d,e,f,g) \ + sysctl_pushback(STRINGIFY(a) "." STRINGIFY(c) + 1, \ + (d) | (SYSCTLTYPE_LONG << 2), sizeof(*e), e) + +#define SYSCTL_ULONG(a,b,c,d,e,f,g) \ + sysctl_pushback(STRINGIFY(a) "." STRINGIFY(c) + 1, \ + (d) | (SYSCTLTYPE_ULONG << 2), sizeof(*e), e) +#define TUNABLE_INT(a,b) + +void keinit_GST(void); +void keexit_GST(void); +int kesysctl_emu_set(void* p, int l); +int kesysctl_emu_get(struct sockopt* sopt); +void sysctl_pushback(char* name, int flags, int datalen, void* data); + +#endif /* _KERNEL */ + +int sysctlbyname(const char *name, void *oldp, size_t *oldlenp, void *newp, + size_t newlen); +#endif /* _WIN32" || EMULATE_SYSCTL */ +#ifdef _WIN32 +int do_cmd(int optname, void *optval, uintptr_t optlen); + +#endif /* _WIN32 */ #endif /* !_GLUE_H */