pfctl.c (0d6c8174ef2f3d8d6fb02ec97753a0937796a5c6) pfctl.c (0d71f9f36e6c1849fdaf6c1edc1178be07357034)
1/* $OpenBSD: pfctl.c,v 1.278 2008/08/31 20:18:17 jmc Exp $ */
2
3/*-
4 * SPDX-License-Identifier: BSD-2-Clause
5 *
6 * Copyright (c) 2001 Daniel Hartmeier
7 * Copyright (c) 2002,2003 Henning Brauer
8 * All rights reserved.

--- 41 unchanged lines hidden (view full) ---

50#include <net/pfvar.h>
51#include <arpa/inet.h>
52#include <net/altq/altq.h>
53#include <sys/sysctl.h>
54
55#include <err.h>
56#include <errno.h>
57#include <fcntl.h>
1/* $OpenBSD: pfctl.c,v 1.278 2008/08/31 20:18:17 jmc Exp $ */
2
3/*-
4 * SPDX-License-Identifier: BSD-2-Clause
5 *
6 * Copyright (c) 2001 Daniel Hartmeier
7 * Copyright (c) 2002,2003 Henning Brauer
8 * All rights reserved.

--- 41 unchanged lines hidden (view full) ---

50#include <net/pfvar.h>
51#include <arpa/inet.h>
52#include <net/altq/altq.h>
53#include <sys/sysctl.h>
54
55#include <err.h>
56#include <errno.h>
57#include <fcntl.h>
58#include <libpfctl.h>
58#include <limits.h>
59#include <netdb.h>
60#include <stdint.h>
61#include <stdio.h>
62#include <stdlib.h>
63#include <string.h>
64#include <unistd.h>
65
59#include <limits.h>
60#include <netdb.h>
61#include <stdint.h>
62#include <stdio.h>
63#include <stdlib.h>
64#include <string.h>
65#include <unistd.h>
66
66#include "pfctl_ioctl.h"
67#include "pfctl_parser.h"
68#include "pfctl.h"
69
70void usage(void);
71int pfctl_enable(int, int);
72int pfctl_disable(int, int);
73int pfctl_clear_stats(int, int);
74int pfctl_get_skip_ifaces(void);

--- 1211 unchanged lines hidden (view full) ---

1286 if (ioctl(pf->dev, DIOCADDADDR, &pf->paddr))
1287 err(1, "DIOCADDADDR");
1288 }
1289 }
1290 return (0);
1291}
1292
1293int
67#include "pfctl_parser.h"
68#include "pfctl.h"
69
70void usage(void);
71int pfctl_enable(int, int);
72int pfctl_disable(int, int);
73int pfctl_clear_stats(int, int);
74int pfctl_get_skip_ifaces(void);

--- 1211 unchanged lines hidden (view full) ---

1286 if (ioctl(pf->dev, DIOCADDADDR, &pf->paddr))
1287 err(1, "DIOCADDADDR");
1288 }
1289 }
1290 return (0);
1291}
1292
1293int
1294pfctl_add_rule(struct pfctl *pf, struct pf_rule *r, const char *anchor_call)
1294pfctl_append_rule(struct pfctl *pf, struct pf_rule *r, const char *anchor_call)
1295{
1296 u_int8_t rs_num;
1297 struct pf_rule *rule;
1298 struct pf_ruleset *rs;
1299 char *p;
1300
1301 rs_num = pf_get_ruleset_number(r->action);
1302 if (rs_num == PF_RULESET_MAX)
1303 errx(1, "Invalid rule type %d", r->action);
1304
1305 rs = &pf->anchor->ruleset;
1306
1307 if (anchor_call[0] && r->anchor == NULL) {
1308 /*
1309 * Don't make non-brace anchors part of the main anchor pool.
1310 */
1311 if ((r->anchor = calloc(1, sizeof(*r->anchor))) == NULL)
1295{
1296 u_int8_t rs_num;
1297 struct pf_rule *rule;
1298 struct pf_ruleset *rs;
1299 char *p;
1300
1301 rs_num = pf_get_ruleset_number(r->action);
1302 if (rs_num == PF_RULESET_MAX)
1303 errx(1, "Invalid rule type %d", r->action);
1304
1305 rs = &pf->anchor->ruleset;
1306
1307 if (anchor_call[0] && r->anchor == NULL) {
1308 /*
1309 * Don't make non-brace anchors part of the main anchor pool.
1310 */
1311 if ((r->anchor = calloc(1, sizeof(*r->anchor))) == NULL)
1312 err(1, "pfctl_add_rule: calloc");
1312 err(1, "pfctl_append_rule: calloc");
1313
1314 pf_init_ruleset(&r->anchor->ruleset);
1315 r->anchor->ruleset.anchor = r->anchor;
1316 if (strlcpy(r->anchor->path, anchor_call,
1317 sizeof(rule->anchor->path)) >= sizeof(rule->anchor->path))
1313
1314 pf_init_ruleset(&r->anchor->ruleset);
1315 r->anchor->ruleset.anchor = r->anchor;
1316 if (strlcpy(r->anchor->path, anchor_call,
1317 sizeof(rule->anchor->path)) >= sizeof(rule->anchor->path))
1318 errx(1, "pfctl_add_rule: strlcpy");
1318 errx(1, "pfctl_append_rule: strlcpy");
1319 if ((p = strrchr(anchor_call, '/')) != NULL) {
1320 if (!strlen(p))
1319 if ((p = strrchr(anchor_call, '/')) != NULL) {
1320 if (!strlen(p))
1321 err(1, "pfctl_add_rule: bad anchor name %s",
1321 err(1, "pfctl_append_rule: bad anchor name %s",
1322 anchor_call);
1323 } else
1324 p = (char *)anchor_call;
1325 if (strlcpy(r->anchor->name, p,
1326 sizeof(rule->anchor->name)) >= sizeof(rule->anchor->name))
1322 anchor_call);
1323 } else
1324 p = (char *)anchor_call;
1325 if (strlcpy(r->anchor->name, p,
1326 sizeof(rule->anchor->name)) >= sizeof(rule->anchor->name))
1327 errx(1, "pfctl_add_rule: strlcpy");
1327 errx(1, "pfctl_append_rule: strlcpy");
1328 }
1329
1330 if ((rule = calloc(1, sizeof(*rule))) == NULL)
1331 err(1, "calloc");
1332 bcopy(r, rule, sizeof(*rule));
1333 TAILQ_INIT(&rule->rpool.list);
1334 pfctl_move_pool(&r->rpool, &rule->rpool);
1335

--- 86 unchanged lines hidden (view full) ---

1422 return (0);
1423
1424 error:
1425 path[len] = '\0';
1426 return (error);
1427
1428}
1429
1328 }
1329
1330 if ((rule = calloc(1, sizeof(*rule))) == NULL)
1331 err(1, "calloc");
1332 bcopy(r, rule, sizeof(*rule));
1333 TAILQ_INIT(&rule->rpool.list);
1334 pfctl_move_pool(&r->rpool, &rule->rpool);
1335

