Major changes:
[ipfw.git] / ipfw / altq.c
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/in.h>
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
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
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         if (ioctl(pffd, DIOCGETALTQS, &pfioc) != 0) {
89                 warn("altq support getting queue list");
90                 close(pffd);
91                 return;
92         }
93         mnr = pfioc.nr;
94         for (pfioc.nr = 0; pfioc.nr < mnr; pfioc.nr++) {
95                 if (ioctl(pffd, DIOCGETALTQ, &pfioc) != 0) {
96                         if (errno == EBUSY)
97                                 break;
98                         warn("altq support getting queue list");
99                         close(pffd);
100                         return;
101                 }
102                 if (pfioc.altq.qid == 0)
103                         continue;
104                 altq = safe_calloc(1, sizeof(*altq));
105                 *altq = pfioc.altq;
106                 TAILQ_INSERT_TAIL(&altq_entries, altq, entries);
107         }
108         close(pffd);
109 }
110
111 u_int32_t
112 altq_name_to_qid(const char *name)
113 {
114         struct pf_altq *altq;
115
116         altq_fetch();
117         TAILQ_FOREACH(altq, &altq_entries, entries)
118                 if (strcmp(name, altq->qname) == 0)
119                         break;
120         if (altq == NULL)
121                 errx(EX_DATAERR, "altq has no queue named `%s'", name);
122         return altq->qid;
123 }
124
125 static const char *
126 altq_qid_to_name(u_int32_t qid)
127 {
128         struct pf_altq *altq;
129
130         altq_fetch();
131         TAILQ_FOREACH(altq, &altq_entries, entries)
132                 if (qid == altq->qid)
133                         break;
134         if (altq == NULL)
135                 return NULL;
136         return altq->qname;
137 }
138
139 void
140 print_altq_cmd(ipfw_insn_altq *altqptr)
141 {
142         if (altqptr) {
143                 const char *qname;
144
145                 qname = altq_qid_to_name(altqptr->qid);
146                 if (qname == NULL)
147                         printf(" altq ?<%u>", altqptr->qid);
148                 else
149                         printf(" altq %s", qname);
150         }
151 }