altq.c revision 187983
1/*
2 * Copyright (c) 2002-2003 Luigi Rizzo
3 * Copyright (c) 1996 Alex Nash, Paul Traina, Poul-Henning Kamp
4 * Copyright (c) 1994 Ugen J.S.Antsilevich
5 *
6 * Idea and grammar partially left from:
7 * Copyright (c) 1993 Daniel Boulet
8 *
9 * Redistribution and use in source forms, with and without modification,
10 * are permitted provided that this entire comment appears intact.
11 *
12 * Redistribution in binary form may occur without any restrictions.
13 * Obviously, it would be nice if you gave credit where credit is due
14 * but requiring it would be too onerous.
15 *
16 * This software is provided ``AS IS'' without any warranties of any kind.
17 *
18 * NEW command line interface for IP firewall facility
19 *
20 * $FreeBSD: head/sbin/ipfw/altq.c 187983 2009-02-01 16:00:49Z luigi $
21 *
22 * altq interface
23 */
24
25#include <sys/types.h>
26#include <sys/socket.h>
27#include <sys/sockio.h>
28
29#include "ipfw2.h"
30
31#include <err.h>
32#include <errno.h>
33#include <stdio.h>
34#include <stdlib.h>
35#include <string.h>
36#include <sysexits.h>
37#include <unistd.h>
38#include <fcntl.h>
39
40#include <net/if.h>		/* IFNAMSIZ */
41#include <net/pfvar.h>
42#include <netinet/ip_fw.h>
43
44/*
45 * Map between current altq queue id numbers and names.
46 */
47static TAILQ_HEAD(, pf_altq) altq_entries =
48	TAILQ_HEAD_INITIALIZER(altq_entries);
49
50void
51altq_set_enabled(int enabled)
52{
53	int pffd;
54
55	pffd = open("/dev/pf", O_RDWR);
56	if (pffd == -1)
57		err(EX_UNAVAILABLE,
58		    "altq support opening pf(4) control device");
59	if (enabled) {
60		if (ioctl(pffd, DIOCSTARTALTQ) != 0 && errno != EEXIST)
61			err(EX_UNAVAILABLE, "enabling altq");
62	} else {
63		if (ioctl(pffd, DIOCSTOPALTQ) != 0 && errno != ENOENT)
64			err(EX_UNAVAILABLE, "disabling altq");
65	}
66	close(pffd);
67}
68
69static void
70altq_fetch(void)
71{
72	struct pfioc_altq pfioc;
73	struct pf_altq *altq;
74	int pffd;
75	unsigned int mnr;
76	static int altq_fetched = 0;
77
78	if (altq_fetched)
79		return;
80	altq_fetched = 1;
81	pffd = open("/dev/pf", O_RDONLY);
82	if (pffd == -1) {
83		warn("altq support opening pf(4) control device");
84		return;
85	}
86	bzero(&pfioc, sizeof(pfioc));
87	if (ioctl(pffd, DIOCGETALTQS, &pfioc) != 0) {
88		warn("altq support getting queue list");
89		close(pffd);
90		return;
91	}
92	mnr = pfioc.nr;
93	for (pfioc.nr = 0; pfioc.nr < mnr; pfioc.nr++) {
94		if (ioctl(pffd, DIOCGETALTQ, &pfioc) != 0) {
95			if (errno == EBUSY)
96				break;
97			warn("altq support getting queue list");
98			close(pffd);
99			return;
100		}
101		if (pfioc.altq.qid == 0)
102			continue;
103		altq = safe_calloc(1, sizeof(*altq));
104		*altq = pfioc.altq;
105		TAILQ_INSERT_TAIL(&altq_entries, altq, entries);
106	}
107	close(pffd);
108}
109
110u_int32_t
111altq_name_to_qid(const char *name)
112{
113	struct pf_altq *altq;
114
115	altq_fetch();
116	TAILQ_FOREACH(altq, &altq_entries, entries)
117		if (strcmp(name, altq->qname) == 0)
118			break;
119	if (altq == NULL)
120		errx(EX_DATAERR, "altq has no queue named `%s'", name);
121	return altq->qid;
122}
123
124const char *
125altq_qid_to_name(u_int32_t qid)
126{
127	struct pf_altq *altq;
128
129	altq_fetch();
130	TAILQ_FOREACH(altq, &altq_entries, entries)
131		if (qid == altq->qid)
132			break;
133	if (altq == NULL)
134		return NULL;
135	return altq->qname;
136}
137
138void
139print_altq_cmd(ipfw_insn_altq *altqptr)
140{
141        if (altqptr) {
142                const char *qname;
143
144                qname = altq_qid_to_name(altqptr->qid);
145                if (qname == NULL)
146                        printf(" altq ?<%u>", altqptr->qid);
147                else
148                        printf(" altq %s", qname);
149        }
150}
151