Watt-32 tcp/ip  2.2 dev-rel.10
pcbootp.c
Go to the documentation of this file.
1 
13 #include <stdio.h>
14 #include <stdlib.h>
15 
16 #include "copyrigh.h"
17 #include "wattcp.h"
18 #include "strings.h"
19 #include "language.h"
20 #include "pcdns.h"
21 #include "syslog2.h"
22 #include "misc.h"
23 #include "timer.h"
24 #include "netaddr.h"
25 #include "pctcp.h"
26 #include "pcsed.h"
27 #include "pcarp.h"
28 #include "pcconfig.h"
29 #include "pcqueue.h"
30 #include "pcpkt.h"
31 #include "pcbootp.h"
32 
33 #undef udp_Socket
34 
35 DWORD _bootp_host = IP_BCAST_ADDR;
36 
37 #if defined(USE_DHCP)
38  int _bootp_timeout = 15; /* give DHCP a chance also (sock_delay=30) */
39 #else
40  int _bootp_timeout = 30;
41 #endif
42 
43 #if defined(USE_BOOTP)
44 
45 static sock_type *boot_sock;
46 
47 static int bootp_xmit (struct bootp *bootp_out);
48 static BOOL bootp_recv (struct bootp *bootp_out, struct bootp *bootp_in);
49 static void bootp_parse (const struct bootp *bootp_in, int len);
50 
60 int BOOTP_do_boot (void)
61 {
62  struct bootp bootp_out, bootp_in;
63  struct udp_Socket sock;
64  DWORD save_ip = my_ip_addr;
65  int rc = 0;
66 
67  boot_sock = (sock_type*) &sock;
68 
69  outs (_LANG("Configuring through BOOTP.."));
70 
71  my_ip_addr = 0UL; /* We must use IP address 0.0.0.0 for sending */
72 
73  if (!udp_open(&sock,IPPORT_BOOTPC,_bootp_host,IPPORT_BOOTPS,NULL))
74  {
75  outsnl (boot_sock->udp.err_msg);
76  my_ip_addr = save_ip;
77  }
78  else
79  {
80  memset (&bootp_in, 0, sizeof(bootp_in));
81  memset (&bootp_out, 0, sizeof(bootp_out));
82  bootp_xmit (&bootp_out);
83  if (bootp_recv(&bootp_out, &bootp_in))
84  {
85  my_ip_addr = intel (bootp_in.bp_yiaddr);
86  rc = 1;
87  }
88  }
89  sock_close (boot_sock);
90  boot_sock = NULL;
91  outsnl (rc ? "okay" : "failed");
92  return (rc);
93 }
94 
95 static int bootp_xmit (struct bootp *bootp_out)
96 {
97  DWORD exchange_id = set_timeout (0); /* "random" exchange ID */
98 
99  _eth_get_hwtype (&bootp_out->bp_htype, &bootp_out->bp_hlen);
100 
101  bootp_out->bp_op = BOOTP_REQUEST;
102  bootp_out->bp_xid = exchange_id;
103  bootp_out->bp_secs = intel16 (((WORD)exchange_id & 7) + 7);
104  *(DWORD*) &bootp_out->bp_vend = intel (VM_RFC1048); /* Magic Number */
105 
106  memcpy (&bootp_out->bp_chaddr, _eth_addr, _eth_mac_len);
107  return sock_fastwrite (boot_sock, (BYTE*)bootp_out, sizeof(*bootp_out));
108 }
109 
110 static BOOL bootp_recv (struct bootp *bootp_out, struct bootp *bootp_in)
111 {
112  DWORD exchange_id = bootp_out->bp_xid;
113  DWORD boot_timer = set_timeout (1000 * _bootp_timeout);
114 
115  while (1)
116  {
117  DWORD vendor;
118  int len;
119 
120  WATT_YIELD();
121 
122  if (chk_timeout(boot_timer) || !tcp_tick(boot_sock))
123  return (FALSE);
124 
125  if (sock_dataready(boot_sock) < sizeof(*bootp_in))
126  continue;
127 
128  /* got a response, lets consider it
129  */
130  memset (bootp_in, 0, sizeof(*bootp_in));
131  len = sock_fastread (boot_sock, (BYTE*)bootp_in, sizeof(*bootp_in));
132  if (len < BOOTP_MIN_SIZE ||
133  bootp_in->bp_op != BOOTP_REPLY)
134  continue;
135 
136  /* Check if transaction ID and MAC-address matches
137  */
138  if (bootp_in->bp_xid != exchange_id ||
139  memcmp(&bootp_in->bp_chaddr, _eth_addr, _eth_mac_len))
140  continue;
141 
142  vendor = intel (*(DWORD*)&bootp_in->bp_vend);
143  if (vendor == VM_RFC1048)
144  bootp_parse (bootp_in, len);
145  break;
146  }
147  return (TRUE);
148 }
149 
150 /*
151  * Parse RFC1048 compliant BOOTP vendor field.
152  * Based heavily on NCSA Telnet BOOTP
153  */
154 static void bootp_parse (const struct bootp *bootp_in, int max)
155 {
156  const BYTE *p = &bootp_in->bp_vend[4]; /* Point after magic value */
157  const BYTE *end = max + (const BYTE*)bootp_in;
158  BOOL got_end = FALSE;
159 
160  while (!got_end && p < end)
161  {
162  DWORD ip;
163  int i, len;
164 
165  switch (*p)
166  {
167  case BOOTP_OPT_PAD:
168  p++;
169  continue;
170 
171  case BOOTP_OPT_SUBNET_MASK:
172  sin_mask = intel (*(DWORD*)(p+2));
173  break;
174 
175  case BOOTP_OPT_ROUTERS_ON_SNET:
176  /* only add first */
177  ip = intel (*(DWORD*)(p+2));
178  _arp_add_gateway (NULL, ip);
179  break;
180 
181  case BOOTP_OPT_DNS_SRV:
182  for (i = 0; i < *(p+1); i += sizeof(ip))
183  {
184  ip = intel (*(DWORD*)(p+2+i));
185  _add_server (&last_nameserver, def_nameservers,
186  DIM(def_nameservers), ip);
187  }
188  break;
189 
190  case BOOTP_OPT_COOKIE_SRV:
191  for (i = 0; i < *(p+1) ; i += sizeof(ip))
192  {
193  ip = intel (*(DWORD*)(p+2+i));
194  _add_server (&last_cookie, cookies, DIM(cookies), ip);
195  }
196  break;
197 
198 #if defined(USE_BSD_API)
199  case BOOTP_OPT_LOG_SRV:
200  ip = intel (*(DWORD*)(p+2)); /* select 1st host */
201  if (!syslog_host_name[0] && /* not in config-file */
202  p[1] % 4 == 0) /* length = n * 4 */
203  _strlcpy (syslog_host_name, _inet_ntoa(NULL,ip),
204  sizeof(syslog_host_name));
205  break;
206 #endif
207 
208  case BOOTP_OPT_HOST_NAME:
209  len = min (p[1], sizeof(hostname));
210  memcpy (&hostname[0], p+2, len);
211  hostname[len] = '\0';
212  break;
213 
214  case BOOTP_OPT_NAME_SRV: /* IEN-116 name server */
215  case BOOTP_OPT_LPR_SRV:
216  case BOOTP_OPT_IMPRESS_SRV:
217  case BOOTP_OPT_RES_LOCATION_SRV:
218  case BOOTP_OPT_TIME_SRV:
219  case BOOTP_OPT_TIME_OFFSET:
220  break;
221 
222  case BOOTP_OPT_END:
223  got_end = TRUE;
224  break;
225 
226  default:
227  break;
228  }
229  p += *(p+1) + 2;
230  }
231 }
232 #endif /* USE_BOOTP */
233 
Definition: pcbootp.h:63
int W32_CALL udp_open(_udp_Socket *s, WORD lport, DWORD ip, WORD port, ProtoHandler handler)
UDP active open.
Definition: pctcp.c:192
BYTE W32_CALL _eth_get_hwtype(BYTE *hwtype, BYTE *hwlen)
Fill in hardware address type/length for BOOTP/DHCP packets.
Definition: pcsed.c:751
int W32_CALL sock_close(sock_type *s)
Close a UDP/TCP socket.
Definition: pctcp.c:3139
int W32_CALL sock_fastwrite(sock_type *s, const BYTE *data, int len)
Simpler, non-blocking (non-looping) version of sock_write().
Definition: pctcp.c:3018
BOOL W32_CALL _arp_add_gateway(const char *config_string, DWORD ip)
Add a gateway to the routing table.
Definition: pcarp.c:247
Core definitions.
char * _strlcpy(char *dst, const char *src, size_t len)
Similar to strncpy(), but always returns 'dst' with 0-termination.
Definition: strings.c:226
mac_address _eth_addr
Local link-layer source address.
Definition: pcsed.c:50
int BOOTP_do_boot(void)
Main BOOTP initialisation.
Definition: pcbootp.c:60
DWORD W32_CALL set_timeout(DWORD msec)
Return time for when given timeout (msec) expires.
Definition: timer.c:503
DWORD sin_mask
our net-mask, 255.255.255.0
Definition: pctcp.c:71
BYTE _eth_mac_len
Size of a MAC address.
Definition: pcsed.c:54
Definition: ip.h:67
int W32_CALL sock_fastread(sock_type *s, BYTE *buf, int len)
Read a socket with maximum 'len' bytes.
Definition: pctcp.c:2931
char hostname[MAX_HOSTLEN+1]
Our configured hostname.
Definition: pctcp.c:59
DWORD my_ip_addr
our IP address
Definition: pctcp.c:70
WORD W32_CALL tcp_tick(sock_type *s)
Must be called periodically by user application (or BSD socket API).
Definition: pctcp.c:1389
char *W32_CALL _inet_ntoa(char *s, DWORD ip)
Convert an IP-address 'ip' into a string.
Definition: netaddr.c:43
WORD W32_CALL sock_dataready(sock_type *s)
sock_dataready - returns number of bytes waiting to be read.
Definition: sock_io.c:246
BOOL W32_CALL chk_timeout(DWORD value)
Check if milli-sec value has expired:
Definition: timer.c:547