1 /*
2  * cmd_solparm.c
3  *
4  * A command interpreter for OpenIPMI
5  *
6  * Author: MontaVista Software, Inc.
7  *         Corey Minyard <minyard@mvista.com>
8  *         source@mvista.com
9  *
10  * Copyright 2004 MontaVista Software Inc.
11  *
12  *  This program is free software; you can redistribute it and/or
13  *  modify it under the terms of the GNU Lesser General Public License
14  *  as published by the Free Software Foundation; either version 2 of
15  *  the License, or (at your option) any later version.
16  *
17  *
18  *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
19  *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
24  *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25  *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
26  *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
27  *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  *
29  *  You should have received a copy of the GNU Lesser General Public
30  *  License along with this program; if not, write to the Free
31  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
32  */
33 
34 #include <errno.h>
35 #include <string.h>
36 #include <ctype.h>
37 #include <stdlib.h>
38 #include <stdio.h>
39 #include <OpenIPMI/ipmiif.h>
40 #include <OpenIPMI/ipmi_solparm.h>
41 #include <OpenIPMI/ipmi_cmdlang.h>
42 #include <OpenIPMI/ipmi_mc.h>
43 
44 /* Internal includes, do not use in your programs */
45 #include <OpenIPMI/internal/ipmi_malloc.h>
46 #include <OpenIPMI/internal/locked_list.h>
47 
48 static locked_list_t *solcs;
49 
50 static void
solparm_list_handler(ipmi_solparm_t * solparm,void * cb_data)51 solparm_list_handler(ipmi_solparm_t *solparm, void *cb_data)
52 {
53     ipmi_cmd_info_t *cmd_info = cb_data;
54     ipmi_cmdlang_t  *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
55     char            solparm_name[IPMI_SOLPARM_NAME_LEN];
56 
57     if (cmdlang->err)
58 	return;
59 
60     ipmi_solparm_get_name(solparm, solparm_name, sizeof(solparm_name));
61 
62     ipmi_cmdlang_out(cmd_info, "Name", solparm_name);
63 }
64 
65 static void
solparm_list(ipmi_domain_t * domain,void * cb_data)66 solparm_list(ipmi_domain_t *domain, void *cb_data)
67 {
68     ipmi_cmd_info_t *cmd_info = cb_data;
69     char             domain_name[IPMI_DOMAIN_NAME_LEN];
70 
71     ipmi_domain_get_name(domain, domain_name, sizeof(domain_name));
72     ipmi_cmdlang_out(cmd_info, "Domain", NULL);
73     ipmi_cmdlang_down(cmd_info);
74     ipmi_cmdlang_out(cmd_info, "Name", domain_name);
75     ipmi_cmdlang_out(cmd_info, "SOLPARMs", NULL);
76     ipmi_cmdlang_down(cmd_info);
77     ipmi_solparm_iterate_solparms(domain, solparm_list_handler, cmd_info);
78     ipmi_cmdlang_up(cmd_info);
79     ipmi_cmdlang_up(cmd_info);
80 }
81 
82 static void
get_mc_name(ipmi_mc_t * mc,void * cb_data)83 get_mc_name(ipmi_mc_t *mc, void *cb_data)
84 {
85     ipmi_cmd_info_t *cmd_info = cb_data;
86     char            mc_name[IPMI_MC_NAME_LEN];
87 
88     ipmi_mc_get_name(mc, mc_name, sizeof(mc_name));
89     ipmi_cmdlang_out(cmd_info, "MC", mc_name);
90 }
91 
92 static void
solparm_info(ipmi_solparm_t * solparm,void * cb_data)93 solparm_info(ipmi_solparm_t *solparm, void *cb_data)
94 {
95     ipmi_cmd_info_t *cmd_info = cb_data;
96     int             rv;
97     char            solparm_name[IPMI_SOLPARM_NAME_LEN];
98 
99     ipmi_solparm_get_name(solparm, solparm_name, sizeof(solparm_name));
100 
101     ipmi_cmdlang_out(cmd_info, "SOLPARM", NULL);
102     ipmi_cmdlang_down(cmd_info);
103     ipmi_cmdlang_out(cmd_info, "Name", solparm_name);
104     rv = ipmi_mc_pointer_cb(ipmi_solparm_get_mc_id(solparm), get_mc_name,
105 			    cmd_info);
106     if (rv) {
107 	ipmi_cmdlang_out_int(cmd_info, "Error getting MC", rv);
108     }
109     ipmi_cmdlang_out_int(cmd_info, "Channel",
110 			 ipmi_solparm_get_channel(solparm));
111     ipmi_cmdlang_up(cmd_info);
112 }
113 
114 static void
solparm_new(ipmi_mc_t * mc,void * cb_data)115 solparm_new(ipmi_mc_t *mc, void *cb_data)
116 {
117     ipmi_cmd_info_t *cmd_info = cb_data;
118     ipmi_cmdlang_t  *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
119     int             channel;
120     int             rv;
121     int             curr_arg = ipmi_cmdlang_get_curr_arg(cmd_info);
122     int             argc = ipmi_cmdlang_get_argc(cmd_info);
123     char            **argv = ipmi_cmdlang_get_argv(cmd_info);
124     ipmi_solparm_t  *solparm;
125     char            solparm_name[IPMI_SOLPARM_NAME_LEN];
126 
127     if ((argc - curr_arg) < 1) {
128 	/* Not enough parameters */
129 	cmdlang->errstr = "Not enough parameters";
130 	cmdlang->err = EINVAL;
131 	goto out_err;
132     }
133 
134     ipmi_cmdlang_get_int(argv[curr_arg], &channel, cmd_info);
135     if (cmdlang->err) {
136 	cmdlang->errstr = "channel invalid";
137 	goto out_err;
138     }
139     curr_arg++;
140 
141     rv = ipmi_solparm_alloc(mc, channel, &solparm);
142     if (rv) {
143 	cmdlang->errstr = "Error from ipmi_solparm_alloc";
144 	cmdlang->err = rv;
145 	goto out_err;
146     }
147 
148     ipmi_solparm_get_name(solparm, solparm_name, sizeof(solparm_name));
149     ipmi_cmdlang_out(cmd_info, "SOLPARM", solparm_name);
150 
151     return;
152 
153  out_err:
154     ipmi_mc_get_name(mc, cmdlang->objstr,
155 		     cmdlang->objstr_len);
156     cmdlang->location = "cmd_solparm.c(solparm_new)";
157 }
158 
159 typedef struct solparm_info_s
160 {
161     char            name[IPMI_SOLPARM_NAME_LEN];
162     ipmi_cmd_info_t *cmd_info;
163 } solparm_info_t;
164 
165 static void
solparm_close_done(ipmi_solparm_t * solparm,int err,void * cb_data)166 solparm_close_done(ipmi_solparm_t *solparm, int err, void *cb_data)
167 {
168     solparm_info_t  *info = cb_data;
169     ipmi_cmd_info_t *cmd_info = info->cmd_info;
170     ipmi_cmdlang_t  *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
171 
172     ipmi_cmdlang_lock(cmd_info);
173     if (err) {
174 	ipmi_solparm_get_name(solparm, cmdlang->objstr,
175 			  cmdlang->objstr_len);
176 	cmdlang->errstr = "Error closing SOLPARM";
177 	cmdlang->err = err;
178 	cmdlang->location = "cmd_solparm.c(solparm_close_done)";
179 	goto out;
180     }
181 
182     ipmi_cmdlang_out(cmd_info, "SOLPARM destroyed", info->name);
183 
184  out:
185     ipmi_cmdlang_unlock(cmd_info);
186     ipmi_cmdlang_cmd_info_put(cmd_info);
187     ipmi_mem_free(info);
188 }
189 
190 static void
solparm_close(ipmi_solparm_t * solparm,void * cb_data)191 solparm_close(ipmi_solparm_t *solparm, void *cb_data)
192 {
193     ipmi_cmd_info_t *cmd_info = cb_data;
194     ipmi_cmdlang_t  *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
195     int             rv;
196     solparm_info_t  *info;
197 
198     info = ipmi_mem_alloc(sizeof(*info));
199     if (!info) {
200 	cmdlang->errstr = "Out of memory";
201 	cmdlang->err = ENOMEM;
202 	goto out_err;
203     }
204     info->cmd_info = cmd_info;
205     ipmi_solparm_get_name(solparm, info->name, sizeof(info->name));
206 
207     ipmi_cmdlang_cmd_info_get(cmd_info);
208     rv = ipmi_solparm_destroy(solparm, solparm_close_done, info);
209     if (rv) {
210 	ipmi_cmdlang_cmd_info_put(cmd_info);
211 	ipmi_solparm_get_name(solparm, cmdlang->objstr,
212 			      cmdlang->objstr_len);
213 	cmdlang->errstr = "Error closing SOLPARM";
214 	cmdlang->err = rv;
215 	ipmi_mem_free(info);
216     }
217     return;
218 
219  out_err:
220     cmdlang->location = "cmd_solparm.c(solparm_close)";
221 }
222 
223 #define SOL_CONFIG_NAME_LEN 80
224 typedef struct sol_config_info_s
225 {
226     char              name[SOL_CONFIG_NAME_LEN];
227     ipmi_sol_config_t *config;
228 } sol_config_info_t;
229 
230 static unsigned int unique_num = 0;
231 
232 typedef struct find_config_s
233 {
234     char              *name;
235     ipmi_sol_config_t *config;
236     int               delete;
237 } find_config_t;
238 
239 static int
find_config_handler(void * cb_data,void * item1,void * item2)240 find_config_handler(void *cb_data, void *item1, void *item2)
241 {
242     sol_config_info_t *info = item1;
243     find_config_t     *find = cb_data;
244 
245     if (strcmp(find->name, info->name) == 0) {
246 	find->config = info->config;
247 	if (find->delete) {
248 	    locked_list_remove(solcs, item1, item2);
249 	    ipmi_mem_free(info);
250 	}
251 	return LOCKED_LIST_ITER_STOP;
252     }
253 
254     return LOCKED_LIST_ITER_CONTINUE;
255 }
256 
257 static ipmi_sol_config_t *
find_config(char * name,int delete)258 find_config(char *name, int delete)
259 {
260     find_config_t find;
261 
262     find.name = name;
263     find.config = NULL;
264     find.delete = delete;
265     locked_list_iterate(solcs, find_config_handler, &find);
266     return find.config;
267 }
268 
269 typedef void (*lp_set)(ipmi_cmd_info_t *cmd_info, char *val,
270 		       ipmi_sol_config_t *solc, void *func);
271 typedef void (*lp_out)(ipmi_cmd_info_t *cmd_info, char *name,
272 		       ipmi_sol_config_t *solc, void *func);
273 typedef struct lp_item_s
274 {
275     lp_set set;
276     lp_out out;
277 } lp_item_t;
278 
279 static void
set_retint(ipmi_cmd_info_t * cmd_info,char * val,ipmi_sol_config_t * solc,void * func)280 set_retint(ipmi_cmd_info_t *cmd_info, char *val,
281 	   ipmi_sol_config_t *solc, void *func)
282 {
283     ipmi_cmdlang_t *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
284     int            (*f)(ipmi_sol_config_t *l, unsigned int v) = func;
285     int            v;
286 
287     ipmi_cmdlang_get_int(val, &v, cmd_info);
288     if (!cmdlang->err) {
289 	cmdlang->err = f(solc, v);
290 	if (cmdlang->err) {
291 	    cmdlang->errstr = "Error setting parameter";
292 	}
293     }
294 }
295 static void
out_retint(ipmi_cmd_info_t * cmd_info,char * name,ipmi_sol_config_t * solc,void * func)296 out_retint(ipmi_cmd_info_t *cmd_info, char *name,
297 	   ipmi_sol_config_t *solc, void *func)
298 {
299     unsigned int   (*f)(ipmi_sol_config_t *l) = func;
300     ipmi_cmdlang_out_int(cmd_info, name, f(solc));
301 }
302 static lp_item_t lp_retint = {set_retint, out_retint};
303 
304 static void
set_retbool(ipmi_cmd_info_t * cmd_info,char * val,ipmi_sol_config_t * solc,void * func)305 set_retbool(ipmi_cmd_info_t *cmd_info, char *val,
306 	    ipmi_sol_config_t *solc, void *func)
307 {
308     ipmi_cmdlang_t *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
309     int            (*f)(ipmi_sol_config_t *l, unsigned int v) = func;
310     int            v;
311 
312     ipmi_cmdlang_get_bool(val, &v, cmd_info);
313     if (!cmdlang->err) {
314 	cmdlang->err = f(solc, v);
315 	if (cmdlang->err) {
316 	    cmdlang->errstr = "Error setting parameter";
317 	}
318     }
319 }
320 static void
out_retbool(ipmi_cmd_info_t * cmd_info,char * name,ipmi_sol_config_t * solc,void * func)321 out_retbool(ipmi_cmd_info_t *cmd_info, char *name,
322 	    ipmi_sol_config_t *solc, void *func)
323 {
324     unsigned int   (*f)(ipmi_sol_config_t *l) = func;
325     ipmi_cmdlang_out_bool(cmd_info, name, f(solc));
326 }
327 static lp_item_t lp_retbool = {set_retbool, out_retbool};
328 
329 static void
set_int(ipmi_cmd_info_t * cmd_info,char * val,ipmi_sol_config_t * solc,void * func)330 set_int(ipmi_cmd_info_t *cmd_info, char *val,
331 	ipmi_sol_config_t *solc, void *func)
332 {
333     ipmi_cmdlang_t *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
334     int            (*f)(ipmi_sol_config_t *l, unsigned int v) = func;
335     int            v;
336 
337     ipmi_cmdlang_get_int(val, &v, cmd_info);
338     if (!cmdlang->err) {
339 	cmdlang->err = f(solc, v);
340 	if (cmdlang->err) {
341 	    cmdlang->errstr = "Error setting parameter";
342 	}
343     }
344 }
345 static void
out_int(ipmi_cmd_info_t * cmd_info,char * name,ipmi_sol_config_t * solc,void * func)346 out_int(ipmi_cmd_info_t *cmd_info, char *name,
347 	ipmi_sol_config_t *solc, void *func)
348 {
349     unsigned int   v;
350     int            rv;
351     int            (*f)(ipmi_sol_config_t *l, unsigned int *v) = func;
352 
353     rv = f(solc, &v);
354     if (!rv)
355 	ipmi_cmdlang_out_int(cmd_info, name, v);
356 }
357 static lp_item_t lp_int = {set_int, out_int};
358 
359 static struct lps_s
360 {
361     char      *name;
362     lp_item_t *lpi;
363     void      *get_func;
364     void      *set_func;
365 } lps[] =
366 /* read-only */
367 #define FR(name, type) { #name, &lp_ ## type, ipmi_solconfig_get_ ## name, \
368 		         NULL }
369 /* Writable */
370 #define F(name, type) { #name, &lp_ ## type, ipmi_solconfig_get_ ## name, \
371 		        ipmi_solconfig_set_ ## name }
372 {
373     F(enable, retbool),
374     F(force_payload_encryption, retbool),
375     F(force_payload_authentication, retbool),
376     F(privilege_level, retint),
377     F(char_accumulation_interval, retint),
378     F(char_send_threshold, retint),
379     F(retry_count, retint),
380     F(retry_interval, retint),
381     F(port_number, retint),
382     FR(payload_channel, int),
383     { NULL }
384 };
385 
386 static void
config_info(ipmi_cmd_info_t * cmd_info,ipmi_sol_config_t * config)387 config_info(ipmi_cmd_info_t *cmd_info, ipmi_sol_config_t *config)
388 {
389     int i;
390 
391     /* Basic items */
392     for (i=0; lps[i].name; i++) {
393 	lp_item_t *lp = lps[i].lpi;
394 	lp->out(cmd_info, lps[i].name, config, lps[i].get_func);
395     }
396 }
397 
398 static void
solparm_config_get_done(ipmi_solparm_t * solparm,int err,ipmi_sol_config_t * config,void * cb_data)399 solparm_config_get_done(ipmi_solparm_t    *solparm,
400 			int               err,
401 			ipmi_sol_config_t *config,
402 			void              *cb_data)
403 {
404     ipmi_cmd_info_t   *cmd_info = cb_data;
405     ipmi_cmdlang_t    *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
406     char              solparm_name[IPMI_SOLPARM_NAME_LEN];
407     sol_config_info_t *info;
408 
409     ipmi_cmdlang_lock(cmd_info);
410     if (err) {
411 	cmdlang->errstr = "Error getting SOLPARM";
412 	cmdlang->err = err;
413 	goto out;
414     }
415 
416     ipmi_solparm_get_name(solparm, solparm_name, sizeof(solparm_name));
417 
418     info = ipmi_mem_alloc(sizeof(*info));
419     if (!info) {
420 	cmdlang->errstr = "Out of memory";
421 	cmdlang->err = ENOMEM;
422 	ipmi_sol_free_config(config);
423 	goto out;
424     }
425     snprintf(info->name, sizeof(info->name), "%s.%u",
426 	     solparm_name, unique_num);
427     info->config = config;
428     if (!locked_list_add(solcs, info, NULL)) {
429 	cmdlang->errstr = "Out of memory";
430 	cmdlang->err = ENOMEM;
431 	ipmi_sol_free_config(config);
432 	ipmi_mem_free(info);
433 	goto out;
434     }
435     unique_num++;
436 
437     ipmi_cmdlang_out(cmd_info, "SOLPARM Config", NULL);
438     ipmi_cmdlang_down(cmd_info);
439     ipmi_cmdlang_out(cmd_info, "Name", info->name);
440     config_info(cmd_info, config);
441     ipmi_cmdlang_up(cmd_info);
442 
443  out:
444     if (cmdlang->err) {
445 	ipmi_solparm_get_name(solparm, cmdlang->objstr,
446 			      cmdlang->objstr_len);
447 	cmdlang->location = "cmd_solparm.c(solparm_config_get_done)";
448     }
449     ipmi_cmdlang_unlock(cmd_info);
450     ipmi_cmdlang_cmd_info_put(cmd_info);
451 }
452 
453 static void
solparm_config_get(ipmi_solparm_t * solparm,void * cb_data)454 solparm_config_get(ipmi_solparm_t *solparm, void *cb_data)
455 {
456     ipmi_cmd_info_t *cmd_info = cb_data;
457     ipmi_cmdlang_t  *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
458     int             rv;
459 
460     ipmi_cmdlang_cmd_info_get(cmd_info);
461     rv = ipmi_sol_get_config(solparm, solparm_config_get_done, cmd_info);
462     if (rv) {
463 	ipmi_solparm_get_name(solparm, cmdlang->objstr,
464 			      cmdlang->objstr_len);
465 	ipmi_cmdlang_cmd_info_put(cmd_info);
466 	cmdlang->errstr = "Error getting SOLPARM";
467 	cmdlang->err = rv;
468 	cmdlang->location = "cmd_solparm.c(solparm_config_get)";
469     }
470 }
471 
472 typedef struct lp_config_op_s
473 {
474     char            name[SOL_CONFIG_NAME_LEN];
475     ipmi_cmd_info_t *cmd_info;
476 } lp_config_op_t;
477 
478 static void
solparm_config_set_done(ipmi_solparm_t * solparm,int err,void * cb_data)479 solparm_config_set_done(ipmi_solparm_t    *solparm,
480 			int               err,
481 			void              *cb_data)
482 {
483     lp_config_op_t  *info = cb_data;
484     ipmi_cmd_info_t *cmd_info = info->cmd_info;
485     ipmi_cmdlang_t  *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
486 
487     ipmi_cmdlang_lock(cmd_info);
488     if (err) {
489 	ipmi_solparm_get_name(solparm, cmdlang->objstr,
490 			      cmdlang->objstr_len);
491 	cmdlang->errstr = "Error setting SOLPARM";
492 	cmdlang->err = err;
493 	cmdlang->location = "cmd_solparm.c(solparm_config_set_done)";
494 	goto out;
495     }
496 
497     ipmi_cmdlang_out(cmd_info, "SOLPARM config set", info->name);
498 
499  out:
500     ipmi_mem_free(info);
501     ipmi_cmdlang_unlock(cmd_info);
502     ipmi_cmdlang_cmd_info_put(cmd_info);
503 }
504 
505 static void
solparm_config_set(ipmi_solparm_t * solparm,void * cb_data)506 solparm_config_set(ipmi_solparm_t *solparm, void *cb_data)
507 {
508     ipmi_cmd_info_t   *cmd_info = cb_data;
509     ipmi_cmdlang_t    *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
510     int               rv;
511     int               curr_arg = ipmi_cmdlang_get_curr_arg(cmd_info);
512     int               argc = ipmi_cmdlang_get_argc(cmd_info);
513     char              **argv = ipmi_cmdlang_get_argv(cmd_info);
514     ipmi_sol_config_t *solc;
515     lp_config_op_t    *info = cb_data;
516     char              *name;
517 
518     if ((argc - curr_arg) < 1) {
519 	/* Not enough parameters */
520 	cmdlang->errstr = "Not enough parameters";
521 	cmdlang->err = EINVAL;
522 	goto out_err;
523     }
524 
525     name = argv[curr_arg];
526     curr_arg++;
527 
528     solc = find_config(name, 0);
529     if (!solc) {
530 	cmdlang->errstr = "Invalid SOL config";
531 	cmdlang->err = EINVAL;
532 	goto out_err;
533     }
534 
535     info = ipmi_mem_alloc(sizeof(*info));
536     if (!info) {
537 	cmdlang->errstr = "Out of memory";
538 	cmdlang->err = ENOMEM;
539 	goto out_err;
540     }
541     info->cmd_info = cmd_info;
542     strncpy(info->name, name, sizeof(info->name) - 1);
543     info->name[sizeof(info->name) - 1] = '\0';
544 
545     ipmi_cmdlang_cmd_info_get(cmd_info);
546     rv = ipmi_sol_set_config(solparm, solc, solparm_config_set_done, info);
547     if (rv) {
548 	ipmi_cmdlang_cmd_info_put(cmd_info);
549 	cmdlang->errstr = "Error setting SOLPARM";
550 	cmdlang->err = rv;
551 	ipmi_mem_free(info);
552 	goto out_err;
553     }
554 
555     return;
556 
557  out_err:
558     ipmi_solparm_get_name(solparm, cmdlang->objstr,
559 			  cmdlang->objstr_len);
560     cmdlang->location = "cmd_solparm.c(solparm_config_set)";
561 }
562 
563 static void
solparm_config_unlock_done(ipmi_solparm_t * solparm,int err,void * cb_data)564 solparm_config_unlock_done(ipmi_solparm_t    *solparm,
565 			   int               err,
566 			   void              *cb_data)
567 {
568     lp_config_op_t  *info = cb_data;
569     ipmi_cmd_info_t *cmd_info = info->cmd_info;
570     ipmi_cmdlang_t  *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
571 
572     ipmi_cmdlang_lock(cmd_info);
573     if (err) {
574 	ipmi_solparm_get_name(solparm, cmdlang->objstr,
575 			      cmdlang->objstr_len);
576 	cmdlang->errstr = "Error unlocking SOLPARM";
577 	cmdlang->err = err;
578 	cmdlang->location = "cmd_solparm.c(solparm_config_unlock_done)";
579 	goto out;
580     }
581 
582     ipmi_cmdlang_out(cmd_info, "SOLPARM config unlocked", info->name);
583 
584  out:
585     ipmi_mem_free(info);
586     ipmi_cmdlang_unlock(cmd_info);
587     ipmi_cmdlang_cmd_info_put(cmd_info);
588 }
589 
590 static void
solparm_config_unlock(ipmi_solparm_t * solparm,void * cb_data)591 solparm_config_unlock(ipmi_solparm_t *solparm, void *cb_data)
592 {
593     ipmi_cmd_info_t   *cmd_info = cb_data;
594     ipmi_cmdlang_t    *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
595     int               rv;
596     int               curr_arg = ipmi_cmdlang_get_curr_arg(cmd_info);
597     int               argc = ipmi_cmdlang_get_argc(cmd_info);
598     char              **argv = ipmi_cmdlang_get_argv(cmd_info);
599     ipmi_sol_config_t *solc;
600     lp_config_op_t    *info = cb_data;
601     char              *name;
602 
603     if ((argc - curr_arg) < 1) {
604 	/* Not enough parameters */
605 	cmdlang->errstr = "Not enough parameters";
606 	cmdlang->err = EINVAL;
607 	goto out_err;
608     }
609 
610     name = argv[curr_arg];
611     curr_arg++;
612     solc = find_config(name, 0);
613     if (!solc) {
614 	cmdlang->errstr = "Invalid SOL config";
615 	cmdlang->err = EINVAL;
616 	goto out_err;
617     }
618 
619     info = ipmi_mem_alloc(sizeof(*info));
620     if (!info) {
621 	cmdlang->errstr = "Out of memory";
622 	cmdlang->err = ENOMEM;
623 	goto out_err;
624     }
625     info->cmd_info = cmd_info;
626     strncpy(info->name, name, sizeof(info->name) - 1);
627     info->name[sizeof(info->name) - 1] = '\0';
628 
629     ipmi_cmdlang_cmd_info_get(cmd_info);
630     rv = ipmi_sol_clear_lock(solparm, solc, solparm_config_unlock_done, info);
631     if (rv) {
632 	ipmi_cmdlang_cmd_info_put(cmd_info);
633 	cmdlang->errstr = "Error getting SOLPARM";
634 	cmdlang->err = rv;
635 	ipmi_mem_free(info);
636 	goto out_err;
637     }
638 
639     return;
640 
641  out_err:
642     ipmi_solparm_get_name(solparm, cmdlang->objstr,
643 			  cmdlang->objstr_len);
644     cmdlang->location = "cmd_solparm.c(solparm_config_unlock)";
645 }
646 
647 static void
solparm_config_close(ipmi_cmd_info_t * cmd_info)648 solparm_config_close(ipmi_cmd_info_t *cmd_info)
649 {
650     ipmi_cmdlang_t    *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
651     int               curr_arg = ipmi_cmdlang_get_curr_arg(cmd_info);
652     int               argc = ipmi_cmdlang_get_argc(cmd_info);
653     char              **argv = ipmi_cmdlang_get_argv(cmd_info);
654     ipmi_sol_config_t *solc;
655     char              *solc_name;
656 
657     if ((argc - curr_arg) < 1) {
658 	/* Not enough parameters */
659 	cmdlang->errstr = "Not enough parameters";
660 	cmdlang->err = EINVAL;
661 	solc_name = "";
662 	goto out_err;
663     }
664     solc_name = argv[curr_arg];
665 
666     solc = find_config(solc_name, 1);
667     if (!solc) {
668 	cmdlang->errstr = "Invalid SOL config";
669 	cmdlang->err = EINVAL;
670 	goto out_err;
671     }
672 
673     ipmi_sol_free_config(solc);
674     ipmi_cmdlang_out(cmd_info, "SOLPARM config destroyed", solc_name);
675     return;
676 
677  out_err:
678     strncpy(cmdlang->objstr, solc_name, cmdlang->objstr_len);
679     cmdlang->location = "cmd_solparm.c(solparm_config_close)";
680 }
681 
682 static int
solparm_config_list_handler(void * cb_data,void * item1,void * item2)683 solparm_config_list_handler(void *cb_data, void *item1, void *item2)
684 {
685     ipmi_cmd_info_t   *cmd_info = cb_data;
686     sol_config_info_t *info = item1;
687 
688     ipmi_cmdlang_out(cmd_info, "Name", info->name);
689     return LOCKED_LIST_ITER_CONTINUE;
690 }
691 
692 static void
solparm_config_list(ipmi_cmd_info_t * cmd_info)693 solparm_config_list(ipmi_cmd_info_t *cmd_info)
694 {
695     ipmi_cmdlang_out(cmd_info, "SOLPARM Configs", NULL);
696     ipmi_cmdlang_down(cmd_info);
697     locked_list_iterate(solcs, solparm_config_list_handler, cmd_info);
698     ipmi_cmdlang_up(cmd_info);
699 }
700 
701 static int
solparm_config_info_handler(void * cb_data,void * item1,void * item2)702 solparm_config_info_handler(void *cb_data, void *item1, void *item2)
703 {
704     ipmi_cmd_info_t   *cmd_info = cb_data;
705     sol_config_info_t *info = item1;
706 
707     ipmi_cmdlang_out(cmd_info, "SOLPARM Config", NULL);
708     ipmi_cmdlang_down(cmd_info);
709     ipmi_cmdlang_out(cmd_info, "Name", info->name);
710     config_info(cmd_info, info->config);
711     ipmi_cmdlang_up(cmd_info);
712     return LOCKED_LIST_ITER_CONTINUE;
713 }
714 
715 static void
solparm_config_info(ipmi_cmd_info_t * cmd_info)716 solparm_config_info(ipmi_cmd_info_t *cmd_info)
717 {
718     ipmi_cmdlang_t    *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
719     int               curr_arg = ipmi_cmdlang_get_curr_arg(cmd_info);
720     int               argc = ipmi_cmdlang_get_argc(cmd_info);
721     char              **argv = ipmi_cmdlang_get_argv(cmd_info);
722     ipmi_sol_config_t *solc;
723 
724     if ((argc - curr_arg) < 1) {
725 	locked_list_iterate(solcs, solparm_config_info_handler, cmd_info);
726     } else {
727 	solc = find_config(argv[curr_arg], 0);
728 	if (!solc) {
729 	    cmdlang->errstr = "Invalid SOL config";
730 	    cmdlang->err = EINVAL;
731 	    goto out_err;
732 	}
733 	ipmi_cmdlang_out(cmd_info, "SOLPARM Config", NULL);
734 	ipmi_cmdlang_down(cmd_info);
735 	ipmi_cmdlang_out(cmd_info, "Name", argv[curr_arg]);
736 	config_info(cmd_info, solc);
737 	ipmi_cmdlang_up(cmd_info);
738     }
739     return;
740 
741  out_err:
742     strncpy(cmdlang->objstr, argv[curr_arg], cmdlang->objstr_len);
743     cmdlang->location = "cmd_solparm.c(solparm_config_info)";
744 }
745 
746 static void
solparm_config_update(ipmi_cmd_info_t * cmd_info)747 solparm_config_update(ipmi_cmd_info_t *cmd_info)
748 {
749     ipmi_cmdlang_t    *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
750     int               curr_arg = ipmi_cmdlang_get_curr_arg(cmd_info);
751     int               argc = ipmi_cmdlang_get_argc(cmd_info);
752     char              **argv = ipmi_cmdlang_get_argv(cmd_info);
753     ipmi_sol_config_t *solc;
754     int               i;
755     char              *name;
756     char              *val;
757     char              *solc_name;
758 
759     if ((argc - curr_arg) < 3) {
760 	/* Not enough parameters */
761 	cmdlang->errstr = "Not enough parameters";
762 	cmdlang->err = EINVAL;
763 	solc_name = "";
764 	goto out_err;
765     }
766     solc_name = argv[curr_arg];
767     curr_arg++;
768 
769     solc = find_config(solc_name, 0);
770     if (!solc) {
771 	cmdlang->errstr = "Invalid SOL config";
772 	cmdlang->err = EINVAL;
773 	goto out_err;
774     }
775 
776     name = argv[curr_arg];
777     curr_arg++;
778     val = argv[curr_arg];
779     curr_arg++;
780 
781     /* Basic items */
782     for (i=0; lps[i].name; i++) {
783 	if (strcmp(lps[i].name, name) == 0) {
784 	    lp_item_t *lp = lps[i].lpi;
785 	    if (!lp->set) {
786 		cmdlang->errstr = "Parameter is read-only";
787 		cmdlang->err = EINVAL;
788 		goto out_err;
789 	    }
790 	    lp->set(cmd_info, val, solc, lps[i].set_func);
791 	    goto out;
792 	}
793     }
794 
795     cmdlang->errstr = "Invalid parameter name";
796     cmdlang->err = EINVAL;
797     goto out_err;
798 
799  out:
800     ipmi_cmdlang_out(cmd_info, "SOLPARM config updated", solc_name);
801     return;
802 
803  out_err:
804     strncpy(cmdlang->objstr, solc_name, cmdlang->objstr_len);
805     cmdlang->location = "cmd_solparm.c(solparm_config_update)";
806 }
807 
808 typedef struct solparm_mc_unlock_s
809 {
810     char            name[IPMI_MC_NAME_LEN];
811     ipmi_cmd_info_t *cmd_info;
812 } solparm_mc_unlock_t;
813 
814 static void
solparm_unlock_mc_done(ipmi_solparm_t * solparm,int err,void * cb_data)815 solparm_unlock_mc_done(ipmi_solparm_t *solparm, int err, void *cb_data)
816 {
817     solparm_mc_unlock_t *info = cb_data;
818     ipmi_cmd_info_t     *cmd_info = info->cmd_info;
819     ipmi_cmdlang_t      *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
820 
821     ipmi_cmdlang_lock(cmd_info);
822     if (err) {
823 	ipmi_solparm_get_name(solparm, cmdlang->objstr,
824 			  cmdlang->objstr_len);
825 	cmdlang->errstr = "Error unlocking MC SOLPARM";
826 	cmdlang->err = err;
827 	cmdlang->location = "cmd_solparm.c(solparm_unlock_mc_done)";
828 	goto out;
829     }
830 
831     ipmi_cmdlang_out(cmd_info, "SOLPARM unlocked", info->name);
832 
833  out:
834     ipmi_cmdlang_unlock(cmd_info);
835     ipmi_solparm_destroy(solparm, NULL, NULL);
836     ipmi_cmdlang_cmd_info_put(cmd_info);
837     ipmi_mem_free(info);
838 }
839 
840 static void
solparm_unlock_mc(ipmi_mc_t * mc,void * cb_data)841 solparm_unlock_mc(ipmi_mc_t *mc, void *cb_data)
842 {
843     ipmi_cmd_info_t *cmd_info = cb_data;
844     ipmi_cmdlang_t  *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
845     int             channel;
846     int             rv;
847     int             curr_arg = ipmi_cmdlang_get_curr_arg(cmd_info);
848     int             argc = ipmi_cmdlang_get_argc(cmd_info);
849     char            **argv = ipmi_cmdlang_get_argv(cmd_info);
850     ipmi_solparm_t  *solparm = NULL;
851     solparm_mc_unlock_t *info;
852 
853     if ((argc - curr_arg) < 1) {
854 	/* Not enough parameters */
855 	cmdlang->errstr = "Not enough parameters";
856 	cmdlang->err = EINVAL;
857 	goto out_err;
858     }
859 
860     ipmi_cmdlang_get_int(argv[curr_arg], &channel, cmd_info);
861     if (cmdlang->err) {
862 	cmdlang->errstr = "channel invalid";
863 	goto out_err;
864     }
865     curr_arg++;
866 
867     rv = ipmi_solparm_alloc(mc, channel, &solparm);
868     if (rv) {
869 	cmdlang->errstr = "Error from ipmi_solparm_alloc";
870 	cmdlang->err = rv;
871 	goto out_err;
872     }
873 
874     info = ipmi_mem_alloc(sizeof(*info));
875     if (!info) {
876 	cmdlang->errstr = "Out of memory";
877 	cmdlang->err = ENOMEM;
878 	goto out_err;
879     }
880     info->cmd_info = cmd_info;
881     ipmi_mc_get_name(mc, info->name, sizeof(info->name));
882 
883     ipmi_cmdlang_cmd_info_get(cmd_info);
884     rv = ipmi_sol_clear_lock(solparm, NULL, solparm_unlock_mc_done, info);
885     if (rv) {
886 	ipmi_cmdlang_cmd_info_put(cmd_info);
887 	cmdlang->errstr = "Error from ipmi_sol_clear_lock";
888 	cmdlang->err = rv;
889 	ipmi_solparm_destroy(solparm, NULL, NULL);
890 	ipmi_mem_free(info);
891 	goto out_err;
892     }
893     return;
894 
895  out_err:
896     if (solparm)
897 	ipmi_solparm_destroy(solparm, NULL, NULL);
898     ipmi_mc_get_name(mc, cmdlang->objstr,
899 		     cmdlang->objstr_len);
900     cmdlang->location = "cmd_solparm.c(solparm_unlock_mc)";
901 }
902 
903 static ipmi_cmdlang_cmd_t *solparm_cmds;
904 static ipmi_cmdlang_cmd_t *config_cmds;
905 
906 static ipmi_cmdlang_init_t cmds_solparm[] =
907 {
908     { "solparm", NULL,
909       "- Commands dealing with SOL Parameters (solparms)",
910       NULL, NULL, &solparm_cmds},
911     { "list", &solparm_cmds,
912       "- List all the solparms in the system",
913       ipmi_cmdlang_domain_handler, solparm_list,  NULL },
914     { "new", &solparm_cmds,
915       "<mc> <channel>"
916       " - Create a solparm for the given MC and channel.",
917       ipmi_cmdlang_mc_handler, solparm_new, NULL },
918     { "info", &solparm_cmds,
919       "<solparm> - Dump information about a solparm",
920       ipmi_cmdlang_solparm_handler, solparm_info, NULL },
921     { "config", &solparm_cmds,
922       "- Commands dealing with SOLPARM configs",
923       NULL, NULL, &config_cmds },
924     { "list", &config_cmds,
925       "- List the sol configurations that currently exist",
926       solparm_config_list, NULL, NULL },
927     { "info", &config_cmds,
928       "<config> - List info on sol configuration",
929       solparm_config_info, NULL, NULL },
930     { "get", &config_cmds,
931       "<solparm> - Fetch the SOL information for the solparm",
932       ipmi_cmdlang_solparm_handler, solparm_config_get, NULL },
933     { "set", &config_cmds,
934       "<solparm> <solparm config> - Set the SOL information for the solparm",
935       ipmi_cmdlang_solparm_handler, solparm_config_set, NULL },
936     { "unlock", &config_cmds,
937       "<solparm> <solparm config> - Unlock, but do not set the config",
938       ipmi_cmdlang_solparm_handler, solparm_config_unlock, NULL },
939     { "update", &config_cmds,
940       "<solparm config> <parm> [selector] <value> - Set the given parameter"
941       " in the solparm config to the given value.  If the parameter has"
942       " a selector of some type, the selector must be given, otherwise"
943       " no selector should be given.",
944       solparm_config_update, NULL, NULL },
945     { "close", &config_cmds,
946       "<solparm config> - free the config",
947       solparm_config_close, NULL, NULL },
948     { "unlock_mc", &solparm_cmds,
949       "<mc> <channel> - Unlock the solparms for the given mc/channel",
950       ipmi_cmdlang_mc_handler, solparm_unlock_mc, NULL },
951     { "close", &solparm_cmds,
952       "<solparm> - Close the solparm",
953       ipmi_cmdlang_solparm_handler, solparm_close, NULL },
954 };
955 #define CMDS_SOLPARM_LEN (sizeof(cmds_solparm)/sizeof(ipmi_cmdlang_init_t))
956 
957 int
ipmi_cmdlang_solparm_init(os_handler_t * os_hnd)958 ipmi_cmdlang_solparm_init(os_handler_t *os_hnd)
959 {
960     int rv;
961 
962     solcs = locked_list_alloc(os_hnd);
963     if (!solcs)
964 	return ENOMEM;
965 
966     rv = ipmi_cmdlang_reg_table(cmds_solparm, CMDS_SOLPARM_LEN);
967     if (rv) {
968 	locked_list_destroy(solcs);
969 	solcs = NULL;
970     }
971 
972     return rv;
973 }
974 
975 static int
config_destroy_handler(void * cb_data,void * item1,void * item2)976 config_destroy_handler(void *cb_data, void *item1, void *item2)
977 {
978     sol_config_info_t *info = item1;
979 
980     ipmi_sol_free_config(info->config);
981     ipmi_mem_free(info);
982     return LOCKED_LIST_ITER_CONTINUE;
983 }
984 
985 void
ipmi_cmdlang_solparm_shutdown(void)986 ipmi_cmdlang_solparm_shutdown(void)
987 {
988     locked_list_iterate(solcs, config_destroy_handler, NULL);
989     locked_list_destroy(solcs);
990     solcs = NULL;
991 }
992