xref: /freebsd/sbin/ipfw/altq.c (revision edf8578117e8844e02c0121147f45e4609b30680)
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
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  	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
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 *
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
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