1 /* -*- mode: c; c-file-style: "openbsd" -*- */ 2 /* 3 * Copyright (c) 2012 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 <sys/queue.h> 19 #include "../lldpd-structs.h" 20 #include "../compat/compat.h" 21 #include "../marshal.h" 22 #include "../ctl.h" 23 24 /* connection.c */ 25 struct lldpctl_conn_t { 26 /* the Unix-domain socket to connect to lldpd */ 27 char *ctlname; 28 29 /* Callback handling */ 30 lldpctl_recv_callback recv; /* Receive callback */ 31 lldpctl_send_callback send; /* Send callback */ 32 void *user_data; /* Callback user data */ 33 34 /* IO state handling. */ 35 uint8_t *input_buffer; /* Current input/output buffer */ 36 uint8_t *output_buffer; /* Current input/output buffer */ 37 size_t input_buffer_len; 38 size_t output_buffer_len; 39 40 #define CONN_STATE_IDLE 0 41 #define CONN_STATE_GET_INTERFACES_SEND 1 42 #define CONN_STATE_GET_INTERFACES_RECV 2 43 #define CONN_STATE_GET_PORT_SEND 3 44 #define CONN_STATE_GET_PORT_RECV 4 45 #define CONN_STATE_SET_PORT_SEND 5 46 #define CONN_STATE_SET_PORT_RECV 6 47 #define CONN_STATE_SET_WATCH_SEND 7 48 #define CONN_STATE_SET_WATCH_RECV 8 49 #define CONN_STATE_GET_CONFIG_SEND 9 50 #define CONN_STATE_GET_CONFIG_RECV 10 51 #define CONN_STATE_SET_CONFIG_SEND 11 52 #define CONN_STATE_SET_CONFIG_RECV 12 53 #define CONN_STATE_GET_CHASSIS_SEND 13 54 #define CONN_STATE_GET_CHASSIS_RECV 14 55 #define CONN_STATE_GET_DEFAULT_PORT_SEND 15 56 #define CONN_STATE_GET_DEFAULT_PORT_RECV 16 57 #define CONN_STATE_WATCHING 17 58 int state; /* Current state */ 59 /* Data attached to the state. It is used to check that we are using the 60 * same data as a previous call until the state machine goes to 61 * CONN_STATE_IDLE. */ 62 char state_data[IFNAMSIZ + 64]; 63 /* Error handling */ 64 lldpctl_error_t error; /* Last error */ 65 66 /* Handling notifications */ 67 lldpctl_change_callback watch_cb; 68 lldpctl_change_callback2 watch_cb2; 69 void *watch_data; 70 int watch_triggered; 71 }; 72 73 /* User data for synchronous callbacks. */ 74 struct lldpctl_conn_sync_t { 75 int fd; /* File descriptor to the socket. */ 76 }; 77 78 ssize_t _lldpctl_needs(lldpctl_conn_t *lldpctl, size_t length); 79 int _lldpctl_do_something(lldpctl_conn_t *conn, 80 int state_send, int state_recv, const char *state_data, 81 enum hmsg_type type, 82 void *to_send, struct marshal_info *mi_send, 83 void **to_recv, struct marshal_info *mi_recv); 84 85 /* errors.c */ 86 #define SET_ERROR(conn, x) ((conn)->error = x) 87 #define RESET_ERROR(conn) SET_ERROR((conn), LLDPCTL_NO_ERROR) 88 89 90 /* atom.c and atom-private.c */ 91 typedef enum { 92 atom_config, 93 atom_interfaces_list, 94 atom_interface, 95 atom_ports_list, 96 atom_port, 97 atom_mgmts_list, 98 atom_mgmt, 99 #ifdef ENABLE_DOT3 100 atom_dot3_power, 101 #endif 102 #ifdef ENABLE_DOT1 103 atom_vlans_list, 104 atom_vlan, 105 atom_ppvids_list, 106 atom_ppvid, 107 atom_pis_list, 108 atom_pi, 109 #endif 110 #ifdef ENABLE_LLDPMED 111 atom_med_policies_list, 112 atom_med_policy, 113 atom_med_locations_list, 114 atom_med_location, 115 atom_med_caelements_list, 116 atom_med_caelement, 117 atom_med_power, 118 #endif 119 #ifdef ENABLE_CUSTOM 120 atom_custom_list, 121 atom_custom, 122 #endif 123 atom_chassis, 124 } atom_t; 125 126 void *_lldpctl_alloc_in_atom(lldpctl_atom_t *, size_t); 127 const char *_lldpctl_dump_in_atom(lldpctl_atom_t *, const uint8_t *, size_t, char, size_t); 128 129 struct atom_buffer { 130 TAILQ_ENTRY(atom_buffer) next; 131 u_int8_t data[0]; 132 }; 133 134 struct lldpctl_atom_t { 135 int count; 136 atom_t type; 137 lldpctl_conn_t *conn; 138 TAILQ_HEAD(, atom_buffer) buffers; /* List of buffers */ 139 140 /* Destructor */ 141 void (*free)(lldpctl_atom_t *); 142 143 /* Iterators */ 144 lldpctl_atom_iter_t *(*iter)(lldpctl_atom_t *); 145 lldpctl_atom_iter_t *(*next)(lldpctl_atom_t *, lldpctl_atom_iter_t *); 146 lldpctl_atom_t *(*value)(lldpctl_atom_t *, lldpctl_atom_iter_t *); 147 148 /* Getters */ 149 lldpctl_atom_t *(*get)(lldpctl_atom_t *, lldpctl_key_t); 150 const char *(*get_str)(lldpctl_atom_t *, lldpctl_key_t); 151 const u_int8_t *(*get_buffer)(lldpctl_atom_t *, lldpctl_key_t, size_t *); 152 long int (*get_int)(lldpctl_atom_t *, lldpctl_key_t); 153 154 /* Setters */ 155 lldpctl_atom_t *(*set)(lldpctl_atom_t *, lldpctl_key_t, lldpctl_atom_t *); 156 lldpctl_atom_t *(*set_str)(lldpctl_atom_t *, lldpctl_key_t, const char *); 157 lldpctl_atom_t *(*set_buffer)(lldpctl_atom_t *, lldpctl_key_t, const u_int8_t *, size_t); 158 lldpctl_atom_t *(*set_int)(lldpctl_atom_t *, lldpctl_key_t, long int); 159 lldpctl_atom_t *(*create)(lldpctl_atom_t *); 160 }; 161 162 struct _lldpctl_atom_config_t { 163 lldpctl_atom_t base; 164 struct lldpd_config *config; 165 }; 166 167 struct _lldpctl_atom_interfaces_list_t { 168 lldpctl_atom_t base; 169 struct lldpd_interface_list *ifs; 170 }; 171 172 struct _lldpctl_atom_interface_t { 173 lldpctl_atom_t base; 174 char *name; 175 }; 176 177 struct _lldpctl_atom_chassis_t { 178 lldpctl_atom_t base; 179 struct lldpd_chassis *chassis; 180 struct _lldpctl_atom_port_t *parent; /* Optional: parent of this atom (owning our reference) */ 181 int embedded; /* This atom is "embedded" (not refcounted) */ 182 }; 183 184 struct _lldpctl_atom_port_t { 185 lldpctl_atom_t base; 186 int local; /* Local or remote port? */ 187 struct lldpd_hardware *hardware; /* Local port only (but optional) */ 188 struct lldpd_port *port; /* Local and remote */ 189 struct _lldpctl_atom_port_t *parent; /* Local port if we are a remote port */ 190 lldpctl_atom_t *chassis; /* Internal atom for chassis */ 191 }; 192 193 /* Can represent any simple list holding just a reference to a port. */ 194 struct _lldpctl_atom_any_list_t { 195 lldpctl_atom_t base; 196 struct _lldpctl_atom_port_t *parent; 197 }; 198 199 struct _lldpctl_atom_mgmts_list_t { 200 lldpctl_atom_t base; 201 lldpctl_atom_t *parent; 202 struct lldpd_chassis *chassis; /* Chassis containing the list of IP addresses */ 203 }; 204 205 struct _lldpctl_atom_mgmt_t { 206 lldpctl_atom_t base; 207 lldpctl_atom_t *parent; 208 struct lldpd_mgmt *mgmt; 209 }; 210 211 #ifdef ENABLE_DOT3 212 struct _lldpctl_atom_dot3_power_t { 213 lldpctl_atom_t base; 214 struct _lldpctl_atom_port_t *parent; 215 }; 216 #endif 217 218 #ifdef ENABLE_DOT1 219 struct _lldpctl_atom_vlan_t { 220 lldpctl_atom_t base; 221 struct _lldpctl_atom_port_t *parent; 222 struct lldpd_vlan *vlan; 223 }; 224 225 struct _lldpctl_atom_ppvid_t { 226 lldpctl_atom_t base; 227 struct _lldpctl_atom_port_t *parent; 228 struct lldpd_ppvid *ppvid; 229 }; 230 231 struct _lldpctl_atom_pi_t { 232 lldpctl_atom_t base; 233 struct _lldpctl_atom_port_t *parent; 234 struct lldpd_pi *pi; 235 }; 236 #endif 237 238 #ifdef ENABLE_LLDPMED 239 struct _lldpctl_atom_med_policy_t { 240 lldpctl_atom_t base; 241 struct _lldpctl_atom_port_t *parent; 242 struct lldpd_med_policy *policy; 243 }; 244 245 struct _lldpctl_atom_med_location_t { 246 lldpctl_atom_t base; 247 struct _lldpctl_atom_port_t *parent; 248 struct lldpd_med_loc *location; 249 }; 250 251 /* This list should have the same structure than _llpdctl_atom_any_list_t */ 252 struct _lldpctl_atom_med_caelements_list_t { 253 lldpctl_atom_t base; 254 struct _lldpctl_atom_med_location_t *parent; 255 }; 256 257 struct _lldpctl_atom_med_caelement_t { 258 lldpctl_atom_t base; 259 struct _lldpctl_atom_med_location_t *parent; 260 int type; 261 uint8_t *value; 262 size_t len; 263 }; 264 265 struct _lldpctl_atom_med_power_t { 266 lldpctl_atom_t base; 267 struct _lldpctl_atom_port_t *parent; 268 }; 269 #endif 270 271 #ifdef ENABLE_CUSTOM 272 struct _lldpctl_atom_custom_list_t { 273 lldpctl_atom_t base; 274 struct _lldpctl_atom_port_t *parent; 275 struct lldpd_custom_list *list; 276 }; 277 278 struct _lldpctl_atom_custom_t { 279 lldpctl_atom_t base; 280 struct _lldpctl_atom_port_t *parent; 281 int op; 282 struct lldpd_custom *tlv; 283 }; 284 #endif 285 286 struct lldpctl_atom_t *_lldpctl_new_atom(lldpctl_conn_t *conn, atom_t type, ...); 287 288 struct atom_map { 289 int key; 290 struct atom_map *next; 291 lldpctl_map_t map[]; 292 }; 293 294 void atom_map_register(struct atom_map *map, int); 295 void init_atom_map(void); 296 297 #define ATOM_MAP_REGISTER(NAME, PRIO) void init_atom_map_ ## NAME() { atom_map_register(& NAME, PRIO); } 298 299 struct atom_builder { 300 atom_t type; /* Atom type */ 301 size_t size; /* Size of structure to allocate */ 302 int (*init)(lldpctl_atom_t *, va_list); /* Optional additional init steps */ 303 void (*free)(lldpctl_atom_t *); /* Optional deallocation steps */ 304 305 lldpctl_atom_iter_t* (*iter)(lldpctl_atom_t *); /* Optional, return an iterator for this object */ 306 lldpctl_atom_iter_t* (*next)(lldpctl_atom_t *, lldpctl_atom_iter_t *); /* Return the next object for the provided iterator */ 307 lldpctl_atom_t* (*value)(lldpctl_atom_t *, lldpctl_atom_iter_t *); /* Return the current object for the provided iterator */ 308 309 lldpctl_atom_t* (*get)(lldpctl_atom_t *, lldpctl_key_t); 310 const char* (*get_str)(lldpctl_atom_t *, lldpctl_key_t); 311 const u_int8_t* (*get_buffer)(lldpctl_atom_t *, lldpctl_key_t, size_t *); 312 long int (*get_int)(lldpctl_atom_t *, lldpctl_key_t); 313 314 lldpctl_atom_t* (*set)(lldpctl_atom_t *, lldpctl_key_t, lldpctl_atom_t *); 315 lldpctl_atom_t* (*set_str)(lldpctl_atom_t *, lldpctl_key_t, const char *); 316 lldpctl_atom_t* (*set_buffer)(lldpctl_atom_t *, lldpctl_key_t, const u_int8_t *, size_t); 317 lldpctl_atom_t* (*set_int)(lldpctl_atom_t *, lldpctl_key_t, long int); 318 lldpctl_atom_t* (*create)(lldpctl_atom_t *); 319 struct atom_builder *nextb; 320 }; 321 322 void atom_builder_register(struct atom_builder *builder, int); 323 void init_atom_builder(void); 324 325 #define ATOM_BUILDER_REGISTER(NAME, PRIO) void init_atom_builder_ ## NAME() { atom_builder_register(& NAME, PRIO); } 326