altq.c revision 302408
1251607Sdim/*
2251607Sdim * Copyright (c) 2002-2003 Luigi Rizzo
3251607Sdim * Copyright (c) 1996 Alex Nash, Paul Traina, Poul-Henning Kamp
4251607Sdim * Copyright (c) 1994 Ugen J.S.Antsilevich
5251607Sdim *
6251607Sdim * Idea and grammar partially left from:
7251607Sdim * Copyright (c) 1993 Daniel Boulet
8251607Sdim *
9251607Sdim * Redistribution and use in source forms, with and without modification,
10251607Sdim * are permitted provided that this entire comment appears intact.
11251607Sdim *
12251607Sdim * Redistribution in binary form may occur without any restrictions.
13251607Sdim * Obviously, it would be nice if you gave credit where credit is due
14251607Sdim * but requiring it would be too onerous.
15251607Sdim *
16251607Sdim * This software is provided ``AS IS'' without any warranties of any kind.
17251607Sdim *
18251607Sdim * NEW command line interface for IP firewall facility
19251607Sdim *
20251607Sdim * $FreeBSD: stable/11/sbin/ipfw/altq.c 270424 2014-08-23 17:37:18Z melifaro $
21251607Sdim *
22251607Sdim * altq interface
23251607Sdim */
24251607Sdim
25251607Sdim#include <sys/types.h>
26251607Sdim#include <sys/socket.h>
27251607Sdim#include <sys/sockio.h>
28251607Sdim
29251607Sdim#include "ipfw2.h"
30251607Sdim
31251607Sdim#include <err.h>
32251607Sdim#include <errno.h>
33251607Sdim#include <stdio.h>
34251607Sdim#include <stdlib.h>
35251607Sdim#include <string.h>
36251607Sdim#include <sysexits.h>
37251607Sdim#include <unistd.h>
38251607Sdim#include <fcntl.h>
39251607Sdim
40251607Sdim#include <net/if.h>		/* IFNAMSIZ */
41251607Sdim#include <net/pfvar.h>
42251607Sdim#include <netinet/in.h>	/* in_addr */
43251607Sdim#include <netinet/ip_fw.h>
44251607Sdim
45251607Sdim/*
46251607Sdim * Map between current altq queue id numbers and names.
47251607Sdim */
48251607Sdimstatic TAILQ_HEAD(, pf_altq) altq_entries =
49251607Sdim	TAILQ_HEAD_INITIALIZER(altq_entries);
50251607Sdim
51251607Sdimvoid
52251607Sdimaltq_set_enabled(int enabled)
53251607Sdim{
54251607Sdim	int pffd;
55251607Sdim
56251607Sdim	pffd = open("/dev/pf", O_RDWR);
57251607Sdim	if (pffd == -1)
58251607Sdim		err(EX_UNAVAILABLE,
59251607Sdim		    "altq support opening pf(4) control device");
60251607Sdim	if (enabled) {
61251607Sdim		if (ioctl(pffd, DIOCSTARTALTQ) != 0 && errno != EEXIST)
62251607Sdim			err(EX_UNAVAILABLE, "enabling altq");
63251607Sdim	} else {
64251607Sdim		if (ioctl(pffd, DIOCSTOPALTQ) != 0 && errno != ENOENT)
65251607Sdim			err(EX_UNAVAILABLE, "disabling altq");
66251607Sdim	}
67251607Sdim	close(pffd);
68251607Sdim}
69251607Sdim
70251607Sdimstatic void
71251607Sdimaltq_fetch(void)
72251607Sdim{
73251607Sdim	struct pfioc_altq pfioc;
74251607Sdim	struct pf_altq *altq;
75251607Sdim	int pffd;
76251607Sdim	unsigned int mnr;
77251607Sdim	static int altq_fetched = 0;
78251607Sdim
79251607Sdim	if (altq_fetched)
80251607Sdim		return;
81251607Sdim	altq_fetched = 1;
82251607Sdim	pffd = open("/dev/pf", O_RDONLY);
83251607Sdim	if (pffd == -1) {
84251607Sdim		warn("altq support opening pf(4) control device");
85251607Sdim		return;
86251607Sdim	}
87251607Sdim	bzero(&pfioc, sizeof(pfioc));
88251607Sdim	if (ioctl(pffd, DIOCGETALTQS, &pfioc) != 0) {
89251607Sdim		warn("altq support getting queue list");
90251607Sdim		close(pffd);
91251607Sdim		return;
92251607Sdim	}
93251607Sdim	mnr = pfioc.nr;
94251607Sdim	for (pfioc.nr = 0; pfioc.nr < mnr; pfioc.nr++) {
95251607Sdim		if (ioctl(pffd, DIOCGETALTQ, &pfioc) != 0) {
96251607Sdim			if (errno == EBUSY)
97251607Sdim				break;
98251607Sdim			warn("altq support getting queue list");
99251607Sdim			close(pffd);
100251607Sdim			return;
101251607Sdim		}
102251607Sdim		if (pfioc.altq.qid == 0)
103251607Sdim			continue;
104251607Sdim		altq = safe_calloc(1, sizeof(*altq));
105251607Sdim		*altq = pfioc.altq;
106251607Sdim		TAILQ_INSERT_TAIL(&altq_entries, altq, entries);
107251607Sdim	}
108251607Sdim	close(pffd);
109251607Sdim}
110251607Sdim
111251607Sdimu_int32_t
112251607Sdimaltq_name_to_qid(const char *name)
113251607Sdim{
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
125static const char *
126altq_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
139void
140print_altq_cmd(struct buf_pr *bp, 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			bprintf(bp, " altq ?<%u>", altqptr->qid);
148		else
149			bprintf(bp, " altq %s", qname);
150	}
151}
152