コード例 #1
0
ファイル: thread-worker.c プロジェクト: chagge/robdns
static void
thread_worker(void *p)
{
    struct CoreWorkerThread *t = (struct CoreWorkerThread *)p;
    struct Core *core = t->core;

    while (!t->should_end) {
        unsigned i;
        struct CoreSocketSet *sockets;
        fd_set readfds;
        int nfds = 0;
        int x;
        struct timeval ts;

        /* [SYNCHRONIZATION POINT] 
        * mark the fact we are using the new socket-set */
        sockets = (struct CoreSocketSet *)core->socket_run;
        t->loop_count++;

        /* During startup, the sockets argument may be NULL for a time.
         * if that's the case, then just wait for a little bit, and try
         * again */
        if (sockets == NULL) {
            /* Sleep for a 10th of a second */
            pixie_mssleep(10); 
            continue;
        }

        /* 
         * See if there are any packets waiting 
         */
        FD_ZERO(&readfds);
        for (i=0; i<sockets->count; i++) {
            FD_SET(sockets->list[i].fd, &readfds);
            if (nfds < sockets->list[i].fd)
                nfds = sockets->list[i].fd;
        }
        ts.tv_sec = 0;
        ts.tv_usec = 1000; /* one millisecond */

        x = select(nfds, &readfds, 0, 0, &ts);
        if (x < 0) {
            LOG_ERR(C_NETWORK, "select() returned error %u\n", WSAGetLastError());
            pixie_mssleep(1000);
            /* at this point, the errors are probably unrecoverable
             * until the system is manually reconfigured */
            continue;
        }
        if (x == 0)
            continue; /* nothing found */

        /*
         * Process any packets that have arrived
         */
        for (i=0; i<sockets->count; i++) {
            struct sockaddr_storage sin;
            socklen_t sizeof_sin = sizeof(sin);
            unsigned char buf[2048];
            unsigned char buf2[2048];
            int bytes_received;
            struct DNS_Incoming request[1];
            struct DNS_OutgoingResponse response[1];
            struct Packet pkt;
            int fd;

            fd = sockets->list[i].fd;
            if (!FD_ISSET(fd, &readfds))
                continue;
        
            /*
             * 1. receive 'packet'
             */
            bytes_received = recvfrom(fd, 
                                      (char*)buf, sizeof(buf),
                                      0, 
                                      (struct sockaddr*)&sin, &sizeof_sin);
            if (bytes_received == 0)
                continue;

        
            /*
             * 2. parse 'packet' into a 'request'
             */
            proto_dns_parse(request, buf, 0, bytes_received);
            if (!request->is_valid)
                continue;


            /*
             * 3. resolve 'request' into a 'repsonse'
             */
            resolver_init(response, 
                          request->query_name.name, 
                          request->query_name.length, 
                          request->query_type,
                          request->id,
                          request->opcode);
            
            resolver_algorithm(core->db_run, response, request);
            

            /*
             * 4. format the 'response' into a 'packet'
             */
            pkt.buf = buf2;
            pkt.max = sizeof(buf2);
            pkt.offset = 0;
            dns_format_response(response, &pkt);
            
            /*
             * 5. Transmit the 'packet'
             */
            if (pkt.offset < pkt.max) {
                sendto(fd, 
                       (char*)pkt.buf, pkt.offset, 0,
                       (struct sockaddr*)&sin,
                       sizeof_sin);
            }
        }
    }
}
コード例 #2
0
ファイル: main-server-socket.c プロジェクト: jet9/robdns
/******************************************************************************
 * This is the mail loop when running over sockets, receiving packets and
 * sending responses.
 ******************************************************************************/
