Homepage

  • Projekte
  • Shop
  • Forum
Erweiterte Suche
  • Schnellzugriff
    • Unbeantwortete Themen
    • Aktive Themen
    • Suche
  • FAQ
  • Anmelden
  • Registrieren
  • Foren-Übersicht
  • Suche

Ein DHCP Client für den AVR Server

Projekt aus Elektor 2007
Antworten
  • Druckansicht
Erweiterte Suche
2 Beiträge • Seite 1 von 1
a_boehme

Ein DHCP Client für den AVR Server

  • Zitieren

Beitrag von a_boehme » 28.08.2006, 01:15:33

Ich habe mal (versucht) einen dhcp client für den Small Webserver zu schreiben.. Evt. gibt's da ja noch Optimierungspotential, wenn nicht viel Spass ;) Hier mal der Quellcode...

----- dhcp.c -------

Code: Alles auswählen

// DHCP Client for Small AVR Server
// (C) 2006 Andreas Böhme
//
#include "evalboard.h"
#include "dhcp.h"
#include "socket.h"


unsigned long transaction = 0xDE524160;
unsigned char new_ip[4] = {0, 0, 0, 0};
unsigned char dhcp_server[4];

void request_ip(void) {
  cli(); dhcp_request(packet, 0, 1); sei();  
}



void dhclient(char* buffer, int bufferlen) {
	unsigned int udpdata;
	unsigned int option_offset = 4;
	unsigned char option_length;
	unsigned char message_type = 0;
	unsigned long lease_t = 0;
	
    udpdata = ((buffer[IP_VERS_LEN] & 0x0F) << 2) + 14 + 8;
	dhcp_t* dhcp_packet = (dhcp_t*) &buffer[udpdata];

	// Hat die Antwort die richtige ID, sonst verwerfen!
    if (dhcp_packet->bp_xid == transaction) {	
	  // Options block parsen um die relevanten Datenteile zu ermitteln
	  while (dhcp_packet->options[option_offset] != 0xff) {
	    switch (dhcp_packet->options[option_offset]) {
		  // Option 51: Lease time
		  case 51: lease_t = dhcp_packet->options[option_offset + 2] * 0x1000000 + dhcp_packet->options[option_offset + 3] * 0x10000 + dhcp_packet->options[option_offset + 4] * 0x100 + dhcp_packet->options[option_offset + 5]; break;
		  // Option 53: DHCP Message Type
		  case 53: message_type = dhcp_packet->options[option_offset + 2]; break;
		  // Option 54: Adresse des Servers
		  case 54: for (unsigned char a = 0; a < 4; a++) dhcp_server[a] = dhcp_packet->options[option_offset + 2 + a];
		  default: ;
		}
  	    option_length = dhcp_packet->options[option_offset + 1];
	    printf ("Option %d: ",dhcp_packet->options[option_offset]);
	    for (unsigned char a = 2; a < option_length + 2; a++)
	      printf ("%x ", dhcp_packet->options[option_offset + a]);
	    printf("\n");
	    option_offset += (option_length + 2);
	  }

  	  if (message_type == 2) {
      	  printf ("Offered Address: %d.%d.%d.%d\n", dhcp_packet->bp_yiaddr[0], dhcp_packet->bp_yiaddr[1], dhcp_packet->bp_yiaddr[2], dhcp_packet->bp_yiaddr[3]);	  
		  for (unsigned char a = 0; a < 4; a++)
            new_ip[a] = dhcp_packet->bp_yiaddr[a];
	      dhcp_request(buffer, bufferlen, 3);
	    }
		else {
		  for (unsigned char a = 0; a < 4; a++)
            new_ip[a] = 0;
		}

		if (message_type == 5) {
     	printf ("Assigned Address: %d.%d.%d.%d\n", dhcp_packet->bp_ciaddr[0], dhcp_packet->bp_ciaddr[1], dhcp_packet->bp_ciaddr[2], dhcp_packet->bp_ciaddr[3]);	  
		for (unsigned char a = 0; a < 4; a++)
		  MYIP[a] = dhcp_packet->bp_ciaddr[a];
		lease_time = lease_t;
	  }
	}
}


