~ubuntu-branches/ubuntu/saucy/nut/saucy

« back to all changes in this revision

Viewing changes to server/oldnet.c

  • Committer: Bazaar Package Importer
  • Author(s): Arnaud Quette
  • Date: 2004-05-28 13:10:01 UTC
  • mto: (16.1.1 squeeze)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20040528131001-yj2m9qcez4ya2w14
Tags: upstream-1.4.2
ImportĀ upstreamĀ versionĀ 1.4.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* oldnet.c - old network command handlers for upsd
 
2
 
 
3
   Copyright (C) 2003  Russell Kroll <rkroll@exploits.org>
 
4
 
 
5
   This program is free software; you can redistribute it and/or modify
 
6
   it under the terms of the GNU General Public License as published by
 
7
   the Free Software Foundation; either version 2 of the License, or
 
8
   (at your option) any later version.
 
9
 
 
10
   This program is distributed in the hope that it will be useful,
 
11
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
   GNU General Public License for more details.
 
14
 
 
15
   You should have received a copy of the GNU General Public License
 
16
   along with this program; if not, write to the Free Software
 
17
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
18
*/
 
19
 
 
20
#include "common.h"
 
21
#include "upsd.h"
 
22
#include "upstype.h"
 
23
#include "user.h"
 
24
#include "neterr.h"
 
25
 
 
26
#include "shared-tables.h"
 
27
#include "shared-tables-init.h"
 
28
 
 
29
#include "sstate.h"
 
30
#include "extstate.h"
 
31
#include "var-map.h"
 
32
#include "var-map-init.h"
 
33
#include "cmd-map.h"
 
34
#include "cmd-map-init.h"
 
35
 
 
36
/* everything in here is for compatibility with old clients */
 
37
 
 
38
        extern  upstype *firstups;
 
39
 
 
40
/* parse varname[@upsname] into separate variables */
 
41
upstype *parsearg(const char *arg, char **varname)
 
42
{
 
43
        char    *argtmp, *upsname;
 
44
        upstype *ups;
 
45
 
 
46
        argtmp = xstrdup(arg);
 
47
 
 
48
        upsname = strchr(argtmp, '@');
 
49
        if (upsname) {
 
50
                *upsname++ = '\0';
 
51
                ups = findups(upsname);
 
52
        } else {
 
53
                ups = firstups;
 
54
        }
 
55
 
 
56
        /* varname may be a subset of argtmp, so copy it and free argtmp */
 
57
        *varname = xstrdup(argtmp);
 
58
        free(argtmp);
 
59
 
 
60
        return ups;
 
61
}
 
62
 
 
63
static const char *oldvar_to_new(const char *old)
 
64
{
 
65
        int     i, type = 0;
 
66
        static  char    temphex[8];
 
67
 
 
68
        /* first look up the type number in netvars */
 
69
        for (i = 0; netvars[i].name != NULL; i++)
 
70
                if (!strcasecmp(netvars[i].name, old))
 
71
                        type = netvars[i].type;
 
72
 
 
73
        if (!type)
 
74
                return NULL;
 
75
 
 
76
        for (i = 0; var_map[i].type != 0; i++)
 
77
                if (var_map[i].type == type)
 
78
                        return var_map[i].name;
 
79
 
 
80
        /* not there - convert to the hex hack for now */
 
81
        snprintf(temphex, sizeof(temphex), "%04X", type);
 
82
        return temphex;
 
83
}
 
84
 
 
85
static const char *oldcmd_to_new(const char *old)
 
86
{
 
87
        int     i, cmd = 0;
 
88
        static  char    temphex[8];
 
89
 
 
90
        /* first look up the type number in instcmds[] */
 
91
        for (i = 0; instcmds[i].name != NULL; i++)
 
92
                if (!strcasecmp(instcmds[i].name, old))
 
93
                        cmd = instcmds[i].cmd;
 
94
 
 
95
        if (!cmd)
 
96
                return NULL;
 
97
 
 
98
        for (i = 0; cmd_map[i].cmd != 0; i++)
 
99
                if (cmd_map[i].cmd == cmd)
 
100
                        return cmd_map[i].name;
 
101
 
 
102
        /* not there - convert to the hex hack for now */
 
103
        snprintf(temphex, sizeof(temphex), "%04X", cmd);
 
104
        return temphex;
 
105
}
 