--- 86 unchanged lines hidden (view full) ---

1422 return (0);
1423
1424 error:
1425 path[len] = '\0';
1426 return (error);
1427
1428}
1429
1430static void
1431pfctl_nv_add_addr(nvlist_t *nvparent, const char *name,
1432 const struct pf_addr *addr)
1433{
1434 nvlist_t *nvl = nvlist_create(0);
1435
1436 nvlist_add_binary(nvl, "addr", addr, sizeof(*addr));
1437
1438 nvlist_add_nvlist(nvparent, name, nvl);
1439}
1440
1441static void
1442pfctl_nv_add_addr_wrap(nvlist_t *nvparent, const char *name,
1443 const struct pf_addr_wrap *addr)
1444{
1445 nvlist_t *nvl = nvlist_create(0);
1446
1447 nvlist_add_number(nvl, "type", addr->type);
1448 nvlist_add_number(nvl, "iflags", addr->iflags);
1449 nvlist_add_string(nvl, "ifname", addr->v.ifname);
1450 nvlist_add_string(nvl, "tblname", addr->v.tblname);
1451 pfctl_nv_add_addr(nvl, "addr", &addr->v.a.addr);
1452 pfctl_nv_add_addr(nvl, "mask", &addr->v.a.mask);
1453
1454 nvlist_add_nvlist(nvparent, name, nvl);
1455}
1456
1457static void
1458pfctl_nv_add_rule_addr(nvlist_t *nvparent, const char *name,
1459 const struct pf_rule_addr *addr)
1460{
1461 u_int64_t ports[2];
1462 nvlist_t *nvl = nvlist_create(0);
1463
1464 pfctl_nv_add_addr_wrap(nvl, "addr", &addr->addr);
1465 ports[0] = addr->port[0];
1466 ports[1] = addr->port[1];
1467 nvlist_add_number_array(nvl, "port", ports, 2);
1468 nvlist_add_number(nvl, "neg", addr->neg);
1469 nvlist_add_number(nvl, "port_op", addr->port_op);
1470
1471 nvlist_add_nvlist(nvparent, name, nvl);
1472}
1473
1474static void
1475pfctl_nv_add_pool(nvlist_t *nvparent, const char *name,
1476 const struct pf_pool *pool)
1477{
1478 u_int64_t ports[2];
1479 nvlist_t *nvl = nvlist_create(0);
1480
1481 nvlist_add_binary(nvl, "key", &pool->key, sizeof(pool->key));
1482 pfctl_nv_add_addr(nvl, "counter", &pool->counter);
1483 nvlist_add_number(nvl, "tblidx", pool->tblidx);
1484
1485 ports[0] = pool->proxy_port[0];
1486 ports[1] = pool->proxy_port[1];
1487 nvlist_add_number_array(nvl, "proxy_port", ports, 2);
1488 nvlist_add_number(nvl, "opts", pool->opts);
1489
1490 nvlist_add_nvlist(nvparent, name, nvl);
1491}
1492
1493static void
1494pfctl_nv_add_uid(nvlist_t *nvparent, const char *name,
1495 const struct pf_rule_uid *uid)
1496{
1497 u_int64_t uids[2];
1498 nvlist_t *nvl = nvlist_create(0);
1499
1500 uids[0] = uid->uid[0];
1501 uids[1] = uid->uid[1];
1502 nvlist_add_number_array(nvl, "uid", uids, 2);
1503 nvlist_add_number(nvl, "op", uid->op);
1504
1505 nvlist_add_nvlist(nvparent, name, nvl);
1506}
1507
1508static void
1509pfctl_nv_add_divert(nvlist_t *nvparent, const char *name,
1510 const struct pf_rule *r)
1511{
1512 nvlist_t *nvl = nvlist_create(0);
1513
1514 pfctl_nv_add_addr(nvl, "addr", &r->divert.addr);
1515 nvlist_add_number(nvl, "port", r->divert.port);
1516
1517 nvlist_add_nvlist(nvparent, name, nvl);
1518}
1519
1520static int
1521pfctl_addrule(struct pfctl *pf, const struct pf_rule *r, const char *anchor,
1522 const char *anchor_call, u_int32_t ticket, u_int32_t pool_ticket)
1523{
1524 struct pfioc_nv nv;
1525 u_int64_t timeouts[PFTM_MAX];
1526 u_int64_t set_prio[2];
1527 nvlist_t *nvl, *nvlr;
1528 int ret;
1529
1530 nvl = nvlist_create(0);
1531 nvlr = nvlist_create(0);
1532
1533 nvlist_add_number(nvl, "ticket", ticket);
1534 nvlist_add_number(nvl, "pool_ticket", pool_ticket);
1535 nvlist_add_string(nvl, "anchor", anchor);
1536 nvlist_add_string(nvl, "anchor_call", anchor_call);
1537
1538 nvlist_add_number(nvlr, "nr", r->nr);
1539 pfctl_nv_add_rule_addr(nvlr, "src", &r->src);
1540 pfctl_nv_add_rule_addr(nvlr, "dst", &r->dst);
1541
1542 nvlist_add_string(nvlr, "label", r->label);
1543 nvlist_add_string(nvlr, "ifname", r->ifname);
1544 nvlist_add_string(nvlr, "qname", r->qname);
1545 nvlist_add_string(nvlr, "pqname", r->pqname);
1546 nvlist_add_string(nvlr, "tagname", r->tagname);
1547 nvlist_add_string(nvlr, "match_tagname", r->match_tagname);
1548 nvlist_add_string(nvlr, "overload_tblname", r->overload_tblname);
1549
1550 pfctl_nv_add_pool(nvlr, "rpool", &r->rpool);
1551
1552 nvlist_add_number(nvlr, "os_fingerprint", r->os_fingerprint);
1553
1554 nvlist_add_number(nvlr, "rtableid", r->rtableid);
1555 for (int i = 0; i < PFTM_MAX; i++)
1556 timeouts[i] = r->timeout[i];
1557 nvlist_add_number_array(nvlr, "timeout", timeouts, PFTM_MAX);
1558 nvlist_add_number(nvlr, "max_states", r->max_states);
1559 nvlist_add_number(nvlr, "max_src_nodes", r->max_src_nodes);
1560 nvlist_add_number(nvlr, "max_src_states", r->max_src_states);
1561 nvlist_add_number(nvlr, "max_src_conn", r->max_src_conn);
1562 nvlist_add_number(nvlr, "max_src_conn_rate.limit",
1563 r->max_src_conn_rate.limit);
1564 nvlist_add_number(nvlr, "max_src_conn_rate.seconds",
1565 r->max_src_conn_rate.seconds);
1566 nvlist_add_number(nvlr, "prob", r->prob);
1567 nvlist_add_number(nvlr, "cuid", r->cuid);
1568 nvlist_add_number(nvlr, "cpid", r->cpid);
1569
1570 nvlist_add_number(nvlr, "return_icmp", r->return_icmp);
1571 nvlist_add_number(nvlr, "return_icmp6", r->return_icmp6);
1572
1573 nvlist_add_number(nvlr, "max_mss", r->max_mss);
1574 nvlist_add_number(nvlr, "scrub_flags", r->scrub_flags);
1575
1576 pfctl_nv_add_uid(nvlr, "uid", &r->uid);
1577 pfctl_nv_add_uid(nvlr, "gid", (struct pf_rule_uid *)&r->gid);
1578
1579 nvlist_add_number(nvlr, "rule_flag", r->rule_flag);
1580 nvlist_add_number(nvlr, "action", r->action);
1581 nvlist_add_number(nvlr, "direction", r->direction);
1582 nvlist_add_number(nvlr, "log", r->log);
1583 nvlist_add_number(nvlr, "logif", r->logif);
1584 nvlist_add_number(nvlr, "quick", r->quick);
1585 nvlist_add_number(nvlr, "ifnot", r->ifnot);
1586 nvlist_add_number(nvlr, "match_tag_not", r->match_tag_not);
1587 nvlist_add_number(nvlr, "natpass", r->natpass);
1588
1589 nvlist_add_number(nvlr, "keep_state", r->keep_state);
1590 nvlist_add_number(nvlr, "af", r->af);
1591 nvlist_add_number(nvlr, "proto", r->proto);
1592 nvlist_add_number(nvlr, "type", r->type);
1593 nvlist_add_number(nvlr, "code", r->code);
1594 nvlist_add_number(nvlr, "flags", r->flags);
1595 nvlist_add_number(nvlr, "flagset", r->flagset);
1596 nvlist_add_number(nvlr, "min_ttl", r->min_ttl);
1597 nvlist_add_number(nvlr, "allow_opts", r->allow_opts);
1598 nvlist_add_number(nvlr, "rt", r->rt);
1599 nvlist_add_number(nvlr, "return_ttl", r->return_ttl);
1600 nvlist_add_number(nvlr, "tos", r->tos);
1601 nvlist_add_number(nvlr, "set_tos", r->set_tos);
1602 nvlist_add_number(nvlr, "anchor_relative", r->anchor_relative);
1603 nvlist_add_number(nvlr, "anchor_wildcard", r->anchor_wildcard);
1604
1605 nvlist_add_number(nvlr, "flush", r->flush);
1606
1607 nvlist_add_number(nvlr, "prio", r->prio);
1608 set_prio[0] = r->set_prio[0];
1609 set_prio[1] = r->set_prio[1];
1610 nvlist_add_number_array(nvlr, "set_prio", set_prio, 2);
1611
1612 pfctl_nv_add_divert(nvlr, "divert", r);
1613
1614 nvlist_add_nvlist(nvl, "rule", nvlr);
1615
1616 /* Now do the call. */
1617 nv.data = nvlist_pack(nvl, &nv.len);
1618 nv.size = nv.len;
1619
1620 ret = ioctl(pf->dev, DIOCADDRULENV, &nv);
1621
1622 free(nv.data);
1623 nvlist_destroy(nvl);
1624
1625 return (ret);
1626}
1627
1628int
1629pfctl_load_rule(struct pfctl *pf, char *path, struct pf_rule *r, int depth)
1630{
1631 u_int8_t rs_num = pf_get_ruleset_number(r->action);
1632 char *name;
1633 u_int32_t ticket;
1634 char anchor[PF_ANCHOR_NAME_SIZE];
1635 int len = strlen(path);

--- 16 unchanged lines hidden (view full) ---

1652 } else
1653 name = r->anchor->path;
1654 } else
1655 name = "";
1656
1657 if ((pf->opts & PF_OPT_NOACTION) == 0) {
1658 if (pfctl_add_pool(pf, &r->rpool, r->af))
1659 return (1);
1430int
1431pfctl_load_rule(struct pfctl *pf, char *path, struct pf_rule *r, int depth)
1432{
1433 u_int8_t rs_num = pf_get_ruleset_number(r->action);
1434 char *name;
1435 u_int32_t ticket;
1436 char anchor[PF_ANCHOR_NAME_SIZE];
1437 int len = strlen(path);

--- 16 unchanged lines hidden (view full) ---

1454 } else
1455 name = r->anchor->path;
1456 } else
1457 name = "";
1458
1459 if ((pf->opts & PF_OPT_NOACTION) == 0) {
1460 if (pfctl_add_pool(pf, &r->rpool, r->af))
1461 return (1);
1660 if (pfctl_addrule(pf, r, anchor, name, ticket,
1462 if (pfctl_add_rule(pf->dev, r, anchor, name, ticket,
1661 pf->paddr.ticket))
1662 err(1, "DIOCADDRULENV");
1663 }
1664
1665 if (pf->opts & PF_OPT_VERBOSE) {
1666 INDENT(depth, !(pf->opts & PF_OPT_VERBOSE2));
1667 print_rule(r, r->anchor ? r->anchor->name : "",
1668 pf->opts & PF_OPT_VERBOSE2,

--- 1042 unchanged lines hidden ---
1463 pf->paddr.ticket))
1464 err(1, "DIOCADDRULENV");
1465 }
1466
1467 if (pf->opts & PF_OPT_VERBOSE) {
1468 INDENT(depth, !(pf->opts & PF_OPT_VERBOSE2));
1469 print_rule(r, r->anchor ? r->anchor->name : "",
1470 pf->opts & PF_OPT_VERBOSE2,

--- 1042 unchanged lines hidden ---