static struct sk_buff *cfg_set_own_addr(void) { u32 addr; if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR)) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); addr = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); if (addr == tipc_own_addr) return tipc_cfg_reply_none(); if (!tipc_addr_node_valid(addr)) return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE " (node address)"); if (tipc_mode == TIPC_NET_MODE) return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED " (cannot change node address once assigned)"); tipc_own_addr = addr; /* * Must release all spinlocks before calling start_net() because * Linux version of TIPC calls eth_media_start() which calls * register_netdevice_notifier() which may block! * * Temporarily releasing the lock should be harmless for non-Linux TIPC, * but Linux version of eth_media_start() should really be reworked * so that it can be called with spinlocks held. */ spin_unlock_bh(&config_lock); tipc_core_start_net(); spin_lock_bh(&config_lock); return tipc_cfg_reply_none(); }
static struct sk_buff *tipc_show_stats(void) { struct sk_buff *buf; struct tlv_desc *rep_tlv; struct print_buf pb; int str_len; u32 value; if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); value = ntohl(*(u32 *)TLV_DATA(req_tlv_area)); if (value != 0) return tipc_cfg_reply_error_string("unsupported argument"); buf = tipc_cfg_reply_alloc(TLV_SPACE(MAX_STATS_INFO)); if (buf == NULL) return NULL; rep_tlv = (struct tlv_desc *)buf->data; tipc_printbuf_init(&pb, (char *)TLV_DATA(rep_tlv), MAX_STATS_INFO); tipc_printf(&pb, "TIPC version " TIPC_MOD_VER "\n"); /* Use additional tipc_printf()'s to return more info ... */ str_len = tipc_printbuf_validate(&pb); skb_put(buf, TLV_SPACE(str_len)); TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); return buf; }
static struct sk_buff *cfg_set_own_addr(void) { u32 addr; if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR)) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); addr = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); if (addr == tipc_own_addr) return tipc_cfg_reply_none(); if (!tipc_addr_node_valid(addr)) return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE " (node address)"); if (tipc_own_addr) return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED " (cannot change node address once assigned)"); /* * Must temporarily release configuration spinlock while switching into * networking mode as it calls tipc_eth_media_start(), which may sleep. * Releasing the lock is harmless as other locally-issued configuration * commands won't occur until this one completes, and remotely-issued * configuration commands can't be received until a local configuration * command to enable the first bearer is received and processed. */ spin_unlock_bh(&config_lock); tipc_core_start_net(addr); spin_lock_bh(&config_lock); return tipc_cfg_reply_none(); }
static struct sk_buff *tipc_show_stats(void) { struct sk_buff *buf; struct tlv_desc *rep_tlv; char *pb; int pb_len; int str_len; u32 value; if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); value = ntohl(*(u32 *)TLV_DATA(req_tlv_area)); if (value != 0) return tipc_cfg_reply_error_string("unsupported argument"); buf = tipc_cfg_reply_alloc(TLV_SPACE(ULTRA_STRING_MAX_LEN)); if (buf == NULL) return NULL; rep_tlv = (struct tlv_desc *)buf->data; pb = TLV_DATA(rep_tlv); pb_len = ULTRA_STRING_MAX_LEN; str_len = tipc_snprintf(pb, pb_len, "TIPC version " TIPC_MOD_VER "\n"); str_len += 1; /* for "\0" */ skb_put(buf, TLV_SPACE(str_len)); TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); return buf; }
static struct sk_buff *cfg_disable_bearer(void) { if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_BEARER_NAME)) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); if (tipc_disable_bearer((char *)TLV_DATA(req_tlv_area))) return tipc_cfg_reply_error_string("unable to disable bearer"); return tipc_cfg_reply_none(); }
static struct sk_buff *cfg_set_remote_mng(void) { u32 value; if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); tipc_remote_management = (value != 0); return tipc_cfg_reply_none(); }
static struct sk_buff *cfg_set_max_clusters(void) { u32 value; if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); if (value != delimit(value, 1, 1)) return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE " (max clusters fixed at 1)"); return tipc_cfg_reply_none(); }
static struct sk_buff *cfg_set_max_slaves(void) { u32 value; if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); if (value != 0) return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED " (max secondary nodes fixed at 0)"); return tipc_cfg_reply_none(); }
static struct sk_buff *cfg_set_own_addr(void) { u32 addr; if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR)) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); addr = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); if (addr == tipc_own_addr) return tipc_cfg_reply_none(); if (!tipc_addr_node_valid(addr)) return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE " (node address)"); <<<<<<< HEAD
struct sk_buff *tipc_log_resize(const void *req_tlv_area, int req_tlv_space) { u32 value; if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); if (value != delimit(value, 0, 32768)) return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE " (log size must be 0-32768)"); tipc_log_reinit(value); return tipc_cfg_reply_none(); }
static struct sk_buff *cfg_set_max_subscriptions(void) { u32 value; if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); if (value != delimit(value, 1, 65535)) return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE " (max subscriptions must be 1-65535"); tipc_max_subscriptions = value; return tipc_cfg_reply_none(); }
static struct sk_buff *cfg_enable_bearer(void) { struct tipc_bearer_config *args; if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_BEARER_CONFIG)) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); args = (struct tipc_bearer_config *)TLV_DATA(req_tlv_area); if (tipc_enable_bearer(args->name, ntohl(args->detect_scope), ntohl(args->priority))) return tipc_cfg_reply_error_string("unable to enable bearer"); return tipc_cfg_reply_none(); }
static struct sk_buff *cfg_set_max_ports(void) { u32 value; if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); if (value == tipc_max_ports) return tipc_cfg_reply_none(); if (value < 127 || value > 65535) return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE " (max ports must be 127-65535)"); return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED " (cannot change max ports while TIPC is active)"); }
struct sk_buff *tipc_log_resize_cmd(const void *req_tlv_area, int req_tlv_space) { u32 value; if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); if (value > 32768) return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE " (log size must be 0-32768)"); if (tipc_log_resize(value)) return tipc_cfg_reply_error_string( "unable to create specified log (log size is now 0)"); return tipc_cfg_reply_none(); }
static struct sk_buff *cfg_set_netid(void) { u32 value; if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); if (value == tipc_net_id) return tipc_cfg_reply_none(); if (value != delimit(value, 1, 9999)) return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE " (network id must be 1-9999)"); if (tipc_mode == TIPC_NET_MODE) return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED " (cannot change network id once TIPC has joined a network)"); tipc_net_id = value; return tipc_cfg_reply_none(); }
static struct sk_buff *cfg_set_max_ports(void) { u32 value; if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); value = *(u32 *)TLV_DATA(req_tlv_area); value = ntohl(value); if (value == tipc_max_ports) return tipc_cfg_reply_none(); if (value != delimit(value, 127, 65535)) return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE " (max ports must be 127-65535)"); if (tipc_mode != TIPC_NOT_RUNNING) return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED " (cannot change max ports while TIPC is active)"); tipc_max_ports = value; return tipc_cfg_reply_none(); }
static struct sk_buff *cfg_set_max_nodes(void) { u32 value; if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); value = *(u32 *)TLV_DATA(req_tlv_area); value = ntohl(value); if (value == tipc_max_nodes) return tipc_cfg_reply_none(); if (value != delimit(value, 8, 2047)) return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE " (max nodes must be 8-2047)"); if (tipc_mode == TIPC_NET_MODE) return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED " (cannot change max nodes once TIPC has joined a network)"); tipc_max_nodes = value; return tipc_cfg_reply_none(); }
static struct sk_buff *cfg_set_own_addr(void) { u32 addr; if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR)) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); addr = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); if (addr == tipc_own_addr) return tipc_cfg_reply_none(); if (!tipc_addr_node_valid(addr)) return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE " (node address)"); if (tipc_own_addr) return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED " (cannot change node address once assigned)"); tipc_net_start(addr); return tipc_cfg_reply_none(); }
static void dissect_pgmopts(ptvcursor_t* cursor, packet_info *pinfo, const char *pktname) { proto_item *tf, *ti, *ti_len; proto_tree *opts_tree = NULL; proto_tree *opt_tree = NULL; tvbuff_t *tvb = ptvcursor_tvbuff(cursor); gboolean theend = FALSE; guint16 opts_total_len; guint8 genopts_type; guint8 genopts_len; guint8 opts_type; opts_tree = proto_tree_add_subtree_format(ptvcursor_tree(cursor), tvb, ptvcursor_current_offset(cursor), -1, ett_pgm_opts, &tf, "%s Options", pktname); ptvcursor_set_tree(cursor, opts_tree); opts_type = tvb_get_guint8(tvb, ptvcursor_current_offset(cursor)); ti = ptvcursor_add(cursor, hf_pgm_opt_type, 1, ENC_BIG_ENDIAN); if (opts_type != PGM_OPT_LENGTH) { expert_add_info_format(pinfo, ti, &ei_pgm_opt_type, "%s Options - initial option is %s, should be %s", pktname, val_to_str(opts_type, opt_vals, "Unknown (0x%02x)"), val_to_str(PGM_OPT_LENGTH, opt_vals, "Unknown (0x%02x)")); return; } ptvcursor_add(cursor, hf_pgm_opt_len, 1, ENC_BIG_ENDIAN); opts_total_len = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor)); proto_item_append_text(tf, " (Total Length %d)", opts_total_len); proto_item_set_len(tf, opts_total_len); ti_len = ptvcursor_add(cursor, hf_pgm_opt_tlen, 2, ENC_BIG_ENDIAN); if (opts_total_len < 4) { expert_add_info_format(pinfo, ti_len, &ei_pgm_opt_tlen, "%s Options (Total Length %u - invalid, must be >= 4)", pktname, opts_total_len); return; } for (opts_total_len -= 4; !theend && opts_total_len != 0;){ if (opts_total_len < 4) { expert_add_info_format(pinfo, ti_len, &ei_pgm_opt_tlen, "Remaining total options length doesn't have enough for an options header"); break; } genopts_type = tvb_get_guint8(tvb, ptvcursor_current_offset(cursor)); genopts_len = tvb_get_guint8(tvb, ptvcursor_current_offset(cursor)+1); if (genopts_type & PGM_OPT_END) { genopts_type &= ~PGM_OPT_END; theend = TRUE; } switch(genopts_type) { case PGM_OPT_JOIN:{ TLV_CHECK(ett_pgm_opts_join); ptvcursor_set_tree(cursor, opt_tree); ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN); if (genopts_len < PGM_OPT_JOIN_SIZE) { proto_tree_add_uint_format_value(opt_tree, hf_pgm_genopt_len, tvb, ptvcursor_current_offset(cursor), 1, genopts_len, "%u (bogus, must be >= %u)", genopts_len, PGM_OPT_JOIN_SIZE); break; } ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_join_res, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_join_minjoin, 4, ENC_BIG_ENDIAN); break; } case PGM_OPT_PARITY_PRM:{ guint8 optdata_po; TLV_CHECK(ett_pgm_opts_parityprm); ptvcursor_set_tree(cursor, opt_tree); ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN); if (genopts_len < PGM_OPT_PARITY_PRM_SIZE) { proto_tree_add_uint_format_value(opt_tree, hf_pgm_genopt_len, ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor), 1, genopts_len, "%u (bogus, must be >= %u)", genopts_len, PGM_OPT_PARITY_PRM_SIZE); break; } ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN); optdata_po = tvb_get_guint8(tvb, ptvcursor_current_offset(cursor)); proto_tree_add_uint_format_value(opt_tree, hf_pgm_opt_parity_prm_po, tvb, ptvcursor_current_offset(cursor), 1, optdata_po, "%s (0x%x)", paritystr(optdata_po), optdata_po); ptvcursor_advance(cursor, 1); ptvcursor_add(cursor, hf_pgm_opt_parity_prm_prmtgsz, 4, ENC_BIG_ENDIAN); break; } case PGM_OPT_PARITY_GRP:{ TLV_CHECK(ett_pgm_opts_paritygrp); ptvcursor_set_tree(cursor, opt_tree); ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN); if (genopts_len < PGM_OPT_PARITY_GRP_SIZE) { proto_tree_add_uint_format_value(opt_tree, hf_pgm_genopt_len, tvb, ptvcursor_current_offset(cursor), 1, genopts_len, "%u (bogus, must be >= %u)", genopts_len, PGM_OPT_PARITY_GRP_SIZE); break; } ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_parity_grp_res, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_parity_grp_prmgrp, 4, ENC_BIG_ENDIAN); break; } case PGM_OPT_NAK_LIST:{ guint8 optdata_len; guint32 naklist[PGM_MAX_NAK_LIST_SZ+1]; unsigned char *nakbuf; gboolean firsttime; int i, j, naks, soffset; TLV_CHECK(ett_pgm_opts_naklist); ptvcursor_set_tree(cursor, opt_tree); ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN); optdata_len = tvb_get_guint8(tvb, ptvcursor_current_offset(cursor)); ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_nak_res, 1, ENC_BIG_ENDIAN); optdata_len -= PGM_OPT_NAK_LIST_SIZE; tvb_memcpy(tvb, (guint8 *)naklist, ptvcursor_current_offset(cursor), optdata_len); firsttime = TRUE; soffset = 0; naks = (int)(optdata_len/sizeof(guint32)); nakbuf = (unsigned char *)wmem_alloc(wmem_packet_scope(), 8192); j = 0; /* * Print out 8 per line */ for (i=0; i < naks; i++) { soffset += MIN(8192-soffset, g_snprintf(nakbuf+soffset, 8192-soffset, "0x%lx ", (unsigned long)g_ntohl(naklist[i]))); if ((++j % 8) == 0) { if (firsttime) { proto_tree_add_bytes_format(opt_tree, hf_pgm_opt_nak_list, tvb, ptvcursor_current_offset(cursor), j*4, nakbuf, "List(%d): %s", naks, nakbuf); soffset = 0; firsttime = FALSE; } else { proto_tree_add_bytes_format_value(opt_tree, hf_pgm_opt_nak_list, tvb, ptvcursor_current_offset(cursor), j*4, nakbuf, "%s", nakbuf); soffset = 0; } ptvcursor_advance(cursor, j*4); j = 0; } } if (j) { if (firsttime) { proto_tree_add_bytes_format(opt_tree, hf_pgm_opt_nak_list, tvb, ptvcursor_current_offset(cursor), j*4, nakbuf, "List(%d): %s", naks, nakbuf); } else { proto_tree_add_bytes_format_value(opt_tree, hf_pgm_opt_nak_list, tvb, ptvcursor_current_offset(cursor), j*4, nakbuf, "%s", nakbuf); } ptvcursor_advance(cursor, j*4); } break; } case PGM_OPT_PGMCC_DATA:{ guint16 optdata_afi; TLV_CHECK(ett_pgm_opts_ccdata); ptvcursor_set_tree(cursor, opt_tree); ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN); if (genopts_len < PGM_OPT_PGMCC_DATA_SIZE) { proto_tree_add_uint_format_value(opt_tree, hf_pgm_genopt_len, tvb, ptvcursor_current_offset(cursor), 1, genopts_len, "%u (bogus, must be >= %u)", genopts_len, PGM_OPT_PGMCC_DATA_SIZE); break; } ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_ccdata_res, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_ccdata_tsp, 4, ENC_BIG_ENDIAN); optdata_afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor)); ti = ptvcursor_add(cursor, hf_pgm_opt_ccdata_afi, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_ccdata_res2, 2, ENC_BIG_ENDIAN); switch (optdata_afi) { case AFNUM_INET: ptvcursor_add(cursor, hf_pgm_opt_ccdata_acker, 4, ENC_BIG_ENDIAN); break; case AFNUM_INET6: ptvcursor_add(cursor, hf_pgm_opt_ccdata_acker6, 16, ENC_NA); break; default: expert_add_info(pinfo, ti, &ei_address_format_invalid); break; } break; } case PGM_OPT_PGMCC_FEEDBACK:{ guint16 optdata_afi; TLV_CHECK(ett_pgm_opts_ccdata); ptvcursor_set_tree(cursor, opt_tree); ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN); if (genopts_len < PGM_OPT_PGMCC_FEEDBACK_SIZE) { proto_tree_add_uint_format_value(opt_tree, hf_pgm_genopt_len, tvb, ptvcursor_current_offset(cursor), 1, genopts_len, "%u (bogus, must be >= %u)", genopts_len, PGM_OPT_PGMCC_FEEDBACK_SIZE); break; } ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_ccfeedbk_res, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_ccfeedbk_tsp, 4, ENC_BIG_ENDIAN); optdata_afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor)); ti = ptvcursor_add(cursor, hf_pgm_opt_ccfeedbk_afi, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_ccfeedbk_lossrate, 2, ENC_BIG_ENDIAN); switch (optdata_afi) { case AFNUM_INET: ptvcursor_add(cursor, hf_pgm_opt_ccfeedbk_acker, 4, ENC_BIG_ENDIAN); break; case AFNUM_INET6: ptvcursor_add(cursor, hf_pgm_opt_ccfeedbk_acker6, 16, ENC_NA); break; default: expert_add_info(pinfo, ti, &ei_address_format_invalid); break; } break; } case PGM_OPT_NAK_BO_IVL:{ TLV_CHECK(ett_pgm_opts_nak_bo_ivl); ptvcursor_set_tree(cursor, opt_tree); ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN); if (genopts_len < PGM_OPT_NAK_BO_IVL_SIZE) { proto_tree_add_uint_format_value(opt_tree, hf_pgm_genopt_len, tvb, ptvcursor_current_offset(cursor), 1, genopts_len, "%u (bogus, must be >= %u)", genopts_len, PGM_OPT_NAK_BO_IVL_SIZE); break; } ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_nak_bo_ivl_res, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_nak_bo_ivl_bo_ivl, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_nak_bo_ivl_bo_ivl_sqn, 4, ENC_BIG_ENDIAN); break; } case PGM_OPT_NAK_BO_RNG:{ TLV_CHECK(ett_pgm_opts_nak_bo_rng); ptvcursor_set_tree(cursor, opt_tree); ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN); if (genopts_len < PGM_OPT_NAK_BO_RNG_SIZE) { proto_tree_add_uint_format_value(opt_tree, hf_pgm_genopt_len, tvb, ptvcursor_current_offset(cursor), 1, genopts_len, "%u (bogus, must be >= %u)", genopts_len, PGM_OPT_NAK_BO_RNG_SIZE); break; } ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_nak_bo_rng_res, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_nak_bo_rng_min_bo_ivl, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_nak_bo_rng_max_bo_ivl, 4, ENC_BIG_ENDIAN); break; } case PGM_OPT_REDIRECT:{ guint16 optdata_afi; TLV_CHECK(ett_pgm_opts_redirect); ptvcursor_set_tree(cursor, opt_tree); ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN); if (genopts_len < PGM_OPT_REDIRECT_SIZE) { proto_tree_add_uint_format_value(opt_tree, hf_pgm_genopt_len, tvb, ptvcursor_current_offset(cursor), 1, genopts_len, "%u (bogus, must be >= %u)", genopts_len, PGM_OPT_REDIRECT_SIZE); break; } ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_redirect_res, 1, ENC_BIG_ENDIAN); optdata_afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor)); ti = ptvcursor_add(cursor, hf_pgm_opt_redirect_afi, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_redirect_res2, 2, ENC_BIG_ENDIAN); switch (optdata_afi) { case AFNUM_INET: ptvcursor_add(cursor, hf_pgm_opt_redirect_dlr, 4, ENC_BIG_ENDIAN); break; case AFNUM_INET6: ptvcursor_add(cursor, hf_pgm_opt_redirect_dlr6, 16, ENC_NA); break; default: expert_add_info(pinfo, ti, &ei_address_format_invalid); break; } break; } case PGM_OPT_FRAGMENT:{ TLV_CHECK(ett_pgm_opts_fragment); ptvcursor_set_tree(cursor, opt_tree); ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN); if (genopts_len < PGM_OPT_FRAGMENT_SIZE) { proto_tree_add_uint_format_value(opt_tree, hf_pgm_genopt_len, tvb, ptvcursor_current_offset(cursor), 1, genopts_len, "%u (bogus, must be >= %u)", genopts_len, PGM_OPT_FRAGMENT_SIZE); break; } ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_fragment_res, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_fragment_first_sqn, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_fragment_offset, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_fragment_total_length, 4, ENC_BIG_ENDIAN); break; } default:{ TLV_CHECK(ett_pgm_opts); ptvcursor_advance(cursor, genopts_len); break; } } opts_total_len -= genopts_len; } return; }