106
 
 
107
/* handler for "REQ" - send a reply */
 
108
void do_sendans(ctype *client, char *varin, char *rest)
 
109
{
 
110
        char    *varname;
 
111
        upstype *ups;
 
112
 
 
113
        const   char    *tempvar, *tempval;
 
114
 
 
115
        if (varin == NULL) {
 
116
                send_err(client, NUT_ERR_MISSING_ARGUMENT);
 
117
                return;
 
118
        }
 
119
 
 
120
        ups = parsearg(varin, &varname);
 
121
 
 
122
        if (ups == NULL) {
 
123
                send_err(client, NUT_ERR_UNKNOWN_UPS);
 
124
                free(varname);
 
125
                return;
 
126
        }
 
127
 
 
128
        /* special case: numlogins is an internal value */
 
129
        if (!strcasecmp(varname, "NUMLOGINS")) {
 
130
                sendback(client, "ANS %s %d\n", varname, ups->numlogins);
 
131
                free(varname);
 
132
                return;
 
133
        }
 
134
 
 
135
        /* make sure this thing is still with us */
 
136
        if (!ups_available(ups, client)) {
 
137
                free(varname);
 
138
                return;
 
139
        }
 
140
 
 
141
        tempvar = oldvar_to_new(varname);
 
142
        free(varname);
 
143
        
 
144
        /* type wasn't resolved in the netvars[] array */
 
145
        if (!tempvar) {
 
146
                send_err(client, NUT_ERR_VAR_UNKNOWN);
 
147
                return;
 
148
        }
 
149
 
 
150
        /* make sure this thing is still with us */
 
151
        if (!ups_available(ups, client))
 
152
                return;
 
153
 
 
154
        tempval = sstate_getinfo(ups, tempvar, 1);
 
155
 
 
156
        if (!tempval) {
 
157
                send_err(client, NUT_ERR_VAR_NOT_SUPPORTED);
 
158
                return;
 
159
        }
 
160
 
 
161
        /* special case - make FSD show up in STATUS */
 
162
        if (!strcasecmp(tempvar, "ups.status") && (ups->fsd == 1)) 
 
163
                sendback(client, "ANS %s FSD %s\n", varin, tempval);
 
164
        else
 
165
                sendback(client, "ANS %s %s\n", varin, tempval);
 
166
}
 
167
 
 
168
/* handler for "LISTVARS" */
 
169
void do_listvars(ctype *client, char *arg, char *rest)
 
170
{
 
171
        char    ans[SMALLBUF];
 
172
        upstype *ups;
 
173
 
 
174
        ups = findups(arg);
 
175
 
 
176
        if (ups == NULL) {
 
177
                send_err(client, NUT_ERR_UNKNOWN_UPS);
 
178
                return;
 
179
        }
 
180
 
 
181
        /* make sure this thing is still with us */
 
182
        if (!ups_available(ups, client))
 
183
                return;
 
184
 
 
185
        memset(ans, '\0', sizeof(ans));
 
186
 
 
187
        /* insert "@upsname" if explicitly specified in request */
 
188
        if ((arg) && (strcmp(arg, "") != 0))
 
189
                snprintf(ans, sizeof(ans), " @%s", arg);
 
190
 
 
191
        sstate_makeinfolist(ups, ans, sizeof(ans));
 
192
 
 
193
        sendback(client, "VARS%s\n", ans);
 
194
}
 
195
 
 
196
/* handler for "LISTRW" */
 
197
void do_listrw(ctype *client, char *arg, char *rest)
 
