http://gimel.esc.cam.ac.uk/james/rpld/src/rpld-1.8-beta-1.tar.gz
[rpld.git] / protocol.c
1 /*************************************************
2 *     rpld - an IBM style RIPL server            *
3 *************************************************/
4
5 /* Copyright (c) 1999,2000,2001 James McKenzie.
6  *                      All rights reserved
7  * Copyright (c) 1998,2000,2001 Christopher Lightfoot.
8  *                      All rights reserved
9  *
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.
13  *
14  * IBM is a trademark of IBM corp.
15  *
16  */
17
18
19 static char rcsid[] =
20   "$Id: protocol.c,v 1.32 2001/11/01 15:30:35 root Exp root $";
21
22 /*
23  * $Log: protocol.c,v $
24  * Revision 1.32  2001/11/01 15:30:35  root
25  * #
26  *
27  * Revision 1.31  2001/11/01 15:30:29  root
28  * #
29  *
30  * Revision 1.30  2001/11/01 15:28:07  root
31  * #
32  *
33  * Revision 1.29  2001/11/01 15:26:45  root
34  * #
35  *
36  * Revision 1.28  2001/11/01 15:24:26  root
37  * #
38  *
39  * Revision 1.27  2001/11/01 15:23:59  root
40  * #
41  *
42  * Revision 1.26  2000/09/26 03:44:29  root
43  * #
44  *
45  * Revision 1.25  2000/09/26 02:31:38  root
46  * #
47  *
48  * Revision 1.24  2000/09/26 01:42:24  root
49  * #
50  *
51  * Revision 1.23  2000/09/26 01:41:20  root
52  * #
53  *
54  * Revision 1.22  2000/09/26 01:41:08  root
55  * #
56  *
57  * Revision 1.21  2000/09/26 01:03:19  root
58  * #
59  *
60  * Revision 1.20  2000/07/29 23:25:58  root
61  * #
62  *
63  * Revision 1.19  2000/07/29 23:25:25  root
64  * #
65  *
66  * Revision 1.18  2000/07/29 23:20:02  root
67  * #
68  *
69  * Revision 1.17  2000/07/23 19:07:49  root
70  * #
71  *
72  * Revision 1.16  2000/07/17 11:59:45  root
73  * #
74  *
75  * Revision 1.15  2000/07/17 10:49:20  root
76  * #
77  *
78  * Revision 1.14  2000/07/17 10:45:38  root
79  * #
80  *
81  * Revision 1.13  2000/07/17 10:43:54  root
82  * #
83  *
84  * Revision 1.12  2000/07/17 10:43:34  root
85  * #
86  *
87  * Revision 1.11  2000/07/16 14:05:28  root
88  * #
89  *
90  * Revision 1.10  2000/07/16 13:18:10  root
91  * #
92  *
93  * Revision 1.1  2000/07/16 13:16:33  root
94  * #
95  *
96  * Revision 1.9  1999/09/13 11:17:35  root
97  * \#
98  *
99  * Revision 1.8  1999/09/13 11:08:34  root
100  * \#
101  *
102  * Revision 1.7  1999/09/13 11:05:27  root
103  * \#
104  *
105  * Revision 1.6  1999/09/13 11:04:13  root
106  * \#
107  *
108  */
109
110 #include "project.h"
111
112 /* Process the find frame and xmit a found frame */
113 void
114 find_frame (struct llcdrv *lld, struct rpl_packet *in)
115 {
116   struct client *c;
117   struct rpl_packet out;
118
119   c = find_client_by_mac (in->mymac);
120
121   if (!c)
122     {
123       syslog (LOG_ERR, "unknown client %s", ethtoa (in->mymac));
124       return;
125     }
126
127   c->blocknum = 0;
128
129   out.type = RPL_PK_FOUND;
130
131   out.flags =
132     RPL_FL_TMZ | RPL_FL_TSZ | RPL_FL_YOUMAC | RPL_FL_MYMAC | RPL_FL_FRAMELEN |
133     RPL_FL_WHOAMI | RPL_FL_SAP;
134
135   out.themightyzero = in->themightyzero;
136   out.thesmallzero = 0;
137   out.whoami = 0;
138
139   if (in->framelen < c->framelen)
140     {
141       c->framelen = in->framelen;
142     }
143
144   if ((c->blocklen + LLC_RPL_OVERHEAD) > c->framelen)
145     {
146       c->blocklen = c->framelen - LLC_RPL_OVERHEAD;
147       c->blocklen &= ~0x7;
148     }
149
150   c->framelen = out.framelen =
151     (in->framelen > c->framelen) ? c->framelen : in->framelen;
152   out.sap = RPL_SAP;
153
154   bcopy (in->mymac, out.youmac, ETH_ALEN);
155   bcopy (lld->mac (lld), out.mymac, ETH_ALEN);
156
157   c->state = ST_FIND;
158
159   rpl_send_packet (lld, c->mac, &out);
160
161   c->state = ST_FOUND;
162
163 }
164
165
166 file_data_frame (struct llcdrv *lld, struct client *c)
167 {
168   struct rpl_packet out;
169   int i;
170
171   u32 addr = 0x10000;
172
173   if (c->state != ST_FILEDATA)
174     return;
175
176   out.flags = RPL_FL_BLOCK | RPL_FL_ADDR | RPL_FL_DATA;
177   out.type = RPL_PK_FILEDATA;
178
179   out.block = c->blocknum;
180
181   client_get_block (c, &out);
182
183   out.addr.run = c->run_addr;
184
185 #ifdef DEBUG
186   printf ("block %5d, %4d bytes to 0x%08x\n", c->blocknum,
187           out.datalen, out.addr.load);
188 #endif
189
190   if (client_last_block (c))
191     {
192       out.addr.flags = RPL_AD_FLAGS_DONE;
193       c->state = ST_DONE;
194 #ifdef DEBUG
195       printf ("Last block - transfering control to 0x%08x\n", c->run_addr);
196 #endif
197       clients_check_status ();
198     }
199   else
200     {
201       if (c->nospew)
202         out.addr.flags = RPL_AD_FLAGS_ASK_MORE;
203       else
204         out.addr.flags = RPL_AD_FLAGS_MORE;
205     }
206
207
208
209   rpl_send_packet (lld, c->mac, &out);
210   c->blocknum++;
211
212   return (i);
213 }
214
215 void
216 send_file_frame (struct llcdrv *lld, struct rpl_packet *in)
217 {
218   struct client *c;
219   struct rpl_packet out;
220
221   c = find_client_by_mac (in->mymac);
222
223   if (!c)
224     {
225       printf ("Unknown client\n");
226       return;
227     }
228
229   c->state = ST_SENDFILE;
230
231   c->blocknum = in->block;
232   c->framelen = in->framelen;
233
234   syslog (LOG_ERR, "client %s requested block %d", ethtoa (c->mac),
235           c->blocknum);
236
237   client_calc_offsets (c);
238
239   c->state = ST_FILEDATA;
240
241   clients_check_status ();      /* This will upgrade our condition to downloading */
242
243
244   if (c->nospew)
245     file_data_frame (lld, c);
246
247
248 }
249
250 /* rpl.c call this after it's interpreted a packet from the nic */
251 void
252 rpl_packet_recvd_callback (struct llcdrv *lld, struct rpl_packet *p)
253 {
254   switch (p->type)
255     {
256     case RPL_PK_FIND:
257
258       if ((p->flags & RPL_FIND_FLAGS) == RPL_FIND_FLAGS)
259         {
260           find_frame (lld, p);
261         }
262       else
263         {
264           syslog (LOG_ERR, "Incomplete FIND frame 0x%x vs 0x%x\n",
265                   p->flags, RPL_FIND_FLAGS);
266         }
267     case RPL_PK_FOUND:         /*We're not a client */
268       break;
269     case RPL_PK_SENDFILE:
270       if ((p->flags & RPL_SEND_FILE_FLAGS) == RPL_SEND_FILE_FLAGS)
271         {
272           send_file_frame (lld, p);
273         }
274       else
275         {
276           syslog (LOG_ERR,
277                   "Incomplete SEND.FILE.REQUEST frame 0x%x vs 0x%x\n",
278                   p->flags, RPL_SEND_FILE_FLAGS);
279         }
280       break;
281     case RPL_PK_FILEDATA:      /*We're not a client */
282       break;
283     default:
284       syslog (LOG_ERR, "Unknown RPL packet type 0x%04x\n", p->type);
285
286     }
287
288 }