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/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 if (ioctl(pffd, DIOCGETALTQS, &pfioc) != 0) { 89 warn("altq support getting queue list"); 90 close(pffd); 91 return; 92 } 93 mnr = pfioc.nr; 94 for (pfioc.nr = 0; pfioc.nr < mnr; pfioc.nr++) { 95 if (ioctl(pffd, DIOCGETALTQ, &pfioc) != 0) { 96 if (errno == EBUSY) 97 break; 98 warn("altq support getting queue list"); 99 close(pffd); 100 return; 101 } 102 if (pfioc.altq.qid == 0) 103 continue; 104 altq = safe_calloc(1, sizeof(*altq)); 105 *altq = pfioc.altq; 106 TAILQ_INSERT_TAIL(&altq_entries, altq, entries); 107 } 108 close(pffd); 109 } 110 111 u_int32_t 112 altq_name_to_qid(const char *name) 113 { 114 struct pf_altq *altq; 115 116 altq_fetch(); 117 TAILQ_FOREACH(altq, &altq_entries, entries) 118 if (strcmp(name, altq->qname) == 0) 119 break; 120 if (altq == NULL) 121 errx(EX_DATAERR, "altq has no queue named `%s'", name); 122 return altq->qid; 123 } 124 125 static const char * 126 altq_qid_to_name(u_int32_t qid) 127 { 128 struct pf_altq *altq; 129 130 altq_fetch(); 131 TAILQ_FOREACH(altq, &altq_entries, entries) 132 if (qid == altq->qid) 133 break; 134 if (altq == NULL) 135 return NULL; 136 return altq->qname; 137 } 138 139 void 140 print_altq_cmd(struct buf_pr *bp, ipfw_insn_altq *altqptr) 141 { 142 if (altqptr) { 143 const char *qname; 144 145 qname = altq_qid_to_name(altqptr->qid); 146 if (qname == NULL) 147 bprintf(bp, " altq ?<%u>", altqptr->qid); 148 else 149 bprintf(bp, " altq %s", qname); 150 } 151 } 152