198
{
 
199
        char    ans[SMALLBUF];
 
200
        upstype *ups;
 
201
 
 
202
        ups = findups(arg);
 
203
 
 
204
        if (ups == NULL) {
 
205
                send_err(client, NUT_ERR_UNKNOWN_UPS);
 
206
                return;
 
207
        }
 
208
 
 
209
        /* make sure this thing is still with us */
 
210
        if (!ups_available(ups, client))
 
211
                return;
 
212
 
 
213
        ans[0] = '\0';
 
214
 
 
215
        /* insert "@upsname" if explicitly specified in request */
 
216
        if ((arg) && (strcmp(arg, "") != 0)) {
 
217
                snprintfcat(ans, sizeof(ans), " @%s", arg);
 
218
        }               
 
219
 
 
220
        sstate_makerwlist(ups, ans, sizeof(ans));
 
221
 
 
222
        sendback(client, "RW%s\n", ans);
 
223
}
 
224
 
 
225
/* handler for "VARTYPE" */
 
226
void do_vartype(ctype *client, char *arg, char *rest)
 
227
{
 
228
        char    *varname;
 
229
        upstype *ups;
 
230
 
 
231
        const   char    *tempvar;
 
232
        int     flags, ecount;
 
233
        const   struct  enum_t  *etmp;
 
234
 
 
235
        if (arg == NULL) {
 
236
                send_err(client, NUT_ERR_MISSING_ARGUMENT);
 
237
                return;
 
238
        }
 
239
 
 
240
        ups = parsearg(arg, &varname);
 
241
 
 
242
        if (ups == NULL) {
 
243
                send_err(client, NUT_ERR_UNKNOWN_UPS);
 
244
                free(varname);
 
245
                return;
 
246
        }
 
247
 
 
248
        tempvar = oldvar_to_new(varname);
 
249
        free(varname);
 
250
 
 
251
        if (!tempvar) {
 
252
                send_err(client, NUT_ERR_VAR_UNKNOWN);
 
253
                return;
 
254
        }
 
255
 
 
256
        flags = sstate_getflags(ups, tempvar);
 
257
 
 
258
        /* see if this variable even exists */
 
259
        if (flags == -1) {
 
260
                send_err(client, NUT_ERR_VAR_NOT_SUPPORTED);
 
261
                return;
 
262
        }
 
263
 
 
264
        /* maybe it's a string */
 
265
        if (flags & ST_FLAG_STRING) {
 
266
                sendback(client, "TYPE STRING %d\n", sstate_getaux(ups, tempvar));
 
267
                return;
 
268
        }
 
269
 
 
270
        /* maybe it's an enum */
 
271
        etmp = sstate_getenumlist(ups, tempvar);
 
272
 
 
273
        ecount = 0;
 
274
        while (etmp) {
 
275
                ecount++;
 
276
                etmp = etmp->next;
 
277
        }
 
278
 
 
279
        if (ecount) {
 
280
                sendback(client, "TYPE ENUM %d\n", ecount);
 
281
                return;
 
282
        }
 
283
 
 
284
        /* unknown */
 
285
        send_err(client, NUT_ERR_UNKNOWN_TYPE);
 
286
}
 
287
 
 
288
/* handler for "VARDESC" */
 
289
void do_vardesc(ctype *client, char *arg, char *rest)
 
290
{
 
291
        int     i;
 
292
 
 
293
        /* find the variable type for the name */
 
294
        for (i = 0; netvars[i].name != NULL; i++) {
 
295
                if (!strcasecmp(netvars[i].name, arg)) {
 
296
                        sendback(client, "DESC \"%s\"\n", netvars[i].desc);
 
297
                        return;
 
298
                }
 
299
        }
 
300
 
 
301
        send_err(client, NUT_ERR_VAR_NOT_SUPPORTED);
 
302
}
 
303
 
 
304
/* handler for "ENUM" */
 
305
void do_enum(ctype *client, char *arg, char *rest)
 
