]> andersk Git - moira.git/blob - lib/mr_param.c
added subnet & address errors
[moira.git] / lib / mr_param.c
1 /*
2  *      $Source$
3  *      $Author$
4  *      $Header$
5  *
6  *      Copyright (C) 1987, 1990 by the Massachusetts Institute of Technology
7  *      For copying and distribution information, please see the file
8  *      <mit-copyright.h>.
9  *
10  */
11
12 #ifndef lint
13 static char *rcsid_sms_param_c = "$Header$";
14 #endif lint
15
16 #include <mit-copyright.h>
17 #include <sys/types.h>
18 #include <netinet/in.h>
19 #include "mr_private.h"
20 #include <string.h>
21
22 /*
23  * GDB operations to send and recieve RPC requests and replies.
24  */
25
26 /*
27  * This doesn't get called until after the actual buffered write completes.
28  * In a non-preflattening version of this, this would then queue the
29  * write of the next bunch of data.
30  */
31
32 /*ARGSUSED*/
33 mr_cont_send(op, hcon, arg)
34     OPERATION op;
35     HALF_CONNECTION hcon;
36     struct mr_params *arg;
37 {
38     op->result = OP_SUCCESS;
39     free(arg->mr_flattened);
40     arg->mr_flattened = NULL;
41     
42     return OP_COMPLETE;
43 }
44
45 mr_start_send(op, hcon, arg)
46     OPERATION op;
47     HALF_CONNECTION hcon;
48     register struct mr_params *arg;
49 {
50     int i, len;
51     unsigned int mr_size;
52     int *argl;
53     char *buf, *bp;
54         
55     /*
56      * This should probably be split into several routines.
57      * It could also probably be made more efficient (punting most
58      * of the argument marshalling stuff) by doing I/O directly
59      * from the strings.  Anyone for a scatter/gather mr_send_data?
60      *
61      * that would look a lot like the uio stuff in the kernel..  hmm.
62      */
63         
64     /*
65      * Marshall the entire data right now..
66      * We are sending the version number,
67      * total request size, request number, 
68      * argument count, and then each argument.
69      * At least for now, each argument is a string, which is
70      * sent as a count of bytes followed by the bytes
71      * (including the trailing '\0'), padded
72      * to a longword boundary.
73      */
74
75     mr_size = 4 * sizeof(long);
76
77     argl = (int *)malloc((unsigned)(sizeof(int) * arg->mr_argc));
78
79     /*
80      * For each argument, figure out how much space is needed.
81      */
82         
83     for (i = 0; i < arg->mr_argc; ++i) {
84         if (arg->mr_argl)
85             argl[i] = len = arg->mr_argl[i];
86         else
87             argl[i] = len = strlen(arg->mr_argv[i]) + 1;
88         mr_size += sizeof(long) + len;
89         /* Round up to next longword boundary.. */
90         mr_size = sizeof(long) * howmany(mr_size, sizeof(long));
91     }
92         
93     arg->mr_flattened = buf = malloc(mr_size);
94
95     memset(arg->mr_flattened, 0, mr_size);
96         
97     arg->mr_size = mr_size;
98         
99     /*
100      * This is gross.  Any better suggestions, anyone?
101      * It should work on the RT's, since malloc is guaranteed to
102      * return a pointer which is aligned correctly for any data.
103      */
104
105     ((long *)buf)[0] = htonl(mr_size);
106     ((long *)buf)[1] = htonl(arg->mr_version_no);
107     ((long *)buf)[2] = htonl(arg->mr_procno);
108     ((long *)buf)[3] = htonl(arg->mr_argc);
109
110     /*
111      * bp is a pointer into the point in the buffer to put
112      * the next argument.
113      */
114         
115     bp = (char *)(((long *)buf) + 4);
116         
117     for (i = 0; i<arg->mr_argc; ++i) {
118         len = argl[i];
119         *((long *)bp) = htonl(len);
120         bp += sizeof(long);
121         memcpy(bp, arg->mr_argv[i], len);
122         bp += sizeof(long) * howmany(len, sizeof(long));
123     }
124     op->fcn.cont = mr_cont_send;
125     arg->mr_size = mr_size;
126
127     free(argl);
128     
129     if (gdb_send_data(hcon, arg->mr_flattened, mr_size) == OP_COMPLETE)
130         return mr_cont_send(op, hcon, arg);
131     else return OP_RUNNING;
132 }       
133         
134 /*ARGSUSED*/
135 mr_cont_recv(op, hcon, argp)
136     OPERATION op;
137     HALF_CONNECTION hcon;
138     mr_params **argp;
139 {
140     int done = FALSE;
141     char *cp;
142     int *ip;
143     int i;
144     register mr_params *arg = *argp;
145                                                        
146     while (!done) {
147         switch (arg->mr_state) {
148         case S_RECV_START:
149             arg->mr_state = S_RECV_DATA;
150             if (gdb_receive_data(hcon, (caddr_t)&arg->mr_size,
151                                  sizeof(long)) == OP_COMPLETE)
152                 continue;
153             done = TRUE;
154             break;
155         case S_RECV_DATA:
156             fflush(stdout);
157             /* Should validate that length is reasonable */
158             arg->mr_size = ntohl(arg->mr_size);
159             if (arg->mr_size > 65536) {
160                 return OP_CANCELLED;
161             }
162             arg->mr_flattened = malloc(arg->mr_size);
163             arg->mr_state = S_DECODE_DATA;
164             memcpy(arg->mr_flattened, (caddr_t)&arg->mr_size, sizeof(long));
165                         
166             if (gdb_receive_data(hcon,
167                                  arg->mr_flattened + sizeof(long),
168                                  arg->mr_size - sizeof(long))
169                 == OP_COMPLETE)
170                 continue;
171             done = TRUE;
172             break;
173         case S_DECODE_DATA:
174             cp = arg->mr_flattened;
175             ip = (int *) cp;
176             /* we already got the overall length.. */
177             for(i=1; i <4; i++) ip[i] = ntohl(ip[i]);
178             arg->mr_version_no = ip[1];
179             if (arg->mr_version_no != MR_VERSION_1 &&
180                 arg->mr_version_no != MR_VERSION_2)
181                 arg->mr_status = MR_VERSION_MISMATCH;
182             else arg->mr_status = ip[2];
183             arg->mr_argc = ip[3];
184             cp += 4 * sizeof(int);
185             arg->mr_argv=(char **)malloc(arg->mr_argc *sizeof(char **));
186             arg->mr_argl=(int *)malloc(arg->mr_argc *sizeof(int *));
187                         
188             for (i = 0; i<arg->mr_argc; ++i) {
189                 u_short nlen = ntohl(* (int *) cp);
190                 cp += sizeof (long);
191                 if (cp + nlen > arg->mr_flattened + arg->mr_size) {
192                     free(arg->mr_flattened);
193                     arg->mr_flattened = NULL;
194                     return OP_CANCELLED;
195                 }                   
196                 arg->mr_argv[i] = (char *)malloc(nlen);
197                 memcpy(arg->mr_argv[i], cp, nlen);
198                 arg->mr_argl[i]=nlen;
199                 cp += sizeof(long) * howmany(nlen, sizeof(long));
200             }
201             free(arg->mr_flattened);
202             arg->mr_flattened = NULL;
203             return OP_COMPLETE;
204         }
205     }
206     return OP_RUNNING;
207 }
208                         
209
210 mr_start_recv(op, hcon, argp)
211     OPERATION op;
212     HALF_CONNECTION hcon;
213     struct mr_params **argp;
214 {
215     register mr_params *arg = *argp;
216     if (!arg) {
217         *argp = arg = (mr_params *)malloc(sizeof(mr_params));
218         arg->mr_argl = NULL;
219         arg->mr_argv = NULL;
220         arg->mr_flattened = NULL;
221     }
222     arg->mr_state = S_RECV_START;
223     op->fcn.cont = mr_cont_recv;
224     return mr_cont_recv(op, hcon, argp);
225 }
226
227 mr_destroy_reply(reply)
228     mr_params *reply;
229 {
230     int i;
231     if (reply) {
232         if (reply->mr_argl)
233             free(reply->mr_argl);
234         reply->mr_argl = NULL;
235         if (reply->mr_flattened)
236             free(reply->mr_flattened);
237         reply->mr_flattened = NULL;
238         if (reply->mr_argv) {
239             for (i=0; i<reply->mr_argc; i++) {
240                 if (reply->mr_argv[i])
241                     free (reply->mr_argv[i]);
242                 reply->mr_argv[i] = NULL;
243             }
244             free(reply->mr_argv);
245         }
246         reply->mr_argv = NULL;
247         free(reply);
248     }
249 }
This page took 0.300177 seconds and 5 git commands to generate.