Example #1
0
    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";
    }
Example #2
0
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;
        }
    }
Example #3
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);
}
Example #4
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");
}