/* -----------------------------------------------------------------------------------------------------------*/ unsigned int UDP_RegisterSocket( unsigned long IP, unsigned int DestinationPort, unsigned int Bufferlenght, unsigned char * UDP_Recivebuffer) { unsigned int SOCKET; SOCKET = UDP_Getfreesocket(); if ( SOCKET == 0xffff ) return( 0xffff ); UDP_sockettable[SOCKET].Socketstate = SOCKET_READY; UDP_sockettable[SOCKET].DestinationPort = ChangeEndian16bit( DestinationPort ); // wenn Zielport Bootps(67) dann Sourceport auf Bootpc(68) setzen um kommunikation mit DHCP-Server zu ermöglichen if ( DestinationPort == 67 ) UDP_sockettable[SOCKET].SourcePort = ChangeEndian16bit( 68 ); else UDP_sockettable[SOCKET].SourcePort =~ DestinationPort; UDP_sockettable[SOCKET].DestinationIP = IP; UDP_sockettable[SOCKET].Bufferfill = 0; UDP_sockettable[SOCKET].Bufferlenght = Bufferlenght; UDP_sockettable[SOCKET].Recivebuffer = UDP_Recivebuffer; UDP_sockettable[SOCKET].ttl = UDP_Default_ttl; if ( IP == 0xffffffff ) { for( unsigned char i = 0 ; i < 6 ; i++ ) UDP_sockettable[SOCKET].MACadress[i] = 0xff; return( SOCKET ); } if ( IS_ADDR_IN_MY_SUBNET( IP, Netmask ) ) if ( IS_BROADCAST_ADDR( IP, Netmask ) ) for( unsigned char i = 0 ; i < 6 ; i++ ) UDP_sockettable[SOCKET].MACadress[i] = 0xff; else GetIP2MAC( IP, &UDP_sockettable[SOCKET].MACadress ); else GetIP2MAC( Gateway, &UDP_sockettable[SOCKET].MACadress ); return(SOCKET); }
/* -----------------------------------------------------------------------------------------------------------*/ void udp( unsigned int packet_lenght, unsigned char * ethernetbuffer ) { unsigned int i, SOCKET , Offset; struct ETH_header * ETH_packet; // ETH_struct anlegen ETH_packet = (struct ETH_header *) ethernetbuffer; struct IP_header * IP_packet; // IP_struct anlegen IP_packet = ( struct IP_header *) ðernetbuffer[ETHERNET_HEADER_LENGTH]; struct UDP_header * UDP_packet; // TCP_struct anlegen UDP_packet = ( struct UDP_header *) ðernetbuffer[ETHERNET_HEADER_LENGTH + ((IP_packet->IP_Version_Headerlen & 0x0f) * 4 )]; #ifdef _DEBUG_ printf_P( PSTR("UDP-Packet empfangen") , packet_lenght ); #endif SOCKET = UDP_GetSocket( ethernetbuffer ); // Socket zugeordnet ? if ( SOCKET == 0xffff ) return; // Socket schon mit daten belegt ? if ( UDP_sockettable[ SOCKET ].Socketstate == SOCKET_BUSY ) return ; // Hat Socket Daten ? if ( ( ChangeEndian16bit( UDP_packet->UDP_Datalenght ) - UDP_HEADER_LENGHT ) == 0 ) return ; // Größe der Daten limitieren auf Puffergröße i = MIN( ChangeEndian16bit( UDP_packet->UDP_Datalenght) - UDP_HEADER_LENGHT , UDP_sockettable[ SOCKET ].Bufferlenght ); // Größe der Daten eintragen UDP_sockettable[ SOCKET ].Bufferfill = i; // Socket als belegt melden UDP_sockettable[ SOCKET ].Socketstate = SOCKET_BUSY; // ttl wieder richtig setzen UDP_sockettable[SOCKET].ttl = UDP_Default_ttl; // Offset für UDP-Daten im Ethernetfrane berechnen Offset = ETHERNET_HEADER_LENGTH + ((IP_packet->IP_Version_Headerlen & 0x0f) * 4 ) + UDP_HEADER_LENGHT; // Daten kopieren while ( i-- ) { UDP_sockettable[ SOCKET ].Recivebuffer[i] = ethernetbuffer[ Offset + i ]; } return; }
/* -----------------------------------------------------------------------------------------------------------*/ void MakeIPheader( unsigned long SourceIP, unsigned char Protocoll, unsigned int Datalenght , unsigned char *ethernetbuffer ) { struct ETH_header *ETH_packet; // ETH_struct anlegen ETH_packet = (struct ETH_header *) ethernetbuffer; struct IP_header *IP_packet; // IP_struct anlegen IP_packet = ( struct IP_header *) ðernetbuffer[ETHERNET_HEADER_LENGTH]; struct TCP_header *TCP_packet; // TCP_struct anlegen TCP_packet = ( struct TCP_header *) ðernetbuffer[ETHERNET_HEADER_LENGTH + ((IP_packet->IP_Version_Headerlen & 0x0f) * 4 )]; IP_packet->IP_Version_Headerlen = 0x45; IP_packet->IP_TOS = 0x0; IP_packet->IP_Totallenght = ChangeEndian16bit ( IP_HEADER_LENGHT + Datalenght ); IP_packet->IP_Identification = 0x1DAC; IP_packet->IP_Flags = 0x40; IP_packet->IP_Fragmentoffset = 0x0; IP_packet->IP_TTL = 64 ; IP_packet->IP_Protocol = Protocoll; IP_packet->IP_Headerchecksum = 0x0; IP_packet->IP_SourceIP = myIP; IP_packet->IP_DestinationIP = SourceIP; IP_packet->IP_Headerchecksum = ChangeEndian16bit( Checksum_16( ðernetbuffer[ETHERNET_HEADER_LENGTH] ,(IP_packet->IP_Version_Headerlen & 0x0f) * 4 ) ); return; }
/* -----------------------------------------------------------------------------------------------------------*/ unsigned int UDP_ListenOnPort( unsigned int Port, unsigned int Bufferlenght, unsigned char * UDP_Recivebuffer) { unsigned int SOCKET; SOCKET = UDP_Getfreesocket(); if ( SOCKET == 0xffff ) return( 0xffff ); UDP_sockettable[SOCKET].Socketstate = SOCKET_READY; UDP_sockettable[SOCKET].DestinationPort = 0 ; UDP_sockettable[SOCKET].SourcePort = ChangeEndian16bit( Port ); UDP_sockettable[SOCKET].DestinationIP = 0 ; UDP_sockettable[SOCKET].Bufferfill = 0; UDP_sockettable[SOCKET].Bufferlenght = Bufferlenght; UDP_sockettable[SOCKET].Recivebuffer = UDP_Recivebuffer; return(SOCKET); }
/* ----------------------------------------------------------------------------------------------------------- Bastelt den UDP-header ------------------------------------------------------------------------------------------------------------*/ unsigned int MakeUDPheader( unsigned int SOCKET, unsigned int Datalenght, unsigned char * ethernetbuffer ) { if ( SOCKET >= MAX_UDP_CONNECTIONS ) return( 0xffff ); struct ETH_header * ETH_packet; // ETH_struct anlegen ETH_packet = (struct ETH_header *) ethernetbuffer; struct IP_header * IP_packet; // IP_struct anlegen IP_packet = ( struct IP_header *) ðernetbuffer[ETHERNET_HEADER_LENGTH]; struct UDP_header * UDP_packet; // TCP_struct anlegen UDP_packet = ( struct UDP_header *) ðernetbuffer[ETHERNET_HEADER_LENGTH + ((IP_packet->IP_Version_Headerlen & 0x0f) * 4 )]; UDP_packet->UDP_DestinationPort = UDP_sockettable[SOCKET].DestinationPort; UDP_packet->UDP_SourcePort = UDP_sockettable[SOCKET].SourcePort; UDP_packet->UDP_Checksum = 0; UDP_packet->UDP_Datalenght = ChangeEndian16bit( 8 + Datalenght ); UDP_sockettable[SOCKET].ttl = UDP_Default_ttl; return(0); }
void icmp( unsigned int packet_lenght, unsigned char *buffer) { unsigned char i; unsigned int checksum; struct ETH_header *ETH_packet; // ETH_struct anlegen ETH_packet = (struct ETH_header *)&buffer[0]; struct IP_header *IP_packet; // IP_struct anlegen IP_packet = ( struct IP_header *)&buffer[ETHERNET_HEADER_LENGTH]; struct ICMP_header *ICMP_packet; // ICMP_struct anlegen ICMP_packet = ( struct ICMP_header *)&buffer[ETHERNET_HEADER_LENGTH + ((IP_packet->IP_Version_Headerlen & 0x0f) * 4 )]; switch ( ICMP_packet->ICMP_type ) { case ICMP_EchoRequest: //IP_header unbauen zum versenden IP_packet->IP_DestinationIP = IP_packet->IP_SourceIP; IP_packet->IP_SourceIP = myIP; //IP_header checksummer ausrechnen IP_packet->IP_Headerchecksum = 0x0; checksum = Checksum_16( &buffer[14], ((IP_packet->IP_Version_Headerlen & 0x0f) * 4 ) ); IP_packet->IP_Headerchecksum = ChangeEndian16bit( checksum ); ICMP_packet->ICMP_type = ICMP_EchoReplay; // auf reply einstellen ICMP_packet->ICMP_code = 0x00; //Simple ICMP Checksummenbildung, die Idee stammt von //Simon, siehe http://avr.auctionant.de/ if(ICMP_packet->ICMP_checksumByteOne > 0xFF-0x08)ICMP_packet->ICMP_checksumByteTwo++; ICMP_packet->ICMP_checksumByteOne+=0x08; // Ethernetframe bauen for(i = 0; i < 6 ; i++ ){ ETH_packet->ETH_destMac[i] = ETH_packet->ETH_sourceMac[i]; ETH_packet->ETH_sourceMac[i] = mymac[i]; } // und ab die post sendEthernetframe( packet_lenght, buffer); // packet_lenght - 4 weil der Controller die checksumme selber berechnet break; case ICMP_EchoReplay: if ( ICMP_packet->ICMP_Identifierer == 0xac1d && ICMP_Replaystate == ICMP_WaitForReplay ) ICMP_Replaystate = ICMP_ReplayOkay; break; } }
/*! \brief Holt von einen Hostname die IP-Adressen * \warning Es ist drauf zu achten das genug Speicher vorgesehen ist fuer die Anworten und das auch Packete mit entsprechender groesse * vom Ethernetmodul empfagen werden koennen und nicht verworfen werden. Siehe MAX_FRAMELEN in enc28j60.h . * \param HOSTNAME Zeiger auf den Hostnamestring der mit 0 teminiert ist. * \retval IP Die IP des Hostname, wenn IP = DNS_NO_ANSWER ist war die Anfrage nicht erfolgreich. Es sollte der DNSserver Eintrag ueberprueft werden * oder die richtigkeit des Hostname. */ unsigned long DNS_ResolveName( char * HOSTNAME ) { int i,UDP_socket; int timer; // udp-puffer anlegen unsigned char * udpbuffer; udpbuffer = (unsigned char*) __builtin_alloca (( size_t ) DNS_BUFFER_LENGHT ); // DNS-struct in udp-puffer anlegen struct DNS_header * DNS_question; DNS_question = ( struct DNS_header *) udpbuffer; // DNS anfrage bauen DNS_question->TransactionID = 0x1acd; DNS_question->Flags = ChangeEndian16bit( 0x0100 ); DNS_question->Questions = ChangeEndian16bit( 1 ); DNS_question->Answer_RRs = 0; DNS_question->Authority_RRs = 0; DNS_question->Additional_RRs = 0; // Hostename für DNS umwandeln, in i steht die länge des neuen strings i = DNS_convertHostName( HOSTNAME, DNS_question->Queries ); DNS_question->Queries[i + 1] = '\0'; DNS_question->Queries[i + 2] = 1; DNS_question->Queries[i + 3] = '\0'; DNS_question->Queries[i + 4] = 1; i = i + 5; // Antwortstruct anlegen struct DNS_answer * DNS_ans; DNS_ans = ( void * ) &DNS_question->Queries[i]; // UDP-Paccket senden UDP_socket = UDP_RegisterSocket( DNSserver , DNS_SERVER_PORT, DNS_BUFFER_LENGHT , udpbuffer); if ( UDP_socket == UDP_SOCKET_ERROR ) return( DNS_NO_ANSWER ); UDP_SendPacket( UDP_socket, DNS_HEADER_LENGHT + i , udpbuffer); // empfang des der DNS-Atwort abwarten timer = CLOCK_RegisterCoundowntimer(); if ( timer == CLOCK_FAILED ) return ( DNS_NO_ANSWER ); CLOCK_SetCountdownTimer ( timer, DNS_REQUEST_TIMEOUT, MSECOUND ); while ( 1 ) { if ( UDP_GetSocketState( UDP_socket ) == UDP_SOCKET_BUSY ) { CLOCK_ReleaseCountdownTimer( timer ); UDP_CloseSocket( UDP_socket ); if ( ( ChangeEndian16bit( DNS_question->Flags ) & 0x000f ) != 0 ) return ( DNS_NO_ANSWER ); break; } if ( CLOCK_GetCountdownTimer( timer ) == 0 ) { CLOCK_ReleaseCountdownTimer( timer ); UDP_CloseSocket( UDP_socket ); return( DNS_NO_ANSWER ); } } // Antwortpacket auseinander nehmen while ( 1 ) { // Wenn noch nicht der Hosteintrag dann nächsten DNS-Answer Datensatz if ( ChangeEndian16bit( DNS_ans->Type ) != A_HOSTNAME ) { i = i + ChangeEndian16bit( DNS_ans->Datalenght ) + DNS_ANSWER_HEADER_LENGHT; DNS_ans = ( void * ) &DNS_question->Queries[i]; } else break; } return( DNS_ans->Adress ); }