コード例 #1
0
ファイル: glenisp.c プロジェクト: glenjamin/buildyourownlisp
struct lval* lval_read(mpc_ast_t* node) {

    // Upwrap top-level form as a single expression
    if (strcmp(node->tag, ">") == 0) {
        return lval_read(node->children[1]);
    }

    if (strstr(node->tag, "number")) {
        return lval_read_num(node->contents);
    }
    if (strstr(node->tag, "symbol")) {
        return lval_sym(node->contents);
    }
    if (strstr(node->tag, "bool")) {
        return lval_read_bool(node->contents);
    }

    struct lval* x;
    if (strstr(node->tag, "sexp")) {
        x = lval_sexp();
    }
    else if (strstr(node->tag, "qexp")) {
        x = lval_qexp();
    }
    else {
        return lval_err("Unexpected node: %s", node->tag);
    }

    for (int i = 0; i < node->children_num; i++) {
        if (read_ignore(node->children[i])) continue;
        x = lval_add(x, lval_read(node->children[i]));
    }
    return x;
}
コード例 #2
0
 void drain_excessive_data()
 {
     // The pipe seems to have data on it, that won't go away
     // Read a big chunk out of it.
     // We don't read until it's exhausted, because if someone were to pipe say /dev/null, that would cause us to hang!
     size_t read_amt = 64 * 1024;
     void *buff = malloc(read_amt);
     read_ignore(this->pipe_fd, buff, read_amt);
     free(buff);
 }
コード例 #3
0
 bool poll()
 {
     bool result = false;
     
     // Check if we are past the readback time
     if (this->readback_time_usec > 0 && get_time() >= this->readback_time_usec)
     {
         // Read back what we wrote. We do nothing with the value.
         while (this->readback_amount > 0)
         {
             char buff[64];
             size_t amt_to_read = mini(this->readback_amount, sizeof buff);
             read_ignore(this->pipe_fd, buff, amt_to_read);
             this->readback_amount -= amt_to_read;
         }
         assert(this->readback_amount == 0);
         this->readback_time_usec = 0;
     }
     
     // Check to see if we are doing readability polling
     if (polling_due_to_readable_fd && pipe_fd >= 0)
     {
         // We are polling, so we are definitely going to sync
         result = true;
         
         // See if this is still readable
         fd_set fds;
         FD_ZERO(&fds);
         FD_SET(this->pipe_fd, &fds);
         struct timeval timeout = {};
         select(this->pipe_fd + 1, &fds, NULL, NULL, &timeout);
         if (! FD_ISSET(this->pipe_fd, &fds))
         {
             // No longer readable, no longer polling
             polling_due_to_readable_fd = false;
             drain_if_still_readable_time_usec = 0;
         }
         else
         {
             // Still readable. If it's been readable for a long time, there is probably lingering data on the pipe
             if (get_time() >= drain_if_still_readable_time_usec)
             {
                 drain_excessive_data();
             }
         }
     }
     
     return result;
 }