void dhcp_request(char *buffer, int bufferlen, unsigned char mode) {
	unsigned int udpdata;
	struct Ethernet_Header *ethernet;
	ethernet = (struct Ethernet_Header *)&buffer[ETHER_OFFSET];
	struct IP_Header *ip;
	ip = (struct IP_Header *)&buffer[IP_OFFSET];
	struct TCP_Header *tcp;
	tcp = (struct TCP_Header *)&buffer[TCP_OFFSET];
	unsigned int result16;
	ethernet->EnetPacketType = 0x0008;

	// Broadcast an 255.255.255.255
	ip->IP_Srcaddr = 0;
    ip->IP_Destaddr = 0xffffffff;
	for (unsigned char a = 0; a < 6; a++) {
		ethernet->EnetPacketSrc[a] = 0xff;
	}
	ip->IP_Vers_Len = 0x45; 
	ip->IP_Tos = 0x00;	
	ip->IP_Id = 0x00c0;	
	ip->IP_Frag_Offset = 0x0040;
	ip->IP_ttl = 64;
	ip->IP_Proto = PROT_UDP;

	buffer[TCP_ACKNUM+0] = 0;
	buffer[TCP_ACKNUM+1] = 0;
	buffer[TCP_ACKNUM+2] = 0;
	buffer[TCP_ACKNUM+3] = 0;

	buffer[TCP_SEQNUM+0] = 0;
	buffer[TCP_SEQNUM+1] = 0;
	buffer[TCP_SEQNUM+2] = 0;
	buffer[TCP_SEQNUM+3] = 0;

	buffer[TCP_HDRFLAGS+1] = FIN_FLAG; 

	tcp_store(buffer);

	buffer[TCP_SRCPORT+0]  = (SOCKET_DHCPD & 0xff);
	buffer[TCP_SRCPORT+1]  = (SOCKET_DHCPD >> 8);
	buffer[TCP_DESTPORT+0] = (SOCKET_DHCP & 0xff);
	buffer[TCP_DESTPORT+1] = (SOCKET_DHCP >> 8);

	tcp_make(buffer);
	//  ????? Funktion in tcp.c eingefügt, wie sonst kann man einen leeren Buffer mit einer bestimmten Grösse erzeugen ?
	make_zero_data (DHCP_PACKET_SIZE, buffer, &bufferlen);
    udpdata = ((buffer[IP_VERS_LEN] & 0x0F) << 2) + 14 + 8;
	//nun dem Buffer (UDP Daten) die Struktur aus DHCP_H aufzwängen ;)
	dhcp_t* dhcp_packet = (dhcp_t*) &buffer[udpdata];
    dhcp_packet->bp_opcode = 0x01; dhcp_packet->bp_htype = 0x01; dhcp_packet->bp_hlen = 0x06; dhcp_packet->bp_hops = 0x00;dhcp_packet->bp_secs = 0x00; dhcp_packet->bp_flags = 0x00;
	for (unsigned char a = 0; a < 6; a++)
	  dhcp_packet->chaddr[a] = mymac[a];
	
	dhcp_packet->bp_xid = transaction;
	//magic cookie in options setzen
    dhcp_packet->options[0] = 0x63;	dhcp_packet->options[1] = 0x82;	dhcp_packet->options[2] = 0x53;	dhcp_packet->options[3] = 0x63;	
	//DHCP Message Type setzen
	dhcp_packet->options[4] = 0x35; dhcp_packet->options[5] = 0x01; dhcp_packet->options[6] = mode; 
	
	// Wir machen ein DISCOVER ohne zusätzliche options
	if (mode == 1) {
  	  for (unsigned char a = 0; a < 4; a++)
	    dhcp_packet->bp_ciaddr[a] = MYIP[a];
	  dhcp_packet->options[7] = 0xff;
	}
	
	// Nun ein DHCP-Request, Options müssen mit dem Werten aus dem DHCPOFFER gefüllt werden
	if (mode == 3) {
  	  for (unsigned char a = 0; a < 4; a++)
	    dhcp_packet->bp_ciaddr[a] = new_ip[a];
	  dhcp_packet->options[7] = 0x32; dhcp_packet->options[8] = 0x04;
	  for (unsigned char a = 0; a < 4; a++)
	    dhcp_packet->options[9+a] = new_ip[a];
      dhcp_packet->options[13] = 0x3d; dhcp_packet->options[14] = 0x07; dhcp_packet->options[15] = 0x01;
      for (unsigned char a = 0; a < 6; a++)
	    dhcp_packet->options[16+a] = mymac[a];
    dhcp_packet->options[22] = 0x36; dhcp_packet->options[23] = 0x04; 
     for (unsigned char a = 0; a < 4; a++)
	    dhcp_packet->options[24+a] = dhcp_server[a];
	dhcp_packet->options[28] = 0xff;
	}
    ip->IP_Destaddr = 0xffffffff;
	ip->IP_Hdr_Cksum = 0x0000;
	
	result16 = (ip->IP_Vers_Len & 0x0F) << 2;

	result16 = checksum (&ip->IP_Vers_Len, result16, 0);

	ip->IP_Hdr_Cksum = ((result16 & 0xFF00) >> 8)|((result16 & 0x00FF)<<8);

	Write_Ethernet_Frame (buffer, bufferlen);

}

------------------- dhcp.h ------------------

Code: Alles auswählen

#ifndef _DHCP_H
 #define _DHCP_H
 
#define DHCP_CHADDR_LEN         16
#define DHCP_SNAME_LEN          64
#define DHCP_FILE_LEN           128
#define DHCP_OPTIONS_LEN        68
#define DHCP_MIN_OPTIONS_LEN    68

#define DHCP_PACKET_SIZE (28 + DHCP_CHADDR_LEN + DHCP_SNAME_LEN + DHCP_FILE_LEN + DHCP_OPTIONS_LEN)
 
