Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
stoip6.c
00001 /* 00002 * Copyright (c) 2014-2015 ARM Limited. All rights reserved. 00003 * SPDX-License-Identifier: Apache-2.0 00004 * Licensed under the Apache License, Version 2.0 (the License); you may 00005 * not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an AS IS BASIS, WITHOUT 00012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 #include <string.h> 00017 #include <stdlib.h> 00018 #include <stdint.h> 00019 #include "common_functions.h" 00020 #include "ip6string.h" 00021 00022 static uint16_t hex(const char *p); 00023 00024 /** 00025 * Convert numeric IPv6 address string to a binary. 00026 * IPv4 tunnelling addresses are not covered. 00027 * \param ip6addr IPv6 address in string format. 00028 * \param len Length of ipv6 string. 00029 * \param dest buffer for address. MUST be 16 bytes. 00030 */ 00031 void stoip6(const char *ip6addr, size_t len, void *dest) 00032 { 00033 uint8_t *addr; 00034 const char *p, *q; 00035 int_fast8_t field_no, coloncolon = -1; 00036 00037 addr = dest; 00038 00039 if (len > 39) { // Too long, not possible. We do not support IPv4-mapped IPv6 addresses 00040 return; 00041 } 00042 00043 // First go forward the string, until end, noting :: position if any 00044 for (field_no = 0, p = ip6addr; (len > (size_t)(p - ip6addr)) && *p && field_no < 8; p = q + 1) { 00045 q = p; 00046 // Seek for ':' or end 00047 while (*q && (*q != ':')) { 00048 q++; 00049 } 00050 //Convert and write this part, (high-endian AKA network byte order) 00051 addr = common_write_16_bit(hex(p), addr); 00052 field_no++; 00053 //Check if we reached "::" 00054 if ((len > (size_t)(q - ip6addr)) && *q && (q[0] == ':') && (q[1] == ':')) { 00055 coloncolon = field_no; 00056 q++; 00057 } 00058 } 00059 00060 if (coloncolon != -1) { 00061 /* Insert zeros in the appropriate place */ 00062 uint_fast8_t head_size = 2 * coloncolon; 00063 uint_fast8_t inserted_size = 2 * (8 - field_no); 00064 uint_fast8_t tail_size = 16 - head_size - inserted_size; 00065 addr = dest; 00066 memmove(addr + head_size + inserted_size, addr + head_size, tail_size); 00067 memset(addr + head_size, 0, inserted_size); 00068 } else if (field_no != 8) { 00069 /* Should really report an error if we didn't get 8 fields */ 00070 memset(addr, 0, 16 - field_no * 2); 00071 } 00072 } 00073 unsigned char sipv6_prefixlength(const char *ip6addr) 00074 { 00075 char *ptr = strchr(ip6addr, '/'); 00076 if (ptr) { 00077 return (unsigned char)strtoul(ptr + 1, 0, 10); 00078 } 00079 return 0; 00080 } 00081 static uint16_t hex(const char *p) 00082 { 00083 uint16_t val = 0; 00084 00085 for (;;) { 00086 char c = *p++; 00087 if ((c >= '0') && (c <= '9')) { 00088 val = (val << 4) | (c - '0'); 00089 } else if ((c >= 'A') && (c <= 'F')) { 00090 val = (val << 4) | (10 + (c - 'A')); 00091 } else if ((c >= 'a') && (c <= 'f')) { 00092 val = (val << 4) | (10 + (c - 'a')); 00093 } else { 00094 break; // Non hex character 00095 } 00096 } 00097 return val; 00098 }
Generated on Tue Jul 12 2022 12:45:49 by
