xref: /freebsd/sbin/ipfw/altq.c (revision 830940567b49bb0c08dfaed40418999e76616909)
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$
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  */
47 static TAILQ_HEAD(, pf_altq) altq_entries =
48 	TAILQ_HEAD_INITIALIZER(altq_entries);
49 
50 void
51 altq_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 
69 static void
70 altq_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 
110 u_int32_t
111 altq_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 
124 static const char *
125 altq_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 
138 void
139 print_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