Contiki-NG
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 /*---------------------------------------------------------------------------*/
59 #if NETSTACK_CONF_WITH_IPV6
60 int
61 uiplib_ip6addrconv(const char *addrstr, uip_ip6addr_t *ipaddr)
62 {
63  uint16_t value;
64  int tmp, zero;
65  unsigned int len;
66  char c = 0; //gcc warning if not initialized
67 
68  value = 0;
69  zero = -1;
70  if(*addrstr == '[') addrstr++;
71 
72  for(len = 0; len < sizeof(uip_ip6addr_t) - 1; addrstr++) {
73  c = *addrstr;
74  if(c == ':' || c == '\0' || c == ']' || c == '/') {
75  ipaddr->u8[len] = (value >> 8) & 0xff;
76  ipaddr->u8[len + 1] = value & 0xff;
77  len += 2;
78  value = 0;
79 
80  if(c == '\0' || c == ']' || c == '/') {
81  break;
82  }
83 
84  if(*(addrstr + 1) == ':') {
85  /* Zero compression */
86  if(zero < 0) {
87  zero = len;
88  }
89  addrstr++;
90  }
91  } else {
92  if(c >= '0' && c <= '9') {
93  tmp = c - '0';
94  } else if(c >= 'a' && c <= 'f') {
95  tmp = c - 'a' + 10;
96  } else if(c >= 'A' && c <= 'F') {
97  tmp = c - 'A' + 10;
98  } else {
99  LOG_ERR("illegal char: '%c'\n", c);
100  return 0;
101  }
102  value = (value << 4) + (tmp & 0xf);
103  }
104  }
105  if(c != '\0' && c != ']' && c != '/') {
106  LOG_ERR("too large address\n");
107  return 0;
108  }
109  if(len < sizeof(uip_ip6addr_t)) {
110  if(zero < 0) {
111  LOG_ERR("too short address\n");
112  return 0;
113  }
114  memmove(&ipaddr->u8[zero + sizeof(uip_ip6addr_t) - len],
115  &ipaddr->u8[zero], len - zero);
116  memset(&ipaddr->u8[zero], 0, sizeof(uip_ip6addr_t) - len);
117  }
118 
119  return 1;
120 }
121 #endif /* NETSTACK_CONF_WITH_IPV6 */
122 /*---------------------------------------------------------------------------*/
123 /* Parse a IPv4-address from a string. Returns the number of characters read
124  * for the address. */
125 int
126 uiplib_ip4addrconv(const char *addrstr, uip_ip4addr_t *ipaddr)
127 {
128  unsigned char tmp;
129  char c;
130  unsigned char i, j;
131  uint8_t charsread = 0;
132 
133  tmp = 0;
134 
135  for(i = 0; i < 4; ++i) {
136  j = 0;
137  do {
138  c = *addrstr;
139  ++j;
140  if(j > 4) {
141  return 0;
142  }
143  if(c == '.' || c == 0 || c == ' ') {
144  ipaddr->u8[i] = tmp;
145  tmp = 0;
146  } else if(c >= '0' && c <= '9') {
147  tmp = (tmp * 10) + (c - '0');
148  } else {
149  return 0;
150  }
151  ++addrstr;
152  ++charsread;
153  } while(c != '.' && c != 0 && c != ' ');
154 
155  }
156  return charsread - 1;
157 }
158 /*---------------------------------------------------------------------------*/
159 void
160 uiplib_ipaddr_print(const uip_ipaddr_t *addr)
161 {
162  char buf[UIPLIB_IPV6_MAX_STR_LEN];
163  uiplib_ipaddr_snprint(buf, sizeof(buf), addr);
164  printf("%s", buf);
165 }
166 /*---------------------------------------------------------------------------*/
167 int
168 uiplib_ipaddr_snprint(char *buf, size_t size, const uip_ipaddr_t *addr)
169 {
170  uint16_t a;
171  unsigned int i;
172  int f;
173  int n = 0;
174 
175  if(size == 0) {
176  return 0;
177  }
178 
179  if(addr == NULL) {
180  n = snprintf(buf, size, "(NULL IP addr)");
181  return n;
182  } else if(ip64_addr_is_ipv4_mapped_addr(addr)) {
183  /*
184  * Printing IPv4-mapped addresses is done according to RFC 4291 [1]
185  *
186  * "An alternative form that is sometimes more
187  * convenient when dealing with a mixed environment
188  * of IPv4 and IPv6 nodes is x:x:x:x:x:x:d.d.d.d,
189  * where the 'x's are the hexadecimal values of the
190  * six high-order 16-bit pieces of the address, and
191  * the 'd's are the decimal values of the four
192  * low-order 8-bit pieces of the address (standard
193  * IPv4 representation)."
194  *
195  * [1] https://tools.ietf.org/html/rfc4291#page-4
196  */
197  n = snprintf(buf, size, "::FFFF:%u.%u.%u.%u", addr->u8[12],
198  addr->u8[13], addr->u8[14], addr->u8[15]);
199  return n;
200  } else {
201  for(i = 0, f = 0; i < sizeof(uip_ipaddr_t); i += 2) {
202  a = (addr->u8[i] << 8) + addr->u8[i + 1];
203  if(a == 0 && f >= 0) {
204  if(f++ == 0) {
205  n += snprintf(buf+n, size-n, "::");
206  if(n >= size) {
207  return n;
208  }
209  }
210  } else {
211  if(f > 0) {
212  f = -1;
213  } else if(i > 0) {
214  n += snprintf(buf+n, size-n, ":");
215  if(n >= size) {
216  return n;
217  }
218  }
219  n += snprintf(buf+n, size-n, "%x", a);
220  if(n >= size) {
221  return n;
222  }
223  }
224  }
225  }
226  return n;
227 }
228 /*---------------------------------------------------------------------------*/
229 /**
230  * @}
231  */
static uip_ipaddr_t ipaddr
Pointer to prefix information option in uip_buf.
Definition: uip-nd6.c:125
static uip_ds6_addr_t * addr
Pointer to a nbr cache entry.
Definition: uip-nd6.c:116
Representation of an IP address.
Definition: uip.h:93
Header file for the IP address manipulation library.
Header file for the uIP TCP/IP stack.
void uiplib_ipaddr_print(const uip_ipaddr_t *addr)
Print an IP address using printf().
Definition: uiplib.c:160
Header file for the logging system
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:168