#include <sys/mutex.h>
#include <sys/refcnt.h>
extern struct mutex pipex_list_mtx;
#define PIPEX_PPTP 1
#define PIPEX_L2TP 1
#define PIPEX_PPPOE 1
#define PIPEX_MPPE 1
#define PIPEX_REWIND_LIMIT 64
#define PIPEX_ENABLED 0x0001
#ifndef PIPEX_MAX_SESSION
#define PIPEX_MAX_SESSION 512
#endif
#define PIPEX_HASH_DIV 8
#define PIPEX_HASH_SIZE (PIPEX_MAX_SESSION/PIPEX_HASH_DIV)
#define PIPEX_HASH_MASK (PIPEX_HASH_SIZE-1)
#define PIPEX_CLOSE_TIMEOUT 30
#define PIPEX_PPPMINLEN 5
#define PIPEX_MPPE_NOLDKEY 64
#define PIPEX_MPPE_OLDKEYMASK (PIPEX_MPPE_NOLDKEY - 1)
#ifdef PIPEX_MPPE
struct pipex_mppe {
struct mutex pxm_mtx;
u_int flags;
#define PIPEX_MPPE_STATELESS 0x01
#define PIPEX_MPPE_RESETREQ 0x02
int16_t keylenbits;
int16_t keylen;
uint16_t coher_cnt;
struct rc4_ctx rc4ctx;
u_char master_key[PIPEX_MPPE_KEYLEN];
u_char session_key[PIPEX_MPPE_KEYLEN];
u_char (*old_session_keys)[PIPEX_MPPE_KEYLEN];
};
#endif
#ifdef PIPEX_PPPOE
struct pipex_pppoe_session {
u_int over_ifidx;
};
#endif
#ifdef PIPEX_PPTP
struct pipex_pptp_session {
int32_t snd_gap;
int32_t rcv_gap;
int32_t ul_snd_una;
uint32_t snd_nxt;
uint32_t rcv_nxt;
uint32_t snd_una;
uint32_t rcv_acked;
int winsz;
int maxwinsz;
int peer_maxwinsz;
};
#endif
#ifdef PIPEX_L2TP
struct pipex_l2tp_session {
uint16_t tunnel_id;
uint16_t peer_tunnel_id;
uint32_t option_flags;
uint32_t ipsecflowinfo;
int16_t ns_gap;
int16_t nr_gap;
uint16_t ul_ns_una;
uint16_t ns_nxt;
uint16_t ns_una;
uint16_t nr_nxt;
uint16_t nr_acked;
};
#endif
struct cpumem;
struct pipex_session_iterator {
struct radix_node ps4_rn[2];
u_int flags;
LIST_ENTRY(pipex_session) session_list;
};
struct pipex_session {
struct radix_node ps4_rn[2];
u_int flags;
#define PIPEX_SFLAGS_MULTICAST 0x01
#define PIPEX_SFLAGS_PPPX 0x02
#define PIPEX_SFLAGS_ITERATOR 0x04
LIST_ENTRY(pipex_session) session_list;
LIST_ENTRY(pipex_session) state_list;
LIST_ENTRY(pipex_session) id_chain;
LIST_ENTRY(pipex_session) peer_addr_chain;
struct refcnt pxs_refcnt;
struct mutex pxs_mtx;
u_int state;
#define PIPEX_STATE_INITIAL 0x0000
#define PIPEX_STATE_OPENED 0x0001
#define PIPEX_STATE_CLOSE_WAIT 0x0002
#define PIPEX_STATE_CLOSE_WAIT2 0x0003
#define PIPEX_STATE_CLOSED 0x0004
uint32_t idle_time;
uint16_t protocol;
uint16_t session_id;
uint16_t peer_session_id;
uint16_t peer_mru;
uint32_t timeout_sec;
int ppp_id;
struct sockaddr_in ip_address;
struct sockaddr_in ip_netmask;
struct sockaddr_in6 ip6_address;
int ip6_prefixlen;
u_int ifindex;
void *ownersc;
uint32_t ppp_flags;
#ifdef PIPEX_MPPE
int ccp_id;
struct pipex_mppe
mppe_recv,
mppe_send;
#endif
struct cpumem *stat_counters;
union {
#ifdef PIPEX_PPPOE
struct pipex_pppoe_session pppoe;
#endif
#ifdef PIPEX_PPTP
struct pipex_pptp_session pptp;
#endif
#ifdef PIPEX_L2TP
struct pipex_l2tp_session l2tp;
#endif
char _proto_unknown[0];
} proto;
union {
struct sockaddr sa;
struct sockaddr_in sin4;
struct sockaddr_in6 sin6;
struct sockaddr_dl sdl;
} peer, local;
};
enum pipex_counters {
pxc_ipackets,
pxc_ierrors,
pxc_ibytes,
pxc_opackets,
pxc_oerrors,
pxc_obytes,
pxc_ncounters
};
struct pipex_gre_header {
uint16_t flags;
#define PIPEX_GRE_KFLAG 0x2000
#define PIPEX_GRE_SFLAG 0x1000
#define PIPEX_GRE_AFLAG 0x0080
#define PIPEX_GRE_VER 0x0001
#define PIPEX_GRE_VERMASK 0x0007
#define PIPEX_GRE_UNUSEDFLAGS 0xcf78
uint16_t type;
#define PIPEX_GRE_PROTO_PPP 0x880b
uint16_t len;
uint16_t call_id;
} __packed;
struct pipex_pppoe_header {
uint8_t vertype;
#define PIPEX_PPPOE_VERTYPE 0x11
uint8_t code;
#define PIPEX_PPPOE_CODE_SESSION 0x00
uint16_t session_id;
uint16_t length;
} __packed;
struct pipex_l2tp_header {
uint16_t flagsver;
#define PIPEX_L2TP_FLAG_MASK 0xfff0
#define PIPEX_L2TP_FLAG_TYPE 0x8000
#define PIPEX_L2TP_FLAG_LENGTH 0x4000
#define PIPEX_L2TP_FLAG_SEQUENCE 0x0800
#define PIPEX_L2TP_FLAG_OFFSET 0x0200
#define PIPEX_L2TP_FLAG_PRIORITY 0x0100
#define PIPEX_L2TP_VER_MASK 0x000f
#define PIPEX_L2TP_VER 2
uint16_t length;
uint16_t tunnel_id;
uint16_t session_id;
} __packed;
struct pipex_l2tp_seq_header {
uint16_t ns;
uint16_t nr;
} __packed;
struct pipex_l2tp_offset_header {
uint16_t offset_size;
} __packed;
#ifdef PIPEX_DEBUG
#define PIPEX_DBG(a) if (pipex_debug & 1) pipex_session_log a
#define PIPEX_MPPE_DBG(a)
#else
#define PIPEX_DBG(a)
#define PIPEX_MPPE_DBG(a)
#endif
LIST_HEAD(pipex_hash_head, pipex_session);
extern struct pipex_hash_head pipex_session_list;
extern struct pipex_hash_head pipex_close_wait_list;
extern struct pipex_hash_head pipex_peer_addr_hashtable[];
extern struct pipex_hash_head pipex_id_hashtable[];
extern struct pool pipex_session_pool;
#define PIPEX_ID_HASHTABLE(key) \
(&pipex_id_hashtable[(key) & PIPEX_HASH_MASK])
#define PIPEX_PEER_ADDR_HASHTABLE(key) \
(&pipex_peer_addr_hashtable[(key) & PIPEX_HASH_MASK])
#define GETCHAR(c, cp) do { \
(c) = *(cp)++; \
} while (0)
#define PUTCHAR(s, cp) do { \
*(cp)++ = (u_char)(s); \
} while (0)
#define GETSHORT(s, cp) do { \
(s) = *(cp)++ << 8; \
(s) |= *(cp)++; \
} while (0)
#define PUTSHORT(s, cp) do { \
*(cp)++ = (u_char) ((s) >> 8); \
*(cp)++ = (u_char) (s); \
} while (0)
#define GETLONG(l, cp) do { \
(l) = *(cp)++ << 8; \
(l) |= *(cp)++; (l) <<= 8; \
(l) |= *(cp)++; (l) <<= 8; \
(l) |= *(cp)++; \
} while (0)
#define PUTLONG(l, cp) do { \
*(cp)++ = (u_char) ((l) >> 24); \
*(cp)++ = (u_char) ((l) >> 16); \
*(cp)++ = (u_char) ((l) >> 8); \
*(cp)++ = (u_char) (l); \
} while (0)
#define PIPEX_PULLUP(m0, l) \
if ((m0)->m_len < (l)) { \
if ((m0)->m_pkthdr.len < (l)) { \
PIPEX_DBG((NULL, LOG_DEBUG, \
"<%s> received packet is too short.", \
__func__)); \
m_freem(m0); \
(m0) = NULL; \
} else { \
(m0) = m_pullup((m0), (l)); \
KASSERT((m0) != NULL); \
} \
}
#define PIPEX_SEEK_NEXTHDR(ptr, len, t) \
((t) (((char *)ptr) + len))
#define SEQ32_LT(a,b) ((int32_t)((a) - (b)) < 0)
#define SEQ32_LE(a,b) ((int32_t)((a) - (b)) <= 0)
#define SEQ32_GT(a,b) ((int32_t)((a) - (b)) > 0)
#define SEQ32_GE(a,b) ((int32_t)((a) - (b)) >= 0)
#define SEQ32_SUB(a,b) ((int32_t)((a) - (b)))
#define SEQ16_LT(a,b) ((int16_t)((a) - (b)) < 0)
#define SEQ16_LE(a,b) ((int16_t)((a) - (b)) <= 0)
#define SEQ16_GT(a,b) ((int16_t)((a) - (b)) > 0)
#define SEQ16_GE(a,b) ((int16_t)((a) - (b)) >= 0)
#define SEQ16_SUB(a,b) ((int16_t)((a) - (b)))
#define pipex_session_is_acfc_accepted(s) \
(((s)->ppp_flags & PIPEX_PPP_ACFC_ACCEPTED)? 1 : 0)
#define pipex_session_is_pfc_accepted(s) \
(((s)->ppp_flags & PIPEX_PPP_PFC_ACCEPTED)? 1 : 0)
#define pipex_session_is_acfc_enabled(s) \
(((s)->ppp_flags & PIPEX_PPP_ACFC_ENABLED)? 1 : 0)
#define pipex_session_is_pfc_enabled(s) \
(((s)->ppp_flags & PIPEX_PPP_PFC_ENABLED)? 1 : 0)
#define pipex_session_has_acf(s) \
(((s)->ppp_flags & PIPEX_PPP_HAS_ACF)? 1 : 0)
#define pipex_session_is_mppe_accepted(s) \
(((s)->ppp_flags & PIPEX_PPP_MPPE_ACCEPTED)? 1 : 0)
#define pipex_session_is_mppe_enabled(s) \
(((s)->ppp_flags & PIPEX_PPP_MPPE_ENABLED)? 1 : 0)
#define pipex_session_is_mppe_required(s) \
(((s)->ppp_flags & PIPEX_PPP_MPPE_REQUIRED)? 1 : 0)
#define pipex_mppe_rc4_keybits(r) ((r)->keylen << 3)
#define pipex_session_is_l2tp_data_sequencing_on(s) \
(((s)->proto.l2tp.option_flags & PIPEX_L2TP_USE_SEQUENCING) ? 1 : 0)
#define PIPEX_IPGRE_HDRLEN (sizeof(struct ip) + sizeof(struct pipex_gre_header))
#define PIPEX_TCP_OPTLEN 40
#define PIPEX_L2TP_MINLEN 8
void pipex_destroy_all_sessions (void *);
int pipex_init_session(struct pipex_session **,
struct pipex_session_req *);
int pipex_link_session(struct pipex_session *,
struct ifnet *, void *);
void pipex_unlink_session(struct pipex_session *);
void pipex_unlink_session_locked(struct pipex_session *);
void pipex_export_session_stats(struct pipex_session *,
struct pipex_statistics *);
int pipex_get_stat (struct pipex_session_stat_req *,
void *);
int pipex_get_closed (struct pipex_session_list_req *,
void *);
struct pipex_session *pipex_lookup_by_ip_address_locked (struct in_addr);
struct pipex_session *pipex_lookup_by_ip_address (struct in_addr);
struct pipex_session *pipex_lookup_by_session_id_locked (int, int);
struct pipex_session *pipex_lookup_by_session_id (int, int);
void pipex_ip_output(struct mbuf *, struct pipex_session *);
void pipex_ppp_output(struct mbuf *, struct pipex_session *,
int);
int pipex_ppp_proto(struct mbuf *, struct pipex_session *,
int, int *);
void pipex_ppp_input(struct mbuf *, struct pipex_session *,
int, struct netstack *);
void pipex_ip_input(struct mbuf *, struct pipex_session *,
struct netstack *);
void pipex_ip6_input(struct mbuf *, struct pipex_session *,
struct netstack *);
struct mbuf *pipex_common_input(struct pipex_session *,
struct mbuf *, int, int, int, struct netstack *);
#ifdef PIPEX_PPPOE
void pipex_pppoe_output (struct mbuf *, struct pipex_session *);
#endif
#ifdef PIPEX_PPTP
void pipex_pptp_output (struct mbuf *, struct pipex_session *, int, int);
struct pipex_session *pipex_pptp_userland_lookup_session(struct mbuf *, struct sockaddr *);
#endif
#ifdef PIPEX_L2TP
void pipex_l2tp_output (struct mbuf *, struct pipex_session *);
#endif
#ifdef PIPEX_MPPE
void pipex_mppe_init (struct pipex_mppe *, int, int, u_char *, int);
void GetNewKeyFromSHA (u_char *, u_char *, int, u_char *);
void pipex_mppe_reduce_key (struct pipex_mppe *);
void mppe_key_change (struct pipex_mppe *);
struct mbuf *pipex_mppe_input (struct mbuf *,
struct pipex_session *);
struct mbuf *pipex_mppe_output (struct mbuf *,
struct pipex_session *, uint16_t);
void pipex_ccp_input (struct mbuf *, struct pipex_session *);
int pipex_ccp_output (struct pipex_session *, int, int);
#endif
struct mbuf *adjust_tcp_mss (struct mbuf *, int);
struct mbuf *ip_is_idle_packet (struct mbuf *, int *);
void pipex_session_log (struct pipex_session *, int, const char *, ...) __attribute__((__format__(__kprintf__,3,4)));
uint32_t pipex_sockaddr_hash_key(struct sockaddr *);
int pipex_sockaddr_compar_addr(struct sockaddr *, struct sockaddr *);
void pipex_timer_start (void);
void pipex_timer_stop (void);
void pipex_timer (void *);
struct pipex_session *pipex_iterator(struct pipex_session *,
struct pipex_session_iterator *, void *);