endlosschleife mit select()



  • ich habe mal wieder ein Problem:
    Mittels select frage ich ein socket ab was auch gut funktioniert.
    wenn ich allerdings nachdem ich ich paket bekommen habe die IP-checksumme
    neu berechne bleibt select irgendwie hängen und es gibt eine Endlosschleife

    besser verständlich hier:

    for( ;; ) {
         FD_ZERO( &read_fds );
         FD_SET( sUDP, &read_fds );	
         ret_val = select( sUDP + 1, &read_fds, NULL, NULL, NULL );
         if( ret_val < 0 )
           break;
         if( ret_val > 0 ) {
    
           if ( FD_ISSET( sUDP, &read_fds ) ) {
    
         int lenInUDP = recvfrom(sUDP, &ethBufferUDP, sizeof(ethBufferUDP), 0, 0, 0);
            ip = (struct iphdr *) ethBufferUDP;
            udp = (struct udphdr *)(ethBufferUDP + sizeof(struct iphdr));
    
           [b]PROBLEM:[/b]
           ip->check = 0    //(1)
           ip->check =  in_cksum ((unsigned short *) ip, ip->ihl * (32 / 8));  //(2)
          }
       }
    }
    

    wenn ich entweder (1) oder! (2) auskommentiere funktioniert select, wenn beide drin sind ist D_ISSET( sUDP, &read_fds ) immer true und es rotiert endlos...

    die checksum function:

    unsigned short in_cksum (unsigned short *addr, int count) {
            register long sum = 0;
            register unsigned short checksum;
    
            while (count > 1)
            {
                    sum += *addr++;
                    count -= 2;
            }
            if (count > 0)
            {
                    sum += *(unsigned char *) addr;
            }
            while (sum >> 16)
            {
                    sum = (sum & 0xffff) + (sum >> 16);
            }
    
            checksum = ~sum;
    
     return checksum;
    }
    


  • Ich sehe jetzt nicht direkt einen Fehler. Wenn ISSET immer true ist, blockiert recvfrom dann oder liest es weiterhin Daten? Wenn ja, dürfte das Problem ja eher woanders liegen. (Versuch mal einen minimalen aber vollständigen Code zu schreiben, der den Fehler demonstriert. Das würde zumindest weiter helfen den Fehler zu analysieren)

    Ansonsten bin ich mir nicht sicher ob dein gecaste mit den strict-aliasing Regeln des C99-Standards kompatibel ist.

    btw. solltest du für count einen unsigned-Typ (am besten eben size_t, aber das hängt von der Größe von ip->ihl ab). Wenn ip->ihl größer als std::numeric_limits<int>::max()*8/32 ist, dann hast du nämlich eine Endlosschleife! (also ein potentieller DOS-Angriff). Für sum würde ich vermutlich auch einen unsigned Typ nehmen. (ok. das war jetzt alles Werbung für einen Artikel über Integer den ich gerade schreibe :D)


Anmelden zum Antworten