From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1750915AbWELJor (ORCPT ); Fri, 12 May 2006 05:44:47 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1750943AbWELJor (ORCPT ); Fri, 12 May 2006 05:44:47 -0400 Received: from mallorn.ii.uj.edu.pl ([149.156.65.90]:14761 "EHLO mallorn.ii.uj.edu.pl") by vger.kernel.org with ESMTP id S1750914AbWELJoq (ORCPT ); Fri, 12 May 2006 05:44:46 -0400 Message-ID: <44645908.3000109@mallorn.ii.uj.edu.pl> Date: Fri, 12 May 2006 11:44:40 +0200 From: =?ISO-8859-2?Q?Pawe=B3_Jaworski?= User-Agent: Thunderbird 1.5.0.2 (X11/20060501) MIME-Version: 1.0 To: i am totally stumped Cc: paweusz@mallorn.ii.uj.edu.pl Subject: Kernel network layer breakes recv_from() as the server (i think) (kernel-bug) Content-Type: text/plain; charset=ISO-8859-2; format=flowed Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org X-Mailing-List: linux-kernel@vger.kernel.org $ brief-problem Kernel network layer breakes recv_from() as the server (i think) $ full-problem I am student of Jagiellonian University of Cracow. Recently I've been trying to write some network programs as a learning of network protocols. Everything went fine except for UDP. I was trying to send a structure through the UDP protocol to the server. Every time I was sending a packet, recv_from() returned "Invalid argument". As it was my homework, i brought the program to my teacher, but... it worked well on systems in my school. 1. It worked on Linux Mandrake (i think) 10 2. It worked on Debian Sarge with kernel-image-2.4.27-2-686-smp 3. It worked on Debian Sarge with kernel-image-2.6.8-2 4. It worked on IRIX (i know it's not Linux, but... it worked) It didn't work on Debian Sarge kernels 2.6.14 (my friend tested), 2.6.15(me) and 2.6.16 (also me) As I am currently working on 2.6.15 (and 2.6.16 was installed only for testing of UDP) - i send info about 2.6.15, and WORKED on kernel 2.6.x Btw. I use some packages from backports.org (this is not exactly sarge), but I tested compiled program from other systems (mandrake, pure debian sarge) and it didn't work. $ keywords networking, kernel $ cat /proc/version Linux version 2.6.15-1-k7 (Debian 2.6.15-7bpo1) (nobse@debian.org) (gcc version 3.3.5 (Debian 1:3.3.5-13)) #2 Tue Mar 7 02:52:03 CET 2006 $ cat str.h #ifndef _STR_H_ #define _STR_H_ #define MAX_PACKET 1024 typedef struct __packet_ { unsigned int nr; unsigned short len; char buf[ MAX_PACKET ]; } packet; #endif /* _STR_H_ */ $ cat server.c #include #include #include #include #include #include #include #include #include /* clock() */ #include #include "str.h" #define boolean unsigned char #define false 0 #define true 1 #define MAX_PACKETS 65535 #define TIMEOUT 1 #define MAX_ERRORS 10 #ifndef socklen_t #define socklen_t int #endif /* socklen_t */ #include int stats[256]; void interrupt_handler() { FILE* f; int i; f = fopen( "stats.txt", "w+" ); for (i=0; i<256; i++) { fprintf( f, "Znak: %d wystapien: %d\n", i, stats[i] ); } fclose( f ); printf( "Zapisano statystyke\n" ); exit(0); } void initCount() { int i; for (i = 0; i<256; i++) { stats[i] = 0; } } void countChars( char* s, int len ) { int p; p = 0; while ( p < len ) { stats[(unsigned char) s[p]]++; p++; } } clock_t MAX_CLOCK_T = (clock_t)-1; unsigned int CLOCK_LEN; /* dlugosc przedzialu zegara */ unsigned int clock_diff( clock_t from, clock_t to ) { return (to - from + MAX_CLOCK_T) % MAX_CLOCK_T; } void changeCase( char* s, int len ) { int p = 0; while (p='A') && (s[p]<='Z')) { s[p] = s[p]+32; } else if ((s[p]>='a') && (s[p]<='z')) { s[p] = s[p]-32; } p++; } } int main( int argc, char** argv ) { struct sockaddr_in cli_address; struct sockaddr_in serv_address; int s; int port; packet p; initCount(); if (signal( SIGINT, interrupt_handler ) == SIG_ERR) { printf( "Blad przechwytywacza sygnalu SIGINT\n" ); }; if ( argc < 2 ) { printf( "Syntax error: %s \n", argv[0] ); exit( 1 ); } memset(&serv_address, 0, sizeof(serv_address)); /* na wszelki wypadek wyzeruj calosc */ port = atol( argv[1] ); printf( "Port: %d\n", port ); /* tworzy gniazdo UDP */ s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if ( s == -1 ) { perror( "Socket error" ); exit( 2 ); } /* przygotuj strukture zawierajaca nr portu, na którym chcemy nasluchiwac */ memset(&serv_address, 0, sizeof(serv_address)); serv_address.sin_family = AF_INET; serv_address.sin_addr.s_addr = htonl(INADDR_ANY); serv_address.sin_port = htons(port); /* zwiaz lokalny koniec gniazda z przygotowanym adresem */ if ( bind(s, (struct sockaddr *) &serv_address, sizeof(serv_address)) == -1 ) { perror( "Cannot bind socket" ); exit(1); }; while (1) { int rd; int i; socklen_t from_size; rd = recvfrom( s, (char*)&p, sizeof(p), 0, (struct sockaddr *)&cli_address, &from_size); printf("Received packet from %s:%d\n\n", inet_ntoa(cli_address.sin_addr), ntohs(cli_address.sin_port)); if ( rd == -1 ) { perror( "recvfrom() failed\n" ); exit( 3 ); } if ( rd != sizeof(packet)) { printf( "Bad size of packet\n" ); } countChars( p.buf, ntohs(p.len) ); changeCase( p.buf, ntohs(p.len) ); sendto( s, &p, sizeof(p), 0, (struct sockaddr *)&cli_address, (size_t) sizeof(cli_address) ); } return 0; } $ cat client.c #include #include #include #include #include #include #include #include #include #include /* clock() */ #include #include /* ioctl */ #include "str.h" #ifndef socklen_t #define socklen_t int #endif /* socklen_t */ #define boolean unsigned char #define false 0 #define true 1 #define MAX_PACKETS 65535 #define TIMEOUT 1 #define MAX_ERRORS 10 clock_t MAX_CLOCK_T = (clock_t)-1; unsigned int CLOCK_LEN; /* dlugosc przedzialu zegara */ unsigned int clock_diff( clock_t from, clock_t to ) { if ( from > to ) { return MAX_CLOCK_T - from + to; } return (to - from); } int try_to_relay( int s, char* buf, int len, struct sockaddr_in address, void* answer ) { int wr; int rd; clock_t start_clock; static int packet_number = 0; packet p; packet p_answer; socklen_t from_size; if ( len > MAX_PACKET ) return -1; packet_number++; p.nr = packet_number; p.len = htons(len); memcpy( p.buf, buf, len ); printf("Sending\n"); wr = sendto(s, &p, sizeof(p), 0, (struct sockaddr *)&address, (size_t) sizeof(address)); if (wr != sizeof(p)) { printf( "ERROR sending\n" ); return -1; } start_clock = clock(); /* czekanie */ while (clock_diff(start_clock, clock()) < CLOCKS_PER_SEC * TIMEOUT) { rd = recvfrom( s, &p_answer, sizeof(p_answer), 0, (struct sockaddr *)&address, &from_size); if ( rd == sizeof(p_answer)) { if ( p_answer.nr == packet_number ) { p_answer.len = ntohs( p_answer.len ); if ( p_answer.len == len ) { memcpy( answer, p_answer.buf, len ); return 0; } else { printf( "Good packet number, but corrupted length.\n" ); exit(1); } } } } printf( "Timeout has been exceeded for packet %d\n", packet_number ); return -2; } int main( int argc, char** argv ) { struct sockaddr_in address; int s; int r; FILE* f; FILE* g; int f_fd; int fionbio_int; memset(&address, 0, sizeof(address)); /* na wszelki wypadek wyzeruj calosc */ address.sin_family = AF_INET; if ( argc < 3 ) { printf( "Syntax error: %s \n", argv[0] ); exit( 1 ); } if (argc>1) { struct hostent *h; h = gethostbyname(argv[1]); if (h == NULL) { printf("Could not solve the host address %s\n", argv[1]); exit(1); }; memcpy(&address.sin_addr, h->h_addr, 4); } address.sin_port = htons(atol(argv[2])); s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); fionbio_int = 1; ioctl( s, FIONBIO, &fionbio_int ); f = fopen( "in.txt", "r" ); f_fd = fileno( f ); if ( f == NULL ) { printf( "Could not open 'in.txt' file for reading\n" ); } g = fopen( "out.txt", "w+" ); if ( g == NULL ) { printf( "Could not open 'out.txt' for writing\n" ); } while (!feof(f)) { int i; int pos; int c; char buf[MAX_PACKET]; char buf_out[MAX_PACKET]; int errors; pos = 0; errors = 0; for (i = 0; i MAX_ERRORS ) { printf( "Maximum number of errors exceeded\n" ); exit(2); }; } for (i=0; iTAbort- SERR- TAbort- SERR- TAbort- SERR- TAbort- SERR- TAbort- SERR- TAbort- SERR- TAbort- SERR- TAbort- SERR- TAbort- SERR- TAbort- SERR- Reset- FastB2B- 0000:00:0e.0 PCI bridge: nVidia Corporation: Unknown device 00ed (rev a2) (prog-if 00 [Normal decode]) Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR+ FastB2B- Status: Cap- 66MHz+ UDF- FastB2B+ ParErr- DEVSEL=fast >TAbort- SERR- Reset- FastB2B- 0000:00:18.0 Host bridge: Advanced Micro Devices [AMD] K8 NorthBridge Control: I/O- Mem- BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- SERR- TAbort- SERR- TAbort- SERR- TAbort- SERR- TAbort- SERR- TAbort- SERR-