{
int ret;
struct stream *s;
+ uint16_t flags = 0;
/* Check buffer size */
if (STREAM_SIZE(zclient->obuf) <
zclient_create_header(s, ZEBRA_OPAQUE_MESSAGE, VRF_DEFAULT);
- /* Send sub-type */
+ /* Send sub-type and flags */
stream_putl(s, type);
+ stream_putw(s, flags);
/* Send opaque data */
stream_write(s, data, datasize);
return ret;
}
+/*
+ * Send an OPAQUE message to a specific zclient. The contents are opaque
+ * to zebra.
+ */
+int zclient_send_opaque_unicast(struct zclient *zclient, uint32_t type,
+ uint8_t proto, uint16_t instance,
+ uint32_t session_id, const uint8_t *data,
+ size_t datasize)
+{
+ int ret;
+ struct stream *s;
+ uint16_t flags = 0;
+
+ /* Check buffer size */
+ if (STREAM_SIZE(zclient->obuf) <
+ (ZEBRA_HEADER_SIZE + sizeof(struct zapi_opaque_msg) + datasize))
+ return -1;
+
+ s = zclient->obuf;
+ stream_reset(s);
+
+ zclient_create_header(s, ZEBRA_OPAQUE_MESSAGE, VRF_DEFAULT);
+
+ /* Send sub-type and flags */
+ SET_FLAG(flags, ZAPI_OPAQUE_FLAG_UNICAST);
+ stream_putl(s, type);
+ stream_putw(s, flags);
+
+ /* Send destination client info */
+ stream_putc(s, proto);
+ stream_putw(s, instance);
+ stream_putl(s, session_id);
+
+ /* Send opaque data */
+ stream_write(s, data, datasize);
+
+ /* Put length into the header at the start of the stream. */
+ stream_putw_at(s, 0, stream_get_endp(s));
+
+ ret = zclient_send_message(zclient);
+
+ return ret;
+}
+
+/*
+ * Decode incoming opaque message into info struct
+ */
+int zclient_opaque_decode(struct stream *s, struct zapi_opaque_msg *info)
+{
+ memset(info, 0, sizeof(*info));
+
+ /* Decode subtype and flags */
+ STREAM_GETL(s, info->type);
+ STREAM_GETW(s, info->flags);
+
+ /* Decode unicast client info if present */
+ if (CHECK_FLAG(info->flags, ZAPI_OPAQUE_FLAG_UNICAST)) {
+ STREAM_GETC(s, info->proto);
+ STREAM_GETW(s, info->instance);
+ STREAM_GETL(s, info->session_id);
+ }
+
+ info->len = STREAM_READABLE(s);
+
+ return 0;
+
+stream_failure:
+
+ return -1;
+}
+
/*
* Send a registration request for opaque messages with a specified subtype.
*/
}
/* Utility to decode opaque registration info */
-int zapi_opaque_reg_decode(struct stream *s,
- struct zapi_opaque_reg_info *info)
+int zapi_opaque_reg_decode(struct stream *s, struct zapi_opaque_reg_info *info)
{
STREAM_GETL(s, info->type);
STREAM_GETC(s, info->proto);
*/
#define ZEBRA_FLAG_RR_USE_DISTANCE 0x40
+ /* The older XXX_MESSAGE flags live here */
uint8_t message;
/*
int zclient_send_opaque(struct zclient *zclient, uint32_t type,
const uint8_t *data, size_t datasize);
+int zclient_send_opaque_unicast(struct zclient *zclient, uint32_t type,
+ uint8_t proto, uint16_t instance,
+ uint32_t session_id, const uint8_t *data,
+ size_t datasize);
+
+/* Struct representing the decoded opaque header info */
+struct zapi_opaque_msg {
+ uint32_t type; /* Subtype */
+ uint16_t len; /* len after zapi header and this info */
+ uint16_t flags;
+
+ /* Client-specific info - *if* UNICAST flag is set */
+ uint8_t proto;
+ uint16_t instance;
+ uint32_t session_id;
+};
+
+#define ZAPI_OPAQUE_FLAG_UNICAST 0x01
+
/* Simple struct to convey registration/unreg requests */
struct zapi_opaque_reg_info {
/* Message subtype */
uint32_t session_id;
};
+/* Decode incoming opaque */
+int zclient_opaque_decode(struct stream *msg, struct zapi_opaque_msg *info);
+
int zclient_register_opaque(struct zclient *zclient, uint32_t type);
int zclient_unregister_opaque(struct zclient *zclient, uint32_t type);
int zapi_opaque_reg_decode(struct stream *msg,
{
struct stream *msg, *dup;
struct zmsghdr hdr;
+ struct zapi_opaque_msg info;
struct opq_msg_reg *reg;
- uint32_t type;
+ int ret;
struct opq_client_reg *client;
struct zserv *zclient;
char buf[50];
/* Dispatch to any registered ZAPI client(s) */
- /* Extract subtype */
- STREAM_GETL(msg, type);
+ /* Extract subtype and flags */
+ ret = zclient_opaque_decode(msg, &info);
+ if (ret != 0)
+ goto drop_it;
/* Look up registered ZAPI client(s) */
- reg = opq_reg_lookup(type);
+ reg = opq_reg_lookup(info.type);
if (reg == NULL) {
if (IS_ZEBRA_DEBUG_RECV)
- zlog_debug("%s: no registrations for opaque type %u",
- __func__, type);
+ zlog_debug("%s: no registrations for opaque type %u, flags %#x",
+ __func__, info.type, info.flags);
goto drop_it;
}
} else {
if (IS_ZEBRA_DEBUG_RECV)
zlog_debug("%s: type %u: no zclient for %s",
- __func__, type,
+ __func__, info.type,
opq_client2str(buf,
sizeof(buf),
client));
}
drop_it:
-stream_failure:
+
if (msg)
stream_free(msg);
}