* Add the abilify to lock/unlock given table from changes.
Example: # ipfw table si lock # ipfw table si info +++ table(si), set(0) +++ kindex: 0, type: cidr, locked valtype: number, references: 0 algorithm: cidr:radix items: 0, size: 288 # ipfw table si add 4.5.6.7 ignored: 4.5.6.7/32 0 ipfw: Adding record failed: table is locked # ipfw table si unlock # ipfw table si add 4.5.6.7 added: 4.5.6.7/32 0 # ipfw table si lock # ipfw table si delete 4.5.6.7 ignored: 4.5.6.7/32 0 ipfw: Deleting record failed: table is locked # ipfw table si unlock # ipfw table si delete 4.5.6.7 deleted: 4.5.6.7/32 0
This commit is contained in:
parent
3a845e1076
commit
4f43138ade
@ -225,6 +225,8 @@ enum tokens {
|
|||||||
TOK_TALIST,
|
TOK_TALIST,
|
||||||
TOK_FTYPE,
|
TOK_FTYPE,
|
||||||
TOK_ATOMIC,
|
TOK_ATOMIC,
|
||||||
|
TOK_LOCK,
|
||||||
|
TOK_UNLOCK,
|
||||||
};
|
};
|
||||||
/*
|
/*
|
||||||
* the following macro returns an error message if we run out of
|
* the following macro returns an error message if we run out of
|
||||||
|
@ -59,6 +59,7 @@ static int table_do_swap(ipfw_obj_header *oh, char *second);
|
|||||||
static void table_create(ipfw_obj_header *oh, int ac, char *av[]);
|
static void table_create(ipfw_obj_header *oh, int ac, char *av[]);
|
||||||
static void table_modify(ipfw_obj_header *oh, int ac, char *av[]);
|
static void table_modify(ipfw_obj_header *oh, int ac, char *av[]);
|
||||||
static void table_lookup(ipfw_obj_header *oh, int ac, char *av[]);
|
static void table_lookup(ipfw_obj_header *oh, int ac, char *av[]);
|
||||||
|
static void table_lock(ipfw_obj_header *oh, int lock);
|
||||||
static int table_swap(ipfw_obj_header *oh, char *second);
|
static int table_swap(ipfw_obj_header *oh, char *second);
|
||||||
static int table_get_info(ipfw_obj_header *oh, ipfw_xtable_info *i);
|
static int table_get_info(ipfw_obj_header *oh, ipfw_xtable_info *i);
|
||||||
static int table_show_info(ipfw_xtable_info *i, void *arg);
|
static int table_show_info(ipfw_xtable_info *i, void *arg);
|
||||||
@ -115,6 +116,8 @@ static struct _s_x tablecmds[] = {
|
|||||||
{ "list", TOK_LIST },
|
{ "list", TOK_LIST },
|
||||||
{ "lookup", TOK_LOOKUP },
|
{ "lookup", TOK_LOOKUP },
|
||||||
{ "atomic", TOK_ATOMIC },
|
{ "atomic", TOK_ATOMIC },
|
||||||
|
{ "lock", TOK_LOCK },
|
||||||
|
{ "unlock", TOK_UNLOCK },
|
||||||
{ NULL, 0 }
|
{ NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -240,6 +243,10 @@ ipfw_table_handler(int ac, char *av[])
|
|||||||
NEED1("second table name required");
|
NEED1("second table name required");
|
||||||
table_swap(&oh, *av);
|
table_swap(&oh, *av);
|
||||||
break;
|
break;
|
||||||
|
case TOK_LOCK:
|
||||||
|
case TOK_UNLOCK:
|
||||||
|
table_lock(&oh, (tcmd == TOK_LOCK));
|
||||||
|
break;
|
||||||
case TOK_DETAIL:
|
case TOK_DETAIL:
|
||||||
case TOK_INFO:
|
case TOK_INFO:
|
||||||
arg = (tcmd == TOK_DETAIL) ? (void *)1 : NULL;
|
arg = (tcmd == TOK_DETAIL) ? (void *)1 : NULL;
|
||||||
@ -297,6 +304,7 @@ static struct _s_x tablenewcmds[] = {
|
|||||||
{ "valtype", TOK_VALTYPE },
|
{ "valtype", TOK_VALTYPE },
|
||||||
{ "algo", TOK_ALGO },
|
{ "algo", TOK_ALGO },
|
||||||
{ "limit", TOK_LIMIT },
|
{ "limit", TOK_LIMIT },
|
||||||
|
{ "locked", TOK_LOCK },
|
||||||
{ NULL, 0 }
|
{ NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -440,6 +448,9 @@ table_create(ipfw_obj_header *oh, int ac, char *av[])
|
|||||||
strlcpy(xi.algoname, *av, sizeof(xi.algoname));
|
strlcpy(xi.algoname, *av, sizeof(xi.algoname));
|
||||||
ac--; av++;
|
ac--; av++;
|
||||||
break;
|
break;
|
||||||
|
case TOK_LOCK:
|
||||||
|
xi.flags |= IPFW_TGFLAGS_LOCKED;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -485,10 +496,6 @@ table_modify(ipfw_obj_header *oh, int ac, char *av[])
|
|||||||
sz = sizeof(tbuf);
|
sz = sizeof(tbuf);
|
||||||
memset(&xi, 0, sizeof(xi));
|
memset(&xi, 0, sizeof(xi));
|
||||||
|
|
||||||
/* Set some defaults to preserve compability */
|
|
||||||
xi.type = IPFW_TABLE_CIDR;
|
|
||||||
xi.vtype = IPFW_VTYPE_U32;
|
|
||||||
|
|
||||||
while (ac > 0) {
|
while (ac > 0) {
|
||||||
if ((tcmd = match_token(tablenewcmds, *av)) == -1)
|
if ((tcmd = match_token(tablenewcmds, *av)) == -1)
|
||||||
errx(EX_USAGE, "unknown option: %s", *av);
|
errx(EX_USAGE, "unknown option: %s", *av);
|
||||||
@ -542,6 +549,25 @@ table_do_modify(ipfw_obj_header *oh, ipfw_xtable_info *i)
|
|||||||
|
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Locks or unlocks given table
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
table_lock(ipfw_obj_header *oh, int lock)
|
||||||
|
{
|
||||||
|
ipfw_xtable_info xi;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
memset(&xi, 0, sizeof(xi));
|
||||||
|
|
||||||
|
xi.mflags |= IPFW_TMFLAGS_LOCK;
|
||||||
|
xi.flags |= (lock != 0) ? IPFW_TGFLAGS_LOCKED : 0;
|
||||||
|
|
||||||
|
if ((error = table_do_modify(oh, &xi)) != 0)
|
||||||
|
err(EX_OSERR, "Table %s failed", lock != 0 ? "lock" : "unlock");
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Destroys given table specified by @oh->ntlv.
|
* Destroys given table specified by @oh->ntlv.
|
||||||
* Returns 0 on success.
|
* Returns 0 on success.
|
||||||
@ -713,7 +739,10 @@ table_show_info(ipfw_xtable_info *i, void *arg)
|
|||||||
snprintf(tvtype, sizeof(tvtype), "%s", vtype);
|
snprintf(tvtype, sizeof(tvtype), "%s", vtype);
|
||||||
|
|
||||||
printf("--- table(%s), set(%u) ---\n", i->tablename, i->set);
|
printf("--- table(%s), set(%u) ---\n", i->tablename, i->set);
|
||||||
printf(" kindex: %d, type: %s\n", i->kidx, ttype);
|
if ((i->flags & IPFW_TGFLAGS_LOCKED) != 0)
|
||||||
|
printf(" kindex: %d, type: %s, locked\n", i->kidx, ttype);
|
||||||
|
else
|
||||||
|
printf(" kindex: %d, type: %s\n", i->kidx, ttype);
|
||||||
printf(" valtype: %s, references: %u\n", tvtype, i->refcnt);
|
printf(" valtype: %s, references: %u\n", tvtype, i->refcnt);
|
||||||
printf(" algorithm: %s\n", i->algoname);
|
printf(" algorithm: %s\n", i->algoname);
|
||||||
printf(" items: %u, size: %u\n", i->count, i->size);
|
printf(" items: %u, size: %u\n", i->count, i->size);
|
||||||
@ -1007,6 +1036,9 @@ table_modify_record(ipfw_obj_header *oh, int ac, char *av[], int add,
|
|||||||
case ENOENT:
|
case ENOENT:
|
||||||
etxt = "record not found";
|
etxt = "record not found";
|
||||||
break;
|
break;
|
||||||
|
case EACCES:
|
||||||
|
etxt = "table is locked";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
etxt = strerror(error);
|
etxt = strerror(error);
|
||||||
}
|
}
|
||||||
|
@ -866,7 +866,7 @@ typedef struct _ipfw_xtable_info {
|
|||||||
uint8_t vtype; /* value type (u32) */
|
uint8_t vtype; /* value type (u32) */
|
||||||
uint8_t vftype; /* value format type (ip,number)*/
|
uint8_t vftype; /* value format type (ip,number)*/
|
||||||
uint16_t mflags; /* modification flags */
|
uint16_t mflags; /* modification flags */
|
||||||
uint16_t spare;
|
uint16_t flags; /* generic table flags */
|
||||||
uint32_t set; /* set table is in */
|
uint32_t set; /* set table is in */
|
||||||
uint32_t kidx; /* kernel index */
|
uint32_t kidx; /* kernel index */
|
||||||
uint32_t refcnt; /* number of references */
|
uint32_t refcnt; /* number of references */
|
||||||
@ -877,13 +877,18 @@ typedef struct _ipfw_xtable_info {
|
|||||||
char algoname[64]; /* algorithm name */
|
char algoname[64]; /* algorithm name */
|
||||||
ipfw_ta_tinfo ta_info; /* additional algo stats */
|
ipfw_ta_tinfo ta_info; /* additional algo stats */
|
||||||
} ipfw_xtable_info;
|
} ipfw_xtable_info;
|
||||||
|
/* Generic table flags */
|
||||||
|
#define IPFW_TGFLAGS_LOCKED 0x01 /* Tables is locked from changes*/
|
||||||
|
/* Table type-specific flags */
|
||||||
#define IPFW_TFFLAG_SRCIP 0x01
|
#define IPFW_TFFLAG_SRCIP 0x01
|
||||||
#define IPFW_TFFLAG_DSTIP 0x02
|
#define IPFW_TFFLAG_DSTIP 0x02
|
||||||
#define IPFW_TFFLAG_SRCPORT 0x04
|
#define IPFW_TFFLAG_SRCPORT 0x04
|
||||||
#define IPFW_TFFLAG_DSTPORT 0x08
|
#define IPFW_TFFLAG_DSTPORT 0x08
|
||||||
#define IPFW_TFFLAG_PROTO 0x10
|
#define IPFW_TFFLAG_PROTO 0x10
|
||||||
#define IPFW_TMFLAGS_FTYPE 0x01 /* Change ftype field */
|
/* Table modification flags */
|
||||||
#define IPFW_TMFLAGS_LIMIT 0x02 /* Change limit value */
|
#define IPFW_TMFLAGS_FTYPE 0x0001 /* Change ftype field */
|
||||||
|
#define IPFW_TMFLAGS_LIMIT 0x0002 /* Change limit value */
|
||||||
|
#define IPFW_TMFLAGS_LOCK 0x0004 /* Change table lock state */
|
||||||
|
|
||||||
typedef struct _ipfw_iface_info {
|
typedef struct _ipfw_iface_info {
|
||||||
char ifname[64]; /* interface name */
|
char ifname[64]; /* interface name */
|
||||||
|
@ -76,7 +76,7 @@ struct table_config {
|
|||||||
uint8_t vtype; /* value type */
|
uint8_t vtype; /* value type */
|
||||||
uint8_t vftype; /* value format type */
|
uint8_t vftype; /* value format type */
|
||||||
uint8_t tflags; /* type flags */
|
uint8_t tflags; /* type flags */
|
||||||
uint8_t spare0;
|
uint8_t locked; /* 1 if locked from changes */
|
||||||
uint32_t count; /* Number of records */
|
uint32_t count; /* Number of records */
|
||||||
uint32_t limit; /* Max number of records */
|
uint32_t limit; /* Max number of records */
|
||||||
uint8_t linked; /* 1 if already linked */
|
uint8_t linked; /* 1 if already linked */
|
||||||
@ -210,6 +210,11 @@ add_table_entry(struct ip_fw_chain *ch, struct tid_info *ti,
|
|||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tc->locked != 0) {
|
||||||
|
IPFW_UH_WUNLOCK(ch);
|
||||||
|
return (EACCES);
|
||||||
|
}
|
||||||
|
|
||||||
/* Try to exit early on limit hit */
|
/* Try to exit early on limit hit */
|
||||||
if ((error = check_table_limit(tc, tei)) != 0 && count == 1) {
|
if ((error = check_table_limit(tc, tei)) != 0 && count == 1) {
|
||||||
IPFW_UH_WUNLOCK(ch);
|
IPFW_UH_WUNLOCK(ch);
|
||||||
@ -439,6 +444,11 @@ del_table_entry(struct ip_fw_chain *ch, struct tid_info *ti,
|
|||||||
return (ESRCH);
|
return (ESRCH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tc->locked != 0) {
|
||||||
|
IPFW_UH_WUNLOCK(ch);
|
||||||
|
return (EACCES);
|
||||||
|
}
|
||||||
|
|
||||||
if (tc->no.type != ti->type) {
|
if (tc->no.type != ti->type) {
|
||||||
IPFW_UH_WUNLOCK(ch);
|
IPFW_UH_WUNLOCK(ch);
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
@ -1616,6 +1626,8 @@ ipfw_modify_table(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
|||||||
tc->vftype = i->vftype;
|
tc->vftype = i->vftype;
|
||||||
if ((i->mflags & IPFW_TMFLAGS_LIMIT) != 0)
|
if ((i->mflags & IPFW_TMFLAGS_LIMIT) != 0)
|
||||||
tc->limit = i->limit;
|
tc->limit = i->limit;
|
||||||
|
if ((i->mflags & IPFW_TMFLAGS_LOCK) != 0)
|
||||||
|
tc->locked = ((i->flags & IPFW_TGFLAGS_LOCKED) != 0);
|
||||||
IPFW_UH_WUNLOCK(ch);
|
IPFW_UH_WUNLOCK(ch);
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
@ -1704,6 +1716,7 @@ create_table_internal(struct ip_fw_chain *ch, struct tid_info *ti,
|
|||||||
|
|
||||||
tc->vftype = i->vftype;
|
tc->vftype = i->vftype;
|
||||||
tc->limit = i->limit;
|
tc->limit = i->limit;
|
||||||
|
tc->locked = (i->flags & IPFW_TGFLAGS_LOCKED) != 0;
|
||||||
|
|
||||||
IPFW_UH_WLOCK(ch);
|
IPFW_UH_WLOCK(ch);
|
||||||
|
|
||||||
@ -1792,6 +1805,7 @@ export_table_info(struct ip_fw_chain *ch, struct table_config *tc,
|
|||||||
i->refcnt = tc->no.refcnt;
|
i->refcnt = tc->no.refcnt;
|
||||||
i->count = tc->count;
|
i->count = tc->count;
|
||||||
i->limit = tc->limit;
|
i->limit = tc->limit;
|
||||||
|
i->flags |= (tc->locked != 0) ? IPFW_TGFLAGS_LOCKED : 0;
|
||||||
i->size = tc->count * sizeof(ipfw_obj_tentry);
|
i->size = tc->count * sizeof(ipfw_obj_tentry);
|
||||||
i->size += sizeof(ipfw_obj_header) + sizeof(ipfw_xtable_info);
|
i->size += sizeof(ipfw_obj_header) + sizeof(ipfw_xtable_info);
|
||||||
strlcpy(i->tablename, tc->tablename, sizeof(i->tablename));
|
strlcpy(i->tablename, tc->tablename, sizeof(i->tablename));
|
||||||
|
Loading…
Reference in New Issue
Block a user