XINU
dhcp.c
Go to the documentation of this file.
1 /* dhcp.c - getlocalip */
2 
3 #include <xinu.h>
4 
5 /*------------------------------------------------------------------------
6  * dhcp_get_opt_val - Retrieve a pointer to the value for a specified
7  * DHCP options key
8  *------------------------------------------------------------------------
9  */
11  const struct dhcpmsg* dmsg, /* DHCP Message */
12  uint32 dmsg_size, /* Size of DHCP Message */
13  uint8 option_key /* Option key to retrieve */
14  )
15 {
16  unsigned char* opt_tmp;
17  unsigned char* eom;
18 
19  eom = (unsigned char*)dmsg + dmsg_size - 1;
20  opt_tmp = (unsigned char*)dmsg->dc_opt;
21 
22  while(opt_tmp < eom) {
23 
24  /* If the option value matches return the value */
25 
26  if((*opt_tmp) == option_key) {
27 
28  /* Offset past the option value and the size */
29 
30  return (char*)(opt_tmp+2);
31  }
32  opt_tmp++; /* Move to length octet */
33  opt_tmp += *(uint8*)opt_tmp + 1;
34  }
35 
36  /* Option value not found */
37 
38  return NULL;
39 }
40 
41 /*------------------------------------------------------------------------
42  * dhcp_bld_bootp_msg - Set the common fields for all DHCP messages
43  *------------------------------------------------------------------------
44  */
45 void dhcp_bld_bootp_msg(struct dhcpmsg* dmsg)
46 {
47  uint32 xid; /* Xid used for the exchange */
48 
49  memcpy(&xid, NetData.ethucast, 4); /* Use 4 bytes from MAC as */
50  /* unique XID */
51  memset(dmsg, 0x00, sizeof(struct dhcpmsg));
52 
53  dmsg->dc_bop = 0x01; /* Outgoing request */
54  dmsg->dc_htype = 0x01; /* Hardware type is Ethernet */
55  dmsg->dc_hlen = 0x06; /* Hardware address length */
56  dmsg->dc_hops = 0x00; /* Hop count */
57  dmsg->dc_xid = htonl(xid); /* Xid (unique ID) */
58  dmsg->dc_secs = 0x0000; /* Seconds */
59  dmsg->dc_flags = 0x0000; /* Flags */
60  dmsg->dc_cip = 0x00000000; /* Client IP address */
61  dmsg->dc_yip = 0x00000000; /* Your IP address */
62  dmsg->dc_sip = 0x00000000; /* Server IP address */
63  dmsg->dc_gip = 0x00000000; /* Gateway IP address */
64  memset(&dmsg->dc_chaddr,'\0',16);/* Client hardware address */
66  memset(&dmsg->dc_bootp,'\0',192);/* Zero the bootp area */
67  dmsg->dc_cookie = htonl(0x63825363); /* Magic cookie for DHCP */
68 }
69 
70 /*------------------------------------------------------------------------
71  * dhcp_bld_disc - handcraft a DHCP Discover message in dmsg
72  *------------------------------------------------------------------------
73  */
75 {
76  uint32 j = 0;
77 
78  dhcp_bld_bootp_msg(dmsg);
79 
80  dmsg->dc_opt[j++] = 0xff & 53; /* DHCP message type option */
81  dmsg->dc_opt[j++] = 0xff & 1; /* Option length */
82  dmsg->dc_opt[j++] = 0xff & 1; /* DHCP Dicover message */
83  dmsg->dc_opt[j++] = 0xff & 0; /* Options padding */
84 
85  dmsg->dc_opt[j++] = 0xff & 55; /* DHCP parameter request list */
86  dmsg->dc_opt[j++] = 0xff & 2; /* Option length */
87  dmsg->dc_opt[j++] = 0xff & 1; /* Request subnet mask */
88  dmsg->dc_opt[j++] = 0xff & 3; /* Request default router addr->*/
89  dmsg->dc_opt[j++] = 0xff; /* End of options */
90 
91  return (uint32)((char *)&dmsg->dc_opt[j] - (char *)dmsg + 1);
92 }
93 
94 /*------------------------------------------------------------------------
95  * dhcp_bld_req - handcraft a DHCP request message in dmsg
96  *------------------------------------------------------------------------
97  */
99  struct dhcpmsg* dmsg, /* DHCP message to build */
100  const struct dhcpmsg* dmsg_offer, /* DHCP offer message */
101  uint32 dsmg_offer_size /* Size of DHCP offer message */
102  )
103 {
104  uint32 j = 0;
105  uint32* server_ip; /* Take the DHCP server IP addr */
106  /* from DHCP offer message */
107 
108  dhcp_bld_bootp_msg(dmsg);
109  dmsg->dc_sip = dmsg_offer->dc_sip; /* Server IP address */
110  dmsg->dc_opt[j++] = 0xff & 53; /* DHCP message type option */
111  dmsg->dc_opt[j++] = 0xff & 1; /* Option length */
112  dmsg->dc_opt[j++] = 0xff & 3; /* DHCP Request message */
113  dmsg->dc_opt[j++] = 0xff & 0; /* Options padding */
114 
115  dmsg->dc_opt[j++] = 0xff & 50; /* Requested IP */
116  dmsg->dc_opt[j++] = 0xff & 4; /* Option length */
117  memcpy(((void *)&dmsg->dc_opt[j]), &dmsg_offer->dc_yip, 4);
118  j += 4;
119 
120  /* Retrieve the DHCP server IP from the DHCP options */
121  server_ip = (uint32*)dhcp_get_opt_val(dmsg_offer,
122  dsmg_offer_size, DHCP_SERVER_ID);
123 
124  if(server_ip == 0) {
125  kprintf("Unable to get server IP add. from DHCP Offer\n");
126  return SYSERR;
127  }
128 
129  dmsg->dc_opt[j++] = 0xff & 54; /* Server IP */
130  dmsg->dc_opt[j++] = 0xff & 4; /* Option length */
131  memcpy((void *)&dmsg->dc_opt[j], server_ip, 4);
132  j += 4;
133  dmsg->dc_opt[j++] = 0xff; /* End of options */
134 
135  return (uint32)((char *)&dmsg->dc_opt[j] - (char *)dmsg + 1);
136 }
137 
138 /*------------------------------------------------------------------------
139  * getlocalip - use DHCP to obtain an IP address
140  *------------------------------------------------------------------------
141  */
143 {
144  int32 slot; /* UDP slot to use */
145  struct dhcpmsg dmsg_snd; /* Holds outgoing DHCP messages */
146  struct dhcpmsg dmsg_rvc; /* Holds incoming DHCP messages */
147 
148  int32 i, j; /* Retry counters */
149  int32 len; /* Length of data sent */
150  int32 inlen; /* Length of data received */
151  char *optptr; /* Pointer to options area */
152  char *eop; /* Address of end of packet */
153  int32 msgtype; /* Type of DCHP message */
154  uint32 addrmask; /* Address mask for network */
155  uint32 routeraddr; /* Default router address */
156  uint32 dnsaddr; /* DNS server address */
157  uint32 ntpaddr; /* NTP server address */
158  uint32 tmp; /* Used for byte conversion */
159  uint32* tmp_server_ip; /* Temporary DHCP server pointer*/
160 
162  if (slot == SYSERR) {
163  kprintf("getlocalip: cannot register with UDP\n");
164  return SYSERR;
165  }
166 
167  len = dhcp_bld_disc(&dmsg_snd);
168  if(len == SYSERR) {
169  kprintf("getlocalip: Unable to build DHCP discover\n");
170  return SYSERR;
171  }
172 
173  for (i = 0; i < DHCP_RETRY; i++) {
175  (char *)&dmsg_snd, len);
176 
177  /* Read 3 incoming DHCP messages and check for an offer */
178  /* or wait for three timeout periods if no message */
179  /* arrives. */
180 
181  for (j=0; j<3; j++) {
182  inlen = udp_recv(slot, (char *)&dmsg_rvc,
183  sizeof(struct dhcpmsg), 2000);
184  if (inlen == TIMEOUT) {
185  continue;
186  } else if (inlen == SYSERR) {
187  return SYSERR;
188  }
189  /* Check that incoming message is a valid */
190  /* response (ID matches our request) */
191 
192  if (dmsg_rvc.dc_xid != dmsg_snd.dc_xid) {
193  continue;
194  }
195 
196  eop = (char *)&dmsg_rvc + inlen - 1;
197  optptr = (char *)&dmsg_rvc.dc_opt;
198  msgtype = addrmask = routeraddr = dnsaddr = ntpaddr = 0;
199 
200  while (optptr < eop) {
201 
202  switch (*optptr) {
203  case 53: /* Message type */
204  msgtype = 0xff & *(optptr+2);
205  break;
206 
207  case 1: /* Subnet mask */
208  memcpy((void *)&tmp, optptr+2, 4);
209  addrmask = ntohl(tmp);
210  break;
211 
212  case 3: /* Router address */
213  memcpy((void *)&tmp, optptr+2, 4);
214  routeraddr = ntohl(tmp);
215  break;
216 
217  case 6: /* DNS server address */
218  memcpy((void *)&tmp, optptr+2, 4);
219  dnsaddr = ntohl(tmp);
220  break;
221 
222  case 42: /* NTP server address */
223  memcpy((void *)&tmp, optptr+2, 4);
224  ntpaddr = ntohl(tmp);
225  break;
226 
227  }
228  optptr++; /* Move to length octet */
229  optptr += (0xff & *optptr) + 1;
230  }
231 
232  if (msgtype == 0x02) { /* Offer - send request */
233  len = dhcp_bld_req(&dmsg_snd, &dmsg_rvc, inlen);
234  if(len == SYSERR) {
235  kprintf("getlocalip: %s\n",
236  "Unable to build DHCP request");
237  return SYSERR;
238  }
240  (char *)&dmsg_snd, len);
241  continue;
242 
243  } else if (dmsg_rvc.dc_opt[2] != 0x05) {
244  /* If not an ack skip it */
245  continue;
246  }
247  if (addrmask != 0) {
248  NetData.ipmask = addrmask;
249  }
250  if (routeraddr != 0) {
251  NetData.iprouter = routeraddr;
252  }
253  if (dnsaddr != 0) {
254  NetData.dnsserver = dnsaddr;
255  }
256  if (ntpaddr != 0) {
257  NetData.ntpserver = ntpaddr;
258  }
259 
260  NetData.ipucast = ntohl(dmsg_rvc.dc_yip);
263  NetData.ipvalid = TRUE;
264  udp_release(slot);
265 
266  /* Retrieve the boot server IP */
267  if (dot2ip((char*)dmsg_rvc.sname,
268  &NetData.bootserver) != OK) {
269  /* Could not retrieve the boot server from */
270  /* the BOOTP fields, so use the DHCP server */
271  /* address */
272  tmp_server_ip = (uint32*)dhcp_get_opt_val(
273  &dmsg_rvc, len, DHCP_SERVER_ID);
274  memcpy((char *)&tmp, tmp_server_ip, 4);
275  NetData.bootserver = ntohl(tmp);
276  }
277  memcpy(NetData.bootfile, dmsg_rvc.bootfile,
278  sizeof(dmsg_rvc.bootfile));
279  return NetData.ipucast;
280  }
281  }
282 
283  kprintf("DHCP failed to get a response\n");
284  udp_release(slot);
285  return (uint32)SYSERR;
286 }
287 
syscall kprintf(char *fmt,...)
ポーリングI/Oを使用して、フォーマットされた文字列をコンソールに出力する。
Definition: kprintf.c:98
#define NULL
連結リスト用のNULLポインタ
Definition: kernel.h:68
int32 udp_recv(uid32, char *, int32, uint32)
Definition: udp.c:146
uint32 ipucast
Definition: net.h:55
#define UDP_DHCP_SPORT
Definition: udp.h:7
uint32 dc_gip
Definition: dhcp.h:44
uint32 ipmask
Definition: net.h:57
uint32 dc_yip
Definition: dhcp.h:42
#define IP_BCAST
IPローカルブロードキャストアドレス。
Definition: ip.h:7
byte dc_hops
Definition: dhcp.h:37
struct network NetData
Definition: net.c:6
char bootfile[NETBOOTFILE]
Definition: net.h:66
全てのシステムヘッダファイルをインクルードする。
#define SYSERR
処理が失敗した場合
Definition: kernel.h:79
uint32 dc_xid
Definition: dhcp.h:38
unsigned char uint8
符号なし8ビット値(unsigned char)
Definition: kernel.h:9
#define OK
処理が成功した場合
Definition: kernel.h:77
uint32 getlocalip(void)
Definition: dhcp.c:142
int32 dhcp_bld_req(struct dhcpmsg *dmsg, const struct dhcpmsg *dmsg_offer, uint32 dsmg_offer_size)
Definition: dhcp.c:98
#define DHCP_SERVER_ID
Definition: dhcp.h:17
#define UDP_DHCP_CPORT
Definition: udp.h:6
#define TIMEOUT
システムコールがタイムアウトした場合
Definition: kernel.h:83
Definition: dhcp.h:33
#define ntohl(x)
Definition: prototypes.h:623
uint16 dc_secs
Definition: dhcp.h:39
byte ethucast[ETH_ADDR_LEN]
Definition: net.h:64
void dhcp_bld_bootp_msg(struct dhcpmsg *dmsg)
Definition: dhcp.c:45
uint32 iprouter
Definition: net.h:59
uint32 dc_cookie
Definition: dhcp.h:53
#define TRUE
Boolean True(1)
Definition: kernel.h:65
#define DHCP_RETRY
Definition: dhcp.h:5
byte dc_bootp[192]
Definition: dhcp.h:47
byte dc_chaddr[16]
Definition: dhcp.h:45
uint32 dc_cip
Definition: dhcp.h:41
int int32
符号あり32ビット整数(int)
Definition: kernel.h:11
byte dc_opt[1024]
Definition: dhcp.h:54
uid32 udp_register(uint32, uint16, uint16)
Definition: udp.c:85
uint16 dc_flags
Definition: dhcp.h:40
byte dc_htype
Definition: dhcp.h:35
void * memset(void *, const int, int32)
指定のByteブロックに対して、同じ値をNバイト分書き込む。
Definition: memset.c:13
uint32 ipprefix
Definition: net.h:58
uint32 ipbcast
Definition: net.h:56
byte dc_bop
Definition: dhcp.h:34
status udp_release(uid32)
Definition: udp.c:502
byte dc_hlen
Definition: dhcp.h:36
int32 dhcp_bld_disc(struct dhcpmsg *dmsg)
Definition: dhcp.c:74
uint32 bootserver
Definition: net.h:60
#define ETH_ADDR_LEN
Definition: ether.h:10
status udp_sendto(uid32, uint32, uint16, char *, int32)
Definition: udp.c:417
uint32 ntpserver
Definition: net.h:62
#define htonl(x)
Definition: prototypes.h:620
char * dhcp_get_opt_val(const struct dhcpmsg *dmsg, uint32 dmsg_size, uint8 option_key)
Definition: dhcp.c:10
unsigned int uint32
符号なし32ビット整数(unsigned int)
Definition: kernel.h:15
uint32 dot2ip(char *, uint32 *)
Definition: dot2ip.c:9
uint32 dnsserver
Definition: net.h:61
void * memcpy(void *, const void *, int32)
メモリAの領域(source)からメモリBの領域(Destination)にN Byteコピーする。
Definition: memcpy.c:13
uint32 dc_sip
Definition: dhcp.h:43
bool8 ipvalid
Definition: net.h:63