/*---------------------------------------------------------------------------*/ int main(void) { EEPROM_main(); int i; uip_ipaddr_t ipaddr; struct timer periodic_timer, arp_timer; memcpy (&uip_ethaddr.addr[0], &eeprom.MAC[0], 6); AVR_init(); egpio_init(); clock_init(); mbuf_init(); adlc_init(); GICR = (1 << INT0); timer_set(&periodic_timer, CLOCK_SECOND / 2); timer_set(&arp_timer, CLOCK_SECOND * 10); nic_init(); uip_ipaddr(ipaddr, eeprom.IPAddr[0],eeprom.IPAddr[1],eeprom.IPAddr[2],eeprom.IPAddr[3]); uip_sethostaddr(ipaddr); uip_ipaddr(ipaddr, eeprom.Gateway[0],eeprom.Gateway[1],eeprom.Gateway[2],eeprom.Gateway[3]); uip_setdraddr(ipaddr); uip_ipaddr(ipaddr, eeprom.Subnet[0],eeprom.Subnet[1],eeprom.Subnet[2],eeprom.Subnet[3]); uip_setnetmask(ipaddr); telnetd_init(); aun_init(); internet_init(); egpio_write (EGPIO_STATUS_GREEN); while(1) { // check the econet for complete packets adlc_poller(); aun_poller (); uip_len = nic_poll(); if(uip_len > 0) { if(BUF->type == htons(UIP_ETHTYPE_IP)) { uip_arp_ipin(); uip_input(); /* If the above function invocation resulted in data that should be sent out on the network, the global variable uip_len is set to a value > 0. */ maybe_send(); } else if(BUF->type == htons(UIP_ETHTYPE_ARP)) { uip_arp_arpin(); /* If the above function invocation resulted in data that should be sent out on the network, the global variable uip_len is set to a value > 0. */ if(uip_len > 0) { nic_send(NULL); } } } else if(timer_expired(&periodic_timer)) { timer_reset(&periodic_timer); for(i = 0; i < UIP_CONNS; i++) { uip_periodic(i); maybe_send(); } #if UIP_UDP for(i = 0; i < UIP_UDP_CONNS; i++) { uip_udp_periodic(i); maybe_send(); } #endif /* UIP_UDP */ /* Call the ARP timer function every 10 seconds. */ if(timer_expired(&arp_timer)) { timer_reset(&arp_timer); uip_arp_timer(); } } } }
krb5_error_code k5_sendto(krb5_context context, const krb5_data *message, const krb5_data *realm, const struct serverlist *servers, k5_transport_strategy strategy, struct sendto_callback_info* callback_info, krb5_data *reply, struct sockaddr *remoteaddr, socklen_t *remoteaddrlen, int *server_used, /* return 0 -> keep going, 1 -> quit */ int (*msg_handler)(krb5_context, const krb5_data *, void *), void *msg_handler_data) { int pass; time_ms delay; krb5_error_code retval; struct conn_state *conns = NULL, *state, **tailptr, *next, *winner; size_t s; struct select_state *sel_state = NULL, *seltemp; char *udpbuf = NULL; krb5_boolean done = FALSE; *reply = empty_data(); /* One for use here, listing all our fds in use, and one for * temporary use in service_fds, for the fds of interest. */ sel_state = malloc(2 * sizeof(*sel_state)); if (sel_state == NULL) { retval = ENOMEM; goto cleanup; } seltemp = &sel_state[1]; cm_init_selstate(sel_state); /* First pass: resolve server hosts, communicate with resulting addresses * of the preferred transport, and wait 1s for an answer from each. */ for (s = 0; s < servers->nservers && !done; s++) { /* Find the current tail pointer. */ for (tailptr = &conns; *tailptr != NULL; tailptr = &(*tailptr)->next); retval = resolve_server(context, realm, servers, s, strategy, message, &udpbuf, &conns); if (retval) goto cleanup; for (state = *tailptr; state != NULL && !done; state = state->next) { /* Contact each new connection, deferring those which use the * non-preferred RFC 4120 transport. */ if (state->defer) continue; if (maybe_send(context, state, message, sel_state, realm, callback_info)) continue; done = service_fds(context, sel_state, 1000, conns, seltemp, realm, msg_handler, msg_handler_data, &winner); } } /* Complete the first pass by contacting servers of the non-preferred RFC * 4120 transport (if given), waiting 1s for an answer from each. */ for (state = conns; state != NULL && !done; state = state->next) { if (!state->defer) continue; if (maybe_send(context, state, message, sel_state, realm, callback_info)) continue; done = service_fds(context, sel_state, 1000, conns, seltemp, realm, msg_handler, msg_handler_data, &winner); } /* Wait for two seconds at the end of the first pass. */ if (!done) { done = service_fds(context, sel_state, 2000, conns, seltemp, realm, msg_handler, msg_handler_data, &winner); } /* Make remaining passes over all of the connections. */ delay = 4000; for (pass = 1; pass < MAX_PASS && !done; pass++) { for (state = conns; state != NULL && !done; state = state->next) { if (maybe_send(context, state, message, sel_state, realm, callback_info)) continue; done = service_fds(context, sel_state, 1000, conns, seltemp, realm, msg_handler, msg_handler_data, &winner); if (sel_state->nfds == 0) break; } /* Wait for the delay backoff at the end of this pass. */ if (!done) { done = service_fds(context, sel_state, delay, conns, seltemp, realm, msg_handler, msg_handler_data, &winner); } if (sel_state->nfds == 0) break; delay *= 2; } if (sel_state->nfds == 0 || !done || winner == NULL) { retval = KRB5_KDC_UNREACH; goto cleanup; } /* Success! */ *reply = make_data(winner->in.buf, winner->in.pos); retval = 0; winner->in.buf = NULL; if (server_used != NULL) *server_used = winner->server_index; if (remoteaddr != NULL && remoteaddrlen != 0 && *remoteaddrlen > 0) (void)getpeername(winner->fd, remoteaddr, remoteaddrlen); TRACE_SENDTO_KDC_RESPONSE(context, reply->length, &winner->addr); cleanup: for (state = conns; state != NULL; state = next) { next = state->next; if (state->fd != INVALID_SOCKET) { if (socktype_for_transport(state->addr.transport) == SOCK_STREAM) TRACE_SENDTO_KDC_TCP_DISCONNECT(context, &state->addr); closesocket(state->fd); free_http_tls_data(context, state); } if (state->state == READING && state->in.buf != udpbuf) free(state->in.buf); if (callback_info) { callback_info->pfn_cleanup(callback_info->data, &state->callback_buffer); } free(state); } if (reply->data != udpbuf) free(udpbuf); free(sel_state); return retval; }
krb5_error_code k5_sendto(krb5_context context, const krb5_data *message, const struct serverlist *servers, int socktype1, int socktype2, struct sendto_callback_info* callback_info, krb5_data *reply, struct sockaddr *remoteaddr, socklen_t *remoteaddrlen, int *server_used, /* return 0 -> keep going, 1 -> quit */ int (*msg_handler)(krb5_context, const krb5_data *, void *), void *msg_handler_data) { int pass, delay; krb5_error_code retval; struct conn_state *conns = NULL, *state, **tailptr, *next, *winner; size_t s; struct select_state *sel_state = NULL, *seltemp; char *udpbuf = NULL; krb5_boolean done = FALSE; reply->data = 0; reply->length = 0; /* One for use here, listing all our fds in use, and one for * temporary use in service_fds, for the fds of interest. */ sel_state = malloc(2 * sizeof(*sel_state)); if (sel_state == NULL) { retval = ENOMEM; goto cleanup; } seltemp = &sel_state[1]; sel_state->max = 0; sel_state->nfds = 0; sel_state->end_time.tv_sec = sel_state->end_time.tv_usec = 0; FD_ZERO(&sel_state->rfds); FD_ZERO(&sel_state->wfds); FD_ZERO(&sel_state->xfds); /* First pass: resolve server hosts, communicate with resulting addresses * of the preferred socktype, and wait 1s for an answer from each. */ for (s = 0; s < servers->nservers && !done; s++) { /* Find the current tail pointer. */ for (tailptr = &conns; *tailptr != NULL; tailptr = &(*tailptr)->next); retval = resolve_server(context, servers, s, socktype1, socktype2, message, &udpbuf, &conns); if (retval) goto cleanup; for (state = *tailptr; state != NULL && !done; state = state->next) { /* Contact each new connection whose socktype matches socktype1. */ if (state->socktype != socktype1) continue; if (maybe_send(context, state, sel_state, callback_info)) continue; done = service_fds(context, sel_state, 1, conns, seltemp, msg_handler, msg_handler_data, &winner); } } /* Complete the first pass by contacting servers of the non-preferred * socktype (if given), waiting 1s for an answer from each. */ for (state = conns; state != NULL && !done; state = state->next) { if (state->socktype != socktype2) continue; if (maybe_send(context, state, sel_state, callback_info)) continue; done = service_fds(context, sel_state, 1, state, seltemp, msg_handler, msg_handler_data, &winner); } /* Wait for two seconds at the end of the first pass. */ if (!done) { done = service_fds(context, sel_state, 2, conns, seltemp, msg_handler, msg_handler_data, &winner); } /* Make remaining passes over all of the connections. */ delay = 4; for (pass = 1; pass < MAX_PASS && !done; pass++) { for (state = conns; state != NULL && !done; state = state->next) { if (maybe_send(context, state, sel_state, callback_info)) continue; done = service_fds(context, sel_state, 1, conns, seltemp, msg_handler, msg_handler_data, &winner); if (sel_state->nfds == 0) break; } /* Wait for the delay backoff at the end of this pass. */ if (!done) { done = service_fds(context, sel_state, delay, conns, seltemp, msg_handler, msg_handler_data, &winner); } if (sel_state->nfds == 0) break; delay *= 2; } if (sel_state->nfds == 0 || !done || winner == NULL) { retval = KRB5_KDC_UNREACH; goto cleanup; } /* Success! */ TRACE_SENDTO_KDC_RESPONSE(context, winner); reply->data = winner->x.in.buf; reply->length = winner->x.in.pos - winner->x.in.buf; retval = 0; winner->x.in.buf = NULL; if (server_used != NULL) *server_used = winner->server_index; if (remoteaddr != NULL && remoteaddrlen != 0 && *remoteaddrlen > 0) (void)getpeername(winner->fd, remoteaddr, remoteaddrlen); cleanup: for (state = conns; state != NULL; state = next) { next = state->next; if (state->fd != INVALID_SOCKET) closesocket(state->fd); if (state->state == READING && state->x.in.buf != udpbuf) free(state->x.in.buf); if (callback_info) { callback_info->pfn_cleanup(callback_info->context, &state->callback_buffer); } free(state); } if (reply->data != udpbuf) free(udpbuf); free(sel_state); return retval; }