FreeBSD/sbin/ipfw/dummynet.c
/* main entry point for dummynet list functions. co.do_pipe indicates
 * which function we want to support.
 * av may contain filtering arguments, either individual entries
 * or ranges, or lists (space or commas are valid separators).
 * Format for a range can be n1-n2 or n3 n4 n5 ...
 * In a range n1 must be <= n2, otherwise the range is ignored.
 * A number 'n4' is translate in a range 'n4-n4'
 * All number must be > 0 and < DN_MAX_ID-1
 */
main entry point for dummynet list functions. co.do_pipe indicates
which function we want to support.
av may contain filtering arguments, either individual entries
or ranges, or lists (space or commas are valid separators).
Format for a range can be n1-n2 or n3 n4 n5
In a range n1 must be <= n2, otherwise the range is ignored.
A number 'n4' is translate in a range 'n4-n4'
All number must be > 0 and < DN_MAX_ID-1
main entry point for dummynet list functions . co . do_pipe indicates which function we want to support . av may contain filtering arguments either individual entries or ranges or lists ( space or commas are valid separators ) . Format for a range can be n1 - n2 or n3 n4 n5 In a range n1 must be < = n2 otherwise the range is ignored . A number ' n4 ' is translate in a range ' n4 - n4 ' All number must be > 0 and < DN_MAX_ID - 1
void
dummynet_list(int ac, char *av[], int show_counters)
{
	struct dn_id *oid, *x = NULL;
	int ret, i;
	int n; 		
	u_int buflen, l;
	u_int max_size;	
	(void)show_counters;	
	ac--;
	av++; 		
	n = parse_range(ac, av, NULL, 0);	
	l = sizeof(*oid) + sizeof(uint32_t) * n * 2;
	oid = safe_calloc(1, l);
	oid_fill(oid, l, DN_CMD_GET, DN_API_VERSION);
	if (n > 0)	
		parse_range(ac, av, (uint32_t *)(oid + 1), n*2);
	max_size = sizeof(struct dn_fs);
	if (max_size < sizeof(struct dn_sch))
		max_size = sizeof(struct dn_sch);
	if (max_size < sizeof(struct dn_flow))
		max_size = sizeof(struct dn_flow);
	switch (co.do_pipe) {
	case 1:
		oid->subtype = DN_LINK;	
		break;
	case 2:
		oid->subtype = DN_FS;	
		break;
	case 3:
		oid->subtype = DN_SCH;	
		break;
	}
	if (n > 0) {
		buflen = 4*1024;
	} else {
		ret = do_cmd(-IP_DUMMYNET3, oid, (uintptr_t)&l);
		if (ret != 0 || oid->id <= sizeof(*oid))
			goto done;
		buflen = oid->id + max_size;
		oid->len = sizeof(*oid); 
	}
	for (i = 0; i < 20; i++) {
		l = buflen;
		x = safe_realloc(x, l);
		bcopy(oid, x, oid->len);
		ret = do_cmd(-IP_DUMMYNET3, x, (uintptr_t)&l);
		if (ret != 0 || x->id <= sizeof(*oid))
			goto done; 
		if (l + max_size <= buflen)
			break; 
		buflen *= 2;	 
	}
	list_pipes(x, O_NEXT(x, l));
done:
	if (x)
		free(x);
	free(oid);
}
void dummynet_list ( int ac , char * av [ ] , int show_counters ) { struct dn_id * oid , * x = NULL ; int ret , i ; int n ; u_int buflen , l ; u_int max_size ; ( void ) show_counters ; ac -- ; av ++ ; n = parse_range ( ac , av , NULL , 0 ) ; l = sizeof ( * oid ) + sizeof ( uint32_t ) * n * 2 ; oid = safe_calloc ( 1 , l ) ; oid_fill ( oid , l , DN_CMD_GET , DN_API_VERSION ) ; if ( n > 0 ) parse_range ( ac , av , ( uint32_t * ) ( oid + 1 ) , n * 2 ) ; max_size = sizeof ( struct dn_fs ) ; if ( max_size < sizeof ( struct dn_sch ) ) max_size = sizeof ( struct dn_sch ) ; if ( max_size < sizeof ( struct dn_flow ) ) max_size = sizeof ( struct dn_flow ) ; switch ( co . do_pipe ) { case 1 : oid -> subtype = DN_LINK ; break ; case 2 : oid -> subtype = DN_FS ; break ; case 3 : oid -> subtype = DN_SCH ; break ; } if ( n > 0 ) { buflen = 4 * 1024 ; } else { ret = do_cmd ( - IP_DUMMYNET3 , oid , ( uintptr_t ) & l ) ; if ( ret != 0 || oid -> id <= sizeof ( * oid ) ) goto done ; buflen = oid -> id + max_size ; oid -> len = sizeof ( * oid ) ; } for ( i = 0 ; i < 20 ; i ++ ) { l = buflen ; x = safe_realloc ( x , l ) ; bcopy ( oid , x , oid -> len ) ; ret = do_cmd ( - IP_DUMMYNET3 , x , ( uintptr_t ) & l ) ; if ( ret != 0 || x -> id <= sizeof ( * oid ) ) goto done ; if ( l + max_size <= buflen ) break ; buflen *= 2 ; } list_pipes ( x , O_NEXT ( x , l ) ) ; done : if ( x ) free ( x ) ; free ( oid ) ; }
main entry point for dummynet list functions.
main entry point for dummynet list functions .
/* # of ranges */ /* largest obj passed up */ // XXX unused, but we should use it. /* skip 'list' | 'show' word */ /* Count # of ranges. */ /* Allocate space to store ranges */ /* store ranges in idx */ /*
	 * Compute the size of the largest object returned. If the
	 * response leaves at least this much spare space in the
	 * buffer, then surely the response is complete; otherwise
	 * there might be a risk of truncation and we will need to
	 * retry with a larger buffer.
	 * XXX don't bother with smaller structs.
	 */ /* list pipe */ /* list queue */ /* list sched */ /*
	 * Ask the kernel an estimate of the required space (result
	 * in oid.id), unless we are requesting a subset of objects,
	 * in which case the kernel does not give an exact answer.
	 * In any case, space might grow in the meantime due to the
	 * creation of new queues, so we must be prepared to retry.
	 */ /* restore */ /* Try a few times, until the buffer fits */ /* no response */ /* ok */ /* double for next attempt */