/* * Copyright (c) 2014 - 2018 The DragonFly Project. All rights reserved. * * This code is derived from software contributed to The DragonFly Project * by Bill Yuan * * 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 DragonFly 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 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 HOLDERS 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #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; /* XXX TODO parse the tcpflag value and store in arg1 or arg3 */ 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); }