Contiki-NG
Loading...
Searching...
No Matches
uiplib.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2004, Adam Dunkels and the Swedish Institute of
3 * Computer Science.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote
15 * products derived from this software without specific prior
16 * written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
19 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
24 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * This file is part of the uIP TCP/IP stack and the Contiki operating system.
31 *
32 *
33 */
34
35/**
36 * \addtogroup uip-addr-lib
37 * @{
38 *
39 * \file
40 * Implementation of the IP address manipulation library
41 * \author
42 * Nicolas Tsiftes <nvt@sics.se>
43 * Niclas Finne <nfi@sics.se>
44 * Joakim Eriksson <joakime@sics.se>
45 */
46
47#include "net/ipv6/uip.h"
48#include "net/ipv6/uiplib.h"
49#include "net/ipv6/ip64-addr.h"
50#include <string.h>
51#include <stdio.h>
52
53/* Log configuration */
54#include "sys/log.h"
55#define LOG_MODULE "uiplib"
56#define LOG_LEVEL LOG_LEVEL_NONE
57
58/*---------------------------------------------------------------------------*/
59int
60uiplib_ip6addrconv(const char *addrstr, uip_ip6addr_t *ipaddr)
61{
62 uint16_t value;
63 int tmp, zero;
64 unsigned int len;
65 const char *group_start;
66 char c = 0; //gcc warning if not initialized
67
68 value = 0;
69 zero = -1;
70 if(*addrstr == '[') addrstr++;
71
72 group_start = addrstr;
73 for(len = 0; len < sizeof(uip_ip6addr_t) - 1; addrstr++) {
74 c = *addrstr;
75 if(c == ':' || c == '\0' || c == ']' || c == '/') {
76 ipaddr->u8[len] = (value >> 8) & 0xff;
77 ipaddr->u8[len + 1] = value & 0xff;
78 len += 2;
79 value = 0;
80
81 if(c == '\0' || c == ']' || c == '/') {
82 break;
83 }
84
85 if(*(addrstr + 1) == ':') {
86 /* Zero compression */
87 if(zero < 0) {
88 zero = len;
89 }
90 addrstr++;
91 }
92 group_start = addrstr + 1;
93 } else if(c == '.') {
94 /* RFC 4291 mixed notation: trailing IPv4 dotted-decimal. */
96 if(uiplib_ip4addrconv(group_start, &v4) == 0) {
97 return 0;
98 }
99 ipaddr->u8[len] = v4.u8[0];
100 ipaddr->u8[len + 1] = v4.u8[1];
101 ipaddr->u8[len + 2] = v4.u8[2];
102 ipaddr->u8[len + 3] = v4.u8[3];
103 len += 4;
104 c = '\0';
105 break;
106 } else {
107 if(c >= '0' && c <= '9') {
108 tmp = c - '0';
109 } else if(c >= 'a' && c <= 'f') {
110 tmp = c - 'a' + 10;
111 } else if(c >= 'A' && c <= 'F') {
112 tmp = c - 'A' + 10;
113 } else {
114 LOG_ERR("illegal char: '%c'\n", c);
115 return 0;
116 }
117 value = (value << 4) + (tmp & 0xf);
118 }
119 }
120 if(c != '\0' && c != ']' && c != '/') {
121 LOG_ERR("too large address\n");
122 return 0;
123 }
124 if(len < sizeof(uip_ip6addr_t)) {
125 if(zero < 0) {
126 LOG_ERR("too short address\n");
127 return 0;
128 }
129 memmove(&ipaddr->u8[zero + sizeof(uip_ip6addr_t) - len],
130 &ipaddr->u8[zero], len - zero);
131 memset(&ipaddr->u8[zero], 0, sizeof(uip_ip6addr_t) - len);
132 }
133
134 return 1;
135}
136/*---------------------------------------------------------------------------*/
137/* Parse a IPv4-address from a string. Returns the number of characters read
138 * for the address. */
139int
140uiplib_ip4addrconv(const char *addrstr, uip_ip4addr_t *ipaddr)
141{
142 unsigned char tmp;
143 char c;
144 unsigned char i, j;
145 uint8_t charsread = 0;
146
147 tmp = 0;
148
149 for(i = 0; i < 4; ++i) {
150 j = 0;
151 do {
152 c = *addrstr;
153 ++j;
154 if(j > 4) {
155 return 0;
156 }
157 if(c == '.' || c == 0 || c == ' ') {
158 ipaddr->u8[i] = tmp;
159 tmp = 0;
160 } else if(c >= '0' && c <= '9') {
161 tmp = (tmp * 10) + (c - '0');
162 } else {
163 return 0;
164 }
165 ++addrstr;
166 ++charsread;
167 } while(c != '.' && c != 0 && c != ' ');
168
169 }
170 return charsread - 1;
171}
172/*---------------------------------------------------------------------------*/
173void
174uiplib_ipaddr_print(const uip_ipaddr_t *addr)
175{
176 char buf[UIPLIB_IPV6_MAX_STR_LEN];
177 uiplib_ipaddr_snprint(buf, sizeof(buf), addr);
178 printf("%s", buf);
179}
180/*---------------------------------------------------------------------------*/
181int
182uiplib_ipaddr_snprint(char *buf, size_t size, const uip_ipaddr_t *addr)
183{
184 unsigned int n = 0;
185
186 if(size == 0) {
187 return 0;
188 }
189
190 if(addr == NULL) {
191 return snprintf(buf, size, "(NULL IP addr)");
192 } else if(ip64_addr_is_ipv4_mapped_addr(addr)) {
193 /*
194 * Printing IPv4-mapped addresses is done according to RFC 4291 [1]
195 *
196 * "An alternative form that is sometimes more
197 * convenient when dealing with a mixed environment
198 * of IPv4 and IPv6 nodes is x:x:x:x:x:x:d.d.d.d,
199 * where the 'x's are the hexadecimal values of the
200 * six high-order 16-bit pieces of the address, and
201 * the 'd's are the decimal values of the four
202 * low-order 8-bit pieces of the address (standard
203 * IPv4 representation)."
204 *
205 * [1] https://tools.ietf.org/html/rfc4291#page-4
206 */
207 return snprintf(buf, size, "::FFFF:%u.%u.%u.%u", addr->u8[12],
208 addr->u8[13], addr->u8[14], addr->u8[15]);
209 } else if(ip64_addr_is_ip64(addr)) {
210 /*
211 * NAT64 well-known prefix (64:ff9b::/96) per RFC 6052 [1].
212 * Print with a trailing dotted-decimal suffix per RFC 4291.
213 *
214 * [1] https://tools.ietf.org/html/rfc6052#section-2.1
215 */
216 return snprintf(buf, size, "64:ff9b::%u.%u.%u.%u", addr->u8[12],
217 addr->u8[13], addr->u8[14], addr->u8[15]);
218 } else {
219 int f = 0;
220 for(size_t i = 0; i < sizeof(uip_ipaddr_t); i += 2) {
221 uint16_t a = (addr->u8[i] << 8) + addr->u8[i + 1];
222 if(a == 0 && f >= 0) {
223 if(f++ == 0) {
224 n += snprintf(buf+n, size-n, "::");
225 if(n >= size) {
226 return n;
227 }
228 }
229 } else {
230 if(f > 0) {
231 f = -1;
232 } else if(i > 0) {
233 n += snprintf(buf+n, size-n, ":");
234 if(n >= size) {
235 return n;
236 }
237 }
238 n += snprintf(buf+n, size-n, "%x", a);
239 if(n >= size) {
240 return n;
241 }
242 }
243 }
244 }
245 return n;
246}
247/*---------------------------------------------------------------------------*/
248/**
249 * @}
250 */
void uiplib_ipaddr_print(const uip_ipaddr_t *addr)
Print an IP address using printf().
Definition uiplib.c:174
int uiplib_ipaddr_snprint(char *buf, size_t size, const uip_ipaddr_t *addr)
Write at most size - 1 characters of the IP address to the output string.
Definition uiplib.c:182
Header file for the logging system.
static uip_ipaddr_t ipaddr
Pointer to prefix information option in uip_buf.
Definition uip-nd6.c:116
static uip_ds6_addr_t * addr
Pointer to a nbr cache entry.
Definition uip-nd6.c:107
Header file for the uIP TCP/IP stack.
Header file for the IP address manipulation library.
Representation of an IP address.
Definition uip.h:95