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 * altq interface
21 */
22
23 #define PFIOC_USE_LATEST
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/in.h> /* in_addr */
43 #include <netinet/ip_fw.h>
44
45 /*
46 * Map between current altq queue id numbers and names.
47 */
48 static TAILQ_HEAD(, pf_altq) altq_entries =
49 TAILQ_HEAD_INITIALIZER(altq_entries);
50
51 void
altq_set_enabled(int enabled)52 altq_set_enabled(int enabled)
53 {
54 int pffd;
55
56 pffd = open("/dev/pf", O_RDWR);
57 if (pffd == -1)
58 err(EX_UNAVAILABLE,
59 "altq support opening pf(4) control device");
60 if (enabled) {
61 if (ioctl(pffd, DIOCSTARTALTQ) != 0 && errno != EEXIST)
62 err(EX_UNAVAILABLE, "enabling altq");
63 } else {
64 if (ioctl(pffd, DIOCSTOPALTQ) != 0 && errno != ENOENT)
65 err(EX_UNAVAILABLE, "disabling altq");
66 }
67 close(pffd);
68 }
69
70 static void
altq_fetch(void)71 altq_fetch(void)
72 {
73 struct pfioc_altq pfioc;
74 struct pf_altq *altq;
75 int pffd;
76 unsigned int mnr;
77 static int altq_fetched = 0;
78
79 if (altq_fetched)
80 return;
81 altq_fetched = 1;
82 pffd = open("/dev/pf", O_RDONLY);
83 if (pffd == -1) {
84 warn("altq support opening pf(4) control device");
85 return;
86 }
87 bzero(&pfioc, sizeof(pfioc));
88 pfioc.version = PFIOC_ALTQ_VERSION;
89 if (ioctl(pffd, DIOCGETALTQS, &pfioc) != 0) {
90 warn("altq support getting queue list");
91 close(pffd);
92 return;
93 }
94 mnr = pfioc.nr;
95 for (pfioc.nr = 0; pfioc.nr < mnr; pfioc.nr++) {
96 if (ioctl(pffd, DIOCGETALTQ, &pfioc) != 0) {
97 if (errno == EBUSY)
98 break;
99 warn("altq support getting queue list");
100 close(pffd);
101 return;
102 }
103 if (pfioc.altq.qid == 0)
104 continue;
105 altq = safe_calloc(1, sizeof(*altq));
106 *altq = pfioc.altq;
107 TAILQ_INSERT_TAIL(&altq_entries, altq, entries);
108 }
109 close(pffd);
110 }
111
112 u_int32_t
altq_name_to_qid(const char * name)113 altq_name_to_qid(const char *name)
114 {
115 struct pf_altq *altq;
116
117 altq_fetch();
118 TAILQ_FOREACH(altq, &altq_entries, entries)
119 if (strcmp(name, altq->qname) == 0)
120 break;
121 if (altq == NULL)
122 errx(EX_DATAERR, "altq has no queue named `%s'", name);
123 return altq->qid;
124 }
125
126 static const char *
altq_qid_to_name(u_int32_t qid)127 altq_qid_to_name(u_int32_t qid)
128 {
129 struct pf_altq *altq;
130
131 altq_fetch();
132 TAILQ_FOREACH(altq, &altq_entries, entries)
133 if (qid == altq->qid)
134 break;
135 if (altq == NULL)
136 return NULL;
137 return altq->qname;
138 }
139
140 void
print_altq_cmd(struct buf_pr * bp,const ipfw_insn_altq * altqptr)141 print_altq_cmd(struct buf_pr *bp, const ipfw_insn_altq *altqptr)
142 {
143 if (altqptr) {
144 const char *qname;
145
146 qname = altq_qid_to_name(altqptr->qid);
147 if (qname == NULL)
148 bprintf(bp, " altq ?<%u>", altqptr->qid);
149 else
150 bprintf(bp, " altq %s", qname);
151 }
152 }
153