typedef struct dhcp_t  {
          char bp_opcode;
	      char bp_htype;
          char bp_hlen;
          char bp_hops;
          unsigned long bp_xid;
          unsigned int  bp_secs;
          unsigned int bp_flags;
          char bp_ciaddr[4];
          char bp_yiaddr[4];
          char bp_siaddr[4];
          char bp_giaddr[4];
		  char chaddr[DHCP_CHADDR_LEN];
		  char sname[DHCP_SNAME_LEN];
		  char fname[DHCP_FILE_LEN];
		  char options[DHCP_OPTIONS_LEN];
      } dhcp_t;

 
extern void dhcp_request(char *buffer, int bufferlen, unsigned char mode);
extern void dhclient(char* buffer, int bufferlen);
extern void request_ip(void);

#endif

---------------------- Änderung in der tcp.c -----------------------------
Folgende Funktion einfügen, und natürlich in tcp.h bekannt machen

Code: Alles auswählen

//############################################################################
//Erzeugt einen leeren Buffer
//############################################################################
char make_zero_data (unsigned int count,char *buffer,int *bufferlen) {
	//Variablen Für die Routine
	unsigned int result16, userdatacount = 8;
	unsigned char Data = 1;
	unsigned char Buffer_Full = 0;

	//Errechnet startpunkt der Daten im Tcp buffer
	//IP Headerlänge + TCP Headerlänge + Ethernetframe
	result16 = ((buffer[IP_VERS_LEN] & 0x0F) << 2)  + 14 + 8;

	for(unsigned int i = 0; i < count; i++) {
		buffer[result16] = 0;
		result16++;
		userdatacount++;
		//sind die daten länger als ein Ethernetbuffer dann abbruch
		if (result16 >  (MTU_SIZE - 1)) {
			Buffer_Full = 1;
			break;
		}
	}
	buffer[UDP_LENGTH+1] = userdatacount & 0xff;
	buffer[UDP_LENGTH] = userdatacount >> 8;
	
	buffer[UDP_CHKSUM+1] = 0x00;   // we don't use a chksum !
	buffer[UDP_CHKSUM] = 0x00;
	
	TCP_New_Packtlen(buffer, bufferlen, result16);
	//*bufferlen = result16;
	return (Buffer_Full);
}

In interrupt4.c vor der Überprüfung auf Ethernet_Ip_Datagram und die IP (ca. Zeile 95) folgendes einfügen:

Code: Alles auswählen

	    if ((Ethernet_IP_Datagramm) && (IP_UDP_Packet) && (tcp->TCP_DestPort == SOCKET_DHCP))
           dhclient(packet,&packetlen);

In der Socket.h sollten dann noch die Ports wie folgt defined sein:

Code: Alles auswählen

#define SOCKET_DHCPD 	0x4300
#define SOCKET_DHCP		0x4400 	//bootpd/dhcp 


Wenn ich nichts vergessen habe, sollte es dann durch Aufruf der Request Funktion erfolgreich eine IP geben... Ich habe es "nur" mit meinem Linux Rechner bis jetzt probiert, daher wäre es gut wenn es noch Tests mit anderen Servern geben würde... Was passiert, wenn 2 Server im Netz hängen ???

Hier noch das LOG über die serielle Schnittstelle:
Option 53: 2
Option 54: c0 a8 1 1
Option 51: 0 0 2 58
Option 1: ff ff ff 0
Option 3: c0 a8 1 2
Option 6: c0 a8 1 1
Option 58: 0 0 1 2c
Option 59: 0 0 2 d
Option 15: 6c 6f 63 61 6c 2e 6e 65 74
Offered Address: 192.168.1.201
Option 53: 5
Option 54: c0 a8 1 1
Option 51: 0 0 2 58
Option 1: ff ff ff 0
Option 3: c0 a8 1 2
Option 6: c0 a8 1 1
Option 58: 0 0 1 2c
Option 59: 0 0 2 d
Option 15: 6c 6f 63 61 6c 2e 6e 65 74
Assigned Address: 192.168.1.201
[/code]
Nach oben

genlog
Beiträge: 14
Registriert: 29.07.2006, 19:27:05
Wohnort: Köln
Kontaktdaten:
Kontaktdaten von genlog
ICQ Website

  • Zitieren

Beitrag von genlog » 09.10.2006, 07:43:15

Was passiert, wenn 2 Server im Netz hängen ???
Innerhalb eines LANs (gleiches Netz) darf es nur einen DHCP-Server geben IMHO.
Kann sonst üble Probleme geben.

:-)

Werde DHCP mal versuchen zu implementieren.

Gruß
Stephan
Nach oben

Antworten
  • Druckansicht

2 Beiträge • Seite 1 von 1

Zurück zu „AVR WebServer (alte Version)“



  • Foren-Übersicht
  • Alle Zeiten sind UTC+02:00
  • Alle Cookies löschen

Powered by phpBB® Forum Software © phpBB Limited

Deutsche Übersetzung durch phpBB.de

Datenschutz | Nutzungsbedingungen

 

 

sitemap  |    |  datenschutz   |  impressum