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 */ 50 static TAILQ_HEAD(, pf_altq) altq_entries = 51 TAILQ_HEAD_INITIALIZER(altq_entries); 52 53 void 54 altq_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 72 static void 73 altq_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 114 u_int32_t 115 altq_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 128 static const char * 129 altq_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 142 void 143 print_altq_cmd(struct buf_pr *bp, 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