1 /** 2 * @file 3 * SNMP pbuf stream wrapper implementation (internal API, do not use in client code). 4 */ 5 6 /* 7 * Copyright (c) 2001-2004 Swedish Institute of Computer Science. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without modification, 11 * are permitted provided that the following conditions are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright notice, 14 * this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright notice, 16 * this list of conditions and the following disclaimer in the documentation 17 * and/or other materials provided with the distribution. 18 * 3. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 22 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 23 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 24 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 26 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 29 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 30 * OF SUCH DAMAGE. 31 * 32 * This file is part of the lwIP TCP/IP stack. 33 * 34 * Author: Martin Hentschel <info@cl-soft.de> 35 * 36 */ 37 38 #include "lwip/apps/snmp_opts.h" 39 40 #if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ 41 42 #include "snmp_pbuf_stream.h" 43 #include "lwip/def.h" 44 #include <string.h> 45 46 err_t 47 snmp_pbuf_stream_init(struct snmp_pbuf_stream* pbuf_stream, struct pbuf* p, u16_t offset, u16_t length) 48 { 49 pbuf_stream->offset = offset; 50 pbuf_stream->length = length; 51 pbuf_stream->pbuf = p; 52 53 return ERR_OK; 54 } 55 56 err_t 57 snmp_pbuf_stream_read(struct snmp_pbuf_stream* pbuf_stream, u8_t* data) 58 { 59 if (pbuf_stream->length == 0) { 60 return ERR_BUF; 61 } 62 63 if (pbuf_copy_partial(pbuf_stream->pbuf, data, 1, pbuf_stream->offset) == 0) { 64 return ERR_BUF; 65 } 66 67 pbuf_stream->offset++; 68 pbuf_stream->length--; 69 70 return ERR_OK; 71 } 72 73 err_t 74 snmp_pbuf_stream_write(struct snmp_pbuf_stream* pbuf_stream, u8_t data) 75 { 76 return snmp_pbuf_stream_writebuf(pbuf_stream, &data, 1); 77 } 78 79 err_t 80 snmp_pbuf_stream_writebuf(struct snmp_pbuf_stream* pbuf_stream, const void* buf, u16_t buf_len) 81 { 82 if (pbuf_stream->length < buf_len) { 83 return ERR_BUF; 84 } 85 86 if (pbuf_take_at(pbuf_stream->pbuf, buf, buf_len, pbuf_stream->offset) != ERR_OK) { 87 return ERR_BUF; 88 } 89 90 pbuf_stream->offset += buf_len; 91 pbuf_stream->length -= buf_len; 92 93 return ERR_OK; 94 } 95 96 err_t 97 snmp_pbuf_stream_writeto(struct snmp_pbuf_stream* pbuf_stream, struct snmp_pbuf_stream* target_pbuf_stream, u16_t len) 98 { 99 100 if ((pbuf_stream == NULL) || (target_pbuf_stream == NULL)) { 101 return ERR_ARG; 102 } 103 if ((len > pbuf_stream->length) || (len > target_pbuf_stream->length)) { 104 return ERR_ARG; 105 } 106 107 if (len == 0) { 108 len = LWIP_MIN(pbuf_stream->length, target_pbuf_stream->length); 109 } 110 111 while (len > 0) { 112 u16_t chunk_len; 113 err_t err; 114 u16_t target_offset; 115 struct pbuf* pbuf = pbuf_skip(pbuf_stream->pbuf, pbuf_stream->offset, &target_offset); 116 117 if ((pbuf == NULL) || (pbuf->len == 0)) { 118 return ERR_BUF; 119 } 120 121 chunk_len = LWIP_MIN(len, pbuf->len); 122 err = snmp_pbuf_stream_writebuf(target_pbuf_stream, &((u8_t*)pbuf->payload)[target_offset], chunk_len); 123 if (err != ERR_OK) { 124 return err; 125 } 126 127 pbuf_stream->offset += chunk_len; 128 pbuf_stream->length -= chunk_len; 129 len -= chunk_len; 130 } 131 132 return ERR_OK; 133 } 134 135 err_t 136 snmp_pbuf_stream_seek(struct snmp_pbuf_stream* pbuf_stream, s32_t offset) 137 { 138 if ((offset < 0) || (offset > pbuf_stream->length)) { 139 /* we cannot seek backwards or forward behind stream end */ 140 return ERR_ARG; 141 } 142 143 pbuf_stream->offset += (u16_t)offset; 144 pbuf_stream->length -= (u16_t)offset; 145 146 return ERR_OK; 147 } 148 149 err_t 150 snmp_pbuf_stream_seek_abs(struct snmp_pbuf_stream* pbuf_stream, u32_t offset) 151 { 152 s32_t rel_offset = offset - pbuf_stream->offset; 153 return snmp_pbuf_stream_seek(pbuf_stream, rel_offset); 154 } 155 156 #endif /* LWIP_SNMP */ 157