mirror of https://github.com/F-Stack/f-stack.git
Add tool: ipfw.
ipfw -- interface for firewall, packet scheduler, NAT and so on. It is comprised of several components: the kernel firewall filter rule processor and its integrated packet accounting facility, the logging facility, NAT, a forward facility, a bridge facility, and an ipstealth facility. Note that the `dummynet` traffic shaper is not merged.
This commit is contained in:
parent
0b8e61ab4d
commit
b37139ca32
26
lib/Makefile
26
lib/Makefile
|
@ -17,6 +17,8 @@ X86_INCLUDES=0
|
|||
|
||||
HOST_OS:=$(shell uname -s)
|
||||
#DEBUG=-O0 -gdwarf-2 -g3
|
||||
#FF_NETGRAPH=1
|
||||
#FF_IPFW=1
|
||||
|
||||
ifeq ($(FF_DPDK),)
|
||||
FF_DPDK=${TOPDIR}/dpdk/x86_64-native-linuxapp-gcc
|
||||
|
@ -50,6 +52,10 @@ ifdef FF_NETGRAPH
|
|||
HOST_CFLAGS+= -DFF_NETGRAPH
|
||||
endif
|
||||
|
||||
ifdef FF_IPFW
|
||||
HOST_CFLAGS+= -DFF_IPFW
|
||||
endif
|
||||
|
||||
HOST_C= ${CC} -c $(HOST_CFLAGS) ${HOST_INCLUDES} ${WERROR} ${PROF} $<
|
||||
|
||||
|
||||
|
@ -122,6 +128,9 @@ VPATH+= $S/netinet
|
|||
VPATH+= $S/netinet/libalias
|
||||
VPATH+= $S/netinet/cc
|
||||
VPATH+= $S/netipsec
|
||||
ifdef FF_IPFW
|
||||
VPATH+= $S/netpfil/ipfw
|
||||
endif
|
||||
VPATH+= $S/opencrypto
|
||||
VPATH+= $S/vm
|
||||
VPATH+= $S/libkern
|
||||
|
@ -373,6 +382,21 @@ NETINET_SRCS+= \
|
|||
alias_sctp.c \
|
||||
alias_util.c
|
||||
|
||||
ifdef FF_IPFW
|
||||
NETIPFW_SRCS+= \
|
||||
ip_fw_dynamic.c \
|
||||
ip_fw_eaction.c \
|
||||
ip_fw_iface.c \
|
||||
ip_fw_log.c \
|
||||
ip_fw_nat.c \
|
||||
ip_fw_pfil.c \
|
||||
ip_fw_sockopt.c \
|
||||
ip_fw_table.c \
|
||||
ip_fw_table_algo.c \
|
||||
ip_fw_table_value.c \
|
||||
ip_fw2.c
|
||||
endif
|
||||
|
||||
ifdef FF_IPSEC
|
||||
NETINET_SRCS+= \
|
||||
ip_ipsec.c
|
||||
|
@ -431,7 +455,7 @@ ASM_SRCS = ${CRYPTO_ASM_SRCS}
|
|||
|
||||
SRCS= ${FF_SRCS} ${CRYPTO_SRCS} ${KERN_SRCS} ${LIBKERN_SRCS} ${MACHINE_SRCS}
|
||||
SRCS+= ${MSRCS} ${NET_SRCS} ${NETGRAPH_SRCS} ${NETINET_SRCS} ${NETINET6_SRCS}
|
||||
SRCS+= ${NETIPSEC_SRCS} ${OPENCRYPTO_SRCS} ${VM_SRCS}
|
||||
SRCS+= ${NETIPSEC_SRCS} ${NETIPFW_SRCS} ${OPENCRYPTO_SRCS} ${VM_SRCS}
|
||||
|
||||
# If witness is enabled.
|
||||
# SRCS+= ${KERN_WITNESS_SRCS}
|
||||
|
|
|
@ -148,9 +148,11 @@ int ff_route_ctl(enum FF_ROUTE_CTL req, enum FF_ROUTE_FLAG flag,
|
|||
* Implemented by user.
|
||||
*
|
||||
* @param data
|
||||
* The data pointer of the packet.
|
||||
* The data pointer of this packet.
|
||||
* @param len
|
||||
* The length of the packet.
|
||||
* The length of this packet.
|
||||
* @param queue_id
|
||||
* Current queue of this packet.
|
||||
* @param nb_queues
|
||||
* Number of queues to be dispatched.
|
||||
*
|
||||
|
@ -160,7 +162,8 @@ int ff_route_ctl(enum FF_ROUTE_CTL req, enum FF_ROUTE_FLAG flag,
|
|||
* Error occurs or packet is handled by user, packet will be freed.
|
||||
*
|
||||
*/
|
||||
typedef int (*dispatch_func_t)(void *data, uint16_t len, uint16_t nb_queues);
|
||||
typedef int (*dispatch_func_t)(void *data, uint16_t len,
|
||||
uint16_t queue_id, uint16_t nb_queues);
|
||||
|
||||
/* regist a packet dispath function */
|
||||
void ff_regist_packet_dispatcher(dispatch_func_t func);
|
||||
|
|
|
@ -919,7 +919,7 @@ process_packets(uint8_t port_id, uint16_t queue_id, struct rte_mbuf **bufs,
|
|||
uint16_t len = rte_pktmbuf_data_len(rtem);
|
||||
|
||||
if (!pkts_from_ring && packet_dispatcher) {
|
||||
int ret = (*packet_dispatcher)(data, len, nb_queues);
|
||||
int ret = (*packet_dispatcher)(data, len, queue_id, nb_queues);
|
||||
if (ret < 0 || ret >= nb_queues) {
|
||||
rte_pktmbuf_free(rtem);
|
||||
continue;
|
||||
|
@ -994,7 +994,7 @@ process_dispatch_ring(uint8_t port_id, uint16_t queue_id,
|
|||
}
|
||||
|
||||
static inline void
|
||||
handle_sysctl_msg(struct ff_msg *msg, uint16_t proc_id)
|
||||
handle_sysctl_msg(struct ff_msg *msg)
|
||||
{
|
||||
int ret = ff_sysctl(msg->sysctl.name, msg->sysctl.namelen,
|
||||
msg->sysctl.old, msg->sysctl.oldlenp, msg->sysctl.new,
|
||||
|
@ -1005,12 +1005,10 @@ handle_sysctl_msg(struct ff_msg *msg, uint16_t proc_id)
|
|||
} else {
|
||||
msg->result = 0;
|
||||
}
|
||||
|
||||
rte_ring_enqueue(msg_ring[proc_id].ring[1], msg);
|
||||
}
|
||||
|
||||
static inline void
|
||||
handle_ioctl_msg(struct ff_msg *msg, uint16_t proc_id)
|
||||
handle_ioctl_msg(struct ff_msg *msg)
|
||||
{
|
||||
int fd, ret;
|
||||
fd = ff_socket(AF_INET, SOCK_DGRAM, 0);
|
||||
|
@ -1029,12 +1027,10 @@ done:
|
|||
} else {
|
||||
msg->result = 0;
|
||||
}
|
||||
|
||||
rte_ring_enqueue(msg_ring[proc_id].ring[1], msg);
|
||||
}
|
||||
|
||||
static inline void
|
||||
handle_route_msg(struct ff_msg *msg, uint16_t proc_id)
|
||||
handle_route_msg(struct ff_msg *msg)
|
||||
{
|
||||
int ret = ff_rtioctl(msg->route.fib, msg->route.data,
|
||||
&msg->route.len, msg->route.maxlen);
|
||||
|
@ -1043,23 +1039,19 @@ handle_route_msg(struct ff_msg *msg, uint16_t proc_id)
|
|||
} else {
|
||||
msg->result = 0;
|
||||
}
|
||||
|
||||
rte_ring_enqueue(msg_ring[proc_id].ring[1], msg);
|
||||
}
|
||||
|
||||
static struct ff_top_args ff_status;
|
||||
static inline void
|
||||
handle_top_msg(struct ff_msg *msg, uint16_t proc_id)
|
||||
handle_top_msg(struct ff_msg *msg)
|
||||
{
|
||||
msg->top = ff_status;
|
||||
msg->result = 0;
|
||||
|
||||
rte_ring_enqueue(msg_ring[proc_id].ring[1], msg);
|
||||
}
|
||||
|
||||
#ifdef FF_NETGRAPH
|
||||
static inline void
|
||||
handle_ngctl_msg(struct ff_msg *msg, uint16_t proc_id)
|
||||
handle_ngctl_msg(struct ff_msg *msg)
|
||||
{
|
||||
int ret = ff_ngctl(msg->ngctl.cmd, msg->ngctl.data);
|
||||
if (ret < 0) {
|
||||
|
@ -1068,16 +1060,52 @@ handle_ngctl_msg(struct ff_msg *msg, uint16_t proc_id)
|
|||
msg->result = 0;
|
||||
msg->ngctl.ret = ret;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
rte_ring_enqueue(msg_ring[proc_id].ring[1], msg);
|
||||
#ifdef FF_IPFW
|
||||
static inline void
|
||||
handle_ipfw_msg(struct ff_msg *msg)
|
||||
{
|
||||
int fd, ret;
|
||||
fd = ff_socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
|
||||
if (fd < 0) {
|
||||
ret = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
switch (msg->ipfw.cmd) {
|
||||
case FF_IPFW_GET:
|
||||
ret = ff_getsockopt(fd, msg->ipfw.level,
|
||||
msg->ipfw.optname, msg->ipfw.optval,
|
||||
msg->ipfw.optlen);
|
||||
break;
|
||||
case FF_IPFW_SET:
|
||||
ret = ff_setsockopt(fd, msg->ipfw.level,
|
||||
msg->ipfw.optname, msg->ipfw.optval,
|
||||
*(msg->ipfw.optlen));
|
||||
break;
|
||||
default:
|
||||
ret = -1;
|
||||
errno = ENOTSUP;
|
||||
break;
|
||||
}
|
||||
|
||||
ff_close(fd);
|
||||
|
||||
done:
|
||||
if (ret < 0) {
|
||||
msg->result = errno;
|
||||
} else {
|
||||
msg->result = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void
|
||||
handle_default_msg(struct ff_msg *msg, uint16_t proc_id)
|
||||
handle_default_msg(struct ff_msg *msg)
|
||||
{
|
||||
msg->result = ENOTSUP;
|
||||
rte_ring_enqueue(msg_ring[proc_id].ring[1], msg);
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
@ -1085,26 +1113,32 @@ handle_msg(struct ff_msg *msg, uint16_t proc_id)
|
|||
{
|
||||
switch (msg->msg_type) {
|
||||
case FF_SYSCTL:
|
||||
handle_sysctl_msg(msg, proc_id);
|
||||
handle_sysctl_msg(msg);
|
||||
break;
|
||||
case FF_IOCTL:
|
||||
handle_ioctl_msg(msg, proc_id);
|
||||
handle_ioctl_msg(msg);
|
||||
break;
|
||||
case FF_ROUTE:
|
||||
handle_route_msg(msg, proc_id);
|
||||
handle_route_msg(msg);
|
||||
break;
|
||||
case FF_TOP:
|
||||
handle_top_msg(msg, proc_id);
|
||||
handle_top_msg(msg);
|
||||
break;
|
||||
#ifdef FF_NETGRAPH
|
||||
case FF_NGCTL:
|
||||
handle_ngctl_msg(msg, proc_id);
|
||||
handle_ngctl_msg(msg);
|
||||
break;
|
||||
#endif
|
||||
#ifdef FF_IPFW
|
||||
case FF_IPFW_CTL:
|
||||
handle_ipfw_msg(msg);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
handle_default_msg(msg, proc_id);
|
||||
handle_default_msg(msg);
|
||||
break;
|
||||
}
|
||||
rte_ring_enqueue(msg_ring[proc_id].ring[1], msg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
|
|
|
@ -896,6 +896,11 @@ securelevel_gt(struct ucred *cr, int level)
|
|||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
securelevel_ge(struct ucred *cr, int level)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send a 'notification' to userland, using standard ways
|
||||
|
@ -1140,3 +1145,37 @@ getcredhostid(struct ucred *cred, unsigned long *hostid)
|
|||
{
|
||||
*hostid = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if gid is a member of the group set.
|
||||
*/
|
||||
int
|
||||
groupmember(gid_t gid, struct ucred *cred)
|
||||
{
|
||||
int l;
|
||||
int h;
|
||||
int m;
|
||||
|
||||
if (cred->cr_groups[0] == gid)
|
||||
return(1);
|
||||
|
||||
/*
|
||||
* If gid was not our primary group, perform a binary search
|
||||
* of the supplemental groups. This is possible because we
|
||||
* sort the groups in crsetgroups().
|
||||
*/
|
||||
l = 1;
|
||||
h = cred->cr_ngroups;
|
||||
while (l < h) {
|
||||
m = l + ((h - l) / 2);
|
||||
if (cred->cr_groups[m] < gid)
|
||||
l = m + 1;
|
||||
else
|
||||
h = m;
|
||||
}
|
||||
if ((l < cred->cr_ngroups) && (cred->cr_groups[l] == gid))
|
||||
return (1);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
|
15
lib/ff_msg.h
15
lib/ff_msg.h
|
@ -41,6 +41,7 @@ enum FF_MSG_TYPE {
|
|||
FF_ROUTE,
|
||||
FF_TOP,
|
||||
FF_NGCTL,
|
||||
FF_IPFW_CTL,
|
||||
};
|
||||
|
||||
struct ff_sysctl_args {
|
||||
|
@ -78,6 +79,19 @@ struct ff_ngctl_args {
|
|||
void *data;
|
||||
};
|
||||
|
||||
enum FF_IPFW_CMD {
|
||||
FF_IPFW_GET,
|
||||
FF_IPFW_SET,
|
||||
};
|
||||
|
||||
struct ff_ipfw_args {
|
||||
int cmd;
|
||||
int level;
|
||||
int optname;
|
||||
void *optval;
|
||||
socklen_t *optlen;
|
||||
};
|
||||
|
||||
#define MAX_MSG_BUF_SIZE 10240
|
||||
|
||||
/* structure of ipc msg */
|
||||
|
@ -96,6 +110,7 @@ struct ff_msg {
|
|||
struct ff_route_args route;
|
||||
struct ff_top_args top;
|
||||
struct ff_ngctl_args ngctl;
|
||||
struct ff_ipfw_args ipfw;
|
||||
};
|
||||
} __attribute__((packed)) __rte_cache_aligned;
|
||||
|
||||
|
|
|
@ -384,7 +384,7 @@ ff_getsockopt(int s, int level, int optname, void *optval,
|
|||
}
|
||||
|
||||
if ((rc = kern_getsockopt(curthread, s, level, optname,
|
||||
optval, UIO_SYSSPACE, optlen)))
|
||||
optval, UIO_USERSPACE, optlen)))
|
||||
goto kern_fail;
|
||||
|
||||
return (rc);
|
||||
|
@ -410,7 +410,7 @@ ff_setsockopt(int s, int level, int optname, const void *optval,
|
|||
}
|
||||
|
||||
if ((rc = kern_setsockopt(curthread, s, level, optname,
|
||||
__DECONST(void *, optval), UIO_SYSSPACE, optlen)))
|
||||
__DECONST(void *, optval), UIO_USERSPACE, optlen)))
|
||||
goto kern_fail;
|
||||
|
||||
return (rc);
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
#define WITHOUT_BPF 1
|
|
@ -0,0 +1 @@
|
|||
//#define IPDIVERT 1
|
|
@ -0,0 +1,12 @@
|
|||
//sets default policy to pass what is not explicitly denied
|
||||
#define IPFIREWALL_DEFAULT_TO_ACCEPT 1
|
||||
|
||||
//enables logging for rules with log keyword
|
||||
//#define IPFIREWALL_VERBOSE 1
|
||||
|
||||
//limits number of logged packets per-entry
|
||||
//#define IPFIREWALL_VERBOSE_LIMIT 5
|
||||
|
||||
//enables NAT
|
||||
//#define IPFIREWALL_NAT 1
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
SUBDIRS=compat libutil libmemstat libxo libnetgraph sysctl ifconfig route top netstat ngctl
|
||||
SUBDIRS=compat libutil libmemstat libxo libnetgraph sysctl ifconfig route top netstat ngctl ipfw
|
||||
|
||||
all:
|
||||
for d in $(SUBDIRS); do ( cd $$d; $(MAKE) all ) ; done
|
||||
|
|
|
@ -152,6 +152,52 @@ About interactive mode:
|
|||
|
||||
For more details, see [Manual page](https://www.freebsd.org/cgi/man.cgi?ngctl).
|
||||
|
||||
# ipfw
|
||||
Usage:
|
||||
```
|
||||
ipfw -P <f-stack proc_id> [-abcdefhnNqStTv] <command>
|
||||
|
||||
where <command> is one of the following:
|
||||
|
||||
add [num] [set N] [prob x] RULE-BODY
|
||||
{pipe|queue} N config PIPE-BODY
|
||||
[pipe|queue] {zero|delete|show} [N{,N}]
|
||||
nat N config {ip IPADDR|if IFNAME|log|deny_in|same_ports|unreg_only|reset|
|
||||
reverse|proxy_only|redirect_addr linkspec|
|
||||
redirect_port linkspec|redirect_proto linkspec}
|
||||
set [disable N... enable N...] | move [rule] X to Y | swap X Y | show
|
||||
set N {show|list|zero|resetlog|delete} [N{,N}] | flush
|
||||
table N {add ip[/bits] [value] | delete ip[/bits] | flush | list}
|
||||
table all {flush | list}
|
||||
|
||||
RULE-BODY: check-state [PARAMS] | ACTION [PARAMS] ADDR [OPTION_LIST]
|
||||
ACTION: check-state | allow | count | deny | unreach{,6} CODE |
|
||||
skipto N | {divert|tee} PORT | forward ADDR |
|
||||
pipe N | queue N | nat N | setfib FIB | reass
|
||||
PARAMS: [log [logamount LOGLIMIT]] [altq QUEUE_NAME]
|
||||
ADDR: [ MAC dst src ether_type ]
|
||||
[ ip from IPADDR [ PORT ] to IPADDR [ PORTLIST ] ]
|
||||
[ ipv6|ip6 from IP6ADDR [ PORT ] to IP6ADDR [ PORTLIST ] ]
|
||||
IPADDR: [not] { any | me | ip/bits{x,y,z} | table(t[,v]) | IPLIST }
|
||||
IP6ADDR: [not] { any | me | me6 | ip6/bits | IP6LIST }
|
||||
IP6LIST: { ip6 | ip6/bits }[,IP6LIST]
|
||||
IPLIST: { ip | ip/bits | ip:mask }[,IPLIST]
|
||||
OPTION_LIST: OPTION [OPTION_LIST]
|
||||
OPTION: bridged | diverted | diverted-loopback | diverted-output |
|
||||
{dst-ip|src-ip} IPADDR | {dst-ip6|src-ip6|dst-ipv6|src-ipv6} IP6ADDR |
|
||||
{dst-port|src-port} LIST |
|
||||
estab | frag | {gid|uid} N | icmptypes LIST | in | out | ipid LIST |
|
||||
iplen LIST | ipoptions SPEC | ipprecedence | ipsec | iptos SPEC |
|
||||
ipttl LIST | ipversion VER | keep-state | layer2 | limit ... |
|
||||
icmp6types LIST | ext6hdr LIST | flow-id N[,N] | fib FIB |
|
||||
mac ... | mac-type LIST | proto LIST | {recv|xmit|via} {IF|IPADDR} |
|
||||
setup | {tcpack|tcpseq|tcpwin} NN | tcpflags SPEC | tcpoptions SPEC |
|
||||
tcpdatalen LIST | verrevpath | versrcreach | antispoof
|
||||
```
|
||||
Note [dummynet](https://www.freebsd.org/cgi/man.cgi?query=dummynet) is not supported yet.
|
||||
|
||||
For more details, see [Manual page](https://www.freebsd.org/cgi/man.cgi?ipfw) or [handbook](https://www.freebsd.org/doc/handbook/firewalls-ipfw.html).
|
||||
|
||||
# how to implement a custom tool for communicating with F-Stack process
|
||||
|
||||
Add a new FF_MSG_TYPE in ff_msg.h:
|
||||
|
|
|
@ -41,6 +41,26 @@
|
|||
#define nitems(x) (sizeof((x)) / sizeof((x)[0]))
|
||||
#endif
|
||||
|
||||
#ifndef rounddown
|
||||
#define rounddown(x, y) (((x)/(y))*(y))
|
||||
#endif
|
||||
|
||||
#ifndef rounddown2
|
||||
#define rounddown2(x, y) ((x)&(~((y)-1))) /* if y is power of two */
|
||||
#endif
|
||||
|
||||
#ifndef roundup
|
||||
#define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) /* to any y */
|
||||
#endif
|
||||
|
||||
#ifndef roundup2
|
||||
#define roundup2(x, y) (((x)+((y)-1))&(~((y)-1))) /* if y is powers of two */
|
||||
#endif
|
||||
|
||||
#ifndef powerof2
|
||||
#define powerof2(x) ((((x)-1)&(x))==0)
|
||||
#endif
|
||||
|
||||
#ifndef __FBSDID
|
||||
#define __FBSDID(s) /* nothing */
|
||||
#endif
|
||||
|
@ -49,6 +69,18 @@
|
|||
#define _PATH_ETC "/etc"
|
||||
#endif
|
||||
|
||||
#ifndef __PAST_END
|
||||
/*
|
||||
* Access a variable length array that has been declared as a fixed
|
||||
* length array.
|
||||
*/
|
||||
#define __PAST_END(array, offset) (((__typeof__(*(array)) *)(array))[offset])
|
||||
#endif
|
||||
|
||||
#ifndef ishexnumber
|
||||
#define ishexnumber(x) isxdigit(x)
|
||||
#endif
|
||||
|
||||
void *reallocf(void *ptr, size_t size);
|
||||
|
||||
int feature_present(const char *feature);
|
||||
|
@ -63,4 +95,6 @@ long long strtonum(const char *numstr, long long minval,
|
|||
|
||||
const char *getprogname(void);
|
||||
|
||||
extern int optreset;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,238 @@
|
|||
/* lint -save -library Flexelint comment for external headers */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2001 Charles Mott <cm@linktel.net>
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
* Alias.h defines the outside world interfaces for the packet aliasing
|
||||
* software.
|
||||
*
|
||||
* This software is placed into the public domain with no restrictions on its
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
#ifndef _ALIAS_H_
|
||||
#define _ALIAS_H_
|
||||
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
|
||||
#define LIBALIAS_BUF_SIZE 128
|
||||
#ifdef _KERNEL
|
||||
/*
|
||||
* The kernel version of libalias does not support these features.
|
||||
*/
|
||||
#define NO_FW_PUNCH
|
||||
#define NO_USE_SOCKETS
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The external interface to libalias, the packet aliasing engine.
|
||||
*
|
||||
* There are two sets of functions:
|
||||
*
|
||||
* PacketAlias*() the old API which doesn't take an instance pointer
|
||||
* and therefore can only have one packet engine at a time.
|
||||
*
|
||||
* LibAlias*() the new API which takes as first argument a pointer to
|
||||
* the instance of the packet aliasing engine.
|
||||
*
|
||||
* The functions otherwise correspond to each other one for one, except
|
||||
* for the LibAliasUnaliasOut()/PacketUnaliasOut() function which were
|
||||
* were misnamed in the old API.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The instance structure
|
||||
*/
|
||||
struct libalias;
|
||||
|
||||
/*
|
||||
* An anonymous structure, a pointer to which is returned from
|
||||
* PacketAliasRedirectAddr(), PacketAliasRedirectPort() or
|
||||
* PacketAliasRedirectProto(), passed to PacketAliasAddServer(),
|
||||
* and freed by PacketAliasRedirectDelete().
|
||||
*/
|
||||
struct alias_link;
|
||||
|
||||
/* Initialization and control functions. */
|
||||
struct libalias *LibAliasInit(struct libalias *);
|
||||
void LibAliasSetAddress(struct libalias *, struct in_addr _addr);
|
||||
void LibAliasSetFWBase(struct libalias *, unsigned int _base, unsigned int _num);
|
||||
void LibAliasSetSkinnyPort(struct libalias *, unsigned int _port);
|
||||
unsigned int
|
||||
LibAliasSetMode(struct libalias *, unsigned int _flags, unsigned int _mask);
|
||||
void LibAliasUninit(struct libalias *);
|
||||
|
||||
/* Packet Handling functions. */
|
||||
int LibAliasIn (struct libalias *, char *_ptr, int _maxpacketsize);
|
||||
int LibAliasOut(struct libalias *, char *_ptr, int _maxpacketsize);
|
||||
int LibAliasOutTry(struct libalias *, char *_ptr, int _maxpacketsize, int _create);
|
||||
int LibAliasUnaliasOut(struct libalias *, char *_ptr, int _maxpacketsize);
|
||||
|
||||
/* Port and address redirection functions. */
|
||||
|
||||
int
|
||||
LibAliasAddServer(struct libalias *, struct alias_link *_lnk,
|
||||
struct in_addr _addr, unsigned short _port);
|
||||
struct alias_link *
|
||||
LibAliasRedirectAddr(struct libalias *, struct in_addr _src_addr,
|
||||
struct in_addr _alias_addr);
|
||||
int LibAliasRedirectDynamic(struct libalias *, struct alias_link *_lnk);
|
||||
void LibAliasRedirectDelete(struct libalias *, struct alias_link *_lnk);
|
||||
struct alias_link *
|
||||
LibAliasRedirectPort(struct libalias *, struct in_addr _src_addr,
|
||||
unsigned short _src_port, struct in_addr _dst_addr,
|
||||
unsigned short _dst_port, struct in_addr _alias_addr,
|
||||
unsigned short _alias_port, unsigned char _proto);
|
||||
struct alias_link *
|
||||
LibAliasRedirectProto(struct libalias *, struct in_addr _src_addr,
|
||||
struct in_addr _dst_addr, struct in_addr _alias_addr,
|
||||
unsigned char _proto);
|
||||
|
||||
/* Fragment Handling functions. */
|
||||
void LibAliasFragmentIn(struct libalias *, char *_ptr, char *_ptr_fragment);
|
||||
char *LibAliasGetFragment(struct libalias *, char *_ptr);
|
||||
int LibAliasSaveFragment(struct libalias *, char *_ptr);
|
||||
|
||||
/* Miscellaneous functions. */
|
||||
int LibAliasCheckNewLink(struct libalias *);
|
||||
unsigned short
|
||||
LibAliasInternetChecksum(struct libalias *, unsigned short *_ptr, int _nbytes);
|
||||
void LibAliasSetTarget(struct libalias *, struct in_addr _target_addr);
|
||||
|
||||
/* Transparent proxying routines. */
|
||||
int LibAliasProxyRule(struct libalias *, const char *_cmd);
|
||||
|
||||
/* Module handling API */
|
||||
int LibAliasLoadModule(char *);
|
||||
int LibAliasUnLoadAllModule(void);
|
||||
int LibAliasRefreshModules(void);
|
||||
|
||||
/* Mbuf helper function. */
|
||||
struct mbuf *m_megapullup(struct mbuf *, int);
|
||||
|
||||
/*
|
||||
* Mode flags and other constants.
|
||||
*/
|
||||
|
||||
|
||||
/* Mode flags, set using PacketAliasSetMode() */
|
||||
|
||||
/*
|
||||
* If PKT_ALIAS_LOG is set, a message will be printed to /var/log/alias.log
|
||||
* every time a link is created or deleted. This is useful for debugging.
|
||||
*/
|
||||
#define PKT_ALIAS_LOG 0x01
|
||||
|
||||
/*
|
||||
* If PKT_ALIAS_DENY_INCOMING is set, then incoming connections (e.g. to ftp,
|
||||
* telnet or web servers will be prevented by the aliasing mechanism.
|
||||
*/
|
||||
#define PKT_ALIAS_DENY_INCOMING 0x02
|
||||
|
||||
/*
|
||||
* If PKT_ALIAS_SAME_PORTS is set, packets will be attempted sent from the
|
||||
* same port as they originated on. This allows e.g. rsh to work *99% of the
|
||||
* time*, but _not_ 100% (it will be slightly flakey instead of not working
|
||||
* at all). This mode bit is set by PacketAliasInit(), so it is a default
|
||||
* mode of operation.
|
||||
*/
|
||||
#define PKT_ALIAS_SAME_PORTS 0x04
|
||||
|
||||
/*
|
||||
* If PKT_ALIAS_USE_SOCKETS is set, then when partially specified links (e.g.
|
||||
* destination port and/or address is zero), the packet aliasing engine will
|
||||
* attempt to allocate a socket for the aliasing port it chooses. This will
|
||||
* avoid interference with the host machine. Fully specified links do not
|
||||
* require this. This bit is set after a call to PacketAliasInit(), so it is
|
||||
* a default mode of operation.
|
||||
*/
|
||||
#ifndef NO_USE_SOCKETS
|
||||
#define PKT_ALIAS_USE_SOCKETS 0x08
|
||||
#endif
|
||||
/*-
|
||||
* If PKT_ALIAS_UNREGISTERED_ONLY is set, then only packets with
|
||||
* unregistered source addresses will be aliased. Private
|
||||
* addresses are those in the following ranges:
|
||||
*
|
||||
* 10.0.0.0 -> 10.255.255.255
|
||||
* 172.16.0.0 -> 172.31.255.255
|
||||
* 192.168.0.0 -> 192.168.255.255
|
||||
*/
|
||||
#define PKT_ALIAS_UNREGISTERED_ONLY 0x10
|
||||
|
||||
/*
|
||||
* If PKT_ALIAS_RESET_ON_ADDR_CHANGE is set, then the table of dynamic
|
||||
* aliasing links will be reset whenever PacketAliasSetAddress() changes the
|
||||
* default aliasing address. If the default aliasing address is left
|
||||
* unchanged by this function call, then the table of dynamic aliasing links
|
||||
* will be left intact. This bit is set after a call to PacketAliasInit().
|
||||
*/
|
||||
#define PKT_ALIAS_RESET_ON_ADDR_CHANGE 0x20
|
||||
|
||||
/*
|
||||
* If PKT_ALIAS_PROXY_ONLY is set, then NAT will be disabled and only
|
||||
* transparent proxying is performed.
|
||||
*/
|
||||
#define PKT_ALIAS_PROXY_ONLY 0x40
|
||||
|
||||
/*
|
||||
* If PKT_ALIAS_REVERSE is set, the actions of PacketAliasIn() and
|
||||
* PacketAliasOut() are reversed.
|
||||
*/
|
||||
#define PKT_ALIAS_REVERSE 0x80
|
||||
|
||||
#ifndef NO_FW_PUNCH
|
||||
/*
|
||||
* If PKT_ALIAS_PUNCH_FW is set, active FTP and IRC DCC connections will
|
||||
* create a 'hole' in the firewall to allow the transfers to work. The
|
||||
* ipfw rule number that the hole is created with is controlled by
|
||||
* PacketAliasSetFWBase(). The hole will be attached to that
|
||||
* particular alias_link, so when the link goes away the hole is deleted.
|
||||
*/
|
||||
#define PKT_ALIAS_PUNCH_FW 0x100
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If PKT_ALIAS_SKIP_GLOBAL is set, nat instance is not checked for matching
|
||||
* states in 'ipfw nat global' rule.
|
||||
*/
|
||||
#define PKT_ALIAS_SKIP_GLOBAL 0x200
|
||||
|
||||
/* Function return codes. */
|
||||
#define PKT_ALIAS_ERROR -1
|
||||
#define PKT_ALIAS_OK 1
|
||||
#define PKT_ALIAS_IGNORED 2
|
||||
#define PKT_ALIAS_UNRESOLVED_FRAGMENT 3
|
||||
#define PKT_ALIAS_FOUND_HEADER_FRAGMENT 4
|
||||
|
||||
#endif /* !_ALIAS_H_ */
|
||||
|
||||
/* lint -restore */
|
|
@ -235,9 +235,20 @@ struct protoent *getprotobynumber(int proto);
|
|||
void setprotoent(int stayopen);
|
||||
void endprotoent(void);
|
||||
|
||||
struct servent *getservent(void);
|
||||
struct servent *getservbyname(const char *name, const char *proto);
|
||||
struct servent *getservbyport(int port, const char *proto);
|
||||
void setservent(int stayopen);
|
||||
void endservent(void);
|
||||
|
||||
int getnameinfo(const struct sockaddr *sa, socklen_t salen,
|
||||
char *host, size_t hostlen, char *serv, size_t servlen, int flags);
|
||||
|
||||
struct netent *getnetbyaddr(uint32_t net, int type);
|
||||
|
||||
struct hostent *gethostbyaddr(const void *addr,
|
||||
socklen_t len, int type);
|
||||
|
||||
struct hostent *gethostbyname2(const char *name, int af);
|
||||
|
||||
#endif /* !_NETDB_H_ */
|
||||
|
|
|
@ -0,0 +1,784 @@
|
|||
/* $FreeBSD$ */
|
||||
/* $KAME: icmp6.h,v 1.46 2001/04/27 15:09:48 itojun Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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.
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1982, 1986, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*
|
||||
* @(#)ip_icmp.h 8.1 (Berkeley) 6/10/93
|
||||
*/
|
||||
|
||||
#ifndef _NETINET_ICMP6_H_
|
||||
#define _NETINET_ICMP6_H_
|
||||
|
||||
#ifdef FSTACK
|
||||
#define __packed __attribute__((__packed__))
|
||||
#endif
|
||||
|
||||
#define ICMPV6_PLD_MAXLEN 1232 /* IPV6_MMTU - sizeof(struct ip6_hdr)
|
||||
- sizeof(struct icmp6_hdr) */
|
||||
|
||||
struct icmp6_hdr {
|
||||
u_int8_t icmp6_type; /* type field */
|
||||
u_int8_t icmp6_code; /* code field */
|
||||
u_int16_t icmp6_cksum; /* checksum field */
|
||||
union {
|
||||
u_int32_t icmp6_un_data32[1]; /* type-specific field */
|
||||
u_int16_t icmp6_un_data16[2]; /* type-specific field */
|
||||
u_int8_t icmp6_un_data8[4]; /* type-specific field */
|
||||
} icmp6_dataun;
|
||||
} __packed;
|
||||
|
||||
#define icmp6_data32 icmp6_dataun.icmp6_un_data32
|
||||
#define icmp6_data16 icmp6_dataun.icmp6_un_data16
|
||||
#define icmp6_data8 icmp6_dataun.icmp6_un_data8
|
||||
#define icmp6_pptr icmp6_data32[0] /* parameter prob */
|
||||
#define icmp6_mtu icmp6_data32[0] /* packet too big */
|
||||
#define icmp6_id icmp6_data16[0] /* echo request/reply */
|
||||
#define icmp6_seq icmp6_data16[1] /* echo request/reply */
|
||||
#define icmp6_maxdelay icmp6_data16[0] /* mcast group membership */
|
||||
|
||||
#define ICMP6_DST_UNREACH 1 /* dest unreachable, codes: */
|
||||
#define ICMP6_PACKET_TOO_BIG 2 /* packet too big */
|
||||
#define ICMP6_TIME_EXCEEDED 3 /* time exceeded, code: */
|
||||
#define ICMP6_PARAM_PROB 4 /* ip6 header bad */
|
||||
|
||||
#define ICMP6_ECHO_REQUEST 128 /* echo service */
|
||||
#define ICMP6_ECHO_REPLY 129 /* echo reply */
|
||||
#define MLD_LISTENER_QUERY 130 /* multicast listener query */
|
||||
#define MLD_LISTENER_REPORT 131 /* multicast listener report */
|
||||
#define MLD_LISTENER_DONE 132 /* multicast listener done */
|
||||
#define MLD_LISTENER_REDUCTION MLD_LISTENER_DONE /* RFC3542 definition */
|
||||
|
||||
/* RFC2292 decls */
|
||||
#define ICMP6_MEMBERSHIP_QUERY 130 /* group membership query */
|
||||
#define ICMP6_MEMBERSHIP_REPORT 131 /* group membership report */
|
||||
#define ICMP6_MEMBERSHIP_REDUCTION 132 /* group membership termination */
|
||||
|
||||
#ifndef _KERNEL
|
||||
/* the followings are for backward compatibility to old KAME apps. */
|
||||
#define MLD6_LISTENER_QUERY MLD_LISTENER_QUERY
|
||||
#define MLD6_LISTENER_REPORT MLD_LISTENER_REPORT
|
||||
#define MLD6_LISTENER_DONE MLD_LISTENER_DONE
|
||||
#endif
|
||||
|
||||
#define ND_ROUTER_SOLICIT 133 /* router solicitation */
|
||||
#define ND_ROUTER_ADVERT 134 /* router advertisement */
|
||||
#define ND_NEIGHBOR_SOLICIT 135 /* neighbor solicitation */
|
||||
#define ND_NEIGHBOR_ADVERT 136 /* neighbor advertisement */
|
||||
#define ND_REDIRECT 137 /* redirect */
|
||||
|
||||
#define ICMP6_ROUTER_RENUMBERING 138 /* router renumbering */
|
||||
|
||||
#define ICMP6_WRUREQUEST 139 /* who are you request */
|
||||
#define ICMP6_WRUREPLY 140 /* who are you reply */
|
||||
#define ICMP6_FQDN_QUERY 139 /* FQDN query */
|
||||
#define ICMP6_FQDN_REPLY 140 /* FQDN reply */
|
||||
#define ICMP6_NI_QUERY 139 /* node information request */
|
||||
#define ICMP6_NI_REPLY 140 /* node information reply */
|
||||
#define MLDV2_LISTENER_REPORT 143 /* RFC3810 listener report */
|
||||
|
||||
/* The definitions below are experimental. TBA */
|
||||
#define MLD_MTRACE_RESP 200 /* mtrace resp (to sender) */
|
||||
#define MLD_MTRACE 201 /* mtrace messages */
|
||||
|
||||
#ifndef _KERNEL
|
||||
#define MLD6_MTRACE_RESP MLD_MTRACE_RESP
|
||||
#define MLD6_MTRACE MLD_MTRACE
|
||||
#endif
|
||||
|
||||
#define ICMP6_MAXTYPE 201
|
||||
|
||||
#define ICMP6_DST_UNREACH_NOROUTE 0 /* no route to destination */
|
||||
#define ICMP6_DST_UNREACH_ADMIN 1 /* administratively prohibited */
|
||||
#define ICMP6_DST_UNREACH_NOTNEIGHBOR 2 /* not a neighbor(obsolete) */
|
||||
#define ICMP6_DST_UNREACH_BEYONDSCOPE 2 /* beyond scope of source address */
|
||||
#define ICMP6_DST_UNREACH_ADDR 3 /* address unreachable */
|
||||
#define ICMP6_DST_UNREACH_NOPORT 4 /* port unreachable */
|
||||
#define ICMP6_DST_UNREACH_POLICY 5 /* failed ingress/egress policy */
|
||||
#define ICMP6_DST_UNREACH_REJECT 6 /* Reject route to destination */
|
||||
#define ICMP6_DST_UNREACH_SRCROUTE 7 /* Error in source routing header */
|
||||
|
||||
#define ICMP6_TIME_EXCEED_TRANSIT 0 /* ttl==0 in transit */
|
||||
#define ICMP6_TIME_EXCEED_REASSEMBLY 1 /* ttl==0 in reass */
|
||||
|
||||
#define ICMP6_PARAMPROB_HEADER 0 /* erroneous header field */
|
||||
#define ICMP6_PARAMPROB_NEXTHEADER 1 /* unrecognized next header */
|
||||
#define ICMP6_PARAMPROB_OPTION 2 /* unrecognized option */
|
||||
|
||||
#define ICMP6_INFOMSG_MASK 0x80 /* all informational messages */
|
||||
|
||||
#define ICMP6_NI_SUBJ_IPV6 0 /* Query Subject is an IPv6 address */
|
||||
#define ICMP6_NI_SUBJ_FQDN 1 /* Query Subject is a Domain name */
|
||||
#define ICMP6_NI_SUBJ_IPV4 2 /* Query Subject is an IPv4 address */
|
||||
|
||||
#define ICMP6_NI_SUCCESS 0 /* node information successful reply */
|
||||
#define ICMP6_NI_REFUSED 1 /* node information request is refused */
|
||||
#define ICMP6_NI_UNKNOWN 2 /* unknown Qtype */
|
||||
|
||||
#define ICMP6_ROUTER_RENUMBERING_COMMAND 0 /* rr command */
|
||||
#define ICMP6_ROUTER_RENUMBERING_RESULT 1 /* rr result */
|
||||
#define ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET 255 /* rr seq num reset */
|
||||
|
||||
/* Used in kernel only */
|
||||
#define ND_REDIRECT_ONLINK 0 /* redirect to an on-link node */
|
||||
#define ND_REDIRECT_ROUTER 1 /* redirect to a better router */
|
||||
|
||||
/*
|
||||
* Multicast Listener Discovery
|
||||
*/
|
||||
struct mld_hdr {
|
||||
struct icmp6_hdr mld_icmp6_hdr;
|
||||
struct in6_addr mld_addr; /* multicast address */
|
||||
} __packed;
|
||||
|
||||
/* definitions to provide backward compatibility to old KAME applications */
|
||||
#ifndef _KERNEL
|
||||
#define mld6_hdr mld_hdr
|
||||
#define mld6_type mld_type
|
||||
#define mld6_code mld_code
|
||||
#define mld6_cksum mld_cksum
|
||||
#define mld6_maxdelay mld_maxdelay
|
||||
#define mld6_reserved mld_reserved
|
||||
#define mld6_addr mld_addr
|
||||
#endif
|
||||
|
||||
/* shortcut macro definitions */
|
||||
#define mld_type mld_icmp6_hdr.icmp6_type
|
||||
#define mld_code mld_icmp6_hdr.icmp6_code
|
||||
#define mld_cksum mld_icmp6_hdr.icmp6_cksum
|
||||
#define mld_maxdelay mld_icmp6_hdr.icmp6_data16[0]
|
||||
#define mld_reserved mld_icmp6_hdr.icmp6_data16[1]
|
||||
#define mld_v2_reserved mld_icmp6_hdr.icmp6_data16[0]
|
||||
#define mld_v2_numrecs mld_icmp6_hdr.icmp6_data16[1]
|
||||
|
||||
/*
|
||||
* Neighbor Discovery
|
||||
*/
|
||||
|
||||
struct nd_router_solicit { /* router solicitation */
|
||||
struct icmp6_hdr nd_rs_hdr;
|
||||
/* could be followed by options */
|
||||
} __packed;
|
||||
|
||||
#define nd_rs_type nd_rs_hdr.icmp6_type
|
||||
#define nd_rs_code nd_rs_hdr.icmp6_code
|
||||
#define nd_rs_cksum nd_rs_hdr.icmp6_cksum
|
||||
#define nd_rs_reserved nd_rs_hdr.icmp6_data32[0]
|
||||
|
||||
struct nd_router_advert { /* router advertisement */
|
||||
struct icmp6_hdr nd_ra_hdr;
|
||||
u_int32_t nd_ra_reachable; /* reachable time */
|
||||
u_int32_t nd_ra_retransmit; /* retransmit timer */
|
||||
/* could be followed by options */
|
||||
} __packed;
|
||||
|
||||
#define nd_ra_type nd_ra_hdr.icmp6_type
|
||||
#define nd_ra_code nd_ra_hdr.icmp6_code
|
||||
#define nd_ra_cksum nd_ra_hdr.icmp6_cksum
|
||||
#define nd_ra_curhoplimit nd_ra_hdr.icmp6_data8[0]
|
||||
#define nd_ra_flags_reserved nd_ra_hdr.icmp6_data8[1]
|
||||
#define ND_RA_FLAG_MANAGED 0x80
|
||||
#define ND_RA_FLAG_OTHER 0x40
|
||||
#define ND_RA_FLAG_HA 0x20
|
||||
|
||||
/*
|
||||
* Router preference values based on draft-draves-ipngwg-router-selection-01.
|
||||
* These are non-standard definitions.
|
||||
*/
|
||||
#define ND_RA_FLAG_RTPREF_MASK 0x18 /* 00011000 */
|
||||
|
||||
#define ND_RA_FLAG_RTPREF_HIGH 0x08 /* 00001000 */
|
||||
#define ND_RA_FLAG_RTPREF_MEDIUM 0x00 /* 00000000 */
|
||||
#define ND_RA_FLAG_RTPREF_LOW 0x18 /* 00011000 */
|
||||
#define ND_RA_FLAG_RTPREF_RSV 0x10 /* 00010000 */
|
||||
|
||||
#define nd_ra_router_lifetime nd_ra_hdr.icmp6_data16[1]
|
||||
|
||||
struct nd_neighbor_solicit { /* neighbor solicitation */
|
||||
struct icmp6_hdr nd_ns_hdr;
|
||||
struct in6_addr nd_ns_target; /*target address */
|
||||
/* could be followed by options */
|
||||
} __packed;
|
||||
|
||||
#define nd_ns_type nd_ns_hdr.icmp6_type
|
||||
#define nd_ns_code nd_ns_hdr.icmp6_code
|
||||
#define nd_ns_cksum nd_ns_hdr.icmp6_cksum
|
||||
#define nd_ns_reserved nd_ns_hdr.icmp6_data32[0]
|
||||
|
||||
struct nd_neighbor_advert { /* neighbor advertisement */
|
||||
struct icmp6_hdr nd_na_hdr;
|
||||
struct in6_addr nd_na_target; /* target address */
|
||||
/* could be followed by options */
|
||||
} __packed;
|
||||
|
||||
#define nd_na_type nd_na_hdr.icmp6_type
|
||||
#define nd_na_code nd_na_hdr.icmp6_code
|
||||
#define nd_na_cksum nd_na_hdr.icmp6_cksum
|
||||
#define nd_na_flags_reserved nd_na_hdr.icmp6_data32[0]
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
#define ND_NA_FLAG_ROUTER 0x80000000
|
||||
#define ND_NA_FLAG_SOLICITED 0x40000000
|
||||
#define ND_NA_FLAG_OVERRIDE 0x20000000
|
||||
#else
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
#define ND_NA_FLAG_ROUTER 0x80
|
||||
#define ND_NA_FLAG_SOLICITED 0x40
|
||||
#define ND_NA_FLAG_OVERRIDE 0x20
|
||||
#endif
|
||||
#endif
|
||||
|
||||
struct nd_redirect { /* redirect */
|
||||
struct icmp6_hdr nd_rd_hdr;
|
||||
struct in6_addr nd_rd_target; /* target address */
|
||||
struct in6_addr nd_rd_dst; /* destination address */
|
||||
/* could be followed by options */
|
||||
} __packed;
|
||||
|
||||
#define nd_rd_type nd_rd_hdr.icmp6_type
|
||||
#define nd_rd_code nd_rd_hdr.icmp6_code
|
||||
#define nd_rd_cksum nd_rd_hdr.icmp6_cksum
|
||||
#define nd_rd_reserved nd_rd_hdr.icmp6_data32[0]
|
||||
|
||||
struct nd_opt_hdr { /* Neighbor discovery option header */
|
||||
u_int8_t nd_opt_type;
|
||||
u_int8_t nd_opt_len;
|
||||
/* followed by option specific data*/
|
||||
} __packed;
|
||||
|
||||
#define ND_OPT_SOURCE_LINKADDR 1
|
||||
#define ND_OPT_TARGET_LINKADDR 2
|
||||
#define ND_OPT_PREFIX_INFORMATION 3
|
||||
#define ND_OPT_REDIRECTED_HEADER 4
|
||||
#define ND_OPT_MTU 5
|
||||
#define ND_OPT_NONCE 14 /* RFC 3971 */
|
||||
#define ND_OPT_ROUTE_INFO 24 /* RFC 4191 */
|
||||
#define ND_OPT_RDNSS 25 /* RFC 6106 */
|
||||
#define ND_OPT_DNSSL 31 /* RFC 6106 */
|
||||
#define ND_OPT_MAX 31
|
||||
|
||||
struct nd_opt_prefix_info { /* prefix information */
|
||||
u_int8_t nd_opt_pi_type;
|
||||
u_int8_t nd_opt_pi_len;
|
||||
u_int8_t nd_opt_pi_prefix_len;
|
||||
u_int8_t nd_opt_pi_flags_reserved;
|
||||
u_int32_t nd_opt_pi_valid_time;
|
||||
u_int32_t nd_opt_pi_preferred_time;
|
||||
u_int32_t nd_opt_pi_reserved2;
|
||||
struct in6_addr nd_opt_pi_prefix;
|
||||
} __packed;
|
||||
|
||||
#define ND_OPT_PI_FLAG_ONLINK 0x80
|
||||
#define ND_OPT_PI_FLAG_AUTO 0x40
|
||||
|
||||
struct nd_opt_rd_hdr { /* redirected header */
|
||||
u_int8_t nd_opt_rh_type;
|
||||
u_int8_t nd_opt_rh_len;
|
||||
u_int16_t nd_opt_rh_reserved1;
|
||||
u_int32_t nd_opt_rh_reserved2;
|
||||
/* followed by IP header and data */
|
||||
} __packed;
|
||||
|
||||
struct nd_opt_mtu { /* MTU option */
|
||||
u_int8_t nd_opt_mtu_type;
|
||||
u_int8_t nd_opt_mtu_len;
|
||||
u_int16_t nd_opt_mtu_reserved;
|
||||
u_int32_t nd_opt_mtu_mtu;
|
||||
} __packed;
|
||||
|
||||
#define ND_OPT_NONCE_LEN ((1 * 8) - 2)
|
||||
#if ((ND_OPT_NONCE_LEN + 2) % 8) != 0
|
||||
#error "(ND_OPT_NONCE_LEN + 2) must be a multiple of 8."
|
||||
#endif
|
||||
struct nd_opt_nonce { /* nonce option */
|
||||
u_int8_t nd_opt_nonce_type;
|
||||
u_int8_t nd_opt_nonce_len;
|
||||
u_int8_t nd_opt_nonce[ND_OPT_NONCE_LEN];
|
||||
} __packed;
|
||||
|
||||
struct nd_opt_route_info { /* route info */
|
||||
u_int8_t nd_opt_rti_type;
|
||||
u_int8_t nd_opt_rti_len;
|
||||
u_int8_t nd_opt_rti_prefixlen;
|
||||
u_int8_t nd_opt_rti_flags;
|
||||
u_int32_t nd_opt_rti_lifetime;
|
||||
/* prefix follows */
|
||||
} __packed;
|
||||
|
||||
struct nd_opt_rdnss { /* RDNSS option (RFC 6106) */
|
||||
u_int8_t nd_opt_rdnss_type;
|
||||
u_int8_t nd_opt_rdnss_len;
|
||||
u_int16_t nd_opt_rdnss_reserved;
|
||||
u_int32_t nd_opt_rdnss_lifetime;
|
||||
/* followed by list of recursive DNS servers */
|
||||
} __packed;
|
||||
|
||||
struct nd_opt_dnssl { /* DNSSL option (RFC 6106) */
|
||||
u_int8_t nd_opt_dnssl_type;
|
||||
u_int8_t nd_opt_dnssl_len;
|
||||
u_int16_t nd_opt_dnssl_reserved;
|
||||
u_int32_t nd_opt_dnssl_lifetime;
|
||||
/* followed by list of DNS search domains */
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* icmp6 namelookup
|
||||
*/
|
||||
|
||||
struct icmp6_namelookup {
|
||||
struct icmp6_hdr icmp6_nl_hdr;
|
||||
u_int8_t icmp6_nl_nonce[8];
|
||||
int32_t icmp6_nl_ttl;
|
||||
#if 0
|
||||
u_int8_t icmp6_nl_len;
|
||||
u_int8_t icmp6_nl_name[3];
|
||||
#endif
|
||||
/* could be followed by options */
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* icmp6 node information
|
||||
*/
|
||||
struct icmp6_nodeinfo {
|
||||
struct icmp6_hdr icmp6_ni_hdr;
|
||||
u_int8_t icmp6_ni_nonce[8];
|
||||
/* could be followed by reply data */
|
||||
} __packed;
|
||||
|
||||
#define ni_type icmp6_ni_hdr.icmp6_type
|
||||
#define ni_code icmp6_ni_hdr.icmp6_code
|
||||
#define ni_cksum icmp6_ni_hdr.icmp6_cksum
|
||||
#define ni_qtype icmp6_ni_hdr.icmp6_data16[0]
|
||||
#define ni_flags icmp6_ni_hdr.icmp6_data16[1]
|
||||
|
||||
#define NI_QTYPE_NOOP 0 /* NOOP */
|
||||
#define NI_QTYPE_SUPTYPES 1 /* Supported Qtypes */
|
||||
#define NI_QTYPE_FQDN 2 /* FQDN (draft 04) */
|
||||
#define NI_QTYPE_DNSNAME 2 /* DNS Name */
|
||||
#define NI_QTYPE_NODEADDR 3 /* Node Addresses */
|
||||
#define NI_QTYPE_IPV4ADDR 4 /* IPv4 Addresses */
|
||||
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
#define NI_SUPTYPE_FLAG_COMPRESS 0x1
|
||||
#define NI_FQDN_FLAG_VALIDTTL 0x1
|
||||
#elif BYTE_ORDER == LITTLE_ENDIAN
|
||||
#define NI_SUPTYPE_FLAG_COMPRESS 0x0100
|
||||
#define NI_FQDN_FLAG_VALIDTTL 0x0100
|
||||
#endif
|
||||
|
||||
#ifdef NAME_LOOKUPS_04
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
#define NI_NODEADDR_FLAG_LINKLOCAL 0x1
|
||||
#define NI_NODEADDR_FLAG_SITELOCAL 0x2
|
||||
#define NI_NODEADDR_FLAG_GLOBAL 0x4
|
||||
#define NI_NODEADDR_FLAG_ALL 0x8
|
||||
#define NI_NODEADDR_FLAG_TRUNCATE 0x10
|
||||
#define NI_NODEADDR_FLAG_ANYCAST 0x20 /* just experimental. not in spec */
|
||||
#elif BYTE_ORDER == LITTLE_ENDIAN
|
||||
#define NI_NODEADDR_FLAG_LINKLOCAL 0x0100
|
||||
#define NI_NODEADDR_FLAG_SITELOCAL 0x0200
|
||||
#define NI_NODEADDR_FLAG_GLOBAL 0x0400
|
||||
#define NI_NODEADDR_FLAG_ALL 0x0800
|
||||
#define NI_NODEADDR_FLAG_TRUNCATE 0x1000
|
||||
#define NI_NODEADDR_FLAG_ANYCAST 0x2000 /* just experimental. not in spec */
|
||||
#endif
|
||||
#else /* draft-ietf-ipngwg-icmp-name-lookups-05 (and later?) */
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
#define NI_NODEADDR_FLAG_TRUNCATE 0x1
|
||||
#define NI_NODEADDR_FLAG_ALL 0x2
|
||||
#define NI_NODEADDR_FLAG_COMPAT 0x4
|
||||
#define NI_NODEADDR_FLAG_LINKLOCAL 0x8
|
||||
#define NI_NODEADDR_FLAG_SITELOCAL 0x10
|
||||
#define NI_NODEADDR_FLAG_GLOBAL 0x20
|
||||
#define NI_NODEADDR_FLAG_ANYCAST 0x40 /* just experimental. not in spec */
|
||||
#elif BYTE_ORDER == LITTLE_ENDIAN
|
||||
#define NI_NODEADDR_FLAG_TRUNCATE 0x0100
|
||||
#define NI_NODEADDR_FLAG_ALL 0x0200
|
||||
#define NI_NODEADDR_FLAG_COMPAT 0x0400
|
||||
#define NI_NODEADDR_FLAG_LINKLOCAL 0x0800
|
||||
#define NI_NODEADDR_FLAG_SITELOCAL 0x1000
|
||||
#define NI_NODEADDR_FLAG_GLOBAL 0x2000
|
||||
#define NI_NODEADDR_FLAG_ANYCAST 0x4000 /* just experimental. not in spec */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
struct ni_reply_fqdn {
|
||||
u_int32_t ni_fqdn_ttl; /* TTL */
|
||||
u_int8_t ni_fqdn_namelen; /* length in octets of the FQDN */
|
||||
u_int8_t ni_fqdn_name[3]; /* XXX: alignment */
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* Router Renumbering. as router-renum-08.txt
|
||||
*/
|
||||
struct icmp6_router_renum { /* router renumbering header */
|
||||
struct icmp6_hdr rr_hdr;
|
||||
u_int8_t rr_segnum;
|
||||
u_int8_t rr_flags;
|
||||
u_int16_t rr_maxdelay;
|
||||
u_int32_t rr_reserved;
|
||||
} __packed;
|
||||
|
||||
#define ICMP6_RR_FLAGS_TEST 0x80
|
||||
#define ICMP6_RR_FLAGS_REQRESULT 0x40
|
||||
#define ICMP6_RR_FLAGS_FORCEAPPLY 0x20
|
||||
#define ICMP6_RR_FLAGS_SPECSITE 0x10
|
||||
#define ICMP6_RR_FLAGS_PREVDONE 0x08
|
||||
|
||||
#define rr_type rr_hdr.icmp6_type
|
||||
#define rr_code rr_hdr.icmp6_code
|
||||
#define rr_cksum rr_hdr.icmp6_cksum
|
||||
#define rr_seqnum rr_hdr.icmp6_data32[0]
|
||||
|
||||
struct rr_pco_match { /* match prefix part */
|
||||
u_int8_t rpm_code;
|
||||
u_int8_t rpm_len;
|
||||
u_int8_t rpm_ordinal;
|
||||
u_int8_t rpm_matchlen;
|
||||
u_int8_t rpm_minlen;
|
||||
u_int8_t rpm_maxlen;
|
||||
u_int16_t rpm_reserved;
|
||||
struct in6_addr rpm_prefix;
|
||||
} __packed;
|
||||
|
||||
#define RPM_PCO_ADD 1
|
||||
#define RPM_PCO_CHANGE 2
|
||||
#define RPM_PCO_SETGLOBAL 3
|
||||
#define RPM_PCO_MAX 4
|
||||
|
||||
struct rr_pco_use { /* use prefix part */
|
||||
u_int8_t rpu_uselen;
|
||||
u_int8_t rpu_keeplen;
|
||||
u_int8_t rpu_ramask;
|
||||
u_int8_t rpu_raflags;
|
||||
u_int32_t rpu_vltime;
|
||||
u_int32_t rpu_pltime;
|
||||
u_int32_t rpu_flags;
|
||||
struct in6_addr rpu_prefix;
|
||||
} __packed;
|
||||
#define ICMP6_RR_PCOUSE_RAFLAGS_ONLINK 0x80
|
||||
#define ICMP6_RR_PCOUSE_RAFLAGS_AUTO 0x40
|
||||
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
#define ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME 0x80000000
|
||||
#define ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME 0x40000000
|
||||
#elif BYTE_ORDER == LITTLE_ENDIAN
|
||||
#define ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME 0x80
|
||||
#define ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME 0x40
|
||||
#endif
|
||||
|
||||
struct rr_result { /* router renumbering result message */
|
||||
u_int16_t rrr_flags;
|
||||
u_int8_t rrr_ordinal;
|
||||
u_int8_t rrr_matchedlen;
|
||||
u_int32_t rrr_ifid;
|
||||
struct in6_addr rrr_prefix;
|
||||
} __packed;
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
#define ICMP6_RR_RESULT_FLAGS_OOB 0x0002
|
||||
#define ICMP6_RR_RESULT_FLAGS_FORBIDDEN 0x0001
|
||||
#elif BYTE_ORDER == LITTLE_ENDIAN
|
||||
#define ICMP6_RR_RESULT_FLAGS_OOB 0x0200
|
||||
#define ICMP6_RR_RESULT_FLAGS_FORBIDDEN 0x0100
|
||||
#endif
|
||||
|
||||
/*
|
||||
* icmp6 filter structures.
|
||||
*/
|
||||
|
||||
struct icmp6_filter {
|
||||
u_int32_t icmp6_filt[8];
|
||||
};
|
||||
|
||||
#ifdef _KERNEL
|
||||
#define ICMP6_FILTER_SETPASSALL(filterp) \
|
||||
do { \
|
||||
int i; u_char *p; \
|
||||
p = (u_char *)filterp; \
|
||||
for (i = 0; i < sizeof(struct icmp6_filter); i++) \
|
||||
p[i] = 0xff; \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
#define ICMP6_FILTER_SETBLOCKALL(filterp) \
|
||||
bzero(filterp, sizeof(struct icmp6_filter))
|
||||
#else /* _KERNEL */
|
||||
#define ICMP6_FILTER_SETPASSALL(filterp) \
|
||||
memset(filterp, 0xff, sizeof(struct icmp6_filter))
|
||||
#define ICMP6_FILTER_SETBLOCKALL(filterp) \
|
||||
memset(filterp, 0x00, sizeof(struct icmp6_filter))
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#define ICMP6_FILTER_SETPASS(type, filterp) \
|
||||
(((filterp)->icmp6_filt[(type) >> 5]) |= (1 << ((type) & 31)))
|
||||
#define ICMP6_FILTER_SETBLOCK(type, filterp) \
|
||||
(((filterp)->icmp6_filt[(type) >> 5]) &= ~(1 << ((type) & 31)))
|
||||
#define ICMP6_FILTER_WILLPASS(type, filterp) \
|
||||
((((filterp)->icmp6_filt[(type) >> 5]) & (1 << ((type) & 31))) != 0)
|
||||
#define ICMP6_FILTER_WILLBLOCK(type, filterp) \
|
||||
((((filterp)->icmp6_filt[(type) >> 5]) & (1 << ((type) & 31))) == 0)
|
||||
|
||||
/*
|
||||
* Variables related to this implementation
|
||||
* of the internet control message protocol version 6.
|
||||
*/
|
||||
struct icmp6errstat {
|
||||
uint64_t icp6errs_dst_unreach_noroute;
|
||||
uint64_t icp6errs_dst_unreach_admin;
|
||||
uint64_t icp6errs_dst_unreach_beyondscope;
|
||||
uint64_t icp6errs_dst_unreach_addr;
|
||||
uint64_t icp6errs_dst_unreach_noport;
|
||||
uint64_t icp6errs_packet_too_big;
|
||||
uint64_t icp6errs_time_exceed_transit;
|
||||
uint64_t icp6errs_time_exceed_reassembly;
|
||||
uint64_t icp6errs_paramprob_header;
|
||||
uint64_t icp6errs_paramprob_nextheader;
|
||||
uint64_t icp6errs_paramprob_option;
|
||||
uint64_t icp6errs_redirect; /* we regard redirect as an error here */
|
||||
uint64_t icp6errs_unknown;
|
||||
};
|
||||
|
||||
struct icmp6stat {
|
||||
/* statistics related to icmp6 packets generated */
|
||||
uint64_t icp6s_error; /* # of calls to icmp6_error */
|
||||
uint64_t icp6s_canterror; /* no error 'cuz old was icmp */
|
||||
uint64_t icp6s_toofreq; /* no error 'cuz rate limitation */
|
||||
uint64_t icp6s_outhist[256];
|
||||
/* statistics related to input message processed */
|
||||
uint64_t icp6s_badcode; /* icmp6_code out of range */
|
||||
uint64_t icp6s_tooshort; /* packet < sizeof(struct icmp6_hdr) */
|
||||
uint64_t icp6s_checksum; /* bad checksum */
|
||||
uint64_t icp6s_badlen; /* calculated bound mismatch */
|
||||
/*
|
||||
* number of responses: this member is inherited from netinet code, but
|
||||
* for netinet6 code, it is already available in icp6s_outhist[].
|
||||
*/
|
||||
uint64_t icp6s_reflect;
|
||||
uint64_t icp6s_inhist[256];
|
||||
uint64_t icp6s_nd_toomanyopt; /* too many ND options */
|
||||
struct icmp6errstat icp6s_outerrhist;
|
||||
#define icp6s_odst_unreach_noroute \
|
||||
icp6s_outerrhist.icp6errs_dst_unreach_noroute
|
||||
#define icp6s_odst_unreach_admin icp6s_outerrhist.icp6errs_dst_unreach_admin
|
||||
#define icp6s_odst_unreach_beyondscope \
|
||||
icp6s_outerrhist.icp6errs_dst_unreach_beyondscope
|
||||
#define icp6s_odst_unreach_addr icp6s_outerrhist.icp6errs_dst_unreach_addr
|
||||
#define icp6s_odst_unreach_noport icp6s_outerrhist.icp6errs_dst_unreach_noport
|
||||
#define icp6s_opacket_too_big icp6s_outerrhist.icp6errs_packet_too_big
|
||||
#define icp6s_otime_exceed_transit \
|
||||
icp6s_outerrhist.icp6errs_time_exceed_transit
|
||||
#define icp6s_otime_exceed_reassembly \
|
||||
icp6s_outerrhist.icp6errs_time_exceed_reassembly
|
||||
#define icp6s_oparamprob_header icp6s_outerrhist.icp6errs_paramprob_header
|
||||
#define icp6s_oparamprob_nextheader \
|
||||
icp6s_outerrhist.icp6errs_paramprob_nextheader
|
||||
#define icp6s_oparamprob_option icp6s_outerrhist.icp6errs_paramprob_option
|
||||
#define icp6s_oredirect icp6s_outerrhist.icp6errs_redirect
|
||||
#define icp6s_ounknown icp6s_outerrhist.icp6errs_unknown
|
||||
uint64_t icp6s_pmtuchg; /* path MTU changes */
|
||||
uint64_t icp6s_nd_badopt; /* bad ND options */
|
||||
uint64_t icp6s_badns; /* bad neighbor solicitation */
|
||||
uint64_t icp6s_badna; /* bad neighbor advertisement */
|
||||
uint64_t icp6s_badrs; /* bad router advertisement */
|
||||
uint64_t icp6s_badra; /* bad router advertisement */
|
||||
uint64_t icp6s_badredirect; /* bad redirect message */
|
||||
};
|
||||
|
||||
#ifdef _KERNEL
|
||||
#include <sys/counter.h>
|
||||
|
||||
VNET_PCPUSTAT_DECLARE(struct icmp6stat, icmp6stat);
|
||||
/*
|
||||
* In-kernel consumers can use these accessor macros directly to update
|
||||
* stats.
|
||||
*/
|
||||
#define ICMP6STAT_ADD(name, val) \
|
||||
VNET_PCPUSTAT_ADD(struct icmp6stat, icmp6stat, name, (val))
|
||||
#define ICMP6STAT_INC(name) ICMP6STAT_ADD(name, 1)
|
||||
|
||||
/*
|
||||
* Kernel module consumers must use this accessor macro.
|
||||
*/
|
||||
void kmod_icmp6stat_inc(int statnum);
|
||||
#define KMOD_ICMP6STAT_INC(name) \
|
||||
kmod_icmp6stat_inc(offsetof(struct icmp6stat, name) / sizeof(uint64_t))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Names for ICMP sysctl objects
|
||||
*/
|
||||
#define ICMPV6CTL_STATS 1
|
||||
#define ICMPV6CTL_REDIRACCEPT 2 /* accept/process redirects */
|
||||
#define ICMPV6CTL_REDIRTIMEOUT 3 /* redirect cache time */
|
||||
#if 0 /*obsoleted*/
|
||||
#define ICMPV6CTL_ERRRATELIMIT 5 /* ICMPv6 error rate limitation */
|
||||
#endif
|
||||
#define ICMPV6CTL_ND6_PRUNE 6
|
||||
#define ICMPV6CTL_ND6_DELAY 8
|
||||
#define ICMPV6CTL_ND6_UMAXTRIES 9
|
||||
#define ICMPV6CTL_ND6_MMAXTRIES 10
|
||||
#define ICMPV6CTL_ND6_USELOOPBACK 11
|
||||
/*#define ICMPV6CTL_ND6_PROXYALL 12 obsoleted, do not reuse here */
|
||||
#define ICMPV6CTL_NODEINFO 13
|
||||
#define ICMPV6CTL_ERRPPSLIMIT 14 /* ICMPv6 error pps limitation */
|
||||
#define ICMPV6CTL_ND6_MAXNUDHINT 15
|
||||
#define ICMPV6CTL_MTUDISC_HIWAT 16
|
||||
#define ICMPV6CTL_MTUDISC_LOWAT 17
|
||||
#define ICMPV6CTL_ND6_DEBUG 18
|
||||
#define ICMPV6CTL_ND6_DRLIST 19
|
||||
#define ICMPV6CTL_ND6_PRLIST 20
|
||||
#define ICMPV6CTL_MLD_MAXSRCFILTER 21
|
||||
#define ICMPV6CTL_MLD_SOMAXSRC 22
|
||||
#define ICMPV6CTL_MLD_VERSION 23
|
||||
#define ICMPV6CTL_ND6_MAXQLEN 24
|
||||
#define ICMPV6CTL_NODEINFO_OLDMCPREFIX 25
|
||||
#define ICMPV6CTL_MAXID 26
|
||||
|
||||
#define RTF_PROBEMTU RTF_PROTO1
|
||||
|
||||
#ifdef _KERNEL
|
||||
# ifdef __STDC__
|
||||
struct rtentry;
|
||||
struct rttimer;
|
||||
struct in6_multi;
|
||||
# endif
|
||||
void icmp6_paramerror(struct mbuf *, int);
|
||||
void icmp6_error(struct mbuf *, int, int, int);
|
||||
void icmp6_error2(struct mbuf *, int, int, int, struct ifnet *);
|
||||
int icmp6_input(struct mbuf **, int *, int);
|
||||
void icmp6_fasttimo(void);
|
||||
void icmp6_slowtimo(void);
|
||||
void icmp6_reflect(struct mbuf *, size_t);
|
||||
void icmp6_prepare(struct mbuf *);
|
||||
void icmp6_redirect_input(struct mbuf *, int);
|
||||
void icmp6_redirect_output(struct mbuf *, struct rtentry *);
|
||||
|
||||
struct ip6ctlparam;
|
||||
void icmp6_mtudisc_update(struct ip6ctlparam *, int);
|
||||
|
||||
/* XXX: is this the right place for these macros? */
|
||||
#define icmp6_ifstat_inc(ifp, tag) \
|
||||
do { \
|
||||
if (ifp) \
|
||||
counter_u64_add(((struct in6_ifextra *) \
|
||||
((ifp)->if_afdata[AF_INET6]))->icmp6_ifstat[\
|
||||
offsetof(struct icmp6_ifstat, tag) / sizeof(uint64_t)], 1);\
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define icmp6_ifoutstat_inc(ifp, type, code) \
|
||||
do { \
|
||||
icmp6_ifstat_inc(ifp, ifs6_out_msg); \
|
||||
if (type < ICMP6_INFOMSG_MASK) \
|
||||
icmp6_ifstat_inc(ifp, ifs6_out_error); \
|
||||
switch (type) { \
|
||||
case ICMP6_DST_UNREACH: \
|
||||
icmp6_ifstat_inc(ifp, ifs6_out_dstunreach); \
|
||||
if (code == ICMP6_DST_UNREACH_ADMIN) \
|
||||
icmp6_ifstat_inc(ifp, ifs6_out_adminprohib); \
|
||||
break; \
|
||||
case ICMP6_PACKET_TOO_BIG: \
|
||||
icmp6_ifstat_inc(ifp, ifs6_out_pkttoobig); \
|
||||
break; \
|
||||
case ICMP6_TIME_EXCEEDED: \
|
||||
icmp6_ifstat_inc(ifp, ifs6_out_timeexceed); \
|
||||
break; \
|
||||
case ICMP6_PARAM_PROB: \
|
||||
icmp6_ifstat_inc(ifp, ifs6_out_paramprob); \
|
||||
break; \
|
||||
case ICMP6_ECHO_REQUEST: \
|
||||
icmp6_ifstat_inc(ifp, ifs6_out_echo); \
|
||||
break; \
|
||||
case ICMP6_ECHO_REPLY: \
|
||||
icmp6_ifstat_inc(ifp, ifs6_out_echoreply); \
|
||||
break; \
|
||||
case MLD_LISTENER_QUERY: \
|
||||
icmp6_ifstat_inc(ifp, ifs6_out_mldquery); \
|
||||
break; \
|
||||
case MLD_LISTENER_REPORT: \
|
||||
icmp6_ifstat_inc(ifp, ifs6_out_mldreport); \
|
||||
break; \
|
||||
case MLD_LISTENER_DONE: \
|
||||
icmp6_ifstat_inc(ifp, ifs6_out_mlddone); \
|
||||
break; \
|
||||
case ND_ROUTER_SOLICIT: \
|
||||
icmp6_ifstat_inc(ifp, ifs6_out_routersolicit); \
|
||||
break; \
|
||||
case ND_ROUTER_ADVERT: \
|
||||
icmp6_ifstat_inc(ifp, ifs6_out_routeradvert); \
|
||||
break; \
|
||||
case ND_NEIGHBOR_SOLICIT: \
|
||||
icmp6_ifstat_inc(ifp, ifs6_out_neighborsolicit); \
|
||||
break; \
|
||||
case ND_NEIGHBOR_ADVERT: \
|
||||
icmp6_ifstat_inc(ifp, ifs6_out_neighboradvert); \
|
||||
break; \
|
||||
case ND_REDIRECT: \
|
||||
icmp6_ifstat_inc(ifp, ifs6_out_redirect); \
|
||||
break; \
|
||||
} \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
VNET_DECLARE(int, icmp6_rediraccept); /* accept/process redirects */
|
||||
VNET_DECLARE(int, icmp6_redirtimeout); /* cache time for redirect routes */
|
||||
|
||||
#define V_icmp6_rediraccept VNET(icmp6_rediraccept)
|
||||
#define V_icmp6_redirtimeout VNET(icmp6_redirtimeout)
|
||||
|
||||
#define ICMP6_NODEINFO_FQDNOK 0x1
|
||||
#define ICMP6_NODEINFO_NODEADDROK 0x2
|
||||
#define ICMP6_NODEINFO_TMPADDROK 0x4
|
||||
#define ICMP6_NODEINFO_GLOBALOK 0x8
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#endif /* not _NETINET_ICMP6_H_ */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
* (c) UNIX System Laboratories, Inc.
|
||||
* All or some portions of this file are derived from material licensed
|
||||
* to the University of California by American Telephone and Telegraph
|
||||
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
|
||||
* the permission of UNIX System Laboratories, Inc.
|
||||
*
|
||||
* 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.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*
|
||||
* @(#)time.h 8.3 (Berkeley) 1/21/94
|
||||
*/
|
||||
|
||||
/*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _TIMECONV_H_
|
||||
#define _TIMECONV_H_
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/_types.h>
|
||||
|
||||
#ifndef _TIME_T_DECLARED
|
||||
typedef __time_t time_t;
|
||||
#define _TIME_T_DECLARED
|
||||
#endif
|
||||
|
||||
time_t _time32_to_time(__int32_t t32);
|
||||
__int32_t _time_to_time32(time_t t);
|
||||
time_t _time64_to_time(__int64_t t64);
|
||||
__int64_t _time_to_time64(time_t t);
|
||||
long _time_to_long(time_t t);
|
||||
time_t _long_to_time(long tlong);
|
||||
int _time_to_int(time_t t);
|
||||
time_t _int_to_time(int tint);
|
||||
|
||||
#endif /* _TIMECONV_H_ */
|
|
@ -26,7 +26,8 @@
|
|||
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include "sys/ioctl.h"
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include "ff_ipc.h"
|
||||
|
||||
/*
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <rte_malloc.h>
|
||||
|
||||
#include "ff_ipc.h"
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
/*-
|
||||
* Copyright (c) 2001 FreeBSD Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* These routines are for converting time_t to fixed-bit representations
|
||||
* for use in protocols or storage. When converting time to a larger
|
||||
* representation of time_t these routines are expected to assume temporal
|
||||
* locality and use the 50-year rule to properly set the msb bits. XXX
|
||||
*
|
||||
* Redistribution and use under the terms of the COPYRIGHT file at the
|
||||
* base of the source tree.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef FSTACK
|
||||
__FBSDID("$FreeBSD$");
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <timeconv.h>
|
||||
|
||||
/*
|
||||
* Convert a 32 bit representation of time_t into time_t. XXX needs to
|
||||
* implement the 50-year rule to handle post-2038 conversions.
|
||||
*/
|
||||
time_t
|
||||
_time32_to_time(__int32_t t32)
|
||||
{
|
||||
return((time_t)t32);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert time_t to a 32 bit representation. If time_t is 64 bits we can
|
||||
* simply chop it down. The resulting 32 bit representation can be
|
||||
* converted back to a temporally local 64 bit time_t using time32_to_time.
|
||||
*/
|
||||
__int32_t
|
||||
_time_to_time32(time_t t)
|
||||
{
|
||||
return((__int32_t)t);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a 64 bit representation of time_t into time_t. If time_t is
|
||||
* represented as 32 bits we can simply chop it and not support times
|
||||
* past 2038.
|
||||
*/
|
||||
time_t
|
||||
_time64_to_time(__int64_t t64)
|
||||
{
|
||||
return((time_t)t64);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert time_t to a 64 bit representation. If time_t is represented
|
||||
* as 32 bits we simply sign-extend and do not support times past 2038.
|
||||
*/
|
||||
__int64_t
|
||||
_time_to_time64(time_t t)
|
||||
{
|
||||
return((__int64_t)t);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert to/from 'long'. Depending on the sizeof(long) this may or
|
||||
* may not require using the 50-year rule.
|
||||
*/
|
||||
long
|
||||
_time_to_long(time_t t)
|
||||
{
|
||||
if (sizeof(long) == sizeof(__int64_t))
|
||||
return(_time_to_time64(t));
|
||||
return((long)t);
|
||||
}
|
||||
|
||||
time_t
|
||||
_long_to_time(long tlong)
|
||||
{
|
||||
if (sizeof(long) == sizeof(__int32_t))
|
||||
return(_time32_to_time(tlong));
|
||||
return((time_t)tlong);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert to/from 'int'. Depending on the sizeof(int) this may or
|
||||
* may not require using the 50-year rule.
|
||||
*/
|
||||
int
|
||||
_time_to_int(time_t t)
|
||||
{
|
||||
if (sizeof(int) == sizeof(__int64_t))
|
||||
return(_time_to_time64(t));
|
||||
return((int)t);
|
||||
}
|
||||
|
||||
time_t
|
||||
_int_to_time(int tint)
|
||||
{
|
||||
if (sizeof(int) == sizeof(__int32_t))
|
||||
return(_time32_to_time(tint));
|
||||
return((time_t)tint);
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
# $FreeBSD$
|
||||
|
||||
TOPDIR?=${CURDIR}/../..
|
||||
include ${TOPDIR}/tools/opts.mk
|
||||
|
||||
PACKAGE=ipfw
|
||||
PROG= ipfw
|
||||
SRCS= ipfw2.c ipv6.c main.c nat.c tables.c compat.c
|
||||
WARNS?= 2
|
||||
|
||||
ifneq (${MK_DUMMYNET},"no")
|
||||
SRCS+= dummynet.c
|
||||
CFLAGS+= -DDUMMYNET
|
||||
endif
|
||||
|
||||
ifneq (${MK_PF},"no")
|
||||
SRCS+= altq.c
|
||||
CFLAGS+=-DPF
|
||||
endif
|
||||
|
||||
LIBADD= util
|
||||
MAN= ipfw.8
|
||||
|
||||
include ${TOPDIR}/tools/prog.mk
|
||||
|
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
* Copyright (c) 2002-2003 Luigi Rizzo
|
||||
* Copyright (c) 1996 Alex Nash, Paul Traina, Poul-Henning Kamp
|
||||
* Copyright (c) 1994 Ugen J.S.Antsilevich
|
||||
*
|
||||
* Idea and grammar partially left from:
|
||||
* Copyright (c) 1993 Daniel Boulet
|
||||
*
|
||||
* Redistribution and use in source forms, with and without modification,
|
||||
* are permitted provided that this entire comment appears intact.
|
||||
*
|
||||
* Redistribution in binary form may occur without any restrictions.
|
||||
* Obviously, it would be nice if you gave credit where credit is due
|
||||
* but requiring it would be too onerous.
|
||||
*
|
||||
* This software is provided ``AS IS'' without any warranties of any kind.
|
||||
*
|
||||
* NEW command line interface for IP firewall facility
|
||||
*
|
||||
* $FreeBSD$
|
||||
*
|
||||
* altq interface
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sockio.h>
|
||||
|
||||
#include "ipfw2.h"
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sysexits.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <net/if.h> /* IFNAMSIZ */
|
||||
#include <net/pfvar.h>
|
||||
#include <netinet/in.h> /* in_addr */
|
||||
#include <netinet/ip_fw.h>
|
||||
|
||||
/*
|
||||
* Map between current altq queue id numbers and names.
|
||||
*/
|
||||
static TAILQ_HEAD(, pf_altq) altq_entries =
|
||||
TAILQ_HEAD_INITIALIZER(altq_entries);
|
||||
|
||||
void
|
||||
altq_set_enabled(int enabled)
|
||||
{
|
||||
int pffd;
|
||||
|
||||
pffd = open("/dev/pf", O_RDWR);
|
||||
if (pffd == -1)
|
||||
err(EX_UNAVAILABLE,
|
||||
"altq support opening pf(4) control device");
|
||||
if (enabled) {
|
||||
if (ioctl(pffd, DIOCSTARTALTQ) != 0 && errno != EEXIST)
|
||||
err(EX_UNAVAILABLE, "enabling altq");
|
||||
} else {
|
||||
if (ioctl(pffd, DIOCSTOPALTQ) != 0 && errno != ENOENT)
|
||||
err(EX_UNAVAILABLE, "disabling altq");
|
||||
}
|
||||
close(pffd);
|
||||
}
|
||||
|
||||
static void
|
||||
altq_fetch(void)
|
||||
{
|
||||
struct pfioc_altq pfioc;
|
||||
struct pf_altq *altq;
|
||||
int pffd;
|
||||
unsigned int mnr;
|
||||
static int altq_fetched = 0;
|
||||
|
||||
if (altq_fetched)
|
||||
return;
|
||||
altq_fetched = 1;
|
||||
pffd = open("/dev/pf", O_RDONLY);
|
||||
if (pffd == -1) {
|
||||
warn("altq support opening pf(4) control device");
|
||||
return;
|
||||
}
|
||||
bzero(&pfioc, sizeof(pfioc));
|
||||
if (ioctl(pffd, DIOCGETALTQS, &pfioc) != 0) {
|
||||
warn("altq support getting queue list");
|
||||
close(pffd);
|
||||
return;
|
||||
}
|
||||
mnr = pfioc.nr;
|
||||
for (pfioc.nr = 0; pfioc.nr < mnr; pfioc.nr++) {
|
||||
if (ioctl(pffd, DIOCGETALTQ, &pfioc) != 0) {
|
||||
if (errno == EBUSY)
|
||||
break;
|
||||
warn("altq support getting queue list");
|
||||
close(pffd);
|
||||
return;
|
||||
}
|
||||
if (pfioc.altq.qid == 0)
|
||||
continue;
|
||||
altq = safe_calloc(1, sizeof(*altq));
|
||||
*altq = pfioc.altq;
|
||||
TAILQ_INSERT_TAIL(&altq_entries, altq, entries);
|
||||
}
|
||||
close(pffd);
|
||||
}
|
||||
|
||||
u_int32_t
|
||||
altq_name_to_qid(const char *name)
|
||||
{
|
||||
struct pf_altq *altq;
|
||||
|
||||
altq_fetch();
|
||||
TAILQ_FOREACH(altq, &altq_entries, entries)
|
||||
if (strcmp(name, altq->qname) == 0)
|
||||
break;
|
||||
if (altq == NULL)
|
||||
errx(EX_DATAERR, "altq has no queue named `%s'", name);
|
||||
return altq->qid;
|
||||
}
|
||||
|
||||
static const char *
|
||||
altq_qid_to_name(u_int32_t qid)
|
||||
{
|
||||
struct pf_altq *altq;
|
||||
|
||||
altq_fetch();
|
||||
TAILQ_FOREACH(altq, &altq_entries, entries)
|
||||
if (qid == altq->qid)
|
||||
break;
|
||||
if (altq == NULL)
|
||||
return NULL;
|
||||
return altq->qname;
|
||||
}
|
||||
|
||||
void
|
||||
print_altq_cmd(struct buf_pr *bp, ipfw_insn_altq *altqptr)
|
||||
{
|
||||
if (altqptr) {
|
||||
const char *qname;
|
||||
|
||||
qname = altq_qid_to_name(altqptr->qid);
|
||||
if (qname == NULL)
|
||||
bprintf(bp, " altq ?<%u>", altqptr->qid);
|
||||
else
|
||||
bprintf(bp, " altq %s", qname);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
* Copyright (C) 2017 THL A29 Limited, a Tencent company.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ff_ipc.h"
|
||||
|
||||
static int
|
||||
ipfw_ctl(int cmd, int level, int optname, void *optval, socklen_t *optlen)
|
||||
{
|
||||
struct ff_msg *msg, *retmsg = NULL;
|
||||
int len;
|
||||
|
||||
switch (cmd) {
|
||||
case FF_IPFW_GET:
|
||||
if (optval == NULL || optlen == NULL) {
|
||||
return EINVAL;
|
||||
}
|
||||
break;
|
||||
case FF_IPFW_SET:
|
||||
break;
|
||||
default:
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
msg = ff_ipc_msg_alloc();
|
||||
if (msg == NULL) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
len = sizeof(struct ff_ipfw_args) + *optlen + sizeof(socklen_t);
|
||||
if (len > msg->buf_len) {
|
||||
errno = EINVAL;
|
||||
ff_ipc_msg_free(msg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
msg->msg_type = FF_IPFW_CTL;
|
||||
msg->ipfw.cmd = cmd;
|
||||
msg->ipfw.level = level;
|
||||
msg->ipfw.optname = optname;
|
||||
msg->ipfw.optval = (void *)msg->buf_addr;
|
||||
msg->ipfw.optlen = (socklen_t *)(msg->buf_addr + (*optlen));
|
||||
|
||||
memcpy(msg->ipfw.optval, optval, *optlen);
|
||||
memcpy(msg->ipfw.optlen, optlen, sizeof(socklen_t));
|
||||
|
||||
int ret = ff_ipc_send(msg);
|
||||
if (ret < 0) {
|
||||
errno = EPIPE;
|
||||
ff_ipc_msg_free(msg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
do {
|
||||
if (retmsg != NULL) {
|
||||
ff_ipc_msg_free(retmsg);
|
||||
}
|
||||
ret = ff_ipc_recv(&retmsg);
|
||||
if (ret < 0) {
|
||||
errno = EPIPE;
|
||||
ff_ipc_msg_free(msg);
|
||||
return -1;
|
||||
}
|
||||
} while (msg != retmsg);
|
||||
|
||||
if (retmsg->result != 0) {
|
||||
ret = -1;
|
||||
errno = retmsg->result;
|
||||
} else {
|
||||
ret = 0;
|
||||
|
||||
if (cmd == FF_IPFW_GET) {
|
||||
memcpy(optval, retmsg->ipfw.optval, *(retmsg->ipfw.optlen));
|
||||
memcpy(optlen, retmsg->ipfw.optlen, sizeof(socklen_t));
|
||||
}
|
||||
}
|
||||
|
||||
ff_ipc_msg_free(msg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
ff_socket(int domain, int type, int protocol)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ff_getsockopt(int sockfd, int level, int optname,
|
||||
void *optval, socklen_t *optlen)
|
||||
{
|
||||
return ipfw_ctl(FF_IPFW_GET, level, optname, optval, optlen);
|
||||
}
|
||||
|
||||
int ff_setsockopt(int sockfd, int level, int optname,
|
||||
const void *optval, socklen_t optlen)
|
||||
{
|
||||
return ipfw_ctl(FF_IPFW_SET, level, optname, (void *)optval, &optlen);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,394 @@
|
|||
/*
|
||||
* Copyright (c) 2002-2003 Luigi Rizzo
|
||||
* Copyright (c) 1996 Alex Nash, Paul Traina, Poul-Henning Kamp
|
||||
* Copyright (c) 1994 Ugen J.S.Antsilevich
|
||||
*
|
||||
* Idea and grammar partially left from:
|
||||
* Copyright (c) 1993 Daniel Boulet
|
||||
*
|
||||
* Redistribution and use in source forms, with and without modification,
|
||||
* are permitted provided that this entire comment appears intact.
|
||||
*
|
||||
* Redistribution in binary form may occur without any restrictions.
|
||||
* Obviously, it would be nice if you gave credit where credit is due
|
||||
* but requiring it would be too onerous.
|
||||
*
|
||||
* This software is provided ``AS IS'' without any warranties of any kind.
|
||||
*
|
||||
* NEW command line interface for IP firewall facility
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
* Options that can be set on the command line.
|
||||
* When reading commands from a file, a subset of the options can also
|
||||
* be applied globally by specifying them before the file name.
|
||||
* After that, each line can contain its own option that changes
|
||||
* the global value.
|
||||
* XXX The context is not restored after each line.
|
||||
*/
|
||||
|
||||
struct cmdline_opts {
|
||||
/* boolean options: */
|
||||
int do_value_as_ip; /* show table value as IP */
|
||||
int do_resolv; /* try to resolve all ip to names */
|
||||
int do_time; /* Show time stamps */
|
||||
int do_quiet; /* Be quiet in add and flush */
|
||||
int do_pipe; /* this cmd refers to a pipe/queue/sched */
|
||||
int do_nat; /* this cmd refers to a nat config */
|
||||
int do_dynamic; /* display dynamic rules */
|
||||
int do_expired; /* display expired dynamic rules */
|
||||
int do_compact; /* show rules in compact mode */
|
||||
int do_force; /* do not ask for confirmation */
|
||||
int show_sets; /* display the set each rule belongs to */
|
||||
int test_only; /* only check syntax */
|
||||
int comment_only; /* only print action and comment */
|
||||
int verbose; /* be verbose on some commands */
|
||||
|
||||
/* The options below can have multiple values. */
|
||||
|
||||
int do_sort; /* field to sort results (0 = no) */
|
||||
/* valid fields are 1 and above */
|
||||
|
||||
int use_set; /* work with specified set number */
|
||||
/* 0 means all sets, otherwise apply to set use_set - 1 */
|
||||
|
||||
};
|
||||
|
||||
extern struct cmdline_opts co;
|
||||
|
||||
/*
|
||||
* _s_x is a structure that stores a string <-> token pairs, used in
|
||||
* various places in the parser. Entries are stored in arrays,
|
||||
* with an entry with s=NULL as terminator.
|
||||
* The search routines are match_token() and match_value().
|
||||
* Often, an element with x=0 contains an error string.
|
||||
*
|
||||
*/
|
||||
struct _s_x {
|
||||
char const *s;
|
||||
int x;
|
||||
};
|
||||
|
||||
extern struct _s_x f_ipdscp[];
|
||||
|
||||
enum tokens {
|
||||
TOK_NULL=0,
|
||||
|
||||
TOK_OR,
|
||||
TOK_NOT,
|
||||
TOK_STARTBRACE,
|
||||
TOK_ENDBRACE,
|
||||
|
||||
TOK_ACCEPT,
|
||||
TOK_COUNT,
|
||||
TOK_EACTION,
|
||||
TOK_PIPE,
|
||||
TOK_LINK,
|
||||
TOK_QUEUE,
|
||||
TOK_FLOWSET,
|
||||
TOK_SCHED,
|
||||
TOK_DIVERT,
|
||||
TOK_TEE,
|
||||
TOK_NETGRAPH,
|
||||
TOK_NGTEE,
|
||||
TOK_FORWARD,
|
||||
TOK_SKIPTO,
|
||||
TOK_DENY,
|
||||
TOK_REJECT,
|
||||
TOK_RESET,
|
||||
TOK_UNREACH,
|
||||
TOK_CHECKSTATE,
|
||||
TOK_NAT,
|
||||
TOK_REASS,
|
||||
TOK_CALL,
|
||||
TOK_RETURN,
|
||||
|
||||
TOK_ALTQ,
|
||||
TOK_LOG,
|
||||
TOK_TAG,
|
||||
TOK_UNTAG,
|
||||
|
||||
TOK_TAGGED,
|
||||
TOK_UID,
|
||||
TOK_GID,
|
||||
TOK_JAIL,
|
||||
TOK_IN,
|
||||
TOK_LIMIT,
|
||||
TOK_KEEPSTATE,
|
||||
TOK_LAYER2,
|
||||
TOK_OUT,
|
||||
TOK_DIVERTED,
|
||||
TOK_DIVERTEDLOOPBACK,
|
||||
TOK_DIVERTEDOUTPUT,
|
||||
TOK_XMIT,
|
||||
TOK_RECV,
|
||||
TOK_VIA,
|
||||
TOK_FRAG,
|
||||
TOK_IPOPTS,
|
||||
TOK_IPLEN,
|
||||
TOK_IPID,
|
||||
TOK_IPPRECEDENCE,
|
||||
TOK_DSCP,
|
||||
TOK_IPTOS,
|
||||
TOK_IPTTL,
|
||||
TOK_IPVER,
|
||||
TOK_ESTAB,
|
||||
TOK_SETUP,
|
||||
TOK_TCPDATALEN,
|
||||
TOK_TCPFLAGS,
|
||||
TOK_TCPOPTS,
|
||||
TOK_TCPSEQ,
|
||||
TOK_TCPACK,
|
||||
TOK_TCPWIN,
|
||||
TOK_ICMPTYPES,
|
||||
TOK_MAC,
|
||||
TOK_MACTYPE,
|
||||
TOK_VERREVPATH,
|
||||
TOK_VERSRCREACH,
|
||||
TOK_ANTISPOOF,
|
||||
TOK_IPSEC,
|
||||
TOK_COMMENT,
|
||||
|
||||
TOK_PLR,
|
||||
TOK_NOERROR,
|
||||
TOK_BUCKETS,
|
||||
TOK_DSTIP,
|
||||
TOK_SRCIP,
|
||||
TOK_DSTPORT,
|
||||
TOK_SRCPORT,
|
||||
TOK_ALL,
|
||||
TOK_MASK,
|
||||
TOK_FLOW_MASK,
|
||||
TOK_SCHED_MASK,
|
||||
TOK_BW,
|
||||
TOK_DELAY,
|
||||
TOK_PROFILE,
|
||||
TOK_BURST,
|
||||
TOK_RED,
|
||||
TOK_GRED,
|
||||
TOK_ECN,
|
||||
TOK_DROPTAIL,
|
||||
TOK_PROTO,
|
||||
#ifdef NEW_AQM
|
||||
/* AQM tokens*/
|
||||
TOK_NO_ECN,
|
||||
TOK_CODEL,
|
||||
TOK_FQ_CODEL,
|
||||
TOK_TARGET,
|
||||
TOK_INTERVAL,
|
||||
TOK_FLOWS,
|
||||
TOK_QUANTUM,
|
||||
|
||||
TOK_PIE,
|
||||
TOK_FQ_PIE,
|
||||
TOK_TUPDATE,
|
||||
TOK_MAX_BURST,
|
||||
TOK_MAX_ECNTH,
|
||||
TOK_ALPHA,
|
||||
TOK_BETA,
|
||||
TOK_CAPDROP,
|
||||
TOK_NO_CAPDROP,
|
||||
TOK_ONOFF,
|
||||
TOK_DRE,
|
||||
TOK_TS,
|
||||
TOK_DERAND,
|
||||
TOK_NO_DERAND,
|
||||
#endif
|
||||
/* dummynet tokens */
|
||||
TOK_WEIGHT,
|
||||
TOK_LMAX,
|
||||
TOK_PRI,
|
||||
TOK_TYPE,
|
||||
TOK_SLOTSIZE,
|
||||
|
||||
TOK_IP,
|
||||
TOK_IF,
|
||||
TOK_ALOG,
|
||||
TOK_DENY_INC,
|
||||
TOK_SAME_PORTS,
|
||||
TOK_UNREG_ONLY,
|
||||
TOK_SKIP_GLOBAL,
|
||||
TOK_RESET_ADDR,
|
||||
TOK_ALIAS_REV,
|
||||
TOK_PROXY_ONLY,
|
||||
TOK_REDIR_ADDR,
|
||||
TOK_REDIR_PORT,
|
||||
TOK_REDIR_PROTO,
|
||||
|
||||
TOK_IPV6,
|
||||
TOK_FLOWID,
|
||||
TOK_ICMP6TYPES,
|
||||
TOK_EXT6HDR,
|
||||
TOK_DSTIP6,
|
||||
TOK_SRCIP6,
|
||||
|
||||
TOK_IPV4,
|
||||
TOK_UNREACH6,
|
||||
TOK_RESET6,
|
||||
|
||||
TOK_FIB,
|
||||
TOK_SETFIB,
|
||||
TOK_LOOKUP,
|
||||
TOK_SOCKARG,
|
||||
TOK_SETDSCP,
|
||||
TOK_FLOW,
|
||||
TOK_IFLIST,
|
||||
/* Table tokens */
|
||||
TOK_CREATE,
|
||||
TOK_DESTROY,
|
||||
TOK_LIST,
|
||||
TOK_INFO,
|
||||
TOK_DETAIL,
|
||||
TOK_MODIFY,
|
||||
TOK_FLUSH,
|
||||
TOK_SWAP,
|
||||
TOK_ADD,
|
||||
TOK_DEL,
|
||||
TOK_VALTYPE,
|
||||
TOK_ALGO,
|
||||
TOK_TALIST,
|
||||
TOK_ATOMIC,
|
||||
TOK_LOCK,
|
||||
TOK_UNLOCK,
|
||||
TOK_VLIST,
|
||||
TOK_OLIST,
|
||||
};
|
||||
|
||||
/*
|
||||
* the following macro returns an error message if we run out of
|
||||
* arguments.
|
||||
*/
|
||||
#define NEED(_p, msg) {if (!_p) errx(EX_USAGE, msg);}
|
||||
#define NEED1(msg) {if (!(*av)) errx(EX_USAGE, msg);}
|
||||
|
||||
struct buf_pr {
|
||||
char *buf; /* allocated buffer */
|
||||
char *ptr; /* current pointer */
|
||||
size_t size; /* total buffer size */
|
||||
size_t avail; /* available storage */
|
||||
size_t needed; /* length needed */
|
||||
};
|
||||
|
||||
int pr_u64(struct buf_pr *bp, uint64_t *pd, int width);
|
||||
int bp_alloc(struct buf_pr *b, size_t size);
|
||||
void bp_free(struct buf_pr *b);
|
||||
int bprintf(struct buf_pr *b, char *format, ...);
|
||||
|
||||
|
||||
/* memory allocation support */
|
||||
void *safe_calloc(size_t number, size_t size);
|
||||
void *safe_realloc(void *ptr, size_t size);
|
||||
|
||||
/* string comparison functions used for historical compatibility */
|
||||
int _substrcmp(const char *str1, const char* str2);
|
||||
int _substrcmp2(const char *str1, const char* str2, const char* str3);
|
||||
int stringnum_cmp(const char *a, const char *b);
|
||||
|
||||
/* utility functions */
|
||||
int match_token(struct _s_x *table, const char *string);
|
||||
int match_token_relaxed(struct _s_x *table, const char *string);
|
||||
int get_token(struct _s_x *table, const char *string, const char *errbase);
|
||||
char const *match_value(struct _s_x *p, int value);
|
||||
size_t concat_tokens(char *buf, size_t bufsize, struct _s_x *table,
|
||||
char *delimiter);
|
||||
int fill_flags(struct _s_x *flags, char *p, char **e, uint32_t *set,
|
||||
uint32_t *clear);
|
||||
void print_flags_buffer(char *buf, size_t sz, struct _s_x *list, uint32_t set);
|
||||
|
||||
struct _ip_fw3_opheader;
|
||||
int do_cmd(int optname, void *optval, uintptr_t optlen);
|
||||
int do_set3(int optname, struct _ip_fw3_opheader *op3, uintptr_t optlen);
|
||||
int do_get3(int optname, struct _ip_fw3_opheader *op3, size_t *optlen);
|
||||
|
||||
struct in6_addr;
|
||||
void n2mask(struct in6_addr *mask, int n);
|
||||
int contigmask(uint8_t *p, int len);
|
||||
|
||||
/*
|
||||
* Forward declarations to avoid include way too many headers.
|
||||
* C does not allow duplicated typedefs, so we use the base struct
|
||||
* that the typedef points to.
|
||||
* Should the typedefs use a different type, the compiler will
|
||||
* still detect the change when compiling the body of the
|
||||
* functions involved, so we do not lose error checking.
|
||||
*/
|
||||
struct _ipfw_insn;
|
||||
struct _ipfw_insn_altq;
|
||||
struct _ipfw_insn_u32;
|
||||
struct _ipfw_insn_ip6;
|
||||
struct _ipfw_insn_icmp6;
|
||||
|
||||
/*
|
||||
* The reserved set numer. This is a constant in ip_fw.h
|
||||
* but we store it in a variable so other files do not depend
|
||||
* in that header just for one constant.
|
||||
*/
|
||||
extern int resvd_set_number;
|
||||
|
||||
/* first-level command handlers */
|
||||
void ipfw_add(char *av[]);
|
||||
void ipfw_show_nat(int ac, char **av);
|
||||
void ipfw_config_pipe(int ac, char **av);
|
||||
void ipfw_config_nat(int ac, char **av);
|
||||
void ipfw_sets_handler(char *av[]);
|
||||
void ipfw_table_handler(int ac, char *av[]);
|
||||
void ipfw_sysctl_handler(char *av[], int which);
|
||||
void ipfw_delete(char *av[]);
|
||||
void ipfw_flush(int force);
|
||||
void ipfw_zero(int ac, char *av[], int optname);
|
||||
void ipfw_list(int ac, char *av[], int show_counters);
|
||||
void ipfw_internal_handler(int ac, char *av[]);
|
||||
int ipfw_check_object_name(const char *name);
|
||||
|
||||
#ifdef PF
|
||||
/* altq.c */
|
||||
void altq_set_enabled(int enabled);
|
||||
u_int32_t altq_name_to_qid(const char *name);
|
||||
void print_altq_cmd(struct buf_pr *bp, struct _ipfw_insn_altq *altqptr);
|
||||
#else
|
||||
#define NO_ALTQ
|
||||
#endif
|
||||
|
||||
/* dummynet.c */
|
||||
void dummynet_list(int ac, char *av[], int show_counters);
|
||||
void dummynet_flush(void);
|
||||
int ipfw_delete_pipe(int pipe_or_queue, int n);
|
||||
|
||||
/* ipv6.c */
|
||||
void print_unreach6_code(struct buf_pr *bp, uint16_t code);
|
||||
void print_ip6(struct buf_pr *bp, struct _ipfw_insn_ip6 *cmd, char const *s);
|
||||
void print_flow6id(struct buf_pr *bp, struct _ipfw_insn_u32 *cmd);
|
||||
void print_icmp6types(struct buf_pr *bp, struct _ipfw_insn_u32 *cmd);
|
||||
void print_ext6hdr(struct buf_pr *bp, struct _ipfw_insn *cmd );
|
||||
|
||||
struct _ipfw_insn *add_srcip6(struct _ipfw_insn *cmd, char *av, int cblen);
|
||||
struct _ipfw_insn *add_dstip6(struct _ipfw_insn *cmd, char *av, int cblen);
|
||||
|
||||
void fill_flow6(struct _ipfw_insn_u32 *cmd, char *av, int cblen);
|
||||
void fill_unreach6_code(u_short *codep, char *str);
|
||||
void fill_icmp6types(struct _ipfw_insn_icmp6 *cmd, char *av, int cblen);
|
||||
int fill_ext6hdr(struct _ipfw_insn *cmd, char *av);
|
||||
|
||||
/* ipfw2.c */
|
||||
void bp_flush(struct buf_pr *b);
|
||||
|
||||
/* tables.c */
|
||||
struct _ipfw_obj_ctlv;
|
||||
int table_check_name(const char *tablename);
|
||||
void ipfw_list_ta(int ac, char *av[]);
|
||||
void ipfw_list_values(int ac, char *av[]);
|
||||
|
||||
#ifdef FSTACK
|
||||
int ff_socket(int domain, int type, int protocol);
|
||||
int ff_getsockopt(int sockfd, int level, int optname,
|
||||
void *optval, socklen_t *optlen);
|
||||
int ff_setsockopt(int sockfd, int level, int optname,
|
||||
const void *optval, socklen_t optlen);
|
||||
|
||||
#define socket(a,b,c) ff_socket(a,b,c)
|
||||
#define setsockopt(a,b,c,d,e) ff_setsockopt(a,b,c,d,e)
|
||||
#define getsockopt(a,b,c,d,e) ff_getsockopt(a,b,c,d,e)
|
||||
#endif
|
||||
|
|
@ -0,0 +1,536 @@
|
|||
/*
|
||||
* Copyright (c) 2002-2003 Luigi Rizzo
|
||||
* Copyright (c) 1996 Alex Nash, Paul Traina, Poul-Henning Kamp
|
||||
* Copyright (c) 1994 Ugen J.S.Antsilevich
|
||||
*
|
||||
* Idea and grammar partially left from:
|
||||
* Copyright (c) 1993 Daniel Boulet
|
||||
*
|
||||
* Redistribution and use in source forms, with and without modification,
|
||||
* are permitted provided that this entire comment appears intact.
|
||||
*
|
||||
* Redistribution in binary form may occur without any restrictions.
|
||||
* Obviously, it would be nice if you gave credit where credit is due
|
||||
* but requiring it would be too onerous.
|
||||
*
|
||||
* This software is provided ``AS IS'' without any warranties of any kind.
|
||||
*
|
||||
* NEW command line interface for IP firewall facility
|
||||
*
|
||||
* $FreeBSD$
|
||||
*
|
||||
* ipv6 support
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "ipfw2.h"
|
||||
|
||||
#include <err.h>
|
||||
#include <netdb.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sysexits.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/icmp6.h>
|
||||
#include <netinet/ip_fw.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#define CHECK_LENGTH(v, len) do { \
|
||||
if ((v) < (len)) \
|
||||
errx(EX_DATAERR, "Rule too long"); \
|
||||
} while (0)
|
||||
|
||||
static struct _s_x icmp6codes[] = {
|
||||
{ "no-route", ICMP6_DST_UNREACH_NOROUTE },
|
||||
{ "admin-prohib", ICMP6_DST_UNREACH_ADMIN },
|
||||
{ "address", ICMP6_DST_UNREACH_ADDR },
|
||||
{ "port", ICMP6_DST_UNREACH_NOPORT },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
void
|
||||
fill_unreach6_code(u_short *codep, char *str)
|
||||
{
|
||||
int val;
|
||||
char *s;
|
||||
|
||||
val = strtoul(str, &s, 0);
|
||||
if (s == str || *s != '\0' || val >= 0x100)
|
||||
val = match_token(icmp6codes, str);
|
||||
if (val < 0)
|
||||
errx(EX_DATAERR, "unknown ICMPv6 unreachable code ``%s''", str);
|
||||
*codep = val;
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
print_unreach6_code(struct buf_pr *bp, uint16_t code)
|
||||
{
|
||||
char const *s = match_value(icmp6codes, code);
|
||||
|
||||
if (s != NULL)
|
||||
bprintf(bp, "unreach6 %s", s);
|
||||
else
|
||||
bprintf(bp, "unreach6 %u", code);
|
||||
}
|
||||
|
||||
/*
|
||||
* Print the ip address contained in a command.
|
||||
*/
|
||||
void
|
||||
print_ip6(struct buf_pr *bp, ipfw_insn_ip6 *cmd, char const *s)
|
||||
{
|
||||
struct hostent *he = NULL;
|
||||
int len = F_LEN((ipfw_insn *) cmd) - 1;
|
||||
struct in6_addr *a = &(cmd->addr6);
|
||||
char trad[255];
|
||||
|
||||
bprintf(bp, "%s%s ", cmd->o.len & F_NOT ? " not": "", s);
|
||||
|
||||
if (cmd->o.opcode == O_IP6_SRC_ME || cmd->o.opcode == O_IP6_DST_ME) {
|
||||
bprintf(bp, "me6");
|
||||
return;
|
||||
}
|
||||
if (cmd->o.opcode == O_IP6) {
|
||||
bprintf(bp, " ip6");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* len == 4 indicates a single IP, whereas lists of 1 or more
|
||||
* addr/mask pairs have len = (2n+1). We convert len to n so we
|
||||
* use that to count the number of entries.
|
||||
*/
|
||||
|
||||
for (len = len / 4; len > 0; len -= 2, a += 2) {
|
||||
int mb = /* mask length */
|
||||
(cmd->o.opcode == O_IP6_SRC || cmd->o.opcode == O_IP6_DST) ?
|
||||
128 : contigmask((uint8_t *)&(a[1]), 128);
|
||||
|
||||
if (mb == 128 && co.do_resolv)
|
||||
he = gethostbyaddr((char *)a, sizeof(*a), AF_INET6);
|
||||
if (he != NULL) /* resolved to name */
|
||||
bprintf(bp, "%s", he->h_name);
|
||||
else if (mb == 0) /* any */
|
||||
bprintf(bp, "any");
|
||||
else { /* numeric IP followed by some kind of mask */
|
||||
if (inet_ntop(AF_INET6, a, trad, sizeof( trad ) ) == NULL)
|
||||
bprintf(bp, "Error ntop in print_ip6\n");
|
||||
bprintf(bp, "%s", trad );
|
||||
if (mb < 0) /* XXX not really legal... */
|
||||
bprintf(bp, ":%s",
|
||||
inet_ntop(AF_INET6, &a[1], trad, sizeof(trad)));
|
||||
else if (mb < 128)
|
||||
bprintf(bp, "/%d", mb);
|
||||
}
|
||||
if (len > 2)
|
||||
bprintf(bp, ",");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
fill_icmp6types(ipfw_insn_icmp6 *cmd, char *av, int cblen)
|
||||
{
|
||||
uint8_t type;
|
||||
|
||||
CHECK_LENGTH(cblen, F_INSN_SIZE(ipfw_insn_icmp6));
|
||||
|
||||
bzero(cmd, sizeof(*cmd));
|
||||
while (*av) {
|
||||
if (*av == ',')
|
||||
av++;
|
||||
type = strtoul(av, &av, 0);
|
||||
if (*av != ',' && *av != '\0')
|
||||
errx(EX_DATAERR, "invalid ICMP6 type");
|
||||
/*
|
||||
* XXX: shouldn't this be 0xFF? I can't see any reason why
|
||||
* we shouldn't be able to filter all possiable values
|
||||
* regardless of the ability of the rest of the kernel to do
|
||||
* anything useful with them.
|
||||
*/
|
||||
if (type > ICMP6_MAXTYPE)
|
||||
errx(EX_DATAERR, "ICMP6 type out of range");
|
||||
cmd->d[type / 32] |= ( 1 << (type % 32));
|
||||
}
|
||||
cmd->o.opcode = O_ICMP6TYPE;
|
||||
cmd->o.len |= F_INSN_SIZE(ipfw_insn_icmp6);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
print_icmp6types(struct buf_pr *bp, ipfw_insn_u32 *cmd)
|
||||
{
|
||||
int i, j;
|
||||
char sep= ' ';
|
||||
|
||||
bprintf(bp, " ip6 icmp6types");
|
||||
for (i = 0; i < 7; i++)
|
||||
for (j=0; j < 32; ++j) {
|
||||
if ( (cmd->d[i] & (1 << (j))) == 0)
|
||||
continue;
|
||||
bprintf(bp, "%c%d", sep, (i*32 + j));
|
||||
sep = ',';
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
print_flow6id(struct buf_pr *bp, ipfw_insn_u32 *cmd)
|
||||
{
|
||||
uint16_t i, limit = cmd->o.arg1;
|
||||
char sep = ',';
|
||||
|
||||
bprintf(bp, " flow-id ");
|
||||
for( i=0; i < limit; ++i) {
|
||||
if (i == limit - 1)
|
||||
sep = ' ';
|
||||
bprintf(bp, "%d%c", cmd->d[i], sep);
|
||||
}
|
||||
}
|
||||
|
||||
/* structure and define for the extension header in ipv6 */
|
||||
static struct _s_x ext6hdrcodes[] = {
|
||||
{ "frag", EXT_FRAGMENT },
|
||||
{ "hopopt", EXT_HOPOPTS },
|
||||
{ "route", EXT_ROUTING },
|
||||
{ "dstopt", EXT_DSTOPTS },
|
||||
{ "ah", EXT_AH },
|
||||
{ "esp", EXT_ESP },
|
||||
{ "rthdr0", EXT_RTHDR0 },
|
||||
{ "rthdr2", EXT_RTHDR2 },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
/* fills command for the extension header filtering */
|
||||
int
|
||||
fill_ext6hdr( ipfw_insn *cmd, char *av)
|
||||
{
|
||||
int tok;
|
||||
char *s = av;
|
||||
|
||||
cmd->arg1 = 0;
|
||||
|
||||
while(s) {
|
||||
av = strsep( &s, ",") ;
|
||||
tok = match_token(ext6hdrcodes, av);
|
||||
switch (tok) {
|
||||
case EXT_FRAGMENT:
|
||||
cmd->arg1 |= EXT_FRAGMENT;
|
||||
break;
|
||||
|
||||
case EXT_HOPOPTS:
|
||||
cmd->arg1 |= EXT_HOPOPTS;
|
||||
break;
|
||||
|
||||
case EXT_ROUTING:
|
||||
cmd->arg1 |= EXT_ROUTING;
|
||||
break;
|
||||
|
||||
case EXT_DSTOPTS:
|
||||
cmd->arg1 |= EXT_DSTOPTS;
|
||||
break;
|
||||
|
||||
case EXT_AH:
|
||||
cmd->arg1 |= EXT_AH;
|
||||
break;
|
||||
|
||||
case EXT_ESP:
|
||||
cmd->arg1 |= EXT_ESP;
|
||||
break;
|
||||
|
||||
case EXT_RTHDR0:
|
||||
cmd->arg1 |= EXT_RTHDR0;
|
||||
break;
|
||||
|
||||
case EXT_RTHDR2:
|
||||
cmd->arg1 |= EXT_RTHDR2;
|
||||
break;
|
||||
|
||||
default:
|
||||
errx( EX_DATAERR, "invalid option for ipv6 exten header" );
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cmd->arg1 == 0 )
|
||||
return 0;
|
||||
cmd->opcode = O_EXT_HDR;
|
||||
cmd->len |= F_INSN_SIZE( ipfw_insn );
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
print_ext6hdr(struct buf_pr *bp, ipfw_insn *cmd )
|
||||
{
|
||||
char sep = ' ';
|
||||
|
||||
bprintf(bp, " extension header:");
|
||||
if (cmd->arg1 & EXT_FRAGMENT ) {
|
||||
bprintf(bp, "%cfragmentation", sep);
|
||||
sep = ',';
|
||||
}
|
||||
if (cmd->arg1 & EXT_HOPOPTS ) {
|
||||
bprintf(bp, "%chop options", sep);
|
||||
sep = ',';
|
||||
}
|
||||
if (cmd->arg1 & EXT_ROUTING ) {
|
||||
bprintf(bp, "%crouting options", sep);
|
||||
sep = ',';
|
||||
}
|
||||
if (cmd->arg1 & EXT_RTHDR0 ) {
|
||||
bprintf(bp, "%crthdr0", sep);
|
||||
sep = ',';
|
||||
}
|
||||
if (cmd->arg1 & EXT_RTHDR2 ) {
|
||||
bprintf(bp, "%crthdr2", sep);
|
||||
sep = ',';
|
||||
}
|
||||
if (cmd->arg1 & EXT_DSTOPTS ) {
|
||||
bprintf(bp, "%cdestination options", sep);
|
||||
sep = ',';
|
||||
}
|
||||
if (cmd->arg1 & EXT_AH ) {
|
||||
bprintf(bp, "%cauthentication header", sep);
|
||||
sep = ',';
|
||||
}
|
||||
if (cmd->arg1 & EXT_ESP ) {
|
||||
bprintf(bp, "%cencapsulated security payload", sep);
|
||||
}
|
||||
}
|
||||
|
||||
/* Try to find ipv6 address by hostname */
|
||||
static int
|
||||
lookup_host6 (char *host, struct in6_addr *ip6addr)
|
||||
{
|
||||
struct hostent *he;
|
||||
|
||||
if (!inet_pton(AF_INET6, host, ip6addr)) {
|
||||
if ((he = gethostbyname2(host, AF_INET6)) == NULL)
|
||||
return(-1);
|
||||
memcpy(ip6addr, he->h_addr_list[0], sizeof( struct in6_addr));
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* fill the addr and mask fields in the instruction as appropriate from av.
|
||||
* Update length as appropriate.
|
||||
* The following formats are allowed:
|
||||
* any matches any IP6. Actually returns an empty instruction.
|
||||
* me returns O_IP6_*_ME
|
||||
*
|
||||
* 03f1::234:123:0342 single IP6 address
|
||||
* 03f1::234:123:0342/24 address/mask
|
||||
* 03f1::234:123:0342/24,03f1::234:123:0343/ List of address
|
||||
*
|
||||
* Set of address (as in ipv6) not supported because ipv6 address
|
||||
* are typically random past the initial prefix.
|
||||
* Return 1 on success, 0 on failure.
|
||||
*/
|
||||
static int
|
||||
fill_ip6(ipfw_insn_ip6 *cmd, char *av, int cblen)
|
||||
{
|
||||
int len = 0;
|
||||
struct in6_addr *d = &(cmd->addr6);
|
||||
/*
|
||||
* Needed for multiple address.
|
||||
* Note d[1] points to struct in6_add r mask6 of cmd
|
||||
*/
|
||||
|
||||
cmd->o.len &= ~F_LEN_MASK; /* zero len */
|
||||
|
||||
if (strcmp(av, "any") == 0)
|
||||
return (1);
|
||||
|
||||
|
||||
if (strcmp(av, "me") == 0) { /* Set the data for "me" opt*/
|
||||
cmd->o.len |= F_INSN_SIZE(ipfw_insn);
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (strcmp(av, "me6") == 0) { /* Set the data for "me" opt*/
|
||||
cmd->o.len |= F_INSN_SIZE(ipfw_insn);
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (strncmp(av, "table(", 6) == 0) {
|
||||
char *p = strchr(av + 6, ',');
|
||||
uint32_t *dm = ((ipfw_insn_u32 *)cmd)->d;
|
||||
|
||||
if (p)
|
||||
*p++ = '\0';
|
||||
cmd->o.opcode = O_IP_DST_LOOKUP;
|
||||
cmd->o.arg1 = strtoul(av + 6, NULL, 0);
|
||||
if (p) {
|
||||
cmd->o.len |= F_INSN_SIZE(ipfw_insn_u32);
|
||||
dm[0] = strtoul(p, NULL, 0);
|
||||
} else
|
||||
cmd->o.len |= F_INSN_SIZE(ipfw_insn);
|
||||
return (1);
|
||||
}
|
||||
|
||||
av = strdup(av);
|
||||
while (av) {
|
||||
/*
|
||||
* After the address we can have '/' indicating a mask,
|
||||
* or ',' indicating another address follows.
|
||||
*/
|
||||
|
||||
char *p;
|
||||
int masklen;
|
||||
char md = '\0';
|
||||
|
||||
CHECK_LENGTH(cblen, 1 + len + 2 * F_INSN_SIZE(struct in6_addr));
|
||||
|
||||
if ((p = strpbrk(av, "/,")) ) {
|
||||
md = *p; /* save the separator */
|
||||
*p = '\0'; /* terminate address string */
|
||||
p++; /* and skip past it */
|
||||
}
|
||||
/* now p points to NULL, mask or next entry */
|
||||
|
||||
/* lookup stores address in *d as a side effect */
|
||||
if (lookup_host6(av, d) != 0) {
|
||||
/* XXX: failed. Free memory and go */
|
||||
errx(EX_DATAERR, "bad address \"%s\"", av);
|
||||
}
|
||||
/* next, look at the mask, if any */
|
||||
masklen = (md == '/') ? atoi(p) : 128;
|
||||
if (masklen > 128 || masklen < 0)
|
||||
errx(EX_DATAERR, "bad width \"%s\''", p);
|
||||
else
|
||||
n2mask(&d[1], masklen);
|
||||
|
||||
APPLY_MASK(d, &d[1]) /* mask base address with mask */
|
||||
|
||||
/* find next separator */
|
||||
|
||||
if (md == '/') { /* find separator past the mask */
|
||||
p = strpbrk(p, ",");
|
||||
if (p != NULL)
|
||||
p++;
|
||||
}
|
||||
av = p;
|
||||
|
||||
/* Check this entry */
|
||||
if (masklen == 0) {
|
||||
/*
|
||||
* 'any' turns the entire list into a NOP.
|
||||
* 'not any' never matches, so it is removed from the
|
||||
* list unless it is the only item, in which case we
|
||||
* report an error.
|
||||
*/
|
||||
if (cmd->o.len & F_NOT && av == NULL && len == 0)
|
||||
errx(EX_DATAERR, "not any never matches");
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* A single IP can be stored alone
|
||||
*/
|
||||
if (masklen == 128 && av == NULL && len == 0) {
|
||||
len = F_INSN_SIZE(struct in6_addr);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Update length and pointer to arguments */
|
||||
len += F_INSN_SIZE(struct in6_addr)*2;
|
||||
d += 2;
|
||||
} /* end while */
|
||||
|
||||
/*
|
||||
* Total length of the command, remember that 1 is the size of
|
||||
* the base command.
|
||||
*/
|
||||
if (len + 1 > F_LEN_MASK)
|
||||
errx(EX_DATAERR, "address list too long");
|
||||
cmd->o.len |= len+1;
|
||||
free(av);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* fills command for ipv6 flow-id filtering
|
||||
* note that the 20 bit flow number is stored in a array of u_int32_t
|
||||
* it's supported lists of flow-id, so in the o.arg1 we store how many
|
||||
* additional flow-id we want to filter, the basic is 1
|
||||
*/
|
||||
void
|
||||
fill_flow6( ipfw_insn_u32 *cmd, char *av, int cblen)
|
||||
{
|
||||
u_int32_t type; /* Current flow number */
|
||||
u_int16_t nflow = 0; /* Current flow index */
|
||||
char *s = av;
|
||||
cmd->d[0] = 0; /* Initializing the base number*/
|
||||
|
||||
while (s) {
|
||||
CHECK_LENGTH(cblen, F_INSN_SIZE(ipfw_insn_u32) + nflow + 1);
|
||||
|
||||
av = strsep( &s, ",") ;
|
||||
type = strtoul(av, &av, 0);
|
||||
if (*av != ',' && *av != '\0')
|
||||
errx(EX_DATAERR, "invalid ipv6 flow number %s", av);
|
||||
if (type > 0xfffff)
|
||||
errx(EX_DATAERR, "flow number out of range %s", av);
|
||||
cmd->d[nflow] |= type;
|
||||
nflow++;
|
||||
}
|
||||
if( nflow > 0 ) {
|
||||
cmd->o.opcode = O_FLOW6ID;
|
||||
cmd->o.len |= F_INSN_SIZE(ipfw_insn_u32) + nflow;
|
||||
cmd->o.arg1 = nflow;
|
||||
}
|
||||
else {
|
||||
errx(EX_DATAERR, "invalid ipv6 flow number %s", av);
|
||||
}
|
||||
}
|
||||
|
||||
ipfw_insn *
|
||||
add_srcip6(ipfw_insn *cmd, char *av, int cblen)
|
||||
{
|
||||
|
||||
fill_ip6((ipfw_insn_ip6 *)cmd, av, cblen);
|
||||
if (cmd->opcode == O_IP_DST_SET) /* set */
|
||||
cmd->opcode = O_IP_SRC_SET;
|
||||
else if (cmd->opcode == O_IP_DST_LOOKUP) /* table */
|
||||
cmd->opcode = O_IP_SRC_LOOKUP;
|
||||
else if (F_LEN(cmd) == 0) { /* any */
|
||||
} else if (F_LEN(cmd) == F_INSN_SIZE(ipfw_insn)) { /* "me" */
|
||||
cmd->opcode = O_IP6_SRC_ME;
|
||||
} else if (F_LEN(cmd) ==
|
||||
(F_INSN_SIZE(struct in6_addr) + F_INSN_SIZE(ipfw_insn))) {
|
||||
/* single IP, no mask*/
|
||||
cmd->opcode = O_IP6_SRC;
|
||||
} else { /* addr/mask opt */
|
||||
cmd->opcode = O_IP6_SRC_MASK;
|
||||
}
|
||||
return cmd;
|
||||
}
|
||||
|
||||
ipfw_insn *
|
||||
add_dstip6(ipfw_insn *cmd, char *av, int cblen)
|
||||
{
|
||||
|
||||
fill_ip6((ipfw_insn_ip6 *)cmd, av, cblen);
|
||||
if (cmd->opcode == O_IP_DST_SET) /* set */
|
||||
;
|
||||
else if (cmd->opcode == O_IP_DST_LOOKUP) /* table */
|
||||
;
|
||||
else if (F_LEN(cmd) == 0) { /* any */
|
||||
} else if (F_LEN(cmd) == F_INSN_SIZE(ipfw_insn)) { /* "me" */
|
||||
cmd->opcode = O_IP6_DST_ME;
|
||||
} else if (F_LEN(cmd) ==
|
||||
(F_INSN_SIZE(struct in6_addr) + F_INSN_SIZE(ipfw_insn))) {
|
||||
/* single IP, no mask*/
|
||||
cmd->opcode = O_IP6_DST;
|
||||
} else { /* addr/mask opt */
|
||||
cmd->opcode = O_IP6_DST_MASK;
|
||||
}
|
||||
return cmd;
|
||||
}
|
|
@ -0,0 +1,663 @@
|
|||
/*
|
||||
* Copyright (c) 2002-2003,2010 Luigi Rizzo
|
||||
* Copyright (c) 1996 Alex Nash, Paul Traina, Poul-Henning Kamp
|
||||
* Copyright (c) 1994 Ugen J.S.Antsilevich
|
||||
*
|
||||
* Idea and grammar partially left from:
|
||||
* Copyright (c) 1993 Daniel Boulet
|
||||
*
|
||||
* Redistribution and use in source forms, with and without modification,
|
||||
* are permitted provided that this entire comment appears intact.
|
||||
*
|
||||
* Redistribution in binary form may occur without any restrictions.
|
||||
* Obviously, it would be nice if you gave credit where credit is due
|
||||
* but requiring it would be too onerous.
|
||||
*
|
||||
* This software is provided ``AS IS'' without any warranties of any kind.
|
||||
*
|
||||
* Command line interface for IP firewall facility
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/wait.h>
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sysexits.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef FSTACK
|
||||
#include <stdint.h>
|
||||
#include "ff_ipc.h"
|
||||
#endif
|
||||
|
||||
#include "ipfw2.h"
|
||||
|
||||
static void
|
||||
help(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"ipfw syntax summary (but please do read the ipfw(8) manpage):\n\n"
|
||||
#ifndef FSTACK
|
||||
"\tipfw [-abcdefhnNqStTv] <command>\n\n"
|
||||
#else
|
||||
"\tipfw -P <f-stack proc_id> [-abcdefhnNqStTv] <command>\n\n"
|
||||
#endif
|
||||
"where <command> is one of the following:\n\n"
|
||||
"add [num] [set N] [prob x] RULE-BODY\n"
|
||||
"{pipe|queue} N config PIPE-BODY\n"
|
||||
"[pipe|queue] {zero|delete|show} [N{,N}]\n"
|
||||
"nat N config {ip IPADDR|if IFNAME|log|deny_in|same_ports|unreg_only|reset|\n"
|
||||
" reverse|proxy_only|redirect_addr linkspec|\n"
|
||||
" redirect_port linkspec|redirect_proto linkspec}\n"
|
||||
"set [disable N... enable N...] | move [rule] X to Y | swap X Y | show\n"
|
||||
"set N {show|list|zero|resetlog|delete} [N{,N}] | flush\n"
|
||||
"table N {add ip[/bits] [value] | delete ip[/bits] | flush | list}\n"
|
||||
"table all {flush | list}\n"
|
||||
"\n"
|
||||
"RULE-BODY: check-state [PARAMS] | ACTION [PARAMS] ADDR [OPTION_LIST]\n"
|
||||
"ACTION: check-state | allow | count | deny | unreach{,6} CODE |\n"
|
||||
" skipto N | {divert|tee} PORT | forward ADDR |\n"
|
||||
" pipe N | queue N | nat N | setfib FIB | reass\n"
|
||||
"PARAMS: [log [logamount LOGLIMIT]] [altq QUEUE_NAME]\n"
|
||||
"ADDR: [ MAC dst src ether_type ] \n"
|
||||
" [ ip from IPADDR [ PORT ] to IPADDR [ PORTLIST ] ]\n"
|
||||
" [ ipv6|ip6 from IP6ADDR [ PORT ] to IP6ADDR [ PORTLIST ] ]\n"
|
||||
"IPADDR: [not] { any | me | ip/bits{x,y,z} | table(t[,v]) | IPLIST }\n"
|
||||
"IP6ADDR: [not] { any | me | me6 | ip6/bits | IP6LIST }\n"
|
||||
"IP6LIST: { ip6 | ip6/bits }[,IP6LIST]\n"
|
||||
"IPLIST: { ip | ip/bits | ip:mask }[,IPLIST]\n"
|
||||
"OPTION_LIST: OPTION [OPTION_LIST]\n"
|
||||
"OPTION: bridged | diverted | diverted-loopback | diverted-output |\n"
|
||||
" {dst-ip|src-ip} IPADDR | {dst-ip6|src-ip6|dst-ipv6|src-ipv6} IP6ADDR |\n"
|
||||
" {dst-port|src-port} LIST |\n"
|
||||
" estab | frag | {gid|uid} N | icmptypes LIST | in | out | ipid LIST |\n"
|
||||
" iplen LIST | ipoptions SPEC | ipprecedence | ipsec | iptos SPEC |\n"
|
||||
" ipttl LIST | ipversion VER | keep-state | layer2 | limit ... |\n"
|
||||
" icmp6types LIST | ext6hdr LIST | flow-id N[,N] | fib FIB |\n"
|
||||
" mac ... | mac-type LIST | proto LIST | {recv|xmit|via} {IF|IPADDR} |\n"
|
||||
" setup | {tcpack|tcpseq|tcpwin} NN | tcpflags SPEC | tcpoptions SPEC |\n"
|
||||
" tcpdatalen LIST | verrevpath | versrcreach | antispoof\n"
|
||||
);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called with the arguments, including program name because getopt
|
||||
* wants it to be present.
|
||||
* Returns 0 if successful, 1 if empty command, errx() in case of errors.
|
||||
* First thing we do is process parameters creating an argv[] array
|
||||
* which includes the program name and a NULL entry at the end.
|
||||
* If we are called with a single string, we split it on whitespace.
|
||||
* Also, arguments with a trailing ',' are joined to the next one.
|
||||
* The pointers (av[]) and data are in a single chunk of memory.
|
||||
* av[0] points to the original program name, all other entries
|
||||
* point into the allocated chunk.
|
||||
*/
|
||||
static int
|
||||
ipfw_main(int oldac, char **oldav)
|
||||
{
|
||||
int ch, ac;
|
||||
const char *errstr;
|
||||
char **av, **save_av;
|
||||
int do_acct = 0; /* Show packet/byte count */
|
||||
int try_next = 0; /* set if pipe cmd not found */
|
||||
int av_size; /* compute the av size */
|
||||
char *av_p; /* used to build the av list */
|
||||
|
||||
#define WHITESP " \t\f\v\n\r"
|
||||
if (oldac < 2)
|
||||
return 1; /* need at least one argument */
|
||||
|
||||
if (oldac == 2) {
|
||||
/*
|
||||
* If we are called with one argument, try to split it into
|
||||
* words for subsequent parsing. Spaces after a ',' are
|
||||
* removed by copying the string in-place.
|
||||
*/
|
||||
char *arg = oldav[1]; /* The string is the first arg. */
|
||||
int l = strlen(arg);
|
||||
int copy = 0; /* 1 if we need to copy, 0 otherwise */
|
||||
int i, j;
|
||||
|
||||
for (i = j = 0; i < l; i++) {
|
||||
if (arg[i] == '#') /* comment marker */
|
||||
break;
|
||||
if (copy) {
|
||||
arg[j++] = arg[i];
|
||||
copy = !strchr("," WHITESP, arg[i]);
|
||||
} else {
|
||||
copy = !strchr(WHITESP, arg[i]);
|
||||
if (copy)
|
||||
arg[j++] = arg[i];
|
||||
}
|
||||
}
|
||||
if (!copy && j > 0) /* last char was a 'blank', remove it */
|
||||
j--;
|
||||
l = j; /* the new argument length */
|
||||
arg[j++] = '\0';
|
||||
if (l == 0) /* empty string! */
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* First, count number of arguments. Because of the previous
|
||||
* processing, this is just the number of blanks plus 1.
|
||||
*/
|
||||
for (i = 0, ac = 1; i < l; i++)
|
||||
if (strchr(WHITESP, arg[i]) != NULL)
|
||||
ac++;
|
||||
|
||||
/*
|
||||
* Allocate the argument list structure as a single block
|
||||
* of memory, containing pointers and the argument
|
||||
* strings. We include one entry for the program name
|
||||
* because getopt expects it, and a NULL at the end
|
||||
* to simplify further parsing.
|
||||
*/
|
||||
ac++; /* add 1 for the program name */
|
||||
av_size = (ac+1) * sizeof(char *) + l + 1;
|
||||
av = safe_calloc(av_size, 1);
|
||||
|
||||
/*
|
||||
* Init the argument pointer to the end of the array
|
||||
* and copy arguments from arg[] to av[]. For each one,
|
||||
* j is the initial character, i is the one past the end.
|
||||
*/
|
||||
av_p = (char *)&av[ac+1];
|
||||
for (ac = 1, i = j = 0; i < l; i++) {
|
||||
if (strchr(WHITESP, arg[i]) != NULL || i == l-1) {
|
||||
if (i == l-1)
|
||||
i++;
|
||||
bcopy(arg+j, av_p, i-j);
|
||||
av[ac] = av_p;
|
||||
av_p += i-j; /* the length of the string */
|
||||
*av_p++ = '\0';
|
||||
ac++;
|
||||
j = i + 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* If an argument ends with ',' join with the next one.
|
||||
*/
|
||||
int first, i, l=0;
|
||||
|
||||
/*
|
||||
* Allocate the argument list structure as a single block
|
||||
* of memory, containing both pointers and the argument
|
||||
* strings. We include some space for the program name
|
||||
* because getopt expects it.
|
||||
* We add an extra pointer to the end of the array,
|
||||
* to make simpler further parsing.
|
||||
*/
|
||||
for (i=0; i<oldac; i++)
|
||||
l += strlen(oldav[i]);
|
||||
|
||||
av_size = (oldac+1) * sizeof(char *) + l + oldac;
|
||||
av = safe_calloc(av_size, 1);
|
||||
|
||||
/*
|
||||
* Init the argument pointer to the end of the array
|
||||
* and copy arguments from arg[] to av[]
|
||||
*/
|
||||
av_p = (char *)&av[oldac+1];
|
||||
for (first = i = ac = 1, l = 0; i < oldac; i++) {
|
||||
char *arg = oldav[i];
|
||||
int k = strlen(arg);
|
||||
|
||||
l += k;
|
||||
if (arg[k-1] != ',' || i == oldac-1) {
|
||||
/* Time to copy. */
|
||||
av[ac] = av_p;
|
||||
for (l=0; first <= i; first++) {
|
||||
strcat(av_p, oldav[first]);
|
||||
av_p += strlen(oldav[first]);
|
||||
}
|
||||
*av_p++ = '\0';
|
||||
ac++;
|
||||
l = 0;
|
||||
first = i+1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* set the progname pointer to the original string
|
||||
* and terminate the array with null
|
||||
*/
|
||||
av[0] = oldav[0];
|
||||
av[ac] = NULL;
|
||||
|
||||
/* Set the force flag for non-interactive processes */
|
||||
if (!co.do_force)
|
||||
co.do_force = !isatty(STDIN_FILENO);
|
||||
|
||||
#ifdef EMULATE_SYSCTL /* sysctl emulation */
|
||||
if ( ac >= 2 && !strcmp(av[1], "sysctl")) {
|
||||
char *s;
|
||||
int i;
|
||||
|
||||
if (ac != 3) {
|
||||
printf( "sysctl emulation usage:\n"
|
||||
" ipfw sysctl name[=value]\n"
|
||||
" ipfw sysctl -a\n");
|
||||
return 0;
|
||||
}
|
||||
s = strchr(av[2], '=');
|
||||
if (s == NULL) {
|
||||
s = !strcmp(av[2], "-a") ? NULL : av[2];
|
||||
sysctlbyname(s, NULL, NULL, NULL, 0);
|
||||
} else { /* ipfw sysctl x.y.z=value */
|
||||
/* assume an INT value, will extend later */
|
||||
if (s[1] == '\0') {
|
||||
printf("ipfw sysctl: missing value\n\n");
|
||||
return 0;
|
||||
}
|
||||
*s = '\0';
|
||||
i = strtol(s+1, NULL, 0);
|
||||
sysctlbyname(av[2], NULL, NULL, &i, sizeof(int));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Save arguments for final freeing of memory. */
|
||||
save_av = av;
|
||||
|
||||
optind = optreset = 1; /* restart getopt() */
|
||||
#ifndef FSTACK
|
||||
while ((ch = getopt(ac, av, "abcdefhinNp:qs:STtv")) != -1)
|
||||
#else
|
||||
while ((ch = getopt(ac, av, "abcdefhinNp:qs:STtvP:")) != -1)
|
||||
#endif
|
||||
switch (ch) {
|
||||
case 'a':
|
||||
do_acct = 1;
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
co.comment_only = 1;
|
||||
co.do_compact = 1;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
co.do_compact = 1;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
co.do_dynamic = 1;
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
co.do_expired = 1;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
co.do_force = 1;
|
||||
break;
|
||||
|
||||
case 'h': /* help */
|
||||
free(save_av);
|
||||
help();
|
||||
break; /* NOTREACHED */
|
||||
|
||||
case 'i':
|
||||
co.do_value_as_ip = 1;
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
co.test_only = 1;
|
||||
break;
|
||||
|
||||
case 'N':
|
||||
co.do_resolv = 1;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
errx(EX_USAGE, "An absolute pathname must be used "
|
||||
"with -p option.");
|
||||
/* NOTREACHED */
|
||||
|
||||
case 'q':
|
||||
co.do_quiet = 1;
|
||||
break;
|
||||
|
||||
case 's': /* sort */
|
||||
co.do_sort = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
co.show_sets = 1;
|
||||
break;
|
||||
|
||||
case 't':
|
||||
co.do_time = 1;
|
||||
break;
|
||||
|
||||
case 'T':
|
||||
co.do_time = 2; /* numeric timestamp */
|
||||
break;
|
||||
|
||||
case 'v': /* verbose */
|
||||
co.verbose = 1;
|
||||
break;
|
||||
#ifdef FSTACK
|
||||
case 'P':
|
||||
ff_set_proc_id(atoi(optarg));
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
free(save_av);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ac -= optind;
|
||||
av += optind;
|
||||
NEED1("bad arguments, for usage summary ``ipfw''");
|
||||
|
||||
/*
|
||||
* An undocumented behaviour of ipfw1 was to allow rule numbers first,
|
||||
* e.g. "100 add allow ..." instead of "add 100 allow ...".
|
||||
* In case, swap first and second argument to get the normal form.
|
||||
*/
|
||||
if (ac > 1 && isdigit(*av[0])) {
|
||||
char *p = av[0];
|
||||
|
||||
av[0] = av[1];
|
||||
av[1] = p;
|
||||
}
|
||||
|
||||
/*
|
||||
* Optional: pipe, queue or nat.
|
||||
*/
|
||||
co.do_nat = 0;
|
||||
co.do_pipe = 0;
|
||||
co.use_set = 0;
|
||||
if (!strncmp(*av, "nat", strlen(*av)))
|
||||
co.do_nat = 1;
|
||||
else if (!strncmp(*av, "pipe", strlen(*av)))
|
||||
co.do_pipe = 1;
|
||||
else if (_substrcmp(*av, "queue") == 0)
|
||||
co.do_pipe = 2;
|
||||
else if (_substrcmp(*av, "flowset") == 0)
|
||||
co.do_pipe = 2;
|
||||
else if (_substrcmp(*av, "sched") == 0)
|
||||
co.do_pipe = 3;
|
||||
else if (!strncmp(*av, "set", strlen(*av))) {
|
||||
if (ac > 1 && isdigit(av[1][0])) {
|
||||
co.use_set = strtonum(av[1], 0, resvd_set_number,
|
||||
&errstr);
|
||||
if (errstr)
|
||||
errx(EX_DATAERR,
|
||||
"invalid set number %s\n", av[1]);
|
||||
ac -= 2; av += 2; co.use_set++;
|
||||
}
|
||||
}
|
||||
|
||||
if (co.do_pipe || co.do_nat) {
|
||||
ac--;
|
||||
av++;
|
||||
}
|
||||
NEED1("missing command");
|
||||
|
||||
/*
|
||||
* For pipes, queues and nats we normally say 'nat|pipe NN config'
|
||||
* but the code is easier to parse as 'nat|pipe config NN'
|
||||
* so we swap the two arguments.
|
||||
*/
|
||||
if ((co.do_pipe || co.do_nat) && ac > 1 && isdigit(*av[0])) {
|
||||
char *p = av[0];
|
||||
|
||||
av[0] = av[1];
|
||||
av[1] = p;
|
||||
}
|
||||
|
||||
if (co.use_set == 0) {
|
||||
if (_substrcmp(*av, "add") == 0)
|
||||
ipfw_add(av);
|
||||
else if (co.do_nat && _substrcmp(*av, "show") == 0)
|
||||
ipfw_show_nat(ac, av);
|
||||
else if (co.do_pipe && _substrcmp(*av, "config") == 0)
|
||||
#ifdef DUMMYNET
|
||||
ipfw_config_pipe(ac, av);
|
||||
#else
|
||||
{
|
||||
errx(EX_UNAVAILABLE, "ipfw_config_pipe not supported");
|
||||
}
|
||||
#endif
|
||||
else if (co.do_nat && _substrcmp(*av, "config") == 0)
|
||||
ipfw_config_nat(ac, av);
|
||||
else if (_substrcmp(*av, "set") == 0)
|
||||
ipfw_sets_handler(av);
|
||||
else if (_substrcmp(*av, "table") == 0)
|
||||
ipfw_table_handler(ac, av);
|
||||
else if (_substrcmp(*av, "enable") == 0)
|
||||
ipfw_sysctl_handler(av, 1);
|
||||
else if (_substrcmp(*av, "disable") == 0)
|
||||
ipfw_sysctl_handler(av, 0);
|
||||
else
|
||||
try_next = 1;
|
||||
}
|
||||
|
||||
if (co.use_set || try_next) {
|
||||
if (_substrcmp(*av, "delete") == 0)
|
||||
ipfw_delete(av);
|
||||
else if (_substrcmp(*av, "flush") == 0)
|
||||
ipfw_flush(co.do_force);
|
||||
else if (_substrcmp(*av, "zero") == 0)
|
||||
ipfw_zero(ac, av, 0 /* IP_FW_ZERO */);
|
||||
else if (_substrcmp(*av, "resetlog") == 0)
|
||||
ipfw_zero(ac, av, 1 /* IP_FW_RESETLOG */);
|
||||
else if (_substrcmp(*av, "print") == 0 ||
|
||||
_substrcmp(*av, "list") == 0)
|
||||
ipfw_list(ac, av, do_acct);
|
||||
else if (_substrcmp(*av, "show") == 0)
|
||||
ipfw_list(ac, av, 1 /* show counters */);
|
||||
else if (_substrcmp(*av, "table") == 0)
|
||||
ipfw_table_handler(ac, av);
|
||||
else if (_substrcmp(*av, "internal") == 0)
|
||||
ipfw_internal_handler(ac, av);
|
||||
else
|
||||
errx(EX_USAGE, "bad command `%s'", *av);
|
||||
}
|
||||
|
||||
/* Free memory allocated in the argument parsing. */
|
||||
free(save_av);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ipfw_readfile(int ac, char *av[])
|
||||
{
|
||||
#define MAX_ARGS 32
|
||||
char buf[4096];
|
||||
char *progname = av[0]; /* original program name */
|
||||
const char *cmd = NULL; /* preprocessor name, if any */
|
||||
const char *filename = av[ac-1]; /* file to read */
|
||||
int c, lineno=0;
|
||||
FILE *f = NULL;
|
||||
pid_t preproc = 0;
|
||||
|
||||
#ifndef FSTACK
|
||||
while ((c = getopt(ac, av, "cfNnp:qS")) != -1) {
|
||||
#else
|
||||
while ((c = getopt(ac, av, "cfNnp:qSP:")) != -1) {
|
||||
#endif
|
||||
switch(c) {
|
||||
case 'c':
|
||||
co.do_compact = 1;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
co.do_force = 1;
|
||||
break;
|
||||
|
||||
case 'N':
|
||||
co.do_resolv = 1;
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
co.test_only = 1;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
/*
|
||||
* ipfw -p cmd [args] filename
|
||||
*
|
||||
* We are done with getopt(). All arguments
|
||||
* except the filename go to the preprocessor,
|
||||
* so we need to do the following:
|
||||
* - check that a filename is actually present;
|
||||
* - advance av by optind-1 to skip arguments
|
||||
* already processed;
|
||||
* - decrease ac by optind, to remove the args
|
||||
* already processed and the final filename;
|
||||
* - set the last entry in av[] to NULL so
|
||||
* popen() can detect the end of the array;
|
||||
* - set optind=ac to let getopt() terminate.
|
||||
*/
|
||||
if (optind == ac)
|
||||
errx(EX_USAGE, "no filename argument");
|
||||
cmd = optarg;
|
||||
av[ac-1] = NULL;
|
||||
av += optind - 1;
|
||||
ac -= optind;
|
||||
optind = ac;
|
||||
break;
|
||||
|
||||
case 'q':
|
||||
co.do_quiet = 1;
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
co.show_sets = 1;
|
||||
break;
|
||||
|
||||
#ifdef FSTACK
|
||||
case 'P':
|
||||
ff_set_proc_id(atoi(optarg));
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
errx(EX_USAGE, "bad arguments, for usage"
|
||||
" summary ``ipfw''");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (cmd == NULL && ac != optind + 1)
|
||||
errx(EX_USAGE, "extraneous filename arguments %s", av[ac-1]);
|
||||
|
||||
if ((f = fopen(filename, "r")) == NULL)
|
||||
err(EX_UNAVAILABLE, "fopen: %s", filename);
|
||||
|
||||
if (cmd != NULL) { /* pipe through preprocessor */
|
||||
int pipedes[2];
|
||||
|
||||
if (pipe(pipedes) == -1)
|
||||
err(EX_OSERR, "cannot create pipe");
|
||||
|
||||
preproc = fork();
|
||||
if (preproc == -1)
|
||||
err(EX_OSERR, "cannot fork");
|
||||
|
||||
if (preproc == 0) {
|
||||
/*
|
||||
* Child, will run the preprocessor with the
|
||||
* file on stdin and the pipe on stdout.
|
||||
*/
|
||||
if (dup2(fileno(f), 0) == -1
|
||||
|| dup2(pipedes[1], 1) == -1)
|
||||
err(EX_OSERR, "dup2()");
|
||||
fclose(f);
|
||||
close(pipedes[1]);
|
||||
close(pipedes[0]);
|
||||
execvp(cmd, av);
|
||||
err(EX_OSERR, "execvp(%s) failed", cmd);
|
||||
} else { /* parent, will reopen f as the pipe */
|
||||
fclose(f);
|
||||
close(pipedes[1]);
|
||||
if ((f = fdopen(pipedes[0], "r")) == NULL) {
|
||||
int savederrno = errno;
|
||||
|
||||
(void)kill(preproc, SIGTERM);
|
||||
errno = savederrno;
|
||||
err(EX_OSERR, "fdopen()");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (fgets(buf, sizeof(buf), f)) { /* read commands */
|
||||
char linename[20];
|
||||
char *args[2];
|
||||
|
||||
lineno++;
|
||||
snprintf(linename, sizeof(linename), "Line %d", lineno);
|
||||
#ifndef FSTACK
|
||||
setprogname(linename); /* XXX */
|
||||
#endif
|
||||
args[0] = progname;
|
||||
args[1] = buf;
|
||||
ipfw_main(2, args);
|
||||
}
|
||||
fclose(f);
|
||||
if (cmd != NULL) {
|
||||
int status;
|
||||
|
||||
if (waitpid(preproc, &status, 0) == -1)
|
||||
errx(EX_OSERR, "waitpid()");
|
||||
if (WIFEXITED(status) && WEXITSTATUS(status) != EX_OK)
|
||||
errx(EX_UNAVAILABLE,
|
||||
"preprocessor exited with status %d",
|
||||
WEXITSTATUS(status));
|
||||
else if (WIFSIGNALED(status))
|
||||
errx(EX_UNAVAILABLE,
|
||||
"preprocessor exited with signal %d",
|
||||
WTERMSIG(status));
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main(int ac, char *av[])
|
||||
{
|
||||
#if defined(_WIN32) && defined(TCC)
|
||||
{
|
||||
WSADATA wsaData;
|
||||
int ret=0;
|
||||
unsigned short wVersionRequested = MAKEWORD(2, 2);
|
||||
ret = WSAStartup(wVersionRequested, &wsaData);
|
||||
if (ret != 0) {
|
||||
/* Tell the user that we could not find a usable */
|
||||
/* Winsock DLL. */
|
||||
printf("WSAStartup failed with error: %d\n", ret);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* If the last argument is an absolute pathname, interpret it
|
||||
* as a file to be preprocessed.
|
||||
*/
|
||||
|
||||
if (ac > 1 && av[ac - 1][0] == '/') {
|
||||
if (access(av[ac - 1], R_OK) == 0)
|
||||
ipfw_readfile(ac, av);
|
||||
else
|
||||
err(EX_USAGE, "pathname: %s", av[ac - 1]);
|
||||
} else {
|
||||
if (ipfw_main(ac, av)) {
|
||||
errx(EX_USAGE,
|
||||
"usage: ipfw [options]\n"
|
||||
"do \"ipfw -h\" or \"man ipfw\" for details");
|
||||
}
|
||||
}
|
||||
return EX_OK;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -10,3 +10,4 @@ MK_JAIL="no"
|
|||
MK_NETGRAPH_SUPPORT="no"
|
||||
MK_IPSEC_SUPPORT="no"
|
||||
MK_HAVE_LIBEDIT="no"
|
||||
MK_DUMMYNET="no"
|
||||
|
|
|
@ -55,6 +55,7 @@ FF_PROG_LIBS+= -Wl,--no-whole-archive -L${FF_DPDK}/lib
|
|||
FF_PROG_LIBS+= -Wl,--whole-archive -lrte_eal -lrte_mempool -lrte_ring
|
||||
FF_PROG_LIBS+= -Wl,--no-whole-archive -lrt -lm -ldl -lcrypto -pthread
|
||||
|
||||
CFLAGS+= -Wno-unused-but-set-variable -Wno-unused-variable
|
||||
CFLAGS+= ${FF_PROG_CFLAGS}
|
||||
CXXFLAGS+= ${FF_PROG_CFLAGS}
|
||||
|
||||
|
|
Loading…
Reference in New Issue