コード例 #4
0
ファイル: dns_parse.c プロジェクト: shrekts/dns_parse
int main(int argc, char **argv) {
    pcap_t * pcap_file;
    char errbuf[PCAP_ERRBUF_SIZE];
    int read;
    config conf;

    int c;
    int arg_failure = 0;

    const char * OPTIONS = "cdfhi:m:MnrtD:x:s:S";

    // Setting configuration defaults.
    uint8_t TCP_SAVE_STATE = 1;
    conf.COUNTS = 0;
    conf.EXCLUDES = 0;
    conf.RECORD_SEP = "";
    conf.SEP = '\t';
    conf.AD_ENABLED = 0;
    conf.NS_ENABLED = 0;
    conf.PRETTY_DATE = 0;
    conf.PRINT_RR_NAME = 0;
    conf.MISSING_TYPE_WARNINGS = 0;
    conf.TCP_STATE_PATH = NULL;
    conf.DEDUPS = 10;
    conf.dedup_pos = 0;
    conf.IGNORE_DOMAINS = NULL;

    c = getopt(argc, argv, OPTIONS);
    while (c != -1) {
        switch (c) {
            case 'c':
                conf.COUNTS = 1;
                break;
            case 'd':
                conf.AD_ENABLED = 1;
                break;
            case 'f':
                print_parsers();
                return 0;
            case 'm':
                conf.RECORD_SEP = optarg;
                conf.SEP = '\n';
                break;
            case 'M':
                conf.MISSING_TYPE_WARNINGS = 1;
                break;
            case 'n':
                conf.NS_ENABLED = 1;
                break;
            case 'r':
                conf.PRINT_RR_NAME = 1;
                break;
            case 's':
                conf.TCP_STATE_PATH = optarg;
                break;
            case 'S':
                TCP_SAVE_STATE = 0;
                break;
            case 't':
                conf.PRETTY_DATE = 1; 
                break;
            case 'D':
                conf.DEDUPS = strtoul(optarg, NULL, 10);
                if (conf.DEDUPS > 10000) {
                    conf.DEDUPS = 10000;
                }
                break;
            case 'i':
                if (optarg)
                    conf.IGNORE_DOMAINS = read_ignore(optarg);
                else
                    arg_failure = 1;
                break;
            case 'x':
                if (conf.EXCLUDES < MAX_EXCLUDES) {
                    int ival = atoi(optarg);
                    if (ival == 0 || ival >= 65536) {
                        fprintf(stderr, "Invalid excluded rtype value. "
                                "Value must be a short int.\n");
                        arg_failure = 1;
                    } else {
                        conf.EXCLUDED[conf.EXCLUDES] = ival;
                        conf.EXCLUDES++; 
                    }
                } else {
                    fprintf(stderr, "Too many excluded rtypes. "
                            "If this limit is an issue, then recompile with "
                            "the MAX_EXCLUDES define set higher.\n");
                    arg_failure = 1;
                }
                break;
            case '?':
                if (optopt == 'x') 
                    fprintf(stderr, "Option -x requires an rtype number.\n");
                else if (optopt == 'm')
                    fprintf(stderr, "Option -m needs a delimiter string.\n");
                else if (isprint(optopt)) 
                    fprintf(stderr, "Unknown option -%c.\n",optopt); 
                else 
                    fprintf(stderr, "Invalid option char: 0x%x.\n", optopt);
            case 'h':
            default:
                arg_failure = 1;
        }
        c = getopt(argc, argv, OPTIONS);
    }

    if (conf.TCP_STATE_PATH == NULL) {
        conf.TCP_STATE_PATH = DEFAULT_TCP_STATE_PATH;
    }

    if (optind == argc - 1) {
        pcap_file = pcap_open_offline(argv[optind], errbuf);
        if (pcap_file == NULL) {
            fprintf(stderr, "Could not open pcapfile.\n%s\n", errbuf);
            return -1;
        }
        conf.datalink = pcap_datalink(pcap_file);
        if (conf.datalink != DLT_EN10MB && conf.datalink != DLT_LINUX_SLL) {
            fprintf(stderr, "Unsupported data link layer: %d\n", conf.datalink);
            arg_failure = 1;
            pcap_close(pcap_file);
        }
    } else if (optind >= argc) {
        fprintf(stderr, "No input file specified.\n");
        arg_failure = 1;
    } else {
        fprintf(stderr, "Multiple input files or bad arguments.");
        arg_failure = 1;
    }
    
    if (arg_failure) {
        fprintf(stderr,
        "Usage: dns_parse [-dnthf] [-m<query sep.>] [-x<rtype>] [-s<path>]\n"
        "                 <pcap file>\n"
        "dns_parse parses a pcap file and gives a nicely "
        "formatted ascii string for each dns request.\n"
        "By default the reservation records are tab separated "
        "and the entire record is ended with a newline.\n\n"
        "The comma separated fields printed for each request are:\n"
        "  time - The time of the request relative to the \n"
        "         capture source clock.\n"
        "  srcip, dstip - the source and dest ipv4 addresses.\n"
        "                 ipv6 support is not present.\n"
        "  size - the size of the dns portion of the message.\n"
        "  proto - udp (u) or tcp(t)\n"
        "  query/response - is it a query(q) or response(r)\n"
        "  authoritative - marked with AA if authoritative\n\n"
        "The resource records are printed after these fields, separated by\n"
        "a tab (a newline in multiline mode). \n"
        "By default the resource record format is:\n"
        "<section> <name> <type> <class> <rdata>\n\n"
        "<section> is a symbol denoting record type.\n"
        "    ? - Questions (No rdata is included or printed).\n"
        "    ! - Answers\n"
        "    $ - Name Servers\n"
        "    + - Additional\n"
        "The rdata is parsed by a custom parser that depends on the\n"
        "record type and class. Use the -f option to get a list of\n"
        "the supported record types and documentation on the parsers.\n\n"
        "Args:\n"
        "<pcapfile> - The pcapfile to parse. Use a '-' for stdin\n"
        "-c\n"
        "   Append a list of counts for each record type (Questions, \n"
        "   Answers, etc) to record fields. Each type is followed by it's\n"
        "   record type symbol.\n"
        "-d\n"
        "   Enable the parsing and output of the Additional\n"
        "   Records section. Disabled by default.\n"
        "-D <count>\n"
        "   Keep hashes of the last <count> packets for de-duplication\n"
        "   purposes (max 10,000). A <count> of zero turns off \n"
        "   de-duplication. \n"
        "   Default 10.\n"
        "-f\n"
        "   Print out documentation on the various resource \n"
        "   record parsers.\n"
        "-n\n"
        "   Enable the parsing and output of the Name Server\n"
        "   Records section. Disabled by default.\n"
        "-i <-|ignorefile>\n"
        "   Ignore requests for domains listed in the file specified.\n"
        "   Two modes are supported. Strict matching with a caret prefix,\n"
        "   e.g. ^sub1.example.com. (Sub)domain matching with e.g. example.com\n"
        "   for example.com, sub.example.com, ..\n"
        "-m<sep> \n"
        "   Multiline mode. Reservation records are newline\n"
        "   separated, and the whole record ends with the\n"
        "   separator given.\n"
        "-M \n"
        "   Print a message for each occurance of a missing class,type\n"
        "   parser.\n"
        "-r \n"
        "   Changes the resource record format to: \n"
        "   <section> <name> <rr_type_name> <rdata>\n"
        "   If the record type isn't known, 'UNKNOWN(<cls>,<type>)' is given\n"
        "   The query record format is the similar, but missing the rdata.\n"
        "-s<path> \n"
        "   Path to the tcp state save file. \n"
        "   This will be loaded (and overwritten) every time dns_parse \n"
        "   is run. \n"
        "   Default is: %s \n"
        "-S \n"
        "   Disable TCP state saving/loading.\n"
        "-t \n"
        "   Print the time/date as in Y-m-d H:M:S (ISO 8601) format.\n"
        "   The time will be in the local timezone.\n"
        "-x\n"
        "   Exclude the given reservation record types by \n"
        "   number. This option can be given multiple times.\n"
        "\n"
        "Supported protocols:\n"
        "DNS can ride on a number of protocols, and dns_parse supports\n"
        "a fair number of them, including:\n"
        "Ethernet, MPLS, IPv4, IPv6, UDP and TCP.\n"
        "IPv4 and IPv6 fragments - fragments are reassembled, but data\n"
        "   may be lost if the fragments are split across multiple pcaps.\n"
        "TCP reassembly - TCP packets are reassembled, but the resulting\n"
        "   data may be offset from their time of occurance. Partial flow\n"
        "   reassembly is supported; long flows are printed whenever a \n"
        "   a lull in that flow occurs (500 ms since the last packet, \n"
        "   this can only be changed at compile time).\n"
        "   TCP flow state is saved at the end of execution, and loaded\n"
        "   at the beginning. See the -S option to disable.\n",
        DEFAULT_TCP_STATE_PATH);
        return -1;
    }

    conf.ip_fragment_head = NULL;

    // Load and prior TCP session info
    conf.tcp_sessions_head = NULL; 
    if (TCP_SAVE_STATE == 1) {
        tcp_load_state(&conf);
    }

    conf.dedup_hashes = calloc(conf.DEDUPS, sizeof(uint64_t));
 
    // need to check this for overflow.
    read = pcap_dispatch(pcap_file, -1, (pcap_handler)handler, 
                         (uint8_t *) &conf);
    
    if (TCP_SAVE_STATE == 1) {
        tcp_save_state(&conf);
    } else {
        tcp_expire(&conf, NULL);
    }

    free(conf.dedup_hashes);
    ip_frag_free(&conf);

    if (read == -1) {
        fprintf(stderr, "pcap_dispatch: %s\n", pcap_geterr(pcap_file));
    } else if (read == -2) {
        fprintf(stderr, "pcap_dispatch: break!\n");
    } VERBOSE( else fprintf(stderr, "pcap_dispatch: %d packets processed\n", read); )