|
Lines 1277-1283
print_ip(struct buf_pr *bp, struct format_opts *fo
Link Here
|
| 1277 |
* prints a MAC address/mask pair |
1277 |
* prints a MAC address/mask pair |
| 1278 |
*/ |
1278 |
*/ |
| 1279 |
static void |
1279 |
static void |
| 1280 |
print_mac(struct buf_pr *bp, uint8_t *addr, uint8_t *mask) |
1280 |
format_mac(struct buf_pr *bp, uint8_t *addr, uint8_t *mask) |
| 1281 |
{ |
1281 |
{ |
| 1282 |
int l = contigmask(mask, 48); |
1282 |
int l = contigmask(mask, 48); |
| 1283 |
|
1283 |
|
|
Lines 1296-1301
static void
Link Here
|
| 1296 |
} |
1296 |
} |
| 1297 |
|
1297 |
|
| 1298 |
static void |
1298 |
static void |
|
|
1299 |
print_mac(struct buf_pr *bp, ipfw_insn_mac *mac) |
| 1300 |
{ |
| 1301 |
|
| 1302 |
bprintf(bp, " MAC"); |
| 1303 |
format_mac(bp, mac->addr, mac->mask); |
| 1304 |
format_mac(bp, mac->addr + 6, mac->mask + 6); |
| 1305 |
} |
| 1306 |
|
| 1307 |
static void |
| 1299 |
fill_icmptypes(ipfw_insn_u32 *cmd, char *av) |
1308 |
fill_icmptypes(ipfw_insn_u32 *cmd, char *av) |
| 1300 |
{ |
1309 |
{ |
| 1301 |
uint8_t type; |
1310 |
uint8_t type; |
|
Lines 1405-1411
show_prerequisites(struct buf_pr *bp, int *flags,
Link Here
|
| 1405 |
*flags |= want; |
1414 |
*flags |= want; |
| 1406 |
} |
1415 |
} |
| 1407 |
|
1416 |
|
|
|
1417 |
#define insntod(cmd, type) ((ipfw_insn_ ## type *)(cmd)) |
| 1418 |
#define IPFW_MAX_CMDS 1000 |
| 1419 |
struct show_state { |
| 1420 |
struct ip_fw_rule *rule; |
| 1421 |
const ipfw_insn *printed[IPFW_MAX_CMDS]; |
| 1422 |
const ipfw_insn *eaction; |
| 1423 |
int pcnt; /* number of printed[] instructions */ |
| 1424 |
int flags; |
| 1425 |
int proto; |
| 1426 |
int or_block; |
| 1427 |
}; |
| 1428 |
|
| 1408 |
static void |
1429 |
static void |
|
|
1430 |
init_state(struct show_state *state, struct ip_fw_rule *rule) |
| 1431 |
{ |
| 1432 |
|
| 1433 |
state->rule = rule; |
| 1434 |
state->eaction = NULL; |
| 1435 |
state->pcnt = 0; |
| 1436 |
state->flags = 0; |
| 1437 |
state->proto = 0; |
| 1438 |
state->or_block = 0; |
| 1439 |
} |
| 1440 |
|
| 1441 |
static int |
| 1442 |
is_printed_opcode(struct show_state *state, const ipfw_insn *cmd) |
| 1443 |
{ |
| 1444 |
int i; |
| 1445 |
|
| 1446 |
for (i = 0; i < state->pcnt; i++) |
| 1447 |
if (state->printed[i] == cmd) |
| 1448 |
return (1); |
| 1449 |
return (0); |
| 1450 |
} |
| 1451 |
|
| 1452 |
static void |
| 1453 |
mark_printed(struct show_state *state, const ipfw_insn *cmd) |
| 1454 |
{ |
| 1455 |
|
| 1456 |
if (state->pcnt < nitems(state->printed) - 1) |
| 1457 |
state->printed[state->pcnt++] = cmd; |
| 1458 |
} |
| 1459 |
|
| 1460 |
static void |
| 1461 |
print_limit(struct buf_pr *bp, const ipfw_insn_limit *limit) |
| 1462 |
{ |
| 1463 |
struct _s_x *p = limit_masks; |
| 1464 |
char const *comma = " "; |
| 1465 |
uint8_t x; |
| 1466 |
|
| 1467 |
bprintf(bp, " limit"); |
| 1468 |
for (x = limit->limit_mask; p->x != 0; p++) { |
| 1469 |
if ((x & p->x) == p->x) { |
| 1470 |
x &= ~p->x; |
| 1471 |
bprintf(bp, "%s%s", comma, p->s); |
| 1472 |
comma = ","; |
| 1473 |
} |
| 1474 |
} |
| 1475 |
bprint_uint_arg(bp, " ", limit->conn_limit); |
| 1476 |
} |
| 1477 |
|
| 1478 |
static ipfw_insn * |
| 1479 |
print_opcode(struct buf_pr *bp, struct format_opts *fo, |
| 1480 |
struct show_state *state, uint8_t opcode) |
| 1481 |
{ |
| 1482 |
struct protoent *pe; |
| 1483 |
struct passwd *pwd; |
| 1484 |
struct group *grp; |
| 1485 |
ipfw_insn *cmd; |
| 1486 |
char const *s; |
| 1487 |
double d; |
| 1488 |
int l; |
| 1489 |
|
| 1490 |
for (l = state->rule->act_ofs, cmd = state->rule->cmd; |
| 1491 |
l > 0; l -= F_LEN(cmd), cmd += F_LEN(cmd)) { |
| 1492 |
/* We use zero opcode to print the rest of options */ |
| 1493 |
if (opcode != 0 && cmd->opcode != opcode) |
| 1494 |
continue; |
| 1495 |
if (is_printed_opcode(state, cmd)) |
| 1496 |
continue; |
| 1497 |
if ((cmd->len & F_OR) != 0 && state->or_block == 0) |
| 1498 |
bprintf(bp, " {"); |
| 1499 |
if (cmd->opcode != O_IN && (cmd->len & F_NOT) != 0) |
| 1500 |
bprintf(bp, " not"); |
| 1501 |
switch (cmd->opcode) { |
| 1502 |
case O_PROB: |
| 1503 |
d = 1.0 * insntod(cmd, u32)->d[0] / 0x7fffffff; |
| 1504 |
bprintf(bp, "prob %f ", d); |
| 1505 |
break; |
| 1506 |
case O_PROBE_STATE: /* no need to print anything here */ |
| 1507 |
break; |
| 1508 |
case O_IP_SRC: |
| 1509 |
case O_IP_SRC_LOOKUP: |
| 1510 |
case O_IP_SRC_MASK: |
| 1511 |
case O_IP_SRC_ME: |
| 1512 |
case O_IP_SRC_SET: |
| 1513 |
case O_IP_DST: |
| 1514 |
case O_IP_DST_LOOKUP: |
| 1515 |
case O_IP_DST_MASK: |
| 1516 |
case O_IP_DST_ME: |
| 1517 |
case O_IP_DST_SET: |
| 1518 |
print_ip(bp, fo, insntod(cmd, ip), ""); |
| 1519 |
break; |
| 1520 |
case O_IP6_SRC: |
| 1521 |
case O_IP6_SRC_MASK: |
| 1522 |
case O_IP6_SRC_ME: |
| 1523 |
case O_IP6_DST: |
| 1524 |
case O_IP6_DST_MASK: |
| 1525 |
case O_IP6_DST_ME: |
| 1526 |
print_ip6(bp, insntod(cmd, ip6), ""); |
| 1527 |
break; |
| 1528 |
case O_FLOW6ID: |
| 1529 |
print_flow6id(bp, insntod(cmd, u32)); |
| 1530 |
break; |
| 1531 |
case O_IP_DSTPORT: |
| 1532 |
case O_IP_SRCPORT: |
| 1533 |
print_newports(bp, insntod(cmd, u16), state->proto, |
| 1534 |
(state->flags & (HAVE_SRCIP | HAVE_DSTIP)) == |
| 1535 |
(HAVE_SRCIP | HAVE_DSTIP) ? cmd->opcode: 0); |
| 1536 |
break; |
| 1537 |
case O_PROTO: |
| 1538 |
pe = getprotobynumber(cmd->arg1); |
| 1539 |
if (state->flags & HAVE_PROTO) |
| 1540 |
bprintf(bp, " proto"); |
| 1541 |
if (pe != NULL) |
| 1542 |
bprintf(bp, " %s", pe->p_name); |
| 1543 |
else |
| 1544 |
bprintf(bp, " %u", cmd->arg1); |
| 1545 |
break; |
| 1546 |
case O_MACADDR2: |
| 1547 |
print_mac(bp, insntod(cmd, mac)); |
| 1548 |
break; |
| 1549 |
case O_MAC_TYPE: |
| 1550 |
print_newports(bp, insntod(cmd, u16), |
| 1551 |
IPPROTO_ETHERTYPE, cmd->opcode); |
| 1552 |
break; |
| 1553 |
case O_FRAG: |
| 1554 |
bprintf(bp, " frag"); |
| 1555 |
break; |
| 1556 |
case O_FIB: |
| 1557 |
bprintf(bp, " fib %u", cmd->arg1); |
| 1558 |
break; |
| 1559 |
case O_SOCKARG: |
| 1560 |
bprintf(bp, " sockarg"); |
| 1561 |
break; |
| 1562 |
case O_IN: |
| 1563 |
bprintf(bp, cmd->len & F_NOT ? " out" : " in"); |
| 1564 |
break; |
| 1565 |
case O_DIVERTED: |
| 1566 |
switch (cmd->arg1) { |
| 1567 |
case 3: |
| 1568 |
bprintf(bp, " diverted"); |
| 1569 |
break; |
| 1570 |
case 2: |
| 1571 |
bprintf(bp, " diverted-output"); |
| 1572 |
break; |
| 1573 |
case 1: |
| 1574 |
bprintf(bp, " diverted-loopback"); |
| 1575 |
break; |
| 1576 |
default: |
| 1577 |
bprintf(bp, " diverted-?<%u>", cmd->arg1); |
| 1578 |
break; |
| 1579 |
} |
| 1580 |
break; |
| 1581 |
case O_LAYER2: |
| 1582 |
bprintf(bp, " layer2"); |
| 1583 |
break; |
| 1584 |
case O_XMIT: |
| 1585 |
case O_RECV: |
| 1586 |
case O_VIA: |
| 1587 |
if (cmd->opcode == O_XMIT) |
| 1588 |
s = "xmit"; |
| 1589 |
else if (cmd->opcode == O_RECV) |
| 1590 |
s = "recv"; |
| 1591 |
else /* if (cmd->opcode == O_VIA) */ |
| 1592 |
s = "via"; |
| 1593 |
switch (insntod(cmd, if)->name[0]) { |
| 1594 |
case '\0': |
| 1595 |
bprintf(bp, " %s %s", s, |
| 1596 |
inet_ntoa(insntod(cmd, if)->p.ip)); |
| 1597 |
break; |
| 1598 |
case '\1': |
| 1599 |
bprintf(bp, " %s table(%s)", s, |
| 1600 |
table_search_ctlv(fo->tstate, |
| 1601 |
insntod(cmd, if)->p.kidx)); |
| 1602 |
break; |
| 1603 |
default: |
| 1604 |
bprintf(bp, " %s %s", s, |
| 1605 |
insntod(cmd, if)->name); |
| 1606 |
} |
| 1607 |
break; |
| 1608 |
case O_IP_FLOW_LOOKUP: |
| 1609 |
s = table_search_ctlv(fo->tstate, cmd->arg1); |
| 1610 |
bprintf(bp, " flow table(%s", s); |
| 1611 |
if (F_LEN(cmd) == F_INSN_SIZE(ipfw_insn_u32)) |
| 1612 |
bprintf(bp, ",%u", insntod(cmd, u32)->d[0]); |
| 1613 |
bprintf(bp, ")"); |
| 1614 |
break; |
| 1615 |
case O_IPID: |
| 1616 |
case O_IPTTL: |
| 1617 |
case O_IPLEN: |
| 1618 |
case O_TCPDATALEN: |
| 1619 |
case O_TCPWIN: |
| 1620 |
if (F_LEN(cmd) == 1) { |
| 1621 |
switch (cmd->opcode) { |
| 1622 |
case O_IPID: |
| 1623 |
s = "ipid"; |
| 1624 |
break; |
| 1625 |
case O_IPTTL: |
| 1626 |
s = "ipttl"; |
| 1627 |
break; |
| 1628 |
case O_IPLEN: |
| 1629 |
s = "iplen"; |
| 1630 |
break; |
| 1631 |
case O_TCPDATALEN: |
| 1632 |
s = "tcpdatalen"; |
| 1633 |
break; |
| 1634 |
case O_TCPWIN: |
| 1635 |
s = "tcpwin"; |
| 1636 |
break; |
| 1637 |
} |
| 1638 |
bprintf(bp, " %s %u", s, cmd->arg1); |
| 1639 |
} else |
| 1640 |
print_newports(bp, insntod(cmd, u16), 0, |
| 1641 |
cmd->opcode); |
| 1642 |
break; |
| 1643 |
case O_IPVER: |
| 1644 |
bprintf(bp, " ipver %u", cmd->arg1); |
| 1645 |
break; |
| 1646 |
case O_IPPRECEDENCE: |
| 1647 |
bprintf(bp, " ipprecedence %u", cmd->arg1 >> 5); |
| 1648 |
break; |
| 1649 |
case O_DSCP: |
| 1650 |
print_dscp(bp, insntod(cmd, u32)); |
| 1651 |
break; |
| 1652 |
case O_IPOPT: |
| 1653 |
print_flags(bp, "ipoptions", cmd, f_ipopts); |
| 1654 |
break; |
| 1655 |
case O_IPTOS: |
| 1656 |
print_flags(bp, "iptos", cmd, f_iptos); |
| 1657 |
break; |
| 1658 |
case O_ICMPTYPE: |
| 1659 |
print_icmptypes(bp, insntod(cmd, u32)); |
| 1660 |
break; |
| 1661 |
case O_ESTAB: |
| 1662 |
bprintf(bp, " established"); |
| 1663 |
break; |
| 1664 |
case O_TCPFLAGS: |
| 1665 |
print_flags(bp, "tcpflags", cmd, f_tcpflags); |
| 1666 |
break; |
| 1667 |
case O_TCPOPTS: |
| 1668 |
print_flags(bp, "tcpoptions", cmd, f_tcpopts); |
| 1669 |
break; |
| 1670 |
case O_TCPACK: |
| 1671 |
bprintf(bp, " tcpack %d", |
| 1672 |
ntohl(insntod(cmd, u32)->d[0])); |
| 1673 |
break; |
| 1674 |
case O_TCPSEQ: |
| 1675 |
bprintf(bp, " tcpseq %d", |
| 1676 |
ntohl(insntod(cmd, u32)->d[0])); |
| 1677 |
break; |
| 1678 |
case O_UID: |
| 1679 |
pwd = getpwuid(insntod(cmd, u32)->d[0]); |
| 1680 |
if (pwd != NULL) |
| 1681 |
bprintf(bp, " uid %s", pwd->pw_name); |
| 1682 |
else |
| 1683 |
bprintf(bp, " uid %u", |
| 1684 |
insntod(cmd, u32)->d[0]); |
| 1685 |
break; |
| 1686 |
case O_GID: |
| 1687 |
grp = getgrgid(insntod(cmd, u32)->d[0]); |
| 1688 |
if (grp != NULL) |
| 1689 |
bprintf(bp, " gid %s", grp->gr_name); |
| 1690 |
else |
| 1691 |
bprintf(bp, " gid %u", |
| 1692 |
insntod(cmd, u32)->d[0]); |
| 1693 |
break; |
| 1694 |
case O_JAIL: |
| 1695 |
bprintf(bp, " jail %d", insntod(cmd, u32)->d[0]); |
| 1696 |
break; |
| 1697 |
case O_VERREVPATH: |
| 1698 |
bprintf(bp, " verrevpath"); |
| 1699 |
break; |
| 1700 |
case O_VERSRCREACH: |
| 1701 |
bprintf(bp, " versrcreach"); |
| 1702 |
break; |
| 1703 |
case O_ANTISPOOF: |
| 1704 |
bprintf(bp, " antispoof"); |
| 1705 |
break; |
| 1706 |
case O_IPSEC: |
| 1707 |
bprintf(bp, " ipsec"); |
| 1708 |
break; |
| 1709 |
case O_NOP: |
| 1710 |
/* |
| 1711 |
* Skip O_NOP, when we printing the rest |
| 1712 |
* of options, it will be handled separately. |
| 1713 |
*/ |
| 1714 |
if (opcode != cmd->opcode) |
| 1715 |
return (NULL); |
| 1716 |
bprintf(bp, " // %s", (char *)(cmd + 1)); |
| 1717 |
break; |
| 1718 |
case O_KEEP_STATE: |
| 1719 |
bprintf(bp, " keep-state"); |
| 1720 |
bprintf(bp, " :%s", |
| 1721 |
object_search_ctlv(fo->tstate, cmd->arg1, |
| 1722 |
IPFW_TLV_STATE_NAME)); |
| 1723 |
break; |
| 1724 |
case O_LIMIT: |
| 1725 |
print_limit(bp, insntod(cmd, limit)); |
| 1726 |
bprintf(bp, " :%s", |
| 1727 |
object_search_ctlv(fo->tstate, cmd->arg1, |
| 1728 |
IPFW_TLV_STATE_NAME)); |
| 1729 |
break; |
| 1730 |
case O_IP6: |
| 1731 |
bprintf(bp, " ip6"); |
| 1732 |
break; |
| 1733 |
case O_IP4: |
| 1734 |
bprintf(bp, " ip4"); |
| 1735 |
break; |
| 1736 |
case O_ICMP6TYPE: |
| 1737 |
print_icmp6types(bp, insntod(cmd, u32)); |
| 1738 |
break; |
| 1739 |
case O_EXT_HDR: |
| 1740 |
print_ext6hdr(bp, cmd); |
| 1741 |
break; |
| 1742 |
case O_TAGGED: |
| 1743 |
if (F_LEN(cmd) == 1) |
| 1744 |
bprint_uint_arg(bp, " tagged ", cmd->arg1); |
| 1745 |
else |
| 1746 |
print_newports(bp, insntod(cmd, u16), |
| 1747 |
0, O_TAGGED); |
| 1748 |
break; |
| 1749 |
default: |
| 1750 |
bprintf(bp, " [opcode %d len %d]", cmd->opcode, |
| 1751 |
cmd->len); |
| 1752 |
} |
| 1753 |
if (cmd->len & F_OR) { |
| 1754 |
bprintf(bp, " or"); |
| 1755 |
state->or_block = 1; |
| 1756 |
} else if (state->or_block != 0) { |
| 1757 |
bprintf(bp, " }"); |
| 1758 |
state->or_block = 0; |
| 1759 |
} |
| 1760 |
mark_printed(state, cmd); |
| 1761 |
return (cmd); |
| 1762 |
} |
| 1763 |
return (NULL); |
| 1764 |
} |
| 1765 |
|
| 1766 |
static void |
| 1767 |
print_fwd(struct buf_pr *bp, ipfw_insn *cmd) |
| 1768 |
{ |
| 1769 |
char buf[INET6_ADDRSTRLEN + IF_NAMESIZE + 2]; |
| 1770 |
ipfw_insn_sa6 *sa6; |
| 1771 |
ipfw_insn_sa *sa; |
| 1772 |
uint16_t port; |
| 1773 |
|
| 1774 |
if (cmd->opcode == O_FORWARD_IP) { |
| 1775 |
sa = insntod(cmd, sa); |
| 1776 |
port = sa->sa.sin_port; |
| 1777 |
if (sa->sa.sin_addr.s_addr == INADDR_ANY) |
| 1778 |
bprintf(bp, "fwd tablearg"); |
| 1779 |
else |
| 1780 |
bprintf(bp, "fwd %s", inet_ntoa(sa->sa.sin_addr)); |
| 1781 |
} else { |
| 1782 |
sa6 = insntod(cmd, sa6); |
| 1783 |
port = sa6->sa.sin6_port; |
| 1784 |
bprintf(bp, "fwd "); |
| 1785 |
if (getnameinfo((const struct sockaddr *)&sa6->sa, |
| 1786 |
sizeof(struct sockaddr_in6), buf, sizeof(buf), NULL, 0, |
| 1787 |
NI_NUMERICHOST) == 0) |
| 1788 |
bprintf(bp, "%s", buf); |
| 1789 |
} |
| 1790 |
if (port != 0) |
| 1791 |
bprintf(bp, ",%u", port); |
| 1792 |
} |
| 1793 |
|
| 1794 |
static ipfw_insn * |
| 1795 |
print_action(struct buf_pr *bp, struct format_opts *fo, |
| 1796 |
struct show_state *state, uint8_t opcode) |
| 1797 |
{ |
| 1798 |
ipfw_insn *cmd; |
| 1799 |
char const *s; |
| 1800 |
int l; |
| 1801 |
|
| 1802 |
for (l = state->rule->cmd_len - state->rule->act_ofs, |
| 1803 |
cmd = ACTION_PTR(state->rule); l > 0; |
| 1804 |
l -= F_LEN(cmd), cmd += F_LEN(cmd)) { |
| 1805 |
if (cmd->opcode != opcode) |
| 1806 |
continue; |
| 1807 |
if (is_printed_opcode(state, cmd)) |
| 1808 |
continue; |
| 1809 |
switch (opcode) { |
| 1810 |
case O_CHECK_STATE: |
| 1811 |
bprintf(bp, "check-state"); |
| 1812 |
if (cmd->arg1 != 0) |
| 1813 |
s = object_search_ctlv(fo->tstate, cmd->arg1, |
| 1814 |
IPFW_TLV_STATE_NAME); |
| 1815 |
else |
| 1816 |
s = NULL; |
| 1817 |
bprintf(bp, " :%s", s ? s: "any"); |
| 1818 |
break; |
| 1819 |
case O_ACCEPT: |
| 1820 |
bprintf(bp, "allow"); |
| 1821 |
break; |
| 1822 |
case O_COUNT: |
| 1823 |
bprintf(bp, "count"); |
| 1824 |
break; |
| 1825 |
case O_DENY: |
| 1826 |
bprintf(bp, "deny"); |
| 1827 |
break; |
| 1828 |
case O_REJECT: |
| 1829 |
if (cmd->arg1 == ICMP_REJECT_RST) |
| 1830 |
bprintf(bp, "reset"); |
| 1831 |
else if (cmd->arg1 == ICMP_REJECT_ABORT) |
| 1832 |
bprintf(bp, "abort"); |
| 1833 |
else if (cmd->arg1 == ICMP_UNREACH_HOST) |
| 1834 |
bprintf(bp, "reject"); |
| 1835 |
else |
| 1836 |
print_reject_code(bp, cmd->arg1); |
| 1837 |
break; |
| 1838 |
case O_UNREACH6: |
| 1839 |
if (cmd->arg1 == ICMP6_UNREACH_RST) |
| 1840 |
bprintf(bp, "reset6"); |
| 1841 |
else if (cmd->arg1 == ICMP6_UNREACH_ABORT) |
| 1842 |
bprintf(bp, "abort6"); |
| 1843 |
else |
| 1844 |
print_unreach6_code(bp, cmd->arg1); |
| 1845 |
break; |
| 1846 |
case O_SKIPTO: |
| 1847 |
bprint_uint_arg(bp, "skipto ", cmd->arg1); |
| 1848 |
break; |
| 1849 |
case O_PIPE: |
| 1850 |
bprint_uint_arg(bp, "pipe ", cmd->arg1); |
| 1851 |
break; |
| 1852 |
case O_QUEUE: |
| 1853 |
bprint_uint_arg(bp, "queue ", cmd->arg1); |
| 1854 |
break; |
| 1855 |
case O_DIVERT: |
| 1856 |
bprint_uint_arg(bp, "divert ", cmd->arg1); |
| 1857 |
break; |
| 1858 |
case O_TEE: |
| 1859 |
bprint_uint_arg(bp, "tee ", cmd->arg1); |
| 1860 |
break; |
| 1861 |
case O_NETGRAPH: |
| 1862 |
bprint_uint_arg(bp, "netgraph ", cmd->arg1); |
| 1863 |
break; |
| 1864 |
case O_NGTEE: |
| 1865 |
bprint_uint_arg(bp, "ngtee ", cmd->arg1); |
| 1866 |
break; |
| 1867 |
case O_FORWARD_IP: |
| 1868 |
case O_FORWARD_IP6: |
| 1869 |
print_fwd(bp, cmd); |
| 1870 |
break; |
| 1871 |
case O_LOG: |
| 1872 |
if (insntod(cmd, log)->max_log > 0) |
| 1873 |
bprintf(bp, " log logamount %d", |
| 1874 |
insntod(cmd, log)->max_log); |
| 1875 |
else |
| 1876 |
bprintf(bp, " log"); |
| 1877 |
break; |
| 1878 |
case O_ALTQ: |
| 1879 |
#ifndef NO_ALTQ |
| 1880 |
print_altq_cmd(bp, insntod(cmd, altq)); |
| 1881 |
#endif |
| 1882 |
break; |
| 1883 |
case O_TAG: |
| 1884 |
bprint_uint_arg(bp, cmd->len & F_NOT ? " untag ": |
| 1885 |
" tag ", cmd->arg1); |
| 1886 |
break; |
| 1887 |
case O_NAT: |
| 1888 |
if (cmd->arg1 != IP_FW_NAT44_GLOBAL) |
| 1889 |
bprint_uint_arg(bp, "nat ", cmd->arg1); |
| 1890 |
else |
| 1891 |
bprintf(bp, "nat global"); |
| 1892 |
break; |
| 1893 |
case O_SETFIB: |
| 1894 |
if (cmd->arg1 == IP_FW_TARG) |
| 1895 |
bprint_uint_arg(bp, "setfib ", cmd->arg1); |
| 1896 |
else |
| 1897 |
bprintf(bp, "setfib %u", cmd->arg1 & 0x7FFF); |
| 1898 |
break; |
| 1899 |
case O_EXTERNAL_ACTION: |
| 1900 |
/* |
| 1901 |
* The external action can consists of two following |
| 1902 |
* each other opcodes - O_EXTERNAL_ACTION and |
| 1903 |
* O_EXTERNAL_INSTANCE. The first contains the ID of |
| 1904 |
* name of external action. The second contains the ID |
| 1905 |
* of name of external action instance. |
| 1906 |
* NOTE: in case when external action has no named |
| 1907 |
* instances support, the second opcode isn't needed. |
| 1908 |
*/ |
| 1909 |
state->eaction = cmd; |
| 1910 |
s = object_search_ctlv(fo->tstate, cmd->arg1, |
| 1911 |
IPFW_TLV_EACTION); |
| 1912 |
if (match_token(rule_eactions, s) != -1) |
| 1913 |
bprintf(bp, "%s", s); |
| 1914 |
else |
| 1915 |
bprintf(bp, "eaction %s", s); |
| 1916 |
break; |
| 1917 |
case O_EXTERNAL_INSTANCE: |
| 1918 |
if (state->eaction == NULL) |
| 1919 |
break; |
| 1920 |
/* |
| 1921 |
* XXX: we need to teach ipfw(9) to rewrite opcodes |
| 1922 |
* in the user buffer on rule addition. When we add |
| 1923 |
* the rule, we specify zero TLV type for |
| 1924 |
* O_EXTERNAL_INSTANCE object. To show correct |
| 1925 |
* rule after `ipfw add` we need to search instance |
| 1926 |
* name with zero type. But when we do `ipfw show` |
| 1927 |
* we calculate TLV type using IPFW_TLV_EACTION_NAME() |
| 1928 |
* macro. |
| 1929 |
*/ |
| 1930 |
s = object_search_ctlv(fo->tstate, cmd->arg1, 0); |
| 1931 |
if (s == NULL) |
| 1932 |
s = object_search_ctlv(fo->tstate, |
| 1933 |
cmd->arg1, IPFW_TLV_EACTION_NAME( |
| 1934 |
state->eaction->arg1)); |
| 1935 |
bprintf(bp, " %s", s); |
| 1936 |
break; |
| 1937 |
case O_EXTERNAL_DATA: |
| 1938 |
if (state->eaction == NULL) |
| 1939 |
break; |
| 1940 |
/* |
| 1941 |
* Currently we support data formatting only for |
| 1942 |
* external data with datalen u16. For unknown data |
| 1943 |
* print its size in bytes. |
| 1944 |
*/ |
| 1945 |
if (cmd->len == F_INSN_SIZE(ipfw_insn)) |
| 1946 |
bprintf(bp, " %u", cmd->arg1); |
| 1947 |
else |
| 1948 |
bprintf(bp, " %ubytes", |
| 1949 |
cmd->len * sizeof(uint32_t)); |
| 1950 |
break; |
| 1951 |
case O_SETDSCP: |
| 1952 |
if (cmd->arg1 == IP_FW_TARG) { |
| 1953 |
bprintf(bp, "setdscp tablearg"); |
| 1954 |
break; |
| 1955 |
} |
| 1956 |
s = match_value(f_ipdscp, cmd->arg1 & 0x3F); |
| 1957 |
if (s != NULL) |
| 1958 |
bprintf(bp, "setdscp %s", s); |
| 1959 |
else |
| 1960 |
bprintf(bp, "setdscp %s", cmd->arg1 & 0x3F); |
| 1961 |
break; |
| 1962 |
case O_REASS: |
| 1963 |
bprintf(bp, "reass"); |
| 1964 |
break; |
| 1965 |
case O_CALLRETURN: |
| 1966 |
if (cmd->len & F_NOT) |
| 1967 |
bprintf(bp, "return"); |
| 1968 |
else |
| 1969 |
bprint_uint_arg(bp, "call ", cmd->arg1); |
| 1970 |
break; |
| 1971 |
default: |
| 1972 |
bprintf(bp, "** unrecognized action %d len %d ", |
| 1973 |
cmd->opcode, cmd->len); |
| 1974 |
} |
| 1975 |
mark_printed(state, cmd); |
| 1976 |
return (cmd); |
| 1977 |
} |
| 1978 |
return (NULL); |
| 1979 |
} |
| 1980 |
|
| 1981 |
static void |
| 1982 |
print_proto(struct buf_pr *bp, struct format_opts *fo, |
| 1983 |
struct show_state *state) |
| 1984 |
{ |
| 1985 |
ipfw_insn *cmd; |
| 1986 |
int l, proto, ip4, ip6, tmp; |
| 1987 |
|
| 1988 |
/* Count all O_PROTO, O_IP4, O_IP6 instructions. */ |
| 1989 |
proto = tmp = ip4 = ip6 = 0; |
| 1990 |
for (l = state->rule->act_ofs, cmd = state->rule->cmd; |
| 1991 |
l > 0; l -= F_LEN(cmd), cmd += F_LEN(cmd)) { |
| 1992 |
switch (cmd->opcode) { |
| 1993 |
case O_PROTO: |
| 1994 |
proto++; |
| 1995 |
break; |
| 1996 |
case O_IP4: |
| 1997 |
ip4 = 1; |
| 1998 |
if (cmd->len & F_OR) |
| 1999 |
ip4++; |
| 2000 |
break; |
| 2001 |
case O_IP6: |
| 2002 |
ip6 = 1; |
| 2003 |
if (cmd->len & F_OR) |
| 2004 |
ip6++; |
| 2005 |
break; |
| 2006 |
default: |
| 2007 |
continue; |
| 2008 |
} |
| 2009 |
} |
| 2010 |
if (proto == 0 && ip4 == 0 && ip6 == 0) { |
| 2011 |
state->proto = IPPROTO_IP; |
| 2012 |
state->flags |= HAVE_PROTO; |
| 2013 |
bprintf(bp, " ip"); |
| 2014 |
return; |
| 2015 |
} |
| 2016 |
/* To handle the case { ip4 or ip6 }, print opcode with F_OR first */ |
| 2017 |
if (ip4 || ip6) |
| 2018 |
cmd = print_opcode(bp, fo, state, ip4 > ip6 ? O_IP4: O_IP6); |
| 2019 |
if (cmd != NULL && (cmd->len & F_OR)) |
| 2020 |
cmd = print_opcode(bp, fo, state, ip4 > ip6 ? O_IP6: O_IP4); |
| 2021 |
if (cmd == NULL || (cmd->len & F_OR)) |
| 2022 |
for (l = proto; l > 0; l--) { |
| 2023 |
cmd = print_opcode(bp, fo, state, O_PROTO); |
| 2024 |
if (cmd != NULL && (cmd->len & F_OR) == 0) |
| 2025 |
break; |
| 2026 |
tmp = cmd->arg1; |
| 2027 |
} |
| 2028 |
/* Initialize proto, it is used by print_newports() */ |
| 2029 |
if (tmp != 0) |
| 2030 |
state->proto = tmp; |
| 2031 |
else if (ip6 != 0) |
| 2032 |
state->proto = IPPROTO_IPV6; |
| 2033 |
else |
| 2034 |
state->proto = IPPROTO_IP; |
| 2035 |
state->flags |= HAVE_PROTO; |
| 2036 |
} |
| 2037 |
|
| 2038 |
static int |
| 2039 |
match_opcode(int opcode, const int opcodes[], size_t nops) |
| 2040 |
{ |
| 2041 |
int i; |
| 2042 |
|
| 2043 |
for (i = 0; i < nops; i++) |
| 2044 |
if (opcode == opcodes[i]) |
| 2045 |
return (1); |
| 2046 |
return (0); |
| 2047 |
} |
| 2048 |
|
| 2049 |
static void |
| 2050 |
print_address(struct buf_pr *bp, struct format_opts *fo, |
| 2051 |
struct show_state *state, const int opcodes[], size_t nops, int portop, |
| 2052 |
int flag) |
| 2053 |
{ |
| 2054 |
ipfw_insn *cmd; |
| 2055 |
int count, l, portcnt; |
| 2056 |
|
| 2057 |
count = portcnt = 0; |
| 2058 |
for (l = state->rule->act_ofs, cmd = state->rule->cmd; |
| 2059 |
l > 0; l -= F_LEN(cmd), cmd += F_LEN(cmd)) { |
| 2060 |
if (match_opcode(cmd->opcode, opcodes, nops)) |
| 2061 |
count++; |
| 2062 |
else if (cmd->opcode == portop) |
| 2063 |
portcnt++; |
| 2064 |
} |
| 2065 |
if (count == 0) |
| 2066 |
bprintf(bp, " any"); |
| 2067 |
for (l = state->rule->act_ofs, cmd = state->rule->cmd; |
| 2068 |
l > 0 && count > 0; l -= F_LEN(cmd), cmd += F_LEN(cmd)) { |
| 2069 |
if (!match_opcode(cmd->opcode, opcodes, nops)) |
| 2070 |
continue; |
| 2071 |
cmd = print_opcode(bp, fo, state, cmd->opcode); |
| 2072 |
if (cmd != NULL && (cmd->len & F_OR) == 0) |
| 2073 |
break; |
| 2074 |
count--; |
| 2075 |
} |
| 2076 |
/* Print ports */ |
| 2077 |
state->flags |= flag; |
| 2078 |
for (l = state->rule->act_ofs, cmd = state->rule->cmd; |
| 2079 |
l > 0 && portcnt > 0; l -= F_LEN(cmd), cmd += F_LEN(cmd)) { |
| 2080 |
if (cmd->opcode != portop) |
| 2081 |
continue; |
| 2082 |
cmd = print_opcode(bp, fo, state, cmd->opcode); |
| 2083 |
if (cmd != NULL && (cmd->len & F_OR) == 0) |
| 2084 |
break; |
| 2085 |
portcnt--; |
| 2086 |
} |
| 2087 |
} |
| 2088 |
|
| 2089 |
static const int action_opcodes[] = { |
| 2090 |
O_CHECK_STATE, O_ACCEPT, O_COUNT, O_DENY, O_REJECT, O_UNREACH6, |
| 2091 |
O_SKIPTO, O_PIPE, O_QUEUE, O_DIVERT, O_TEE, O_NETGRAPH, O_NGTEE, |
| 2092 |
O_FORWARD_IP, O_FORWARD_IP6, O_NAT, O_SETFIB, O_SETDSCP, O_REASS, |
| 2093 |
O_CALLRETURN, O_EXTERNAL_ACTION, O_EXTERNAL_INSTANCE, O_EXTERNAL_DATA |
| 2094 |
}; |
| 2095 |
|
| 2096 |
static const int modifier_opcodes[] = { |
| 2097 |
O_LOG, O_ALTQ, O_TAG |
| 2098 |
}; |
| 2099 |
|
| 2100 |
static const int src_opcodes[] = { |
| 2101 |
O_IP_SRC, O_IP_SRC_LOOKUP, O_IP_SRC_MASK, O_IP_SRC_ME, |
| 2102 |
O_IP_SRC_SET, O_IP6_SRC, O_IP6_SRC_MASK, O_IP6_SRC_ME |
| 2103 |
}; |
| 2104 |
|
| 2105 |
static const int dst_opcodes[] = { |
| 2106 |
O_IP_DST, O_IP_DST_LOOKUP, O_IP_DST_MASK, O_IP_DST_ME, |
| 2107 |
O_IP_DST_SET, O_IP6_DST, O_IP6_DST_MASK, O_IP6_DST_ME |
| 2108 |
}; |
| 2109 |
|
| 2110 |
static void |
| 2111 |
show_static_rule2(struct cmdline_opts *co, struct format_opts *fo, |
| 2112 |
struct buf_pr *bp, struct ip_fw_rule *rule, struct ip_fw_bcounter *cntr) |
| 2113 |
{ |
| 2114 |
struct show_state state; |
| 2115 |
ipfw_insn *cmd; |
| 2116 |
static int twidth = 0; |
| 2117 |
int i; |
| 2118 |
|
| 2119 |
/* Print # DISABLED or skip the rule */ |
| 2120 |
if ((fo->set_mask & (1 << rule->set)) == 0) { |
| 2121 |
/* disabled mask */ |
| 2122 |
if (!co->show_sets) |
| 2123 |
return; |
| 2124 |
else |
| 2125 |
bprintf(bp, "# DISABLED "); |
| 2126 |
} |
| 2127 |
bprintf(bp, "%05u ", rule->rulenum); |
| 2128 |
|
| 2129 |
/* Print counters if enabled */ |
| 2130 |
if (fo->pcwidth > 0 || fo->bcwidth > 0) { |
| 2131 |
pr_u64(bp, &cntr->pcnt, fo->pcwidth); |
| 2132 |
pr_u64(bp, &cntr->bcnt, fo->bcwidth); |
| 2133 |
} |
| 2134 |
|
| 2135 |
/* Print timestamp */ |
| 2136 |
if (co->do_time == TIMESTAMP_NUMERIC) |
| 2137 |
bprintf(bp, "%10u ", cntr->timestamp); |
| 2138 |
else if (co->do_time == TIMESTAMP_STRING) { |
| 2139 |
char timestr[30]; |
| 2140 |
time_t t = (time_t)0; |
| 2141 |
|
| 2142 |
if (twidth == 0) { |
| 2143 |
strcpy(timestr, ctime(&t)); |
| 2144 |
*strchr(timestr, '\n') = '\0'; |
| 2145 |
twidth = strlen(timestr); |
| 2146 |
} |
| 2147 |
if (cntr->timestamp > 0) { |
| 2148 |
t = _long_to_time(cntr->timestamp); |
| 2149 |
|
| 2150 |
strcpy(timestr, ctime(&t)); |
| 2151 |
*strchr(timestr, '\n') = '\0'; |
| 2152 |
bprintf(bp, "%s ", timestr); |
| 2153 |
} else { |
| 2154 |
bprintf(bp, "%*s", twidth, " "); |
| 2155 |
} |
| 2156 |
} |
| 2157 |
|
| 2158 |
/* Print set number */ |
| 2159 |
if (co->show_sets) |
| 2160 |
bprintf(bp, "set %d ", rule->set); |
| 2161 |
|
| 2162 |
init_state(&state, rule); |
| 2163 |
/* Print the optional "match probability" */ |
| 2164 |
cmd = print_opcode(bp, fo, &state, O_PROB); |
| 2165 |
/* Print rule action */ |
| 2166 |
for (i = 0; i < nitems(action_opcodes); i++) { |
| 2167 |
cmd = print_action(bp, fo, &state, action_opcodes[i]); |
| 2168 |
if (cmd == NULL) |
| 2169 |
continue; |
| 2170 |
/* Handle special cases */ |
| 2171 |
switch (cmd->opcode) { |
| 2172 |
case O_CHECK_STATE: |
| 2173 |
goto end; |
| 2174 |
case O_EXTERNAL_ACTION: |
| 2175 |
case O_EXTERNAL_INSTANCE: |
| 2176 |
/* External action can have several instructions */ |
| 2177 |
continue; |
| 2178 |
} |
| 2179 |
break; |
| 2180 |
} |
| 2181 |
/* Print rule modifiers */ |
| 2182 |
for (i = 0; i < nitems(modifier_opcodes); i++) |
| 2183 |
print_action(bp, fo, &state, modifier_opcodes[i]); |
| 2184 |
/* |
| 2185 |
* Print rule body |
| 2186 |
*/ |
| 2187 |
if (co->comment_only != 0) |
| 2188 |
goto end; |
| 2189 |
print_proto(bp, fo, &state); |
| 2190 |
if (rule->flags & IPFW_RULE_NOOPT) { /* empty rules before options */ |
| 2191 |
if (co->do_compact == 0) |
| 2192 |
bprintf(bp, " from any to any"); |
| 2193 |
} else |
| 2194 |
bprintf(bp, " from"); |
| 2195 |
|
| 2196 |
/* Print source */ |
| 2197 |
print_address(bp, fo, &state, src_opcodes, nitems(src_opcodes), |
| 2198 |
O_IP_SRCPORT, HAVE_SRCIP); |
| 2199 |
|
| 2200 |
/* Print destination */ |
| 2201 |
bprintf(bp, " to"); |
| 2202 |
print_address(bp, fo, &state, dst_opcodes, nitems(dst_opcodes), |
| 2203 |
O_IP_DSTPORT, HAVE_DSTIP); |
| 2204 |
|
| 2205 |
/* Print the rest of options */ |
| 2206 |
while (print_opcode(bp, fo, &state, 0)) |
| 2207 |
; |
| 2208 |
end: |
| 2209 |
/* Print comment at the end */ |
| 2210 |
cmd = print_opcode(bp, fo, &state, O_NOP); |
| 2211 |
if (co->comment_only != 0 && cmd == NULL) |
| 2212 |
bprintf(bp, " // ..."); |
| 2213 |
bprintf(bp, "\n"); |
| 2214 |
} |
| 2215 |
|
| 2216 |
static void |
| 1409 |
show_static_rule(struct cmdline_opts *co, struct format_opts *fo, |
2217 |
show_static_rule(struct cmdline_opts *co, struct format_opts *fo, |
| 1410 |
struct buf_pr *bp, struct ip_fw_rule *rule, struct ip_fw_bcounter *cntr) |
2218 |
struct buf_pr *bp, struct ip_fw_rule *rule, struct ip_fw_bcounter *cntr) |
| 1411 |
{ |
2219 |
{ |
|
Lines 1881-1893
show_static_rule(struct cmdline_opts *co, struct f
Link Here
|
| 1881 |
if (cmd->len & F_NOT && cmd->opcode != O_IN) |
2689 |
if (cmd->len & F_NOT && cmd->opcode != O_IN) |
| 1882 |
bprintf(bp, " not"); |
2690 |
bprintf(bp, " not"); |
| 1883 |
switch(cmd->opcode) { |
2691 |
switch(cmd->opcode) { |
| 1884 |
case O_MACADDR2: { |
2692 |
case O_MACADDR2: |
| 1885 |
ipfw_insn_mac *m = (ipfw_insn_mac *)cmd; |
2693 |
print_mac(bp, (ipfw_insn_mac *)cmd); |
| 1886 |
|
|
|
| 1887 |
bprintf(bp, " MAC"); |
| 1888 |
print_mac(bp, m->addr, m->mask); |
| 1889 |
print_mac(bp, m->addr + 6, m->mask + 6); |
| 1890 |
} |
| 1891 |
break; |
2694 |
break; |
| 1892 |
|
2695 |
|
| 1893 |
case O_MAC_TYPE: |
2696 |
case O_MAC_TYPE: |
|
Lines 2537-2543
list_static_range(struct cmdline_opts *co, struct
Link Here
|
| 2537 |
if (co->use_set && r->set != co->use_set - 1) |
3340 |
if (co->use_set && r->set != co->use_set - 1) |
| 2538 |
continue; |
3341 |
continue; |
| 2539 |
if (r->rulenum >= fo->first && r->rulenum <= fo->last) { |
3342 |
if (r->rulenum >= fo->first && r->rulenum <= fo->last) { |
| 2540 |
show_static_rule(co, fo, bp, r, cntr); |
3343 |
show_static_rule2(co, fo, bp, r, cntr); |
| 2541 |
printf("%s", bp->buf); |
3344 |
printf("%s", bp->buf); |
| 2542 |
c += rtlv->length; |
3345 |
c += rtlv->length; |
| 2543 |
bp_flush(bp); |
3346 |
bp_flush(bp); |
|
Lines 5152-5158
ipfw_add(char *av[])
Link Here
|
| 5152 |
sfo.tstate = tstate; |
5955 |
sfo.tstate = tstate; |
| 5153 |
sfo.set_mask = (uint32_t)(-1); |
5956 |
sfo.set_mask = (uint32_t)(-1); |
| 5154 |
bp_alloc(&bp, 4096); |
5957 |
bp_alloc(&bp, 4096); |
| 5155 |
show_static_rule(&co, &sfo, &bp, rule, NULL); |
5958 |
show_static_rule2(&co, &sfo, &bp, rule, NULL); |
| 5156 |
printf("%s", bp.buf); |
5959 |
printf("%s", bp.buf); |
| 5157 |
bp_free(&bp); |
5960 |
bp_free(&bp); |
| 5158 |
} |
5961 |
} |