1 /*************************************************
2 * rpld - an IBM style RIPL server *
3 *************************************************/
5 /* Copyright (c) 1999,2000, James McKenzie.
7 * Copyright (c) 1998,2000, Christopher Lightfoot.
10 * By using this file, you agree to the terms and conditions set
11 * forth in the LICENCE file which can be found at the top level of
12 * the rpld distribution.
14 * IBM is a trademark of IBM corp.
20 "$Id: client.c,v 1.29 2000/09/26 04:06:07 root Exp root $";
24 * Revision 1.29 2000/09/26 04:06:07 root
27 * Revision 1.28 2000/09/26 03:48:23 root
30 * Revision 1.27 2000/09/26 02:32:46 root
33 * Revision 1.26 2000/09/26 02:31:38 root
36 * Revision 1.25 2000/09/26 01:41:22 root
39 * Revision 1.24 2000/09/26 01:41:20 root
42 * Revision 1.23 2000/09/26 01:39:17 root
45 * Revision 1.22 2000/09/26 01:03:19 root
48 * Revision 1.21 2000/07/29 23:25:58 root
51 * Revision 1.20 2000/07/29 23:25:25 root
54 * Revision 1.19 2000/07/23 19:14:19 root
57 * Revision 1.18 2000/07/23 19:07:49 root
60 * Revision 1.17 2000/07/17 10:49:20 root
63 * Revision 1.16 2000/07/17 10:45:38 root
66 * Revision 1.15 2000/07/17 10:43:54 root
69 * Revision 1.14 2000/07/17 10:43:34 root
72 * Revision 1.13 2000/07/16 14:22:06 root
75 * Revision 1.12 2000/07/16 14:05:28 root
78 * Revision 1.11 2000/07/16 13:18:10 root
81 * Revision 1.1 2000/07/16 13:16:33 root
84 * Revision 1.10 1999/09/14 17:12:38 root
87 * Revision 1.9 1999/09/14 17:12:05 root
90 * Revision 1.8 1999/09/13 11:17:35 root
93 * Revision 1.7 1999/09/13 11:05:27 root
96 * Revision 1.6 1999/09/13 11:04:13 root
103 struct client *clients = NULL;
106 cache_locally (struct clfile *f)
111 fd = open (f->path, O_RDONLY);
115 syslog (LOG_ERR, "can't open %s:%m", f->path);
123 len = lseek (fd, 0, SEEK_END);
124 lseek (fd, 0, SEEK_SET);
127 f->data = malloc (len);
130 lseek (fd, f->offset, SEEK_SET);
131 read (fd, f->data, len);
141 /* Cache the last client */
143 find_client_by_mac (unsigned char *mac)
145 struct client *pc = NULL, *c = clients;
147 /* We need to match clients by a (possibly partial) MAC address; however
148 * this struct client is also used to transmit to them, so we need to return
149 * a struct client containing a _real_ MAC address; this is a first and
150 * pretty ugly implementation of this idea.
154 if (memcmp (mac, c->mac, c->partial_mac_len) == 0)
156 /* if partial match, create new struct client */
157 if (c->partial_mac_len != ETH_ALEN)
159 pc = (struct client *) malloc (sizeof (struct client));
160 memcpy (pc, c, sizeof (struct client));
169 /* else reorder the tree for speed, and return the found client */
171 { /*Short circuit for next time */
187 client_calc_offsets (struct client *c)
204 fd = open (f->path, O_RDONLY);
207 syslog (LOG_ERR, "can't open %s:%m", f->path);
213 len = lseek (fd, 0, SEEK_END);
224 printf ("%s is %d bytes long gives", f->path, len);
226 blocks = len / (c->blocklen);
227 len = len - (blocks * c->blocklen);
236 printf (" %d blocks [%d,%d]\n", blocks, f->sblock, f->eblock);
248 #define NOTINRANGE(l,v,h) (((v)<(l)) || ((v)>(h)))
250 client_get_block (struct client *c, struct rpl_packet *p)
258 p->datalen = 0; /* Some buggy clients request
259 * blocks after the end when
260 * they get confused */
262 if ((!f) || (NOTINRANGE (f->sblock, c->blocknum, f->eblock)))
270 while (f && (f->eblock < c->blocknum))
275 syslog (LOG_ERR, "this shouldn't happen oops!");
281 f->f = fopen (f->path, "r");
286 syslog (LOG_ERR, "failed to open %s ", f->path);
296 offset = (c->blocklen) * (c->blocknum - f->sblock);
300 toread = f->length - offset;
301 if (toread > c->blocklen)
302 toread = c->blocklen;
306 toread = c->blocklen;
311 fseek (f->f, offset + f->offset, SEEK_SET);
312 p->datalen = fread (p->data, 1, toread, f->f);
313 if ((p->datalen != toread) && (c->blocknum != f->eblock))
315 syslog (LOG_ERR, "short read on %s", f->path);
320 bcopy (f->data + offset, p->data, toread);
324 p->addr.load = f->load_addr + offset;
329 client_last_block (struct client *c)
334 if ((!f) || (NOTINRANGE (f->sblock, c->blocknum, f->eblock)))
343 while (f && (f->eblock < c->blocknum))
348 syslog (LOG_ERR, "this shouldn't happen oops!");
349 return 1; /*Infact past the last block */
353 if (!(f->next) && (f->eblock == c->blocknum))
363 client_flush_cache (struct client *c)
378 clients_check_status ()
380 struct client *c = clients;
387 if ((c->state == ST_FILEDATA) && (!c->nospew))
390 if (pacing < c->pacing)
398 client_dispatch (struct llcdrv *lld)
400 struct client *c = clients;
404 if ((c->state == ST_FILEDATA) && (!c->nospew))
406 file_data_frame (lld, c);