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 #ifdef DHCP_DEBUG
00111 rprintf("DHCP: Got request ACK, bind complete\r\n");
00112
00113
00114 rprintfProgStrM("Ip Addr: "); netPrintIPAddr(htonl(packet->bootp.yiaddr));rprintfCRLF();
00115 rprintfProgStrM("Netmask: "); netPrintIPAddr(netmask); rprintfCRLF();
00116 rprintfProgStrM("Gateway: "); netPrintIPAddr(gateway); rprintfCRLF();
00117 rprintfProgStrM("LeaseTm: "); rprintfNum(10,8,FALSE,' ',DhcpLeaseTime); rprintfCRLF();
00118 #endif
00119
00120
00121 ipSetAddress(htonl(packet->bootp.yiaddr), netmask, gateway);
00122 }
00123 }
00124
00125 void dhcpRequest(void)
00126 {
00127 struct netDhcpHeader* packet;
00128 uint32_t val;
00129
00130 packet = (struct netDhcpHeader*)&netstackGetBuffer()[ETH_HEADER_LEN+IP_HEADER_LEN+UDP_HEADER_LEN];
00131
00132
00133 packet->bootp.op = BOOTP_OP_BOOTREQUEST;
00134 packet->bootp.htype = BOOTP_HTYPE_ETHERNET;
00135 packet->bootp.hlen = BOOTP_HLEN_ETHERNET;
00136 packet->bootp.ciaddr = HTONL(0l);
00137 packet->bootp.yiaddr = HTONL(0l);
00138 packet->bootp.siaddr = HTONL(0l);
00139 packet->bootp.giaddr = HTONL(0l);
00140 nicGetMacAddress(&packet->bootp.chaddr[0]);
00141 packet->bootp.xid = DhcpTransactID;
00142 packet->bootp.flags = HTONS(1);
00143
00144
00145
00146 packet->cookie = 0x63538263;
00147
00148 val = DHCP_MSG_DHCPDISCOVER;
00149 dhcpSetOption(packet->options, DHCP_OPT_DHCPMSGTYPE, 1, &val);
00150
00151 #ifdef DHCP_DEBUG
00152 rprintfProgStrM("DHCP: Sending Query\r\n");
00153
00154 #endif
00155
00156
00157 udpSend(0xFFFFFFFF, DHCP_UDP_SERVER_PORT, DHCP_HEADER_LEN+3+1, (uint8_t*)packet);
00158 }
00159
00160 void dhcpRelease(void)
00161 {
00162 struct netDhcpHeader* packet;
00163 uint32_t val;
00164 uint8_t* optptr;
00165
00166 packet = (struct netDhcpHeader*)&netstackGetBuffer()[ETH_HEADER_LEN+IP_HEADER_LEN+UDP_HEADER_LEN];
00167
00168
00169 packet->bootp.op = BOOTP_OP_BOOTREQUEST;
00170 packet->bootp.htype = BOOTP_HTYPE_ETHERNET;
00171 packet->bootp.hlen = BOOTP_HLEN_ETHERNET;
00172 packet->bootp.ciaddr = htonl(ipGetMyAddress());
00173 packet->bootp.yiaddr = HTONL(0l);
00174 packet->bootp.siaddr = HTONL(0l);
00175 packet->bootp.giaddr = HTONL(0l);
00176 nicGetMacAddress(&packet->bootp.chaddr[0]);
00177 packet->bootp.xid = DhcpTransactID;
00178 packet->bootp.flags = HTONS(1);
00179
00180
00181
00182 packet->cookie = 0x63538263;
00183
00184 val = DHCP_MSG_DHCPRELEASE;
00185 optptr = dhcpSetOption(packet->options, DHCP_OPT_DHCPMSGTYPE, 1, &val);
00186
00187 val = htonl(DhcpServerIP);
00188 optptr = dhcpSetOption(optptr, DHCP_OPT_SERVERID, 4, &val);
00189
00190 optptr = dhcpSetOption(optptr, DHCP_OPT_REQUESTEDIP, 4, &packet->bootp.ciaddr);
00191
00192 #ifdef DHCP_DEBUG
00193 rprintfProgStrM("DHCP: Sending Release to "); netPrintIPAddr(DhcpServerIP); rprintfCRLF();
00194
00195 #endif
00196
00197
00198 udpSend(DhcpServerIP, DHCP_UDP_SERVER_PORT, DHCP_HEADER_LEN+3+6+6+1, (uint8_t*)packet);
00199
00200
00201 ipSetAddress(0,0,0);
00202 DhcpLeaseTime = 0;
00203 }
00204
00205 void dhcpTimer(void)
00206 {
00207
00208
00209
00210 if(DhcpLeaseTime)
00211 DhcpLeaseTime--;
00212 }
00213
00214 uint8_t dhcpGetOption(uint8_t* options, uint8_t optcode, uint8_t optlen, void* optvalptr)
00215 {
00216 uint8_t i;
00217
00218
00219 for (;;)
00220 {
00221
00222 if(*options == DHCP_OPT_PAD)
00223 options++;
00224
00225 else if(*options == DHCP_OPT_END)
00226 break;
00227
00228 else if(*options == optcode)
00229 {
00230
00231
00232 optlen = MIN(optlen, *(options+1));
00233
00234
00235
00236
00237 for(i=0; i<optlen; i++)
00238 *(((uint8_t*)optvalptr)+i) = *(options+i+2);
00239
00240 return *(options+1);
00241 }
00242 else
00243 {
00244
00245 options++;
00246 options+=*options;
00247 options++;
00248 }
00249 }
00250
00251 return 0;
00252 }
00253
00254
00255 uint8_t* dhcpSetOption(uint8_t* options, uint8_t optcode, uint8_t optlen, void* optvalptr)
00256 {
00257
00258
00259
00260 *options++ = optcode;
00261
00262 *options++ = optlen;
00263
00264 while(optlen--)
00265 *options++ = *((uint8_t*)optvalptr)++;
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