- rc= mme_parsekey(ip,&mme,prefix,preflen,0); if (rc) goto x_rc;
-
- for (insertat=0, search=mm->entries;
- insertat < mm->allocd &&
- search->prefixlen != -1;
- insertat++, search++) {
- cmp= mme_ordercompare(&mme,search);
- if (!cmp) {
- mme_free(&mme);
- Tcl_DecrRefCount(search->data);
- goto put_here;
+ rc= ame_parsekey(ip,&new,prefix,preflen,0); if (rc) return rc;
+
+ sr= am_search(am, &new, &searched);
+
+ replacements= &new;
+ nreplacements= 1;
+ replace_start= searched;
+ replace_end= searched;
+
+ switch (sr) {
+
+ case sr_notfound:
+ break;
+
+ case sr_exact:
+ replace_end= searched+1;
+ break;
+
+ case sr_aroundsmall:
+ u.ame= new;
+ u.sign= -1;
+ replace_start= am_binarychop(am, 0, searched, &u,
+ am_amend_aroundsmall_binchoptest, &dummy);
+ u.sign= +1;
+ replace_end= am_binarychop(am, searched+1, am.used, &u,
+ am_amend_aroundsmall_binchoptest, &dummy);
+ break;
+
+ case sr_inbig:
+ /* Urgh, we need to break it up. This produces
+ * - innermost prefix (the new one) as specified
+ * - one for each bitlength
+ * <= innermost
+ * > outermost (the existing one)
+ * each one specifying the outermost prefix plus zero, one,
+ * two, etc. bits of the innermost followed by one bit
+ * opposite to the innermost, with the outermost's data
+ * Eg, if we have ff/8=>A and want to amend so that ffff/16=>B
+ * then we replace ff/8 with ff0/9=>A ff8/10=>A ffc/11=>A ...
+ * ... fff8/14=>A fffc/15=>A fffe/16=>A ffff/16=>B.
+ */
+
+ breaking= &am.entries[searched];
+ nreplacements= new.prefix - breaking->prefixlen + 1;
+ fixme check integer overflow ^
+ replacements= TALLOC(sizeof(*replacements) * nreplacements);
+
+ for (fragmentlen= breaking->prefixlen + 1,
+ left_insert= 0, right_insert= nreplacements;
+ fragmentlen <= new.prefix;
+ fragmentlen++) {
+ int fragmentbytes;
+
+ fragmentbytes= prefix_bytes(fragmentlen)
+ fragment->prefixlen= fragmentlen;
+ fragment->prefix= TALLOC(fragmentbytes);
+ memcpy(fragment->prefix, new.prefix, fragmentbytes);
+ ame_clear_unwanted(fragment, fragmentbytes);
+
+ fragment->prefix[fragmentbytes] ^=
+ 0x80u >> ((fragmentlen+7) & 7);
+
+ switch (ame_compare(&fragment, &new)) {
+ case -2: replacements[left_insert++]= fragment; break;
+ case +2: replacements[--right_insert]= fragment; break;
+ default: abort();
+ }