1f1220db8SAlexander V. Chernikov /* 2f1220db8SAlexander V. Chernikov * Copyright (c) 2002-2003 Luigi Rizzo 3f1220db8SAlexander V. Chernikov * Copyright (c) 1996 Alex Nash, Paul Traina, Poul-Henning Kamp 4f1220db8SAlexander V. Chernikov * Copyright (c) 1994 Ugen J.S.Antsilevich 5f1220db8SAlexander V. Chernikov * 6f1220db8SAlexander V. Chernikov * Idea and grammar partially left from: 7f1220db8SAlexander V. Chernikov * Copyright (c) 1993 Daniel Boulet 8f1220db8SAlexander V. Chernikov * 9f1220db8SAlexander V. Chernikov * Redistribution and use in source forms, with and without modification, 10f1220db8SAlexander V. Chernikov * are permitted provided that this entire comment appears intact. 11f1220db8SAlexander V. Chernikov * 12f1220db8SAlexander V. Chernikov * Redistribution in binary form may occur without any restrictions. 13f1220db8SAlexander V. Chernikov * Obviously, it would be nice if you gave credit where credit is due 14f1220db8SAlexander V. Chernikov * but requiring it would be too onerous. 15f1220db8SAlexander V. Chernikov * 16f1220db8SAlexander V. Chernikov * This software is provided ``AS IS'' without any warranties of any kind. 17f1220db8SAlexander V. Chernikov * 18f1220db8SAlexander V. Chernikov * in-kernel tables support 19f1220db8SAlexander V. Chernikov * 20f1220db8SAlexander V. Chernikov * $FreeBSD: projects/ipfw/sbin/ipfw/ipfw2.c 267467 2014-06-14 10:58:39Z melifaro $ 21f1220db8SAlexander V. Chernikov */ 22f1220db8SAlexander V. Chernikov 23f1220db8SAlexander V. Chernikov 24f1220db8SAlexander V. Chernikov #include <sys/types.h> 25f1220db8SAlexander V. Chernikov #include <sys/param.h> 26f1220db8SAlexander V. Chernikov #include <sys/socket.h> 27f1220db8SAlexander V. Chernikov #include <sys/sysctl.h> 28f1220db8SAlexander V. Chernikov 29f1220db8SAlexander V. Chernikov #include <ctype.h> 30f1220db8SAlexander V. Chernikov #include <err.h> 31f1220db8SAlexander V. Chernikov #include <errno.h> 32f1220db8SAlexander V. Chernikov #include <netdb.h> 33f1220db8SAlexander V. Chernikov #include <stddef.h> /* offsetof */ 34f1220db8SAlexander V. Chernikov #include <stdio.h> 35f1220db8SAlexander V. Chernikov #include <stdlib.h> 36f1220db8SAlexander V. Chernikov #include <string.h> 37f1220db8SAlexander V. Chernikov #include <sysexits.h> 38f1220db8SAlexander V. Chernikov 39f1220db8SAlexander V. Chernikov #define IPFW_INTERNAL /* Access to protected structures in ip_fw.h. */ 40f1220db8SAlexander V. Chernikov 41f1220db8SAlexander V. Chernikov #include <net/if.h> 42f1220db8SAlexander V. Chernikov #include <net/if_dl.h> 43f1220db8SAlexander V. Chernikov #include <net/route.h> /* def. of struct route */ 44f1220db8SAlexander V. Chernikov #include <netinet/in.h> 45f1220db8SAlexander V. Chernikov #include <netinet/ip_fw.h> 46f1220db8SAlexander V. Chernikov #include <arpa/inet.h> 47f1220db8SAlexander V. Chernikov #include <alias.h> 48f1220db8SAlexander V. Chernikov 49f1220db8SAlexander V. Chernikov #include "ipfw2.h" 50f1220db8SAlexander V. Chernikov 51f1220db8SAlexander V. Chernikov static void table_list(ipfw_xtable_info *i, int need_header); 52ac35ff17SAlexander V. Chernikov static void table_modify_record(ipfw_obj_header *oh, int ac, char *av[], 53*3a845e10SAlexander V. Chernikov int add, int quiet, int update, int atomic); 54ac35ff17SAlexander V. Chernikov static int table_flush(ipfw_obj_header *oh); 55ac35ff17SAlexander V. Chernikov static int table_destroy(ipfw_obj_header *oh); 56ac35ff17SAlexander V. Chernikov static int table_do_create(ipfw_obj_header *oh, ipfw_xtable_info *i); 57adf3b2b9SAlexander V. Chernikov static int table_do_modify(ipfw_obj_header *oh, ipfw_xtable_info *i); 5846d52008SAlexander V. Chernikov static int table_do_swap(ipfw_obj_header *oh, char *second); 59adf3b2b9SAlexander V. Chernikov static void table_create(ipfw_obj_header *oh, int ac, char *av[]); 60adf3b2b9SAlexander V. Chernikov static void table_modify(ipfw_obj_header *oh, int ac, char *av[]); 61adf3b2b9SAlexander V. Chernikov static void table_lookup(ipfw_obj_header *oh, int ac, char *av[]); 6246d52008SAlexander V. Chernikov static int table_swap(ipfw_obj_header *oh, char *second); 63ac35ff17SAlexander V. Chernikov static int table_get_info(ipfw_obj_header *oh, ipfw_xtable_info *i); 64f1220db8SAlexander V. Chernikov static int table_show_info(ipfw_xtable_info *i, void *arg); 65ac35ff17SAlexander V. Chernikov static void table_fill_ntlv(ipfw_obj_ntlv *ntlv, char *name, uint32_t set, 66ac35ff17SAlexander V. Chernikov uint16_t uidx); 67f1220db8SAlexander V. Chernikov 68f1220db8SAlexander V. Chernikov static int table_flush_one(ipfw_xtable_info *i, void *arg); 69f1220db8SAlexander V. Chernikov static int table_show_one(ipfw_xtable_info *i, void *arg); 70720ee730SAlexander V. Chernikov static int table_do_get_list(ipfw_xtable_info *i, ipfw_obj_header **poh); 71f1220db8SAlexander V. Chernikov static void table_show_list(ipfw_obj_header *oh, int need_header); 7281d3153dSAlexander V. Chernikov static void table_show_entry(ipfw_xtable_info *i, ipfw_obj_tentry *tent); 73f1220db8SAlexander V. Chernikov 74ac35ff17SAlexander V. Chernikov static void tentry_fill_key(ipfw_obj_header *oh, ipfw_obj_tentry *tent, 7581d3153dSAlexander V. Chernikov char *key, uint8_t *ptype, uint8_t *pvtype, ipfw_xtable_info *xi); 76ac35ff17SAlexander V. Chernikov static void tentry_fill_value(ipfw_obj_header *oh, ipfw_obj_tentry *tent, 77ac35ff17SAlexander V. Chernikov char *arg, uint8_t type, uint8_t vtype); 78ac35ff17SAlexander V. Chernikov 79f1220db8SAlexander V. Chernikov typedef int (table_cb_t)(ipfw_xtable_info *i, void *arg); 80f1220db8SAlexander V. Chernikov static int tables_foreach(table_cb_t *f, void *arg, int sort); 81f1220db8SAlexander V. Chernikov 82f1220db8SAlexander V. Chernikov #ifndef s6_addr32 83f1220db8SAlexander V. Chernikov #define s6_addr32 __u6_addr.__u6_addr32 84f1220db8SAlexander V. Chernikov #endif 85f1220db8SAlexander V. Chernikov 86ac35ff17SAlexander V. Chernikov static struct _s_x tabletypes[] = { 87ac35ff17SAlexander V. Chernikov { "cidr", IPFW_TABLE_CIDR }, 88ac35ff17SAlexander V. Chernikov { "iface", IPFW_TABLE_INTERFACE }, 89b23d5de9SAlexander V. Chernikov { "number", IPFW_TABLE_NUMBER }, 90914bffb6SAlexander V. Chernikov { "flow", IPFW_TABLE_FLOW }, 91ac35ff17SAlexander V. Chernikov { NULL, 0 } 92ac35ff17SAlexander V. Chernikov }; 93ac35ff17SAlexander V. Chernikov 94ac35ff17SAlexander V. Chernikov static struct _s_x tablevaltypes[] = { 95ac35ff17SAlexander V. Chernikov { "number", IPFW_VTYPE_U32 }, 96ac35ff17SAlexander V. Chernikov { NULL, 0 } 97ac35ff17SAlexander V. Chernikov }; 98ac35ff17SAlexander V. Chernikov 99adf3b2b9SAlexander V. Chernikov static struct _s_x tablefvaltypes[] = { 100adf3b2b9SAlexander V. Chernikov { "ip", IPFW_VFTYPE_IP }, 101adf3b2b9SAlexander V. Chernikov { "number", IPFW_VFTYPE_U32 }, 102adf3b2b9SAlexander V. Chernikov { NULL, 0 } 103adf3b2b9SAlexander V. Chernikov }; 104adf3b2b9SAlexander V. Chernikov 105ac35ff17SAlexander V. Chernikov static struct _s_x tablecmds[] = { 106ac35ff17SAlexander V. Chernikov { "add", TOK_ADD }, 107ac35ff17SAlexander V. Chernikov { "delete", TOK_DEL }, 10846d52008SAlexander V. Chernikov { "create", TOK_CREATE }, 109ac35ff17SAlexander V. Chernikov { "destroy", TOK_DESTROY }, 110ac35ff17SAlexander V. Chernikov { "flush", TOK_FLUSH }, 111adf3b2b9SAlexander V. Chernikov { "modify", TOK_MODIFY }, 11246d52008SAlexander V. Chernikov { "swap", TOK_SWAP }, 113ac35ff17SAlexander V. Chernikov { "info", TOK_INFO }, 114358b9d09SAlexander V. Chernikov { "detail", TOK_DETAIL }, 115ac35ff17SAlexander V. Chernikov { "list", TOK_LIST }, 11681d3153dSAlexander V. Chernikov { "lookup", TOK_LOOKUP }, 117*3a845e10SAlexander V. Chernikov { "atomic", TOK_ATOMIC }, 118ac35ff17SAlexander V. Chernikov { NULL, 0 } 119ac35ff17SAlexander V. Chernikov }; 120ac35ff17SAlexander V. Chernikov 121f1220db8SAlexander V. Chernikov static int 122f1220db8SAlexander V. Chernikov lookup_host (char *host, struct in_addr *ipaddr) 123f1220db8SAlexander V. Chernikov { 124f1220db8SAlexander V. Chernikov struct hostent *he; 125f1220db8SAlexander V. Chernikov 126f1220db8SAlexander V. Chernikov if (!inet_aton(host, ipaddr)) { 127f1220db8SAlexander V. Chernikov if ((he = gethostbyname(host)) == NULL) 128f1220db8SAlexander V. Chernikov return(-1); 129f1220db8SAlexander V. Chernikov *ipaddr = *(struct in_addr *)he->h_addr_list[0]; 130f1220db8SAlexander V. Chernikov } 131f1220db8SAlexander V. Chernikov return(0); 132f1220db8SAlexander V. Chernikov } 133f1220db8SAlexander V. Chernikov 134f1220db8SAlexander V. Chernikov /* 135f1220db8SAlexander V. Chernikov * This one handles all table-related commands 136ac35ff17SAlexander V. Chernikov * ipfw table NAME create ... 137ac35ff17SAlexander V. Chernikov * ipfw table NAME destroy 138ac35ff17SAlexander V. Chernikov * ipfw table NAME add addr[/masklen] [value] 139ac35ff17SAlexander V. Chernikov * ipfw table NAME delete addr[/masklen] 140ac35ff17SAlexander V. Chernikov * ipfw table {NAME | all} flush 141ac35ff17SAlexander V. Chernikov * ipfw table {NAME | all} list 142ac35ff17SAlexander V. Chernikov * ipfw table {NAME | all} info 143f1220db8SAlexander V. Chernikov */ 144f1220db8SAlexander V. Chernikov void 145f1220db8SAlexander V. Chernikov ipfw_table_handler(int ac, char *av[]) 146f1220db8SAlexander V. Chernikov { 147ac35ff17SAlexander V. Chernikov int do_add, is_all; 148*3a845e10SAlexander V. Chernikov int atomic, error, tcmd; 149ac35ff17SAlexander V. Chernikov ipfw_xtable_info i; 150ac35ff17SAlexander V. Chernikov ipfw_obj_header oh; 151f1220db8SAlexander V. Chernikov char *tablename; 152ac35ff17SAlexander V. Chernikov uint32_t set; 153358b9d09SAlexander V. Chernikov void *arg; 154f1220db8SAlexander V. Chernikov 155ac35ff17SAlexander V. Chernikov memset(&oh, 0, sizeof(oh)); 156ac35ff17SAlexander V. Chernikov is_all = 0; 157ac35ff17SAlexander V. Chernikov if (co.use_set != 0) 158ac35ff17SAlexander V. Chernikov set = co.use_set - 1; 159ac35ff17SAlexander V. Chernikov else 160ac35ff17SAlexander V. Chernikov set = 0; 161f1220db8SAlexander V. Chernikov 162f1220db8SAlexander V. Chernikov ac--; av++; 1639d099b4fSAlexander V. Chernikov NEED1("table needs name"); 164f1220db8SAlexander V. Chernikov tablename = *av; 165f1220db8SAlexander V. Chernikov 166ac35ff17SAlexander V. Chernikov if (table_check_name(tablename) == 0) { 167ac35ff17SAlexander V. Chernikov table_fill_ntlv(&oh.ntlv, *av, set, 1); 168ac35ff17SAlexander V. Chernikov oh.idx = 1; 169ac35ff17SAlexander V. Chernikov } else { 170ac35ff17SAlexander V. Chernikov if (strcmp(tablename, "all") == 0) 171ac35ff17SAlexander V. Chernikov is_all = 1; 172ac35ff17SAlexander V. Chernikov else 173ac35ff17SAlexander V. Chernikov errx(EX_USAGE, "table name %s is invalid", tablename); 174ac35ff17SAlexander V. Chernikov } 175ac35ff17SAlexander V. Chernikov ac--; av++; 1769d099b4fSAlexander V. Chernikov NEED1("table needs command"); 177ac35ff17SAlexander V. Chernikov 178ac35ff17SAlexander V. Chernikov if ((tcmd = match_token(tablecmds, *av)) == -1) 179ac35ff17SAlexander V. Chernikov errx(EX_USAGE, "invalid table command %s", *av); 180*3a845e10SAlexander V. Chernikov /* Check if atomic operation was requested */ 181*3a845e10SAlexander V. Chernikov atomic = 0; 182*3a845e10SAlexander V. Chernikov if (tcmd == TOK_ATOMIC) { 183*3a845e10SAlexander V. Chernikov ac--; av++; 184*3a845e10SAlexander V. Chernikov NEED1("atomic needs command"); 185*3a845e10SAlexander V. Chernikov if ((tcmd = match_token(tablecmds, *av)) == -1) 186*3a845e10SAlexander V. Chernikov errx(EX_USAGE, "invalid table command %s", *av); 187*3a845e10SAlexander V. Chernikov switch (tcmd) { 188*3a845e10SAlexander V. Chernikov case TOK_ADD: 189*3a845e10SAlexander V. Chernikov break; 190*3a845e10SAlexander V. Chernikov default: 191*3a845e10SAlexander V. Chernikov errx(EX_USAGE, "atomic is not compatible with %s", *av); 192*3a845e10SAlexander V. Chernikov } 193*3a845e10SAlexander V. Chernikov atomic = 1; 194*3a845e10SAlexander V. Chernikov } 195ac35ff17SAlexander V. Chernikov 196ac35ff17SAlexander V. Chernikov switch (tcmd) { 197ac35ff17SAlexander V. Chernikov case TOK_LIST: 198ac35ff17SAlexander V. Chernikov case TOK_INFO: 199358b9d09SAlexander V. Chernikov case TOK_DETAIL: 200ac35ff17SAlexander V. Chernikov case TOK_FLUSH: 201ac35ff17SAlexander V. Chernikov break; 202ac35ff17SAlexander V. Chernikov default: 203ac35ff17SAlexander V. Chernikov if (is_all != 0) 204ac35ff17SAlexander V. Chernikov errx(EX_USAGE, "table name required"); 205ac35ff17SAlexander V. Chernikov } 206ac35ff17SAlexander V. Chernikov 207ac35ff17SAlexander V. Chernikov switch (tcmd) { 208ac35ff17SAlexander V. Chernikov case TOK_ADD: 209ac35ff17SAlexander V. Chernikov case TOK_DEL: 210f1220db8SAlexander V. Chernikov do_add = **av == 'a'; 211f1220db8SAlexander V. Chernikov ac--; av++; 212*3a845e10SAlexander V. Chernikov table_modify_record(&oh, ac, av, do_add, co.do_quiet, 213*3a845e10SAlexander V. Chernikov co.do_quiet, atomic); 214ac35ff17SAlexander V. Chernikov break; 215ac35ff17SAlexander V. Chernikov case TOK_CREATE: 216f1220db8SAlexander V. Chernikov ac--; av++; 217ac35ff17SAlexander V. Chernikov table_create(&oh, ac, av); 218ac35ff17SAlexander V. Chernikov break; 219adf3b2b9SAlexander V. Chernikov case TOK_MODIFY: 220adf3b2b9SAlexander V. Chernikov ac--; av++; 221adf3b2b9SAlexander V. Chernikov table_modify(&oh, ac, av); 222adf3b2b9SAlexander V. Chernikov break; 223ac35ff17SAlexander V. Chernikov case TOK_DESTROY: 224ac35ff17SAlexander V. Chernikov if (table_destroy(&oh) != 0) 225ac35ff17SAlexander V. Chernikov err(EX_OSERR, "failed to destroy table %s", tablename); 226ac35ff17SAlexander V. Chernikov break; 227ac35ff17SAlexander V. Chernikov case TOK_FLUSH: 228f1220db8SAlexander V. Chernikov if (is_all == 0) { 229ac35ff17SAlexander V. Chernikov if ((error = table_flush(&oh)) != 0) 230f1220db8SAlexander V. Chernikov err(EX_OSERR, "failed to flush table %s info", 231f1220db8SAlexander V. Chernikov tablename); 232f1220db8SAlexander V. Chernikov } else { 233ac35ff17SAlexander V. Chernikov error = tables_foreach(table_flush_one, &oh, 1); 234f1220db8SAlexander V. Chernikov if (error != 0) 235f1220db8SAlexander V. Chernikov err(EX_OSERR, "failed to flush tables list"); 236f1220db8SAlexander V. Chernikov } 237ac35ff17SAlexander V. Chernikov break; 23846d52008SAlexander V. Chernikov case TOK_SWAP: 23946d52008SAlexander V. Chernikov ac--; av++; 24046d52008SAlexander V. Chernikov NEED1("second table name required"); 24146d52008SAlexander V. Chernikov table_swap(&oh, *av); 24246d52008SAlexander V. Chernikov break; 243358b9d09SAlexander V. Chernikov case TOK_DETAIL: 244ac35ff17SAlexander V. Chernikov case TOK_INFO: 245358b9d09SAlexander V. Chernikov arg = (tcmd == TOK_DETAIL) ? (void *)1 : NULL; 246f1220db8SAlexander V. Chernikov if (is_all == 0) { 247ac35ff17SAlexander V. Chernikov if ((error = table_get_info(&oh, &i)) != 0) 248f1220db8SAlexander V. Chernikov err(EX_OSERR, "failed to request table info"); 249358b9d09SAlexander V. Chernikov table_show_info(&i, arg); 250f1220db8SAlexander V. Chernikov } else { 251358b9d09SAlexander V. Chernikov error = tables_foreach(table_show_info, arg, 1); 252f1220db8SAlexander V. Chernikov if (error != 0) 253f1220db8SAlexander V. Chernikov err(EX_OSERR, "failed to request tables list"); 254f1220db8SAlexander V. Chernikov } 255ac35ff17SAlexander V. Chernikov break; 256ac35ff17SAlexander V. Chernikov case TOK_LIST: 257ac35ff17SAlexander V. Chernikov if (is_all == 0) { 258ac35ff17SAlexander V. Chernikov ipfw_xtable_info i; 259ac35ff17SAlexander V. Chernikov if ((error = table_get_info(&oh, &i)) != 0) 260ac35ff17SAlexander V. Chernikov err(EX_OSERR, "failed to request table info"); 261ac35ff17SAlexander V. Chernikov table_show_one(&i, NULL); 262f1220db8SAlexander V. Chernikov } else { 263ac35ff17SAlexander V. Chernikov error = tables_foreach(table_show_one, NULL, 1); 264ac35ff17SAlexander V. Chernikov if (error != 0) 265ac35ff17SAlexander V. Chernikov err(EX_OSERR, "failed to request tables list"); 266f1220db8SAlexander V. Chernikov } 267ac35ff17SAlexander V. Chernikov break; 26881d3153dSAlexander V. Chernikov case TOK_LOOKUP: 26981d3153dSAlexander V. Chernikov ac--; av++; 27081d3153dSAlexander V. Chernikov table_lookup(&oh, ac, av); 27181d3153dSAlexander V. Chernikov break; 272f1220db8SAlexander V. Chernikov } 273f1220db8SAlexander V. Chernikov } 274f1220db8SAlexander V. Chernikov 275f1220db8SAlexander V. Chernikov static void 276ac35ff17SAlexander V. Chernikov table_fill_ntlv(ipfw_obj_ntlv *ntlv, char *name, uint32_t set, uint16_t uidx) 277f1220db8SAlexander V. Chernikov { 278f1220db8SAlexander V. Chernikov 279563b5ab1SAlexander V. Chernikov ntlv->head.type = IPFW_TLV_TBL_NAME; 280f1220db8SAlexander V. Chernikov ntlv->head.length = sizeof(ipfw_obj_ntlv); 281f1220db8SAlexander V. Chernikov ntlv->idx = uidx; 282ac35ff17SAlexander V. Chernikov ntlv->set = set; 283f1220db8SAlexander V. Chernikov strlcpy(ntlv->name, name, sizeof(ntlv->name)); 284f1220db8SAlexander V. Chernikov } 285f1220db8SAlexander V. Chernikov 286f1220db8SAlexander V. Chernikov static void 287f1220db8SAlexander V. Chernikov table_fill_objheader(ipfw_obj_header *oh, ipfw_xtable_info *i) 288f1220db8SAlexander V. Chernikov { 289f1220db8SAlexander V. Chernikov 290f1220db8SAlexander V. Chernikov oh->idx = 1; 29181d3153dSAlexander V. Chernikov table_fill_ntlv(&oh->ntlv, i->tablename, i->set, 1); 292ac35ff17SAlexander V. Chernikov } 293ac35ff17SAlexander V. Chernikov 294ac35ff17SAlexander V. Chernikov static struct _s_x tablenewcmds[] = { 295ac35ff17SAlexander V. Chernikov { "type", TOK_TYPE }, 296adf3b2b9SAlexander V. Chernikov { "ftype", TOK_FTYPE }, 297ac35ff17SAlexander V. Chernikov { "valtype", TOK_VALTYPE }, 298ac35ff17SAlexander V. Chernikov { "algo", TOK_ALGO }, 2994c0c07a5SAlexander V. Chernikov { "limit", TOK_LIMIT }, 300ac35ff17SAlexander V. Chernikov { NULL, 0 } 301ac35ff17SAlexander V. Chernikov }; 302ac35ff17SAlexander V. Chernikov 303914bffb6SAlexander V. Chernikov static struct _s_x flowtypecmds[] = { 304914bffb6SAlexander V. Chernikov { "src-ip", IPFW_TFFLAG_SRCIP }, 305914bffb6SAlexander V. Chernikov { "proto", IPFW_TFFLAG_PROTO }, 306914bffb6SAlexander V. Chernikov { "src-port", IPFW_TFFLAG_SRCPORT }, 307914bffb6SAlexander V. Chernikov { "dst-ip", IPFW_TFFLAG_DSTIP }, 308914bffb6SAlexander V. Chernikov { "dst-port", IPFW_TFFLAG_DSTPORT }, 309914bffb6SAlexander V. Chernikov { NULL, 0 } 310914bffb6SAlexander V. Chernikov }; 311914bffb6SAlexander V. Chernikov 312914bffb6SAlexander V. Chernikov int 313914bffb6SAlexander V. Chernikov table_parse_type(uint8_t ttype, char *p, uint8_t *tflags) 314914bffb6SAlexander V. Chernikov { 315914bffb6SAlexander V. Chernikov uint8_t fset, fclear; 316914bffb6SAlexander V. Chernikov 317914bffb6SAlexander V. Chernikov /* Parse type options */ 318914bffb6SAlexander V. Chernikov switch(ttype) { 319914bffb6SAlexander V. Chernikov case IPFW_TABLE_FLOW: 320914bffb6SAlexander V. Chernikov fset = fclear = 0; 321914bffb6SAlexander V. Chernikov fill_flags(flowtypecmds, p, &fset, 322914bffb6SAlexander V. Chernikov &fclear); 323914bffb6SAlexander V. Chernikov *tflags = fset; 324914bffb6SAlexander V. Chernikov break; 325914bffb6SAlexander V. Chernikov default: 326914bffb6SAlexander V. Chernikov return (EX_USAGE); 327914bffb6SAlexander V. Chernikov } 328914bffb6SAlexander V. Chernikov 329914bffb6SAlexander V. Chernikov return (0); 330914bffb6SAlexander V. Chernikov } 331914bffb6SAlexander V. Chernikov 332914bffb6SAlexander V. Chernikov void 333914bffb6SAlexander V. Chernikov table_print_type(char *tbuf, size_t size, uint8_t type, uint8_t tflags) 334914bffb6SAlexander V. Chernikov { 335914bffb6SAlexander V. Chernikov const char *tname; 336914bffb6SAlexander V. Chernikov int l; 337914bffb6SAlexander V. Chernikov 338914bffb6SAlexander V. Chernikov if ((tname = match_value(tabletypes, type)) == NULL) 339914bffb6SAlexander V. Chernikov tname = "unknown"; 340914bffb6SAlexander V. Chernikov 341914bffb6SAlexander V. Chernikov l = snprintf(tbuf, size, "%s", tname); 342914bffb6SAlexander V. Chernikov tbuf += l; 343914bffb6SAlexander V. Chernikov size -= l; 344914bffb6SAlexander V. Chernikov 345914bffb6SAlexander V. Chernikov switch(type) { 346914bffb6SAlexander V. Chernikov case IPFW_TABLE_FLOW: 347914bffb6SAlexander V. Chernikov if (tflags != 0) { 348914bffb6SAlexander V. Chernikov *tbuf++ = ':'; 349914bffb6SAlexander V. Chernikov l--; 350914bffb6SAlexander V. Chernikov print_flags_buffer(tbuf, size, flowtypecmds, tflags); 351914bffb6SAlexander V. Chernikov } 352914bffb6SAlexander V. Chernikov break; 353914bffb6SAlexander V. Chernikov } 354914bffb6SAlexander V. Chernikov } 355914bffb6SAlexander V. Chernikov 356ac35ff17SAlexander V. Chernikov /* 357ac35ff17SAlexander V. Chernikov * Creates new table 358ac35ff17SAlexander V. Chernikov * 359ac35ff17SAlexander V. Chernikov * ipfw table NAME create [ type { cidr | iface | u32 } ] 360ac35ff17SAlexander V. Chernikov * [ valtype { number | ip | dscp } ] 361ac35ff17SAlexander V. Chernikov * [ algo algoname ] 362ac35ff17SAlexander V. Chernikov */ 363ac35ff17SAlexander V. Chernikov static void 364ac35ff17SAlexander V. Chernikov table_create(ipfw_obj_header *oh, int ac, char *av[]) 365ac35ff17SAlexander V. Chernikov { 366ac35ff17SAlexander V. Chernikov ipfw_xtable_info xi; 367ac35ff17SAlexander V. Chernikov int error, tcmd, val; 368ac35ff17SAlexander V. Chernikov size_t sz; 369914bffb6SAlexander V. Chernikov char *p; 370ac35ff17SAlexander V. Chernikov char tbuf[128]; 371ac35ff17SAlexander V. Chernikov 372ac35ff17SAlexander V. Chernikov sz = sizeof(tbuf); 373ac35ff17SAlexander V. Chernikov memset(&xi, 0, sizeof(xi)); 374ac35ff17SAlexander V. Chernikov 375ac35ff17SAlexander V. Chernikov /* Set some defaults to preserve compability */ 376ac35ff17SAlexander V. Chernikov xi.type = IPFW_TABLE_CIDR; 377ac35ff17SAlexander V. Chernikov xi.vtype = IPFW_VTYPE_U32; 378ac35ff17SAlexander V. Chernikov 379ac35ff17SAlexander V. Chernikov while (ac > 0) { 380ac35ff17SAlexander V. Chernikov if ((tcmd = match_token(tablenewcmds, *av)) == -1) 381ac35ff17SAlexander V. Chernikov errx(EX_USAGE, "unknown option: %s", *av); 382ac35ff17SAlexander V. Chernikov ac--; av++; 383ac35ff17SAlexander V. Chernikov 384ac35ff17SAlexander V. Chernikov switch (tcmd) { 3854c0c07a5SAlexander V. Chernikov case TOK_LIMIT: 3864c0c07a5SAlexander V. Chernikov NEED1("limit value required"); 3874c0c07a5SAlexander V. Chernikov xi.limit = strtol(*av, NULL, 10); 3884c0c07a5SAlexander V. Chernikov ac--; av++; 3894c0c07a5SAlexander V. Chernikov break; 390ac35ff17SAlexander V. Chernikov case TOK_TYPE: 391ac35ff17SAlexander V. Chernikov NEED1("table type required"); 392914bffb6SAlexander V. Chernikov /* Type may have suboptions after ':' */ 393914bffb6SAlexander V. Chernikov if ((p = strchr(*av, ':')) != NULL) 394914bffb6SAlexander V. Chernikov *p++ = '\0'; 395ac35ff17SAlexander V. Chernikov val = match_token(tabletypes, *av); 396914bffb6SAlexander V. Chernikov if (val == -1) { 397914bffb6SAlexander V. Chernikov concat_tokens(tbuf, sizeof(tbuf), tabletypes, 398914bffb6SAlexander V. Chernikov ", "); 399914bffb6SAlexander V. Chernikov errx(EX_USAGE, 400914bffb6SAlexander V. Chernikov "Unknown tabletype: %s. Supported: %s", 401ac35ff17SAlexander V. Chernikov *av, tbuf); 402914bffb6SAlexander V. Chernikov } 403914bffb6SAlexander V. Chernikov xi.type = val; 404914bffb6SAlexander V. Chernikov if (p != NULL) { 405914bffb6SAlexander V. Chernikov error = table_parse_type(val, p, &xi.tflags); 406914bffb6SAlexander V. Chernikov if (error != 0) 407914bffb6SAlexander V. Chernikov errx(EX_USAGE, 408914bffb6SAlexander V. Chernikov "Unsupported suboptions: %s", p); 409914bffb6SAlexander V. Chernikov } 410914bffb6SAlexander V. Chernikov ac--; av++; 411ac35ff17SAlexander V. Chernikov break; 412ac35ff17SAlexander V. Chernikov case TOK_VALTYPE: 413ac35ff17SAlexander V. Chernikov NEED1("table value type required"); 414ac35ff17SAlexander V. Chernikov val = match_token(tablevaltypes, *av); 415ac35ff17SAlexander V. Chernikov if (val != -1) { 416ac35ff17SAlexander V. Chernikov xi.vtype = val; 417ac35ff17SAlexander V. Chernikov ac--; av++; 418ac35ff17SAlexander V. Chernikov break; 419ac35ff17SAlexander V. Chernikov } 420ac35ff17SAlexander V. Chernikov concat_tokens(tbuf, sizeof(tbuf), tablevaltypes, ", "); 421ac35ff17SAlexander V. Chernikov errx(EX_USAGE, "Unknown value type: %s. Supported: %s", 422ac35ff17SAlexander V. Chernikov *av, tbuf); 423ac35ff17SAlexander V. Chernikov break; 424adf3b2b9SAlexander V. Chernikov case TOK_FTYPE: 425adf3b2b9SAlexander V. Chernikov NEED1("table value format type required"); 426adf3b2b9SAlexander V. Chernikov val = match_token(tablefvaltypes, *av); 427adf3b2b9SAlexander V. Chernikov if (val != -1) { 428adf3b2b9SAlexander V. Chernikov xi.vftype = val; 429adf3b2b9SAlexander V. Chernikov ac--; av++; 430adf3b2b9SAlexander V. Chernikov break; 431adf3b2b9SAlexander V. Chernikov } 432adf3b2b9SAlexander V. Chernikov concat_tokens(tbuf, sizeof(tbuf), tablefvaltypes, ", "); 433adf3b2b9SAlexander V. Chernikov errx(EX_USAGE, "Unknown format type: %s. Supported: %s", 434adf3b2b9SAlexander V. Chernikov *av, tbuf); 435adf3b2b9SAlexander V. Chernikov break; 436ac35ff17SAlexander V. Chernikov case TOK_ALGO: 437ac35ff17SAlexander V. Chernikov NEED1("table algorithm name required"); 438ac35ff17SAlexander V. Chernikov if (strlen(*av) > sizeof(xi.algoname)) 439ac35ff17SAlexander V. Chernikov errx(EX_USAGE, "algorithm name too long"); 440ac35ff17SAlexander V. Chernikov strlcpy(xi.algoname, *av, sizeof(xi.algoname)); 441ac35ff17SAlexander V. Chernikov ac--; av++; 442ac35ff17SAlexander V. Chernikov break; 443ac35ff17SAlexander V. Chernikov } 444ac35ff17SAlexander V. Chernikov } 445ac35ff17SAlexander V. Chernikov 446ac35ff17SAlexander V. Chernikov if ((error = table_do_create(oh, &xi)) != 0) 447ac35ff17SAlexander V. Chernikov err(EX_OSERR, "Table creation failed"); 448f1220db8SAlexander V. Chernikov } 449f1220db8SAlexander V. Chernikov 450f1220db8SAlexander V. Chernikov /* 451ac35ff17SAlexander V. Chernikov * Creates new table 452ac35ff17SAlexander V. Chernikov * 453ac35ff17SAlexander V. Chernikov * Request: [ ipfw_obj_header ipfw_xtable_info ] 454ac35ff17SAlexander V. Chernikov * 455f1220db8SAlexander V. Chernikov * Returns 0 on success. 456f1220db8SAlexander V. Chernikov */ 457f1220db8SAlexander V. Chernikov static int 458ac35ff17SAlexander V. Chernikov table_do_create(ipfw_obj_header *oh, ipfw_xtable_info *i) 459f1220db8SAlexander V. Chernikov { 460ac35ff17SAlexander V. Chernikov char tbuf[sizeof(ipfw_obj_header) + sizeof(ipfw_xtable_info)]; 461ac35ff17SAlexander V. Chernikov int error; 462f1220db8SAlexander V. Chernikov 463ac35ff17SAlexander V. Chernikov memcpy(tbuf, oh, sizeof(*oh)); 464ac35ff17SAlexander V. Chernikov memcpy(tbuf + sizeof(*oh), i, sizeof(*i)); 465ac35ff17SAlexander V. Chernikov oh = (ipfw_obj_header *)tbuf; 466ac35ff17SAlexander V. Chernikov 467ac35ff17SAlexander V. Chernikov error = do_set3(IP_FW_TABLE_XCREATE, &oh->opheader, sizeof(tbuf)); 468ac35ff17SAlexander V. Chernikov 469ac35ff17SAlexander V. Chernikov return (error); 470ac35ff17SAlexander V. Chernikov } 471ac35ff17SAlexander V. Chernikov 472ac35ff17SAlexander V. Chernikov /* 473adf3b2b9SAlexander V. Chernikov * Modifies existing table 474adf3b2b9SAlexander V. Chernikov * 475adf3b2b9SAlexander V. Chernikov * ipfw table NAME modify [ limit number ] [ ftype { number | ip } ] 476adf3b2b9SAlexander V. Chernikov */ 477adf3b2b9SAlexander V. Chernikov static void 478adf3b2b9SAlexander V. Chernikov table_modify(ipfw_obj_header *oh, int ac, char *av[]) 479adf3b2b9SAlexander V. Chernikov { 480adf3b2b9SAlexander V. Chernikov ipfw_xtable_info xi; 481adf3b2b9SAlexander V. Chernikov int error, tcmd, val; 482adf3b2b9SAlexander V. Chernikov size_t sz; 483adf3b2b9SAlexander V. Chernikov char tbuf[128]; 484adf3b2b9SAlexander V. Chernikov 485adf3b2b9SAlexander V. Chernikov sz = sizeof(tbuf); 486adf3b2b9SAlexander V. Chernikov memset(&xi, 0, sizeof(xi)); 487adf3b2b9SAlexander V. Chernikov 488adf3b2b9SAlexander V. Chernikov /* Set some defaults to preserve compability */ 489adf3b2b9SAlexander V. Chernikov xi.type = IPFW_TABLE_CIDR; 490adf3b2b9SAlexander V. Chernikov xi.vtype = IPFW_VTYPE_U32; 491adf3b2b9SAlexander V. Chernikov 492adf3b2b9SAlexander V. Chernikov while (ac > 0) { 493adf3b2b9SAlexander V. Chernikov if ((tcmd = match_token(tablenewcmds, *av)) == -1) 494adf3b2b9SAlexander V. Chernikov errx(EX_USAGE, "unknown option: %s", *av); 495adf3b2b9SAlexander V. Chernikov ac--; av++; 496adf3b2b9SAlexander V. Chernikov 497adf3b2b9SAlexander V. Chernikov switch (tcmd) { 498adf3b2b9SAlexander V. Chernikov case TOK_LIMIT: 499adf3b2b9SAlexander V. Chernikov NEED1("limit value required"); 500adf3b2b9SAlexander V. Chernikov xi.limit = strtol(*av, NULL, 10); 501adf3b2b9SAlexander V. Chernikov xi.mflags |= IPFW_TMFLAGS_LIMIT; 502adf3b2b9SAlexander V. Chernikov ac--; av++; 503adf3b2b9SAlexander V. Chernikov break; 504adf3b2b9SAlexander V. Chernikov case TOK_FTYPE: 505adf3b2b9SAlexander V. Chernikov NEED1("table value format type required"); 506adf3b2b9SAlexander V. Chernikov val = match_token(tablefvaltypes, *av); 507adf3b2b9SAlexander V. Chernikov if (val != -1) { 508adf3b2b9SAlexander V. Chernikov xi.vftype = val; 509adf3b2b9SAlexander V. Chernikov xi.mflags |= IPFW_TMFLAGS_FTYPE; 510adf3b2b9SAlexander V. Chernikov ac--; av++; 511adf3b2b9SAlexander V. Chernikov break; 512adf3b2b9SAlexander V. Chernikov } 513adf3b2b9SAlexander V. Chernikov concat_tokens(tbuf, sizeof(tbuf), tablefvaltypes, ", "); 514adf3b2b9SAlexander V. Chernikov errx(EX_USAGE, "Unknown value type: %s. Supported: %s", 515adf3b2b9SAlexander V. Chernikov *av, tbuf); 516adf3b2b9SAlexander V. Chernikov break; 517adf3b2b9SAlexander V. Chernikov } 518adf3b2b9SAlexander V. Chernikov } 519adf3b2b9SAlexander V. Chernikov 520adf3b2b9SAlexander V. Chernikov if ((error = table_do_modify(oh, &xi)) != 0) 521adf3b2b9SAlexander V. Chernikov err(EX_OSERR, "Table modification failed"); 522adf3b2b9SAlexander V. Chernikov } 523adf3b2b9SAlexander V. Chernikov 524adf3b2b9SAlexander V. Chernikov /* 525adf3b2b9SAlexander V. Chernikov * Modifies existing table. 526adf3b2b9SAlexander V. Chernikov * 527adf3b2b9SAlexander V. Chernikov * Request: [ ipfw_obj_header ipfw_xtable_info ] 528adf3b2b9SAlexander V. Chernikov * 529adf3b2b9SAlexander V. Chernikov * Returns 0 on success. 530adf3b2b9SAlexander V. Chernikov */ 531adf3b2b9SAlexander V. Chernikov static int 532adf3b2b9SAlexander V. Chernikov table_do_modify(ipfw_obj_header *oh, ipfw_xtable_info *i) 533adf3b2b9SAlexander V. Chernikov { 534adf3b2b9SAlexander V. Chernikov char tbuf[sizeof(ipfw_obj_header) + sizeof(ipfw_xtable_info)]; 535adf3b2b9SAlexander V. Chernikov int error; 536adf3b2b9SAlexander V. Chernikov 537adf3b2b9SAlexander V. Chernikov memcpy(tbuf, oh, sizeof(*oh)); 538adf3b2b9SAlexander V. Chernikov memcpy(tbuf + sizeof(*oh), i, sizeof(*i)); 539adf3b2b9SAlexander V. Chernikov oh = (ipfw_obj_header *)tbuf; 540adf3b2b9SAlexander V. Chernikov 541adf3b2b9SAlexander V. Chernikov error = do_set3(IP_FW_TABLE_XMODIFY, &oh->opheader, sizeof(tbuf)); 542adf3b2b9SAlexander V. Chernikov 543adf3b2b9SAlexander V. Chernikov return (error); 544adf3b2b9SAlexander V. Chernikov } 545adf3b2b9SAlexander V. Chernikov /* 546ac35ff17SAlexander V. Chernikov * Destroys given table specified by @oh->ntlv. 547ac35ff17SAlexander V. Chernikov * Returns 0 on success. 548ac35ff17SAlexander V. Chernikov */ 549ac35ff17SAlexander V. Chernikov static int 550ac35ff17SAlexander V. Chernikov table_destroy(ipfw_obj_header *oh) 551ac35ff17SAlexander V. Chernikov { 552ac35ff17SAlexander V. Chernikov 553ac35ff17SAlexander V. Chernikov if (do_set3(IP_FW_TABLE_XDESTROY, &oh->opheader, sizeof(*oh)) != 0) 554f1220db8SAlexander V. Chernikov return (-1); 555f1220db8SAlexander V. Chernikov 556f1220db8SAlexander V. Chernikov return (0); 557f1220db8SAlexander V. Chernikov } 558f1220db8SAlexander V. Chernikov 559f1220db8SAlexander V. Chernikov /* 560ac35ff17SAlexander V. Chernikov * Flushes given table specified by @oh->ntlv. 561f1220db8SAlexander V. Chernikov * Returns 0 on success. 562f1220db8SAlexander V. Chernikov */ 563f1220db8SAlexander V. Chernikov static int 564ac35ff17SAlexander V. Chernikov table_flush(ipfw_obj_header *oh) 565f1220db8SAlexander V. Chernikov { 566f1220db8SAlexander V. Chernikov 567ac35ff17SAlexander V. Chernikov if (do_set3(IP_FW_TABLE_XFLUSH, &oh->opheader, sizeof(*oh)) != 0) 568f1220db8SAlexander V. Chernikov return (-1); 569f1220db8SAlexander V. Chernikov 570f1220db8SAlexander V. Chernikov return (0); 571f1220db8SAlexander V. Chernikov } 572f1220db8SAlexander V. Chernikov 57346d52008SAlexander V. Chernikov static int 57446d52008SAlexander V. Chernikov table_do_swap(ipfw_obj_header *oh, char *second) 57546d52008SAlexander V. Chernikov { 57646d52008SAlexander V. Chernikov char tbuf[sizeof(ipfw_obj_header) + sizeof(ipfw_obj_ntlv)]; 57746d52008SAlexander V. Chernikov int error; 57846d52008SAlexander V. Chernikov 57946d52008SAlexander V. Chernikov memset(tbuf, 0, sizeof(tbuf)); 58046d52008SAlexander V. Chernikov memcpy(tbuf, oh, sizeof(*oh)); 58146d52008SAlexander V. Chernikov oh = (ipfw_obj_header *)tbuf; 58246d52008SAlexander V. Chernikov table_fill_ntlv((ipfw_obj_ntlv *)(oh + 1), second, oh->ntlv.set, 1); 58346d52008SAlexander V. Chernikov 58446d52008SAlexander V. Chernikov error = do_set3(IP_FW_TABLE_XSWAP, &oh->opheader, sizeof(tbuf)); 58546d52008SAlexander V. Chernikov 58646d52008SAlexander V. Chernikov return (error); 58746d52008SAlexander V. Chernikov } 58846d52008SAlexander V. Chernikov 58946d52008SAlexander V. Chernikov /* 59046d52008SAlexander V. Chernikov * Swaps given table with @second one. 59146d52008SAlexander V. Chernikov */ 59246d52008SAlexander V. Chernikov static int 59346d52008SAlexander V. Chernikov table_swap(ipfw_obj_header *oh, char *second) 59446d52008SAlexander V. Chernikov { 59546d52008SAlexander V. Chernikov int error; 59646d52008SAlexander V. Chernikov 59746d52008SAlexander V. Chernikov if (table_check_name(second) != 0) 59846d52008SAlexander V. Chernikov errx(EX_USAGE, "table name %s is invalid", second); 59946d52008SAlexander V. Chernikov 60046d52008SAlexander V. Chernikov error = table_do_swap(oh, second); 60146d52008SAlexander V. Chernikov 60246d52008SAlexander V. Chernikov switch (error) { 60346d52008SAlexander V. Chernikov case EINVAL: 60446d52008SAlexander V. Chernikov errx(EX_USAGE, "Unable to swap table: check types"); 60546d52008SAlexander V. Chernikov case EFBIG: 60646d52008SAlexander V. Chernikov errx(EX_USAGE, "Unable to swap table: check limits"); 60746d52008SAlexander V. Chernikov } 60846d52008SAlexander V. Chernikov 60946d52008SAlexander V. Chernikov return (0); 61046d52008SAlexander V. Chernikov } 61146d52008SAlexander V. Chernikov 61246d52008SAlexander V. Chernikov 613f1220db8SAlexander V. Chernikov /* 614ac35ff17SAlexander V. Chernikov * Retrieves table in given table specified by @oh->ntlv. 615f1220db8SAlexander V. Chernikov * it inside @i. 616f1220db8SAlexander V. Chernikov * Returns 0 on success. 617f1220db8SAlexander V. Chernikov */ 618f1220db8SAlexander V. Chernikov static int 619ac35ff17SAlexander V. Chernikov table_get_info(ipfw_obj_header *oh, ipfw_xtable_info *i) 620f1220db8SAlexander V. Chernikov { 621f1220db8SAlexander V. Chernikov char tbuf[sizeof(ipfw_obj_header) + sizeof(ipfw_xtable_info)]; 622ac35ff17SAlexander V. Chernikov int error; 623f1220db8SAlexander V. Chernikov size_t sz; 624f1220db8SAlexander V. Chernikov 625f1220db8SAlexander V. Chernikov sz = sizeof(tbuf); 626f1220db8SAlexander V. Chernikov memset(tbuf, 0, sizeof(tbuf)); 627ac35ff17SAlexander V. Chernikov memcpy(tbuf, oh, sizeof(*oh)); 628f1220db8SAlexander V. Chernikov oh = (ipfw_obj_header *)tbuf; 629f1220db8SAlexander V. Chernikov 630ac35ff17SAlexander V. Chernikov if ((error = do_get3(IP_FW_TABLE_XINFO, &oh->opheader, &sz)) != 0) 631ac35ff17SAlexander V. Chernikov return (error); 632f1220db8SAlexander V. Chernikov 633f1220db8SAlexander V. Chernikov if (sz < sizeof(tbuf)) 634ac35ff17SAlexander V. Chernikov return (EINVAL); 635f1220db8SAlexander V. Chernikov 636f1220db8SAlexander V. Chernikov *i = *(ipfw_xtable_info *)(oh + 1); 637f1220db8SAlexander V. Chernikov 638f1220db8SAlexander V. Chernikov return (0); 639f1220db8SAlexander V. Chernikov } 640f1220db8SAlexander V. Chernikov 6415f379342SAlexander V. Chernikov static struct _s_x tablealgoclass[] = { 6425f379342SAlexander V. Chernikov { "hash", IPFW_TACLASS_HASH }, 6435f379342SAlexander V. Chernikov { "array", IPFW_TACLASS_ARRAY }, 6445f379342SAlexander V. Chernikov { "radix", IPFW_TACLASS_RADIX }, 6455f379342SAlexander V. Chernikov { NULL, 0 } 6465f379342SAlexander V. Chernikov }; 6475f379342SAlexander V. Chernikov 6485f379342SAlexander V. Chernikov struct ta_cldata { 6495f379342SAlexander V. Chernikov uint8_t taclass; 6505f379342SAlexander V. Chernikov uint8_t spare4; 6515f379342SAlexander V. Chernikov uint16_t itemsize; 6525f379342SAlexander V. Chernikov uint16_t itemsize6; 6535f379342SAlexander V. Chernikov uint32_t size; 6545f379342SAlexander V. Chernikov uint32_t count; 6555f379342SAlexander V. Chernikov }; 6565f379342SAlexander V. Chernikov 6575f379342SAlexander V. Chernikov /* 6585f379342SAlexander V. Chernikov * Print global/per-AF table @i algorithm info. 6595f379342SAlexander V. Chernikov */ 6605f379342SAlexander V. Chernikov static void 6615f379342SAlexander V. Chernikov table_show_tainfo(ipfw_xtable_info *i, struct ta_cldata *d, 6625f379342SAlexander V. Chernikov const char *af, const char *taclass) 6635f379342SAlexander V. Chernikov { 6645f379342SAlexander V. Chernikov 6655f379342SAlexander V. Chernikov switch (d->taclass) { 6665f379342SAlexander V. Chernikov case IPFW_TACLASS_HASH: 6675f379342SAlexander V. Chernikov case IPFW_TACLASS_ARRAY: 6685f379342SAlexander V. Chernikov printf(" %salgorithm %s info\n", af, taclass); 6695f379342SAlexander V. Chernikov if (d->itemsize == d->itemsize6) 6705f379342SAlexander V. Chernikov printf(" size: %u items: %u itemsize: %u\n", 6715f379342SAlexander V. Chernikov d->size, d->count, d->itemsize); 6725f379342SAlexander V. Chernikov else 6735f379342SAlexander V. Chernikov printf(" size: %u items: %u " 6745f379342SAlexander V. Chernikov "itemsize4: %u itemsize6: %u\n", 6755f379342SAlexander V. Chernikov d->size, d->count, 6765f379342SAlexander V. Chernikov d->itemsize, d->itemsize6); 6775f379342SAlexander V. Chernikov break; 6785f379342SAlexander V. Chernikov case IPFW_TACLASS_RADIX: 6795f379342SAlexander V. Chernikov printf(" %salgorithm %s info\n", af, taclass); 6805f379342SAlexander V. Chernikov if (d->itemsize == d->itemsize6) 6815f379342SAlexander V. Chernikov printf(" items: %u itemsize: %u\n", 6825f379342SAlexander V. Chernikov d->count, d->itemsize); 6835f379342SAlexander V. Chernikov else 6845f379342SAlexander V. Chernikov printf(" items: %u " 6855f379342SAlexander V. Chernikov "itemsize4: %u itemsize6: %u\n", 6865f379342SAlexander V. Chernikov d->count, d->itemsize, d->itemsize6); 6875f379342SAlexander V. Chernikov break; 6885f379342SAlexander V. Chernikov default: 6895f379342SAlexander V. Chernikov printf(" algo class: %s\n", taclass); 6905f379342SAlexander V. Chernikov } 6915f379342SAlexander V. Chernikov } 6925f379342SAlexander V. Chernikov 693f1220db8SAlexander V. Chernikov /* 694f1220db8SAlexander V. Chernikov * Prints table info struct @i in human-readable form. 695f1220db8SAlexander V. Chernikov */ 696f1220db8SAlexander V. Chernikov static int 697f1220db8SAlexander V. Chernikov table_show_info(ipfw_xtable_info *i, void *arg) 698f1220db8SAlexander V. Chernikov { 699adf3b2b9SAlexander V. Chernikov const char *vtype, *vftype; 7005f379342SAlexander V. Chernikov ipfw_ta_tinfo *tainfo; 7015f379342SAlexander V. Chernikov int afdata, afitem; 7025f379342SAlexander V. Chernikov struct ta_cldata d; 703adf3b2b9SAlexander V. Chernikov char ttype[64], tvtype[64]; 704f1220db8SAlexander V. Chernikov 705914bffb6SAlexander V. Chernikov table_print_type(ttype, sizeof(ttype), i->type, i->tflags); 706ac35ff17SAlexander V. Chernikov if ((vtype = match_value(tablevaltypes, i->vtype)) == NULL) 707ac35ff17SAlexander V. Chernikov vtype = "unknown"; 708adf3b2b9SAlexander V. Chernikov if ((vftype = match_value(tablefvaltypes, i->vftype)) == NULL) 709adf3b2b9SAlexander V. Chernikov vftype = "unknown"; 710adf3b2b9SAlexander V. Chernikov if (strcmp(vtype, vftype) != 0) 711adf3b2b9SAlexander V. Chernikov snprintf(tvtype, sizeof(tvtype), "%s(%s)", vtype, vftype); 712adf3b2b9SAlexander V. Chernikov else 713adf3b2b9SAlexander V. Chernikov snprintf(tvtype, sizeof(tvtype), "%s", vtype); 714ac35ff17SAlexander V. Chernikov 715914bffb6SAlexander V. Chernikov printf("--- table(%s), set(%u) ---\n", i->tablename, i->set); 716914bffb6SAlexander V. Chernikov printf(" kindex: %d, type: %s\n", i->kidx, ttype); 717adf3b2b9SAlexander V. Chernikov printf(" valtype: %s, references: %u\n", tvtype, i->refcnt); 7189d099b4fSAlexander V. Chernikov printf(" algorithm: %s\n", i->algoname); 719f1220db8SAlexander V. Chernikov printf(" items: %u, size: %u\n", i->count, i->size); 7204c0c07a5SAlexander V. Chernikov if (i->limit > 0) 7214c0c07a5SAlexander V. Chernikov printf(" limit: %u\n", i->limit); 722f1220db8SAlexander V. Chernikov 723358b9d09SAlexander V. Chernikov /* Print algo-specific info if requested & set */ 724358b9d09SAlexander V. Chernikov if (arg == NULL) 725358b9d09SAlexander V. Chernikov return (0); 726358b9d09SAlexander V. Chernikov 7275f379342SAlexander V. Chernikov if ((i->ta_info.flags & IPFW_TATFLAGS_DATA) == 0) 7285f379342SAlexander V. Chernikov return (0); 7295f379342SAlexander V. Chernikov tainfo = &i->ta_info; 7305f379342SAlexander V. Chernikov 7315f379342SAlexander V. Chernikov afdata = 0; 7325f379342SAlexander V. Chernikov afitem = 0; 7335f379342SAlexander V. Chernikov if (tainfo->flags & IPFW_TATFLAGS_AFDATA) 7345f379342SAlexander V. Chernikov afdata = 1; 7355f379342SAlexander V. Chernikov if (tainfo->flags & IPFW_TATFLAGS_AFITEM) 7365f379342SAlexander V. Chernikov afitem = 1; 7375f379342SAlexander V. Chernikov 7385f379342SAlexander V. Chernikov memset(&d, 0, sizeof(d)); 7395f379342SAlexander V. Chernikov d.taclass = tainfo->taclass4; 7405f379342SAlexander V. Chernikov d.size = tainfo->size4; 7415f379342SAlexander V. Chernikov d.count = tainfo->count4; 7425f379342SAlexander V. Chernikov d.itemsize = tainfo->itemsize4; 7435f379342SAlexander V. Chernikov if (afdata == 0 && afitem != 0) 7445f379342SAlexander V. Chernikov d.itemsize6 = tainfo->itemsize6; 7455f379342SAlexander V. Chernikov else 7465f379342SAlexander V. Chernikov d.itemsize6 = d.itemsize; 7475f379342SAlexander V. Chernikov if ((vtype = match_value(tablealgoclass, d.taclass)) == NULL) 7485f379342SAlexander V. Chernikov vtype = "unknown"; 7495f379342SAlexander V. Chernikov 7505f379342SAlexander V. Chernikov if (afdata == 0) { 7515f379342SAlexander V. Chernikov table_show_tainfo(i, &d, "", vtype); 7525f379342SAlexander V. Chernikov } else { 7535f379342SAlexander V. Chernikov table_show_tainfo(i, &d, "IPv4 ", vtype); 7545f379342SAlexander V. Chernikov memset(&d, 0, sizeof(d)); 7555f379342SAlexander V. Chernikov d.taclass = tainfo->taclass6; 7565f379342SAlexander V. Chernikov if ((vtype = match_value(tablealgoclass, d.taclass)) == NULL) 7575f379342SAlexander V. Chernikov vtype = "unknown"; 7585f379342SAlexander V. Chernikov d.size = tainfo->size6; 7595f379342SAlexander V. Chernikov d.count = tainfo->count6; 7605f379342SAlexander V. Chernikov d.itemsize = tainfo->itemsize6; 7615f379342SAlexander V. Chernikov d.itemsize6 = d.itemsize; 7625f379342SAlexander V. Chernikov table_show_tainfo(i, &d, "IPv6 ", vtype); 7635f379342SAlexander V. Chernikov } 7645f379342SAlexander V. Chernikov 765f1220db8SAlexander V. Chernikov return (0); 766f1220db8SAlexander V. Chernikov } 767f1220db8SAlexander V. Chernikov 768f1220db8SAlexander V. Chernikov 769f1220db8SAlexander V. Chernikov /* 770f1220db8SAlexander V. Chernikov * Function wrappers which can be used either 771f1220db8SAlexander V. Chernikov * as is or as foreach function parameter. 772f1220db8SAlexander V. Chernikov */ 773f1220db8SAlexander V. Chernikov 774f1220db8SAlexander V. Chernikov static int 775f1220db8SAlexander V. Chernikov table_show_one(ipfw_xtable_info *i, void *arg) 776f1220db8SAlexander V. Chernikov { 777f1220db8SAlexander V. Chernikov ipfw_obj_header *oh; 77881d3153dSAlexander V. Chernikov int error; 779f1220db8SAlexander V. Chernikov 780720ee730SAlexander V. Chernikov if ((error = table_do_get_list(i, &oh)) != 0) { 78181d3153dSAlexander V. Chernikov err(EX_OSERR, "Error requesting table %s list", i->tablename); 78281d3153dSAlexander V. Chernikov return (error); 78381d3153dSAlexander V. Chernikov } 78481d3153dSAlexander V. Chernikov 785f1220db8SAlexander V. Chernikov table_show_list(oh, 1); 786f1220db8SAlexander V. Chernikov 787f1220db8SAlexander V. Chernikov free(oh); 788f1220db8SAlexander V. Chernikov return (0); 789f1220db8SAlexander V. Chernikov } 790f1220db8SAlexander V. Chernikov 791f1220db8SAlexander V. Chernikov static int 792f1220db8SAlexander V. Chernikov table_flush_one(ipfw_xtable_info *i, void *arg) 793f1220db8SAlexander V. Chernikov { 794ac35ff17SAlexander V. Chernikov ipfw_obj_header *oh; 795f1220db8SAlexander V. Chernikov 796ac35ff17SAlexander V. Chernikov oh = (ipfw_obj_header *)arg; 797ac35ff17SAlexander V. Chernikov 798ac35ff17SAlexander V. Chernikov table_fill_ntlv(&oh->ntlv, i->tablename, i->set, 1); 799ac35ff17SAlexander V. Chernikov 800ac35ff17SAlexander V. Chernikov return (table_flush(oh)); 801f1220db8SAlexander V. Chernikov } 802f1220db8SAlexander V. Chernikov 803ac35ff17SAlexander V. Chernikov static int 804ac35ff17SAlexander V. Chernikov table_do_modify_record(int cmd, ipfw_obj_header *oh, 805*3a845e10SAlexander V. Chernikov ipfw_obj_tentry *tent, int count, int atomic) 806ac35ff17SAlexander V. Chernikov { 807db785d31SAlexander V. Chernikov ipfw_obj_ctlv *ctlv; 808*3a845e10SAlexander V. Chernikov ipfw_obj_tentry *tent_base; 809*3a845e10SAlexander V. Chernikov caddr_t pbuf; 810db785d31SAlexander V. Chernikov char xbuf[sizeof(*oh) + sizeof(ipfw_obj_ctlv) + sizeof(*tent)]; 811*3a845e10SAlexander V. Chernikov int error, i; 812*3a845e10SAlexander V. Chernikov size_t sz; 813ac35ff17SAlexander V. Chernikov 814*3a845e10SAlexander V. Chernikov sz = sizeof(*ctlv) + sizeof(*tent) * count; 815*3a845e10SAlexander V. Chernikov if (count == 1) { 816ac35ff17SAlexander V. Chernikov memset(xbuf, 0, sizeof(xbuf)); 817*3a845e10SAlexander V. Chernikov pbuf = xbuf; 818*3a845e10SAlexander V. Chernikov } else { 819*3a845e10SAlexander V. Chernikov if ((pbuf = calloc(1, sizeof(*oh) + sz)) == NULL) 820*3a845e10SAlexander V. Chernikov return (ENOMEM); 821*3a845e10SAlexander V. Chernikov } 822*3a845e10SAlexander V. Chernikov 823*3a845e10SAlexander V. Chernikov memcpy(pbuf, oh, sizeof(*oh)); 824*3a845e10SAlexander V. Chernikov oh = (ipfw_obj_header *)pbuf; 825ac35ff17SAlexander V. Chernikov oh->opheader.version = 1; 826ac35ff17SAlexander V. Chernikov 827db785d31SAlexander V. Chernikov ctlv = (ipfw_obj_ctlv *)(oh + 1); 828*3a845e10SAlexander V. Chernikov ctlv->count = count; 829*3a845e10SAlexander V. Chernikov ctlv->head.length = sz; 830*3a845e10SAlexander V. Chernikov if (atomic != 0) 831*3a845e10SAlexander V. Chernikov ctlv->flags |= IPFW_CTF_ATOMIC; 832db785d31SAlexander V. Chernikov 833*3a845e10SAlexander V. Chernikov tent_base = tent; 834*3a845e10SAlexander V. Chernikov memcpy(ctlv + 1, tent, sizeof(*tent) * count); 835db785d31SAlexander V. Chernikov tent = (ipfw_obj_tentry *)(ctlv + 1); 836*3a845e10SAlexander V. Chernikov for (i = 0; i < count; i++, tent++) { 837ac35ff17SAlexander V. Chernikov tent->head.length = sizeof(ipfw_obj_tentry); 838*3a845e10SAlexander V. Chernikov tent->idx = oh->idx; 839*3a845e10SAlexander V. Chernikov } 840ac35ff17SAlexander V. Chernikov 841*3a845e10SAlexander V. Chernikov sz += sizeof(*oh); 842*3a845e10SAlexander V. Chernikov error = do_get3(cmd, &oh->opheader, &sz); 843*3a845e10SAlexander V. Chernikov tent = (ipfw_obj_tentry *)(ctlv + 1); 844*3a845e10SAlexander V. Chernikov /* Copy result back to provided buffer */ 845*3a845e10SAlexander V. Chernikov memcpy(tent_base, ctlv + 1, sizeof(*tent) * count); 846*3a845e10SAlexander V. Chernikov 847*3a845e10SAlexander V. Chernikov if (pbuf != xbuf) 848*3a845e10SAlexander V. Chernikov free(pbuf); 849ac35ff17SAlexander V. Chernikov 850ac35ff17SAlexander V. Chernikov return (error); 851ac35ff17SAlexander V. Chernikov } 852ac35ff17SAlexander V. Chernikov 853ac35ff17SAlexander V. Chernikov static void 854*3a845e10SAlexander V. Chernikov table_modify_record(ipfw_obj_header *oh, int ac, char *av[], int add, 855*3a845e10SAlexander V. Chernikov int quiet, int update, int atomic) 856ac35ff17SAlexander V. Chernikov { 857*3a845e10SAlexander V. Chernikov ipfw_obj_tentry *ptent, tent, *tent_buf; 85881d3153dSAlexander V. Chernikov ipfw_xtable_info xi; 859ac35ff17SAlexander V. Chernikov uint8_t type, vtype; 860*3a845e10SAlexander V. Chernikov int cmd, count, error, i, ignored; 861*3a845e10SAlexander V. Chernikov char *texterr, *etxt, *px; 862ac35ff17SAlexander V. Chernikov 863ac35ff17SAlexander V. Chernikov if (ac == 0) 864ac35ff17SAlexander V. Chernikov errx(EX_USAGE, "address required"); 865ac35ff17SAlexander V. Chernikov 866ac35ff17SAlexander V. Chernikov if (add != 0) { 867ac35ff17SAlexander V. Chernikov cmd = IP_FW_TABLE_XADD; 8684c0c07a5SAlexander V. Chernikov texterr = "Adding record failed"; 869ac35ff17SAlexander V. Chernikov } else { 870ac35ff17SAlexander V. Chernikov cmd = IP_FW_TABLE_XDEL; 8714c0c07a5SAlexander V. Chernikov texterr = "Deleting record failed"; 872ac35ff17SAlexander V. Chernikov } 873ac35ff17SAlexander V. Chernikov 874*3a845e10SAlexander V. Chernikov /* 875*3a845e10SAlexander V. Chernikov * Calculate number of entries: 876*3a845e10SAlexander V. Chernikov * Assume [key val] x N for add 877*3a845e10SAlexander V. Chernikov * and 878*3a845e10SAlexander V. Chernikov * key x N for delete 879*3a845e10SAlexander V. Chernikov */ 880*3a845e10SAlexander V. Chernikov count = (add != 0) ? ac / 2 + 1 : ac; 881*3a845e10SAlexander V. Chernikov 882*3a845e10SAlexander V. Chernikov if (count <= 1) { 883*3a845e10SAlexander V. Chernikov /* Adding single entry with/without value */ 884*3a845e10SAlexander V. Chernikov memset(&tent, 0, sizeof(tent)); 885*3a845e10SAlexander V. Chernikov tent_buf = &tent; 886*3a845e10SAlexander V. Chernikov } else { 887*3a845e10SAlexander V. Chernikov 888*3a845e10SAlexander V. Chernikov if ((tent_buf = calloc(count, sizeof(tent))) == NULL) 889*3a845e10SAlexander V. Chernikov errx(EX_OSERR, 890*3a845e10SAlexander V. Chernikov "Unable to allocate memory for all entries"); 891*3a845e10SAlexander V. Chernikov } 892*3a845e10SAlexander V. Chernikov ptent = tent_buf; 893*3a845e10SAlexander V. Chernikov 894*3a845e10SAlexander V. Chernikov memset(&xi, 0, sizeof(xi)); 895*3a845e10SAlexander V. Chernikov count = 0; 896*3a845e10SAlexander V. Chernikov while (ac > 0) { 897*3a845e10SAlexander V. Chernikov tentry_fill_key(oh, ptent, *av, &type, &vtype, &xi); 898*3a845e10SAlexander V. Chernikov 899*3a845e10SAlexander V. Chernikov /* 900*3a845e10SAlexander V. Chernikov * compability layer: auto-create table if not exists 901*3a845e10SAlexander V. Chernikov */ 902*3a845e10SAlexander V. Chernikov if (xi.tablename[0] == '\0') { 903*3a845e10SAlexander V. Chernikov xi.type = type; 904*3a845e10SAlexander V. Chernikov xi.vtype = vtype; 905*3a845e10SAlexander V. Chernikov strlcpy(xi.tablename, oh->ntlv.name, 906*3a845e10SAlexander V. Chernikov sizeof(xi.tablename)); 907*3a845e10SAlexander V. Chernikov fprintf(stderr, "DEPRECATED: inserting data info " 908*3a845e10SAlexander V. Chernikov "non-existent table %s. (auto-created)\n", 909*3a845e10SAlexander V. Chernikov xi.tablename); 910*3a845e10SAlexander V. Chernikov table_do_create(oh, &xi); 911*3a845e10SAlexander V. Chernikov } 912*3a845e10SAlexander V. Chernikov 913*3a845e10SAlexander V. Chernikov oh->ntlv.type = type; 914*3a845e10SAlexander V. Chernikov ac--; av++; 915*3a845e10SAlexander V. Chernikov 916*3a845e10SAlexander V. Chernikov if (add != 0 && ac > 0) { 917*3a845e10SAlexander V. Chernikov tentry_fill_value(oh, ptent, *av, type, vtype); 918*3a845e10SAlexander V. Chernikov ac--; av++; 919*3a845e10SAlexander V. Chernikov } 920*3a845e10SAlexander V. Chernikov 921*3a845e10SAlexander V. Chernikov if (update != 0) 922*3a845e10SAlexander V. Chernikov ptent->head.flags |= IPFW_TF_UPDATE; 923*3a845e10SAlexander V. Chernikov 924*3a845e10SAlexander V. Chernikov count++; 925*3a845e10SAlexander V. Chernikov ptent++; 926*3a845e10SAlexander V. Chernikov } 927*3a845e10SAlexander V. Chernikov 928*3a845e10SAlexander V. Chernikov error = table_do_modify_record(cmd, oh, tent_buf, count, atomic); 929*3a845e10SAlexander V. Chernikov 930*3a845e10SAlexander V. Chernikov /* 931*3a845e10SAlexander V. Chernikov * Compatibility stuff: do not yell on duplicate keys or 932*3a845e10SAlexander V. Chernikov * failed deletions. 933*3a845e10SAlexander V. Chernikov */ 934*3a845e10SAlexander V. Chernikov if (error == 0 || (error == EEXIST && add != 0) || 935*3a845e10SAlexander V. Chernikov (error == ENOENT && add == 0)) { 936*3a845e10SAlexander V. Chernikov if (quiet != 0) { 937*3a845e10SAlexander V. Chernikov if (tent_buf != &tent) 938*3a845e10SAlexander V. Chernikov free(tent_buf); 939*3a845e10SAlexander V. Chernikov return; 940*3a845e10SAlexander V. Chernikov } 941*3a845e10SAlexander V. Chernikov } 942*3a845e10SAlexander V. Chernikov 943*3a845e10SAlexander V. Chernikov /* Report results back */ 944*3a845e10SAlexander V. Chernikov ptent = tent_buf; 945*3a845e10SAlexander V. Chernikov for (i = 0; i < count; ptent++, i++) { 946*3a845e10SAlexander V. Chernikov ignored = 0; 947*3a845e10SAlexander V. Chernikov switch (ptent->result) { 948*3a845e10SAlexander V. Chernikov case IPFW_TR_ADDED: 949*3a845e10SAlexander V. Chernikov px = "added"; 950*3a845e10SAlexander V. Chernikov break; 951*3a845e10SAlexander V. Chernikov case IPFW_TR_DELETED: 952*3a845e10SAlexander V. Chernikov px = "deleted"; 953*3a845e10SAlexander V. Chernikov break; 954*3a845e10SAlexander V. Chernikov case IPFW_TR_UPDATED: 955*3a845e10SAlexander V. Chernikov px = "updated"; 956*3a845e10SAlexander V. Chernikov break; 957*3a845e10SAlexander V. Chernikov case IPFW_TR_LIMIT: 958*3a845e10SAlexander V. Chernikov px = "limit"; 959*3a845e10SAlexander V. Chernikov ignored = 1; 960*3a845e10SAlexander V. Chernikov break; 961*3a845e10SAlexander V. Chernikov case IPFW_TR_ERROR: 962*3a845e10SAlexander V. Chernikov px = "error"; 963*3a845e10SAlexander V. Chernikov ignored = 1; 964*3a845e10SAlexander V. Chernikov break; 965*3a845e10SAlexander V. Chernikov case IPFW_TR_NOTFOUND: 966*3a845e10SAlexander V. Chernikov px = "notfound"; 967*3a845e10SAlexander V. Chernikov ignored = 1; 968*3a845e10SAlexander V. Chernikov break; 969*3a845e10SAlexander V. Chernikov case IPFW_TR_EXISTS: 970*3a845e10SAlexander V. Chernikov px = "exists"; 971*3a845e10SAlexander V. Chernikov ignored = 1; 972*3a845e10SAlexander V. Chernikov break; 973*3a845e10SAlexander V. Chernikov case IPFW_TR_IGNORED: 974*3a845e10SAlexander V. Chernikov px = "ignored"; 975*3a845e10SAlexander V. Chernikov ignored = 1; 976*3a845e10SAlexander V. Chernikov break; 977*3a845e10SAlexander V. Chernikov default: 978*3a845e10SAlexander V. Chernikov px = "unknown"; 979*3a845e10SAlexander V. Chernikov ignored = 1; 980*3a845e10SAlexander V. Chernikov } 981*3a845e10SAlexander V. Chernikov 982*3a845e10SAlexander V. Chernikov if (error != 0 && atomic != 0 && ignored == 0) 983*3a845e10SAlexander V. Chernikov printf("%s(reverted): ", px); 984*3a845e10SAlexander V. Chernikov else 985*3a845e10SAlexander V. Chernikov printf("%s: ", px); 986*3a845e10SAlexander V. Chernikov 987*3a845e10SAlexander V. Chernikov table_show_entry(&xi, ptent); 988*3a845e10SAlexander V. Chernikov } 989*3a845e10SAlexander V. Chernikov 990*3a845e10SAlexander V. Chernikov if (tent_buf != &tent) 991*3a845e10SAlexander V. Chernikov free(tent_buf); 992*3a845e10SAlexander V. Chernikov 993*3a845e10SAlexander V. Chernikov if (error == 0) 9944c0c07a5SAlexander V. Chernikov return; 9954c0c07a5SAlexander V. Chernikov 9964c0c07a5SAlexander V. Chernikov /* Try to provide more human-readable error */ 9974c0c07a5SAlexander V. Chernikov switch (error) { 9984c0c07a5SAlexander V. Chernikov case EEXIST: 9994c0c07a5SAlexander V. Chernikov etxt = "record already exists"; 10004c0c07a5SAlexander V. Chernikov break; 10014c0c07a5SAlexander V. Chernikov case EFBIG: 10024c0c07a5SAlexander V. Chernikov etxt = "limit hit"; 10034c0c07a5SAlexander V. Chernikov break; 10044c0c07a5SAlexander V. Chernikov case ESRCH: 10054c0c07a5SAlexander V. Chernikov etxt = "table not found"; 10064c0c07a5SAlexander V. Chernikov break; 10074c0c07a5SAlexander V. Chernikov case ENOENT: 10084c0c07a5SAlexander V. Chernikov etxt = "record not found"; 10094c0c07a5SAlexander V. Chernikov break; 10104c0c07a5SAlexander V. Chernikov default: 10114c0c07a5SAlexander V. Chernikov etxt = strerror(error); 10124c0c07a5SAlexander V. Chernikov } 10134c0c07a5SAlexander V. Chernikov 10144c0c07a5SAlexander V. Chernikov errx(EX_OSERR, "%s: %s", texterr, etxt); 1015ac35ff17SAlexander V. Chernikov } 1016ac35ff17SAlexander V. Chernikov 101781d3153dSAlexander V. Chernikov static int 101881d3153dSAlexander V. Chernikov table_do_lookup(ipfw_obj_header *oh, char *key, ipfw_xtable_info *xi, 101981d3153dSAlexander V. Chernikov ipfw_obj_tentry *xtent) 102081d3153dSAlexander V. Chernikov { 102181d3153dSAlexander V. Chernikov char xbuf[sizeof(ipfw_obj_header) + sizeof(ipfw_obj_tentry)]; 102281d3153dSAlexander V. Chernikov ipfw_obj_tentry *tent; 102381d3153dSAlexander V. Chernikov uint8_t type, vtype; 102481d3153dSAlexander V. Chernikov int error; 102581d3153dSAlexander V. Chernikov size_t sz; 102681d3153dSAlexander V. Chernikov 102781d3153dSAlexander V. Chernikov memcpy(xbuf, oh, sizeof(*oh)); 102881d3153dSAlexander V. Chernikov oh = (ipfw_obj_header *)xbuf; 102981d3153dSAlexander V. Chernikov tent = (ipfw_obj_tentry *)(oh + 1); 103081d3153dSAlexander V. Chernikov 103181d3153dSAlexander V. Chernikov memset(tent, 0, sizeof(*tent)); 103281d3153dSAlexander V. Chernikov tent->head.length = sizeof(*tent); 103381d3153dSAlexander V. Chernikov tent->idx = 1; 103481d3153dSAlexander V. Chernikov 103581d3153dSAlexander V. Chernikov tentry_fill_key(oh, tent, key, &type, &vtype, xi); 103681d3153dSAlexander V. Chernikov oh->ntlv.type = type; 103781d3153dSAlexander V. Chernikov 103881d3153dSAlexander V. Chernikov sz = sizeof(xbuf); 103981d3153dSAlexander V. Chernikov if ((error = do_get3(IP_FW_TABLE_XFIND, &oh->opheader, &sz)) != 0) 104081d3153dSAlexander V. Chernikov return (error); 104181d3153dSAlexander V. Chernikov 104281d3153dSAlexander V. Chernikov if (sz < sizeof(xbuf)) 104381d3153dSAlexander V. Chernikov return (EINVAL); 104481d3153dSAlexander V. Chernikov 104581d3153dSAlexander V. Chernikov *xtent = *tent; 104681d3153dSAlexander V. Chernikov 104781d3153dSAlexander V. Chernikov return (0); 104881d3153dSAlexander V. Chernikov } 104981d3153dSAlexander V. Chernikov 105081d3153dSAlexander V. Chernikov static void 105181d3153dSAlexander V. Chernikov table_lookup(ipfw_obj_header *oh, int ac, char *av[]) 105281d3153dSAlexander V. Chernikov { 105381d3153dSAlexander V. Chernikov ipfw_obj_tentry xtent; 105481d3153dSAlexander V. Chernikov ipfw_xtable_info xi; 1055914bffb6SAlexander V. Chernikov char key[64]; 105681d3153dSAlexander V. Chernikov int error; 105781d3153dSAlexander V. Chernikov 105881d3153dSAlexander V. Chernikov if (ac == 0) 105981d3153dSAlexander V. Chernikov errx(EX_USAGE, "address required"); 106081d3153dSAlexander V. Chernikov 1061914bffb6SAlexander V. Chernikov strlcpy(key, *av, sizeof(key)); 1062914bffb6SAlexander V. Chernikov 1063*3a845e10SAlexander V. Chernikov memset(&xi, 0, sizeof(xi)); 1064914bffb6SAlexander V. Chernikov error = table_do_lookup(oh, key, &xi, &xtent); 106581d3153dSAlexander V. Chernikov 106681d3153dSAlexander V. Chernikov switch (error) { 106781d3153dSAlexander V. Chernikov case 0: 106881d3153dSAlexander V. Chernikov break; 106981d3153dSAlexander V. Chernikov case ESRCH: 107081d3153dSAlexander V. Chernikov errx(EX_UNAVAILABLE, "Table %s not found", oh->ntlv.name); 107181d3153dSAlexander V. Chernikov case ENOENT: 107281d3153dSAlexander V. Chernikov errx(EX_UNAVAILABLE, "Entry %s not found", *av); 107381d3153dSAlexander V. Chernikov case ENOTSUP: 107481d3153dSAlexander V. Chernikov errx(EX_UNAVAILABLE, "Table %s algo does not support " 107581d3153dSAlexander V. Chernikov "\"lookup\" method", oh->ntlv.name); 107681d3153dSAlexander V. Chernikov default: 107781d3153dSAlexander V. Chernikov err(EX_OSERR, "getsockopt(IP_FW_TABLE_XFIND)"); 107881d3153dSAlexander V. Chernikov } 107981d3153dSAlexander V. Chernikov 108081d3153dSAlexander V. Chernikov table_show_entry(&xi, &xtent); 108181d3153dSAlexander V. Chernikov } 1082ac35ff17SAlexander V. Chernikov 1083ac35ff17SAlexander V. Chernikov static void 1084914bffb6SAlexander V. Chernikov tentry_fill_key_type(char *arg, ipfw_obj_tentry *tentry, uint8_t type, 1085914bffb6SAlexander V. Chernikov uint8_t tflags) 1086ac35ff17SAlexander V. Chernikov { 1087914bffb6SAlexander V. Chernikov char *p, *pp; 1088ac35ff17SAlexander V. Chernikov int mask, af; 1089914bffb6SAlexander V. Chernikov struct in6_addr *paddr, tmp; 1090914bffb6SAlexander V. Chernikov struct tflow_entry *tfe; 1091ac35ff17SAlexander V. Chernikov uint32_t key, *pkey; 1092914bffb6SAlexander V. Chernikov uint16_t port; 1093914bffb6SAlexander V. Chernikov struct protoent *pent; 1094914bffb6SAlexander V. Chernikov struct servent *sent; 1095ac35ff17SAlexander V. Chernikov int masklen; 1096ac35ff17SAlexander V. Chernikov 1097ac35ff17SAlexander V. Chernikov masklen = 0; 1098ac35ff17SAlexander V. Chernikov af = 0; 1099ac35ff17SAlexander V. Chernikov paddr = (struct in6_addr *)&tentry->k; 1100ac35ff17SAlexander V. Chernikov 1101ac35ff17SAlexander V. Chernikov switch (type) { 1102ac35ff17SAlexander V. Chernikov case IPFW_TABLE_CIDR: 1103ac35ff17SAlexander V. Chernikov /* Remove / if exists */ 1104ac35ff17SAlexander V. Chernikov if ((p = strchr(arg, '/')) != NULL) { 1105ac35ff17SAlexander V. Chernikov *p = '\0'; 1106ac35ff17SAlexander V. Chernikov mask = atoi(p + 1); 1107ac35ff17SAlexander V. Chernikov } 1108ac35ff17SAlexander V. Chernikov 1109ac35ff17SAlexander V. Chernikov if (inet_pton(AF_INET, arg, paddr) == 1) { 1110ac35ff17SAlexander V. Chernikov if (p != NULL && mask > 32) 1111ac35ff17SAlexander V. Chernikov errx(EX_DATAERR, "bad IPv4 mask width: %s", 1112ac35ff17SAlexander V. Chernikov p + 1); 1113ac35ff17SAlexander V. Chernikov 1114ac35ff17SAlexander V. Chernikov masklen = p ? mask : 32; 1115ac35ff17SAlexander V. Chernikov af = AF_INET; 1116ac35ff17SAlexander V. Chernikov } else if (inet_pton(AF_INET6, arg, paddr) == 1) { 1117ac35ff17SAlexander V. Chernikov if (IN6_IS_ADDR_V4COMPAT(paddr)) 1118ac35ff17SAlexander V. Chernikov errx(EX_DATAERR, 1119ac35ff17SAlexander V. Chernikov "Use IPv4 instead of v4-compatible"); 1120ac35ff17SAlexander V. Chernikov if (p != NULL && mask > 128) 1121ac35ff17SAlexander V. Chernikov errx(EX_DATAERR, "bad IPv6 mask width: %s", 1122ac35ff17SAlexander V. Chernikov p + 1); 1123ac35ff17SAlexander V. Chernikov 1124ac35ff17SAlexander V. Chernikov masklen = p ? mask : 128; 1125ac35ff17SAlexander V. Chernikov af = AF_INET6; 1126ac35ff17SAlexander V. Chernikov } else { 1127ac35ff17SAlexander V. Chernikov /* Assume FQDN */ 1128ac35ff17SAlexander V. Chernikov if (lookup_host(arg, (struct in_addr *)paddr) != 0) 1129ac35ff17SAlexander V. Chernikov errx(EX_NOHOST, "hostname ``%s'' unknown", arg); 1130ac35ff17SAlexander V. Chernikov 1131ac35ff17SAlexander V. Chernikov masklen = 32; 1132ac35ff17SAlexander V. Chernikov type = IPFW_TABLE_CIDR; 1133ac35ff17SAlexander V. Chernikov af = AF_INET; 1134ac35ff17SAlexander V. Chernikov } 1135ac35ff17SAlexander V. Chernikov break; 1136ac35ff17SAlexander V. Chernikov case IPFW_TABLE_INTERFACE: 1137ac35ff17SAlexander V. Chernikov /* Assume interface name. Copy significant data only */ 1138ac35ff17SAlexander V. Chernikov mask = MIN(strlen(arg), IF_NAMESIZE - 1); 1139ac35ff17SAlexander V. Chernikov memcpy(paddr, arg, mask); 1140ac35ff17SAlexander V. Chernikov /* Set mask to exact match */ 1141ac35ff17SAlexander V. Chernikov masklen = 8 * IF_NAMESIZE; 1142ac35ff17SAlexander V. Chernikov break; 1143b23d5de9SAlexander V. Chernikov case IPFW_TABLE_NUMBER: 1144ac35ff17SAlexander V. Chernikov /* Port or any other key */ 1145ac35ff17SAlexander V. Chernikov key = strtol(arg, &p, 10); 1146ac35ff17SAlexander V. Chernikov if (*p != '\0') 1147ac35ff17SAlexander V. Chernikov errx(EX_DATAERR, "Invalid number: %s", arg); 1148ac35ff17SAlexander V. Chernikov 1149ac35ff17SAlexander V. Chernikov pkey = (uint32_t *)paddr; 1150ac35ff17SAlexander V. Chernikov *pkey = key; 1151ac35ff17SAlexander V. Chernikov masklen = 32; 1152ac35ff17SAlexander V. Chernikov break; 1153914bffb6SAlexander V. Chernikov case IPFW_TABLE_FLOW: 1154914bffb6SAlexander V. Chernikov /* Assume [src-ip][,proto][,src-port][,dst-ip][,dst-port] */ 1155914bffb6SAlexander V. Chernikov tfe = &tentry->k.flow; 1156914bffb6SAlexander V. Chernikov af = 0; 1157914bffb6SAlexander V. Chernikov 1158914bffb6SAlexander V. Chernikov /* Handle <ipv4|ipv6>*/ 1159914bffb6SAlexander V. Chernikov if ((tflags & IPFW_TFFLAG_SRCIP) != 0) { 1160914bffb6SAlexander V. Chernikov if ((p = strchr(arg, ',')) != NULL) 1161914bffb6SAlexander V. Chernikov *p++ = '\0'; 1162914bffb6SAlexander V. Chernikov /* Determine family using temporary storage */ 1163914bffb6SAlexander V. Chernikov if (inet_pton(AF_INET, arg, &tmp) == 1) { 1164914bffb6SAlexander V. Chernikov if (af != 0 && af != AF_INET) 1165914bffb6SAlexander V. Chernikov errx(EX_DATAERR, 1166914bffb6SAlexander V. Chernikov "Inconsistent address family\n"); 1167914bffb6SAlexander V. Chernikov af = AF_INET; 1168914bffb6SAlexander V. Chernikov memcpy(&tfe->a.a4.sip, &tmp, 4); 1169914bffb6SAlexander V. Chernikov } else if (inet_pton(AF_INET6, arg, &tmp) == 1) { 1170914bffb6SAlexander V. Chernikov if (af != 0 && af != AF_INET6) 1171914bffb6SAlexander V. Chernikov errx(EX_DATAERR, 1172914bffb6SAlexander V. Chernikov "Inconsistent address family\n"); 1173914bffb6SAlexander V. Chernikov af = AF_INET6; 1174914bffb6SAlexander V. Chernikov memcpy(&tfe->a.a6.sip6, &tmp, 16); 1175914bffb6SAlexander V. Chernikov } 1176914bffb6SAlexander V. Chernikov 1177914bffb6SAlexander V. Chernikov arg = p; 1178914bffb6SAlexander V. Chernikov } 1179914bffb6SAlexander V. Chernikov 1180914bffb6SAlexander V. Chernikov /* Handle <proto-num|proto-name> */ 1181914bffb6SAlexander V. Chernikov if ((tflags & IPFW_TFFLAG_PROTO) != 0) { 1182914bffb6SAlexander V. Chernikov if ((p = strchr(arg, ',')) != NULL) 1183914bffb6SAlexander V. Chernikov *p++ = '\0'; 1184914bffb6SAlexander V. Chernikov 1185914bffb6SAlexander V. Chernikov key = strtol(arg, &pp, 10); 1186914bffb6SAlexander V. Chernikov if (*pp != '\0') { 1187914bffb6SAlexander V. Chernikov if ((pent = getprotobyname(arg)) == NULL) 1188914bffb6SAlexander V. Chernikov errx(EX_DATAERR, "Unknown proto: %s", 1189914bffb6SAlexander V. Chernikov arg); 1190914bffb6SAlexander V. Chernikov else 1191914bffb6SAlexander V. Chernikov key = pent->p_proto; 1192914bffb6SAlexander V. Chernikov } 1193914bffb6SAlexander V. Chernikov 1194914bffb6SAlexander V. Chernikov if (key > 255) 1195914bffb6SAlexander V. Chernikov errx(EX_DATAERR, "Bad protocol number: %u",key); 1196914bffb6SAlexander V. Chernikov 1197914bffb6SAlexander V. Chernikov tfe->proto = key; 1198914bffb6SAlexander V. Chernikov 1199914bffb6SAlexander V. Chernikov arg = p; 1200914bffb6SAlexander V. Chernikov } 1201914bffb6SAlexander V. Chernikov 1202914bffb6SAlexander V. Chernikov /* Handle <port-num|service-name> */ 1203914bffb6SAlexander V. Chernikov if ((tflags & IPFW_TFFLAG_SRCPORT) != 0) { 1204914bffb6SAlexander V. Chernikov if ((p = strchr(arg, ',')) != NULL) 1205914bffb6SAlexander V. Chernikov *p++ = '\0'; 1206914bffb6SAlexander V. Chernikov 1207914bffb6SAlexander V. Chernikov if ((port = htons(strtol(arg, NULL, 10))) == 0) { 1208914bffb6SAlexander V. Chernikov if ((sent = getservbyname(arg, NULL)) == NULL) 1209914bffb6SAlexander V. Chernikov errx(EX_DATAERR, "Unknown service: %s", 1210914bffb6SAlexander V. Chernikov arg); 1211914bffb6SAlexander V. Chernikov else 1212914bffb6SAlexander V. Chernikov key = sent->s_port; 1213914bffb6SAlexander V. Chernikov } 1214914bffb6SAlexander V. Chernikov 1215914bffb6SAlexander V. Chernikov tfe->sport = port; 1216914bffb6SAlexander V. Chernikov 1217914bffb6SAlexander V. Chernikov arg = p; 1218914bffb6SAlexander V. Chernikov } 1219914bffb6SAlexander V. Chernikov 1220914bffb6SAlexander V. Chernikov /* Handle <ipv4|ipv6>*/ 1221914bffb6SAlexander V. Chernikov if ((tflags & IPFW_TFFLAG_DSTIP) != 0) { 1222914bffb6SAlexander V. Chernikov if ((p = strchr(arg, ',')) != NULL) 1223914bffb6SAlexander V. Chernikov *p++ = '\0'; 1224914bffb6SAlexander V. Chernikov /* Determine family using temporary storage */ 1225914bffb6SAlexander V. Chernikov if (inet_pton(AF_INET, arg, &tmp) == 1) { 1226914bffb6SAlexander V. Chernikov if (af != 0 && af != AF_INET) 1227914bffb6SAlexander V. Chernikov errx(EX_DATAERR, 1228914bffb6SAlexander V. Chernikov "Inconsistent address family"); 1229914bffb6SAlexander V. Chernikov af = AF_INET; 1230914bffb6SAlexander V. Chernikov memcpy(&tfe->a.a4.dip, &tmp, 4); 1231914bffb6SAlexander V. Chernikov } else if (inet_pton(AF_INET6, arg, &tmp) == 1) { 1232914bffb6SAlexander V. Chernikov if (af != 0 && af != AF_INET6) 1233914bffb6SAlexander V. Chernikov errx(EX_DATAERR, 1234914bffb6SAlexander V. Chernikov "Inconsistent address family"); 1235914bffb6SAlexander V. Chernikov af = AF_INET6; 1236914bffb6SAlexander V. Chernikov memcpy(&tfe->a.a6.dip6, &tmp, 16); 1237914bffb6SAlexander V. Chernikov } 1238914bffb6SAlexander V. Chernikov 1239914bffb6SAlexander V. Chernikov arg = p; 1240914bffb6SAlexander V. Chernikov } 1241914bffb6SAlexander V. Chernikov 1242914bffb6SAlexander V. Chernikov /* Handle <port-num|service-name> */ 1243914bffb6SAlexander V. Chernikov if ((tflags & IPFW_TFFLAG_DSTPORT) != 0) { 1244914bffb6SAlexander V. Chernikov if ((p = strchr(arg, ',')) != NULL) 1245914bffb6SAlexander V. Chernikov *p++ = '\0'; 1246914bffb6SAlexander V. Chernikov 1247914bffb6SAlexander V. Chernikov if ((port = htons(strtol(arg, NULL, 10))) == 0) { 1248914bffb6SAlexander V. Chernikov if ((sent = getservbyname(arg, NULL)) == NULL) 1249914bffb6SAlexander V. Chernikov errx(EX_DATAERR, "Unknown service: %s", 1250914bffb6SAlexander V. Chernikov arg); 1251914bffb6SAlexander V. Chernikov else 1252914bffb6SAlexander V. Chernikov key = sent->s_port; 1253914bffb6SAlexander V. Chernikov } 1254914bffb6SAlexander V. Chernikov 1255914bffb6SAlexander V. Chernikov tfe->dport = port; 1256914bffb6SAlexander V. Chernikov 1257914bffb6SAlexander V. Chernikov arg = p; 1258914bffb6SAlexander V. Chernikov } 1259914bffb6SAlexander V. Chernikov 1260914bffb6SAlexander V. Chernikov tfe->af = af; 1261914bffb6SAlexander V. Chernikov 1262914bffb6SAlexander V. Chernikov break; 1263914bffb6SAlexander V. Chernikov 1264ac35ff17SAlexander V. Chernikov default: 1265ac35ff17SAlexander V. Chernikov errx(EX_DATAERR, "Unsupported table type: %d", type); 1266ac35ff17SAlexander V. Chernikov } 1267ac35ff17SAlexander V. Chernikov 1268ac35ff17SAlexander V. Chernikov tentry->subtype = af; 1269ac35ff17SAlexander V. Chernikov tentry->masklen = masklen; 1270ac35ff17SAlexander V. Chernikov } 1271ac35ff17SAlexander V. Chernikov 1272ac35ff17SAlexander V. Chernikov static void 1273ac35ff17SAlexander V. Chernikov tentry_fill_key(ipfw_obj_header *oh, ipfw_obj_tentry *tent, char *key, 127481d3153dSAlexander V. Chernikov uint8_t *ptype, uint8_t *pvtype, ipfw_xtable_info *xi) 1275ac35ff17SAlexander V. Chernikov { 1276914bffb6SAlexander V. Chernikov uint8_t type, tflags, vtype; 1277ac35ff17SAlexander V. Chernikov int error; 1278db785d31SAlexander V. Chernikov char *del; 1279ac35ff17SAlexander V. Chernikov 1280ac35ff17SAlexander V. Chernikov type = 0; 1281914bffb6SAlexander V. Chernikov tflags = 0; 1282ac35ff17SAlexander V. Chernikov vtype = 0; 1283ac35ff17SAlexander V. Chernikov 1284*3a845e10SAlexander V. Chernikov if (xi->tablename[0] == '\0') 128581d3153dSAlexander V. Chernikov error = table_get_info(oh, xi); 1286*3a845e10SAlexander V. Chernikov else 1287*3a845e10SAlexander V. Chernikov error = 0; 128881d3153dSAlexander V. Chernikov 128981d3153dSAlexander V. Chernikov if (error == 0) { 129081d3153dSAlexander V. Chernikov /* Table found. */ 129181d3153dSAlexander V. Chernikov type = xi->type; 1292914bffb6SAlexander V. Chernikov tflags = xi->tflags; 129381d3153dSAlexander V. Chernikov vtype = xi->vtype; 129481d3153dSAlexander V. Chernikov } else { 129581d3153dSAlexander V. Chernikov if (error != ESRCH) 129681d3153dSAlexander V. Chernikov errx(EX_OSERR, "Error requesting table %s info", 129781d3153dSAlexander V. Chernikov oh->ntlv.name); 1298ac35ff17SAlexander V. Chernikov /* 129981d3153dSAlexander V. Chernikov * Table does not exist. 130081d3153dSAlexander V. Chernikov * Compability layer: try to interpret data as CIDR 130181d3153dSAlexander V. Chernikov * before failing. 1302ac35ff17SAlexander V. Chernikov */ 1303db785d31SAlexander V. Chernikov if ((del = strchr(key, '/')) != NULL) 1304db785d31SAlexander V. Chernikov *del = '\0'; 1305ac35ff17SAlexander V. Chernikov if (inet_pton(AF_INET, key, &tent->k.addr6) == 1 || 1306ac35ff17SAlexander V. Chernikov inet_pton(AF_INET6, key, &tent->k.addr6) == 1) { 1307ac35ff17SAlexander V. Chernikov /* OK Prepare and send */ 1308ac35ff17SAlexander V. Chernikov type = IPFW_TABLE_CIDR; 1309ac35ff17SAlexander V. Chernikov /* 131081d3153dSAlexander V. Chernikov * XXX: Value type is forced to be u32. 131181d3153dSAlexander V. Chernikov * This should be changed for MFC. 1312ac35ff17SAlexander V. Chernikov */ 131381d3153dSAlexander V. Chernikov vtype = IPFW_VTYPE_U32; 131481d3153dSAlexander V. Chernikov } else { 131581d3153dSAlexander V. Chernikov /* Inknown key */ 131681d3153dSAlexander V. Chernikov errx(EX_USAGE, "Table %s does not exist, cannot guess " 1317db785d31SAlexander V. Chernikov "key '%s' type", oh->ntlv.name, key); 131881d3153dSAlexander V. Chernikov } 1319db785d31SAlexander V. Chernikov if (del != NULL) 1320db785d31SAlexander V. Chernikov *del = '/'; 1321ac35ff17SAlexander V. Chernikov } 1322ac35ff17SAlexander V. Chernikov 1323914bffb6SAlexander V. Chernikov tentry_fill_key_type(key, tent, type, tflags); 1324ac35ff17SAlexander V. Chernikov 1325ac35ff17SAlexander V. Chernikov *ptype = type; 1326ac35ff17SAlexander V. Chernikov *pvtype = vtype; 1327ac35ff17SAlexander V. Chernikov } 1328ac35ff17SAlexander V. Chernikov 1329ac35ff17SAlexander V. Chernikov static void 1330ac35ff17SAlexander V. Chernikov tentry_fill_value(ipfw_obj_header *oh, ipfw_obj_tentry *tent, char *arg, 1331ac35ff17SAlexander V. Chernikov uint8_t type, uint8_t vtype) 1332ac35ff17SAlexander V. Chernikov { 1333adf3b2b9SAlexander V. Chernikov uint32_t val; 1334ac35ff17SAlexander V. Chernikov char *p; 1335ac35ff17SAlexander V. Chernikov 1336adf3b2b9SAlexander V. Chernikov /* Try to interpret as number first */ 1337adf3b2b9SAlexander V. Chernikov tent->value = strtoul(arg, &p, 0); 1338adf3b2b9SAlexander V. Chernikov if (*p == '\0') 1339adf3b2b9SAlexander V. Chernikov return; 1340adf3b2b9SAlexander V. Chernikov if (inet_pton(AF_INET, arg, &val) == 1) { 1341adf3b2b9SAlexander V. Chernikov tent->value = ntohl(val); 1342adf3b2b9SAlexander V. Chernikov return; 1343adf3b2b9SAlexander V. Chernikov } 1344adf3b2b9SAlexander V. Chernikov /* Try hostname */ 1345adf3b2b9SAlexander V. Chernikov if (lookup_host(arg, (struct in_addr *)&tent->value) == 0) 1346adf3b2b9SAlexander V. Chernikov return; 1347adf3b2b9SAlexander V. Chernikov errx(EX_OSERR, "Unable to parse value %s", arg); 1348adf3b2b9SAlexander V. Chernikov #if 0 1349ac35ff17SAlexander V. Chernikov switch (vtype) { 1350ac35ff17SAlexander V. Chernikov case IPFW_VTYPE_U32: 1351ac35ff17SAlexander V. Chernikov tent->value = strtoul(arg, &p, 0); 1352ac35ff17SAlexander V. Chernikov if (*p != '\0') 1353ac35ff17SAlexander V. Chernikov errx(EX_USAGE, "Invalid number: %s", arg); 1354ac35ff17SAlexander V. Chernikov break; 1355ac35ff17SAlexander V. Chernikov case IPFW_VTYPE_IP: 1356ac35ff17SAlexander V. Chernikov if (inet_pton(AF_INET, arg, &tent->value) == 1) 1357ac35ff17SAlexander V. Chernikov break; 1358ac35ff17SAlexander V. Chernikov /* Try hostname */ 1359ac35ff17SAlexander V. Chernikov if (lookup_host(arg, (struct in_addr *)&tent->value) != 0) 1360ac35ff17SAlexander V. Chernikov errx(EX_USAGE, "Invalid IPv4 address: %s", arg); 1361ac35ff17SAlexander V. Chernikov break; 1362ac35ff17SAlexander V. Chernikov case IPFW_VTYPE_DSCP: 1363ac35ff17SAlexander V. Chernikov if (isalpha(*arg)) { 1364ac35ff17SAlexander V. Chernikov if ((code = match_token(f_ipdscp, arg)) == -1) 1365ac35ff17SAlexander V. Chernikov errx(EX_DATAERR, "Unknown DSCP code"); 1366ac35ff17SAlexander V. Chernikov } else { 1367ac35ff17SAlexander V. Chernikov code = strtoul(arg, NULL, 10); 1368ac35ff17SAlexander V. Chernikov if (code < 0 || code > 63) 1369ac35ff17SAlexander V. Chernikov errx(EX_DATAERR, "Invalid DSCP value"); 1370ac35ff17SAlexander V. Chernikov } 1371ac35ff17SAlexander V. Chernikov tent->value = code; 1372ac35ff17SAlexander V. Chernikov break; 1373ac35ff17SAlexander V. Chernikov default: 1374ac35ff17SAlexander V. Chernikov errx(EX_OSERR, "Unsupported format type %d", vtype); 1375ac35ff17SAlexander V. Chernikov } 1376adf3b2b9SAlexander V. Chernikov #endif 1377ac35ff17SAlexander V. Chernikov } 1378f1220db8SAlexander V. Chernikov 1379f1220db8SAlexander V. Chernikov /* 1380f1220db8SAlexander V. Chernikov * Compare table names. 1381f1220db8SAlexander V. Chernikov * Honor number comparison. 1382f1220db8SAlexander V. Chernikov */ 1383f1220db8SAlexander V. Chernikov static int 1384f1220db8SAlexander V. Chernikov tablename_cmp(const void *a, const void *b) 1385f1220db8SAlexander V. Chernikov { 1386f1220db8SAlexander V. Chernikov ipfw_xtable_info *ia, *ib; 1387f1220db8SAlexander V. Chernikov 1388f1220db8SAlexander V. Chernikov ia = (ipfw_xtable_info *)a; 1389f1220db8SAlexander V. Chernikov ib = (ipfw_xtable_info *)b; 1390f1220db8SAlexander V. Chernikov 139168394ec8SAlexander V. Chernikov return (stringnum_cmp(ia->tablename, ib->tablename)); 1392f1220db8SAlexander V. Chernikov } 1393f1220db8SAlexander V. Chernikov 1394f1220db8SAlexander V. Chernikov /* 1395f1220db8SAlexander V. Chernikov * Retrieves table list from kernel, 1396f1220db8SAlexander V. Chernikov * optionally sorts it and calls requested function for each table. 1397f1220db8SAlexander V. Chernikov * Returns 0 on success. 1398f1220db8SAlexander V. Chernikov */ 1399f1220db8SAlexander V. Chernikov static int 1400f1220db8SAlexander V. Chernikov tables_foreach(table_cb_t *f, void *arg, int sort) 1401f1220db8SAlexander V. Chernikov { 140228ea4fa3SAlexander V. Chernikov ipfw_obj_lheader *olh; 1403f1220db8SAlexander V. Chernikov ipfw_xtable_info *info; 1404f1220db8SAlexander V. Chernikov size_t sz; 1405f1220db8SAlexander V. Chernikov int i, error; 1406f1220db8SAlexander V. Chernikov 140728ea4fa3SAlexander V. Chernikov /* Start with reasonable default */ 140828ea4fa3SAlexander V. Chernikov sz = sizeof(*olh) + 16 * sizeof(ipfw_xtable_info); 1409f1220db8SAlexander V. Chernikov 141028ea4fa3SAlexander V. Chernikov for (;;) { 1411f1220db8SAlexander V. Chernikov if ((olh = calloc(1, sz)) == NULL) 1412f1220db8SAlexander V. Chernikov return (ENOMEM); 1413f1220db8SAlexander V. Chernikov 1414f1220db8SAlexander V. Chernikov olh->size = sz; 141528ea4fa3SAlexander V. Chernikov error = do_get3(IP_FW_TABLES_XLIST, &olh->opheader, &sz); 141628ea4fa3SAlexander V. Chernikov if (error == ENOMEM) { 141728ea4fa3SAlexander V. Chernikov sz = olh->size; 1418f1220db8SAlexander V. Chernikov free(olh); 141928ea4fa3SAlexander V. Chernikov continue; 142028ea4fa3SAlexander V. Chernikov } else if (error != 0) { 142128ea4fa3SAlexander V. Chernikov free(olh); 142228ea4fa3SAlexander V. Chernikov return (error); 1423f1220db8SAlexander V. Chernikov } 1424f1220db8SAlexander V. Chernikov 1425f1220db8SAlexander V. Chernikov if (sort != 0) 1426f1220db8SAlexander V. Chernikov qsort(olh + 1, olh->count, olh->objsize, tablename_cmp); 1427f1220db8SAlexander V. Chernikov 1428f1220db8SAlexander V. Chernikov info = (ipfw_xtable_info *)(olh + 1); 1429f1220db8SAlexander V. Chernikov for (i = 0; i < olh->count; i++) { 1430f1220db8SAlexander V. Chernikov error = f(info, arg); /* Ignore errors for now */ 1431f1220db8SAlexander V. Chernikov info = (ipfw_xtable_info *)((caddr_t)info + olh->objsize); 1432f1220db8SAlexander V. Chernikov } 1433f1220db8SAlexander V. Chernikov 1434f1220db8SAlexander V. Chernikov free(olh); 143528ea4fa3SAlexander V. Chernikov break; 143628ea4fa3SAlexander V. Chernikov } 1437f1220db8SAlexander V. Chernikov 1438f1220db8SAlexander V. Chernikov return (0); 1439f1220db8SAlexander V. Chernikov } 1440f1220db8SAlexander V. Chernikov 144128ea4fa3SAlexander V. Chernikov 1442f1220db8SAlexander V. Chernikov /* 1443f1220db8SAlexander V. Chernikov * Retrieves all entries for given table @i in 1444720ee730SAlexander V. Chernikov * eXtended format. Allocate buffer large enough 1445720ee730SAlexander V. Chernikov * to store result. Called needs to free it later. 1446f1220db8SAlexander V. Chernikov * 1447f1220db8SAlexander V. Chernikov * Returns 0 on success. 1448f1220db8SAlexander V. Chernikov */ 1449f1220db8SAlexander V. Chernikov static int 1450720ee730SAlexander V. Chernikov table_do_get_list(ipfw_xtable_info *i, ipfw_obj_header **poh) 1451f1220db8SAlexander V. Chernikov { 1452720ee730SAlexander V. Chernikov ipfw_obj_header *oh; 1453f1220db8SAlexander V. Chernikov size_t sz; 145481d3153dSAlexander V. Chernikov int error, c; 1455f1220db8SAlexander V. Chernikov 145681d3153dSAlexander V. Chernikov sz = 0; 1457720ee730SAlexander V. Chernikov oh = NULL; 1458720ee730SAlexander V. Chernikov error = 0; 1459720ee730SAlexander V. Chernikov for (c = 0; c < 8; c++) { 146081d3153dSAlexander V. Chernikov if (sz < i->size) 1461720ee730SAlexander V. Chernikov sz = i->size + 44; 1462720ee730SAlexander V. Chernikov if (oh != NULL) 1463720ee730SAlexander V. Chernikov free(oh); 1464720ee730SAlexander V. Chernikov if ((oh = calloc(1, sz)) == NULL) 1465720ee730SAlexander V. Chernikov continue; 1466720ee730SAlexander V. Chernikov table_fill_objheader(oh, i); 1467d3a4f924SAlexander V. Chernikov oh->opheader.version = 1; /* Current version */ 146881d3153dSAlexander V. Chernikov error = do_get3(IP_FW_TABLE_XLIST, &oh->opheader, &sz); 1469d3a4f924SAlexander V. Chernikov 1470720ee730SAlexander V. Chernikov if (error == 0) { 1471720ee730SAlexander V. Chernikov *poh = oh; 1472720ee730SAlexander V. Chernikov return (0); 147381d3153dSAlexander V. Chernikov } 1474f1220db8SAlexander V. Chernikov 1475720ee730SAlexander V. Chernikov if (error != ENOMEM) 1476720ee730SAlexander V. Chernikov break; 1477720ee730SAlexander V. Chernikov } 1478720ee730SAlexander V. Chernikov free(oh); 1479720ee730SAlexander V. Chernikov 1480720ee730SAlexander V. Chernikov return (error); 1481f1220db8SAlexander V. Chernikov } 1482f1220db8SAlexander V. Chernikov 1483f1220db8SAlexander V. Chernikov /* 1484f1220db8SAlexander V. Chernikov * Shows all entries from @oh in human-readable format 1485f1220db8SAlexander V. Chernikov */ 1486f1220db8SAlexander V. Chernikov static void 1487f1220db8SAlexander V. Chernikov table_show_list(ipfw_obj_header *oh, int need_header) 1488f1220db8SAlexander V. Chernikov { 148981d3153dSAlexander V. Chernikov ipfw_obj_tentry *tent; 149081d3153dSAlexander V. Chernikov uint32_t count; 1491f1220db8SAlexander V. Chernikov ipfw_xtable_info *i; 1492f1220db8SAlexander V. Chernikov 1493f1220db8SAlexander V. Chernikov i = (ipfw_xtable_info *)(oh + 1); 149481d3153dSAlexander V. Chernikov tent = (ipfw_obj_tentry *)(i + 1); 1495f1220db8SAlexander V. Chernikov 1496f1220db8SAlexander V. Chernikov if (need_header) 1497f1220db8SAlexander V. Chernikov printf("--- table(%s), set(%u) ---\n", i->tablename, i->set); 1498f1220db8SAlexander V. Chernikov 1499f1220db8SAlexander V. Chernikov count = i->count; 1500f1220db8SAlexander V. Chernikov while (count > 0) { 150181d3153dSAlexander V. Chernikov table_show_entry(i, tent); 150281d3153dSAlexander V. Chernikov tent = (ipfw_obj_tentry *)((caddr_t)tent + tent->head.length); 150381d3153dSAlexander V. Chernikov count--; 150481d3153dSAlexander V. Chernikov } 150581d3153dSAlexander V. Chernikov } 150681d3153dSAlexander V. Chernikov 150781d3153dSAlexander V. Chernikov static void 150881d3153dSAlexander V. Chernikov table_show_entry(ipfw_xtable_info *i, ipfw_obj_tentry *tent) 150981d3153dSAlexander V. Chernikov { 1510914bffb6SAlexander V. Chernikov char *comma, tbuf[128], pval[32]; 1511914bffb6SAlexander V. Chernikov void *paddr; 151281d3153dSAlexander V. Chernikov uint32_t tval; 1513914bffb6SAlexander V. Chernikov struct tflow_entry *tfe; 151481d3153dSAlexander V. Chernikov 151581d3153dSAlexander V. Chernikov tval = tent->value; 151681d3153dSAlexander V. Chernikov 1517adf3b2b9SAlexander V. Chernikov if (co.do_value_as_ip || i->vftype == IPFW_VFTYPE_IP) { 1518914bffb6SAlexander V. Chernikov tval = htonl(tval); 1519914bffb6SAlexander V. Chernikov inet_ntop(AF_INET, &tval, pval, sizeof(pval)); 1520914bffb6SAlexander V. Chernikov } else 1521914bffb6SAlexander V. Chernikov snprintf(pval, sizeof(pval), "%u", tval); 1522914bffb6SAlexander V. Chernikov 1523f1220db8SAlexander V. Chernikov switch (i->type) { 1524f1220db8SAlexander V. Chernikov case IPFW_TABLE_CIDR: 1525f1220db8SAlexander V. Chernikov /* IPv4 or IPv6 prefixes */ 152681d3153dSAlexander V. Chernikov inet_ntop(tent->subtype, &tent->k, tbuf, sizeof(tbuf)); 1527914bffb6SAlexander V. Chernikov printf("%s/%u %s\n", tbuf, tent->masklen, pval); 1528f1220db8SAlexander V. Chernikov break; 1529f1220db8SAlexander V. Chernikov case IPFW_TABLE_INTERFACE: 1530f1220db8SAlexander V. Chernikov /* Interface names */ 1531914bffb6SAlexander V. Chernikov printf("%s %s\n", tent->k.iface, pval); 1532b23d5de9SAlexander V. Chernikov break; 1533b23d5de9SAlexander V. Chernikov case IPFW_TABLE_NUMBER: 1534b23d5de9SAlexander V. Chernikov /* numbers */ 1535914bffb6SAlexander V. Chernikov printf("%u %s\n", tent->k.key, pval); 1536b23d5de9SAlexander V. Chernikov break; 1537914bffb6SAlexander V. Chernikov case IPFW_TABLE_FLOW: 1538914bffb6SAlexander V. Chernikov /* flows */ 1539914bffb6SAlexander V. Chernikov tfe = &tent->k.flow; 1540914bffb6SAlexander V. Chernikov comma = ""; 1541914bffb6SAlexander V. Chernikov 1542914bffb6SAlexander V. Chernikov if ((i->tflags & IPFW_TFFLAG_SRCIP) != 0) { 1543914bffb6SAlexander V. Chernikov if (tfe->af == AF_INET) 1544914bffb6SAlexander V. Chernikov paddr = &tfe->a.a4.sip; 1545914bffb6SAlexander V. Chernikov else 1546914bffb6SAlexander V. Chernikov paddr = &tfe->a.a6.sip6; 1547914bffb6SAlexander V. Chernikov 1548914bffb6SAlexander V. Chernikov inet_ntop(tfe->af, paddr, tbuf, sizeof(tbuf)); 1549914bffb6SAlexander V. Chernikov printf("%s%s", comma, tbuf); 1550914bffb6SAlexander V. Chernikov comma = ","; 1551914bffb6SAlexander V. Chernikov } 1552914bffb6SAlexander V. Chernikov 1553914bffb6SAlexander V. Chernikov if ((i->tflags & IPFW_TFFLAG_PROTO) != 0) { 1554914bffb6SAlexander V. Chernikov printf("%s%d", comma, tfe->proto); 1555914bffb6SAlexander V. Chernikov comma = ","; 1556914bffb6SAlexander V. Chernikov } 1557914bffb6SAlexander V. Chernikov 1558914bffb6SAlexander V. Chernikov if ((i->tflags & IPFW_TFFLAG_SRCPORT) != 0) { 1559914bffb6SAlexander V. Chernikov printf("%s%d", comma, ntohs(tfe->sport)); 1560914bffb6SAlexander V. Chernikov comma = ","; 1561914bffb6SAlexander V. Chernikov } 1562914bffb6SAlexander V. Chernikov if ((i->tflags & IPFW_TFFLAG_DSTIP) != 0) { 1563914bffb6SAlexander V. Chernikov if (tfe->af == AF_INET) 1564914bffb6SAlexander V. Chernikov paddr = &tfe->a.a4.dip; 1565914bffb6SAlexander V. Chernikov else 1566914bffb6SAlexander V. Chernikov paddr = &tfe->a.a6.dip6; 1567914bffb6SAlexander V. Chernikov 1568914bffb6SAlexander V. Chernikov inet_ntop(tfe->af, paddr, tbuf, sizeof(tbuf)); 1569914bffb6SAlexander V. Chernikov printf("%s%s", comma, tbuf); 1570914bffb6SAlexander V. Chernikov comma = ","; 1571914bffb6SAlexander V. Chernikov } 1572914bffb6SAlexander V. Chernikov 1573914bffb6SAlexander V. Chernikov if ((i->tflags & IPFW_TFFLAG_DSTPORT) != 0) { 1574914bffb6SAlexander V. Chernikov printf("%s%d", comma, ntohs(tfe->dport)); 1575914bffb6SAlexander V. Chernikov comma = ","; 1576914bffb6SAlexander V. Chernikov } 1577914bffb6SAlexander V. Chernikov 1578914bffb6SAlexander V. Chernikov printf(" %s\n", pval); 1579f1220db8SAlexander V. Chernikov } 1580f1220db8SAlexander V. Chernikov } 1581f1220db8SAlexander V. Chernikov 15829d099b4fSAlexander V. Chernikov static int 15839d099b4fSAlexander V. Chernikov table_do_get_algolist(ipfw_obj_lheader **polh) 15849d099b4fSAlexander V. Chernikov { 15859d099b4fSAlexander V. Chernikov ipfw_obj_lheader req, *olh; 15869d099b4fSAlexander V. Chernikov size_t sz; 15879d099b4fSAlexander V. Chernikov int error; 15889d099b4fSAlexander V. Chernikov 15899d099b4fSAlexander V. Chernikov memset(&req, 0, sizeof(req)); 15909d099b4fSAlexander V. Chernikov sz = sizeof(req); 15919d099b4fSAlexander V. Chernikov 15929d099b4fSAlexander V. Chernikov error = do_get3(IP_FW_TABLES_ALIST, &req.opheader, &sz); 15939d099b4fSAlexander V. Chernikov if (error != 0 && error != ENOMEM) 15949d099b4fSAlexander V. Chernikov return (error); 15959d099b4fSAlexander V. Chernikov 15969d099b4fSAlexander V. Chernikov sz = req.size; 15979d099b4fSAlexander V. Chernikov if ((olh = calloc(1, sz)) == NULL) 15989d099b4fSAlexander V. Chernikov return (ENOMEM); 15999d099b4fSAlexander V. Chernikov 16009d099b4fSAlexander V. Chernikov olh->size = sz; 16019d099b4fSAlexander V. Chernikov if ((error = do_get3(IP_FW_TABLES_ALIST, &olh->opheader, &sz)) != 0) { 16029d099b4fSAlexander V. Chernikov free(olh); 16039d099b4fSAlexander V. Chernikov return (error); 16049d099b4fSAlexander V. Chernikov } 16059d099b4fSAlexander V. Chernikov 16069d099b4fSAlexander V. Chernikov *polh = olh; 16079d099b4fSAlexander V. Chernikov return (0); 16089d099b4fSAlexander V. Chernikov } 16099d099b4fSAlexander V. Chernikov 16109d099b4fSAlexander V. Chernikov void 16119d099b4fSAlexander V. Chernikov ipfw_list_ta(int ac, char *av[]) 16129d099b4fSAlexander V. Chernikov { 16139d099b4fSAlexander V. Chernikov ipfw_obj_lheader *olh; 16149d099b4fSAlexander V. Chernikov ipfw_ta_info *info; 16159d099b4fSAlexander V. Chernikov int error, i; 16169d099b4fSAlexander V. Chernikov const char *atype; 16179d099b4fSAlexander V. Chernikov 16189d099b4fSAlexander V. Chernikov error = table_do_get_algolist(&olh); 16199d099b4fSAlexander V. Chernikov if (error != 0) 16209d099b4fSAlexander V. Chernikov err(EX_OSERR, "Unable to request algorithm list"); 16219d099b4fSAlexander V. Chernikov 16229d099b4fSAlexander V. Chernikov info = (ipfw_ta_info *)(olh + 1); 16239d099b4fSAlexander V. Chernikov for (i = 0; i < olh->count; i++) { 16249d099b4fSAlexander V. Chernikov if ((atype = match_value(tabletypes, info->type)) == NULL) 16259d099b4fSAlexander V. Chernikov atype = "unknown"; 16268ce7a2bcSAlexander V. Chernikov printf("--- %s ---\n", info->algoname); 16278ce7a2bcSAlexander V. Chernikov printf(" type: %s\n refcount: %u\n", atype, info->refcnt); 16289d099b4fSAlexander V. Chernikov 16299d099b4fSAlexander V. Chernikov info = (ipfw_ta_info *)((caddr_t)info + olh->objsize); 16309d099b4fSAlexander V. Chernikov } 16319d099b4fSAlexander V. Chernikov 16329d099b4fSAlexander V. Chernikov free(olh); 16339d099b4fSAlexander V. Chernikov } 16349d099b4fSAlexander V. Chernikov 16356c2997ffSAlexander V. Chernikov int 16366c2997ffSAlexander V. Chernikov compare_ntlv(const void *_a, const void *_b) 16376c2997ffSAlexander V. Chernikov { 16386c2997ffSAlexander V. Chernikov ipfw_obj_ntlv *a, *b; 16396c2997ffSAlexander V. Chernikov 16406c2997ffSAlexander V. Chernikov a = (ipfw_obj_ntlv *)_a; 16416c2997ffSAlexander V. Chernikov b = (ipfw_obj_ntlv *)_b; 16426c2997ffSAlexander V. Chernikov 16436c2997ffSAlexander V. Chernikov if (a->set < b->set) 16446c2997ffSAlexander V. Chernikov return (-1); 16456c2997ffSAlexander V. Chernikov else if (a->set > b->set) 16466c2997ffSAlexander V. Chernikov return (1); 16476c2997ffSAlexander V. Chernikov 16486c2997ffSAlexander V. Chernikov if (a->idx < b->idx) 16496c2997ffSAlexander V. Chernikov return (-1); 16506c2997ffSAlexander V. Chernikov else if (a->idx > b->idx) 16516c2997ffSAlexander V. Chernikov return (1); 16526c2997ffSAlexander V. Chernikov 16536c2997ffSAlexander V. Chernikov return (0); 16546c2997ffSAlexander V. Chernikov } 1655563b5ab1SAlexander V. Chernikov 1656563b5ab1SAlexander V. Chernikov int 16576c2997ffSAlexander V. Chernikov compare_kntlv(const void *k, const void *v) 1658563b5ab1SAlexander V. Chernikov { 1659563b5ab1SAlexander V. Chernikov ipfw_obj_ntlv *ntlv; 1660563b5ab1SAlexander V. Chernikov uint16_t key; 1661563b5ab1SAlexander V. Chernikov 1662563b5ab1SAlexander V. Chernikov key = *((uint16_t *)k); 1663563b5ab1SAlexander V. Chernikov ntlv = (ipfw_obj_ntlv *)v; 1664563b5ab1SAlexander V. Chernikov 1665563b5ab1SAlexander V. Chernikov if (key < ntlv->idx) 1666563b5ab1SAlexander V. Chernikov return (-1); 1667563b5ab1SAlexander V. Chernikov else if (key > ntlv->idx) 1668563b5ab1SAlexander V. Chernikov return (1); 1669563b5ab1SAlexander V. Chernikov 1670563b5ab1SAlexander V. Chernikov return (0); 1671563b5ab1SAlexander V. Chernikov } 1672563b5ab1SAlexander V. Chernikov 1673563b5ab1SAlexander V. Chernikov /* 1674563b5ab1SAlexander V. Chernikov * Finds table name in @ctlv by @idx. 1675563b5ab1SAlexander V. Chernikov * Uses the following facts: 1676563b5ab1SAlexander V. Chernikov * 1) All TLVs are the same size 1677563b5ab1SAlexander V. Chernikov * 2) Kernel implementation provides already sorted list. 1678563b5ab1SAlexander V. Chernikov * 1679563b5ab1SAlexander V. Chernikov * Returns table name or NULL. 1680563b5ab1SAlexander V. Chernikov */ 1681563b5ab1SAlexander V. Chernikov char * 1682563b5ab1SAlexander V. Chernikov table_search_ctlv(ipfw_obj_ctlv *ctlv, uint16_t idx) 1683563b5ab1SAlexander V. Chernikov { 1684563b5ab1SAlexander V. Chernikov ipfw_obj_ntlv *ntlv; 1685563b5ab1SAlexander V. Chernikov 1686563b5ab1SAlexander V. Chernikov ntlv = bsearch(&idx, (ctlv + 1), ctlv->count, ctlv->objsize, 16876c2997ffSAlexander V. Chernikov compare_kntlv); 1688563b5ab1SAlexander V. Chernikov 1689563b5ab1SAlexander V. Chernikov if (ntlv != 0) 1690563b5ab1SAlexander V. Chernikov return (ntlv->name); 1691563b5ab1SAlexander V. Chernikov 1692563b5ab1SAlexander V. Chernikov return (NULL); 1693563b5ab1SAlexander V. Chernikov } 1694563b5ab1SAlexander V. Chernikov 16956c2997ffSAlexander V. Chernikov void 16966c2997ffSAlexander V. Chernikov table_sort_ctlv(ipfw_obj_ctlv *ctlv) 16976c2997ffSAlexander V. Chernikov { 16986c2997ffSAlexander V. Chernikov 16996c2997ffSAlexander V. Chernikov qsort(ctlv + 1, ctlv->count, ctlv->objsize, compare_ntlv); 17006c2997ffSAlexander V. Chernikov } 17016c2997ffSAlexander V. Chernikov 17026c2997ffSAlexander V. Chernikov int 17036c2997ffSAlexander V. Chernikov table_check_name(char *tablename) 17046c2997ffSAlexander V. Chernikov { 17056c2997ffSAlexander V. Chernikov int c, i, l; 17066c2997ffSAlexander V. Chernikov 17076c2997ffSAlexander V. Chernikov /* 17086c2997ffSAlexander V. Chernikov * Check if tablename is null-terminated and contains 17096c2997ffSAlexander V. Chernikov * valid symbols only. Valid mask is: 1710ac35ff17SAlexander V. Chernikov * [a-zA-Z0-9\-_\.]{1,63} 17116c2997ffSAlexander V. Chernikov */ 17126c2997ffSAlexander V. Chernikov l = strlen(tablename); 17136c2997ffSAlexander V. Chernikov if (l == 0 || l >= 64) 17146c2997ffSAlexander V. Chernikov return (EINVAL); 17156c2997ffSAlexander V. Chernikov for (i = 0; i < l; i++) { 17166c2997ffSAlexander V. Chernikov c = tablename[i]; 17176c2997ffSAlexander V. Chernikov if (isalpha(c) || isdigit(c) || c == '_' || 17186c2997ffSAlexander V. Chernikov c == '-' || c == '.') 17196c2997ffSAlexander V. Chernikov continue; 17206c2997ffSAlexander V. Chernikov return (EINVAL); 17216c2997ffSAlexander V. Chernikov } 17226c2997ffSAlexander V. Chernikov 1723ac35ff17SAlexander V. Chernikov /* Restrict some 'special' names */ 1724ac35ff17SAlexander V. Chernikov if (strcmp(tablename, "all") == 0) 1725ac35ff17SAlexander V. Chernikov return (EINVAL); 1726ac35ff17SAlexander V. Chernikov 17276c2997ffSAlexander V. Chernikov return (0); 17286c2997ffSAlexander V. Chernikov } 17296c2997ffSAlexander V. Chernikov 1730