]> git.ipfire.org Git - thirdparty/lldpd.git/blob - src/client/lldpctl.c
75f733b687d0c5b11ef6d3c4e542a5d6b84c5258
[thirdparty/lldpd.git] / src / client / lldpctl.c
1 /* -*- mode: c; c-file-style: "openbsd" -*- */
2 /*
3 * Copyright (c) 2008 Vincent Bernat <bernat@luffy.cx>
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <unistd.h>
21 #include <time.h>
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
28 #include "../log.h"
29 #include "../ctl.h"
30 #include "client.h"
31
32 static void usage(void);
33
34 #ifdef HAVE___PROGNAME
35 extern const char *__progname;
36 #else
37 # define __progname "lldpctl"
38 #endif
39
40
41 static void
42 usage(void)
43 {
44 fprintf(stderr, "Usage: %s [OPTIONS ...] [INTERFACES ...]\n", __progname);
45 fprintf(stderr, "Version: %s\n", PACKAGE_STRING);
46
47 fprintf(stderr, "\n");
48
49 fprintf(stderr, "-d Enable more debugging information.\n");
50 fprintf(stderr, "-a Display all remote ports, including hidden ones.\n");
51 fprintf(stderr, "-w Watch for changes.\n");
52 fprintf(stderr, "-C Display global configuration of lldpd.\n");
53 fprintf(stderr, "-N Make lldpd transmit LLDP PDU now.\n");
54 fprintf(stderr, "-f format Choose output format (plain, keyvalue or xml).\n");
55 fprintf(stderr, "-L location Enable the transmission of LLDP-MED location TLV for the\n");
56 fprintf(stderr, " given interfaces. Can be repeated to enable the transmission\n");
57 fprintf(stderr, " of the location in several formats.\n");
58 fprintf(stderr, "-P policy Enable the transmission of LLDP-MED Network Policy TLVs\n");
59 fprintf(stderr, " for the given interfaces. Can be repeated to specify\n");
60 fprintf(stderr, " different policies.\n");
61 fprintf(stderr, "-O poe Enable the transmission of LLDP-MED POE-MDI TLV\n");
62 fprintf(stderr, " for the given interfaces.\n");
63 fprintf(stderr, "-o poe Enable the transmission of Dot3 POE-MDI TLV\n");
64 fprintf(stderr, " for the given interfaces.\n");
65
66 fprintf(stderr, "\n");
67
68 fprintf(stderr, "see manual page lldpctl(8) for more information\n");
69 exit(1);
70 }
71
72 struct cbargs {
73 int argc;
74 char **argv;
75 struct writer *w;
76 };
77
78 void
79 watchcb(lldpctl_conn_t *conn,
80 lldpctl_change_t type,
81 lldpctl_atom_t *interface,
82 lldpctl_atom_t *neighbor,
83 void *data)
84 {
85 int ch, i;
86 struct cbargs *args = data;
87 optind = 0;
88 while ((ch = getopt(args->argc, args->argv, LLDPCTL_ARGS)) != -1);
89 if (optind < args->argc) {
90 for (i = optind; i < args->argc; i++)
91 if (strcmp(args->argv[i],
92 lldpctl_atom_get_str(interface,
93 lldpctl_k_interface_name)) == 0)
94 break;
95 if (i == args->argc)
96 return;
97 }
98 switch (type) {
99 case lldpctl_c_deleted:
100 tag_start(args->w, "lldp-deleted", "LLDP neighbor deleted");
101 break;
102 case lldpctl_c_updated:
103 tag_start(args->w, "lldp-updated", "LLDP neighbor updated");
104 break;
105 case lldpctl_c_added:
106 tag_start(args->w, "lldp-added", "LLDP neighbor added");
107 break;
108 default: return;
109 }
110 display_interface(conn, args->w, 1, interface, neighbor);
111 tag_end(args->w);
112 }
113
114 int
115 main(int argc, char *argv[])
116 {
117 int ch, debug = 1;
118 char *fmt = "plain";
119 int action = 0, hidden = 0, watch = 0, configuration = 0, now = 0;
120 lldpctl_conn_t *conn;
121 struct cbargs args;
122
123 /* Get and parse command line options */
124 while ((ch = getopt(argc, argv, LLDPCTL_ARGS)) != -1) {
125 switch (ch) {
126 case 'h':
127 usage();
128 break;
129 case 'd':
130 debug++;
131 break;
132 case 'v':
133 fprintf(stdout, "%s\n", PACKAGE_VERSION);
134 exit(0);
135 break;
136 case 'a':
137 hidden = 1;
138 break;
139 case 'f':
140 fmt = optarg;
141 break;
142 case 'L':
143 case 'P':
144 case 'O':
145 case 'o':
146 action = 1;
147 break;
148 case 'w':
149 watch = 1;
150 break;
151 case 'C':
152 configuration = 1;
153 break;
154 case 'N':
155 now = 1;
156 break;
157 default:
158 usage();
159 }
160 }
161
162 log_init(debug, __progname);
163
164 if ((action != 0) &&
165 (getuid() != geteuid() || getgid() != getegid())) {
166 fatalx("mere mortals may not do that, admin privileges are required.");
167 }
168
169 conn = lldpctl_new(NULL, NULL, NULL);
170 if (conn == NULL) exit(EXIT_FAILURE);
171
172 args.argc = argc;
173 args.argv = argv;
174 if (watch) {
175 if (lldpctl_watch_callback(conn, watchcb, &args) < 0) {
176 LLOG_WARNX("unable to watch for neighbors. %s",
177 lldpctl_last_strerror(conn));
178 exit(EXIT_FAILURE);
179 }
180 }
181
182 do {
183 if (strcmp(fmt, "plain") == 0) {
184 args.w = txt_init(stdout);
185 } else if (strcmp(fmt, "keyvalue") == 0) {
186 args.w = kv_init(stdout);
187 }
188 #ifdef USE_XML
189 else if (strcmp(fmt,"xml") == 0 ) {
190 args.w = xml_init(stdout);
191 }
192 #endif
193 else {
194 args.w = txt_init(stdout);
195 }
196
197 if (action) {
198 modify_interfaces(conn, argc, argv, optind);
199 } else if (watch) {
200 if (lldpctl_watch(conn) < 0) {
201 LLOG_WARNX("unable to watch for neighbors. %s",
202 lldpctl_last_strerror(conn));
203 watch = 0;
204 }
205 } else if (configuration) {
206 display_configuration(conn, args.w);
207 } else if (now) {
208 lldpctl_atom_t *config = lldpctl_get_configuration(conn);
209 if (config == NULL) {
210 LLOG_WARNX("unable to get configuration from lldpd. %s",
211 lldpctl_last_strerror(conn));
212 } else {
213 if (lldpctl_atom_set_int(config,
214 lldpctl_k_config_tx_interval, -1) == NULL) {
215 LLOG_WARNX("unable to ask lldpd for immediate retransmission. %s",
216 lldpctl_last_strerror(conn));
217 } else
218 LLOG_INFO("immediate retransmission requested successfuly");
219 lldpctl_atom_dec_ref(config);
220 }
221 } else {
222 display_interfaces(conn, args.w,
223 hidden, argc, argv);
224 }
225 args.w->finish(args.w);
226 } while (watch);
227
228 lldpctl_release(conn);
229 return EXIT_SUCCESS;
230 }