xref: /dragonfly/lib/libipfw3/layer4/ipfw3_layer4.c (revision 4408d5485757eef6e44859025e931d1c1b6746c4)
1 /*
2  * Copyright (c) 2014 - 2018 The DragonFly Project.  All rights reserved.
3  *
4  * This code is derived from software contributed to The DragonFly Project
5  * by Bill Yuan <bycn82@dragonflybsd.org>
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>
39 #include <pcap.h>
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 
50 #include <net/ipfw3/ip_fw3.h>
51 #include "../../../sbin/ipfw3/ipfw3.h"
52 #include "ipfw3_layer4.h"
53 
54 int
char_at(char * str,char c)55 char_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 }
64 
65 void
parse_tcpflag(ipfw_insn ** cmd,int * ac,char ** av[])66 parse_tcpflag(ipfw_insn **cmd, int *ac, char **av[])
67 {
68           (*cmd)->opcode = O_LAYER4_TCPFLAG;
69           (*cmd)->module = MODULE_LAYER4_ID;
70           (*cmd)->len |= LEN_OF_IPFWINSN;
71           /* XXX TODO parse the tcpflag value and store in arg1 or arg3 */
72           NEXT_ARG1;
73 }
74 
75 void
parse_uid(ipfw_insn ** cmd,int * ac,char ** av[])76 parse_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 
97 void
parse_gid(ipfw_insn ** cmd,int * ac,char ** av[])98 parse_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 
119 void
parse_established(ipfw_insn ** cmd,int * ac,char ** av[])120 parse_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 
128 void
parse_bpf(ipfw_insn ** cmd,int * ac,char ** av[])129 parse_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 
159 void
show_tcpflag(ipfw_insn * cmd,int show_or)160 show_tcpflag(ipfw_insn *cmd, int show_or)
161 {
162           char *word = "tcpflag";
163           if (show_or)
164                     word = "or";
165           printf(" %s %d", word, cmd->arg1);
166 }
167 
168 void
show_uid(ipfw_insn * cmd,int show_or)169 show_uid(ipfw_insn *cmd, int show_or)
170 {
171           ipfw_insn_u32 *cmd32 = (ipfw_insn_u32 *)cmd;
172           struct passwd *pwd = getpwuid(cmd32->d[0]);
173           char *word = "uid";
174           if (show_or)
175                     word = "or";
176           if (pwd){
177                     printf(" %s %s", word, pwd->pw_name);
178           }else{
179                     printf(" %s %u", word, cmd32->d[0]);
180           }
181 }
182 
183 void
show_gid(ipfw_insn * cmd,int show_or)184 show_gid(ipfw_insn *cmd, int show_or)
185 {
186           ipfw_insn_u32 *cmd32 = (ipfw_insn_u32 *)cmd;
187           struct group *grp = getgrgid(cmd32->d[0]);
188           char *word = "gid";
189           if (show_or)
190                     word = "or";
191           if (grp){
192                     printf(" %s %s", word, grp->gr_name);
193           }else{
194                     printf(" %s %u", word, cmd32->d[0]);
195           }
196 }
197 
198 void
show_established(ipfw_insn * cmd,int show_or)199 show_established(ipfw_insn *cmd, int show_or)
200 {
201           printf(" established");
202 }
203 
204 void
show_bpf(ipfw_insn * cmd,int show_or)205 show_bpf(ipfw_insn *cmd, int show_or)
206 {
207           ipfw_insn_bpf *bpf;
208           char *word = "bpf";
209           if (show_or)
210                     word = "or";
211           bpf = (ipfw_insn_bpf *)cmd;
212           printf(" %s \"%s\"", word, bpf->bf_str);
213 }
214 
215 void
load_module(register_func function,register_keyword keyword)216 load_module(register_func function, register_keyword keyword)
217 {
218           keyword(MODULE_LAYER4_ID, O_LAYER4_TCPFLAG, "tcpflag", FILTER);
219           function(MODULE_LAYER4_ID, O_LAYER4_TCPFLAG,
220                               (parser_func)parse_tcpflag, (shower_func)show_tcpflag);
221           keyword(MODULE_LAYER4_ID, O_LAYER4_UID, "uid", FILTER);
222           function(MODULE_LAYER4_ID, O_LAYER4_UID,
223                               (parser_func)parse_uid, (shower_func)show_uid);
224           keyword(MODULE_LAYER4_ID, O_LAYER4_GID, "gid", FILTER);
225           function(MODULE_LAYER4_ID, O_LAYER4_GID,
226                               (parser_func)parse_gid, (shower_func)show_gid);
227           keyword(MODULE_LAYER4_ID, O_LAYER4_ESTABLISHED, "established", FILTER);
228           function(MODULE_LAYER4_ID, O_LAYER4_ESTABLISHED,
229                               (parser_func)parse_established, (shower_func)show_established);
230           keyword(MODULE_LAYER4_ID, O_LAYER4_BPF, "bpf", FILTER);
231           function(MODULE_LAYER4_ID, O_LAYER4_BPF,
232                               (parser_func)parse_bpf, (shower_func)show_bpf);
233 }
234