xref: /freebsd/sbin/ipfw/altq.c (revision 912430f6f017498d33da73c9eb2ca0bf1cce68c2)
123c608c8SLuigi Rizzo /*
223c608c8SLuigi Rizzo  * Copyright (c) 2002-2003 Luigi Rizzo
323c608c8SLuigi Rizzo  * Copyright (c) 1996 Alex Nash, Paul Traina, Poul-Henning Kamp
423c608c8SLuigi Rizzo  * Copyright (c) 1994 Ugen J.S.Antsilevich
523c608c8SLuigi Rizzo  *
623c608c8SLuigi Rizzo  * Idea and grammar partially left from:
723c608c8SLuigi Rizzo  * Copyright (c) 1993 Daniel Boulet
823c608c8SLuigi Rizzo  *
923c608c8SLuigi Rizzo  * Redistribution and use in source forms, with and without modification,
1023c608c8SLuigi Rizzo  * are permitted provided that this entire comment appears intact.
1123c608c8SLuigi Rizzo  *
1223c608c8SLuigi Rizzo  * Redistribution in binary form may occur without any restrictions.
1323c608c8SLuigi Rizzo  * Obviously, it would be nice if you gave credit where credit is due
1423c608c8SLuigi Rizzo  * but requiring it would be too onerous.
1523c608c8SLuigi Rizzo  *
1623c608c8SLuigi Rizzo  * This software is provided ``AS IS'' without any warranties of any kind.
1723c608c8SLuigi Rizzo  *
1823c608c8SLuigi Rizzo  * NEW command line interface for IP firewall facility
1923c608c8SLuigi Rizzo  *
2023c608c8SLuigi Rizzo  * $FreeBSD$
2123c608c8SLuigi Rizzo  *
2223c608c8SLuigi Rizzo  * altq interface
2323c608c8SLuigi Rizzo  */
2423c608c8SLuigi Rizzo 
2523c608c8SLuigi Rizzo #include <sys/types.h>
2623c608c8SLuigi Rizzo #include <sys/socket.h>
2723c608c8SLuigi Rizzo #include <sys/sockio.h>
2823c608c8SLuigi Rizzo 
2923c608c8SLuigi Rizzo #include "ipfw2.h"
3023c608c8SLuigi Rizzo 
3123c608c8SLuigi Rizzo #include <err.h>
3223c608c8SLuigi Rizzo #include <errno.h>
3323c608c8SLuigi Rizzo #include <stdio.h>
3423c608c8SLuigi Rizzo #include <stdlib.h>
3523c608c8SLuigi Rizzo #include <string.h>
3623c608c8SLuigi Rizzo #include <sysexits.h>
3723c608c8SLuigi Rizzo #include <unistd.h>
3823c608c8SLuigi Rizzo #include <fcntl.h>
3923c608c8SLuigi Rizzo 
4023c608c8SLuigi Rizzo #include <net/if.h>		/* IFNAMSIZ */
4123c608c8SLuigi Rizzo #include <net/pfvar.h>
42cc4d3c30SLuigi Rizzo #include <netinet/in.h>	/* in_addr */
4323c608c8SLuigi Rizzo #include <netinet/ip_fw.h>
4423c608c8SLuigi Rizzo 
4523c608c8SLuigi Rizzo /*
4623c608c8SLuigi Rizzo  * Map between current altq queue id numbers and names.
4723c608c8SLuigi Rizzo  */
4823c608c8SLuigi Rizzo static TAILQ_HEAD(, pf_altq) altq_entries =
4923c608c8SLuigi Rizzo 	TAILQ_HEAD_INITIALIZER(altq_entries);
5023c608c8SLuigi Rizzo 
5123c608c8SLuigi Rizzo void
5223c608c8SLuigi Rizzo altq_set_enabled(int enabled)
5323c608c8SLuigi Rizzo {
5423c608c8SLuigi Rizzo 	int pffd;
5523c608c8SLuigi Rizzo 
5623c608c8SLuigi Rizzo 	pffd = open("/dev/pf", O_RDWR);
5723c608c8SLuigi Rizzo 	if (pffd == -1)
5823c608c8SLuigi Rizzo 		err(EX_UNAVAILABLE,
5923c608c8SLuigi Rizzo 		    "altq support opening pf(4) control device");
6023c608c8SLuigi Rizzo 	if (enabled) {
6123c608c8SLuigi Rizzo 		if (ioctl(pffd, DIOCSTARTALTQ) != 0 && errno != EEXIST)
6223c608c8SLuigi Rizzo 			err(EX_UNAVAILABLE, "enabling altq");
6323c608c8SLuigi Rizzo 	} else {
6423c608c8SLuigi Rizzo 		if (ioctl(pffd, DIOCSTOPALTQ) != 0 && errno != ENOENT)
6523c608c8SLuigi Rizzo 			err(EX_UNAVAILABLE, "disabling altq");
6623c608c8SLuigi Rizzo 	}
6723c608c8SLuigi Rizzo 	close(pffd);
6823c608c8SLuigi Rizzo }
6923c608c8SLuigi Rizzo 
7023c608c8SLuigi Rizzo static void
7123c608c8SLuigi Rizzo altq_fetch(void)
7223c608c8SLuigi Rizzo {
7323c608c8SLuigi Rizzo 	struct pfioc_altq pfioc;
7423c608c8SLuigi Rizzo 	struct pf_altq *altq;
7523c608c8SLuigi Rizzo 	int pffd;
7623c608c8SLuigi Rizzo 	unsigned int mnr;
7723c608c8SLuigi Rizzo 	static int altq_fetched = 0;
7823c608c8SLuigi Rizzo 
7923c608c8SLuigi Rizzo 	if (altq_fetched)
8023c608c8SLuigi Rizzo 		return;
8123c608c8SLuigi Rizzo 	altq_fetched = 1;
8223c608c8SLuigi Rizzo 	pffd = open("/dev/pf", O_RDONLY);
8323c608c8SLuigi Rizzo 	if (pffd == -1) {
8423c608c8SLuigi Rizzo 		warn("altq support opening pf(4) control device");
8523c608c8SLuigi Rizzo 		return;
8623c608c8SLuigi Rizzo 	}
8723c608c8SLuigi Rizzo 	bzero(&pfioc, sizeof(pfioc));
8823c608c8SLuigi Rizzo 	if (ioctl(pffd, DIOCGETALTQS, &pfioc) != 0) {
8923c608c8SLuigi Rizzo 		warn("altq support getting queue list");
9023c608c8SLuigi Rizzo 		close(pffd);
9123c608c8SLuigi Rizzo 		return;
9223c608c8SLuigi Rizzo 	}
9323c608c8SLuigi Rizzo 	mnr = pfioc.nr;
9423c608c8SLuigi Rizzo 	for (pfioc.nr = 0; pfioc.nr < mnr; pfioc.nr++) {
9523c608c8SLuigi Rizzo 		if (ioctl(pffd, DIOCGETALTQ, &pfioc) != 0) {
9623c608c8SLuigi Rizzo 			if (errno == EBUSY)
9723c608c8SLuigi Rizzo 				break;
9823c608c8SLuigi Rizzo 			warn("altq support getting queue list");
9923c608c8SLuigi Rizzo 			close(pffd);
10023c608c8SLuigi Rizzo 			return;
10123c608c8SLuigi Rizzo 		}
10223c608c8SLuigi Rizzo 		if (pfioc.altq.qid == 0)
10323c608c8SLuigi Rizzo 			continue;
10423c608c8SLuigi Rizzo 		altq = safe_calloc(1, sizeof(*altq));
10523c608c8SLuigi Rizzo 		*altq = pfioc.altq;
10623c608c8SLuigi Rizzo 		TAILQ_INSERT_TAIL(&altq_entries, altq, entries);
10723c608c8SLuigi Rizzo 	}
10823c608c8SLuigi Rizzo 	close(pffd);
10923c608c8SLuigi Rizzo }
11023c608c8SLuigi Rizzo 
11123c608c8SLuigi Rizzo u_int32_t
11223c608c8SLuigi Rizzo altq_name_to_qid(const char *name)
11323c608c8SLuigi Rizzo {
11423c608c8SLuigi Rizzo 	struct pf_altq *altq;
11523c608c8SLuigi Rizzo 
11623c608c8SLuigi Rizzo 	altq_fetch();
11723c608c8SLuigi Rizzo 	TAILQ_FOREACH(altq, &altq_entries, entries)
11823c608c8SLuigi Rizzo 		if (strcmp(name, altq->qname) == 0)
11923c608c8SLuigi Rizzo 			break;
12023c608c8SLuigi Rizzo 	if (altq == NULL)
12123c608c8SLuigi Rizzo 		errx(EX_DATAERR, "altq has no queue named `%s'", name);
12223c608c8SLuigi Rizzo 	return altq->qid;
12323c608c8SLuigi Rizzo }
12423c608c8SLuigi Rizzo 
1253e9771d2SLuigi Rizzo static const char *
12623c608c8SLuigi Rizzo altq_qid_to_name(u_int32_t qid)
12723c608c8SLuigi Rizzo {
12823c608c8SLuigi Rizzo 	struct pf_altq *altq;
12923c608c8SLuigi Rizzo 
13023c608c8SLuigi Rizzo 	altq_fetch();
13123c608c8SLuigi Rizzo 	TAILQ_FOREACH(altq, &altq_entries, entries)
13223c608c8SLuigi Rizzo 		if (qid == altq->qid)
13323c608c8SLuigi Rizzo 			break;
13423c608c8SLuigi Rizzo 	if (altq == NULL)
13523c608c8SLuigi Rizzo 		return NULL;
13623c608c8SLuigi Rizzo 	return altq->qname;
13723c608c8SLuigi Rizzo }
13823c608c8SLuigi Rizzo 
13923c608c8SLuigi Rizzo void
140*912430f6SAlexander V. Chernikov print_altq_cmd(struct buf_pr *bp, ipfw_insn_altq *altqptr)
14123c608c8SLuigi Rizzo {
14223c608c8SLuigi Rizzo 	if (altqptr) {
14323c608c8SLuigi Rizzo 		const char *qname;
14423c608c8SLuigi Rizzo 
14523c608c8SLuigi Rizzo 		qname = altq_qid_to_name(altqptr->qid);
14623c608c8SLuigi Rizzo 		if (qname == NULL)
147*912430f6SAlexander V. Chernikov 			bprintf(bp, " altq ?<%u>", altqptr->qid);
14823c608c8SLuigi Rizzo 		else
149*912430f6SAlexander V. Chernikov 			bprintf(bp, " altq %s", qname);
15023c608c8SLuigi Rizzo 	}
15123c608c8SLuigi Rizzo }
152