View | Details | Raw Unified | Return to bug 222705 | Differences between
and this patch

Collapse All | Expand All

(-)sbin/ipfw/ipfw2.c (-10 / +807 lines)
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 (opcode != O_IN && (cmd->len & F_NOT) != 0)
1500
			bprintf(bp, " not");
1501
		switch (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) ?  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, 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 (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
					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;
1987
1988
	/* Count all O_PROTO, O_IP4, O_IP6 instructions. */
1989
	proto = 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
			break;
1999
		case O_IP6:
2000
			ip6 = 1;
2001
			break;
2002
		default:
2003
			continue;
2004
		}
2005
	}
2006
	if (proto == 0 && ip4 == 0 && ip6 == 0) {
2007
		state->proto = IPPROTO_IP;
2008
		state->flags |= HAVE_PROTO;
2009
		bprintf(bp, " ip");
2010
		return;
2011
	}
2012
	if (ip4 != 0)
2013
		print_opcode(bp, fo, state, O_IP4);
2014
	if (ip6 != 0)
2015
		print_opcode(bp, fo, state, O_IP6);
2016
	for (l = proto; l > 0; l--) {
2017
		cmd = print_opcode(bp, fo, state, O_PROTO);
2018
		if (cmd != NULL && (cmd->len & F_OR) == 0)
2019
			break;
2020
		proto = cmd->arg1;
2021
	}
2022
	/* Initialize proto, it is used by print_newports() */
2023
	if (proto != 0)
2024
		state->proto = proto;
2025
	else if (ip6 != 0)
2026
		state->proto = IPPROTO_IPV6;
2027
	else
2028
		state->proto = IPPROTO_IP;
2029
	state->flags |= HAVE_PROTO;
2030
}
2031
2032
static int
2033
match_opcode(int opcode, const int opcodes[], size_t nops)
2034
{
2035
	int i;
2036
2037
	for (i = 0; i < nops; i++)
2038
		if (opcode == opcodes[i])
2039
			return (1);
2040
	return (0);
2041
}
2042
2043
static void
2044
print_address(struct buf_pr *bp, struct format_opts *fo,
2045
    struct show_state *state, const int opcodes[], size_t nops, int portop,
2046
    int flag)
2047
{
2048
	ipfw_insn *cmd;
2049
	int count, l, portcnt;
2050
2051
	count = portcnt = 0;
2052
	for (l = state->rule->act_ofs, cmd = state->rule->cmd;
2053
	    l > 0; l -= F_LEN(cmd), cmd += F_LEN(cmd)) {
2054
		if (match_opcode(cmd->opcode, opcodes, nops))
2055
			count++;
2056
		else if (cmd->opcode == portop)
2057
			portcnt++;
2058
	}
2059
	if (count == 0)
2060
		bprintf(bp, " any");
2061
	for (l = state->rule->act_ofs, cmd = state->rule->cmd;
2062
	    l > 0 && count > 0; l -= F_LEN(cmd), cmd += F_LEN(cmd)) {
2063
		if (!match_opcode(cmd->opcode, opcodes, nops))
2064
			continue;
2065
		cmd = print_opcode(bp, fo, state, cmd->opcode);
2066
		if (cmd != NULL && (cmd->len & F_OR) == 0)
2067
			break;
2068
		count--;
2069
	}
2070
	/* Print ports */
2071
	state->flags |= flag;
2072
	for (l = state->rule->act_ofs, cmd = state->rule->cmd;
2073
	    l > 0 && portcnt > 0; l -= F_LEN(cmd), cmd += F_LEN(cmd)) {
2074
		if (cmd->opcode != portop)
2075
			continue;
2076
		cmd = print_opcode(bp, fo, state, cmd->opcode);
2077
		if (cmd != NULL && (cmd->len & F_OR) == 0)
2078
			break;
2079
		portcnt--;
2080
	}
2081
}
2082
2083
static const int action_opcodes[] = {
2084
	O_CHECK_STATE, O_ACCEPT, O_COUNT, O_DENY, O_REJECT, O_UNREACH6,
2085
	O_SKIPTO, O_PIPE, O_QUEUE, O_DIVERT, O_TEE, O_NETGRAPH, O_NGTEE,
2086
	O_FORWARD_IP, O_FORWARD_IP6, O_NAT, O_SETFIB, O_SETDSCP, O_REASS,
2087
	O_CALLRETURN, O_EXTERNAL_ACTION, O_EXTERNAL_INSTANCE, O_EXTERNAL_DATA
2088
};
2089
2090
static const int modifier_opcodes[] = {
2091
	O_LOG, O_ALTQ, O_TAG
2092
};
2093
2094
static const int src_opcodes[] = {
2095
	O_IP_SRC, O_IP_SRC_LOOKUP, O_IP_SRC_MASK, O_IP_SRC_ME,
2096
	O_IP_SRC_SET, O_IP6_SRC, O_IP6_SRC_MASK, O_IP6_SRC_ME
2097
};
2098
2099
static const int dst_opcodes[] = {
2100
	O_IP_DST, O_IP_DST_LOOKUP, O_IP_DST_MASK, O_IP_DST_ME,
2101
	O_IP_DST_SET, O_IP6_DST, O_IP6_DST_MASK, O_IP6_DST_ME
2102
};
2103
2104
static void
2105
show_static_rule2(struct cmdline_opts *co, struct format_opts *fo,
2106
    struct buf_pr *bp, struct ip_fw_rule *rule, struct ip_fw_bcounter *cntr)
