OpenWrt – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /* |
2 | * Utility used to calculate the 6rd subnet. |
||
3 | * |
||
4 | * Copyright 2012, Stéphan Kochen <stephan@kochen.nl> |
||
5 | * |
||
6 | * This program is free software; you can redistribute it and/or |
||
7 | * modify it under the terms of the GNU General Public License |
||
8 | * as published by the Free Software Foundation; either version 2 |
||
9 | * of the License, or (at your option) any later version. |
||
10 | * |
||
11 | * This program is distributed in the hope that it will be useful, |
||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
14 | * GNU General Public License for more details. |
||
15 | * |
||
16 | * You should have received a copy of the GNU General Public License |
||
17 | * along with this program; if not, write to the Free Software |
||
18 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||
19 | */ |
||
20 | |||
21 | #include <stdio.h> |
||
22 | #include <stdlib.h> |
||
23 | #include <string.h> |
||
24 | #include <sys/errno.h> |
||
25 | #include <arpa/inet.h> |
||
26 | #include <netinet/in.h> |
||
27 | |||
28 | #define INET_PREFIXSTRLEN (INET_ADDRSTRLEN+3) |
||
29 | #define INET6_PREFIXSTRLEN (INET6_ADDRSTRLEN+4) |
||
30 | |||
31 | static void print_usage() |
||
32 | { |
||
33 | fprintf(stderr, "Usage: 6rdcalc <v6 prefix>/<mask> <v4 address>/<mask>\n"); |
||
34 | exit(1); |
||
35 | } |
||
36 | |||
37 | static void print_error() |
||
38 | { |
||
39 | fprintf(stderr, "%s", strerror(errno)); |
||
40 | exit(1); |
||
41 | } |
||
42 | |||
43 | static void parse_str(int af, char *str, void *addr, unsigned long *mask) |
||
44 | { |
||
45 | int ret; |
||
46 | char *slash; |
||
47 | |||
48 | /* Split the address at the slash. */ |
||
49 | if ((slash = strchr(str, '/')) == NULL) |
||
50 | print_usage(); |
||
51 | *slash = '\0'; |
||
52 | |||
53 | /* Parse the address. */ |
||
54 | if ((ret = inet_pton(af, str, addr)) != 1) { |
||
55 | if (ret == 0) |
||
56 | print_usage(); |
||
57 | else |
||
58 | print_error(); |
||
59 | } |
||
60 | |||
61 | /* Parse the mask. */ |
||
62 | *mask = strtoul(slash+1, NULL, 10); |
||
63 | if ((af == AF_INET && *mask > 32) || |
||
64 | (af == AF_INET6 && *mask > 128)) |
||
65 | print_usage(); |
||
66 | } |
||
67 | |||
68 | int main(int argc, const char **argv) |
||
69 | { |
||
70 | char v6str[INET6_PREFIXSTRLEN], v4str[INET_PREFIXSTRLEN]; |
||
71 | struct in6_addr v6; |
||
72 | struct in_addr v4; |
||
73 | unsigned long v6it, v4it, mask; |
||
74 | unsigned char *byte4, *byte6; |
||
75 | unsigned char bit4, bit6; |
||
76 | |||
77 | /* Check parameters. */ |
||
78 | if (argc != 3) |
||
79 | print_usage(); |
||
80 | |||
81 | /* Parse the v6 address. */ |
||
82 | strncpy(v6str, argv[1], INET6_PREFIXSTRLEN); |
||
83 | v6str[INET6_PREFIXSTRLEN-1] = '\0'; |
||
84 | parse_str(AF_INET6, v6str, &v6, &v6it); |
||
85 | |||
86 | /* Parse the v4 address */ |
||
87 | strncpy(v4str, argv[2], INET_PREFIXSTRLEN); |
||
88 | v6str[INET_PREFIXSTRLEN-1] = '\0'; |
||
89 | parse_str(AF_INET, v4str, &v4, &v4it); |
||
90 | |||
91 | /* Check if the combined mask is within bounds. */ |
||
92 | mask = (32 - v4it) + v6it; |
||
93 | if (mask > 128) |
||
94 | print_usage(); |
||
95 | |||
96 | /* Combine the addresses. */ |
||
97 | while (v4it < 32) { |
||
98 | byte6 = (unsigned char *)(&v6.s6_addr) + (v6it >> 3); |
||
99 | byte4 = (unsigned char *)(&v4.s_addr) + (v4it >> 3); |
||
100 | bit6 = 128 >> (v6it & 0x07); |
||
101 | bit4 = 128 >> (v4it & 0x07); |
||
102 | |||
103 | if (*byte4 & bit4) |
||
104 | *byte6 |= bit6; |
||
105 | else |
||
106 | *byte6 &= ~bit6; |
||
107 | |||
108 | v4it++; v6it++; |
||
109 | } |
||
110 | |||
111 | /* Clear remaining bits. */ |
||
112 | while (v6it < 128) { |
||
113 | byte6 = (unsigned char *)(&v6.s6_addr) + (v6it >> 3); |
||
114 | bit6 = 128 >> (v6it & 0x07); |
||
115 | |||
116 | *byte6 &= ~bit6; |
||
117 | |||
118 | v6it++; |
||
119 | } |
||
120 | |||
121 | /* Print the subnet prefix. */ |
||
122 | if (inet_ntop(AF_INET6, &v6, v6str, sizeof(v6str)) == NULL) |
||
123 | print_error(); |
||
124 | printf("%s/%lu\n", v6str, mask); |
||
125 | return 0; |
||
126 | } |