FreeBSD/sys/netinet6/nd6.c
/*
 * Parse multiple ND options.
 * This function is much easier to use, for ND routines that do not need
 * multiple options of the same type.
 */
Parse multiple ND options.
This function is much easier to use, for ND routines that do not need
multiple options of the same type.
Parse multiple ND options . This function is much easier to use for ND routines that do not need multiple options of the same type .
int
nd6_options(union nd_opts *ndopts)
{
	struct nd_opt_hdr *nd_opt;
	int i = 0;
	KASSERT(ndopts != NULL, ("%s: ndopts == NULL", __func__));
	KASSERT(ndopts->nd_opts_last != NULL, ("%s: uninitialized ndopts",
	    __func__));
	if (ndopts->nd_opts_search == NULL)
		return 0;
	while (1) {
		nd_opt = nd6_option(ndopts);
		if (nd_opt == NULL && ndopts->nd_opts_last == NULL) {
			ICMP6STAT_INC(icp6s_nd_badopt);
			bzero(ndopts, sizeof(*ndopts));
			return -1;
		}
		if (nd_opt == NULL)
			goto skip1;
		switch (nd_opt->nd_opt_type) {
		case ND_OPT_SOURCE_LINKADDR:
		case ND_OPT_TARGET_LINKADDR:
		case ND_OPT_MTU:
		case ND_OPT_REDIRECTED_HEADER:
		case ND_OPT_NONCE:
			if (ndopts->nd_opt_array[nd_opt->nd_opt_type]) {
				nd6log((LOG_INFO,
				    "duplicated ND6 option found (type=%d)\n",
				    nd_opt->nd_opt_type));
			} else {
				ndopts->nd_opt_array[nd_opt->nd_opt_type]
					= nd_opt;
			}
			break;
		case ND_OPT_PREFIX_INFORMATION:
			if (ndopts->nd_opt_array[nd_opt->nd_opt_type] == 0) {
				ndopts->nd_opt_array[nd_opt->nd_opt_type]
					= nd_opt;
			}
			ndopts->nd_opts_pi_end =
				(struct nd_opt_prefix_info *)nd_opt;
			break;
		case ND_OPT_RDNSS:	
		case ND_OPT_DNSSL:	
			break;
		default:
			nd6log((LOG_DEBUG,
			    "nd6_options: unsupported option %d - "
			    "option ignored\n", nd_opt->nd_opt_type));
		}
skip1:
		i++;
		if (i > V_nd6_maxndopt) {
			ICMP6STAT_INC(icp6s_nd_toomanyopt);
			nd6log((LOG_INFO, "too many loop in nd opt\n"));
			break;
		}
		if (ndopts->nd_opts_done)
			break;
	}
	return 0;
}
int nd6_options ( union nd_opts * ndopts ) { struct nd_opt_hdr * nd_opt ; int i = 0 ; KASSERT ( ndopts != NULL , ( " " , __func__ ) ) ; KASSERT ( ndopts -> nd_opts_last != NULL , ( " " , __func__ ) ) ; if ( ndopts -> nd_opts_search == NULL ) return 0 ; while ( 1 ) { nd_opt = nd6_option ( ndopts ) ; if ( nd_opt == NULL && ndopts -> nd_opts_last == NULL ) { ICMP6STAT_INC ( icp6s_nd_badopt ) ; bzero ( ndopts , sizeof ( * ndopts ) ) ; return -1 ; } if ( nd_opt == NULL ) goto skip1 ; switch ( nd_opt -> nd_opt_type ) { case ND_OPT_SOURCE_LINKADDR : case ND_OPT_TARGET_LINKADDR : case ND_OPT_MTU : case ND_OPT_REDIRECTED_HEADER : case ND_OPT_NONCE : if ( ndopts -> nd_opt_array [ nd_opt -> nd_opt_type ] ) { nd6log ( ( LOG_INFO , " \n " , nd_opt -> nd_opt_type ) ) ; } else { ndopts -> nd_opt_array [ nd_opt -> nd_opt_type ] = nd_opt ; } break ; case ND_OPT_PREFIX_INFORMATION : if ( ndopts -> nd_opt_array [ nd_opt -> nd_opt_type ] == 0 ) { ndopts -> nd_opt_array [ nd_opt -> nd_opt_type ] = nd_opt ; } ndopts -> nd_opts_pi_end = ( struct nd_opt_prefix_info * ) nd_opt ; break ; case ND_OPT_RDNSS : case ND_OPT_DNSSL : break ; default : nd6log ( ( LOG_DEBUG , " " " \n " , nd_opt -> nd_opt_type ) ) ; } skip1 : i ++ ; if ( i > V_nd6_maxndopt ) { ICMP6STAT_INC ( icp6s_nd_toomanyopt ) ; nd6log ( ( LOG_INFO , " \n " ) ) ; break ; } if ( ndopts -> nd_opts_done ) break ; } return 0 ; }
Parse multiple ND options.
Parse multiple ND options .
/*
			 * Message validation requires that all included
			 * options have a length that is greater than zero.
			 */ /* XXX bark? */ /* What about ND_OPT_ROUTE_INFO? RFC 4191 */ /* RFC 6106 */ /* RFC 6106 */ /*
			 * Silently ignore options we know and do not care about
			 * in the kernel.
			 */ /*
			 * Unknown options must be silently ignored,
			 * to accommodate future extension to the protocol.
			 */