static void generate_cpp (const std::string &name_, const basic_state_machine<char_type, id_type> &sm_, const bool pointers_, std::ostream &os_) { typedef basic_state_machine<char_type, id_type> sm; typedef typename sm::internals internals; const internals &internals_ = sm_.data (); std::size_t additional_tabs_ = 0; os_ << "template<typename iter_type, typename id_type>\n"; os_ << "void " << name_ << " (lexertl::"; if (internals_._features & recursive_bit) { os_ << "basic_push_match_results"; } else { os_ << "basic_match_results"; } os_ << "<iter_type, id_type> &results_)\n"; os_ << "{\n"; os_ << " typedef lexertl::"; if (internals_._features & recursive_bit) { os_ << "basic_push_match_results"; } else { os_ << "basic_match_results"; } os_ << "<iter_type, id_type> results;\n"; os_ << " typename results::iter_type end_ = results_.eoi;\n"; if (internals_._features & skip_bit) { os_ << "skip:\n"; } os_ << " typename results::iter_type start_ = results_.start = " "results_.end;\n\n"; if (internals_._features & again_bit) { os_ << "again:\n"; } os_ << " if (start_ == end_)\n"; os_ << " {\n"; // We want a number regardless of id_type. os_ << " results_.id = " << static_cast<std::size_t> (internals_._eoi) << ";\n"; os_ << " results_.user_id = results::npos ();\n"; os_ << " results_.end = start_;\n"; os_ << " return;\n"; os_ << " }\n\n"; os_ << " typename results::iter_type curr_ = start_;\n"; if (internals_._features & bol_bit) { os_ << " bool bol_ = results_.bol;\n"; } dump_tables (sm_, 1, pointers_, os_); if (internals_._dfa->size () > 1) { os_ << " const id_type *lookup_ = lookups_[results_.state];\n"; os_ << " const id_type dfa_alphabet_ = dfa_alphabets_" "[results_.state];\n"; os_ << " const "; if (pointers_) { os_ << "void * const"; } else { os_ << "id_type"; } os_ << " *dfa_ = dfas_[results_.state];\n"; } os_ << " const "; if (pointers_) { os_ << "void * const"; } else { os_ << "id_type"; } os_ << " *ptr_ = dfa_ + dfa_alphabet_;\n"; os_ << " bool end_state_ = *ptr_ != 0;\n"; if (internals_._features & recursive_bit) { os_ << " bool pop_ = ("; if (pointers_) { // Done this way for GCC: os_ << "static_cast<id_type>(reinterpret_cast<ptrdiff_t>("; } os_ << "*ptr_"; if (pointers_) { os_ << ')'; } os_ <<" & " << pop_dfa_bit; if (pointers_) { os_ << ')'; } os_ << ") != 0;\n"; } os_ << " id_type id_ = "; if (pointers_) { // Done this way for GCC: os_ << "static_cast<id_type>(reinterpret_cast<ptrdiff_t>("; } os_ << "*(ptr_ + " << id_index << ")"; if (pointers_) { os_ << "))"; } os_ << ";\n"; os_ << " id_type uid_ = "; if (pointers_) { // Done this way for GCC: os_ << "static_cast<id_type>(reinterpret_cast<ptrdiff_t>("; } os_ << "*(ptr_ + " << user_id_index << ")"; if (pointers_) { os_ << "))"; } os_ << ";\n"; if (internals_._features & recursive_bit) { os_ << " id_type push_dfa_ = "; if (pointers_) { // Done this way for GCC: os_ << "static_cast<id_type>(reinterpret_cast<ptrdiff_t>("; } os_ << "*(ptr_ + " << push_dfa_index << ")"; if (pointers_) { os_ << "))"; } os_ << ";\n"; } if (internals_._dfa->size () > 1) { os_ << " id_type start_state_ = results_.state;\n"; } if (internals_._features & bol_bit) { os_ << " bool end_bol_ = bol_;\n"; } os_ << " typename results::iter_type end_token_ = curr_;\n"; if (internals_._features & eol_bit) { os_ << " "; if (pointers_) { os_ << "const void * const *"; } else { os_ << "id_type "; } os_ << "EOL_state_ = 0;\n"; } os_ << '\n'; if (internals_._features & bol_bit) { os_ << " if (bol_)\n"; os_ << " {\n"; os_ << " const "; if (pointers_) { os_ << "void *"; } else { os_ << "id_type "; } os_ << "state_ = *dfa_;\n\n"; os_ << " if (state_)\n"; os_ << " {\n"; os_ << " ptr_ = "; if (pointers_) { os_ << "reinterpret_cast<void * const *>(state_);\n"; } else { os_ << "&dfa_[state_ * dfa_alphabet_];\n"; } os_ << " }\n"; os_ << " }\n\n"; } os_ << " while (curr_ != end_)\n"; os_ << " {\n"; if (internals_._features & eol_bit) { os_ << " EOL_state_ = "; if (pointers_) { os_ << "reinterpret_cast<const void * const *>("; } os_ << "ptr_[" << eol_index << ']'; if (pointers_) { os_ << ')'; } os_ << ";\n\n"; os_ << " if (EOL_state_ && *curr_ == '\\n')\n"; os_ << " {\n"; os_ << " ptr_ = "; if (pointers_) { os_ << "EOL_state_"; } else { os_ << "&dfa_[EOL_state_ * dfa_alphabet_]"; } os_ << ";\n"; os_ << " }\n"; os_ << " else\n"; os_ << " {\n"; ++additional_tabs_; } output_char_loop (internals_._features, additional_tabs_, pointers_, os_, bool_<(sizeof (typename sm::traits::input_char_type) > 1)> ()); if (internals_._features & eol_bit) { output_tabs (additional_tabs_, os_); os_ << " }\n"; --additional_tabs_; } os_ << '\n'; os_ << " if (*ptr_)\n"; os_ << " {\n"; os_ << " end_state_ = true;\n"; if (internals_._features & recursive_bit) { os_ << " pop_ = ("; if (pointers_) { // Done this way for GCC: os_ << "static_cast<id_type>(reinterpret_cast<ptrdiff_t>("; } os_ << "*ptr_"; if (pointers_) { os_ << ')'; } os_ <<" & " << pop_dfa_bit; if (pointers_) { os_ << ')'; } os_ << ") != 0;\n"; } os_ << " id_ = "; if (pointers_) { // Done this way for GCC: os_ << "static_cast<id_type>(reinterpret_cast<ptrdiff_t>("; } os_ << "*(ptr_ + " << id_index << ")"; if (pointers_) { os_ << "))"; } os_ << ";\n"; os_ << " uid_ = "; if (pointers_) { // Done this way for GCC: os_ << "static_cast<id_type>(reinterpret_cast<ptrdiff_t>("; } os_ << "*(ptr_ + " << user_id_index << ")"; if (pointers_) { os_ << "))"; } os_ << ";\n"; if (internals_._features & recursive_bit) { os_ << " push_dfa_ = "; if (pointers_) { // Done this way for GCC: os_ << "static_cast<id_type>(reinterpret_cast<ptrdiff_t>("; } os_ << "*(ptr_ + " << push_dfa_index << ')'; if (pointers_) { os_ << "))"; } os_ << ";\n"; } if (internals_._dfa->size () > 1) { os_ << " start_state_ = "; if (pointers_) { // Done this way for GCC: os_ << "static_cast<id_type>(reinterpret_cast<ptrdiff_t>("; } os_ << "*(ptr_ + " << next_dfa_index << ')'; if (pointers_) { os_ << "))"; } os_ << ";\n"; } if (internals_._features & bol_bit) { os_ << " end_bol_ = bol_;\n"; } os_ << " end_token_ = curr_;\n"; os_ << " }\n"; os_ << " }\n\n"; output_quit (os_, bool_<(sizeof (typename sm::traits::input_char_type) > 1)> ()); if (internals_._features & eol_bit) { os_ << " if (curr_ == end_)\n"; os_ << " {\n"; os_ << " EOL_state_ = "; if (pointers_) { os_ << "reinterpret_cast<const void * const *>("; } os_ << "ptr_[" << eol_index << ']'; if (pointers_) { os_ << ')'; } os_ << ";\n"; os_ << "\n"; os_ << " if (EOL_state_)\n"; os_ << " {\n"; os_ << " ptr_ = "; if (pointers_) { os_ << "EOL_state_"; } else { os_ << "&dfa_[EOL_state_ * dfa_alphabet_]"; } os_ << ";\n\n"; os_ << " if (*ptr_)\n"; os_ << " {\n"; os_ << " end_state_ = true;\n"; if (internals_._features & recursive_bit) { os_ << " pop_ = ("; if (pointers_) { // Done this way for GCC: os_ << "static_cast<id_type>(reinterpret_cast<ptrdiff_t>("; } os_ << "*ptr_"; if (pointers_) { os_ << ')'; } os_ <<" & " << pop_dfa_bit; if (pointers_) { os_ << ')'; } os_ << ") != 0;\n"; } os_ << " id_ = "; if (pointers_) { // Done this way for GCC: os_ << "static_cast<id_type>(reinterpret_cast<ptrdiff_t>("; } os_ << "*(ptr_ + " << id_index << ")"; if (pointers_) { os_ << "))"; } os_ << ";\n"; os_ << " uid_ = "; if (pointers_) { // Done this way for GCC: os_ << "static_cast<id_type>(reinterpret_cast<ptrdiff_t>("; } os_ << "*(ptr_ + " << user_id_index << ")"; if (pointers_) { os_ << "))"; } os_ <<";\n"; if (internals_._features & recursive_bit) { os_ << " push_dfa_ = "; if (pointers_) { // Done this way for GCC: os_ << "static_cast<id_type>(reinterpret_cast<ptrdiff_t>("; } os_ << "*(ptr_ + " << push_dfa_index << ')'; if (pointers_) { os_ << "))"; } os_ << ";\n"; } if (internals_._dfa->size () > 1) { os_ << " start_state_ = "; if (pointers_) { // Done this way for GCC: os_ << "static_cast<id_type>(reinterpret_cast<ptrdiff_t>("; } os_ << "*(ptr_ + " << next_dfa_index << ')'; if (pointers_) { os_ << "))"; } os_ << ";\n"; } if (internals_._features & bol_bit) { os_ << " end_bol_ = bol_;\n"; } os_ << " end_token_ = curr_;\n"; os_ << " }\n"; os_ << " }\n"; os_ << " }\n\n"; } os_ << " if (end_state_)\n"; os_ << " {\n"; os_ << " // Return longest match\n"; if (internals_._features & recursive_bit) { os_ << " if (pop_)\n"; os_ << " {\n"; os_ << " start_state_ = results_." "stack.top ().first;\n"; os_ << " results_.stack.pop ();\n"; os_ << " }\n"; os_ << " else if (push_dfa_ != results_.npos ())\n"; os_ << " {\n"; os_ << " results_.stack.push (typename results::" "id_type_pair\n"; os_ << " (push_dfa_, id_));\n"; os_ << " }\n\n"; } if (internals_._dfa->size () > 1) { os_ << " results_.state = start_state_;\n"; } if (internals_._features & bol_bit) { os_ << " results_.bol = end_bol_;\n"; } os_ << " results_.end = end_token_;\n"; if (internals_._features & skip_bit) { // We want a number regardless of id_type. os_ << "\n if (id_ == results_.skip ()) goto skip;\n"; } if (internals_._features & again_bit) { // We want a number regardless of id_type. os_ << "\n if (id_ == " << static_cast<std::size_t>(internals_._eoi); if (internals_._features & recursive_bit) { os_ << " || (pop_ && !results_.stack.empty () &&\n"; // We want a number regardless of id_type. os_ << " results_.stack.top ().second == " << static_cast<std::size_t>(internals_._eoi) << ')'; } os_ << ")\n"; os_ << " {\n"; os_ << " start_ = end_token_;\n"; os_ << " goto again;\n"; os_ << " }\n"; } os_ << " }\n"; os_ << " else\n"; os_ << " {\n"; os_ << " // No match causes char to be skipped\n"; if (internals_._features & bol_bit) { os_ << " results_.bol = *start_ == '\\n';\n"; } os_ << " results_.end = results_.start;\n"; os_ << " ++results_.end;\n"; os_ << " id_ = results::npos ();\n"; os_ << " uid_ = results::npos ();\n"; os_ << " }\n\n"; os_ << " results_.id = id_;\n"; os_ << " results_.user_id = uid_;\n"; os_ << "}\n"; }
int main(int argc, char **argv) { struct sockaddr_in6 sin6; int rc, fd, i, opt; time_t expiry_time, source_expiry_time, kernel_dump_time; const char **config_files = NULL; int num_config_files = 0; void *vrc; unsigned int seed; struct interface *ifp; gettime(&now); rc = read_random_bytes(&seed, sizeof(seed)); if(rc < 0) { perror("read(random)"); seed = 42; } seed ^= (now.tv_sec ^ now.tv_usec); srandom(seed); parse_address("ff02:0:0:0:0:0:1:6", protocol_group, NULL); protocol_port = 6696; change_smoothing_half_life(4); has_ipv6_subtrees = kernel_has_ipv6_subtrees(); while(1) { opt = getopt(argc, argv, "m:p:h:H:i:k:A:sruS:d:g:G:lwz:M:t:T:c:C:DL:I:V"); if(opt < 0) break; switch(opt) { case 'm': rc = parse_address(optarg, protocol_group, NULL); if(rc < 0) goto usage; if(protocol_group[0] != 0xff) { fprintf(stderr, "%s is not a multicast address\n", optarg); goto usage; } if(protocol_group[1] != 2) { fprintf(stderr, "Warning: %s is not a link-local multicast address\n", optarg); } break; case 'p': protocol_port = parse_nat(optarg); if(protocol_port <= 0 || protocol_port > 0xFFFF) goto usage; break; case 'h': default_wireless_hello_interval = parse_thousands(optarg); if(default_wireless_hello_interval <= 0 || default_wireless_hello_interval > 0xFFFF * 10) goto usage; break; case 'H': default_wired_hello_interval = parse_thousands(optarg); if(default_wired_hello_interval <= 0 || default_wired_hello_interval > 0xFFFF * 10) goto usage; break; case 'k': kernel_metric = parse_nat(optarg); if(kernel_metric < 0 || kernel_metric > 0xFFFF) goto usage; break; case 'A': allow_duplicates = parse_nat(optarg); if(allow_duplicates < 0 || allow_duplicates > 0xFFFF) goto usage; break; case 's': split_horizon = 0; break; case 'r': random_id = 1; break; case 'u': keep_unfeasible = 1; break; case 'S': state_file = optarg; break; case 'd': debug = parse_nat(optarg); if(debug < 0) goto usage; break; case 'g': case 'G': if(opt == 'g') local_server_write = 0; else local_server_write = 1; if(optarg[0] == '/') { local_server_port = -1; free(local_server_path); local_server_path = strdup(optarg); } else { local_server_port = parse_nat(optarg); free(local_server_path); local_server_path = NULL; if(local_server_port <= 0 || local_server_port > 0xFFFF) goto usage; } break; case 'l': link_detect = 1; break; case 'w': all_wireless = 1; break; case 'z': { char *comma; diversity_kind = (int)strtol(optarg, &comma, 0); if(*comma == '\0') diversity_factor = 128; else if(*comma == ',') diversity_factor = parse_nat(comma + 1); else goto usage; if(diversity_factor <= 0 || diversity_factor > 256) goto usage; } break; case 'M': { int l = parse_nat(optarg); if(l < 0 || l > 3600) goto usage; change_smoothing_half_life(l); break; } case 't': export_table = parse_nat(optarg); if(export_table < 0 || export_table > 0xFFFF) goto usage; break; case 'T': if(add_import_table(parse_nat(optarg))) goto usage; break; case 'c': config_files = realloc(config_files, (num_config_files + 1) * sizeof(char*)); if(config_files == NULL) { fprintf(stderr, "Couldn't allocate config file.\n"); exit(1); } config_files[num_config_files++] = optarg; break; case 'C': rc = parse_config_from_string(optarg, strlen(optarg), NULL); if(rc != CONFIG_ACTION_DONE) { fprintf(stderr, "Couldn't parse configuration from command line.\n"); exit(1); } break; case 'D': do_daemonise = 1; break; case 'L': logfile = optarg; break; case 'I': pidfile = optarg; break; case 'V': fprintf(stderr, "%s\n", BABELD_VERSION); exit(0); break; default: goto usage; } } if(num_config_files == 0) { if(access("/etc/babeld.conf", F_OK) >= 0) { config_files = malloc(sizeof(char*)); if(config_files == NULL) { fprintf(stderr, "Couldn't allocate config file.\n"); exit(1); } config_files[num_config_files++] = "/etc/babeld.conf"; } } for(i = 0; i < num_config_files; i++) { int line; rc = parse_config_from_file(config_files[i], &line); if(rc < 0) { fprintf(stderr, "Couldn't parse configuration from file %s " "(error at line %d).\n", config_files[i], line); exit(1); } } free(config_files); if(default_wireless_hello_interval <= 0) default_wireless_hello_interval = 4000; default_wireless_hello_interval = MAX(default_wireless_hello_interval, 5); if(default_wired_hello_interval <= 0) default_wired_hello_interval = 4000; default_wired_hello_interval = MAX(default_wired_hello_interval, 5); resend_delay = 2000; resend_delay = MIN(resend_delay, default_wireless_hello_interval / 2); resend_delay = MIN(resend_delay, default_wired_hello_interval / 2); resend_delay = MAX(resend_delay, 20); if(do_daemonise) { if(logfile == NULL) logfile = "/var/log/babeld.log"; } rc = reopen_logfile(); if(rc < 0) { perror("reopen_logfile()"); exit(1); } fd = open("/dev/null", O_RDONLY); if(fd < 0) { perror("open(null)"); exit(1); } rc = dup2(fd, 0); if(rc < 0) { perror("dup2(null, 0)"); exit(1); } close(fd); if(do_daemonise) { rc = daemonise(); if(rc < 0) { perror("daemonise"); exit(1); } } if(pidfile && pidfile[0] != '\0') { int pfd, len; char buf[100]; len = snprintf(buf, 100, "%lu", (unsigned long)getpid()); if(len < 0 || len >= 100) { perror("snprintf(getpid)"); exit(1); } pfd = open(pidfile, O_WRONLY | O_CREAT | O_EXCL, 0644); if(pfd < 0) { char buf[40]; snprintf(buf, 40, "creat(%s)", pidfile); buf[39] = '\0'; perror(buf); exit(1); } rc = write(pfd, buf, len); if(rc < len) { perror("write(pidfile)"); goto fail_pid; } close(pfd); } rc = kernel_setup(1); if(rc < 0) { fprintf(stderr, "kernel_setup failed.\n"); goto fail_pid; } rc = kernel_setup_socket(1); if(rc < 0) { fprintf(stderr, "kernel_setup_socket failed.\n"); kernel_setup(0); goto fail_pid; } rc = finalise_config(); if(rc < 0) { fprintf(stderr, "Couldn't finalise configuration.\n"); goto fail; } for(i = optind; i < argc; i++) { vrc = add_interface(argv[i], NULL); if(vrc == NULL) goto fail; } if(interfaces == NULL) { fprintf(stderr, "Eek... asked to run on no interfaces!\n"); goto fail; } if(!have_id && !random_id) { /* We use all available interfaces here, since this increases the chances of getting a stable router-id in case the set of Babel interfaces changes. */ for(i = 1; i < 256; i++) { char buf[IF_NAMESIZE], *ifname; unsigned char eui[8]; ifname = if_indextoname(i, buf); if(ifname == NULL) continue; rc = if_eui64(ifname, i, eui); if(rc < 0) continue; memcpy(myid, eui, 8); have_id = 1; break; } } if(!have_id) { if(!random_id) fprintf(stderr, "Warning: couldn't find router id -- " "using random value.\n"); rc = read_random_bytes(myid, 8); if(rc < 0) { perror("read(random)"); goto fail; } /* Clear group and global bits */ myid[0] &= ~3; } myseqno = (random() & 0xFFFF); fd = open(state_file, O_RDONLY); if(fd < 0 && errno != ENOENT) perror("open(babel-state)"); rc = unlink(state_file); if(fd >= 0 && rc < 0) { perror("unlink(babel-state)"); /* If we couldn't unlink it, it's probably stale. */ close(fd); fd = -1; } if(fd >= 0) { char buf[100]; int s; rc = read(fd, buf, 99); if(rc < 0) { perror("read(babel-state)"); } else { buf[rc] = '\0'; rc = sscanf(buf, "%d\n", &s); if(rc == 1 && s >= 0 && s <= 0xFFFF) { myseqno = seqno_plus(s, 1); } else { fprintf(stderr, "Couldn't parse babel-state.\n"); } } close(fd); fd = -1; } protocol_socket = babel_socket(protocol_port); if(protocol_socket < 0) { perror("Couldn't create link local socket"); goto fail; } if(local_server_port >= 0) { local_server_socket = tcp_server_socket(local_server_port, 1); if(local_server_socket < 0) { perror("local_server_socket"); goto fail; } } else if(local_server_path) { local_server_socket = unix_server_socket(local_server_path); if(local_server_socket < 0) { perror("local_server_socket"); goto fail; } } init_signals(); rc = resize_receive_buffer(1500); if(rc < 0) goto fail; if(receive_buffer == NULL) goto fail; check_interfaces(); rc = check_xroutes(0); if(rc < 0) fprintf(stderr, "Warning: couldn't check exported routes.\n"); rc = check_rules(); if(rc < 0) fprintf(stderr, "Warning: couldn't check rules.\n"); kernel_routes_changed = 0; kernel_rules_changed = 0; kernel_link_changed = 0; kernel_addr_changed = 0; kernel_dump_time = now.tv_sec + roughly(30); schedule_neighbours_check(5000, 1); schedule_interfaces_check(30000, 1); expiry_time = now.tv_sec + roughly(30); source_expiry_time = now.tv_sec + roughly(300); /* Make some noise so that others notice us, and send retractions in case we were restarted recently */ FOR_ALL_INTERFACES(ifp) { if(!if_up(ifp)) continue; /* Apply jitter before we send the first message. */ usleep(roughly(10000)); gettime(&now); send_hello(ifp); send_wildcard_retraction(ifp); } FOR_ALL_INTERFACES(ifp) { if(!if_up(ifp)) continue; usleep(roughly(10000)); gettime(&now); send_hello(ifp); send_wildcard_retraction(ifp); send_self_update(ifp); send_request(ifp, NULL, 0, NULL, 0); flushupdates(ifp); flushbuf(ifp); } debugf("Entering main loop.\n"); while(1) { struct timeval tv; fd_set readfds; gettime(&now); tv = check_neighbours_timeout; timeval_min(&tv, &check_interfaces_timeout); timeval_min_sec(&tv, expiry_time); timeval_min_sec(&tv, source_expiry_time); timeval_min_sec(&tv, kernel_dump_time); timeval_min(&tv, &resend_time); FOR_ALL_INTERFACES(ifp) { if(!if_up(ifp)) continue; timeval_min(&tv, &ifp->flush_timeout); timeval_min(&tv, &ifp->hello_timeout); timeval_min(&tv, &ifp->update_timeout); timeval_min(&tv, &ifp->update_flush_timeout); } timeval_min(&tv, &unicast_flush_timeout); FD_ZERO(&readfds); if(timeval_compare(&tv, &now) > 0) { int maxfd = 0; timeval_minus(&tv, &tv, &now); FD_SET(protocol_socket, &readfds); maxfd = MAX(maxfd, protocol_socket); if(kernel_socket < 0) kernel_setup_socket(1); if(kernel_socket >= 0) { FD_SET(kernel_socket, &readfds); maxfd = MAX(maxfd, kernel_socket); } if(local_server_socket >= 0 && num_local_sockets < MAX_LOCAL_SOCKETS) { FD_SET(local_server_socket, &readfds); maxfd = MAX(maxfd, local_server_socket); } for(i = 0; i < num_local_sockets; i++) { FD_SET(local_sockets[i].fd, &readfds); maxfd = MAX(maxfd, local_sockets[i].fd); } rc = select(maxfd + 1, &readfds, NULL, NULL, &tv); if(rc < 0) { if(errno != EINTR) { perror("select"); sleep(1); } rc = 0; FD_ZERO(&readfds); } } gettime(&now); if(exiting) break; if(kernel_socket >= 0 && FD_ISSET(kernel_socket, &readfds)) { struct kernel_filter filter = {0}; filter.route = kernel_route_notify; filter.addr = kernel_addr_notify; filter.link = kernel_link_notify; filter.rule = kernel_rule_notify; kernel_callback(&filter); } if(FD_ISSET(protocol_socket, &readfds)) { rc = babel_recv(protocol_socket, receive_buffer, receive_buffer_size, (struct sockaddr*)&sin6, sizeof(sin6)); if(rc < 0) { if(errno != EAGAIN && errno != EINTR) { perror("recv"); sleep(1); } } else { FOR_ALL_INTERFACES(ifp) { if(!if_up(ifp)) continue; if(ifp->ifindex == sin6.sin6_scope_id) { parse_packet((unsigned char*)&sin6.sin6_addr, ifp, receive_buffer, rc); VALGRIND_MAKE_MEM_UNDEFINED(receive_buffer, receive_buffer_size); break; } } } } if(local_server_socket >= 0 && FD_ISSET(local_server_socket, &readfds)) accept_local_connections(); i = 0; while(i < num_local_sockets) { if(FD_ISSET(local_sockets[i].fd, &readfds)) { rc = local_read(&local_sockets[i]); if(rc <= 0) { if(rc < 0) { if(errno == EINTR || errno == EAGAIN) continue; perror("read(local_socket)"); } local_socket_destroy(i); } } i++; } if(reopening) { kernel_dump_time = now.tv_sec; check_neighbours_timeout = now; expiry_time = now.tv_sec; rc = reopen_logfile(); if(rc < 0) { perror("reopen_logfile"); break; } reopening = 0; } if(kernel_link_changed || kernel_addr_changed) { check_interfaces(); kernel_link_changed = 0; } if(kernel_routes_changed || kernel_addr_changed || kernel_rules_changed || now.tv_sec >= kernel_dump_time) { rc = check_xroutes(1); if(rc < 0) fprintf(stderr, "Warning: couldn't check exported routes.\n"); rc = check_rules(); if(rc < 0) fprintf(stderr, "Warning: couldn't check rules.\n"); kernel_routes_changed = kernel_rules_changed = kernel_addr_changed = 0; if(kernel_socket >= 0) kernel_dump_time = now.tv_sec + roughly(300); else kernel_dump_time = now.tv_sec + roughly(30); } if(timeval_compare(&check_neighbours_timeout, &now) < 0) { int msecs; msecs = check_neighbours(); /* Multiply by 3/2 to allow neighbours to expire. */ msecs = MAX(3 * msecs / 2, 10); schedule_neighbours_check(msecs, 1); } if(timeval_compare(&check_interfaces_timeout, &now) < 0) { check_interfaces(); schedule_interfaces_check(30000, 1); } if(now.tv_sec >= expiry_time) { expire_routes(); expire_resend(); expiry_time = now.tv_sec + roughly(30); } if(now.tv_sec >= source_expiry_time) { expire_sources(); source_expiry_time = now.tv_sec + roughly(300); } FOR_ALL_INTERFACES(ifp) { if(!if_up(ifp)) continue; if(timeval_compare(&now, &ifp->hello_timeout) >= 0) send_hello(ifp); if(timeval_compare(&now, &ifp->update_timeout) >= 0) send_update(ifp, 0, NULL, 0, NULL, 0); if(timeval_compare(&now, &ifp->update_flush_timeout) >= 0) flushupdates(ifp); } if(resend_time.tv_sec != 0) { if(timeval_compare(&now, &resend_time) >= 0) do_resend(); } if(unicast_flush_timeout.tv_sec != 0) { if(timeval_compare(&now, &unicast_flush_timeout) >= 0) flush_unicast(1); } FOR_ALL_INTERFACES(ifp) { if(!if_up(ifp)) continue; if(ifp->flush_timeout.tv_sec != 0) { if(timeval_compare(&now, &ifp->flush_timeout) >= 0) flushbuf(ifp); } } if(UNLIKELY(debug || dumping)) { dump_tables(stdout); dumping = 0; } }
/// @brief Create C Cordic Tables and test the results /// @return 0 int main (int argc, char *argv[]) { Cordic_T x1; char str[256]; char *oname; char *p; double d; int a; int i; FILE *FO; for(i=1; i<argc;++i) { p = argv[i]; if(*p != '-') continue; ++p; if(*p == 'o') { oname = argv[++i]; } } if(!oname) { fprintf(stderr,"Usage: %s -o filename [-p]\n",argv[0]); fprintf(stderr,"-o filename is CORDIC C table output file\n"); exit(1); } FO = fopen(oname,"w"); if(FO == NULL) { fprintf(stderr,"Can not open: [%s]\n", oname); exit (1); } fprintf(FO,"#ifndef _CORDIC_INC_H\n"); fprintf(FO,"#define _CORDIC_INC_H\n"); fprintf(FO,"/**\n"); fprintf(FO," @file %s\n", basename(oname)); fprintf(FO," Generated by:[%s]\n", basename(argv[0])); fprintf(FO," On: %s\n", get_date()); fprintf(FO," By Mike Gore 2015, Cordic C Table\n"); fprintf(FO,"*/\n"); dump_tables( FO); fprintf(FO,"#else // CORDIC_TABLE\n"); fprintf(FO,"extern const Cordic_T v_atangrad[];\n"); fprintf(FO,"#endif // CORDIC_TABLE\n"); fprintf(FO,"#endif // _CORDIC_INC_H\n"); printf("// Verify CORDIC table \n"); for(d=0;d<=1;d+=.1) { x1 = FP2Cordic(d); Circular (Cordic_K, 0L, x1); a = (int) 100 * d + 0.000005; // rounding - 0.1 is not exact sprintf(str,"%d Gradians", a); PrintXYZ (str); } printf("// End of CORDIC verify\n"); return (0); }
/*ARGSUSED*/ void startup_kernel(void) { char *cmdline; uintptr_t addr; #if defined(__xpv) physdev_set_iopl_t set_iopl; #endif /* __xpv */ /* * At this point we are executing in a 32 bit real mode. */ #if defined(__xpv) cmdline = (char *)xen_info->cmd_line; #else /* __xpv */ cmdline = (char *)mb_info->cmdline; #endif /* __xpv */ prom_debug = (strstr(cmdline, "prom_debug") != NULL); map_debug = (strstr(cmdline, "map_debug") != NULL); #if defined(__xpv) /* * For dom0, before we initialize the console subsystem we'll * need to enable io operations, so set I/O priveldge level to 1. */ if (DOMAIN_IS_INITDOMAIN(xen_info)) { set_iopl.iopl = 1; (void) HYPERVISOR_physdev_op(PHYSDEVOP_set_iopl, &set_iopl); } #endif /* __xpv */ bcons_init(cmdline); DBG_MSG("\n\nSolaris prekernel set: "); DBG_MSG(cmdline); DBG_MSG("\n"); if (strstr(cmdline, "multiboot") != NULL) { dboot_panic(NO_MULTIBOOT); } /* * boot info must be 16 byte aligned for 64 bit kernel ABI */ addr = (uintptr_t)boot_info; addr = (addr + 0xf) & ~0xf; bi = (struct xboot_info *)addr; DBG((uintptr_t)bi); bi->bi_cmdline = (native_ptr_t)(uintptr_t)cmdline; /* * Need correct target_kernel_text value */ #if defined(_BOOT_TARGET_amd64) target_kernel_text = KERNEL_TEXT_amd64; #elif defined(__xpv) target_kernel_text = KERNEL_TEXT_i386_xpv; #else target_kernel_text = KERNEL_TEXT_i386; #endif DBG(target_kernel_text); #if defined(__xpv) /* * XXPV Derive this stuff from CPUID / what the hypervisor has enabled */ #if defined(_BOOT_TARGET_amd64) /* * 64-bit hypervisor. */ amd64_support = 1; pae_support = 1; #else /* _BOOT_TARGET_amd64 */ /* * See if we are running on a PAE Hypervisor */ { xen_capabilities_info_t caps; if (HYPERVISOR_xen_version(XENVER_capabilities, &caps) != 0) dboot_panic("HYPERVISOR_xen_version(caps) failed"); caps[sizeof (caps) - 1] = 0; if (prom_debug) dboot_printf("xen capabilities %s\n", caps); if (strstr(caps, "x86_32p") != NULL) pae_support = 1; } #endif /* _BOOT_TARGET_amd64 */ { xen_platform_parameters_t p; if (HYPERVISOR_xen_version(XENVER_platform_parameters, &p) != 0) dboot_panic("HYPERVISOR_xen_version(parms) failed"); DBG(p.virt_start); mfn_to_pfn_mapping = (pfn_t *)(xen_virt_start = p.virt_start); } /* * The hypervisor loads stuff starting at 1Gig */ mfn_base = ONE_GIG; DBG(mfn_base); /* * enable writable page table mode for the hypervisor */ if (HYPERVISOR_vm_assist(VMASST_CMD_enable, VMASST_TYPE_writable_pagetables) < 0) dboot_panic("HYPERVISOR_vm_assist(writable_pagetables) failed"); /* * check for NX support */ if (pae_support) { uint32_t eax = 0x80000000; uint32_t edx = get_cpuid_edx(&eax); if (eax >= 0x80000001) { eax = 0x80000001; edx = get_cpuid_edx(&eax); if (edx & CPUID_AMD_EDX_NX) NX_support = 1; } } #if !defined(_BOOT_TARGET_amd64) /* * The 32-bit hypervisor uses segmentation to protect itself from * guests. This means when a guest attempts to install a flat 4GB * code or data descriptor the 32-bit hypervisor will protect itself * by silently shrinking the segment such that if the guest attempts * any access where the hypervisor lives a #gp fault is generated. * The problem is that some applications expect a full 4GB flat * segment for their current thread pointer and will use negative * offset segment wrap around to access data. TLS support in linux * brand is one example of this. * * The 32-bit hypervisor can catch the #gp fault in these cases * and emulate the access without passing the #gp fault to the guest * but only if VMASST_TYPE_4gb_segments is explicitly turned on. * Seems like this should have been the default. * Either way, we want the hypervisor -- and not Solaris -- to deal * to deal with emulating these accesses. */ if (HYPERVISOR_vm_assist(VMASST_CMD_enable, VMASST_TYPE_4gb_segments) < 0) dboot_panic("HYPERVISOR_vm_assist(4gb_segments) failed"); #endif /* !_BOOT_TARGET_amd64 */ #else /* __xpv */ /* * use cpuid to enable MMU features */ if (have_cpuid()) { uint32_t eax, edx; eax = 1; edx = get_cpuid_edx(&eax); if (edx & CPUID_INTC_EDX_PSE) largepage_support = 1; if (edx & CPUID_INTC_EDX_PGE) pge_support = 1; if (edx & CPUID_INTC_EDX_PAE) pae_support = 1; eax = 0x80000000; edx = get_cpuid_edx(&eax); if (eax >= 0x80000001) { eax = 0x80000001; edx = get_cpuid_edx(&eax); if (edx & CPUID_AMD_EDX_LM) amd64_support = 1; if (edx & CPUID_AMD_EDX_NX) NX_support = 1; } } else { dboot_printf("cpuid not supported\n"); } #endif /* __xpv */ #if defined(_BOOT_TARGET_amd64) if (amd64_support == 0) dboot_panic("long mode not supported, rebooting"); else if (pae_support == 0) dboot_panic("long mode, but no PAE; rebooting"); #else /* * Allow the command line to over-ride use of PAE for 32 bit. */ if (strstr(cmdline, "disablePAE=true") != NULL) { pae_support = 0; NX_support = 0; amd64_support = 0; } #endif /* * initialize the simple memory allocator */ init_mem_alloc(); #if !defined(__xpv) && !defined(_BOOT_TARGET_amd64) /* * disable PAE on 32 bit h/w w/o NX and < 4Gig of memory */ if (max_mem < FOUR_GIG && NX_support == 0) pae_support = 0; #endif /* * configure mmu information */ if (pae_support) { shift_amt = shift_amt_pae; ptes_per_table = 512; pte_size = 8; lpagesize = TWO_MEG; #if defined(_BOOT_TARGET_amd64) top_level = 3; #else top_level = 2; #endif } else { pae_support = 0; NX_support = 0; shift_amt = shift_amt_nopae; ptes_per_table = 1024; pte_size = 4; lpagesize = FOUR_MEG; top_level = 1; } DBG(pge_support); DBG(NX_support); DBG(largepage_support); DBG(amd64_support); DBG(top_level); DBG(pte_size); DBG(ptes_per_table); DBG(lpagesize); #if defined(__xpv) ktext_phys = ONE_GIG; /* from UNIX Mapfile */ #else ktext_phys = FOUR_MEG; /* from UNIX Mapfile */ #endif #if !defined(__xpv) && defined(_BOOT_TARGET_amd64) /* * For grub, copy kernel bits from the ELF64 file to final place. */ DBG_MSG("\nAllocating nucleus pages.\n"); ktext_phys = (uintptr_t)do_mem_alloc(ksize, FOUR_MEG); if (ktext_phys == 0) dboot_panic("failed to allocate aligned kernel memory"); if (dboot_elfload64(mb_header.load_addr) != 0) dboot_panic("failed to parse kernel ELF image, rebooting"); #endif DBG(ktext_phys); /* * Allocate page tables. */ build_page_tables(); /* * return to assembly code to switch to running kernel */ entry_addr_low = (uint32_t)target_kernel_text; DBG(entry_addr_low); bi->bi_use_largepage = largepage_support; bi->bi_use_pae = pae_support; bi->bi_use_pge = pge_support; bi->bi_use_nx = NX_support; #if defined(__xpv) bi->bi_next_paddr = next_avail_addr - mfn_base; DBG(bi->bi_next_paddr); bi->bi_next_vaddr = (native_ptr_t)next_avail_addr; DBG(bi->bi_next_vaddr); /* * unmap unused pages in start area to make them available for DMA */ while (next_avail_addr < scratch_end) { (void) HYPERVISOR_update_va_mapping(next_avail_addr, 0, UVMF_INVLPG | UVMF_LOCAL); next_avail_addr += MMU_PAGESIZE; } bi->bi_xen_start_info = (uintptr_t)xen_info; DBG((uintptr_t)HYPERVISOR_shared_info); bi->bi_shared_info = (native_ptr_t)HYPERVISOR_shared_info; bi->bi_top_page_table = (uintptr_t)top_page_table - mfn_base; #else /* __xpv */ bi->bi_next_paddr = next_avail_addr; DBG(bi->bi_next_paddr); bi->bi_next_vaddr = (uintptr_t)next_avail_addr; DBG(bi->bi_next_vaddr); bi->bi_mb_info = (uintptr_t)mb_info; bi->bi_top_page_table = (uintptr_t)top_page_table; #endif /* __xpv */ bi->bi_kseg_size = FOUR_MEG; DBG(bi->bi_kseg_size); #ifndef __xpv if (map_debug) dump_tables(); #endif DBG_MSG("\n\n*** DBOOT DONE -- back to asm to jump to kernel\n\n"); }