]> git.ipfire.org Git - thirdparty/lldpd.git/blame - src/lldpctl.c
Update ISC license wording.
[thirdparty/lldpd.git] / src / lldpctl.c
CommitLineData
43c02e7b
VB
1/*
2 * Copyright (c) 2008 Vincent Bernat <bernat@luffy.cx>
3 *
51434125 4 * Permission to use, copy, modify, and/or distribute this software for any
43c02e7b
VB
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include "lldpd.h"
18
19#include <stdio.h>
20#include <unistd.h>
fa835fd5 21#include <time.h>
43c02e7b
VB
22#include <errno.h>
23#include <sys/types.h>
24#include <sys/socket.h>
25#include <sys/un.h>
26#include <arpa/inet.h>
27
8888d191 28static void usage(void);
43c02e7b
VB
29
30TAILQ_HEAD(interfaces, lldpd_interface);
650cae58 31
6bb9c4e0
VB
32#ifdef HAVE___PROGNAME
33extern const char *__progname;
34#else
35# define __progname "lldpctl"
36#endif
37
2e1ea850
AH
38extern void
39get_interfaces(int s, struct interfaces *ifs);
650cae58 40
2e1ea850 41extern void
1480ce74 42display_interfaces(int s, const char * fmt, int argc, char *argv[]);
43c02e7b 43
42ee7382 44#define LLDPCTL_ARGS "hdf:L:P:O:o:"
b258db58 45
8888d191 46static void
43c02e7b
VB
47usage(void)
48{
53132616
VB
49 fprintf(stderr, "Usage: %s [OPTIONS ...] [INTERFACES ...]\n", __progname);
50
51 fprintf(stderr, "\n");
52
53 fprintf(stderr, "-d Enable more debugging information.\n");
999509a3 54 fprintf(stderr, "-f format Choose output format (plain, keyvalue or xml).\n");
8347587d 55#ifdef ENABLE_LLDPMED
53132616
VB
56 fprintf(stderr, "-L location Enable the transmission of LLDP-MED location TLV for the\n");
57 fprintf(stderr, " given interfaces. Can be repeated to enable the transmission\n");
58 fprintf(stderr, " of the location in several formats.\n");
86f24df3
VB
59 fprintf(stderr, "-P policy Enable the transmission of LLDP-MED Network Policy TLVs\n");
60 fprintf(stderr, " for the given interfaces. Can be repeated to specify\n");
61 fprintf(stderr, " different policies.\n");
009ddd23
VB
62 fprintf(stderr, "-O poe Enable the trabsmission of LLDP-MED POE-MDI TLV\n");
63 fprintf(stderr, " for the given interfaces.\n");
8347587d 64#endif
42ee7382
VB
65#ifdef ENABLE_DOT3
66 fprintf(stderr, "-o poe Enable the trabsmission of Dot3 POE-MDI TLV\n");
67 fprintf(stderr, " for the given interfaces.\n");
68#endif
53132616
VB
69
70 fprintf(stderr, "\n");
71
740593ff 72 fprintf(stderr, "see manual page lldpctl(8) for more information\n");
43c02e7b
VB
73 exit(1);
74}
75
740593ff 76#ifdef ENABLE_LLDPMED
8888d191 77static int
740593ff
VB
78lldpd_parse_location(struct lldpd_port *port, const char *location)
79{
80 char *l, *e, *s, *data, *n;
81 double ll, altitude;
82 u_int32_t intpart, floatpart;
83 int type = 0, i;
84
85 if (strlen(location) == 0)
86 return 0;
87 if ((l = strdup(location)) == NULL)
88 fatal(NULL);
89 s = l;
f0bd3505 90 if ((e = strchr(s, ':')) == NULL)
740593ff
VB
91 goto invalid_location;
92 *e = '\0';
93 type = atoi(s);
94 switch (type) {
95 case LLDPMED_LOCFORMAT_COORD:
96 /* Coordinates */
97 if ((port->p_med_location[0].data =
98 (char *)malloc(16)) == NULL)
99 fatal(NULL);
100 port->p_med_location[0].data_len = 16;
101 port->p_med_location[0].format = LLDPMED_LOCFORMAT_COORD;
102 data = port->p_med_location[0].data;
103
104 /* Latitude and longitude */
105 for (i = 0; i < 2; i++) {
106 s = e+1;
f0bd3505 107 if ((e = strchr(s, ':')) == NULL)
740593ff
VB
108 goto invalid_location;
109 *e = '\0';
110 ll = atof(s);
111 s = e + 1;
f0bd3505 112 if ((e = strchr(s, ':')) == NULL)
740593ff
VB
113 goto invalid_location;
114 *e = '\0';
115 intpart = (int)ll;
116 floatpart = (ll - intpart) * (1 << 25);
117 if (((i == 0) && (*s == 'S')) ||
118 ((i == 1) && (*s == 'W'))) {
119 intpart = ~intpart;
120 intpart += 1;
121 floatpart = ~floatpart;
122 floatpart += 1;
123 } else if (((i == 0) && (*s != 'N')) ||
124 ((i == 1) && (*s != 'E')))
125 goto invalid_location;
126 *(u_int8_t *)data = (6 << 2) | /* Precision */
127 ((intpart & 0x180) >> 7); /* Int part 2 bits */
128 data++;
129 *(u_int8_t *)data = (((intpart & 0x7f) << 1) | /* Int part 7 bits */
130 ((floatpart & 0x1000000) >> 24)); /* Float part 1 bit */
131 data++;
132 *(u_int8_t *)data = (floatpart & 0xff0000) >> 16; /* 8 bits */
133 data++;
134 *(u_int8_t *)data = (floatpart & 0xff00) >> 8; /* 8 bits */
135 data++;
136 *(u_int8_t *)data = (floatpart & 0xff); /* 8 bits */
137 data++;
138 }
139
140 /* Altitude */
141 s = e+1;
f0bd3505 142 if ((e = strchr(s, ':')) == NULL)
740593ff
VB
143 goto invalid_location;
144 *e = '\0';
145 altitude = atof(s);
146 s = e+1;
f0bd3505 147 if ((e = strchr(s, ':')) == NULL)
740593ff
VB
148 goto invalid_location;
149 *e = '\0';
150 if (altitude < 0) {
151 intpart = -(int)altitude;
152 floatpart = (-(altitude + intpart)) * (1 << 8);
153 intpart = ~intpart; intpart += 1;
154 floatpart = ~floatpart; floatpart += 1;
155 } else {
156 intpart = (int)altitude;
157 floatpart = (altitude - intpart) * (1 << 8);
158 }
159 if ((*s != 'm') && (*s != 'f'))
160 goto invalid_location;
161 *(u_int8_t *)data = ((((*s == 'm')?1:2) << 4) | /* Type 4 bits */
162 0); /* Precision 4 bits */
163 data++;
164 *(u_int8_t *)data = ((6 << 6) | /* Precision 2 bits */
165 ((intpart & 0x3f0000) >> 16)); /* Int 6 bits */
166 data++;
167 *(u_int8_t *)data = (intpart & 0xff00) >> 8; /* Int 8 bits */
168 data++;
169 *(u_int8_t *)data = intpart & 0xff; /* Int 8 bits */
170 data++;
171 *(u_int8_t *)data = floatpart & 0xff; /* Float 8 bits */
172 data++;
173
174 /* Datum */
175 s = e + 1;
f0bd3505 176 if (strchr(s, ':') != NULL)
740593ff
VB
177 goto invalid_location;
178 *(u_int8_t *)data = atoi(s);
179 break;
180 case LLDPMED_LOCFORMAT_CIVIC:
181 /* Civic address */
182 port->p_med_location[1].data_len = 4;
183 s = e+1;
f0bd3505 184 if ((s = strchr(s, ':')) == NULL)
740593ff
VB
185 goto invalid_location;
186 s = s+1;
187 do {
f0bd3505 188 if ((s = strchr(s, ':')) == NULL)
740593ff
VB
189 break;
190 s = s+1;
191 /* s is the beginning of the word */
f0bd3505 192 if ((n = strchr(s, ':')) == NULL)
740593ff
VB
193 n = s + strlen(s);
194 /* n is the end of the word */
195 port->p_med_location[1].data_len += (n - s) + 2;
f0bd3505 196 if ((s = strchr(s, ':')) == NULL)
740593ff
VB
197 break;
198 s = s+1;
199 } while (1);
200 s = e+1;
201 if ((port->p_med_location[1].data =
202 (char *)malloc(port->p_med_location[1].data_len)) ==
203 NULL)
204 fatal(NULL);
205 port->p_med_location[1].format = LLDPMED_LOCFORMAT_CIVIC;
206 data = port->p_med_location[1].data;
207 *(u_int8_t *)data = port->p_med_location[1].data_len - 1;
208 data++;
209 *(u_int8_t *)data = 2; /* Client location */
210 data++;
f0bd3505 211 if ((e = strchr(s, ':')) == NULL)
740593ff
VB
212 goto invalid_location;
213 if ((e - s) != 2)
214 goto invalid_location;
215 memcpy(data, s, 2); /* Country code */
216 data += 2;
217 while (*e != '\0') {
218 s=e+1;
f0bd3505 219 if ((e = strchr(s, ':')) == NULL)
740593ff
VB
220 goto invalid_location;
221 *e = '\0';
222 *(u_int8_t *)data = atoi(s);
223 data++;
224 s=e+1;
f0bd3505 225 if ((e = strchr(s, ':')) == NULL)
740593ff
VB
226 e = s + strlen(s);
227 *(u_int8_t *)data = e - s;
228 data++;
229 memcpy(data, s, e-s);
230 data += e-s;
231 }
232 break;
233 case LLDPMED_LOCFORMAT_ELIN:
234 s = e+1;
235 port->p_med_location[2].data_len = strlen(s);
236 if ((port->p_med_location[2].data =
237 (char *)malloc(strlen(s))) == NULL)
238 fatal(NULL);
239 port->p_med_location[2].format = LLDPMED_LOCFORMAT_ELIN;
240 strcpy(port->p_med_location[2].data, s);
241 break;
242 default:
243 type = 0;
244 goto invalid_location;
245 }
246
247 port->p_med_cap_enabled |= LLDPMED_CAP_LOCATION;
248 return 0;
249invalid_location:
250 LLOG_WARNX("the format of the location is invalid (%s)",
251 location);
252 if (type) {
253 free(port->p_med_location[type-1].data);
254 memset(&port->p_med_location[type-1], 0,
255 sizeof(struct lldpd_med_loc));
256 }
257 free(l);
258 return -1;
259}
260
86f24df3
VB
261static int
262lldpd_parse_policy(struct lldpd_port *port, const char *policy)
263{
264 const char *e;
265 int app_type = 0;
266 int unknown_policy_flag = 0;
267 int tagged_flag = 0;
268 int vlan_id = 0;
269 int l2_prio = 0;
270 int dscp = 0;
271
272 if (strlen(policy) == 0) {
273 return 0;
274 }
275
276 e = policy;
277
278 /* Application Type: */
279 app_type = atoi(e);
280 if (app_type < 1 || app_type > LLDPMED_APPTYPE_LAST) {
281 LLOG_WARNX("Application Type (%u) out of range.", app_type);
282 goto invalid_policy;
283 }
284
285 /* Unknown Policy Flag (U): */
286 if ((e = strchr(e, ':')) == NULL) {
287 LLOG_WARNX("Expected Unknown Policy Flag (U).");
288 goto invalid_policy;
289 }
290 e = e + 1;
291 unknown_policy_flag = atoi(e);
292 if (unknown_policy_flag < 0 || unknown_policy_flag > 1) {
293 LLOG_WARNX("Unknown Policy Flag (%u) out of range.", unknown_policy_flag);
294 goto invalid_policy;
295 }
296
297 /* Tagged Flag (T): */
298 if ((e = strchr(e, ':')) == NULL) {
299 LLOG_WARNX("Expected Tagged Flag (T).");
300 goto invalid_policy;
301 }
302 e = e + 1;
303 tagged_flag = atoi(e);
304 if (tagged_flag < 0 || tagged_flag > 1) {
305 LLOG_WARNX("Tagged Flag (%u) out of range.", tagged_flag);
306 goto invalid_policy;
307 }
308
309 /* VLAN-ID (VID): */
310 if ((e = strchr(e, ':')) == NULL) {
311 LLOG_WARNX("Expected VLAN ID (VID).");
312 goto invalid_policy;
313 }
314 e = e + 1;
315 vlan_id = atoi(e);
316 if (vlan_id < 0 || vlan_id > 4094) {
317 LLOG_WARNX("VLAN ID (%u) out of range.", vlan_id);
318 goto invalid_policy;
319 }
320
321 /* Layer 2 Priority: */
322 if ((e = strchr(e, ':')) == NULL) {
323 LLOG_WARNX("Expected Layer 2 Priority.");
324 goto invalid_policy;
325 }
326 e = e + 1;
327 l2_prio = atoi(e);
328 if (l2_prio < 0 || l2_prio > 7) {
329 LLOG_WARNX("Layer 2 Priority (%u) out of range.", l2_prio);
330 goto invalid_policy;
331 }
332
333 /* DSCP value: */
334 if ((e = strchr(e, ':')) == NULL) {
335 LLOG_WARNX("Expected DSCP value.");
336 goto invalid_policy;
337 }
338 e = e + 1;
339 dscp = atoi(e);
340 if (dscp < 0 || dscp > 63) {
341 LLOG_WARNX("DSCP value (%u) out of range.", dscp);
342 goto invalid_policy;
343 }
344
345 port->p_med_policy[app_type - 1].type = (u_int8_t) app_type;
346 port->p_med_policy[app_type - 1].unknown = (u_int8_t) unknown_policy_flag;
347 port->p_med_policy[app_type - 1].tagged = (u_int8_t) tagged_flag;
348 port->p_med_policy[app_type - 1].vid = (u_int16_t) vlan_id;
349 port->p_med_policy[app_type - 1].priority = (u_int8_t) l2_prio;
350 port->p_med_policy[app_type - 1].dscp = (u_int8_t) dscp;
351
352 port->p_med_cap_enabled |= LLDPMED_CAP_POLICY;
353 return 0;
354
355invalid_policy:
356 LLOG_WARNX("The format of the policy is invalid (%s)",
357 policy);
358 return -1;
359}
360
009ddd23
VB
361static int
362lldpd_parse_power(struct lldpd_port *port, const char *poe)
363{
364 const char *e;
365 int device_type = 0;
366 int source = 0;
367 int priority = 0;
368 int val = 0;
369
370 if (strlen(poe) == 0)
371 return 0;
372 e = poe;
373
374 /* Device type */
375 if (!strncmp(e, "PD", 2))
376 device_type = LLDPMED_POW_TYPE_PD;
377 else if (!strncmp(e, "PSE", 3))
378 device_type = LLDPMED_POW_TYPE_PSE;
379 else {
380 LLOG_WARNX("Device type should be either 'PD' or 'PSE'.");
381 goto invalid_poe;
382 }
383
384 /* Source */
385 if ((e = strchr(e, ':')) == NULL) {
386 LLOG_WARNX("Expected power source.");
387 goto invalid_poe;
388 }
389 source = atoi(++e);
390 if (source < 0 || source > 3) {
391 LLOG_WARNX("Power source out of range (%d).", source);
392 goto invalid_poe;
393 }
394
395 /* Priority */
396 if ((e = strchr(e, ':')) == NULL) {
397 LLOG_WARNX("Expected power priority.");
398 goto invalid_poe;
399 }
400 priority = atoi(++e);
401 if (priority < 0 || priority > 3) {
402 LLOG_WARNX("Power priority out of range (%d).", priority);
403 goto invalid_poe;
404 }
405
406 /* Value */
407 if ((e = strchr(e, ':')) == NULL) {
408 LLOG_WARNX("Expected power value.");
409 goto invalid_poe;
410 }
411 val = atoi(++e);
412 if (val < 0 || val > 1023) {
413 LLOG_WARNX("Power value out of range (%d).", val);
414 goto invalid_poe;
415 }
416
417 port->p_med_power.devicetype = device_type;
418 port->p_med_power.priority = priority;
419 port->p_med_power.val = val;
420
421 switch (device_type) {
422 case LLDPMED_POW_TYPE_PD:
423 switch (source) {
424 case 1:
425 port->p_med_power.source = LLDPMED_POW_SOURCE_PSE;
426 break;
427 case 2:
428 port->p_med_power.source = LLDPMED_POW_SOURCE_LOCAL;
429 break;
430 case 3:
431 port->p_med_power.source = LLDPMED_POW_SOURCE_BOTH;
432 break;
433 default:
434 port->p_med_power.source = LLDPMED_POW_SOURCE_UNKNOWN;
435 break;
436 }
437 port->p_med_cap_enabled |= LLDPMED_CAP_MDI_PD;
438 break;
439 case LLDPMED_POW_TYPE_PSE:
440 switch (source) {
441 case 1:
442 port->p_med_power.source = LLDPMED_POW_SOURCE_PRIMARY;
443 break;
444 case 2:
445 port->p_med_power.source = LLDPMED_POW_SOURCE_BACKUP;
446 break;
447 default:
448 port->p_med_power.source = LLDPMED_POW_SOURCE_UNKNOWN;
449 break;
450 }
451 port->p_med_cap_enabled |= LLDPMED_CAP_MDI_PSE;
452 break;
453 }
454 return 0;
455
456 invalid_poe:
457 LLOG_WARNX("The format POE-MDI is invalid (%s)", poe);
458 return -1;
459}
42ee7382
VB
460#endif
461
462#ifdef ENABLE_DOT3
463static int
464lldpd_parse_dot3_power(struct lldpd_port *port, const char *poe)
465{
466 const char *e;
608cb51c 467 struct lldpd_dot3_power target;
42ee7382
VB
468
469 if (strlen(poe) == 0)
470 return 0;
471 e = poe;
608cb51c 472 memset(&target, 0, sizeof(target));
009ddd23 473
42ee7382
VB
474 /* Device type */
475 if (!strncmp(e, "PD", 2))
608cb51c 476 target.devicetype = LLDP_DOT3_POWER_PD;
42ee7382 477 else if (!strncmp(e, "PSE", 3))
608cb51c 478 target.devicetype = LLDP_DOT3_POWER_PSE;
42ee7382
VB
479 else {
480 LLOG_WARNX("Device type should be either 'PD' or 'PSE'.");
481 goto invalid_dot3_poe;
482 }
483
484 /* Supported */
485 if ((e = strchr(e, ':')) == NULL) {
486 LLOG_WARNX("Expected power support.");
487 goto invalid_dot3_poe;
488 }
608cb51c
VB
489 target.supported = atoi(++e);
490 if (target.supported > 1) {
491 LLOG_WARNX("Power support should be 1 or 0, not %d", target.supported);
42ee7382
VB
492 goto invalid_dot3_poe;
493 }
494
495 /* Enabled */
496 if ((e = strchr(e, ':')) == NULL) {
497 LLOG_WARNX("Expected power ability.");
498 goto invalid_dot3_poe;
499 }
608cb51c
VB
500 target.enabled = atoi(++e);
501 if (target.enabled > 1) {
502 LLOG_WARNX("Power ability should be 1 or 0, not %d", target.enabled);
42ee7382
VB
503 goto invalid_dot3_poe;
504 }
505
506 /* Pair control */
507 if ((e = strchr(e, ':')) == NULL) {
508 LLOG_WARNX("Expected power pair control ability.");
509 goto invalid_dot3_poe;
510 }
608cb51c
VB
511 target.paircontrol = atoi(++e);
512 if (target.paircontrol > 1) {
513 LLOG_WARNX("Power pair control ability should be 1 or 0, not %d",
514 target.paircontrol);
42ee7382
VB
515 goto invalid_dot3_poe;
516 }
517
518 /* Power pairs */
519 if ((e = strchr(e, ':')) == NULL) {
520 LLOG_WARNX("Expected power pairs.");
521 goto invalid_dot3_poe;
522 }
608cb51c
VB
523 target.pairs = atoi(++e);
524 if (target.pairs < 1 || target.pairs > 2) {
525 LLOG_WARNX("Power pairs should be 1 or 2, not %d.", target.pairs);
42ee7382
VB
526 goto invalid_dot3_poe;
527 }
528
529 /* Class */
530 if ((e = strchr(e, ':')) == NULL) {
531 LLOG_WARNX("Expected power class.");
532 goto invalid_dot3_poe;
533 }
608cb51c
VB
534 target.class = atoi(++e);
535 if (target.class > 5) {
536 LLOG_WARNX("Power class out of range (%d).", target.class);
537 goto invalid_dot3_poe;
538 }
539 /* 802.3at */
540 if ((e = strchr(e, ':')) == NULL) {
541 target.powertype = LLDP_DOT3_POWER_8023AT_OFF;
542 goto no8023at;
543 }
544 /* 802.3at: Power type */
545 target.powertype = atoi(++e);
546 if ((target.powertype != LLDP_DOT3_POWER_8023AT_TYPE1) &&
547 (target.powertype != LLDP_DOT3_POWER_8023AT_TYPE2)) {
548 LLOG_WARNX("Incorrect power type (%d).", target.powertype);
549 goto invalid_dot3_poe;
550 }
551 /* 802.3at: Source */
552 if ((e = strchr(e, ':')) == NULL) {
553 LLOG_WARNX("Expected power source.");
554 goto invalid_dot3_poe;
555 }
556 target.source = atoi(++e);
557 if (target.source > 3) {
558 LLOG_WARNX("Power source out of range (%d).", target.source);
559 goto invalid_dot3_poe;
560 }
561 /* 802.3at: priority */
562 if ((e = strchr(e, ':')) == NULL) {
563 LLOG_WARNX("Expected power priority.");
564 goto invalid_dot3_poe;
565 }
566 target.priority = atoi(++e);
567 if (target.priority > 3) {
568 LLOG_WARNX("Power priority out of range (%d).", target.priority);
569 goto invalid_dot3_poe;
570 }
571 /* 802.3at: requested */
572 if ((e = strchr(e, ':')) == NULL) {
573 LLOG_WARNX("Expected requested power value.");
574 goto invalid_dot3_poe;
575 }
576 target.requested = atoi(++e);
577 /* 802.3at: allocated */
578 if ((e = strchr(e, ':')) == NULL) {
579 LLOG_WARNX("Expected allocated power value.");
42ee7382
VB
580 goto invalid_dot3_poe;
581 }
608cb51c 582 target.allocated = atoi(++e);
42ee7382 583
608cb51c
VB
584 no8023at:
585 memcpy(&port->p_power, &target, sizeof(target));
42ee7382
VB
586 return 0;
587
588 invalid_dot3_poe:
589 LLOG_WARNX("The format POE-MDI is invalid (%s)", poe);
590 return -1;
591}
592#endif
593
594#ifdef ENABLE_LLDPMED
8888d191 595static void
740593ff
VB
596set_location(int s, int argc, char *argv[])
597{
598 int i, ch;
599 struct interfaces ifs;
600 struct lldpd_interface *iff;
601 struct lldpd_port port;
602 void *p;
603 struct hmsg *h;
604
605 if ((h = (struct hmsg *)malloc(MAX_HMSGSIZE)) == NULL)
606 fatal(NULL);
607
608 memset(&port, 0, sizeof(struct lldpd_port));
609 optind = 1;
b258db58 610 while ((ch = getopt(argc, argv, LLDPCTL_ARGS)) != -1) {
740593ff
VB
611 switch (ch) {
612 case 'L':
613 if ((lldpd_parse_location(&port, optarg)) == -1)
614 fatalx("incorrect location");
615 break;
616 }
617 }
618
619 get_interfaces(s, &ifs);
620 TAILQ_FOREACH(iff, &ifs, next) {
621 if (optind < argc) {
622 for (i = optind; i < argc; i++)
623 if (strncmp(argv[i], iff->name, IFNAMSIZ) == 0)
624 break;
625 if (i == argc)
626 continue;
627 }
628
629 ctl_msg_init(h, HMSG_SET_LOCATION);
630 strlcpy((char *)&h->data, iff->name, IFNAMSIZ);
631 h->hdr.len += IFNAMSIZ;
632 p = (char*)&h->data + IFNAMSIZ;
633 if (ctl_msg_pack_structure(STRUCT_LLDPD_MED_LOC
634 STRUCT_LLDPD_MED_LOC STRUCT_LLDPD_MED_LOC,
635 port.p_med_location,
636 3*sizeof(struct lldpd_med_loc), h, &p) == -1) {
637 LLOG_WARNX("set_location: unable to set location for %s", iff->name);
638 fatalx("aborting");
639 }
640 if (ctl_msg_send(s, h) == -1)
641 fatalx("set_location: unable to send request");
642 if (ctl_msg_recv(s, h) == -1)
643 fatalx("set_location: unable to receive answer");
644 if (h->hdr.type != HMSG_SET_LOCATION)
645 fatalx("set_location: unknown answer type received");
d2879532 646 LLOG_INFO("Location set successfully for %s", iff->name);
740593ff
VB
647 }
648}
86f24df3
VB
649
650static void
651set_policy(int s, int argc, char *argv[])
652{
653 int i, ch;
654 struct interfaces ifs;
655 struct lldpd_interface *iff;
656 struct lldpd_port port;
657 void *p;
658 struct hmsg *h;
659
660 if ((h = (struct hmsg *)malloc(MAX_HMSGSIZE)) == NULL)
661 fatal(NULL);
662
663 memset(&port, 0, sizeof(struct lldpd_port));
664 optind = 1;
b258db58 665 while ((ch = getopt(argc, argv, LLDPCTL_ARGS)) != -1) {
86f24df3
VB
666 switch (ch) {
667 case 'P':
668 if ((lldpd_parse_policy(&port, optarg)) == -1)
669 fatalx("Incorrect Network Policy.");
670 break;
671 }
672 }
673
674 get_interfaces(s, &ifs);
675 TAILQ_FOREACH(iff, &ifs, next) {
676 if (optind < argc) {
677 for (i = optind; i < argc; i++)
678 if (strncmp(argv[i], iff->name, IFNAMSIZ) == 0)
679 break;
680 if (i == argc)
681 continue;
682 }
683
684 ctl_msg_init(h, HMSG_SET_POLICY);
685 strlcpy((char *)&h->data, iff->name, IFNAMSIZ);
686 h->hdr.len += IFNAMSIZ;
687 p = (char*)&h->data + IFNAMSIZ;
688 if (ctl_msg_pack_structure(
689 STRUCT_LLDPD_MED_POLICY
690 STRUCT_LLDPD_MED_POLICY
691 STRUCT_LLDPD_MED_POLICY
692 STRUCT_LLDPD_MED_POLICY
693 STRUCT_LLDPD_MED_POLICY
694 STRUCT_LLDPD_MED_POLICY
695 STRUCT_LLDPD_MED_POLICY
696 STRUCT_LLDPD_MED_POLICY,
697 port.p_med_policy,
698 8*sizeof(struct lldpd_med_policy), h, &p) == -1) {
699 LLOG_WARNX("set_policy: Unable to set Network Policy for %s", iff->name);
700 fatalx("aborting");
701 }
702 if (ctl_msg_send(s, h) == -1)
703 fatalx("set_policy: unable to send request");
704 if (ctl_msg_recv(s, h) == -1)
705 fatalx("set_policy: unable to receive answer");
706 if (h->hdr.type != HMSG_SET_POLICY)
707 fatalx("set_policy: unknown answer type received");
708 LLOG_INFO("Network Policy successfully set for %s", iff->name);
709 }
710}
009ddd23
VB
711
712static void
713set_power(int s, int argc, char *argv[])
714{
715 int i, ch;
716 struct interfaces ifs;
717 struct lldpd_interface *iff;
718 struct lldpd_port port;
719 void *p;
720 struct hmsg *h;
721
722 if ((h = (struct hmsg *)malloc(MAX_HMSGSIZE)) == NULL)
723 fatal(NULL);
724
725 memset(&port, 0, sizeof(struct lldpd_port));
726 optind = 1;
727 while ((ch = getopt(argc, argv, LLDPCTL_ARGS)) != -1) {
728 switch (ch) {
729 case 'O':
730 if ((lldpd_parse_power(&port, optarg)) == -1)
731 fatalx("Incorrect POE-MDI.");
732 break;
733 }
734 }
735
736 get_interfaces(s, &ifs);
737 TAILQ_FOREACH(iff, &ifs, next) {
738 if (optind < argc) {
739 for (i = optind; i < argc; i++)
740 if (strncmp(argv[i], iff->name, IFNAMSIZ) == 0)
741 break;
742 if (i == argc)
743 continue;
744 }
745
746 ctl_msg_init(h, HMSG_SET_POWER);
747 strlcpy((char *)&h->data, iff->name, IFNAMSIZ);
748 h->hdr.len += IFNAMSIZ;
749 p = (char*)&h->data + IFNAMSIZ;
750 if (ctl_msg_pack_structure(STRUCT_LLDPD_MED_POWER,
751 &port.p_med_power,
752 sizeof(struct lldpd_med_power), h, &p) == -1) {
753 LLOG_WARNX("set_power: Unable to set POE-MDI for %s", iff->name);
754 fatalx("aborting");
755 }
756 if (ctl_msg_send(s, h) == -1)
757 fatalx("set_power: unable to send request");
758 if (ctl_msg_recv(s, h) == -1)
759 fatalx("set_power: unable to receive answer");
760 if (h->hdr.type != HMSG_SET_POWER)
761 fatalx("set_power: unknown answer type received");
762 LLOG_INFO("POE-MDI successfully set for %s", iff->name);
763 }
764}
740593ff
VB
765#endif
766
42ee7382
VB
767#ifdef ENABLE_DOT3
768static void
769set_dot3_power(int s, int argc, char *argv[])
770{
771 int i, ch;
772 struct interfaces ifs;
773 struct lldpd_interface *iff;
774 struct lldpd_port port;
775 void *p;
776 struct hmsg *h;
777
778 if ((h = (struct hmsg *)malloc(MAX_HMSGSIZE)) == NULL)
779 fatal(NULL);
780
781 memset(&port, 0, sizeof(struct lldpd_port));
782 optind = 1;
783 while ((ch = getopt(argc, argv, LLDPCTL_ARGS)) != -1) {
784 switch (ch) {
785 case 'o':
786 if ((lldpd_parse_dot3_power(&port, optarg)) == -1)
787 fatalx("Incorrect POE-MDI.");
788 break;
789 }
790 }
791
792 get_interfaces(s, &ifs);
793 TAILQ_FOREACH(iff, &ifs, next) {
794 if (optind < argc) {
795 for (i = optind; i < argc; i++)
796 if (strncmp(argv[i], iff->name, IFNAMSIZ) == 0)
797 break;
798 if (i == argc)
799 continue;
800 }
801
802 ctl_msg_init(h, HMSG_SET_DOT3_POWER);
803 strlcpy((char *)&h->data, iff->name, IFNAMSIZ);
804 h->hdr.len += IFNAMSIZ;
805 p = (char*)&h->data + IFNAMSIZ;
806 if (ctl_msg_pack_structure(STRUCT_LLDPD_DOT3_POWER,
807 &port.p_power,
808 sizeof(struct lldpd_dot3_power), h, &p) == -1) {
809 LLOG_WARNX("set_dot3_power: Unable to set POE-MDI for %s", iff->name);
810 fatalx("aborting");
811 }
812 if (ctl_msg_send(s, h) == -1)
813 fatalx("set_dot3_power: unable to send request");
814 if (ctl_msg_recv(s, h) == -1)
815 fatalx("set_dot3_power: unable to receive answer");
816 if (h->hdr.type != HMSG_SET_DOT3_POWER)
817 fatalx("set_dot3_power: unknown answer type received");
818 LLOG_INFO("Dot3 POE-MDI successfully set for %s", iff->name);
819 }
820}
821#endif
822
740593ff
VB
823int
824main(int argc, char *argv[])
825{
826 int ch, s, debug = 1;
1480ce74 827 char * fmt = "plain";
b258db58
VB
828#define ACTION_SET_LOCATION (1 << 0)
829#define ACTION_SET_POLICY (1 << 1)
009ddd23 830#define ACTION_SET_POWER (1 << 2)
42ee7382 831#define ACTION_SET_DOT3_POWER (1 << 3)
740593ff 832 int action = 0;
43c02e7b 833
740593ff
VB
834 /*
835 * Get and parse command line options
836 */
b258db58 837 while ((ch = getopt(argc, argv, LLDPCTL_ARGS)) != -1) {
740593ff 838 switch (ch) {
b162b740
VB
839 case 'h':
840 usage();
841 break;
740593ff
VB
842 case 'd':
843 debug++;
844 break;
1480ce74
AH
845 case 'f':
846 fmt = optarg;
847 break;
740593ff 848 case 'L':
86f24df3 849 case 'P':
009ddd23 850 case 'O':
86f24df3 851#ifdef ENABLE_LLDPMED
009ddd23
VB
852 switch (ch) {
853 case 'L': action |= ACTION_SET_LOCATION; break;
854 case 'P': action |= ACTION_SET_POLICY; break;
855 case 'O': action |= ACTION_SET_POWER; break;
856 }
86f24df3
VB
857#else
858 fprintf(stderr, "LLDP-MED support is not built-in\n");
859 usage();
42ee7382
VB
860#endif
861 break;
862 case 'o':
863#ifdef ENABLE_DOT3
864 action |= ACTION_SET_DOT3_POWER;
865#else
866 fprintf(stderr, "Dot3 support is not built-in\n");
867 usage();
740593ff
VB
868#endif
869 break;
870 default:
871 usage();
872 }
9a784fd2
AH
873 }
874
6bb9c4e0 875 log_init(debug, __progname);
9a784fd2 876
05eacc7a 877 if ((action != 0) && (getuid() != 0)) {
9a784fd2
AH
878 fatalx("mere mortals may not do that, 'root' privileges are required.");
879 }
43c02e7b 880
740593ff
VB
881 if ((s = ctl_connect(LLDPD_CTL_SOCKET)) == -1)
882 fatalx("unable to connect to socket " LLDPD_CTL_SOCKET);
883
740593ff 884#ifdef ENABLE_LLDPMED
b258db58 885 if (action & ACTION_SET_LOCATION)
740593ff 886 set_location(s, argc, argv);
b258db58 887 if (action & ACTION_SET_POLICY)
86f24df3 888 set_policy(s, argc, argv);
009ddd23
VB
889 if (action & ACTION_SET_POWER)
890 set_power(s, argc, argv);
42ee7382
VB
891#endif
892#ifdef ENABLE_DOT3
893 if (action & ACTION_SET_DOT3_POWER)
894 set_dot3_power(s, argc, argv);
740593ff 895#endif
b258db58 896 if (!action)
1480ce74 897 display_interfaces(s, fmt, argc, argv);
740593ff
VB
898
899 close(s);
43c02e7b
VB
900 return 0;
901}