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