static int ioctl_delete(ITF *itf,uint32_t ip,int flags) { ENTRY *entry,*walk,*next; if (!(entry = lookup_ip(itf,ip))) { diag(COMPONENT,DIAG_WARN,"ioctl_delete didn't find entry"); return -ENOENT; } if ((flags ^ entry->flags) & ATF_ARPSRV) return -EINVAL; send_notifications(entry,0); if ((entry->flags & ATF_ARPSRV) && entry->itf) for (walk = entry->itf->table; walk; walk = next) { next = walk->next; if (walk != entry && walk->state == as_resolv) { send_notifications(walk,0); if (!walk->vccs && !(walk->flags & ATF_PERM)) /* PERM is rather unlikely here, since this would be a second ARP server (only ARP servers can go as_resolv if PERM), but we'll check for it anyway. */ discard_entry(walk); else { STOP_TIMER(walk); walk->state = as_invalid; } } } discard_entry(entry); return 0; }
static void timeout(ENTRY *entry) { VCC *vcc,*next; entry->timer = NULL; switch (entry->state) { case as_resolv: send_notifications(entry,0); if ((entry->flags & ATF_ARPSRV) && !entry->vccs) { if (entry->itf) want_arp_srv(entry->itf); break; } if (!entry->vccs && !(entry->flags & (ATF_PERM | ATF_ARPSRV))) discard_entry(entry); else entry->state = as_invalid; break; case as_valid: if (!entry->vccs && !(entry->flags & (ATF_PERM | ATF_ARPSRV)) && entry->itf->arp_srv) { discard_entry(entry); break; } for (vcc = entry->vccs; vcc; vcc = next) { next = vcc->next; if (!vcc->connecting) if (set_ip(vcc->fd,0) < 0) { diag(COMPONENT,DIAG_ERROR,"set_ip(0): %s", strerror(errno)); disconnect_vcc(vcc); } } if (entry->svc && entry->itf->arp_srv && !(entry->flags & ATF_ARPSRV)) revalidate(entry); else { inarp_request(entry); START_TIMER(entry,REPLY); entry->state = as_invalid; } break; case as_invalid: if (!entry->svc) { inarp_request(entry); START_TIMER(entry,REPLY); } else if ((!entry->itf || !entry->itf->arp_srv) && !(entry->flags & ATF_PERM)) discard_entry(entry); break; default: diag(COMPONENT,DIAG_FATAL,"timed out in state %s", entry_state_name[entry->state]); } }
static void test_discard_entry_no_response(void **state) { struct entry *e; krb5_context context = *state; krb5_data req = string2data("I'm a test request"); e = insert_entry(context, &req, NULL, 0); discard_entry(context, e); assert_null(k5_hashtab_get(hash_table, req.data, req.length)); assert_int_equal(num_entries, 0); assert_int_equal(total_size, 0); }
static void learn_nak(uint32_t ip) { ITF *itf; ENTRY *entry; if (!ip) return; itf = lookup_itf_by_ip(ip); if (!itf) return; entry = lookup_ip(itf,ip); if (!entry || entry->state != as_resolv) return; send_notifications(entry,0); if (entry->flags & ATF_PERM) return; if (entry->vccs) entry->state = as_invalid; else discard_entry(entry); }
void vcc_detach(ENTRY *entry) { ENTRY *walk; /* immediately try to bring it up again if this was the connection to the ATMARP server and we still need it. Should delay this in case the ARP server has a real problem. @@@ */ /* UPDATE: the delay might work now ... */ if (entry->itf && entry->itf->arp_srv == entry) for (walk = entry->itf->table; walk; walk = walk->next) { if (walk->state == as_resolv) break; if (walk) { if (entry->state == as_valid) START_TIMER(entry,REGISTER); /* (void) want_arp_srv(entry->itf); */ return; } } if (!entry->vccs && entry->state == as_invalid && !(entry->flags & ATF_PERM)) discard_entry(entry); }
void vcc_failed(VCC *vcc) { ENTRY *entry,*next; diag(COMPONENT,DIAG_DEBUG,"failed VCC 0x%p",vcc); Q_REMOVE(vcc->entry->vccs,vcc); if (!(vcc->entry->flags & ATF_ARPSRV) || vcc->entry->vccs) { /* VCC is already closed */ vcc_detach(vcc->entry); free(vcc); return; } for (entry = vcc->entry->itf->table; entry; entry = next) { next = entry->next; if (entry == vcc->entry || entry->state != as_resolv) continue; if (entry->vccs || (entry->flags & ATF_PERM)) entry->state = as_invalid; else discard_entry(entry); } START_TIMER(vcc->entry,RETRY); free(vcc); }