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[], 53ac35ff17SAlexander V. Chernikov int add, int update); 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); 57ac35ff17SAlexander V. Chernikov static void table_create(ipfw_obj_header *oh, int ac, char *av[]); 5881d3153dSAlexander V. Chernikov static void table_lookup(ipfw_obj_header *oh, int ac, char *av[]); 59ac35ff17SAlexander V. Chernikov static int table_get_info(ipfw_obj_header *oh, ipfw_xtable_info *i); 60f1220db8SAlexander V. Chernikov static int table_show_info(ipfw_xtable_info *i, void *arg); 61ac35ff17SAlexander V. Chernikov static void table_fill_ntlv(ipfw_obj_ntlv *ntlv, char *name, uint32_t set, 62ac35ff17SAlexander V. Chernikov uint16_t uidx); 63f1220db8SAlexander V. Chernikov 64f1220db8SAlexander V. Chernikov static int table_flush_one(ipfw_xtable_info *i, void *arg); 65f1220db8SAlexander V. Chernikov static int table_show_one(ipfw_xtable_info *i, void *arg); 66f1220db8SAlexander V. Chernikov static int table_get_list(ipfw_xtable_info *i, ipfw_obj_header *oh); 67f1220db8SAlexander V. Chernikov static void table_show_list(ipfw_obj_header *oh, int need_header); 6881d3153dSAlexander V. Chernikov static void table_show_entry(ipfw_xtable_info *i, ipfw_obj_tentry *tent); 69f1220db8SAlexander V. Chernikov 70ac35ff17SAlexander V. Chernikov static void tentry_fill_key(ipfw_obj_header *oh, ipfw_obj_tentry *tent, 7181d3153dSAlexander V. Chernikov char *key, uint8_t *ptype, uint8_t *pvtype, ipfw_xtable_info *xi); 72ac35ff17SAlexander V. Chernikov static void tentry_fill_value(ipfw_obj_header *oh, ipfw_obj_tentry *tent, 73ac35ff17SAlexander V. Chernikov char *arg, uint8_t type, uint8_t vtype); 74ac35ff17SAlexander V. Chernikov 75f1220db8SAlexander V. Chernikov typedef int (table_cb_t)(ipfw_xtable_info *i, void *arg); 76f1220db8SAlexander V. Chernikov static int tables_foreach(table_cb_t *f, void *arg, int sort); 77f1220db8SAlexander V. Chernikov 78f1220db8SAlexander V. Chernikov #ifndef s6_addr32 79f1220db8SAlexander V. Chernikov #define s6_addr32 __u6_addr.__u6_addr32 80f1220db8SAlexander V. Chernikov #endif 81f1220db8SAlexander V. Chernikov 82ac35ff17SAlexander V. Chernikov static struct _s_x tabletypes[] = { 83ac35ff17SAlexander V. Chernikov { "cidr", IPFW_TABLE_CIDR }, 84ac35ff17SAlexander V. Chernikov { "iface", IPFW_TABLE_INTERFACE }, 85b23d5de9SAlexander V. Chernikov { "number", IPFW_TABLE_NUMBER }, 86ac35ff17SAlexander V. Chernikov { NULL, 0 } 87ac35ff17SAlexander V. Chernikov }; 88ac35ff17SAlexander V. Chernikov 89ac35ff17SAlexander V. Chernikov static struct _s_x tablevaltypes[] = { 90ac35ff17SAlexander V. Chernikov { "dscp", IPFW_VTYPE_DSCP }, 91ac35ff17SAlexander V. Chernikov { "ip", IPFW_VTYPE_IP }, 92ac35ff17SAlexander V. Chernikov { "number", IPFW_VTYPE_U32 }, 93ac35ff17SAlexander V. Chernikov { NULL, 0 } 94ac35ff17SAlexander V. Chernikov }; 95ac35ff17SAlexander V. Chernikov 96ac35ff17SAlexander V. Chernikov static struct _s_x tablecmds[] = { 97ac35ff17SAlexander V. Chernikov { "add", TOK_ADD }, 98ac35ff17SAlexander V. Chernikov { "create", TOK_CREATE }, 99ac35ff17SAlexander V. Chernikov { "delete", TOK_DEL }, 100ac35ff17SAlexander V. Chernikov { "destroy", TOK_DESTROY }, 101ac35ff17SAlexander V. Chernikov { "flush", TOK_FLUSH }, 102ac35ff17SAlexander V. Chernikov { "info", TOK_INFO }, 103ac35ff17SAlexander V. Chernikov { "list", TOK_LIST }, 10481d3153dSAlexander V. Chernikov { "lookup", TOK_LOOKUP }, 105ac35ff17SAlexander V. Chernikov { NULL, 0 } 106ac35ff17SAlexander V. Chernikov }; 107ac35ff17SAlexander V. Chernikov 108f1220db8SAlexander V. Chernikov static int 109f1220db8SAlexander V. Chernikov lookup_host (char *host, struct in_addr *ipaddr) 110f1220db8SAlexander V. Chernikov { 111f1220db8SAlexander V. Chernikov struct hostent *he; 112f1220db8SAlexander V. Chernikov 113f1220db8SAlexander V. Chernikov if (!inet_aton(host, ipaddr)) { 114f1220db8SAlexander V. Chernikov if ((he = gethostbyname(host)) == NULL) 115f1220db8SAlexander V. Chernikov return(-1); 116f1220db8SAlexander V. Chernikov *ipaddr = *(struct in_addr *)he->h_addr_list[0]; 117f1220db8SAlexander V. Chernikov } 118f1220db8SAlexander V. Chernikov return(0); 119f1220db8SAlexander V. Chernikov } 120f1220db8SAlexander V. Chernikov 121f1220db8SAlexander V. Chernikov /* 122f1220db8SAlexander V. Chernikov * This one handles all table-related commands 123ac35ff17SAlexander V. Chernikov * ipfw table NAME create ... 124ac35ff17SAlexander V. Chernikov * ipfw table NAME destroy 125ac35ff17SAlexander V. Chernikov * ipfw table NAME add addr[/masklen] [value] 126ac35ff17SAlexander V. Chernikov * ipfw table NAME delete addr[/masklen] 127ac35ff17SAlexander V. Chernikov * ipfw table {NAME | all} flush 128ac35ff17SAlexander V. Chernikov * ipfw table {NAME | all} list 129ac35ff17SAlexander V. Chernikov * ipfw table {NAME | all} info 130f1220db8SAlexander V. Chernikov */ 131f1220db8SAlexander V. Chernikov void 132f1220db8SAlexander V. Chernikov ipfw_table_handler(int ac, char *av[]) 133f1220db8SAlexander V. Chernikov { 134ac35ff17SAlexander V. Chernikov int do_add, is_all; 135ac35ff17SAlexander V. Chernikov int error, tcmd; 136ac35ff17SAlexander V. Chernikov ipfw_xtable_info i; 137ac35ff17SAlexander V. Chernikov ipfw_obj_header oh; 138f1220db8SAlexander V. Chernikov char *tablename; 139ac35ff17SAlexander V. Chernikov uint32_t set; 140f1220db8SAlexander V. Chernikov 141ac35ff17SAlexander V. Chernikov memset(&oh, 0, sizeof(oh)); 142ac35ff17SAlexander V. Chernikov is_all = 0; 143ac35ff17SAlexander V. Chernikov if (co.use_set != 0) 144ac35ff17SAlexander V. Chernikov set = co.use_set - 1; 145ac35ff17SAlexander V. Chernikov else 146ac35ff17SAlexander V. Chernikov set = 0; 147f1220db8SAlexander V. Chernikov 148f1220db8SAlexander V. Chernikov ac--; av++; 1499d099b4fSAlexander V. Chernikov NEED1("table needs name"); 150f1220db8SAlexander V. Chernikov tablename = *av; 151f1220db8SAlexander V. Chernikov 152ac35ff17SAlexander V. Chernikov if (table_check_name(tablename) == 0) { 153ac35ff17SAlexander V. Chernikov table_fill_ntlv(&oh.ntlv, *av, set, 1); 154ac35ff17SAlexander V. Chernikov oh.idx = 1; 155ac35ff17SAlexander V. Chernikov } else { 156ac35ff17SAlexander V. Chernikov if (strcmp(tablename, "all") == 0) 157ac35ff17SAlexander V. Chernikov is_all = 1; 158ac35ff17SAlexander V. Chernikov else 159ac35ff17SAlexander V. Chernikov errx(EX_USAGE, "table name %s is invalid", tablename); 160ac35ff17SAlexander V. Chernikov } 161ac35ff17SAlexander V. Chernikov ac--; av++; 1629d099b4fSAlexander V. Chernikov NEED1("table needs command"); 163ac35ff17SAlexander V. Chernikov 164ac35ff17SAlexander V. Chernikov if ((tcmd = match_token(tablecmds, *av)) == -1) 165ac35ff17SAlexander V. Chernikov errx(EX_USAGE, "invalid table command %s", *av); 166ac35ff17SAlexander V. Chernikov 167ac35ff17SAlexander V. Chernikov switch (tcmd) { 168ac35ff17SAlexander V. Chernikov case TOK_LIST: 169ac35ff17SAlexander V. Chernikov case TOK_INFO: 170ac35ff17SAlexander V. Chernikov case TOK_FLUSH: 171ac35ff17SAlexander V. Chernikov break; 172ac35ff17SAlexander V. Chernikov default: 173ac35ff17SAlexander V. Chernikov if (is_all != 0) 174ac35ff17SAlexander V. Chernikov errx(EX_USAGE, "table name required"); 175ac35ff17SAlexander V. Chernikov } 176ac35ff17SAlexander V. Chernikov 177ac35ff17SAlexander V. Chernikov switch (tcmd) { 178ac35ff17SAlexander V. Chernikov case TOK_ADD: 179ac35ff17SAlexander V. Chernikov case TOK_DEL: 180f1220db8SAlexander V. Chernikov do_add = **av == 'a'; 181f1220db8SAlexander V. Chernikov ac--; av++; 182ac35ff17SAlexander V. Chernikov table_modify_record(&oh, ac, av, do_add, co.do_quiet); 183ac35ff17SAlexander V. Chernikov break; 184ac35ff17SAlexander V. Chernikov case TOK_CREATE: 185f1220db8SAlexander V. Chernikov ac--; av++; 186ac35ff17SAlexander V. Chernikov table_create(&oh, ac, av); 187ac35ff17SAlexander V. Chernikov break; 188ac35ff17SAlexander V. Chernikov case TOK_DESTROY: 189ac35ff17SAlexander V. Chernikov if (table_destroy(&oh) != 0) 190ac35ff17SAlexander V. Chernikov err(EX_OSERR, "failed to destroy table %s", tablename); 191ac35ff17SAlexander V. Chernikov break; 192ac35ff17SAlexander V. Chernikov case TOK_FLUSH: 193f1220db8SAlexander V. Chernikov if (is_all == 0) { 194ac35ff17SAlexander V. Chernikov if ((error = table_flush(&oh)) != 0) 195f1220db8SAlexander V. Chernikov err(EX_OSERR, "failed to flush table %s info", 196f1220db8SAlexander V. Chernikov tablename); 197f1220db8SAlexander V. Chernikov } else { 198ac35ff17SAlexander V. Chernikov error = tables_foreach(table_flush_one, &oh, 1); 199f1220db8SAlexander V. Chernikov if (error != 0) 200f1220db8SAlexander V. Chernikov err(EX_OSERR, "failed to flush tables list"); 201f1220db8SAlexander V. Chernikov } 202ac35ff17SAlexander V. Chernikov break; 203ac35ff17SAlexander V. Chernikov case TOK_INFO: 204f1220db8SAlexander V. Chernikov if (is_all == 0) { 205ac35ff17SAlexander V. Chernikov if ((error = table_get_info(&oh, &i)) != 0) 206f1220db8SAlexander V. Chernikov err(EX_OSERR, "failed to request table info"); 207f1220db8SAlexander V. Chernikov table_show_info(&i, NULL); 208f1220db8SAlexander V. Chernikov } else { 209f1220db8SAlexander V. Chernikov error = tables_foreach(table_show_info, NULL, 1); 210f1220db8SAlexander V. Chernikov if (error != 0) 211f1220db8SAlexander V. Chernikov err(EX_OSERR, "failed to request tables list"); 212f1220db8SAlexander V. Chernikov } 213ac35ff17SAlexander V. Chernikov break; 214ac35ff17SAlexander V. Chernikov case TOK_LIST: 215ac35ff17SAlexander V. Chernikov if (is_all == 0) { 216ac35ff17SAlexander V. Chernikov ipfw_xtable_info i; 217ac35ff17SAlexander V. Chernikov if ((error = table_get_info(&oh, &i)) != 0) 218ac35ff17SAlexander V. Chernikov err(EX_OSERR, "failed to request table info"); 219ac35ff17SAlexander V. Chernikov table_show_one(&i, NULL); 220f1220db8SAlexander V. Chernikov } else { 221ac35ff17SAlexander V. Chernikov error = tables_foreach(table_show_one, NULL, 1); 222ac35ff17SAlexander V. Chernikov if (error != 0) 223ac35ff17SAlexander V. Chernikov err(EX_OSERR, "failed to request tables list"); 224f1220db8SAlexander V. Chernikov } 225ac35ff17SAlexander V. Chernikov break; 22681d3153dSAlexander V. Chernikov case TOK_LOOKUP: 22781d3153dSAlexander V. Chernikov ac--; av++; 22881d3153dSAlexander V. Chernikov table_lookup(&oh, ac, av); 22981d3153dSAlexander V. Chernikov break; 230f1220db8SAlexander V. Chernikov } 231f1220db8SAlexander V. Chernikov } 232f1220db8SAlexander V. Chernikov 233f1220db8SAlexander V. Chernikov static void 234ac35ff17SAlexander V. Chernikov table_fill_ntlv(ipfw_obj_ntlv *ntlv, char *name, uint32_t set, uint16_t uidx) 235f1220db8SAlexander V. Chernikov { 236f1220db8SAlexander V. Chernikov 237563b5ab1SAlexander V. Chernikov ntlv->head.type = IPFW_TLV_TBL_NAME; 238f1220db8SAlexander V. Chernikov ntlv->head.length = sizeof(ipfw_obj_ntlv); 239f1220db8SAlexander V. Chernikov ntlv->idx = uidx; 240ac35ff17SAlexander V. Chernikov ntlv->set = set; 241f1220db8SAlexander V. Chernikov strlcpy(ntlv->name, name, sizeof(ntlv->name)); 242f1220db8SAlexander V. Chernikov } 243f1220db8SAlexander V. Chernikov 244f1220db8SAlexander V. Chernikov static void 245f1220db8SAlexander V. Chernikov table_fill_objheader(ipfw_obj_header *oh, ipfw_xtable_info *i) 246f1220db8SAlexander V. Chernikov { 247f1220db8SAlexander V. Chernikov 248f1220db8SAlexander V. Chernikov oh->idx = 1; 24981d3153dSAlexander V. Chernikov table_fill_ntlv(&oh->ntlv, i->tablename, i->set, 1); 250ac35ff17SAlexander V. Chernikov } 251ac35ff17SAlexander V. Chernikov 252ac35ff17SAlexander V. Chernikov static struct _s_x tablenewcmds[] = { 253ac35ff17SAlexander V. Chernikov { "type", TOK_TYPE}, 254ac35ff17SAlexander V. Chernikov { "valtype", TOK_VALTYPE }, 255ac35ff17SAlexander V. Chernikov { "algo", TOK_ALGO }, 256ac35ff17SAlexander V. Chernikov { NULL, 0 } 257ac35ff17SAlexander V. Chernikov }; 258ac35ff17SAlexander V. Chernikov 259ac35ff17SAlexander V. Chernikov /* 260ac35ff17SAlexander V. Chernikov * Creates new table 261ac35ff17SAlexander V. Chernikov * 262ac35ff17SAlexander V. Chernikov * ipfw table NAME create [ type { cidr | iface | u32 } ] 263ac35ff17SAlexander V. Chernikov * [ valtype { number | ip | dscp } ] 264ac35ff17SAlexander V. Chernikov * [ algo algoname ] 265ac35ff17SAlexander V. Chernikov * 266ac35ff17SAlexander V. Chernikov * Request: [ ipfw_obj_header ipfw_xtable_info ] 267ac35ff17SAlexander V. Chernikov */ 268ac35ff17SAlexander V. Chernikov static void 269ac35ff17SAlexander V. Chernikov table_create(ipfw_obj_header *oh, int ac, char *av[]) 270ac35ff17SAlexander V. Chernikov { 271ac35ff17SAlexander V. Chernikov ipfw_xtable_info xi; 272ac35ff17SAlexander V. Chernikov int error, tcmd, val; 273ac35ff17SAlexander V. Chernikov size_t sz; 274ac35ff17SAlexander V. Chernikov char tbuf[128]; 275ac35ff17SAlexander V. Chernikov 276ac35ff17SAlexander V. Chernikov sz = sizeof(tbuf); 277ac35ff17SAlexander V. Chernikov memset(&xi, 0, sizeof(xi)); 278ac35ff17SAlexander V. Chernikov 279ac35ff17SAlexander V. Chernikov /* Set some defaults to preserve compability */ 280ac35ff17SAlexander V. Chernikov xi.type = IPFW_TABLE_CIDR; 281ac35ff17SAlexander V. Chernikov xi.vtype = IPFW_VTYPE_U32; 282ac35ff17SAlexander V. Chernikov 283ac35ff17SAlexander V. Chernikov while (ac > 0) { 284ac35ff17SAlexander V. Chernikov if ((tcmd = match_token(tablenewcmds, *av)) == -1) 285ac35ff17SAlexander V. Chernikov errx(EX_USAGE, "unknown option: %s", *av); 286ac35ff17SAlexander V. Chernikov ac--; av++; 287ac35ff17SAlexander V. Chernikov 288ac35ff17SAlexander V. Chernikov switch (tcmd) { 289ac35ff17SAlexander V. Chernikov case TOK_TYPE: 290ac35ff17SAlexander V. Chernikov NEED1("table type required"); 291ac35ff17SAlexander V. Chernikov val = match_token(tabletypes, *av); 292ac35ff17SAlexander V. Chernikov if (val != -1) { 293ac35ff17SAlexander V. Chernikov xi.type = val; 294ac35ff17SAlexander V. Chernikov ac--; av++; 295ac35ff17SAlexander V. Chernikov break; 296ac35ff17SAlexander V. Chernikov } 297ac35ff17SAlexander V. Chernikov concat_tokens(tbuf, sizeof(tbuf), tabletypes, ", "); 298ac35ff17SAlexander V. Chernikov errx(EX_USAGE, "Unknown tabletype: %s. Supported: %s", 299ac35ff17SAlexander V. Chernikov *av, tbuf); 300ac35ff17SAlexander V. Chernikov break; 301ac35ff17SAlexander V. Chernikov case TOK_VALTYPE: 302ac35ff17SAlexander V. Chernikov NEED1("table value type required"); 303ac35ff17SAlexander V. Chernikov val = match_token(tablevaltypes, *av); 304ac35ff17SAlexander V. Chernikov if (val != -1) { 305ac35ff17SAlexander V. Chernikov xi.vtype = val; 306ac35ff17SAlexander V. Chernikov ac--; av++; 307ac35ff17SAlexander V. Chernikov break; 308ac35ff17SAlexander V. Chernikov } 309ac35ff17SAlexander V. Chernikov concat_tokens(tbuf, sizeof(tbuf), tablevaltypes, ", "); 310ac35ff17SAlexander V. Chernikov errx(EX_USAGE, "Unknown value type: %s. Supported: %s", 311ac35ff17SAlexander V. Chernikov *av, tbuf); 312ac35ff17SAlexander V. Chernikov break; 313ac35ff17SAlexander V. Chernikov case TOK_ALGO: 314ac35ff17SAlexander V. Chernikov NEED1("table algorithm name required"); 315ac35ff17SAlexander V. Chernikov if (strlen(*av) > sizeof(xi.algoname)) 316ac35ff17SAlexander V. Chernikov errx(EX_USAGE, "algorithm name too long"); 317ac35ff17SAlexander V. Chernikov strlcpy(xi.algoname, *av, sizeof(xi.algoname)); 318ac35ff17SAlexander V. Chernikov ac--; av++; 319ac35ff17SAlexander V. Chernikov break; 320ac35ff17SAlexander V. Chernikov } 321ac35ff17SAlexander V. Chernikov } 322ac35ff17SAlexander V. Chernikov 323ac35ff17SAlexander V. Chernikov if ((error = table_do_create(oh, &xi)) != 0) 324ac35ff17SAlexander V. Chernikov err(EX_OSERR, "Table creation failed"); 325f1220db8SAlexander V. Chernikov } 326f1220db8SAlexander V. Chernikov 327f1220db8SAlexander V. Chernikov /* 328ac35ff17SAlexander V. Chernikov * Creates new table 329ac35ff17SAlexander V. Chernikov * 330ac35ff17SAlexander V. Chernikov * Request: [ ipfw_obj_header ipfw_xtable_info ] 331ac35ff17SAlexander V. Chernikov * 332f1220db8SAlexander V. Chernikov * Returns 0 on success. 333f1220db8SAlexander V. Chernikov */ 334f1220db8SAlexander V. Chernikov static int 335ac35ff17SAlexander V. Chernikov table_do_create(ipfw_obj_header *oh, ipfw_xtable_info *i) 336f1220db8SAlexander V. Chernikov { 337ac35ff17SAlexander V. Chernikov char tbuf[sizeof(ipfw_obj_header) + sizeof(ipfw_xtable_info)]; 338ac35ff17SAlexander V. Chernikov int error; 339f1220db8SAlexander V. Chernikov 340ac35ff17SAlexander V. Chernikov memcpy(tbuf, oh, sizeof(*oh)); 341ac35ff17SAlexander V. Chernikov memcpy(tbuf + sizeof(*oh), i, sizeof(*i)); 342ac35ff17SAlexander V. Chernikov oh = (ipfw_obj_header *)tbuf; 343ac35ff17SAlexander V. Chernikov 344ac35ff17SAlexander V. Chernikov error = do_set3(IP_FW_TABLE_XCREATE, &oh->opheader, sizeof(tbuf)); 345ac35ff17SAlexander V. Chernikov 346ac35ff17SAlexander V. Chernikov return (error); 347ac35ff17SAlexander V. Chernikov } 348ac35ff17SAlexander V. Chernikov 349ac35ff17SAlexander V. Chernikov /* 350ac35ff17SAlexander V. Chernikov * Destroys given table specified by @oh->ntlv. 351ac35ff17SAlexander V. Chernikov * Returns 0 on success. 352ac35ff17SAlexander V. Chernikov */ 353ac35ff17SAlexander V. Chernikov static int 354ac35ff17SAlexander V. Chernikov table_destroy(ipfw_obj_header *oh) 355ac35ff17SAlexander V. Chernikov { 356ac35ff17SAlexander V. Chernikov 357ac35ff17SAlexander V. Chernikov if (do_set3(IP_FW_TABLE_XDESTROY, &oh->opheader, sizeof(*oh)) != 0) 358f1220db8SAlexander V. Chernikov return (-1); 359f1220db8SAlexander V. Chernikov 360f1220db8SAlexander V. Chernikov return (0); 361f1220db8SAlexander V. Chernikov } 362f1220db8SAlexander V. Chernikov 363f1220db8SAlexander V. Chernikov /* 364ac35ff17SAlexander V. Chernikov * Flushes given table specified by @oh->ntlv. 365f1220db8SAlexander V. Chernikov * Returns 0 on success. 366f1220db8SAlexander V. Chernikov */ 367f1220db8SAlexander V. Chernikov static int 368ac35ff17SAlexander V. Chernikov table_flush(ipfw_obj_header *oh) 369f1220db8SAlexander V. Chernikov { 370f1220db8SAlexander V. Chernikov 371ac35ff17SAlexander V. Chernikov if (do_set3(IP_FW_TABLE_XFLUSH, &oh->opheader, sizeof(*oh)) != 0) 372f1220db8SAlexander V. Chernikov return (-1); 373f1220db8SAlexander V. Chernikov 374f1220db8SAlexander V. Chernikov return (0); 375f1220db8SAlexander V. Chernikov } 376f1220db8SAlexander V. Chernikov 377f1220db8SAlexander V. Chernikov /* 378ac35ff17SAlexander V. Chernikov * Retrieves table in given table specified by @oh->ntlv. 379f1220db8SAlexander V. Chernikov * it inside @i. 380f1220db8SAlexander V. Chernikov * Returns 0 on success. 381f1220db8SAlexander V. Chernikov */ 382f1220db8SAlexander V. Chernikov static int 383ac35ff17SAlexander V. Chernikov table_get_info(ipfw_obj_header *oh, ipfw_xtable_info *i) 384f1220db8SAlexander V. Chernikov { 385f1220db8SAlexander V. Chernikov char tbuf[sizeof(ipfw_obj_header) + sizeof(ipfw_xtable_info)]; 386ac35ff17SAlexander V. Chernikov int error; 387f1220db8SAlexander V. Chernikov size_t sz; 388f1220db8SAlexander V. Chernikov 389f1220db8SAlexander V. Chernikov sz = sizeof(tbuf); 390f1220db8SAlexander V. Chernikov memset(tbuf, 0, sizeof(tbuf)); 391ac35ff17SAlexander V. Chernikov memcpy(tbuf, oh, sizeof(*oh)); 392f1220db8SAlexander V. Chernikov oh = (ipfw_obj_header *)tbuf; 393f1220db8SAlexander V. Chernikov 394ac35ff17SAlexander V. Chernikov if ((error = do_get3(IP_FW_TABLE_XINFO, &oh->opheader, &sz)) != 0) 395ac35ff17SAlexander V. Chernikov return (error); 396f1220db8SAlexander V. Chernikov 397f1220db8SAlexander V. Chernikov if (sz < sizeof(tbuf)) 398ac35ff17SAlexander V. Chernikov return (EINVAL); 399f1220db8SAlexander V. Chernikov 400f1220db8SAlexander V. Chernikov *i = *(ipfw_xtable_info *)(oh + 1); 401f1220db8SAlexander V. Chernikov 402f1220db8SAlexander V. Chernikov return (0); 403f1220db8SAlexander V. Chernikov } 404f1220db8SAlexander V. Chernikov 405f1220db8SAlexander V. Chernikov /* 406f1220db8SAlexander V. Chernikov * Prints table info struct @i in human-readable form. 407f1220db8SAlexander V. Chernikov */ 408f1220db8SAlexander V. Chernikov static int 409f1220db8SAlexander V. Chernikov table_show_info(ipfw_xtable_info *i, void *arg) 410f1220db8SAlexander V. Chernikov { 411ac35ff17SAlexander V. Chernikov const char *ttype, *vtype; 412f1220db8SAlexander V. Chernikov 413f1220db8SAlexander V. Chernikov printf("--- table(%s), set(%u) ---\n", i->tablename, i->set); 414ac35ff17SAlexander V. Chernikov if ((ttype = match_value(tabletypes, i->type)) == NULL) 415ac35ff17SAlexander V. Chernikov ttype = "unknown"; 416ac35ff17SAlexander V. Chernikov if ((vtype = match_value(tablevaltypes, i->vtype)) == NULL) 417ac35ff17SAlexander V. Chernikov vtype = "unknown"; 418ac35ff17SAlexander V. Chernikov 419ac35ff17SAlexander V. Chernikov printf(" type: %s, kindex: %d\n", ttype, i->kidx); 4209d099b4fSAlexander V. Chernikov printf(" valtype: %s, references: %u\n", vtype, i->refcnt); 4219d099b4fSAlexander V. Chernikov printf(" algorithm: %s\n", i->algoname); 422f1220db8SAlexander V. Chernikov printf(" items: %u, size: %u\n", i->count, i->size); 423f1220db8SAlexander V. Chernikov 424f1220db8SAlexander V. Chernikov return (0); 425f1220db8SAlexander V. Chernikov } 426f1220db8SAlexander V. Chernikov 427f1220db8SAlexander V. Chernikov 428f1220db8SAlexander V. Chernikov /* 429f1220db8SAlexander V. Chernikov * Function wrappers which can be used either 430f1220db8SAlexander V. Chernikov * as is or as foreach function parameter. 431f1220db8SAlexander V. Chernikov */ 432f1220db8SAlexander V. Chernikov 433f1220db8SAlexander V. Chernikov static int 434f1220db8SAlexander V. Chernikov table_show_one(ipfw_xtable_info *i, void *arg) 435f1220db8SAlexander V. Chernikov { 436f1220db8SAlexander V. Chernikov ipfw_obj_header *oh; 43781d3153dSAlexander V. Chernikov int error; 438f1220db8SAlexander V. Chernikov 439ac35ff17SAlexander V. Chernikov if ((oh = calloc(1, i->size)) == NULL) 440f1220db8SAlexander V. Chernikov return (ENOMEM); 441f1220db8SAlexander V. Chernikov 44281d3153dSAlexander V. Chernikov if ((error = table_get_list(i, oh)) != 0) { 44381d3153dSAlexander V. Chernikov err(EX_OSERR, "Error requesting table %s list", i->tablename); 44481d3153dSAlexander V. Chernikov return (error); 44581d3153dSAlexander V. Chernikov } 44681d3153dSAlexander V. Chernikov 447f1220db8SAlexander V. Chernikov table_show_list(oh, 1); 448f1220db8SAlexander V. Chernikov 449f1220db8SAlexander V. Chernikov free(oh); 450f1220db8SAlexander V. Chernikov return (0); 451f1220db8SAlexander V. Chernikov } 452f1220db8SAlexander V. Chernikov 453f1220db8SAlexander V. Chernikov static int 454f1220db8SAlexander V. Chernikov table_flush_one(ipfw_xtable_info *i, void *arg) 455f1220db8SAlexander V. Chernikov { 456ac35ff17SAlexander V. Chernikov ipfw_obj_header *oh; 457f1220db8SAlexander V. Chernikov 458ac35ff17SAlexander V. Chernikov oh = (ipfw_obj_header *)arg; 459ac35ff17SAlexander V. Chernikov 460ac35ff17SAlexander V. Chernikov table_fill_ntlv(&oh->ntlv, i->tablename, i->set, 1); 461ac35ff17SAlexander V. Chernikov 462ac35ff17SAlexander V. Chernikov return (table_flush(oh)); 463f1220db8SAlexander V. Chernikov } 464f1220db8SAlexander V. Chernikov 465ac35ff17SAlexander V. Chernikov static int 466ac35ff17SAlexander V. Chernikov table_do_modify_record(int cmd, ipfw_obj_header *oh, 467ac35ff17SAlexander V. Chernikov ipfw_obj_tentry *tent, int update) 468ac35ff17SAlexander V. Chernikov { 469db785d31SAlexander V. Chernikov ipfw_obj_ctlv *ctlv; 470db785d31SAlexander V. Chernikov char xbuf[sizeof(*oh) + sizeof(ipfw_obj_ctlv) + sizeof(*tent)]; 471ac35ff17SAlexander V. Chernikov int error; 472ac35ff17SAlexander V. Chernikov 473ac35ff17SAlexander V. Chernikov memset(xbuf, 0, sizeof(xbuf)); 474ac35ff17SAlexander V. Chernikov memcpy(xbuf, oh, sizeof(*oh)); 475ac35ff17SAlexander V. Chernikov oh = (ipfw_obj_header *)xbuf; 476ac35ff17SAlexander V. Chernikov oh->opheader.version = 1; 477ac35ff17SAlexander V. Chernikov 478db785d31SAlexander V. Chernikov ctlv = (ipfw_obj_ctlv *)(oh + 1); 479db785d31SAlexander V. Chernikov ctlv->count = 1; 480db785d31SAlexander V. Chernikov ctlv->head.length = sizeof(*ctlv) + sizeof(*tent); 481db785d31SAlexander V. Chernikov 482db785d31SAlexander V. Chernikov memcpy(ctlv + 1, tent, sizeof(*tent)); 483db785d31SAlexander V. Chernikov tent = (ipfw_obj_tentry *)(ctlv + 1); 484ac35ff17SAlexander V. Chernikov if (update != 0) 48581d3153dSAlexander V. Chernikov tent->head.flags |= IPFW_TF_UPDATE; 486ac35ff17SAlexander V. Chernikov tent->head.length = sizeof(ipfw_obj_tentry); 487ac35ff17SAlexander V. Chernikov 488ac35ff17SAlexander V. Chernikov error = do_set3(cmd, &oh->opheader, sizeof(xbuf)); 489ac35ff17SAlexander V. Chernikov 490ac35ff17SAlexander V. Chernikov return (error); 491ac35ff17SAlexander V. Chernikov } 492ac35ff17SAlexander V. Chernikov 493ac35ff17SAlexander V. Chernikov static void 494ac35ff17SAlexander V. Chernikov table_modify_record(ipfw_obj_header *oh, int ac, char *av[], int add, int update) 495ac35ff17SAlexander V. Chernikov { 496ac35ff17SAlexander V. Chernikov ipfw_obj_tentry tent; 49781d3153dSAlexander V. Chernikov ipfw_xtable_info xi; 498ac35ff17SAlexander V. Chernikov uint8_t type, vtype; 499ac35ff17SAlexander V. Chernikov int cmd; 500ac35ff17SAlexander V. Chernikov char *texterr; 501ac35ff17SAlexander V. Chernikov 502ac35ff17SAlexander V. Chernikov if (ac == 0) 503ac35ff17SAlexander V. Chernikov errx(EX_USAGE, "address required"); 504ac35ff17SAlexander V. Chernikov 505ac35ff17SAlexander V. Chernikov memset(&tent, 0, sizeof(tent)); 506ac35ff17SAlexander V. Chernikov tent.head.length = sizeof(tent); 507ac35ff17SAlexander V. Chernikov tent.idx = 1; 508ac35ff17SAlexander V. Chernikov 50981d3153dSAlexander V. Chernikov tentry_fill_key(oh, &tent, *av, &type, &vtype, &xi); 510db785d31SAlexander V. Chernikov 511db785d31SAlexander V. Chernikov /* 512db785d31SAlexander V. Chernikov * compability layer: auto-create table if not exists 513db785d31SAlexander V. Chernikov */ 514db785d31SAlexander V. Chernikov if (xi.tablename[0] == '\0') { 515db785d31SAlexander V. Chernikov xi.type = type; 516db785d31SAlexander V. Chernikov xi.vtype = vtype; 517db785d31SAlexander V. Chernikov strlcpy(xi.tablename, oh->ntlv.name, sizeof(xi.tablename)); 518db785d31SAlexander V. Chernikov fprintf(stderr, "DEPRECATED: inserting data info non-existent " 519db785d31SAlexander V. Chernikov "table %s. (auto-created)\n", xi.tablename); 520db785d31SAlexander V. Chernikov table_do_create(oh, &xi); 521db785d31SAlexander V. Chernikov } 522db785d31SAlexander V. Chernikov 523ac35ff17SAlexander V. Chernikov oh->ntlv.type = type; 524ac35ff17SAlexander V. Chernikov ac--; av++; 525ac35ff17SAlexander V. Chernikov 526ac35ff17SAlexander V. Chernikov if (add != 0) { 527ac35ff17SAlexander V. Chernikov if (ac > 0) 528ac35ff17SAlexander V. Chernikov tentry_fill_value(oh, &tent, *av, type, vtype); 529ac35ff17SAlexander V. Chernikov cmd = IP_FW_TABLE_XADD; 530ac35ff17SAlexander V. Chernikov texterr = "setsockopt(IP_FW_TABLE_XADD)"; 531ac35ff17SAlexander V. Chernikov } else { 532ac35ff17SAlexander V. Chernikov cmd = IP_FW_TABLE_XDEL; 533ac35ff17SAlexander V. Chernikov texterr = "setsockopt(IP_FW_TABLE_XDEL)"; 534ac35ff17SAlexander V. Chernikov } 535ac35ff17SAlexander V. Chernikov 536ac35ff17SAlexander V. Chernikov if (table_do_modify_record(cmd, oh, &tent, update) != 0) 537ac35ff17SAlexander V. Chernikov err(EX_OSERR, "%s", texterr); 538ac35ff17SAlexander V. Chernikov } 539ac35ff17SAlexander V. Chernikov 54081d3153dSAlexander V. Chernikov static int 54181d3153dSAlexander V. Chernikov table_do_lookup(ipfw_obj_header *oh, char *key, ipfw_xtable_info *xi, 54281d3153dSAlexander V. Chernikov ipfw_obj_tentry *xtent) 54381d3153dSAlexander V. Chernikov { 54481d3153dSAlexander V. Chernikov char xbuf[sizeof(ipfw_obj_header) + sizeof(ipfw_obj_tentry)]; 54581d3153dSAlexander V. Chernikov ipfw_obj_tentry *tent; 54681d3153dSAlexander V. Chernikov uint8_t type, vtype; 54781d3153dSAlexander V. Chernikov int error; 54881d3153dSAlexander V. Chernikov size_t sz; 54981d3153dSAlexander V. Chernikov 55081d3153dSAlexander V. Chernikov memcpy(xbuf, oh, sizeof(*oh)); 55181d3153dSAlexander V. Chernikov oh = (ipfw_obj_header *)xbuf; 55281d3153dSAlexander V. Chernikov tent = (ipfw_obj_tentry *)(oh + 1); 55381d3153dSAlexander V. Chernikov 55481d3153dSAlexander V. Chernikov memset(tent, 0, sizeof(*tent)); 55581d3153dSAlexander V. Chernikov tent->head.length = sizeof(*tent); 55681d3153dSAlexander V. Chernikov tent->idx = 1; 55781d3153dSAlexander V. Chernikov 55881d3153dSAlexander V. Chernikov tentry_fill_key(oh, tent, key, &type, &vtype, xi); 55981d3153dSAlexander V. Chernikov oh->ntlv.type = type; 56081d3153dSAlexander V. Chernikov 56181d3153dSAlexander V. Chernikov sz = sizeof(xbuf); 56281d3153dSAlexander V. Chernikov if ((error = do_get3(IP_FW_TABLE_XFIND, &oh->opheader, &sz)) != 0) 56381d3153dSAlexander V. Chernikov return (error); 56481d3153dSAlexander V. Chernikov 56581d3153dSAlexander V. Chernikov if (sz < sizeof(xbuf)) 56681d3153dSAlexander V. Chernikov return (EINVAL); 56781d3153dSAlexander V. Chernikov 56881d3153dSAlexander V. Chernikov *xtent = *tent; 56981d3153dSAlexander V. Chernikov 57081d3153dSAlexander V. Chernikov return (0); 57181d3153dSAlexander V. Chernikov } 57281d3153dSAlexander V. Chernikov 57381d3153dSAlexander V. Chernikov static void 57481d3153dSAlexander V. Chernikov table_lookup(ipfw_obj_header *oh, int ac, char *av[]) 57581d3153dSAlexander V. Chernikov { 57681d3153dSAlexander V. Chernikov ipfw_obj_tentry xtent; 57781d3153dSAlexander V. Chernikov ipfw_xtable_info xi; 57881d3153dSAlexander V. Chernikov int error; 57981d3153dSAlexander V. Chernikov 58081d3153dSAlexander V. Chernikov if (ac == 0) 58181d3153dSAlexander V. Chernikov errx(EX_USAGE, "address required"); 58281d3153dSAlexander V. Chernikov 58381d3153dSAlexander V. Chernikov error = table_do_lookup(oh, *av, &xi, &xtent); 58481d3153dSAlexander V. Chernikov 58581d3153dSAlexander V. Chernikov switch (error) { 58681d3153dSAlexander V. Chernikov case 0: 58781d3153dSAlexander V. Chernikov break; 58881d3153dSAlexander V. Chernikov case ESRCH: 58981d3153dSAlexander V. Chernikov errx(EX_UNAVAILABLE, "Table %s not found", oh->ntlv.name); 59081d3153dSAlexander V. Chernikov case ENOENT: 59181d3153dSAlexander V. Chernikov errx(EX_UNAVAILABLE, "Entry %s not found", *av); 59281d3153dSAlexander V. Chernikov case ENOTSUP: 59381d3153dSAlexander V. Chernikov errx(EX_UNAVAILABLE, "Table %s algo does not support " 59481d3153dSAlexander V. Chernikov "\"lookup\" method", oh->ntlv.name); 59581d3153dSAlexander V. Chernikov default: 59681d3153dSAlexander V. Chernikov err(EX_OSERR, "getsockopt(IP_FW_TABLE_XFIND)"); 59781d3153dSAlexander V. Chernikov } 59881d3153dSAlexander V. Chernikov 59981d3153dSAlexander V. Chernikov table_show_entry(&xi, &xtent); 60081d3153dSAlexander V. Chernikov } 601ac35ff17SAlexander V. Chernikov 602ac35ff17SAlexander V. Chernikov static void 603ac35ff17SAlexander V. Chernikov tentry_fill_key_type(char *arg, ipfw_obj_tentry *tentry, uint8_t type) 604ac35ff17SAlexander V. Chernikov { 605ac35ff17SAlexander V. Chernikov char *p; 606ac35ff17SAlexander V. Chernikov int mask, af; 607ac35ff17SAlexander V. Chernikov struct in6_addr *paddr; 608ac35ff17SAlexander V. Chernikov uint32_t key, *pkey; 609ac35ff17SAlexander V. Chernikov int masklen; 610ac35ff17SAlexander V. Chernikov 611ac35ff17SAlexander V. Chernikov masklen = 0; 612ac35ff17SAlexander V. Chernikov af = 0; 613ac35ff17SAlexander V. Chernikov paddr = (struct in6_addr *)&tentry->k; 614ac35ff17SAlexander V. Chernikov 615ac35ff17SAlexander V. Chernikov switch (type) { 616ac35ff17SAlexander V. Chernikov case IPFW_TABLE_CIDR: 617ac35ff17SAlexander V. Chernikov /* Remove / if exists */ 618ac35ff17SAlexander V. Chernikov if ((p = strchr(arg, '/')) != NULL) { 619ac35ff17SAlexander V. Chernikov *p = '\0'; 620ac35ff17SAlexander V. Chernikov mask = atoi(p + 1); 621ac35ff17SAlexander V. Chernikov } 622ac35ff17SAlexander V. Chernikov 623ac35ff17SAlexander V. Chernikov if (inet_pton(AF_INET, arg, paddr) == 1) { 624ac35ff17SAlexander V. Chernikov if (p != NULL && mask > 32) 625ac35ff17SAlexander V. Chernikov errx(EX_DATAERR, "bad IPv4 mask width: %s", 626ac35ff17SAlexander V. Chernikov p + 1); 627ac35ff17SAlexander V. Chernikov 628ac35ff17SAlexander V. Chernikov masklen = p ? mask : 32; 629ac35ff17SAlexander V. Chernikov af = AF_INET; 630ac35ff17SAlexander V. Chernikov } else if (inet_pton(AF_INET6, arg, paddr) == 1) { 631ac35ff17SAlexander V. Chernikov if (IN6_IS_ADDR_V4COMPAT(paddr)) 632ac35ff17SAlexander V. Chernikov errx(EX_DATAERR, 633ac35ff17SAlexander V. Chernikov "Use IPv4 instead of v4-compatible"); 634ac35ff17SAlexander V. Chernikov if (p != NULL && mask > 128) 635ac35ff17SAlexander V. Chernikov errx(EX_DATAERR, "bad IPv6 mask width: %s", 636ac35ff17SAlexander V. Chernikov p + 1); 637ac35ff17SAlexander V. Chernikov 638ac35ff17SAlexander V. Chernikov masklen = p ? mask : 128; 639ac35ff17SAlexander V. Chernikov af = AF_INET6; 640ac35ff17SAlexander V. Chernikov } else { 641ac35ff17SAlexander V. Chernikov /* Assume FQDN */ 642ac35ff17SAlexander V. Chernikov if (lookup_host(arg, (struct in_addr *)paddr) != 0) 643ac35ff17SAlexander V. Chernikov errx(EX_NOHOST, "hostname ``%s'' unknown", arg); 644ac35ff17SAlexander V. Chernikov 645ac35ff17SAlexander V. Chernikov masklen = 32; 646ac35ff17SAlexander V. Chernikov type = IPFW_TABLE_CIDR; 647ac35ff17SAlexander V. Chernikov af = AF_INET; 648ac35ff17SAlexander V. Chernikov } 649ac35ff17SAlexander V. Chernikov break; 650ac35ff17SAlexander V. Chernikov case IPFW_TABLE_INTERFACE: 651ac35ff17SAlexander V. Chernikov /* Assume interface name. Copy significant data only */ 652ac35ff17SAlexander V. Chernikov mask = MIN(strlen(arg), IF_NAMESIZE - 1); 653ac35ff17SAlexander V. Chernikov memcpy(paddr, arg, mask); 654ac35ff17SAlexander V. Chernikov /* Set mask to exact match */ 655ac35ff17SAlexander V. Chernikov masklen = 8 * IF_NAMESIZE; 656ac35ff17SAlexander V. Chernikov break; 657b23d5de9SAlexander V. Chernikov case IPFW_TABLE_NUMBER: 658ac35ff17SAlexander V. Chernikov /* Port or any other key */ 659ac35ff17SAlexander V. Chernikov key = strtol(arg, &p, 10); 660ac35ff17SAlexander V. Chernikov if (*p != '\0') 661ac35ff17SAlexander V. Chernikov errx(EX_DATAERR, "Invalid number: %s", arg); 662ac35ff17SAlexander V. Chernikov 663ac35ff17SAlexander V. Chernikov pkey = (uint32_t *)paddr; 664ac35ff17SAlexander V. Chernikov *pkey = key; 665ac35ff17SAlexander V. Chernikov masklen = 32; 666ac35ff17SAlexander V. Chernikov break; 667ac35ff17SAlexander V. Chernikov default: 668ac35ff17SAlexander V. Chernikov errx(EX_DATAERR, "Unsupported table type: %d", type); 669ac35ff17SAlexander V. Chernikov } 670ac35ff17SAlexander V. Chernikov 671ac35ff17SAlexander V. Chernikov tentry->subtype = af; 672ac35ff17SAlexander V. Chernikov tentry->masklen = masklen; 673ac35ff17SAlexander V. Chernikov } 674ac35ff17SAlexander V. Chernikov 675ac35ff17SAlexander V. Chernikov static void 676ac35ff17SAlexander V. Chernikov tentry_fill_key(ipfw_obj_header *oh, ipfw_obj_tentry *tent, char *key, 67781d3153dSAlexander V. Chernikov uint8_t *ptype, uint8_t *pvtype, ipfw_xtable_info *xi) 678ac35ff17SAlexander V. Chernikov { 679ac35ff17SAlexander V. Chernikov uint8_t type, vtype; 680ac35ff17SAlexander V. Chernikov int error; 681db785d31SAlexander V. Chernikov char *del; 682ac35ff17SAlexander V. Chernikov 683ac35ff17SAlexander V. Chernikov type = 0; 684ac35ff17SAlexander V. Chernikov vtype = 0; 685ac35ff17SAlexander V. Chernikov 68681d3153dSAlexander V. Chernikov error = table_get_info(oh, xi); 68781d3153dSAlexander V. Chernikov 68881d3153dSAlexander V. Chernikov if (error == 0) { 68981d3153dSAlexander V. Chernikov /* Table found. */ 69081d3153dSAlexander V. Chernikov type = xi->type; 69181d3153dSAlexander V. Chernikov vtype = xi->vtype; 69281d3153dSAlexander V. Chernikov } else { 69381d3153dSAlexander V. Chernikov if (error != ESRCH) 69481d3153dSAlexander V. Chernikov errx(EX_OSERR, "Error requesting table %s info", 69581d3153dSAlexander V. Chernikov oh->ntlv.name); 696ac35ff17SAlexander V. Chernikov /* 69781d3153dSAlexander V. Chernikov * Table does not exist. 69881d3153dSAlexander V. Chernikov * Compability layer: try to interpret data as CIDR 69981d3153dSAlexander V. Chernikov * before failing. 700ac35ff17SAlexander V. Chernikov */ 701db785d31SAlexander V. Chernikov if ((del = strchr(key, '/')) != NULL) 702db785d31SAlexander V. Chernikov *del = '\0'; 703ac35ff17SAlexander V. Chernikov if (inet_pton(AF_INET, key, &tent->k.addr6) == 1 || 704ac35ff17SAlexander V. Chernikov inet_pton(AF_INET6, key, &tent->k.addr6) == 1) { 705ac35ff17SAlexander V. Chernikov /* OK Prepare and send */ 706ac35ff17SAlexander V. Chernikov type = IPFW_TABLE_CIDR; 707ac35ff17SAlexander V. Chernikov /* 70881d3153dSAlexander V. Chernikov * XXX: Value type is forced to be u32. 70981d3153dSAlexander V. Chernikov * This should be changed for MFC. 710ac35ff17SAlexander V. Chernikov */ 71181d3153dSAlexander V. Chernikov vtype = IPFW_VTYPE_U32; 71281d3153dSAlexander V. Chernikov } else { 71381d3153dSAlexander V. Chernikov /* Inknown key */ 71481d3153dSAlexander V. Chernikov errx(EX_USAGE, "Table %s does not exist, cannot guess " 715db785d31SAlexander V. Chernikov "key '%s' type", oh->ntlv.name, key); 71681d3153dSAlexander V. Chernikov } 717db785d31SAlexander V. Chernikov if (del != NULL) 718db785d31SAlexander V. Chernikov *del = '/'; 719ac35ff17SAlexander V. Chernikov } 720ac35ff17SAlexander V. Chernikov 721ac35ff17SAlexander V. Chernikov tentry_fill_key_type(key, tent, type); 722ac35ff17SAlexander V. Chernikov 723ac35ff17SAlexander V. Chernikov *ptype = type; 724ac35ff17SAlexander V. Chernikov *pvtype = vtype; 725ac35ff17SAlexander V. Chernikov } 726ac35ff17SAlexander V. Chernikov 727ac35ff17SAlexander V. Chernikov static void 728ac35ff17SAlexander V. Chernikov tentry_fill_value(ipfw_obj_header *oh, ipfw_obj_tentry *tent, char *arg, 729ac35ff17SAlexander V. Chernikov uint8_t type, uint8_t vtype) 730ac35ff17SAlexander V. Chernikov { 731ac35ff17SAlexander V. Chernikov int code; 732ac35ff17SAlexander V. Chernikov char *p; 733ac35ff17SAlexander V. Chernikov 734ac35ff17SAlexander V. Chernikov switch (vtype) { 735ac35ff17SAlexander V. Chernikov case IPFW_VTYPE_U32: 736ac35ff17SAlexander V. Chernikov tent->value = strtoul(arg, &p, 0); 737ac35ff17SAlexander V. Chernikov if (*p != '\0') 738ac35ff17SAlexander V. Chernikov errx(EX_USAGE, "Invalid number: %s", arg); 739ac35ff17SAlexander V. Chernikov break; 740ac35ff17SAlexander V. Chernikov case IPFW_VTYPE_IP: 741ac35ff17SAlexander V. Chernikov if (inet_pton(AF_INET, arg, &tent->value) == 1) 742ac35ff17SAlexander V. Chernikov break; 743ac35ff17SAlexander V. Chernikov /* Try hostname */ 744ac35ff17SAlexander V. Chernikov if (lookup_host(arg, (struct in_addr *)&tent->value) != 0) 745ac35ff17SAlexander V. Chernikov errx(EX_USAGE, "Invalid IPv4 address: %s", arg); 746ac35ff17SAlexander V. Chernikov break; 747ac35ff17SAlexander V. Chernikov case IPFW_VTYPE_DSCP: 748ac35ff17SAlexander V. Chernikov if (isalpha(*arg)) { 749ac35ff17SAlexander V. Chernikov if ((code = match_token(f_ipdscp, arg)) == -1) 750ac35ff17SAlexander V. Chernikov errx(EX_DATAERR, "Unknown DSCP code"); 751ac35ff17SAlexander V. Chernikov } else { 752ac35ff17SAlexander V. Chernikov code = strtoul(arg, NULL, 10); 753ac35ff17SAlexander V. Chernikov if (code < 0 || code > 63) 754ac35ff17SAlexander V. Chernikov errx(EX_DATAERR, "Invalid DSCP value"); 755ac35ff17SAlexander V. Chernikov } 756ac35ff17SAlexander V. Chernikov tent->value = code; 757ac35ff17SAlexander V. Chernikov break; 758ac35ff17SAlexander V. Chernikov default: 759ac35ff17SAlexander V. Chernikov errx(EX_OSERR, "Unsupported format type %d", vtype); 760ac35ff17SAlexander V. Chernikov } 761ac35ff17SAlexander V. Chernikov } 762f1220db8SAlexander V. Chernikov 763f1220db8SAlexander V. Chernikov /* 764f1220db8SAlexander V. Chernikov * Compare table names. 765f1220db8SAlexander V. Chernikov * Honor number comparison. 766f1220db8SAlexander V. Chernikov */ 767f1220db8SAlexander V. Chernikov static int 768f1220db8SAlexander V. Chernikov tablename_cmp(const void *a, const void *b) 769f1220db8SAlexander V. Chernikov { 770f1220db8SAlexander V. Chernikov ipfw_xtable_info *ia, *ib; 771f1220db8SAlexander V. Chernikov 772f1220db8SAlexander V. Chernikov ia = (ipfw_xtable_info *)a; 773f1220db8SAlexander V. Chernikov ib = (ipfw_xtable_info *)b; 774f1220db8SAlexander V. Chernikov 77568394ec8SAlexander V. Chernikov return (stringnum_cmp(ia->tablename, ib->tablename)); 776f1220db8SAlexander V. Chernikov } 777f1220db8SAlexander V. Chernikov 778f1220db8SAlexander V. Chernikov /* 779f1220db8SAlexander V. Chernikov * Retrieves table list from kernel, 780f1220db8SAlexander V. Chernikov * optionally sorts it and calls requested function for each table. 781f1220db8SAlexander V. Chernikov * Returns 0 on success. 782f1220db8SAlexander V. Chernikov */ 783f1220db8SAlexander V. Chernikov static int 784f1220db8SAlexander V. Chernikov tables_foreach(table_cb_t *f, void *arg, int sort) 785f1220db8SAlexander V. Chernikov { 786f1220db8SAlexander V. Chernikov ipfw_obj_lheader req, *olh; 787f1220db8SAlexander V. Chernikov ipfw_xtable_info *info; 788f1220db8SAlexander V. Chernikov size_t sz; 789f1220db8SAlexander V. Chernikov int i, error; 790f1220db8SAlexander V. Chernikov 791f1220db8SAlexander V. Chernikov memset(&req, 0, sizeof(req)); 792f1220db8SAlexander V. Chernikov sz = sizeof(req); 793f1220db8SAlexander V. Chernikov 794d3a4f924SAlexander V. Chernikov if ((error = do_get3(IP_FW_TABLES_XGETSIZE, &req.opheader, &sz)) != 0) 795f1220db8SAlexander V. Chernikov return (errno); 796f1220db8SAlexander V. Chernikov 797f1220db8SAlexander V. Chernikov sz = req.size; 798f1220db8SAlexander V. Chernikov if ((olh = calloc(1, sz)) == NULL) 799f1220db8SAlexander V. Chernikov return (ENOMEM); 800f1220db8SAlexander V. Chernikov 801f1220db8SAlexander V. Chernikov olh->size = sz; 802d3a4f924SAlexander V. Chernikov if ((error = do_get3(IP_FW_TABLES_XLIST, &olh->opheader, &sz)) != 0) { 803f1220db8SAlexander V. Chernikov free(olh); 804f1220db8SAlexander V. Chernikov return (errno); 805f1220db8SAlexander V. Chernikov } 806f1220db8SAlexander V. Chernikov 807f1220db8SAlexander V. Chernikov if (sort != 0) 808f1220db8SAlexander V. Chernikov qsort(olh + 1, olh->count, olh->objsize, tablename_cmp); 809f1220db8SAlexander V. Chernikov 810f1220db8SAlexander V. Chernikov info = (ipfw_xtable_info *)(olh + 1); 811f1220db8SAlexander V. Chernikov for (i = 0; i < olh->count; i++) { 812f1220db8SAlexander V. Chernikov error = f(info, arg); /* Ignore errors for now */ 813f1220db8SAlexander V. Chernikov info = (ipfw_xtable_info *)((caddr_t)info + olh->objsize); 814f1220db8SAlexander V. Chernikov } 815f1220db8SAlexander V. Chernikov 816f1220db8SAlexander V. Chernikov free(olh); 817f1220db8SAlexander V. Chernikov 818f1220db8SAlexander V. Chernikov return (0); 819f1220db8SAlexander V. Chernikov } 820f1220db8SAlexander V. Chernikov 821f1220db8SAlexander V. Chernikov /* 822f1220db8SAlexander V. Chernikov * Retrieves all entries for given table @i in 823d3a4f924SAlexander V. Chernikov * eXtended format. Assumes buffer of size 824d3a4f924SAlexander V. Chernikov * @i->size has already been allocated by caller. 825f1220db8SAlexander V. Chernikov * 826f1220db8SAlexander V. Chernikov * Returns 0 on success. 827f1220db8SAlexander V. Chernikov */ 828f1220db8SAlexander V. Chernikov static int 829f1220db8SAlexander V. Chernikov table_get_list(ipfw_xtable_info *i, ipfw_obj_header *oh) 830f1220db8SAlexander V. Chernikov { 831f1220db8SAlexander V. Chernikov size_t sz; 83281d3153dSAlexander V. Chernikov int error, c; 833f1220db8SAlexander V. Chernikov 83481d3153dSAlexander V. Chernikov sz = 0; 83581d3153dSAlexander V. Chernikov for (c = 0; c < 3; c++) { 836f1220db8SAlexander V. Chernikov table_fill_objheader(oh, i); 83781d3153dSAlexander V. Chernikov if (sz < i->size) 838f1220db8SAlexander V. Chernikov sz = i->size; 839f1220db8SAlexander V. Chernikov 840d3a4f924SAlexander V. Chernikov oh->opheader.version = 1; /* Current version */ 84181d3153dSAlexander V. Chernikov error = do_get3(IP_FW_TABLE_XLIST, &oh->opheader, &sz); 842d3a4f924SAlexander V. Chernikov 84381d3153dSAlexander V. Chernikov if (error != ENOMEM) 844f1220db8SAlexander V. Chernikov return (errno); 84581d3153dSAlexander V. Chernikov } 846f1220db8SAlexander V. Chernikov 84781d3153dSAlexander V. Chernikov return (ENOMEM); 848f1220db8SAlexander V. Chernikov } 849f1220db8SAlexander V. Chernikov 850f1220db8SAlexander V. Chernikov /* 851f1220db8SAlexander V. Chernikov * Shows all entries from @oh in human-readable format 852f1220db8SAlexander V. Chernikov */ 853f1220db8SAlexander V. Chernikov static void 854f1220db8SAlexander V. Chernikov table_show_list(ipfw_obj_header *oh, int need_header) 855f1220db8SAlexander V. Chernikov { 85681d3153dSAlexander V. Chernikov ipfw_obj_tentry *tent; 85781d3153dSAlexander V. Chernikov uint32_t count; 858f1220db8SAlexander V. Chernikov ipfw_xtable_info *i; 859f1220db8SAlexander V. Chernikov 860f1220db8SAlexander V. Chernikov i = (ipfw_xtable_info *)(oh + 1); 86181d3153dSAlexander V. Chernikov tent = (ipfw_obj_tentry *)(i + 1); 862f1220db8SAlexander V. Chernikov 863f1220db8SAlexander V. Chernikov if (need_header) 864f1220db8SAlexander V. Chernikov printf("--- table(%s), set(%u) ---\n", i->tablename, i->set); 865f1220db8SAlexander V. Chernikov 866f1220db8SAlexander V. Chernikov count = i->count; 867f1220db8SAlexander V. Chernikov while (count > 0) { 86881d3153dSAlexander V. Chernikov table_show_entry(i, tent); 86981d3153dSAlexander V. Chernikov tent = (ipfw_obj_tentry *)((caddr_t)tent + tent->head.length); 87081d3153dSAlexander V. Chernikov count--; 87181d3153dSAlexander V. Chernikov } 87281d3153dSAlexander V. Chernikov } 87381d3153dSAlexander V. Chernikov 87481d3153dSAlexander V. Chernikov static void 87581d3153dSAlexander V. Chernikov table_show_entry(ipfw_xtable_info *i, ipfw_obj_tentry *tent) 87681d3153dSAlexander V. Chernikov { 87781d3153dSAlexander V. Chernikov char tbuf[128]; 87881d3153dSAlexander V. Chernikov uint32_t tval; 87981d3153dSAlexander V. Chernikov 88081d3153dSAlexander V. Chernikov tval = tent->value; 88181d3153dSAlexander V. Chernikov 882f1220db8SAlexander V. Chernikov switch (i->type) { 883f1220db8SAlexander V. Chernikov case IPFW_TABLE_CIDR: 884f1220db8SAlexander V. Chernikov /* IPv4 or IPv6 prefixes */ 88581d3153dSAlexander V. Chernikov inet_ntop(tent->subtype, &tent->k, tbuf, sizeof(tbuf)); 886f1220db8SAlexander V. Chernikov 887f1220db8SAlexander V. Chernikov if (co.do_value_as_ip) { 888f1220db8SAlexander V. Chernikov tval = htonl(tval); 88981d3153dSAlexander V. Chernikov printf("%s/%u %s\n", tbuf, tent->masklen, 890f1220db8SAlexander V. Chernikov inet_ntoa(*(struct in_addr *)&tval)); 891f1220db8SAlexander V. Chernikov } else 89281d3153dSAlexander V. Chernikov printf("%s/%u %u\n", tbuf, tent->masklen, tval); 893f1220db8SAlexander V. Chernikov break; 894f1220db8SAlexander V. Chernikov case IPFW_TABLE_INTERFACE: 895f1220db8SAlexander V. Chernikov /* Interface names */ 896f1220db8SAlexander V. Chernikov if (co.do_value_as_ip) { 897f1220db8SAlexander V. Chernikov tval = htonl(tval); 89881d3153dSAlexander V. Chernikov printf("%s %s\n", tent->k.iface, 899f1220db8SAlexander V. Chernikov inet_ntoa(*(struct in_addr *)&tval)); 900f1220db8SAlexander V. Chernikov } else 90181d3153dSAlexander V. Chernikov printf("%s %u\n", tent->k.iface, tval); 902b23d5de9SAlexander V. Chernikov break; 903b23d5de9SAlexander V. Chernikov case IPFW_TABLE_NUMBER: 904b23d5de9SAlexander V. Chernikov /* numbers */ 905b23d5de9SAlexander V. Chernikov if (co.do_value_as_ip) { 906b23d5de9SAlexander V. Chernikov tval = htonl(tval); 907b23d5de9SAlexander V. Chernikov printf("%u %s\n", tent->k.key, 908b23d5de9SAlexander V. Chernikov inet_ntoa(*(struct in_addr *)&tval)); 909b23d5de9SAlexander V. Chernikov } else 910b23d5de9SAlexander V. Chernikov printf("%u %u\n", tent->k.key, tval); 911b23d5de9SAlexander V. Chernikov break; 912f1220db8SAlexander V. Chernikov } 913f1220db8SAlexander V. Chernikov } 914f1220db8SAlexander V. Chernikov 9159d099b4fSAlexander V. Chernikov static int 9169d099b4fSAlexander V. Chernikov table_do_get_algolist(ipfw_obj_lheader **polh) 9179d099b4fSAlexander V. Chernikov { 9189d099b4fSAlexander V. Chernikov ipfw_obj_lheader req, *olh; 9199d099b4fSAlexander V. Chernikov size_t sz; 9209d099b4fSAlexander V. Chernikov int error; 9219d099b4fSAlexander V. Chernikov 9229d099b4fSAlexander V. Chernikov memset(&req, 0, sizeof(req)); 9239d099b4fSAlexander V. Chernikov sz = sizeof(req); 9249d099b4fSAlexander V. Chernikov 9259d099b4fSAlexander V. Chernikov error = do_get3(IP_FW_TABLES_ALIST, &req.opheader, &sz); 9269d099b4fSAlexander V. Chernikov if (error != 0 && error != ENOMEM) 9279d099b4fSAlexander V. Chernikov return (error); 9289d099b4fSAlexander V. Chernikov 9299d099b4fSAlexander V. Chernikov sz = req.size; 9309d099b4fSAlexander V. Chernikov if ((olh = calloc(1, sz)) == NULL) 9319d099b4fSAlexander V. Chernikov return (ENOMEM); 9329d099b4fSAlexander V. Chernikov 9339d099b4fSAlexander V. Chernikov olh->size = sz; 9349d099b4fSAlexander V. Chernikov if ((error = do_get3(IP_FW_TABLES_ALIST, &olh->opheader, &sz)) != 0) { 9359d099b4fSAlexander V. Chernikov free(olh); 9369d099b4fSAlexander V. Chernikov return (error); 9379d099b4fSAlexander V. Chernikov } 9389d099b4fSAlexander V. Chernikov 9399d099b4fSAlexander V. Chernikov *polh = olh; 9409d099b4fSAlexander V. Chernikov return (0); 9419d099b4fSAlexander V. Chernikov } 9429d099b4fSAlexander V. Chernikov 9439d099b4fSAlexander V. Chernikov void 9449d099b4fSAlexander V. Chernikov ipfw_list_ta(int ac, char *av[]) 9459d099b4fSAlexander V. Chernikov { 9469d099b4fSAlexander V. Chernikov ipfw_obj_lheader *olh; 9479d099b4fSAlexander V. Chernikov ipfw_ta_info *info; 9489d099b4fSAlexander V. Chernikov int error, i; 9499d099b4fSAlexander V. Chernikov const char *atype; 9509d099b4fSAlexander V. Chernikov 9519d099b4fSAlexander V. Chernikov error = table_do_get_algolist(&olh); 9529d099b4fSAlexander V. Chernikov if (error != 0) 9539d099b4fSAlexander V. Chernikov err(EX_OSERR, "Unable to request algorithm list"); 9549d099b4fSAlexander V. Chernikov 9559d099b4fSAlexander V. Chernikov info = (ipfw_ta_info *)(olh + 1); 9569d099b4fSAlexander V. Chernikov for (i = 0; i < olh->count; i++) { 9579d099b4fSAlexander V. Chernikov if ((atype = match_value(tabletypes, info->type)) == NULL) 9589d099b4fSAlexander V. Chernikov atype = "unknown"; 959*8ce7a2bcSAlexander V. Chernikov printf("--- %s ---\n", info->algoname); 960*8ce7a2bcSAlexander V. Chernikov printf(" type: %s\n refcount: %u\n", atype, info->refcnt); 9619d099b4fSAlexander V. Chernikov 9629d099b4fSAlexander V. Chernikov info = (ipfw_ta_info *)((caddr_t)info + olh->objsize); 9639d099b4fSAlexander V. Chernikov } 9649d099b4fSAlexander V. Chernikov 9659d099b4fSAlexander V. Chernikov free(olh); 9669d099b4fSAlexander V. Chernikov } 9679d099b4fSAlexander V. Chernikov 9686c2997ffSAlexander V. Chernikov int 9696c2997ffSAlexander V. Chernikov compare_ntlv(const void *_a, const void *_b) 9706c2997ffSAlexander V. Chernikov { 9716c2997ffSAlexander V. Chernikov ipfw_obj_ntlv *a, *b; 9726c2997ffSAlexander V. Chernikov 9736c2997ffSAlexander V. Chernikov a = (ipfw_obj_ntlv *)_a; 9746c2997ffSAlexander V. Chernikov b = (ipfw_obj_ntlv *)_b; 9756c2997ffSAlexander V. Chernikov 9766c2997ffSAlexander V. Chernikov if (a->set < b->set) 9776c2997ffSAlexander V. Chernikov return (-1); 9786c2997ffSAlexander V. Chernikov else if (a->set > b->set) 9796c2997ffSAlexander V. Chernikov return (1); 9806c2997ffSAlexander V. Chernikov 9816c2997ffSAlexander V. Chernikov if (a->idx < b->idx) 9826c2997ffSAlexander V. Chernikov return (-1); 9836c2997ffSAlexander V. Chernikov else if (a->idx > b->idx) 9846c2997ffSAlexander V. Chernikov return (1); 9856c2997ffSAlexander V. Chernikov 9866c2997ffSAlexander V. Chernikov return (0); 9876c2997ffSAlexander V. Chernikov } 988563b5ab1SAlexander V. Chernikov 989563b5ab1SAlexander V. Chernikov int 9906c2997ffSAlexander V. Chernikov compare_kntlv(const void *k, const void *v) 991563b5ab1SAlexander V. Chernikov { 992563b5ab1SAlexander V. Chernikov ipfw_obj_ntlv *ntlv; 993563b5ab1SAlexander V. Chernikov uint16_t key; 994563b5ab1SAlexander V. Chernikov 995563b5ab1SAlexander V. Chernikov key = *((uint16_t *)k); 996563b5ab1SAlexander V. Chernikov ntlv = (ipfw_obj_ntlv *)v; 997563b5ab1SAlexander V. Chernikov 998563b5ab1SAlexander V. Chernikov if (key < ntlv->idx) 999563b5ab1SAlexander V. Chernikov return (-1); 1000563b5ab1SAlexander V. Chernikov else if (key > ntlv->idx) 1001563b5ab1SAlexander V. Chernikov return (1); 1002563b5ab1SAlexander V. Chernikov 1003563b5ab1SAlexander V. Chernikov return (0); 1004563b5ab1SAlexander V. Chernikov } 1005563b5ab1SAlexander V. Chernikov 1006563b5ab1SAlexander V. Chernikov /* 1007563b5ab1SAlexander V. Chernikov * Finds table name in @ctlv by @idx. 1008563b5ab1SAlexander V. Chernikov * Uses the following facts: 1009563b5ab1SAlexander V. Chernikov * 1) All TLVs are the same size 1010563b5ab1SAlexander V. Chernikov * 2) Kernel implementation provides already sorted list. 1011563b5ab1SAlexander V. Chernikov * 1012563b5ab1SAlexander V. Chernikov * Returns table name or NULL. 1013563b5ab1SAlexander V. Chernikov */ 1014563b5ab1SAlexander V. Chernikov char * 1015563b5ab1SAlexander V. Chernikov table_search_ctlv(ipfw_obj_ctlv *ctlv, uint16_t idx) 1016563b5ab1SAlexander V. Chernikov { 1017563b5ab1SAlexander V. Chernikov ipfw_obj_ntlv *ntlv; 1018563b5ab1SAlexander V. Chernikov 1019563b5ab1SAlexander V. Chernikov ntlv = bsearch(&idx, (ctlv + 1), ctlv->count, ctlv->objsize, 10206c2997ffSAlexander V. Chernikov compare_kntlv); 1021563b5ab1SAlexander V. Chernikov 1022563b5ab1SAlexander V. Chernikov if (ntlv != 0) 1023563b5ab1SAlexander V. Chernikov return (ntlv->name); 1024563b5ab1SAlexander V. Chernikov 1025563b5ab1SAlexander V. Chernikov return (NULL); 1026563b5ab1SAlexander V. Chernikov } 1027563b5ab1SAlexander V. Chernikov 10286c2997ffSAlexander V. Chernikov void 10296c2997ffSAlexander V. Chernikov table_sort_ctlv(ipfw_obj_ctlv *ctlv) 10306c2997ffSAlexander V. Chernikov { 10316c2997ffSAlexander V. Chernikov 10326c2997ffSAlexander V. Chernikov qsort(ctlv + 1, ctlv->count, ctlv->objsize, compare_ntlv); 10336c2997ffSAlexander V. Chernikov } 10346c2997ffSAlexander V. Chernikov 10356c2997ffSAlexander V. Chernikov int 10366c2997ffSAlexander V. Chernikov table_check_name(char *tablename) 10376c2997ffSAlexander V. Chernikov { 10386c2997ffSAlexander V. Chernikov int c, i, l; 10396c2997ffSAlexander V. Chernikov 10406c2997ffSAlexander V. Chernikov /* 10416c2997ffSAlexander V. Chernikov * Check if tablename is null-terminated and contains 10426c2997ffSAlexander V. Chernikov * valid symbols only. Valid mask is: 1043ac35ff17SAlexander V. Chernikov * [a-zA-Z0-9\-_\.]{1,63} 10446c2997ffSAlexander V. Chernikov */ 10456c2997ffSAlexander V. Chernikov l = strlen(tablename); 10466c2997ffSAlexander V. Chernikov if (l == 0 || l >= 64) 10476c2997ffSAlexander V. Chernikov return (EINVAL); 10486c2997ffSAlexander V. Chernikov for (i = 0; i < l; i++) { 10496c2997ffSAlexander V. Chernikov c = tablename[i]; 10506c2997ffSAlexander V. Chernikov if (isalpha(c) || isdigit(c) || c == '_' || 10516c2997ffSAlexander V. Chernikov c == '-' || c == '.') 10526c2997ffSAlexander V. Chernikov continue; 10536c2997ffSAlexander V. Chernikov return (EINVAL); 10546c2997ffSAlexander V. Chernikov } 10556c2997ffSAlexander V. Chernikov 1056ac35ff17SAlexander V. Chernikov /* Restrict some 'special' names */ 1057ac35ff17SAlexander V. Chernikov if (strcmp(tablename, "all") == 0) 1058ac35ff17SAlexander V. Chernikov return (EINVAL); 1059ac35ff17SAlexander V. Chernikov 10606c2997ffSAlexander V. Chernikov return (0); 10616c2997ffSAlexander V. Chernikov } 10626c2997ffSAlexander V. Chernikov 1063