Watt-32 tcp/ip  2.2 dev-rel.10
geteth.c
Go to the documentation of this file.
1 
6 /* Copyright (c) 1997-2002 Gisle Vanem <gvanem@yahoo.no>
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in the
15  * documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  * must display the following acknowledgement:
18  * This product includes software developed by Gisle Vanem
19  * Bergen, Norway.
20  *
21  * THIS SOFTWARE IS PROVIDED BY ME (Gisle Vanem) AND CONTRIBUTORS ``AS IS''
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED. IN NO EVENT SHALL I OR CONTRIBUTORS BE LIABLE FOR ANY
25  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  *
33  * 28.apr 2000 - Created
34  */
35 
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 
40 #include "wattcp.h"
41 #include "misc.h"
42 #include "run.h"
43 #include "pcarp.h"
44 #include "pcconfig.h"
45 #include "pcdns.h"
46 #include "pcdbug.h"
47 #include "strings.h"
48 #include "netaddr.h"
49 #include "bsddbug.h"
50 #include "get_xby.h"
51 
52 #if defined(USE_BSD_API)
53 
54 #include <net/if.h>
55 #include <net/if_arp.h>
56 #include <net/if_dl.h>
57 #include <net/if_ether.h>
58 #include <net/route.h>
59 
60 #if defined(TEST_PROG)
61  #undef SOCK_DEBUGF
62  #define SOCK_DEBUGF(args) printf args
63 #endif
64 
65 #if !defined(USE_BUFFERED_IO)
66  #error This file needs USE_BUFFERED_IO
67 #endif
68 
69 struct ethent {
70  eth_address eth_addr; /* ether/MAC address of host */
71  DWORD ip_addr; /* IP-address (host order) */
72  char *name; /* host-name for IP-address */
73  struct ethent *next;
74  };
75 
76 static struct ethent *eth0 = NULL;
77 static int num_entries = -1;
78 static char ethersFname [MAX_PATHLEN] = "";
79 
80 static int get_ether_entry (char *in_buf, eth_address *e, char *out_buf, size_t out_buf_size);
81 static void end_ether_entries (void);
82 
83 void W32_CALL InitEthersFile (const char *fname)
84 {
85  if (fname && *fname)
86  _strlcpy (ethersFname, fname, sizeof(ethersFname));
87 }
88 
89 const char * W32_CALL GetEthersFile (void)
90 {
91  return (ethersFname[0] ? ethersFname : NULL);
92 }
93 
94 int W32_CALL NumEtherEntries (void)
95 {
96  return (num_entries);
97 }
98 
104 void W32_CALL ReadEthersFile (void)
105 {
106  FILE *file;
107  char buf [2*MAX_HOSTLEN];
108 
109  if (!ethersFname[0])
110  return;
111 
112  if (!FOPEN_TXT(file, ethersFname))
113  {
114  netdb_warn (ethersFname);
115  return;
116  }
117 
118  while (fgets(buf,sizeof(buf),file))
119  {
120  struct ethent *e;
121  struct hostent *h;
122  char host_ip [MAX_HOSTLEN];
123  int save;
124  eth_address eth;
125 
126  if (!get_ether_entry(buf,&eth,host_ip,sizeof(host_ip)))
127  continue;
128 
129  if (num_entries == -1)
130  num_entries = 0;
131  num_entries++;
132 
133  save = called_from_resolve;
134  called_from_resolve = TRUE; /* prevent a DNS lookup */
135  h = gethostbyname (host_ip);
136  called_from_resolve = save;
137 
138  /* If 'h == NULL': means 'host_ip' contained a host-name that cannot be resolved
139  * at this moment. gethostbyname()+resolve() cannot be called at startup.
140  * If 'h != NULL': means 'host_ip' is simply an IPv4-address or a host-name (or alias)
141  * that is in '/etc/hosts' file.
142  */
143  if (!h)
144  {
145  CONSOLE_MSG (4, ("ReadEthersFile(): gethostbyname() failed\n"));
146  continue;
147  }
148  CONSOLE_MSG (4, ("\n"));
149 
150  e = calloc (sizeof(*e), 1);
151  if (!e)
152  break;
153 
154  e->ip_addr = ntohl (*(DWORD*)h->h_addr);
155  memcpy (&e->eth_addr, &eth, sizeof(e->eth_addr));
156 
157  /* Add this to the permanent ARP-cache.
158  */
159  _arp_cache_add (e->ip_addr, &e->eth_addr, FALSE);
160 
161  if (h->h_name)
162  {
163  e->name = strdup (h->h_name);
164  if (!e->name)
165  break;
166  }
167  e->next = eth0;
168  eth0 = e;
169  }
170 
171  FCLOSE (file);
172  RUNDOWN_ADD (end_ether_entries, 250);
173 }
174 
175 /*
176  * Parse a string of text containing an ethernet address and
177  * hostname/IP-address and separate it into its component parts.
178  * E.g.
179  * in_buf -> "88-87-17-17-5a-3e 10.0.0.4"
180  * in_buf -> "E0-CA-94-3D-74-F0 printer"
181  */
182 #define MIN_LEN sizeof("0:0:0:0:0:0 a.b.c.d")
183 
184 static int get_ether_entry (char *in_buf, eth_address *e,
185  char *name, size_t name_max)
186 {
187  size_t len, i;
188  unsigned eth [sizeof(*e)];
189  BOOL ok, colon;
190  char *token = strltrim (in_buf);
191  char *ip_name;
192  char *tok_buf = NULL;
193 
194  if (*token == '#' || *token == ';' || *token == '\n' || strlen(token) < MIN_LEN)
195  return (0);
196 
197  colon = (token[2] == ':');
198 
199  ok = colon ? (sscanf(token, "%02x:%02x:%02x:%02x:%02x:%02x",
200  &eth[0], &eth[1], &eth[2],
201  &eth[3], &eth[4], &eth[5]) == DIM(eth)) :
202  (sscanf(token, "%02x-%02x-%02x-%02x-%02x-%02x",
203  &eth[0], &eth[1], &eth[2],
204  &eth[3], &eth[4], &eth[5]) == DIM(eth));
205  if (!ok)
206  {
207  CONSOLE_MSG (1, ("get_ether_entry(): sscanf() failed\n"));
208  return (0);
209  }
210 
211  token = strtok_r (token, " \t", &tok_buf);
212  ip_name = strtok_r (NULL, " #\t\n", &tok_buf);
213 
214  if (!token || !ip_name || (len = strlen(ip_name)) < 1 || len > name_max)
215  {
216  CONSOLE_MSG (1, ("get_ether_entry(): short line or malformed ip_name '%s'\n", ip_name));
217  return (0);
218  }
219 
220  ip_name = (char*) expand_var_str (ip_name);
221 
222  _strlcpy (name, ip_name, name_max);
223 
224  for (i = 0; i < sizeof(*e); i++)
225  ((BYTE*)e)[i] = eth[i];
226 
227  CONSOLE_MSG (4, ("get_ether_entry(): ip: %s, eth: %02X:%02X:%02X:%02X:%02X:%02X\n",
228  ip_name, eth[0],eth[1],eth[2],eth[3],eth[4],eth[5]));
229 
230  return (1);
231 }
232 
233 /*
234  * Free memory in 'eth0' array
235  */
236 static void end_ether_entries (void)
237 {
238  struct ethent *e, *next;
239 
240  if (_watt_fatal_error)
241  return;
242 
243  for (e = eth0; e; e = next)
244  {
245  DO_FREE (e->name);
246  next = e->next;
247  free (e);
248  }
249  eth0 = NULL;
250  num_entries = 0;
251 }
252 
253 void W32_CALL DumpEthersCache (void)
254 {
255  const struct ethent *e;
256 
257  if (!ethersFname[0])
258  {
259  SOCK_DEBUGF (("No ETHERS line found in WATTCP.CFG\n"));
260  return;
261  }
262 
263  SOCK_DEBUGF (("\n%s entries:\n", ethersFname));
264  for (e = eth0; e; e = e->next)
265  SOCK_DEBUGF ((" %s = %-15.15s (%s)\n",
266  MAC_address(&e->eth_addr), _inet_ntoa(NULL,e->ip_addr),
267  e->name ? e->name : "none"));
268 }
269 #endif /* USE_BSD_API */
270 
271 /*
272  * Find the name associated with ether-addr 'eth'.
273  * Returns null if not found in 'eth0' list.
274  */
275 const char * W32_CALL GetEtherName (const eth_address *eth)
276 {
277 #if defined(USE_BSD_API)
278  const struct ethent *e;
279 
280  for (e = eth0; e; e = e->next)
281  if (!memcmp(eth, e->eth_addr, sizeof(*eth)))
282  return (e->name);
283 #endif
284  ARGSUSED (eth);
285  return (NULL);
286 }
287 
288 #if defined(TEST_PROG)
289 
290 #include "pcdbug.h"
291 #include "sock_ini.h"
292 
293 int main (void)
294 {
295 #if defined(USE_BSD_API)
296  debug_on = 2;
297  dbug_init();
298  sock_init();
299  DumpEthersCache();
300 
301 #else
302  puts ("\"USE_BSD_API\" not defined");
303 #endif /* USE_BSD_API */
304  return (0);
305 }
306 #endif /* TEST_PROG */
char * strltrim(const char *s)
Return pointer to first non-blank (space/tab) in a string.
Definition: strings.c:243
BOOL W32_CALL _arp_cache_add(DWORD ip, const void *eth, BOOL expires)
Add given IP/Ether address to ARP-cache.
Definition: pcarp.c:1352
Definition: netdb.h:102
Definition: pcdbug.c:1463
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
const char * MAC_address(const void *addr)
Return hexa-decimal string for an 6/7 byte MAC-address.
Definition: misc.c:963
const char * expand_var_str(const char *str)
Return a string with a environment variable expanded (only one).
Definition: pcconfig.c:231
void W32_CALL ReadEthersFile(void)
Read the /etc/ethers file.
Definition: geteth.c:104
BOOL called_from_resolve
Hacks to make gethostbyname() and resolve() cooperate.
Definition: pcdns.c:60
BOOL _watt_fatal_error
Definition: misc.c:60
Definition: geteth.c:69
char *W32_CALL _inet_ntoa(char *s, DWORD ip)
Convert an IP-address 'ip' into a string.
Definition: netaddr.c:43
int main(int argc, char **argv)
Definition: echo.c:223