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