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