1187983Sluigi/*
2187983Sluigi * Copyright (c) 2002-2003 Luigi Rizzo
3187983Sluigi * Copyright (c) 1996 Alex Nash, Paul Traina, Poul-Henning Kamp
4187983Sluigi * Copyright (c) 1994 Ugen J.S.Antsilevich
5187983Sluigi *
6187983Sluigi * Idea and grammar partially left from:
7187983Sluigi * Copyright (c) 1993 Daniel Boulet
8187983Sluigi *
9187983Sluigi * Redistribution and use in source forms, with and without modification,
10187983Sluigi * are permitted provided that this entire comment appears intact.
11187983Sluigi *
12187983Sluigi * Redistribution in binary form may occur without any restrictions.
13187983Sluigi * Obviously, it would be nice if you gave credit where credit is due
14187983Sluigi * but requiring it would be too onerous.
15187983Sluigi *
16187983Sluigi * This software is provided ``AS IS'' without any warranties of any kind.
17187983Sluigi *
18187983Sluigi * NEW command line interface for IP firewall facility
19187983Sluigi *
20187983Sluigi * $FreeBSD$
21187983Sluigi *
22187983Sluigi * altq interface
23187983Sluigi */
24187983Sluigi
25187983Sluigi#include <sys/types.h>
26187983Sluigi#include <sys/socket.h>
27187983Sluigi#include <sys/sockio.h>
28187983Sluigi
29187983Sluigi#include "ipfw2.h"
30187983Sluigi
31187983Sluigi#include <err.h>
32187983Sluigi#include <errno.h>
33187983Sluigi#include <stdio.h>
34187983Sluigi#include <stdlib.h>
35187983Sluigi#include <string.h>
36187983Sluigi#include <sysexits.h>
37187983Sluigi#include <unistd.h>
38187983Sluigi#include <fcntl.h>
39187983Sluigi
40187983Sluigi#include <net/if.h>		/* IFNAMSIZ */
41187983Sluigi#include <net/pfvar.h>
42204591Sluigi#include <netinet/in.h>	/* in_addr */
43187983Sluigi#include <netinet/ip_fw.h>
44187983Sluigi
45187983Sluigi/*
46187983Sluigi * Map between current altq queue id numbers and names.
47187983Sluigi */
48220802Sglebiusstatic TAILQ_HEAD(, pf_altq) altq_entries =
49187983Sluigi	TAILQ_HEAD_INITIALIZER(altq_entries);
50187983Sluigi
51187983Sluigivoid
52187983Sluigialtq_set_enabled(int enabled)
53187983Sluigi{
54187983Sluigi	int pffd;
55187983Sluigi
56187983Sluigi	pffd = open("/dev/pf", O_RDWR);
57187983Sluigi	if (pffd == -1)
58187983Sluigi		err(EX_UNAVAILABLE,
59187983Sluigi		    "altq support opening pf(4) control device");
60187983Sluigi	if (enabled) {
61187983Sluigi		if (ioctl(pffd, DIOCSTARTALTQ) != 0 && errno != EEXIST)
62187983Sluigi			err(EX_UNAVAILABLE, "enabling altq");
63187983Sluigi	} else {
64187983Sluigi		if (ioctl(pffd, DIOCSTOPALTQ) != 0 && errno != ENOENT)
65187983Sluigi			err(EX_UNAVAILABLE, "disabling altq");
66187983Sluigi	}
67187983Sluigi	close(pffd);
68187983Sluigi}
69187983Sluigi
70187983Sluigistatic void
71187983Sluigialtq_fetch(void)
72187983Sluigi{
73187983Sluigi	struct pfioc_altq pfioc;
74187983Sluigi	struct pf_altq *altq;
75187983Sluigi	int pffd;
76187983Sluigi	unsigned int mnr;
77187983Sluigi	static int altq_fetched = 0;
78187983Sluigi
79187983Sluigi	if (altq_fetched)
80187983Sluigi		return;
81187983Sluigi	altq_fetched = 1;
82187983Sluigi	pffd = open("/dev/pf", O_RDONLY);
83187983Sluigi	if (pffd == -1) {
84187983Sluigi		warn("altq support opening pf(4) control device");
85187983Sluigi		return;
86187983Sluigi	}
87187983Sluigi	bzero(&pfioc, sizeof(pfioc));
88187983Sluigi	if (ioctl(pffd, DIOCGETALTQS, &pfioc) != 0) {
89187983Sluigi		warn("altq support getting queue list");
90187983Sluigi		close(pffd);
91187983Sluigi		return;
92187983Sluigi	}
93187983Sluigi	mnr = pfioc.nr;
94187983Sluigi	for (pfioc.nr = 0; pfioc.nr < mnr; pfioc.nr++) {
95187983Sluigi		if (ioctl(pffd, DIOCGETALTQ, &pfioc) != 0) {
96187983Sluigi			if (errno == EBUSY)
97187983Sluigi				break;
98187983Sluigi			warn("altq support getting queue list");
99187983Sluigi			close(pffd);
100187983Sluigi			return;
101187983Sluigi		}
102187983Sluigi		if (pfioc.altq.qid == 0)
103187983Sluigi			continue;
104187983Sluigi		altq = safe_calloc(1, sizeof(*altq));
105187983Sluigi		*altq = pfioc.altq;
106187983Sluigi		TAILQ_INSERT_TAIL(&altq_entries, altq, entries);
107187983Sluigi	}
108187983Sluigi	close(pffd);
109187983Sluigi}
110187983Sluigi
111187983Sluigiu_int32_t
112187983Sluigialtq_name_to_qid(const char *name)
113187983Sluigi{
114187983Sluigi	struct pf_altq *altq;
115187983Sluigi
116187983Sluigi	altq_fetch();
117187983Sluigi	TAILQ_FOREACH(altq, &altq_entries, entries)
118187983Sluigi		if (strcmp(name, altq->qname) == 0)
119187983Sluigi			break;
120187983Sluigi	if (altq == NULL)
121187983Sluigi		errx(EX_DATAERR, "altq has no queue named `%s'", name);
122187983Sluigi	return altq->qid;
123187983Sluigi}
124187983Sluigi
125189394Sluigistatic const char *
126187983Sluigialtq_qid_to_name(u_int32_t qid)
127187983Sluigi{
128187983Sluigi	struct pf_altq *altq;
129187983Sluigi
130187983Sluigi	altq_fetch();
131187983Sluigi	TAILQ_FOREACH(altq, &altq_entries, entries)
132187983Sluigi		if (qid == altq->qid)
133187983Sluigi			break;
134187983Sluigi	if (altq == NULL)
135187983Sluigi		return NULL;
136187983Sluigi	return altq->qname;
137187983Sluigi}
138187983Sluigi
139187983Sluigivoid
140187983Sluigiprint_altq_cmd(ipfw_insn_altq *altqptr)
141187983Sluigi{
142220802Sglebius	if (altqptr) {
143220802Sglebius		const char *qname;
144187983Sluigi
145220802Sglebius		qname = altq_qid_to_name(altqptr->qid);
146220802Sglebius		if (qname == NULL)
147220802Sglebius			printf(" altq ?<%u>", altqptr->qid);
148220802Sglebius		else
149220802Sglebius			printf(" altq %s", qname);
150220802Sglebius	}
151187983Sluigi}
152