/** * Allocate a buffer inside an atom and dump another buffer in it. * * The dump is done in hexadecimal with the provided separator. * * @param atom Atom which will be used as a container. * @param input Buffer we want to dump. * @param size Size of the buffer * @param sep Separator to use. * @param max Maximum number of bytes to dump. Can be 0 if no maximum. * @return A string representing the dump of the buffer or @c NULL if error. */ const char* _lldpctl_dump_in_atom(lldpctl_atom_t *atom, const uint8_t *input, size_t size, char sep, size_t max) { static const char truncation[] = "[...]"; size_t i, len; char *buffer = NULL; if (max > 0 && size > max) len = max * 3 + sizeof(truncation) + 1; else len = size * 3 + 1; if ((buffer = _lldpctl_alloc_in_atom(atom, len)) == NULL) return NULL; for (i = 0; (i < size) && (max == 0 || i < max); i++) snprintf(buffer + i * 3, 4, "%02x%c", *(u_int8_t*)(input + i), sep); if (max > 0 && size > max) snprintf(buffer + i * 3, sizeof(truncation) + 1, "%s", truncation); else *(buffer + i*3 - 1) = 0; return buffer; }
static lldpctl_atom_t* _lldpctl_atom_set_buffer_custom(lldpctl_atom_t *atom, lldpctl_key_t key, const u_int8_t *buf, size_t n) { struct _lldpctl_atom_custom_t *custom = (struct _lldpctl_atom_custom_t *)atom; /* Only local port can be modified */ if (!custom->parent->local) { SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST); return NULL; } switch (key) { case lldpctl_k_custom_tlv_oui: memcpy(&custom->tlv->oui, buf, min(n, sizeof(custom->tlv->oui))); return atom; case lldpctl_k_custom_tlv_oui_info_string: if (n == 0 || n > LLDP_TLV_ORG_OUI_INFO_MAXLEN) { SET_ERROR(atom->conn, LLDPCTL_ERR_BAD_VALUE); return NULL; } custom->tlv->oui_info_len = n; if (!(custom->tlv->oui_info = _lldpctl_alloc_in_atom(atom, n))) { custom->tlv->oui_info_len = 0; SET_ERROR(atom->conn, LLDPCTL_ERR_NOMEM); return NULL; } memcpy(custom->tlv->oui_info, buf, n); return atom; default: SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST); return NULL; } }
static lldpctl_atom_t* _lldpctl_atom_create_custom_list(lldpctl_atom_t *atom) { struct _lldpctl_atom_custom_list_t *custom = (struct _lldpctl_atom_custom_list_t *)atom; struct lldpd_custom *tlv; tlv = _lldpctl_alloc_in_atom(atom, sizeof(struct lldpd_custom)); if (!tlv) return NULL; return _lldpctl_new_atom(atom->conn, atom_custom, custom->parent, tlv); }
const char* lldpctl_atom_get_str(lldpctl_atom_t *atom, lldpctl_key_t key) { char *strresult = NULL; const uint8_t *bufresult = NULL; long int intresult = -1; int n1; size_t n2; if (atom == NULL) return NULL; RESET_ERROR(atom->conn); if (atom->get_str != NULL) { strresult = (char *)atom->get_str(atom, key); if (strresult) return strresult; if (lldpctl_last_error(atom->conn) != LLDPCTL_ERR_NOT_EXIST) return NULL; } RESET_ERROR(atom->conn); if (atom->get_int != NULL) { intresult = atom->get_int(atom, key); if (lldpctl_last_error(atom->conn) != LLDPCTL_ERR_NOT_EXIST) { strresult = _lldpctl_alloc_in_atom(atom, 21); if (!strresult) return NULL; n1 = snprintf(strresult, 21, "%ld", intresult); if (n1 > -1 && n1 < 21) return strresult; SET_ERROR(atom->conn, LLDPCTL_ERR_NOMEM); /* Not really true... */ return NULL; } } RESET_ERROR(atom->conn); if (atom->get_buffer != NULL) { bufresult = atom->get_buffer(atom, key, &n2); if (bufresult) return _lldpctl_dump_in_atom(atom, bufresult, n2, ' ', 0); if (lldpctl_last_error(atom->conn) != LLDPCTL_ERR_NOT_EXIST) return NULL; } SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST); return NULL; }
static struct _lldpctl_atom_config_t* __lldpctl_atom_set_str_config(struct _lldpctl_atom_config_t *c, char **local, char **global, const char *value) { if (value) { char *aval = NULL; size_t len = strlen(value) + 1; aval = _lldpctl_alloc_in_atom((lldpctl_atom_t *)c, len); if (!aval) return NULL; memcpy(aval, value, len); *local = aval; free(*global); *global = strdup(aval); } else { free(*global); *local = *global = NULL; } return c; }
static const char* _lldpctl_atom_get_str_mgmt(lldpctl_atom_t *atom, lldpctl_key_t key) { char *ipaddress = NULL; size_t len; int af; struct _lldpctl_atom_mgmt_t *m = (struct _lldpctl_atom_mgmt_t *)atom; /* Local and remote port */ switch (key) { case lldpctl_k_mgmt_ip: switch (m->mgmt->m_family) { case LLDPD_AF_IPV4: len = INET_ADDRSTRLEN + 1; af = AF_INET; break; case LLDPD_AF_IPV6: len = INET6_ADDRSTRLEN + 1; af = AF_INET6; break; default: len = 0; } if (len == 0) break; ipaddress = _lldpctl_alloc_in_atom(atom, len); if (!ipaddress) return NULL; if (inet_ntop(af, &m->mgmt->m_addr, ipaddress, len) == NULL) break; return ipaddress; default: SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST); return NULL; } SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST); return NULL; }
static const char* _lldpctl_atom_get_str_port(lldpctl_atom_t *atom, lldpctl_key_t key) { struct _lldpctl_atom_port_t *p = (struct _lldpctl_atom_port_t *)atom; struct lldpd_port *port = p->port; struct lldpd_hardware *hardware = p->hardware; char *ipaddress = NULL; size_t len; /* Local port only */ switch (key) { case lldpctl_k_port_name: if (hardware != NULL) return hardware->h_ifname; break; case lldpctl_k_port_status: if (p->local) return map_lookup(port_status_map.map, LLDPD_RXTX_FROM_PORT(port)); break; default: break; } if (!port) return NULL; /* Local and remote port */ switch (key) { case lldpctl_k_port_protocol: return map_lookup(lldpd_protocol_map.map, port->p_protocol); case lldpctl_k_port_id_subtype: return map_lookup(port_id_subtype_map, port->p_id_subtype); case lldpctl_k_port_id: switch (port->p_id_subtype) { case LLDP_PORTID_SUBTYPE_IFNAME: case LLDP_PORTID_SUBTYPE_IFALIAS: case LLDP_PORTID_SUBTYPE_LOCAL: return port->p_id; case LLDP_PORTID_SUBTYPE_LLADDR: return _lldpctl_dump_in_atom(atom, (uint8_t*)port->p_id, port->p_id_len, ':', 0); case LLDP_PORTID_SUBTYPE_ADDR: switch (port->p_id[0]) { case LLDP_MGMT_ADDR_IP4: len = INET_ADDRSTRLEN + 1; break; case LLDP_MGMT_ADDR_IP6: len = INET6_ADDRSTRLEN + 1; break; default: len = 0; } if (len > 0) { ipaddress = _lldpctl_alloc_in_atom(atom, len); if (!ipaddress) return NULL; if (inet_ntop((port->p_id[0] == LLDP_MGMT_ADDR_IP4)? AF_INET:AF_INET6, &port->p_id[1], ipaddress, len) == NULL) break; return ipaddress; } break; } SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST); return NULL; case lldpctl_k_port_descr: return port->p_descr; #ifdef ENABLE_DOT3 case lldpctl_k_port_dot3_mautype: return map_lookup(operational_mau_type_values, port->p_macphy.mau_type); #endif default: /* Compatibility: query the associated chassis too */ return lldpctl_atom_get_str(p->chassis, key); } }