Contiki-NG
uipbuf.c
1 /*
2  * Copyright (c) 2017, RISE SICS, Yanzi Networks
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. The name of the authors may not be used to endorse or promote
14  * products derived from this software without specific prior
15  * written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS''
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
23  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
27  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
28  * DAMAGE.
29  *
30  *
31  */
32 #include "contiki.h"
33 #include "net/ipv6/uip.h"
34 #include "net/ipv6/uipbuf.h"
35 #include <string.h>
36 
37 /*---------------------------------------------------------------------------*/
38 
39 static uint16_t uipbuf_attrs[UIPBUF_ATTR_MAX];
40 static uint16_t uipbuf_default_attrs[UIPBUF_ATTR_MAX];
41 
42 /*---------------------------------------------------------------------------*/
43 void
44 uipbuf_clear(void)
45 {
46  uip_len = 0;
47  uip_ext_len = 0;
48  uip_last_proto = 0;
49  uipbuf_clear_attr();
50 }
51 /*---------------------------------------------------------------------------*/
52 bool
53 uipbuf_add_ext_hdr(int16_t len)
54 {
55  if(len + uip_len <= UIP_LINK_MTU && len + uip_len >= 0 && len + uip_ext_len >= 0) {
56  uip_ext_len += len;
57  uip_len += len;
58  return true;
59  } else {
60  return false;
61  }
62 }
63 /*---------------------------------------------------------------------------*/
64 bool
65 uipbuf_set_len(uint16_t len)
66 {
67  if(len <= UIP_LINK_MTU) {
68  uip_len = len;
69  return true;
70  } else {
71  return false;
72  }
73 }
74 /*---------------------------------------------------------------------------*/
75 void
76 uipbuf_set_len_field(struct uip_ip_hdr *hdr, uint16_t len)
77 {
78  hdr->len[0] = (len >> 8);
79  hdr->len[1] = (len & 0xff);
80 }
81 /*---------------------------------------------------------------------------*/
82 uint16_t
83 uipbuf_get_len_field(struct uip_ip_hdr *hdr)
84 {
85  return ((uint16_t)(hdr->len[0]) << 8) + hdr->len[1];
86 }
87 /*---------------------------------------------------------------------------*/
88 /* Get the next header given the buffer - start indicates that this is
89  start of the IPv6 header - needs to be set to 0 when in an ext hdr */
90 uint8_t *
91 uipbuf_get_next_header(uint8_t *buffer, uint16_t size, uint8_t *protocol, bool start)
92 {
93  int curr_hdr_len = 0;
94  int next_hdr_len = 0;
95  uint8_t *next_header = NULL;
96  struct uip_ip_hdr *ipbuf = NULL;
97  struct uip_ext_hdr *curr_ext = NULL;
98  struct uip_ext_hdr *next_ext = NULL;
99 
100  if(start) {
101  /* protocol in the IP buffer */
102  ipbuf = (struct uip_ip_hdr *)buffer;
103  *protocol = ipbuf->proto;
104  curr_hdr_len = UIP_IPH_LEN;
105  } else {
106  /* protocol in the Ext hdr */
107  curr_ext = (struct uip_ext_hdr *)buffer;
108  *protocol = curr_ext->next;
109  /* This is just an ext header */
110  curr_hdr_len = (curr_ext->len << 3) + 8;
111  }
112 
113  /* Check first if enough space for current header */
114  if(curr_hdr_len > size) {
115  return NULL;
116  }
117  next_header = buffer + curr_hdr_len;
118 
119  /* Check if the buffer is large enough for the next header */
120  if(uip_is_proto_ext_hdr(*protocol)) {
121  if(curr_hdr_len + sizeof(struct uip_ext_hdr) > size) {
122  return NULL;
123  }
124  next_ext = (struct uip_ext_hdr *)next_header;
125  next_hdr_len = (next_ext->len << 3) + 8;
126  } else {
127  if(*protocol == UIP_PROTO_TCP) {
128  next_hdr_len = UIP_TCPH_LEN;
129  } else if(*protocol == UIP_PROTO_UDP) {
130  next_hdr_len = UIP_UDPH_LEN;
131  } else if(*protocol == UIP_PROTO_ICMP6) {
132  next_hdr_len = UIP_ICMPH_LEN;
133  }
134  }
135 
136  /* Size must be enough to hold both the current and next header */
137  if(next_hdr_len == 0 || curr_hdr_len + next_hdr_len > size) {
138  return NULL;
139  }
140 
141  return next_header;
142 }
143 /*---------------------------------------------------------------------------*/
144 /* Get the final header given the buffer - that is assumed to be at start
145  of an IPv6 header */
146 uint8_t *
147 uipbuf_get_last_header(uint8_t *buffer, uint16_t size, uint8_t *protocol)
148 {
149  uint8_t *nbuf;
150 
151  nbuf = uipbuf_get_next_header(buffer, size, protocol, true);
152  while(nbuf != NULL && uip_is_proto_ext_hdr(*protocol)) {
153  /* move to the ext hdr */
154  nbuf = uipbuf_get_next_header(nbuf, size - (nbuf - buffer), protocol, false);
155  }
156 
157  /* In case the buffer wasn't large enough for all headers, return NULL */
158  return nbuf;
159 }
160 /*---------------------------------------------------------------------------*/
161 uint8_t *
162 uipbuf_search_header(uint8_t *buffer, uint16_t size, uint8_t protocol)
163 {
164  uint8_t *nbuf;
165  uint8_t next_proto;
166 
167  nbuf = uipbuf_get_next_header(buffer, size, &next_proto, true);
168  while(nbuf != NULL && next_proto != protocol && uip_is_proto_ext_hdr(next_proto)) {
169  /* move to the ext hdr */
170  nbuf = uipbuf_get_next_header(nbuf, size - (nbuf - buffer), &next_proto, false);
171  }
172 
173  if(next_proto == protocol) {
174  return nbuf;
175  } else {
176  return NULL;
177  }
178 }
179 /*---------------------------------------------------------------------------*/
180 /**
181  * Common functions for uipbuf (attributes, etc).
182  *
183  */
184 /*---------------------------------------------------------------------------*/
185 uint16_t
186 uipbuf_get_attr(uint8_t type)
187 {
188  if(type < UIPBUF_ATTR_MAX) {
189  return uipbuf_attrs[type];
190  }
191  return 0;
192 }
193 /*---------------------------------------------------------------------------*/
194 int
195 uipbuf_set_attr(uint8_t type, uint16_t value)
196 {
197  if(type < UIPBUF_ATTR_MAX) {
198  uipbuf_attrs[type] = value;
199  return 1;
200  }
201  return 0;
202 }
203 /*---------------------------------------------------------------------------*/
204 int
205 uipbuf_set_default_attr(uint8_t type, uint16_t value)
206 {
207  if(type < UIPBUF_ATTR_MAX) {
208  uipbuf_default_attrs[type] = value;
209  return 1;
210  }
211  return 0;
212 }
213 /*---------------------------------------------------------------------------*/
214 void
215 uipbuf_clear_attr(void)
216 {
217  /* set everything to "defaults" */
218  memcpy(uipbuf_attrs, uipbuf_default_attrs, sizeof(uipbuf_attrs));
219 }
220 /*---------------------------------------------------------------------------*/
221 void
222 uipbuf_set_attr_flag(uint16_t flag)
223 {
224  /* Assume only 16-bits for flags now */
225  uipbuf_attrs[UIPBUF_ATTR_FLAGS] |= flag;
226 }
227 /*---------------------------------------------------------------------------*/
228 void
229 uipbuf_clr_attr_flag(uint16_t flag)
230 {
231  uipbuf_attrs[UIPBUF_ATTR_FLAGS] &= ~flag;
232 }
233 /*---------------------------------------------------------------------------*/
234 uint16_t
235 uipbuf_is_attr_flag(uint16_t flag)
236 {
237  return (uipbuf_attrs[UIPBUF_ATTR_FLAGS] & flag) == flag;
238 }
239 /*---------------------------------------------------------------------------*/
240 void
241 uipbuf_init(void)
242 {
243  memset(uipbuf_default_attrs, 0, sizeof(uipbuf_default_attrs));
244  /* And initialize anything that should be initialized */
245  uipbuf_set_default_attr(UIPBUF_ATTR_MAX_MAC_TRANSMISSIONS,
247  /* set the not-set default value - this will cause the MAC layer to
248  configure its default */
249  uipbuf_set_default_attr(UIPBUF_ATTR_LLSEC_LEVEL,
250  UIPBUF_ATTR_LLSEC_LEVEL_MAC_DEFAULT);
251 }
252 
253 /*---------------------------------------------------------------------------*/
uint8_t uip_last_proto
The final protocol after IPv6 extension headers: UIP_PROTO_TCP, UIP_PROTO_UDP or UIP_PROTO_ICMP6.
Definition: uip6.c:125
uint16_t uip_len
The length of the packet in the uip_buf buffer.
Definition: uip6.c:159
#define UIP_MAX_MAC_TRANSMISSIONS_UNDEFINED
This is the default value of MAC-layer transmissons for uIPv6.
Definition: uipopt.h:463
#define UIP_LINK_MTU
The maximum transmission unit at the IP Layer.
Definition: uipopt.h:172
static void start(void)
Start measurement.
uint16_t uip_ext_len
The length of the extension headers.
Definition: uip6.c:122
Header file for the uIP TCP/IP stack.