2107
{
2108
	struct show_state state;
2109
	ipfw_insn *cmd;
2110
	static int twidth = 0;
2111
	int i;
2112
2113
	/* Print # DISABLED or skip the rule */
2114
	if ((fo->set_mask & (1 << rule->set)) == 0) {
2115
		/* disabled mask */
2116
		if (!co->show_sets)
2117
			return;
2118
		else
2119
			bprintf(bp, "# DISABLED ");
2120
	}
2121
	bprintf(bp, "%05u ", rule->rulenum);
2122
2123
	/* Print counters if enabled */
2124
	if (fo->pcwidth > 0 || fo->bcwidth > 0) {
2125
		pr_u64(bp, &cntr->pcnt, fo->pcwidth);
2126
		pr_u64(bp, &cntr->bcnt, fo->bcwidth);
2127
	}
2128
2129
	/* Print timestamp */
2130
	if (co->do_time == TIMESTAMP_NUMERIC)
2131
		bprintf(bp, "%10u ", cntr->timestamp);
2132
	else if (co->do_time == TIMESTAMP_STRING) {
2133
		char timestr[30];
2134
		time_t t = (time_t)0;
2135
2136
		if (twidth == 0) {
2137
			strcpy(timestr, ctime(&t));
2138
			*strchr(timestr, '\n') = '\0';
2139
			twidth = strlen(timestr);
2140
		}
2141
		if (cntr->timestamp > 0) {
2142
			t = _long_to_time(cntr->timestamp);
2143
2144
			strcpy(timestr, ctime(&t));
2145
			*strchr(timestr, '\n') = '\0';
2146
			bprintf(bp, "%s ", timestr);
2147
		} else {
2148
			bprintf(bp, "%*s", twidth, " ");
2149
		}
2150
	}
2151
2152
	/* Print set number */
2153
	if (co->show_sets)
2154
		bprintf(bp, "set %d ", rule->set);
2155
2156
	init_state(&state, rule);
2157
	/* Print the optional "match probability" */
2158
	cmd = print_opcode(bp, fo, &state, O_PROB);
2159
	/* Print rule action */
2160
	for (i = 0; i < nitems(action_opcodes); i++) {
2161
		cmd = print_action(bp, fo, &state, action_opcodes[i]);
2162
		if (cmd == NULL)
2163
			continue;
2164
		/* Handle special cases */
2165
		switch (cmd->opcode) {
2166
		case O_CHECK_STATE:
2167
			goto end;
2168
		case O_EXTERNAL_ACTION:
2169
		case O_EXTERNAL_INSTANCE:
2170
			/* External action can have several instructions */
2171
			continue;
2172
		}
2173
		break;
2174
	}
2175
	/* Print rule modifiers */
2176
	for (i = 0; i < nitems(modifier_opcodes); i++)
2177
		print_action(bp, fo, &state, modifier_opcodes[i]);
2178
	/*
2179
	 * Print rule body
2180
	 */
2181
	if (co->comment_only != 0)
2182
		goto end;
2183
	print_proto(bp, fo, &state);
2184
	if (rule->flags & IPFW_RULE_NOOPT) { /* empty rules before options */
2185
		if (co->do_compact == 0)
2186
			bprintf(bp, " from any to any");
2187
	} else
2188
		bprintf(bp, " from");
2189
2190
	/* Print source */
2191
	print_address(bp, fo, &state, src_opcodes, nitems(src_opcodes),
2192
	    O_IP_SRCPORT, HAVE_SRCIP);
2193
2194
	/* Print destination */
2195
	bprintf(bp, " to");
2196
	print_address(bp, fo, &state, dst_opcodes, nitems(dst_opcodes),
2197
	    O_IP_DSTPORT, HAVE_DSTIP);
2198
2199
	/* Print the rest of options */
2200
	while (print_opcode(bp, fo, &state, 0))
2201
		;
2202
end:
2203
	/* Print comment at the end */
2204
	cmd = print_opcode(bp, fo, &state, O_NOP);
2205
	if (co->comment_only != 0 && cmd == NULL)
2206
		bprintf(bp, " // ...");
2207
	bprintf(bp, "\n");
2208
}
2209
2210
static void
1409
show_static_rule(struct cmdline_opts *co, struct format_opts *fo,
2211
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)
2212
    struct buf_pr *bp, struct ip_fw_rule *rule, struct ip_fw_bcounter *cntr)
