IOCTLS
To add and delete rules to the filter list, three basic ioctls are provided for use. The ioctls are called as:
ioctl(fd, SIOCADDFR, struct frentry **)
ioctl(fd, SIOCDELFR, struct frentry **)
ioctl(fd, SIOCIPFFL, int *)
However, the full complement is as follows:
ioctl(fd, SIOCADAFR, struct frentry **) (same as SIOCADDFR)
ioctl(fd, SIOCRMAFR, struct frentry **) (same as SIOCDELFR)
ioctl(fd, SIOCADIFR, struct frentry **)
ioctl(fd, SIOCRMIFR, struct frentry **)
ioctl(fd, SIOCINAFR, struct frentry **)
ioctl(fd, SIOCINIFR, struct frentry **)
ioctl(fd, SIOCSETFF, u_int *)
ioctl(fd, SIOGGETFF, u_int *)
ioctl(fd, SIOCGETFS, struct friostat **)
ioctl(fd, SIOCIPFFL, int *)
ioctl(fd, SIOCIPFFB, int *)
ioctl(fd, SIOCSWAPA, u_int *)
ioctl(fd, SIOCFRENB, u_int *)
ioctl(fd, SIOCFRSYN, u_int *)
ioctl(fd, SIOCFRZST, struct friostat **)
ioctl(fd, SIOCZRLST, struct frentry **)
ioctl(fd, SIOCAUTHW, struct fr_info **)
ioctl(fd, SIOCAUTHR, struct fr_info **)
ioctl(fd, SIOCATHST, struct fr_authstat **)
The variations, SIOCADAFR vs. SIOCADIFR, allow operation on the two lists, active and inactive, respectively. All of these ioctls are implemented as being routing ioctls and thus the same rules for the various routing ioctls and the file descriptor are employed, mainly being that the fd must be that of the device associated with the module (i.e., /dev/ipl).
The three groups of ioctls above perform adding rules to the end of the list (SIOCAD*), deletion of rules from any place in the list (SIOCRM*) and insertion of a rule into the list (SIOCIN*). The rule place into which it is inserted is stored in the "fr_hits" field, below.
typedef struct frentry {
struct frentry *fr_next;
u_short fr_group; /* group to which this rule belongs */
u_short fr_grhead; /* group # which this rule starts */
struct frentry *fr_grp;
intfr_ref; /* reference count - for grouping */
void *fr_ifa;
#if BSD >= 199306
void *fr_oifa;
#endif
/*
* These are only incremented when a packet matches this rule and
* it is the last match
*/
U_QUAD_T fr_hits;
U_QUAD_T fr_bytes;
/*
* Fields after this may not change whilst in the kernel.
*/
struct fr_ip fr_ip;
struct fr_ip fr_mip; /* mask structure */
u_char fr_tcpfm; /* tcp flags mask */
u_char fr_tcpf; /* tcp flags */
u_short fr_icmpm; /* data for ICMP packets (mask) */
u_short fr_icmp;
u_char fr_scmp; /* data for port comparisons */
u_char fr_dcmp;
u_short fr_dport;
u_short fr_sport;
u_short fr_stop; /* top port for <> and >< */
u_short fr_dtop; /* top port for <> and >< */
u_32_t fr_flags; /* per-rule flags && options (see below) */
u_short fr_skip; /* # of rules to skip */
u_short fr_loglevel; /* syslog log facility + priority */
int(*fr_func) __P((int, ip_t *, fr_info_t *));
char fr_icode; /* return ICMP code */
char fr_ifname[IFNAMSIZ];
#if BSD > 199306
char fr_oifname[IFNAMSIZ];
#endif
struct frdest fr_tif; /* "to" interface */
struct frdest fr_dif; /* duplicate packet interfaces */
} frentry_t;
When adding a new rule, all unused fields (in the filter rule) should be initialised to be zero. To insert a rule, at a particular position in the filter list, the number of the rule which it is to be inserted before must be put in the "fr_hits" field (the first rule is number 0).
Flags which are recognised in fr_flags:
FR_BLOCK 0x000001 /* do not allow packet to pass */
FR_PASS 0x000002 /* allow packet to pass */
FR_OUTQUE 0x000004 /* outgoing packets */
FR_INQUE 0x000008 /* ingoing packets */
FR_LOG0x000010 /* Log */
FR_LOGB 0x000011 /* Log-fail */
FR_LOGP 0x000012 /* Log-pass */
FR_LOGBODY 0x000020 /* log the body of packets too */
FR_LOGFIRST0x000040 /* log only the first packet to match */
FR_RETRST 0x000080 /* return a TCP RST packet if blocked */
FR_RETICMP 0x000100 /* return an ICMP packet if blocked */
FR_FAKEICMP0x00180 /* Return ICMP unreachable with fake source */
FR_NOMATCH 0x000200 /* no match occured */
FR_ACCOUNT 0x000400 /* count packet bytes */
FR_KEEPFRAG0x000800 /* keep fragment information */
FR_KEEPSTATE 0x001000 /* keep connection state information */
FR_INACTIVE0x002000
FR_QUICK 0x004000 /* match & stop processing list */
FR_FASTROUTE 0x008000 /* bypass normal routing */
FR_CALLNOW 0x010000 /* call another function (fr_func) if matches */
FR_DUP0x020000 /* duplicate the packet */
FR_LOGORBLOCK 0x040000 /* block the packet if it cant be logged */
FR_NOTSRCIP0x080000 /* not the src IP# */
FR_NOTDSTIP0x100000 /* not the dst IP# */
FR_AUTH 0x200000 /* use authentication */
FR_PREAUTH 0x400000 /* require preauthentication */
Values for fr_scomp and fr_dcomp (source and destination port value comparisons) :
FR_NONE 0
FR_EQUAL 1
FR_NEQUAL 2
FR_LESST 3
FR_GREATERT4
FR_LESSTE 5
FR_GREATERTE 6
FR_OUTRANGE7
FR_INRANGE 8
The third ioctl, SIOCIPFFL, flushes either the input filter list, the output filter list or both and it returns the number of filters removed from the list(s). The values which it will take and recognise are FR_INQUE and FR_OUTQUE (see above). This ioctl is also implemented for /dev/ipstate and will flush all state tables entries if passed 0 or just all those which are not established if passed 1.