00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "nip_init.h"
00032 #include "dispatcher.h"
00033 #include "inet.h"
00034 #include "os_core.h"
00035 #include "nip_error.h"
00036 #include "net/net_if.h"
00037 #include "net/udp.h"
00038 #include "app/dhcp.h"
00039 #include "app/ports.h"
00040
00041
00042 #if (NIP_DHCP_ENABLE==1)
00043
00044 #define DHCPMSGSIZE sizeof( struct nip_dhcp_packet )
00045
00046
00047
00048 #if NIP_NET_IF_COUNT > 1
00049 struct nip_dhcp_config nip_dhcp_conf[ NIP_NET_IF_COUNT ];
00050 #define NIP_DHCP_CONF( if_id ) nip_dhcp_conf[if_id]
00051 #else
00052 struct nip_dhcp_config nip_dhcp_conf;
00053 #define NIP_DHCP_CONF( if_id ) nip_dhcp_conf
00054 #endif
00055 nip_udp_sock_id_t nip_dhcp_sock = NIP_UDP_NO_SOCKET;
00056
00057
00058
00059 void nip_dhcp_start( nip_net_if_id_t net_if )
00060 {
00061 NIP_DHCP_CONF( net_if ).state = NIP_DHCP_STAT_INIT;
00062
00063 nip_disp_notify_if( net_if, NIP_DISP_IF_DHCP );
00064 }
00065
00066
00067 void nip_dhcp_disable( nip_net_if_id_t net_if )
00068 {
00069 NIP_DHCP_CONF( net_if ).state = NIP_DHCP_STAT_DISABLED;
00070 }
00071
00072
00073
00074
00075
00076
00077
00078 void nip_dhcp_disp_sock_init( void )
00079 {
00080 struct nip_udp_sock_addr addr;
00081
00082
00083 addr.port = NIP_UDP_PORT_DHCPCLIENT;
00084 addr.ip[0] = 0;
00085 addr.ip[1] = 0;
00086 addr.ip[2] = 0;
00087 addr.ip[3] = 0;
00088
00089 nip_dhcp_sock = nip_udp_socket(
00090 &addr,
00091 NIP_UDP_SOCK_FLG_LISTENING | NIP_UDP_SOCK_FLG_NON_BLOCK
00092 );
00093
00094
00095
00096
00097
00098
00099 }
00100
00101
00102 struct nip_dhcp_option *nip_dhcp_find_option( uint8_t opttype, struct nip_dhcp_packet *msg, nip_mem_size_t msg_size )
00103 {
00104 uint8_t i = 0;
00105
00106
00107 while ( msg->options[i] != DHCP_OPTION_END )
00108 {
00109
00110 if ( &msg->options[i+msg->options[i+1]+2] > &((uint8_t*)msg)[msg_size] )
00111 break;
00112
00113
00114 if ( msg->options[i] == DHCP_OPTION_PADDING )
00115 {
00116 i++;
00117 continue;
00118 }
00119
00120
00121 if (msg->options[i]==opttype){
00122
00123 return (struct nip_dhcp_option*) &msg->options[i];
00124 } else{
00125
00126 i+=msg->options[i+1]+2;
00127 }
00128 }
00129
00130 return NULL;
00131 }
00132
00133
00134
00135 void nip_dhcp_disp_check( void )
00136 {
00137 nip_net_if_id_t if_id = NIP_CURR_IF;
00138 nip_net_if_t *net_if = & nip_net_if_list[ if_id ];
00139
00140
00141
00142 #if NIP_NET_IF_COUNT > 1
00143 struct nip_dhcp_config *conf = & NIP_DHCP_CONF( if_id );
00144 #define CONF_ATTR(attr) conf-> attr
00145 #else
00146 #define CONF_ATTR(attr) nip_dhcp_conf.attr
00147 #endif
00148
00149 struct nip_dhcp_packet *msg;
00150 struct nip_dhcp_option *opt;
00151 nip_mem_size_t msg_size;
00152 uint8_t i;
00153 uint8_t optcode;
00154 void *addr;
00155 nip_time_t tc = nip_tickcount();
00156
00157
00158
00159 while ( 0 < (msg_size = nip_udp_recvfrom( nip_dhcp_sock, NULL, 0, &CONF_ATTR(serv_addr) )) )
00160 {
00161
00162
00163 msg = nip_udp_data_ptr( nip_dhcp_sock, NIP_UDP_RX_BUF );
00164
00165 if ( msg != NULL )
00166 {
00167 opt = nip_dhcp_find_option( DHCP_OPTION_MSGTYPE, msg, msg_size );
00168
00169
00170 if ( msg->xid == CONF_ATTR(xid)
00171 && msg->op == NIP_DHCP_OP_REPLY
00172 && opt != NULL )
00173 {
00174 switch ( opt->value.msgtype )
00175 {
00176 case DHCP_OPTION_MSGTYPE_OFFER:
00177 if ( CONF_ATTR(state) == NIP_DHCP_STAT_SELECTING )
00178 {
00179
00180 opt->value.msgtype = DHCP_OPTION_MSGTYPE_REQUEST;
00181 nip_memcpy( msg->ciaddr, msg->yiaddr, 4 );
00182 nip_memset( msg->yiaddr, 0, 4 );
00183
00184
00185
00186
00187 nip_udp_forward( nip_dhcp_sock );
00188
00189 CONF_ATTR(state) = NIP_DHCP_STAT_REQUESTING;
00190 goto transmit;
00191 }
00192 break;
00193 case DHCP_OPTION_MSGTYPE_ACK:
00194
00195
00196 if ( CONF_ATTR(state) == NIP_DHCP_STAT_REQUESTING
00197 || CONF_ATTR(state) == NIP_DHCP_STAT_REBINDING
00198 || CONF_ATTR(state) == NIP_DHCP_STAT_RENEWING )
00199 {
00200
00201
00202 nip_ip_addr_set( if_id, msg->yiaddr );
00203
00204 opt = nip_dhcp_find_option( DHCP_OPTION_SUBNETMASK, msg, msg_size );
00205 if ( opt != NULL && opt->valsize == 4 )
00206 nip_ip_subnet_set( if_id, opt->value.ipaddr );
00207
00208
00209 i = 1;
00210 do
00211 {
00212
00213 addr = net_if->ip_conf.std_gateway;
00214 optcode = DHCP_OPTION_ROUTER;
00215
00216 if ( i==2 )
00217 {
00218 #if NIP_DNS_ENABLE == 1
00219 addr = net_if->ip_conf.name_server;
00220 optcode = DHCP_OPTION_DNS;
00221 #else
00222 i++;
00223 #endif
00224 }
00225 if ( i==3 )
00226 {
00227 addr = &CONF_ATTR(leasetime);
00228 optcode = DHCP_OPTION_LEASETIME;
00229 }
00230 if ( i==4 )
00231 {
00232 addr = &CONF_ATTR(t1);
00233 optcode = DHCP_OPTION_RENEWAL_TIME;
00234 }
00235 if ( i==5 )
00236 {
00237 addr = &CONF_ATTR(t2);
00238 optcode = DHCP_OPTION_REBINDING_TIME;
00239 }
00240 opt = nip_dhcp_find_option( optcode, msg, msg_size );
00241 if ( opt != NULL && opt->valsize >= 4 )
00242 {
00243 if ( i<3 )
00244 nip_memcpy( addr, opt->value.ipaddr, 4 );
00245 else
00246 *(nip_time_t*)addr = tc + ntohl( opt->value.time );
00247 } else
00248 {
00249 nip_memset( addr, 0, 4 );
00250 }
00251 }
00252 while ( ++i < 6 );
00253
00254 CONF_ATTR(state) = NIP_DHCP_STAT_BOUND;
00255
00256 }
00257 break;
00258
00259 case DHCP_OPTION_MSGTYPE_NAK:
00260
00261 CONF_ATTR(state) = NIP_DHCP_STAT_INIT;
00262 break;
00263 }
00264 }
00265
00266 nip_udp_ptr_release( nip_dhcp_sock, NIP_UDP_RX_BUF );
00267 }
00268
00269
00270 nip_udp_cancel_recv( nip_dhcp_sock );
00271
00272
00273 if ( CONF_ATTR(state) == NIP_DHCP_STAT_BOUND )
00274 {
00275 nip_udp_close( nip_dhcp_sock );
00276 nip_dhcp_sock = NIP_UDP_NO_SOCKET;
00277 }
00278
00279 }
00280
00281
00282
00283
00284 switch ( CONF_ATTR(state) )
00285 {
00286 case NIP_DHCP_STAT_BOUND:
00287
00288
00289 if ( CONF_ATTR(t1) < tc )
00290 {
00291 CONF_ATTR(state) = NIP_DHCP_STAT_RENEWING;
00292
00293 goto prepare;
00294 }
00295 goto quit;
00296
00297 case NIP_DHCP_STAT_RENEWING:
00298
00299
00300 if ( CONF_ATTR(t2) < tc )
00301 {
00302 CONF_ATTR(state) = NIP_DHCP_STAT_REBINDING;
00303
00304 goto prepare;
00305 }
00306 break;
00307
00308 case NIP_DHCP_STAT_REBINDING:
00309
00310 if ( CONF_ATTR(leasetime) < tc )
00311 {
00312
00313
00314
00315 nip_ip_addr_autoconf( if_id );
00316 goto prepare;
00317 }
00318 break;
00319
00320 case NIP_DHCP_STAT_REQUESTING:
00321 case NIP_DHCP_STAT_SELECTING:
00322 break;
00323
00324 case NIP_DHCP_STAT_INIT:
00325 goto prepare;
00326
00327 default:
00328
00329 goto quit;
00330 break;
00331 }
00332
00333
00334
00335 goto retrans;
00336
00337
00338
00339
00340
00341 prepare:
00342
00343
00344 CONF_ATTR(backoff_delay) = NIP_DHCP_INIT_BACKOFF;
00345 CONF_ATTR(ts) = 0;
00346
00347 retrans:
00348
00349 if ( tc < CONF_ATTR(ts) )
00350 {
00351 return;
00352 }
00353
00354
00355 if ( nip_dhcp_sock == NIP_UDP_NO_SOCKET )
00356 {
00357 NIP_CURR_CMD = &nip_dhcp_disp_sock_init;
00358 goto quit;
00359 }
00360
00361
00362 if ( NIP_E_OK != nip_udp_init_send( nip_dhcp_sock, DHCPMSGSIZE ) )
00363 goto quit;
00364
00365
00366 if ( NIP_E_OK != nip_udp_write( nip_dhcp_sock, NULL, DHCPMSGSIZE ) )
00367 {
00368 nip_udp_cancel_send( nip_dhcp_sock );
00369 goto quit;
00370 }
00371
00372
00373
00374
00375
00376 if ( CONF_ATTR(state) == NIP_DHCP_STAT_REQUESTING
00377 || CONF_ATTR(state) == NIP_DHCP_STAT_SELECTING )
00378 CONF_ATTR(state) = NIP_DHCP_STAT_INIT;
00379
00380 if ( CONF_ATTR(state) == NIP_DHCP_STAT_INIT
00381 || CONF_ATTR(state) == NIP_DHCP_STAT_REBINDING )
00382 {
00383
00384 nip_memset( CONF_ATTR(serv_addr).ip, 255, 4 );
00385 CONF_ATTR(serv_addr).port = NIP_UDP_PORT_DHCPSERVER;
00386 }
00387
00388 if ( CONF_ATTR(state) == NIP_DHCP_STAT_RENEWING
00389 || CONF_ATTR(state) == NIP_DHCP_STAT_REBINDING )
00390 {
00391 optcode = DHCP_OPTION_MSGTYPE_REQUEST;
00392 }
00393 else
00394
00395 {
00396 CONF_ATTR(state) = NIP_DHCP_STAT_SELECTING;
00397 optcode = DHCP_OPTION_MSGTYPE_DISCOVER;
00398
00399
00400
00401
00402
00403 }
00404
00405
00406
00407 CONF_ATTR(xid) = net_if->phy_conf.hw_addr[net_if->phy_conf.hw_addr_size-1] + (tc<<8);
00408
00409
00410 msg = nip_udp_data_ptr( nip_dhcp_sock, NIP_UDP_TX_BUF );
00411
00412
00413 nip_memset( msg, 0, DHCPMSGSIZE );
00414
00415 msg->htype = net_if->phy_conf.type;
00416 msg->hlen = net_if->phy_conf.hw_addr_size;
00417 msg->xid = CONF_ATTR(xid);
00418
00419
00420 nip_memcpy(
00421 msg->ciaddr,
00422 net_if->ip_conf.addr,
00423 4
00424 );
00425 msg->magic_cookie = NIP_DHCP_MAGIC_COOKIE;
00426
00427
00428 msg->options[0] = DHCP_OPTION_MSGTYPE;
00429 msg->options[1] = 1;
00430 msg->options[2] = optcode;
00431 msg->options[3] = DHCP_OPTION_END;
00432
00433
00434
00435 transmit:
00436
00437
00438
00439 msg->op = NIP_DHCP_OP_REQUEST;
00440
00441
00442 nip_memcpy(
00443 msg->chaddr,
00444 net_if->phy_conf.hw_addr,
00445 net_if->phy_conf.hw_addr_size
00446 );
00447
00448
00449
00450 msg->flags[0]=0xF0;
00451
00452
00453 nip_udp_ptr_release( nip_dhcp_sock, NIP_UDP_TX_BUF );
00454
00455
00456 nip_udp_transmit( nip_dhcp_sock, &CONF_ATTR(serv_addr), if_id );
00457
00458
00459 CONF_ATTR(ts) = tc + CONF_ATTR(backoff_delay);
00460 CONF_ATTR(backoff_delay) <<= 1;
00461 if ( CONF_ATTR(backoff_delay) > NIP_DHCP_MAX_BACKOFF )
00462 CONF_ATTR(backoff_delay) = NIP_DHCP_MAX_BACKOFF;
00463
00464 quit:
00465 return;
00466
00467 }
00468
00469
00470
00471
00472
00473
00474 #endif // (NIP_DHCP_ENABLE==1)