void
sockets_thread(struct Core *conf)
{
    int err;
    SOCKET fd;
    struct sockaddr_in6 sin;
    static const unsigned port = 53;
    
    /*
     * This software obtains its speed by bypassing the operating system
     * stack. Thus, running on top of 'sockets' is going to be a lot 
     * slower
     */
    fprintf(stderr, "WARNING: running in slow 'sockets' mode\n");
    
    
    /*
     * Legacy Windows is legacy.
     */
#if defined(WIN32)
    {WSADATA x; WSAStartup(0x201, &x);}
#endif
    
    /*
     * Create a socket for incoming UDP packets. By specifying IPv6, we are
     * actually going to allow both IPv4 and IPv6.
     */
    fd = socket(AF_INET6, SOCK_DGRAM, 0);
    if (fd <= 0) {
        LOG(0, "FAIL: couldn't create socket %u\n", WSAGetLastError());
        return;
    }
    
    /*
     * Set the 'reuse' feature of the socket, otherwise restarting the process
     * requires a wait before binding back to the same port number
     */
    {
        int on = 1;
        err = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&on,sizeof(on));
        if (err < 0) {
            perror("setsockopt(SO_REUSEADDR) failed");
            exit(1); 
        }
    }

    /*
     * Enable both IPv4 and IPv6 to be used on the same sockets. This appears to
     * be needed for Windows, but not needed for Mac OS X.
     */
    {
        int on = 0;
        err = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&on, sizeof(on)); 
        if (err < 0) {
            perror("setsockopt(IPV6_V6ONLY) failed");
            exit(1); 
        }
    }
    
    
    /*
     * Listen on any IPv4 or IPv6 address in the system
     */
    memset(&sin, 0, sizeof(sin));
    sin.sin6_family = AF_INET6;
    sin.sin6_addr = in6addr_any;
    sin.sin6_port = htons(port);
    err = bind(fd, (struct sockaddr*)&sin, sizeof(sin));
    if (err) {
        switch (WSAGetLastError()) {
            case WSA(EACCES):
                LOG(0, "FAIL: couldn't bind to port %u: %s\n", port, 
                    "access denied");
                if (port <= 1024)
                    LOG(0, "  hint... need to be root for ports below 1024\n");
                break;
            case WSA(EADDRINUSE):
                LOG(0, "FAIL: couldn't bind to port %u: %s\n", port, 
                    "address in use");
                LOG(0, "  hint... some other server is running on that port\n");
                break;
            default:
                LOG(0, "FAIL: couldn't bind to port %u: %u\n", port,
                    WSAGetLastError());
        }
        exit(1);
    } else {
        fprintf(stderr, "UDP port: %u\n", port);
    }
    
    /*
     * Sit in loop processing incoming UDP packets
     */
    for (;;) {
        unsigned char buf[2048];
        int bytes_received;
        socklen_t sizeof_sin = sizeof(sin);
        struct DNS_Incoming request[1];
        struct DNS_OutgoingResponse response[1];
        struct Packet pkt;
        unsigned char buf2[2048];
        
        /*
         * 1. receive 'packet'
         */
        bytes_received = recvfrom(fd, 
                                  (char*)buf, sizeof(buf),
                                  0, 
                                  (struct sockaddr*)&sin, &sizeof_sin);
        if (bytes_received == 0)
            continue;

        
        /*
         * 2. parse 'packet' into a 'request'
         */
        proto_dns_parse(request, buf, 0, bytes_received);
        if (!request->is_valid)
            continue;


        /*
         * 3. resolve 'request' into a 'repsonse'
         */
        resolver_init(response, 
                      request->query_name.name, 
                      request->query_name.length, 
                      request->query_type,
                      request->id,
                      request->opcode);
            
        resolver_algorithm(conf->db, response, request);
            

        /*
         * 4. format the 'response' into a 'packet'
         */
        pkt.buf = buf2;
        pkt.max = sizeof(buf2);
        pkt.offset = 0;
        dns_format_response(response, &pkt);
            
        /*
         * 5. Transmit the 'packet'
         */
        if (pkt.offset < pkt.max) {
            sendto(fd, 
                   (char*)pkt.buf, pkt.offset, 0,
                   (struct sockaddr*)&sin,
                   sizeof_sin);
        }
    }
}
コード例 #3
0
ファイル: main-pcap2zone.c プロジェクト: Zabrane/robdns
static int
grab_dns_response(struct Catalog *catalog, const unsigned char *px, unsigned offset, unsigned max)
{
    struct DNS_Incoming dns[1];
    unsigned i;
    struct DomainPointer domain;
    unsigned char domain_buffer[256];
    char unsigned tmp_buffer[65536];
    unsigned tmp_offset;
    unsigned src_offset;

    /* kludge */
    px += offset;
    offset = 0;
    max -= offset;

    domain.name = domain_buffer;

    proto_dns_parse(dns, px, offset, max);

    if (!dns->is_valid)
        return Failure;
    if (!dns->qr)
        return Failure;

    for (i=dns->qdcount; i<dns->rr_count; i++) {
        int type;
        int xclass;
        unsigned ttl;
        unsigned rdlength;
        const unsigned char *rdata;

        offset = dns->rr_offset[i];

        /* extract the domain name */
        dns_extract_name(px, offset, max, &domain);
        offset = dns_name_skip(px, offset, max);

        /* extract the data */
        if (offset + 10 > max)
            continue;
        type = px[offset+0]<<8 | px[offset+1];
        xclass = px[offset+2]<<8 | px[offset+3];
        if (xclass != 1)
            continue;
        ttl = px[offset+4]<<24 | px[offset+5]<<16 | px[offset+6]<<8 | px[offset+7];
        rdlength = px[offset+8]<<8 | px[offset+9];
        rdata = &px[offset + 10];
        offset += 10;
        

        /* insert the data into the catalog */
        if (offset + rdlength > max)
            continue;
        else
            offset += rdlength;

        tmp_offset = 0;
        src_offset = (unsigned)(rdata - px);

        switch (type) {
        case 41: /*OPT*/
            continue;

        case TYPE_NS:
        case TYPE_CNAME:
            extract_name(   tmp_buffer, &tmp_offset, sizeof(tmp_buffer),
                            px, &src_offset, max);
            rdata = tmp_buffer;
            rdlength = tmp_offset;
            break;

        case TYPE_SOA:
            extract_name(   tmp_buffer, &tmp_offset, sizeof(tmp_buffer),
                            px, &src_offset, max);
            extract_name(   tmp_buffer, &tmp_offset, sizeof(tmp_buffer),
                            px, &src_offset, max);
            extract_copy(   tmp_buffer, &tmp_offset, sizeof(tmp_buffer),
                            px, &src_offset, max,
                            offset-src_offset);
            rdata = tmp_buffer;
            rdlength = tmp_offset;
            break;
        case TYPE_RRSIG:
            //printf(".");
            break;
        }


        zonefile_load(
            domain,
            root,
            type,
            ttl,
            rdlength,
            rdata,
            10000,
            catalog);

        
    }

    return Success;
}