rem: int offset; uint32	offset_in_chunk; int size;
add: uint32 offset; uint32 offset_in_chunk; uint32 size;
context: status_t add_buffer_attribute(net_buffer *buffer, const void *id, int type, ...){	net_attribute *attr;		if (! buffer)		return B_BAD_VALUE;		attr = new_attribute(&buffer->attributes, id);	if (! attr)		return B_NO_MEMORY;	if (type & FROM_BUFFER) {		va_list args;		net_buffer_chunk *chunk;		int offset;		uint32	offset_in_chunk;		int size;		uint8 *ptr;					type = (type & NET_ATTRIBUTE_FLAGS_MASK);				va_start(args, type);		offset 	= va_arg(args, int);		size 	= va_arg(args, int);		va_end(args);				chunk = find_buffer_chunk(buffer, offset, &offset_in_chunk, NULL);		if (chunk == NULL) {			delete_attribute(attr, &buffer->attributes);			return B_BAD_VALUE;		};		attr->size = size;				if (size < chunk->len - offset_in_chunk) {			ptr  = (uint8 *) chunk->data;			ptr += offset_in_chunk;			attr->type = type | NET_ATTRIBUTE_POINTER;			attr->u.ptr = ptr;			} else {			// data overlap this chunk, use iovec attribute type			int i;			uint32 len;			uint32 chunk_len;					i = 0;			len = 0;			while (chunk) {				ptr  = (uint8 *) chunk->data;				ptr += offset_in_chunk;				chunk_len = min((chunk->len - offset_in_chunk), (size - len));					attr->u.vec[i].iov_base = ptr;				attr->u.vec[i].iov_len = chunk_len;					len += chunk_len;				i++;				if (len >= size || i > 16)					break;					offset_in_chunk = 0; // only the first chunk							chunk = chunk->next_data;	// next chunk			};				attr->type = type | NET_ATTRIBUTE_IOVEC;		}	} else {		// Not implemented		return B_ERROR;		}	return B_OK;}