#include <err.h>
#include <errno.h>
#include <grp.h>
#include <pwd.h>
#include <pcap.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sysexits.h>
#include <net/if.h>
#include <net/route.h>
#include <net/pfil.h>
#include <netinet/in.h>
#include <net/ipfw3/ip_fw3.h>
#include "../../../sbin/ipfw3/ipfw3.h"
#include "ipfw3_layer4.h"
int
char_at(char *str, char c)
{
int pos;
for (pos = 0; str[pos] != '\0'; pos++) {
if (str[pos] == c)
return pos;
}
return -1;
}
void
parse_tcpflag(ipfw_insn **cmd, int *ac, char **av[])
{
(*cmd)->opcode = O_LAYER4_TCPFLAG;
(*cmd)->module = MODULE_LAYER4_ID;
(*cmd)->len |= LEN_OF_IPFWINSN;
NEXT_ARG1;
}
void
parse_uid(ipfw_insn **cmd, int *ac, char **av[])
{
char *end;
uid_t uid;
struct passwd *pwd;
NEXT_ARG1;
ipfw_insn_u32 *cmd32 = (ipfw_insn_u32 *)(*cmd);
uid = strtoul(**av, &end, 0);
pwd = (*end == '\0') ? getpwuid(uid) : getpwnam(**av);
if (pwd == NULL)
errx(EX_DATAERR, "uid \"%s\" not exists", **av);
cmd32->d[0] = pwd->pw_uid;
(*cmd)->opcode = O_LAYER4_UID;
(*cmd)->module = MODULE_LAYER4_ID;
(*cmd)->len |= F_INSN_SIZE(ipfw_insn_u32);
NEXT_ARG1;
}
void
parse_gid(ipfw_insn **cmd, int *ac, char **av[])
{
char *end;
gid_t gid;
struct group *grp;
NEXT_ARG1;
ipfw_insn_u32 *cmd32 = (ipfw_insn_u32 *)(*cmd);
gid = strtoul(**av, &end, 0);
grp = (*end == '\0') ? getgrgid(gid) : getgrnam(**av);
if (grp == NULL)
errx(EX_DATAERR, "gid \"%s\" not exists", **av);
cmd32->d[0] = grp->gr_gid;
(*cmd)->opcode = O_LAYER4_GID;
(*cmd)->module = MODULE_LAYER4_ID;
(*cmd)->len |= F_INSN_SIZE(ipfw_insn_u32);
NEXT_ARG1;
}
void
parse_established(ipfw_insn **cmd, int *ac, char **av[])
{
NEXT_ARG1;
(*cmd)->opcode = O_LAYER4_ESTABLISHED;
(*cmd)->module = MODULE_LAYER4_ID;
(*cmd)->len |= LEN_OF_IPFWINSN;
}
void
parse_bpf(ipfw_insn **cmd, int *ac, char **av[])
{
struct bpf_program program;
ipfw_insn_bpf *bpf;
int avlen;
NEXT_ARG1;
(*cmd)->opcode = O_LAYER4_BPF;
(*cmd)->module = MODULE_LAYER4_ID;
avlen = strlen(**av);
if (avlen > 256)
errx(EX_DATAERR, "bpf \"%s\" too long (max 256)", **av);
bpf = (ipfw_insn_bpf *)(*cmd);
strcpy(bpf->bf_str, **av);
if (pcap_compile_nopcap(65535, DLT_RAW, &program, **av, 1,
PCAP_NETMASK_UNKNOWN))
errx(EX_DATAERR, "bpf \"%s\" compilation error", **av);
bpf->bf_len = program.bf_len;
memcpy(&bpf->bf_insn, program.bf_insns,
sizeof(struct bpf_insn) * program.bf_len);
(*cmd)->len |= (sizeof(ipfw_insn_bpf) +
sizeof(struct bpf_insn) * (bpf->bf_len - 1)) /
sizeof(uint32_t);
pcap_freecode(&program);
NEXT_ARG1;
}
void
show_tcpflag(ipfw_insn *cmd, int show_or)
{
char *word = "tcpflag";
if (show_or)
word = "or";
printf(" %s %d", word, cmd->arg1);
}
void
show_uid(ipfw_insn *cmd, int show_or)
{
ipfw_insn_u32 *cmd32 = (ipfw_insn_u32 *)cmd;
struct passwd *pwd = getpwuid(cmd32->d[0]);
char *word = "uid";
if (show_or)
word = "or";
if (pwd){
printf(" %s %s", word, pwd->pw_name);
}else{
printf(" %s %u", word, cmd32->d[0]);
}
}
void
show_gid(ipfw_insn *cmd, int show_or)
{
ipfw_insn_u32 *cmd32 = (ipfw_insn_u32 *)cmd;
struct group *grp = getgrgid(cmd32->d[0]);
char *word = "gid";
if (show_or)
word = "or";
if (grp){
printf(" %s %s", word, grp->gr_name);
}else{
printf(" %s %u", word, cmd32->d[0]);
}
}
void
show_established(ipfw_insn *cmd, int show_or)
{
printf(" established");
}
void
show_bpf(ipfw_insn *cmd, int show_or)
{
ipfw_insn_bpf *bpf;
char *word = "bpf";
if (show_or)
word = "or";
bpf = (ipfw_insn_bpf *)cmd;
printf(" %s \"%s\"", word, bpf->bf_str);
}
void
load_module(register_func function, register_keyword keyword)
{
keyword(MODULE_LAYER4_ID, O_LAYER4_TCPFLAG, "tcpflag", FILTER);
function(MODULE_LAYER4_ID, O_LAYER4_TCPFLAG,
(parser_func)parse_tcpflag, (shower_func)show_tcpflag);
keyword(MODULE_LAYER4_ID, O_LAYER4_UID, "uid", FILTER);
function(MODULE_LAYER4_ID, O_LAYER4_UID,
(parser_func)parse_uid, (shower_func)show_uid);
keyword(MODULE_LAYER4_ID, O_LAYER4_GID, "gid", FILTER);
function(MODULE_LAYER4_ID, O_LAYER4_GID,
(parser_func)parse_gid, (shower_func)show_gid);
keyword(MODULE_LAYER4_ID, O_LAYER4_ESTABLISHED, "established", FILTER);
function(MODULE_LAYER4_ID, O_LAYER4_ESTABLISHED,
(parser_func)parse_established, (shower_func)show_established);
keyword(MODULE_LAYER4_ID, O_LAYER4_BPF, "bpf", FILTER);
function(MODULE_LAYER4_ID, O_LAYER4_BPF,
(parser_func)parse_bpf, (shower_func)show_bpf);
}