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  next_ext = (struct uip_ext_hdr *)next_header;
122  next_hdr_len = (next_ext->len << 3) + 8;
123  } else {
124  if(*protocol == UIP_PROTO_TCP) {
125  next_hdr_len = UIP_TCPH_LEN;
126  } else if(*protocol == UIP_PROTO_UDP) {
127  next_hdr_len = UIP_UDPH_LEN;
128  } else if(*protocol == UIP_PROTO_ICMP6) {
129  next_hdr_len = UIP_ICMPH_LEN;
130  }
131  }
132 
133  /* Size must be enough to hold both the current and next header */
134  if(next_hdr_len == 0 || curr_hdr_len + next_hdr_len > size) {
135  return NULL;
136  }
137 
138  return next_header;
139 }
140 /*---------------------------------------------------------------------------*/
141 /* Get the final header given the buffer - that is assumed to be at start
142  of an IPv6 header */
143 uint8_t *
144 uipbuf_get_last_header(uint8_t *buffer, uint16_t size, uint8_t *protocol)
145 {
146  uint8_t *nbuf;
147 
148  nbuf = uipbuf_get_next_header(buffer, size, protocol, true);
149  while(nbuf != NULL && uip_is_proto_ext_hdr(*protocol)) {
150  /* move to the ext hdr */
151  nbuf = uipbuf_get_next_header(nbuf, size - (nbuf - buffer), protocol, false);
152  }
153 
154  /* In case the buffer wasn't large enough for all headers, return NULL */
155  return nbuf;
156 }
157 /*---------------------------------------------------------------------------*/
158 uint8_t *
159 uipbuf_search_header(uint8_t *buffer, uint16_t size, uint8_t protocol)
160 {
161  uint8_t *nbuf;
162  uint8_t next_proto;
163 
164  nbuf = uipbuf_get_next_header(buffer, size, &next_proto, true);
165  while(nbuf != NULL && next_proto != protocol && uip_is_proto_ext_hdr(next_proto)) {
166  /* move to the ext hdr */
167  nbuf = uipbuf_get_next_header(nbuf, size - (nbuf - buffer), &next_proto, false);
168  }
169 
170  if(next_proto == protocol) {
171  return nbuf;
172  } else {
173  return NULL;
174  }
175 }
176 /*---------------------------------------------------------------------------*/
177 /**
178  * Common functions for uipbuf (attributes, etc).
179  *
180  */
181 /*---------------------------------------------------------------------------*/
182 uint16_t
183 uipbuf_get_attr(uint8_t type)
184 {
185  if(type < UIPBUF_ATTR_MAX) {
186  return uipbuf_attrs[type];
187  }
188  return 0;
189 }
190 /*---------------------------------------------------------------------------*/
191 int
192 uipbuf_set_attr(uint8_t type, uint16_t value)
193 {
194  if(type < UIPBUF_ATTR_MAX) {
195  uipbuf_attrs[type] = value;
196  return 1;
197  }
198  return 0;
199 }
200 /*---------------------------------------------------------------------------*/
201 int
202 uipbuf_set_default_attr(uint8_t type, uint16_t value)
203 {
204  if(type < UIPBUF_ATTR_MAX) {
205  uipbuf_default_attrs[type] = value;
206  return 1;
207  }
208  return 0;
209 }
210 /*---------------------------------------------------------------------------*/
211 void
212 uipbuf_clear_attr(void)
213 {
214  /* set everything to "defaults" */
215  memcpy(uipbuf_attrs, uipbuf_default_attrs, sizeof(uipbuf_attrs));
216 }
217 /*---------------------------------------------------------------------------*/
218 void
219 uipbuf_set_attr_flag(uint16_t flag)
220 {
221  /* Assume only 16-bits for flags now */
222  uipbuf_attrs[UIPBUF_ATTR_FLAGS] |= flag;
223 }
224 /*---------------------------------------------------------------------------*/
225 void
226 uipbuf_clr_attr_flag(uint16_t flag)
227 {
228  uipbuf_attrs[UIPBUF_ATTR_FLAGS] &= ~flag;
229 }
230 /*---------------------------------------------------------------------------*/
231 uint16_t
232 uipbuf_is_attr_flag(uint16_t flag)
233 {
234  return (uipbuf_attrs[UIPBUF_ATTR_FLAGS] & flag) == flag;
235 }
236 /*---------------------------------------------------------------------------*/
237 void
238 uipbuf_init(void)
239 {
240  memset(uipbuf_default_attrs, 0, sizeof(uipbuf_default_attrs));
241  /* And initialize anything that should be initialized */
242  uipbuf_set_default_attr(UIPBUF_ATTR_MAX_MAC_TRANSMISSIONS,
244  /* set the not-set default value - this will cause the MAC layer to
245  configure its default */
246  uipbuf_set_default_attr(UIPBUF_ATTR_LLSEC_LEVEL,
247  UIPBUF_ATTR_LLSEC_LEVEL_MAC_DEFAULT);
248 }
249 
250 /*---------------------------------------------------------------------------*/
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:519
#define UIP_LINK_MTU
The maximum transmission unit at the IP Layer.
Definition: uipopt.h:228
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.