integrated
[ipfw.git] / glue.h
1 /*
2  * Copyright (c) 2009 Luigi Rizzo, Marta Carbone, Universita` di Pisa
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  */
25 /*
26  * $Id: glue.h 11277 2012-06-10 17:44:15Z marta $
27  *
28  * glue code to adapt the FreeBSD version to linux and windows,
29  * userland and kernel.
30  * This is included before any other headers, so we do not have
31  * a chance to override any #define that should appear in other
32  * headers.
33  * First handle headers for userland and kernel. Then common code
34  * (including headers that require a specific order of inclusion),
35  * then the user- and kernel- specific parts.
36  */
37  
38 #ifndef _GLUE_H
39 #define _GLUE_H
40
41
42 /*
43  * common definitions to allow portability
44  */
45 #ifndef __FBSDID
46 #define __FBSDID(x)
47 #endif  /* FBSDID */
48
49 #ifndef KERNEL_MODULE   /* Userland headers */
50
51 #if defined(__CYGWIN32__) && !defined(_WIN32)                                   
52 #define _WIN32                                                                  
53 #endif                                                                          
54
55 #if defined(TCC) && defined(_WIN32)
56 #include <tcc_glue.h>
57 #endif /* TCC */
58
59 #include <stdint.h>     /* linux needs it in addition to sys/types.h */
60 #include <sys/types.h>  /* for size_t */
61 #include <sys/ioctl.h>
62 #include <time.h>
63 #include <errno.h>
64 #ifdef __linux__
65 #include <netinet/ether.h>      /* linux only 20111031 */
66 #endif
67
68 #else /* KERNEL_MODULE, kernel headers */
69
70 #ifdef __linux__
71
72 #include <linux/version.h>
73
74 #define ifnet           net_device      /* remap */
75 #define _KERNEL         # make kernel structure visible
76 #define KLD_MODULE      # add the module glue
77 #define INET            # want inet support
78
79 #include <linux/stddef.h>       /* linux kernel */
80 #include <linux/types.h>        /* linux kernel */
81
82 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) // or 2.4.x
83 #include <linux/linkage.h>      /* linux/msg.h require this */
84 #include <linux/netdevice.h>    /* just MAX_ADDR_LEN 8 on 2.4 32 on 2.6, also brings in byteorder */
85 #endif
86
87 /* on 2.6.22, msg.h requires spinlock_types.h */
88 /* XXX spinlock_type.h was introduced in 2.6.14 */
89 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13) && \
90         LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
91 #include <linux/spinlock_types.h>
92 #endif
93 /* XXX m_type define conflict with include/sys/mbuf.h,
94  * so early include msg.h (to be solved)
95 */
96 #include <linux/msg.h>  
97
98 #include <linux/list.h>
99 #include <linux/in.h>           /* struct in_addr */
100 #include <linux/in6.h>          /* struct in6_addr */
101 #include <linux/icmp.h>
102 /*
103  * LIST_HEAD in queue.h conflict with linux/list.h
104  * some previous linux include need list.h definition
105  */
106 #undef LIST_HEAD
107
108 #define IF_NAMESIZE     (16)
109 typedef uint32_t        in_addr_t;
110
111 #define printf(fmt, arg...) printk(KERN_ERR fmt, ##arg)
112 #endif  /* __linux__ */
113
114 #endif /* KERNEL_MODULE end of kernel headers */
115
116
117 /*
118  * Part 2: common userland and kernel definitions
119  */
120
121 #ifndef ETHER_ADDR_LEN
122 #define ETHER_ADDR_LEN (6+0)       /* length of an Ethernet address */
123 #endif
124
125 #define ICMP6_DST_UNREACH_NOROUTE       0       /* no route to destination */
126 #define ICMP6_DST_UNREACH_ADMIN         1       /* administratively prohibited */
127 #define ICMP6_DST_UNREACH_ADDR          3       /* address unreachable */
128 #define ICMP6_DST_UNREACH_NOPORT        4       /* port unreachable */
129
130 /*
131  * linux: sysctl are mapped into /sys/module/ipfw_mod parameters
132  * windows: they are emulated via get/setsockopt
133  */
134 #define CTLFLAG_RD              1
135 #define CTLFLAG_RDTUN   1
136 #define CTLFLAG_RW              2
137 #define CTLFLAG_SECURE3 0 // unsupported
138 #define CTLFLAG_VNET    0       /* unsupported */
139
140 /* if needed, queue.h must be included here after list.h */
141
142 /*
143  * struct thread is used in linux and windows kernel.
144  * In windows, we need to emulate the sockopt interface
145  * so also the userland needs to have the struct sockopt defined.
146  * In order to achieve 64 bit compatibility, padding has been inserted.
147  */
148 struct thread {
149         void *sopt_td;
150         void *td_ucred;
151 };
152
153 enum sopt_dir { SOPT_GET, SOPT_SET };
154
155 struct  sockopt {
156         enum    sopt_dir sopt_dir; /* is this a get or a set? */
157         int     sopt_level;     /* second arg of [gs]etsockopt */
158         int     sopt_name;      /* third arg of [gs]etsockopt */
159 #ifdef _X64EMU
160                 void* pad1;
161                 void* pad2;
162 #endif
163                 void   *sopt_val;       /* fourth arg of [gs]etsockopt */
164                 size_t  sopt_valsize;   /* (almost) fifth arg of [gs]etsockopt */
165 #ifdef _X64EMU
166                 void* pad3;
167                 void* pad4;
168 #endif
169                 struct  thread *sopt_td; /* calling thread or null if kernel */
170 };
171
172
173 #define INET_ADDRSTRLEN         (16)    /* missing in netinet/in.h */
174
175 /*
176  * List of values used for set/getsockopt options.
177  * The base value on FreeBSD is defined as a macro,
178  * if not available we will use our own enum.
179  * The TABLE_BASE value is used in the kernel.
180  */
181 #ifndef IP_FW_TABLE_ADD
182 #define _IPFW_SOCKOPT_BASE      100     /* 40 on freebsd */
183 enum ipfw_msg_type {
184         IP_FW_TABLE_ADD         = _IPFW_SOCKOPT_BASE,
185         IP_FW_TABLE_DEL,
186         IP_FW_TABLE_FLUSH,
187         IP_FW_TABLE_GETSIZE,
188         IP_FW_TABLE_LIST,
189         IP_FW_DYN_GET,          /* new addition */
190
191         /* IP_FW3 and IP_DUMMYNET3 are the new API */
192         IP_FW3                  = _IPFW_SOCKOPT_BASE + 8,
193         IP_DUMMYNET3,
194
195         IP_FW_ADD               = _IPFW_SOCKOPT_BASE + 10,
196         IP_FW_DEL,
197         IP_FW_FLUSH,
198         IP_FW_ZERO,
199         IP_FW_GET,
200         IP_FW_RESETLOG,
201
202         IP_FW_NAT_CFG,
203         IP_FW_NAT_DEL,
204         IP_FW_NAT_GET_CONFIG,
205         IP_FW_NAT_GET_LOG,
206
207         IP_DUMMYNET_CONFIGURE,
208         IP_DUMMYNET_DEL ,
209         IP_DUMMYNET_FLUSH,
210         /* 63 is missing */
211         IP_DUMMYNET_GET         = _IPFW_SOCKOPT_BASE + 24,
212         _IPFW_SOCKOPT_END
213 };
214 #endif /* IP_FW_TABLE_ADD */
215
216 /*
217  * Part 3: userland stuff
218  */
219
220 #ifndef KERNEL_MODULE
221
222 /*
223  * internal names in struct in6_addr (netinet/in6.h) differ,
224  * so we remap the FreeBSD names to the platform-specific ones.
225  */
226 #ifndef _WIN32
227 #define __u6_addr       in6_u
228 #define __u6_addr32     u6_addr32
229 #define in6_u __in6_u   /* missing type for ipv6 (linux 2.6.28) */
230 #else   /* _WIN32 uses different naming */
231 #define __u6_addr       __u6
232 #define __u6_addr32     __s6_addr32
233 #endif  /* _WIN32 */
234
235 /* missing in linux netinet/ip.h */
236 #define IPTOS_ECN_ECT0  0x02    /* ECN-capable transport (0) */
237 #define IPTOS_ECN_CE    0x03    /* congestion experienced */
238
239 /* defined in freebsd netinet/icmp6.h */
240 #define ICMP6_MAXTYPE   201
241
242 /* on freebsd sys/socket.h pf specific */
243 #define NET_RT_IFLIST   3               /* survey interface list */
244
245 #if defined(__linux__) || defined(__CYGWIN32__)
246 /* on freebsd net/if.h XXX used */
247 struct if_data {
248         /* ... */
249         u_long ifi_mtu; /* maximum transmission unit */
250 };
251
252 /*
253  * Message format for use in obtaining information about interfaces
254  * from getkerninfo and the routing socket.
255  * This is used in nat.c
256  */
257 struct if_msghdr {
258         u_short ifm_msglen;     /* to skip over unknown messages */
259         u_char  ifm_version;    /* future binary compatibility */
260         u_char  ifm_type;       /* message type */
261         int     ifm_addrs;      /* like rtm_addrs */
262         int     ifm_flags;      /* value of if_flags */
263         u_short ifm_index;      /* index for associated ifp */
264         struct  if_data ifm_data;/* stats and other ifdata */
265 };
266
267 /*
268  * Message format for use in obtaining information about interface
269  * addresses from getkerninfo and the routing socket
270  */
271 struct ifa_msghdr {
272         u_short ifam_msglen;    /* to skip over unknown messages */
273         u_char  ifam_version;   /* future binary compatibility */
274         u_char  ifam_type;      /* message type */
275         int     ifam_addrs;     /* like rtm_addrs */
276         int     ifam_flags;     /* value of ifa_flags */
277         u_short ifam_index;     /* index for associated ifp */
278         int     ifam_metric;    /* value of ifa_metric */
279 };
280
281 #ifndef NO_RTM  /* conflicting with netlink */
282 /* missing in net/route.h */
283 #define RTM_VERSION     5       /* Up the ante and ignore older versions */
284 #define RTM_IFINFO      0xe     /* iface going up/down etc. */
285 #define RTM_NEWADDR     0xc     /* address being added to iface */
286 #define RTA_IFA         0x20    /* interface addr sockaddr present */
287 #endif  /* NO_RTM */
288
289 /* SA_SIZE is used in the userland nat.c modified */
290 #define SA_SIZE(sa)                                             \
291     (  (!(sa) ) ?      \
292         sizeof(long)            :                               \
293         1 + ( (sizeof(struct sockaddr) - 1) | (sizeof(long) - 1) ) )
294
295 /* sys/time.h */
296 /*
297  * Getkerninfo clock information structure
298  */
299 struct clockinfo {
300         int     hz;             /* clock frequency */
301         int     tick;           /* micro-seconds per hz tick */
302         int     spare;
303         int     stathz;         /* statistics clock frequency */
304         int     profhz;         /* profiling clock frequency */
305 };
306
307 /* no sin_len in sockaddr, we only remap in userland */
308 #define sin_len sin_zero[0]
309
310 #endif /* Linux/Win */
311
312 /*
313  * linux does not have a reentrant version of qsort,
314  * so we the FreeBSD stdlib version.
315  */
316 void qsort_r(void *a, size_t n, size_t es, void *thunk,
317         int cmp_t(void *, const void *, const void *));
318
319 /* prototypes from libutil */
320 /* humanize_number(3) */
321 #define HN_DECIMAL              0x01
322 #define HN_NOSPACE              0x02
323 #define HN_B                    0x04
324 #define HN_DIVISOR_1000         0x08
325
326 #define HN_GETSCALE             0x10
327 #define HN_AUTOSCALE            0x20
328
329 int     humanize_number(char *_buf, size_t _len, int64_t _number,
330             const char *_suffix, int _scale, int _flags);
331 int     expand_number(const char *_buf, int64_t *_num);
332
333 #define setprogname(x)  /* not present in linux */
334
335 extern int optreset;    /* not present in linux */
336
337 size_t strlcpy(char * dst, const char * src, size_t siz);
338 long long int strtonum(const char *nptr, long long minval,
339         long long maxval, const char **errstr);
340  
341 int sysctlbyname(const char *name, void *oldp, size_t *oldlenp,
342         void *newp, size_t newlen);
343  
344
345 #else /* KERNEL_MODULE */
346
347 /*
348  * Part 4: kernel stuff
349  */
350
351 /* linux and windows kernel do not have bcopy ? */
352 #define bcopy(_s, _d, _l)       memcpy(_d, _s, _l)
353 /* definitions useful for the kernel side */
354 struct route_in6 {
355         int dummy;
356 };
357
358 #ifdef __linux__
359
360 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) // or 2.4.x
361 #include <linux/in6.h>
362 #endif
363
364 /* skb_dst() and skb_dst_set() was introduced from linux 2.6.31 */
365 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31)
366 void skb_dst_set(struct sk_buff *skb, struct dst_entry *dst);
367 struct dst_entry *skb_dst(const struct sk_buff *skb);
368 #endif
369
370 /* The struct flowi changed */
371 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38) // check boundaries
372 #define flow_daddr fl.u.ip4
373 #else
374 #define flow_daddr fl.nl_u.ip4_u
375 #endif
376
377 #endif /* __linux__ */
378
379 /* 
380  * Do not load prio_heap.h header because of conflicting names
381  * with our heap functions defined in include/netinet/ipfw/dn_heap.h
382  */
383 #define _LINUX_PRIO_HEAP_H
384 /* 
385  * The following define prevent the ipv6.h header to be loaded.
386  * Starting from the 2.6.38 kernel the ipv6.h file, which is included
387  * by include/net/inetpeer.h in turn included by net/route.h
388  * include the system tcp.h file while we want to include 
389  * our include/net/tcp.h instead.
390  */
391 #ifndef _NET_IPV6_H
392 #define _NET_IPV6_H
393 static inline void ipv6_addr_copy(struct in6_addr *a1, const struct in6_addr *a2)
394 {
395         memcpy(a1, a2, sizeof(struct in6_addr));
396 }
397 #endif /* _NET_IPV6_H */
398
399 #endif  /* KERNEL_MODULE */
400
401 /*
402  * Part 5: windows specific stuff
403  */
404
405 #ifdef _WIN32
406 #ifndef KERNEL_MODULE
407 #define CTL_CODE( DeviceType, Function, Method, Access ) (                 \
408     ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
409 )
410
411 #define METHOD_BUFFERED                 0
412 #define METHOD_IN_DIRECT                1
413 #define METHOD_OUT_DIRECT               2
414 #define METHOD_NEITHER                  3
415 #define FILE_ANY_ACCESS                 0
416 #define FILE_READ_DATA            ( 0x0001 )    // file & pipe
417 #define FILE_WRITE_DATA           ( 0x0002 )    // file & pipe
418 #endif /* !KERNEL_MODULE */
419
420 #define FILE_DEVICE_IPFW                0x00654324
421 #define IP_FW_BASE_CTL                  0x840
422 #define IP_FW_SETSOCKOPT \
423         CTL_CODE(FILE_DEVICE_IPFW, IP_FW_BASE_CTL + 1, METHOD_BUFFERED, FILE_WRITE_DATA)
424 #define IP_FW_GETSOCKOPT \
425         CTL_CODE(FILE_DEVICE_IPFW, IP_FW_BASE_CTL + 2, METHOD_BUFFERED, FILE_ANY_ACCESS)
426
427 /*********************************
428 * missing declarations in altq.c *
429 **********************************/
430
431 #define _IOWR(x,y,t) _IOW(x,y,t)
432
433 /**********************************
434 * missing declarations in ipfw2.c *
435 ***********************************/
436
437 #define ICMP_UNREACH_NET                0       /* bad net */
438 #define ICMP_UNREACH_HOST               1       /* bad host */
439 #define ICMP_UNREACH_PROTOCOL           2       /* bad protocol */
440 #define ICMP_UNREACH_PORT               3       /* bad port */
441 #define ICMP_UNREACH_NEEDFRAG           4       /* IP_DF caused drop */
442 #define ICMP_UNREACH_SRCFAIL            5       /* src route failed */
443 #define ICMP_UNREACH_NET_UNKNOWN        6       /* unknown net */
444 #define ICMP_UNREACH_HOST_UNKNOWN       7       /* unknown host */
445 #define ICMP_UNREACH_ISOLATED           8       /* src host isolated */
446 #define ICMP_UNREACH_NET_PROHIB         9       /* prohibited access */
447 #define ICMP_UNREACH_HOST_PROHIB        10      /* ditto */
448 #define ICMP_UNREACH_TOSNET             11      /* bad tos for net */
449 #define ICMP_UNREACH_TOSHOST            12      /* bad tos for host */
450 #define ICMP_UNREACH_FILTER_PROHIB      13      /* admin prohib */
451 #define ICMP_UNREACH_HOST_PRECEDENCE    14      /* host prec vio. */
452 #define ICMP_UNREACH_PRECEDENCE_CUTOFF  15      /* prec cutoff */
453
454 #define __unused
455
456
457 struct ether_addr;
458 struct ether_addr * ether_aton(const char *a);
459
460 /*********************************
461 * missing declarations in ipv6.c *
462 **********************************/
463
464 struct hostent* gethostbyname2(const char *name, int af);
465
466
467 /********************
468 * windows wrappings *
469 *********************/
470
471 int my_socket(int domain, int ty, int proto);
472 #define socket(_a, _b, _c)      my_socket(_a, _b, _c)
473
474 #endif /* _WIN32 */
475 /*******************
476 * SYSCTL emulation *
477 ********************/
478 #if defined (_WIN32) || defined (EMULATE_SYSCTL)
479 #define STRINGIFY(x) #x
480
481 /* flag is set with the last 2 bits for access, as defined in glue.h
482  * and the rest for type
483  */
484 enum {
485         SYSCTLTYPE_INT = 0,
486         SYSCTLTYPE_UINT,
487         SYSCTLTYPE_SHORT,
488         SYSCTLTYPE_USHORT,
489         SYSCTLTYPE_LONG,
490         SYSCTLTYPE_ULONG,
491         SYSCTLTYPE_STRING,
492 };
493
494 struct sysctlhead {
495         uint32_t blocklen; //total size of the entry
496         uint32_t namelen; //strlen(name) + '\0'
497         uint32_t flags; //type and access
498         uint32_t datalen;
499 };
500
501 #ifdef _KERNEL
502
503 #ifdef SYSCTL_NODE
504 #undef SYSCTL_NODE
505 #endif
506 #define SYSCTL_NODE(a,b,c,d,e,f)
507 #define SYSCTL_DECL(a)
508 #define SYSCTL_VNET_PROC(a,b,c,d,e,f,g,h,i)
509
510 #define GST_HARD_LIMIT 100
511
512 /* In the module, GST is implemented as an array of
513  * sysctlentry, but while passing data to the userland
514  * pointers are useless, the buffer is actually made of:
515  * - sysctlhead (fixed size, containing lengths)
516  * - data (typically 32 bit)
517  * - name (zero-terminated and padded to mod4)
518  */
519
520 struct sysctlentry {
521         struct sysctlhead head;
522         char* name;
523         void* data;
524 };
525
526 struct sysctltable {
527         int count; //number of valid tables
528         int totalsize; //total size of valid entries of al the valid tables
529         void* namebuffer; //a buffer for all chained names
530         struct sysctlentry entry[GST_HARD_LIMIT];
531 };
532
533 #ifdef SYSBEGIN
534 #undef SYSBEGIN
535 #endif
536 #define SYSBEGIN(x) void sysctl_addgroup_##x() {
537 #ifdef SYSEND
538 #undef SYSEND
539 #endif
540 #define SYSEND }
541
542 /* XXX remove duplication */
543 #define SYSCTL_INT(a,b,c,d,e,f,g)                               \
544         sysctl_pushback(STRINGIFY(a) "." STRINGIFY(c) + 1,      \
545                 (d) | (SYSCTLTYPE_INT << 2), sizeof(*e), e)
546
547 #define SYSCTL_VNET_INT(a,b,c,d,e,f,g)                          \
548         sysctl_pushback(STRINGIFY(a) "." STRINGIFY(c) + 1,      \
549                 (d) | (SYSCTLTYPE_INT << 2), sizeof(*e), e)
550
551 #define SYSCTL_UINT(a,b,c,d,e,f,g)                              \
552         sysctl_pushback(STRINGIFY(a) "." STRINGIFY(c) + 1,      \
553                 (d) | (SYSCTLTYPE_UINT << 2), sizeof(*e), e)
554
555 #define SYSCTL_LONG(a,b,c,d,e,f,g)                              \
556         sysctl_pushback(STRINGIFY(a) "." STRINGIFY(c) + 1,      \
557                 (d) | (SYSCTLTYPE_LONG << 2), sizeof(*e), e)
558
559 #define SYSCTL_ULONG(a,b,c,d,e,f,g)                             \
560         sysctl_pushback(STRINGIFY(a) "." STRINGIFY(c) + 1,      \
561                 (d) | (SYSCTLTYPE_ULONG << 2), sizeof(*e), e)
562 #define TUNABLE_INT(a,b)
563
564 void keinit_GST(void);
565 void keexit_GST(void);
566 int kesysctl_emu_set(void* p, int l);
567 int kesysctl_emu_get(struct sockopt* sopt);
568 void sysctl_pushback(char* name, int flags, int datalen, void* data);
569
570 #endif /* _KERNEL */
571
572 int sysctlbyname(const char *name, void *oldp, size_t *oldlenp, void *newp,
573          size_t newlen);
574 #endif /* _WIN32" || EMULATE_SYSCTL */
575 #ifdef _WIN32
576 int do_cmd(int optname, void *optval, uintptr_t optlen);
577
578 #endif /* _WIN32 */
579
580 #endif /* !_GLUE_H */