1411
{
2213
{
Lines 1881-1893 show_static_rule(struct cmdline_opts *co, struct f Link Here
1881
			if (cmd->len & F_NOT && cmd->opcode != O_IN)
2683
			if (cmd->len & F_NOT && cmd->opcode != O_IN)
1882
				bprintf(bp, " not");
2684
				bprintf(bp, " not");
1883
			switch(cmd->opcode) {
2685
			switch(cmd->opcode) {
1884
			case O_MACADDR2: {
2686
			case O_MACADDR2:
1885
				ipfw_insn_mac *m = (ipfw_insn_mac *)cmd;
2687
				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;
2688
				break;
1892
2689
1893
			case O_MAC_TYPE:
2690
			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)
3334
		if (co->use_set && r->set != co->use_set - 1)
2538
			continue;
3335
			continue;
2539
		if (r->rulenum >= fo->first && r->rulenum <= fo->last) {
3336
		if (r->rulenum >= fo->first && r->rulenum <= fo->last) {
2540
			show_static_rule(co, fo, bp, r, cntr);
3337
			show_static_rule2(co, fo, bp, r, cntr);
2541
			printf("%s", bp->buf);
3338
			printf("%s", bp->buf);
2542
			c += rtlv->length;
3339
			c += rtlv->length;
2543
			bp_flush(bp);
3340
			bp_flush(bp);
Lines 5152-5158 ipfw_add(char *av[]) Link Here
5152
		sfo.tstate = tstate;
5949
		sfo.tstate = tstate;
5153
		sfo.set_mask = (uint32_t)(-1);
5950
		sfo.set_mask = (uint32_t)(-1);
5154
		bp_alloc(&bp, 4096);
5951
		bp_alloc(&bp, 4096);
5155
		show_static_rule(&co, &sfo, &bp, rule, NULL);
5952
		show_static_rule2(&co, &sfo, &bp, rule, NULL);
5156
		printf("%s", bp.buf);
5953
		printf("%s", bp.buf);
5157
		bp_free(&bp);
5954
		bp_free(&bp);
5158
	}
5955
	}
(-)sbin/ipfw/ipfw2.h (+6 lines)
Lines 56-61 struct cmdline_opts { Link Here
56
56
57
};
57
};
58
58
59
enum {
60
	TIMESTAMP_NONE = 0,
61
	TIMESTAMP_STRING,
62
	TIMESTAMP_NUMERIC,
63
};
64
59
extern struct cmdline_opts co;
65
extern struct cmdline_opts co;
60
66
61
/*
67
/*
(-)sbin/ipfw/main.c (-2 / +2 lines)
Lines 324-334 ipfw_main(int oldac, char **oldav) Link Here
324
			break;
324
			break;
325
325
326
		case 't':
326
		case 't':
327
			co.do_time = 1;
327
			co.do_time = TIMESTAMP_STRING;
328
			break;
328
			break;
329
329
330
		case 'T':
330
		case 'T':
331
			co.do_time = 2;	/* numeric timestamp */
331
			co.do_time = TIMESTAMP_NUMERIC;
332
			break;
332
			break;
333
333
334
		case 'v': /* verbose */
334
		case 'v': /* verbose */

Return to bug 222705