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