]> git.ipfire.org Git - thirdparty/lldpd.git/blame - src/lldpctl.c
Replace index() by strchr()
[thirdparty/lldpd.git] / src / lldpctl.c
CommitLineData
43c02e7b
VB
1/*
2 * Copyright (c) 2008 Vincent Bernat <bernat@luffy.cx>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
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>
21#include <errno.h>
22#include <sys/types.h>
23#include <sys/socket.h>
24#include <sys/un.h>
25#include <arpa/inet.h>
26
8888d191 27static void usage(void);
43c02e7b
VB
28
29TAILQ_HEAD(interfaces, lldpd_interface);
a1347cd8 30#ifdef ENABLE_DOT1
43c02e7b 31TAILQ_HEAD(vlans, lldpd_vlan);
a1347cd8 32#endif
43c02e7b 33
650cae58
VB
34#define ntohll(x) (((u_int64_t)(ntohl((int)((x << 32) >> 32))) << 32) | \
35 (unsigned int)ntohl(((int)(x >> 32))))
36#define htonll(x) ntohll(x)
37
38
43c02e7b
VB
39struct value_string {
40 int value;
41 char *string;
42};
43
650cae58
VB
44#ifdef ENABLE_LLDPMED
45static const struct value_string civic_address_type_values[] = {
46 { 0, "Language" },
47 { 1, "National subdivisions" },
48 { 2, "County, parish, district" },
49 { 3, "City, township" },
50 { 4, "City division, borough, ward" },
51 { 5, "Neighborhood, block" },
52 { 6, "Street" },
53 { 16, "Leading street direction" },
54 { 17, "Trailing street suffix" },
55 { 18, "Street suffix" },
56 { 19, "House number" },
57 { 20, "House number suffix" },
58 { 21, "Landmark or vanity address" },
59 { 22, "Additional location info" },
60 { 23, "Name" },
61 { 24, "Postal/ZIP code" },
62 { 25, "Building" },
63 { 26, "Unit" },
64 { 27, "Floor" },
65 { 28, "Room number" },
66 { 29, "Place type" },
67 { 128, "Script" },
68 { 0, NULL }
69};
70#endif
71
a1347cd8 72#ifdef ENABLE_DOT3
43c02e7b
VB
73static const struct value_string operational_mau_type_values[] = {
74 { 1, "AUI - no internal MAU, view from AUI" },
75 { 2, "10Base5 - thick coax MAU" },
76 { 3, "Foirl - FOIRL MAU" },
77 { 4, "10Base2 - thin coax MAU" },
78 { 5, "10BaseT - UTP MAU" },
79 { 6, "10BaseFP - passive fiber MAU" },
80 { 7, "10BaseFB - sync fiber MAU" },
81 { 8, "10BaseFL - async fiber MAU" },
82 { 9, "10Broad36 - broadband DTE MAU" },
83 { 10, "10BaseTHD - UTP MAU, half duplex mode" },
84 { 11, "10BaseTFD - UTP MAU, full duplex mode" },
85 { 12, "10BaseFLHD - async fiber MAU, half duplex mode" },
86 { 13, "10BaseFLDF - async fiber MAU, full duplex mode" },
87 { 14, "10BaseT4 - 4 pair category 3 UTP" },
88 { 15, "100BaseTXHD - 2 pair category 5 UTP, half duplex mode" },
89 { 16, "100BaseTXFD - 2 pair category 5 UTP, full duplex mode" },
90 { 17, "100BaseFXHD - X fiber over PMT, half duplex mode" },
91 { 18, "100BaseFXFD - X fiber over PMT, full duplex mode" },
92 { 19, "100BaseT2HD - 2 pair category 3 UTP, half duplex mode" },
93 { 20, "100BaseT2DF - 2 pair category 3 UTP, full duplex mode" },
94 { 21, "1000BaseXHD - PCS/PMA, unknown PMD, half duplex mode" },
95 { 22, "1000BaseXFD - PCS/PMA, unknown PMD, full duplex mode" },
96 { 23, "1000BaseLXHD - Fiber over long-wavelength laser, half duplex mode" },
97 { 24, "1000BaseLXFD - Fiber over long-wavelength laser, full duplex mode" },
98 { 25, "1000BaseSXHD - Fiber over short-wavelength laser, half duplex mode" },
99 { 26, "1000BaseSXFD - Fiber over short-wavelength laser, full duplex mode" },
100 { 27, "1000BaseCXHD - Copper over 150-Ohm balanced cable, half duplex mode" },
101 { 28, "1000BaseCXFD - Copper over 150-Ohm balanced cable, full duplex mode" },
102 { 29, "1000BaseTHD - Four-pair Category 5 UTP, half duplex mode" },
103 { 30, "1000BaseTFD - Four-pair Category 5 UTP, full duplex mode" },
104 { 31, "10GigBaseX - X PCS/PMA, unknown PMD." },
105 { 32, "10GigBaseLX4 - X fiber over WWDM optics" },
106 { 33, "10GigBaseR - R PCS/PMA, unknown PMD." },
107 { 34, "10GigBaseER - R fiber over 1550 nm optics" },
108 { 35, "10GigBaseLR - R fiber over 1310 nm optics" },
109 { 36, "10GigBaseSR - R fiber over 850 nm optics" },
110 { 37, "10GigBaseW - W PCS/PMA, unknown PMD." },
111 { 38, "10GigBaseEW - W fiber over 1550 nm optics" },
112 { 39, "10GigBaseLW - W fiber over 1310 nm optics" },
113 { 40, "10GigBaseSW - W fiber over 850 nm optics" },
4b7f39b1
VB
114 { 41, "10GigBaseCX4 - X copper over 8 pair 100-Ohm balanced cable" },
115 { 42, "2BaseTL - Voice grade UTP copper, up to 2700m, optional PAF" },
116 { 43, "10PassTS - Voice grade UTP copper, up to 750m, optional PAF" },
117 { 44, "100BaseBX10D - One single-mode fiber OLT, long wavelength, 10km" },
118 { 45, "100BaseBX10U - One single-mode fiber ONU, long wavelength, 10km" },
119 { 46, "100BaseLX10 - Two single-mode fibers, long wavelength, 10km" },
120 { 47, "1000BaseBX10D - One single-mode fiber OLT, long wavelength, 10km" },
121 { 48, "1000BaseBX10U - One single-mode fiber ONU, long wavelength, 10km" },
122 { 49, "1000BaseLX10 - Two sigle-mode fiber, long wavelength, 10km" },
123 { 50, "1000BasePX10D - One single-mode fiber EPON OLT, 10km" },
124 { 51, "1000BasePX10U - One single-mode fiber EPON ONU, 10km" },
125 { 52, "1000BasePX20D - One single-mode fiber EPON OLT, 20km" },
126 { 53, "1000BasePX20U - One single-mode fiber EPON ONU, 20km" },
43c02e7b
VB
127 { 0, NULL }
128};
a1347cd8 129#endif
43c02e7b 130
8888d191 131static void
43c02e7b
VB
132usage(void)
133{
134 extern const char *__progname;
135
740593ff
VB
136 fprintf(stderr, "usage: %s [options]\n", __progname);
137 fprintf(stderr, "see manual page lldpctl(8) for more information\n");
43c02e7b
VB
138 exit(1);
139}
140
141static char*
142dump(void *data, int size, int max, char sep)
143{
144 int i;
145 size_t len;
146 static char *buffer = NULL;
147 static char truncation[] = "[...]";
148
149 free(buffer);
150 if (size > max)
151 len = max * 3 + sizeof(truncation) + 1;
152 else
153 len = size * 3;
154
155 if ((buffer = (char *)malloc(len)) == NULL)
156 fatal(NULL);
157
158 for (i = 0; (i < size) && (i < max); i++)
159 sprintf(buffer + i * 3, "%02x%c", *(u_int8_t*)(data + i), sep);
160 if (size > max)
161 sprintf(buffer + i * 3, "%s", truncation);
162 else
163 *(buffer + i*3 - 1) = 0;
164 return buffer;
165}
166
167
8888d191 168static void
43c02e7b
VB
169get_interfaces(int s, struct interfaces *ifs)
170{
171 void *p;
172 struct hmsg *h;
173
174 if ((h = (struct hmsg *)malloc(MAX_HMSGSIZE)) == NULL)
175 fatal(NULL);
176 ctl_msg_init(h, HMSG_GET_INTERFACES);
177 if (ctl_msg_send(s, h) == -1)
178 fatalx("get_interfaces: unable to send request");
179 if (ctl_msg_recv(s, h) == -1)
180 fatalx("get_interfaces: unable to receive answer");
181 if (h->hdr.type != HMSG_GET_INTERFACES)
182 fatalx("get_interfaces: unknown answer type received");
183 p = &h->data;
184 if (ctl_msg_unpack_list(STRUCT_LLDPD_INTERFACE,
185 ifs, sizeof(struct lldpd_interface), h, &p) == -1)
186 fatalx("get_interfaces: unable to retrieve the list of interfaces");
187}
188
a1347cd8 189#ifdef ENABLE_DOT1
8888d191 190static int
84853b92 191get_vlans(int s, struct vlans *vls, char *interface, int nb)
43c02e7b
VB
192{
193 void *p;
194 struct hmsg *h;
195
196 if ((h = (struct hmsg *)malloc(MAX_HMSGSIZE)) == NULL)
197 fatal(NULL);
198 ctl_msg_init(h, HMSG_GET_VLANS);
740593ff 199 strlcpy((char *)&h->data, interface, IFNAMSIZ);
84853b92
VB
200 memcpy((char*)&h->data + IFNAMSIZ, &nb, sizeof(int));
201 h->hdr.len += IFNAMSIZ + sizeof(int);
43c02e7b
VB
202 if (ctl_msg_send(s, h) == -1)
203 fatalx("get_vlans: unable to send request");
204 if (ctl_msg_recv(s, h) == -1)
205 fatalx("get_vlans: unable to receive answer");
206 if (h->hdr.type != HMSG_GET_VLANS)
207 fatalx("get_vlans: unknown answer type received");
208 p = &h->data;
209 if (ctl_msg_unpack_list(STRUCT_LLDPD_VLAN,
210 vls, sizeof(struct lldpd_vlan), h, &p) == -1)
211 fatalx("get_vlans: unable to retrieve the list of vlans");
212 return 1;
213}
a1347cd8 214#endif
43c02e7b 215
8888d191 216static int
84853b92 217get_chassis(int s, struct lldpd_chassis *chassis, char *interface, int nb)
43c02e7b
VB
218{
219 struct hmsg *h;
220 void *p;
221
222 if ((h = (struct hmsg *)malloc(MAX_HMSGSIZE)) == NULL)
223 fatal(NULL);
224 ctl_msg_init(h, HMSG_GET_CHASSIS);
740593ff 225 strlcpy((char *)&h->data, interface, IFNAMSIZ);
84853b92
VB
226 memcpy((char*)&h->data + IFNAMSIZ, &nb, sizeof(int));
227 h->hdr.len += IFNAMSIZ + sizeof(int);
43c02e7b
VB
228 if (ctl_msg_send(s, h) == -1)
229 fatalx("get_chassis: unable to send request to get chassis");
230 if (ctl_msg_recv(s, h) == -1)
231 fatalx("get_chassis: unable to receive answer to get chassis");
232 if (h->hdr.type == HMSG_NONE)
233 /* No chassis */
234 return -1;
235 p = &h->data;
236 if (ctl_msg_unpack_structure(STRUCT_LLDPD_CHASSIS,
237 chassis, sizeof(struct lldpd_chassis), h, &p) == -1) {
238 LLOG_WARNX("unable to retrieve chassis for %s", interface);
239 fatalx("get_chassis: abort");
240 }
241 return 1;
242}
243
8888d191 244static int
84853b92 245get_port(int s, struct lldpd_port *port, char *interface, int nb)
43c02e7b
VB
246{
247 struct hmsg *h;
248 void *p;
249
250 if ((h = (struct hmsg *)malloc(MAX_HMSGSIZE)) == NULL)
251 fatal(NULL);
252 ctl_msg_init(h, HMSG_GET_PORT);
740593ff 253 strlcpy((char *)&h->data, interface, IFNAMSIZ);
84853b92
VB
254 memcpy((char*)&h->data + IFNAMSIZ, &nb, sizeof(int));
255 h->hdr.len += IFNAMSIZ + sizeof(int);
43c02e7b
VB
256 if (ctl_msg_send(s, h) == -1)
257 fatalx("get_port: unable to send request to get port");
258 if (ctl_msg_recv(s, h) == -1)
259 fatalx("get_port: unable to receive answer to get port");
260 if (h->hdr.type == HMSG_NONE)
261 /* No port */
262 return -1;
263 p = &h->data;
264 if (ctl_msg_unpack_structure(STRUCT_LLDPD_PORT,
265 port, sizeof(struct lldpd_port), h, &p) == -1) {
266 LLOG_WARNX("unable to retrieve port information for %s",
267 interface);
268 fatalx("get_chassis: abort");
269 }
270 return 1;
271}
272
84853b92
VB
273static int
274get_nb_port(int s, char *interface)
275{
276 struct hmsg *h;
277 int nb;
278
279 if ((h = (struct hmsg *)malloc(MAX_HMSGSIZE)) == NULL)
280 fatal(NULL);
281 ctl_msg_init(h, HMSG_GET_NB_PORTS);
282 strlcpy((char *)&h->data, interface, IFNAMSIZ);
283 h->hdr.len += IFNAMSIZ;
284 if (ctl_msg_send(s, h) == -1)
285 fatalx("get_nb_port: unable to send request to get number of ports");
286 if (ctl_msg_recv(s, h) == -1)
287 fatalx("get_nb_port: unable to receive answer to get number of ports");
288 if (h->hdr.type == HMSG_NONE)
289 return -1;
290 if (h->hdr.len != sizeof(int))
291 fatalx("get_nb_port: bad message length");
292 memcpy(&nb, &h->data, sizeof(int));
293 return nb;
294}
295
8888d191 296static void
43c02e7b
VB
297display_cap(struct lldpd_chassis *chassis, u_int8_t bit, char *symbol)
298{
299 if (chassis->c_cap_available & bit)
300 printf("%s(%c) ", symbol,
301 (chassis->c_cap_enabled & bit)?'E':'d');
302}
303
8888d191 304static void
43c02e7b
VB
305pretty_print(char *string)
306{
307 char *s = NULL;
f0bd3505 308 if (((s = strchr(string, '\n')) == NULL) && (strlen(string) < 60)) {
43c02e7b
VB
309 printf("%s\n", string);
310 return;
311 } else
312 printf("\n");
313 while (s != NULL) {
314 *s = '\0';
315 printf(" %s\n", string);
316 *s = '\n';
317 string = s + 1;
f0bd3505 318 s = strchr(string, '\n');
43c02e7b
VB
319 }
320 printf(" %s\n", string);
321}
322
6772b237 323#ifdef ENABLE_LLDPMED
8888d191 324static int
1e379fe3 325display_fixed_precision(u_int64_t value, int intpart, int floatpart, int displaysign)
650cae58 326{
650cae58
VB
327 u_int64_t tmp = value;
328 int negative = 0;
329 u_int32_t integer = 0;
115ff55c 330 if (value & (1ULL<<(intpart + floatpart - 1))) {
650cae58
VB
331 negative = 1;
332 tmp = ~value;
333 tmp += 1;
334 }
1e379fe3
VB
335 integer = (u_int32_t)((tmp &
336 (((1ULL << intpart)-1) << floatpart)) >> floatpart);
337 tmp = (tmp & ((1<< floatpart) - 1))*10000/(1ULL << floatpart);
338 printf("%s%u.%04llu", displaysign?(negative?"-":"+"):"",
339 integer, (unsigned long long int)tmp);
340 return negative;
341}
342
8888d191 343static void
1e379fe3
VB
344display_latitude_or_longitude(int option, u_int64_t value)
345{
346 int negative;
347 negative = display_fixed_precision(value, 9, 25, 0);
348 if (option == 0)
349 printf("%s", negative?" South":" North");
350 else
351 printf("%s", negative?" West":" East");
650cae58
VB
352}
353
8888d191 354static void
740593ff 355display_med(struct lldpd_chassis *chassis, struct lldpd_port *port)
6772b237 356{
e3a44efb 357 int i;
650cae58 358 char *value;
efe3f9b0 359 printf(" LLDP-MED Device Type: ");
6772b237
VB
360 switch (chassis->c_med_type) {
361 case LLDPMED_CLASS_I:
362 printf("Generic Endpoint (Class I)");
363 break;
364 case LLDPMED_CLASS_II:
365 printf("Media Endpoint (Class II)");
366 break;
367 case LLDPMED_CLASS_III:
368 printf("Communication Device Endpoint (Class III)");
369 break;
370 case LLDPMED_NETWORK_DEVICE:
371 printf("Network Connectivity Device");
372 break;
373 default:
374 printf("Unknown (%d)", chassis->c_med_type);
375 break;
376 }
efe3f9b0 377 printf("\n LLDP-MED Capabilities:");
4982b864 378 if (chassis->c_med_cap_available & LLDPMED_CAP_CAP)
6772b237 379 printf(" Capabilities");
4982b864 380 if (chassis->c_med_cap_available & LLDPMED_CAP_POLICY)
6772b237 381 printf(" Policy");
4982b864 382 if (chassis->c_med_cap_available & LLDPMED_CAP_LOCATION)
6772b237 383 printf(" Location");
4982b864 384 if (chassis->c_med_cap_available & LLDPMED_CAP_MDI_PSE)
a49b3a79 385 printf(" MDI/PSE");
4982b864 386 if (chassis->c_med_cap_available & LLDPMED_CAP_MDI_PD)
a49b3a79 387 printf(" MDI/PD");
4982b864 388 if (chassis->c_med_cap_available & LLDPMED_CAP_IV)
6772b237
VB
389 printf(" Inventory");
390 printf("\n");
e3a44efb 391 for (i = 0; i < LLDPMED_APPTYPE_LAST; i++) {
740593ff 392 if (i+1 == port->p_med_policy[i].type) {
e3a44efb 393 printf(" LLDP-MED Network Policy for ");
740593ff 394 switch(port->p_med_policy[i].type) {
e3a44efb
VB
395 case LLDPMED_APPTYPE_VOICE:
396 printf("Voice");
397 break;
398 case LLDPMED_APPTYPE_VOICESIGNAL:
399 printf("Voice Signaling");
400 break;
401 case LLDPMED_APPTYPE_GUESTVOICE:
402 printf("Guest Voice");
403 break;
404 case LLDPMED_APPTYPE_GUESTVOICESIGNAL:
405 printf("Guest Voice Signaling");
406 break;
407 case LLDPMED_APPTYPE_SOFTPHONEVOICE:
408 printf("Softphone Voice");
409 break;
410 case LLDPMED_APPTYPE_VIDEOCONFERENCE:
411 printf("Video Conferencing");
412 break;
413 case LLDPMED_APPTYPE_VIDEOSTREAM:
414 printf("Streaming Video");
415 break;
416 case LLDPMED_APPTYPE_VIDEOSIGNAL:
417 printf("Video Signaling");
418 break;
419 default:
420 printf("Reserved");
421 }
422 printf(":\n Policy: ");
740593ff 423 if (port->p_med_policy[i].unknown) {
e3a44efb
VB
424 printf("unknown, ");
425 } else {
426 printf("defined, ");
427 }
740593ff 428 if (!port->p_med_policy[i].tagged) {
e3a44efb
VB
429 printf("un");
430 }
431 printf("tagged");
432 printf("\n VLAN ID: ");
740593ff 433 if (port->p_med_policy[i].vid == 0) {
e3a44efb 434 printf("Priority Tagged");
740593ff 435 } else if (port->p_med_policy[i].vid == 4095) {
e3a44efb
VB
436 printf("reserved");
437 } else {
740593ff 438 printf("%u", port->p_med_policy[i].vid);
e3a44efb
VB
439 }
440 printf("\n Layer 2 Priority: ");
740593ff 441 printf("%u", port->p_med_policy[i].priority);
e3a44efb 442 printf("\n DSCP Value: ");
740593ff 443 printf("%u\n", port->p_med_policy[i].dscp);
efe3f9b0 444 }
efe3f9b0 445 }
e3a44efb 446 for (i = 0; i < LLDPMED_LOCFORMAT_LAST; i++) {
740593ff 447 if (i+1 == port->p_med_location[i].format) {
e3a44efb 448 printf(" LLDP-MED Location Identification: ");
740593ff 449 switch(port->p_med_location[i].format) {
e3a44efb 450 case LLDPMED_LOCFORMAT_COORD:
1e379fe3 451 printf("\n Coordinate-based data: ");
740593ff 452 if (port->p_med_location[i].data_len != 16)
650cae58
VB
453 printf("bad data length");
454 else {
455 u_int64_t l;
1e379fe3
VB
456
457 /* Latitude and longitude */
3d1337f3
VB
458 memcpy(&l, port->p_med_location[i].data,
459 sizeof(u_int64_t));
460 l = (ntohll(l) &
0d83ebae 461 0x03FFFFFFFF000000ULL) >> 24;
650cae58
VB
462 display_latitude_or_longitude(0, l);
463 printf(", ");
3d1337f3
VB
464 memcpy(&l, port->p_med_location[i].data + 5,
465 sizeof(u_int64_t));
466 l = (ntohll(l) &
0d83ebae 467 0x03FFFFFFFF000000ULL) >> 24;
650cae58 468 display_latitude_or_longitude(1, l);
1e379fe3
VB
469
470 /* Altitude */
471 printf(", ");
3d1337f3
VB
472 memcpy(&l, port->p_med_location[i].data + 10,
473 sizeof(u_int64_t));
474 l = (ntohll(l) &
1e379fe3
VB
475 0x3FFFFFFF000000ULL) >> 24;
476 display_fixed_precision(l, 22, 8, 1);
740593ff 477 switch ((*(u_int8_t*)(port->p_med_location[i].data +
1e379fe3
VB
478 10)) & 0xf0) {
479 case (1 << 4):
480 printf(" meters"); break;
481 case (2 << 4):
482 printf(" floors"); break;
483 default:
484 printf(" (unknown)");
485 }
486
487 /* Datum */
740593ff 488 switch (*(u_int8_t*)(port->p_med_location[i].data +
1e379fe3
VB
489 15)) {
490 case 1:
491 printf(", WGS84"); break;
492 case 2:
493 printf(", NAD83"); break;
494 case 3:
495 printf(", NAD83/MLLW"); break;
496 }
650cae58 497 }
e3a44efb
VB
498 break;
499 case LLDPMED_LOCFORMAT_CIVIC:
650cae58 500 printf("Civic address: ");
740593ff
VB
501 if ((port->p_med_location[i].data_len < 3) ||
502 (port->p_med_location[i].data_len - 1 !=
503 *(u_int8_t*)port->p_med_location[i].data))
650cae58
VB
504 printf("bad data length");
505 else {
506 int l = 4, n, catype, calength, j = 0;
507 printf("\n%28s: %c%c", "Country",
740593ff
VB
508 ((char *)port->p_med_location[i].data)[2],
509 ((char *)port->p_med_location[i].data)[3]);
510 while ((n = (port->
511 p_med_location[i].data_len - l)) >= 2) {
512 catype = *(u_int8_t*)(port->
513 p_med_location[i].data + l);
514 calength = *(u_int8_t*)(port->
515 p_med_location[i].data + l + 1);
650cae58
VB
516 if (n < 2 + calength) {
517 printf("bad data length");
518 break;
519 }
520 for (j = 0;
521 civic_address_type_values[j].string != NULL;
522 j++) {
523 if (civic_address_type_values[j].value ==
524 catype)
525 break;
526 }
527 if (civic_address_type_values[j].string == NULL) {
528 printf("unknown type %d", catype);
529 break;
530 }
740593ff
VB
531 if ((value = strndup((char *)(port->
532 p_med_location[i].data + l + 2),
650cae58
VB
533 calength)) == NULL) {
534 printf("not enough memory");
535 break;
536 }
537 printf("\n%28s: %s",
538 civic_address_type_values[j].string,
539 value);
540 free(value);
541 l += 2 + calength;
542 }
543 }
e3a44efb
VB
544 break;
545 case LLDPMED_LOCFORMAT_ELIN:
740593ff
VB
546 if ((value = strndup((char *)(port->
547 p_med_location[i].data),
548 port->p_med_location[i].data_len)) == NULL) {
650cae58
VB
549 printf("not enough memory");
550 break;
551 }
552 printf("ECS ELIN: %s", value);
553 free(value);
e3a44efb
VB
554 break;
555 default:
556 printf("unknown location data format: \n %s",
740593ff
VB
557 dump(port->p_med_location[i].data,
558 port->p_med_location[i].data_len, 20, ' '));
e3a44efb
VB
559 }
560 printf("\n");
efe3f9b0 561 }
efe3f9b0 562 }
740593ff 563 if (port->p_med_pow_devicetype) {
efe3f9b0
VB
564 printf(" LLDP-MED Extended Power-over-Ethernet:\n");
565 printf(" Power Type & Source: ");
740593ff 566 switch (port->p_med_pow_devicetype) {
994812b9 567 case LLDPMED_POW_TYPE_PSE:
efe3f9b0 568 printf("PSE Device");
994812b9
VB
569 break;
570 case LLDPMED_POW_TYPE_PD:
efe3f9b0 571 printf("PD Device");
994812b9
VB
572 break;
573 default:
efe3f9b0
VB
574 printf("reserved");
575 }
740593ff 576 switch (port->p_med_pow_source) {
994812b9
VB
577 case LLDPMED_POW_SOURCE_UNKNOWN:
578 case LLDPMED_POW_SOURCE_RESERVED:
579 printf(", unknown"); break;
580 case LLDPMED_POW_SOURCE_PRIMARY:
581 printf(", Primary Power Source");
582 break;
583 case LLDPMED_POW_SOURCE_BACKUP:
584 printf(", Backup Power Source / Power Conservation Mode");
585 break;
586 case LLDPMED_POW_SOURCE_PSE:
587 printf(", PSE"); break;
588 case LLDPMED_POW_SOURCE_LOCAL:
589 printf(", local"); break;
590 case LLDPMED_POW_SOURCE_BOTH:
591 printf(", PSE & local");
592 break;
593 }
e3a44efb 594 printf("\n Power Priority: ");
740593ff 595 switch (port->p_med_pow_priority) {
994812b9
VB
596 case LLDPMED_POW_PRIO_CRITICAL:
597 printf("critical"); break;
598 case LLDPMED_POW_PRIO_HIGH:
599 printf("high"); break;
600 case LLDPMED_POW_PRIO_LOW:
601 printf("low"); break;
602 default:
efe3f9b0 603 printf("unknown");
efe3f9b0 604 }
e3a44efb 605 printf("\n Power Value: ");
740593ff
VB
606 if(port->p_med_pow_val < 1024) {
607 printf("%u mW", port->p_med_pow_val * 100);
efe3f9b0
VB
608 } else {
609 printf("reserved");
610 }
228fcecd 611 printf("\n");
efe3f9b0 612 }
6772b237
VB
613 if (chassis->c_med_hw ||
614 chassis->c_med_sw ||
615 chassis->c_med_fw ||
616 chassis->c_med_sn ||
617 chassis->c_med_manuf ||
618 chassis->c_med_model ||
619 chassis->c_med_asset) {
620 printf(" LLDP-MED Inventory:\n");
621 if (chassis->c_med_hw)
622 printf(" Hardware Revision: %s\n", chassis->c_med_hw);
623 if (chassis->c_med_sw)
624 printf(" Software Revision: %s\n", chassis->c_med_sw);
625 if (chassis->c_med_fw)
626 printf(" Firmware Revision: %s\n", chassis->c_med_fw);
627 if (chassis->c_med_sn)
628 printf(" Serial Number: %s\n", chassis->c_med_sn);
629 if (chassis->c_med_manuf)
630 printf(" Manufacturer: %s\n",
631 chassis->c_med_manuf);
632 if (chassis->c_med_model)
633 printf(" Model: %s\n",
634 chassis->c_med_model);
635 if (chassis->c_med_asset)
636 printf(" Asset ID: %s\n",
637 chassis->c_med_asset);
638 }
639}
640#endif
641
8888d191 642static void
43c02e7b
VB
643display_chassis(struct lldpd_chassis *chassis)
644{
645 char *cid;
646 if ((cid = (char *)malloc(chassis->c_id_len + 1)) == NULL)
647 fatal(NULL);
648 memcpy(cid, chassis->c_id, chassis->c_id_len);
649 cid[chassis->c_id_len] = 0;
650 switch (chassis->c_id_subtype) {
651 case LLDP_CHASSISID_SUBTYPE_IFNAME:
652 printf(" ChassisID: %s (ifName)\n", cid);
653 break;
654 case LLDP_CHASSISID_SUBTYPE_IFALIAS:
655 printf(" ChassisID: %s (ifAlias)\n", cid);
656 break;
657 case LLDP_CHASSISID_SUBTYPE_LOCAL:
658 printf(" ChassisID: %s (local)\n", cid);
659 break;
660 case LLDP_CHASSISID_SUBTYPE_LLADDR:
661 printf(" ChassisID: %s (MAC)\n",
662 dump(chassis->c_id, chassis->c_id_len, ETH_ALEN, ':'));
663 break;
664 case LLDP_CHASSISID_SUBTYPE_ADDR:
665 if (*(u_int8_t*)chassis->c_id == 1) {
666 printf(" ChassisID: %s (IP)\n",
667 inet_ntoa(*(struct in_addr*)(chassis->c_id +
668 1)));
669 break;
670 }
671 case LLDP_CHASSISID_SUBTYPE_PORT:
672 case LLDP_CHASSISID_SUBTYPE_CHASSIS:
673 default:
674 printf(" ChassisID: %s (unhandled type)\n",
675 dump(chassis->c_id, chassis->c_id_len, 16, ' '));
676 }
677 printf(" SysName: %s\n", chassis->c_name);
678 printf(" SysDescr: "); pretty_print(chassis->c_descr);
a806f67a
VB
679 if (chassis->c_mgmt.s_addr != INADDR_ANY)
680 printf(" MgmtIP: %s\n", inet_ntoa(chassis->c_mgmt));
43c02e7b
VB
681 printf(" Caps: ");
682 display_cap(chassis, LLDP_CAP_OTHER, "Other");
683 display_cap(chassis, LLDP_CAP_REPEATER, "Repeater");
684 display_cap(chassis, LLDP_CAP_BRIDGE, "Bridge");
45e96f2e 685 display_cap(chassis, LLDP_CAP_ROUTER, "Router");
43c02e7b
VB
686 display_cap(chassis, LLDP_CAP_WLAN, "Wlan");
687 display_cap(chassis, LLDP_CAP_TELEPHONE, "Tel");
688 display_cap(chassis, LLDP_CAP_DOCSIS, "Docsis");
689 display_cap(chassis, LLDP_CAP_STATION, "Station");
690 printf("\n");
691}
692
a1347cd8 693#ifdef ENABLE_DOT3
8888d191 694static void
43c02e7b
VB
695display_autoneg(struct lldpd_port *port, int bithd, int bitfd, char *desc)
696{
697 if (!((port->p_autoneg_advertised & bithd) ||
698 (port->p_autoneg_advertised & bitfd)))
699 return;
700 printf("%s ", desc);
701 if (port->p_autoneg_advertised & bithd) {
702 printf("(HD");
703 if (port->p_autoneg_advertised & bitfd) {
704 printf(", FD) ");
705 return;
706 }
707 printf(") ");
708 return;
709 }
710 printf("(FD) ");
711}
a1347cd8 712#endif
43c02e7b 713
8888d191 714static void
43c02e7b
VB
715display_port(struct lldpd_port *port)
716{
717 char *pid;
3d1337f3 718 struct in_addr address;
a1347cd8 719#ifdef ENABLE_DOT3
43c02e7b 720 int i;
a1347cd8 721#endif
43c02e7b
VB
722
723 if ((pid = (char *)malloc(port->p_id_len + 1)) == NULL)
724 fatal(NULL);
725 memcpy(pid, port->p_id, port->p_id_len);
726 pid[port->p_id_len] = 0;
727 switch (port->p_id_subtype) {
728 case LLDP_PORTID_SUBTYPE_IFNAME:
729 printf(" PortID: %s (ifName)\n", pid);
730 break;
731 case LLDP_PORTID_SUBTYPE_IFALIAS:
732 printf(" PortID: %s (ifAlias)\n", pid);
733 break;
734 case LLDP_PORTID_SUBTYPE_LOCAL:
735 printf(" PortID: %s (local)\n", pid);
736 break;
737 case LLDP_PORTID_SUBTYPE_LLADDR:
738 printf(" PortID: %s (MAC)\n",
739 dump(port->p_id, port->p_id_len, ETH_ALEN, ':'));
740 break;
741 case LLDP_PORTID_SUBTYPE_ADDR:
742 if (*(u_int8_t*)port->p_id == 1) {
3d1337f3
VB
743 memcpy(&address, port->p_id + 1,
744 sizeof(struct in_addr));
43c02e7b 745 printf(" PortID: %s (IP)\n",
3d1337f3 746 inet_ntoa(address));
43c02e7b
VB
747 break;
748 }
749 case LLDP_PORTID_SUBTYPE_PORT:
750 case LLDP_PORTID_SUBTYPE_AGENTCID:
751 default:
752 printf(" ChassisID: %s (unhandled type)\n",
753 dump(port->p_id, port->p_id_len, 16, ' '));
754 }
755 printf(" PortDescr: "); pretty_print(port->p_descr);
a1347cd8 756#ifdef ENABLE_DOT3
548109b2 757 if (port->p_mfs)
748e05df 758 printf(" MFS: %d bytes\n", port->p_mfs);
43c02e7b
VB
759 if (port->p_aggregid)
760 printf("\n Port is aggregated. PortAggregID: %d\n",
761 port->p_aggregid);
762
a9e9242e
VB
763 if (port->p_autoneg_support || port->p_autoneg_enabled ||
764 port->p_mau_type) {
765 printf("\n Autoneg: %ssupported/%senabled\n",
766 port->p_autoneg_support?"":"not ",
767 port->p_autoneg_enabled?"":"not ");
768 if (port->p_autoneg_enabled) {
769 printf(" PMD autoneg: ");
770 display_autoneg(port, LLDP_DOT3_LINK_AUTONEG_10BASE_T,
771 LLDP_DOT3_LINK_AUTONEG_10BASET_FD,
772 "10Base-T");
773 display_autoneg(port, LLDP_DOT3_LINK_AUTONEG_100BASE_TX,
774 LLDP_DOT3_LINK_AUTONEG_100BASE_TXFD,
775 "100Base-T");
776 display_autoneg(port, LLDP_DOT3_LINK_AUTONEG_100BASE_T2,
777 LLDP_DOT3_LINK_AUTONEG_100BASE_T2FD,
778 "100Base-T2");
779 display_autoneg(port, LLDP_DOT3_LINK_AUTONEG_1000BASE_X,
780 LLDP_DOT3_LINK_AUTONEG_1000BASE_XFD,
781 "100Base-X");
782 display_autoneg(port, LLDP_DOT3_LINK_AUTONEG_1000BASE_T,
783 LLDP_DOT3_LINK_AUTONEG_1000BASE_TFD,
784 "1000Base-T");
785 printf("\n");
786 }
787 printf(" MAU oper type: ");
788 for (i = 0; operational_mau_type_values[i].value != 0; i++) {
789 if (operational_mau_type_values[i].value ==
790 port->p_mau_type) {
791 printf("%s\n", operational_mau_type_values[i].string);
792 break;
793 }
43c02e7b 794 }
a9e9242e
VB
795 if (operational_mau_type_values[i].value == 0)
796 printf("unknown (%d)\n", port->p_mau_type);
43c02e7b 797 }
a1347cd8 798#endif
43c02e7b
VB
799}
800
a1347cd8 801#ifdef ENABLE_DOT1
8888d191 802static void
43c02e7b
VB
803display_vlans(struct lldpd_port *port)
804{
805 int i = 0;
806 struct lldpd_vlan *vlan;
807 TAILQ_FOREACH(vlan, &port->p_vlans, v_entries)
75b3469d
VB
808 printf(" %cVLAN %4d: %-20s%c",
809 (port->p_pvid == vlan->v_vid)?'*':' ',
810 vlan->v_vid, vlan->v_name,
43c02e7b
VB
811 (i++ % 2) ? '\n' : ' ');
812 if (i % 2)
813 printf("\n");
814}
a1347cd8 815#endif
43c02e7b 816
8888d191 817static void
740593ff 818display_interfaces(int s, int argc, char *argv[])
43c02e7b 819{
84853b92 820 int i, nb;
43c02e7b 821 struct interfaces ifs;
a1347cd8 822#ifdef ENABLE_DOT1
43c02e7b 823 struct vlans vls;
a1347cd8 824#endif
43c02e7b
VB
825 struct lldpd_interface *iff;
826 struct lldpd_chassis chassis;
827 struct lldpd_port port;
828 char sep[80];
740593ff 829
43c02e7b
VB
830 memset(sep, '-', 79);
831 sep[79] = 0;
43c02e7b 832 get_interfaces(s, &ifs);
740593ff 833
43c02e7b
VB
834 printf("%s\n", sep);
835 printf(" LLDP neighbors\n");
836 printf("%s\n", sep);
837 TAILQ_FOREACH(iff, &ifs, next) {
ccea83b2
VB
838 if (optind < argc) {
839 for (i = optind; i < argc; i++)
840 if (strncmp(argv[i], iff->name, IFNAMSIZ) == 0)
841 break;
842 if (i == argc)
843 continue;
844 }
84853b92
VB
845 nb = get_nb_port(s, iff->name);
846 for (i = 0; i < nb; i++) {
847 if (!((get_chassis(s, &chassis, iff->name, i) != -1) &&
848 (get_port(s, &port, iff->name, i) != -1)))
849 continue;
850 printf("Interface: %s (via ", iff->name);
851 switch (port.p_protocol) {
852 case (LLDPD_MODE_LLDP): printf("LLDP"); break;
853 case (LLDPD_MODE_CDPV1): printf("CDPv1"); break;
854 case (LLDPD_MODE_CDPV2): printf("CDPv2"); break;
855 case (LLDPD_MODE_EDP): printf("EDP"); break;
856 case (LLDPD_MODE_FDP): printf("FDP"); break;
857 case (LLDPD_MODE_SONMP): printf("SONMP"); break;
858 default: printf("unknown protocol"); break;
859 }
860 printf(") - RID: %d\n", chassis.c_index);
43c02e7b
VB
861 display_chassis(&chassis);
862 printf("\n");
863 display_port(&port);
a1347cd8 864#ifdef ENABLE_DOT1
84853b92 865 if (get_vlans(s, &vls, iff->name, i) != -1) {
43c02e7b
VB
866 memcpy(&port.p_vlans, &vls, sizeof(struct vlans));
867 if (!TAILQ_EMPTY(&port.p_vlans)) {
868 printf("\n");
869 display_vlans(&port);
870 }
871 }
a1347cd8 872#endif
6772b237 873#ifdef ENABLE_LLDPMED
740593ff 874 if (port.p_med_cap_enabled) {
6772b237 875 printf("\n");
740593ff 876 display_med(&chassis, &port);
6772b237
VB
877 }
878#endif
43c02e7b
VB
879 printf("%s\n", sep);
880 }
881 }
740593ff
VB
882}
883
884#ifdef ENABLE_LLDPMED
8888d191 885static int
740593ff
VB
886lldpd_parse_location(struct lldpd_port *port, const char *location)
887{
888 char *l, *e, *s, *data, *n;
889 double ll, altitude;
890 u_int32_t intpart, floatpart;
891 int type = 0, i;
892
893 if (strlen(location) == 0)
894 return 0;
895 if ((l = strdup(location)) == NULL)
896 fatal(NULL);
897 s = l;
f0bd3505 898 if ((e = strchr(s, ':')) == NULL)
740593ff
VB
899 goto invalid_location;
900 *e = '\0';
901 type = atoi(s);
902 switch (type) {
903 case LLDPMED_LOCFORMAT_COORD:
904 /* Coordinates */
905 if ((port->p_med_location[0].data =
906 (char *)malloc(16)) == NULL)
907 fatal(NULL);
908 port->p_med_location[0].data_len = 16;
909 port->p_med_location[0].format = LLDPMED_LOCFORMAT_COORD;
910 data = port->p_med_location[0].data;
911
912 /* Latitude and longitude */
913 for (i = 0; i < 2; i++) {
914 s = e+1;
f0bd3505 915 if ((e = strchr(s, ':')) == NULL)
740593ff
VB
916 goto invalid_location;
917 *e = '\0';
918 ll = atof(s);
919 s = e + 1;
f0bd3505 920 if ((e = strchr(s, ':')) == NULL)
740593ff
VB
921 goto invalid_location;
922 *e = '\0';
923 intpart = (int)ll;
924 floatpart = (ll - intpart) * (1 << 25);
925 if (((i == 0) && (*s == 'S')) ||
926 ((i == 1) && (*s == 'W'))) {
927 intpart = ~intpart;
928 intpart += 1;
929 floatpart = ~floatpart;
930 floatpart += 1;
931 } else if (((i == 0) && (*s != 'N')) ||
932 ((i == 1) && (*s != 'E')))
933 goto invalid_location;
934 *(u_int8_t *)data = (6 << 2) | /* Precision */
935 ((intpart & 0x180) >> 7); /* Int part 2 bits */
936 data++;
937 *(u_int8_t *)data = (((intpart & 0x7f) << 1) | /* Int part 7 bits */
938 ((floatpart & 0x1000000) >> 24)); /* Float part 1 bit */
939 data++;
940 *(u_int8_t *)data = (floatpart & 0xff0000) >> 16; /* 8 bits */
941 data++;
942 *(u_int8_t *)data = (floatpart & 0xff00) >> 8; /* 8 bits */
943 data++;
944 *(u_int8_t *)data = (floatpart & 0xff); /* 8 bits */
945 data++;
946 }
947
948 /* Altitude */
949 s = e+1;
f0bd3505 950 if ((e = strchr(s, ':')) == NULL)
740593ff
VB
951 goto invalid_location;
952 *e = '\0';
953 altitude = atof(s);
954 s = e+1;
f0bd3505 955 if ((e = strchr(s, ':')) == NULL)
740593ff
VB
956 goto invalid_location;
957 *e = '\0';
958 if (altitude < 0) {
959 intpart = -(int)altitude;
960 floatpart = (-(altitude + intpart)) * (1 << 8);
961 intpart = ~intpart; intpart += 1;
962 floatpart = ~floatpart; floatpart += 1;
963 } else {
964 intpart = (int)altitude;
965 floatpart = (altitude - intpart) * (1 << 8);
966 }
967 if ((*s != 'm') && (*s != 'f'))
968 goto invalid_location;
969 *(u_int8_t *)data = ((((*s == 'm')?1:2) << 4) | /* Type 4 bits */
970 0); /* Precision 4 bits */
971 data++;
972 *(u_int8_t *)data = ((6 << 6) | /* Precision 2 bits */
973 ((intpart & 0x3f0000) >> 16)); /* Int 6 bits */
974 data++;
975 *(u_int8_t *)data = (intpart & 0xff00) >> 8; /* Int 8 bits */
976 data++;
977 *(u_int8_t *)data = intpart & 0xff; /* Int 8 bits */
978 data++;
979 *(u_int8_t *)data = floatpart & 0xff; /* Float 8 bits */
980 data++;
981
982 /* Datum */
983 s = e + 1;
f0bd3505 984 if (strchr(s, ':') != NULL)
740593ff
VB
985 goto invalid_location;
986 *(u_int8_t *)data = atoi(s);
987 break;
988 case LLDPMED_LOCFORMAT_CIVIC:
989 /* Civic address */
990 port->p_med_location[1].data_len = 4;
991 s = e+1;
f0bd3505 992 if ((s = strchr(s, ':')) == NULL)
740593ff
VB
993 goto invalid_location;
994 s = s+1;
995 do {
f0bd3505 996 if ((s = strchr(s, ':')) == NULL)
740593ff
VB
997 break;
998 s = s+1;
999 /* s is the beginning of the word */
f0bd3505 1000 if ((n = strchr(s, ':')) == NULL)
740593ff
VB
1001 n = s + strlen(s);
1002 /* n is the end of the word */
1003 port->p_med_location[1].data_len += (n - s) + 2;
f0bd3505 1004 if ((s = strchr(s, ':')) == NULL)
740593ff
VB
1005 break;
1006 s = s+1;
1007 } while (1);
1008 s = e+1;
1009 if ((port->p_med_location[1].data =
1010 (char *)malloc(port->p_med_location[1].data_len)) ==
1011 NULL)
1012 fatal(NULL);
1013 port->p_med_location[1].format = LLDPMED_LOCFORMAT_CIVIC;
1014 data = port->p_med_location[1].data;
1015 *(u_int8_t *)data = port->p_med_location[1].data_len - 1;
1016 data++;
1017 *(u_int8_t *)data = 2; /* Client location */
1018 data++;
f0bd3505 1019 if ((e = strchr(s, ':')) == NULL)
740593ff
VB
1020 goto invalid_location;
1021 if ((e - s) != 2)
1022 goto invalid_location;
1023 memcpy(data, s, 2); /* Country code */
1024 data += 2;
1025 while (*e != '\0') {
1026 s=e+1;
f0bd3505 1027 if ((e = strchr(s, ':')) == NULL)
740593ff
VB
1028 goto invalid_location;
1029 *e = '\0';
1030 *(u_int8_t *)data = atoi(s);
1031 data++;
1032 s=e+1;
f0bd3505 1033 if ((e = strchr(s, ':')) == NULL)
740593ff
VB
1034 e = s + strlen(s);
1035 *(u_int8_t *)data = e - s;
1036 data++;
1037 memcpy(data, s, e-s);
1038 data += e-s;
1039 }
1040 break;
1041 case LLDPMED_LOCFORMAT_ELIN:
1042 s = e+1;
1043 port->p_med_location[2].data_len = strlen(s);
1044 if ((port->p_med_location[2].data =
1045 (char *)malloc(strlen(s))) == NULL)
1046 fatal(NULL);
1047 port->p_med_location[2].format = LLDPMED_LOCFORMAT_ELIN;
1048 strcpy(port->p_med_location[2].data, s);
1049 break;
1050 default:
1051 type = 0;
1052 goto invalid_location;
1053 }
1054
1055 port->p_med_cap_enabled |= LLDPMED_CAP_LOCATION;
1056 return 0;
1057invalid_location:
1058 LLOG_WARNX("the format of the location is invalid (%s)",
1059 location);
1060 if (type) {
1061 free(port->p_med_location[type-1].data);
1062 memset(&port->p_med_location[type-1], 0,
1063 sizeof(struct lldpd_med_loc));
1064 }
1065 free(l);
1066 return -1;
1067}
1068
8888d191 1069static void
740593ff
VB
1070set_location(int s, int argc, char *argv[])
1071{
1072 int i, ch;
1073 struct interfaces ifs;
1074 struct lldpd_interface *iff;
1075 struct lldpd_port port;
1076 void *p;
1077 struct hmsg *h;
1078
1079 if ((h = (struct hmsg *)malloc(MAX_HMSGSIZE)) == NULL)
1080 fatal(NULL);
1081
1082 memset(&port, 0, sizeof(struct lldpd_port));
1083 optind = 1;
1084 while ((ch = getopt(argc, argv, "dL:")) != -1) {
1085 switch (ch) {
1086 case 'L':
1087 if ((lldpd_parse_location(&port, optarg)) == -1)
1088 fatalx("incorrect location");
1089 break;
1090 }
1091 }
1092
1093 get_interfaces(s, &ifs);
1094 TAILQ_FOREACH(iff, &ifs, next) {
1095 if (optind < argc) {
1096 for (i = optind; i < argc; i++)
1097 if (strncmp(argv[i], iff->name, IFNAMSIZ) == 0)
1098 break;
1099 if (i == argc)
1100 continue;
1101 }
1102
1103 ctl_msg_init(h, HMSG_SET_LOCATION);
1104 strlcpy((char *)&h->data, iff->name, IFNAMSIZ);
1105 h->hdr.len += IFNAMSIZ;
1106 p = (char*)&h->data + IFNAMSIZ;
1107 if (ctl_msg_pack_structure(STRUCT_LLDPD_MED_LOC
1108 STRUCT_LLDPD_MED_LOC STRUCT_LLDPD_MED_LOC,
1109 port.p_med_location,
1110 3*sizeof(struct lldpd_med_loc), h, &p) == -1) {
1111 LLOG_WARNX("set_location: unable to set location for %s", iff->name);
1112 fatalx("aborting");
1113 }
1114 if (ctl_msg_send(s, h) == -1)
1115 fatalx("set_location: unable to send request");
1116 if (ctl_msg_recv(s, h) == -1)
1117 fatalx("set_location: unable to receive answer");
1118 if (h->hdr.type != HMSG_SET_LOCATION)
1119 fatalx("set_location: unknown answer type received");
1120 LLOG_INFO("Location set succesfully for %s", iff->name);
1121 }
1122}
1123#endif
1124
1125int
1126main(int argc, char *argv[])
1127{
1128 int ch, s, debug = 1;
1129#define ACTION_SET_LOCATION 1
1130 int action = 0;
43c02e7b 1131
740593ff
VB
1132 /*
1133 * Get and parse command line options
1134 */
1135 while ((ch = getopt(argc, argv, "dL:")) != -1) {
1136 switch (ch) {
1137 case 'd':
1138 debug++;
1139 break;
1140 case 'L':
1141#ifdef ENABLE_LLDPMED
1142 action = ACTION_SET_LOCATION;
1143#else
1144 fprintf(stderr, "LLDP-MED support is not built-in\n");
1145 usage();
1146#endif
1147 break;
1148 default:
1149 usage();
1150 }
1151 }
1152
1153 log_init(debug);
43c02e7b 1154
740593ff
VB
1155 if ((s = ctl_connect(LLDPD_CTL_SOCKET)) == -1)
1156 fatalx("unable to connect to socket " LLDPD_CTL_SOCKET);
1157
1158 switch (action) {
1159#ifdef ENABLE_LLDPMED
1160 case ACTION_SET_LOCATION:
1161 set_location(s, argc, argv);
1162 break;
1163#endif
1164 default:
1165 display_interfaces(s, argc, argv);
1166 }
1167
1168 close(s);
43c02e7b
VB
1169 return 0;
1170}