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:
whl739 2017-11-14 16:34:53 +08:00
parent 0b8e61ab4d
commit b37139ca32
33 changed files with 18532 additions and 31 deletions

View File

@ -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}

View File

@ -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);

View File

@ -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

View File

@ -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);
}

View File

@ -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;

View File

@ -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);

View File

@ -0,0 +1 @@
#define WITHOUT_BPF 1

1
lib/opt/opt_ipdivert.h Normal file
View File

@ -0,0 +1 @@
//#define IPDIVERT 1

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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 */

View File

@ -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_ */

View File

@ -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

View File

@ -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_ */

View File

@ -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"
/*

View File

@ -25,6 +25,7 @@
*/
#include <string.h>
#include <sys/socket.h>
#include <rte_malloc.h>
#include "ff_ipc.h"

102
tools/compat/time32.c Normal file
View File

@ -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);
}

25
tools/ipfw/Makefile Normal file
View File

@ -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

151
tools/ipfw/altq.c Normal file
View File

@ -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);
}
}

129
tools/ipfw/compat.c Normal file
View File

@ -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);
}

1989
tools/ipfw/dummynet.c Normal file

File diff suppressed because it is too large Load Diff

3725
tools/ipfw/ipfw.8 Normal file

File diff suppressed because it is too large Load Diff

5333
tools/ipfw/ipfw2.c Normal file

File diff suppressed because it is too large Load Diff

394
tools/ipfw/ipfw2.h Normal file
View File

@ -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

536
tools/ipfw/ipv6.c Normal file
View File

@ -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;
}

663
tools/ipfw/main.c Normal file
View File

@ -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;
}

1117
tools/ipfw/nat.c Normal file

File diff suppressed because it is too large Load Diff

2011
tools/ipfw/tables.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -10,3 +10,4 @@ MK_JAIL="no"
MK_NETGRAPH_SUPPORT="no"
MK_IPSEC_SUPPORT="no"
MK_HAVE_LIBEDIT="no"
MK_DUMMYNET="no"

View File

@ -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}