1 /*
2  Copyright (c) 2007 - 2010 RIPE NCC - All Rights Reserved
3 
4  Permission to use, copy, modify, and distribute this software and its
5  documentation for any purpose and without fee is hereby granted, provided
6  that the above copyright notice appear in all copies and that both that
7  copyright notice and this permission notice appear in supporting
8  documentation, and that the name of the author not be used in advertising or
9  publicity pertaining to distribution of the software without specific,
10  written prior permission.
11 
12  THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
13  ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
14  AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
15  DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
16  AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19 
20 /*
21  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
22  *
23  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
24  *
25  * This file contains Original Code and/or Modifications of Original Code
26  * as defined in and that are subject to the Apple Public Source License
27  * Version 2.0 (the 'License'). You may not use this file except in
28  * compliance with the License. The rights granted to you under the License
29  * may not be used to create, or enable the creation or redistribution of,
30  * unlawful or unlicensed copies of an Apple operating system, or to
31  * circumvent, violate, or enable the circumvention or violation of, any
32  * terms of an Apple operating system software license agreement.
33  *
34  * Please obtain a copy of the License at
35  * http://www.opensource.apple.com/apsl/ and read it before using this file.
36  *
37  * The Original Code and all software distributed under the License are
38  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
39  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
40  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
41  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
42  * Please see the License for the specific language governing rights and
43  * limitations under the License.
44  *
45  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
46  */
47 
48 /*
49  * Copyright 1994, 1995 Massachusetts Institute of Technology
50  *
51  * Permission to use, copy, modify, and distribute this software and
52  * its documentation for any purpose and without fee is hereby
53  * granted, provided that both the above copyright notice and this
54  * permission notice appear in all copies, that both the above
55  * copyright notice and this permission notice appear in all
56  * supporting documentation, and that the name of M.I.T. not be used
57  * in advertising or publicity pertaining to distribution of the
58  * software without specific, written prior permission.  M.I.T. makes
59  * no representations about the suitability of this software for any
60  * purpose.  It is provided "as is" without express or implied
61  * warranty.
62  *
63  * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''.  M.I.T. DISCLAIMS
64  * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
65  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
66  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
67  * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
68  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
69  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
70  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
71  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
72  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
73  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
74  * SUCH DAMAGE.
75  */
76 
77 #include <sys/param.h>
78 #include <netinet/in.h>
79 #include <string.h>
80 #include <stdio.h>
81 #include <stdbool.h>
82 #include <assert.h>
83 #include <sys/types.h>
84 #include <sys/socket.h>
85 #include <arpa/inet.h>
86 
87 #include "util.h"
88 
89 const char OCTETS[][4] = {
90      "0",  "1",  "2",  "3",  "4",  "5",  "6",  "7",  "8",  "9", "10", "11", "12", "13", "14", "15",
91     "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31",
92     "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47",
93     "48", "49", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "60", "61", "62", "63",
94     "64", "65", "66", "67", "68", "69", "70", "71", "72", "73", "74", "75", "76", "77", "78", "79",
95     "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "90", "91", "92", "93", "94", "95",
96     "96", "97", "98", "99",
97     "100", "101", "102", "103", "104", "105", "106", "107", "108", "109",
98     "110", "111", "112", "113", "114", "115", "116", "117", "118", "119", "120", "121", "122",
99     "123", "124", "125", "126", "127", "128", "129", "130", "131", "132", "133", "134", "135",
100     "136", "137", "138", "139", "140", "141", "142", "143", "144", "145", "146", "147", "148",
101     "149", "150", "151", "152", "153", "154", "155", "156", "157", "158", "159", "160", "161",
102     "162", "163", "164", "165", "166", "167", "168", "169", "170", "171", "172", "173", "174",
103     "175", "176", "177", "178", "179", "180", "181", "182", "183", "184", "185", "186", "187",
104     "188", "189", "190", "191", "192", "193", "194", "195", "196", "197", "198", "199", "200",
105     "201", "202", "203", "204", "205", "206", "207", "208", "209", "210", "211", "212", "213",
106     "214", "215", "216", "217", "218", "219", "220", "221", "222", "223", "224", "225", "226",
107     "227", "228", "229", "230", "231", "232", "233", "234", "235", "236", "237", "238", "239",
108     "240", "241", "242", "243", "244", "245", "246", "247", "248", "249", "250", "251", "252",
109     "253", "254", "255"
110 };
111 
fmt_ipv4(BGPDUMP_IP_ADDRESS addr,char * buffer)112 char *fmt_ipv4(BGPDUMP_IP_ADDRESS addr, char *buffer)
113 {
114     assert(buffer);
115     uint8_t *ap = (uint8_t *)&addr.v4_addr.s_addr;
116 
117     int pos = 0;
118     int i;
119     for(i = 0; i < 4; ++i) {
120         const char *octet = OCTETS[ap[i]];
121         buffer[pos++] = octet[0];
122         octet[1] ? buffer[pos++] = octet[1] : (void)0;
123         octet[2] ? buffer[pos++] = octet[2] : (void)0;
124         buffer[pos++] = '.';
125     }
126 
127     buffer[pos - 1] = '\0';
128 
129     return buffer;
130 }
131 
fmt_ipv6(BGPDUMP_IP_ADDRESS addr,char * buffer)132 char *fmt_ipv6(BGPDUMP_IP_ADDRESS addr, char *buffer)
133 {
134     static const char hexchars[] = "0123456789abcdef";
135 
136     assert(buffer);
137 
138     /*  check for mapped or compat addresses */
139     bool m = IN6_IS_ADDR_V4MAPPED(&addr.v6_addr);
140     bool c = IN6_IS_ADDR_V4COMPAT(&addr.v6_addr);
141     if (m || c) {
142         char buffer2[100];
143         BGPDUMP_IP_ADDRESS mapped = { .v4_addr.s_addr = ((uint32_t *)addr.v6_addr.s6_addr)[3] };
144 
145         sprintf(buffer, "::%s%s", m ? "ffff:" : "", fmt_ipv4(mapped, buffer2));
146         return buffer;
147     }
148 
149     char hexa[8][5];
150     int zr[8];
151     size_t len;
152     uint8_t x8, hx8;
153     uint16_t x16;
154 
155     int i, k = 0;
156     for (i = 0; i < 16; i += 2) {
157         int j = 0;
158         bool skip = 1;
159 
160         memset(hexa[k], 0, 5);
161 
162         x8 = addr.v6_addr.s6_addr[i];
163 
164         hx8 = x8 >> 4;
165         if (hx8 != 0)
166         {
167             skip = 0;
168             hexa[k][j++] = hexchars[hx8];
169         }
170 
171         hx8 = x8 & 0x0f;
172         if ((skip == 0) || ((skip == 1) && (hx8 != 0)))
173         {
174             skip = 0;
175             hexa[k][j++] = hexchars[hx8];
176         }
177 
178         x8 = addr.v6_addr.s6_addr[i + 1];
179 
180         hx8 = x8 >> 4;
181         if ((skip == 0) || ((skip == 1) && (hx8 != 0)))
182         {
183             hexa[k][j++] = hexchars[hx8];
184         }
185 
186         hx8 = x8 & 0x0f;
187         hexa[k][j] = hexchars[hx8];
188 
189         k++;
190     }
191 
192     /* find runs of zeros for :: convention */
193     int j = 0;
194     for (i = 7; i >= 0; i--)
195     {
196         zr[i] = j;
197         x16 = ((uint16_t *)addr.v6_addr.s6_addr)[i];
198         if (x16 == 0) j++;
199         else j = 0;
200         zr[i] = j;
201     }
202 
203     /* find longest run of zeros */
204     k = -1;
205     j = 0;
206     for(i = 0; i < 8; i++)
207     {
208         if (zr[i] > j)
209         {
210             k = i;
211             j = zr[i];
212         }
213     }
214 
215     for(i = 0; i < 8; i++)
216     {
217         if (i != k) zr[i] = 0;
218     }
219 
220     len = 0;
221     for (i = 0; i < 8; i++)
222     {
223         if (zr[i] != 0)
224         {
225             /* check for leading zero */
226             if (i == 0)
227                 buffer[len++] = ':';
228             buffer[len++] = ':';
229             i += (zr[i] - 1);
230             continue;
231         }
232         for (j = 0; hexa[i][j] != '\0'; j++)
233             buffer[len++] = hexa[i][j];
234         if (i != 7)
235             buffer[len++] = ':';
236     }
237 
238     buffer[len] = '\0';
239 
240     return buffer;
241 }
242 
test_roundtrip(char * str)243 static void test_roundtrip(char *str)
244 {
245     BGPDUMP_IP_ADDRESS addr;
246     inet_pton(AF_INET6, str, &addr.v6_addr);
247     char tmp[1000];
248     fmt_ipv6(addr, tmp);
249     printf("%s -> %s [%s]\n", str, tmp, strcmp(str, tmp) ? "ERROR" : "ok");
250 }
251 
test_fmt_ip()252 void test_fmt_ip()
253 {
254     test_roundtrip("fe80::");
255     test_roundtrip("2001:db8::1");
256     test_roundtrip("::ffff:192.168.2.1");
257     test_roundtrip("::192.168.1.2");
258     test_roundtrip("2001:7f8:30::2:1:0:8447");
259 }
260