306
{
 
307
        char    *varname;
 
308
        int     i, type;
 
309
        upstype *ups;
 
310
 
 
311
        const   char    *tempvar, *tempval;
 
312
        const   struct  enum_t  *etmp;
 
313
 
 
314
        if (arg == NULL) {
 
315
                send_err(client, NUT_ERR_MISSING_ARGUMENT);
 
316
                return;
 
317
        }
 
318
 
 
319
        ups = parsearg(arg, &varname);
 
320
 
 
321
        if (ups == NULL) {
 
322
                send_err(client, NUT_ERR_UNKNOWN_UPS);
 
323
                free(varname);
 
324
                return;
 
325
        }
 
326
 
 
327
        type = 0;
 
328
 
 
329
        /* find the variable type for the name */
 
330
        for (i = 0; netvars[i].name != NULL; i++)
 
331
                if (!strcasecmp(netvars[i].name, varname))
 
332
                        type = netvars[i].type;
 
333
 
 
334
        if (type == 0) {        /* didn't find it */
 
335
                send_err(client, NUT_ERR_UNKNOWN_TYPE);
 
336
                free(varname);
 
337
                return;
 
338
        }
 
339
 
 
340
        tempvar = oldvar_to_new(varname);
 
341
        free(varname);
 
342
 
 
343
        if (!tempvar) {
 
344
                send_err(client, NUT_ERR_VAR_NOT_SUPPORTED);
 
345
                return;
 
346
        }
 
347
 
 
348
        /* see if this variable even exists first */
 
349
        tempval = sstate_getinfo(ups, tempvar, 1);
 
350
 
 
351
        if (!tempval) {
 
352
                send_err(client, NUT_ERR_VAR_NOT_SUPPORTED);
 
353
                return;
 
354
        }
 
355
 
 
356
        /* bail out here if the write fails */
 
357
        if (!sendback(client, "ENUM %s\n", varname))
 
358
                return;
 
359
 
 
360
        etmp = sstate_getenumlist(ups, tempvar);
 
361
 
 
362
        while (etmp) {
 
363
                char    resp[SMALLBUF];
 
364
 
 
365
                if (!strcmp(etmp->val, tempval))
 
366
                        snprintf(resp, sizeof(resp), "OPTION \"%s\" SELECTED",
 
367
                                etmp->val);
 
368
                else
 
369
                        snprintf(resp, sizeof(resp), "OPTION \"%s\"",
 
370
                                etmp->val);
 
371
 
 
372
                if (!sendback(client, "%s\n", resp))
 
373
                        return;
 
374
 
 
375
                etmp = etmp->next;
 
376
        }
 
377
 
 
378
        sendback(client, "END\n");
 
379
}
 
380
 
 
381
/* handler for "SET" */
 
382
void do_set(ctype *client, char *arg, char *rest)
 
