Čeština / English
Login

SVN Repository / Prohlížení

Aktuální adresář: FITkit / trunk / mcu / libs / enc28j60 /

enc28j60_dhcp.c

   1  /*******************************************************************************
   2     enc28j60_dhcp.c: Implementace protokolu DHCP.
   3     Copyright (C) 2010 Brno University of Technology,
   4                        Faculty of Information Technology
   5     Author(s): Martin Musil <xmusil34 AT fit.vutbr.cz>
   6  
   7     LICENSE TERMS
   8  
   9     Redistribution and use in source and binary forms, with or without
  10     modification, are permitted provided that the following conditions
  11     are met:
  12     1. Redistributions of source code must retain the above copyright
  13        notice, this list of conditions and the following disclaimer.
  14     2. Redistributions in binary form must reproduce the above copyright
  15        notice, this list of conditions and the following disclaimer in
  16        the documentation and/or other materials provided with the
  17        distribution.
  18     3. All advertising materials mentioning features or use of this software
  19        or firmware must display the following acknowledgement:
  20  
  21          This product includes software developed by the University of
  22          Technology, Faculty of Information Technology, Brno and its
  23          contributors.
  24  
  25     4. Neither the name of the Company nor the names of its contributors
  26        may be used to endorse or promote products derived from this
  27        software without specific prior written permission.
  28  
  29     This software or firmware is provided ``as is'', and any express or implied
  30     warranties, including, but not limited to, the implied warranties of
  31     merchantability and fitness for a particular purpose are disclaimed.
  32     In no event shall the company or contributors be liable for any
  33     direct, indirect, incidental, special, exemplary, or consequential
  34     damages (including, but not limited to, procurement of substitute
  35     goods or services; loss of use, data, or profits; or business
  36     interruption) however caused and on any theory of liability, whether
  37     in contract, strict liability, or tort (including negligence or
  38     otherwise) arising in any way out of the use of this software, even
  39     if advised of the possibility of such damage.
  40  
  41     $Id$
  42  
  43  *******************************************************************************/
  44  #include "enc28j60_dhcp.h"
  45  #include "enc28j60_udp.h"
  46  #include "enc28j60_ip.h"
  47  #include "enc28j60_arp.h"
  48  #include "enc28j60_spi.h"
  49  
  50  #include "enc28j60_string.h"
  51  
  52  extern unsigned char local_mac[MAC_LEN];
  53  unsigned char dhcp_state = DHCP_DISCOVER;
  54  unsigned long magic_cookie = 0x63538263;
  55  
  56  unsigned char dhcp_message_type;
  57  unsigned long dhcp_server_id = 0;
  58  unsigned long dhcp_netmask = 0;
  59  unsigned long dhcp_router = 0;
  60  unsigned long dhcp_dns_server = 0;
  61  unsigned long dhcp_transaction_id = 0x12345678;
  62  unsigned long dhcp_requested_ip = 0;
  63  unsigned char dhcp_timeout = DHCP_TIMEOUT;
  64  
  65  
  66  char dhcp_send_discover();
  67  
  68  char dhcp_send_request();
  69  
  70  // UDP handler - prijem DHCP zprav
  71  UDP_APP_HANDLER(dhcp_fsm){
  72  	//term_send_str_crlf(" DHCP zprava");
  73  	struct bootp_h bootp_header;
  74  
  75  	if(rx_left() < BOOTP_HEADER_LEN_TOTAL + MAGIC_LEN)	//paket musi byt vetsi nez bootp hlavicka + magic cookie
  76  		return;
  77  
  78  	rx_read(&bootp_header, BOOTP_HEADER_LEN);
  79  
  80  	if(bootp_header.opcode != BOOTP_REPLY){				//pouze BOOTP odpovedi
  81  		return;}
  82  
  83  	if(bootp_header.hw_type != BOOTP_HW_ETH){			//pouze ethernet protokol
  84  		return;}
  85  
  86  
  87  		return;}
  88  
  89  	if(bootp_header.transaction_id != dhcp_transaction_id){		//kontrola ID transkace (pouzivam cast MAC adresy)
  90  		return;}
  91  
  92  	rx_skip(BOOTP_HEADER_LEN_TOTAL - BOOTP_HEADER_LEN);						//prekoceni dalsich polozek hlavicky (server name, filename)
  93  
  94  		//magic packet
  95  	unsigned long dhcp_magic;
  96  	rx_read(&dhcp_magic,MAGIC_LEN);
  97  
  98  	if(dhcp_magic != MAGIC_COOKIE)									//kontrola pritomnosti magic_cookie
  99  		return;
 100  
 101  	dhcp_requested_ip = bootp_header.your_ip;							//nabizena IP adresa
 102  	unsigned int option;
 103  
 104  		//cteni DHCP nastaveni
 105  	while((rx_left() >0) & ((option=rx_getc()) != DHCP_END)){		//precteni typu parametru
 106  
 107  		if(option == DHCP_PAD)							//mezera
 108  			continue;
 109  
 110  		int len = rx_getc();					//delka parametru
 111  
 112  		switch(option){
 113  			case DHCP_MESSAGE_TYPE:				//typ zpravy
 114  				dhcp_message_type = rx_getc();
 115  				break;
 116  			case DHCP_ROUTER:					//IP routeru
 117  				rx_read(&dhcp_router,IP_LEN);
 118  				break;
 119  			case DHCP_DNS_SERVER:				//IP DNS serveru
 120  				rx_read(&dhcp_dns_server,IP_LEN);
 121  				break;
 122  			case DHCP_SERVER_ID:				//IP DHCP serveru
 123  				rx_read(&dhcp_server_id,IP_LEN);
 124  				break;
 125  			case DHCP_SUBNET_MASK:				//maska podsite
 126  				rx_read(&dhcp_netmask,IP_LEN);
 127  				break;
 128  
 129  			default:
 130  				rx_skip(len);
 131  		}
 132  	}
 133  	switch(dhcp_state){
 134  		case DHCP_DISCOVER:
 135  
 136  			switch(dhcp_message_type){		//prislusna akce na prichozi zpravu
 137  				case DHCP_OFFER:		//nabidka IP
 138  						dhcp_state = DHCP_REQUEST;
 139  						dhcp_timeout = DHCP_TIMEOUT;
 140  						dhcp_send_request();
 141  					break;
 142  
 143  				default:
 144  						dhcp_reset();
 145  			}
 146  
 147  		case DHCP_REQUEST:
 148  
 149  			switch(dhcp_message_type){			//prislusna akce na prichozi zpravu
 150  
 151  					//potvrzeni, ze se muze nabidnuta IP adresa pouzivat
 152  				case DHCP_ACK:
 153  
 154  					//nastaveni IP adresy,masky,brany,DNS
 155  					set_ip_l(HTONL(dhcp_requested_ip));
 156  					set_netmask_l(HTONL(dhcp_netmask));
 157  					set_gateway_l(HTONL(dhcp_router));
 158  					set_dns_server_l(HTONL(dhcp_dns_server));
 159  					dhcp_state = DHCP_ACK;
 160  
 161  					//zavreni socketu s DHCP
 162  					udp_unbind(DHCP_CLIENT_PORT);
 163  					break;
 164  
 165  				case DHCP_OFFER:
 166  					break;
 167  					//odmitnuti serveru
 168  				case DHCP_DECLINE:
 169  				case DHCP_NACK:
 170  					dhcp_reset();
 171  					break;
 172  			}
 173  	}
 174  return;
 175  }
 176  
 177  
 178  /**
 179   \brief Inicializace DHCP protokolu.
 180   **/
 181  char dhcp_init(){
 182  	set_ip(0,0,0,0);				//nulovani IP adres
 183  	set_netmask(255,255,255,255);
 184  	set_gateway(0,0,0,0);
 185  	dhcp_state = DHCP_DISCOVER;
 186  	dhcp_timeout = DHCP_TIMEOUT;
 187  	enc_memcpy(&dhcp_transaction_id, &local_mac,MAC_LEN -2); 	//ID transkace (pouziva se cast MAC adresy)
 188  
 189  	//zaregistrovani portu 68 pro prijem DHCP zprav
 190  return udp_bind(DHCP_CLIENT_PORT,dhcp_fsm);
 191  }
 192  
 193  /**
 194   \brief Restart DHCP klienta.
 195   **/
 196  char dhcp_reset(){
 197  	set_ip(0,0,0,0);				//nulovani IP adres
 198  	set_netmask(255,255,255,255);
 199  	set_gateway(0,0,0,0);
 200  	dhcp_state = DHCP_DISCOVER;
 201  	dhcp_timeout = DHCP_TIMEOUT;
 202  	dhcp_transaction_id++;
 203  
 204  	//zaregistrovani portu 68 pro prijem DHCP zprav
 205  return udp_bind(DHCP_CLIENT_PORT,dhcp_fsm);
 206  }
 207  
 208  /**
 209  
 210  
 211   **/
 212  void dhcp_timer(){
 213  
 214  	if(dhcp_timeout == 0)
 215  		dhcp_reset();
 216  
 217  	switch(dhcp_state){
 218  
 219  		case DHCP_DISCOVER:
 220  			dhcp_send_discover();
 221  			dhcp_timeout--;
 222  			break;
 223  
 224  		case DHCP_REQUEST:
 225  			dhcp_send_request();
 226  			dhcp_timeout--;
 227  			break;
 228  
 229  		case DHCP_ACK:
 230  
 231  			if(link_change()){		//stav linky se zmenil
 232  
 233  				if(!link_up()){		//kontrola, zda je linka zapnuta
 234  
 235  					//kabel odpojen, reset DHCP nastaveni
 236  					dhcp_reset();
 237  					arp_table_clear();
 238  					return;
 239  				}
 240  			}
 241  			break;
 242  	}
 243  
 244  return;
 245  }
 246  
 247  /**
 248  
 249   **/
 250  char dhcp_ready(){
 251  
 252  	if(dhcp_state == DHCP_ACK){
 253  		return 1;
 254  	}
 255  
 256  return 0;
 257  }
 258  
 259  
 260  
 261  char dhcp_send_discover(){
 262  
 263  	struct bootp_h bootp_header;
 264  	enc_memset(&bootp_header,0,BOOTP_HEADER_LEN);
 265  
 266  		//vyplneni hlavicky
 267  	bootp_header.opcode = BOOTP_REQUEST;
 268  	bootp_header.hw_type = BOOTP_HW_ETH;
 269  	bootp_header.hw_address_length = MAC_LEN;
 270  	bootp_header.transaction_id = dhcp_transaction_id;
 271  	enc_memcpy(&bootp_header.client_hw_address, &local_mac, MAC_LEN);
 272  
 273  		//inicializace bufferu
 274  	if(tx_init(UDP_PROTO) < 0)
 275  		return -1;
 276  
 277  		//zapsani hlavicky
 278  	tx_write(&bootp_header,BOOTP_HEADER_LEN);
 279  		//vyplneni mista pro host name a boot filename
 280  	tx_fill(0,BOOTP_HEADER_LEN_TOTAL - BOOTP_HEADER_LEN);
 281  		//magic cookie
 282  	tx_write(&magic_cookie,MAGIC_LEN);
 283  
 284  		//DHCP request (zadost)
 285  	tx_putc(DHCP_MESSAGE_TYPE);
 286  	tx_putc(1);
 287  	tx_putc(DHCP_DISCOVER);
 288  
 289  	tx_putc(12);			//typ:hostname
 290  	tx_putc(6);				//delka
 291  	tx_write("FITKit",6);	//hodnota
 292  
 293  
 294  	tx_putc(55);			//typ:parameter request list
 295  	tx_putc(3);				//delka
 296  	tx_putc(1);				//maska
 297  	tx_putc(3);				//router
 298  	tx_putc(6);				//DNS
 299  
 300  	tx_putc(DHCP_END);		//ukonceni DHCP zadosti
 301  
 302  	tx_close();
 303  
 304  		//odeslani DHCP zadosti
 305  	udp_send(DHCP_SERVER_PORT,DHCP_CLIENT_PORT,IP_BROADCAST);
 306  
 307  	dhcp_state = DHCP_DISCOVER;
 308  
 309  return 0;
 310  }
 311  
 312  char dhcp_send_request(){
 313  
 314  		//inicializace tx bufferu
 315  	if(tx_init(UDP_PROTO) < 0)
 316  		return -1;
 317  
 318  		//vytvoreni BOOTP hlavicky
 319  	struct bootp_h bootp_header;
 320  	enc_memset(&bootp_header,0,BOOTP_HEADER_LEN);
 321  
 322  	bootp_header.opcode = BOOTP_REQUEST;
 323  	bootp_header.hw_type = BOOTP_HW_ETH;
 324  	bootp_header.hw_address_length = MAC_LEN;
 325  	bootp_header.transaction_id = dhcp_transaction_id;
 326  	enc_memcpy(&bootp_header.client_hw_address, &local_mac, MAC_LEN);
 327  
 328  		//zapis do tx bufferu
 329  	tx_write(&bootp_header, BOOTP_HEADER_LEN);
 330  	tx_fill(0,BOOTP_HEADER_LEN_TOTAL - BOOTP_HEADER_LEN);
 331  
 332  		//DHCP magic_cookie
 333  	tx_write(&magic_cookie,MAGIC_LEN);
 334  
 335  		//zapsani DHCP parametru
 336  	tx_putc(DHCP_MESSAGE_TYPE);		//typ zpravy
 337  	tx_putc(1);
 338  	tx_putc(DHCP_REQUEST);			//zadost
 339  
 340  	tx_putc(DHCP_REQUESTED_IP);		//zadost o nabizenou IP
 341  	tx_putc(4);
 342  	tx_write(&dhcp_requested_ip, IP_LEN);
 343  
 344  	tx_putc(DHCP_SERVER_ID);		// ID DHCP serveru, ktery ucinil nabidku
 345  	tx_putc(4);
 346  	tx_write(&dhcp_server_id, IP_LEN);
 347  
 348  
 349  	tx_putc(12);			//typ:hostname
 350  	tx_putc(6);				//delka
 351  	tx_write("FITKit",6);	//hodnota
 352  
 353  
 354  	tx_putc(55);			//typ:parameter request list
 355  	tx_putc(3);				//delka
 356  	tx_putc(1);				//maska
 357  	tx_putc(3);				//router
 358  	tx_putc(6);				//DNS
 359  
 360  
 361  	tx_putc(DHCP_END);		//ukonceni DHCP zadosti
 362  	tx_close();
 363  
 364  		//odeslani
 365  	udp_send(DHCP_SERVER_PORT,DHCP_CLIENT_PORT,IP_BROADCAST);
 366  
 367  	dhcp_state = DHCP_REQUEST;
 368  
 369  return 0;
 370  }
 371  
Zobrazeno: 683833x Naposledy: 5.7.2022 04:41:19