Index: sys/netpfil/ipfw/ip_fw_sockopt.c =================================================================== --- sys/netpfil/ipfw/ip_fw_sockopt.c +++ sys/netpfil/ipfw/ip_fw_sockopt.c @@ -760,36 +760,36 @@ else if (V_autoinc_step > 1000) V_autoinc_step = 1000; - /* FIXME: Handle count > 1 */ - ci = rci; - krule = ci->krule; - rulenum = krule->rulenum; + for (ci = rci, i = 0; i < count; ci++, i++) { + krule = ci->krule; + rulenum = krule->rulenum; - /* find the insertion point, we will insert before */ - insert_before = rulenum ? rulenum + 1 : IPFW_DEFAULT_RULE; - i = ipfw_find_rule(chain, insert_before, 0); - /* duplicate first part */ - if (i > 0) - bcopy(chain->map, map, i * sizeof(struct ip_fw *)); - map[i] = krule; - /* duplicate remaining part, we always have the default rule */ - bcopy(chain->map + i, map + i + 1, - sizeof(struct ip_fw *) *(chain->n_rules - i)); - if (rulenum == 0) { - /* Compute rule number and write it back */ - rulenum = i > 0 ? map[i-1]->rulenum : 0; - if (rulenum < IPFW_DEFAULT_RULE - V_autoinc_step) - rulenum += V_autoinc_step; - krule->rulenum = rulenum; - /* Save number to userland rule */ - pnum = (uint16_t *)((caddr_t)ci->urule + ci->urule_numoff); - *pnum = rulenum; - } + /* find the insertion point, we will insert before */ + insert_before = rulenum ? rulenum + 1 : IPFW_DEFAULT_RULE; + i = ipfw_find_rule(chain, insert_before, 0); + /* duplicate first part */ + if (i > 0) + bcopy(chain->map, map, i * sizeof(struct ip_fw *)); + map[i] = krule; + /* duplicate remaining part, we always have the default rule */ + bcopy(chain->map + i, map + i + 1, + sizeof(struct ip_fw *) *(chain->n_rules - i)); + if (rulenum == 0) { + /* Compute rule number and write it back */ + rulenum = i > 0 ? map[i-1]->rulenum : 0; + if (rulenum < IPFW_DEFAULT_RULE - V_autoinc_step) + rulenum += V_autoinc_step; + krule->rulenum = rulenum; + /* Save number to userland rule */ + pnum = (uint16_t *)((caddr_t)ci->urule + ci->urule_numoff); + *pnum = rulenum; + } - krule->id = chain->id + 1; - update_skipto_cache(chain, map); - map = swap_map(chain, map, chain->n_rules + 1); - chain->static_len += RULEUSIZE0(krule); + krule->id = chain->id + 1; + update_skipto_cache(chain, map); + map = swap_map(chain, map, chain->n_rules + 1); + chain->static_len += RULEUSIZE0(krule); + } IPFW_UH_WUNLOCK(chain); if (map) free(map, M_IPFW); @@ -3001,12 +3001,6 @@ return (EINVAL); if ((clen % sizeof(uint64_t)) != 0) return (EINVAL); - - /* - * TODO: Permit adding multiple rules at once - */ - if (ctlv->count != 1) - return (ENOTSUP); clen -= sizeof(*ctlv);