uIP 1.0
C:/asm/STM32-ethernet/ENC28J60prj/uip-master/apps/dhcpc/dhcpc.c
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 /*---------------------------------------------------------------------------*/