uIP 1.0
|
00001 /* 00002 * Copyright (c) 2005, Swedish Institute of Computer Science 00003 * Все права зарезервированы. * 00004 * Повторное распространение, использование в исходном и двоичном виде, 00005 * с модификацией или без - разрешается, если выполняются следующие 00006 * условия: 00007 * 1. Распространение исходного кода должно сохранить вышеуказанную пометку 00008 * копирайта, этот список условий и следующую правовую оговорку. 00009 * 2. Распространение исходного кода должно сохранить вышеуказанную пометку 00010 * копирайта, этот список условий и следующую правовую оговорку в 00011 * документации и/или других материалах, которые будут предоставлены 00012 * вместе с распространяемыми материалами. 00013 * 3. Имя автора не может использоваться, чтобы подтвердить или продвинуть 00014 * продукты, написанные с использованием этого программного обеспечения 00015 * без специального на то разрешения. 00016 * 00017 * ЭТО ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ ПРЕДОСТАВЛЯЕТСЯ АВТОРОМ ``КАК ЕСТЬ'', БЕЗ 00018 * КАКОЙ-ЛИБО ЛЮБОЙ РАСШИРЕННОЙ ИЛИ ПОДРАЗУМЕВАЕМОЙ ГАРАНТИИ, ВКЛЮЧАЯ, 00019 * НО НЕ ОГРАНИЧИВАЯСЬ ЭТИМ, ГАРАНТИИ ВЫСОКОГО СПРОСА И ПРИГОДНОСТИ 00020 * ДЛЯ КОНКРЕТНОЙ ЦЕЛИ. АВТОР НИ ПРИ КАКИХ УСЛОВИЯХ НЕ ОТВЕТСТВЕНЕН 00021 * ЗА ЛЮБЫЕ УБЫТКИ - ПРЯМЫЕ, КОСВЕННЫЕ, СЛУЧАЙНЫЕ, СПЕЦИАЛЬНЫЕ, ОБРАЗЦОВЫЕ 00022 * ИЛИ ПОСЛЕДОВАТЕЛЬНЫЕ (ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ ЭТИМ, ТРЕБОВАНИЯ 00023 * ЗАМЕНЫ ТОВАРА ИЛИ СЕРВИСА; ПОТЕРИ ИСПОЛЬЗОВАНИЯ, ДАННЫХ ИЛИ ВЫГОДЫ; 00024 * ИЛИ ПРЕКРАЩЕНИЕ БИЗНЕСА), ОДНАКО ВЫЗВАННЫЕ ПО ЛЮБОЙ ТЕОРИИ ОТВЕТСТВЕННОСТИ, 00025 * ЛИБО В КОНТРАКТЕ, ПРЯМОЙ ОТВЕТСТВЕННОСТИ, ЛИБО В НАРУШЕНИИ ЗАКОННЫХ ПРАВ 00026 * (ВКЛЮЧАЯ ТАК ИЛИ ИНАЧЕ НЕБРЕЖНОСТЬ), ВОЗНИКАЮЩИЕ ВСЕГДА ИЗ ИСПОЛЬЗОВАНИЯ 00027 * ЭТОГО ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ, ДАЖЕ ЕСЛИ БЫЛО ПРЕДУПРЕЖДЕНИЕ О ВОЗМОЖНОСТИ 00028 * ТАКОГО ПОВРЕЖДЕНИЯ. 00029 * 00030 * Этот файл является частью стека uIP TCP/IP. 00031 * 00032 * @(#)$Id: dhcpc.c,v 1.2 2006/06/11 21:46:37 adam Exp $ 00033 */ 00034 00035 #include <stdio.h> 00036 #include <string.h> 00037 00038 #include "uip.h" 00039 #include "dhcpc.h" 00040 #include "timer.h" 00041 #include "pt.h" 00042 00043 #define STATE_INITIAL 0 00044 #define STATE_SENDING 1 00045 #define STATE_OFFER_RECEIVED 2 00046 #define STATE_CONFIG_RECEIVED 3 00047 00048 static struct dhcpc_state s; 00049 00050 struct dhcp_msg { 00051 u8_t op, htype, hlen, hops; 00052 u8_t xid[4]; 00053 u16_t secs, flags; 00054 u8_t ciaddr[4]; 00055 u8_t yiaddr[4]; 00056 u8_t siaddr[4]; 00057 u8_t giaddr[4]; 00058 u8_t chaddr[16]; 00059 #ifndef UIP_CONF_DHCP_LIGHT 00060 u8_t sname[64]; 00061 u8_t file[128]; 00062 #endif 00063 u8_t options[312]; 00064 }; 00065 00066 #define BOOTP_BROADCAST 0x8000 00067 00068 #define DHCP_REQUEST 1 00069 #define DHCP_REPLY 2 00070 #define DHCP_HTYPE_ETHERNET 1 00071 #define DHCP_HLEN_ETHERNET 6 00072 #define DHCP_MSG_LEN 236 00073 00074 #define DHCPC_SERVER_PORT 67 00075 #define DHCPC_CLIENT_PORT 68 00076 00077 #define DHCPDISCOVER 1 00078 #define DHCPOFFER 2 00079 #define DHCPREQUEST 3 00080 #define DHCPDECLINE 4 00081 #define DHCPACK 5 00082 #define DHCPNAK 6 00083 #define DHCPRELEASE 7 00084 00085 #define DHCP_OPTION_SUBNET_MASK 1 00086 #define DHCP_OPTION_ROUTER 3 00087 #define DHCP_OPTION_DNS_SERVER 6 00088 #define DHCP_OPTION_REQ_IPADDR 50 00089 #define DHCP_OPTION_LEASE_TIME 51 00090 #define DHCP_OPTION_MSG_TYPE 53 00091 #define DHCP_OPTION_SERVER_ID 54 00092 #define DHCP_OPTION_REQ_LIST 55 00093 #define DHCP_OPTION_END 255 00094 00095 static const u8_t xid[4] = {0xad, 0xde, 0x12, 0x23}; 00096 static const u8_t magic_cookie[4] = {99, 130, 83, 99}; 00097 /*---------------------------------------------------------------------------*/ 00098 static u8_t * 00099 add_msg_type(u8_t *optptr, u8_t type) 00100 { 00101 *optptr++ = DHCP_OPTION_MSG_TYPE; 00102 *optptr++ = 1; 00103 *optptr++ = type; 00104 return optptr; 00105 } 00106 /*---------------------------------------------------------------------------*/ 00107 static u8_t * 00108 add_server_id(u8_t *optptr) 00109 { 00110 *optptr++ = DHCP_OPTION_SERVER_ID; 00111 *optptr++ = 4; 00112 memcpy(optptr, s.serverid, 4); 00113 return optptr + 4; 00114 } 00115 /*---------------------------------------------------------------------------*/ 00116 static u8_t * 00117 add_req_ipaddr(u8_t *optptr) 00118 { 00119 *optptr++ = DHCP_OPTION_REQ_IPADDR; 00120 *optptr++ = 4; 00121 memcpy(optptr, s.ipaddr, 4); 00122 return optptr + 4; 00123 } 00124 /*---------------------------------------------------------------------------*/ 00125 static u8_t * 00126 add_req_options(u8_t *optptr) 00127 { 00128 *optptr++ = DHCP_OPTION_REQ_LIST; 00129 *optptr++ = 3; 00130 *optptr++ = DHCP_OPTION_SUBNET_MASK; 00131 *optptr++ = DHCP_OPTION_ROUTER; 00132 *optptr++ = DHCP_OPTION_DNS_SERVER; 00133 return optptr; 00134 } 00135 /*---------------------------------------------------------------------------*/ 00136 static u8_t * 00137 add_end(u8_t *optptr) 00138 { 00139 *optptr++ = DHCP_OPTION_END; 00140 return optptr; 00141 } 00142 /*---------------------------------------------------------------------------*/ 00143 static void 00144 create_msg(register struct dhcp_msg *m) 00145 { 00146 m->op = DHCP_REQUEST; 00147 m->htype = DHCP_HTYPE_ETHERNET; 00148 m->hlen = s.mac_len; 00149 m->hops = 0; 00150 memcpy(m->xid, xid, sizeof(m->xid)); 00151 m->secs = 0; 00152 m->flags = HTONS(BOOTP_BROADCAST); /* Бит широковещания. */ 00153 /* uip_ipaddr_copy(m->ciaddr, uip_hostaddr);*/ 00154 memcpy(m->ciaddr, uip_hostaddr, sizeof(m->ciaddr)); 00155 memset(m->yiaddr, 0, sizeof(m->yiaddr)); 00156 memset(m->siaddr, 0, sizeof(m->siaddr)); 00157 memset(m->giaddr, 0, sizeof(m->giaddr)); 00158 memcpy(m->chaddr, s.mac_addr, s.mac_len); 00159 memset(&m->chaddr[s.mac_len], 0, sizeof(m->chaddr) - s.mac_len); 00160 #ifndef UIP_CONF_DHCP_LIGHT 00161 memset(m->sname, 0, sizeof(m->sname)); 00162 memset(m->file, 0, sizeof(m->file)); 00163 #endif 00164 00165 memcpy(m->options, magic_cookie, sizeof(magic_cookie)); 00166 } 00167 /*---------------------------------------------------------------------------*/ 00168 static void 00169 send_discover(void) 00170 { 00171 u8_t *end; 00172 struct dhcp_msg *m = (struct dhcp_msg *)uip_appdata; 00173 00174 create_msg(m); 00175 00176 end = add_msg_type(&m->options[4], DHCPDISCOVER); 00177 end = add_req_options(end); 00178 end = add_end(end); 00179 00180 uip_send(uip_appdata, end - (u8_t *)uip_appdata); 00181 } 00182 /*---------------------------------------------------------------------------*/ 00183 static void 00184 send_request(void) 00185 { 00186 u8_t *end; 00187 struct dhcp_msg *m = (struct dhcp_msg *)uip_appdata; 00188 00189 create_msg(m); 00190 00191 end = add_msg_type(&m->options[4], DHCPREQUEST); 00192 end = add_server_id(end); 00193 end = add_req_ipaddr(end); 00194 end = add_end(end); 00195 00196 uip_send(uip_appdata, end - (u8_t *)uip_appdata); 00197 } 00198 /*---------------------------------------------------------------------------*/ 00199 static u8_t 00200 parse_options(u8_t *optptr, int len) 00201 { 00202 u8_t *end = optptr + len; 00203 u8_t type = 0; 00204 00205 while(optptr < end) { 00206 switch(*optptr) { 00207 case DHCP_OPTION_SUBNET_MASK: 00208 memcpy(s.netmask, optptr + 2, 4); 00209 break; 00210 case DHCP_OPTION_ROUTER: 00211 memcpy(s.default_router, optptr + 2, 4); 00212 break; 00213 case DHCP_OPTION_DNS_SERVER: 00214 memcpy(s.dnsaddr, optptr + 2, 4); 00215 break; 00216 case DHCP_OPTION_MSG_TYPE: 00217 type = *(optptr + 2); 00218 break; 00219 case DHCP_OPTION_SERVER_ID: 00220 memcpy(s.serverid, optptr + 2, 4); 00221 break; 00222 case DHCP_OPTION_LEASE_TIME: 00223 memcpy(s.lease_time, optptr + 2, 4); 00224 break; 00225 case DHCP_OPTION_END: 00226 return type; 00227 } 00228 00229 optptr += optptr[1] + 2; 00230 } 00231 return type; 00232 } 00233 /*---------------------------------------------------------------------------*/ 00234 static u8_t 00235 parse_msg(void) 00236 { 00237 struct dhcp_msg *m = (struct dhcp_msg *)uip_appdata; 00238 00239 if(m->op == DHCP_REPLY && 00240 memcmp(m->xid, xid, sizeof(xid)) == 0 && 00241 memcmp(m->chaddr, s.mac_addr, s.mac_len) == 0) { 00242 memcpy(s.ipaddr, m->yiaddr, 4); 00243 return parse_options(&m->options[4], uip_datalen()); 00244 } 00245 return 0; 00246 } 00247 /*---------------------------------------------------------------------------*/ 00248 static 00249 PT_THREAD(handle_dhcp(void)) 00250 { 00251 PT_BEGIN(&s.pt); 00252 00253 /* try_again:*/ 00254 s.state = STATE_SENDING; 00255 s.ticks = CLOCK_SECOND; 00256 00257 do { 00258 send_discover(); 00259 timer_set(&s.timer, s.ticks); 00260 PT_WAIT_UNTIL(&s.pt, uip_newdata() || timer_expired(&s.timer)); 00261 00262 if(uip_newdata() && parse_msg() == DHCPOFFER) { 00263 s.state = STATE_OFFER_RECEIVED; 00264 break; 00265 } 00266 00267 if(s.ticks < CLOCK_SECOND * 60) { 00268 s.ticks *= 2; 00269 } 00270 } while(s.state != STATE_OFFER_RECEIVED); 00271 00272 s.ticks = CLOCK_SECOND; 00273 00274 do { 00275 send_request(); 00276 timer_set(&s.timer, s.ticks); 00277 PT_WAIT_UNTIL(&s.pt, uip_newdata() || timer_expired(&s.timer)); 00278 00279 if(uip_newdata() && parse_msg() == DHCPACK) { 00280 s.state = STATE_CONFIG_RECEIVED; 00281 break; 00282 } 00283 00284 if(s.ticks <= CLOCK_SECOND * 10) { 00285 s.ticks += CLOCK_SECOND; 00286 } else { 00287 PT_RESTART(&s.pt); 00288 } 00289 } while(s.state != STATE_CONFIG_RECEIVED); 00290 00291 #if 0 00292 printf("Got IP address %d.%d.%d.%d\n", 00293 uip_ipaddr1(s.ipaddr), uip_ipaddr2(s.ipaddr), 00294 uip_ipaddr3(s.ipaddr), uip_ipaddr4(s.ipaddr)); 00295 printf("Got netmask %d.%d.%d.%d\n", 00296 uip_ipaddr1(s.netmask), uip_ipaddr2(s.netmask), 00297 uip_ipaddr3(s.netmask), uip_ipaddr4(s.netmask)); 00298 printf("Got DNS server %d.%d.%d.%d\n", 00299 uip_ipaddr1(s.dnsaddr), uip_ipaddr2(s.dnsaddr), 00300 uip_ipaddr3(s.dnsaddr), uip_ipaddr4(s.dnsaddr)); 00301 printf("Got default router %d.%d.%d.%d\n", 00302 uip_ipaddr1(s.default_router), uip_ipaddr2(s.default_router), 00303 uip_ipaddr3(s.default_router), uip_ipaddr4(s.default_router)); 00304 printf("Lease expires in %ld seconds\n", 00305 ntohs(s.lease_time[0])*65536ul + ntohs(s.lease_time[1])); 00306 #endif 00307 00308 dhcpc_configured(&s); 00309 00310 /* timer_stop(&s.timer);*/ 00311 00312 /* 00313 * PT_END перезапускает поток, что мы делаем вместо этого. В конечном 00314 * счете мы должны здесь повторно получить истекшую аренду адреса. 00315 */ 00316 while(1) { 00317 PT_YIELD(&s.pt); 00318 } 00319 00320 PT_END(&s.pt); 00321 } 00322 /*---------------------------------------------------------------------------*/ 00323 void 00324 dhcpc_init(const void *mac_addr, int mac_len) 00325 { 00326 uip_ipaddr_t addr; 00327 00328 s.mac_addr = mac_addr; 00329 s.mac_len = mac_len; 00330 00331 s.state = STATE_INITIAL; 00332 uip_ipaddr(addr, 255,255,255,255); 00333 s.conn = uip_udp_new(&addr, HTONS(DHCPC_SERVER_PORT)); 00334 if(s.conn != NULL) { 00335 uip_udp_bind(s.conn, HTONS(DHCPC_CLIENT_PORT)); 00336 } 00337 PT_INIT(&s.pt); 00338 } 00339 /*---------------------------------------------------------------------------*/ 00340 void 00341 dhcpc_appcall(void) 00342 { 00343 handle_dhcp(); 00344 } 00345 /*---------------------------------------------------------------------------*/ 00346 void 00347 dhcpc_request(void) 00348 { 00349 u16_t ipaddr[2]; 00350 00351 if(s.state == STATE_INITIAL) { 00352 uip_ipaddr(ipaddr, 0,0,0,0); 00353 uip_sethostaddr(ipaddr); 00354 /* handle_dhcp(PROCESS_EVENT_NONE, NULL);*/ 00355 } 00356 } 00357 /*---------------------------------------------------------------------------*/