00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "global.h"
00016 #include "net.h"
00017 #include "nic.h"
00018 #include "ip.h"
00019 #include "netstack.h"
00020
00021 #include "dhcp.h"
00022
00023 #include "rprintf.h"
00024
00025
00026 uint32_t DhcpServerIP;
00027 uint32_t DhcpTransactID;
00028 uint32_t DhcpLeaseTime;
00029
00030 void dhcpInit(void)
00031 {
00032 uint8_t macaddr[6];
00033
00034
00035 nicGetMacAddress(macaddr);
00036
00037 DhcpTransactID = *((uint32_t*)&macaddr);
00038
00039 DhcpLeaseTime = 0;
00040 }
00041
00042 void dhcpIn(unsigned int len, struct netDhcpHeader* packet)
00043 {
00044 uint8_t msgtype;
00045 uint32_t sid;
00046 uint8_t* optptr;
00047 uint32_t val;
00048 uint32_t netmask;
00049 uint32_t gateway;
00050
00051 #if NET_DEBUG >= 3
00052 dhcpPrintHeader(packet);
00053 #endif
00054
00055
00056 if((packet->bootp.op != BOOTP_OP_BOOTREPLY) || (packet->bootp.xid != DhcpTransactID))
00057 return;
00058
00059
00060
00061 dhcpGetOption(packet->options, DHCP_OPT_DHCPMSGTYPE, 1, &msgtype);
00062 #if NET_DEBUG >= 2
00063 rprintf("DHCP: Received msgtype = %d\r\n", msgtype);
00064 #endif
00065
00066 if(msgtype == DHCP_MSG_DHCPOFFER)
00067 {
00068
00069 dhcpGetOption(packet->options, DHCP_OPT_SERVERID, 4, &sid);
00070 #ifdef DHCP_DEBUG
00071 rprintfProgStrM("DHCP: Got offer from server "); netPrintIPAddr(htonl(sid)); rprintfCRLF();
00072 #endif
00073
00074
00075 packet->bootp.op = BOOTP_OP_BOOTREQUEST;
00076
00077 val = DHCP_MSG_DHCPREQUEST;
00078 optptr = dhcpSetOption(packet->options, DHCP_OPT_DHCPMSGTYPE, 1, &val);
00079
00080 optptr = dhcpSetOption(optptr, DHCP_OPT_SERVERID, 4, &sid);
00081
00082 optptr = dhcpSetOption(optptr, DHCP_OPT_REQUESTEDIP, 4, &packet->bootp.yiaddr);
00083
00084 ((uint8_t*)&val)[0] = DHCP_OPT_NETMASK;
00085 ((uint8_t*)&val)[1] = DHCP_OPT_ROUTERS;
00086 ((uint8_t*)&val)[2] = DHCP_OPT_DNSSERVERS;
00087 ((uint8_t*)&val)[3] = DHCP_OPT_DOMAINNAME;
00088 optptr = dhcpSetOption(optptr, DHCP_OPT_PARAMREQLIST, 4, &val);
00089
00090 #ifdef DHCP_DEBUG
00091 rprintfProgStrM("DHCP: Sending request in response to offer\r\n");
00092 #endif
00093
00094 DhcpServerIP = htonl(sid);
00095 udpSend(DhcpServerIP, DHCP_UDP_SERVER_PORT, DHCP_HEADER_LEN+3+6+6+6+1, (uint8_t*)packet);
00096
00097 }
00098 else if(msgtype == DHCP_MSG_DHCPACK)
00099 {
00100
00101 dhcpGetOption(packet->options, DHCP_OPT_NETMASK, 4, &val);
00102 netmask = htonl(val);
00103
00104 dhcpGetOption(packet->options, DHCP_OPT_ROUTERS, 4, &val);
00105 gateway = htonl(val);
00106
00107 dhcpGetOption(packet->options, DHCP_OPT_LEASETIME, 4, &val);
00108 DhcpLeaseTime = htonl(val);
00109
00110
00111 ipSetConfig(htonl(packet->bootp.yiaddr), netmask, gateway);
00112
00113 #ifdef DHCP_DEBUG
00114 rprintf("DHCP: Got request ACK, bind complete\r\n");
00115
00116
00117 ipPrintConfig(ipGetConfig());
00118 rprintfProgStrM("LeaseTm : "); rprintfNum(10,8,FALSE,' ',DhcpLeaseTime); rprintfCRLF();
00119 #endif
00120 }
00121 }
00122
00123 void dhcpRequest(void)
00124 {
00125 struct netDhcpHeader* packet;
00126 uint32_t val;
00127
00128 packet = (struct netDhcpHeader*)&netstackGetBuffer()[ETH_HEADER_LEN+IP_HEADER_LEN+UDP_HEADER_LEN];
00129
00130
00131 packet->bootp.op = BOOTP_OP_BOOTREQUEST;
00132 packet->bootp.htype = BOOTP_HTYPE_ETHERNET;
00133 packet->bootp.hlen = BOOTP_HLEN_ETHERNET;
00134 packet->bootp.ciaddr = htonl(ipGetConfig()->ip);
00135 packet->bootp.yiaddr = HTONL(0l);
00136 packet->bootp.siaddr = HTONL(0l);
00137 packet->bootp.giaddr = HTONL(0l);
00138 nicGetMacAddress(&packet->bootp.chaddr[0]);
00139 packet->bootp.xid = DhcpTransactID;
00140 packet->bootp.flags = HTONS(1);
00141
00142
00143
00144 packet->cookie = 0x63538263;
00145
00146 val = DHCP_MSG_DHCPDISCOVER;
00147 dhcpSetOption(packet->options, DHCP_OPT_DHCPMSGTYPE, 1, &val);
00148
00149 #ifdef DHCP_DEBUG
00150 rprintfProgStrM("DHCP: Sending Query\r\n");
00151
00152 #endif
00153
00154
00155 udpSend(0xFFFFFFFF, DHCP_UDP_SERVER_PORT, DHCP_HEADER_LEN+3+1, (uint8_t*)packet);
00156 }
00157
00158 void dhcpRelease(void)
00159 {
00160 struct netDhcpHeader* packet;
00161 uint32_t val;
00162 uint8_t* optptr;
00163
00164 packet = (struct netDhcpHeader*)&netstackGetBuffer()[ETH_HEADER_LEN+IP_HEADER_LEN+UDP_HEADER_LEN];
00165
00166
00167 packet->bootp.op = BOOTP_OP_BOOTREQUEST;
00168 packet->bootp.htype = BOOTP_HTYPE_ETHERNET;
00169 packet->bootp.hlen = BOOTP_HLEN_ETHERNET;
00170 packet->bootp.ciaddr = htonl(ipGetConfig()->ip);
00171 packet->bootp.yiaddr = HTONL(0l);
00172 packet->bootp.siaddr = HTONL(0l);
00173 packet->bootp.giaddr = HTONL(0l);
00174 nicGetMacAddress(&packet->bootp.chaddr[0]);
00175 packet->bootp.xid = DhcpTransactID;
00176 packet->bootp.flags = HTONS(1);
00177
00178
00179
00180 packet->cookie = 0x63538263;
00181
00182 val = DHCP_MSG_DHCPRELEASE;
00183 optptr = dhcpSetOption(packet->options, DHCP_OPT_DHCPMSGTYPE, 1, &val);
00184
00185 val = htonl(DhcpServerIP);
00186 optptr = dhcpSetOption(optptr, DHCP_OPT_SERVERID, 4, &val);
00187
00188 optptr = dhcpSetOption(optptr, DHCP_OPT_REQUESTEDIP, 4, &packet->bootp.ciaddr);
00189
00190 #ifdef DHCP_DEBUG
00191 rprintfProgStrM("DHCP: Sending Release to "); netPrintIPAddr(DhcpServerIP); rprintfCRLF();
00192
00193 #endif
00194
00195
00196 udpSend(DhcpServerIP, DHCP_UDP_SERVER_PORT, DHCP_HEADER_LEN+3+6+6+1, (uint8_t*)packet);
00197
00198
00199 ipSetConfig(0,0,0);
00200 DhcpLeaseTime = 0;
00201 }
00202
00203 void dhcpTimer(void)
00204 {
00205
00206
00207
00208 if(DhcpLeaseTime)
00209 DhcpLeaseTime--;
00210 }
00211
00212 uint8_t dhcpGetOption(uint8_t* options, uint8_t optcode, uint8_t optlen, void* optvalptr)
00213 {
00214 uint8_t i;
00215
00216
00217 for (;;)
00218 {
00219
00220 if(*options == DHCP_OPT_PAD)
00221 options++;
00222
00223 else if(*options == DHCP_OPT_END)
00224 break;
00225
00226 else if(*options == optcode)
00227 {
00228
00229
00230 optlen = MIN(optlen, *(options+1));
00231
00232
00233
00234
00235 for(i=0; i<optlen; i++)
00236 *(((uint8_t*)optvalptr)+i) = *(options+i+2);
00237
00238 return *(options+1);
00239 }
00240 else
00241 {
00242
00243 options++;
00244 options+=*options;
00245 options++;
00246 }
00247 }
00248
00249 return 0;
00250 }
00251
00252
00253 uint8_t* dhcpSetOption(uint8_t* options, uint8_t optcode, uint8_t optlen, void* optvalptr)
00254 {
00255
00256
00257
00258 *options++ = optcode;
00259
00260 *options++ = optlen;
00261
00262 while(optlen--)
00263 {
00264 *options++ = *(uint8_t*)optvalptr++;
00265 }
00266
00267 *options = DHCP_OPT_END;
00268
00269
00270 return options;
00271 }
00272
00273
00274 #ifdef DHCP_DEBUG_PRINT
00275 void dhcpPrintHeader(struct netDhcpHeader* packet)
00276 {
00277 rprintfProgStrM("DHCP Packet:\r\n");
00278
00279 rprintfProgStrM("Op : ");
00280 switch(packet->bootp.op)
00281 {
00282 case BOOTP_OP_BOOTREQUEST: rprintfProgStrM("BOOTREQUEST"); break;
00283 case BOOTP_OP_BOOTREPLY: rprintfProgStrM("BOOTREPLY"); break;
00284 default: rprintfProgStrM("UNKNOWN"); break;
00285 }
00286 rprintfCRLF();
00287
00288 rprintfProgStrM("XID : 0x"); rprintfu32(packet->bootp.xid); rprintfCRLF();
00289
00290 rprintfProgStrM("ClIpAddr: "); netPrintIPAddr(htonl(packet->bootp.ciaddr)); rprintfCRLF();
00291
00292 rprintfProgStrM("YrIpAddr: "); netPrintIPAddr(htonl(packet->bootp.yiaddr)); rprintfCRLF();
00293
00294 rprintfProgStrM("SvIpAddr: "); netPrintIPAddr(htonl(packet->bootp.siaddr)); rprintfCRLF();
00295
00296 rprintfProgStrM("GwIpAddr: "); netPrintIPAddr(htonl(packet->bootp.giaddr)); rprintfCRLF();
00297
00298 rprintfProgStrM("ClHwAddr: "); netPrintEthAddr((struct netEthAddr*)packet->bootp.chaddr); rprintfCRLF();
00299 }
00300 #endif