xref: /dflybsd-src/lib/libipfw3/layer4/ipfw3_layer4.c (revision 4408d5485757eef6e44859025e931d1c1b6746c4)
16a03354eSMatthew Dillon /*
2*4408d548SBill Yuan  * Copyright (c) 2014 - 2018 The DragonFly Project.  All rights reserved.
36a03354eSMatthew Dillon  *
46a03354eSMatthew Dillon  * This code is derived from software contributed to The DragonFly Project
59187b359SBill Yuan  * by Bill Yuan <bycn82@dragonflybsd.org>
66a03354eSMatthew Dillon  *
76a03354eSMatthew Dillon  * Redistribution and use in source and binary forms, with or without
86a03354eSMatthew Dillon  * modification, are permitted provided that the following conditions
96a03354eSMatthew Dillon  * are met:
106a03354eSMatthew Dillon  *
116a03354eSMatthew Dillon  * 1. Redistributions of source code must retain the above copyright
126a03354eSMatthew Dillon  *    notice, this list of conditions and the following disclaimer.
136a03354eSMatthew Dillon  * 2. Redistributions in binary form must reproduce the above copyright
146a03354eSMatthew Dillon  *    notice, this list of conditions and the following disclaimer in
156a03354eSMatthew Dillon  *    the documentation and/or other materials provided with the
166a03354eSMatthew Dillon  *    distribution.
176a03354eSMatthew Dillon  * 3. Neither the name of The DragonFly Project nor the names of its
186a03354eSMatthew Dillon  *    contributors may be used to endorse or promote products derived
196a03354eSMatthew Dillon  *    from this software without specific, prior written permission.
206a03354eSMatthew Dillon  *
216a03354eSMatthew Dillon  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
226a03354eSMatthew Dillon  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
236a03354eSMatthew Dillon  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
246a03354eSMatthew Dillon  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
256a03354eSMatthew Dillon  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
266a03354eSMatthew Dillon  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
276a03354eSMatthew Dillon  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
286a03354eSMatthew Dillon  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
296a03354eSMatthew Dillon  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
306a03354eSMatthew Dillon  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
316a03354eSMatthew Dillon  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
326a03354eSMatthew Dillon  * SUCH DAMAGE.
336a03354eSMatthew Dillon  */
346a03354eSMatthew Dillon 
356a03354eSMatthew Dillon #include <err.h>
366a03354eSMatthew Dillon #include <errno.h>
376a03354eSMatthew Dillon #include <grp.h>
386a03354eSMatthew Dillon #include <pwd.h>
39e895e94dSBill Yuan #include <pcap.h>
406a03354eSMatthew Dillon #include <stdio.h>
416a03354eSMatthew Dillon #include <stdlib.h>
426a03354eSMatthew Dillon #include <string.h>
436a03354eSMatthew Dillon #include <sysexits.h>
446a03354eSMatthew Dillon 
456a03354eSMatthew Dillon #include <net/if.h>
466a03354eSMatthew Dillon #include <net/route.h>
476a03354eSMatthew Dillon #include <net/pfil.h>
486a03354eSMatthew Dillon #include <netinet/in.h>
496a03354eSMatthew Dillon 
5059ea0e34SBill Yuan #include <net/ipfw3/ip_fw3.h>
519187b359SBill Yuan #include "../../../sbin/ipfw3/ipfw3.h"
526a03354eSMatthew Dillon #include "ipfw3_layer4.h"
536a03354eSMatthew Dillon 
54e895e94dSBill Yuan int
char_at(char * str,char c)55e895e94dSBill Yuan char_at(char *str, char c)
56e895e94dSBill Yuan {
57e895e94dSBill Yuan 	int pos;
58e895e94dSBill Yuan 	for (pos = 0; str[pos] != '\0'; pos++) {
59e895e94dSBill Yuan 		if (str[pos] == c)
60e895e94dSBill Yuan 			return pos;
61e895e94dSBill Yuan 	}
62e895e94dSBill Yuan 	return -1;
63e895e94dSBill Yuan }
646a03354eSMatthew Dillon 
656a03354eSMatthew Dillon void
parse_tcpflag(ipfw_insn ** cmd,int * ac,char ** av[])666a03354eSMatthew Dillon parse_tcpflag(ipfw_insn **cmd, int *ac, char **av[])
676a03354eSMatthew Dillon {
686a03354eSMatthew Dillon 	(*cmd)->opcode = O_LAYER4_TCPFLAG;
696a03354eSMatthew Dillon 	(*cmd)->module = MODULE_LAYER4_ID;
705f62bb52SBill Yuan 	(*cmd)->len |= LEN_OF_IPFWINSN;
716a03354eSMatthew Dillon 	/* XXX TODO parse the tcpflag value and store in arg1 or arg3 */
726a03354eSMatthew Dillon 	NEXT_ARG1;
736a03354eSMatthew Dillon }
746a03354eSMatthew Dillon 
756a03354eSMatthew Dillon void
parse_uid(ipfw_insn ** cmd,int * ac,char ** av[])766a03354eSMatthew Dillon parse_uid(ipfw_insn **cmd, int *ac, char **av[])
776a03354eSMatthew Dillon {
786a03354eSMatthew Dillon 	char *end;
796a03354eSMatthew Dillon 	uid_t uid;
806a03354eSMatthew Dillon 	struct passwd *pwd;
816a03354eSMatthew Dillon 
826a03354eSMatthew Dillon 	NEXT_ARG1;
836a03354eSMatthew Dillon 	ipfw_insn_u32 *cmd32 = (ipfw_insn_u32 *)(*cmd);
846a03354eSMatthew Dillon 	uid = strtoul(**av, &end, 0);
856a03354eSMatthew Dillon 	pwd = (*end == '\0') ? getpwuid(uid) : getpwnam(**av);
866a03354eSMatthew Dillon 	if (pwd == NULL)
876a03354eSMatthew Dillon 		errx(EX_DATAERR, "uid \"%s\" not exists", **av);
886a03354eSMatthew Dillon 
896a03354eSMatthew Dillon 	cmd32->d[0] = pwd->pw_uid;
906a03354eSMatthew Dillon 
916a03354eSMatthew Dillon 	(*cmd)->opcode = O_LAYER4_UID;
926a03354eSMatthew Dillon 	(*cmd)->module = MODULE_LAYER4_ID;
935f62bb52SBill Yuan 	(*cmd)->len |= F_INSN_SIZE(ipfw_insn_u32);
946a03354eSMatthew Dillon 	NEXT_ARG1;
956a03354eSMatthew Dillon }
966a03354eSMatthew Dillon 
976a03354eSMatthew Dillon void
parse_gid(ipfw_insn ** cmd,int * ac,char ** av[])986a03354eSMatthew Dillon parse_gid(ipfw_insn **cmd, int *ac, char **av[])
996a03354eSMatthew Dillon {
1006a03354eSMatthew Dillon 	char *end;
1016a03354eSMatthew Dillon 	gid_t gid;
1026a03354eSMatthew Dillon 	struct group *grp;
1036a03354eSMatthew Dillon 
1046a03354eSMatthew Dillon 	NEXT_ARG1;
1056a03354eSMatthew Dillon 	ipfw_insn_u32 *cmd32 = (ipfw_insn_u32 *)(*cmd);
1066a03354eSMatthew Dillon 	gid = strtoul(**av, &end, 0);
1076a03354eSMatthew Dillon 	grp = (*end == '\0') ? getgrgid(gid) : getgrnam(**av);
1086a03354eSMatthew Dillon 	if (grp == NULL)
1096a03354eSMatthew Dillon 		errx(EX_DATAERR, "gid \"%s\" not exists", **av);
1106a03354eSMatthew Dillon 
1116a03354eSMatthew Dillon 	cmd32->d[0] = grp->gr_gid;
1126a03354eSMatthew Dillon 
1136a03354eSMatthew Dillon 	(*cmd)->opcode = O_LAYER4_GID;
1146a03354eSMatthew Dillon 	(*cmd)->module = MODULE_LAYER4_ID;
1155f62bb52SBill Yuan 	(*cmd)->len |= F_INSN_SIZE(ipfw_insn_u32);
1166a03354eSMatthew Dillon 	NEXT_ARG1;
1176a03354eSMatthew Dillon }
1186a03354eSMatthew Dillon 
1196a03354eSMatthew Dillon void
parse_established(ipfw_insn ** cmd,int * ac,char ** av[])120dee12ddaSBill Yuan parse_established(ipfw_insn **cmd, int *ac, char **av[])
121dee12ddaSBill Yuan {
122dee12ddaSBill Yuan 	NEXT_ARG1;
123dee12ddaSBill Yuan 	(*cmd)->opcode = O_LAYER4_ESTABLISHED;
124dee12ddaSBill Yuan 	(*cmd)->module = MODULE_LAYER4_ID;
125dee12ddaSBill Yuan 	(*cmd)->len |= LEN_OF_IPFWINSN;
126dee12ddaSBill Yuan }
127dee12ddaSBill Yuan 
128dee12ddaSBill Yuan void
parse_bpf(ipfw_insn ** cmd,int * ac,char ** av[])129e895e94dSBill Yuan parse_bpf(ipfw_insn **cmd, int *ac, char **av[])
130e895e94dSBill Yuan {
131e895e94dSBill Yuan 	struct bpf_program program;
132e895e94dSBill Yuan 	ipfw_insn_bpf *bpf;
133e895e94dSBill Yuan 	int avlen;
134e895e94dSBill Yuan 
135e895e94dSBill Yuan 	NEXT_ARG1;
136e895e94dSBill Yuan 	(*cmd)->opcode = O_LAYER4_BPF;
137e895e94dSBill Yuan 	(*cmd)->module = MODULE_LAYER4_ID;
138e895e94dSBill Yuan 
139e895e94dSBill Yuan 	avlen = strlen(**av);
140e895e94dSBill Yuan 	if (avlen > 256)
141e895e94dSBill Yuan 		errx(EX_DATAERR, "bpf \"%s\" too long (max 256)", **av);
142e895e94dSBill Yuan 	bpf = (ipfw_insn_bpf *)(*cmd);
143e895e94dSBill Yuan 	strcpy(bpf->bf_str, **av);
144e895e94dSBill Yuan 	if (pcap_compile_nopcap(65535, DLT_RAW, &program, **av, 1,
145e895e94dSBill Yuan 			PCAP_NETMASK_UNKNOWN))
146e895e94dSBill Yuan 		errx(EX_DATAERR, "bpf \"%s\" compilation error", **av);
147e895e94dSBill Yuan 	bpf->bf_len = program.bf_len;
148e895e94dSBill Yuan 
149e895e94dSBill Yuan 	memcpy(&bpf->bf_insn, program.bf_insns,
150e895e94dSBill Yuan 			sizeof(struct bpf_insn) * program.bf_len);
151e895e94dSBill Yuan 	(*cmd)->len |= (sizeof(ipfw_insn_bpf) +
152e895e94dSBill Yuan 			sizeof(struct bpf_insn) * (bpf->bf_len - 1)) /
153e895e94dSBill Yuan 			sizeof(uint32_t);
154e895e94dSBill Yuan 
155e895e94dSBill Yuan 	pcap_freecode(&program);
156e895e94dSBill Yuan 	NEXT_ARG1;
157e895e94dSBill Yuan }
158e895e94dSBill Yuan 
159e895e94dSBill Yuan void
show_tcpflag(ipfw_insn * cmd,int show_or)1606ce8c93fSBill Yuan show_tcpflag(ipfw_insn *cmd, int show_or)
1616a03354eSMatthew Dillon {
1625f62bb52SBill Yuan 	char *word = "tcpflag";
1635f62bb52SBill Yuan 	if (show_or)
1645f62bb52SBill Yuan 		word = "or";
1655f62bb52SBill Yuan 	printf(" %s %d", word, cmd->arg1);
1666a03354eSMatthew Dillon }
1676a03354eSMatthew Dillon 
1686a03354eSMatthew Dillon void
show_uid(ipfw_insn * cmd,int show_or)1696ce8c93fSBill Yuan show_uid(ipfw_insn *cmd, int show_or)
1706a03354eSMatthew Dillon {
1716a03354eSMatthew Dillon 	ipfw_insn_u32 *cmd32 = (ipfw_insn_u32 *)cmd;
1726a03354eSMatthew Dillon 	struct passwd *pwd = getpwuid(cmd32->d[0]);
1735f62bb52SBill Yuan 	char *word = "uid";
1745f62bb52SBill Yuan 	if (show_or)
1755f62bb52SBill Yuan 		word = "or";
1766a03354eSMatthew Dillon 	if (pwd){
1775f62bb52SBill Yuan 		printf(" %s %s", word, pwd->pw_name);
1786a03354eSMatthew Dillon 	}else{
1795f62bb52SBill Yuan 		printf(" %s %u", word, cmd32->d[0]);
1806a03354eSMatthew Dillon 	}
1816a03354eSMatthew Dillon }
1826a03354eSMatthew Dillon 
1836a03354eSMatthew Dillon void
show_gid(ipfw_insn * cmd,int show_or)1846ce8c93fSBill Yuan show_gid(ipfw_insn *cmd, int show_or)
1856a03354eSMatthew Dillon {
1866a03354eSMatthew Dillon 	ipfw_insn_u32 *cmd32 = (ipfw_insn_u32 *)cmd;
1876a03354eSMatthew Dillon 	struct group *grp = getgrgid(cmd32->d[0]);
1885f62bb52SBill Yuan 	char *word = "gid";
1895f62bb52SBill Yuan 	if (show_or)
1905f62bb52SBill Yuan 		word = "or";
1916a03354eSMatthew Dillon 	if (grp){
1925f62bb52SBill Yuan 		printf(" %s %s", word, grp->gr_name);
1936a03354eSMatthew Dillon 	}else{
1945f62bb52SBill Yuan 		printf(" %s %u", word, cmd32->d[0]);
1956a03354eSMatthew Dillon 	}
1966a03354eSMatthew Dillon }
1976a03354eSMatthew Dillon 
198dee12ddaSBill Yuan void
show_established(ipfw_insn * cmd,int show_or)1996ce8c93fSBill Yuan show_established(ipfw_insn *cmd, int show_or)
200dee12ddaSBill Yuan {
201dee12ddaSBill Yuan 	printf(" established");
202dee12ddaSBill Yuan }
2036a03354eSMatthew Dillon 
2046a03354eSMatthew Dillon void
show_bpf(ipfw_insn * cmd,int show_or)205e895e94dSBill Yuan show_bpf(ipfw_insn *cmd, int show_or)
206e895e94dSBill Yuan {
207e895e94dSBill Yuan 	ipfw_insn_bpf *bpf;
2086ce8c93fSBill Yuan 	char *word = "bpf";
2096ce8c93fSBill Yuan 	if (show_or)
2106ce8c93fSBill Yuan 		word = "or";
211e895e94dSBill Yuan 	bpf = (ipfw_insn_bpf *)cmd;
2126ce8c93fSBill Yuan 	printf(" %s \"%s\"", word, bpf->bf_str);
213e895e94dSBill Yuan }
214e895e94dSBill Yuan 
215e895e94dSBill Yuan void
load_module(register_func function,register_keyword keyword)2166a03354eSMatthew Dillon load_module(register_func function, register_keyword keyword)
2176a03354eSMatthew Dillon {
2183b6ebdc3SBill Yuan 	keyword(MODULE_LAYER4_ID, O_LAYER4_TCPFLAG, "tcpflag", FILTER);
2196a03354eSMatthew Dillon 	function(MODULE_LAYER4_ID, O_LAYER4_TCPFLAG,
2206a03354eSMatthew Dillon 			(parser_func)parse_tcpflag, (shower_func)show_tcpflag);
2213b6ebdc3SBill Yuan 	keyword(MODULE_LAYER4_ID, O_LAYER4_UID, "uid", FILTER);
2226a03354eSMatthew Dillon 	function(MODULE_LAYER4_ID, O_LAYER4_UID,
2236a03354eSMatthew Dillon 			(parser_func)parse_uid, (shower_func)show_uid);
2243b6ebdc3SBill Yuan 	keyword(MODULE_LAYER4_ID, O_LAYER4_GID, "gid", FILTER);
2256a03354eSMatthew Dillon 	function(MODULE_LAYER4_ID, O_LAYER4_GID,
2266a03354eSMatthew Dillon 			(parser_func)parse_gid, (shower_func)show_gid);
2273b6ebdc3SBill Yuan 	keyword(MODULE_LAYER4_ID, O_LAYER4_ESTABLISHED, "established", FILTER);
228dee12ddaSBill Yuan 	function(MODULE_LAYER4_ID, O_LAYER4_ESTABLISHED,
229dee12ddaSBill Yuan 			(parser_func)parse_established, (shower_func)show_established);
2303b6ebdc3SBill Yuan 	keyword(MODULE_LAYER4_ID, O_LAYER4_BPF, "bpf", FILTER);
231e895e94dSBill Yuan 	function(MODULE_LAYER4_ID, O_LAYER4_BPF,
232e895e94dSBill Yuan 			(parser_func)parse_bpf, (shower_func)show_bpf);
2336a03354eSMatthew Dillon }
234