ipfw3: support bpf filter in layer4 module
[dragonfly.git] / lib / libipfw3 / layer4 / ipfw3_layer4.c
CommitLineData
105c533e
BY
1/*
2 * Copyright (c) 2014 The DragonFly Project. All rights reserved.
3 *
4 * This code is derived from software contributed to The DragonFly Project
5 * by Bill Yuan <bycn82@gmail.com>
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * 3. Neither the name of The DragonFly Project nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific, prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35#include <err.h>
36#include <errno.h>
37#include <grp.h>
38#include <pwd.h>
e895e94d 39#include <pcap.h>
105c533e
BY
40#include <stdio.h>
41#include <stdlib.h>
42#include <string.h>
43#include <sysexits.h>
44
45#include <net/if.h>
46#include <net/route.h>
47#include <net/pfil.h>
48#include <netinet/in.h>
49
6a03354e
MD
50#include "../../../sys/net/ipfw3/ip_fw3.h"
51#include "../../../sbin/ipfw3/ipfw.h"
52#include "ipfw3_layer4.h"
105c533e 53
e895e94d
BY
54int
55char_at(char *str, char c)
56{
57 int pos;
58 for (pos = 0; str[pos] != '\0'; pos++) {
59 if (str[pos] == c)
60 return pos;
61 }
62 return -1;
63}
105c533e
BY
64
65void
66parse_tcpflag(ipfw_insn **cmd, int *ac, char **av[])
67{
68 (*cmd)->opcode = O_LAYER4_TCPFLAG;
69 (*cmd)->module = MODULE_LAYER4_ID;
70 (*cmd)->len = ((*cmd)->len&(F_NOT|F_OR))|LEN_OF_IPFWINSN;
71 /* XXX TODO parse the tcpflag value and store in arg1 or arg3 */
72 NEXT_ARG1;
73}
74
75void
76parse_uid(ipfw_insn **cmd, int *ac, char **av[])
77{
78 char *end;
79 uid_t uid;
80 struct passwd *pwd;
81
82 NEXT_ARG1;
83 ipfw_insn_u32 *cmd32 = (ipfw_insn_u32 *)(*cmd);
84 uid = strtoul(**av, &end, 0);
85 pwd = (*end == '\0') ? getpwuid(uid) : getpwnam(**av);
86 if (pwd == NULL)
87 errx(EX_DATAERR, "uid \"%s\" not exists", **av);
88
89 cmd32->d[0] = pwd->pw_uid;
90
91 (*cmd)->opcode = O_LAYER4_UID;
92 (*cmd)->module = MODULE_LAYER4_ID;
93 (*cmd)->len = F_INSN_SIZE(ipfw_insn_u32);
94 NEXT_ARG1;
95}
96
97void
98parse_gid(ipfw_insn **cmd, int *ac, char **av[])
99{
100 char *end;
101 gid_t gid;
102 struct group *grp;
103
104 NEXT_ARG1;
105 ipfw_insn_u32 *cmd32 = (ipfw_insn_u32 *)(*cmd);
106 gid = strtoul(**av, &end, 0);
107 grp = (*end == '\0') ? getgrgid(gid) : getgrnam(**av);
108 if (grp == NULL)
109 errx(EX_DATAERR, "gid \"%s\" not exists", **av);
110
111 cmd32->d[0] = grp->gr_gid;
112
113 (*cmd)->opcode = O_LAYER4_GID;
114 (*cmd)->module = MODULE_LAYER4_ID;
115 (*cmd)->len = F_INSN_SIZE(ipfw_insn_u32);
116 NEXT_ARG1;
117}
118
dee12dda
BY
119void
120parse_established(ipfw_insn **cmd, int *ac, char **av[])
121{
122 NEXT_ARG1;
123 (*cmd)->opcode = O_LAYER4_ESTABLISHED;
124 (*cmd)->module = MODULE_LAYER4_ID;
125 (*cmd)->len |= LEN_OF_IPFWINSN;
126}
127
e895e94d
BY
128void
129parse_bpf(ipfw_insn **cmd, int *ac, char **av[])
130{
131 struct bpf_program program;
132 ipfw_insn_bpf *bpf;
133 int avlen;
134
135 NEXT_ARG1;
136 (*cmd)->opcode = O_LAYER4_BPF;
137 (*cmd)->module = MODULE_LAYER4_ID;
138
139 avlen = strlen(**av);
140 if (avlen > 256)
141 errx(EX_DATAERR, "bpf \"%s\" too long (max 256)", **av);
142 bpf = (ipfw_insn_bpf *)(*cmd);
143 strcpy(bpf->bf_str, **av);
144 if (pcap_compile_nopcap(65535, DLT_RAW, &program, **av, 1,
145 PCAP_NETMASK_UNKNOWN))
146 errx(EX_DATAERR, "bpf \"%s\" compilation error", **av);
147 bpf->bf_len = program.bf_len;
148
149 memcpy(&bpf->bf_insn, program.bf_insns,
150 sizeof(struct bpf_insn) * program.bf_len);
151 (*cmd)->len |= (sizeof(ipfw_insn_bpf) +
152 sizeof(struct bpf_insn) * (bpf->bf_len - 1)) /
153 sizeof(uint32_t);
154
155 pcap_freecode(&program);
156 NEXT_ARG1;
157}
158
105c533e
BY
159void
160show_tcpflag(ipfw_insn *cmd)
161{
162 printf(" tcpflag %d", cmd->arg1);
163}
164
165void
166show_uid(ipfw_insn *cmd)
167{
168 ipfw_insn_u32 *cmd32 = (ipfw_insn_u32 *)cmd;
169 struct passwd *pwd = getpwuid(cmd32->d[0]);
170 if (pwd){
171 printf(" uid %s", pwd->pw_name);
172 }else{
173 printf(" uid %u", cmd32->d[0]);
174 }
175}
176
177void
178show_gid(ipfw_insn *cmd)
179{
180 ipfw_insn_u32 *cmd32 = (ipfw_insn_u32 *)cmd;
181 struct group *grp = getgrgid(cmd32->d[0]);
182 if (grp){
183 printf(" gid %s", grp->gr_name);
184 }else{
185 printf(" gid %u", cmd32->d[0]);
186 }
187}
188
dee12dda
BY
189void
190show_established(ipfw_insn *cmd)
191{
192 printf(" established");
193}
105c533e 194
e895e94d
BY
195void
196show_bpf(ipfw_insn *cmd, int show_or)
197{
198 ipfw_insn_bpf *bpf;
199 bpf = (ipfw_insn_bpf *)cmd;
200 printf(" bpf \"%s\"", bpf->bf_str);
201}
202
105c533e
BY
203void
204load_module(register_func function, register_keyword keyword)
205{
206 keyword(MODULE_LAYER4_ID, O_LAYER4_TCPFLAG, "tcpflag", IPFW_KEYWORD_TYPE_FILTER);
207 function(MODULE_LAYER4_ID, O_LAYER4_TCPFLAG,
208 (parser_func)parse_tcpflag, (shower_func)show_tcpflag);
209 keyword(MODULE_LAYER4_ID, O_LAYER4_UID, "uid", IPFW_KEYWORD_TYPE_FILTER);
210 function(MODULE_LAYER4_ID, O_LAYER4_UID,
211 (parser_func)parse_uid, (shower_func)show_uid);
212 keyword(MODULE_LAYER4_ID, O_LAYER4_GID, "gid", IPFW_KEYWORD_TYPE_FILTER);
213 function(MODULE_LAYER4_ID, O_LAYER4_GID,
214 (parser_func)parse_gid, (shower_func)show_gid);
dee12dda
BY
215 keyword(MODULE_LAYER4_ID, O_LAYER4_ESTABLISHED, "established", IPFW_KEYWORD_TYPE_FILTER);
216 function(MODULE_LAYER4_ID, O_LAYER4_ESTABLISHED,
217 (parser_func)parse_established, (shower_func)show_established);
e895e94d
BY
218 keyword(MODULE_LAYER4_ID, O_LAYER4_BPF, "bpf", IPFW_KEYWORD_TYPE_FILTER);
219 function(MODULE_LAYER4_ID, O_LAYER4_BPF,
220 (parser_func)parse_bpf, (shower_func)show_bpf);
105c533e 221}