383
{
 
384
        char    *newval, *varname, *ptr;
 
385
        upstype *ups;
 
386
        int     i, type, found;
 
387
 
 
388
        char    cmd[SMALLBUF], esc[SMALLBUF];
 
389
        const   char    *tempvar, *tempval;
 
390
        const   struct  enum_t  *etmp;
 
391
 
 
392
        if ((arg == NULL) || (rest == NULL)) {
 
393
                send_err(client, NUT_ERR_MISSING_ARGUMENT);
 
394
                return;
 
395
        }
 
396
 
 
397
        ups = parsearg(arg, &varname);
 
398
 
 
399
        if (ups == NULL) {
 
400
                send_err(client, NUT_ERR_UNKNOWN_UPS);
 
401
                free(varname);
 
402
                return;
 
403
        }
 
404
 
 
405
        type = 0;
 
406
        /* make sure 'varname' is part of the protocol as we know it */
 
407
        for (i = 0; netvars[i].name != NULL; i++)
 
408
                if (!strcasecmp(netvars[i].name, varname))
 
409
                        type = netvars[i].type;
 
410
        
 
411
        /* type wasn't resolved in the netvars[] array */
 
412
        if (type == 0) {
 
413
                send_err(client, NUT_ERR_VAR_UNKNOWN);
 
414
                free(varname);
 
415
                return;
 
416
        }
 
417
 
 
418
        /* make sure this thing is still with us */
 
419
        if (!ups_available(ups, client)) {
 
420
                free(varname);
 
421
                return;
 
422
        }
 
423
 
 
424
        tempvar = oldvar_to_new(varname);
 
425
        free(varname);
 
426
        
 
427
        /* not resolved in netvars[] */
 
428
        if (!tempvar) {
 
429
                send_err(client, NUT_ERR_VAR_UNKNOWN);
 
430
                return;
 
431
        }
 
432
 
 
433
        /* see if this UPS supports that variable */
 
434
        tempval = sstate_getinfo(ups, tempvar, 1);
 
435
 
 
436
        if (!tempval) {
 
437
                send_err(client, NUT_ERR_VAR_NOT_SUPPORTED);
 
438
                return;
 
439
        }
 
440
 
 
441
        /* make sure this variable is writable (RW) */
 
442
        if ((sstate_getflags(ups, tempvar) & ST_FLAG_RW) == 0) {
 
443
                send_err(client, NUT_ERR_READONLY);
 
444
                return;
 
445
        }
 
446
 
 
447
        /* clean up rest into something usable */
 
448
        newval = xstrdup(rest);
 
449
 
 
450
        ptr = strchr(newval, 13);
 
451
        if (ptr)
 
452
                *ptr = '\0';    /* strip trailing CR */
 
453
 
 
454
        ptr = strchr(newval, 10);
 
455
        if (ptr)
 
456
                *ptr = '\0';    /* strip trailing LF */
 
457
 
 
458
        /* finally, see if the new value is allowed for this variable */
 
459
 
 
460
        /* check the length if this is for a string */
 
461
        if (sstate_getflags(ups, tempvar) & ST_FLAG_STRING) {
 
462
                if (strlen(newval) > sstate_getaux(ups, tempvar)) {
 
463
                        send_err(client, NUT_ERR_TOO_LONG);
 
464
                        free(newval);
 
465
                        return;
 
466
                }
 
467
        }
 
468
 
 
469
        /* see if it's enumerated */
 
470
        etmp = sstate_getenumlist(ups, tempvar);
 
471
 
 
472
        if (etmp) {
 
473
                found = 0;
 
474
 
 
475
                /* make sure this value is supported */
 
476
 
 
477
                while (etmp) {
 
478
                        if (!strcmp(etmp->val, newval)) {
 
479
                                found = 1;
 
480
                                break;
 
481
                        }
 
482
 
 
483
                        etmp = etmp->next;
 
484
                }
 
485
 
 
486
                if (!found) {
 
487
                        send_err(client, NUT_ERR_INVALID_VALUE);
 
488
                        free(newval);
 
489
                        return;
 
490
                }
 
491
        }
 
492
        
 
493
        upslogx(LOG_INFO, "Set variable: %s@%s set %s on %s to %s",
 
494
               client->username, client->addr, varname, ups->name, 
 
495
               newval);
 
496
 
 
497
        snprintf(cmd, sizeof(cmd), "SET %s \"%s\"\n",
 
498
                tempvar, pconf_encode(newval, esc, sizeof(esc)));
 
499
 
 
500
        free(newval);
 
501
 
 
502
        if (!sstate_sendline(ups, cmd)) {
 
503
                upslogx(LOG_INFO, "Set command send failed");
 
504
                send_err(client, NUT_ERR_SET_FAILED);
 
505
                return;
 
506
        }
 
507
 
 
508
        sendback(client, "OK\n");
 
509
}
 
510
 
 
511
/* handler for "INSTCMD" */
 
512
void do_instcmd(ctype *client, char *arg, char *rest)
 
