494 lines
14 KiB
C
494 lines
14 KiB
C
/*
|
|
* Copyright (c) 2009 Luigi Rizzo, Marta Carbone, Universita` di Pisa
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
* SUCH DAMAGE.
|
|
*/
|
|
/*
|
|
* $Id: glue.h 8327 2011-03-22 17:01:35Z 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
|
|
*/
|
|
#ifndef __FBSDID
|
|
#define __FBSDID(x) struct __hack
|
|
#endif /* FBSDID */
|
|
|
|
#include <stdint.h> /* linux needs it in addition to sys/types.h */
|
|
#include <sys/types.h> /* for size_t */
|
|
|
|
#define true 1 /* stdbool */
|
|
#ifdef _KERNEL /* prevent a warning */
|
|
#undef _KERNEL
|
|
#include <sys/ioctl.h>
|
|
#include <sys/time.h>
|
|
#include <errno.h> /* we want errno */
|
|
#define _KERNEL
|
|
#else
|
|
#include <sys/ioctl.h>
|
|
#endif
|
|
|
|
#include <time.h>
|
|
#ifndef USERSPACE
|
|
#include <netinet/ether.h>
|
|
#endif
|
|
|
|
|
|
/*----- */
|
|
|
|
/* ipfw2.c - from timeconv.h */
|
|
static __inline time_t
|
|
_long_to_time(long tlong)
|
|
{
|
|
#if 0 /* modified by acetcom */
|
|
if (sizeof(long) == sizeof(__int32_t))
|
|
return((time_t)(__int32_t)(tlong));
|
|
#else
|
|
if (sizeof(long) == sizeof(int32_t))
|
|
return((time_t)(int32_t)(tlong));
|
|
#endif
|
|
return((time_t)tlong);
|
|
}
|
|
|
|
#define min(a, b) ((a) < (b) ? (a) : (b) ) // radix.c
|
|
/*
|
|
* debugging macros from ip_dn_private.h
|
|
*/
|
|
#include <sys/time.h>
|
|
#include <stdio.h>
|
|
extern char *strrchr(const char *, int);
|
|
static inline const char *xyz(const char *s) {
|
|
static char buf[128];
|
|
struct timeval t;
|
|
const char *ret = strrchr(s, '/');
|
|
if (ret) s = ret + 1;
|
|
gettimeofday(&t, NULL);
|
|
buf[sizeof(buf) - 1] = '\0';
|
|
snprintf(buf, sizeof(buf), "[%4d.%06d] %s",
|
|
(int)(t.tv_sec % 1000), (int)(t.tv_usec), s);
|
|
return buf;
|
|
}
|
|
|
|
#define ND(fmt, ...) do {} while (0)
|
|
#define D1(fmt, ...) do {} while (0)
|
|
#define D(fmt, ...) fprintf(stderr, "%s:%-10s [%d] " fmt "\n", \
|
|
xyz(__FILE__), __FUNCTION__, __LINE__, ## __VA_ARGS__)
|
|
|
|
/* Rate limited version of "D", lps indicates how many per second */
|
|
#define RD(lps, format, ...) \
|
|
do { \
|
|
static int t0, __cnt; \
|
|
struct timeval __xxts; \
|
|
gettimeofday(&__xxts, NULL); \
|
|
if (t0 != __xxts.tv_sec) { \
|
|
t0 = __xxts.tv_sec; \
|
|
__cnt = 0; \
|
|
} \
|
|
if (__cnt++ < lps) { \
|
|
D(format, ##__VA_ARGS__); \
|
|
} \
|
|
} while (0)
|
|
|
|
#define DX(lev, fmt, ...) do { \
|
|
if (dn_cfg.debug > lev) D(fmt, ## __VA_ARGS__); } while (0)
|
|
/* end debugging macros */
|
|
|
|
|
|
/*
|
|
* sbin/ipfw on non-freebsd platform
|
|
*/
|
|
#ifdef NEED_STRTONUM
|
|
/* prototypes from libutil */
|
|
/* humanize_number(3) */
|
|
#define HN_DECIMAL 0x01
|
|
#define HN_NOSPACE 0x02
|
|
#define HN_B 0x04
|
|
#define HN_DIVISOR_1000 0x08
|
|
#define HN_IEC_PREFIXES 0x10
|
|
|
|
#define HN_GETSCALE 0x10
|
|
#define HN_AUTOSCALE 0x20
|
|
|
|
|
|
int humanize_number(char *_buf, size_t _len, int64_t _number,
|
|
const char *_suffix, int _scale, int _flags);
|
|
int expand_number(const char *buf, uint64_t *num);
|
|
|
|
|
|
long long
|
|
strtonum(const char *nptr, long long minval, long long maxval,
|
|
const char **errstr);
|
|
#ifndef __APPLE__
|
|
int ishexnumber(int c);
|
|
#endif
|
|
#endif /* NEED_STRTONUM */
|
|
|
|
#ifdef NEED_SYSCTLBYNAME /* and other linux calls */
|
|
int sysctlbyname(const char *name, void *oldp, size_t *oldlenp,
|
|
void *newp, size_t newlen);
|
|
#define setprogname(x) /* not present in linux */
|
|
|
|
extern int optreset; /* not present in linux */
|
|
|
|
long long int strtonum(const char *nptr, long long minval,
|
|
long long maxval, const char **errstr);
|
|
|
|
|
|
struct ether_addr;
|
|
struct ether_addr * ether_aton(const char *a);
|
|
|
|
#define ICMP6_MAXTYPE 201
|
|
#define __u6_addr in6_u
|
|
#define in6_u __in6_u /* missing type for ipv6 (linux 2.6.28) */
|
|
|
|
|
|
#define __u6_addr32 u6_addr32
|
|
/* on freebsd sys/socket.h pf specific */
|
|
#define NET_RT_IFLIST 3 /* survey interface list */
|
|
|
|
#define RTM_VERSION 5 /* Up the ante and ignore older versions */
|
|
|
|
#endif // NEED_SYSCTLBYNAME
|
|
|
|
#ifdef NEED_SIN_LEN
|
|
/*
|
|
* linux at least does not have sin_len and sin6_len, so we remap
|
|
* to some safe fields (check use of sin6_flowinfo XXX)
|
|
*/
|
|
#define sin_len sin_zero[0]
|
|
#define sin6_len sin6_flowinfo
|
|
#endif /* NEED_SIN_LEN */
|
|
|
|
#ifdef NEED_ROUNDUP2 /* in freensd is in sys/param.h */
|
|
/* round up to the next power of 2 (y) */
|
|
#define roundup2(x, y) (((x)+((y)-1))&(~((y)-1))) /* if y is powers of two */
|
|
#endif // NEED_ROUNDUP2
|
|
|
|
/* possibly redundant, does not harm */
|
|
size_t strlcpy(char * dst, const char * src, size_t siz);
|
|
|
|
/*
|
|
* Part 2: common userland and kernel definitions
|
|
*/
|
|
|
|
#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 */
|
|
|
|
/* if needed, queue.h must be included here after list.h */
|
|
|
|
/*
|
|
* our own struct thread
|
|
*/
|
|
struct thread { /* ip_fw_sockopt */
|
|
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 */
|
|
};
|
|
|
|
|
|
/*
|
|
* 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.
|
|
*/
|
|
#define _IPFW_SOCKOPT_BASE 100 /* 40 on freebsd */
|
|
#define IP_FW_TABLE_ADD (_IPFW_SOCKOPT_BASE + 0)
|
|
#define IP_FW_TABLE_DEL (_IPFW_SOCKOPT_BASE + 1)
|
|
#define IP_FW_TABLE_FLUSH (_IPFW_SOCKOPT_BASE + 2)
|
|
#define IP_FW_TABLE_GETSIZE (_IPFW_SOCKOPT_BASE + 3)
|
|
#define IP_FW_TABLE_LIST (_IPFW_SOCKOPT_BASE + 4)
|
|
#define IP_FW_DYN_GET (_IPFW_SOCKOPT_BASE + 5)
|
|
|
|
#define IP_FW3 (_IPFW_SOCKOPT_BASE + 8)
|
|
#define IP_DUMMYNET3 (_IPFW_SOCKOPT_BASE + 9)
|
|
|
|
#define IP_FW_ADD (_IPFW_SOCKOPT_BASE + 10)
|
|
#define IP_FW_DEL (_IPFW_SOCKOPT_BASE + 11)
|
|
#define IP_FW_FLUSH (_IPFW_SOCKOPT_BASE + 12)
|
|
#define IP_FW_ZERO (_IPFW_SOCKOPT_BASE + 13)
|
|
#define IP_FW_GET (_IPFW_SOCKOPT_BASE + 14)
|
|
#define IP_FW_RESETLOG (_IPFW_SOCKOPT_BASE + 15)
|
|
|
|
#define IP_FW_NAT_CFG (_IPFW_SOCKOPT_BASE + 16)
|
|
#define IP_FW_NAT_DEL (_IPFW_SOCKOPT_BASE + 17)
|
|
#define IP_FW_NAT_GET_CONFIG (_IPFW_SOCKOPT_BASE + 18)
|
|
#define IP_FW_NAT_GET_LOG (_IPFW_SOCKOPT_BASE + 19)
|
|
|
|
#define IP_DUMMYNET_CONFIGURE (_IPFW_SOCKOPT_BASE + 20)
|
|
#define IP_DUMMYNET_DEL (_IPFW_SOCKOPT_BASE + 21)
|
|
#define IP_DUMMYNET_FLUSH (_IPFW_SOCKOPT_BASE + 22)
|
|
/* 63 is missing */
|
|
#define IP_DUMMYNET_GET (_IPFW_SOCKOPT_BASE + 24)
|
|
#define _IPFW_SOCKOPT_END (_IPFW_SOCKOPT_BASE + 25)
|
|
|
|
/*
|
|
* Part 3: userland stuff for linux/windows
|
|
*/
|
|
|
|
|
|
/*
|
|
* now remap functions for userland or linux kernel etc.
|
|
*/
|
|
#ifdef USERSPACE
|
|
/*
|
|
* definitions used when the programs communicate through userspace.
|
|
* We need to define the socket and addresses used to talk, and
|
|
* the userland side must also remap socket() and [gs]etsockopt()
|
|
* to appropriate wrappers.
|
|
*/
|
|
|
|
#define LOCALADDR "127.0.0.1"
|
|
#define IPFW_PORT 5555
|
|
|
|
#ifndef KERNEL_SIDE
|
|
#ifdef _KERNEL
|
|
#error _KERNEL defined in user space
|
|
#endif
|
|
int do_connect(const char *addr, int port);
|
|
#include <sys/socket.h> /* for socklen_t */
|
|
|
|
#define socket(a, b, c) do_connect(LOCALADDR, IPFW_PORT)
|
|
#define setsockopt setsockopt2
|
|
#define getsockopt getsockopt2
|
|
int getsockopt2(int s, int lev, int optname, void *optval, socklen_t *optlen);
|
|
int setsockopt2(int s, int lev, int optname, void *optval, socklen_t optlen);
|
|
#endif /* KERNEL_SIDE */
|
|
|
|
#endif /* USERSPACE */
|
|
|
|
/*
|
|
* Part 5: windows specific stuff and sysctl emulation
|
|
*/
|
|
|
|
/*******************
|
|
* SYSCTL emulation *
|
|
********************/
|
|
#ifdef EMULATE_SYSCTL
|
|
|
|
/* this needs to be here, as it is part of the user-kernel messages */
|
|
/* 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 = 1,
|
|
SYSCTLTYPE_SHORT = 2,
|
|
SYSCTLTYPE_USHORT = 3,
|
|
SYSCTLTYPE_LONG = 4,
|
|
SYSCTLTYPE_ULONG = 5,
|
|
SYSCTLTYPE_STRING = 6,
|
|
|
|
/* the following are SYSCTL_PROC equivalents of the above,
|
|
* where the SYSCTLTYPE is shifted 2 bits,
|
|
* and SYSCTLTYPE_PROC is set
|
|
*/
|
|
SYSCTLTYPE_PROC = 0x100,
|
|
CTLTYPE_INT = (0x100 | (0<<2)),
|
|
CTLTYPE_UINT = (0x100 | (1<<2)),
|
|
CTLTYPE_LONG = (0x100 | (4<<2)),
|
|
CTLTYPE_ULONG = (0x100 | (5<<2))
|
|
};
|
|
|
|
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;
|
|
};
|
|
|
|
|
|
#endif /* EMULATE_SYSCTL */
|
|
|
|
#ifndef __FreeBSD__
|
|
int sysctlbyname(const char *name, void *oldp, size_t *oldlenp, void *newp,
|
|
size_t newlen);
|
|
|
|
#define test_bit(ix, pData) ((*pData) & (1<<(ix)))
|
|
#define __set_bit(ix, pData) (*pData) |= (1<<(ix))
|
|
#define __clear_bit(ix, pData) (*pData) &= ~(1<<(ix))
|
|
|
|
static inline int fls(int _n)
|
|
{
|
|
unsigned int n = _n;
|
|
int i = 0;
|
|
for (i = 0; n > 0; n >>= 1, i++)
|
|
;
|
|
return i;
|
|
}
|
|
|
|
static inline unsigned long __fls(unsigned long word)
|
|
{
|
|
return fls(word) - 1;
|
|
}
|
|
|
|
|
|
#endif /* !FreeBSD */
|
|
|
|
#ifdef KERNEL_SIDE
|
|
/* sys/counter.h , to be moved to a file */
|
|
typedef uint64_t *counter_u64_t; // XXX kernel
|
|
static inline void counter_u64_add(counter_u64_t c, int64_t v)
|
|
{
|
|
*c += v;
|
|
}
|
|
static inline void counter_u64_zero(counter_u64_t c)
|
|
{
|
|
*c = 0;
|
|
}
|
|
static inline uint64_t counter_u64_fetch(counter_u64_t c)
|
|
{
|
|
return *c;
|
|
}
|
|
|
|
struct rm_priotracker {
|
|
};
|
|
|
|
#define vslock(_a, _b) (0)
|
|
#define vsunlock(_a, _b)
|
|
|
|
typedef uint64_t u_register_t; // XXX not on osx ?
|
|
|
|
typedef uintptr_t eventhandler_tag;
|
|
#define EVENTHANDLER_REGISTER(_a, _b, ...) (uintptr_t)_b;
|
|
#define EVENTHANDLER_DEREGISTER(_a, _b, ...) (void)_b;
|
|
|
|
// XXX this needs to be completed
|
|
#define if_name(_ifp) (_ifp->if_xname)
|
|
#define ifunit_ref(_n) NULL // XXX
|
|
#define if_rele(_n)
|
|
|
|
#define rtalloc1_fib(_a, ...) NULL
|
|
#define rt_key(_a) NULL
|
|
#define rt_mask(_a) NULL
|
|
#define RTFREE_LOCKED(_a) ((void)NULL)
|
|
struct rtentry {
|
|
};
|
|
#define rt_tables_get_rnh(_a, _b) NULL
|
|
|
|
#endif /* KERNEL_SIDE */
|
|
|
|
#ifdef _KERNEL
|
|
/* XXX kernel support */
|
|
/* on freebsd net/if.h XXX used */
|
|
#ifdef linux
|
|
#define div64(a,b) (((int64_t)a)/((int64_t)b))
|
|
#define LINUX_VERSION_CODE 30003
|
|
#define KERNEL_VERSION(a,b,c) (a*10000+b*100 + c)
|
|
#define __printflike(a,b)
|
|
#endif /* linux */
|
|
|
|
#endif /* _KERNEL */
|
|
|
|
#ifndef __FreeBSD__
|
|
#ifndef IFNAMSIZ
|
|
#define IFNAMSIZ 16
|
|
#endif
|
|
#include "missing.h"
|
|
|
|
struct if_data {
|
|
/* ... */
|
|
u_long ifi_mtu; /* maximum transmission unit */
|
|
};
|
|
|
|
#endif
|
|
|
|
#ifdef __APPLE__
|
|
#include <sys/socketvar.h> // need in kernel
|
|
|
|
/* needed both in kernel and userspace */
|
|
struct if_data64 { // XXX Darwin version
|
|
/* ... */
|
|
u_long ifi_mtu; /* maximum transmission unit */
|
|
};
|
|
|
|
struct net_event_data {
|
|
};
|
|
|
|
struct in_addr;
|
|
#endif /* __APPLE__ */
|
|
|
|
#define __PAST_END(v, idx) v[idx]
|
|
|
|
/*
|
|
* a fast copy routine
|
|
*/
|
|
#include <strings.h>
|
|
// XXX only for multiples of 64 bytes, non overlapped.
|
|
static inline void
|
|
_pkt_copy(const void *_src, void *_dst, int l)
|
|
{
|
|
const uint64_t *src = _src;
|
|
uint64_t *dst = _dst;
|
|
#define likely(x) __builtin_expect(!!(x), 1)
|
|
#define unlikely(x) __builtin_expect(!!(x), 0)
|
|
if (unlikely(l >= 1024)) {
|
|
bcopy(src, dst, l);
|
|
return;
|
|
}
|
|
for (; l > 0; l-=64) {
|
|
*dst++ = *src++;
|
|
*dst++ = *src++;
|
|
*dst++ = *src++;
|
|
*dst++ = *src++;
|
|
*dst++ = *src++;
|
|
*dst++ = *src++;
|
|
*dst++ = *src++;
|
|
*dst++ = *src++;
|
|
}
|
|
}
|
|
|
|
#endif /* !_GLUE_H */
|