513
{
 
514
        char    *cmdname;
 
515
        upstype *ups;
 
516
        int     found;
 
517
 
 
518
        char    sockcmd[SMALLBUF];
 
519
        const   char    *tempcn;
 
520
        const   struct  cmdlist_t       *ctmp;
 
521
 
 
522
        if (!arg) {
 
523
                send_err(client, NUT_ERR_MISSING_ARGUMENT);
 
524
                return;
 
525
        }               
 
526
 
 
527
        ups = parsearg(arg, &cmdname);
 
528
 
 
529
        if (ups == NULL) {
 
530
                send_err(client, NUT_ERR_UNKNOWN_UPS);
 
531
                free(cmdname);
 
532
                return;
 
533
        }
 
534
 
 
535
        tempcn = oldcmd_to_new(cmdname);
 
536
        free(cmdname);
 
537
 
 
538
        if (!tempcn) {
 
539
                send_err(client, NUT_ERR_UNKNOWN_INSTCMD);
 
540
                return;
 
541
        }
 
542
 
 
543
        /* now make sure the UPS can actually DO this command */
 
544
 
 
545
        ctmp = sstate_getcmdlist(ups);
 
546
 
 
547
        found = 0;
 
548
        while (ctmp) {
 
549
                if (!strcasecmp(ctmp->name, tempcn)) {
 
550
                        found = 1;
 
551
                        break;
 
552
                }
 
553
 
 
554
                ctmp = ctmp->next;
 
555
        }
 
556
 
 
557
        if (!found) {
 
558
                send_err(client, NUT_ERR_CMD_NOT_SUPPORTED);
 
559
                return;
 
560
        }
 
561
 
 
562
        /* see if this user is allowed to do this command */
 
563
        if (!user_checkinstcmd(&client->sock, client->username, 
 
564
                client->password, tempcn)) {
 
565
                send_err(client, NUT_ERR_ACCESS_DENIED);
 
566
                return;
 
567
        }
 
568
 
 
569
        upslogx(LOG_INFO, "Instant command: %s@%s did %s on %s",
 
570
               client->username, client->addr, cmdname, 
 
571
               ups->name);
 
572
 
 
573
        snprintf(sockcmd, sizeof(sockcmd), "INSTCMD %s\n", tempcn);
 
574
 
 
575
        if (!sstate_sendline(ups, sockcmd)) {
 
576
                upslogx(LOG_INFO, "Set command send failed");
 
577
                send_err(client, NUT_ERR_INSTCMD_FAILED);
 
578
                return;
 
579
        }
 
580
 
 
581
        sendback(client, "OK\n");
 
582
}
 
583
 
 
584
/* handler for "LISTINSTCMD" */
 
585
void do_listinstcmd(ctype *client, char *arg, char *rest)
 
586
{
 
587
        char    ans[SMALLBUF];
 
588
        upstype *ups;
 
589
 
 
590
        ups = findups(arg);
 
591
 
 
592
        if (ups == NULL) {
 
593
                send_err(client, NUT_ERR_UNKNOWN_UPS);
 
594
                return;
 
595
        }
 
596
 
 
597
        /* make sure this thing is still with us */
 
598
        if (!ups_available(ups, client))
 
599
                return;
 
600
 
 
601
        ans[0] = '\0';
 
602
 
 
603
        /* insert "@upsname" if explicitly specified in request */
 
604
        if ((arg) && (strcmp(arg, "") != 0))
 
605
                snprintfcat(ans, sizeof(ans), " @%s", arg); 
 
606
 
 
607
        sstate_makeinstcmdlist(ups, ans, sizeof(ans));
 
608
 
 
609
        sendback(client, "INSTCMDS%s\n", ans);
 
610
}
 
611
 
 
612
/* handler for "INSTCMDDESC" */
 
613
void do_instcmddesc(ctype *client, char *arg, char *rest)
 
614
{
 
615
        int     i;
 
616
 
 
617
        if (arg == NULL) {
 
618
                send_err(client, NUT_ERR_MISSING_ARGUMENT);
 
619
                return;
 
620
        }
 
621
 
 
622
        /* find the variable type for the name */
 
623
        for (i = 0; instcmds[i].name != NULL; i++) {
 
624
                if (!strcasecmp(instcmds[i].name, arg)) {
 
625
                        sendback(client, "DESC \"%s\"\n", instcmds[i].desc);
 
626
                        return;
 
627
                }
 
628
        }
 
629
 
 
630
        send_err(client, NUT_ERR_CMD_NOT_SUPPORTED);
 
631
}